@kilivi/payloadcms-theme-management 0.2.8 → 0.2.10

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.
@@ -1,8 +1,8 @@
1
1
  'use client';
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
- import { useField, useFormFields } from '@payloadcms/ui';
3
+ import { Drawer, useField, useFormFields, useModal } from '@payloadcms/ui';
4
4
  import { HexColorInput, HexColorPicker } from 'react-colorful';
5
- import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
5
+ import { useCallback, useEffect, useMemo, useState } from 'react';
6
6
  // Import CSS only in browser environment
7
7
  // This prevents Node.js from trying to import CSS directly
8
8
  // which causes ERR_UNKNOWN_FILE_EXTENSION error
@@ -89,32 +89,19 @@ const ThemeColorPickerField = ({ field, path })=>{
89
89
  path
90
90
  });
91
91
  const [localValue, setLocalValue] = useState(value || '');
92
- const [showPicker, setShowPicker] = useState(false);
92
+ const { openModal, closeModal } = useModal();
93
93
  const [hexValue, setHexValue] = useState(toHex(value || ''));
94
- const pickerRef = useRef(null);
95
94
  const allFields = useFormFields(([fields])=>fields);
96
95
  const mode = path.includes('lightMode') ? 'lightMode' : 'darkMode';
97
96
  const modePrefix = `themeConfiguration.${mode}`;
97
+ // Generate unique drawer slug for this color picker instance
98
+ const drawerSlug = `color-picker-${path.replace(/\./g, '-')}`;
98
99
  useEffect(()=>{
99
100
  setLocalValue(value || '');
100
101
  setHexValue(toHex(value || ''));
101
102
  }, [
102
103
  value
103
104
  ]);
104
- // Close picker when clicking outside
105
- useEffect(()=>{
106
- function handleClickOutside(event) {
107
- if (pickerRef.current && !pickerRef.current.contains(event.target)) {
108
- setShowPicker(false);
109
- }
110
- }
111
- if (showPicker) {
112
- document.addEventListener('mousedown', handleClickOutside);
113
- return ()=>document.removeEventListener('mousedown', handleClickOutside);
114
- }
115
- }, [
116
- showPicker
117
- ]);
118
105
  const colorValues = useMemo(()=>{
119
106
  if (!allFields) {
120
107
  return {};
@@ -195,7 +182,7 @@ const ThemeColorPickerField = ({ field, path })=>{
195
182
  style: {
196
183
  backgroundColor: hexValue
197
184
  },
198
- onClick: ()=>setShowPicker(!showPicker),
185
+ onClick: ()=>openModal(drawerSlug),
199
186
  "aria-label": "Open color picker"
200
187
  }),
201
188
  /*#__PURE__*/ _jsx("input", {
@@ -207,33 +194,111 @@ const ThemeColorPickerField = ({ field, path })=>{
207
194
  })
208
195
  ]
209
196
  }),
