@tenphi/glaze 0.12.0 → 0.13.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/docs/api.md CHANGED
@@ -25,8 +25,8 @@ Full reference for every public method, option, and type exported by `@tenphi/gl
25
25
 
26
26
  | Method | Description |
27
27
  |---|---|
28
- | `glaze(hue, saturation?)` | Create a theme from hue (0–360) and saturation (0–100). Default saturation: `100`. |
29
- | `glaze({ hue, saturation })` | Create a theme from an options object. |
28
+ | `glaze(hue, saturation?, config?)` | Create a theme from hue (0–360) and saturation (0–100). Optional `config` overrides the global config for this theme. |
29
+ | `glaze({ hue, saturation }, config?)` | Create a theme from an options object, with optional per-theme config override. |
30
30
  | `glaze.from(data)` | Create a theme from an exported configuration (`theme.export()` snapshot). |
31
31
  | `glaze.fromHex(hex)` | Create a theme from a hex color (`#rgb` or `#rrggbb`). Extracts hue and saturation. |
32
32
  | `glaze.fromRgb(r, g, b)` | Create a theme from RGB values (0–255). Extracts hue and saturation. |
@@ -37,8 +37,13 @@ const b = glaze({ hue: 280, saturation: 80 });
37
37
  const c = glaze.fromHex('#7a4dbf');
38
38
  const d = glaze.fromRgb(122, 77, 191);
39
39
  const e = glaze.from(a.export());
40
+
41
+ // Per-theme config override:
42
+ const rawTheme = glaze(280, 80, { lightLightness: false, darkLightness: false });
40
43
  ```
41
44
 
45
+ The optional `config` parameter is a `GlazeConfigOverride` — see [Per-instance config override](#per-instance-config-override).
46
+
42
47
  ---
43
48
 
44
49
  ## Theme methods
@@ -81,13 +86,16 @@ const def = theme.color('surface'); // get
81
86
 
82
87
  ### `theme.extend(options)`
83
88
 
84
- Creates a new theme inheriting all color definitions, optionally replacing the hue / saturation seed and merging in per-theme overrides:
89
+ Creates a new theme inheriting all color definitions, optionally replacing the hue / saturation seed, color overrides, and config:
85
90
 
86
91
  ```ts
87
92
  const danger = primary.extend({
88
93
  hue: 23,
89
94
  colors: { 'accent-fill': { lightness: 48, mode: 'fixed' } },
90
95
  });
96
+
97
+ // Inherit parent's config override and tighten the dark window further:
98
+ const highSat = base.extend({ config: { darkLightness: [10, 100] } });
91
99
  ```
92
100
 
93
101
  `GlazeExtendOptions`:
@@ -97,6 +105,7 @@ const danger = primary.extend({
97
105
  | `hue` | `number` | Replace the hue seed. Defaults to the parent's hue. |
98
106
  | `saturation` | `number` | Replace the saturation seed. Defaults to the parent's saturation. |
99
107
  | `colors` | `ColorMap` | Per-theme overrides (additive merge over the inherited map). |
108
+ | `config` | `GlazeConfigOverride` | Config override for the child. Shallow-merged with the parent's override — child fields win. |
100
109
 
101
110
  Colors marked with `inherit: false` on the parent are **not** copied into the child.
102
111
 
@@ -289,20 +298,30 @@ See [Mix colors](#mix-colors) below.
289
298
 
290
299
  ## Standalone color tokens
291
300
 
292
- `glaze.color()` creates a single color token without a full theme. Two overloads:
301
+ `glaze.color()` creates a single color token without a full theme.
293
302
 
294
303
  ```ts
