@promptctl/rich-js 0.23.0 → 0.24.1
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/THIRD-PARTY-NOTICES +29 -1
- package/dist/core/animation.d.ts +78 -0
- package/dist/core/animation.js +107 -0
- package/dist/core/cell-widths.d.ts +9 -0
- package/dist/core/cell-widths.js +140 -0
- package/dist/core/cells.d.ts +17 -11
- package/dist/core/cells.js +100 -25
- package/dist/core/clock.d.ts +9 -1
- package/dist/core/clock.js +22 -2
- package/dist/core/color.d.ts +10 -0
- package/dist/core/color.js +36 -1
- package/dist/core/console.js +5 -5
- package/dist/core/easing.d.ts +138 -7
- package/dist/core/easing.js +355 -17
- package/dist/core/json.js +2 -1
- package/dist/core/measure.js +2 -2
- package/dist/core/place.js +2 -1
- package/dist/core/pretty.js +2 -2
- package/dist/core/protocol.d.ts +73 -19
- package/dist/core/protocol.js +56 -15
- package/dist/core/render.js +2 -1
- package/dist/core/segment.d.ts +28 -1
- package/dist/core/segment.js +60 -44
- package/dist/core/strip.d.ts +107 -29
- package/dist/core/strip.js +242 -131
- package/dist/core/style.d.ts +18 -1
- package/dist/core/style.js +49 -9
- package/dist/core/text.js +26 -15
- package/dist/core/timeline.d.ts +84 -0
- package/dist/core/timeline.js +144 -0
- package/dist/core/tween.d.ts +49 -0
- package/dist/core/tween.js +69 -0
- package/dist/host/app.js +4 -6
- package/dist/host/index.d.ts +1 -1
- package/dist/host/input.d.ts +37 -13
- package/dist/host/input.js +146 -56
- package/dist/host/terminal-host.d.ts +16 -0
- package/dist/host/terminal-host.js +1 -0
- package/dist/index.d.ts +16 -11
- package/dist/index.js +15 -5
- package/dist/node/terminal-host.d.ts +8 -1
- package/dist/node/terminal-host.js +2 -0
- package/dist/renderables/align.d.ts +3 -2
- package/dist/renderables/align.js +3 -0
- package/dist/renderables/columns.d.ts +3 -2
- package/dist/renderables/columns.js +7 -2
- package/dist/renderables/constrain.d.ts +3 -2
- package/dist/renderables/constrain.js +5 -1
- package/dist/renderables/effect.d.ts +83 -30
- package/dist/renderables/effect.js +155 -57
- package/dist/renderables/effects.d.ts +88 -39
- package/dist/renderables/effects.js +444 -105
- package/dist/renderables/embed.d.ts +10 -0
- package/dist/renderables/embed.js +18 -9
- package/dist/renderables/flexStrip.d.ts +3 -2
- package/dist/renderables/flexStrip.js +6 -1
- package/dist/renderables/frames.d.ts +116 -0
- package/dist/renderables/frames.js +133 -0
- package/dist/renderables/group.d.ts +3 -2
- package/dist/renderables/group.js +5 -2
- package/dist/renderables/html-entities.d.ts +8 -0
- package/dist/renderables/html-entities.js +386 -0
- package/dist/renderables/layout.d.ts +3 -2
- package/dist/renderables/layout.js +15 -2
- package/dist/renderables/list-view.d.ts +3 -2
- package/dist/renderables/list-view.js +12 -5
- package/dist/renderables/live.d.ts +23 -7
- package/dist/renderables/live.js +69 -35
- package/dist/renderables/markdown-parse.d.ts +109 -0
- package/dist/renderables/markdown-parse.js +1421 -0
- package/dist/renderables/markdown-url.d.ts +19 -0
- package/dist/renderables/markdown-url.js +314 -0
- package/dist/renderables/markdown.d.ts +7 -6
- package/dist/renderables/markdown.js +363 -499
- package/dist/renderables/padding.d.ts +8 -20
- package/dist/renderables/padding.js +32 -50
- package/dist/renderables/panel.d.ts +26 -26
- package/dist/renderables/panel.js +67 -103
- package/dist/renderables/progress.d.ts +5 -3
- package/dist/renderables/progress.js +14 -3
- package/dist/renderables/progressBar.js +4 -4
- package/dist/renderables/python-space.d.ts +13 -0
- package/dist/renderables/python-space.js +24 -0
- package/dist/renderables/spinner.d.ts +73 -27
- package/dist/renderables/spinner.js +110 -51
- package/dist/renderables/status.d.ts +8 -3
- package/dist/renderables/status.js +8 -5
- package/dist/renderables/syntax.js +2 -1
- package/dist/renderables/table.d.ts +19 -11
- package/dist/renderables/table.js +140 -156
- package/dist/renderables/traceback.d.ts +1 -1
- package/dist/renderables/traceback.js +6 -5
- package/dist/renderables/tree.d.ts +6 -5
- package/dist/renderables/tree.js +11 -7
- package/dist/renderables/viewport.d.ts +13 -5
- package/dist/renderables/viewport.js +41 -20
- package/dist/template-bindings/animation-funcs.d.ts +37 -0
- package/dist/template-bindings/animation-funcs.js +83 -0
- package/dist/template-bindings/color-funcs.d.ts +13 -0
- package/dist/template-bindings/color-funcs.js +1 -1
- package/dist/template-bindings/helpers.d.ts +6 -0
- package/dist/template-bindings/helpers.js +12 -3
- package/dist/template-bindings/index.d.ts +6 -2
- package/dist/template-bindings/index.js +8 -3
- package/dist/themes/ramp.d.ts +18 -3
- package/dist/themes/ramp.js +23 -2
- package/dist/widgets/focus-manager.d.ts +21 -14
- package/dist/widgets/focus-manager.js +28 -29
- package/dist/widgets/index.d.ts +1 -1
- package/dist/widgets/static-item.d.ts +4 -3
- package/dist/widgets/static-item.js +9 -7
- package/dist/widgets/text-input.d.ts +28 -18
- package/dist/widgets/text-input.js +144 -101
- package/dist/widgets/widget-app.d.ts +19 -3
- package/dist/widgets/widget-app.js +39 -21
- package/dist/widgets/widget-base.js +0 -3
- package/package.json +2 -5
|
@@ -69,42 +69,30 @@ let DefaultFocusManager = (() => {
|
|
|
69
69
|
__esDecorate(this, null, _setFocus_decorators, { kind: "method", name: "setFocus", static: false, private: false, access: { has: obj => "setFocus" in obj, get: obj => obj.setFocus }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
70
70
|
if (_metadata) Object.defineProperty(this, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
|
|
71
71
|
}
|
|
72
|
-
|
|
72
|
+
view = __runInitializers(this, _instanceExtraInitializers);
|
|
73
73
|
#currentWidget_accessor_storage = __runInitializers(this, _currentWidget_initializers, null);
|
|
74
74
|
get currentWidget() { return this.#currentWidget_accessor_storage; }
|
|
75
75
|
set currentWidget(value) { this.#currentWidget_accessor_storage = value; }
|
|
76
76
|
changeHandlers = (__runInitializers(this, _currentWidget_extraInitializers), new Set());
|
|
77
77
|
/**
|
|
78
|
-
*
|
|
79
|
-
*
|
|
80
|
-
*
|
|
81
|
-
* of the widgets held here would be a second picture of the frame, and
|
|
82
|
-
* wrong from the next paint.
|
|
78
|
+
* [LAW:one-source-of-truth] The view is asked every time rather than kept:
|
|
79
|
+
* a list of the widgets held here would be a second picture of the frame,
|
|
80
|
+
* and wrong from the next paint.
|
|
83
81
|
*/
|
|
84
|
-
constructor(
|
|
85
|
-
this.
|
|
82
|
+
constructor(view) {
|
|
83
|
+
this.view = view;
|
|
86
84
|
}
|
|
87
85
|
get current() {
|
|
88
86
|
return this.currentWidget;
|
|
89
87
|
}
|
|
90
88
|
get widgets() {
|
|
91
|
-
return this.onScreen().filter(takesFocus);
|
|
89
|
+
return this.view.onScreen().filter(takesFocus);
|
|
92
90
|
}
|
|
93
91
|
next() {
|
|
94
|
-
|
|
95
|
-
if (focusable.length === 0)
|
|
96
|
-
return;
|
|
97
|
-
const currentIdx = this.currentWidget ? focusable.indexOf(this.currentWidget) : -1;
|
|
98
|
-
const nextIdx = (currentIdx + 1) % focusable.length;
|
|
99
|
-
this.setFocus(focusable[nextIdx]);
|
|
92
|
+
this.step(this.view.present());
|
|
100
93
|
}
|
|
101
94
|
prev() {
|
|
102
|
-
|
|
103
|
-
if (focusable.length === 0)
|
|
104
|
-
return;
|
|
105
|
-
const currentIdx = this.currentWidget ? focusable.indexOf(this.currentWidget) : -1;
|
|
106
|
-
const prevIdx = currentIdx <= 0 ? focusable.length - 1 : currentIdx - 1;
|
|
107
|
-
this.setFocus(focusable[prevIdx]);
|
|
95
|
+
this.step([...this.view.present()].reverse());
|
|
108
96
|
}
|
|
109
97
|
// A widget not on screen yet can take focus: an app that is about to show
|
|
110
98
|
// it focuses it first, and the frame that shows it keeps it (`settle`).
|
|
@@ -115,20 +103,21 @@ let DefaultFocusManager = (() => {
|
|
|
115
103
|
}
|
|
116
104
|
/**
|
|
117
105
|
* Put focus where the frame just painted lets it rest: it stays on a widget
|
|
118
|
-
* the view
|
|
119
|
-
* one on screen that can, or to none.
|
|
106
|
+
* the view holds (`present`) that can take it, and otherwise moves to the
|
|
107
|
+
* first one on screen that can, or to none.
|
|
120
108
|
*
|
|
121
|
-
*
|
|
122
|
-
* shrank, a viewport scrolled, an overlay covers it
|
|
123
|
-
*
|
|
109
|
+
* In the view, not on screen: a widget cropped for the moment — the
|
|
110
|
+
* terminal shrank, a viewport scrolled, an overlay covers it, its container
|
|
111
|
+
* handed it no column — is still in the view, and keeps focus and whatever
|
|
112
|
+
* focus holds, like a half-typed filter.
|
|
124
113
|
*
|
|
125
114
|
* [LAW:single-enforcer] The one place focus follows the frame — onto the
|
|
126
|
-
* first widget when the app starts, off a widget that
|
|
115
|
+
* first widget when the app starts, off a widget that left the view
|
|
127
116
|
* or was disabled.
|
|
128
117
|
*/
|
|
129
|
-
settle(
|
|
118
|
+
settle() {
|
|
130
119
|
const current = this.currentWidget;
|
|
131
|
-
if (current && takesFocus(current) &&
|
|
120
|
+
if (current && takesFocus(current) && this.view.present().includes(current))
|
|
132
121
|
return;
|
|
133
122
|
const first = this.widgets[0];
|
|
134
123
|
if (first)
|
|
@@ -154,6 +143,16 @@ let DefaultFocusManager = (() => {
|
|
|
154
143
|
event.stop();
|
|
155
144
|
}
|
|
156
145
|
// --- Private ---
|
|
146
|
+
// To the first widget Tab moves between that follows the focused one in
|
|
147
|
+
// `order`, wrapping. It is found by its place in the view, not among those
|
|
148
|
+
// on screen, so Tab from a widget on no cell moves to its neighbour.
|
|
149
|
+
step(order) {
|
|
150
|
+
const tabbable = new Set(this.widgets);
|
|
151
|
+
const at = this.currentWidget ? order.indexOf(this.currentWidget) : -1;
|
|
152
|
+
const target = [...order.slice(at + 1), ...order.slice(0, at + 1)].find((widget) => tabbable.has(widget));
|
|
153
|
+
if (target)
|
|
154
|
+
this.setFocus(target);
|
|
155
|
+
}
|
|
157
156
|
// No focus is where `settle` leaves an app with nothing to focus, and only
|
|
158
157
|
// there: anywhere else the next frame would put focus back on the first
|
|
159
158
|
// widget, so there is no public way in.
|
package/dist/widgets/index.d.ts
CHANGED
|
@@ -4,7 +4,7 @@ export { StaticItem } from "./static-item.js";
|
|
|
4
4
|
export type { StaticItemOptions } from "./static-item.js";
|
|
5
5
|
export { WidgetBase } from "./widget-base.js";
|
|
6
6
|
export { WidgetApp } from "./widget-app.js";
|
|
7
|
-
export type { WidgetAppOptions } from "./widget-app.js";
|
|
7
|
+
export type { WidgetAppOptions, WidgetPresence } from "./widget-app.js";
|
|
8
8
|
export { Button } from "./button.js";
|
|
9
9
|
export type { ButtonVariant, ButtonOptions } from "./button.js";
|
|
10
10
|
export { Checkbox } from "./checkbox.js";
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
* renderable.
|
|
12
12
|
*/
|
|
13
13
|
import { Segment } from "../core/segment.js";
|
|
14
|
-
import type { Measurable, Renderable, RenderOptions } from "../core/protocol.js";
|
|
14
|
+
import type { Composite, Measurable, Renderable, RenderOptions } from "../core/protocol.js";
|
|
15
15
|
import { WidgetBase } from "./widget-base.js";
|
|
16
16
|
import type { KeyEvent } from "./types.js";
|
|
17
17
|
export interface StaticItemOptions {
|
|
@@ -19,12 +19,13 @@ export interface StaticItemOptions {
|
|
|
19
19
|
render: Renderable | ((options: RenderOptions) => Iterable<Segment>);
|
|
20
20
|
measure?: Measurable["measure"];
|
|
21
21
|
}
|
|
22
|
-
export declare class StaticItem extends WidgetBase {
|
|
22
|
+
export declare class StaticItem extends WidgetBase implements Composite {
|
|
23
23
|
readonly id: string;
|
|
24
24
|
readonly focusable = false;
|
|
25
|
-
private readonly
|
|
25
|
+
private readonly body;
|
|
26
26
|
private readonly measureFn;
|
|
27
27
|
constructor(options: StaticItemOptions);
|
|
28
|
+
contents(): Iterable<Renderable>;
|
|
28
29
|
handleKey(_event: KeyEvent): void;
|
|
29
30
|
protected draw(options: RenderOptions): Iterable<Segment>;
|
|
30
31
|
measure(options: RenderOptions): {
|
|
@@ -11,27 +11,29 @@
|
|
|
11
11
|
* renderable.
|
|
12
12
|
*/
|
|
13
13
|
import { Segment } from "../core/segment.js";
|
|
14
|
+
import { render } from "../core/protocol.js";
|
|
14
15
|
import { WidgetBase } from "./widget-base.js";
|
|
15
16
|
export class StaticItem extends WidgetBase {
|
|
16
17
|
id;
|
|
17
18
|
focusable = false;
|
|
18
|
-
|
|
19
|
+
// The body as a renderable either way: a function is one that holds nothing.
|
|
20
|
+
body;
|
|
19
21
|
measureFn;
|
|
20
22
|
constructor(options) {
|
|
21
23
|
super();
|
|
22
24
|
this.id = options.id;
|
|
23
25
|
const r = options.render;
|
|
24
|
-
this.
|
|
25
|
-
typeof r === "function"
|
|
26
|
-
? (opts) => r(opts)
|
|
27
|
-
: (opts) => r.render(opts);
|
|
26
|
+
this.body = typeof r === "function" ? { render: r } : r;
|
|
28
27
|
this.measureFn = options.measure;
|
|
29
28
|
}
|
|
29
|
+
*contents() {
|
|
30
|
+
yield this.body;
|
|
31
|
+
}
|
|
30
32
|
// Static items don't respond to keys. WidgetBase.handleMouse / handleFocus
|
|
31
33
|
// are already no-ops, so we only need to satisfy the abstract handleKey.
|
|
32
34
|
handleKey(_event) { }
|
|
33
35
|
draw(options) {
|
|
34
|
-
return this.
|
|
36
|
+
return render(this.body, options);
|
|
35
37
|
}
|
|
36
38
|
measure(options) {
|
|
37
39
|
if (this.measureFn)
|
|
@@ -41,7 +43,7 @@ export class StaticItem extends WidgetBase {
|
|
|
41
43
|
// values too, not just the "\n" sentinel segment. Walking segments and
|
|
42
44
|
// testing `seg.text === "\n"` miscounts widths for any renderable
|
|
43
45
|
// that emits "a\nb" as a single segment.
|
|
44
|
-
const segments = Array.from(this.
|
|
46
|
+
const segments = Array.from(render(this.body, options));
|
|
45
47
|
const lines = Segment.splitLines(segments);
|
|
46
48
|
let max = 0;
|
|
47
49
|
for (const line of lines) {
|
|
@@ -3,10 +3,12 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Two modes:
|
|
5
5
|
* - single-line (default): Enter submits; newlines in value are rendered
|
|
6
|
-
* as a literal `↵` glyph if they ever appear
|
|
6
|
+
* as a literal `↵` glyph if they ever appear, and
|
|
7
|
+
* any other glyph of zero cells as `◌`.
|
|
7
8
|
* - multi-line (`multiline: true`): Enter inserts a `\n`; `value` may
|
|
8
9
|
* contain logical line breaks; Up/Down navigate
|
|
9
10
|
* between logical lines preserving column intent.
|
|
11
|
+
* A glyph of zero cells is drawn as `◌` here too.
|
|
10
12
|
*
|
|
11
13
|
* [LAW:dataflow-not-control-flow] cursor and value are observable data; the
|
|
12
14
|
* keymap dispatches to small `@action` mutators that all flow through the
|
|
@@ -69,20 +71,22 @@ import { ThemedWidget } from "./themed-widget.js";
|
|
|
69
71
|
import type { KeyEvent, WidgetMouseEvent } from "./types.js";
|
|
70
72
|
/**
|
|
71
73
|
* A soft-wrap strategy. Given one logical line of text and cell-width budgets,
|
|
72
|
-
* return the visual sub-rows that line wraps into. The
|
|
73
|
-
*
|
|
74
|
-
*
|
|
74
|
+
* return the visual sub-rows that line wraps into. The line arrives as the
|
|
75
|
+
* widget shows it — each glyph of zero cells already its one-cell `◌`, each
|
|
76
|
+
* glyph of a password its mask — so the budget counts the cells drawn. The
|
|
77
|
+
* first sub-row uses `firstWidth` as its capacity; every subsequent
|
|
78
|
+
* (continuation) sub-row uses `continuationWidth` (typically
|
|
79
|
+
* `firstWidth - cellLen(continuationMarker)`).
|
|
75
80
|
*
|
|
76
|
-
* Each returned row
|
|
77
|
-
*
|
|
78
|
-
*
|
|
79
|
-
* - `start` — code-unit offset into the *logical line* where `content`
|
|
80
|
-
* begins, so the widget can map visual positions back to absolute `value`
|
|
81
|
-
* offsets for cursor projection.
|
|
81
|
+
* Each returned row is the stretch `[start, end)` of the line as given that
|
|
82
|
+
* the row draws; the widget draws the matching stretch of `value` and
|
|
83
|
+
* prepends the continuation marker itself.
|
|
82
84
|
*
|
|
83
|
-
* [LAW:types-are-the-program]
|
|
84
|
-
*
|
|
85
|
-
*
|
|
85
|
+
* [LAW:types-are-the-program] A row names where it falls in the line rather
|
|
86
|
+
* than carrying text of its own, so it cannot draw anything the line does not
|
|
87
|
+
* hold. Budget params are `CellCol`; offsets are `CodePoint` (a `CodeUnit` on
|
|
88
|
+
* a code-point boundary) — the type system prevents mixing these integer
|
|
89
|
+
* spaces inside a custom strategy.
|
|
86
90
|
*
|
|
87
91
|
* Built-in: `charGreedyWrap` (break at any character at the width limit).
|
|
88
92
|
* Custom: any function matching this signature. Template-aware wrapping
|
|
@@ -94,9 +98,10 @@ export type WrapStrategy = (logicalLine: string, budget: {
|
|
|
94
98
|
continuationWidth: CellCol;
|
|
95
99
|
}) => readonly WrapRow[];
|
|
96
100
|
export interface WrapRow {
|
|
97
|
-
|
|
98
|
-
/** Code-point offset into the logical line where `content` begins. */
|
|
101
|
+
/** Offset into the line as given where the row begins. */
|
|
99
102
|
readonly start: CodePoint;
|
|
103
|
+
/** Offset into the line as given where the row ends, exclusive. */
|
|
104
|
+
readonly end: CodePoint;
|
|
100
105
|
}
|
|
101
106
|
/**
|
|
102
107
|
* Character-greedy soft wrap. Breaks at any character once `firstWidth`
|
|
@@ -225,7 +230,7 @@ export declare class TextInput extends ThemedWidget {
|
|
|
225
230
|
private _killBuffer;
|
|
226
231
|
private _scrollStart;
|
|
227
232
|
private _singleLineViewportStart;
|
|
228
|
-
private
|
|
233
|
+
private _drawn;
|
|
229
234
|
readonly multiline: boolean;
|
|
230
235
|
constructor(options?: TextInputOptions);
|
|
231
236
|
handleKey(event: KeyEvent): void;
|
|
@@ -257,12 +262,16 @@ export declare class TextInput extends ThemedWidget {
|
|
|
257
262
|
private _insertText;
|
|
258
263
|
protected get ground(): Style;
|
|
259
264
|
protected draw(options: RenderOptions): Iterable<Segment>;
|
|
265
|
+
private _shownAs;
|
|
260
266
|
private _shown;
|
|
267
|
+
private _shownCells;
|
|
268
|
+
private _offsetAtShownCell;
|
|
261
269
|
private _renderSingleLine;
|
|
262
270
|
private _renderMultiline;
|
|
271
|
+
private _drawsArrows;
|
|
263
272
|
private _emitRowContent;
|
|
264
273
|
private _computeVisualRows;
|
|
265
|
-
measure(
|
|
274
|
+
measure(options: RenderOptions): {
|
|
266
275
|
minimum: number;
|
|
267
276
|
maximum: number;
|
|
268
277
|
};
|
|
@@ -271,7 +280,8 @@ export declare class TextInput extends ThemedWidget {
|
|
|
271
280
|
* scroll, else `undefined`. X is the cursor's 1-indexed visual row; Y is
|
|
272
281
|
* the total visual row count. Reads cached state populated by the most
|
|
273
282
|
* recent `render()` — call from a `Panel.bottomRightAccessory` thunk so
|
|
274
|
-
* it evaluates after content has been rendered for the current frame
|
|
283
|
+
* it evaluates after content has been rendered for the current frame;
|
|
284
|
+
* `BorderAccessory` names the widths where it has not.
|
|
275
285
|
*
|
|
276
286
|
* Returns `undefined` when:
|
|
277
287
|
* - `scrollIndicator` is not `"indices"`, or
|