@stackwright/themes 0.4.0 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,19 +1,389 @@
1
1
  "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+
30
+ // src/index.ts
31
+ var index_exports = {};
32
+ __export(index_exports, {
33
+ ColorModeScript: () => ColorModeScript,
34
+ ThemeLoader: () => ThemeLoader,
35
+ ThemeProvider: () => ThemeProvider,
36
+ ThemeStyleInjector: () => ThemeStyleInjector,
37
+ colorsSchema: () => colorsSchema,
38
+ componentStyleSchema: () => componentStyleSchema,
39
+ themeConfigSchema: () => themeConfigSchema,
40
+ themeSchema: () => themeSchema,
41
+ themeToCSSVars: () => themeToCSSVars,
42
+ useTheme: () => useTheme,
43
+ useThemeOptional: () => useThemeOptional
44
+ });
45
+ module.exports = __toCommonJS(index_exports);
46
+
47
+ // src/types.ts
48
+ var import_zod = require("zod");
49
+ var componentStyleSchema = import_zod.z.object({
50
+ base: import_zod.z.string().optional(),
51
+ primary: import_zod.z.string().optional(),
52
+ secondary: import_zod.z.string().optional(),
53
+ outline: import_zod.z.string().optional(),
54
+ shadow: import_zod.z.string().optional(),
55
+ nav: import_zod.z.string().optional(),
56
+ text: import_zod.z.string().optional()
57
+ }).catchall(import_zod.z.string().optional());
58
+ var colorsSchema = import_zod.z.object({
59
+ primary: import_zod.z.string(),
60
+ secondary: import_zod.z.string(),
61
+ accent: import_zod.z.string(),
62
+ background: import_zod.z.string(),
63
+ surface: import_zod.z.string(),
64
+ text: import_zod.z.string(),
65
+ textSecondary: import_zod.z.string()
66
+ });
67
+ var themeConfigSchema = import_zod.z.object({
68
+ id: import_zod.z.string(),
69
+ name: import_zod.z.string(),
70
+ description: import_zod.z.string(),
71
+ colors: colorsSchema,
72
+ darkColors: colorsSchema.optional(),
73
+ backgroundImage: import_zod.z.object({
74
+ url: import_zod.z.string(),
75
+ repeat: import_zod.z.enum(["repeat", "repeat-x", "repeat-y", "no-repeat"]).optional(),
76
+ size: import_zod.z.string().optional(),
77
+ position: import_zod.z.string().optional(),
78
+ attachment: import_zod.z.enum(["scroll", "fixed", "local"]).optional(),
79
+ scale: import_zod.z.number().optional(),
80
+ animation: import_zod.z.enum(["drift", "float", "shimmer", "shimmer-float", "none"]).optional(),
81
+ customAnimation: import_zod.z.string().optional()
82
+ }).optional(),
83
+ typography: import_zod.z.object({
84
+ fontFamily: import_zod.z.object({
85
+ primary: import_zod.z.string(),
86
+ secondary: import_zod.z.string()
87
+ }),
88
+ scale: import_zod.z.object({
89
+ xs: import_zod.z.string(),
90
+ sm: import_zod.z.string(),
91
+ base: import_zod.z.string(),
92
+ lg: import_zod.z.string(),
93
+ xl: import_zod.z.string(),
94
+ "2xl": import_zod.z.string(),
95
+ "3xl": import_zod.z.string()
96
+ })
97
+ }),
98
+ spacing: import_zod.z.object({
99
+ xs: import_zod.z.string(),
100
+ sm: import_zod.z.string(),
101
+ md: import_zod.z.string(),
102
+ lg: import_zod.z.string(),
103
+ xl: import_zod.z.string(),
104
+ "2xl": import_zod.z.string()
105
+ }),
106
+ components: import_zod.z.object({
107
+ button: componentStyleSchema.optional(),
108
+ card: componentStyleSchema.optional(),
109
+ header: componentStyleSchema.optional(),
110
+ footer: componentStyleSchema.optional()
111
+ }).optional()
112
+ });
113
+ var themeSchema = themeConfigSchema;
114
+
115
+ // src/ThemeProvider.tsx
116
+ var import_react = require("react");
117
+ var import_jsx_runtime = require("react/jsx-runtime");
118
+ var ThemeContext = (0, import_react.createContext)(void 0);
119
+ var COLOR_MODE_COOKIE = "sw-color-mode";
120
+ function getSystemPreference() {
121
+ if (typeof window === "undefined") return "light";
122
+ return window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
123
+ }
124
+ var useIsomorphicLayoutEffect = typeof window !== "undefined" ? import_react.useLayoutEffect : import_react.useEffect;
125
+ function resolveColors(theme, mode) {
126
+ if (mode === "dark" && theme.darkColors) {
127
+ return theme.darkColors;
128
+ }
129
+ return theme.colors;
130
+ }
131
+ function readCookie(name) {
132
+ if (typeof document === "undefined") return void 0;
133
+ const match = document.cookie.match(new RegExp("(?:^|; )" + name + "=([^;]*)"));
134
+ return match ? decodeURIComponent(match[1]) : void 0;
135
+ }
136
+ function writeCookie(name, value) {
137
+ if (typeof document === "undefined") return;
138
+ const maxAge = 365 * 24 * 60 * 60;
139
+ document.cookie = name + "=" + encodeURIComponent(value) + "; max-age=" + maxAge + "; path=/; SameSite=Lax";
140
+ }
141
+ function deleteCookie(name) {
142
+ if (typeof document === "undefined") return;
143
+ document.cookie = name + "=; max-age=0; path=/";
144
+ }
145
+ var ThemeProvider = ({
146
+ theme: initialTheme,
147
+ children,
148
+ initialColorMode = "system"
149
+ }) => {
150
+ const [rawTheme, setRawTheme] = (0, import_react.useState)(initialTheme);
151
+ const [colorMode, setColorModeState] = (0, import_react.useState)(initialColorMode);
152
+ const [systemPreference, setSystemPreference] = (0, import_react.useState)("light");
153
+ useIsomorphicLayoutEffect(() => {
154
+ const saved = readCookie(COLOR_MODE_COOKIE);
155
+ if (saved === "light" || saved === "dark") {
156
+ setColorModeState(saved);
157
+ }
158
+ const attr = document.documentElement.getAttribute("data-sw-color-mode");
159
+ if (attr === "dark" || attr === "light") {
160
+ setSystemPreference(attr);
161
+ } else {
162
+ setSystemPreference(getSystemPreference());
163
+ }
164
+ }, []);
165
+ (0, import_react.useEffect)(() => {
166
+ if (typeof window === "undefined") return;
167
+ const mql = window.matchMedia("(prefers-color-scheme: dark)");
168
+ const handler = (e) => {
169
+ setSystemPreference(e.matches ? "dark" : "light");
170
+ };
171
+ mql.addEventListener("change", handler);
172
+ return () => mql.removeEventListener("change", handler);
173
+ }, []);
174
+ const setColorMode = (0, import_react.useCallback)((mode) => {
175
+ setColorModeState(mode);
176
+ if (mode === "system") {
177
+ deleteCookie(COLOR_MODE_COOKIE);
178
+ } else {
179
+ writeCookie(COLOR_MODE_COOKIE, mode);
180
+ }
181
+ }, []);
182
+ const resolvedColorMode = colorMode === "system" ? systemPreference : colorMode;
183
+ const theme = (0, import_react.useMemo)(() => {
184
+ const effectiveColors = resolveColors(rawTheme, resolvedColorMode);
185
+ if (effectiveColors === rawTheme.colors) return rawTheme;
186
+ return { ...rawTheme, colors: effectiveColors };
187
+ }, [rawTheme, resolvedColorMode]);
188
+ const setTheme = (0, import_react.useCallback)((t) => setRawTheme(t), []);
189
+ const value = (0, import_react.useMemo)(
190
+ () => ({ theme, rawTheme, setTheme, colorMode, setColorMode, resolvedColorMode }),
191
+ [theme, rawTheme, setTheme, colorMode, setColorMode, resolvedColorMode]
192
+ );
193
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ThemeContext.Provider, { value, children });
194
+ };
195
+ var useTheme = () => {
196
+ const context = (0, import_react.useContext)(ThemeContext);
197
+ if (!context) {
198
+ throw new Error("useTheme must be used within a ThemeProvider");
199
+ }
200
+ return context;
201
+ };
202
+ var useThemeOptional = () => {
203
+ return (0, import_react.useContext)(ThemeContext);
204
+ };
205
+ function themeToCSSVars(theme) {
206
+ return {
207
+ "--sw-color-primary": theme.colors.primary,
208
+ "--sw-color-secondary": theme.colors.secondary,
209
+ "--sw-color-accent": theme.colors.accent,
210
+ "--sw-color-bg": theme.colors.background,
211
+ "--sw-color-surface": theme.colors.surface,
212
+ "--sw-color-text": theme.colors.text,
213
+ "--sw-color-text-secondary": theme.colors.textSecondary,
214
+ "--sw-font-primary": theme.typography?.fontFamily?.primary ?? "sans-serif",
215
+ "--sw-font-secondary": theme.typography?.fontFamily?.secondary ?? "sans-serif",
216
+ "--sw-spacing-xs": theme.spacing?.xs ?? "0.25rem",
217
+ "--sw-spacing-sm": theme.spacing?.sm ?? "0.5rem",
218
+ "--sw-spacing-md": theme.spacing?.md ?? "1rem",
219
+ "--sw-spacing-lg": theme.spacing?.lg ?? "1.5rem",
220
+ "--sw-spacing-xl": theme.spacing?.xl ?? "2rem",
221
+ "--sw-spacing-2xl": theme.spacing?.["2xl"] ?? "3rem"
222
+ };
223
+ }
224
+ function ThemeStyleInjector({
225
+ theme: themeProp,
226
+ children,
227
+ className
228
+ }) {
229
+ const ctx = useThemeOptional();
230
+ const theme = themeProp ?? ctx?.theme;
231
+ if (!theme) {
232
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_jsx_runtime.Fragment, { children });
233
+ }
234
+ const cssVars = themeToCSSVars(theme);
235
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className, style: cssVars, children });
236
+ }
237
+
238
+ // src/themeLoader.ts
239
+ var yaml = __toESM(require("js-yaml"));
240
+ var ThemeLoader = class {
241
+ static themes = /* @__PURE__ */ new Map();
242
+ static loadThemeFromYaml(yamlContent) {
243
+ try {
244
+ const theme = yaml.load(yamlContent);
245
+ this.themes.set(theme.name, theme);
246
+ return theme;
247
+ } catch (error) {
248
+ throw new Error(`Failed to parse theme YAML: ${error}`);
7
249
  }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
- for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
250
+ }
251
+ static loadThemeFromFile(themeName) {
252
+ const themeData = this.getEmbeddedTheme(themeName);
253
+ return this.loadThemeFromYaml(themeData);
254
+ }
255
+ static getTheme(name) {
256
+ return this.themes.get(name);
257
+ }
258
+ static getAllThemes() {
259
+ return Array.from(this.themes.values());
260
+ }
261
+ static registerCustomTheme(theme) {
262
+ this.themes.set(theme.name, theme);
263
+ }
264
+ static loadCustomTheme(theme) {
265
+ this.registerCustomTheme(theme);
266
+ return theme;
267
+ }
268
+ static getEmbeddedTheme(name) {
269
+ const themes = {
270
+ corporate: `
271
+ id: "corporate"
272
+ name: "Corporate"
273
+ description: "A professional amber-toned corporate theme"
274
+ colors:
275
+ primary: "#f59e0b"
276
+ secondary: "#334155"
277
+ accent: "#d97706"
278
+ background: "#f8fafc"
279
+ surface: "#ffffff"
280
+ text: "#1f2937"
281
+ textSecondary: "#6b7280"
282
+ darkColors:
283
+ primary: "#fbbf24"
284
+ secondary: "#94a3b8"
285
+ accent: "#f59e0b"
286
+ background: "#0f172a"
287
+ surface: "#1e293b"
288
+ text: "#f1f5f9"
289
+ textSecondary: "#94a3b8"
290
+ typography:
291
+ fontFamily:
292
+ primary: "Roboto, sans-serif"
293
+ secondary: "Roboto, sans-serif"
294
+ scale:
295
+ xs: "0.75rem"
296
+ sm: "0.875rem"
297
+ base: "1rem"
298
+ lg: "1.125rem"
299
+ xl: "1.25rem"
300
+ 2xl: "1.5rem"
301
+ 3xl: "1.875rem"
302
+ spacing:
303
+ xs: "0.5rem"
304
+ sm: "0.75rem"
305
+ md: "1rem"
306
+ lg: "1.5rem"
307
+ xl: "2rem"
308
+ 2xl: "3rem"
309
+ `,
310
+ soft: `
311
+ id: "soft"
312
+ name: "Soft"
313
+ description: "A gentle pink-toned soft theme"
314
+ colors:
315
+ primary: "#ec4899"
316
+ secondary: "#6b7280"
317
+ accent: "#db2777"
318
+ background: "#f9fafb"
319
+ surface: "#ffffff"
320
+ text: "#374151"
321
+ textSecondary: "#9ca3af"
322
+ darkColors:
323
+ primary: "#f472b6"
324
+ secondary: "#9ca3af"
325
+ accent: "#ec4899"
326
+ background: "#111827"
327
+ surface: "#1f2937"
328
+ text: "#f9fafb"
329
+ textSecondary: "#9ca3af"
330
+ typography:
331
+ fontFamily:
332
+ primary: "Roboto, sans-serif"
333
+ secondary: "Roboto, sans-serif"
334
+ scale:
335
+ xs: "0.75rem"
336
+ sm: "0.875rem"
337
+ base: "1rem"
338
+ lg: "1.125rem"
339
+ xl: "1.25rem"
340
+ 2xl: "1.5rem"
341
+ 3xl: "1.875rem"
342
+ spacing:
343
+ xs: "0.5rem"
344
+ sm: "0.75rem"
345
+ md: "1rem"
346
+ lg: "1.5rem"
347
+ xl: "2rem"
348
+ 2xl: "3rem"
349
+ `
350
+ };
351
+ if (!themes[name]) {
352
+ throw new Error(`Theme '${name}' not found`);
353
+ }
354
+ return themes[name];
355
+ }
15
356
  };
