@kilivi/payloadcms-theme-management 0.5.8 → 1.0.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 (57) hide show
  1. package/README.md +531 -40
  2. package/dist/app/api/google-fonts/route.d.ts +31 -0
  3. package/dist/app/api/google-fonts/route.d.ts.map +1 -0
  4. package/dist/app/api/google-fonts/route.js +925 -0
  5. package/dist/app/api/google-fonts/route.js.map +1 -0
  6. package/dist/fields/FontSelectField.js +1 -1
  7. package/dist/fields/FontSelectField.js.map +1 -1
  8. package/dist/fields/ThemeTokenSelectField.d.ts.map +1 -1
  9. package/dist/fields/ThemeTokenSelectField.js +12 -5
  10. package/dist/fields/ThemeTokenSelectField.js.map +1 -1
  11. package/dist/fields/themeConfigurationField.d.ts.map +1 -1
  12. package/dist/fields/themeConfigurationField.js +25 -15
  13. package/dist/fields/themeConfigurationField.js.map +1 -1
  14. package/dist/globals/ThemeSettings/FontPicker/FontPreview.d.ts +17 -0
  15. package/dist/globals/ThemeSettings/FontPicker/FontPreview.d.ts.map +1 -0
  16. package/dist/globals/ThemeSettings/FontPicker/FontPreview.js +229 -0
  17. package/dist/globals/ThemeSettings/FontPicker/FontPreview.js.map +1 -0
  18. package/dist/globals/ThemeSettings/FontPicker/PreviewContent.d.ts +20 -0
  19. package/dist/globals/ThemeSettings/FontPicker/PreviewContent.d.ts.map +1 -0
  20. package/dist/globals/ThemeSettings/FontPicker/PreviewContent.js +400 -0
  21. package/dist/globals/ThemeSettings/FontPicker/PreviewContent.js.map +1 -0
  22. package/dist/globals/ThemeSettings/FontPicker/index.d.ts +25 -0
  23. package/dist/globals/ThemeSettings/FontPicker/index.d.ts.map +1 -0
  24. package/dist/globals/ThemeSettings/FontPicker/index.js +483 -0
  25. package/dist/globals/ThemeSettings/FontPicker/index.js.map +1 -0
  26. package/dist/globals/ThemeSettings/FontPicker/styles.css +337 -0
  27. package/dist/globals/ThemeSettings/FontPicker/translations.d.ts +76 -0
  28. package/dist/globals/ThemeSettings/FontPicker/translations.d.ts.map +1 -0
  29. package/dist/globals/ThemeSettings/FontPicker/translations.js +147 -0
  30. package/dist/globals/ThemeSettings/FontPicker/translations.js.map +1 -0
  31. package/dist/globals/ThemeSettings/config.d.ts +10 -0
  32. package/dist/globals/ThemeSettings/config.d.ts.map +1 -0
  33. package/dist/globals/ThemeSettings/config.js +171 -0
  34. package/dist/globals/ThemeSettings/config.js.map +1 -0
  35. package/dist/globals/ThemeSettings/fields/FontLoadingGuideField.d.ts +5 -0
  36. package/dist/globals/ThemeSettings/fields/FontLoadingGuideField.d.ts.map +1 -0
  37. package/dist/globals/ThemeSettings/fields/FontLoadingGuideField.js +177 -0
  38. package/dist/globals/ThemeSettings/fields/FontLoadingGuideField.js.map +1 -0
  39. package/dist/globals/ThemeSettings/fields/TypographyInfoField.d.ts +5 -0
  40. package/dist/globals/ThemeSettings/fields/TypographyInfoField.d.ts.map +1 -0
  41. package/dist/globals/ThemeSettings/fields/TypographyInfoField.js +89 -0
  42. package/dist/globals/ThemeSettings/fields/TypographyInfoField.js.map +1 -0
  43. package/dist/globals/ThemeSettings/index.d.ts +4 -0
  44. package/dist/globals/ThemeSettings/index.d.ts.map +1 -0
  45. package/dist/globals/ThemeSettings/index.js +4 -0
  46. package/dist/globals/ThemeSettings/index.js.map +1 -0
  47. package/dist/index.d.ts.map +1 -1
  48. package/dist/index.js +119 -20
  49. package/dist/index.js.map +1 -1
  50. package/dist/types.d.ts +9 -1
  51. package/dist/types.d.ts.map +1 -1
  52. package/dist/types.js.map +1 -1
  53. package/dist/utilities/getThemeSettings.d.ts +34 -0
  54. package/dist/utilities/getThemeSettings.d.ts.map +1 -0
  55. package/dist/utilities/getThemeSettings.js +67 -0
  56. package/dist/utilities/getThemeSettings.js.map +1 -0
  57. package/package.json +2 -2
package/dist/index.js CHANGED
@@ -69,7 +69,7 @@ const THEME_FIELD_NAME = 'themeConfiguration';
69
69
  const ensureCollectionsArray = (collections)=>Array.isArray(collections) ? collections : [];
