@kilivi/payloadcms-theme-management 2.0.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 (235) hide show
  1. package/README.md +346 -845
  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 +13 -1
  12. package/dist/components/ServerThemeInjector.d.ts.map +1 -1
  13. package/dist/components/ServerThemeInjector.js +65 -15
  14. package/dist/components/ServerThemeInjector.js.map +1 -1
  15. package/dist/components/ThemeLivePreviewSync.d.ts +4 -0
  16. package/dist/components/ThemeLivePreviewSync.d.ts.map +1 -1
  17. package/dist/components/ThemeLivePreviewSync.js +28 -4
  18. package/dist/components/ThemeLivePreviewSync.js.map +1 -1
  19. package/dist/components/ThemeSwitcher.d.ts +36 -0
  20. package/dist/components/ThemeSwitcher.d.ts.map +1 -0
  21. package/dist/components/ThemeSwitcher.js +89 -0
  22. package/dist/components/ThemeSwitcher.js.map +1 -0
  23. package/dist/components/typographyPreviewUtils.d.ts +5 -0
  24. package/dist/components/typographyPreviewUtils.d.ts.map +1 -1
  25. package/dist/components/typographyPreviewUtils.js +24 -11
  26. package/dist/components/typographyPreviewUtils.js.map +1 -1
  27. package/dist/constants/devicePreviews.d.ts +35 -0
  28. package/dist/constants/devicePreviews.d.ts.map +1 -0
  29. package/dist/constants/devicePreviews.js +43 -0
  30. package/dist/constants/devicePreviews.js.map +1 -0
  31. package/dist/constants/themeFonts.d.ts +94 -168
  32. package/dist/constants/themeFonts.d.ts.map +1 -1
  33. package/dist/constants/themeFonts.js +260 -140
  34. package/dist/constants/themeFonts.js.map +1 -1
  35. package/dist/endpoints/themeFonts.d.ts +5 -0
  36. package/dist/endpoints/themeFonts.d.ts.map +1 -0
  37. package/dist/endpoints/themeFonts.js +138 -0
  38. package/dist/endpoints/themeFonts.js.map +1 -0
  39. package/dist/extended-presets.d.ts +0 -4
  40. package/dist/extended-presets.d.ts.map +1 -1
  41. package/dist/extended-presets.js +1 -18
  42. package/dist/extended-presets.js.map +1 -1
  43. package/dist/extended-themes.d.ts.map +1 -1
  44. package/dist/extended-themes.js +428 -0
  45. package/dist/extended-themes.js.map +1 -1
  46. package/dist/fields/AccessibilityAuditField.d.ts +2 -0
  47. package/dist/fields/AccessibilityAuditField.d.ts.map +1 -0
  48. package/dist/fields/AccessibilityAuditField.js +303 -0
  49. package/dist/fields/AccessibilityAuditField.js.map +1 -0
  50. package/dist/fields/AppearancePreviewField.d.ts +2 -0
  51. package/dist/fields/AppearancePreviewField.d.ts.map +1 -0
  52. package/dist/fields/AppearancePreviewField.js +826 -0
  53. package/dist/fields/AppearancePreviewField.js.map +1 -0
  54. package/dist/fields/ColorPickerField.d.ts.map +1 -1
  55. package/dist/fields/ColorPickerField.js +89 -85
  56. package/dist/fields/ColorPickerField.js.map +1 -1
  57. package/dist/fields/FontSelectField.css +155 -0
  58. package/dist/fields/FontSelectField.d.ts +8 -0
  59. package/dist/fields/FontSelectField.d.ts.map +1 -1
  60. package/dist/fields/FontSelectField.js +223 -188
  61. package/dist/fields/FontSelectField.js.map +1 -1
  62. package/dist/fields/PaletteGeneratorField.d.ts +7 -0
  63. package/dist/fields/PaletteGeneratorField.d.ts.map +1 -0
  64. package/dist/fields/PaletteGeneratorField.js +327 -0
  65. package/dist/fields/PaletteGeneratorField.js.map +1 -0
  66. package/dist/fields/StylePresetField.d.ts +3 -0
  67. package/dist/fields/StylePresetField.d.ts.map +1 -0
  68. package/dist/fields/StylePresetField.js +463 -0
  69. package/dist/fields/StylePresetField.js.map +1 -0
  70. package/dist/fields/ThemeColorPickerField.css +115 -35
  71. package/dist/fields/ThemeColorPickerField.d.ts.map +1 -1
  72. package/dist/fields/ThemeColorPickerField.js +204 -70
  73. package/dist/fields/ThemeColorPickerField.js.map +1 -1
  74. package/dist/fields/ThemeExportField.d.ts +6 -0
  75. package/dist/fields/ThemeExportField.d.ts.map +1 -0
  76. package/dist/fields/ThemeExportField.js +202 -0
  77. package/dist/fields/ThemeExportField.js.map +1 -0
  78. package/dist/fields/ThemePresetImportField.d.ts.map +1 -1
  79. package/dist/fields/ThemePresetImportField.js +56 -25
  80. package/dist/fields/ThemePresetImportField.js.map +1 -1
  81. package/dist/fields/ThemePreviewField.css +444 -5
  82. package/dist/fields/ThemePreviewField.d.ts.map +1 -1
  83. package/dist/fields/ThemePreviewField.js +265 -170
  84. package/dist/fields/ThemePreviewField.js.map +1 -1
  85. package/dist/fields/ThemeTokenSelectField.d.ts.map +1 -1
  86. package/dist/fields/ThemeTokenSelectField.js +278 -80
  87. package/dist/fields/ThemeTokenSelectField.js.map +1 -1
  88. package/dist/fields/colorFieldHelpers.d.ts +90 -0
  89. package/dist/fields/colorFieldHelpers.d.ts.map +1 -0
  90. package/dist/fields/colorFieldHelpers.js +133 -0
  91. package/dist/fields/colorFieldHelpers.js.map +1 -0
  92. package/dist/fields/colorModeFields.d.ts +1 -1
  93. package/dist/fields/colorModeFields.d.ts.map +1 -1
  94. package/dist/fields/colorModeFields.js +49 -7
  95. package/dist/fields/colorModeFields.js.map +1 -1
  96. package/dist/fields/themeConfigurationField.d.ts +8 -1
  97. package/dist/fields/themeConfigurationField.d.ts.map +1 -1
  98. package/dist/fields/themeConfigurationField.js +1209 -228
  99. package/dist/fields/themeConfigurationField.js.map +1 -1
  100. package/dist/globals/ThemeSettings/FontPicker/FontPreview.d.ts.map +1 -1
  101. package/dist/globals/ThemeSettings/FontPicker/FontPreview.js +8 -4
  102. package/dist/globals/ThemeSettings/FontPicker/FontPreview.js.map +1 -1
  103. package/dist/globals/ThemeSettings/FontPicker/index.d.ts.map +1 -1
  104. package/dist/globals/ThemeSettings/FontPicker/index.js +81 -26
  105. package/dist/globals/ThemeSettings/FontPicker/index.js.map +1 -1
  106. package/dist/globals/ThemeSettings/FontPicker/styles.css +98 -41
  107. package/dist/globals/ThemeSettings/FontPicker/translations.d.ts +6 -0
  108. package/dist/globals/ThemeSettings/FontPicker/translations.d.ts.map +1 -1
  109. package/dist/globals/ThemeSettings/FontPicker/translations.js +14 -2
  110. package/dist/globals/ThemeSettings/FontPicker/translations.js.map +1 -1
  111. package/dist/globals/ThemeSettings/config.d.ts.map +1 -1
  112. package/dist/globals/ThemeSettings/config.js +76 -79
  113. package/dist/globals/ThemeSettings/config.js.map +1 -1
  114. package/dist/globals/ThemeSettings/fields/FontLoadingGuideField.d.ts.map +1 -1
  115. package/dist/globals/ThemeSettings/fields/FontLoadingGuideField.js +63 -62
  116. package/dist/globals/ThemeSettings/fields/FontLoadingGuideField.js.map +1 -1
  117. package/dist/globals/ThemeSettings/fields/TypographyInfoField.d.ts.map +1 -1
  118. package/dist/globals/ThemeSettings/fields/TypographyInfoField.js +22 -25
  119. package/dist/globals/ThemeSettings/fields/TypographyInfoField.js.map +1 -1
  120. package/dist/hooks/useAppearanceSession.d.ts +50 -0
  121. package/dist/hooks/useAppearanceSession.d.ts.map +1 -0
  122. package/dist/hooks/useAppearanceSession.js +91 -0
  123. package/dist/hooks/useAppearanceSession.js.map +1 -0
  124. package/dist/hooks/useNativeLivePreview.d.ts +15 -0
  125. package/dist/hooks/useNativeLivePreview.d.ts.map +1 -0
  126. package/dist/hooks/useNativeLivePreview.js +18 -0
  127. package/dist/hooks/useNativeLivePreview.js.map +1 -0
  128. package/dist/hooks/useThemeFonts.d.ts +10 -0
  129. package/dist/hooks/useThemeFonts.d.ts.map +1 -0
  130. package/dist/hooks/useThemeFonts.js +36 -0
  131. package/dist/hooks/useThemeFonts.js.map +1 -0
  132. package/dist/hooks/useThemeTranslations.d.ts +13 -0
  133. package/dist/hooks/useThemeTranslations.d.ts.map +1 -0
  134. package/dist/hooks/useThemeTranslations.js +22 -0
  135. package/dist/hooks/useThemeTranslations.js.map +1 -0
  136. package/dist/i18n.d.ts +53 -0
  137. package/dist/i18n.d.ts.map +1 -0
  138. package/dist/i18n.js +53 -0
  139. package/dist/i18n.js.map +1 -0
  140. package/dist/index.d.ts +13 -4
  141. package/dist/index.d.ts.map +1 -1
  142. package/dist/index.js +59 -29
  143. package/dist/index.js.map +1 -1
  144. package/dist/next-fonts.d.ts +3 -0
  145. package/dist/next-fonts.d.ts.map +1 -0
  146. package/dist/next-fonts.js +360 -0
  147. package/dist/next-fonts.js.map +1 -0
  148. package/dist/payload-types.d.ts +34 -6
  149. package/dist/payload-types.d.ts.map +1 -1
  150. package/dist/payload-types.js.map +1 -1
  151. package/dist/presets.d.ts +14 -0
  152. package/dist/presets.d.ts.map +1 -1
  153. package/dist/presets.js.map +1 -1
  154. package/dist/providers/Theme/index.d.ts.map +1 -1
  155. package/dist/providers/Theme/index.js +75 -11
  156. package/dist/providers/Theme/index.js.map +1 -1
  157. package/dist/providers/Theme/themeConfig.d.ts.map +1 -1
  158. package/dist/providers/Theme/themeConfig.js +104 -0
  159. package/dist/providers/Theme/themeConfig.js.map +1 -1
  160. package/dist/providers/Theme/types.d.ts +1 -1
  161. package/dist/providers/Theme/types.d.ts.map +1 -1
  162. package/dist/providers/Theme/types.js +10 -1
  163. package/dist/providers/Theme/types.js.map +1 -1
  164. package/dist/style-presets.d.ts +75 -0
  165. package/dist/style-presets.d.ts.map +1 -0
  166. package/dist/style-presets.js +738 -0
  167. package/dist/style-presets.js.map +1 -0
  168. package/dist/translations.d.ts +164 -1
  169. package/dist/translations.d.ts.map +1 -1
  170. package/dist/translations.js +320 -9
  171. package/dist/translations.js.map +1 -1
  172. package/dist/tweakcn-special-themes.d.ts.map +1 -1
  173. package/dist/tweakcn-special-themes.js +585 -9
  174. package/dist/tweakcn-special-themes.js.map +1 -1
  175. package/dist/types/css.d.js +3 -0
  176. package/dist/types/css.d.js.map +1 -0
  177. package/dist/types.d.ts +26 -0
  178. package/dist/types.d.ts.map +1 -1
  179. package/dist/types.js +1 -1
  180. package/dist/types.js.map +1 -1
  181. package/dist/utilities/getThemeSettings.d.ts.map +1 -1
  182. package/dist/utilities/getThemeSettings.js +2 -14
  183. package/dist/utilities/getThemeSettings.js.map +1 -1
  184. package/dist/utils/contrast.d.ts +63 -0
  185. package/dist/utils/contrast.d.ts.map +1 -0
  186. package/dist/utils/contrast.js +158 -0
  187. package/dist/utils/contrast.js.map +1 -0
  188. package/dist/utils/exportTokens.d.ts +30 -0
  189. package/dist/utils/exportTokens.d.ts.map +1 -0
  190. package/dist/utils/exportTokens.js +183 -0
  191. package/dist/utils/exportTokens.js.map +1 -0
  192. package/dist/utils/generatePalette.d.ts +46 -0
  193. package/dist/utils/generatePalette.d.ts.map +1 -0
  194. package/dist/utils/generatePalette.js +127 -0
  195. package/dist/utils/generatePalette.js.map +1 -0
  196. package/dist/utils/generateThemeCSS.d.ts.map +1 -1
  197. package/dist/utils/generateThemeCSS.js +2 -40
  198. package/dist/utils/generateThemeCSS.js.map +1 -1
  199. package/dist/utils/livePreviewThemeRuntime.d.ts +22 -3
  200. package/dist/utils/livePreviewThemeRuntime.d.ts.map +1 -1
  201. package/dist/utils/livePreviewThemeRuntime.js +48 -15
  202. package/dist/utils/livePreviewThemeRuntime.js.map +1 -1
  203. package/dist/utils/localizedText.d.ts +8 -0
  204. package/dist/utils/localizedText.d.ts.map +1 -0
  205. package/dist/utils/localizedText.js +21 -0
  206. package/dist/utils/localizedText.js.map +1 -0
  207. package/dist/utils/resolveThemeConfiguration.d.ts +60 -1
  208. package/dist/utils/resolveThemeConfiguration.d.ts.map +1 -1
  209. package/dist/utils/resolveThemeConfiguration.js +53 -13
  210. package/dist/utils/resolveThemeConfiguration.js.map +1 -1
  211. package/dist/utils/themeColors.d.ts +3 -0
  212. package/dist/utils/themeColors.d.ts.map +1 -1
  213. package/dist/utils/themeColors.js +30 -1
  214. package/dist/utils/themeColors.js.map +1 -1
  215. package/dist/utils/themeHtmlAttributes.d.ts +32 -12
  216. package/dist/utils/themeHtmlAttributes.d.ts.map +1 -1
  217. package/dist/utils/themeHtmlAttributes.js +38 -5
  218. package/dist/utils/themeHtmlAttributes.js.map +1 -1
  219. package/dist/utils/themeUtils.d.ts +3 -5
  220. package/dist/utils/themeUtils.d.ts.map +1 -1
  221. package/dist/utils/themeUtils.js +474 -6
  222. package/dist/utils/themeUtils.js.map +1 -1
  223. package/dist/utils/tweakcnConverter.d.ts +1 -3
  224. package/dist/utils/tweakcnConverter.d.ts.map +1 -1
  225. package/dist/utils/tweakcnConverter.js +1 -3
  226. package/dist/utils/tweakcnConverter.js.map +1 -1
  227. package/package.json +15 -5
  228. package/dist/components/ThemePreview.d.ts +0 -3
  229. package/dist/components/ThemePreview.d.ts.map +0 -1
  230. package/dist/components/ThemePreview.js +0 -321
  231. package/dist/components/ThemePreview.js.map +0 -1
  232. package/dist/plugin.d.ts +0 -2
  233. package/dist/plugin.d.ts.map +0 -1
  234. package/dist/plugin.js +0 -3
  235. package/dist/plugin.js.map +0 -1
