@kilivi/payloadcms-theme-management 0.5.6 → 0.5.8
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.
- package/README.md +34 -38
- package/dist/components/InitTheme.d.ts +3 -0
- package/dist/components/InitTheme.d.ts.map +1 -1
- package/dist/components/InitTheme.js +9 -7
- package/dist/components/InitTheme.js.map +1 -1
- package/dist/components/ServerThemeInjector.d.ts.map +1 -1
- package/dist/components/ServerThemeInjector.js +1 -11
- package/dist/components/ServerThemeInjector.js.map +1 -1
- package/dist/components/ThemePreview.d.ts.map +1 -1
- package/dist/components/ThemePreview.js +3 -3
- package/dist/components/ThemePreview.js.map +1 -1
- package/dist/fields/ThemePresetImportField.d.ts +4 -0
- package/dist/fields/ThemePresetImportField.d.ts.map +1 -0
- package/dist/fields/ThemePresetImportField.js +219 -0
- package/dist/fields/ThemePresetImportField.js.map +1 -0
- package/dist/fields/ThemePreviewField.d.ts.map +1 -1
- package/dist/fields/ThemePreviewField.js +32 -25
- package/dist/fields/ThemePreviewField.js.map +1 -1
- package/dist/fields/themeConfigurationField.d.ts.map +1 -1
- package/dist/fields/themeConfigurationField.js +44 -10
- package/dist/fields/themeConfigurationField.js.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +7 -4
- package/dist/index.js.map +1 -1
- package/dist/providers/Theme/themeConfig.d.ts.map +1 -1
- package/dist/providers/Theme/themeConfig.js +256 -8
- package/dist/providers/Theme/themeConfig.js.map +1 -1
- package/dist/providers/Theme/types.d.ts +5 -3
- package/dist/providers/Theme/types.d.ts.map +1 -1
- package/dist/providers/Theme/types.js +34 -13
- package/dist/providers/Theme/types.js.map +1 -1
- package/dist/server.d.ts +1 -1
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +1 -1
- package/dist/server.js.map +1 -1
- package/dist/utils/customThemePresets.d.ts +5 -0
- package/dist/utils/customThemePresets.d.ts.map +1 -0
- package/dist/utils/customThemePresets.js +82 -0
- package/dist/utils/customThemePresets.js.map +1 -0
- package/dist/utils/extendedThemeHelpers.d.ts +1 -1
- package/dist/utils/extendedThemeHelpers.d.ts.map +1 -1
- package/dist/utils/extendedThemeHelpers.js +16 -16
- package/dist/utils/extendedThemeHelpers.js.map +1 -1
- package/dist/utils/generateThemeCSS.d.ts +11 -0
- package/dist/utils/generateThemeCSS.d.ts.map +1 -0
- package/dist/utils/generateThemeCSS.js +309 -0
- package/dist/utils/generateThemeCSS.js.map +1 -0
- package/dist/utils/resolveThemeConfiguration.d.ts +1 -1
- package/dist/utils/resolveThemeConfiguration.d.ts.map +1 -1
- package/dist/utils/resolveThemeConfiguration.js +3 -3
- package/dist/utils/resolveThemeConfiguration.js.map +1 -1
- package/dist/utils/themeAssets.d.ts +7 -0
- package/dist/utils/themeAssets.d.ts.map +1 -1
- package/dist/utils/themeAssets.js +23 -35
- package/dist/utils/themeAssets.js.map +1 -1
- package/dist/utils/themeCSS.d.ts +11 -0
- package/dist/utils/themeCSS.d.ts.map +1 -0
- package/dist/utils/themeCSS.js +32 -0
- package/dist/utils/themeCSS.js.map +1 -0
- package/package.json +3 -1
package/README.md
CHANGED
|
@@ -43,12 +43,12 @@ yarn add @kilivi/payloadcms-theme-management
|
|
|
43
43
|
### 1. Add Plugin to Payload Config
|
|
44
44
|
|
|
45
45
|
```typescript
|
|
46
|
-
import { buildConfig } from 'payload'
|
|
47
46
|
import { themeManagementPlugin } from '@kilivi/payloadcms-theme-management'
|
|
47
|
+
import { buildConfig } from 'payload'
|
|
48
48
|
|
|
49
49
|
export default buildConfig({
|
|
50
50
|
// ... other config
|
|
51
|
-
|
|
51
|
+
|
|
52
52
|
globals: [
|
|
53
53
|
{
|
|
54
54
|
slug: 'site-settings',
|
|
@@ -61,7 +61,7 @@ export default buildConfig({
|
|
|
61
61
|
],
|
|
62
62
|
},
|
|
63
63
|
],
|
|
64
|
-
|
|
64
|
+
|
|
65
65
|
plugins: [
|
|
66
66
|
themeManagementPlugin({
|
|
67
67
|
enabled: true,
|
|
@@ -84,13 +84,9 @@ import { ServerThemeInjector } from '@kilivi/payloadcms-theme-management/server'
|
|
|
84
84
|
import configPromise from '@payload-config'
|
|
85
85
|
import { getPayload } from 'payload'
|
|
86
86
|
|
|
87
|
-
export default async function RootLayout({
|
|
88
|
-
children,
|
|
89
|
-
}: {
|
|
90
|
-
children: React.ReactNode
|
|
91
|
-
}) {
|
|
87
|
+
export default async function RootLayout({ children }: { children: React.ReactNode }) {
|
|
92
88
|
const payload = await getPayload({ config: configPromise })
|
|
93
|
-
|
|
89
|
+
|
|
94
90
|
const { docs } = await payload.find({
|
|
95
91
|
collection: 'site-settings',
|
|
96
92
|
limit: 1,
|
|
@@ -123,25 +119,22 @@ The plugin injects CSS custom properties you can use:
|
|
|
123
119
|
Or with Tailwind CSS:
|
|
124
120
|
|
|
125
121
|
```tsx
|
|
126
|
-
<div className="bg-primary text-primary-foreground rounded-lg">
|
|
127
|
-
Themed Content
|
|
128
|
-
</div>
|
|
122
|
+
<div className="bg-primary text-primary-foreground rounded-lg">Themed Content</div>
|
|
129
123
|
```
|
|
130
124
|
|
|
131
|
-
|
|
132
125
|
## Plugin Configuration Options
|
|
133
126
|
|
|
134
|
-
| Option
|
|
135
|
-
|
|
136
|
-
| `enabled`
|
|
137
|
-
| `targetCollection`
|
|
138
|
-
| `themePresets`
|
|
139
|
-
| `defaultTheme`
|
|
140
|
-
| `includeColorModeToggle` | `boolean`
|
|
141
|
-
| `includeCustomCSS`
|
|
142
|
-
| `includeBrandIdentity`
|
|
143
|
-
| `enableAdvancedFeatures` | `boolean`
|
|
144
|
-
| `enableLogging`
|
|
127
|
+
| Option | Type | Default | Description |
|
|
128
|
+
| ------------------------ | --------------- | ----------------- | ----------------------------------------------- |
|
|
129
|
+
| `enabled` | `boolean` | `true` | Enable/disable the plugin |
|
|
130
|
+
| `targetCollection` | `string` | `'site-settings'` | Global or collection slug to add theme field to |
|
|
131
|
+
| `themePresets` | `ThemePreset[]` | Built-in presets | Custom theme presets |
|
|
132
|
+
| `defaultTheme` | `string` | `'cool'` | Default theme preset name |
|
|
133
|
+
| `includeColorModeToggle` | `boolean` | `true` | Show light/dark mode toggle |
|
|
134
|
+
| `includeCustomCSS` | `boolean` | `true` | Allow custom CSS injection |
|
|
135
|
+
| `includeBrandIdentity` | `boolean` | `false` | Show brand identity fields |
|
|
136
|
+
| `enableAdvancedFeatures` | `boolean` | `true` | Enable advanced customization |
|
|
137
|
+
| `enableLogging` | `boolean` | `false` | Log plugin actions to console |
|
|
145
138
|
|
|
146
139
|
## Available Theme Presets
|
|
147
140
|
|
|
@@ -157,6 +150,7 @@ Or with Tailwind CSS:
|
|
|
157
150
|
The plugin automatically adds a **Live Preview** page to your admin panel at `/admin/theme-preview`.
|
|
158
151
|
|
|
159
152
|
### Features:
|
|
153
|
+
|
|
160
154
|
- ✅ **Zero Configuration** - Works automatically when plugin is installed
|
|
161
155
|
- ✅ **Real-time Updates** - See changes instantly as you edit theme settings
|
|
162
156
|
- ✅ **Light/Dark Toggle** - Preview both modes side-by-side
|
|
@@ -164,6 +158,7 @@ The plugin automatically adds a **Live Preview** page to your admin panel at `/a
|
|
|
164
158
|
- ✅ **Professional UI** - Clean, modern preview interface
|
|
165
159
|
|
|
166
160
|
### How to Access:
|
|
161
|
+
|
|
167
162
|
1. Install the plugin (see Quick Start above)
|
|
168
163
|
2. Navigate to `/admin/theme-preview` in your Payload admin panel
|
|
169
164
|
3. Open theme settings in another tab and see changes update live!
|
|
@@ -178,25 +173,23 @@ Import from `@kilivi/payloadcms-theme-management` for client-safe code:
|
|
|
178
173
|
|
|
179
174
|
```typescript
|
|
180
175
|
// Plugin
|
|
181
|
-
import { themeManagementPlugin } from '@kilivi/payloadcms-theme-management'
|
|
182
|
-
|
|
183
176
|
// Client Components
|
|
184
|
-
import { ThemeProvider } from '@kilivi/payloadcms-theme-management'
|
|
185
177
|
|
|
186
178
|
// Utilities
|
|
187
|
-
import {
|
|
179
|
+
import {
|
|
180
|
+
fetchThemeConfiguration,
|
|
188
181
|
generateThemeColorsCss,
|
|
189
182
|
generateThemeCSS,
|
|
190
183
|
getThemeStyles,
|
|
191
184
|
resolveThemeConfiguration,
|
|
192
|
-
|
|
185
|
+
themeManagementPlugin,
|
|
186
|
+
ThemeProvider,
|
|
193
187
|
} from '@kilivi/payloadcms-theme-management'
|
|
194
|
-
|
|
195
188
|
// Types
|
|
196
189
|
import type {
|
|
197
|
-
ThemePreset,
|
|
198
190
|
ThemeDefaults,
|
|
199
191
|
ThemeManagementPluginOptions,
|
|
192
|
+
ThemePreset,
|
|
200
193
|
} from '@kilivi/payloadcms-theme-management'
|
|
201
194
|
```
|
|
202
195
|
|
|
@@ -206,22 +199,23 @@ import type {
|
|
|
206
199
|
|
|
207
200
|
```typescript
|
|
208
201
|
import {
|
|
209
|
-
ServerThemeInjector,
|
|
210
202
|
getThemeCriticalCSS,
|
|
211
|
-
|
|
212
|
-
|
|
203
|
+
getThemeCSS,
|
|
204
|
+
ServerThemeInjector,
|
|
213
205
|
} from '@kilivi/payloadcms-theme-management/server'
|
|
214
206
|
```
|
|
215
207
|
|
|
208
|
+
> **Heads up:** Legacy helpers `getThemeCSSPath` and `generateThemePreloadLinks` are still exported for backwards compatibility but now return empty strings and emit console warnings. Prefer the inline CSS utilities above.
|
|
209
|
+
|
|
216
210
|
### Subpath Exports
|
|
217
211
|
|
|
218
212
|
```typescript
|
|
219
213
|
// Direct field imports
|
|
220
|
-
import { ThemeColorPickerField } from '@kilivi/payloadcms-theme-management/fields/ThemeColorPickerField'
|
|
221
|
-
import { ThemeTokenSelectField } from '@kilivi/payloadcms-theme-management/fields/ThemeTokenSelectField'
|
|
222
214
|
|
|
223
215
|
// Direct component imports
|
|
224
216
|
import { ThemePreview } from '@kilivi/payloadcms-theme-management/components/ThemePreview'
|
|
217
|
+
import { ThemeColorPickerField } from '@kilivi/payloadcms-theme-management/fields/ThemeColorPickerField'
|
|
218
|
+
import { ThemeTokenSelectField } from '@kilivi/payloadcms-theme-management/fields/ThemeTokenSelectField'
|
|
225
219
|
```
|
|
226
220
|
|
|
227
221
|
## Integration Examples
|
|
@@ -317,7 +311,6 @@ See [MIGRATION_GUIDE.md](./docs/MIGRATION_GUIDE.md) for detailed migration instr
|
|
|
317
311
|
+ import { ServerThemeInjector } from '@kilivi/payloadcms-theme-management/server'
|
|
318
312
|
```
|
|
319
313
|
|
|
320
|
-
|
|
321
314
|
## Testing
|
|
322
315
|
|
|
323
316
|
See [TEST_APP_GUIDE.md](./docs/TEST_APP_GUIDE.md) for instructions on creating a test application.
|
|
@@ -347,6 +340,7 @@ import { ServerThemeInjector } from '@kilivi/payloadcms-theme-management/server'
|
|
|
347
340
|
```
|
|
348
341
|
|
|
349
342
|
Then clear your cache:
|
|
343
|
+
|
|
350
344
|
```bash
|
|
351
345
|
rm -rf .next node_modules/.cache
|
|
352
346
|
pnpm install
|
|
@@ -430,15 +424,17 @@ Created for Payload CMS v3 applications.
|
|
|
430
424
|
## Changelog
|
|
431
425
|
|
|
432
426
|
### v0.1.9 (Latest)
|
|
427
|
+
|
|
433
428
|
- ✅ **Fixed:** Server/client component separation
|
|
434
429
|
- ✅ **Added:** `server-only` package to prevent bundling errors
|
|
435
430
|
- ✅ **Changed:** `ServerThemeInjector` now exported from `/server` entry
|
|
436
431
|
- ✅ **Added:** Comprehensive documentation
|
|
437
432
|
|
|
438
433
|
### v0.1.7
|
|
434
|
+
|
|
439
435
|
- ✅ **Fixed:** ESM import resolution with `.js` extensions
|
|
440
436
|
- ✅ **Added:** SWC + TypeScript build pipeline
|
|
441
437
|
|
|
442
438
|
### v0.1.5
|
|
443
|
-
- Initial release with theme management features
|
|
444
439
|
|
|
440
|
+
- Initial release with theme management features
|
|
@@ -7,6 +7,9 @@ import React from 'react';
|
|
|
7
7
|
* - User preference from localStorage
|
|
8
8
|
* - Admin-controlled color mode toggle
|
|
9
9
|
* - Auto mode with system preference fallback
|
|
10
|
+
*
|
|
11
|
+
* Note: Uses Next.js Script component with beforeInteractive strategy
|
|
12
|
+
* to ensure theme is applied before React hydration, preventing flash of unstyled content.
|
|
10
13
|
*/
|
|
11
14
|
export declare const InitTheme: React.FC;
|
|
12
15
|
//# sourceMappingURL=InitTheme.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"InitTheme.d.ts","sourceRoot":"","sources":["../../src/components/InitTheme.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"InitTheme.d.ts","sourceRoot":"","sources":["../../src/components/InitTheme.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AAIzB;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,SAAS,EAAE,KAAK,CAAC,EAyD7B,CAAA"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
-
import Script from 'next/script';
|
|
3
2
|
import React from 'react';
|
|
3
|
+
import Script from 'next/script';
|
|
4
4
|
import { modeLocalStorageKey } from '../providers/Theme/shared.js';
|
|
5
5
|
/**
|
|
6
6
|
* Client-side theme initialization script
|
|
@@ -10,10 +10,11 @@ import { modeLocalStorageKey } from '../providers/Theme/shared.js';
|
|
|
10
10
|
* - User preference from localStorage
|
|
11
11
|
* - Admin-controlled color mode toggle
|
|
12
12
|
* - Auto mode with system preference fallback
|
|
13
|
+
*
|
|
14
|
+
* Note: Uses Next.js Script component with beforeInteractive strategy
|
|
15
|
+
* to ensure theme is applied before React hydration, preventing flash of unstyled content.
|
|
13
16
|
*/ export const InitTheme = ()=>{
|
|
14
|
-
|
|
15
|
-
dangerouslySetInnerHTML: {
|
|
16
|
-
__html: `
|
|
17
|
+
const scriptContent = `
|
|
17
18
|
(function () {
|
|
18
19
|
function getImplicitModePreference() {
|
|
19
20
|
var mediaQuery = '(prefers-color-scheme: dark)'
|
|
@@ -62,10 +63,11 @@ import { modeLocalStorageKey } from '../providers/Theme/shared.js';
|
|
|
62
63
|
})
|
|
63
64
|
}
|
|
64
65
|
})();
|
|
65
|
-
|
|
66
|
-
|
|
66
|
+
`;
|
|
67
|
+
return /*#__PURE__*/ _jsx(Script, {
|
|
67
68
|
id: "theme-script",
|
|
68
|
-
strategy: "beforeInteractive"
|
|
69
|
+
strategy: "beforeInteractive",
|
|
70
|
+
children: scriptContent
|
|
69
71
|
});
|
|
70
72
|
};
|
|
71
73
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/components/InitTheme.tsx"],"sourcesContent":["import
|
|
1
|
+
{"version":3,"sources":["../../src/components/InitTheme.tsx"],"sourcesContent":["import React from 'react'\nimport Script from 'next/script'\nimport { modeLocalStorageKey } from '../providers/Theme/shared.js'\n\n/**\n * Client-side theme initialization script\n * Prevents FOUC by applying theme mode before React hydration\n * Handles:\n * - System preference detection\n * - User preference from localStorage\n * - Admin-controlled color mode toggle\n * - Auto mode with system preference fallback\n *\n * Note: Uses Next.js Script component with beforeInteractive strategy\n * to ensure theme is applied before React hydration, preventing flash of unstyled content.\n */\nexport const InitTheme: React.FC = () => {\n const scriptContent = `\n (function () {\n function getImplicitModePreference() {\n var mediaQuery = '(prefers-color-scheme: dark)'\n var mql = window.matchMedia(mediaQuery)\n return mql.matches ? 'dark' : 'light'\n }\n\n function modeIsValid(mode) {\n return mode === 'light' || mode === 'dark'\n }\n\n // Get current mode from server-set attribute\n var currentMode = document.documentElement.getAttribute('data-theme-mode')\n var allowToggle = document.documentElement.getAttribute('data-allow-color-mode-toggle') === 'true'\n \n // Only override mode if admin allows toggle and user has preference\n if (allowToggle) {\n var modePreference = window.localStorage.getItem('${modeLocalStorageKey}')\n \n if (modeIsValid(modePreference)) {\n currentMode = modePreference\n } else if (currentMode === 'auto') {\n currentMode = getImplicitModePreference()\n }\n } else if (currentMode === 'auto') {\n // Admin set auto mode - use system preference\n currentMode = getImplicitModePreference()\n }\n\n // Apply the determined mode\n if (currentMode && modeIsValid(currentMode)) {\n document.documentElement.setAttribute('data-theme-mode', currentMode)\n }\n\n // Listen for system theme changes only when needed\n if (allowToggle || currentMode === 'auto') {\n var mediaQuery = window.matchMedia('(prefers-color-scheme: dark)')\n mediaQuery.addEventListener('change', function(e) {\n var shouldUpdate = allowToggle \n ? !window.localStorage.getItem('${modeLocalStorageKey}')\n : document.documentElement.getAttribute('data-theme-mode') === 'auto'\n \n if (shouldUpdate) {\n document.documentElement.setAttribute('data-theme-mode', e.matches ? 'dark' : 'light')\n }\n })\n }\n })();\n `\n\n return (\n <Script id=\"theme-script\" strategy=\"beforeInteractive\">\n {scriptContent}\n </Script>\n )\n}\n"],"names":["React","Script","modeLocalStorageKey","InitTheme","scriptContent","id","strategy"],"mappings":";AAAA,OAAOA,WAAW,QAAO;AACzB,OAAOC,YAAY,cAAa;AAChC,SAASC,mBAAmB,QAAQ,+BAA8B;AAElE;;;;;;;;;;;CAWC,GACD,OAAO,MAAMC,YAAsB;IACjC,MAAMC,gBAAgB,CAAC;;;;;;;;;;;;;;;;;;wDAkB+B,EAAEF,oBAAoB;;;;;;;;;;;;;;;;;;;;;;0CAsBpC,EAAEA,oBAAoB;;;;;;;;;EAS9D,CAAC;IAED,qBACE,KAACD;QAAOI,IAAG;QAAeC,UAAS;kBAChCF;;AAGP,EAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ServerThemeInjector.d.ts","sourceRoot":"","sources":["../../src/components/ServerThemeInjector.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"ServerThemeInjector.d.ts","sourceRoot":"","sources":["../../src/components/ServerThemeInjector.tsx"],"names":[],"mappings":"AAUA,UAAU,wBAAwB;IAChC;;;;;;;;;OASG;IACH,kBAAkB,CAAC,EAAE,OAAO,CAAA;CAC7B;AAMD;;;GAGG;AACH,wBAAsB,mBAAmB,CAAC,EACxC,kBAAkB,GACnB,EAAE,QAAQ,CAAC,wBAAwB,CAAC,wCAsFpC"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
2
|
import { getBorderRadiusConfig } from '../providers/Theme/themeConfig.js';
|
|
3
3
|
import { resolveThemeConfiguration } from '../utils/resolveThemeConfiguration.js';
|
|
4
|
-
import { createFallbackCriticalCSS, getThemeCriticalCSS
|
|
4
|
+
import { createFallbackCriticalCSS, getThemeCriticalCSS } from '../utils/themeAssets.js';
|
|
5
5
|
import { generateThemeColorsCss } from '../utils/themeColors.js';
|
|
6
6
|
import { generateThemeCSS } from '../utils/themeUtils.js';
|
|
7
7
|
import { InitTheme } from './InitTheme.js';
|
|
@@ -60,7 +60,6 @@ ${borderRadiusCSS}
|
|
|
60
60
|
colorModesCSS,
|
|
61
61
|
customCSSBlock
|
|
62
62
|
].filter((block)=>Boolean(block?.trim?.().length)).join('\n\n');
|
|
63
|
-
const themeCSSPath = getThemeCSSPath(theme);
|
|
64
63
|
return /*#__PURE__*/ _jsxs(_Fragment, {
|
|
65
64
|
children: [
|
|
66
65
|
/*#__PURE__*/ _jsx(InitTheme, {}),
|
|
@@ -69,15 +68,6 @@ ${borderRadiusCSS}
|
|
|
69
68
|
dangerouslySetInnerHTML: {
|
|
70
69
|
__html: combinedCSS
|
|
71
70
|
}
|
|
72
|
-
}),
|
|
73
|
-
/*#__PURE__*/ _jsx("link", {
|
|
74
|
-
rel: "preload",
|
|
75
|
-
href: themeCSSPath,
|
|
76
|
-
as: "style"
|
|
77
|
-
}),
|
|
78
|
-
/*#__PURE__*/ _jsx("link", {
|
|
79
|
-
rel: "stylesheet",
|
|
80
|
-
href: themeCSSPath
|
|
81
71
|
})
|
|
82
72
|
]
|
|
83
73
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/components/ServerThemeInjector.tsx"],"sourcesContent":["import type { ThemeTypographyPreset } from '../presets.js'\nimport { getBorderRadiusConfig } from '../providers/Theme/themeConfig.js'\nimport type { BorderRadiusPreset, ThemeDefaults } from '../providers/Theme/types.js'\nimport { resolveThemeConfiguration } from '../utils/resolveThemeConfiguration.js'\nimport type { ResolvedThemeConfiguration } from '../utils/resolveThemeConfiguration.js'\nimport {
|
|
1
|
+
{"version":3,"sources":["../../src/components/ServerThemeInjector.tsx"],"sourcesContent":["import type { ThemeTypographyPreset } from '../presets.js'\nimport { getBorderRadiusConfig } from '../providers/Theme/themeConfig.js'\nimport type { BorderRadiusPreset, ThemeDefaults } from '../providers/Theme/types.js'\nimport { resolveThemeConfiguration } from '../utils/resolveThemeConfiguration.js'\nimport type { ResolvedThemeConfiguration } from '../utils/resolveThemeConfiguration.js'\nimport { createFallbackCriticalCSS, getThemeCriticalCSS } from '../utils/themeAssets.js'\nimport { generateThemeColorsCss } from '../utils/themeColors.js'\nimport { generateThemeCSS } from '../utils/themeUtils.js'\nimport { InitTheme } from './InitTheme.js'\n\ninterface ServerThemeInjectorProps {\n /**\n * Theme configuration object from your site settings.\n * Pass the themeConfiguration field directly, not the entire site settings object.\n *\n * @example\n * ```tsx\n * const siteSettings = await payload.findGlobal({ slug: 'site-settings' })\n * <ServerThemeInjector themeConfiguration={siteSettings.themeConfiguration} />\n * ```\n */\n themeConfiguration?: unknown\n}\n\ntype RuntimeThemeConfiguration = Omit<ResolvedThemeConfiguration, 'typography'> & {\n typography?: ThemeTypographyPreset | null\n}\n\n/**\n * Server-side theme CSS injector to prevent FOUC\n * This component injects critical theme CSS directly into the HTML head during SSR\n */\nexport async function ServerThemeInjector({\n themeConfiguration,\n}: Readonly<ServerThemeInjectorProps>) {\n // Accept unknown type to avoid type conflicts between app's payload-types and plugin's payload-types\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const resolvedConfiguration = resolveThemeConfiguration(themeConfiguration as any)\n const {\n theme,\n borderRadius,\n customCSS,\n lightMode,\n darkMode,\n fontScale,\n spacing,\n animationLevel,\n allowColorModeToggle,\n colorMode,\n typography,\n } = resolvedConfiguration\n\n // Use resolved configuration directly\n const normalizedThemeConfiguration: RuntimeThemeConfiguration = {\n theme,\n colorMode,\n allowColorModeToggle,\n borderRadius,\n fontScale,\n spacing,\n animationLevel,\n customCSS: customCSS ?? null,\n lightMode,\n darkMode,\n typography: typography ?? undefined,\n }\n\n let criticalCSS = await getThemeCriticalCSS(theme as ThemeDefaults)\n criticalCSS ??= createFallbackCriticalCSS(theme as ThemeDefaults)\n\n const borderRadiusMap: Record<string, BorderRadiusPreset> = {\n none: 'none',\n small: 'small',\n medium: 'medium',\n large: 'large',\n xl: 'xl',\n full: 'xl',\n }\n const mappedBorderRadius = borderRadiusMap[borderRadius ?? 'medium'] ?? 'medium'\n const borderRadiusConfig = getBorderRadiusConfig(mappedBorderRadius)\n const cssRecord =\n typeof borderRadiusConfig?.css === 'string'\n ? { '--radius-default': borderRadiusConfig.css }\n : (borderRadiusConfig?.css ?? {})\n\n const borderRadiusCSS = Object.entries(cssRecord)\n .map(([property, value]) => ` ${property}: ${value};`)\n .join('\\n')\n\n const borderRadiusBlock = borderRadiusCSS\n ? `:root {\n${borderRadiusCSS}\n}`\n : ''\n\n const themeConfigurationCSS = generateThemeCSS(normalizedThemeConfiguration)\n const colorModesCSS = generateThemeColorsCss({ themeName: theme, lightMode, darkMode })\n const customCSSBlock = typeof customCSS === 'string' ? customCSS.trim() : ''\n\n const combinedCSS = [\n criticalCSS,\n borderRadiusBlock,\n themeConfigurationCSS,\n colorModesCSS,\n customCSSBlock,\n ]\n .filter((block) => Boolean(block?.trim?.().length))\n .join('\\n\\n')\n\n return (\n <>\n <InitTheme />\n <style\n id=\"theme-critical-css\"\n dangerouslySetInnerHTML={{\n __html: combinedCSS,\n }}\n />\n </>\n )\n}\n"],"names":["getBorderRadiusConfig","resolveThemeConfiguration","createFallbackCriticalCSS","getThemeCriticalCSS","generateThemeColorsCss","generateThemeCSS","InitTheme","ServerThemeInjector","themeConfiguration","resolvedConfiguration","theme","borderRadius","customCSS","lightMode","darkMode","fontScale","spacing","animationLevel","allowColorModeToggle","colorMode","typography","normalizedThemeConfiguration","undefined","criticalCSS","borderRadiusMap","none","small","medium","large","xl","full","mappedBorderRadius","borderRadiusConfig","cssRecord","css","borderRadiusCSS","Object","entries","map","property","value","join","borderRadiusBlock","themeConfigurationCSS","colorModesCSS","themeName","customCSSBlock","trim","combinedCSS","filter","block","Boolean","length","style","id","dangerouslySetInnerHTML","__html"],"mappings":";AACA,SAASA,qBAAqB,QAAQ,oCAAmC;AAEzE,SAASC,yBAAyB,QAAQ,wCAAuC;AAEjF,SAASC,yBAAyB,EAAEC,mBAAmB,QAAQ,0BAAyB;AACxF,SAASC,sBAAsB,QAAQ,0BAAyB;AAChE,SAASC,gBAAgB,QAAQ,yBAAwB;AACzD,SAASC,SAAS,QAAQ,iBAAgB;AAoB1C;;;CAGC,GACD,OAAO,eAAeC,oBAAoB,EACxCC,kBAAkB,EACiB;IACnC,qGAAqG;IACrG,8DAA8D;IAC9D,MAAMC,wBAAwBR,0BAA0BO;IACxD,MAAM,EACJE,KAAK,EACLC,YAAY,EACZC,SAAS,EACTC,SAAS,EACTC,QAAQ,EACRC,SAAS,EACTC,OAAO,EACPC,cAAc,EACdC,oBAAoB,EACpBC,SAAS,EACTC,UAAU,EACX,GAAGX;IAEJ,sCAAsC;IACtC,MAAMY,+BAA0D;QAC9DX;QACAS;QACAD;QACAP;QACAI;QACAC;QACAC;QACAL,WAAWA,aAAa;QACxBC;QACAC;QACAM,YAAYA,cAAcE;IAC5B;IAEA,IAAIC,cAAc,MAAMpB,oBAAoBO;IAC5Ca,gBAAgBrB,0BAA0BQ;IAE1C,MAAMc,kBAAsD;QAC1DC,MAAM;QACNC,OAAO;QACPC,QAAQ;QACRC,OAAO;QACPC,IAAI;QACJC,MAAM;IACR;IACA,MAAMC,qBAAqBP,eAAe,CAACb,gBAAgB,SAAS,IAAI;IACxE,MAAMqB,qBAAqBhC,sBAAsB+B;IACjD,MAAME,YACJ,OAAOD,oBAAoBE,QAAQ,WAC/B;QAAE,oBAAoBF,mBAAmBE,GAAG;IAAC,IAC5CF,oBAAoBE,OAAO,CAAC;IAEnC,MAAMC,kBAAkBC,OAAOC,OAAO,CAACJ,WACpCK,GAAG,CAAC,CAAC,CAACC,UAAUC,MAAM,GAAK,CAAC,EAAE,EAAED,SAAS,EAAE,EAAEC,MAAM,CAAC,CAAC,EACrDC,IAAI,CAAC;IAER,MAAMC,oBAAoBP,kBACtB,CAAC;AACP,EAAEA,gBAAgB;CACjB,CAAC,GACI;IAEJ,MAAMQ,wBAAwBtC,iBAAiBgB;IAC/C,MAAMuB,gBAAgBxC,uBAAuB;QAAEyC,WAAWnC;QAAOG;QAAWC;IAAS;IACrF,MAAMgC,iBAAiB,OAAOlC,cAAc,WAAWA,UAAUmC,IAAI,KAAK;IAE1E,MAAMC,cAAc;QAClBzB;QACAmB;QACAC;QACAC;QACAE;KACD,CACEG,MAAM,CAAC,CAACC,QAAUC,QAAQD,OAAOH,SAASK,SAC1CX,IAAI,CAAC;IAER,qBACE;;0BACE,KAACnC;0BACD,KAAC+C;gBACCC,IAAG;gBACHC,yBAAyB;oBACvBC,QAAQR;gBACV;;;;AAIR"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ThemePreview.d.ts","sourceRoot":"","sources":["../../src/components/ThemePreview.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAkB,MAAM,OAAO,CAAA;
|
|
1
|
+
{"version":3,"file":"ThemePreview.d.ts","sourceRoot":"","sources":["../../src/components/ThemePreview.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAkB,MAAM,OAAO,CAAA;AAqBtC,MAAM,CAAC,OAAO,UAAU,YAAY,sBA8PnC"}
|
|
@@ -2,14 +2,14 @@
|
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
3
|
import { useField } from '@payloadcms/ui';
|
|
4
4
|
import React, { useMemo } from 'react';
|
|
5
|
+
import { allThemePresets } from '../presets.js';
|
|
5
6
|
import { themeIsValid } from '../providers/Theme/types.js';
|
|
6
|
-
import { defaultThemePresets } from '../presets.js';
|
|
7
7
|
const DEFAULT_THEME_KEY = 'cool';
|
|
8
|
-
const basePresetMap =
|
|
8
|
+
const basePresetMap = allThemePresets.reduce((accumulator, preset)=>{
|
|
9
9
|
accumulator[preset.name] = preset;
|
|
10
10
|
return accumulator;
|
|
11
11
|
}, {});
|
|
12
|
-
const fallbackPreset = basePresetMap[DEFAULT_THEME_KEY] ??
|
|
12
|
+
const fallbackPreset = basePresetMap[DEFAULT_THEME_KEY] ?? allThemePresets[0];
|
|
13
13
|
const fallbackLightMode = fallbackPreset?.lightMode ?? {
|
|
14
14
|
primary: '#3b82f6',
|
|
15
15
|
accent: '#06b6d4',
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/components/ThemePreview.tsx"],"sourcesContent":["'use client'\n\nimport { useField } from '@payloadcms/ui'\nimport React, { useMemo } from 'react'\nimport { themeIsValid } from '../providers/Theme/types.js'\nimport { defaultThemePresets } from '../presets.js'\n\nconst DEFAULT_THEME_KEY = 'cool'\nconst basePresetMap = defaultThemePresets.reduce<\n Record<string, (typeof defaultThemePresets)[number]>\n>((accumulator, preset) => {\n accumulator[preset.name] = preset\n return accumulator\n}, {})\n\nconst fallbackPreset = basePresetMap[DEFAULT_THEME_KEY] ?? defaultThemePresets[0]\nconst fallbackLightMode = fallbackPreset?.lightMode ?? {\n primary: '#3b82f6',\n accent: '#06b6d4',\n background: '#ffffff',\n foreground: '#1f2937',\n}\n\nexport default function ThemePreview() {\n // Get individual field values using useField hooks\n const { value: selectedTheme } = useField<string>({ path: 'themeConfiguration.theme' })\n const { value: primaryColor } = useField<string>({\n path: 'themeConfiguration.customization.primaryColor',\n })\n const { value: accentColor } = useField<string>({\n path: 'themeConfiguration.customization.accentColor',\n })\n const { value: backgroundColor } = useField<string>({\n path: 'themeConfiguration.customization.backgroundColor',\n })\n const { value: textColor } = useField<string>({\n path: 'themeConfiguration.customization.textColor',\n })\n\n // Determine current theme and if overrides are active\n const currentTheme = themeIsValid(selectedTheme)\n ? selectedTheme\n : (fallbackPreset?.name ?? 'cool')\n const hasOverrides = Boolean(primaryColor || accentColor || backgroundColor || textColor)\n\n const themeColors = useMemo(() => {\n const preset = basePresetMap[currentTheme] ?? fallbackPreset\n const lightMode = preset?.lightMode ?? fallbackLightMode\n\n return {\n primary: lightMode?.primary ?? fallbackLightMode.primary,\n accent:\n lightMode?.accent ??\n lightMode?.secondary ??\n fallbackLightMode.accent ??\n fallbackLightMode.primary,\n background: lightMode?.background ?? fallbackLightMode.background,\n text: lightMode?.foreground ?? fallbackLightMode.foreground,\n }\n }, [currentTheme])\n\n const currentColors = useMemo(\n () => ({\n primary: primaryColor || themeColors.primary,\n accent: accentColor || themeColors.accent,\n background: backgroundColor || themeColors.background,\n text: textColor || themeColors.text,\n }),\n [primaryColor, accentColor, backgroundColor, textColor, themeColors],\n )\n\n return (\n <div className=\"theme-preview\" style={{ marginTop: '20px' }}>\n <div\n style={{\n fontSize: '16px',\n fontWeight: '600',\n marginBottom: '16px',\n color: '#374151',\n }}\n >\n 🎨 Live Theme Preview\n </div>\n\n <div\n className=\"preview-container\"\n style={{\n border: '2px solid #e5e7eb',\n borderRadius: '12px',\n overflow: 'hidden',\n backgroundColor: currentColors.background,\n color: currentColors.text,\n minHeight: '300px',\n }}\n >\n {/* Header */}\n <div\n style={{\n backgroundColor: currentColors.primary,\n color: currentColors.background,\n padding: '16px 24px',\n display: 'flex',\n justifyContent: 'space-between',\n alignItems: 'center',\n }}\n >\n <div style={{ fontSize: '20px', fontWeight: '700' }}>Your Website</div>\n <nav style={{ display: 'flex', gap: '24px', fontSize: '14px' }}>\n <span>Home</span>\n <span>About</span>\n <span>Services</span>\n <span>Contact</span>\n </nav>\n </div>\n\n {/* Content */}\n <div style={{ padding: '32px 24px' }}>\n <h1\n style={{\n fontSize: '32px',\n fontWeight: '800',\n marginBottom: '16px',\n color: currentColors.text,\n }}\n >\n Welcome to Your Site\n </h1>\n\n <p\n style={{\n fontSize: '16px',\n lineHeight: '1.6',\n marginBottom: '24px',\n color: currentColors.text,\n opacity: 0.8,\n }}\n >\n This is how your content will look with the selected theme. The colors and styling will\n be applied across your entire website.\n </p>\n\n {/* Buttons */}\n <div style={{ display: 'flex', gap: '12px', marginBottom: '32px' }}>\n <button\n style={{\n backgroundColor: currentColors.primary,\n color: currentColors.background,\n border: 'none',\n padding: '12px 24px',\n borderRadius: '6px',\n fontSize: '14px',\n fontWeight: '600',\n cursor: 'pointer',\n }}\n >\n Primary Button\n </button>\n <button\n style={{\n backgroundColor: 'transparent',\n color: currentColors.primary,\n border: `2px solid ${currentColors.primary}`,\n padding: '10px 24px',\n borderRadius: '6px',\n fontSize: '14px',\n fontWeight: '600',\n cursor: 'pointer',\n }}\n >\n Secondary Button\n </button>\n </div>\n\n {/* Card */}\n <div\n style={{\n backgroundColor: currentColors.text,\n color: currentColors.background,\n padding: '24px',\n borderRadius: '8px',\n opacity: 0.05,\n marginBottom: '16px',\n }}\n />\n <div\n style={{\n border: `1px solid ${currentColors.text}`,\n padding: '20px',\n borderRadius: '8px',\n opacity: 0.1,\n }}\n >\n <h3\n style={{\n fontSize: '18px',\n fontWeight: '600',\n marginBottom: '12px',\n color: currentColors.text,\n }}\n >\n Sample Card\n </h3>\n <p\n style={{\n fontSize: '14px',\n color: currentColors.text,\n opacity: 0.7,\n }}\n >\n This shows how cards and content blocks will appear.\n </p>\n </div>\n </div>\n\n {/* Footer */}\n <div\n style={{\n backgroundColor: currentColors.accent,\n color: currentColors.background,\n padding: '16px 24px',\n textAlign: 'center',\n fontSize: '14px',\n marginTop: 'auto',\n }}\n >\n © 2025 Your Website. Powered by PayloadCMS.\n </div>\n </div>\n\n {/* Theme info */}\n <div\n style={{\n marginTop: '12px',\n fontSize: '12px',\n color: '#6b7280',\n display: 'grid',\n gridTemplateColumns: 'repeat(2, 1fr)',\n gap: '8px',\n }}\n >\n <div>\n <strong>Active Theme:</strong> {currentTheme}\n </div>\n <div>\n <strong>Primary:</strong> {currentColors.primary}\n </div>\n <div>\n <strong>Accent:</strong> {currentColors.accent}\n </div>\n <div>\n <strong>Background:</strong> {currentColors.background}\n </div>\n </div>\n\n {/* Customization indicator */}\n {hasOverrides && (\n <div\n style={{\n marginTop: '8px',\n padding: '8px 12px',\n backgroundColor: '#fef3c7',\n borderRadius: '6px',\n fontSize: '11px',\n color: '#92400e',\n display: 'flex',\n alignItems: 'center',\n gap: '6px',\n }}\n >\n <span>⚡</span>\n <span>\n <strong>Custom colors applied</strong> - overriding theme defaults\n </span>\n </div>\n )}\n </div>\n )\n}\n"],"names":["useField","React","useMemo","themeIsValid","defaultThemePresets","DEFAULT_THEME_KEY","basePresetMap","reduce","accumulator","preset","name","fallbackPreset","fallbackLightMode","lightMode","primary","accent","background","foreground","ThemePreview","value","selectedTheme","path","primaryColor","accentColor","backgroundColor","textColor","currentTheme","hasOverrides","Boolean","themeColors","secondary","text","currentColors","div","className","style","marginTop","fontSize","fontWeight","marginBottom","color","border","borderRadius","overflow","minHeight","padding","display","justifyContent","alignItems","nav","gap","span","h1","p","lineHeight","opacity","button","cursor","h3","textAlign","gridTemplateColumns","strong"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../src/components/ThemePreview.tsx"],"sourcesContent":["'use client'\n\nimport { useField } from '@payloadcms/ui'\nimport React, { useMemo } from 'react'\nimport { allThemePresets } from '../presets.js'\nimport { themeIsValid } from '../providers/Theme/types.js'\n\nconst DEFAULT_THEME_KEY = 'cool'\nconst basePresetMap = allThemePresets.reduce<Record<string, (typeof allThemePresets)[number]>>(\n (accumulator, preset) => {\n accumulator[preset.name] = preset\n return accumulator\n },\n {},\n)\n\nconst fallbackPreset = basePresetMap[DEFAULT_THEME_KEY] ?? allThemePresets[0]\nconst fallbackLightMode = fallbackPreset?.lightMode ?? {\n primary: '#3b82f6',\n accent: '#06b6d4',\n background: '#ffffff',\n foreground: '#1f2937',\n}\n\nexport default function ThemePreview() {\n // Get individual field values using useField hooks\n const { value: selectedTheme } = useField<string>({ path: 'themeConfiguration.theme' })\n const { value: primaryColor } = useField<string>({\n path: 'themeConfiguration.customization.primaryColor',\n })\n const { value: accentColor } = useField<string>({\n path: 'themeConfiguration.customization.accentColor',\n })\n const { value: backgroundColor } = useField<string>({\n path: 'themeConfiguration.customization.backgroundColor',\n })\n const { value: textColor } = useField<string>({\n path: 'themeConfiguration.customization.textColor',\n })\n\n // Determine current theme and if overrides are active\n const currentTheme = themeIsValid(selectedTheme)\n ? selectedTheme\n : (fallbackPreset?.name ?? 'cool')\n const hasOverrides = Boolean(primaryColor || accentColor || backgroundColor || textColor)\n\n const themeColors = useMemo(() => {\n const preset = basePresetMap[currentTheme] ?? fallbackPreset\n const lightMode = preset?.lightMode ?? fallbackLightMode\n\n return {\n primary: lightMode?.primary ?? fallbackLightMode.primary,\n accent:\n lightMode?.accent ??\n lightMode?.secondary ??\n fallbackLightMode.accent ??\n fallbackLightMode.primary,\n background: lightMode?.background ?? fallbackLightMode.background,\n text: lightMode?.foreground ?? fallbackLightMode.foreground,\n }\n }, [currentTheme])\n\n const currentColors = useMemo(\n () => ({\n primary: primaryColor || themeColors.primary,\n accent: accentColor || themeColors.accent,\n background: backgroundColor || themeColors.background,\n text: textColor || themeColors.text,\n }),\n [primaryColor, accentColor, backgroundColor, textColor, themeColors],\n )\n\n return (\n <div className=\"theme-preview\" style={{ marginTop: '20px' }}>\n <div\n style={{\n fontSize: '16px',\n fontWeight: '600',\n marginBottom: '16px',\n color: '#374151',\n }}\n >\n 🎨 Live Theme Preview\n </div>\n\n <div\n className=\"preview-container\"\n style={{\n border: '2px solid #e5e7eb',\n borderRadius: '12px',\n overflow: 'hidden',\n backgroundColor: currentColors.background,\n color: currentColors.text,\n minHeight: '300px',\n }}\n >\n {/* Header */}\n <div\n style={{\n backgroundColor: currentColors.primary,\n color: currentColors.background,\n padding: '16px 24px',\n display: 'flex',\n justifyContent: 'space-between',\n alignItems: 'center',\n }}\n >\n <div style={{ fontSize: '20px', fontWeight: '700' }}>Your Website</div>\n <nav style={{ display: 'flex', gap: '24px', fontSize: '14px' }}>\n <span>Home</span>\n <span>About</span>\n <span>Services</span>\n <span>Contact</span>\n </nav>\n </div>\n\n {/* Content */}\n <div style={{ padding: '32px 24px' }}>\n <h1\n style={{\n fontSize: '32px',\n fontWeight: '800',\n marginBottom: '16px',\n color: currentColors.text,\n }}\n >\n Welcome to Your Site\n </h1>\n\n <p\n style={{\n fontSize: '16px',\n lineHeight: '1.6',\n marginBottom: '24px',\n color: currentColors.text,\n opacity: 0.8,\n }}\n >\n This is how your content will look with the selected theme. The colors and styling will\n be applied across your entire website.\n </p>\n\n {/* Buttons */}\n <div style={{ display: 'flex', gap: '12px', marginBottom: '32px' }}>\n <button\n style={{\n backgroundColor: currentColors.primary,\n color: currentColors.background,\n border: 'none',\n padding: '12px 24px',\n borderRadius: '6px',\n fontSize: '14px',\n fontWeight: '600',\n cursor: 'pointer',\n }}\n >\n Primary Button\n </button>\n <button\n style={{\n backgroundColor: 'transparent',\n color: currentColors.primary,\n border: `2px solid ${currentColors.primary}`,\n padding: '10px 24px',\n borderRadius: '6px',\n fontSize: '14px',\n fontWeight: '600',\n cursor: 'pointer',\n }}\n >\n Secondary Button\n </button>\n </div>\n\n {/* Card */}\n <div\n style={{\n backgroundColor: currentColors.text,\n color: currentColors.background,\n padding: '24px',\n borderRadius: '8px',\n opacity: 0.05,\n marginBottom: '16px',\n }}\n />\n <div\n style={{\n border: `1px solid ${currentColors.text}`,\n padding: '20px',\n borderRadius: '8px',\n opacity: 0.1,\n }}\n >\n <h3\n style={{\n fontSize: '18px',\n fontWeight: '600',\n marginBottom: '12px',\n color: currentColors.text,\n }}\n >\n Sample Card\n </h3>\n <p\n style={{\n fontSize: '14px',\n color: currentColors.text,\n opacity: 0.7,\n }}\n >\n This shows how cards and content blocks will appear.\n </p>\n </div>\n </div>\n\n {/* Footer */}\n <div\n style={{\n backgroundColor: currentColors.accent,\n color: currentColors.background,\n padding: '16px 24px',\n textAlign: 'center',\n fontSize: '14px',\n marginTop: 'auto',\n }}\n >\n © 2025 Your Website. Powered by PayloadCMS.\n </div>\n </div>\n\n {/* Theme info */}\n <div\n style={{\n marginTop: '12px',\n fontSize: '12px',\n color: '#6b7280',\n display: 'grid',\n gridTemplateColumns: 'repeat(2, 1fr)',\n gap: '8px',\n }}\n >\n <div>\n <strong>Active Theme:</strong> {currentTheme}\n </div>\n <div>\n <strong>Primary:</strong> {currentColors.primary}\n </div>\n <div>\n <strong>Accent:</strong> {currentColors.accent}\n </div>\n <div>\n <strong>Background:</strong> {currentColors.background}\n </div>\n </div>\n\n {/* Customization indicator */}\n {hasOverrides && (\n <div\n style={{\n marginTop: '8px',\n padding: '8px 12px',\n backgroundColor: '#fef3c7',\n borderRadius: '6px',\n fontSize: '11px',\n color: '#92400e',\n display: 'flex',\n alignItems: 'center',\n gap: '6px',\n }}\n >\n <span>⚡</span>\n <span>\n <strong>Custom colors applied</strong> - overriding theme defaults\n </span>\n </div>\n )}\n </div>\n )\n}\n"],"names":["useField","React","useMemo","allThemePresets","themeIsValid","DEFAULT_THEME_KEY","basePresetMap","reduce","accumulator","preset","name","fallbackPreset","fallbackLightMode","lightMode","primary","accent","background","foreground","ThemePreview","value","selectedTheme","path","primaryColor","accentColor","backgroundColor","textColor","currentTheme","hasOverrides","Boolean","themeColors","secondary","text","currentColors","div","className","style","marginTop","fontSize","fontWeight","marginBottom","color","border","borderRadius","overflow","minHeight","padding","display","justifyContent","alignItems","nav","gap","span","h1","p","lineHeight","opacity","button","cursor","h3","textAlign","gridTemplateColumns","strong"],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ThemePresetImportField.d.ts","sourceRoot":"","sources":["../../src/fields/ThemePresetImportField.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,SAAS,CAAA;AASnD,QAAA,MAAM,sBAAsB,GAAI,iBAAiB,oBAAoB,gCAyJpE,CAAA;AAED,eAAe,sBAAsB,CAAA"}
|