@kilivi/payloadcms-theme-management 1.0.0 → 1.0.2
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/dist/constants/themeFonts.d.ts +6 -0
- package/dist/constants/themeFonts.d.ts.map +1 -1
- package/dist/constants/themeFonts.js +8 -0
- package/dist/constants/themeFonts.js.map +1 -1
- package/dist/fields/FontSelectField.js +1 -1
- package/dist/fields/FontSelectField.js.map +1 -1
- package/dist/fields/ThemePreviewField.d.ts.map +1 -1
- package/dist/fields/ThemePreviewField.js +6 -2
- package/dist/fields/ThemePreviewField.js.map +1 -1
- package/dist/fields/ThemeTokenSelectField.d.ts.map +1 -1
- package/dist/fields/ThemeTokenSelectField.js +132 -35
- package/dist/fields/ThemeTokenSelectField.js.map +1 -1
- package/package.json +1 -1
|
@@ -78,6 +78,9 @@ export declare const HEADING_FONT_OPTIONS: readonly [{
|
|
|
78
78
|
readonly value: "custom";
|
|
79
79
|
}];
|
|
80
80
|
export declare const BASE_FONT_SIZE_OPTIONS: readonly [{
|
|
81
|
+
readonly label: "preset";
|
|
82
|
+
readonly value: "preset";
|
|
83
|
+
}, {
|
|
81
84
|
readonly label: "14px";
|
|
82
85
|
readonly value: "14";
|
|
83
86
|
}, {
|
|
@@ -94,6 +97,9 @@ export declare const BASE_FONT_SIZE_OPTIONS: readonly [{
|
|
|
94
97
|
readonly value: "18";
|
|
95
98
|
}];
|
|
96
99
|
export declare const LINE_HEIGHT_OPTIONS: readonly [{
|
|
100
|
+
readonly label: "preset";
|
|
101
|
+
readonly value: "preset";
|
|
102
|
+
}, {
|
|
97
103
|
readonly label: "1.4";
|
|
98
104
|
readonly value: "1.4";
|
|
99
105
|
}, {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"themeFonts.d.ts","sourceRoot":"","sources":["../../src/constants/themeFonts.ts"],"names":[],"mappings":"AACA,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA6CpB,CAAA;AAEV,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAuCvB,CAAA;AAEV,eAAO,MAAM,sBAAsB
|
|
1
|
+
{"version":3,"file":"themeFonts.d.ts","sourceRoot":"","sources":["../../src/constants/themeFonts.ts"],"names":[],"mappings":"AACA,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA6CpB,CAAA;AAEV,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAuCvB,CAAA;AAEV,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;;;;;;EAOzB,CAAA;AAEV,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;EAOtB,CAAA;AAEV,eAAO,MAAM,iBAAiB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAWpD,CAAA"}
|
|
@@ -98,6 +98,10 @@ export const HEADING_FONT_OPTIONS = [
|
|
|
98
98
|
}
|
|
99
99
|
];
|
|
100
100
|
export const BASE_FONT_SIZE_OPTIONS = [
|
|
101
|
+
{
|
|
102
|
+
label: 'preset',
|
|
103
|
+
value: 'preset'
|
|
104
|
+
},
|
|
101
105
|
{
|
|
102
106
|
label: '14px',
|
|
103
107
|
value: '14'
|
|
@@ -120,6 +124,10 @@ export const BASE_FONT_SIZE_OPTIONS = [
|
|
|
120
124
|
}
|
|
121
125
|
];
|
|
122
126
|
export const LINE_HEIGHT_OPTIONS = [
|
|
127
|
+
{
|
|
128
|
+
label: 'preset',
|
|
129
|
+
value: 'preset'
|
|
130
|
+
},
|
|
123
131
|
{
|
|
124
132
|
label: '1.4',
|
|
125
133
|
value: '1.4'
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/constants/themeFonts.ts"],"sourcesContent":["// Theme font constants for the plugin\nexport const BODY_FONT_OPTIONS = [\n { label: 'Use theme preset', value: 'preset' },\n {\n label: 'System',\n value: 'system-ui',\n fontFamily: 'system-ui, -apple-system, BlinkMacSystemFont, \"Segoe UI\", sans-serif',\n category: 'sans-serif' as const,\n },\n {\n label: 'Inter',\n value: 'Inter',\n fontFamily: '\"Inter\", sans-serif',\n category: 'sans-serif' as const,\n },\n {\n label: 'Roboto',\n value: 'Roboto',\n fontFamily: '\"Roboto\", sans-serif',\n category: 'sans-serif' as const,\n },\n {\n label: 'Open Sans',\n value: 'Open Sans',\n fontFamily: '\"Open Sans\", sans-serif',\n category: 'sans-serif' as const,\n },\n {\n label: 'Lato',\n value: 'Lato',\n fontFamily: '\"Lato\", sans-serif',\n category: 'sans-serif' as const,\n },\n {\n label: 'Montserrat',\n value: 'Montserrat',\n fontFamily: '\"Montserrat\", sans-serif',\n category: 'sans-serif' as const,\n },\n {\n label: 'Poppins',\n value: 'Poppins',\n fontFamily: '\"Poppins\", sans-serif',\n category: 'sans-serif' as const,\n },\n { label: 'Custom font...', value: 'custom' },\n] as const\n\nexport const HEADING_FONT_OPTIONS = [\n { label: 'Use theme preset', value: 'preset' },\n {\n label: 'System',\n value: 'system-ui',\n fontFamily: 'system-ui, -apple-system, BlinkMacSystemFont, \"Segoe UI\", sans-serif',\n category: 'sans-serif' as const,\n },\n {\n label: 'Inter',\n value: 'Inter',\n fontFamily: '\"Inter\", sans-serif',\n category: 'sans-serif' as const,\n },\n {\n label: 'Playfair Display',\n value: 'Playfair Display',\n fontFamily: '\"Playfair Display\", serif',\n category: 'serif' as const,\n },\n {\n label: 'Merriweather',\n value: 'Merriweather',\n fontFamily: '\"Merriweather\", serif',\n category: 'serif' as const,\n },\n {\n label: 'Montserrat',\n value: 'Montserrat',\n fontFamily: '\"Montserrat\", sans-serif',\n category: 'sans-serif' as const,\n },\n {\n label: 'Raleway',\n value: 'Raleway',\n fontFamily: '\"Raleway\", sans-serif',\n category: 'sans-serif' as const,\n },\n { label: 'Custom font...', value: 'custom' },\n] as const\n\nexport const BASE_FONT_SIZE_OPTIONS = [\n { label: '14px', value: '14' },\n { label: '15px', value: '15' },\n { label: '16px', value: '16' },\n { label: '17px', value: '17' },\n { label: '18px', value: '18' },\n] as const\n\nexport const LINE_HEIGHT_OPTIONS = [\n { label: '1.4', value: '1.4' },\n { label: '1.5', value: '1.5' },\n { label: '1.6', value: '1.6' },\n { label: '1.7', value: '1.7' },\n { label: '1.8', value: '1.8' },\n] as const\n\nexport const FONT_VALUE_TO_CSS: Record<string, string> = {\n 'system-ui': 'system-ui, -apple-system, BlinkMacSystemFont, \"Segoe UI\", sans-serif',\n Inter: '\"Inter\", sans-serif',\n Roboto: '\"Roboto\", sans-serif',\n 'Open Sans': '\"Open Sans\", sans-serif',\n Lato: '\"Lato\", sans-serif',\n Montserrat: '\"Montserrat\", sans-serif',\n Poppins: '\"Poppins\", sans-serif',\n 'Playfair Display': '\"Playfair Display\", serif',\n Merriweather: '\"Merriweather\", serif',\n Raleway: '\"Raleway\", sans-serif',\n}\n"],"names":["BODY_FONT_OPTIONS","label","value","fontFamily","category","HEADING_FONT_OPTIONS","BASE_FONT_SIZE_OPTIONS","LINE_HEIGHT_OPTIONS","FONT_VALUE_TO_CSS","Inter","Roboto","Lato","Montserrat","Poppins","Merriweather","Raleway"],"mappings":"AAAA,sCAAsC;AACtC,OAAO,MAAMA,oBAAoB;IAC/B;QAAEC,OAAO;QAAoBC,OAAO;IAAS;IAC7C;QACED,OAAO;QACPC,OAAO;QACPC,YAAY;QACZC,UAAU;IACZ;IACA;QACEH,OAAO;QACPC,OAAO;QACPC,YAAY;QACZC,UAAU;IACZ;IACA;QACEH,OAAO;QACPC,OAAO;QACPC,YAAY;QACZC,UAAU;IACZ;IACA;QACEH,OAAO;QACPC,OAAO;QACPC,YAAY;QACZC,UAAU;IACZ;IACA;QACEH,OAAO;QACPC,OAAO;QACPC,YAAY;QACZC,UAAU;IACZ;IACA;QACEH,OAAO;QACPC,OAAO;QACPC,YAAY;QACZC,UAAU;IACZ;IACA;QACEH,OAAO;QACPC,OAAO;QACPC,YAAY;QACZC,UAAU;IACZ;IACA;QAAEH,OAAO;QAAkBC,OAAO;IAAS;CAC5C,CAAS;AAEV,OAAO,MAAMG,uBAAuB;IAClC;QAAEJ,OAAO;QAAoBC,OAAO;IAAS;IAC7C;QACED,OAAO;QACPC,OAAO;QACPC,YAAY;QACZC,UAAU;IACZ;IACA;QACEH,OAAO;QACPC,OAAO;QACPC,YAAY;QACZC,UAAU;IACZ;IACA;QACEH,OAAO;QACPC,OAAO;QACPC,YAAY;QACZC,UAAU;IACZ;IACA;QACEH,OAAO;QACPC,OAAO;QACPC,YAAY;QACZC,UAAU;IACZ;IACA;QACEH,OAAO;QACPC,OAAO;QACPC,YAAY;QACZC,UAAU;IACZ;IACA;QACEH,OAAO;QACPC,OAAO;QACPC,YAAY;QACZC,UAAU;IACZ;IACA;QAAEH,OAAO;QAAkBC,OAAO;IAAS;CAC5C,CAAS;AAEV,OAAO,MAAMI,yBAAyB;IACpC;QAAEL,OAAO;QAAQC,OAAO;IAAK;IAC7B;QAAED,OAAO;QAAQC,OAAO;IAAK;IAC7B;QAAED,OAAO;QAAQC,OAAO;IAAK;IAC7B;QAAED,OAAO;QAAQC,OAAO;IAAK;IAC7B;QAAED,OAAO;QAAQC,OAAO;IAAK;CAC9B,CAAS;AAEV,OAAO,MAAMK,sBAAsB;IACjC;QAAEN,OAAO;QAAOC,OAAO;IAAM;IAC7B;QAAED,OAAO;QAAOC,OAAO;IAAM;IAC7B;QAAED,OAAO;QAAOC,OAAO;IAAM;IAC7B;QAAED,OAAO;QAAOC,OAAO;IAAM;IAC7B;QAAED,OAAO;QAAOC,OAAO;IAAM;CAC9B,CAAS;AAEV,OAAO,MAAMM,oBAA4C;IACvD,aAAa;IACbC,OAAO;IACPC,QAAQ;IACR,aAAa;IACbC,MAAM;IACNC,YAAY;IACZC,SAAS;IACT,oBAAoB;IACpBC,cAAc;IACdC,SAAS;AACX,EAAC"}
|
|
1
|
+
{"version":3,"sources":["../../src/constants/themeFonts.ts"],"sourcesContent":["// Theme font constants for the plugin\nexport const BODY_FONT_OPTIONS = [\n { label: 'Use theme preset', value: 'preset' },\n {\n label: 'System',\n value: 'system-ui',\n fontFamily: 'system-ui, -apple-system, BlinkMacSystemFont, \"Segoe UI\", sans-serif',\n category: 'sans-serif' as const,\n },\n {\n label: 'Inter',\n value: 'Inter',\n fontFamily: '\"Inter\", sans-serif',\n category: 'sans-serif' as const,\n },\n {\n label: 'Roboto',\n value: 'Roboto',\n fontFamily: '\"Roboto\", sans-serif',\n category: 'sans-serif' as const,\n },\n {\n label: 'Open Sans',\n value: 'Open Sans',\n fontFamily: '\"Open Sans\", sans-serif',\n category: 'sans-serif' as const,\n },\n {\n label: 'Lato',\n value: 'Lato',\n fontFamily: '\"Lato\", sans-serif',\n category: 'sans-serif' as const,\n },\n {\n label: 'Montserrat',\n value: 'Montserrat',\n fontFamily: '\"Montserrat\", sans-serif',\n category: 'sans-serif' as const,\n },\n {\n label: 'Poppins',\n value: 'Poppins',\n fontFamily: '\"Poppins\", sans-serif',\n category: 'sans-serif' as const,\n },\n { label: 'Custom font...', value: 'custom' },\n] as const\n\nexport const HEADING_FONT_OPTIONS = [\n { label: 'Use theme preset', value: 'preset' },\n {\n label: 'System',\n value: 'system-ui',\n fontFamily: 'system-ui, -apple-system, BlinkMacSystemFont, \"Segoe UI\", sans-serif',\n category: 'sans-serif' as const,\n },\n {\n label: 'Inter',\n value: 'Inter',\n fontFamily: '\"Inter\", sans-serif',\n category: 'sans-serif' as const,\n },\n {\n label: 'Playfair Display',\n value: 'Playfair Display',\n fontFamily: '\"Playfair Display\", serif',\n category: 'serif' as const,\n },\n {\n label: 'Merriweather',\n value: 'Merriweather',\n fontFamily: '\"Merriweather\", serif',\n category: 'serif' as const,\n },\n {\n label: 'Montserrat',\n value: 'Montserrat',\n fontFamily: '\"Montserrat\", sans-serif',\n category: 'sans-serif' as const,\n },\n {\n label: 'Raleway',\n value: 'Raleway',\n fontFamily: '\"Raleway\", sans-serif',\n category: 'sans-serif' as const,\n },\n { label: 'Custom font...', value: 'custom' },\n] as const\n\nexport const BASE_FONT_SIZE_OPTIONS = [\n { label: 'preset', value: 'preset' },\n { label: '14px', value: '14' },\n { label: '15px', value: '15' },\n { label: '16px', value: '16' },\n { label: '17px', value: '17' },\n { label: '18px', value: '18' },\n] as const\n\nexport const LINE_HEIGHT_OPTIONS = [\n { label: 'preset', value: 'preset' },\n { label: '1.4', value: '1.4' },\n { label: '1.5', value: '1.5' },\n { label: '1.6', value: '1.6' },\n { label: '1.7', value: '1.7' },\n { label: '1.8', value: '1.8' },\n] as const\n\nexport const FONT_VALUE_TO_CSS: Record<string, string> = {\n 'system-ui': 'system-ui, -apple-system, BlinkMacSystemFont, \"Segoe UI\", sans-serif',\n Inter: '\"Inter\", sans-serif',\n Roboto: '\"Roboto\", sans-serif',\n 'Open Sans': '\"Open Sans\", sans-serif',\n Lato: '\"Lato\", sans-serif',\n Montserrat: '\"Montserrat\", sans-serif',\n Poppins: '\"Poppins\", sans-serif',\n 'Playfair Display': '\"Playfair Display\", serif',\n Merriweather: '\"Merriweather\", serif',\n Raleway: '\"Raleway\", sans-serif',\n}\n"],"names":["BODY_FONT_OPTIONS","label","value","fontFamily","category","HEADING_FONT_OPTIONS","BASE_FONT_SIZE_OPTIONS","LINE_HEIGHT_OPTIONS","FONT_VALUE_TO_CSS","Inter","Roboto","Lato","Montserrat","Poppins","Merriweather","Raleway"],"mappings":"AAAA,sCAAsC;AACtC,OAAO,MAAMA,oBAAoB;IAC/B;QAAEC,OAAO;QAAoBC,OAAO;IAAS;IAC7C;QACED,OAAO;QACPC,OAAO;QACPC,YAAY;QACZC,UAAU;IACZ;IACA;QACEH,OAAO;QACPC,OAAO;QACPC,YAAY;QACZC,UAAU;IACZ;IACA;QACEH,OAAO;QACPC,OAAO;QACPC,YAAY;QACZC,UAAU;IACZ;IACA;QACEH,OAAO;QACPC,OAAO;QACPC,YAAY;QACZC,UAAU;IACZ;IACA;QACEH,OAAO;QACPC,OAAO;QACPC,YAAY;QACZC,UAAU;IACZ;IACA;QACEH,OAAO;QACPC,OAAO;QACPC,YAAY;QACZC,UAAU;IACZ;IACA;QACEH,OAAO;QACPC,OAAO;QACPC,YAAY;QACZC,UAAU;IACZ;IACA;QAAEH,OAAO;QAAkBC,OAAO;IAAS;CAC5C,CAAS;AAEV,OAAO,MAAMG,uBAAuB;IAClC;QAAEJ,OAAO;QAAoBC,OAAO;IAAS;IAC7C;QACED,OAAO;QACPC,OAAO;QACPC,YAAY;QACZC,UAAU;IACZ;IACA;QACEH,OAAO;QACPC,OAAO;QACPC,YAAY;QACZC,UAAU;IACZ;IACA;QACEH,OAAO;QACPC,OAAO;QACPC,YAAY;QACZC,UAAU;IACZ;IACA;QACEH,OAAO;QACPC,OAAO;QACPC,YAAY;QACZC,UAAU;IACZ;IACA;QACEH,OAAO;QACPC,OAAO;QACPC,YAAY;QACZC,UAAU;IACZ;IACA;QACEH,OAAO;QACPC,OAAO;QACPC,YAAY;QACZC,UAAU;IACZ;IACA;QAAEH,OAAO;QAAkBC,OAAO;IAAS;CAC5C,CAAS;AAEV,OAAO,MAAMI,yBAAyB;IACpC;QAAEL,OAAO;QAAUC,OAAO;IAAS;IACnC;QAAED,OAAO;QAAQC,OAAO;IAAK;IAC7B;QAAED,OAAO;QAAQC,OAAO;IAAK;IAC7B;QAAED,OAAO;QAAQC,OAAO;IAAK;IAC7B;QAAED,OAAO;QAAQC,OAAO;IAAK;IAC7B;QAAED,OAAO;QAAQC,OAAO;IAAK;CAC9B,CAAS;AAEV,OAAO,MAAMK,sBAAsB;IACjC;QAAEN,OAAO;QAAUC,OAAO;IAAS;IACnC;QAAED,OAAO;QAAOC,OAAO;IAAM;IAC7B;QAAED,OAAO;QAAOC,OAAO;IAAM;IAC7B;QAAED,OAAO;QAAOC,OAAO;IAAM;IAC7B;QAAED,OAAO;QAAOC,OAAO;IAAM;IAC7B;QAAED,OAAO;QAAOC,OAAO;IAAM;CAC9B,CAAS;AAEV,OAAO,MAAMM,oBAA4C;IACvD,aAAa;IACbC,OAAO;IACPC,QAAQ;IACR,aAAa;IACbC,MAAM;IACNC,YAAY;IACZC,SAAS;IACT,oBAAoB;IACpBC,cAAc;IACdC,SAAS;AACX,EAAC"}
|
|
@@ -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: '100%',\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'\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":"AAAA;;AAEA,SAASA,QAAQ,QAAQ,iBAAgB;AAEzC,SAASC,SAAS,EAAEC,QAAQ,QAAQ,QAAO;AAS3C,MAAMC,kBAA8C,CAAC,EAAEC,KAAK,EAAEC,IAAI,EAAE;IAClE,MAAM,EAAEC,KAAK,EAAEC,QAAQ,EAAE,GAAGP,SAAiB;QAAEK;IAAK;IACpD,MAAM,CAACG,QAAQC,UAAU,GAAGP,SAAS;IAErC,MAAMQ,UAAU,AAACN,MAAMM,OAAO,IAAqB,EAAE;IACrD,MAAMC,iBAAiBD,QAAQE,IAAI,CAAC,CAACC,MAAQA,IAAIP,KAAK,KAAKA;IAE3D,MAAMQ,eAAe,CAACC;QACpBR,SAASQ;QACTN,UAAU;IACZ;IAEAR,UAAU;QACR,MAAMe,qBAAqB,CAACC;YAC1B,MAAMC,SAASD,EAAEC,MAAM;YACvB,IAAI,CAACA,OAAOC,OAAO,CAAC,2BAA2B;gBAC7CV,UAAU;YACZ;QACF;QAEA,IAAID,QAAQ;YACVY,SAASC,gBAAgB,CAAC,aAAaL;YACvC,OAAO,IAAMI,SAASE,mBAAmB,CAAC,aAAaN;QACzD;IACF,GAAG;QAACR;KAAO;IAEX,MAAMe,QACJ,OAAOnB,MAAMmB,KAAK,KAAK,WAAWnB,MAAMmB,KAAK,GAAGnB,MAAMmB,KAAK,EAAEC,MAAMpB,MAAMmB,KAAK,EAAEE,MAAM;IAExF,qBACE,MAACC;QAAIC,WAAU;QAAwBC,OAAO;YAAEC,UAAU;YAAYC,cAAc;QAAO;;0BACzF,KAACP;gBACCK,OAAO;oBACLG,SAAS;oBACTD,cAAc;oBACdE,UAAU;oBACVC,YAAY;oBACZC,OAAO;gBACT;0BAECX;;0BAGH,MAACY;gBACCC,MAAK;gBACLC,SAAS,IAAM5B,UAAU,CAACD;gBAC1BoB,OAAO;oBACLU,OAAO;oBACPC,SAAS;oBACTC,cAAc;oBACdC,QAAQ;oBACRC,iBAAiB;oBACjBR,OAAO;oBACPS,WAAW;oBACXC,QAAQ;oBACRb,SAAS;oBACTc,gBAAgB;oBAChBC,YAAY;oBACZd,UAAU;oBACVe,YAAYpC,gBAAgBoC,cAAc;oBAC1CC,YAAY;gBACd;gBACAC,cAAc,CAAChC;oBACbA,EAAEiC,aAAa,CAACtB,KAAK,CAACuB,WAAW,GAAG;gBACtC;gBACAC,cAAc,CAACnC;oBACbA,EAAEiC,aAAa,CAACtB,KAAK,CAACuB,WAAW,GAAG;gBACtC;;kCAEA,KAACE;wBAAKzB,OAAO;4BAAE0B,MAAM;wBAAE;kCAAI3C,gBAAgBY,SAAS;;kCACpD,KAACgC;wBACCjB,OAAM;wBACNkB,QAAO;wBACPC,SAAQ;wBACRC,MAAK;wBACL9B,OAAO;4BACLoB,YAAY;4BACZW,WAAWnD,SAAS,mBAAmB;wBACzC;kCAEA,cAAA,KAACH;4BACCuD,GAAE;4BACFC,QAAO;4BACPC,aAAY;4BACZC,eAAc;4BACdC,gBAAe;;;;;YAKpBxD,wBACC,KAACkB;gBACCE,OAAO;oBACLC,UAAU;oBACVoC,KAAK;oBACLC,MAAM;oBACNC,OAAO;oBACPC,WAAW;oBACXC,WAAW;oBACXC,WAAW;oBACX5B,iBAAiB;oBACjBD,QAAQ;oBACRD,cAAc;oBACd+B,WAAW;oBACXC,QAAQ;gBACV;0BAEC9D,QAAQ+D,GAAG,CAAC,CAACC;oBACZ,MAAMC,aAAaD,OAAOpE,KAAK,KAAKA;oBAEpC,IAAIyC,aAAa2B,OAAO3B,UAAU;oBAClC,IAAI,CAACA,YAAY;wBACf,IAAI2B,OAAOE,QAAQ,KAAK,cAAc7B,aAAa;6BAC9C,IAAI2B,OAAOE,QAAQ,KAAK,SAAS7B,aAAa;6BAC9C,IAAI2B,OAAOE,QAAQ,KAAK,aAAa7B,aAAa;6BAClDA,aAAa;oBACpB;oBAEA,qBACE,MAACZ;wBAECC,MAAK;wBACLC,SAAS,IAAMvB,aAAa4D,OAAOpE,KAAK;wBACxCsB,OAAO;4BACLU,OAAO;4BACPC,SAAS;4BACTE,QAAQ;4BACRC,iBAAiBiC,aAAa,+BAA+B;4BAC7DzC,OAAO;4BACPS,WAAW;4BACXC,QAAQ;4BACRZ,UAAU;4BACVe;4BACAhB,SAAS;4BACT8C,eAAe;4BACfC,KAAK;4BACL9B,YAAY;wBACd;wBACAC,cAAc,CAAChC;4BACb,IAAI,CAAC0D,YAAY;gCACf1D,EAAEiC,aAAa,CAACtB,KAAK,CAACc,eAAe,GAAG;4BAC1C;wBACF;wBACAU,cAAc,CAACnC;4BACb,IAAI,CAAC0D,YAAY;gCACf1D,EAAEiC,aAAa,CAACtB,KAAK,CAACc,eAAe,GAAG;4BAC1C;wBACF;;0CAEA,MAAChB;gCACCE,OAAO;oCACLK,YAAY0C,aAAa,MAAM;oCAC/B5C,SAAS;oCACTe,YAAY;oCACZgC,KAAK;gCACP;;oCAECH,4BACC,KAACpB;wCAAIjB,OAAM;wCAAKkB,QAAO;wCAAKC,SAAQ;wCAAYC,MAAK;kDACnD,cAAA,KAACrD;4CACCuD,GAAE;4CACFC,QAAO;4CACPC,aAAY;4CACZC,eAAc;4CACdC,gBAAe;;;oCAIpBU,OAAOnD,KAAK;;;0CAEf,KAACG;gCACCE,OAAO;oCACLI,UAAU;oCACVE,OAAO;oCACP6C,WACEL,OAAOpE,KAAK,KAAK,YAAYoE,OAAOpE,KAAK,KAAK,WAAW,WAAW;gCACxE;0CAEC,AAAC,CAAA;oCACA,IAAIoE,OAAOpE,KAAK,KAAK,UAAU,OAAO;oCACtC,IAAIoE,OAAOpE,KAAK,KAAK,UAAU,OAAO;oCACtC,OAAO;gCACT,CAAA;;;uBA9DGoE,OAAOpE,KAAK;gBAkEvB;;;;AAKV;AAEA,eAAeH,gBAAe"}
|
|
@@ -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;AA2PrD,MAAM,CAAC,OAAO,UAAU,iBAAiB,CAAC,KAAK,EAAE,sBAAsB,+
|
|
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,+BAyZtE"}
|
|
@@ -239,8 +239,12 @@ function ModePreview({ icon, title, colors, typography, radius }) {
|
|
|
239
239
|
}
|
|
240
240
|
export default function ThemePreviewField(props) {
|
|
241
241
|
const { field, path } = props;
|
|
242
|
-
// If the plugin provided theme presets via admin config, prefer those;
|
|
243
|
-
|
|
242
|
+
// If the plugin provided theme presets via admin config, prefer those;
|
|
243
|
+
// support both `field.admin.themePresets` (legacy) and `field.admin.custom.themePresets`
|
|
244
|
+
// otherwise fallback to `allThemePresets`.
|
|
245
|
+
// Prefer presets passed via `admin.custom.themePresets` (set by the field factory / plugin).
|
|
246
|
+
// Fall back to legacy `admin.themePresets` for backwards compatibility, then to `allThemePresets`.
|
|
247
|
+
const baseThemePresets = field?.admin?.custom?.themePresets ?? field?.admin?.themePresets ?? allThemePresets;
|
|
244
248
|
const runtimeThemePresets = useMemo(()=>{
|
|
245
249
|
return baseThemePresets.reduce((acc, preset)=>{
|
|
246
250
|
acc[preset.name] = {
|
|
@@ -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; 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
|
+
{"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 +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;
|
|
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,+BAoN1E"}
|
|
@@ -2,53 +2,61 @@
|
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
3
|
import { useField } from '@payloadcms/ui';
|
|
4
4
|
import { useCallback, useEffect, useMemo, useState } from 'react';
|
|
5
|
-
import { allThemePresets } from '../index.js';
|
|
5
|
+
import { allThemePresets, fetchThemeConfiguration } from '../index.js';
|
|
6
6
|
import { resolveThemeConfiguration } from '../utils/resolveThemeConfiguration.js';
|
|
7
7
|
const FALLBACK_TOKENS = [
|
|
8
8
|
{
|
|
9
9
|
value: 'background',
|
|
10
|
-
label:
|
|
10
|
+
label: {
|
|
11
|
+
en: 'Theme background',
|
|
12
|
+
cs: 'Pozadí tématu'
|
|
13
|
+
},
|
|
11
14
|
color: 'var(--background)'
|
|
12
15
|
},
|
|
13
16
|
{
|
|
14
17
|
value: 'card',
|
|
15
|
-
label:
|
|
18
|
+
label: {
|
|
19
|
+
en: 'Card background',
|
|
20
|
+
cs: 'Pozadí karty'
|
|
21
|
+
},
|
|
16
22
|
color: 'var(--card)'
|
|
17
23
|
},
|
|
18
24
|
{
|
|
19
25
|
value: 'muted',
|
|
20
|
-
label:
|
|
26
|
+
label: {
|
|
27
|
+
en: 'Muted surface',
|
|
28
|
+
cs: 'Tlumený povrch'
|
|
29
|
+
},
|
|
21
30
|
color: 'var(--muted)'
|
|
22
31
|
},
|
|
23
32
|
{
|
|
24
33
|
value: 'accent',
|
|
25
|
-
label:
|
|
34
|
+
label: {
|
|
35
|
+
en: 'Accent surface',
|
|
36
|
+
cs: 'Akcentní povrch'
|
|
37
|
+
},
|
|
26
38
|
color: 'var(--accent)'
|
|
27
39
|
},
|
|
28
40
|
{
|
|
29
41
|
value: 'secondary',
|
|
30
|
-
label:
|
|
42
|
+
label: {
|
|
43
|
+
en: 'Secondary surface',
|
|
44
|
+
cs: 'Sekundární povrch'
|
|
45
|
+
},
|
|
31
46
|
color: 'var(--secondary)'
|
|
32
47
|
},
|
|
33
48
|
{
|
|
34
49
|
value: 'primary',
|
|
35
|
-
label:
|
|
50
|
+
label: {
|
|
51
|
+
en: 'Primary surface',
|
|
52
|
+
cs: 'Primární povrch'
|
|
53
|
+
},
|
|
36
54
|
color: 'var(--primary)'
|
|
37
55
|
}
|
|
38
56
|
];
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
if (!response.ok) {
|
|
43
|
-
return null;
|
|
44
|
-
}
|
|
45
|
-
const data = await response.json();
|
|
46
|
-
return data?.docs?.[0]?.themeConfiguration ?? null;
|
|
47
|
-
} catch (error) {
|
|
48
|
-
console.warn('[ThemeTokenSelectField] Failed to fetch theme configuration:', error);
|
|
49
|
-
return null;
|
|
50
|
-
}
|
|
51
|
-
}
|
|
57
|
+
// Use plugin-provided fetch helper which supports collection/global and options
|
|
58
|
+
// This will use `collectionSlug`, `useGlobal`, tenant, locale, depth, draft, etc.
|
|
59
|
+
// Accept fetch options from field.admin.custom to allow overrides in different setups.
|
|
52
60
|
function buildOptionsFromConfiguration(configuration, themePresets) {
|
|
53
61
|
if (!configuration) {
|
|
54
62
|
return FALLBACK_TOKENS;
|
|
@@ -71,20 +79,44 @@ function buildOptionsFromConfiguration(configuration, themePresets) {
|
|
|
71
79
|
return null;
|
|
72
80
|
}
|
|
73
81
|
const labelMap = {
|
|
74
|
-
background:
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
82
|
+
background: {
|
|
83
|
+
en: 'Theme background',
|
|
84
|
+
cs: 'Pozadí tématu'
|
|
85
|
+
},
|
|
86
|
+
card: {
|
|
87
|
+
en: 'Card background',
|
|
88
|
+
cs: 'Pozadí karty'
|
|
89
|
+
},
|
|
90
|
+
muted: {
|
|
91
|
+
en: 'Muted surface',
|
|
92
|
+
cs: 'Tlumený povrch'
|
|
93
|
+
},
|
|
94
|
+
accent: {
|
|
95
|
+
en: 'Accent surface',
|
|
96
|
+
cs: 'Akcentní povrch'
|
|
97
|
+
},
|
|
98
|
+
secondary: {
|
|
99
|
+
en: 'Secondary surface',
|
|
100
|
+
cs: 'Sekundární povrch'
|
|
101
|
+
},
|
|
102
|
+
primary: {
|
|
103
|
+
en: 'Primary surface',
|
|
104
|
+
cs: 'Primární povrch'
|
|
105
|
+
},
|
|
106
|
+
popover: {
|
|
107
|
+
en: 'Popover surface',
|
|
108
|
+
cs: 'Popover povrch'
|
|
109
|
+
}
|
|
81
110
|
};
|
|
82
111
|
return {
|
|
83
112
|
value: key,
|
|
84
|
-
label: labelMap[key] ??
|
|
113
|
+
label: labelMap[key] ?? {
|
|
114
|
+
en: key,
|
|
115
|
+
cs: key
|
|
116
|
+
},
|
|
85
117
|
color: value
|
|
86
118
|
};
|
|
87
|
-
}).filter((token)=>
|
|
119
|
+
}).filter((token)=>token !== null);
|
|
88
120
|
return tokens.length > 0 ? tokens : FALLBACK_TOKENS;
|
|
89
121
|
}
|
|
90
122
|
export default function ThemeTokenSelectField(props) {
|
|
@@ -103,26 +135,90 @@ export default function ThemeTokenSelectField(props) {
|
|
|
103
135
|
]);
|
|
104
136
|
useEffect(()=>{
|
|
105
137
|
let isMounted = true;
|
|
106
|
-
|
|
138
|
+
// Allow fields to override fetch options via admin.custom
|
|
139
|
+
const custom = field.admin?.custom ?? {};
|
|
140
|
+
const fetchOpts = custom.fetchThemeConfigurationOptions ?? custom.fetchOptions ?? (custom.collectionSlug || typeof custom.useGlobal !== 'undefined' ? {
|
|
141
|
+
collectionSlug: custom.collectionSlug,
|
|
142
|
+
useGlobal: custom.useGlobal,
|
|
143
|
+
tenantSlug: custom.tenantSlug,
|
|
144
|
+
depth: custom.depth,
|
|
145
|
+
locale: custom.locale,
|
|
146
|
+
draft: custom.draft,
|
|
147
|
+
queryParams: custom.queryParams
|
|
148
|
+
} : undefined);
|
|
149
|
+
fetchThemeConfiguration(fetchOpts).then(async (configuration)=>{
|
|
107
150
|
if (!isMounted) return;
|
|
151
|
+
if (configuration) {
|
|
152
|
+
setOptions(buildOptionsFromConfiguration(configuration, themePresets));
|
|
153
|
+
return;
|
|
154
|
+
}
|
|
155
|
+
// If nothing found and fetchOpts didn't explicitly request global, try fallback to global
|
|
156
|
+
// This helps in setups where plugin created a standalone global (default slug 'appearance-settings')
|
|
157
|
+
const explicitlyRequestedGlobal = !!(fetchOpts?.useGlobal === true || fetchOpts?.collectionSlug === 'appearance-settings');
|
|
158
|
+
if (!explicitlyRequestedGlobal) {
|
|
159
|
+
try {
|
|
160
|
+
// Prefer custom.collectionSlug if provided, otherwise try the default standalone slug
|
|
161
|
+
const fallbackCollection = custom && custom.collectionSlug || 'appearance-settings';
|
|
162
|
+
const fallbackOpts = {
|
|
163
|
+
useGlobal: true,
|
|
164
|
+
collectionSlug: fallbackCollection
|
|
165
|
+
};
|
|
166
|
+
const fallbackConfig = await fetchThemeConfiguration(fallbackOpts);
|
|
167
|
+
if (!isMounted) return;
|
|
168
|
+
if (fallbackConfig) {
|
|
169
|
+
// Found theme config in global, use it
|
|
170
|
+
setOptions(buildOptionsFromConfiguration(fallbackConfig, themePresets));
|
|
171
|
+
return;
|
|
172
|
+
}
|
|
173
|
+
} catch (e) {
|
|
174
|
+
console.warn('[ThemeTokenSelectField] Fallback global fetch failed:', e);
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
// final fallback: use empty tokens
|
|
108
178
|
setOptions(buildOptionsFromConfiguration(configuration, themePresets));
|
|
109
179
|
});
|
|
110
180
|
return ()=>{
|
|
111
181
|
isMounted = false;
|
|
112
182
|
};
|
|
113
|
-
}, [
|
|
183
|
+
}, [
|
|
184
|
+
themePresets,
|
|
185
|
+
field.admin?.custom
|
|
186
|
+
]);
|
|
114
187
|
const handleSelect = useCallback((nextValue)=>{
|
|
115
188
|
setValue(nextValue);
|
|
116
189
|
}, [
|
|
117
190
|
setValue
|
|
118
191
|
]);
|
|
119
|
-
const label = typeof field.label === 'string' ? field.label : '';
|
|
192
|
+
const label = typeof field.label === 'string' ? field.label : field.label?.en || field.label?.cs || '';
|
|
120
193
|
let description = '';
|
|
121
194
|
if (typeof field.admin?.description === 'string') {
|
|
122
195
|
description = field.admin.description;
|
|
123
196
|
} else if (field.admin?.description && typeof field.admin.description === 'object' && typeof field.admin.description.en === 'string') {
|
|
124
197
|
description = field.admin.description.en;
|
|
125
198
|
}
|
|
199
|
+
// Helper function to get label text from localized or string label
|
|
200
|
+
const getOptionLabel = (option)=>{
|
|
201
|
+
if (typeof option.label === 'string') {
|
|
202
|
+
return option.label;
|
|
203
|
+
}
|
|
204
|
+
// Prefer English, fallback to Czech, then any available language
|
|
205
|
+
return option.label.en || option.label.cs || Object.values(option.label)[0] || option.value;
|
|
206
|
+
};
|
|
207
|
+
// Resolve CSS variable colors (e.g., 'var(--primary)') to their computed values when possible
|
|
208
|
+
const resolveCssColor = (color)=>{
|
|
209
|
+
if (typeof window === 'undefined' || !color || !color.trim().startsWith('var(')) {
|
|
210
|
+
return color;
|
|
211
|
+
}
|
|
212
|
+
try {
|
|
213
|
+
const match = color.trim().match(/var\((--[^)]+)\)/);
|
|
214
|
+
if (!match) return color;
|
|
215
|
+
const varName = match[1];
|
|
216
|
+
const computed = getComputedStyle(document.documentElement).getPropertyValue(varName).trim();
|
|
217
|
+
return computed || color;
|
|
218
|
+
} catch (e) {
|
|
219
|
+
return color;
|
|
220
|
+
}
|
|
221
|
+
};
|
|
126
222
|
return /*#__PURE__*/ _jsxs("div", {
|
|
127
223
|
className: "field-type theme-token-select",
|
|
128
224
|
children: [
|
|
@@ -182,7 +278,8 @@ export default function ThemeTokenSelectField(props) {
|
|
|
182
278
|
height: '32px',
|
|
183
279
|
borderRadius: '8px',
|
|
184
280
|
border: '1px solid rgba(15, 23, 42, 0.08)',
|
|
185
|
-
|
|
281
|
+
backgroundColor: resolveCssColor(option.color),
|
|
282
|
+
flexShrink: 0
|
|
186
283
|
}
|
|
187
284
|
}),
|
|
188
285
|
/*#__PURE__*/ _jsx("span", {
|
|
@@ -191,7 +288,7 @@ export default function ThemeTokenSelectField(props) {
|
|
|
191
288
|
fontWeight: 600,
|
|
192
289
|
color: 'var(--theme-elevation-800)'
|
|
193
290
|
},
|
|
194
|
-
children: option
|
|
291
|
+
children: getOptionLabel(option)
|
|
195
292
|
})
|
|
196
293
|
]
|
|
197
294
|
}, option.value);
|
|
@@ -206,7 +303,7 @@ export default function ThemeTokenSelectField(props) {
|
|
|
206
303
|
},
|
|
207
304
|
children: options.map((option)=>/*#__PURE__*/ _jsx("option", {
|
|
208
305
|
value: option.value,
|
|
209
|
-
children: option
|
|
306
|
+
children: getOptionLabel(option)
|
|
210
307
|
}, option.value))
|
|
211
308
|
})
|
|
212
309
|
]
|
|
@@ -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 } from '../index.js'\nimport type { ThemePreset } from '../presets.js'\nimport { resolveThemeConfiguration } from '../utils/resolveThemeConfiguration.js'\n\ninterface ThemeColorOption {\n value: string\n label: string\n color: string\n description?: string\n}\n\nconst FALLBACK_TOKENS: ThemeColorOption[] = [\n { value: 'background', label: 'Theme background', color: 'var(--background)' },\n { value: 'card', label: 'Card background', color: 'var(--card)' },\n { value: 'muted', label: 'Muted surface', color: 'var(--muted)' },\n { value: 'accent', label: 'Accent surface', color: 'var(--accent)' },\n { value: 'secondary', label: 'Secondary surface', color: 'var(--secondary)' },\n { value: 'primary', label: 'Primary surface', color: 'var(--primary)' },\n]\n\nasync function fetchThemeConfiguration(): Promise<Record<string, unknown> | null> {\n try {\n const response = await fetch('/api/site-settings')\n if (!response.ok) {\n return null\n }\n const data = await response.json()\n return data?.docs?.[0]?.themeConfiguration ?? null\n } catch (error) {\n console.warn('[ThemeTokenSelectField] Failed to fetch theme configuration:', error)\n return null\n }\n}\n\nfunction buildOptionsFromConfiguration(\n configuration: 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, string> = {\n background: 'Theme background',\n card: 'Card background',\n muted: 'Muted surface',\n accent: 'Accent surface',\n secondary: 'Secondary surface',\n primary: 'Primary surface',\n popover: 'Popover surface',\n }\n\n return {\n value: key,\n label: labelMap[key] ?? key,\n color: value,\n }\n })\n .filter((token): token is ThemeColorOption => Boolean(token))\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 fetchThemeConfiguration().then((configuration) => {\n if (!isMounted) return\n setOptions(buildOptionsFromConfiguration(configuration, themePresets))\n })\n\n return () => {\n isMounted = false\n }\n }, [])\n\n const handleSelect = useCallback(\n (nextValue: string) => {\n setValue(nextValue)\n },\n [setValue],\n )\n\n const label = typeof field.label === 'string' ? field.label : ''\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 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 background: option.color,\n }}\n />\n <span\n style={{ fontSize: '13px', fontWeight: 600, color: 'var(--theme-elevation-800)' }}\n >\n {option.label}\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 {option.label}\n </option>\n ))}\n </select>\n </div>\n )\n}\n"],"names":["useField","useCallback","useEffect","useMemo","useState","allThemePresets","resolveThemeConfiguration","FALLBACK_TOKENS","value","label","color","fetchThemeConfiguration","response","fetch","ok","data","json","docs","themeConfiguration","error","console","warn","buildOptionsFromConfiguration","configuration","themePresets","resolved","lightMode","orderedKeys","typedLightMode","tokens","map","key","trim","length","labelMap","background","card","muted","accent","secondary","primary","popover","filter","token","Boolean","ThemeTokenSelectField","props","path","field","setValue","options","setOptions","selectedValue","customPresets","admin","custom","isMounted","then","handleSelect","nextValue","description","en","div","className","htmlFor","style","display","marginBottom","required","span","fontSize","gridTemplateColumns","gap","option","isActive","button","type","onClick","alignItems","padding","borderRadius","border","backgroundColor","boxShadow","cursor","transition","aria-hidden","width","height","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 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":"AAAA;;AAEA,SAASA,QAAQ,QAAQ,iBAAgB;AAEzC,SAASC,WAAW,EAAEC,SAAS,EAAEC,OAAO,EAAEC,QAAQ,QAAQ,QAAO;AACjE,SAASC,eAAe,EAAEC,uBAAuB,QAAQ,cAAa;AAItE,SAASC,yBAAyB,QAAQ,wCAAuC;AASjF,MAAMC,kBAAsC;IAC1C;QACEC,OAAO;QACPC,OAAO;YAAEC,IAAI;YAAoBC,IAAI;QAAgB;QACrDC,OAAO;IACT;IACA;QAAEJ,OAAO;QAAQC,OAAO;YAAEC,IAAI;YAAmBC,IAAI;QAAe;QAAGC,OAAO;IAAc;IAC5F;QAAEJ,OAAO;QAASC,OAAO;YAAEC,IAAI;YAAiBC,IAAI;QAAiB;QAAGC,OAAO;IAAe;IAC9F;QACEJ,OAAO;QACPC,OAAO;YAAEC,IAAI;YAAkBC,IAAI;QAAkB;QACrDC,OAAO;IACT;IACA;QACEJ,OAAO;QACPC,OAAO;YAAEC,IAAI;YAAqBC,IAAI;QAAoB;QAC1DC,OAAO;IACT;IACA;QACEJ,OAAO;QACPC,OAAO;YAAEC,IAAI;YAAmBC,IAAI;QAAkB;QACtDC,OAAO;IACT;CACD;AAED,gFAAgF;AAChF,kFAAkF;AAClF,uFAAuF;AAEvF,SAASC,8BACPC,aAAsE,EACtEC,YAA2B;IAE3B,IAAI,CAACD,eAAe;QAClB,OAAOP;IACT;IAEA,MAAMS,WAAWV,0BAA0BQ;IAC3C,MAAMG,YAAYD,SAASC,SAAS,IAAIF,YAAY,CAAC,EAAE,EAAEE,aAAa,CAAC;IACvE,MAAMC,cAAwB;QAC5B;QACA;QACA;QACA;QACA;QACA;QACA;KACD;IAED,MAAMC,iBAAiBF;IAEvB,MAAMG,SAASF,YACZG,GAAG,CAAC,CAACC;QACJ,MAAMd,QAAQW,gBAAgB,CAACG,IAAI;QACnC,IAAI,OAAOd,UAAU,YAAYA,MAAMe,IAAI,GAAGC,MAAM,KAAK,GAAG;YAC1D,OAAO;QACT;QAEA,MAAMC,WAAuD;YAC3DC,YAAY;gBAAEhB,IAAI;gBAAoBC,IAAI;YAAgB;YAC1DgB,MAAM;gBAAEjB,IAAI;gBAAmBC,IAAI;YAAe;YAClDiB,OAAO;gBAAElB,IAAI;gBAAiBC,IAAI;YAAiB;YACnDkB,QAAQ;gBAAEnB,IAAI;gBAAkBC,IAAI;YAAkB;YACtDmB,WAAW;gBAAEpB,IAAI;gBAAqBC,IAAI;YAAoB;YAC9DoB,SAAS;gBAAErB,IAAI;gBAAmBC,IAAI;YAAkB;YACxDqB,SAAS;gBAAEtB,IAAI;gBAAmBC,IAAI;YAAiB;QACzD;QAEA,OAAO;YACLH,OAAOc;YACPb,OAAOgB,QAAQ,CAACH,IAAI,IAAI;gBAAEZ,IAAIY;gBAAKX,IAAIW;YAAI;YAC3CV,OAAOJ;QACT;IACF,GACCyB,MAAM,CAAC,CAACC,QAA8CA,UAAU;IAEnE,OAAOd,OAAOI,MAAM,GAAG,IAAIJ,SAASb;AACtC;AAEA,eAAe,SAAS4B,sBAAsBC,KAA6B;IACzE,MAAM,EAAEC,IAAI,EAAEC,KAAK,EAAE,GAAGF;IACxB,MAAM,EAAE5B,KAAK,EAAE+B,QAAQ,EAAE,GAAGxC,SAAiB;QAAEsC;IAAK;IACpD,MAAM,CAACG,SAASC,WAAW,GAAGtC,SAA6BI;IAC3D,MAAMmC,gBAAgBlC,SAAS;IAE/B,qDAAqD;IACrD,MAAMO,eAAeb,QAAQ;QAC3B,MAAMyC,gBAAiBL,MAAMM,KAAK,EAAEC,QAA6C9B;QACjF,OAAO4B,iBAAiBA,cAAcnB,MAAM,GAAG,IAAImB,gBAAgBvC;IACrE,GAAG;QAACkC,MAAMM,KAAK,EAAEC;KAAO;IAExB5C,UAAU;QACR,IAAI6C,YAAY;QAEhB,0DAA0D;QAC1D,MAAMD,SAAS,AAACP,MAAMM,KAAK,EAAEC,UAAkB,CAAC;QAEhD,MAAME,YACJF,OAAOG,8BAA8B,IACrCH,OAAOI,YAAY,IAClBJ,CAAAA,OAAOK,cAAc,IAAI,OAAOL,OAAOM,SAAS,KAAK,cAClD;YACED,gBAAgBL,OAAOK,cAAc;YACrCC,WAAWN,OAAOM,SAAS;YAC3BC,YAAYP,OAAOO,UAAU;YAC7BC,OAAOR,OAAOQ,KAAK;YACnBC,QAAQT,OAAOS,MAAM;YACrBC,OAAOV,OAAOU,KAAK;YACnBC,aAAaX,OAAOW,WAAW;QACjC,IACAC,SAAQ;QAEdpD,wBAAwB0C,WAAWW,IAAI,CAAC,OAAO5C;YAC7C,IAAI,CAACgC,WAAW;YAChB,IAAIhC,eAAe;gBACjB2B,WAAW5B,8BAA8BC,eAAeC;gBACxD;YACF;YAEA,0FAA0F;YAC1F,qGAAqG;YACrG,MAAM4C,4BAA4B,CAAC,CACjC,CAAA,AAACZ,WAA0DI,cAAc,QACzE,AAACJ,WAA0DG,mBACzD,qBAAoB;YAGxB,IAAI,CAACS,2BAA2B;gBAC9B,IAAI;oBACF,sFAAsF;oBACtF,MAAMC,qBAAqB,AAACf,UAAUA,OAAOK,cAAc,IAAK;oBAChE,MAAMW,eAA+C;wBACnDV,WAAW;wBACXD,gBAAgBU;oBAClB;oBACA,MAAME,iBAAiB,MAAMzD,wBAAwBwD;oBACrD,IAAI,CAACf,WAAW;oBAChB,IAAIgB,gBAAgB;wBAClB,uCAAuC;wBACvCrB,WAAW5B,8BAA8BiD,gBAAgB/C;wBACzD;oBACF;gBACF,EAAE,OAAOgD,GAAG;oBACVC,QAAQC,IAAI,CAAC,yDAAyDF;gBACxE;YACF;YAEA,mCAAmC;YACnCtB,WAAW5B,8BAA8BC,eAAeC;QAC1D;QAEA,OAAO;YACL+B,YAAY;QACd;IACF,GAAG;QAAC/B;QAAcuB,MAAMM,KAAK,EAAEC;KAAO;IAEtC,MAAMqB,eAAelE,YACnB,CAACmE;QACC5B,SAAS4B;IACX,GACA;QAAC5B;KAAS;IAGZ,MAAM9B,QACJ,OAAO6B,MAAM7B,KAAK,KAAK,WAAW6B,MAAM7B,KAAK,GAAG6B,MAAM7B,KAAK,EAAEC,MAAM4B,MAAM7B,KAAK,EAAEE,MAAM;IACxF,IAAIyD,cAAc;IAClB,IAAI,OAAO9B,MAAMM,KAAK,EAAEwB,gBAAgB,UAAU;QAChDA,cAAc9B,MAAMM,KAAK,CAACwB,WAAW;IACvC,OAAO,IACL9B,MAAMM,KAAK,EAAEwB,eACb,OAAO9B,MAAMM,KAAK,CAACwB,WAAW,KAAK,YACnC,OAAO9B,MAAMM,KAAK,CAACwB,WAAW,CAAC1D,EAAE,KAAK,UACtC;QACA0D,cAAc9B,MAAMM,KAAK,CAACwB,WAAW,CAAC1D,EAAE;IAC1C;IAEA,mEAAmE;IACnE,MAAM2D,iBAAiB,CAACC;QACtB,IAAI,OAAOA,OAAO7D,KAAK,KAAK,UAAU;YACpC,OAAO6D,OAAO7D,KAAK;QACrB;QACA,iEAAiE;QACjE,OAAO6D,OAAO7D,KAAK,CAACC,EAAE,IAAI4D,OAAO7D,KAAK,CAACE,EAAE,IAAI4D,OAAOC,MAAM,CAACF,OAAO7D,KAAK,CAAC,CAAC,EAAE,IAAI6D,OAAO9D,KAAK;IAC7F;IAEA,8FAA8F;IAC9F,MAAMiE,kBAAkB,CAAC7D;QACvB,IAAI,OAAO8D,WAAW,eAAe,CAAC9D,SAAS,CAACA,MAAMW,IAAI,GAAGoD,UAAU,CAAC,SAAS;YAC/E,OAAO/D;QACT;QAEA,IAAI;YACF,MAAMgE,QAAQhE,MAAMW,IAAI,GAAGqD,KAAK,CAAC;YACjC,IAAI,CAACA,OAAO,OAAOhE;YACnB,MAAMiE,UAAUD,KAAK,CAAC,EAAE;YACxB,MAAME,WAAWC,iBAAiBC,SAASC,eAAe,EAAEC,gBAAgB,CAACL,SAAStD,IAAI;YAC1F,OAAOuD,YAAYlE;QACrB,EAAE,OAAOmD,GAAG;YACV,OAAOnD;QACT;IACF;IAEA,qBACE,MAACuE;QAAIC,WAAU;;YACZ3E,uBACC,MAACA;gBACC2E,WAAU;gBACVC,SAAShD;gBACTiD,OAAO;oBAAEC,SAAS;oBAASC,cAAc;gBAAM;;oBAE9C/E;oBACA6B,MAAMmD,QAAQ,kBAAI,KAACC;wBAAKN,WAAU;kCAAW;;;;YAIjDhB,6BACC,KAACe;gBACCC,WAAU;gBACVE,OAAO;oBAAEE,cAAc;oBAAQG,UAAU;oBAAQ/E,OAAO;gBAA6B;0BAEpFwD;;0BAIL,KAACe;gBACCC,WAAU;gBACVE,OAAO;oBACLC,SAAS;oBACTK,qBAAqB;oBACrBC,KAAK;gBACP;0BAECrD,QAAQnB,GAAG,CAAC,CAACiD;oBACZ,MAAMwB,WAAWxB,OAAO9D,KAAK,KAAKkC;oBAClC,qBACE,MAACqD;wBACCC,MAAK;wBAELC,SAAS,IAAM/B,aAAaI,OAAO9D,KAAK;wBACxC8E,OAAO;4BACLC,SAAS;4BACTW,YAAY;4BACZL,KAAK;4BACLM,SAAS;4BACTC,cAAc;4BACdC,QAAQP,WACJ,uCACA;4BACJQ,iBAAiB;4BACjBC,WAAWT,WACP,8CACA;4BACJU,QAAQ;4BACRC,YAAY;wBACd;;0CAEA,KAACf;gCACCgB,aAAW;gCACXpB,OAAO;oCACLqB,OAAO;oCACPC,QAAQ;oCACRR,cAAc;oCACdC,QAAQ;oCACRC,iBAAiB7B,gBAAgBH,OAAO1D,KAAK;oCAC7CiG,YAAY;gCACd;;0CAEF,KAACnB;gCACCJ,OAAO;oCAAEK,UAAU;oCAAQmB,YAAY;oCAAKlG,OAAO;gCAA6B;0CAE/EyD,eAAeC;;;uBAjCbA,OAAO9D,KAAK;gBAqCvB;;0BAGF,KAACuG;gBACCC,IAAI3E;gBACJ7B,OAAOkC;gBACPuE,UAAU,CAACC,QAAUhD,aAAagD,MAAMC,MAAM,CAAC3G,KAAK;gBACpD8E,OAAO;oBAAEC,SAAS;gBAAO;0BAExB/C,QAAQnB,GAAG,CAAC,CAACiD,uBACZ,KAACA;wBAA0B9D,OAAO8D,OAAO9D,KAAK;kCAC3C6D,eAAeC;uBADLA,OAAO9D,KAAK;;;;AAOnC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kilivi/payloadcms-theme-management",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.2",
|
|
4
4
|
"description": "Theme configuration plugin for Payload CMS v3 with 60+ professional themes and standalone collection support",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|