@kilivi/payloadcms-theme-management 1.0.2 → 1.0.4
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.
- package/README.md +4 -0
- package/dist/components/ThemePreview.d.ts.map +1 -1
- package/dist/components/ThemePreview.js +15 -12
- package/dist/components/ThemePreview.js.map +1 -1
- package/dist/constants/themeFonts.d.ts +68 -17
- package/dist/constants/themeFonts.d.ts.map +1 -1
- package/dist/constants/themeFonts.js +68 -17
- package/dist/constants/themeFonts.js.map +1 -1
- package/dist/fields/FontSelectField.d.ts.map +1 -1
- package/dist/fields/FontSelectField.js +44 -7
- package/dist/fields/FontSelectField.js.map +1 -1
- package/dist/fields/ThemePreviewField.d.ts.map +1 -1
- package/dist/fields/ThemePreviewField.js +35 -29
- package/dist/fields/ThemePreviewField.js.map +1 -1
- package/dist/fields/ThemeTokenSelectField.d.ts.map +1 -1
- package/dist/fields/ThemeTokenSelectField.js +0 -1
- package/dist/fields/ThemeTokenSelectField.js.map +1 -1
- package/dist/globals/ThemeSettings/FontPicker/FontPreview.d.ts.map +1 -1
- package/dist/globals/ThemeSettings/FontPicker/FontPreview.js +7 -4
- package/dist/globals/ThemeSettings/FontPicker/FontPreview.js.map +1 -1
- package/dist/globals/ThemeSettings/config.d.ts.map +1 -1
- package/dist/globals/ThemeSettings/config.js +32 -8
- package/dist/globals/ThemeSettings/config.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +29 -12
- package/dist/index.js.map +1 -1
- package/dist/providers/font-loader.d.ts +1 -1
- package/dist/providers/font-loader.d.ts.map +1 -1
- package/dist/providers/font-loader.js.map +1 -1
- package/dist/translations.d.ts +49 -0
- package/dist/translations.d.ts.map +1 -0
- package/dist/translations.js +121 -0
- package/dist/translations.js.map +1 -0
- package/dist/types/jest-axe.d.js +2 -0
- package/dist/types/jest-axe.d.js.map +1 -0
- package/dist/types/payload-ui.d.js +2 -0
- package/dist/types/payload-ui.d.js.map +1 -0
- package/dist/utilities/getThemeSettings.d.ts.map +1 -1
- package/dist/utilities/getThemeSettings.js +8 -2
- package/dist/utilities/getThemeSettings.js.map +1 -1
- package/dist/utils/getAdminLanguage.d.ts +2 -0
- package/dist/utils/getAdminLanguage.d.ts.map +1 -0
- package/dist/utils/getAdminLanguage.js +21 -0
- package/dist/utils/getAdminLanguage.js.map +1 -0
- package/package.json +22 -4
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
3
|
import { useField } from '@payloadcms/ui';
|
|
4
4
|
import { useEffect, useState } from 'react';
|
|
5
|
+
import { getTranslations } from '../translations.js';
|
|
6
|
+
import { getAdminLanguage } from '../utils/getAdminLanguage.js';
|
|
5
7
|
const FontSelectField = ({ field, path })=>{
|
|
6
8
|
const { value, setValue } = useField({
|
|
7
9
|
path
|
|
@@ -9,6 +11,36 @@ const FontSelectField = ({ field, path })=>{
|
|
|
9
11
|
const [isOpen, setIsOpen] = useState(false);
|
|
10
12
|
const options = field.options || [];
|
|
11
13
|
const selectedOption = options.find((opt)=>opt.value === value);
|
|
14
|
+
const [loadedFonts, setLoadedFonts] = useState(new Set());
|
|
15
|
+
const getOptionLabel = (opt)=>{
|
|
16
|
+
if (typeof opt.label === 'string') return opt.label;
|
|
17
|
+
const lang = getAdminLanguage();
|
|
18
|
+
return opt.label[lang] || opt.label.en || opt.label.cs || 'Font';
|
|
19
|
+
};
|
|
20
|
+
const ensureFontLoaded = (fontValue)=>{
|
|
21
|
+
if (!fontValue || [
|
|
22
|
+
'preset',
|
|
23
|
+
'custom',
|
|
24
|
+
'system-ui'
|
|
25
|
+
].includes(fontValue)) return;
|
|
26
|
+
// Avoid duplicate loads
|
|
27
|
+
if (loadedFonts.has(fontValue)) return;
|
|
28
|
+
if (typeof document === 'undefined') return;
|
|
29
|
+
const linkId = `font-${fontValue.replace(/\s+/g, '-')}`;
|
|
30
|
+
if (document.getElementById(linkId)) {
|
|
31
|
+
setLoadedFonts((prev)=>new Set(prev).add(fontValue));
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
const weights = '400;700' // reasonable default weights
|
|
35
|
+
;
|
|
36
|
+
const fontUrl = `https://fonts.googleapis.com/css2?family=${encodeURIComponent(fontValue)}:wght@${weights}&display=swap`;
|
|
37
|
+
const link = document.createElement('link');
|
|
38
|
+
link.id = linkId;
|
|
39
|
+
link.rel = 'stylesheet';
|
|
40
|
+
link.href = fontUrl;
|
|
41
|
+
link.onload = ()=>setLoadedFonts((prev)=>new Set(prev).add(fontValue));
|
|
42
|
+
document.head.appendChild(link);
|
|
43
|
+
};
|
|
12
44
|
const handleSelect = (optionValue)=>{
|
|
13
45
|
setValue(optionValue);
|
|
14
46
|
setIsOpen(false);
|
|
@@ -27,7 +59,8 @@ const FontSelectField = ({ field, path })=>{
|
|
|
27
59
|
}, [
|
|
28
60
|
isOpen
|
|
29
61
|
]);
|
|
30
|
-
const
|
|
62
|
+
const t = getTranslations(getAdminLanguage());
|
|
63
|
+
const label = typeof field.label === 'string' ? field.label : typeof field.label === 'object' ? field.label?.en || field.label?.cs : field.label || 'Font';
|
|
31
64
|
return /*#__PURE__*/ _jsxs("div", {
|
|
32
65
|
className: "font-select-container",
|
|
33
66
|
style: {
|
|
@@ -75,8 +108,9 @@ const FontSelectField = ({ field, path })=>{
|
|
|
75
108
|
style: {
|
|
76
109
|
flex: 1
|
|
77
110
|
},
|
|
78
|
-
children: selectedOption
|
|
111
|
+
children: selectedOption ? getOptionLabel(selectedOption) : t.ui.selectFontPlaceholder
|
|
79
112
|
}),
|
|
113
|
+
' ',
|
|
80
114
|
/*#__PURE__*/ _jsx("svg", {
|
|
81
115
|
width: "12",
|
|
82
116
|
height: "12",
|
|
@@ -142,6 +176,8 @@ const FontSelectField = ({ field, path })=>{
|
|
|
142
176
|
if (!isSelected) {
|
|
143
177
|
e.currentTarget.style.backgroundColor = 'var(--theme-elevation-50)';
|
|
144
178
|
}
|
|
179
|
+
// Lazy-load a preview font when hovering
|
|
180
|
+
ensureFontLoaded(option.value);
|
|
145
181
|
},
|
|
146
182
|
onMouseLeave: (e)=>{
|
|
147
183
|
if (!isSelected) {
|
|
@@ -170,19 +206,20 @@ const FontSelectField = ({ field, path })=>{
|
|
|
170
206
|
strokeLinejoin: "round"
|
|
171
207
|
})
|
|
172
208
|
}),
|
|
173
|
-
option
|
|
209
|
+
getOptionLabel(option)
|
|
174
210
|
]
|
|
175
211
|
}),
|
|
176
212
|
/*#__PURE__*/ _jsx("div", {
|
|
177
213
|
style: {
|
|
178
214
|
fontSize: '16px',
|
|
179
215
|
color: 'var(--theme-elevation-600)',
|
|
180
|
-
fontStyle: option.value === 'preset' || option.value === 'custom' ? 'italic' : 'normal'
|
|
216
|
+
fontStyle: option.value === 'preset' || option.value === 'custom' ? 'italic' : 'normal',
|
|
217
|
+
fontFamily: option.fontFamily || undefined
|
|
181
218
|
},
|
|
182
219
|
children: (()=>{
|
|
183
|
-
if (option.value === 'preset') return
|
|
184
|
-
if (option.value === 'custom') return
|
|
185
|
-
return
|
|
220
|
+
if (option.value === 'preset') return t.ui.usePreset;
|
|
221
|
+
if (option.value === 'custom') return t.ui.specifyCustom;
|
|
222
|
+
return t.ui.sampleSentence;
|
|
186
223
|
})()
|
|
187
224
|
})
|
|
188
225
|
]
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/fields/FontSelectField.tsx"],"sourcesContent":["'use client'\n\nimport { useField } from '@payloadcms/ui'\nimport type { SelectFieldClientComponent } from 'payload'\nimport { useEffect, useState } from 'react'\n\ninterface FontOption {\n label: string\n value: string\n fontFamily?: string\n category?: 'sans-serif' | 'serif' | 'monospace' | 'display'\n}\n\nconst FontSelectField: SelectFieldClientComponent = ({ field, path }) => {\n const { value, setValue } = useField<string>({ path })\n const [isOpen, setIsOpen] = useState(false)\n\n const options = (field.options as FontOption[]) || []\n const selectedOption = options.find((opt) => opt.value === value)\n\n const handleSelect = (optionValue: string) => {\n setValue(optionValue)\n setIsOpen(false)\n }\n\n useEffect(() => {\n const handleClickOutside = (e: MouseEvent) => {\n const target = e.target as HTMLElement\n if (!target.closest('.font-select-container')) {\n setIsOpen(false)\n }\n }\n\n if (isOpen) {\n document.addEventListener('mousedown', handleClickOutside)\n return () => document.removeEventListener('mousedown', handleClickOutside)\n }\n }, [isOpen])\n\n const label =\n typeof field.label === 'string' ? field.label : field.label?.en || field.label?.cs || 'Font'\n\n return (\n <div className=\"font-select-container\" style={{ position: 'relative', marginBottom: '12px' }}>\n <label\n style={{\n display: 'block',\n marginBottom: '6px',\n fontSize: '13px',\n fontWeight: 600,\n color: 'var(--theme-elevation-800)',\n }}\n >\n {label}\n </label>\n\n <button\n type=\"button\"\n onClick={() => setIsOpen(!isOpen)}\n style={{\n width: '300px',\n padding: '10px 14px',\n borderRadius: '6px',\n border: '1px solid var(--theme-elevation-200)',\n backgroundColor: 'var(--theme-input-bg)',\n color: 'var(--theme-elevation-800)',\n textAlign: 'left',\n cursor: 'pointer',\n display: 'flex',\n justifyContent: 'space-between',\n alignItems: 'center',\n fontSize: '14px',\n fontFamily: selectedOption?.fontFamily || 'inherit',\n transition: 'border-color 0.2s ease',\n }}\n onMouseEnter={(e) => {\n e.currentTarget.style.borderColor = 'var(--theme-elevation-400)'\n }}\n onMouseLeave={(e) => {\n e.currentTarget.style.borderColor = 'var(--theme-elevation-200)'\n }}\n >\n <span style={{ flex: 1 }}>{selectedOption?.label || 'Select font...'}</span>\n <svg\n width=\"12\"\n height=\"12\"\n viewBox=\"0 0 12 12\"\n fill=\"none\"\n style={{\n transition: 'transform 0.2s ease',\n transform: isOpen ? 'rotate(180deg)' : 'rotate(0deg)',\n }}\n >\n <path\n d=\"M3 4.5L6 7.5L9 4.5\"\n stroke=\"currentColor\"\n strokeWidth=\"1.5\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n </svg>\n </button>\n\n {isOpen && (\n <div\n style={{\n position: 'absolute',\n top: '100%',\n left: 0,\n right: 0,\n marginTop: '4px',\n maxHeight: '280px',\n overflowY: 'auto',\n backgroundColor: 'var(--theme-elevation-0)',\n border: '1px solid var(--theme-elevation-200)',\n borderRadius: '8px',\n boxShadow: '0 8px 24px rgba(15, 23, 42, 0.15)',\n zIndex: 1000,\n }}\n >\n {options.map((option) => {\n const isSelected = option.value === value\n\n let fontFamily = option.fontFamily\n if (!fontFamily) {\n if (option.category === 'sans-serif') fontFamily = 'system-ui, sans-serif'\n else if (option.category === 'serif') fontFamily = 'Georgia, serif'\n else if (option.category === 'monospace') fontFamily = 'monospace'\n else fontFamily = 'inherit'\n }\n\n return (\n <button\n key={option.value}\n type=\"button\"\n onClick={() => handleSelect(option.value)}\n style={{\n width: '250px',\n padding: '12px 14px',\n border: 'none',\n backgroundColor: isSelected ? 'var(--theme-elevation-100)' : 'transparent',\n color: 'var(--theme-elevation-800)',\n textAlign: 'left',\n cursor: 'pointer',\n fontSize: '14px',\n fontFamily,\n display: 'flex',\n flexDirection: 'column',\n gap: '4px',\n transition: 'background-color 0.15s ease',\n }}\n onMouseEnter={(e) => {\n if (!isSelected) {\n e.currentTarget.style.backgroundColor = 'var(--theme-elevation-50)'\n }\n }}\n onMouseLeave={(e) => {\n if (!isSelected) {\n e.currentTarget.style.backgroundColor = 'transparent'\n }\n }}\n >\n <div\n style={{\n fontWeight: isSelected ? 600 : 500,\n display: 'flex',\n alignItems: 'center',\n gap: '8px',\n }}\n >\n {isSelected && (\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" fill=\"none\">\n <path\n d=\"M11.6667 3.5L5.25 9.91667L2.33334 7\"\n stroke=\"var(--theme-elevation-500)\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n </svg>\n )}\n {option.label}\n </div>\n <div\n style={{\n fontSize: '16px',\n color: 'var(--theme-elevation-600)',\n fontStyle:\n option.value === 'preset' || option.value === 'custom' ? 'italic' : 'normal',\n }}\n >\n {(() => {\n if (option.value === 'preset') return 'Use theme preset font'\n if (option.value === 'custom') return 'Specify custom font below'\n return 'The quick brown fox jumps over the lazy dog'\n })()}\n </div>\n </button>\n )\n })}\n </div>\n )}\n </div>\n )\n}\n\nexport default FontSelectField\n"],"names":["useField","useEffect","useState","FontSelectField","field","path","value","setValue","isOpen","setIsOpen","options","selectedOption","find","opt","handleSelect","optionValue","handleClickOutside","e","target","closest","document","addEventListener","removeEventListener","label","en","cs","div","className","style","position","marginBottom","display","fontSize","fontWeight","color","button","type","onClick","width","padding","borderRadius","border","backgroundColor","textAlign","cursor","justifyContent","alignItems","fontFamily","transition","onMouseEnter","currentTarget","borderColor","onMouseLeave","span","flex","svg","height","viewBox","fill","transform","d","stroke","strokeWidth","strokeLinecap","strokeLinejoin","top","left","right","marginTop","maxHeight","overflowY","boxShadow","zIndex","map","option","isSelected","category","flexDirection","gap","fontStyle"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../src/fields/FontSelectField.tsx"],"sourcesContent":["'use client'\n\nimport { useField } from '@payloadcms/ui'\nimport type { SelectFieldClientComponent } from 'payload'\nimport { useEffect, useState } from 'react'\nimport { getTranslations } from '../translations.js'\nimport { getAdminLanguage } from '../utils/getAdminLanguage.js'\n\ntype LocalizedLabel = Record<string, string>\n\ninterface FontOption {\n label: string | LocalizedLabel\n value: string\n fontFamily?: string\n category?: 'sans-serif' | 'serif' | 'monospace' | 'display'\n}\n\nconst FontSelectField: SelectFieldClientComponent = ({ field, path }) => {\n const { value, setValue } = useField<string>({ path })\n const [isOpen, setIsOpen] = useState(false)\n\n const options = (field.options as FontOption[]) || []\n const selectedOption = options.find((opt) => opt.value === value)\n const [loadedFonts, setLoadedFonts] = useState<Set<string>>(new Set())\n\n const getOptionLabel = (opt: FontOption) => {\n if (typeof opt.label === 'string') return opt.label\n const lang = getAdminLanguage()\n return opt.label[lang] || opt.label.en || opt.label.cs || 'Font'\n }\n\n const ensureFontLoaded = (fontValue: string | undefined) => {\n if (!fontValue || ['preset', 'custom', 'system-ui'].includes(fontValue)) return\n // Avoid duplicate loads\n if (loadedFonts.has(fontValue)) return\n\n if (typeof document === 'undefined') return\n\n const linkId = `font-${fontValue.replace(/\\s+/g, '-')}`\n if (document.getElementById(linkId)) {\n setLoadedFonts((prev) => new Set(prev).add(fontValue))\n return\n }\n\n const weights = '400;700' // reasonable default weights\n const fontUrl = `https://fonts.googleapis.com/css2?family=${encodeURIComponent(\n fontValue,\n )}:wght@${weights}&display=swap`\n const link = document.createElement('link')\n link.id = linkId\n link.rel = 'stylesheet'\n link.href = fontUrl\n link.onload = () => setLoadedFonts((prev) => new Set(prev).add(fontValue))\n document.head.appendChild(link)\n }\n\n const handleSelect = (optionValue: string) => {\n setValue(optionValue)\n setIsOpen(false)\n }\n\n useEffect(() => {\n const handleClickOutside = (e: MouseEvent) => {\n const target = e.target as HTMLElement\n if (!target.closest('.font-select-container')) {\n setIsOpen(false)\n }\n }\n\n if (isOpen) {\n document.addEventListener('mousedown', handleClickOutside)\n return () => document.removeEventListener('mousedown', handleClickOutside)\n }\n }, [isOpen])\n\n const t = getTranslations(getAdminLanguage())\n const label =\n typeof field.label === 'string'\n ? field.label\n : typeof field.label === 'object'\n ? field.label?.en || field.label?.cs\n : field.label || 'Font'\n\n return (\n <div className=\"font-select-container\" style={{ position: 'relative', marginBottom: '12px' }}>\n <label\n style={{\n display: 'block',\n marginBottom: '6px',\n fontSize: '13px',\n fontWeight: 600,\n color: 'var(--theme-elevation-800)',\n }}\n >\n {label}\n </label>\n\n <button\n type=\"button\"\n onClick={() => setIsOpen(!isOpen)}\n style={{\n width: '300px',\n padding: '10px 14px',\n borderRadius: '6px',\n border: '1px solid var(--theme-elevation-200)',\n backgroundColor: 'var(--theme-input-bg)',\n color: 'var(--theme-elevation-800)',\n textAlign: 'left',\n cursor: 'pointer',\n display: 'flex',\n justifyContent: 'space-between',\n alignItems: 'center',\n fontSize: '14px',\n fontFamily: selectedOption?.fontFamily || 'inherit',\n transition: 'border-color 0.2s ease',\n }}\n onMouseEnter={(e) => {\n e.currentTarget.style.borderColor = 'var(--theme-elevation-400)'\n }}\n onMouseLeave={(e) => {\n e.currentTarget.style.borderColor = 'var(--theme-elevation-200)'\n }}\n >\n <span style={{ flex: 1 }}>\n {selectedOption ? getOptionLabel(selectedOption) : t.ui.selectFontPlaceholder}\n </span>{' '}\n <svg\n width=\"12\"\n height=\"12\"\n viewBox=\"0 0 12 12\"\n fill=\"none\"\n style={{\n transition: 'transform 0.2s ease',\n transform: isOpen ? 'rotate(180deg)' : 'rotate(0deg)',\n }}\n >\n <path\n d=\"M3 4.5L6 7.5L9 4.5\"\n stroke=\"currentColor\"\n strokeWidth=\"1.5\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n </svg>\n </button>\n\n {isOpen && (\n <div\n style={{\n position: 'absolute',\n top: '100%',\n left: 0,\n right: 0,\n marginTop: '4px',\n maxHeight: '280px',\n overflowY: 'auto',\n backgroundColor: 'var(--theme-elevation-0)',\n border: '1px solid var(--theme-elevation-200)',\n borderRadius: '8px',\n boxShadow: '0 8px 24px rgba(15, 23, 42, 0.15)',\n zIndex: 1000,\n }}\n >\n {options.map((option) => {\n const isSelected = option.value === value\n\n let fontFamily = option.fontFamily\n if (!fontFamily) {\n if (option.category === 'sans-serif') fontFamily = 'system-ui, sans-serif'\n else if (option.category === 'serif') fontFamily = 'Georgia, serif'\n else if (option.category === 'monospace') fontFamily = 'monospace'\n else fontFamily = 'inherit'\n }\n\n return (\n <button\n key={option.value}\n type=\"button\"\n onClick={() => handleSelect(option.value)}\n style={{\n width: '250px',\n padding: '12px 14px',\n border: 'none',\n backgroundColor: isSelected ? 'var(--theme-elevation-100)' : 'transparent',\n color: 'var(--theme-elevation-800)',\n textAlign: 'left',\n cursor: 'pointer',\n fontSize: '14px',\n fontFamily,\n display: 'flex',\n flexDirection: 'column',\n gap: '4px',\n transition: 'background-color 0.15s ease',\n }}\n onMouseEnter={(e) => {\n if (!isSelected) {\n e.currentTarget.style.backgroundColor = 'var(--theme-elevation-50)'\n }\n // Lazy-load a preview font when hovering\n ensureFontLoaded(option.value)\n }}\n onMouseLeave={(e) => {\n if (!isSelected) {\n e.currentTarget.style.backgroundColor = 'transparent'\n }\n }}\n >\n <div\n style={{\n fontWeight: isSelected ? 600 : 500,\n display: 'flex',\n alignItems: 'center',\n gap: '8px',\n }}\n >\n {isSelected && (\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" fill=\"none\">\n <path\n d=\"M11.6667 3.5L5.25 9.91667L2.33334 7\"\n stroke=\"var(--theme-elevation-500)\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n </svg>\n )}\n {getOptionLabel(option)}\n </div>\n <div\n style={{\n fontSize: '16px',\n color: 'var(--theme-elevation-600)',\n fontStyle:\n option.value === 'preset' || option.value === 'custom' ? 'italic' : 'normal',\n fontFamily: option.fontFamily || undefined,\n }}\n >\n {(() => {\n if (option.value === 'preset') return t.ui.usePreset\n if (option.value === 'custom') return t.ui.specifyCustom\n return t.ui.sampleSentence\n })()}\n </div>\n </button>\n )\n })}\n </div>\n )}\n </div>\n )\n}\n\nexport default FontSelectField\n"],"names":["useField","useEffect","useState","getTranslations","getAdminLanguage","FontSelectField","field","path","value","setValue","isOpen","setIsOpen","options","selectedOption","find","opt","loadedFonts","setLoadedFonts","Set","getOptionLabel","label","lang","en","cs","ensureFontLoaded","fontValue","includes","has","document","linkId","replace","getElementById","prev","add","weights","fontUrl","encodeURIComponent","link","createElement","id","rel","href","onload","head","appendChild","handleSelect","optionValue","handleClickOutside","e","target","closest","addEventListener","removeEventListener","t","div","className","style","position","marginBottom","display","fontSize","fontWeight","color","button","type","onClick","width","padding","borderRadius","border","backgroundColor","textAlign","cursor","justifyContent","alignItems","fontFamily","transition","onMouseEnter","currentTarget","borderColor","onMouseLeave","span","flex","ui","selectFontPlaceholder","svg","height","viewBox","fill","transform","d","stroke","strokeWidth","strokeLinecap","strokeLinejoin","top","left","right","marginTop","maxHeight","overflowY","boxShadow","zIndex","map","option","isSelected","category","flexDirection","gap","fontStyle","undefined","usePreset","specifyCustom","sampleSentence"],"mappings":"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"}
|
|
@@ -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;
|
|
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;AAwPrD,MAAM,CAAC,OAAO,UAAU,iBAAiB,CAAC,KAAK,EAAE,sBAAsB,+BAqatE"}
|
|
@@ -6,32 +6,13 @@ import { useCallback, useEffect, useMemo, useRef } from 'react';
|
|
|
6
6
|
import { resolveTypographyPreview } from '../components/typographyPreviewUtils.js';
|
|
7
7
|
import { allThemePresets } from '../index.js';
|
|
8
8
|
import { borderRadiusPresets } from '../providers/Theme/themeConfig.js';
|
|
9
|
+
import { getTranslations } from '../translations.js';
|
|
10
|
+
import { getAdminLanguage } from '../utils/getAdminLanguage.js';
|
|
9
11
|
import { darkModeDefaults, lightModeDefaults } from './colorModeFields.js';
|
|
10
12
|
// FALLBACK_THEME and runtime theme presets are computed inside the component
|
|
11
13
|
const colorKeys = Object.keys(lightModeDefaults);
|
|
12
|
-
const highlightSwatches = [
|
|
13
|
-
{
|
|
14
|
-
key: 'primary',
|
|
15
|
-
label: 'Primary'
|
|
16
|
-
},
|
|
17
|
-
{
|
|
18
|
-
key: 'secondary',
|
|
19
|
-
label: 'Secondary'
|
|
20
|
-
},
|
|
21
|
-
{
|
|
22
|
-
key: 'accent',
|
|
23
|
-
label: 'Accent'
|
|
24
|
-
},
|
|
25
|
-
{
|
|
26
|
-
key: 'background',
|
|
27
|
-
label: 'Background'
|
|
28
|
-
},
|
|
29
|
-
{
|
|
30
|
-
key: 'foreground',
|
|
31
|
-
label: 'Foreground'
|
|
32
|
-
}
|
|
33
|
-
];
|
|
34
14
|
function ModePreview({ icon, title, colors, typography, radius }) {
|
|
15
|
+
const t = getTranslations(getAdminLanguage());
|
|
35
16
|
const background = colors.background ?? '#ffffff';
|
|
36
17
|
const foreground = colors.foreground ?? '#0a0a0a';
|
|
37
18
|
const borderColor = colors.border ?? 'rgba(148, 163, 184, 0.35)';
|
|
@@ -116,7 +97,7 @@ function ModePreview({ icon, title, colors, typography, radius }) {
|
|
|
116
97
|
color: primaryForeground,
|
|
117
98
|
boxShadow: '0 6px 14px rgba(15, 23, 42, 0.15)'
|
|
118
99
|
},
|
|
119
|
-
children:
|
|
100
|
+
children: t.ui.primaryAction
|
|
120
101
|
}),
|
|
121
102
|
/*#__PURE__*/ _jsx("button", {
|
|
122
103
|
type: "button",
|
|
@@ -132,7 +113,7 @@ function ModePreview({ icon, title, colors, typography, radius }) {
|
|
|
132
113
|
color: secondaryForeground,
|
|
133
114
|
boxShadow: 'inset 0 0 0 1px rgba(15, 23, 42, 0.08)'
|
|
134
115
|
},
|
|
135
|
-
children:
|
|
116
|
+
children: t.ui.secondaryAction
|
|
136
117
|
})
|
|
137
118
|
]
|
|
138
119
|
}),
|
|
@@ -414,6 +395,31 @@ export default function ThemePreviewField(props) {
|
|
|
414
395
|
chip: borderRadiusCSS['--radius-default'] ?? '0.75rem',
|
|
415
396
|
pill: borderRadiusCSS['--radius-xl'] ?? borderRadiusCSS['--radius-large'] ?? '999px'
|
|
416
397
|
};
|
|
398
|
+
// Translate labels at runtime based on admin language
|
|
399
|
+
const t = getTranslations(getAdminLanguage());
|
|
400
|
+
// Explicitly type keys as `keyof ColorModeColors` to satisfy TypeScript when indexing `lightMode`/`darkMode`
|
|
401
|
+
const highlightSwatches = [
|
|
402
|
+
{
|
|
403
|
+
key: 'primary',
|
|
404
|
+
label: t.colors.primary
|
|
405
|
+
},
|
|
406
|
+
{
|
|
407
|
+
key: 'secondary',
|
|
408
|
+
label: t.colors.secondary
|
|
409
|
+
},
|
|
410
|
+
{
|
|
411
|
+
key: 'accent',
|
|
412
|
+
label: t.colors.accent
|
|
413
|
+
},
|
|
414
|
+
{
|
|
415
|
+
key: 'background',
|
|
416
|
+
label: t.colors.background
|
|
417
|
+
},
|
|
418
|
+
{
|
|
419
|
+
key: 'foreground',
|
|
420
|
+
label: t.colors.foreground
|
|
421
|
+
}
|
|
422
|
+
];
|
|
417
423
|
const fieldLabel = typeof field.label === 'string' ? field.label : field.label?.en || field.label?.cs || 'Theme';
|
|
418
424
|
return /*#__PURE__*/ _jsxs("div", {
|
|
419
425
|
style: {
|
|
@@ -451,7 +457,7 @@ export default function ThemePreviewField(props) {
|
|
|
451
457
|
className: "theme-preset-list",
|
|
452
458
|
children: Object.entries(runtimeThemePresets).map(([key, preset])=>{
|
|
453
459
|
const isSelected = key === selectedTheme;
|
|
454
|
-
const swatches = highlightSwatches.map(({ key: colorKey })=>preset.lightMode[colorKey]).filter((
|
|
460
|
+
const swatches = highlightSwatches.map(({ key: colorKey })=>preset.lightMode[colorKey]).filter((v)=>typeof v === 'string' && v.trim().length > 0);
|
|
455
461
|
return /*#__PURE__*/ _jsxs("button", {
|
|
456
462
|
type: "button",
|
|
457
463
|
onClick: ()=>handleThemeSelect(key),
|
|
@@ -601,14 +607,14 @@ export default function ThemePreviewField(props) {
|
|
|
601
607
|
},
|
|
602
608
|
children: [
|
|
603
609
|
/*#__PURE__*/ _jsx("span", {
|
|
604
|
-
children:
|
|
610
|
+
children: getTranslations('en').livePreview.smallTitle
|
|
605
611
|
}),
|
|
606
612
|
/*#__PURE__*/ _jsx("span", {
|
|
607
613
|
style: {
|
|
608
614
|
fontSize: '12px',
|
|
609
615
|
color: 'var(--theme-elevation-600)'
|
|
610
616
|
},
|
|
611
|
-
children: activePreset ? activePreset.label : '
|
|
617
|
+
children: activePreset ? activePreset.label : getTranslations('en').preview.customPalette
|
|
612
618
|
})
|
|
613
619
|
]
|
|
614
620
|
}),
|
|
@@ -620,14 +626,14 @@ export default function ThemePreviewField(props) {
|
|
|
620
626
|
children: [
|
|
621
627
|
/*#__PURE__*/ _jsx(ModePreview, {
|
|
622
628
|
icon: "☀️",
|
|
623
|
-
title:
|
|
629
|
+
title: getTranslations('en').ui.lightMode,
|
|
624
630
|
colors: lightModeColors,
|
|
625
631
|
typography: previewTypography,
|
|
626
632
|
radius: previewRadius
|
|
627
633
|
}),
|
|
628
634
|
/*#__PURE__*/ _jsx(ModePreview, {
|
|
629
635
|
icon: "🌙",
|
|
630
|
-
title:
|
|
636
|
+
title: getTranslations('en').ui.darkMode,
|
|
631
637
|
colors: darkModeColors,
|
|
632
638
|
typography: previewTypography,
|
|
633
639
|
radius: previewRadius
|
|
@@ -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 { 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;\n // support both `field.admin.themePresets` (legacy) and `field.admin.custom.themePresets`\n // otherwise fallback to `allThemePresets`.\n // Prefer presets passed via `admin.custom.themePresets` (set by the field factory / plugin).\n // Fall back to legacy `admin.themePresets` for backwards compatibility, then to `allThemePresets`.\n const baseThemePresets =\n (field?.admin?.custom as unknown as { themePresets?: ThemePreset[] })?.themePresets ??\n (field?.admin as any)?.themePresets ??\n 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","custom","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
|
+
{"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 { getTranslations } from '../translations.js'\nimport { getAdminLanguage } from '../utils/getAdminLanguage.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\n// translations and swatches will be computed inside the component to respect admin language at runtime\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 t = getTranslations(getAdminLanguage())\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 {t.ui.primaryAction}\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 {t.ui.secondaryAction}\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;\n // support both `field.admin.themePresets` (legacy) and `field.admin.custom.themePresets`\n // otherwise fallback to `allThemePresets`.\n // Prefer presets passed via `admin.custom.themePresets` (set by the field factory / plugin).\n // Fall back to legacy `admin.themePresets` for backwards compatibility, then to `allThemePresets`.\n const baseThemePresets =\n (field?.admin?.custom as unknown as { themePresets?: ThemePreset[] })?.themePresets ??\n (field?.admin as unknown as { themePresets?: ThemePreset[] })?.themePresets ??\n 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]: any) => 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 // Translate labels at runtime based on admin language\n const t = getTranslations(getAdminLanguage())\n // Explicitly type keys as `keyof ColorModeColors` to satisfy TypeScript when indexing `lightMode`/`darkMode`\n const highlightSwatches: { key: keyof ColorModeColors; label: string }[] = [\n { key: 'primary', label: t.colors.primary },\n { key: 'secondary', label: t.colors.secondary },\n { key: 'accent', label: t.colors.accent },\n { key: 'background', label: t.colors.background },\n { key: 'foreground', label: t.colors.foreground },\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] as string | undefined)\n .filter((v): v is string => typeof v === 'string' && v.trim().length > 0)\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 {/* safe translations for preview header */}\n <span>{getTranslations('en').livePreview.smallTitle}</span>\n <span style={{ fontSize: '12px', color: 'var(--theme-elevation-600)' }}>\n {activePreset ? activePreset.label : getTranslations('en').preview.customPalette}\n </span>\n </div>\n\n <div\n style={{\n display: 'grid',\n gap: '16px',\n }}\n >\n <ModePreview\n icon=\"☀️\"\n title={getTranslations('en').ui.lightMode}\n colors={lightModeColors}\n typography={previewTypography}\n radius={previewRadius}\n />\n <ModePreview\n icon=\"🌙\"\n title={getTranslations('en').ui.darkMode}\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","getTranslations","getAdminLanguage","darkModeDefaults","lightModeDefaults","colorKeys","Object","keys","ModePreview","icon","title","colors","typography","radius","t","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","ui","primaryAction","chip","secondaryAction","gridTemplateColumns","p","margin","bodyLabel","headingLabel","ThemePreviewField","props","field","path","baseThemePresets","admin","custom","themePresets","runtimeThemePresets","reduce","acc","preset","name","label","lightMode","darkMode","fallbackTheme","value","selectedTheme","setValue","dispatchFields","formFields","formState","hasAppliedInitialPresetRef","applyPreset","presetName","forEach","key","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","highlightSwatches","fieldLabel","en","cs","marginBottom","flex","minWidth","maxWidth","className","entries","map","isSelected","swatches","colorKey","filter","v","onClick","aria-hidden","index","marginTop","swatchValue","width","height","description","position","top","alignSelf","maxHeight","overflowY","livePreview","smallTitle","preview","customPalette"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ThemeTokenSelectField.d.ts","sourceRoot":"","sources":["../../src/fields/ThemeTokenSelectField.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,SAAS,CAAA;AA8FrD,MAAM,CAAC,OAAO,UAAU,qBAAqB,CAAC,KAAK,EAAE,sBAAsB,+
|
|
1
|
+
{"version":3,"file":"ThemeTokenSelectField.d.ts","sourceRoot":"","sources":["../../src/fields/ThemeTokenSelectField.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,SAAS,CAAA;AA8FrD,MAAM,CAAC,OAAO,UAAU,qBAAqB,CAAC,KAAK,EAAE,sBAAsB,+BAgO1E"}
|
|
@@ -135,7 +135,6 @@ export default function ThemeTokenSelectField(props) {
|
|
|
135
135
|
]);
|
|
136
136
|
useEffect(()=>{
|
|
137
137
|
let isMounted = true;
|
|
138
|
-
// Allow fields to override fetch options via admin.custom
|
|
139
138
|
const custom = field.admin?.custom ?? {};
|
|
140
139
|
const fetchOpts = custom.fetchThemeConfigurationOptions ?? custom.fetchOptions ?? (custom.collectionSlug || typeof custom.useGlobal !== 'undefined' ? {
|
|
141
140
|
collectionSlug: custom.collectionSlug,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/fields/ThemeTokenSelectField.tsx"],"sourcesContent":["'use client'\n\nimport { useField } from '@payloadcms/ui'\nimport type { SelectFieldClientProps } from 'payload'\nimport { useCallback, useEffect, useMemo, useState } from 'react'\nimport { allThemePresets, fetchThemeConfiguration } from '../index.js'\nimport type { SiteThemeConfiguration } from '../payload-types.js'\nimport type { ThemePreset } from '../presets.js'\nimport type { FetchThemeConfigurationOptions } from '../types.js'\nimport { resolveThemeConfiguration } from '../utils/resolveThemeConfiguration.js'\n\ninterface ThemeColorOption {\n value: string\n label: string | { [key: string]: string | undefined }\n color: string\n description?: string\n}\n\nconst FALLBACK_TOKENS: ThemeColorOption[] = [\n {\n value: 'background',\n label: { en: 'Theme background', cs: 'Pozadí tématu' },\n color: 'var(--background)',\n },\n { value: 'card', label: { en: 'Card background', cs: 'Pozadí karty' }, color: 'var(--card)' },\n { value: 'muted', label: { en: 'Muted surface', cs: 'Tlumený povrch' }, color: 'var(--muted)' },\n {\n value: 'accent',\n label: { en: 'Accent surface', cs: 'Akcentní povrch' },\n color: 'var(--accent)',\n },\n {\n value: 'secondary',\n label: { en: 'Secondary surface', cs: 'Sekundární povrch' },\n color: 'var(--secondary)',\n },\n {\n value: 'primary',\n label: { en: 'Primary surface', cs: 'Primární povrch' },\n color: 'var(--primary)',\n },\n]\n\n// Use plugin-provided fetch helper which supports collection/global and options\n// This will use `collectionSlug`, `useGlobal`, tenant, locale, depth, draft, etc.\n// Accept fetch options from field.admin.custom to allow overrides in different setups.\n\nfunction buildOptionsFromConfiguration(\n configuration: SiteThemeConfiguration | Record<string, unknown> | null,\n themePresets: ThemePreset[],\n): ThemeColorOption[] {\n if (!configuration) {\n return FALLBACK_TOKENS\n }\n\n const resolved = resolveThemeConfiguration(configuration)\n const lightMode = resolved.lightMode ?? themePresets[0]?.lightMode ?? {}\n const orderedKeys: string[] = [\n 'background',\n 'card',\n 'muted',\n 'accent',\n 'secondary',\n 'primary',\n 'popover',\n ]\n\n const typedLightMode = lightMode as Record<string, string | null | undefined>\n\n const tokens = orderedKeys\n .map((key) => {\n const value = typedLightMode?.[key]\n if (typeof value !== 'string' || value.trim().length === 0) {\n return null\n }\n\n const labelMap: Record<string, { en: string; cs: string }> = {\n background: { en: 'Theme background', cs: 'Pozadí tématu' },\n card: { en: 'Card background', cs: 'Pozadí karty' },\n muted: { en: 'Muted surface', cs: 'Tlumený povrch' },\n accent: { en: 'Accent surface', cs: 'Akcentní povrch' },\n secondary: { en: 'Secondary surface', cs: 'Sekundární povrch' },\n primary: { en: 'Primary surface', cs: 'Primární povrch' },\n popover: { en: 'Popover surface', cs: 'Popover povrch' },\n }\n\n return {\n value: key,\n label: labelMap[key] ?? { en: key, cs: key },\n color: value,\n }\n })\n .filter((token): token is NonNullable<typeof token> => token !== null)\n\n return tokens.length > 0 ? tokens : FALLBACK_TOKENS\n}\n\nexport default function ThemeTokenSelectField(props: SelectFieldClientProps) {\n const { path, field } = props\n const { value, setValue } = useField<string>({ path })\n const [options, setOptions] = useState<ThemeColorOption[]>(FALLBACK_TOKENS)\n const selectedValue = value || 'background'\n\n // Get themePresets from admin.custom or use defaults\n const themePresets = useMemo(() => {\n const customPresets = (field.admin?.custom as { themePresets?: ThemePreset[] })?.themePresets\n return customPresets && customPresets.length > 0 ? customPresets : allThemePresets\n }, [field.admin?.custom])\n\n useEffect(() => {\n let isMounted = true\n\n // Allow fields to override fetch options via admin.custom\n const custom = (field.admin?.custom as any) ?? {}\n\n const fetchOpts: FetchThemeConfigurationOptions | undefined =\n custom.fetchThemeConfigurationOptions ??\n custom.fetchOptions ??\n (custom.collectionSlug || typeof custom.useGlobal !== 'undefined'\n ? {\n collectionSlug: custom.collectionSlug,\n useGlobal: custom.useGlobal,\n tenantSlug: custom.tenantSlug,\n depth: custom.depth,\n locale: custom.locale,\n draft: custom.draft,\n queryParams: custom.queryParams,\n }\n : undefined)\n\n fetchThemeConfiguration(fetchOpts).then(async (configuration) => {\n if (!isMounted) return\n if (configuration) {\n setOptions(buildOptionsFromConfiguration(configuration, themePresets))\n return\n }\n\n // If nothing found and fetchOpts didn't explicitly request global, try fallback to global\n // This helps in setups where plugin created a standalone global (default slug 'appearance-settings')\n const explicitlyRequestedGlobal = !!(\n (fetchOpts as FetchThemeConfigurationOptions | undefined)?.useGlobal === true ||\n (fetchOpts as FetchThemeConfigurationOptions | undefined)?.collectionSlug ===\n 'appearance-settings'\n )\n\n if (!explicitlyRequestedGlobal) {\n try {\n // Prefer custom.collectionSlug if provided, otherwise try the default standalone slug\n const fallbackCollection = (custom && custom.collectionSlug) || 'appearance-settings'\n const fallbackOpts: FetchThemeConfigurationOptions = {\n useGlobal: true,\n collectionSlug: fallbackCollection,\n }\n const fallbackConfig = await fetchThemeConfiguration(fallbackOpts)\n if (!isMounted) return\n if (fallbackConfig) {\n // Found theme config in global, use it\n setOptions(buildOptionsFromConfiguration(fallbackConfig, themePresets))\n return\n }\n } catch (e) {\n console.warn('[ThemeTokenSelectField] Fallback global fetch failed:', e)\n }\n }\n\n // final fallback: use empty tokens\n setOptions(buildOptionsFromConfiguration(configuration, themePresets))\n })\n\n return () => {\n isMounted = false\n }\n }, [themePresets, field.admin?.custom])\n\n const handleSelect = useCallback(\n (nextValue: string) => {\n setValue(nextValue)\n },\n [setValue],\n )\n\n const label =\n typeof field.label === 'string' ? field.label : field.label?.en || field.label?.cs || ''\n let description = ''\n if (typeof field.admin?.description === 'string') {\n description = field.admin.description\n } else if (\n field.admin?.description &&\n typeof field.admin.description === 'object' &&\n typeof field.admin.description.en === 'string'\n ) {\n description = field.admin.description.en\n }\n\n // Helper function to get label text from localized or string label\n const getOptionLabel = (option: ThemeColorOption): string => {\n if (typeof option.label === 'string') {\n return option.label\n }\n // Prefer English, fallback to Czech, then any available language\n return option.label.en || option.label.cs || Object.values(option.label)[0] || option.value\n }\n\n // Resolve CSS variable colors (e.g., 'var(--primary)') to their computed values when possible\n const resolveCssColor = (color: string): string => {\n if (typeof window === 'undefined' || !color || !color.trim().startsWith('var(')) {\n return color\n }\n\n try {\n const match = color.trim().match(/var\\((--[^)]+)\\)/)\n if (!match) return color\n const varName = match[1]\n const computed = getComputedStyle(document.documentElement).getPropertyValue(varName).trim()\n return computed || color\n } catch (e) {\n return color\n }\n }\n\n return (\n <div className=\"field-type theme-token-select\">\n {label && (\n <label\n className=\"field-label\"\n htmlFor={path}\n style={{ display: 'block', marginBottom: '8px' }}\n >\n {label}\n {field.required && <span className=\"required\">*</span>}\n </label>\n )}\n\n {description && (\n <div\n className=\"field-description\"\n style={{ marginBottom: '12px', fontSize: '13px', color: 'var(--theme-elevation-500)' }}\n >\n {description}\n </div>\n )}\n\n <div\n className=\"token-grid\"\n style={{\n display: 'grid',\n gridTemplateColumns: 'repeat(auto-fill, minmax(140px, 1fr))',\n gap: '10px',\n }}\n >\n {options.map((option) => {\n const isActive = option.value === selectedValue\n return (\n <button\n type=\"button\"\n key={option.value}\n onClick={() => handleSelect(option.value)}\n style={{\n display: 'flex',\n alignItems: 'center',\n gap: '10px',\n padding: '10px 12px',\n borderRadius: '10px',\n border: isActive\n ? '2px solid var(--theme-success-500)'\n : '1px solid var(--theme-elevation-150)',\n backgroundColor: 'var(--theme-elevation-0)',\n boxShadow: isActive\n ? '0 10px 20px -10px rgba(59, 130, 246, 0.4)'\n : '0 1px 2px rgba(15, 23, 42, 0.08)',\n cursor: 'pointer',\n transition: 'border-color 0.2s ease, box-shadow 0.2s ease',\n }}\n >\n <span\n aria-hidden\n style={{\n width: '32px',\n height: '32px',\n borderRadius: '8px',\n border: '1px solid rgba(15, 23, 42, 0.08)',\n backgroundColor: resolveCssColor(option.color),\n flexShrink: 0,\n }}\n />\n <span\n style={{ fontSize: '13px', fontWeight: 600, color: 'var(--theme-elevation-800)' }}\n >\n {getOptionLabel(option)}\n </span>\n </button>\n )\n })}\n </div>\n\n <select\n id={path}\n value={selectedValue}\n onChange={(event) => handleSelect(event.target.value)}\n style={{ display: 'none' }}\n >\n {options.map((option) => (\n <option key={option.value} value={option.value}>\n {getOptionLabel(option)}\n </option>\n ))}\n </select>\n </div>\n )\n}\n"],"names":["useField","useCallback","useEffect","useMemo","useState","allThemePresets","fetchThemeConfiguration","resolveThemeConfiguration","FALLBACK_TOKENS","value","label","en","cs","color","buildOptionsFromConfiguration","configuration","themePresets","resolved","lightMode","orderedKeys","typedLightMode","tokens","map","key","trim","length","labelMap","background","card","muted","accent","secondary","primary","popover","filter","token","ThemeTokenSelectField","props","path","field","setValue","options","setOptions","selectedValue","customPresets","admin","custom","isMounted","fetchOpts","fetchThemeConfigurationOptions","fetchOptions","collectionSlug","useGlobal","tenantSlug","depth","locale","draft","queryParams","undefined","then","explicitlyRequestedGlobal","fallbackCollection","fallbackOpts","fallbackConfig","e","console","warn","handleSelect","nextValue","description","getOptionLabel","option","Object","values","resolveCssColor","window","startsWith","match","varName","computed","getComputedStyle","document","documentElement","getPropertyValue","div","className","htmlFor","style","display","marginBottom","required","span","fontSize","gridTemplateColumns","gap","isActive","button","type","onClick","alignItems","padding","borderRadius","border","backgroundColor","boxShadow","cursor","transition","aria-hidden","width","height","flexShrink","fontWeight","select","id","onChange","event","target"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../src/fields/ThemeTokenSelectField.tsx"],"sourcesContent":["'use client'\n\nimport { useField } from '@payloadcms/ui'\nimport type { SelectFieldClientProps } from 'payload'\nimport { useCallback, useEffect, useMemo, useState } from 'react'\nimport { allThemePresets, fetchThemeConfiguration } from '../index.js'\nimport type { SiteThemeConfiguration } from '../payload-types.js'\nimport type { ThemePreset } from '../presets.js'\nimport type { FetchThemeConfigurationOptions } from '../types.js'\nimport { resolveThemeConfiguration } from '../utils/resolveThemeConfiguration.js'\n\ninterface ThemeColorOption {\n value: string\n label: string | { [key: string]: string | undefined }\n color: string\n description?: string\n}\n\nconst FALLBACK_TOKENS: ThemeColorOption[] = [\n {\n value: 'background',\n label: { en: 'Theme background', cs: 'Pozadí tématu' },\n color: 'var(--background)',\n },\n { value: 'card', label: { en: 'Card background', cs: 'Pozadí karty' }, color: 'var(--card)' },\n { value: 'muted', label: { en: 'Muted surface', cs: 'Tlumený povrch' }, color: 'var(--muted)' },\n {\n value: 'accent',\n label: { en: 'Accent surface', cs: 'Akcentní povrch' },\n color: 'var(--accent)',\n },\n {\n value: 'secondary',\n label: { en: 'Secondary surface', cs: 'Sekundární povrch' },\n color: 'var(--secondary)',\n },\n {\n value: 'primary',\n label: { en: 'Primary surface', cs: 'Primární povrch' },\n color: 'var(--primary)',\n },\n]\n\n// Use plugin-provided fetch helper which supports collection/global and options\n// This will use `collectionSlug`, `useGlobal`, tenant, locale, depth, draft, etc.\n// Accept fetch options from field.admin.custom to allow overrides in different setups.\n\nfunction buildOptionsFromConfiguration(\n configuration: SiteThemeConfiguration | Record<string, unknown> | null,\n themePresets: ThemePreset[],\n): ThemeColorOption[] {\n if (!configuration) {\n return FALLBACK_TOKENS\n }\n\n const resolved = resolveThemeConfiguration(configuration)\n const lightMode = resolved.lightMode ?? themePresets[0]?.lightMode ?? {}\n const orderedKeys: string[] = [\n 'background',\n 'card',\n 'muted',\n 'accent',\n 'secondary',\n 'primary',\n 'popover',\n ]\n\n const typedLightMode = lightMode as Record<string, string | null | undefined>\n\n const tokens = orderedKeys\n .map((key) => {\n const value = typedLightMode?.[key]\n if (typeof value !== 'string' || value.trim().length === 0) {\n return null\n }\n\n const labelMap: Record<string, { en: string; cs: string }> = {\n background: { en: 'Theme background', cs: 'Pozadí tématu' },\n card: { en: 'Card background', cs: 'Pozadí karty' },\n muted: { en: 'Muted surface', cs: 'Tlumený povrch' },\n accent: { en: 'Accent surface', cs: 'Akcentní povrch' },\n secondary: { en: 'Secondary surface', cs: 'Sekundární povrch' },\n primary: { en: 'Primary surface', cs: 'Primární povrch' },\n popover: { en: 'Popover surface', cs: 'Popover povrch' },\n }\n\n return {\n value: key,\n label: labelMap[key] ?? { en: key, cs: key },\n color: value,\n }\n })\n .filter((token): token is NonNullable<typeof token> => token !== null)\n\n return tokens.length > 0 ? tokens : FALLBACK_TOKENS\n}\n\nexport default function ThemeTokenSelectField(props: SelectFieldClientProps) {\n const { path, field } = props\n const { value, setValue } = useField<string>({ path })\n const [options, setOptions] = useState<ThemeColorOption[]>(FALLBACK_TOKENS)\n const selectedValue = value || 'background'\n\n // Get themePresets from admin.custom or use defaults\n const themePresets = useMemo(() => {\n const customPresets = (field.admin?.custom as { themePresets?: ThemePreset[] })?.themePresets\n return customPresets && customPresets.length > 0 ? customPresets : allThemePresets\n }, [field.admin?.custom])\n\n useEffect(() => {\n let isMounted = true\n\n // Allow fields to override fetch options via admin.custom\n type CustomAdmin = {\n fetchThemeConfigurationOptions?: FetchThemeConfigurationOptions\n fetchOptions?: FetchThemeConfigurationOptions\n collectionSlug?: string\n useGlobal?: boolean\n tenantSlug?: string\n depth?: number\n locale?: string\n draft?: boolean\n queryParams?: Record<string, unknown>\n }\n\n const custom = (field.admin?.custom as unknown as CustomAdmin) ?? {}\n\n const fetchOpts: FetchThemeConfigurationOptions | undefined =\n custom.fetchThemeConfigurationOptions ??\n custom.fetchOptions ??\n (custom.collectionSlug || typeof custom.useGlobal !== 'undefined'\n ? ({\n collectionSlug: custom.collectionSlug,\n useGlobal: custom.useGlobal,\n tenantSlug: custom.tenantSlug,\n depth: custom.depth,\n locale: custom.locale,\n draft: custom.draft,\n queryParams: custom.queryParams,\n } as unknown as FetchThemeConfigurationOptions)\n : undefined)\n\n fetchThemeConfiguration(fetchOpts).then(async (configuration) => {\n if (!isMounted) return\n if (configuration) {\n setOptions(buildOptionsFromConfiguration(configuration, themePresets))\n return\n }\n\n // If nothing found and fetchOpts didn't explicitly request global, try fallback to global\n // This helps in setups where plugin created a standalone global (default slug 'appearance-settings')\n const explicitlyRequestedGlobal = !!(\n (fetchOpts as FetchThemeConfigurationOptions | undefined)?.useGlobal === true ||\n (fetchOpts as FetchThemeConfigurationOptions | undefined)?.collectionSlug ===\n 'appearance-settings'\n )\n\n if (!explicitlyRequestedGlobal) {\n try {\n // Prefer custom.collectionSlug if provided, otherwise try the default standalone slug\n const fallbackCollection = (custom && custom.collectionSlug) || 'appearance-settings'\n const fallbackOpts: FetchThemeConfigurationOptions = {\n useGlobal: true,\n collectionSlug: fallbackCollection,\n }\n const fallbackConfig = await fetchThemeConfiguration(fallbackOpts)\n if (!isMounted) return\n if (fallbackConfig) {\n // Found theme config in global, use it\n setOptions(buildOptionsFromConfiguration(fallbackConfig, themePresets))\n return\n }\n } catch (e) {\n console.warn('[ThemeTokenSelectField] Fallback global fetch failed:', e)\n }\n }\n\n // final fallback: use empty tokens\n setOptions(buildOptionsFromConfiguration(configuration, themePresets))\n })\n\n return () => {\n isMounted = false\n }\n }, [themePresets, field.admin?.custom])\n\n const handleSelect = useCallback(\n (nextValue: string) => {\n setValue(nextValue)\n },\n [setValue],\n )\n\n const label =\n typeof field.label === 'string' ? field.label : field.label?.en || field.label?.cs || ''\n let description = ''\n if (typeof field.admin?.description === 'string') {\n description = field.admin.description\n } else if (\n field.admin?.description &&\n typeof field.admin.description === 'object' &&\n typeof field.admin.description.en === 'string'\n ) {\n description = field.admin.description.en\n }\n\n // Helper function to get label text from localized or string label\n const getOptionLabel = (option: ThemeColorOption): string => {\n if (typeof option.label === 'string') {\n return option.label\n }\n // Prefer English, fallback to Czech, then any available language\n return option.label.en || option.label.cs || Object.values(option.label)[0] || option.value\n }\n\n // Resolve CSS variable colors (e.g., 'var(--primary)') to their computed values when possible\n const resolveCssColor = (color: string): string => {\n if (typeof window === 'undefined' || !color || !color.trim().startsWith('var(')) {\n return color\n }\n\n try {\n const match = color.trim().match(/var\\((--[^)]+)\\)/)\n if (!match) return color\n const varName = match[1]\n const computed = getComputedStyle(document.documentElement).getPropertyValue(varName).trim()\n return computed || color\n } catch (e) {\n return color\n }\n }\n\n return (\n <div className=\"field-type theme-token-select\">\n {label && (\n <label\n className=\"field-label\"\n htmlFor={path}\n style={{ display: 'block', marginBottom: '8px' }}\n >\n {label}\n {field.required && <span className=\"required\">*</span>}\n </label>\n )}\n\n {description && (\n <div\n className=\"field-description\"\n style={{ marginBottom: '12px', fontSize: '13px', color: 'var(--theme-elevation-500)' }}\n >\n {description}\n </div>\n )}\n\n <div\n className=\"token-grid\"\n style={{\n display: 'grid',\n gridTemplateColumns: 'repeat(auto-fill, minmax(140px, 1fr))',\n gap: '10px',\n }}\n >\n {options.map((option) => {\n const isActive = option.value === selectedValue\n return (\n <button\n type=\"button\"\n key={option.value}\n onClick={() => handleSelect(option.value)}\n style={{\n display: 'flex',\n alignItems: 'center',\n gap: '10px',\n padding: '10px 12px',\n borderRadius: '10px',\n border: isActive\n ? '2px solid var(--theme-success-500)'\n : '1px solid var(--theme-elevation-150)',\n backgroundColor: 'var(--theme-elevation-0)',\n boxShadow: isActive\n ? '0 10px 20px -10px rgba(59, 130, 246, 0.4)'\n : '0 1px 2px rgba(15, 23, 42, 0.08)',\n cursor: 'pointer',\n transition: 'border-color 0.2s ease, box-shadow 0.2s ease',\n }}\n >\n <span\n aria-hidden\n style={{\n width: '32px',\n height: '32px',\n borderRadius: '8px',\n border: '1px solid rgba(15, 23, 42, 0.08)',\n backgroundColor: resolveCssColor(option.color),\n flexShrink: 0,\n }}\n />\n <span\n style={{ fontSize: '13px', fontWeight: 600, color: 'var(--theme-elevation-800)' }}\n >\n {getOptionLabel(option)}\n </span>\n </button>\n )\n })}\n </div>\n\n <select\n id={path}\n value={selectedValue}\n onChange={(event) => handleSelect(event.target.value)}\n style={{ display: 'none' }}\n >\n {options.map((option) => (\n <option key={option.value} value={option.value}>\n {getOptionLabel(option)}\n </option>\n ))}\n </select>\n </div>\n )\n}\n"],"names":["useField","useCallback","useEffect","useMemo","useState","allThemePresets","fetchThemeConfiguration","resolveThemeConfiguration","FALLBACK_TOKENS","value","label","en","cs","color","buildOptionsFromConfiguration","configuration","themePresets","resolved","lightMode","orderedKeys","typedLightMode","tokens","map","key","trim","length","labelMap","background","card","muted","accent","secondary","primary","popover","filter","token","ThemeTokenSelectField","props","path","field","setValue","options","setOptions","selectedValue","customPresets","admin","custom","isMounted","fetchOpts","fetchThemeConfigurationOptions","fetchOptions","collectionSlug","useGlobal","tenantSlug","depth","locale","draft","queryParams","undefined","then","explicitlyRequestedGlobal","fallbackCollection","fallbackOpts","fallbackConfig","e","console","warn","handleSelect","nextValue","description","getOptionLabel","option","Object","values","resolveCssColor","window","startsWith","match","varName","computed","getComputedStyle","document","documentElement","getPropertyValue","div","className","htmlFor","style","display","marginBottom","required","span","fontSize","gridTemplateColumns","gap","isActive","button","type","onClick","alignItems","padding","borderRadius","border","backgroundColor","boxShadow","cursor","transition","aria-hidden","width","height","flexShrink","fontWeight","select","id","onChange","event","target"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FontPreview.d.ts","sourceRoot":"","sources":["../../../../src/globals/ThemeSettings/FontPicker/FontPreview.tsx"],"names":[],"mappings":"AAEA,OAAO,KAA4B,MAAM,OAAO,CAAA;AAChD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,qCAAqC,CAAA;
|
|
1
|
+
{"version":3,"file":"FontPreview.d.ts","sourceRoot":"","sources":["../../../../src/globals/ThemeSettings/FontPicker/FontPreview.tsx"],"names":[],"mappings":"AAEA,OAAO,KAA4B,MAAM,OAAO,CAAA;AAChD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,qCAAqC,CAAA;AAIrE,MAAM,MAAM,cAAc,GACtB,IAAI,GACJ,IAAI,GACJ,IAAI,GACJ,MAAM,GACN,OAAO,GACP,OAAO,GACP,SAAS,GACT,MAAM,GACN,KAAK,GACL,MAAM,CAAA;AAEV,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,UAAU,CAAA;IAChB,OAAO,EAAE,cAAc,CAAA;IACvB,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,MAAM,CAAC,EAAE,MAAM,IAAI,CAAA;CACpB;AAED;;;;;GAKG;AACH,eAAO,MAAM,WAAW,EAAE,KAAK,CAAC,EAAE,CAAC,gBAAgB,CAgPlD,CAAA"}
|