@tenphi/glaze 1.1.1 → 1.3.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.cts CHANGED
@@ -62,6 +62,24 @@ declare function resolveMinContrast(value: MinContrast$1): number;
62
62
  * selected spec rather than an outer pair).
63
63
  */
64
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;
65
83
  /**
66
84
  * APCA lightness contrast (Lc), signed: positive for dark text on light bg,
67
85
  * negative for light text on dark bg. Inputs are screen luminances (0–1).
@@ -88,6 +106,19 @@ interface FindToneForContrastOptions {
88
106
  initialDirection?: 'lighter' | 'darker';
89
107
  /** Auto-flip tone direction when contrast can't be met. Default: false. */
90
108
  flip?: boolean;
109
+ /**
110
+ * When `flip` is on and *both* directions meet the target, keep
111
+ * `initialDirection` instead of taking whichever result lands nearer the
112
+ * preferred tone. Default: false (nearest wins).
113
+ *
114
+ * The nearest-wins tie-break is unstable along a ramp of targets: which side
115
+ * is nearer shifts as the target grows, so a color can swap sides between two
116
+ * adjacent targets. Set this when a caller needs the side to be a property of
117
+ * the color rather than of the target — the manual contrast level does. The
118
+ * flip itself is unaffected: an initial direction that cannot reach the
119
+ * target still falls back to the opposite side.
120
+ */
121
+ preferInitial?: boolean;
91
122
  /** Use the hue-independent "safe" chroma boundary. Default: false. */
92
123
  pastel?: boolean;
93
124
  }
@@ -200,7 +231,14 @@ type GlazeColorFormat = 'okhsl' | 'okhst' | 'rgb' | 'hsl' | 'oklch';
200
231
  interface GlazeOutputModes {
201
232
  /** Include dark scheme variants. Default: true. */
202
233
  dark?: boolean;
203
- /** Include high-contrast variants (both light-HC and dark-HC). Default: false. */
234
+ /**
235
+ * Include high-contrast variants (both light-HC and dark-HC). Default: false.
236
+ *
237
+ * Inert while a global `contrastLevel` is set: a manual level has no separate
238
+ * high-contrast tier, so this reads as "emit high-contrast variants when
239
+ * contrast is automatic".
240
+ * @see GlazeConfig.contrastLevel
241
+ */
204
242
  highContrast?: boolean;
205
243
  }
206
244
  /** Hex color string for DX hints. Runtime validation in `parseHex()`. */
