@promptctl/rich-js 0.2.0 → 0.3.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 +29 -15
- package/dist/core/cells.d.ts +83 -3
- package/dist/core/cells.d.ts.map +1 -1
- package/dist/core/cells.js +113 -1
- package/dist/core/cells.js.map +1 -1
- package/dist/core/console.d.ts +0 -1
- package/dist/core/console.d.ts.map +1 -1
- package/dist/core/console.js +20 -16
- package/dist/core/console.js.map +1 -1
- package/dist/core/highlighter.d.ts.map +1 -1
- package/dist/core/highlighter.js.map +1 -1
- package/dist/core/oklch.d.ts +106 -0
- package/dist/core/oklch.d.ts.map +1 -0
- package/dist/core/oklch.js +221 -0
- package/dist/core/oklch.js.map +1 -0
- package/dist/core/render.d.ts +26 -7
- package/dist/core/render.d.ts.map +1 -1
- package/dist/core/render.js +83 -15
- package/dist/core/render.js.map +1 -1
- package/dist/core/segment.d.ts +14 -1
- package/dist/core/segment.d.ts.map +1 -1
- package/dist/core/segment.js +28 -3
- package/dist/core/segment.js.map +1 -1
- package/dist/core/style.d.ts +11 -2
- package/dist/core/style.d.ts.map +1 -1
- package/dist/core/style.js +31 -18
- package/dist/core/style.js.map +1 -1
- package/dist/core/text.d.ts +20 -0
- package/dist/core/text.d.ts.map +1 -1
- package/dist/core/text.js +31 -0
- package/dist/core/text.js.map +1 -1
- package/dist/index.d.ts +11 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +12 -3
- package/dist/index.js.map +1 -1
- package/dist/renderables/columns.d.ts.map +1 -1
- package/dist/renderables/columns.js +15 -22
- package/dist/renderables/columns.js.map +1 -1
- package/dist/renderables/layout.d.ts.map +1 -1
- package/dist/renderables/layout.js +8 -29
- package/dist/renderables/layout.js.map +1 -1
- package/dist/renderables/live.d.ts.map +1 -1
- package/dist/renderables/live.js +8 -7
- package/dist/renderables/live.js.map +1 -1
- package/dist/renderables/panel.d.ts +34 -0
- package/dist/renderables/panel.d.ts.map +1 -1
- package/dist/renderables/panel.js +66 -23
- package/dist/renderables/panel.js.map +1 -1
- package/dist/template-bindings/index.d.ts +35 -0
- package/dist/template-bindings/index.d.ts.map +1 -1
- package/dist/template-bindings/index.js +61 -0
- package/dist/template-bindings/index.js.map +1 -1
- package/dist/template-bindings/style-funcs.d.ts.map +1 -1
- package/dist/template-bindings/style-funcs.js +32 -0
- package/dist/template-bindings/style-funcs.js.map +1 -1
- package/dist/themes/colorMath.d.ts +40 -0
- package/dist/themes/colorMath.d.ts.map +1 -1
- package/dist/themes/colorMath.js +82 -1
- package/dist/themes/colorMath.js.map +1 -1
- package/dist/themes/data/catppuccin-frappe.d.ts +4 -0
- package/dist/themes/data/catppuccin-frappe.d.ts.map +1 -0
- package/dist/themes/data/catppuccin-frappe.js +159 -0
- package/dist/themes/data/catppuccin-frappe.js.map +1 -0
- package/dist/themes/data/catppuccin-macchiato.d.ts +4 -0
- package/dist/themes/data/catppuccin-macchiato.d.ts.map +1 -0
- package/dist/themes/data/catppuccin-macchiato.js +159 -0
- package/dist/themes/data/catppuccin-macchiato.js.map +1 -0
- package/dist/themes/data/cyberpunk.d.ts +18 -0
- package/dist/themes/data/cyberpunk.d.ts.map +1 -0
- package/dist/themes/data/cyberpunk.js +192 -0
- package/dist/themes/data/cyberpunk.js.map +1 -0
- package/dist/themes/data/default.d.ts +4 -0
- package/dist/themes/data/default.d.ts.map +1 -0
- package/dist/themes/data/default.js +159 -0
- package/dist/themes/data/default.js.map +1 -0
- package/dist/themes/data/index.d.ts +10 -3
- package/dist/themes/data/index.d.ts.map +1 -1
- package/dist/themes/data/index.js +24 -7
- package/dist/themes/data/index.js.map +1 -1
- package/dist/themes/data/svg-export.d.ts +4 -0
- package/dist/themes/data/svg-export.d.ts.map +1 -0
- package/dist/themes/data/svg-export.js +159 -0
- package/dist/themes/data/svg-export.js.map +1 -0
- package/dist/themes/data/types.d.ts +4 -3
- package/dist/themes/data/types.d.ts.map +1 -1
- package/dist/themes/registry.d.ts +29 -2
- package/dist/themes/registry.d.ts.map +1 -1
- package/dist/themes/registry.js +62 -12
- package/dist/themes/registry.js.map +1 -1
- package/dist/themes/terminalThemes.d.ts +29 -20
- package/dist/themes/terminalThemes.d.ts.map +1 -1
- package/dist/themes/terminalThemes.js +50 -249
- package/dist/themes/terminalThemes.js.map +1 -1
- package/dist/themes/transpose.d.ts +88 -0
- package/dist/themes/transpose.d.ts.map +1 -0
- package/dist/themes/transpose.js +139 -0
- package/dist/themes/transpose.js.map +1 -0
- package/dist/widgets/button.d.ts +8 -5
- package/dist/widgets/button.d.ts.map +1 -1
- package/dist/widgets/button.js +36 -11
- package/dist/widgets/button.js.map +1 -1
- package/dist/widgets/checkbox.d.ts +1 -2
- package/dist/widgets/checkbox.d.ts.map +1 -1
- package/dist/widgets/checkbox.js +20 -7
- package/dist/widgets/checkbox.js.map +1 -1
- package/dist/widgets/dropdown.d.ts +4 -3
- package/dist/widgets/dropdown.d.ts.map +1 -1
- package/dist/widgets/dropdown.js +109 -27
- package/dist/widgets/dropdown.js.map +1 -1
- package/dist/widgets/event-router.d.ts +6 -3
- package/dist/widgets/event-router.d.ts.map +1 -1
- package/dist/widgets/event-router.js +179 -68
- package/dist/widgets/event-router.js.map +1 -1
- package/dist/widgets/focus-manager.d.ts +2 -1
- package/dist/widgets/focus-manager.d.ts.map +1 -1
- package/dist/widgets/focus-manager.js +28 -9
- package/dist/widgets/focus-manager.js.map +1 -1
- package/dist/widgets/index.d.ts +2 -2
- package/dist/widgets/index.d.ts.map +1 -1
- package/dist/widgets/index.js +1 -1
- package/dist/widgets/index.js.map +1 -1
- package/dist/widgets/screen.d.ts +2 -0
- package/dist/widgets/screen.d.ts.map +1 -1
- package/dist/widgets/screen.js +148 -45
- package/dist/widgets/screen.js.map +1 -1
- package/dist/widgets/slider.d.ts +6 -3
- package/dist/widgets/slider.d.ts.map +1 -1
- package/dist/widgets/slider.js +34 -10
- package/dist/widgets/slider.js.map +1 -1
- package/dist/widgets/static-item.d.ts +1 -1
- package/dist/widgets/static-item.d.ts.map +1 -1
- package/dist/widgets/static-item.js +12 -13
- package/dist/widgets/static-item.js.map +1 -1
- package/dist/widgets/text-input.d.ts +239 -13
- package/dist/widgets/text-input.d.ts.map +1 -1
- package/dist/widgets/text-input.js +1004 -74
- package/dist/widgets/text-input.js.map +1 -1
- package/dist/widgets/toggle.d.ts +1 -2
- package/dist/widgets/toggle.d.ts.map +1 -1
- package/dist/widgets/toggle.js +20 -8
- package/dist/widgets/toggle.js.map +1 -1
- package/dist/widgets/types.d.ts +21 -4
- package/dist/widgets/types.d.ts.map +1 -1
- package/dist/widgets/types.js +19 -0
- package/dist/widgets/types.js.map +1 -1
- package/dist/widgets/widget-base.d.ts +1 -0
- package/dist/widgets/widget-base.d.ts.map +1 -1
- package/dist/widgets/widget-base.js +24 -7
- package/dist/widgets/widget-base.js.map +1 -1
- package/package.json +5 -3
package/dist/widgets/button.js
CHANGED
|
@@ -5,11 +5,15 @@
|
|
|
5
5
|
*
|
|
6
6
|
* Four visual states:
|
|
7
7
|
* normal — variant colors from theme semantic palette (muted)
|
|
8
|
-
* hover — full variant accent
|
|
8
|
+
* hover — full variant accent bg + on-accent fg (WCAG contrast)
|
|
9
9
|
* focus — brackets [ label ] surrounding the button
|
|
10
|
-
* active — color
|
|
10
|
+
* active — same color pair as hover, plus bold (pressed cue)
|
|
11
11
|
*
|
|
12
|
-
* States compose: active > focus > hover > normal.
|
|
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.
|
|
13
17
|
*/
|
|
14
18
|
var __runInitializers = (this && this.__runInitializers) || function (thisArg, initializers, value) {
|
|
15
19
|
var useValue = arguments.length > 2;
|
|
@@ -49,6 +53,7 @@ import { observable, action } from "mobx";
|
|
|
49
53
|
import { Segment } from "../core/segment.js";
|
|
50
54
|
import { Style } from "../core/style.js";
|
|
51
55
|
import { ColorSpec } from "../core/color.js";
|
|
56
|
+
import { cellLen } from "../core/cells.js";
|
|
52
57
|
import { DEFAULT_TERMINAL_THEME } from "../themes/terminalThemes.js";
|
|
53
58
|
import { WidgetBase } from "./widget-base.js";
|
|
54
59
|
// Variant → palette key mapping. Per variant:
|
|
@@ -65,7 +70,7 @@ const VARIANT_KEYS = {
|
|
|
65
70
|
danger: { bg: "error-muted", fg: "text-error", hover: "error", hoverFg: "on-error" },
|
|
66
71
|
};
|
|
67
72
|
let Button = (() => {
|
|
68
|
-
var _a;
|
|
73
|
+
var _a, _b;
|
|
69
74
|
let _classSuper = WidgetBase;
|
|
70
75
|
let _instanceExtraInitializers = [];
|
|
71
76
|
let _label_decorators;
|
|
@@ -74,24 +79,29 @@ let Button = (() => {
|
|
|
74
79
|
let _variant_decorators;
|
|
75
80
|
let _variant_initializers = [];
|
|
76
81
|
let _variant_extraInitializers = [];
|
|
82
|
+
let __theme_decorators;
|
|
83
|
+
let __theme_initializers = [];
|
|
84
|
+
let __theme_extraInitializers = [];
|
|
85
|
+
let _setTheme_decorators;
|
|
77
86
|
let _handleKey_decorators;
|
|
78
87
|
let _handleMouse_decorators;
|
|
79
|
-
let _setHovered_decorators;
|
|
80
88
|
let _setActive_decorators;
|
|
81
89
|
return class Button extends _classSuper {
|
|
82
90
|
static {
|
|
83
91
|
const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
|
|
84
92
|
_label_decorators = [observable];
|
|
85
93
|
_variant_decorators = [(_a = observable).ref.bind(_a)];
|
|
94
|
+
__theme_decorators = [(_b = observable).ref.bind(_b)];
|
|
95
|
+
_setTheme_decorators = [action];
|
|
86
96
|
_handleKey_decorators = [action];
|
|
87
97
|
_handleMouse_decorators = [action];
|
|
88
|
-
_setHovered_decorators = [action];
|
|
89
98
|
_setActive_decorators = [action];
|
|
90
99
|
__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);
|
|
91
100
|
__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);
|
|
101
|
+
__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);
|
|
102
|
+
__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);
|
|
92
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);
|
|
93
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);
|
|
94
|
-
__esDecorate(this, null, _setHovered_decorators, { kind: "method", name: "setHovered", static: false, private: false, access: { has: obj => "setHovered" in obj, get: obj => obj.setHovered }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
95
105
|
__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);
|
|
96
106
|
if (_metadata) Object.defineProperty(this, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
|
|
97
107
|
}
|
|
@@ -103,9 +113,14 @@ let Button = (() => {
|
|
|
103
113
|
#variant_accessor_storage = (__runInitializers(this, _label_extraInitializers), __runInitializers(this, _variant_initializers, void 0));
|
|
104
114
|
get variant() { return this.#variant_accessor_storage; }
|
|
105
115
|
set variant(value) { this.#variant_accessor_storage = value; }
|
|
106
|
-
|
|
116
|
+
#_theme_accessor_storage = (__runInitializers(this, _variant_extraInitializers), __runInitializers(this, __theme_initializers, void 0));
|
|
117
|
+
// [LAW:types-are-the-program] @observable.ref so setTheme() triggers a
|
|
118
|
+
// re-render — see slider.ts.
|
|
119
|
+
get _theme() { return this.#_theme_accessor_storage; }
|
|
120
|
+
set _theme(value) { this.#_theme_accessor_storage = value; }
|
|
107
121
|
constructor(options) {
|
|
108
122
|
super();
|
|
123
|
+
__runInitializers(this, __theme_extraInitializers);
|
|
109
124
|
this.id = options.id ?? `button-${options.label.toLowerCase().replace(/\s+/g, "-")}`;
|
|
110
125
|
this.label = options.label;
|
|
111
126
|
this.variant = options.variant ?? "default";
|
|
@@ -120,6 +135,15 @@ let Button = (() => {
|
|
|
120
135
|
if (event.key === "enter" || event.key === "space") {
|
|
121
136
|
this.active = true;
|
|
122
137
|
this.emitSubmit();
|
|
138
|
+
// [LAW:one-source-of-truth] Keyboard activation must leave the widget
|
|
139
|
+
// in the same end state as mouse activation: `active` cleared after
|
|
140
|
+
// the press. Mouse has a natural mouse_up to clear it; keyboard does
|
|
141
|
+
// not, so we schedule the clear on the next microtask. The single-
|
|
142
|
+
// frame `active=true` paint gives the user the visual "pressed" cue
|
|
143
|
+
// and is then cleared, matching mouse behaviour.
|
|
144
|
+
queueMicrotask(() => { if (this.active)
|
|
145
|
+
this.setActive(false); });
|
|
146
|
+
event.stop();
|
|
123
147
|
}
|
|
124
148
|
}
|
|
125
149
|
handleMouse(event) {
|
|
@@ -135,8 +159,7 @@ let Button = (() => {
|
|
|
135
159
|
}
|
|
136
160
|
}
|
|
137
161
|
}
|
|
138
|
-
// ---
|
|
139
|
-
setHovered(value) { this.hovered = value; }
|
|
162
|
+
// --- Active mutator (the keyboard-activation microtask uses this) ---
|
|
140
163
|
setActive(value) { this.active = value; }
|
|
141
164
|
// --- Rendering ---
|
|
142
165
|
render(_options) {
|
|
@@ -161,7 +184,9 @@ let Button = (() => {
|
|
|
161
184
|
return [new Segment(text, new Style({ color: fg, bgcolor: bg }))];
|
|
162
185
|
}
|
|
163
186
|
measure(_options) {
|
|
164
|
-
|
|
187
|
+
// [LAW:one-source-of-truth] cellLen is the cell-width authority; .length
|
|
188
|
+
// counts UTF-16 code units and miscounts wide / emoji characters.
|
|
189
|
+
const width = cellLen(this.label) + 4;
|
|
165
190
|
return { minimum: width, maximum: width };
|
|
166
191
|
}
|
|
167
192
|
// --- Palette resolution ---
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"button.js","sourceRoot":"","sources":["../../src/widgets/button.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"button.js","sourceRoot":"","sources":["../../src/widgets/button.ts"],"names":[],"mappings":"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"}
|
|
@@ -27,12 +27,11 @@ export declare class Checkbox extends WidgetBase {
|
|
|
27
27
|
readonly focusable = true;
|
|
28
28
|
accessor label: string;
|
|
29
29
|
accessor checked: boolean;
|
|
30
|
-
private _theme;
|
|
30
|
+
private accessor _theme;
|
|
31
31
|
constructor(options: CheckboxOptions);
|
|
32
32
|
setTheme(theme: TerminalTheme): void;
|
|
33
33
|
handleKey(event: KeyEvent): void;
|
|
34
34
|
handleMouse(event: WidgetMouseEvent): void;
|
|
35
|
-
setHovered(value: boolean): void;
|
|
36
35
|
render(options: RenderOptions): Iterable<Segment>;
|
|
37
36
|
measure(_options: RenderOptions): {
|
|
38
37
|
minimum: number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"checkbox.d.ts","sourceRoot":"","sources":["../../src/widgets/checkbox.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAGH,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"checkbox.d.ts","sourceRoot":"","sources":["../../src/widgets/checkbox.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAGH,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAK7C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACzD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACtD,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,KAAK,EAAE,QAAQ,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAE7D,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,KAAK,CAAC,EAAE,aAAa,CAAC;CACvB;AAED,qBAAa,QAAS,SAAQ,UAAU;IACtC,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,SAAS,QAAQ;IAEd,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAItB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAgB;gBAE3C,OAAO,EAAE,eAAe;IAUpC,QAAQ,CAAC,KAAK,EAAE,aAAa,GAAG,IAAI;IAKpC,SAAS,CAAC,KAAK,EAAE,QAAQ,GAAG,IAAI;IAevB,WAAW,CAAC,KAAK,EAAE,gBAAgB,GAAG,IAAI;IAUnD,MAAM,CAAC,OAAO,EAAE,aAAa,GAAG,QAAQ,CAAC,OAAO,CAAC;IAYjD,OAAO,CAAC,QAAQ,EAAE,aAAa,GAAG;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE;IAQtE,OAAO,CAAC,cAAc;CAKvB"}
|
package/dist/widgets/checkbox.js
CHANGED
|
@@ -48,9 +48,11 @@ import { observable, action } from "mobx";
|
|
|
48
48
|
import { Segment } from "../core/segment.js";
|
|
49
49
|
import { Style } from "../core/style.js";
|
|
50
50
|
import { ColorSpec } from "../core/color.js";
|
|
51
|
+
import { cellLen } from "../core/cells.js";
|
|
51
52
|
import { DEFAULT_TERMINAL_THEME } from "../themes/terminalThemes.js";
|
|
52
53
|
import { WidgetBase } from "./widget-base.js";
|
|
53
54
|
let Checkbox = (() => {
|
|
55
|
+
var _a;
|
|
54
56
|
let _classSuper = WidgetBase;
|
|
55
57
|
let _instanceExtraInitializers = [];
|
|
56
58
|
let _label_decorators;
|
|
@@ -59,22 +61,27 @@ let Checkbox = (() => {
|
|
|
59
61
|
let _checked_decorators;
|
|
60
62
|
let _checked_initializers = [];
|
|
61
63
|
let _checked_extraInitializers = [];
|
|
64
|
+
let __theme_decorators;
|
|
65
|
+
let __theme_initializers = [];
|
|
66
|
+
let __theme_extraInitializers = [];
|
|
67
|
+
let _setTheme_decorators;
|
|
62
68
|
let _handleKey_decorators;
|
|
63
69
|
let _handleMouse_decorators;
|
|
64
|
-
let _setHovered_decorators;
|
|
65
70
|
return class Checkbox extends _classSuper {
|
|
66
71
|
static {
|
|
67
72
|
const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
|
|
68
73
|
_label_decorators = [observable];
|
|
69
74
|
_checked_decorators = [observable];
|
|
75
|
+
__theme_decorators = [(_a = observable).ref.bind(_a)];
|
|
76
|
+
_setTheme_decorators = [action];
|
|
70
77
|
_handleKey_decorators = [action];
|
|
71
78
|
_handleMouse_decorators = [action];
|
|
72
|
-
_setHovered_decorators = [action];
|
|
73
79
|
__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);
|
|
74
80
|
__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);
|
|
75
83
|
__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);
|
|
76
84
|
__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);
|
|
77
|
-
__esDecorate(this, null, _setHovered_decorators, { kind: "method", name: "setHovered", static: false, private: false, access: { has: obj => "setHovered" in obj, get: obj => obj.setHovered }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
78
85
|
if (_metadata) Object.defineProperty(this, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
|
|
79
86
|
}
|
|
80
87
|
id = __runInitializers(this, _instanceExtraInitializers);
|
|
@@ -85,9 +92,14 @@ let Checkbox = (() => {
|
|
|
85
92
|
#checked_accessor_storage = (__runInitializers(this, _label_extraInitializers), __runInitializers(this, _checked_initializers, void 0));
|
|
86
93
|
get checked() { return this.#checked_accessor_storage; }
|
|
87
94
|
set checked(value) { this.#checked_accessor_storage = value; }
|
|
88
|
-
|
|
95
|
+
#_theme_accessor_storage = (__runInitializers(this, _checked_extraInitializers), __runInitializers(this, __theme_initializers, void 0));
|
|
96
|
+
// [LAW:types-are-the-program] @observable.ref 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; }
|
|
89
100
|
constructor(options) {
|
|
90
101
|
super();
|
|
102
|
+
__runInitializers(this, __theme_extraInitializers);
|
|
91
103
|
this.id = options.id ?? `checkbox-${options.label.toLowerCase().replace(/\s+/g, "-")}`;
|
|
92
104
|
this.label = options.label;
|
|
93
105
|
this.checked = options.checked ?? false;
|
|
@@ -102,10 +114,12 @@ let Checkbox = (() => {
|
|
|
102
114
|
if (event.key === "space") {
|
|
103
115
|
this.checked = !this.checked;
|
|
104
116
|
this.emitChange();
|
|
117
|
+
event.stop();
|
|
105
118
|
return;
|
|
106
119
|
}
|
|
107
120
|
if (event.key === "enter") {
|
|
108
121
|
this.emitSubmit();
|
|
122
|
+
event.stop();
|
|
109
123
|
}
|
|
110
124
|
}
|
|
111
125
|
handleMouse(event) {
|
|
@@ -116,8 +130,6 @@ let Checkbox = (() => {
|
|
|
116
130
|
this.emitChange();
|
|
117
131
|
}
|
|
118
132
|
}
|
|
119
|
-
// --- Hover/active mutators (router fast-path uses setHovered) ---
|
|
120
|
-
setHovered(value) { this.hovered = value; }
|
|
121
133
|
// --- Rendering ---
|
|
122
134
|
render(options) {
|
|
123
135
|
const indicator = this.checked ? (options.asciiOnly ? "x" : "✓") : " ";
|
|
@@ -129,7 +141,8 @@ let Checkbox = (() => {
|
|
|
129
141
|
return [new Segment(text, new Style({ color: fg, underline: this.focused }))];
|
|
130
142
|
}
|
|
131
143
|
measure(_options) {
|
|
132
|
-
|
|
144
|
+
// [LAW:one-source-of-truth] cellLen — see button.ts.
|
|
145
|
+
const width = cellLen(this.label) + 4;
|
|
133
146
|
return { minimum: width, maximum: width };
|
|
134
147
|
}
|
|
135
148
|
// --- Palette resolution ---
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"checkbox.js","sourceRoot":"","sources":["../../src/widgets/checkbox.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,MAAM,CAAC;AAC1C,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAC7C,OAAO,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AACzC,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC7C,OAAO,EAAE,sBAAsB,EAAE,MAAM,6BAA6B,CAAC;AAGrE,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;IAWjC,QAAQ
|
|
1
|
+
{"version":3,"file":"checkbox.js","sourceRoot":"","sources":["../../src/widgets/checkbox.ts"],"names":[],"mappings":"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"}
|
|
@@ -26,7 +26,7 @@ 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
28
|
import { WidgetBase } from "./widget-base.js";
|
|
29
|
-
import type { KeyEvent, WidgetMouseEvent, OverlayRenderable } from "./types.js";
|
|
29
|
+
import type { KeyEvent, WidgetMouseEvent, WidgetFocusEvent, OverlayRenderable } from "./types.js";
|
|
30
30
|
export interface DropdownOptions {
|
|
31
31
|
options: string[];
|
|
32
32
|
selectedIndex?: number;
|
|
@@ -46,12 +46,13 @@ export declare class Dropdown extends WidgetBase implements OverlayRenderable {
|
|
|
46
46
|
label: string;
|
|
47
47
|
idx: number;
|
|
48
48
|
}[];
|
|
49
|
-
private _theme;
|
|
49
|
+
private accessor _theme;
|
|
50
50
|
constructor(options: DropdownOptions);
|
|
51
|
+
private clampIndex;
|
|
51
52
|
setTheme(theme: TerminalTheme): void;
|
|
52
53
|
handleKey(event: KeyEvent): void;
|
|
53
54
|
handleMouse(event: WidgetMouseEvent): void;
|
|
54
|
-
|
|
55
|
+
handleFocus(event: WidgetFocusEvent): void;
|
|
55
56
|
render(options: RenderOptions): Iterable<Segment>;
|
|
56
57
|
private headerText;
|
|
57
58
|
renderOverlay(_options: RenderOptions): Iterable<Segment> | null;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dropdown.d.ts","sourceRoot":"","sources":["../../src/widgets/dropdown.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAGH,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"dropdown.d.ts","sourceRoot":"","sources":["../../src/widgets/dropdown.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAGH,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAK7C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACzD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACtD,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,KAAK,EACV,QAAQ,EACR,gBAAgB,EAChB,gBAAgB,EAChB,iBAAiB,EAClB,MAAM,YAAY,CAAC;AAEpB,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,KAAK,CAAC,EAAE,aAAa,CAAC;CACvB;AAED,qBAAa,QAAS,SAAQ,UAAW,YAAW,iBAAiB;IACnE,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,SAAS,QAAQ;IAEN,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,CAAC;IACnC,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAS;IACnC,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAC;IAClC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAM;IAKzC,IAAI,eAAe,IAAI;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,EAAE,CAQtD;IAKe,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAgB;gBAE3C,OAAO,EAAE,eAAe;IAqBpC,OAAO,CAAC,UAAU;IAMlB,QAAQ,CAAC,KAAK,EAAE,aAAa,GAAG,IAAI;IAKpC,SAAS,CAAC,KAAK,EAAE,QAAQ,GAAG,IAAI;IAsFvB,WAAW,CAAC,KAAK,EAAE,gBAAgB,GAAG,IAAI;IAmD1C,WAAW,CAAC,KAAK,EAAE,gBAAgB,GAAG,IAAI;IAUnD,MAAM,CAAC,OAAO,EAAE,aAAa,GAAG,QAAQ,CAAC,OAAO,CAAC;IAoCjD,OAAO,CAAC,UAAU;IAiBlB,aAAa,CAAC,QAAQ,EAAE,aAAa,GAAG,QAAQ,CAAC,OAAO,CAAC,GAAG,IAAI;IAchE,OAAO,CAAC,gBAAgB;IAkBxB,OAAO,CAAC,eAAe;IAyCvB,OAAO,CAAC,WAAW;IASnB,OAAO,CAAC,QAAQ,EAAE,aAAa,GAAG;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE;IAOtE,OAAO,CAAC,cAAc;CAKvB"}
|
package/dist/widgets/dropdown.js
CHANGED
|
@@ -60,10 +60,11 @@ import { observable, action } from "mobx";
|
|
|
60
60
|
import { Segment } from "../core/segment.js";
|
|
61
61
|
import { Style } from "../core/style.js";
|
|
62
62
|
import { ColorSpec } from "../core/color.js";
|
|
63
|
+
import { cellLen, setCellSize, splitText, asCellCol } from "../core/cells.js";
|
|
63
64
|
import { DEFAULT_TERMINAL_THEME } from "../themes/terminalThemes.js";
|
|
64
65
|
import { WidgetBase } from "./widget-base.js";
|
|
65
66
|
let Dropdown = (() => {
|
|
66
|
-
var _a;
|
|
67
|
+
var _a, _b;
|
|
67
68
|
let _classSuper = WidgetBase;
|
|
68
69
|
let _instanceExtraInitializers = [];
|
|
69
70
|
let _options_decorators;
|
|
@@ -81,9 +82,13 @@ let Dropdown = (() => {
|
|
|
81
82
|
let _filter_decorators;
|
|
82
83
|
let _filter_initializers = [];
|
|
83
84
|
let _filter_extraInitializers = [];
|
|
85
|
+
let __theme_decorators;
|
|
86
|
+
let __theme_initializers = [];
|
|
87
|
+
let __theme_extraInitializers = [];
|
|
88
|
+
let _setTheme_decorators;
|
|
84
89
|
let _handleKey_decorators;
|
|
85
90
|
let _handleMouse_decorators;
|
|
86
|
-
let
|
|
91
|
+
let _handleFocus_decorators;
|
|
87
92
|
return class Dropdown extends _classSuper {
|
|
88
93
|
static {
|
|
89
94
|
const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
|
|
@@ -92,17 +97,21 @@ let Dropdown = (() => {
|
|
|
92
97
|
_expanded_decorators = [observable];
|
|
93
98
|
_highlightedIndex_decorators = [observable];
|
|
94
99
|
_filter_decorators = [observable];
|
|
100
|
+
__theme_decorators = [(_b = observable).ref.bind(_b)];
|
|
101
|
+
_setTheme_decorators = [action];
|
|
95
102
|
_handleKey_decorators = [action];
|
|
96
103
|
_handleMouse_decorators = [action];
|
|
97
|
-
|
|
104
|
+
_handleFocus_decorators = [action];
|
|
98
105
|
__esDecorate(this, null, _options_decorators, { kind: "accessor", name: "options", static: false, private: false, access: { has: obj => "options" in obj, get: obj => obj.options, set: (obj, value) => { obj.options = value; } }, metadata: _metadata }, _options_initializers, _options_extraInitializers);
|
|
99
106
|
__esDecorate(this, null, _selectedIndex_decorators, { kind: "accessor", name: "selectedIndex", static: false, private: false, access: { has: obj => "selectedIndex" in obj, get: obj => obj.selectedIndex, set: (obj, value) => { obj.selectedIndex = value; } }, metadata: _metadata }, _selectedIndex_initializers, _selectedIndex_extraInitializers);
|
|
100
107
|
__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);
|
|
101
108
|
__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);
|
|
102
109
|
__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);
|
|
103
112
|
__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);
|
|
104
113
|
__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);
|
|
105
|
-
__esDecorate(this, null,
|
|
114
|
+
__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);
|
|
106
115
|
if (_metadata) Object.defineProperty(this, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
|
|
107
116
|
}
|
|
108
117
|
id = __runInitializers(this, _instanceExtraInitializers);
|
|
@@ -135,16 +144,38 @@ let Dropdown = (() => {
|
|
|
135
144
|
}
|
|
136
145
|
return result;
|
|
137
146
|
}
|
|
138
|
-
|
|
147
|
+
#_theme_accessor_storage = (__runInitializers(this, _filter_extraInitializers), __runInitializers(this, __theme_initializers, void 0));
|
|
148
|
+
// [LAW:types-are-the-program] @observable.ref 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; }
|
|
139
153
|
constructor(options) {
|
|
140
154
|
super();
|
|
155
|
+
__runInitializers(this, __theme_extraInitializers);
|
|
141
156
|
this.id = options.id ?? `dropdown-${Math.random().toString(36).slice(2, 8)}`;
|
|
142
157
|
this.options = [...options.options];
|
|
143
|
-
|
|
158
|
+
// [LAW:types-are-the-program] selectedIndex must point to a valid
|
|
159
|
+
// option (or be 0 for the empty-options case). Clamp at the trust
|
|
160
|
+
// boundary so headerText / render / commit logic can all assume
|
|
161
|
+
// validity. Empty options is allowed — render falls back to an
|
|
162
|
+
// empty label and commit is a no-op until options are populated.
|
|
163
|
+
this.selectedIndex = this.clampIndex(options.selectedIndex ?? 0);
|
|
144
164
|
this.highlightedIndex = this.selectedIndex;
|
|
145
165
|
this.disabled = options.disabled ?? false;
|
|
146
166
|
this._theme = options.theme ?? DEFAULT_TERMINAL_THEME;
|
|
147
167
|
}
|
|
168
|
+
// [LAW:single-enforcer] One place owns "is this index valid for the
|
|
169
|
+
// current options". selectedIndex and options are public observables —
|
|
170
|
+
// external code can move them out of range. Anywhere internal code
|
|
171
|
+
// seeds highlightedIndex from selectedIndex (constructor + every
|
|
172
|
+
// expand path), route through this clamp so the seeded value is
|
|
173
|
+
// always a legal option index (or 0 for empty options).
|
|
174
|
+
clampIndex(n) {
|
|
175
|
+
if (this.options.length === 0)
|
|
176
|
+
return 0;
|
|
177
|
+
return Math.max(0, Math.min(n, this.options.length - 1));
|
|
178
|
+
}
|
|
148
179
|
setTheme(theme) { this._theme = theme; }
|
|
149
180
|
// --- Event handlers ---
|
|
150
181
|
handleKey(event) {
|
|
@@ -159,7 +190,8 @@ let Dropdown = (() => {
|
|
|
159
190
|
// enter/space remain the explicit "open with selection seeded" gesture.
|
|
160
191
|
if (event.key === "enter" || event.key === "space") {
|
|
161
192
|
this.expanded = true;
|
|
162
|
-
this.highlightedIndex = this.selectedIndex;
|
|
193
|
+
this.highlightedIndex = this.clampIndex(this.selectedIndex);
|
|
194
|
+
event.stop();
|
|
163
195
|
return;
|
|
164
196
|
}
|
|
165
197
|
// Any other printable char auto-expands and starts filtering.
|
|
@@ -167,6 +199,7 @@ let Dropdown = (() => {
|
|
|
167
199
|
this.expanded = true;
|
|
168
200
|
this.filter = this.filter + event.character;
|
|
169
201
|
this.highlightedIndex = 0;
|
|
202
|
+
event.stop();
|
|
170
203
|
}
|
|
171
204
|
return;
|
|
172
205
|
}
|
|
@@ -174,16 +207,19 @@ let Dropdown = (() => {
|
|
|
174
207
|
switch (event.key) {
|
|
175
208
|
case "up":
|
|
176
209
|
this.highlightedIndex = Math.max(0, this.highlightedIndex - 1);
|
|
210
|
+
event.stop();
|
|
177
211
|
return;
|
|
178
212
|
case "down": {
|
|
179
213
|
const max = Math.max(0, this.filteredOptions.length - 1);
|
|
180
214
|
this.highlightedIndex = Math.min(max, this.highlightedIndex + 1);
|
|
215
|
+
event.stop();
|
|
181
216
|
return;
|
|
182
217
|
}
|
|
183
218
|
case "enter": {
|
|
184
219
|
// [LAW:one-source-of-truth] Map filtered position → canonical idx.
|
|
185
220
|
// No-op when filteredOptions is empty (highlighted is undefined).
|
|
186
221
|
const picked = this.filteredOptions[this.highlightedIndex];
|
|
222
|
+
event.stop();
|
|
187
223
|
if (picked === undefined)
|
|
188
224
|
return;
|
|
189
225
|
this.selectedIndex = picked.idx;
|
|
@@ -197,16 +233,30 @@ let Dropdown = (() => {
|
|
|
197
233
|
// Single-step: clear filter + collapse.
|
|
198
234
|
this.filter = "";
|
|
199
235
|
this.expanded = false;
|
|
236
|
+
event.stop();
|
|
200
237
|
return;
|
|
201
238
|
case "backspace":
|
|
202
239
|
// [LAW:dataflow-not-control-flow] slice(0,-1) on "" is "" — no guard.
|
|
203
240
|
this.filter = this.filter.slice(0, -1);
|
|
204
241
|
this.highlightedIndex = 0;
|
|
242
|
+
event.stop();
|
|
243
|
+
return;
|
|
244
|
+
case "tab":
|
|
245
|
+
// First Tab while expanded cancels (clear filter + collapse) and
|
|
246
|
+
// KEEPS focus on the dropdown. event.stop() halts the chain so
|
|
247
|
+
// FocusManager's normal-priority Tab handler never runs — focus
|
|
248
|
+
// traversal only happens on the *next* Tab press, when this widget
|
|
249
|
+
// is collapsed and no longer stops the event. Shift direction is
|
|
250
|
+
// ignored: both Tab and Shift+Tab cancel.
|
|
251
|
+
this.filter = "";
|
|
252
|
+
this.expanded = false;
|
|
253
|
+
event.stop();
|
|
205
254
|
return;
|
|
206
255
|
}
|
|
207
256
|
if (isPrintable) {
|
|
208
257
|
this.filter = this.filter + event.character;
|
|
209
258
|
this.highlightedIndex = 0;
|
|
259
|
+
event.stop();
|
|
210
260
|
}
|
|
211
261
|
}
|
|
212
262
|
handleMouse(event) {
|
|
@@ -224,7 +274,7 @@ let Dropdown = (() => {
|
|
|
224
274
|
if (!this.expanded) {
|
|
225
275
|
if (inside) {
|
|
226
276
|
this.expanded = true;
|
|
227
|
-
this.highlightedIndex = this.selectedIndex;
|
|
277
|
+
this.highlightedIndex = this.clampIndex(this.selectedIndex);
|
|
228
278
|
}
|
|
229
279
|
return;
|
|
230
280
|
}
|
|
@@ -252,14 +302,28 @@ let Dropdown = (() => {
|
|
|
252
302
|
this.emitChange();
|
|
253
303
|
this.emitSubmit();
|
|
254
304
|
}
|
|
255
|
-
//
|
|
256
|
-
|
|
305
|
+
// [LAW:single-enforcer] FocusManager is the single dispatcher of focus
|
|
306
|
+
// transitions; overriding handleFocus here catches every blur path (Tab
|
|
307
|
+
// cycling, programmatic focus, unregister) so the overlay cannot outlive
|
|
308
|
+
// the widget's focus. Collapse is the data; no separate "should I close"
|
|
309
|
+
// branch lives at the router or elsewhere.
|
|
310
|
+
handleFocus(event) {
|
|
311
|
+
super.handleFocus(event);
|
|
312
|
+
if (event.type === "blur") {
|
|
313
|
+
this.filter = "";
|
|
314
|
+
this.expanded = false;
|
|
315
|
+
}
|
|
316
|
+
}
|
|
257
317
|
// --- Rendering ---
|
|
258
318
|
render(options) {
|
|
259
319
|
// Header only — the inline footprint that flow layout sees. Always
|
|
260
320
|
// 1 row regardless of `expanded`/`filter`. Option rows live in
|
|
261
321
|
// renderOverlay. Width invariant: maxLabelLen + 4.
|
|
262
322
|
const arrowChar = options.asciiOnly ? "v" : "▾";
|
|
323
|
+
// [LAW:one-source-of-truth] render() owns the asciiOnly switch; the
|
|
324
|
+
// caret character flows into headerText as data rather than headerText
|
|
325
|
+
// re-reading the option flag. Same arrow / caret resolution path.
|
|
326
|
+
const caret = this.focused ? (options.asciiOnly ? "|" : "│") : "";
|
|
263
327
|
const maxLabelLen = this.maxLabelLen();
|
|
264
328
|
const baseStyle = this.disabled
|
|
265
329
|
? new Style({ color: "#666666", bgcolor: "#333333", dim: true })
|
|
@@ -268,7 +332,7 @@ let Dropdown = (() => {
|
|
|
268
332
|
bgcolor: this.resolvePalette("surface"),
|
|
269
333
|
underline: this.focused,
|
|
270
334
|
});
|
|
271
|
-
const headerLabel = this.headerText(maxLabelLen);
|
|
335
|
+
const headerLabel = this.headerText(maxLabelLen, caret);
|
|
272
336
|
return [
|
|
273
337
|
new Segment("[", baseStyle),
|
|
274
338
|
new Segment(`${headerLabel} ${arrowChar}`, baseStyle),
|
|
@@ -278,14 +342,28 @@ let Dropdown = (() => {
|
|
|
278
342
|
// [LAW:dataflow-not-control-flow] One header text function; the data
|
|
279
343
|
// (filter empty vs not) chooses between selected-label and query+cursor.
|
|
280
344
|
// Both branches yield exactly maxLabelLen cells — width invariant.
|
|
281
|
-
|
|
345
|
+
// Selected label is centered; filter input is left-aligned so the caret
|
|
346
|
+
// doesn't jitter horizontally while typing.
|
|
347
|
+
//
|
|
348
|
+
// [LAW:one-source-of-truth] All width math is in terminal cells via
|
|
349
|
+
// cellLen / setCellSize / splitText — plain `.length` would miscount
|
|
350
|
+
// wide / emoji characters and break the width invariant.
|
|
351
|
+
headerText(maxLabelLen, caret) {
|
|
282
352
|
if (this.filter === "") {
|
|
283
|
-
|
|
353
|
+
const raw = this.options[this.selectedIndex] ?? "";
|
|
354
|
+
const w = cellLen(raw);
|
|
355
|
+
if (w >= maxLabelLen)
|
|
356
|
+
return setCellSize(raw, asCellCol(maxLabelLen));
|
|
357
|
+
const pad = maxLabelLen - w;
|
|
358
|
+
const left = Math.floor(pad / 2);
|
|
359
|
+
const right = pad - left;
|
|
360
|
+
return " ".repeat(left) + raw + " ".repeat(right);
|
|
284
361
|
}
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
const
|
|
288
|
-
|
|
362
|
+
// Leading space gives the filter input a small gutter from the [ chrome,
|
|
363
|
+
// matching the visual breathing room of the centered label.
|
|
364
|
+
const filterRoom = Math.max(0, maxLabelLen - cellLen(caret) - 1);
|
|
365
|
+
const [filterText] = splitText(this.filter, asCellCol(filterRoom));
|
|
366
|
+
return setCellSize(" " + filterText + caret, asCellCol(maxLabelLen));
|
|
289
367
|
}
|
|
290
368
|
renderOverlay(_options) {
|
|
291
369
|
if (!this.expanded)
|
|
@@ -304,7 +382,7 @@ let Dropdown = (() => {
|
|
|
304
382
|
}
|
|
305
383
|
renderNoMatchRow(maxLabelLen) {
|
|
306
384
|
// Right-clipped + padded so width matches a normal option row.
|
|
307
|
-
const text = "(no matches)"
|
|
385
|
+
const text = setCellSize("(no matches)", asCellCol(maxLabelLen));
|
|
308
386
|
const inner = ` ${text} `;
|
|
309
387
|
const style = this.disabled
|
|
310
388
|
? new Style({ color: "#666666", bgcolor: "#333333", dim: true })
|
|
@@ -314,15 +392,17 @@ let Dropdown = (() => {
|
|
|
314
392
|
dim: true,
|
|
315
393
|
});
|
|
316
394
|
return [
|
|
317
|
-
new Segment("
|
|
395
|
+
new Segment(" ", style),
|
|
318
396
|
new Segment(inner, style),
|
|
319
|
-
new Segment("
|
|
397
|
+
new Segment(" ", style),
|
|
320
398
|
];
|
|
321
399
|
}
|
|
322
400
|
renderOptionRow(entry, fpos, maxLabelLen) {
|
|
323
|
-
// Row: "
|
|
401
|
+
// Row: " " + label.padEnd(maxLabelLen) + " "
|
|
324
402
|
// Width = 1 + 1 + maxLabelLen + 1 + 1 = maxLabelLen + 4.
|
|
325
|
-
|
|
403
|
+
// Overlay rows are unbracketed — selection/highlight are conveyed by bg
|
|
404
|
+
// color; the header keeps [ ] as its focus-indicator chrome.
|
|
405
|
+
const label = setCellSize(entry.label, asCellCol(maxLabelLen));
|
|
326
406
|
const inner = ` ${label} `;
|
|
327
407
|
const isSelected = entry.idx === this.selectedIndex;
|
|
328
408
|
const isHighlighted = fpos === this.highlightedIndex;
|
|
@@ -345,16 +425,18 @@ let Dropdown = (() => {
|
|
|
345
425
|
bgcolor: this.resolvePalette("surface"),
|
|
346
426
|
});
|
|
347
427
|
return [
|
|
348
|
-
new Segment("
|
|
428
|
+
new Segment(" ", rowStyle),
|
|
349
429
|
new Segment(inner, rowStyle),
|
|
350
|
-
new Segment("
|
|
430
|
+
new Segment(" ", rowStyle),
|
|
351
431
|
];
|
|
352
432
|
}
|
|
353
433
|
maxLabelLen() {
|
|
354
434
|
let m = 0;
|
|
355
|
-
for (const label of this.options)
|
|
356
|
-
|
|
357
|
-
|
|
435
|
+
for (const label of this.options) {
|
|
436
|
+
const w = cellLen(label);
|
|
437
|
+
if (w > m)
|
|
438
|
+
m = w;
|
|
439
|
+
}
|
|
358
440
|
return m;
|
|
359
441
|
}
|
|
360
442
|
measure(_options) {
|