Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions apps/web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
"@formkit/auto-animate": "^0.9.0",
"@legendapp/list": "catalog:",
"@lexical/react": "^0.41.0",
"@noble/hashes": "catalog:",
"@pierre/diffs": "catalog:",
"@pierre/trees": "1.0.0-beta.4",
"@t3tools/client-runtime": "workspace:*",
Expand All @@ -36,6 +37,8 @@
"culori": "^4.0.2",
"effect": "catalog:",
"jose": "catalog:",
"jsonc-parser": "3.3.1",
"jszip": "3.10.1",
"lexical": "^0.41.0",
"lucide-react": "^0.564.0",
"react": "19.2.6",
Expand Down
37 changes: 14 additions & 23 deletions apps/web/src/components/settings/ThemeEditorPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -610,7 +610,7 @@ export function ThemeEditorPanel({
[activeAppearance, editingTheme, selectedRole],
);

const handleSubmit = useCallback(() => {
const handleSubmit = () => {
if (!name.trim()) {
setError("Name your theme first.");
return;
Expand Down Expand Up @@ -645,8 +645,8 @@ export function ThemeEditorPanel({
return;
}
mergedAppearance = editedModes[0] ?? null;
savedTheme = updateCustomTheme(
parseThemeFile({
savedTheme = updateCustomTheme({
...parseThemeFile({
version: THEME_FILE_VERSION,
id: mergeTarget.id,
name: mergeTarget.label,
Expand All @@ -658,7 +658,8 @@ export function ThemeEditorPanel({
},
...(mergeTarget.managed === true && !isAdvanced ? { managed: true } : {}),
}),
);
...(mergeTarget.collection ? { collection: mergeTarget.collection } : {}),
});
retiredTheme = editingTheme;
try {
removeCustomTheme(editingTheme.id);
Expand All @@ -676,8 +677,8 @@ export function ThemeEditorPanel({
} else if (editingTheme) {
const baseAppearance = editingTheme.appearance;
const variantAppearance = baseAppearance === "light" ? "dark" : "light";
savedTheme = updateCustomTheme(
parseThemeFile({
savedTheme = updateCustomTheme({
...parseThemeFile({
version: THEME_FILE_VERSION,
id: editingTheme.id,
name,
Expand All @@ -688,7 +689,8 @@ export function ThemeEditorPanel({
: {}),
...(isAdvanced ? {} : { managed: true }),
}),
);
...(editingTheme.collection ? { collection: editingTheme.collection } : {}),
});
} else if (mergeTarget) {
if (takenAppearances.includes(activeAppearance)) {
setError(
Expand All @@ -701,8 +703,8 @@ export function ThemeEditorPanel({
// survives when every palette in the theme came from the guided
// editor.
mergedAppearance = activeAppearance;
savedTheme = updateCustomTheme(
parseThemeFile({
savedTheme = updateCustomTheme({
...parseThemeFile({
version: THEME_FILE_VERSION,
id: mergeTarget.id,
name: mergeTarget.label,
Expand All @@ -714,7 +716,8 @@ export function ThemeEditorPanel({
},
...(mergeTarget.managed === true && !isAdvanced ? { managed: true } : {}),
}),
);
...(mergeTarget.collection ? { collection: mergeTarget.collection } : {}),
});
} else {
savedTheme = installCustomTheme(
parseThemeFile({
Expand Down Expand Up @@ -762,19 +765,7 @@ export function ThemeEditorPanel({
: "Could not create the theme.",
);
}
}, [
activeAppearance,
colorsByAppearance,
editingTheme,
isAdvanced,
isEditing,
mergeTarget,
name,
onOpenChange,
onSaved,
simpleColorsDirtyByAppearance,
takenAppearances,
]);
};

const renderNameField = () => (
<label className="grid grid-cols-[minmax(0,1fr)_minmax(0,2fr)] items-center gap-3">
Expand Down
28 changes: 26 additions & 2 deletions apps/web/src/components/settings/ThemeImportDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import {
DialogPopup,
DialogTitle,
} from "../ui/dialog";
import { ThemeSearchSection } from "./ThemeSearchSection";

/**
* A full theme export is a few KB, so anything past this is not a theme file.
Expand Down Expand Up @@ -360,9 +361,16 @@ export function ThemeImportDialog({
: null;
for (const theme of conflicts) {
try {
const existingTheme =
mode === "update"
? getCustomThemes().find((candidate) => candidate.id === theme.id)
: undefined;
const themeToUpdate = existingTheme?.collection
? { ...theme, collection: existingTheme.collection }
: theme;
resolved.push(
mode === "update"
? updateCustomTheme(theme)
? updateCustomTheme(themeToUpdate)
: installCustomTheme(versionedCopy(theme, preferredName)),
);
} catch (cause) {
Expand Down Expand Up @@ -426,7 +434,23 @@ export function ThemeImportDialog({
<DialogHeader>
<DialogTitle>Add a theme</DialogTitle>
</DialogHeader>
<DialogPanel className="space-y-4">
<DialogPanel className="space-y-5">
<ThemeSearchSection
onInstalled={(themes, context) => {
onImportedMany(themes, context);
onOpenChange(false);
}}
open={open}
/>

<div className="flex items-center gap-3" aria-hidden>
<div className="h-px flex-1 bg-border" />
<span className="text-muted-foreground text-[11px] uppercase tracking-wider">
or import a file
</span>
<div className="h-px flex-1 bg-border" />
</div>

{(() => {
const dropHandlers = {
onDragEnter: (event: DragEvent<HTMLDivElement>) => {
Expand Down
Loading
Loading