@tenphi/glaze 0.0.0-snapshot.0821a67 → 0.0.0-snapshot.0fcd6cf
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/AGENTS.md +169 -0
- package/README.md +110 -1394
- package/dist/index.cjs +4874 -1375
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1643 -249
- package/dist/index.d.mts +1643 -249
- package/dist/index.mjs +4843 -1375
- package/dist/index.mjs.map +1 -1
- package/docs/contrast.mdx +751 -0
- package/docs/exporting.mdx +851 -0
- package/docs/getting-started.mdx +488 -0
- package/docs/methodology.mdx +977 -0
- package/docs/migration.md +505 -0
- package/docs/mixes.mdx +305 -0
- package/docs/okhst.mdx +680 -0
- package/docs/reference/color-definitions.md +554 -0
- package/docs/reference/color-tokens.md +417 -0
- package/docs/reference/configuration.md +510 -0
- package/docs/reference/contrast.md +277 -0
- package/docs/reference/index.md +223 -0
- package/docs/reference/output.md +834 -0
- package/docs/reference/palette.md +435 -0
- package/docs/reference/theme.md +332 -0
- package/docs/reference/utilities.md +629 -0
- package/docs/schemes.mdx +637 -0
- package/docs/shadows-and-glows.mdx +737 -0
- package/package.json +20 -10
package/dist/index.d.cts
CHANGED
|
@@ -1,91 +1,263 @@
|
|
|
1
1
|
//#region src/contrast-solver.d.ts
|
|
2
|
-
/**
|
|
3
|
-
* OKHSL Contrast Solver
|
|
4
|
-
*
|
|
5
|
-
* Finds the closest OKHSL lightness that satisfies a WCAG 2 contrast target
|
|
6
|
-
* against a base color. Used by glaze when resolving dependent colors
|
|
7
|
-
* with `contrast`.
|
|
8
|
-
*/
|
|
9
2
|
type LinearRgb = [number, number, number];
|
|
10
3
|
type ContrastPreset = 'AA' | 'AAA' | 'AA-large' | 'AAA-large';
|
|
11
4
|
type MinContrast$1 = number | ContrastPreset;
|
|
12
|
-
|
|
5
|
+
/**
|
|
6
|
+
* Named APCA Lc floor presets (APCA Bronze Simple Mode conformance levels),
|
|
7
|
+
* independent of role. Use them anywhere an APCA target is accepted.
|
|
8
|
+
*
|
|
9
|
+
* | Preset | Lc | Use case |
|
|
10
|
+
* | ------------- | --- | ---------------------------------------------------- |
|
|
11
|
+
* | `'preferred'` | 90 | Preferred body / column text |
|
|
12
|
+
* | `'body'` | 75 | Minimum body / column text |
|
|
13
|
+
* | `'content'` | 60 | Readable non-body content (~WCAG AA 4.5:1) |
|
|
14
|
+
* | `'large'` | 45 | Large/bold headlines; fine icons/outlines (~3:1) |
|
|
15
|
+
* | `'non-text'` | 30 | Solid icons/controls; placeholder/disabled text |
|
|
16
|
+
* | `'min'` | 15 | Dividers/decorative; APCA "point of invisibility" |
|
|
17
|
+
*/
|
|
18
|
+
type ApcaPreset = 'preferred' | 'body' | 'content' | 'large' | 'non-text' | 'min';
|
|
19
|
+
declare const APCA_PRESETS: Record<ApcaPreset, number>;
|
|
20
|
+
/**
|
|
21
|
+
* APCA-W3 "Enhanced Level" delta added to a bare APCA target in high-contrast
|
|
22
|
+
* mode when no explicit HC value is provided (analogous to WCAG AAA over AA).
|
|
23
|
+
* Only applied when neither the outer `contrast` pair nor the inner `apca`
|
|
24
|
+
* pair carries an explicit HC entry.
|
|
25
|
+
*/
|
|
26
|
+
declare const APCA_HC_ENHANCEMENT = 15;
|
|
27
|
+
/** Upper bound for an APCA Lc target after HC enhancement. */
|
|
28
|
+
declare const APCA_MAX_LC = 106;
|
|
29
|
+
/**
|
|
30
|
+
* Resolve an APCA target — a raw Lc number (kept as-is) or an `ApcaPreset`
|
|
31
|
+
* keyword mapped to its Lc value. The magnitude is forced non-negative.
|
|
32
|
+
*/
|
|
33
|
+
declare function resolveApcaTarget(value: number | ApcaPreset): number;
|
|
34
|
+
/** Metric + numeric target after resolving a `ContrastSpec` for a mode. */
|
|
35
|
+
interface ResolvedContrast {
|
|
36
|
+
metric: 'wcag' | 'apca';
|
|
37
|
+
/** WCAG ratio (>= 1) or APCA Lc magnitude (0–106). */
|
|
38
|
+
target: number;
|
|
39
|
+
/**
|
|
40
|
+
* APCA argument order: which side the resolved (candidate) color plays
|
|
41
|
+
* against the base. `'fg'` (default) → `apcaContrast(yCandidate, yBase)`;
|
|
42
|
+
* `'bg'` → `apcaContrast(yBase, yCandidate)`. Always `'fg'` for WCAG
|
|
43
|
+
* (symmetric, ignored).
|
|
44
|
+
*/
|
|
45
|
+
polarity?: 'fg' | 'bg';
|
|
46
|
+
}
|
|
47
|
+
declare function resolveMinContrast(value: MinContrast$1): number;
|
|
48
|
+
/**
|
|
49
|
+
* Resolve a `ContrastSpec` (already selected from any outer HC pair) for a
|
|
50
|
+
* given mode into `{ metric, target }`. Handles the inner metric HC pair and
|
|
51
|
+
* preset resolution. `polarity` is passed through to the result for the APCA
|
|
52
|
+
* branch (it controls argument order in the solver); WCAG ignores it.
|
|
53
|
+
*
|
|
54
|
+
* `outerExplicitHC` indicates whether the caller selected this `spec` from an
|
|
55
|
+
* explicit high-contrast entry of the outer `contrast` pair. Together with the
|
|
56
|
+
* inner metric pair, it decides whether the HC auto-enhancement fires:
|
|
57
|
+
* - APCA: +15 Lc "Enhanced Level" boost when neither level is explicit.
|
|
58
|
+
* - WCAG: AA → AAA / AA-large → AAA-large promotion (SC 1.4.3 → 1.4.6) when
|
|
59
|
+
* neither level is explicit. AAA-family presets and bare numbers are left
|
|
60
|
+
* unchanged (AAA is the top WCAG tier).
|
|
61
|
+
* Defaults to `false` (correct for direct callers, which pass a single
|
|
62
|
+
* selected spec rather than an outer pair).
|
|
63
|
+
*/
|
|
64
|
+
declare function resolveContrastForMode(spec: ContrastSpec, isHighContrast: boolean, polarity?: 'fg' | 'bg', outerExplicitHC?: boolean): ResolvedContrast;
|
|
65
|
+
/**
|
|
66
|
+
* Resolve a `contrast` spec — including its outer `[normal, highContrast]`
|
|
67
|
+
* pair — at a manual contrast `level` (0–100), by resolving both ends and
|
|
68
|
+
* interpolating the numeric target.
|
|
69
|
+
*
|
|
70
|
+
* Level 0 / 100 delegate verbatim to {@link resolveContrastForMode}, so the
|
|
71
|
+
* endpoints are bit-identical to classic normal / high-contrast resolution.
|
|
72
|
+
* Resolving each end fully first also means every rule that governs the
|
|
73
|
+
* escalation still applies at both ends for free: preset mapping, the
|
|
74
|
+
* `APCA_MAX_LC` clamp, and the explicit-HC suppression that cancels the
|
|
75
|
+
* `AA → AAA` promotion and the `+15 Lc` enhancement.
|
|
76
|
+
*
|
|
77
|
+
* Throws when the two ends measure in different metrics — a WCAG ratio and an
|
|
78
|
+
* APCA Lc live on different scales, so there is no target between them. Such a
|
|
79
|
+
* pair is rejected at authoring time by `validateColorDefs`; this is the guard
|
|
80
|
+
* for direct callers.
|
|
81
|
+
*/
|
|
82
|
+
declare function resolveContrastForLevel(spec: HCPair<ContrastSpec>, level: number, polarity?: 'fg' | 'bg'): ResolvedContrast;
|
|
83
|
+
/**
|
|
84
|
+
* APCA lightness contrast (Lc), signed: positive for dark text on light bg,
|
|
85
|
+
* negative for light text on dark bg. Inputs are screen luminances (0–1).
|
|
86
|
+
*/
|
|
87
|
+
declare function apcaContrast(yText: number, yBg: number): number;
|
|
88
|
+
interface FindToneForContrastOptions {
|
|
13
89
|
/** Hue of the candidate color (0–360). */
|
|
14
90
|
hue: number;
|
|
15
91
|
/** Saturation of the candidate color (0–1). */
|
|
16
92
|
saturation: number;
|
|
17
|
-
/** Preferred
|
|
18
|
-
|
|
19
|
-
/** Base/reference color as linear sRGB
|
|
20
|
-
baseLinearRgb:
|
|
21
|
-
/**
|
|
22
|
-
contrast:
|
|
23
|
-
/** Search bounds for
|
|
24
|
-
|
|
93
|
+
/** Preferred tone of the candidate (0–1). */
|
|
94
|
+
preferredTone: number;
|
|
95
|
+
/** Base/reference color as linear sRGB. */
|
|
96
|
+
baseLinearRgb: LinearRgb;
|
|
97
|
+
/** Resolved contrast floor (metric + target). */
|
|
98
|
+
contrast: ResolvedContrast;
|
|
99
|
+
/** Search bounds for tone. Default: [0, 1]. */
|
|
100
|
+
toneRange?: [number, number];
|
|
25
101
|
/** Convergence threshold. Default: 1e-4. */
|
|
26
102
|
epsilon?: number;
|
|
27
|
-
/** Maximum binary-search iterations per branch. Default:
|
|
103
|
+
/** Maximum binary-search iterations per branch. Default: 18. */
|
|
28
104
|
maxIterations?: number;
|
|
105
|
+
/**
|
|
106
|
+
* Preferred search direction before auto-flip is considered. Default: the
|
|
107
|
+
* side whose bound scores higher (the only open side when `preferredTone`
|
|
108
|
+
* sits on a bound); a tie within float noise starts `'darker'`.
|
|
109
|
+
*/
|
|
110
|
+
initialDirection?: 'lighter' | 'darker';
|
|
111
|
+
/**
|
|
112
|
+
* Also search the opposite direction. Default: false. When both directions
|
|
113
|
+
* meet the target, the result nearer `preferredTone` wins; a gap within
|
|
114
|
+
* twice the search resolution is a tie and keeps `initialDirection`.
|
|
115
|
+
*/
|
|
116
|
+
flip?: boolean;
|
|
117
|
+
/**
|
|
118
|
+
* When `flip` is on and *both* directions meet the target, keep
|
|
119
|
+
* `initialDirection` instead of taking whichever result lands nearer the
|
|
120
|
+
* preferred tone. Default: false (nearest wins).
|
|
121
|
+
*
|
|
122
|
+
* The nearest-wins tie-break is unstable along a ramp of targets: which side
|
|
123
|
+
* is nearer shifts as the target grows, so a color can swap sides between two
|
|
124
|
+
* adjacent targets. Set this when a caller needs the side to be a property of
|
|
125
|
+
* the color rather than of the target — the manual contrast level does. The
|
|
126
|
+
* flip itself is unaffected: an initial direction that cannot reach the
|
|
127
|
+
* target still falls back to the opposite side.
|
|
128
|
+
*/
|
|
129
|
+
preferInitial?: boolean;
|
|
130
|
+
/** Use the hue-independent "safe" chroma boundary. Default: false. */
|
|
131
|
+
pastel?: boolean;
|
|
29
132
|
}
|
|
30
|
-
interface
|
|
31
|
-
/** Chosen
|
|
32
|
-
|
|
33
|
-
/** Achieved WCAG
|
|
133
|
+
interface FindToneForContrastResult {
|
|
134
|
+
/** Chosen tone in 0–1. */
|
|
135
|
+
tone: number;
|
|
136
|
+
/** Achieved score (WCAG ratio or APCA Lc magnitude). */
|
|
34
137
|
contrast: number;
|
|
35
138
|
/** Whether the target was reached. */
|
|
36
139
|
met: boolean;
|
|
37
|
-
/**
|
|
140
|
+
/**
|
|
141
|
+
* The side the result was found on. The two sides meet at `preferredTone`,
|
|
142
|
+
* so a met result sits on that side of the base too. `'preferred'` whenever
|
|
143
|
+
* a met result is `preferredTone` itself: it already cleared the
|
|
144
|
+
* overshooting search target, or it clears the bare target and no search
|
|
145
|
+
* could improve on it — no searched side met the floor, or the starting
|
|
146
|
+
* side's only position was `preferredTone` (it sits on that side's bound).
|
|
147
|
+
* Also `'preferred'` when `toneRange` leaves no room to search, met or not.
|
|
148
|
+
* An unmet result otherwise reports the side whose extreme it pinned to.
|
|
149
|
+
*/
|
|
38
150
|
branch: 'lighter' | 'darker' | 'preferred';
|
|
151
|
+
/** Whether the result auto-flipped to the opposite direction. */
|
|
152
|
+
flipped?: boolean;
|
|
39
153
|
}
|
|
40
|
-
declare function resolveMinContrast(value: MinContrast$1): number;
|
|
41
154
|
/**
|
|
42
|
-
* Find the
|
|
43
|
-
*
|
|
155
|
+
* Find the tone that satisfies a contrast floor against a base color,
|
|
156
|
+
* staying as close to `preferredTone` as possible. A searched result keeps the
|
|
157
|
+
* overshoot (1% for WCAG, 0.5 Lc for APCA). When no searched side reaches the
|
|
158
|
+
* floor, the result pins to the initial direction's extreme, unmet — unless
|
|
159
|
+
* `preferredTone` itself clears the bare target, which is then kept as met
|
|
160
|
+
* (`branch: 'preferred'`, the same label a met result gets when the starting
|
|
161
|
+
* side's only position is `preferredTone`).
|
|
44
162
|
*/
|
|
45
|
-
declare function
|
|
163
|
+
declare function findToneForContrast(options: FindToneForContrastOptions): FindToneForContrastResult;
|
|
46
164
|
interface FindValueForMixContrastOptions {
|
|
47
165
|
/** Preferred mix parameter (0–1). */
|
|
48
166
|
preferredValue: number;
|
|
49
|
-
/** Base color as linear sRGB. */
|
|
167
|
+
/** Base color as linear sRGB — the color the mix is measured against. */
|
|
50
168
|
baseLinearRgb: LinearRgb;
|
|
51
|
-
/**
|
|
52
|
-
|
|
53
|
-
/** WCAG contrast target. */
|
|
54
|
-
contrast: MinContrast$1;
|
|
169
|
+
/** Resolved contrast floor (metric + target). */
|
|
170
|
+
contrast: ResolvedContrast;
|
|
55
171
|
/**
|
|
56
|
-
*
|
|
57
|
-
*
|
|
58
|
-
*
|
|
172
|
+
* Luminance of the mixed color at parameter t, in the metric's basis
|
|
173
|
+
* ({@link metricLuminance}). This closure is the only view the solver has of
|
|
174
|
+
* the mix's target color, blend, and color space.
|
|
59
175
|
*/
|
|
60
176
|
luminanceAtValue: (t: number) => number;
|
|
61
177
|
/** Convergence threshold. Default: 1e-4. */
|
|
62
178
|
epsilon?: number;
|
|
63
179
|
/** Maximum binary-search iterations per branch. Default: 20. */
|
|
64
180
|
maxIterations?: number;
|
|
181
|
+
/** Auto-flip mix direction when contrast can't be met. Default: false. */
|
|
182
|
+
flip?: boolean;
|
|
65
183
|
}
|
|
66
184
|
interface FindValueForMixContrastResult {
|
|
67
|
-
/** Chosen mix parameter (0–1). */
|
|
68
185
|
value: number;
|
|
69
|
-
/** Achieved WCAG contrast ratio. */
|
|
70
186
|
contrast: number;
|
|
71
|
-
/** Whether the target was reached. */
|
|
72
187
|
met: boolean;
|
|
188
|
+
flipped?: boolean;
|
|
73
189
|
}
|
|
74
190
|
/**
|
|
75
|
-
* Find the mix parameter (ratio or opacity) that satisfies a
|
|
76
|
-
*
|
|
191
|
+
* Find the mix parameter (ratio or opacity) that satisfies a contrast floor
|
|
192
|
+
* against a base color, staying as close to `preferredValue` as possible.
|
|
193
|
+
* Misses pin to the initial direction's end like the tone solver, and a
|
|
194
|
+
* `preferredValue` that clears the bare target is kept as met when no searched
|
|
195
|
+
* side reaches the floor (a value of 1 has no room toward the target).
|
|
77
196
|
*/
|
|
78
197
|
declare function findValueForMixContrast(options: FindValueForMixContrastOptions): FindValueForMixContrastResult;
|
|
79
198
|
//#endregion
|
|
80
199
|
//#region src/types.d.ts
|
|
81
200
|
/** A value or [normal, high-contrast] pair. */
|
|
82
201
|
type HCPair<T> = T | [T, T];
|
|
202
|
+
/** Bare WCAG contrast target: a ratio number or a named preset. */
|
|
83
203
|
type MinContrast = number | ContrastPreset;
|
|
204
|
+
/**
|
|
205
|
+
* A contrast floor with a pluggable metric.
|
|
206
|
+
*
|
|
207
|
+
* - `number` / `ContrastPreset`: a WCAG ratio (bare form).
|
|
208
|
+
* - `{ wcag }`: WCAG ratio or preset, optionally an HC pair.
|
|
209
|
+
* - `{ apca }`: APCA Lc target (absolute value or preset), optionally an HC pair.
|
|
210
|
+
*
|
|
211
|
+
* The `[normal, highContrast]` pair may live at the outer level
|
|
212
|
+
* (`[4.5, 7]`, `[{ wcag: 4.5 }, { wcag: 7 }]`) or inside the metric
|
|
213
|
+
* (`{ wcag: [4.5, 7] }`, `{ apca: [45, 60] }`, `{ apca: ['content', 'body'] }`).
|
|
214
|
+
*/
|
|
215
|
+
type ContrastSpec = number | ContrastPreset | {
|
|
216
|
+
wcag: HCPair<number | ContrastPreset>;
|
|
217
|
+
} | {
|
|
218
|
+
apca: HCPair<number | ApcaPreset>;
|
|
219
|
+
};
|
|
220
|
+
/**
|
|
221
|
+
* The semantic role a color plays against its base, used to fix APCA contrast
|
|
222
|
+
* polarity (which side is the foreground vs the background). WCAG is
|
|
223
|
+
* symmetric, so role never changes WCAG results.
|
|
224
|
+
*/
|
|
225
|
+
type Role = 'text' | 'surface' | 'border';
|
|
226
|
+
/**
|
|
227
|
+
* Any string accepted as a `role`. Canonical values plus aliases normalized by
|
|
228
|
+
* `normalizeRole` (see `roles.ts`): `surface` (bg/background/fill/canvas/
|
|
229
|
+
* paper/layer), `text` (fg/foreground/content/ink/label/stroke), `border`
|
|
230
|
+
* (divider/outline/separator/hairline/rule).
|
|
231
|
+
*/
|
|
232
|
+
type RoleInput = Role | 'bg' | 'background' | 'fill' | 'canvas' | 'paper' | 'layer' | 'fg' | 'foreground' | 'content' | 'ink' | 'label' | 'stroke' | 'divider' | 'outline' | 'separator' | 'hairline' | 'rule';
|
|
84
233
|
type AdaptationMode = 'auto' | 'fixed' | 'static';
|
|
85
234
|
/** A signed relative offset string, e.g. '+20' or '-15.5'. */
|
|
86
235
|
type RelativeValue = `+${number}` | `-${number}`;
|
|
236
|
+
/**
|
|
237
|
+
* Force a color to a tone extreme:
|
|
238
|
+
* - `'max'`: the highest tone in the active scheme range/window.
|
|
239
|
+
* - `'min'`: the lowest tone.
|
|
240
|
+
*
|
|
241
|
+
* Under `mode: 'auto'` the extreme inverts in the dark scheme (so `'max'`
|
|
242
|
+
* tracks the inversion and becomes the darkest tone). No `base` required.
|
|
243
|
+
*/
|
|
244
|
+
type ExtremeValue = 'max' | 'min';
|
|
245
|
+
/**
|
|
246
|
+
* A tone value as authored on a color.
|
|
247
|
+
* - Number: absolute tone (0–100).
|
|
248
|
+
* - `'+N'` / `'-N'`: relative to the base's tone (requires `base`).
|
|
249
|
+
* - `'max'` / `'min'`: forced to the scheme's tone extreme (no base needed).
|
|
250
|
+
*/
|
|
251
|
+
type ToneValue = number | RelativeValue | ExtremeValue;
|
|
87
252
|
/** Color format for output. */
|
|
88
|
-
type GlazeColorFormat = 'okhsl' | 'rgb' | 'hsl' | 'oklch';
|
|
253
|
+
type GlazeColorFormat = 'okhsl' | 'okhst' | 'rgb' | 'hsl' | 'oklch';
|
|
254
|
+
/**
|
|
255
|
+
* Output format for an HDR glow value (`glaze.formatHdr()`). Only
|
|
256
|
+
* `'srgb-linear'` — `color(srgb-linear R G B)` with channels that may exceed
|
|
257
|
+
* 1 — since OKLCH lightness clamps at parse time and `rgb()` / `hsl()` cannot
|
|
258
|
+
* go past white.
|
|
259
|
+
*/
|
|
260
|
+
type GlazeHdrFormat = 'srgb-linear';
|
|
89
261
|
/**
|
|
90
262
|
* Controls which scheme variants are generated in the export.
|
|
91
263
|
* Light is always included (it's the default).
|
|
@@ -93,8 +265,29 @@ type GlazeColorFormat = 'okhsl' | 'rgb' | 'hsl' | 'oklch';
|
|
|
93
265
|
interface GlazeOutputModes {
|
|
94
266
|
/** Include dark scheme variants. Default: true. */
|
|
95
267
|
dark?: boolean;
|
|
96
|
-
/**
|
|
268
|
+
/**
|
|
269
|
+
* Include high-contrast variants (both light-HC and dark-HC). Default: false.
|
|
270
|
+
*
|
|
271
|
+
* Independent of `contrastLevel` — the level positions the normal variants
|
|
272
|
+
* while these stay the true high-contrast resolution, so the two compose. The
|
|
273
|
+
* exception is a global level of 100, where the normal variants already *are*
|
|
274
|
+
* the high-contrast ones: the tier would duplicate them and is dropped.
|
|
275
|
+
* @see GlazeConfig.contrastLevel
|
|
276
|
+
*/
|
|
97
277
|
highContrast?: boolean;
|
|
278
|
+
/**
|
|
279
|
+
* Include the HDR tier of glows past SDR white (`variant.hdr`, set by
|
|
280
|
+
* `GlowTuning.headroom`). Default: false — every exporter's output stays
|
|
281
|
+
* byte-identical to SDR even when a headroom is set.
|
|
282
|
+
*
|
|
283
|
+
* When on, each exporter adds the HDR values next to the SDR ones it
|
|
284
|
+
* already emits (only for the scheme variants the other modes include),
|
|
285
|
+
* always written as `color(srgb-linear R G B)`: Tasty `hdr` state keys,
|
|
286
|
+
* `json()` `lightHdr` / `darkHdr` / … keys, `tokens()` `lightHdr` / … maps,
|
|
287
|
+
* Tailwind blocks under `hdrSelector`, DTCG `$extensions`. `css()` reads
|
|
288
|
+
* its own `hdr` option, which falls back to this.
|
|
289
|
+
*/
|
|
290
|
+
hdr?: boolean;
|
|
98
291
|
}
|
|
99
292
|
/** Hex color string for DX hints. Runtime validation in `parseHex()`. */
|
|
100
293
|
type HexColor = `#${string}`;
|
|
@@ -104,14 +297,66 @@ interface OkhslColor {
|
|
|
104
297
|
s: number;
|
|
105
298
|
l: number;
|
|
106
299
|
}
|
|
300
|
+
/**
|
|
301
|
+
* Direct OKHST color input — OKHSL with the lightness axis replaced by the
|
|
302
|
+
* contrast-uniform tone axis. `h`: 0–360, `s`: 0–1, `t`: 0–1 (tone).
|
|
303
|
+
*/
|
|
304
|
+
interface OkhstColor {
|
|
305
|
+
h: number;
|
|
306
|
+
s: number;
|
|
307
|
+
t: number;
|
|
308
|
+
}
|
|
309
|
+
/** sRGB components in 0–255 (value-shorthand object form). */
|
|
310
|
+
interface RgbColor {
|
|
311
|
+
r: number;
|
|
312
|
+
g: number;
|
|
313
|
+
b: number;
|
|
314
|
+
}
|
|
315
|
+
/** OKLCh components matching CSS `oklch(L C H)` (L/C: 0–1, H: degrees). */
|
|
316
|
+
interface OklchColor {
|
|
317
|
+
l: number;
|
|
318
|
+
c: number;
|
|
319
|
+
h: number;
|
|
320
|
+
}
|
|
107
321
|
interface RegularColorDef {
|
|
108
322
|
/**
|
|
109
|
-
*
|
|
110
|
-
*
|
|
111
|
-
*
|
|
323
|
+
* Seed this color from a literal color instead of from the theme.
|
|
324
|
+
*
|
|
325
|
+
* Accepts the same values as `glaze.color()` — hex, `rgb()`, `hsl()`,
|
|
326
|
+
* `okhsl()`, `okhst()`, `oklch()`, or a value object. It supplies three
|
|
327
|
+
* things at once: `hue`, `tone`, and — unlike every other color in a theme —
|
|
328
|
+
* an **absolute saturation** rather than a factor of the seed. That last
|
|
329
|
+
* part is the point: a color can now be more saturated than its theme, so
|
|
330
|
+
* honoring a brand color no longer means re-seeding the whole theme to reach
|
|
331
|
+
* it.
|
|
332
|
+
*
|
|
333
|
+
* The **light, normal-contrast** variant reproduces the value exactly
|
|
334
|
+
* (a local `lightTone: false`, matching the value-shorthand form of
|
|
335
|
+
* `glaze.color()`). Dark and high-contrast variants adapt as usual — they
|
|
336
|
+
* are where readability outranks fidelity, and a color pinned across every
|
|
337
|
+
* scheme would defeat both. A `contrast` floor still applies everywhere and
|
|
338
|
+
* still only moves the color when the authored value misses it.
|
|
339
|
+
*
|
|
340
|
+
* Sibling fields override what the value supplied, so
|
|
341
|
+
* `{ from: '#2F5BFF', hue: 300 }` keeps its saturation and tone but rotates
|
|
342
|
+
* the hue.
|
|
343
|
+
*/
|
|
344
|
+
from?: GlazeColorValue;
|
|
345
|
+
/**
|
|
346
|
+
* Tone value (0–100, contrast-uniform — see `docs/okhst.mdx`).
|
|
347
|
+
* - Number: absolute tone.
|
|
348
|
+
* - String ('+N' / '-N'): relative to base color's tone (requires `base`).
|
|
349
|
+
* - `'max'` / `'min'`: force to the scheme's tone extreme (no base needed).
|
|
350
|
+
*
|
|
351
|
+
* Defaults to the tone of `from` when that is set.
|
|
352
|
+
*/
|
|
353
|
+
tone?: HCPair<ToneValue>;
|
|
354
|
+
/**
|
|
355
|
+
* Saturation factor applied to the seed saturation (0–1, default: 1).
|
|
356
|
+
*
|
|
357
|
+
* With `from`, an explicit value here is still a factor of the seed and
|
|
358
|
+
* overrides the absolute saturation the color carried.
|
|
112
359
|
*/
|
|
113
|
-
lightness?: HCPair<number | RelativeValue>;
|
|
114
|
-
/** Saturation factor applied to the seed saturation (0–1, default: 1). */
|
|
115
360
|
saturation?: number;
|
|
116
361
|
/**
|
|
117
362
|
* Hue override for this color.
|
|
@@ -119,69 +364,217 @@ interface RegularColorDef {
|
|
|
119
364
|
* - String ('+N' / '-N'): relative to the theme seed hue.
|
|
120
365
|
*/
|
|
121
366
|
hue?: number | RelativeValue;
|
|
367
|
+
/**
|
|
368
|
+
* Dark-scheme hue override. Applies to the `dark` and `darkContrast`
|
|
369
|
+
* variants; falls back to `hue` when omitted.
|
|
370
|
+
* - Number: absolute hue (0–360).
|
|
371
|
+
* - String ('+N' / '-N'): relative to the theme's **dark** seed hue
|
|
372
|
+
* (`GlazeTheme.darkHue`, itself defaulting to the light seed hue).
|
|
373
|
+
*
|
|
374
|
+
* Ignored under `mode: 'static'`, which pins one value across all schemes.
|
|
375
|
+
*/
|
|
376
|
+
darkHue?: number | RelativeValue;
|
|
377
|
+
/**
|
|
378
|
+
* Dark-scheme saturation factor (0–1) applied to the dark seed
|
|
379
|
+
* saturation. Applies to the `dark` and `darkContrast` variants; falls
|
|
380
|
+
* back to `saturation` when omitted.
|
|
381
|
+
*
|
|
382
|
+
* When set, the global `darkDesaturation` reduction is **not** applied on
|
|
383
|
+
* top — the resulting saturation is taken literally. Ignored under
|
|
384
|
+
* `mode: 'static'`.
|
|
385
|
+
*/
|
|
386
|
+
darkSaturation?: number;
|
|
122
387
|
/** Name of another color in the same theme (dependent color). */
|
|
123
388
|
base?: string;
|
|
124
|
-
/**
|
|
125
|
-
|
|
389
|
+
/**
|
|
390
|
+
* Contrast floor against the base color. A bare number/preset is WCAG;
|
|
391
|
+
* use `{ wcag }` / `{ apca }` to pick the metric. Accepts an HC pair.
|
|
392
|
+
*/
|
|
393
|
+
contrast?: HCPair<ContrastSpec>;
|
|
126
394
|
/** Adaptation mode. Default: 'auto'. */
|
|
127
395
|
mode?: AdaptationMode;
|
|
396
|
+
/**
|
|
397
|
+
* Whether to flip out-of-bounds results to the opposite side instead of
|
|
398
|
+
* clamping to the extreme. Affects both:
|
|
399
|
+
* - relative `tone`: when `base ± delta` exceeds `[0, 100]`, mirror the
|
|
400
|
+
* delta to the other side of the base. If the mirrored target is also
|
|
401
|
+
* out of range, keep the original delta and clamp on the authored side.
|
|
402
|
+
* - `contrast`: when the requested direction can't meet the floor, try the
|
|
403
|
+
* opposite side (same as the global `autoFlip`).
|
|
404
|
+
*
|
|
405
|
+
* Defaults to the global `autoFlip` config (default `true`). Set `false`
|
|
406
|
+
* to clamp instead.
|
|
407
|
+
*/
|
|
408
|
+
autoFlip?: boolean;
|
|
128
409
|
/**
|
|
129
410
|
* Fixed opacity (0–1).
|
|
130
411
|
* Output includes alpha in the CSS value.
|
|
131
412
|
* Does not affect contrast resolution — a semi-transparent color
|
|
132
|
-
* has no fixed perceived
|
|
413
|
+
* has no fixed perceived tone, so `contrast` and `opacity`
|
|
133
414
|
* should not be combined (a console.warn is emitted).
|
|
134
415
|
*/
|
|
135
416
|
opacity?: number;
|
|
417
|
+
/**
|
|
418
|
+
* Per-color override for the hue-independent "safe" chroma limit used in
|
|
419
|
+
* OKHSL↔sRGB conversions (luminance, contrast solving, output formatting).
|
|
420
|
+
* Falls through to the per-theme / per-token `pastel` override when omitted.
|
|
421
|
+
* @see GlazeConfigOverride.pastel
|
|
422
|
+
*/
|
|
423
|
+
pastel?: boolean;
|
|
424
|
+
/**
|
|
425
|
+
* Semantic role against `base`: how this color is used. Fixes APCA contrast
|
|
426
|
+
* polarity (the argument order in `apcaContrast`). WCAG is symmetric so it
|
|
427
|
+
* never affects WCAG results.
|
|
428
|
+
*
|
|
429
|
+
* Resolution: explicit `role` wins; else inferred from the color name when
|
|
430
|
+
* `inferRole` is enabled (default); else the opposite of the base's role;
|
|
431
|
+
* else defaults to `'text'` (foreground).
|
|
432
|
+
*/
|
|
433
|
+
role?: RoleInput;
|
|
136
434
|
/**
|
|
137
435
|
* Whether this color is inherited by child themes created via `extend()`.
|
|
138
436
|
* Default: true. Set to false to make this color local to the current theme.
|
|
139
437
|
*/
|
|
140
438
|
inherit?: boolean;
|
|
141
439
|
}
|
|
142
|
-
/**
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
/**
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
440
|
+
/**
|
|
441
|
+
* Tuning shared by `shadow` and `glow`. Global defaults come from
|
|
442
|
+
* `shadowTuning` / `glowTuning`; a per-color `tuning` merges over them field
|
|
443
|
+
* by field.
|
|
444
|
+
*/
|
|
445
|
+
interface LightingTuning {
|
|
446
|
+
/**
|
|
447
|
+
* β — how strongly the object (`fg`) scales the step. The step is
|
|
448
|
+
* `intensity × k` with `k = max(0, 1 + β · d · (t_bg − t_fg) / 100)`,
|
|
449
|
+
* `d = +1` for a shadow and `−1` for a glow: a darker object deepens its
|
|
450
|
+
* shadow, a lighter one strengthens its glow. An object at the surface's
|
|
451
|
+
* own tone (or no `fg`) gives exactly `intensity`. `0` ignores the object.
|
|
452
|
+
* Default: 0.5.
|
|
453
|
+
*/
|
|
454
|
+
objectInfluence?: number;
|
|
455
|
+
/**
|
|
456
|
+
* Pigment saturation (0–1) in the surface's hue. Default: 0 (neutral black /
|
|
457
|
+
* white). Shows only with `reach` below 1 — pure black and white have no hue.
|
|
458
|
+
*/
|
|
459
|
+
tint?: number;
|
|
460
|
+
/**
|
|
461
|
+
* Where the pigment sits (0–1): the fraction of the way from the surface's
|
|
462
|
+
* tone to black (shadow) / white (glow). Default: 1 (pure black / white),
|
|
463
|
+
* the most reach. Lower values let a `tint` show at the cost of reach.
|
|
464
|
+
*/
|
|
465
|
+
reach?: number;
|
|
152
466
|
/**
|
|
153
|
-
*
|
|
154
|
-
* Default: 0.
|
|
467
|
+
* Pull (0–1) of the pigment hue from the surface's hue toward the object's
|
|
468
|
+
* (`fg`) hue. Default: 0. Needs `fg`, a `tint`, and `reach` below 1 to show.
|
|
155
469
|
*/
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
470
|
+
hueBleed?: number;
|
|
471
|
+
}
|
|
472
|
+
/**
|
|
473
|
+
* Tuning for `shadow` colors: the shared {@link LightingTuning}. It has no
|
|
474
|
+
* `headroom` — a shadow darkens toward black, and nothing goes below black —
|
|
475
|
+
* so a `headroom` set on a shadow's tuning throws.
|
|
476
|
+
*/
|
|
477
|
+
type ShadowTuning = LightingTuning;
|
|
478
|
+
/** Tuning for `glow` colors: the shared {@link LightingTuning} plus HDR `headroom`. */
|
|
479
|
+
interface GlowTuning extends LightingTuning {
|
|
159
480
|
/**
|
|
160
|
-
*
|
|
161
|
-
* 0
|
|
481
|
+
* Stops above SDR white a glow may use when its step crosses white. Default:
|
|
482
|
+
* 0 (SDR only). Counted in stops — doublings of SDR white's luminance — not
|
|
483
|
+
* as a ratio: `1` allows up to 2× white, `2` up to 4×. Must be a finite
|
|
484
|
+
* number ≥ 0; values above 2 clamp to 2 with a one-time warning.
|
|
485
|
+
*
|
|
486
|
+
* Only a glow whose target tone (surface tone + `intensity × k`) passes 100
|
|
487
|
+
* gets an HDR value: the variant's `hdr`, an opaque exposure of what SDR
|
|
488
|
+
* paints at its brightest — the pigment at full opacity, or a white surface
|
|
489
|
+
* no pigment can lift — plus a gain in stops. A pigment that cannot lift a
|
|
490
|
+
* non-white surface at all (`reach: 0` on a gray surface, say) paints
|
|
491
|
+
* nothing in SDR, so it gets no HDR value either and keeps the SDR "cannot
|
|
492
|
+
* reach" warning. On a chromatic surface a `reach: 0` gray can measure
|
|
493
|
+
* slightly brighter than the surface and pins at full opacity instead.
|
|
494
|
+
* Nothing about the SDR variant changes. The gain lands the exact step when
|
|
495
|
+
* the headroom allows it; the brightest channel caps at `2^headroom`.
|
|
496
|
+
* High-contrast schemes use the same headroom.
|
|
497
|
+
*
|
|
498
|
+
* The HDR value lands the whole step, not just the part past white. A
|
|
499
|
+
* full-reach glow (the default `reach: 1`) is pinned at white, so its HDR
|
|
500
|
+
* value starts at white (`exposure` → 0) as the target passes 100. A glow
|
|
501
|
+
* with `reach` below 1 is pinned at its pigment, below white: just under 100
|
|
502
|
+
* it stays short there (and warns), and just past 100 its HDR value jumps to
|
|
503
|
+
* the exact step.
|
|
162
504
|
*/
|
|
163
|
-
|
|
505
|
+
headroom?: number;
|
|
164
506
|
}
|
|
507
|
+
/**
|
|
508
|
+
* A translucent dark overlay that lands the surface (`bg`) exactly
|
|
509
|
+
* `intensity` tones darker in every scheme — a shade for state layers and
|
|
510
|
+
* scrims, or, with `fg`, an object-aware drop shadow.
|
|
511
|
+
*/
|
|
165
512
|
interface ShadowColorDef {
|
|
166
513
|
type: 'shadow';
|
|
167
514
|
/**
|
|
168
|
-
*
|
|
169
|
-
*
|
|
515
|
+
* The surface the shadow falls on. Must reference a color that is not a
|
|
516
|
+
* shadow or glow.
|
|
170
517
|
*/
|
|
171
518
|
bg: string;
|
|
172
519
|
/**
|
|
173
|
-
*
|
|
174
|
-
*
|
|
175
|
-
* Omit for
|
|
520
|
+
* The object casting the shadow (e.g. the card). A darker object casts a
|
|
521
|
+
* deeper shadow, a lighter one a softer shadow — see
|
|
522
|
+
* `LightingTuning.objectInfluence`. Omit for an exact shade of `intensity`
|
|
523
|
+
* tones. Must reference a color that is not a shadow or glow.
|
|
176
524
|
*/
|
|
177
525
|
fg?: string;
|
|
178
526
|
/**
|
|
179
|
-
*
|
|
527
|
+
* Tone step, 0–100: how many tones darker than `bg` the composite lands.
|
|
180
528
|
* Supports [normal, highContrast] pair.
|
|
181
529
|
*/
|
|
182
530
|
intensity: HCPair<number>;
|
|
183
531
|
/** Override default tuning. Merged field-by-field with global `shadowTuning`. */
|
|
184
532
|
tuning?: ShadowTuning;
|
|
533
|
+
/**
|
|
534
|
+
* Per-color override for the hue-independent "safe" chroma limit used in
|
|
535
|
+
* OKHSL↔sRGB conversions (luminance, contrast solving, output formatting).
|
|
536
|
+
* Falls through to the per-theme / per-token `pastel` override when omitted.
|
|
537
|
+
* @see GlazeConfigOverride.pastel
|
|
538
|
+
*/
|
|
539
|
+
pastel?: boolean;
|
|
540
|
+
/**
|
|
541
|
+
* Whether this color is inherited by child themes created via `extend()`.
|
|
542
|
+
* Default: true. Set to false to make this color local to the current theme.
|
|
543
|
+
*/
|
|
544
|
+
inherit?: boolean;
|
|
545
|
+
}
|
|
546
|
+
/**
|
|
547
|
+
* The mirror of {@link ShadowColorDef}: a translucent light overlay that lands
|
|
548
|
+
* the surface (`bg`) exactly `intensity` tones lighter in every scheme — for
|
|
549
|
+
* dark-mode elevation, edge highlights, and lightening state layers.
|
|
550
|
+
*/
|
|
551
|
+
interface GlowColorDef {
|
|
552
|
+
type: 'glow';
|
|
553
|
+
/**
|
|
554
|
+
* The surface the glow falls on. Must reference a color that is not a
|
|
555
|
+
* shadow or glow.
|
|
556
|
+
*/
|
|
557
|
+
bg: string;
|
|
558
|
+
/**
|
|
559
|
+
* The object emitting the glow. A lighter object glows stronger, a darker
|
|
560
|
+
* one weaker — see `LightingTuning.objectInfluence`. Omit for an exact tint
|
|
561
|
+
* of `intensity` tones. Must reference a color that is not a shadow or glow.
|
|
562
|
+
*/
|
|
563
|
+
fg?: string;
|
|
564
|
+
/**
|
|
565
|
+
* Tone step, 0–100: how many tones lighter than `bg` the composite lands.
|
|
566
|
+
* Supports [normal, highContrast] pair.
|
|
567
|
+
*/
|
|
568
|
+
intensity: HCPair<number>;
|
|
569
|
+
/** Override default tuning. Merged field-by-field with global `glowTuning`. */
|
|
570
|
+
tuning?: GlowTuning;
|
|
571
|
+
/**
|
|
572
|
+
* Per-color override for the hue-independent "safe" chroma limit used in
|
|
573
|
+
* OKHSL↔sRGB conversions (luminance, contrast solving, output formatting).
|
|
574
|
+
* Falls through to the per-theme / per-token `pastel` override when omitted.
|
|
575
|
+
* @see GlazeConfigOverride.pastel
|
|
576
|
+
*/
|
|
577
|
+
pastel?: boolean;
|
|
185
578
|
/**
|
|
186
579
|
* Whether this color is inherited by child themes created via `extend()`.
|
|
187
580
|
* Default: true. Set to false to make this color local to the current theme.
|
|
@@ -209,36 +602,94 @@ interface MixColorDef {
|
|
|
209
602
|
/**
|
|
210
603
|
* Interpolation color space for opaque blending. Default: 'okhsl'.
|
|
211
604
|
* - 'okhsl': perceptually uniform, consistent with Glaze's internal model.
|
|
212
|
-
* - 'srgb': linear sRGB interpolation
|
|
605
|
+
* - 'srgb': linear-light sRGB interpolation (like CSS
|
|
606
|
+
* `color-mix(in srgb-linear, …)`).
|
|
213
607
|
*
|
|
214
|
-
* Ignored for 'transparent' blend
|
|
608
|
+
* Ignored for 'transparent' blend: the browser composites that one, and
|
|
609
|
+
* its contrast solve models the browser (`source-over` on gamma-encoded
|
|
610
|
+
* sRGB).
|
|
215
611
|
*/
|
|
216
612
|
space?: 'okhsl' | 'srgb';
|
|
217
613
|
/**
|
|
218
|
-
* Minimum
|
|
614
|
+
* Minimum contrast between the base and the resulting color.
|
|
219
615
|
* In 'opaque' mode, adjusts the mix ratio to meet contrast.
|
|
220
616
|
* In 'transparent' mode, adjusts opacity to meet contrast against the composite.
|
|
221
|
-
*
|
|
617
|
+
* A bare number/preset is WCAG; use `{ wcag }` / `{ apca }` to pick the
|
|
618
|
+
* metric. Supports [normal, highContrast] pair.
|
|
619
|
+
*/
|
|
620
|
+
contrast?: HCPair<ContrastSpec>;
|
|
621
|
+
/**
|
|
622
|
+
* Per-color override for the hue-independent "safe" chroma limit used in
|
|
623
|
+
* OKHSL↔sRGB conversions (luminance, contrast solving, output formatting).
|
|
624
|
+
* Falls through to the per-theme / per-token `pastel` override when omitted.
|
|
625
|
+
* @see GlazeConfigOverride.pastel
|
|
626
|
+
*/
|
|
627
|
+
pastel?: boolean;
|
|
628
|
+
/**
|
|
629
|
+
* Semantic role of the mixed result against `base`. Same semantics as
|
|
630
|
+
* `RegularColorDef.role` (fixes APCA polarity). Resolution and defaults
|
|
631
|
+
* are identical.
|
|
222
632
|
*/
|
|
223
|
-
|
|
633
|
+
role?: RoleInput;
|
|
224
634
|
/**
|
|
225
635
|
* Whether this color is inherited by child themes created via `extend()`.
|
|
226
636
|
* Default: true. Set to false to make this color local to the current theme.
|
|
227
637
|
*/
|
|
228
638
|
inherit?: boolean;
|
|
229
639
|
}
|
|
230
|
-
type ColorDef = RegularColorDef | ShadowColorDef | MixColorDef;
|
|
640
|
+
type ColorDef = RegularColorDef | ShadowColorDef | GlowColorDef | MixColorDef;
|
|
231
641
|
type ColorMap = Record<string, ColorDef>;
|
|
232
|
-
/**
|
|
642
|
+
/**
|
|
643
|
+
* Resolved color for a single scheme variant.
|
|
644
|
+
*
|
|
645
|
+
* Stored in OKHST: `h` / `s` are OKHSL hue/saturation, `t` is the canonical
|
|
646
|
+
* contrast-uniform tone (0–1, reference eps). Convert to OKHSL lightness via
|
|
647
|
+
* `variantToOkhsl` at the rendering / luminance edges.
|
|
648
|
+
*/
|
|
233
649
|
interface ResolvedColorVariant {
|
|
234
650
|
/** OKHSL hue (0–360). */
|
|
235
651
|
h: number;
|
|
236
652
|
/** OKHSL saturation (0–1). */
|
|
237
653
|
s: number;
|
|
238
|
-
/**
|
|
239
|
-
|
|
654
|
+
/** Canonical tone (0–1, reference eps). */
|
|
655
|
+
t: number;
|
|
240
656
|
/** Opacity (0–1). Default: 1. */
|
|
241
657
|
alpha: number;
|
|
658
|
+
/**
|
|
659
|
+
* Effective `pastel` flag used while resolving this variant (author def or
|
|
660
|
+
* config fallback). Carried on the variant so output formatting matches the
|
|
661
|
+
* gamut mapping applied during resolution.
|
|
662
|
+
*/
|
|
663
|
+
pastel?: boolean;
|
|
664
|
+
/**
|
|
665
|
+
* HDR tier of a glow whose step crosses SDR white, present only when the
|
|
666
|
+
* glow's `headroom` is above 0, its target tone passes 100, and SDR is
|
|
667
|
+
* pinned at its brightest — the pigment at full opacity, or a white surface
|
|
668
|
+
* (see `GlowTuning.headroom`). Absent everywhere else — shadows, mixes,
|
|
669
|
+
* regular colors, a glow whose pigment cannot lift a non-white surface, and
|
|
670
|
+
* every glow at the default headroom of 0.
|
|
671
|
+
*/
|
|
672
|
+
hdr?: ResolvedHdr;
|
|
673
|
+
}
|
|
674
|
+
/**
|
|
675
|
+
* The HDR value of a glow past SDR white: an opaque base plus a gain. The base
|
|
676
|
+
* is what SDR paints at its brightest — the glow's pigment at full opacity, or
|
|
677
|
+
* the white surface it cannot lift — and the HDR color is that base's linear
|
|
678
|
+
* sRGB times `2^exposure`. Format it with `glaze.formatHdr()`.
|
|
679
|
+
*
|
|
680
|
+
* Stored in OKHST like the variant. `s` is always standard (non-pastel)
|
|
681
|
+
* OKHSL saturation, whatever the variant's `pastel`, since the base is an
|
|
682
|
+
* arbitrary in-gamut composite.
|
|
683
|
+
*/
|
|
684
|
+
interface ResolvedHdr {
|
|
685
|
+
/** Base OKHSL hue (0–360). */
|
|
686
|
+
h: number;
|
|
687
|
+
/** Base OKHSL saturation (0–1, non-pastel). */
|
|
688
|
+
s: number;
|
|
689
|
+
/** Base canonical tone (0–1, reference eps). */
|
|
690
|
+
t: number;
|
|
691
|
+
/** Gain over the base in stops (`log2` of the linear factor), above 0. */
|
|
692
|
+
exposure: number;
|
|
242
693
|
}
|
|
243
694
|
/** Fully resolved color across all scheme variants. */
|
|
244
695
|
interface ResolvedColor {
|
|
@@ -247,117 +698,337 @@ interface ResolvedColor {
|
|
|
247
698
|
dark: ResolvedColorVariant;
|
|
248
699
|
lightContrast: ResolvedColorVariant;
|
|
249
700
|
darkContrast: ResolvedColorVariant;
|
|
250
|
-
/** Adaptation mode
|
|
701
|
+
/** Adaptation mode of a regular color; `undefined` for shadow / glow / mix. */
|
|
251
702
|
mode?: AdaptationMode;
|
|
252
703
|
}
|
|
704
|
+
/**
|
|
705
|
+
* A scheme tone window.
|
|
706
|
+
* - `[lo, hi]`: OKHSL-lightness endpoints (0–100) the authored tone is
|
|
707
|
+
* remapped into, using the reference eps `0.05`. The common form.
|
|
708
|
+
* - `{ lo, hi, eps }`: same, with an explicit render curvature `eps`
|
|
709
|
+
* (advanced — most palettes never need this).
|
|
710
|
+
* - `false`: disable clamping (full range `[0, 100]` at the reference eps).
|
|
711
|
+
* This removes the *boundaries*, not the tone curve.
|
|
712
|
+
*/
|
|
713
|
+
type ToneWindow = false | [number, number] | {
|
|
714
|
+
lo: number;
|
|
715
|
+
hi: number;
|
|
716
|
+
eps: number;
|
|
717
|
+
};
|
|
253
718
|
interface GlazeConfig {
|
|
254
|
-
/** Light scheme
|
|
255
|
-
|
|
256
|
-
/** Dark scheme
|
|
257
|
-
|
|
719
|
+
/** Light scheme tone window — `[lo, hi]` (default `[10, 100]`), `{ lo, hi, eps }` for advanced eps tuning, or `false` to disable clamping. */
|
|
720
|
+
lightTone?: ToneWindow;
|
|
721
|
+
/** Dark scheme tone window — `[lo, hi]` (default `[15, 95]`), `{ lo, hi, eps }`, or `false` to disable clamping. */
|
|
722
|
+
darkTone?: ToneWindow;
|
|
258
723
|
/** Saturation reduction factor for dark scheme (0–1). Default: 0.1. */
|
|
259
724
|
darkDesaturation?: number;
|
|
260
725
|
/**
|
|
261
|
-
*
|
|
262
|
-
*
|
|
263
|
-
*
|
|
264
|
-
*
|
|
726
|
+
* State alias names for Tasty token export. Default to media-query states
|
|
727
|
+
* (`'@media(prefers-color-scheme: dark)'` / `'@media(prefers-contrast: more)'`
|
|
728
|
+
* / `'@media(dynamic-range: high)'`) so tokens react to the OS preference
|
|
729
|
+
* and the display without registering custom states. `hdr` keys an HDR
|
|
730
|
+
* glow value and is used only with `modes.hdr`.
|
|
265
731
|
*/
|
|
266
|
-
darkCurve?: HCPair<number>;
|
|
267
|
-
/** State alias names for token export. */
|
|
268
732
|
states?: {
|
|
269
733
|
dark?: string;
|
|
270
734
|
highContrast?: string;
|
|
735
|
+
hdr?: string;
|
|
271
736
|
};
|
|
272
|
-
/**
|
|
737
|
+
/**
|
|
738
|
+
* Which scheme variants to include in exports. Defaults: `dark: true`,
|
|
739
|
+
* `highContrast: false`, `hdr: false`.
|
|
740
|
+
*/
|
|
273
741
|
modes?: GlazeOutputModes;
|
|
274
|
-
/**
|
|
742
|
+
/**
|
|
743
|
+
* Default tuning for all shadow colors. Per-color tuning merges field-by-field.
|
|
744
|
+
* A `headroom` here throws: it is a glow-only field.
|
|
745
|
+
*/
|
|
275
746
|
shadowTuning?: ShadowTuning;
|
|
747
|
+
/**
|
|
748
|
+
* Default tuning for all glow colors, including HDR `headroom`. Per-color
|
|
749
|
+
* tuning merges field-by-field.
|
|
750
|
+
*/
|
|
751
|
+
glowTuning?: GlowTuning;
|
|
752
|
+
/**
|
|
753
|
+
* Manual contrast level — a 0–100 slider from normal contrast (`0`) to high
|
|
754
|
+
* contrast (`100`), or `'auto'` (the default) to take the authored normal
|
|
755
|
+
* entries as-is.
|
|
756
|
+
*
|
|
757
|
+
* With a number, Glaze resolves the `light` / `dark` variants *at* that level.
|
|
758
|
+
* That is all it does: `lightContrast` / `darkContrast` stay the true
|
|
759
|
+
* high-contrast resolution at every level, and `modes.highContrast` alone
|
|
760
|
+
* decides whether they are emitted. Level `0` therefore reproduces `'auto'`
|
|
761
|
+
* bit for bit. At `100` the normal variants *are* the high-contrast ones, so a
|
|
762
|
+
* separate tier would duplicate them and a global level of 100 drops it.
|
|
763
|
+
*
|
|
764
|
+
* The level interpolates all three things that make high contrast differ:
|
|
765
|
+
* authored `[normal, highContrast]` pairs, the tone-window widening, and
|
|
766
|
+
* the `AA → AAA` / APCA `+15 Lc` escalation. Contrast floors are re-solved
|
|
767
|
+
* at the interpolated target, so every level is a solution rather than an
|
|
768
|
+
* approximation, and a color keeps to one side of its base as the level moves.
|
|
769
|
+
*
|
|
770
|
+
* Pass `'auto'` to leave manual mode; `configure()` never clears a field by
|
|
771
|
+
* omission. See `docs/reference/contrast.md` for the ramp's edge cases (un-interpolable
|
|
772
|
+
* pairs, side changes) and the export-freeze rule.
|
|
773
|
+
*
|
|
774
|
+
* @default 'auto'
|
|
775
|
+
*/
|
|
776
|
+
contrastLevel?: number | 'auto';
|
|
777
|
+
/**
|
|
778
|
+
* Automatically flip tone direction when contrast can't be met.
|
|
779
|
+
*
|
|
780
|
+
* When enabled (default `true`), the solver searches the requested
|
|
781
|
+
* tone direction first. If that direction can't reach the target,
|
|
782
|
+
* it tries the opposite direction and uses it when it passes. If neither
|
|
783
|
+
* side passes, the tone is pinned to the requested-direction
|
|
784
|
+
* extreme and a warning is emitted.
|
|
785
|
+
*
|
|
786
|
+
* Set to `false` for strict "no flip" behavior. The opposite
|
|
787
|
+
* direction is never considered: if the requested direction can't
|
|
788
|
+
* meet the target, the tone is pinned to its extreme (never
|
|
789
|
+
* falls back to the originally requested tone).
|
|
790
|
+
*/
|
|
791
|
+
autoFlip?: boolean;
|
|
792
|
+
/**
|
|
793
|
+
* If true (default), infer a color's `role` from its name when no explicit
|
|
794
|
+
* `role` is set. Set to `false` to opt out of name-based inference (the
|
|
795
|
+
* base-opposite and default-foreground fallbacks still apply).
|
|
796
|
+
* @default true
|
|
797
|
+
*/
|
|
798
|
+
inferRole?: boolean;
|
|
276
799
|
}
|
|
277
800
|
interface GlazeConfigResolved {
|
|
278
|
-
|
|
279
|
-
|
|
801
|
+
lightTone: ToneWindow;
|
|
802
|
+
darkTone: ToneWindow;
|
|
280
803
|
darkDesaturation: number;
|
|
281
|
-
darkCurve: HCPair<number>;
|
|
282
804
|
states: {
|
|
283
805
|
dark: string;
|
|
284
806
|
highContrast: string;
|
|
807
|
+
hdr: string;
|
|
285
808
|
};
|
|
286
809
|
modes: Required<GlazeOutputModes>;
|
|
287
810
|
shadowTuning?: ShadowTuning;
|
|
811
|
+
glowTuning?: GlowTuning;
|
|
812
|
+
autoFlip: boolean;
|
|
813
|
+
/**
|
|
814
|
+
* Manual contrast level (0–100) for the normal variants, or `'auto'` to take
|
|
815
|
+
* the authored normal entries as-is.
|
|
816
|
+
* @see GlazeConfig.contrastLevel
|
|
817
|
+
*/
|
|
818
|
+
contrastLevel: number | 'auto';
|
|
819
|
+
/**
|
|
820
|
+
* Instance-level pastel default (`def.pastel ?? config.pastel`).
|
|
821
|
+
* Not set via `glaze.configure()` — only via per-theme / per-token
|
|
822
|
+
* `GlazeConfigOverride` (default `false`).
|
|
823
|
+
*/
|
|
824
|
+
pastel: boolean;
|
|
825
|
+
inferRole: boolean;
|
|
826
|
+
}
|
|
827
|
+
/**
|
|
828
|
+
* Per-instance config override for `glaze.color()` and `glaze()` themes.
|
|
829
|
+
* Fields that are set take priority over the live global config. Fields
|
|
830
|
+
* that are omitted fall through to the live global at resolve time
|
|
831
|
+
* (`pastel` is instance-only and defaults to `false` when omitted).
|
|
832
|
+
*
|
|
833
|
+
* `false` for a tone window disables clamping (full range at reference eps).
|
|
834
|
+
*/
|
|
835
|
+
interface GlazeConfigOverride {
|
|
836
|
+
/** Light scheme tone window, or `false` to disable clamping. */
|
|
837
|
+
lightTone?: ToneWindow;
|
|
838
|
+
/** Dark scheme tone window, or `false` to disable clamping. */
|
|
839
|
+
darkTone?: ToneWindow;
|
|
840
|
+
/** Saturation reduction factor for dark scheme (0–1). */
|
|
841
|
+
darkDesaturation?: number;
|
|
842
|
+
/** Whether to auto-flip tone when contrast can't be met. */
|
|
843
|
+
autoFlip?: boolean;
|
|
844
|
+
/**
|
|
845
|
+
* Manual contrast level (0–100) for this instance, or `'auto'` to opt out of a
|
|
846
|
+
* global level and take the authored normal entries as-is. Either way the
|
|
847
|
+
* instance keeps its high-contrast tier; a per-instance level never changes
|
|
848
|
+
* which modes are emitted.
|
|
849
|
+
*
|
|
850
|
+
* Only an instance-authored level is frozen into `.export()` snapshots — a
|
|
851
|
+
* level inherited from the global config is treated as a live preference and
|
|
852
|
+
* re-read at restore time.
|
|
853
|
+
*
|
|
854
|
+
* @see GlazeConfig.contrastLevel
|
|
855
|
+
*/
|
|
856
|
+
contrastLevel?: number | 'auto';
|
|
857
|
+
/**
|
|
858
|
+
* Instance-level pastel default for colors that omit per-color `pastel`.
|
|
859
|
+
* Not available on `glaze.configure()` — set here or per-color.
|
|
860
|
+
* @default false
|
|
861
|
+
*/
|
|
862
|
+
pastel?: boolean;
|
|
863
|
+
/**
|
|
864
|
+
* If true, infer a color's `role` from its name when no explicit `role` is
|
|
865
|
+
* set. Falls through to the live global at resolve time when omitted.
|
|
866
|
+
*/
|
|
867
|
+
inferRole?: boolean;
|
|
868
|
+
/**
|
|
869
|
+
* Shadow tuning defaults. Only meaningful for themes; harmless on
|
|
870
|
+
* standalone color tokens.
|
|
871
|
+
*/
|
|
872
|
+
shadowTuning?: ShadowTuning;
|
|
873
|
+
/**
|
|
874
|
+
* Glow tuning defaults. Only meaningful for themes; harmless on
|
|
875
|
+
* standalone color tokens.
|
|
876
|
+
*/
|
|
877
|
+
glowTuning?: GlowTuning;
|
|
288
878
|
}
|
|
879
|
+
/**
|
|
880
|
+
* Current authoring-export schema version. Bump when the export shape
|
|
881
|
+
* changes in a non-compatible way. Written on every `.export()` snapshot.
|
|
882
|
+
*
|
|
883
|
+
* - `1` — Glaze 2.x.
|
|
884
|
+
* - `2` — Glaze 3: `shadow` `intensity` / `fg` / `tuning` changed meaning and
|
|
885
|
+
* `glow` was added. Version-1 theme snapshots that carry shadow defs or a
|
|
886
|
+
* `shadowTuning` are rejected on restore.
|
|
887
|
+
*/
|
|
888
|
+
declare const GLAZE_EXPORT_VERSION: 2;
|
|
889
|
+
/** Literal type of {@link GLAZE_EXPORT_VERSION}. */
|
|
890
|
+
type GlazeExportVersion = typeof GLAZE_EXPORT_VERSION;
|
|
891
|
+
/** Discriminator for authoring export snapshots. */
|
|
892
|
+
type GlazeExportKind = 'theme' | 'color' | 'palette';
|
|
289
893
|
/** Serialized theme configuration (no resolved values). */
|
|
290
894
|
interface GlazeThemeExport {
|
|
895
|
+
/** Snapshot kind. Always written by `theme.export()`; optional on legacy hand-written configs. */
|
|
896
|
+
kind?: 'theme';
|
|
897
|
+
/** Schema version. Always written by `theme.export()`; optional on legacy configs. */
|
|
898
|
+
version?: number;
|
|
291
899
|
hue: number;
|
|
292
900
|
saturation: number;
|
|
901
|
+
/** Dark-scheme seed hue (0–360). Omitted when the theme reuses `hue`. */
|
|
902
|
+
darkHue?: number;
|
|
903
|
+
/** Dark-scheme seed saturation (0–100). Omitted when the theme reuses `saturation`. */
|
|
904
|
+
darkSaturation?: number;
|
|
293
905
|
colors: ColorMap;
|
|
294
|
-
}
|
|
295
|
-
/** Input for `glaze.shadow()` standalone factory. */
|
|
296
|
-
interface GlazeShadowInput {
|
|
297
906
|
/**
|
|
298
|
-
*
|
|
299
|
-
* (
|
|
300
|
-
*
|
|
301
|
-
* (0–255) tuple. Alpha components are dropped with a warning.
|
|
907
|
+
* Effective config freeze from `.export()` —
|
|
908
|
+
* `getConfig() ∪ instance local ∪ exportArg`. May be sparse on legacy
|
|
909
|
+
* snapshots (omitted fields fall through to the live global at restore).
|
|
302
910
|
*/
|
|
303
|
-
|
|
911
|
+
config?: GlazeConfigOverride;
|
|
912
|
+
}
|
|
913
|
+
/** Input for the `glaze.shadow()` and `glaze.glow()` standalone factories. */
|
|
914
|
+
interface GlazeLightingInput {
|
|
304
915
|
/**
|
|
305
|
-
*
|
|
306
|
-
*
|
|
916
|
+
* The surface — accepts any `GlazeColorValue` form: hex
|
|
917
|
+
* (`#rgb` / `#rgba` / `#rrggbb` / `#rrggbbaa`), `rgb()` / `hsl()` /
|
|
918
|
+
* `okhsl()` / `okhst()` / `oklch()` strings, or literal objects
|
|
919
|
+
* (`{ r, g, b }`, `{ h, s, l }`, `{ h, s, t }`, `{ l, c, h }`). Alpha
|
|
920
|
+
* components are dropped with a warning.
|
|
307
921
|
*/
|
|
922
|
+
bg: GlazeColorValue;
|
|
923
|
+
/** The object casting the shadow / emitting the glow. Same forms as `bg`. */
|
|
308
924
|
fg?: GlazeColorValue;
|
|
309
|
-
/**
|
|
925
|
+
/** Tone step, 0–100. */
|
|
310
926
|
intensity: number;
|
|
311
|
-
tuning?:
|
|
927
|
+
tuning?: LightingTuning;
|
|
928
|
+
}
|
|
929
|
+
/** Input for `glaze.shadow()`. */
|
|
930
|
+
type GlazeShadowInput = GlazeLightingInput;
|
|
931
|
+
/** Input for `glaze.glow()`: the shared input, with glow tuning (`headroom`). */
|
|
932
|
+
interface GlazeGlowInput extends GlazeLightingInput {
|
|
933
|
+
tuning?: GlowTuning;
|
|
312
934
|
}
|
|
313
935
|
/** Input for the structured `glaze.color()` overload. */
|
|
314
936
|
interface GlazeColorInput {
|
|
315
937
|
hue: number;
|
|
316
938
|
saturation: number;
|
|
317
|
-
|
|
939
|
+
tone: HCPair<number | ExtremeValue>;
|
|
318
940
|
saturationFactor?: number;
|
|
941
|
+
/**
|
|
942
|
+
* Dark-scheme hue. Number is absolute (0–360); `'+N'`/`'-N'` is relative
|
|
943
|
+
* to the dark seed hue, which defaults to `hue`. Falls back to `hue`.
|
|
944
|
+
*/
|
|
945
|
+
darkHue?: number | RelativeValue;
|
|
946
|
+
/** Dark-scheme seed saturation (0–100). Defaults to `saturation`. */
|
|
947
|
+
darkSaturation?: number;
|
|
948
|
+
/** Dark-scheme multiplier on the dark seed (0–1). Defaults to `saturationFactor`. */
|
|
949
|
+
darkSaturationFactor?: number;
|
|
319
950
|
mode?: AdaptationMode;
|
|
951
|
+
/** Flip out-of-bounds results instead of clamping. Default: global `autoFlip`. */
|
|
952
|
+
autoFlip?: boolean;
|
|
320
953
|
/**
|
|
321
954
|
* Fixed opacity (0–1). Output includes alpha in the CSS value.
|
|
322
|
-
* Combining with `contrast` is not recommended (perceived
|
|
955
|
+
* Combining with `contrast` is not recommended (perceived tone
|
|
323
956
|
* becomes unpredictable) — a `console.warn` is emitted in that case.
|
|
324
957
|
*/
|
|
325
958
|
opacity?: number;
|
|
326
959
|
/**
|
|
327
960
|
* Optional dependency on another color. Same semantics as
|
|
328
|
-
* `GlazeColorOverrides.base` — `contrast` and relative `
|
|
961
|
+
* `GlazeColorOverrides.base` — `contrast` and relative `tone`
|
|
329
962
|
* anchor to the base per scheme.
|
|
330
963
|
*/
|
|
331
964
|
base?: GlazeColorToken | GlazeColorValue;
|
|
332
965
|
/**
|
|
333
|
-
*
|
|
966
|
+
* Contrast floor. Without `base`, solved against the token's own input
|
|
967
|
+
* color (`hue`, `saturation`, normal `tone`), held fixed in every scheme;
|
|
968
|
+
* with `base`, against the base's resolved variant per scheme. A bare
|
|
969
|
+
* number/preset is WCAG; use `{ wcag }` / `{ apca }` to pick the metric.
|
|
334
970
|
*/
|
|
335
|
-
contrast?: HCPair<
|
|
971
|
+
contrast?: HCPair<ContrastSpec>;
|
|
336
972
|
/**
|
|
337
973
|
* Optional human-readable name for the token. Used in error and
|
|
338
974
|
* warning messages (otherwise an internal name like `"value"` is
|
|
339
|
-
* used).
|
|
975
|
+
* used) and as `resolve().name`. A debug label only: it does not
|
|
976
|
+
* affect output keys or the token's `role`.
|
|
340
977
|
*/
|
|
341
978
|
name?: string;
|
|
979
|
+
/**
|
|
980
|
+
* Per-color override for the hue-independent "safe" chroma limit used in
|
|
981
|
+
* OKHSL↔sRGB conversions (luminance, contrast solving, output formatting).
|
|
982
|
+
* Falls through to the per-theme / per-token `pastel` override when omitted.
|
|
983
|
+
* @see GlazeConfigOverride.pastel
|
|
984
|
+
*/
|
|
985
|
+
pastel?: boolean;
|
|
986
|
+
/**
|
|
987
|
+
* Semantic role against the token's anchor (`base`, or its own input
|
|
988
|
+
* color when `contrast` is set without one): how this token is used.
|
|
989
|
+
* Fixes APCA contrast polarity; WCAG ignores it. Defaults to `'text'` —
|
|
990
|
+
* the token is the foreground and the anchor the background, with or
|
|
991
|
+
* without `base`. Unlike a theme color, a token never infers its role
|
|
992
|
+
* from `name`, so `inferRole` has no effect on it.
|
|
993
|
+
*/
|
|
994
|
+
role?: RoleInput;
|
|
342
995
|
}
|
|
343
996
|
/**
|
|
344
997
|
* Any single-color input form accepted by the value-shorthand
|
|
345
998
|
* overload of `glaze.color()`.
|
|
346
999
|
*
|
|
347
|
-
* Strings cover hex (`#rgb` / `#
|
|
348
|
-
*
|
|
349
|
-
* `
|
|
350
|
-
*
|
|
1000
|
+
* Strings cover hex with a leading `#` (`#rgb` / `#rgba` / `#rrggbb` /
|
|
1001
|
+
* `#rrggbbaa`) and the five color functions Glaze itself emits: `rgb()`,
|
|
1002
|
+
* `hsl()`, `okhsl()`, `okhst()`, `oklch()`, plus the `rgba()` / `hsla()`
|
|
1003
|
+
* aliases. Function names are case-insensitive; components are numbers or
|
|
1004
|
+
* percentages, separated by spaces or commas. Their scales:
|
|
1005
|
+
* - `rgb()` — channels 0–255, or percentages (`100%` is 255).
|
|
1006
|
+
* - `hsl()` / `okhsl()` / `okhst()` — saturation, lightness and tone are
|
|
1007
|
+
* percentages or bare 0–1 fractions: `hsl(120 50% 50%)` or
|
|
1008
|
+
* `hsl(120 0.5 0.5)`. Unlike CSS, a bare `hsl(120 50 50)` does not mean
|
|
1009
|
+
* 50%; it is out of range and resolves to white without a warning.
|
|
1010
|
+
* - `oklch()` — L 0–1 or a percentage; C bare, or a percentage where
|
|
1011
|
+
* `100%` is 0.4.
|
|
1012
|
+
* - Hue is in degrees, bare or with `deg`. Other angle units (`turn`,
|
|
1013
|
+
* `rad`, `grad`) are misread as degrees rather than rejected.
|
|
1014
|
+
*
|
|
1015
|
+
* An alpha component (hex alpha, `/ A`, or any fourth component) is
|
|
1016
|
+
* dropped with a warning. Named colors, other color functions, and
|
|
1017
|
+
* relative color syntax throw.
|
|
351
1018
|
*
|
|
352
|
-
*
|
|
353
|
-
*
|
|
354
|
-
*
|
|
1019
|
+
* Literal object forms, told apart by their keys:
|
|
1020
|
+
* - `{ r, g, b }` — sRGB 0–255.
|
|
1021
|
+
* - `{ l, c, h }` — OKLCh (L/C: 0–1, H: degrees), same as `oklch()` strings.
|
|
1022
|
+
* - `{ h, s, t }` — OKHST (h: 0–360, s/t: 0–1). Tone in 0–1, so `t: 0.7` is
|
|
1023
|
+
* tone 70.
|
|
1024
|
+
* - `{ h, s, l }` — OKHSL (h: 0–360, s/l: 0–1).
|
|
355
1025
|
*
|
|
356
|
-
*
|
|
357
|
-
*
|
|
1026
|
+
* An object `s`, `l`, `t` or `c` above 1.5 throws, which catches 0–100
|
|
1027
|
+
* input; the OKHSL / OKHST errors point to the structured form. String
|
|
1028
|
+
* components have no such check.
|
|
358
1029
|
*/
|
|
359
|
-
type GlazeColorValue = string | OkhslColor |
|
|
360
|
-
/**
|
|
1030
|
+
type GlazeColorValue = string | OkhslColor | OkhstColor | RgbColor | OklchColor;
|
|
1031
|
+
/** Color overrides for the `from` and value-shorthand inputs. */
|
|
361
1032
|
interface GlazeColorOverrides {
|
|
362
1033
|
/**
|
|
363
1034
|
* Override hue. Number is absolute (0–360); `'+N'`/`'-N'` is relative
|
|
@@ -368,45 +1039,75 @@ interface GlazeColorOverrides {
|
|
|
368
1039
|
/** Override seed saturation (0–100). Default: extracted from value. */
|
|
369
1040
|
saturation?: number;
|
|
370
1041
|
/**
|
|
371
|
-
*
|
|
372
|
-
*
|
|
1042
|
+
* Dark-scheme hue. Number is absolute (0–360); `'+N'`/`'-N'` is relative
|
|
1043
|
+
* to the dark seed hue, which defaults to the (possibly overridden) seed
|
|
1044
|
+
* hue. Falls back to `hue` when omitted.
|
|
1045
|
+
*/
|
|
1046
|
+
darkHue?: number | RelativeValue;
|
|
1047
|
+
/**
|
|
1048
|
+
* Dark-scheme seed saturation (0–100). Defaults to `saturation`. When set,
|
|
1049
|
+
* the global `darkDesaturation` reduction is not applied on top.
|
|
1050
|
+
*/
|
|
1051
|
+
darkSaturation?: number;
|
|
1052
|
+
/**
|
|
1053
|
+
* Dark-scheme multiplier on the dark seed (0–1). Defaults to
|
|
1054
|
+
* `saturationFactor`. When set, the global `darkDesaturation` reduction is
|
|
1055
|
+
* not applied on top.
|
|
1056
|
+
*/
|
|
1057
|
+
darkSaturationFactor?: number;
|
|
1058
|
+
/**
|
|
1059
|
+
* Override tone. Number is absolute (0–100, contrast-uniform); `'+N'`/`'-N'`
|
|
1060
|
+
* is relative to the literal seed (the value passed to `glaze.color()`);
|
|
1061
|
+
* `'max'` / `'min'` force to the scheme's tone extreme.
|
|
373
1062
|
* Supports HCPair for high-contrast.
|
|
374
1063
|
*/
|
|
375
|
-
|
|
1064
|
+
tone?: HCPair<ToneValue>;
|
|
376
1065
|
/** Saturation multiplier on the seed (0–1). Default: 1. */
|
|
377
1066
|
saturationFactor?: number;
|
|
378
1067
|
/**
|
|
379
|
-
* Adaptation mode. Defaults
|
|
380
|
-
*
|
|
381
|
-
*
|
|
382
|
-
*
|
|
383
|
-
*
|
|
384
|
-
*
|
|
1068
|
+
* Adaptation mode. Defaults to `'auto'` for every input form, so
|
|
1069
|
+
* colors automatically adapt between light and dark like an ordinary
|
|
1070
|
+
* theme color. Value-shorthand inputs (strings and literal objects)
|
|
1071
|
+
* preserve light tone via a local `lightTone: false` default; other
|
|
1072
|
+
* omitted config fields fall through to the live global at resolve
|
|
1073
|
+
* time. Structured `{ hue, saturation, tone }` form also falls
|
|
1074
|
+
* through for both tone windows unless overridden.
|
|
385
1075
|
*
|
|
386
|
-
* Pass `'fixed'` explicitly to opt
|
|
387
|
-
*
|
|
388
|
-
*
|
|
1076
|
+
* Pass `'fixed'` explicitly to opt back into the linear, non-
|
|
1077
|
+
* inverting mapping; pass `'static'` to pin the same tone
|
|
1078
|
+
* across every variant.
|
|
389
1079
|
*/
|
|
390
1080
|
mode?: AdaptationMode;
|
|
391
1081
|
/**
|
|
392
|
-
*
|
|
1082
|
+
* Flip out-of-bounds results (relative `tone` overshoot / unmet
|
|
1083
|
+
* `contrast`) to the opposite side instead of clamping. Defaults to
|
|
1084
|
+
* the global `autoFlip`.
|
|
1085
|
+
*/
|
|
1086
|
+
autoFlip?: boolean;
|
|
1087
|
+
/**
|
|
1088
|
+
* Contrast floor. By default solved against the literal seed
|
|
393
1089
|
* (the value itself); when `base` is set, solved against the base's
|
|
394
|
-
* resolved variant per scheme. Same shape as `RegularColorDef.contrast
|
|
1090
|
+
* resolved variant per scheme. Same shape as `RegularColorDef.contrast`
|
|
1091
|
+
* (bare number/preset = WCAG; `{ wcag }` / `{ apca }` to pick the metric).
|
|
395
1092
|
*/
|
|
396
|
-
contrast?: HCPair<
|
|
1093
|
+
contrast?: HCPair<ContrastSpec>;
|
|
397
1094
|
/**
|
|
398
1095
|
* Optional dependency on another color. Accepts either a
|
|
399
1096
|
* `GlazeColorToken` (returned by another `glaze.color()`) or a raw
|
|
400
|
-
* `GlazeColorValue` (hex /
|
|
1097
|
+
* `GlazeColorValue` (hex / CSS strings / `{ r, g, b }` / `{ h, s, l }` / …),
|
|
401
1098
|
* which is automatically wrapped in `glaze.color(value)`.
|
|
402
1099
|
*
|
|
403
1100
|
* When set:
|
|
404
1101
|
* - `contrast` is solved against the base's resolved variant
|
|
405
1102
|
* per-scheme (light / dark / lightContrast / darkContrast).
|
|
406
|
-
* - Relative `
|
|
407
|
-
*
|
|
1103
|
+
* - Relative `tone: '+N'` / `'-N'` is anchored to the base's
|
|
1104
|
+
* tone per-scheme (matches theme behavior for dependent colors).
|
|
408
1105
|
* - Relative `hue: '+N'` / `'-N'` still anchors to the seed (the
|
|
409
1106
|
* value passed to `glaze.color()`), not the base.
|
|
1107
|
+
* - The link resolves against the base token's own variants in every
|
|
1108
|
+
* scheme: what the base paints, under its own config, whatever form
|
|
1109
|
+
* the base was made in. A light `'+0'` lands on the base and a light
|
|
1110
|
+
* `contrast` floor is measured against it.
|
|
410
1111
|
*
|
|
411
1112
|
* The base token's `.resolve()` is called lazily on first resolve and
|
|
412
1113
|
* its result is captured by reference; later mutations to the base's
|
|
@@ -415,52 +1116,46 @@ interface GlazeColorOverrides {
|
|
|
415
1116
|
base?: GlazeColorToken | GlazeColorValue;
|
|
416
1117
|
/**
|
|
417
1118
|
* Fixed opacity (0–1). Output includes alpha in the CSS value.
|
|
418
|
-
* Combining with `contrast` is not recommended (perceived
|
|
1119
|
+
* Combining with `contrast` is not recommended (perceived tone
|
|
419
1120
|
* becomes unpredictable) — a `console.warn` is emitted in that case.
|
|
420
1121
|
*/
|
|
421
1122
|
opacity?: number;
|
|
422
1123
|
/**
|
|
423
1124
|
* Optional human-readable name for the token. Used in error and
|
|
424
1125
|
* warning messages (otherwise an internal name like `"value"` is
|
|
425
|
-
* used).
|
|
1126
|
+
* used) and as `resolve().name`. A debug label only: it does not
|
|
1127
|
+
* affect output keys or the token's `role`.
|
|
426
1128
|
*/
|
|
427
1129
|
name?: string;
|
|
1130
|
+
/**
|
|
1131
|
+
* Per-color override for the hue-independent "safe" chroma limit used in
|
|
1132
|
+
* OKHSL↔sRGB conversions (luminance, contrast solving, output formatting).
|
|
1133
|
+
* Falls through to the per-theme / per-token `pastel` override when omitted.
|
|
1134
|
+
* @see GlazeConfigOverride.pastel
|
|
1135
|
+
*/
|
|
1136
|
+
pastel?: boolean;
|
|
1137
|
+
/**
|
|
1138
|
+
* Semantic role against the token's anchor (`base`, or the literal seed
|
|
1139
|
+
* when `contrast` / a relative `tone` is set without one): how this token
|
|
1140
|
+
* is used. Fixes APCA contrast polarity; WCAG ignores it. Defaults to
|
|
1141
|
+
* `'text'` — the token is the foreground and the anchor the background,
|
|
1142
|
+
* with or without `base`. Unlike a theme color, a token never infers its
|
|
1143
|
+
* role from `name`, so `inferRole` has no effect on it.
|
|
1144
|
+
*/
|
|
1145
|
+
role?: RoleInput;
|
|
428
1146
|
}
|
|
429
1147
|
/**
|
|
430
|
-
*
|
|
431
|
-
*
|
|
1148
|
+
* Object input for `glaze.color()` that carries a raw color value plus
|
|
1149
|
+
* optional color overrides in the same object.
|
|
432
1150
|
*
|
|
433
|
-
*
|
|
434
|
-
*
|
|
435
|
-
*
|
|
436
|
-
*
|
|
437
|
-
*
|
|
438
|
-
* - **String inputs** (`'#1a1a1a'`, `'rgb(...)'`, `'okhsl(...)'`, ...):
|
|
439
|
-
* - `lightLightness: false` — preserve input exactly.
|
|
440
|
-
* - `darkLightness: [globalConfig.darkLightness[0], 100]` — extended
|
|
441
|
-
* dark window so the auto-mode dark variant can Möbius-invert all
|
|
442
|
-
* the way up to white.
|
|
443
|
-
*
|
|
444
|
-
* - **`OkhslColor` / `[r, g, b]` tuple / structured inputs**:
|
|
445
|
-
* - `lightLightness: false` — preserve input exactly.
|
|
446
|
-
* - `darkLightness: globalConfig.darkLightness` — same window
|
|
447
|
-
* theme colors use, snapshotted at create time.
|
|
448
|
-
*
|
|
449
|
-
* Passing this object replaces both fields at once. To keep one
|
|
450
|
-
* field's default while overriding the other, restate the default
|
|
451
|
-
* explicitly.
|
|
1151
|
+
* ```ts
|
|
1152
|
+
* glaze.color({ from: '#1a1a2e', base: bg, contrast: 'AA' })
|
|
1153
|
+
* glaze.color({ from: { r: 38, g: 252, b: 178 }, tone: '+10' })
|
|
1154
|
+
* ```
|
|
452
1155
|
*/
|
|
453
|
-
interface
|
|
454
|
-
/**
|
|
455
|
-
|
|
456
|
-
/**
|
|
457
|
-
* Dark-mode lightness window. Snapshotted from `globalConfig` at
|
|
458
|
-
* create time: extended `[globalConfig.darkLightness[0], 100]` for
|
|
459
|
-
* string inputs, plain `globalConfig.darkLightness` for object /
|
|
460
|
-
* tuple / structured inputs. Pass `false` to preserve input
|
|
461
|
-
* lightness in dark mode too.
|
|
462
|
-
*/
|
|
463
|
-
darkLightness?: false | [number, number];
|
|
1156
|
+
interface GlazeFromInput extends GlazeColorOverrides {
|
|
1157
|
+
/** The source color value. Accepts the same forms as a bare `GlazeColorValue`. */
|
|
1158
|
+
from: GlazeColorValue;
|
|
464
1159
|
}
|
|
465
1160
|
/** Options for `GlazeColorToken.css()`. */
|
|
466
1161
|
interface GlazeColorCssOptions {
|
|
@@ -470,13 +1165,19 @@ interface GlazeColorCssOptions {
|
|
|
470
1165
|
* `name: 'brand'` → `--brand-color: …`.
|
|
471
1166
|
*/
|
|
472
1167
|
name: string;
|
|
473
|
-
/** Output color format. Default: '
|
|
1168
|
+
/** Output color format. Default: 'oklch'. */
|
|
474
1169
|
format?: GlazeColorFormat;
|
|
475
1170
|
/**
|
|
476
1171
|
* Suffix appended to the name. Default: '-color' (matches
|
|
477
1172
|
* `theme.css` default).
|
|
478
1173
|
*/
|
|
479
1174
|
suffix?: string;
|
|
1175
|
+
/**
|
|
1176
|
+
* Emit hue as a separate `--{name}-hue` custom property, referenced via
|
|
1177
|
+
* `var()`. Requires `format: 'oklch'` (any other format throws) and a
|
|
1178
|
+
* pastel token.
|
|
1179
|
+
*/
|
|
1180
|
+
splitHue?: boolean;
|
|
480
1181
|
}
|
|
481
1182
|
/** Return type for `glaze.color()`. */
|
|
482
1183
|
interface GlazeColorToken {
|
|
@@ -486,7 +1187,7 @@ interface GlazeColorToken {
|
|
|
486
1187
|
token(options?: GlazeTokenOptions): Record<string, string>;
|
|
487
1188
|
/**
|
|
488
1189
|
* Export as a tasty style-to-state binding (no color name key).
|
|
489
|
-
* Uses `#name` keys and state aliases (`''`,
|
|
1190
|
+
* Uses `#name` keys and state aliases (`''`, `'@media(prefers-color-scheme: dark)'`, etc.).
|
|
490
1191
|
* @see https://tasty.style/docs
|
|
491
1192
|
*/
|
|
492
1193
|
tasty(options?: GlazeTokenOptions): Record<string, string>;
|
|
@@ -494,22 +1195,46 @@ interface GlazeColorToken {
|
|
|
494
1195
|
json(options?: GlazeJsonOptions): Record<string, string>;
|
|
495
1196
|
/** Export as CSS custom property declarations grouped by scheme variant. */
|
|
496
1197
|
css(options: GlazeColorCssOptions): GlazeCssResult;
|
|
1198
|
+
/**
|
|
1199
|
+
* Export as W3C DTCG color tokens (one per scheme variant, no color name
|
|
1200
|
+
* key). Each entry is a full `{ $type: 'color', $value }` token.
|
|
1201
|
+
* @see https://www.designtokens.org/
|
|
1202
|
+
*/
|
|
1203
|
+
dtcg(options?: GlazeDtcgOptions): GlazeColorDtcgResult;
|
|
1204
|
+
/**
|
|
1205
|
+
* Export as a single W3C DTCG Resolver-Module document for this color,
|
|
1206
|
+
* keyed by `name` across all scheme variants. `name` is required.
|
|
1207
|
+
* @see https://www.designtokens.org/
|
|
1208
|
+
*/
|
|
1209
|
+
dtcgResolver(options: GlazeColorDtcgResolverOptions): GlazeDtcgResolverDocument;
|
|
1210
|
+
/**
|
|
1211
|
+
* Export as a Tailwind CSS v4 `@theme` block (light baseline) plus dark /
|
|
1212
|
+
* high-contrast overrides. Returns a single ready-to-paste CSS string.
|
|
1213
|
+
* `name` is required (forms `--color-<name>`).
|
|
1214
|
+
* @see https://tailwindcss.com/docs/theme
|
|
1215
|
+
*/
|
|
1216
|
+
tailwind(options: GlazeColorTailwindOptions): string;
|
|
497
1217
|
/**
|
|
498
1218
|
* Serialize the token as a JSON-safe object. Captures the original
|
|
499
|
-
* input value, overrides, and
|
|
1219
|
+
* input value, overrides, and config so it can be rehydrated via
|
|
500
1220
|
* `glaze.colorFrom(...)`. `base` is recursively serialized.
|
|
1221
|
+
* Optional `override` is merged over the instance local at export time.
|
|
501
1222
|
*/
|
|
502
|
-
export(): GlazeColorTokenExport;
|
|
1223
|
+
export(override?: GlazeConfigOverride): GlazeColorTokenExport;
|
|
503
1224
|
}
|
|
504
1225
|
/**
|
|
505
1226
|
* JSON-safe serialization of a `glaze.color()` token. Pass to
|
|
506
1227
|
* `glaze.colorFrom(...)` to rehydrate.
|
|
507
1228
|
*/
|
|
508
1229
|
interface GlazeColorTokenExport {
|
|
1230
|
+
/** Snapshot kind. Always written by `token.export()`; optional on legacy snapshots. */
|
|
1231
|
+
kind?: 'color';
|
|
1232
|
+
/** Schema version. Always written by `token.export()`; optional on legacy snapshots. */
|
|
1233
|
+
version?: number;
|
|
509
1234
|
/**
|
|
510
1235
|
* Discriminator for the source overload that created the token.
|
|
511
|
-
* - `'value'`: created via `glaze.color(value, overrides
|
|
512
|
-
* - `'structured'`: created via `glaze.color({ hue, saturation, ... }
|
|
1236
|
+
* - `'value'`: created via `glaze.color(value)` or `glaze.color({ from, ...overrides })`.
|
|
1237
|
+
* - `'structured'`: created via `glaze.color({ hue, saturation, ... })`.
|
|
513
1238
|
*/
|
|
514
1239
|
form: 'value' | 'structured';
|
|
515
1240
|
/** Original input. For `form: 'value'` this is the raw `GlazeColorValue`; for `form: 'structured'` this is the structured input. */
|
|
@@ -519,8 +1244,26 @@ interface GlazeColorTokenExport {
|
|
|
519
1244
|
* serialized. Only present for `form: 'value'`.
|
|
520
1245
|
*/
|
|
521
1246
|
overrides?: GlazeColorOverridesExport;
|
|
522
|
-
/**
|
|
523
|
-
|
|
1247
|
+
/**
|
|
1248
|
+
* Effective config freeze from `.export()` — `getConfig() ∪ local ∪
|
|
1249
|
+
* exportArg` at call time. Used by `glaze.colorFrom()` to pin
|
|
1250
|
+
* deterministic behavior across later `configure()` calls.
|
|
1251
|
+
*/
|
|
1252
|
+
config?: GlazeConfigOverride;
|
|
1253
|
+
}
|
|
1254
|
+
/**
|
|
1255
|
+
* JSON-safe serialization of a `glaze.palette()` composition.
|
|
1256
|
+
* Pass to `glaze.paletteFrom(...)` to rehydrate.
|
|
1257
|
+
*/
|
|
1258
|
+
interface GlazePaletteExport {
|
|
1259
|
+
/** Snapshot kind. Always written by `palette.export()`. */
|
|
1260
|
+
kind?: 'palette';
|
|
1261
|
+
/** Schema version. Always written by `palette.export()`. */
|
|
1262
|
+
version?: number;
|
|
1263
|
+
/** Per-theme authoring snapshots keyed by theme name. */
|
|
1264
|
+
themes: Record<string, GlazeThemeExport>;
|
|
1265
|
+
/** Primary theme name, if set on the palette. */
|
|
1266
|
+
primary?: string;
|
|
524
1267
|
}
|
|
525
1268
|
/**
|
|
526
1269
|
* Serializable shape of a structured `glaze.color({...})` input.
|
|
@@ -530,13 +1273,19 @@ interface GlazeColorTokenExport {
|
|
|
530
1273
|
interface GlazeColorInputExport {
|
|
531
1274
|
hue: number;
|
|
532
1275
|
saturation: number;
|
|
533
|
-
|
|
1276
|
+
tone: HCPair<number | ExtremeValue>;
|
|
534
1277
|
saturationFactor?: number;
|
|
1278
|
+
darkHue?: number | RelativeValue;
|
|
1279
|
+
darkSaturation?: number;
|
|
1280
|
+
darkSaturationFactor?: number;
|
|
535
1281
|
mode?: AdaptationMode;
|
|
1282
|
+
autoFlip?: boolean;
|
|
536
1283
|
opacity?: number;
|
|
537
1284
|
base?: GlazeColorTokenExport | GlazeColorValue;
|
|
538
|
-
contrast?: HCPair<
|
|
1285
|
+
contrast?: HCPair<ContrastSpec>;
|
|
539
1286
|
name?: string;
|
|
1287
|
+
pastel?: boolean;
|
|
1288
|
+
role?: RoleInput;
|
|
540
1289
|
}
|
|
541
1290
|
/**
|
|
542
1291
|
* Serializable shape of `GlazeColorOverrides`. `base` is replaced by
|
|
@@ -545,19 +1294,49 @@ interface GlazeColorInputExport {
|
|
|
545
1294
|
interface GlazeColorOverridesExport {
|
|
546
1295
|
hue?: number | RelativeValue;
|
|
547
1296
|
saturation?: number;
|
|
548
|
-
|
|
1297
|
+
darkHue?: number | RelativeValue;
|
|
1298
|
+
darkSaturation?: number;
|
|
1299
|
+
darkSaturationFactor?: number;
|
|
1300
|
+
tone?: HCPair<ToneValue>;
|
|
549
1301
|
saturationFactor?: number;
|
|
550
1302
|
mode?: AdaptationMode;
|
|
551
|
-
|
|
1303
|
+
autoFlip?: boolean;
|
|
1304
|
+
contrast?: HCPair<ContrastSpec>;
|
|
552
1305
|
base?: GlazeColorTokenExport | GlazeColorValue;
|
|
553
1306
|
opacity?: number;
|
|
554
1307
|
name?: string;
|
|
1308
|
+
pastel?: boolean;
|
|
1309
|
+
role?: RoleInput;
|
|
1310
|
+
}
|
|
1311
|
+
/**
|
|
1312
|
+
* The hue/saturation seed pair a theme resolves against.
|
|
1313
|
+
*
|
|
1314
|
+
* `darkHue` / `darkSaturation` are a separate seed for the `dark` and
|
|
1315
|
+
* `darkContrast` variants; each falls back to its light counterpart. Setting
|
|
1316
|
+
* `darkSaturation` opts the theme out of the global `darkDesaturation`
|
|
1317
|
+
* reduction — the authored value is used literally.
|
|
1318
|
+
*/
|
|
1319
|
+
interface GlazeThemeSeed {
|
|
1320
|
+
/** Light-scheme hue seed (0–360). */
|
|
1321
|
+
hue: number;
|
|
1322
|
+
/** Light-scheme saturation seed (0–100). */
|
|
1323
|
+
saturation: number;
|
|
1324
|
+
/** Dark-scheme hue seed (0–360). Defaults to `hue`. */
|
|
1325
|
+
darkHue?: number;
|
|
1326
|
+
/** Dark-scheme saturation seed (0–100). Defaults to `saturation`. */
|
|
1327
|
+
darkSaturation?: number;
|
|
555
1328
|
}
|
|
556
1329
|
interface GlazeTheme {
|
|
557
1330
|
/** The hue seed (0–360). */
|
|
558
1331
|
readonly hue: number;
|
|
559
1332
|
/** The saturation seed (0–100). */
|
|
560
1333
|
readonly saturation: number;
|
|
1334
|
+
/** The dark-scheme hue seed (0–360), or `undefined` when `hue` is reused. */
|
|
1335
|
+
readonly darkHue: number | undefined;
|
|
1336
|
+
/** The dark-scheme saturation seed (0–100), or `undefined` when `saturation` is reused. */
|
|
1337
|
+
readonly darkSaturation: number | undefined;
|
|
1338
|
+
/** The effective config for this theme. */
|
|
1339
|
+
getConfig(): GlazeConfigResolved;
|
|
561
1340
|
/** Add/replace colors (additive merge with existing definitions). */
|
|
562
1341
|
colors(defs: ColorMap): void;
|
|
563
1342
|
/** Get a color definition by name. */
|
|
@@ -573,7 +1352,7 @@ interface GlazeTheme {
|
|
|
573
1352
|
/** Clear all color definitions. */
|
|
574
1353
|
reset(): void;
|
|
575
1354
|
/** Export the theme configuration as a JSON-safe object. */
|
|
576
|
-
export(): GlazeThemeExport;
|
|
1355
|
+
export(override?: GlazeConfigOverride): GlazeThemeExport;
|
|
577
1356
|
/** Create a child theme inheriting all color definitions. */
|
|
578
1357
|
extend(options: GlazeExtendOptions): GlazeTheme;
|
|
579
1358
|
/** Resolve all colors and return the result map. */
|
|
@@ -585,57 +1364,368 @@ interface GlazeTheme {
|
|
|
585
1364
|
* theme.tokens()
|
|
586
1365
|
* // → { light: { surface: 'okhsl(...)' }, dark: { surface: 'okhsl(...)' } }
|
|
587
1366
|
* ```
|
|
1367
|
+
*
|
|
1368
|
+
* With `modes.hdr`, each scheme map is followed by a dense `<scheme>Hdr`
|
|
1369
|
+
* map (`lightHdr`, `darkHdr`, …): every glow with an HDR value in any
|
|
1370
|
+
* emitted scheme, as `color(srgb-linear …)`, or its SDR value where that
|
|
1371
|
+
* scheme has none.
|
|
588
1372
|
*/
|
|
589
1373
|
tokens(options?: GlazeJsonOptions): Record<string, Record<string, string>>;
|
|
590
1374
|
/**
|
|
591
1375
|
* Export as tasty style-to-state bindings.
|
|
592
|
-
* Uses `#name` color token keys and state aliases (`''`,
|
|
1376
|
+
* Uses `#name` color token keys and state aliases (`''`, `'@media(prefers-color-scheme: dark)'`, etc.).
|
|
593
1377
|
* Spread into component styles or register as a recipe via `configure({ recipes })`.
|
|
1378
|
+
* With `modes.hdr`, a glow's HDR value follows each SDR key that has one,
|
|
1379
|
+
* under `states.hdr` (`'@media(dynamic-range: high)'`) combined with it.
|
|
594
1380
|
* @see https://tasty.style/docs
|
|
595
1381
|
*/
|
|
596
|
-
tasty(options?:
|
|
597
|
-
/**
|
|
1382
|
+
tasty(options?: GlazeTastyOptions): Record<string, Record<string, string>>;
|
|
1383
|
+
/**
|
|
1384
|
+
* Export as plain JSON. With `modes.hdr`, a glow variant with an HDR value
|
|
1385
|
+
* adds a `<scheme>Hdr` key (`lightHdr`, …) right after its SDR key.
|
|
1386
|
+
*/
|
|
598
1387
|
json(options?: GlazeJsonOptions): Record<string, Record<string, string>>;
|
|
599
1388
|
/** Export as CSS custom property declarations. */
|
|
600
1389
|
css(options?: GlazeCssOptions): GlazeCssResult;
|
|
1390
|
+
/**
|
|
1391
|
+
* Export as W3C Design Tokens Format Module (2025.10) documents, one per
|
|
1392
|
+
* scheme variant. Consumable by Figma, Tokens Studio, Style Dictionary,
|
|
1393
|
+
* Terrazzo, and any DTCG-compatible tool.
|
|
1394
|
+
* @see https://www.designtokens.org/
|
|
1395
|
+
*/
|
|
1396
|
+
dtcg(options?: GlazeDtcgOptions): GlazeDtcgResult;
|
|
1397
|
+
/**
|
|
1398
|
+
* Export as a single W3C DTCG Resolver-Module document describing every
|
|
1399
|
+
* scheme variant as one `sets` entry plus a single `scheme` modifier with a
|
|
1400
|
+
* context per variant. Consumable by resolver tools such as Dispersa.
|
|
1401
|
+
* @see https://www.designtokens.org/
|
|
1402
|
+
*/
|
|
1403
|
+
dtcgResolver(options?: GlazeDtcgResolverOptions): GlazeDtcgResolverDocument;
|
|
1404
|
+
/**
|
|
1405
|
+
* Export as a Tailwind CSS v4 `@theme` block (light baseline) plus dark /
|
|
1406
|
+
* high-contrast overrides under configurable selectors. Returns a single
|
|
1407
|
+
* ready-to-paste CSS string.
|
|
1408
|
+
* @see https://tailwindcss.com/docs/theme
|
|
1409
|
+
*/
|
|
1410
|
+
tailwind(options?: GlazeTailwindOptions): string;
|
|
601
1411
|
}
|
|
602
1412
|
interface GlazeExtendOptions {
|
|
603
1413
|
hue?: number;
|
|
604
1414
|
saturation?: number;
|
|
1415
|
+
/** Replace the dark-scheme hue seed (0–360). Defaults to the parent's. */
|
|
1416
|
+
darkHue?: number;
|
|
1417
|
+
/** Replace the dark-scheme saturation seed (0–100). Defaults to the parent's. */
|
|
1418
|
+
darkSaturation?: number;
|
|
605
1419
|
colors?: ColorMap;
|
|
1420
|
+
/** Config override for the child theme. Merged with the parent's override. */
|
|
1421
|
+
config?: GlazeConfigOverride;
|
|
606
1422
|
}
|
|
1423
|
+
/**
|
|
1424
|
+
* Options for `token.token()` / `token.tasty()`, and the base of the theme and
|
|
1425
|
+
* palette `tasty()` options: output format, scheme variants, state aliases.
|
|
1426
|
+
*/
|
|
607
1427
|
interface GlazeTokenOptions {
|
|
608
|
-
/**
|
|
609
|
-
|
|
610
|
-
|
|
1428
|
+
/**
|
|
1429
|
+
* Override state aliases for this export. `hdr` keys an HDR glow value
|
|
1430
|
+
* (with `modes.hdr`); a `glaze.color()` token is never a glow, so it never
|
|
1431
|
+
* uses it.
|
|
1432
|
+
*/
|
|
611
1433
|
states?: {
|
|
612
1434
|
dark?: string;
|
|
613
1435
|
highContrast?: string;
|
|
1436
|
+
hdr?: string;
|
|
614
1437
|
};
|
|
615
1438
|
/** Override which scheme variants to include. */
|
|
616
1439
|
modes?: GlazeOutputModes;
|
|
617
|
-
/** Output color format. Default: '
|
|
1440
|
+
/** Output color format. Default: 'oklch'. */
|
|
618
1441
|
format?: GlazeColorFormat;
|
|
619
1442
|
}
|
|
1443
|
+
/** Options for `theme.tasty()`. */
|
|
1444
|
+
interface GlazeTastyOptions extends GlazeTokenOptions {
|
|
1445
|
+
/**
|
|
1446
|
+
* Emit hue as a separate custom property, referenced via `var()`.
|
|
1447
|
+
* Requires `format: 'oklch'` (any other format throws) and every color to
|
|
1448
|
+
* be pastel.
|
|
1449
|
+
*/
|
|
1450
|
+
splitHue?: boolean;
|
|
1451
|
+
/**
|
|
1452
|
+
* Base name for the theme-level hue var (`--{name}-hue`). Default: `'theme'`.
|
|
1453
|
+
* Must not equal the name of a color that sets its own hue (throws).
|
|
1454
|
+
*/
|
|
1455
|
+
name?: string;
|
|
1456
|
+
}
|
|
1457
|
+
/** Options for `theme.tokens()` / `theme.json()` and their palette and token counterparts. */
|
|
620
1458
|
interface GlazeJsonOptions {
|
|
621
1459
|
/** Override which scheme variants to include. */
|
|
622
1460
|
modes?: GlazeOutputModes;
|
|
623
|
-
/** Output color format. Default: '
|
|
1461
|
+
/** Output color format. Default: 'oklch'. */
|
|
624
1462
|
format?: GlazeColorFormat;
|
|
625
1463
|
}
|
|
1464
|
+
/** Options for `theme.css()`. */
|
|
626
1465
|
interface GlazeCssOptions {
|
|
627
|
-
/** Output color format. Default: '
|
|
1466
|
+
/** Output color format. Default: 'oklch'. */
|
|
628
1467
|
format?: GlazeColorFormat;
|
|
629
1468
|
/** Suffix appended to each CSS custom property name. Default: '-color'. */
|
|
630
1469
|
suffix?: string;
|
|
1470
|
+
/**
|
|
1471
|
+
* Emit hue as a separate custom property, referenced via `var()`.
|
|
1472
|
+
* Requires `format: 'oklch'` (any other format throws) and every color to
|
|
1473
|
+
* be pastel.
|
|
1474
|
+
*/
|
|
1475
|
+
splitHue?: boolean;
|
|
1476
|
+
/**
|
|
1477
|
+
* Base name for the theme-level hue var (`--{name}-hue`). Default: `'theme'`.
|
|
1478
|
+
* Must not equal the name of a color that sets its own hue (throws).
|
|
1479
|
+
*/
|
|
1480
|
+
name?: string;
|
|
1481
|
+
/**
|
|
1482
|
+
* Add the HDR tier as `result.hdr` (see {@link GlazeCssResult.hdr}).
|
|
1483
|
+
* Default: the global `modes.hdr` (false). `css()` has no `modes` — it
|
|
1484
|
+
* always emits all four schemes — so this is its HDR switch.
|
|
1485
|
+
*/
|
|
1486
|
+
hdr?: boolean;
|
|
631
1487
|
}
|
|
632
|
-
/** CSS custom property declarations
|
|
633
|
-
interface
|
|
1488
|
+
/** CSS custom property declarations for each scheme variant. */
|
|
1489
|
+
interface GlazeCssSchemeBlocks {
|
|
634
1490
|
light: string;
|
|
635
1491
|
dark: string;
|
|
636
1492
|
lightContrast: string;
|
|
637
1493
|
darkContrast: string;
|
|
638
1494
|
}
|
|
1495
|
+
/** CSS custom property declarations grouped by scheme variant. */
|
|
1496
|
+
interface GlazeCssResult extends GlazeCssSchemeBlocks {
|
|
1497
|
+
/**
|
|
1498
|
+
* The HDR tier, present when HDR output is on — the `hdr` option, which
|
|
1499
|
+
* defaults to the global `modes.hdr`: one block per scheme,
|
|
1500
|
+
* each re-declaring every color that has an HDR value in any scheme — its
|
|
1501
|
+
* HDR value (`color(srgb-linear R G B)`) where that scheme has one, and
|
|
1502
|
+
* the scheme's SDR declaration where it has none. The blocks are dense so
|
|
1503
|
+
* a light HDR value can never leak into dark: wire each one after the SDR
|
|
1504
|
+
* blocks, under the same selector plus `(dynamic-range: high)`. Every block
|
|
1505
|
+
* is an empty string when no color has an HDR value.
|
|
1506
|
+
*/
|
|
1507
|
+
hdr?: GlazeCssSchemeBlocks;
|
|
1508
|
+
}
|
|
1509
|
+
/**
|
|
1510
|
+
* Color space used for DTCG `$value` color objects.
|
|
1511
|
+
* @see https://www.designtokens.org/
|
|
1512
|
+
*/
|
|
1513
|
+
type DtcgColorSpace = 'srgb' | 'oklch';
|
|
1514
|
+
/**
|
|
1515
|
+
* A DTCG color `$value` in the sRGB color space: gamma sRGB components in
|
|
1516
|
+
* 0–1 plus a 6-digit `hex` hint. Universally understood by Figma, Tokens
|
|
1517
|
+
* Studio, Style Dictionary, and every DTCG reader.
|
|
1518
|
+
*/
|
|
1519
|
+
interface DtcgSrgbColorValue {
|
|
1520
|
+
colorSpace: 'srgb';
|
|
1521
|
+
components: [number, number, number];
|
|
1522
|
+
hex: HexColor;
|
|
1523
|
+
/** Opacity 0–1. Omitted when fully opaque (alpha = 1). */
|
|
1524
|
+
alpha?: number;
|
|
1525
|
+
}
|
|
1526
|
+
/**
|
|
1527
|
+
* A DTCG color `$value` in the OKLCH color space: `[L, C, H]` components
|
|
1528
|
+
* (L/C: 0–1, H: degrees). Wide-gamut and Glaze-native; no `hex` is emitted.
|
|
1529
|
+
*/
|
|
1530
|
+
interface DtcgOklchColorValue {
|
|
1531
|
+
colorSpace: 'oklch';
|
|
1532
|
+
components: [number, number, number];
|
|
1533
|
+
/** Opacity 0–1. Omitted when fully opaque (alpha = 1). */
|
|
1534
|
+
alpha?: number;
|
|
1535
|
+
}
|
|
1536
|
+
/** A DTCG `$value` for a color token, in either supported color space. */
|
|
1537
|
+
type DtcgColorValue = DtcgSrgbColorValue | DtcgOklchColorValue;
|
|
1538
|
+
/**
|
|
1539
|
+
* The HDR value of a glow past SDR white, carried in a DTCG token's
|
|
1540
|
+
* `$extensions['me.tenphi.glaze'].hdr` (`$value` stays the SDR color, since
|
|
1541
|
+
* DTCG color components stop at 1). Maps onto native APIs: UIKit / AppKit
|
|
1542
|
+
* `exposure`, SwiftUI `exposureAdjust(exposure)` on `base`, or Android
|
|
1543
|
+
* `Color.pack(…components, LINEAR_EXTENDED_SRGB)` from `value`.
|
|
1544
|
+
*/
|
|
1545
|
+
interface GlazeDtcgHdr {
|
|
1546
|
+
/** Gain over `base` in stops (`log2` of the linear factor), above 0. */
|
|
1547
|
+
exposure: number;
|
|
1548
|
+
/**
|
|
1549
|
+
* Luminance tone of the HDR value (e.g. `112`) — past 100 when the headroom
|
|
1550
|
+
* covers the step; a saturated base capped by `headroom` can land below 100,
|
|
1551
|
+
* though its brightest channel still exceeds 1.
|
|
1552
|
+
*/
|
|
1553
|
+
tone: number;
|
|
1554
|
+
/** The opaque base (what SDR paints), as a DTCG sRGB color. */
|
|
1555
|
+
base: DtcgSrgbColorValue;
|
|
1556
|
+
/**
|
|
1557
|
+
* The HDR color: linear sRGB `base × 2^exposure`, its brightest channel
|
|
1558
|
+
* above 1 (the others may stay below).
|
|
1559
|
+
*/
|
|
1560
|
+
value: {
|
|
1561
|
+
colorSpace: 'srgb-linear';
|
|
1562
|
+
components: [number, number, number];
|
|
1563
|
+
};
|
|
1564
|
+
}
|
|
1565
|
+
/** The Glaze namespace of a DTCG token's `$extensions`. */
|
|
1566
|
+
interface GlazeDtcgExtensions {
|
|
1567
|
+
'me.tenphi.glaze': {
|
|
1568
|
+
/** Present only with `modes.hdr`, on a glow variant that has an HDR value. */hdr: GlazeDtcgHdr;
|
|
1569
|
+
};
|
|
1570
|
+
}
|
|
1571
|
+
/**
|
|
1572
|
+
* A single W3C DTCG color token: `{ $type: 'color', $value }`.
|
|
1573
|
+
* `$description` is optional and not populated by Glaze today. `$extensions`
|
|
1574
|
+
* is set only with `modes.hdr`, on a glow variant with an HDR value.
|
|
1575
|
+
*/
|
|
1576
|
+
interface DtcgColorToken {
|
|
1577
|
+
$type: 'color';
|
|
1578
|
+
$value: DtcgColorValue;
|
|
1579
|
+
$description?: string;
|
|
1580
|
+
$extensions?: GlazeDtcgExtensions;
|
|
1581
|
+
}
|
|
1582
|
+
/**
|
|
1583
|
+
* A W3C Design Tokens Format Module (2025.10) token tree for one scheme.
|
|
1584
|
+
* Glaze emits one document per scheme variant — the most tool-compatible
|
|
1585
|
+
* convention (one file per Style Dictionary theme / Tokens Studio set /
|
|
1586
|
+
* Figma variable mode).
|
|
1587
|
+
*/
|
|
1588
|
+
type DtcgDocument = Record<string, DtcgColorToken>;
|
|
1589
|
+
/** DTCG token documents grouped by scheme variant. Light is always present. */
|
|
1590
|
+
interface GlazeDtcgResult {
|
|
1591
|
+
light: DtcgDocument;
|
|
1592
|
+
dark?: DtcgDocument;
|
|
1593
|
+
lightContrast?: DtcgDocument;
|
|
1594
|
+
darkContrast?: DtcgDocument;
|
|
1595
|
+
}
|
|
1596
|
+
/** A single DTCG color token grouped by scheme variant (standalone tokens). */
|
|
1597
|
+
interface GlazeColorDtcgResult {
|
|
1598
|
+
light: DtcgColorToken;
|
|
1599
|
+
dark?: DtcgColorToken;
|
|
1600
|
+
lightContrast?: DtcgColorToken;
|
|
1601
|
+
darkContrast?: DtcgColorToken;
|
|
1602
|
+
}
|
|
1603
|
+
/** Options for `theme.dtcg()` / `palette.dtcg()`. */
|
|
1604
|
+
interface GlazeDtcgOptions {
|
|
1605
|
+
/** Override which scheme variants to include. */
|
|
1606
|
+
modes?: GlazeOutputModes;
|
|
1607
|
+
/**
|
|
1608
|
+
* DTCG color space. `'srgb'` (default) emits sRGB components plus a `hex`
|
|
1609
|
+
* hint — universally understood (Figma, Tokens Studio). `'oklch'` emits
|
|
1610
|
+
* OKLCH components with no hex — Glaze-native, wide-gamut.
|
|
1611
|
+
*/
|
|
1612
|
+
colorSpace?: DtcgColorSpace;
|
|
1613
|
+
}
|
|
1614
|
+
/**
|
|
1615
|
+
* A node in a DTCG Resolver-Module token tree: either a leaf color token or a
|
|
1616
|
+
* nested group. A flat `DtcgDocument` (top-level color-name keys) is a valid
|
|
1617
|
+
* shallow tree, so Glaze's per-scheme documents slot directly into
|
|
1618
|
+
* `sets.<name>.sources` and `modifiers.<name>.contexts.<ctx>` entries.
|
|
1619
|
+
*/
|
|
1620
|
+
interface DtcgTokenTree {
|
|
1621
|
+
[key: string]: DtcgColorToken | DtcgTokenTree;
|
|
1622
|
+
}
|
|
1623
|
+
/** A named set in a resolver document: a list of token-tree sources. */
|
|
1624
|
+
interface DtcgResolverSet {
|
|
1625
|
+
sources: DtcgTokenTree[];
|
|
1626
|
+
}
|
|
1627
|
+
/**
|
|
1628
|
+
* A named modifier (an axis such as `scheme`) in a resolver document.
|
|
1629
|
+
* `default` names the context applied when no override is selected; `contexts`
|
|
1630
|
+
* maps each context name to the token-tree overrides applied for it.
|
|
1631
|
+
*/
|
|
1632
|
+
interface DtcgResolverModifier {
|
|
1633
|
+
default: string;
|
|
1634
|
+
contexts: Record<string, DtcgTokenTree[]>;
|
|
1635
|
+
}
|
|
1636
|
+
/** A JSON-pointer `$ref` entry in a resolver document's `resolutionOrder`. */
|
|
1637
|
+
interface DtcgResolverRef {
|
|
1638
|
+
$ref: string;
|
|
1639
|
+
}
|
|
1640
|
+
/**
|
|
1641
|
+
* A W3C DTCG Resolver-Module document. Describes every scheme variant in a
|
|
1642
|
+
* single file as `sets` (base token sources) plus `modifiers` (per-context
|
|
1643
|
+
* overrides) composed in `resolutionOrder`. Consumable by resolver tools such
|
|
1644
|
+
* as Dispersa.
|
|
1645
|
+
* @see https://www.designtokens.org/
|
|
1646
|
+
*/
|
|
1647
|
+
interface GlazeDtcgResolverDocument {
|
|
1648
|
+
version: string;
|
|
1649
|
+
sets: Record<string, DtcgResolverSet>;
|
|
1650
|
+
modifiers: Record<string, DtcgResolverModifier>;
|
|
1651
|
+
resolutionOrder: DtcgResolverRef[];
|
|
1652
|
+
}
|
|
1653
|
+
/** Renaming of the four scheme variants as resolver-modifier context names. */
|
|
1654
|
+
interface GlazeDtcgResolverContextNames {
|
|
1655
|
+
light?: string;
|
|
1656
|
+
dark?: string;
|
|
1657
|
+
lightContrast?: string;
|
|
1658
|
+
darkContrast?: string;
|
|
1659
|
+
}
|
|
1660
|
+
/**
|
|
1661
|
+
* Options for `theme.dtcgResolver()` / `palette.dtcgResolver()`. Extends
|
|
1662
|
+
* `GlazeDtcgOptions` so `modes` + `colorSpace` pass through to the underlying
|
|
1663
|
+
* per-scheme `dtcg()` build.
|
|
1664
|
+
*/
|
|
1665
|
+
interface GlazeDtcgResolverOptions extends GlazeDtcgOptions {
|
|
1666
|
+
/** Name of the single set holding the default (light) token tree. Default `'base'`. */
|
|
1667
|
+
setName?: string;
|
|
1668
|
+
/**
|
|
1669
|
+
* Name of the modifier describing the scheme axis. Default `'scheme'`
|
|
1670
|
+
* (Glaze's term for the light / dark / high-contrast axis).
|
|
1671
|
+
*/
|
|
1672
|
+
modifierName?: string;
|
|
1673
|
+
/**
|
|
1674
|
+
* Override the four context names emitted on the modifier. Defaults to the
|
|
1675
|
+
* Glaze variant keys: `light` / `dark` / `lightContrast` / `darkContrast`.
|
|
1676
|
+
*/
|
|
1677
|
+
contextNames?: GlazeDtcgResolverContextNames;
|
|
1678
|
+
/** Resolver document version. Default `'2025.10'`. */
|
|
1679
|
+
version?: string;
|
|
1680
|
+
}
|
|
1681
|
+
/** Options for `glaze.color().dtcgResolver()`. `name` is required. */
|
|
1682
|
+
interface GlazeColorDtcgResolverOptions extends GlazeDtcgResolverOptions {
|
|
1683
|
+
/** Token name keying the color within each token tree. Required. */
|
|
1684
|
+
name: string;
|
|
1685
|
+
}
|
|
1686
|
+
/** Options for `theme.tailwind()` / `palette.tailwind()`. */
|
|
1687
|
+
interface GlazeTailwindOptions {
|
|
1688
|
+
/** Override which scheme variants to include. */
|
|
1689
|
+
modes?: GlazeOutputModes;
|
|
1690
|
+
/** Output color format. Default: 'oklch'. */
|
|
1691
|
+
format?: GlazeColorFormat;
|
|
1692
|
+
/**
|
|
1693
|
+
* CSS custom property namespace, forming `--<namespace><name>`.
|
|
1694
|
+
* Default: `'color-'` → `--color-surface`. (Tailwind v4's `--color-*`
|
|
1695
|
+
* convention, which auto-generates `bg-*` / `text-*` / `border-*`.)
|
|
1696
|
+
*
|
|
1697
|
+
* Named `namespace` rather than `prefix` to avoid clashing with the
|
|
1698
|
+
* palette theme-prefix option on `palette.tailwind()`.
|
|
1699
|
+
*/
|
|
1700
|
+
namespace?: string;
|
|
1701
|
+
/**
|
|
1702
|
+
* Selector wrapping the dark-scheme overrides. Default: `'.dark'`.
|
|
1703
|
+
* Pass a media query such as `'@media (prefers-color-scheme: dark)'` to
|
|
1704
|
+
* drive dark mode from the OS preference instead of a class.
|
|
1705
|
+
*/
|
|
1706
|
+
darkSelector?: string;
|
|
1707
|
+
/**
|
|
1708
|
+
* Selector wrapping the light high-contrast overrides. Default:
|
|
1709
|
+
* `'.high-contrast'`. The combined dark + high-contrast overrides are
|
|
1710
|
+
* emitted under `${darkSelector}${highContrastSelector}` (e.g.
|
|
1711
|
+
* `.dark.high-contrast`).
|
|
1712
|
+
*/
|
|
1713
|
+
highContrastSelector?: string;
|
|
1714
|
+
/**
|
|
1715
|
+
* Selector wrapping the HDR overrides, emitted with `modes.hdr` after every
|
|
1716
|
+
* SDR block. Default: `'@media (dynamic-range: high)'`. Each HDR block is
|
|
1717
|
+
* dense (every color with an HDR value in any emitted scheme, SDR value
|
|
1718
|
+
* where the scheme has none) and is scoped by this selector alone (light),
|
|
1719
|
+
* combined with `darkSelector` (dark), with `highContrastSelector` (light
|
|
1720
|
+
* high contrast), or with both.
|
|
1721
|
+
*/
|
|
1722
|
+
hdrSelector?: string;
|
|
1723
|
+
}
|
|
1724
|
+
/** Options for `glaze.color().tailwind()`. `name` is required. */
|
|
1725
|
+
interface GlazeColorTailwindOptions extends GlazeTailwindOptions {
|
|
1726
|
+
/** Custom property base name (without leading `--`). Required. */
|
|
1727
|
+
name: string;
|
|
1728
|
+
}
|
|
639
1729
|
/** Options for `glaze.palette()` creation. */
|
|
640
1730
|
interface GlazePaletteOptions {
|
|
641
1731
|
/**
|
|
@@ -652,7 +1742,10 @@ interface GlazePaletteOptions {
|
|
|
652
1742
|
*/
|
|
653
1743
|
primary?: string;
|
|
654
1744
|
}
|
|
655
|
-
/**
|
|
1745
|
+
/**
|
|
1746
|
+
* Options shared by every palette export except `json()`: `tokens()`,
|
|
1747
|
+
* `tasty()`, `css()`, `dtcg()`, `dtcgResolver()`, and `tailwind()`.
|
|
1748
|
+
*/
|
|
656
1749
|
interface GlazePaletteExportOptions {
|
|
657
1750
|
/**
|
|
658
1751
|
* Prefix mode. `true` uses `"<themeName>-"`, or provide a custom map.
|
|
@@ -668,7 +1761,58 @@ interface GlazePaletteExportOptions {
|
|
|
668
1761
|
*/
|
|
669
1762
|
primary?: string | false;
|
|
670
1763
|
}
|
|
1764
|
+
/**
|
|
1765
|
+
* Options for `palette.tasty()`. There is no `name`: each theme's hue var is
|
|
1766
|
+
* named after the theme.
|
|
1767
|
+
*/
|
|
1768
|
+
interface GlazePaletteTastyOptions extends GlazeTokenOptions, GlazePaletteExportOptions {
|
|
1769
|
+
/**
|
|
1770
|
+
* Emit hue as a separate custom property, referenced via `var()`.
|
|
1771
|
+
* Requires `format: 'oklch'` (any other format throws) and every color to
|
|
1772
|
+
* be pastel. The theme-level hue var is `--{themeName}-hue`.
|
|
1773
|
+
*/
|
|
1774
|
+
splitHue?: boolean;
|
|
1775
|
+
}
|
|
1776
|
+
/**
|
|
1777
|
+
* Options for `palette.css()`. There is no `name`: each theme's hue var is
|
|
1778
|
+
* named after the theme.
|
|
1779
|
+
*/
|
|
1780
|
+
interface GlazePaletteCssOptions extends GlazePaletteExportOptions {
|
|
1781
|
+
/** Output color format. Default: 'oklch'. */
|
|
1782
|
+
format?: GlazeColorFormat;
|
|
1783
|
+
/** Suffix appended to each CSS custom property name. Default: '-color'. */
|
|
1784
|
+
suffix?: string;
|
|
1785
|
+
/**
|
|
1786
|
+
* Emit hue as a separate custom property, referenced via `var()`.
|
|
1787
|
+
* Requires `format: 'oklch'` (any other format throws) and every color to
|
|
1788
|
+
* be pastel. The theme-level hue var is `--{themeName}-hue`.
|
|
1789
|
+
*/
|
|
1790
|
+
splitHue?: boolean;
|
|
1791
|
+
/**
|
|
1792
|
+
* Add the HDR tier as `result.hdr` (see {@link GlazeCssResult.hdr}).
|
|
1793
|
+
* Default: the global `modes.hdr` (false).
|
|
1794
|
+
*/
|
|
1795
|
+
hdr?: boolean;
|
|
1796
|
+
}
|
|
671
1797
|
interface GlazePalette {
|
|
1798
|
+
/** Theme names in insertion order. */
|
|
1799
|
+
list(): string[];
|
|
1800
|
+
/** Primary theme name, if set at palette creation. */
|
|
1801
|
+
readonly primary: string | undefined;
|
|
1802
|
+
/** Get a theme by name. Returns the live instance held by the palette. */
|
|
1803
|
+
theme(name: string): GlazeTheme | undefined;
|
|
1804
|
+
/**
|
|
1805
|
+
* Shallow copy of the theme map (same instances the palette holds).
|
|
1806
|
+
* Mutating a returned theme affects subsequent palette exports.
|
|
1807
|
+
*/
|
|
1808
|
+
themes(): Record<string, GlazeTheme>;
|
|
1809
|
+
/**
|
|
1810
|
+
* Export the palette authoring configuration as a JSON-safe object.
|
|
1811
|
+
* Restorable via `glaze.paletteFrom(...)`. Distinct from `json()`, which
|
|
1812
|
+
* emits resolved color strings. Optional `override` is forwarded to each
|
|
1813
|
+
* nested `theme.export(override)`.
|
|
1814
|
+
*/
|
|
1815
|
+
export(override?: GlazeConfigOverride): GlazePaletteExport;
|
|
672
1816
|
/**
|
|
673
1817
|
* Export all themes as a flat token map grouped by scheme variant.
|
|
674
1818
|
* Prefix defaults to `true` — all tokens are prefixed with the theme name.
|
|
@@ -683,77 +1827,275 @@ interface GlazePalette {
|
|
|
683
1827
|
tokens(options?: GlazeJsonOptions & GlazePaletteExportOptions): Record<string, Record<string, string>>;
|
|
684
1828
|
/**
|
|
685
1829
|
* Export all themes as tasty style-to-state bindings.
|
|
686
|
-
* Uses `#name` color token keys and state aliases (`''`,
|
|
1830
|
+
* Uses `#name` color token keys and state aliases (`''`, `'@media(prefers-color-scheme: dark)'`, etc.).
|
|
687
1831
|
* Prefix defaults to `true`. Inherits the palette-level `primary`.
|
|
688
1832
|
* @see https://tasty.style/docs
|
|
689
1833
|
*/
|
|
690
|
-
tasty(options?:
|
|
691
|
-
/**
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
1834
|
+
tasty(options?: GlazePaletteTastyOptions): Record<string, Record<string, string>>;
|
|
1835
|
+
/**
|
|
1836
|
+
* Export all themes as plain JSON grouped by theme name. No prefix, primary
|
|
1837
|
+
* alias, or collision handling: each theme keeps its own key.
|
|
1838
|
+
*/
|
|
1839
|
+
json(options?: GlazeJsonOptions): Record<string, Record<string, Record<string, string>>>;
|
|
695
1840
|
/** Export all themes as CSS custom property declarations. */
|
|
696
|
-
css(options?:
|
|
1841
|
+
css(options?: GlazePaletteCssOptions): GlazeCssResult;
|
|
1842
|
+
/**
|
|
1843
|
+
* Export all themes as W3C DTCG documents, one per scheme variant.
|
|
1844
|
+
* Prefix defaults to `true`. Inherits the palette-level `primary`.
|
|
1845
|
+
* @see https://www.designtokens.org/
|
|
1846
|
+
*/
|
|
1847
|
+
dtcg(options?: GlazeDtcgOptions & GlazePaletteExportOptions): GlazeDtcgResult;
|
|
1848
|
+
/**
|
|
1849
|
+
* Export all themes as a single W3C DTCG Resolver-Module document. Prefix
|
|
1850
|
+
* defaults to `true`. Inherits the palette-level `primary`.
|
|
1851
|
+
* @see https://www.designtokens.org/
|
|
1852
|
+
*/
|
|
1853
|
+
dtcgResolver(options?: GlazeDtcgResolverOptions & GlazePaletteExportOptions): GlazeDtcgResolverDocument;
|
|
1854
|
+
/**
|
|
1855
|
+
* Export all themes as a Tailwind CSS v4 `@theme` block plus dark /
|
|
1856
|
+
* high-contrast overrides. Returns a single ready-to-paste CSS string.
|
|
1857
|
+
* Prefix defaults to `true`.
|
|
1858
|
+
* @see https://tailwindcss.com/docs/theme
|
|
1859
|
+
*/
|
|
1860
|
+
tailwind(options?: GlazeTailwindOptions & GlazePaletteExportOptions): string;
|
|
697
1861
|
}
|
|
698
1862
|
//#endregion
|
|
1863
|
+
//#region src/serialize.d.ts
|
|
1864
|
+
/** Type guard for theme authoring snapshots (prefers `kind`, falls back to shape). */
|
|
1865
|
+
declare function isThemeExport(data: unknown): data is GlazeThemeExport;
|
|
1866
|
+
/** Type guard for color-token authoring snapshots. */
|
|
1867
|
+
declare function isColorTokenExport(data: unknown): data is GlazeColorTokenExport;
|
|
1868
|
+
/** Type guard for palette authoring snapshots. */
|
|
1869
|
+
declare function isPaletteExport(data: unknown): data is GlazePaletteExport;
|
|
1870
|
+
//#endregion
|
|
699
1871
|
//#region src/glaze.d.ts
|
|
700
1872
|
type PaletteInput = Record<string, GlazeTheme>;
|
|
701
1873
|
/**
|
|
702
1874
|
* Create a single-hue glaze theme.
|
|
703
1875
|
*
|
|
1876
|
+
* An optional `config` override can be supplied to customize the resolve
|
|
1877
|
+
* behavior for this theme (tone windows, etc.). The
|
|
1878
|
+
* override is **merged over the live global config at resolve time** —
|
|
1879
|
+
* the theme still reacts to later `configure()` calls for fields it
|
|
1880
|
+
* didn't override.
|
|
1881
|
+
*
|
|
1882
|
+
* The object form also accepts `darkHue` / `darkSaturation` — a separate
|
|
1883
|
+
* seed pair for the dark and dark-high-contrast schemes. Both default to
|
|
1884
|
+
* their light counterparts, and an explicit `darkSaturation` opts the theme
|
|
1885
|
+
* out of the global `darkDesaturation` reduction.
|
|
1886
|
+
*
|
|
704
1887
|
* @example
|
|
705
1888
|
* ```ts
|
|
706
|
-
* const primary = glaze({ hue: 280, saturation: 80 });
|
|
707
|
-
* // or shorthand:
|
|
708
1889
|
* const primary = glaze(280, 80);
|
|
1890
|
+
* // or shorthand:
|
|
1891
|
+
* const primary = glaze({ hue: 280, saturation: 80 });
|
|
1892
|
+
* // with a retuned dark seed:
|
|
1893
|
+
* const primary = glaze({ hue: 280, saturation: 80, darkHue: 268, darkSaturation: 65 });
|
|
1894
|
+
* // with config override:
|
|
1895
|
+
* const raw = glaze(280, 80, { lightTone: false });
|
|
1896
|
+
* const rawSeed = glaze({ hue: 280, saturation: 80 }, { lightTone: false });
|
|
709
1897
|
* ```
|
|
710
1898
|
*/
|
|
711
|
-
declare function glaze(
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
1899
|
+
declare function glaze(hue: number, saturation?: number, config?: GlazeConfigOverride): GlazeTheme;
|
|
1900
|
+
declare function glaze(seed: GlazeThemeSeed, config?: GlazeConfigOverride): GlazeTheme;
|
|
1901
|
+
/** @deprecated Pass the config second: `glaze(seed, config)`. */
|
|
1902
|
+
declare function glaze(seed: GlazeThemeSeed, saturation: undefined, config?: GlazeConfigOverride): GlazeTheme;
|
|
715
1903
|
declare namespace glaze {
|
|
716
1904
|
var configure: (config: GlazeConfig) => void;
|
|
717
|
-
var palette: (themes: PaletteInput, options?: GlazePaletteOptions) =>
|
|
718
|
-
|
|
719
|
-
tasty(options?: GlazeTokenOptions & GlazePaletteExportOptions): Record<string, Record<string, string>>;
|
|
720
|
-
json(options?: GlazeJsonOptions & {
|
|
721
|
-
prefix?: boolean | Record<string, string>;
|
|
722
|
-
}): Record<string, Record<string, Record<string, string>>>;
|
|
723
|
-
css(options?: GlazeCssOptions & GlazePaletteExportOptions): GlazeCssResult;
|
|
724
|
-
};
|
|
1905
|
+
var palette: (themes: PaletteInput, options?: GlazePaletteOptions) => GlazePalette;
|
|
1906
|
+
var themeFrom: (data: GlazeThemeExport) => GlazeTheme;
|
|
725
1907
|
var from: (data: GlazeThemeExport) => GlazeTheme;
|
|
726
|
-
var color:
|
|
727
|
-
(input: GlazeColorInput, scaling?: GlazeColorScaling): GlazeColorToken;
|
|
728
|
-
(value: GlazeColorValue, overrides?: GlazeColorOverrides, scaling?: GlazeColorScaling): GlazeColorToken;
|
|
729
|
-
};
|
|
1908
|
+
var color: (input: GlazeFromInput | GlazeColorInput | GlazeColorValue, config?: GlazeConfigOverride) => GlazeColorToken;
|
|
730
1909
|
var shadow: (input: GlazeShadowInput) => ResolvedColorVariant;
|
|
731
|
-
var
|
|
1910
|
+
var glow: (input: GlazeGlowInput) => ResolvedColorVariant;
|
|
1911
|
+
var format: (variant: ResolvedColorVariant, colorFormat?: GlazeColorFormat, pastel?: boolean) => string;
|
|
1912
|
+
var formatHdr: (variant: ResolvedColorVariant, hdrFormat?: GlazeHdrFormat) => string | undefined;
|
|
732
1913
|
var fromHex: (hex: string) => GlazeTheme;
|
|
733
1914
|
var fromRgb: (r: number, g: number, b: number) => GlazeTheme;
|
|
734
1915
|
var colorFrom: (data: GlazeColorTokenExport) => GlazeColorToken;
|
|
1916
|
+
var paletteFrom: (data: GlazePaletteExport) => GlazePalette;
|
|
1917
|
+
var isThemeExport: typeof isThemeExport;
|
|
1918
|
+
var isColorTokenExport: typeof isColorTokenExport;
|
|
1919
|
+
var isPaletteExport: typeof isPaletteExport;
|
|
735
1920
|
var getConfig: () => GlazeConfigResolved;
|
|
736
1921
|
var resetConfig: () => void;
|
|
737
1922
|
}
|
|
738
1923
|
//#endregion
|
|
1924
|
+
//#region src/channels.d.ts
|
|
1925
|
+
interface HueDeclaration {
|
|
1926
|
+
prop: string;
|
|
1927
|
+
value: string;
|
|
1928
|
+
}
|
|
1929
|
+
interface HuePlan {
|
|
1930
|
+
/** CSS `var()` reference spliced into `oklch(L C <hueVar>)`. */
|
|
1931
|
+
hueVar: string;
|
|
1932
|
+
/** When true, emit a full inline color (shadow/glow/mix/achromatic). */
|
|
1933
|
+
inline: boolean;
|
|
1934
|
+
/** Scheme-independent `--*-hue` declarations for this color. */
|
|
1935
|
+
declarations: HueDeclaration[];
|
|
1936
|
+
}
|
|
1937
|
+
interface ChannelCtx {
|
|
1938
|
+
seedHue: number;
|
|
1939
|
+
/**
|
|
1940
|
+
* Dark-scheme seed hue, when the theme authored one. Drives the dark
|
|
1941
|
+
* `--{baseName}-hue` value; falls back to `seedHue`.
|
|
1942
|
+
*/
|
|
1943
|
+
darkSeedHue?: number;
|
|
1944
|
+
/** Theme-level hue var base name (without `--` / `-hue`). */
|
|
1945
|
+
baseName: string;
|
|
1946
|
+
/** Token / custom-property name prefix used for hue var naming (`brand-` etc.). */
|
|
1947
|
+
prefix: string;
|
|
1948
|
+
defs: ColorMap;
|
|
1949
|
+
mode: 'theme' | 'standalone';
|
|
1950
|
+
/** Standalone: resolved hue from the primary variant (scheme-independent). */
|
|
1951
|
+
resolvedHue?: number;
|
|
1952
|
+
/**
|
|
1953
|
+
* When false, hue declarations are not emitted (the pass only references
|
|
1954
|
+
* hue vars already declared by a sibling pass). Used by palette primary
|
|
1955
|
+
* unprefixed aliases so they reference the themed `--{themeName}-*-hue`
|
|
1956
|
+
* vars without re-declaring (and colliding with) other themes' base vars.
|
|
1957
|
+
* Defaults to true.
|
|
1958
|
+
*/
|
|
1959
|
+
emitDeclarations?: boolean;
|
|
1960
|
+
}
|
|
1961
|
+
//#endregion
|
|
1962
|
+
//#region src/format-guard.d.ts
|
|
1963
|
+
/**
|
|
1964
|
+
* Throw when a non-native Glaze color space is requested for an export that
|
|
1965
|
+
* emits raw CSS or non-Tasty token maps.
|
|
1966
|
+
*/
|
|
1967
|
+
declare function assertNativeFormat(format: GlazeColorFormat | undefined, method: string): void;
|
|
1968
|
+
/**
|
|
1969
|
+
* Throw when `splitHue` is enabled but any exported color is not pastel.
|
|
1970
|
+
* Hue rotation is only clip-free when chroma is bounded by the hue-independent
|
|
1971
|
+
* safe chroma (`computeSafeChromaOKLCH`).
|
|
1972
|
+
*/
|
|
1973
|
+
declare function assertAllPastel(resolved: Map<string, ResolvedColor>, modes: Required<GlazeOutputModes>): void;
|
|
1974
|
+
//#endregion
|
|
1975
|
+
//#region src/roles.d.ts
|
|
1976
|
+
/**
|
|
1977
|
+
* Normalize a `RoleInput` (canonical value or alias) into a canonical `Role`.
|
|
1978
|
+
* Returns `undefined` for unrecognized strings so callers can fall through to
|
|
1979
|
+
* the next step of the resolution chain.
|
|
1980
|
+
*/
|
|
1981
|
+
declare function normalizeRole(input: RoleInput | undefined): Role | undefined;
|
|
1982
|
+
/**
|
|
1983
|
+
* Infer a `Role` from a color name by matching its tokens against the role
|
|
1984
|
+
* keyword sets. When multiple tokens match, the **last** recognized token
|
|
1985
|
+
* wins (so `button-text` → `text`, `input-bg` → `surface`, `card-border` →
|
|
1986
|
+
* `border`). Returns `undefined` when no token matches.
|
|
1987
|
+
*/
|
|
1988
|
+
declare function inferRoleFromName(name: string): Role | undefined;
|
|
1989
|
+
/** APCA argument order: which side the resolved color plays. */
|
|
1990
|
+
type Polarity = 'fg' | 'bg';
|
|
1991
|
+
/**
|
|
1992
|
+
* Map a role to its APCA polarity. `text` and `border` are foreground spots
|
|
1993
|
+
* against their base (the candidate is the text argument); `surface` is the
|
|
1994
|
+
* background (the base is the text argument).
|
|
1995
|
+
*/
|
|
1996
|
+
declare function roleToPolarity(role: Role): Polarity;
|
|
1997
|
+
/**
|
|
1998
|
+
* The opposite role of `role`, used when a color with no explicit role and no
|
|
1999
|
+
* inferable name depends on a base: the dependent color plays the opposite
|
|
2000
|
+
* role of its base. `surface` ↔ `text`; `border` is treated as a foreground
|
|
2001
|
+
* spot, so its opposite is `surface`.
|
|
2002
|
+
*/
|
|
2003
|
+
declare function oppositeRole(role: Role): Role;
|
|
2004
|
+
//#endregion
|
|
2005
|
+
//#region src/okhst.d.ts
|
|
2006
|
+
/**
|
|
2007
|
+
* Reference eps for the OKHST color space. WCAG 2 contrast is
|
|
2008
|
+
* `(Y_hi + 0.05) / (Y_lo + 0.05)`, so an eps of `0.05` makes equal tone
|
|
2009
|
+
* steps yield equal WCAG contrast. This is the canonical eps used by
|
|
2010
|
+
* `okhst()` input, `{ h, s, t }` input, stored `ResolvedColorVariant.t`,
|
|
2011
|
+
* relative `tone` offsets, and the contrast solver.
|
|
2012
|
+
*/
|
|
2013
|
+
declare const REF_EPS = 0.05;
|
|
2014
|
+
/**
|
|
2015
|
+
* Map a luminance `Y` (0–1) to tone (0–100) at the given eps.
|
|
2016
|
+
* `toneFromY(0) === 0` and `toneFromY(1) === 100` for any eps.
|
|
2017
|
+
*/
|
|
2018
|
+
declare function toneFromY(y: number, eps?: number): number;
|
|
2019
|
+
/** Map a tone (0–100) back to luminance (0–1). Inverse of {@link toneFromY}. */
|
|
2020
|
+
declare function yFromTone(t: number, eps?: number): number;
|
|
2021
|
+
/** OKHSL lightness (0–1) -> tone (0–100). */
|
|
2022
|
+
declare function toTone(l: number, eps?: number): number;
|
|
2023
|
+
/** Tone (0–100) -> OKHSL lightness (0–1). Inverse of {@link toTone}. */
|
|
2024
|
+
declare function fromTone(t: number, eps?: number): number;
|
|
2025
|
+
/** Convert OKHST `{ h, s, t }` (t in 0–1) to OKHSL `{ h, s, l }`. */
|
|
2026
|
+
declare function okhstToOkhsl(c: {
|
|
2027
|
+
h: number;
|
|
2028
|
+
s: number;
|
|
2029
|
+
t: number;
|
|
2030
|
+
}): {
|
|
2031
|
+
h: number;
|
|
2032
|
+
s: number;
|
|
2033
|
+
l: number;
|
|
2034
|
+
};
|
|
2035
|
+
/** Convert OKHSL `{ h, s, l }` to OKHST `{ h, s, t }` (t in 0–1). */
|
|
2036
|
+
declare function okhslToOkhst(c: {
|
|
2037
|
+
h: number;
|
|
2038
|
+
s: number;
|
|
2039
|
+
l: number;
|
|
2040
|
+
}): {
|
|
2041
|
+
h: number;
|
|
2042
|
+
s: number;
|
|
2043
|
+
t: number;
|
|
2044
|
+
};
|
|
2045
|
+
/**
|
|
2046
|
+
* Edge adapter: a resolved variant stores canonical tone `t` (0–1). Convert
|
|
2047
|
+
* it to the OKHSL `{ h, s, l }` the formatters and luminance pipeline expect —
|
|
2048
|
+
* `s` and `l` on the same 0–1 factor scale, so `const { h, s, l } =
|
|
2049
|
+
* variantToOkhsl(v)` destructures straight into `formatOkhsl` / `formatRgb` /
|
|
2050
|
+
* `okhslToLinearSrgb` with no rescaling. `alpha` stays on the variant; use
|
|
2051
|
+
* `glaze.format(v, format)` for a string that carries it.
|
|
2052
|
+
*/
|
|
2053
|
+
declare function variantToOkhsl(v: {
|
|
2054
|
+
h: number;
|
|
2055
|
+
s: number;
|
|
2056
|
+
t: number;
|
|
2057
|
+
}): {
|
|
2058
|
+
h: number;
|
|
2059
|
+
s: number;
|
|
2060
|
+
l: number;
|
|
2061
|
+
};
|
|
2062
|
+
//#endregion
|
|
739
2063
|
//#region src/okhsl-color-math.d.ts
|
|
740
2064
|
/**
|
|
741
2065
|
* OKHSL color math primitives for the glaze theme generator.
|
|
742
2066
|
*
|
|
743
|
-
* Provides bidirectional OKHSL ↔ sRGB conversion,
|
|
744
|
-
*
|
|
745
|
-
*
|
|
2067
|
+
* Provides bidirectional OKHSL ↔ sRGB conversion, luminance computation
|
|
2068
|
+
* for both contrast metrics (WCAG 2 relative luminance and APCA screen
|
|
2069
|
+
* luminance `Ys` — both the exact functions the contrast solver uses, and
|
|
2070
|
+
* both public), strict hex parsing (`parseHex` / `parseHexAlpha` check every
|
|
2071
|
+
* digit), and multi-format output (okhsl, rgb, hsl, oklch, plus the
|
|
2072
|
+
* `color(srgb-linear …)` writer for HDR glow values, whose channels may exceed
|
|
2073
|
+
* 1).
|
|
746
2074
|
*/
|
|
747
2075
|
type Vec3 = [number, number, number];
|
|
2076
|
+
/**
|
|
2077
|
+
* OKHSL toe function: maps OKLab lightness L to perceptual lightness l.
|
|
2078
|
+
* Exported for the OKHST tone transfers in `okhst.ts`.
|
|
2079
|
+
*/
|
|
2080
|
+
/**
|
|
2081
|
+
* OKHSL lightness of the gamut cusp for a hue — the lightness where the
|
|
2082
|
+
* realizable chroma peaks. Reuses the same `find_cusp` OKHSL already runs for
|
|
2083
|
+
* its `s` normalization (no new color math); the OKLab cusp lightness is run
|
|
2084
|
+
* through the OKHSL `toe` and clamped to `[0.001, 0.999]` so divisions that
|
|
2085
|
+
* key off it stay safe. Cached per (rounded) hue.
|
|
2086
|
+
*
|
|
2087
|
+
* @param h Hue, 0–360.
|
|
2088
|
+
*/
|
|
2089
|
+
declare function cuspLightness(h: number): number;
|
|
748
2090
|
/**
|
|
749
2091
|
* Convert OKHSL (h: 0–360, s: 0–1, l: 0–1) to OKLab [L, a, b].
|
|
750
2092
|
*/
|
|
751
|
-
declare function okhslToOklab(h: number, s: number, l: number): [number, number, number];
|
|
2093
|
+
declare function okhslToOklab(h: number, s: number, l: number, pastel?: boolean): [number, number, number];
|
|
752
2094
|
/**
|
|
753
2095
|
* Convert OKHSL (h: 0–360, s: 0–1, l: 0–1) to linear sRGB.
|
|
754
2096
|
* Channels may exceed [0, 1] near gamut boundaries — caller must clamp if needed.
|
|
755
2097
|
*/
|
|
756
|
-
declare function okhslToLinearSrgb(h: number, s: number, l: number): [number, number, number];
|
|
2098
|
+
declare function okhslToLinearSrgb(h: number, s: number, l: number, pastel?: boolean): [number, number, number];
|
|
757
2099
|
/**
|
|
758
2100
|
* Compute relative luminance Y from linear sRGB channels.
|
|
759
2101
|
* Per WCAG 2: Y = 0.2126·R + 0.7152·G + 0.0722·B
|
|
@@ -765,25 +2107,42 @@ declare function relativeLuminanceFromLinearRgb(rgb: [number, number, number]):
|
|
|
765
2107
|
declare function contrastRatioFromLuminance(yA: number, yB: number): number;
|
|
766
2108
|
/**
|
|
767
2109
|
* Convert OKHSL to gamma-encoded sRGB (clamped to 0–1).
|
|
2110
|
+
* h: 0–360, s: 0–1, l: 0–1. Returns [r, g, b] with each channel 0–1.
|
|
768
2111
|
*/
|
|
769
|
-
declare function okhslToSrgb(h: number, s: number, l: number): [number, number, number];
|
|
2112
|
+
declare function okhslToSrgb(h: number, s: number, l: number, pastel?: boolean): [number, number, number];
|
|
770
2113
|
/**
|
|
771
2114
|
* Compute WCAG 2 relative luminance from linear sRGB, matching the browser
|
|
772
2115
|
* rendering pipeline: gamma-encode, clamp to sRGB gamut [0,1], then linearize.
|
|
773
2116
|
* This avoids over/under-estimating luminance for out-of-gamut OKHSL colors.
|
|
774
2117
|
*/
|
|
775
2118
|
declare function gamutClampedLuminance(linearRgb: [number, number, number]): number;
|
|
2119
|
+
/**
|
|
2120
|
+
* Compute APCA screen luminance (`Ys`) from linear sRGB.
|
|
2121
|
+
*
|
|
2122
|
+
* APCA does not use the WCAG piecewise sRGB EOTF; it defines its own
|
|
2123
|
+
* luminance as `0.2126·R^2.4 + 0.7152·G^2.4 + 0.0722·B^2.4` over the
|
|
2124
|
+
* gamma-encoded (display) channels with a simple 2.4 exponent. The APCA
|
|
2125
|
+
* soft-clamp threshold in `apcaContrast` is calibrated against this basis,
|
|
2126
|
+
* so the solver must feed it `Ys`, not WCAG relative luminance. Channels
|
|
2127
|
+
* are gamut-clamped to [0, 1] first, matching `gamutClampedLuminance`.
|
|
2128
|
+
*
|
|
2129
|
+
* This is exactly the luminance Glaze's contrast solver (and its drift
|
|
2130
|
+
* check) feeds `apcaContrast`, so
|
|
2131
|
+
* `apcaContrast(apcaLuminanceFromLinearRgb(text), apcaLuminanceFromLinearRgb(bg))`
|
|
2132
|
+
* reproduces the solver's Lc for a resolved pair.
|
|
2133
|
+
*/
|
|
2134
|
+
declare function apcaLuminanceFromLinearRgb(linearRgb: [number, number, number]): number;
|
|
776
2135
|
/**
|
|
777
2136
|
* Convert OKLab to OKHSL.
|
|
778
2137
|
* Input: [L, a, b] where L: 0–1, a/b: roughly -0.5 to 0.5.
|
|
779
2138
|
* Returns [h, s, l] where h: 0–360, s: 0–1, l: 0–1.
|
|
780
2139
|
*/
|
|
781
|
-
declare const oklabToOkhsl: (lab: Vec3) => Vec3;
|
|
2140
|
+
declare const oklabToOkhsl: (lab: Vec3, pastel?: boolean) => Vec3;
|
|
782
2141
|
/**
|
|
783
2142
|
* Convert gamma-encoded sRGB (0–1 per channel) to OKHSL.
|
|
784
2143
|
* Returns [h, s, l] where h: 0–360, s: 0–1, l: 0–1.
|
|
785
2144
|
*/
|
|
786
|
-
declare function srgbToOkhsl(rgb: [number, number, number]): [number, number, number];
|
|
2145
|
+
declare function srgbToOkhsl(rgb: [number, number, number], pastel?: boolean): [number, number, number];
|
|
787
2146
|
/**
|
|
788
2147
|
* Convert CSS HSL (sRGB-based) to gamma-encoded sRGB [r, g, b] in 0–1 range.
|
|
789
2148
|
* h: 0–360, s: 0–1, l: 0–1.
|
|
@@ -794,7 +2153,9 @@ declare function srgbToOkhsl(rgb: [number, number, number]): [number, number, nu
|
|
|
794
2153
|
declare function hslToSrgb(h: number, s: number, l: number): [number, number, number];
|
|
795
2154
|
/**
|
|
796
2155
|
* Parse a hex color string (#rgb or #rrggbb) to sRGB [r, g, b] in 0–1 range.
|
|
797
|
-
* Returns null if the string is not a valid hex
|
|
2156
|
+
* The leading `#` is optional. Returns null if the string is not a valid hex
|
|
2157
|
+
* color: a wrong length, any character outside `0-9a-f` (case-insensitive),
|
|
2158
|
+
* or a form with alpha.
|
|
798
2159
|
*
|
|
799
2160
|
* For 8-digit hex (`#rrggbbaa`) and 4-digit hex (`#rgba`) with alpha,
|
|
800
2161
|
* use {@link parseHexAlpha}.
|
|
@@ -803,7 +2164,12 @@ declare function parseHex(hex: string): [number, number, number] | null;
|
|
|
803
2164
|
/**
|
|
804
2165
|
* Parse a hex color string (#rgb, #rrggbb, #rgba, or #rrggbbaa) to
|
|
805
2166
|
* sRGB [r, g, b] in 0–1 range plus an optional alpha (0–1).
|
|
806
|
-
* Returns null if the string is not a valid hex
|
|
2167
|
+
* The leading `#` is optional. Returns null if the string is not a valid hex
|
|
2168
|
+
* color: a wrong length or any character outside `0-9a-f`
|
|
2169
|
+
* (case-insensitive).
|
|
2170
|
+
*
|
|
2171
|
+
* Every digit is checked up front: `parseInt` alone stops at the first bad
|
|
2172
|
+
* character, so `'#1z2z3z'` would otherwise read as `#010203`.
|
|
807
2173
|
*/
|
|
808
2174
|
declare function parseHexAlpha(hex: string): {
|
|
809
2175
|
rgb: [number, number, number];
|
|
@@ -811,25 +2177,53 @@ declare function parseHexAlpha(hex: string): {
|
|
|
811
2177
|
} | null;
|
|
812
2178
|
/**
|
|
813
2179
|
* Format OKHSL values as a CSS `okhsl(H S% L%)` string.
|
|
814
|
-
* h: 0–360, s: 0–
|
|
2180
|
+
* h: 0–360, s: 0–1, l: 0–1 (factor scale, as returned by every converter).
|
|
2181
|
+
*/
|
|
2182
|
+
declare function formatOkhsl(h: number, s: number, l: number, pastel?: boolean): string;
|
|
2183
|
+
/**
|
|
2184
|
+
* Format OKHST values as a CSS `okhst(H S% T%)` string.
|
|
2185
|
+
* h: 0–360, s: 0–1, t: 0–1 (factor scale, matching `ResolvedColorVariant`).
|
|
2186
|
+
*
|
|
2187
|
+
* Pastel recompute matches `formatOkhsl`: convert via OKLab so external
|
|
2188
|
+
* parsers that only understand non-pastel OKHST render identically.
|
|
815
2189
|
*/
|
|
816
|
-
declare function
|
|
2190
|
+
declare function formatOkhst(h: number, s: number, t: number, pastel?: boolean): string;
|
|
817
2191
|
/**
|
|
818
2192
|
* Format OKHSL values as a CSS `rgb(R G B)` string.
|
|
819
2193
|
* Uses 2 decimal places to avoid 8-bit quantization contrast loss.
|
|
820
|
-
* h: 0–360, s: 0–
|
|
2194
|
+
* h: 0–360, s: 0–1, l: 0–1 (factor scale, as returned by every converter).
|
|
821
2195
|
*/
|
|
822
|
-
declare function formatRgb(h: number, s: number, l: number): string;
|
|
2196
|
+
declare function formatRgb(h: number, s: number, l: number, pastel?: boolean): string;
|
|
823
2197
|
/**
|
|
824
2198
|
* Format OKHSL values as a CSS `hsl(H S% L%)` string.
|
|
825
|
-
* h: 0–360, s: 0–
|
|
2199
|
+
* h: 0–360, s: 0–1, l: 0–1 (factor scale, as returned by every converter).
|
|
826
2200
|
*/
|
|
827
|
-
declare function formatHsl(h: number, s: number, l: number): string;
|
|
2201
|
+
declare function formatHsl(h: number, s: number, l: number, pastel?: boolean): string;
|
|
828
2202
|
/**
|
|
829
2203
|
* Format OKHSL values as a CSS `oklch(L C H)` string.
|
|
830
|
-
* h: 0–360, s: 0–
|
|
2204
|
+
* h: 0–360, s: 0–1, l: 0–1 (factor scale, as returned by every converter).
|
|
2205
|
+
*/
|
|
2206
|
+
declare function formatOklch(h: number, s: number, l: number, pastel?: boolean): string;
|
|
2207
|
+
/**
|
|
2208
|
+
* Format linear sRGB channels as a CSS `color(srgb-linear R G B)` string with
|
|
2209
|
+
* 4 decimals. Unlike the other writers it takes linear light, not OKHSL, and
|
|
2210
|
+
* does not clamp: a channel may exceed 1, which is how an HDR glow value
|
|
2211
|
+
* (`glaze.formatHdr()`) goes past SDR white — `1` is SDR white, `2` one stop
|
|
2212
|
+
* above it. Opaque only; HDR values carry no alpha.
|
|
2213
|
+
*/
|
|
2214
|
+
declare function formatSrgbLinear(rgb: [number, number, number]): string;
|
|
2215
|
+
/**
|
|
2216
|
+
* Convert gamma-encoded sRGB channels (0–1) to a 6-digit lowercase hex
|
|
2217
|
+
* string (`#rrggbb`). Channels are clamped to [0,1] and rounded to 8-bit.
|
|
2218
|
+
* Alpha is not encoded here — DTCG carries it as a separate `alpha` field.
|
|
2219
|
+
*/
|
|
2220
|
+
declare function srgbToHex(rgb: [number, number, number]): `#${string}`;
|
|
2221
|
+
/**
|
|
2222
|
+
* Convert OKHSL (h: 0–360, s: 0–1, l: 0–1) to OKLCH components `[L, C, H]`.
|
|
2223
|
+
* L: 0–1, C: 0–~0.4 (chroma), H: 0–360 (hue). Shared by `formatOklch` and
|
|
2224
|
+
* the DTCG `oklch` colorSpace exporter so the two never drift apart.
|
|
831
2225
|
*/
|
|
832
|
-
declare function
|
|
2226
|
+
declare function okhslToOklch(h: number, s: number, l: number, pastel?: boolean): [number, number, number];
|
|
833
2227
|
//#endregion
|
|
834
|
-
export { type AdaptationMode, type ColorDef, type ColorMap, type ContrastPreset, type
|
|
2228
|
+
export { APCA_HC_ENHANCEMENT, APCA_MAX_LC, APCA_PRESETS, type AdaptationMode, type ApcaPreset, type ChannelCtx, type ColorDef, type ColorMap, type ContrastPreset, type ContrastSpec, type DtcgColorSpace, type DtcgColorToken, type DtcgColorValue, type DtcgDocument, type DtcgOklchColorValue, type DtcgResolverModifier, type DtcgResolverRef, type DtcgResolverSet, type DtcgSrgbColorValue, type DtcgTokenTree, type ExtremeValue, type FindToneForContrastOptions, type FindToneForContrastResult, type FindValueForMixContrastOptions, type FindValueForMixContrastResult, GLAZE_EXPORT_VERSION, type GlazeColorCssOptions, type GlazeColorDtcgResolverOptions, type GlazeColorDtcgResult, type GlazeColorFormat, type GlazeColorInput, type GlazeColorInputExport, type GlazeColorOverrides, type GlazeColorOverridesExport, type GlazeColorTailwindOptions, type GlazeColorToken, type GlazeColorTokenExport, type GlazeColorValue, type GlazeConfig, type GlazeConfigOverride, type GlazeConfigResolved, type GlazeCssOptions, type GlazeCssResult, type GlazeCssSchemeBlocks, type GlazeDtcgExtensions, type GlazeDtcgHdr, type GlazeDtcgOptions, type GlazeDtcgResolverContextNames, type GlazeDtcgResolverDocument, type GlazeDtcgResolverOptions, type GlazeDtcgResult, type GlazeExportKind, type GlazeExportVersion, type GlazeExtendOptions, type GlazeFromInput, type GlazeGlowInput, type GlazeHdrFormat, type GlazeJsonOptions, type GlazeLightingInput, type GlazeOutputModes, type GlazePalette, type GlazePaletteCssOptions, type GlazePaletteExport, type GlazePaletteExportOptions, type GlazePaletteOptions, type GlazePaletteTastyOptions, type GlazeShadowInput, type GlazeTailwindOptions, type GlazeTastyOptions, type GlazeTheme, type GlazeThemeExport, type GlazeThemeSeed, type GlazeTokenOptions, type GlowColorDef, type GlowTuning, type HCPair, type HexColor, type HueDeclaration, type HuePlan, type LightingTuning, type MinContrast, type MixColorDef, type OkhslColor, type OkhstColor, type OklchColor, type Polarity, REF_EPS, type RegularColorDef, type RelativeValue, type ResolvedColor, type ResolvedColorVariant, type ResolvedContrast, type ResolvedHdr, type RgbColor, type Role, type RoleInput, type ShadowColorDef, type ShadowTuning, type ToneValue, type ToneWindow, apcaContrast, apcaLuminanceFromLinearRgb, assertAllPastel, assertNativeFormat, contrastRatioFromLuminance, cuspLightness, findToneForContrast, findValueForMixContrast, formatHsl, formatOkhsl, formatOkhst, formatOklch, formatRgb, formatSrgbLinear, fromTone, gamutClampedLuminance, glaze, hslToSrgb, inferRoleFromName, isColorTokenExport, isPaletteExport, isThemeExport, normalizeRole, okhslToLinearSrgb, okhslToOkhst, okhslToOklab, okhslToOklch, okhslToSrgb, okhstToOkhsl, oklabToOkhsl, oppositeRole, parseHex, parseHexAlpha, relativeLuminanceFromLinearRgb, resolveApcaTarget, resolveContrastForLevel, resolveContrastForMode, resolveMinContrast, roleToPolarity, srgbToHex, srgbToOkhsl, toTone, toneFromY, variantToOkhsl, yFromTone };
|
|
835
2229
|
//# sourceMappingURL=index.d.cts.map
|