@codenhub/theme 0.1.0 → 0.1.1
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/LICENSE +201 -201
- package/README.md +20 -429
- package/dist/index.d.ts +31 -6
- package/dist/index.js +1 -1
- package/docs/index.md +52 -0
- package/docs/reference.md +104 -0
- package/llms-full.txt +204 -0
- package/llms.txt +13 -0
- package/package.json +12 -3
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Reference
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
# Theme API, Persistence, DOM, and SSR Behavior
|
|
6
|
+
|
|
7
|
+
## Create and Initialize
|
|
8
|
+
|
|
9
|
+
`createTheme<TSchema>(options?): Theme<TSchema>` validates configuration and
|
|
10
|
+
creates a manager. `ThemeOptions` contains:
|
|
11
|
+
|
|
12
|
+
- `themes`: definitions, defaulting to `LIGHT_THEME` and `DARK_THEME`.
|
|
13
|
+
- `defaultTheme`: pre-init and SSR fallback, default `"light"`.
|
|
14
|
+
- `systemTheme`: configured names for light/dark OS preference.
|
|
15
|
+
- `storageKey`: `localStorage` key, default `"app-theme-preference"`.
|
|
16
|
+
- `attribute`: document-root attribute, default `"data-theme"`.
|
|
17
|
+
- `isTailwindCss`: toggle the root `dark` class, default `false`.
|
|
18
|
+
- `shouldApplyClass`: add `theme-${name}` by default, disable classes, or return
|
|
19
|
+
one custom class token with a `ThemeClassResolver`.
|
|
20
|
+
- `tokenSchema`: maps typed token names to CSS custom-property names.
|
|
21
|
+
|
|
22
|
+
`ThemeDefinition` has a unique `name`, `colorScheme` (`light` or `dark`),
|
|
23
|
+
optional static tokens, and optional `pairedTheme` target for `toggle()`.
|
|
24
|
+
`SystemThemeMap` maps OS light and dark preferences.
|
|
25
|
+
|
|
26
|
+
`init(tokens?)` is idempotent until `destroy()`. It registers media-query and
|
|
27
|
+
cross-tab storage listeners, selects valid stored preference before system
|
|
28
|
+
preference, applies the theme, and emits an `"init"` change.
|
|
29
|
+
|
|
30
|
+
## Theme Operations
|
|
31
|
+
|
|
32
|
+
- `get(options?)` returns the active definition. Tokens merge computed CSS values,
|
|
33
|
+
static theme values, then runtime overrides. Reading computed values can force
|
|
34
|
+
style calculation; pass `{ skipComputed: true }` to bypass reading computed DOM styles.
|
|
35
|
+
- `set(name, tokens?)` applies and persists a configured theme; unknown names
|
|
36
|
+
throw.
|
|
37
|
+
- `toggle(tokens?)` switches to `pairedTheme` if defined on the active theme, or
|
|
38
|
+
otherwise by active `colorScheme` between the names in `systemTheme`, then
|
|
39
|
+
persists the choice.
|
|
40
|
+
- `clearPreference()` removes storage and applies the current system theme.
|
|
41
|
+
- `getStored()` returns a valid configured stored name or `null`.
|
|
42
|
+
- `getSystem()` returns the mapped system theme, or `defaultTheme` when media
|
|
43
|
+
queries are unavailable.
|
|
44
|
+
- `getPrePaintScript()` returns a synchronous inline IIFE script string to inject
|
|
45
|
+
into document `<head>` to prevent flash of unstyled content (FOUC). Supports custom
|
|
46
|
+
class resolvers and static token custom properties. Also available as standalone export
|
|
47
|
+
`getPrePaintScript(options?)`.
|
|
48
|
+
|
|
49
|
+
Runtime token overrides persist across theme changes. Passing a new object,
|
|
50
|
+
including `{}`, replaces them. Tokens require a schema and unknown token keys
|
|
51
|
+
throw.
|
|
52
|
+
|
|
53
|
+
## DOM, Persistence, and Events
|
|
54
|
+
|
|
55
|
+
Applying a theme sets the configured root attribute and
|
|
56
|
+
`document.documentElement.style.colorScheme`, updates configured theme classes,
|
|
57
|
+
toggles Tailwind's `dark` class when enabled, and writes mapped token values as
|
|
58
|
+
CSS custom properties. The package supplies no CSS or token values beyond the
|
|
59
|
+
built-in light/dark definitions.
|
|
60
|
+
|
|
61
|
+
Explicit preferences use `localStorage`. `storage` events synchronize valid
|
|
62
|
+
changes from other tabs. OS preference changes apply only while no valid stored
|
|
63
|
+
preference exists. Storage read/write/remove failures are logged with
|
|
64
|
+
`console.error` and treated as unavailable.
|
|
65
|
+
|
|
66
|
+
`subscribe(ThemeChangeListener)` returns an unsubscribe function. Subscribers
|
|
67
|
+
receive `ThemeChangeDetail` with `name`, `theme`, and `ThemeChangeSource`:
|
|
68
|
+
`"init"`, `"set"`, `"toggle"`, `"clearPreference"`, or `"system"`. Subscriber
|
|
69
|
+
errors are logged and do not stop later listeners. Browsers also receive a
|
|
70
|
+
window `CustomEvent` named by `THEME_CHANGE_EVENT` (`"themechange"`).
|
|
71
|
+
|
|
72
|
+
## Validation and Cleanup
|
|
73
|
+
|
|
74
|
+
Creation throws for invalid attributes/storage keys, malformed or duplicate
|
|
75
|
+
themes, invalid color schemes/classes/token schemas, and missing default/system
|
|
76
|
+
theme names. Applying a custom class resolver can throw if it returns an empty
|
|
77
|
+
or whitespace-containing class. Runtime token calls throw without a matching
|
|
78
|
+
schema.
|
|
79
|
+
|
|
80
|
+
`destroy(options?)` removes media-query and storage listeners, clears
|
|
81
|
+
in-process subscribers and runtime tokens, and resets internal active state.
|
|
82
|
+
By default, it does not remove persisted preference or revert attributes,
|
|
83
|
+
classes, custom properties, or `colorScheme` already applied to the document;
|
|
84
|
+
pass `{ revertDom: true }` to remove configured DOM attributes, classes, and
|
|
85
|
+
CSS custom properties from `document.documentElement`.
|
|
86
|
+
|
|
87
|
+
## SSR and Pre-Paint Behavior
|
|
88
|
+
|
|
89
|
+
Without browser APIs, storage, DOM, events, and listeners are skipped;
|
|
90
|
+
`getSystem()` uses `defaultTheme`. Calls remain usable but cannot produce server
|
|
91
|
+
HTML attributes. To avoid a flash, applications must apply equivalent validated
|
|
92
|
+
storage/system logic in a blocking pre-paint script or render matching server
|
|
93
|
+
markup. Keep that logic aligned with custom names, mappings, storage key,
|
|
94
|
+
attribute, classes, and color scheme. Note that `getPrePaintScript()` serializes
|
|
95
|
+
static tokens defined on configured theme definitions (`ThemeDefinition.tokens`);
|
|
96
|
+
runtime token overrides passed to `init(tokens)` or `set(name, tokens)` are applied
|
|
97
|
+
during client-side execution after hydration.
|
|
98
|
+
|
|
99
|
+
## Public Exports
|
|
100
|
+
|
|
101
|
+
The root exports `createTheme`, `getPrePaintScript`, `THEME_CHANGE_EVENT`,
|
|
102
|
+
`LIGHT_THEME`, and `DARK_THEME`, plus `Theme`, `ThemeDefinition`, `SystemThemeMap`,
|
|
103
|
+
`ThemeClassResolver`, `ThemeChangeSource`, `ThemeChangeDetail`,
|
|
104
|
+
`ThemeChangeListener`, and `ThemeOptions` types.
|
package/llms-full.txt
ADDED
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
<!-- Source: README.md -->
|
|
2
|
+
|
|
3
|
+
# @codenhub/theme
|
|
4
|
+
|
|
5
|
+
Zero-dependency browser theme preference, persistence, DOM, and token manager.
|
|
6
|
+
|
|
7
|
+
## Installation
|
|
8
|
+
|
|
9
|
+
```sh
|
|
10
|
+
pnpm add @codenhub/theme
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Usage
|
|
14
|
+
|
|
15
|
+
```ts
|
|
16
|
+
import { createTheme, getPrePaintScript } from "@codenhub/theme";
|
|
17
|
+
|
|
18
|
+
const theme = createTheme().init();
|
|
19
|
+
theme.set("dark");
|
|
20
|
+
|
|
21
|
+
// Get inline IIFE script string for <head> to prevent FOUC:
|
|
22
|
+
const script = theme.getPrePaintScript(); // or standalone getPrePaintScript()
|
|
23
|
+
|
|
24
|
+
// Remove media-query/storage listeners and subscribers on teardown.
|
|
25
|
+
theme.destroy({ revertDom: true });
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## Documentation
|
|
29
|
+
|
|
30
|
+
- [Documentation overview](docs/index.md)
|
|
31
|
+
- [API, persistence, DOM, and SSR behavior](docs/reference.md)
|
|
32
|
+
|
|
33
|
+
## Requirements
|
|
34
|
+
|
|
35
|
+
- Browser integration uses `document.documentElement`, `localStorage`,
|
|
36
|
+
`matchMedia`, `storage` events, and `CustomEvent`.
|
|
37
|
+
- SSR is supported by skipping unavailable browser work and using the configured
|
|
38
|
+
default theme.
|
|
39
|
+
- Consumers provide CSS selectors, variables, visual tokens, and any pre-paint
|
|
40
|
+
script needed to prevent a theme flash.
|
|
41
|
+
|
|
42
|
+
## Notes
|
|
43
|
+
|
|
44
|
+
Construction validates theme names, mappings, attributes, classes, and token
|
|
45
|
+
schemas and throws on invalid configuration. Storage failures are reported to
|
|
46
|
+
the console and treated as unavailable storage.
|
|
47
|
+
|
|
48
|
+
## License
|
|
49
|
+
|
|
50
|
+
Licensed under Apache-2.0.
|
|
51
|
+
|
|
52
|
+
<!-- Source: docs/index.md -->
|
|
53
|
+
|
|
54
|
+
# Manage Browser Themes
|
|
55
|
+
|
|
56
|
+
`@codenhub/theme` resolves stored and system theme preferences, applies theme
|
|
57
|
+
state to the document root, synchronizes browser tabs, exposes change events,
|
|
58
|
+
and maps typed tokens to CSS custom properties.
|
|
59
|
+
|
|
60
|
+
It fits browser applications that need one owner for theme preference and DOM
|
|
61
|
+
synchronization while keeping selectors, visual design, and CSS in application
|
|
62
|
+
code.
|
|
63
|
+
|
|
64
|
+
## Setup
|
|
65
|
+
|
|
66
|
+
### Installation
|
|
67
|
+
|
|
68
|
+
```sh
|
|
69
|
+
pnpm add @codenhub/theme
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
### Quick start
|
|
73
|
+
|
|
74
|
+
```ts
|
|
75
|
+
import { createTheme } from "@codenhub/theme";
|
|
76
|
+
|
|
77
|
+
const theme = createTheme().init();
|
|
78
|
+
theme.set("dark");
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
Call `destroy()` when the manager's owner is removed. The package persists an
|
|
82
|
+
explicit preference and follows system preference when appropriate.
|
|
83
|
+
|
|
84
|
+
## Requirements
|
|
85
|
+
|
|
86
|
+
- Browser integration uses `document.documentElement`, `localStorage`,
|
|
87
|
+
`matchMedia`, `storage` events, and `CustomEvent`.
|
|
88
|
+
- SSR is supported by skipping unavailable browser work and using the configured
|
|
89
|
+
default theme.
|
|
90
|
+
- Consumers provide CSS selectors, variables, visual tokens, and any pre-paint
|
|
91
|
+
script needed to prevent a theme flash.
|
|
92
|
+
|
|
93
|
+
The package cannot produce server HTML attributes or prevent a flash before
|
|
94
|
+
initialization. Applications that need pre-paint consistency must apply matching
|
|
95
|
+
theme logic before rendering.
|
|
96
|
+
|
|
97
|
+
## Next steps
|
|
98
|
+
|
|
99
|
+
- [API, persistence, DOM, and SSR behavior](docs/reference.md): Complete exports,
|
|
100
|
+
configuration, tokens, browser synchronization, validation, pre-paint
|
|
101
|
+
concerns, and cleanup.
|
|
102
|
+
|
|
103
|
+
<!-- Source: docs/reference.md -->
|
|
104
|
+
|
|
105
|
+
# Theme API, Persistence, DOM, and SSR Behavior
|
|
106
|
+
|
|
107
|
+
## Create and Initialize
|
|
108
|
+
|
|
109
|
+
`createTheme<TSchema>(options?): Theme<TSchema>` validates configuration and
|
|
110
|
+
creates a manager. `ThemeOptions` contains:
|
|
111
|
+
|
|
112
|
+
- `themes`: definitions, defaulting to `LIGHT_THEME` and `DARK_THEME`.
|
|
113
|
+
- `defaultTheme`: pre-init and SSR fallback, default `"light"`.
|
|
114
|
+
- `systemTheme`: configured names for light/dark OS preference.
|
|
115
|
+
- `storageKey`: `localStorage` key, default `"app-theme-preference"`.
|
|
116
|
+
- `attribute`: document-root attribute, default `"data-theme"`.
|
|
117
|
+
- `isTailwindCss`: toggle the root `dark` class, default `false`.
|
|
118
|
+
- `shouldApplyClass`: add `theme-${name}` by default, disable classes, or return
|
|
119
|
+
one custom class token with a `ThemeClassResolver`.
|
|
120
|
+
- `tokenSchema`: maps typed token names to CSS custom-property names.
|
|
121
|
+
|
|
122
|
+
`ThemeDefinition` has a unique `name`, `colorScheme` (`light` or `dark`),
|
|
123
|
+
optional static tokens, and optional `pairedTheme` target for `toggle()`.
|
|
124
|
+
`SystemThemeMap` maps OS light and dark preferences.
|
|
125
|
+
|
|
126
|
+
`init(tokens?)` is idempotent until `destroy()`. It registers media-query and
|
|
127
|
+
cross-tab storage listeners, selects valid stored preference before system
|
|
128
|
+
preference, applies the theme, and emits an `"init"` change.
|
|
129
|
+
|
|
130
|
+
## Theme Operations
|
|
131
|
+
|
|
132
|
+
- `get(options?)` returns the active definition. Tokens merge computed CSS values,
|
|
133
|
+
static theme values, then runtime overrides. Reading computed values can force
|
|
134
|
+
style calculation; pass `{ skipComputed: true }` to bypass reading computed DOM styles.
|
|
135
|
+
- `set(name, tokens?)` applies and persists a configured theme; unknown names
|
|
136
|
+
throw.
|
|
137
|
+
- `toggle(tokens?)` switches to `pairedTheme` if defined on the active theme, or
|
|
138
|
+
otherwise by active `colorScheme` between the names in `systemTheme`, then
|
|
139
|
+
persists the choice.
|
|
140
|
+
- `clearPreference()` removes storage and applies the current system theme.
|
|
141
|
+
- `getStored()` returns a valid configured stored name or `null`.
|
|
142
|
+
- `getSystem()` returns the mapped system theme, or `defaultTheme` when media
|
|
143
|
+
queries are unavailable.
|
|
144
|
+
- `getPrePaintScript()` returns a synchronous inline IIFE script string to inject
|
|
145
|
+
into document `<head>` to prevent flash of unstyled content (FOUC). Supports custom
|
|
146
|
+
class resolvers and static token custom properties. Also available as standalone export
|
|
147
|
+
`getPrePaintScript(options?)`.
|
|
148
|
+
|
|
149
|
+
Runtime token overrides persist across theme changes. Passing a new object,
|
|
150
|
+
including `{}`, replaces them. Tokens require a schema and unknown token keys
|
|
151
|
+
throw.
|
|
152
|
+
|
|
153
|
+
## DOM, Persistence, and Events
|
|
154
|
+
|
|
155
|
+
Applying a theme sets the configured root attribute and
|
|
156
|
+
`document.documentElement.style.colorScheme`, updates configured theme classes,
|
|
157
|
+
toggles Tailwind's `dark` class when enabled, and writes mapped token values as
|
|
158
|
+
CSS custom properties. The package supplies no CSS or token values beyond the
|
|
159
|
+
built-in light/dark definitions.
|
|
160
|
+
|
|
161
|
+
Explicit preferences use `localStorage`. `storage` events synchronize valid
|
|
162
|
+
changes from other tabs. OS preference changes apply only while no valid stored
|
|
163
|
+
preference exists. Storage read/write/remove failures are logged with
|
|
164
|
+
`console.error` and treated as unavailable.
|
|
165
|
+
|
|
166
|
+
`subscribe(ThemeChangeListener)` returns an unsubscribe function. Subscribers
|
|
167
|
+
receive `ThemeChangeDetail` with `name`, `theme`, and `ThemeChangeSource`:
|
|
168
|
+
`"init"`, `"set"`, `"toggle"`, `"clearPreference"`, or `"system"`. Subscriber
|
|
169
|
+
errors are logged and do not stop later listeners. Browsers also receive a
|
|
170
|
+
window `CustomEvent` named by `THEME_CHANGE_EVENT` (`"themechange"`).
|
|
171
|
+
|
|
172
|
+
## Validation and Cleanup
|
|
173
|
+
|
|
174
|
+
Creation throws for invalid attributes/storage keys, malformed or duplicate
|
|
175
|
+
themes, invalid color schemes/classes/token schemas, and missing default/system
|
|
176
|
+
theme names. Applying a custom class resolver can throw if it returns an empty
|
|
177
|
+
or whitespace-containing class. Runtime token calls throw without a matching
|
|
178
|
+
schema.
|
|
179
|
+
|
|
180
|
+
`destroy(options?)` removes media-query and storage listeners, clears
|
|
181
|
+
in-process subscribers and runtime tokens, and resets internal active state.
|
|
182
|
+
By default, it does not remove persisted preference or revert attributes,
|
|
183
|
+
classes, custom properties, or `colorScheme` already applied to the document;
|
|
184
|
+
pass `{ revertDom: true }` to remove configured DOM attributes, classes, and
|
|
185
|
+
CSS custom properties from `document.documentElement`.
|
|
186
|
+
|
|
187
|
+
## SSR and Pre-Paint Behavior
|
|
188
|
+
|
|
189
|
+
Without browser APIs, storage, DOM, events, and listeners are skipped;
|
|
190
|
+
`getSystem()` uses `defaultTheme`. Calls remain usable but cannot produce server
|
|
191
|
+
HTML attributes. To avoid a flash, applications must apply equivalent validated
|
|
192
|
+
storage/system logic in a blocking pre-paint script or render matching server
|
|
193
|
+
markup. Keep that logic aligned with custom names, mappings, storage key,
|
|
194
|
+
attribute, classes, and color scheme. Note that `getPrePaintScript()` serializes
|
|
195
|
+
static tokens defined on configured theme definitions (`ThemeDefinition.tokens`);
|
|
196
|
+
runtime token overrides passed to `init(tokens)` or `set(name, tokens)` are applied
|
|
197
|
+
during client-side execution after hydration.
|
|
198
|
+
|
|
199
|
+
## Public Exports
|
|
200
|
+
|
|
201
|
+
The root exports `createTheme`, `getPrePaintScript`, `THEME_CHANGE_EVENT`,
|
|
202
|
+
`LIGHT_THEME`, and `DARK_THEME`, plus `Theme`, `ThemeDefinition`, `SystemThemeMap`,
|
|
203
|
+
`ThemeClassResolver`, `ThemeChangeSource`, `ThemeChangeDetail`,
|
|
204
|
+
`ThemeChangeListener`, and `ThemeOptions` types.
|
package/llms.txt
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# @codenhub/theme
|
|
2
|
+
|
|
3
|
+
> Zero-dependency browser theme preference, persistence, DOM, cross-tab, event,
|
|
4
|
+
> and token manager with SSR-safe fallbacks.
|
|
5
|
+
|
|
6
|
+
Call `init()` in the browser, keep pre-paint logic aligned with configuration,
|
|
7
|
+
and call `destroy()` to release media-query/storage listeners and subscribers.
|
|
8
|
+
|
|
9
|
+
## Documentation
|
|
10
|
+
|
|
11
|
+
- [Documentation overview](docs/index.md): Purpose, status, and starting points.
|
|
12
|
+
- [API, persistence, DOM, and SSR behavior](docs/reference.md): Complete exports,
|
|
13
|
+
configuration, tokens, listeners, failures, pre-paint behavior, and cleanup.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@codenhub/theme",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.1",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Zero-dependency browser theme preference helper for TypeScript apps.",
|
|
6
6
|
"homepage": "https://github.com/codenhub/codenhub/tree/main/packages/theme",
|
|
@@ -11,7 +11,10 @@
|
|
|
11
11
|
"directory": "packages/theme"
|
|
12
12
|
},
|
|
13
13
|
"files": [
|
|
14
|
-
"dist"
|
|
14
|
+
"dist",
|
|
15
|
+
"docs",
|
|
16
|
+
"llms.txt",
|
|
17
|
+
"llms-full.txt"
|
|
15
18
|
],
|
|
16
19
|
"type": "module",
|
|
17
20
|
"main": "./dist/index.js",
|
|
@@ -32,9 +35,15 @@
|
|
|
32
35
|
"tsdown": "^0.22.3",
|
|
33
36
|
"typescript": "^6.0.3",
|
|
34
37
|
"vitest": "^4.1.10",
|
|
35
|
-
"@codenhub/styles": "0.0
|
|
38
|
+
"@codenhub/styles": "0.1.0",
|
|
36
39
|
"@codenhub/vite-plugin-icons": "0.0.1"
|
|
37
40
|
},
|
|
41
|
+
"codenhub": {
|
|
42
|
+
"docs": {
|
|
43
|
+
"label": "Theme",
|
|
44
|
+
"status": "active"
|
|
45
|
+
}
|
|
46
|
+
},
|
|
38
47
|
"scripts": {
|
|
39
48
|
"dev": "pnpm --filter=@codenhub/theme-dev dev",
|
|
40
49
|
"debug": "pnpm build && pnpm --filter=@codenhub/theme-debug dev",
|