@kilivi/payloadcms-theme-management 0.5.7 → 0.5.8

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.
@@ -7,6 +7,9 @@ import React from 'react';
7
7
  * - User preference from localStorage
8
8
  * - Admin-controlled color mode toggle
9
9
  * - Auto mode with system preference fallback
10
+ *
11
+ * Note: Uses Next.js Script component with beforeInteractive strategy
12
+ * to ensure theme is applied before React hydration, preventing flash of unstyled content.
10
13
  */
11
14
  export declare const InitTheme: React.FC;
12
15
  //# sourceMappingURL=InitTheme.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"InitTheme.d.ts","sourceRoot":"","sources":["../../src/components/InitTheme.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,MAAM,OAAO,CAAA;AAGzB;;;;;;;;GAQG;AACH,eAAO,MAAM,SAAS,EAAE,KAAK,CAAC,EA2D7B,CAAA"}
1
+ {"version":3,"file":"InitTheme.d.ts","sourceRoot":"","sources":["../../src/components/InitTheme.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AAIzB;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,SAAS,EAAE,KAAK,CAAC,EAyD7B,CAAA"}
@@ -1,6 +1,6 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
- import Script from 'next/script';
3
2
  import React from 'react';
3
+ import Script from 'next/script';
4
4
  import { modeLocalStorageKey } from '../providers/Theme/shared.js';
5
5
  /**
6
6
  * Client-side theme initialization script
@@ -10,10 +10,11 @@ import { modeLocalStorageKey } from '../providers/Theme/shared.js';
10
10
  * - User preference from localStorage
11
11
  * - Admin-controlled color mode toggle
12
12
  * - Auto mode with system preference fallback
13
+ *
14
+ * Note: Uses Next.js Script component with beforeInteractive strategy
15
+ * to ensure theme is applied before React hydration, preventing flash of unstyled content.
13
16
  */ export const InitTheme = ()=>{
14
- return /*#__PURE__*/ _jsx(Script, {
15
- dangerouslySetInnerHTML: {
16
- __html: `
17
+ const scriptContent = `
17
18
  (function () {
18
19
  function getImplicitModePreference() {
19
20
  var mediaQuery = '(prefers-color-scheme: dark)'
@@ -62,10 +63,11 @@ import { modeLocalStorageKey } from '../providers/Theme/shared.js';
62
63
  })
63
64
  }
64
65
  })();
65
- `
66
- },
66
+ `;
67
+ return /*#__PURE__*/ _jsx(Script, {
67
68
  id: "theme-script",
68
- strategy: "beforeInteractive"
69
+ strategy: "beforeInteractive",
70
+ children: scriptContent
69
71
  });
70
72
  };
71
73
 
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/components/InitTheme.tsx"],"sourcesContent":["import Script from 'next/script'\nimport React from 'react'\nimport { modeLocalStorageKey } from '../providers/Theme/shared.js'\n\n/**\n * Client-side theme initialization script\n * Prevents FOUC by applying theme mode before React hydration\n * Handles:\n * - System preference detection\n * - User preference from localStorage\n * - Admin-controlled color mode toggle\n * - Auto mode with system preference fallback\n */\nexport const InitTheme: React.FC = () => {\n return (\n <Script\n dangerouslySetInnerHTML={{\n __html: `\n (function () {\n function getImplicitModePreference() {\n var mediaQuery = '(prefers-color-scheme: dark)'\n var mql = window.matchMedia(mediaQuery)\n return mql.matches ? 'dark' : 'light'\n }\n\n function modeIsValid(mode) {\n return mode === 'light' || mode === 'dark'\n }\n\n // Get current mode from server-set attribute\n var currentMode = document.documentElement.getAttribute('data-theme-mode')\n var allowToggle = document.documentElement.getAttribute('data-allow-color-mode-toggle') === 'true'\n \n // Only override mode if admin allows toggle and user has preference\n if (allowToggle) {\n var modePreference = window.localStorage.getItem('${modeLocalStorageKey}')\n \n if (modeIsValid(modePreference)) {\n currentMode = modePreference\n } else if (currentMode === 'auto') {\n currentMode = getImplicitModePreference()\n }\n } else if (currentMode === 'auto') {\n // Admin set auto mode - use system preference\n currentMode = getImplicitModePreference()\n }\n\n // Apply the determined mode\n if (currentMode && modeIsValid(currentMode)) {\n document.documentElement.setAttribute('data-theme-mode', currentMode)\n }\n\n // Listen for system theme changes only when needed\n if (allowToggle || currentMode === 'auto') {\n var mediaQuery = window.matchMedia('(prefers-color-scheme: dark)')\n mediaQuery.addEventListener('change', function(e) {\n var shouldUpdate = allowToggle \n ? !window.localStorage.getItem('${modeLocalStorageKey}')\n : document.documentElement.getAttribute('data-theme-mode') === 'auto'\n \n if (shouldUpdate) {\n document.documentElement.setAttribute('data-theme-mode', e.matches ? 'dark' : 'light')\n }\n })\n }\n })();\n `,\n }}\n id=\"theme-script\"\n strategy=\"beforeInteractive\"\n />\n )\n}\n"],"names":["Script","React","modeLocalStorageKey","InitTheme","dangerouslySetInnerHTML","__html","id","strategy"],"mappings":";AAAA,OAAOA,YAAY,cAAa;AAChC,OAAOC,WAAW,QAAO;AACzB,SAASC,mBAAmB,QAAQ,+BAA8B;AAElE;;;;;;;;CAQC,GACD,OAAO,MAAMC,YAAsB;IACjC,qBACE,KAACH;QACCI,yBAAyB;YACvBC,QAAQ,CAAC;;;;;;;;;;;;;;;;;;wDAkBuC,EAAEH,oBAAoB;;;;;;;;;;;;;;;;;;;;;;0CAsBpC,EAAEA,oBAAoB;;;;;;;;;EAS9D,CAAC;QACG;QACAI,IAAG;QACHC,UAAS;;AAGf,EAAC"}
1
+ {"version":3,"sources":["../../src/components/InitTheme.tsx"],"sourcesContent":["import React from 'react'\nimport Script from 'next/script'\nimport { modeLocalStorageKey } from '../providers/Theme/shared.js'\n\n/**\n * Client-side theme initialization script\n * Prevents FOUC by applying theme mode before React hydration\n * Handles:\n * - System preference detection\n * - User preference from localStorage\n * - Admin-controlled color mode toggle\n * - Auto mode with system preference fallback\n *\n * Note: Uses Next.js Script component with beforeInteractive strategy\n * to ensure theme is applied before React hydration, preventing flash of unstyled content.\n */\nexport const InitTheme: React.FC = () => {\n const scriptContent = `\n (function () {\n function getImplicitModePreference() {\n var mediaQuery = '(prefers-color-scheme: dark)'\n var mql = window.matchMedia(mediaQuery)\n return mql.matches ? 'dark' : 'light'\n }\n\n function modeIsValid(mode) {\n return mode === 'light' || mode === 'dark'\n }\n\n // Get current mode from server-set attribute\n var currentMode = document.documentElement.getAttribute('data-theme-mode')\n var allowToggle = document.documentElement.getAttribute('data-allow-color-mode-toggle') === 'true'\n \n // Only override mode if admin allows toggle and user has preference\n if (allowToggle) {\n var modePreference = window.localStorage.getItem('${modeLocalStorageKey}')\n \n if (modeIsValid(modePreference)) {\n currentMode = modePreference\n } else if (currentMode === 'auto') {\n currentMode = getImplicitModePreference()\n }\n } else if (currentMode === 'auto') {\n // Admin set auto mode - use system preference\n currentMode = getImplicitModePreference()\n }\n\n // Apply the determined mode\n if (currentMode && modeIsValid(currentMode)) {\n document.documentElement.setAttribute('data-theme-mode', currentMode)\n }\n\n // Listen for system theme changes only when needed\n if (allowToggle || currentMode === 'auto') {\n var mediaQuery = window.matchMedia('(prefers-color-scheme: dark)')\n mediaQuery.addEventListener('change', function(e) {\n var shouldUpdate = allowToggle \n ? !window.localStorage.getItem('${modeLocalStorageKey}')\n : document.documentElement.getAttribute('data-theme-mode') === 'auto'\n \n if (shouldUpdate) {\n document.documentElement.setAttribute('data-theme-mode', e.matches ? 'dark' : 'light')\n }\n })\n }\n })();\n `\n\n return (\n <Script id=\"theme-script\" strategy=\"beforeInteractive\">\n {scriptContent}\n </Script>\n )\n}\n"],"names":["React","Script","modeLocalStorageKey","InitTheme","scriptContent","id","strategy"],"mappings":";AAAA,OAAOA,WAAW,QAAO;AACzB,OAAOC,YAAY,cAAa;AAChC,SAASC,mBAAmB,QAAQ,+BAA8B;AAElE;;;;;;;;;;;CAWC,GACD,OAAO,MAAMC,YAAsB;IACjC,MAAMC,gBAAgB,CAAC;;;;;;;;;;;;;;;;;;wDAkB+B,EAAEF,oBAAoB;;;;;;;;;;;;;;;;;;;;;;0CAsBpC,EAAEA,oBAAoB;;;;;;;;;EAS9D,CAAC;IAED,qBACE,KAACD;QAAOI,IAAG;QAAeC,UAAS;kBAChCF;;AAGP,EAAC"}
@@ -0,0 +1,4 @@
1
+ import type { JSONFieldClientProps } from 'payload';
2
+ declare const ThemePresetImportField: ({ field, path }: JSONFieldClientProps) => import("react").JSX.Element;
3
+ export default ThemePresetImportField;
4
+ //# sourceMappingURL=ThemePresetImportField.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ThemePresetImportField.d.ts","sourceRoot":"","sources":["../../src/fields/ThemePresetImportField.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,SAAS,CAAA;AASnD,QAAA,MAAM,sBAAsB,GAAI,iBAAiB,oBAAoB,gCAyJpE,CAAA;AAED,eAAe,sBAAsB,CAAA"}
@@ -0,0 +1,219 @@
1
+ 'use client';
2
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
+ import { Button, Drawer, useField, useModal } from '@payloadcms/ui';
4
+ import { toast } from 'sonner';
5
+ import { useCallback, useMemo, useRef, useState } from 'react';
6
+ import { parseThemePresetInput } from '../utils/customThemePresets.js';
7
+ const baseClass = 'theme-preset-import-field';
8
+ const drawerSlug = 'import-theme-presets';
9
+ const ThemePresetImportField = ({ field, path })=>{
10
+ const { value, setValue } = useField({
11
+ path
12
+ });
13
+ const [textValue, setTextValue] = useState('');
14
+ const { closeModal, openModal } = useModal();
15
+ const fileInputRef = useRef(null);
16
+ const presetSummary = useMemo(()=>{
17
+ if (!value || value.length === 0) {
18
+ return 'No custom presets imported';
19
+ }
20
+ const names = value.map((preset)=>preset.name).join(', ');
21
+ return `${value.length} preset${value.length === 1 ? '' : 's'}: ${names}`;
22
+ }, [
23
+ value
24
+ ]);
25
+ const applyFromText = useCallback((raw)=>{
26
+ if (!raw.trim()) {
27
+ setValue(null);
28
+ closeModal(drawerSlug);
29
+ toast.success('Cleared custom presets');
30
+ return;
31
+ }
32
+ const presets = parseThemePresetInput(raw);
33
+ if (presets.length === 0) {
34
+ toast.error('No valid presets found. Ensure each entry has a name and label.');
35
+ return;
36
+ }
37
+ setValue(presets);
38
+ closeModal(drawerSlug);
39
+ toast.success(`Imported ${presets.length} preset${presets.length === 1 ? '' : 's'}`);
40
+ setTextValue('');
41
+ }, [
42
+ setValue,
43
+ closeModal
44
+ ]);
45
+ const handleApplyClick = useCallback(()=>{
46
+ applyFromText(textValue);
47
+ }, [
48
+ applyFromText,
49
+ textValue
50
+ ]);
51
+ const handleFileChange = useCallback(async (event)=>{
52
+ const file = event.target?.files?.[0];
53
+ if (!file) return;
54
+ try {
55
+ const content = await file.text();
56
+ setTextValue(content);
57
+ applyFromText(content);
58
+ } catch (error) {
59
+ toast.error(error.message);
60
+ } finally{
61
+ if (event.target) {
62
+ event.target.value = '';
63
+ }
64
+ }
65
+ }, [
66
+ applyFromText
67
+ ]);
68
+ const handleImportClick = useCallback(()=>{
69
+ fileInputRef.current?.click();
70
+ }, []);
71
+ const handleClear = useCallback(()=>{
72
+ setValue(null);
73
+ toast.success('Cleared custom presets');
74
+ }, [
75
+ setValue
76
+ ]);
77
+ const label = typeof field.label === 'string' ? field.label : field.label?.en ?? 'Custom Presets';
78
+ const description = typeof field.admin?.description === 'string' ? field.admin.description : field.admin?.description?.en;
79
+ return /*#__PURE__*/ _jsxs(_Fragment, {
80
+ children: [
81
+ /*#__PURE__*/ _jsxs("div", {
82
+ className: baseClass,
83
+ style: {
84
+ display: 'grid',
85
+ gap: '0.75rem'
86
+ },
87
+ children: [
88
+ /*#__PURE__*/ _jsxs("div", {
89
+ style: {
90
+ display: 'flex',
91
+ flexDirection: 'column',
92
+ gap: '0.25rem'
93
+ },
94
+ children: [
95
+ /*#__PURE__*/ _jsx("label", {
96
+ style: {
97
+ fontWeight: 600
98
+ },
99
+ children: label
100
+ }),
101
+ description && /*#__PURE__*/ _jsx("p", {
102
+ style: {
103
+ margin: 0,
104
+ color: 'var(--theme-elevation-500)',
105
+ fontSize: '0.9rem'
106
+ },
107
+ children: description
108
+ })
109
+ ]
110
+ }),
111
+ /*#__PURE__*/ _jsxs("div", {
112
+ style: {
113
+ display: 'flex',
114
+ alignItems: 'center',
115
+ gap: '0.5rem',
116
+ flexWrap: 'wrap'
117
+ },
118
+ children: [
119
+ /*#__PURE__*/ _jsx(Button, {
120
+ buttonStyle: "secondary",
121
+ onClick: ()=>openModal(drawerSlug),
122
+ size: "small",
123
+ children: "Import Presets"
124
+ }),
125
+ value && value.length > 0 && /*#__PURE__*/ _jsx(Button, {
126
+ buttonStyle: "secondary",
127
+ onClick: handleClear,
128
+ size: "small",
129
+ children: "Clear"
130
+ }),
131
+ /*#__PURE__*/ _jsx("span", {
132
+ style: {
133
+ fontSize: '0.875rem',
134
+ color: 'var(--theme-elevation-600)'
135
+ },
136
+ children: presetSummary
137
+ })
138
+ ]
139
+ })
140
+ ]
141
+ }),
142
+ /*#__PURE__*/ _jsx(Drawer, {
143
+ slug: drawerSlug,
144
+ title: "Import Theme Presets",
145
+ children: /*#__PURE__*/ _jsxs("div", {
146
+ style: {
147
+ padding: '1.5rem',
148
+ display: 'grid',
149
+ gap: '1rem'
150
+ },
151
+ children: [
152
+ /*#__PURE__*/ _jsx("p", {
153
+ style: {
154
+ margin: 0,
155
+ color: 'var(--theme-elevation-600)'
156
+ },
157
+ children: "Paste JSON or upload a .json file containing theme preset definitions."
158
+ }),
159
+ /*#__PURE__*/ _jsx("textarea", {
160
+ value: textValue,
161
+ onChange: (event)=>setTextValue(event.target.value),
162
+ rows: 15,
163
+ spellCheck: false,
164
+ style: {
165
+ width: '100%',
166
+ fontFamily: 'monospace',
167
+ borderRadius: '8px',
168
+ border: '1px solid var(--theme-elevation-200)',
169
+ padding: '12px',
170
+ fontSize: '0.875rem'
171
+ },
172
+ placeholder: `[
173
+ {
174
+ "name": "brand-dark",
175
+ "label": "Brand Dark",
176
+ "borderRadius": "medium",
177
+ "lightMode": { "background": "#ffffff", "foreground": "#111" },
178
+ "darkMode": { "background": "#0a0a0a", "foreground": "#fff" }
179
+ }
180
+ ]`
181
+ }),
182
+ /*#__PURE__*/ _jsxs("div", {
183
+ style: {
184
+ display: 'flex',
185
+ gap: '0.5rem',
186
+ justifyContent: 'flex-end'
187
+ },
188
+ children: [
189
+ /*#__PURE__*/ _jsx(Button, {
190
+ buttonStyle: "secondary",
191
+ onClick: handleImportClick,
192
+ children: "Upload JSON File"
193
+ }),
194
+ /*#__PURE__*/ _jsx(Button, {
195
+ buttonStyle: "primary",
196
+ onClick: handleApplyClick,
197
+ disabled: !textValue.trim(),
198
+ children: "Apply"
199
+ })
200
+ ]
201
+ }),
202
+ /*#__PURE__*/ _jsx("input", {
203
+ type: "file",
204
+ accept: "application/json",
205
+ ref: fileInputRef,
206
+ onChange: handleFileChange,
207
+ style: {
208
+ display: 'none'
209
+ }
210
+ })
211
+ ]
212
+ })
213
+ })
214
+ ]
215
+ });
216
+ };
217
+ export default ThemePresetImportField;
218
+
219
+ //# sourceMappingURL=ThemePresetImportField.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/fields/ThemePresetImportField.tsx"],"sourcesContent":["'use client'\n\nimport { Button, Drawer, useField, useModal } from '@payloadcms/ui'\nimport type { JSONFieldClientProps } from 'payload'\nimport { toast } from 'sonner'\nimport { useCallback, useMemo, useRef, useState, type ChangeEvent } from 'react'\nimport type { ThemePreset } from '../presets.js'\nimport { parseThemePresetInput } from '../utils/customThemePresets.js'\n\nconst baseClass = 'theme-preset-import-field'\nconst drawerSlug = 'import-theme-presets'\n\nconst ThemePresetImportField = ({ field, path }: JSONFieldClientProps) => {\n const { value, setValue } = useField<ThemePreset[] | null>({ path })\n const [textValue, setTextValue] = useState('')\n const { closeModal, openModal } = useModal()\n const fileInputRef = useRef<HTMLInputElement | null>(null)\n\n const presetSummary = useMemo(() => {\n if (!value || value.length === 0) {\n return 'No custom presets imported'\n }\n const names = value.map((preset) => preset.name).join(', ')\n return `${value.length} preset${value.length === 1 ? '' : 's'}: ${names}`\n }, [value])\n\n const applyFromText = useCallback(\n (raw: string) => {\n if (!raw.trim()) {\n setValue(null)\n closeModal(drawerSlug)\n toast.success('Cleared custom presets')\n return\n }\n\n const presets = parseThemePresetInput(raw)\n if (presets.length === 0) {\n toast.error('No valid presets found. Ensure each entry has a name and label.')\n return\n }\n\n setValue(presets)\n closeModal(drawerSlug)\n toast.success(`Imported ${presets.length} preset${presets.length === 1 ? '' : 's'}`)\n setTextValue('')\n },\n [setValue, closeModal],\n )\n\n const handleApplyClick = useCallback(() => {\n applyFromText(textValue)\n }, [applyFromText, textValue])\n\n const handleFileChange = useCallback(\n async (event: ChangeEvent<HTMLInputElement>) => {\n const file = event.target?.files?.[0]\n if (!file) return\n try {\n const content = await file.text()\n setTextValue(content)\n applyFromText(content)\n } catch (error) {\n toast.error((error as Error).message)\n } finally {\n if (event.target) {\n event.target.value = ''\n }\n }\n },\n [applyFromText],\n )\n\n const handleImportClick = useCallback(() => {\n fileInputRef.current?.click()\n }, [])\n\n const handleClear = useCallback(() => {\n setValue(null)\n toast.success('Cleared custom presets')\n }, [setValue])\n\n const label =\n typeof field.label === 'string' ? field.label : (field.label?.en ?? 'Custom Presets')\n const description =\n typeof field.admin?.description === 'string'\n ? field.admin.description\n : (field.admin?.description as Record<string, string>)?.en\n\n return (\n <>\n <div className={baseClass} style={{ display: 'grid', gap: '0.75rem' }}>\n <div style={{ display: 'flex', flexDirection: 'column', gap: '0.25rem' }}>\n <label style={{ fontWeight: 600 }}>{label}</label>\n {description && (\n <p style={{ margin: 0, color: 'var(--theme-elevation-500)', fontSize: '0.9rem' }}>\n {description}\n </p>\n )}\n </div>\n\n <div style={{ display: 'flex', alignItems: 'center', gap: '0.5rem', flexWrap: 'wrap' }}>\n <Button buttonStyle=\"secondary\" onClick={() => openModal(drawerSlug)} size=\"small\">\n Import Presets\n </Button>\n {value && value.length > 0 && (\n <Button buttonStyle=\"secondary\" onClick={handleClear} size=\"small\">\n Clear\n </Button>\n )}\n <span style={{ fontSize: '0.875rem', color: 'var(--theme-elevation-600)' }}>\n {presetSummary}\n </span>\n </div>\n </div>\n\n <Drawer slug={drawerSlug} title=\"Import Theme Presets\">\n <div style={{ padding: '1.5rem', display: 'grid', gap: '1rem' }}>\n <p style={{ margin: 0, color: 'var(--theme-elevation-600)' }}>\n Paste JSON or upload a .json file containing theme preset definitions.\n </p>\n\n <textarea\n value={textValue}\n onChange={(event) => setTextValue(event.target.value)}\n rows={15}\n spellCheck={false}\n style={{\n width: '100%',\n fontFamily: 'monospace',\n borderRadius: '8px',\n border: '1px solid var(--theme-elevation-200)',\n padding: '12px',\n fontSize: '0.875rem',\n }}\n placeholder={`[\n {\n \"name\": \"brand-dark\",\n \"label\": \"Brand Dark\",\n \"borderRadius\": \"medium\",\n \"lightMode\": { \"background\": \"#ffffff\", \"foreground\": \"#111\" },\n \"darkMode\": { \"background\": \"#0a0a0a\", \"foreground\": \"#fff\" }\n }\n]`}\n />\n\n <div style={{ display: 'flex', gap: '0.5rem', justifyContent: 'flex-end' }}>\n <Button buttonStyle=\"secondary\" onClick={handleImportClick}>\n Upload JSON File\n </Button>\n <Button buttonStyle=\"primary\" onClick={handleApplyClick} disabled={!textValue.trim()}>\n Apply\n </Button>\n </div>\n\n <input\n type=\"file\"\n accept=\"application/json\"\n ref={fileInputRef}\n onChange={handleFileChange}\n style={{ display: 'none' }}\n />\n </div>\n </Drawer>\n </>\n )\n}\n\nexport default ThemePresetImportField\n"],"names":["Button","Drawer","useField","useModal","toast","useCallback","useMemo","useRef","useState","parseThemePresetInput","baseClass","drawerSlug","ThemePresetImportField","field","path","value","setValue","textValue","setTextValue","closeModal","openModal","fileInputRef","presetSummary","length","names","map","preset","name","join","applyFromText","raw","trim","success","presets","error","handleApplyClick","handleFileChange","event","file","target","files","content","text","message","handleImportClick","current","click","handleClear","label","en","description","admin","div","className","style","display","gap","flexDirection","fontWeight","p","margin","color","fontSize","alignItems","flexWrap","buttonStyle","onClick","size","span","slug","title","padding","textarea","onChange","rows","spellCheck","width","fontFamily","borderRadius","border","placeholder","justifyContent","disabled","input","type","accept","ref"],"mappings":"AAAA;;AAEA,SAASA,MAAM,EAAEC,MAAM,EAAEC,QAAQ,EAAEC,QAAQ,QAAQ,iBAAgB;AAEnE,SAASC,KAAK,QAAQ,SAAQ;AAC9B,SAASC,WAAW,EAAEC,OAAO,EAAEC,MAAM,EAAEC,QAAQ,QAA0B,QAAO;AAEhF,SAASC,qBAAqB,QAAQ,iCAAgC;AAEtE,MAAMC,YAAY;AAClB,MAAMC,aAAa;AAEnB,MAAMC,yBAAyB,CAAC,EAAEC,KAAK,EAAEC,IAAI,EAAwB;IACnE,MAAM,EAAEC,KAAK,EAAEC,QAAQ,EAAE,GAAGd,SAA+B;QAAEY;IAAK;IAClE,MAAM,CAACG,WAAWC,aAAa,GAAGV,SAAS;IAC3C,MAAM,EAAEW,UAAU,EAAEC,SAAS,EAAE,GAAGjB;IAClC,MAAMkB,eAAed,OAAgC;IAErD,MAAMe,gBAAgBhB,QAAQ;QAC5B,IAAI,CAACS,SAASA,MAAMQ,MAAM,KAAK,GAAG;YAChC,OAAO;QACT;QACA,MAAMC,QAAQT,MAAMU,GAAG,CAAC,CAACC,SAAWA,OAAOC,IAAI,EAAEC,IAAI,CAAC;QACtD,OAAO,GAAGb,MAAMQ,MAAM,CAAC,OAAO,EAAER,MAAMQ,MAAM,KAAK,IAAI,KAAK,IAAI,EAAE,EAAEC,OAAO;IAC3E,GAAG;QAACT;KAAM;IAEV,MAAMc,gBAAgBxB,YACpB,CAACyB;QACC,IAAI,CAACA,IAAIC,IAAI,IAAI;YACff,SAAS;YACTG,WAAWR;YACXP,MAAM4B,OAAO,CAAC;YACd;QACF;QAEA,MAAMC,UAAUxB,sBAAsBqB;QACtC,IAAIG,QAAQV,MAAM,KAAK,GAAG;YACxBnB,MAAM8B,KAAK,CAAC;YACZ;QACF;QAEAlB,SAASiB;QACTd,WAAWR;QACXP,MAAM4B,OAAO,CAAC,CAAC,SAAS,EAAEC,QAAQV,MAAM,CAAC,OAAO,EAAEU,QAAQV,MAAM,KAAK,IAAI,KAAK,KAAK;QACnFL,aAAa;IACf,GACA;QAACF;QAAUG;KAAW;IAGxB,MAAMgB,mBAAmB9B,YAAY;QACnCwB,cAAcZ;IAChB,GAAG;QAACY;QAAeZ;KAAU;IAE7B,MAAMmB,mBAAmB/B,YACvB,OAAOgC;QACL,MAAMC,OAAOD,MAAME,MAAM,EAAEC,OAAO,CAAC,EAAE;QACrC,IAAI,CAACF,MAAM;QACX,IAAI;YACF,MAAMG,UAAU,MAAMH,KAAKI,IAAI;YAC/BxB,aAAauB;YACbZ,cAAcY;QAChB,EAAE,OAAOP,OAAO;YACd9B,MAAM8B,KAAK,CAAC,AAACA,MAAgBS,OAAO;QACtC,SAAU;YACR,IAAIN,MAAME,MAAM,EAAE;gBAChBF,MAAME,MAAM,CAACxB,KAAK,GAAG;YACvB;QACF;IACF,GACA;QAACc;KAAc;IAGjB,MAAMe,oBAAoBvC,YAAY;QACpCgB,aAAawB,OAAO,EAAEC;IACxB,GAAG,EAAE;IAEL,MAAMC,cAAc1C,YAAY;QAC9BW,SAAS;QACTZ,MAAM4B,OAAO,CAAC;IAChB,GAAG;QAAChB;KAAS;IAEb,MAAMgC,QACJ,OAAOnC,MAAMmC,KAAK,KAAK,WAAWnC,MAAMmC,KAAK,GAAInC,MAAMmC,KAAK,EAAEC,MAAM;IACtE,MAAMC,cACJ,OAAOrC,MAAMsC,KAAK,EAAED,gBAAgB,WAChCrC,MAAMsC,KAAK,CAACD,WAAW,GACtBrC,MAAMsC,KAAK,EAAED,aAAwCD;IAE5D,qBACE;;0BACE,MAACG;gBAAIC,WAAW3C;gBAAW4C,OAAO;oBAAEC,SAAS;oBAAQC,KAAK;gBAAU;;kCAClE,MAACJ;wBAAIE,OAAO;4BAAEC,SAAS;4BAAQE,eAAe;4BAAUD,KAAK;wBAAU;;0CACrE,KAACR;gCAAMM,OAAO;oCAAEI,YAAY;gCAAI;0CAAIV;;4BACnCE,6BACC,KAACS;gCAAEL,OAAO;oCAAEM,QAAQ;oCAAGC,OAAO;oCAA8BC,UAAU;gCAAS;0CAC5EZ;;;;kCAKP,MAACE;wBAAIE,OAAO;4BAAEC,SAAS;4BAAQQ,YAAY;4BAAUP,KAAK;4BAAUQ,UAAU;wBAAO;;0CACnF,KAAChE;gCAAOiE,aAAY;gCAAYC,SAAS,IAAM9C,UAAUT;gCAAawD,MAAK;0CAAQ;;4BAGlFpD,SAASA,MAAMQ,MAAM,GAAG,mBACvB,KAACvB;gCAAOiE,aAAY;gCAAYC,SAASnB;gCAAaoB,MAAK;0CAAQ;;0CAIrE,KAACC;gCAAKd,OAAO;oCAAEQ,UAAU;oCAAYD,OAAO;gCAA6B;0CACtEvC;;;;;;0BAKP,KAACrB;gBAAOoE,MAAM1D;gBAAY2D,OAAM;0BAC9B,cAAA,MAAClB;oBAAIE,OAAO;wBAAEiB,SAAS;wBAAUhB,SAAS;wBAAQC,KAAK;oBAAO;;sCAC5D,KAACG;4BAAEL,OAAO;gCAAEM,QAAQ;gCAAGC,OAAO;4BAA6B;sCAAG;;sCAI9D,KAACW;4BACCzD,OAAOE;4BACPwD,UAAU,CAACpC,QAAUnB,aAAamB,MAAME,MAAM,CAACxB,KAAK;4BACpD2D,MAAM;4BACNC,YAAY;4BACZrB,OAAO;gCACLsB,OAAO;gCACPC,YAAY;gCACZC,cAAc;gCACdC,QAAQ;gCACRR,SAAS;gCACTT,UAAU;4BACZ;4BACAkB,aAAa,CAAC;;;;;;;;CAQzB,CAAC;;sCAGQ,MAAC5B;4BAAIE,OAAO;gCAAEC,SAAS;gCAAQC,KAAK;gCAAUyB,gBAAgB;4BAAW;;8CACvE,KAACjF;oCAAOiE,aAAY;oCAAYC,SAAStB;8CAAmB;;8CAG5D,KAAC5C;oCAAOiE,aAAY;oCAAUC,SAAS/B;oCAAkB+C,UAAU,CAACjE,UAAUc,IAAI;8CAAI;;;;sCAKxF,KAACoD;4BACCC,MAAK;4BACLC,QAAO;4BACPC,KAAKjE;4BACLoD,UAAUrC;4BACVkB,OAAO;gCAAEC,SAAS;4BAAO;;;;;;;AAMrC;AAEA,eAAe3C,uBAAsB"}
@@ -1 +1 @@
1
- {"version":3,"file":"ThemePreviewField.d.ts","sourceRoot":"","sources":["../../src/fields/ThemePreviewField.tsx"],"names":[],"mappings":"AAEA,OAAO,yBAAyB,CAAA;AAEhC,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,SAAS,CAAA;AAyQrD,MAAM,CAAC,OAAO,UAAU,iBAAiB,CAAC,KAAK,EAAE,sBAAsB,+BA8XtE"}
1
+ {"version":3,"file":"ThemePreviewField.d.ts","sourceRoot":"","sources":["../../src/fields/ThemePreviewField.tsx"],"names":[],"mappings":"AAEA,OAAO,yBAAyB,CAAA;AAEhC,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,SAAS,CAAA;AA2PrD,MAAM,CAAC,OAAO,UAAU,iBAAiB,CAAC,KAAK,EAAE,sBAAsB,+BAmZtE"}
@@ -7,23 +7,7 @@ import { resolveTypographyPreview } from '../components/typographyPreviewUtils.j
7
7
  import { allThemePresets } from '../index.js';
8
8
  import { borderRadiusPresets } from '../providers/Theme/themeConfig.js';
9
9
  import { darkModeDefaults, lightModeDefaults } from './colorModeFields.js';
10
- const FALLBACK_THEME = allThemePresets[0]?.name ?? 'cool';
11
- const themePresets = allThemePresets.reduce((acc, preset)=>{
12
- acc[preset.name] = {
13
- label: preset.label,
14
- lightMode: {
15
- ...lightModeDefaults,
16
- ...preset.lightMode ?? {}
17
- },
18
- darkMode: {
19
- ...darkModeDefaults,
20
- ...preset.darkMode ?? {}
21
- },
22
- typography: preset.typography,
23
- borderRadius: preset.borderRadius
24
- };
25
- return acc;
26
- }, {});
10
+ // FALLBACK_THEME and runtime theme presets are computed inside the component
27
11
  const colorKeys = Object.keys(lightModeDefaults);
28
12
  const highlightSwatches = [
29
13
  {
@@ -255,6 +239,29 @@ function ModePreview({ icon, title, colors, typography, radius }) {
255
239
  }
256
240
  export default function ThemePreviewField(props) {
257
241
  const { field, path } = props;
242
+ // If the plugin provided theme presets via admin config, prefer those; otherwise fallback to allThemePresets
243
+ const baseThemePresets = field?.admin?.themePresets ?? allThemePresets;
244
+ const runtimeThemePresets = useMemo(()=>{
245
+ return baseThemePresets.reduce((acc, preset)=>{
246
+ acc[preset.name] = {
247
+ label: preset.label,
248
+ lightMode: {
249
+ ...lightModeDefaults,
250
+ ...preset.lightMode ?? {}
251
+ },
252
+ darkMode: {
253
+ ...darkModeDefaults,
254
+ ...preset.darkMode ?? {}
255
+ },
256
+ typography: preset.typography,
257
+ borderRadius: preset.borderRadius
258
+ };
259
+ return acc;
260
+ }, {});
261
+ }, [
262
+ baseThemePresets
263
+ ]);
264
+ const fallbackTheme = baseThemePresets[0]?.name ?? 'cool';
258
265
  const { value: selectedTheme, setValue } = useField({
259
266
  path
260
267
  });
@@ -262,7 +269,7 @@ export default function ThemePreviewField(props) {
262
269
  const formFields = useFormFields(([formState])=>formState);
263
270
  const hasAppliedInitialPresetRef = useRef(false);
264
271
  const applyPreset = useCallback((presetName)=>{
265
- const preset = themePresets[presetName];
272
+ const preset = runtimeThemePresets[presetName];
266
273
  if (!preset) {
267
274
  return;
268
275
  }
@@ -302,11 +309,11 @@ export default function ThemePreviewField(props) {
302
309
  if (!selectedTheme) {
303
310
  return;
304
311
  }
305
- if (themePresets[selectedTheme]) {
312
+ if (runtimeThemePresets[selectedTheme]) {
306
313
  return;
307
314
  }
308
315
  hasAppliedInitialPresetRef.current = false;
309
- setValue(FALLBACK_THEME);
316
+ setValue(fallbackTheme);
310
317
  }, [
311
318
  selectedTheme,
312
319
  setValue
@@ -321,7 +328,7 @@ export default function ThemePreviewField(props) {
321
328
  if (!formFields) {
322
329
  return;
323
330
  }
324
- const preset = themePresets[selectedTheme];
331
+ const preset = runtimeThemePresets[selectedTheme];
325
332
  if (!preset) {
326
333
  hasAppliedInitialPresetRef.current = true;
327
334
  return;
@@ -345,7 +352,7 @@ export default function ThemePreviewField(props) {
345
352
  applyPreset
346
353
  ]);
347
354
  const lightModeColors = useMemo(()=>{
348
- const presetLightMode = selectedTheme ? themePresets[selectedTheme]?.lightMode : undefined;
355
+ const presetLightMode = selectedTheme ? runtimeThemePresets[selectedTheme]?.lightMode : undefined;
349
356
  return colorKeys.reduce((acc, key)=>{
350
357
  const fieldState = formFields?.[`themeConfiguration.lightMode.${key}`];
351
358
  const rawValue = typeof fieldState?.value === 'string' && fieldState.value.trim().length > 0 ? fieldState.value : undefined;
@@ -357,7 +364,7 @@ export default function ThemePreviewField(props) {
357
364
  selectedTheme
358
365
  ]);
359
366
  const darkModeColors = useMemo(()=>{
360
- const presetDarkMode = selectedTheme ? themePresets[selectedTheme]?.darkMode : undefined;
367
+ const presetDarkMode = selectedTheme ? runtimeThemePresets[selectedTheme]?.darkMode : undefined;
361
368
  return colorKeys.reduce((acc, key)=>{
362
369
  const fieldState = formFields?.[`themeConfiguration.darkMode.${key}`];
363
370
  const rawValue = typeof fieldState?.value === 'string' && fieldState.value.trim().length > 0 ? fieldState.value : undefined;
@@ -368,7 +375,7 @@ export default function ThemePreviewField(props) {
368
375
  formFields,
369
376
  selectedTheme
370
377
  ]);
371
- const activePreset = selectedTheme ? themePresets[selectedTheme] : undefined;
378
+ const activePreset = selectedTheme ? runtimeThemePresets[selectedTheme] : undefined;
372
379
  const formTypographySelection = useMemo(()=>{
373
380
  if (!formFields) {
374
381
  return null;
@@ -438,7 +445,7 @@ export default function ThemePreviewField(props) {
438
445
  children: [
439
446
  /*#__PURE__*/ _jsx("div", {
440
447
  className: "theme-preset-list",
441
- children: Object.entries(themePresets).map(([key, preset])=>{
448
+ children: Object.entries(runtimeThemePresets).map(([key, preset])=>{
442
449
  const isSelected = key === selectedTheme;
443
450
  const swatches = highlightSwatches.map(({ key: colorKey })=>preset.lightMode[colorKey]).filter((color)=>Boolean(color));
444
451
  return /*#__PURE__*/ _jsxs("button", {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/fields/ThemePreviewField.tsx"],"sourcesContent":["'use client'\n\nimport './ThemePreviewField.css'\nimport { useField, useForm, useFormFields } from '@payloadcms/ui'\nimport type { SelectFieldClientProps } from 'payload'\nimport { useCallback, useEffect, useMemo, useRef } from 'react'\nimport type {\n ResolvedTypographyPreview,\n TypographySelection,\n} from '../components/typographyPreviewUtils.js'\nimport { resolveTypographyPreview } from '../components/typographyPreviewUtils.js'\nimport { allThemePresets } from '../index.js'\nimport type { ThemeTypographyPreset } from '../presets.js'\nimport { borderRadiusPresets } from '../providers/Theme/themeConfig.js'\nimport { darkModeDefaults, lightModeDefaults } from './colorModeFields.js'\n\ninterface ColorModeColors {\n background?: string\n foreground?: string\n card?: string\n cardForeground?: string\n popover?: string\n popoverForeground?: string\n primary?: string\n primaryForeground?: string\n secondary?: string\n secondaryForeground?: string\n muted?: string\n mutedForeground?: string\n accent?: string\n accentForeground?: string\n destructive?: string\n destructiveForeground?: string\n border?: string\n input?: string\n ring?: string\n}\n\ninterface ThemePresetDefinition {\n label: string\n lightMode: ColorModeColors\n darkMode: ColorModeColors\n typography?: ThemeTypographyPreset\n borderRadius: 'none' | 'small' | 'medium' | 'large' | 'xl'\n}\n\nconst FALLBACK_THEME = allThemePresets[0]?.name ?? 'cool'\n\nconst themePresets = allThemePresets.reduce<Record<string, ThemePresetDefinition>>(\n (acc, preset) => {\n acc[preset.name] = {\n label: preset.label,\n lightMode: { ...lightModeDefaults, ...(preset.lightMode ?? {}) },\n darkMode: { ...darkModeDefaults, ...(preset.darkMode ?? {}) },\n typography: preset.typography,\n borderRadius: preset.borderRadius,\n }\n return acc\n },\n {},\n)\n\nconst colorKeys = Object.keys(lightModeDefaults) as (keyof ColorModeColors)[]\n\nconst highlightSwatches: Array<{ key: keyof ColorModeColors; label: string }> = [\n { key: 'primary', label: 'Primary' },\n { key: 'secondary', label: 'Secondary' },\n { key: 'accent', label: 'Accent' },\n { key: 'background', label: 'Background' },\n { key: 'foreground', label: 'Foreground' },\n]\n\ninterface ModePreviewProps {\n icon: string\n title: string\n colors: ColorModeColors\n typography: ResolvedTypographyPreview\n radius: {\n card: string\n chip: string\n pill: string\n }\n}\n\nfunction ModePreview({ icon, title, colors, typography, radius }: Readonly<ModePreviewProps>) {\n const background = colors.background ?? '#ffffff'\n const foreground = colors.foreground ?? '#0a0a0a'\n const borderColor = colors.border ?? 'rgba(148, 163, 184, 0.35)'\n const cardBackground = colors.card ?? background\n const cardForeground = colors.cardForeground ?? foreground\n const primary = colors.primary ?? foreground\n const primaryForeground = colors.primaryForeground ?? background\n const secondary = colors.secondary ?? '#f4f4f5'\n const secondaryForeground = colors.secondaryForeground ?? foreground\n const muted = colors.muted ?? secondary\n const mutedForeground = colors.mutedForeground ?? secondaryForeground\n const accent = colors.accent ?? secondary\n const accentForeground = colors.accentForeground ?? secondaryForeground\n const headingFont = typography.headingFont\n const bodyFont = typography.bodyFont\n const baseFontSize = typography.baseFontSize\n const lineHeight = typography.lineHeight\n\n return (\n <div\n style={{\n display: 'grid',\n gap: '16px',\n padding: '18px',\n borderRadius: '12px',\n backgroundColor: background,\n color: foreground,\n border: `1px solid ${borderColor}`,\n boxShadow: '0 8px 20px rgba(15, 23, 42, 0.08)',\n fontFamily: bodyFont,\n }}\n >\n <div\n style={{\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'space-between',\n fontSize: '12px',\n fontWeight: 600,\n letterSpacing: '0.08em',\n textTransform: 'uppercase',\n opacity: 0.7,\n }}\n >\n <span>\n {icon} {title}\n </span>\n <span style={{ fontFamily: 'monospace', fontSize: '11px' }}>\n {background.toUpperCase()}\n </span>\n </div>\n\n <div\n style={{\n backgroundColor: cardBackground,\n color: cardForeground,\n borderRadius: radius.card,\n border: `1px solid ${borderColor}`,\n padding: '16px',\n display: 'flex',\n gap: '12px',\n flexWrap: 'wrap',\n }}\n >\n <button\n type=\"button\"\n style={{\n padding: '10px 18px',\n borderRadius: radius.pill,\n border: 'none',\n cursor: 'pointer',\n fontSize: '12px',\n fontWeight: 600,\n letterSpacing: '0.02em',\n backgroundColor: primary,\n color: primaryForeground,\n boxShadow: '0 6px 14px rgba(15, 23, 42, 0.15)',\n }}\n >\n Primary Action\n </button>\n <button\n type=\"button\"\n style={{\n padding: '10px 18px',\n borderRadius: radius.chip,\n border: '1px solid transparent',\n cursor: 'pointer',\n fontSize: '12px',\n fontWeight: 600,\n letterSpacing: '0.02em',\n backgroundColor: secondary,\n color: secondaryForeground,\n boxShadow: 'inset 0 0 0 1px rgba(15, 23, 42, 0.08)',\n }}\n >\n Secondary\n </button>\n </div>\n\n <div\n style={{\n display: 'grid',\n gridTemplateColumns: 'repeat(auto-fit, minmax(120px, 1fr))',\n gap: '10px',\n }}\n >\n <div\n style={{\n borderRadius: radius.chip,\n padding: '10px 12px',\n fontSize: '12px',\n fontWeight: 500,\n backgroundColor: muted,\n color: mutedForeground,\n }}\n >\n Muted Card\n </div>\n <div\n style={{\n borderRadius: radius.chip,\n padding: '10px 12px',\n fontSize: '12px',\n fontWeight: 500,\n backgroundColor: accent,\n color: accentForeground,\n }}\n >\n Accent Tag\n </div>\n </div>\n\n <div\n style={{\n display: 'grid',\n gap: '8px',\n borderRadius: '10px',\n border: `1px dashed ${borderColor}`,\n padding: '14px',\n backgroundColor: 'rgba(148, 163, 184, 0.08)',\n }}\n >\n <div\n style={{\n fontFamily: headingFont,\n fontSize: 'clamp(24px, 3vw, 32px)',\n fontWeight: 600,\n lineHeight: 1.2,\n }}\n >\n Nadpis / Heading preview\n </div>\n <p\n style={{\n margin: 0,\n fontFamily: bodyFont,\n fontSize: baseFontSize,\n lineHeight,\n color: foreground,\n opacity: 0.85,\n }}\n >\n Sphinx of black quartz, judge my vow. Příliš žluťoučký kůň úpěl ďábelské ódy.\n </p>\n <div\n style={{\n display: 'flex',\n flexWrap: 'wrap',\n gap: '10px',\n fontSize: '11px',\n color: 'rgba(15, 23, 42, 0.7)',\n }}\n >\n <span>Body: {typography.bodyLabel}</span>\n <span>Heading: {typography.headingLabel}</span>\n <span>Base size: {baseFontSize}</span>\n <span>Line height: {lineHeight}</span>\n </div>\n </div>\n </div>\n )\n}\n\nexport default function ThemePreviewField(props: SelectFieldClientProps) {\n const { field, path } = props\n const { value: selectedTheme, setValue } = useField<string>({ path })\n const { dispatchFields } = useForm()\n const formFields = useFormFields(([formState]) => formState)\n const hasAppliedInitialPresetRef = useRef(false)\n\n const applyPreset = useCallback(\n (presetName: string) => {\n const preset = themePresets[presetName]\n if (!preset) {\n return\n }\n\n colorKeys.forEach((key) => {\n const lightValue = preset.lightMode[key]\n const darkValue = preset.darkMode[key]\n\n if (lightValue) {\n dispatchFields({\n type: 'UPDATE',\n path: `themeConfiguration.lightMode.${key}`,\n value: lightValue,\n })\n }\n\n if (darkValue) {\n dispatchFields({\n type: 'UPDATE',\n path: `themeConfiguration.darkMode.${key}`,\n value: darkValue,\n })\n }\n })\n },\n [dispatchFields],\n )\n\n const handleThemeSelect = useCallback(\n (value: string) => {\n setValue(value)\n\n if (!value) {\n return\n }\n\n hasAppliedInitialPresetRef.current = true\n applyPreset(value)\n },\n [applyPreset, setValue],\n )\n\n useEffect(() => {\n if (!selectedTheme) {\n return\n }\n\n if (themePresets[selectedTheme]) {\n return\n }\n\n hasAppliedInitialPresetRef.current = false\n setValue(FALLBACK_THEME)\n }, [selectedTheme, setValue])\n\n useEffect(() => {\n if (hasAppliedInitialPresetRef.current) {\n return\n }\n\n if (!selectedTheme) {\n return\n }\n\n if (!formFields) {\n return\n }\n\n const preset = themePresets[selectedTheme]\n if (!preset) {\n hasAppliedInitialPresetRef.current = true\n return\n }\n\n const hasExistingValues = colorKeys.some((key) => {\n const lightField = formFields[`themeConfiguration.lightMode.${key}`]\n const darkField = formFields[`themeConfiguration.darkMode.${key}`]\n\n const lightValue = typeof lightField?.value === 'string' && lightField.value.trim().length > 0\n const darkValue = typeof darkField?.value === 'string' && darkField.value.trim().length > 0\n\n return lightValue || darkValue\n })\n\n if (hasExistingValues) {\n hasAppliedInitialPresetRef.current = true\n return\n }\n\n applyPreset(selectedTheme)\n hasAppliedInitialPresetRef.current = true\n }, [selectedTheme, formFields, applyPreset])\n\n const lightModeColors = useMemo(() => {\n const presetLightMode = selectedTheme ? themePresets[selectedTheme]?.lightMode : undefined\n\n return colorKeys.reduce<ColorModeColors>((acc, key) => {\n const fieldState = formFields?.[`themeConfiguration.lightMode.${key}`]\n const rawValue =\n typeof fieldState?.value === 'string' && fieldState.value.trim().length > 0\n ? fieldState.value\n : undefined\n\n acc[key] = rawValue ?? presetLightMode?.[key] ?? lightModeDefaults[key]\n return acc\n }, {} as ColorModeColors)\n }, [formFields, selectedTheme])\n\n const darkModeColors = useMemo(() => {\n const presetDarkMode = selectedTheme ? themePresets[selectedTheme]?.darkMode : undefined\n\n return colorKeys.reduce<ColorModeColors>((acc, key) => {\n const fieldState = formFields?.[`themeConfiguration.darkMode.${key}`]\n const rawValue =\n typeof fieldState?.value === 'string' && fieldState.value.trim().length > 0\n ? fieldState.value\n : undefined\n\n acc[key] = rawValue ?? presetDarkMode?.[key] ?? darkModeDefaults[key]\n return acc\n }, {} as ColorModeColors)\n }, [formFields, selectedTheme])\n\n const activePreset = selectedTheme ? themePresets[selectedTheme] : undefined\n const formTypographySelection = useMemo<TypographySelection | null>(() => {\n if (!formFields) {\n return null\n }\n\n const getValue = (key: string) => formFields[`themeConfiguration.typography.${key}`]?.value\n\n return {\n bodyFont: (getValue('bodyFont') as string | undefined) ?? undefined,\n headingFont: (getValue('headingFont') as string | undefined) ?? undefined,\n bodyFontCustom: (getValue('bodyFontCustom') as string | undefined) ?? undefined,\n headingFontCustom: (getValue('headingFontCustom') as string | undefined) ?? undefined,\n baseFontSize: (getValue('baseFontSize') as string | undefined) ?? undefined,\n lineHeight: (getValue('lineHeight') as string | undefined) ?? undefined,\n }\n }, [formFields])\n\n const previewTypography = useMemo<ResolvedTypographyPreview>(() => {\n return resolveTypographyPreview(formTypographySelection, selectedTheme)\n }, [formTypographySelection, selectedTheme])\n\n const borderRadiusValue = formFields?.['themeConfiguration.borderRadius']?.value\n const presetRadius = activePreset?.borderRadius ?? 'medium'\n const resolvedBorderRadius = (\n typeof borderRadiusValue === 'string' && borderRadiusValue.length\n ? borderRadiusValue\n : presetRadius\n ) as keyof typeof borderRadiusPresets\n const borderRadiusPreset = borderRadiusPresets[resolvedBorderRadius] ?? borderRadiusPresets.medium\n const borderRadiusCSS =\n typeof borderRadiusPreset.css === 'string'\n ? { '--radius-default': borderRadiusPreset.css }\n : (borderRadiusPreset.css as Record<string, string>)\n const previewRadius = {\n card: borderRadiusCSS['--radius-large'] ?? '1rem',\n chip: borderRadiusCSS['--radius-default'] ?? '0.75rem',\n pill: borderRadiusCSS['--radius-xl'] ?? borderRadiusCSS['--radius-large'] ?? '999px',\n }\n\n const fieldLabel =\n typeof field.label === 'string' ? field.label : field.label?.en || field.label?.cs || 'Theme'\n\n return (\n <div style={{ marginBottom: '24px' }}>\n <label\n style={{\n display: 'block',\n marginBottom: '10px',\n fontSize: '13px',\n fontWeight: 600,\n color: 'var(--theme-elevation-800)',\n }}\n >\n {fieldLabel}\n </label>\n\n <div\n style={{\n display: 'flex',\n flexWrap: 'wrap',\n gap: '24px',\n alignItems: 'flex-start',\n }}\n >\n <div\n style={{\n flex: '0 0 320px',\n minWidth: '260px',\n maxWidth: '420px',\n display: 'grid',\n gap: '12px',\n }}\n >\n <div className=\"theme-preset-list\">\n {Object.entries(themePresets).map(([key, preset]) => {\n const isSelected = key === selectedTheme\n const swatches = highlightSwatches\n .map(({ key: colorKey }) => preset.lightMode[colorKey])\n .filter((color): color is string => Boolean(color))\n\n return (\n <button\n key={key}\n type=\"button\"\n onClick={() => handleThemeSelect(key)}\n className={`theme-preset-button ${isSelected ? 'selected' : ''}`}\n >\n <div className=\"theme-info\">\n <span className=\"theme-label\">{preset.label}</span>\n <span className=\"theme-name\">{key}</span>\n </div>\n <div className=\"theme-swatches\" aria-hidden=\"true\">\n {swatches.map((color, index) => (\n <span\n key={`${key}-swatch-${color}-${index}`}\n className=\"color-swatch\"\n style={{ backgroundColor: color }}\n />\n ))}\n </div>\n </button>\n )\n })}\n </div>\n\n {activePreset && (\n <div\n style={{\n padding: '12px',\n borderRadius: '10px',\n border: '1px solid var(--theme-elevation-200)',\n backgroundColor: 'var(--theme-elevation-50)',\n display: 'grid',\n gap: '8px',\n fontSize: '12px',\n color: 'var(--theme-elevation-600)',\n }}\n >\n <div style={{ fontWeight: 600, color: 'var(--theme-elevation-800)' }}>\n {activePreset.label}\n </div>\n <div>Primary color: {activePreset.lightMode.primary}</div>\n <div>Accent color: {activePreset.lightMode.accent}</div>\n <div\n style={{\n display: 'flex',\n flexWrap: 'wrap',\n gap: '12px',\n marginTop: '4px',\n }}\n >\n {highlightSwatches.map(({ key, label }) => {\n const swatchValue = activePreset.lightMode[key]\n\n if (!swatchValue) {\n return null\n }\n\n return (\n <div\n key={key}\n style={{\n display: 'flex',\n alignItems: 'center',\n gap: '6px',\n minWidth: 'fit-content',\n }}\n >\n <span\n style={{\n width: '22px',\n height: '22px',\n borderRadius: '999px',\n border: '1px solid rgba(15, 23, 42, 0.12)',\n backgroundColor: swatchValue,\n boxShadow: 'inset 0 1px 2px rgba(15, 23, 42, 0.08)',\n }}\n aria-hidden=\"true\"\n />\n <span style={{ fontSize: '11px', color: 'var(--theme-elevation-700)' }}>\n {label}\n </span>\n </div>\n )\n })}\n </div>\n </div>\n )}\n\n {field.admin?.description && (\n <div\n style={{\n fontSize: '12px',\n color: 'var(--theme-elevation-600)',\n lineHeight: 1.5,\n }}\n >\n {typeof field.admin.description === 'string'\n ? field.admin.description\n : field.admin.description?.en || field.admin.description?.cs || ''}\n </div>\n )}\n </div>\n\n <div\n style={{\n flex: '1 1 420px',\n minWidth: '320px',\n position: 'sticky',\n top: '96px',\n alignSelf: 'flex-start',\n }}\n >\n <div\n style={{\n width: '100%',\n borderRadius: '16px',\n border: '1px solid var(--theme-elevation-200)',\n backgroundColor: 'var(--theme-elevation-25)',\n padding: '20px',\n display: 'grid',\n gap: '18px',\n maxHeight: 'calc(100vh - 140px)',\n overflowY: 'auto',\n }}\n >\n <div\n style={{\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'space-between',\n fontWeight: 600,\n fontSize: '13px',\n color: 'var(--theme-elevation-800)',\n }}\n >\n <span>🎨 Live Preview</span>\n <span style={{ fontSize: '12px', color: 'var(--theme-elevation-600)' }}>\n {activePreset ? activePreset.label : 'Custom palette'}\n </span>\n </div>\n\n <div\n style={{\n display: 'grid',\n gap: '16px',\n }}\n >\n <ModePreview\n icon=\"☀️\"\n title=\"Light Mode\"\n colors={lightModeColors}\n typography={previewTypography}\n radius={previewRadius}\n />\n <ModePreview\n icon=\"🌙\"\n title=\"Dark Mode\"\n colors={darkModeColors}\n typography={previewTypography}\n radius={previewRadius}\n />\n </div>\n </div>\n </div>\n </div>\n </div>\n )\n}\n"],"names":["useField","useForm","useFormFields","useCallback","useEffect","useMemo","useRef","resolveTypographyPreview","allThemePresets","borderRadiusPresets","darkModeDefaults","lightModeDefaults","FALLBACK_THEME","name","themePresets","reduce","acc","preset","label","lightMode","darkMode","typography","borderRadius","colorKeys","Object","keys","highlightSwatches","key","ModePreview","icon","title","colors","radius","background","foreground","borderColor","border","cardBackground","card","cardForeground","primary","primaryForeground","secondary","secondaryForeground","muted","mutedForeground","accent","accentForeground","headingFont","bodyFont","baseFontSize","lineHeight","div","style","display","gap","padding","backgroundColor","color","boxShadow","fontFamily","alignItems","justifyContent","fontSize","fontWeight","letterSpacing","textTransform","opacity","span","toUpperCase","flexWrap","button","type","pill","cursor","chip","gridTemplateColumns","p","margin","bodyLabel","headingLabel","ThemePreviewField","props","field","path","value","selectedTheme","setValue","dispatchFields","formFields","formState","hasAppliedInitialPresetRef","applyPreset","presetName","forEach","lightValue","darkValue","handleThemeSelect","current","hasExistingValues","some","lightField","darkField","trim","length","lightModeColors","presetLightMode","undefined","fieldState","rawValue","darkModeColors","presetDarkMode","activePreset","formTypographySelection","getValue","bodyFontCustom","headingFontCustom","previewTypography","borderRadiusValue","presetRadius","resolvedBorderRadius","borderRadiusPreset","medium","borderRadiusCSS","css","previewRadius","fieldLabel","en","cs","marginBottom","flex","minWidth","maxWidth","className","entries","map","isSelected","swatches","colorKey","filter","Boolean","onClick","aria-hidden","index","marginTop","swatchValue","width","height","admin","description","position","top","alignSelf","maxHeight","overflowY"],"mappings":"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"}
1
+ {"version":3,"sources":["../../src/fields/ThemePreviewField.tsx"],"sourcesContent":["'use client'\n\nimport './ThemePreviewField.css'\nimport { useField, useForm, useFormFields } from '@payloadcms/ui'\nimport type { SelectFieldClientProps } from 'payload'\nimport { useCallback, useEffect, useMemo, useRef } from 'react'\nimport type {\n ResolvedTypographyPreview,\n TypographySelection,\n} from '../components/typographyPreviewUtils.js'\nimport { resolveTypographyPreview } from '../components/typographyPreviewUtils.js'\nimport { allThemePresets } from '../index.js'\nimport type { ThemePreset, ThemeTypographyPreset } from '../presets.js'\nimport { borderRadiusPresets } from '../providers/Theme/themeConfig.js'\nimport { darkModeDefaults, lightModeDefaults } from './colorModeFields.js'\n\ninterface ColorModeColors {\n background?: string\n foreground?: string\n card?: string\n cardForeground?: string\n popover?: string\n popoverForeground?: string\n primary?: string\n primaryForeground?: string\n secondary?: string\n secondaryForeground?: string\n muted?: string\n mutedForeground?: string\n accent?: string\n accentForeground?: string\n destructive?: string\n destructiveForeground?: string\n border?: string\n input?: string\n ring?: string\n}\n\ninterface ThemePresetDefinition {\n label: string\n lightMode: ColorModeColors\n darkMode: ColorModeColors\n typography?: ThemeTypographyPreset\n borderRadius: 'none' | 'small' | 'medium' | 'large' | 'xl'\n}\n\n// FALLBACK_THEME and runtime theme presets are computed inside the component\n\nconst colorKeys = Object.keys(lightModeDefaults) as (keyof ColorModeColors)[]\n\nconst highlightSwatches: Array<{ key: keyof ColorModeColors; label: string }> = [\n { key: 'primary', label: 'Primary' },\n { key: 'secondary', label: 'Secondary' },\n { key: 'accent', label: 'Accent' },\n { key: 'background', label: 'Background' },\n { key: 'foreground', label: 'Foreground' },\n]\n\ninterface ModePreviewProps {\n icon: string\n title: string\n colors: ColorModeColors\n typography: ResolvedTypographyPreview\n radius: {\n card: string\n chip: string\n pill: string\n }\n}\n\nfunction ModePreview({ icon, title, colors, typography, radius }: Readonly<ModePreviewProps>) {\n const background = colors.background ?? '#ffffff'\n const foreground = colors.foreground ?? '#0a0a0a'\n const borderColor = colors.border ?? 'rgba(148, 163, 184, 0.35)'\n const cardBackground = colors.card ?? background\n const cardForeground = colors.cardForeground ?? foreground\n const primary = colors.primary ?? foreground\n const primaryForeground = colors.primaryForeground ?? background\n const secondary = colors.secondary ?? '#f4f4f5'\n const secondaryForeground = colors.secondaryForeground ?? foreground\n const muted = colors.muted ?? secondary\n const mutedForeground = colors.mutedForeground ?? secondaryForeground\n const accent = colors.accent ?? secondary\n const accentForeground = colors.accentForeground ?? secondaryForeground\n const headingFont = typography.headingFont\n const bodyFont = typography.bodyFont\n const baseFontSize = typography.baseFontSize\n const lineHeight = typography.lineHeight\n\n return (\n <div\n style={{\n display: 'grid',\n gap: '16px',\n padding: '18px',\n borderRadius: '12px',\n backgroundColor: background,\n color: foreground,\n border: `1px solid ${borderColor}`,\n boxShadow: '0 8px 20px rgba(15, 23, 42, 0.08)',\n fontFamily: bodyFont,\n }}\n >\n <div\n style={{\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'space-between',\n fontSize: '12px',\n fontWeight: 600,\n letterSpacing: '0.08em',\n textTransform: 'uppercase',\n opacity: 0.7,\n }}\n >\n <span>\n {icon} {title}\n </span>\n <span style={{ fontFamily: 'monospace', fontSize: '11px' }}>\n {background.toUpperCase()}\n </span>\n </div>\n\n <div\n style={{\n backgroundColor: cardBackground,\n color: cardForeground,\n borderRadius: radius.card,\n border: `1px solid ${borderColor}`,\n padding: '16px',\n display: 'flex',\n gap: '12px',\n flexWrap: 'wrap',\n }}\n >\n <button\n type=\"button\"\n style={{\n padding: '10px 18px',\n borderRadius: radius.pill,\n border: 'none',\n cursor: 'pointer',\n fontSize: '12px',\n fontWeight: 600,\n letterSpacing: '0.02em',\n backgroundColor: primary,\n color: primaryForeground,\n boxShadow: '0 6px 14px rgba(15, 23, 42, 0.15)',\n }}\n >\n Primary Action\n </button>\n <button\n type=\"button\"\n style={{\n padding: '10px 18px',\n borderRadius: radius.chip,\n border: '1px solid transparent',\n cursor: 'pointer',\n fontSize: '12px',\n fontWeight: 600,\n letterSpacing: '0.02em',\n backgroundColor: secondary,\n color: secondaryForeground,\n boxShadow: 'inset 0 0 0 1px rgba(15, 23, 42, 0.08)',\n }}\n >\n Secondary\n </button>\n </div>\n\n <div\n style={{\n display: 'grid',\n gridTemplateColumns: 'repeat(auto-fit, minmax(120px, 1fr))',\n gap: '10px',\n }}\n >\n <div\n style={{\n borderRadius: radius.chip,\n padding: '10px 12px',\n fontSize: '12px',\n fontWeight: 500,\n backgroundColor: muted,\n color: mutedForeground,\n }}\n >\n Muted Card\n </div>\n <div\n style={{\n borderRadius: radius.chip,\n padding: '10px 12px',\n fontSize: '12px',\n fontWeight: 500,\n backgroundColor: accent,\n color: accentForeground,\n }}\n >\n Accent Tag\n </div>\n </div>\n\n <div\n style={{\n display: 'grid',\n gap: '8px',\n borderRadius: '10px',\n border: `1px dashed ${borderColor}`,\n padding: '14px',\n backgroundColor: 'rgba(148, 163, 184, 0.08)',\n }}\n >\n <div\n style={{\n fontFamily: headingFont,\n fontSize: 'clamp(24px, 3vw, 32px)',\n fontWeight: 600,\n lineHeight: 1.2,\n }}\n >\n Nadpis / Heading preview\n </div>\n <p\n style={{\n margin: 0,\n fontFamily: bodyFont,\n fontSize: baseFontSize,\n lineHeight,\n color: foreground,\n opacity: 0.85,\n }}\n >\n Sphinx of black quartz, judge my vow. Příliš žluťoučký kůň úpěl ďábelské ódy.\n </p>\n <div\n style={{\n display: 'flex',\n flexWrap: 'wrap',\n gap: '10px',\n fontSize: '11px',\n color: 'rgba(15, 23, 42, 0.7)',\n }}\n >\n <span>Body: {typography.bodyLabel}</span>\n <span>Heading: {typography.headingLabel}</span>\n <span>Base size: {baseFontSize}</span>\n <span>Line height: {lineHeight}</span>\n </div>\n </div>\n </div>\n )\n}\n\nexport default function ThemePreviewField(props: SelectFieldClientProps) {\n const { field, path } = props\n // If the plugin provided theme presets via admin config, prefer those; otherwise fallback to allThemePresets\n const baseThemePresets =\n (field?.admin as unknown as { themePresets?: ThemePreset[] })?.themePresets ?? allThemePresets\n const runtimeThemePresets = useMemo(() => {\n return (baseThemePresets as ThemePreset[]).reduce<Record<string, ThemePresetDefinition>>(\n (acc, preset) => {\n acc[preset.name] = {\n label: preset.label,\n lightMode: { ...lightModeDefaults, ...(preset.lightMode ?? {}) },\n darkMode: { ...darkModeDefaults, ...(preset.darkMode ?? {}) },\n typography: preset.typography,\n borderRadius: preset.borderRadius,\n }\n return acc\n },\n {},\n )\n }, [baseThemePresets])\n const fallbackTheme = baseThemePresets[0]?.name ?? 'cool'\n const { value: selectedTheme, setValue } = useField<string>({ path })\n const { dispatchFields } = useForm()\n const formFields = useFormFields(([formState]) => formState)\n const hasAppliedInitialPresetRef = useRef(false)\n\n const applyPreset = useCallback(\n (presetName: string) => {\n const preset = runtimeThemePresets[presetName]\n if (!preset) {\n return\n }\n\n colorKeys.forEach((key) => {\n const lightValue = preset.lightMode[key]\n const darkValue = preset.darkMode[key]\n\n if (lightValue) {\n dispatchFields({\n type: 'UPDATE',\n path: `themeConfiguration.lightMode.${key}`,\n value: lightValue,\n })\n }\n\n if (darkValue) {\n dispatchFields({\n type: 'UPDATE',\n path: `themeConfiguration.darkMode.${key}`,\n value: darkValue,\n })\n }\n })\n },\n [dispatchFields],\n )\n\n const handleThemeSelect = useCallback(\n (value: string) => {\n setValue(value)\n\n if (!value) {\n return\n }\n\n hasAppliedInitialPresetRef.current = true\n applyPreset(value)\n },\n [applyPreset, setValue],\n )\n\n useEffect(() => {\n if (!selectedTheme) {\n return\n }\n\n if (runtimeThemePresets[selectedTheme]) {\n return\n }\n\n hasAppliedInitialPresetRef.current = false\n setValue(fallbackTheme)\n }, [selectedTheme, setValue])\n\n useEffect(() => {\n if (hasAppliedInitialPresetRef.current) {\n return\n }\n\n if (!selectedTheme) {\n return\n }\n\n if (!formFields) {\n return\n }\n\n const preset = runtimeThemePresets[selectedTheme]\n if (!preset) {\n hasAppliedInitialPresetRef.current = true\n return\n }\n\n const hasExistingValues = colorKeys.some((key) => {\n const lightField = formFields[`themeConfiguration.lightMode.${key}`]\n const darkField = formFields[`themeConfiguration.darkMode.${key}`]\n\n const lightValue = typeof lightField?.value === 'string' && lightField.value.trim().length > 0\n const darkValue = typeof darkField?.value === 'string' && darkField.value.trim().length > 0\n\n return lightValue || darkValue\n })\n\n if (hasExistingValues) {\n hasAppliedInitialPresetRef.current = true\n return\n }\n\n applyPreset(selectedTheme)\n hasAppliedInitialPresetRef.current = true\n }, [selectedTheme, formFields, applyPreset])\n\n const lightModeColors = useMemo(() => {\n const presetLightMode = selectedTheme\n ? runtimeThemePresets[selectedTheme]?.lightMode\n : undefined\n\n return colorKeys.reduce<ColorModeColors>((acc, key) => {\n const fieldState = formFields?.[`themeConfiguration.lightMode.${key}`]\n const rawValue =\n typeof fieldState?.value === 'string' && fieldState.value.trim().length > 0\n ? fieldState.value\n : undefined\n\n acc[key] = rawValue ?? presetLightMode?.[key] ?? lightModeDefaults[key]\n return acc\n }, {} as ColorModeColors)\n }, [formFields, selectedTheme])\n\n const darkModeColors = useMemo(() => {\n const presetDarkMode = selectedTheme ? runtimeThemePresets[selectedTheme]?.darkMode : undefined\n\n return colorKeys.reduce<ColorModeColors>((acc, key) => {\n const fieldState = formFields?.[`themeConfiguration.darkMode.${key}`]\n const rawValue =\n typeof fieldState?.value === 'string' && fieldState.value.trim().length > 0\n ? fieldState.value\n : undefined\n\n acc[key] = rawValue ?? presetDarkMode?.[key] ?? darkModeDefaults[key]\n return acc\n }, {} as ColorModeColors)\n }, [formFields, selectedTheme])\n\n const activePreset = selectedTheme ? runtimeThemePresets[selectedTheme] : undefined\n const formTypographySelection = useMemo<TypographySelection | null>(() => {\n if (!formFields) {\n return null\n }\n\n const getValue = (key: string) => formFields[`themeConfiguration.typography.${key}`]?.value\n\n return {\n bodyFont: (getValue('bodyFont') as string | undefined) ?? undefined,\n headingFont: (getValue('headingFont') as string | undefined) ?? undefined,\n bodyFontCustom: (getValue('bodyFontCustom') as string | undefined) ?? undefined,\n headingFontCustom: (getValue('headingFontCustom') as string | undefined) ?? undefined,\n baseFontSize: (getValue('baseFontSize') as string | undefined) ?? undefined,\n lineHeight: (getValue('lineHeight') as string | undefined) ?? undefined,\n }\n }, [formFields])\n\n const previewTypography = useMemo<ResolvedTypographyPreview>(() => {\n return resolveTypographyPreview(formTypographySelection, selectedTheme)\n }, [formTypographySelection, selectedTheme])\n\n const borderRadiusValue = formFields?.['themeConfiguration.borderRadius']?.value\n const presetRadius = activePreset?.borderRadius ?? 'medium'\n const resolvedBorderRadius = (\n typeof borderRadiusValue === 'string' && borderRadiusValue.length\n ? borderRadiusValue\n : presetRadius\n ) as keyof typeof borderRadiusPresets\n const borderRadiusPreset = borderRadiusPresets[resolvedBorderRadius] ?? borderRadiusPresets.medium\n const borderRadiusCSS =\n typeof borderRadiusPreset.css === 'string'\n ? { '--radius-default': borderRadiusPreset.css }\n : (borderRadiusPreset.css as Record<string, string>)\n const previewRadius = {\n card: borderRadiusCSS['--radius-large'] ?? '1rem',\n chip: borderRadiusCSS['--radius-default'] ?? '0.75rem',\n pill: borderRadiusCSS['--radius-xl'] ?? borderRadiusCSS['--radius-large'] ?? '999px',\n }\n\n const fieldLabel =\n typeof field.label === 'string' ? field.label : field.label?.en || field.label?.cs || 'Theme'\n\n return (\n <div style={{ marginBottom: '24px' }}>\n <label\n style={{\n display: 'block',\n marginBottom: '10px',\n fontSize: '13px',\n fontWeight: 600,\n color: 'var(--theme-elevation-800)',\n }}\n >\n {fieldLabel}\n </label>\n\n <div\n style={{\n display: 'flex',\n flexWrap: 'wrap',\n gap: '24px',\n alignItems: 'flex-start',\n }}\n >\n <div\n style={{\n flex: '0 0 320px',\n minWidth: '260px',\n maxWidth: '420px',\n display: 'grid',\n gap: '12px',\n }}\n >\n <div className=\"theme-preset-list\">\n {Object.entries(runtimeThemePresets).map(([key, preset]) => {\n const isSelected = key === selectedTheme\n const swatches = highlightSwatches\n .map(({ key: colorKey }) => preset.lightMode[colorKey])\n .filter((color): color is string => Boolean(color))\n\n return (\n <button\n key={key}\n type=\"button\"\n onClick={() => handleThemeSelect(key)}\n className={`theme-preset-button ${isSelected ? 'selected' : ''}`}\n >\n <div className=\"theme-info\">\n <span className=\"theme-label\">{preset.label}</span>\n <span className=\"theme-name\">{key}</span>\n </div>\n <div className=\"theme-swatches\" aria-hidden=\"true\">\n {swatches.map((color, index) => (\n <span\n key={`${key}-swatch-${color}-${index}`}\n className=\"color-swatch\"\n style={{ backgroundColor: color }}\n />\n ))}\n </div>\n </button>\n )\n })}\n </div>\n\n {activePreset && (\n <div\n style={{\n padding: '12px',\n borderRadius: '10px',\n border: '1px solid var(--theme-elevation-200)',\n backgroundColor: 'var(--theme-elevation-50)',\n display: 'grid',\n gap: '8px',\n fontSize: '12px',\n color: 'var(--theme-elevation-600)',\n }}\n >\n <div style={{ fontWeight: 600, color: 'var(--theme-elevation-800)' }}>\n {activePreset.label}\n </div>\n <div>Primary color: {activePreset.lightMode.primary}</div>\n <div>Accent color: {activePreset.lightMode.accent}</div>\n <div\n style={{\n display: 'flex',\n flexWrap: 'wrap',\n gap: '12px',\n marginTop: '4px',\n }}\n >\n {highlightSwatches.map(({ key, label }) => {\n const swatchValue = activePreset.lightMode[key]\n\n if (!swatchValue) {\n return null\n }\n\n return (\n <div\n key={key}\n style={{\n display: 'flex',\n alignItems: 'center',\n gap: '6px',\n minWidth: 'fit-content',\n }}\n >\n <span\n style={{\n width: '22px',\n height: '22px',\n borderRadius: '999px',\n border: '1px solid rgba(15, 23, 42, 0.12)',\n backgroundColor: swatchValue,\n boxShadow: 'inset 0 1px 2px rgba(15, 23, 42, 0.08)',\n }}\n aria-hidden=\"true\"\n />\n <span style={{ fontSize: '11px', color: 'var(--theme-elevation-700)' }}>\n {label}\n </span>\n </div>\n )\n })}\n </div>\n </div>\n )}\n\n {field.admin?.description && (\n <div\n style={{\n fontSize: '12px',\n color: 'var(--theme-elevation-600)',\n lineHeight: 1.5,\n }}\n >\n {typeof field.admin.description === 'string'\n ? field.admin.description\n : field.admin.description?.en || field.admin.description?.cs || ''}\n </div>\n )}\n </div>\n\n <div\n style={{\n flex: '1 1 420px',\n minWidth: '320px',\n position: 'sticky',\n top: '96px',\n alignSelf: 'flex-start',\n }}\n >\n <div\n style={{\n width: '100%',\n borderRadius: '16px',\n border: '1px solid var(--theme-elevation-200)',\n backgroundColor: 'var(--theme-elevation-25)',\n padding: '20px',\n display: 'grid',\n gap: '18px',\n maxHeight: 'calc(100vh - 140px)',\n overflowY: 'auto',\n }}\n >\n <div\n style={{\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'space-between',\n fontWeight: 600,\n fontSize: '13px',\n color: 'var(--theme-elevation-800)',\n }}\n >\n <span>🎨 Live Preview</span>\n <span style={{ fontSize: '12px', color: 'var(--theme-elevation-600)' }}>\n {activePreset ? activePreset.label : 'Custom palette'}\n </span>\n </div>\n\n <div\n style={{\n display: 'grid',\n gap: '16px',\n }}\n >\n <ModePreview\n icon=\"☀️\"\n title=\"Light Mode\"\n colors={lightModeColors}\n typography={previewTypography}\n radius={previewRadius}\n />\n <ModePreview\n icon=\"🌙\"\n title=\"Dark Mode\"\n colors={darkModeColors}\n typography={previewTypography}\n radius={previewRadius}\n />\n </div>\n </div>\n </div>\n </div>\n </div>\n )\n}\n"],"names":["useField","useForm","useFormFields","useCallback","useEffect","useMemo","useRef","resolveTypographyPreview","allThemePresets","borderRadiusPresets","darkModeDefaults","lightModeDefaults","colorKeys","Object","keys","highlightSwatches","key","label","ModePreview","icon","title","colors","typography","radius","background","foreground","borderColor","border","cardBackground","card","cardForeground","primary","primaryForeground","secondary","secondaryForeground","muted","mutedForeground","accent","accentForeground","headingFont","bodyFont","baseFontSize","lineHeight","div","style","display","gap","padding","borderRadius","backgroundColor","color","boxShadow","fontFamily","alignItems","justifyContent","fontSize","fontWeight","letterSpacing","textTransform","opacity","span","toUpperCase","flexWrap","button","type","pill","cursor","chip","gridTemplateColumns","p","margin","bodyLabel","headingLabel","ThemePreviewField","props","field","path","baseThemePresets","admin","themePresets","runtimeThemePresets","reduce","acc","preset","name","lightMode","darkMode","fallbackTheme","value","selectedTheme","setValue","dispatchFields","formFields","formState","hasAppliedInitialPresetRef","applyPreset","presetName","forEach","lightValue","darkValue","handleThemeSelect","current","hasExistingValues","some","lightField","darkField","trim","length","lightModeColors","presetLightMode","undefined","fieldState","rawValue","darkModeColors","presetDarkMode","activePreset","formTypographySelection","getValue","bodyFontCustom","headingFontCustom","previewTypography","borderRadiusValue","presetRadius","resolvedBorderRadius","borderRadiusPreset","medium","borderRadiusCSS","css","previewRadius","fieldLabel","en","cs","marginBottom","flex","minWidth","maxWidth","className","entries","map","isSelected","swatches","colorKey","filter","Boolean","onClick","aria-hidden","index","marginTop","swatchValue","width","height","description","position","top","alignSelf","maxHeight","overflowY"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"themeConfigurationField.d.ts","sourceRoot":"","sources":["../../src/fields/themeConfigurationField.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAS,SAAS,EAAE,MAAM,SAAS,CAAA;AAO/C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AAG9C,UAAU,8BAA8B;IACtC,YAAY,EAAE,WAAW,EAAE,CAAA;IAC3B,YAAY,EAAE,MAAM,CAAA;IACpB,sBAAsB,EAAE,OAAO,CAAA;IAC/B,gBAAgB,EAAE,OAAO,CAAA;IACzB,oBAAoB,EAAE,OAAO,CAAA;IAC7B,sBAAsB,CAAC,EAAE,OAAO,CAAA;CACjC;AAGD,MAAM,MAAM,QAAQ,GAAG,WAAW,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAA;AAE7D;;;GAGG;AACH,wBAAgB,6BAA6B,CAAC,OAAO,EAAE,8BAA8B,GAAG,QAAQ,CAoY/F"}
1
+ {"version":3,"file":"themeConfigurationField.d.ts","sourceRoot":"","sources":["../../src/fields/themeConfigurationField.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAS,SAAS,EAAE,MAAM,SAAS,CAAA;AAO/C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AAG9C,UAAU,8BAA8B;IACtC,YAAY,EAAE,WAAW,EAAE,CAAA;IAC3B,YAAY,EAAE,MAAM,CAAA;IACpB,sBAAsB,EAAE,OAAO,CAAA;IAC/B,gBAAgB,EAAE,OAAO,CAAA;IACzB,oBAAoB,EAAE,OAAO,CAAA;IAC7B,sBAAsB,CAAC,EAAE,OAAO,CAAA;CACjC;AAGD,MAAM,MAAM,QAAQ,GAAG,WAAW,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAA;AAE7D;;;GAGG;AACH,wBAAgB,6BAA6B,CAAC,OAAO,EAAE,8BAA8B,GAAG,QAAQ,CAsa/F"}
@@ -5,25 +5,22 @@ import { darkModeField, lightModeField } from './colorModeFields.js';
5
5
  * Theme Selection populates lightMode/darkMode colors automatically
6
6
  */ export function createThemeConfigurationField(options) {
7
7
  const { themePresets, defaultTheme, includeColorModeToggle, includeCustomCSS, enableAdvancedFeatures = true } = options;
8
- const themeOptions = themePresets.map((preset)=>{
9
- const previewColor = preset.preview?.colors.primary;
10
- const label = previewColor ? `${preset.label} • ${previewColor}` : preset.label;
11
- return {
12
- label,
13
- value: preset.name
14
- };
15
- });
16
8
  const fields = [
17
9
  {
18
10
  name: 'theme',
19
- type: 'select',
11
+ type: 'text',
20
12
  required: true,
21
13
  defaultValue: defaultTheme,
22
- options: themeOptions,
23
14
  label: {
24
15
  en: '🎨 Theme Selection',
25
16
  cs: '🎨 Výběr tématu'
26
17
  },
18
+ validate: (value)=>{
19
+ if (typeof value === 'string' && value.trim().length > 0) {
20
+ return true;
21
+ }
22
+ return 'Select a theme';
23
+ },
27
24
  admin: {
28
25
  description: {
29
26
  en: 'Select a theme to auto-populate color values. You can customize colors after selection.',
@@ -31,6 +28,9 @@ import { darkModeField, lightModeField } from './colorModeFields.js';
31
28
  },
32
29
  components: {
33
30
  Field: '@kilivi/payloadcms-theme-management/fields/ThemePreviewField'
31
+ },
32
+ custom: {
33
+ themePresets
34
34
  }
35
35
  }
36
36
  }
@@ -352,6 +352,40 @@ import { darkModeField, lightModeField } from './colorModeFields.js';
352
352
  }
353
353
  ]
354
354
  });
355
+ // Custom Theme Presets importer
356
+ fields.push({
357
+ type: 'collapsible',
358
+ label: {
359
+ en: '🧩 Custom Theme Presets',
360
+ cs: '🧩 Vlastní motivy'
361
+ },
362
+ admin: {
363
+ initCollapsed: true,
364
+ description: {
365
+ en: 'Import additional theme presets via JSON to extend or override the defaults. These presets become available instantly in the Theme Selection above.',
366
+ cs: 'Importujte další motivy pomocí JSONu a rozšiřte nebo přepište výchozí nabídku. Motivy budou ihned k dispozici ve výběru výše.'
367
+ }
368
+ },
369
+ fields: [
370
+ {
371
+ name: 'customThemePresets',
372
+ type: 'json',
373
+ label: {
374
+ en: 'Custom Preset JSON',
375
+ cs: 'JSON s vlastními motivy'
376
+ },
377
+ admin: {
378
+ description: {
379
+ en: 'Paste or import an array (or object map) of theme presets. Each entry should include at least a unique "name" and "label" with optional lightMode/darkMode colors.',
380
+ cs: 'Vložte nebo importujte pole (či objekt) motivů. Každý motiv musí mít unikátní „name“ a „label“ a volitelně barvy pro světly/tmavý režim.'
381
+ },
382
+ components: {
383
+ Field: '@kilivi/payloadcms-theme-management/fields/ThemePresetImportField'
384
+ }
385
+ }
386
+ }
387
+ ]
388
+ });
355
389
  // Advanced Settings (when using extended theme configuration)
356
390
  if (enableAdvancedFeatures) {
357
391
  const advancedFields = [
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/fields/themeConfigurationField.ts"],"sourcesContent":["import type { Field, TabsField } from 'payload'\nimport {\n BASE_FONT_SIZE_OPTIONS,\n BODY_FONT_OPTIONS,\n HEADING_FONT_OPTIONS,\n LINE_HEIGHT_OPTIONS,\n} from '../constants/themeFonts.js'\nimport type { ThemePreset } from '../index.js'\nimport { darkModeField, lightModeField } from './colorModeFields.js'\n\ninterface ThemeConfigurationFieldOptions {\n themePresets: ThemePreset[]\n defaultTheme: string\n includeColorModeToggle: boolean\n includeCustomCSS: boolean\n includeBrandIdentity: boolean\n enableAdvancedFeatures?: boolean\n}\n\n// Type for a single tab (not the full TabsField)\nexport type ThemeTab = NonNullable<TabsField['tabs']>[number]\n\n/**\n * Theme Configuration Field with Theme Selection as default value setter\n * Theme Selection populates lightMode/darkMode colors automatically\n */\nexport function createThemeConfigurationField(options: ThemeConfigurationFieldOptions): ThemeTab {\n const {\n themePresets,\n defaultTheme,\n includeColorModeToggle,\n includeCustomCSS,\n enableAdvancedFeatures = true,\n } = options\n\n const themeOptions = themePresets.map((preset) => {\n const previewColor = preset.preview?.colors.primary\n const label = previewColor ? `${preset.label} • ${previewColor}` : preset.label\n return {\n label,\n value: preset.name,\n }\n })\n\n const fields: Field[] = [\n {\n name: 'theme',\n type: 'select',\n required: true,\n defaultValue: defaultTheme,\n options: themeOptions,\n label: {\n en: '🎨 Theme Selection',\n cs: '🎨 Výběr tématu',\n },\n admin: {\n description: {\n en: 'Select a theme to auto-populate color values. You can customize colors after selection.',\n cs: 'Vyberte téma pro automatické předvyplnění barev. Po výběru můžete barvy upravit.',\n },\n components: {\n Field: '@kilivi/payloadcms-theme-management/fields/ThemePreviewField',\n },\n },\n },\n ]\n\n // Border Radius Configuration - Always visible\n fields.push({\n type: 'row',\n fields: [\n {\n name: 'borderRadius',\n type: 'select',\n label: {\n en: '📐 Border Radius',\n cs: '📐 Zaoblení rohů',\n },\n defaultValue: 'medium',\n options: [\n { label: { en: 'None (0px)', cs: 'Žádné (0px)' }, value: 'none' },\n { label: { en: 'Small (0.25rem)', cs: 'Malé (0.25rem)' }, value: 'small' },\n { label: { en: 'Medium (0.5rem)', cs: 'Střední (0.5rem)' }, value: 'medium' },\n { label: { en: 'Large (0.75rem)', cs: 'Velké (0.75rem)' }, value: 'large' },\n { label: { en: 'XL (1rem)', cs: 'XL (1rem)' }, value: 'xl' },\n ],\n admin: {\n description: {\n en: 'Default corner rounding for UI elements',\n cs: 'Výchozí zaoblení rohů pro UI prvky',\n },\n width: '50%',\n },\n },\n {\n name: 'spacing',\n type: 'select',\n label: {\n en: '📏 Spacing Scale',\n cs: '📏 Škála rozestupů',\n },\n defaultValue: 'medium',\n options: [\n { label: { en: 'Compact', cs: 'Kompaktní' }, value: 'compact' },\n { label: { en: 'Medium', cs: 'Střední' }, value: 'medium' },\n { label: { en: 'Comfortable', cs: 'Pohodlné' }, value: 'comfortable' },\n ],\n admin: {\n description: {\n en: 'Global spacing between elements',\n cs: 'Globální rozestupy mezi prvky',\n },\n width: '50%',\n },\n },\n ],\n })\n\n // Color Mode Settings\n if (includeColorModeToggle) {\n fields.push({\n type: 'collapsible',\n label: {\n en: '🌗 Color Mode Settings',\n cs: '🌗 Nastavení barevného režimu',\n },\n admin: {\n initCollapsed: false,\n description: {\n en: 'Configure light and dark mode colors. Changes here override theme selection.',\n cs: 'Nakonfigurujte barvy světlého a tmavého režimu. Změny zde přepíší výběr tématu.',\n },\n },\n fields: [\n {\n type: 'row',\n fields: [\n {\n name: 'colorMode',\n type: 'select',\n label: {\n en: 'Default Color Mode',\n cs: 'Výchozí barevný režim',\n },\n defaultValue: 'auto',\n options: [\n {\n label: {\n en: 'Auto (System)',\n cs: 'Automaticky (Systém)',\n },\n value: 'auto',\n },\n {\n label: { en: 'Light', cs: 'Světlý' },\n value: 'light',\n },\n {\n label: { en: 'Dark', cs: 'Tmavý' },\n value: 'dark',\n },\n ],\n admin: {\n description: {\n en: 'Default color mode for visitors',\n cs: 'Výchozí barevný režim pro návštěvníky',\n },\n width: '50%',\n },\n },\n {\n name: 'allowColorModeToggle',\n type: 'checkbox',\n label: {\n en: 'Enable Mode Toggle',\n cs: 'Povolit přepínač režimu',\n },\n defaultValue: true,\n admin: {\n description: {\n en: 'Let visitors switch modes',\n cs: 'Umožnit návštěvníkům přepínat režimy',\n },\n width: '50%',\n },\n },\n ],\n },\n lightModeField,\n darkModeField,\n ],\n })\n }\n\n // Typography - Always visible\n fields.push({\n type: 'collapsible',\n label: {\n en: '🅰️ Typography',\n cs: '🅰️ Typografie',\n },\n admin: {\n initCollapsed: true,\n description: {\n en: 'Choose font families and base typography settings. Leave fields on \"Use preset\" to inherit the theme defaults.',\n cs: 'Zvolte rodiny písem a základní typografické nastavení. Hodnota \"Použít výchozí\" zachová nastavení motivu.',\n },\n },\n fields: [\n {\n name: 'typography',\n type: 'group',\n fields: [\n {\n type: 'row',\n fields: [\n {\n name: 'bodyFont',\n type: 'select',\n label: {\n en: 'Body font',\n cs: 'Písmo pro text',\n },\n defaultValue: 'preset',\n // @ts-expect-error - Pass full objects including fontFamily for custom rendering\n options: BODY_FONT_OPTIONS,\n admin: {\n width: '50%',\n components: {\n Field: '@kilivi/payloadcms-theme-management/fields/FontSelectField',\n },\n },\n },\n {\n name: 'headingFont',\n type: 'select',\n label: {\n en: 'Heading font',\n cs: 'Písmo pro nadpisy',\n },\n defaultValue: 'preset',\n // @ts-expect-error - Pass full objects including fontFamily for custom rendering\n options: HEADING_FONT_OPTIONS,\n admin: {\n width: '50%',\n components: {\n Field: '@kilivi/payloadcms-theme-management/fields/FontSelectField',\n },\n },\n },\n ],\n },\n {\n type: 'row',\n fields: [\n {\n name: 'bodyFontCustom',\n type: 'text',\n label: {\n en: 'Custom body font stack',\n cs: 'Vlastní písmo pro text',\n },\n admin: {\n width: '50%',\n placeholder: '\"IBM Plex Sans\", sans-serif',\n description: {\n en: 'Provide full CSS font-family stack when using a custom font.',\n cs: 'Při volbě vlastního písma zadejte celý CSS zápis font-family.',\n },\n condition: (_, siblingData) => siblingData?.bodyFont === 'custom',\n },\n },\n {\n name: 'headingFontCustom',\n type: 'text',\n label: {\n en: 'Custom heading font stack',\n cs: 'Vlastní písmo pro nadpisy',\n },\n admin: {\n width: '50%',\n placeholder: '\"Cormorant Garamond\", serif',\n description: {\n en: 'Provide full CSS font-family stack when using a custom heading font.',\n cs: 'Při volbě vlastního nadpisového písma zadejte celý CSS zápis font-family.',\n },\n condition: (_, siblingData) => siblingData?.headingFont === 'custom',\n },\n },\n ],\n },\n {\n type: 'row',\n fields: [\n {\n name: 'baseFontSize',\n type: 'select',\n label: {\n en: 'Base font size',\n cs: 'Základní velikost písma',\n },\n defaultValue: 'preset',\n options: BASE_FONT_SIZE_OPTIONS.map((option) => ({\n label: option.label,\n value: option.value,\n })),\n admin: {\n width: '50%',\n },\n },\n {\n name: 'lineHeight',\n type: 'select',\n label: {\n en: 'Line height',\n cs: 'Řádkování',\n },\n defaultValue: 'preset',\n options: LINE_HEIGHT_OPTIONS.map((option) => ({\n label: option.label,\n value: option.value,\n })),\n admin: {\n width: '50%',\n },\n },\n ],\n },\n ],\n },\n ],\n })\n\n // Advanced Settings (when using extended theme configuration)\n if (enableAdvancedFeatures) {\n const advancedFields: Field[] = [\n {\n name: 'animationLevel',\n type: 'select',\n label: {\n en: 'Animation Level',\n cs: 'Úroveň animací',\n },\n defaultValue: 'medium',\n options: [\n { label: { en: 'None', cs: 'Žádné' }, value: 'none' },\n { label: { en: 'Reduced', cs: 'Snížené' }, value: 'reduced' },\n { label: { en: 'Medium', cs: 'Střední' }, value: 'medium' },\n { label: { en: 'High', cs: 'Vysoké' }, value: 'high' },\n ],\n admin: {\n description: {\n en: 'Control website animations and transitions',\n cs: 'Kontrola animací a přechodů na webu',\n },\n width: '50%',\n },\n },\n ]\n\n if (includeCustomCSS) {\n advancedFields.push({\n name: 'customCSS',\n type: 'code',\n label: {\n en: 'Custom CSS',\n cs: 'Vlastní CSS',\n },\n admin: {\n language: 'css',\n description: {\n en: 'Add custom CSS to override default styles',\n cs: 'Přidejte vlastní CSS pro přepsání výchozích stylů',\n },\n // placeholder:\n // ':root {\\n --primary: #your-color;\\n --border-radius: 8px;\\n --font-family: \"Your Font\";\\n}\\n\\n.custom-class {\\n /* Your custom styles */\\n}',\n // rows: 8,\n },\n })\n }\n\n fields.push({\n type: 'collapsible',\n label: {\n en: '⚙️ Advanced Settings',\n cs: '⚙️ Pokročilé nastavení',\n },\n admin: {\n initCollapsed: true,\n },\n fields: advancedFields,\n })\n }\n\n // Return as tab configuration to be injected into tabs structure\n return {\n label: {\n en: '🎨 Appearance Settings',\n cs: '🎨 Nastavení vzhledu',\n },\n fields: [\n {\n name: 'themeConfiguration',\n type: 'group',\n admin: {\n description: {\n en: 'Configure website appearance and styling',\n cs: 'Nakonfigurujte vzhled a stylování webu',\n },\n },\n fields,\n },\n ],\n }\n}\n"],"names":["BASE_FONT_SIZE_OPTIONS","BODY_FONT_OPTIONS","HEADING_FONT_OPTIONS","LINE_HEIGHT_OPTIONS","darkModeField","lightModeField","createThemeConfigurationField","options","themePresets","defaultTheme","includeColorModeToggle","includeCustomCSS","enableAdvancedFeatures","themeOptions","map","preset","previewColor","preview","colors","primary","label","value","name","fields","type","required","defaultValue","en","cs","admin","description","components","Field","push","width","initCollapsed","placeholder","condition","_","siblingData","bodyFont","headingFont","option","advancedFields","language"],"mappings":"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;qBACD;gBACH;gBACA7B;gBACAD;aACD;QACH;IACF;IAEA,8BAA8B;IAC9BmB,OAAOU,IAAI,CAAC;QACVT,MAAM;QACNJ,OAAO;YACLO,IAAI;YACJC,IAAI;QACN;QACAC,OAAO;YACLM,eAAe;YACfL,aAAa;gBACXH,IAAI;gBACJC,IAAI;YACN;QACF;QACAL,QAAQ;YACN;gBACED,MAAM;gBACNE,MAAM;gBACND,QAAQ;oBACN;wBACEC,MAAM;wBACND,QAAQ;4BACN;gCACED,MAAM;gCACNE,MAAM;gCACNJ,OAAO;oCACLO,IAAI;oCACJC,IAAI;gCACN;gCACAF,cAAc;gCACd,iFAAiF;gCACjFnB,SAASN;gCACT4B,OAAO;oCACLK,OAAO;oCACPH,YAAY;wCACVC,OAAO;oCACT;gCACF;4BACF;4BACA;gCACEV,MAAM;gCACNE,MAAM;gCACNJ,OAAO;oCACLO,IAAI;oCACJC,IAAI;gCACN;gCACAF,cAAc;gCACd,iFAAiF;gCACjFnB,SAASL;gCACT2B,OAAO;oCACLK,OAAO;oCACPH,YAAY;wCACVC,OAAO;oCACT;gCACF;4BACF;yBACD;oBACH;oBACA;wBACER,MAAM;wBACND,QAAQ;4BACN;gCACED,MAAM;gCACNE,MAAM;gCACNJ,OAAO;oCACLO,IAAI;oCACJC,IAAI;gCACN;gCACAC,OAAO;oCACLK,OAAO;oCACPE,aAAa;oCACbN,aAAa;wCACXH,IAAI;wCACJC,IAAI;oCACN;oCACAS,WAAW,CAACC,GAAGC,cAAgBA,aAAaC,aAAa;gCAC3D;4BACF;4BACA;gCACElB,MAAM;gCACNE,MAAM;gCACNJ,OAAO;oCACLO,IAAI;oCACJC,IAAI;gCACN;gCACAC,OAAO;oCACLK,OAAO;oCACPE,aAAa;oCACbN,aAAa;wCACXH,IAAI;wCACJC,IAAI;oCACN;oCACAS,WAAW,CAACC,GAAGC,cAAgBA,aAAaE,gBAAgB;gCAC9D;4BACF;yBACD;oBACH;oBACA;wBACEjB,MAAM;wBACND,QAAQ;4BACN;gCACED,MAAM;gCACNE,MAAM;gCACNJ,OAAO;oCACLO,IAAI;oCACJC,IAAI;gCACN;gCACAF,cAAc;gCACdnB,SAASP,uBAAuBc,GAAG,CAAC,CAAC4B,SAAY,CAAA;wCAC/CtB,OAAOsB,OAAOtB,KAAK;wCACnBC,OAAOqB,OAAOrB,KAAK;oCACrB,CAAA;gCACAQ,OAAO;oCACLK,OAAO;gCACT;4BACF;4BACA;gCACEZ,MAAM;gCACNE,MAAM;gCACNJ,OAAO;oCACLO,IAAI;oCACJC,IAAI;gCACN;gCACAF,cAAc;gCACdnB,SAASJ,oBAAoBW,GAAG,CAAC,CAAC4B,SAAY,CAAA;wCAC5CtB,OAAOsB,OAAOtB,KAAK;wCACnBC,OAAOqB,OAAOrB,KAAK;oCACrB,CAAA;gCACAQ,OAAO;oCACLK,OAAO;gCACT;4BACF;yBACD;oBACH;iBACD;YACH;SACD;IACH;IAEA,8DAA8D;IAC9D,IAAItB,wBAAwB;QAC1B,MAAM+B,iBAA0B;YAC9B;gBACErB,MAAM;gBACNE,MAAM;gBACNJ,OAAO;oBACLO,IAAI;oBACJC,IAAI;gBACN;gBACAF,cAAc;gBACdnB,SAAS;oBACP;wBAAEa,OAAO;4BAAEO,IAAI;4BAAQC,IAAI;wBAAQ;wBAAGP,OAAO;oBAAO;oBACpD;wBAAED,OAAO;4BAAEO,IAAI;4BAAWC,IAAI;wBAAU;wBAAGP,OAAO;oBAAU;oBAC5D;wBAAED,OAAO;4BAAEO,IAAI;4BAAUC,IAAI;wBAAU;wBAAGP,OAAO;oBAAS;oBAC1D;wBAAED,OAAO;4BAAEO,IAAI;4BAAQC,IAAI;wBAAS;wBAAGP,OAAO;oBAAO;iBACtD;gBACDQ,OAAO;oBACLC,aAAa;wBACXH,IAAI;wBACJC,IAAI;oBACN;oBACAM,OAAO;gBACT;YACF;SACD;QAED,IAAIvB,kBAAkB;YACpBgC,eAAeV,IAAI,CAAC;gBAClBX,MAAM;gBACNE,MAAM;gBACNJ,OAAO;oBACLO,IAAI;oBACJC,IAAI;gBACN;gBACAC,OAAO;oBACLe,UAAU;oBACVd,aAAa;wBACXH,IAAI;wBACJC,IAAI;oBACN;gBAIF;YACF;QACF;QAEAL,OAAOU,IAAI,CAAC;YACVT,MAAM;YACNJ,OAAO;gBACLO,IAAI;gBACJC,IAAI;YACN;YACAC,OAAO;gBACLM,eAAe;YACjB;YACAZ,QAAQoB;QACV;IACF;IAEA,iEAAiE;IACjE,OAAO;QACLvB,OAAO;YACLO,IAAI;YACJC,IAAI;QACN;QACAL,QAAQ;YACN;gBACED,MAAM;gBACNE,MAAM;gBACNK,OAAO;oBACLC,aAAa;wBACXH,IAAI;wBACJC,IAAI;oBACN;gBACF;gBACAL;YACF;SACD;IACH;AACF"}
1
+ {"version":3,"sources":["../../src/fields/themeConfigurationField.ts"],"sourcesContent":["import type { Field, TabsField } from 'payload'\nimport {\n BASE_FONT_SIZE_OPTIONS,\n BODY_FONT_OPTIONS,\n HEADING_FONT_OPTIONS,\n LINE_HEIGHT_OPTIONS,\n} from '../constants/themeFonts.js'\nimport type { ThemePreset } from '../index.js'\nimport { darkModeField, lightModeField } from './colorModeFields.js'\n\ninterface ThemeConfigurationFieldOptions {\n themePresets: ThemePreset[]\n defaultTheme: string\n includeColorModeToggle: boolean\n includeCustomCSS: boolean\n includeBrandIdentity: boolean\n enableAdvancedFeatures?: boolean\n}\n\n// Type for a single tab (not the full TabsField)\nexport type ThemeTab = NonNullable<TabsField['tabs']>[number]\n\n/**\n * Theme Configuration Field with Theme Selection as default value setter\n * Theme Selection populates lightMode/darkMode colors automatically\n */\nexport function createThemeConfigurationField(options: ThemeConfigurationFieldOptions): ThemeTab {\n const {\n themePresets,\n defaultTheme,\n includeColorModeToggle,\n includeCustomCSS,\n enableAdvancedFeatures = true,\n } = options\n\n const fields: Field[] = [\n {\n name: 'theme',\n type: 'text',\n required: true,\n defaultValue: defaultTheme,\n label: {\n en: '🎨 Theme Selection',\n cs: '🎨 Výběr tématu',\n },\n validate: (value: unknown) => {\n if (typeof value === 'string' && value.trim().length > 0) {\n return true\n }\n return 'Select a theme'\n },\n admin: {\n description: {\n en: 'Select a theme to auto-populate color values. You can customize colors after selection.',\n cs: 'Vyberte téma pro automatické předvyplnění barev. Po výběru můžete barvy upravit.',\n },\n components: {\n Field: '@kilivi/payloadcms-theme-management/fields/ThemePreviewField',\n },\n custom: {\n themePresets,\n },\n },\n },\n ]\n\n // Border Radius Configuration - Always visible\n fields.push({\n type: 'row',\n fields: [\n {\n name: 'borderRadius',\n type: 'select',\n label: {\n en: '📐 Border Radius',\n cs: '📐 Zaoblení rohů',\n },\n defaultValue: 'medium',\n options: [\n { label: { en: 'None (0px)', cs: 'Žádné (0px)' }, value: 'none' },\n { label: { en: 'Small (0.25rem)', cs: 'Malé (0.25rem)' }, value: 'small' },\n { label: { en: 'Medium (0.5rem)', cs: 'Střední (0.5rem)' }, value: 'medium' },\n { label: { en: 'Large (0.75rem)', cs: 'Velké (0.75rem)' }, value: 'large' },\n { label: { en: 'XL (1rem)', cs: 'XL (1rem)' }, value: 'xl' },\n ],\n admin: {\n description: {\n en: 'Default corner rounding for UI elements',\n cs: 'Výchozí zaoblení rohů pro UI prvky',\n },\n width: '50%',\n },\n },\n {\n name: 'spacing',\n type: 'select',\n label: {\n en: '📏 Spacing Scale',\n cs: '📏 Škála rozestupů',\n },\n defaultValue: 'medium',\n options: [\n { label: { en: 'Compact', cs: 'Kompaktní' }, value: 'compact' },\n { label: { en: 'Medium', cs: 'Střední' }, value: 'medium' },\n { label: { en: 'Comfortable', cs: 'Pohodlné' }, value: 'comfortable' },\n ],\n admin: {\n description: {\n en: 'Global spacing between elements',\n cs: 'Globální rozestupy mezi prvky',\n },\n width: '50%',\n },\n },\n ],\n })\n\n // Color Mode Settings\n if (includeColorModeToggle) {\n fields.push({\n type: 'collapsible',\n label: {\n en: '🌗 Color Mode Settings',\n cs: '🌗 Nastavení barevného režimu',\n },\n admin: {\n initCollapsed: false,\n description: {\n en: 'Configure light and dark mode colors. Changes here override theme selection.',\n cs: 'Nakonfigurujte barvy světlého a tmavého režimu. Změny zde přepíší výběr tématu.',\n },\n },\n fields: [\n {\n type: 'row',\n fields: [\n {\n name: 'colorMode',\n type: 'select',\n label: {\n en: 'Default Color Mode',\n cs: 'Výchozí barevný režim',\n },\n defaultValue: 'auto',\n options: [\n {\n label: {\n en: 'Auto (System)',\n cs: 'Automaticky (Systém)',\n },\n value: 'auto',\n },\n {\n label: { en: 'Light', cs: 'Světlý' },\n value: 'light',\n },\n {\n label: { en: 'Dark', cs: 'Tmavý' },\n value: 'dark',\n },\n ],\n admin: {\n description: {\n en: 'Default color mode for visitors',\n cs: 'Výchozí barevný režim pro návštěvníky',\n },\n width: '50%',\n },\n },\n {\n name: 'allowColorModeToggle',\n type: 'checkbox',\n label: {\n en: 'Enable Mode Toggle',\n cs: 'Povolit přepínač režimu',\n },\n defaultValue: true,\n admin: {\n description: {\n en: 'Let visitors switch modes',\n cs: 'Umožnit návštěvníkům přepínat režimy',\n },\n width: '50%',\n },\n },\n ],\n },\n lightModeField,\n darkModeField,\n ],\n })\n }\n\n // Typography - Always visible\n fields.push({\n type: 'collapsible',\n label: {\n en: '🅰️ Typography',\n cs: '🅰️ Typografie',\n },\n admin: {\n initCollapsed: true,\n description: {\n en: 'Choose font families and base typography settings. Leave fields on \"Use preset\" to inherit the theme defaults.',\n cs: 'Zvolte rodiny písem a základní typografické nastavení. Hodnota \"Použít výchozí\" zachová nastavení motivu.',\n },\n },\n fields: [\n {\n name: 'typography',\n type: 'group',\n fields: [\n {\n type: 'row',\n fields: [\n {\n name: 'bodyFont',\n type: 'select',\n label: {\n en: 'Body font',\n cs: 'Písmo pro text',\n },\n defaultValue: 'preset',\n // @ts-expect-error - Pass full objects including fontFamily for custom rendering\n options: BODY_FONT_OPTIONS,\n admin: {\n width: '50%',\n components: {\n Field: '@kilivi/payloadcms-theme-management/fields/FontSelectField',\n },\n },\n },\n {\n name: 'headingFont',\n type: 'select',\n label: {\n en: 'Heading font',\n cs: 'Písmo pro nadpisy',\n },\n defaultValue: 'preset',\n // @ts-expect-error - Pass full objects including fontFamily for custom rendering\n options: HEADING_FONT_OPTIONS,\n admin: {\n width: '50%',\n components: {\n Field: '@kilivi/payloadcms-theme-management/fields/FontSelectField',\n },\n },\n },\n ],\n },\n {\n type: 'row',\n fields: [\n {\n name: 'bodyFontCustom',\n type: 'text',\n label: {\n en: 'Custom body font stack',\n cs: 'Vlastní písmo pro text',\n },\n admin: {\n width: '50%',\n placeholder: '\"IBM Plex Sans\", sans-serif',\n description: {\n en: 'Provide full CSS font-family stack when using a custom font.',\n cs: 'Při volbě vlastního písma zadejte celý CSS zápis font-family.',\n },\n condition: (_, siblingData) => siblingData?.bodyFont === 'custom',\n },\n },\n {\n name: 'headingFontCustom',\n type: 'text',\n label: {\n en: 'Custom heading font stack',\n cs: 'Vlastní písmo pro nadpisy',\n },\n admin: {\n width: '50%',\n placeholder: '\"Cormorant Garamond\", serif',\n description: {\n en: 'Provide full CSS font-family stack when using a custom heading font.',\n cs: 'Při volbě vlastního nadpisového písma zadejte celý CSS zápis font-family.',\n },\n condition: (_, siblingData) => siblingData?.headingFont === 'custom',\n },\n },\n ],\n },\n {\n type: 'row',\n fields: [\n {\n name: 'baseFontSize',\n type: 'select',\n label: {\n en: 'Base font size',\n cs: 'Základní velikost písma',\n },\n defaultValue: 'preset',\n options: BASE_FONT_SIZE_OPTIONS.map((option) => ({\n label: option.label,\n value: option.value,\n })),\n admin: {\n width: '50%',\n },\n },\n {\n name: 'lineHeight',\n type: 'select',\n label: {\n en: 'Line height',\n cs: 'Řádkování',\n },\n defaultValue: 'preset',\n options: LINE_HEIGHT_OPTIONS.map((option) => ({\n label: option.label,\n value: option.value,\n })),\n admin: {\n width: '50%',\n },\n },\n ],\n },\n ],\n },\n ],\n })\n\n // Custom Theme Presets importer\n fields.push({\n type: 'collapsible',\n label: {\n en: '🧩 Custom Theme Presets',\n cs: '🧩 Vlastní motivy',\n },\n admin: {\n initCollapsed: true,\n description: {\n en: 'Import additional theme presets via JSON to extend or override the defaults. These presets become available instantly in the Theme Selection above.',\n cs: 'Importujte další motivy pomocí JSONu a rozšiřte nebo přepište výchozí nabídku. Motivy budou ihned k dispozici ve výběru výše.',\n },\n },\n fields: [\n {\n name: 'customThemePresets',\n type: 'json',\n label: {\n en: 'Custom Preset JSON',\n cs: 'JSON s vlastními motivy',\n },\n admin: {\n description: {\n en: 'Paste or import an array (or object map) of theme presets. Each entry should include at least a unique \"name\" and \"label\" with optional lightMode/darkMode colors.',\n cs: 'Vložte nebo importujte pole (či objekt) motivů. Každý motiv musí mít unikátní „name“ a „label“ a volitelně barvy pro světly/tmavý režim.',\n },\n components: {\n Field: '@kilivi/payloadcms-theme-management/fields/ThemePresetImportField',\n },\n },\n },\n ],\n })\n\n // Advanced Settings (when using extended theme configuration)\n if (enableAdvancedFeatures) {\n const advancedFields: Field[] = [\n {\n name: 'animationLevel',\n type: 'select',\n label: {\n en: 'Animation Level',\n cs: 'Úroveň animací',\n },\n defaultValue: 'medium',\n options: [\n { label: { en: 'None', cs: 'Žádné' }, value: 'none' },\n { label: { en: 'Reduced', cs: 'Snížené' }, value: 'reduced' },\n { label: { en: 'Medium', cs: 'Střední' }, value: 'medium' },\n { label: { en: 'High', cs: 'Vysoké' }, value: 'high' },\n ],\n admin: {\n description: {\n en: 'Control website animations and transitions',\n cs: 'Kontrola animací a přechodů na webu',\n },\n width: '50%',\n },\n },\n ]\n\n if (includeCustomCSS) {\n advancedFields.push({\n name: 'customCSS',\n type: 'code',\n label: {\n en: 'Custom CSS',\n cs: 'Vlastní CSS',\n },\n admin: {\n language: 'css',\n description: {\n en: 'Add custom CSS to override default styles',\n cs: 'Přidejte vlastní CSS pro přepsání výchozích stylů',\n },\n // placeholder:\n // ':root {\\n --primary: #your-color;\\n --border-radius: 8px;\\n --font-family: \"Your Font\";\\n}\\n\\n.custom-class {\\n /* Your custom styles */\\n}',\n // rows: 8,\n },\n })\n }\n\n fields.push({\n type: 'collapsible',\n label: {\n en: '⚙️ Advanced Settings',\n cs: '⚙️ Pokročilé nastavení',\n },\n admin: {\n initCollapsed: true,\n },\n fields: advancedFields,\n })\n }\n\n // Return as tab configuration to be injected into tabs structure\n return {\n label: {\n en: '🎨 Appearance Settings',\n cs: '🎨 Nastavení vzhledu',\n },\n fields: [\n {\n name: 'themeConfiguration',\n type: 'group',\n admin: {\n description: {\n en: 'Configure website appearance and styling',\n cs: 'Nakonfigurujte vzhled a stylování webu',\n },\n },\n fields,\n },\n ],\n }\n}\n"],"names":["BASE_FONT_SIZE_OPTIONS","BODY_FONT_OPTIONS","HEADING_FONT_OPTIONS","LINE_HEIGHT_OPTIONS","darkModeField","lightModeField","createThemeConfigurationField","options","themePresets","defaultTheme","includeColorModeToggle","includeCustomCSS","enableAdvancedFeatures","fields","name","type","required","defaultValue","label","en","cs","validate","value","trim","length","admin","description","components","Field","custom","push","width","initCollapsed","placeholder","condition","_","siblingData","bodyFont","headingFont","map","option","advancedFields","language"],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ import type { ThemePreset } from '../presets.js';
2
+ export declare function sanitizeThemePreset(candidate: unknown, fallbackName?: string): ThemePreset | null;
3
+ export declare function parseThemePresetInput(value: unknown): ThemePreset[];
4
+ export declare function mergeThemePresets(base: ThemePreset[], extras: ThemePreset[]): ThemePreset[];
5
+ //# sourceMappingURL=customThemePresets.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"customThemePresets.d.ts","sourceRoot":"","sources":["../../src/utils/customThemePresets.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA;AAmBhD,wBAAgB,mBAAmB,CAAC,SAAS,EAAE,OAAO,EAAE,YAAY,CAAC,EAAE,MAAM,GAAG,WAAW,GAAG,IAAI,CA8BjG;AAED,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,OAAO,GAAG,WAAW,EAAE,CAsCnE;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,WAAW,EAAE,EAAE,MAAM,EAAE,WAAW,EAAE,GAAG,WAAW,EAAE,CAc3F"}
@@ -0,0 +1,82 @@
1
+ function isRecord(value) {
2
+ return typeof value === 'object' && value !== null;
3
+ }
4
+ function normalizeBorderRadius(value) {
5
+ if (value === 'none' || value === 'small' || value === 'medium' || value === 'large' || value === 'xl') {
6
+ return value;
7
+ }
8
+ return 'medium';
9
+ }
10
+ export function sanitizeThemePreset(candidate, fallbackName) {
11
+ if (!isRecord(candidate)) {
12
+ return null;
13
+ }
14
+ const nameCandidate = typeof candidate.name === 'string' ? candidate.name.trim() : fallbackName;
15
+ if (!nameCandidate || nameCandidate.length === 0) {
16
+ return null;
17
+ }
18
+ const labelCandidate = typeof candidate.label === 'string' && candidate.label.trim().length > 0 ? candidate.label.trim() : nameCandidate;
19
+ const lightMode = isRecord(candidate.lightMode) ? candidate.lightMode : {};
20
+ const darkMode = isRecord(candidate.darkMode) ? candidate.darkMode : {};
21
+ return {
22
+ ...candidate,
23
+ name: nameCandidate,
24
+ label: labelCandidate,
25
+ borderRadius: normalizeBorderRadius(candidate.borderRadius),
26
+ lightMode,
27
+ darkMode
28
+ };
29
+ }
30
+ export function parseThemePresetInput(value) {
31
+ if (!value) return [];
32
+ const presets = [];
33
+ const pushPreset = (candidate, fallbackName)=>{
34
+ const preset = sanitizeThemePreset(candidate, fallbackName);
35
+ if (preset) {
36
+ presets.push(preset);
37
+ }
38
+ };
39
+ if (typeof value === 'string') {
40
+ try {
41
+ const parsed = JSON.parse(value);
42
+ return parseThemePresetInput(parsed);
43
+ } catch {
44
+ return [];
45
+ }
46
+ }
47
+ if (Array.isArray(value)) {
48
+ value.forEach((candidate, index)=>pushPreset(candidate, `custom-${index + 1}`));
49
+ return presets;
50
+ }
51
+ if (isRecord(value)) {
52
+ Object.entries(value).forEach(([key, candidate])=>{
53
+ if (isRecord(candidate)) {
54
+ pushPreset({
55
+ ...candidate,
56
+ name: candidate.name ?? key
57
+ }, key);
58
+ } else {
59
+ pushPreset(candidate, key);
60
+ }
61
+ });
62
+ return presets;
63
+ }
64
+ return [];
65
+ }
66
+ export function mergeThemePresets(base, extras) {
67
+ if (!extras.length) return base;
68
+ const map = new Map();
69
+ base.forEach((preset)=>{
70
+ if (preset?.name) {
71
+ map.set(preset.name, preset);
72
+ }
73
+ });
74
+ extras.forEach((preset)=>{
75
+ if (preset?.name) {
76
+ map.set(preset.name, preset);
77
+ }
78
+ });
79
+ return Array.from(map.values());
80
+ }
81
+
82
+ //# sourceMappingURL=customThemePresets.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/utils/customThemePresets.ts"],"sourcesContent":["import type { ThemePreset } from '../presets.js'\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null\n}\n\nfunction normalizeBorderRadius(value: unknown): ThemePreset['borderRadius'] {\n if (\n value === 'none' ||\n value === 'small' ||\n value === 'medium' ||\n value === 'large' ||\n value === 'xl'\n ) {\n return value\n }\n return 'medium'\n}\n\nexport function sanitizeThemePreset(candidate: unknown, fallbackName?: string): ThemePreset | null {\n if (!isRecord(candidate)) {\n return null\n }\n\n const nameCandidate = typeof candidate.name === 'string' ? candidate.name.trim() : fallbackName\n if (!nameCandidate || nameCandidate.length === 0) {\n return null\n }\n\n const labelCandidate =\n typeof candidate.label === 'string' && candidate.label.trim().length > 0\n ? candidate.label.trim()\n : nameCandidate\n\n const lightMode = isRecord(candidate.lightMode)\n ? (candidate.lightMode as Record<string, string>)\n : {}\n const darkMode = isRecord(candidate.darkMode)\n ? (candidate.darkMode as Record<string, string>)\n : {}\n\n return {\n ...candidate,\n name: nameCandidate,\n label: labelCandidate,\n borderRadius: normalizeBorderRadius(candidate.borderRadius),\n lightMode,\n darkMode,\n } as ThemePreset\n}\n\nexport function parseThemePresetInput(value: unknown): ThemePreset[] {\n if (!value) return []\n\n const presets: ThemePreset[] = []\n\n const pushPreset = (candidate: unknown, fallbackName?: string) => {\n const preset = sanitizeThemePreset(candidate, fallbackName)\n if (preset) {\n presets.push(preset)\n }\n }\n\n if (typeof value === 'string') {\n try {\n const parsed = JSON.parse(value)\n return parseThemePresetInput(parsed)\n } catch {\n return []\n }\n }\n\n if (Array.isArray(value)) {\n value.forEach((candidate, index) => pushPreset(candidate, `custom-${index + 1}`))\n return presets\n }\n\n if (isRecord(value)) {\n Object.entries(value).forEach(([key, candidate]) => {\n if (isRecord(candidate)) {\n pushPreset({ ...candidate, name: candidate.name ?? key }, key)\n } else {\n pushPreset(candidate, key)\n }\n })\n return presets\n }\n\n return []\n}\n\nexport function mergeThemePresets(base: ThemePreset[], extras: ThemePreset[]): ThemePreset[] {\n if (!extras.length) return base\n const map = new Map<string, ThemePreset>()\n base.forEach((preset) => {\n if (preset?.name) {\n map.set(preset.name, preset)\n }\n })\n extras.forEach((preset) => {\n if (preset?.name) {\n map.set(preset.name, preset)\n }\n })\n return Array.from(map.values())\n}\n"],"names":["isRecord","value","normalizeBorderRadius","sanitizeThemePreset","candidate","fallbackName","nameCandidate","name","trim","length","labelCandidate","label","lightMode","darkMode","borderRadius","parseThemePresetInput","presets","pushPreset","preset","push","parsed","JSON","parse","Array","isArray","forEach","index","Object","entries","key","mergeThemePresets","base","extras","map","Map","set","from","values"],"mappings":"AAEA,SAASA,SAASC,KAAc;IAC9B,OAAO,OAAOA,UAAU,YAAYA,UAAU;AAChD;AAEA,SAASC,sBAAsBD,KAAc;IAC3C,IACEA,UAAU,UACVA,UAAU,WACVA,UAAU,YACVA,UAAU,WACVA,UAAU,MACV;QACA,OAAOA;IACT;IACA,OAAO;AACT;AAEA,OAAO,SAASE,oBAAoBC,SAAkB,EAAEC,YAAqB;IAC3E,IAAI,CAACL,SAASI,YAAY;QACxB,OAAO;IACT;IAEA,MAAME,gBAAgB,OAAOF,UAAUG,IAAI,KAAK,WAAWH,UAAUG,IAAI,CAACC,IAAI,KAAKH;IACnF,IAAI,CAACC,iBAAiBA,cAAcG,MAAM,KAAK,GAAG;QAChD,OAAO;IACT;IAEA,MAAMC,iBACJ,OAAON,UAAUO,KAAK,KAAK,YAAYP,UAAUO,KAAK,CAACH,IAAI,GAAGC,MAAM,GAAG,IACnEL,UAAUO,KAAK,CAACH,IAAI,KACpBF;IAEN,MAAMM,YAAYZ,SAASI,UAAUQ,SAAS,IACzCR,UAAUQ,SAAS,GACpB,CAAC;IACL,MAAMC,WAAWb,SAASI,UAAUS,QAAQ,IACvCT,UAAUS,QAAQ,GACnB,CAAC;IAEL,OAAO;QACL,GAAGT,SAAS;QACZG,MAAMD;QACNK,OAAOD;QACPI,cAAcZ,sBAAsBE,UAAUU,YAAY;QAC1DF;QACAC;IACF;AACF;AAEA,OAAO,SAASE,sBAAsBd,KAAc;IAClD,IAAI,CAACA,OAAO,OAAO,EAAE;IAErB,MAAMe,UAAyB,EAAE;IAEjC,MAAMC,aAAa,CAACb,WAAoBC;QACtC,MAAMa,SAASf,oBAAoBC,WAAWC;QAC9C,IAAIa,QAAQ;YACVF,QAAQG,IAAI,CAACD;QACf;IACF;IAEA,IAAI,OAAOjB,UAAU,UAAU;QAC7B,IAAI;YACF,MAAMmB,SAASC,KAAKC,KAAK,CAACrB;YAC1B,OAAOc,sBAAsBK;QAC/B,EAAE,OAAM;YACN,OAAO,EAAE;QACX;IACF;IAEA,IAAIG,MAAMC,OAAO,CAACvB,QAAQ;QACxBA,MAAMwB,OAAO,CAAC,CAACrB,WAAWsB,QAAUT,WAAWb,WAAW,CAAC,OAAO,EAAEsB,QAAQ,GAAG;QAC/E,OAAOV;IACT;IAEA,IAAIhB,SAASC,QAAQ;QACnB0B,OAAOC,OAAO,CAAC3B,OAAOwB,OAAO,CAAC,CAAC,CAACI,KAAKzB,UAAU;YAC7C,IAAIJ,SAASI,YAAY;gBACvBa,WAAW;oBAAE,GAAGb,SAAS;oBAAEG,MAAMH,UAAUG,IAAI,IAAIsB;gBAAI,GAAGA;YAC5D,OAAO;gBACLZ,WAAWb,WAAWyB;YACxB;QACF;QACA,OAAOb;IACT;IAEA,OAAO,EAAE;AACX;AAEA,OAAO,SAASc,kBAAkBC,IAAmB,EAAEC,MAAqB;IAC1E,IAAI,CAACA,OAAOvB,MAAM,EAAE,OAAOsB;IAC3B,MAAME,MAAM,IAAIC;IAChBH,KAAKN,OAAO,CAAC,CAACP;QACZ,IAAIA,QAAQX,MAAM;YAChB0B,IAAIE,GAAG,CAACjB,OAAOX,IAAI,EAAEW;QACvB;IACF;IACAc,OAAOP,OAAO,CAAC,CAACP;QACd,IAAIA,QAAQX,MAAM;YAChB0B,IAAIE,GAAG,CAACjB,OAAOX,IAAI,EAAEW;QACvB;IACF;IACA,OAAOK,MAAMa,IAAI,CAACH,IAAII,MAAM;AAC9B"}
@@ -115,5 +115,5 @@ export declare function createUseExtendedTheme(presets: Record<string, ExtendedT
115
115
  * }
116
116
  * ```
117
117
  */
118
- export declare function getTailwindVarReferences(): any;
118
+ export declare function getTailwindVarReferences(): Record<string, unknown>;
119
119
  //# sourceMappingURL=extendedThemeHelpers.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"extendedThemeHelpers.d.ts","sourceRoot":"","sources":["../../src/utils/extendedThemeHelpers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAA;AAGpF;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,kBAAkB,CAChC,KAAK,EAAE,mBAAmB,EAC1B,IAAI,GAAE,OAAO,GAAG,MAAgB,GAC/B,IAAI,CAaN;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,mBAAmB,GAAG,MAAM,CAU3E;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,kBAAkB,IAAI,IAAI,CAgBzC;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,sBAAsB,CAAC,CAAC,SAAS,MAAM,iBAAiB,EACtE,KAAK,EAAE,mBAAmB,EAC1B,IAAI,EAAE,OAAO,GAAG,MAAM,EACtB,IAAI,EAAE,CAAC,EAAE,GACR,IAAI,CAAC,iBAAiB,EAAE,CAAC,CAAC,CAW5B;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,mBAAmB,CAAC;;;2BAK/B,MAAM,QAAQ,OAAO,GAAG,MAAM;;EAmBjF;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,wBAAwB,IAAI,GAAG,CA2C9C"}
1
+ {"version":3,"file":"extendedThemeHelpers.d.ts","sourceRoot":"","sources":["../../src/utils/extendedThemeHelpers.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAA;AAEpF;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,kBAAkB,CAChC,KAAK,EAAE,mBAAmB,EAC1B,IAAI,GAAE,OAAO,GAAG,MAAgB,GAC/B,IAAI,CAaN;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,mBAAmB,GAAG,MAAM,CAU3E;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,kBAAkB,IAAI,IAAI,CAqCzC;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,sBAAsB,CAAC,CAAC,SAAS,MAAM,iBAAiB,EACtE,KAAK,EAAE,mBAAmB,EAC1B,IAAI,EAAE,OAAO,GAAG,MAAM,EACtB,IAAI,EAAE,CAAC,EAAE,GACR,IAAI,CAAC,iBAAiB,EAAE,CAAC,CAAC,CAW5B;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,mBAAmB,CAAC;;;2BAK/B,MAAM,QAAQ,OAAO,GAAG,MAAM;;EAmBjF;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,wBAAwB,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CA2ClE"}
@@ -2,15 +2,15 @@ import * as React from 'react';
2
2
  /**
3
3
  * Apply an extended theme client-side by setting CSS variables on document.documentElement
4
4
  * Works exactly like silicondeck/shadcn-dashboard-landing-template's useThemeManager
5
- *
5
+ *
6
6
  * @example
7
7
  * ```tsx
8
8
  * import { extendedThemePresets, applyExtendedTheme } from '@kilivi/payloadcms-theme-management'
9
- *
9
+ *
10
10
  * // In a client component or hook
11
11
  * function useExtendedTheme() {
12
12
  * const isDark = document.documentElement.classList.contains('dark')
13
- *
13
+ *
14
14
  * useEffect(() => {
15
15
  * applyExtendedTheme(extendedThemePresets['cool-extended'], isDark ? 'dark' : 'light')
16
16
  * }, [isDark])
@@ -31,14 +31,14 @@ import * as React from 'react';
31
31
  /**
32
32
  * Generate CSS content for globals.css
33
33
  * Add this to your globals.css file to define base theme variables
34
- *
34
+ *
35
35
  * @example
36
36
  * ```tsx
37
37
  * import { extendedThemePresets, generateExtendedThemeCSS } from '@kilivi/payloadcms-theme-management'
38
- *
38
+ *
39
39
  * // Generate CSS for cool-extended theme
40
40
  * const css = generateExtendedThemeCSS(extendedThemePresets['cool-extended'])
41
- *
41
+ *
42
42
  * // Copy this to your globals.css:
43
43
  * // :root {
44
44
  * // --background: oklch(...);
@@ -57,11 +57,11 @@ import * as React from 'react';
57
57
  /**
58
58
  * Reset all extended theme CSS variables
59
59
  * Useful when switching between themes or resetting to defaults
60
- *
60
+ *
61
61
  * @example
62
62
  * ```tsx
63
63
  * import { resetExtendedTheme } from '@kilivi/payloadcms-theme-management'
64
- *
64
+ *
65
65
  * // Remove all extended theme variables
66
66
  * resetExtendedTheme()
67
67
  * ```
@@ -104,11 +104,11 @@ import * as React from 'react';
104
104
  /**
105
105
  * Extract specific color tokens from an extended theme
106
106
  * Useful when you only need a subset of theme colors
107
- *
107
+ *
108
108
  * @example
109
109
  * ```tsx
110
110
  * import { extendedThemePresets, getExtendedThemeTokens } from '@kilivi/payloadcms-theme-management'
111
- *
111
+ *
112
112
  * const chartColors = getExtendedThemeTokens(
113
113
  * extendedThemePresets['cool-extended'],
114
114
  * 'light',
@@ -128,16 +128,16 @@ import * as React from 'react';
128
128
  /**
129
129
  * Create a React hook for theme management
130
130
  * Factory function to create a custom hook tied to your theme system
131
- *
131
+ *
132
132
  * @example
133
133
  * ```tsx
134
134
  * import { extendedThemePresets, createUseExtendedTheme } from '@kilivi/payloadcms-theme-management'
135
- *
135
+ *
136
136
  * const useExtendedTheme = createUseExtendedTheme(extendedThemePresets)
137
- *
137
+ *
138
138
  * function MyComponent() {
139
139
  * const { applyTheme, currentMode } = useExtendedTheme()
140
- *
140
+ *
141
141
  * return (
142
142
  * <button onClick={() => applyTheme('neon-extended', 'dark')}>
143
143
  * Apply Neon Dark
@@ -170,12 +170,12 @@ import * as React from 'react';
170
170
  /**
171
171
  * Get Tailwind CSS color references for extended themes
172
172
  * Use this in your tailwind.config.ts to enable semantic color classes
173
- *
173
+ *
174
174
  * @example
175
175
  * ```ts
176
176
  * // tailwind.config.ts
177
177
  * import { getTailwindVarReferences } from '@kilivi/payloadcms-theme-management'
178
- *
178
+ *
179
179
  * export default {
180
180
  * theme: {
181
181
  * extend: {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/utils/extendedThemeHelpers.ts"],"sourcesContent":["import type { ExtendedThemePreset, ShadcnColorTokens } from '../extended-presets.js'\nimport * as React from 'react'\n\n/**\n * Apply an extended theme client-side by setting CSS variables on document.documentElement\n * Works exactly like silicondeck/shadcn-dashboard-landing-template's useThemeManager\n * \n * @example\n * ```tsx\n * import { extendedThemePresets, applyExtendedTheme } from '@kilivi/payloadcms-theme-management'\n * \n * // In a client component or hook\n * function useExtendedTheme() {\n * const isDark = document.documentElement.classList.contains('dark')\n * \n * useEffect(() => {\n * applyExtendedTheme(extendedThemePresets['cool-extended'], isDark ? 'dark' : 'light')\n * }, [isDark])\n * }\n * ```\n */\nexport function applyExtendedTheme(\n theme: ExtendedThemePreset,\n mode: 'light' | 'dark' = 'light'\n): void {\n if (typeof document === 'undefined') {\n console.warn('applyExtendedTheme can only be called in browser environment')\n return\n }\n \n const tokens = theme.styles[mode]\n const root = document.documentElement\n \n // Apply CSS variables to document root (same as silicondeck's approach)\n Object.entries(tokens).forEach(([key, value]) => {\n root.style.setProperty(`--${key}`, value)\n })\n}\n\n/**\n * Generate CSS content for globals.css\n * Add this to your globals.css file to define base theme variables\n * \n * @example\n * ```tsx\n * import { extendedThemePresets, generateExtendedThemeCSS } from '@kilivi/payloadcms-theme-management'\n * \n * // Generate CSS for cool-extended theme\n * const css = generateExtendedThemeCSS(extendedThemePresets['cool-extended'])\n * \n * // Copy this to your globals.css:\n * // :root {\n * // --background: oklch(...);\n * // ...\n * // }\n * // .dark {\n * // --background: oklch(...);\n * // ...\n * // }\n * ```\n */\nexport function generateExtendedThemeCSS(theme: ExtendedThemePreset): string {\n const lightVars = Object.entries(theme.styles.light)\n .map(([key, value]) => ` --${key}: ${value};`)\n .join('\\n')\n\n const darkVars = Object.entries(theme.styles.dark)\n .map(([key, value]) => ` --${key}: ${value};`)\n .join('\\n')\n\n return `:root {\\n${lightVars}\\n}\\n\\n.dark {\\n${darkVars}\\n}`\n}\n\n/**\n * Reset all extended theme CSS variables\n * Useful when switching between themes or resetting to defaults\n * \n * @example\n * ```tsx\n * import { resetExtendedTheme } from '@kilivi/payloadcms-theme-management'\n * \n * // Remove all extended theme variables\n * resetExtendedTheme()\n * ```\n */\nexport function resetExtendedTheme(): void {\n if (typeof document === 'undefined') return\n\n const root = document.documentElement\n const allVars = [\n 'background', 'foreground', 'card', 'card-foreground', 'popover', 'popover-foreground',\n 'primary', 'primary-foreground', 'secondary', 'secondary-foreground',\n 'muted', 'muted-foreground', 'accent', 'accent-foreground',\n 'destructive', 'destructive-foreground', 'border', 'input', 'ring',\n 'chart-1', 'chart-2', 'chart-3', 'chart-4', 'chart-5',\n 'radius', 'font-sans', 'font-mono'\n ]\n\n allVars.forEach(varName => {\n root.style.removeProperty(`--${varName}`)\n })\n}\n\n/**\n * Extract specific color tokens from an extended theme\n * Useful when you only need a subset of theme colors\n * \n * @example\n * ```tsx\n * import { extendedThemePresets, getExtendedThemeTokens } from '@kilivi/payloadcms-theme-management'\n * \n * const chartColors = getExtendedThemeTokens(\n * extendedThemePresets['cool-extended'],\n * 'light',\n * ['chart-1', 'chart-2', 'chart-3', 'chart-4', 'chart-5']\n * )\n * ```\n */\nexport function getExtendedThemeTokens<K extends keyof ShadcnColorTokens>(\n theme: ExtendedThemePreset,\n mode: 'light' | 'dark',\n keys: K[]\n): Pick<ShadcnColorTokens, K> {\n const tokens = theme.styles[mode]\n const result = {} as Pick<ShadcnColorTokens, K>\n \n keys.forEach(key => {\n if (tokens[key]) {\n result[key] = tokens[key]\n }\n })\n \n return result\n}\n\n/**\n * Create a React hook for theme management\n * Factory function to create a custom hook tied to your theme system\n * \n * @example\n * ```tsx\n * import { extendedThemePresets, createUseExtendedTheme } from '@kilivi/payloadcms-theme-management'\n * \n * const useExtendedTheme = createUseExtendedTheme(extendedThemePresets)\n * \n * function MyComponent() {\n * const { applyTheme, currentMode } = useExtendedTheme()\n * \n * return (\n * <button onClick={() => applyTheme('neon-extended', 'dark')}>\n * Apply Neon Dark\n * </button>\n * )\n * }\n * ```\n */\nexport function createUseExtendedTheme(presets: Record<string, ExtendedThemePreset>) {\n return function useExtendedTheme() {\n const [currentTheme, setCurrentTheme] = React.useState<string>('default')\n const [currentMode, setCurrentMode] = React.useState<'light' | 'dark'>('light')\n\n const applyTheme = React.useCallback((themeKey: string, mode: 'light' | 'dark') => {\n const theme = presets[themeKey]\n if (!theme) {\n console.warn(`Theme \"${themeKey}\" not found`)\n return\n }\n\n applyExtendedTheme(theme, mode)\n setCurrentTheme(themeKey)\n setCurrentMode(mode)\n }, [])\n\n return {\n currentTheme,\n currentMode,\n applyTheme,\n resetTheme: resetExtendedTheme\n }\n }\n}\n\n/**\n * Get Tailwind CSS color references for extended themes\n * Use this in your tailwind.config.ts to enable semantic color classes\n * \n * @example\n * ```ts\n * // tailwind.config.ts\n * import { getTailwindVarReferences } from '@kilivi/payloadcms-theme-management'\n * \n * export default {\n * theme: {\n * extend: {\n * colors: getTailwindVarReferences()\n * }\n * }\n * }\n * ```\n */\nexport function getTailwindVarReferences(): any {\n return {\n background: 'hsl(var(--background))',\n foreground: 'hsl(var(--foreground))',\n card: {\n DEFAULT: 'hsl(var(--card))',\n foreground: 'hsl(var(--card-foreground))',\n },\n popover: {\n DEFAULT: 'hsl(var(--popover))',\n foreground: 'hsl(var(--popover-foreground))',\n },\n primary: {\n DEFAULT: 'hsl(var(--primary))',\n foreground: 'hsl(var(--primary-foreground))',\n },\n secondary: {\n DEFAULT: 'hsl(var(--secondary))',\n foreground: 'hsl(var(--secondary-foreground))',\n },\n muted: {\n DEFAULT: 'hsl(var(--muted))',\n foreground: 'hsl(var(--muted-foreground))',\n },\n accent: {\n DEFAULT: 'hsl(var(--accent))',\n foreground: 'hsl(var(--accent-foreground))',\n },\n destructive: {\n DEFAULT: 'hsl(var(--destructive))',\n foreground: 'hsl(var(--destructive-foreground))',\n },\n border: 'hsl(var(--border))',\n input: 'hsl(var(--input))',\n ring: 'hsl(var(--ring))',\n chart: {\n '1': 'hsl(var(--chart-1))',\n '2': 'hsl(var(--chart-2))',\n '3': 'hsl(var(--chart-3))',\n '4': 'hsl(var(--chart-4))',\n '5': 'hsl(var(--chart-5))',\n },\n }\n}\n"],"names":["React","applyExtendedTheme","theme","mode","document","console","warn","tokens","styles","root","documentElement","Object","entries","forEach","key","value","style","setProperty","generateExtendedThemeCSS","lightVars","light","map","join","darkVars","dark","resetExtendedTheme","allVars","varName","removeProperty","getExtendedThemeTokens","keys","result","createUseExtendedTheme","presets","useExtendedTheme","currentTheme","setCurrentTheme","useState","currentMode","setCurrentMode","applyTheme","useCallback","themeKey","resetTheme","getTailwindVarReferences","background","foreground","card","DEFAULT","popover","primary","secondary","muted","accent","destructive","border","input","ring","chart"],"mappings":"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"}
1
+ {"version":3,"sources":["../../src/utils/extendedThemeHelpers.ts"],"sourcesContent":["import * as React from 'react'\nimport type { ExtendedThemePreset, ShadcnColorTokens } from '../extended-presets.js'\n\n/**\n * Apply an extended theme client-side by setting CSS variables on document.documentElement\n * Works exactly like silicondeck/shadcn-dashboard-landing-template's useThemeManager\n *\n * @example\n * ```tsx\n * import { extendedThemePresets, applyExtendedTheme } from '@kilivi/payloadcms-theme-management'\n *\n * // In a client component or hook\n * function useExtendedTheme() {\n * const isDark = document.documentElement.classList.contains('dark')\n *\n * useEffect(() => {\n * applyExtendedTheme(extendedThemePresets['cool-extended'], isDark ? 'dark' : 'light')\n * }, [isDark])\n * }\n * ```\n */\nexport function applyExtendedTheme(\n theme: ExtendedThemePreset,\n mode: 'light' | 'dark' = 'light',\n): void {\n if (typeof document === 'undefined') {\n console.warn('applyExtendedTheme can only be called in browser environment')\n return\n }\n\n const tokens = theme.styles[mode]\n const root = document.documentElement\n\n // Apply CSS variables to document root (same as silicondeck's approach)\n Object.entries(tokens).forEach(([key, value]) => {\n root.style.setProperty(`--${key}`, value)\n })\n}\n\n/**\n * Generate CSS content for globals.css\n * Add this to your globals.css file to define base theme variables\n *\n * @example\n * ```tsx\n * import { extendedThemePresets, generateExtendedThemeCSS } from '@kilivi/payloadcms-theme-management'\n *\n * // Generate CSS for cool-extended theme\n * const css = generateExtendedThemeCSS(extendedThemePresets['cool-extended'])\n *\n * // Copy this to your globals.css:\n * // :root {\n * // --background: oklch(...);\n * // ...\n * // }\n * // .dark {\n * // --background: oklch(...);\n * // ...\n * // }\n * ```\n */\nexport function generateExtendedThemeCSS(theme: ExtendedThemePreset): string {\n const lightVars = Object.entries(theme.styles.light)\n .map(([key, value]) => ` --${key}: ${value};`)\n .join('\\n')\n\n const darkVars = Object.entries(theme.styles.dark)\n .map(([key, value]) => ` --${key}: ${value};`)\n .join('\\n')\n\n return `:root {\\n${lightVars}\\n}\\n\\n.dark {\\n${darkVars}\\n}`\n}\n\n/**\n * Reset all extended theme CSS variables\n * Useful when switching between themes or resetting to defaults\n *\n * @example\n * ```tsx\n * import { resetExtendedTheme } from '@kilivi/payloadcms-theme-management'\n *\n * // Remove all extended theme variables\n * resetExtendedTheme()\n * ```\n */\nexport function resetExtendedTheme(): void {\n if (typeof document === 'undefined') return\n\n const root = document.documentElement\n const allVars = [\n 'background',\n 'foreground',\n 'card',\n 'card-foreground',\n 'popover',\n 'popover-foreground',\n 'primary',\n 'primary-foreground',\n 'secondary',\n 'secondary-foreground',\n 'muted',\n 'muted-foreground',\n 'accent',\n 'accent-foreground',\n 'destructive',\n 'destructive-foreground',\n 'border',\n 'input',\n 'ring',\n 'chart-1',\n 'chart-2',\n 'chart-3',\n 'chart-4',\n 'chart-5',\n 'radius',\n 'font-sans',\n 'font-mono',\n ]\n\n allVars.forEach((varName) => {\n root.style.removeProperty(`--${varName}`)\n })\n}\n\n/**\n * Extract specific color tokens from an extended theme\n * Useful when you only need a subset of theme colors\n *\n * @example\n * ```tsx\n * import { extendedThemePresets, getExtendedThemeTokens } from '@kilivi/payloadcms-theme-management'\n *\n * const chartColors = getExtendedThemeTokens(\n * extendedThemePresets['cool-extended'],\n * 'light',\n * ['chart-1', 'chart-2', 'chart-3', 'chart-4', 'chart-5']\n * )\n * ```\n */\nexport function getExtendedThemeTokens<K extends keyof ShadcnColorTokens>(\n theme: ExtendedThemePreset,\n mode: 'light' | 'dark',\n keys: K[],\n): Pick<ShadcnColorTokens, K> {\n const tokens = theme.styles[mode]\n const result = {} as Pick<ShadcnColorTokens, K>\n\n keys.forEach((key) => {\n if (tokens[key]) {\n result[key] = tokens[key]\n }\n })\n\n return result\n}\n\n/**\n * Create a React hook for theme management\n * Factory function to create a custom hook tied to your theme system\n *\n * @example\n * ```tsx\n * import { extendedThemePresets, createUseExtendedTheme } from '@kilivi/payloadcms-theme-management'\n *\n * const useExtendedTheme = createUseExtendedTheme(extendedThemePresets)\n *\n * function MyComponent() {\n * const { applyTheme, currentMode } = useExtendedTheme()\n *\n * return (\n * <button onClick={() => applyTheme('neon-extended', 'dark')}>\n * Apply Neon Dark\n * </button>\n * )\n * }\n * ```\n */\nexport function createUseExtendedTheme(presets: Record<string, ExtendedThemePreset>) {\n return function useExtendedTheme() {\n const [currentTheme, setCurrentTheme] = React.useState<string>('default')\n const [currentMode, setCurrentMode] = React.useState<'light' | 'dark'>('light')\n\n const applyTheme = React.useCallback((themeKey: string, mode: 'light' | 'dark') => {\n const theme = presets[themeKey]\n if (!theme) {\n console.warn(`Theme \"${themeKey}\" not found`)\n return\n }\n\n applyExtendedTheme(theme, mode)\n setCurrentTheme(themeKey)\n setCurrentMode(mode)\n }, [])\n\n return {\n currentTheme,\n currentMode,\n applyTheme,\n resetTheme: resetExtendedTheme,\n }\n }\n}\n\n/**\n * Get Tailwind CSS color references for extended themes\n * Use this in your tailwind.config.ts to enable semantic color classes\n *\n * @example\n * ```ts\n * // tailwind.config.ts\n * import { getTailwindVarReferences } from '@kilivi/payloadcms-theme-management'\n *\n * export default {\n * theme: {\n * extend: {\n * colors: getTailwindVarReferences()\n * }\n * }\n * }\n * ```\n */\nexport function getTailwindVarReferences(): Record<string, unknown> {\n return {\n background: 'hsl(var(--background))',\n foreground: 'hsl(var(--foreground))',\n card: {\n DEFAULT: 'hsl(var(--card))',\n foreground: 'hsl(var(--card-foreground))',\n },\n popover: {\n DEFAULT: 'hsl(var(--popover))',\n foreground: 'hsl(var(--popover-foreground))',\n },\n primary: {\n DEFAULT: 'hsl(var(--primary))',\n foreground: 'hsl(var(--primary-foreground))',\n },\n secondary: {\n DEFAULT: 'hsl(var(--secondary))',\n foreground: 'hsl(var(--secondary-foreground))',\n },\n muted: {\n DEFAULT: 'hsl(var(--muted))',\n foreground: 'hsl(var(--muted-foreground))',\n },\n accent: {\n DEFAULT: 'hsl(var(--accent))',\n foreground: 'hsl(var(--accent-foreground))',\n },\n destructive: {\n DEFAULT: 'hsl(var(--destructive))',\n foreground: 'hsl(var(--destructive-foreground))',\n },\n border: 'hsl(var(--border))',\n input: 'hsl(var(--input))',\n ring: 'hsl(var(--ring))',\n chart: {\n '1': 'hsl(var(--chart-1))',\n '2': 'hsl(var(--chart-2))',\n '3': 'hsl(var(--chart-3))',\n '4': 'hsl(var(--chart-4))',\n '5': 'hsl(var(--chart-5))',\n },\n }\n}\n"],"names":["React","applyExtendedTheme","theme","mode","document","console","warn","tokens","styles","root","documentElement","Object","entries","forEach","key","value","style","setProperty","generateExtendedThemeCSS","lightVars","light","map","join","darkVars","dark","resetExtendedTheme","allVars","varName","removeProperty","getExtendedThemeTokens","keys","result","createUseExtendedTheme","presets","useExtendedTheme","currentTheme","setCurrentTheme","useState","currentMode","setCurrentMode","applyTheme","useCallback","themeKey","resetTheme","getTailwindVarReferences","background","foreground","card","DEFAULT","popover","primary","secondary","muted","accent","destructive","border","input","ring","chart"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kilivi/payloadcms-theme-management",
3
- "version": "0.5.7",
3
+ "version": "0.5.8",
4
4
  "description": "Theme configuration plugin for Payload CMS v3 with 60+ professional themes",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -55,6 +55,7 @@
55
55
  "peerDependencies": {
56
56
  "payload": "^3.0.0",
57
57
  "@payloadcms/ui": "^3.0.0",
58
+ "next": "^14.0.0 || ^15.0.0",
58
59
  "react": "^18.3.0 || ^19.0.0-rc",
59
60
  "react-dom": "^18.3.0 || ^19.0.0-rc"
60
61
  },
@@ -76,6 +77,7 @@
76
77
  "jest": "^30.2.0",
77
78
  "jest-environment-jsdom": "^30.2.0",
78
79
  "mongodb-memory-server": "^10.2.3",
80
+ "next": "^15.0.0",
79
81
  "payload": "^3.58.0",
80
82
  "playwright": "^1.56.0",
81
83
  "postcss": "^8.5.0",