@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
package/dist/i18n.d.ts ADDED
@@ -0,0 +1,53 @@
1
+ import type { Config } from 'payload';
2
+ import { type DeepPartial, type PluginTranslations } from './translations.js';
3
+ /**
4
+ * Additional or overriding translations, keyed by language code.
5
+ * Each entry is deep-merged over the built-in English/Czech translations, so you
6
+ * only need to provide the keys you want to add or change.
7
+ */
8
+ export type ThemeManagementI18nTranslations = Record<string, DeepPartial<PluginTranslations>>;
9
+ export interface ThemeManagementI18nOptions {
10
+ /**
11
+ * Extra languages or per-key overrides for the plugin admin UI strings.
12
+ *
13
+ * @example
14
+ * i18n: {
15
+ * translations: {
16
+ * de: { tabLabel: 'Darstellung', ui: { lightMode: 'Heller Modus' } },
17
+ * en: { tabLabel: 'Theme' }, // override a built-in string
18
+ * },
19
+ * }
20
+ */
21
+ translations?: ThemeManagementI18nTranslations;
22
+ /**
23
+ * Pass-through to `config.i18n.supportedLanguages`. Provide language objects from
24
+ * `@payloadcms/translations/languages/*` when you want the Payload admin to offer a
25
+ * brand-new admin language (beyond the project defaults).
26
+ *
27
+ * @example
28
+ * import { de } from '@payloadcms/translations/languages/de'
29
+ * i18n: { supportedLanguages: { de } }
30
+ */
31
+ supportedLanguages?: Record<string, unknown>;
32
+ }
33
+ type PayloadTranslationsByLang = Record<string, Record<string, unknown>>;
34
+ /**
35
+ * Build the plugin's translations in Payload's native `config.i18n.translations`
36
+ * shape: `{ [lang]: { 'theme-management': { ...keys } } }`.
37
+ *
38
+ * Every language is filled out via `getTranslations`, so English acts as the
39
+ * fallback for any missing key in another language.
40
+ */
41
+ export declare function getThemeManagementI18nTranslations(): PayloadTranslationsByLang;
42
+ /**
43
+ * Merge the plugin's translations into an existing `config.i18n`, following the
44
+ * official Payload plugin i18n pattern. Translations already present on the
45
+ * incoming config win over the plugin defaults, so apps can freely override.
46
+ *
47
+ * Any `options.translations` are registered first so they participate in the
48
+ * merge (and are visible to `getTranslations` at runtime), and any
49
+ * `options.supportedLanguages` are passed straight through.
50
+ */
51
+ export declare function mergeThemeManagementI18n(existing: Config['i18n'], options?: ThemeManagementI18nOptions): NonNullable<Config['i18n']>;
52
+ export {};
53
+ //# sourceMappingURL=i18n.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"i18n.d.ts","sourceRoot":"","sources":["../src/i18n.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,SAAS,CAAA;AACrC,OAAO,EAML,KAAK,WAAW,EAChB,KAAK,kBAAkB,EACxB,MAAM,mBAAmB,CAAA;AAE1B;;;;GAIG;AACH,MAAM,MAAM,+BAA+B,GAAG,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,kBAAkB,CAAC,CAAC,CAAA;AAE7F,MAAM,WAAW,0BAA0B;IACzC;;;;;;;;;;OAUG;IACH,YAAY,CAAC,EAAE,+BAA+B,CAAA;IAC9C;;;;;;;;OAQG;IACH,kBAAkB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAC7C;AAED,KAAK,yBAAyB,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAA;AAExE;;;;;;GAMG;AACH,wBAAgB,kCAAkC,IAAI,yBAAyB,CAM9E;AAED;;;;;;;;GAQG;AACH,wBAAgB,wBAAwB,CACtC,QAAQ,EAAE,MAAM,CAAC,MAAM,CAAC,EACxB,OAAO,CAAC,EAAE,0BAA0B,GACnC,WAAW,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAgC7B"}
package/dist/i18n.js ADDED
@@ -0,0 +1,53 @@
1
+ import { THEME_MANAGEMENT_I18N_NAMESPACE, availableLanguages, deepMerge, getTranslations, registerTranslations } from './translations.js';
2
+ /**
3
+ * Build the plugin's translations in Payload's native `config.i18n.translations`
4
+ * shape: `{ [lang]: { 'theme-management': { ...keys } } }`.
5
+ *
6
+ * Every language is filled out via `getTranslations`, so English acts as the
7
+ * fallback for any missing key in another language.
8
+ */ export function getThemeManagementI18nTranslations() {
9
+ const out = {};
10
+ for (const lang of availableLanguages()){
11
+ out[lang] = {
12
+ [THEME_MANAGEMENT_I18N_NAMESPACE]: getTranslations(lang)
13
+ };
14
+ }
15
+ return out;
16
+ }
17
+ /**
18
+ * Merge the plugin's translations into an existing `config.i18n`, following the
19
+ * official Payload plugin i18n pattern. Translations already present on the
20
+ * incoming config win over the plugin defaults, so apps can freely override.
21
+ *
22
+ * Any `options.translations` are registered first so they participate in the
23
+ * merge (and are visible to `getTranslations` at runtime), and any
24
+ * `options.supportedLanguages` are passed straight through.
25
+ */ export function mergeThemeManagementI18n(existing, options) {
26
+ if (options?.translations) {
27
+ registerTranslations(options.translations);
28
+ }
29
+ const pluginTranslations = getThemeManagementI18nTranslations();
30
+ const existingTranslations = existing?.translations ?? {};
31
+ // Start from existing translations to preserve every other namespace/language,
32
+ // then layer the plugin namespace underneath the app's own values.
33
+ const mergedTranslations = {
34
+ ...existingTranslations
35
+ };
36
+ for (const lang of Object.keys(pluginTranslations)){
37
+ mergedTranslations[lang] = deepMerge(pluginTranslations[lang], existingTranslations[lang] ?? {});
38
+ }
39
+ const merged = {
40
+ ...existing ?? {},
41
+ translations: mergedTranslations
42
+ };
43
+ if (options?.supportedLanguages) {
44
+ ;
45
+ merged.supportedLanguages = {
46
+ ...existing?.supportedLanguages ?? {},
47
+ ...options.supportedLanguages
48
+ };
49
+ }
50
+ return merged;
51
+ }
52
+
53
+ //# sourceMappingURL=i18n.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/i18n.ts"],"sourcesContent":["import type { Config } from 'payload'\nimport {\n THEME_MANAGEMENT_I18N_NAMESPACE,\n availableLanguages,\n deepMerge,\n getTranslations,\n registerTranslations,\n type DeepPartial,\n type PluginTranslations,\n} from './translations.js'\n\n/**\n * Additional or overriding translations, keyed by language code.\n * Each entry is deep-merged over the built-in English/Czech translations, so you\n * only need to provide the keys you want to add or change.\n */\nexport type ThemeManagementI18nTranslations = Record<string, DeepPartial<PluginTranslations>>\n\nexport interface ThemeManagementI18nOptions {\n /**\n * Extra languages or per-key overrides for the plugin admin UI strings.\n *\n * @example\n * i18n: {\n * translations: {\n * de: { tabLabel: 'Darstellung', ui: { lightMode: 'Heller Modus' } },\n * en: { tabLabel: 'Theme' }, // override a built-in string\n * },\n * }\n */\n translations?: ThemeManagementI18nTranslations\n /**\n * Pass-through to `config.i18n.supportedLanguages`. Provide language objects from\n * `@payloadcms/translations/languages/*` when you want the Payload admin to offer a\n * brand-new admin language (beyond the project defaults).\n *\n * @example\n * import { de } from '@payloadcms/translations/languages/de'\n * i18n: { supportedLanguages: { de } }\n */\n supportedLanguages?: Record<string, unknown>\n}\n\ntype PayloadTranslationsByLang = Record<string, Record<string, unknown>>\n\n/**\n * Build the plugin's translations in Payload's native `config.i18n.translations`\n * shape: `{ [lang]: { 'theme-management': { ...keys } } }`.\n *\n * Every language is filled out via `getTranslations`, so English acts as the\n * fallback for any missing key in another language.\n */\nexport function getThemeManagementI18nTranslations(): PayloadTranslationsByLang {\n const out: PayloadTranslationsByLang = {}\n for (const lang of availableLanguages()) {\n out[lang] = { [THEME_MANAGEMENT_I18N_NAMESPACE]: getTranslations(lang) }\n }\n return out\n}\n\n/**\n * Merge the plugin's translations into an existing `config.i18n`, following the\n * official Payload plugin i18n pattern. Translations already present on the\n * incoming config win over the plugin defaults, so apps can freely override.\n *\n * Any `options.translations` are registered first so they participate in the\n * merge (and are visible to `getTranslations` at runtime), and any\n * `options.supportedLanguages` are passed straight through.\n */\nexport function mergeThemeManagementI18n(\n existing: Config['i18n'],\n options?: ThemeManagementI18nOptions,\n): NonNullable<Config['i18n']> {\n if (options?.translations) {\n registerTranslations(options.translations)\n }\n\n const pluginTranslations = getThemeManagementI18nTranslations()\n const existingTranslations = (existing?.translations ?? {}) as PayloadTranslationsByLang\n\n // Start from existing translations to preserve every other namespace/language,\n // then layer the plugin namespace underneath the app's own values.\n const mergedTranslations: PayloadTranslationsByLang = { ...existingTranslations }\n for (const lang of Object.keys(pluginTranslations)) {\n mergedTranslations[lang] = deepMerge(\n pluginTranslations[lang] as Record<string, unknown>,\n (existingTranslations[lang] ?? {}) as Record<string, unknown>,\n )\n }\n\n const merged = {\n ...(existing ?? {}),\n translations: mergedTranslations,\n } as NonNullable<Config['i18n']>\n\n if (options?.supportedLanguages) {\n ;(merged as { supportedLanguages?: Record<string, unknown> }).supportedLanguages = {\n ...((existing as { supportedLanguages?: Record<string, unknown> } | undefined)\n ?.supportedLanguages ?? {}),\n ...options.supportedLanguages,\n }\n }\n\n return merged\n}\n"],"names":["THEME_MANAGEMENT_I18N_NAMESPACE","availableLanguages","deepMerge","getTranslations","registerTranslations","getThemeManagementI18nTranslations","out","lang","mergeThemeManagementI18n","existing","options","translations","pluginTranslations","existingTranslations","mergedTranslations","Object","keys","merged","supportedLanguages"],"mappings":"AACA,SACEA,+BAA+B,EAC/BC,kBAAkB,EAClBC,SAAS,EACTC,eAAe,EACfC,oBAAoB,QAGf,oBAAmB;AAoC1B;;;;;;CAMC,GACD,OAAO,SAASC;IACd,MAAMC,MAAiC,CAAC;IACxC,KAAK,MAAMC,QAAQN,qBAAsB;QACvCK,GAAG,CAACC,KAAK,GAAG;YAAE,CAACP,gCAAgC,EAAEG,gBAAgBI;QAAM;IACzE;IACA,OAAOD;AACT;AAEA;;;;;;;;CAQC,GACD,OAAO,SAASE,yBACdC,QAAwB,EACxBC,OAAoC;IAEpC,IAAIA,SAASC,cAAc;QACzBP,qBAAqBM,QAAQC,YAAY;IAC3C;IAEA,MAAMC,qBAAqBP;IAC3B,MAAMQ,uBAAwBJ,UAAUE,gBAAgB,CAAC;IAEzD,+EAA+E;IAC/E,mEAAmE;IACnE,MAAMG,qBAAgD;QAAE,GAAGD,oBAAoB;IAAC;IAChF,KAAK,MAAMN,QAAQQ,OAAOC,IAAI,CAACJ,oBAAqB;QAClDE,kBAAkB,CAACP,KAAK,GAAGL,UACzBU,kBAAkB,CAACL,KAAK,EACvBM,oBAAoB,CAACN,KAAK,IAAI,CAAC;IAEpC;IAEA,MAAMU,SAAS;QACb,GAAIR,YAAY,CAAC,CAAC;QAClBE,cAAcG;IAChB;IAEA,IAAIJ,SAASQ,oBAAoB;;QAC7BD,OAA4DC,kBAAkB,GAAG;YACjF,GAAI,AAACT,UACDS,sBAAsB,CAAC,CAAC;YAC5B,GAAGR,QAAQQ,kBAAkB;QAC/B;IACF;IAEA,OAAOD;AACT"}
package/dist/index.d.ts CHANGED
@@ -13,20 +13,26 @@ export type { ThemeTab } from './fields/themeConfigurationField.js';
13
13
  export { extendedThemePresets, allExtendedThemePresets, extendedThemeToCSSVariables, } from './extended-presets.js';