16
- Object.defineProperty(exports, "__esModule", { value: true });
17
- __exportStar(require("./types"), exports);
18
- __exportStar(require("./ThemeProvider"), exports);
19
- __exportStar(require("./themeLoader"), exports);
357
+
358
+ // src/ColorModeScript.tsx
359
+ var import_jsx_runtime2 = require("react/jsx-runtime");
360
+ function ColorModeScript({ fallback = "system" }) {
361
+ const scriptContent = `
362
+ (function(){
363
+ try {
364
+ var m = document.cookie.match(/(?:^|; )sw-color-mode=([^;]*)/);
365
+ var mode = m ? m[1] : '${fallback}';
366
+ if (mode === 'system') {
367
+ mode = window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';
368
+ }
369
+ document.documentElement.setAttribute('data-sw-color-mode', mode);
370
+ } catch(e) {}
371
+ })();
372
+ `.trim();
373
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("script", { dangerouslySetInnerHTML: { __html: scriptContent } });
374
+ }
375
+ // Annotate the CommonJS export names for ESM import in node:
376
+ 0 && (module.exports = {
377
+ ColorModeScript,
378
+ ThemeLoader,
379
+ ThemeProvider,
380
+ ThemeStyleInjector,
381
+ colorsSchema,
382
+ componentStyleSchema,
383
+ themeConfigSchema,
384
+ themeSchema,
385
+ themeToCSSVars,
386
+ useTheme,
387
+ useThemeOptional
388
+ });
389
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts","../src/types.ts","../src/ThemeProvider.tsx","../src/themeLoader.ts","../src/ColorModeScript.tsx"],"sourcesContent":["export * from './types';\nexport * from './ThemeProvider';\nexport * from './themeLoader';\nexport * from './ColorModeScript';\nexport type { ThemeConfig, Theme, ComponentStyle, ThemeColors, ColorMode } from './types';\nexport { colorsSchema, componentStyleSchema, themeConfigSchema, themeSchema } from './types';\n","import { z } from 'zod';\n\nexport const componentStyleSchema = z\n .object({\n base: z.string().optional(),\n primary: z.string().optional(),\n secondary: z.string().optional(),\n outline: z.string().optional(),\n shadow: z.string().optional(),\n nav: z.string().optional(),\n text: z.string().optional(),\n })\n .catchall(z.string().optional());\n\nexport const colorsSchema = z.object({\n primary: z.string(),\n secondary: z.string(),\n accent: z.string(),\n background: z.string(),\n surface: z.string(),\n text: z.string(),\n textSecondary: z.string(),\n});\n\nexport type ThemeColors = z.infer<typeof colorsSchema>;\n\nexport type ColorMode = 'light' | 'dark' | 'system';\n\nexport const themeConfigSchema = z.object({\n id: z.string(),\n name: z.string(),\n description: z.string(),\n colors: colorsSchema,\n darkColors: colorsSchema.optional(),\n backgroundImage: z\n .object({\n url: z.string(),\n repeat: z.enum(['repeat', 'repeat-x', 'repeat-y', 'no-repeat']).optional(),\n size: z.string().optional(),\n position: z.string().optional(),\n attachment: z.enum(['scroll', 'fixed', 'local']).optional(),\n scale: z.number().optional(),\n animation: z.enum(['drift', 'float', 'shimmer', 'shimmer-float', 'none']).optional(),\n customAnimation: z.string().optional(),\n })\n .optional(),\n typography: z.object({\n fontFamily: z.object({\n primary: z.string(),\n secondary: z.string(),\n }),\n scale: z.object({\n xs: z.string(),\n sm: z.string(),\n base: z.string(),\n lg: z.string(),\n xl: z.string(),\n '2xl': z.string(),\n '3xl': z.string(),\n }),\n }),\n spacing: z.object({\n xs: z.string(),\n sm: z.string(),\n md: z.string(),\n lg: z.string(),\n xl: z.string(),\n '2xl': z.string(),\n }),\n components: z\n .object({\n button: componentStyleSchema.optional(),\n card: componentStyleSchema.optional(),\n header: componentStyleSchema.optional(),\n footer: componentStyleSchema.optional(),\n })\n .optional(),\n});\n\nexport const themeSchema = themeConfigSchema;\n\nexport type ThemeConfig = z.infer<typeof themeConfigSchema>;\nexport type ComponentStyle = z.infer<typeof componentStyleSchema>;\nexport interface Theme extends ThemeConfig {}\nexport type { ThemeColors as ThemeColorsType };\n","import React, {\n createContext,\n useContext,\n useState,\n useEffect,\n useLayoutEffect,\n useMemo,\n useCallback,\n ReactNode,\n CSSProperties,\n} from 'react';\nimport { Theme, ColorMode, ThemeColors } from './types';\n\n// ---------------------------------------------------------------------------\n// Context\n// ---------------------------------------------------------------------------\n\ninterface ThemeContextType {\n /** The resolved theme — `colors` reflects the active color mode. */\n theme: Theme;\n /** The original theme with both `colors` and `darkColors` intact. */\n rawTheme: Theme;\n setTheme: (theme: Theme) => void;\n /** Current color mode setting (`'light'`, `'dark'`, or `'system'`). */\n colorMode: ColorMode;\n /** Switch the color mode. */\n setColorMode: (mode: ColorMode) => void;\n /** The actually active mode after resolving `'system'`. */\n resolvedColorMode: 'light' | 'dark';\n}\n\nconst ThemeContext = createContext<ThemeContextType | undefined>(undefined);\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nconst COLOR_MODE_COOKIE = 'sw-color-mode';\n\n/** Detect OS-level dark mode preference via `matchMedia`. SSR-safe. */\nfunction getSystemPreference(): 'light' | 'dark' {\n if (typeof window === 'undefined') return 'light';\n return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';\n}\n\n/**\n * SSR-safe `useLayoutEffect`. Falls back to `useEffect` on the server to\n * avoid React warnings, but uses `useLayoutEffect` on the client so that\n * color-mode state updates happen before the browser paints — preventing\n * a visible flash of the wrong theme.\n */\nconst useIsomorphicLayoutEffect = typeof window !== 'undefined' ? useLayoutEffect : useEffect;\n\n/** Pick the effective colors for the given mode. */\nfunction resolveColors(theme: Theme, mode: 'light' | 'dark'): ThemeColors {\n if (mode === 'dark' && theme.darkColors) {\n return theme.darkColors;\n }\n return theme.colors;\n}\n\n/**\n * Read a cookie by name. SSR-safe (returns undefined when no document).\n * Inline to avoid circular dependency on @stackwright/core.\n */\nfunction readCookie(name: string): string | undefined {\n if (typeof document === 'undefined') return undefined;\n const match = document.cookie.match(new RegExp('(?:^|; )' + name + '=([^;]*)'));\n return match ? decodeURIComponent(match[1]) : undefined;\n}\n\n/** Write a cookie. SSR-safe no-op when no document. */\nfunction writeCookie(name: string, value: string): void {\n if (typeof document === 'undefined') return;\n const maxAge = 365 * 24 * 60 * 60;\n document.cookie =\n name + '=' + encodeURIComponent(value) + '; max-age=' + maxAge + '; path=/; SameSite=Lax';\n}\n\n/** Remove a cookie by setting max-age=0. */\nfunction deleteCookie(name: string): void {\n if (typeof document === 'undefined') return;\n document.cookie = name + '=; max-age=0; path=/';\n}\n\n// ---------------------------------------------------------------------------\n// ThemeProvider\n// ---------------------------------------------------------------------------\n\ninterface ThemeProviderProps {\n theme: Theme;\n children: ReactNode;\n /** Initial color mode. Defaults to `'system'`. */\n initialColorMode?: ColorMode;\n}\n\nexport const ThemeProvider: React.FC<ThemeProviderProps> = ({\n theme: initialTheme,\n children,\n initialColorMode = 'system',\n}) => {\n const [rawTheme, setRawTheme] = useState<Theme>(initialTheme);\n const [colorMode, setColorModeState] = useState<ColorMode>(initialColorMode);\n // Always initialise to 'light' — this matches the server render and\n // avoids the hydration mismatch that occurred when the useState\n // initialiser read from the DOM attribute set by ColorModeScript.\n const [systemPreference, setSystemPreference] = useState<'light' | 'dark'>('light');\n\n // After hydration, sync the real color mode from cookie / blocking-script\n // attribute / OS preference. Uses layoutEffect to run before the browser\n // paints, so the user never sees the wrong theme.\n useIsomorphicLayoutEffect(() => {\n const saved = readCookie(COLOR_MODE_COOKIE);\n if (saved === 'light' || saved === 'dark') {\n setColorModeState(saved);\n }\n\n // Trust the blocking ColorModeScript's attribute first, then fall back\n // to matchMedia.\n const attr = document.documentElement.getAttribute('data-sw-color-mode');\n if (attr === 'dark' || attr === 'light') {\n setSystemPreference(attr);\n } else {\n setSystemPreference(getSystemPreference());\n }\n }, []);\n\n // Listen for OS-level color scheme changes.\n useEffect(() => {\n if (typeof window === 'undefined') return;\n const mql = window.matchMedia('(prefers-color-scheme: dark)');\n const handler = (e: MediaQueryListEvent) => {\n setSystemPreference(e.matches ? 'dark' : 'light');\n };\n mql.addEventListener('change', handler);\n return () => mql.removeEventListener('change', handler);\n }, []);\n\n // Persist color mode to cookie on change, and clear when set to 'system'.\n const setColorMode = useCallback((mode: ColorMode) => {\n setColorModeState(mode);\n if (mode === 'system') {\n deleteCookie(COLOR_MODE_COOKIE);\n } else {\n writeCookie(COLOR_MODE_COOKIE, mode);\n }\n }, []);\n\n const resolvedColorMode: 'light' | 'dark' = colorMode === 'system' ? systemPreference : colorMode;\n\n // Build the effective theme — swap `colors` for `darkColors` when in dark mode.\n const theme = useMemo<Theme>(() => {\n const effectiveColors = resolveColors(rawTheme, resolvedColorMode);\n if (effectiveColors === rawTheme.colors) return rawTheme;\n return { ...rawTheme, colors: effectiveColors };\n }, [rawTheme, resolvedColorMode]);\n\n const setTheme = useCallback((t: Theme) => setRawTheme(t), []);\n\n const value = useMemo<ThemeContextType>(\n () => ({ theme, rawTheme, setTheme, colorMode, setColorMode, resolvedColorMode }),\n [theme, rawTheme, setTheme, colorMode, setColorMode, resolvedColorMode]\n );\n\n return <ThemeContext.Provider value={value}>{children}</ThemeContext.Provider>;\n};\n\n// ---------------------------------------------------------------------------\n// Hooks\n// ---------------------------------------------------------------------------\n\n/**\n * Access the current theme and color mode controls.\n * Must be called inside a `<ThemeProvider>`.\n */\nexport const useTheme = (): ThemeContextType => {\n const context = useContext(ThemeContext);\n if (!context) {\n throw new Error('useTheme must be used within a ThemeProvider');\n }\n return context;\n};\n\n/**\n * Like `useTheme`, but returns `undefined` instead of throwing when\n * no `ThemeProvider` is present. Useful for optional-context components\n * like `ThemeStyleInjector`.\n */\nexport const useThemeOptional = (): ThemeContextType | undefined => {\n return useContext(ThemeContext);\n};\n\n// ---------------------------------------------------------------------------\n// CSS custom property helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Converts a Stackwright Theme to CSS custom properties.\n * Inject these via ThemeStyleInjector or a `<style>` tag.\n */\nexport function themeToCSSVars(theme: Theme): Record<string, string> {\n return {\n '--sw-color-primary': theme.colors.primary,\n '--sw-color-secondary': theme.colors.secondary,\n '--sw-color-accent': theme.colors.accent,\n '--sw-color-bg': theme.colors.background,\n '--sw-color-surface': theme.colors.surface,\n '--sw-color-text': theme.colors.text,\n '--sw-color-text-secondary': theme.colors.textSecondary,\n '--sw-font-primary': theme.typography?.fontFamily?.primary ?? 'sans-serif',\n '--sw-font-secondary': theme.typography?.fontFamily?.secondary ?? 'sans-serif',\n '--sw-spacing-xs': theme.spacing?.xs ?? '0.25rem',\n '--sw-spacing-sm': theme.spacing?.sm ?? '0.5rem',\n '--sw-spacing-md': theme.spacing?.md ?? '1rem',\n '--sw-spacing-lg': theme.spacing?.lg ?? '1.5rem',\n '--sw-spacing-xl': theme.spacing?.xl ?? '2rem',\n '--sw-spacing-2xl': theme.spacing?.['2xl'] ?? '3rem',\n };\n}\n\n// ---------------------------------------------------------------------------\n// ThemeStyleInjector\n// ---------------------------------------------------------------------------\n\ninterface ThemeStyleInjectorProps {\n /**\n * Explicit theme override. When omitted the resolved theme from the\n * nearest `ThemeProvider` is used automatically — this is the\n * recommended approach so CSS vars stay in sync with color mode changes.\n */\n theme?: Theme;\n children: ReactNode;\n className?: string;\n}\n\n/**\n * Wraps children in a div that injects Stackwright CSS custom properties.\n * Place this inside a `<ThemeProvider>` and it will track color mode\n * changes automatically.\n */\nexport function ThemeStyleInjector({\n theme: themeProp,\n children,\n className,\n}: ThemeStyleInjectorProps) {\n const ctx = useThemeOptional();\n const theme = themeProp ?? ctx?.theme;\n\n if (!theme) {\n // No theme from prop or context — render children unstyled rather than crashing.\n return <>{children}</>;\n }\n\n const cssVars = themeToCSSVars(theme);\n return (\n <div className={className} style={cssVars as CSSProperties}>\n {children}\n </div>\n );\n}\n","import * as yaml from 'js-yaml';\nimport { Theme } from './types';\n\nexport class ThemeLoader {\n private static themes: Map<string, Theme> = new Map();\n\n static loadThemeFromYaml(yamlContent: string): Theme {\n try {\n const theme = yaml.load(yamlContent) as Theme;\n this.themes.set(theme.name, theme);\n return theme;\n } catch (error) {\n throw new Error(`Failed to parse theme YAML: ${error}`);\n }\n }\n\n static loadThemeFromFile(themeName: string): Theme {\n const themeData = this.getEmbeddedTheme(themeName);\n return this.loadThemeFromYaml(themeData);\n }\n\n static getTheme(name: string): Theme | undefined {\n return this.themes.get(name);\n }\n\n static getAllThemes(): Theme[] {\n return Array.from(this.themes.values());\n }\n\n static registerCustomTheme(theme: Theme): void {\n this.themes.set(theme.name, theme);\n }\n\n static loadCustomTheme(theme: Theme): Theme {\n this.registerCustomTheme(theme);\n return theme;\n }\n\n private static getEmbeddedTheme(name: string): string {\n const themes: Record<string, string> = {\n corporate: `\nid: \"corporate\"\nname: \"Corporate\"\ndescription: \"A professional amber-toned corporate theme\"\ncolors:\n primary: \"#f59e0b\"\n secondary: \"#334155\"\n accent: \"#d97706\"\n background: \"#f8fafc\"\n surface: \"#ffffff\"\n text: \"#1f2937\"\n textSecondary: \"#6b7280\"\ndarkColors:\n primary: \"#fbbf24\"\n secondary: \"#94a3b8\"\n accent: \"#f59e0b\"\n background: \"#0f172a\"\n surface: \"#1e293b\"\n text: \"#f1f5f9\"\n textSecondary: \"#94a3b8\"\ntypography:\n fontFamily:\n primary: \"Roboto, sans-serif\"\n secondary: \"Roboto, sans-serif\"\n scale:\n xs: \"0.75rem\"\n sm: \"0.875rem\"\n base: \"1rem\"\n lg: \"1.125rem\"\n xl: \"1.25rem\"\n 2xl: \"1.5rem\"\n 3xl: \"1.875rem\"\nspacing:\n xs: \"0.5rem\"\n sm: \"0.75rem\"\n md: \"1rem\"\n lg: \"1.5rem\"\n xl: \"2rem\"\n 2xl: \"3rem\"\n`,\n soft: `\nid: \"soft\"\nname: \"Soft\"\ndescription: \"A gentle pink-toned soft theme\"\ncolors:\n primary: \"#ec4899\"\n secondary: \"#6b7280\"\n accent: \"#db2777\"\n background: \"#f9fafb\"\n surface: \"#ffffff\"\n text: \"#374151\"\n textSecondary: \"#9ca3af\"\ndarkColors:\n primary: \"#f472b6\"\n secondary: \"#9ca3af\"\n accent: \"#ec4899\"\n background: \"#111827\"\n surface: \"#1f2937\"\n text: \"#f9fafb\"\n textSecondary: \"#9ca3af\"\ntypography:\n fontFamily:\n primary: \"Roboto, sans-serif\"\n secondary: \"Roboto, sans-serif\"\n scale:\n xs: \"0.75rem\"\n sm: \"0.875rem\"\n base: \"1rem\"\n lg: \"1.125rem\"\n xl: \"1.25rem\"\n 2xl: \"1.5rem\"\n 3xl: \"1.875rem\"\nspacing:\n xs: \"0.5rem\"\n sm: \"0.75rem\"\n md: \"1rem\"\n lg: \"1.5rem\"\n xl: \"2rem\"\n 2xl: \"3rem\"\n`,\n };\n\n if (!themes[name]) {\n throw new Error(`Theme '${name}' not found`);\n }\n\n return themes[name];\n }\n}\n","import React from 'react';\nimport { ColorMode } from './types';\n\n/**\n * Blocking script that reads the `sw-color-mode` cookie and applies the\n * correct color mode attribute to `<html>` before React hydrates.\n *\n * Place this in `_document.tsx` `<Head>` (Pages Router) or in a `<script>`\n * tag in `layout.tsx` (App Router). It must execute before the body is\n * painted — intentionally render-blocking.\n *\n * The `data-sw-color-mode` attribute set by this script is read by\n * `ThemeProvider`'s `systemPreference` initialiser, ensuring the first\n * React render matches the visible state — no hydration mismatch.\n *\n * For return visitors (cookie exists): correct theme on first paint, zero flash.\n * For first-time visitors with OS dark mode: one-frame flash (same as next-themes v0.2).\n */\nexport function ColorModeScript({ fallback = 'system' }: { fallback?: ColorMode }) {\n // The script is raw JS — no React, no module imports. It reads the cookie\n // and sets a data attribute. ~300 bytes, executes in <1ms.\n const scriptContent = `\n(function(){\n try {\n var m = document.cookie.match(/(?:^|; )sw-color-mode=([^;]*)/);\n var mode = m ? m[1] : '${fallback}';\n if (mode === 'system') {\n mode = window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';\n }\n document.documentElement.setAttribute('data-sw-color-mode', mode);\n } catch(e) {}\n})();\n`.trim();\n\n return <script dangerouslySetInnerHTML={{ __html: scriptContent }} />;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAA,iBAAkB;AAEX,IAAM,uBAAuB,aACjC,OAAO;AAAA,EACN,MAAM,aAAE,OAAO,EAAE,SAAS;AAAA,EAC1B,SAAS,aAAE,OAAO,EAAE,SAAS;AAAA,EAC7B,WAAW,aAAE,OAAO,EAAE,SAAS;AAAA,EAC/B,SAAS,aAAE,OAAO,EAAE,SAAS;AAAA,EAC7B,QAAQ,aAAE,OAAO,EAAE,SAAS;AAAA,EAC5B,KAAK,aAAE,OAAO,EAAE,SAAS;AAAA,EACzB,MAAM,aAAE,OAAO,EAAE,SAAS;AAC5B,CAAC,EACA,SAAS,aAAE,OAAO,EAAE,SAAS,CAAC;AAE1B,IAAM,eAAe,aAAE,OAAO;AAAA,EACnC,SAAS,aAAE,OAAO;AAAA,EAClB,WAAW,aAAE,OAAO;AAAA,EACpB,QAAQ,aAAE,OAAO;AAAA,EACjB,YAAY,aAAE,OAAO;AAAA,EACrB,SAAS,aAAE,OAAO;AAAA,EAClB,MAAM,aAAE,OAAO;AAAA,EACf,eAAe,aAAE,OAAO;AAC1B,CAAC;AAMM,IAAM,oBAAoB,aAAE,OAAO;AAAA,EACxC,IAAI,aAAE,OAAO;AAAA,EACb,MAAM,aAAE,OAAO;AAAA,EACf,aAAa,aAAE,OAAO;AAAA,EACtB,QAAQ;AAAA,EACR,YAAY,aAAa,SAAS;AAAA,EAClC,iBAAiB,aACd,OAAO;AAAA,IACN,KAAK,aAAE,OAAO;AAAA,IACd,QAAQ,aAAE,KAAK,CAAC,UAAU,YAAY,YAAY,WAAW,CAAC,EAAE,SAAS;AAAA,IACzE,MAAM,aAAE,OAAO,EAAE,SAAS;AAAA,IAC1B,UAAU,aAAE,OAAO,EAAE,SAAS;AAAA,IAC9B,YAAY,aAAE,KAAK,CAAC,UAAU,SAAS,OAAO,CAAC,EAAE,SAAS;AAAA,IAC1D,OAAO,aAAE,OAAO,EAAE,SAAS;AAAA,IAC3B,WAAW,aAAE,KAAK,CAAC,SAAS,SAAS,WAAW,iBAAiB,MAAM,CAAC,EAAE,SAAS;AAAA,IACnF,iBAAiB,aAAE,OAAO,EAAE,SAAS;AAAA,EACvC,CAAC,EACA,SAAS;AAAA,EACZ,YAAY,aAAE,OAAO;AAAA,IACnB,YAAY,aAAE,OAAO;AAAA,MACnB,SAAS,aAAE,OAAO;AAAA,MAClB,WAAW,aAAE,OAAO;AAAA,IACtB,CAAC;AAAA,IACD,OAAO,aAAE,OAAO;AAAA,MACd,IAAI,aAAE,OAAO;AAAA,MACb,IAAI,aAAE,OAAO;AAAA,MACb,MAAM,aAAE,OAAO;AAAA,MACf,IAAI,aAAE,OAAO;AAAA,MACb,IAAI,aAAE,OAAO;AAAA,MACb,OAAO,aAAE,OAAO;AAAA,MAChB,OAAO,aAAE,OAAO;AAAA,IAClB,CAAC;AAAA,EACH,CAAC;AAAA,EACD,SAAS,aAAE,OAAO;AAAA,IAChB,IAAI,aAAE,OAAO;AAAA,IACb,IAAI,aAAE,OAAO;AAAA,IACb,IAAI,aAAE,OAAO;AAAA,IACb,IAAI,aAAE,OAAO;AAAA,IACb,IAAI,aAAE,OAAO;AAAA,IACb,OAAO,aAAE,OAAO;AAAA,EAClB,CAAC;AAAA,EACD,YAAY,aACT,OAAO;AAAA,IACN,QAAQ,qBAAqB,SAAS;AAAA,IACtC,MAAM,qBAAqB,SAAS;AAAA,IACpC,QAAQ,qBAAqB,SAAS;AAAA,IACtC,QAAQ,qBAAqB,SAAS;AAAA,EACxC,CAAC,EACA,SAAS;AACd,CAAC;AAEM,IAAM,cAAc;;;AC/E3B,mBAUO;AA0JE;AArIT,IAAM,mBAAe,4BAA4C,MAAS;AAM1E,IAAM,oBAAoB;AAG1B,SAAS,sBAAwC;AAC/C,MAAI,OAAO,WAAW,YAAa,QAAO;AAC1C,SAAO,OAAO,WAAW,8BAA8B,EAAE,UAAU,SAAS;AAC9E;AAQA,IAAM,4BAA4B,OAAO,WAAW,cAAc,+BAAkB;AAGpF,SAAS,cAAc,OAAc,MAAqC;AACxE,MAAI,SAAS,UAAU,MAAM,YAAY;AACvC,WAAO,MAAM;AAAA,EACf;AACA,SAAO,MAAM;AACf;AAMA,SAAS,WAAW,MAAkC;AACpD,MAAI,OAAO,aAAa,YAAa,QAAO;AAC5C,QAAM,QAAQ,SAAS,OAAO,MAAM,IAAI,OAAO,aAAa,OAAO,UAAU,CAAC;AAC9E,SAAO,QAAQ,mBAAmB,MAAM,CAAC,CAAC,IAAI;AAChD;AAGA,SAAS,YAAY,MAAc,OAAqB;AACtD,MAAI,OAAO,aAAa,YAAa;AACrC,QAAM,SAAS,MAAM,KAAK,KAAK;AAC/B,WAAS,SACP,OAAO,MAAM,mBAAmB,KAAK,IAAI,eAAe,SAAS;AACrE;AAGA,SAAS,aAAa,MAAoB;AACxC,MAAI,OAAO,aAAa,YAAa;AACrC,WAAS,SAAS,OAAO;AAC3B;AAaO,IAAM,gBAA8C,CAAC;AAAA,EAC1D,OAAO;AAAA,EACP;AAAA,EACA,mBAAmB;AACrB,MAAM;AACJ,QAAM,CAAC,UAAU,WAAW,QAAI,uBAAgB,YAAY;AAC5D,QAAM,CAAC,WAAW,iBAAiB,QAAI,uBAAoB,gBAAgB;AAI3E,QAAM,CAAC,kBAAkB,mBAAmB,QAAI,uBAA2B,OAAO;AAKlF,4BAA0B,MAAM;AAC9B,UAAM,QAAQ,WAAW,iBAAiB;AAC1C,QAAI,UAAU,WAAW,UAAU,QAAQ;AACzC,wBAAkB,KAAK;AAAA,IACzB;AAIA,UAAM,OAAO,SAAS,gBAAgB,aAAa,oBAAoB;AACvE,QAAI,SAAS,UAAU,SAAS,SAAS;AACvC,0BAAoB,IAAI;AAAA,IAC1B,OAAO;AACL,0BAAoB,oBAAoB,CAAC;AAAA,IAC3C;AAAA,EACF,GAAG,CAAC,CAAC;AAGL,8BAAU,MAAM;AACd,QAAI,OAAO,WAAW,YAAa;AACnC,UAAM,MAAM,OAAO,WAAW,8BAA8B;AAC5D,UAAM,UAAU,CAAC,MAA2B;AAC1C,0BAAoB,EAAE,UAAU,SAAS,OAAO;AAAA,IAClD;AACA,QAAI,iBAAiB,UAAU,OAAO;AACtC,WAAO,MAAM,IAAI,oBAAoB,UAAU,OAAO;AAAA,EACxD,GAAG,CAAC,CAAC;AAGL,QAAM,mBAAe,0BAAY,CAAC,SAAoB;AACpD,sBAAkB,IAAI;AACtB,QAAI,SAAS,UAAU;AACrB,mBAAa,iBAAiB;AAAA,IAChC,OAAO;AACL,kBAAY,mBAAmB,IAAI;AAAA,IACrC;AAAA,EACF,GAAG,CAAC,CAAC;AAEL,QAAM,oBAAsC,cAAc,WAAW,mBAAmB;AAGxF,QAAM,YAAQ,sBAAe,MAAM;AACjC,UAAM,kBAAkB,cAAc,UAAU,iBAAiB;AACjE,QAAI,oBAAoB,SAAS,OAAQ,QAAO;AAChD,WAAO,EAAE,GAAG,UAAU,QAAQ,gBAAgB;AAAA,EAChD,GAAG,CAAC,UAAU,iBAAiB,CAAC;AAEhC,QAAM,eAAW,0BAAY,CAAC,MAAa,YAAY,CAAC,GAAG,CAAC,CAAC;AAE7D,QAAM,YAAQ;AAAA,IACZ,OAAO,EAAE,OAAO,UAAU,UAAU,WAAW,cAAc,kBAAkB;AAAA,IAC/E,CAAC,OAAO,UAAU,UAAU,WAAW,cAAc,iBAAiB;AAAA,EACxE;AAEA,SAAO,4CAAC,aAAa,UAAb,EAAsB,OAAe,UAAS;AACxD;AAUO,IAAM,WAAW,MAAwB;AAC9C,QAAM,cAAU,yBAAW,YAAY;AACvC,MAAI,CAAC,SAAS;AACZ,UAAM,IAAI,MAAM,8CAA8C;AAAA,EAChE;AACA,SAAO;AACT;AAOO,IAAM,mBAAmB,MAAoC;AAClE,aAAO,yBAAW,YAAY;AAChC;AAUO,SAAS,eAAe,OAAsC;AACnE,SAAO;AAAA,IACL,sBAAsB,MAAM,OAAO;AAAA,IACnC,wBAAwB,MAAM,OAAO;AAAA,IACrC,qBAAqB,MAAM,OAAO;AAAA,IAClC,iBAAiB,MAAM,OAAO;AAAA,IAC9B,sBAAsB,MAAM,OAAO;AAAA,IACnC,mBAAmB,MAAM,OAAO;AAAA,IAChC,6BAA6B,MAAM,OAAO;AAAA,IAC1C,qBAAqB,MAAM,YAAY,YAAY,WAAW;AAAA,IAC9D,uBAAuB,MAAM,YAAY,YAAY,aAAa;AAAA,IAClE,mBAAmB,MAAM,SAAS,MAAM;AAAA,IACxC,mBAAmB,MAAM,SAAS,MAAM;AAAA,IACxC,mBAAmB,MAAM,SAAS,MAAM;AAAA,IACxC,mBAAmB,MAAM,SAAS,MAAM;AAAA,IACxC,mBAAmB,MAAM,SAAS,MAAM;AAAA,IACxC,oBAAoB,MAAM,UAAU,KAAK,KAAK;AAAA,EAChD;AACF;AAsBO,SAAS,mBAAmB;AAAA,EACjC,OAAO;AAAA,EACP;AAAA,EACA;AACF,GAA4B;AAC1B,QAAM,MAAM,iBAAiB;AAC7B,QAAM,QAAQ,aAAa,KAAK;AAEhC,MAAI,CAAC,OAAO;AAEV,WAAO,2EAAG,UAAS;AAAA,EACrB;AAEA,QAAM,UAAU,eAAe,KAAK;AACpC,SACE,4CAAC,SAAI,WAAsB,OAAO,SAC/B,UACH;AAEJ;;;ACnQA,WAAsB;AAGf,IAAM,cAAN,MAAkB;AAAA,EACvB,OAAe,SAA6B,oBAAI,IAAI;AAAA,EAEpD,OAAO,kBAAkB,aAA4B;AACnD,QAAI;AACF,YAAM,QAAa,UAAK,WAAW;AACnC,WAAK,OAAO,IAAI,MAAM,MAAM,KAAK;AACjC,aAAO;AAAA,IACT,SAAS,OAAO;AACd,YAAM,IAAI,MAAM,+BAA+B,KAAK,EAAE;AAAA,IACxD;AAAA,EACF;AAAA,EAEA,OAAO,kBAAkB,WAA0B;AACjD,UAAM,YAAY,KAAK,iBAAiB,SAAS;AACjD,WAAO,KAAK,kBAAkB,SAAS;AAAA,EACzC;AAAA,EAEA,OAAO,SAAS,MAAiC;AAC/C,WAAO,KAAK,OAAO,IAAI,IAAI;AAAA,EAC7B;AAAA,EAEA,OAAO,eAAwB;AAC7B,WAAO,MAAM,KAAK,KAAK,OAAO,OAAO,CAAC;AAAA,EACxC;AAAA,EAEA,OAAO,oBAAoB,OAAoB;AAC7C,SAAK,OAAO,IAAI,MAAM,MAAM,KAAK;AAAA,EACnC;AAAA,EAEA,OAAO,gBAAgB,OAAqB;AAC1C,SAAK,oBAAoB,KAAK;AAC9B,WAAO;AAAA,EACT;AAAA,EAEA,OAAe,iBAAiB,MAAsB;AACpD,UAAM,SAAiC;AAAA,MACrC,WAAW;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAwCX,MAAM;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAwCR;AAEA,QAAI,CAAC,OAAO,IAAI,GAAG;AACjB,YAAM,IAAI,MAAM,UAAU,IAAI,aAAa;AAAA,IAC7C;AAEA,WAAO,OAAO,IAAI;AAAA,EACpB;AACF;;;AC9FS,IAAAA,sBAAA;AAhBF,SAAS,gBAAgB,EAAE,WAAW,SAAS,GAA6B;AAGjF,QAAM,gBAAgB;AAAA;AAAA;AAAA;AAAA,6BAIK,QAAQ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOnC,KAAK;AAEL,SAAO,6CAAC,YAAO,yBAAyB,EAAE,QAAQ,cAAc,GAAG;AACrE;","names":["import_jsx_runtime"]}