295
- glaze.color(input: GlazeColorInput, scaling?: GlazeColorScaling): GlazeColorToken;
296
- glaze.color(value: GlazeColorValue, overrides?: GlazeColorOverrides, scaling?: GlazeColorScaling): GlazeColorToken;
304
+ // arg1: the color (four shapes see below)
305
+ // arg2: optional config override (GlazeConfigOverride — see below)
306
+ glaze.color(color: GlazeFromInput | GlazeColorInput | GlazeColorValue, config?: GlazeConfigOverride): GlazeColorToken;
297
307
  ```
298
308
 
299
309
  ### Input forms
300
310
 
301
- `GlazeColorValue` (the value-shorthand input) accepts:
311
+ `glaze.color()` accepts **four input shapes**, discriminated by structure:
312
+
313
+ | Shape | Example | Notes |
314
+ |---|---|---|
315
+ | **Bare string** | `'#26fcb2'` | Hex or CSS color function (`rgb()`, `hsl()`, `okhsl()`, `oklch()`). |
316
+ | **Value object** | `{ h: 152, s: 0.95, l: 0.74 }` | OKHSL, `{ r, g, b }` (sRGB 0–255), or `{ l, c, h }` (OKLCh). |
317
+ | **`{ from, ...overrides }`** | `{ from: '#1a1a2e', base: bg, contrast: 'AA' }` | Value + color overrides in one object. |
318
+ | **Structured** | `{ hue: 152, saturation: 95, lightness: 74 }` | Full theme-style token (hue/saturation/lightness all in 0–100). |
319
+
320
+ `GlazeColorValue` (bare string or value-object forms) accepts:
302
321
 
303
322
  | Form | Example | Notes |
304
323
  |---|---|---|
305
- | Hex | `'#26fcb2'`, `'#26fcb2ff'`, `'#abc'` | 3, 6, or 8 digits. Alpha components are dropped with a `console.warn` — use `opacity` instead. |
324
+ | Hex | `'#26fcb2'`, `'#26fcb2ff'`, `'#abc'` | 3, 6, or 8 digits. Alpha is dropped with a `console.warn` — use `opacity` instead. |
306
325
  | `rgb()` | `'rgb(38 252 178)'`, `'rgb(38 252 178 / 0.8)'` | Modern space syntax. Alpha dropped with warning. |
307
326
  | `hsl()` | `'hsl(152 97% 57%)'` | Modern space syntax. Alpha dropped with warning. |
308
327
  | `okhsl()` | `'okhsl(152 95% 74%)'` | Glaze's own emit format. Alpha dropped with warning. |
@@ -311,7 +330,7 @@ glaze.color(value: GlazeColorValue, overrides?: GlazeColorOverrides, scaling?: G
311
330
  | `RgbColor` object | `{ r: 38, g: 252, b: 178 }` | sRGB 0–255. RGB tuple `[r, g, b]` is not supported — use this object form. |
312
331
  | `OklchColor` object | `{ l: 0.85, c: 0.18, h: 152 }` | OKLCh (L/C: 0–1, H: degrees), same semantics as `oklch()` strings. |
313
332
 
314
- `GlazeColorInput` (the structured input) is `{ hue, saturation, lightness, ... }`:
333
+ `GlazeColorInput` (structured form) is `{ hue, saturation, lightness, ... }`:
315
334
 
316
335
  | Field | Type | Description |
317
336
  |---|---|---|
@@ -322,63 +341,49 @@ glaze.color(value: GlazeColorValue, overrides?: GlazeColorOverrides, scaling?: G
322
341
  | `mode` | `AdaptationMode` | Default: `'auto'`. |
323
342
  | `opacity` | `number` | Fixed alpha 0–1. |
324
343
  | `base` | `GlazeColorToken \| GlazeColorValue` | Optional dependency. See [Pairing colors](#pairing-colors). |
325
- | `contrast` | `HCPair<MinContrast>` | WCAG floor against `base` (requires `base`). |
344
+ | `contrast` | `HCPair<MinContrast>` | WCAG floor against `base`. Without `base`, anchored to the literal seed. |
326
345
  | `name` | `string` | Debug label for warnings; doesn't change output keys. Reserved names (`'value'`, `'seed'`, `'externalBase'`) are rejected. |
327
346
 
328
- Named CSS colors (`'red'`, `'blueviolet'`) are not supported.
329
-
330
- ### Defaults
331
-
332
- Every input form defaults to `mode: 'auto'` so the resolved token adapts between light and dark like an ordinary theme color. The *scaling* snapshot taken at create time differs by input form:
333
-
334
- - **Value-shorthand** (hex, `rgb()` / `hsl()` / `okhsl()` / `oklch()` strings, `{ r, g, b }`, `{ h, s, l }`, `{ l, c, h }`):
335
- - Light variant preserves the input lightness exactly (`lightLightness: false`).
336
- - Dark variant uses `globalConfig.darkLightness` (default `[15, 95]`), snapshotted at create time.
337
- - **Structured input** (`{ hue, saturation, lightness, ... }`):
338
- - Both variants use `globalConfig.lightLightness` / `globalConfig.darkLightness` (defaults `[10, 100]` / `[15, 95]`) — same as a theme color.
339
- - All windows are **snapshotted at color-creation time** so later `glaze.configure()` calls don't retroactively change exported tokens. `token.export()` round-trips byte-for-byte.
340
-
341
- To opt back into the legacy fixed-linear default (no Möbius inversion), pass `{ mode: 'fixed' }` as the second arg, or supply an explicit `scaling` (see [`GlazeColorScaling`](#glazecolorscaling)).
342
-
343
- ### `GlazeColorOverrides`
347
+ `GlazeFromInput` (from form) is `{ from: GlazeColorValue, ...colorOverrides }`:
344
348
 
345
- Overrides for the value-shorthand overload's second argument:
346
-
347
- | Option | Notes |
349
+ | Field | Notes |
348
350
  |---|---|
349
- | `hue` | Number (absolute 0–360) or `'+N'`/`'-N'` (relative to seed never to `base`). |
351
+ | `from` | **Required.** The source color value same forms as `GlazeColorValue`. |
352
+ | `hue` | Number (absolute 0–360) or `'+N'`/`'-N'` (relative to seed, never to `base`). |
350
353
  | `saturation` | Override seed saturation (0–100). |
351
- | `lightness` | Number (absolute 0–100) or `'+N'`/`'-N'`. Without `base`, relative is anchored to the literal seed; with `base`, anchored to `base`'s lightness per scheme. Supports `[normal, hc]` pairs. |
352
- | `saturationFactor` | Multiplier on the seed (0–1). Default: `1`. |
353
- | `mode` | `'auto'` (default for every input form) / `'fixed'` / `'static'`. |
354
- | `contrast` | WCAG floor. Without `base`, anchored to the literal seed; with `base`, solved per scheme against `base`'s resolved variant. When the target can't be met, a `console.warn` is emitted and the closest passing variant is returned. |
355
- | `base` | `GlazeColorToken` **or** raw `GlazeColorValue`. Raw values are auto-wrapped via `glaze.color(value)`. When set, `contrast` and relative `lightness` anchor to it per scheme; relative `hue` still anchors to the seed. |
356
- | `opacity` | Fixed alpha 0–1 applied to every variant. Combining with `contrast` is not recommended — `console.warn` is emitted. |
357
- | `name` | Debug label only — surfaces in `console.warn` / Error messages. Does not change output keys. |
354
+ | `lightness` | Number (absolute 0–100) or `'+N'`/`'-N'`. Without `base`, relative anchors to the seed; with `base`, anchors to `base`'s lightness per scheme. |
355
+ | `saturationFactor` | Multiplier on the seed (0–1). |
356
+ | `mode` | `'auto'` (default) / `'fixed'` / `'static'`. |
357
+ | `contrast` | WCAG floor. Without `base`, anchored to the literal seed; with `base`, solved per scheme. |
358
+ | `base` | `GlazeColorToken` or raw `GlazeColorValue`. See [Pairing colors](#pairing-colors). |
359
+ | `opacity` | Fixed alpha 0–1. Combining with `contrast` is not recommended — `console.warn` is emitted. |
360
+ | `name` | Debug label only — surfaces in warnings/errors. Does not change output keys. |
358
361
 
359
- ### `GlazeColorScaling`
362
+ Named CSS colors (`'red'`, `'blueviolet'`) are not supported.
360
363
 
361
- Per-call lightness-window override. Mirrors `GlazeConfig`'s field names:
364
+ ### Defaults
362
365
 
363
- | Key | Default for value-shorthand | Default for structured input | Effect |
364
- |---|---|---|---|
365
- | `lightLightness` | `false` | `globalConfig.lightLightness` (snapshotted) | `false` = preserve input. Pass `[lo, hi]` to opt into a remap window. |
366
- | `darkLightness` | `globalConfig.darkLightness` (snapshotted) | `globalConfig.darkLightness` (snapshotted) | `false` = preserve input in dark too. Pass `[lo, hi]` to override the window (e.g. `[15, 100]` for a `#000` → white dark flip). |
366
+ Every input form defaults to `mode: 'auto'` so the resolved token adapts between light and dark like an ordinary theme color. The config snapshot taken at create time differs by input form:
367
367
 