14
14
  export type { ExtendedThemePreset, ShadcnColorTokens } from './extended-presets.js';
15
15
  export { applyExtendedTheme, generateExtendedThemeCSS, resetExtendedTheme, getExtendedThemeTokens, createUseExtendedTheme, getTailwindVarReferences, } from './utils/extendedThemeHelpers.js';
16
- export type { ThemeManagementPluginOptions, ThemeManagementCacheRevalidationOptions, FetchThemeConfigurationOptions, ThemeManagementLivePreviewOptions, ThemeManagementLivePreviewUrlArgs, } from './types.js';
16
+ export type { ThemeManagementPluginOptions, ThemeManagementCacheRevalidationOptions, FetchThemeConfigurationOptions, ThemeManagementLivePreviewOptions, ThemeManagementLivePreviewUrlArgs, PluginLogger, } from './types.js';
17
+ export type { SiteThemeConfiguration, ThemeColorOverride, ThemeTypographyOverride, ThemeCustomization, ThemeVisualEffects, ThemeComponentStyles, } from './payload-types.js';
17
18
  export { DEFAULT_THEME_CONFIGURATION, resolveThemeConfiguration, } from './utils/resolveThemeConfiguration.js';
18
- export type { ResolvedThemeConfiguration } from './utils/resolveThemeConfiguration.js';
19
+ export type { ResolvedThemeConfiguration, ResolvedVisualEffects, ResolvedComponentStyles, } from './utils/resolveThemeConfiguration.js';
20
+ export { allStylePresets, stylePresetCategories } from './style-presets.js';
21
+ export type { StylePreset } from './style-presets.js';
19
22
  export { generateThemeColorsCss, hexToHsl } from './utils/themeColors.js';
