@dheme/react 2.10.0 → 2.12.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.
package/README.md CHANGED
@@ -79,6 +79,7 @@ The main provider. Manages theme state, API calls, caching, and CSS variable app
79
79
  saturationAdjust: 10,
80
80
  secondaryColor: '#10b981',
81
81
  borderIsColored: false,
82
+ tailwindVersion: 'v4', // 'v3' | 'v4' (default: 'v4')
82
83
  }}
83
84
  defaultMode="light" // 'light' | 'dark' (default: 'light')
84
85
  persist={true} // Cache in localStorage (default: true)
@@ -103,6 +104,9 @@ The main provider. Manages theme state, API calls, caching, and CSS variable app
103
104
  | `onThemeChange` | `(theme: GenerateThemeResponse) => void` | - | Called when theme data changes. |
104
105
  | `onModeChange` | `(mode: ThemeMode) => void` | - | Called when mode changes. |
105
106
  | `onError` | `(error: Error) => void` | - | Called on API errors. |
107
+ | `fallback` | `React.ReactNode` | - | Shown while the theme is loading for the first time. |
108
+
109
+ > **`themeParams.tailwindVersion`** controls the CSS variable format applied to `:root`. Use `'v3'` for projects that wrap variables with `hsl(var(--token))` (Tailwind v3 / shadcn/ui default), or `'v4'` (default) for projects that use `var(--token)` directly (Tailwind v4 / `@theme inline`).
106
110
 
107
111
  ### `<DhemeScript>`
108
112
 
@@ -259,7 +263,22 @@ The provider also syncs the `dark` class on `<html>` automatically.
259
263
 
260
264
  ## CSS Variables
261
265
 
262
- The provider sets 19 CSS variables + `--radius` on `:root`:
266
+ The provider sets 19 CSS variables + `--radius` on `:root`. The value format depends on `themeParams.tailwindVersion`:
267
+
268
+ **Tailwind v4** (default) — wrapped `hsl()`, use with `var(--token)`:
269
+
270
+ ```css
271
+ :root {
272
+ --background: hsl(0 0% 100%);
273
+ --foreground: hsl(222.2 84% 4.9%);
274
+ --primary: hsl(221.2 83.2% 53.3%);
275
+ --primary-foreground: hsl(210 40% 98%);
276
+ /* ... 15 more tokens */
277
+ --radius: 0.5rem;
278
+ }
279
+ ```
280
+
281
+ **Tailwind v3** (`tailwindVersion: 'v3'`) — bare channels, use with `hsl(var(--token))`:
263
282
 
264
283
  ```css
265
284
  :root {
@@ -272,8 +291,6 @@ The provider sets 19 CSS variables + `--radius` on `:root`:
272
291
  }
273
292
  ```
274
293
 
275
- Values are in shadcn/ui format (`h s% l%`), directly compatible with Tailwind CSS `hsl()` usage.
276
-
277
294
  ## ThemeGenerator
278
295
 
279
296
  A floating FAB (Floating Action Button) that lets users generate and preview themes in real time — directly inside your app. No external dependencies beyond React itself.
@@ -409,25 +426,31 @@ const [open, setOpen] = useState(false);
409
426
 
410
427
  ## Utilities
411
428
 
412
- ### `themeToCSS(theme, mode)`
429
+ ### `themeToCSS(theme, mode, tailwindVersion?)`
413
430
 
414
431
  Convert a `GenerateThemeResponse` to a CSS variable assignment string.
415
432
 
416
433
  ```typescript
417
434
  import { themeToCSS } from '@dheme/react';
418
435
 
436
+ // Tailwind v4 (default) — hsl() wrapped
419
437
  const css = themeToCSS(theme, 'light');
438
+ // "--background:hsl(0 0% 100%);--foreground:hsl(222.2 84% 4.9%);..."
439
+
440
+ // Tailwind v3 — bare channels
441
+ const css = themeToCSS(theme, 'light', 'v3');
420
442
  // "--background:0 0% 100%;--foreground:222.2 84% 4.9%;..."
421
443
  ```
422
444
 
423
- ### `applyThemeCSSVariables(theme, mode)`
445
+ ### `applyThemeCSSVariables(theme, mode, tailwindVersion?)`
424
446
 
