@kilivi/payloadcms-theme-management 2.1.0 → 2.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (81) hide show
  1. package/README.md +37 -7
  2. package/dist/components/ServerThemeInjector.d.ts +13 -1
  3. package/dist/components/ServerThemeInjector.d.ts.map +1 -1
  4. package/dist/components/ServerThemeInjector.js +24 -1
  5. package/dist/components/ServerThemeInjector.js.map +1 -1
  6. package/dist/components/ThemeLivePreviewSync.d.ts +3 -0
  7. package/dist/components/ThemeLivePreviewSync.d.ts.map +1 -1
  8. package/dist/components/ThemeLivePreviewSync.js +28 -4
  9. package/dist/components/ThemeLivePreviewSync.js.map +1 -1
  10. package/dist/components/typographyPreviewUtils.d.ts +5 -0
  11. package/dist/components/typographyPreviewUtils.d.ts.map +1 -1
  12. package/dist/components/typographyPreviewUtils.js +16 -10
  13. package/dist/components/typographyPreviewUtils.js.map +1 -1
  14. package/dist/constants/themeFonts.d.ts +94 -168
  15. package/dist/constants/themeFonts.d.ts.map +1 -1
  16. package/dist/constants/themeFonts.js +260 -140
  17. package/dist/constants/themeFonts.js.map +1 -1
  18. package/dist/endpoints/themeFonts.d.ts +5 -0
  19. package/dist/endpoints/themeFonts.d.ts.map +1 -0
  20. package/dist/endpoints/themeFonts.js +138 -0
  21. package/dist/endpoints/themeFonts.js.map +1 -0
  22. package/dist/fields/AppearancePreviewField.d.ts.map +1 -1
  23. package/dist/fields/AppearancePreviewField.js +196 -133
  24. package/dist/fields/AppearancePreviewField.js.map +1 -1
  25. package/dist/fields/FontSelectField.css +155 -0
  26. package/dist/fields/FontSelectField.d.ts +4 -2
  27. package/dist/fields/FontSelectField.d.ts.map +1 -1
  28. package/dist/fields/FontSelectField.js +80 -118
  29. package/dist/fields/FontSelectField.js.map +1 -1
  30. package/dist/fields/StylePresetField.d.ts.map +1 -1
  31. package/dist/fields/StylePresetField.js +31 -30
  32. package/dist/fields/StylePresetField.js.map +1 -1
  33. package/dist/fields/ThemePreviewField.css +63 -1
  34. package/dist/fields/ThemePreviewField.d.ts.map +1 -1
  35. package/dist/fields/ThemePreviewField.js +2 -5
  36. package/dist/fields/ThemePreviewField.js.map +1 -1
  37. package/dist/fields/themeConfigurationField.d.ts.map +1 -1
  38. package/dist/fields/themeConfigurationField.js +320 -271
  39. package/dist/fields/themeConfigurationField.js.map +1 -1
  40. package/dist/hooks/useNativeLivePreview.d.ts +15 -0
  41. package/dist/hooks/useNativeLivePreview.d.ts.map +1 -0
  42. package/dist/hooks/useNativeLivePreview.js +18 -0
  43. package/dist/hooks/useNativeLivePreview.js.map +1 -0
  44. package/dist/hooks/useThemeFonts.d.ts +10 -0
  45. package/dist/hooks/useThemeFonts.d.ts.map +1 -0
  46. package/dist/hooks/useThemeFonts.js +36 -0
  47. package/dist/hooks/useThemeFonts.js.map +1 -0
  48. package/dist/index.d.ts +3 -0
  49. package/dist/index.d.ts.map +1 -1
  50. package/dist/index.js +9 -0
  51. package/dist/index.js.map +1 -1
  52. package/dist/next-fonts.d.ts +3 -0
  53. package/dist/next-fonts.d.ts.map +1 -0
  54. package/dist/next-fonts.js +360 -0
  55. package/dist/next-fonts.js.map +1 -0
  56. package/dist/payload-types.d.ts +10 -6
  57. package/dist/payload-types.d.ts.map +1 -1
  58. package/dist/payload-types.js.map +1 -1
  59. package/dist/presets.d.ts +6 -0
  60. package/dist/presets.d.ts.map +1 -1
  61. package/dist/presets.js.map +1 -1
  62. package/dist/style-presets.d.ts +27 -18
  63. package/dist/style-presets.d.ts.map +1 -1
  64. package/dist/style-presets.js +399 -217
  65. package/dist/style-presets.js.map +1 -1
  66. package/dist/translations.d.ts +5 -0
  67. package/dist/translations.d.ts.map +1 -1
  68. package/dist/translations.js +10 -0
  69. package/dist/translations.js.map +1 -1
  70. package/dist/utils/livePreviewThemeRuntime.d.ts +6 -1
  71. package/dist/utils/livePreviewThemeRuntime.d.ts.map +1 -1
  72. package/dist/utils/livePreviewThemeRuntime.js +11 -1
  73. package/dist/utils/livePreviewThemeRuntime.js.map +1 -1
  74. package/dist/utils/resolveThemeConfiguration.d.ts +15 -0
  75. package/dist/utils/resolveThemeConfiguration.d.ts.map +1 -1
  76. package/dist/utils/resolveThemeConfiguration.js +41 -8
  77. package/dist/utils/resolveThemeConfiguration.js.map +1 -1
  78. package/dist/utils/themeUtils.d.ts.map +1 -1
  79. package/dist/utils/themeUtils.js +60 -2
  80. package/dist/utils/themeUtils.js.map +1 -1
  81. package/package.json +5 -1
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/fields/AppearancePreviewField.tsx"],"sourcesContent":["'use client'\n\nimport { useFormFields } from '@payloadcms/ui'\nimport { Monitor, Moon, Smartphone, Sparkles, Sun, Tablet, type LucideIcon } from 'lucide-react'\nimport { useId, useMemo, useState } from 'react'\nimport {\n DEFAULT_DEVICE_PREVIEW_ID,\n DEVICE_PREVIEWS,\n getDevicePreview,\n type DevicePreviewId,\n} from '../constants/devicePreviews.js'\nimport { useThemeLanguage, useThemeTranslations } from '../hooks/useThemeTranslations.js'\nimport { resolveTypographyPreview } from '../components/typographyPreviewUtils.js'\nimport { borderRadiusPresets } from '../providers/Theme/themeConfig.js'\n\nconst DEVICE_ICONS: Record<DevicePreviewId, LucideIcon> = {\n mobile: Smartphone,\n tablet: Tablet,\n desktop: Monitor,\n}\n\n/**\n * Live, reactive preview of the Visual Effects + Component Styles + colour\n * choices. Mounted as a `ui` field inside the Appearance Settings tab so editors\n * see the combined result of every control update instantly — mirroring the CSS\n * that `generateThemeCSS` produces on the front-end.\n */\n\ntype Mode = 'light' | 'dark'\n\nconst SHADOW_MAP: Record<string, string> = {\n none: 'none',\n subtle: '0 1px 3px rgba(0,0,0,0.06), 0 1px 2px rgba(0,0,0,0.04)',\n medium: '0 4px 6px -1px rgba(0,0,0,0.1), 0 2px 4px -2px rgba(0,0,0,0.1)',\n strong: '0 10px 15px -3px rgba(0,0,0,0.1), 0 4px 6px -4px rgba(0,0,0,0.1)',\n dramatic: '0 25px 50px -12px rgba(0,0,0,0.25)',\n}\n\nconst BLUR_PX_MAP: Record<string, string> = {\n none: '0px',\n slight: '4px',\n medium: '8px',\n strong: '16px',\n heavy: '24px',\n}\n\nconst BUTTON_SIZE_MAP: Record<string, { padding: string; fontSize: string }> = {\n small: { padding: '6px 12px', fontSize: '12px' },\n medium: { padding: '8px 16px', fontSize: '13px' },\n large: { padding: '10px 24px', fontSize: '15px' },\n xl: { padding: '14px 32px', fontSize: '17px' },\n}\n\nfunction radiusToPx(token: string | undefined): string {\n const preset = borderRadiusPresets[(token ?? 'medium') as keyof typeof borderRadiusPresets]\n const css = preset?.css as Record<string, string> | undefined\n return css?.['--radius-large'] ?? css?.['--radius-default'] ?? '0.75rem'\n}\n\ninterface Palette {\n background: string\n foreground: string\n card: string\n cardForeground: 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 border: string\n gradientFrom: string\n gradientVia: string\n gradientTo: string\n}\n\ninterface Choices {\n effectStyle: string\n shadowIntensity: string\n backdropBlur: string\n borderStyle: string\n borderWidth: string\n glassOpacity: number\n buttonVariant: string\n buttonSize: string\n cardStyle: string\n cardHoverEffect: string\n imageStyle: string\n navbarStyle: string\n footerStyle: string\n linkStyle: string\n borderRadius: string\n}\n\nfunction cardSurface(c: Choices, p: Palette, radius: string): React.CSSProperties {\n const base: React.CSSProperties = {\n background: p.card,\n color: p.cardForeground,\n borderRadius: radius,\n border: `${c.borderWidth} ${c.borderStyle === 'none' ? 'solid' : c.borderStyle} ${p.border}`,\n padding: '16px',\n transition: 'transform 200ms ease, box-shadow 200ms ease',\n }\n\n // Card style takes precedence for the structural look, effect style for depth.\n if (c.cardStyle === 'bordered') {\n return {\n ...base,\n border: `2px solid ${p.foreground}`,\n borderRadius: 0,\n boxShadow: `4px 4px 0 ${p.foreground}`,\n }\n }\n if (c.cardStyle === 'gradient-border') {\n return {\n ...base,\n border: '2px solid transparent',\n borderImage: `linear-gradient(135deg, ${p.gradientFrom}, ${p.gradientVia}, ${p.gradientTo}) 1`,\n boxShadow: SHADOW_MAP[c.shadowIntensity] ?? SHADOW_MAP.medium,\n }\n }\n\n switch (c.effectStyle) {\n case 'glass':\n return {\n ...base,\n background: `color-mix(in srgb, ${p.card} ${c.glassOpacity}%, transparent)`,\n backdropFilter: `blur(${BLUR_PX_MAP[c.backdropBlur] ?? '8px'}) saturate(150%)`,\n border: `1px solid color-mix(in srgb, ${p.border} 50%, transparent)`,\n boxShadow: '0 4px 24px rgba(0,0,0,0.10), inset 0 1px 0 rgba(255,255,255,0.15)',\n }\n case 'neumorphic':\n return {\n ...base,\n background: p.background,\n border: 'none',\n boxShadow: '6px 6px 12px rgba(0,0,0,0.12), -6px -6px 12px rgba(255,255,255,0.7)',\n }\n case 'clay':\n return {\n ...base,\n border: 'none',\n boxShadow: '4px 4px 0 rgba(0,0,0,0.22), 0 8px 20px rgba(0,0,0,0.08)',\n }\n case 'elevated':\n return { ...base, border: 'none', boxShadow: SHADOW_MAP[c.shadowIntensity] ?? SHADOW_MAP.medium }\n case 'flat':\n default:\n return { ...base, boxShadow: 'none' }\n }\n}\n\nfunction buttonStyle(c: Choices, p: Palette, radius: string): React.CSSProperties {\n const size = BUTTON_SIZE_MAP[c.buttonSize] ?? BUTTON_SIZE_MAP.medium!\n const base: React.CSSProperties = {\n ...size,\n fontWeight: 600,\n cursor: 'pointer',\n borderRadius: radius,\n border: 'none',\n transition: 'transform 120ms ease, box-shadow 120ms ease',\n whiteSpace: 'nowrap',\n }\n switch (c.buttonVariant) {\n case 'outlined':\n return { ...base, background: 'transparent', color: p.primary, border: `1.5px solid ${p.primary}` }\n case 'ghost':\n return { ...base, background: 'transparent', color: p.primary }\n case 'gradient':\n return {\n ...base,\n backgroundImage: `linear-gradient(135deg, ${p.gradientFrom}, ${p.gradientVia}, ${p.gradientTo})`,\n color: p.primaryForeground,\n }\n case 'pill':\n return { ...base, background: p.primary, color: p.primaryForeground, borderRadius: '9999px' }\n case 'brutal':\n return {\n ...base,\n background: p.card,\n color: p.foreground,\n border: `2px solid ${p.foreground}`,\n borderRadius: 0,\n boxShadow: `3px 3px 0 ${p.foreground}`,\n }\n case 'filled':\n default:\n return { ...base, background: p.primary, color: p.primaryForeground }\n }\n}\n\nfunction navbarStyle(c: Choices, p: Palette): React.CSSProperties {\n const base: React.CSSProperties = {\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'space-between',\n padding: '10px 14px',\n background: p.background,\n color: p.foreground,\n borderBottom: `1px solid ${p.border}`,\n }\n switch (c.navbarStyle) {\n case 'transparent':\n return { ...base, background: 'transparent', borderBottom: '1px solid transparent' }\n case 'blur':\n return {\n ...base,\n background: `color-mix(in srgb, ${p.background} 70%, transparent)`,\n backdropFilter: 'blur(12px)',\n }\n case 'floating':\n return {\n ...base,\n margin: '8px',\n borderRadius: radiusToPx(c.borderRadius),\n border: `1px solid ${p.border}`,\n boxShadow: '0 4px 24px rgba(0,0,0,0.10)',\n }\n case 'minimal':\n return { ...base, borderBottom: `1px solid ${p.border}`, boxShadow: 'none' }\n case 'solid':\n default:\n return base\n }\n}\n\nfunction linkStyle(c: Choices, p: Palette): React.CSSProperties {\n switch (c.linkStyle) {\n case 'underline':\n return { color: p.primary, textDecoration: 'underline', textUnderlineOffset: '0.15em' }\n case 'none':\n return { color: p.primary, textDecoration: 'none' }\n case 'highlight':\n return {\n color: p.foreground,\n textDecoration: 'none',\n backgroundImage: `linear-gradient(transparent 60%, color-mix(in srgb, ${p.primary} 28%, transparent) 0)`,\n }\n case 'animated':\n return {\n color: p.primary,\n textDecoration: 'none',\n borderBottom: `2px solid ${p.primary}`,\n paddingBottom: '1px',\n }\n case 'underline-hover':\n default:\n return { color: p.primary, textDecoration: 'none' }\n }\n}\n\nexport default function AppearancePreviewField() {\n const formFields = useFormFields(([state]) => state) as Record<\n string,\n { value?: unknown } | undefined\n >\n const lang = useThemeLanguage() as 'en' | 'cs'\n const translations = useThemeTranslations()\n const t = translations.appearancePreview\n const site = translations.preview\n const [mode, setMode] = useState<Mode>('light')\n const [device, setDevice] = useState<DevicePreviewId>(DEFAULT_DEVICE_PREVIEW_ID)\n const uid = useId().replace(/[:]/g, '')\n\n const activeDevice = getDevicePreview(device)\n\n // Fonts follow the Typography section (or the theme preset when set to \"Use theme preset\"),\n // so this single preview shows colours, type and component styles together.\n const typographyValue = (key: string) =>\n formFields?.[`themeConfiguration.typography.${key}`]?.value as string | undefined\n const typography = resolveTypographyPreview(\n {\n bodyFont: typographyValue('bodyFont'),\n headingFont: typographyValue('headingFont'),\n bodyFontCustom: typographyValue('bodyFontCustom'),\n headingFontCustom: typographyValue('headingFontCustom'),\n baseFontSize: typographyValue('baseFontSize'),\n lineHeight: typographyValue('lineHeight'),\n },\n formFields?.['themeConfiguration.theme']?.value as string | undefined,\n )\n\n const str = (key: string, fallback: string): string => {\n const v = formFields?.[`themeConfiguration.${key}`]?.value\n return typeof v === 'string' && v.trim().length > 0 ? v : fallback\n }\n const num = (key: string, fallback: number): number => {\n const v = formFields?.[`themeConfiguration.${key}`]?.value\n return typeof v === 'number' ? v : fallback\n }\n\n const choices: Choices = {\n effectStyle: str('visualEffects.effectStyle', 'flat'),\n shadowIntensity: str('visualEffects.shadowIntensity', 'medium'),\n backdropBlur: str('visualEffects.backdropBlur', 'none'),\n borderStyle: str('visualEffects.borderStyle', 'solid'),\n borderWidth: str('visualEffects.borderWidth', '1px'),\n glassOpacity: num('visualEffects.glassOpacity', 60),\n buttonVariant: str('componentStyles.buttonVariant', 'filled'),\n buttonSize: str('componentStyles.buttonSize', 'medium'),\n cardStyle: str('componentStyles.cardStyle', 'elevated'),\n cardHoverEffect: str('componentStyles.cardHoverEffect', 'lift'),\n imageStyle: str('componentStyles.imageStyle', 'default'),\n navbarStyle: str('componentStyles.navbarStyle', 'solid'),\n footerStyle: str('componentStyles.footerStyle', 'standard'),\n linkStyle: str('componentStyles.linkStyle', 'underline-hover'),\n borderRadius: str('borderRadius', 'medium'),\n }\n\n const modeKey = mode === 'light' ? 'lightMode' : 'darkMode'\n const fallback: Palette =\n mode === 'light'\n ? {\n background: '#ffffff',\n foreground: '#0a0a0a',\n card: '#ffffff',\n cardForeground: '#0a0a0a',\n primary: '#9372f7',\n primaryForeground: '#fafafa',\n secondary: '#f4f4f5',\n secondaryForeground: '#18181b',\n muted: '#f4f4f5',\n mutedForeground: '#71717a',\n accent: '#f4f4f5',\n accentForeground: '#18181b',\n border: '#e4e4e7',\n gradientFrom: '#9372f7',\n gradientVia: '#7c6ff0',\n gradientTo: '#22d3ee',\n }\n : {\n background: '#0a0a0a',\n foreground: '#fafafa',\n card: '#09090b',\n cardForeground: '#fafafa',\n primary: '#9372f7',\n primaryForeground: '#09090b',\n secondary: '#27272a',\n secondaryForeground: '#fafafa',\n muted: '#27272a',\n mutedForeground: '#a1a1aa',\n accent: '#27272a',\n accentForeground: '#fafafa',\n border: '#27272a',\n gradientFrom: '#9372f7',\n gradientVia: '#7c6ff0',\n gradientTo: '#22d3ee',\n }\n\n const palette: Palette = useMemo(() => {\n const p = { ...fallback }\n ;(Object.keys(fallback) as (keyof Palette)[]).forEach((key) => {\n p[key] = str(`${modeKey}.${key}`, fallback[key])\n })\n return p\n }, [formFields, mode])\n\n const radius = radiusToPx(choices.borderRadius)\n const card = cardSurface(choices, palette, radius)\n const btn = buttonStyle(choices, palette, radius)\n const nav = navbarStyle(choices, palette)\n\n // Hover effects can't be expressed inline, so emit a scoped style block.\n const hoverCSS = (() => {\n const sel = `.${uid} .tm-prev-card`\n switch (choices.cardHoverEffect) {\n case 'lift':\n return `${sel}:hover{transform:translateY(-6px);box-shadow:0 20px 40px rgba(0,0,0,0.14)}`\n case 'scale':\n return `${sel}:hover{transform:scale(1.02)}`\n case 'glow':\n return `${sel}:hover{box-shadow:0 0 0 3px color-mix(in srgb, ${palette.primary} 25%, transparent),0 8px 32px rgba(0,0,0,0.12)}`\n case 'shadow':\n return `${sel}:hover{box-shadow:0 24px 50px -12px rgba(0,0,0,0.35)}`\n case 'tilt':\n return `${sel}:hover{transform:perspective(800px) rotateX(3deg) rotateY(-3deg)}`\n default:\n return ''\n }\n })()\n const btnHoverCSS = `.${uid} .tm-prev-btn:hover{filter:brightness(1.05)}${\n choices.buttonVariant === 'brutal'\n ? `.${uid} .tm-prev-btn:hover{transform:translate(-2px,-2px);box-shadow:5px 5px 0 ${palette.foreground}}`\n : ''\n }`\n // Movement-based hover effects only run for users who haven't asked for reduced motion.\n const previewCSS = `@media (prefers-reduced-motion: no-preference){${hoverCSS}${btnHoverCSS}}`\n\n const chipLabels = t.chips\n const chips: Array<[string, string]> = [\n [chipLabels.effect, choices.effectStyle],\n [chipLabels.shadow, choices.shadowIntensity],\n [chipLabels.card, choices.cardStyle],\n [chipLabels.hover, choices.cardHoverEffect],\n [chipLabels.button, `${choices.buttonVariant} / ${choices.buttonSize}`],\n [chipLabels.navbar, choices.navbarStyle],\n [chipLabels.footer, choices.footerStyle],\n [chipLabels.link, choices.linkStyle],\n [chipLabels.radius, choices.borderRadius],\n ]\n\n const footerStyleCss: React.CSSProperties =\n choices.footerStyle === 'dark'\n ? { background: palette.foreground, color: palette.background }\n : choices.footerStyle === 'full-color'\n ? { background: palette.primary, color: palette.primaryForeground }\n : choices.footerStyle === 'gradient-top'\n ? {\n background: palette.background,\n color: palette.mutedForeground,\n borderTop: '3px solid transparent',\n borderImage: `linear-gradient(135deg, ${palette.gradientFrom}, ${palette.gradientVia}, ${palette.gradientTo}) 1`,\n }\n : choices.footerStyle === 'minimal'\n ? { background: 'transparent', color: palette.mutedForeground, borderTop: `1px solid ${palette.border}` }\n : { background: palette.muted, color: palette.mutedForeground, borderTop: `1px solid ${palette.border}` }\n\n return (\n // The slot spans the whole right column of the Appearance tab on wide admins;\n // its inner panel is sticky so the preview stays in view while editing.\n <div className={`tm-live-preview-slot ${uid}`}>\n <div className=\"tm-live-preview\">\n <style dangerouslySetInnerHTML={{ __html: previewCSS }} />\n\n <div\n style={{\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'space-between',\n marginBottom: '8px',\n gap: '8px',\n flexWrap: 'wrap',\n }}\n >\n <div>\n <div\n style={{\n display: 'inline-flex',\n alignItems: 'center',\n gap: '6px',\n fontSize: '13px',\n fontWeight: 600,\n color: 'var(--theme-elevation-800)',\n }}\n >\n <Sparkles size={14} aria-hidden />\n {t.title}\n </div>\n <div style={{ fontSize: '12px', color: 'var(--theme-elevation-600)' }}>{t.subtitle}</div>\n </div>\n <div style={{ display: 'inline-flex', gap: '8px', flexWrap: 'wrap' }}>\n {/* Device / viewport switcher */}\n <div\n role=\"group\"\n aria-label={t.viewport}\n style={{ display: 'inline-flex', borderRadius: '8px', overflow: 'hidden', border: '1px solid var(--theme-elevation-200)' }}\n >\n {DEVICE_PREVIEWS.map((d) => {\n const Icon = DEVICE_ICONS[d.id]\n return (\n <button\n key={d.id}\n type=\"button\"\n aria-pressed={device === d.id}\n onClick={() => setDevice(d.id)}\n title={`${lang === 'cs' ? d.labelCs : d.label} — ${d.width}×${d.height}`}\n style={{\n display: 'inline-flex',\n alignItems: 'center',\n gap: '5px',\n minHeight: '28px',\n padding: '5px 10px',\n fontSize: '12px',\n fontWeight: 600,\n cursor: 'pointer',\n border: 'none',\n background: device === d.id ? 'var(--theme-elevation-800)' : 'transparent',\n color: device === d.id ? 'var(--theme-elevation-0)' : 'var(--theme-elevation-600)',\n }}\n >\n <Icon size={13} aria-hidden />\n {lang === 'cs' ? d.labelCs : d.label}\n </button>\n )\n })}\n </div>\n {/* Light / dark switcher */}\n <div\n role=\"group\"\n aria-label={`${t.light} / ${t.dark}`}\n style={{ display: 'inline-flex', borderRadius: '8px', overflow: 'hidden', border: '1px solid var(--theme-elevation-200)' }}\n >\n {(['light', 'dark'] as Mode[]).map((m) => {\n const Icon = m === 'light' ? Sun : Moon\n return (\n <button\n key={m}\n type=\"button\"\n aria-pressed={mode === m}\n onClick={() => setMode(m)}\n style={{\n display: 'inline-flex',\n alignItems: 'center',\n gap: '5px',\n minHeight: '28px',\n padding: '5px 12px',\n fontSize: '12px',\n fontWeight: 600,\n cursor: 'pointer',\n border: 'none',\n background: mode === m ? 'var(--theme-elevation-800)' : 'transparent',\n color: mode === m ? 'var(--theme-elevation-0)' : 'var(--theme-elevation-600)',\n }}\n >\n <Icon size={13} aria-hidden />\n {m === 'light' ? t.light : t.dark}\n </button>\n )\n })}\n </div>\n </div>\n </div>\n\n {/* Viewport wrapper — constrains the frame to the active device width */}\n <div\n style={{\n display: 'flex',\n justifyContent: 'center',\n background: 'var(--theme-elevation-50)',\n borderRadius: '14px',\n padding: device === 'desktop' ? '0' : '16px',\n }}\n >\n {/* Browser-like frame. It is a picture of the site, so it is inert: its\n sample buttons and links must not become dead tab stops. */}\n <div\n ref={(el) => el?.setAttribute('inert', '')}\n style={{\n width: '100%',\n maxWidth: device === 'desktop' ? '100%' : `${activeDevice.width}px`,\n borderRadius: '14px',\n overflow: 'hidden',\n border: '1px solid var(--theme-elevation-200)',\n boxShadow: '0 8px 24px rgba(0,0,0,0.10)',\n background: palette.background,\n color: palette.foreground,\n fontFamily: typography.bodyFont,\n lineHeight: typography.lineHeight,\n }}\n >\n <nav style={nav}>\n <span style={{ fontWeight: 700, fontSize: '13px' }}>{site.siteTitle}</span>\n <span style={{ display: 'flex', gap: '14px', fontSize: '12px', opacity: 0.85 }}>\n <span>{site.nav.home}</span>\n <span>{site.nav.about}</span>\n <span style={{ ...linkStyle(choices, palette) }}>{site.nav.services}</span>\n </span>\n </nav>\n\n <div style={{ padding: '20px', display: 'grid', gap: '14px' }}>\n <div>\n <div\n style={{ fontFamily: typography.headingFont, fontSize: '22px', fontWeight: 700, lineHeight: 1.2 }}\n >\n {t.heading}\n </div>\n <p\n style={{\n margin: '6px 0 0',\n fontSize: `calc(${typography.baseFontSize} * 0.8125)`,\n lineHeight: typography.lineHeight,\n color: palette.mutedForeground,\n }}\n >\n {t.body}\n <a style={linkStyle(choices, palette)}>{t.link}</a>.\n </p>\n </div>\n\n <div className=\"tm-prev-card\" style={card}>\n <div style={{ display: 'flex', gap: '10px', alignItems: 'center', flexWrap: 'wrap' }}>\n <button type=\"button\" className=\"tm-prev-btn\" style={btn}>\n {t.primary}\n </button>\n <button\n type=\"button\"\n style={{\n ...BUTTON_SIZE_MAP[choices.buttonSize] ?? BUTTON_SIZE_MAP.medium,\n fontWeight: 600,\n cursor: 'pointer',\n borderRadius: radius,\n background: palette.secondary,\n color: palette.secondaryForeground,\n border: 'none',\n }}\n >\n {t.secondary}\n </button>\n <span\n aria-hidden\n style={{\n marginLeft: 'auto',\n width: '54px',\n height: '22px',\n borderRadius: '6px',\n backgroundImage: `linear-gradient(135deg, ${palette.gradientFrom}, ${palette.gradientVia}, ${palette.gradientTo})`,\n boxShadow: 'inset 0 0 0 1px rgba(0,0,0,0.08)',\n }}\n />\n </div>\n </div>\n </div>\n\n <div style={{ padding: '12px 16px', fontSize: '11px', ...footerStyleCss }}>\n © {new Date().getFullYear()} {site.siteTitle} — {t.footer}\n </div>\n </div>\n </div>\n\n {/* Active spec chips */}\n <div style={{ display: 'flex', flexWrap: 'wrap', gap: '5px', marginTop: '10px' }}>\n {chips.map(([k, v]) => (\n <span\n key={k}\n style={{\n fontSize: '11px',\n padding: '2px 7px',\n borderRadius: '999px',\n background: 'var(--theme-elevation-50)',\n border: '1px solid var(--theme-elevation-150)',\n color: 'var(--theme-elevation-700)',\n }}\n >\n <span style={{ color: 'var(--theme-elevation-600)' }}>{k}:</span> <strong style={{ fontWeight: 600 }}>{v}</strong>\n </span>\n ))}\n </div>\n </div>\n </div>\n )\n}\n"],"names":["useFormFields","Monitor","Moon","Smartphone","Sparkles","Sun","Tablet","useId","useMemo","useState","DEFAULT_DEVICE_PREVIEW_ID","DEVICE_PREVIEWS","getDevicePreview","useThemeLanguage","useThemeTranslations","resolveTypographyPreview","borderRadiusPresets","DEVICE_ICONS","mobile","tablet","desktop","SHADOW_MAP","none","subtle","medium","strong","dramatic","BLUR_PX_MAP","slight","heavy","BUTTON_SIZE_MAP","small","padding","fontSize","large","xl","radiusToPx","token","preset","css","cardSurface","c","p","radius","base","background","card","color","cardForeground","borderRadius","border","borderWidth","borderStyle","transition","cardStyle","foreground","boxShadow","borderImage","gradientFrom","gradientVia","gradientTo","shadowIntensity","effectStyle","glassOpacity","backdropFilter","backdropBlur","buttonStyle","size","buttonSize","fontWeight","cursor","whiteSpace","buttonVariant","primary","backgroundImage","primaryForeground","navbarStyle","display","alignItems","justifyContent","borderBottom","margin","linkStyle","textDecoration","textUnderlineOffset","paddingBottom","AppearancePreviewField","formFields","state","lang","translations","t","appearancePreview","site","preview","mode","setMode","device","setDevice","uid","replace","activeDevice","typographyValue","key","value","typography","bodyFont","headingFont","bodyFontCustom","headingFontCustom","baseFontSize","lineHeight","str","fallback","v","trim","length","num","choices","cardHoverEffect","imageStyle","footerStyle","modeKey","secondary","secondaryForeground","muted","mutedForeground","accent","accentForeground","palette","Object","keys","forEach","btn","nav","hoverCSS","sel","btnHoverCSS","previewCSS","chipLabels","chips","effect","shadow","hover","button","navbar","footer","link","footerStyleCss","borderTop","div","className","style","dangerouslySetInnerHTML","__html","marginBottom","gap","flexWrap","aria-hidden","title","subtitle","role","aria-label","viewport","overflow","map","d","Icon","id","type","aria-pressed","onClick","labelCs","label","width","height","minHeight","light","dark","m","ref","el","setAttribute","maxWidth","fontFamily","span","siteTitle","opacity","home","about","services","heading","body","a","marginLeft","Date","getFullYear","marginTop","k"],"mappings":"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"}
1
+ {"version":3,"sources":["../../src/fields/AppearancePreviewField.tsx"],"sourcesContent":["'use client'\n\nimport { useFormFields } from '@payloadcms/ui'\nimport {\n ExternalLink,\n Monitor,\n Moon,\n Smartphone,\n Sparkles,\n Sun,\n Tablet,\n type LucideIcon,\n} from 'lucide-react'\nimport { useId, useMemo, useState } from 'react'\nimport {\n DEFAULT_DEVICE_PREVIEW_ID,\n DEVICE_PREVIEWS,\n getDevicePreview,\n type DevicePreviewId,\n} from '../constants/devicePreviews.js'\nimport { useThemeLanguage, useThemeTranslations } from '../hooks/useThemeTranslations.js'\nimport { resolveTypographyPreview } from '../components/typographyPreviewUtils.js'\nimport { useNativeLivePreview } from '../hooks/useNativeLivePreview.js'\nimport { useThemeFonts } from '../hooks/useThemeFonts.js'\nimport { borderRadiusPresets } from '../providers/Theme/themeConfig.js'\n\nconst DEVICE_ICONS: Record<DevicePreviewId, LucideIcon> = {\n mobile: Smartphone,\n tablet: Tablet,\n desktop: Monitor,\n}\n\n/**\n * Live, reactive preview of the Visual Effects + Component Styles + colour\n * choices. Mounted as a `ui` field inside the Appearance Settings tab so editors\n * see the combined result of every control update instantly — mirroring the CSS\n * that `generateThemeCSS` produces on the front-end.\n */\n\ntype Mode = 'light' | 'dark'\n\nconst SHADOW_MAP: Record<string, string> = {\n none: 'none',\n subtle: '0 1px 3px rgba(0,0,0,0.06), 0 1px 2px rgba(0,0,0,0.04)',\n medium: '0 4px 6px -1px rgba(0,0,0,0.1), 0 2px 4px -2px rgba(0,0,0,0.1)',\n strong: '0 10px 15px -3px rgba(0,0,0,0.1), 0 4px 6px -4px rgba(0,0,0,0.1)',\n dramatic: '0 25px 50px -12px rgba(0,0,0,0.25)',\n}\n\nconst BLUR_PX_MAP: Record<string, string> = {\n none: '0px',\n slight: '4px',\n medium: '8px',\n strong: '16px',\n heavy: '24px',\n}\n\nconst BUTTON_SIZE_MAP: Record<string, { padding: string; fontSize: string }> = {\n small: { padding: '6px 12px', fontSize: '12px' },\n medium: { padding: '8px 16px', fontSize: '13px' },\n large: { padding: '10px 24px', fontSize: '15px' },\n xl: { padding: '14px 32px', fontSize: '17px' },\n}\n\nfunction radiusToPx(token: string | undefined): string {\n const preset = borderRadiusPresets[(token ?? 'medium') as keyof typeof borderRadiusPresets]\n const css = preset?.css as Record<string, string> | undefined\n return css?.['--radius-large'] ?? css?.['--radius-default'] ?? '0.75rem'\n}\n\ninterface Palette {\n background: string\n foreground: string\n card: string\n cardForeground: 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 border: string\n gradientFrom: string\n gradientVia: string\n gradientTo: string\n}\n\ninterface Choices {\n effectStyle: string\n shadowIntensity: string\n backdropBlur: string\n borderStyle: string\n borderWidth: string\n glassOpacity: number\n buttonVariant: string\n buttonSize: string\n cardStyle: string\n cardHoverEffect: string\n imageStyle: string\n navbarStyle: string\n footerStyle: string\n linkStyle: string\n borderRadius: string\n /** Padding / gap multiplier from the spacing scale. */\n space: number\n}\n\nconst SPACING_SCALE: Record<string, number> = { compact: 0.75, medium: 1, comfortable: 1.5, spacious: 1.5 }\nconst px = (value: number, c: Choices) => `${Math.round(value * c.space)}px`\n\nfunction cardSurface(c: Choices, p: Palette, radius: string): React.CSSProperties {\n const base: React.CSSProperties = {\n background: p.card,\n color: p.cardForeground,\n borderRadius: radius,\n border:\n c.borderStyle === 'none' || c.borderWidth === '0px'\n ? 'none'\n : `${c.borderWidth} ${c.borderStyle} ${p.border}`,\n padding: px(16, c),\n transition: 'transform 200ms ease, box-shadow 200ms ease',\n }\n\n // Card style takes precedence for the structural look, effect style for depth.\n if (c.cardStyle === 'bordered') {\n return {\n ...base,\n border: `2px solid ${p.foreground}`,\n borderRadius: 0,\n boxShadow: `4px 4px 0 ${p.foreground}`,\n }\n }\n if (c.cardStyle === 'gradient-border') {\n return {\n ...base,\n border: '2px solid transparent',\n borderImage: `linear-gradient(135deg, ${p.gradientFrom}, ${p.gradientVia}, ${p.gradientTo}) 1`,\n boxShadow: SHADOW_MAP[c.shadowIntensity] ?? SHADOW_MAP.medium,\n }\n }\n\n switch (c.effectStyle) {\n case 'glass':\n return {\n ...base,\n background: `color-mix(in srgb, ${p.card} ${c.glassOpacity}%, transparent)`,\n backdropFilter: `blur(${BLUR_PX_MAP[c.backdropBlur] ?? '8px'}) saturate(150%)`,\n border: `1px solid color-mix(in srgb, ${p.border} 50%, transparent)`,\n boxShadow: '0 4px 24px rgba(0,0,0,0.10), inset 0 1px 0 rgba(255,255,255,0.15)',\n }\n case 'neumorphic':\n return {\n ...base,\n background: p.background,\n border: 'none',\n boxShadow: '6px 6px 12px rgba(0,0,0,0.12), -6px -6px 12px rgba(255,255,255,0.7)',\n }\n case 'clay':\n return {\n ...base,\n border: 'none',\n boxShadow: '4px 4px 0 rgba(0,0,0,0.22), 0 8px 20px rgba(0,0,0,0.08)',\n }\n case 'elevated':\n return { ...base, border: 'none', boxShadow: SHADOW_MAP[c.shadowIntensity] ?? SHADOW_MAP.medium }\n case 'flat':\n default:\n return { ...base, boxShadow: 'none' }\n }\n}\n\nfunction buttonStyle(c: Choices, p: Palette, radius: string): React.CSSProperties {\n const size = BUTTON_SIZE_MAP[c.buttonSize] ?? BUTTON_SIZE_MAP.medium!\n const base: React.CSSProperties = {\n ...size,\n fontWeight: 600,\n cursor: 'pointer',\n borderRadius: radius,\n border: 'none',\n transition: 'transform 120ms ease, box-shadow 120ms ease',\n whiteSpace: 'nowrap',\n }\n switch (c.buttonVariant) {\n case 'outlined':\n return { ...base, background: 'transparent', color: p.primary, border: `1.5px solid ${p.primary}` }\n case 'ghost':\n return { ...base, background: 'transparent', color: p.primary }\n case 'gradient':\n return {\n ...base,\n backgroundImage: `linear-gradient(135deg, ${p.gradientFrom}, ${p.gradientVia}, ${p.gradientTo})`,\n color: p.primaryForeground,\n }\n case 'pill':\n return { ...base, background: p.primary, color: p.primaryForeground, borderRadius: '9999px' }\n case 'brutal':\n return {\n ...base,\n background: p.card,\n color: p.foreground,\n border: `2px solid ${p.foreground}`,\n borderRadius: 0,\n boxShadow: `3px 3px 0 ${p.foreground}`,\n }\n case 'filled':\n default:\n return { ...base, background: p.primary, color: p.primaryForeground }\n }\n}\n\nfunction navbarStyle(c: Choices, p: Palette): React.CSSProperties {\n const base: React.CSSProperties = {\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'space-between',\n padding: `${px(10, c)} ${px(14, c)}`,\n background: p.background,\n color: p.foreground,\n borderBottom: `1px solid ${p.border}`,\n }\n switch (c.navbarStyle) {\n case 'transparent':\n return { ...base, background: 'transparent', borderBottom: '1px solid transparent' }\n case 'blur':\n return {\n ...base,\n background: `color-mix(in srgb, ${p.background} 70%, transparent)`,\n backdropFilter: 'blur(12px)',\n }\n case 'floating':\n return {\n ...base,\n margin: '8px',\n borderRadius: radiusToPx(c.borderRadius),\n border: `1px solid ${p.border}`,\n boxShadow: '0 4px 24px rgba(0,0,0,0.10)',\n }\n case 'minimal':\n return { ...base, borderBottom: `1px solid ${p.border}`, boxShadow: 'none' }\n case 'solid':\n default:\n return base\n }\n}\n\nfunction linkStyle(c: Choices, p: Palette): React.CSSProperties {\n switch (c.linkStyle) {\n case 'underline':\n return { color: p.primary, textDecoration: 'underline', textUnderlineOffset: '0.15em' }\n case 'none':\n return { color: p.primary, textDecoration: 'none' }\n case 'highlight':\n return {\n color: p.foreground,\n textDecoration: 'none',\n backgroundImage: `linear-gradient(transparent 60%, color-mix(in srgb, ${p.primary} 28%, transparent) 0)`,\n }\n case 'animated':\n return {\n color: p.primary,\n textDecoration: 'none',\n borderBottom: `2px solid ${p.primary}`,\n paddingBottom: '1px',\n }\n case 'underline-hover':\n default:\n return { color: p.primary, textDecoration: 'none' }\n }\n}\n\nexport default function AppearancePreviewField() {\n const formFields = useFormFields(([state]) => state) as Record<\n string,\n { value?: unknown } | undefined\n >\n const lang = useThemeLanguage() as 'en' | 'cs'\n const translations = useThemeTranslations()\n const t = translations.appearancePreview\n const site = translations.preview\n const [mode, setMode] = useState<Mode>('light')\n const [device, setDevice] = useState<DevicePreviewId>(DEFAULT_DEVICE_PREVIEW_ID)\n const uid = useId().replace(/[:]/g, '')\n const nativePreview = useNativeLivePreview()\n\n const activeDevice = getDevicePreview(device)\n\n // Fonts follow the Typography section (or the theme preset when set to \"Use theme preset\"),\n // so this single preview shows colours, type and component styles together.\n const typographyValue = (key: string) =>\n formFields?.[`themeConfiguration.typography.${key}`]?.value as string | undefined\n const typography = resolveTypographyPreview(\n {\n bodyFont: typographyValue('bodyFont'),\n headingFont: typographyValue('headingFont'),\n bodyFontCustom: typographyValue('bodyFontCustom'),\n headingFontCustom: typographyValue('headingFontCustom'),\n baseFontSize: typographyValue('baseFontSize'),\n lineHeight: typographyValue('lineHeight'),\n headingWeight: typographyValue('headingWeight'),\n letterSpacing: typographyValue('letterSpacing'),\n },\n formFields?.['themeConfiguration.theme']?.value as string | undefined,\n )\n useThemeFonts([typographyValue('bodyFont'), typographyValue('headingFont')])\n\n const str = (key: string, fallback: string): string => {\n const v = formFields?.[`themeConfiguration.${key}`]?.value\n return typeof v === 'string' && v.trim().length > 0 ? v : fallback\n }\n const num = (key: string, fallback: number): number => {\n const v = formFields?.[`themeConfiguration.${key}`]?.value\n return typeof v === 'number' ? v : fallback\n }\n\n const choices: Choices = {\n effectStyle: str('visualEffects.effectStyle', 'flat'),\n shadowIntensity: str('visualEffects.shadowIntensity', 'medium'),\n backdropBlur: str('visualEffects.backdropBlur', 'none'),\n borderStyle: str('visualEffects.borderStyle', 'solid'),\n borderWidth: str('visualEffects.borderWidth', '1px'),\n glassOpacity: num('visualEffects.glassOpacity', 60),\n buttonVariant: str('componentStyles.buttonVariant', 'filled'),\n buttonSize: str('componentStyles.buttonSize', 'medium'),\n cardStyle: str('componentStyles.cardStyle', 'elevated'),\n cardHoverEffect: str('componentStyles.cardHoverEffect', 'lift'),\n imageStyle: str('componentStyles.imageStyle', 'default'),\n navbarStyle: str('componentStyles.navbarStyle', 'solid'),\n footerStyle: str('componentStyles.footerStyle', 'standard'),\n linkStyle: str('componentStyles.linkStyle', 'underline-hover'),\n borderRadius: str('borderRadius', 'medium'),\n space: SPACING_SCALE[str('spacing', 'medium')] ?? 1,\n }\n\n const modeKey = mode === 'light' ? 'lightMode' : 'darkMode'\n const fallback: Palette =\n mode === 'light'\n ? {\n background: '#ffffff',\n foreground: '#0a0a0a',\n card: '#ffffff',\n cardForeground: '#0a0a0a',\n primary: '#9372f7',\n primaryForeground: '#fafafa',\n secondary: '#f4f4f5',\n secondaryForeground: '#18181b',\n muted: '#f4f4f5',\n mutedForeground: '#71717a',\n accent: '#f4f4f5',\n accentForeground: '#18181b',\n border: '#e4e4e7',\n gradientFrom: '#9372f7',\n gradientVia: '#7c6ff0',\n gradientTo: '#22d3ee',\n }\n : {\n background: '#0a0a0a',\n foreground: '#fafafa',\n card: '#09090b',\n cardForeground: '#fafafa',\n primary: '#9372f7',\n primaryForeground: '#09090b',\n secondary: '#27272a',\n secondaryForeground: '#fafafa',\n muted: '#27272a',\n mutedForeground: '#a1a1aa',\n accent: '#27272a',\n accentForeground: '#fafafa',\n border: '#27272a',\n gradientFrom: '#9372f7',\n gradientVia: '#7c6ff0',\n gradientTo: '#22d3ee',\n }\n\n const palette: Palette = useMemo(() => {\n const p = { ...fallback }\n ;(Object.keys(fallback) as (keyof Palette)[]).forEach((key) => {\n p[key] = str(`${modeKey}.${key}`, fallback[key])\n })\n // Same fallback as the site's --gradient-brand: primary → accent when no stops are set.\n p.gradientFrom = str(`${modeKey}.gradientFrom`, p.primary)\n p.gradientTo = str(`${modeKey}.gradientTo`, p.accent)\n p.gradientVia = str(`${modeKey}.gradientVia`, p.gradientFrom)\n return p\n }, [formFields, mode])\n\n const radius = radiusToPx(choices.borderRadius)\n const card = cardSurface(choices, palette, radius)\n const btn = buttonStyle(choices, palette, radius)\n const nav = navbarStyle(choices, palette)\n\n // Hover effects can't be expressed inline, so emit a scoped style block.\n const hoverCSS = (() => {\n const sel = `.${uid} .tm-prev-card`\n switch (choices.cardHoverEffect) {\n case 'lift':\n return `${sel}:hover{transform:translateY(-6px);box-shadow:0 20px 40px rgba(0,0,0,0.14)}`\n case 'scale':\n return `${sel}:hover{transform:scale(1.02)}`\n case 'glow':\n return `${sel}:hover{box-shadow:0 0 0 3px color-mix(in srgb, ${palette.primary} 25%, transparent),0 8px 32px rgba(0,0,0,0.12)}`\n case 'shadow':\n return `${sel}:hover{box-shadow:0 24px 50px -12px rgba(0,0,0,0.35)}`\n case 'tilt':\n return `${sel}:hover{transform:perspective(800px) rotateX(3deg) rotateY(-3deg)}`\n default:\n return ''\n }\n })()\n const btnHoverCSS = `.${uid} .tm-prev-btn:hover{filter:brightness(1.05)}${\n choices.buttonVariant === 'brutal'\n ? `.${uid} .tm-prev-btn:hover{transform:translate(-2px,-2px);box-shadow:5px 5px 0 ${palette.foreground}}`\n : ''\n }`\n // Movement-based hover effects only run for users who haven't asked for reduced motion.\n const previewCSS = `@media (prefers-reduced-motion: no-preference){${hoverCSS}${btnHoverCSS}}`\n\n // Content image treatment, mirroring the site's [data-img] rules.\n const imageCss: React.CSSProperties = (() => {\n const base: React.CSSProperties = {\n aspectRatio: '4 / 3',\n borderRadius: 0,\n backgroundImage: `radial-gradient(circle at 70% 30%, ${palette.accent} 0 18%, transparent 19%), linear-gradient(160deg, ${palette.gradientFrom}, ${palette.gradientTo})`,\n }\n switch (choices.imageStyle) {\n case 'rounded':\n return { ...base, borderRadius: radius }\n case 'circle':\n return { ...base, aspectRatio: '1 / 1', borderRadius: '9999px' }\n case 'grayscale':\n return { ...base, filter: 'grayscale(1)' }\n case 'duotone':\n return { ...base, filter: 'grayscale(1) contrast(1.05)', mixBlendMode: 'luminosity' }\n case 'vignette':\n return { ...base, boxShadow: 'inset 0 0 40px rgba(0,0,0,0.45)' }\n case 'polaroid':\n return {\n ...base,\n border: '8px solid #fff',\n borderBottomWidth: '24px',\n boxShadow: '0 6px 16px rgba(0,0,0,0.18)',\n borderRadius: '2px',\n }\n default:\n return base\n }\n })()\n\n const headingStyle: React.CSSProperties = {\n fontFamily: typography.headingFont,\n fontWeight: Number(typography.headingWeight) || 700,\n letterSpacing: typography.headingLetterSpacing,\n textTransform: typography.headingTransform,\n lineHeight: 1.15,\n margin: 0,\n }\n\n const footerStyleCss: React.CSSProperties =\n choices.footerStyle === 'dark'\n ? { background: palette.foreground, color: palette.background }\n : choices.footerStyle === 'full-color'\n ? { background: palette.primary, color: palette.primaryForeground }\n : choices.footerStyle === 'gradient-top'\n ? {\n background: palette.background,\n color: palette.mutedForeground,\n borderTop: '3px solid transparent',\n borderImage: `linear-gradient(135deg, ${palette.gradientFrom}, ${palette.gradientVia}, ${palette.gradientTo}) 1`,\n }\n : choices.footerStyle === 'minimal'\n ? { background: 'transparent', color: palette.mutedForeground, borderTop: `1px solid ${palette.border}` }\n : { background: palette.muted, color: palette.mutedForeground, borderTop: `1px solid ${palette.border}` }\n\n // With Payload's native Live Preview the real site is the preview: no mock.\n if (nativePreview.isEnabled) {\n if (nativePreview.isOpen) return null\n return (\n <div className=\"tm-native-preview-hint\">\n <div className=\"tm-native-preview-hint__text\">\n <span className=\"tm-native-preview-hint__title\">\n <Sparkles size={14} aria-hidden />\n {t.nativeTitle}\n </span>\n <span className=\"tm-native-preview-hint__body\">{t.nativeBody}</span>\n </div>\n <button type=\"button\" className=\"tm-native-preview-hint__action\" onClick={nativePreview.open}>\n <ExternalLink size={14} aria-hidden />\n {t.nativeOpen}\n </button>\n </div>\n )\n }\n\n return (\n // The slot spans the whole right column of the Appearance tab on wide admins;\n // its inner panel is sticky so the preview stays in view while editing.\n <div className={`tm-live-preview-slot ${uid}`}>\n <div className=\"tm-live-preview\">\n <style dangerouslySetInnerHTML={{ __html: previewCSS }} />\n\n <div\n style={{\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'space-between',\n marginBottom: '8px',\n gap: '8px',\n flexWrap: 'wrap',\n }}\n >\n <div>\n <div\n style={{\n display: 'inline-flex',\n alignItems: 'center',\n gap: '6px',\n fontSize: '13px',\n fontWeight: 600,\n color: 'var(--theme-elevation-800)',\n }}\n >\n <Sparkles size={14} aria-hidden />\n {t.title}\n </div>\n <div style={{ fontSize: '12px', color: 'var(--theme-elevation-600)' }}>{t.subtitle}</div>\n </div>\n <div style={{ display: 'inline-flex', gap: '8px', flexWrap: 'wrap' }}>\n {/* Device / viewport switcher */}\n <div\n role=\"group\"\n aria-label={t.viewport}\n style={{ display: 'inline-flex', borderRadius: '8px', overflow: 'hidden', border: '1px solid var(--theme-elevation-200)' }}\n >\n {DEVICE_PREVIEWS.map((d) => {\n const Icon = DEVICE_ICONS[d.id]\n return (\n <button\n key={d.id}\n type=\"button\"\n aria-pressed={device === d.id}\n onClick={() => setDevice(d.id)}\n title={`${lang === 'cs' ? d.labelCs : d.label} — ${d.width}×${d.height}`}\n style={{\n display: 'inline-flex',\n alignItems: 'center',\n gap: '5px',\n minHeight: '28px',\n padding: '5px 10px',\n fontSize: '12px',\n fontWeight: 600,\n cursor: 'pointer',\n border: 'none',\n background: device === d.id ? 'var(--theme-elevation-800)' : 'transparent',\n color: device === d.id ? 'var(--theme-elevation-0)' : 'var(--theme-elevation-600)',\n }}\n >\n <Icon size={13} aria-hidden />\n {lang === 'cs' ? d.labelCs : d.label}\n </button>\n )\n })}\n </div>\n {/* Light / dark switcher */}\n <div\n role=\"group\"\n aria-label={`${t.light} / ${t.dark}`}\n style={{ display: 'inline-flex', borderRadius: '8px', overflow: 'hidden', border: '1px solid var(--theme-elevation-200)' }}\n >\n {(['light', 'dark'] as Mode[]).map((m) => {\n const Icon = m === 'light' ? Sun : Moon\n return (\n <button\n key={m}\n type=\"button\"\n aria-pressed={mode === m}\n onClick={() => setMode(m)}\n style={{\n display: 'inline-flex',\n alignItems: 'center',\n gap: '5px',\n minHeight: '28px',\n padding: '5px 12px',\n fontSize: '12px',\n fontWeight: 600,\n cursor: 'pointer',\n border: 'none',\n background: mode === m ? 'var(--theme-elevation-800)' : 'transparent',\n color: mode === m ? 'var(--theme-elevation-0)' : 'var(--theme-elevation-600)',\n }}\n >\n <Icon size={13} aria-hidden />\n {m === 'light' ? t.light : t.dark}\n </button>\n )\n })}\n </div>\n </div>\n </div>\n\n {/* Viewport wrapper — constrains the frame to the active device width */}\n <div\n style={{\n display: 'flex',\n justifyContent: 'center',\n background: 'var(--theme-elevation-50)',\n borderRadius: '14px',\n padding: device === 'desktop' ? '0' : '16px',\n }}\n >\n {/* Browser-like frame. It is a picture of the site, so it is inert: its\n sample buttons and links must not become dead tab stops. */}\n <div\n ref={(el) => el?.setAttribute('inert', '')}\n style={{\n width: '100%',\n maxWidth: device === 'desktop' ? '100%' : `${activeDevice.width}px`,\n borderRadius: '14px',\n overflow: 'hidden',\n border: '1px solid var(--theme-elevation-200)',\n boxShadow: '0 8px 24px rgba(0,0,0,0.10)',\n background: palette.background,\n color: palette.foreground,\n fontFamily: typography.bodyFont,\n lineHeight: typography.lineHeight,\n }}\n >\n <nav style={nav}>\n <span style={{ fontWeight: 700, fontSize: '13px' }}>{site.siteTitle}</span>\n <span style={{ display: 'flex', gap: '14px', fontSize: '12px', opacity: 0.85 }}>\n <span>{site.nav.home}</span>\n <span>{site.nav.about}</span>\n <span style={{ ...linkStyle(choices, palette) }}>{site.nav.services}</span>\n </span>\n </nav>\n\n <div style={{ padding: px(20, choices), display: 'grid', gap: px(14, choices) }}>\n <div>\n <div style={{ ...headingStyle, fontSize: '24px' }}>{t.heading}</div>\n <p\n style={{\n margin: `${px(6, choices)} 0 0`,\n fontSize: `calc(${typography.baseFontSize} * 0.8125)`,\n lineHeight: typography.lineHeight,\n color: palette.mutedForeground,\n maxWidth: '60ch',\n }}\n >\n {t.body}\n <a style={linkStyle(choices, palette)}>{t.link}</a>.\n </p>\n </div>\n\n <div\n style={{\n display: 'grid',\n gridTemplateColumns: device === 'mobile' ? '1fr' : 'minmax(0, 3fr) minmax(0, 2fr)',\n gap: px(12, choices),\n alignItems: 'start',\n }}\n >\n <div className=\"tm-prev-card\" style={card}>\n <div style={{ ...headingStyle, fontSize: '15px', marginBottom: px(6, choices) }}>\n {t.cardTitle}\n </div>\n <p\n style={{\n margin: `0 0 ${px(12, choices)}`,\n fontSize: `calc(${typography.baseFontSize} * 0.75)`,\n lineHeight: typography.lineHeight,\n color: palette.cardForeground,\n opacity: 0.8,\n }}\n >\n {t.cardBody}\n </p>\n <div style={{ display: 'flex', gap: '8px', alignItems: 'center', flexWrap: 'wrap' }}>\n <button type=\"button\" className=\"tm-prev-btn\" style={btn}>\n {t.primary}\n </button>\n <button\n type=\"button\"\n style={{\n ...(BUTTON_SIZE_MAP[choices.buttonSize] ?? BUTTON_SIZE_MAP.medium),\n fontWeight: 600,\n cursor: 'pointer',\n borderRadius: choices.buttonVariant === 'pill' ? '9999px' : radius,\n background: palette.secondary,\n color: palette.secondaryForeground,\n border: 'none',\n }}\n >\n {t.secondary}\n </button>\n </div>\n </div>\n <div aria-hidden style={imageCss} />\n </div>\n </div>\n\n <div style={{ padding: `${px(12, choices)} ${px(16, choices)}`, fontSize: '11px', ...footerStyleCss }}>\n © {new Date().getFullYear()} {site.siteTitle} — {t.footer}\n </div>\n </div>\n </div>\n\n </div>\n </div>\n )\n}\n"],"names":["useFormFields","ExternalLink","Monitor","Moon","Smartphone","Sparkles","Sun","Tablet","useId","useMemo","useState","DEFAULT_DEVICE_PREVIEW_ID","DEVICE_PREVIEWS","getDevicePreview","useThemeLanguage","useThemeTranslations","resolveTypographyPreview","useNativeLivePreview","useThemeFonts","borderRadiusPresets","DEVICE_ICONS","mobile","tablet","desktop","SHADOW_MAP","none","subtle","medium","strong","dramatic","BLUR_PX_MAP","slight","heavy","BUTTON_SIZE_MAP","small","padding","fontSize","large","xl","radiusToPx","token","preset","css","SPACING_SCALE","compact","comfortable","spacious","px","value","c","Math","round","space","cardSurface","p","radius","base","background","card","color","cardForeground","borderRadius","border","borderStyle","borderWidth","transition","cardStyle","foreground","boxShadow","borderImage","gradientFrom","gradientVia","gradientTo","shadowIntensity","effectStyle","glassOpacity","backdropFilter","backdropBlur","buttonStyle","size","buttonSize","fontWeight","cursor","whiteSpace","buttonVariant","primary","backgroundImage","primaryForeground","navbarStyle","display","alignItems","justifyContent","borderBottom","margin","linkStyle","textDecoration","textUnderlineOffset","paddingBottom","AppearancePreviewField","formFields","state","lang","translations","t","appearancePreview","site","preview","mode","setMode","device","setDevice","uid","replace","nativePreview","activeDevice","typographyValue","key","typography","bodyFont","headingFont","bodyFontCustom","headingFontCustom","baseFontSize","lineHeight","headingWeight","letterSpacing","str","fallback","v","trim","length","num","choices","cardHoverEffect","imageStyle","footerStyle","modeKey","secondary","secondaryForeground","muted","mutedForeground","accent","accentForeground","palette","Object","keys","forEach","btn","nav","hoverCSS","sel","btnHoverCSS","previewCSS","imageCss","aspectRatio","filter","mixBlendMode","borderBottomWidth","headingStyle","fontFamily","Number","headingLetterSpacing","textTransform","headingTransform","footerStyleCss","borderTop","isEnabled","isOpen","div","className","span","aria-hidden","nativeTitle","nativeBody","button","type","onClick","open","nativeOpen","style","dangerouslySetInnerHTML","__html","marginBottom","gap","flexWrap","title","subtitle","role","aria-label","viewport","overflow","map","d","Icon","id","aria-pressed","labelCs","label","width","height","minHeight","light","dark","m","ref","el","setAttribute","maxWidth","siteTitle","opacity","home","about","services","heading","body","a","link","gridTemplateColumns","cardTitle","cardBody","Date","getFullYear","footer"],"mappings":"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"}
@@ -0,0 +1,155 @@
1
+ /* Font select, styled like Payload's own select (react-select `.rs__control`). */
2
+
3
+ .tm-font-select {
4
+ position: relative;
5
+ min-width: 0;
6
+ margin-bottom: var(--spacing-field, 1rem);
7
+ }
8
+
9
+ .tm-font-select__trigger {
10
+ display: flex;
11
+ align-items: center;
12
+ justify-content: space-between;
13
+ gap: 8px;
14
+ width: 100%;
15
+ min-height: 40px;
16
+ padding: 7px 12px;
17
+ border: 1px solid var(--theme-elevation-150);
18
+ border-radius: var(--style-radius-s);
19
+ background: var(--theme-input-bg);
20
+ color: var(--theme-elevation-800);
21
+ box-shadow: 0 2px 2px -1px #0000001a;
22
+ font-family: var(--font-body);
23
+ font-size: 1rem;
24
+ line-height: 20px;
25
+ text-align: left;
26
+ cursor: pointer;
27
+ transition: border-color 100ms ease;
28
+ }
29
+
30
+ .tm-font-select__trigger:hover {
31
+ border-color: var(--theme-elevation-250);
32
+ }
33
+
34
+ .tm-font-select__trigger:focus-visible {
35
+ outline: var(--accessibility-outline, 2px solid var(--theme-elevation-800));
36
+ outline-offset: var(--accessibility-outline-offset, 1px);
37
+ }
38
+
39
+ .tm-font-select__value {
40
+ flex: 1 1 auto;
41
+ min-width: 0;
42
+ overflow: hidden;
43
+ text-overflow: ellipsis;
44
+ white-space: nowrap;
45
+ }
46
+
47
+ .tm-font-select__chevron {
48
+ flex-shrink: 0;
49
+ color: var(--theme-elevation-500);
50
+ transition: transform 150ms ease;
51
+ }
52
+
53
+ .tm-font-select__chevron.is-open {
54
+ transform: rotate(180deg);
55
+ }
56
+
57
+ .tm-font-select__listbox {
58
+ position: absolute;
59
+ top: 100%;
60
+ left: 0;
61
+ z-index: 1000;
62
+ /* Wide enough for the sample line even when the field sits in a half-width column. */
63
+ width: max(100%, 300px);
64
+ max-width: calc(100vw - 32px);
65
+ max-height: 340px;
66
+ margin-top: 4px;
67
+ padding: 4px 0;
68
+ overflow-x: hidden;
69
+ overflow-y: auto;
70
+ overscroll-behavior: contain;
71
+ border: 1px solid var(--theme-elevation-150);
72
+ border-radius: var(--style-radius-m, 6px);
73
+ background: var(--theme-elevation-0);
74
+ box-shadow: 0 10px 28px -6px rgba(0, 0, 0, 0.22);
75
+ }
76
+
77
+ .tm-font-select__listbox:focus-visible {
78
+ outline: none;
79
+ }
80
+
81
+ .tm-font-select__group {
82
+ padding: 10px 12px 4px 36px;
83
+ font-family: var(--font-body);
84
+ font-size: 12px;
85
+ font-weight: 600;
86
+ color: var(--theme-elevation-500);
87
+ }
88
+
89
+ .tm-font-select__option {
90
+ display: flex;
91
+ align-items: flex-start;
92
+ gap: 8px;
93
+ padding: 7px 12px;
94
+ color: var(--theme-elevation-800);
95
+ cursor: pointer;
96
+ }
97
+
98
+ .tm-font-select__option.is-active {
99
+ background: var(--theme-elevation-100);
100
+ /* The keyboard position never relies on the fill alone. */
101
+ box-shadow: inset 2px 0 0 var(--theme-elevation-800);
102
+ }
103
+
104
+ .tm-font-select__check {
105
+ display: inline-flex;
106
+ flex: 0 0 16px;
107
+ justify-content: center;
108
+ padding-top: 3px;
109
+ color: var(--theme-elevation-800);
110
+ }
111
+
112
+ .tm-font-select__text {
113
+ display: grid;
114
+ gap: 1px;
115
+ min-width: 0;
116
+ flex: 1 1 auto;
117
+ }
118
+
119
+ .tm-font-select__name {
120
+ font-size: 15px;
121
+ line-height: 1.35;
122
+ white-space: nowrap;
123
+ overflow: hidden;
124
+ text-overflow: ellipsis;
125
+ }
126
+
127
+ .tm-font-select__option.is-selected .tm-font-select__name {
128
+ font-weight: 600;
129
+ }
130
+
131
+ .tm-font-select__sample {
132
+ font-size: 13px;
133
+ line-height: 1.4;
134
+ color: var(--theme-elevation-500);
135
+ white-space: nowrap;
136
+ overflow: hidden;
137
+ text-overflow: ellipsis;
138
+ }
139
+
140
+ .tm-font-select__sample.is-hint {
141
+ font-family: var(--font-body);
142
+ font-size: 12px;
143
+ }
144
+
145
+ @media (prefers-reduced-motion: reduce) {
146
+ .tm-font-select__chevron,
147
+ .tm-font-select__trigger {
148
+ transition: none;
149
+ }
150
+ }
151
+
152
+ .tm-font-select__listbox.is-align-end {
153
+ left: auto;
154
+ right: 0;
155
+ }
@@ -1,9 +1,11 @@
1
+ import './FontSelectField.css';
1
2
  import type { SelectFieldClientComponent } from 'payload';
2
3
  /**
3
4
  * Font select with live font previews. Implements the WAI-ARIA "select-only
4
5
  * combobox" pattern: a button trigger plus a listbox navigated with the arrow
5
- * keys, Home/End, Enter/Space and Escape. Preview fonts load for whichever option
6
- * is active, so keyboard users get the same previews as mouse users.
6
+ * keys, Home/End, Enter/Space and Escape. Options are grouped by font category.
7
+ * Preview fonts come from the plugin's self-hosted font endpoint: the selected
8
+ * face always, every face while the list is open.
7
9
  */
8
10
  declare const FontSelectField: SelectFieldClientComponent;
9
11
  export default FontSelectField;
@@ -1 +1 @@
1
- {"version":3,"file":"FontSelectField.d.ts","sourceRoot":"","sources":["../../src/fields/FontSelectField.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,SAAS,CAAA;AAwBzD;;;;;GAKG;AACH,QAAA,MAAM,eAAe,EAAE,0BAsRtB,CAAA;AAED,eAAe,eAAe,CAAA"}
1
+ {"version":3,"file":"FontSelectField.d.ts","sourceRoot":"","sources":["../../src/fields/FontSelectField.tsx"],"names":[],"mappings":"AAEA,OAAO,uBAAuB,CAAA;AAI9B,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,SAAS,CAAA;AA4BzD;;;;;;GAMG;AACH,QAAA,MAAM,eAAe,EAAE,0BAyOtB,CAAA;AAED,eAAe,eAAe,CAAA"}