@poodle-kit/ui 0.1.0 → 0.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.
@@ -0,0 +1,287 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+
3
+ type Theme = 'light' | 'dark' | 'system' | string;
4
+ type ColorValue = string | {
5
+ DEFAULT: string;
6
+ foreground: string;
7
+ };
8
+ interface ThemeColors {
9
+ background?: ColorValue;
10
+ foreground?: ColorValue;
11
+ muted?: ColorValue;
12
+ accent?: ColorValue;
13
+ card?: ColorValue;
14
+ popover?: ColorValue;
15
+ primary?: ColorValue;
16
+ secondary?: ColorValue;
17
+ info?: ColorValue;
18
+ danger?: ColorValue;
19
+ warning?: ColorValue;
20
+ success?: ColorValue;
21
+ destructive?: ColorValue;
22
+ border?: ColorValue;
23
+ input?: ColorValue;
24
+ ring?: ColorValue;
25
+ [key: string]: ColorValue | undefined;
26
+ }
27
+ interface ThemeConfig {
28
+ colors: ThemeColors;
29
+ spacing?: Record<string, string>;
30
+ radius?: Record<string, string>;
31
+ fontSize?: Record<string, string | [string, {
32
+ lineHeight: string;
33
+ letterSpacing?: string;
34
+ }]>;
35
+ fontFamily?: Record<string, string[]>;
36
+ fontWeight?: Record<string, string>;
37
+ shadows?: Record<string, string>;
38
+ zIndex?: Record<string, string>;
39
+ animation?: {
40
+ duration?: Record<string, string>;
41
+ ease?: Record<string, string>;
42
+ };
43
+ [key: string]: unknown;
44
+ }
45
+ interface CustomThemeDefinition {
46
+ dark?: boolean;
47
+ cssVars?: Record<string, string>;
48
+ }
49
+ interface ThemeProviderProps {
50
+ children: React.ReactNode;
51
+ defaultTheme?: Theme;
52
+ storageKey?: string;
53
+ /** Custom theme configuration for light mode */
54
+ config?: ThemeConfig;
55
+ /** Custom theme configuration for dark mode */
56
+ darkConfig?: ThemeConfig;
57
+ /** Legacy: Custom theme definitions (deprecated, use config instead) */
58
+ customThemes?: Record<string, CustomThemeDefinition>;
59
+ enableColorSchemeSync?: boolean;
60
+ }
61
+ interface ThemeProviderState {
62
+ theme: Theme;
63
+ setTheme: (theme: Theme) => void;
64
+ }
65
+ declare function defineTheme<T extends ThemeConfig>(config: T): T;
66
+
67
+ declare function ThemeProvider({ children, defaultTheme, storageKey, config, darkConfig, customThemes, enableColorSchemeSync, }: ThemeProviderProps): react_jsx_runtime.JSX.Element;
68
+
69
+ declare function useTheme(): ThemeProviderState;
70
+
71
+ /**
72
+ * Convert ThemeConfig to CSS variables object
73
+ */
74
+ declare function themeToCssVars(theme: ThemeConfig): Record<string, string>;
75
+ /**
76
+ * Apply CSS variables to an element
77
+ */
78
+ declare function applyCssVars(element: HTMLElement, cssVars: Record<string, string>): void;
79
+ /**
80
+ * Remove CSS variables from an element
81
+ */
82
+ declare function removeCssVars(element: HTMLElement, keys: string[]): void;
83
+ /**
84
+ * Format CSS variables object to CSS string
85
+ * Useful for build-time CSS generation
86
+ *
87
+ * @example
88
+ * ```ts
89
+ * const cssVars = themeToCssVars(myTheme);
90
+ * const cssString = formatCssVars(cssVars);
91
+ * console.log(cssString);
92
+ * // Output:
93
+ * // --color-primary: oklch(0.5 0.2 250);
94
+ * // --color-primary-foreground: oklch(1 0 0);
95
+ * ```
96
+ */
97
+ declare function formatCssVars(cssVars: Record<string, string>): string;
98
+ /**
99
+ * Generate CSS variables string from theme config
100
+ * Combines themeToCssVars + formatCssVars for convenience
101
+ *
102
+ * @example
103
+ * ```ts
104
+ * import { defineTheme, generateThemeCss } from '@poodle-kit/ui/theme';
105
+ *
106
+ * const myTheme = defineTheme({ colors: { ... } });
107
+ * const cssString = generateThemeCss(myTheme);
108
+ * console.log(cssString);
109
+ * // Output:
110
+ * // --color-primary: oklch(0.5 0.2 250);
111
+ * // --color-primary-foreground: oklch(1 0 0);
112
+ * ```
113
+ */
114
+ declare function generateThemeCss(theme: ThemeConfig): string;
115
+
116
+ /**
117
+ * Default Theme Tokens
118
+ *
119
+ * This is a reference implementation showing how to define themes.
120
+ * Copy this pattern to your project and customize the values.
121
+ *
122
+ * @example
123
+ * ```tsx
124
+ * // your-app/src/theme/my-theme.ts
125
+ * import { defineTheme } from '@poodle-kit/ui/theme';
126
+ *
127
+ * export const myLightTheme = defineTheme({
128
+ * colors: {
129
+ * primary: { DEFAULT: 'oklch(0.5 0.2 250)', foreground: 'oklch(1 0 0)' },
130
+ * // ... your custom colors
131
+ * },
132
+ * radius: { md: '0.5rem' },
133
+ * });
134
+ *
135
+ * export const myDarkTheme = defineTheme({
136
+ * colors: {
137
+ * primary: { DEFAULT: 'oklch(0.7 0.2 250)', foreground: 'oklch(0.09 0 0)' },
138
+ * // ... your custom colors
139
+ * },
140
+ * radius: { md: '0.5rem' },
141
+ * });
142
+ * ```
143
+ *
144
+ * Then use in your app:
145
+ * ```tsx
146
+ * import { ThemeProvider } from '@poodle-kit/ui';
147
+ * import { myLightTheme, myDarkTheme } from './theme/my-theme';
148
+ *
149
+ * <ThemeProvider config={myLightTheme} darkConfig={myDarkTheme}>
150
+ * <App />
151
+ * </ThemeProvider>
152
+ * ```
153
+ */
154
+ /**
155
+ * Default Light Theme
156
+ * Clean neutral design with semantic color tokens
157
+ */
158
+ declare const defaultLightTheme: {
159
+ colors: {
160
+ background: {
161
+ DEFAULT: string;
162
+ foreground: string;
163
+ };
164
+ muted: {
165
+ DEFAULT: string;
166
+ foreground: string;
167
+ };
168
+ accent: {
169
+ DEFAULT: string;
170
+ foreground: string;
171
+ };
172
+ card: {
173
+ DEFAULT: string;
174
+ foreground: string;
175
+ };
176
+ popover: {
177
+ DEFAULT: string;
178
+ foreground: string;
179
+ };
180
+ primary: {
181
+ DEFAULT: string;
182
+ foreground: string;
183
+ };
184
+ secondary: {
185
+ DEFAULT: string;
186
+ foreground: string;
187
+ };
188
+ info: {
189
+ DEFAULT: string;
190
+ foreground: string;
191
+ };
192
+ danger: {
193
+ DEFAULT: string;
194
+ foreground: string;
195
+ };
196
+ warning: {
197
+ DEFAULT: string;
198
+ foreground: string;
199
+ };
200
+ success: {
201
+ DEFAULT: string;
202
+ foreground: string;
203
+ };
204
+ border: string;
205
+ input: string;
206
+ ring: string;
207
+ };
208
+ radius: {
209
+ none: string;
210
+ sm: string;
211
+ base: string;
212
+ md: string;
213
+ lg: string;
214
+ xl: string;
215
+ '2xl': string;
216
+ '3xl': string;
217
+ full: string;
218
+ };
219
+ };
220
+ /**
221
+ * Default Dark Theme
222
+ * Clean neutral design with semantic color tokens
223
+ */
224
+ declare const defaultDarkTheme: {
225
+ colors: {
226
+ background: {
227
+ DEFAULT: string;
228
+ foreground: string;
229
+ };
230
+ muted: {
231
+ DEFAULT: string;
232
+ foreground: string;
233
+ };
234
+ accent: {
235
+ DEFAULT: string;
236
+ foreground: string;
237
+ };
238
+ card: {
239
+ DEFAULT: string;
240
+ foreground: string;
241
+ };
242
+ popover: {
243
+ DEFAULT: string;
244
+ foreground: string;
245
+ };
246
+ primary: {
247
+ DEFAULT: string;
248
+ foreground: string;
249
+ };
250
+ secondary: {
251
+ DEFAULT: string;
252
+ foreground: string;
253
+ };
254
+ info: {
255
+ DEFAULT: string;
256
+ foreground: string;
257
+ };
258
+ danger: {
259
+ DEFAULT: string;
260
+ foreground: string;
261
+ };
262
+ warning: {
263
+ DEFAULT: string;
264
+ foreground: string;
265
+ };
266
+ success: {
267
+ DEFAULT: string;
268
+ foreground: string;
269
+ };
270
+ border: string;
271
+ input: string;
272
+ ring: string;
273
+ };
274
+ radius: {
275
+ none: string;
276
+ sm: string;
277
+ base: string;
278
+ md: string;
279
+ lg: string;
280
+ xl: string;
281
+ '2xl': string;
282
+ '3xl': string;
283
+ full: string;
284
+ };
285
+ };
286
+
287
+ export { type CustomThemeDefinition, type Theme, type ThemeColors, type ThemeConfig, ThemeProvider, type ThemeProviderProps, type ThemeProviderState, applyCssVars, defaultDarkTheme, defaultLightTheme, defineTheme, formatCssVars, generateThemeCss, removeCssVars, themeToCssVars, useTheme };
@@ -0,0 +1,386 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/theme/index.ts
21
+ var theme_exports = {};
22
+ __export(theme_exports, {
23
+ ThemeProvider: () => ThemeProvider,
24
+ applyCssVars: () => applyCssVars,
25
+ defaultDarkTheme: () => defaultDarkTheme,
26
+ defaultLightTheme: () => defaultLightTheme,
27
+ defineTheme: () => defineTheme,
28
+ formatCssVars: () => formatCssVars,
29
+ generateThemeCss: () => generateThemeCss,
30
+ removeCssVars: () => removeCssVars,
31
+ themeToCssVars: () => themeToCssVars,
32
+ useTheme: () => useTheme
33
+ });
34
+ module.exports = __toCommonJS(theme_exports);
35
+
36
+ // src/theme/provider.tsx
37
+ var import_react = require("react");
38
+
39
+ // src/theme/theme-to-css-vars.ts
40
+ function themeToCssVars(theme) {
41
+ const cssVars = {};
42
+ if (theme.colors) {
43
+ Object.entries(theme.colors).forEach(([key, value]) => {
44
+ if (typeof value === "string") {
45
+ cssVars[`--color-${key}`] = value;
46
+ } else if (typeof value === "object" && value !== null) {
47
+ if ("DEFAULT" in value) {
48
+ cssVars[`--color-${key}`] = value.DEFAULT;
49
+ }
50
+ if ("foreground" in value) {
51
+ cssVars[`--color-${key}-foreground`] = value.foreground;
52
+ }
53
+ }
54
+ });
55
+ }
56
+ if (theme.radius) {
57
+ Object.entries(theme.radius).forEach(([key, value]) => {
58
+ cssVars[`--radius-${key}`] = value;
59
+ });
60
+ }
61
+ if (theme.fontSize) {
62
+ Object.entries(theme.fontSize).forEach(([key, value]) => {
63
+ if (Array.isArray(value)) {
64
+ const [size, config] = value;
65
+ cssVars[`--text-${key}`] = size;
66
+ if (config.lineHeight) {
67
+ cssVars[`--leading-${key}`] = config.lineHeight;
68
+ }
69
+ } else {
70
+ cssVars[`--text-${key}`] = value;
71
+ }
72
+ });
73
+ }
74
+ if (theme.fontFamily) {
75
+ Object.entries(theme.fontFamily).forEach(([key, value]) => {
76
+ cssVars[`--font-${key}`] = value.join(", ");
77
+ });
78
+ }
79
+ if (theme.fontWeight) {
80
+ Object.entries(theme.fontWeight).forEach(([key, value]) => {
81
+ cssVars[`--font-weight-${key}`] = value;
82
+ });
83
+ }
84
+ if (theme.shadows) {
85
+ Object.entries(theme.shadows).forEach(([key, value]) => {
86
+ cssVars[`--shadow-${key}`] = value;
87
+ });
88
+ }
89
+ if (theme.zIndex) {
90
+ Object.entries(theme.zIndex).forEach(([key, value]) => {
91
+ cssVars[`--z-${key}`] = value.toString();
92
+ });
93
+ }
94
+ if (theme.animation) {
95
+ if (theme.animation.duration) {
96
+ Object.entries(theme.animation.duration).forEach(
97
+ ([key, value]) => {
98
+ cssVars[`--duration-${key}`] = value;
99
+ }
100
+ );
101
+ }
102
+ if (theme.animation.ease) {
103
+ Object.entries(theme.animation.ease).forEach(([key, value]) => {
104
+ cssVars[`--ease-${key}`] = value;
105
+ });
106
+ }
107
+ }
108
+ if (theme.spacing) {
109
+ Object.entries(theme.spacing).forEach(([key, value]) => {
110
+ cssVars[`--spacing-${key}`] = value;
111
+ });
112
+ }
113
+ return cssVars;
114
+ }
115
+ function applyCssVars(element, cssVars) {
116
+ Object.entries(cssVars).forEach(([key, value]) => {
117
+ element.style.setProperty(key, value);
118
+ });
119
+ }
120
+ function removeCssVars(element, keys) {
121
+ keys.forEach((key) => {
122
+ element.style.removeProperty(key);
123
+ });
124
+ }
125
+ function formatCssVars(cssVars) {
126
+ return Object.entries(cssVars).map(([key, value]) => ` ${key}: ${value};`).join("\n");
127
+ }
128
+ function generateThemeCss(theme) {
129
+ const cssVars = themeToCssVars(theme);
130
+ return formatCssVars(cssVars);
131
+ }
132
+
133
+ // src/theme/provider.tsx
134
+ var import_jsx_runtime = require("react/jsx-runtime");
135
+ var ThemeContext = (0, import_react.createContext)(void 0);
136
+ function ThemeProvider({
137
+ children,
138
+ defaultTheme = "system",
139
+ storageKey = "poodle-ui-theme",
140
+ config,
141
+ darkConfig,
142
+ customThemes = {},
143
+ enableColorSchemeSync = true
144
+ }) {
145
+ const [theme, setTheme] = (0, import_react.useState)(() => {
146
+ if (typeof window === "undefined") {
147
+ return defaultTheme;
148
+ }
149
+ try {
150
+ return localStorage.getItem(storageKey) || defaultTheme;
151
+ } catch {
152
+ return defaultTheme;
153
+ }
154
+ });
155
+ const lightCssVars = (0, import_react.useMemo)(
156
+ () => config ? themeToCssVars(config) : null,
157
+ [config]
158
+ );
159
+ const darkCssVars = (0, import_react.useMemo)(
160
+ () => darkConfig ? themeToCssVars(darkConfig) : null,
161
+ [darkConfig]
162
+ );
163
+ (0, import_react.useEffect)(() => {
164
+ var _a, _b;
165
+ const root = window.document.documentElement;
166
+ root.classList.remove(
167
+ "light",
168
+ "dark",
169
+ ...Object.keys(customThemes)
170
+ );
171
+ let actualTheme;
172
+ if (theme === "system") {
173
+ actualTheme = window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
174
+ } else {
175
+ actualTheme = theme;
176
+ }
177
+ root.classList.add(actualTheme);
178
+ if (enableColorSchemeSync) {
179
+ const isDark = actualTheme === "dark" || ((_a = customThemes[actualTheme]) == null ? void 0 : _a.dark);
180
+ root.style.colorScheme = isDark ? "dark" : "light";
181
+ }
182
+ if (actualTheme === "light" && lightCssVars) {
183
+ applyCssVars(root, lightCssVars);
184
+ } else if (actualTheme === "dark" && darkCssVars) {
185
+ applyCssVars(root, darkCssVars);
186
+ } else if ((_b = customThemes[actualTheme]) == null ? void 0 : _b.cssVars) {
187
+ Object.entries(customThemes[actualTheme].cssVars).forEach(
188
+ ([key, value2]) => {
189
+ root.style.setProperty(key, value2);
190
+ }
191
+ );
192
+ }
193
+ }, [
194
+ theme,
195
+ lightCssVars,
196
+ darkCssVars,
197
+ customThemes,
198
+ enableColorSchemeSync
199
+ ]);
200
+ (0, import_react.useEffect)(() => {
201
+ if (theme !== "system") return;
202
+ const mediaQuery = window.matchMedia(
203
+ "(prefers-color-scheme: dark)"
204
+ );
205
+ const handler = () => {
206
+ setTheme("system");
207
+ };
208
+ mediaQuery.addEventListener("change", handler);
209
+ return () => mediaQuery.removeEventListener("change", handler);
210
+ }, [theme]);
211
+ const handleSetTheme = (newTheme) => {
212
+ try {
213
+ localStorage.setItem(storageKey, newTheme);
214
+ } catch {
215
+ }
216
+ setTheme(newTheme);
217
+ };
218
+ const value = {
219
+ theme,
220
+ setTheme: handleSetTheme
221
+ };
222
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ThemeContext.Provider, { value, children });
223
+ }
224
+
225
+ // src/theme/use-theme.ts
226
+ var import_react2 = require("react");
227
+ function useTheme() {
228
+ const context = (0, import_react2.useContext)(ThemeContext);
229
+ if (context === void 0) {
230
+ throw new Error("useTheme must be used within a ThemeProvider");
231
+ }
232
+ return context;
233
+ }
234
+
235
+ // src/theme/types.ts
236
+ function defineTheme(config) {
237
+ return config;
238
+ }
239
+
240
+ // src/theme/defaults/default.ts
241
+ var defaultLightTheme = defineTheme({
242
+ colors: {
243
+ // Page & Container colors
244
+ background: {
245
+ DEFAULT: "oklch(1 0 0)",
246
+ foreground: "oklch(0.09 0 0)"
247
+ },
248
+ muted: {
249
+ DEFAULT: "oklch(0.96 0 0)",
250
+ foreground: "oklch(0.45 0 0)"
251
+ },
252
+ accent: {
253
+ DEFAULT: "oklch(0.96 0 0)",
254
+ foreground: "oklch(0.09 0 0)"
255
+ },
256
+ card: {
257
+ DEFAULT: "oklch(1 0 0)",
258
+ foreground: "oklch(0.09 0 0)"
259
+ },
260
+ popover: {
261
+ DEFAULT: "oklch(1 0 0)",
262
+ foreground: "oklch(0.09 0 0)"
263
+ },
264
+ // Brand & Action colors
265
+ primary: {
266
+ DEFAULT: "oklch(0.09 0 0)",
267
+ foreground: "oklch(0.98 0 0)"
268
+ },
269
+ secondary: {
270
+ DEFAULT: "oklch(0.45 0 0)",
271
+ foreground: "oklch(0.98 0 0)"
272
+ },
273
+ // Semantic colors
274
+ info: {
275
+ DEFAULT: "oklch(0.55 0.15 250)",
276
+ foreground: "oklch(0.98 0 0)"
277
+ },
278
+ danger: {
279
+ DEFAULT: "oklch(0.576 0.204 27.325)",
280
+ foreground: "oklch(0.98 0 0)"
281
+ },
282
+ warning: {
283
+ DEFAULT: "oklch(0.75 0.15 75)",
284
+ foreground: "oklch(0.09 0 0)"
285
+ },
286
+ success: {
287
+ DEFAULT: "oklch(0.60 0.15 145)",
288
+ foreground: "oklch(0.98 0 0)"
289
+ },
290
+ // Border & Input colors
291
+ border: "oklch(0.90 0 0)",
292
+ input: "oklch(0.90 0 0)",
293
+ ring: "oklch(0.09 0 0)"
294
+ },
295
+ radius: {
296
+ none: "0",
297
+ sm: "0.125rem",
298
+ base: "0.25rem",
299
+ md: "0.375rem",
300
+ lg: "0.5rem",
301
+ xl: "0.75rem",
302
+ "2xl": "1rem",
303
+ "3xl": "1.5rem",
304
+ full: "9999px"
305
+ }
306
+ });
307
+ var defaultDarkTheme = defineTheme({
308
+ colors: {
309
+ // Page & Container colors
310
+ background: {
311
+ DEFAULT: "oklch(0.09 0 0)",
312
+ foreground: "oklch(0.98 0 0)"
313
+ },
314
+ muted: {
315
+ DEFAULT: "oklch(0.17 0 0)",
316
+ foreground: "oklch(0.65 0 0)"
317
+ },
318
+ accent: {
319
+ DEFAULT: "oklch(0.17 0 0)",
320
+ foreground: "oklch(0.98 0 0)"
321
+ },
322
+ card: {
323
+ DEFAULT: "oklch(0.09 0 0)",
324
+ foreground: "oklch(0.98 0 0)"
325
+ },
326
+ popover: {
327
+ DEFAULT: "oklch(0.09 0 0)",
328
+ foreground: "oklch(0.98 0 0)"
329
+ },
330
+ // Brand & Action colors
331
+ primary: {
332
+ DEFAULT: "oklch(0.98 0 0)",
333
+ foreground: "oklch(0.09 0 0)"
334
+ },
335
+ secondary: {
336
+ DEFAULT: "oklch(0.65 0 0)",
337
+ foreground: "oklch(0.09 0 0)"
338
+ },
339
+ // Semantic colors
340
+ info: {
341
+ DEFAULT: "oklch(0.65 0.15 250)",
342
+ foreground: "oklch(0.09 0 0)"
343
+ },
344
+ danger: {
345
+ DEFAULT: "oklch(0.701 0.191 29.234)",
346
+ foreground: "oklch(0.09 0 0)"
347
+ },
348
+ warning: {
349
+ DEFAULT: "oklch(0.80 0.15 75)",
350
+ foreground: "oklch(0.09 0 0)"
351
+ },
352
+ success: {
353
+ DEFAULT: "oklch(0.70 0.15 145)",
354
+ foreground: "oklch(0.09 0 0)"
355
+ },
356
+ // Border & Input colors
357
+ border: "oklch(0.27 0 0)",
358
+ input: "oklch(0.27 0 0)",
359
+ ring: "oklch(0.98 0 0)"
360
+ },
361
+ radius: {
362
+ none: "0",
363
+ sm: "0.125rem",
364
+ base: "0.25rem",
365
+ md: "0.375rem",
366
+ lg: "0.5rem",
367
+ xl: "0.75rem",
368
+ "2xl": "1rem",
369
+ "3xl": "1.5rem",
370
+ full: "9999px"
371
+ }
372
+ });
373
+ // Annotate the CommonJS export names for ESM import in node:
374
+ 0 && (module.exports = {
375
+ ThemeProvider,
376
+ applyCssVars,
377
+ defaultDarkTheme,
378
+ defaultLightTheme,
379
+ defineTheme,
380
+ formatCssVars,
381
+ generateThemeCss,
382
+ removeCssVars,
383
+ themeToCssVars,
384
+ useTheme
385
+ });
386
+ //# sourceMappingURL=index.js.map