@tydavidson/design-system 1.1.7 → 1.1.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,15 +1,34 @@
1
+ import * as React from 'react';
1
2
  import { ThemeProvider as ThemeProvider$1, useTheme as useTheme$1 } from 'next-themes';
2
3
  import { jsx, Fragment, jsxs } from 'react/jsx-runtime';
3
- import * as React from 'react';
4
4
  import { clsx } from 'clsx';
5
5
  import { twMerge } from 'tailwind-merge';
6
6
  import { IconSun, IconMoon } from '@tabler/icons-react';
7
+ import dynamic from 'next/dynamic';
8
+
9
+ var __defProp = Object.defineProperty;
10
+ var __getOwnPropNames = Object.getOwnPropertyNames;
11
+ var __esm = (fn, res) => function __init() {
12
+ return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
13
+ };
14
+ var __export = (target, all) => {
15
+ for (var name in all)
16
+ __defProp(target, name, { get: all[name], enumerable: true });
17
+ };
7
18
 
8
19
  // src/themes/theme-provider.tsx
20
+ var theme_provider_exports = {};
21
+ __export(theme_provider_exports, {
22
+ ThemeProvider: () => ThemeProvider,
23
+ ThemeProviderNoSSR: () => ThemeProviderNoSSR
24
+ });
9
25
  function ThemeProvider({
10
26
  children,
11
27
  ...props
12
28
  }) {
29
+ if (typeof window === "undefined") {
30
+ return /* @__PURE__ */ jsx(Fragment, { children });
31
+ }
13
32
  return /* @__PURE__ */ jsx(
14
33
  ThemeProvider$1,
15
34
  {
@@ -22,64 +41,96 @@ function ThemeProvider({
22
41
  }
23
42
  );
24
43
  }
25
-
26
- // src/lib/theme-utils.ts
27
- var mapColorToShadcnVariant = (color) => {
28
- switch (color) {
29
- case "brand":
30
- return "default";
31
- case "error":
32
- return "destructive";
33
- case "warning":
34
- case "success":
35
- return "secondary";
36
- // Will need additional classes
37
- default:
38
- return "default";
44
+ function ThemeProviderNoSSR({
45
+ children,
46
+ ...props
47
+ }) {
48
+ const [mounted, setMounted] = React.useState(false);
49
+ React.useEffect(() => {
50
+ setMounted(true);
51
+ }, []);
52
+ if (!mounted) {
53
+ return /* @__PURE__ */ jsx(Fragment, { children });
39
54
  }
40
- };
41
- var mapVariantToShadcnVariant = (variant) => {
42
- switch (variant) {
43
- case "primary":
44
- return "default";
45
- case "secondary":
46
- return "outline";
47
- case "tertiary":
48
- return "ghost";
49
- default:
50
- return "default";
55
+ return /* @__PURE__ */ jsx(ThemeProvider, { ...props, children });
56
+ }
57
+ var init_theme_provider = __esm({
58
+ "src/themes/theme-provider.tsx"() {
59
+ "use client";
51
60
  }
52
- };
53
- var getColorVariantClasses = (color, variant) => {
54
- const colorVariantMap = {
55
- primary: {
56
- brand: "bg-brand-600 hover:bg-brand-700 text-white focus-visible:ring-brand-500",
57
- error: "bg-error-600 hover:bg-error-700 text-white focus-visible:ring-error-500",
58
- warning: "bg-warning-600 hover:bg-warning-700 text-white focus-visible:ring-warning-500",
59
- success: "bg-success-600 hover:bg-success-700 text-white focus-visible:ring-success-500"
60
- },
61
- secondary: {
62
- brand: "border-brand-300 text-brand-700 hover:bg-brand-50 focus-visible:ring-brand-500",
63
- error: "border-error-300 text-error-700 hover:bg-error-50 focus-visible:ring-error-500",
64
- warning: "border-warning-300 text-warning-700 hover:bg-warning-50 focus-visible:ring-warning-500",
65
- success: "border-success-300 text-success-700 hover:bg-success-50 focus-visible:ring-success-500"
66
- },
67
- tertiary: {
68
- brand: "text-brand-700 hover:bg-brand-50 focus-visible:ring-brand-500",
69
- error: "text-error-700 hover:bg-error-50 focus-visible:ring-error-500",
70
- warning: "text-warning-700 hover:bg-warning-50 focus-visible:ring-warning-500",
71
- success: "text-success-700 hover:bg-success-50 focus-visible:ring-success-500"
72
- }
73
- };
74
- return colorVariantMap[variant]?.[color] || "";
75
- };
76
- var isDarkTheme = (theme, systemTheme) => {
77
- if (theme === "system") {
78
- return systemTheme === "dark";
61
+ });
62
+
63
+ // src/lib/theme-utils.ts
64
+ var mapColorToShadcnVariant, mapVariantToShadcnVariant, getColorVariantClasses, isDarkTheme;
65
+ var init_theme_utils = __esm({
66
+ "src/lib/theme-utils.ts"() {
67
+ mapColorToShadcnVariant = (color) => {
68
+ switch (color) {
69
+ case "brand":
70
+ return "default";
71
+ case "error":
72
+ return "destructive";
73
+ case "warning":
74
+ case "success":
75
+ return "secondary";
76
+ // Will need additional classes
77
+ default:
78
+ return "default";
79
+ }
80
+ };
81
+ mapVariantToShadcnVariant = (variant) => {
82
+ switch (variant) {
83
+ case "primary":
84
+ return "default";
85
+ case "secondary":
86
+ return "outline";
87
+ case "tertiary":
88
+ return "ghost";
89
+ default:
90
+ return "default";
91
+ }
92
+ };
93
+ getColorVariantClasses = (color, variant) => {
94
+ const colorVariantMap = {
95
+ primary: {
96
+ brand: "bg-brand-600 hover:bg-brand-700 text-white focus-visible:ring-brand-500",
97
+ error: "bg-error-600 hover:bg-error-700 text-white focus-visible:ring-error-500",
98
+ warning: "bg-warning-600 hover:bg-warning-700 text-white focus-visible:ring-warning-500",
99
+ success: "bg-success-600 hover:bg-success-700 text-white focus-visible:ring-success-500"
100
+ },
101
+ secondary: {
102
+ brand: "border-brand-300 text-brand-700 hover:bg-brand-50 focus-visible:ring-brand-500",
103
+ error: "border-error-300 text-error-700 hover:bg-error-50 focus-visible:ring-error-500",
104
+ warning: "border-warning-300 text-warning-700 hover:bg-warning-50 focus-visible:ring-warning-500",
105
+ success: "border-success-300 text-success-700 hover:bg-success-50 focus-visible:ring-success-500"
106
+ },
107
+ tertiary: {
108
+ brand: "text-brand-700 hover:bg-brand-50 focus-visible:ring-brand-500",
109
+ error: "text-error-700 hover:bg-error-50 focus-visible:ring-error-500",
110
+ warning: "text-warning-700 hover:bg-warning-50 focus-visible:ring-warning-500",
111
+ success: "text-success-700 hover:bg-success-50 focus-visible:ring-success-500"
112
+ }
113
+ };
114
+ return colorVariantMap[variant]?.[color] || "";
115
+ };
116
+ isDarkTheme = (theme, systemTheme) => {
117
+ if (theme === "system") {
118
+ return systemTheme === "dark";
119
+ }
120
+ return theme === "dark";
121
+ };
79
122
  }
80
- return theme === "dark";
81
- };
123
+ });
82
124
  function useTheme() {
125
+ if (typeof window === "undefined") {
126
+ return {
127
+ theme: "system",
128
+ setTheme: () => {
129
+ },
130
+ resolvedTheme: "light",
131
+ isDark: false
132
+ };
133
+ }
83
134
  const { theme, setTheme, resolvedTheme, systemTheme } = useTheme$1();
84
135
  const isDark = isDarkTheme(theme, systemTheme);
85
136
  return {
@@ -89,14 +140,33 @@ function useTheme() {
89
140
  isDark
90
141
  };
91
142
  }
143
+ function useThemeServer() {
144
+ return {
145
+ theme: "system",
146
+ setTheme: () => {
147
+ },
148
+ resolvedTheme: "light",
149
+ isDark: false
150
+ };
151
+ }
92
152
  function ThemeContextProvider({
93
153
  children
94
154
  }) {
95
155
  return /* @__PURE__ */ jsx(Fragment, { children });
96
156
  }
157
+ var init_theme_context = __esm({
158
+ "src/themes/theme-context.tsx"() {
159
+ "use client";
160
+ init_theme_utils();
161
+ }
162
+ });
97
163
  function cn(...inputs) {
98
164
  return twMerge(clsx(inputs));
99
165
  }
166
+ var init_utils = __esm({
167
+ "src/lib/utils.ts"() {
168
+ }
169
+ });
100
170
  function ThemeToggle({
101
171
  className,
102
172
  variant = "icon",
@@ -184,7 +254,64 @@ function ThemeToggle({
184
254
  }
185
255
  );
186
256
  }
257
+ var init_theme_toggle = __esm({
258
+ "src/components/ui/theme-toggle/theme-toggle.tsx"() {
259
+ "use client";
260
+ init_theme_context();
261
+ init_utils();
262
+ }
263
+ });
264
+
265
+ // src/components/ui/theme-toggle/index.ts
266
+ var theme_toggle_exports = {};
267
+ __export(theme_toggle_exports, {
268
+ ThemeToggle: () => ThemeToggle
269
+ });
270
+ var init_theme_toggle2 = __esm({
271
+ "src/components/ui/theme-toggle/index.ts"() {
272
+ init_theme_toggle();
273
+ }
274
+ });
275
+
276
+ // src/themes/index.ts
277
+ init_theme_provider();
278
+ init_theme_context();
279
+ init_theme_toggle2();
280
+ var DynamicThemeProvider = dynamic(
281
+ () => Promise.resolve().then(() => (init_theme_provider(), theme_provider_exports)).then((mod) => ({ default: mod.ThemeProvider })),
282
+ {
283
+ ssr: false,
284
+ loading: () => /* @__PURE__ */ jsx("div", { style: { visibility: "hidden" } })
285
+ }
286
+ );
287
+ var DynamicThemeProviderNoSSR = dynamic(
288
+ () => Promise.resolve().then(() => (init_theme_provider(), theme_provider_exports)).then((mod) => ({ default: mod.ThemeProviderNoSSR })),
289
+ {
290
+ ssr: false,
291
+ loading: () => /* @__PURE__ */ jsx("div", { style: { visibility: "hidden" } })
292
+ }
293
+ );
294
+ var DynamicThemeToggle = dynamic(
295
+ () => Promise.resolve().then(() => (init_theme_toggle2(), theme_toggle_exports)).then((mod) => ({ default: mod.ThemeToggle })),
296
+ {
297
+ ssr: false,
298
+ loading: () => /* @__PURE__ */ jsx("div", { style: { visibility: "hidden" } })
299
+ }
300
+ );
301
+ function SafeThemeProvider({
302
+ children,
303
+ noSSR = false,
304
+ ...props
305
+ }) {
306
+ if (noSSR) {
307
+ return /* @__PURE__ */ jsx(DynamicThemeProviderNoSSR, { ...props, children });
308
+ }
309
+ return /* @__PURE__ */ jsx(DynamicThemeProvider, { ...props, children });
310
+ }
311
+
312
+ // src/themes/index.ts
313
+ init_theme_utils();
187
314
 
188
- export { ThemeContextProvider, ThemeProvider, ThemeToggle, getColorVariantClasses, isDarkTheme, mapColorToShadcnVariant, mapVariantToShadcnVariant, useTheme };
315
+ export { DynamicThemeProvider, DynamicThemeProviderNoSSR, DynamicThemeToggle, SafeThemeProvider, ThemeContextProvider, ThemeProvider, ThemeProviderNoSSR, ThemeToggle, getColorVariantClasses, isDarkTheme, mapColorToShadcnVariant, mapVariantToShadcnVariant, useTheme, useThemeServer };
189
316
  //# sourceMappingURL=index.mjs.map
190
317
  //# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/themes/theme-provider.tsx","../../src/lib/theme-utils.ts","../../src/themes/theme-context.tsx","../../src/lib/utils.ts","../../src/components/ui/theme-toggle/theme-toggle.tsx"],"names":["NextThemesProvider","useNextTheme","jsx"],"mappings":";;;;;;;;AAYO,SAAS,aAAA,CAAc;AAAA,EAC5B,QAAA;AAAA,EACA,GAAG;AACL,CAAA,EAAuB;AACrB,EAAA,uBACE,GAAA;AAAA,IAACA,eAAA;AAAA,IAAA;AAAA,MACC,SAAA,EAAU,OAAA;AAAA,MACV,YAAA,EAAa,QAAA;AAAA,MACb,YAAA,EAAY,IAAA;AAAA,MACZ,yBAAA,EAAyB,IAAA;AAAA,MACxB,GAAG,KAAA;AAAA,MAEH;AAAA;AAAA,GACH;AAEJ;;;ACPO,IAAM,uBAAA,GAA0B,CAAC,KAAA,KAAsB;AAC5D,EAAA,QAAQ,KAAA;AAAO,IACb,KAAK,OAAA;AAAS,MAAA,OAAO,SAAA;AAAA,IACrB,KAAK,OAAA;AAAS,MAAA,OAAO,aAAA;AAAA,IACrB,KAAK,SAAA;AAAA,IACL,KAAK,SAAA;AACH,MAAA,OAAO,WAAA;AAAA;AAAA,IACT;AAAS,MAAA,OAAO,SAAA;AAAA;AAEpB;AAQO,IAAM,yBAAA,GAA4B,CAAC,OAAA,KAA8B;AACtE,EAAA,QAAQ,OAAA;AAAS,IACf,KAAK,SAAA;AAAW,MAAA,OAAO,SAAA;AAAA,IACvB,KAAK,WAAA;AAAa,MAAA,OAAO,SAAA;AAAA,IACzB,KAAK,UAAA;AAAY,MAAA,OAAO,OAAA;AAAA,IACxB;AAAS,MAAA,OAAO,SAAA;AAAA;AAEpB;AASO,IAAM,sBAAA,GAAyB,CACpC,KAAA,EACA,OAAA,KACW;AACX,EAAA,MAAM,eAAA,GAAwE;AAAA,IAC5E,OAAA,EAAS;AAAA,MACP,KAAA,EAAO,yEAAA;AAAA,MACP,KAAA,EAAO,yEAAA;AAAA,MACP,OAAA,EAAS,+EAAA;AAAA,MACT,OAAA,EAAS;AAAA,KACX;AAAA,IACA,SAAA,EAAW;AAAA,MACT,KAAA,EAAO,gFAAA;AAAA,MACP,KAAA,EAAO,gFAAA;AAAA,MACP,OAAA,EAAS,wFAAA;AAAA,MACT,OAAA,EAAS;AAAA,KACX;AAAA,IACA,QAAA,EAAU;AAAA,MACR,KAAA,EAAO,+DAAA;AAAA,MACP,KAAA,EAAO,+DAAA;AAAA,MACP,OAAA,EAAS,qEAAA;AAAA,MACT,OAAA,EAAS;AAAA;AACX,GACF;AAEA,EAAA,OAAO,eAAA,CAAgB,OAAO,CAAA,GAAI,KAAK,CAAA,IAAK,EAAA;AAC9C;AASO,IAAM,WAAA,GAAc,CAAC,KAAA,EAA2B,WAAA,KAA6C;AAClG,EAAA,IAAI,UAAU,QAAA,EAAU;AACtB,IAAA,OAAO,WAAA,KAAgB,MAAA;AAAA,EACzB;AACA,EAAA,OAAO,KAAA,KAAU,MAAA;AACnB;AClFO,SAAS,QAAA,GAAW;AACzB,EAAA,MAAM,EAAE,KAAA,EAAO,QAAA,EAAU,aAAA,EAAe,WAAA,KAAgBC,UAAA,EAAa;AAGrE,EAAA,MAAM,MAAA,GAAS,WAAA,CAAY,KAAA,EAAO,WAAW,CAAA;AAE7C,EAAA,OAAO;AAAA,IACL,OAAO,KAAA,IAAS,QAAA;AAAA,IAChB,QAAA;AAAA,IACA,eAAe,aAAA,IAAiB,OAAA;AAAA,IAChC;AAAA,GACF;AACF;AAMO,SAAS,oBAAA,CAAqB;AAAA,EACnC;AACF,CAAA,EAEG;AAED,EAAA,uBAAOC,GAAAA,CAAA,QAAA,EAAA,EAAG,QAAA,EAAS,CAAA;AACrB;AC1BO,SAAS,MAAM,MAAA,EAAsB;AAC1C,EAAA,OAAO,OAAA,CAAQ,IAAA,CAAK,MAAM,CAAC,CAAA;AAC7B;ACeO,SAAS,WAAA,CAAY;AAAA,EAC1B,SAAA;AAAA,EACA,OAAA,GAAU,MAAA;AAAA,EACV,IAAA,GAAO,IAAA;AAAA,EACP,GAAG;AACL,CAAA,EAAqB;AACnB,EAAA,MAAM,EAAE,KAAA,EAAO,QAAA,EAAU,aAAA,KAAkB,QAAA,EAAS;AACpD,EAAA,MAAM,CAAC,OAAA,EAAS,UAAU,CAAA,GAAU,eAAS,KAAK,CAAA;AAGlD,EAAM,gBAAU,MAAM;AACpB,IAAA,UAAA,CAAW,IAAI,CAAA;AAAA,EACjB,CAAA,EAAG,EAAE,CAAA;AAGL,EAAA,IAAI,CAAC,SAAS,OAAO,IAAA;AAGrB,EAAA,MAAM,cAAc,MAAM;AACxB,IAAA,QAAA,CAAS,aAAA,KAAkB,MAAA,GAAS,OAAA,GAAU,MAAM,CAAA;AAAA,EACtD,CAAA;AAGA,EAAA,MAAM,QAAA,GAAW;AAAA,IACf,EAAA,EAAI,EAAA;AAAA,IACJ,EAAA,EAAI,EAAA;AAAA,IACJ,EAAA,EAAI;AAAA,GACN;AAGA,EAAA,MAAM,WAAA,GAAc;AAAA,IAClB,EAAA,EAAI,SAAA;AAAA,IACJ,EAAA,EAAI,WAAA;AAAA,IACJ,EAAA,EAAI;AAAA,GACN;AAGA,EAAA,MAAM,eAAA,GAAkB;AAAA,IACtB,EAAA,EAAI,SAAA;AAAA,IACJ,EAAA,EAAI,SAAA;AAAA,IACJ,EAAA,EAAI;AAAA,GACN;AAGA,EAAA,IAAI,YAAY,MAAA,EAAQ;AACtB,IAAA,uBACEA,GAAAA;AAAA,MAAC,QAAA;AAAA,MAAA;AAAA,QACC,IAAA,EAAK,QAAA;AAAA,QACL,OAAA,EAAS,WAAA;AAAA,QACT,SAAA,EAAW,EAAA;AAAA,UACT,mIAAA;AAAA,UACA,YAAY,IAAI,CAAA;AAAA,UAChB;AAAA,SACF;AAAA,QACA,YAAA,EAAY,aAAA,KAAkB,MAAA,GAAS,uBAAA,GAA0B,sBAAA;AAAA,QAChE,GAAG,KAAA;AAAA,QAEH,QAAA,EAAA,aAAA,KAAkB,yBACjBA,GAAAA,CAAC,WAAQ,IAAA,EAAM,QAAA,CAAS,IAAI,CAAA,EAAG,MAAA,EAAQ,KAAK,CAAA,mBAE5CA,IAAC,QAAA,EAAA,EAAS,IAAA,EAAM,SAAS,IAAI,CAAA,EAAG,QAAQ,GAAA,EAAK;AAAA;AAAA,KAEjD;AAAA,EAEJ;AAGA,EAAA,IAAI,YAAY,QAAA,EAAU;AACxB,IAAA,uBACEA,GAAAA;AAAA,MAAC,QAAA;AAAA,MAAA;AAAA,QACC,IAAA,EAAK,QAAA;AAAA,QACL,OAAA,EAAS,WAAA;AAAA,QACT,SAAA,EAAW,EAAA;AAAA,UACT,gGAAA;AAAA,UACA,gBAAgB,IAAI,CAAA;AAAA,UACpB,8CAAA;AAAA,UACA;AAAA,SACF;AAAA,QACC,GAAG,KAAA;AAAA,QAEH,QAAA,EAAA,aAAA,KAAkB,SAAS,YAAA,GAAe;AAAA;AAAA,KAC7C;AAAA,EAEJ;AAGA,EAAA,uBACEA,GAAAA;AAAA,IAAC,QAAA;AAAA,IAAA;AAAA,MACC,IAAA,EAAK,QAAA;AAAA,MACL,OAAA,EAAS,WAAA;AAAA,MACT,SAAA,EAAW,EAAA;AAAA,QACT,oKAAA;AAAA,QACA,gBAAgB,IAAI,CAAA;AAAA,QACpB,aAAA,KAAkB,SACd,qDAAA,GACA,kDAAA;AAAA,QACJ;AAAA,OACF;AAAA,MACA,YAAA,EAAY,aAAA,KAAkB,MAAA,GAAS,uBAAA,GAA0B,sBAAA;AAAA,MAChE,GAAG,KAAA;AAAA,MAEH,QAAA,EAAA,aAAA,KAAkB,MAAA,mBACjB,IAAA,CAAC,MAAA,EAAA,EAAK,WAAU,mBAAA,EACd,QAAA,EAAA;AAAA,wBAAAA,GAAAA,CAAC,WAAQ,IAAA,EAAM,QAAA,CAAS,IAAI,CAAA,EAAG,MAAA,EAAQ,GAAA,EAAK,SAAA,EAAU,MAAA,EAAO,CAAA;AAAA,QAAE;AAAA,OAAA,EAEjE,CAAA,mBAEA,IAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,mBAAA,EACd,QAAA,EAAA;AAAA,wBAAAA,GAAAA,CAAC,YAAS,IAAA,EAAM,QAAA,CAAS,IAAI,CAAA,EAAG,MAAA,EAAQ,GAAA,EAAK,SAAA,EAAU,MAAA,EAAO,CAAA;AAAA,QAAE;AAAA,OAAA,EAElE;AAAA;AAAA,GAEJ;AAEJ","file":"index.mjs","sourcesContent":["\"use client\"\n\nimport * as React from \"react\"\nimport { ThemeProvider as NextThemesProvider } from \"next-themes\"\nimport type { ThemeProviderProps } from \"next-themes/dist/types\"\n\n/**\n * ThemeProvider component for handling theme state\n * \n * This wraps the next-themes provider with sensible defaults\n * for handling light/dark themes and system preferences\n */\nexport function ThemeProvider({ \n children, \n ...props \n}: ThemeProviderProps) {\n return (\n <NextThemesProvider\n attribute=\"class\"\n defaultTheme=\"system\"\n enableSystem\n disableTransitionOnChange\n {...props}\n >\n {children}\n </NextThemesProvider>\n )\n}","/**\n * Utility functions for theme handling\n */\n\n/**\n * Supported color theme values\n */\nexport type ThemeColor = 'brand' | 'error' | 'warning' | 'success';\n\n/**\n * Supported component variant types\n */\nexport type ComponentVariant = 'primary' | 'secondary' | 'tertiary';\n\n/**\n * Map design system colors to shadcn variants\n * \n * @param color - The design system color\n * @returns The corresponding shadcn variant\n */\nexport const mapColorToShadcnVariant = (color: ThemeColor) => {\n switch (color) {\n case 'brand': return 'default';\n case 'error': return 'destructive';\n case 'warning':\n case 'success':\n return 'secondary'; // Will need additional classes\n default: return 'default';\n }\n};\n\n/**\n * Map design system variants to shadcn variants\n * \n * @param variant - The design system variant\n * @returns The corresponding shadcn variant\n */\nexport const mapVariantToShadcnVariant = (variant: ComponentVariant) => {\n switch (variant) {\n case 'primary': return 'default';\n case 'secondary': return 'outline';\n case 'tertiary': return 'ghost';\n default: return 'default';\n }\n};\n\n/**\n * Generate Tailwind classes for color/variant combinations\n * \n * @param color - The design system color\n * @param variant - The design system variant\n * @returns String of Tailwind classes\n */\nexport const getColorVariantClasses = (\n color: ThemeColor, \n variant: ComponentVariant\n): string => {\n const colorVariantMap: Record<ComponentVariant, Record<ThemeColor, string>> = {\n primary: {\n brand: 'bg-brand-600 hover:bg-brand-700 text-white focus-visible:ring-brand-500',\n error: 'bg-error-600 hover:bg-error-700 text-white focus-visible:ring-error-500',\n warning: 'bg-warning-600 hover:bg-warning-700 text-white focus-visible:ring-warning-500',\n success: 'bg-success-600 hover:bg-success-700 text-white focus-visible:ring-success-500',\n },\n secondary: {\n brand: 'border-brand-300 text-brand-700 hover:bg-brand-50 focus-visible:ring-brand-500',\n error: 'border-error-300 text-error-700 hover:bg-error-50 focus-visible:ring-error-500',\n warning: 'border-warning-300 text-warning-700 hover:bg-warning-50 focus-visible:ring-warning-500',\n success: 'border-success-300 text-success-700 hover:bg-success-50 focus-visible:ring-success-500',\n },\n tertiary: {\n brand: 'text-brand-700 hover:bg-brand-50 focus-visible:ring-brand-500',\n error: 'text-error-700 hover:bg-error-50 focus-visible:ring-error-500',\n warning: 'text-warning-700 hover:bg-warning-50 focus-visible:ring-warning-500',\n success: 'text-success-700 hover:bg-success-50 focus-visible:ring-success-500',\n }\n };\n\n return colorVariantMap[variant]?.[color] || '';\n};\n\n/**\n * Determine if the current theme is dark\n * \n * @param theme - The current theme\n * @param systemTheme - The system theme\n * @returns True if the theme is dark\n */\nexport const isDarkTheme = (theme: string | undefined, systemTheme: string | undefined): boolean => {\n if (theme === 'system') {\n return systemTheme === 'dark';\n }\n return theme === 'dark';\n};","\"use client\"\n\nimport { useTheme as useNextTheme } from \"next-themes\"\nimport { isDarkTheme } from \"../lib/theme-utils\"\n\n/**\n * Enhanced useTheme hook that works directly with next-themes\n * \n * This hook provides a simplified interface to next-themes with additional\n * utility properties for better compatibility with Next.js App Router\n */\nexport function useTheme() {\n const { theme, setTheme, resolvedTheme, systemTheme } = useNextTheme();\n \n // Determine if the theme is dark\n const isDark = isDarkTheme(theme, systemTheme);\n \n return {\n theme: theme || \"system\",\n setTheme,\n resolvedTheme: resolvedTheme || \"light\",\n isDark,\n };\n}\n\n/**\n * @deprecated Use ThemeProvider from './theme-provider' instead\n * This component is kept for backward compatibility but is no longer needed\n */\nexport function ThemeContextProvider({ \n children \n}: { \n children: React.ReactNode \n}) {\n // This is now a no-op wrapper for backward compatibility\n return <>{children}</>;\n}","import { clsx, type ClassValue } from 'clsx';\nimport { twMerge } from 'tailwind-merge';\n\n/**\n * Combines multiple class values into a single className string\n * with proper Tailwind CSS class merging.\n * \n * @param inputs - Class values to merge\n * @returns Merged className string\n */\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs));\n}\n\n/**\n * Utility function to generate a unique ID.\n * Useful for ensuring unique IDs for form elements.\n * \n * @param prefix - Optional prefix for the ID\n * @returns A unique ID string\n */\nexport function generateId(prefix = 'id'): string {\n const randomId = Math.random().toString(36).substring(2, 9);\n return `${prefix}-${randomId}`;\n}\n\n/**\n * Type guard to check if a value is not null or undefined\n * \n * @param value - Value to check\n * @returns True if value is not null or undefined\n */\nexport function isNotNullOrUndefined<T>(value: T | null | undefined): value is T {\n return value !== null && value !== undefined;\n}\n\n/**\n * Returns only the props that are safe to spread onto a DOM element\n * by filtering out custom props\n * \n * @param props - The props object\n * @param propNames - Names of custom props to filter out\n * @returns Object with only DOM-safe props\n */\nexport function filterDOMProps<T extends Record<string, any>, K extends keyof T>(\n props: T, \n propNames: K[]\n): Omit<T, K> {\n const result = { ...props };\n propNames.forEach(name => delete result[name]);\n return result;\n}","\"use client\"\n\nimport * as React from \"react\"\nimport { useTheme } from \"../../../themes/theme-context\"\nimport { cn } from \"../../../lib/utils\"\nimport { IconMoon, IconSun } from \"@tabler/icons-react\"\n\n/**\n * Props for the ThemeToggle component\n */\nexport interface ThemeToggleProps extends React.HTMLAttributes<HTMLButtonElement> {\n /**\n * Variant of the toggle\n * @default 'icon'\n */\n variant?: 'icon' | 'switch' | 'button';\n \n /**\n * Size of the toggle\n * @default 'md'\n */\n size?: 'sm' | 'md' | 'lg';\n}\n\n/**\n * ThemeToggle component to switch between light and dark themes\n */\nexport function ThemeToggle({ \n className, \n variant = 'icon', \n size = 'md',\n ...props \n}: ThemeToggleProps) {\n const { theme, setTheme, resolvedTheme } = useTheme()\n const [mounted, setMounted] = React.useState(false)\n\n // Handle hydration mismatch\n React.useEffect(() => {\n setMounted(true)\n }, [])\n\n // Only render on client to prevent hydration mismatch\n if (!mounted) return null;\n\n // Toggle between light and dark\n const toggleTheme = () => {\n setTheme(resolvedTheme === \"dark\" ? \"light\" : \"dark\")\n }\n\n // Size mapping for Tabler icons\n const iconSize = {\n sm: 16,\n md: 20,\n lg: 24,\n }\n\n // Size classes for button\n const sizeClasses = {\n sm: 'h-8 w-8',\n md: 'h-10 w-10',\n lg: 'h-12 w-12',\n }\n\n // Text size classes\n const textSizeClasses = {\n sm: 'text-xs',\n md: 'text-sm',\n lg: 'text-base',\n }\n\n // Variant specific rendering\n if (variant === 'icon') {\n return (\n <button\n type=\"button\"\n onClick={toggleTheme}\n className={cn(\n \"inline-flex items-center justify-center rounded-md border border-input bg-background hover:bg-accent hover:text-accent-foreground\",\n sizeClasses[size],\n className\n )}\n aria-label={resolvedTheme === \"dark\" ? \"Switch to light theme\" : \"Switch to dark theme\"}\n {...props}\n >\n {resolvedTheme === \"dark\" ? (\n <IconSun size={iconSize[size]} stroke={1.5} />\n ) : (\n <IconMoon size={iconSize[size]} stroke={1.5} />\n )}\n </button>\n )\n }\n \n // Button variant\n if (variant === 'button') {\n return (\n <button\n type=\"button\"\n onClick={toggleTheme}\n className={cn(\n \"inline-flex items-center justify-center rounded-md border border-input bg-background px-4 py-2\",\n textSizeClasses[size],\n \"hover:bg-accent hover:text-accent-foreground\",\n className\n )}\n {...props}\n >\n {resolvedTheme === \"dark\" ? \"Light Mode\" : \"Dark Mode\"}\n </button>\n )\n }\n \n // Switch variant\n return (\n <button\n type=\"button\"\n onClick={toggleTheme}\n className={cn(\n \"inline-flex items-center justify-center rounded-md px-3 py-2 font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring\",\n textSizeClasses[size],\n resolvedTheme === \"dark\" \n ? \"bg-accent text-accent-foreground hover:bg-accent/80\" \n : \"bg-muted text-muted-foreground hover:bg-muted/80\",\n className\n )}\n aria-label={resolvedTheme === \"dark\" ? \"Switch to light theme\" : \"Switch to dark theme\"}\n {...props}\n >\n {resolvedTheme === \"dark\" ? (\n <span className=\"flex items-center\">\n <IconSun size={iconSize[size]} stroke={1.5} className=\"mr-2\" />\n Light\n </span>\n ) : (\n <span className=\"flex items-center\">\n <IconMoon size={iconSize[size]} stroke={1.5} className=\"mr-2\" />\n Dark\n </span>\n )}\n </button>\n )\n}"]}
1
+ {"version":3,"sources":["../../src/themes/theme-provider.tsx","../../src/lib/theme-utils.ts","../../src/themes/theme-context.tsx","../../src/lib/utils.ts","../../src/components/ui/theme-toggle/theme-toggle.tsx","../../src/components/ui/theme-toggle/index.ts","../../src/themes/index.ts","../../src/themes/dynamic-imports.tsx"],"names":["NextThemesProvider","useNextTheme","jsx","Fragment","React2","init_theme_toggle"],"mappings":"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","file":"index.mjs","sourcesContent":["\"use client\"\n\nimport * as React from \"react\"\nimport { ThemeProvider as NextThemesProvider } from \"next-themes\"\nimport type { ThemeProviderProps } from \"next-themes/dist/types\"\n\n/**\n * ThemeProvider component for handling theme state\n * \n * This wraps the next-themes provider with sensible defaults\n * for handling light/dark themes and system preferences\n * \n * IMPORTANT: This component must be used in a Client Component context.\n * For Server Components, use the NoSSR wrapper or dynamic imports.\n */\nexport function ThemeProvider({ \n children, \n ...props \n}: ThemeProviderProps) {\n // Ensure we're in a client environment\n if (typeof window === 'undefined') {\n // Return children without theme provider in SSR\n return <>{children}</>;\n }\n\n return (\n <NextThemesProvider\n attribute=\"class\"\n defaultTheme=\"system\"\n enableSystem\n disableTransitionOnChange\n {...props}\n >\n {children}\n </NextThemesProvider>\n )\n}\n\n/**\n * NoSSR wrapper for theme provider to prevent SSR issues\n * Use this when you need to ensure the theme provider only renders on the client\n */\nexport function ThemeProviderNoSSR({ \n children, \n ...props \n}: ThemeProviderProps) {\n const [mounted, setMounted] = React.useState(false);\n\n React.useEffect(() => {\n setMounted(true);\n }, []);\n\n if (!mounted) {\n return <>{children}</>;\n }\n\n return (\n <ThemeProvider {...props}>\n {children}\n </ThemeProvider>\n );\n}","/**\n * Utility functions for theme handling\n */\n\n/**\n * Supported color theme values\n */\nexport type ThemeColor = 'brand' | 'error' | 'warning' | 'success';\n\n/**\n * Supported component variant types\n */\nexport type ComponentVariant = 'primary' | 'secondary' | 'tertiary';\n\n/**\n * Map design system colors to shadcn variants\n * \n * @param color - The design system color\n * @returns The corresponding shadcn variant\n */\nexport const mapColorToShadcnVariant = (color: ThemeColor) => {\n switch (color) {\n case 'brand': return 'default';\n case 'error': return 'destructive';\n case 'warning':\n case 'success':\n return 'secondary'; // Will need additional classes\n default: return 'default';\n }\n};\n\n/**\n * Map design system variants to shadcn variants\n * \n * @param variant - The design system variant\n * @returns The corresponding shadcn variant\n */\nexport const mapVariantToShadcnVariant = (variant: ComponentVariant) => {\n switch (variant) {\n case 'primary': return 'default';\n case 'secondary': return 'outline';\n case 'tertiary': return 'ghost';\n default: return 'default';\n }\n};\n\n/**\n * Generate Tailwind classes for color/variant combinations\n * \n * @param color - The design system color\n * @param variant - The design system variant\n * @returns String of Tailwind classes\n */\nexport const getColorVariantClasses = (\n color: ThemeColor, \n variant: ComponentVariant\n): string => {\n const colorVariantMap: Record<ComponentVariant, Record<ThemeColor, string>> = {\n primary: {\n brand: 'bg-brand-600 hover:bg-brand-700 text-white focus-visible:ring-brand-500',\n error: 'bg-error-600 hover:bg-error-700 text-white focus-visible:ring-error-500',\n warning: 'bg-warning-600 hover:bg-warning-700 text-white focus-visible:ring-warning-500',\n success: 'bg-success-600 hover:bg-success-700 text-white focus-visible:ring-success-500',\n },\n secondary: {\n brand: 'border-brand-300 text-brand-700 hover:bg-brand-50 focus-visible:ring-brand-500',\n error: 'border-error-300 text-error-700 hover:bg-error-50 focus-visible:ring-error-500',\n warning: 'border-warning-300 text-warning-700 hover:bg-warning-50 focus-visible:ring-warning-500',\n success: 'border-success-300 text-success-700 hover:bg-success-50 focus-visible:ring-success-500',\n },\n tertiary: {\n brand: 'text-brand-700 hover:bg-brand-50 focus-visible:ring-brand-500',\n error: 'text-error-700 hover:bg-error-50 focus-visible:ring-error-500',\n warning: 'text-warning-700 hover:bg-warning-50 focus-visible:ring-warning-500',\n success: 'text-success-700 hover:bg-success-50 focus-visible:ring-success-500',\n }\n };\n\n return colorVariantMap[variant]?.[color] || '';\n};\n\n/**\n * Determine if the current theme is dark\n * \n * @param theme - The current theme\n * @param systemTheme - The system theme\n * @returns True if the theme is dark\n */\nexport const isDarkTheme = (theme: string | undefined, systemTheme: string | undefined): boolean => {\n if (theme === 'system') {\n return systemTheme === 'dark';\n }\n return theme === 'dark';\n};","\"use client\"\n\nimport { useTheme as useNextTheme } from \"next-themes\"\nimport { isDarkTheme } from \"../lib/theme-utils\"\n\n/**\n * Enhanced useTheme hook that works directly with next-themes\n * \n * This hook provides a simplified interface to next-themes with additional\n * utility properties for better compatibility with Next.js App Router\n * \n * IMPORTANT: This hook must be used within a Client Component.\n * For Server Components, use the useThemeServer hook instead.\n */\nexport function useTheme() {\n // Ensure we're in a client environment\n if (typeof window === 'undefined') {\n // Return default values for SSR\n return {\n theme: \"system\",\n setTheme: () => {},\n resolvedTheme: \"light\",\n isDark: false,\n };\n }\n\n const { theme, setTheme, resolvedTheme, systemTheme } = useNextTheme();\n \n // Determine if the theme is dark\n const isDark = isDarkTheme(theme, systemTheme);\n \n return {\n theme: theme || \"system\",\n setTheme,\n resolvedTheme: resolvedTheme || \"light\",\n isDark,\n };\n}\n\n/**\n * Server-safe theme hook that can be used in Server Components\n * Returns default theme values without accessing client-side APIs\n */\nexport function useThemeServer() {\n return {\n theme: \"system\",\n setTheme: () => {},\n resolvedTheme: \"light\",\n isDark: false,\n };\n}\n\n/**\n * @deprecated Use ThemeProvider from './theme-provider' instead\n * This component is kept for backward compatibility but is no longer needed\n */\nexport function ThemeContextProvider({ \n children \n}: { \n children: React.ReactNode \n}) {\n // This is now a no-op wrapper for backward compatibility\n return <>{children}</>;\n}","import { clsx, type ClassValue } from 'clsx';\nimport { twMerge } from 'tailwind-merge';\n\n/**\n * Combines multiple class values into a single className string\n * with proper Tailwind CSS class merging.\n * \n * @param inputs - Class values to merge\n * @returns Merged className string\n */\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs));\n}\n\n/**\n * Utility function to generate a unique ID.\n * Useful for ensuring unique IDs for form elements.\n * \n * @param prefix - Optional prefix for the ID\n * @returns A unique ID string\n */\nexport function generateId(prefix = 'id'): string {\n const randomId = Math.random().toString(36).substring(2, 9);\n return `${prefix}-${randomId}`;\n}\n\n/**\n * Type guard to check if a value is not null or undefined\n * \n * @param value - Value to check\n * @returns True if value is not null or undefined\n */\nexport function isNotNullOrUndefined<T>(value: T | null | undefined): value is T {\n return value !== null && value !== undefined;\n}\n\n/**\n * Returns only the props that are safe to spread onto a DOM element\n * by filtering out custom props\n * \n * @param props - The props object\n * @param propNames - Names of custom props to filter out\n * @returns Object with only DOM-safe props\n */\nexport function filterDOMProps<T extends Record<string, any>, K extends keyof T>(\n props: T, \n propNames: K[]\n): Omit<T, K> {\n const result = { ...props };\n propNames.forEach(name => delete result[name]);\n return result;\n}","\"use client\"\n\nimport * as React from \"react\"\nimport { useTheme } from \"../../../themes/theme-context\"\nimport { cn } from \"../../../lib/utils\"\nimport { IconMoon, IconSun } from \"@tabler/icons-react\"\n\n/**\n * Props for the ThemeToggle component\n */\nexport interface ThemeToggleProps extends React.HTMLAttributes<HTMLButtonElement> {\n /**\n * Variant of the toggle\n * @default 'icon'\n */\n variant?: 'icon' | 'switch' | 'button';\n \n /**\n * Size of the toggle\n * @default 'md'\n */\n size?: 'sm' | 'md' | 'lg';\n}\n\n/**\n * ThemeToggle component to switch between light and dark themes\n */\nexport function ThemeToggle({ \n className, \n variant = 'icon', \n size = 'md',\n ...props \n}: ThemeToggleProps) {\n const { theme, setTheme, resolvedTheme } = useTheme()\n const [mounted, setMounted] = React.useState(false)\n\n // Handle hydration mismatch\n React.useEffect(() => {\n setMounted(true)\n }, [])\n\n // Only render on client to prevent hydration mismatch\n if (!mounted) return null;\n\n // Toggle between light and dark\n const toggleTheme = () => {\n setTheme(resolvedTheme === \"dark\" ? \"light\" : \"dark\")\n }\n\n // Size mapping for Tabler icons\n const iconSize = {\n sm: 16,\n md: 20,\n lg: 24,\n }\n\n // Size classes for button\n const sizeClasses = {\n sm: 'h-8 w-8',\n md: 'h-10 w-10',\n lg: 'h-12 w-12',\n }\n\n // Text size classes\n const textSizeClasses = {\n sm: 'text-xs',\n md: 'text-sm',\n lg: 'text-base',\n }\n\n // Variant specific rendering\n if (variant === 'icon') {\n return (\n <button\n type=\"button\"\n onClick={toggleTheme}\n className={cn(\n \"inline-flex items-center justify-center rounded-md border border-input bg-background hover:bg-accent hover:text-accent-foreground\",\n sizeClasses[size],\n className\n )}\n aria-label={resolvedTheme === \"dark\" ? \"Switch to light theme\" : \"Switch to dark theme\"}\n {...props}\n >\n {resolvedTheme === \"dark\" ? (\n <IconSun size={iconSize[size]} stroke={1.5} />\n ) : (\n <IconMoon size={iconSize[size]} stroke={1.5} />\n )}\n </button>\n )\n }\n \n // Button variant\n if (variant === 'button') {\n return (\n <button\n type=\"button\"\n onClick={toggleTheme}\n className={cn(\n \"inline-flex items-center justify-center rounded-md border border-input bg-background px-4 py-2\",\n textSizeClasses[size],\n \"hover:bg-accent hover:text-accent-foreground\",\n className\n )}\n {...props}\n >\n {resolvedTheme === \"dark\" ? \"Light Mode\" : \"Dark Mode\"}\n </button>\n )\n }\n \n // Switch variant\n return (\n <button\n type=\"button\"\n onClick={toggleTheme}\n className={cn(\n \"inline-flex items-center justify-center rounded-md px-3 py-2 font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring\",\n textSizeClasses[size],\n resolvedTheme === \"dark\" \n ? \"bg-accent text-accent-foreground hover:bg-accent/80\" \n : \"bg-muted text-muted-foreground hover:bg-muted/80\",\n className\n )}\n aria-label={resolvedTheme === \"dark\" ? \"Switch to light theme\" : \"Switch to dark theme\"}\n {...props}\n >\n {resolvedTheme === \"dark\" ? (\n <span className=\"flex items-center\">\n <IconSun size={iconSize[size]} stroke={1.5} className=\"mr-2\" />\n Light\n </span>\n ) : (\n <span className=\"flex items-center\">\n <IconMoon size={iconSize[size]} stroke={1.5} className=\"mr-2\" />\n Dark\n </span>\n )}\n </button>\n )\n}","export * from './theme-toggle';","// Theme system exports\nexport { ThemeProvider, ThemeProviderNoSSR } from './theme-provider';\nexport { ThemeContextProvider, useTheme, useThemeServer } from './theme-context';\nexport { ThemeToggle } from '../components/ui/theme-toggle/index';\n\n// Dynamic imports for Server Component compatibility\nexport { \n DynamicThemeProvider, \n DynamicThemeProviderNoSSR, \n DynamicThemeToggle,\n SafeThemeProvider \n} from './dynamic-imports';\n\n// Re-export theme utilities\nexport { isDarkTheme, mapColorToShadcnVariant, mapVariantToShadcnVariant, getColorVariantClasses } from '../lib/theme-utils';\n\n// Export types\nexport type { ThemeColor, ComponentVariant } from '../lib/theme-utils';\n","\"use client\"\n\nimport dynamic from 'next/dynamic'\nimport type { ComponentType } from 'react'\n\n/**\n * Dynamically import theme components to prevent SSR issues\n * Use these imports when you need to use theme components in Server Components\n */\n\n// Dynamic import for ThemeProvider\nexport const DynamicThemeProvider = dynamic(\n () => import('./theme-provider').then(mod => ({ default: mod.ThemeProvider })),\n {\n ssr: false,\n loading: () => <div style={{ visibility: 'hidden' }} />,\n }\n) as ComponentType<any>\n\n// Dynamic import for ThemeProviderNoSSR\nexport const DynamicThemeProviderNoSSR = dynamic(\n () => import('./theme-provider').then(mod => ({ default: mod.ThemeProviderNoSSR })),\n {\n ssr: false,\n loading: () => <div style={{ visibility: 'hidden' }} />,\n }\n) as ComponentType<any>\n\n// Dynamic import for ThemeToggle\nexport const DynamicThemeToggle = dynamic(\n () => import('../components/ui/theme-toggle').then(mod => ({ default: mod.ThemeToggle })),\n {\n ssr: false,\n loading: () => <div style={{ visibility: 'hidden' }} />,\n }\n) as ComponentType<any>\n\n/**\n * Safe theme provider for Next.js App Router\n * Automatically handles Server Component compatibility\n */\nexport function SafeThemeProvider({ \n children, \n noSSR = false,\n ...props \n}: {\n children: React.ReactNode\n noSSR?: boolean\n [key: string]: any\n}) {\n if (noSSR) {\n return <DynamicThemeProviderNoSSR {...props}>{children}</DynamicThemeProviderNoSSR>\n }\n \n return <DynamicThemeProvider {...props}>{children}</DynamicThemeProvider>\n} "]}
@@ -95,9 +95,32 @@ module.exports = {
95
95
 
96
96
  ### Next.js App Router
97
97
 
98
+ **Option 1: Safe Theme Provider (Recommended)**
98
99
  ```tsx
99
100
  // app/layout.tsx
100
- import { ThemeProvider } from '@tydavidson/design-system/themes';
101
+ import { SafeThemeProvider } from '@tydavidson/design-system/themes';
102
+
103
+ export default function RootLayout({
104
+ children,
105
+ }: {
106
+ children: React.ReactNode;
107
+ }) {
108
+ return (
109
+ <html lang="en" suppressHydrationWarning>
110
+ <body>
111
+ <SafeThemeProvider>
112
+ {children}
113
+ </SafeThemeProvider>
114
+ </body>
115
+ </html>
116
+ );
117
+ }
118
+ ```
119
+
120
+ **Option 2: NoSSR Theme Provider**
121
+ ```tsx
122
+ // app/layout.tsx
123
+ import { ThemeProviderNoSSR } from '@tydavidson/design-system/themes';
101
124
 
102
125
  export default function RootLayout({
103
126
  children,
@@ -107,9 +130,31 @@ export default function RootLayout({
107
130
  return (
108
131
  <html lang="en" suppressHydrationWarning>
109
132
  <body>
110
- <ThemeProvider>
133
+ <ThemeProviderNoSSR>
111
134
  {children}
112
- </ThemeProvider>
135
+ </ThemeProviderNoSSR>
136
+ </body>
137
+ </html>
138
+ );
139
+ }
140
+ ```
141
+
142
+ **Option 3: Dynamic Import (For Server Components)**
143
+ ```tsx
144
+ // app/layout.tsx
145
+ import { DynamicThemeProvider } from '@tydavidson/design-system/themes';
146
+
147
+ export default function RootLayout({
148
+ children,
149
+ }: {
150
+ children: React.ReactNode;
151
+ }) {
152
+ return (
153
+ <html lang="en" suppressHydrationWarning>
154
+ <body>
155
+ <DynamicThemeProvider>
156
+ {children}
157
+ </DynamicThemeProvider>
113
158
  </body>
114
159
  </html>
115
160
  );
@@ -185,9 +230,61 @@ function MyPage() {
185
230
  }
186
231
  ```
187
232
 
233
+ ## Server Component Compatibility
234
+
235
+ ### Using Theme System in Server Components
236
+
237
+ The design system provides several options for using theme functionality in Next.js App Router Server Components:
238
+
239
+ **For Server Components:**
240
+ ```tsx
241
+ // Use the server-safe hook
242
+ import { useThemeServer } from '@tydavidson/design-system/themes';
243
+
244
+ export default function ServerComponent() {
245
+ const { theme, isDark } = useThemeServer();
246
+
247
+ return (
248
+ <div className={isDark ? 'dark' : 'light'}>
249
+ Current theme: {theme}
250
+ </div>
251
+ );
252
+ }
253
+ ```
254
+
255
+ **For Client Components:**
256
+ ```tsx
257
+ 'use client';
258
+ import { useTheme } from '@tydavidson/design-system/themes';
259
+
260
+ export default function ClientComponent() {
261
+ const { theme, setTheme, isDark } = useTheme();
262
+
263
+ return (
264
+ <button onClick={() => setTheme('dark')}>
265
+ Switch to Dark Mode
266
+ </button>
267
+ );
268
+ }
269
+ ```
270
+
271
+ **Dynamic Theme Toggle in Server Components:**
272
+ ```tsx
273
+ import { DynamicThemeToggle } from '@tydavidson/design-system/themes';
274
+
275
+ export default function ServerComponent() {
276
+ return (
277
+ <div>
278
+ <h1>My Page</h1>
279
+ <DynamicThemeToggle />
280
+ </div>
281
+ );
282
+ }
283
+ ```
284
+
188
285
  ## Common Issues and Solutions
189
286
 
190
- ### 1. Hydration Mismatch Errors
287
+ ### 1. React Context Errors in Server Components
191
288
 
192
289
  **Problem**: Server-side rendering doesn't match client-side rendering.
193
290
 
@@ -14,12 +14,30 @@ Quick solutions for common issues when using the Float Design System.
14
14
 
15
15
  ### React Context errors in Next.js App Router
16
16
 
17
- **Problem**: `Error: useTheme must be used within a ThemeContextProvider`
17
+ **Problem**: `Error: useTheme must be used within a ThemeContextProvider` or `createContext is not a function`
18
18
 
19
19
  **Solution**:
20
- 1. Use version 1.1.4 or later (this was fixed)
21
- 2. Make sure you're using `ThemeProvider` (not `ThemeContextProvider`)
22
- 3. Ensure the provider wraps your app correctly
20
+ 1. Use version 1.1.8 or later (Server Component compatibility added)
21
+ 2. Use `SafeThemeProvider` instead of `ThemeProvider` in your root layout
22
+ 3. For Server Components, use `useThemeServer` instead of `useTheme`
23
+ 4. For dynamic theme toggles in Server Components, use `DynamicThemeToggle`
24
+
25
+ ```tsx
26
+ // app/layout.tsx - Use SafeThemeProvider
27
+ import { SafeThemeProvider } from '@tydavidson/design-system/themes';
28
+
29
+ export default function RootLayout({ children }) {
30
+ return (
31
+ <html lang="en" suppressHydrationWarning>
32
+ <body>
33
+ <SafeThemeProvider>
34
+ {children}
35
+ </SafeThemeProvider>
36
+ </body>
37
+ </html>
38
+ );
39
+ }
40
+ ```
23
41
 
24
42
  ### Hydration mismatch errors
25
43
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tydavidson/design-system",
3
- "version": "1.1.7",
3
+ "version": "1.1.8",
4
4
  "description": "Float Design System with email components and theme system",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",