@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
|
@@ -82,6 +82,16 @@ export declare class InlineLabel {
|
|
|
82
82
|
*/
|
|
83
83
|
text(options: RenderOptions, base?: TextStyle): RichText;
|
|
84
84
|
}
|
|
85
|
+
/**
|
|
86
|
+
* `text`, changed in place into a fragment of a line it shares, as Rich's
|
|
87
|
+
* `_title` reads one: its own end is not drawn, newlines become spaces so it
|
|
88
|
+
* stays on its line, and tabs are widened to their stops before anything
|
|
89
|
+
* measures it, so a cut to a border and the width a label asks for count
|
|
90
|
+
* the cells it will draw. [LAW:single-enforcer] The one reading of "set into
|
|
91
|
+
* a line", for a label read through the crossing above and for text a
|
|
92
|
+
* caller hands over already read (`Frames`).
|
|
93
|
+
*/
|
|
94
|
+
export declare function setIntoLine(text: RichText): RichText;
|
|
85
95
|
/**
|
|
86
96
|
* A label cut to `width` cells as Rich's `Text.truncate` cuts one: its plain
|
|
87
97
|
* text set to the width less `marker` — a wide character the cut splits leaves
|
|
@@ -23,6 +23,7 @@
|
|
|
23
23
|
*/
|
|
24
24
|
import { cellCount, cellLen, setCellSize } from "../core/cells.js";
|
|
25
25
|
import { activeHighlighter, readStr } from "../core/markup.js";
|
|
26
|
+
import { render } from "../core/protocol.js";
|
|
26
27
|
import { Segment } from "../core/segment.js";
|
|
27
28
|
import { RichText } from "../core/text.js";
|
|
28
29
|
/**
|
|
@@ -71,7 +72,7 @@ export class EmbeddedText {
|
|
|
71
72
|
return text;
|
|
72
73
|
}
|
|
73
74
|
render(options) {
|
|
74
|
-
return this.text(options)
|
|
75
|
+
return render(this.text(options), options);
|
|
75
76
|
}
|
|
76
77
|
/**
|
|
77
78
|
* Measured unhighlighted, as Rich's `Measurement.get` reads a string with
|
|
@@ -114,15 +115,23 @@ export class InlineLabel {
|
|
|
114
115
|
* caller's cut. A string reads with `base` as its style, as `EmbeddedText.text` reads one.
|
|
115
116
|
*/
|
|
116
117
|
text(options, base) {
|
|
117
|
-
|
|
118
|
-
// A fragment of the line, so its own end is not drawn, as Rich's `_title` clears it.
|
|
119
|
-
text.end = "";
|
|
120
|
-
text.plain = text.plain.replaceAll("\n", " ");
|
|
121
|
-
// Tabs widened before anything measures it, so a cut to the border and
|
|
122
|
-
// the width a title asks for count the cells the label will draw.
|
|
123
|
-
return text.expandTabs();
|
|
118
|
+
return setIntoLine(this._content.text(options, base));
|
|
124
119
|
}
|
|
125
120
|
}
|
|
121
|
+
/**
|
|
122
|
+
* `text`, changed in place into a fragment of a line it shares, as Rich's
|
|
123
|
+
* `_title` reads one: its own end is not drawn, newlines become spaces so it
|
|
124
|
+
* stays on its line, and tabs are widened to their stops before anything
|
|
125
|
+
* measures it, so a cut to a border and the width a label asks for count
|
|
126
|
+
* the cells it will draw. [LAW:single-enforcer] The one reading of "set into
|
|
127
|
+
* a line", for a label read through the crossing above and for text a
|
|
128
|
+
* caller hands over already read (`Frames`).
|
|
129
|
+
*/
|
|
130
|
+
export function setIntoLine(text) {
|
|
131
|
+
text.end = "";
|
|
132
|
+
text.plain = text.plain.replaceAll("\n", " ");
|
|
133
|
+
return text.expandTabs();
|
|
134
|
+
}
|
|
126
135
|
/**
|
|
127
136
|
* A label cut to `width` cells as Rich's `Text.truncate` cuts one: its plain
|
|
128
137
|
* text set to the width less `marker` — a wide character the cut splits leaves
|
|
@@ -155,7 +164,7 @@ export function present(content) {
|
|
|
155
164
|
*/
|
|
156
165
|
export function drawLabel(text, options, base) {
|
|
157
166
|
text.overflow = "ignore";
|
|
158
|
-
return [...Segment.applyStyle(
|
|
167
|
+
return [...Segment.applyStyle(render(text, options), base)];
|
|
159
168
|
}
|
|
160
169
|
/**
|
|
161
170
|
* Caller content as a label, or no label at all: content that is not
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
* FlexStrip reuses it verbatim. There is no second concept of "join."
|
|
17
17
|
*/
|
|
18
18
|
import { Segment } from "../core/segment.js";
|
|
19
|
-
import type { Renderable, Measurable, RenderOptions } from "../core/protocol.js";
|
|
19
|
+
import type { Composite, Renderable, Measurable, RenderOptions } from "../core/protocol.js";
|
|
20
20
|
import { type Joiner, type StyledRenderable } from "../core/strip.js";
|
|
21
21
|
export type FlexAlign = "left" | "center" | "right" | "justify";
|
|
22
22
|
export interface FlexStripOptions<T extends StyledRenderable> {
|
|
@@ -27,12 +27,13 @@ export interface FlexStripOptions<T extends StyledRenderable> {
|
|
|
27
27
|
/** Line alignment when packed items don't fill the available width (default "left"). */
|
|
28
28
|
align?: FlexAlign;
|
|
29
29
|
}
|
|
30
|
-
export declare class FlexStrip<T extends StyledRenderable = StyledRenderable> implements Renderable, Measurable {
|
|
30
|
+
export declare class FlexStrip<T extends StyledRenderable = StyledRenderable> implements Renderable, Measurable, Composite {
|
|
31
31
|
readonly items: readonly T[];
|
|
32
32
|
readonly joiner: Joiner<T> | undefined;
|
|
33
33
|
readonly gap: number;
|
|
34
34
|
readonly align: FlexAlign;
|
|
35
35
|
constructor(items: readonly T[], options?: FlexStripOptions<T>);
|
|
36
|
+
contents(): Iterable<Renderable>;
|
|
36
37
|
render(options: RenderOptions): Iterable<Segment>;
|
|
37
38
|
measure(options: RenderOptions): {
|
|
38
39
|
minimum: number;
|
|
@@ -16,9 +16,10 @@
|
|
|
16
16
|
* FlexStrip reuses it verbatim. There is no second concept of "join."
|
|
17
17
|
*/
|
|
18
18
|
import { Segment } from "../core/segment.js";
|
|
19
|
+
import { render } from "../core/protocol.js";
|
|
19
20
|
import { drawItem, drawJoin } from "../core/strip.js";
|
|
20
21
|
function renderToBlock(r, options) {
|
|
21
|
-
const segments = [...
|
|
22
|
+
const segments = [...render(r, options)];
|
|
22
23
|
let width = 0;
|
|
23
24
|
for (const s of segments)
|
|
24
25
|
width += s.cellLength;
|
|
@@ -55,6 +56,10 @@ export class FlexStrip {
|
|
|
55
56
|
this.gap = options?.gap ?? 0;
|
|
56
57
|
this.align = options?.align ?? "left";
|
|
57
58
|
}
|
|
59
|
+
// The items; a join is drawn from what the joiner emits for it, not held.
|
|
60
|
+
contents() {
|
|
61
|
+
return this.items;
|
|
62
|
+
}
|
|
58
63
|
*render(options) {
|
|
59
64
|
const items = this.items;
|
|
60
65
|
if (items.length === 0)
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Frames — content that changes on a beat: a sequence of frames, each held
|
|
3
|
+
* for its own seconds and looping, drawn as the one in progress at a time
|
|
4
|
+
* the host hands in.
|
|
5
|
+
*
|
|
6
|
+
* An effect moves a cell's colours and may never change a glyph
|
|
7
|
+
* (`./effect.ts`: "It changes how cells look, never which cells exist or who
|
|
8
|
+
* drew them"). A frame is the other kind of motion — what the element shows
|
|
9
|
+
* changes — so it is its own primitive and not a wider `Effect`, and the two
|
|
10
|
+
* compose by nesting: `new Effected(new Frames(…), …)` lights whichever frame
|
|
11
|
+
* is up.
|
|
12
|
+
*
|
|
13
|
+
* [LAW:no-ambient-temporal-coupling] `t` is an argument, as
|
|
14
|
+
* `Effected`'s is, never a clock read: whoever draws frames hands each one
|
|
15
|
+
* its time (`core/clock.ts`), so the same `t` draws the same bytes at one
|
|
16
|
+
* redraw a second or sixty. The host's rate is the host's. At sixty a frame
|
|
17
|
+
* shows for exactly its hold; at one a second a hold shorter than a second is
|
|
18
|
+
* skipped and a period of whole seconds freezes on one frame, and nothing
|
|
19
|
+
* here adapts to that — the beat is `core/easing.ts`'s, the one timing
|
|
20
|
+
* vocabulary, and a draw costs the same at `t = 0` and `t = 10⁶`.
|
|
21
|
+
*
|
|
22
|
+
* The sequence and the moment are two values, because only one of them
|
|
23
|
+
* changes from frame to frame. A `FrameSequence` is the frames prepared once
|
|
24
|
+
* — the beat, the one width, each frame set into a line and padded — and an
|
|
25
|
+
* `Animation` of the frame shown (`core/animation.ts`); a `Frames` is that
|
|
26
|
+
* sequence at a `t`, whose work is one frame's — finding which, and copying
|
|
27
|
+
* it: a host holds the sequence and asks it for a frame, as `Spinner` holds
|
|
28
|
+
* its two, so a draw costs the same over ninety frames as over one. The
|
|
29
|
+
* sequence is a value the host keeps, not a memo here: nothing is looked up
|
|
30
|
+
* by key.
|
|
31
|
+
*
|
|
32
|
+
* The frame drawn is drawn until the next begins, and its cells say so: they
|
|
33
|
+
* are stamped with the sequence's `nextChange` (`Style.nextChange`), which
|
|
34
|
+
* rides up through every container to whoever holds the composed frame
|
|
35
|
+
* (`Segment.nextChange`), so a host drawing at `t` knows when to draw again,
|
|
36
|
+
* and one drawing slower than the frames turn can see that it is skipping
|
|
37
|
+
* them. The stamp is put on by whoever draws the frame at a host time
|
|
38
|
+
* (`frameAt`) — a `Frames`, a `Spinner`, the template `frames` function —
|
|
39
|
+
* and the sequence's `at` hands over the frame alone, because the time a
|
|
40
|
+
* sequence is asked for may be one a `Timeline` mapped from the host's.
|
|
41
|
+
*
|
|
42
|
+
* Every frame is drawn at one width, the widest frame's, each padded on the
|
|
43
|
+
* right to it, so whatever sits beside the frames never moves as they turn;
|
|
44
|
+
* and the frame is a fragment of a line (`setIntoLine`), ending no line of
|
|
45
|
+
* its own, so it sits among other cells. Frames are `RichText`, each free to
|
|
46
|
+
* carry its own style, and read once, here: markup is a string's reading
|
|
47
|
+
* under the console that draws it, which a frame handed to a template
|
|
48
|
+
* binding has no console for, so the frame arrives read, as a `Group`'s
|
|
49
|
+
* children do.
|
|
50
|
+
*/
|
|
51
|
+
import type { Animation } from "../core/animation.js";
|
|
52
|
+
import { type Beat } from "../core/easing.js";
|
|
53
|
+
import type { Measurable, Renderable, RenderOptions } from "../core/protocol.js";
|
|
54
|
+
import type { Segment } from "../core/segment.js";
|
|
55
|
+
import type { RichText } from "../core/text.js";
|
|
56
|
+
/** One frame: what it shows, and how long it is held, in seconds. */
|
|
57
|
+
export interface Frame {
|
|
58
|
+
readonly text: RichText;
|
|
59
|
+
readonly seconds: number;
|
|
60
|
+
}
|
|
61
|
+
/** A sequence of frames prepared to be drawn: built once, asked for the frame at a time. */
|
|
62
|
+
export declare class FrameSequence implements Animation<RichText> {
|
|
63
|
+
/** Which frame is in progress when: the holds are the frames' seconds, in order. */
|
|
64
|
+
readonly beat: Beat;
|
|
65
|
+
/** The width every frame draws at: the widest frame's, in cells. */
|
|
66
|
+
readonly width: number;
|
|
67
|
+
private readonly _shown;
|
|
68
|
+
constructor(frames: readonly Frame[]);
|
|
69
|
+
/**
|
|
70
|
+
* The frame in progress at `t`, at `width` cells, ending no line: a copy,
|
|
71
|
+
* the caller's to change, carrying no word on when it changes — that is
|
|
72
|
+
* `frameAt`'s, stamped by whoever draws it at a host time. `beat.at`
|
|
73
|
+
* refuses a `t` that is not finite.
|
|
74
|
+
*/
|
|
75
|
+
at(t: number): RichText;
|
|
76
|
+
/** When the frame in progress at `t` gives way to the next: the beat's answer, its holds being the frames'. */
|
|
77
|
+
nextChange(t: number): number;
|
|
78
|
+
/** When the frame in progress at `t` began: the beat's answer. */
|
|
79
|
+
lastChange(t: number): number;
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* The frame `animation` shows at host time `t`, its every cell — padding
|
|
83
|
+
* included, so a blank frame among drawn ones still turns — stamped with when
|
|
84
|
+
* it gives way to the next, `animation.nextChange(t)`. [LAW:one-source-of-truth]
|
|
85
|
+
* The stamp is that one answer carried on the cells (`Segment.nextChange`),
|
|
86
|
+
* so a container holding the frame passes it up without asking the
|
|
87
|
+
* animation; and it is put on here, where the host's time is known, and not
|
|
88
|
+
* in the animation's `at`, whose own time a `Timeline` or an
|
|
89
|
+
* `Animation.sequence` may have mapped from the host's — a stamp made there
|
|
90
|
+
* would be a moment on a clock the host cannot read. A copy is stamped, the
|
|
91
|
+
* caller's to change: an animation may hand back the one `RichText` it
|
|
92
|
+
* holds, as `Animation.constant` does, and a stamp on that would outlive
|
|
93
|
+
* the draw it was true for.
|
|
94
|
+
*/
|
|
95
|
+
export declare function frameAt(animation: Animation<RichText>, t: number): RichText;
|
|
96
|
+
export interface FramesOptions {
|
|
97
|
+
/** The moment to draw, in seconds. */
|
|
98
|
+
readonly t: number;
|
|
99
|
+
}
|
|
100
|
+
/** A sequence's frame in progress at one moment, as a renderable. */
|
|
101
|
+
export declare class Frames implements Renderable, Measurable {
|
|
102
|
+
readonly sequence: FrameSequence;
|
|
103
|
+
readonly t: number;
|
|
104
|
+
private readonly _shown;
|
|
105
|
+
constructor(sequence: FrameSequence, options: FramesOptions);
|
|
106
|
+
render(options: RenderOptions): Iterable<Segment>;
|
|
107
|
+
/**
|
|
108
|
+
* One width both ways: a frame is one picture, never wrapped apart at a
|
|
109
|
+
* space or narrowed as the frames turn. Fitting it to the room is
|
|
110
|
+
* `Measurement.get`'s, as for every measurable.
|
|
111
|
+
*/
|
|
112
|
+
measure(): {
|
|
113
|
+
minimum: number;
|
|
114
|
+
maximum: number;
|
|
115
|
+
};
|
|
116
|
+
}
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Frames — content that changes on a beat: a sequence of frames, each held
|
|
3
|
+
* for its own seconds and looping, drawn as the one in progress at a time
|
|
4
|
+
* the host hands in.
|
|
5
|
+
*
|
|
6
|
+
* An effect moves a cell's colours and may never change a glyph
|
|
7
|
+
* (`./effect.ts`: "It changes how cells look, never which cells exist or who
|
|
8
|
+
* drew them"). A frame is the other kind of motion — what the element shows
|
|
9
|
+
* changes — so it is its own primitive and not a wider `Effect`, and the two
|
|
10
|
+
* compose by nesting: `new Effected(new Frames(…), …)` lights whichever frame
|
|
11
|
+
* is up.
|
|
12
|
+
*
|
|
13
|
+
* [LAW:no-ambient-temporal-coupling] `t` is an argument, as
|
|
14
|
+
* `Effected`'s is, never a clock read: whoever draws frames hands each one
|
|
15
|
+
* its time (`core/clock.ts`), so the same `t` draws the same bytes at one
|
|
16
|
+
* redraw a second or sixty. The host's rate is the host's. At sixty a frame
|
|
17
|
+
* shows for exactly its hold; at one a second a hold shorter than a second is
|
|
18
|
+
* skipped and a period of whole seconds freezes on one frame, and nothing
|
|
19
|
+
* here adapts to that — the beat is `core/easing.ts`'s, the one timing
|
|
20
|
+
* vocabulary, and a draw costs the same at `t = 0` and `t = 10⁶`.
|
|
21
|
+
*
|
|
22
|
+
* The sequence and the moment are two values, because only one of them
|
|
23
|
+
* changes from frame to frame. A `FrameSequence` is the frames prepared once
|
|
24
|
+
* — the beat, the one width, each frame set into a line and padded — and an
|
|
25
|
+
* `Animation` of the frame shown (`core/animation.ts`); a `Frames` is that
|
|
26
|
+
* sequence at a `t`, whose work is one frame's — finding which, and copying
|
|
27
|
+
* it: a host holds the sequence and asks it for a frame, as `Spinner` holds
|
|
28
|
+
* its two, so a draw costs the same over ninety frames as over one. The
|
|
29
|
+
* sequence is a value the host keeps, not a memo here: nothing is looked up
|
|
30
|
+
* by key.
|
|
31
|
+
*
|
|
32
|
+
* The frame drawn is drawn until the next begins, and its cells say so: they
|
|
33
|
+
* are stamped with the sequence's `nextChange` (`Style.nextChange`), which
|
|
34
|
+
* rides up through every container to whoever holds the composed frame
|
|
35
|
+
* (`Segment.nextChange`), so a host drawing at `t` knows when to draw again,
|
|
36
|
+
* and one drawing slower than the frames turn can see that it is skipping
|
|
37
|
+
* them. The stamp is put on by whoever draws the frame at a host time
|
|
38
|
+
* (`frameAt`) — a `Frames`, a `Spinner`, the template `frames` function —
|
|
39
|
+
* and the sequence's `at` hands over the frame alone, because the time a
|
|
40
|
+
* sequence is asked for may be one a `Timeline` mapped from the host's.
|
|
41
|
+
*
|
|
42
|
+
* Every frame is drawn at one width, the widest frame's, each padded on the
|
|
43
|
+
* right to it, so whatever sits beside the frames never moves as they turn;
|
|
44
|
+
* and the frame is a fragment of a line (`setIntoLine`), ending no line of
|
|
45
|
+
* its own, so it sits among other cells. Frames are `RichText`, each free to
|
|
46
|
+
* carry its own style, and read once, here: markup is a string's reading
|
|
47
|
+
* under the console that draws it, which a frame handed to a template
|
|
48
|
+
* binding has no console for, so the frame arrives read, as a `Group`'s
|
|
49
|
+
* children do.
|
|
50
|
+
*/
|
|
51
|
+
import { beat } from "../core/easing.js";
|
|
52
|
+
import { render } from "../core/protocol.js";
|
|
53
|
+
import { Style } from "../core/style.js";
|
|
54
|
+
import { setIntoLine } from "./embed.js";
|
|
55
|
+
/** A sequence of frames prepared to be drawn: built once, asked for the frame at a time. */
|
|
56
|
+
export class FrameSequence {
|
|
57
|
+
/** Which frame is in progress when: the holds are the frames' seconds, in order. */
|
|
58
|
+
beat;
|
|
59
|
+
/** The width every frame draws at: the widest frame's, in cells. */
|
|
60
|
+
width;
|
|
61
|
+
// Each frame as it draws: a line fragment padded to `width`, made once.
|
|
62
|
+
_shown;
|
|
63
|
+
constructor(frames) {
|
|
64
|
+
this.beat = beat(frames.map((frame) => frame.seconds));
|
|
65
|
+
const texts = frames.map((frame) => setIntoLine(frame.text.copy()));
|
|
66
|
+
const widths = texts.map((text) => text.cellLength);
|
|
67
|
+
this.width = Math.max(...widths);
|
|
68
|
+
this._shown = texts.map((text, i) => {
|
|
69
|
+
// One picture: a slot narrower than the frame crops it, never folds
|
|
70
|
+
// or wraps it onto a second line, which `Frames.measure` says it cannot take.
|
|
71
|
+
text.noWrap = true;
|
|
72
|
+
text.overflow = "crop";
|
|
73
|
+
return text.padRight(this.width - widths[i]);
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* The frame in progress at `t`, at `width` cells, ending no line: a copy,
|
|
78
|
+
* the caller's to change, carrying no word on when it changes — that is
|
|
79
|
+
* `frameAt`'s, stamped by whoever draws it at a host time. `beat.at`
|
|
80
|
+
* refuses a `t` that is not finite.
|
|
81
|
+
*/
|
|
82
|
+
at(t) {
|
|
83
|
+
return this._shown[this.beat.at(t)].copy();
|
|
84
|
+
}
|
|
85
|
+
/** When the frame in progress at `t` gives way to the next: the beat's answer, its holds being the frames'. */
|
|
86
|
+
nextChange(t) {
|
|
87
|
+
return this.beat.nextChange(t);
|
|
88
|
+
}
|
|
89
|
+
/** When the frame in progress at `t` began: the beat's answer. */
|
|
90
|
+
lastChange(t) {
|
|
91
|
+
return this.beat.lastChange(t);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* The frame `animation` shows at host time `t`, its every cell — padding
|
|
96
|
+
* included, so a blank frame among drawn ones still turns — stamped with when
|
|
97
|
+
* it gives way to the next, `animation.nextChange(t)`. [LAW:one-source-of-truth]
|
|
98
|
+
* The stamp is that one answer carried on the cells (`Segment.nextChange`),
|
|
99
|
+
* so a container holding the frame passes it up without asking the
|
|
100
|
+
* animation; and it is put on here, where the host's time is known, and not
|
|
101
|
+
* in the animation's `at`, whose own time a `Timeline` or an
|
|
102
|
+
* `Animation.sequence` may have mapped from the host's — a stamp made there
|
|
103
|
+
* would be a moment on a clock the host cannot read. A copy is stamped, the
|
|
104
|
+
* caller's to change: an animation may hand back the one `RichText` it
|
|
105
|
+
* holds, as `Animation.constant` does, and a stamp on that would outlive
|
|
106
|
+
* the draw it was true for.
|
|
107
|
+
*/
|
|
108
|
+
export function frameAt(animation, t) {
|
|
109
|
+
return animation.at(t).copy().stylize(new Style({ nextChange: animation.nextChange(t) }));
|
|
110
|
+
}
|
|
111
|
+
/** A sequence's frame in progress at one moment, as a renderable. */
|
|
112
|
+
export class Frames {
|
|
113
|
+
sequence;
|
|
114
|
+
t;
|
|
115
|
+
// The frame `t` lands on, found once, here, so a bad time fails at construction.
|
|
116
|
+
_shown;
|
|
117
|
+
constructor(sequence, options) {
|
|
118
|
+
this.sequence = sequence;
|
|
119
|
+
this.t = options.t;
|
|
120
|
+
this._shown = frameAt(sequence, options.t);
|
|
121
|
+
}
|
|
122
|
+
render(options) {
|
|
123
|
+
return render(this._shown, options);
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* One width both ways: a frame is one picture, never wrapped apart at a
|
|
127
|
+
* space or narrowed as the frames turn. Fitting it to the room is
|
|
128
|
+
* `Measurement.get`'s, as for every measurable.
|
|
129
|
+
*/
|
|
130
|
+
measure() {
|
|
131
|
+
return { minimum: this.sequence.width, maximum: this.sequence.width };
|
|
132
|
+
}
|
|
133
|
+
}
|
|
@@ -4,11 +4,12 @@
|
|
|
4
4
|
*/
|
|
5
5
|
import type { Segment } from "../core/segment.js";
|
|
6
6
|
import { type Measurement } from "../core/measure.js";
|
|
7
|
-
import type { Measurable, Renderable, RenderOptions } from "../core/protocol.js";
|
|
8
|
-
export declare class Group implements Renderable, Measurable {
|
|
7
|
+
import type { Composite, Measurable, Renderable, RenderOptions } from "../core/protocol.js";
|
|
8
|
+
export declare class Group implements Renderable, Measurable, Composite {
|
|
9
9
|
readonly renderables: Renderable[];
|
|
10
10
|
constructor(...renderables: Renderable[]);
|
|
11
11
|
render(options: RenderOptions): Iterable<Segment>;
|
|
12
12
|
/** As wide as its widest member: the reference's `measure_renderables`. */
|
|
13
13
|
measure(options: RenderOptions): Measurement;
|
|
14
|
+
contents(): Iterable<Renderable>;
|
|
14
15
|
}
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* No visual chrome — purely a container.
|
|
4
4
|
*/
|
|
5
5
|
import { measureRenderables } from "../core/measure.js";
|
|
6
|
-
import { stackedHeight } from "../core/protocol.js";
|
|
6
|
+
import { render, stackedHeight } from "../core/protocol.js";
|
|
7
7
|
export class Group {
|
|
8
8
|
renderables;
|
|
9
9
|
constructor(...renderables) {
|
|
@@ -12,11 +12,14 @@ export class Group {
|
|
|
12
12
|
*render(options) {
|
|
13
13
|
const memberOptions = { ...options, height: stackedHeight(options.height) };
|
|
14
14
|
for (const renderable of this.renderables) {
|
|
15
|
-
yield*
|
|
15
|
+
yield* render(renderable, memberOptions);
|
|
16
16
|
}
|
|
17
17
|
}
|
|
18
18
|
/** As wide as its widest member: the reference's `measure_renderables`. */
|
|
19
19
|
measure(options) {
|
|
20
20
|
return measureRenderables(options, this.renderables);
|
|
21
21
|
}
|
|
22
|
+
contents() {
|
|
23
|
+
return this.renderables;
|
|
24
|
+
}
|
|
22
25
|
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* HTML's named character references, each name without its `;`, to the
|
|
3
|
+
* characters it stands for — the table markdown-it-py, Rich's parser, decodes
|
|
4
|
+
* with. Generated by scripts/html-entities.py from Python's
|
|
5
|
+
* `html.entities.html5`; regenerate rather than edit.
|
|
6
|
+
*/
|
|
7
|
+
/** The characters `name`, a reference's name without its `&` and `;`, stands for, if it names any. */
|
|
8
|
+
export declare function namedReference(name: string): string | undefined;
|