@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/README.md CHANGED
@@ -2,23 +2,25 @@
2
2
 
3
3
  A comprehensive theme management plugin for Payload CMS v3 that provides powerful theming capabilities with SSR support, preventing FOUC (Flash of Unstyled Content).
4
4
 
5
- ## πŸŽ‰ Version 0.2.1 - New Features!
5
+ ## πŸŽ‰ Version 0.6.0 - New Features!
6
6
 
7
+ - **βœ… Standalone Global Support** - Create separate appearance settings as a global
8
+ - **βœ… Auto-Populate Light/Dark Colors** - Theme selection hook automatically fills color fields
9
+ - **βœ… Multi-Tenant Ready** - Full support for multi-tenant applications
10
+ - **βœ… Cleaner Data Structure** - Fixed nesting issues for better API integration
7
11
  - **βœ… Live Theme Preview** - Real-time theme preview in admin panel at `/admin/theme-preview`
8
12
  - **βœ… Professional Color Picker** - Enhanced color picker with react-colorful library
9
- - **βœ… Streamlined Tokens** - Optimized to 24 essential color tokens
10
- - **βœ… Tabs Structure** - Plugin creates a "NastavenΓ­ vzhledu" (Appearance Settings) tab
11
- - **βœ… Extended Theme Support** - OKLCH color format with semantic tokens
12
13
  - **βœ… shadcn/ui Compatible** - Works with https://ui.shadcn.com/themes
13
14
  - **βœ… TweakCN Compatible** - Works with https://tweakcn.com/editor/theme
14
- - **βœ… Chart Colors** - 5 customizable colors for data visualization
15
15
 
16
16
  ## Features
17
17
 
18
18
  - 🎨 **Multiple Theme Presets** - Cool, Brutal, Neon, Solar, and more
19
+ - 🎯 **Auto-Populate Colors** - Theme selection automatically sets Light/Dark mode colors
20
+ - 🌍 **Standalone Global** - Create separate appearance settings global (v0.6.0+)
19
21
  - πŸ–ΌοΈ **Live Theme Preview** - Real-time preview in admin panel (no configuration needed!)
20
22
  - 🎨 **Extended Themes** - OKLCH-based themes with full shadcn/ui token support
21
- - 🎨 **Custom Color Palette** - Full HSL color customization (24 semantic tokens)
23
+ - 🎨 **Custom Color Palette** - Full HSL color customization (19 semantic tokens)
22
24
  - πŸ”€ **Typography Control** - Google Fonts integration for headings, body, and code
23
25
  - πŸ“ **Border Radius Presets** - Sharp, Rounded, or Pill styles
24
26
  - πŸŒ“ **Dark Mode Support** - Built-in light/dark/system mode toggle
@@ -27,6 +29,7 @@ A comprehensive theme management plugin for Payload CMS v3 that provides powerfu
27
29
  - ⚑ **Performance Optimized** - Critical CSS inlining, preload links
28
30
  - 🎯 **Type Safe** - Full TypeScript support
29
31
  - πŸ”§ **Highly Configurable** - Flexible plugin options
32
+ - πŸ‘₯ **Multi-Tenant Support** - Built-in multi-tenant capabilities
30
33
 
31
34
  ## Installation
32
35
 
@@ -42,6 +45,8 @@ yarn add @kilivi/payloadcms-theme-management
42
45
 
43
46
  ### 1. Add Plugin to Payload Config
44
47
 
48
+ #### Option A: Add as Tab to Existing Collection (Default)
49
+
45
50
  ```typescript
46
51
  import { themeManagementPlugin } from '@kilivi/payloadcms-theme-management'
47
52
  import { buildConfig } from 'payload'
@@ -49,7 +54,7 @@ import { buildConfig } from 'payload'
49
54
  export default buildConfig({
50
55
  // ... other config
51
56
 
52
- globals: [
57
+ collections: [
53
58
  {
54
59
  slug: 'site-settings',
55
60
  fields: [
@@ -57,7 +62,7 @@ export default buildConfig({
57
62
  name: 'siteName',
58
63
  type: 'text',
59
64
  },
60
- // Theme configuration will be injected here
65
+ // Theme configuration will be injected here as a tab inside this collection
61
66
  ],
62
67
  },
63
68
  ],
@@ -74,10 +79,37 @@ export default buildConfig({
74
79
  })
75
80
  ```
