@promptctl/rich-js 0.17.0 → 0.18.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 (206) hide show
  1. package/README.md +13 -26
  2. package/package.json +7 -3
  3. package/dist/core/box.d.ts +0 -144
  4. package/dist/core/box.js +0 -391
  5. package/dist/core/cells.d.ts +0 -148
  6. package/dist/core/cells.js +0 -266
  7. package/dist/core/color.d.ts +0 -250
  8. package/dist/core/color.js +0 -1029
  9. package/dist/core/console.d.ts +0 -156
  10. package/dist/core/console.js +0 -472
  11. package/dist/core/emoji.d.ts +0 -24
  12. package/dist/core/emoji.js +0 -391
  13. package/dist/core/export-html.d.ts +0 -24
  14. package/dist/core/export-html.js +0 -106
  15. package/dist/core/export-lines.d.ts +0 -121
  16. package/dist/core/export-lines.js +0 -141
  17. package/dist/core/highlighter.d.ts +0 -33
  18. package/dist/core/highlighter.js +0 -124
  19. package/dist/core/json.d.ts +0 -27
  20. package/dist/core/json.js +0 -53
  21. package/dist/core/markup.d.ts +0 -97
  22. package/dist/core/markup.js +0 -619
  23. package/dist/core/measure.d.ts +0 -27
  24. package/dist/core/measure.js +0 -61
  25. package/dist/core/oklch.d.ts +0 -161
  26. package/dist/core/oklch.js +0 -312
  27. package/dist/core/osc8.d.ts +0 -68
  28. package/dist/core/osc8.js +0 -90
  29. package/dist/core/pretty.d.ts +0 -141
  30. package/dist/core/pretty.js +0 -472
  31. package/dist/core/protocol.d.ts +0 -137
  32. package/dist/core/protocol.js +0 -101
  33. package/dist/core/render.d.ts +0 -84
  34. package/dist/core/render.js +0 -145
  35. package/dist/core/segment.d.ts +0 -142
  36. package/dist/core/segment.js +0 -433
  37. package/dist/core/spinnerData.d.ts +0 -10
  38. package/dist/core/spinnerData.js +0 -115
  39. package/dist/core/strip.d.ts +0 -145
  40. package/dist/core/strip.js +0 -308
  41. package/dist/core/style.d.ts +0 -144
  42. package/dist/core/style.js +0 -723
  43. package/dist/core/subscription.d.ts +0 -12
  44. package/dist/core/subscription.js +0 -12
  45. package/dist/core/text.d.ts +0 -255
  46. package/dist/core/text.js +0 -990
  47. package/dist/core/wrap.d.ts +0 -41
  48. package/dist/core/wrap.js +0 -127
  49. package/dist/host/host-stream.d.ts +0 -30
  50. package/dist/host/host-stream.js +0 -35
  51. package/dist/host/index.d.ts +0 -3
  52. package/dist/host/index.js +0 -2
  53. package/dist/host/terminal-host.d.ts +0 -143
  54. package/dist/host/terminal-host.js +0 -132
  55. package/dist/index.d.ts +0 -87
  56. package/dist/index.js +0 -104
  57. package/dist/node/prompt.d.ts +0 -21
  58. package/dist/node/prompt.js +0 -30
  59. package/dist/node/save.d.ts +0 -17
  60. package/dist/node/save.js +0 -21
  61. package/dist/node/terminal-host.d.ts +0 -84
  62. package/dist/node/terminal-host.js +0 -160
  63. package/dist/node/traceback.d.ts +0 -27
  64. package/dist/node/traceback.js +0 -112
  65. package/dist/renderables/align.d.ts +0 -16
  66. package/dist/renderables/align.js +0 -46
  67. package/dist/renderables/columns.d.ts +0 -61
  68. package/dist/renderables/columns.js +0 -168
  69. package/dist/renderables/constrain.d.ts +0 -15
  70. package/dist/renderables/constrain.js +0 -37
  71. package/dist/renderables/flexStrip.d.ts +0 -41
  72. package/dist/renderables/flexStrip.js +0 -200
  73. package/dist/renderables/group.d.ts +0 -11
  74. package/dist/renderables/group.js +0 -15
  75. package/dist/renderables/layout.d.ts +0 -92
  76. package/dist/renderables/layout.js +0 -315
  77. package/dist/renderables/live.d.ts +0 -47
  78. package/dist/renderables/live.js +0 -131
  79. package/dist/renderables/markdown.d.ts +0 -24
  80. package/dist/renderables/markdown.js +0 -182
  81. package/dist/renderables/padding.d.ts +0 -38
  82. package/dist/renderables/padding.js +0 -140
  83. package/dist/renderables/panel.d.ts +0 -116
  84. package/dist/renderables/panel.js +0 -322
  85. package/dist/renderables/progress.d.ts +0 -90
  86. package/dist/renderables/progress.js +0 -241
  87. package/dist/renderables/progressBar.d.ts +0 -31
  88. package/dist/renderables/progressBar.js +0 -52
  89. package/dist/renderables/prompt.d.ts +0 -49
  90. package/dist/renderables/prompt.js +0 -125
  91. package/dist/renderables/rule.d.ts +0 -24
  92. package/dist/renderables/rule.js +0 -90
  93. package/dist/renderables/spinner.d.ts +0 -29
  94. package/dist/renderables/spinner.js +0 -64
  95. package/dist/renderables/status.d.ts +0 -23
  96. package/dist/renderables/status.js +0 -60
  97. package/dist/renderables/syntax.d.ts +0 -35
  98. package/dist/renderables/syntax.js +0 -114
  99. package/dist/renderables/table.d.ts +0 -182
  100. package/dist/renderables/table.js +0 -697
  101. package/dist/renderables/traceback.d.ts +0 -31
  102. package/dist/renderables/traceback.js +0 -109
  103. package/dist/renderables/tree.d.ts +0 -54
  104. package/dist/renderables/tree.js +0 -159
  105. package/dist/template-bindings/color-funcs.d.ts +0 -87
  106. package/dist/template-bindings/color-funcs.js +0 -219
  107. package/dist/template-bindings/helpers.d.ts +0 -24
  108. package/dist/template-bindings/helpers.js +0 -48
  109. package/dist/template-bindings/index.d.ts +0 -107
  110. package/dist/template-bindings/index.js +0 -144
  111. package/dist/template-bindings/palette-funcs.d.ts +0 -94
  112. package/dist/template-bindings/palette-funcs.js +0 -151
  113. package/dist/template-bindings/style-funcs.d.ts +0 -28
  114. package/dist/template-bindings/style-funcs.js +0 -151
  115. package/dist/themes/buildPalette.d.ts +0 -36
  116. package/dist/themes/buildPalette.js +0 -56
  117. package/dist/themes/colorMath.d.ts +0 -82
  118. package/dist/themes/colorMath.js +0 -254
  119. package/dist/themes/colorRef.d.ts +0 -51
  120. package/dist/themes/colorRef.js +0 -96
  121. package/dist/themes/data/atom-one-dark.d.ts +0 -3
  122. package/dist/themes/data/atom-one-dark.js +0 -158
  123. package/dist/themes/data/atom-one-light.d.ts +0 -3
  124. package/dist/themes/data/atom-one-light.js +0 -158
  125. package/dist/themes/data/catppuccin-frappe.d.ts +0 -3
  126. package/dist/themes/data/catppuccin-frappe.js +0 -158
  127. package/dist/themes/data/catppuccin-latte.d.ts +0 -3
  128. package/dist/themes/data/catppuccin-latte.js +0 -158
  129. package/dist/themes/data/catppuccin-macchiato.d.ts +0 -3
  130. package/dist/themes/data/catppuccin-macchiato.js +0 -158
  131. package/dist/themes/data/catppuccin-mocha.d.ts +0 -3
  132. package/dist/themes/data/catppuccin-mocha.js +0 -158
  133. package/dist/themes/data/cyberpunk.d.ts +0 -17
  134. package/dist/themes/data/cyberpunk.js +0 -191
  135. package/dist/themes/data/default.d.ts +0 -3
  136. package/dist/themes/data/default.js +0 -158
  137. package/dist/themes/data/dracula.d.ts +0 -3
  138. package/dist/themes/data/dracula.js +0 -158
  139. package/dist/themes/data/flexoki.d.ts +0 -3
  140. package/dist/themes/data/flexoki.js +0 -158
  141. package/dist/themes/data/gruvbox.d.ts +0 -3
  142. package/dist/themes/data/gruvbox.js +0 -158
  143. package/dist/themes/data/index.d.ts +0 -35
  144. package/dist/themes/data/index.js +0 -64
  145. package/dist/themes/data/monokai.d.ts +0 -3
  146. package/dist/themes/data/monokai.js +0 -158
  147. package/dist/themes/data/nord.d.ts +0 -3
  148. package/dist/themes/data/nord.js +0 -158
  149. package/dist/themes/data/rose-pine-dawn.d.ts +0 -3
  150. package/dist/themes/data/rose-pine-dawn.js +0 -158
  151. package/dist/themes/data/rose-pine-moon.d.ts +0 -3
  152. package/dist/themes/data/rose-pine-moon.js +0 -158
  153. package/dist/themes/data/rose-pine.d.ts +0 -3
  154. package/dist/themes/data/rose-pine.js +0 -158
  155. package/dist/themes/data/solarized-dark.d.ts +0 -3
  156. package/dist/themes/data/solarized-dark.js +0 -158
  157. package/dist/themes/data/solarized-light.d.ts +0 -3
  158. package/dist/themes/data/solarized-light.js +0 -158
  159. package/dist/themes/data/svg-export.d.ts +0 -3
  160. package/dist/themes/data/svg-export.js +0 -158
  161. package/dist/themes/data/textual-ansi.d.ts +0 -3
  162. package/dist/themes/data/textual-ansi.js +0 -158
  163. package/dist/themes/data/textual-dark.d.ts +0 -3
  164. package/dist/themes/data/textual-dark.js +0 -158
  165. package/dist/themes/data/textual-light.d.ts +0 -3
  166. package/dist/themes/data/textual-light.js +0 -158
  167. package/dist/themes/data/tokyo-night.d.ts +0 -3
  168. package/dist/themes/data/tokyo-night.js +0 -158
  169. package/dist/themes/data/types.d.ts +0 -15
  170. package/dist/themes/data/types.js +0 -1
  171. package/dist/themes/palette.d.ts +0 -21
  172. package/dist/themes/palette.js +0 -28
  173. package/dist/themes/ramp.d.ts +0 -83
  174. package/dist/themes/ramp.js +0 -122
  175. package/dist/themes/registry.d.ts +0 -43
  176. package/dist/themes/registry.js +0 -82
  177. package/dist/themes/terminalThemes.d.ts +0 -54
  178. package/dist/themes/terminalThemes.js +0 -68
  179. package/dist/themes/transpose.d.ts +0 -87
  180. package/dist/themes/transpose.js +0 -138
  181. package/dist/widgets/button.d.ts +0 -49
  182. package/dist/widgets/button.js +0 -206
  183. package/dist/widgets/checkbox.d.ts +0 -41
  184. package/dist/widgets/checkbox.js +0 -155
  185. package/dist/widgets/dropdown.d.ts +0 -67
  186. package/dist/widgets/dropdown.js +0 -453
  187. package/dist/widgets/event-router.d.ts +0 -78
  188. package/dist/widgets/event-router.js +0 -622
  189. package/dist/widgets/focus-manager.d.ts +0 -26
  190. package/dist/widgets/focus-manager.js +0 -193
  191. package/dist/widgets/index.d.ts +0 -22
  192. package/dist/widgets/index.js +0 -15
  193. package/dist/widgets/screen.d.ts +0 -98
  194. package/dist/widgets/screen.js +0 -530
  195. package/dist/widgets/slider.d.ts +0 -57
  196. package/dist/widgets/slider.js +0 -270
  197. package/dist/widgets/static-item.d.ts +0 -40
  198. package/dist/widgets/static-item.js +0 -60
  199. package/dist/widgets/text-input.d.ts +0 -274
  200. package/dist/widgets/text-input.js +0 -1162
  201. package/dist/widgets/toggle.d.ts +0 -44
  202. package/dist/widgets/toggle.js +0 -179
  203. package/dist/widgets/types.d.ts +0 -108
  204. package/dist/widgets/types.js +0 -31
  205. package/dist/widgets/widget-base.d.ts +0 -42
  206. package/dist/widgets/widget-base.js +0 -173