@@ -248,6 +286,26 @@ interface RegularColorDef {
248
286
  * - String ('+N' / '-N'): relative to the theme seed hue.
249
287
  */
250
288
  hue?: number | RelativeValue;
289
+ /**
290
+ * Dark-scheme hue override. Applies to the `dark` and `darkContrast`
291
+ * variants; falls back to `hue` when omitted.
292
+ * - Number: absolute hue (0–360).
293
+ * - String ('+N' / '-N'): relative to the theme's **dark** seed hue
294
+ * (`GlazeTheme.darkHue`, itself defaulting to the light seed hue).
295
+ *
296
+ * Ignored under `mode: 'static'`, which pins one value across all schemes.
297
+ */
298
+ darkHue?: number | RelativeValue;
299
+ /**
300
+ * Dark-scheme saturation factor (0–1) applied to the dark seed
301
+ * saturation. Applies to the `dark` and `darkContrast` variants; falls
302
+ * back to `saturation` when omitted.
303
+ *
304
+ * When set, the global `darkDesaturation` reduction is **not** applied on
305
+ * top — the resulting saturation is taken literally. Ignored under
306
+ * `mode: 'static'`.
307
+ */
308
+ darkSaturation?: number;
251
309
  /** Name of another color in the same theme (dependent color). */
252
310
  base?: string;
253
311
  /**
@@ -475,10 +533,38 @@ interface GlazeConfig {
475
533
  dark?: string;
476
534
  highContrast?: string;
477
535
  };
478
- /** Which scheme variants to include in exports. Default: both true. */
536
+ /**
537
+ * Which scheme variants to include in exports. Defaults: `dark: true`,
538
+ * `highContrast: false`.
539
+ */
479
540
  modes?: GlazeOutputModes;
480
541
  /** Default tuning for all shadow colors. Per-color tuning merges field-by-field. */
481
542
  shadowTuning?: ShadowTuning;
543
+ /**
544
+ * Manual contrast level — a 0–100 slider from normal contrast (`0`) to high
545
+ * contrast (`100`), or `'auto'` (the default) to keep the two-tier
546
+ * normal + high-contrast model.
547
+ *
548
+ * With a number, Glaze resolves the `light` / `dark` variants *at* that
549
+ * level and stops emitting a separate high-contrast tier:
550
+ * `lightContrast` / `darkContrast` mirror their normal counterparts and
551
+ * `modes.highContrast` defaults to `false`. Level `0` is therefore "normal
552
+ * contrast, no high-contrast tier"; `100` is "the high-contrast scheme as
553
+ * the only scheme".
554
+ *
555
+ * The level interpolates all three things that make high contrast differ:
556
+ * authored `[normal, highContrast]` pairs, the tone-window widening, and
557
+ * the `AA → AAA` / APCA `+15 Lc` escalation. Contrast floors are re-solved
558
+ * at the interpolated target, so every level is a solution rather than an
559
+ * approximation, and a color keeps to one side of its base as the level moves.
560
+ *
561
+ * Pass `'auto'` to leave manual mode; `configure()` never clears a field by
562
+ * omission. See `docs/api.md` for the ramp's edge cases (un-interpolable
563
+ * pairs, side changes) and the export-freeze rule.
564
+ *
565
+ * @default 'auto'
566
+ */
567
+ contrastLevel?: number | 'auto';
482
568
  /**
483
569
  * Automatically flip tone direction when contrast can't be met.
484
570
  *
@@ -513,6 +599,12 @@ interface GlazeConfigResolved {
513
599
  modes: Required<GlazeOutputModes>;
514
600
  shadowTuning?: ShadowTuning;
515
601
  autoFlip: boolean;
602
+ /**
603
+ * Manual contrast level (0–100), or `'auto'` for the two-tier
604
+ * normal + high-contrast model.
605
+ * @see GlazeConfig.contrastLevel
606
+ */
607
+ contrastLevel: number | 'auto';
516
608
  /**
517
609
  * Instance-level pastel default (`def.pastel ?? config.pastel`).
518
610
  * Not set via `glaze.configure()` — only via per-theme / per-token
@@ -538,6 +630,17 @@ interface GlazeConfigOverride {
538
630
  darkDesaturation?: number;
539
631
  /** Whether to auto-flip tone when contrast can't be met. */
540
632
  autoFlip?: boolean;
633
+ /**
634
+ * Manual contrast level (0–100) for this instance, or `'auto'` to opt out
635
+ * of a global level and keep the two-tier normal + high-contrast model.
636
+ *
637
+ * Only an instance-authored level is frozen into `.export()` snapshots — a
638
+ * level inherited from the global config is treated as a live preference and
639
+ * re-read at restore time.
640
+ *
641
+ * @see GlazeConfig.contrastLevel
642
+ */
643
+ contrastLevel?: number | 'auto';
541
644
  /**
542
645
  * Instance-level pastel default for colors that omit per-color `pastel`.
543
646
  * Not available on `glaze.configure()` — set here or per-color.
@@ -572,6 +675,10 @@ interface GlazeThemeExport {
572
675
  version?: number;
573
676
  hue: number;
574
677
  saturation: number;
678
+ /** Dark-scheme seed hue (0–360). Omitted when the theme reuses `hue`. */
679
+ darkHue?: number;
680
+ /** Dark-scheme seed saturation (0–100). Omitted when the theme reuses `saturation`. */
681
+ darkSaturation?: number;
575
682
  colors: ColorMap;
576
683
  /**
577
684
  * Effective config freeze from `.export()` —
@@ -604,6 +711,15 @@ interface GlazeColorInput {
604
711
  saturation: number;
605
712
  tone: HCPair<number | ExtremeValue>;
606
713
  saturationFactor?: number;
714
+ /**
715
+ * Dark-scheme hue. Number is absolute (0–360); `'+N'`/`'-N'` is relative
716
+ * to the dark seed hue, which defaults to `hue`. Falls back to `hue`.
717
+ */
718
+ darkHue?: number | RelativeValue;
719
+ /** Dark-scheme seed saturation (0–100). Defaults to `saturation`. */
720
+ darkSaturation?: number;
721
+ /** Dark-scheme multiplier on the dark seed (0–1). Defaults to `saturationFactor`. */
722
+ darkSaturationFactor?: number;
607
723
  mode?: AdaptationMode;
608
724
  /** Flip out-of-bounds results instead of clamping. Default: global `autoFlip`. */
609
725
  autoFlip?: boolean;
@@ -673,6 +789,23 @@ interface GlazeColorOverrides {
673
789
  hue?: number | RelativeValue;
674
790
  /** Override seed saturation (0–100). Default: extracted from value. */
675
791
  saturation?: number;
792
+ /**
793
+ * Dark-scheme hue. Number is absolute (0–360); `'+N'`/`'-N'` is relative
794
+ * to the dark seed hue, which defaults to the (possibly overridden) seed
795
+ * hue. Falls back to `hue` when omitted.
796
+ */
797
+ darkHue?: number | RelativeValue;
798
+ /**
799
+ * Dark-scheme seed saturation (0–100). Defaults to `saturation`. When set,
800
+ * the global `darkDesaturation` reduction is not applied on top.
801
+ */
802
+ darkSaturation?: number;
803
+ /**
804
+ * Dark-scheme multiplier on the dark seed (0–1). Defaults to
805
+ * `saturationFactor`. When set, the global `darkDesaturation` reduction is
806
+ * not applied on top.
807
+ */
808
+ darkSaturationFactor?: number;
676
809
  /**
677
810
  * Override tone. Number is absolute (0–100, contrast-uniform); `'+N'`/`'-N'`
678
811
  * is relative to the literal seed (the value passed to `glaze.color()`);
@@ -889,6 +1022,9 @@ interface GlazeColorInputExport {
889
1022
  saturation: number;
890
1023
  tone: HCPair<number | ExtremeValue>;
891
1024
  saturationFactor?: number;
1025
+ darkHue?: number | RelativeValue;
1026
+ darkSaturation?: number;
1027
+ darkSaturationFactor?: number;
892
1028
  mode?: AdaptationMode;
893
1029
  autoFlip?: boolean;
894
1030
  opacity?: number;
@@ -905,6 +1041,9 @@ interface GlazeColorInputExport {
905
1041
  interface GlazeColorOverridesExport {
906
1042
  hue?: number | RelativeValue;
907
1043
  saturation?: number;
1044
+ darkHue?: number | RelativeValue;
1045
+ darkSaturation?: number;
1046
+ darkSaturationFactor?: number;
908
1047
  tone?: HCPair<ToneValue>;
909
1048
  saturationFactor?: number;
910
1049
  mode?: AdaptationMode;
@@ -916,11 +1055,33 @@ interface GlazeColorOverridesExport {
916
1055
  pastel?: boolean;
917
1056
  role?: RoleInput;
918
1057
  }
1058
+ /**
1059
+ * The hue/saturation seed pair a theme resolves against.
1060
+ *
1061
+ * `darkHue` / `darkSaturation` are a separate seed for the `dark` and
1062
+ * `darkContrast` variants; each falls back to its light counterpart. Setting
1063
+ * `darkSaturation` opts the theme out of the global `darkDesaturation`
1064
+ * reduction — the authored value is used literally.
1065
+ */
1066
+ interface GlazeThemeSeed {
1067
+ /** Light-scheme hue seed (0–360). */
1068
+ hue: number;
1069
+ /** Light-scheme saturation seed (0–100). */
1070
+ saturation: number;
1071
+ /** Dark-scheme hue seed (0–360). Defaults to `hue`. */
1072
+ darkHue?: number;
1073
+ /** Dark-scheme saturation seed (0–100). Defaults to `saturation`. */
1074
+ darkSaturation?: number;
1075
+ }
919
1076
  interface GlazeTheme {
920
1077
  /** The hue seed (0–360). */
921
1078
  readonly hue: number;
922
1079
  /** The saturation seed (0–100). */
923
1080
  readonly saturation: number;
1081
+ /** The dark-scheme hue seed (0–360), or `undefined` when `hue` is reused. */
1082
+ readonly darkHue: number | undefined;
1083
+ /** The dark-scheme saturation seed (0–100), or `undefined` when `saturation` is reused. */
1084
+ readonly darkSaturation: number | undefined;
924
1085
  /** The effective config for this theme. */
925
1086
  getConfig(): GlazeConfigResolved;
926
1087
  /** Add/replace colors (additive merge with existing definitions). */
@@ -988,6 +1149,10 @@ interface GlazeTheme {
988
1149
  interface GlazeExtendOptions {
989
1150
  hue?: number;
990
1151
  saturation?: number;
1152
+ /** Replace the dark-scheme hue seed (0–360). Defaults to the parent's. */
1153
+ darkHue?: number;
1154
+ /** Replace the dark-scheme saturation seed (0–100). Defaults to the parent's. */
1155
+ darkSaturation?: number;
991
1156
  colors?: ColorMap;
992
1157
  /** Config override for the child theme. Merged with the parent's override. */
993
1158
  config?: GlazeConfigOverride;
@@ -1341,19 +1506,23 @@ type PaletteInput = Record<string, GlazeTheme>;
1341
1506
  * the theme still reacts to later `configure()` calls for fields it
1342
1507
  * didn't override.
1343
1508
  *
1509
+ * The object form also accepts `darkHue` / `darkSaturation` — a separate
1510
+ * seed pair for the dark and dark-high-contrast schemes. Both default to
1511
+ * their light counterparts, and an explicit `darkSaturation` opts the theme
1512
+ * out of the global `darkDesaturation` reduction.
1513
+ *
1344
1514
  * @example
1345
1515
  * ```ts
1346
1516
  * const primary = glaze(280, 80);
1347
1517
  * // or shorthand:
1348
1518
  * const primary = glaze({ hue: 280, saturation: 80 });
1519
+ * // with a retuned dark seed:
1520
+ * const primary = glaze({ hue: 280, saturation: 80, darkHue: 268, darkSaturation: 65 });
1349
1521
  * // with config override:
1350
1522
  * const raw = glaze(280, 80, { lightTone: false });
1351
1523
  * ```
1352
1524
  */
1353
- declare function glaze(hueOrOptions: number | {
1354
- hue: number;
1355
- saturation: number;
1356
- }, saturation?: number, config?: GlazeConfigOverride): GlazeTheme;
1525
+ declare function glaze(hueOrOptions: number | GlazeThemeSeed, saturation?: number, config?: GlazeConfigOverride): GlazeTheme;
1357
1526
  declare namespace glaze {
1358
1527
  var configure: (config: GlazeConfig) => void;
1359
1528
  var palette: (themes: PaletteInput, options?: GlazePaletteOptions) => GlazePalette;
@@ -1388,6 +1557,11 @@ interface HuePlan {
1388
1557
  }
1389
1558
  interface ChannelCtx {
1390
1559
  seedHue: number;
1560
+ /**
1561
+ * Dark-scheme seed hue, when the theme authored one. Drives the dark
1562
+ * `--{baseName}-hue` value; falls back to `seedHue`.
1563
+ */
1564
+ darkSeedHue?: number;
1391
1565
  /** Theme-level hue var base name (without `--` / `-hue`). */
1392
1566
  baseName: string;
1393
1567
  /** Token / custom-property name prefix used for hue var naming (`brand-` etc.). */
@@ -1632,5 +1806,5 @@ declare function srgbToHex(rgb: [number, number, number]): `#${string}`;
1632
1806
  */
1633
1807
  declare function okhslToOklch(h: number, s: number, l: number, pastel?: boolean): [number, number, number];
1634
1808
  //#endregion
1635
- 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 GlazeDtcgOptions, type GlazeDtcgResolverContextNames, type GlazeDtcgResolverDocument, type GlazeDtcgResolverOptions, type GlazeDtcgResult, type GlazeExportKind, type GlazeExportVersion, type GlazeExtendOptions, type GlazeFromInput, type GlazeJsonOptions, type GlazeOutputModes, type GlazePalette, type GlazePaletteExport, type GlazePaletteExportOptions, type GlazePaletteOptions, type GlazeShadowInput, type GlazeTailwindOptions, type GlazeTheme, type GlazeThemeExport, type GlazeTokenOptions, type HCPair, type HexColor, type HueDeclaration, type HuePlan, 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 RgbColor, type Role, type RoleInput, type ShadowColorDef, type ShadowTuning, type ToneValue, type ToneWindow, apcaContrast, assertAllPastel, assertNativeFormat, contrastRatioFromLuminance, cuspLightness, findToneForContrast, findValueForMixContrast, formatHsl, formatOkhsl, formatOkhst, formatOklch, formatRgb, fromTone, gamutClampedLuminance, glaze, hslToSrgb, inferRoleFromName, isColorTokenExport, isPaletteExport, isThemeExport, normalizeRole, okhslToLinearSrgb, okhslToOkhst, okhslToOklab, okhslToOklch, okhslToSrgb, okhstToOkhsl, oklabToOkhsl, oppositeRole, parseHex, parseHexAlpha, relativeLuminanceFromLinearRgb, resolveApcaTarget, resolveContrastForMode, resolveMinContrast, roleToPolarity, srgbToHex, srgbToOkhsl, toTone, toneFromY, variantToOkhsl, yFromTone };
1809
+ 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 GlazeDtcgOptions, type GlazeDtcgResolverContextNames, type GlazeDtcgResolverDocument, type GlazeDtcgResolverOptions, type GlazeDtcgResult, type GlazeExportKind, type GlazeExportVersion, type GlazeExtendOptions, type GlazeFromInput, type GlazeJsonOptions, type GlazeOutputModes, type GlazePalette, type GlazePaletteExport, type GlazePaletteExportOptions, type GlazePaletteOptions, type GlazeShadowInput, type GlazeTailwindOptions, type GlazeTheme, type GlazeThemeExport, type GlazeThemeSeed, type GlazeTokenOptions, type HCPair, type HexColor, type HueDeclaration, type HuePlan, 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 RgbColor, type Role, type RoleInput, type ShadowColorDef, type ShadowTuning, type ToneValue, type ToneWindow, apcaContrast, assertAllPastel, assertNativeFormat, contrastRatioFromLuminance, cuspLightness, findToneForContrast, findValueForMixContrast, formatHsl, formatOkhsl, formatOkhst, formatOklch, formatRgb, 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 };
1636
1810
  //# sourceMappingURL=index.d.cts.map
package/dist/index.d.mts CHANGED
@@ -62,6 +62,24 @@ declare function resolveMinContrast(value: MinContrast$1): number;
62
62
  * selected spec rather than an outer pair).
63
63
  */
64
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;
65
83
  /**
66
84
  * APCA lightness contrast (Lc), signed: positive for dark text on light bg,
67
85
  * negative for light text on dark bg. Inputs are screen luminances (0–1).
@@ -88,6 +106,19 @@ interface FindToneForContrastOptions {
88
106
  initialDirection?: 'lighter' | 'darker';
89
107
  /** Auto-flip tone direction when contrast can't be met. Default: false. */
90
108
  flip?: boolean;
109
+ /**
110
+ * When `flip` is on and *both* directions meet the target, keep
111
+ * `initialDirection` instead of taking whichever result lands nearer the
112
+ * preferred tone. Default: false (nearest wins).
113
+ *
114
+ * The nearest-wins tie-break is unstable along a ramp of targets: which side
115
+ * is nearer shifts as the target grows, so a color can swap sides between two
116
+ * adjacent targets. Set this when a caller needs the side to be a property of
117
+ * the color rather than of the target — the manual contrast level does. The
118
+ * flip itself is unaffected: an initial direction that cannot reach the
119
+ * target still falls back to the opposite side.
120
+ */
121
+ preferInitial?: boolean;
91
122
  /** Use the hue-independent "safe" chroma boundary. Default: false. */
92
123
  pastel?: boolean;
93
124
  }
@@ -200,7 +231,14 @@ type GlazeColorFormat = 'okhsl' | 'okhst' | 'rgb' | 'hsl' | 'oklch';
200
231
  interface GlazeOutputModes {
201
232
  /** Include dark scheme variants. Default: true. */
202
233
  dark?: boolean;
203
- /** Include high-contrast variants (both light-HC and dark-HC). Default: false. */
234
+ /**
235
+ * Include high-contrast variants (both light-HC and dark-HC). Default: false.
236
+ *
237
+ * Inert while a global `contrastLevel` is set: a manual level has no separate
238
+ * high-contrast tier, so this reads as "emit high-contrast variants when
239
+ * contrast is automatic".
240
+ * @see GlazeConfig.contrastLevel
241
+ */
204
242
  highContrast?: boolean;
205
243
  }
206
244
  /** Hex color string for DX hints. Runtime validation in `parseHex()`. */
@@ -248,6 +286,26 @@ interface RegularColorDef {
248
286
  * - String ('+N' / '-N'): relative to the theme seed hue.
249
287
  */
250
288
  hue?: number | RelativeValue;
289
+ /**
290
+ * Dark-scheme hue override. Applies to the `dark` and `darkContrast`
291
+ * variants; falls back to `hue` when omitted.
292
+ * - Number: absolute hue (0–360).
293
+ * - String ('+N' / '-N'): relative to the theme's **dark** seed hue
294
+ * (`GlazeTheme.darkHue`, itself defaulting to the light seed hue).
295
+ *
296
+ * Ignored under `mode: 'static'`, which pins one value across all schemes.
297
+ */
298
+ darkHue?: number | RelativeValue;
299
+ /**
300
+ * Dark-scheme saturation factor (0–1) applied to the dark seed
301
+ * saturation. Applies to the `dark` and `darkContrast` variants; falls
302
+ * back to `saturation` when omitted.
303
+ *
304
+ * When set, the global `darkDesaturation` reduction is **not** applied on
305
+ * top — the resulting saturation is taken literally. Ignored under
306
+ * `mode: 'static'`.
307
+ */
308
+ darkSaturation?: number;
251
309
  /** Name of another color in the same theme (dependent color). */
252
310
  base?: string;
253
311
  /**
@@ -475,10 +533,38 @@ interface GlazeConfig {
475
533
  dark?: string;
476
534
  highContrast?: string;
477
535
  };
478
- /** Which scheme variants to include in exports. Default: both true. */
536
+ /**
537
+ * Which scheme variants to include in exports. Defaults: `dark: true`,
538
+ * `highContrast: false`.
539
+ */
479
540
  modes?: GlazeOutputModes;
480
541
  /** Default tuning for all shadow colors. Per-color tuning merges field-by-field. */
481
542
  shadowTuning?: ShadowTuning;
543
+ /**
544
+ * Manual contrast level — a 0–100 slider from normal contrast (`0`) to high
545
+ * contrast (`100`), or `'auto'` (the default) to keep the two-tier
546
+ * normal + high-contrast model.
547
+ *
548
+ * With a number, Glaze resolves the `light` / `dark` variants *at* that
549
+ * level and stops emitting a separate high-contrast tier:
550
+ * `lightContrast` / `darkContrast` mirror their normal counterparts and
551
+ * `modes.highContrast` defaults to `false`. Level `0` is therefore "normal
552
+ * contrast, no high-contrast tier"; `100` is "the high-contrast scheme as
553
+ * the only scheme".
554
+ *
555
+ * The level interpolates all three things that make high contrast differ:
556
+ * authored `[normal, highContrast]` pairs, the tone-window widening, and
557
+ * the `AA → AAA` / APCA `+15 Lc` escalation. Contrast floors are re-solved
558
+ * at the interpolated target, so every level is a solution rather than an
559
+ * approximation, and a color keeps to one side of its base as the level moves.
560
+ *
561
+ * Pass `'auto'` to leave manual mode; `configure()` never clears a field by
562
+ * omission. See `docs/api.md` for the ramp's edge cases (un-interpolable
563
+ * pairs, side changes) and the export-freeze rule.
564
+ *
565
+ * @default 'auto'
566
+ */
567
+ contrastLevel?: number | 'auto';
482
568
  /**
483
569
  * Automatically flip tone direction when contrast can't be met.
484
570
  *
@@ -513,6 +599,12 @@ interface GlazeConfigResolved {
513
599
  modes: Required<GlazeOutputModes>;
514
600
  shadowTuning?: ShadowTuning;
515
601
  autoFlip: boolean;
602
+ /**
603
+ * Manual contrast level (0–100), or `'auto'` for the two-tier
604
+ * normal + high-contrast model.
605
+ * @see GlazeConfig.contrastLevel
606
+ */
607
+ contrastLevel: number | 'auto';
516
608
  /**
517
609
  * Instance-level pastel default (`def.pastel ?? config.pastel`).
518
610
  * Not set via `glaze.configure()` — only via per-theme / per-token
@@ -538,6 +630,17 @@ interface GlazeConfigOverride {
538
630
  darkDesaturation?: number;
539
631
  /** Whether to auto-flip tone when contrast can't be met. */
540
632
  autoFlip?: boolean;
633
+ /**
634
+ * Manual contrast level (0–100) for this instance, or `'auto'` to opt out
635
+ * of a global level and keep the two-tier normal + high-contrast model.
636
+ *
637
+ * Only an instance-authored level is frozen into `.export()` snapshots — a
638
+ * level inherited from the global config is treated as a live preference and
639
+ * re-read at restore time.
640
+ *
641
+ * @see GlazeConfig.contrastLevel
642
+ */
643
+ contrastLevel?: number | 'auto';
541
644
  /**
542
645
  * Instance-level pastel default for colors that omit per-color `pastel`.
543
646
  * Not available on `glaze.configure()` — set here or per-color.
@@ -572,6 +675,10 @@ interface GlazeThemeExport {
572
675
  version?: number;
573
676
  hue: number;
574
677
  saturation: number;
678
+ /** Dark-scheme seed hue (0–360). Omitted when the theme reuses `hue`. */
679
+ darkHue?: number;
680
+ /** Dark-scheme seed saturation (0–100). Omitted when the theme reuses `saturation`. */
681
+ darkSaturation?: number;
575
682
  colors: ColorMap;
576
683
  /**
577
684
  * Effective config freeze from `.export()` —
@@ -604,6 +711,15 @@ interface GlazeColorInput {
604
711
  saturation: number;
605
712
  tone: HCPair<number | ExtremeValue>;
606
713
  saturationFactor?: number;
714
+ /**
715
+ * Dark-scheme hue. Number is absolute (0–360); `'+N'`/`'-N'` is relative
716
+ * to the dark seed hue, which defaults to `hue`. Falls back to `hue`.
717
+ */
718
+ darkHue?: number | RelativeValue;
719
+ /** Dark-scheme seed saturation (0–100). Defaults to `saturation`. */
720
+ darkSaturation?: number;
721
+ /** Dark-scheme multiplier on the dark seed (0–1). Defaults to `saturationFactor`. */
722
+ darkSaturationFactor?: number;
607
723
  mode?: AdaptationMode;
608
724
  /** Flip out-of-bounds results instead of clamping. Default: global `autoFlip`. */
609
725
  autoFlip?: boolean;
@@ -673,6 +789,23 @@ interface GlazeColorOverrides {
673
789
  hue?: number | RelativeValue;
674
790
  /** Override seed saturation (0–100). Default: extracted from value. */
675
791
  saturation?: number;
792
+ /**
793
+ * Dark-scheme hue. Number is absolute (0–360); `'+N'`/`'-N'` is relative
794
+ * to the dark seed hue, which defaults to the (possibly overridden) seed
795
+ * hue. Falls back to `hue` when omitted.
796
+ */
797
+ darkHue?: number | RelativeValue;
798
+ /**
799
+ * Dark-scheme seed saturation (0–100). Defaults to `saturation`. When set,
800
+ * the global `darkDesaturation` reduction is not applied on top.
801
+ */
802
+ darkSaturation?: number;
803
+ /**
804
+ * Dark-scheme multiplier on the dark seed (0–1). Defaults to
805
+ * `saturationFactor`. When set, the global `darkDesaturation` reduction is
806
+ * not applied on top.
807
+ */
808
+ darkSaturationFactor?: number;
676
809
  /**
677
810
  * Override tone. Number is absolute (0–100, contrast-uniform); `'+N'`/`'-N'`
678
811
  * is relative to the literal seed (the value passed to `glaze.color()`);
@@ -889,6 +1022,9 @@ interface GlazeColorInputExport {
889
1022
  saturation: number;
890
1023
  tone: HCPair<number | ExtremeValue>;
891
1024
  saturationFactor?: number;
1025
+ darkHue?: number | RelativeValue;
1026
+ darkSaturation?: number;
1027
+ darkSaturationFactor?: number;
892
1028
  mode?: AdaptationMode;
893
1029
  autoFlip?: boolean;
894
1030
  opacity?: number;
@@ -905,6 +1041,9 @@ interface GlazeColorInputExport {
905
1041
  interface GlazeColorOverridesExport {
906
1042
  hue?: number | RelativeValue;
907
1043
  saturation?: number;
1044
+ darkHue?: number | RelativeValue;
1045
+ darkSaturation?: number;
1046
+ darkSaturationFactor?: number;
908
1047
  tone?: HCPair<ToneValue>;
909
1048
  saturationFactor?: number;
910
1049
  mode?: AdaptationMode;
@@ -916,11 +1055,33 @@ interface GlazeColorOverridesExport {
916
1055
  pastel?: boolean;
917
1056
  role?: RoleInput;
918
1057
  }
1058
+ /**
1059
+ * The hue/saturation seed pair a theme resolves against.
1060
+ *
1061
+ * `darkHue` / `darkSaturation` are a separate seed for the `dark` and
1062
+ * `darkContrast` variants; each falls back to its light counterpart. Setting
1063
+ * `darkSaturation` opts the theme out of the global `darkDesaturation`
1064
+ * reduction — the authored value is used literally.
1065
+ */
1066
+ interface GlazeThemeSeed {
1067
+ /** Light-scheme hue seed (0–360). */
1068
+ hue: number;
1069
+ /** Light-scheme saturation seed (0–100). */
1070
+ saturation: number;
1071
+ /** Dark-scheme hue seed (0–360). Defaults to `hue`. */
1072
+ darkHue?: number;
1073
+ /** Dark-scheme saturation seed (0–100). Defaults to `saturation`. */
1074
+ darkSaturation?: number;
1075
+ }
919
1076
  interface GlazeTheme {
920
1077
  /** The hue seed (0–360). */
921
1078
  readonly hue: number;
922
1079
  /** The saturation seed (0–100). */
923
1080
  readonly saturation: number;
1081
+ /** The dark-scheme hue seed (0–360), or `undefined` when `hue` is reused. */
1082
+ readonly darkHue: number | undefined;
1083
+ /** The dark-scheme saturation seed (0–100), or `undefined` when `saturation` is reused. */
1084
+ readonly darkSaturation: number | undefined;
924
1085
  /** The effective config for this theme. */
925
1086
  getConfig(): GlazeConfigResolved;
926
1087
  /** Add/replace colors (additive merge with existing definitions). */
@@ -988,6 +1149,10 @@ interface GlazeTheme {
988
1149
  interface GlazeExtendOptions {
989
1150
  hue?: number;
990
1151
  saturation?: number;
1152
+ /** Replace the dark-scheme hue seed (0–360). Defaults to the parent's. */
1153
+ darkHue?: number;
1154
+ /** Replace the dark-scheme saturation seed (0–100). Defaults to the parent's. */
1155
+ darkSaturation?: number;
991
1156
  colors?: ColorMap;
992
1157
  /** Config override for the child theme. Merged with the parent's override. */
993
1158
  config?: GlazeConfigOverride;
@@ -1341,19 +1506,23 @@ type PaletteInput = Record<string, GlazeTheme>;
1341
1506
  * the theme still reacts to later `configure()` calls for fields it
1342
1507
  * didn't override.
1343
1508
  *
1509
+ * The object form also accepts `darkHue` / `darkSaturation` — a separate
1510
+ * seed pair for the dark and dark-high-contrast schemes. Both default to
1511
+ * their light counterparts, and an explicit `darkSaturation` opts the theme
1512
+ * out of the global `darkDesaturation` reduction.
1513
+ *
1344
1514
  * @example
1345
1515
  * ```ts
1346
1516
  * const primary = glaze(280, 80);
1347
1517
  * // or shorthand:
1348
1518
  * const primary = glaze({ hue: 280, saturation: 80 });
1519
+ * // with a retuned dark seed:
1520
+ * const primary = glaze({ hue: 280, saturation: 80, darkHue: 268, darkSaturation: 65 });
1349
1521
  * // with config override:
1350
1522
  * const raw = glaze(280, 80, { lightTone: false });
1351
1523
  * ```
1352
1524
  */
1353
- declare function glaze(hueOrOptions: number | {
1354
- hue: number;
1355
- saturation: number;
1356
- }, saturation?: number, config?: GlazeConfigOverride): GlazeTheme;
1525
+ declare function glaze(hueOrOptions: number | GlazeThemeSeed, saturation?: number, config?: GlazeConfigOverride): GlazeTheme;
1357
1526
  declare namespace glaze {
1358
1527
  var configure: (config: GlazeConfig) => void;
1359
1528
  var palette: (themes: PaletteInput, options?: GlazePaletteOptions) => GlazePalette;
@@ -1388,6 +1557,11 @@ interface HuePlan {
1388
1557
  }
1389
1558
  interface ChannelCtx {
1390
1559
  seedHue: number;
1560
+ /**
1561
+ * Dark-scheme seed hue, when the theme authored one. Drives the dark
1562
+ * `--{baseName}-hue` value; falls back to `seedHue`.
1563
+ */
1564
+ darkSeedHue?: number;
1391
1565
  /** Theme-level hue var base name (without `--` / `-hue`). */
1392
1566
  baseName: string;
1393
1567
  /** Token / custom-property name prefix used for hue var naming (`brand-` etc.). */
@@ -1632,5 +1806,5 @@ declare function srgbToHex(rgb: [number, number, number]): `#${string}`;
1632
1806
  */
1633
1807
  declare function okhslToOklch(h: number, s: number, l: number, pastel?: boolean): [number, number, number];
1634
1808
  //#endregion
1635
- 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 GlazeDtcgOptions, type GlazeDtcgResolverContextNames, type GlazeDtcgResolverDocument, type GlazeDtcgResolverOptions, type GlazeDtcgResult, type GlazeExportKind, type GlazeExportVersion, type GlazeExtendOptions, type GlazeFromInput, type GlazeJsonOptions, type GlazeOutputModes, type GlazePalette, type GlazePaletteExport, type GlazePaletteExportOptions, type GlazePaletteOptions, type GlazeShadowInput, type GlazeTailwindOptions, type GlazeTheme, type GlazeThemeExport, type GlazeTokenOptions, type HCPair, type HexColor, type HueDeclaration, type HuePlan, 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 RgbColor, type Role, type RoleInput, type ShadowColorDef, type ShadowTuning, type ToneValue, type ToneWindow, apcaContrast, assertAllPastel, assertNativeFormat, contrastRatioFromLuminance, cuspLightness, findToneForContrast, findValueForMixContrast, formatHsl, formatOkhsl, formatOkhst, formatOklch, formatRgb, fromTone, gamutClampedLuminance, glaze, hslToSrgb, inferRoleFromName, isColorTokenExport, isPaletteExport, isThemeExport, normalizeRole, okhslToLinearSrgb, okhslToOkhst, okhslToOklab, okhslToOklch, okhslToSrgb, okhstToOkhsl, oklabToOkhsl, oppositeRole, parseHex, parseHexAlpha, relativeLuminanceFromLinearRgb, resolveApcaTarget, resolveContrastForMode, resolveMinContrast, roleToPolarity, srgbToHex, srgbToOkhsl, toTone, toneFromY, variantToOkhsl, yFromTone };
1809
+ 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 GlazeDtcgOptions, type GlazeDtcgResolverContextNames, type GlazeDtcgResolverDocument, type GlazeDtcgResolverOptions, type GlazeDtcgResult, type GlazeExportKind, type GlazeExportVersion, type GlazeExtendOptions, type GlazeFromInput, type GlazeJsonOptions, type GlazeOutputModes, type GlazePalette, type GlazePaletteExport, type GlazePaletteExportOptions, type GlazePaletteOptions, type GlazeShadowInput, type GlazeTailwindOptions, type GlazeTheme, type GlazeThemeExport, type GlazeThemeSeed, type GlazeTokenOptions, type HCPair, type HexColor, type HueDeclaration, type HuePlan, 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 RgbColor, type Role, type RoleInput, type ShadowColorDef, type ShadowTuning, type ToneValue, type ToneWindow, apcaContrast, assertAllPastel, assertNativeFormat, contrastRatioFromLuminance, cuspLightness, findToneForContrast, findValueForMixContrast, formatHsl, formatOkhsl, formatOkhst, formatOklch, formatRgb, 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 };
1636
1810
  //# sourceMappingURL=index.d.mts.map