@chances-ai/ui-core 24.0.0 → 24.2.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.
Files changed (45) hide show
  1. package/dist/index.d.ts +1 -0
  2. package/dist/index.d.ts.map +1 -1
  3. package/dist/index.js +5 -0
  4. package/dist/index.js.map +1 -1
  5. package/dist/theme/builtins.d.ts +25 -0
  6. package/dist/theme/builtins.d.ts.map +1 -0
  7. package/dist/theme/builtins.js +209 -0
  8. package/dist/theme/builtins.js.map +1 -0
  9. package/dist/theme/color.d.ts +78 -0
  10. package/dist/theme/color.d.ts.map +1 -0
  11. package/dist/theme/color.js +200 -0
  12. package/dist/theme/color.js.map +1 -0
  13. package/dist/theme/contrast.d.ts +18 -0
  14. package/dist/theme/contrast.d.ts.map +1 -0
  15. package/dist/theme/contrast.js +25 -0
  16. package/dist/theme/contrast.js.map +1 -0
  17. package/dist/theme/index.d.ts +29 -0
  18. package/dist/theme/index.d.ts.map +1 -0
  19. package/dist/theme/index.js +42 -0
  20. package/dist/theme/index.js.map +1 -0
  21. package/dist/theme/project.d.ts +14 -0
  22. package/dist/theme/project.d.ts.map +1 -0
  23. package/dist/theme/project.js +37 -0
  24. package/dist/theme/project.js.map +1 -0
  25. package/dist/theme/resolve.d.ts +11 -0
  26. package/dist/theme/resolve.d.ts.map +1 -0
  27. package/dist/theme/resolve.js +152 -0
  28. package/dist/theme/resolve.js.map +1 -0
  29. package/dist/theme/schema.d.ts +60 -0
  30. package/dist/theme/schema.d.ts.map +1 -0
  31. package/dist/theme/schema.js +81 -0
  32. package/dist/theme/schema.js.map +1 -0
  33. package/dist/theme/tokens.d.ts +40 -0
  34. package/dist/theme/tokens.d.ts.map +1 -0
  35. package/dist/theme/tokens.js +116 -0
  36. package/dist/theme/tokens.js.map +1 -0
  37. package/dist/theme.d.ts +10 -29
  38. package/dist/theme.d.ts.map +1 -1
  39. package/dist/theme.js +19 -73
  40. package/dist/theme.js.map +1 -1
  41. package/dist/web-theme.d.ts +6 -6
  42. package/dist/web-theme.d.ts.map +1 -1
  43. package/dist/web-theme.js +18 -37
  44. package/dist/web-theme.js.map +1 -1
  45. package/package.json +3 -3
package/dist/index.d.ts CHANGED
@@ -23,4 +23,5 @@ export { type AppEventBus, LocalEventBus } from "./event-bus.js";
23
23
  export { type WebMode, type WebSurface, WEB_SURFACE, themeCssVars } from "./web-theme.js";
24
24
  export { type MdNode, type MdInline, parseMarkdown } from "./markdown-model.js";
25
25
  export { DEFAULT_VERBS, pickVerb, formatTokenCount, formatElapsed } from "./progress-model.js";
26
+ export { hexToRgb, rgbToHex, rgbToOklch, oklchToRgb, hexToOklch, oklchToHex, fitOklch, generateScale, generateNeutralScale, mixColors, shift, blend, lighten, darken, hexToRgbString, rgbStringToHex, hueDelta, relativeLuminance, contrastRatio, on, WCAG_AA_NORMAL, WCAG_AA_LARGE, type HexColor, type OklchColor, type ColorValue, type ThemeSeeds, type ChancesThemeVariant, type ChancesTheme, type ChancesTokenName, type ChancesTokens, type TuiRole, type WebChromeToken, type ThemeMode, type ThemeSettingId, parseCustomTheme, TUI_ROLES, WEB_CHROME_TOKENS, ALL_TOKENS, TOKEN_GROUPS, resolveThemeVariant, resolveThemeTokens, parseThemeSetting, toTuiTheme, toCssVars, kebab, BUILTIN_THEMES, DEFAULT_THEME, DALTONIZED_THEME, ANSI_THEME, } from "./theme/index.js";
26
27
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EACL,KAAK,KAAK,EACV,KAAK,YAAY,EACjB,KAAK,MAAM,EACX,KAAK,UAAU,EACf,UAAU,EACV,SAAS,EACT,YAAY,EACZ,cAAc,EACd,cAAc,GACf,MAAM,YAAY,CAAC;AAEpB,OAAO,EACL,KAAK,OAAO,EACZ,KAAK,OAAO,EACZ,cAAc,EACd,mBAAmB,EACnB,eAAe,GAChB,MAAM,4BAA4B,CAAC;AAEpC,OAAO,EACL,KAAK,OAAO,EACZ,KAAK,OAAO,EACZ,KAAK,UAAU,EACf,gBAAgB,EAChB,aAAa,EACb,SAAS,EACT,QAAQ,GACT,MAAM,iBAAiB,CAAC;AAEzB,OAAO,EACL,KAAK,WAAW,EAChB,KAAK,cAAc,EACnB,qBAAqB,EACrB,oBAAoB,GACrB,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EAAE,YAAY,EAAE,eAAe,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAE7F,OAAO,EACL,aAAa,EACb,KAAK,oBAAoB,EACzB,KAAK,IAAI,EACT,KAAK,QAAQ,EACb,WAAW,GACZ,MAAM,iBAAiB,CAAC;AAEzB,OAAO,EAAE,KAAK,WAAW,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAEjE,OAAO,EAAE,KAAK,OAAO,EAAE,KAAK,UAAU,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAE1F,OAAO,EAAE,KAAK,MAAM,EAAE,KAAK,QAAQ,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAEhF,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EACL,KAAK,KAAK,EACV,KAAK,YAAY,EACjB,KAAK,MAAM,EACX,KAAK,UAAU,EACf,UAAU,EACV,SAAS,EACT,YAAY,EACZ,cAAc,EACd,cAAc,GACf,MAAM,YAAY,CAAC;AAEpB,OAAO,EACL,KAAK,OAAO,EACZ,KAAK,OAAO,EACZ,cAAc,EACd,mBAAmB,EACnB,eAAe,GAChB,MAAM,4BAA4B,CAAC;AAEpC,OAAO,EACL,KAAK,OAAO,EACZ,KAAK,OAAO,EACZ,KAAK,UAAU,EACf,gBAAgB,EAChB,aAAa,EACb,SAAS,EACT,QAAQ,GACT,MAAM,iBAAiB,CAAC;AAEzB,OAAO,EACL,KAAK,WAAW,EAChB,KAAK,cAAc,EACnB,qBAAqB,EACrB,oBAAoB,GACrB,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EAAE,YAAY,EAAE,eAAe,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAE7F,OAAO,EACL,aAAa,EACb,KAAK,oBAAoB,EACzB,KAAK,IAAI,EACT,KAAK,QAAQ,EACb,WAAW,GACZ,MAAM,iBAAiB,CAAC;AAEzB,OAAO,EAAE,KAAK,WAAW,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAEjE,OAAO,EAAE,KAAK,OAAO,EAAE,KAAK,UAAU,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAE1F,OAAO,EAAE,KAAK,MAAM,EAAE,KAAK,QAAQ,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAEhF,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAM/F,OAAO,EACL,QAAQ,EACR,QAAQ,EACR,UAAU,EACV,UAAU,EACV,UAAU,EACV,UAAU,EACV,QAAQ,EACR,aAAa,EACb,oBAAoB,EACpB,SAAS,EACT,KAAK,EACL,KAAK,EACL,OAAO,EACP,MAAM,EACN,cAAc,EACd,cAAc,EACd,QAAQ,EACR,iBAAiB,EACjB,aAAa,EACb,EAAE,EACF,cAAc,EACd,aAAa,EACb,KAAK,QAAQ,EACb,KAAK,UAAU,EACf,KAAK,UAAU,EACf,KAAK,UAAU,EACf,KAAK,mBAAmB,EACxB,KAAK,YAAY,EACjB,KAAK,gBAAgB,EACrB,KAAK,aAAa,EAClB,KAAK,OAAO,EACZ,KAAK,cAAc,EACnB,KAAK,SAAS,EACd,KAAK,cAAc,EACnB,gBAAgB,EAChB,SAAS,EACT,iBAAiB,EACjB,UAAU,EACV,YAAY,EACZ,mBAAmB,EACnB,kBAAkB,EAClB,iBAAiB,EACjB,UAAU,EACV,SAAS,EACT,KAAK,EACL,cAAc,EACd,aAAa,EACb,gBAAgB,EAChB,UAAU,GACX,MAAM,kBAAkB,CAAC"}
package/dist/index.js CHANGED
@@ -23,4 +23,9 @@ export { LocalEventBus } from "./event-bus.js";
23
23
  export { WEB_SURFACE, themeCssVars } from "./web-theme.js";