@@ -1,122 +0,0 @@
1
- /**
2
- * A color ramp: a number mapped onto a color through ordered stops.
3
- *
4
- * "What does 73 % spent look like" has no answer in a vocabulary of discrete
5
- * adjustments (`darken`, `mix`, `contrastOn`): each takes colors and returns a
6
- * color, and none takes a *measurement*. Without a ramp the answer gets
7
- * computed outside the theme system — a script emits a hex, a template
8
- * branches `if ge .pct 80 … else if ge .pct 50 …` — and that color decision
9
- * can no longer transpose with the palette it was meant to belong to. A ramp
10
- * is the one function whose input is a number, so the decision stays inside.
11
- *
12
- * A threshold cascade is a ramp too: the same stops with a `step` easing hold
13
- * each color until the next position, which is exactly `≥ threshold → hotter`
14
- * written as data. [LAW:one-type-per-behavior] One primitive; the easing is a
15
- * value, so a gradient and a cascade differ by one word, not by which function
16
- * was called.
17
- *
18
- * Interpolation is in OKLCH (`Oklch.mix`), so a `linear` ramp between two
19
- * theme colors passes through perceptually even steps rather than the muddy
20
- * midpoints of an sRGB blend.
21
- *
22
- * [LAW:one-way-deps] Imports `core/color` and `core/oklch` only; nothing here
23
- * knows what a palette is. Resolving stop *names* is the template binding's
24
- * job (`paletteFuncs`), which hands this module resolved colors.
25
- */
26
- import { Oklch } from "../core/oklch.js";
27
- /**
28
- * How a value between two stops maps to progress along them. Each easing is
29
- * a function on segment progress `t ∈ [0, 1)` — `linear` keeps it, `step`
30
- * holds the left stop for the whole segment.
31
- *
32
- * [LAW:dataflow-not-control-flow] The easing is looked up by name and applied
33
- * unconditionally; `at` runs the same code for a gradient and a cascade.
34
- */
35
- export const RAMP_EASINGS = {
36
- linear: (t) => t,
37
- step: () => 0,
38
- };
39
- export const RAMP_EASING_NAMES = Object.keys(RAMP_EASINGS);
40
- /**
41
- * The gate a spelled easing crosses. [LAW:parse-dont-validate] — returns the
42
- * narrowed name, so `ColorRamp` never re-checks. Unknown names throw naming
43
- * every legal one. [LAW:no-silent-failure]
44
- */
45
- export function parseRampEasing(name) {
46
- if (!Object.hasOwn(RAMP_EASINGS, name)) {
47
- throw new RangeError(`unknown ramp easing ${JSON.stringify(name)}; expected one of ` +
48
- RAMP_EASING_NAMES.map((n) => JSON.stringify(n)).join(", "));
49
- }
50
- return name;
51
- }
52
- /**
53
- * An immutable ramp over stops sorted by position.
54
- *
55
- * [LAW:single-enforcer] The constructor is the one place a ramp's shape is
56
- * checked — at least one stop, every position finite, positions
57
- * non-decreasing — matching the `ColorRgba`/`Oklch` pattern. Positions are
58
- * required to arrive in order rather than being sorted here: a ramp whose
59
- * stops are read from configuration (`warning at 80, error at 50`) is an
60
- * authoring mistake, and sorting would quietly render a different ramp than
61
- * the one written. [LAW:no-silent-failure]
62
- *
63
- * Two stops may share a position: that is a hard edge, the later color
64
- * taking over at exactly that value (CSS gradients spell a hard stop the
65
- * same way).
66
- */
67
- export class ColorRamp {
68
- easing;
69
- stops;
70
- constructor(easing, stops) {
71
- this.easing = easing;
72
- this.stops = stops;
73
- if (stops.length === 0) {
74
- throw new RangeError("a ColorRamp needs at least one stop");
75
- }
76
- for (const [i, stop] of stops.entries()) {
77
- if (!Number.isFinite(stop.at)) {
78
- throw new RangeError(`ColorRamp stop ${i} has a non-finite position ${stop.at}`);
79
- }
80
- const prev = stops[i - 1];
81
- if (prev !== undefined && stop.at < prev.at) {
82
- throw new RangeError(`ColorRamp stops must be in ascending position order; ` +
83
- `stop ${i} at ${stop.at} follows stop ${i - 1} at ${prev.at}`);
84
- }
85
- }
86
- }
87
- /**
88
- * The color at `value`. Below the first stop it is the first color; at or
89
- * above the last stop it is the last; between two stops it is `easing`
90
- * of the way from the lower to the upper, so a value exactly on a stop is
91
- * that stop's color, byte for byte.
92
- *
93
- * The two endpoint returns are the exactness contract, not a shortcut:
94
- * the sRGB → OKLCH → sRGB round-trip can land a channel one unit off, and a
95
- * ramp that does not hit its own stops exactly would make a `step` ramp
96
- * paint a color the author never wrote.
97
- */
98
- at(value) {
99
- if (!Number.isFinite(value)) {
100
- throw new RangeError(`ColorRamp.at needs a finite value, got ${value}`);
101
- }
102
- const stops = this.stops;
103
- // The last stop at or below `value`; -1 when `value` is below them all.
104
- let lower = -1;
105
- while (lower + 1 < stops.length && stops[lower + 1].at <= value)
106
- lower++;
107
- if (lower < 0)
108
- return stops[0].color;
109
- const from = stops[lower];
110
- if (lower === stops.length - 1)
111
- return from.color;
112
- // `to.at > value >= from.at` by construction of `lower`, so the segment
113
- // has positive width and `t ∈ [0, 1)`.
114
- const to = stops[lower + 1];
115
- const t = RAMP_EASINGS[this.easing]((value - from.at) / (to.at - from.at));
116
- if (t <= 0)
117
- return from.color;
118
- if (t >= 1)
119
- return to.color;
120
- return Oklch.fromRgba(from.color).mix(Oklch.fromRgba(to.color), t).toRgba();
121
- }
122
- }
@@ -1,43 +0,0 @@
1
- import { ColorRgba } from "../core/color.js";
2
- import { Palette } from "./palette.js";
3
- import { type ThemeName } from "./data/index.js";
4
- export type { ThemeName };
5
- /**
6
- * Returns the static list of available theme names. Pure and synchronous.
7
- */
8
- export declare function listThemePalettes(): readonly ThemeName[];
9
- /**
10
- * Returns the Palette for `name`, or `null` if unknown.
11
- *
12
- * Synchronous: theme data is bundled at compile time via the data barrel,
13
- * so no I/O happens here. The Palette itself (which requires hex-parsing
14
- * ~150 vars into ColorRgba values) is constructed lazily on first request
15
- * and cached — subsequent calls for the same name return the same instance.
16
- */
17
- export declare function getThemePalette(name: ThemeName): Palette;
18
- export declare function getThemePalette(name: string): Palette | null;
19
- /**
20
- * The eight base colors every theme must declare. Returned by
21
- * `getThemeBaseColors` for callers (notably `terminalThemes.ts`) that only
22
- * need the substrate and would otherwise pay the cost of hydrating the
23
- * full ~150-var palette and polluting the registry cache.
24
- */
25
- export interface ThemeBaseColors {
26
- readonly name: string;
27
- readonly dark: boolean;
28
- readonly bg: ColorRgba;
29
- readonly fg: ColorRgba;
30
- readonly primary: ColorRgba;
31
- readonly secondary: ColorRgba;
32
- readonly accent: ColorRgba;
33
- readonly success: ColorRgba;
34
- readonly warning: ColorRgba;
35
- readonly error: ColorRgba;
36
- }
37
- /**
38
- * Read just the eight base colors from a theme's data file. Cheap — parses
39
- * 8 hex strings, allocates no Palette, touches no cache. Use this when you
40
- * want a `TerminalTheme`-shaped substrate without forcing the full ~150-var
41
- * palette through the registry's hydration path.
42
- */
43
- export declare function getThemeBaseColors(name: ThemeName): ThemeBaseColors;
@@ -1,82 +0,0 @@
1
- import { parseRgbHex, parseRgbaHex } from "../core/color.js";
2
- import { Palette } from "./palette.js";
3
- import { THEMES } from "./data/index.js";
4
- const THEME_NAMES = Object.freeze(Object.keys(THEMES).sort());
5
- const cache = new Map();
6
- /**
7
- * Returns the static list of available theme names. Pure and synchronous.
8
- */
9
- export function listThemePalettes() {
10
- return THEME_NAMES;
11
- }
12
- export function getThemePalette(name) {
13
- if (!isThemeName(name))
14
- return null;
15
- const cached = cache.get(name);
16
- if (cached !== undefined)
17
- return cached;
18
- const palette = hydrate(THEMES[name]);
19
- cache.set(name, palette);
20
- return palette;
21
- }
22
- function isThemeName(name) {
23
- return Object.hasOwn(THEMES, name);
24
- }
25
- /**
26
- * Read just the eight base colors from a theme's data file. Cheap — parses
27
- * 8 hex strings, allocates no Palette, touches no cache. Use this when you
28
- * want a `TerminalTheme`-shaped substrate without forcing the full ~150-var
29
- * palette through the registry's hydration path.
30
- */
31
- export function getThemeBaseColors(name) {
32
- const data = THEMES[name];
33
- return {
34
- name: data.name,
35
- dark: data.dark,
36
- bg: requireBaseVar(data, "background"),
37
- fg: requireBaseVar(data, "foreground"),
38
- primary: requireBaseVar(data, "primary"),
39
- secondary: requireBaseVar(data, "secondary"),
40
- accent: requireBaseVar(data, "accent"),
41
- success: requireBaseVar(data, "success"),
42
- warning: requireBaseVar(data, "warning"),
43
- error: requireBaseVar(data, "error"),
44
- };
45
- }
46
- function requireBaseVar(data, key) {
47
- const v = data.vars[key];
48
- if (v === undefined) {
49
- throw new Error(`Theme ${data.name}: required base var "${key}" missing from data file`);
50
- }
51
- return parseHex(v, data.name, key);
52
- }
53
- /**
54
- * Parse a `ThemePaletteData`'s hex strings into a Palette of ColorRgba.
55
- *
56
- * [LAW:single-enforcer] Hex → ColorRgba conversion for theme data lives
57
- * here, not on Palette. Keeping the parser in this module preserves the
58
- * `core/color → themes/palette` one-way edge (palette.ts must not import
59
- * ColorRgba as a value, or it cycles with core/color's own use of Palette
60
- * for INTERNAL_DEFAULT_THEME).
61
- */
62
- function hydrate(data) {
63
- const map = new Map();
64
- for (const [k, v] of Object.entries(data.vars)) {
65
- map.set(k, parseHex(v, data.name, k));
66
- }
67
- return new Palette(data.name, data.dark, map);
68
- }
69
- // [LAW:single-enforcer] This is the loud-failure boundary for theme hex
70
- // data. `parseRgbHex`/`parseRgbaHex` in core/color.ts trust their input
71
- // shape (they assume the caller validated); here we are the caller from
72
- // the untrusted side (authored data files) and the place that has to
73
- // reject `"0G"`, `""`, `"#GGGGGG"`, etc.
74
- const HEX_RE = /^[0-9a-fA-F]+$/;
75
- function parseHex(value, theme, key) {
76
- const hex = value.startsWith("#") ? value.slice(1) : value;
77
- if ((hex.length !== 6 && hex.length !== 8) || !HEX_RE.test(hex)) {
78
- throw new Error(`Theme ${theme}: var ${key} has invalid hex ${JSON.stringify(value)} ` +
79
- `(expected #RRGGBB or #RRGGBBAA)`);
80
- }
81
- return hex.length === 6 ? parseRgbHex(hex) : parseRgbaHex(hex);
82
- }
@@ -1,54 +0,0 @@
1
- /**
2
- * Pre-built `TerminalTheme` constants — every theme in the registry has a
3
- * matching `<NAME>` export here. There is no inline-only theme; the data
4
- * file is the single source of truth for every theme's hex values.
5
- *
6
- * Editing `data/<name>.ts` updates both the registry's full ~150-var
7
- * palette (via `getThemePalette(name)`) AND the matching `TerminalTheme`
8
- * constant exported below (via `getThemeBaseColors(name)`, which pulls
9
- * just the 8 substrate keys). The two views never drift because both
10
- * derive from the same authored data.
11
- *
12
- * [LAW:one-source-of-truth] Hex values live in `data/<name>.ts`. This
13
- * module is a derived view that builds a `TerminalTheme` from each
14
- * theme's eight base colors via `buildPalette` for the substrate palette
15
- * and `STANDARD_TABLE` for the ANSI substrate.
16
- *
17
- * [LAW:one-type-per-behavior] Every theme has the same shape — name,
18
- * `dark` flag, full Palette in the registry, `TerminalTheme` constant
19
- * here. Consumers can pick any theme by name without branching on which
20
- * APIs work for it.
21
- *
22
- * [LAW:one-way-deps] `core/color → themes/palette` remains the only edge
23
- * into themes/. This file imports only sibling theme modules and core
24
- * color primitives; nothing in `core/` imports back.
25
- *
26
- * Note on `ansiColors`: every preset theme uses `STANDARD_TABLE`. Theme
27
- * identity lives in the semantic `palette`, not in the standard ANSI
28
- * 16/256 LUT — `ColorSpec.parse("red")` is intentionally canonical across
29
- * themes, matching Textual's model.
30
- */
31
- import { TerminalTheme } from "../core/color.js";
32
- export declare const DEFAULT_TERMINAL_THEME: TerminalTheme;
33
- export declare const SVG_EXPORT_THEME: TerminalTheme;
34
- export declare const MONOKAI: TerminalTheme;
35
- export declare const NORD: TerminalTheme;
36
- export declare const GRUVBOX: TerminalTheme;
37
- export declare const DRACULA: TerminalTheme;
38
- export declare const TOKYO_NIGHT: TerminalTheme;
39
- export declare const FLEXOKI: TerminalTheme;
40
- export declare const CYBERPUNK: TerminalTheme;
41
- export declare const CATPPUCCIN_MOCHA: TerminalTheme;
42
- export declare const CATPPUCCIN_LATTE: TerminalTheme;
43
- export declare const CATPPUCCIN_FRAPPE: TerminalTheme;
44
- export declare const CATPPUCCIN_MACCHIATO: TerminalTheme;
45
- export declare const SOLARIZED_DARK: TerminalTheme;
46
- export declare const SOLARIZED_LIGHT: TerminalTheme;
47
- export declare const ROSE_PINE: TerminalTheme;
48
- export declare const ROSE_PINE_MOON: TerminalTheme;
49
- export declare const ROSE_PINE_DAWN: TerminalTheme;
50
- export declare const ATOM_ONE_DARK: TerminalTheme;
51
- export declare const ATOM_ONE_LIGHT: TerminalTheme;
52
- export declare const TEXTUAL_DARK: TerminalTheme;
53
- export declare const TEXTUAL_LIGHT: TerminalTheme;
54
- export declare const TEXTUAL_ANSI: TerminalTheme;
@@ -1,68 +0,0 @@
1
- /**
2
- * Pre-built `TerminalTheme` constants — every theme in the registry has a
3
- * matching `<NAME>` export here. There is no inline-only theme; the data
4
- * file is the single source of truth for every theme's hex values.
5
- *
6
- * Editing `data/<name>.ts` updates both the registry's full ~150-var
7
- * palette (via `getThemePalette(name)`) AND the matching `TerminalTheme`
8
- * constant exported below (via `getThemeBaseColors(name)`, which pulls
9
- * just the 8 substrate keys). The two views never drift because both
10
- * derive from the same authored data.
11
- *
12
- * [LAW:one-source-of-truth] Hex values live in `data/<name>.ts`. This
13
- * module is a derived view that builds a `TerminalTheme` from each
14
- * theme's eight base colors via `buildPalette` for the substrate palette
15
- * and `STANDARD_TABLE` for the ANSI substrate.
16
- *
17
- * [LAW:one-type-per-behavior] Every theme has the same shape — name,
18
- * `dark` flag, full Palette in the registry, `TerminalTheme` constant
19
- * here. Consumers can pick any theme by name without branching on which
20
- * APIs work for it.
21
- *
22
- * [LAW:one-way-deps] `core/color → themes/palette` remains the only edge
23
- * into themes/. This file imports only sibling theme modules and core
24
- * color primitives; nothing in `core/` imports back.
25
- *
26
- * Note on `ansiColors`: every preset theme uses `STANDARD_TABLE`. Theme
27
- * identity lives in the semantic `palette`, not in the standard ANSI
28
- * 16/256 LUT — `ColorSpec.parse("red")` is intentionally canonical across
29
- * themes, matching Textual's model.
30
- */
31
- import { STANDARD_TABLE, TerminalTheme, } from "../core/color.js";
32
- import { buildPalette } from "./buildPalette.js";
33
- import { getThemeBaseColors } from "./registry.js";
34
- function defineTheme(d) {
35
- return new TerminalTheme(d.bg, d.fg, STANDARD_TABLE, buildPalette(d.name, d.dark, {
36
- primary: d.primary,
37
- secondary: d.secondary,
38
- accent: d.accent,
39
- success: d.success,
40
- warning: d.warning,
41
- error: d.error,
42
- background: d.bg,
43
- foreground: d.fg,
44
- }));
45
- }
46
- export const DEFAULT_TERMINAL_THEME = defineTheme(getThemeBaseColors("default"));
47
- export const SVG_EXPORT_THEME = defineTheme(getThemeBaseColors("svg-export"));
48
- export const MONOKAI = defineTheme(getThemeBaseColors("monokai"));
49
- export const NORD = defineTheme(getThemeBaseColors("nord"));
50
- export const GRUVBOX = defineTheme(getThemeBaseColors("gruvbox"));
51
- export const DRACULA = defineTheme(getThemeBaseColors("dracula"));
52
- export const TOKYO_NIGHT = defineTheme(getThemeBaseColors("tokyo-night"));
53
- export const FLEXOKI = defineTheme(getThemeBaseColors("flexoki"));
54
- export const CYBERPUNK = defineTheme(getThemeBaseColors("cyberpunk"));
55
- export const CATPPUCCIN_MOCHA = defineTheme(getThemeBaseColors("catppuccin-mocha"));
56
- export const CATPPUCCIN_LATTE = defineTheme(getThemeBaseColors("catppuccin-latte"));
57
- export const CATPPUCCIN_FRAPPE = defineTheme(getThemeBaseColors("catppuccin-frappe"));
58
- export const CATPPUCCIN_MACCHIATO = defineTheme(getThemeBaseColors("catppuccin-macchiato"));
59
- export const SOLARIZED_DARK = defineTheme(getThemeBaseColors("solarized-dark"));
60
- export const SOLARIZED_LIGHT = defineTheme(getThemeBaseColors("solarized-light"));
61
- export const ROSE_PINE = defineTheme(getThemeBaseColors("rose-pine"));
62
- export const ROSE_PINE_MOON = defineTheme(getThemeBaseColors("rose-pine-moon"));
63
- export const ROSE_PINE_DAWN = defineTheme(getThemeBaseColors("rose-pine-dawn"));
64
- export const ATOM_ONE_DARK = defineTheme(getThemeBaseColors("atom-one-dark"));
65
- export const ATOM_ONE_LIGHT = defineTheme(getThemeBaseColors("atom-one-light"));
66
- export const TEXTUAL_DARK = defineTheme(getThemeBaseColors("textual-dark"));
67
- export const TEXTUAL_LIGHT = defineTheme(getThemeBaseColors("textual-light"));
68
- export const TEXTUAL_ANSI = defineTheme(getThemeBaseColors("textual-ansi"));
@@ -1,87 +0,0 @@
1
- /**
2
- * Transpose a Palette to a new "key" — analogous to transposing a melody.
3
- *
4
- * melody / chord progression :: Palette (relationships between colors)
5
- * key (signature) :: ThemeKey (hue / chroma / lightness deltas)
6
- * "in C major" / "in D…" :: the resulting transposed Palette
7
- *
8
- * Because OKLCH is perceptually uniform, "+30° hue" looks like a
9
- * consistent jump everywhere on the color wheel — the way a perfect-fifth
10
- * interval sounds the same in every musical key. Transposition is closed
11
- * under composition: `transpose(transpose(p, k1), k2)` produces the same
12
- * colors as a single transpose with the combined deltas, modulo round-trip
13
- * quantization.
14
- *
15
- * [LAW:dataflow-not-control-flow] A single uniform per-color transform
16
- * runs for every var in the palette. Anchor protection selects *which*
17
- * `ThemeKey` to apply (data), not *whether* to apply one (branch).
18
- *
19
- * [LAW:one-source-of-truth] Anchor classification lives only in
20
- * `ANCHORED_ROOTS` below. The buildPalette derivation guarantees every
21
- * variant of a semantic root shares the root as its hyphen prefix
22
- * (`error`, `error-darken-1`, `error-lighten-2`, ...), so one set covers
23
- * the whole family.
24
- *
25
- * [LAW:one-way-deps] Imports flow `core/oklch → themes/transpose`;
26
- * nothing in core/ depends back on this file.
27
- */
28
- import { type ThemeKey } from "../core/oklch.js";
29
- import { Palette } from "./palette.js";
30
- /**
31
- * Semantic roots whose hue is locked under transposition. `error` must
32
- * look red-ish, `success` green-ish, `warning` amber-ish — rotating the
33
- * hue would make the UI lie about meaning. Lightness and chroma *still*
34
- * transform for these roles, so they invert correctly during dark↔light
35
- * flips and respond to chroma scaling alongside everything else.
36
- */
37
- export declare const ANCHORED_ROOTS: ReadonlySet<string>;
38
- /**
39
- * Whether a palette var's hue is locked under transposition. The single
40
- * predicate used by `transposePalette`. Exported so callers building
41
- * higher-level theme machinery can stay consistent with the locking rule.
42
- */
43
- export declare function isAnchored(varName: string): boolean;
44
- /**
45
- * Return a new `Palette` whose colors are the transposition of `palette`'s
46
- * colors by `key`. Pure. Identity (`IDENTITY`) returns a Palette with byte-exact
47
- * colors — fast-pathed so identity does not pay the sRGB↔OKLCH round-trip
48
- * quantization cost.
49
- *
50
- * The `dark` flag of the result is derived from the actual lightness of
51
- * the resulting `background` var (`Oklch.fromRgba(bg).l < 0.5`) — *not*
52
- * from the key's coefficients. The strongest theorem: "dark iff
53
- * background is dark." This is honest under every transform — pure
54
- * lightness shifts, mirror-inversions, hue rotations that don't touch L,
55
- * and combinations of all three. [LAW:types-are-the-program]
56
- *
57
- * The transposing path throws if the palette has no `background` var (the
58
- * `dark`-flag derivation has nothing to read). Failing loudly is preferred
59
- * over a silent fallback because the alternative — trusting the source
60
- * `palette.dark` after an arbitrary L-transform — produces flags that lie.
61
- * The identity fast-path is exempt: it preserves the source `dark` flag
62
- * verbatim (no derivation), so it needs no `background` and never throws.
63
- *
64
- * @param name Optional override for the resulting palette name. Defaults
65
- * to the source palette's name. Callers building a family of transposed
66
- * palettes (e.g. "gruvbox +60°") supply their own.
67
- */
68
- export declare function transposePalette(palette: Palette, key: ThemeKey, name?: string): Palette;
69
- /**
70
- * Build the `ThemeKey` that rotates `palette` so its *tonic* var lands on
71
- * `targetHueDeg`. The musical operation directly: a key is the set of
72
- * intervals from the tonic, so "play this theme in the key of <hue>" means
73
- * "shift every color by exactly the interval that carries the tonic's
74
- * current hue to the target." Pick the tonic's pitch and the rest follows.
75
- *
76
- * Returns a hue-only key (chroma and lightness untouched). Callers that also
77
- * want to scale chroma or shift lightness spread their own axes over the
78
- * result — those are independent transposition dimensions, not part of
79
- * choosing the key. [LAW:one-type-per-behavior] a degree-shift key and a
80
- * root-note key are the *same* transform; this is just a second constructor
81
- * for it, so `transposePalette` stays untouched.
82
- *
83
- * Throws if `tonicVar` is absent — the interval has no anchor to measure
84
- * from, so there is no honest key to return. Failing loudly beats inventing
85
- * a zero shift that would silently mean "no transposition."
86
- */
87
- export declare function themeKeyForRoot(palette: Palette, tonicVar: string, targetHueDeg: number): ThemeKey;
@@ -1,138 +0,0 @@
1
- /**
2
- * Transpose a Palette to a new "key" — analogous to transposing a melody.
3
- *
4
- * melody / chord progression :: Palette (relationships between colors)
5
- * key (signature) :: ThemeKey (hue / chroma / lightness deltas)
6
- * "in C major" / "in D…" :: the resulting transposed Palette
7
- *
8
- * Because OKLCH is perceptually uniform, "+30° hue" looks like a
9
- * consistent jump everywhere on the color wheel — the way a perfect-fifth
10
- * interval sounds the same in every musical key. Transposition is closed
11
- * under composition: `transpose(transpose(p, k1), k2)` produces the same
12
- * colors as a single transpose with the combined deltas, modulo round-trip
13
- * quantization.
14
- *
15
- * [LAW:dataflow-not-control-flow] A single uniform per-color transform
16
- * runs for every var in the palette. Anchor protection selects *which*
17
- * `ThemeKey` to apply (data), not *whether* to apply one (branch).
18
- *
19
- * [LAW:one-source-of-truth] Anchor classification lives only in
20
- * `ANCHORED_ROOTS` below. The buildPalette derivation guarantees every
21
- * variant of a semantic root shares the root as its hyphen prefix
22
- * (`error`, `error-darken-1`, `error-lighten-2`, ...), so one set covers
23
- * the whole family.
24
- *
25
- * [LAW:one-way-deps] Imports flow `core/oklch → themes/transpose`;
26
- * nothing in core/ depends back on this file.
27
- */
28
- import { Oklch, isIdentityKey } from "../core/oklch.js";
29
- import { Palette } from "./palette.js";
30
- /**
31
- * Semantic roots whose hue is locked under transposition. `error` must
32
- * look red-ish, `success` green-ish, `warning` amber-ish — rotating the
33
- * hue would make the UI lie about meaning. Lightness and chroma *still*
34
- * transform for these roles, so they invert correctly during dark↔light
35
- * flips and respond to chroma scaling alongside everything else.
36
- */
37
- // [LAW:types-are-the-program] The `ReadonlySet` type is the immutability
38
- // enforcement — typed code cannot call `add`/`delete`. (`Object.freeze` is
39
- // not used here because it is a no-op on Set membership; relying on it would
40
- // imply a runtime guarantee it does not provide.)
41
- export const ANCHORED_ROOTS = new Set([
42
- "error",
43
- "success",
44
- "warning",
45
- ]);
46
- function rootOf(varName) {
47
- const dash = varName.indexOf("-");
48
- return dash === -1 ? varName : varName.slice(0, dash);
49
- }
50
- /**
51
- * Whether a palette var's hue is locked under transposition. The single
52
- * predicate used by `transposePalette`. Exported so callers building
53
- * higher-level theme machinery can stay consistent with the locking rule.
54
- */
55
- export function isAnchored(varName) {
56
- return ANCHORED_ROOTS.has(rootOf(varName));
57
- }
58
- /**
59
- * Return a new `Palette` whose colors are the transposition of `palette`'s
60
- * colors by `key`. Pure. Identity (`IDENTITY`) returns a Palette with byte-exact
61
- * colors — fast-pathed so identity does not pay the sRGB↔OKLCH round-trip
62
- * quantization cost.
63
- *
64
- * The `dark` flag of the result is derived from the actual lightness of
65
- * the resulting `background` var (`Oklch.fromRgba(bg).l < 0.5`) — *not*
66
- * from the key's coefficients. The strongest theorem: "dark iff
67
- * background is dark." This is honest under every transform — pure
68
- * lightness shifts, mirror-inversions, hue rotations that don't touch L,
69
- * and combinations of all three. [LAW:types-are-the-program]
70
- *
71
- * The transposing path throws if the palette has no `background` var (the
72
- * `dark`-flag derivation has nothing to read). Failing loudly is preferred
73
- * over a silent fallback because the alternative — trusting the source
74
- * `palette.dark` after an arbitrary L-transform — produces flags that lie.
75
- * The identity fast-path is exempt: it preserves the source `dark` flag
76
- * verbatim (no derivation), so it needs no `background` and never throws.
77
- *
78
- * @param name Optional override for the resulting palette name. Defaults
79
- * to the source palette's name. Callers building a family of transposed
80
- * palettes (e.g. "gruvbox +60°") supply their own.
81
- */
82
- export function transposePalette(palette, key, name) {
83
- if (isIdentityKey(key)) {
84
- return new Palette(name ?? palette.name, palette.dark, palette.vars);
85
- }
86
- // Anchors share *everything except* hue with the user's key. They still
87
- // lightness-invert in a dark↔light flip; they still chroma-scale in a
88
- // saturation sweep — only their hue is held.
89
- const anchorKey = { ...key, hueShift: 0 };
90
- const next = new Map();
91
- for (const [varName, color] of palette.vars) {
92
- const effective = isAnchored(varName) ? anchorKey : key;
93
- next.set(varName, Oklch.fromRgba(color).applyKey(effective).toRgba());
94
- }
95
- const newBackground = next.get("background");
96
- if (newBackground === undefined) {
97
- throw new Error(`transposePalette: palette "${palette.name}" has no "background" ` +
98
- `var; cannot derive the dark flag without a background color.`);
99
- }
100
- const newDark = Oklch.fromRgba(newBackground).l < 0.5;
101
- return new Palette(name ?? palette.name, newDark, next);
102
- }
103
- /**
104
- * Build the `ThemeKey` that rotates `palette` so its *tonic* var lands on
105
- * `targetHueDeg`. The musical operation directly: a key is the set of
106
- * intervals from the tonic, so "play this theme in the key of <hue>" means
107
- * "shift every color by exactly the interval that carries the tonic's
108
- * current hue to the target." Pick the tonic's pitch and the rest follows.
109
- *
110
- * Returns a hue-only key (chroma and lightness untouched). Callers that also
111
- * want to scale chroma or shift lightness spread their own axes over the
112
- * result — those are independent transposition dimensions, not part of
113
- * choosing the key. [LAW:one-type-per-behavior] a degree-shift key and a
114
- * root-note key are the *same* transform; this is just a second constructor
115
- * for it, so `transposePalette` stays untouched.
116
- *
117
- * Throws if `tonicVar` is absent — the interval has no anchor to measure
118
- * from, so there is no honest key to return. Failing loudly beats inventing
119
- * a zero shift that would silently mean "no transposition."
120
- */
121
- export function themeKeyForRoot(palette, tonicVar, targetHueDeg) {
122
- // Validate the numeric input at the boundary: a non-finite target would
123
- // propagate as NaN to Oklch's constructor several calls downstream, where
124
- // the error is far less actionable.
125
- if (!Number.isFinite(targetHueDeg)) {
126
- throw new RangeError(`themeKeyForRoot: targetHueDeg must be a finite number; got ${targetHueDeg}`);
127
- }
128
- const tonic = palette.get(tonicVar);
129
- if (tonic === undefined) {
130
- throw new Error(`themeKeyForRoot: palette "${palette.name}" has no "${tonicVar}" var ` +
131
- `to use as the tonic; cannot measure the transposition interval.`);
132
- }
133
- const tonicHue = Oklch.fromRgba(tonic).h;
134
- let hueShift = (targetHueDeg - tonicHue) % 360;
135
- if (hueShift < 0)
136
- hueShift += 360;
137
- return { hueShift, chromaScale: 1, lightnessScale: 1, lightnessShift: 0 };
138
- }
@@ -1,49 +0,0 @@
1
- /**
2
- * Button widget — labeled action trigger with variant styling.
3
- * [LAW:dataflow-not-control-flow] rendering is a pure function of observable state.
4
- * [LAW:one-type-per-behavior] shared widget infrastructure lives on WidgetBase.
5
- *
6
- * Four visual states:
7
- * normal — variant colors from theme semantic palette (muted)
8
- * hover — full variant accent bg + on-accent fg (WCAG contrast)
9
- * focus — brackets [ label ] surrounding the button
10
- * active — same color pair as hover, plus bold (pressed cue)
11
- *
12
- * States compose: active > focus > hover > normal. Active and hover
13
- * deliberately share colors — active differentiates via bold rather
14
- * than fg/bg inversion, because inversion produces mostly-accent text
15
- * on bg-tinted surface, which is unreadable for accents whose contrast
16
- * partner depends on luminance.
17
- */
18
- import { Segment } from "../core/segment.js";
19
- import type { RenderOptions } from "../core/protocol.js";
20
- import type { TerminalTheme } from "../core/color.js";
21
- import { WidgetBase } from "./widget-base.js";
22
- import type { KeyEvent, WidgetMouseEvent } from "./types.js";
23
- export type ButtonVariant = "default" | "primary" | "success" | "warning" | "danger";
24
- export interface ButtonOptions {
25
- label: string;
26
- variant?: ButtonVariant;
27
- id?: string;
28
- disabled?: boolean;
29
- theme?: TerminalTheme;
30
- }
31
- export declare class Button extends WidgetBase {
32
- readonly id: string;
33
- readonly focusable = true;
34
- accessor label: string;
35
- accessor variant: ButtonVariant;
36
- private accessor _theme;
37
- constructor(options: ButtonOptions);
38
- setTheme(theme: TerminalTheme): void;
39
- handleKey(event: KeyEvent): void;
40
- handleMouse(event: WidgetMouseEvent): void;
41
- setActive(value: boolean): void;
42
- render(_options: RenderOptions): Iterable<Segment>;
43
- measure(_options: RenderOptions): {
44
- minimum: number;
45
- maximum: number;
46
- };
47
- private resolveColors;
48
- private resolvePalette;
49
- }