@skdx/tokens 0.26.0 → 0.28.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/LICENSE +21 -0
- package/README.md +77 -57
- package/dist/themes/AntDark.d.cts +3 -7
- package/dist/themes/AntDark.d.ts +3 -7
- package/dist/themes/ChakraDark.d.cts +3 -7
- package/dist/themes/ChakraDark.d.ts +3 -7
- package/dist/themes/DefaultTheme.d.cts +1 -2
- package/dist/themes/DefaultTheme.d.ts +1 -2
- package/dist/themes/DraculaLight.d.cts +1 -9
- package/dist/themes/DraculaLight.d.ts +1 -9
- package/dist/themes/EverforestDark.d.cts +1 -2
- package/dist/themes/EverforestDark.d.ts +1 -2
- package/dist/themes/EverforestLight.d.cts +4 -8
- package/dist/themes/EverforestLight.d.ts +4 -8
- package/dist/themes/FluentDark.d.cts +2 -6
- package/dist/themes/FluentDark.d.ts +2 -6
- package/dist/themes/GruvboxLight.d.cts +1 -2
- package/dist/themes/GruvboxLight.d.ts +1 -2
- package/dist/themes/MaterialBrand.d.cts +1 -1
- package/dist/themes/MaterialBrand.d.ts +1 -1
- package/dist/themes/MaterialDark.d.cts +3 -7
- package/dist/themes/MaterialDark.d.ts +3 -7
- package/dist/themes/MidnightBrand.d.cts +2 -5
- package/dist/themes/MidnightBrand.d.ts +2 -5
- package/dist/themes/MidnightLight.d.cts +2 -5
- package/dist/themes/MidnightLight.d.ts +2 -5
- package/dist/themes/NordLight.d.cts +1 -2
- package/dist/themes/NordLight.d.ts +1 -2
- package/dist/themes/OneLight.d.cts +4 -8
- package/dist/themes/OneLight.d.ts +4 -8
- package/dist/themes/PrimerDark.d.cts +0 -1
- package/dist/themes/PrimerDark.d.ts +0 -1
- package/dist/themes/RosePineDawn.d.cts +4 -8
- package/dist/themes/RosePineDawn.d.ts +4 -8
- package/dist/themes/SkandaDark.d.cts +3 -7
- package/dist/themes/SkandaDark.d.ts +3 -7
- package/dist/themes/SynthwaveLight.d.cts +3 -7
- package/dist/themes/SynthwaveLight.d.ts +3 -7
- package/dist/themes/brands.d.cts +7 -14
- package/dist/themes/brands.d.ts +7 -14
- package/dist/themes/createBrandTheme.d.cts +13 -21
- package/dist/themes/createBrandTheme.d.ts +13 -21
- package/dist/utils/aliases.d.cts +22 -92
- package/dist/utils/aliases.d.ts +22 -92
- package/dist/utils/contrast.d.cts +2 -17
- package/dist/utils/contrast.d.ts +2 -17
- package/dist/utils/cssVars.d.cts +7 -29
- package/dist/utils/cssVars.d.ts +7 -29
- package/dist/utils/foundation.d.cts +47 -143
- package/dist/utils/foundation.d.ts +47 -143
- package/dist/utils/mode.d.cts +31 -43
- package/dist/utils/mode.d.ts +31 -43
- package/dist/utils/theme.d.cts +83 -240
- package/dist/utils/theme.d.ts +83 -240
- package/dist/utils/toCss.d.cts +18 -57
- package/dist/utils/toCss.d.ts +18 -57
- package/package.json +1 -1
|
@@ -1,79 +1,42 @@
|
|
|
1
1
|
import { type ThemeControls, type ThemeControlsCoarse, type ThemeMotion, type ThemeRadii, type ThemeShadows, type ThemeSpace, type ThemeTypography } from './theme.js';
|
|
2
2
|
/**
|
|
3
|
-
* The type system: one font stack,
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
* A theme picks colors. It does not get to resize the type scale, because a
|
|
7
|
-
* layout that reflows when you switch brand is a layout that was never
|
|
8
|
-
* designed — it was designed once, against one scale, and every other brand
|
|
9
|
-
* was hoping. The two font *stacks* are the only part a theme can override,
|
|
10
|
-
* and only through {@link ThemeTypographyDeviation}, because impersonating a
|
|
11
|
-
* design language means impersonating its typeface.
|
|
12
|
-
*
|
|
3
|
+
* The type system: one font stack, scale, weight set, line-heights and
|
|
4
|
+
* tracking steps, shared by every theme. Only the font stacks are
|
|
5
|
+
* per-theme overridable, via {@link ThemeTypographyDeviation}.
|
|
13
6
|
* @public
|
|
14
7
|
*/
|
|
15
8
|
export declare const typography: ThemeTypography;
|
|
16
9
|
/**
|
|
17
|
-
* The spacing scale — a 4px base
|
|
18
|
-
*
|
|
19
|
-
* rhythm, and rhythm is a property of the design system, not of the brand
|
|
20
|
-
* painted on top of it.
|
|
21
|
-
*
|
|
10
|
+
* The spacing scale — a 4px base, structural rather than per-brand: gap and
|
|
11
|
+
* padding are rhythm, a property of the system, not the brand on top of it.
|
|
22
12
|
* @public
|
|
23
13
|
*/
|
|
24
14
|
export declare const space: ThemeSpace;
|
|
25
15
|
/**
|
|
26
|
-
* The corner-radius scale
|
|
27
|
-
*
|
|
28
|
-
* that rounds its corners differently is a different component library
|
|
29
|
-
* wearing the same class names.
|
|
30
|
-
*
|
|
16
|
+
* The corner-radius scale, structural like {@link space}: a component's
|
|
17
|
+
* silhouette is part of the system's shape language, not the brand's.
|
|
31
18
|
* @public
|
|
32
19
|
*/
|
|
33
20
|
export declare const radii: ThemeRadii;
|
|
34
21
|
/**
|
|
35
22
|
* The elevation scale — geometry only. Every value defers its color to
|
|
36
23
|
* `var(--skdx-shadow-color)` and scales its alpha by
|
|
37
|
-
* `var(--skdx-shadow-strength)`, both
|
|
38
|
-
* {@link ThemeShadowColor})
|
|
39
|
-
*
|
|
40
|
-
* This split is the whole reason shadows can be shared at all. A shadow is one
|
|
41
|
-
* CSS string that welds geometry to a color, so before this every theme
|
|
42
|
-
* restated `0 4px 6px -1px` purely to be able to change `rgb(…)` at the end of
|
|
43
|
-
* it — 38 copies of the same three offsets, and no way to tell a deliberate
|
|
44
|
-
* elevation change from a color change.
|
|
45
|
-
*
|
|
46
|
-
* The base alphas below are the original `skanda-light` values, so a theme
|
|
47
|
-
* with `strength: '1'` renders exactly what it did before the split.
|
|
48
|
-
* Substitution is lazy: these live at `:root`, but `var(--skdx-shadow-color)`
|
|
49
|
-
* resolves against the element the shadow is finally *used* on, so the active
|
|
50
|
-
* `[data-skdx-theme]` block wins. `calc()` is legal in the alpha slot, and an
|
|
51
|
-
* alpha above 1 clamps rather than erroring — which is what keeps a
|
|
52
|
-
* high-strength dark theme from being a footgun.
|
|
53
|
-
*
|
|
24
|
+
* `var(--skdx-shadow-strength)`, both supplied by a theme (see
|
|
25
|
+
* {@link ThemeShadowColor}), so 38 themes share one set of offsets instead of
|
|
26
|
+
* each restating them to vary only the color.
|
|
54
27
|
* @public
|
|
55
28
|
*/
|
|
56
29
|
export declare const shadows: ThemeShadows;
|
|
57
30
|
/**
|
|
58
|
-
* The shared animation timing
|
|
59
|
-
*
|
|
60
|
-
* a theme's {@link Theme.motion} without importing this module.
|
|
61
|
-
*
|
|
62
|
-
* See {@link ThemeMotion} for why motion is theme-invariant.
|
|
63
|
-
*
|
|
31
|
+
* The shared animation timing, re-exported from {@link defaultMotion}. See
|
|
32
|
+
* {@link ThemeMotion} for why motion is theme-invariant.
|
|
64
33
|
* @public
|
|
65
34
|
*/
|
|
66
35
|
export declare const motion: Required<ThemeMotion>;
|
|
67
36
|
/**
|
|
68
37
|
* A structural stacking-order scale for overlay-class UI (dropdowns, sticky
|
|
69
|
-
* headers, dialog/popover backdrops, floating content, toasts)
|
|
70
|
-
*
|
|
71
|
-
* theme should stack the same way — so it's exported once here rather than
|
|
72
|
-
* duplicated into all 38 {@link Theme} objects. Consumers building an app
|
|
73
|
-
* with multiple concurrent overlay types (e.g. a `Select` opened from inside
|
|
74
|
-
* a `Dialog`, with a `Toast` on top of both) should coordinate their own
|
|
75
|
-
* z-indices against this scale instead of picking ad hoc numbers per
|
|
76
|
-
* component.
|
|
38
|
+
* headers, dialog/popover backdrops, floating content, toasts) — every theme
|
|
39
|
+
* stacks the same way, so it's exported once rather than duplicated per theme.
|
|
77
40
|
*
|
|
78
41
|
* @example
|
|
79
42
|
* ```css
|
|
@@ -88,27 +51,20 @@ export declare const zIndex: {
|
|
|
88
51
|
readonly base: 0;
|
|
89
52
|
readonly dropdown: 10;
|
|
90
53
|
readonly sticky: 20;
|
|
91
|
-
/**
|
|
54
|
+
/** Scrim behind modal. */
|
|
92
55
|
readonly overlay: 30;
|
|
93
|
-
/**
|
|
56
|
+
/** Modal surface; above scrim, below popovers opened from inside. */
|
|
94
57
|
readonly modal: 35;
|
|
95
58
|
readonly popover: 40;
|
|
96
59
|
readonly toast: 50;
|
|
97
|
-
/**
|
|
98
|
-
* Escape hatch for the one thing that must sit above everything, e.g. a
|
|
99
|
-
* debug overlay or an "app is offline" banner. Deliberately far above
|
|
100
|
-
* `toast` so app code never has to guess a bigger number.
|
|
101
|
-
*/
|
|
60
|
+
/** Escape hatch for the one thing that must sit above everything, e.g. a debug overlay. */
|
|
102
61
|
readonly max: 9999;
|
|
103
62
|
};
|
|
104
63
|
/** The shape of the {@link zIndex} scale — a map of named stacking layers (`sticky`, `overlay`, `popover`, `toast`, …) to their numeric `z-index`. @public */
|
|
105
64
|
export type ZIndexScale = typeof zIndex;
|
|
106
65
|
/**
|
|
107
|
-
* Structural focus-ring geometry (width/offset)
|
|
108
|
-
*
|
|
109
|
-
* but the ring's thickness and offset are a layout constant every theme
|
|
110
|
-
* should share, so they live here rather than being repeated as identical
|
|
111
|
-
* values across all 38 bundled themes.
|
|
66
|
+
* Structural focus-ring geometry (width/offset). The ring's *color* is themed
|
|
67
|
+
* per brand ({@link SemanticColors.focusRing}); thickness/offset are shared.
|
|
112
68
|
*
|
|
113
69
|
* @example
|
|
114
70
|
* ```css
|
|
@@ -124,30 +80,17 @@ export declare const focusRing: {
|
|
|
124
80
|
readonly width: "2px";
|
|
125
81
|
readonly offset: "2px";
|
|
126
82
|
/**
|
|
127
|
-
*
|
|
128
|
-
*
|
|
129
|
-
* An outline is painted outward from the border edge and is clipped by an
|
|
130
|
-
* ancestor's `overflow` exactly like any other overflowing paint — which
|
|
131
|
-
* sliced the ring off inside every control group that rounds its corners by
|
|
132
|
-
* clipping. Because `outline-offset` is read from a custom property, such a
|
|
133
|
-
* container sets this on itself and every descendant ring moves *inside* the
|
|
134
|
-
* border box, where nothing can reach it. One declaration per clipping
|
|
135
|
-
* container, no per-part focus rules.
|
|
136
|
-
*
|
|
137
|
-
* Negative by exactly the ring width, which lands it flush against the
|
|
138
|
-
* inside of the edge rather than floating in from it.
|
|
83
|
+
* Offset for clipping containers; moves ring inside border-box so overflow
|
|
84
|
+
* doesn't clip. Negative ring width, flush inside edge.
|
|
139
85
|
*/
|
|
140
86
|
readonly offsetInset: "calc(-1 * var(--skdx-focus-ring-width))";
|
|
141
87
|
};
|
|
142
88
|
/** The shape of the {@link focusRing} geometry — the structural `width`/`offset` of the focus ring (its color is themed separately). @public */
|
|
143
89
|
export type FocusRingScale = typeof focusRing;
|
|
144
90
|
/**
|
|
145
|
-
* Border thicknesses
|
|
146
|
-
*
|
|
147
|
-
*
|
|
148
|
-
* Three steps only — a hairline, an emphasis weight (focus/selected/invalid
|
|
149
|
-
* outlines drawn without the focus ring), and a heavy weight for deliberate
|
|
150
|
-
* structural rules. There is no `0`: that's `border: none`, not a token.
|
|
91
|
+
* Border thicknesses, structural like {@link focusRing}: a brand changes
|
|
92
|
+
* border *color* ({@link SemanticColors.border}), not hairline width. No `0`
|
|
93
|
+
* step — that's `border: none`, not a token.
|
|
151
94
|
*
|
|
152
95
|
* @example
|
|
153
96
|
* ```css
|
|
@@ -165,37 +108,25 @@ export declare const borderWidth: {
|
|
|
165
108
|
/** The shape of the {@link borderWidth} scale — `thin`/`thick`/`thicker` border thicknesses. @public */
|
|
166
109
|
export type BorderWidthScale = typeof borderWidth;
|
|
167
110
|
/**
|
|
168
|
-
* The shared control geometry — heights, paddings, icon boxes, row heights
|
|
169
|
-
* overlay insets. See {@link ThemeControls} for why this is structural
|
|
170
|
-
* than per-brand, and for the retuning escape hatch.
|
|
171
|
-
*
|
|
172
|
-
*
|
|
173
|
-
* range the two reference libraries surveyed occupy. Several values are
|
|
174
|
-
* `var()` references rather than lengths on purpose: a control's inline
|
|
175
|
-
* padding *is* a step of {@link space}, and restating `0.75rem` here would let
|
|
176
|
-
* the two drift. The exceptions are the four numbers that are deliberately off
|
|
177
|
-
* a scale — `padding.sm` (10px), `height.compact` (32px), `item.gap` (2px) and
|
|
178
|
-
* `target.min` (24px) — each documented where it is declared.
|
|
179
|
-
*
|
|
111
|
+
* The shared control geometry — heights, paddings, icon boxes, row heights
|
|
112
|
+
* and overlay insets. See {@link ThemeControls} for why this is structural
|
|
113
|
+
* rather than per-brand, and for the retuning escape hatch. Values are
|
|
114
|
+
* `var()` references where they equal a {@link space} step, so the two can't
|
|
115
|
+
* drift; the few off-scale exceptions are documented where declared.
|
|
180
116
|
* @public
|
|
181
117
|
*/
|
|
182
118
|
export declare const controls: ThemeControls;
|
|
183
119
|
/**
|
|
184
|
-
* What a coarse pointer overrides
|
|
185
|
-
*
|
|
120
|
+
* What a coarse pointer overrides, emitted as a `@media (pointer: coarse)`
|
|
121
|
+
* block by {@link foundationToCss}; see {@link ThemeControlsCoarse} for why
|
|
186
122
|
* only hit sizes are listed.
|
|
187
|
-
*
|
|
188
123
|
* @public
|
|
189
124
|
*/
|
|
190
125
|
export declare const controlsCoarse: ThemeControlsCoarse;
|
|
191
126
|
/**
|
|
192
|
-
* The two opacities the system
|
|
193
|
-
*
|
|
194
|
-
*
|
|
195
|
-
* control is, and how much a modal scrim dims the page behind it.
|
|
196
|
-
*
|
|
197
|
-
* Scrim *color* is themed ({@link SemanticColors.overlay}); this is the
|
|
198
|
-
* structural strength of the dim, so every brand's scrim occludes equally.
|
|
127
|
+
* The two opacities the system has an opinion about — disabled fade and
|
|
128
|
+
* modal scrim dim — not an arbitrary 0–100 ramp. Scrim *color* is themed
|
|
129
|
+
* ({@link SemanticColors.overlay}); this is the structural dim strength.
|
|
199
130
|
*
|
|
200
131
|
* @example
|
|
201
132
|
* ```css
|
|
@@ -212,16 +143,9 @@ export declare const opacity: {
|
|
|
212
143
|
/** The shape of the {@link opacity} scale — the `disabled` and `scrim` opacities. @public */
|
|
213
144
|
export type OpacityScale = typeof opacity;
|
|
214
145
|
/**
|
|
215
|
-
* Viewport widths, in pixels, as **TypeScript exports only** —
|
|
216
|
-
*
|
|
217
|
-
*
|
|
218
|
-
* var(--x))` is invalid CSS), so a `--skdx-breakpoint-*` variable would be a
|
|
219
|
-
* token that looks usable and isn't. Consume these from JS/TS, or from a
|
|
220
|
-
* build step that inlines the number into your own media queries.
|
|
221
|
-
*
|
|
222
|
-
* The components themselves are headless and ship no responsive behavior;
|
|
223
|
-
* this exists so consumers building a styled layer on top don't have to
|
|
224
|
-
* invent their own set.
|
|
146
|
+
* Viewport widths, in pixels, as **TypeScript exports only** — not emitted as
|
|
147
|
+
* CSS custom properties, since `@media (min-width: var(--x))` is invalid CSS.
|
|
148
|
+
* Consume from JS/TS or inline into your own media queries.
|
|
225
149
|
*
|
|
226
150
|
* @example
|
|
227
151
|
* ```ts
|
|
@@ -242,51 +166,31 @@ export declare const breakpoints: {
|
|
|
242
166
|
export type BreakpointScale = typeof breakpoints;
|
|
243
167
|
/**
|
|
244
168
|
* Flattens every shared token into a map of CSS custom property names to
|
|
245
|
-
* values — the foundation's counterpart to `themeToCssVars`. Together
|
|
246
|
-
*
|
|
247
|
-
*
|
|
248
|
-
* {@link breakpoints} is not included — see its docs for why a breakpoint
|
|
249
|
-
* can't be a CSS custom property.
|
|
169
|
+
* values — the foundation's counterpart to `themeToCssVars`. Together they
|
|
170
|
+
* are the complete `--skdx-*` surface, and never overlap. {@link breakpoints}
|
|
171
|
+
* is excluded, since a breakpoint can't be a CSS custom property.
|
|
250
172
|
*
|
|
251
173
|
* @returns A plain object keyed by CSS custom property name (e.g. `'--skdx-space-4'`), unprefixed by any selector.
|
|
252
|
-
*
|
|
253
174
|
* @public
|
|
254
175
|
*/
|
|
255
176
|
export declare function foundationToCssVars(): Record<string, string>;
|
|
256
177
|
/**
|
|
257
178
|
* The control metrics a coarse pointer overrides, as a var map — the
|
|
258
179
|
* `@media (pointer: coarse)` counterpart to {@link foundationToCssVars}.
|
|
259
|
-
*
|
|
260
|
-
*
|
|
261
|
-
* both blocks from these functions rather than restating the values, which is
|
|
262
|
-
* the only thing that keeps the two in step.
|
|
263
|
-
*
|
|
180
|
+
* Exported so `@skdx/skins` can render its fallback copy from these
|
|
181
|
+
* functions instead of restating the values.
|
|
264
182
|
* @public
|
|
265
183
|
*/
|
|
266
184
|
export declare function coarsePointerToCssVars(): Record<string, string>;
|
|
267
185
|
/**
|
|
268
186
|
* Renders every shared token as a `:root`-scoped `--skdx-*` rule block — the
|
|
269
187
|
* theme-invariant counterpart to {@link themeToCss}. **Inject this exactly
|
|
270
|
-
* once**, then
|
|
271
|
-
* the type scale, spacing, radii, shadow geometry and motion are simply
|
|
272
|
-
* absent, because no theme declares them any more.
|
|
273
|
-
*
|
|
274
|
-
* Followed by a `@media (prefers-reduced-motion: reduce)` block that
|
|
275
|
-
* re-declares every `--skdx-motion-duration-*` and `--skdx-motion-stagger-*` as
|
|
276
|
-
* `0ms`. Components are headless and animate nothing themselves, so honoring
|
|
277
|
-
* the preference has to happen where the durations are *defined* rather than
|
|
278
|
-
* where they're used — this way a consumer who writes `transition-duration:
|
|
279
|
-
* var(--skdx-motion-duration-normal)` gets WCAG 2.3.3 behavior for free instead
|
|
280
|
-
* of having to remember the media query at every call site. The easing curve
|
|
281
|
-
* is left alone: it's a shape, not a duration, and is inert at `0ms`. A theme
|
|
282
|
-
* that retunes motion via `ThemeMotionDeviation` emits its own copy of this
|
|
283
|
-
* block, so the guarantee survives the escape hatch.
|
|
188
|
+
* once**, then `themeToCss(theme)` per theme alongside it.
|
|
284
189
|
*
|
|
285
|
-
*
|
|
286
|
-
*
|
|
287
|
-
*
|
|
288
|
-
*
|
|
289
|
-
* having to remember the query.
|
|
190
|
+
* Also emits a `@media (prefers-reduced-motion: reduce)` block zeroing every
|
|
191
|
+
* motion duration/stagger at the definition site (WCAG 2.3.3 for free at every
|
|
192
|
+
* call site, no per-consumer media query), and a `@media (pointer: coarse)`
|
|
193
|
+
* block re-declaring the hit sizes from {@link controlsCoarse} the same way.
|
|
290
194
|
*
|
|
291
195
|
* @example
|
|
292
196
|
* ```ts
|
package/dist/utils/mode.d.cts
CHANGED
|
@@ -1,62 +1,31 @@
|
|
|
1
|
-
/** `localStorage` key
|
|
1
|
+
/** `localStorage` key for mode preference (`'light' | 'dark' | 'system'`). @public */
|
|
2
2
|
export declare const MODE_STORAGE_KEY = "skdx-mode";
|
|
3
|
-
/** `localStorage` key
|
|
3
|
+
/** `localStorage` key for brand preference (a {@link Brand} name). @public */
|
|
4
4
|
export declare const BRAND_STORAGE_KEY = "skdx-brand";
|
|
5
5
|
/** Options for {@link watchSystemMode}. @public */
|
|
6
6
|
export interface WatchSystemModeOptions {
|
|
7
|
-
/** Brand
|
|
7
|
+
/** Brand pair to apply (unknown names fall back to default). @default 'skanda' */
|
|
8
8
|
brand?: string;
|
|
9
|
-
/**
|
|
9
|
+
/** Target element for theme. @default document.documentElement */
|
|
10
10
|
element?: HTMLElement;
|
|
11
|
-
/**
|
|
11
|
+
/** Mirror resolved mode to `localStorage`. @default false */
|
|
12
12
|
persist?: boolean;
|
|
13
|
-
/** `localStorage` key
|
|
13
|
+
/** `localStorage` key when `persist` is on. @default MODE_STORAGE_KEY */
|
|
14
14
|
storageKey?: string;
|
|
15
15
|
}
|
|
16
16
|
/**
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
* returned function on unmount.
|
|
21
|
-
*
|
|
22
|
-
* Browser-only (it reads `window.matchMedia`); guard it behind a mounted
|
|
23
|
-
* effect in an SSR framework, and pair it with {@link getThemeInitScript} so
|
|
24
|
-
* the first paint already matches.
|
|
25
|
-
*
|
|
26
|
-
* @returns An unsubscribe function that detaches the change listener.
|
|
17
|
+
* Follow OS color-scheme: apply theme, re-apply on preference change (runtime half
|
|
18
|
+
* of "mode: system"). Browser-only; guard behind mounted effect in SSR.
|
|
19
|
+
* Pair with {@link getThemeInitScript} so first paint matches.
|
|
27
20
|
*
|
|
21
|
+
* @returns Unsubscribe function (detaches listener).
|
|
28
22
|
* @example
|
|
29
23
|
* ```ts
|
|
30
24
|
* import { watchSystemMode } from '@skdx/tokens';
|
|
31
|
-
*
|
|
32
25
|
* const stop = watchSystemMode({ brand: 'nord', persist: true });
|
|
33
|
-
* // later…
|
|
34
26
|
* stop();
|
|
35
27
|
* ```
|
|
36
|
-
*
|
|
37
28
|
* @public
|
|
38
|
-
*/
|
|
39
|
-
export declare function watchSystemMode(options?: WatchSystemModeOptions): () => void;
|
|
40
|
-
/** Options for {@link getThemeInitScript}. @public */
|
|
41
|
-
export interface ThemeInitScriptOptions {
|
|
42
|
-
/** `localStorage` key holding the brand name. @default BRAND_STORAGE_KEY */
|
|
43
|
-
brandKey?: string;
|
|
44
|
-
/** `localStorage` key holding `'light' | 'dark' | 'system'`. @default MODE_STORAGE_KEY */
|
|
45
|
-
modeKey?: string;
|
|
46
|
-
/** Brand used when nothing is persisted or the persisted name is unknown. @default 'skanda' */
|
|
47
|
-
fallbackBrand?: string;
|
|
48
|
-
}
|
|
49
|
-
/**
|
|
50
|
-
* Builds the blocking snippet that stamps `data-skdx-theme` and `data-skdx-mode`
|
|
51
|
-
* on `<html>` *before first paint*, so a dark-mode visitor never sees a flash
|
|
52
|
-
* of the light theme. It reads the persisted brand and mode, resolves
|
|
53
|
-
* `'system'` through `prefers-color-scheme`, and maps brand + mode to the
|
|
54
|
-
* theme name your stylesheet is keyed by — the brand→theme-name table is
|
|
55
|
-
* baked into the returned string at call time from {@link brands}.
|
|
56
|
-
*
|
|
57
|
-
* Returns bare JavaScript (no `<script>` wrapper) so each framework can inject
|
|
58
|
-
* it its own way. It only sets attributes, so the page's CSS must already
|
|
59
|
-
* contain a `[data-skdx-theme="…"]` block per theme (see `themeToCss`).
|
|
60
29
|
*
|
|
61
30
|
* @example Next.js (App Router, `app/layout.tsx`)
|
|
62
31
|
* ```tsx
|
|
@@ -78,12 +47,31 @@ export interface ThemeInitScriptOptions {
|
|
|
78
47
|
* <script>%skdx.themeInit%</script>
|
|
79
48
|
* </head>
|
|
80
49
|
* ```
|
|
50
|
+
*/
|
|
51
|
+
export declare function watchSystemMode(options?: WatchSystemModeOptions): () => void;
|
|
52
|
+
/** Options for {@link getThemeInitScript}. @public */
|
|
53
|
+
export interface ThemeInitScriptOptions {
|
|
54
|
+
/** `localStorage` key for brand name. @default BRAND_STORAGE_KEY */
|
|
55
|
+
brandKey?: string;
|
|
56
|
+
/** `localStorage` key for mode. @default MODE_STORAGE_KEY */
|
|
57
|
+
modeKey?: string;
|
|
58
|
+
/** Fallback brand when nothing persisted or unknown. @default 'skanda' */
|
|
59
|
+
fallbackBrand?: string;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Blocking snippet that stamps `data-skdx-theme` and `data-skdx-mode` on
|
|
63
|
+
* `<html>` before first paint (prevents dark-mode flash). Resolves `'system'`
|
|
64
|
+
* through `prefers-color-scheme`. Returns bare JS (no `<script>` wrapper);
|
|
65
|
+
* your CSS must have `[data-skdx-theme="…"]` blocks.
|
|
81
66
|
*
|
|
82
|
-
* @example
|
|
67
|
+
* @example Next.js
|
|
68
|
+
* ```tsx
|
|
69
|
+
* <script dangerouslySetInnerHTML={{ __html: getThemeInitScript() }} />
|
|
70
|
+
* ```
|
|
71
|
+
* @example Astro
|
|
83
72
|
* ```astro
|
|
84
73
|
* <script is:inline set:html={getThemeInitScript()} />
|
|
85
74
|
* ```
|
|
86
|
-
*
|
|
87
75
|
* @public
|
|
88
76
|
*/
|
|
89
77
|
export declare function getThemeInitScript(options?: ThemeInitScriptOptions): string;
|
package/dist/utils/mode.d.ts
CHANGED
|
@@ -1,62 +1,31 @@
|
|
|
1
|
-
/** `localStorage` key
|
|
1
|
+
/** `localStorage` key for mode preference (`'light' | 'dark' | 'system'`). @public */
|
|
2
2
|
export declare const MODE_STORAGE_KEY = "skdx-mode";
|
|
3
|
-
/** `localStorage` key
|
|
3
|
+
/** `localStorage` key for brand preference (a {@link Brand} name). @public */
|
|
4
4
|
export declare const BRAND_STORAGE_KEY = "skdx-brand";
|
|
5
5
|
/** Options for {@link watchSystemMode}. @public */
|
|
6
6
|
export interface WatchSystemModeOptions {
|
|
7
|
-
/** Brand
|
|
7
|
+
/** Brand pair to apply (unknown names fall back to default). @default 'skanda' */
|
|
8
8
|
brand?: string;
|
|
9
|
-
/**
|
|
9
|
+
/** Target element for theme. @default document.documentElement */
|
|
10
10
|
element?: HTMLElement;
|
|
11
|
-
/**
|
|
11
|
+
/** Mirror resolved mode to `localStorage`. @default false */
|
|
12
12
|
persist?: boolean;
|
|
13
|
-
/** `localStorage` key
|
|
13
|
+
/** `localStorage` key when `persist` is on. @default MODE_STORAGE_KEY */
|
|
14
14
|
storageKey?: string;
|
|
15
15
|
}
|
|
16
16
|
/**
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
* returned function on unmount.
|
|
21
|
-
*
|
|
22
|
-
* Browser-only (it reads `window.matchMedia`); guard it behind a mounted
|
|
23
|
-
* effect in an SSR framework, and pair it with {@link getThemeInitScript} so
|
|
24
|
-
* the first paint already matches.
|
|
25
|
-
*
|
|
26
|
-
* @returns An unsubscribe function that detaches the change listener.
|
|
17
|
+
* Follow OS color-scheme: apply theme, re-apply on preference change (runtime half
|
|
18
|
+
* of "mode: system"). Browser-only; guard behind mounted effect in SSR.
|
|
19
|
+
* Pair with {@link getThemeInitScript} so first paint matches.
|
|
27
20
|
*
|
|
21
|
+
* @returns Unsubscribe function (detaches listener).
|
|
28
22
|
* @example
|
|
29
23
|
* ```ts
|
|
30
24
|
* import { watchSystemMode } from '@skdx/tokens';
|
|
31
|
-
*
|
|
32
25
|
* const stop = watchSystemMode({ brand: 'nord', persist: true });
|
|
33
|
-
* // later…
|
|
34
26
|
* stop();
|
|
35
27
|
* ```
|
|
36
|
-
*
|
|
37
28
|
* @public
|
|
38
|
-
*/
|
|
39
|
-
export declare function watchSystemMode(options?: WatchSystemModeOptions): () => void;
|
|
40
|
-
/** Options for {@link getThemeInitScript}. @public */
|
|
41
|
-
export interface ThemeInitScriptOptions {
|
|
42
|
-
/** `localStorage` key holding the brand name. @default BRAND_STORAGE_KEY */
|
|
43
|
-
brandKey?: string;
|
|
44
|
-
/** `localStorage` key holding `'light' | 'dark' | 'system'`. @default MODE_STORAGE_KEY */
|
|
45
|
-
modeKey?: string;
|
|
46
|
-
/** Brand used when nothing is persisted or the persisted name is unknown. @default 'skanda' */
|
|
47
|
-
fallbackBrand?: string;
|
|
48
|
-
}
|
|
49
|
-
/**
|
|
50
|
-
* Builds the blocking snippet that stamps `data-skdx-theme` and `data-skdx-mode`
|
|
51
|
-
* on `<html>` *before first paint*, so a dark-mode visitor never sees a flash
|
|
52
|
-
* of the light theme. It reads the persisted brand and mode, resolves
|
|
53
|
-
* `'system'` through `prefers-color-scheme`, and maps brand + mode to the
|
|
54
|
-
* theme name your stylesheet is keyed by — the brand→theme-name table is
|
|
55
|
-
* baked into the returned string at call time from {@link brands}.
|
|
56
|
-
*
|
|
57
|
-
* Returns bare JavaScript (no `<script>` wrapper) so each framework can inject
|
|
58
|
-
* it its own way. It only sets attributes, so the page's CSS must already
|
|
59
|
-
* contain a `[data-skdx-theme="…"]` block per theme (see `themeToCss`).
|
|
60
29
|
*
|
|
61
30
|
* @example Next.js (App Router, `app/layout.tsx`)
|
|
62
31
|
* ```tsx
|
|
@@ -78,12 +47,31 @@ export interface ThemeInitScriptOptions {
|
|
|
78
47
|
* <script>%skdx.themeInit%</script>
|
|
79
48
|
* </head>
|
|
80
49
|
* ```
|
|
50
|
+
*/
|
|
51
|
+
export declare function watchSystemMode(options?: WatchSystemModeOptions): () => void;
|
|
52
|
+
/** Options for {@link getThemeInitScript}. @public */
|
|
53
|
+
export interface ThemeInitScriptOptions {
|
|
54
|
+
/** `localStorage` key for brand name. @default BRAND_STORAGE_KEY */
|
|
55
|
+
brandKey?: string;
|
|
56
|
+
/** `localStorage` key for mode. @default MODE_STORAGE_KEY */
|
|
57
|
+
modeKey?: string;
|
|
58
|
+
/** Fallback brand when nothing persisted or unknown. @default 'skanda' */
|
|
59
|
+
fallbackBrand?: string;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Blocking snippet that stamps `data-skdx-theme` and `data-skdx-mode` on
|
|
63
|
+
* `<html>` before first paint (prevents dark-mode flash). Resolves `'system'`
|
|
64
|
+
* through `prefers-color-scheme`. Returns bare JS (no `<script>` wrapper);
|
|
65
|
+
* your CSS must have `[data-skdx-theme="…"]` blocks.
|
|
81
66
|
*
|
|
82
|
-
* @example
|
|
67
|
+
* @example Next.js
|
|
68
|
+
* ```tsx
|
|
69
|
+
* <script dangerouslySetInnerHTML={{ __html: getThemeInitScript() }} />
|
|
70
|
+
* ```
|
|
71
|
+
* @example Astro
|
|
83
72
|
* ```astro
|
|
84
73
|
* <script is:inline set:html={getThemeInitScript()} />
|
|
85
74
|
* ```
|
|
86
|
-
*
|
|
87
75
|
* @public
|
|
88
76
|
*/
|
|
89
77
|
export declare function getThemeInitScript(options?: ThemeInitScriptOptions): string;
|