24
24
  export { parseMarkdown } from "./markdown-model.js";
25
25
  export { DEFAULT_VERBS, pickVerb, formatTokenCount, formatElapsed } from "./progress-model.js";
26
+ // (7.3 / task 03) The seed-driven OKLCH token engine. The design-system package
27
+ // consumes these to generate the `@theme` bridge + runtime `--ch-*` vars; custom
28
+ // themes parse through `parseCustomTheme`. The public `Theme`/`resolveTheme`
29
+ // (TUI) + `themeCssVars` (web) above are thin shims over this.
30
+ export { hexToRgb, rgbToHex, rgbToOklch, oklchToRgb, hexToOklch, oklchToHex, fitOklch, generateScale, generateNeutralScale, mixColors, shift, blend, lighten, darken, hexToRgbString, rgbStringToHex, hueDelta, relativeLuminance, contrastRatio, on, WCAG_AA_NORMAL, WCAG_AA_LARGE, parseCustomTheme, TUI_ROLES, WEB_CHROME_TOKENS, ALL_TOKENS, TOKEN_GROUPS, resolveThemeVariant, resolveThemeTokens, parseThemeSetting, toTuiTheme, toCssVars, kebab, BUILTIN_THEMES, DEFAULT_THEME, DALTONIZED_THEME, ANSI_THEME, } from "./theme/index.js";
26
31
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAKL,UAAU,EACV,SAAS,EACT,YAAY,EACZ,cAAc,EACd,cAAc,GACf,MAAM,YAAY,CAAC;AAEpB,OAAO,EAGL,cAAc,EACd,mBAAmB,EACnB,eAAe,GAChB,MAAM,4BAA4B,CAAC;AAEpC,OAAO,EAIL,gBAAgB,EAChB,aAAa,EACb,SAAS,EACT,QAAQ,GACT,MAAM,iBAAiB,CAAC;AAEzB,OAAO,EAGL,qBAAqB,EACrB,oBAAoB,GACrB,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EAAE,YAAY,EAAE,eAAe,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAE7F,OAAO,EACL,aAAa,EAIb,WAAW,GACZ,MAAM,iBAAiB,CAAC;AAEzB,OAAO,EAAoB,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAEjE,OAAO,EAAiC,WAAW,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAE1F,OAAO,EAA8B,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAEhF,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAKL,UAAU,EACV,SAAS,EACT,YAAY,EACZ,cAAc,EACd,cAAc,GACf,MAAM,YAAY,CAAC;AAEpB,OAAO,EAGL,cAAc,EACd,mBAAmB,EACnB,eAAe,GAChB,MAAM,4BAA4B,CAAC;AAEpC,OAAO,EAIL,gBAAgB,EAChB,aAAa,EACb,SAAS,EACT,QAAQ,GACT,MAAM,iBAAiB,CAAC;AAEzB,OAAO,EAGL,qBAAqB,EACrB,oBAAoB,GACrB,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EAAE,YAAY,EAAE,eAAe,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAE7F,OAAO,EACL,aAAa,EAIb,WAAW,GACZ,MAAM,iBAAiB,CAAC;AAEzB,OAAO,EAAoB,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAEjE,OAAO,EAAiC,WAAW,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAE1F,OAAO,EAA8B,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAEhF,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAE/F,gFAAgF;AAChF,iFAAiF;AACjF,6EAA6E;AAC7E,+DAA+D;AAC/D,OAAO,EACL,QAAQ,EACR,QAAQ,EACR,UAAU,EACV,UAAU,EACV,UAAU,EACV,UAAU,EACV,QAAQ,EACR,aAAa,EACb,oBAAoB,EACpB,SAAS,EACT,KAAK,EACL,KAAK,EACL,OAAO,EACP,MAAM,EACN,cAAc,EACd,cAAc,EACd,QAAQ,EACR,iBAAiB,EACjB,aAAa,EACb,EAAE,EACF,cAAc,EACd,aAAa,EAab,gBAAgB,EAChB,SAAS,EACT,iBAAiB,EACjB,UAAU,EACV,YAAY,EACZ,mBAAmB,EACnB,kBAAkB,EAClB,iBAAiB,EACjB,UAAU,EACV,SAAS,EACT,KAAK,EACL,cAAc,EACd,aAAa,EACb,gBAAgB,EAChB,UAAU,GACX,MAAM,kBAAkB,CAAC"}
@@ -0,0 +1,25 @@
1
+ /**
2
+ * (7.3 / task 03 — W0) The built-in themes `[11.6]`/`[11.9]`:
3
+ * - `default` — seeds drive the NEW web chrome scales; `overrides` PIN all 23
4
+ * claude-code visual-language roles + the surface anchors to TODAY's exact
5
+ * RGB ⇒ the TUI projection is byte-identical to the old hard-coded palettes
6
+ * (zero regression, 7.3 §2.5). The engine is still exercised (chrome scales).
7
+ * - `daltonized` — colorblind-safe, FULLY generated from blue-shifted seeds
8
+ * (claude-code design: green→blue, pink→blue, pure-red high-contrast).
9
+ * - `ansi` — TUI-only 16-color theme; roles pinned to `ansi:<name>` so the
10
+ * terminal's own palette carries meaning (claude-code design, copy-not-fork).
11
+ *
12
+ * The `default` overrides are built from the EXACT legacy rgb literals via
13
+ * `rgbStringToHex` so the round-trip back through `hexToRgbString` (project-tui)
14
+ * is lossless by construction.
15
+ */
16
+ import type { ChancesTheme } from "./schema.js";
17
+ export declare const DEFAULT_THEME: ChancesTheme;
18
+ /** Daltonized (deuteranopia-safe): blue replaces green, blue replaces pink,
19
+ * high-contrast red. Fully generated (no pinning) from blue-shifted seeds +
20
+ * explicit expressive seeds (so the discrete badges stay distinguishable by
21
+ * LIGHTNESS, not hue — see engine.test Δh exemption). */
22
+ export declare const DALTONIZED_THEME: ChancesTheme;
23
+ export declare const ANSI_THEME: ChancesTheme;
24
+ export declare const BUILTIN_THEMES: Record<string, ChancesTheme>;
25
+ //# sourceMappingURL=builtins.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"builtins.d.ts","sourceRoot":"","sources":["../../src/theme/builtins.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,OAAO,KAAK,EAAE,YAAY,EAAc,MAAM,aAAa,CAAC;AAwG5D,eAAO,MAAM,aAAa,EAAE,YAM3B,CAAC;AAEF;;;0DAG0D;AAC1D,eAAO,MAAM,gBAAgB,EAAE,YAoC9B,CAAC;AAsDF,eAAO,MAAM,UAAU,EAAE,YAOxB,CAAC;AAEF,eAAO,MAAM,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAIvD,CAAC"}
@@ -0,0 +1,209 @@
1
+ import { rgbStringToHex } from "./color.js";
2
+ /** Convert a {role: "rgb(...)"} map into a {role: "#rrggbb"} override map. */
3
+ function pinRgb(map) {
4
+ const out = {};
5
+ for (const [k, v] of Object.entries(map))
6
+ out[k] = rgbStringToHex(v);
7
+ return out;
8
+ }
9
+ // -- the legacy dark palette (claude-code visual-language facts) ---------------
10
+ const DARK_PIN = {
11
+ accent: "rgb(215,119,87)",
12
+ success: "rgb(78,186,101)",
13
+ error: "rgb(255,107,128)",
14
+ warning: "rgb(255,193,7)",
15
+ permission: "rgb(177,185,249)",
16
+ planMode: "rgb(72,150,140)",
17
+ autoAccept: "rgb(175,135,255)",
18
+ bashPink: "rgb(253,93,177)",
19
+ diffAddedBg: "rgb(34,92,43)",
20
+ diffRemovedBg: "rgb(122,41,54)",
21
+ diffAddedWordBg: "rgb(56,166,96)",
22
+ diffRemovedWordBg: "rgb(179,89,107)",
23
+ userMessageBg: "rgb(55,55,55)",
24
+ stall: "rgb(171,43,63)",
25
+ synKeyword: "rgb(198,120,221)",
26
+ synString: "rgb(152,195,121)",
27
+ synComment: "rgb(106,115,125)",
28
+ synNumber: "rgb(209,154,102)",
29
+ synFunction: "rgb(97,175,239)",
30
+ synType: "rgb(229,192,123)",
31
+ synLiteral: "rgb(86,182,194)",
32
+ synTitle: "rgb(97,175,239)",
33
+ synAttr: "rgb(209,154,102)",
34
+ // surface anchors — same colors as WEB_SURFACE.dark; web-theme.test locks the
35
+ // two value-equal (the legacy `--ch-bg` alias must not drift from `--ch-bg-base`).
36
+ bgBase: "rgb(0,0,0)",
37
+ textBase: "rgb(255,255,255)",
38
+ borderBase: "rgb(85,85,85)",
39
+ };
40
+ // -- the legacy light palette --------------------------------------------------
41
+ const LIGHT_PIN = {
42
+ accent: "rgb(215,119,87)",
43
+ success: "rgb(44,122,57)",
44
+ error: "rgb(171,43,63)",
45
+ warning: "rgb(150,108,30)",
46
+ permission: "rgb(87,105,247)",
47
+ planMode: "rgb(0,102,102)",
48
+ autoAccept: "rgb(135,0,255)",
49
+ bashPink: "rgb(255,0,135)",
50
+ diffAddedBg: "rgb(105,219,124)",
51
+ diffRemovedBg: "rgb(255,168,180)",
52
+ diffAddedWordBg: "rgb(47,157,68)",
53
+ diffRemovedWordBg: "rgb(209,69,75)",
54
+ userMessageBg: "rgb(240,240,240)",
55
+ stall: "rgb(171,43,63)",
56
+ synKeyword: "rgb(166,38,164)",
57
+ synString: "rgb(80,161,79)",
58
+ synComment: "rgb(160,161,167)",
59
+ synNumber: "rgb(152,104,1)",
60
+ synFunction: "rgb(64,120,242)",
61
+ synType: "rgb(193,132,1)",
62
+ synLiteral: "rgb(1,132,188)",
63
+ synTitle: "rgb(64,120,242)",
64
+ synAttr: "rgb(152,104,1)",
65
+ // surface anchors — same colors as WEB_SURFACE.light; web-theme.test locks the
66
+ // two value-equal (the legacy `--ch-bg` alias must not drift from `--ch-bg-base`).
67
+ bgBase: "rgb(255,255,255)",
68
+ textBase: "rgb(0,0,0)",
69
+ borderBase: "rgb(204,204,204)",
70
+ };
71
+ /** Neutral-ish seeds for the default theme: only used to GENERATE the new web
72
+ * chrome scales (the 23 roles + anchors are pinned). `generateNeutralScale`
73
+ * uses absolute lightness steps, so the neutral seed's lightness is irrelevant
74
+ * — hue/chroma only. */
75
+ const DEFAULT_DARK_SEEDS = {
76
+ neutral: "#808080",
77
+ primary: "#d77757",
78
+ success: "#4eba65",
79
+ warning: "#ffc107",
80
+ error: "#ff6b80",
81
+ info: "#b1b9f9",
82
+ interactive: "#87a0f7",
83
+ diffAdd: "#38a660",
84
+ diffDelete: "#b3596b",
85
+ };
86
+ const DEFAULT_LIGHT_SEEDS = {
87
+ neutral: "#808080",
88
+ primary: "#d77757",
89
+ success: "#2c7a39",
90
+ warning: "#966c1e",
91
+ error: "#ab2b3f",
92
+ info: "#5769f7",
93
+ interactive: "#4078f2",
94
+ diffAdd: "#2f9d44",
95
+ diffDelete: "#d1454b",
96
+ };
97
+ export const DEFAULT_THEME = {
98
+ id: "default",
99
+ name: "Default",
100
+ dark: { seeds: DEFAULT_DARK_SEEDS, overrides: pinRgb(DARK_PIN) },
101
+ light: { seeds: DEFAULT_LIGHT_SEEDS, overrides: pinRgb(LIGHT_PIN) },
102
+ surfaces: ["tui", "web"],
103
+ };
104
+ /** Daltonized (deuteranopia-safe): blue replaces green, blue replaces pink,
105
+ * high-contrast red. Fully generated (no pinning) from blue-shifted seeds +
106
+ * explicit expressive seeds (so the discrete badges stay distinguishable by
107
+ * LIGHTNESS, not hue — see engine.test Δh exemption). */
108
+ export const DALTONIZED_THEME = {
109
+ id: "daltonized",
110
+ name: "Daltonized",
111
+ dark: {
112
+ seeds: {
113
+ neutral: "#808080",
114
+ primary: "#3399ff",
115
+ success: "#3399ff",
116
+ warning: "#ffcc00",
117
+ error: "#cc0000",
118
+ info: "#0066cc",
119
+ interactive: "#3399ff",
120
+ diffAdd: "#3399ff",
121
+ diffDelete: "#cc0000",
122
+ planMode: "#00b2b2",
123
+ autoAccept: "#9966ff",
124
+ bashPink: "#0099cc",
125
+ },
126
+ },
127
+ light: {
128
+ seeds: {
129
+ neutral: "#808080",
130
+ primary: "#0066cc",
131
+ success: "#006699",
132
+ warning: "#ff9900",
133
+ error: "#cc0000",
134
+ info: "#0066cc",
135
+ interactive: "#0066cc",
136
+ diffAdd: "#0066cc",
137
+ diffDelete: "#cc0000",
138
+ planMode: "#007a7a",
139
+ autoAccept: "#6600cc",
140
+ bashPink: "#0077aa",
141
+ },
142
+ },
143
+ surfaces: ["tui", "web"],
144
+ };
145
+ // -- ansi-16 (TUI-only) --------------------------------------------------------
146
+ const ANSI_DARK = {
147
+ accent: "ansi:redBright",
148
+ success: "ansi:greenBright",
149
+ error: "ansi:redBright",
150
+ warning: "ansi:yellowBright",
151
+ permission: "ansi:blueBright",
152
+ planMode: "ansi:cyan",
153
+ autoAccept: "ansi:magenta",
154
+ bashPink: "ansi:magentaBright",
155
+ stall: "ansi:red",
156
+ userMessageBg: "ansi:black",
157
+ diffAddedBg: "ansi:green",
158
+ diffRemovedBg: "ansi:red",
159
+ diffAddedWordBg: "ansi:greenBright",
160
+ diffRemovedWordBg: "ansi:redBright",
161
+ synKeyword: "ansi:magenta",
162
+ synString: "ansi:green",
163
+ synComment: "ansi:blackBright",
164
+ synNumber: "ansi:yellow",
165
+ synFunction: "ansi:blue",
166
+ synType: "ansi:yellow",
167
+ synLiteral: "ansi:cyan",
168
+ synTitle: "ansi:blue",
169
+ synAttr: "ansi:yellow",
170
+ };
171
+ const ANSI_LIGHT = {
172
+ accent: "ansi:red",
173
+ success: "ansi:green",
174
+ error: "ansi:red",
175
+ warning: "ansi:yellow",
176
+ permission: "ansi:blue",
177
+ planMode: "ansi:cyan",
178
+ autoAccept: "ansi:magenta",
179
+ bashPink: "ansi:magenta",
180
+ stall: "ansi:red",
181
+ userMessageBg: "ansi:white",
182
+ diffAddedBg: "ansi:green",
183
+ diffRemovedBg: "ansi:red",
184
+ diffAddedWordBg: "ansi:greenBright",
185
+ diffRemovedWordBg: "ansi:redBright",
186
+ synKeyword: "ansi:magenta",
187
+ synString: "ansi:green",
188
+ synComment: "ansi:blackBright",
189
+ synNumber: "ansi:yellow",
190
+ synFunction: "ansi:blue",
191
+ synType: "ansi:yellow",
192
+ synLiteral: "ansi:cyan",
193
+ synTitle: "ansi:blue",
194
+ synAttr: "ansi:yellow",
195
+ };
196
+ export const ANSI_THEME = {
197
+ id: "ansi",
198
+ name: "ANSI 16",
199
+ // seeds present for type-completeness; chrome tokens unused on the TUI surface.
200
+ dark: { seeds: DEFAULT_DARK_SEEDS, overrides: ANSI_DARK },
201
+ light: { seeds: DEFAULT_LIGHT_SEEDS, overrides: ANSI_LIGHT },
202
+ surfaces: ["tui"],
203
+ };
204
+ export const BUILTIN_THEMES = {
205
+ default: DEFAULT_THEME,
206
+ daltonized: DALTONIZED_THEME,
207
+ ansi: ANSI_THEME,
208
+ };
209
+ //# sourceMappingURL=builtins.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"builtins.js","sourceRoot":"","sources":["../../src/theme/builtins.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,78 @@
1
+ /**
2
+ * (7.3 / task 03 — W0) OKLCH color math: the heart of the seed-driven token
3
+ * engine `[11.4]`. Ported near-verbatim from opencode `packages/ui/src/theme/
4
+ * color.ts` (MIT) — the Björn Ottosson sRGB↔OKLab↔OKLCH matrices + the 12-step
5
+ * `generateScale` ladder. Pure functions, NO `node:*` / `process.*` → satisfies
6
+ * the browser-safe boundary (`.dependency-cruiser.cjs`).
7
+ *
8
+ * All inputs/outputs are sRGB in [0,1] (rgb) or `#rrggbb` hex; OKLCH is `{l,c,h}`
9
+ * with l∈[0,1], c≥0, h∈[0,360). `fitOklch` clamps an out-of-gamut color back into
10
+ * sRGB by shrinking chroma so every generated swatch is renderable.
11
+ */
12
+ import type { HexColor, OklchColor } from "./schema.js";
13
+ /** A 12-step generated color ladder. Tuple-typed so step indexing (`scale[6]`)
14
+ * is `HexColor`, not `HexColor | undefined`, under `noUncheckedIndexedAccess`. */
15
+ export type Scale = readonly [
16
+ HexColor,
17
+ HexColor,
18
+ HexColor,
19
+ HexColor,
20
+ HexColor,
21
+ HexColor,
22
+ HexColor,
23
+ HexColor,
24
+ HexColor,
25
+ HexColor,
26
+ HexColor,
27
+ HexColor
28
+ ];
29
+ export declare function hexToRgb(hex: HexColor): {
30
+ r: number;
31
+ g: number;
32
+ b: number;
33
+ };
34
+ export declare function rgbToHex(r: number, g: number, b: number): HexColor;
35
+ export declare function rgbToOklch(r: number, g: number, b: number): OklchColor;
36
+ export declare function oklchToRgb(oklch: OklchColor): {
37
+ r: number;
38
+ g: number;
39
+ b: number;
40
+ };
41
+ export declare function hexToOklch(hex: HexColor): OklchColor;
42
+ export declare function fitOklch(oklch: OklchColor): OklchColor;
43
+ export declare function oklchToHex(oklch: OklchColor): HexColor;
44
+ /** A perceptual brand/state scale: 12 OKLCH-stepped swatches off one seed,
45
+ * light→dark depending on `isDark`. Indices 0..11 = lightest→darkest (dark
46
+ * mode) / lightest-bg→darkest-fg (light mode). Verbatim opencode ladders. */
47
+ export declare function generateScale(seed: HexColor, isDark: boolean): Scale;
48
+ /** A 12-step neutral (gray) scale off the `neutral` seed (low chroma).
49
+ * Indices 0..11 = lightest-bg→darkest-fg (light) / darkest-bg→lightest-fg (dark).
50
+ * The TEXT segment (7..10 = textWeaker/textWeak/iconBase/textBase) is tuned so
51
+ * the scale is MONOTONIC in contrast and `textWeak` (n8) clears WCAG AA-normal
52
+ * (≥4.5) + `textWeaker` (n7) clears AA-large (≥3.0) against the bg, in BOTH modes
53
+ * (measured against the daltonized near-white/near-black bg, the tighter case).
54
+ * This is the "neutral-light-scale debt" repair (docs/7.3 §11): the old light n8
55
+ * used the seed's `base.l`, which fell BELOW n9 (non-monotonic, n8≈3.95<AA), and
56
+ * dark n8 maxed at 0.55 (≈3.4<AA). Steps are now absolute (the neutral seed
57
+ * contributes hue/chroma only — its lightness is intentionally irrelevant). The
58
+ * ui-core engine.test WCAG gate asserts these thresholds across every theme. */
59
+ export declare function generateNeutralScale(seed: HexColor, isDark: boolean): Scale;
60
+ export declare function mixColors(color1: HexColor, color2: HexColor, amount: number): HexColor;
61
+ /** Shift a color in OKLCH space: additive l/h, multiplicative c. */
62
+ export declare function shift(color: HexColor, value: {
63
+ l?: number;
64
+ c?: number;
65
+ h?: number;
66
+ }): HexColor;
67
+ export declare function blend(color: HexColor, background: HexColor, alpha: number): HexColor;
68
+ export declare function lighten(color: HexColor, amount: number): HexColor;
69
+ export declare function darken(color: HexColor, amount: number): HexColor;
70
+ /** `#rrggbb` → `rgb(r,g,b)` integer string — the TUI/Ink color form. The inverse
71
+ * of {@link rgbStringToHex}; integer-rgb round-trips losslessly (W0 keystone). */
72
+ export declare function hexToRgbString(hex: HexColor): string;
73
+ /** `rgb(r,g,b)` (any spacing) → `#rrggbb`. Throws on malformed input. */
74
+ export declare function rgbStringToHex(rgb: string): HexColor;
75
+ /** OKLCH hue-angle difference in [0,180] — used by the discrete-brand-color
76
+ * Δh gate (plan/accept/bash must stay perceptually distinct). */
77
+ export declare function hueDelta(a: HexColor, b: HexColor): number;
78
+ //# sourceMappingURL=color.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"color.d.ts","sourceRoot":"","sources":["../../src/theme/color.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,KAAK,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAExD;mFACmF;AACnF,MAAM,MAAM,KAAK,GAAG,SAAS;IAC3B,QAAQ;IACR,QAAQ;IACR,QAAQ;IACR,QAAQ;IACR,QAAQ;IACR,QAAQ;IACR,QAAQ;IACR,QAAQ;IACR,QAAQ;IACR,QAAQ;IACR,QAAQ;IACR,QAAQ;CACT,CAAC;AAUF,wBAAgB,QAAQ,CAAC,GAAG,EAAE,QAAQ,GAAG;IAAE,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAA;CAAE,CAgB3E;AAED,wBAAgB,QAAQ,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,QAAQ,CAOlE;AAYD,wBAAgB,UAAU,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,UAAU,CAsBtE;AAED,wBAAgB,UAAU,CAAC,KAAK,EAAE,UAAU,GAAG;IAAE,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAA;CAAE,CAuBjF;AAED,wBAAgB,UAAU,CAAC,GAAG,EAAE,QAAQ,GAAG,UAAU,CAGpD;AAED,wBAAgB,QAAQ,CAAC,KAAK,EAAE,UAAU,GAAG,UAAU,CAmBtD;AAED,wBAAgB,UAAU,CAAC,KAAK,EAAE,UAAU,GAAG,QAAQ,CAGtD;AAED;;8EAE8E;AAC9E,wBAAgB,aAAa,CAAC,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,GAAG,KAAK,CAmBpE;AAED;;;;;;;;;;iFAUiF;AACjF,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,GAAG,KAAK,CAa3E;AAED,wBAAgB,SAAS,CAAC,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,GAAG,QAAQ,CAStF;AAED,oEAAoE;AACpE,wBAAgB,KAAK,CAAC,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE;IAAE,CAAC,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,QAAQ,CAO9F;AAED,wBAAgB,KAAK,CAAC,KAAK,EAAE,QAAQ,EAAE,UAAU,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,GAAG,QAAQ,CAQpF;AAED,wBAAgB,OAAO,CAAC,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,GAAG,QAAQ,CAGjE;AAED,wBAAgB,MAAM,CAAC,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,GAAG,QAAQ,CAGhE;AAED;mFACmF;AACnF,wBAAgB,cAAc,CAAC,GAAG,EAAE,QAAQ,GAAG,MAAM,CAGpD;AAED,yEAAyE;AACzE,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,QAAQ,CAIpD;AAED;kEACkE;AAClE,wBAAgB,QAAQ,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE,QAAQ,GAAG,MAAM,CAIzD"}
@@ -0,0 +1,200 @@
1
+ function clamp(v, min, max) {
2
+ return Math.max(min, Math.min(max, v));
3
+ }
4
+ function hue(v) {
5
+ return ((v % 360) + 360) % 360;
6
+ }
7
+ export function hexToRgb(hex) {
8
+ const h = hex.replace("#", "");
9
+ const full = h.length === 3 || h.length === 4
10
+ ? h
11
+ .split("")
12
+ .map((c) => c + c)
13
+ .join("")
14
+ : h;
15
+ const rgb = full.length === 8 ? full.slice(0, 6) : full;
16
+ const num = parseInt(rgb, 16);
17
+ return {
18
+ r: ((num >> 16) & 255) / 255,
19
+ g: ((num >> 8) & 255) / 255,
20
+ b: (num & 255) / 255,
21
+ };
22
+ }
23
+ export function rgbToHex(r, g, b) {
24
+ const toHex = (v) => {
25
+ const clamped = clamp(v, 0, 1);
26
+ const int = Math.round(clamped * 255);
27
+ return int.toString(16).padStart(2, "0");
28
+ };
29
+ return `#${toHex(r)}${toHex(g)}${toHex(b)}`;
30
+ }
31
+ function linearToSrgb(c) {
32
+ if (c <= 0.0031308)
33
+ return c * 12.92;
34
+ return 1.055 * Math.pow(c, 1 / 2.4) - 0.055;
35
+ }
36
+ function srgbToLinear(c) {
37
+ if (c <= 0.04045)
38
+ return c / 12.92;
39
+ return Math.pow((c + 0.055) / 1.055, 2.4);
40
+ }
41
+ export function rgbToOklch(r, g, b) {
42
+ const lr = srgbToLinear(r);
43
+ const lg = srgbToLinear(g);
44
+ const lb = srgbToLinear(b);
45
+ const l_ = 0.4122214708 * lr + 0.5363325363 * lg + 0.0514459929 * lb;
46
+ const m_ = 0.2119034982 * lr + 0.6806995451 * lg + 0.1073969566 * lb;
47
+ const s_ = 0.0883024619 * lr + 0.2817188376 * lg + 0.6299787005 * lb;
48
+ const l = Math.cbrt(l_);
49
+ const m = Math.cbrt(m_);
50
+ const s = Math.cbrt(s_);
51
+ const L = 0.2104542553 * l + 0.793617785 * m - 0.0040720468 * s;
52
+ const a = 1.9779984951 * l - 2.428592205 * m + 0.4505937099 * s;
53
+ const bOk = 0.0259040371 * l + 0.7827717662 * m - 0.808675766 * s;
54
+ const C = Math.sqrt(a * a + bOk * bOk);
55
+ let H = Math.atan2(bOk, a) * (180 / Math.PI);
56
+ if (H < 0)
57
+ H += 360;
58
+ return { l: L, c: C, h: H };
59
+ }
60
+ export function oklchToRgb(oklch) {
61
+ const { l: L, c: C, h: H } = oklch;
62
+ const a = C * Math.cos((H * Math.PI) / 180);
63
+ const b = C * Math.sin((H * Math.PI) / 180);
64
+ const l = L + 0.3963377774 * a + 0.2158037573 * b;
65
+ const m = L - 0.1055613458 * a - 0.0638541728 * b;
66
+ const s = L - 0.0894841775 * a - 1.291485548 * b;
67
+ const l3 = l * l * l;
68
+ const m3 = m * m * m;
69
+ const s3 = s * s * s;
70
+ const lr = 4.0767416621 * l3 - 3.3077115913 * m3 + 0.2309699292 * s3;
71
+ const lg = -1.2684380046 * l3 + 2.6097574011 * m3 - 0.3413193965 * s3;
72
+ const lb = -0.0041960863 * l3 - 0.7034186147 * m3 + 1.707614701 * s3;
73
+ return {
74
+ r: linearToSrgb(lr),
75
+ g: linearToSrgb(lg),
76
+ b: linearToSrgb(lb),
77
+ };
78
+ }
79
+ export function hexToOklch(hex) {
80
+ const { r, g, b } = hexToRgb(hex);
81
+ return rgbToOklch(r, g, b);
82
+ }
83
+ export function fitOklch(oklch) {
84
+ const base = {
85
+ l: clamp(oklch.l, 0, 1),
86
+ c: Math.max(0, oklch.c),
87
+ h: hue(oklch.h),
88
+ };
89
+ const inGamut = (rgb) => rgb.r >= 0 && rgb.r <= 1 && rgb.g >= 0 && rgb.g <= 1 && rgb.b >= 0 && rgb.b <= 1;
90
+ if (inGamut(oklchToRgb(base)))
91
+ return base;
92
+ let c = base.c;
93
+ for (let i = 0; i < 24; i++) {
94
+ c *= 0.9;
95
+ const next = { ...base, c };
96
+ if (inGamut(oklchToRgb(next)))
97
+ return next;
98
+ }
99
+ return { ...base, c: 0 };
100
+ }
101
+ export function oklchToHex(oklch) {
102
+ const { r, g, b } = oklchToRgb(fitOklch(oklch));
103
+ return rgbToHex(r, g, b);
104
+ }
105
+ /** A perceptual brand/state scale: 12 OKLCH-stepped swatches off one seed,
106
+ * light→dark depending on `isDark`. Indices 0..11 = lightest→darkest (dark
107
+ * mode) / lightest-bg→darkest-fg (light mode). Verbatim opencode ladders. */
108
+ export function generateScale(seed, isDark) {
109
+ const base = hexToOklch(seed);
110
+ const scale = [];
111
+ const lightSteps = isDark
112
+ ? [
113
+ 0.118, 0.138, 0.167, 0.202, 0.246, 0.304, 0.378, 0.468, clamp(base.l * 0.825, 0.53, 0.705),
114
+ clamp(base.l * 0.89, 0.61, 0.79), clamp(base.l + 0.033, 0.868, 0.943), 0.984,
115
+ ]
116
+ : [0.993, 0.983, 0.962, 0.936, 0.906, 0.866, 0.811, 0.74, base.l, Math.max(0, base.l - 0.036), 0.49, 0.27];
117
+ const chromaMultipliers = isDark
118
+ ? [0.52, 0.68, 0.86, 1.02, 1.14, 1.24, 1.36, 1.48, 1.56, 1.64, 1.62, 1.15]
119
+ : [0.12, 0.24, 0.46, 0.68, 0.84, 0.98, 1.08, 1.16, 1.22, 1.26, 1.18, 0.98];
120
+ for (let i = 0; i < 12; i++) {
121
+ scale.push(oklchToHex({ l: lightSteps[i], c: base.c * chromaMultipliers[i], h: base.h }));
122
+ }
123
+ return scale;
124
+ }
125
+ /** A 12-step neutral (gray) scale off the `neutral` seed (low chroma).
126
+ * Indices 0..11 = lightest-bg→darkest-fg (light) / darkest-bg→lightest-fg (dark).
127
+ * The TEXT segment (7..10 = textWeaker/textWeak/iconBase/textBase) is tuned so
128
+ * the scale is MONOTONIC in contrast and `textWeak` (n8) clears WCAG AA-normal
129
+ * (≥4.5) + `textWeaker` (n7) clears AA-large (≥3.0) against the bg, in BOTH modes
130
+ * (measured against the daltonized near-white/near-black bg, the tighter case).
131
+ * This is the "neutral-light-scale debt" repair (docs/7.3 §11): the old light n8
132
+ * used the seed's `base.l`, which fell BELOW n9 (non-monotonic, n8≈3.95<AA), and
133
+ * dark n8 maxed at 0.55 (≈3.4<AA). Steps are now absolute (the neutral seed
134
+ * contributes hue/chroma only — its lightness is intentionally irrelevant). The
135
+ * ui-core engine.test WCAG gate asserts these thresholds across every theme. */
136
+ export function generateNeutralScale(seed, isDark) {
137
+ const base = hexToOklch(seed);
138
+ const scale = [];
139
+ const neutralChroma = Math.min(base.c, isDark ? 0.068 : 0.04);
140
+ const lightSteps = isDark
141
+ ? [0.138, 0.156, 0.178, 0.202, 0.232, 0.272, 0.326, 0.52, 0.58, 0.62, 0.72, 0.956]
142
+ : [0.991, 0.979, 0.964, 0.946, 0.931, 0.913, 0.891, 0.64, 0.55, 0.5, 0.44, 0.205];
143
+ for (let i = 0; i < 12; i++) {
144
+ scale.push(oklchToHex({ l: lightSteps[i], c: neutralChroma, h: base.h }));
145
+ }
146
+ return scale;
147
+ }
148
+ export function mixColors(color1, color2, amount) {
149
+ const c1 = hexToOklch(color1);
150
+ const c2 = hexToOklch(color2);
151
+ const delta = ((((c2.h - c1.h) % 360) + 540) % 360) - 180;
152
+ return oklchToHex({
153
+ l: c1.l + (c2.l - c1.l) * amount,
154
+ c: c1.c + (c2.c - c1.c) * amount,
155
+ h: c1.h + delta * amount,
156
+ });
157
+ }
158
+ /** Shift a color in OKLCH space: additive l/h, multiplicative c. */
159
+ export function shift(color, value) {
160
+ const base = hexToOklch(color);
161
+ return oklchToHex({
162
+ l: base.l + (value.l ?? 0),
163
+ c: base.c * (value.c ?? 1),
164
+ h: base.h + (value.h ?? 0),
165
+ });
166
+ }
167
+ export function blend(color, background, alpha) {
168
+ const fg = hexToRgb(color);
169
+ const bg = hexToRgb(background);
170
+ return rgbToHex(fg.r * alpha + bg.r * (1 - alpha), fg.g * alpha + bg.g * (1 - alpha), fg.b * alpha + bg.b * (1 - alpha));
171
+ }
172
+ export function lighten(color, amount) {
173
+ const oklch = hexToOklch(color);
174
+ return oklchToHex({ ...oklch, l: clamp(oklch.l + amount, 0, 1) });
175
+ }
176
+ export function darken(color, amount) {
177
+ const oklch = hexToOklch(color);
178
+ return oklchToHex({ ...oklch, l: clamp(oklch.l - amount, 0, 1) });
179
+ }
180
+ /** `#rrggbb` → `rgb(r,g,b)` integer string — the TUI/Ink color form. The inverse
181
+ * of {@link rgbStringToHex}; integer-rgb round-trips losslessly (W0 keystone). */
182
+ export function hexToRgbString(hex) {
183
+ const { r, g, b } = hexToRgb(hex);
184
+ return `rgb(${Math.round(r * 255)},${Math.round(g * 255)},${Math.round(b * 255)})`;
185
+ }
186
+ /** `rgb(r,g,b)` (any spacing) → `#rrggbb`. Throws on malformed input. */
187
+ export function rgbStringToHex(rgb) {
188
+ const m = rgb.match(/rgb\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*\)/i);
189
+ if (!m)
190
+ throw new Error(`not an rgb() string: ${rgb}`);
191
+ return rgbToHex(Number(m[1]) / 255, Number(m[2]) / 255, Number(m[3]) / 255);
192
+ }
193
+ /** OKLCH hue-angle difference in [0,180] — used by the discrete-brand-color
194
+ * Δh gate (plan/accept/bash must stay perceptually distinct). */
195
+ export function hueDelta(a, b) {
196
+ const ha = hexToOklch(a).h;
197
+ const hb = hexToOklch(b).h;
198
+ return Math.abs(((((hb - ha) % 360) + 540) % 360) - 180);
199
+ }
200
+ //# sourceMappingURL=color.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"color.js","sourceRoot":"","sources":["../../src/theme/color.ts"],"names":[],"mappings":"AA8BA,SAAS,KAAK,CAAC,CAAS,EAAE,GAAW,EAAE,GAAW;IAChD,OAAO,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC;AACzC,CAAC;AAED,SAAS,GAAG,CAAC,CAAS;IACpB,OAAO,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,GAAG,GAAG,CAAC,GAAG,GAAG,CAAC;AACjC,CAAC;AAED,MAAM,UAAU,QAAQ,CAAC,GAAa;IACpC,MAAM,CAAC,GAAG,GAAG,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;IAC/B,MAAM,IAAI,GACR,CAAC,CAAC,MAAM,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,KAAK,CAAC;QAC9B,CAAC,CAAC,CAAC;aACE,KAAK,CAAC,EAAE,CAAC;aACT,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC;aACjB,IAAI,CAAC,EAAE,CAAC;QACb,CAAC,CAAC,CAAC,CAAC;IACR,MAAM,GAAG,GAAG,IAAI,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IACxD,MAAM,GAAG,GAAG,QAAQ,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;IAC9B,OAAO;QACL,CAAC,EAAE,CAAC,CAAC,GAAG,IAAI,EAAE,CAAC,GAAG,GAAG,CAAC,GAAG,GAAG;QAC5B,CAAC,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,GAAG,GAAG,CAAC,GAAG,GAAG;QAC3B,CAAC,EAAE,CAAC,GAAG,GAAG,GAAG,CAAC,GAAG,GAAG;KACrB,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,QAAQ,CAAC,CAAS,EAAE,CAAS,EAAE,CAAS;IACtD,MAAM,KAAK,GAAG,CAAC,CAAS,EAAU,EAAE;QAClC,MAAM,OAAO,GAAG,KAAK,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;QAC/B,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,GAAG,GAAG,CAAC,CAAC;QACtC,OAAO,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;IAC3C,CAAC,CAAC;IACF,OAAO,IAAI,KAAK,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;AAC9C,CAAC;AAED,SAAS,YAAY,CAAC,CAAS;IAC7B,IAAI,CAAC,IAAI,SAAS;QAAE,OAAO,CAAC,GAAG,KAAK,CAAC;IACrC,OAAO,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,GAAG,GAAG,CAAC,GAAG,KAAK,CAAC;AAC9C,CAAC;AAED,SAAS,YAAY,CAAC,CAAS;IAC7B,IAAI,CAAC,IAAI,OAAO;QAAE,OAAO,CAAC,GAAG,KAAK,CAAC;IACnC,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,GAAG,KAAK,EAAE,GAAG,CAAC,CAAC;AAC5C,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,CAAS,EAAE,CAAS,EAAE,CAAS;IACxD,MAAM,EAAE,GAAG,YAAY,CAAC,CAAC,CAAC,CAAC;IAC3B,MAAM,EAAE,GAAG,YAAY,CAAC,CAAC,CAAC,CAAC;IAC3B,MAAM,EAAE,GAAG,YAAY,CAAC,CAAC,CAAC,CAAC;IAE3B,MAAM,EAAE,GAAG,YAAY,GAAG,EAAE,GAAG,YAAY,GAAG,EAAE,GAAG,YAAY,GAAG,EAAE,CAAC;IACrE,MAAM,EAAE,GAAG,YAAY,GAAG,EAAE,GAAG,YAAY,GAAG,EAAE,GAAG,YAAY,GAAG,EAAE,CAAC;IACrE,MAAM,EAAE,GAAG,YAAY,GAAG,EAAE,GAAG,YAAY,GAAG,EAAE,GAAG,YAAY,GAAG,EAAE,CAAC;IAErE,MAAM,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACxB,MAAM,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACxB,MAAM,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAExB,MAAM,CAAC,GAAG,YAAY,GAAG,CAAC,GAAG,WAAW,GAAG,CAAC,GAAG,YAAY,GAAG,CAAC,CAAC;IAChE,MAAM,CAAC,GAAG,YAAY,GAAG,CAAC,GAAG,WAAW,GAAG,CAAC,GAAG,YAAY,GAAG,CAAC,CAAC;IAChE,MAAM,GAAG,GAAG,YAAY,GAAG,CAAC,GAAG,YAAY,GAAG,CAAC,GAAG,WAAW,GAAG,CAAC,CAAC;IAElE,MAAM,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,GAAG,GAAG,GAAG,GAAG,CAAC,CAAC;IACvC,IAAI,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC,GAAG,CAAC,GAAG,GAAG,IAAI,CAAC,EAAE,CAAC,CAAC;IAC7C,IAAI,CAAC,GAAG,CAAC;QAAE,CAAC,IAAI,GAAG,CAAC;IAEpB,OAAO,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC;AAC9B,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,KAAiB;IAC1C,MAAM,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,GAAG,KAAK,CAAC;IAEnC,MAAM,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,EAAE,CAAC,GAAG,GAAG,CAAC,CAAC;IAC5C,MAAM,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,EAAE,CAAC,GAAG,GAAG,CAAC,CAAC;IAE5C,MAAM,CAAC,GAAG,CAAC,GAAG,YAAY,GAAG,CAAC,GAAG,YAAY,GAAG,CAAC,CAAC;IAClD,MAAM,CAAC,GAAG,CAAC,GAAG,YAAY,GAAG,CAAC,GAAG,YAAY,GAAG,CAAC,CAAC;IAClD,MAAM,CAAC,GAAG,CAAC,GAAG,YAAY,GAAG,CAAC,GAAG,WAAW,GAAG,CAAC,CAAC;IAEjD,MAAM,EAAE,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IACrB,MAAM,EAAE,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IACrB,MAAM,EAAE,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAErB,MAAM,EAAE,GAAG,YAAY,GAAG,EAAE,GAAG,YAAY,GAAG,EAAE,GAAG,YAAY,GAAG,EAAE,CAAC;IACrE,MAAM,EAAE,GAAG,CAAC,YAAY,GAAG,EAAE,GAAG,YAAY,GAAG,EAAE,GAAG,YAAY,GAAG,EAAE,CAAC;IACtE,MAAM,EAAE,GAAG,CAAC,YAAY,GAAG,EAAE,GAAG,YAAY,GAAG,EAAE,GAAG,WAAW,GAAG,EAAE,CAAC;IAErE,OAAO;QACL,CAAC,EAAE,YAAY,CAAC,EAAE,CAAC;QACnB,CAAC,EAAE,YAAY,CAAC,EAAE,CAAC;QACnB,CAAC,EAAE,YAAY,CAAC,EAAE,CAAC;KACpB,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,GAAa;IACtC,MAAM,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC;IAClC,OAAO,UAAU,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;AAC7B,CAAC;AAED,MAAM,UAAU,QAAQ,CAAC,KAAiB;IACxC,MAAM,IAAI,GAAG;QACX,CAAC,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;QACvB,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC;QACvB,CAAC,EAAE,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC;KAChB,CAAC;IAEF,MAAM,OAAO,GAAG,CAAC,GAAwC,EAAW,EAAE,CACpE,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC;IAEnF,IAAI,OAAO,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;QAAE,OAAO,IAAI,CAAC;IAE3C,IAAI,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC;IACf,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC;QAC5B,CAAC,IAAI,GAAG,CAAC;QACT,MAAM,IAAI,GAAG,EAAE,GAAG,IAAI,EAAE,CAAC,EAAE,CAAC;QAC5B,IAAI,OAAO,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;YAAE,OAAO,IAAI,CAAC;IAC7C,CAAC;IACD,OAAO,EAAE,GAAG,IAAI,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC;AAC3B,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,KAAiB;IAC1C,MAAM,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,GAAG,UAAU,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC;IAChD,OAAO,QAAQ,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;AAC3B,CAAC;AAED;;8EAE8E;AAC9E,MAAM,UAAU,aAAa,CAAC,IAAc,EAAE,MAAe;IAC3D,MAAM,IAAI,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC;IAC9B,MAAM,KAAK,GAAe,EAAE,CAAC;IAE7B,MAAM,UAAU,GAAG,MAAM;QACvB,CAAC,CAAC;YACE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC,GAAG,KAAK,EAAE,IAAI,EAAE,KAAK,CAAC;YAC1F,KAAK,CAAC,IAAI,CAAC,CAAC,GAAG,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC,GAAG,KAAK,EAAE,KAAK,EAAE,KAAK,CAAC,EAAE,KAAK;SAC7E;QACH,CAAC,CAAC,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,GAAG,KAAK,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;IAE7G,MAAM,iBAAiB,GAAG,MAAM;QAC9B,CAAC,CAAC,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC;QAC1E,CAAC,CAAC,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;IAE7E,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC;QAC5B,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC,EAAE,UAAU,CAAC,CAAC,CAAE,EAAE,CAAC,EAAE,IAAI,CAAC,CAAC,GAAG,iBAAiB,CAAC,CAAC,CAAE,EAAE,CAAC,EAAE,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IAC9F,CAAC;IACD,OAAO,KAAyB,CAAC;AACnC,CAAC;AAED;;;;;;;;;;iFAUiF;AACjF,MAAM,UAAU,oBAAoB,CAAC,IAAc,EAAE,MAAe;IAClE,MAAM,IAAI,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC;IAC9B,MAAM,KAAK,GAAe,EAAE,CAAC;IAC7B,MAAM,aAAa,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;IAE9D,MAAM,UAAU,GAAG,MAAM;QACvB,CAAC,CAAC,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,CAAC;QAClF,CAAC,CAAC,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC;IAEpF,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC;QAC5B,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC,EAAE,UAAU,CAAC,CAAC,CAAE,EAAE,CAAC,EAAE,aAAa,EAAE,CAAC,EAAE,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IAC7E,CAAC;IACD,OAAO,KAAyB,CAAC;AACnC,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,MAAgB,EAAE,MAAgB,EAAE,MAAc;IAC1E,MAAM,EAAE,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC;IAC9B,MAAM,EAAE,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC;IAC9B,MAAM,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,GAAG,GAAG,CAAC,GAAG,GAAG,CAAC,GAAG,GAAG,CAAC;IAC1D,OAAO,UAAU,CAAC;QAChB,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,GAAG,MAAM;QAChC,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,GAAG,MAAM;QAChC,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,KAAK,GAAG,MAAM;KACzB,CAAC,CAAC;AACL,CAAC;AAED,oEAAoE;AACpE,MAAM,UAAU,KAAK,CAAC,KAAe,EAAE,KAA6C;IAClF,MAAM,IAAI,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC;IAC/B,OAAO,UAAU,CAAC;QAChB,CAAC,EAAE,IAAI,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC;QAC1B,CAAC,EAAE,IAAI,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC;QAC1B,CAAC,EAAE,IAAI,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC;KAC3B,CAAC,CAAC;AACL,CAAC;AAED,MAAM,UAAU,KAAK,CAAC,KAAe,EAAE,UAAoB,EAAE,KAAa;IACxE,MAAM,EAAE,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IAC3B,MAAM,EAAE,GAAG,QAAQ,CAAC,UAAU,CAAC,CAAC;IAChC,OAAO,QAAQ,CACb,EAAE,CAAC,CAAC,GAAG,KAAK,GAAG,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,KAAK,CAAC,EACjC,EAAE,CAAC,CAAC,GAAG,KAAK,GAAG,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,KAAK,CAAC,EACjC,EAAE,CAAC,CAAC,GAAG,KAAK,GAAG,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,KAAK,CAAC,CAClC,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,OAAO,CAAC,KAAe,EAAE,MAAc;IACrD,MAAM,KAAK,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC;IAChC,OAAO,UAAU,CAAC,EAAE,GAAG,KAAK,EAAE,CAAC,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC,GAAG,MAAM,EAAE,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC;AACpE,CAAC;AAED,MAAM,UAAU,MAAM,CAAC,KAAe,EAAE,MAAc;IACpD,MAAM,KAAK,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC;IAChC,OAAO,UAAU,CAAC,EAAE,GAAG,KAAK,EAAE,CAAC,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC,GAAG,MAAM,EAAE,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC;AACpE,CAAC;AAED;mFACmF;AACnF,MAAM,UAAU,cAAc,CAAC,GAAa;IAC1C,MAAM,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC;IAClC,OAAO,OAAO,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,GAAG,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,GAAG,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,GAAG,CAAC,GAAG,CAAC;AACrF,CAAC;AAED,yEAAyE;AACzE,MAAM,UAAU,cAAc,CAAC,GAAW;IACxC,MAAM,CAAC,GAAG,GAAG,CAAC,KAAK,CAAC,yDAAyD,CAAC,CAAC;IAC/E,IAAI,CAAC,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,wBAAwB,GAAG,EAAE,CAAC,CAAC;IACvD,OAAO,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC;AAC9E,CAAC;AAED;kEACkE;AAClE,MAAM,UAAU,QAAQ,CAAC,CAAW,EAAE,CAAW;IAC/C,MAAM,EAAE,GAAG,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC3B,MAAM,EAAE,GAAG,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC3B,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,GAAG,GAAG,CAAC,GAAG,GAAG,CAAC,GAAG,GAAG,CAAC,GAAG,GAAG,CAAC,CAAC;AAC3D,CAAC"}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * (7.3 / task 03 — W0) WCAG 2.x contrast math + the black/white "on" picker.
3
+ * Ported from opencode `resolve.ts` (the `lum`/`hit`/`on` helpers, MIT). Backs
4
+ * the contrast-aware token engine `[11.4]` + the WCAG release gate (§2.9):
5
+ * `text-base on bg-base`, `text-on-accent on accent`, diff text on diff bg, … all
6
+ * asserted ≥ AA. Pure; no `node:*`.
7
+ */
8
+ import type { HexColor } from "./schema.js";
9
+ /** WCAG relative luminance of an sRGB color (0=black .. 1=white). */
10
+ export declare function relativeLuminance(hex: HexColor): number;
11
+ /** WCAG contrast ratio between two colors, in [1, 21]. Symmetric. */
12
+ export declare function contrastRatio(a: HexColor, b: HexColor): number;
13
+ /** Pick black or white for maximum legibility on `fill` (text-on-state tokens). */
14
+ export declare function on(fill: HexColor): HexColor;
15
+ /** WCAG AA thresholds: normal text 4.5, large text / UI components 3.0. */
16
+ export declare const WCAG_AA_NORMAL = 4.5;
17
+ export declare const WCAG_AA_LARGE = 3;
18
+ //# sourceMappingURL=contrast.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"contrast.d.ts","sourceRoot":"","sources":["../../src/theme/contrast.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAG5C,qEAAqE;AACrE,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,QAAQ,GAAG,MAAM,CAIvD;AAED,qEAAqE;AACrE,wBAAgB,aAAa,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE,QAAQ,GAAG,MAAM,CAM9D;AAED,mFAAmF;AACnF,wBAAgB,EAAE,CAAC,IAAI,EAAE,QAAQ,GAAG,QAAQ,CAI3C;AAED,2EAA2E;AAC3E,eAAO,MAAM,cAAc,MAAM,CAAC;AAClC,eAAO,MAAM,aAAa,IAAM,CAAC"}
@@ -0,0 +1,25 @@
1
+ import { hexToRgb } from "./color.js";
2
+ /** WCAG relative luminance of an sRGB color (0=black .. 1=white). */
3
+ export function relativeLuminance(hex) {
4
+ const { r, g, b } = hexToRgb(hex);
5
+ const lift = (v) => (v <= 0.04045 ? v / 12.92 : Math.pow((v + 0.055) / 1.055, 2.4));
6
+ return 0.2126 * lift(r) + 0.7152 * lift(g) + 0.0722 * lift(b);
7
+ }
8
+ /** WCAG contrast ratio between two colors, in [1, 21]. Symmetric. */
9
+ export function contrastRatio(a, b) {
10
+ const x = relativeLuminance(a);
11
+ const y = relativeLuminance(b);
12
+ const light = Math.max(x, y);
13
+ const dark = Math.min(x, y);
14
+ return (light + 0.05) / (dark + 0.05);
15
+ }
16
+ /** Pick black or white for maximum legibility on `fill` (text-on-state tokens). */
17
+ export function on(fill) {
18
+ const light = "#ffffff";
19
+ const dark = "#000000";
20
+ return contrastRatio(light, fill) > contrastRatio(dark, fill) ? light : dark;
21
+ }
22
+ /** WCAG AA thresholds: normal text 4.5, large text / UI components 3.0. */
23
+ export const WCAG_AA_NORMAL = 4.5;
24
+ export const WCAG_AA_LARGE = 3.0;
25
+ //# sourceMappingURL=contrast.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"contrast.js","sourceRoot":"","sources":["../../src/theme/contrast.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAEtC,qEAAqE;AACrE,MAAM,UAAU,iBAAiB,CAAC,GAAa;IAC7C,MAAM,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC;IAClC,MAAM,IAAI,GAAG,CAAC,CAAS,EAAU,EAAE,CAAC,CAAC,CAAC,IAAI,OAAO,CAAC,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,GAAG,KAAK,EAAE,GAAG,CAAC,CAAC,CAAC;IACpG,OAAO,MAAM,GAAG,IAAI,CAAC,CAAC,CAAC,GAAG,MAAM,GAAG,IAAI,CAAC,CAAC,CAAC,GAAG,MAAM,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;AAChE,CAAC;AAED,qEAAqE;AACrE,MAAM,UAAU,aAAa,CAAC,CAAW,EAAE,CAAW;IACpD,MAAM,CAAC,GAAG,iBAAiB,CAAC,CAAC,CAAC,CAAC;IAC/B,MAAM,CAAC,GAAG,iBAAiB,CAAC,CAAC,CAAC,CAAC;IAC/B,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IAC7B,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IAC5B,OAAO,CAAC,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,GAAG,IAAI,CAAC,CAAC;AACxC,CAAC;AAED,mFAAmF;AACnF,MAAM,UAAU,EAAE,CAAC,IAAc;IAC/B,MAAM,KAAK,GAAa,SAAS,CAAC;IAClC,MAAM,IAAI,GAAa,SAAS,CAAC;IACjC,OAAO,aAAa,CAAC,KAAK,EAAE,IAAI,CAAC,GAAG,aAAa,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC;AAC/E,CAAC;AAED,2EAA2E;AAC3E,MAAM,CAAC,MAAM,cAAc,GAAG,GAAG,CAAC;AAClC,MAAM,CAAC,MAAM,aAAa,GAAG,GAAG,CAAC"}