368
- Passing `scaling` is **all-or-nothing** both fields are replaced. To keep one field's default while overriding the other, restate the default explicitly.
368
+ - **Value-shorthand** (bare strings, value objects, and `{ from, ...overrides }`):
369
+ - Light variant preserves the input lightness exactly (`lightLightness: false`).
370
+ - All other config fields (`darkLightness`, `darkDesaturation`, `darkCurve`, `autoFlip`) snapshot from `globalConfig` at create time.
371
+ - **Structured input** (`{ hue, saturation, lightness, ... }`):
372
+ - Both lightness windows snapshot from `globalConfig` at create time (same as a theme color).
373
+ - All fields are **snapshotted at color-creation time** — later `glaze.configure()` calls don't retroactively change existing tokens.
369
374
 
370
375
  ```ts
371
- // Preserve raw lightness in dark mode too
372
- glaze.color('#26fcb2', undefined, { darkLightness: false });
376
+ // Bare string adapts automatically
377
+ glaze.color('#26fcb2')
373
378
 
374
- // Opt into theme-style light remap + extended dark (e.g. #000 → white in dark)
375
- glaze.color('#000000', undefined, {
376
- lightLightness: [10, 100],
377
- darkLightness: [15, 100],
378
- });
379
+ // Value-object same behavior
380
+ glaze.color({ h: 152, s: 0.95, l: 0.74 })
379
381
 
380
- // Structured form takes scaling as the second positional arg
381
- glaze.color({ hue: 152, saturation: 95, lightness: 74 }, { darkLightness: false });
382
+ // From form value + color overrides
383
+ glaze.color({ from: '#1a1a2e', hue: '+20', contrast: 'AA' })
384
+
385
+ // Structured form — explicit hue/saturation/lightness (0–100)
386
+ glaze.color({ hue: 152, saturation: 95, lightness: 74 })
382
387
  ```