@@ -1,4 +1,5 @@
1
1
  import { borderRadiusPresets } from '../providers/Theme/themeConfig.js';
2
+ import { hexToHsl } from './themeColors.js';
2
3
  /**
3
4
  * Generates complete CSS for a theme preset
4
5
  * Creates both light and dark mode CSS variables
@@ -31,45 +32,6 @@ import { borderRadiusPresets } from '../providers/Theme/themeConfig.js';
31
32
  sections.push(buildCssBlock(`[data-theme='${name}'][data-theme-mode='dark']`, darkLines));
32
33
  return sections.join('\n').trim();
33
34
  }
34
- /**
35
- * Convert HEX color to HSL format
36
- * Example: #3b82f6 -> hsl(221, 83%, 53%)
37
- */ function hexToHsl(hex) {
38
- let normalized = hex.trim();
39
- if (!normalized.startsWith('#')) {
40
- normalized = `#${normalized}`;
41
- }
42
- if (normalized.length === 4) {
43
- normalized = `#${normalized[1]}${normalized[1]}${normalized[2]}${normalized[2]}${normalized[3]}${normalized[3]}`;
44
- }
45
- const r = parseInt(normalized.substring(1, 3), 16) / 255;
46
- const g = parseInt(normalized.substring(3, 5), 16) / 255;
47
- const b = parseInt(normalized.substring(5, 7), 16) / 255;
48
- const max = Math.max(r, g, b);
49
- const min = Math.min(r, g, b);
50
- let h = 0;
51
- let s = 0;
52
- const l = (max + min) / 2;
53
- if (max !== min) {
54
- const d = max - min;
55
- s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
56
- switch(max){
57
- case r:
58
- h = ((g - b) / d + (g < b ? 6 : 0)) / 6;
59
- break;
60
- case g:
61
- h = ((b - r) / d + 2) / 6;
62
- break;
63
- case b:
64
- h = ((r - g) / d + 4) / 6;
65
- break;
66
- }
67
- }
68
- const hDeg = Math.round(h * 360);
69
- const sPercent = Math.round(s * 100);
70
- const lPercent = Math.round(l * 100);
71
- return `hsl(${hDeg}, ${sPercent}%, ${lPercent}%)`;
72
- }
73
35
  function toCssColor(color) {
74
36
  if (!color) return null;
75
37
  const trimmed = color.trim();
@@ -280,7 +242,7 @@ function toKebab(token) {
280
242
  }
281
243
  function getDefaultTypography() {
282
244
  return {
283
- fontFamily: 'var(--font-geist-sans)',
245
+ fontFamily: 'var(--font-inter, var(--font-geist-sans), system-ui, sans-serif)',
284
246
  headingFamily: 'var(--font-outfit)',
285
247
  baseFontSize: '16px',
286
248
  lineHeight: '1.75',
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/utils/generateThemeCSS.ts"],"sourcesContent":["import type { ThemePreset } from '../presets.js'\nimport { borderRadiusPresets } from '../providers/Theme/themeConfig.js'\n\n/**\n * Generates complete CSS for a theme preset\n * Creates both light and dark mode CSS variables\n */\nexport function generateThemeCSS(preset: ThemePreset): string {\n const { name, label, borderRadius, typography, lightMode, darkMode } = preset\n\n const rootLines: string[] = []\n const darkLines: string[] = []\n\n // Typography\n const typographyPreset = typography ?? getDefaultTypography()\n pushTypography(rootLines, typographyPreset)\n\n // Layout (shared across themes)\n pushLayoutDefaults(rootLines)\n\n // Border radius based on preset definition\n pushBorderRadius(rootLines, borderRadius)\n\n // Component system defaults derived from colors\n pushComponentDefaults(rootLines, lightMode)\n\n // Light mode colours\n pushColorTokens(rootLines, lightMode, 'light')\n\n // Shared status colors (can be overridden later)\n pushStatusColors(rootLines, 'light')\n\n // Dark mode colors\n pushColorTokens(darkLines, darkMode, 'dark')\n pushStatusColors(darkLines, 'dark')\n pushDarkModeComponentOverrides(darkLines, darkMode)\n\n const sections: string[] = []\n sections.push(`/* ${label} Theme */`)\n sections.push(buildCssBlock(`[data-theme='${name}']`, rootLines))\n\n sections.push(`\n/* ${label} Theme - Dark Mode */`)\n sections.push(buildCssBlock(`[data-theme='${name}'][data-theme-mode='dark']`, darkLines))\n\n return sections.join('\\n').trim()\n}\n\n/**\n * Convert HEX color to HSL format\n * Example: #3b82f6 -> hsl(221, 83%, 53%)\n */\nfunction hexToHsl(hex: string): string {\n let normalized = hex.trim()\n if (!normalized.startsWith('#')) {\n normalized = `#${normalized}`\n }\n\n if (normalized.length === 4) {\n normalized = `#${normalized[1]}${normalized[1]}${normalized[2]}${normalized[2]}${normalized[3]}${normalized[3]}`\n }\n\n const r = parseInt(normalized.substring(1, 3), 16) / 255\n const g = parseInt(normalized.substring(3, 5), 16) / 255\n const b = parseInt(normalized.substring(5, 7), 16) / 255\n\n const max = Math.max(r, g, b)\n const min = Math.min(r, g, b)\n let h = 0\n let s = 0\n const l = (max + min) / 2\n\n if (max !== min) {\n const d = max - min\n s = l > 0.5 ? d / (2 - max - min) : d / (max + min)\n\n switch (max) {\n case r:\n h = ((g - b) / d + (g < b ? 6 : 0)) / 6\n break\n case g:\n h = ((b - r) / d + 2) / 6\n break\n case b:\n h = ((r - g) / d + 4) / 6\n break\n }\n }\n\n const hDeg = Math.round(h * 360)\n const sPercent = Math.round(s * 100)\n const lPercent = Math.round(l * 100)\n\n return `hsl(${hDeg}, ${sPercent}%, ${lPercent}%)`\n}\n\nfunction toCssColor(color?: string | null): string | null {\n if (!color) return null\n const trimmed = color.trim()\n if (/^var\\(/i.test(trimmed) || /^hsl\\(/i.test(trimmed) || /^rgb(a)?\\(/i.test(trimmed)) {\n return trimmed\n }\n if (/^#?[0-9a-f]{6}$/i.test(trimmed) || /^#?[0-9a-f]{3}$/i.test(trimmed)) {\n return hexToHsl(trimmed)\n }\n return trimmed\n}\n\nfunction buildCssBlock(selector: string, lines: string[]): string {\n if (!lines.length) {\n return `${selector} {}`\n }\n\n const body = lines.map((line) => (line.startsWith('--') ? ` ${line}` : line)).join('\\n')\n return `${selector} {\\n${body}\\n}`\n}\n\nfunction pushTypography(lines: string[], typography: NonNullable<ThemePreset['typography']>): void {\n const {\n fontFamily,\n headingFamily,\n baseFontSize,\n lineHeight,\n fontWeights = {},\n letterSpacing = {},\n } = typography\n\n if (fontFamily) lines.push(`--typography-fontFamily: ${fontFamily};`)\n if (headingFamily) lines.push(`--typography-headingFamily: ${headingFamily};`)\n if (baseFontSize) lines.push(`--typography-baseFontSize: ${baseFontSize};`)\n if (lineHeight) lines.push(`--typography-lineHeight: ${lineHeight};`)\n\n Object.entries(fontWeights).forEach(([token, weight]) => {\n if (weight) {\n lines.push(`--typography-fontWeights-${token}: ${weight};`)\n }\n })\n\n Object.entries(letterSpacing).forEach(([token, value]) => {\n if (value) {\n lines.push(`--typography-letterSpacing-${token}: ${value};`)\n }\n })\n}\n\nfunction pushLayoutDefaults(lines: string[]): void {\n lines.push('--layout-containerWidth: 1440px;')\n lines.push('--layout-containerPadding: 1.5rem;')\n lines.push('--layout-containerPaddingTablet: 2.5rem;')\n lines.push('--layout-containerPaddingDesktop: 3rem;')\n lines.push('--layout-sectionSpacing: 5rem;')\n lines.push('--layout-sectionSpacingTablet: 7rem;')\n lines.push('--layout-sectionSpacingDesktop: 9rem;')\n lines.push('--layout-gridGap: 2rem;')\n lines.push('--layout-gridGapTablet: 2.5rem;')\n lines.push('--layout-gridGapDesktop: 3rem;')\n}\n\nfunction pushBorderRadius(lines: string[], borderRadius?: ThemePreset['borderRadius']): void {\n const presetKey = borderRadius ?? 'medium'\n const preset = borderRadiusPresets[presetKey]\n\n if (preset?.css) {\n Object.entries(preset.css).forEach(([token, value]) => {\n lines.push(`${token}: ${value};`)\n })\n\n const defaultRadius =\n preset.css['--radius-default'] ??\n preset.css['--radius-medium'] ??\n preset.css['--radius-large'] ??\n preset.css['--radius']\n\n if (defaultRadius) {\n lines.push(`--radius: ${defaultRadius};`)\n }\n }\n}\n\nfunction pushComponentDefaults(lines: string[], lightMode?: ThemePreset['lightMode']): void {\n lines.push('--components-button-padding: 1rem 2.5rem;')\n lines.push('--components-button-padding-large: 1.25rem 3rem;')\n lines.push('--components-button-transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);')\n lines.push('--components-button-hover-scale: 1.02;')\n lines.push('--components-button-hover-opacity: 0.9;')\n lines.push('--components-button-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);')\n lines.push('--components-button-hover-shadow: 0 4px 16px rgba(0, 0, 0, 0.15);')\n\n lines.push('--components-card-padding: 2.5rem;')\n lines.push('--components-card-padding-compact: 1.5rem;')\n lines.push(\n '--components-card-shadow: 0 4px 16px -4px rgba(34, 42, 69, 0.12), 0 2px 8px -2px rgba(34, 42, 69, 0.08);',\n )\n lines.push(\n '--components-card-hover-shadow: 0 12px 48px -12px rgba(34, 42, 69, 0.2), 0 8px 32px -8px rgba(34, 42, 69, 0.12);',\n )\n lines.push('--components-card-hover-transform: translateY(-8px) scale(1.02);')\n\n const borderColor = toCssColor(lightMode?.border)\n if (borderColor) {\n lines.push(`--components-card-border: 1px solid ${borderColor};`)\n lines.push(`--components-input-border: 1.5px solid ${borderColor};`)\n }\n\n const primaryColor = toCssColor(lightMode?.primary)\n if (primaryColor) {\n lines.push(`--components-input-focus-border: 2px solid ${primaryColor};`)\n }\n\n lines.push('--components-input-height: 3.5rem;')\n lines.push('--components-input-padding: 1.25rem 1.75rem;')\n}\n\nconst COLOR_TOKENS: Array<{\n key: keyof NonNullable<ThemePreset['lightMode']>\n wrapWithVar?: boolean\n}> = [\n { key: 'background' },\n { key: 'foreground' },\n { key: 'card' },\n { key: 'cardForeground' },\n { key: 'popover' },\n { key: 'popoverForeground' },\n { key: 'primary', wrapWithVar: true },\n { key: 'primaryForeground' },\n { key: 'secondary' },\n { key: 'secondaryForeground' },\n { key: 'muted' },\n { key: 'mutedForeground' },\n { key: 'accent', wrapWithVar: true },\n { key: 'accentForeground' },\n { key: 'destructive' },\n { key: 'destructiveForeground' },\n { key: 'border' },\n { key: 'input' },\n { key: 'ring' },\n]\n\nfunction pushColorTokens(\n lines: string[],\n colors: ThemePreset['lightMode'] | ThemePreset['darkMode'],\n mode: 'light' | 'dark',\n): void {\n if (!colors) return\n\n COLOR_TOKENS.forEach(({ key, wrapWithVar }) => {\n const value = toCssColor(colors[key])\n if (!value) return\n\n if (key === 'ring') {\n lines.push('--ring: var(--primary);')\n return\n }\n\n if (wrapWithVar) {\n const customVar = key === 'accent' ? '--accent-custom' : '--primary-custom'\n lines.push(`--${toKebab(key)}: var(${customVar}, ${value});`)\n } else {\n lines.push(`--${toKebab(key)}: ${value};`)\n }\n })\n\n if (mode === 'light') {\n lines.push('--primary-hover: color-mix(in hsl, var(--primary), black 10%);')\n lines.push('--secondary-hover: color-mix(in hsl, var(--secondary), black 10%);')\n lines.push('--accent-hover: color-mix(in hsl, var(--accent), white 10%);')\n } else {\n lines.push('--primary-hover: color-mix(in hsl, var(--primary), white 10%);')\n lines.push('--secondary-hover: color-mix(in hsl, var(--secondary), white 10%);')\n lines.push('--accent-hover: color-mix(in hsl, var(--accent), white 10%);')\n }\n}\n\nfunction pushStatusColors(lines: string[], mode: 'light' | 'dark'): void {\n if (mode === 'light') {\n lines.push('--success: hsl(120, 60%, 40%);')\n lines.push('--success-foreground: hsl(0, 0%, 100%);')\n lines.push('--warning: hsl(42, 85%, 55%);')\n lines.push('--warning-foreground: hsl(25, 15%, 15%);')\n lines.push('--error: hsl(0, 85%, 52%);')\n lines.push('--error-foreground: hsl(0, 0%, 100%);')\n lines.push('--info: var(--primary);')\n lines.push('--info-foreground: var(--primary-foreground);')\n } else {\n lines.push('--success: hsl(120, 60%, 50%);')\n lines.push('--success-foreground: hsl(0, 0%, 10%);')\n lines.push('--warning: hsl(42, 85%, 55%);')\n lines.push('--warning-foreground: hsl(0, 0%, 10%);')\n lines.push('--error: hsl(0, 85%, 52%);')\n lines.push('--error-foreground: hsl(0, 0%, 100%);')\n lines.push('--info: var(--primary);')\n lines.push('--info-foreground: var(--primary-foreground);')\n }\n}\n\nfunction pushDarkModeComponentOverrides(lines: string[], darkMode?: ThemePreset['darkMode']): void {\n lines.push(\n '--components-card-shadow: 0 8px 32px -8px rgba(0, 0, 0, 0.6), 0 4px 16px -4px rgba(0, 0, 0, 0.4);',\n )\n lines.push(\n '--components-card-hover-shadow: 0 16px 64px -16px rgba(0, 0, 0, 0.8), 0 12px 40px -12px rgba(0, 0, 0, 0.6);',\n )\n\n const borderColor = toCssColor(darkMode?.border)\n if (borderColor) {\n lines.push(`--components-card-border: 1px solid ${borderColor};`)\n }\n\n const primaryColor = toCssColor(darkMode?.primary)\n if (primaryColor) {\n lines.push(`--components-input-focus-border: 2px solid ${primaryColor};`)\n }\n}\n\nfunction toKebab(token: string): string {\n return token.replace(/[A-Z]/g, (match) => `-${match.toLowerCase()}`)\n}\n\nfunction getDefaultTypography(): NonNullable<ThemePreset['typography']> {\n return {\n fontFamily: 'var(--font-geist-sans)',\n headingFamily: 'var(--font-outfit)',\n baseFontSize: '16px',\n lineHeight: '1.75',\n fontWeights: {\n light: '300',\n normal: '400',\n medium: '500',\n semibold: '600',\n bold: '700',\n black: '900',\n },\n letterSpacing: {\n tight: '-0.02em',\n normal: '0',\n wide: '0.025em',\n wider: '0.05em',\n },\n }\n}\n\n/**\n * Generate CSS for all themes\n */\nexport function generateAllThemesCSS(presets: ThemePreset[]): string {\n return presets.map((preset) => generateThemeCSS(preset)).join('\\n\\n')\n}\n"],"names":["borderRadiusPresets","generateThemeCSS","preset","name","label","borderRadius","typography","lightMode","darkMode","rootLines","darkLines","typographyPreset","getDefaultTypography","pushTypography","pushLayoutDefaults","pushBorderRadius","pushComponentDefaults","pushColorTokens","pushStatusColors","pushDarkModeComponentOverrides","sections","push","buildCssBlock","join","trim","hexToHsl","hex","normalized","startsWith","length","r","parseInt","substring","g","b","max","Math","min","h","s","l","d","hDeg","round","sPercent","lPercent","toCssColor","color","trimmed","test","selector","lines","body","map","line","fontFamily","headingFamily","baseFontSize","lineHeight","fontWeights","letterSpacing","Object","entries","forEach","token","weight","value","presetKey","css","defaultRadius","borderColor","border","primaryColor","primary","COLOR_TOKENS","key","wrapWithVar","colors","mode","customVar","toKebab","replace","match","toLowerCase","light","normal","medium","semibold","bold","black","tight","wide","wider","generateAllThemesCSS","presets"],"mappings":"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"}
1
+ {"version":3,"sources":["../../src/utils/generateThemeCSS.ts"],"sourcesContent":["import type { ThemePreset } from '../presets.js'\nimport { borderRadiusPresets } from '../providers/Theme/themeConfig.js'\nimport { hexToHsl } from './themeColors.js'\n\n/**\n * Generates complete CSS for a theme preset\n * Creates both light and dark mode CSS variables\n */\nexport function generateThemeCSS(preset: ThemePreset): string {\n const { name, label, borderRadius, typography, lightMode, darkMode } = preset\n\n const rootLines: string[] = []\n const darkLines: string[] = []\n\n // Typography\n const typographyPreset = typography ?? getDefaultTypography()\n pushTypography(rootLines, typographyPreset)\n\n // Layout (shared across themes)\n pushLayoutDefaults(rootLines)\n\n // Border radius based on preset definition\n pushBorderRadius(rootLines, borderRadius)\n\n // Component system defaults derived from colors\n pushComponentDefaults(rootLines, lightMode)\n\n // Light mode colours\n pushColorTokens(rootLines, lightMode, 'light')\n\n // Shared status colors (can be overridden later)\n pushStatusColors(rootLines, 'light')\n\n // Dark mode colors\n pushColorTokens(darkLines, darkMode, 'dark')\n pushStatusColors(darkLines, 'dark')\n pushDarkModeComponentOverrides(darkLines, darkMode)\n\n const sections: string[] = []\n sections.push(`/* ${label} Theme */`)\n sections.push(buildCssBlock(`[data-theme='${name}']`, rootLines))\n\n sections.push(`\n/* ${label} Theme - Dark Mode */`)\n sections.push(buildCssBlock(`[data-theme='${name}'][data-theme-mode='dark']`, darkLines))\n\n return sections.join('\\n').trim()\n}\n\nfunction toCssColor(color?: string | null): string | null {\n if (!color) return null\n const trimmed = color.trim()\n if (/^var\\(/i.test(trimmed) || /^hsl\\(/i.test(trimmed) || /^rgb(a)?\\(/i.test(trimmed)) {\n return trimmed\n }\n if (/^#?[0-9a-f]{6}$/i.test(trimmed) || /^#?[0-9a-f]{3}$/i.test(trimmed)) {\n return hexToHsl(trimmed)\n }\n return trimmed\n}\n\nfunction buildCssBlock(selector: string, lines: string[]): string {\n if (!lines.length) {\n return `${selector} {}`\n }\n\n const body = lines.map((line) => (line.startsWith('--') ? ` ${line}` : line)).join('\\n')\n return `${selector} {\\n${body}\\n}`\n}\n\nfunction pushTypography(lines: string[], typography: NonNullable<ThemePreset['typography']>): void {\n const {\n fontFamily,\n headingFamily,\n baseFontSize,\n lineHeight,\n fontWeights = {},\n letterSpacing = {},\n } = typography\n\n if (fontFamily) lines.push(`--typography-fontFamily: ${fontFamily};`)\n if (headingFamily) lines.push(`--typography-headingFamily: ${headingFamily};`)\n if (baseFontSize) lines.push(`--typography-baseFontSize: ${baseFontSize};`)\n if (lineHeight) lines.push(`--typography-lineHeight: ${lineHeight};`)\n\n Object.entries(fontWeights).forEach(([token, weight]) => {\n if (weight) {\n lines.push(`--typography-fontWeights-${token}: ${weight};`)\n }\n })\n\n Object.entries(letterSpacing).forEach(([token, value]) => {\n if (value) {\n lines.push(`--typography-letterSpacing-${token}: ${value};`)\n }\n })\n}\n\nfunction pushLayoutDefaults(lines: string[]): void {\n lines.push('--layout-containerWidth: 1440px;')\n lines.push('--layout-containerPadding: 1.5rem;')\n lines.push('--layout-containerPaddingTablet: 2.5rem;')\n lines.push('--layout-containerPaddingDesktop: 3rem;')\n lines.push('--layout-sectionSpacing: 5rem;')\n lines.push('--layout-sectionSpacingTablet: 7rem;')\n lines.push('--layout-sectionSpacingDesktop: 9rem;')\n lines.push('--layout-gridGap: 2rem;')\n lines.push('--layout-gridGapTablet: 2.5rem;')\n lines.push('--layout-gridGapDesktop: 3rem;')\n}\n\nfunction pushBorderRadius(lines: string[], borderRadius?: ThemePreset['borderRadius']): void {\n const presetKey = borderRadius ?? 'medium'\n const preset = borderRadiusPresets[presetKey]\n\n if (preset?.css) {\n Object.entries(preset.css).forEach(([token, value]) => {\n lines.push(`${token}: ${value};`)\n })\n\n const defaultRadius =\n preset.css['--radius-default'] ??\n preset.css['--radius-medium'] ??\n preset.css['--radius-large'] ??\n preset.css['--radius']\n\n if (defaultRadius) {\n lines.push(`--radius: ${defaultRadius};`)\n }\n }\n}\n\nfunction pushComponentDefaults(lines: string[], lightMode?: ThemePreset['lightMode']): void {\n lines.push('--components-button-padding: 1rem 2.5rem;')\n lines.push('--components-button-padding-large: 1.25rem 3rem;')\n lines.push('--components-button-transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);')\n lines.push('--components-button-hover-scale: 1.02;')\n lines.push('--components-button-hover-opacity: 0.9;')\n lines.push('--components-button-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);')\n lines.push('--components-button-hover-shadow: 0 4px 16px rgba(0, 0, 0, 0.15);')\n\n lines.push('--components-card-padding: 2.5rem;')\n lines.push('--components-card-padding-compact: 1.5rem;')\n lines.push(\n '--components-card-shadow: 0 4px 16px -4px rgba(34, 42, 69, 0.12), 0 2px 8px -2px rgba(34, 42, 69, 0.08);',\n )\n lines.push(\n '--components-card-hover-shadow: 0 12px 48px -12px rgba(34, 42, 69, 0.2), 0 8px 32px -8px rgba(34, 42, 69, 0.12);',\n )\n lines.push('--components-card-hover-transform: translateY(-8px) scale(1.02);')\n\n const borderColor = toCssColor(lightMode?.border)\n if (borderColor) {\n lines.push(`--components-card-border: 1px solid ${borderColor};`)\n lines.push(`--components-input-border: 1.5px solid ${borderColor};`)\n }\n\n const primaryColor = toCssColor(lightMode?.primary)\n if (primaryColor) {\n lines.push(`--components-input-focus-border: 2px solid ${primaryColor};`)\n }\n\n lines.push('--components-input-height: 3.5rem;')\n lines.push('--components-input-padding: 1.25rem 1.75rem;')\n}\n\nconst COLOR_TOKENS: Array<{\n key: keyof NonNullable<ThemePreset['lightMode']>\n wrapWithVar?: boolean\n}> = [\n { key: 'background' },\n { key: 'foreground' },\n { key: 'card' },\n { key: 'cardForeground' },\n { key: 'popover' },\n { key: 'popoverForeground' },\n { key: 'primary', wrapWithVar: true },\n { key: 'primaryForeground' },\n { key: 'secondary' },\n { key: 'secondaryForeground' },\n { key: 'muted' },\n { key: 'mutedForeground' },\n { key: 'accent', wrapWithVar: true },\n { key: 'accentForeground' },\n { key: 'destructive' },\n { key: 'destructiveForeground' },\n { key: 'border' },\n { key: 'input' },\n { key: 'ring' },\n]\n\nfunction pushColorTokens(\n lines: string[],\n colors: ThemePreset['lightMode'] | ThemePreset['darkMode'],\n mode: 'light' | 'dark',\n): void {\n if (!colors) return\n\n COLOR_TOKENS.forEach(({ key, wrapWithVar }) => {\n const value = toCssColor(colors[key])\n if (!value) return\n\n if (key === 'ring') {\n lines.push('--ring: var(--primary);')\n return\n }\n\n if (wrapWithVar) {\n const customVar = key === 'accent' ? '--accent-custom' : '--primary-custom'\n lines.push(`--${toKebab(key)}: var(${customVar}, ${value});`)\n } else {\n lines.push(`--${toKebab(key)}: ${value};`)\n }\n })\n\n if (mode === 'light') {\n lines.push('--primary-hover: color-mix(in hsl, var(--primary), black 10%);')\n lines.push('--secondary-hover: color-mix(in hsl, var(--secondary), black 10%);')\n lines.push('--accent-hover: color-mix(in hsl, var(--accent), white 10%);')\n } else {\n lines.push('--primary-hover: color-mix(in hsl, var(--primary), white 10%);')\n lines.push('--secondary-hover: color-mix(in hsl, var(--secondary), white 10%);')\n lines.push('--accent-hover: color-mix(in hsl, var(--accent), white 10%);')\n }\n}\n\nfunction pushStatusColors(lines: string[], mode: 'light' | 'dark'): void {\n if (mode === 'light') {\n lines.push('--success: hsl(120, 60%, 40%);')\n lines.push('--success-foreground: hsl(0, 0%, 100%);')\n lines.push('--warning: hsl(42, 85%, 55%);')\n lines.push('--warning-foreground: hsl(25, 15%, 15%);')\n lines.push('--error: hsl(0, 85%, 52%);')\n lines.push('--error-foreground: hsl(0, 0%, 100%);')\n lines.push('--info: var(--primary);')\n lines.push('--info-foreground: var(--primary-foreground);')\n } else {\n lines.push('--success: hsl(120, 60%, 50%);')\n lines.push('--success-foreground: hsl(0, 0%, 10%);')\n lines.push('--warning: hsl(42, 85%, 55%);')\n lines.push('--warning-foreground: hsl(0, 0%, 10%);')\n lines.push('--error: hsl(0, 85%, 52%);')\n lines.push('--error-foreground: hsl(0, 0%, 100%);')\n lines.push('--info: var(--primary);')\n lines.push('--info-foreground: var(--primary-foreground);')\n }\n}\n\nfunction pushDarkModeComponentOverrides(lines: string[], darkMode?: ThemePreset['darkMode']): void {\n lines.push(\n '--components-card-shadow: 0 8px 32px -8px rgba(0, 0, 0, 0.6), 0 4px 16px -4px rgba(0, 0, 0, 0.4);',\n )\n lines.push(\n '--components-card-hover-shadow: 0 16px 64px -16px rgba(0, 0, 0, 0.8), 0 12px 40px -12px rgba(0, 0, 0, 0.6);',\n )\n\n const borderColor = toCssColor(darkMode?.border)\n if (borderColor) {\n lines.push(`--components-card-border: 1px solid ${borderColor};`)\n }\n\n const primaryColor = toCssColor(darkMode?.primary)\n if (primaryColor) {\n lines.push(`--components-input-focus-border: 2px solid ${primaryColor};`)\n }\n}\n\nfunction toKebab(token: string): string {\n return token.replace(/[A-Z]/g, (match) => `-${match.toLowerCase()}`)\n}\n\nfunction getDefaultTypography(): NonNullable<ThemePreset['typography']> {\n return {\n fontFamily: 'var(--font-inter, var(--font-geist-sans), system-ui, sans-serif)',\n headingFamily: 'var(--font-outfit)',\n baseFontSize: '16px',\n lineHeight: '1.75',\n fontWeights: {\n light: '300',\n normal: '400',\n medium: '500',\n semibold: '600',\n bold: '700',\n black: '900',\n },\n letterSpacing: {\n tight: '-0.02em',\n normal: '0',\n wide: '0.025em',\n wider: '0.05em',\n },\n }\n}\n\n/**\n * Generate CSS for all themes\n */\nexport function generateAllThemesCSS(presets: ThemePreset[]): string {\n return presets.map((preset) => generateThemeCSS(preset)).join('\\n\\n')\n}\n"],"names":["borderRadiusPresets","hexToHsl","generateThemeCSS","preset","name","label","borderRadius","typography","lightMode","darkMode","rootLines","darkLines","typographyPreset","getDefaultTypography","pushTypography","pushLayoutDefaults","pushBorderRadius","pushComponentDefaults","pushColorTokens","pushStatusColors","pushDarkModeComponentOverrides","sections","push","buildCssBlock","join","trim","toCssColor","color","trimmed","test","selector","lines","length","body","map","line","startsWith","fontFamily","headingFamily","baseFontSize","lineHeight","fontWeights","letterSpacing","Object","entries","forEach","token","weight","value","presetKey","css","defaultRadius","borderColor","border","primaryColor","primary","COLOR_TOKENS","key","wrapWithVar","colors","mode","customVar","toKebab","replace","match","toLowerCase","light","normal","medium","semibold","bold","black","tight","wide","wider","generateAllThemesCSS","presets"],"mappings":"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"}
@@ -1,7 +1,26 @@
1
- export declare const extractThemeConfigurationFromLiveData: (liveData: Record<string, unknown>, themeConfigurationKey?: string) => unknown;
2
- export declare const buildLivePreviewThemeRuntime: (themeConfiguration: unknown) => {
3
- theme: "cyberpunk" | "minimal" | "retro" | "brutal" | "pastel" | "ocean" | "forest" | "sunset" | "lavender" | "neutral" | "blue" | "green" | "red" | "orange" | "rose" | "violet" | "zinc" | "slate" | "stone" | "gray" | "cool" | "neon" | "solar" | "dealership" | "real-estate" | "real-estate-gold" | "real-estate-neutral";
1
+ import { type ThemeFontLoading } from '../constants/themeFonts.js';
2
+ /**
3
+ * Keys that strongly indicate a live-preview payload is (or contains) a theme
4
+ * configuration object. Used to avoid applying default theme CSS when an
5
+ * unrelated form (e.g. a page editor) emits live-preview data.
6
+ */
7
+ export declare const THEME_LIKE_KEYS: readonly ["theme", "colorMode", "allowColorModeToggle", "lightMode", "darkMode", "customCSS", "borderRadius", "fontScale", "spacing", "animationLevel"];
8
+ export declare const isThemeLikeObject: (value: unknown) => value is Record<string, unknown>;
9
+ /**
10
+ * Safely extract the theme configuration object from a live-preview payload.
11
+ *
12
+ * Returns `null` when the payload is unrelated (e.g. page form data) so callers
13
+ * can skip re-applying theme CSS instead of falling back to defaults — which
14
+ * would visibly reset the theme while editing other documents.
15
+ */
16
+ export declare const extractThemeConfigurationFromLiveData: (liveData: Record<string, unknown> | undefined, themeConfigurationKey?: string) => Record<string, unknown> | null;
17
+ export declare const buildLivePreviewThemeRuntime: (themeConfiguration: unknown, apiRoute?: string, fontLoading?: ThemeFontLoading) => {
18
+ theme: "cyberpunk" | "minimal" | "retro" | "brutal" | "pastel" | "ocean" | "forest" | "sunset" | "lavender" | "glassmorphism" | "claymorphism" | "neumorphism" | "aurora" | "luxury" | "healthcare" | "nordic" | "warm-earth" | "neutral" | "blue" | "green" | "red" | "orange" | "rose" | "violet" | "zinc" | "slate" | "stone" | "gray" | "cool" | "neon" | "solar" | "dealership" | "real-estate" | "real-estate-gold" | "real-estate-neutral";
4
19
  mode: "light" | "dark";
20
+ attributes: {
21
+ [k: string]: string;
22
+ };
23
+ fontsHref: string;
5
24
  css: string;
6
25
  };
7
26
  //# sourceMappingURL=livePreviewThemeRuntime.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"livePreviewThemeRuntime.d.ts","sourceRoot":"","sources":["../../src/utils/livePreviewThemeRuntime.ts"],"names":[],"mappings":"AAKA,eAAO,MAAM,qCAAqC,GAChD,UAAU,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACjC,8BAA4C,KAC3C,OAOF,CAAA;AAkBD,eAAO,MAAM,4BAA4B,GAAI,oBAAoB,OAAO;;;;CA0CvE,CAAA"}
1
+ {"version":3,"file":"livePreviewThemeRuntime.d.ts","sourceRoot":"","sources":["../../src/utils/livePreviewThemeRuntime.ts"],"names":[],"mappings":"AAAA,OAAO,EAAuB,KAAK,gBAAgB,EAAE,MAAM,4BAA4B,CAAA;AAOvF;;;;GAIG;AACH,eAAO,MAAM,eAAe,yJAWlB,CAAA;AAEV,eAAO,MAAM,iBAAiB,GAAI,OAAO,OAAO,KAAG,KAAK,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAKjF,CAAA;AAED;;;;;;GAMG;AACH,eAAO,MAAM,qCAAqC,GAChD,UAAU,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,EAC7C,8BAA4C,KAC3C,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAa5B,CAAA;AAkBD,eAAO,MAAM,4BAA4B,GACvC,oBAAoB,OAAO,EAC3B,iBAAiB,EACjB,cAAa,gBAAgC;;;;;;;;CA2C9C,CAAA"}
@@ -1,13 +1,48 @@
1
+ import { buildThemeFontsHref } from '../constants/themeFonts.js';
1
2
  import { getBorderRadiusConfig } from '../providers/Theme/themeConfig.js';
2
3
  import { resolveThemeConfiguration } from './resolveThemeConfiguration.js';
3
4
  import { generateThemeColorsCss } from './themeColors.js';
5
+ import { getThemeHtmlAttributes } from './themeHtmlAttributes.js';
4
6
  import { generateThemeCSS } from './themeUtils.js';
5
- export const extractThemeConfigurationFromLiveData = (liveData, themeConfigurationKey = 'themeConfiguration')=>{
7
+ /**
8
+ * Keys that strongly indicate a live-preview payload is (or contains) a theme
9
+ * configuration object. Used to avoid applying default theme CSS when an
10
+ * unrelated form (e.g. a page editor) emits live-preview data.
11
+ */ export const THEME_LIKE_KEYS = [
12
+ 'theme',
13
+ 'colorMode',
14
+ 'allowColorModeToggle',
15
+ 'lightMode',
16
+ 'darkMode',
17
+ 'customCSS',
18
+ 'borderRadius',
19
+ 'fontScale',
20
+ 'spacing',
21
+ 'animationLevel'
22
+ ];
23
+ export const isThemeLikeObject = (value)=>{
24
+ if (!value || typeof value !== 'object' || Array.isArray(value)) {
25
+ return false;
26
+ }
27
+ return THEME_LIKE_KEYS.some((key)=>key in value);
28
+ };
29
+ /**
30
+ * Safely extract the theme configuration object from a live-preview payload.
31
+ *
32
+ * Returns `null` when the payload is unrelated (e.g. page form data) so callers
33
+ * can skip re-applying theme CSS instead of falling back to defaults — which
34
+ * would visibly reset the theme while editing other documents.
35
+ */ export const extractThemeConfigurationFromLiveData = (liveData, themeConfigurationKey = 'themeConfiguration')=>{
6
36
  const candidate = liveData?.[themeConfigurationKey];
7
- if (candidate && typeof candidate === 'object') {
37
+ if (candidate && typeof candidate === 'object' && !Array.isArray(candidate)) {
8
38
  return candidate;
9
39
  }
10
- return liveData;
40
+ // Some forms emit the theme config object directly at the root.
41
+ if (isThemeLikeObject(liveData)) {
42
+ return liveData;
43
+ }
44
+ // Ignore unrelated live-preview payloads to avoid fallback defaults.
45
+ return null;
11
46
  };
12
47
  const resolveColorMode = (mode)=>{
13
48
  if (mode === 'dark') {
@@ -18,19 +53,9 @@ const resolveColorMode = (mode)=>{
18
53
  }
19
54
  return 'light';
20
55
  };
21
- export const buildLivePreviewThemeRuntime = (themeConfiguration)=>{
22
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
56
+ export const buildLivePreviewThemeRuntime = (themeConfiguration, apiRoute = '/api', fontLoading = 'self-hosted')=>{
23
57
  const resolved = resolveThemeConfiguration(themeConfiguration);
24
- const borderRadiusMap = {
25
- none: 'none',
26
- small: 'small',
27
- medium: 'medium',
28
- large: 'large',
29
- xl: 'xl',
30
- full: 'xl'
31
- };
32
- const mappedBorderRadius = borderRadiusMap[resolved.borderRadius ?? 'medium'] ?? 'medium';
33
- const borderRadiusConfig = getBorderRadiusConfig(mappedBorderRadius);
58
+ const borderRadiusConfig = getBorderRadiusConfig(resolved.borderRadius ?? 'medium');
34
59
  const cssRecord = typeof borderRadiusConfig?.css === 'string' ? {
35
60
  '--radius-default': borderRadiusConfig.css
36
61
  } : borderRadiusConfig?.css ?? {};
@@ -43,9 +68,17 @@ export const buildLivePreviewThemeRuntime = (themeConfiguration)=>{
43
68
  darkMode: resolved.darkMode
44
69
  });
45
70
  const customCSSBlock = typeof resolved.customCSS === 'string' ? resolved.customCSS.trim() : '';
71
+ // Every data-* attribute the generated CSS targets (effects, card / button /
72
+ // navbar styles …), so Visual Effects and Component Styles update live too.
73
+ const attributes = Object.fromEntries(Object.entries(getThemeHtmlAttributes(resolved)).filter((entry)=>entry[0].startsWith('data-') && typeof entry[1] === 'string'));
46
74
  return {
47
75
  theme: resolved.theme,
48
76
  mode: resolveColorMode(resolved.colorMode),
77
+ attributes,
78
+ fontsHref: buildThemeFontsHref(resolved.fontSelections ?? [], {
79
+ apiRoute,
80
+ mode: fontLoading
81
+ }),
49
82
  css: [
50
83
  borderRadiusBlock,
51
84
  themeConfigurationCSS,
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/utils/livePreviewThemeRuntime.ts"],"sourcesContent":["import { getBorderRadiusConfig } from '../providers/Theme/themeConfig.js'\nimport { resolveThemeConfiguration } from './resolveThemeConfiguration.js'\nimport { generateThemeColorsCss } from './themeColors.js'\nimport { generateThemeCSS } from './themeUtils.js'\n\nexport const extractThemeConfigurationFromLiveData = (\n liveData: Record<string, unknown>,\n themeConfigurationKey = 'themeConfiguration',\n): unknown => {\n const candidate = liveData?.[themeConfigurationKey]\n if (candidate && typeof candidate === 'object') {\n return candidate\n }\n\n return liveData\n}\n\nconst resolveColorMode = (mode: string): 'light' | 'dark' => {\n if (mode === 'dark') {\n return 'dark'\n }\n\n if (\n mode === 'auto' &&\n globalThis.window !== undefined &&\n typeof globalThis.window.matchMedia === 'function'\n ) {\n return globalThis.window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light'\n }\n\n return 'light'\n}\n\nexport const buildLivePreviewThemeRuntime = (themeConfiguration: unknown) => {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const resolved = resolveThemeConfiguration(themeConfiguration as any)\n\n const borderRadiusMap: Record<string, 'none' | 'small' | 'medium' | 'large' | 'xl'> = {\n none: 'none',\n small: 'small',\n medium: 'medium',\n large: 'large',\n xl: 'xl',\n full: 'xl',\n }\n\n const mappedBorderRadius = borderRadiusMap[resolved.borderRadius ?? 'medium'] ?? 'medium'\n const borderRadiusConfig = getBorderRadiusConfig(mappedBorderRadius)\n const cssRecord =\n typeof borderRadiusConfig?.css === 'string'\n ? { '--radius-default': borderRadiusConfig.css }\n : (borderRadiusConfig?.css ?? {})\n\n const borderRadiusCSS = Object.entries(cssRecord)\n .map(([property, value]) => ` ${property}: ${value};`)\n .join('\\n')\n\n const borderRadiusBlock = borderRadiusCSS ? `:root {\\n${borderRadiusCSS}\\n}` : ''\n\n const themeConfigurationCSS = generateThemeCSS(resolved)\n const colorModesCSS = generateThemeColorsCss({\n themeName: resolved.theme,\n lightMode: resolved.lightMode,\n darkMode: resolved.darkMode,\n })\n\n const customCSSBlock = typeof resolved.customCSS === 'string' ? resolved.customCSS.trim() : ''\n\n return {\n theme: resolved.theme,\n mode: resolveColorMode(resolved.colorMode),\n css: [borderRadiusBlock, themeConfigurationCSS, colorModesCSS, customCSSBlock]\n .filter((block) => Boolean(block?.trim?.().length))\n .join('\\n\\n'),\n }\n}\n"],"names":["getBorderRadiusConfig","resolveThemeConfiguration","generateThemeColorsCss","generateThemeCSS","extractThemeConfigurationFromLiveData","liveData","themeConfigurationKey","candidate","resolveColorMode","mode","globalThis","window","undefined","matchMedia","matches","buildLivePreviewThemeRuntime","themeConfiguration","resolved","borderRadiusMap","none","small","medium","large","xl","full","mappedBorderRadius","borderRadius","borderRadiusConfig","cssRecord","css","borderRadiusCSS","Object","entries","map","property","value","join","borderRadiusBlock","themeConfigurationCSS","colorModesCSS","themeName","theme","lightMode","darkMode","customCSSBlock","customCSS","trim","colorMode","filter","block","Boolean","length"],"mappings":"AAAA,SAASA,qBAAqB,QAAQ,oCAAmC;AACzE,SAASC,yBAAyB,QAAQ,iCAAgC;AAC1E,SAASC,sBAAsB,QAAQ,mBAAkB;AACzD,SAASC,gBAAgB,QAAQ,kBAAiB;AAElD,OAAO,MAAMC,wCAAwC,CACnDC,UACAC,wBAAwB,oBAAoB;IAE5C,MAAMC,YAAYF,UAAU,CAACC,sBAAsB;IACnD,IAAIC,aAAa,OAAOA,cAAc,UAAU;QAC9C,OAAOA;IACT;IAEA,OAAOF;AACT,EAAC;AAED,MAAMG,mBAAmB,CAACC;IACxB,IAAIA,SAAS,QAAQ;QACnB,OAAO;IACT;IAEA,IACEA,SAAS,UACTC,WAAWC,MAAM,KAAKC,aACtB,OAAOF,WAAWC,MAAM,CAACE,UAAU,KAAK,YACxC;QACA,OAAOH,WAAWC,MAAM,CAACE,UAAU,CAAC,gCAAgCC,OAAO,GAAG,SAAS;IACzF;IAEA,OAAO;AACT;AAEA,OAAO,MAAMC,+BAA+B,CAACC;IAC3C,8DAA8D;IAC9D,MAAMC,WAAWhB,0BAA0Be;IAE3C,MAAME,kBAAgF;QACpFC,MAAM;QACNC,OAAO;QACPC,QAAQ;QACRC,OAAO;QACPC,IAAI;QACJC,MAAM;IACR;IAEA,MAAMC,qBAAqBP,eAAe,CAACD,SAASS,YAAY,IAAI,SAAS,IAAI;IACjF,MAAMC,qBAAqB3B,sBAAsByB;IACjD,MAAMG,YACJ,OAAOD,oBAAoBE,QAAQ,WAC/B;QAAE,oBAAoBF,mBAAmBE,GAAG;IAAC,IAC5CF,oBAAoBE,OAAO,CAAC;IAEnC,MAAMC,kBAAkBC,OAAOC,OAAO,CAACJ,WACpCK,GAAG,CAAC,CAAC,CAACC,UAAUC,MAAM,GAAK,CAAC,EAAE,EAAED,SAAS,EAAE,EAAEC,MAAM,CAAC,CAAC,EACrDC,IAAI,CAAC;IAER,MAAMC,oBAAoBP,kBAAkB,CAAC,SAAS,EAAEA,gBAAgB,GAAG,CAAC,GAAG;IAE/E,MAAMQ,wBAAwBnC,iBAAiBc;IAC/C,MAAMsB,gBAAgBrC,uBAAuB;QAC3CsC,WAAWvB,SAASwB,KAAK;QACzBC,WAAWzB,SAASyB,SAAS;QAC7BC,UAAU1B,SAAS0B,QAAQ;IAC7B;IAEA,MAAMC,iBAAiB,OAAO3B,SAAS4B,SAAS,KAAK,WAAW5B,SAAS4B,SAAS,CAACC,IAAI,KAAK;IAE5F,OAAO;QACLL,OAAOxB,SAASwB,KAAK;QACrBhC,MAAMD,iBAAiBS,SAAS8B,SAAS;QACzClB,KAAK;YAACQ;YAAmBC;YAAuBC;YAAeK;SAAe,CAC3EI,MAAM,CAAC,CAACC,QAAUC,QAAQD,OAAOH,SAASK,SAC1Cf,IAAI,CAAC;IACV;AACF,EAAC"}
1
+ {"version":3,"sources":["../../src/utils/livePreviewThemeRuntime.ts"],"sourcesContent":["import { buildThemeFontsHref, type ThemeFontLoading } from '../constants/themeFonts.js'\nimport { getBorderRadiusConfig } from '../providers/Theme/themeConfig.js'\nimport { resolveThemeConfiguration } from './resolveThemeConfiguration.js'\nimport { generateThemeColorsCss } from './themeColors.js'\nimport { getThemeHtmlAttributes } from './themeHtmlAttributes.js'\nimport { generateThemeCSS } from './themeUtils.js'\n\n/**\n * Keys that strongly indicate a live-preview payload is (or contains) a theme\n * configuration object. Used to avoid applying default theme CSS when an\n * unrelated form (e.g. a page editor) emits live-preview data.\n */\nexport const THEME_LIKE_KEYS = [\n 'theme',\n 'colorMode',\n 'allowColorModeToggle',\n 'lightMode',\n 'darkMode',\n 'customCSS',\n 'borderRadius',\n 'fontScale',\n 'spacing',\n 'animationLevel',\n] as const\n\nexport const isThemeLikeObject = (value: unknown): value is Record<string, unknown> => {\n if (!value || typeof value !== 'object' || Array.isArray(value)) {\n return false\n }\n return THEME_LIKE_KEYS.some((key) => key in (value as Record<string, unknown>))\n}\n\n/**\n * Safely extract the theme configuration object from a live-preview payload.\n *\n * Returns `null` when the payload is unrelated (e.g. page form data) so callers\n * can skip re-applying theme CSS instead of falling back to defaults — which\n * would visibly reset the theme while editing other documents.\n */\nexport const extractThemeConfigurationFromLiveData = (\n liveData: Record<string, unknown> | undefined,\n themeConfigurationKey = 'themeConfiguration',\n): Record<string, unknown> | null => {\n const candidate = liveData?.[themeConfigurationKey]\n if (candidate && typeof candidate === 'object' && !Array.isArray(candidate)) {\n return candidate as Record<string, unknown>\n }\n\n // Some forms emit the theme config object directly at the root.\n if (isThemeLikeObject(liveData)) {\n return liveData as Record<string, unknown>\n }\n\n // Ignore unrelated live-preview payloads to avoid fallback defaults.\n return null\n}\n\nconst resolveColorMode = (mode: string): 'light' | 'dark' => {\n if (mode === 'dark') {\n return 'dark'\n }\n\n if (\n mode === 'auto' &&\n globalThis.window !== undefined &&\n typeof globalThis.window.matchMedia === 'function'\n ) {\n return globalThis.window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light'\n }\n\n return 'light'\n}\n\nexport const buildLivePreviewThemeRuntime = (\n themeConfiguration: unknown,\n apiRoute = '/api',\n fontLoading: ThemeFontLoading = 'self-hosted',\n) => {\n const resolved = resolveThemeConfiguration(themeConfiguration)\n\n const borderRadiusConfig = getBorderRadiusConfig(resolved.borderRadius ?? 'medium')\n const cssRecord =\n typeof borderRadiusConfig?.css === 'string'\n ? { '--radius-default': borderRadiusConfig.css }\n : (borderRadiusConfig?.css ?? {})\n\n const borderRadiusCSS = Object.entries(cssRecord)\n .map(([property, value]) => ` ${property}: ${value};`)\n .join('\\n')\n\n const borderRadiusBlock = borderRadiusCSS ? `:root {\\n${borderRadiusCSS}\\n}` : ''\n\n const themeConfigurationCSS = generateThemeCSS(resolved)\n const colorModesCSS = generateThemeColorsCss({\n themeName: resolved.theme,\n lightMode: resolved.lightMode,\n darkMode: resolved.darkMode,\n })\n\n const customCSSBlock = typeof resolved.customCSS === 'string' ? resolved.customCSS.trim() : ''\n\n // Every data-* attribute the generated CSS targets (effects, card / button /\n // navbar styles …), so Visual Effects and Component Styles update live too.\n const attributes = Object.fromEntries(\n Object.entries(getThemeHtmlAttributes(resolved)).filter(\n (entry): entry is [string, string] =>\n entry[0].startsWith('data-') && typeof entry[1] === 'string',\n ),\n )\n\n return {\n theme: resolved.theme,\n mode: resolveColorMode(resolved.colorMode),\n attributes,\n fontsHref: buildThemeFontsHref(resolved.fontSelections ?? [], { apiRoute, mode: fontLoading }),\n css: [borderRadiusBlock, themeConfigurationCSS, colorModesCSS, customCSSBlock]\n .filter((block) => Boolean(block?.trim?.().length))\n .join('\\n\\n'),\n }\n}\n"],"names":["buildThemeFontsHref","getBorderRadiusConfig","resolveThemeConfiguration","generateThemeColorsCss","getThemeHtmlAttributes","generateThemeCSS","THEME_LIKE_KEYS","isThemeLikeObject","value","Array","isArray","some","key","extractThemeConfigurationFromLiveData","liveData","themeConfigurationKey","candidate","resolveColorMode","mode","globalThis","window","undefined","matchMedia","matches","buildLivePreviewThemeRuntime","themeConfiguration","apiRoute","fontLoading","resolved","borderRadiusConfig","borderRadius","cssRecord","css","borderRadiusCSS","Object","entries","map","property","join","borderRadiusBlock","themeConfigurationCSS","colorModesCSS","themeName","theme","lightMode","darkMode","customCSSBlock","customCSS","trim","attributes","fromEntries","filter","entry","startsWith","colorMode","fontsHref","fontSelections","block","Boolean","length"],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Payload field labels, descriptions and placeholders arrive either as plain
3
+ * strings or as `{ en, cs, … }` objects. Resolve them against the active admin
4
+ * language (full tag, then base language), falling back to English and then to
5
+ * the first available translation.
6
+ */
7
+ export declare function resolveLocalizedText(value: unknown, language: string, fallback?: string): string;
8
+ //# sourceMappingURL=localizedText.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"localizedText.d.ts","sourceRoot":"","sources":["../../src/utils/localizedText.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAClC,KAAK,EAAE,OAAO,EACd,QAAQ,EAAE,MAAM,EAChB,QAAQ,SAAK,GACZ,MAAM,CASR"}
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Payload field labels, descriptions and placeholders arrive either as plain
3
+ * strings or as `{ en, cs, … }` objects. Resolve them against the active admin
4
+ * language (full tag, then base language), falling back to English and then to
5
+ * the first available translation.
6
+ */ export function resolveLocalizedText(value, language, fallback = '') {
7
+ if (typeof value === 'string') return value;
8
+ if (!value || typeof value !== 'object') return fallback;
9
+ const localized = value;
10
+ const base = language.split('-')[0];
11
+ const candidates = [
12
+ localized[language],
13
+ localized[base],
14
+ localized.en,
15
+ ...Object.values(localized)
16
+ ];
17
+ const resolved = candidates.find((candidate)=>typeof candidate === 'string');
18
+ return resolved ?? fallback;
19
+ }
20
+
21
+ //# sourceMappingURL=localizedText.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/utils/localizedText.ts"],"sourcesContent":["/**\n * Payload field labels, descriptions and placeholders arrive either as plain\n * strings or as `{ en, cs, … }` objects. Resolve them against the active admin\n * language (full tag, then base language), falling back to English and then to\n * the first available translation.\n */\nexport function resolveLocalizedText(\n value: unknown,\n language: string,\n fallback = '',\n): string {\n if (typeof value === 'string') return value\n if (!value || typeof value !== 'object') return fallback\n\n const localized = value as Record<string, unknown>\n const base = language.split('-')[0]\n const candidates = [localized[language], localized[base], localized.en, ...Object.values(localized)]\n const resolved = candidates.find((candidate): candidate is string => typeof candidate === 'string')\n return resolved ?? fallback\n}\n"],"names":["resolveLocalizedText","value","language","fallback","localized","base","split","candidates","en","Object","values","resolved","find","candidate"],"mappings":"AAAA;;;;;CAKC,GACD,OAAO,SAASA,qBACdC,KAAc,EACdC,QAAgB,EAChBC,WAAW,EAAE;IAEb,IAAI,OAAOF,UAAU,UAAU,OAAOA;IACtC,IAAI,CAACA,SAAS,OAAOA,UAAU,UAAU,OAAOE;IAEhD,MAAMC,YAAYH;IAClB,MAAMI,OAAOH,SAASI,KAAK,CAAC,IAAI,CAAC,EAAE;IACnC,MAAMC,aAAa;QAACH,SAAS,CAACF,SAAS;QAAEE,SAAS,CAACC,KAAK;QAAED,UAAUI,EAAE;WAAKC,OAAOC,MAAM,CAACN;KAAW;IACpG,MAAMO,WAAWJ,WAAWK,IAAI,CAAC,CAACC,YAAmC,OAAOA,cAAc;IAC1F,OAAOF,YAAYR;AACrB"}
@@ -11,6 +11,8 @@ interface ThemeTypographyOverride {
11
11
  headingFontCustom?: string | null;
12
12
  baseFontSize?: string | null;
13
13
  lineHeight?: string | null;
14
+ headingWeight?: string | null;
15
+ letterSpacing?: string | null;
14
16
  }
15
17
  /**
16
18
  * Generic theme configuration interface that accepts any compatible structure
@@ -46,6 +48,29 @@ interface GenericThemeConfiguration {
46
48
  info?: string | null;
47
49
  } | null;
48
50
  typography?: ThemeTypographyOverride | null;
51
+ fontSelections?: string[] | null;
52
+ typographyOverridden?: boolean | null;
53
+ visualEffects?: {
54
+ effectStyle?: string | null;
55
+ shadowIntensity?: string | null;
56
+ backdropBlur?: string | null;
57
+ borderStyle?: string | null;
58
+ borderWidth?: string | null;
59
+ glassOpacity?: number | null;
60
+ } | null;
61
+ componentStyles?: {
62
+ buttonVariant?: string | null;
63
+ buttonSize?: string | null;
64
+ cardStyle?: string | null;
65
+ cardHoverEffect?: string | null;
66
+ imageStyle?: string | null;
67
+ iconSet?: string | null;
68
+ navbarStyle?: string | null;
69
+ footerStyle?: string | null;
70
+ linkStyle?: string | null;
71
+ enableScrollReveal?: boolean | null;
72
+ enableHoverAnimations?: boolean | null;
73
+ } | null;
49
74
  }
50
75
  declare const BORDER_RADIUS_VALUES: readonly ["none", "small", "medium", "large", "xl"];
51
76
  declare const FONT_SCALE_VALUES: readonly ["small", "medium", "large"];
@@ -56,6 +81,27 @@ type FontScaleOption = (typeof FONT_SCALE_VALUES)[number];
56
81
  type SpacingOption = (typeof SPACING_VALUES)[number];
57
82
  type AnimationLevelOption = (typeof ANIMATION_LEVEL_VALUES)[number];
58
83
  type ThemeColorConfiguration = NonNullable<GenericThemeConfiguration['lightMode']>;
84
+ export interface ResolvedVisualEffects {
85
+ effectStyle?: string | null;
86
+ shadowIntensity?: string | null;
87
+ backdropBlur?: string | null;
88
+ borderStyle?: string | null;
89
+ borderWidth?: string | null;
90
+ glassOpacity?: number | null;
91
+ }
92
+ export interface ResolvedComponentStyles {
93
+ buttonVariant?: string | null;
94
+ buttonSize?: string | null;
95
+ cardStyle?: string | null;
96
+ cardHoverEffect?: string | null;
97
+ imageStyle?: string | null;
98
+ iconSet?: string | null;
99
+ navbarStyle?: string | null;
100
+ footerStyle?: string | null;
101
+ linkStyle?: string | null;
102
+ enableScrollReveal?: boolean | null;
103
+ enableHoverAnimations?: boolean | null;
104
+ }
59
105
  export interface ResolvedThemeConfiguration {
60
106
  theme: ThemeDefaults;
61
107
  colorMode: Mode;
@@ -68,8 +114,21 @@ export interface ResolvedThemeConfiguration {
68
114
  lightMode?: ThemeColorConfiguration;
69
115
  darkMode?: ThemeColorConfiguration;
70
116
  typography: ThemeTypographyPreset | null;
117
+ /**
118
+ * The body / heading font values picked in the admin ('Inter', 'Lora' …),
119
+ * kept so the font files can be requested (see `ServerThemeInjector`).
120
+ */
121
+ fontSelections?: string[];
122
+ /**
123
+ * True when the editor picked something in Typography (a font, size, line
124
+ * height, heading weight or tracking) instead of "Use theme preset". Base
125
+ * typography rules are only emitted then, so untouched sites render as before.
126
+ */
127
+ typographyOverridden?: boolean;
128
+ visualEffects?: ResolvedVisualEffects | null;
129
+ componentStyles?: ResolvedComponentStyles | null;
71
130
  }
72
131
  export declare const DEFAULT_THEME_CONFIGURATION: ResolvedThemeConfiguration;
73
- export declare function resolveThemeConfiguration(themeConfiguration?: GenericThemeConfiguration | null): ResolvedThemeConfiguration;
132
+ export declare function resolveThemeConfiguration(themeConfiguration?: unknown): ResolvedThemeConfiguration;
74
133
  export {};
75
134
  //# sourceMappingURL=resolveThemeConfiguration.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"resolveThemeConfiguration.d.ts","sourceRoot":"","sources":["../../src/utils/resolveThemeConfiguration.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,eAAe,CAAA;AAE1D,OAAO,KAAK,EAAE,IAAI,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAA;AAGtE;;;GAGG;AACH,UAAU,uBAAuB;IAC/B,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACxB,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC3B,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC9B,iBAAiB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACjC,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC5B,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CAC3B;AAED;;;GAGG;AACH,UAAU,yBAAyB;IACjC,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACrB,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACzB,oBAAoB,CAAC,EAAE,OAAO,GAAG,IAAI,CAAA;IACrC,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC5B,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACzB,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACvB,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC9B,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACzB,SAAS,CAAC,EAAE;QACV,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;QACvB,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;QACzB,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;QACtB,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;QACvB,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;QACvB,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;QACvB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;QACrB,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;KACrB,GAAG,IAAI,CAAA;IACR,QAAQ,CAAC,EAAE;QACT,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;QACvB,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;QACzB,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;QACtB,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;QACvB,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;QACvB,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;QACvB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;QACrB,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;KACrB,GAAG,IAAI,CAAA;IACR,UAAU,CAAC,EAAE,uBAAuB,GAAG,IAAI,CAAA;CAC5C;AAED,QAAA,MAAM,oBAAoB,qDAAsD,CAAA;AAIhF,QAAA,MAAM,iBAAiB,uCAAwC,CAAA;AAC/D,QAAA,MAAM,cAAc,4CAA6C,CAAA;AACjE,QAAA,MAAM,sBAAsB,gDAAiD,CAAA;AAM7E,KAAK,kBAAkB,GAAG,CAAC,OAAO,oBAAoB,CAAC,CAAC,MAAM,CAAC,CAAA;AAC/D,KAAK,eAAe,GAAG,CAAC,OAAO,iBAAiB,CAAC,CAAC,MAAM,CAAC,CAAA;AACzD,KAAK,aAAa,GAAG,CAAC,OAAO,cAAc,CAAC,CAAC,MAAM,CAAC,CAAA;AACpD,KAAK,oBAAoB,GAAG,CAAC,OAAO,sBAAsB,CAAC,CAAC,MAAM,CAAC,CAAA;AAInE,KAAK,uBAAuB,GAAG,WAAW,CAAC,yBAAyB,CAAC,WAAW,CAAC,CAAC,CAAA;AAKlF,MAAM,WAAW,0BAA0B;IACzC,KAAK,EAAE,aAAa,CAAA;IACpB,SAAS,EAAE,IAAI,CAAA;IACf,oBAAoB,EAAE,OAAO,CAAA;IAC7B,YAAY,EAAE,kBAAkB,CAAA;IAChC,SAAS,EAAE,eAAe,CAAA;IAC1B,OAAO,EAAE,aAAa,CAAA;IACtB,cAAc,EAAE,oBAAoB,CAAA;IACpC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;IACxB,SAAS,CAAC,EAAE,uBAAuB,CAAA;IACnC,QAAQ,CAAC,EAAE,uBAAuB,CAAA;IAClC,UAAU,EAAE,qBAAqB,GAAG,IAAI,CAAA;CACzC;AAED,eAAO,MAAM,2BAA2B,EAAE,0BAYzC,CAAA;AA4CD,wBAAgB,yBAAyB,CACvC,kBAAkB,CAAC,EAAE,yBAAyB,GAAG,IAAI,GACpD,0BAA0B,CA0D5B"}
1
+ {"version":3,"file":"resolveThemeConfiguration.d.ts","sourceRoot":"","sources":["../../src/utils/resolveThemeConfiguration.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import { FONT_VALUE_TO_CSS } from '../constants/themeFonts.js';
1
+ import { getFontCatalogEntry, LETTER_SPACING_TO_CSS, toFontSizeCss } from '../constants/themeFonts.js';
2
2
  import { allThemePresets } from '../presets.js';
3
3
  import { themeIsValid } from '../providers/Theme/types.js';
4
4
  const BORDER_RADIUS_VALUES = [
@@ -21,6 +21,10 @@ const SPACING_VALUES = [
21
21
  'medium',
22
22
  'spacious'
23
23
  ];
24
+ // Earlier versions stored the roomiest spacing option as 'comfortable'.
25
+ const LEGACY_SPACING_ALIASES = {
26
+ comfortable: 'spacious'
27
+ };
24
28
  const ANIMATION_LEVEL_VALUES = [
25
29
  'none',
26
30
  'reduced',
@@ -84,15 +88,17 @@ function isMode(value) {
84
88
  return typeof value === 'string' && MODE_VALUES.includes(value);
85
89
  }
86
90
  export function resolveThemeConfiguration(themeConfiguration) {
87
- if (!themeConfiguration) {
91
+ // Accept `unknown` so callers don't need to cast from app-specific payload-types
92
+ const cfg = themeConfiguration !== null && typeof themeConfiguration === 'object' && !Array.isArray(themeConfiguration) ? themeConfiguration : null;
93
+ if (!cfg) {
88
94
  return DEFAULT_THEME_CONFIGURATION;
89
95
  }
90
- const { theme, colorMode, allowColorModeToggle, borderRadius, fontScale, spacing, animationLevel, customCSS, lightMode, darkMode, typography } = themeConfiguration;
96
+ const { theme, colorMode, allowColorModeToggle, borderRadius, fontScale, spacing, animationLevel, customCSS, lightMode, darkMode, typography, visualEffects, componentStyles } = cfg;
91
97
  const resolvedTheme = typeof theme === 'string' && themeIsValid(theme) ? theme : DEFAULT_THEME_CONFIGURATION.theme;
92
98
  const resolvedMode = isMode(colorMode) ? colorMode : DEFAULT_THEME_CONFIGURATION.colorMode;
93
99
  const resolvedBorderRadius = resolveBorderRadius(borderRadius);
94
100
  const resolvedFontScale = isFontScale(fontScale) ? fontScale : DEFAULT_THEME_CONFIGURATION.fontScale;
95
- const resolvedSpacing = isSpacing(spacing) ? spacing : DEFAULT_THEME_CONFIGURATION.spacing;
101
+ const resolvedSpacing = isSpacing(spacing) ? spacing : typeof spacing === 'string' && LEGACY_SPACING_ALIASES[spacing] || DEFAULT_THEME_CONFIGURATION.spacing;
96
102
  const resolvedAnimationLevel = resolveAnimationLevel(animationLevel);
97
103
  const resolvedAllowToggle = typeof allowColorModeToggle === 'boolean' ? allowColorModeToggle : DEFAULT_THEME_CONFIGURATION.allowColorModeToggle;
98
104
  const resolvedCustomCSS = typeof customCSS === 'string' ? customCSS : null;
@@ -101,7 +107,26 @@ export function resolveThemeConfiguration(themeConfiguration) {
101
107
  const baseDarkMode = preset?.darkMode ?? DEFAULT_THEME_CONFIGURATION.darkMode;
102
108
  const resolvedLightMode = mergeColorModes(baseLightMode, lightMode);
103
109
  const resolvedDarkMode = mergeColorModes(baseDarkMode, darkMode);
104
- const resolvedTypography = mergeTypography(preset?.typography, typography) ?? preset?.typography ?? null;
110
+ // Accept an already-resolved configuration too (callers often resolve once and
111
+ // pass the result to several helpers): its typography is final, keep it as is.
112
+ const typographyIsResolved = typography !== null && typeof typography === 'object' && typeof typography.fontFamily === 'string';
113
+ const resolvedTypography = typographyIsResolved ? typography : mergeTypography(preset?.typography, typography) ?? preset?.typography ?? null;
114
+ const isSet = (value)=>typeof value === 'string' && value !== '' && value !== 'preset';
115
+ const typographyOverridden = typographyIsResolved ? cfg.typographyOverridden === true : Boolean(typography && [
116
+ typography.bodyFont,
117
+ typography.headingFont,
118
+ typography.baseFontSize,
119
+ typography.lineHeight,
120
+ typography.headingWeight,
121
+ typography.letterSpacing
122
+ ].some(isSet));
123
+ const fontSelections = typographyIsResolved ? cfg.fontSelections ?? [] : [
124
+ typography?.bodyFont,
125
+ typography?.headingFont
126
+ ].filter((value)=>typeof value === 'string' && value !== 'preset' && value !== 'custom');
127
+ // Pass visualEffects and componentStyles through as-is (no normalization needed)
128
+ const resolvedVisualEffects = visualEffects ?? null;
129
+ const resolvedComponentStyles = componentStyles ?? null;
105
130
  return {
106
131
  theme: resolvedTheme,
107
132
  colorMode: resolvedMode,
@@ -113,7 +138,11 @@ export function resolveThemeConfiguration(themeConfiguration) {
113
138
  customCSS: resolvedCustomCSS,
114
139
  lightMode: resolvedLightMode,
115
140
  darkMode: resolvedDarkMode,
116
- typography: resolvedTypography
141
+ typography: resolvedTypography,
142
+ fontSelections,
143
+ typographyOverridden,
144
+ visualEffects: resolvedVisualEffects,
145
+ componentStyles: resolvedComponentStyles
117
146
  };
118
147
  }
119
148
  function mergeColorModes(base, overrides) {
@@ -141,10 +170,13 @@ function mergeTypography(base, overrides) {
141
170
  return base ?? null;
142
171
  }
143
172
  const result = {
144
- fontFamily: base?.fontFamily ?? 'var(--font-geist-sans)',
145
- headingFamily: base?.headingFamily ?? 'var(--font-geist-sans)',
146
- baseFontSize: base?.baseFontSize ?? '16px',
173
+ fontFamily: base?.fontFamily ?? 'var(--font-inter, var(--font-geist-sans), system-ui, sans-serif)',
174
+ headingFamily: base?.headingFamily ?? 'var(--font-outfit, var(--font-geist-sans), system-ui, sans-serif)',
175
+ baseFontSize: toFontSizeCss(base?.baseFontSize) ?? '16px',
147
176
  lineHeight: base?.lineHeight ?? '1.6',
177
+ headingWeight: base?.headingWeight,
178
+ headingLetterSpacing: base?.headingLetterSpacing,
179
+ headingTransform: base?.headingTransform,
148
180
  fontWeights: {
149
181
  ...base?.fontWeights ?? {}
150
182
  },
@@ -161,12 +193,21 @@ function mergeTypography(base, overrides) {
161
193
  if (resolvedHeadingFont) {
162
194
  result.headingFamily = resolvedHeadingFont;
163
195
  }
164
- if (overrides.baseFontSize && overrides.baseFontSize !== 'preset') {
165
- result.baseFontSize = overrides.baseFontSize;
196
+ const baseFontSize = toFontSizeCss(overrides.baseFontSize);
197
+ if (baseFontSize) {
198
+ result.baseFontSize = baseFontSize;
166
199
  }
167
200
  if (overrides.lineHeight && overrides.lineHeight !== 'preset') {
168
201
  result.lineHeight = overrides.lineHeight;
169
202
  }
203
+ if (overrides.headingWeight && overrides.headingWeight !== 'preset') {
204
+ result.headingWeight = overrides.headingWeight;
205
+ }
206
+ const tracking = overrides.letterSpacing ? LETTER_SPACING_TO_CSS[overrides.letterSpacing] : undefined;
207
+ if (tracking !== undefined) {
208
+ result.headingLetterSpacing = tracking;
209
+ result.headingTransform = overrides.letterSpacing === 'wider' ? 'uppercase' : 'none';
210
+ }
170
211
  }
171
212
  return result;
172
213
  }
@@ -178,8 +219,7 @@ function resolveFontSelection(selection, custom, fallback) {
178
219
  const trimmed = custom?.trim();
179
220
  return trimmed && trimmed.length > 0 ? trimmed : fallback ?? null;
180
221
  }
181
- const mapped = FONT_VALUE_TO_CSS[selection];
182
- return mapped ?? fallback ?? null;
222
+ return getFontCatalogEntry(selection)?.fontFamily ?? fallback ?? null;
183
223
  }
184
224
 
185
225
  //# sourceMappingURL=resolveThemeConfiguration.js.map