paperclip-theme 0.1.1 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -8,7 +8,9 @@ export declare const EXPORT_NAMES: {
8
8
  };
9
9
  export declare const STATE_KEYS: {
10
10
  readonly activeTheme: "active-theme";
11
+ readonly userThemes: "user-themes";
11
12
  };
13
+ export declare const REMOTE_REGISTRY_URL = "https://raw.githubusercontent.com/Khaleeq2/paperclip-plugins/master/registry/themes.json";
12
14
  export declare const DATA_ENDPOINTS: {
13
15
  readonly activeTheme: "active-theme";
14
16
  readonly presets: "presets";
@@ -16,6 +18,8 @@ export declare const DATA_ENDPOINTS: {
16
18
  export declare const ACTION_NAMES: {
17
19
  readonly applyTheme: "apply-theme";
18
20
  readonly resetTheme: "reset-theme";
21
+ readonly importTheme: "import-theme";
22
+ readonly removeUserTheme: "remove-user-theme";
19
23
  };
20
24
  /**
21
25
  * Semantic CSS custom properties that control Paperclip's entire look.
@@ -1 +1 @@
1
- {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,SAAS,0BAA0B,CAAC;AACjD,eAAO,MAAM,cAAc,UAAU,CAAC;AAEtC,eAAO,MAAM,QAAQ;;CAEX,CAAC;AAEX,eAAO,MAAM,YAAY;;CAEf,CAAC;AAEX,eAAO,MAAM,UAAU;;CAEb,CAAC;AAEX,eAAO,MAAM,cAAc;;;CAGjB,CAAC;AAEX,eAAO,MAAM,YAAY;;;CAGf,CAAC;AAEX;;;GAGG;AACH,eAAO,MAAM,YAAY;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA+Bf,CAAC;AAEX;;;GAGG;AACH,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,OAAO,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC/B,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;;GAGG;AACH,eAAO,MAAM,uBAAuB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAqB1D,CAAC;AAEF,eAAO,MAAM,wBAAwB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAqB3D,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,aAAa,EAAE,WAAW,EAuhBtC,CAAC"}
1
+ {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,SAAS,0BAA0B,CAAC;AACjD,eAAO,MAAM,cAAc,UAAU,CAAC;AAEtC,eAAO,MAAM,QAAQ;;CAEX,CAAC;AAEX,eAAO,MAAM,YAAY;;CAEf,CAAC;AAEX,eAAO,MAAM,UAAU;;;CAGb,CAAC;AAEX,eAAO,MAAM,mBAAmB,6FAC4D,CAAC;AAE7F,eAAO,MAAM,cAAc;;;CAGjB,CAAC;AAEX,eAAO,MAAM,YAAY;;;;;CAKf,CAAC;AAEX;;;GAGG;AACH,eAAO,MAAM,YAAY;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA+Bf,CAAC;AAEX;;;GAGG;AACH,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,OAAO,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC/B,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;;GAGG;AACH,eAAO,MAAM,uBAAuB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAqB1D,CAAC;AAEF,eAAO,MAAM,wBAAwB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAqB3D,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,aAAa,EAAE,WAAW,EAuhBtC,CAAC"}
package/dist/constants.js CHANGED
@@ -8,7 +8,9 @@ export const EXPORT_NAMES = {
8
8
  };
9
9
  export const STATE_KEYS = {
10
10
  activeTheme: "active-theme",
11
+ userThemes: "user-themes",
11
12
  };
13
+ export const REMOTE_REGISTRY_URL = "https://raw.githubusercontent.com/Khaleeq2/paperclip-plugins/master/registry/themes.json";
12
14
  export const DATA_ENDPOINTS = {
13
15
  activeTheme: "active-theme",
14
16
  presets: "presets",
@@ -16,6 +18,8 @@ export const DATA_ENDPOINTS = {
16
18
  export const ACTION_NAMES = {
17
19
  applyTheme: "apply-theme",
18
20
  resetTheme: "reset-theme",
21
+ importTheme: "import-theme",
22
+ removeUserTheme: "remove-user-theme",
19
23
  };
20
24
  /**
21
25
  * Semantic CSS custom properties that control Paperclip's entire look.
@@ -1 +1 @@
1
- {"version":3,"file":"constants.js","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"constants.js","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"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"}
package/dist/ui/index.js CHANGED
@@ -606,12 +606,15 @@ function ThemeSettingsPage() {
606
606
  const presetsResult = usePluginData("presets");
607
607
  const applyTheme = usePluginAction("apply-theme");
608
608
  const resetTheme = usePluginAction("reset-theme");
609
+ const importThemeAction = usePluginAction("import-theme");
609
610
  const [localTheme, setLocalTheme] = useState(null);
610
611
  const [saving, setSaving] = useState(false);
611
612
  const [savedAt, setSavedAt] = useState(null);
612
613
  const [hasUnsaved, setHasUnsaved] = useState(false);
613
614
  const [showModal, setShowModal] = useState(false);
615
+ const [importError, setImportError] = useState(null);
614
616
  const initialLoadDone = useRef(false);
617
+ const fileInputRef = useRef(null);
615
618
  const presets = presetsResult.data ?? [];
616
619
  const serverTheme = activeThemeResult.data ?? null;
617
620
  const visiblePresets = presets.slice(0, MAX_VISIBLE_PRESETS);
@@ -691,6 +694,45 @@ function ThemeSettingsPage() {
691
694
  setSaving(false);
692
695
  }
693
696
  }, [resetTheme]);
697
+ const handleExport = useCallback(() => {
698
+ if (!localTheme) return;
699
+ const payload = JSON.stringify(localTheme, null, 2);
700
+ const blob = new Blob([payload], { type: "application/json" });
701
+ const url = URL.createObjectURL(blob);
702
+ const a = document.createElement("a");
703
+ a.href = url;
704
+ a.download = `${localTheme.id}.theme.json`;
705
+ document.body.appendChild(a);
706
+ a.click();
707
+ document.body.removeChild(a);
708
+ URL.revokeObjectURL(url);
709
+ }, [localTheme]);
710
+ const handleImportFile = useCallback(
711
+ async (e) => {
712
+ setImportError(null);
713
+ const file = e.target.files?.[0];
714
+ if (!file) return;
715
+ try {
716
+ const text = await file.text();
717
+ const parsed = JSON.parse(text);
718
+ if (typeof parsed !== "object" || parsed === null || typeof parsed.id !== "string" || typeof parsed.name !== "string" || typeof parsed.tokens !== "object" || typeof parsed.isDark !== "boolean") {
719
+ setImportError("Invalid theme file: must contain id, name, tokens, and isDark fields.");
720
+ return;
721
+ }
722
+ const result = await importThemeAction(parsed);
723
+ const imported = result;
724
+ setLocalTheme(imported);
725
+ injectThemeCSS(imported);
726
+ setHasUnsaved(true);
727
+ setSavedAt(null);
728
+ } catch (err) {
729
+ setImportError(`Import failed: ${String(err)}`);
730
+ } finally {
731
+ if (fileInputRef.current) fileInputRef.current.value = "";
732
+ }
733
+ },
734
+ [importThemeAction]
735
+ );
694
736
  const radiusNum = parseFloat(localTheme?.radius ?? "0") || 0;
695
737
  return /* @__PURE__ */ jsxs("div", { style: styles.root, children: [
696
738
  /* @__PURE__ */ jsxs("div", { style: styles.header, children: [
@@ -806,6 +848,46 @@ function ThemeSettingsPage() {
806
848
  savedAt
807
849
  ] }),
808
850
  hasUnsaved && !savedAt && /* @__PURE__ */ jsx("span", { style: { ...styles.saved, color: "var(--chart-1)" }, children: "Unsaved changes" })
851
+ ] }),
852
+ /* @__PURE__ */ jsxs("div", { style: styles.section, children: [
853
+ /* @__PURE__ */ jsx("p", { style: styles.sectionLabel, children: "Share" }),
854
+ /* @__PURE__ */ jsx("p", { style: { ...styles.subtitle, marginTop: -8 }, children: "Export your current theme as a JSON file to share with others, or import a community theme." }),
855
+ /* @__PURE__ */ jsxs("div", { style: styles.actions, children: [
856
+ /* @__PURE__ */ jsx(
857
+ "button",
858
+ {
859
+ type: "button",
860
+ style: {
861
+ ...styles.btnSecondary,
862
+ opacity: localTheme ? 1 : 0.5,
863
+ pointerEvents: localTheme ? "auto" : "none"
864
+ },
865
+ onClick: handleExport,
866
+ disabled: !localTheme,
867
+ children: "Export Theme"
868
+ }
869
+ ),
870
+ /* @__PURE__ */ jsx(
871
+ "button",
872
+ {
873
+ type: "button",
874
+ style: styles.btnSecondary,
875
+ onClick: () => fileInputRef.current?.click(),
876
+ children: "Import Theme"
877
+ }
878
+ ),
879
+ /* @__PURE__ */ jsx(
880
+ "input",
881
+ {
882
+ ref: fileInputRef,
883
+ type: "file",
884
+ accept: ".json,application/json",
885
+ style: { display: "none" },
886
+ onChange: handleImportFile
887
+ }
888
+ )
889
+ ] }),
890
+ importError && /* @__PURE__ */ jsx("p", { style: { fontSize: 12, color: "var(--destructive)", margin: 0 }, children: importError })
809
891
  ] })
810
892
  ] });