383
388
 
384
389
  ### Token methods
@@ -394,12 +399,71 @@ A `GlazeColorToken` exposes:
394
399
  | `token.css({ name, format?, suffix? })` | CSS custom property declarations grouped by scheme variant. `name` is **required** and becomes the variable identifier (`'brand'` → `--brand-color`). Defaults: `format: 'rgb'`, `suffix: '-color'` (matches `theme.css`). |
395
400
  | `token.export()` | JSON-safe snapshot — pass to `glaze.colorFrom(...)` to rehydrate. |
396
401
 
402
+ ### Per-instance config override
403
+
404
+ The optional `config` second argument (`GlazeConfigOverride`) overrides the resolve-relevant global config fields for a single token or theme. Fields that are omitted fall through to the live global config at create time (and are snapshotted). Pass `false` for a lightness window to disable clamping entirely — equivalent to `[0, 100]`.
405
+
406
+ `GlazeConfigOverride`:
407
+
408
+ | Field | Default (from global) | Description |
409
+ |---|---|---|
410
+ | `lightLightness` | `[10, 100]` | Light window `[lo, hi]` or `false` (disable clamping = `[0, 100]`). |
411
+ | `darkLightness` | `[15, 95]` | Dark window `[lo, hi]` or `false` (disable clamping). |
412
+ | `darkDesaturation` | `0.1` | Saturation reduction in dark scheme (0–1). |
413
+ | `darkCurve` | `0.5` | Möbius beta for dark `auto`-inversion (0–1). Accepts `[normal, hc]` pair. |
414
+ | `autoFlip` | `true` | When solving `contrast`, allow the solver to switch lightness direction if the requested side can't meet the target. |
415
+ | `shadowTuning` | `undefined` | Default shadow tuning (meaningful for themes; harmless on color tokens). |
416
+
417
+ Config overrides apply to both `glaze.color()` tokens and `glaze()` themes:
418
+
419
+ ```ts
420
+ // Standalone color — preserve raw lightness in both schemes
421
+ glaze.color('#26fcb2', { darkLightness: false })
422
+
423
+ // Restore the #000 → white dark flip (full dark range)
424
+ glaze.color('#000000', {
425
+ lightLightness: false,
426
+ darkLightness: [15, 100],
427
+ })
428
+
429
+ // Structured form with config override
430
+ glaze.color({ hue: 152, saturation: 95, lightness: 74 }, { darkLightness: false })
431
+
432
+ // Theme with config override
433
+ const rawTheme = glaze(280, 80, { lightLightness: false })
434
+ ```
435
+
436
+ The override is **snapshotted at create time** so later `glaze.configure()` calls don't change already-created tokens or themes (for non-overridden fields, the snapshot captured the global value at creation time; for themes, non-overridden fields are re-read from the live global at resolve time — see [Theme config override](#theme-config-override)).
437
+
438
+ ### Theme config override
439
+
440
+ When a theme is created with a `GlazeConfigOverride`, the override is **merged over the live global config at resolve time**. This means:
441
+
442
+ - Fields you overrode are fixed — `glaze.configure()` can't change them for this theme.
443
+ - Fields you didn't override still react to later `glaze.configure()` calls.
444
+
445
+ ```ts
446
+ const t = glaze(280, 80, { lightLightness: [0, 50] });
447
+ t.colors({ text: { lightness: 50, saturation: 1 } });
448
+ // text.light.l ≈ 0.25 — always, regardless of global lightLightness changes.
449
+ // text.dark.s reacts to glaze.configure({ darkDesaturation }) since it's not overridden.
450
+ ```
451
+
452
+ `extend` inherits the parent's override and shallow-merges the child's:
453
+
454
+ ```ts
455
+ const child = t.extend({ config: { darkLightness: false } });
456
+ // child: lightLightness: [0, 50] (inherited) + darkLightness: false (added)
457
+ ```
458
+
459
+ `theme.export()` includes `config`; `glaze.from(data)` restores it.
460
+
397
461
  ### `glaze.colorFrom(data)`