70
70
  export const themeManagementPlugin = (options = {})=>{
71
71
  return (config)=>{
72
- const { enabled = true, targetCollection = 'site-settings', themePresets = allThemePresets, defaultTheme = 'cool', includeColorModeToggle = true, includeCustomCSS = true, includeBrandIdentity = false, enableAdvancedFeatures = true, enableLogging = false } = options;
72
+ const { enabled = true, targetCollection = 'site-settings', useStandaloneCollection = false, standaloneCollectionSlug = 'appearance-settings', standaloneCollectionLabel = 'Appearance Settings', themePresets = allThemePresets, defaultTheme = 'cool', includeColorModeToggle = true, includeCustomCSS = true, includeBrandIdentity = false, enableAdvancedFeatures = true, enableLogging = false } = options;
73
73
  if (!enabled) {
74
74
  if (enableLogging) {
75
75
  console.log('🎨 Theme Management Plugin: disabled via options, skipping.');
@@ -84,6 +84,83 @@ export const themeManagementPlugin = (options = {})=>{
84
84
  includeBrandIdentity: includeBrandIdentity ?? false,
85
85
  enableAdvancedFeatures
86
86
  });
87
+ // If using standalone collection, create a new global
88
+ if (useStandaloneCollection) {
89
+ if (enableLogging) {
90
+ console.log(`🎨 Theme Management Plugin: creating standalone global "${standaloneCollectionSlug}"`);
91
+ }
92
+ // Extract the fields from the tab directly (no wrapping in group)
93
+ const tabFields = themeTab.fields ?? [];
94
+ /**
95
+ * Hook to auto-populate lightMode and darkMode colors when theme changes
96
+ */ const beforeChangeHook = async (args)=>{
97
+ const { data } = args;
98
+ // If theme is being changed, auto-populate color modes
99
+ if (data?.themeConfiguration?.theme) {
100
+ const themeName = data.themeConfiguration.theme;
101
+ const selectedPreset = themePresets.find((p)=>p.name === themeName);
102
+ if (selectedPreset) {
103
+ // Initialize light and dark mode colors from preset if not already set
104
+ if (!data.themeConfiguration.lightMode) {
105
+ data.themeConfiguration.lightMode = {};
106
+ }
107
+ if (!data.themeConfiguration.darkMode) {
108
+ data.themeConfiguration.darkMode = {};
109
+ }
110
+ // Only populate if not manually edited (first time or empty)
111
+ const isLightModeEmpty = !data.themeConfiguration.lightMode?.background;
112
+ const isDarkModeEmpty = !data.themeConfiguration.darkMode?.background;
113
+ if (isLightModeEmpty && selectedPreset.lightMode) {
114
+ data.themeConfiguration.lightMode = {
115
+ ...selectedPreset.lightMode
116
+ };
117
+ }
118
+ if (isDarkModeEmpty && selectedPreset.darkMode) {
119
+ data.themeConfiguration.darkMode = {
120
+ ...selectedPreset.darkMode
121
+ };
122
+ }
123
+ }
124
+ }
125
+ return data;
126
+ };
127
+ const standaloneGlobal = {
128
+ slug: standaloneCollectionSlug,
129
+ label: standaloneCollectionLabel,
130
+ admin: {
131
+ group: 'Settings'
132
+ },
133
+ access: {
134
+ read: ()=>true,
135
+ create: ({ req })=>!!req?.user,
136
+ update: ({ req })=>!!req?.user,
137
+ delete: ({ req })=>!!req?.user
138
+ },
139
+ fields: tabFields,
140
+ hooks: {
141
+ beforeChange: [
142
+ beforeChangeHook
143
+ ]
144
+ }
145
+ };
146
+ const globals = Array.isArray(config.globals) ? config.globals : [];
147
+ // Check if global already exists
148
+ const existingIndex = globals.findIndex((g)=>g.slug === standaloneCollectionSlug);
149
+ if (existingIndex !== -1) {
150
+ if (enableLogging) {
151
+ console.warn(`🎨 Theme Management Plugin: global "${standaloneCollectionSlug}" already exists, skipping creation.`);
152
+ }
153
+ return config;
154
+ }
155
+ return {
156
+ ...config,
157
+ globals: [
158
+ ...globals,
159
+ standaloneGlobal
160
+ ]
161
+ };
162
+ }
163
+ // Otherwise, add as tab to existing collection
87
164
  let collectionTouched = false;
88
165
  const collections = ensureCollectionsArray(config.collections).map((collection)=>{
89
166
  if (collection.slug !== targetCollection) {
@@ -116,27 +193,49 @@ export const fetchThemeConfiguration = async (options)=>{
116
193
  const normalizedOptions = typeof options === 'string' ? {
117
194
  tenantSlug: options
118
195
  } : options ?? {};
119
- const { tenantSlug, collectionSlug = 'site-settings', depth, locale, draft, queryParams = {} } = normalizedOptions;
120
- const params = new URLSearchParams({
121
- limit: '1'
122
- });
123
- if (typeof depth === 'number') params.set('depth', String(depth));
124
- if (tenantSlug) params.set('tenant', tenantSlug);
125
- if (locale) params.set('locale', locale);
126
- if (draft) params.set('draft', 'true');
127
- Object.entries(queryParams).forEach(([key, value])=>{
128
- if (value === undefined) return;
129
- params.set(key, String(value));
130
- });
131
- const url = `/api/${collectionSlug}?${params.toString()}`;
196
+ const { tenantSlug, collectionSlug = 'site-settings', depth, locale, draft, queryParams = {}, useGlobal = false } = normalizedOptions;
132
197
  try {
133
- const response = await fetch(url);
134
- if (!response.ok) {
135
- throw new Error(`Failed to fetch theme configuration (status ${response.status})`);
198
+ if (useGlobal) {
199
+ // Fetch from global endpoint
200
+ const params = new URLSearchParams();
201
+ if (typeof depth === 'number') params.set('depth', String(depth));
202
+ if (tenantSlug) params.set('tenant', tenantSlug);
203
+ if (locale) params.set('locale', locale);
204
+ if (draft) params.set('draft', 'true');
205
+ Object.entries(queryParams).forEach(([key, value])=>{
206
+ if (value === undefined) return;
207
+ params.set(key, String(value));
208
+ });
209
+ const queryString = params.toString();
210
+ const url = `/api/globals/${collectionSlug}${queryString ? `?${queryString}` : ''}`;
211
+ const response = await fetch(url);
212
+ if (!response.ok) {
213
+ throw new Error(`Failed to fetch theme global (status ${response.status})`);
214
+ }
215
+ const data = await response.json();
216
+ return data?.themeConfiguration ?? null;
217
+ } else {
218
+ // Fetch from collection endpoint (legacy/default behavior)
219
+ const params = new URLSearchParams({
220
+ limit: '1'
221
+ });
222
+ if (typeof depth === 'number') params.set('depth', String(depth));
223
+ if (tenantSlug) params.set('tenant', tenantSlug);
224
+ if (locale) params.set('locale', locale);
225
+ if (draft) params.set('draft', 'true');
226
+ Object.entries(queryParams).forEach(([key, value])=>{
227
+ if (value === undefined) return;
228
+ params.set(key, String(value));
229
+ });
230
+ const url = `/api/${collectionSlug}?${params.toString()}`;
231
+ const response = await fetch(url);
232
+ if (!response.ok) {
233
+ throw new Error(`Failed to fetch theme configuration (status ${response.status})`);
234
+ }
235
+ const data = await response.json();
236
+ const doc = data.docs?.[0];
237
+ return doc?.themeConfiguration ?? null;
136
238
  }
137
- const data = await response.json();
138
- const doc = data.docs?.[0];
139
- return doc?.themeConfiguration ?? null;
140
239
  } catch (error) {
141
240
  console.warn('Failed to fetch theme configuration:', error);
142
241
  return null;
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts"],"sourcesContent":["import type { CollectionConfig, Config, Field, Plugin, TabsField } from 'payload'\nimport { createThemeConfigurationField } from './fields/themeConfigurationField.js'\nimport type { ThemeTab } from './fields/themeConfigurationField.js'\nimport type { SiteThemeConfiguration } from './payload-types.js'\nimport type { ThemePreset } from './presets.js'\nimport { allThemePresets } from './presets.js'\nimport type { FetchThemeConfigurationOptions, ThemeManagementPluginOptions } from './types.js'\n\nconst THEME_FIELD_NAME = 'themeConfiguration'\n\n/**\n * Removes existing theme configuration from a group field (legacy)\n */\nconst removeExistingThemeField = (fields: Field[] = []): Field[] =>\n fields.filter((field) => {\n const candidate = field as { name?: unknown }\n return candidate?.name !== THEME_FIELD_NAME\n })\n\n/**\n * Finds the tabs field in the collection fields array\n */\nconst findTabsField = (fields: Field[] = []): TabsField | null => {\n for (const field of fields) {\n if (field.type === 'tabs') {\n return field as TabsField\n }\n }\n return null\n}\n\n/**\n * Removes existing Appearance Settings tab if it exists\n */\nconst removeExistingThemeTab = (\n tabs: NonNullable<TabsField['tabs']>,\n): NonNullable<TabsField['tabs']> => {\n return tabs.filter((tab) => {\n const labelEn =\n typeof tab.label === 'object' && tab.label !== null\n ? (tab.label as { en?: string }).en\n : tab.label\n return labelEn !== '🎨 Appearance Settings' && labelEn !== 'Appearance Settings'\n })\n}\n\n/**\n * Injects theme tab into existing tabs field\n */\nconst injectThemeTab = (\n fields: Field[] | undefined,\n themeTab: ThemeTab,\n enableLogging: boolean,\n): Field[] => {\n // First, remove any legacy theme field (group-based)\n const sanitizedFields = removeExistingThemeField(fields ?? [])\n\n // Find the tabs field\n const tabsField = findTabsField(sanitizedFields)\n\n if (!tabsField || !tabsField.tabs) {\n if (enableLogging) {\n console.warn(\n '🎨 Theme Management Plugin: No tabs field found. Creating a new tabs structure.',\n )\n }\n\n // If no tabs exist, create a basic tabs structure with just the theme tab\n const newTabsField: TabsField = {\n type: 'tabs',\n tabs: [themeTab],\n }\n\n return [...sanitizedFields, newTabsField]\n }\n\n // Remove existing theme tab if present\n const sanitizedTabs = removeExistingThemeTab(tabsField.tabs)\n\n // Add theme tab to the end\n const updatedTabs = [...sanitizedTabs, themeTab]\n\n if (enableLogging) {\n console.log('🎨 Theme Management Plugin: injecting Appearance Settings tab')\n }\n\n // Update the tabs field\n const updatedTabsField: TabsField = {\n ...tabsField,\n tabs: updatedTabs,\n }\n\n // Replace the old tabs field with the updated one\n return sanitizedFields.map((field) => (field.type === 'tabs' ? updatedTabsField : field))\n}\n\nconst ensureCollectionsArray = (collections: Config['collections']): CollectionConfig[] =>\n Array.isArray(collections) ? collections : []\n\nexport const themeManagementPlugin = (options: ThemeManagementPluginOptions = {}): Plugin => {\n return (config: Config): Config => {\n const {\n enabled = true,\n targetCollection = 'site-settings',\n themePresets = allThemePresets,\n defaultTheme = 'cool',\n includeColorModeToggle = true,\n includeCustomCSS = true,\n includeBrandIdentity = false,\n enableAdvancedFeatures = true,\n enableLogging = false,\n } = options\n\n if (!enabled) {\n if (enableLogging) {\n console.log('🎨 Theme Management Plugin: disabled via options, skipping.')\n }\n return config\n }\n\n const themeTab = createThemeConfigurationField({\n themePresets,\n defaultTheme,\n includeColorModeToggle,\n includeCustomCSS,\n includeBrandIdentity: includeBrandIdentity ?? false,\n enableAdvancedFeatures,\n })\n\n let collectionTouched = false\n\n const collections = ensureCollectionsArray(config.collections).map((collection) => {\n if (collection.slug !== targetCollection) {\n return collection\n }\n\n collectionTouched = true\n\n if (enableLogging) {\n console.log(`🎨 Theme Management Plugin: enhancing collection \"${collection.slug}\"`)\n }\n\n const existingFields = Array.isArray(collection.fields) ? collection.fields : []\n\n const fields = injectThemeTab(existingFields, themeTab, enableLogging)\n\n return {\n ...collection,\n fields,\n }\n })\n\n if (!collectionTouched) {\n if (enableLogging) {\n console.warn(\n `🎨 Theme Management Plugin: collection \"${targetCollection}\" was not found, leaving config untouched.`,\n )\n }\n return config\n }\n\n return {\n ...config,\n collections,\n }\n }\n}\n\ntype FetchOptionsInput = string | FetchThemeConfigurationOptions\n\nexport const fetchThemeConfiguration = async (\n options?: FetchOptionsInput,\n): Promise<SiteThemeConfiguration | null> => {\n const normalizedOptions = typeof options === 'string' ? { tenantSlug: options } : (options ?? {})\n\n const {\n tenantSlug,\n collectionSlug = 'site-settings',\n depth,\n locale,\n draft,\n queryParams = {},\n } = normalizedOptions\n\n const params = new URLSearchParams({ limit: '1' })\n\n if (typeof depth === 'number') params.set('depth', String(depth))\n if (tenantSlug) params.set('tenant', tenantSlug)\n if (locale) params.set('locale', locale)\n if (draft) params.set('draft', 'true')\n\n Object.entries(queryParams).forEach(([key, value]) => {\n if (value === undefined) return\n params.set(key, String(value))\n })\n\n const url = `/api/${collectionSlug}?${params.toString()}`\n\n try {\n const response = await fetch(url)\n if (!response.ok) {\n throw new Error(`Failed to fetch theme configuration (status ${response.status})`)\n }\n\n const data = (await response.json()) as {\n docs?: Array<{ themeConfiguration?: SiteThemeConfiguration }>\n }\n\n const doc = data.docs?.[0]\n\n return doc?.themeConfiguration ?? null\n } catch (error) {\n console.warn('Failed to fetch theme configuration:', error)\n return null\n }\n}\n\nexport const getThemePreset = (themeName: string): ThemePreset | null => {\n return allThemePresets.find((preset) => preset.name === themeName) || null\n}\n\nexport const getAvailableThemePresets = (): ThemePreset[] => {\n return allThemePresets\n}\n\nexport { defaultThemePresets, allThemePresets } from './presets.js'\nexport type { ThemePreset, ThemeTypographyPreset } from './presets.js'\nexport type { ThemeTab } from './fields/themeConfigurationField.js'\nexport {\n extendedThemePresets,\n allExtendedThemePresets,\n extendedThemeToCSSVariables,\n} from './extended-presets.js'\nexport type { ExtendedThemePreset, ShadcnColorTokens } from './extended-presets.js'\nexport {\n applyExtendedTheme,\n generateExtendedThemeCSS,\n resetExtendedTheme,\n getExtendedThemeTokens,\n createUseExtendedTheme,\n getTailwindVarReferences,\n} from './utils/extendedThemeHelpers.js'\nexport type { ThemeManagementPluginOptions, FetchThemeConfigurationOptions } from './types.js'\nexport {\n DEFAULT_THEME_CONFIGURATION,\n resolveThemeConfiguration,\n} from './utils/resolveThemeConfiguration.js'\nexport type { ResolvedThemeConfiguration } from './utils/resolveThemeConfiguration.js'\nexport { generateThemeColorsCss, hexToHsl } from './utils/themeColors.js'\nexport { generateThemeCSS, getThemeStyles } from './utils/themeUtils.js'\nexport { getThemeHtmlAttributes } from './utils/themeHtmlAttributes.js'\n\n// Dynamic theme CSS generation\nexport {\n generateThemeCSS as generatePresetCSS,\n generateAllThemesCSS,\n} from './utils/generateThemeCSS.js'\nexport { getThemeDynamicCSS, getAllDynamicThemesCSS } from './utils/themeCSS.js'\n\nexport type { Mode, ThemeDefaults } from './providers/Theme/types.js'\nexport { ThemeProvider } from './providers/Theme/index.js'\n\n// Font loading utilities for Next.js integration\nexport {\n getFontLoaderCode,\n getThemeFontFamilies,\n ThemeFontProvider,\n useThemeFonts,\n FONT_IMPORT_MAP,\n} from './providers/font-loader.js'\n\n// Note: Do NOT re-export client components from the root entry to avoid\n// server-side evaluation during `payload generate:importmap`.\n// If needed, import directly from subpath: `@kilivi/payloadcms-theme-management/fields/ThemeLivePreview`\n\nexport const ThemeManagementPlugin = themeManagementPlugin\n/** @deprecated use {@link themeManagementPlugin} */\nexport const themeConfigurationPlugin = themeManagementPlugin\n\nexport default themeManagementPlugin\n"],"names":["createThemeConfigurationField","allThemePresets","THEME_FIELD_NAME","removeExistingThemeField","fields","filter","field","candidate","name","findTabsField","type","removeExistingThemeTab","tabs","tab","labelEn","label","en","injectThemeTab","themeTab","enableLogging","sanitizedFields","tabsField","console","warn","newTabsField","sanitizedTabs","updatedTabs","log","updatedTabsField","map","ensureCollectionsArray","collections","Array","isArray","themeManagementPlugin","options","config","enabled","targetCollection","themePresets","defaultTheme","includeColorModeToggle","includeCustomCSS","includeBrandIdentity","enableAdvancedFeatures","collectionTouched","collection","slug","existingFields","fetchThemeConfiguration","normalizedOptions","tenantSlug","collectionSlug","depth","locale","draft","queryParams","params","URLSearchParams","limit","set","String","Object","entries","forEach","key","value","undefined","url","toString","response","fetch","ok","Error","status","data","json","doc","docs","themeConfiguration","error","getThemePreset","themeName","find","preset","getAvailableThemePresets","defaultThemePresets","extendedThemePresets","allExtendedThemePresets","extendedThemeToCSSVariables","applyExtendedTheme","generateExtendedThemeCSS","resetExtendedTheme","getExtendedThemeTokens","createUseExtendedTheme","getTailwindVarReferences","DEFAULT_THEME_CONFIGURATION","resolveThemeConfiguration","generateThemeColorsCss","hexToHsl","generateThemeCSS","getThemeStyles","getThemeHtmlAttributes","generatePresetCSS","generateAllThemesCSS","getThemeDynamicCSS","getAllDynamicThemesCSS","ThemeProvider","getFontLoaderCode","getThemeFontFamilies","ThemeFontProvider","useThemeFonts","FONT_IMPORT_MAP","ThemeManagementPlugin","themeConfigurationPlugin"],"mappings":"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"}
1
+ {"version":3,"sources":["../src/index.ts"],"sourcesContent":["import type { CollectionConfig, Config, Field, Plugin, TabsField } from 'payload'\nimport { createThemeConfigurationField } from './fields/themeConfigurationField.js'\nimport type { ThemeTab } from './fields/themeConfigurationField.js'\nimport type { SiteThemeConfiguration } from './payload-types.js'\nimport type { ThemePreset } from './presets.js'\nimport { allThemePresets } from './presets.js'\nimport type { FetchThemeConfigurationOptions, ThemeManagementPluginOptions } from './types.js'\n\nconst THEME_FIELD_NAME = 'themeConfiguration'\n\n/**\n * Removes existing theme configuration from a group field (legacy)\n */\nconst removeExistingThemeField = (fields: Field[] = []): Field[] =>\n fields.filter((field) => {\n const candidate = field as { name?: unknown }\n return candidate?.name !== THEME_FIELD_NAME\n })\n\n/**\n * Finds the tabs field in the collection fields array\n */\nconst findTabsField = (fields: Field[] = []): TabsField | null => {\n for (const field of fields) {\n if (field.type === 'tabs') {\n return field as TabsField\n }\n }\n return null\n}\n\n/**\n * Removes existing Appearance Settings tab if it exists\n */\nconst removeExistingThemeTab = (\n tabs: NonNullable<TabsField['tabs']>,\n): NonNullable<TabsField['tabs']> => {\n return tabs.filter((tab) => {\n const labelEn =\n typeof tab.label === 'object' && tab.label !== null\n ? (tab.label as { en?: string }).en\n : tab.label\n return labelEn !== '🎨 Appearance Settings' && labelEn !== 'Appearance Settings'\n })\n}\n\n/**\n * Injects theme tab into existing tabs field\n */\nconst injectThemeTab = (\n fields: Field[] | undefined,\n themeTab: ThemeTab,\n enableLogging: boolean,\n): Field[] => {\n // First, remove any legacy theme field (group-based)\n const sanitizedFields = removeExistingThemeField(fields ?? [])\n\n // Find the tabs field\n const tabsField = findTabsField(sanitizedFields)\n\n if (!tabsField || !tabsField.tabs) {\n if (enableLogging) {\n console.warn(\n '🎨 Theme Management Plugin: No tabs field found. Creating a new tabs structure.',\n )\n }\n\n // If no tabs exist, create a basic tabs structure with just the theme tab\n const newTabsField: TabsField = {\n type: 'tabs',\n tabs: [themeTab],\n }\n\n return [...sanitizedFields, newTabsField]\n }\n\n // Remove existing theme tab if present\n const sanitizedTabs = removeExistingThemeTab(tabsField.tabs)\n\n // Add theme tab to the end\n const updatedTabs = [...sanitizedTabs, themeTab]\n\n if (enableLogging) {\n console.log('🎨 Theme Management Plugin: injecting Appearance Settings tab')\n }\n\n // Update the tabs field\n const updatedTabsField: TabsField = {\n ...tabsField,\n tabs: updatedTabs,\n }\n\n // Replace the old tabs field with the updated one\n return sanitizedFields.map((field) => (field.type === 'tabs' ? updatedTabsField : field))\n}\n\nconst ensureCollectionsArray = (collections: Config['collections']): CollectionConfig[] =>\n Array.isArray(collections) ? collections : []\n\nexport const themeManagementPlugin = (options: ThemeManagementPluginOptions = {}): Plugin => {\n return (config: Config): Config => {\n const {\n enabled = true,\n targetCollection = 'site-settings',\n useStandaloneCollection = false,\n standaloneCollectionSlug = 'appearance-settings',\n standaloneCollectionLabel = 'Appearance Settings',\n themePresets = allThemePresets,\n defaultTheme = 'cool',\n includeColorModeToggle = true,\n includeCustomCSS = true,\n includeBrandIdentity = false,\n enableAdvancedFeatures = true,\n enableLogging = false,\n } = options\n\n if (!enabled) {\n if (enableLogging) {\n console.log('🎨 Theme Management Plugin: disabled via options, skipping.')\n }\n return config\n }\n\n const themeTab = createThemeConfigurationField({\n themePresets,\n defaultTheme,\n includeColorModeToggle,\n includeCustomCSS,\n includeBrandIdentity: includeBrandIdentity ?? false,\n enableAdvancedFeatures,\n })\n\n // If using standalone collection, create a new global\n if (useStandaloneCollection) {\n if (enableLogging) {\n console.log(\n `🎨 Theme Management Plugin: creating standalone global \"${standaloneCollectionSlug}\"`,\n )\n }\n\n // Extract the fields from the tab directly (no wrapping in group)\n const tabFields = (themeTab.fields ?? []) as Field[]\n\n /**\n * Hook to auto-populate lightMode and darkMode colors when theme changes\n */\n const beforeChangeHook = async (args: any) => {\n const { data } = args\n\n // If theme is being changed, auto-populate color modes\n if (data?.themeConfiguration?.theme) {\n const themeName = data.themeConfiguration.theme\n const selectedPreset = themePresets.find((p) => p.name === themeName)\n\n if (selectedPreset) {\n // Initialize light and dark mode colors from preset if not already set\n if (!data.themeConfiguration.lightMode) {\n data.themeConfiguration.lightMode = {}\n }\n if (!data.themeConfiguration.darkMode) {\n data.themeConfiguration.darkMode = {}\n }\n\n // Only populate if not manually edited (first time or empty)\n const isLightModeEmpty = !data.themeConfiguration.lightMode?.background\n const isDarkModeEmpty = !data.themeConfiguration.darkMode?.background\n\n if (isLightModeEmpty && selectedPreset.lightMode) {\n data.themeConfiguration.lightMode = { ...selectedPreset.lightMode }\n }\n\n if (isDarkModeEmpty && selectedPreset.darkMode) {\n data.themeConfiguration.darkMode = { ...selectedPreset.darkMode }\n }\n }\n }\n\n return data\n }\n\n const standaloneGlobal: any = {\n slug: standaloneCollectionSlug,\n label: standaloneCollectionLabel,\n admin: {\n group: 'Settings',\n },\n access: {\n read: () => true,\n create: ({ req }: { req?: any }) => !!req?.user,\n update: ({ req }: { req?: any }) => !!req?.user,\n delete: ({ req }: { req?: any }) => !!req?.user,\n },\n fields: tabFields,\n hooks: {\n beforeChange: [beforeChangeHook],\n },\n }\n\n const globals = Array.isArray(config.globals) ? config.globals : []\n\n // Check if global already exists\n const existingIndex = globals.findIndex((g) => g.slug === standaloneCollectionSlug)\n\n if (existingIndex !== -1) {\n if (enableLogging) {\n console.warn(\n `🎨 Theme Management Plugin: global \"${standaloneCollectionSlug}\" already exists, skipping creation.`,\n )\n }\n return config\n }\n\n return {\n ...config,\n globals: [...globals, standaloneGlobal],\n }\n }\n\n // Otherwise, add as tab to existing collection\n let collectionTouched = false\n\n const collections = ensureCollectionsArray(config.collections).map((collection) => {\n if (collection.slug !== targetCollection) {\n return collection\n }\n\n collectionTouched = true\n\n if (enableLogging) {\n console.log(`🎨 Theme Management Plugin: enhancing collection \"${collection.slug}\"`)\n }\n\n const existingFields = Array.isArray(collection.fields) ? collection.fields : []\n\n const fields = injectThemeTab(existingFields, themeTab, enableLogging)\n\n return {\n ...collection,\n fields,\n }\n })\n\n if (!collectionTouched) {\n if (enableLogging) {\n console.warn(\n `🎨 Theme Management Plugin: collection \"${targetCollection}\" was not found, leaving config untouched.`,\n )\n }\n return config\n }\n\n return {\n ...config,\n collections,\n }\n }\n}\n\ntype FetchOptionsInput = string | FetchThemeConfigurationOptions\n\nexport const fetchThemeConfiguration = async (\n options?: FetchOptionsInput,\n): Promise<SiteThemeConfiguration | null> => {\n const normalizedOptions = typeof options === 'string' ? { tenantSlug: options } : (options ?? {})\n\n const {\n tenantSlug,\n collectionSlug = 'site-settings', // Can be overridden to 'appearance-settings' if using standalone\n depth,\n locale,\n draft,\n queryParams = {},\n useGlobal = false, // Set to true if using standalone global instead of collection\n } = normalizedOptions\n\n try {\n if (useGlobal) {\n // Fetch from global endpoint\n const params = new URLSearchParams()\n\n if (typeof depth === 'number') params.set('depth', String(depth))\n if (tenantSlug) params.set('tenant', tenantSlug)\n if (locale) params.set('locale', locale)\n if (draft) params.set('draft', 'true')\n\n Object.entries(queryParams).forEach(([key, value]) => {\n if (value === undefined) return\n params.set(key, String(value))\n })\n\n const queryString = params.toString()\n const url = `/api/globals/${collectionSlug}${queryString ? `?${queryString}` : ''}`\n\n const response = await fetch(url)\n if (!response.ok) {\n throw new Error(`Failed to fetch theme global (status ${response.status})`)\n }\n\n const data = (await response.json()) as {\n themeConfiguration?: SiteThemeConfiguration\n }\n\n return data?.themeConfiguration ?? null\n } else {\n // Fetch from collection endpoint (legacy/default behavior)\n const params = new URLSearchParams({ limit: '1' })\n\n if (typeof depth === 'number') params.set('depth', String(depth))\n if (tenantSlug) params.set('tenant', tenantSlug)\n if (locale) params.set('locale', locale)\n if (draft) params.set('draft', 'true')\n\n Object.entries(queryParams).forEach(([key, value]) => {\n if (value === undefined) return\n params.set(key, String(value))\n })\n\n const url = `/api/${collectionSlug}?${params.toString()}`\n\n const response = await fetch(url)\n if (!response.ok) {\n throw new Error(`Failed to fetch theme configuration (status ${response.status})`)\n }\n\n const data = (await response.json()) as {\n docs?: Array<{ themeConfiguration?: SiteThemeConfiguration }>\n }\n\n const doc = data.docs?.[0]\n\n return doc?.themeConfiguration ?? null\n }\n } catch (error) {\n console.warn('Failed to fetch theme configuration:', error)\n return null\n }\n}\n\nexport const getThemePreset = (themeName: string): ThemePreset | null => {\n return allThemePresets.find((preset) => preset.name === themeName) || null\n}\n\nexport const getAvailableThemePresets = (): ThemePreset[] => {\n return allThemePresets\n}\n\nexport { defaultThemePresets, allThemePresets } from './presets.js'\nexport type { ThemePreset, ThemeTypographyPreset } from './presets.js'\nexport type { ThemeTab } from './fields/themeConfigurationField.js'\nexport {\n extendedThemePresets,\n allExtendedThemePresets,\n extendedThemeToCSSVariables,\n} from './extended-presets.js'\nexport type { ExtendedThemePreset, ShadcnColorTokens } from './extended-presets.js'\nexport {\n applyExtendedTheme,\n generateExtendedThemeCSS,\n resetExtendedTheme,\n getExtendedThemeTokens,\n createUseExtendedTheme,\n getTailwindVarReferences,\n} from './utils/extendedThemeHelpers.js'\nexport type { ThemeManagementPluginOptions, FetchThemeConfigurationOptions } from './types.js'\nexport {\n DEFAULT_THEME_CONFIGURATION,\n resolveThemeConfiguration,\n} from './utils/resolveThemeConfiguration.js'\nexport type { ResolvedThemeConfiguration } from './utils/resolveThemeConfiguration.js'\nexport { generateThemeColorsCss, hexToHsl } from './utils/themeColors.js'\nexport { generateThemeCSS, getThemeStyles } from './utils/themeUtils.js'\nexport { getThemeHtmlAttributes } from './utils/themeHtmlAttributes.js'\n\n// Dynamic theme CSS generation\nexport {\n generateThemeCSS as generatePresetCSS,\n generateAllThemesCSS,\n} from './utils/generateThemeCSS.js'\nexport { getThemeDynamicCSS, getAllDynamicThemesCSS } from './utils/themeCSS.js'\n\nexport type { Mode, ThemeDefaults } from './providers/Theme/types.js'\nexport { ThemeProvider } from './providers/Theme/index.js'\n\n// Font loading utilities for Next.js integration\nexport {\n getFontLoaderCode,\n getThemeFontFamilies,\n ThemeFontProvider,\n useThemeFonts,\n FONT_IMPORT_MAP,\n} from './providers/font-loader.js'\n\n// Note: Do NOT re-export client components from the root entry to avoid\n// server-side evaluation during `payload generate:importmap`.\n// If needed, import directly from subpath: `@kilivi/payloadcms-theme-management/fields/ThemeLivePreview`\n\nexport const ThemeManagementPlugin = themeManagementPlugin\n/** @deprecated use {@link themeManagementPlugin} */\nexport const themeConfigurationPlugin = themeManagementPlugin\n\nexport default themeManagementPlugin\n"],"names":["createThemeConfigurationField","allThemePresets","THEME_FIELD_NAME","removeExistingThemeField","fields","filter","field","candidate","name","findTabsField","type","removeExistingThemeTab","tabs","tab","labelEn","label","en","injectThemeTab","themeTab","enableLogging","sanitizedFields","tabsField","console","warn","newTabsField","sanitizedTabs","updatedTabs","log","updatedTabsField","map","ensureCollectionsArray","collections","Array","isArray","themeManagementPlugin","options","config","enabled","targetCollection","useStandaloneCollection","standaloneCollectionSlug","standaloneCollectionLabel","themePresets","defaultTheme","includeColorModeToggle","includeCustomCSS","includeBrandIdentity","enableAdvancedFeatures","tabFields","beforeChangeHook","args","data","themeConfiguration","theme","themeName","selectedPreset","find","p","lightMode","darkMode","isLightModeEmpty","background","isDarkModeEmpty","standaloneGlobal","slug","admin","group","access","read","create","req","user","update","delete","hooks","beforeChange","globals","existingIndex","findIndex","g","collectionTouched","collection","existingFields","fetchThemeConfiguration","normalizedOptions","tenantSlug","collectionSlug","depth","locale","draft","queryParams","useGlobal","params","URLSearchParams","set","String","Object","entries","forEach","key","value","undefined","queryString","toString","url","response","fetch","ok","Error","status","json","limit","doc","docs","error","getThemePreset","preset","getAvailableThemePresets","defaultThemePresets","extendedThemePresets","allExtendedThemePresets","extendedThemeToCSSVariables","applyExtendedTheme","generateExtendedThemeCSS","resetExtendedTheme","getExtendedThemeTokens","createUseExtendedTheme","getTailwindVarReferences","DEFAULT_THEME_CONFIGURATION","resolveThemeConfiguration","generateThemeColorsCss","hexToHsl","generateThemeCSS","getThemeStyles","getThemeHtmlAttributes","generatePresetCSS","generateAllThemesCSS","getThemeDynamicCSS","getAllDynamicThemesCSS","ThemeProvider","getFontLoaderCode","getThemeFontFamilies","ThemeFontProvider","useThemeFonts","FONT_IMPORT_MAP","ThemeManagementPlugin","themeConfigurationPlugin"],"mappings":"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"}
package/dist/types.d.ts CHANGED
@@ -4,6 +4,12 @@ export interface ThemeManagementPluginOptions {
4
4
  enabled?: boolean;
5
5
  /** Collection slug that stores site-level settings (default: `site-settings`) */
6
6
  targetCollection?: string;
7
+ /** Create a standalone collection instead of adding as a tab (default: false) */
8
+ useStandaloneCollection?: boolean;
9
+ /** Name of the standalone collection (default: 'appearance-settings') */
10
+ standaloneCollectionSlug?: string;
11
+ /** Label for the standalone collection (default: 'Appearance Settings') */
12
+ standaloneCollectionLabel?: string | Record<string, string>;
7
13
  /** Theme presets available to editors */
8
14
  themePresets?: ThemePreset[];
9
15
  /** Default preset name when no value is stored */
@@ -22,7 +28,7 @@ export interface ThemeManagementPluginOptions {
22
28
  export interface FetchThemeConfigurationOptions {
23
29
  /** Optional tenant identifier if your project is multi-tenant */
24
30
  tenantSlug?: string;
25
- /** Collection slug override (default: `site-settings`) */
31
+ /** Collection/Global slug override (default: `site-settings`) */
26
32
  collectionSlug?: string;
27
33
  /** Depth parameter passed to Payload REST API */
28
34
  depth?: number;
@@ -32,5 +38,7 @@ export interface FetchThemeConfigurationOptions {
32
38
  draft?: boolean;
33
39
  /** Extra query parameters to append to the request */
34
40
  queryParams?: Record<string, string | number | boolean>;
41
+ /** Set to true if using standalone global instead of collection (default: false) */
42
+ useGlobal?: boolean;
35
43
  }
36
44
  //# sourceMappingURL=types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAA;AAE/C,MAAM,WAAW,4BAA4B;IAC5C,gDAAgD;IAChD,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,iFAAiF;IACjF,gBAAgB,CAAC,EAAE,MAAM,CAAA;IACzB,yCAAyC;IACzC,YAAY,CAAC,EAAE,WAAW,EAAE,CAAA;IAC5B,kDAAkD;IAClD,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,gEAAgE;IAChE,sBAAsB,CAAC,EAAE,OAAO,CAAA;IAChC,+BAA+B;IAC/B,gBAAgB,CAAC,EAAE,OAAO,CAAA;IAC1B,gDAAgD;IAChD,oBAAoB,CAAC,EAAE,OAAO,CAAA;IAC9B,uDAAuD;IACvD,sBAAsB,CAAC,EAAE,OAAO,CAAA;IAChC,kDAAkD;IAClD,aAAa,CAAC,EAAE,OAAO,CAAA;CACvB;AAED,MAAM,WAAW,8BAA8B;IAC9C,iEAAiE;IACjE,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,0DAA0D;IAC1D,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,iDAAiD;IACjD,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,kDAAkD;IAClD,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,8BAA8B;IAC9B,KAAK,CAAC,EAAE,OAAO,CAAA;IACf,sDAAsD;IACtD,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,CAAA;CACvD"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAA;AAE/C,MAAM,WAAW,4BAA4B;IAC3C,gDAAgD;IAChD,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,iFAAiF;IACjF,gBAAgB,CAAC,EAAE,MAAM,CAAA;IACzB,iFAAiF;IACjF,uBAAuB,CAAC,EAAE,OAAO,CAAA;IACjC,yEAAyE;IACzE,wBAAwB,CAAC,EAAE,MAAM,CAAA;IACjC,2EAA2E;IAC3E,yBAAyB,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAC3D,yCAAyC;IACzC,YAAY,CAAC,EAAE,WAAW,EAAE,CAAA;IAC5B,kDAAkD;IAClD,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,gEAAgE;IAChE,sBAAsB,CAAC,EAAE,OAAO,CAAA;IAChC,+BAA+B;IAC/B,gBAAgB,CAAC,EAAE,OAAO,CAAA;IAC1B,gDAAgD;IAChD,oBAAoB,CAAC,EAAE,OAAO,CAAA;IAC9B,uDAAuD;IACvD,sBAAsB,CAAC,EAAE,OAAO,CAAA;IAChC,kDAAkD;IAClD,aAAa,CAAC,EAAE,OAAO,CAAA;CACxB;AAED,MAAM,WAAW,8BAA8B;IAC7C,iEAAiE;IACjE,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,iEAAiE;IACjE,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,iDAAiD;IACjD,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,kDAAkD;IAClD,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,8BAA8B;IAC9B,KAAK,CAAC,EAAE,OAAO,CAAA;IACf,sDAAsD;IACtD,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,CAAA;IACvD,oFAAoF;IACpF,SAAS,CAAC,EAAE,OAAO,CAAA;CACpB"}
package/dist/types.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/types.ts"],"sourcesContent":["import type { ThemePreset } from './presets.js'\n\nexport interface ThemeManagementPluginOptions {\n\t/** Whether the plugin should register itself */\n\tenabled?: boolean\n\t/** Collection slug that stores site-level settings (default: `site-settings`) */\n\ttargetCollection?: string\n\t/** Theme presets available to editors */\n\tthemePresets?: ThemePreset[]\n\t/** Default preset name when no value is stored */\n\tdefaultTheme?: string\n\t/** Allow editors to toggle between light / dark / auto modes */\n\tincludeColorModeToggle?: boolean\n\t/** Expose custom CSS editor */\n\tincludeCustomCSS?: boolean\n\t/** Reserved for future use, keeps API parity */\n\tincludeBrandIdentity?: boolean\n\t/** Enable advanced controls such as animation level */\n\tenableAdvancedFeatures?: boolean\n\t/** Log helpful messages during config mutation */\n\tenableLogging?: boolean\n}\n\nexport interface FetchThemeConfigurationOptions {\n\t/** Optional tenant identifier if your project is multi-tenant */\n\ttenantSlug?: string\n\t/** Collection slug override (default: `site-settings`) */\n\tcollectionSlug?: string\n\t/** Depth parameter passed to Payload REST API */\n\tdepth?: number\n\t/** Locale parameter passed to Payload REST API */\n\tlocale?: string\n\t/** Include draft documents */\n\tdraft?: boolean\n\t/** Extra query parameters to append to the request */\n\tqueryParams?: Record<string, string | number | boolean>\n}\n\n"],"names":[],"mappings":"AAuBA,WAaC"}
1
+ {"version":3,"sources":["../src/types.ts"],"sourcesContent":["import type { ThemePreset } from './presets.js'\n\nexport interface ThemeManagementPluginOptions {\n /** Whether the plugin should register itself */\n enabled?: boolean\n /** Collection slug that stores site-level settings (default: `site-settings`) */\n targetCollection?: string\n /** Create a standalone collection instead of adding as a tab (default: false) */\n useStandaloneCollection?: boolean\n /** Name of the standalone collection (default: 'appearance-settings') */\n standaloneCollectionSlug?: string\n /** Label for the standalone collection (default: 'Appearance Settings') */\n standaloneCollectionLabel?: string | Record<string, string>\n /** Theme presets available to editors */\n themePresets?: ThemePreset[]\n /** Default preset name when no value is stored */\n defaultTheme?: string\n /** Allow editors to toggle between light / dark / auto modes */\n includeColorModeToggle?: boolean\n /** Expose custom CSS editor */\n includeCustomCSS?: boolean\n /** Reserved for future use, keeps API parity */\n includeBrandIdentity?: boolean\n /** Enable advanced controls such as animation level */\n enableAdvancedFeatures?: boolean\n /** Log helpful messages during config mutation */\n enableLogging?: boolean\n}\n\nexport interface FetchThemeConfigurationOptions {\n /** Optional tenant identifier if your project is multi-tenant */\n tenantSlug?: string\n /** Collection/Global slug override (default: `site-settings`) */\n collectionSlug?: string\n /** Depth parameter passed to Payload REST API */\n depth?: number\n /** Locale parameter passed to Payload REST API */\n locale?: string\n /** Include draft documents */\n draft?: boolean\n /** Extra query parameters to append to the request */\n queryParams?: Record<string, string | number | boolean>\n /** Set to true if using standalone global instead of collection (default: false) */\n useGlobal?: boolean\n}\n"],"names":[],"mappings":"AA6BA,WAeC"}
@@ -0,0 +1,34 @@
1
+ import type { Payload } from 'payload';
2
+ export interface ThemeSettingsData {
3
+ activeFont: string;
4
+ googleFontsApiKey?: string;
5
+ fontWeightHeading: string;
6
+ fontWeightBody: string;
7
+ }
8
+ /**
9
+ * Get theme settings from Payload CMS
10
+ *
11
+ * This helper fetches the ThemeSettings global and returns
12
+ * the typography configuration.
13
+ *
14
+ * @param payload - Payload instance
15
+ * @returns Theme settings data
16
+ */
17
+ export declare function getThemeSettings(payload?: Payload): Promise<ThemeSettingsData | null>;
18
+ /**
19
+ * Generate Google Fonts CSS URL
20
+ *
21
+ * @param fontFamily - Font family name
22
+ * @param weights - Array of font weights
23
+ * @returns Google Fonts CSS URL
24
+ */
25
+ export declare function getGoogleFontUrl(fontFamily: string, weights?: string[]): string;
26
+ /**
27
+ * Check if a font is pre-imported via next/font/google
28
+ *
29
+ * These fonts are optimized and don't require runtime loading
30
+ */
31
+ export declare const PRE_IMPORTED_FONTS: readonly ["Inter", "Nunito", "Montserrat", "Manrope", "Mulish", "Barlow", "Raleway", "Playfair Display"];
32
+ export type PreImportedFont = (typeof PRE_IMPORTED_FONTS)[number];
33
+ export declare function isPreImportedFont(fontFamily: string): fontFamily is PreImportedFont;
34
+ //# sourceMappingURL=getThemeSettings.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"getThemeSettings.d.ts","sourceRoot":"","sources":["../../src/utilities/getThemeSettings.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,SAAS,CAAA;AAEtC,MAAM,WAAW,iBAAiB;IAChC,UAAU,EAAE,MAAM,CAAA;IAClB,iBAAiB,CAAC,EAAE,MAAM,CAAA;IAC1B,iBAAiB,EAAE,MAAM,CAAA;IACzB,cAAc,EAAE,MAAM,CAAA;CACvB;AAED;;;;;;;;GAQG;AACH,wBAAsB,gBAAgB,CAAC,OAAO,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,iBAAiB,GAAG,IAAI,CAAC,CA2B3F;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,GAAE,MAAM,EAAmB,GAAG,MAAM,CAI/F;AAED;;;;GAIG;AACH,eAAO,MAAM,kBAAkB,0GASrB,CAAA;AAEV,MAAM,MAAM,eAAe,GAAG,CAAC,OAAO,kBAAkB,CAAC,CAAC,MAAM,CAAC,CAAA;AAEjE,wBAAgB,iBAAiB,CAAC,UAAU,EAAE,MAAM,GAAG,UAAU,IAAI,eAAe,CAEnF"}
@@ -0,0 +1,67 @@
1
+ /**
2
+ * Get theme settings from Payload CMS
3
+ *
4
+ * This helper fetches the ThemeSettings global and returns
5
+ * the typography configuration.
6
+ *
7
+ * @param payload - Payload instance
8
+ * @returns Theme settings data
9
+ */ export async function getThemeSettings(payload) {
10
+ if (!payload) {
11
+ // If no payload instance provided, try to get it from the global scope
12
+ // This is useful in server components where payload might be available globally
13
+ if (typeof window === 'undefined' && global.payload) {
14
+ payload = global.payload;
15
+ } else {
16
+ console.warn('getThemeSettings: No payload instance available');
17
+ return null;
18
+ }
19
+ }
20
+ try {
21
+ const themeSettings = await payload.findGlobal({
22
+ slug: 'themeSettings'
23
+ });
24
+ return {
25
+ activeFont: themeSettings.activeFont || 'Inter',
26
+ googleFontsApiKey: themeSettings.googleFontsApiKey,
27
+ fontWeightHeading: themeSettings.fontWeightHeading || '700',
28
+ fontWeightBody: themeSettings.fontWeightBody || '400'
29
+ };
30
+ } catch (error) {
31
+ console.error('Error fetching theme settings:', error);
32
+ return null;
33
+ }
34
+ }
35
+ /**
36
+ * Generate Google Fonts CSS URL
37
+ *
38
+ * @param fontFamily - Font family name
39
+ * @param weights - Array of font weights
40
+ * @returns Google Fonts CSS URL
41
+ */ export function getGoogleFontUrl(fontFamily, weights = [
42
+ '400',
43
+ '700'
44
+ ]) {
45
+ const family = fontFamily.replace(/\s+/g, '+');
46
+ const weightsStr = weights.join(';');
47
+ return `https://fonts.googleapis.com/css2?family=${family}:wght@${weightsStr}&display=swap`;
48
+ }
49
+ /**
50
+ * Check if a font is pre-imported via next/font/google
51
+ *
52
+ * These fonts are optimized and don't require runtime loading
53
+ */ export const PRE_IMPORTED_FONTS = [
54
+ 'Inter',
55
+ 'Nunito',
56
+ 'Montserrat',
57
+ 'Manrope',
58
+ 'Mulish',
59
+ 'Barlow',
60
+ 'Raleway',
61
+ 'Playfair Display'
62
+ ];
63
+ export function isPreImportedFont(fontFamily) {
64
+ return PRE_IMPORTED_FONTS.includes(fontFamily);
65
+ }
66
+
67
+ //# sourceMappingURL=getThemeSettings.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/utilities/getThemeSettings.ts"],"sourcesContent":["import type { Payload } from 'payload'\n\nexport interface ThemeSettingsData {\n activeFont: string\n googleFontsApiKey?: string\n fontWeightHeading: string\n fontWeightBody: string\n}\n\n/**\n * Get theme settings from Payload CMS\n *\n * This helper fetches the ThemeSettings global and returns\n * the typography configuration.\n *\n * @param payload - Payload instance\n * @returns Theme settings data\n */\nexport async function getThemeSettings(payload?: Payload): Promise<ThemeSettingsData | null> {\n if (!payload) {\n // If no payload instance provided, try to get it from the global scope\n // This is useful in server components where payload might be available globally\n if (typeof window === 'undefined' && (global as any).payload) {\n payload = (global as any).payload\n } else {\n console.warn('getThemeSettings: No payload instance available')\n return null\n }\n }\n\n try {\n const themeSettings = await payload!.findGlobal({\n slug: 'themeSettings',\n })\n\n return {\n activeFont: themeSettings.activeFont || 'Inter',\n googleFontsApiKey: themeSettings.googleFontsApiKey,\n fontWeightHeading: themeSettings.fontWeightHeading || '700',\n fontWeightBody: themeSettings.fontWeightBody || '400',\n }\n } catch (error) {\n console.error('Error fetching theme settings:', error)\n return null\n }\n}\n\n/**\n * Generate Google Fonts CSS URL\n *\n * @param fontFamily - Font family name\n * @param weights - Array of font weights\n * @returns Google Fonts CSS URL\n */\nexport function getGoogleFontUrl(fontFamily: string, weights: string[] = ['400', '700']): string {\n const family = fontFamily.replace(/\\s+/g, '+')\n const weightsStr = weights.join(';')\n return `https://fonts.googleapis.com/css2?family=${family}:wght@${weightsStr}&display=swap`\n}\n\n/**\n * Check if a font is pre-imported via next/font/google\n *\n * These fonts are optimized and don't require runtime loading\n */\nexport const PRE_IMPORTED_FONTS = [\n 'Inter',\n 'Nunito',\n 'Montserrat',\n 'Manrope',\n 'Mulish',\n 'Barlow',\n 'Raleway',\n 'Playfair Display',\n] as const\n\nexport type PreImportedFont = (typeof PRE_IMPORTED_FONTS)[number]\n\nexport function isPreImportedFont(fontFamily: string): fontFamily is PreImportedFont {\n return (PRE_IMPORTED_FONTS as readonly string[]).includes(fontFamily)\n}\n"],"names":["getThemeSettings","payload","window","global","console","warn","themeSettings","findGlobal","slug","activeFont","googleFontsApiKey","fontWeightHeading","fontWeightBody","error","getGoogleFontUrl","fontFamily","weights","family","replace","weightsStr","join","PRE_IMPORTED_FONTS","isPreImportedFont","includes"],"mappings":"AASA;;;;;;;;CAQC,GACD,OAAO,eAAeA,iBAAiBC,OAAiB;IACtD,IAAI,CAACA,SAAS;QACZ,uEAAuE;QACvE,gFAAgF;QAChF,IAAI,OAAOC,WAAW,eAAe,AAACC,OAAeF,OAAO,EAAE;YAC5DA,UAAU,AAACE,OAAeF,OAAO;QACnC,OAAO;YACLG,QAAQC,IAAI,CAAC;YACb,OAAO;QACT;IACF;IAEA,IAAI;QACF,MAAMC,gBAAgB,MAAML,QAASM,UAAU,CAAC;YAC9CC,MAAM;QACR;QAEA,OAAO;YACLC,YAAYH,cAAcG,UAAU,IAAI;YACxCC,mBAAmBJ,cAAcI,iBAAiB;YAClDC,mBAAmBL,cAAcK,iBAAiB,IAAI;YACtDC,gBAAgBN,cAAcM,cAAc,IAAI;QAClD;IACF,EAAE,OAAOC,OAAO;QACdT,QAAQS,KAAK,CAAC,kCAAkCA;QAChD,OAAO;IACT;AACF;AAEA;;;;;;CAMC,GACD,OAAO,SAASC,iBAAiBC,UAAkB,EAAEC,UAAoB;IAAC;IAAO;CAAM;IACrF,MAAMC,SAASF,WAAWG,OAAO,CAAC,QAAQ;IAC1C,MAAMC,aAAaH,QAAQI,IAAI,CAAC;IAChC,OAAO,CAAC,yCAAyC,EAAEH,OAAO,MAAM,EAAEE,WAAW,aAAa,CAAC;AAC7F;AAEA;;;;CAIC,GACD,OAAO,MAAME,qBAAqB;IAChC;IACA;IACA;IACA;IACA;IACA;IACA;IACA;CACD,CAAS;AAIV,OAAO,SAASC,kBAAkBP,UAAkB;IAClD,OAAO,AAACM,mBAAyCE,QAAQ,CAACR;AAC5D"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@kilivi/payloadcms-theme-management",
3
- "version": "0.5.8",
4
- "description": "Theme configuration plugin for Payload CMS v3 with 60+ professional themes",
3
+ "version": "1.0.0",
4
+ "description": "Theme configuration plugin for Payload CMS v3 with 60+ professional themes and standalone collection support",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
7
7
  "types": "./dist/index.d.ts",