76
81
 
82
+ > **Note:** Option A injects an **Appearance Settings** tab into the specified collection (`targetCollection`). If you prefer a separate global (standalone settings), use **Option B** below and set `useStandaloneCollection: true` in the plugin options.
83
+
84
+ #### Option B: Create Standalone Global (Separate Settings)
85
+
86
+ ```typescript
87
+ import { themeManagementPlugin } from '@kilivi/payloadcms-theme-management'
88
+ import { buildConfig } from 'payload'
89
+
90
+ export default buildConfig({
91
+ // ... other config
92
+
93
+ plugins: [
94
+ themeManagementPlugin({
95
+ enabled: true,
96
+ useStandaloneCollection: true, // Creates a separate global
97
+ standaloneCollectionSlug: 'appearance-settings', // Optional: custom slug
98
+ standaloneCollectionLabel: 'Appearance Settings', // Optional: custom label
99
+ defaultTheme: 'cool',
100
+ includeColorModeToggle: true,
101
+ enableLogging: true,
102
+ }),
103
+ ],
104
+ })
105
+ ```
106
+
77
107
  ### 2. Add Server Theme Injection (Next.js)
78
108
 
79
109
  **⚠️ IMPORTANT:** Import from `/server` entry point!
80
110
 
111
+ #### If Using Default (Tab in existing collection):
112
+
81
113
  ```tsx
82
114
  // app/layout.tsx
83
115
  import { ServerThemeInjector } from '@kilivi/payloadcms-theme-management/server'
@@ -88,7 +120,7 @@ export default async function RootLayout({ children }: { children: React.ReactNo
88
120
  const payload = await getPayload({ config: configPromise })
89
121
 
90
122
  const { docs } = await payload.find({
91
- collection: 'site-settings',
123
+ collection: 'site-settings', // Your target collection
92
124
  limit: 1,
93
125
  })
94
126
 
@@ -103,6 +135,33 @@ export default async function RootLayout({ children }: { children: React.ReactNo
103
135
  }
104
136
  ```
105
137
 
138
+ #### If Using Standalone Global:
139
+
140
+ ```tsx
141
+ // app/layout.tsx
142
+ import { ServerThemeInjector } from '@kilivi/payloadcms-theme-management/server'
143
+ import configPromise from '@payload-config'
144
+ import { getPayload } from 'payload'
145
+
146
+ export default async function RootLayout({ children }: { children: React.ReactNode }) {
147
+ const payload = await getPayload({ config: configPromise })
148
+
149
+ // Fetch from standalone global
150
+ const appearanceSettings = await payload.globals.findBySlug({
151
+ slug: 'appearance-settings', // Your standalone global slug
152
+ })
153
+
154
+ return (
155
+ <html lang="en">
156
+ <head>
157
+ <ServerThemeInjector themeConfiguration={appearanceSettings?.themeConfiguration} />
158
+ </head>
159
+ <body>{children}</body>
160
+ </html>
161
+ )
162
+ }
163
+ ```
164
+
106
165
  ### 3. Use Theme Variables in Your CSS
107
166
 
108
167
  The plugin injects CSS custom properties you can use:
@@ -124,17 +183,20 @@ Or with Tailwind CSS:
124
183
 
125
184
  ## Plugin Configuration Options
126
185
 
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 |
186
+ | Option | Type | Default | Description |
187
+ | --------------------------- | ---------------------------------- | ----------------------- | ----------------------------------------------------------------- |
188
+ | `enabled` | `boolean` | `true` | Enable/disable the plugin |
189
+ | `targetCollection` | `string` | `'site-settings'` | Collection slug to add theme field to (when not using standalone) |
190
+ | `useStandaloneCollection` | `boolean` | `false` | Create a separate global instead of adding as a tab |
191
+ | `standaloneCollectionSlug` | `string` | `'appearance-settings'` | Slug for the standalone global |
192
+ | `standaloneCollectionLabel` | `string \| Record<string, string>` | `'Appearance Settings'` | Label for the standalone global (supports i18n) |
193
+ | `themePresets` | `ThemePreset[]` | Built-in presets | Custom theme presets |
194
+ | `defaultTheme` | `string` | `'cool'` | Default theme preset name |
195
+ | `includeColorModeToggle` | `boolean` | `true` | Show light/dark mode toggle |
196
+ | `includeCustomCSS` | `boolean` | `true` | Allow custom CSS injection |
197
+ | `includeBrandIdentity` | `boolean` | `false` | Show brand identity fields |
198
+ | `enableAdvancedFeatures` | `boolean` | `true` | Enable advanced customization |
199
+ | `enableLogging` | `boolean` | `false` | Log plugin actions to console |
138
200
 