398
462
 
399
- Inverse of `token.export()`. Captures the original input value, all overrides (with any `base` token recursively serialized), and the effective `scaling` so later `glaze.configure()` calls don't change exported tokens.
463
+ Inverse of `token.export()`. The exported snapshot includes the original input, all overrides (with any `base` token recursively serialized), and the full effective config so later `glaze.configure()` calls don't change rehydrated tokens.
400
464
 
401
465
  ```ts
402
- const text = glaze.color('#1a1a1a', { contrast: 'AA' });
466
+ const text = glaze.color({ from: '#1a1a1a', contrast: 'AA' });
403
467
  const data = text.export();
404
468
  const restored = glaze.colorFrom(data);
405
469
  // restored.resolve() === text.resolve() byte-for-byte
@@ -415,17 +479,17 @@ Set `base` to anchor a standalone color to another standalone color or raw value
415
479
  const bg = glaze.color('#1a1a2e');
416
480
 
417
481
  // Text guaranteed AA against `bg` in every scheme.
418
- const text = glaze.color('#ffffff', { base: bg, contrast: 'AA' });
482
+ const text = glaze.color({ from: '#ffffff', base: bg, contrast: 'AA' });
419
483
 
420
484
  // Border 8 lightness units lighter than `bg` in each scheme.
421
- const border = glaze.color('#000000', {
485
+ const border = glaze.color({ from: '#000000',
422
486
  base: bg,
423
487
  lightness: '+8',
424
488
  mode: 'fixed',
425
489
  });
426
490
 
427
491
  // Raw-value base — Glaze auto-wraps it via `glaze.color(value)`.
428
- const text2 = glaze.color('#ffffff', { base: '#1a1a2e', contrast: 'AA' });
492
+ const text2 = glaze.color({ from: '#ffffff', base: '#1a1a2e', contrast: 'AA' });
429
493
  ```
430
494
 
431
495
  Behavior with `base`:
@@ -435,15 +499,15 @@ Behavior with `base`:
435
499
  - Relative `hue: '+N'` / `'-N'` still anchors to the **seed** (the value passed to `glaze.color()`), not the base.
436
500
  - `mode` works as a per-pair knob.
437
501
  - The base token's `.resolve()` is called lazily on the first resolve of the dependent and the result is captured by reference; later mutations to the base don't apply.
438
- - Raw-value bases inherit the same string-vs-object scaling defaults. To skip auto-invert on the base, wrap it yourself: `base: glaze.color(value, undefined, { darkLightness: false })`.
502
+ - **Structured bases are resolved at full range for linking math**: when a value/`from` color links to a base created via the structured form, the contrast/lightness anchor uses the raw input lightness (not the windowed output). This ensures the anchor matches what you intended, not what the light window remapped it to. The base's own `.resolve()` output is unaffected.
439
503
  - When the contrast target is physically unreachable, `glaze` emits a single `console.warn` per `(name, scheme, target)` triple and returns the closest passing variant. Use the `name` override to make the warning identifiable.