20
23
  export { generateThemeCSS, getThemeStyles } from './utils/themeUtils.js';
21
24
  export { getThemeHtmlAttributes } from './utils/themeHtmlAttributes.js';
22
25
  export { generateThemeCSS as generatePresetCSS, generateAllThemesCSS, } from './utils/generateThemeCSS.js';
23
26
  export { getThemeDynamicCSS, getAllDynamicThemesCSS } from './utils/themeCSS.js';
24
27
  export type { Mode, ThemeDefaults } from './providers/Theme/types.js';
25
- export { ThemeProvider } from './providers/Theme/index.js';
28
+ export { ThemeProvider, useTheme } from './providers/Theme/index.js';
26
29
  export { getFontLoaderCode, getThemeFontFamilies, ThemeFontProvider, useThemeFonts, FONT_IMPORT_MAP, } from './providers/font-loader.js';
27
30
  export declare const ThemeManagementPlugin: (options?: ThemeManagementPluginOptions) => Plugin;
28
31
  /** @deprecated use {@link themeManagementPlugin} */
29
32
  export declare const themeConfigurationPlugin: (options?: ThemeManagementPluginOptions) => Plugin;
30
- export { translations, getTranslations, registerTranslations, availableLanguages, } from './translations.js';
33
+ export { translations, getTranslations, registerTranslations, availableLanguages, THEME_MANAGEMENT_I18N_NAMESPACE, } from './translations.js';
34
+ export type { PluginTranslations, Language, DeepPartial } from './translations.js';
35
+ export { mergeThemeManagementI18n, getThemeManagementI18nTranslations, } from './i18n.js';
36
+ export type { ThemeManagementI18nOptions, ThemeManagementI18nTranslations, } from './i18n.js';
31
37
  export default themeManagementPlugin;