210
- showPicker && /*#__PURE__*/ _jsxs("div", {
211
- className: "color-picker-popover",
212
- ref: pickerRef,
213
- children: [
214
- /*#__PURE__*/ _jsx(HexColorPicker, {
215
- color: hexValue,
216
- onChange: handleHexChange
217
- }),
218
- /*#__PURE__*/ _jsxs("div", {
219
- className: "picker-footer",
220
- children: [
221
- /*#__PURE__*/ _jsx(HexColorInput, {
222
- color: hexValue,
223
- onChange: handleHexChange,
224
- prefixed: true,
225
- placeholder: "#000000",
226
- className: "hex-input"
227
- }),
228
- /*#__PURE__*/ _jsx("button", {
229
- type: "button",
230
- onClick: ()=>setShowPicker(false),
231
- className: "close-button",
232
- children: "Done"
233
- })
234
- ]
235
- })
236
- ]
197
+ /*#__PURE__*/ _jsx(Drawer, {
198
+ slug: drawerSlug,
199
+ title: `Choose ${label}`,
200
+ children: /*#__PURE__*/ _jsxs("div", {
201
+ style: {
202
+ padding: '20px'
203
+ },
204
+ children: [
205
+ /*#__PURE__*/ _jsx(HexColorPicker, {
206
+ color: hexValue,
207
+ onChange: handleHexChange,
208
+ style: {
209
+ width: '100%',
210
+ height: '220px'
211
+ }
212
+ }),
213
+ /*#__PURE__*/ _jsxs("div", {
214
+ style: {
215
+ marginTop: '16px',
216
+ display: 'flex',
217
+ gap: '12px',
218
+ alignItems: 'center'
219
+ },
220
+ children: [
221
+ /*#__PURE__*/ _jsx(HexColorInput, {
222
+ color: hexValue,
223
+ onChange: handleHexChange,
224
+ prefixed: true,
225
+ placeholder: "#000000",
226
+ style: {
227
+ flex: 1,
228
+ padding: '10px',
229
+ borderRadius: '6px',
230
+ border: '1px solid var(--theme-elevation-150)',
231
+ fontSize: '14px',
232
+ fontFamily: 'monospace'
233
+ }
234
+ }),
235
+ /*#__PURE__*/ _jsx("button", {
236
+ type: "button",
237
+ onClick: ()=>closeModal(drawerSlug),
238
+ style: {
239
+ padding: '10px 20px',
240
+ borderRadius: '6px',
241
+ border: 'none',
242
+ backgroundColor: 'var(--theme-elevation-500)',
243
+ color: 'var(--theme-elevation-0)',
244
+ cursor: 'pointer',
245
+ fontWeight: 600
246
+ },
247
+ children: "Done"
248
+ })
249
+ ]
250
+ }),
251
+ /*#__PURE__*/ _jsxs("div", {
252
+ style: {
253
+ marginTop: '16px'
254
+ },
255
+ children: [
256
+ /*#__PURE__*/ _jsx("div", {
257
+ style: {
258
+ fontSize: '12px',
259
+ fontWeight: 600,
260
+ marginBottom: '8px',
261
+ color: 'var(--theme-elevation-500)'
262
+ },
263
+ children: "Quick Colors"
264
+ }),
265
+ /*#__PURE__*/ _jsx("div", {
266
+ style: {
267
+ display: 'grid',
268
+ gridTemplateColumns: 'repeat(8, 1fr)',
269
+ gap: '8px'
270
+ },
271
+ children: [
272
+ '#ef4444',
273
+ '#f97316',
274
+ '#f59e0b',
275
+ '#84cc16',
276
+ '#10b981',
277
+ '#06b6d4',
278
+ '#3b82f6',
279
+ '#8b5cf6',
280
+ '#ec4899',
281
+ '#64748b',
282
+ '#000000',
283
+ '#ffffff'
284
+ ].map((color)=>/*#__PURE__*/ _jsx("button", {
285
+ type: "button",
286
+ onClick: ()=>handleHexChange(color),
287
+ style: {
288
+ width: '100%',
289
+ height: '32px',
290
+ borderRadius: '4px',
291
+ border: hexValue.toLowerCase() === color.toLowerCase() ? '2px solid var(--theme-elevation-800)' : '1px solid var(--theme-elevation-150)',
292
+ backgroundColor: color,
293
+ cursor: 'pointer'
294
+ },
295
+ "aria-label": `Select ${color}`
296
+ }, color))
297
+ })
298
+ ]
299
+ })
300
+ ]
301
+ })
237
302
  }),
238
303
  /*#__PURE__*/ _jsx("div", {
239
304
  className: "color-preview",
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/fields/ThemeColorPickerField.tsx"],"sourcesContent":["'use client'\n\nimport { useField, useFormFields } from '@payloadcms/ui'\nimport type { TextFieldClientComponent } from 'payload'\nimport { HexColorInput, HexColorPicker } from 'react-colorful'\nimport { useCallback, useEffect, useMemo, useRef, useState } from 'react'\n\n// Import CSS only in browser environment\n// This prevents Node.js from trying to import CSS directly\n// which causes ERR_UNKNOWN_FILE_EXTENSION error\nif (typeof window !== 'undefined') {\n // @ts-expect-error - Dynamic import of CSS is not recognized by TypeScript\n import('./ThemeColorPickerField.css').catch((err) => {\n console.warn('Failed to load CSS file:', err)\n })\n}\n\nfunction resolveLocalizedValue(value: unknown, fallback: string) {\n if (typeof value === 'string') {\n return value\n }\n\n if (typeof value === 'object' && value !== null) {\n const localized = value as Record<string, unknown>\n const resolved = localized.en ?? localized.cs ?? localized['']\n if (typeof resolved === 'string') {\n return resolved\n }\n }\n\n return fallback\n}\n\n/**\n * Convert various color formats to HEX for the color picker\n */\nfunction toHex(color: string): string {\n if (!color) return '#000000'\n\n // Already hex\n if (color.startsWith('#')) return color\n\n // OKLCH format - extract hue and convert to approximate hex\n if (color.startsWith('oklch')) {\n // For now, return a default - proper conversion requires color-conversion library\n return '#3b82f6' // blue-500 as default\n }\n\n // HSL format\n if (color.startsWith('hsl')) {\n const regex = /hsl\\((\\d+),\\s*(\\d+)%,\\s*(\\d+)%\\)/\n const match = regex.exec(color)\n if (match) {\n const [, h, s, l] = match.map(Number)\n return hslToHex(h, s, l)\n }\n }\n\n return '#000000'\n}\n\n/**\n * Convert HSL to HEX\n */\nfunction hslToHex(h: number, s: number, l: number): string {\n s /= 100\n l /= 100\n\n const c = (1 - Math.abs(2 * l - 1)) * s\n const x = c * (1 - Math.abs(((h / 60) % 2) - 1))\n const m = l - c / 2\n\n let r = 0\n let g = 0\n let b = 0\n\n if (h >= 0 && h < 60) {\n r = c\n g = x\n } else if (h >= 60 && h < 120) {\n r = x\n g = c\n } else if (h >= 120 && h < 180) {\n g = c\n b = x\n } else if (h >= 180 && h < 240) {\n g = x\n b = c\n } else if (h >= 240 && h < 300) {\n r = x\n b = c\n } else if (h >= 300 && h < 360) {\n r = c\n b = x\n }\n\n const toHex = (n: number) => {\n const hex = Math.round((n + m) * 255).toString(16)\n return hex.length === 1 ? '0' + hex : hex\n }\n\n return `#${toHex(r)}${toHex(g)}${toHex(b)}`\n}\n\nconst ThemeColorPickerField: TextFieldClientComponent = ({ field, path }) => {\n const { value, setValue } = useField<string>({ path })\n const [localValue, setLocalValue] = useState(value || '')\n const [showPicker, setShowPicker] = useState(false)\n const [hexValue, setHexValue] = useState(toHex(value || ''))\n const pickerRef = useRef<HTMLDivElement>(null)\n const allFields = useFormFields(([fields]) => fields)\n\n const mode = path.includes('lightMode') ? 'lightMode' : 'darkMode'\n const modePrefix = `themeConfiguration.${mode}`\n\n useEffect(() => {\n setLocalValue(value || '')\n setHexValue(toHex(value || ''))\n }, [value])\n\n // Close picker when clicking outside\n useEffect(() => {\n function handleClickOutside(event: MouseEvent) {\n if (pickerRef.current && !pickerRef.current.contains(event.target as Node)) {\n setShowPicker(false)\n }\n }\n\n if (showPicker) {\n document.addEventListener('mousedown', handleClickOutside)\n return () => document.removeEventListener('mousedown', handleClickOutside)\n }\n }, [showPicker])\n\n const colorValues = useMemo(() => {\n if (!allFields) {\n return {}\n }\n\n const names = [\n 'background',\n 'foreground',\n 'card',\n 'cardForeground',\n 'popover',\n 'popoverForeground',\n 'primary',\n 'primaryForeground',\n 'secondary',\n 'secondaryForeground',\n 'muted',\n 'mutedForeground',\n 'accent',\n 'accentForeground',\n 'destructive',\n 'destructiveForeground',\n 'border',\n 'input',\n 'ring',\n ]\n\n return names.reduce<Record<string, string>>((accumulator, name) => {\n const fieldState = allFields[`${modePrefix}.${name}`]\n const parsedValue = typeof fieldState?.value === 'string' ? fieldState.value : undefined\n accumulator[name] = parsedValue ?? ''\n return accumulator\n }, {})\n }, [allFields, modePrefix])\n\n const handleHexChange = useCallback(\n (hex: string) => {\n setHexValue(hex)\n setLocalValue(hex)\n setValue(hex)\n },\n [setValue],\n )\n\n const handleTextChange = useCallback(\n (nextValue: string) => {\n setLocalValue(nextValue)\n setValue(nextValue)\n setHexValue(toHex(nextValue))\n },\n [setValue],\n )\n\n const fieldName = path.split('.').pop() || ''\n const label = resolveLocalizedValue(field.label, fieldName)\n const description = resolveLocalizedValue(field.admin?.description, '')\n\n return (\n <div className=\"theme-color-picker-field\">\n <div className=\"field-header\">\n <label className=\"field-label\">{label}</label>\n {description && <div className=\"field-description\">{description}</div>}\n </div>\n\n <div className=\"color-picker-container\">\n <div className=\"color-input-wrapper\">\n <button\n type=\"button\"\n className=\"color-swatch\"\n style={{ backgroundColor: hexValue }}\n onClick={() => setShowPicker(!showPicker)}\n aria-label=\"Open color picker\"\n />\n <input\n type=\"text\"\n value={localValue || ''}\n onChange={(event) => handleTextChange(event.target.value)}\n placeholder=\"oklch(...) or #hex\"\n className=\"text-input\"\n />\n </div>\n\n {/* Professional Color Picker Popover */}\n {showPicker && (\n <div className=\"color-picker-popover\" ref={pickerRef}>\n <HexColorPicker color={hexValue} onChange={handleHexChange} />\n <div className=\"picker-footer\">\n <HexColorInput\n color={hexValue}\n onChange={handleHexChange}\n prefixed\n placeholder=\"#000000\"\n className=\"hex-input\"\n />\n <button type=\"button\" onClick={() => setShowPicker(false)} className=\"close-button\">\n Done\n </button>\n </div>\n </div>\n )}\n\n <div className=\"color-preview\" style={{ backgroundColor: hexValue }}>\n <span className=\"preview-label\">{localValue || 'Not set'}</span>\n </div>\n </div>\n\n {(fieldName === 'primary' || fieldName === 'background') && (\n <div\n className=\"mini-preview\"\n style={{\n backgroundColor: colorValues.background || '#ffffff',\n color: colorValues.foreground || '#000000',\n borderColor: colorValues.border || '#e2e8f0',\n }}\n >\n <div\n className=\"preview-card\"\n style={{\n backgroundColor: colorValues.card || '#ffffff',\n color: colorValues.cardForeground || '#000000',\n borderColor: colorValues.border || '#e2e8f0',\n }}\n >\n <button\n className=\"preview-button\"\n style={{\n backgroundColor: colorValues.primary || '#0070f3',\n color: colorValues.primaryForeground || '#ffffff',\n }}\n >\n Primary Button\n </button>\n <button\n className=\"preview-button secondary\"\n style={{\n backgroundColor: colorValues.secondary || '#f1f5f9',\n color: colorValues.secondaryForeground || '#0f172a',\n }}\n >\n Secondary\n </button>\n </div>\n </div>\n )}\n </div>\n )\n}\n\nexport default ThemeColorPickerField\n"],"names":["useField","useFormFields","HexColorInput","HexColorPicker","useCallback","useEffect","useMemo","useRef","useState","window","catch","err","console","warn","resolveLocalizedValue","value","fallback","localized","resolved","en","cs","toHex","color","startsWith","regex","match","exec","h","s","l","map","Number","hslToHex","c","Math","abs","x","m","r","g","b","n","hex","round","toString","length","ThemeColorPickerField","field","path","setValue","localValue","setLocalValue","showPicker","setShowPicker","hexValue","setHexValue","pickerRef","allFields","fields","mode","includes","modePrefix","handleClickOutside","event","current","contains","target","document","addEventListener","removeEventListener","colorValues","names","reduce","accumulator","name","fieldState","parsedValue","undefined","handleHexChange","handleTextChange","nextValue","fieldName","split","pop","label","description","admin","div","className","button","type","style","backgroundColor","onClick","aria-label","input","onChange","placeholder","ref","prefixed","span","background","foreground","borderColor","border","card","cardForeground","primary","primaryForeground","secondary","secondaryForeground"],"mappings":"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"}
1
+ {"version":3,"sources":["../../src/fields/ThemeColorPickerField.tsx"],"sourcesContent":["'use client'\n\nimport { Drawer, useField, useFormFields, useModal } from '@payloadcms/ui'\nimport type { TextFieldClientComponent } from 'payload'\nimport { HexColorInput, HexColorPicker } from 'react-colorful'\nimport { useCallback, useEffect, useMemo, useState } from 'react'\n\n// Import CSS only in browser environment\n// This prevents Node.js from trying to import CSS directly\n// which causes ERR_UNKNOWN_FILE_EXTENSION error\nif (typeof window !== 'undefined') {\n // @ts-expect-error - Dynamic import of CSS is not recognized by TypeScript\n import('./ThemeColorPickerField.css').catch((err) => {\n console.warn('Failed to load CSS file:', err)\n })\n}\n\nfunction resolveLocalizedValue(value: unknown, fallback: string) {\n if (typeof value === 'string') {\n return value\n }\n\n if (typeof value === 'object' && value !== null) {\n const localized = value as Record<string, unknown>\n const resolved = localized.en ?? localized.cs ?? localized['']\n if (typeof resolved === 'string') {\n return resolved\n }\n }\n\n return fallback\n}\n\n/**\n * Convert various color formats to HEX for the color picker\n */\nfunction toHex(color: string): string {\n if (!color) return '#000000'\n\n // Already hex\n if (color.startsWith('#')) return color\n\n // OKLCH format - extract hue and convert to approximate hex\n if (color.startsWith('oklch')) {\n // For now, return a default - proper conversion requires color-conversion library\n return '#3b82f6' // blue-500 as default\n }\n\n // HSL format\n if (color.startsWith('hsl')) {\n const regex = /hsl\\((\\d+),\\s*(\\d+)%,\\s*(\\d+)%\\)/\n const match = regex.exec(color)\n if (match) {\n const [, h, s, l] = match.map(Number)\n return hslToHex(h, s, l)\n }\n }\n\n return '#000000'\n}\n\n/**\n * Convert HSL to HEX\n */\nfunction hslToHex(h: number, s: number, l: number): string {\n s /= 100\n l /= 100\n\n const c = (1 - Math.abs(2 * l - 1)) * s\n const x = c * (1 - Math.abs(((h / 60) % 2) - 1))\n const m = l - c / 2\n\n let r = 0\n let g = 0\n let b = 0\n\n if (h >= 0 && h < 60) {\n r = c\n g = x\n } else if (h >= 60 && h < 120) {\n r = x\n g = c\n } else if (h >= 120 && h < 180) {\n g = c\n b = x\n } else if (h >= 180 && h < 240) {\n g = x\n b = c\n } else if (h >= 240 && h < 300) {\n r = x\n b = c\n } else if (h >= 300 && h < 360) {\n r = c\n b = x\n }\n\n const toHex = (n: number) => {\n const hex = Math.round((n + m) * 255).toString(16)\n return hex.length === 1 ? '0' + hex : hex\n }\n\n return `#${toHex(r)}${toHex(g)}${toHex(b)}`\n}\n\nconst ThemeColorPickerField: TextFieldClientComponent = ({ field, path }) => {\n const { value, setValue } = useField<string>({ path })\n const [localValue, setLocalValue] = useState(value || '')\n const { openModal, closeModal } = useModal()\n const [hexValue, setHexValue] = useState(toHex(value || ''))\n const allFields = useFormFields(([fields]) => fields)\n\n const mode = path.includes('lightMode') ? 'lightMode' : 'darkMode'\n const modePrefix = `themeConfiguration.${mode}`\n\n // Generate unique drawer slug for this color picker instance\n const drawerSlug = `color-picker-${path.replace(/\\./g, '-')}`\n\n useEffect(() => {\n setLocalValue(value || '')\n setHexValue(toHex(value || ''))\n }, [value])\n\n const colorValues = useMemo(() => {\n if (!allFields) {\n return {}\n }\n\n const names = [\n 'background',\n 'foreground',\n 'card',\n 'cardForeground',\n 'popover',\n 'popoverForeground',\n 'primary',\n 'primaryForeground',\n 'secondary',\n 'secondaryForeground',\n 'muted',\n 'mutedForeground',\n 'accent',\n 'accentForeground',\n 'destructive',\n 'destructiveForeground',\n 'border',\n 'input',\n 'ring',\n ]\n\n return names.reduce<Record<string, string>>((accumulator, name) => {\n const fieldState = allFields[`${modePrefix}.${name}`]\n const parsedValue = typeof fieldState?.value === 'string' ? fieldState.value : undefined\n accumulator[name] = parsedValue ?? ''\n return accumulator\n }, {})\n }, [allFields, modePrefix])\n\n const handleHexChange = useCallback(\n (hex: string) => {\n setHexValue(hex)\n setLocalValue(hex)\n setValue(hex)\n },\n [setValue],\n )\n\n const handleTextChange = useCallback(\n (nextValue: string) => {\n setLocalValue(nextValue)\n setValue(nextValue)\n setHexValue(toHex(nextValue))\n },\n [setValue],\n )\n\n const fieldName = path.split('.').pop() || ''\n const label = resolveLocalizedValue(field.label, fieldName)\n const description = resolveLocalizedValue(field.admin?.description, '')\n\n return (\n <div className=\"theme-color-picker-field\">\n <div className=\"field-header\">\n <label className=\"field-label\">{label}</label>\n {description && <div className=\"field-description\">{description}</div>}\n </div>\n\n <div className=\"color-picker-container\">\n <div className=\"color-input-wrapper\">\n <button\n type=\"button\"\n className=\"color-swatch\"\n style={{ backgroundColor: hexValue }}\n onClick={() => openModal(drawerSlug)}\n aria-label=\"Open color picker\"\n />\n <input\n type=\"text\"\n value={localValue || ''}\n onChange={(event) => handleTextChange(event.target.value)}\n placeholder=\"oklch(...) or #hex\"\n className=\"text-input\"\n />\n </div>\n\n {/* Color Picker Modal Drawer */}\n <Drawer slug={drawerSlug} title={`Choose ${label}`}>\n <div style={{ padding: '20px' }}>\n <HexColorPicker\n color={hexValue}\n onChange={handleHexChange}\n style={{ width: '100%', height: '220px' }}\n />\n <div style={{ marginTop: '16px', display: 'flex', gap: '12px', alignItems: 'center' }}>\n <HexColorInput\n color={hexValue}\n onChange={handleHexChange}\n prefixed\n placeholder=\"#000000\"\n style={{\n flex: 1,\n padding: '10px',\n borderRadius: '6px',\n border: '1px solid var(--theme-elevation-150)',\n fontSize: '14px',\n fontFamily: 'monospace',\n }}\n />\n <button\n type=\"button\"\n onClick={() => closeModal(drawerSlug)}\n style={{\n padding: '10px 20px',\n borderRadius: '6px',\n border: 'none',\n backgroundColor: 'var(--theme-elevation-500)',\n color: 'var(--theme-elevation-0)',\n cursor: 'pointer',\n fontWeight: 600,\n }}\n >\n Done\n </button>\n </div>\n\n {/* Quick Color Swatches */}\n <div style={{ marginTop: '16px' }}>\n <div\n style={{\n fontSize: '12px',\n fontWeight: 600,\n marginBottom: '8px',\n color: 'var(--theme-elevation-500)',\n }}\n >\n Quick Colors\n </div>\n <div style={{ display: 'grid', gridTemplateColumns: 'repeat(8, 1fr)', gap: '8px' }}>\n {[\n '#ef4444',\n '#f97316',\n '#f59e0b',\n '#84cc16',\n '#10b981',\n '#06b6d4',\n '#3b82f6',\n '#8b5cf6',\n '#ec4899',\n '#64748b',\n '#000000',\n '#ffffff',\n ].map((color) => (\n <button\n key={color}\n type=\"button\"\n onClick={() => handleHexChange(color)}\n style={{\n width: '100%',\n height: '32px',\n borderRadius: '4px',\n border:\n hexValue.toLowerCase() === color.toLowerCase()\n ? '2px solid var(--theme-elevation-800)'\n : '1px solid var(--theme-elevation-150)',\n backgroundColor: color,\n cursor: 'pointer',\n }}\n aria-label={`Select ${color}`}\n />\n ))}\n </div>\n </div>\n </div>\n </Drawer>\n\n <div className=\"color-preview\" style={{ backgroundColor: hexValue }}>\n <span className=\"preview-label\">{localValue || 'Not set'}</span>\n </div>\n </div>\n\n {(fieldName === 'primary' || fieldName === 'background') && (\n <div\n className=\"mini-preview\"\n style={{\n backgroundColor: colorValues.background || '#ffffff',\n color: colorValues.foreground || '#000000',\n borderColor: colorValues.border || '#e2e8f0',\n }}\n >\n <div\n className=\"preview-card\"\n style={{\n backgroundColor: colorValues.card || '#ffffff',\n color: colorValues.cardForeground || '#000000',\n borderColor: colorValues.border || '#e2e8f0',\n }}\n >\n <button\n className=\"preview-button\"\n style={{\n backgroundColor: colorValues.primary || '#0070f3',\n color: colorValues.primaryForeground || '#ffffff',\n }}\n >\n Primary Button\n </button>\n <button\n className=\"preview-button secondary\"\n style={{\n backgroundColor: colorValues.secondary || '#f1f5f9',\n color: colorValues.secondaryForeground || '#0f172a',\n }}\n >\n Secondary\n </button>\n </div>\n </div>\n )}\n </div>\n )\n}\n\nexport default ThemeColorPickerField\n"],"names":["Drawer","useField","useFormFields","useModal","HexColorInput","HexColorPicker","useCallback","useEffect","useMemo","useState","window","catch","err","console","warn","resolveLocalizedValue","value","fallback","localized","resolved","en","cs","toHex","color","startsWith","regex","match","exec","h","s","l","map","Number","hslToHex","c","Math","abs","x","m","r","g","b","n","hex","round","toString","length","ThemeColorPickerField","field","path","setValue","localValue","setLocalValue","openModal","closeModal","hexValue","setHexValue","allFields","fields","mode","includes","modePrefix","drawerSlug","replace","colorValues","names","reduce","accumulator","name","fieldState","parsedValue","undefined","handleHexChange","handleTextChange","nextValue","fieldName","split","pop","label","description","admin","div","className","button","type","style","backgroundColor","onClick","aria-label","input","onChange","event","target","placeholder","slug","title","padding","width","height","marginTop","display","gap","alignItems","prefixed","flex","borderRadius","border","fontSize","fontFamily","cursor","fontWeight","marginBottom","gridTemplateColumns","toLowerCase","span","background","foreground","borderColor","card","cardForeground","primary","primaryForeground","secondary","secondaryForeground"],"mappings":"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"}
@@ -0,0 +1,153 @@
1
+ /**
2
+ * Enhanced Font Selector - Visual Examples
3
+ *
4
+ * This file demonstrates how the font selector appears with actual fonts
5
+ */
6
+ /**
7
+ * BEFORE (Standard Payload Select):
8
+ *
9
+ * ┌──────────────────────────────┐
10
+ * │ Body font ▼ │
11
+ * ├──────────────────────────────┤
12
+ * │ System │
13
+ * │ Inter │
14
+ * │ Roboto │
15
+ * │ Open Sans │
16
+ * │ ... │
17
+ * └──────────────────────────────┘
18
+ *
19
+ * Issues:
20
+ * - No visual preview of fonts
21
+ * - Can't see how font looks
22
+ * - Generic dropdown appearance
23
+ * - No distinction between fonts
24
+ */
25
+ /**
26
+ * AFTER (Custom Font Selector):
27
+ *
28
+ * ┌────────────────────────────────────┐
29
+ * │ Body font │
30
+ * │ ┌────────────────────────────┐ │
31
+ * │ │ Inter ▼ │ │
32
+ * │ └────────────────────────────┘ │
33
+ * └────────────────────────────────────┘
34
+ *
35
+ * Opens dropdown:
36
+ *
37
+ * ┌────────────────────────────────────┐
38
+ * │ ✓ Inter │
39
+ * │ The quick brown fox jumps... │
40
+ * │ (rendered in Inter font) │
41
+ * ├────────────────────────────────────┤
42
+ * │ Roboto │
43
+ * │ The quick brown fox jumps... │
44
+ * │ (rendered in Roboto font) │
45
+ * ├────────────────────────────────────┤
46
+ * │ Playfair Display │
47
+ * │ The quick brown fox jumps... │
48
+ * │ (rendered in Playfair font) │
49
+ * └────────────────────────────────────┘
50
+ *
51
+ * Features:
52
+ * ✅ Live font preview
53
+ * ✅ Check mark on selected
54
+ * ✅ Hover effects
55
+ * ✅ Smooth transitions
56
+ * ✅ Font category badges
57
+ */
58
+ /**
59
+ * Color Picker BEFORE (Inline Popover):
60
+ *
61
+ * ┌────────────────────────────────┐
62
+ * │ Primary color │
63
+ * │ ┌───┐ #3b82f6 │
64
+ * │ │███│ ──────────── │
65
+ * │ └───┘ │
66
+ * │ ┌──────────────────┐ │
67
+ * │ │ Color Picker │ │
68
+ * │ │ [Hex Wheel] │ │
69
+ * │ │ #3b82f6 │ │
70
+ * │ └──────────────────┘ │
71
+ * └────────────────────────────────┘
72
+ *
73
+ * Issues:
74
+ * - Takes up inline space
75
+ * - Hard to use on mobile
76
+ * - No quick color swatches
77
+ * - Click-outside handling complex
78
+ */
79
+ /**
80
+ * Color Picker AFTER (Modal Drawer):
81
+ *
82
+ * Field:
83
+ * ┌────────────────────────────────┐
84
+ * │ Primary color │
85
+ * │ ┌───┐ #3b82f6 │
86
+ * │ │███│ ──────────── │
87
+ * │ └───┘ │
88
+ * └────────────────────────────────┘
89
+ *
90
+ * Click swatch → Opens Modal:
91
+ *
92
+ * ╔════════════════════════════════╗
93
+ * ║ Choose Primary color [×] ║
94
+ * ╠════════════════════════════════╣
95
+ * ║ ║
96
+ * ║ ┌────────────────────┐ ║
97
+ * ║ │ │ ║
98
+ * ║ │ [Color Wheel] │ ║
99
+ * ║ │ │ ║
100
+ * ║ └────────────────────┘ ║
101
+ * ║ ║
102
+ * ║ #3b82f6 [Done] ║
103
+ * ║ ║
104
+ * ║ Quick Colors: ║
105
+ * ║ ┌──┬──┬──┬──┬──┬──┬──┬──┐ ║
106
+ * ║ │██│██│██│██│██│██│██│██│ ║
107
+ * ║ └──┴──┴──┴──┴──┴──┴──┴──┘ ║
108
+ * ║ ║
109
+ * ╚════════════════════════════════╝
110
+ *
111
+ * Features:
112
+ * ✅ Full-screen modal (Payload Drawer)
113
+ * ✅ Larger color picker (220px)
114
+ * ✅ Quick color swatches
115
+ * ✅ Better mobile UX
116
+ * ✅ Escape key to close
117
+ */
118
+ /**
119
+ * Theme Preset Selector (Already Had Swatches!):
120
+ *
121
+ * ┌─────────────────────────────────────┐
122
+ * │ Cool & Professional ●●●●● │
123
+ * │ cool │
124
+ * ├─────────────────────────────────────┤
125
+ * │ Warm & Inviting ●●●●● │
126
+ * │ warm │
127
+ * ├─────────────────────────────────────┤
128
+ * │ Dark & Modern ●●●●● │
129
+ * │ dark │
130
+ * └─────────────────────────────────────┘
131
+ *
132
+ * Legend:
133
+ * ● = Color swatch for:
134
+ * - Primary
135
+ * - Secondary
136
+ * - Accent
137
+ * - Background
138
+ * - Foreground
139
+ */
140
+ export declare const examples: {
141
+ fontSelector: {
142
+ before: string;
143
+ after: string;
144
+ };
145
+ colorPicker: {
146
+ before: string;
147
+ after: string;
148
+ };
149
+ themePresets: {
150
+ status: string;
151
+ };
152
+ };
153
+ //# sourceMappingURL=VISUAL_EXAMPLES.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"VISUAL_EXAMPLES.d.ts","sourceRoot":"","sources":["../../src/fields/VISUAL_EXAMPLES.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH;;;;;;;;;;;;;;;;;;GAkBG;AAEH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AAEH;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AAEH;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,eAAO,MAAM,QAAQ;;;;;;;;;;;;CAYpB,CAAA"}
@@ -0,0 +1,148 @@
1
+ /**
2
+ * Enhanced Font Selector - Visual Examples
3
+ *
4
+ * This file demonstrates how the font selector appears with actual fonts
5
+ */ /**
6
+ * BEFORE (Standard Payload Select):
7
+ *
8
+ * ┌──────────────────────────────┐
9
+ * │ Body font ▼ │
10
+ * ├──────────────────────────────┤
11
+ * │ System │
12
+ * │ Inter │
13
+ * │ Roboto │
14
+ * │ Open Sans │
15
+ * │ ... │
16
+ * └──────────────────────────────┘
17
+ *
18
+ * Issues:
19
+ * - No visual preview of fonts
20
+ * - Can't see how font looks
21
+ * - Generic dropdown appearance
22
+ * - No distinction between fonts
23
+ */ /**
24
+ * AFTER (Custom Font Selector):
25
+ *
26
+ * ┌────────────────────────────────────┐
27
+ * │ Body font │
28
+ * │ ┌────────────────────────────┐ │
29
+ * │ │ Inter ▼ │ │
30
+ * │ └────────────────────────────┘ │
31
+ * └────────────────────────────────────┘
32
+ *
33
+ * Opens dropdown:
34
+ *
35
+ * ┌────────────────────────────────────┐
36
+ * │ ✓ Inter │
37
+ * │ The quick brown fox jumps... │
38
+ * │ (rendered in Inter font) │
39
+ * ├────────────────────────────────────┤
40
+ * │ Roboto │
41
+ * │ The quick brown fox jumps... │
42
+ * │ (rendered in Roboto font) │
43
+ * ├────────────────────────────────────┤
44
+ * │ Playfair Display │
45
+ * │ The quick brown fox jumps... │
46
+ * │ (rendered in Playfair font) │
47
+ * └────────────────────────────────────┘
48
+ *
49
+ * Features:
50
+ * ✅ Live font preview
51
+ * ✅ Check mark on selected
52
+ * ✅ Hover effects
53
+ * ✅ Smooth transitions
54
+ * ✅ Font category badges
55
+ */ /**
56
+ * Color Picker BEFORE (Inline Popover):
57
+ *
58
+ * ┌────────────────────────────────┐
59
+ * │ Primary color │
60
+ * │ ┌───┐ #3b82f6 │
61
+ * │ │███│ ──────────── │
62
+ * │ └───┘ │
63
+ * │ ┌──────────────────┐ │
64
+ * │ │ Color Picker │ │
65
+ * │ │ [Hex Wheel] │ │
66
+ * │ │ #3b82f6 │ │
67
+ * │ └──────────────────┘ │
68
+ * └────────────────────────────────┘
69
+ *
70
+ * Issues:
71
+ * - Takes up inline space
72
+ * - Hard to use on mobile
73
+ * - No quick color swatches
74
+ * - Click-outside handling complex
75
+ */ /**
76
+ * Color Picker AFTER (Modal Drawer):
77
+ *
78
+ * Field:
79
+ * ┌────────────────────────────────┐
80
+ * │ Primary color │
81
+ * │ ┌───┐ #3b82f6 │
82
+ * │ │███│ ──────────── │
83
+ * │ └───┘ │
84
+ * └────────────────────────────────┘
85
+ *
86
+ * Click swatch → Opens Modal:
87
+ *
88
+ * ╔════════════════════════════════╗
89
+ * ║ Choose Primary color [×] ║
90
+ * ╠════════════════════════════════╣
91
+ * ║ ║
92
+ * ║ ┌────────────────────┐ ║
93
+ * ║ │ │ ║
94
+ * ║ │ [Color Wheel] │ ║
95
+ * ║ │ │ ║
96
+ * ║ └────────────────────┘ ║
97
+ * ║ ║
98
+ * ║ #3b82f6 [Done] ║
99
+ * ║ ║
100
+ * ║ Quick Colors: ║
101
+ * ║ ┌──┬──┬──┬──┬──┬──┬──┬──┐ ║
102
+ * ║ │██│██│██│██│██│██│██│██│ ║
103
+ * ║ └──┴──┴──┴──┴──┴──┴──┴──┘ ║
104
+ * ║ ║
105
+ * ╚════════════════════════════════╝
106
+ *
107
+ * Features:
108
+ * ✅ Full-screen modal (Payload Drawer)
109
+ * ✅ Larger color picker (220px)
110
+ * ✅ Quick color swatches
111
+ * ✅ Better mobile UX
112
+ * ✅ Escape key to close
113
+ */ /**
114
+ * Theme Preset Selector (Already Had Swatches!):
115
+ *
116
+ * ┌─────────────────────────────────────┐
117
+ * │ Cool & Professional ●●●●● │
118
+ * │ cool │
119
+ * ├─────────────────────────────────────┤
120
+ * │ Warm & Inviting ●●●●● │
121
+ * │ warm │
122
+ * ├─────────────────────────────────────┤
123
+ * │ Dark & Modern ●●●●● │
124
+ * │ dark │
125
+ * └─────────────────────────────────────┘
126
+ *
127
+ * Legend:
128
+ * ● = Color swatch for:
129
+ * - Primary
130
+ * - Secondary
131
+ * - Accent
132
+ * - Background
133
+ * - Foreground
134
+ */ export const examples = {
135
+ fontSelector: {
136
+ before: 'Standard dropdown with no preview',
137
+ after: 'Custom component with live font rendering'
138
+ },
139
+ colorPicker: {
140
+ before: 'Inline popover',
141
+ after: 'Modal drawer with quick swatches'
142
+ },
143
+ themePresets: {
144
+ status: 'Already implemented with color swatches!'
145
+ }
146
+ };
147
+
148
+ //# sourceMappingURL=VISUAL_EXAMPLES.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/fields/VISUAL_EXAMPLES.ts"],"sourcesContent":["/**\n * Enhanced Font Selector - Visual Examples\n *\n * This file demonstrates how the font selector appears with actual fonts\n */\n\n/**\n * BEFORE (Standard Payload Select):\n *\n * ┌──────────────────────────────┐\n * │ Body font ▼ │\n * ├──────────────────────────────┤\n * │ System │\n * │ Inter │\n * │ Roboto │\n * │ Open Sans │\n * │ ... │\n * └──────────────────────────────┘\n *\n * Issues:\n * - No visual preview of fonts\n * - Can't see how font looks\n * - Generic dropdown appearance\n * - No distinction between fonts\n */\n\n/**\n * AFTER (Custom Font Selector):\n *\n * ┌────────────────────────────────────┐\n * │ Body font │\n * │ ┌────────────────────────────┐ │\n * │ │ Inter ▼ │ │\n * │ └────────────────────────────┘ │\n * └────────────────────────────────────┘\n *\n * Opens dropdown:\n *\n * ┌────────────────────────────────────┐\n * │ ✓ Inter │\n * │ The quick brown fox jumps... │\n * │ (rendered in Inter font) │\n * ├────────────────────────────────────┤\n * │ Roboto │\n * │ The quick brown fox jumps... │\n * │ (rendered in Roboto font) │\n * ├────────────────────────────────────┤\n * │ Playfair Display │\n * │ The quick brown fox jumps... │\n * │ (rendered in Playfair font) │\n * └────────────────────────────────────┘\n *\n * Features:\n * ✅ Live font preview\n * ✅ Check mark on selected\n * ✅ Hover effects\n * ✅ Smooth transitions\n * ✅ Font category badges\n */\n\n/**\n * Color Picker BEFORE (Inline Popover):\n *\n * ┌────────────────────────────────┐\n * │ Primary color │\n * │ ┌───┐ #3b82f6 │\n * │ │███│ ──────────── │\n * │ └───┘ │\n * │ ┌──────────────────┐ │\n * │ │ Color Picker │ │\n * │ │ [Hex Wheel] │ │\n * │ │ #3b82f6 │ │\n * │ └──────────────────┘ │\n * └────────────────────────────────┘\n *\n * Issues:\n * - Takes up inline space\n * - Hard to use on mobile\n * - No quick color swatches\n * - Click-outside handling complex\n */\n\n/**\n * Color Picker AFTER (Modal Drawer):\n *\n * Field:\n * ┌────────────────────────────────┐\n * │ Primary color │\n * │ ┌───┐ #3b82f6 │\n * │ │███│ ──────────── │\n * │ └───┘ │\n * └────────────────────────────────┘\n *\n * Click swatch → Opens Modal:\n *\n * ╔════════════════════════════════╗\n * ║ Choose Primary color [×] ║\n * ╠════════════════════════════════╣\n * ║ ║\n * ║ ┌────────────────────┐ ║\n * ║ │ │ ║\n * ║ │ [Color Wheel] │ ║\n * ║ │ │ ║\n * ║ └────────────────────┘ ║\n * ║ ║\n * ║ #3b82f6 [Done] ║\n * ║ ║\n * ║ Quick Colors: ║\n * ║ ┌──┬──┬──┬──┬──┬──┬──┬──┐ ║\n * ║ │██│██│██│██│██│██│██│██│ ║\n * ║ └──┴──┴──┴──┴──┴──┴──┴──┘ ║\n * ║ ║\n * ╚════════════════════════════════╝\n *\n * Features:\n * ✅ Full-screen modal (Payload Drawer)\n * ✅ Larger color picker (220px)\n * ✅ Quick color swatches\n * ✅ Better mobile UX\n * ✅ Escape key to close\n */\n\n/**\n * Theme Preset Selector (Already Had Swatches!):\n *\n * ┌─────────────────────────────────────┐\n * │ Cool & Professional ●●●●● │\n * │ cool │\n * ├─────────────────────────────────────┤\n * │ Warm & Inviting ●●●●● │\n * │ warm │\n * ├─────────────────────────────────────┤\n * │ Dark & Modern ●●●●● │\n * │ dark │\n * └─────────────────────────────────────┘\n *\n * Legend:\n * ● = Color swatch for:\n * - Primary\n * - Secondary\n * - Accent\n * - Background\n * - Foreground\n */\n\nexport const examples = {\n fontSelector: {\n before: 'Standard dropdown with no preview',\n after: 'Custom component with live font rendering',\n },\n colorPicker: {\n before: 'Inline popover',\n after: 'Modal drawer with quick swatches',\n },\n themePresets: {\n status: 'Already implemented with color swatches!',\n },\n}\n"],"names":["examples","fontSelector","before","after","colorPicker","themePresets","status"],"mappings":"AAAA;;;;CAIC,GAED;;;;;;;;;;;;;;;;;;CAkBC,GAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAgCC,GAED;;;;;;;;;;;;;;;;;;;;CAoBC,GAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAsCC,GAED;;;;;;;;;;;;;;;;;;;;;CAqBC,GAED,OAAO,MAAMA,WAAW;IACtBC,cAAc;QACZC,QAAQ;QACRC,OAAO;IACT;IACAC,aAAa;QACXF,QAAQ;QACRC,OAAO;IACT;IACAE,cAAc;QACZC,QAAQ;IACV;AACF,EAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"themeConfigurationField.d.ts","sourceRoot":"","sources":["../../src/fields/themeConfigurationField.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,SAAS,CAAA;AAOpC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AAW9C,UAAU,8BAA8B;IACtC,YAAY,EAAE,WAAW,EAAE,CAAA;IAC3B,YAAY,EAAE,MAAM,CAAA;IACpB,sBAAsB,EAAE,OAAO,CAAA;IAC/B,gBAAgB,EAAE,OAAO,CAAA;IACzB,oBAAoB,EAAE,OAAO,CAAA;IAC7B,sBAAsB,CAAC,EAAE,OAAO,CAAA;CACjC;AAED;;;GAGG;AACH,wBAAgB,6BAA6B,CAC3C,OAAO,EAAE,8BAA8B,GACtC;IACD,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAA;KAAE,CAAA;IACjC,WAAW,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAA;KAAE,CAAA;IACvC,MAAM,EAAE,KAAK,EAAE,CAAA;CAChB,CA6aA"}
1
+ {"version":3,"file":"themeConfigurationField.d.ts","sourceRoot":"","sources":["../../src/fields/themeConfigurationField.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,SAAS,CAAA;AAOpC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AAW9C,UAAU,8BAA8B;IACtC,YAAY,EAAE,WAAW,EAAE,CAAA;IAC3B,YAAY,EAAE,MAAM,CAAA;IACpB,sBAAsB,EAAE,OAAO,CAAA;IAC/B,gBAAgB,EAAE,OAAO,CAAA;IACzB,oBAAoB,EAAE,OAAO,CAAA;IAC7B,sBAAsB,CAAC,EAAE,OAAO,CAAA;CACjC;AAED;;;GAGG;AACH,wBAAgB,6BAA6B,CAAC,OAAO,EAAE,8BAA8B,GAAG;IACtF,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAA;KAAE,CAAA;IACjC,WAAW,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAA;KAAE,CAAA;IACvC,MAAM,EAAE,KAAK,EAAE,CAAA;CAChB,CAmbA"}
@@ -1,6 +1,6 @@
1
1
  import { BASE_FONT_SIZE_OPTIONS, BODY_FONT_OPTIONS, HEADING_FONT_OPTIONS, LINE_HEIGHT_OPTIONS } from '../constants/themeFonts.js';
2
2
  import { darkModeField, lightModeField } from './colorModeFields.js';
3
- import { extendedThemeSelectionField, lightModeColorsField, darkModeColorsField, shadowConfigField, typographyConfigField, designSystemConfigField } from './extendedThemeFields.js';
3
+ import { darkModeColorsField, designSystemConfigField, extendedThemeSelectionField, lightModeColorsField, shadowConfigField, typographyConfigField } from './extendedThemeFields.js';
4
4
  /**
5
5
  * Theme Configuration Tab Configuration
6
6
  * Returns tab config that can be injected into existing tabs field
@@ -178,7 +178,10 @@ import { extendedThemeSelectionField, lightModeColorsField, darkModeColorsField,
178
178
  value: option.value
179
179
  })),
180
180
  admin: {
181
- width: '50%'
181
+ width: '50%',
182
+ components: {
183
+ Field: '@/fields/FontSelectField#default'
184
+ }
182
185
  }
183
186
  },
184
187
  {
@@ -194,7 +197,10 @@ import { extendedThemeSelectionField, lightModeColorsField, darkModeColorsField,
194
197
  value: option.value
195
198
  })),
196
199
  admin: {
197
- width: '50%'
200
+ width: '50%',
201
+ components: {
202
+ Field: '@/fields/FontSelectField#default'
203
+ }
198
204
  }
199
205
  }
200
206
  ]