440
504
 
441
505
  Chains compose:
442
506
 
443
507
  ```ts
444
508
  const bg = glaze.color('#000000');
445
- const surface = glaze.color('#222222', { base: bg, contrast: 'AAA' });
446
- const text = glaze.color('#ffffff', { base: surface, contrast: 'AA' });
509
+ const surface = glaze.color({ from: '#222222', base: bg, contrast: 'AAA' });
510
+ const text = glaze.color({ from: '#ffffff', base: surface, contrast: 'AA' });
447
511
  ```
448
512
 
449
513
  ### `name` is a debug label
@@ -902,10 +966,10 @@ S_dark = S_light * (1 - darkDesaturation) // default: 0.1
902
966
 
903
967
  ```ts
904
968
  glaze.configure({
905
- lightLightness: [10, 100],
906
- darkLightness: [15, 95],
969
+ lightLightness: [10, 100], // or false to disable clamping
970
+ darkLightness: [15, 95], // or false to disable clamping
907
971
  darkDesaturation: 0.1,
908
- darkCurve: 0.5, // or [normal, hc] pair
972
+ darkCurve: 0.5, // or [normal, hc] pair
909
973
  states: {
910
974
  dark: '@dark',
911
975
  highContrast: '@high-contrast',
@@ -925,8 +989,8 @@ glaze.configure({
925
989
 
926
990
  | Field | Default | Description |
927
991
  |---|---|---|
928
- | `lightLightness` | `[10, 100]` | Light scheme lightness window `[lo, hi]`. Bypassed in HC. |
929
- | `darkLightness` | `[15, 95]` | Dark scheme lightness window. Bypassed in HC. |
992
+ | `lightLightness` | `[10, 100]` | Light scheme lightness window `[lo, hi]`, or `false` to disable clamping (equivalent to `[0, 100]`). Bypassed in HC. |
993
+ | `darkLightness` | `[15, 95]` | Dark scheme lightness window, or `false` to disable clamping. Bypassed in HC. |
930
994
  | `darkDesaturation` | `0.1` | Saturation reduction in dark scheme (0–1). |
931
995
  | `darkCurve` | `0.5` | Möbius beta for dark `auto`-inversion (0–1). Accepts `[normal, hc]` pair. |
932
996
  | `states.dark` | `'@dark'` | State alias for dark mode tokens (Tasty export). |
@@ -942,7 +1006,7 @@ glaze.configure({
942
1006
  | `glaze.getConfig()` | Snapshot the current resolved config (shallow copy). |
943
1007
  | `glaze.resetConfig()` | Reset to defaults (also bumps the version counter). |
944
1008
 
945
- Standalone `glaze.color()` tokens snapshot the relevant fields at create time, so later `configure()` calls don't change already-created tokens.
1009
+ Standalone `glaze.color()` tokens snapshot the resolve-relevant fields at create time, so later `configure()` calls don't change already-created tokens. Themes merge the live global at resolve time for fields not overridden via `GlazeConfigOverride`.
946
1010
 
947
1011
  ---
948
1012
 
@@ -974,8 +1038,10 @@ Resolution priority (highest first):
974
1038
 
975
1039
  | Condition | Behavior |
976
1040
  |---|---|
977
- | `contrast` without `base` | Validation error |
978
- | Relative `lightness` without `base` | Validation error |
1041
+ | `contrast` without `base` in a **theme** color | Validation error |
1042
+ | Relative `lightness` without `base` in a **theme** color | Validation error |
1043
+ | `contrast` without `base` in `glaze.color()` | Anchors against the literal seed (no error) |
1044
+ | Relative `lightness` without `base` in `glaze.color()` | Anchors against the literal seed (no error) |
979
1045
  | `lightness` resolves outside 0–100 | Clamp silently |
980
1046
  | `saturation` outside 0–1 | Clamp silently |
981
1047
  | Circular `base` references | Validation error |
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tenphi/glaze",
3
- "version": "0.12.0",
3
+ "version": "0.13.0",
4
4
  "description": "OKHSL-based color theme generator with WCAG contrast solving for light, dark, and high-contrast schemes",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",