139
201
  ## Available Theme Presets
140
202
 
@@ -222,33 +284,433 @@ import { ThemeTokenSelectField } from '@kilivi/payloadcms-theme-management/field
222
284
 
223
285
  ### With Tailwind CSS
224
286
 
225
- ```typescript
226
- // tailwind.config.ts
227
- import type { Config } from 'tailwindcss'
287
+ #### tailwind.config.mjs
228
288
 
229
- const config: Config = {
289
+ ```typescript
290
+ /* eslint-disable @typescript-eslint/no-unused-vars */
291
+ /* eslint-disable @typescript-eslint/no-require-imports */
292
+ /* eslint-disable import/no-anonymous-default-export */
293
+ import defaultTheme from 'tailwindcss/defaultTheme'
294
+
295
+ /** @type {import('tailwindcss').Config} */
296
+ export default {
297
+ darkMode: ['class'],
298
+ content: [
299
+ './src/app/**/*.{ts,tsx}',
300
+ './src/components/**/*.{ts,tsx}',
301
+ './src/collections/**/*.{ts,tsx}',
302
+ './src/providers/**/*.{ts,tsx}',
303
+ './src/heros/**/*.{ts,tsx}',
304
+ ],
305
+ safelist: [
306
+ // Grid columns
307
+ 'col-span-4',
308
+ 'md:col-span-2',
309
+ 'lg:col-span-4',
310
+ 'lg:col-span-6',
311
+ 'lg:col-span-8',
312
+ 'lg:col-span-12',
313
+ // Border colors
314
+ 'border-border',
315
+ 'border-error',
316
+ 'border-success',
317
+ 'border-warning',
318
+ // Background colors
319
+ 'bg-card',
320
+ 'bg-error/30',
321
+ 'bg-success/30',
322
+ 'bg-warning/30',
323
+ ],
230
324
  theme: {
325
+ container: {
326
+ center: true,
327
+ padding: {
328
+ DEFAULT: 'var(--layout-containerPadding)',
329
+ md: 'var(--layout-containerPaddingTablet)',
330
+ lg: 'var(--layout-containerPaddingDesktop)',
331
+ },
332
+ screens: {
333
+ sm: '640px',
334
+ md: '768px',
335
+ lg: '1024px',
336
+ xl: '1280px',
337
+ },
338
+ },
231
339
  extend: {
232
340
  colors: {
233
- background: 'hsl(var(--background))',
234
- foreground: 'hsl(var(--foreground))',
235
- primary: {
236
- DEFAULT: 'hsl(var(--primary))',
237
- foreground: 'hsl(var(--primary-foreground))',
238
- },
239
- // ... other color variables
341
+ background: 'var(--background)',
342
+ foreground: 'var(--foreground)',
343
+ card: 'var(--card)',
344
+ 'card-foreground': 'var(--card-foreground)',
345
+ popover: 'var(--popover)',
346
+ 'popover-foreground': 'var(--popover-foreground)',
347
+ primary: 'var(--primary)',
348
+ 'primary-foreground': 'var(--primary-foreground)',
349
+ secondary: 'var(--secondary)',
350
+ 'secondary-foreground': 'var(--secondary-foreground)',
351
+ muted: 'var(--muted)',
352
+ 'muted-foreground': 'var(--muted-foreground)',
353
+ accent: 'var(--accent)',
354
+ 'accent-foreground': 'var(--accent-foreground)',
355
+ destructive: 'var(--destructive)',
356
+ 'destructive-foreground': 'var(--destructive-foreground)',
357
+ border: 'var(--border)',
358
+ input: 'var(--input)',
359
+ ring: 'var(--ring)',
360
+ success: 'var(--success)',
361
+ 'success-foreground': 'var(--success-foreground)',
362
+ warning: 'var(--warning)',
363
+ 'warning-foreground': 'var(--warning-foreground)',
364
+ error: 'var(--error)',
365
+ 'error-foreground': 'var(--error-foreground)',
366
+ info: 'var(--info)',
367
+ 'info-foreground': 'var(--info-foreground)',
240
368
  },
241
369
  borderRadius: {
242
- lg: 'var(--radius)',
243
- md: 'calc(var(--radius) - 2px)',
244
- sm: 'calc(var(--radius) - 4px)',
370
+ sm: 'var(--radius-small)',
371
+ DEFAULT: 'var(--radius-default)',
372
+ md: 'var(--radius-medium)',
373
+ lg: 'var(--radius-large)',
245
374
  },
246
375
  fontFamily: {
247
- heading: ['var(--font-heading)', 'sans-serif'],
248
- body: ['var(--font-body)', 'sans-serif'],
376
+ sans: ['var(--typography-fontFamily)', ...defaultTheme.fontFamily.sans],
377
+ heading: ['var(--typography-headingFamily)', ...defaultTheme.fontFamily.sans],
378
+ mono: ['var(--font-geist-mono)', ...defaultTheme.fontFamily.mono],
379
+ },
380
+ fontSize: {
381
+ base: ['var(--typography-baseFontSize)', { lineHeight: 'var(--typography-lineHeight)' }],
382
+ },
383
+ letterSpacing: {
384
+ tight: 'var(--typography-letterSpacing-tight)',
385
+ normal: 'var(--typography-letterSpacing-normal)',
386
+ wide: 'var(--typography-letterSpacing-wide)',
387
+ },
388
+ fontWeight: {
389
+ normal: 'var(--typography-fontWeights-normal)',
390
+ medium: 'var(--typography-fontWeights-medium)',
391
+ semibold: 'var(--typography-fontWeights-semibold)',
392
+ bold: 'var(--typography-fontWeights-bold)',
393
+ },
394
+ spacing: {
395
+ section: {
396
+ DEFAULT: 'var(--layout-sectionSpacing)',
397
+ md: 'var(--layout-sectionSpacingTablet)',
398
+ lg: 'var(--layout-sectionSpacingDesktop)',
399
+ },
400
+ },
401
+ transitionProperty: {
402
+ button: 'var(--components-button-transition)',
403
+ },
404
+ scale: {
405
+ 'button-hover': 'var(--components-button-hover-scale)',
406
+ },
407
+ opacity: {
408
+ 'button-hover': 'var(--components-button-hover-opacity)',
409
+ },
410
+ boxShadow: {
411
+ card: 'var(--components-card-shadow)',
412
+ },
413
+ padding: {
414
+ card: 'var(--components-card-padding)',
415
+ button: 'var(--components-button-padding)',
416
+ input: 'var(--components-input-padding)',
417
+ },
418
+ height: {
419
+ input: 'var(--components-input-height)',
420
+ },
421
+ typography: ({ theme }) => ({
422
+ DEFAULT: {
423
+ css: {
424
+ '--tw-prose-body': theme('colors.foreground'),
425
+ '--tw-prose-headings': theme('colors.foreground'),
426
+ '--tw-prose-lead': theme('colors.muted.foreground'),
427
+ '--tw-prose-links': theme('colors.primary'),
428
+ '--tw-prose-bold': theme('colors.foreground'),
429
+ '--tw-prose-counters': theme('colors.foreground'),
430
+ '--tw-prose-bullets': theme('colors.foreground'),
431
+ '--tw-prose-hr': theme('colors.border'),
432
+ '--tw-prose-quotes': theme('colors.foreground'),
433
+ '--tw-prose-quote-borders': theme('colors.border'),
434
+ '--tw-prose-captions': theme('colors.muted.foreground'),
435
+ '--tw-prose-code': theme('colors.foreground'),
436
+ '--tw-prose-pre-code': theme('colors.foreground'),
437
+ '--tw-prose-pre-bg': theme('colors.muted'),
438
+ '--tw-prose-th-borders': theme('colors.border'),
439
+ '--tw-prose-td-borders': theme('colors.border'),
440
+ h1: {
441
+ fontWeight: 'var(--typography-fontWeights-bold)',
442
+ marginBottom: '0.25em',
443
+ fontFamily: theme('fontFamily.heading'),
444
+ letterSpacing: 'var(--typography-letterSpacing-tight)',
445
+ },
446
+ h2: {
447
+ fontFamily: theme('fontFamily.heading'),
448
+ fontWeight: 'var(--typography-fontWeights-semibold)',
449
+ letterSpacing: 'var(--typography-letterSpacing-tight)',
450
+ },
451
+ h3: {
452
+ fontFamily: theme('fontFamily.heading'),
453
+ fontWeight: 'var(--typography-fontWeights-semibold)',
454
+ letterSpacing: 'var(--typography-letterSpacing-tight)',
455
+ },
456
+ h4: {
457
+ fontFamily: theme('fontFamily.heading'),
458
+ fontWeight: 'var(--typography-fontWeights-medium)',
459
+ letterSpacing: 'var(--typography-letterSpacing-normal)',
460
+ },
461
+ },
462
+ },
463
+ base: {
464
+ css: [
465
+ {
466
+ h1: { fontSize: '2.5rem' },
467
+ h2: { fontSize: '1.25rem' },
468
+ },
469
+ ],
470
+ },
471
+ md: {
472
+ css: [
473
+ {
474
+ h1: { fontSize: '3.5rem' },
475
+ h2: { fontSize: '1.5rem' },
476
+ },
477
+ ],
478
+ },
479
+ invert: {
480
+ css: {
481
+ '--tw-prose-body': 'var(--foreground)',
482
+ '--tw-prose-headings': 'var(--foreground)',
483
+ '--tw-prose-lead': 'var(--muted-foreground)',
484
+ '--tw-prose-links': 'var(--primary)',
485
+ '--tw-prose-bold': 'var(--foreground)',
486
+ '--tw-prose-counters': 'var(--foreground)',
487
+ '--tw-prose-bullets': 'var(--foreground)',
488
+ '--tw-prose-hr': 'var(--border)',
489
+ '--tw-prose-quotes': 'var(--foreground)',
490
+ '--tw-prose-quote-borders': 'var(--border)',
491
+ '--tw-prose-captions': 'var(--muted-foreground)',
492
+ '--tw-prose-code': 'var(--foreground)',
493
+ '--tw-prose-pre-code': 'var(--foreground)',
494
+ '--tw-prose-pre-bg': 'var(--muted)',
495
+ '--tw-prose-th-borders': 'var(--border)',
496
+ '--tw-prose-td-borders': 'var(--border)',
497
+ },
498
+ },
499
+ }),
500
+ animation: {
501
+ 'accordion-down': 'accordion-down 0.2s ease-out',
502
+ 'accordion-up': 'accordion-up 0.2s ease-out',
503
+ },
504
+ keyframes: {
505
+ 'accordion-down': {
506
+ from: { height: 0 },
507
+ to: { height: 'var(--radix-accordion-content-height)' },
508
+ },
509
+ 'accordion-up': {
510
+ from: { height: 'var(--radix-accordion-content-height)' },
511
+ to: { height: 0 },
512
+ },
249
513
  },
250
514
  },
251
515
  },
516
+ plugins: [require('tailwindcss-animate'), require('@tailwindcss/typography')],
517
+ }
518
+ ```
519
+
520
+ #### globals.css
521
+
522
+ ```css
523
+ @import 'tailwindcss';
524
+
525
+ @config '../../../../../tailwind.config.mjs';
526
+
527
+ @layer base {
528
+ /* Theme Configuration CSS Variables */
529
+ :root {
530
+ /* Font Scale Presets */
531
+ --font-scale-small: 0.875;
532
+ --font-scale-medium: 1;
533
+ --font-scale-large: 1.125;
534
+ --font-scale-xl: 1.25;
535
+
536
+ /* Spacing Presets */
537
+ --spacing-compact: 0.75;
538
+ --spacing-comfortable: 1;
539
+ --spacing-spacious: 1.25;
540
+ --spacing-xl: 1.5;
541
+
542
+ /* Animation Levels */
543
+ --animation-none-duration: 0ms;
544
+ --animation-reduced-duration: 100ms;
545
+ --animation-normal-duration: 200ms;
546
+ --animation-enhanced-duration: 300ms;
547
+
548
+ /* Dynamic theme configuration (set by JS) */
549
+ --theme-font-scale: var(--font-scale-medium);
550
+ --theme-spacing: var(--spacing-comfortable);
551
+ --theme-animation-level: normal;
552
+
553
+ /* Apply spacing multiplier to layout */
554
+ --layout-containerPadding-scaled: calc(
555
+ var(--layout-containerPadding) * var(--theme-spacing, 1)
556
+ );
557
+ --layout-containerPaddingTablet-scaled: calc(
558
+ var(--layout-containerPaddingTablet) * var(--theme-spacing, 1)
559
+ );
560
+ --layout-containerPaddingDesktop-scaled: calc(
561
+ var(--layout-containerPaddingDesktop) * var(--theme-spacing, 1)
562
+ );
563
+ --layout-sectionSpacing-scaled: calc(var(--layout-sectionSpacing) * var(--theme-spacing, 1));
564
+ --layout-sectionSpacingTablet-scaled: calc(
565
+ var(--layout-sectionSpacingTablet) * var(--theme-spacing, 1)
566
+ );
567
+ --layout-sectionSpacingDesktop-scaled: calc(
568
+ var(--layout-sectionSpacingDesktop) * var(--theme-spacing, 1)
569
+ );
570
+ --components-card-padding-scaled: calc(
571
+ var(--components-card-padding) * var(--theme-spacing, 1)
572
+ );
573
+ --components-button-padding-scaled: var(--components-button-padding);
574
+ --components-input-padding-scaled: var(--components-input-padding);
575
+ }
576
+
577
+ *,
578
+ *::before,
579
+ *::after {
580
+ box-sizing: border-box;
581
+ margin: 0;
582
+ padding: 0;
583
+ @apply border-border;
584
+ }
585
+
586
+ html {
587
+ -webkit-text-size-adjust: 100%;
588
+ font-size: calc(var(--typography-baseFontSize, 16px) * var(--theme-font-scale, 1));
589
+ line-height: var(--typography-lineHeight, 1.5);
590
+ font-family: var(--typography-fontFamily, system-ui, sans-serif);
591
+ visibility: hidden;
592
+ }
593
+
594
+ /* Animation level controls */
595
+ [data-animation-level='none'] * {
596
+ animation-duration: var(--animation-none-duration) !important;
597
+ transition-duration: var(--animation-none-duration) !important;
598
+ }
599
+
600
+ [data-animation-level='reduced'] * {
601
+ animation-duration: var(--animation-reduced-duration) !important;
602
+ transition-duration: var(--animation-reduced-duration) !important;
603
+ }
604
+
605
+ [data-animation-level='normal'] * {
606
+ animation-duration: var(--animation-normal-duration);
607
+ transition-duration: var(--animation-normal-duration);
608
+ }
609
+
610
+ [data-animation-level='enhanced'] * {
611
+ animation-duration: var(--animation-enhanced-duration);
612
+ transition-duration: var(--animation-enhanced-duration);
613
+ }
614
+
615
+ h1,
616
+ h2,
617
+ h3,
618
+ h4,
619
+ h5,
620
+ h6 {
621
+ font-family: var(
622
+ --typography-headingFamily,
623
+ var(--typography-fontFamily, system-ui, sans-serif)
624
+ );
625
+ font-weight: var(--typography-fontWeights-bold, 700);
626
+ line-height: 1.2;
627
+ }
628
+
629
+ /* Prevent flash of unstyled content except for Storybook */
630
+ :root:not([data-theme]):not([data-theme-mode]):not(.sb-show-main) {
631
+ visibility: hidden;
632
+ }
633
+
634
+ :root[data-theme][data-theme-mode],
635
+ .sb-show-main {
636
+ visibility: visible;
637
+ }
638
+
639
+ html:not(.sb-show-main) {
640
+ opacity: 0;
641
+ }
642
+
643
+ html[data-theme-mode='dark'],
644
+ html[data-theme-mode='light'],
645
+ html.sb-show-main {
646
+ opacity: 1;
647
+ transition: opacity 0ms;
648
+ }
649
+
650
+ /* Force immediate opacity when JS is disabled */
651
+ html:not([data-theme-mode]) {
652
+ opacity: 1;
653
+ }
654
+
655
+ /* Media queries for responsive layout */
656
+ @media (min-width: 640px) {
657
+ :root {
658
+ --layout-containerPadding: var(--layout-containerPaddingTablet, 2rem);
659
+ --layout-sectionSpacing: var(--layout-sectionSpacingTablet, 3rem);
660
+ }
661
+ }
662
+
663
+ @media (min-width: 1024px) {
664
+ :root {
665
+ --layout-containerPadding: var(--layout-containerPaddingDesktop, 2rem);
666
+ --layout-sectionSpacing: var(--layout-sectionSpacingDesktop, 4rem);
667
+ }
668
+ }
669
+
670
+ /* Ensure dark mode styles take precedence */
671
+ html[data-theme-mode='dark'] {
672
+ color-scheme: dark;
673
+ }
674
+
675
+ /* Native View Transitions API - React 19 */
676
+ @view-transition {
677
+ navigation: auto;
678
+ }
679
+
680
+ /* Smooth fade transition for page navigation */
681
+ ::view-transition-old(root),
682
+ ::view-transition-new(root) {
683
+ animation-duration: 0.3s;
684
+ animation-timing-function: ease-in-out;
685
+ }
686
+
687
+ ::view-transition-old(root) {
688
+ animation-name: fade-out;
689
+ }
690
+
691
+ ::view-transition-new(root) {
692
+ animation-name: fade-in;
693
+ }
694
+
695
+ @keyframes fade-out {
696
+ to {
697
+ opacity: 0;
698
+ }
699
+ }
700
+
701
+ @keyframes fade-in {
702
+ from {
703
+ opacity: 0;
704
+ }
705
+ }
706
+
707
+ /* Respect user's reduced motion preference */
708
+ @media (prefers-reduced-motion: reduce) {
709
+ ::view-transition-old(root),
710
+ ::view-transition-new(root) {
711
+ animation-duration: 0.01ms !important;
712
+ }
713
+ }
252
714
  }
