@space-man/react-theme-animation 2.0.0 → 2.3.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 (60) hide show
  1. package/README.md +90 -464
  2. package/dist/core/index.cjs +74 -0
  3. package/dist/core/index.cjs.map +1 -0
  4. package/dist/{esm/types/index.d.ts → core/index.d.cts} +30 -12
  5. package/dist/{cjs/types → core}/index.d.ts +30 -12
  6. package/dist/core/index.js +66 -0
  7. package/dist/core/index.js.map +1 -0
  8. package/dist/index.cjs +1756 -0
  9. package/dist/index.cjs.map +1 -0
  10. package/dist/index.d.cts +4 -0
  11. package/dist/index.d.ts +4 -0
  12. package/dist/index.js +1706 -0
  13. package/dist/index.js.map +1 -0
  14. package/dist/react/index.cjs +1742 -0
  15. package/dist/react/index.cjs.map +1 -0
  16. package/dist/react/index.d.cts +224 -0
  17. package/dist/react/index.d.ts +224 -0
  18. package/dist/react/index.js +1697 -0
  19. package/dist/react/index.js.map +1 -0
  20. package/dist/tanstack/index.cjs +34 -0
  21. package/dist/tanstack/index.cjs.map +1 -0
  22. package/dist/tanstack/index.d.cts +20 -0
  23. package/dist/tanstack/index.d.ts +20 -0
  24. package/dist/tanstack/index.js +27 -0
  25. package/dist/tanstack/index.js.map +1 -0
  26. package/package.json +66 -37
  27. package/dist/cjs/components/SpacemanThemeProvider.d.ts +0 -57
  28. package/dist/cjs/components/SpacemanThemeProvider.js +0 -113
  29. package/dist/cjs/components/ThemeSelector.d.ts +0 -3
  30. package/dist/cjs/components/ThemeSelector.js +0 -39
  31. package/dist/cjs/components/ThemeSwitcher.d.ts +0 -3
  32. package/dist/cjs/components/ThemeSwitcher.js +0 -81
  33. package/dist/cjs/components/ViteThemeProvider.d.ts +0 -38
  34. package/dist/cjs/components/ViteThemeProvider.js +0 -117
  35. package/dist/cjs/components/ui/select.d.ts +0 -15
  36. package/dist/cjs/components/ui/select.js +0 -83
  37. package/dist/cjs/hooks/use-theme-animation.d.ts +0 -2
  38. package/dist/cjs/hooks/use-theme-animation.js +0 -234
  39. package/dist/cjs/index.d.ts +0 -8
  40. package/dist/cjs/index.js +0 -23
  41. package/dist/cjs/types/index.js +0 -9
  42. package/dist/cjs/utils/animations.d.ts +0 -21
  43. package/dist/cjs/utils/animations.js +0 -189
  44. package/dist/esm/components/SpacemanThemeProvider.d.ts +0 -57
  45. package/dist/esm/components/SpacemanThemeProvider.js +0 -108
  46. package/dist/esm/components/ThemeSelector.d.ts +0 -3
  47. package/dist/esm/components/ThemeSelector.js +0 -35
  48. package/dist/esm/components/ThemeSwitcher.d.ts +0 -3
  49. package/dist/esm/components/ThemeSwitcher.js +0 -77
  50. package/dist/esm/components/ViteThemeProvider.d.ts +0 -38
  51. package/dist/esm/components/ViteThemeProvider.js +0 -112
  52. package/dist/esm/components/ui/select.d.ts +0 -15
  53. package/dist/esm/components/ui/select.js +0 -39
  54. package/dist/esm/hooks/use-theme-animation.d.ts +0 -2
  55. package/dist/esm/hooks/use-theme-animation.js +0 -230
  56. package/dist/esm/index.d.ts +0 -8
  57. package/dist/esm/index.js +0 -7
  58. package/dist/esm/types/index.js +0 -6
  59. package/dist/esm/utils/animations.d.ts +0 -21
  60. package/dist/esm/utils/animations.js +0 -177
