@promptctl/rich-js 0.18.1 → 0.20.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 +11 -8
- 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 +99 -18
- package/dist/core/color.js +334 -146
- 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/noise.d.ts +31 -0
- package/dist/core/noise.js +94 -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 +161 -0
- package/dist/core/place.d.ts +1 -1
- package/dist/core/place.js +4 -6
- package/dist/core/pretty.d.ts +126 -2
- package/dist/core/pretty.js +571 -105
- package/dist/core/protocol.d.ts +43 -3
- package/dist/core/protocol.js +23 -2
- 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/selection.d.ts +12 -0
- package/dist/core/selection.js +14 -0
- package/dist/core/strip.d.ts +116 -74
- package/dist/core/strip.js +266 -217
- package/dist/core/style.d.ts +27 -7
- package/dist/core/style.js +106 -41
- 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 +95 -17
- package/dist/host/app.js +201 -61
- package/dist/host/index.d.ts +4 -1
- package/dist/host/index.js +1 -0
- package/dist/host/input.d.ts +84 -0
- package/dist/host/input.js +498 -0
- package/dist/host/terminal-host.d.ts +15 -2
- package/dist/host/terminal-host.js +2 -0
- package/dist/index.d.ts +26 -14
- package/dist/index.js +17 -7
- 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 +10 -2
- package/dist/node/terminal-host.js +7 -0
- 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 +113 -0
- package/dist/renderables/effect.js +182 -0
- package/dist/renderables/effects.d.ts +252 -0
- package/dist/renderables/effects.js +565 -0
- package/dist/renderables/embed.d.ts +94 -31
- package/dist/renderables/embed.js +141 -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/list-view.d.ts +42 -0
- package/dist/renderables/list-view.js +78 -0
- 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 +110 -16
- package/dist/renderables/progress.js +212 -81
- package/dist/renderables/progressBar.d.ts +24 -4
- package/dist/renderables/progressBar.js +78 -23
- 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 +3 -2
- package/dist/renderables/rule.js +50 -52
- 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 +373 -197
- 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.d.ts +30 -0
- package/dist/renderables/viewport.js +61 -7
- 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 +17 -51
- package/dist/widgets/event-router.d.ts +31 -40
- package/dist/widgets/event-router.js +52 -483
- package/dist/widgets/index.d.ts +2 -1
- 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/types.d.ts +8 -25
- package/dist/widgets/types.js +8 -0
- package/dist/widgets/widget-app.d.ts +24 -7
- package/dist/widgets/widget-app.js +35 -18
- package/dist/widgets/widget-base.d.ts +2 -0
- package/dist/widgets/widget-base.js +9 -2
- package/package.json +31 -17
|
@@ -22,10 +22,15 @@
|
|
|
22
22
|
* [LAW:types-are-the-program] Three integer spaces coexist: `CellCol` (terminal
|
|
23
23
|
* cell columns), `CodeUnit` (JS UTF-16 indices), and `CodePoint` (code-unit
|
|
24
24
|
* offsets that are additionally on a Unicode code-point boundary — a subtype of
|
|
25
|
-
* `CodeUnit`). `cursorPosition` is `CodePoint
|
|
26
|
-
*
|
|
25
|
+
* `CodeUnit`). `cursorPosition` is `CodePoint`, and stronger: its setter
|
|
26
|
+
* parses any offset to a grapheme-cluster boundary. Visual positions are `CellCol`. The three are never
|
|
27
27
|
* interchangeable — the type system enforces this at every crossing point.
|
|
28
28
|
*
|
|
29
|
+
* [LAW:one-source-of-truth] The cursor moves, deletes and draws one grapheme
|
|
30
|
+
* cluster at a time (`nextGrapheme` / `prevGrapheme`) — the unit `cellLen`
|
|
31
|
+
* measures — so `👍🏽` is one step and one cursor cell, never a glyph and a
|
|
32
|
+
* stray skin-tone swatch.
|
|
33
|
+
*
|
|
29
34
|
* Keymap (readline / emacs compatible):
|
|
30
35
|
*
|
|
31
36
|
* ─── motion ───
|
|
@@ -89,14 +94,13 @@ var __esDecorate = (this && this.__esDecorate) || function (ctor, descriptorIn,
|
|
|
89
94
|
if (target) Object.defineProperty(target, contextIn.name, descriptor);
|
|
90
95
|
done = true;
|
|
91
96
|
};
|
|
92
|
-
import { observable, action, observableRef } from "mobx";
|
|
97
|
+
import { observable, action, observableRef, runInAction } from "mobx";
|
|
93
98
|
import { Segment } from "../core/segment.js";
|
|
94
99
|
import { Style } from "../core/style.js";
|
|
95
|
-
import {
|
|
96
|
-
import { cellLen, setCellSize, splitText, cellStepFrom, cellColToCodeUnitOffset, asCellCol, asCodePoint, nextCodePoint, prevCodePoint, } from "../core/cells.js";
|
|
97
|
-
import { DEFAULT_TERMINAL_THEME } from "../themes/terminalThemes.js";
|
|
100
|
+
import { cellLen, setCellSize, splitText, cellStepFrom, cellColToCodeUnitOffset, asCellCol, asCodePoint, asCodeUnit, graphemeBoundary, graphemes, nextGrapheme, prevGrapheme, } from "../core/cells.js";
|
|
98
101
|
import { drawable } from "../core/protocol.js";
|
|
99
|
-
import {
|
|
102
|
+
import { ThemedWidget } from "./themed-widget.js";
|
|
103
|
+
import { ink } from "./ink.js";
|
|
100
104
|
/**
|
|
101
105
|
* Character-greedy soft wrap. Breaks at any character once `firstWidth`
|
|
102
106
|
* (or `continuationWidth` for continuation rows) cells are exhausted. The
|
|
@@ -131,11 +135,18 @@ const NEWLINE_GLYPH = "↵";
|
|
|
131
135
|
const ASCII_NEWLINE_GLYPH = "~";
|
|
132
136
|
const MASK_GLYPH = "•";
|
|
133
137
|
const ASCII_MASK_GLYPH = "*";
|
|
138
|
+
// Text a key may insert: anything but the C0 controls, DEL and the C1
|
|
139
|
+
// controls, which a terminal reads as escape sequences (U+009B is CSI).
|
|
140
|
+
const PRINTABLE = /^[^\x00-\x1f\x7f-\x9f]+$/u;
|
|
134
141
|
// Word-character regex used by Alt+B/F and Ctrl+Left/Right. Matches the
|
|
135
142
|
// readline default (alphanumeric + underscore), which is what users typing
|
|
136
143
|
// shell commands or code identifiers expect.
|
|
137
144
|
const WORD_CHAR_RE = /[A-Za-z0-9_]/;
|
|
138
145
|
const WHITESPACE_RE = /\s/;
|
|
146
|
+
/** CRLF and lone CR as LF, the line break `value` holds. */
|
|
147
|
+
function toLf(text) {
|
|
148
|
+
return text.replace(/\r\n?/g, "\n");
|
|
149
|
+
}
|
|
139
150
|
function isWordChar(c) {
|
|
140
151
|
return c !== undefined && WORD_CHAR_RE.test(c);
|
|
141
152
|
}
|
|
@@ -143,14 +154,14 @@ function isWhitespace(c) {
|
|
|
143
154
|
return c !== undefined && WHITESPACE_RE.test(c);
|
|
144
155
|
}
|
|
145
156
|
let TextInput = (() => {
|
|
146
|
-
let _classSuper =
|
|
157
|
+
let _classSuper = ThemedWidget;
|
|
147
158
|
let _instanceExtraInitializers = [];
|
|
148
|
-
let
|
|
149
|
-
let
|
|
150
|
-
let
|
|
151
|
-
let
|
|
152
|
-
let
|
|
153
|
-
let
|
|
159
|
+
let __value_decorators;
|
|
160
|
+
let __value_initializers = [];
|
|
161
|
+
let __value_extraInitializers = [];
|
|
162
|
+
let __cursor_decorators;
|
|
163
|
+
let __cursor_initializers = [];
|
|
164
|
+
let __cursor_extraInitializers = [];
|
|
154
165
|
let _placeholder_decorators;
|
|
155
166
|
let _placeholder_initializers = [];
|
|
156
167
|
let _placeholder_extraInitializers = [];
|
|
@@ -188,8 +199,8 @@ let TextInput = (() => {
|
|
|
188
199
|
return class TextInput extends _classSuper {
|
|
189
200
|
static {
|
|
190
201
|
const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
|
|
191
|
-
|
|
192
|
-
|
|
202
|
+
__value_decorators = [observable];
|
|
203
|
+
__cursor_decorators = [observable];
|
|
193
204
|
_placeholder_decorators = [observableRef];
|
|
194
205
|
_indicatorStyleOverride_decorators = [observableRef];
|
|
195
206
|
_cursorStyleOverride_decorators = [observableRef];
|
|
@@ -216,8 +227,8 @@ let TextInput = (() => {
|
|
|
216
227
|
_yank_decorators = [action];
|
|
217
228
|
_transposeChars_decorators = [action];
|
|
218
229
|
__insertText_decorators = [action];
|
|
219
|
-
__esDecorate(this, null,
|
|
220
|
-
__esDecorate(this, null,
|
|
230
|
+
__esDecorate(this, null, __value_decorators, { kind: "accessor", name: "_value", static: false, private: false, access: { has: obj => "_value" in obj, get: obj => obj._value, set: (obj, value) => { obj._value = value; } }, metadata: _metadata }, __value_initializers, __value_extraInitializers);
|
|
231
|
+
__esDecorate(this, null, __cursor_decorators, { kind: "accessor", name: "_cursor", static: false, private: false, access: { has: obj => "_cursor" in obj, get: obj => obj._cursor, set: (obj, value) => { obj._cursor = value; } }, metadata: _metadata }, __cursor_initializers, __cursor_extraInitializers);
|
|
221
232
|
__esDecorate(this, null, _placeholder_decorators, { kind: "accessor", name: "placeholder", static: false, private: false, access: { has: obj => "placeholder" in obj, get: obj => obj.placeholder, set: (obj, value) => { obj.placeholder = value; } }, metadata: _metadata }, _placeholder_initializers, _placeholder_extraInitializers);
|
|
222
233
|
__esDecorate(this, null, _indicatorStyleOverride_decorators, { kind: "accessor", name: "indicatorStyleOverride", static: false, private: false, access: { has: obj => "indicatorStyleOverride" in obj, get: obj => obj.indicatorStyleOverride, set: (obj, value) => { obj.indicatorStyleOverride = value; } }, metadata: _metadata }, _indicatorStyleOverride_initializers, _indicatorStyleOverride_extraInitializers);
|
|
223
234
|
__esDecorate(this, null, _cursorStyleOverride_decorators, { kind: "accessor", name: "cursorStyleOverride", static: false, private: false, access: { has: obj => "cursorStyleOverride" in obj, get: obj => obj.cursorStyleOverride, set: (obj, value) => { obj.cursorStyleOverride = value; } }, metadata: _metadata }, _cursorStyleOverride_initializers, _cursorStyleOverride_extraInitializers);
|
|
@@ -248,17 +259,31 @@ let TextInput = (() => {
|
|
|
248
259
|
}
|
|
249
260
|
id = __runInitializers(this, _instanceExtraInitializers);
|
|
250
261
|
focusable = true;
|
|
251
|
-
#
|
|
252
|
-
get
|
|
253
|
-
set
|
|
254
|
-
#
|
|
255
|
-
get
|
|
256
|
-
set
|
|
257
|
-
|
|
262
|
+
#_value_accessor_storage = __runInitializers(this, __value_initializers, void 0);
|
|
263
|
+
get _value() { return this.#_value_accessor_storage; }
|
|
264
|
+
set _value(value) { this.#_value_accessor_storage = value; }
|
|
265
|
+
#_cursor_accessor_storage = (__runInitializers(this, __value_extraInitializers), __runInitializers(this, __cursor_initializers, void 0));
|
|
266
|
+
get _cursor() { return this.#_cursor_accessor_storage; }
|
|
267
|
+
set _cursor(value) { this.#_cursor_accessor_storage = value; }
|
|
268
|
+
// [LAW:single-enforcer] Every write to either half of the pair passes
|
|
269
|
+
// `graphemeBoundary`, so the cursor is a cluster boundary inside `value`
|
|
270
|
+
// whoever set it last — a caller replacing `value`, a click, an insert that
|
|
271
|
+
// grew the cluster before it. A line break is `\n`, as in an HTML
|
|
272
|
+
// textarea's value: `\r\n` is one cluster, and a cursor could not rest at
|
|
273
|
+
// its line's end.
|
|
274
|
+
get value() { return this._value; }
|
|
275
|
+
set value(v) {
|
|
276
|
+
runInAction(() => {
|
|
277
|
+
this._value = toLf(v);
|
|
278
|
+
this._cursor = graphemeBoundary(this._value, this._cursor);
|
|
279
|
+
});
|
|
280
|
+
}
|
|
281
|
+
get cursorPosition() { return this._cursor; }
|
|
282
|
+
set cursorPosition(p) { this._cursor = graphemeBoundary(this._value, p); }
|
|
283
|
+
#placeholder_accessor_storage = (__runInitializers(this, __cursor_extraInitializers), __runInitializers(this, _placeholder_initializers, void 0));
|
|
258
284
|
get placeholder() { return this.#placeholder_accessor_storage; }
|
|
259
285
|
set placeholder(value) { this.#placeholder_accessor_storage = value; }
|
|
260
|
-
|
|
261
|
-
_maxLength;
|
|
286
|
+
_maxLength = __runInitializers(this, _placeholder_extraInitializers);
|
|
262
287
|
_password;
|
|
263
288
|
_multiline;
|
|
264
289
|
_wrap;
|
|
@@ -311,11 +336,12 @@ let TextInput = (() => {
|
|
|
311
336
|
// single-line renderer. Captured by _renderSingleLine and read by
|
|
312
337
|
// handleMouse so the hit-test uses the same visual origin the user sees.
|
|
313
338
|
_singleLineViewportStart = asCellCol(0);
|
|
339
|
+
_singleLineAsciiOnly = false;
|
|
314
340
|
multiline;
|
|
315
341
|
constructor(options = {}) {
|
|
316
|
-
super();
|
|
342
|
+
super(options.theme);
|
|
317
343
|
this.id = options.id ?? `text-input-${Math.random().toString(36).slice(2, 8)}`;
|
|
318
|
-
this.
|
|
344
|
+
this._value = toLf(options.value ?? "");
|
|
319
345
|
this.placeholder = options.placeholder ?? "";
|
|
320
346
|
// [LAW:dataflow-not-control-flow] Initial cursor position is data, not
|
|
321
347
|
// a render-time branch. Single-line inputs follow the pre-filled-form
|
|
@@ -323,9 +349,8 @@ let TextInput = (() => {
|
|
|
323
349
|
// inputs follow the textarea convention (cursor at start — pre-loaded
|
|
324
350
|
// content is read top-to-bottom, and the viewport's "scroll into view"
|
|
325
351
|
// logic does nothing because row 0 is already inside the initial window).
|
|
326
|
-
this.
|
|
352
|
+
this._cursor = graphemeBoundary(this._value, asCodeUnit((options.multiline ?? false) ? 0 : this._value.length));
|
|
327
353
|
this.disabled = options.disabled ?? false;
|
|
328
|
-
this._theme = options.theme ?? DEFAULT_TERMINAL_THEME;
|
|
329
354
|
this._maxLength = options.maxLength;
|
|
330
355
|
this._password = options.password ?? false;
|
|
331
356
|
this._multiline = options.multiline ?? false;
|
|
@@ -340,7 +365,6 @@ let TextInput = (() => {
|
|
|
340
365
|
this.contentStyleOverride = options.contentStyle;
|
|
341
366
|
this.multiline = this._multiline;
|
|
342
367
|
}
|
|
343
|
-
setTheme(theme) { this._theme = theme; }
|
|
344
368
|
// --- Event handlers ---
|
|
345
369
|
handleKey(event) {
|
|
346
370
|
if (this.disabled)
|
|
@@ -499,14 +523,12 @@ let TextInput = (() => {
|
|
|
499
523
|
}
|
|
500
524
|
}
|
|
501
525
|
// ─── printable insertion ───
|
|
502
|
-
// A
|
|
526
|
+
// A non-control `event.character` with no command modifiers is text to
|
|
503
527
|
// insert. Ctrl/meta-modified keys produce empty `character` from the
|
|
504
|
-
// router (see event-router.ts) so they never reach this branch.
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
event.character >= " " &&
|
|
509
|
-
event.character !== "\x7f") {
|
|
528
|
+
// router (see event-router.ts) so they never reach this branch. The router
|
|
529
|
+
// sends one code point per key, so `👍🏽` arrives as `👍` then `🏽`, and an
|
|
530
|
+
// astral code point is two UTF-16 units — a `.length === 1` test drops it.
|
|
531
|
+
if (PRINTABLE.test(event.character) && !event.ctrl && !event.meta) {
|
|
510
532
|
this._insertText(event.character);
|
|
511
533
|
event.stop();
|
|
512
534
|
}
|
|
@@ -525,7 +547,7 @@ let TextInput = (() => {
|
|
|
525
547
|
const rawRowIdx = this._scrollStart + event.y;
|
|
526
548
|
// Clicks on minRows-padded empty rows (beyond the last real row) snap to end.
|
|
527
549
|
if (rawRowIdx >= rows.length) {
|
|
528
|
-
this.cursorPosition =
|
|
550
|
+
this.cursorPosition = asCodeUnit(this.value.length);
|
|
529
551
|
this._preferredColumn = null;
|
|
530
552
|
return;
|
|
531
553
|
}
|
|
@@ -534,13 +556,7 @@ let TextInput = (() => {
|
|
|
534
556
|
// Continuation rows start after the marker; non-continuation rows start at column 0.
|
|
535
557
|
const contentXOff = asCellCol(row.isContinuation ? this._markerWidth : 0);
|
|
536
558
|
const relX = asCellCol(Math.max(0, event.x - contentXOff));
|
|
537
|
-
|
|
538
|
-
const absPos = row.valueStart + pos;
|
|
539
|
-
const chu = absPos < this.value.length ? this.value.charCodeAt(absPos) : 0;
|
|
540
|
-
const prevChu = absPos > 0 ? this.value.charCodeAt(absPos - 1) : 0;
|
|
541
|
-
this.cursorPosition = asCodePoint(chu >= 0xDC00 && chu <= 0xDFFF && prevChu >= 0xD800 && prevChu <= 0xDBFF
|
|
542
|
-
? absPos + 1
|
|
543
|
-
: absPos);
|
|
559
|
+
this.cursorPosition = asCodeUnit(row.valueStart + cellColToCodeUnitOffset(row.content, relX));
|
|
544
560
|
}
|
|
545
561
|
else {
|
|
546
562
|
// [LAW:types-are-the-program] relX is a cell-column offset into the full
|
|
@@ -548,20 +564,19 @@ let TextInput = (() => {
|
|
|
548
564
|
// by _renderSingleLine) so a click on a scrolled viewport maps to the
|
|
549
565
|
// correct code-unit in the underlying value.
|
|
550
566
|
const relX = asCellCol(Math.max(0, event.x - 1) + this._singleLineViewportStart);
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
const
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
: pos);
|
|
567
|
+
// The glyphs of `value` whose shown cells lie wholly left of the click,
|
|
568
|
+
// shown as the last render showed them.
|
|
569
|
+
const drawn = { asciiOnly: this._singleLineAsciiOnly };
|
|
570
|
+
let at = 0;
|
|
571
|
+
let col = 0;
|
|
572
|
+
for (const g of graphemes(this.value)) {
|
|
573
|
+
const w = cellLen(this._shown(g, drawn));
|
|
574
|
+
if (col + w > relX)
|
|
575
|
+
break;
|
|
576
|
+
col += w;
|
|
577
|
+
at += g.length;
|
|
578
|
+
}
|
|
579
|
+
this.cursorPosition = asCodeUnit(at);
|
|
565
580
|
}
|
|
566
581
|
this._preferredColumn = null;
|
|
567
582
|
}
|
|
@@ -569,11 +584,11 @@ let TextInput = (() => {
|
|
|
569
584
|
setHovered(value) { this.hovered = value; }
|
|
570
585
|
// ─── Public motion primitives ───────────────────────────────────────────
|
|
571
586
|
moveCharLeft() {
|
|
572
|
-
this.cursorPosition =
|
|
587
|
+
this.cursorPosition = prevGrapheme(this.value, this.cursorPosition);
|
|
573
588
|
this._preferredColumn = null;
|
|
574
589
|
}
|
|
575
590
|
moveCharRight() {
|
|
576
|
-
this.cursorPosition =
|
|
591
|
+
this.cursorPosition = nextGrapheme(this.value, this.cursorPosition);
|
|
577
592
|
this._preferredColumn = null;
|
|
578
593
|
}
|
|
579
594
|
moveLineUp() {
|
|
@@ -587,7 +602,7 @@ let TextInput = (() => {
|
|
|
587
602
|
return;
|
|
588
603
|
const col = this._preferredColumn ?? this._cursorVisualCol();
|
|
589
604
|
const target = this._visualRows[rowIdx - 1];
|
|
590
|
-
this.cursorPosition =
|
|
605
|
+
this.cursorPosition = asCodeUnit(target.valueStart + this._clampColForRow(col, rowIdx - 1));
|
|
591
606
|
this._preferredColumn = col;
|
|
592
607
|
return;
|
|
593
608
|
}
|
|
@@ -601,7 +616,7 @@ let TextInput = (() => {
|
|
|
601
616
|
while (prevLineStart > 0 && this.value[prevLineStart - 1] !== "\n")
|
|
602
617
|
prevLineStart--;
|
|
603
618
|
const prevLineContent = this.value.slice(prevLineStart, prevLineEnd);
|
|
604
|
-
this.cursorPosition =
|
|
619
|
+
this.cursorPosition = asCodeUnit(prevLineStart + cellColToCodeUnitOffset(prevLineContent, asCellCol(Math.min(col, cellLen(prevLineContent)))));
|
|
605
620
|
this._preferredColumn = col;
|
|
606
621
|
}
|
|
607
622
|
moveLineDown() {
|
|
@@ -610,7 +625,7 @@ let TextInput = (() => {
|
|
|
610
625
|
if (rowIdx === this._visualRows.length - 1)
|
|
611
626
|
return;
|
|
612
627
|
const col = this._preferredColumn ?? this._cursorVisualCol();
|
|
613
|
-
this.cursorPosition =
|
|
628
|
+
this.cursorPosition = asCodeUnit(this._visualRows[rowIdx + 1].valueStart + this._clampColForRow(col, rowIdx + 1));
|
|
614
629
|
this._preferredColumn = col;
|
|
615
630
|
return;
|
|
616
631
|
}
|
|
@@ -625,14 +640,14 @@ let TextInput = (() => {
|
|
|
625
640
|
while (nextLineEnd < this.value.length && this.value[nextLineEnd] !== "\n")
|
|
626
641
|
nextLineEnd++;
|
|
627
642
|
const nextLineContent = this.value.slice(nextLineStart, nextLineEnd);
|
|
628
|
-
this.cursorPosition =
|
|
643
|
+
this.cursorPosition = asCodeUnit(nextLineStart + cellColToCodeUnitOffset(nextLineContent, asCellCol(Math.min(col, cellLen(nextLineContent)))));
|
|
629
644
|
this._preferredColumn = col;
|
|
630
645
|
}
|
|
631
646
|
// Clamp `col` (a cell column) to the target visual row's content, returning
|
|
632
647
|
// the code-unit offset within that row. When the row IS followed by a
|
|
633
648
|
// continuation of the same logical line, we clamp to the last valid
|
|
634
|
-
//
|
|
635
|
-
// one cell before the visual end when the last
|
|
649
|
+
// cluster boundary strictly inside the row (which may be more than
|
|
650
|
+
// one cell before the visual end when the last glyph is wide) so the
|
|
636
651
|
// cursor stays strictly inside the target row — landing at the boundary
|
|
637
652
|
// would cause `_cursorVisualRow` to resolve to the *later* row, making
|
|
638
653
|
// every subsequent Up/Down stick at the boundary.
|
|
@@ -679,23 +694,23 @@ let TextInput = (() => {
|
|
|
679
694
|
this._preferredColumn = null;
|
|
680
695
|
}
|
|
681
696
|
moveDocStart() {
|
|
682
|
-
this.cursorPosition =
|
|
697
|
+
this.cursorPosition = asCodeUnit(0);
|
|
683
698
|
this._preferredColumn = null;
|
|
684
699
|
}
|
|
685
700
|
moveDocEnd() {
|
|
686
|
-
this.cursorPosition =
|
|
701
|
+
this.cursorPosition = asCodeUnit(this.value.length);
|
|
687
702
|
this._preferredColumn = null;
|
|
688
703
|
}
|
|
689
704
|
moveWordLeft() {
|
|
690
705
|
let p = this.cursorPosition;
|
|
691
706
|
while (p > 0) {
|
|
692
|
-
const prev =
|
|
707
|
+
const prev = prevGrapheme(this.value, p);
|
|
693
708
|
if (isWordChar(this.value.slice(prev, p)))
|
|
694
709
|
break;
|
|
695
710
|
p = prev;
|
|
696
711
|
}
|
|
697
712
|
while (p > 0) {
|
|
698
|
-
const prev =
|
|
713
|
+
const prev = prevGrapheme(this.value, p);
|
|
699
714
|
if (!isWordChar(this.value.slice(prev, p)))
|
|
700
715
|
break;
|
|
701
716
|
p = prev;
|
|
@@ -706,13 +721,13 @@ let TextInput = (() => {
|
|
|
706
721
|
moveWordRight() {
|
|
707
722
|
let p = this.cursorPosition;
|
|
708
723
|
while (p < this.value.length) {
|
|
709
|
-
const next =
|
|
724
|
+
const next = nextGrapheme(this.value, p);
|
|
710
725
|
if (isWordChar(this.value.slice(p, next)))
|
|
711
726
|
break;
|
|
712
727
|
p = next;
|
|
713
728
|
}
|
|
714
729
|
while (p < this.value.length) {
|
|
715
|
-
const next =
|
|
730
|
+
const next = nextGrapheme(this.value, p);
|
|
716
731
|
if (!isWordChar(this.value.slice(p, next)))
|
|
717
732
|
break;
|
|
718
733
|
p = next;
|
|
@@ -724,7 +739,7 @@ let TextInput = (() => {
|
|
|
724
739
|
deleteCharBack() {
|
|
725
740
|
if (this.cursorPosition === 0)
|
|
726
741
|
return;
|
|
727
|
-
const newPos =
|
|
742
|
+
const newPos = prevGrapheme(this.value, this.cursorPosition);
|
|
728
743
|
this.value = this.value.slice(0, newPos) + this.value.slice(this.cursorPosition);
|
|
729
744
|
this.cursorPosition = newPos;
|
|
730
745
|
this._preferredColumn = null;
|
|
@@ -733,7 +748,7 @@ let TextInput = (() => {
|
|
|
733
748
|
deleteCharForward() {
|
|
734
749
|
if (this.cursorPosition >= this.value.length)
|
|
735
750
|
return;
|
|
736
|
-
const nextPos =
|
|
751
|
+
const nextPos = nextGrapheme(this.value, this.cursorPosition);
|
|
737
752
|
this.value = this.value.slice(0, this.cursorPosition) + this.value.slice(nextPos);
|
|
738
753
|
this._preferredColumn = null;
|
|
739
754
|
this.emitChange();
|
|
@@ -744,13 +759,13 @@ let TextInput = (() => {
|
|
|
744
759
|
// → "foo |" → "|" rather than getting stuck on the trailing space.
|
|
745
760
|
let p = this.cursorPosition;
|
|
746
761
|
while (p > 0) {
|
|
747
|
-
const prev =
|
|
762
|
+
const prev = prevGrapheme(this.value, p);
|
|
748
763
|
if (!isWhitespace(this.value.slice(prev, p)))
|
|
749
764
|
break;
|
|
750
765
|
p = prev;
|
|
751
766
|
}
|
|
752
767
|
while (p > 0) {
|
|
753
|
-
const prev =
|
|
768
|
+
const prev = prevGrapheme(this.value, p);
|
|
754
769
|
if (isWhitespace(this.value.slice(prev, p)))
|
|
755
770
|
break;
|
|
756
771
|
p = prev;
|
|
@@ -766,13 +781,13 @@ let TextInput = (() => {
|
|
|
766
781
|
deleteWordForward() {
|
|
767
782
|
let p = this.cursorPosition;
|
|
768
783
|
while (p < this.value.length) {
|
|
769
|
-
const next =
|
|
784
|
+
const next = nextGrapheme(this.value, p);
|
|
770
785
|
if (isWordChar(this.value.slice(p, next)))
|
|
771
786
|
break;
|
|
772
787
|
p = next;
|
|
773
788
|
}
|
|
774
789
|
while (p < this.value.length) {
|
|
775
|
-
const next =
|
|
790
|
+
const next = nextGrapheme(this.value, p);
|
|
776
791
|
if (!isWordChar(this.value.slice(p, next)))
|
|
777
792
|
break;
|
|
778
793
|
p = next;
|
|
@@ -820,26 +835,28 @@ let TextInput = (() => {
|
|
|
820
835
|
// Readline `transpose-chars`: swap the char before the cursor with the
|
|
821
836
|
// char at the cursor and advance. At end-of-value, swap the trailing
|
|
822
837
|
// two chars without advancing. At position 0, no-op.
|
|
823
|
-
|
|
824
|
-
if (len < 2 || this.cursorPosition === 0)
|
|
838
|
+
if (this.cursorPosition === 0)
|
|
825
839
|
return;
|
|
826
840
|
const p = this.cursorPosition;
|
|
827
|
-
if (p ===
|
|
828
|
-
// End-of-value: swap the trailing two
|
|
829
|
-
|
|
830
|
-
const
|
|
841
|
+
if (p === this.value.length) {
|
|
842
|
+
// End-of-value: swap the trailing two glyphs; cursor stays. One glyph
|
|
843
|
+
// has nothing to swap with.
|
|
844
|
+
const cp2 = prevGrapheme(this.value, p);
|
|
845
|
+
if (cp2 === 0)
|
|
846
|
+
return;
|
|
847
|
+
const cp1 = prevGrapheme(this.value, cp2);
|
|
831
848
|
this.value = this.value.slice(0, cp1) + this.value.slice(cp2) + this.value.slice(cp1, cp2);
|
|
832
849
|
this._preferredColumn = null;
|
|
833
850
|
this.emitChange();
|
|
834
851
|
return;
|
|
835
852
|
}
|
|
836
|
-
// Normal case:
|
|
837
|
-
const cpBefore =
|
|
838
|
-
const cpAfter =
|
|
853
|
+
// Normal case: the whole glyphs before and at the cursor.
|
|
854
|
+
const cpBefore = prevGrapheme(this.value, p);
|
|
855
|
+
const cpAfter = nextGrapheme(this.value, p);
|
|
839
856
|
const charBefore = this.value.slice(cpBefore, p);
|
|
840
857
|
const charAt = this.value.slice(p, cpAfter);
|
|
841
858
|
this.value = this.value.slice(0, cpBefore) + charAt + charBefore + this.value.slice(cpAfter);
|
|
842
|
-
this.cursorPosition =
|
|
859
|
+
this.cursorPosition = cpAfter;
|
|
843
860
|
this._preferredColumn = null;
|
|
844
861
|
this.emitChange();
|
|
845
862
|
}
|
|
@@ -860,42 +877,58 @@ let TextInput = (() => {
|
|
|
860
877
|
let toInsert = text;
|
|
861
878
|
if (this._maxLength !== undefined) {
|
|
862
879
|
const room = this._maxLength - this.value.length;
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
880
|
+
// Cut between glyphs: the longest run of whole clusters within `room`.
|
|
881
|
+
let fit = 0;
|
|
882
|
+
for (const g of graphemes(toInsert)) {
|
|
883
|
+
if (fit + g.length > room)
|
|
884
|
+
break;
|
|
885
|
+
fit += g.length;
|
|
886
|
+
}
|
|
887
|
+
toInsert = toInsert.slice(0, fit);
|
|
867
888
|
}
|
|
889
|
+
if (toInsert.length === 0)
|
|
890
|
+
return;
|
|
891
|
+
// The end is taken before the write: the value setter has already moved
|
|
892
|
+
// the cursor past a cluster the insert grew.
|
|
893
|
+
const end = asCodeUnit(this.cursorPosition + toInsert.length);
|
|
868
894
|
this.value =
|
|
869
895
|
this.value.slice(0, this.cursorPosition) +
|
|
870
896
|
toInsert +
|
|
871
897
|
this.value.slice(this.cursorPosition);
|
|
872
|
-
this.cursorPosition =
|
|
898
|
+
this.cursorPosition = end;
|
|
873
899
|
this._preferredColumn = null;
|
|
874
900
|
this.emitChange();
|
|
875
901
|
}
|
|
876
902
|
// --- Rendering ---
|
|
903
|
+
// [LAW:one-source-of-truth] The style a value is drawn in is also what a
|
|
904
|
+
// short row is padded with, so a caller's `contentStyle` fills the row.
|
|
905
|
+
get ground() {
|
|
906
|
+
return this.disabled
|
|
907
|
+
? new Style(this.disabledInk)
|
|
908
|
+
: this.contentStyleOverride ?? super.ground;
|
|
909
|
+
}
|
|
877
910
|
draw(options) {
|
|
878
911
|
if (this._multiline)
|
|
879
912
|
return this._renderMultiline(options);
|
|
880
913
|
return this._renderSingleLine(options);
|
|
881
914
|
}
|
|
915
|
+
// [LAW:dataflow-not-control-flow] How a stretch of `value` is shown in one
|
|
916
|
+
// line derives from mode: one mask cell per glyph, or `\n` as a visible
|
|
917
|
+
// glyph. The render and the click hit-test both read it.
|
|
918
|
+
_shown(text, options) {
|
|
919
|
+
return this._password
|
|
920
|
+
? drawable(options, MASK_GLYPH, ASCII_MASK_GLYPH).repeat(graphemes(text).length)
|
|
921
|
+
: text.replace(/\n/g, drawable(options, NEWLINE_GLYPH, ASCII_NEWLINE_GLYPH));
|
|
922
|
+
}
|
|
882
923
|
_renderSingleLine(options) {
|
|
883
924
|
const showPlaceholder = this.focused && this.value.length === 0 && this.placeholder.length > 0;
|
|
884
|
-
//
|
|
885
|
-
// mode
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
const rawDisplay = showPlaceholder
|
|
889
|
-
? this.placeholder
|
|
890
|
-
: this._password
|
|
891
|
-
? drawable(options, MASK_GLYPH, ASCII_MASK_GLYPH).repeat(this.value.length)
|
|
892
|
-
: this.value.indexOf("\n") >= 0
|
|
893
|
-
? this.value.replace(/\n/g, drawable(options, NEWLINE_GLYPH, ASCII_NEWLINE_GLYPH))
|
|
894
|
-
: this.value;
|
|
895
|
-
// Measure in cell space — cursorPosition is a code-unit index; convert to
|
|
896
|
-
// cell column for all viewport arithmetic.
|
|
925
|
+
// The cursor's column is the width of the shown text before it, whatever
|
|
926
|
+
// the mode — a placeholder is shown only over an empty value.
|
|
927
|
+
this._singleLineAsciiOnly = options.asciiOnly ?? false;
|
|
928
|
+
const shown = (text) => this._shown(text, options);
|
|
929
|
+
const rawDisplay = showPlaceholder ? this.placeholder : shown(this.value);
|
|
897
930
|
const rawCellWidth = asCellCol(cellLen(rawDisplay));
|
|
898
|
-
const cursorCellCol = asCellCol(cellLen(
|
|
931
|
+
const cursorCellCol = asCellCol(cellLen(shown(this.value.slice(0, this.cursorPosition))));
|
|
899
932
|
const maxAvailable = asCellCol(Math.max(MIN_CONTENT_WIDTH, options.maxWidth - 2));
|
|
900
933
|
const desiredWidth = asCellCol(Math.max(MIN_CONTENT_WIDTH, rawCellWidth, cursorCellCol + 1));
|
|
901
934
|
const contentWidth = asCellCol(Math.min(maxAvailable, desiredWidth));
|
|
@@ -910,25 +943,16 @@ let TextInput = (() => {
|
|
|
910
943
|
const display = setCellSize(visible, contentWidth);
|
|
911
944
|
const cursorDisplayCellCol = asCellCol(cursorCellCol - actualStartCell);
|
|
912
945
|
const bracketStyle = this.disabled
|
|
913
|
-
? new Style(
|
|
914
|
-
: new Style(
|
|
915
|
-
const contentStyle = this.disabled
|
|
916
|
-
? new Style({
|
|
917
|
-
:
|
|
918
|
-
|
|
919
|
-
: this.contentStyleOverride ?? new Style({ color: this.resolvePalette("foreground") });
|
|
920
|
-
const cursorStyle = this.cursorStyleOverride ?? new Style({
|
|
921
|
-
color: this.resolvePalette("on-primary"),
|
|
922
|
-
bgcolor: this.resolvePalette("primary"),
|
|
923
|
-
});
|
|
946
|
+
? new Style(this.disabledInk)
|
|
947
|
+
: new Style(ink(this.theme, "foreground", "background"));
|
|
948
|
+
const contentStyle = showPlaceholder && !this.disabled
|
|
949
|
+
? new Style({ ...ink(this.theme, "foreground", "background"), dim: true })
|
|
950
|
+
: this.ground;
|
|
951
|
+
const cursorStyle = this.cursorStyleOverride ?? new Style(ink(this.theme, "on-primary", "primary"));
|
|
924
952
|
const segments = [new Segment("[", bracketStyle)];
|
|
925
953
|
if (this.focused && !this.disabled && cursorDisplayCellCol >= 0 && cursorDisplayCellCol < contentWidth) {
|
|
926
954
|
const [before, rest] = splitText(display, cursorDisplayCellCol);
|
|
927
|
-
|
|
928
|
-
for (const ch of rest) {
|
|
929
|
-
firstCh = ch;
|
|
930
|
-
break;
|
|
931
|
-
}
|
|
955
|
+
const firstCh = rest.slice(0, nextGrapheme(rest, asCodePoint(0)));
|
|
932
956
|
const at = firstCh || " ";
|
|
933
957
|
const after = rest.slice(firstCh.length);
|
|
934
958
|
if (before.length > 0)
|
|
@@ -981,14 +1005,9 @@ let TextInput = (() => {
|
|
|
981
1005
|
if (this._minRows !== undefined && total < this._minRows && this._maxRows === undefined) {
|
|
982
1006
|
padRows = this._minRows - total;
|
|
983
1007
|
}
|
|
984
|
-
const contentStyle = this.
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
const markerStyle = new Style({ color: this.resolvePalette("foreground"), dim: true });
|
|
988
|
-
const cursorStyle = this.cursorStyleOverride ?? new Style({
|
|
989
|
-
color: this.resolvePalette("on-primary"),
|
|
990
|
-
bgcolor: this.resolvePalette("primary"),
|
|
991
|
-
});
|
|
1008
|
+
const contentStyle = this.ground;
|
|
1009
|
+
const markerStyle = new Style({ ...ink(this.theme, "foreground", "background"), dim: true });
|
|
1010
|
+
const cursorStyle = this.cursorStyleOverride ?? new Style(ink(this.theme, "on-primary", "primary"));
|
|
992
1011
|
// Scroll-direction arrows appear in the rightmost cell of the first/last
|
|
993
1012
|
// visible row, *only* when scroll is actually possible in that direction.
|
|
994
1013
|
// _emitRowContent reserves the indicator's cells so content never
|
|
@@ -999,7 +1018,7 @@ let TextInput = (() => {
|
|
|
999
1018
|
const arrowsMode = this._scrollIndicator === "arrows";
|
|
1000
1019
|
const canScrollUp = arrowsMode && scrollable && this._scrollStart > 0;
|
|
1001
1020
|
const canScrollDown = arrowsMode && scrollable && this._scrollStart + this._maxRows < total;
|
|
1002
|
-
const indicatorStyle = this.indicatorStyleOverride ?? new Style(
|
|
1021
|
+
const indicatorStyle = this.indicatorStyleOverride ?? new Style(ink(this.theme, "text-primary", "background"));
|
|
1003
1022
|
const segments = [];
|
|
1004
1023
|
const showCursor = this.focused && !this.disabled;
|
|
1005
1024
|
for (let i = 0; i < visibleCount; i++) {
|
|
@@ -1051,7 +1070,7 @@ let TextInput = (() => {
|
|
|
1051
1070
|
return;
|
|
1052
1071
|
}
|
|
1053
1072
|
const before = content.slice(0, cursorCol);
|
|
1054
|
-
const nextCp =
|
|
1073
|
+
const nextCp = nextGrapheme(content, asCodePoint(cursorCol));
|
|
1055
1074
|
const at = content.slice(cursorCol, nextCp) || " ";
|
|
1056
1075
|
const after = content.slice(nextCp);
|
|
1057
1076
|
if (before.length > 0)
|
|
@@ -1075,11 +1094,7 @@ let TextInput = (() => {
|
|
|
1075
1094
|
: -1;
|
|
1076
1095
|
if (cursorCellColInRow >= 0 && cursorCellColInRow < contentCellWidth) {
|
|
1077
1096
|
const [before, rest] = splitText(paddedContent, asCellCol(cursorCellColInRow));
|
|
1078
|
-
|
|
1079
|
-
for (const ch of rest) {
|
|
1080
|
-
firstCh = ch;
|
|
1081
|
-
break;
|
|
1082
|
-
}
|
|
1097
|
+
const firstCh = rest.slice(0, nextGrapheme(rest, asCodePoint(0)));
|
|
1083
1098
|
const at = firstCh || " ";
|
|
1084
1099
|
const after = rest.slice(firstCh.length);
|
|
1085
1100
|
if (before.length > 0)
|
|
@@ -1154,12 +1169,6 @@ let TextInput = (() => {
|
|
|
1154
1169
|
const cursorRow1 = this._cursorVisualRow() + 1;
|
|
1155
1170
|
return `[${cursorRow1}/${rows.length}]`;
|
|
1156
1171
|
}
|
|
1157
|
-
// --- Palette resolution ---
|
|
1158
|
-
resolvePalette(key) {
|
|
1159
|
-
const rgba = this._theme.palette.get(key);
|
|
1160
|
-
// [LAW:no-defensive-null-guards] palette must contain all keys.
|
|
1161
|
-
return ColorSpec.fromRgba(rgba);
|
|
1162
|
-
}
|
|
1163
1172
|
};
|
|
1164
1173
|
})();
|
|
1165
1174
|
export { TextInput };
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ThemedWidget — a widget that draws every cell it owns from one theme's
|
|
3
|
+
* palette: the interactive widgets, as against `StaticItem`, which shows
|
|
4
|
+
* content it did not draw.
|
|
5
|
+
*
|
|
6
|
+
* [LAW:one-type-per-behavior] The theme, how it is swapped, what a disabled
|
|
7
|
+
* widget looks like, and the ground a padded row stands on are the same for
|
|
8
|
+
* every such widget, so they live here once.
|
|
9
|
+
*/
|
|
10
|
+
import { Style } from "../core/style.js";
|
|
11
|
+
import type { TerminalTheme } from "../core/color.js";
|
|
12
|
+
import { WidgetBase } from "./widget-base.js";
|
|
13
|
+
import { ink } from "./ink.js";
|
|
14
|
+
export declare abstract class ThemedWidget extends WidgetBase {
|
|
15
|
+
protected accessor theme: TerminalTheme;
|
|
16
|
+
constructor(theme: TerminalTheme | undefined);
|
|
17
|
+
setTheme(theme: TerminalTheme): void;
|
|
18
|
+
protected get ground(): Style;
|
|
19
|
+
protected get disabledInk(): ReturnType<typeof ink>;
|
|
20
|
+
}
|