253
715
  ```
254
716
 
@@ -257,12 +719,29 @@ const config: Config = {
257
719
  ```typescript
258
720
  import { fetchThemeConfiguration } from '@kilivi/payloadcms-theme-management'
259
721
 
260
- // Simple usage
722
+ // Default: fetch from 'site-settings' collection
261
723
  const theme = await fetchThemeConfiguration()
262
724
 
263
- // With options
725
+ // Fetch from standalone global
264
726
  const theme = await fetchThemeConfiguration({
265
- collectionSlug: 'site-settings',
727
+ collectionSlug: 'appearance-settings', // Your standalone global slug
728
+ useGlobal: true, // Set to true when using standalone global
729
+ depth: 2,
730
+ locale: 'en',
731
+ })
732
+
733
+ // With multi-tenant support
734
+ const theme = await fetchThemeConfiguration({
735
+ tenantSlug: 'tenant-123', // Optional: tenant identifier
736
+ collectionSlug: 'appearance-settings',
737
+ useGlobal: true,
738
+ depth: 2,
739
+ })
740
+
741
+ // From collection (default behavior)
742
+ const theme = await fetchThemeConfiguration({
743
+ collectionSlug: 'site-settings', // Collection slug
744
+ useGlobal: false, // Use collection endpoint
266
745
  depth: 2,
267
746
  locale: 'en',
268
747
  })
@@ -423,7 +902,19 @@ Created for Payload CMS v3 applications.
423
902
 
424
903
  ## Changelog
425
904
 
426
- ### v0.1.9 (Latest)
905
+ ### v0.6.0 (Latest)
906
+
907
+ - βœ… **Added:** Standalone Global Support β€” create separate appearance settings as a global
908
+ - βœ… **Added:** Auto-populate Light/Dark colors when selecting a theme
909
+ - βœ… **Added:** Multi-tenant support and tenant-aware theme fetching
910
+ - βœ… **Fixed:** Cleaner data structure for improved API integration
911
+ - βœ… **Added:** Live Theme Preview at `/admin/theme-preview` (real-time updates)
912
+ - βœ… **Added:** Professional color picker (react-colorful)
913
+ - βœ… **Improved:** shadcn/ui and TweakCN compatibility
914
+ - βœ… **Improved:** SSR theme injection, zero FOUC, and performance optimizations
915
+ - βœ… **Updated:** Documentation and examples
916
+
917
+ ### v0.1.9
427
918
 
428
919
  - βœ… **Fixed:** Server/client component separation
429
920
  - βœ… **Added:** `server-only` package to prevent bundling errors