425
447
  Manually apply CSS variables to `:root`.
426
448
 
427
449
  ```typescript
428
450
  import { applyThemeCSSVariables } from '@dheme/react';
429
451
 
430
- applyThemeCSSVariables(theme, 'dark');
452
+ applyThemeCSSVariables(theme, 'dark'); // Tailwind v4 (default)
453
+ applyThemeCSSVariables(theme, 'dark', 'v3'); // Tailwind v3
431
454
  ```
432
455
 
433
456
  ### `removeThemeCSSVariables()`
package/dist/index.d.mts CHANGED
@@ -45,6 +45,14 @@ interface DhemeProviderProps {
45
45
  onThemeChange?: (theme: GenerateThemeResponse) => void;
46
46
  onModeChange?: (mode: ThemeMode) => void;
47
47
  onError?: (error: Error) => void;
48
+ /**
49
+ * Rendered instead of children while the initial theme is loading.
50
+ * Use this to prevent layout flash by showing a skeleton or spinner.
51
+ *
52
+ * Note: when using @dheme/next with DhemeScript, the theme is injected
53
+ * server-side — omit this prop in that case to avoid an unnecessary flash.
54
+ */
55
+ fallback?: React.ReactNode;
48
56
  children: React.ReactNode;
49
57
  }
50
58
  interface DhemeScriptProps {
@@ -52,7 +60,7 @@ interface DhemeScriptProps {
52
60
  nonce?: string;
53
61
  }
54
62
 
55
- declare function DhemeProvider({ apiKey, theme: primaryColor, themeParams, defaultMode, baseUrl, persist, autoApply, onGenerateTheme: customGenerateTheme, onThemeChange, onModeChange, onError, children, }: DhemeProviderProps): React__default.ReactElement;
63
+ declare function DhemeProvider({ apiKey, theme: primaryColor, themeParams, defaultMode, baseUrl, persist, autoApply, onGenerateTheme: customGenerateTheme, onThemeChange, onModeChange, onError, fallback, children, }: DhemeProviderProps): React__default.ReactElement;
56
64
 
57
65
  declare function DhemeScript({ defaultMode, nonce, }: DhemeScriptProps): React__default.ReactElement;
58
66
 
@@ -99,9 +107,9 @@ declare function useGenerateTheme(): {
99
107
 
100
108
  declare function useDhemeClient(): DhemeClient;
101
109
 
102
- declare function themeToCSS(theme: GenerateThemeResponse, mode: ThemeMode): string;
103
- declare function themeToCSSBothModes(theme: GenerateThemeResponse): string;
104
- declare function applyThemeCSSVariables(theme: GenerateThemeResponse, mode: ThemeMode): void;
110
+ declare function themeToCSS(theme: GenerateThemeResponse, mode: ThemeMode, tailwindVersion?: 'v3' | 'v4'): string;
111
+ declare function themeToCSSBothModes(theme: GenerateThemeResponse, tailwindVersion?: 'v3' | 'v4'): string;
112
+ declare function applyThemeCSSVariables(theme: GenerateThemeResponse, mode: ThemeMode, tailwindVersion?: 'v3' | 'v4'): void;
105
113
  declare function removeThemeCSSVariables(): void;
106
114
 
107
115
  declare function buildCacheKey(params: GenerateThemeRequest): string;
package/dist/index.d.ts CHANGED
@@ -45,6 +45,14 @@ interface DhemeProviderProps {
45
45
  onThemeChange?: (theme: GenerateThemeResponse) => void;
46
46
  onModeChange?: (mode: ThemeMode) => void;
47
47
  onError?: (error: Error) => void;
48
+ /**
49
+ * Rendered instead of children while the initial theme is loading.
50
+ * Use this to prevent layout flash by showing a skeleton or spinner.
51
+ *
52
+ * Note: when using @dheme/next with DhemeScript, the theme is injected
53
+ * server-side — omit this prop in that case to avoid an unnecessary flash.
54
+ */
55
+ fallback?: React.ReactNode;
48
56
  children: React.ReactNode;
49
57
  }
50
58
  interface DhemeScriptProps {
@@ -52,7 +60,7 @@ interface DhemeScriptProps {
52
60
  nonce?: string;
53
61
  }
54
62
 
55
- declare function DhemeProvider({ apiKey, theme: primaryColor, themeParams, defaultMode, baseUrl, persist, autoApply, onGenerateTheme: customGenerateTheme, onThemeChange, onModeChange, onError, children, }: DhemeProviderProps): React__default.ReactElement;
63
+ declare function DhemeProvider({ apiKey, theme: primaryColor, themeParams, defaultMode, baseUrl, persist, autoApply, onGenerateTheme: customGenerateTheme, onThemeChange, onModeChange, onError, fallback, children, }: DhemeProviderProps): React__default.ReactElement;
56
64
 
57
65
  declare function DhemeScript({ defaultMode, nonce, }: DhemeScriptProps): React__default.ReactElement;
58
66
 
@@ -99,9 +107,9 @@ declare function useGenerateTheme(): {
99
107
 
100
108
  declare function useDhemeClient(): DhemeClient;
101
109
 
102
- declare function themeToCSS(theme: GenerateThemeResponse, mode: ThemeMode): string;
103
- declare function themeToCSSBothModes(theme: GenerateThemeResponse): string;
104
- declare function applyThemeCSSVariables(theme: GenerateThemeResponse, mode: ThemeMode): void;
110
+ declare function themeToCSS(theme: GenerateThemeResponse, mode: ThemeMode, tailwindVersion?: 'v3' | 'v4'): string;
111
+ declare function themeToCSSBothModes(theme: GenerateThemeResponse, tailwindVersion?: 'v3' | 'v4'): string;
112
+ declare function applyThemeCSSVariables(theme: GenerateThemeResponse, mode: ThemeMode, tailwindVersion?: 'v3' | 'v4'): void;
105
113
  declare function removeThemeCSSVariables(): void;
106
114
 
107
115
  declare function buildCacheKey(params: GenerateThemeRequest): string;
package/dist/index.js CHANGED
@@ -110,17 +110,18 @@ var TOKEN_TO_CSS_VAR = {
110
110
  };
111
111
 
112
112
  // src/utils/cssVariables.ts
113
- function formatHSL(color) {
114
- return `hsl(${color.h} ${color.s}% ${color.l}%)`;
113
+ function formatHSL(color, tailwindVersion = "v4") {
114
+ const bare = `${color.h} ${color.s}% ${color.l}%`;
115
+ return tailwindVersion === "v3" ? bare : `hsl(${bare})`;
115
116
  }
116
- function themeToCSS(theme, mode) {
117
+ function themeToCSS(theme, mode, tailwindVersion = "v4") {
117
118
  const colors = theme.colors[mode];
118
119
  if (!colors) return "";
119
120
  const parts = [];
120
121
  for (const key of CSS_TOKEN_KEYS) {
121
122
  const color = colors[key];
122
123
  if (color) {
123
- parts.push(`${TOKEN_TO_CSS_VAR[key]}:${formatHSL(color)}`);
124
+ parts.push(`${TOKEN_TO_CSS_VAR[key]}:${formatHSL(color, tailwindVersion)}`);
124
125
  }
125
126
  }
126
127
  if (theme.radius != null) {
@@ -128,12 +129,12 @@ function themeToCSS(theme, mode) {
128
129
  }
129
130
  return parts.join(";");
130
131
  }
131
- function themeToCSSBothModes(theme) {
132
- const lightCSS = themeToCSS(theme, "light");
133
- const darkCSS = themeToCSS(theme, "dark");
132
+ function themeToCSSBothModes(theme, tailwindVersion = "v4") {
133
+ const lightCSS = themeToCSS(theme, "light", tailwindVersion);
134
+ const darkCSS = themeToCSS(theme, "dark", tailwindVersion);
134
135
  return `:root{${lightCSS}}.dark{${darkCSS}}`;
135
136
  }
136
- function applyThemeCSSVariables(theme, mode) {
137
+ function applyThemeCSSVariables(theme, mode, tailwindVersion = "v4") {
137
138
  if (typeof document === "undefined") return;
138
139
  const colors = theme.colors[mode];
139
140
  if (!colors) return;
@@ -141,7 +142,7 @@ function applyThemeCSSVariables(theme, mode) {
141
142
  for (const key of CSS_TOKEN_KEYS) {
142
143
  const color = colors[key];
143
144
  if (color) {
144
- style.setProperty(TOKEN_TO_CSS_VAR[key], formatHSL(color));
145
+ style.setProperty(TOKEN_TO_CSS_VAR[key], formatHSL(color, tailwindVersion));
145
146
  }
146
147
  }
147
148
  if (theme.radius != null) {
@@ -263,6 +264,7 @@ function DhemeProvider({
263
264
  onThemeChange,
264
265
  onModeChange,
265
266
  onError,
267
+ fallback,
266
268
  children
267
269
  }) {
268
270
  const client = (0, import_react3.useMemo)(() => new import_sdk.DhemeClient({ apiKey, baseUrl }), [apiKey, baseUrl]);
@@ -296,7 +298,7 @@ function DhemeProvider({
296
298
  }, []);
297
299
  (0, import_react3.useEffect)(() => {
298
300
  if (theme && autoApply) {
299
- applyThemeCSSVariables(theme, mode);
301
+ applyThemeCSSVariables(theme, mode, themeParams?.tailwindVersion ?? "v4");
300
302
  }
301
303
  if (typeof document !== "undefined") {
302
304
  if (mode === "dark") {
@@ -334,7 +336,7 @@ function DhemeProvider({
334
336
  setTheme(data);
335
337
  setIsReady(true);
336
338
  if (autoApplyRef.current) {
337
- applyThemeCSSVariables(data, modeRef.current);
339
+ applyThemeCSSVariables(data, modeRef.current, params.tailwindVersion ?? "v4");
338
340
  }
339
341
  if (persistRef.current) {
340
342
  const key = buildCacheKey(params);
@@ -373,7 +375,7 @@ function DhemeProvider({
373
375
  if (cached) {
374
376
  setTheme(cached);
375
377
  setIsReady(true);
376
- if (autoApply) applyThemeCSSVariables(cached, mode);
378
+ if (autoApply) applyThemeCSSVariables(cached, mode, params.tailwindVersion ?? "v4");
377
379
  const controller = new AbortController();
378
380
  abortRef.current = controller;
379
381
  fetchTheme(params).then((data) => {
@@ -382,7 +384,8 @@ function DhemeProvider({
382
384
  const freshLight = JSON.stringify(data.colors.light);
383
385
  if (cachedLight !== freshLight) {
384
386
  setTheme(data);
385
- if (autoApply) applyThemeCSSVariables(data, modeRef.current);
387
+ if (autoApply)
388
+ applyThemeCSSVariables(data, modeRef.current, params.tailwindVersion ?? "v4");
386
389
  saveThemeToCache(cacheKey, data);
387
390
  onThemeChangeRef.current?.(data);
388
391
  }
@@ -403,7 +406,11 @@ function DhemeProvider({
403
406
  return import_react3.default.createElement(
404
407
  ThemeDataContext.Provider,
405
408
  { value: themeDataValue },
406
- import_react3.default.createElement(ThemeActionsContext.Provider, { value: themeActionsValue }, children)
409
+ import_react3.default.createElement(
410
+ ThemeActionsContext.Provider,
411
+ { value: themeActionsValue },
412
+ !isReady && fallback != null ? fallback : children
413
+ )
407
414
  );
408
415
  }
409
416
 
package/dist/index.mjs CHANGED
@@ -60,17 +60,18 @@ var TOKEN_TO_CSS_VAR = {
60
60
  };
61
61
 
62
62
  // src/utils/cssVariables.ts
63
- function formatHSL(color) {
64
- return `hsl(${color.h} ${color.s}% ${color.l}%)`;
63
+ function formatHSL(color, tailwindVersion = "v4") {
64
+ const bare = `${color.h} ${color.s}% ${color.l}%`;
65
+ return tailwindVersion === "v3" ? bare : `hsl(${bare})`;
65
66
  }
66
- function themeToCSS(theme, mode) {
67
+ function themeToCSS(theme, mode, tailwindVersion = "v4") {
67
68
  const colors = theme.colors[mode];
68
69
  if (!colors) return "";
69
70
  const parts = [];
70
71
  for (const key of CSS_TOKEN_KEYS) {
71
72
  const color = colors[key];
72
73
  if (color) {
73
- parts.push(`${TOKEN_TO_CSS_VAR[key]}:${formatHSL(color)}`);
74
+ parts.push(`${TOKEN_TO_CSS_VAR[key]}:${formatHSL(color, tailwindVersion)}`);
74
75
  }
75
76
  }
76
77
  if (theme.radius != null) {
@@ -78,12 +79,12 @@ function themeToCSS(theme, mode) {
78
79
  }
79
80
  return parts.join(";");
80
81
  }
81
- function themeToCSSBothModes(theme) {
82
- const lightCSS = themeToCSS(theme, "light");
83
- const darkCSS = themeToCSS(theme, "dark");
82
+ function themeToCSSBothModes(theme, tailwindVersion = "v4") {
83
+ const lightCSS = themeToCSS(theme, "light", tailwindVersion);
84
+ const darkCSS = themeToCSS(theme, "dark", tailwindVersion);
84
85
  return `:root{${lightCSS}}.dark{${darkCSS}}`;
85
86
  }
86
- function applyThemeCSSVariables(theme, mode) {
87
+ function applyThemeCSSVariables(theme, mode, tailwindVersion = "v4") {
87
88
  if (typeof document === "undefined") return;
88
89
  const colors = theme.colors[mode];
89
90
  if (!colors) return;
@@ -91,7 +92,7 @@ function applyThemeCSSVariables(theme, mode) {
91
92
  for (const key of CSS_TOKEN_KEYS) {
92
93
  const color = colors[key];
93
94
  if (color) {
94
- style.setProperty(TOKEN_TO_CSS_VAR[key], formatHSL(color));
95
+ style.setProperty(TOKEN_TO_CSS_VAR[key], formatHSL(color, tailwindVersion));
95
96
  }
96
97
  }
97
98
  if (theme.radius != null) {
@@ -213,6 +214,7 @@ function DhemeProvider({
213
214
  onThemeChange,
214
215
  onModeChange,
215
216
  onError,
217
+ fallback,
216
218
  children
217
219
  }) {
218
220
  const client = useMemo(() => new DhemeClient({ apiKey, baseUrl }), [apiKey, baseUrl]);
@@ -246,7 +248,7 @@ function DhemeProvider({
246
248
  }, []);
247
249
  useEffect(() => {
248
250
  if (theme && autoApply) {
249
- applyThemeCSSVariables(theme, mode);
251
+ applyThemeCSSVariables(theme, mode, themeParams?.tailwindVersion ?? "v4");
250
252
  }
251
253
  if (typeof document !== "undefined") {
252
254
  if (mode === "dark") {
@@ -284,7 +286,7 @@ function DhemeProvider({
284
286
  setTheme(data);
285
287
  setIsReady(true);
286
288
  if (autoApplyRef.current) {
287
- applyThemeCSSVariables(data, modeRef.current);
289
+ applyThemeCSSVariables(data, modeRef.current, params.tailwindVersion ?? "v4");
288
290
  }
289
291
  if (persistRef.current) {
290
292
  const key = buildCacheKey(params);
@@ -323,7 +325,7 @@ function DhemeProvider({
323
325
  if (cached) {
324
326
  setTheme(cached);
325
327
  setIsReady(true);
326
- if (autoApply) applyThemeCSSVariables(cached, mode);
328
+ if (autoApply) applyThemeCSSVariables(cached, mode, params.tailwindVersion ?? "v4");
327
329
  const controller = new AbortController();
328
330
  abortRef.current = controller;
329
331
  fetchTheme(params).then((data) => {
@@ -332,7 +334,8 @@ function DhemeProvider({
332
334
  const freshLight = JSON.stringify(data.colors.light);
333
335
  if (cachedLight !== freshLight) {
334
336
  setTheme(data);
335
- if (autoApply) applyThemeCSSVariables(data, modeRef.current);
337
+ if (autoApply)
338
+ applyThemeCSSVariables(data, modeRef.current, params.tailwindVersion ?? "v4");
336
339
  saveThemeToCache(cacheKey, data);
337
340
  onThemeChangeRef.current?.(data);
338
341
  }
@@ -353,7 +356,11 @@ function DhemeProvider({
353
356
  return React.createElement(
354
357
  ThemeDataContext.Provider,
355
358
  { value: themeDataValue },
356
- React.createElement(ThemeActionsContext.Provider, { value: themeActionsValue }, children)
359
+ React.createElement(
360
+ ThemeActionsContext.Provider,
361
+ { value: themeActionsValue },
362
+ !isReady && fallback != null ? fallback : children
363
+ )
357
364
  );
358
365
  }
359
366
 
package/dist/utils.d.mts CHANGED
@@ -2,9 +2,9 @@ import { GenerateThemeResponse, GenerateThemeRequest } from '@dheme/sdk';
2
2
 
3
3
  type ThemeMode = 'light' | 'dark';
4
4
 
5
- declare function themeToCSS(theme: GenerateThemeResponse, mode: ThemeMode): string;
6
- declare function themeToCSSBothModes(theme: GenerateThemeResponse): string;
7
- declare function applyThemeCSSVariables(theme: GenerateThemeResponse, mode: ThemeMode): void;
5
+ declare function themeToCSS(theme: GenerateThemeResponse, mode: ThemeMode, tailwindVersion?: 'v3' | 'v4'): string;
6
+ declare function themeToCSSBothModes(theme: GenerateThemeResponse, tailwindVersion?: 'v3' | 'v4'): string;
7
+ declare function applyThemeCSSVariables(theme: GenerateThemeResponse, mode: ThemeMode, tailwindVersion?: 'v3' | 'v4'): void;
8
8
  declare function removeThemeCSSVariables(): void;
9
9
 
10
10
  declare function buildCacheKey(params: GenerateThemeRequest): string;
package/dist/utils.d.ts CHANGED
@@ -2,9 +2,9 @@ import { GenerateThemeResponse, GenerateThemeRequest } from '@dheme/sdk';
2
2
 
3
3
  type ThemeMode = 'light' | 'dark';
4
4
 
5
- declare function themeToCSS(theme: GenerateThemeResponse, mode: ThemeMode): string;
6
- declare function themeToCSSBothModes(theme: GenerateThemeResponse): string;
7
- declare function applyThemeCSSVariables(theme: GenerateThemeResponse, mode: ThemeMode): void;
5
+ declare function themeToCSS(theme: GenerateThemeResponse, mode: ThemeMode, tailwindVersion?: 'v3' | 'v4'): string;
6
+ declare function themeToCSSBothModes(theme: GenerateThemeResponse, tailwindVersion?: 'v3' | 'v4'): string;
7
+ declare function applyThemeCSSVariables(theme: GenerateThemeResponse, mode: ThemeMode, tailwindVersion?: 'v3' | 'v4'): void;
8
8
  declare function removeThemeCSSVariables(): void;
9
9
 
10
10
  declare function buildCacheKey(params: GenerateThemeRequest): string;
package/dist/utils.js CHANGED
@@ -75,17 +75,18 @@ var TOKEN_TO_CSS_VAR = {
75
75
  };
76
76
 
77
77
  // src/utils/cssVariables.ts
78
- function formatHSL(color) {
79
- return `hsl(${color.h} ${color.s}% ${color.l}%)`;
78
+ function formatHSL(color, tailwindVersion = "v4") {
79
+ const bare = `${color.h} ${color.s}% ${color.l}%`;
80
+ return tailwindVersion === "v3" ? bare : `hsl(${bare})`;
80
81
  }
81
- function themeToCSS(theme, mode) {
82
+ function themeToCSS(theme, mode, tailwindVersion = "v4") {
82
83
  const colors = theme.colors[mode];
83
84
  if (!colors) return "";
84
85
  const parts = [];
85
86
  for (const key of CSS_TOKEN_KEYS) {
86
87
  const color = colors[key];
87
88
  if (color) {
88
- parts.push(`${TOKEN_TO_CSS_VAR[key]}:${formatHSL(color)}`);
89
+ parts.push(`${TOKEN_TO_CSS_VAR[key]}:${formatHSL(color, tailwindVersion)}`);
89
90
  }
90
91
  }
91
92
  if (theme.radius != null) {
@@ -93,12 +94,12 @@ function themeToCSS(theme, mode) {
93
94
  }
94
95
  return parts.join(";");
95
96
  }
96
- function themeToCSSBothModes(theme) {
97
- const lightCSS = themeToCSS(theme, "light");
98
- const darkCSS = themeToCSS(theme, "dark");
97
+ function themeToCSSBothModes(theme, tailwindVersion = "v4") {
98
+ const lightCSS = themeToCSS(theme, "light", tailwindVersion);
99
+ const darkCSS = themeToCSS(theme, "dark", tailwindVersion);
99
100
  return `:root{${lightCSS}}.dark{${darkCSS}}`;
100
101
  }
101
- function applyThemeCSSVariables(theme, mode) {
102
+ function applyThemeCSSVariables(theme, mode, tailwindVersion = "v4") {
102
103
  if (typeof document === "undefined") return;
103
104
  const colors = theme.colors[mode];
104
105
  if (!colors) return;
@@ -106,7 +107,7 @@ function applyThemeCSSVariables(theme, mode) {
106
107
  for (const key of CSS_TOKEN_KEYS) {
107
108
  const color = colors[key];
108
109
  if (color) {
109
- style.setProperty(TOKEN_TO_CSS_VAR[key], formatHSL(color));
110
+ style.setProperty(TOKEN_TO_CSS_VAR[key], formatHSL(color, tailwindVersion));
110
111
  }
111
112
  }
112
113
  if (theme.radius != null) {
package/dist/utils.mjs CHANGED
@@ -43,17 +43,18 @@ var TOKEN_TO_CSS_VAR = {
43
43
  };
44
44
 
45
45
  // src/utils/cssVariables.ts
46
- function formatHSL(color) {
47
- return `hsl(${color.h} ${color.s}% ${color.l}%)`;
46
+ function formatHSL(color, tailwindVersion = "v4") {
47
+ const bare = `${color.h} ${color.s}% ${color.l}%`;
48
+ return tailwindVersion === "v3" ? bare : `hsl(${bare})`;
48
49
  }
49
- function themeToCSS(theme, mode) {
50
+ function themeToCSS(theme, mode, tailwindVersion = "v4") {
50
51
  const colors = theme.colors[mode];
51
52
  if (!colors) return "";
52
53
  const parts = [];
53
54
  for (const key of CSS_TOKEN_KEYS) {
54
55
  const color = colors[key];
55
56
  if (color) {
56
- parts.push(`${TOKEN_TO_CSS_VAR[key]}:${formatHSL(color)}`);
57
+ parts.push(`${TOKEN_TO_CSS_VAR[key]}:${formatHSL(color, tailwindVersion)}`);
57
58
  }
58
59
  }
59
60
  if (theme.radius != null) {
@@ -61,12 +62,12 @@ function themeToCSS(theme, mode) {
61
62
  }
62
63
  return parts.join(";");
63
64
  }
64
- function themeToCSSBothModes(theme) {
65
- const lightCSS = themeToCSS(theme, "light");
66
- const darkCSS = themeToCSS(theme, "dark");
65
+ function themeToCSSBothModes(theme, tailwindVersion = "v4") {
66
+ const lightCSS = themeToCSS(theme, "light", tailwindVersion);
67
+ const darkCSS = themeToCSS(theme, "dark", tailwindVersion);
67
68
  return `:root{${lightCSS}}.dark{${darkCSS}}`;
68
69
  }
69
- function applyThemeCSSVariables(theme, mode) {
70
+ function applyThemeCSSVariables(theme, mode, tailwindVersion = "v4") {
70
71
  if (typeof document === "undefined") return;
71
72
  const colors = theme.colors[mode];
72
73
  if (!colors) return;
@@ -74,7 +75,7 @@ function applyThemeCSSVariables(theme, mode) {
74
75
  for (const key of CSS_TOKEN_KEYS) {
75
76
  const color = colors[key];
76
77
  if (color) {
77
- style.setProperty(TOKEN_TO_CSS_VAR[key], formatHSL(color));
78
+ style.setProperty(TOKEN_TO_CSS_VAR[key], formatHSL(color, tailwindVersion));
78
79
  }
79
80
  }
80
81
  if (theme.radius != null) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dheme/react",
3
- "version": "2.10.0",
3
+ "version": "2.12.0",
4
4
  "description": "React bindings for Dheme SDK with zero-FOUC theme application",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",