@promptctl/rich-js 0.18.1 → 0.19.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 +9 -7
- package/dist/core/box.d.ts +3 -1
- package/dist/core/box.js +6 -13
- package/dist/core/cells.d.ts +61 -28
- package/dist/core/cells.js +171 -124
- package/dist/core/clock.d.ts +48 -0
- package/dist/core/clock.js +42 -0
- package/dist/core/color.d.ts +98 -18
- package/dist/core/color.js +331 -144
- package/dist/core/console.d.ts +38 -7
- package/dist/core/console.js +159 -90
- package/dist/core/easing.d.ts +86 -0
- package/dist/core/easing.js +171 -0
- package/dist/core/env.d.ts +16 -0
- package/dist/core/env.js +16 -0
- package/dist/core/export-html.js +1 -4
- package/dist/core/export-lines.d.ts +22 -13
- package/dist/core/export-lines.js +37 -19
- package/dist/core/export-svg.d.ts +49 -0
- package/dist/core/export-svg.js +213 -0
- package/dist/core/fnv1a.d.ts +10 -0
- package/dist/core/fnv1a.js +17 -0
- package/dist/core/highlighter.d.ts +2 -2
- package/dist/core/highlighter.js +113 -47
- package/dist/core/json.js +1 -1
- package/dist/core/markup.d.ts +28 -7
- package/dist/core/markup.js +235 -312
- package/dist/core/measure.d.ts +3 -3
- package/dist/core/measure.js +12 -7
- package/dist/core/memo.d.ts +19 -0
- package/dist/core/memo.js +34 -0
- package/dist/core/osc8.d.ts +6 -6
- package/dist/core/osc8.js +9 -21
- package/dist/core/paint.d.ts +107 -0
- package/dist/core/paint.js +150 -0
- package/dist/core/place.d.ts +1 -1
- package/dist/core/place.js +4 -6
- package/dist/core/pretty.d.ts +105 -2
- package/dist/core/pretty.js +527 -97
- package/dist/core/protocol.d.ts +41 -3
- package/dist/core/protocol.js +20 -0
- package/dist/core/render.d.ts +33 -30
- package/dist/core/render.js +43 -83
- package/dist/core/segment.d.ts +6 -5
- package/dist/core/segment.js +11 -15
- package/dist/core/strip.d.ts +13 -2
- package/dist/core/strip.js +44 -23
- package/dist/core/style.d.ts +27 -7
- package/dist/core/style.js +97 -34
- package/dist/core/text.d.ts +43 -16
- package/dist/core/text.js +180 -59
- package/dist/core/wrap.d.ts +5 -0
- package/dist/core/wrap.js +16 -3
- package/dist/host/app.d.ts +31 -19
- package/dist/host/app.js +90 -60
- package/dist/host/index.d.ts +2 -1
- package/dist/host/terminal-host.d.ts +3 -2
- package/dist/index.d.ts +17 -10
- package/dist/index.js +11 -4
- package/dist/node/prompt.d.ts +13 -0
- package/dist/node/prompt.js +30 -9
- package/dist/node/save.d.ts +4 -3
- package/dist/node/save.js +6 -3
- package/dist/node/terminal-host.d.ts +3 -2
- package/dist/node/traceback.d.ts +2 -1
- package/dist/node/traceback.js +3 -39
- package/dist/renderables/align.js +2 -9
- package/dist/renderables/columns.d.ts +45 -29
- package/dist/renderables/columns.js +142 -103
- package/dist/renderables/constrain.js +6 -12
- package/dist/renderables/effect.d.ts +98 -0
- package/dist/renderables/effect.js +160 -0
- package/dist/renderables/embed.d.ts +87 -30
- package/dist/renderables/embed.js +134 -45
- package/dist/renderables/group.d.ts +6 -3
- package/dist/renderables/group.js +5 -0
- package/dist/renderables/layout.d.ts +6 -23
- package/dist/renderables/layout.js +24 -113
- package/dist/renderables/live.d.ts +40 -16
- package/dist/renderables/live.js +96 -83
- package/dist/renderables/markdown.d.ts +16 -2
- package/dist/renderables/markdown.js +521 -118
- package/dist/renderables/padding.d.ts +22 -1
- package/dist/renderables/padding.js +30 -24
- package/dist/renderables/panel.d.ts +31 -33
- package/dist/renderables/panel.js +137 -141
- package/dist/renderables/progress.d.ts +104 -16
- package/dist/renderables/progress.js +205 -81
- package/dist/renderables/progressBar.d.ts +2 -2
- package/dist/renderables/progressBar.js +30 -19
- package/dist/renderables/prompt.d.ts +37 -15
- package/dist/renderables/prompt.js +125 -85
- package/dist/renderables/ratio.d.ts +123 -0
- package/dist/renderables/ratio.js +213 -0
- package/dist/renderables/rule.d.ts +1 -0
- package/dist/renderables/rule.js +44 -48
- package/dist/renderables/spinner.d.ts +28 -2
- package/dist/renderables/spinner.js +52 -19
- package/dist/renderables/status.d.ts +13 -7
- package/dist/renderables/status.js +15 -29
- package/dist/renderables/syntax.d.ts +37 -7
- package/dist/renderables/syntax.js +134 -83
- package/dist/renderables/table.d.ts +58 -20
- package/dist/renderables/table.js +370 -192
- package/dist/renderables/traceback.d.ts +5 -4
- package/dist/renderables/traceback.js +239 -68
- package/dist/renderables/tree.d.ts +10 -2
- package/dist/renderables/tree.js +61 -34
- package/dist/renderables/viewport.js +2 -4
- package/dist/template-bindings/color-funcs.d.ts +31 -9
- package/dist/template-bindings/color-funcs.js +40 -14
- package/dist/template-bindings/helpers.d.ts +4 -2
- package/dist/template-bindings/helpers.js +5 -20
- package/dist/template-bindings/index.d.ts +29 -17
- package/dist/template-bindings/index.js +36 -20
- package/dist/template-bindings/palette-funcs.d.ts +3 -1
- package/dist/template-bindings/palette-funcs.js +11 -7
- package/dist/template-bindings/style-funcs.js +4 -2
- package/dist/themes/buildPalette.d.ts +24 -3
- package/dist/themes/buildPalette.js +52 -8
- package/dist/themes/colorMath.d.ts +29 -17
- package/dist/themes/colorMath.js +74 -48
- package/dist/themes/colorRef.d.ts +2 -17
- package/dist/themes/colorRef.js +13 -31
- package/dist/themes/palette.d.ts +24 -0
- package/dist/themes/palette.js +46 -3
- package/dist/themes/ramp.d.ts +21 -34
- package/dist/themes/ramp.js +23 -42
- package/dist/themes/registry.js +39 -28
- package/dist/widgets/button.d.ts +2 -6
- package/dist/widgets/button.js +9 -40
- package/dist/widgets/checkbox.d.ts +2 -5
- package/dist/widgets/checkbox.js +9 -31
- package/dist/widgets/dropdown.d.ts +2 -5
- package/dist/widgets/dropdown.js +14 -48
- package/dist/widgets/ink.d.ts +22 -0
- package/dist/widgets/ink.js +31 -0
- package/dist/widgets/slider.d.ts +2 -5
- package/dist/widgets/slider.js +11 -34
- package/dist/widgets/text-input.d.ts +19 -10
- package/dist/widgets/text-input.js +156 -147
- package/dist/widgets/themed-widget.d.ts +20 -0
- package/dist/widgets/themed-widget.js +89 -0
- package/dist/widgets/toggle.d.ts +2 -5
- package/dist/widgets/toggle.js +8 -31
- package/dist/widgets/widget-app.d.ts +2 -0
- package/dist/widgets/widget-app.js +13 -6
- package/dist/widgets/widget-base.d.ts +2 -0
- package/dist/widgets/widget-base.js +9 -2
- package/package.json +11 -1
package/dist/themes/registry.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { Palette } from "./palette.js";
|
|
1
|
+
import { ColorParseError, ColorTable, parseHexColor } from "../core/color.js";
|
|
2
|
+
import { Palette, drawnOn } from "./palette.js";
|
|
3
|
+
import { ACCENT_KEYS, accentText } from "./buildPalette.js";
|
|
3
4
|
import { THEMES } from "./data/index.js";
|
|
4
5
|
import { ANSI_SLOTS } from "./data/types.js";
|
|
5
6
|
const THEME_NAMES = Object.freeze(Object.keys(THEMES).sort());
|
|
@@ -31,17 +32,22 @@ function isThemeName(name) {
|
|
|
31
32
|
*/
|
|
32
33
|
export function getThemeBaseColors(name) {
|
|
33
34
|
const data = THEMES[name];
|
|
35
|
+
const bg = requireBaseVar(data, "background");
|
|
36
|
+
// The colours `getThemePalette(name)` hands out for the same names: drawn on
|
|
37
|
+
// the theme's own background, as a Palette draws every colour it holds.
|
|
38
|
+
const draw = drawnOn(data.name, bg);
|
|
39
|
+
const base = (key) => draw(requireBaseVar(data, key));
|
|
34
40
|
return {
|
|
35
41
|
name: data.name,
|
|
36
42
|
dark: data.dark,
|
|
37
|
-
bg
|
|
38
|
-
fg:
|
|
39
|
-
primary:
|
|
40
|
-
secondary:
|
|
41
|
-
accent:
|
|
42
|
-
success:
|
|
43
|
-
warning:
|
|
44
|
-
error:
|
|
43
|
+
bg,
|
|
44
|
+
fg: base("foreground"),
|
|
45
|
+
primary: base("primary"),
|
|
46
|
+
secondary: base("secondary"),
|
|
47
|
+
accent: base("accent"),
|
|
48
|
+
success: base("success"),
|
|
49
|
+
warning: base("warning"),
|
|
50
|
+
error: base("error"),
|
|
45
51
|
ansi: new ColorTable(ANSI_SLOTS.map((slot) => parseOpaqueHex(data.ansi[slot], data.name, `ansi.${slot}`))),
|
|
46
52
|
};
|
|
47
53
|
}
|
|
@@ -64,31 +70,36 @@ function requireBaseVar(data, key) {
|
|
|
64
70
|
function hydrate(data) {
|
|
65
71
|
const map = new Map();
|
|
66
72
|
for (const [k, v] of Object.entries(data.vars)) {
|
|
67
|
-
map.set(k, parseHex(v, data.name, k));
|
|
73
|
+
map.set(k, parseHex(v, data.name, `var ${k}`));
|
|
74
|
+
}
|
|
75
|
+
// The data is Textual's as authored; its `text-*` is held to the pair this
|
|
76
|
+
// library promises by the same rule `buildPalette` derives it with.
|
|
77
|
+
for (const key of ACCENT_KEYS) {
|
|
78
|
+
const text = requireBaseVar(data, `text-${key}`);
|
|
79
|
+
map.set(`text-${key}`, accentText(text, requireBaseVar(data, `${key}-muted`), requireBaseVar(data, "background")));
|
|
68
80
|
}
|
|
69
81
|
return new Palette(data.name, data.dark, map);
|
|
70
82
|
}
|
|
71
|
-
//
|
|
72
|
-
//
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
83
|
+
// Theme data is authored, so a malformed colour names the theme and the key it
|
|
84
|
+
// sits under; the grammar itself is `parseHexColor`'s.
|
|
85
|
+
function parseHex(value, theme, key) {
|
|
86
|
+
try {
|
|
87
|
+
return parseHexColor(value);
|
|
88
|
+
}
|
|
89
|
+
catch (cause) {
|
|
90
|
+
if (!(cause instanceof ColorParseError))
|
|
91
|
+
throw cause;
|
|
92
|
+
throw new Error(`Theme ${theme}: ${key}: ${cause.message}`, { cause });
|
|
93
|
+
}
|
|
94
|
+
}
|
|
77
95
|
/**
|
|
78
96
|
* An ANSI slot is a colour a terminal paints, never a blend, so it takes no
|
|
79
97
|
* alpha: `flattenAlpha` leaves a STANDARD spec alone and would pass one through.
|
|
80
98
|
*/
|
|
81
99
|
function parseOpaqueHex(value, theme, key) {
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
return parseRgbHex(value.slice(1));
|
|
86
|
-
}
|
|
87
|
-
function parseHex(value, theme, key) {
|
|
88
|
-
const hex = value.startsWith("#") ? value.slice(1) : value;
|
|
89
|
-
if ((hex.length !== 6 && hex.length !== 8) || !HEX_RE.test(hex)) {
|
|
90
|
-
throw new Error(`Theme ${theme}: var ${key} has invalid hex ${JSON.stringify(value)} ` +
|
|
91
|
-
`(expected #RRGGBB or #RRGGBBAA)`);
|
|
100
|
+
const color = parseHex(value, theme, key);
|
|
101
|
+
if (color.alpha !== 1) {
|
|
102
|
+
throw new Error(`Theme ${theme}: ${key} has alpha in ${JSON.stringify(value)} (expected #RRGGBB)`);
|
|
92
103
|
}
|
|
93
|
-
return
|
|
104
|
+
return color;
|
|
94
105
|
}
|
package/dist/widgets/button.d.ts
CHANGED
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
import { Segment } from "../core/segment.js";
|
|
19
19
|
import type { RenderOptions } from "../core/protocol.js";
|
|
20
20
|
import type { TerminalTheme } from "../core/color.js";
|
|
21
|
-
import {
|
|
21
|
+
import { ThemedWidget } from "./themed-widget.js";
|
|
22
22
|
import type { KeyEvent, WidgetMouseEvent } from "./types.js";
|
|
23
23
|
export type ButtonVariant = "default" | "primary" | "success" | "warning" | "danger";
|
|
24
24
|
export interface ButtonOptions {
|
|
@@ -28,14 +28,12 @@ export interface ButtonOptions {
|
|
|
28
28
|
disabled?: boolean;
|
|
29
29
|
theme?: TerminalTheme;
|
|
30
30
|
}
|
|
31
|
-
export declare class Button extends
|
|
31
|
+
export declare class Button extends ThemedWidget {
|
|
32
32
|
readonly id: string;
|
|
33
33
|
readonly focusable = true;
|
|
34
34
|
accessor label: string;
|
|
35
35
|
accessor variant: ButtonVariant;
|
|
36
|
-
private accessor _theme;
|
|
37
36
|
constructor(options: ButtonOptions);
|
|
38
|
-
setTheme(theme: TerminalTheme): void;
|
|
39
37
|
handleKey(event: KeyEvent): void;
|
|
40
38
|
handleMouse(event: WidgetMouseEvent): void;
|
|
41
39
|
setActive(value: boolean): void;
|
|
@@ -44,6 +42,4 @@ export declare class Button extends WidgetBase {
|
|
|
44
42
|
minimum: number;
|
|
45
43
|
maximum: number;
|
|
46
44
|
};
|
|
47
|
-
private resolveColors;
|
|
48
|
-
private resolvePalette;
|
|
49
45
|
}
|
package/dist/widgets/button.js
CHANGED
|
@@ -52,10 +52,9 @@ var __esDecorate = (this && this.__esDecorate) || function (ctor, descriptorIn,
|
|
|
52
52
|
import { observable, action, observableRef } from "mobx";
|
|
53
53
|
import { Segment } from "../core/segment.js";
|
|
54
54
|
import { Style } from "../core/style.js";
|
|
55
|
-
import { ColorSpec } from "../core/color.js";
|
|
56
55
|
import { cellLen } from "../core/cells.js";
|
|
57
|
-
import {
|
|
58
|
-
import {
|
|
56
|
+
import { ThemedWidget } from "./themed-widget.js";
|
|
57
|
+
import { ink } from "./ink.js";
|
|
59
58
|
// Variant → palette key mapping. Per variant:
|
|
60
59
|
// bg / fg — normal state. Muted accent bg + mostly-accent fg → readable.
|
|
61
60
|
// hover — full accent bg; pair with hoverFg, NOT with `fg`. The
|
|
@@ -70,7 +69,7 @@ const VARIANT_KEYS = {
|
|
|
70
69
|
danger: { bg: "error-muted", fg: "text-error", hover: "error", hoverFg: "on-error" },
|
|
71
70
|
};
|
|
72
71
|
let Button = (() => {
|
|
73
|
-
let _classSuper =
|
|
72
|
+
let _classSuper = ThemedWidget;
|
|
74
73
|
let _instanceExtraInitializers = [];
|
|
75
74
|
let _label_decorators;
|
|
76
75
|
let _label_initializers = [];
|
|
@@ -78,10 +77,6 @@ let Button = (() => {
|
|
|
78
77
|
let _variant_decorators;
|
|
79
78
|
let _variant_initializers = [];
|
|
80
79
|
let _variant_extraInitializers = [];
|
|
81
|
-
let __theme_decorators;
|
|
82
|
-
let __theme_initializers = [];
|
|
83
|
-
let __theme_extraInitializers = [];
|
|
84
|
-
let _setTheme_decorators;
|
|
85
80
|
let _handleKey_decorators;
|
|
86
81
|
let _handleMouse_decorators;
|
|
87
82
|
let _setActive_decorators;
|
|
@@ -90,15 +85,11 @@ let Button = (() => {
|
|
|
90
85
|
const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
|
|
91
86
|
_label_decorators = [observable];
|
|
92
87
|
_variant_decorators = [observableRef];
|
|
93
|
-
__theme_decorators = [observableRef];
|
|
94
|
-
_setTheme_decorators = [action];
|
|
95
88
|
_handleKey_decorators = [action];
|
|
96
89
|
_handleMouse_decorators = [action];
|
|
97
90
|
_setActive_decorators = [action];
|
|
98
91
|
__esDecorate(this, null, _label_decorators, { kind: "accessor", name: "label", static: false, private: false, access: { has: obj => "label" in obj, get: obj => obj.label, set: (obj, value) => { obj.label = value; } }, metadata: _metadata }, _label_initializers, _label_extraInitializers);
|
|
99
92
|
__esDecorate(this, null, _variant_decorators, { kind: "accessor", name: "variant", static: false, private: false, access: { has: obj => "variant" in obj, get: obj => obj.variant, set: (obj, value) => { obj.variant = value; } }, metadata: _metadata }, _variant_initializers, _variant_extraInitializers);
|
|
100
|
-
__esDecorate(this, null, __theme_decorators, { kind: "accessor", name: "_theme", static: false, private: false, access: { has: obj => "_theme" in obj, get: obj => obj._theme, set: (obj, value) => { obj._theme = value; } }, metadata: _metadata }, __theme_initializers, __theme_extraInitializers);
|
|
101
|
-
__esDecorate(this, null, _setTheme_decorators, { kind: "method", name: "setTheme", static: false, private: false, access: { has: obj => "setTheme" in obj, get: obj => obj.setTheme }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
102
93
|
__esDecorate(this, null, _handleKey_decorators, { kind: "method", name: "handleKey", static: false, private: false, access: { has: obj => "handleKey" in obj, get: obj => obj.handleKey }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
103
94
|
__esDecorate(this, null, _handleMouse_decorators, { kind: "method", name: "handleMouse", static: false, private: false, access: { has: obj => "handleMouse" in obj, get: obj => obj.handleMouse }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
104
95
|
__esDecorate(this, null, _setActive_decorators, { kind: "method", name: "setActive", static: false, private: false, access: { has: obj => "setActive" in obj, get: obj => obj.setActive }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
@@ -112,21 +103,14 @@ let Button = (() => {
|
|
|
112
103
|
#variant_accessor_storage = (__runInitializers(this, _label_extraInitializers), __runInitializers(this, _variant_initializers, void 0));
|
|
113
104
|
get variant() { return this.#variant_accessor_storage; }
|
|
114
105
|
set variant(value) { this.#variant_accessor_storage = value; }
|
|
115
|
-
#_theme_accessor_storage = (__runInitializers(this, _variant_extraInitializers), __runInitializers(this, __theme_initializers, void 0));
|
|
116
|
-
// [LAW:types-are-the-program] @observableRef so setTheme() triggers a
|
|
117
|
-
// re-render — see slider.ts.
|
|
118
|
-
get _theme() { return this.#_theme_accessor_storage; }
|
|
119
|
-
set _theme(value) { this.#_theme_accessor_storage = value; }
|
|
120
106
|
constructor(options) {
|
|
121
|
-
super();
|
|
122
|
-
__runInitializers(this,
|
|
107
|
+
super(options.theme);
|
|
108
|
+
__runInitializers(this, _variant_extraInitializers);
|
|
123
109
|
this.id = options.id ?? `button-${options.label.toLowerCase().replace(/\s+/g, "-")}`;
|
|
124
110
|
this.label = options.label;
|
|
125
111
|
this.variant = options.variant ?? "default";
|
|
126
112
|
this.disabled = options.disabled ?? false;
|
|
127
|
-
this._theme = options.theme ?? DEFAULT_TERMINAL_THEME;
|
|
128
113
|
}
|
|
129
|
-
setTheme(theme) { this._theme = theme; }
|
|
130
114
|
// --- Event handlers ---
|
|
131
115
|
handleKey(event) {
|
|
132
116
|
if (this.disabled)
|
|
@@ -170,19 +154,17 @@ let Button = (() => {
|
|
|
170
154
|
const right = focused ? "]" : " ";
|
|
171
155
|
const text = `${left} ${this.label} ${right}`;
|
|
172
156
|
if (this.disabled) {
|
|
173
|
-
return [new Segment(text, new Style(
|
|
157
|
+
return [new Segment(text, new Style(this.disabledInk))];
|
|
174
158
|
}
|
|
175
159
|
// Active and hover share the same colour pair (full accent bg + on-accent fg).
|
|
176
160
|
// Active is differentiated by bold, not by inverting fg/bg — inversion gives
|
|
177
161
|
// mostly-accent text on mostly-bg-tinted background, which is unreadable for
|
|
178
162
|
// accents whose contrast partner depends on luminance.
|
|
163
|
+
const keys = VARIANT_KEYS[this.variant];
|
|
179
164
|
if (this.active || this.hovered) {
|
|
180
|
-
|
|
181
|
-
const bg = this.resolvePalette(VARIANT_KEYS[this.variant].hover);
|
|
182
|
-
return [new Segment(text, new Style({ color: fg, bgcolor: bg, bold: this.active }))];
|
|
165
|
+
return [new Segment(text, new Style({ ...ink(this.theme, keys.hoverFg, keys.hover), bold: this.active }))];
|
|
183
166
|
}
|
|
184
|
-
|
|
185
|
-
return [new Segment(text, new Style({ color: fg, bgcolor: bg }))];
|
|
167
|
+
return [new Segment(text, new Style(ink(this.theme, keys.fg, keys.bg)))];
|
|
186
168
|
}
|
|
187
169
|
measure(_options) {
|
|
188
170
|
// [LAW:one-source-of-truth] cellLen is the cell-width authority; .length
|
|
@@ -190,19 +172,6 @@ let Button = (() => {
|
|
|
190
172
|
const width = cellLen(this.label) + 4;
|
|
191
173
|
return { minimum: width, maximum: width };
|
|
192
174
|
}
|
|
193
|
-
// --- Palette resolution ---
|
|
194
|
-
resolveColors(bgKey) {
|
|
195
|
-
const keys = VARIANT_KEYS[this.variant];
|
|
196
|
-
return {
|
|
197
|
-
fg: this.resolvePalette(keys.fg),
|
|
198
|
-
bg: this.resolvePalette(bgKey === "hover" ? keys.hover : keys.bg),
|
|
199
|
-
};
|
|
200
|
-
}
|
|
201
|
-
resolvePalette(key) {
|
|
202
|
-
const rgba = this._theme.palette.get(key);
|
|
203
|
-
// [LAW:no-defensive-null-guards] palette is required and must contain all keys.
|
|
204
|
-
return ColorSpec.fromRgba(rgba);
|
|
205
|
-
}
|
|
206
175
|
};
|
|
207
176
|
})();
|
|
208
177
|
export { Button };
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
import { Segment } from "../core/segment.js";
|
|
14
14
|
import { type RenderOptions } from "../core/protocol.js";
|
|
15
15
|
import type { TerminalTheme } from "../core/color.js";
|
|
16
|
-
import {
|
|
16
|
+
import { ThemedWidget } from "./themed-widget.js";
|
|
17
17
|
import type { KeyEvent, WidgetMouseEvent } from "./types.js";
|
|
18
18
|
export interface CheckboxOptions {
|
|
19
19
|
label: string;
|
|
@@ -22,14 +22,12 @@ export interface CheckboxOptions {
|
|
|
22
22
|
disabled?: boolean;
|
|
23
23
|
theme?: TerminalTheme;
|
|
24
24
|
}
|
|
25
|
-
export declare class Checkbox extends
|
|
25
|
+
export declare class Checkbox extends ThemedWidget {
|
|
26
26
|
readonly id: string;
|
|
27
27
|
readonly focusable = true;
|
|
28
28
|
accessor label: string;
|
|
29
29
|
accessor checked: boolean;
|
|
30
|
-
private accessor _theme;
|
|
31
30
|
constructor(options: CheckboxOptions);
|
|
32
|
-
setTheme(theme: TerminalTheme): void;
|
|
33
31
|
handleKey(event: KeyEvent): void;
|
|
34
32
|
handleMouse(event: WidgetMouseEvent): void;
|
|
35
33
|
protected draw(options: RenderOptions): Iterable<Segment>;
|
|
@@ -37,5 +35,4 @@ export declare class Checkbox extends WidgetBase {
|
|
|
37
35
|
minimum: number;
|
|
38
36
|
maximum: number;
|
|
39
37
|
};
|
|
40
|
-
private resolvePalette;
|
|
41
38
|
}
|
package/dist/widgets/checkbox.js
CHANGED
|
@@ -44,16 +44,15 @@ var __esDecorate = (this && this.__esDecorate) || function (ctor, descriptorIn,
|
|
|
44
44
|
if (target) Object.defineProperty(target, contextIn.name, descriptor);
|
|
45
45
|
done = true;
|
|
46
46
|
};
|
|
47
|
-
import { observable, action
|
|
47
|
+
import { observable, action } from "mobx";
|
|
48
48
|
import { Segment } from "../core/segment.js";
|
|
49
49
|
import { Style } from "../core/style.js";
|
|
50
|
-
import { ColorSpec } from "../core/color.js";
|
|
51
50
|
import { cellLen } from "../core/cells.js";
|
|
52
|
-
import { DEFAULT_TERMINAL_THEME } from "../themes/terminalThemes.js";
|
|
53
51
|
import { drawable } from "../core/protocol.js";
|
|
54
|
-
import {
|
|
52
|
+
import { ThemedWidget } from "./themed-widget.js";
|
|
53
|
+
import { ink } from "./ink.js";
|
|
55
54
|
let Checkbox = (() => {
|
|
56
|
-
let _classSuper =
|
|
55
|
+
let _classSuper = ThemedWidget;
|
|
57
56
|
let _instanceExtraInitializers = [];
|
|
58
57
|
let _label_decorators;
|
|
59
58
|
let _label_initializers = [];
|
|
@@ -61,10 +60,6 @@ let Checkbox = (() => {
|
|
|
61
60
|
let _checked_decorators;
|
|
62
61
|
let _checked_initializers = [];
|
|
63
62
|
let _checked_extraInitializers = [];
|
|
64
|
-
let __theme_decorators;
|
|
65
|
-
let __theme_initializers = [];
|
|
66
|
-
let __theme_extraInitializers = [];
|
|
67
|
-
let _setTheme_decorators;
|
|
68
63
|
let _handleKey_decorators;
|
|
69
64
|
let _handleMouse_decorators;
|
|
70
65
|
return class Checkbox extends _classSuper {
|
|
@@ -72,14 +67,10 @@ let Checkbox = (() => {
|
|
|
72
67
|
const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
|
|
73
68
|
_label_decorators = [observable];
|
|
74
69
|
_checked_decorators = [observable];
|
|
75
|
-
__theme_decorators = [observableRef];
|
|
76
|
-
_setTheme_decorators = [action];
|
|
77
70
|
_handleKey_decorators = [action];
|
|
78
71
|
_handleMouse_decorators = [action];
|
|
79
72
|
__esDecorate(this, null, _label_decorators, { kind: "accessor", name: "label", static: false, private: false, access: { has: obj => "label" in obj, get: obj => obj.label, set: (obj, value) => { obj.label = value; } }, metadata: _metadata }, _label_initializers, _label_extraInitializers);
|
|
80
73
|
__esDecorate(this, null, _checked_decorators, { kind: "accessor", name: "checked", static: false, private: false, access: { has: obj => "checked" in obj, get: obj => obj.checked, set: (obj, value) => { obj.checked = value; } }, metadata: _metadata }, _checked_initializers, _checked_extraInitializers);
|
|
81
|
-
__esDecorate(this, null, __theme_decorators, { kind: "accessor", name: "_theme", static: false, private: false, access: { has: obj => "_theme" in obj, get: obj => obj._theme, set: (obj, value) => { obj._theme = value; } }, metadata: _metadata }, __theme_initializers, __theme_extraInitializers);
|
|
82
|
-
__esDecorate(this, null, _setTheme_decorators, { kind: "method", name: "setTheme", static: false, private: false, access: { has: obj => "setTheme" in obj, get: obj => obj.setTheme }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
83
74
|
__esDecorate(this, null, _handleKey_decorators, { kind: "method", name: "handleKey", static: false, private: false, access: { has: obj => "handleKey" in obj, get: obj => obj.handleKey }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
84
75
|
__esDecorate(this, null, _handleMouse_decorators, { kind: "method", name: "handleMouse", static: false, private: false, access: { has: obj => "handleMouse" in obj, get: obj => obj.handleMouse }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
85
76
|
if (_metadata) Object.defineProperty(this, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
|
|
@@ -92,21 +83,14 @@ let Checkbox = (() => {
|
|
|
92
83
|
#checked_accessor_storage = (__runInitializers(this, _label_extraInitializers), __runInitializers(this, _checked_initializers, void 0));
|
|
93
84
|
get checked() { return this.#checked_accessor_storage; }
|
|
94
85
|
set checked(value) { this.#checked_accessor_storage = value; }
|
|
95
|
-
#_theme_accessor_storage = (__runInitializers(this, _checked_extraInitializers), __runInitializers(this, __theme_initializers, void 0));
|
|
96
|
-
// [LAW:types-are-the-program] @observableRef so setTheme() triggers a
|
|
97
|
-
// re-render — see slider.ts.
|
|
98
|
-
get _theme() { return this.#_theme_accessor_storage; }
|
|
99
|
-
set _theme(value) { this.#_theme_accessor_storage = value; }
|
|
100
86
|
constructor(options) {
|
|
101
|
-
super();
|
|
102
|
-
__runInitializers(this,
|
|
87
|
+
super(options.theme);
|
|
88
|
+
__runInitializers(this, _checked_extraInitializers);
|
|
103
89
|
this.id = options.id ?? `checkbox-${options.label.toLowerCase().replace(/\s+/g, "-")}`;
|
|
104
90
|
this.label = options.label;
|
|
105
91
|
this.checked = options.checked ?? false;
|
|
106
92
|
this.disabled = options.disabled ?? false;
|
|
107
|
-
this._theme = options.theme ?? DEFAULT_TERMINAL_THEME;
|
|
108
93
|
}
|
|
109
|
-
setTheme(theme) { this._theme = theme; }
|
|
110
94
|
// --- Event handlers ---
|
|
111
95
|
handleKey(event) {
|
|
112
96
|
if (this.disabled)
|
|
@@ -136,22 +120,16 @@ let Checkbox = (() => {
|
|
|
136
120
|
const indicator = this.checked ? drawable(options, "✓", "x") : " ";
|
|
137
121
|
const text = `[${indicator}] ${this.label}`;
|
|
138
122
|
if (this.disabled) {
|
|
139
|
-
return [new Segment(text, new Style(
|
|
123
|
+
return [new Segment(text, new Style(this.disabledInk))];
|
|
140
124
|
}
|
|
141
|
-
const
|
|
142
|
-
return [new Segment(text, new Style({
|
|
125
|
+
const colors = ink(this.theme, this.checked ? "text-primary" : "foreground", "background");
|
|
126
|
+
return [new Segment(text, new Style({ ...colors, underline: this.focused }))];
|
|
143
127
|
}
|
|
144
128
|
measure(_options) {
|
|
145
129
|
// [LAW:one-source-of-truth] cellLen — see button.ts.
|
|
146
130
|
const width = cellLen(this.label) + 4;
|
|
147
131
|
return { minimum: width, maximum: width };
|
|
148
132
|
}
|
|
149
|
-
// --- Palette resolution ---
|
|
150
|
-
resolvePalette(key) {
|
|
151
|
-
const rgba = this._theme.palette.get(key);
|
|
152
|
-
// [LAW:no-defensive-null-guards] palette must contain all keys; missing is a construction bug.
|
|
153
|
-
return ColorSpec.fromRgba(rgba);
|
|
154
|
-
}
|
|
155
133
|
};
|
|
156
134
|
})();
|
|
157
135
|
export { Checkbox };
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
import { Segment } from "../core/segment.js";
|
|
26
26
|
import { type RenderOptions } from "../core/protocol.js";
|
|
27
27
|
import type { TerminalTheme } from "../core/color.js";
|
|
28
|
-
import {
|
|
28
|
+
import { ThemedWidget } from "./themed-widget.js";
|
|
29
29
|
import type { KeyEvent, WidgetMouseEvent, WidgetFocusEvent, OverlayRenderable } from "./types.js";
|
|
30
30
|
export interface DropdownOptions {
|
|
31
31
|
options: string[];
|
|
@@ -34,7 +34,7 @@ export interface DropdownOptions {
|
|
|
34
34
|
disabled?: boolean;
|
|
35
35
|
theme?: TerminalTheme;
|
|
36
36
|
}
|
|
37
|
-
export declare class Dropdown extends
|
|
37
|
+
export declare class Dropdown extends ThemedWidget implements OverlayRenderable {
|
|
38
38
|
readonly id: string;
|
|
39
39
|
readonly focusable = true;
|
|
40
40
|
accessor options: string[];
|
|
@@ -46,10 +46,8 @@ export declare class Dropdown extends WidgetBase implements OverlayRenderable {
|
|
|
46
46
|
label: string;
|
|
47
47
|
idx: number;
|
|
48
48
|
}[];
|
|
49
|
-
private accessor _theme;
|
|
50
49
|
constructor(options: DropdownOptions);
|
|
51
50
|
private clampIndex;
|
|
52
|
-
setTheme(theme: TerminalTheme): void;
|
|
53
51
|
handleKey(event: KeyEvent): void;
|
|
54
52
|
handleMouse(event: WidgetMouseEvent): void;
|
|
55
53
|
handleFocus(event: WidgetFocusEvent): void;
|
|
@@ -63,5 +61,4 @@ export declare class Dropdown extends WidgetBase implements OverlayRenderable {
|
|
|
63
61
|
minimum: number;
|
|
64
62
|
maximum: number;
|
|
65
63
|
};
|
|
66
|
-
private resolvePalette;
|
|
67
64
|
}
|
package/dist/widgets/dropdown.js
CHANGED
|
@@ -56,16 +56,15 @@ var __esDecorate = (this && this.__esDecorate) || function (ctor, descriptorIn,
|
|
|
56
56
|
if (target) Object.defineProperty(target, contextIn.name, descriptor);
|
|
57
57
|
done = true;
|
|
58
58
|
};
|
|
59
|
-
import { observable, action,
|
|
59
|
+
import { observable, action, observableShallow } from "mobx";
|
|
60
60
|
import { Segment } from "../core/segment.js";
|
|
61
61
|
import { Style } from "../core/style.js";
|
|
62
|
-
import { ColorSpec } from "../core/color.js";
|
|
63
62
|
import { cellLen, setCellSize, splitText, asCellCol } from "../core/cells.js";
|
|
64
|
-
import { DEFAULT_TERMINAL_THEME } from "../themes/terminalThemes.js";
|
|
65
63
|
import { drawable } from "../core/protocol.js";
|
|
66
|
-
import {
|
|
64
|
+
import { ThemedWidget } from "./themed-widget.js";
|
|
65
|
+
import { ink } from "./ink.js";
|
|
67
66
|
let Dropdown = (() => {
|
|
68
|
-
let _classSuper =
|
|
67
|
+
let _classSuper = ThemedWidget;
|
|
69
68
|
let _instanceExtraInitializers = [];
|
|
70
69
|
let _options_decorators;
|
|
71
70
|
let _options_initializers = [];
|
|
@@ -82,10 +81,6 @@ let Dropdown = (() => {
|
|
|
82
81
|
let _filter_decorators;
|
|
83
82
|
let _filter_initializers = [];
|
|
84
83
|
let _filter_extraInitializers = [];
|
|
85
|
-
let __theme_decorators;
|
|
86
|
-
let __theme_initializers = [];
|
|
87
|
-
let __theme_extraInitializers = [];
|
|
88
|
-
let _setTheme_decorators;
|
|
89
84
|
let _handleKey_decorators;
|
|
90
85
|
let _handleMouse_decorators;
|
|
91
86
|
let _handleFocus_decorators;
|
|
@@ -97,8 +92,6 @@ let Dropdown = (() => {
|
|
|
97
92
|
_expanded_decorators = [observable];
|
|
98
93
|
_highlightedIndex_decorators = [observable];
|
|
99
94
|
_filter_decorators = [observable];
|
|
100
|
-
__theme_decorators = [observableRef];
|
|
101
|
-
_setTheme_decorators = [action];
|
|
102
95
|
_handleKey_decorators = [action];
|
|
103
96
|
_handleMouse_decorators = [action];
|
|
104
97
|
_handleFocus_decorators = [action];
|
|
@@ -107,8 +100,6 @@ let Dropdown = (() => {
|
|
|
107
100
|
__esDecorate(this, null, _expanded_decorators, { kind: "accessor", name: "expanded", static: false, private: false, access: { has: obj => "expanded" in obj, get: obj => obj.expanded, set: (obj, value) => { obj.expanded = value; } }, metadata: _metadata }, _expanded_initializers, _expanded_extraInitializers);
|
|
108
101
|
__esDecorate(this, null, _highlightedIndex_decorators, { kind: "accessor", name: "highlightedIndex", static: false, private: false, access: { has: obj => "highlightedIndex" in obj, get: obj => obj.highlightedIndex, set: (obj, value) => { obj.highlightedIndex = value; } }, metadata: _metadata }, _highlightedIndex_initializers, _highlightedIndex_extraInitializers);
|
|
109
102
|
__esDecorate(this, null, _filter_decorators, { kind: "accessor", name: "filter", static: false, private: false, access: { has: obj => "filter" in obj, get: obj => obj.filter, set: (obj, value) => { obj.filter = value; } }, metadata: _metadata }, _filter_initializers, _filter_extraInitializers);
|
|
110
|
-
__esDecorate(this, null, __theme_decorators, { kind: "accessor", name: "_theme", static: false, private: false, access: { has: obj => "_theme" in obj, get: obj => obj._theme, set: (obj, value) => { obj._theme = value; } }, metadata: _metadata }, __theme_initializers, __theme_extraInitializers);
|
|
111
|
-
__esDecorate(this, null, _setTheme_decorators, { kind: "method", name: "setTheme", static: false, private: false, access: { has: obj => "setTheme" in obj, get: obj => obj.setTheme }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
112
103
|
__esDecorate(this, null, _handleKey_decorators, { kind: "method", name: "handleKey", static: false, private: false, access: { has: obj => "handleKey" in obj, get: obj => obj.handleKey }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
113
104
|
__esDecorate(this, null, _handleMouse_decorators, { kind: "method", name: "handleMouse", static: false, private: false, access: { has: obj => "handleMouse" in obj, get: obj => obj.handleMouse }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
114
105
|
__esDecorate(this, null, _handleFocus_decorators, { kind: "method", name: "handleFocus", static: false, private: false, access: { has: obj => "handleFocus" in obj, get: obj => obj.handleFocus }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
@@ -144,15 +135,9 @@ let Dropdown = (() => {
|
|
|
144
135
|
}
|
|
145
136
|
return result;
|
|
146
137
|
}
|
|
147
|
-
#_theme_accessor_storage = (__runInitializers(this, _filter_extraInitializers), __runInitializers(this, __theme_initializers, void 0));
|
|
148
|
-
// [LAW:types-are-the-program] @observableRef so setTheme() triggers a
|
|
149
|
-
// re-render — render() and resolvePalette() read _theme.palette, so the
|
|
150
|
-
// theme reference must participate in MobX reactivity.
|
|
151
|
-
get _theme() { return this.#_theme_accessor_storage; }
|
|
152
|
-
set _theme(value) { this.#_theme_accessor_storage = value; }
|
|
153
138
|
constructor(options) {
|
|
154
|
-
super();
|
|
155
|
-
__runInitializers(this,
|
|
139
|
+
super(options.theme);
|
|
140
|
+
__runInitializers(this, _filter_extraInitializers);
|
|
156
141
|
this.id = options.id ?? `dropdown-${Math.random().toString(36).slice(2, 8)}`;
|
|
157
142
|
this.options = [...options.options];
|
|
158
143
|
// [LAW:types-are-the-program] selectedIndex must point to a valid
|
|
@@ -163,7 +148,6 @@ let Dropdown = (() => {
|
|
|
163
148
|
this.selectedIndex = this.clampIndex(options.selectedIndex ?? 0);
|
|
164
149
|
this.highlightedIndex = this.selectedIndex;
|
|
165
150
|
this.disabled = options.disabled ?? false;
|
|
166
|
-
this._theme = options.theme ?? DEFAULT_TERMINAL_THEME;
|
|
167
151
|
}
|
|
168
152
|
// [LAW:single-enforcer] One place owns "is this index valid for the
|
|
169
153
|
// current options". selectedIndex and options are public observables —
|
|
@@ -176,7 +160,6 @@ let Dropdown = (() => {
|
|
|
176
160
|
return 0;
|
|
177
161
|
return Math.max(0, Math.min(n, this.options.length - 1));
|
|
178
162
|
}
|
|
179
|
-
setTheme(theme) { this._theme = theme; }
|
|
180
163
|
// --- Event handlers ---
|
|
181
164
|
handleKey(event) {
|
|
182
165
|
if (this.disabled)
|
|
@@ -322,10 +305,9 @@ let Dropdown = (() => {
|
|
|
322
305
|
const caret = this.focused ? drawable(options, "│", "|") : "";
|
|
323
306
|
const maxLabelLen = this.maxLabelLen();
|
|
324
307
|
const baseStyle = this.disabled
|
|
325
|
-
? new Style(
|
|
308
|
+
? new Style(this.disabledInk)
|
|
326
309
|
: new Style({
|
|
327
|
-
|
|
328
|
-
bgcolor: this.resolvePalette("surface"),
|
|
310
|
+
...ink(this.theme, "foreground", "surface"),
|
|
329
311
|
underline: this.focused,
|
|
330
312
|
});
|
|
331
313
|
const headerLabel = this.headerText(maxLabelLen, caret);
|
|
@@ -381,10 +363,9 @@ let Dropdown = (() => {
|
|
|
381
363
|
const text = setCellSize("(no matches)", asCellCol(maxLabelLen));
|
|
382
364
|
const inner = ` ${text} `;
|
|
383
365
|
const style = this.disabled
|
|
384
|
-
? new Style(
|
|
366
|
+
? new Style(this.disabledInk)
|
|
385
367
|
: new Style({
|
|
386
|
-
|
|
387
|
-
bgcolor: this.resolvePalette("surface"),
|
|
368
|
+
...ink(this.theme, "foreground", "surface"),
|
|
388
369
|
dim: true,
|
|
389
370
|
});
|
|
390
371
|
return [
|
|
@@ -405,21 +386,12 @@ let Dropdown = (() => {
|
|
|
405
386
|
// Highlighted: muted bg → text-primary (mostly-accent fg) is readable.
|
|
406
387
|
// Selected: full primary bg → on-primary (WCAG contrast) for fg.
|
|
407
388
|
const rowStyle = this.disabled
|
|
408
|
-
? new Style(
|
|
389
|
+
? new Style(this.disabledInk)
|
|
409
390
|
: isHighlighted
|
|
410
|
-
? new Style(
|
|
411
|
-
color: this.resolvePalette("text-primary"),
|
|
412
|
-
bgcolor: this.resolvePalette("primary-muted"),
|
|
413
|
-
})
|
|
391
|
+
? new Style(ink(this.theme, "text-primary", "primary-muted"))
|
|
414
392
|
: isSelected
|
|
415
|
-
? new Style(
|
|
416
|
-
|
|
417
|
-
bgcolor: this.resolvePalette("primary"),
|
|
418
|
-
})
|
|
419
|
-
: new Style({
|
|
420
|
-
color: this.resolvePalette("foreground"),
|
|
421
|
-
bgcolor: this.resolvePalette("surface"),
|
|
422
|
-
});
|
|
393
|
+
? new Style(ink(this.theme, "on-primary", "primary"))
|
|
394
|
+
: new Style(ink(this.theme, "foreground", "surface"));
|
|
423
395
|
return [
|
|
424
396
|
new Segment(" ", rowStyle),
|
|
425
397
|
new Segment(inner, rowStyle),
|
|
@@ -439,12 +411,6 @@ let Dropdown = (() => {
|
|
|
439
411
|
const width = this.maxLabelLen() + 4;
|
|
440
412
|
return { minimum: width, maximum: width };
|
|
441
413
|
}
|
|
442
|
-
// --- Palette resolution ---
|
|
443
|
-
resolvePalette(key) {
|
|
444
|
-
const rgba = this._theme.palette.get(key);
|
|
445
|
-
// [LAW:no-defensive-null-guards] palette must contain all keys.
|
|
446
|
-
return ColorSpec.fromRgba(rgba);
|
|
447
|
-
}
|
|
448
414
|
};
|
|
449
415
|
})();
|
|
450
416
|
export { Dropdown };
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ink — the colour pair a widget cell is drawn in: a foreground and the ground
|
|
3
|
+
* it stands on, both from one theme's palette.
|
|
4
|
+
*
|
|
5
|
+
* A palette's colours are chosen against that palette's own background. A
|
|
6
|
+
* foreground drawn over whatever the terminal shows is readable only when the
|
|
7
|
+
* terminal happens to match the theme — the default theme's white text
|
|
8
|
+
* vanished into a light terminal. With both halves taken from the palette, a
|
|
9
|
+
* widget looks the same on every terminal, so it is readable on all of them
|
|
10
|
+
* exactly when its theme is readable against itself.
|
|
11
|
+
*
|
|
12
|
+
* [LAW:types-are-the-program] There is no call that takes a foreground alone,
|
|
13
|
+
* so a widget cannot draw half a pair.
|
|
14
|
+
* [LAW:single-enforcer] Every widget resolves palette keys here, and this is
|
|
15
|
+
* where a key the palette lacks, or one that draws no colour (a theme's
|
|
16
|
+
* fully transparent "no background"), is reported.
|
|
17
|
+
*/
|
|
18
|
+
import { ColorSpec, type TerminalTheme } from "../core/color.js";
|
|
19
|
+
export declare function ink(theme: TerminalTheme, fg: string, bg: string): {
|
|
20
|
+
color: ColorSpec;
|
|
21
|
+
bgcolor: ColorSpec;
|
|
22
|
+
};
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ink — the colour pair a widget cell is drawn in: a foreground and the ground
|
|
3
|
+
* it stands on, both from one theme's palette.
|
|
4
|
+
*
|
|
5
|
+
* A palette's colours are chosen against that palette's own background. A
|
|
6
|
+
* foreground drawn over whatever the terminal shows is readable only when the
|
|
7
|
+
* terminal happens to match the theme — the default theme's white text
|
|
8
|
+
* vanished into a light terminal. With both halves taken from the palette, a
|
|
9
|
+
* widget looks the same on every terminal, so it is readable on all of them
|
|
10
|
+
* exactly when its theme is readable against itself.
|
|
11
|
+
*
|
|
12
|
+
* [LAW:types-are-the-program] There is no call that takes a foreground alone,
|
|
13
|
+
* so a widget cannot draw half a pair.
|
|
14
|
+
* [LAW:single-enforcer] Every widget resolves palette keys here, and this is
|
|
15
|
+
* where a key the palette lacks, or one that draws no colour (a theme's
|
|
16
|
+
* fully transparent "no background"), is reported.
|
|
17
|
+
*/
|
|
18
|
+
import { ColorSpec } from "../core/color.js";
|
|
19
|
+
export function ink(theme, fg, bg) {
|
|
20
|
+
return { color: paletteColor(theme, fg), bgcolor: paletteColor(theme, bg) };
|
|
21
|
+
}
|
|
22
|
+
function paletteColor(theme, key) {
|
|
23
|
+
const rgba = theme.palette.get(key);
|
|
24
|
+
if (rgba === undefined) {
|
|
25
|
+
throw new RangeError(`palette ${JSON.stringify(theme.palette.name)} has no ${JSON.stringify(key)}`);
|
|
26
|
+
}
|
|
27
|
+
if (rgba.alpha === 0) {
|
|
28
|
+
throw new RangeError(`palette ${JSON.stringify(theme.palette.name)}: ${JSON.stringify(key)} is fully transparent, so it cannot be half of a widget's colour pair`);
|
|
29
|
+
}
|
|
30
|
+
return ColorSpec.fromRgba(rgba);
|
|
31
|
+
}
|
package/dist/widgets/slider.d.ts
CHANGED
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
import { Segment } from "../core/segment.js";
|
|
21
21
|
import { type RenderOptions } from "../core/protocol.js";
|
|
22
22
|
import type { TerminalTheme } from "../core/color.js";
|
|
23
|
-
import {
|
|
23
|
+
import { ThemedWidget } from "./themed-widget.js";
|
|
24
24
|
import type { KeyEvent, WidgetMouseEvent } from "./types.js";
|
|
25
25
|
export interface SliderOptions {
|
|
26
26
|
value?: number;
|
|
@@ -32,7 +32,7 @@ export interface SliderOptions {
|
|
|
32
32
|
disabled?: boolean;
|
|
33
33
|
theme?: TerminalTheme;
|
|
34
34
|
}
|
|
35
|
-
export declare class Slider extends
|
|
35
|
+
export declare class Slider extends ThemedWidget {
|
|
36
36
|
readonly id: string;
|
|
37
37
|
readonly focusable = true;
|
|
38
38
|
accessor value: number;
|
|
@@ -40,10 +40,8 @@ export declare class Slider extends WidgetBase {
|
|
|
40
40
|
accessor max: number;
|
|
41
41
|
accessor step: number;
|
|
42
42
|
accessor width: number;
|
|
43
|
-
private accessor _theme;
|
|
44
43
|
private _dragging;
|
|
45
44
|
constructor(options?: SliderOptions);
|
|
46
|
-
setTheme(theme: TerminalTheme): void;
|
|
47
45
|
handleKey(event: KeyEvent): void;
|
|
48
46
|
handleMouse(event: WidgetMouseEvent): void;
|
|
49
47
|
private setValue;
|
|
@@ -53,5 +51,4 @@ export declare class Slider extends WidgetBase {
|
|
|
53
51
|
minimum: number;
|
|
54
52
|
maximum: number;
|
|
55
53
|
};
|
|
56
|
-
private resolvePalette;
|
|
57
54
|
}
|