@kilivi/payloadcms-theme-management 2.0.0 → 2.1.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 (214) hide show
  1. package/README.md +318 -847
  2. package/dist/components/AppearanceSessionControls.d.ts +15 -0
  3. package/dist/components/AppearanceSessionControls.d.ts.map +1 -0
  4. package/dist/components/AppearanceSessionControls.js +152 -0
  5. package/dist/components/AppearanceSessionControls.js.map +1 -0
  6. package/dist/components/ColorModeToggle.css +42 -0
  7. package/dist/components/ColorModeToggle.d.ts +40 -0
  8. package/dist/components/ColorModeToggle.d.ts.map +1 -0
  9. package/dist/components/ColorModeToggle.js +111 -0
  10. package/dist/components/ColorModeToggle.js.map +1 -0
  11. package/dist/components/ServerThemeInjector.d.ts.map +1 -1
  12. package/dist/components/ServerThemeInjector.js +41 -14
  13. package/dist/components/ServerThemeInjector.js.map +1 -1
  14. package/dist/components/ThemeLivePreviewSync.d.ts +1 -0
  15. package/dist/components/ThemeLivePreviewSync.d.ts.map +1 -1
  16. package/dist/components/ThemeLivePreviewSync.js +1 -1
  17. package/dist/components/ThemeLivePreviewSync.js.map +1 -1
  18. package/dist/components/ThemeSwitcher.d.ts +36 -0
  19. package/dist/components/ThemeSwitcher.d.ts.map +1 -0
  20. package/dist/components/ThemeSwitcher.js +89 -0
  21. package/dist/components/ThemeSwitcher.js.map +1 -0
  22. package/dist/components/typographyPreviewUtils.d.ts.map +1 -1
  23. package/dist/components/typographyPreviewUtils.js +8 -1
  24. package/dist/components/typographyPreviewUtils.js.map +1 -1
  25. package/dist/constants/devicePreviews.d.ts +35 -0
  26. package/dist/constants/devicePreviews.d.ts.map +1 -0
  27. package/dist/constants/devicePreviews.js +43 -0
  28. package/dist/constants/devicePreviews.js.map +1 -0
  29. package/dist/constants/themeFonts.js +9 -9
  30. package/dist/constants/themeFonts.js.map +1 -1
  31. package/dist/extended-presets.d.ts +0 -4
  32. package/dist/extended-presets.d.ts.map +1 -1
  33. package/dist/extended-presets.js +1 -18
  34. package/dist/extended-presets.js.map +1 -1
  35. package/dist/extended-themes.d.ts.map +1 -1
  36. package/dist/extended-themes.js +428 -0
  37. package/dist/extended-themes.js.map +1 -1
  38. package/dist/fields/AccessibilityAuditField.d.ts +2 -0
  39. package/dist/fields/AccessibilityAuditField.d.ts.map +1 -0
  40. package/dist/fields/AccessibilityAuditField.js +303 -0
  41. package/dist/fields/AccessibilityAuditField.js.map +1 -0
  42. package/dist/fields/AppearancePreviewField.d.ts +2 -0
  43. package/dist/fields/AppearancePreviewField.d.ts.map +1 -0
  44. package/dist/fields/AppearancePreviewField.js +763 -0
  45. package/dist/fields/AppearancePreviewField.js.map +1 -0
  46. package/dist/fields/ColorPickerField.d.ts.map +1 -1
  47. package/dist/fields/ColorPickerField.js +89 -85
  48. package/dist/fields/ColorPickerField.js.map +1 -1
  49. package/dist/fields/FontSelectField.d.ts +6 -0
  50. package/dist/fields/FontSelectField.d.ts.map +1 -1
  51. package/dist/fields/FontSelectField.js +195 -122
  52. package/dist/fields/FontSelectField.js.map +1 -1
  53. package/dist/fields/PaletteGeneratorField.d.ts +7 -0
  54. package/dist/fields/PaletteGeneratorField.d.ts.map +1 -0
  55. package/dist/fields/PaletteGeneratorField.js +327 -0
  56. package/dist/fields/PaletteGeneratorField.js.map +1 -0
  57. package/dist/fields/StylePresetField.d.ts +3 -0
  58. package/dist/fields/StylePresetField.d.ts.map +1 -0
  59. package/dist/fields/StylePresetField.js +462 -0
  60. package/dist/fields/StylePresetField.js.map +1 -0
  61. package/dist/fields/ThemeColorPickerField.css +115 -35
  62. package/dist/fields/ThemeColorPickerField.d.ts.map +1 -1
  63. package/dist/fields/ThemeColorPickerField.js +204 -70
  64. package/dist/fields/ThemeColorPickerField.js.map +1 -1
  65. package/dist/fields/ThemeExportField.d.ts +6 -0
  66. package/dist/fields/ThemeExportField.d.ts.map +1 -0
  67. package/dist/fields/ThemeExportField.js +202 -0
  68. package/dist/fields/ThemeExportField.js.map +1 -0
  69. package/dist/fields/ThemePresetImportField.d.ts.map +1 -1
  70. package/dist/fields/ThemePresetImportField.js +56 -25
  71. package/dist/fields/ThemePresetImportField.js.map +1 -1
  72. package/dist/fields/ThemePreviewField.css +382 -5
  73. package/dist/fields/ThemePreviewField.d.ts.map +1 -1
  74. package/dist/fields/ThemePreviewField.js +268 -170
  75. package/dist/fields/ThemePreviewField.js.map +1 -1
  76. package/dist/fields/ThemeTokenSelectField.d.ts.map +1 -1
  77. package/dist/fields/ThemeTokenSelectField.js +278 -80
  78. package/dist/fields/ThemeTokenSelectField.js.map +1 -1
  79. package/dist/fields/colorFieldHelpers.d.ts +90 -0
  80. package/dist/fields/colorFieldHelpers.d.ts.map +1 -0
  81. package/dist/fields/colorFieldHelpers.js +133 -0
  82. package/dist/fields/colorFieldHelpers.js.map +1 -0
  83. package/dist/fields/colorModeFields.d.ts +1 -1
  84. package/dist/fields/colorModeFields.d.ts.map +1 -1
  85. package/dist/fields/colorModeFields.js +49 -7
  86. package/dist/fields/colorModeFields.js.map +1 -1
  87. package/dist/fields/themeConfigurationField.d.ts +8 -1
  88. package/dist/fields/themeConfigurationField.d.ts.map +1 -1
  89. package/dist/fields/themeConfigurationField.js +961 -29
  90. package/dist/fields/themeConfigurationField.js.map +1 -1
  91. package/dist/globals/ThemeSettings/FontPicker/FontPreview.d.ts.map +1 -1
  92. package/dist/globals/ThemeSettings/FontPicker/FontPreview.js +8 -4
  93. package/dist/globals/ThemeSettings/FontPicker/FontPreview.js.map +1 -1
  94. package/dist/globals/ThemeSettings/FontPicker/index.d.ts.map +1 -1
  95. package/dist/globals/ThemeSettings/FontPicker/index.js +81 -26
  96. package/dist/globals/ThemeSettings/FontPicker/index.js.map +1 -1
  97. package/dist/globals/ThemeSettings/FontPicker/styles.css +98 -41
  98. package/dist/globals/ThemeSettings/FontPicker/translations.d.ts +6 -0
  99. package/dist/globals/ThemeSettings/FontPicker/translations.d.ts.map +1 -1
  100. package/dist/globals/ThemeSettings/FontPicker/translations.js +14 -2
  101. package/dist/globals/ThemeSettings/FontPicker/translations.js.map +1 -1
  102. package/dist/globals/ThemeSettings/config.d.ts.map +1 -1
  103. package/dist/globals/ThemeSettings/config.js +76 -79
  104. package/dist/globals/ThemeSettings/config.js.map +1 -1
  105. package/dist/globals/ThemeSettings/fields/FontLoadingGuideField.d.ts.map +1 -1
  106. package/dist/globals/ThemeSettings/fields/FontLoadingGuideField.js +63 -62
  107. package/dist/globals/ThemeSettings/fields/FontLoadingGuideField.js.map +1 -1
  108. package/dist/globals/ThemeSettings/fields/TypographyInfoField.d.ts.map +1 -1
  109. package/dist/globals/ThemeSettings/fields/TypographyInfoField.js +22 -25
  110. package/dist/globals/ThemeSettings/fields/TypographyInfoField.js.map +1 -1
  111. package/dist/hooks/useAppearanceSession.d.ts +50 -0
  112. package/dist/hooks/useAppearanceSession.d.ts.map +1 -0
  113. package/dist/hooks/useAppearanceSession.js +91 -0
  114. package/dist/hooks/useAppearanceSession.js.map +1 -0
  115. package/dist/hooks/useThemeTranslations.d.ts +13 -0
  116. package/dist/hooks/useThemeTranslations.d.ts.map +1 -0
  117. package/dist/hooks/useThemeTranslations.js +22 -0
  118. package/dist/hooks/useThemeTranslations.js.map +1 -0
  119. package/dist/i18n.d.ts +53 -0
  120. package/dist/i18n.d.ts.map +1 -0
  121. package/dist/i18n.js +53 -0
  122. package/dist/i18n.js.map +1 -0
  123. package/dist/index.d.ts +10 -4
  124. package/dist/index.d.ts.map +1 -1
  125. package/dist/index.js +50 -29
  126. package/dist/index.js.map +1 -1
  127. package/dist/payload-types.d.ts +24 -0
  128. package/dist/payload-types.d.ts.map +1 -1
  129. package/dist/payload-types.js.map +1 -1
  130. package/dist/presets.d.ts +8 -0
  131. package/dist/presets.d.ts.map +1 -1
  132. package/dist/presets.js.map +1 -1
  133. package/dist/providers/Theme/index.d.ts.map +1 -1
  134. package/dist/providers/Theme/index.js +75 -11
  135. package/dist/providers/Theme/index.js.map +1 -1
  136. package/dist/providers/Theme/themeConfig.d.ts.map +1 -1
  137. package/dist/providers/Theme/themeConfig.js +104 -0
  138. package/dist/providers/Theme/themeConfig.js.map +1 -1
  139. package/dist/providers/Theme/types.d.ts +1 -1
  140. package/dist/providers/Theme/types.d.ts.map +1 -1
  141. package/dist/providers/Theme/types.js +10 -1
  142. package/dist/providers/Theme/types.js.map +1 -1
  143. package/dist/style-presets.d.ts +66 -0
  144. package/dist/style-presets.d.ts.map +1 -0
  145. package/dist/style-presets.js +556 -0
  146. package/dist/style-presets.js.map +1 -0
  147. package/dist/translations.d.ts +159 -1
  148. package/dist/translations.d.ts.map +1 -1
  149. package/dist/translations.js +310 -9
  150. package/dist/translations.js.map +1 -1
  151. package/dist/tweakcn-special-themes.d.ts.map +1 -1
  152. package/dist/tweakcn-special-themes.js +585 -9
  153. package/dist/tweakcn-special-themes.js.map +1 -1
  154. package/dist/types/css.d.js +3 -0
  155. package/dist/types/css.d.js.map +1 -0
  156. package/dist/types.d.ts +26 -0
  157. package/dist/types.d.ts.map +1 -1
  158. package/dist/types.js +1 -1
  159. package/dist/types.js.map +1 -1
  160. package/dist/utilities/getThemeSettings.d.ts.map +1 -1
  161. package/dist/utilities/getThemeSettings.js +2 -14
  162. package/dist/utilities/getThemeSettings.js.map +1 -1
  163. package/dist/utils/contrast.d.ts +63 -0
  164. package/dist/utils/contrast.d.ts.map +1 -0
  165. package/dist/utils/contrast.js +158 -0
  166. package/dist/utils/contrast.js.map +1 -0
  167. package/dist/utils/exportTokens.d.ts +30 -0
  168. package/dist/utils/exportTokens.d.ts.map +1 -0
  169. package/dist/utils/exportTokens.js +183 -0
  170. package/dist/utils/exportTokens.js.map +1 -0
  171. package/dist/utils/generatePalette.d.ts +46 -0
  172. package/dist/utils/generatePalette.d.ts.map +1 -0
  173. package/dist/utils/generatePalette.js +127 -0
  174. package/dist/utils/generatePalette.js.map +1 -0
  175. package/dist/utils/generateThemeCSS.d.ts.map +1 -1
  176. package/dist/utils/generateThemeCSS.js +2 -40
  177. package/dist/utils/generateThemeCSS.js.map +1 -1
  178. package/dist/utils/livePreviewThemeRuntime.d.ts +16 -2
  179. package/dist/utils/livePreviewThemeRuntime.d.ts.map +1 -1
  180. package/dist/utils/livePreviewThemeRuntime.js +37 -14
  181. package/dist/utils/livePreviewThemeRuntime.js.map +1 -1
  182. package/dist/utils/localizedText.d.ts +8 -0
  183. package/dist/utils/localizedText.d.ts.map +1 -0
  184. package/dist/utils/localizedText.js +21 -0
  185. package/dist/utils/localizedText.js.map +1 -0
  186. package/dist/utils/resolveThemeConfiguration.d.ts +45 -1
  187. package/dist/utils/resolveThemeConfiguration.d.ts.map +1 -1
  188. package/dist/utils/resolveThemeConfiguration.js +12 -5
  189. package/dist/utils/resolveThemeConfiguration.js.map +1 -1
  190. package/dist/utils/themeColors.d.ts +3 -0
  191. package/dist/utils/themeColors.d.ts.map +1 -1
  192. package/dist/utils/themeColors.js +30 -1
  193. package/dist/utils/themeColors.js.map +1 -1
  194. package/dist/utils/themeHtmlAttributes.d.ts +32 -12
  195. package/dist/utils/themeHtmlAttributes.d.ts.map +1 -1
  196. package/dist/utils/themeHtmlAttributes.js +38 -5
  197. package/dist/utils/themeHtmlAttributes.js.map +1 -1
  198. package/dist/utils/themeUtils.d.ts +3 -5
  199. package/dist/utils/themeUtils.d.ts.map +1 -1
  200. package/dist/utils/themeUtils.js +416 -6
  201. package/dist/utils/themeUtils.js.map +1 -1
  202. package/dist/utils/tweakcnConverter.d.ts +1 -3
  203. package/dist/utils/tweakcnConverter.d.ts.map +1 -1
  204. package/dist/utils/tweakcnConverter.js +1 -3
  205. package/dist/utils/tweakcnConverter.js.map +1 -1
  206. package/package.json +11 -5
  207. package/dist/components/ThemePreview.d.ts +0 -3
  208. package/dist/components/ThemePreview.d.ts.map +0 -1
  209. package/dist/components/ThemePreview.js +0 -321
  210. package/dist/components/ThemePreview.js.map +0 -1
  211. package/dist/plugin.d.ts +0 -2
  212. package/dist/plugin.d.ts.map +0 -1
  213. package/dist/plugin.js +0 -3
  214. package/dist/plugin.js.map +0 -1