32
38
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAiD,MAAM,EAAa,MAAM,SAAS,CAAA;AAG/F,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,oBAAoB,CAAA;AAChE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAA;AAG/C,OAAO,KAAK,EACV,8BAA8B,EAG9B,4BAA4B,EAC7B,MAAM,YAAY,CAAA;AA2hBnB,eAAO,MAAM,qBAAqB,GAAI,UAAS,4BAAiC,KAAG,MA+NlF,CAAA;AAED,KAAK,iBAAiB,GAAG,MAAM,GAAG,8BAA8B,CAAA;AAEhE,eAAO,MAAM,uBAAuB,GAClC,UAAU,iBAAiB,KAC1B,OAAO,CAAC,sBAAsB,GAAG,IAAI,CA6EvC,CAAA;AAED,eAAO,MAAM,cAAc,GAAI,WAAW,MAAM,KAAG,WAAW,GAAG,IAEhE,CAAA;AAED,eAAO,MAAM,wBAAwB,QAAO,WAAW,EAEtD,CAAA;AAED,OAAO,EAAE,mBAAmB,EAAE,eAAe,EAAE,MAAM,cAAc,CAAA;AACnE,YAAY,EAAE,WAAW,EAAE,qBAAqB,EAAE,MAAM,cAAc,CAAA;AACtE,YAAY,EAAE,QAAQ,EAAE,MAAM,qCAAqC,CAAA;AACnE,OAAO,EACL,oBAAoB,EACpB,uBAAuB,EACvB,2BAA2B,GAC5B,MAAM,uBAAuB,CAAA;AAC9B,YAAY,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAA;AACnF,OAAO,EACL,kBAAkB,EAClB,wBAAwB,EACxB,kBAAkB,EAClB,sBAAsB,EACtB,sBAAsB,EACtB,wBAAwB,GACzB,MAAM,iCAAiC,CAAA;AACxC,YAAY,EACV,4BAA4B,EAC5B,uCAAuC,EACvC,8BAA8B,EAC9B,iCAAiC,EACjC,iCAAiC,GAClC,MAAM,YAAY,CAAA;AACnB,OAAO,EACL,2BAA2B,EAC3B,yBAAyB,GAC1B,MAAM,sCAAsC,CAAA;AAC7C,YAAY,EAAE,0BAA0B,EAAE,MAAM,sCAAsC,CAAA;AACtF,OAAO,EAAE,sBAAsB,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAA;AACzE,OAAO,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAA;AACxE,OAAO,EAAE,sBAAsB,EAAE,MAAM,gCAAgC,CAAA;AAGvE,OAAO,EACL,gBAAgB,IAAI,iBAAiB,EACrC,oBAAoB,GACrB,MAAM,6BAA6B,CAAA;AACpC,OAAO,EAAE,kBAAkB,EAAE,sBAAsB,EAAE,MAAM,qBAAqB,CAAA;AAEhF,YAAY,EAAE,IAAI,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAA;AACrE,OAAO,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAA;AAG1D,OAAO,EACL,iBAAiB,EACjB,oBAAoB,EACpB,iBAAiB,EACjB,aAAa,EACb,eAAe,GAChB,MAAM,4BAA4B,CAAA;AAMnC,eAAO,MAAM,qBAAqB,aApXa,4BAA4B,KAAQ,MAoXzB,CAAA;AAC1D,oDAAoD;AACpD,eAAO,MAAM,wBAAwB,aAtXU,4BAA4B,KAAQ,MAsXtB,CAAA;AAG7D,OAAO,EACL,YAAY,EACZ,eAAe,EACf,oBAAoB,EACpB,kBAAkB,GACnB,MAAM,mBAAmB,CAAA;AAE1B,eAAe,qBAAqB,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -1,5 +1,7 @@
1
+ import { DEFAULT_LIVE_PREVIEW_BREAKPOINTS } from './constants/devicePreviews.js';
1
2
  import { createThemeConfigurationField } from './fields/themeConfigurationField.js';
2
3
  import { allThemePresets } from './presets.js';
