@tenphi/glaze 0.13.0 → 0.15.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.mts CHANGED
@@ -1,78 +1,66 @@
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
- interface FindLightnessForContrastOptions {
5
+ /** Metric + numeric target after resolving a `ContrastSpec` for a mode. */
6
+ interface ResolvedContrast {
7
+ metric: 'wcag' | 'apca';
8
+ /** WCAG ratio (>= 1) or APCA Lc magnitude (0–106). */
9
+ target: number;
10
+ }
11
+ declare function resolveMinContrast(value: MinContrast$1): number;
12
+ /**
13
+ * Resolve a `ContrastSpec` (already selected from any outer HC pair) for a
14
+ * given mode into `{ metric, target }`. Handles the inner metric HC pair and
15
+ * preset resolution.
16
+ */
17
+ declare function resolveContrastForMode(spec: ContrastSpec, isHighContrast: boolean): ResolvedContrast;
18
+ /**
19
+ * APCA lightness contrast (Lc), signed: positive for dark text on light bg,
20
+ * negative for light text on dark bg. Inputs are screen luminances (0–1).
21
+ */
22
+ declare function apcaContrast(yText: number, yBg: number): number;
23
+ interface FindToneForContrastOptions {
13
24
  /** Hue of the candidate color (0–360). */
14
25
  hue: number;
15
26
  /** Saturation of the candidate color (0–1). */
16
27
  saturation: number;
17
- /** Preferred lightness of the candidate (0–1). */
18
- preferredLightness: number;
19
- /** Base/reference color as linear sRGB (channels may be outside 0–1 before clamp). */
20
- baseLinearRgb: [number, number, number];
21
- /** WCAG contrast ratio target floor. */
22
- contrast: MinContrast$1;
23
- /** Search bounds for lightness. Default: [0, 1]. */
24
- lightnessRange?: [number, number];
28
+ /** Preferred tone of the candidate (0–1). */
29
+ preferredTone: number;
30
+ /** Base/reference color as linear sRGB. */
31
+ baseLinearRgb: LinearRgb;
32
+ /** Resolved contrast floor (metric + target). */
33
+ contrast: ResolvedContrast;
34
+ /** Search bounds for tone. Default: [0, 1]. */
35
+ toneRange?: [number, number];
25
36
  /** Convergence threshold. Default: 1e-4. */
26
37
  epsilon?: number;
27
- /** Maximum binary-search iterations per branch. Default: 14. */
38
+ /** Maximum binary-search iterations per branch. Default: 18. */
28
39
  maxIterations?: number;
29
- /**
30
- * Preferred search direction before auto-flip is considered.
31
- *
32
- * Theme resolution sets this from the requested lightness relative to
33
- * the base color so `autoFlip: false` preserves the authored direction.
34
- * When omitted, the solver falls back to the side whose extreme has
35
- * higher contrast against the base.
36
- */
40
+ /** Preferred search direction before auto-flip is considered. */
37
41
  initialDirection?: 'lighter' | 'darker';
38
- /**
39
- * Auto-flip lightness direction when contrast can't be met.
40
- *
41
- * When `true`, the solver searches the initial direction first. If that side
42
- * doesn't reach the target, it tries the opposite direction and
43
- * uses it when it passes. If neither side passes, it returns the
44
- * extreme lightness of the initial direction.
45
- *
46
- * When `false`, only the initial direction is considered. If it
47
- * doesn't reach the target, the result is pinned to the initial
48
- * direction's extreme — never to the original preferred lightness.
49
- *
50
- * Default: false.
51
- */
42
+ /** Auto-flip tone direction when contrast can't be met. Default: false. */
52
43
  flip?: boolean;
44
+ /** Use the hue-independent "safe" chroma boundary. Default: false. */
45
+ pastel?: boolean;
53
46
  }
54
- interface FindLightnessForContrastResult {
55
- /** Chosen lightness in 0–1. */
56
- lightness: number;
57
- /** Achieved WCAG contrast ratio. */
47
+ interface FindToneForContrastResult {
48
+ /** Chosen tone in 0–1. */
49
+ tone: number;
50
+ /** Achieved score (WCAG ratio or APCA Lc magnitude). */
58
51
  contrast: number;
59
52
  /** Whether the target was reached. */
60
53
  met: boolean;
61
54
  /** Which branch was selected. */
62
55
  branch: 'lighter' | 'darker' | 'preferred';
63
- /**
64
- * Whether the result was auto-flipped to the opposite direction.
65
- * Only set when the initial direction failed and the opposite
66
- * direction satisfied the target.
67
- */
56
+ /** Whether the result auto-flipped to the opposite direction. */
68
57
  flipped?: boolean;
69
58
  }
70
- declare function resolveMinContrast(value: MinContrast$1): number;
71
59
  /**
72
- * Find the OKHSL lightness that satisfies a WCAG 2 contrast target
73
- * against a base color, staying as close to `preferredLightness` as possible.
60
+ * Find the tone that satisfies a contrast floor against a base color,
61
+ * staying as close to `preferredTone` as possible.
74
62
  */
75
- declare function findLightnessForContrast(options: FindLightnessForContrastOptions): FindLightnessForContrastResult;
63
+ declare function findToneForContrast(options: FindToneForContrastOptions): FindToneForContrastResult;
76
64
  interface FindValueForMixContrastOptions {
77
65
  /** Preferred mix parameter (0–1). */
78
66
  preferredValue: number;
@@ -80,62 +68,69 @@ interface FindValueForMixContrastOptions {
80
68
  baseLinearRgb: LinearRgb;
81
69
  /** Target color as linear sRGB. */
82
70
  targetLinearRgb: LinearRgb;
83
- /** WCAG contrast target. */
84
- contrast: MinContrast$1;
85
- /**
86
- * Compute the luminance of the mixed color at parameter t.
87
- * For opaque: luminance of OKHSL-interpolated color.
88
- * For transparent: luminance of alpha-composited color over base.
89
- */
71
+ /** Resolved contrast floor (metric + target). */
72
+ contrast: ResolvedContrast;
73
+ /** Compute the luminance of the mixed color at parameter t. */
90
74
  luminanceAtValue: (t: number) => number;
91
75
  /** Convergence threshold. Default: 1e-4. */
92
76
  epsilon?: number;
93
77
  /** Maximum binary-search iterations per branch. Default: 20. */
94
78
  maxIterations?: number;
95
- /**
96
- * Auto-flip mix direction when contrast can't be met.
97
- *
98
- * When `true`, the solver searches the initial direction first
99
- * (the side whose extreme has higher contrast against the base).
100
- * If that side doesn't reach the target, it tries the opposite
101
- * direction and uses it when it passes. If neither side passes,
102
- * it returns the extreme mix value of the initial direction.
103
- *
104
- * When `false`, only the initial direction is considered. If it
105
- * doesn't reach the target, the result is pinned to the initial
106
- * direction's extreme — never to the original preferred value.
107
- *
108
- * Default: false.
109
- */
79
+ /** Auto-flip mix direction when contrast can't be met. Default: false. */
110
80
  flip?: boolean;
111
81
  }
112
82
  interface FindValueForMixContrastResult {
113
- /** Chosen mix parameter (0–1). */
114
83
  value: number;
115
- /** Achieved WCAG contrast ratio. */
116
84
  contrast: number;
117
- /** Whether the target was reached. */
118
85
  met: boolean;
119
- /**
120
- * Whether the result was auto-flipped to the opposite direction.
121
- * Only set when the initial direction failed and the opposite
122
- * direction satisfied the target.
123
- */
124
86
  flipped?: boolean;
125
87
  }
126
88
  /**
127
- * Find the mix parameter (ratio or opacity) that satisfies a WCAG 2 contrast
128
- * target against a base color, staying as close to `preferredValue` as possible.
89
+ * Find the mix parameter (ratio or opacity) that satisfies a contrast floor
90
+ * against a base color, staying as close to `preferredValue` as possible.
129
91
  */
130
92
  declare function findValueForMixContrast(options: FindValueForMixContrastOptions): FindValueForMixContrastResult;
131
93
  //#endregion
132
94
  //#region src/types.d.ts
133
95
  /** A value or [normal, high-contrast] pair. */
134
96
  type HCPair<T> = T | [T, T];
97
+ /** Bare WCAG contrast target: a ratio number or a named preset. */
135
98
  type MinContrast = number | ContrastPreset;
99
+ /**
100
+ * A contrast floor with a pluggable metric.
101
+ *
102
+ * - `number` / `ContrastPreset`: a WCAG ratio (bare form).
103
+ * - `{ wcag }`: WCAG ratio or preset, optionally an HC pair.
104
+ * - `{ apca }`: APCA Lc target (absolute value), optionally an HC pair.
105
+ *
106
+ * The `[normal, highContrast]` pair may live at the outer level
107
+ * (`[4.5, 7]`, `[{ wcag: 4.5 }, { wcag: 7 }]`) or inside the metric
108
+ * (`{ wcag: [4.5, 7] }`, `{ apca: [45, 60] }`).
109
+ */
110
+ type ContrastSpec = number | ContrastPreset | {
111
+ wcag: HCPair<number | ContrastPreset>;
112
+ } | {
113
+ apca: HCPair<number>;
114
+ };
136
115
  type AdaptationMode = 'auto' | 'fixed' | 'static';
137
116
  /** A signed relative offset string, e.g. '+20' or '-15.5'. */
138
117
  type RelativeValue = `+${number}` | `-${number}`;
118
+ /**
119
+ * Force a color to a tone extreme:
120
+ * - `'max'`: the highest tone in the active scheme range/window.
121
+ * - `'min'`: the lowest tone.
122
+ *
123
+ * Under `mode: 'auto'` the extreme inverts in the dark scheme (so `'max'`
124
+ * tracks the inversion and becomes the darkest tone). No `base` required.
125
+ */
126
+ type ExtremeValue = 'max' | 'min';
127
+ /**
128
+ * A tone value as authored on a color.
129
+ * - Number: absolute tone (0–100).
130
+ * - `'+N'` / `'-N'`: relative to the base's tone (requires `base`).
131
+ * - `'max'` / `'min'`: forced to the scheme's tone extreme (no base needed).
132
+ */
133
+ type ToneValue = number | RelativeValue | ExtremeValue;
139
134
  /** Color format for output. */
140
135
  type GlazeColorFormat = 'okhsl' | 'rgb' | 'hsl' | 'oklch';
141
136
  /**
@@ -156,6 +151,15 @@ interface OkhslColor {
156
151
  s: number;
157
152
  l: number;
158
153
  }
154
+ /**
155
+ * Direct OKHST color input — OKHSL with the lightness axis replaced by the
156
+ * contrast-uniform tone axis. `h`: 0–360, `s`: 0–1, `t`: 0–1 (tone).
157
+ */
158
+ interface OkhstColor {
159
+ h: number;
160
+ s: number;
161
+ t: number;
162
+ }
159
163
  /** sRGB components in 0–255 (value-shorthand object form). */
160
164
  interface RgbColor {
161
165
  r: number;
@@ -170,11 +174,12 @@ interface OklchColor {
170
174
  }
171
175
  interface RegularColorDef {
172
176
  /**
173
- * Lightness value (0–100).
174
- * - Number: absolute lightness.
175
- * - String ('+N' / '-N'): relative to base color's lightness (requires `base`).
177
+ * Tone value (0–100, contrast-uniform — see `docs/okhst.md`).
178
+ * - Number: absolute tone.
179
+ * - String ('+N' / '-N'): relative to base color's tone (requires `base`).
180
+ * - `'max'` / `'min'`: force to the scheme's tone extreme (no base needed).
176
181
  */
177
- lightness?: HCPair<number | RelativeValue>;
182
+ tone?: HCPair<ToneValue>;
178
183
  /** Saturation factor applied to the seed saturation (0–1, default: 1). */
179
184
  saturation?: number;
180
185
  /**
@@ -185,15 +190,30 @@ interface RegularColorDef {
185
190
  hue?: number | RelativeValue;
186
191
  /** Name of another color in the same theme (dependent color). */
187
192
  base?: string;
188
- /** WCAG contrast ratio floor against the base color. */
189
- contrast?: HCPair<MinContrast>;
193
+ /**
194
+ * Contrast floor against the base color. A bare number/preset is WCAG;
195
+ * use `{ wcag }` / `{ apca }` to pick the metric. Accepts an HC pair.
196
+ */
197
+ contrast?: HCPair<ContrastSpec>;
190
198
  /** Adaptation mode. Default: 'auto'. */
191
199
  mode?: AdaptationMode;
200
+ /**
201
+ * Whether to flip out-of-bounds results to the opposite side instead of
202
+ * clamping to the extreme. Affects both:
203
+ * - relative `tone`: when `base ± delta` exceeds `[0, 100]`, mirror the
204
+ * delta to the other side of the base.
205
+ * - `contrast`: when the requested direction can't meet the floor, try the
206
+ * opposite side (same as the global `autoFlip`).
207
+ *
208
+ * Defaults to the global `autoFlip` config (default `true`). Set `false`
209
+ * to clamp instead.
210
+ */
211
+ flip?: boolean;
192
212
  /**
193
213
  * Fixed opacity (0–1).
194
214
  * Output includes alpha in the CSS value.
195
215
  * Does not affect contrast resolution — a semi-transparent color
196
- * has no fixed perceived lightness, so `contrast` and `opacity`
216
+ * has no fixed perceived tone, so `contrast` and `opacity`
197
217
  * should not be combined (a console.warn is emitted).
198
218
  */
199
219
  opacity?: number;
@@ -279,12 +299,13 @@ interface MixColorDef {
279
299
  */
280
300
  space?: 'okhsl' | 'srgb';
281
301
  /**
282
- * Minimum WCAG contrast between the base and the resulting color.
302
+ * Minimum contrast between the base and the resulting color.
283
303
  * In 'opaque' mode, adjusts the mix ratio to meet contrast.
284
304
  * In 'transparent' mode, adjusts opacity to meet contrast against the composite.
285
- * Supports [normal, highContrast] pair.
305
+ * A bare number/preset is WCAG; use `{ wcag }` / `{ apca }` to pick the
306
+ * metric. Supports [normal, highContrast] pair.
286
307
  */
287
- contrast?: HCPair<MinContrast>;
308
+ contrast?: HCPair<ContrastSpec>;
288
309
  /**
289
310
  * Whether this color is inherited by child themes created via `extend()`.
290
311
  * Default: true. Set to false to make this color local to the current theme.
@@ -293,14 +314,20 @@ interface MixColorDef {
293
314
  }
294
315
  type ColorDef = RegularColorDef | ShadowColorDef | MixColorDef;
295
316
  type ColorMap = Record<string, ColorDef>;
296
- /** Resolved color for a single scheme variant. */
317
+ /**
318
+ * Resolved color for a single scheme variant.
319
+ *
320
+ * Stored in OKHST: `h` / `s` are OKHSL hue/saturation, `t` is the canonical
321
+ * contrast-uniform tone (0–1, reference eps). Convert to OKHSL lightness via
322
+ * `variantToOkhsl` at the rendering / luminance edges.
323
+ */
297
324
  interface ResolvedColorVariant {
298
325
  /** OKHSL hue (0–360). */
299
326
  h: number;
300
327
  /** OKHSL saturation (0–1). */
301
328
  s: number;
302
- /** OKHSL lightness (0–1). */
303
- l: number;
329
+ /** Canonical tone (0–1, reference eps). */
330
+ t: number;
304
331
  /** Opacity (0–1). Default: 1. */
305
332
  alpha: number;
306
333
  }
@@ -315,24 +342,26 @@ interface ResolvedColor {
315
342
  mode?: AdaptationMode;
316
343
  }
317
344
  /**
318
- * Lightness window value. A `[lo, hi]` tuple (0–100) or `false` to disable
319
- * clamping entirely (equivalent to `[0, 100]`).
345
+ * A scheme tone window.
346
+ * - `[lo, hi]`: OKHSL-lightness endpoints (0100) the authored tone is
347
+ * remapped into, using the reference eps `0.05`. The common form.
348
+ * - `{ lo, hi, eps }`: same, with an explicit render curvature `eps`
349
+ * (advanced — most palettes never need this).
350
+ * - `false`: disable clamping (full range `[0, 100]` at the reference eps).
351
+ * This removes the *boundaries*, not the tone curve.
320
352
  */
321
- type LightnessWindow = false | [number, number];
353
+ type ToneWindow = false | [number, number] | {
354
+ lo: number;
355
+ hi: number;
356
+ eps: number;
357
+ };
322
358
  interface GlazeConfig {
323
- /** Light scheme lightness window [lo, hi]. Default: [10, 100]. Pass `false` to disable clamping. */
324
- lightLightness?: LightnessWindow;
325
- /** Dark scheme lightness window [lo, hi]. Default: [15, 95]. Pass `false` to disable clamping. */
326
- darkLightness?: LightnessWindow;
359
+ /** Light scheme tone window — `[lo, hi]` (default `[10, 100]`), `{ lo, hi, eps }` for advanced eps tuning, or `false` to disable clamping. */
360
+ lightTone?: ToneWindow;
361
+ /** Dark scheme tone window — `[lo, hi]` (default `[15, 95]`), `{ lo, hi, eps }`, or `false` to disable clamping. */
362
+ darkTone?: ToneWindow;
327
363
  /** Saturation reduction factor for dark scheme (0–1). Default: 0.1. */
328
364
  darkDesaturation?: number;
329
- /**
330
- * Möbius beta for dark auto-inversion (0–1).
331
- * Lower values expand subtle near-white distinctions in dark mode.
332
- * Set to 1 for linear (legacy) behavior. Default: 0.5.
333
- * Accepts [normal, highContrast] pair for separate HC tuning.
334
- */
335
- darkCurve?: HCPair<number>;
336
365
  /** State alias names for token export. */
337
366
  states?: {
338
367
  dark?: string;
@@ -343,26 +372,32 @@ interface GlazeConfig {
343
372
  /** Default tuning for all shadow colors. Per-color tuning merges field-by-field. */
344
373
  shadowTuning?: ShadowTuning;
345
374
  /**
346
- * Automatically flip lightness direction when contrast can't be met.
375
+ * Automatically flip tone direction when contrast can't be met.
347
376
  *
348
377
  * When enabled (default `true`), the solver searches the requested
349
- * lightness direction first. If that direction can't reach the target,
378
+ * tone direction first. If that direction can't reach the target,
350
379
  * it tries the opposite direction and uses it when it passes. If neither
351
- * side passes, the lightness is pinned to the requested-direction
380
+ * side passes, the tone is pinned to the requested-direction
352
381
  * extreme and a warning is emitted.
353
382
  *
354
383
  * Set to `false` for strict "no flip" behavior. The opposite
355
384
  * direction is never considered: if the requested direction can't
356
- * meet the target, the lightness is pinned to its extreme (never
357
- * falls back to the originally requested lightness).
385
+ * meet the target, the tone is pinned to its extreme (never
386
+ * falls back to the originally requested tone).
358
387
  */
359
388
  autoFlip?: boolean;
389
+ /**
390
+ * If true, uses a hue-independent "safe" chroma limit across all colors
391
+ * so that scaling saturation never exceeds the sRGB boundary at any hue
392
+ * for the given lightness.
393
+ * @default false
394
+ */
395
+ pastel?: boolean;
360
396
  }
361
397
  interface GlazeConfigResolved {
362
- lightLightness: LightnessWindow;
363
- darkLightness: LightnessWindow;
398
+ lightTone: ToneWindow;
399
+ darkTone: ToneWindow;
364
400
  darkDesaturation: number;
365
- darkCurve: HCPair<number>;
366
401
  states: {
367
402
  dark: string;
368
403
  highContrast: string;
@@ -370,25 +405,30 @@ interface GlazeConfigResolved {
370
405
  modes: Required<GlazeOutputModes>;
371
406
  shadowTuning?: ShadowTuning;
372
407
  autoFlip: boolean;
408
+ pastel: boolean;
373
409
  }
374
410
  /**
375
411
  * Per-instance config override for `glaze.color()` and `glaze()` themes.
376
412
  * Fields that are set take priority over the live global config. Fields
377
413
  * that are omitted fall through to the live global at resolve time.
378
414
  *
379
- * `false` for a lightness window disables clamping (equivalent to `[0, 100]`).
415
+ * `false` for a tone window disables clamping (full range at reference eps).
380
416
  */
381
417
  interface GlazeConfigOverride {
382
- /** Light scheme lightness window, or `false` to disable clamping. */
383
- lightLightness?: LightnessWindow;
384
- /** Dark scheme lightness window, or `false` to disable clamping. */
385
- darkLightness?: LightnessWindow;
418
+ /** Light scheme tone window, or `false` to disable clamping. */
419
+ lightTone?: ToneWindow;
420
+ /** Dark scheme tone window, or `false` to disable clamping. */
421
+ darkTone?: ToneWindow;
386
422
  /** Saturation reduction factor for dark scheme (0–1). */
387
423
  darkDesaturation?: number;
388
- /** Möbius beta for dark auto-inversion. Accepts [normal, hc] pair. */
389
- darkCurve?: HCPair<number>;
390
- /** Whether to auto-flip lightness when contrast can't be met. */
424
+ /** Whether to auto-flip tone when contrast can't be met. */
391
425
  autoFlip?: boolean;
426
+ /**
427
+ * If true, uses a hue-independent "safe" chroma limit across all colors
428
+ * so that scaling saturation never exceeds the sRGB boundary at any hue
429
+ * for the given lightness.
430
+ */
431
+ pastel?: boolean;
392
432
  /**
393
433
  * Shadow tuning defaults. Only meaningful for themes; harmless on
394
434
  * standalone color tokens.
@@ -425,25 +465,28 @@ interface GlazeShadowInput {
425
465
  interface GlazeColorInput {
426
466
  hue: number;
427
467
  saturation: number;
428
- lightness: HCPair<number>;
468
+ tone: HCPair<number | ExtremeValue>;
429
469
  saturationFactor?: number;
430
470
  mode?: AdaptationMode;
471
+ /** Flip out-of-bounds results instead of clamping. Default: global `autoFlip`. */
472
+ flip?: boolean;
431
473
  /**
432
474
  * Fixed opacity (0–1). Output includes alpha in the CSS value.
433
- * Combining with `contrast` is not recommended (perceived lightness
475
+ * Combining with `contrast` is not recommended (perceived tone
434
476
  * becomes unpredictable) — a `console.warn` is emitted in that case.
435
477
  */
436
478
  opacity?: number;
437
479
  /**
438
480
  * Optional dependency on another color. Same semantics as
439
- * `GlazeColorOverrides.base` — `contrast` and relative `lightness`
481
+ * `GlazeColorOverrides.base` — `contrast` and relative `tone`
440
482
  * anchor to the base per scheme.
441
483
  */
442
484
  base?: GlazeColorToken | GlazeColorValue;
443
485
  /**
444
- * WCAG contrast floor against `base`. Requires `base` to be set.
486
+ * Contrast floor against `base`. Requires `base` to be set. A bare
487
+ * number/preset is WCAG; use `{ wcag }` / `{ apca }` to pick the metric.
445
488
  */
446
- contrast?: HCPair<MinContrast>;
489
+ contrast?: HCPair<ContrastSpec>;
447
490
  /**
448
491
  * Optional human-readable name for the token. Used in error and
449
492
  * warning messages (otherwise an internal name like `"value"` is
@@ -463,10 +506,11 @@ interface GlazeColorInput {
463
506
  * Literal object forms:
464
507
  * - `{ h, s, l }` — OKHSL (h: 0–360, s/l: 0–1). Passing 0–100 for `s`/`l`
465
508
  * throws with a hint to use the structured form.
509
+ * - `{ h, s, t }` — OKHST (h: 0–360, s/t: 0–1). Tone in 0–1.
466
510
  * - `{ r, g, b }` — sRGB 0–255.
467
511
  * - `{ l, c, h }` — OKLCh (L/C: 0–1, H: degrees), same as `oklch()` strings.
468
512
  */
469
- type GlazeColorValue = string | OkhslColor | RgbColor | OklchColor;
513
+ type GlazeColorValue = string | OkhslColor | OkhstColor | RgbColor | OklchColor;
470
514
  /** Color overrides for the `from` and value-shorthand inputs. */
471
515
  interface GlazeColorOverrides {
472
516
  /**
@@ -478,33 +522,41 @@ interface GlazeColorOverrides {
478
522
  /** Override seed saturation (0–100). Default: extracted from value. */
479
523
  saturation?: number;
480
524
  /**
481
- * Override lightness. Number is absolute (0–100); `'+N'`/`'-N'` is
482
- * relative to the literal seed (the value passed to `glaze.color()`).
525
+ * Override tone. Number is absolute (0–100, contrast-uniform); `'+N'`/`'-N'`
526
+ * is relative to the literal seed (the value passed to `glaze.color()`);
527
+ * `'max'` / `'min'` force to the scheme's tone extreme.
483
528
  * Supports HCPair for high-contrast.
484
529
  */
485
- lightness?: HCPair<number | RelativeValue>;
530
+ tone?: HCPair<ToneValue>;
486
531
  /** Saturation multiplier on the seed (0–1). Default: 1. */
487
532
  saturationFactor?: number;
488
533
  /**
489
534
  * Adaptation mode. Defaults to `'auto'` for every input form, so
490
535
  * colors automatically adapt between light and dark like an ordinary
491
536
  * theme color. All value-shorthand inputs (strings and literal objects)
492
- * preserve light lightness (`lightLightness: false`) and snapshot
493
- * `globalConfig.darkLightness` on the dark side. Only the structured
494
- * `{ hue, saturation, lightness }` form also snapshots
495
- * `globalConfig.lightLightness`.
537
+ * preserve light tone (`lightTone: false`) and snapshot
538
+ * `globalConfig.darkTone` on the dark side. Only the structured
539
+ * `{ hue, saturation, tone }` form also snapshots
540
+ * `globalConfig.lightTone`.
496
541
  *
497
- * Pass `'fixed'` explicitly to opt back into the legacy linear, non-
498
- * inverting mapping; pass `'static'` to pin the same lightness
542
+ * Pass `'fixed'` explicitly to opt back into the linear, non-
543
+ * inverting mapping; pass `'static'` to pin the same tone
499
544
  * across every variant.
500
545
  */
501
546
  mode?: AdaptationMode;
502
547
  /**
503
- * WCAG contrast floor. By default solved against the literal seed
548
+ * Flip out-of-bounds results (relative `tone` overshoot / unmet
549
+ * `contrast`) to the opposite side instead of clamping. Defaults to
550
+ * the global `autoFlip`.
551
+ */
552
+ flip?: boolean;
553
+ /**
554
+ * Contrast floor. By default solved against the literal seed
504
555
  * (the value itself); when `base` is set, solved against the base's
505
- * resolved variant per scheme. Same shape as `RegularColorDef.contrast`.
556
+ * resolved variant per scheme. Same shape as `RegularColorDef.contrast`
557
+ * (bare number/preset = WCAG; `{ wcag }` / `{ apca }` to pick the metric).
506
558
  */
507
- contrast?: HCPair<MinContrast>;
559
+ contrast?: HCPair<ContrastSpec>;
508
560
  /**
509
561
  * Optional dependency on another color. Accepts either a
510
562
  * `GlazeColorToken` (returned by another `glaze.color()`) or a raw
@@ -514,14 +566,14 @@ interface GlazeColorOverrides {
514
566
  * When set:
515
567
  * - `contrast` is solved against the base's resolved variant
516
568
  * per-scheme (light / dark / lightContrast / darkContrast).
517
- * - Relative `lightness: '+N'` / `'-N'` is anchored to the base's
518
- * lightness per-scheme (matches theme behavior for dependent colors).
569
+ * - Relative `tone: '+N'` / `'-N'` is anchored to the base's
570
+ * tone per-scheme (matches theme behavior for dependent colors).
519
571
  * - Relative `hue: '+N'` / `'-N'` still anchors to the seed (the
520
572
  * value passed to `glaze.color()`), not the base.
521
573
  * - When the base was created via the structured form (with explicit
522
- * `hue`/`saturation`/`lightness`), it is resolved at full range
523
- * (`lightLightness: false`) for the linking math — ensuring the
524
- * contrast/lightness anchor matches the input lightness, not the
574
+ * `hue`/`saturation`/`tone`), it is resolved at full range
575
+ * (`lightTone: false`) for the linking math — ensuring the
576
+ * contrast/tone anchor matches the input tone, not the
525
577
  * windowed output. The base's own `.resolve()` output is unaffected.
526
578
  *
527
579
  * The base token's `.resolve()` is called lazily on first resolve and
@@ -531,7 +583,7 @@ interface GlazeColorOverrides {
531
583
  base?: GlazeColorToken | GlazeColorValue;
532
584
  /**
533
585
  * Fixed opacity (0–1). Output includes alpha in the CSS value.
534
- * Combining with `contrast` is not recommended (perceived lightness
586
+ * Combining with `contrast` is not recommended (perceived tone
535
587
  * becomes unpredictable) — a `console.warn` is emitted in that case.
536
588
  */
537
589
  opacity?: number;
@@ -548,7 +600,7 @@ interface GlazeColorOverrides {
548
600
  *
549
601
  * ```ts
550
602
  * glaze.color({ from: '#1a1a2e', base: bg, contrast: 'AA' })
551
- * glaze.color({ from: { r: 38, g: 252, b: 178 }, lightness: '+10' })
603
+ * glaze.color({ from: { r: 38, g: 252, b: 178 }, tone: '+10' })
552
604
  * ```
553
605
  */
554
606
  interface GlazeFromInput extends GlazeColorOverrides {
@@ -629,12 +681,13 @@ interface GlazeColorTokenExport {
629
681
  interface GlazeColorInputExport {
630
682
  hue: number;
631
683
  saturation: number;
632
- lightness: HCPair<number>;
684
+ tone: HCPair<number | ExtremeValue>;
633
685
  saturationFactor?: number;
634
686
  mode?: AdaptationMode;
687
+ flip?: boolean;
635
688
  opacity?: number;
636
689
  base?: GlazeColorTokenExport | GlazeColorValue;
637
- contrast?: HCPair<MinContrast>;
690
+ contrast?: HCPair<ContrastSpec>;
638
691
  name?: string;
639
692
  }
640
693
  /**
@@ -644,10 +697,11 @@ interface GlazeColorInputExport {
644
697
  interface GlazeColorOverridesExport {
645
698
  hue?: number | RelativeValue;
646
699
  saturation?: number;
647
- lightness?: HCPair<number | RelativeValue>;
700
+ tone?: HCPair<ToneValue>;
648
701
  saturationFactor?: number;
649
702
  mode?: AdaptationMode;
650
- contrast?: HCPair<MinContrast>;
703
+ flip?: boolean;
704
+ contrast?: HCPair<ContrastSpec>;
651
705
  base?: GlazeColorTokenExport | GlazeColorValue;
652
706
  opacity?: number;
653
707
  name?: string;
@@ -657,6 +711,8 @@ interface GlazeTheme {
657
711
  readonly hue: number;
658
712
  /** The saturation seed (0–100). */
659
713
  readonly saturation: number;
714
+ /** The effective config for this theme. */
715
+ getConfig(): GlazeConfigResolved;
660
716
  /** Add/replace colors (additive merge with existing definitions). */
661
717
  colors(defs: ColorMap): void;
662
718
  /** Get a color definition by name. */
@@ -803,7 +859,7 @@ type PaletteInput = Record<string, GlazeTheme>;
803
859
  * Create a single-hue glaze theme.
804
860
  *
805
861
  * An optional `config` override can be supplied to customize the resolve
806
- * behavior for this theme (lightness windows, dark curve, etc.). The
862
+ * behavior for this theme (tone windows, etc.). The
807
863
  * override is **merged over the live global config at resolve time** —
808
864
  * the theme still reacts to later `configure()` calls for fields it
809
865
  * didn't override.
@@ -814,7 +870,7 @@ type PaletteInput = Record<string, GlazeTheme>;
814
870
  * // or shorthand:
815
871
  * const primary = glaze({ hue: 280, saturation: 80 });
816
872
  * // with config override:
817
- * const raw = glaze(280, 80, { lightLightness: false });
873
+ * const raw = glaze(280, 80, { lightTone: false });
818
874
  * ```
819
875
  */
820
876
  declare function glaze(hueOrOptions: number | {
@@ -827,7 +883,7 @@ declare namespace glaze {
827
883
  var from: (data: GlazeThemeExport) => GlazeTheme;
828
884
  var color: (input: GlazeFromInput | GlazeColorInput | GlazeColorValue, config?: GlazeConfigOverride) => GlazeColorToken;
829
885
  var shadow: (input: GlazeShadowInput) => ResolvedColorVariant;
830
- var format: (variant: ResolvedColorVariant, colorFormat?: GlazeColorFormat) => string;
886
+ var format: (variant: ResolvedColorVariant, colorFormat?: GlazeColorFormat, pastel?: boolean) => string;
831
887
  var fromHex: (hex: string) => GlazeTheme;
832
888
  var fromRgb: (r: number, g: number, b: number) => GlazeTheme;
833
889
  var colorFrom: (data: GlazeColorTokenExport) => GlazeColorToken;
@@ -835,24 +891,92 @@ declare namespace glaze {
835
891
  var resetConfig: () => void;
836
892
  }
837
893
  //#endregion
894
+ //#region src/okhst.d.ts
895
+ /**
896
+ * Reference eps for the OKHST color space. WCAG 2 contrast is
897
+ * `(Y_hi + 0.05) / (Y_lo + 0.05)`, so an eps of `0.05` makes equal tone
898
+ * steps yield equal WCAG contrast. This is the canonical eps used by
899
+ * `okhst()` input, `{ h, s, t }` input, stored `ResolvedColorVariant.t`,
900
+ * relative `tone` offsets, and the contrast solver.
901
+ */
902
+ declare const REF_EPS = 0.05;
903
+ /**
904
+ * Map a luminance `Y` (0–1) to tone (0–100) at the given eps.
905
+ * `toneFromY(0) === 0` and `toneFromY(1) === 100` for any eps.
906
+ */
907
+ declare function toneFromY(y: number, eps?: number): number;
908
+ /** Map a tone (0–100) back to luminance (0–1). Inverse of {@link toneFromY}. */
909
+ declare function yFromTone(t: number, eps?: number): number;
910
+ /** OKHSL lightness (0–1) -> tone (0–100). */
911
+ declare function toTone(l: number, eps?: number): number;
912
+ /** Tone (0–100) -> OKHSL lightness (0–1). Inverse of {@link toTone}. */
913
+ declare function fromTone(t: number, eps?: number): number;
914
+ /** Convert OKHST `{ h, s, t }` (t in 0–1) to OKHSL `{ h, s, l }`. */
915
+ declare function okhstToOkhsl(c: {
916
+ h: number;
917
+ s: number;
918
+ t: number;
919
+ }): {
920
+ h: number;
921
+ s: number;
922
+ l: number;
923
+ };
924
+ /** Convert OKHSL `{ h, s, l }` to OKHST `{ h, s, t }` (t in 0–1). */
925
+ declare function okhslToOkhst(c: {
926
+ h: number;
927
+ s: number;
928
+ l: number;
929
+ }): {
930
+ h: number;
931
+ s: number;
932
+ t: number;
933
+ };
934
+ /**
935
+ * Edge adapter: a resolved variant stores canonical tone `t` (0–1). Convert
936
+ * it to the OKHSL `{ h, s, l }` the formatters and luminance pipeline expect.
937
+ */
938
+ declare function variantToOkhsl(v: {
939
+ h: number;
940
+ s: number;
941
+ t: number;
942
+ }): {
943
+ h: number;
944
+ s: number;
945
+ l: number;
946
+ };
947
+ //#endregion
838
948
  //#region src/okhsl-color-math.d.ts
839
949
  /**
840
950
  * OKHSL color math primitives for the glaze theme generator.
841
951
  *
842
- * Provides bidirectional OKHSL ↔ sRGB conversion, relative luminance
843
- * computation for WCAG 2 contrast calculations, and multi-format output
844
- * (okhsl, rgb, hsl, oklch).
952
+ * Provides bidirectional OKHSL ↔ sRGB conversion, luminance computation
953
+ * for both contrast metrics (WCAG 2 relative luminance and APCA screen
954
+ * luminance `Ys`), and multi-format output (okhsl, rgb, hsl, oklch).
845
955
  */
846
956
  type Vec3 = [number, number, number];
957
+ /**
958
+ * OKHSL toe function: maps OKLab lightness L to perceptual lightness l.
959
+ * Exported for the OKHST tone transfers in `okhst.ts`.
960
+ */
961
+ /**
962
+ * OKHSL lightness of the gamut cusp for a hue — the lightness where the
963
+ * realizable chroma peaks. Reuses the same `find_cusp` OKHSL already runs for
964
+ * its `s` normalization (no new color math); the OKLab cusp lightness is run
965
+ * through the OKHSL `toe` and clamped to `[0.001, 0.999]` so divisions that
966
+ * key off it stay safe. Cached per (rounded) hue.
967
+ *
968
+ * @param h Hue, 0–360.
969
+ */
970
+ declare function cuspLightness(h: number): number;
847
971
  /**
848
972
  * Convert OKHSL (h: 0–360, s: 0–1, l: 0–1) to OKLab [L, a, b].
849
973
  */
850
- declare function okhslToOklab(h: number, s: number, l: number): [number, number, number];
974
+ declare function okhslToOklab(h: number, s: number, l: number, pastel?: boolean): [number, number, number];
851
975
  /**
852
976
  * Convert OKHSL (h: 0–360, s: 0–1, l: 0–1) to linear sRGB.
853
977
  * Channels may exceed [0, 1] near gamut boundaries — caller must clamp if needed.
854
978
  */
855
- declare function okhslToLinearSrgb(h: number, s: number, l: number): [number, number, number];
979
+ declare function okhslToLinearSrgb(h: number, s: number, l: number, pastel?: boolean): [number, number, number];
856
980
  /**
857
981
  * Compute relative luminance Y from linear sRGB channels.
858
982
  * Per WCAG 2: Y = 0.2126·R + 0.7152·G + 0.0722·B
@@ -865,7 +989,7 @@ declare function contrastRatioFromLuminance(yA: number, yB: number): number;
865
989
  /**
866
990
  * Convert OKHSL to gamma-encoded sRGB (clamped to 0–1).
867
991
  */
868
- declare function okhslToSrgb(h: number, s: number, l: number): [number, number, number];
992
+ declare function okhslToSrgb(h: number, s: number, l: number, pastel?: boolean): [number, number, number];
869
993
  /**
870
994
  * Compute WCAG 2 relative luminance from linear sRGB, matching the browser
871
995
  * rendering pipeline: gamma-encode, clamp to sRGB gamut [0,1], then linearize.
@@ -877,12 +1001,12 @@ declare function gamutClampedLuminance(linearRgb: [number, number, number]): num
877
1001
  * Input: [L, a, b] where L: 0–1, a/b: roughly -0.5 to 0.5.
878
1002
  * Returns [h, s, l] where h: 0–360, s: 0–1, l: 0–1.
879
1003
  */
880
- declare const oklabToOkhsl: (lab: Vec3) => Vec3;
1004
+ declare const oklabToOkhsl: (lab: Vec3, pastel?: boolean) => Vec3;
881
1005
  /**
882
1006
  * Convert gamma-encoded sRGB (0–1 per channel) to OKHSL.
883
1007
  * Returns [h, s, l] where h: 0–360, s: 0–1, l: 0–1.
884
1008
  */
885
- declare function srgbToOkhsl(rgb: [number, number, number]): [number, number, number];
1009
+ declare function srgbToOkhsl(rgb: [number, number, number], pastel?: boolean): [number, number, number];
886
1010
  /**
887
1011
  * Convert CSS HSL (sRGB-based) to gamma-encoded sRGB [r, g, b] in 0–1 range.
888
1012
  * h: 0–360, s: 0–1, l: 0–1.
@@ -912,23 +1036,23 @@ declare function parseHexAlpha(hex: string): {
912
1036
  * Format OKHSL values as a CSS `okhsl(H S% L%)` string.
913
1037
  * h: 0–360, s: 0–100, l: 0–100 (percentage scale for s and l).
914
1038
  */
915
- declare function formatOkhsl(h: number, s: number, l: number): string;
1039
+ declare function formatOkhsl(h: number, s: number, l: number, pastel?: boolean): string;
916
1040
  /**
917
1041
  * Format OKHSL values as a CSS `rgb(R G B)` string.
918
1042
  * Uses 2 decimal places to avoid 8-bit quantization contrast loss.
919
1043
  * h: 0–360, s: 0–100, l: 0–100 (percentage scale for s and l).
920
1044
  */
921
- declare function formatRgb(h: number, s: number, l: number): string;
1045
+ declare function formatRgb(h: number, s: number, l: number, pastel?: boolean): string;
922
1046
  /**
923
1047
  * Format OKHSL values as a CSS `hsl(H S% L%)` string.
924
1048
  * h: 0–360, s: 0–100, l: 0–100 (percentage scale for s and l).
925
1049
  */
926
- declare function formatHsl(h: number, s: number, l: number): string;
1050
+ declare function formatHsl(h: number, s: number, l: number, pastel?: boolean): string;
927
1051
  /**
928
1052
  * Format OKHSL values as a CSS `oklch(L C H)` string.
929
1053
  * h: 0–360, s: 0–100, l: 0–100 (percentage scale for s and l).
930
1054
  */
931
- declare function formatOklch(h: number, s: number, l: number): string;
1055
+ declare function formatOklch(h: number, s: number, l: number, pastel?: boolean): string;
932
1056
  //#endregion
933
- export { type AdaptationMode, type ColorDef, type ColorMap, type ContrastPreset, type FindLightnessForContrastOptions, type FindLightnessForContrastResult, type FindValueForMixContrastOptions, type FindValueForMixContrastResult, type GlazeColorCssOptions, type GlazeColorFormat, type GlazeColorInput, type GlazeColorInputExport, type GlazeColorOverrides, type GlazeColorOverridesExport, type GlazeColorToken, type GlazeColorTokenExport, type GlazeColorValue, type GlazeConfig, type GlazeConfigOverride, type GlazeConfigResolved, type GlazeCssOptions, type GlazeCssResult, type GlazeExtendOptions, type GlazeFromInput, type GlazeJsonOptions, type GlazeOutputModes, type GlazePalette, type GlazePaletteExportOptions, type GlazePaletteOptions, type GlazeShadowInput, type GlazeTheme, type GlazeThemeExport, type GlazeTokenOptions, type HCPair, type HexColor, type LightnessWindow, type MinContrast, type MixColorDef, type OkhslColor, type OklchColor, type RegularColorDef, type RelativeValue, type ResolvedColor, type ResolvedColorVariant, type RgbColor, type ShadowColorDef, type ShadowTuning, contrastRatioFromLuminance, findLightnessForContrast, findValueForMixContrast, formatHsl, formatOkhsl, formatOklch, formatRgb, gamutClampedLuminance, glaze, hslToSrgb, okhslToLinearSrgb, okhslToOklab, okhslToSrgb, oklabToOkhsl, parseHex, parseHexAlpha, relativeLuminanceFromLinearRgb, resolveMinContrast, srgbToOkhsl };
1057
+ export { type AdaptationMode, type ColorDef, type ColorMap, type ContrastPreset, type ContrastSpec, type ExtremeValue, type FindToneForContrastOptions, type FindToneForContrastResult, type FindValueForMixContrastOptions, type FindValueForMixContrastResult, type GlazeColorCssOptions, type GlazeColorFormat, type GlazeColorInput, type GlazeColorInputExport, type GlazeColorOverrides, type GlazeColorOverridesExport, type GlazeColorToken, type GlazeColorTokenExport, type GlazeColorValue, type GlazeConfig, type GlazeConfigOverride, type GlazeConfigResolved, type GlazeCssOptions, type GlazeCssResult, type GlazeExtendOptions, type GlazeFromInput, type GlazeJsonOptions, type GlazeOutputModes, type GlazePalette, type GlazePaletteExportOptions, type GlazePaletteOptions, type GlazeShadowInput, type GlazeTheme, type GlazeThemeExport, type GlazeTokenOptions, type HCPair, type HexColor, type MinContrast, type MixColorDef, type OkhslColor, type OkhstColor, type OklchColor, REF_EPS, type RegularColorDef, type RelativeValue, type ResolvedColor, type ResolvedColorVariant, type ResolvedContrast, type RgbColor, type ShadowColorDef, type ShadowTuning, type ToneValue, type ToneWindow, apcaContrast, contrastRatioFromLuminance, cuspLightness, findToneForContrast, findValueForMixContrast, formatHsl, formatOkhsl, formatOklch, formatRgb, fromTone, gamutClampedLuminance, glaze, hslToSrgb, okhslToLinearSrgb, okhslToOkhst, okhslToOklab, okhslToSrgb, okhstToOkhsl, oklabToOkhsl, parseHex, parseHexAlpha, relativeLuminanceFromLinearRgb, resolveContrastForMode, resolveMinContrast, srgbToOkhsl, toTone, toneFromY, variantToOkhsl, yFromTone };
934
1058
  //# sourceMappingURL=index.d.mts.map