@@ -0,0 +1,763 @@
1
+ 'use client';
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { useFormFields } from '@payloadcms/ui';
4
+ import { Monitor, Moon, Smartphone, Sparkles, Sun, Tablet } from 'lucide-react';
5
+ import { useId, useMemo, useState } from 'react';
6
+ import { DEFAULT_DEVICE_PREVIEW_ID, DEVICE_PREVIEWS, getDevicePreview } from '../constants/devicePreviews.js';
7
+ import { useThemeLanguage, useThemeTranslations } from '../hooks/useThemeTranslations.js';
8
+ import { resolveTypographyPreview } from '../components/typographyPreviewUtils.js';
9
+ import { borderRadiusPresets } from '../providers/Theme/themeConfig.js';
10
+ const DEVICE_ICONS = {
11
+ mobile: Smartphone,
12
+ tablet: Tablet,
13
+ desktop: Monitor
14
+ };
15
+ const SHADOW_MAP = {
16
+ none: 'none',
17
+ subtle: '0 1px 3px rgba(0,0,0,0.06), 0 1px 2px rgba(0,0,0,0.04)',
18
+ medium: '0 4px 6px -1px rgba(0,0,0,0.1), 0 2px 4px -2px rgba(0,0,0,0.1)',
19
+ strong: '0 10px 15px -3px rgba(0,0,0,0.1), 0 4px 6px -4px rgba(0,0,0,0.1)',
20
+ dramatic: '0 25px 50px -12px rgba(0,0,0,0.25)'
21
+ };
22
+ const BLUR_PX_MAP = {
23
+ none: '0px',
24
+ slight: '4px',
25
+ medium: '8px',
26
+ strong: '16px',
27
+ heavy: '24px'
28
+ };
29
+ const BUTTON_SIZE_MAP = {
30
+ small: {
31
+ padding: '6px 12px',
32
+ fontSize: '12px'
33
+ },
34
+ medium: {
35
+ padding: '8px 16px',
36
+ fontSize: '13px'
37
+ },
38
+ large: {
39
+ padding: '10px 24px',
40
+ fontSize: '15px'
41
+ },
42
+ xl: {
43
+ padding: '14px 32px',
44
+ fontSize: '17px'
45
+ }
46
+ };
47
+ function radiusToPx(token) {
48
+ const preset = borderRadiusPresets[token ?? 'medium'];
49
+ const css = preset?.css;
50
+ return css?.['--radius-large'] ?? css?.['--radius-default'] ?? '0.75rem';
51
+ }
52
+ function cardSurface(c, p, radius) {
53
+ const base = {
54
+ background: p.card,
55
+ color: p.cardForeground,
56
+ borderRadius: radius,
57
+ border: `${c.borderWidth} ${c.borderStyle === 'none' ? 'solid' : c.borderStyle} ${p.border}`,
58
+ padding: '16px',
59
+ transition: 'transform 200ms ease, box-shadow 200ms ease'
60
+ };
61
+ // Card style takes precedence for the structural look, effect style for depth.
62
+ if (c.cardStyle === 'bordered') {
63
+ return {
64
+ ...base,
65
+ border: `2px solid ${p.foreground}`,
66
+ borderRadius: 0,
67
+ boxShadow: `4px 4px 0 ${p.foreground}`
68
+ };
69
+ }
70
+ if (c.cardStyle === 'gradient-border') {
71
+ return {
72
+ ...base,
73
+ border: '2px solid transparent',
74
+ borderImage: `linear-gradient(135deg, ${p.gradientFrom}, ${p.gradientVia}, ${p.gradientTo}) 1`,
75
+ boxShadow: SHADOW_MAP[c.shadowIntensity] ?? SHADOW_MAP.medium
76
+ };
77
+ }
78
+ switch(c.effectStyle){
79
+ case 'glass':
80
+ return {
81
+ ...base,
82
+ background: `color-mix(in srgb, ${p.card} ${c.glassOpacity}%, transparent)`,
83
+ backdropFilter: `blur(${BLUR_PX_MAP[c.backdropBlur] ?? '8px'}) saturate(150%)`,
84
+ border: `1px solid color-mix(in srgb, ${p.border} 50%, transparent)`,
85
+ boxShadow: '0 4px 24px rgba(0,0,0,0.10), inset 0 1px 0 rgba(255,255,255,0.15)'
86
+ };
87
+ case 'neumorphic':
88
+ return {
89
+ ...base,
90
+ background: p.background,
91
+ border: 'none',
92
+ boxShadow: '6px 6px 12px rgba(0,0,0,0.12), -6px -6px 12px rgba(255,255,255,0.7)'
93
+ };
94
+ case 'clay':
95
+ return {
96
+ ...base,
97
+ border: 'none',
98
+ boxShadow: '4px 4px 0 rgba(0,0,0,0.22), 0 8px 20px rgba(0,0,0,0.08)'
99
+ };
100
+ case 'elevated':
101
+ return {
102
+ ...base,
103
+ border: 'none',
104
+ boxShadow: SHADOW_MAP[c.shadowIntensity] ?? SHADOW_MAP.medium
105
+ };
106
+ case 'flat':
107
+ default:
108
+ return {
109
+ ...base,
110
+ boxShadow: 'none'
111
+ };
112
+ }
113
+ }
114
+ function buttonStyle(c, p, radius) {
115
+ const size = BUTTON_SIZE_MAP[c.buttonSize] ?? BUTTON_SIZE_MAP.medium;
116
+ const base = {
117
+ ...size,
118
+ fontWeight: 600,
119
+ cursor: 'pointer',
120
+ borderRadius: radius,
121
+ border: 'none',
122
+ transition: 'transform 120ms ease, box-shadow 120ms ease',
123
+ whiteSpace: 'nowrap'
124
+ };
125
+ switch(c.buttonVariant){
126
+ case 'outlined':
127
+ return {
128
+ ...base,
129
+ background: 'transparent',
130
+ color: p.primary,
131
+ border: `1.5px solid ${p.primary}`
132
+ };
133
+ case 'ghost':
134
+ return {
135
+ ...base,
136
+ background: 'transparent',
137
+ color: p.primary
138
+ };
139
+ case 'gradient':
140
+ return {
141
+ ...base,
142
+ backgroundImage: `linear-gradient(135deg, ${p.gradientFrom}, ${p.gradientVia}, ${p.gradientTo})`,
143
+ color: p.primaryForeground
144
+ };
145
+ case 'pill':
146
+ return {
147
+ ...base,
148
+ background: p.primary,
149
+ color: p.primaryForeground,
150
+ borderRadius: '9999px'
151
+ };
152
+ case 'brutal':
153
+ return {
154
+ ...base,
155
+ background: p.card,
156
+ color: p.foreground,
157
+ border: `2px solid ${p.foreground}`,
158
+ borderRadius: 0,
159
+ boxShadow: `3px 3px 0 ${p.foreground}`
160
+ };
161
+ case 'filled':
162
+ default:
163
+ return {
164
+ ...base,
165
+ background: p.primary,
166
+ color: p.primaryForeground
167
+ };
168
+ }
169
+ }
170
+ function navbarStyle(c, p) {
171
+ const base = {
172
+ display: 'flex',
173
+ alignItems: 'center',
174
+ justifyContent: 'space-between',
175
+ padding: '10px 14px',
176
+ background: p.background,
177
+ color: p.foreground,
178
+ borderBottom: `1px solid ${p.border}`
179
+ };
180
+ switch(c.navbarStyle){
181
+ case 'transparent':
182
+ return {
183
+ ...base,
184
+ background: 'transparent',
185
+ borderBottom: '1px solid transparent'
186
+ };
187
+ case 'blur':
188
+ return {
189
+ ...base,
190
+ background: `color-mix(in srgb, ${p.background} 70%, transparent)`,
191
+ backdropFilter: 'blur(12px)'
192
+ };
193
+ case 'floating':
194
+ return {
195
+ ...base,
196
+ margin: '8px',
197
+ borderRadius: radiusToPx(c.borderRadius),
198
+ border: `1px solid ${p.border}`,
199
+ boxShadow: '0 4px 24px rgba(0,0,0,0.10)'
200
+ };
201
+ case 'minimal':
202
+ return {
203
+ ...base,
204
+ borderBottom: `1px solid ${p.border}`,
205
+ boxShadow: 'none'
206
+ };
207
+ case 'solid':
208
+ default:
209
+ return base;
210
+ }
211
+ }
212
+ function linkStyle(c, p) {
213
+ switch(c.linkStyle){
214
+ case 'underline':
215
+ return {
216
+ color: p.primary,
217
+ textDecoration: 'underline',
218
+ textUnderlineOffset: '0.15em'
219
+ };
220
+ case 'none':
221
+ return {
222
+ color: p.primary,
223
+ textDecoration: 'none'
224
+ };
225
+ case 'highlight':
226
+ return {
227
+ color: p.foreground,
228
+ textDecoration: 'none',
229
+ backgroundImage: `linear-gradient(transparent 60%, color-mix(in srgb, ${p.primary} 28%, transparent) 0)`
230
+ };
231
+ case 'animated':
232
+ return {
233
+ color: p.primary,
234
+ textDecoration: 'none',
235
+ borderBottom: `2px solid ${p.primary}`,
236
+ paddingBottom: '1px'
237
+ };
238
+ case 'underline-hover':
239
+ default:
240
+ return {
241
+ color: p.primary,
242
+ textDecoration: 'none'
243
+ };
244
+ }
245
+ }
246
+ export default function AppearancePreviewField() {
247
+ const formFields = useFormFields(([state])=>state);
248
+ const lang = useThemeLanguage();
249
+ const translations = useThemeTranslations();
250
+ const t = translations.appearancePreview;
251
+ const site = translations.preview;
252
+ const [mode, setMode] = useState('light');
253
+ const [device, setDevice] = useState(DEFAULT_DEVICE_PREVIEW_ID);
254
+ const uid = useId().replace(/[:]/g, '');
255
+ const activeDevice = getDevicePreview(device);
256
+ // Fonts follow the Typography section (or the theme preset when set to "Use theme preset"),
257
+ // so this single preview shows colours, type and component styles together.
258
+ const typographyValue = (key)=>formFields?.[`themeConfiguration.typography.${key}`]?.value;
259
+ const typography = resolveTypographyPreview({
260
+ bodyFont: typographyValue('bodyFont'),
261
+ headingFont: typographyValue('headingFont'),
262
+ bodyFontCustom: typographyValue('bodyFontCustom'),
263
+ headingFontCustom: typographyValue('headingFontCustom'),
264
+ baseFontSize: typographyValue('baseFontSize'),
265
+ lineHeight: typographyValue('lineHeight')
266
+ }, formFields?.['themeConfiguration.theme']?.value);
267
+ const str = (key, fallback)=>{
268
+ const v = formFields?.[`themeConfiguration.${key}`]?.value;
269
+ return typeof v === 'string' && v.trim().length > 0 ? v : fallback;
270
+ };
271
+ const num = (key, fallback)=>{
272
+ const v = formFields?.[`themeConfiguration.${key}`]?.value;
273
+ return typeof v === 'number' ? v : fallback;
274
+ };
275
+ const choices = {
276
+ effectStyle: str('visualEffects.effectStyle', 'flat'),
277
+ shadowIntensity: str('visualEffects.shadowIntensity', 'medium'),
278
+ backdropBlur: str('visualEffects.backdropBlur', 'none'),
279
+ borderStyle: str('visualEffects.borderStyle', 'solid'),
280
+ borderWidth: str('visualEffects.borderWidth', '1px'),
281
+ glassOpacity: num('visualEffects.glassOpacity', 60),
282
+ buttonVariant: str('componentStyles.buttonVariant', 'filled'),
283
+ buttonSize: str('componentStyles.buttonSize', 'medium'),
284
+ cardStyle: str('componentStyles.cardStyle', 'elevated'),
285
+ cardHoverEffect: str('componentStyles.cardHoverEffect', 'lift'),
286
+ imageStyle: str('componentStyles.imageStyle', 'default'),
287
+ navbarStyle: str('componentStyles.navbarStyle', 'solid'),
288
+ footerStyle: str('componentStyles.footerStyle', 'standard'),
289
+ linkStyle: str('componentStyles.linkStyle', 'underline-hover'),
290
+ borderRadius: str('borderRadius', 'medium')
291
+ };
292
+ const modeKey = mode === 'light' ? 'lightMode' : 'darkMode';
293
+ const fallback = mode === 'light' ? {
294
+ background: '#ffffff',
295
+ foreground: '#0a0a0a',
296
+ card: '#ffffff',
297
+ cardForeground: '#0a0a0a',
298
+ primary: '#9372f7',
299
+ primaryForeground: '#fafafa',
300
+ secondary: '#f4f4f5',
301
+ secondaryForeground: '#18181b',
302
+ muted: '#f4f4f5',
303
+ mutedForeground: '#71717a',
304
+ accent: '#f4f4f5',
305
+ accentForeground: '#18181b',
306
+ border: '#e4e4e7',
307
+ gradientFrom: '#9372f7',
308
+ gradientVia: '#7c6ff0',
309
+ gradientTo: '#22d3ee'
310
+ } : {
311
+ background: '#0a0a0a',
312
+ foreground: '#fafafa',
313
+ card: '#09090b',
314
+ cardForeground: '#fafafa',
315
+ primary: '#9372f7',
316
+ primaryForeground: '#09090b',
317
+ secondary: '#27272a',
318
+ secondaryForeground: '#fafafa',
319
+ muted: '#27272a',
320
+ mutedForeground: '#a1a1aa',
321
+ accent: '#27272a',
322
+ accentForeground: '#fafafa',
323
+ border: '#27272a',
324
+ gradientFrom: '#9372f7',
325
+ gradientVia: '#7c6ff0',
326
+ gradientTo: '#22d3ee'
327
+ };
328
+ const palette = useMemo(()=>{
329
+ const p = {
330
+ ...fallback
331
+ };
332
+ Object.keys(fallback).forEach((key)=>{
333
+ p[key] = str(`${modeKey}.${key}`, fallback[key]);
334
+ });
335
+ return p;
336
+ }, [
337
+ formFields,
338
+ mode
339
+ ]);
340
+ const radius = radiusToPx(choices.borderRadius);
341
+ const card = cardSurface(choices, palette, radius);
342
+ const btn = buttonStyle(choices, palette, radius);
343
+ const nav = navbarStyle(choices, palette);
344
+ // Hover effects can't be expressed inline, so emit a scoped style block.
345
+ const hoverCSS = (()=>{
346
+ const sel = `.${uid} .tm-prev-card`;
347
+ switch(choices.cardHoverEffect){
348
+ case 'lift':
349
+ return `${sel}:hover{transform:translateY(-6px);box-shadow:0 20px 40px rgba(0,0,0,0.14)}`;
350
+ case 'scale':
351
+ return `${sel}:hover{transform:scale(1.02)}`;
352
+ case 'glow':
353
+ 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)}`;
354
+ case 'shadow':
355
+ return `${sel}:hover{box-shadow:0 24px 50px -12px rgba(0,0,0,0.35)}`;
356
+ case 'tilt':
357
+ return `${sel}:hover{transform:perspective(800px) rotateX(3deg) rotateY(-3deg)}`;
358
+ default:
359
+ return '';
360
+ }
361
+ })();
362
+ const btnHoverCSS = `.${uid} .tm-prev-btn:hover{filter:brightness(1.05)}${choices.buttonVariant === 'brutal' ? `.${uid} .tm-prev-btn:hover{transform:translate(-2px,-2px);box-shadow:5px 5px 0 ${palette.foreground}}` : ''}`;
363
+ // Movement-based hover effects only run for users who haven't asked for reduced motion.
364
+ const previewCSS = `@media (prefers-reduced-motion: no-preference){${hoverCSS}${btnHoverCSS}}`;
365
+ const chipLabels = t.chips;
366
+ const chips = [
367
+ [
368
+ chipLabels.effect,
369
+ choices.effectStyle
370
+ ],
371
+ [
372
+ chipLabels.shadow,
373
+ choices.shadowIntensity
374
+ ],
375
+ [
376
+ chipLabels.card,
377
+ choices.cardStyle
378
+ ],
379
+ [
380
+ chipLabels.hover,
381
+ choices.cardHoverEffect
382
+ ],
383
+ [
384
+ chipLabels.button,
385
+ `${choices.buttonVariant} / ${choices.buttonSize}`
386
+ ],
387
+ [
388
+ chipLabels.navbar,
389
+ choices.navbarStyle
390
+ ],
391
+ [
392
+ chipLabels.footer,
393
+ choices.footerStyle
394
+ ],
395
+ [
396
+ chipLabels.link,
397
+ choices.linkStyle
398
+ ],
399
+ [
400
+ chipLabels.radius,
401
+ choices.borderRadius
402
+ ]
403
+ ];
404
+ const footerStyleCss = choices.footerStyle === 'dark' ? {
405
+ background: palette.foreground,
406
+ color: palette.background
407
+ } : choices.footerStyle === 'full-color' ? {
408
+ background: palette.primary,
409
+ color: palette.primaryForeground
410
+ } : choices.footerStyle === 'gradient-top' ? {
411
+ background: palette.background,
412
+ color: palette.mutedForeground,
413
+ borderTop: '3px solid transparent',
414
+ borderImage: `linear-gradient(135deg, ${palette.gradientFrom}, ${palette.gradientVia}, ${palette.gradientTo}) 1`
415
+ } : choices.footerStyle === 'minimal' ? {
416
+ background: 'transparent',
417
+ color: palette.mutedForeground,
418
+ borderTop: `1px solid ${palette.border}`
419
+ } : {
420
+ background: palette.muted,
421
+ color: palette.mutedForeground,
422
+ borderTop: `1px solid ${palette.border}`
423
+ };
424
+ return(// The slot spans the whole right column of the Appearance tab on wide admins;
425
+ // its inner panel is sticky so the preview stays in view while editing.
426
+ /*#__PURE__*/ _jsx("div", {
427
+ className: `tm-live-preview-slot ${uid}`,
428
+ children: /*#__PURE__*/ _jsxs("div", {
429
+ className: "tm-live-preview",
430
+ children: [
431
+ /*#__PURE__*/ _jsx("style", {
432
+ dangerouslySetInnerHTML: {
433
+ __html: previewCSS
434
+ }
435
+ }),
436
+ /*#__PURE__*/ _jsxs("div", {
437
+ style: {
438
+ display: 'flex',
439
+ alignItems: 'center',
440
+ justifyContent: 'space-between',
441
+ marginBottom: '8px',
442
+ gap: '8px',
443
+ flexWrap: 'wrap'
444
+ },
445
+ children: [
446
+ /*#__PURE__*/ _jsxs("div", {
447
+ children: [
448
+ /*#__PURE__*/ _jsxs("div", {
449
+ style: {
450
+ display: 'inline-flex',
451
+ alignItems: 'center',
452
+ gap: '6px',
453
+ fontSize: '13px',
454
+ fontWeight: 600,
455
+ color: 'var(--theme-elevation-800)'
456
+ },
457
+ children: [
458
+ /*#__PURE__*/ _jsx(Sparkles, {
459
+ size: 14,
460
+ "aria-hidden": true
461
+ }),
462
+ t.title
463
+ ]
464
+ }),
465
+ /*#__PURE__*/ _jsx("div", {
466
+ style: {
467
+ fontSize: '12px',
468
+ color: 'var(--theme-elevation-600)'
469
+ },
470
+ children: t.subtitle
471
+ })
472
+ ]
473
+ }),
474
+ /*#__PURE__*/ _jsxs("div", {
475
+ style: {
476
+ display: 'inline-flex',
477
+ gap: '8px',
478
+ flexWrap: 'wrap'
479
+ },
480
+ children: [
481
+ /*#__PURE__*/ _jsx("div", {
482
+ role: "group",
483
+ "aria-label": t.viewport,
484
+ style: {
485
+ display: 'inline-flex',
486
+ borderRadius: '8px',
487
+ overflow: 'hidden',
488
+ border: '1px solid var(--theme-elevation-200)'
489
+ },
490
+ children: DEVICE_PREVIEWS.map((d)=>{
491
+ const Icon = DEVICE_ICONS[d.id];
492
+ return /*#__PURE__*/ _jsxs("button", {
493
+ type: "button",
494
+ "aria-pressed": device === d.id,
495
+ onClick: ()=>setDevice(d.id),
496
+ title: `${lang === 'cs' ? d.labelCs : d.label} — ${d.width}×${d.height}`,
497
+ style: {
498
+ display: 'inline-flex',
499
+ alignItems: 'center',
500
+ gap: '5px',
501
+ minHeight: '28px',
502
+ padding: '5px 10px',
503
+ fontSize: '12px',
504
+ fontWeight: 600,
505
+ cursor: 'pointer',
506
+ border: 'none',
507
+ background: device === d.id ? 'var(--theme-elevation-800)' : 'transparent',
508
+ color: device === d.id ? 'var(--theme-elevation-0)' : 'var(--theme-elevation-600)'
509
+ },
510
+ children: [
511
+ /*#__PURE__*/ _jsx(Icon, {
512
+ size: 13,
513
+ "aria-hidden": true
514
+ }),
515
+ lang === 'cs' ? d.labelCs : d.label
516
+ ]
517
+ }, d.id);
518
+ })
519
+ }),
520
+ /*#__PURE__*/ _jsx("div", {
521
+ role: "group",
522
+ "aria-label": `${t.light} / ${t.dark}`,
523
+ style: {
524
+ display: 'inline-flex',
525
+ borderRadius: '8px',
526
+ overflow: 'hidden',
527
+ border: '1px solid var(--theme-elevation-200)'
528
+ },
529
+ children: [
530
+ 'light',
531
+ 'dark'
532
+ ].map((m)=>{
533
+ const Icon = m === 'light' ? Sun : Moon;
534
+ return /*#__PURE__*/ _jsxs("button", {
535
+ type: "button",
536
+ "aria-pressed": mode === m,
537
+ onClick: ()=>setMode(m),
538
+ style: {
539
+ display: 'inline-flex',
540
+ alignItems: 'center',
541
+ gap: '5px',
542
+ minHeight: '28px',
543
+ padding: '5px 12px',
544
+ fontSize: '12px',
545
+ fontWeight: 600,
546
+ cursor: 'pointer',
547
+ border: 'none',
548
+ background: mode === m ? 'var(--theme-elevation-800)' : 'transparent',
549
+ color: mode === m ? 'var(--theme-elevation-0)' : 'var(--theme-elevation-600)'
550
+ },
551
+ children: [
552
+ /*#__PURE__*/ _jsx(Icon, {
553
+ size: 13,
554
+ "aria-hidden": true
555
+ }),
556
+ m === 'light' ? t.light : t.dark
557
+ ]
558
+ }, m);
559
+ })
560
+ })
561
+ ]
562
+ })
563
+ ]
564
+ }),
565
+ /*#__PURE__*/ _jsx("div", {
566
+ style: {
567
+ display: 'flex',
568
+ justifyContent: 'center',
569
+ background: 'var(--theme-elevation-50)',
570
+ borderRadius: '14px',
571
+ padding: device === 'desktop' ? '0' : '16px'
572
+ },
573
+ children: /*#__PURE__*/ _jsxs("div", {
574
+ ref: (el)=>el?.setAttribute('inert', ''),
575
+ style: {
576
+ width: '100%',
577
+ maxWidth: device === 'desktop' ? '100%' : `${activeDevice.width}px`,
578
+ borderRadius: '14px',
579
+ overflow: 'hidden',
580
+ border: '1px solid var(--theme-elevation-200)',
581
+ boxShadow: '0 8px 24px rgba(0,0,0,0.10)',
582
+ background: palette.background,
583
+ color: palette.foreground,
584
+ fontFamily: typography.bodyFont,
585
+ lineHeight: typography.lineHeight
586
+ },
587
+ children: [
588
+ /*#__PURE__*/ _jsxs("nav", {
589
+ style: nav,
590
+ children: [
591
+ /*#__PURE__*/ _jsx("span", {
592
+ style: {
593
+ fontWeight: 700,
594
+ fontSize: '13px'
595
+ },
596
+ children: site.siteTitle
597
+ }),
598
+ /*#__PURE__*/ _jsxs("span", {
599
+ style: {
600
+ display: 'flex',
601
+ gap: '14px',
602
+ fontSize: '12px',
603
+ opacity: 0.85
604
+ },
605
+ children: [
606
+ /*#__PURE__*/ _jsx("span", {
607
+ children: site.nav.home
608
+ }),
609
+ /*#__PURE__*/ _jsx("span", {
610
+ children: site.nav.about
611
+ }),
612
+ /*#__PURE__*/ _jsx("span", {
613
+ style: {
614
+ ...linkStyle(choices, palette)
615
+ },
616
+ children: site.nav.services
617
+ })
618
+ ]
619
+ })
620
+ ]
621
+ }),
622
+ /*#__PURE__*/ _jsxs("div", {
623
+ style: {
624
+ padding: '20px',
625
+ display: 'grid',
626
+ gap: '14px'
627
+ },
628
+ children: [
629
+ /*#__PURE__*/ _jsxs("div", {
630
+ children: [
631
+ /*#__PURE__*/ _jsx("div", {
632
+ style: {
633
+ fontFamily: typography.headingFont,
634
+ fontSize: '22px',
635
+ fontWeight: 700,
636
+ lineHeight: 1.2
637
+ },
638
+ children: t.heading
639
+ }),
640
+ /*#__PURE__*/ _jsxs("p", {
641
+ style: {
642
+ margin: '6px 0 0',
643
+ fontSize: `calc(${typography.baseFontSize} * 0.8125)`,
644
+ lineHeight: typography.lineHeight,
645
+ color: palette.mutedForeground
646
+ },
647
+ children: [
648
+ t.body,
649
+ /*#__PURE__*/ _jsx("a", {
650
+ style: linkStyle(choices, palette),
651
+ children: t.link
652
+ }),
653
+ "."
654
+ ]
655
+ })
656
+ ]
657
+ }),
658
+ /*#__PURE__*/ _jsx("div", {
659
+ className: "tm-prev-card",
660
+ style: card,
661
+ children: /*#__PURE__*/ _jsxs("div", {
662
+ style: {
663
+ display: 'flex',
664
+ gap: '10px',
665
+ alignItems: 'center',
666
+ flexWrap: 'wrap'
667
+ },
668
+ children: [
669
+ /*#__PURE__*/ _jsx("button", {
670
+ type: "button",
671
+ className: "tm-prev-btn",
672
+ style: btn,
673
+ children: t.primary
674
+ }),
675
+ /*#__PURE__*/ _jsx("button", {
676
+ type: "button",
677
+ style: {
678
+ ...BUTTON_SIZE_MAP[choices.buttonSize] ?? BUTTON_SIZE_MAP.medium,
679
+ fontWeight: 600,
680
+ cursor: 'pointer',
681
+ borderRadius: radius,
682
+ background: palette.secondary,
683
+ color: palette.secondaryForeground,
684
+ border: 'none'
685
+ },
686
+ children: t.secondary
687
+ }),
688
+ /*#__PURE__*/ _jsx("span", {
689
+ "aria-hidden": true,
690
+ style: {
691
+ marginLeft: 'auto',
692
+ width: '54px',
693
+ height: '22px',
694
+ borderRadius: '6px',
695
+ backgroundImage: `linear-gradient(135deg, ${palette.gradientFrom}, ${palette.gradientVia}, ${palette.gradientTo})`,
696
+ boxShadow: 'inset 0 0 0 1px rgba(0,0,0,0.08)'
697
+ }
698
+ })
699
+ ]
700
+ })
701
+ })
702
+ ]
703
+ }),
704
+ /*#__PURE__*/ _jsxs("div", {
705
+ style: {
706
+ padding: '12px 16px',
707
+ fontSize: '11px',
708
+ ...footerStyleCss
709
+ },
710
+ children: [
711
+ "© ",
712
+ new Date().getFullYear(),
713
+ " ",
714
+ site.siteTitle,
715
+ " — ",
716
+ t.footer
717
+ ]
718
+ })
719
+ ]
720
+ })
721
+ }),
722
+ /*#__PURE__*/ _jsx("div", {
723
+ style: {
724
+ display: 'flex',
725
+ flexWrap: 'wrap',
726
+ gap: '5px',
727
+ marginTop: '10px'
728
+ },
729
+ children: chips.map(([k, v])=>/*#__PURE__*/ _jsxs("span", {
730
+ style: {
731
+ fontSize: '11px',
732
+ padding: '2px 7px',
733
+ borderRadius: '999px',
734
+ background: 'var(--theme-elevation-50)',
735
+ border: '1px solid var(--theme-elevation-150)',
736
+ color: 'var(--theme-elevation-700)'
737
+ },
738
+ children: [
739
+ /*#__PURE__*/ _jsxs("span", {
740
+ style: {
741
+ color: 'var(--theme-elevation-600)'
742
+ },
743
+ children: [
744
+ k,
745
+ ":"
746
+ ]
747
+ }),
748
+ " ",
749
+ /*#__PURE__*/ _jsx("strong", {
750
+ style: {
751
+ fontWeight: 600
752
+ },
753
+ children: v
754
+ })
755
+ ]
756
+ }, k))
757
+ })
758
+ ]
759
+ })
760
+ }));
761
+ }
762
+
763
+ //# sourceMappingURL=AppearancePreviewField.js.map