@@ -0,0 +1,1742 @@
1
+ 'use client';
2
+ 'use strict';
3
+
4
+ var React4 = require('react');
5
+ var reactDom = require('react-dom');
6
+ var react = require('motion/react');
7
+ var clsx = require('clsx');
8
+ var jsxRuntime = require('react/jsx-runtime');
9
+ var SelectPrimitive = require('@radix-ui/react-select');
10
+
11
+ function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
12
+
13
+ function _interopNamespace(e) {
14
+ if (e && e.__esModule) return e;
15
+ var n = Object.create(null);
16
+ if (e) {
17
+ Object.keys(e).forEach(function (k) {
18
+ if (k !== 'default') {
19
+ var d = Object.getOwnPropertyDescriptor(e, k);
20
+ Object.defineProperty(n, k, d.get ? d : {
21
+ enumerable: true,
22
+ get: function () { return e[k]; }
23
+ });
24
+ }
25
+ });
26
+ }
27
+ n.default = e;
28
+ return Object.freeze(n);
29
+ }
30
+
31
+ var React4__default = /*#__PURE__*/_interopDefault(React4);
32
+ var SelectPrimitive__namespace = /*#__PURE__*/_interopNamespace(SelectPrimitive);
33
+
34
+ // src/react/hooks/use-theme-animation.ts
35
+
36
+ // src/core/types/index.ts
37
+ var ThemeAnimationType = /* @__PURE__ */ ((ThemeAnimationType2) => {
38
+ ThemeAnimationType2["CIRCLE"] = "circle";
39
+ ThemeAnimationType2["BLUR_CIRCLE"] = "blur-circle";
40
+ ThemeAnimationType2["SLIDE"] = "slide";
41
+ return ThemeAnimationType2;
42
+ })(ThemeAnimationType || {});
43
+
44
+ // src/core/utils/animations.ts
45
+ var isBrowser = typeof window !== "undefined";
46
+ var injectBaseStyles = () => {
47
+ if (isBrowser) {
48
+ const styleId = "spaceman-theme-base-style";
49
+ if (!document.getElementById(styleId)) {
50
+ const style = document.createElement("style");
51
+ style.id = styleId;
52
+ const isHighResolution = window.innerWidth >= 3e3 || window.innerHeight >= 2e3;
53
+ style.textContent = `
54
+ ::view-transition-old(root),
55
+ ::view-transition-new(root) {
56
+ animation: none;
57
+ mix-blend-mode: normal;
58
+ ${isHighResolution ? "transform: translateZ(0);" : ""}
59
+ }
60
+
61
+ ${isHighResolution ? `
62
+ ::view-transition-group(root),
63
+ ::view-transition-image-pair(root),
64
+ ::view-transition-old(root),
65
+ ::view-transition-new(root) {
66
+ backface-visibility: hidden;
67
+ perspective: 1000px;
68
+ transform: translate3d(0, 0, 0);
69
+ }
70
+ ` : ""}
71
+ `;
72
+ document.head.appendChild(style);
73
+ }
74
+ }
75
+ };
76
+ var createBlurCircleMask = (blur) => {
77
+ const isHighResolution = isBrowser && (window.innerWidth >= 3e3 || window.innerHeight >= 2e3);
78
+ const blurFilter = `<filter id="blur"><feGaussianBlur stdDeviation="${blur}" /></filter>`;
79
+ const circleRadius = isHighResolution ? 20 : 25;
80
+ return `url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="-50 -50 100 100"><defs>${blurFilter}</defs><circle cx="0" cy="0" r="${circleRadius}" fill="white" filter="url(%23blur)"/></svg>')`;
81
+ };
82
+ var getSystemTheme = () => {
83
+ if (!isBrowser) return "light";
84
+ return window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
85
+ };
86
+ var resolveTheme = (theme) => {
87
+ if (theme === "system") {
88
+ return getSystemTheme();
89
+ }
90
+ return theme === "dark" ? "dark" : "light";
91
+ };
92
+ var resolveThemeForServer = (theme) => {
93
+ if (theme === "system") {
94
+ return "system";
95
+ }
96
+ return theme === "dark" ? "dark" : "light";
97
+ };
98
+ var supportsViewTransitions = () => {
99
+ return isBrowser && "startViewTransition" in document;
100
+ };
101
+ var prefersReducedMotion = () => {
102
+ return isBrowser && window.matchMedia("(prefers-reduced-motion: reduce)").matches;
103
+ };
104
+ var createCircleAnimation = (config) => {
105
+ const { x, y, duration, easing } = config;
106
+ const topLeft = Math.hypot(x, y);
107
+ const topRight = Math.hypot(window.innerWidth - x, y);
108
+ const bottomLeft = Math.hypot(x, window.innerHeight - y);
109
+ const bottomRight = Math.hypot(window.innerWidth - x, window.innerHeight - y);
110
+ const maxRadius = Math.max(topLeft, topRight, bottomLeft, bottomRight);
111
+ document.documentElement.animate(
112
+ {
113
+ clipPath: [
114
+ `circle(0px at ${x}px ${y}px)`,
115
+ `circle(${maxRadius}px at ${x}px ${y}px)`
116
+ ]
117
+ },
118
+ {
119
+ duration,
120
+ easing,
121
+ pseudoElement: "::view-transition-new(root)"
122
+ }
123
+ );
124
+ };
125
+ var createSlideAnimation = (config) => {
126
+ const { a = -100, b = 0, x = 0, y = 0, duration, styleId } = config;
127
+ const styleElement = document.createElement("style");
128
+ styleElement.id = styleId;
129
+ styleElement.textContent = `
130
+ ::view-transition-old(root) {
131
+ animation-delay: ${duration}ms;
132
+ }
133
+
134
+ ::view-transition-new(root) {
135
+ animation: move-in ${duration}ms;
136
+ animation-timing-function: cubic-bezier(0.66, 0, 0.34, 1);
137
+ }
138
+
139
+ @keyframes move-in {
140
+ from {
141
+ translate: ${a}% ${b}%;
142
+ }
143
+ to {
144
+ translate: ${x}% ${y}%;
145
+ }
146
+ }
147
+ `;
148
+ document.head.appendChild(styleElement);
149
+ setTimeout(() => {
150
+ const styleElement2 = document.getElementById(styleId);
151
+ if (styleElement2) {
152
+ styleElement2.remove();
153
+ }
154
+ }, duration);
155
+ };
156
+ var createBlurCircleAnimation = (config) => {
157
+ const { x, y, duration, easing, blurAmount, styleId } = config;
158
+ const existingStyle = document.getElementById(styleId);
159
+ if (existingStyle) {
160
+ existingStyle.remove();
161
+ }
162
+ const viewportSize = Math.max(window.innerWidth, window.innerHeight) + 200;
163
+ const isHighResolution = window.innerWidth >= 3e3 || window.innerHeight >= 2e3;
164
+ const scaleFactor = isHighResolution ? 2.5 : 4;
165
+ const optimalMaskSize = isHighResolution ? Math.min(viewportSize * scaleFactor, 5e3) : viewportSize * scaleFactor;
166
+ const topLeft = Math.hypot(x, y);
167
+ const topRight = Math.hypot(window.innerWidth - x, y);
168
+ const bottomLeft = Math.hypot(x, window.innerHeight - y);
169
+ const bottomRight = Math.hypot(window.innerWidth - x, window.innerHeight - y);
170
+ const maxRadius = Math.max(topLeft, topRight, bottomLeft, bottomRight);
171
+ const styleElement = document.createElement("style");
172
+ styleElement.id = styleId;
173
+ const blurFactor = isHighResolution ? 1.5 : 1.2;
174
+ const finalMaskSize = Math.max(optimalMaskSize, maxRadius * 2.5);
175
+ styleElement.textContent = `
176
+ ::view-transition-group(root) {
177
+ animation-duration: ${duration}ms;
178
+ animation-timing-function: ${isHighResolution ? "cubic-bezier(0.2, 0, 0.2, 1)" : "linear(0 0%, 0.2342 12.49%, 0.4374 24.99%,0.6093 37.49%, 0.6835 43.74%,0.7499 49.99%, 0.8086 56.25%,0.8593 62.5%, 0.9023 68.75%, 0.9375 75%,0.9648 81.25%, 0.9844 87.5%,0.9961 93.75%, 1 100%)"};
179
+ will-change: transform;
180
+ }
181
+
182
+ ::view-transition-new(root) {
183
+ mask: ${createBlurCircleMask(blurAmount * blurFactor)} 0 0 / 100% 100% no-repeat;
184
+ mask-position: ${x}px ${y}px;
185
+ animation: spaceman-mask-scale ${duration}ms ${easing};
186
+ transform-origin: ${x}px ${y}px;
187
+ will-change: mask-size, mask-position;
188
+ }
189
+
190
+ ::view-transition-old(root),
191
+ .dark::view-transition-old(root) {
192
+ animation: spaceman-mask-scale ${duration}ms ${easing};
193
+ transform-origin: ${x}px ${y}px;
194
+ z-index: -1;
195
+ will-change: mask-size, mask-position;
196
+ }
197
+
198
+ @keyframes spaceman-mask-scale {
199
+ 0% {
200
+ mask-size: 0px;
201
+ mask-position: ${x}px ${y}px;
202
+ }
203
+ 100% {
204
+ mask-size: ${finalMaskSize}px;
205
+ mask-position: ${x - finalMaskSize / 2}px ${y - finalMaskSize / 2}px;
206
+ }
207
+ }
208
+ `;
209
+ document.head.appendChild(styleElement);
210
+ setTimeout(() => {
211
+ const styleElement2 = document.getElementById(styleId);
212
+ if (styleElement2) {
213
+ styleElement2.remove();
214
+ }
215
+ }, duration);
216
+ };
217
+
218
+ // src/react/hooks/use-theme-animation.ts
219
+ var isBrowser2 = typeof window !== "undefined";
220
+ var useThemeAnimation = (props = {}) => {
221
+ const {
222
+ duration: propsDuration = 750,
223
+ easing = "ease-in-out",
224
+ animationType = "circle" /* CIRCLE */,
225
+ blurAmount = 2,
226
+ styleId = "spaceman-theme-style",
227
+ themes = ["light", "dark", "system"],
228
+ colorThemes = ["default"],
229
+ defaultTheme = "system",
230
+ defaultColorTheme = "default",
231
+ globalClassName = "dark",
232
+ colorThemePrefix = "theme-",
233
+ attribute = "class",
234
+ value,
235
+ enableColorScheme = true,
236
+ storageKey = "theme",
237
+ colorStorageKey = "color-theme",
238
+ theme: externalTheme,
239
+ colorTheme: externalColorTheme,
240
+ onThemeChange,
241
+ onColorThemeChange,
242
+ initialTheme,
243
+ initialColorTheme,
244
+ systemThemeMode = "js",
245
+ // Slide animation options
246
+ slideDirection = "left",
247
+ slideFromX,
248
+ slideFromY,
249
+ slideToX = 0,
250
+ slideToY = 0
251
+ } = props;
252
+ const isHighResolution = isBrowser2 && (window.innerWidth >= 3e3 || window.innerHeight >= 2e3);
253
+ const duration = isHighResolution ? Math.max(propsDuration * 0.8, 500) : propsDuration;
254
+ const [mounted, setMounted] = React4.useState(false);
255
+ React4.useEffect(() => {
256
+ injectBaseStyles();
257
+ setMounted(true);
258
+ }, []);
259
+ const [internalTheme, setInternalTheme] = React4.useState(() => {
260
+ if (initialTheme !== void 0) return initialTheme;
261
+ if (!isBrowser2) return defaultTheme;
262
+ const saved = localStorage.getItem(storageKey);
263
+ return saved && themes.indexOf(saved) !== -1 ? saved : defaultTheme;
264
+ });
265
+ const [internalColorTheme, setInternalColorTheme] = React4.useState(() => {
266
+ if (initialColorTheme !== void 0) return initialColorTheme;
267
+ if (!isBrowser2) return defaultColorTheme;
268
+ const saved = localStorage.getItem(colorStorageKey);
269
+ return saved && colorThemes.indexOf(saved) !== -1 ? saved : defaultColorTheme;
270
+ });
271
+ const currentTheme = externalTheme ?? internalTheme;
272
+ const currentColorTheme = externalColorTheme ?? internalColorTheme;
273
+ const [, setSystemTheme] = React4.useState(() => getSystemTheme());
274
+ const systemTheme = getSystemTheme();
275
+ const resolvedTheme = resolveTheme(currentTheme);
276
+ React4.useEffect(() => {
277
+ if (!isBrowser2) return;
278
+ const mediaQuery = window.matchMedia("(prefers-color-scheme: dark)");
279
+ const handleChange = () => setSystemTheme(getSystemTheme());
280
+ mediaQuery.addEventListener("change", handleChange);
281
+ return () => mediaQuery.removeEventListener("change", handleChange);
282
+ }, []);
283
+ React4.useEffect(() => {
284
+ if (!isBrowser2 || !mounted) return;
285
+ const element = document.documentElement;
286
+ const lightValue = value?.light;
287
+ const darkValue = value?.dark ?? globalClassName;
288
+ const systemValue = value?.system ?? "system";
289
+ if (attribute === "data-theme") {
290
+ if (systemThemeMode === "css" && currentTheme === "system") {
291
+ element.setAttribute("data-theme", systemValue);
292
+ } else {
293
+ element.setAttribute(
294
+ "data-theme",
295
+ resolvedTheme === "dark" ? darkValue : lightValue ?? "light"
296
+ );
297
+ }
298
+ } else {
299
+ if (lightValue) {
300
+ element.classList.remove(lightValue);
301
+ }
302
+ element.classList.remove(darkValue, systemValue, "auto");
303
+ if (systemThemeMode === "css" && currentTheme === "system") {
304
+ element.classList.add(systemValue);
305
+ } else if (resolvedTheme === "dark") {
306
+ element.classList.add(darkValue);
307
+ } else if (lightValue) {
308
+ element.classList.add(lightValue);
309
+ } else {
310
+ element.classList.remove(darkValue);
311
+ }
312
+ }
313
+ if (enableColorScheme) {
314
+ element.style.colorScheme = systemThemeMode === "css" && currentTheme === "system" ? "" : resolvedTheme;
315
+ } else {
316
+ element.style.removeProperty("color-scheme");
317
+ }
318
+ colorThemes.forEach((theme) => {
319
+ element.classList.remove(`${colorThemePrefix}${theme}`);
320
+ });
321
+ element.classList.add(`${colorThemePrefix}${currentColorTheme}`);
322
+ }, [
323
+ resolvedTheme,
324
+ currentTheme,
325
+ currentColorTheme,
326
+ globalClassName,
327
+ colorThemePrefix,
328
+ colorThemes,
329
+ attribute,
330
+ value,
331
+ enableColorScheme,
332
+ mounted,
333
+ systemThemeMode
334
+ ]);
335
+ const ref = React4.useRef(null);
336
+ const setTheme = React4.useCallback(
337
+ (newTheme) => {
338
+ if (isBrowser2) {
339
+ localStorage.setItem(storageKey, newTheme);
340
+ }
341
+ if (externalTheme === void 0) {
342
+ setInternalTheme(newTheme);
343
+ }
344
+ if (onThemeChange) {
345
+ onThemeChange(newTheme);
346
+ }
347
+ },
348
+ [onThemeChange, externalTheme, storageKey]
349
+ );
350
+ const setColorTheme = React4.useCallback(
351
+ (newColorTheme) => {
352
+ if (isBrowser2) {
353
+ localStorage.setItem(colorStorageKey, newColorTheme);
354
+ }
355
+ if (externalColorTheme === void 0) {
356
+ setInternalColorTheme(newColorTheme);
357
+ }
358
+ if (onColorThemeChange) {
359
+ onColorThemeChange(newColorTheme);
360
+ }
361
+ },
362
+ [onColorThemeChange, externalColorTheme, colorStorageKey]
363
+ );
364
+ const switchTheme = React4.useCallback(
365
+ async (newTheme, animationOff = false) => {
366
+ if (!ref.current || !supportsViewTransitions() || prefersReducedMotion() || animationOff) {
367
+ setTheme(newTheme);
368
+ return;
369
+ }
370
+ const getSlideFromCoords = (direction) => {
371
+ switch (direction) {
372
+ case "left":
373
+ return { a: -100, b: 0 };
374
+ case "right":
375
+ return { a: 100, b: 0 };
376
+ case "top":
377
+ return { a: 0, b: -100 };
378
+ case "bottom":
379
+ return { a: 0, b: 100 };
380
+ case "top-left":
381
+ return { a: -100, b: -100 };
382
+ case "top-right":
383
+ return { a: 100, b: -100 };
384
+ case "bottom-left":
385
+ return { a: -100, b: 100 };
386
+ case "bottom-right":
387
+ return { a: 100, b: 100 };
388
+ default:
389
+ return { a: -100, b: 0 };
390
+ }
391
+ };
392
+ let animationConfig;
393
+ if (animationType === "slide" /* SLIDE */) {
394
+ const fromCoords = slideFromX !== void 0 && slideFromY !== void 0 ? { a: slideFromX, b: slideFromY } : getSlideFromCoords(slideDirection);
395
+ animationConfig = {
396
+ a: fromCoords.a,
397
+ b: fromCoords.b,
398
+ x: slideToX,
399
+ y: slideToY,
400
+ duration,
401
+ easing,
402
+ animationType,
403
+ blurAmount,
404
+ styleId
405
+ };
406
+ } else {
407
+ const { top, left, width, height } = ref.current.getBoundingClientRect();
408
+ const x = left + width / 2;
409
+ const y = top + height / 2;
410
+ animationConfig = {
411
+ x,
412
+ y,
413
+ duration,
414
+ easing,
415
+ animationType,
416
+ blurAmount,
417
+ styleId
418
+ };
419
+ }
420
+ if (animationType === "blur-circle" /* BLUR_CIRCLE */) {
421
+ createBlurCircleAnimation(animationConfig);
422
+ }
423
+ if (animationType === "slide" /* SLIDE */) {
424
+ createSlideAnimation(animationConfig);
425
+ }
426
+ await document.startViewTransition(() => {
427
+ reactDom.flushSync(() => {
428
+ setTheme(newTheme);
429
+ });
430
+ }).ready;
431
+ if (animationType === "circle" /* CIRCLE */) {
432
+ createCircleAnimation(animationConfig);
433
+ }
434
+ },
435
+ [
436
+ setTheme,
437
+ duration,
438
+ easing,
439
+ animationType,
440
+ blurAmount,
441
+ styleId,
442
+ slideDirection,
443
+ slideFromX,
444
+ slideFromY,
445
+ slideToX,
446
+ slideToY
447
+ ]
448
+ );
449
+ const switchColorTheme = React4.useCallback(
450
+ (newColorTheme) => {
451
+ if (colorThemes.indexOf(newColorTheme) === -1) {
452
+ console.warn(
453
+ `Color theme "${newColorTheme}" not found in available themes`
454
+ );
455
+ return;
456
+ }
457
+ setColorTheme(newColorTheme);
458
+ },
459
+ [colorThemes, setColorTheme]
460
+ );
461
+ const toggleTheme = React4.useCallback(
462
+ async (animationOff = false) => {
463
+ const newTheme = resolvedTheme === "dark" ? "light" : "dark";
464
+ await switchTheme(newTheme, animationOff);
465
+ },
466
+ [resolvedTheme, switchTheme]
467
+ );
468
+ const toggleLightTheme = React4.useCallback(
469
+ async (animationOff = false) => {
470
+ if (resolvedTheme === "light") return;
471
+ await switchTheme("light", animationOff);
472
+ },
473
+ [resolvedTheme, switchTheme]
474
+ );
475
+ const toggleDarkTheme = React4.useCallback(
476
+ async (animationOff = false) => {
477
+ if (resolvedTheme === "dark") return;
478
+ await switchTheme("dark", animationOff);
479
+ },
480
+ [resolvedTheme, switchTheme]
481
+ );
482
+ const toggleColorTheme = React4.useCallback(() => {
483
+ const currentIndex = colorThemes.indexOf(currentColorTheme);
484
+ const nextIndex = (currentIndex + 1) % colorThemes.length;
485
+ const nextColorTheme = colorThemes[nextIndex];
486
+ setColorTheme(nextColorTheme);
487
+ }, [currentColorTheme, colorThemes, setColorTheme]);
488
+ const createColorThemeToggle = React4.useCallback(
489
+ (targetColorTheme) => {
490
+ return () => {
491
+ if (colorThemes.indexOf(targetColorTheme) === -1) {
492
+ console.warn(
493
+ `Color theme "${targetColorTheme}" not found in available themes`
494
+ );
495
+ return;
496
+ }
497
+ setColorTheme(targetColorTheme);
498
+ };
499
+ },
500
+ [colorThemes, setColorTheme]
501
+ );
502
+ const isColorThemeActive = React4.useCallback(
503
+ (targetColorTheme) => {
504
+ return currentColorTheme === targetColorTheme;
505
+ },
506
+ [currentColorTheme]
507
+ );
508
+ return {
509
+ ref,
510
+ theme: currentTheme,
511
+ colorTheme: currentColorTheme,
512
+ resolvedTheme,
513
+ systemTheme,
514
+ setTheme,
515
+ setColorTheme,
516
+ switchTheme,
517
+ switchColorTheme,
518
+ toggleTheme,
519
+ toggleLightTheme,
520
+ toggleDarkTheme,
521
+ toggleColorTheme,
522
+ createColorThemeToggle,
523
+ isColorThemeActive
524
+ };
525
+ };
526
+ var SharedThemeContext = React4.createContext(
527
+ null
528
+ );
529
+ var useSharedThemeContext = () => {
530
+ return React4.useContext(SharedThemeContext);
531
+ };
532
+ var SunIcon = () => /* @__PURE__ */ jsxRuntime.jsxs(
533
+ "svg",
534
+ {
535
+ width: "16",
536
+ height: "16",
537
+ viewBox: "0 0 24 24",
538
+ fill: "none",
539
+ stroke: "currentColor",
540
+ strokeWidth: "2",
541
+ strokeLinecap: "round",
542
+ strokeLinejoin: "round",
543
+ children: [
544
+ /* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "12", cy: "12", r: "5" }),
545
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M12 1v2M12 21v2M4.22 4.22l1.42 1.42M18.36 18.36l1.42 1.42M1 12h2M21 12h2M4.22 19.78l1.42-1.42M18.36 5.64l1.42-1.42" })
546
+ ]
547
+ }
548
+ );
549
+ var MoonIcon = () => /* @__PURE__ */ jsxRuntime.jsx(
550
+ "svg",
551
+ {
552
+ width: "16",
553
+ height: "16",
554
+ viewBox: "0 0 24 24",
555
+ fill: "none",
556
+ stroke: "currentColor",
557
+ strokeWidth: "2",
558
+ strokeLinecap: "round",
559
+ strokeLinejoin: "round",
560
+ children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z" })
561
+ }
562
+ );
563
+ var MonitorIcon = () => /* @__PURE__ */ jsxRuntime.jsxs(
564
+ "svg",
565
+ {
566
+ width: "16",
567
+ height: "16",
568
+ viewBox: "0 0 24 24",
569
+ fill: "none",
570
+ stroke: "currentColor",
571
+ strokeWidth: "2",
572
+ strokeLinecap: "round",
573
+ strokeLinejoin: "round",
574
+ children: [
575
+ /* @__PURE__ */ jsxRuntime.jsx("rect", { width: "20", height: "14", x: "2", y: "3", rx: "2" }),
576
+ /* @__PURE__ */ jsxRuntime.jsx("line", { x1: "8", x2: "16", y1: "21", y2: "21" }),
577
+ /* @__PURE__ */ jsxRuntime.jsx("line", { x1: "12", x2: "12", y1: "17", y2: "21" })
578
+ ]
579
+ }
580
+ );
581
+ var ThemeOption = ({
582
+ icon,
583
+ value,
584
+ isActive,
585
+ isHovered,
586
+ onClick,
587
+ onMouseEnter,
588
+ onMouseLeave,
589
+ buttonRef
590
+ }) => {
591
+ return /* @__PURE__ */ jsxRuntime.jsxs(
592
+ "button",
593
+ {
594
+ ref: isActive ? buttonRef : void 0,
595
+ className: clsx.clsx(
596
+ "relative flex h-9 w-12 cursor-pointer items-center justify-center",
597
+ "text-muted-foreground hover:text-foreground",
598
+ isActive && "text-foreground font-medium"
599
+ ),
600
+ role: "radio",
601
+ "aria-checked": isActive,
602
+ "aria-label": `Switch to ${value} theme`,
603
+ onClick: (event) => onClick(value, event),
604
+ onMouseEnter,
605
+ onMouseLeave,
606
+ style: {
607
+ borderRadius: "var(--radius)"
608
+ },
609
+ children: [
610
+ isHovered && /* @__PURE__ */ jsxRuntime.jsx(
611
+ react.motion.div,
612
+ {
613
+ layoutId: "theme-hover",
614
+ className: "absolute inset-0 bg-muted",
615
+ style: {
616
+ borderRadius: "var(--radius)"
617
+ },
618
+ transition: {
619
+ type: "spring",
620
+ bounce: 0,
621
+ stiffness: 100,
622
+ damping: 10,
623
+ duration: 0.3
624
+ }
625
+ }
626
+ ),
627
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "relative z-10 flex items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "[&_svg]:size-4", children: icon }) }),
628
+ isActive && /* @__PURE__ */ jsxRuntime.jsx(
629
+ "div",
630
+ {
631
+ className: "absolute bottom-0 left-1/2 h-0.5 w-6 -translate-x-1/2 rounded-full",
632
+ style: {
633
+ backgroundColor: "hsl(var(--primary))"
634
+ }
635
+ }
636
+ )
637
+ ]
638
+ }
639
+ );
640
+ };
641
+ var THEME_OPTIONS = [
642
+ {
643
+ icon: /* @__PURE__ */ jsxRuntime.jsx(MonitorIcon, {}),
644
+ value: "system"
645
+ },
646
+ {
647
+ icon: /* @__PURE__ */ jsxRuntime.jsx(SunIcon, {}),
648
+ value: "light"
649
+ },
650
+ {
651
+ icon: /* @__PURE__ */ jsxRuntime.jsx(MoonIcon, {}),
652
+ value: "dark"
653
+ }
654
+ ];
655
+ var ThemeSwitcherView = ({
656
+ className,
657
+ onSwitchTheme,
658
+ theme,
659
+ themes,
660
+ themeRef
661
+ }) => {
662
+ const [isMounted, setIsMounted] = React4.useState(false);
663
+ const [hoveredTheme, setHoveredTheme] = React4.useState(null);
664
+ React4.useEffect(() => {
665
+ setIsMounted(true);
666
+ }, []);
667
+ const handleThemeChange = async (newTheme, event) => {
668
+ await onSwitchTheme(newTheme, event);
669
+ };
670
+ const filteredOptions = THEME_OPTIONS.filter(
671
+ (option) => themes.includes(option.value)
672
+ );
673
+ return /* @__PURE__ */ jsxRuntime.jsx(
674
+ "div",
675
+ {
676
+ className: clsx.clsx(
677
+ "inline-flex h-9 items-center overflow-hidden bg-background shadow-sm border border-border",
678
+ isMounted ? "opacity-100" : "opacity-0",
679
+ className
680
+ ),
681
+ style: {
682
+ borderRadius: "var(--radius)",
683
+ backgroundColor: "hsl(var(--background))"
684
+ },
685
+ role: "radiogroup",
686
+ onMouseLeave: () => setHoveredTheme(null),
687
+ children: filteredOptions.map((option) => /* @__PURE__ */ jsxRuntime.jsx(
688
+ ThemeOption,
689
+ {
690
+ icon: option.icon,
691
+ value: option.value,
692
+ isActive: theme === option.value,
693
+ isHovered: hoveredTheme === option.value,
694
+ onClick: handleThemeChange,
695
+ onMouseEnter: () => setHoveredTheme(option.value),
696
+ onMouseLeave: () => {
697
+ },
698
+ buttonRef: theme === option.value ? themeRef : void 0
699
+ },
700
+ option.value
701
+ ))
702
+ }
703
+ );
704
+ };
705
+ var ThemeSwitcherWithContext = ({ className, contextTheme, themes = ["light", "dark", "system"] }) => {
706
+ const handleSwitchTheme = async (theme, event) => {
707
+ if (contextTheme.switchThemeFromElement && event) {
708
+ await contextTheme.switchThemeFromElement(theme, event.currentTarget);
709
+ return;
710
+ }
711
+ await contextTheme.switchTheme(theme);
712
+ };
713
+ return /* @__PURE__ */ jsxRuntime.jsx(
714
+ ThemeSwitcherView,
715
+ {
716
+ className,
717
+ onSwitchTheme: handleSwitchTheme,
718
+ theme: contextTheme.theme,
719
+ themes,
720
+ themeRef: contextTheme.ref
721
+ }
722
+ );
723
+ };
724
+ var ThemeSwitcherStandalone = ({
725
+ themes = ["light", "dark", "system"],
726
+ currentTheme,
727
+ onThemeChange,
728
+ animationType,
729
+ duration,
730
+ className
731
+ }) => {
732
+ const standaloneHook = useThemeAnimation({
733
+ animationType,
734
+ duration,
735
+ themes,
736
+ ...currentTheme !== void 0 && { theme: currentTheme },
737
+ onThemeChange
738
+ });
739
+ const handleSwitchTheme = async (theme) => {
740
+ await standaloneHook.switchTheme(theme);
741
+ };
742
+ return /* @__PURE__ */ jsxRuntime.jsx(
743
+ ThemeSwitcherView,
744
+ {
745
+ className,
746
+ onSwitchTheme: handleSwitchTheme,
747
+ theme: standaloneHook.theme,
748
+ themes,
749
+ themeRef: standaloneHook.ref
750
+ }
751
+ );
752
+ };
753
+ var ThemeSwitcher = (props) => {
754
+ const contextTheme = useSharedThemeContext();
755
+ if (contextTheme) {
756
+ return /* @__PURE__ */ jsxRuntime.jsx(ThemeSwitcherWithContext, { ...props, contextTheme });
757
+ }
758
+ return /* @__PURE__ */ jsxRuntime.jsx(ThemeSwitcherStandalone, { ...props });
759
+ };
760
+ function Select({
761
+ ...props
762
+ }) {
763
+ return /* @__PURE__ */ jsxRuntime.jsx(SelectPrimitive__namespace.Root, { "data-slot": "select", ...props });
764
+ }
765
+ function SelectValue({
766
+ ...props
767
+ }) {
768
+ return /* @__PURE__ */ jsxRuntime.jsx(SelectPrimitive__namespace.Value, { "data-slot": "select-value", ...props });
769
+ }
770
+ var ChevronDownIcon = () => /* @__PURE__ */ jsxRuntime.jsx(
771
+ "svg",
772
+ {
773
+ width: "16",
774
+ height: "16",
775
+ viewBox: "0 0 24 24",
776
+ fill: "none",
777
+ stroke: "currentColor",
778
+ strokeWidth: "2",
779
+ strokeLinecap: "round",
780
+ strokeLinejoin: "round",
781
+ children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "m6 9 6 6 6-6" })
782
+ }
783
+ );
784
+ var CheckIcon = () => /* @__PURE__ */ jsxRuntime.jsx(
785
+ "svg",
786
+ {
787
+ width: "16",
788
+ height: "16",
789
+ viewBox: "0 0 24 24",
790
+ fill: "none",
791
+ stroke: "currentColor",
792
+ strokeWidth: "2",
793
+ strokeLinecap: "round",
794
+ strokeLinejoin: "round",
795
+ children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M20 6 9 17l-5-5" })
796
+ }
797
+ );
798
+ function SelectTrigger({
799
+ className,
800
+ size = "default",
801
+ children,
802
+ ...props
803
+ }) {
804
+ return /* @__PURE__ */ jsxRuntime.jsxs(
805
+ SelectPrimitive__namespace.Trigger,
806
+ {
807
+ "data-slot": "select-trigger",
808
+ "data-size": size,
809
+ className: clsx.clsx(
810
+ "border-input data-[placeholder]:text-muted-foreground [&_svg:not([class*='text-'])]:text-muted-foreground focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:bg-input/30 dark:hover:bg-input/50 flex w-fit items-center justify-between gap-2 rounded-md border bg-transparent px-3 py-2 text-sm whitespace-nowrap shadow-xs transition-[color,box-shadow] outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50 data-[size=default]:h-9 data-[size=sm]:h-8 *:data-[slot=select-value]:line-clamp-1 *:data-[slot=select-value]:flex *:data-[slot=select-value]:items-center *:data-[slot=select-value]:gap-2 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
811
+ className
812
+ ),
813
+ ...props,
814
+ children: [
815
+ children,
816
+ /* @__PURE__ */ jsxRuntime.jsx(SelectPrimitive__namespace.Icon, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(ChevronDownIcon, {}) })
817
+ ]
818
+ }
819
+ );
820
+ }
821
+ function SelectContent({
822
+ className,
823
+ children,
824
+ position = "popper",
825
+ ...props
826
+ }) {
827
+ return /* @__PURE__ */ jsxRuntime.jsx(SelectPrimitive__namespace.Portal, { children: /* @__PURE__ */ jsxRuntime.jsx(
828
+ SelectPrimitive__namespace.Content,
829
+ {
830
+ "data-slot": "select-content",
831
+ className: clsx.clsx(
832
+ "bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 relative z-50 max-h-(--radix-select-content-available-height) min-w-[8rem] origin-(--radix-select-content-transform-origin) overflow-x-hidden overflow-y-auto rounded-md border shadow-md",
833
+ position === "popper" && "data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1",
834
+ className
835
+ ),
836
+ position,
837
+ ...props,
838
+ children: /* @__PURE__ */ jsxRuntime.jsx(
839
+ SelectPrimitive__namespace.Viewport,
840
+ {
841
+ className: clsx.clsx(
842
+ "p-1",
843
+ position === "popper" && "h-[var(--radix-select-trigger-height)] w-full min-w-[var(--radix-select-trigger-width)]"
844
+ ),
845
+ children
846
+ }
847
+ )
848
+ }
849
+ ) });
850
+ }
851
+ function SelectItem({
852
+ className,
853
+ children,
854
+ ...props
855
+ }) {
856
+ return /* @__PURE__ */ jsxRuntime.jsxs(
857
+ SelectPrimitive__namespace.Item,
858
+ {
859
+ "data-slot": "select-item",
860
+ className: clsx.clsx(
861
+ "focus:bg-accent focus:text-accent-foreground [&_svg:not([class*='text-'])]:text-muted-foreground relative flex w-full cursor-default items-center gap-2 rounded-sm py-1.5 pr-8 pl-2 text-sm outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 *:[span]:last:flex *:[span]:last:items-center *:[span]:last:gap-2",
862
+ className
863
+ ),
864
+ ...props,
865
+ children: [
866
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "absolute left-2 flex h-3.5 w-3.5 items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(SelectPrimitive__namespace.ItemIndicator, { children: /* @__PURE__ */ jsxRuntime.jsx(CheckIcon, {}) }) }),
867
+ /* @__PURE__ */ jsxRuntime.jsx(SelectPrimitive__namespace.ItemText, { children })
868
+ ]
869
+ }
870
+ );
871
+ }
872
+ var ThemeSelectorView = ({
873
+ colorTheme,
874
+ colorThemes,
875
+ onSelectColorTheme
876
+ }) => {
877
+ return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: colorThemes.length > 1 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-col gap-2", children: /* @__PURE__ */ jsxRuntime.jsxs(
878
+ Select,
879
+ {
880
+ value: colorTheme,
881
+ onValueChange: (value) => onSelectColorTheme(value),
882
+ children: [
883
+ /* @__PURE__ */ jsxRuntime.jsx(SelectTrigger, { className: "capitalize", children: /* @__PURE__ */ jsxRuntime.jsx(SelectValue, { placeholder: "Choose a color theme" }) }),
884
+ /* @__PURE__ */ jsxRuntime.jsx(SelectContent, { children: colorThemes.map((theme) => /* @__PURE__ */ jsxRuntime.jsx(SelectItem, { className: "capitalize", value: theme, children: theme }, theme)) })
885
+ ]
886
+ }
887
+ ) }) : null });
888
+ };
889
+ var ThemeSelectorWithContext = ({ colorThemes = ["default"], contextTheme }) => {
890
+ return /* @__PURE__ */ jsxRuntime.jsx(
891
+ ThemeSelectorView,
892
+ {
893
+ colorTheme: contextTheme.colorTheme,
894
+ colorThemes,
895
+ onSelectColorTheme: contextTheme.setColorTheme
896
+ }
897
+ );
898
+ };
899
+ var ThemeSelectorStandalone = ({
900
+ themes = ["light", "dark", "system"],
901
+ colorThemes = ["default"],
902
+ currentColorTheme,
903
+ onColorThemeChange,
904
+ animationType,
905
+ duration
906
+ }) => {
907
+ const standaloneHook = useThemeAnimation({
908
+ animationType,
909
+ duration,
910
+ themes,
911
+ colorThemes,
912
+ ...currentColorTheme !== void 0 && { colorTheme: currentColorTheme },
913
+ onColorThemeChange
914
+ });
915
+ return /* @__PURE__ */ jsxRuntime.jsx(
916
+ ThemeSelectorView,
917
+ {
918
+ colorTheme: standaloneHook.colorTheme,
919
+ colorThemes,
920
+ onSelectColorTheme: standaloneHook.setColorTheme
921
+ }
922
+ );
923
+ };
924
+ var ThemeSelector = (props) => {
925
+ const contextTheme = useSharedThemeContext();
926
+ if (contextTheme) {
927
+ return /* @__PURE__ */ jsxRuntime.jsx(ThemeSelectorWithContext, { ...props, contextTheme });
928
+ }
929
+ return /* @__PURE__ */ jsxRuntime.jsx(ThemeSelectorStandalone, { ...props });
930
+ };
931
+
932
+ // src/react/components/provider-helpers.ts
933
+ var withElementAsRef = async (ref, element, run) => {
934
+ if (ref.current) {
935
+ const originalRef = ref.current;
936
+ Object.defineProperty(ref, "current", {
937
+ value: element,
938
+ writable: true,
939
+ configurable: true
940
+ });
941
+ await run();
942
+ Object.defineProperty(ref, "current", {
943
+ value: originalRef,
944
+ writable: true,
945
+ configurable: true
946
+ });
947
+ return;
948
+ }
949
+ Object.defineProperty(ref, "current", {
950
+ value: element,
951
+ writable: true,
952
+ configurable: true
953
+ });
954
+ await run();
955
+ };
956
+ var getBrowserSystemTheme = () => {
957
+ return typeof window !== "undefined" && window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
958
+ };
959
+ var getNextResolvedTheme = (resolvedTheme) => {
960
+ return resolvedTheme === "dark" ? "light" : "dark";
961
+ };
962
+ var SpacemanThemeContext = React4.createContext(void 0);
963
+ var SpacemanThemeProvider = ({
964
+ children,
965
+ themes = ["light", "dark", "system"],
966
+ colorThemes = ["default"],
967
+ defaultTheme = "system",
968
+ defaultColorTheme = "default",
969
+ animationType = "circle" /* CIRCLE */,
970
+ duration = 750
971
+ }) => {
972
+ const [mounted, setMounted] = React4.useState(false);
973
+ const themeState = useThemeAnimation({
974
+ themes,
975
+ colorThemes,
976
+ defaultTheme,
977
+ defaultColorTheme,
978
+ animationType,
979
+ duration
980
+ });
981
+ React4.useEffect(() => {
982
+ setMounted(true);
983
+ }, []);
984
+ const switchThemeFromElement = async (theme, element) => {
985
+ await withElementAsRef(themeState.ref, element, async () => {
986
+ await themeState.switchTheme(theme);
987
+ });
988
+ };
989
+ if (!mounted) {
990
+ const loadingContextValue = {
991
+ ref: { current: null },
992
+ theme: defaultTheme,
993
+ colorTheme: defaultColorTheme,
994
+ resolvedTheme: defaultTheme === "dark" ? "dark" : "light",
995
+ setTheme: () => {
996
+ },
997
+ setColorTheme: () => {
998
+ },
999
+ switchTheme: async () => {
1000
+ },
1001
+ switchThemeFromElement: async () => {
1002
+ },
1003
+ switchColorTheme: () => {
1004
+ },
1005
+ toggleTheme: async () => {
1006
+ },
1007
+ toggleLightTheme: async () => {
1008
+ },
1009
+ toggleDarkTheme: async () => {
1010
+ },
1011
+ toggleColorTheme: () => {
1012
+ },
1013
+ createColorThemeToggle: () => () => {
1014
+ },
1015
+ isColorThemeActive: () => false
1016
+ };
1017
+ return /* @__PURE__ */ jsxRuntime.jsx(SpacemanThemeContext.Provider, { value: loadingContextValue, children: /* @__PURE__ */ jsxRuntime.jsx(SharedThemeContext.Provider, { value: loadingContextValue, children }) });
1018
+ }
1019
+ const contextValue = {
1020
+ ref: themeState.ref,
1021
+ theme: themeState.theme,
1022
+ colorTheme: themeState.colorTheme,
1023
+ resolvedTheme: themeState.resolvedTheme,
1024
+ setTheme: themeState.setTheme,
1025
+ setColorTheme: themeState.setColorTheme,
1026
+ switchTheme: themeState.switchTheme,
1027
+ switchThemeFromElement,
1028
+ switchColorTheme: themeState.switchColorTheme,
1029
+ toggleTheme: themeState.toggleTheme,
1030
+ toggleLightTheme: themeState.toggleLightTheme,
1031
+ toggleDarkTheme: themeState.toggleDarkTheme,
1032
+ toggleColorTheme: themeState.toggleColorTheme,
1033
+ createColorThemeToggle: themeState.createColorThemeToggle,
1034
+ isColorThemeActive: themeState.isColorThemeActive
1035
+ };
1036
+ return /* @__PURE__ */ jsxRuntime.jsx(SpacemanThemeContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsxRuntime.jsx(SharedThemeContext.Provider, { value: contextValue, children }) });
1037
+ };
1038
+ var useSpacemanTheme = () => {
1039
+ const context = React4.useContext(SpacemanThemeContext);
1040
+ if (context === void 0) {
1041
+ throw new Error(
1042
+ "useSpacemanTheme must be used within a SpacemanThemeProvider"
1043
+ );
1044
+ }
1045
+ return context;
1046
+ };
1047
+ var NextThemeContext = React4.createContext(
1048
+ void 0
1049
+ );
1050
+ var createDisableTransitions = () => {
1051
+ const css = document.createElement("style");
1052
+ css.textContent = "*,*::before,*::after{-webkit-transition:none!important;-moz-transition:none!important;-o-transition:none!important;-ms-transition:none!important;transition:none!important}";
1053
+ document.head.appendChild(css);
1054
+ window.getComputedStyle(document.body);
1055
+ return () => {
1056
+ setTimeout(() => {
1057
+ if (css.parentNode) {
1058
+ css.parentNode.removeChild(css);
1059
+ }
1060
+ }, 1);
1061
+ };
1062
+ };
1063
+ var generatePreHydrationScript = ({
1064
+ attribute,
1065
+ colorStorageKey,
1066
+ colorThemePrefix,
1067
+ defaultColorTheme,
1068
+ defaultTheme,
1069
+ enableColorScheme,
1070
+ enableSystem,
1071
+ globalClassName,
1072
+ storageKey,
1073
+ value
1074
+ }) => {
1075
+ const lightValue = value?.light ?? "light";
1076
+ const darkValue = value?.dark ?? globalClassName;
1077
+ const systemValue = value?.system ?? "system";
1078
+ return `(function(){try{var d=document.documentElement;var theme=localStorage.getItem('${storageKey}')||'${defaultTheme}';var colorTheme=localStorage.getItem('${colorStorageKey}')||'${defaultColorTheme}';if(!${JSON.stringify(
1079
+ enableSystem
1080
+ )}&&theme==='system'){theme='${defaultTheme === "system" ? "light" : defaultTheme}';}var resolved=theme==='system'?(window.matchMedia('(prefers-color-scheme: dark)').matches?'dark':'light'):theme;var attr='${attribute}';var lightValue='${lightValue}';var darkValue='${darkValue}';var systemValue='${systemValue}';if(attr==='data-theme'){d.setAttribute('data-theme',theme==='system'?systemValue:(resolved==='dark'?darkValue:lightValue));}else{d.classList.remove(lightValue,darkValue,systemValue,'auto');d.classList.add(theme==='system'?systemValue:(resolved==='dark'?darkValue:lightValue));}if(${JSON.stringify(
1081
+ enableColorScheme
1082
+ )}){d.style.colorScheme=theme==='system'?'':resolved;}else{d.style.removeProperty('color-scheme');}d.classList.add('${colorThemePrefix}'+colorTheme);}catch(e){console.warn('Theme pre-hydration script failed:',e);}})();`;
1083
+ };
1084
+ var ThemePreHydrationScript = React4__default.default.memo(
1085
+ ({
1086
+ attribute,
1087
+ colorStorageKey,
1088
+ colorThemePrefix,
1089
+ defaultColorTheme,
1090
+ defaultTheme,
1091
+ enableColorScheme,
1092
+ enableSystem,
1093
+ globalClassName,
1094
+ nonce,
1095
+ scriptProps,
1096
+ storageKey,
1097
+ value
1098
+ }) => /* @__PURE__ */ jsxRuntime.jsx(
1099
+ "script",
1100
+ {
1101
+ ...scriptProps,
1102
+ nonce,
1103
+ suppressHydrationWarning: true,
1104
+ dangerouslySetInnerHTML: {
1105
+ __html: generatePreHydrationScript({
1106
+ attribute,
1107
+ colorStorageKey,
1108
+ colorThemePrefix,
1109
+ defaultColorTheme,
1110
+ defaultTheme,
1111
+ enableColorScheme,
1112
+ enableSystem,
1113
+ globalClassName,
1114
+ storageKey,
1115
+ value
1116
+ })
1117
+ }
1118
+ }
1119
+ )
1120
+ );
1121
+ ThemePreHydrationScript.displayName = "ThemePreHydrationScript";
1122
+ var NextThemeProvider = ({
1123
+ attribute = "class",
1124
+ children,
1125
+ colorStorageKey = "color-theme",
1126
+ colorThemePrefix = "theme-",
1127
+ colorThemes = ["default"],
1128
+ defaultColorTheme = "default",
1129
+ defaultTheme = "system",
1130
+ disableAnimationOnInit = true,
1131
+ disablePreHydrationScript = false,
1132
+ disableTransitionOnChange = false,
1133
+ duration = 750,
1134
+ enableColorScheme = true,
1135
+ enableSystem = true,
1136
+ forcedTheme,
1137
+ globalClassName = "dark",
1138
+ nonce,
1139
+ onColorThemeChange,
1140
+ onThemeChange,
1141
+ scriptProps,
1142
+ storageKey = "theme",
1143
+ themes,
1144
+ value,
1145
+ animationType = "circle" /* CIRCLE */
1146
+ }) => {
1147
+ const allowedThemes = React4.useMemo(() => {
1148
+ if (themes && themes.length > 0) {
1149
+ return themes;
1150
+ }
1151
+ return enableSystem ? ["light", "dark", "system"] : ["light", "dark"];
1152
+ }, [enableSystem, themes]);
1153
+ const effectiveDefaultTheme = React4.useMemo(() => {
1154
+ if (defaultTheme === "system" && !enableSystem) {
1155
+ return "light";
1156
+ }
1157
+ return defaultTheme;
1158
+ }, [defaultTheme, enableSystem]);
1159
+ const [mounted, setMounted] = React4.useState(false);
1160
+ const themeState = useThemeAnimation({
1161
+ animationType,
1162
+ attribute,
1163
+ colorStorageKey,
1164
+ colorTheme: forcedTheme ? void 0 : void 0,
1165
+ colorThemePrefix,
1166
+ colorThemes,
1167
+ defaultColorTheme,
1168
+ defaultTheme: effectiveDefaultTheme,
1169
+ duration,
1170
+ enableColorScheme,
1171
+ globalClassName,
1172
+ onColorThemeChange,
1173
+ onThemeChange,
1174
+ storageKey,
1175
+ theme: forcedTheme,
1176
+ themes: allowedThemes,
1177
+ value
1178
+ });
1179
+ React4.useEffect(() => {
1180
+ setMounted(true);
1181
+ }, []);
1182
+ const withTransitionsDisabled = React4.useCallback(
1183
+ async (fn) => {
1184
+ const cleanup = disableTransitionOnChange ? createDisableTransitions() : void 0;
1185
+ try {
1186
+ return await fn();
1187
+ } finally {
1188
+ cleanup?.();
1189
+ }
1190
+ },
1191
+ [disableTransitionOnChange]
1192
+ );
1193
+ const setTheme = React4.useCallback(
1194
+ (theme) => {
1195
+ void withTransitionsDisabled(async () => {
1196
+ themeState.setTheme(theme);
1197
+ });
1198
+ },
1199
+ [themeState, withTransitionsDisabled]
1200
+ );
1201
+ const switchTheme = React4.useCallback(
1202
+ async (theme, animationOff = false) => {
1203
+ await withTransitionsDisabled(async () => {
1204
+ if (!mounted && disableAnimationOnInit) {
1205
+ themeState.setTheme(theme);
1206
+ return;
1207
+ }
1208
+ await themeState.switchTheme(theme, animationOff);
1209
+ });
1210
+ },
1211
+ [disableAnimationOnInit, mounted, themeState, withTransitionsDisabled]
1212
+ );
1213
+ const switchThemeFromElement = React4.useCallback(
1214
+ async (theme, element) => {
1215
+ await withTransitionsDisabled(async () => {
1216
+ if (!mounted && disableAnimationOnInit) {
1217
+ themeState.setTheme(theme);
1218
+ return;
1219
+ }
1220
+ await withElementAsRef(themeState.ref, element, async () => {
1221
+ await themeState.switchTheme(theme);
1222
+ });
1223
+ });
1224
+ },
1225
+ [disableAnimationOnInit, mounted, themeState, withTransitionsDisabled]
1226
+ );
1227
+ const contextValue = React4.useMemo(
1228
+ () => ({
1229
+ ref: themeState.ref,
1230
+ theme: themeState.theme,
1231
+ colorTheme: themeState.colorTheme,
1232
+ resolvedTheme: themeState.resolvedTheme,
1233
+ systemTheme: themeState.systemTheme,
1234
+ setTheme,
1235
+ setColorTheme: themeState.setColorTheme,
1236
+ switchTheme,
1237
+ switchColorTheme: themeState.switchColorTheme,
1238
+ toggleTheme: async (animationOff = false) => switchTheme(
1239
+ getNextResolvedTheme(themeState.resolvedTheme),
1240
+ animationOff
1241
+ ),
1242
+ toggleLightTheme: async (animationOff = false) => {
1243
+ if (themeState.resolvedTheme === "light") return;
1244
+ await switchTheme("light", animationOff);
1245
+ },
1246
+ toggleDarkTheme: async (animationOff = false) => {
1247
+ if (themeState.resolvedTheme === "dark") return;
1248
+ await switchTheme("dark", animationOff);
1249
+ },
1250
+ toggleColorTheme: themeState.toggleColorTheme,
1251
+ createColorThemeToggle: themeState.createColorThemeToggle,
1252
+ isColorThemeActive: themeState.isColorThemeActive,
1253
+ switchThemeFromElement
1254
+ }),
1255
+ [setTheme, switchTheme, switchThemeFromElement, themeState]
1256
+ );
1257
+ return /* @__PURE__ */ jsxRuntime.jsx(NextThemeContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsxRuntime.jsxs(SharedThemeContext.Provider, { value: contextValue, children: [
1258
+ !disablePreHydrationScript && !forcedTheme ? /* @__PURE__ */ jsxRuntime.jsx(
1259
+ ThemePreHydrationScript,
1260
+ {
1261
+ attribute,
1262
+ colorStorageKey,
1263
+ colorThemePrefix,
1264
+ defaultColorTheme,
1265
+ defaultTheme: effectiveDefaultTheme,
1266
+ enableColorScheme,
1267
+ enableSystem,
1268
+ globalClassName,
1269
+ nonce,
1270
+ scriptProps,
1271
+ storageKey,
1272
+ value
1273
+ }
1274
+ ) : null,
1275
+ children
1276
+ ] }) });
1277
+ };
1278
+ var ThemeProvider = NextThemeProvider;
1279
+ var useNextTheme = () => {
1280
+ const context = React4.useContext(NextThemeContext);
1281
+ if (context === void 0) {
1282
+ throw new Error("useNextTheme must be used within a NextThemeProvider");
1283
+ }
1284
+ return context;
1285
+ };
1286
+ var useTheme = useNextTheme;
1287
+ var isBrowser3 = typeof window !== "undefined";
1288
+ var useSyncServerThemeStorage = ({
1289
+ enabled,
1290
+ theme,
1291
+ colorTheme,
1292
+ storageKey,
1293
+ colorStorageKey
1294
+ }) => {
1295
+ React4.useEffect(() => {
1296
+ if (!enabled || !isBrowser3) return;
1297
+ if (theme) {
1298
+ localStorage.setItem(storageKey, theme);
1299
+ }
1300
+ if (colorTheme) {
1301
+ localStorage.setItem(colorStorageKey, colorTheme);
1302
+ }
1303
+ }, [enabled, theme, colorTheme, storageKey, colorStorageKey]);
1304
+ };
1305
+
1306
+ // src/tanstack/helpers.ts
1307
+ var STORAGE_KEY = "theme";
1308
+ var COLOR_STORAGE_KEY = "color-theme";
1309
+ var GLOBAL_CLASS_NAME = "dark";
1310
+ var COLOR_THEME_PREFIX = "theme-";
1311
+ var TanStackThemeContext = React4.createContext(void 0);
1312
+ var generateTanStackPreHydrationScript = (storageKey, colorStorageKey, defaultTheme, defaultColorTheme, globalClassName, colorThemePrefix, systemThemeMode) => {
1313
+ return `
1314
+ (function() {
1315
+ try {
1316
+ var theme = localStorage.getItem('${storageKey}') || '${defaultTheme}';
1317
+ var colorTheme = localStorage.getItem('${colorStorageKey}') || '${defaultColorTheme}';
1318
+ var el = document.documentElement;
1319
+ var resolved;
1320
+ if (theme === 'system') {
1321
+ if ('${systemThemeMode}' === 'css') {
1322
+ el.classList.remove('${globalClassName}');
1323
+ el.classList.remove('auto');
1324
+ el.classList.remove('system');
1325
+ el.classList.add('system');
1326
+ el.style.colorScheme = '';
1327
+ } else {
1328
+ resolved = window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';
1329
+ if (resolved === 'dark') {
1330
+ el.classList.add('${globalClassName}');
1331
+ } else {
1332
+ el.classList.remove('${globalClassName}');
1333
+ }
1334
+ el.classList.remove('system');
1335
+ el.classList.remove('auto');
1336
+ el.style.colorScheme = resolved;
1337
+ }
1338
+ } else {
1339
+ resolved = theme;
1340
+ el.classList.remove('system');
1341
+ el.classList.remove('auto');
1342
+ if (resolved === 'dark') {
1343
+ el.classList.add('${globalClassName}');
1344
+ } else {
1345
+ el.classList.remove('${globalClassName}');
1346
+ }
1347
+ el.style.colorScheme = resolved;
1348
+ }
1349
+ if (colorTheme && colorTheme !== 'default') {
1350
+ el.classList.add('${colorThemePrefix}' + colorTheme);
1351
+ }
1352
+ } catch (e) {
1353
+ console.warn('Theme pre-hydration script failed:', e);
1354
+ }
1355
+ })();
1356
+ `;
1357
+ };
1358
+ var TanStackStartThemeScript = React4__default.default.memo(
1359
+ ({
1360
+ storageKey = STORAGE_KEY,
1361
+ colorStorageKey = COLOR_STORAGE_KEY,
1362
+ defaultTheme = "system",
1363
+ defaultColorTheme = "default",
1364
+ globalClassName = GLOBAL_CLASS_NAME,
1365
+ colorThemePrefix = COLOR_THEME_PREFIX,
1366
+ nonce,
1367
+ systemThemeMode = "js"
1368
+ }) => {
1369
+ const scriptContent = generateTanStackPreHydrationScript(
1370
+ storageKey,
1371
+ colorStorageKey,
1372
+ defaultTheme,
1373
+ defaultColorTheme,
1374
+ globalClassName,
1375
+ colorThemePrefix,
1376
+ systemThemeMode
1377
+ );
1378
+ return /* @__PURE__ */ jsxRuntime.jsx(
1379
+ "script",
1380
+ {
1381
+ nonce,
1382
+ suppressHydrationWarning: true,
1383
+ dangerouslySetInnerHTML: { __html: scriptContent }
1384
+ }
1385
+ );
1386
+ }
1387
+ );
1388
+ TanStackStartThemeScript.displayName = "TanStackStartThemeScript";
1389
+ var useHydrated = () => {
1390
+ return React4.useSyncExternalStore(
1391
+ () => () => {
1392
+ },
1393
+ () => true,
1394
+ () => false
1395
+ );
1396
+ };
1397
+ var getNextColorTheme = (colorThemes, currentColorTheme) => {
1398
+ if (colorThemes.length === 0) return currentColorTheme;
1399
+ const currentIndex = colorThemes.indexOf(currentColorTheme);
1400
+ const nextIndex = currentIndex === -1 ? 0 : (currentIndex + 1) % colorThemes.length;
1401
+ return colorThemes[nextIndex];
1402
+ };
1403
+ var TanStackThemeProvider = ({
1404
+ children,
1405
+ themes = ["light", "dark", "system"],
1406
+ colorThemes = ["default"],
1407
+ defaultTheme = "system",
1408
+ defaultColorTheme = "default",
1409
+ animationType = "circle" /* CIRCLE */,
1410
+ duration = 750,
1411
+ storageKey = STORAGE_KEY,
1412
+ colorStorageKey = COLOR_STORAGE_KEY,
1413
+ globalClassName = GLOBAL_CLASS_NAME,
1414
+ colorThemePrefix = COLOR_THEME_PREFIX,
1415
+ serverTheme,
1416
+ serverColorTheme,
1417
+ systemThemeMode = "css",
1418
+ onServerThemeChange,
1419
+ onServerColorThemeChange
1420
+ }) => {
1421
+ const isHydrated = useHydrated();
1422
+ const hasServerTheme = serverTheme !== void 0;
1423
+ const initialTheme = hasServerTheme ? serverTheme : void 0;
1424
+ const themeState = useThemeAnimation({
1425
+ themes,
1426
+ colorThemes,
1427
+ defaultTheme,
1428
+ defaultColorTheme,
1429
+ animationType,
1430
+ duration,
1431
+ storageKey,
1432
+ colorStorageKey,
1433
+ globalClassName,
1434
+ colorThemePrefix,
1435
+ initialTheme,
1436
+ initialColorTheme: serverColorTheme,
1437
+ systemThemeMode
1438
+ });
1439
+ useSyncServerThemeStorage({
1440
+ enabled: hasServerTheme,
1441
+ theme: initialTheme,
1442
+ colorTheme: serverColorTheme,
1443
+ storageKey,
1444
+ colorStorageKey
1445
+ });
1446
+ const setThemeWithServer = React4.useCallback(
1447
+ (newTheme) => {
1448
+ themeState.setTheme(newTheme);
1449
+ onServerThemeChange?.(newTheme);
1450
+ },
1451
+ [themeState, onServerThemeChange]
1452
+ );
1453
+ const setColorThemeWithServer = React4.useCallback(
1454
+ (newColorTheme) => {
1455
+ themeState.setColorTheme(newColorTheme);
1456
+ onServerColorThemeChange?.(newColorTheme);
1457
+ },
1458
+ [themeState, onServerColorThemeChange]
1459
+ );
1460
+ const switchThemeWithHydrationAwareness = React4.useCallback(
1461
+ async (theme, animationOff = false) => {
1462
+ if (!isHydrated) {
1463
+ setThemeWithServer(theme);
1464
+ return;
1465
+ }
1466
+ await themeState.switchTheme(theme, animationOff);
1467
+ onServerThemeChange?.(theme);
1468
+ },
1469
+ [isHydrated, themeState, setThemeWithServer, onServerThemeChange]
1470
+ );
1471
+ const toggleThemeWithHydrationAwareness = React4.useCallback(
1472
+ async (animationOff = false) => {
1473
+ const nextTheme = getNextResolvedTheme(themeState.resolvedTheme);
1474
+ if (!isHydrated) {
1475
+ setThemeWithServer(nextTheme);
1476
+ return;
1477
+ }
1478
+ await themeState.toggleTheme(animationOff);
1479
+ onServerThemeChange?.(nextTheme);
1480
+ },
1481
+ [isHydrated, themeState, setThemeWithServer, onServerThemeChange]
1482
+ );
1483
+ const toggleLightThemeWithHydrationAwareness = React4.useCallback(
1484
+ async (animationOff = false) => {
1485
+ if (!isHydrated) {
1486
+ setThemeWithServer("light");
1487
+ return;
1488
+ }
1489
+ await themeState.toggleLightTheme(animationOff);
1490
+ onServerThemeChange?.("light");
1491
+ },
1492
+ [isHydrated, themeState, setThemeWithServer, onServerThemeChange]
1493
+ );
1494
+ const toggleDarkThemeWithHydrationAwareness = React4.useCallback(
1495
+ async (animationOff = false) => {
1496
+ if (!isHydrated) {
1497
+ setThemeWithServer("dark");
1498
+ return;
1499
+ }
1500
+ await themeState.toggleDarkTheme(animationOff);
1501
+ onServerThemeChange?.("dark");
1502
+ },
1503
+ [isHydrated, themeState, setThemeWithServer, onServerThemeChange]
1504
+ );
1505
+ const switchColorThemeWithServer = React4.useCallback(
1506
+ (newColorTheme) => {
1507
+ themeState.switchColorTheme(newColorTheme);
1508
+ onServerColorThemeChange?.(newColorTheme);
1509
+ },
1510
+ [themeState, onServerColorThemeChange]
1511
+ );
1512
+ const toggleColorThemeWithServer = React4.useCallback(() => {
1513
+ const nextColorTheme = getNextColorTheme(colorThemes, themeState.colorTheme);
1514
+ themeState.toggleColorTheme();
1515
+ onServerColorThemeChange?.(nextColorTheme);
1516
+ }, [colorThemes, themeState, onServerColorThemeChange]);
1517
+ const createColorThemeToggleWithServer = React4.useCallback(
1518
+ (targetColorTheme) => () => {
1519
+ themeState.createColorThemeToggle(targetColorTheme)();
1520
+ onServerColorThemeChange?.(targetColorTheme);
1521
+ },
1522
+ [themeState, onServerColorThemeChange]
1523
+ );
1524
+ const switchThemeFromElement = React4.useCallback(
1525
+ async (theme, element) => {
1526
+ if (!isHydrated) {
1527
+ setThemeWithServer(theme);
1528
+ return;
1529
+ }
1530
+ await withElementAsRef(themeState.ref, element, async () => {
1531
+ await themeState.switchTheme(theme);
1532
+ });
1533
+ onServerThemeChange?.(theme);
1534
+ },
1535
+ [isHydrated, themeState, setThemeWithServer, onServerThemeChange]
1536
+ );
1537
+ const systemTheme = getBrowserSystemTheme();
1538
+ const serverResolvedTheme = (() => {
1539
+ if (hasServerTheme) {
1540
+ if (serverTheme === "dark") return "dark";
1541
+ if (serverTheme === "system") return systemTheme;
1542
+ return "light";
1543
+ }
1544
+ return defaultTheme === "dark" ? "dark" : "light";
1545
+ })();
1546
+ if (!isHydrated) {
1547
+ const loadingContextValue = {
1548
+ ref: { current: null },
1549
+ theme: initialTheme ?? defaultTheme,
1550
+ colorTheme: serverColorTheme ?? defaultColorTheme,
1551
+ resolvedTheme: serverResolvedTheme,
1552
+ systemTheme: "light",
1553
+ isHydrated: false,
1554
+ setTheme: setThemeWithServer,
1555
+ setColorTheme: setColorThemeWithServer,
1556
+ switchTheme: async (theme) => setThemeWithServer(theme),
1557
+ switchThemeFromElement: async (theme) => setThemeWithServer(theme),
1558
+ switchColorTheme: switchColorThemeWithServer,
1559
+ toggleTheme: async () => {
1560
+ const nextTheme = serverResolvedTheme === "dark" ? "light" : "dark";
1561
+ setThemeWithServer(nextTheme);
1562
+ },
1563
+ toggleLightTheme: async () => setThemeWithServer("light"),
1564
+ toggleDarkTheme: async () => setThemeWithServer("dark"),
1565
+ toggleColorTheme: toggleColorThemeWithServer,
1566
+ createColorThemeToggle: createColorThemeToggleWithServer,
1567
+ isColorThemeActive: themeState.isColorThemeActive
1568
+ };
1569
+ return /* @__PURE__ */ jsxRuntime.jsx(TanStackThemeContext.Provider, { value: loadingContextValue, children: /* @__PURE__ */ jsxRuntime.jsx(SharedThemeContext.Provider, { value: loadingContextValue, children }) });
1570
+ }
1571
+ const contextValue = {
1572
+ ref: themeState.ref,
1573
+ theme: themeState.theme,
1574
+ colorTheme: themeState.colorTheme,
1575
+ resolvedTheme: themeState.resolvedTheme,
1576
+ systemTheme,
1577
+ isHydrated: true,
1578
+ setTheme: setThemeWithServer,
1579
+ setColorTheme: setColorThemeWithServer,
1580
+ switchTheme: switchThemeWithHydrationAwareness,
1581
+ switchThemeFromElement,
1582
+ switchColorTheme: switchColorThemeWithServer,
1583
+ toggleTheme: toggleThemeWithHydrationAwareness,
1584
+ toggleLightTheme: toggleLightThemeWithHydrationAwareness,
1585
+ toggleDarkTheme: toggleDarkThemeWithHydrationAwareness,
1586
+ toggleColorTheme: toggleColorThemeWithServer,
1587
+ createColorThemeToggle: createColorThemeToggleWithServer,
1588
+ isColorThemeActive: themeState.isColorThemeActive
1589
+ };
1590
+ return /* @__PURE__ */ jsxRuntime.jsx(TanStackThemeContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsxRuntime.jsx(SharedThemeContext.Provider, { value: contextValue, children }) });
1591
+ };
1592
+ var useTanStackTheme = () => {
1593
+ const context = React4.useContext(TanStackThemeContext);
1594
+ if (context === void 0) {
1595
+ throw new Error(
1596
+ "useTanStackTheme must be used within a TanStackThemeProvider"
1597
+ );
1598
+ }
1599
+ return context;
1600
+ };
1601
+ var ViteThemeContext = React4.createContext(
1602
+ void 0
1603
+ );
1604
+ var ViteThemeProvider = ({
1605
+ children,
1606
+ themes = ["light", "dark", "system"],
1607
+ colorThemes = ["default"],
1608
+ defaultTheme = "system",
1609
+ defaultColorTheme = "default",
1610
+ animationType = "circle" /* CIRCLE */,
1611
+ duration = 750,
1612
+ attribute = "class",
1613
+ disableTransitionOnChange = false,
1614
+ storageKey = "vite-theme",
1615
+ colorStorageKey = "vite-color-theme",
1616
+ globalClassName = "dark",
1617
+ colorThemePrefix = "theme-"
1618
+ }) => {
1619
+ const themeState = useThemeAnimation({
1620
+ themes,
1621
+ colorThemes,
1622
+ defaultTheme,
1623
+ defaultColorTheme,
1624
+ animationType,
1625
+ duration,
1626
+ storageKey,
1627
+ colorStorageKey,
1628
+ globalClassName: attribute === "class" ? globalClassName : void 0,
1629
+ colorThemePrefix
1630
+ });
1631
+ const applyTransitionDisable = React4.useCallback(() => {
1632
+ if (!disableTransitionOnChange) return () => {
1633
+ };
1634
+ const css = document.createElement("style");
1635
+ css.textContent = `*,*::before,*::after{-webkit-transition:none!important;-moz-transition:none!important;-o-transition:none!important;-ms-transition:none!important;transition:none!important}`;
1636
+ document.head.appendChild(css);
1637
+ window.getComputedStyle(document.body);
1638
+ return () => {
1639
+ setTimeout(() => {
1640
+ document.head.removeChild(css);
1641
+ }, 1);
1642
+ };
1643
+ }, [disableTransitionOnChange]);
1644
+ const wrappedSetTheme = React4.useCallback(
1645
+ (theme) => {
1646
+ const cleanup = applyTransitionDisable();
1647
+ themeState.setTheme(theme);
1648
+ cleanup();
1649
+ },
1650
+ [themeState.setTheme, applyTransitionDisable]
1651
+ );
1652
+ const wrappedSwitchTheme = React4.useCallback(
1653
+ async (theme, animationOff = false) => {
1654
+ const cleanup = applyTransitionDisable();
1655
+ await themeState.switchTheme(theme, animationOff);
1656
+ cleanup();
1657
+ },
1658
+ [themeState.switchTheme, applyTransitionDisable]
1659
+ );
1660
+ const wrappedToggleTheme = React4.useCallback(
1661
+ async (animationOff = false) => {
1662
+ const cleanup = applyTransitionDisable();
1663
+ await themeState.toggleTheme(animationOff);
1664
+ cleanup();
1665
+ },
1666
+ [themeState.toggleTheme, applyTransitionDisable]
1667
+ );
1668
+ const wrappedToggleLightTheme = React4.useCallback(
1669
+ async (animationOff = false) => {
1670
+ const cleanup = applyTransitionDisable();
1671
+ await themeState.toggleLightTheme(animationOff);
1672
+ cleanup();
1673
+ },
1674
+ [themeState.toggleLightTheme, applyTransitionDisable]
1675
+ );
1676
+ const wrappedToggleDarkTheme = React4.useCallback(
1677
+ async (animationOff = false) => {
1678
+ const cleanup = applyTransitionDisable();
1679
+ await themeState.toggleDarkTheme(animationOff);
1680
+ cleanup();
1681
+ },
1682
+ [themeState.toggleDarkTheme, applyTransitionDisable]
1683
+ );
1684
+ const switchThemeFromElement = async (theme, element) => {
1685
+ const cleanup = applyTransitionDisable();
1686
+ await withElementAsRef(themeState.ref, element, async () => {
1687
+ await themeState.switchTheme(theme);
1688
+ });
1689
+ cleanup();
1690
+ };
1691
+ const systemTheme = getBrowserSystemTheme();
1692
+ const contextValue = {
1693
+ ref: themeState.ref,
1694
+ theme: themeState.theme,
1695
+ colorTheme: themeState.colorTheme,
1696
+ resolvedTheme: themeState.resolvedTheme,
1697
+ systemTheme,
1698
+ setTheme: wrappedSetTheme,
1699
+ setColorTheme: themeState.setColorTheme,
1700
+ switchTheme: wrappedSwitchTheme,
1701
+ switchThemeFromElement,
1702
+ switchColorTheme: themeState.switchColorTheme,
1703
+ toggleTheme: wrappedToggleTheme,
1704
+ toggleLightTheme: wrappedToggleLightTheme,
1705
+ toggleDarkTheme: wrappedToggleDarkTheme,
1706
+ toggleColorTheme: themeState.toggleColorTheme,
1707
+ createColorThemeToggle: themeState.createColorThemeToggle,
1708
+ isColorThemeActive: themeState.isColorThemeActive
1709
+ };
1710
+ return /* @__PURE__ */ jsxRuntime.jsx(ViteThemeContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsxRuntime.jsx(SharedThemeContext.Provider, { value: contextValue, children }) });
1711
+ };
1712
+ var useViteTheme = () => {
1713
+ const context = React4.useContext(ViteThemeContext);
1714
+ if (context === void 0) {
1715
+ throw new Error("useViteTheme must be used within a ViteThemeProvider");
1716
+ }
1717
+ return context;
1718
+ };
1719
+
1720
+ exports.NextThemeProvider = NextThemeProvider;
1721
+ exports.SpacemanThemeProvider = SpacemanThemeProvider;
1722
+ exports.TanStackStartThemeScript = TanStackStartThemeScript;
1723
+ exports.TanStackThemeProvider = TanStackThemeProvider;
1724
+ exports.ThemeAnimationType = ThemeAnimationType;
1725
+ exports.ThemeProvider = ThemeProvider;
1726
+ exports.ThemeSelector = ThemeSelector;
1727
+ exports.ThemeSwitcher = ThemeSwitcher;
1728
+ exports.ViteThemeProvider = ViteThemeProvider;
1729
+ exports.getSystemTheme = getSystemTheme;
1730
+ exports.injectBaseStyles = injectBaseStyles;
1731
+ exports.prefersReducedMotion = prefersReducedMotion;
1732
+ exports.resolveTheme = resolveTheme;
1733
+ exports.resolveThemeForServer = resolveThemeForServer;
1734
+ exports.supportsViewTransitions = supportsViewTransitions;
1735
+ exports.useNextTheme = useNextTheme;
1736
+ exports.useSpacemanTheme = useSpacemanTheme;
1737
+ exports.useTanStackTheme = useTanStackTheme;
1738
+ exports.useTheme = useTheme;
1739
+ exports.useThemeAnimation = useThemeAnimation;
1740
+ exports.useViteTheme = useViteTheme;
1741
+ //# sourceMappingURL=index.cjs.map
1742
+ //# sourceMappingURL=index.cjs.map