@hadoku/themes 0.0.0-stage → 5.12.15

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (64) hide show
  1. package/LICENSE +21 -0
  2. package/LICENSE-lucide +43 -0
  3. package/README.md +433 -2
  4. package/THEME_USAGE_GUIDE.md +308 -0
  5. package/dist/HadokuThemeRoot.d.ts +53 -0
  6. package/dist/HadokuThemeRoot.js +66 -0
  7. package/dist/ThemeIcons.d.ts +31 -0
  8. package/dist/ThemeIcons.js +91 -0
  9. package/dist/effects.d.ts +25 -0
  10. package/dist/effects.js +25 -0
  11. package/dist/icons/Icon.d.ts +36 -0
  12. package/dist/icons/Icon.js +89 -0
  13. package/dist/icons/index.d.ts +61 -0
  14. package/dist/icons/index.js +87 -0
  15. package/dist/icons/registry.generated.d.ts +158 -0
  16. package/dist/icons/registry.generated.js +446 -0
  17. package/dist/index.d.ts +82 -0
  18. package/dist/index.js +169 -0
  19. package/dist/metadata.d.ts +35 -0
  20. package/dist/metadata.js +108 -0
  21. package/dist/platform/index.d.ts +94 -0
  22. package/dist/platform/index.js +149 -0
  23. package/dist/platform/usePlatform.d.ts +29 -0
  24. package/dist/platform/usePlatform.js +65 -0
  25. package/dist/prefsApiBase.d.ts +37 -0
  26. package/dist/prefsApiBase.js +40 -0
  27. package/dist/theme-types.d.ts +34 -0
  28. package/dist/theme-types.js +1 -0
  29. package/dist/themeContext.d.ts +62 -0
  30. package/dist/themeContext.js +70 -0
  31. package/dist/themePrefs.d.ts +29 -0
  32. package/dist/themePrefs.js +48 -0
  33. package/dist/useRefElement.d.ts +19 -0
  34. package/dist/useRefElement.js +52 -0
  35. package/dist/useTheme.d.ts +46 -0
  36. package/dist/useTheme.js +216 -0
  37. package/package.json +83 -4
  38. package/scripts/audit-tokens.mjs +126 -0
  39. package/scripts/check-contrast.mjs +24 -0
  40. package/scripts/check-docs.mjs +53 -0
  41. package/scripts/check-icons.mjs +473 -0
  42. package/scripts/check-usage.mjs +297 -0
  43. package/scripts/codemod-icons.mjs +396 -0
  44. package/scripts/generate-icons.mjs +199 -0
  45. package/scripts/generate-preview.mjs +374 -0
  46. package/scripts/generate-tailwind-colors.mjs +109 -0
  47. package/scripts/lib/color.mjs +184 -0
  48. package/scripts/lib/contract.d.mts +58 -0
  49. package/scripts/lib/contract.mjs +348 -0
  50. package/scripts/lib/derive.mjs +324 -0
  51. package/scripts/lib/icon-registry.mjs +92 -0
  52. package/scripts/lib/parse-themes.mjs +19 -0
  53. package/scripts/lib/tokens.mjs +188 -0
  54. package/scripts/normalize-tokens.mjs +161 -0
  55. package/src/advanced.css +218 -0
  56. package/src/icons/Icon.tsx +151 -0
  57. package/src/icons/emoji-map.json +202 -0
  58. package/src/icons/index.ts +151 -0
  59. package/src/icons/registry.generated.ts +455 -0
  60. package/src/icons/sources.json +150 -0
  61. package/src/icons.css +145 -0
  62. package/src/style.css +1421 -0
  63. package/src/tailwind-colors.css +88 -0
  64. package/src/tailwind-integration.css +49 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 WolffM
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/LICENSE-lucide ADDED
@@ -0,0 +1,43 @@
1
+ ISC License
2
+
3
+ Copyright (c) 2026 Lucide Icons and Contributors
4
+
5
+ Permission to use, copy, modify, and/or distribute this software for any
6
+ purpose with or without fee is hereby granted, provided that the above
7
+ copyright notice and this permission notice appear in all copies.
8
+
9
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12
+ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16
+
17
+ ---
18
+
19
+ The following Lucide icons are derived from the Feather project:
20
+
21
+ airplay, alert-circle, alert-octagon, alert-triangle, aperture, arrow-down-circle, arrow-down-left, arrow-down-right, arrow-down, arrow-left-circle, arrow-left, arrow-right-circle, arrow-right, arrow-up-circle, arrow-up-left, arrow-up-right, arrow-up, at-sign, calendar, cast, check, chevron-down, chevron-left, chevron-right, chevron-up, chevrons-down, chevrons-left, chevrons-right, chevrons-up, circle, clipboard, clock, code, columns, command, compass, corner-down-left, corner-down-right, corner-left-down, corner-left-up, corner-right-down, corner-right-up, corner-up-left, corner-up-right, crosshair, database, divide-circle, divide-square, dollar-sign, download, external-link, feather, frown, hash, headphones, help-circle, info, italic, key, layout, life-buoy, link-2, link, loader, lock, log-in, log-out, maximize, meh, minimize, minimize-2, minus-circle, minus-square, minus, monitor, moon, more-horizontal, more-vertical, move, music, navigation-2, navigation, octagon, pause-circle, percent, plus-circle, plus-square, plus, power, radio, rss, search, server, share, shopping-bag, sidebar, smartphone, smile, square, table-2, tablet, target, terminal, trash-2, trash, triangle, tv, type, upload, x-circle, x-octagon, x-square, x, zoom-in, zoom-out
22
+
23
+ The MIT License (MIT) (for the icons listed above)
24
+
25
+ Copyright (c) 2013-present Cole Bemis
26
+
27
+ Permission is hereby granted, free of charge, to any person obtaining a copy
28
+ of this software and associated documentation files (the "Software"), to deal
29
+ in the Software without restriction, including without limitation the rights
30
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
31
+ copies of the Software, and to permit persons to whom the Software is
32
+ furnished to do so, subject to the following conditions:
33
+
34
+ The above copyright notice and this permission notice shall be included in all
35
+ copies or substantial portions of the Software.
36
+
37
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
38
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
39
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
40
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
41
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
42
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
43
+ SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,434 @@
1
- # Temporary Holding Version
1
+ # @wolffm/themes
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ Beautiful color themes using CSS custom properties. Framework-agnostic and ready to use in any web project.
4
+
5
+ ## Themes
6
+
7
+ 9 theme families (18 themes), each with light and dark variants:
8
+
9
+ - **Light** (default) / **Dark** - Clean blue and white / Sophisticated midnight with purple accents
10
+ - **Strawberry** Light/Dark - Sweet pink tones
11
+ - **Ocean** Light/Dark - Deep sea blues and tropical coral
12
+ - **Cyberpunk** Light/Dark - Neon dystopia with electric colors
13
+ - **Coffee** Light/Dark - Rich espresso and cream tones
14
+ - **Lavender** Light/Dark - Soft purple elegance
15
+ - **Nature** Light/Dark - Lush leaf greens inspired by forests and earth
16
+ - **Pink** Light/Dark - Bubblegum pink and neon glows
17
+ - **Izakaya** Light/Dark - Japanese izakaya-inspired warm tones (Kitsune contest winner)
18
+
19
+ ## Installation
20
+
21
+ ```bash
22
+ npm install @wolffm/themes
23
+ ```
24
+
25
+ ## Usage
26
+
27
+ ### Import CSS
28
+
29
+ ```javascript
30
+ import '@wolffm/themes/style.css'
31
+ ```
32
+
33
+ ### Use Theme Utilities
34
+
35
+ ```typescript
36
+ import { setTheme, loadTheme, saveTheme, THEMES } from '@wolffm/themes'
37
+
38
+ // Set theme (applies immediately)
39
+ setTheme('dark')
40
+ setTheme('cyberpunk-dark')
41
+
42
+ // Save to sessionStorage and apply
43
+ saveTheme('lavender-light')
44
+
45
+ // Load saved theme on app start
46
+ const theme = loadTheme()
47
+
48
+ // Get all available themes
49
+ console.log(THEMES) // ['light', 'dark', 'strawberry-light', ...]
50
+ ```
51
+
52
+ ### Apply to HTML
53
+
54
+ ```html
55
+ <!-- Set globally on html element -->
56
+ <html data-theme="dark">
57
+ <!-- Or on a specific container -->
58
+ <div data-theme="strawberry-light">
59
+ <!-- Your content -->
60
+ </div>
61
+ </html>
62
+ ```
63
+
64
+ ## CSS Variables
65
+
66
+ Each theme defines 47 variables (41 color + 6 shadow). Color variables use the
67
+ `--color-*` namespace — which is also Tailwind v4's — so they map straight to
68
+ utilities. Everything else is namespaced `--hdk-*` to avoid colliding with
69
+ Tailwind internals.
70
+
71
+ > **Which token do I use for X?** → [`THEME_USAGE_GUIDE.md`](./THEME_USAGE_GUIDE.md).
72
+ > That is the doc to read (and to point agents at) before writing any styles.
73
+
74
+ ### Colors — 5 semantic families × 6 tokens
75
+
76
+ Every family carries an identical set. The rectangle is the point: the
77
+ symmetric guess is always correct.
78
+
79
+ | | fill | gradient/pressed | tint | hover overlay | text on fill | text on tint |
80
+ | --------- | ----------------- | ---------------- | ----- | ------------- | -------------------- | ----------------------- |
81
+ | `primary` | `--color-primary` | `-dark` | `-bg` | `-hover` | `--color-on-primary` | `--color-on-primary-bg` |
82
+ | `success` | `--color-success` | `-dark` | `-bg` | `-hover` | `--color-on-success` | `--color-on-success-bg` |
83
+ | `warning` | `--color-warning` | `-dark` | `-bg` | `-hover` | `--color-on-warning` | `--color-on-warning-bg` |
84
+ | `danger` | `--color-danger` | `-dark` | `-bg` | `-hover` | `--color-on-danger` | `--color-on-danger-bg` |
85
+ | `neutral` | `--color-neutral` | `-dark` | `-bg` | `-hover` | `--color-on-neutral` | `--color-on-neutral-bg` |
86
+
87
+ ### Colors — structural
88
+
89
+ - `--color-text` (+ `-secondary`, `-tertiary`, `-muted`)
90
+ - `--color-border` (+ `-light`)
91
+ - `--color-bg` (+ `-card`, `-alt`, `-hover`, `-overlay`)
92
+
93
+ Every `on-*` pair is verified ≥4.5:1 against its surface in all 18 themes by
94
+ `scripts/check-contrast.mjs`.
95
+
96
+ ### Typography
97
+
98
+ - `--font-family`
99
+ - `--hdk-text-*` (xs, sm, md, base, lg) - font sizes
100
+ - `--font-weight-*` (normal, semibold, bold)
101
+ - `--line-height-*` (normal, relaxed)
102
+
103
+ ### Spacing
104
+
105
+ - `--hdk-space-*` (xs, sm, md, lg, xl, 2xl, 3xl, 4xl, 5xl)
106
+
107
+ ### Layout
108
+
109
+ - `--hdk-radius` (+ sm, lg variants) - border radius
110
+ - `--hdk-shadow-*` (sm, md, lg, focus, focus-sm, focus-alt)
111
+
112
+ ### Transitions
113
+
114
+ - `--transition-fast`
115
+ - `--transition-smooth`
116
+
117
+ ### Usage Example
118
+
119
+ ```css
120
+ .my-button {
121
+ background: var(--color-primary);
122
+ color: var(--color-on-primary);
123
+ padding: var(--hdk-space-md) var(--hdk-space-xl);
124
+ border-radius: var(--hdk-radius);
125
+ font-size: var(--hdk-text-base);
126
+ box-shadow: var(--hdk-shadow-sm);
127
+ transition: var(--transition-fast);
128
+ }
129
+
130
+ .my-button:hover {
131
+ background: var(--color-primary-dark);
132
+ box-shadow: var(--hdk-shadow-md);
133
+ }
134
+ ```
135
+
136
+ ## Tailwind v4 Compatibility
137
+
138
+ This package uses namespaced CSS variables (`--hdk-*`) to avoid collisions with Tailwind v4's internal variables.
139
+
140
+ ### Why Namespacing?
141
+
142
+ Tailwind v4 uses CSS custom properties internally:
143
+
144
+ - `--spacing-*` powers `max-w-md`, `p-4`, `gap-*`, etc.
145
+ - `--radius-*` powers `rounded-md`, `rounded-lg`, etc.
146
+ - `--font-size-*` powers `text-sm`, `text-base`, etc.
147
+ - `--shadow-*` powers `shadow-sm`, `shadow-md`, etc.
148
+
149
+ Without namespacing, a theme variable like `--spacing-md: 8px` would break `max-w-md` (changing it from 28rem to 8px).
150
+
151
+ ### Variable Mapping
152
+
153
+ | Old Name (v1.x) | New Name (v2.x) |
154
+ | ----------------- | ----------------- |
155
+ | `--spacing-md` | `--hdk-space-md` |
156
+ | `--font-size-sm` | `--hdk-text-sm` |
157
+ | `--border-radius` | `--hdk-radius` |
158
+ | `--shadow-sm` | `--hdk-shadow-sm` |
159
+ | `--shadow-modal` | `--hdk-shadow-lg` |
160
+
161
+ ### Tailwind Integration
162
+
163
+ Three imports, no hand-written `@theme` block:
164
+
165
+ ```css
166
+ @import '@wolffm/themes/style.css'; /* 1. tokens — MUST be unlayered */
167
+ @import 'tailwindcss'; /* 2. Tailwind */
168
+ @import '@wolffm/themes/tailwind-colors.css'; /* 3. all 41 colours */
169
+ @import '@wolffm/themes/tailwind-integration.css'; /* 4. radius/shadow/type (optional) */
170
+ ```
171
+
172
+ You now get `bg-primary`, `text-on-primary`, `bg-success-bg`,
173
+ `text-on-danger-bg`, `border-border`, `bg-bg-card` — every token, as a utility.
174
+
175
+ **Never hand-roll a `@theme` colour block.** A local copy is exactly the drift
176
+ this package exists to prevent; `tailwind-colors.css` is generated from
177
+ `style.css` and CI fails if the two disagree.
178
+
179
+ **Step 1 must stay unlayered.** Tailwind emits each `@theme` entry into
180
+ `@layer theme` as `:root { --x: var(--x) }`, which is self-referential and
181
+ invalid on its own. It resolves only because `style.css` declares the same
182
+ properties outside any cascade layer, and unlayered wins. Import it with
183
+ `layer(...)` and all 41 colours silently become `transparent`.
184
+
185
+ `tailwind-integration.css` (step 4) is separate and optional — it maps
186
+ `--hdk-*` radius/shadow/type onto `rounded-*`, `shadow-*`, `text-*`.
187
+
188
+ ### Migration from v1.x
189
+
190
+ Search and replace in your CSS:
191
+
192
+ ```
193
+ var(--spacing- → var(--hdk-space-
194
+ var(--font-size- → var(--hdk-text-
195
+ var(--border-radius → var(--hdk-radius
196
+ var(--shadow- → var(--hdk-shadow-
197
+ var(--shadow-modal) → var(--hdk-shadow-lg)
198
+ ```
199
+
200
+ ## React Integration
201
+
202
+ ### Using the `useTheme` Hook (Recommended)
203
+
204
+ ```tsx
205
+ import { useTheme, THEME_FAMILIES, THEME_ICON_MAP } from '@wolffm/themes'
206
+ import { ConnectedThemePicker } from '@wolffm/task-ui-components'
207
+ import '@wolffm/themes/style.css'
208
+ import '@wolffm/task-ui-components/theme-picker.css'
209
+
210
+ function App() {
211
+ const { theme, setTheme } = useTheme()
212
+
213
+ return (
214
+ <ConnectedThemePicker
215
+ themeFamilies={THEME_FAMILIES}
216
+ currentTheme={theme}
217
+ onThemeChange={setTheme}
218
+ getThemeIcon={theme => {
219
+ const Icon = THEME_ICON_MAP[theme]
220
+ return Icon ? <Icon /> : null
221
+ }}
222
+ />
223
+ )
224
+ }
225
+ ```
226
+
227
+ ### Manual React Integration
228
+
229
+ ```tsx
230
+ import { useEffect, useState } from 'react'
231
+ import { loadTheme, setTheme, THEMES, type Theme } from '@wolffm/themes'
232
+ import '@wolffm/themes/style.css'
233
+
234
+ function App() {
235
+ const [theme, setThemeState] = useState<Theme>('light')
236
+
237
+ useEffect(() => {
238
+ const savedTheme = loadTheme()
239
+ setThemeState(savedTheme)
240
+ }, [])
241
+
242
+ const handleThemeChange = (newTheme: Theme) => {
243
+ setTheme(newTheme)
244
+ setThemeState(newTheme)
245
+ }
246
+
247
+ return (
248
+ <select value={theme} onChange={e => handleThemeChange(e.target.value as Theme)}>
249
+ {THEMES.map(t => (
250
+ <option key={t} value={t}>
251
+ {t}
252
+ </option>
253
+ ))}
254
+ </select>
255
+ )
256
+ }
257
+ ```
258
+
259
+ ## Framework Examples
260
+
261
+ ### Vue
262
+
263
+ ```vue
264
+ <script setup lang="ts">
265
+ import { ref, onMounted } from 'vue'
266
+ import { loadTheme, setTheme, THEMES, type Theme } from '@wolffm/themes'
267
+ import '@wolffm/themes/style.css'
268
+
269
+ const theme = ref<Theme>('light')
270
+
271
+ onMounted(() => {
272
+ theme.value = loadTheme()
273
+ })
274
+
275
+ const handleThemeChange = (newTheme: Theme) => {
276
+ setTheme(newTheme)
277
+ theme.value = newTheme
278
+ }
279
+ </script>
280
+
281
+ <template>
282
+ <select v-model="theme" @change="handleThemeChange(theme)">
283
+ <option v-for="t in THEMES" :key="t" :value="t">{{ t }}</option>
284
+ </select>
285
+ </template>
286
+ ```
287
+
288
+ ### Vanilla JS
289
+
290
+ ```javascript
291
+ import { loadTheme, setTheme, THEMES } from '@wolffm/themes'
292
+ import '@wolffm/themes/style.css'
293
+
294
+ // Load saved theme on page load
295
+ document.addEventListener('DOMContentLoaded', () => {
296
+ loadTheme()
297
+
298
+ // Theme switcher
299
+ const select = document.getElementById('theme-select')
300
+ THEMES.forEach(theme => {
301
+ const option = document.createElement('option')
302
+ option.value = theme
303
+ option.textContent = theme
304
+ select.appendChild(option)
305
+ })
306
+
307
+ select.addEventListener('change', e => {
308
+ setTheme(e.target.value)
309
+ })
310
+ })
311
+ ```
312
+
313
+ ## Theme Editor
314
+
315
+ Hosted at **https://hadoku.me/task/editor** (service tier and up). Pick a theme,
316
+ drag sliders, and the app's real components recolour live; **Save** commits the
317
+ change to `main` under a new version, which publishes.
318
+
319
+ - **Per token** — brightness / saturation / hue / opacity sliders (OKLCH, so a
320
+ brightness step looks even across hues) plus a typed value
321
+ - **Per group** — Surfaces, Text and each semantic family can be shifted at once
322
+ - **Contract** — the same checks `lint:css` runs (`scripts/lib/contract.mjs`,
323
+ exported as `@wolffm/themes/contract`), live; a failure blocks Save, and the
324
+ save route re-checks before committing
325
+ - **Comfort** — advisory meters for what AA cannot see: page glare, card-vs-page
326
+ separation, border visibility, text harshness, and whether `success` / `warning`
327
+ / `danger` still read as their meaning
328
+
329
+ The editor ships as `@wolffm/task/editor` (src/editor/ in the repo root); its
330
+ save route is `worker/src/routes/theme-editor.ts`. Locally, `pnpm run dev:api`
331
+ plus `vite` serve it at `/editor.html` against an in-memory GitHub — a local
332
+ save never touches the real repo.
333
+
334
+ ## API Reference
335
+
336
+ ### React Utilities (New in v1.1.3+)
337
+
338
+ #### `useTheme(): { theme: Theme, setTheme: (theme: Theme) => void }`
339
+
340
+ React hook for stateful theme management. Automatically saves to sessionStorage and syncs across tabs.
341
+
342
+ ```tsx
343
+ const { theme, setTheme } = useTheme()
344
+ ```
345
+
346
+ #### `THEME_FAMILIES: ThemeFamily[]`
347
+
348
+ Pre-configured array of all 9 theme families with icons and labels. Use with `ThemePicker` or `ConnectedThemePicker` components from `@wolffm/task-ui-components`.
349
+
350
+ ```tsx
351
+ import { THEME_FAMILIES } from '@wolffm/themes'
352
+ // Each family includes: lightTheme, darkTheme, lightLabel, darkLabel, lightIcon, darkIcon
353
+ ```
354
+
355
+ #### `THEME_ICON_MAP: Record<Theme, IconComponent>`
356
+
357
+ Map of theme names to their corresponding icon components.
358
+
359
+ ```tsx
360
+ import { THEME_ICON_MAP } from '@wolffm/themes'
361
+ const Icon = THEME_ICON_MAP['cyberpunk-dark']
362
+ ```
363
+
364
+ ### Core Functions
365
+
366
+ #### `setTheme(theme: Theme): void`
367
+
368
+ Apply a theme immediately. Sets `data-theme` attribute on `<html>` element.
369
+
370
+ #### `getTheme(): Theme`
371
+
372
+ Get the currently active theme.
373
+
374
+ #### `saveTheme(theme: Theme): void`
375
+
376
+ Save theme to sessionStorage and apply it.
377
+
378
+ #### `loadTheme(): Theme`
379
+
380
+ Load saved theme from sessionStorage, apply it, and return the theme name. Respects browser's `prefers-color-scheme` preference if no saved theme. Returns 'light' if no preference.
381
+
382
+ #### `initTheme(): Theme`
383
+
384
+ Convenience function. Same as `loadTheme()`.
385
+
386
+ #### `clearTheme(): void`
387
+
388
+ Remove saved theme and reset to 'light'.
389
+
390
+ ### Types
391
+
392
+ ```typescript
393
+ type Theme =
394
+ | 'light'
395
+ | 'dark'
396
+ | 'strawberry-light'
397
+ | 'strawberry-dark'
398
+ | 'ocean-light'
399
+ | 'ocean-dark'
400
+ | 'cyberpunk-light'
401
+ | 'cyberpunk-dark'
402
+ | 'coffee-light'
403
+ | 'coffee-dark'
404
+ | 'lavender-light'
405
+ | 'lavender-dark'
406
+ | 'nature-light'
407
+ | 'nature-dark'
408
+ | 'pink-light'
409
+ | 'pink-dark'
410
+ | 'izakaya-light'
411
+ | 'izakaya-dark'
412
+
413
+ const THEMES: readonly Theme[]
414
+ ```
415
+
416
+ ## Browser Support
417
+
418
+ Works in all modern browsers that support:
419
+
420
+ - CSS Custom Properties (CSS Variables)
421
+ - ES2022 modules
422
+ - sessionStorage
423
+
424
+ ## License
425
+
426
+ MIT
427
+
428
+ ## Author
429
+
430
+ WolffM - [GitHub](https://github.com/WolffM)
431
+
432
+ ## Related Packages
433
+
434
+ - [@wolffm/task](https://github.com/WolffM/hadoku-task) - Task management micro-frontend using these themes