@structyl/themes 1.0.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,425 @@
1
+ import * as React from 'react';
2
+
3
+ type ThemeMode = 'light' | 'dark' | 'system';
4
+ type ResolvedMode = 'light' | 'dark';
5
+ type Theme = string;
6
+ interface ThemeTokens {
7
+ bg: string;
8
+ fg: string;
9
+ card: string;
10
+ 'card-fg': string;
11
+ popover: string;
12
+ 'popover-fg': string;
13
+ primary: string;
14
+ 'primary-fg': string;
15
+ 'primary-hover': string;
16
+ 'primary-active': string;
17
+ secondary: string;
18
+ 'secondary-fg': string;
19
+ muted: string;
20
+ 'muted-fg': string;
21
+ accent: string;
22
+ 'accent-fg': string;
23
+ destructive: string;
24
+ 'destructive-fg': string;
25
+ success: string;
26
+ 'success-fg': string;
27
+ warning: string;
28
+ 'warning-fg': string;
29
+ info: string;
30
+ 'info-fg': string;
31
+ border: string;
32
+ 'border-strong': string;
33
+ input: string;
34
+ ring: string;
35
+ overlay: string;
36
+ shadow: string;
37
+ 'primary-light': string;
38
+ 'primary-dark': string;
39
+ 'primary-contrast': string;
40
+ 'primary-dark-bg': string;
41
+ 'secondary-light': string;
42
+ 'secondary-dark': string;
43
+ 'secondary-contrast': string;
44
+ 'secondary-dark-bg': string;
45
+ 'error-light': string;
46
+ 'error-dark': string;
47
+ 'error-contrast': string;
48
+ 'error-dark-bg': string;
49
+ 'warning-light': string;
50
+ 'warning-dark': string;
51
+ 'warning-contrast': string;
52
+ 'warning-dark-bg': string;
53
+ 'info-light': string;
54
+ 'info-dark': string;
55
+ 'info-contrast': string;
56
+ 'info-dark-bg': string;
57
+ 'success-light': string;
58
+ 'success-dark': string;
59
+ 'success-contrast': string;
60
+ 'success-dark-bg': string;
61
+ 'primary-state-contained': string;
62
+ 'primary-state-outlined': string;
63
+ 'primary-state-resting': string;
64
+ 'primary-shade-12': string;
65
+ 'primary-shade-16': string;
66
+ 'secondary-state-contained': string;
67
+ 'secondary-state-outlined': string;
68
+ 'secondary-state-resting': string;
69
+ 'secondary-shade-12': string;
70
+ 'secondary-shade-16': string;
71
+ 'error-state-contained': string;
72
+ 'error-state-outlined': string;
73
+ 'error-state-resting': string;
74
+ 'error-alert-bg': string;
75
+ 'error-alert-content': string;
76
+ 'error-shade-12': string;
77
+ 'error-shade-16': string;
78
+ 'warning-state-contained': string;
79
+ 'warning-state-outlined': string;
80
+ 'warning-state-resting': string;
81
+ 'warning-alert-bg': string;
82
+ 'warning-alert-content': string;
83
+ 'warning-shade-12': string;
84
+ 'warning-shade-16': string;
85
+ 'info-state-contained': string;
86
+ 'info-state-outlined': string;
87
+ 'info-state-resting': string;
88
+ 'info-alert-bg': string;
89
+ 'info-alert-content': string;
90
+ 'info-shade-12': string;
91
+ 'info-shade-16': string;
92
+ 'success-state-contained': string;
93
+ 'success-state-outlined': string;
94
+ 'success-state-resting': string;
95
+ 'success-alert-bg': string;
96
+ 'success-alert-content': string;
97
+ 'success-shade-12': string;
98
+ 'success-shade-16': string;
99
+ text: string;
100
+ 'text-secondary': string;
101
+ 'text-disabled': string;
102
+ 'text-info': string;
103
+ 'text-fill': string;
104
+ 'text-shade-12': string;
105
+ 'text-shade-16': string;
106
+ surface: string;
107
+ 'surface-paper': string;
108
+ divider: string;
109
+ 'outlined-border': string;
110
+ 'input-line': string;
111
+ 'action-active': string;
112
+ 'action-hover': string;
113
+ 'action-selected': string;
114
+ 'action-disabled': string;
115
+ 'action-disabled-bg': string;
116
+ 'action-focus': string;
117
+ backdrop: string;
118
+ 'rating-active': string;
119
+ 'snackbar-bg': string;
120
+ 'map-grid': string;
121
+ 'table-top-header': string;
122
+ 'table-header': string;
123
+ 'table-row': string;
124
+ 'table-col-border': string;
125
+ 'table-border': string;
126
+ [key: string]: string;
127
+ }
128
+ interface ThemeConfig {
129
+ light: Partial<ThemeTokens> & Record<string, string>;
130
+ dark: Partial<ThemeTokens> & Record<string, string>;
131
+ }
132
+
133
+ interface ThemeContextValue {
134
+ theme: Theme;
135
+ setTheme: (theme: Theme) => void;
136
+ mode: ThemeMode;
137
+ setMode: (mode: ThemeMode) => void;
138
+ resolvedMode: ResolvedMode;
139
+ themes: string[];
140
+ }
141
+ interface ThemeProviderProps {
142
+ children: React.ReactNode;
143
+ defaultTheme?: Theme;
144
+ defaultMode?: ThemeMode;
145
+ storageKey?: string | false;
146
+ enableTransitions?: boolean;
147
+ themes?: Record<string, ThemeConfig>;
148
+ attribute?: string;
149
+ }
150
+ declare function ThemeProvider(props: ThemeProviderProps): React.JSX.Element;
151
+
152
+ declare function useTheme(): ThemeContextValue;
153
+
154
+ interface ThemeScriptProps {
155
+ defaultTheme?: string;
156
+ defaultMode?: ThemeMode;
157
+ storageKey?: string;
158
+ attribute?: string;
159
+ }
160
+ /**
161
+ * Renders a <style> block with the default theme's CSS variables plus an inline
162
+ * script that updates them from localStorage before first paint. Place inside
163
+ * <head> of your root layout to prevent flash of unstyled content.
164
+ */
165
+ declare function ThemeScript({ defaultTheme, defaultMode, storageKey, attribute, }: ThemeScriptProps): React.JSX.Element;
166
+
167
+ interface PaletteColor {
168
+ main: string;
169
+ light: string;
170
+ dark: string;
171
+ contrastText: string;
172
+ darkBackground?: string;
173
+ state: {
174
+ containedHover: string;
175
+ outlinedHover: string;
176
+ outlinedResting: string;
177
+ };
178
+ shade: {
179
+ 12: string;
180
+ 16: string;
181
+ };
182
+ }
183
+ interface AlertPaletteColor extends PaletteColor {
184
+ alert: {
185
+ background: string;
186
+ content: string;
187
+ };
188
+ }
189
+ interface StructylScale {
190
+ '50': string;
191
+ '100': string;
192
+ '200': string;
193
+ '300': string;
194
+ '400': string;
195
+ '500': string;
196
+ '600': string;
197
+ '700': string;
198
+ '800': string;
199
+ '900': string;
200
+ A100: string;
201
+ A200: string;
202
+ A400: string;
203
+ A700: string;
204
+ }
205
+ interface StaticPalette {
206
+ yellow: StructylScale;
207
+ amber: StructylScale;
208
+ blue: StructylScale;
209
+ blueGrey: StructylScale;
210
+ brown: StructylScale;
211
+ teal: StructylScale;
212
+ red: StructylScale;
213
+ purple: StructylScale;
214
+ pink: StructylScale;
215
+ orange: StructylScale;
216
+ lime: StructylScale;
217
+ lightGreen: StructylScale;
218
+ cyan: StructylScale;
219
+ deepOrange: StructylScale;
220
+ deepPurple: StructylScale;
221
+ green: StructylScale;
222
+ grey: StructylScale;
223
+ indigo: StructylScale;
224
+ lightBlue: StructylScale;
225
+ }
226
+
227
+ declare const defaultThemes: Record<string, ThemeConfig>;
228
+
229
+ declare const sharedSemanticLight: Partial<ThemeTokens>;
230
+ declare const sharedSemanticDark: Partial<ThemeTokens>;
231
+ declare const staticPalette: StaticPalette;
232
+ declare const generalColors: {
233
+ readonly 'yellow-golden': "rgba(255, 215, 0, 0.6)";
234
+ readonly 'yellow-pale': "rgba(255, 255, 153, 0.4)";
235
+ readonly 'yellow-amber': "rgba(255, 191, 0, 0.7)";
236
+ readonly 'yellow-sunshine': "rgba(255, 239, 0, 0.5)";
237
+ readonly 'yellow-light': "rgba(255, 255, 0, 0.5)";
238
+ readonly 'yellow-warm': "rgba(255, 204, 0, 0.8)";
239
+ readonly 'yellow-soft': "rgba(255, 229, 153, 0.7)";
240
+ readonly 'red-rose': "rgba(255, 51, 51, 0.5)";
241
+ readonly 'red-crimson': "rgba(220, 20, 60, 0.6)";
242
+ readonly 'red-light-coral': "rgba(240, 128, 128, 0.5)";
243
+ readonly 'red-fire-brick': "rgba(178, 34, 34, 0.8)";
244
+ readonly 'red-bright': "rgba(255, 0, 0, 0.7)";
245
+ readonly 'red-soft-coral': "rgba(255, 102, 102, 0.6)";
246
+ readonly 'red-dark': "rgba(204, 0, 0, 0.8)";
247
+ readonly 'blue-turquoise': "rgba(64, 224, 208, 0.6)";
248
+ readonly 'blue-dodger': "rgba(30, 144, 255, 0.5)";
249
+ readonly 'blue-navy': "rgba(0, 0, 128, 0.8)";
250
+ readonly 'blue-steel': "rgba(70, 130, 180, 0.7)";
251
+ readonly 'blue-sky': "rgba(0, 153, 255, 0.5)";
252
+ readonly 'blue-light': "rgba(51, 204, 255, 0.7)";
253
+ readonly 'blue-deep': "rgba(0, 51, 204, 0.8)";
254
+ readonly 'green-lime': "rgba(50, 205, 50, 0.5)";
255
+ readonly 'green-pale': "rgba(152, 251, 152, 0.4)";
256
+ readonly 'green-forest': "rgba(34, 139, 34, 0.7)";
257
+ readonly 'green-olive': "rgba(128, 128, 0, 0.6)";
258
+ readonly 'green-fresh': "rgba(0, 204, 0, 0.6)";
259
+ readonly 'green-soft-mint': "rgba(102, 255, 153, 0.7)";
260
+ readonly 'green-dark': "rgba(0, 153, 76, 0.8)";
261
+ readonly 'orange-tangerine': "rgba(255, 140, 0, 0.6)";
262
+ readonly 'orange-apricot': "rgba(251, 206, 177, 0.5)";
263
+ readonly 'orange-burnt': "rgba(204, 85, 0, 0.7)";
264
+ readonly 'orange-carrot': "rgba(237, 145, 33, 0.6)";
265
+ readonly 'orange-bright': "rgba(255, 102, 0, 0.7)";
266
+ readonly 'orange-soft-peach': "rgba(255, 178, 102, 0.6)";
267
+ readonly 'orange-deep': "rgba(204, 85, 0, 0.8)";
268
+ };
269
+
270
+ /**
271
+ * Color accent presets for @structyl/themes.
272
+ *
273
+ * Built-in presets cover 10 common accent colors. Users can extend the list
274
+ * by creating additional `ColorPreset` objects and passing them to
275
+ * `useColorPreset({ extraPresets: [...] })` or calling `applyColorPreset`
276
+ * with any arbitrary hex color.
277
+ */
278
+ /** A single accent-color preset. */
279
+ interface ColorPreset {
280
+ /** Unique machine-readable identifier. */
281
+ id: string;
282
+ /** Human-readable display name. */
283
+ name: string;
284
+ /** Primary hex color value (e.g. `'#6366f1'`). */
285
+ hex: string;
286
+ }
287
+ /**
288
+ * The 10 built-in accent presets shipped with @structyl/themes.
289
+ * Typed `as const` so that `ColorPresetId` is a precise union of literal IDs.
290
+ */
291
+ declare const COLOR_PRESETS: readonly [{
292
+ readonly id: "structyl";
293
+ readonly name: "Structyl";
294
+ readonly hex: "#5754a3";
295
+ }, {
296
+ readonly id: "indigo";
297
+ readonly name: "Indigo";
298
+ readonly hex: "#6366f1";
299
+ }, {
300
+ readonly id: "ocean";
301
+ readonly name: "Ocean";
302
+ readonly hex: "#0284c7";
303
+ }, {
304
+ readonly id: "rose";
305
+ readonly name: "Rose";
306
+ readonly hex: "#e11d48";
307
+ }, {
308
+ readonly id: "forest";
309
+ readonly name: "Forest";
310
+ readonly hex: "#16a34a";
311
+ }, {
312
+ readonly id: "sunset";
313
+ readonly name: "Sunset";
314
+ readonly hex: "#f97316";
315
+ }, {
316
+ readonly id: "violet";
317
+ readonly name: "Violet";
318
+ readonly hex: "#7c3aed";
319
+ }, {
320
+ readonly id: "slate";
321
+ readonly name: "Slate";
322
+ readonly hex: "#475569";
323
+ }, {
324
+ readonly id: "ember";
325
+ readonly name: "Ember";
326
+ readonly hex: "#be123c";
327
+ }, {
328
+ readonly id: "zinc";
329
+ readonly name: "Zinc";
330
+ readonly hex: "#71717a";
331
+ }];
332
+ /** Union of all built-in preset IDs (e.g. `'structyl' | 'indigo' | 'ocean' | ...`). */
333
+ type ColorPresetId = (typeof COLOR_PRESETS)[number]['id'];
334
+ /**
335
+ * Create a custom preset object. Useful for building typed preset lists
336
+ * that will be passed to `useColorPreset({ extraPresets: [...] })`.
337
+ *
338
+ * @example
339
+ * const myPreset = createColorPreset('brand', 'My Brand', '#ff5500');
340
+ */
341
+ declare function createColorPreset(id: string, name: string, hex: string): ColorPreset;
342
+ /**
343
+ * Apply an accent preset to the document root by overriding the five
344
+ * primary-color CSS custom properties. Safe to call on every theme/mode
345
+ * change — the ThemeProvider will reset base vars first, then this re-applies.
346
+ *
347
+ * No-op in SSR environments.
348
+ *
349
+ * @param hex - The hex color string (e.g. `'#6366f1'`).
350
+ */
351
+ declare function applyColorPreset(hex: string): void;
352
+ /**
353
+ * Remove all CSS custom properties applied by `applyColorPreset`,
354
+ * restoring whatever values the active ThemeProvider theme supplies.
355
+ *
356
+ * No-op in SSR environments.
357
+ */
358
+ declare function clearColorPreset(): void;
359
+
360
+ interface UseColorPresetOptions {
361
+ /**
362
+ * Custom presets to add on top of the 10 built-ins.
363
+ * Built-ins always come first in `presets`.
364
+ *
365
+ * @example
366
+ * const brandPreset = createColorPreset('brand', 'Brand Blue', '#1a6cf0');
367
+ * const { setPreset } = useColorPreset({ extraPresets: [brandPreset] });
368
+ */
369
+ extraPresets?: ColorPreset[];
370
+ /**
371
+ * localStorage key used to persist the active preset across page loads.
372
+ * Override if you need multiple independent pickers on the same origin.
373
+ *
374
+ * @default 'structyl-color-preset'
375
+ */
376
+ storageKey?: string;
377
+ }
378
+ interface UseColorPresetReturn {
379
+ /** All available presets: built-ins first, then any `extraPresets`. */
380
+ presets: ColorPreset[];
381
+ /** ID of the currently active preset, or `null` when using the default theme. */
382
+ activeId: string | null;
383
+ /** Full preset object for the active ID, or `null`. */
384
+ activePreset: ColorPreset | null;
385
+ /**
386
+ * Activate a preset by its `id` and `hex` color.
387
+ * Applies CSS variables immediately and persists to localStorage.
388
+ */
389
+ setPreset: (id: string, hex: string) => void;
390
+ /**
391
+ * Clear the active preset, restoring the ThemeProvider's base theme colors.
392
+ * Also removes the stored value from localStorage.
393
+ */
394
+ clearPreset: () => void;
395
+ }
396
+ /**
397
+ * Manages an accent-color preset on top of the active structyl theme.
398
+ *
399
+ * Must be used inside a `<ThemeProvider>`. Persists the selection to
400
+ * localStorage and re-applies it whenever the base theme or color-mode
401
+ * changes (because ThemeProvider resets `--color-primary` on change).
402
+ *
403
+ * @example
404
+ * function AccentPicker() {
405
+ * const { presets, activeId, setPreset, clearPreset } = useColorPreset();
406
+ * return (
407
+ * <>
408
+ * {presets.map(p => (
409
+ * <button key={p.id} onClick={() => setPreset(p.id, p.hex)}
410
+ * style={{ background: p.hex }}>
411
+ * {p.name}
412
+ * </button>
413
+ * ))}
414
+ * {activeId && <button onClick={clearPreset}>Reset</button>}
415
+ * </>
416
+ * );
417
+ * }
418
+ *
419
+ * @example Adding custom presets
420
+ * const brandPreset = createColorPreset('brand', 'Company Blue', '#1a6cf0');
421
+ * const { presets } = useColorPreset({ extraPresets: [brandPreset] });
422
+ */
423
+ declare function useColorPreset(options?: UseColorPresetOptions): UseColorPresetReturn;
424
+
425
+ export { type AlertPaletteColor, COLOR_PRESETS, type ColorPreset, type ColorPresetId, type PaletteColor, type StaticPalette, type StructylScale, type Theme, type ThemeConfig, type ThemeMode, ThemeProvider, ThemeScript, type ThemeTokens, type UseColorPresetOptions, type UseColorPresetReturn, applyColorPreset, clearColorPreset, createColorPreset, defaultThemes, generalColors, sharedSemanticDark, sharedSemanticLight, staticPalette, useColorPreset, useTheme };