4
+ import { mergeThemeManagementI18n } from './i18n.js';
3
5
  import { getTranslations, translations } from './translations.js';
4
6
  const THEME_FIELD_NAME = 'themeConfiguration';
5
7
  /**
@@ -46,7 +48,7 @@ const THEME_FIELD_NAME = 'themeConfiguration';
46
48
  const tabsField = findTabsField(sanitizedFields);
47
49
  if (!tabsField || !tabsField.tabs) {
48
50
  if (enableLogging) {
49
- console.warn('🎨 Theme Management Plugin: No tabs field found. Creating a new tabs structure.');
51
+ console.warn('Theme Management Plugin: No tabs field found. Creating a new tabs structure.');
50
52
  }
51
53
  // If no tabs exist, create a basic tabs structure with just the theme tab
52
54
  const newTabsField = {
@@ -68,7 +70,7 @@ const THEME_FIELD_NAME = 'themeConfiguration';
68
70
  themeTab
69
71
  ];
70
72
  if (enableLogging) {
71
- console.log('🎨 Theme Management Plugin: injecting Appearance Settings tab');
73
+ console.log('Theme Management Plugin: injecting Appearance Settings tab');
72
74
  }
73
75
  // Update the tabs field
74
76
  const updatedTabsField = {
@@ -81,9 +83,12 @@ const THEME_FIELD_NAME = 'themeConfiguration';
81
83
  const ensureCollectionsArray = (collections)=>Array.isArray(collections) ? collections : [];
82
84
  const ensureEndpointsArray = (endpoints)=>Array.isArray(endpoints) ? endpoints : [];
83
85
  const normalizeLivePreviewOptions = (livePreview)=>{
84
- if (livePreview === false) {
86
+ if (!livePreview) {
87
+ // undefined or false → live preview not configured; show ThemePreviewField instead
85
88
  return {
86
89
  enabled: false,
90
+ injectRoute: false,
91
+ routePath: '/theme/preview',
87
92
  pageCollection: 'pages',
88
93
  pageSlug: 'home',
89
94
  fallbackToFirstPage: true,
@@ -92,15 +97,17 @@ const normalizeLivePreviewOptions = (livePreview)=>{
92
97
  breakpoints: undefined
93
98
  };
94
99
  }
95
- const raw = typeof livePreview === 'object' && livePreview ? livePreview : {};
100
+ const raw = typeof livePreview === 'object' ? livePreview : {};
96
101
  return {
97
102
  enabled: raw.enabled ?? true,
103
+ injectRoute: raw.injectRoute ?? false,
104
+ routePath: normalizeRoutePath(raw.routePath),
98
105
  pageCollection: raw.pageCollection ?? 'pages',
99
106
  pageSlug: raw.pageSlug ?? 'home',
100
107
  fallbackToFirstPage: raw.fallbackToFirstPage ?? true,
101
108
  tenantField: raw.tenantField ?? 'tenant',
102
109
  tenantQueryParam: raw.tenantQueryParam ?? 'tenant',
103
- breakpoints: raw.breakpoints,
110
+ breakpoints: raw.breakpoints ?? DEFAULT_LIVE_PREVIEW_BREAKPOINTS,
104
111
  url: raw.url
105
112
  };
106
113
  };
@@ -240,7 +247,7 @@ const resolveLivePreviewUrl = async (args)=>{
240
247
  return buildDefaultPreviewPath(resolvedPageSlug, tenantSlug, livePreview.tenantQueryParam);
241
248
  } catch (error) {
242
249
  if (enableLogging) {
243
- req.payload.logger?.warn?.('🎨 Theme Management Plugin: live preview URL fallback used', error);
250
+ req.payload.logger?.warn?.('Theme Management Plugin: live preview URL fallback used', error);
244
251
  }
245
252
  return buildDefaultPreviewPath(livePreview.pageSlug, tenantSlug, livePreview.tenantQueryParam);
246
253
  }
@@ -299,11 +306,11 @@ const executeThemeRevalidation = async (options)=>{
299
306
  tags.forEach((tag)=>revalidateTag(tag));
300
307
  paths.forEach((path)=>revalidatePath(path));
301
308
  if (enableLogging) {
302
- logger?.info?.(`🎨 Theme Management Plugin: revalidated cache tags=[${tags.join(', ')}] paths=[${paths.join(', ')}]`);
309
+ logger?.info?.(`Theme Management Plugin: revalidated cache tags=[${tags.join(', ')}] paths=[${paths.join(', ')}]`);
303
310
  }
304
311
  } catch (error) {
305
312
  if (enableLogging) {
306
- logger?.error?.('🎨 Theme Management Plugin: cache invalidation failed:', error);
313
+ logger?.error?.('Theme Management Plugin: cache invalidation failed:', error);
307
314
  }
308
315
  throw error;
309
316
  }
@@ -312,6 +319,68 @@ const executeThemeRevalidation = async (options)=>{
312
319
  paths
313
320
  };
314
321
  };
322
+ const readQueryStringFromRequest = (req, paramName)=>{
323
+ const reqRecord = asRecord(req);
324
+ // Try URLSearchParams from native fetch/Node.js
325
+ const queryValue = reqRecord?.query;
326
+ if (queryValue && typeof URLSearchParams !== 'undefined' && queryValue instanceof URLSearchParams) {
327
+ return pickString(queryValue.get(paramName));
328
+ }
329
+ // Try object form (common in Payload)
330
+ const queryRecord = asRecord(queryValue);
331
+ if (queryRecord) {
332
+ const rawValue = queryRecord[paramName];
333
+ if (Array.isArray(rawValue)) {
334
+ return pickString(rawValue[0]);
335
+ }
336
+ return pickString(rawValue);
337
+ }
338
+ // Try manual URL parsing as fallback
339
+ const urlValue = pickString(reqRecord?.url) ?? pickString(reqRecord?.originalUrl);
340
+ if (urlValue) {
341
+ try {
342
+ const url = new URL(urlValue, 'http://localhost');
343
+ return pickString(url.searchParams.get(paramName));
344
+ } catch {
345
+ // Ignore parse errors
346
+ }
347
+ }
348
+ return undefined;
349
+ };
350
+ const createLivePreviewEndpoint = (options)=>{
351
+ const { livePreview, enableLogging } = options;
352
+ if (!livePreview.enabled || !livePreview.injectRoute) {
353
+ return null;
354
+ }
355
+ return {
356
+ path: livePreview.routePath,
357
+ method: 'get',
358
+ handler: async (req)=>{
359
+ const previewSecret = process.env.PREVIEW_SECRET ?? process.env.PAYLOAD_PREVIEW_SECRET;
360
+ if (previewSecret) {
361
+ const providedSecret = readQueryStringFromRequest(req, 'previewSecret') ?? readQueryStringFromRequest(req, 'preview');
362
+ if (providedSecret !== previewSecret) {
363
+ return jsonResponse({
364
+ error: 'Unauthorized'
365
+ }, 401);
366
+ }
367
+ }
368
+ const pageSlug = readQueryStringFromRequest(req, 'pageSlug') ?? livePreview.pageSlug;
369
+ const tenantSlug = readQueryStringFromRequest(req, 'tenant');
370
+ // Redirect to the actual client page (standard Payload live preview behavior)
371
+ const destination = buildDefaultPreviewPath(pageSlug, tenantSlug, livePreview.tenantQueryParam);
372
+ if (enableLogging) {
373
+ console.log('Theme Management Plugin: live preview redirect', destination);
374
+ }
375
+ return {
376
+ status: 307,
377
+ headers: {
378
+ Location: destination
379
+ }
380
+ };
381
+ }
382
+ };
383
+ };
315
384
  const createCacheRevalidationEndpoint = (options)=>{
316
385
  const { cacheRevalidation, enableLogging } = options;
317
386
  if (!cacheRevalidation.enabled || !cacheRevalidation.injectRoute) {
@@ -356,9 +425,10 @@ const mergeEndpoint = (endpoints, endpoint)=>{
356
425
  if (!endpoint) {
357
426
  return endpoints;
358
427
  }
428
+ const record = endpoint;
359
429
  const withoutExisting = endpoints.filter((candidate)=>{
360
- const record = candidate;
361
- return !(record?.path === endpoint.path && typeof record.method === 'string' && record.method.toLowerCase() === endpoint.method);
430
+ const candidateRecord = candidate;
431
+ return !(candidateRecord?.path === record?.path && typeof candidateRecord.method === 'string' && typeof record.method === 'string' && candidateRecord.method.toLowerCase() === record.method.toLowerCase());
362
432
  });
363
433
  return [
364
434
  ...withoutExisting,
@@ -379,7 +449,7 @@ const jsonResponse = (body, status = 200)=>{
379
449
  export const themeManagementPlugin = (options = {})=>{
380
450
  return (config)=>{
381
451
  const { enabled = true, targetCollection = 'site-settings', useStandaloneCollection = false, standaloneCollectionSlug = 'appearance-settings', // Allow either string or localized object; default comes from plugin translations
382
- standaloneCollectionLabel = getTranslations().standaloneCollectionLabel, themePresets = allThemePresets, defaultTheme = 'cool', includeColorModeToggle = true, includeCustomCSS = true, includeBrandIdentity = false, enableAdvancedFeatures = true, enableLogging = false, livePreview = true, cacheRevalidation } = options;
452
+ standaloneCollectionLabel = getTranslations().standaloneCollectionLabel, themePresets = allThemePresets, defaultTheme = 'cool', includeColorModeToggle = true, includeCustomCSS = true, customThemeConfigurationFields, customThemeConfigurationSections, includeBrandIdentity = false, enableAdvancedFeatures = true, enableLogging = false, livePreview = true, cacheRevalidation, i18n } = options;
383
453
  const normalizedLivePreview = normalizeLivePreviewOptions(livePreview);
384
454
  const normalizedCacheRevalidation = normalizeCacheRevalidationOptions({
385
455
  cacheRevalidation,
@@ -388,23 +458,34 @@ export const themeManagementPlugin = (options = {})=>{
388
458
  });
389
459
  if (!enabled) {
390
460
  if (enableLogging) {
391
- console.log('🎨 Theme Management Plugin: disabled via options, skipping.');
461
+ console.log('Theme Management Plugin: disabled via options, skipping.');
392
462
  }
393
463
  return config;
394
464
  }
465
+ // Register the plugin's translations into Payload's native i18n
466
+ // (`theme-management` namespace), merging in any user-provided extensions or
467
+ // overrides. This config is used as the base for every return path below.
468
+ const configWithI18n = {
469
+ ...config,
470
+ i18n: mergeThemeManagementI18n(config.i18n, i18n)
471
+ };
395
472
  const themeTab = createThemeConfigurationField({
396
473
  themePresets,
397
474
  defaultTheme,
398
475
  includeColorModeToggle,
399
476
  includeCustomCSS,
477
+ customThemeConfigurationFields,
478
+ customThemeConfigurationSections,
400
479
  includeBrandIdentity: includeBrandIdentity ?? false,
401
480
  enableAdvancedFeatures,
402
- useThemePreviewField: !normalizedLivePreview.enabled
481
+ // Always show the static ModePreview panel; it hides at runtime when the user
482
+ // actively enters livePreview mode (isLivePreviewing = true in context).
483
+ useThemePreviewField: true
403
484
  });
404
485
  // If using standalone collection, create a new global
405
486
  if (useStandaloneCollection) {
406
487
  if (enableLogging) {
407
- console.log(`🎨 Theme Management Plugin: creating standalone global "${standaloneCollectionSlug}"`);
488
+ console.log(`Theme Management Plugin: creating standalone global "${standaloneCollectionSlug}"`);
408
489
  }
409
490
  // Extract the fields from the tab directly (no wrapping in group)
410
491
  const tabFields = themeTab.fields ?? [];
@@ -481,23 +562,28 @@ export const themeManagementPlugin = (options = {})=>{
481
562
  ]
482
563
  }
483
564
  };
484
- const globals = Array.isArray(config.globals) ? config.globals : [];
565
+ const globals = Array.isArray(configWithI18n.globals) ? configWithI18n.globals : [];
485
566
  // Check if global already exists
486
567
  const existingIndex = globals.findIndex((g)=>g.slug === standaloneCollectionSlug);
487
568
  if (existingIndex !== -1) {
488
569
  if (enableLogging) {
489
- console.warn(`🎨 Theme Management Plugin: global "${standaloneCollectionSlug}" already exists, skipping creation.`);
570
+ console.warn(`Theme Management Plugin: global "${standaloneCollectionSlug}" already exists, skipping creation.`);
490
571
  }
491
- return config;
572
+ return configWithI18n;
492
573
  }
493
- const currentEndpoints = ensureEndpointsArray(config.endpoints);
574
+ const currentEndpoints = ensureEndpointsArray(configWithI18n.endpoints);
575
+ const livePreviewEndpoint = createLivePreviewEndpoint({
576
+ livePreview: normalizedLivePreview,
577
+ enableLogging
578
+ });
579
+ let endpoints = mergeEndpoint(currentEndpoints, livePreviewEndpoint);
494
580
  const cacheEndpoint = createCacheRevalidationEndpoint({
495
581
  cacheRevalidation: normalizedCacheRevalidation,
496
582
  enableLogging
497
583
  });
498
- const endpoints = mergeEndpoint(currentEndpoints, cacheEndpoint);
584
+ endpoints = mergeEndpoint(endpoints, cacheEndpoint);
499
585
  return {
500
- ...config,
586
+ ...configWithI18n,
501
587
  endpoints,
502
588
  globals: [
503
589
  ...globals,
@@ -507,13 +593,13 @@ export const themeManagementPlugin = (options = {})=>{
507
593
  }
508
594
  // Otherwise, add as tab to existing collection
509
595
  let collectionTouched = false;
510
- const collections = ensureCollectionsArray(config.collections).map((collection)=>{
596
+ const collections = ensureCollectionsArray(configWithI18n.collections).map((collection)=>{
511
597
  if (collection.slug !== targetCollection) {
512
598
  return collection;
513
599
  }
514
600
  collectionTouched = true;
515
601
  if (enableLogging) {
516
- console.log(`🎨 Theme Management Plugin: enhancing collection "${collection.slug}"`);
602
+ console.log(`Theme Management Plugin: enhancing collection "${collection.slug}"`);
517
603
  }
518
604
  const existingFields = Array.isArray(collection.fields) ? collection.fields : [];
519
605
  const fields = injectThemeTab(existingFields, themeTab, enableLogging);
@@ -529,18 +615,23 @@ export const themeManagementPlugin = (options = {})=>{
529
615
  });
530
616
  if (!collectionTouched) {
531
617
  if (enableLogging) {
532
- console.warn(`🎨 Theme Management Plugin: collection "${targetCollection}" was not found, leaving config untouched.`);
618
+ console.warn(`Theme Management Plugin: collection "${targetCollection}" was not found, leaving config untouched.`);
533
619
  }
534
- return config;
620
+ return configWithI18n;
535
621
  }
536
- const currentEndpoints = ensureEndpointsArray(config.endpoints);
622
+ const currentEndpoints = ensureEndpointsArray(configWithI18n.endpoints);
623
+ const livePreviewEndpoint = createLivePreviewEndpoint({
624
+ livePreview: normalizedLivePreview,
625
+ enableLogging
626
+ });
627
+ let endpoints = mergeEndpoint(currentEndpoints, livePreviewEndpoint);
537
628
  const cacheEndpoint = createCacheRevalidationEndpoint({
538
629
  cacheRevalidation: normalizedCacheRevalidation,
539
630
  enableLogging
540
631
  });
541
- const endpoints = mergeEndpoint(currentEndpoints, cacheEndpoint);
632
+ endpoints = mergeEndpoint(endpoints, cacheEndpoint);
542
633
  return {
543
- ...config,
634
+ ...configWithI18n,
544
635
  endpoints,
545
636
  collections
546
637
  };
@@ -550,7 +641,7 @@ export const fetchThemeConfiguration = async (options)=>{
550
641
  const normalizedOptions = typeof options === 'string' ? {
551
642
  tenantSlug: options
552
643
  } : options ?? {};
553
- const { tenantSlug, collectionSlug = 'site-settings', depth, locale, draft, queryParams = {}, useGlobal = false } = normalizedOptions;
644
+ const { tenantSlug, collectionSlug = 'site-settings', depth, locale, draft, queryParams = {}, useGlobal = false, signal } = normalizedOptions;
554
645
  try {
555
646
  if (useGlobal) {
556
647
  // Fetch from global endpoint
@@ -567,7 +658,9 @@ export const fetchThemeConfiguration = async (options)=>{
567
658
  });
568
659
  const queryString = params.toString();
569
660
  const url = `/api/globals/${collectionSlug}${queryString ? `?${queryString}` : ''}`;
570
- const response = await fetch(url);
661
+ const response = await fetch(url, {
662
+ signal
663
+ });
571
664
  if (!response.ok) {
572
665
  throw new Error(`Failed to fetch theme global (status ${response.status})`);
573
666
  }
@@ -588,7 +681,9 @@ export const fetchThemeConfiguration = async (options)=>{
588
681
  params.set(key, String(value));
589
682
  });
590
683
  const url = `/api/${collectionSlug}?${params.toString()}`;
591
- const response = await fetch(url);
684
+ const response = await fetch(url, {
685
+ signal
686
+ });
592
687
  if (!response.ok) {
593
688
  throw new Error(`Failed to fetch theme configuration (status ${response.status})`);
594
689
  }
@@ -611,13 +706,14 @@ export { defaultThemePresets, allThemePresets } from './presets.js';
611
706
  export { extendedThemePresets, allExtendedThemePresets, extendedThemeToCSSVariables } from './extended-presets.js';
612
707
  export { applyExtendedTheme, generateExtendedThemeCSS, resetExtendedTheme, getExtendedThemeTokens, createUseExtendedTheme, getTailwindVarReferences } from './utils/extendedThemeHelpers.js';
613
708
  export { DEFAULT_THEME_CONFIGURATION, resolveThemeConfiguration } from './utils/resolveThemeConfiguration.js';
709
+ export { allStylePresets, stylePresetCategories } from './style-presets.js';
614
710
  export { generateThemeColorsCss, hexToHsl } from './utils/themeColors.js';
615
711
  export { generateThemeCSS, getThemeStyles } from './utils/themeUtils.js';
616
712
  export { getThemeHtmlAttributes } from './utils/themeHtmlAttributes.js';
617
713
  // Dynamic theme CSS generation
618
714
  export { generateThemeCSS as generatePresetCSS, generateAllThemesCSS } from './utils/generateThemeCSS.js';
619
715
  export { getThemeDynamicCSS, getAllDynamicThemesCSS } from './utils/themeCSS.js';
620
- export { ThemeProvider } from './providers/Theme/index.js';
716
+ export { ThemeProvider, useTheme } from './providers/Theme/index.js';
621
717
  // Font loading utilities for Next.js integration
622
718
  export { getFontLoaderCode, getThemeFontFamilies, ThemeFontProvider, useThemeFonts, FONT_IMPORT_MAP } from './providers/font-loader.js';
623
719
  // Note: Do NOT re-export client components from the root entry to avoid
@@ -626,7 +722,9 @@ export { getFontLoaderCode, getThemeFontFamilies, ThemeFontProvider, useThemeFon
626
722
  export const ThemeManagementPlugin = themeManagementPlugin;
627
723
  /** @deprecated use {@link themeManagementPlugin} */ export const themeConfigurationPlugin = themeManagementPlugin;
628
724
  // Export plugin translations for consumers to merge into their payload translations
629
- export { translations, getTranslations, registerTranslations, availableLanguages } from './translations.js';
725
+ export { translations, getTranslations, registerTranslations, availableLanguages, THEME_MANAGEMENT_I18N_NAMESPACE } from './translations.js';
726
+ // Native Payload i18n helpers (theme-management namespace)
727
+ export { mergeThemeManagementI18n, getThemeManagementI18nTranslations } from './i18n.js';
630
728
  export default themeManagementPlugin;
631
729
 
632
730
  //# sourceMappingURL=index.js.map