@kilivi/payloadcms-theme-management 1.1.2 → 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 +130 -32
  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 +30 -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
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/globals/ThemeSettings/config.ts"],"sourcesContent":["import type { GlobalConfig } from 'payload'\n\n/**\n * ThemeSettings Global Configuration\n *\n * This global stores theme-related settings including:\n * - Active font family (selected via FontPicker)\n * - Google Fonts API key (optional, for extended font library)\n */\nexport const ThemeSettings: GlobalConfig = {\n slug: 'themeSettings',\n label: { en: 'Theme Settings', cs: 'Nastavení témat' },\n admin: {\n group: { en: 'Settings', cs: 'Nastavení' },\n },\n access: {\n read: () => true,\n update: ({ req }) => {\n // Only admins can update theme settings\n return req.user?.roles?.includes('admin') || false\n },\n },\n fields: [\n {\n type: 'tabs',\n tabs: [\n {\n label: { en: 'Typography', cs: 'Typografie' },\n fields: [\n {\n name: 'activeFont',\n type: 'text',\n label: { en: 'Active Font Family', cs: 'Aktivní rodina písem' },\n defaultValue: 'Inter',\n admin: {\n description: {\n en: 'The currently active font family for your website',\n cs: 'Aktuální rodina písem pro váš web',\n },\n components: {\n Field: '@kilivi/payloadcms-theme-management/globals/ThemeSettings/FontPicker',\n },\n },\n },\n {\n name: 'googleFontsApiKey',\n type: 'text',\n label: { en: 'Google Fonts API Key', cs: 'Google Fonts API klíč' },\n admin: {\n description: {\n en: \"Optional: Add your Google Fonts API key to access the full library of 1400+ fonts. Without this, you'll have access to 35 popular fonts.\",\n cs: 'Volitelné: přidejte svůj Google Fonts API klíč pro přístup k plné knihovně 1400+ písem. Bez něj máte k dispozici 35 populárních písem.',\n },\n placeholder: 'AIzaSy...',\n },\n },\n\n {\n type: 'row',\n fields: [\n {\n name: 'fontWeightHeading',\n type: 'select',\n label: 'Heading Font Weight',\n defaultValue: '700',\n options: [\n { label: '100 - Thin', value: '100' },\n { label: '200 - Extra Light', value: '200' },\n { label: '300 - Light', value: '300' },\n { label: '400 - Regular', value: '400' },\n { label: '500 - Medium', value: '500' },\n { label: '600 - Semi Bold', value: '600' },\n { label: '700 - Bold', value: '700' },\n { label: '800 - Extra Bold', value: '800' },\n { label: '900 - Black', value: '900' },\n ],\n },\n {\n name: 'fontWeightBody',\n type: 'select',\n label: 'Body Font Weight',\n defaultValue: '400',\n options: [\n { label: '100 - Thin', value: '100' },\n { label: '200 - Extra Light', value: '200' },\n { label: '300 - Light', value: '300' },\n { label: '400 - Regular', value: '400' },\n { label: '500 - Medium', value: '500' },\n { label: '600 - Semi Bold', value: '600' },\n { label: '700 - Bold', value: '700' },\n { label: '800 - Extra Bold', value: '800' },\n { label: '900 - Black', value: '900' },\n ],\n },\n ],\n },\n {\n type: 'ui',\n name: 'typographyInfo',\n admin: {\n components: {\n Field:\n '@kilivi/payloadcms-theme-management/globals/ThemeSettings/fields/TypographyInfoField',\n },\n },\n },\n ],\n },\n {\n label: { en: 'Font Loading', cs: 'Načítání písem' },\n fields: [\n {\n type: 'ui',\n name: 'fontLoadingGuide',\n admin: {\n components: {\n Field:\n '@kilivi/payloadcms-theme-management/globals/ThemeSettings/fields/FontLoadingGuideField',\n },\n },\n },\n ],\n },\n ],\n },\n ],\n}\n"],"names":["ThemeSettings","slug","label","en","cs","admin","group","access","read","update","req","user","roles","includes","fields","type","tabs","name","defaultValue","description","components","Field","placeholder","options","value"],"mappings":"AAEA;;;;;;CAMC,GACD,OAAO,MAAMA,gBAA8B;IACzCC,MAAM;IACNC,OAAO;QAAEC,IAAI;QAAkBC,IAAI;IAAkB;IACrDC,OAAO;QACLC,OAAO;YAAEH,IAAI;YAAYC,IAAI;QAAY;IAC3C;IACAG,QAAQ;QACNC,MAAM,IAAM;QACZC,QAAQ,CAAC,EAAEC,GAAG,EAAE;YACd,wCAAwC;YACxC,OAAOA,IAAIC,IAAI,EAAEC,OAAOC,SAAS,YAAY;QAC/C;IACF;IACAC,QAAQ;QACN;YACEC,MAAM;YACNC,MAAM;gBACJ;oBACEd,OAAO;wBAAEC,IAAI;wBAAcC,IAAI;oBAAa;oBAC5CU,QAAQ;wBACN;4BACEG,MAAM;4BACNF,MAAM;4BACNb,OAAO;gCAAEC,IAAI;gCAAsBC,IAAI;4BAAuB;4BAC9Dc,cAAc;4BACdb,OAAO;gCACLc,aAAa;oCACXhB,IAAI;oCACJC,IAAI;gCACN;gCACAgB,YAAY;oCACVC,OAAO;gCACT;4BACF;wBACF;wBACA;4BACEJ,MAAM;4BACNF,MAAM;4BACNb,OAAO;gCAAEC,IAAI;gCAAwBC,IAAI;4BAAwB;4BACjEC,OAAO;gCACLc,aAAa;oCACXhB,IAAI;oCACJC,IAAI;gCACN;gCACAkB,aAAa;4BACf;wBACF;wBAEA;4BACEP,MAAM;4BACND,QAAQ;gCACN;oCACEG,MAAM;oCACNF,MAAM;oCACNb,OAAO;oCACPgB,cAAc;oCACdK,SAAS;wCACP;4CAAErB,OAAO;4CAAcsB,OAAO;wCAAM;wCACpC;4CAAEtB,OAAO;4CAAqBsB,OAAO;wCAAM;wCAC3C;4CAAEtB,OAAO;4CAAesB,OAAO;wCAAM;wCACrC;4CAAEtB,OAAO;4CAAiBsB,OAAO;wCAAM;wCACvC;4CAAEtB,OAAO;4CAAgBsB,OAAO;wCAAM;wCACtC;4CAAEtB,OAAO;4CAAmBsB,OAAO;wCAAM;wCACzC;4CAAEtB,OAAO;4CAAcsB,OAAO;wCAAM;wCACpC;4CAAEtB,OAAO;4CAAoBsB,OAAO;wCAAM;wCAC1C;4CAAEtB,OAAO;4CAAesB,OAAO;wCAAM;qCACtC;gCACH;gCACA;oCACEP,MAAM;oCACNF,MAAM;oCACNb,OAAO;oCACPgB,cAAc;oCACdK,SAAS;wCACP;4CAAErB,OAAO;4CAAcsB,OAAO;wCAAM;wCACpC;4CAAEtB,OAAO;4CAAqBsB,OAAO;wCAAM;wCAC3C;4CAAEtB,OAAO;4CAAesB,OAAO;wCAAM;wCACrC;4CAAEtB,OAAO;4CAAiBsB,OAAO;wCAAM;wCACvC;4CAAEtB,OAAO;4CAAgBsB,OAAO;wCAAM;wCACtC;4CAAEtB,OAAO;4CAAmBsB,OAAO;wCAAM;wCACzC;4CAAEtB,OAAO;4CAAcsB,OAAO;wCAAM;wCACpC;4CAAEtB,OAAO;4CAAoBsB,OAAO;wCAAM;wCAC1C;4CAAEtB,OAAO;4CAAesB,OAAO;wCAAM;qCACtC;gCACH;6BACD;wBACH;wBACA;4BACET,MAAM;4BACNE,MAAM;4BACNZ,OAAO;gCACLe,YAAY;oCACVC,OACE;gCACJ;4BACF;wBACF;qBACD;gBACH;gBACA;oBACEnB,OAAO;wBAAEC,IAAI;wBAAgBC,IAAI;oBAAiB;oBAClDU,QAAQ;wBACN;4BACEC,MAAM;4BACNE,MAAM;4BACNZ,OAAO;gCACLe,YAAY;oCACVC,OACE;gCACJ;4BACF;wBACF;qBACD;gBACH;aACD;QACH;KACD;AACH,EAAC"}
1
+ {"version":3,"sources":["../../../src/globals/ThemeSettings/config.ts"],"sourcesContent":["import type { GlobalConfig } from 'payload'\n\nconst fontWeightOptions = [\n { value: '100', label: { en: '100 – Thin', cs: '100 – Vlasové' } },\n { value: '200', label: { en: '200 – Extra light', cs: '200 – Extra tenké' } },\n { value: '300', label: { en: '300 – Light', cs: '300 – Tenké' } },\n { value: '400', label: { en: '400 – Regular', cs: '400 – Normální' } },\n { value: '500', label: { en: '500 – Medium', cs: '500 – Střední' } },\n { value: '600', label: { en: '600 – Semi bold', cs: '600 – Polotučné' } },\n { value: '700', label: { en: '700 – Bold', cs: '700 – Tučné' } },\n { value: '800', label: { en: '800 – Extra bold', cs: '800 – Extra tučné' } },\n { value: '900', label: { en: '900 – Black', cs: '900 – Černé' } },\n]\n\n/**\n * ThemeSettings Global Configuration\n *\n * This global stores theme-related settings including:\n * - Active font family (selected via FontPicker)\n * - Google Fonts API key (optional, for extended font library)\n */\nexport const ThemeSettings: GlobalConfig = {\n slug: 'themeSettings',\n label: { en: 'Theme Settings', cs: 'Nastavení motivu' },\n admin: {\n group: { en: 'Settings', cs: 'Nastavení' },\n },\n access: {\n read: () => true,\n update: ({ req }) => {\n // Only admins can update theme settings\n return req.user?.roles?.includes('admin') || false\n },\n },\n fields: [\n {\n type: 'tabs',\n tabs: [\n {\n label: { en: 'Typography', cs: 'Typografie' },\n fields: [\n {\n name: 'activeFont',\n type: 'text',\n label: { en: 'Active Font Family', cs: 'Aktivní rodina písem' },\n defaultValue: 'Inter',\n admin: {\n description: {\n en: 'The currently active font family for your website',\n cs: 'Aktuální rodina písem pro váš web',\n },\n components: {\n Field: '@kilivi/payloadcms-theme-management/globals/ThemeSettings/FontPicker',\n },\n },\n },\n {\n name: 'googleFontsApiKey',\n type: 'text',\n label: { en: 'Google Fonts API Key', cs: 'Google Fonts API klíč' },\n admin: {\n description: {\n en: \"Optional: Add your Google Fonts API key to access the full library of 1400+ fonts. Without this, you'll have access to 35 popular fonts.\",\n cs: 'Volitelné: přidejte svůj Google Fonts API klíč pro přístup k plné knihovně 1400+ písem. Bez něj máte k dispozici 35 populárních písem.',\n },\n placeholder: 'AIzaSy...',\n },\n },\n\n {\n type: 'row',\n fields: [\n {\n name: 'fontWeightHeading',\n type: 'select',\n label: { en: 'Heading font weight', cs: 'Tloušťka písma nadpisů' },\n defaultValue: '700',\n options: fontWeightOptions,\n },\n {\n name: 'fontWeightBody',\n type: 'select',\n label: { en: 'Body font weight', cs: 'Tloušťka písma textu' },\n defaultValue: '400',\n options: fontWeightOptions,\n },\n ],\n },\n {\n type: 'ui',\n name: 'typographyInfo',\n admin: {\n components: {\n Field:\n '@kilivi/payloadcms-theme-management/globals/ThemeSettings/fields/TypographyInfoField',\n },\n },\n },\n ],\n },\n {\n label: { en: 'Font Loading', cs: 'Načítání písem' },\n fields: [\n {\n type: 'ui',\n name: 'fontLoadingGuide',\n admin: {\n components: {\n Field:\n '@kilivi/payloadcms-theme-management/globals/ThemeSettings/fields/FontLoadingGuideField',\n },\n },\n },\n ],\n },\n ],\n },\n ],\n}\n"],"names":["fontWeightOptions","value","label","en","cs","ThemeSettings","slug","admin","group","access","read","update","req","user","roles","includes","fields","type","tabs","name","defaultValue","description","components","Field","placeholder","options"],"mappings":"AAEA,MAAMA,oBAAoB;IACxB;QAAEC,OAAO;QAAOC,OAAO;YAAEC,IAAI;YAAcC,IAAI;QAAgB;IAAE;IACjE;QAAEH,OAAO;QAAOC,OAAO;YAAEC,IAAI;YAAqBC,IAAI;QAAoB;IAAE;IAC5E;QAAEH,OAAO;QAAOC,OAAO;YAAEC,IAAI;YAAeC,IAAI;QAAc;IAAE;IAChE;QAAEH,OAAO;QAAOC,OAAO;YAAEC,IAAI;YAAiBC,IAAI;QAAiB;IAAE;IACrE;QAAEH,OAAO;QAAOC,OAAO;YAAEC,IAAI;YAAgBC,IAAI;QAAgB;IAAE;IACnE;QAAEH,OAAO;QAAOC,OAAO;YAAEC,IAAI;YAAmBC,IAAI;QAAkB;IAAE;IACxE;QAAEH,OAAO;QAAOC,OAAO;YAAEC,IAAI;YAAcC,IAAI;QAAc;IAAE;IAC/D;QAAEH,OAAO;QAAOC,OAAO;YAAEC,IAAI;YAAoBC,IAAI;QAAoB;IAAE;IAC3E;QAAEH,OAAO;QAAOC,OAAO;YAAEC,IAAI;YAAeC,IAAI;QAAc;IAAE;CACjE;AAED;;;;;;CAMC,GACD,OAAO,MAAMC,gBAA8B;IACzCC,MAAM;IACNJ,OAAO;QAAEC,IAAI;QAAkBC,IAAI;IAAmB;IACtDG,OAAO;QACLC,OAAO;YAAEL,IAAI;YAAYC,IAAI;QAAY;IAC3C;IACAK,QAAQ;QACNC,MAAM,IAAM;QACZC,QAAQ,CAAC,EAAEC,GAAG,EAAE;YACd,wCAAwC;YACxC,OAAOA,IAAIC,IAAI,EAAEC,OAAOC,SAAS,YAAY;QAC/C;IACF;IACAC,QAAQ;QACN;YACEC,MAAM;YACNC,MAAM;gBACJ;oBACEhB,OAAO;wBAAEC,IAAI;wBAAcC,IAAI;oBAAa;oBAC5CY,QAAQ;wBACN;4BACEG,MAAM;4BACNF,MAAM;4BACNf,OAAO;gCAAEC,IAAI;gCAAsBC,IAAI;4BAAuB;4BAC9DgB,cAAc;4BACdb,OAAO;gCACLc,aAAa;oCACXlB,IAAI;oCACJC,IAAI;gCACN;gCACAkB,YAAY;oCACVC,OAAO;gCACT;4BACF;wBACF;wBACA;4BACEJ,MAAM;4BACNF,MAAM;4BACNf,OAAO;gCAAEC,IAAI;gCAAwBC,IAAI;4BAAwB;4BACjEG,OAAO;gCACLc,aAAa;oCACXlB,IAAI;oCACJC,IAAI;gCACN;gCACAoB,aAAa;4BACf;wBACF;wBAEA;4BACEP,MAAM;4BACND,QAAQ;gCACN;oCACEG,MAAM;oCACNF,MAAM;oCACNf,OAAO;wCAAEC,IAAI;wCAAuBC,IAAI;oCAAyB;oCACjEgB,cAAc;oCACdK,SAASzB;gCACX;gCACA;oCACEmB,MAAM;oCACNF,MAAM;oCACNf,OAAO;wCAAEC,IAAI;wCAAoBC,IAAI;oCAAuB;oCAC5DgB,cAAc;oCACdK,SAASzB;gCACX;6BACD;wBACH;wBACA;4BACEiB,MAAM;4BACNE,MAAM;4BACNZ,OAAO;gCACLe,YAAY;oCACVC,OACE;gCACJ;4BACF;wBACF;qBACD;gBACH;gBACA;oBACErB,OAAO;wBAAEC,IAAI;wBAAgBC,IAAI;oBAAiB;oBAClDY,QAAQ;wBACN;4BACEC,MAAM;4BACNE,MAAM;4BACNZ,OAAO;gCACLe,YAAY;oCACVC,OACE;gCACJ;4BACF;wBACF;qBACD;gBACH;aACD;QACH;KACD;AACH,EAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"FontLoadingGuideField.d.ts","sourceRoot":"","sources":["../../../../src/globals/ThemeSettings/fields/FontLoadingGuideField.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAA;AACjD,OAAO,KAAK,MAAM,OAAO,CAAA;AAEzB,QAAA,MAAM,qBAAqB,EAAE,KAAK,CAAC,EAAE,CAAC,kBAAkB,CAmHvD,CAAA;AAED,eAAe,qBAAqB,CAAA"}
1
+ {"version":3,"file":"FontLoadingGuideField.d.ts","sourceRoot":"","sources":["../../../../src/globals/ThemeSettings/fields/FontLoadingGuideField.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAA;AACjD,OAAO,KAAK,MAAM,OAAO,CAAA;AA+BzB,QAAA,MAAM,qBAAqB,EAAE,KAAK,CAAC,EAAE,CAAC,kBAAkB,CA8FvD,CAAA;AAED,eAAe,qBAAqB,CAAA"}
@@ -1,10 +1,39 @@
1
1
  'use client';
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { Globe, Package } from 'lucide-react';
3
4
  import React from 'react';
5
+ import { useThemeTranslations } from '../../../hooks/useThemeTranslations.js';
6
+ const PRE_IMPORTED_FONTS = [
7
+ 'Inter',
8
+ 'Nunito',
9
+ 'Montserrat',
10
+ 'Manrope',
11
+ 'Mulish',
12
+ 'Barlow',
13
+ 'Raleway',
14
+ 'Playfair Display'
15
+ ];
16
+ const calloutStyle = {
17
+ background: 'var(--theme-elevation-50)',
18
+ border: '1px solid var(--theme-elevation-150)',
19
+ borderRadius: '8px',
20
+ padding: '16px',
21
+ marginBottom: '24px'
22
+ };
23
+ const calloutHeadingStyle = {
24
+ display: 'flex',
25
+ alignItems: 'center',
26
+ gap: '8px',
27
+ margin: '0 0 8px 0',
28
+ fontSize: '16px',
29
+ fontWeight: 600
30
+ };
4
31
  const FontLoadingGuideField = ()=>{
32
+ const t = useThemeTranslations().fontGuide;
5
33
  return /*#__PURE__*/ _jsxs("div", {
6
34
  style: {
7
- padding: '24px'
35
+ padding: '24px',
36
+ color: 'var(--theme-text)'
8
37
  },
9
38
  children: [
10
39
  /*#__PURE__*/ _jsx("h2", {
@@ -13,24 +42,21 @@ const FontLoadingGuideField = ()=>{
13
42
  fontSize: '20px',
14
43
  fontWeight: 700
15
44
  },
16
- children: "Font Loading Strategy"
45
+ children: t.strategyTitle
17
46
  }),
18
47
  /*#__PURE__*/ _jsxs("div", {
19
- style: {
20
- background: '#eff6ff',
21
- border: '1px solid #bfdbfe',
22
- borderRadius: '8px',
23
- padding: '16px',
24
- marginBottom: '24px'
25
- },
48
+ style: calloutStyle,
26
49
  children: [
27
- /*#__PURE__*/ _jsx("h3", {
28
- style: {
29
- margin: '0 0 8px 0',
30
- fontSize: '16px',
31
- fontWeight: 600
32
- },
33
- children: "📦 Pre-imported Fonts (Optimized)"
50
+ /*#__PURE__*/ _jsxs("h3", {
51
+ style: calloutHeadingStyle,
52
+ children: [
53
+ /*#__PURE__*/ _jsx(Package, {
54
+ size: 16,
55
+ color: "var(--theme-success-600)",
56
+ "aria-hidden": true
57
+ }),
58
+ t.preImportedTitle
59
+ ]
34
60
  }),
35
61
  /*#__PURE__*/ _jsx("p", {
36
62
  style: {
@@ -38,59 +64,33 @@ const FontLoadingGuideField = ()=>{
38
64
  fontSize: '14px',
39
65
  lineHeight: '1.6'
40
66
  },
41
- children: "These 8 popular fonts are pre-optimized via next/font/google for zero runtime loading:"
67
+ children: t.preImportedCopy
42
68
  }),
43
- /*#__PURE__*/ _jsxs("ul", {
69
+ /*#__PURE__*/ _jsx("ul", {
44
70
  style: {
45
71
  margin: 0,
46
72
  paddingLeft: '20px',
47
73
  fontSize: '14px'
48
74
  },
49
- children: [
50
- /*#__PURE__*/ _jsx("li", {
51
- children: "Inter"
52
- }),
53
- /*#__PURE__*/ _jsx("li", {
54
- children: "Nunito"
55
- }),
56
- /*#__PURE__*/ _jsx("li", {
57
- children: "Montserrat"
58
- }),
59
- /*#__PURE__*/ _jsx("li", {
60
- children: "Manrope"
61
- }),
62
- /*#__PURE__*/ _jsx("li", {
63
- children: "Mulish"
64
- }),
65
- /*#__PURE__*/ _jsx("li", {
66
- children: "Barlow"
67
- }),
68
- /*#__PURE__*/ _jsx("li", {
69
- children: "Raleway"
70
- }),
71
- /*#__PURE__*/ _jsx("li", {
72
- children: "Playfair Display"
73
- })
74
- ]
75
+ children: PRE_IMPORTED_FONTS.map((font)=>/*#__PURE__*/ _jsx("li", {
76
+ children: font
77
+ }, font))
75
78
  })
76
79
  ]
77
80
  }),
78
81
  /*#__PURE__*/ _jsxs("div", {
79
- style: {
80
- background: '#fef3c7',
81
- border: '1px solid #fde68a',
82
- borderRadius: '8px',
83
- padding: '16px',
84
- marginBottom: '24px'
85
- },
82
+ style: calloutStyle,
86
83
  children: [
87
- /*#__PURE__*/ _jsx("h3", {
88
- style: {
89
- margin: '0 0 8px 0',
90
- fontSize: '16px',
91
- fontWeight: 600
92
- },
93
- children: "🌐 Dynamic Fonts (Google Fonts CSS)"
84
+ /*#__PURE__*/ _jsxs("h3", {
85
+ style: calloutHeadingStyle,
86
+ children: [
87
+ /*#__PURE__*/ _jsx(Globe, {
88
+ size: 16,
89
+ color: "var(--theme-warning-600)",
90
+ "aria-hidden": true
91
+ }),
92
+ t.dynamicTitle
93
+ ]
94
94
  }),
95
95
  /*#__PURE__*/ _jsx("p", {
96
96
  style: {
@@ -98,7 +98,7 @@ const FontLoadingGuideField = ()=>{
98
98
  fontSize: '14px',
99
99
  lineHeight: '1.6'
100
100
  },
101
- children: "Other fonts are loaded dynamically via Google Fonts CSS link. This provides access to 1400+ fonts but requires runtime loading."
101
+ children: t.dynamicCopy
102
102
  })
103
103
  ]
104
104
  }),
@@ -108,12 +108,13 @@ const FontLoadingGuideField = ()=>{
108
108
  fontWeight: 600,
109
109
  marginBottom: '12px'
110
110
  },
111
- children: "Implementation Example"
111
+ children: t.exampleTitle
112
112
  }),
113
113
  /*#__PURE__*/ _jsx("pre", {
114
114
  style: {
115
- background: '#1f2937',
116
- color: '#f9fafb',
115
+ // Inverted elevation tokens: the code block contrasts with the page in both admin themes.
116
+ background: 'var(--theme-elevation-900)',
117
+ color: 'var(--theme-elevation-50)',
117
118
  padding: '16px',
118
119
  borderRadius: '8px',
119
120
  fontSize: '13px',
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/globals/ThemeSettings/fields/FontLoadingGuideField.tsx"],"sourcesContent":["'use client'\n\nimport type { UIFieldClientProps } from 'payload'\nimport React from 'react'\n\nconst FontLoadingGuideField: React.FC<UIFieldClientProps> = () => {\n return (\n <div style={{ padding: '24px' }}>\n <h2 style={{ marginTop: 0, fontSize: '20px', fontWeight: 700 }}>Font Loading Strategy</h2>\n\n <div\n style={{\n background: '#eff6ff',\n border: '1px solid #bfdbfe',\n borderRadius: '8px',\n padding: '16px',\n marginBottom: '24px',\n }}\n >\n <h3 style={{ margin: '0 0 8px 0', fontSize: '16px', fontWeight: 600 }}>\n 📦 Pre-imported Fonts (Optimized)\n </h3>\n <p style={{ margin: '0 0 12px 0', fontSize: '14px', lineHeight: '1.6' }}>\n These 8 popular fonts are pre-optimized via next/font/google for zero runtime loading:\n </p>\n <ul style={{ margin: 0, paddingLeft: '20px', fontSize: '14px' }}>\n <li>Inter</li>\n <li>Nunito</li>\n <li>Montserrat</li>\n <li>Manrope</li>\n <li>Mulish</li>\n <li>Barlow</li>\n <li>Raleway</li>\n <li>Playfair Display</li>\n </ul>\n </div>\n\n <div\n style={{\n background: '#fef3c7',\n border: '1px solid #fde68a',\n borderRadius: '8px',\n padding: '16px',\n marginBottom: '24px',\n }}\n >\n <h3 style={{ margin: '0 0 8px 0', fontSize: '16px', fontWeight: 600 }}>\n 🌐 Dynamic Fonts (Google Fonts CSS)\n </h3>\n <p style={{ margin: 0, fontSize: '14px', lineHeight: '1.6' }}>\n Other fonts are loaded dynamically via Google Fonts CSS link. This provides access to\n 1400+ fonts but requires runtime loading.\n </p>\n </div>\n\n <h3 style={{ fontSize: '16px', fontWeight: 600, marginBottom: '12px' }}>\n Implementation Example\n </h3>\n <pre\n style={{\n background: '#1f2937',\n color: '#f9fafb',\n padding: '16px',\n borderRadius: '8px',\n fontSize: '13px',\n overflowX: 'auto',\n lineHeight: '1.6',\n }}\n >\n {`// app/layout.tsx\nimport { Inter, Nunito, Montserrat } from 'next/font/google'\nimport { getThemeSettings } from '@/utilities/getThemeSettings'\n\nconst inter = Inter({ subsets: ['latin'], variable: '--font-inter' })\nconst nunito = Nunito({ subsets: ['latin'], variable: '--font-nunito' })\nconst montserrat = Montserrat({ subsets: ['latin'], variable: '--font-montserrat' })\n\nexport default async function RootLayout({ children }) {\n const themeSettings = await getThemeSettings()\n const activeFont = themeSettings?.activeFont || 'Inter'\n \n const fontMap = {\n 'Inter': inter.variable,\n 'Nunito': nunito.variable,\n 'Montserrat': montserrat.variable,\n // ... other pre-imported fonts\n }\n \n const selectedFontClass = fontMap[activeFont] || ''\n const isDynamicFont = !selectedFontClass\n \n return (\n <html className={selectedFontClass || ''} \n style={isDynamicFont ? {\n '--font-primary': \\`'\\${activeFont}', sans-serif\\`\n } : undefined}>\n <head>\n {isDynamicFont && (\n <>\n <link rel=\"preconnect\" href=\"https://fonts.googleapis.com\" />\n <link rel=\"preconnect\" href=\"https://fonts.gstatic.com\" crossOrigin=\"\" />\n <link \n href={\\`https://fonts.googleapis.com/css2?family=\\${activeFont.replace(' ', '+')}:wght@300;400;500;600;700&display=swap\\`}\n rel=\"stylesheet\" \n />\n </>\n )}\n </head>\n <body className=\"font-primary\">{children}</body>\n </html>\n )\n}\n\n// CSS\n.font-primary {\n font-family: var(--font-primary, 'Inter', sans-serif);\n}`}\n </pre>\n </div>\n )\n}\n\nexport default FontLoadingGuideField\n"],"names":["React","FontLoadingGuideField","div","style","padding","h2","marginTop","fontSize","fontWeight","background","border","borderRadius","marginBottom","h3","margin","p","lineHeight","ul","paddingLeft","li","pre","color","overflowX"],"mappings":"AAAA;;AAGA,OAAOA,WAAW,QAAO;AAEzB,MAAMC,wBAAsD;IAC1D,qBACE,MAACC;QAAIC,OAAO;YAAEC,SAAS;QAAO;;0BAC5B,KAACC;gBAAGF,OAAO;oBAAEG,WAAW;oBAAGC,UAAU;oBAAQC,YAAY;gBAAI;0BAAG;;0BAEhE,MAACN;gBACCC,OAAO;oBACLM,YAAY;oBACZC,QAAQ;oBACRC,cAAc;oBACdP,SAAS;oBACTQ,cAAc;gBAChB;;kCAEA,KAACC;wBAAGV,OAAO;4BAAEW,QAAQ;4BAAaP,UAAU;4BAAQC,YAAY;wBAAI;kCAAG;;kCAGvE,KAACO;wBAAEZ,OAAO;4BAAEW,QAAQ;4BAAcP,UAAU;4BAAQS,YAAY;wBAAM;kCAAG;;kCAGzE,MAACC;wBAAGd,OAAO;4BAAEW,QAAQ;4BAAGI,aAAa;4BAAQX,UAAU;wBAAO;;0CAC5D,KAACY;0CAAG;;0CACJ,KAACA;0CAAG;;0CACJ,KAACA;0CAAG;;0CACJ,KAACA;0CAAG;;0CACJ,KAACA;0CAAG;;0CACJ,KAACA;0CAAG;;0CACJ,KAACA;0CAAG;;0CACJ,KAACA;0CAAG;;;;;;0BAIR,MAACjB;gBACCC,OAAO;oBACLM,YAAY;oBACZC,QAAQ;oBACRC,cAAc;oBACdP,SAAS;oBACTQ,cAAc;gBAChB;;kCAEA,KAACC;wBAAGV,OAAO;4BAAEW,QAAQ;4BAAaP,UAAU;4BAAQC,YAAY;wBAAI;kCAAG;;kCAGvE,KAACO;wBAAEZ,OAAO;4BAAEW,QAAQ;4BAAGP,UAAU;4BAAQS,YAAY;wBAAM;kCAAG;;;;0BAMhE,KAACH;gBAAGV,OAAO;oBAAEI,UAAU;oBAAQC,YAAY;oBAAKI,cAAc;gBAAO;0BAAG;;0BAGxE,KAACQ;gBACCjB,OAAO;oBACLM,YAAY;oBACZY,OAAO;oBACPjB,SAAS;oBACTO,cAAc;oBACdJ,UAAU;oBACVe,WAAW;oBACXN,YAAY;gBACd;0BAEC,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA+CT,CAAC;;;;AAIF;AAEA,eAAef,sBAAqB"}
1
+ {"version":3,"sources":["../../../../src/globals/ThemeSettings/fields/FontLoadingGuideField.tsx"],"sourcesContent":["'use client'\n\nimport { Globe, Package } from 'lucide-react'\nimport type { UIFieldClientProps } from 'payload'\nimport React from 'react'\nimport { useThemeTranslations } from '../../../hooks/useThemeTranslations.js'\n\nconst PRE_IMPORTED_FONTS = [\n 'Inter',\n 'Nunito',\n 'Montserrat',\n 'Manrope',\n 'Mulish',\n 'Barlow',\n 'Raleway',\n 'Playfair Display',\n]\n\nconst calloutStyle: React.CSSProperties = {\n background: 'var(--theme-elevation-50)',\n border: '1px solid var(--theme-elevation-150)',\n borderRadius: '8px',\n padding: '16px',\n marginBottom: '24px',\n}\n\nconst calloutHeadingStyle: React.CSSProperties = {\n display: 'flex',\n alignItems: 'center',\n gap: '8px',\n margin: '0 0 8px 0',\n fontSize: '16px',\n fontWeight: 600,\n}\n\nconst FontLoadingGuideField: React.FC<UIFieldClientProps> = () => {\n const t = useThemeTranslations().fontGuide\n\n return (\n <div style={{ padding: '24px', color: 'var(--theme-text)' }}>\n <h2 style={{ marginTop: 0, fontSize: '20px', fontWeight: 700 }}>{t.strategyTitle}</h2>\n\n <div style={calloutStyle}>\n <h3 style={calloutHeadingStyle}>\n <Package size={16} color=\"var(--theme-success-600)\" aria-hidden />\n {t.preImportedTitle}\n </h3>\n <p style={{ margin: '0 0 12px 0', fontSize: '14px', lineHeight: '1.6' }}>\n {t.preImportedCopy}\n </p>\n <ul style={{ margin: 0, paddingLeft: '20px', fontSize: '14px' }}>\n {PRE_IMPORTED_FONTS.map((font) => (\n <li key={font}>{font}</li>\n ))}\n </ul>\n </div>\n\n <div style={calloutStyle}>\n <h3 style={calloutHeadingStyle}>\n <Globe size={16} color=\"var(--theme-warning-600)\" aria-hidden />\n {t.dynamicTitle}\n </h3>\n <p style={{ margin: 0, fontSize: '14px', lineHeight: '1.6' }}>{t.dynamicCopy}</p>\n </div>\n\n <h3 style={{ fontSize: '16px', fontWeight: 600, marginBottom: '12px' }}>{t.exampleTitle}</h3>\n <pre\n style={{\n // Inverted elevation tokens: the code block contrasts with the page in both admin themes.\n background: 'var(--theme-elevation-900)',\n color: 'var(--theme-elevation-50)',\n padding: '16px',\n borderRadius: '8px',\n fontSize: '13px',\n overflowX: 'auto',\n lineHeight: '1.6',\n }}\n >\n {`// app/layout.tsx\nimport { Inter, Nunito, Montserrat } from 'next/font/google'\nimport { getThemeSettings } from '@/utilities/getThemeSettings'\n\nconst inter = Inter({ subsets: ['latin'], variable: '--font-inter' })\nconst nunito = Nunito({ subsets: ['latin'], variable: '--font-nunito' })\nconst montserrat = Montserrat({ subsets: ['latin'], variable: '--font-montserrat' })\n\nexport default async function RootLayout({ children }) {\n const themeSettings = await getThemeSettings()\n const activeFont = themeSettings?.activeFont || 'Inter'\n \n const fontMap = {\n 'Inter': inter.variable,\n 'Nunito': nunito.variable,\n 'Montserrat': montserrat.variable,\n // ... other pre-imported fonts\n }\n \n const selectedFontClass = fontMap[activeFont] || ''\n const isDynamicFont = !selectedFontClass\n \n return (\n <html className={selectedFontClass || ''} \n style={isDynamicFont ? {\n '--font-primary': \\`'\\${activeFont}', sans-serif\\`\n } : undefined}>\n <head>\n {isDynamicFont && (\n <>\n <link rel=\"preconnect\" href=\"https://fonts.googleapis.com\" />\n <link rel=\"preconnect\" href=\"https://fonts.gstatic.com\" crossOrigin=\"\" />\n <link \n href={\\`https://fonts.googleapis.com/css2?family=\\${activeFont.replace(' ', '+')}:wght@300;400;500;600;700&display=swap\\`}\n rel=\"stylesheet\" \n />\n </>\n )}\n </head>\n <body className=\"font-primary\">{children}</body>\n </html>\n )\n}\n\n// CSS\n.font-primary {\n font-family: var(--font-primary, 'Inter', sans-serif);\n}`}\n </pre>\n </div>\n )\n}\n\nexport default FontLoadingGuideField\n"],"names":["Globe","Package","React","useThemeTranslations","PRE_IMPORTED_FONTS","calloutStyle","background","border","borderRadius","padding","marginBottom","calloutHeadingStyle","display","alignItems","gap","margin","fontSize","fontWeight","FontLoadingGuideField","t","fontGuide","div","style","color","h2","marginTop","strategyTitle","h3","size","aria-hidden","preImportedTitle","p","lineHeight","preImportedCopy","ul","paddingLeft","map","font","li","dynamicTitle","dynamicCopy","exampleTitle","pre","overflowX"],"mappings":"AAAA;;AAEA,SAASA,KAAK,EAAEC,OAAO,QAAQ,eAAc;AAE7C,OAAOC,WAAW,QAAO;AACzB,SAASC,oBAAoB,QAAQ,yCAAwC;AAE7E,MAAMC,qBAAqB;IACzB;IACA;IACA;IACA;IACA;IACA;IACA;IACA;CACD;AAED,MAAMC,eAAoC;IACxCC,YAAY;IACZC,QAAQ;IACRC,cAAc;IACdC,SAAS;IACTC,cAAc;AAChB;AAEA,MAAMC,sBAA2C;IAC/CC,SAAS;IACTC,YAAY;IACZC,KAAK;IACLC,QAAQ;IACRC,UAAU;IACVC,YAAY;AACd;AAEA,MAAMC,wBAAsD;IAC1D,MAAMC,IAAIhB,uBAAuBiB,SAAS;IAE1C,qBACE,MAACC;QAAIC,OAAO;YAAEb,SAAS;YAAQc,OAAO;QAAoB;;0BACxD,KAACC;gBAAGF,OAAO;oBAAEG,WAAW;oBAAGT,UAAU;oBAAQC,YAAY;gBAAI;0BAAIE,EAAEO,aAAa;;0BAEhF,MAACL;gBAAIC,OAAOjB;;kCACV,MAACsB;wBAAGL,OAAOX;;0CACT,KAACV;gCAAQ2B,MAAM;gCAAIL,OAAM;gCAA2BM,aAAW;;4BAC9DV,EAAEW,gBAAgB;;;kCAErB,KAACC;wBAAET,OAAO;4BAAEP,QAAQ;4BAAcC,UAAU;4BAAQgB,YAAY;wBAAM;kCACnEb,EAAEc,eAAe;;kCAEpB,KAACC;wBAAGZ,OAAO;4BAAEP,QAAQ;4BAAGoB,aAAa;4BAAQnB,UAAU;wBAAO;kCAC3DZ,mBAAmBgC,GAAG,CAAC,CAACC,qBACvB,KAACC;0CAAeD;+BAAPA;;;;0BAKf,MAAChB;gBAAIC,OAAOjB;;kCACV,MAACsB;wBAAGL,OAAOX;;0CACT,KAACX;gCAAM4B,MAAM;gCAAIL,OAAM;gCAA2BM,aAAW;;4BAC5DV,EAAEoB,YAAY;;;kCAEjB,KAACR;wBAAET,OAAO;4BAAEP,QAAQ;4BAAGC,UAAU;4BAAQgB,YAAY;wBAAM;kCAAIb,EAAEqB,WAAW;;;;0BAG9E,KAACb;gBAAGL,OAAO;oBAAEN,UAAU;oBAAQC,YAAY;oBAAKP,cAAc;gBAAO;0BAAIS,EAAEsB,YAAY;;0BACvF,KAACC;gBACCpB,OAAO;oBACL,0FAA0F;oBAC1FhB,YAAY;oBACZiB,OAAO;oBACPd,SAAS;oBACTD,cAAc;oBACdQ,UAAU;oBACV2B,WAAW;oBACXX,YAAY;gBACd;0BAEC,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA+CT,CAAC;;;;AAIF;AAEA,eAAed,sBAAqB"}
@@ -1 +1 @@
1
- {"version":3,"file":"TypographyInfoField.d.ts","sourceRoot":"","sources":["../../../../src/globals/ThemeSettings/fields/TypographyInfoField.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAA;AACjD,OAAO,KAAK,MAAM,OAAO,CAAA;AAEzB,QAAA,MAAM,mBAAmB,EAAE,KAAK,CAAC,EAAE,CAAC,kBAAkB,CA2DrD,CAAA;AAED,eAAe,mBAAmB,CAAA"}
1
+ {"version":3,"file":"TypographyInfoField.d.ts","sourceRoot":"","sources":["../../../../src/globals/ThemeSettings/fields/TypographyInfoField.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAA;AACjD,OAAO,KAAK,MAAM,OAAO,CAAA;AAczB,QAAA,MAAM,mBAAmB,EAAE,KAAK,CAAC,EAAE,CAAC,kBAAkB,CAqCrD,CAAA;AAED,eAAe,mBAAmB,CAAA"}
@@ -1,14 +1,27 @@
1
1
  'use client';
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  import React from 'react';
4
+ import { useThemeTranslations } from '../../../hooks/useThemeTranslations.js';
5
+ const codeStyle = {
6
+ // Inverted elevation tokens: the code block contrasts with the page in both admin themes.
7
+ background: 'var(--theme-elevation-900)',
8
+ color: 'var(--theme-elevation-50)',
9
+ padding: '12px',
10
+ borderRadius: '6px',
11
+ fontSize: '12px',
12
+ marginTop: '8px',
13
+ overflowX: 'auto'
14
+ };
4
15
  const TypographyInfoField = ()=>{
16
+ const t = useThemeTranslations().fontGuide;
5
17
  return /*#__PURE__*/ _jsxs("div", {
6
18
  style: {
7
19
  padding: '16px',
8
- background: '#f3f4f6',
9
- border: '1px solid #e5e7eb',
20
+ background: 'var(--theme-elevation-50)',
21
+ border: '1px solid var(--theme-elevation-150)',
10
22
  borderRadius: '8px',
11
- marginTop: '16px'
23
+ marginTop: '16px',
24
+ color: 'var(--theme-text)'
12
25
  },
13
26
  children: [
14
27
  /*#__PURE__*/ _jsx("h3", {
@@ -17,7 +30,7 @@ const TypographyInfoField = ()=>{
17
30
  fontSize: '14px',
18
31
  fontWeight: 600
19
32
  },
20
- children: "How to Use Selected Font"
33
+ children: t.usageTitle
21
34
  }),
22
35
  /*#__PURE__*/ _jsx("p", {
23
36
  style: {
@@ -25,7 +38,7 @@ const TypographyInfoField = ()=>{
25
38
  fontSize: '13px',
26
39
  lineHeight: '1.6'
27
40
  },
28
- children: "After selecting a font, you need to load it in your frontend application. Here are the recommended approaches:"
41
+ children: t.usageIntro
29
42
  }),
30
43
  /*#__PURE__*/ _jsxs("div", {
31
44
  style: {
@@ -36,18 +49,10 @@ const TypographyInfoField = ()=>{
36
49
  style: {
37
50
  fontSize: '13px'
38
51
  },
39
- children: "Option 1: next/font/google (Recommended)"
52
+ children: t.optionNextFont
40
53
  }),
41
54
  /*#__PURE__*/ _jsx("pre", {
42
- style: {
43
- background: '#1f2937',
44
- color: '#f9fafb',
45
- padding: '12px',
46
- borderRadius: '6px',
47
- fontSize: '12px',
48
- marginTop: '8px',
49
- overflowX: 'auto'
50
- },
55
+ style: codeStyle,
51
56
  children: `import { Inter } from 'next/font/google'
52
57
 
53
58
  const inter = Inter({ subsets: ['latin'] })
@@ -64,18 +69,10 @@ const inter = Inter({ subsets: ['latin'] })
64
69
  style: {
65
70
  fontSize: '13px'
66
71
  },
67
- children: "Option 2: Google Fonts CSS Link"
72
+ children: t.optionCssLink
68
73
  }),
69
74
  /*#__PURE__*/ _jsx("pre", {
70
- style: {
71
- background: '#1f2937',
72
- color: '#f9fafb',
73
- padding: '12px',
74
- borderRadius: '6px',
75
- fontSize: '12px',
76
- marginTop: '8px',
77
- overflowX: 'auto'
78
- },
75
+ style: codeStyle,
79
76
  children: `<link rel="preconnect" href="https://fonts.googleapis.com">
80
77
  <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;700&display=swap" rel="stylesheet">`
81
78
  })
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/globals/ThemeSettings/fields/TypographyInfoField.tsx"],"sourcesContent":["'use client'\n\nimport type { UIFieldClientProps } from 'payload'\nimport React from 'react'\n\nconst TypographyInfoField: React.FC<UIFieldClientProps> = () => {\n return (\n <div\n style={{\n padding: '16px',\n background: '#f3f4f6',\n border: '1px solid #e5e7eb',\n borderRadius: '8px',\n marginTop: '16px',\n }}\n >\n <h3 style={{ margin: '0 0 8px 0', fontSize: '14px', fontWeight: 600 }}>\n How to Use Selected Font\n </h3>\n <p style={{ margin: '0 0 12px 0', fontSize: '13px', lineHeight: '1.6' }}>\n After selecting a font, you need to load it in your frontend application. Here are the\n recommended approaches:\n </p>\n <div style={{ marginBottom: '12px' }}>\n <strong style={{ fontSize: '13px' }}>Option 1: next/font/google (Recommended)</strong>\n <pre\n style={{\n background: '#1f2937',\n color: '#f9fafb',\n padding: '12px',\n borderRadius: '6px',\n fontSize: '12px',\n marginTop: '8px',\n overflowX: 'auto',\n }}\n >\n {`import { Inter } from 'next/font/google'\n\nconst inter = Inter({ subsets: ['latin'] })\n\n<html className={inter.variable}>\n <body className=\"font-primary\">...</body>\n</html>`}\n </pre>\n </div>\n <div>\n <strong style={{ fontSize: '13px' }}>Option 2: Google Fonts CSS Link</strong>\n <pre\n style={{\n background: '#1f2937',\n color: '#f9fafb',\n padding: '12px',\n borderRadius: '6px',\n fontSize: '12px',\n marginTop: '8px',\n overflowX: 'auto',\n }}\n >\n {`<link rel=\"preconnect\" href=\"https://fonts.googleapis.com\">\n<link href=\"https://fonts.googleapis.com/css2?family=Inter:wght@400;700&display=swap\" rel=\"stylesheet\">`}\n </pre>\n </div>\n </div>\n )\n}\n\nexport default TypographyInfoField\n"],"names":["React","TypographyInfoField","div","style","padding","background","border","borderRadius","marginTop","h3","margin","fontSize","fontWeight","p","lineHeight","marginBottom","strong","pre","color","overflowX"],"mappings":"AAAA;;AAGA,OAAOA,WAAW,QAAO;AAEzB,MAAMC,sBAAoD;IACxD,qBACE,MAACC;QACCC,OAAO;YACLC,SAAS;YACTC,YAAY;YACZC,QAAQ;YACRC,cAAc;YACdC,WAAW;QACb;;0BAEA,KAACC;gBAAGN,OAAO;oBAAEO,QAAQ;oBAAaC,UAAU;oBAAQC,YAAY;gBAAI;0BAAG;;0BAGvE,KAACC;gBAAEV,OAAO;oBAAEO,QAAQ;oBAAcC,UAAU;oBAAQG,YAAY;gBAAM;0BAAG;;0BAIzE,MAACZ;gBAAIC,OAAO;oBAAEY,cAAc;gBAAO;;kCACjC,KAACC;wBAAOb,OAAO;4BAAEQ,UAAU;wBAAO;kCAAG;;kCACrC,KAACM;wBACCd,OAAO;4BACLE,YAAY;4BACZa,OAAO;4BACPd,SAAS;4BACTG,cAAc;4BACdI,UAAU;4BACVH,WAAW;4BACXW,WAAW;wBACb;kCAEC,CAAC;;;;;;OAML,CAAC;;;;0BAGF,MAACjB;;kCACC,KAACc;wBAAOb,OAAO;4BAAEQ,UAAU;wBAAO;kCAAG;;kCACrC,KAACM;wBACCd,OAAO;4BACLE,YAAY;4BACZa,OAAO;4BACPd,SAAS;4BACTG,cAAc;4BACdI,UAAU;4BACVH,WAAW;4BACXW,WAAW;wBACb;kCAEC,CAAC;uGAC2F,CAAC;;;;;;AAKxG;AAEA,eAAelB,oBAAmB"}
1
+ {"version":3,"sources":["../../../../src/globals/ThemeSettings/fields/TypographyInfoField.tsx"],"sourcesContent":["'use client'\n\nimport type { UIFieldClientProps } from 'payload'\nimport React from 'react'\nimport { useThemeTranslations } from '../../../hooks/useThemeTranslations.js'\n\nconst codeStyle: React.CSSProperties = {\n // Inverted elevation tokens: the code block contrasts with the page in both admin themes.\n background: 'var(--theme-elevation-900)',\n color: 'var(--theme-elevation-50)',\n padding: '12px',\n borderRadius: '6px',\n fontSize: '12px',\n marginTop: '8px',\n overflowX: 'auto',\n}\n\nconst TypographyInfoField: React.FC<UIFieldClientProps> = () => {\n const t = useThemeTranslations().fontGuide\n\n return (\n <div\n style={{\n padding: '16px',\n background: 'var(--theme-elevation-50)',\n border: '1px solid var(--theme-elevation-150)',\n borderRadius: '8px',\n marginTop: '16px',\n color: 'var(--theme-text)',\n }}\n >\n <h3 style={{ margin: '0 0 8px 0', fontSize: '14px', fontWeight: 600 }}>{t.usageTitle}</h3>\n <p style={{ margin: '0 0 12px 0', fontSize: '13px', lineHeight: '1.6' }}>{t.usageIntro}</p>\n <div style={{ marginBottom: '12px' }}>\n <strong style={{ fontSize: '13px' }}>{t.optionNextFont}</strong>\n <pre style={codeStyle}>\n {`import { Inter } from 'next/font/google'\n\nconst inter = Inter({ subsets: ['latin'] })\n\n<html className={inter.variable}>\n <body className=\"font-primary\">...</body>\n</html>`}\n </pre>\n </div>\n <div>\n <strong style={{ fontSize: '13px' }}>{t.optionCssLink}</strong>\n <pre style={codeStyle}>\n {`<link rel=\"preconnect\" href=\"https://fonts.googleapis.com\">\n<link href=\"https://fonts.googleapis.com/css2?family=Inter:wght@400;700&display=swap\" rel=\"stylesheet\">`}\n </pre>\n </div>\n </div>\n )\n}\n\nexport default TypographyInfoField\n"],"names":["React","useThemeTranslations","codeStyle","background","color","padding","borderRadius","fontSize","marginTop","overflowX","TypographyInfoField","t","fontGuide","div","style","border","h3","margin","fontWeight","usageTitle","p","lineHeight","usageIntro","marginBottom","strong","optionNextFont","pre","optionCssLink"],"mappings":"AAAA;;AAGA,OAAOA,WAAW,QAAO;AACzB,SAASC,oBAAoB,QAAQ,yCAAwC;AAE7E,MAAMC,YAAiC;IACrC,0FAA0F;IAC1FC,YAAY;IACZC,OAAO;IACPC,SAAS;IACTC,cAAc;IACdC,UAAU;IACVC,WAAW;IACXC,WAAW;AACb;AAEA,MAAMC,sBAAoD;IACxD,MAAMC,IAAIV,uBAAuBW,SAAS;IAE1C,qBACE,MAACC;QACCC,OAAO;YACLT,SAAS;YACTF,YAAY;YACZY,QAAQ;YACRT,cAAc;YACdE,WAAW;YACXJ,OAAO;QACT;;0BAEA,KAACY;gBAAGF,OAAO;oBAAEG,QAAQ;oBAAaV,UAAU;oBAAQW,YAAY;gBAAI;0BAAIP,EAAEQ,UAAU;;0BACpF,KAACC;gBAAEN,OAAO;oBAAEG,QAAQ;oBAAcV,UAAU;oBAAQc,YAAY;gBAAM;0BAAIV,EAAEW,UAAU;;0BACtF,MAACT;gBAAIC,OAAO;oBAAES,cAAc;gBAAO;;kCACjC,KAACC;wBAAOV,OAAO;4BAAEP,UAAU;wBAAO;kCAAII,EAAEc,cAAc;;kCACtD,KAACC;wBAAIZ,OAAOZ;kCACT,CAAC;;;;;;OAML,CAAC;;;;0BAGF,MAACW;;kCACC,KAACW;wBAAOV,OAAO;4BAAEP,UAAU;wBAAO;kCAAII,EAAEgB,aAAa;;kCACrD,KAACD;wBAAIZ,OAAOZ;kCACT,CAAC;uGAC2F,CAAC;;;;;;AAKxG;AAEA,eAAeQ,oBAAmB"}
@@ -0,0 +1,50 @@
1
+ /**
2
+ * Editing-session state shared by the Appearance Settings fields: which parts of
3
+ * the look are locked, and a one-step undo snapshot of the last bulk change
4
+ * (theme preset, style preset or generated palette).
5
+ *
6
+ * Deliberately not persisted: locks reset on reload and nothing new is stored in
7
+ * the document. The fields live in separate React trees (Payload renders each
8
+ * custom field on its own), so the state sits in a tiny module-level store.
9
+ */
10
+ export type AppearanceLock = 'colors' | 'fonts' | 'style';
11
+ export type AppearanceSource = 'theme' | 'style' | 'palette';
12
+ export interface UndoEntry {
13
+ path: string;
14
+ value: unknown;
15
+ }
16
+ export interface AppearanceUndo {
17
+ id: number;
18
+ source: AppearanceSource;
19
+ label: string;
20
+ entries: UndoEntry[];
21
+ }
22
+ interface AppearanceSessionState {
23
+ locks: Record<AppearanceLock, boolean>;
24
+ undo: AppearanceUndo | null;
25
+ }
26
+ export declare function toggleAppearanceLock(lock: AppearanceLock): void;
27
+ export declare function recordAppearanceUndo(source: AppearanceSource, label: string, entries: UndoEntry[]): void;
28
+ export declare function clearAppearanceUndo(id?: number): void;
29
+ export declare function getAppearanceSession(): AppearanceSessionState;
30
+ /** Test helper: restore the initial session state. */
31
+ export declare function resetAppearanceSession(): void;
32
+ export declare function useAppearanceSession(): AppearanceSessionState;
33
+ type FormFieldsState = Record<string, {
34
+ value?: unknown;
35
+ } | undefined> | undefined;
36
+ type Dispatch = (action: {
37
+ type: 'UPDATE';
38
+ path: string;
39
+ value: unknown;
40
+ }) => void;
41
+ /**
42
+ * Collects field writes for one bulk action, remembering each field's previous
43
+ * value (first write wins) so the whole action can be undone in one step.
44
+ */
45
+ export declare function createBulkWriter(formFields: FormFieldsState, dispatchFields: Dispatch): {
46
+ write(path: string, value: unknown): void;
47
+ commit(source: AppearanceSource, label: string): void;
48
+ };
49
+ export {};
50
+ //# sourceMappingURL=useAppearanceSession.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useAppearanceSession.d.ts","sourceRoot":"","sources":["../../src/hooks/useAppearanceSession.ts"],"names":[],"mappings":"AAIA;;;;;;;;GAQG;AAEH,MAAM,MAAM,cAAc,GAAG,QAAQ,GAAG,OAAO,GAAG,OAAO,CAAA;AACzD,MAAM,MAAM,gBAAgB,GAAG,OAAO,GAAG,OAAO,GAAG,SAAS,CAAA;AAE5D,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE,OAAO,CAAA;CACf;AAED,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,MAAM,CAAA;IACV,MAAM,EAAE,gBAAgB,CAAA;IACxB,KAAK,EAAE,MAAM,CAAA;IACb,OAAO,EAAE,SAAS,EAAE,CAAA;CACrB;AAED,UAAU,sBAAsB;IAC9B,KAAK,EAAE,MAAM,CAAC,cAAc,EAAE,OAAO,CAAC,CAAA;IACtC,IAAI,EAAE,cAAc,GAAG,IAAI,CAAA;CAC5B;AAmBD,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,cAAc,QAExD;AAED,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,gBAAgB,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,SAAS,EAAE,QAGjG;AAED,wBAAgB,mBAAmB,CAAC,EAAE,CAAC,EAAE,MAAM,QAG9C;AAED,wBAAgB,oBAAoB,IAAI,sBAAsB,CAE7D;AAED,sDAAsD;AACtD,wBAAgB,sBAAsB,SAErC;AAED,wBAAgB,oBAAoB,IAAI,sBAAsB,CAE7D;AAED,KAAK,eAAe,GAAG,MAAM,CAAC,MAAM,EAAE;IAAE,KAAK,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG,SAAS,CAAC,GAAG,SAAS,CAAA;AAClF,KAAK,QAAQ,GAAG,CAAC,MAAM,EAAE;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,OAAO,CAAA;CAAE,KAAK,IAAI,CAAA;AAElF;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,UAAU,EAAE,eAAe,EAAE,cAAc,EAAE,QAAQ;gBAItE,MAAM,SAAS,OAAO;mBAInB,gBAAgB,SAAS,MAAM;EAKjD"}
@@ -0,0 +1,91 @@
1
+ 'use client';
2
+ import { useSyncExternalStore } from 'react';
3
+ let state = {
4
+ locks: {
5
+ colors: false,
6
+ fonts: false,
7
+ style: false
8
+ },
9
+ undo: null
10
+ };
11
+ let nextUndoId = 1;
12
+ const listeners = new Set();
13
+ function setState(next) {
14
+ state = next;
15
+ listeners.forEach((listener)=>listener());
16
+ }
17
+ function subscribe(listener) {
18
+ listeners.add(listener);
19
+ return ()=>listeners.delete(listener);
20
+ }
21
+ export function toggleAppearanceLock(lock) {
22
+ setState({
23
+ ...state,
24
+ locks: {
25
+ ...state.locks,
26
+ [lock]: !state.locks[lock]
27
+ }
28
+ });
29
+ }
30
+ export function recordAppearanceUndo(source, label, entries) {
31
+ if (entries.length === 0) return;
32
+ setState({
33
+ ...state,
34
+ undo: {
35
+ id: nextUndoId++,
36
+ source,
37
+ label,
38
+ entries
39
+ }
40
+ });
41
+ }
42
+ export function clearAppearanceUndo(id) {
43
+ if (!state.undo || id !== undefined && state.undo.id !== id) return;
44
+ setState({
45
+ ...state,
46
+ undo: null
47
+ });
48
+ }
49
+ export function getAppearanceSession() {
50
+ return state;
51
+ }
52
+ /** Test helper: restore the initial session state. */ export function resetAppearanceSession() {
53
+ setState({
54
+ locks: {
55
+ colors: false,
56
+ fonts: false,
57
+ style: false
58
+ },
59
+ undo: null
60
+ });
61
+ }
62
+ export function useAppearanceSession() {
63
+ return useSyncExternalStore(subscribe, getAppearanceSession, getAppearanceSession);
64
+ }
65
+ /**
66
+ * Collects field writes for one bulk action, remembering each field's previous
67
+ * value (first write wins) so the whole action can be undone in one step.
68
+ */ export function createBulkWriter(formFields, dispatchFields) {
69
+ const previous = new Map();
70
+ return {
71
+ write (path, value) {
72
+ if (!previous.has(path)) previous.set(path, formFields?.[path]?.value);
73
+ dispatchFields({
74
+ type: 'UPDATE',
75
+ path,
76
+ value
77
+ });
78
+ },
79
+ commit (source, label) {
80
+ const entries = [
81
+ ...previous.entries()
82
+ ].map(([path, value])=>({
83
+ path,
84
+ value
85
+ }));
86
+ recordAppearanceUndo(source, label, entries);
87
+ }
88
+ };
89
+ }
90
+
91
+ //# sourceMappingURL=useAppearanceSession.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/hooks/useAppearanceSession.ts"],"sourcesContent":["'use client'\n\nimport { useSyncExternalStore } from 'react'\n\n/**\n * Editing-session state shared by the Appearance Settings fields: which parts of\n * the look are locked, and a one-step undo snapshot of the last bulk change\n * (theme preset, style preset or generated palette).\n *\n * Deliberately not persisted: locks reset on reload and nothing new is stored in\n * the document. The fields live in separate React trees (Payload renders each\n * custom field on its own), so the state sits in a tiny module-level store.\n */\n\nexport type AppearanceLock = 'colors' | 'fonts' | 'style'\nexport type AppearanceSource = 'theme' | 'style' | 'palette'\n\nexport interface UndoEntry {\n path: string\n value: unknown\n}\n\nexport interface AppearanceUndo {\n id: number\n source: AppearanceSource\n label: string\n entries: UndoEntry[]\n}\n\ninterface AppearanceSessionState {\n locks: Record<AppearanceLock, boolean>\n undo: AppearanceUndo | null\n}\n\nlet state: AppearanceSessionState = {\n locks: { colors: false, fonts: false, style: false },\n undo: null,\n}\nlet nextUndoId = 1\nconst listeners = new Set<() => void>()\n\nfunction setState(next: AppearanceSessionState) {\n state = next\n listeners.forEach((listener) => listener())\n}\n\nfunction subscribe(listener: () => void) {\n listeners.add(listener)\n return () => listeners.delete(listener)\n}\n\nexport function toggleAppearanceLock(lock: AppearanceLock) {\n setState({ ...state, locks: { ...state.locks, [lock]: !state.locks[lock] } })\n}\n\nexport function recordAppearanceUndo(source: AppearanceSource, label: string, entries: UndoEntry[]) {\n if (entries.length === 0) return\n setState({ ...state, undo: { id: nextUndoId++, source, label, entries } })\n}\n\nexport function clearAppearanceUndo(id?: number) {\n if (!state.undo || (id !== undefined && state.undo.id !== id)) return\n setState({ ...state, undo: null })\n}\n\nexport function getAppearanceSession(): AppearanceSessionState {\n return state\n}\n\n/** Test helper: restore the initial session state. */\nexport function resetAppearanceSession() {\n setState({ locks: { colors: false, fonts: false, style: false }, undo: null })\n}\n\nexport function useAppearanceSession(): AppearanceSessionState {\n return useSyncExternalStore(subscribe, getAppearanceSession, getAppearanceSession)\n}\n\ntype FormFieldsState = Record<string, { value?: unknown } | undefined> | undefined\ntype Dispatch = (action: { type: 'UPDATE'; path: string; value: unknown }) => void\n\n/**\n * Collects field writes for one bulk action, remembering each field's previous\n * value (first write wins) so the whole action can be undone in one step.\n */\nexport function createBulkWriter(formFields: FormFieldsState, dispatchFields: Dispatch) {\n const previous = new Map<string, unknown>()\n\n return {\n write(path: string, value: unknown) {\n if (!previous.has(path)) previous.set(path, formFields?.[path]?.value)\n dispatchFields({ type: 'UPDATE', path, value })\n },\n commit(source: AppearanceSource, label: string) {\n const entries = [...previous.entries()].map(([path, value]) => ({ path, value }))\n recordAppearanceUndo(source, label, entries)\n },\n }\n}\n"],"names":["useSyncExternalStore","state","locks","colors","fonts","style","undo","nextUndoId","listeners","Set","setState","next","forEach","listener","subscribe","add","delete","toggleAppearanceLock","lock","recordAppearanceUndo","source","label","entries","length","id","clearAppearanceUndo","undefined","getAppearanceSession","resetAppearanceSession","useAppearanceSession","createBulkWriter","formFields","dispatchFields","previous","Map","write","path","value","has","set","type","commit","map"],"mappings":"AAAA;AAEA,SAASA,oBAAoB,QAAQ,QAAO;AAgC5C,IAAIC,QAAgC;IAClCC,OAAO;QAAEC,QAAQ;QAAOC,OAAO;QAAOC,OAAO;IAAM;IACnDC,MAAM;AACR;AACA,IAAIC,aAAa;AACjB,MAAMC,YAAY,IAAIC;AAEtB,SAASC,SAASC,IAA4B;IAC5CV,QAAQU;IACRH,UAAUI,OAAO,CAAC,CAACC,WAAaA;AAClC;AAEA,SAASC,UAAUD,QAAoB;IACrCL,UAAUO,GAAG,CAACF;IACd,OAAO,IAAML,UAAUQ,MAAM,CAACH;AAChC;AAEA,OAAO,SAASI,qBAAqBC,IAAoB;IACvDR,SAAS;QAAE,GAAGT,KAAK;QAAEC,OAAO;YAAE,GAAGD,MAAMC,KAAK;YAAE,CAACgB,KAAK,EAAE,CAACjB,MAAMC,KAAK,CAACgB,KAAK;QAAC;IAAE;AAC7E;AAEA,OAAO,SAASC,qBAAqBC,MAAwB,EAAEC,KAAa,EAAEC,OAAoB;IAChG,IAAIA,QAAQC,MAAM,KAAK,GAAG;IAC1Bb,SAAS;QAAE,GAAGT,KAAK;QAAEK,MAAM;YAAEkB,IAAIjB;YAAca;YAAQC;YAAOC;QAAQ;IAAE;AAC1E;AAEA,OAAO,SAASG,oBAAoBD,EAAW;IAC7C,IAAI,CAACvB,MAAMK,IAAI,IAAKkB,OAAOE,aAAazB,MAAMK,IAAI,CAACkB,EAAE,KAAKA,IAAK;IAC/Dd,SAAS;QAAE,GAAGT,KAAK;QAAEK,MAAM;IAAK;AAClC;AAEA,OAAO,SAASqB;IACd,OAAO1B;AACT;AAEA,oDAAoD,GACpD,OAAO,SAAS2B;IACdlB,SAAS;QAAER,OAAO;YAAEC,QAAQ;YAAOC,OAAO;YAAOC,OAAO;QAAM;QAAGC,MAAM;IAAK;AAC9E;AAEA,OAAO,SAASuB;IACd,OAAO7B,qBAAqBc,WAAWa,sBAAsBA;AAC/D;AAKA;;;CAGC,GACD,OAAO,SAASG,iBAAiBC,UAA2B,EAAEC,cAAwB;IACpF,MAAMC,WAAW,IAAIC;IAErB,OAAO;QACLC,OAAMC,IAAY,EAAEC,KAAc;YAChC,IAAI,CAACJ,SAASK,GAAG,CAACF,OAAOH,SAASM,GAAG,CAACH,MAAML,YAAY,CAACK,KAAK,EAAEC;YAChEL,eAAe;gBAAEQ,MAAM;gBAAUJ;gBAAMC;YAAM;QAC/C;QACAI,QAAOrB,MAAwB,EAAEC,KAAa;YAC5C,MAAMC,UAAU;mBAAIW,SAASX,OAAO;aAAG,CAACoB,GAAG,CAAC,CAAC,CAACN,MAAMC,MAAM,GAAM,CAAA;oBAAED;oBAAMC;gBAAM,CAAA;YAC9ElB,qBAAqBC,QAAQC,OAAOC;QACtC;IACF;AACF"}
@@ -0,0 +1,13 @@
1
+ import { type PluginTranslations } from '../translations.js';
2
+ /**
3
+ * Resolve the current Payload admin language using Payload's native i18n context
4
+ * (instead of sniffing `navigator.language`). Falls back to English.
5
+ */
6
+ export declare function useThemeLanguage(): string;
7
+ /**
8
+ * Return the plugin's translations for the active admin language, with English
9
+ * used as the fallback for any missing key. Use this in client field components
10
+ * so the strings follow the admin's selected locale natively.
11
+ */
12
+ export declare function useThemeTranslations(): PluginTranslations;
13
+ //# sourceMappingURL=useThemeTranslations.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useThemeTranslations.d.ts","sourceRoot":"","sources":["../../src/hooks/useThemeTranslations.ts"],"names":[],"mappings":"AAGA,OAAO,EAAmB,KAAK,kBAAkB,EAAE,MAAM,oBAAoB,CAAA;AAE7E;;;GAGG;AACH,wBAAgB,gBAAgB,IAAI,MAAM,CAMzC;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,IAAI,kBAAkB,CAEzD"}
@@ -0,0 +1,22 @@
1
+ 'use client';
2
+ import { useTranslation } from '@payloadcms/ui';
3
+ import { getTranslations } from '../translations.js';
4
+ /**
5
+ * Resolve the current Payload admin language using Payload's native i18n context
6
+ * (instead of sniffing `navigator.language`). Falls back to English.
7
+ */ export function useThemeLanguage() {
8
+ // Tolerate `useTranslation()` returning undefined (e.g. outside an i18n provider
9
+ // or in unit tests with reset mocks) by falling back to English.
10
+ const result = useTranslation();
11
+ const language = result?.i18n?.language;
12
+ return typeof language === 'string' && language.length >= 2 ? language : 'en';
13
+ }
14
+ /**
15
+ * Return the plugin's translations for the active admin language, with English
16
+ * used as the fallback for any missing key. Use this in client field components
17
+ * so the strings follow the admin's selected locale natively.
18
+ */ export function useThemeTranslations() {
19
+ return getTranslations(useThemeLanguage());
20
+ }
21
+
22
+ //# sourceMappingURL=useThemeTranslations.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/hooks/useThemeTranslations.ts"],"sourcesContent":["'use client'\n\nimport { useTranslation } from '@payloadcms/ui'\nimport { getTranslations, type PluginTranslations } from '../translations.js'\n\n/**\n * Resolve the current Payload admin language using Payload's native i18n context\n * (instead of sniffing `navigator.language`). Falls back to English.\n */\nexport function useThemeLanguage(): string {\n // Tolerate `useTranslation()` returning undefined (e.g. outside an i18n provider\n // or in unit tests with reset mocks) by falling back to English.\n const result = useTranslation() as { i18n?: { language?: string } } | undefined\n const language = result?.i18n?.language\n return typeof language === 'string' && language.length >= 2 ? language : 'en'\n}\n\n/**\n * Return the plugin's translations for the active admin language, with English\n * used as the fallback for any missing key. Use this in client field components\n * so the strings follow the admin's selected locale natively.\n */\nexport function useThemeTranslations(): PluginTranslations {\n return getTranslations(useThemeLanguage())\n}\n"],"names":["useTranslation","getTranslations","useThemeLanguage","result","language","i18n","length","useThemeTranslations"],"mappings":"AAAA;AAEA,SAASA,cAAc,QAAQ,iBAAgB;AAC/C,SAASC,eAAe,QAAiC,qBAAoB;AAE7E;;;CAGC,GACD,OAAO,SAASC;IACd,iFAAiF;IACjF,iEAAiE;IACjE,MAAMC,SAASH;IACf,MAAMI,WAAWD,QAAQE,MAAMD;IAC/B,OAAO,OAAOA,aAAa,YAAYA,SAASE,MAAM,IAAI,IAAIF,WAAW;AAC3E;AAEA;;;;CAIC,GACD,OAAO,SAASG;IACd,OAAON,gBAAgBC;AACzB"}