811
893
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/ui/index.tsx"],
4
- "sourcesContent": ["import React, { useState, useEffect, useCallback, useRef, useMemo } from \"react\";\nimport {\n usePluginData,\n usePluginAction,\n} from \"@paperclipai/plugin-sdk/ui\";\n\n/* \u2500\u2500\u2500 Types \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\ninterface ThemeConfig {\n id: string;\n name: string;\n description: string;\n author: string;\n isDark: boolean;\n tokens: Record<string, string>;\n radius: string;\n createdAt: string;\n updatedAt: string;\n}\n\n/* \u2500\u2500\u2500 Constants \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\nconst MAX_VISIBLE_PRESETS = 8;\nconst CARD_WIDTH = 192;\nconst CARD_GAP = 10;\nconst SWATCH_TOKENS = [\"--background\", \"--primary\", \"--accent\", \"--chart-1\", \"--destructive\"];\n\n/* \u2500\u2500\u2500 CSS injection engine \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\nconst STYLE_ELEMENT_ID = \"blazo-theme-overrides\";\n\nfunction injectThemeCSS(theme: ThemeConfig): void {\n let el = document.getElementById(STYLE_ELEMENT_ID) as HTMLStyleElement | null;\n if (!el) {\n el = document.createElement(\"style\");\n el.id = STYLE_ELEMENT_ID;\n document.head.appendChild(el);\n }\n\n const entries = Object.entries(theme.tokens);\n const radiusEntry = theme.radius ? ` --radius: ${theme.radius};` : \"\";\n\n const lines = entries.map(([key, value]) => ` ${key}: ${value};`);\n if (radiusEntry) lines.push(radiusEntry);\n\n const darkToggle = theme.isDark ? \"dark\" : \"light\";\n el.textContent = `:root { ${lines.join(\" \")} }\\n`;\n\n const htmlEl = document.documentElement;\n htmlEl.classList.toggle(\"dark\", theme.isDark);\n htmlEl.classList.toggle(\"light\", !theme.isDark);\n htmlEl.style.colorScheme = darkToggle;\n}\n\nfunction clearThemeCSS(): void {\n const el = document.getElementById(STYLE_ELEMENT_ID);\n if (el) el.remove();\n}\n\n/* \u2500\u2500\u2500 Token groups for the editor \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\ninterface TokenGroup {\n label: string;\n description: string;\n tokens: string[];\n}\n\nconst TOKEN_GROUPS: TokenGroup[] = [\n {\n label: \"Surfaces\",\n description: \"Background and card colors\",\n tokens: [\"--background\", \"--card\", \"--muted\", \"--accent\"],\n },\n {\n label: \"Text\",\n description: \"Foreground and label colors\",\n tokens: [\"--foreground\", \"--card-foreground\", \"--muted-foreground\", \"--accent-foreground\"],\n },\n {\n label: \"Interactive\",\n description: \"Buttons, links, and primary actions\",\n tokens: [\"--primary\", \"--primary-foreground\"],\n },\n {\n label: \"Feedback\",\n description: \"Errors and destructive actions\",\n tokens: [\"--destructive\", \"--destructive-foreground\"],\n },\n {\n label: \"Structure\",\n description: \"Borders and focus rings\",\n tokens: [\"--border\", \"--input\", \"--ring\"],\n },\n {\n label: \"Charts\",\n description: \"Dashboard visualization colors\",\n tokens: [\"--chart-1\", \"--chart-2\", \"--chart-3\", \"--chart-4\", \"--chart-5\"],\n },\n];\n\n/* \u2500\u2500\u2500 Helpers \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\nfunction tokenDisplayName(token: string): string {\n return token\n .replace(/^--/, \"\")\n .split(\"-\")\n .map((w) => w.charAt(0).toUpperCase() + w.slice(1))\n .join(\" \");\n}\n\nfunction oklchToHex(oklchStr: string): string {\n const canvas = document.createElement(\"canvas\");\n canvas.width = 1;\n canvas.height = 1;\n const ctx2d = canvas.getContext(\"2d\");\n if (!ctx2d) return \"#000000\";\n ctx2d.fillStyle = oklchStr;\n ctx2d.fillRect(0, 0, 1, 1);\n const [r, g, b] = ctx2d.getImageData(0, 0, 1, 1).data;\n return `#${(r ?? 0).toString(16).padStart(2, \"0\")}${(g ?? 0).toString(16).padStart(2, \"0\")}${(b ?? 0).toString(16).padStart(2, \"0\")}`;\n}\n\nfunction hexToOklch(hex: string): string {\n const canvas = document.createElement(\"canvas\");\n canvas.width = 1;\n canvas.height = 1;\n const ctx2d = canvas.getContext(\"2d\");\n if (!ctx2d) return \"oklch(0% 0 0)\";\n ctx2d.fillStyle = hex;\n ctx2d.fillRect(0, 0, 1, 1);\n const [r, g, b] = ctx2d.getImageData(0, 0, 1, 1).data;\n const rLin = srgbToLinear((r ?? 0) / 255);\n const gLin = srgbToLinear((g ?? 0) / 255);\n const bLin = srgbToLinear((b ?? 0) / 255);\n const l = 0.4122214708 * rLin + 0.5363325363 * gLin + 0.0514459929 * bLin;\n const m = 0.2119034982 * rLin + 0.6806995451 * gLin + 0.1073969566 * bLin;\n const s = 0.0883024619 * rLin + 0.2817188376 * gLin + 0.6299787005 * bLin;\n const lRoot = Math.cbrt(l);\n const mRoot = Math.cbrt(m);\n const sRoot = Math.cbrt(s);\n const L = 0.2104542553 * lRoot + 0.7936177850 * mRoot - 0.0040720468 * sRoot;\n const a = 1.9779984951 * lRoot - 2.4285922050 * mRoot + 0.4505937099 * sRoot;\n const bOklab = 0.0259040371 * lRoot + 0.7827717662 * mRoot - 0.8086757660 * sRoot;\n const C = Math.sqrt(a * a + bOklab * bOklab);\n let H = (Math.atan2(bOklab, a) * 180) / Math.PI;\n if (H < 0) H += 360;\n return `oklch(${(L * 100).toFixed(1)}% ${C.toFixed(3)} ${H.toFixed(1)})`;\n}\n\nfunction srgbToLinear(c: number): number {\n return c <= 0.04045 ? c / 12.92 : Math.pow((c + 0.055) / 1.055, 2.4);\n}\n\n/* \u2500\u2500\u2500 Style definitions \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\nconst styles = {\n root: {\n fontFamily: \"var(--font-sans, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif)\",\n color: \"var(--foreground)\",\n maxWidth: 720,\n display: \"flex\",\n flexDirection: \"column\" as const,\n gap: 32,\n },\n header: {\n display: \"flex\",\n flexDirection: \"column\" as const,\n gap: 6,\n },\n title: {\n fontSize: 20,\n fontWeight: 600,\n letterSpacing: \"-0.01em\",\n margin: 0,\n color: \"var(--foreground)\",\n },\n subtitle: {\n fontSize: 13,\n color: \"var(--muted-foreground)\",\n margin: 0,\n lineHeight: 1.5,\n },\n section: {\n display: \"flex\",\n flexDirection: \"column\" as const,\n gap: 16,\n },\n sectionHeader: {\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"space-between\",\n margin: 0,\n },\n sectionLabel: {\n fontSize: 13,\n fontWeight: 600,\n textTransform: \"uppercase\" as const,\n letterSpacing: \"0.04em\",\n color: \"var(--muted-foreground)\",\n margin: 0,\n },\n seeAllBtn: {\n fontSize: 12,\n fontWeight: 500,\n color: \"var(--primary)\",\n background: \"none\",\n border: \"none\",\n cursor: \"pointer\",\n padding: \"2px 0\",\n outline: \"none\",\n transition: \"opacity 150ms ease\",\n },\n presetsScroller: {\n overflowX: \"auto\" as const,\n overflowY: \"hidden\" as const,\n WebkitOverflowScrolling: \"touch\" as const,\n scrollbarWidth: \"thin\" as const,\n paddingBottom: 4,\n },\n presetsTrack: {\n display: \"grid\",\n gridTemplateRows: \"1fr 1fr\",\n gridAutoFlow: \"column\" as const,\n gridAutoColumns: `${CARD_WIDTH}px`,\n gap: CARD_GAP,\n },\n presetCard: (isActive: boolean) => ({\n position: \"relative\" as const,\n width: CARD_WIDTH,\n padding: \"12px 14px\",\n borderRadius: 8,\n border: `1.5px solid ${isActive ? \"var(--primary)\" : \"var(--border)\"}`,\n background: isActive ? \"var(--accent)\" : \"transparent\",\n cursor: \"pointer\",\n transition: \"all 150ms ease\",\n display: \"flex\",\n flexDirection: \"column\" as const,\n gap: 5,\n outline: \"none\",\n boxSizing: \"border-box\" as const,\n textAlign: \"left\" as const,\n }),\n presetName: {\n fontSize: 13,\n fontWeight: 500,\n color: \"var(--foreground)\",\n margin: 0,\n whiteSpace: \"nowrap\" as const,\n overflow: \"hidden\" as const,\n textOverflow: \"ellipsis\" as const,\n },\n presetDesc: {\n fontSize: 11,\n color: \"var(--muted-foreground)\",\n margin: 0,\n lineHeight: 1.35,\n display: \"-webkit-box\",\n WebkitLineClamp: 2,\n WebkitBoxOrient: \"vertical\" as const,\n overflow: \"hidden\" as const,\n },\n presetMeta: {\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"space-between\",\n marginTop: 2,\n },\n presetColors: {\n display: \"flex\",\n gap: 3,\n },\n presetSwatch: (color: string) => ({\n width: 14,\n height: 14,\n borderRadius: 3,\n background: color,\n border: \"1px solid rgba(128,128,128,0.25)\",\n flexShrink: 0,\n }),\n presetModeBadge: (isDark: boolean) => ({\n fontSize: 9,\n fontWeight: 600,\n textTransform: \"uppercase\" as const,\n letterSpacing: \"0.06em\",\n color: \"var(--muted-foreground)\",\n background: \"var(--muted)\",\n padding: \"1px 5px\",\n borderRadius: 3,\n lineHeight: \"16px\",\n }),\n activeBadge: {\n position: \"absolute\" as const,\n top: 7,\n right: 8,\n fontSize: 9,\n fontWeight: 600,\n textTransform: \"uppercase\" as const,\n letterSpacing: \"0.06em\",\n color: \"var(--primary-foreground)\",\n background: \"var(--primary)\",\n padding: \"1px 6px\",\n borderRadius: 999,\n lineHeight: \"16px\",\n },\n tokenGroup: {\n display: \"flex\",\n flexDirection: \"column\" as const,\n gap: 10,\n padding: \"16px 0\",\n borderBottom: \"1px solid var(--border)\",\n },\n tokenGroupHeader: {\n display: \"flex\",\n flexDirection: \"column\" as const,\n gap: 2,\n },\n tokenGroupLabel: {\n fontSize: 14,\n fontWeight: 500,\n color: \"var(--foreground)\",\n margin: 0,\n },\n tokenGroupDesc: {\n fontSize: 12,\n color: \"var(--muted-foreground)\",\n margin: 0,\n },\n tokenRow: {\n display: \"flex\",\n alignItems: \"center\",\n gap: 12,\n padding: \"4px 0\",\n },\n colorInput: {\n width: 32,\n height: 32,\n border: \"1.5px solid var(--border)\",\n borderRadius: 6,\n padding: 0,\n cursor: \"pointer\",\n background: \"none\",\n flexShrink: 0,\n outline: \"none\",\n },\n tokenLabel: {\n fontSize: 13,\n fontWeight: 400,\n color: \"var(--foreground)\",\n flex: 1,\n minWidth: 0,\n },\n tokenValue: {\n fontSize: 11,\n fontFamily: \"var(--font-mono, 'SF Mono', Consolas, monospace)\",\n color: \"var(--muted-foreground)\",\n textAlign: \"right\" as const,\n whiteSpace: \"nowrap\" as const,\n overflow: \"hidden\" as const,\n textOverflow: \"ellipsis\" as const,\n maxWidth: 180,\n },\n radiusSection: {\n display: \"flex\",\n alignItems: \"center\",\n gap: 16,\n padding: \"8px 0\",\n },\n rangeInput: {\n flex: 1,\n accentColor: \"var(--primary)\",\n cursor: \"pointer\",\n },\n radiusValue: {\n fontSize: 13,\n fontFamily: \"var(--font-mono, 'SF Mono', Consolas, monospace)\",\n color: \"var(--muted-foreground)\",\n minWidth: 48,\n textAlign: \"right\" as const,\n },\n radiusPreview: (r: string) => ({\n width: 32,\n height: 32,\n borderRadius: r,\n border: \"2px solid var(--primary)\",\n background: \"var(--accent)\",\n flexShrink: 0,\n }),\n actions: {\n display: \"flex\",\n gap: 10,\n paddingTop: 8,\n },\n btnPrimary: {\n padding: \"9px 20px\",\n borderRadius: 6,\n border: \"none\",\n background: \"var(--primary)\",\n color: \"var(--primary-foreground)\",\n fontSize: 13,\n fontWeight: 500,\n cursor: \"pointer\",\n transition: \"opacity 150ms ease\",\n outline: \"none\",\n },\n btnSecondary: {\n padding: \"9px 20px\",\n borderRadius: 6,\n border: \"1.5px solid var(--border)\",\n background: \"transparent\",\n color: \"var(--foreground)\",\n fontSize: 13,\n fontWeight: 500,\n cursor: \"pointer\",\n transition: \"all 150ms ease\",\n outline: \"none\",\n },\n saved: {\n fontSize: 12,\n color: \"var(--muted-foreground)\",\n alignSelf: \"center\" as const,\n transition: \"opacity 300ms ease\",\n },\n overlay: {\n position: \"fixed\" as const,\n inset: 0,\n background: \"rgba(0,0,0,0.55)\",\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n zIndex: 9999,\n backdropFilter: \"blur(4px)\",\n },\n modal: {\n background: \"var(--card)\",\n border: \"1px solid var(--border)\",\n borderRadius: 12,\n width: \"min(640px, calc(100vw - 48px))\",\n maxHeight: \"min(560px, calc(100vh - 80px))\",\n display: \"flex\",\n flexDirection: \"column\" as const,\n boxShadow: \"0 16px 48px rgba(0,0,0,0.25)\",\n overflow: \"hidden\" as const,\n },\n modalHeader: {\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"space-between\",\n padding: \"16px 20px 0 20px\",\n },\n modalTitle: {\n fontSize: 16,\n fontWeight: 600,\n margin: 0,\n color: \"var(--foreground)\",\n },\n modalCloseBtn: {\n width: 28,\n height: 28,\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n background: \"none\",\n border: \"none\",\n borderRadius: 6,\n cursor: \"pointer\",\n color: \"var(--muted-foreground)\",\n fontSize: 18,\n lineHeight: 1,\n outline: \"none\",\n transition: \"background 150ms ease\",\n },\n modalSearch: {\n margin: \"12px 20px\",\n padding: \"8px 12px\",\n borderRadius: 6,\n border: \"1.5px solid var(--border)\",\n background: \"var(--muted)\",\n color: \"var(--foreground)\",\n fontSize: 13,\n outline: \"none\",\n width: \"calc(100% - 40px)\",\n boxSizing: \"border-box\" as const,\n transition: \"border-color 150ms ease\",\n },\n modalCount: {\n fontSize: 11,\n color: \"var(--muted-foreground)\",\n padding: \"0 20px 8px 20px\",\n margin: 0,\n },\n modalGrid: {\n flex: 1,\n overflowY: \"auto\" as const,\n padding: \"0 20px 20px 20px\",\n display: \"grid\",\n gridTemplateColumns: \"repeat(auto-fill, minmax(180px, 1fr))\",\n gap: 10,\n alignContent: \"start\",\n },\n};\n\n/* \u2500\u2500\u2500 Preset Card \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\nfunction PresetCard({\n preset,\n isActive,\n onSelect,\n compact,\n}: {\n preset: ThemeConfig;\n isActive: boolean;\n onSelect: () => void;\n compact?: boolean;\n}) {\n const cardStyle = compact\n ? {\n ...styles.presetCard(isActive),\n width: \"auto\" as const,\n }\n : styles.presetCard(isActive);\n\n return (\n <button\n type=\"button\"\n style={cardStyle}\n onClick={onSelect}\n onMouseEnter={(e) => {\n if (!isActive) (e.currentTarget.style.borderColor = \"var(--muted-foreground)\");\n }}\n onMouseLeave={(e) => {\n if (!isActive) (e.currentTarget.style.borderColor = \"var(--border)\");\n }}\n >\n {isActive && <span style={styles.activeBadge}>Active</span>}\n <p style={styles.presetName}>{preset.name}</p>\n <p style={styles.presetDesc}>{preset.description}</p>\n <div style={styles.presetMeta}>\n <div style={styles.presetColors}>\n {SWATCH_TOKENS.map((t) => (\n <div key={t} style={styles.presetSwatch(preset.tokens[t] ?? \"#333\")} />\n ))}\n </div>\n <span style={styles.presetModeBadge(preset.isDark)}>\n {preset.isDark ? \"Dark\" : \"Light\"}\n </span>\n </div>\n </button>\n );\n}\n\n/* \u2500\u2500\u2500 \"See All\" Modal \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\nfunction PresetModal({\n presets,\n activeId,\n onSelect,\n onClose,\n}: {\n presets: ThemeConfig[];\n activeId: string | undefined;\n onSelect: (preset: ThemeConfig) => void;\n onClose: () => void;\n}) {\n const [search, setSearch] = useState(\"\");\n const searchRef = useRef<HTMLInputElement>(null);\n\n useEffect(() => {\n searchRef.current?.focus();\n }, []);\n\n useEffect(() => {\n const handleKey = (e: KeyboardEvent) => {\n if (e.key === \"Escape\") onClose();\n };\n document.addEventListener(\"keydown\", handleKey);\n return () => document.removeEventListener(\"keydown\", handleKey);\n }, [onClose]);\n\n const filtered = useMemo(() => {\n if (!search.trim()) return presets;\n const q = search.toLowerCase().trim();\n return presets.filter(\n (p) =>\n p.name.toLowerCase().includes(q) ||\n p.description.toLowerCase().includes(q) ||\n p.author.toLowerCase().includes(q) ||\n (p.isDark ? \"dark\" : \"light\").includes(q),\n );\n }, [presets, search]);\n\n return (\n <div\n style={styles.overlay}\n onClick={(e) => {\n if (e.target === e.currentTarget) onClose();\n }}\n >\n <div style={styles.modal}>\n <div style={styles.modalHeader}>\n <h3 style={styles.modalTitle}>All Themes</h3>\n <button\n type=\"button\"\n style={styles.modalCloseBtn}\n onClick={onClose}\n onMouseEnter={(e) => {\n e.currentTarget.style.background = \"var(--muted)\";\n }}\n onMouseLeave={(e) => {\n e.currentTarget.style.background = \"none\";\n }}\n >\n &#x2715;\n </button>\n </div>\n <input\n ref={searchRef}\n type=\"text\"\n placeholder=\"Search themes...\"\n value={search}\n onChange={(e) => setSearch(e.target.value)}\n style={styles.modalSearch}\n onFocus={(e) => {\n e.currentTarget.style.borderColor = \"var(--primary)\";\n }}\n onBlur={(e) => {\n e.currentTarget.style.borderColor = \"var(--border)\";\n }}\n />\n <p style={styles.modalCount}>\n {filtered.length} of {presets.length} themes\n </p>\n <div style={styles.modalGrid}>\n {filtered.map((preset) => (\n <PresetCard\n key={preset.id}\n preset={preset}\n isActive={activeId === preset.id}\n onSelect={() => {\n onSelect(preset);\n onClose();\n }}\n compact\n />\n ))}\n {filtered.length === 0 && (\n <p style={{ ...styles.subtitle, gridColumn: \"1 / -1\", textAlign: \"center\" as const, padding: \"32px 0\" }}>\n No themes match your search.\n </p>\n )}\n </div>\n </div>\n </div>\n );\n}\n\n/* \u2500\u2500\u2500 Token Editor Row \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\nfunction TokenRow({\n token,\n value,\n onChange,\n}: {\n token: string;\n value: string;\n onChange: (token: string, value: string) => void;\n}) {\n const hex = oklchToHex(value);\n return (\n <div style={styles.tokenRow}>\n <input\n type=\"color\"\n style={styles.colorInput}\n value={hex}\n onChange={(e) => {\n const newOklch = hexToOklch(e.target.value);\n onChange(token, newOklch);\n }}\n title={tokenDisplayName(token)}\n />\n <span style={styles.tokenLabel}>{tokenDisplayName(token)}</span>\n <span style={styles.tokenValue}>{value}</span>\n </div>\n );\n}\n\n/* \u2500\u2500\u2500 Main Settings Page Component \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\nexport function ThemeSettingsPage() {\n const activeThemeResult = usePluginData<ThemeConfig | null>(\"active-theme\");\n const presetsResult = usePluginData<ThemeConfig[]>(\"presets\");\n const applyTheme = usePluginAction(\"apply-theme\");\n const resetTheme = usePluginAction(\"reset-theme\");\n\n const [localTheme, setLocalTheme] = useState<ThemeConfig | null>(null);\n const [saving, setSaving] = useState(false);\n const [savedAt, setSavedAt] = useState<string | null>(null);\n const [hasUnsaved, setHasUnsaved] = useState(false);\n const [showModal, setShowModal] = useState(false);\n const initialLoadDone = useRef(false);\n\n const presets: ThemeConfig[] = presetsResult.data ?? [];\n const serverTheme: ThemeConfig | null = activeThemeResult.data ?? null;\n\n const visiblePresets = presets.slice(0, MAX_VISIBLE_PRESETS);\n const hasMore = presets.length > MAX_VISIBLE_PRESETS;\n\n useEffect(() => {\n if (initialLoadDone.current) return;\n if (serverTheme) {\n setLocalTheme(serverTheme);\n injectThemeCSS(serverTheme);\n initialLoadDone.current = true;\n } else if (presets.length > 0 && activeThemeResult.data === null) {\n initialLoadDone.current = true;\n }\n }, [serverTheme, presets, activeThemeResult.data]);\n\n const selectPreset = useCallback(\n (preset: ThemeConfig) => {\n const next = { ...preset, updatedAt: new Date().toISOString() };\n setLocalTheme(next);\n injectThemeCSS(next);\n setHasUnsaved(true);\n setSavedAt(null);\n },\n [],\n );\n\n const updateToken = useCallback(\n (token: string, value: string) => {\n setLocalTheme((prev) => {\n if (!prev) return prev;\n const next = {\n ...prev,\n tokens: { ...prev.tokens, [token]: value },\n updatedAt: new Date().toISOString(),\n };\n injectThemeCSS(next);\n return next;\n });\n setHasUnsaved(true);\n setSavedAt(null);\n },\n [],\n );\n\n const updateRadius = useCallback((value: string) => {\n setLocalTheme((prev) => {\n if (!prev) return prev;\n const next = { ...prev, radius: value, updatedAt: new Date().toISOString() };\n injectThemeCSS(next);\n return next;\n });\n setHasUnsaved(true);\n setSavedAt(null);\n }, []);\n\n const handleSave = useCallback(async () => {\n if (!localTheme) return;\n setSaving(true);\n try {\n await applyTheme(localTheme);\n setHasUnsaved(false);\n setSavedAt(new Date().toLocaleTimeString());\n } catch (err) {\n console.error(\"Failed to save theme:\", err);\n } finally {\n setSaving(false);\n }\n }, [localTheme, applyTheme]);\n\n const handleReset = useCallback(async () => {\n setSaving(true);\n try {\n const result = await resetTheme({});\n const restored = result as unknown as ThemeConfig;\n setLocalTheme(restored);\n injectThemeCSS(restored);\n setHasUnsaved(false);\n setSavedAt(null);\n } catch (err) {\n console.error(\"Failed to reset theme:\", err);\n } finally {\n setSaving(false);\n }\n }, [resetTheme]);\n\n const radiusNum = parseFloat(localTheme?.radius ?? \"0\") || 0;\n\n return (\n <div style={styles.root}>\n {/* Header */}\n <div style={styles.header}>\n <h2 style={styles.title}>Theme</h2>\n <p style={styles.subtitle}>\n Choose a preset or fine-tune individual design tokens. Changes preview instantly.\n </p>\n </div>\n\n {/* Presets \u2014 2-row horizontal scroll */}\n <div style={styles.section}>\n <div style={styles.sectionHeader}>\n <p style={styles.sectionLabel}>Presets</p>\n {hasMore && (\n <button\n type=\"button\"\n style={styles.seeAllBtn}\n onClick={() => setShowModal(true)}\n onMouseEnter={(e) => { e.currentTarget.style.opacity = \"0.7\"; }}\n onMouseLeave={(e) => { e.currentTarget.style.opacity = \"1\"; }}\n >\n See all {presets.length} themes\n </button>\n )}\n </div>\n <div style={styles.presetsScroller}>\n <div style={styles.presetsTrack}>\n {visiblePresets.map((preset) => (\n <PresetCard\n key={preset.id}\n preset={preset}\n isActive={localTheme?.id === preset.id}\n onSelect={() => selectPreset(preset)}\n />\n ))}\n </div>\n </div>\n </div>\n\n {/* \"See All\" modal */}\n {showModal && (\n <PresetModal\n presets={presets}\n activeId={localTheme?.id}\n onSelect={selectPreset}\n onClose={() => setShowModal(false)}\n />\n )}\n\n {/* Token Editor */}\n {localTheme && (\n <div style={styles.section}>\n <p style={styles.sectionLabel}>Design Tokens</p>\n {TOKEN_GROUPS.map((group) => (\n <div key={group.label} style={styles.tokenGroup}>\n <div style={styles.tokenGroupHeader}>\n <p style={styles.tokenGroupLabel}>{group.label}</p>\n <p style={styles.tokenGroupDesc}>{group.description}</p>\n </div>\n {group.tokens.map((token) => (\n <TokenRow\n key={token}\n token={token}\n value={localTheme.tokens[token] ?? \"\"}\n onChange={updateToken}\n />\n ))}\n </div>\n ))}\n </div>\n )}\n\n {/* Radius */}\n {localTheme && (\n <div style={styles.section}>\n <p style={styles.sectionLabel}>Border Radius</p>\n <div style={styles.radiusSection}>\n <div style={styles.radiusPreview(localTheme.radius || \"0\")} />\n <input\n type=\"range\"\n min=\"0\"\n max=\"1.5\"\n step=\"0.125\"\n value={radiusNum}\n onChange={(e) => updateRadius(`${e.target.value}rem`)}\n style={styles.rangeInput}\n />\n <span style={styles.radiusValue}>{localTheme.radius || \"0\"}</span>\n </div>\n </div>\n )}\n\n {/* Actions */}\n <div style={styles.actions}>\n <button\n type=\"button\"\n style={{\n ...styles.btnPrimary,\n opacity: saving || !hasUnsaved ? 0.5 : 1,\n pointerEvents: saving || !hasUnsaved ? \"none\" : \"auto\",\n }}\n onClick={handleSave}\n disabled={saving || !hasUnsaved}\n >\n {saving ? \"Saving\\u2026\" : \"Save Theme\"}\n </button>\n <button\n type=\"button\"\n style={styles.btnSecondary}\n onClick={handleReset}\n disabled={saving}\n >\n Reset to Default\n </button>\n {savedAt && (\n <span style={styles.saved}>Saved at {savedAt}</span>\n )}\n {hasUnsaved && !savedAt && (\n <span style={{ ...styles.saved, color: \"var(--chart-1)\" }}>Unsaved changes</span>\n )}\n </div>\n </div>\n );\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import React, { useState, useEffect, useCallback, useRef, useMemo } from \"react\";\nimport {\n usePluginData,\n usePluginAction,\n} from \"@paperclipai/plugin-sdk/ui\";\n\n/* \u2500\u2500\u2500 Types \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\ninterface ThemeConfig {\n id: string;\n name: string;\n description: string;\n author: string;\n isDark: boolean;\n tokens: Record<string, string>;\n radius: string;\n createdAt: string;\n updatedAt: string;\n}\n\n/* \u2500\u2500\u2500 Constants \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\nconst MAX_VISIBLE_PRESETS = 8;\nconst CARD_WIDTH = 192;\nconst CARD_GAP = 10;\nconst SWATCH_TOKENS = [\"--background\", \"--primary\", \"--accent\", \"--chart-1\", \"--destructive\"];\n\n/* \u2500\u2500\u2500 CSS injection engine \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\nconst STYLE_ELEMENT_ID = \"blazo-theme-overrides\";\n\nfunction injectThemeCSS(theme: ThemeConfig): void {\n let el = document.getElementById(STYLE_ELEMENT_ID) as HTMLStyleElement | null;\n if (!el) {\n el = document.createElement(\"style\");\n el.id = STYLE_ELEMENT_ID;\n document.head.appendChild(el);\n }\n\n const entries = Object.entries(theme.tokens);\n const radiusEntry = theme.radius ? ` --radius: ${theme.radius};` : \"\";\n\n const lines = entries.map(([key, value]) => ` ${key}: ${value};`);\n if (radiusEntry) lines.push(radiusEntry);\n\n const darkToggle = theme.isDark ? \"dark\" : \"light\";\n el.textContent = `:root { ${lines.join(\" \")} }\\n`;\n\n const htmlEl = document.documentElement;\n htmlEl.classList.toggle(\"dark\", theme.isDark);\n htmlEl.classList.toggle(\"light\", !theme.isDark);\n htmlEl.style.colorScheme = darkToggle;\n}\n\nfunction clearThemeCSS(): void {\n const el = document.getElementById(STYLE_ELEMENT_ID);\n if (el) el.remove();\n}\n\n/* \u2500\u2500\u2500 Token groups for the editor \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\ninterface TokenGroup {\n label: string;\n description: string;\n tokens: string[];\n}\n\nconst TOKEN_GROUPS: TokenGroup[] = [\n {\n label: \"Surfaces\",\n description: \"Background and card colors\",\n tokens: [\"--background\", \"--card\", \"--muted\", \"--accent\"],\n },\n {\n label: \"Text\",\n description: \"Foreground and label colors\",\n tokens: [\"--foreground\", \"--card-foreground\", \"--muted-foreground\", \"--accent-foreground\"],\n },\n {\n label: \"Interactive\",\n description: \"Buttons, links, and primary actions\",\n tokens: [\"--primary\", \"--primary-foreground\"],\n },\n {\n label: \"Feedback\",\n description: \"Errors and destructive actions\",\n tokens: [\"--destructive\", \"--destructive-foreground\"],\n },\n {\n label: \"Structure\",\n description: \"Borders and focus rings\",\n tokens: [\"--border\", \"--input\", \"--ring\"],\n },\n {\n label: \"Charts\",\n description: \"Dashboard visualization colors\",\n tokens: [\"--chart-1\", \"--chart-2\", \"--chart-3\", \"--chart-4\", \"--chart-5\"],\n },\n];\n\n/* \u2500\u2500\u2500 Helpers \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\nfunction tokenDisplayName(token: string): string {\n return token\n .replace(/^--/, \"\")\n .split(\"-\")\n .map((w) => w.charAt(0).toUpperCase() + w.slice(1))\n .join(\" \");\n}\n\nfunction oklchToHex(oklchStr: string): string {\n const canvas = document.createElement(\"canvas\");\n canvas.width = 1;\n canvas.height = 1;\n const ctx2d = canvas.getContext(\"2d\");\n if (!ctx2d) return \"#000000\";\n ctx2d.fillStyle = oklchStr;\n ctx2d.fillRect(0, 0, 1, 1);\n const [r, g, b] = ctx2d.getImageData(0, 0, 1, 1).data;\n return `#${(r ?? 0).toString(16).padStart(2, \"0\")}${(g ?? 0).toString(16).padStart(2, \"0\")}${(b ?? 0).toString(16).padStart(2, \"0\")}`;\n}\n\nfunction hexToOklch(hex: string): string {\n const canvas = document.createElement(\"canvas\");\n canvas.width = 1;\n canvas.height = 1;\n const ctx2d = canvas.getContext(\"2d\");\n if (!ctx2d) return \"oklch(0% 0 0)\";\n ctx2d.fillStyle = hex;\n ctx2d.fillRect(0, 0, 1, 1);\n const [r, g, b] = ctx2d.getImageData(0, 0, 1, 1).data;\n const rLin = srgbToLinear((r ?? 0) / 255);\n const gLin = srgbToLinear((g ?? 0) / 255);\n const bLin = srgbToLinear((b ?? 0) / 255);\n const l = 0.4122214708 * rLin + 0.5363325363 * gLin + 0.0514459929 * bLin;\n const m = 0.2119034982 * rLin + 0.6806995451 * gLin + 0.1073969566 * bLin;\n const s = 0.0883024619 * rLin + 0.2817188376 * gLin + 0.6299787005 * bLin;\n const lRoot = Math.cbrt(l);\n const mRoot = Math.cbrt(m);\n const sRoot = Math.cbrt(s);\n const L = 0.2104542553 * lRoot + 0.7936177850 * mRoot - 0.0040720468 * sRoot;\n const a = 1.9779984951 * lRoot - 2.4285922050 * mRoot + 0.4505937099 * sRoot;\n const bOklab = 0.0259040371 * lRoot + 0.7827717662 * mRoot - 0.8086757660 * sRoot;\n const C = Math.sqrt(a * a + bOklab * bOklab);\n let H = (Math.atan2(bOklab, a) * 180) / Math.PI;\n if (H < 0) H += 360;\n return `oklch(${(L * 100).toFixed(1)}% ${C.toFixed(3)} ${H.toFixed(1)})`;\n}\n\nfunction srgbToLinear(c: number): number {\n return c <= 0.04045 ? c / 12.92 : Math.pow((c + 0.055) / 1.055, 2.4);\n}\n\n/* \u2500\u2500\u2500 Style definitions \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\nconst styles = {\n root: {\n fontFamily: \"var(--font-sans, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif)\",\n color: \"var(--foreground)\",\n maxWidth: 720,\n display: \"flex\",\n flexDirection: \"column\" as const,\n gap: 32,\n },\n header: {\n display: \"flex\",\n flexDirection: \"column\" as const,\n gap: 6,\n },\n title: {\n fontSize: 20,\n fontWeight: 600,\n letterSpacing: \"-0.01em\",\n margin: 0,\n color: \"var(--foreground)\",\n },\n subtitle: {\n fontSize: 13,\n color: \"var(--muted-foreground)\",\n margin: 0,\n lineHeight: 1.5,\n },\n section: {\n display: \"flex\",\n flexDirection: \"column\" as const,\n gap: 16,\n },\n sectionHeader: {\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"space-between\",\n margin: 0,\n },\n sectionLabel: {\n fontSize: 13,\n fontWeight: 600,\n textTransform: \"uppercase\" as const,\n letterSpacing: \"0.04em\",\n color: \"var(--muted-foreground)\",\n margin: 0,\n },\n seeAllBtn: {\n fontSize: 12,\n fontWeight: 500,\n color: \"var(--primary)\",\n background: \"none\",\n border: \"none\",\n cursor: \"pointer\",\n padding: \"2px 0\",\n outline: \"none\",\n transition: \"opacity 150ms ease\",\n },\n presetsScroller: {\n overflowX: \"auto\" as const,\n overflowY: \"hidden\" as const,\n WebkitOverflowScrolling: \"touch\" as const,\n scrollbarWidth: \"thin\" as const,\n paddingBottom: 4,\n },\n presetsTrack: {\n display: \"grid\",\n gridTemplateRows: \"1fr 1fr\",\n gridAutoFlow: \"column\" as const,\n gridAutoColumns: `${CARD_WIDTH}px`,\n gap: CARD_GAP,\n },\n presetCard: (isActive: boolean) => ({\n position: \"relative\" as const,\n width: CARD_WIDTH,\n padding: \"12px 14px\",\n borderRadius: 8,\n border: `1.5px solid ${isActive ? \"var(--primary)\" : \"var(--border)\"}`,\n background: isActive ? \"var(--accent)\" : \"transparent\",\n cursor: \"pointer\",\n transition: \"all 150ms ease\",\n display: \"flex\",\n flexDirection: \"column\" as const,\n gap: 5,\n outline: \"none\",\n boxSizing: \"border-box\" as const,\n textAlign: \"left\" as const,\n }),\n presetName: {\n fontSize: 13,\n fontWeight: 500,\n color: \"var(--foreground)\",\n margin: 0,\n whiteSpace: \"nowrap\" as const,\n overflow: \"hidden\" as const,\n textOverflow: \"ellipsis\" as const,\n },\n presetDesc: {\n fontSize: 11,\n color: \"var(--muted-foreground)\",\n margin: 0,\n lineHeight: 1.35,\n display: \"-webkit-box\",\n WebkitLineClamp: 2,\n WebkitBoxOrient: \"vertical\" as const,\n overflow: \"hidden\" as const,\n },\n presetMeta: {\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"space-between\",\n marginTop: 2,\n },\n presetColors: {\n display: \"flex\",\n gap: 3,\n },\n presetSwatch: (color: string) => ({\n width: 14,\n height: 14,\n borderRadius: 3,\n background: color,\n border: \"1px solid rgba(128,128,128,0.25)\",\n flexShrink: 0,\n }),\n presetModeBadge: (isDark: boolean) => ({\n fontSize: 9,\n fontWeight: 600,\n textTransform: \"uppercase\" as const,\n letterSpacing: \"0.06em\",\n color: \"var(--muted-foreground)\",\n background: \"var(--muted)\",\n padding: \"1px 5px\",\n borderRadius: 3,\n lineHeight: \"16px\",\n }),\n activeBadge: {\n position: \"absolute\" as const,\n top: 7,\n right: 8,\n fontSize: 9,\n fontWeight: 600,\n textTransform: \"uppercase\" as const,\n letterSpacing: \"0.06em\",\n color: \"var(--primary-foreground)\",\n background: \"var(--primary)\",\n padding: \"1px 6px\",\n borderRadius: 999,\n lineHeight: \"16px\",\n },\n tokenGroup: {\n display: \"flex\",\n flexDirection: \"column\" as const,\n gap: 10,\n padding: \"16px 0\",\n borderBottom: \"1px solid var(--border)\",\n },\n tokenGroupHeader: {\n display: \"flex\",\n flexDirection: \"column\" as const,\n gap: 2,\n },\n tokenGroupLabel: {\n fontSize: 14,\n fontWeight: 500,\n color: \"var(--foreground)\",\n margin: 0,\n },\n tokenGroupDesc: {\n fontSize: 12,\n color: \"var(--muted-foreground)\",\n margin: 0,\n },\n tokenRow: {\n display: \"flex\",\n alignItems: \"center\",\n gap: 12,\n padding: \"4px 0\",\n },\n colorInput: {\n width: 32,\n height: 32,\n border: \"1.5px solid var(--border)\",\n borderRadius: 6,\n padding: 0,\n cursor: \"pointer\",\n background: \"none\",\n flexShrink: 0,\n outline: \"none\",\n },\n tokenLabel: {\n fontSize: 13,\n fontWeight: 400,\n color: \"var(--foreground)\",\n flex: 1,\n minWidth: 0,\n },\n tokenValue: {\n fontSize: 11,\n fontFamily: \"var(--font-mono, 'SF Mono', Consolas, monospace)\",\n color: \"var(--muted-foreground)\",\n textAlign: \"right\" as const,\n whiteSpace: \"nowrap\" as const,\n overflow: \"hidden\" as const,\n textOverflow: \"ellipsis\" as const,\n maxWidth: 180,\n },\n radiusSection: {\n display: \"flex\",\n alignItems: \"center\",\n gap: 16,\n padding: \"8px 0\",\n },\n rangeInput: {\n flex: 1,\n accentColor: \"var(--primary)\",\n cursor: \"pointer\",\n },\n radiusValue: {\n fontSize: 13,\n fontFamily: \"var(--font-mono, 'SF Mono', Consolas, monospace)\",\n color: \"var(--muted-foreground)\",\n minWidth: 48,\n textAlign: \"right\" as const,\n },\n radiusPreview: (r: string) => ({\n width: 32,\n height: 32,\n borderRadius: r,\n border: \"2px solid var(--primary)\",\n background: \"var(--accent)\",\n flexShrink: 0,\n }),\n actions: {\n display: \"flex\",\n gap: 10,\n paddingTop: 8,\n },\n btnPrimary: {\n padding: \"9px 20px\",\n borderRadius: 6,\n border: \"none\",\n background: \"var(--primary)\",\n color: \"var(--primary-foreground)\",\n fontSize: 13,\n fontWeight: 500,\n cursor: \"pointer\",\n transition: \"opacity 150ms ease\",\n outline: \"none\",\n },\n btnSecondary: {\n padding: \"9px 20px\",\n borderRadius: 6,\n border: \"1.5px solid var(--border)\",\n background: \"transparent\",\n color: \"var(--foreground)\",\n fontSize: 13,\n fontWeight: 500,\n cursor: \"pointer\",\n transition: \"all 150ms ease\",\n outline: \"none\",\n },\n saved: {\n fontSize: 12,\n color: \"var(--muted-foreground)\",\n alignSelf: \"center\" as const,\n transition: \"opacity 300ms ease\",\n },\n overlay: {\n position: \"fixed\" as const,\n inset: 0,\n background: \"rgba(0,0,0,0.55)\",\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n zIndex: 9999,\n backdropFilter: \"blur(4px)\",\n },\n modal: {\n background: \"var(--card)\",\n border: \"1px solid var(--border)\",\n borderRadius: 12,\n width: \"min(640px, calc(100vw - 48px))\",\n maxHeight: \"min(560px, calc(100vh - 80px))\",\n display: \"flex\",\n flexDirection: \"column\" as const,\n boxShadow: \"0 16px 48px rgba(0,0,0,0.25)\",\n overflow: \"hidden\" as const,\n },\n modalHeader: {\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"space-between\",\n padding: \"16px 20px 0 20px\",\n },\n modalTitle: {\n fontSize: 16,\n fontWeight: 600,\n margin: 0,\n color: \"var(--foreground)\",\n },\n modalCloseBtn: {\n width: 28,\n height: 28,\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n background: \"none\",\n border: \"none\",\n borderRadius: 6,\n cursor: \"pointer\",\n color: \"var(--muted-foreground)\",\n fontSize: 18,\n lineHeight: 1,\n outline: \"none\",\n transition: \"background 150ms ease\",\n },\n modalSearch: {\n margin: \"12px 20px\",\n padding: \"8px 12px\",\n borderRadius: 6,\n border: \"1.5px solid var(--border)\",\n background: \"var(--muted)\",\n color: \"var(--foreground)\",\n fontSize: 13,\n outline: \"none\",\n width: \"calc(100% - 40px)\",\n boxSizing: \"border-box\" as const,\n transition: \"border-color 150ms ease\",\n },\n modalCount: {\n fontSize: 11,\n color: \"var(--muted-foreground)\",\n padding: \"0 20px 8px 20px\",\n margin: 0,\n },\n modalGrid: {\n flex: 1,\n overflowY: \"auto\" as const,\n padding: \"0 20px 20px 20px\",\n display: \"grid\",\n gridTemplateColumns: \"repeat(auto-fill, minmax(180px, 1fr))\",\n gap: 10,\n alignContent: \"start\",\n },\n};\n\n/* \u2500\u2500\u2500 Preset Card \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\nfunction PresetCard({\n preset,\n isActive,\n onSelect,\n compact,\n}: {\n preset: ThemeConfig;\n isActive: boolean;\n onSelect: () => void;\n compact?: boolean;\n}) {\n const cardStyle = compact\n ? {\n ...styles.presetCard(isActive),\n width: \"auto\" as const,\n }\n : styles.presetCard(isActive);\n\n return (\n <button\n type=\"button\"\n style={cardStyle}\n onClick={onSelect}\n onMouseEnter={(e) => {\n if (!isActive) (e.currentTarget.style.borderColor = \"var(--muted-foreground)\");\n }}\n onMouseLeave={(e) => {\n if (!isActive) (e.currentTarget.style.borderColor = \"var(--border)\");\n }}\n >\n {isActive && <span style={styles.activeBadge}>Active</span>}\n <p style={styles.presetName}>{preset.name}</p>\n <p style={styles.presetDesc}>{preset.description}</p>\n <div style={styles.presetMeta}>\n <div style={styles.presetColors}>\n {SWATCH_TOKENS.map((t) => (\n <div key={t} style={styles.presetSwatch(preset.tokens[t] ?? \"#333\")} />\n ))}\n </div>\n <span style={styles.presetModeBadge(preset.isDark)}>\n {preset.isDark ? \"Dark\" : \"Light\"}\n </span>\n </div>\n </button>\n );\n}\n\n/* \u2500\u2500\u2500 \"See All\" Modal \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\nfunction PresetModal({\n presets,\n activeId,\n onSelect,\n onClose,\n}: {\n presets: ThemeConfig[];\n activeId: string | undefined;\n onSelect: (preset: ThemeConfig) => void;\n onClose: () => void;\n}) {\n const [search, setSearch] = useState(\"\");\n const searchRef = useRef<HTMLInputElement>(null);\n\n useEffect(() => {\n searchRef.current?.focus();\n }, []);\n\n useEffect(() => {\n const handleKey = (e: KeyboardEvent) => {\n if (e.key === \"Escape\") onClose();\n };\n document.addEventListener(\"keydown\", handleKey);\n return () => document.removeEventListener(\"keydown\", handleKey);\n }, [onClose]);\n\n const filtered = useMemo(() => {\n if (!search.trim()) return presets;\n const q = search.toLowerCase().trim();\n return presets.filter(\n (p) =>\n p.name.toLowerCase().includes(q) ||\n p.description.toLowerCase().includes(q) ||\n p.author.toLowerCase().includes(q) ||\n (p.isDark ? \"dark\" : \"light\").includes(q),\n );\n }, [presets, search]);\n\n return (\n <div\n style={styles.overlay}\n onClick={(e) => {\n if (e.target === e.currentTarget) onClose();\n }}\n >\n <div style={styles.modal}>\n <div style={styles.modalHeader}>\n <h3 style={styles.modalTitle}>All Themes</h3>\n <button\n type=\"button\"\n style={styles.modalCloseBtn}\n onClick={onClose}\n onMouseEnter={(e) => {\n e.currentTarget.style.background = \"var(--muted)\";\n }}\n onMouseLeave={(e) => {\n e.currentTarget.style.background = \"none\";\n }}\n >\n &#x2715;\n </button>\n </div>\n <input\n ref={searchRef}\n type=\"text\"\n placeholder=\"Search themes...\"\n value={search}\n onChange={(e) => setSearch(e.target.value)}\n style={styles.modalSearch}\n onFocus={(e) => {\n e.currentTarget.style.borderColor = \"var(--primary)\";\n }}\n onBlur={(e) => {\n e.currentTarget.style.borderColor = \"var(--border)\";\n }}\n />\n <p style={styles.modalCount}>\n {filtered.length} of {presets.length} themes\n </p>\n <div style={styles.modalGrid}>\n {filtered.map((preset) => (\n <PresetCard\n key={preset.id}\n preset={preset}\n isActive={activeId === preset.id}\n onSelect={() => {\n onSelect(preset);\n onClose();\n }}\n compact\n />\n ))}\n {filtered.length === 0 && (\n <p style={{ ...styles.subtitle, gridColumn: \"1 / -1\", textAlign: \"center\" as const, padding: \"32px 0\" }}>\n No themes match your search.\n </p>\n )}\n </div>\n </div>\n </div>\n );\n}\n\n/* \u2500\u2500\u2500 Token Editor Row \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\nfunction TokenRow({\n token,\n value,\n onChange,\n}: {\n token: string;\n value: string;\n onChange: (token: string, value: string) => void;\n}) {\n const hex = oklchToHex(value);\n return (\n <div style={styles.tokenRow}>\n <input\n type=\"color\"\n style={styles.colorInput}\n value={hex}\n onChange={(e) => {\n const newOklch = hexToOklch(e.target.value);\n onChange(token, newOklch);\n }}\n title={tokenDisplayName(token)}\n />\n <span style={styles.tokenLabel}>{tokenDisplayName(token)}</span>\n <span style={styles.tokenValue}>{value}</span>\n </div>\n );\n}\n\n/* \u2500\u2500\u2500 Main Settings Page Component \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\nexport function ThemeSettingsPage() {\n const activeThemeResult = usePluginData<ThemeConfig | null>(\"active-theme\");\n const presetsResult = usePluginData<ThemeConfig[]>(\"presets\");\n const applyTheme = usePluginAction(\"apply-theme\");\n const resetTheme = usePluginAction(\"reset-theme\");\n const importThemeAction = usePluginAction(\"import-theme\");\n\n const [localTheme, setLocalTheme] = useState<ThemeConfig | null>(null);\n const [saving, setSaving] = useState(false);\n const [savedAt, setSavedAt] = useState<string | null>(null);\n const [hasUnsaved, setHasUnsaved] = useState(false);\n const [showModal, setShowModal] = useState(false);\n const [importError, setImportError] = useState<string | null>(null);\n const initialLoadDone = useRef(false);\n const fileInputRef = useRef<HTMLInputElement>(null);\n\n const presets: ThemeConfig[] = presetsResult.data ?? [];\n const serverTheme: ThemeConfig | null = activeThemeResult.data ?? null;\n\n const visiblePresets = presets.slice(0, MAX_VISIBLE_PRESETS);\n const hasMore = presets.length > MAX_VISIBLE_PRESETS;\n\n useEffect(() => {\n if (initialLoadDone.current) return;\n if (serverTheme) {\n setLocalTheme(serverTheme);\n injectThemeCSS(serverTheme);\n initialLoadDone.current = true;\n } else if (presets.length > 0 && activeThemeResult.data === null) {\n initialLoadDone.current = true;\n }\n }, [serverTheme, presets, activeThemeResult.data]);\n\n const selectPreset = useCallback(\n (preset: ThemeConfig) => {\n const next = { ...preset, updatedAt: new Date().toISOString() };\n setLocalTheme(next);\n injectThemeCSS(next);\n setHasUnsaved(true);\n setSavedAt(null);\n },\n [],\n );\n\n const updateToken = useCallback(\n (token: string, value: string) => {\n setLocalTheme((prev) => {\n if (!prev) return prev;\n const next = {\n ...prev,\n tokens: { ...prev.tokens, [token]: value },\n updatedAt: new Date().toISOString(),\n };\n injectThemeCSS(next);\n return next;\n });\n setHasUnsaved(true);\n setSavedAt(null);\n },\n [],\n );\n\n const updateRadius = useCallback((value: string) => {\n setLocalTheme((prev) => {\n if (!prev) return prev;\n const next = { ...prev, radius: value, updatedAt: new Date().toISOString() };\n injectThemeCSS(next);\n return next;\n });\n setHasUnsaved(true);\n setSavedAt(null);\n }, []);\n\n const handleSave = useCallback(async () => {\n if (!localTheme) return;\n setSaving(true);\n try {\n await applyTheme(localTheme);\n setHasUnsaved(false);\n setSavedAt(new Date().toLocaleTimeString());\n } catch (err) {\n console.error(\"Failed to save theme:\", err);\n } finally {\n setSaving(false);\n }\n }, [localTheme, applyTheme]);\n\n const handleReset = useCallback(async () => {\n setSaving(true);\n try {\n const result = await resetTheme({});\n const restored = result as unknown as ThemeConfig;\n setLocalTheme(restored);\n injectThemeCSS(restored);\n setHasUnsaved(false);\n setSavedAt(null);\n } catch (err) {\n console.error(\"Failed to reset theme:\", err);\n } finally {\n setSaving(false);\n }\n }, [resetTheme]);\n\n const handleExport = useCallback(() => {\n if (!localTheme) return;\n const payload = JSON.stringify(localTheme, null, 2);\n const blob = new Blob([payload], { type: \"application/json\" });\n const url = URL.createObjectURL(blob);\n const a = document.createElement(\"a\");\n a.href = url;\n a.download = `${localTheme.id}.theme.json`;\n document.body.appendChild(a);\n a.click();\n document.body.removeChild(a);\n URL.revokeObjectURL(url);\n }, [localTheme]);\n\n const handleImportFile = useCallback(\n async (e: React.ChangeEvent<HTMLInputElement>) => {\n setImportError(null);\n const file = e.target.files?.[0];\n if (!file) return;\n try {\n const text = await file.text();\n const parsed: unknown = JSON.parse(text);\n if (\n typeof parsed !== \"object\" ||\n parsed === null ||\n typeof (parsed as Record<string, unknown>).id !== \"string\" ||\n typeof (parsed as Record<string, unknown>).name !== \"string\" ||\n typeof (parsed as Record<string, unknown>).tokens !== \"object\" ||\n typeof (parsed as Record<string, unknown>).isDark !== \"boolean\"\n ) {\n setImportError(\"Invalid theme file: must contain id, name, tokens, and isDark fields.\");\n return;\n }\n const result = await importThemeAction(parsed);\n const imported = result as unknown as ThemeConfig;\n setLocalTheme(imported);\n injectThemeCSS(imported);\n setHasUnsaved(true);\n setSavedAt(null);\n } catch (err) {\n setImportError(`Import failed: ${String(err)}`);\n } finally {\n if (fileInputRef.current) fileInputRef.current.value = \"\";\n }\n },\n [importThemeAction],\n );\n\n const radiusNum = parseFloat(localTheme?.radius ?? \"0\") || 0;\n\n return (\n <div style={styles.root}>\n {/* Header */}\n <div style={styles.header}>\n <h2 style={styles.title}>Theme</h2>\n <p style={styles.subtitle}>\n Choose a preset or fine-tune individual design tokens. Changes preview instantly.\n </p>\n </div>\n\n {/* Presets \u2014 2-row horizontal scroll */}\n <div style={styles.section}>\n <div style={styles.sectionHeader}>\n <p style={styles.sectionLabel}>Presets</p>\n {hasMore && (\n <button\n type=\"button\"\n style={styles.seeAllBtn}\n onClick={() => setShowModal(true)}\n onMouseEnter={(e) => { e.currentTarget.style.opacity = \"0.7\"; }}\n onMouseLeave={(e) => { e.currentTarget.style.opacity = \"1\"; }}\n >\n See all {presets.length} themes\n </button>\n )}\n </div>\n <div style={styles.presetsScroller}>\n <div style={styles.presetsTrack}>\n {visiblePresets.map((preset) => (\n <PresetCard\n key={preset.id}\n preset={preset}\n isActive={localTheme?.id === preset.id}\n onSelect={() => selectPreset(preset)}\n />\n ))}\n </div>\n </div>\n </div>\n\n {/* \"See All\" modal */}\n {showModal && (\n <PresetModal\n presets={presets}\n activeId={localTheme?.id}\n onSelect={selectPreset}\n onClose={() => setShowModal(false)}\n />\n )}\n\n {/* Token Editor */}\n {localTheme && (\n <div style={styles.section}>\n <p style={styles.sectionLabel}>Design Tokens</p>\n {TOKEN_GROUPS.map((group) => (\n <div key={group.label} style={styles.tokenGroup}>\n <div style={styles.tokenGroupHeader}>\n <p style={styles.tokenGroupLabel}>{group.label}</p>\n <p style={styles.tokenGroupDesc}>{group.description}</p>\n </div>\n {group.tokens.map((token) => (\n <TokenRow\n key={token}\n token={token}\n value={localTheme.tokens[token] ?? \"\"}\n onChange={updateToken}\n />\n ))}\n </div>\n ))}\n </div>\n )}\n\n {/* Radius */}\n {localTheme && (\n <div style={styles.section}>\n <p style={styles.sectionLabel}>Border Radius</p>\n <div style={styles.radiusSection}>\n <div style={styles.radiusPreview(localTheme.radius || \"0\")} />\n <input\n type=\"range\"\n min=\"0\"\n max=\"1.5\"\n step=\"0.125\"\n value={radiusNum}\n onChange={(e) => updateRadius(`${e.target.value}rem`)}\n style={styles.rangeInput}\n />\n <span style={styles.radiusValue}>{localTheme.radius || \"0\"}</span>\n </div>\n </div>\n )}\n\n {/* Actions */}\n <div style={styles.actions}>\n <button\n type=\"button\"\n style={{\n ...styles.btnPrimary,\n opacity: saving || !hasUnsaved ? 0.5 : 1,\n pointerEvents: saving || !hasUnsaved ? \"none\" : \"auto\",\n }}\n onClick={handleSave}\n disabled={saving || !hasUnsaved}\n >\n {saving ? \"Saving\\u2026\" : \"Save Theme\"}\n </button>\n <button\n type=\"button\"\n style={styles.btnSecondary}\n onClick={handleReset}\n disabled={saving}\n >\n Reset to Default\n </button>\n {savedAt && (\n <span style={styles.saved}>Saved at {savedAt}</span>\n )}\n {hasUnsaved && !savedAt && (\n <span style={{ ...styles.saved, color: \"var(--chart-1)\" }}>Unsaved changes</span>\n )}\n </div>\n\n {/* Import / Export */}\n <div style={styles.section}>\n <p style={styles.sectionLabel}>Share</p>\n <p style={{ ...styles.subtitle, marginTop: -8 }}>\n Export your current theme as a JSON file to share with others, or import a community theme.\n </p>\n <div style={styles.actions}>\n <button\n type=\"button\"\n style={{\n ...styles.btnSecondary,\n opacity: localTheme ? 1 : 0.5,\n pointerEvents: localTheme ? \"auto\" : \"none\",\n }}\n onClick={handleExport}\n disabled={!localTheme}\n >\n Export Theme\n </button>\n <button\n type=\"button\"\n style={styles.btnSecondary}\n onClick={() => fileInputRef.current?.click()}\n >\n Import Theme\n </button>\n <input\n ref={fileInputRef}\n type=\"file\"\n accept=\".json,application/json\"\n style={{ display: \"none\" }}\n onChange={handleImportFile}\n />\n </div>\n {importError && (\n <p style={{ fontSize: 12, color: \"var(--destructive)\", margin: 0 }}>\n {importError}\n </p>\n )}\n </div>\n </div>\n );\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -1 +1 @@
1
- {"version":3,"file":"worker.d.ts","sourceRoot":"","sources":["../src/worker.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,eAAe,EAGrB,MAAM,yBAAyB,CAAC;AA6BjC,QAAA,MAAM,MAAM,EAAE,eAkEZ,CAAC;AAEH,eAAe,MAAM,CAAC"}
1
+ {"version":3,"file":"worker.d.ts","sourceRoot":"","sources":["../src/worker.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,eAAe,EAGrB,MAAM,yBAAyB,CAAC;AAwHjC,QAAA,MAAM,MAAM,EAAE,eAoHZ,CAAC;AAEH,eAAe,MAAM,CAAC"}
package/dist/worker.js CHANGED
@@ -1,6 +1,9 @@
1
1
  import { definePlugin, runWorker, } from "@paperclipai/plugin-sdk";
2
- import { STATE_KEYS, DATA_ENDPOINTS, ACTION_NAMES, THEME_PRESETS, } from "./constants.js";
2
+ import { STATE_KEYS, DATA_ENDPOINTS, ACTION_NAMES, THEME_PRESETS, REMOTE_REGISTRY_URL, } from "./constants.js";
3
3
  let currentContext = null;
4
+ /** In-memory cache of remote themes, refreshed on startup. */
5
+ let remoteThemes = [];
6
+ /* ─── State helpers ──────────────────────────────────────────────── */
4
7
  async function readTheme(ctx) {
5
8
  return (await ctx.state.get({
6
9
  scopeKind: "instance",
@@ -10,21 +13,85 @@ async function readTheme(ctx) {
10
13
  async function writeTheme(ctx, theme) {
11
14
  await ctx.state.set({ scopeKind: "instance", stateKey: STATE_KEYS.activeTheme }, theme);
12
15
  }
16
+ async function readUserThemes(ctx) {
17
+ const stored = await ctx.state.get({
18
+ scopeKind: "instance",
19
+ stateKey: STATE_KEYS.userThemes,
20
+ });
21
+ if (!Array.isArray(stored))
22
+ return [];
23
+ return stored;
24
+ }
25
+ async function writeUserThemes(ctx, themes) {
26
+ await ctx.state.set({ scopeKind: "instance", stateKey: STATE_KEYS.userThemes }, themes);
27
+ }
28
+ function isValidTheme(t) {
29
+ if (typeof t !== "object" || t === null)
30
+ return false;
31
+ const obj = t;
32
+ return (typeof obj.id === "string" &&
33
+ typeof obj.name === "string" &&
34
+ typeof obj.tokens === "object" &&
35
+ obj.tokens !== null &&
36
+ typeof obj.isDark === "boolean");
37
+ }
38
+ async function fetchRemoteThemes(logger) {
39
+ try {
40
+ const response = await fetch(REMOTE_REGISTRY_URL);
41
+ if (!response.ok) {
42
+ logger.warn(`Remote theme registry returned ${response.status}, using bundled fallback`);
43
+ return [];
44
+ }
45
+ const payload = await response.json();
46
+ if (typeof payload !== "object" ||
47
+ payload === null ||
48
+ !Array.isArray(payload.themes)) {
49
+ logger.warn("Remote theme registry has invalid shape, using bundled fallback");
50
+ return [];
51
+ }
52
+ const themes = payload.themes.filter(isValidTheme);
53
+ logger.info(`Fetched ${themes.length} themes from remote registry`);
54
+ return themes;
55
+ }
56
+ catch (err) {
57
+ logger.warn(`Failed to fetch remote theme registry: ${String(err)}`);
58
+ return [];
59
+ }
60
+ }
61
+ /* ─── Merge logic: remote wins over bundled, user themes appended ── */
62
+ function mergePresets(bundled, remote, user) {
63
+ const merged = new Map();
64
+ for (const t of bundled)
65
+ merged.set(t.id, t);
66
+ for (const t of remote)
67
+ merged.set(t.id, t);
68
+ const result = Array.from(merged.values());
69
+ for (const t of user) {
70
+ if (!merged.has(t.id)) {
71
+ result.push(t);
72
+ }
73
+ }
74
+ return result;
75
+ }
76
+ /* ─── Plugin definition ──────────────────────────────────────────── */
13
77
  const plugin = definePlugin({
14
78
  async setup(ctx) {
15
79
  currentContext = ctx;
80
+ remoteThemes = await fetchRemoteThemes(ctx.logger);
16
81
  ctx.data.register(DATA_ENDPOINTS.activeTheme, async () => {
17
82
  return await readTheme(ctx);
18
83
  });
19
84
  ctx.data.register(DATA_ENDPOINTS.presets, async () => {
20
- return THEME_PRESETS;
85
+ const userThemes = await readUserThemes(ctx);
86
+ return mergePresets(THEME_PRESETS, remoteThemes, userThemes);
21
87
  });
22
88
  ctx.actions.register(ACTION_NAMES.applyTheme, async (params) => {
23
89
  const incoming = params;
24
90
  if (!incoming.id) {
25
91
  throw new Error("Theme id is required");
26
92
  }
27
- const preset = THEME_PRESETS.find((p) => p.id === incoming.id);
93
+ const allPresets = mergePresets(THEME_PRESETS, remoteThemes, await readUserThemes(ctx));
94
+ const preset = allPresets.find((p) => p.id === incoming.id);
28
95
  const theme = preset
29
96
  ? {
30
97
  ...preset,
@@ -47,23 +114,58 @@ const plugin = definePlugin({
47
114
  return theme;
48
115
  });
49
116
  ctx.actions.register(ACTION_NAMES.resetTheme, async () => {
50
- const defaultTheme = THEME_PRESETS[0];
117
+ const allPresets = mergePresets(THEME_PRESETS, remoteThemes, await readUserThemes(ctx));
118
+ const defaultTheme = allPresets[0];
51
119
  if (!defaultTheme) {
52
120
  throw new Error("No default preset found");
53
121
  }
54
122
  await writeTheme(ctx, defaultTheme);
55
123
  return defaultTheme;
56
124
  });
125
+ ctx.actions.register(ACTION_NAMES.importTheme, async (params) => {
126
+ const incoming = params;
127
+ if (!isValidTheme(incoming)) {
128
+ throw new Error("Invalid theme: must include id (string), name (string), tokens (object), isDark (boolean)");
129
+ }
130
+ const theme = {
131
+ id: incoming.id,
132
+ name: incoming.name,
133
+ description: incoming.description ?? "",
134
+ author: incoming.author ?? "Community",
135
+ isDark: incoming.isDark,
136
+ tokens: incoming.tokens,
137
+ radius: incoming.radius ?? "0",
138
+ createdAt: incoming.createdAt ?? new Date().toISOString(),
139
+ updatedAt: new Date().toISOString(),
140
+ };
141
+ const existing = await readUserThemes(ctx);
142
+ const filtered = existing.filter((t) => t.id !== theme.id);
143
+ filtered.push(theme);
144
+ await writeUserThemes(ctx, filtered);
145
+ return theme;
146
+ });
147
+ ctx.actions.register(ACTION_NAMES.removeUserTheme, async (params) => {
148
+ const { id } = params;
149
+ if (!id)
150
+ throw new Error("Theme id is required");
151
+ const existing = await readUserThemes(ctx);
152
+ const filtered = existing.filter((t) => t.id !== id);
153
+ await writeUserThemes(ctx, filtered);
154
+ return { removed: id };
155
+ });
57
156
  },
58
157
  async onHealth() {
59
158
  const ctx = currentContext;
60
159
  const activeTheme = ctx ? await readTheme(ctx) : null;
160
+ const userThemes = ctx ? await readUserThemes(ctx) : [];
61
161
  return {
62
162
  status: "ok",
63
163
  message: "Theme Customizer ready",
64
164
  details: {
65
165
  activePreset: activeTheme?.name ?? "Default (unset)",
66
- presetsAvailable: THEME_PRESETS.length,
166
+ bundledPresets: THEME_PRESETS.length,
167
+ remotePresets: remoteThemes.length,
168
+ userImported: userThemes.length,
67
169
  },
68
170
  };
69
171
  },
@@ -1 +1 @@
1
- {"version":3,"file":"worker.js","sourceRoot":"","sources":["../src/worker.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"worker.js","sourceRoot":"","sources":["../src/worker.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "paperclip-theme",
3
- "version": "0.1.1",
3
+ "version": "0.2.0",
4
4
  "description": "In-app theme customizer for Paperclip with live preview, presets, and shareable configs",
5
5
  "type": "module",
6
6
  "exports": {
package/src/constants.ts CHANGED
@@ -11,8 +11,12 @@ export const EXPORT_NAMES = {
11
11
 
12
12
  export const STATE_KEYS = {
13
13
  activeTheme: "active-theme",
14
+ userThemes: "user-themes",
14
15
  } as const;
15
16
 
17
+ export const REMOTE_REGISTRY_URL =
18
+ "https://raw.githubusercontent.com/Khaleeq2/paperclip-plugins/master/registry/themes.json";
19
+
16
20
  export const DATA_ENDPOINTS = {
17
21
  activeTheme: "active-theme",
18
22
  presets: "presets",
@@ -21,6 +25,8 @@ export const DATA_ENDPOINTS = {
21
25
  export const ACTION_NAMES = {
22
26
  applyTheme: "apply-theme",
23
27
  resetTheme: "reset-theme",
28
+ importTheme: "import-theme",
29
+ removeUserTheme: "remove-user-theme",
24
30
  } as const;
25
31
 
26
32
  /**
package/src/ui/index.tsx CHANGED
@@ -690,13 +690,16 @@ export function ThemeSettingsPage() {
690
690
  const presetsResult = usePluginData<ThemeConfig[]>("presets");
691
691
  const applyTheme = usePluginAction("apply-theme");
692
692
  const resetTheme = usePluginAction("reset-theme");
693
+ const importThemeAction = usePluginAction("import-theme");
693
694
 
694
695
  const [localTheme, setLocalTheme] = useState<ThemeConfig | null>(null);
695
696
  const [saving, setSaving] = useState(false);
696
697
  const [savedAt, setSavedAt] = useState<string | null>(null);
697
698
  const [hasUnsaved, setHasUnsaved] = useState(false);
698
699
  const [showModal, setShowModal] = useState(false);
700
+ const [importError, setImportError] = useState<string | null>(null);
699
701
  const initialLoadDone = useRef(false);
702
+ const fileInputRef = useRef<HTMLInputElement>(null);
700
703
 
701
704
  const presets: ThemeConfig[] = presetsResult.data ?? [];
702
705
  const serverTheme: ThemeConfig | null = activeThemeResult.data ?? null;
@@ -785,6 +788,54 @@ export function ThemeSettingsPage() {
785
788
  }
786
789
  }, [resetTheme]);
787
790
 
791
+ const handleExport = useCallback(() => {
792
+ if (!localTheme) return;
793
+ const payload = JSON.stringify(localTheme, null, 2);
794
+ const blob = new Blob([payload], { type: "application/json" });
795
+ const url = URL.createObjectURL(blob);
796
+ const a = document.createElement("a");
797
+ a.href = url;
798
+ a.download = `${localTheme.id}.theme.json`;
799
+ document.body.appendChild(a);
800
+ a.click();
801
+ document.body.removeChild(a);
802
+ URL.revokeObjectURL(url);
803
+ }, [localTheme]);
804
+
805
+ const handleImportFile = useCallback(
806
+ async (e: React.ChangeEvent<HTMLInputElement>) => {
807
+ setImportError(null);
808
+ const file = e.target.files?.[0];
809
+ if (!file) return;
810
+ try {
811
+ const text = await file.text();
812
+ const parsed: unknown = JSON.parse(text);
813
+ if (
814
+ typeof parsed !== "object" ||
815
+ parsed === null ||
816
+ typeof (parsed as Record<string, unknown>).id !== "string" ||
817
+ typeof (parsed as Record<string, unknown>).name !== "string" ||
818
+ typeof (parsed as Record<string, unknown>).tokens !== "object" ||
819
+ typeof (parsed as Record<string, unknown>).isDark !== "boolean"
820
+ ) {
821
+ setImportError("Invalid theme file: must contain id, name, tokens, and isDark fields.");
822
+ return;
823
+ }
824
+ const result = await importThemeAction(parsed);
825
+ const imported = result as unknown as ThemeConfig;
826
+ setLocalTheme(imported);
827
+ injectThemeCSS(imported);
828
+ setHasUnsaved(true);
829
+ setSavedAt(null);
830
+ } catch (err) {
831
+ setImportError(`Import failed: ${String(err)}`);
832
+ } finally {
833
+ if (fileInputRef.current) fileInputRef.current.value = "";
834
+ }
835
+ },
836
+ [importThemeAction],
837
+ );
838
+
788
839
  const radiusNum = parseFloat(localTheme?.radius ?? "0") || 0;
789
840
 
790
841
  return (
@@ -909,6 +960,47 @@ export function ThemeSettingsPage() {
909
960
  <span style={{ ...styles.saved, color: "var(--chart-1)" }}>Unsaved changes</span>
910
961
  )}
911
962
  </div>
963
+
964
+ {/* Import / Export */}
965
+ <div style={styles.section}>
966
+ <p style={styles.sectionLabel}>Share</p>
967
+ <p style={{ ...styles.subtitle, marginTop: -8 }}>
968
+ Export your current theme as a JSON file to share with others, or import a community theme.
969
+ </p>
970
+ <div style={styles.actions}>
971
+ <button
972
+ type="button"
973
+ style={{
974
+ ...styles.btnSecondary,
975
+ opacity: localTheme ? 1 : 0.5,
976
+ pointerEvents: localTheme ? "auto" : "none",
977
+ }}
978
+ onClick={handleExport}
979
+ disabled={!localTheme}
980
+ >
981
+ Export Theme
982
+ </button>
983
+ <button
984
+ type="button"
985
+ style={styles.btnSecondary}
986
+ onClick={() => fileInputRef.current?.click()}
987
+ >
988
+ Import Theme
989
+ </button>
990
+ <input
991
+ ref={fileInputRef}
992
+ type="file"
993
+ accept=".json,application/json"
994
+ style={{ display: "none" }}
995
+ onChange={handleImportFile}
996
+ />
997
+ </div>
998
+ {importError && (
999
+ <p style={{ fontSize: 12, color: "var(--destructive)", margin: 0 }}>
1000
+ {importError}
1001
+ </p>
1002
+ )}
1003
+ </div>
912
1004
  </div>
913
1005
  );
914
1006
  }
package/src/worker.ts CHANGED
@@ -11,11 +11,17 @@ import {
11
11
  DATA_ENDPOINTS,
12
12
  ACTION_NAMES,
13
13
  THEME_PRESETS,
14
+ REMOTE_REGISTRY_URL,
14
15
  type ThemeConfig,
15
16
  } from "./constants.js";
16
17
 
17
18
  let currentContext: PluginContext | null = null;
18
19
 
20
+ /** In-memory cache of remote themes, refreshed on startup. */
21
+ let remoteThemes: ThemeConfig[] = [];
22
+
23
+ /* ─── State helpers ──────────────────────────────────────────────── */
24
+
19
25
  async function readTheme(ctx: PluginContext): Promise<ThemeConfig | null> {
20
26
  return (await ctx.state.get({
21
27
  scopeKind: "instance",
@@ -33,16 +39,104 @@ async function writeTheme(
33
39
  );
34
40
  }
35
41
 
42
+ async function readUserThemes(ctx: PluginContext): Promise<ThemeConfig[]> {
43
+ const stored = await ctx.state.get({
44
+ scopeKind: "instance",
45
+ stateKey: STATE_KEYS.userThemes,
46
+ });
47
+ if (!Array.isArray(stored)) return [];
48
+ return stored as ThemeConfig[];
49
+ }
50
+
51
+ async function writeUserThemes(
52
+ ctx: PluginContext,
53
+ themes: ThemeConfig[],
54
+ ): Promise<void> {
55
+ await ctx.state.set(
56
+ { scopeKind: "instance", stateKey: STATE_KEYS.userThemes },
57
+ themes,
58
+ );
59
+ }
60
+
61
+ /* ─── Remote registry fetch ──────────────────────────────────────── */
62
+
63
+ interface RegistryPayload {
64
+ version: number;
65
+ updatedAt: string;
66
+ themes: ThemeConfig[];
67
+ }
68
+
69
+ function isValidTheme(t: unknown): t is ThemeConfig {
70
+ if (typeof t !== "object" || t === null) return false;
71
+ const obj = t as Record<string, unknown>;
72
+ return (
73
+ typeof obj.id === "string" &&
74
+ typeof obj.name === "string" &&
75
+ typeof obj.tokens === "object" &&
76
+ obj.tokens !== null &&
77
+ typeof obj.isDark === "boolean"
78
+ );
79
+ }
80
+
81
+ async function fetchRemoteThemes(logger: PluginContext["logger"]): Promise<ThemeConfig[]> {
82
+ try {
83
+ const response = await fetch(REMOTE_REGISTRY_URL);
84
+ if (!response.ok) {
85
+ logger.warn(`Remote theme registry returned ${response.status}, using bundled fallback`);
86
+ return [];
87
+ }
88
+ const payload: unknown = await response.json();
89
+ if (
90
+ typeof payload !== "object" ||
91
+ payload === null ||
92
+ !Array.isArray((payload as RegistryPayload).themes)
93
+ ) {
94
+ logger.warn("Remote theme registry has invalid shape, using bundled fallback");
95
+ return [];
96
+ }
97
+ const themes = (payload as RegistryPayload).themes.filter(isValidTheme);
98
+ logger.info(`Fetched ${themes.length} themes from remote registry`);
99
+ return themes;
100
+ } catch (err) {
101
+ logger.warn(`Failed to fetch remote theme registry: ${String(err)}`);
102
+ return [];
103
+ }
104
+ }
105
+
106
+ /* ─── Merge logic: remote wins over bundled, user themes appended ── */
107
+
108
+ function mergePresets(
109
+ bundled: ThemeConfig[],
110
+ remote: ThemeConfig[],
111
+ user: ThemeConfig[],
112
+ ): ThemeConfig[] {
113
+ const merged = new Map<string, ThemeConfig>();
114
+ for (const t of bundled) merged.set(t.id, t);
115
+ for (const t of remote) merged.set(t.id, t);
116
+ const result = Array.from(merged.values());
117
+ for (const t of user) {
118
+ if (!merged.has(t.id)) {
119
+ result.push(t);
120
+ }
121
+ }
122
+ return result;
123
+ }
124
+
125
+ /* ─── Plugin definition ──────────────────────────────────────────── */
126
+
36
127
  const plugin: PaperclipPlugin = definePlugin({
37
128
  async setup(ctx) {
38
129
  currentContext = ctx;
39
130
 
131
+ remoteThemes = await fetchRemoteThemes(ctx.logger);
132
+
40
133
  ctx.data.register(DATA_ENDPOINTS.activeTheme, async () => {
41
134
  return await readTheme(ctx);
42
135
  });
43
136
 
44
137
  ctx.data.register(DATA_ENDPOINTS.presets, async () => {
45
- return THEME_PRESETS;
138
+ const userThemes = await readUserThemes(ctx);
139
+ return mergePresets(THEME_PRESETS, remoteThemes, userThemes);
46
140
  });
47
141
 
48
142
  ctx.actions.register(ACTION_NAMES.applyTheme, async (params) => {
@@ -52,7 +146,12 @@ const plugin: PaperclipPlugin = definePlugin({
52
146
  throw new Error("Theme id is required");
53
147
  }
54
148
 
55
- const preset = THEME_PRESETS.find((p) => p.id === incoming.id);
149
+ const allPresets = mergePresets(
150
+ THEME_PRESETS,
151
+ remoteThemes,
152
+ await readUserThemes(ctx),
153
+ );
154
+ const preset = allPresets.find((p) => p.id === incoming.id);
56
155
 
57
156
  const theme: ThemeConfig = preset
58
157
  ? {
@@ -78,24 +177,66 @@ const plugin: PaperclipPlugin = definePlugin({
78
177
  });
79
178
 
80
179
  ctx.actions.register(ACTION_NAMES.resetTheme, async () => {
81
- const defaultTheme = THEME_PRESETS[0];
180
+ const allPresets = mergePresets(
181
+ THEME_PRESETS,
182
+ remoteThemes,
183
+ await readUserThemes(ctx),
184
+ );
185
+ const defaultTheme = allPresets[0];
82
186
  if (!defaultTheme) {
83
187
  throw new Error("No default preset found");
84
188
  }
85
189
  await writeTheme(ctx, defaultTheme);
86
190
  return defaultTheme;
87
191
  });
192
+
193
+ ctx.actions.register(ACTION_NAMES.importTheme, async (params) => {
194
+ const incoming = params as unknown;
195
+ if (!isValidTheme(incoming)) {
196
+ throw new Error(
197
+ "Invalid theme: must include id (string), name (string), tokens (object), isDark (boolean)",
198
+ );
199
+ }
200
+ const theme: ThemeConfig = {
201
+ id: incoming.id,
202
+ name: incoming.name,
203
+ description: incoming.description ?? "",
204
+ author: incoming.author ?? "Community",
205
+ isDark: incoming.isDark,
206
+ tokens: incoming.tokens,
207
+ radius: incoming.radius ?? "0",
208
+ createdAt: incoming.createdAt ?? new Date().toISOString(),
209
+ updatedAt: new Date().toISOString(),
210
+ };
211
+ const existing = await readUserThemes(ctx);
212
+ const filtered = existing.filter((t) => t.id !== theme.id);
213
+ filtered.push(theme);
214
+ await writeUserThemes(ctx, filtered);
215
+ return theme;
216
+ });
217
+
218
+ ctx.actions.register(ACTION_NAMES.removeUserTheme, async (params) => {
219
+ const { id } = params as { id?: string };
220
+ if (!id) throw new Error("Theme id is required");
221
+ const existing = await readUserThemes(ctx);
222
+ const filtered = existing.filter((t) => t.id !== id);
223
+ await writeUserThemes(ctx, filtered);
224
+ return { removed: id };
225
+ });
88
226
  },
89
227
 
90
228
  async onHealth(): Promise<PluginHealthDiagnostics> {
91
229
  const ctx = currentContext;
92
230
  const activeTheme = ctx ? await readTheme(ctx) : null;
231
+ const userThemes = ctx ? await readUserThemes(ctx) : [];
93
232
  return {
94
233
  status: "ok",
95
234
  message: "Theme Customizer ready",
96
235
  details: {
97
236
  activePreset: activeTheme?.name ?? "Default (unset)",
98
- presetsAvailable: THEME_PRESETS.length,
237
+ bundledPresets: THEME_PRESETS.length,
238
+ remotePresets: remoteThemes.length,
239
+ userImported: userThemes.length,
99
240
  },
100
241
  };
101
242
  },