@tenphi/glaze 0.10.0 → 0.11.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/README.md +15 -9
- package/dist/index.cjs +47 -25
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +19 -12
- package/dist/index.d.mts +19 -12
- package/dist/index.mjs +47 -25
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -282,27 +282,33 @@ adapt to both lightness windows. The defaults vary by input form,
|
|
|
282
282
|
because string inputs are typically end-user values (color pickers,
|
|
283
283
|
theme settings) where natural light/dark inversion is the expectation:
|
|
284
284
|
|
|
285
|
+
Every input form defaults to **`mode: 'auto'`** so the resolved token
|
|
286
|
+
adapts between light and dark like an ordinary theme color. The
|
|
287
|
+
*scaling* snapshot taken at create time differs by input form:
|
|
288
|
+
|
|
285
289
|
- **String value-shorthand** (hex, `rgb()`, `hsl()`, `okhsl()`,
|
|
286
290
|
`oklch()`):
|
|
287
291
|
- Light variant preserves the input lightness exactly.
|
|
288
292
|
- Dark variant is **Möbius-inverted** into `[globalConfig.darkLightness[0], 100]`,
|
|
289
293
|
so `glaze.color('#000')` renders as `#fff` in dark mode and
|
|
290
294
|
`glaze.color('#fff')` falls to the dark `lo` floor (default `0.15`).
|
|
291
|
-
- Adaptation mode defaults to `'auto'`.
|
|
292
295
|
- The dark `lo` is snapshotted from `globalConfig` at color-creation
|
|
293
296
|
time, matching how an explicit `scaling.darkLightness: [lo, hi]`
|
|
294
297
|
behaves.
|
|
295
298
|
|
|
296
299
|
- **Object / tuple value-shorthand** (`{ h, s, l }`, `[r, g, b]`) and
|
|
297
300
|
the **structured form** (`{ hue, saturation, lightness, ... }`):
|
|
298
|
-
-
|
|
299
|
-
|
|
300
|
-
(
|
|
301
|
+
- Both light and dark variants are mapped through
|
|
302
|
+
`globalConfig.lightLightness` / `globalConfig.darkLightness`
|
|
303
|
+
(defaults `[10, 100]` / `[15, 95]`) — the same windows a theme color
|
|
304
|
+
uses. With the `'auto'` default the dark variant is Möbius-inverted
|
|
305
|
+
into that dark window, so a near-white seed lands at a near-dark
|
|
306
|
+
dark variant.
|
|
307
|
+
- Both windows are snapshotted at color-creation time so later
|
|
301
308
|
`glaze.configure()` calls don't retroactively change exported tokens.
|
|
302
|
-
- Adaptation mode defaults to `'fixed'` (linear, no Möbius curve).
|
|
303
309
|
|
|
304
|
-
To opt back into the
|
|
305
|
-
|
|
310
|
+
To opt back into the legacy fixed-linear default (no Möbius inversion),
|
|
311
|
+
pass `{ mode: 'fixed' }` as the second arg, or supply an explicit
|
|
306
312
|
`scaling` as the third arg (see [Lightness scaling](#lightness-scaling)).
|
|
307
313
|
|
|
308
314
|
```ts
|
|
@@ -373,7 +379,7 @@ All overrides:
|
|
|
373
379
|
| `saturation` | Override seed saturation (0–100) |
|
|
374
380
|
| `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 |
|
|
375
381
|
| `saturationFactor` | Multiplier on seed (0–1, default 1) |
|
|
376
|
-
| `mode` | `'auto'` (default for
|
|
382
|
+
| `mode` | `'auto'` (default for every input form) / `'fixed'` / `'static'` — see [Adaptation Modes](#adaptation-modes) |
|
|
377
383
|
| `contrast` | WCAG floor. Without `base`, anchored to the literal seed; with `base`, solved per scheme against `base`'s resolved variant. Same shape as `RegularColorDef.contrast`. When the target can't be physically met, `glaze` emits a `console.warn` and returns the closest passing variant |
|
|
378
384
|
| `base` | Another `glaze.color()` token **or** a raw `GlazeColorValue` (hex / `rgb()` / `OkhslColor` / `[r, g, b]`). Raw values are auto-wrapped via `glaze.color(value)` so they pick up the same auto-invert defaults as an explicit wrap. When set, `contrast` and relative `lightness` anchor to it per scheme; relative `hue` still anchors to the seed |
|
|
379
385
|
| `opacity` | Fixed alpha 0–1 applied to every variant. Surfaces in `rgb(... / A)`, `okhsl(... / A)`, etc. Combining with `contrast` is not recommended (perceived lightness becomes unpredictable) — `glaze` emits a `console.warn` |
|
|
@@ -1423,7 +1429,7 @@ brand.colors({ surface: { lightness: 97 }, text: { base: 'surface', lightness: '
|
|
|
1423
1429
|
| `glaze.fromHex(hex)` | Create a theme from a hex color (`#rgb` or `#rrggbb`) |
|
|
1424
1430
|
| `glaze.fromRgb(r, g, b)` | Create a theme from RGB values (0–255) |
|
|
1425
1431
|
| `glaze.color(input, scaling?)` | Create a standalone color token from `{ hue, saturation, lightness, opacity?, contrast?, base?, name?, ... }`. Optional `scaling` overrides the lightness windows |
|
|
1426
|
-
| `glaze.color(value, overrides?, scaling?)` | Create a standalone color token from a hex string (3/6/8 digits), an `rgb()` / `hsl()` / `okhsl()` / `oklch()` string, an `{ h, s, l }` OKHSL object, or an `[r, g, b]` (0–255) tuple. Overrides accept absolute or relative `hue` / `lightness`, `saturation`, `mode`, `contrast`, `opacity`, `name`, and `base` (a `GlazeColorToken` or any `GlazeColorValue`; raw values are auto-wrapped). When `base` is set, `contrast` and relative `lightness` are anchored to the base per scheme — see [Pairing Colors](#pairing-colors).
|
|
1432
|
+
| `glaze.color(value, overrides?, scaling?)` | Create a standalone color token from a hex string (3/6/8 digits), an `rgb()` / `hsl()` / `okhsl()` / `oklch()` string, an `{ h, s, l }` OKHSL object, or an `[r, g, b]` (0–255) tuple. Overrides accept absolute or relative `hue` / `lightness`, `saturation`, `mode`, `contrast`, `opacity`, `name`, and `base` (a `GlazeColorToken` or any `GlazeColorValue`; raw values are auto-wrapped). When `base` is set, `contrast` and relative `lightness` are anchored to the base per scheme — see [Pairing Colors](#pairing-colors). Every input form defaults to `mode: 'auto'`; string inputs additionally preserve light lightness exactly and extend the dark window to `[lo, 100]`, while object / tuple / structured inputs snapshot both windows from `globalConfig.lightLightness` / `globalConfig.darkLightness`. |
|
|
1427
1433
|
| `glaze.colorFrom(data)` | Rehydrate a `glaze.color()` token from a `.export()` snapshot. Inverse of `token.export()` — see [Persisting Standalone Colors](#persisting-standalone-colors) |
|
|
1428
1434
|
| `glaze.shadow(input)` | Compute a standalone shadow color (returns `ResolvedColorVariant`). `bg` / `fg` accept any `GlazeColorValue` form |
|
|
1429
1435
|
| `glaze.format(variant, format?)` | Format any `ResolvedColorVariant` as a CSS string |
|
package/dist/index.cjs
CHANGED
|
@@ -361,6 +361,12 @@ const oklabToOkhsl = (lab) => {
|
|
|
361
361
|
0,
|
|
362
362
|
toe(L)
|
|
363
363
|
];
|
|
364
|
+
const L_EXTREME_EPSILON = 1e-6;
|
|
365
|
+
if (L >= 1 - L_EXTREME_EPSILON || L <= L_EXTREME_EPSILON) return [
|
|
366
|
+
0,
|
|
367
|
+
0,
|
|
368
|
+
toe(L)
|
|
369
|
+
];
|
|
364
370
|
const a_ = a / C;
|
|
365
371
|
const b_ = b / C;
|
|
366
372
|
let h = Math.atan2(b, a) * (180 / Math.PI);
|
|
@@ -904,16 +910,25 @@ const STANDALONE_BASE = "externalBase";
|
|
|
904
910
|
* retroactively change the resolved variants of an already-created
|
|
905
911
|
* token (matches the documented "frozen at create time" semantics).
|
|
906
912
|
*
|
|
907
|
-
* String value-shorthand inputs
|
|
913
|
+
* String value-shorthand inputs preserve their light lightness exactly
|
|
914
|
+
* (`lightLightness: false`) and use an extended dark window
|
|
908
915
|
* `[globalConfig.darkLightness[0], 100]` so a totally-black input can
|
|
909
|
-
* Möbius-invert to totally-white in dark mode
|
|
910
|
-
* structured inputs
|
|
916
|
+
* Möbius-invert to totally-white in dark mode. Object / tuple /
|
|
917
|
+
* structured inputs snapshot both windows from `globalConfig` verbatim
|
|
918
|
+
* so they behave like an ordinary theme color (auto-adapted on both
|
|
919
|
+
* sides).
|
|
911
920
|
*/
|
|
912
|
-
function defaultStandaloneScaling(
|
|
913
|
-
|
|
921
|
+
function defaultStandaloneScaling(isString) {
|
|
922
|
+
if (isString) {
|
|
923
|
+
const [darkLo] = globalConfig.darkLightness;
|
|
924
|
+
return {
|
|
925
|
+
lightLightness: false,
|
|
926
|
+
darkLightness: [darkLo, 100]
|
|
927
|
+
};
|
|
928
|
+
}
|
|
914
929
|
return {
|
|
915
|
-
lightLightness:
|
|
916
|
-
darkLightness:
|
|
930
|
+
lightLightness: globalConfig.lightLightness,
|
|
931
|
+
darkLightness: globalConfig.darkLightness
|
|
917
932
|
};
|
|
918
933
|
}
|
|
919
934
|
/** Reserved internal names that user-supplied `name` must not collide with. */
|
|
@@ -1942,17 +1957,18 @@ function extractOkhslFromValue(value) {
|
|
|
1942
1957
|
* Build the `ColorMap` for a value-shorthand `glaze.color()` call.
|
|
1943
1958
|
*
|
|
1944
1959
|
* The user-facing color (`STANDALONE_VALUE`) defaults to `mode: 'auto'`
|
|
1945
|
-
*
|
|
1960
|
+
* across every value-shorthand form. String inputs pair with the
|
|
1946
1961
|
* extended dark window so a totally-black input renders as totally-white
|
|
1947
|
-
* in dark mode
|
|
1948
|
-
*
|
|
1962
|
+
* in dark mode; `OkhslColor` / RGB-tuple inputs auto-adapt into the
|
|
1963
|
+
* snapshotted `globalConfig.lightLightness` / `globalConfig.darkLightness`
|
|
1964
|
+
* windows.
|
|
1949
1965
|
*
|
|
1950
1966
|
* When the user requests `contrast` or relative `lightness`, a hidden
|
|
1951
1967
|
* `STANDALONE_SEED` def is synthesized at `mode: 'static'`. That keeps
|
|
1952
1968
|
* the seed pinned to the literal user-provided color across all four
|
|
1953
1969
|
* variants, so the contrast solver always anchors against it.
|
|
1954
1970
|
*/
|
|
1955
|
-
function buildStandaloneValueDefs(main, options
|
|
1971
|
+
function buildStandaloneValueDefs(main, options) {
|
|
1956
1972
|
const seedHue = typeof options?.hue === "number" ? options.hue : main.h;
|
|
1957
1973
|
const seedSaturation = options?.saturation ?? main.s * 100;
|
|
1958
1974
|
const relativeHue = typeof options?.hue === "string" ? options.hue : void 0;
|
|
@@ -1968,7 +1984,7 @@ function buildStandaloneValueDefs(main, options, inputIsString) {
|
|
|
1968
1984
|
saturation: options?.saturationFactor,
|
|
1969
1985
|
lightness: lightnessOption ?? main.l * 100,
|
|
1970
1986
|
contrast: options?.contrast,
|
|
1971
|
-
mode: options?.mode ??
|
|
1987
|
+
mode: options?.mode ?? "auto",
|
|
1972
1988
|
opacity: options?.opacity,
|
|
1973
1989
|
base: hasExternalBase ? STANDALONE_BASE : needsSeedAnchor ? STANDALONE_SEED : void 0
|
|
1974
1990
|
};
|
|
@@ -2069,7 +2085,7 @@ function createColorToken(input, scaling) {
|
|
|
2069
2085
|
const defs = { [primary]: {
|
|
2070
2086
|
lightness: input.lightness,
|
|
2071
2087
|
saturation: input.saturationFactor,
|
|
2072
|
-
mode: input.mode ?? "
|
|
2088
|
+
mode: input.mode ?? "auto",
|
|
2073
2089
|
contrast: input.contrast,
|
|
2074
2090
|
opacity: input.opacity,
|
|
2075
2091
|
base: hasExternalBase ? STANDALONE_BASE : needsSeedAnchor ? STANDALONE_SEED : void 0
|
|
@@ -2091,7 +2107,7 @@ function createColorTokenFromValue(value, options, scaling) {
|
|
|
2091
2107
|
const inputIsString = typeof value === "string";
|
|
2092
2108
|
const main = extractOkhslFromValue(value);
|
|
2093
2109
|
const baseToken = resolveBaseToken(options?.base);
|
|
2094
|
-
const { seedHue, seedSaturation, defs, primary } = buildStandaloneValueDefs(main, options
|
|
2110
|
+
const { seedHue, seedSaturation, defs, primary } = buildStandaloneValueDefs(main, options);
|
|
2095
2111
|
const effectiveScaling = scaling ?? defaultStandaloneScaling(inputIsString);
|
|
2096
2112
|
const exportData = () => ({
|
|
2097
2113
|
form: "value",
|
|
@@ -2211,17 +2227,23 @@ function isStructuredColorInput(input) {
|
|
|
2211
2227
|
* emits (`rgb()`, `hsl()`, `okhsl()`, `oklch()`), an `OkhslColor`
|
|
2212
2228
|
* object `{ h, s, l }` (0–1 ranges), or an `[r, g, b]` (0–255) tuple.
|
|
2213
2229
|
*
|
|
2214
|
-
* Defaults
|
|
2215
|
-
*
|
|
2216
|
-
*
|
|
2217
|
-
*
|
|
2218
|
-
*
|
|
2219
|
-
*
|
|
2220
|
-
* -
|
|
2221
|
-
*
|
|
2222
|
-
*
|
|
2223
|
-
* -
|
|
2224
|
-
* `
|
|
2230
|
+
* Defaults: every input form defaults to `mode: 'auto'` so colors
|
|
2231
|
+
* automatically adapt between light and dark like an ordinary theme
|
|
2232
|
+
* color. The scaling snapshot taken at create time differs by input
|
|
2233
|
+
* form:
|
|
2234
|
+
* - String value-shorthand: `{ lightLightness: false, darkLightness:
|
|
2235
|
+
* [globalConfig.darkLightness[0], 100] }`. Light preserves the input
|
|
2236
|
+
* exactly; dark Möbius-inverts up to 100, so `glaze.color('#000')`
|
|
2237
|
+
* renders as `#fff` in dark mode (and `glaze.color('#fff')` falls to
|
|
2238
|
+
* the dark `lo` floor).
|
|
2239
|
+
* - `OkhslColor` object / RGB-tuple / structured value-shorthand:
|
|
2240
|
+
* `{ lightLightness: globalConfig.lightLightness, darkLightness:
|
|
2241
|
+
* globalConfig.darkLightness }` — both windows come straight from
|
|
2242
|
+
* `globalConfig`, so the resulting token behaves like a theme color.
|
|
2243
|
+
*
|
|
2244
|
+
* Pass `{ mode: 'fixed' }` to opt back into the legacy linear, non-
|
|
2245
|
+
* inverting mapping, or `{ mode: 'static' }` to pin the same lightness
|
|
2246
|
+
* across every variant.
|
|
2225
2247
|
*
|
|
2226
2248
|
* Relative `lightness: '+N'` and `contrast: <ratio>` are anchored to
|
|
2227
2249
|
* the literal seed (the value passed in) by default, pinned at
|