@promptctl/rich-js 0.24.1 → 0.25.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/README.md +7 -0
- package/dist/core/anchor.d.ts +5 -0
- package/dist/core/anchor.js +11 -4
- package/dist/core/animation.d.ts +175 -10
- package/dist/core/animation.js +283 -15
- package/dist/core/ansi.js +2 -2
- package/dist/core/box.d.ts +7 -7
- package/dist/core/cells.d.ts +23 -13
- package/dist/core/cells.js +58 -48
- package/dist/core/clock.d.ts +2 -2
- package/dist/core/clock.js +6 -4
- package/dist/core/color.d.ts +27 -10
- package/dist/core/color.js +24 -33
- package/dist/core/console.d.ts +28 -17
- package/dist/core/console.js +44 -39
- package/dist/core/easing.d.ts +30 -0
- package/dist/core/easing.js +65 -20
- package/dist/core/emoji.d.ts +1 -1
- package/dist/core/emoji.js +1 -2
- package/dist/core/export-html.js +2 -1
- package/dist/core/export-lines.js +3 -3
- package/dist/core/highlighter.d.ts +9 -8
- package/dist/core/highlighter.js +3 -2
- package/dist/core/json.js +2 -2
- package/dist/core/markup.js +16 -12
- package/dist/core/measure.js +2 -2
- package/dist/core/memo.d.ts +11 -2
- package/dist/core/memo.js +16 -0
- package/dist/core/oklch.js +17 -6
- package/dist/core/osc8.d.ts +1 -1
- package/dist/core/osc8.js +4 -5
- package/dist/core/paint.d.ts +2 -1
- package/dist/core/paint.js +4 -3
- package/dist/core/pattern.d.ts +21 -0
- package/dist/core/pattern.js +21 -0
- package/dist/core/pretty.js +9 -10
- package/dist/core/protocol.d.ts +100 -39
- package/dist/core/protocol.js +167 -21
- package/dist/core/render.d.ts +15 -2
- package/dist/core/render.js +25 -5
- package/dist/core/segment.d.ts +13 -5
- package/dist/core/segment.js +23 -9
- package/dist/core/spinnerData.d.ts +1 -1
- package/dist/core/state.d.ts +53 -0
- package/dist/core/state.js +82 -0
- package/dist/core/strip.d.ts +98 -29
- package/dist/core/strip.js +211 -150
- package/dist/core/style.d.ts +47 -14
- package/dist/core/style.js +57 -28
- package/dist/core/text.d.ts +5 -8
- package/dist/core/text.js +116 -124
- package/dist/core/timeline.d.ts +30 -5
- package/dist/core/timeline.js +43 -7
- package/dist/core/tween.d.ts +1 -1
- package/dist/core/tween.js +5 -3
- package/dist/core/view.d.ts +92 -0
- package/dist/core/view.js +83 -0
- package/dist/host/app.d.ts +49 -21
- package/dist/host/app.js +71 -37
- package/dist/host/input.js +3 -4
- package/dist/index.d.ts +24 -12
- package/dist/index.js +9 -4
- package/dist/node/traceback.js +4 -3
- package/dist/renderables/align.d.ts +2 -3
- package/dist/renderables/align.js +0 -3
- package/dist/renderables/change.d.ts +42 -0
- package/dist/renderables/change.js +112 -0
- package/dist/renderables/columns.d.ts +3 -4
- package/dist/renderables/columns.js +2 -7
- package/dist/renderables/constrain.d.ts +2 -3
- package/dist/renderables/constrain.js +0 -3
- package/dist/renderables/effect.d.ts +158 -63
- package/dist/renderables/effect.js +378 -155
- package/dist/renderables/effects.d.ts +122 -11
- package/dist/renderables/effects.js +238 -94
- package/dist/renderables/embed.d.ts +1 -1
- package/dist/renderables/embed.js +16 -8
- package/dist/renderables/flexStrip.d.ts +2 -3
- package/dist/renderables/flexStrip.js +0 -4
- package/dist/renderables/frames.d.ts +35 -54
- package/dist/renderables/frames.js +43 -58
- package/dist/renderables/glyph-effect.d.ts +158 -0
- package/dist/renderables/glyph-effect.js +237 -0
- package/dist/renderables/glyph-effects.d.ts +147 -0
- package/dist/renderables/glyph-effects.js +283 -0
- package/dist/renderables/group.d.ts +3 -4
- package/dist/renderables/group.js +0 -3
- package/dist/renderables/layout.d.ts +12 -12
- package/dist/renderables/layout.js +40 -46
- package/dist/renderables/lifecycle.d.ts +77 -0
- package/dist/renderables/lifecycle.js +132 -0
- package/dist/renderables/list-view.d.ts +4 -5
- package/dist/renderables/list-view.js +9 -13
- package/dist/renderables/live.d.ts +36 -21
- package/dist/renderables/live.js +88 -41
- package/dist/renderables/markdown-parse.d.ts +4 -4
- package/dist/renderables/markdown-parse.js +52 -46
- package/dist/renderables/markdown-url.js +11 -11
- package/dist/renderables/padding.d.ts +4 -5
- package/dist/renderables/padding.js +0 -3
- package/dist/renderables/panel.d.ts +14 -16
- package/dist/renderables/panel.js +6 -14
- package/dist/renderables/progress.d.ts +83 -34
- package/dist/renderables/progress.js +182 -95
- package/dist/renderables/progressBar.d.ts +22 -12
- package/dist/renderables/progressBar.js +32 -9
- package/dist/renderables/prompt.js +3 -2
- package/dist/renderables/python-space.js +2 -1
- package/dist/renderables/scroll.d.ts +50 -0
- package/dist/renderables/scroll.js +106 -0
- package/dist/renderables/spinner.d.ts +35 -14
- package/dist/renderables/spinner.js +65 -25
- package/dist/renderables/status.js +1 -1
- package/dist/renderables/syntax.d.ts +10 -9
- package/dist/renderables/syntax.js +3 -2
- package/dist/renderables/table.d.ts +34 -40
- package/dist/renderables/table.js +41 -63
- package/dist/renderables/traceback.d.ts +2 -2
- package/dist/renderables/traceback.js +6 -5
- package/dist/renderables/tree.d.ts +27 -25
- package/dist/renderables/tree.js +104 -58
- package/dist/renderables/viewport.d.ts +75 -44
- package/dist/renderables/viewport.js +145 -82
- package/dist/template-bindings/animation-funcs.d.ts +78 -9
- package/dist/template-bindings/animation-funcs.js +132 -14
- package/dist/template-bindings/index.d.ts +5 -5
- package/dist/template-bindings/index.js +5 -5
- package/dist/themes/ramp.d.ts +46 -3
- package/dist/themes/ramp.js +61 -4
- package/dist/themes/registry.js +5 -7
- package/dist/widgets/button.js +3 -2
- package/dist/widgets/checkbox.js +4 -3
- package/dist/widgets/dropdown.d.ts +3 -1
- package/dist/widgets/dropdown.js +20 -15
- package/dist/widgets/event-router.js +4 -2
- package/dist/widgets/focus-manager.d.ts +2 -0
- package/dist/widgets/focus-manager.js +6 -4
- package/dist/widgets/hit.d.ts +6 -0
- package/dist/widgets/hit.js +8 -1
- package/dist/widgets/observable.d.ts +23 -0
- package/dist/widgets/observable.js +43 -0
- package/dist/widgets/slider.d.ts +1 -1
- package/dist/widgets/slider.js +12 -3
- package/dist/widgets/static-item.d.ts +2 -3
- package/dist/widgets/static-item.js +0 -3
- package/dist/widgets/text-input.d.ts +28 -32
- package/dist/widgets/text-input.js +360 -346
- package/dist/widgets/themed-widget.js +2 -1
- package/dist/widgets/toggle.js +4 -3
- package/dist/widgets/types.d.ts +10 -4
- package/dist/widgets/types.js +8 -2
- package/dist/widgets/widget-app.d.ts +14 -4
- package/dist/widgets/widget-app.js +36 -7
- package/dist/widgets/widget-base.d.ts +2 -2
- package/dist/widgets/widget-base.js +29 -18
- package/package.json +8 -1
|
@@ -7,37 +7,33 @@
|
|
|
7
7
|
* (`./effect.ts`: "It changes how cells look, never which cells exist or who
|
|
8
8
|
* drew them"). A frame is the other kind of motion — what the element shows
|
|
9
9
|
* changes — so it is its own primitive and not a wider `Effect`, and the two
|
|
10
|
-
* compose by nesting: `new Effected(
|
|
11
|
-
*
|
|
10
|
+
* compose by nesting: `new Effected(sequence, …)` lights whichever frame is
|
|
11
|
+
* up.
|
|
12
12
|
*
|
|
13
|
-
* [LAW:no-ambient-temporal-coupling] `t` is
|
|
14
|
-
*
|
|
15
|
-
*
|
|
13
|
+
* [LAW:no-ambient-temporal-coupling] `t` is the frame's time, never a
|
|
14
|
+
* clock read: whoever draws frames hands each one its time
|
|
15
|
+
* (`RenderOptions.frame`), so the same `t` draws the same bytes at one
|
|
16
16
|
* redraw a second or sixty. The host's rate is the host's. At sixty a frame
|
|
17
17
|
* shows for exactly its hold; at one a second a hold shorter than a second is
|
|
18
18
|
* skipped and a period of whole seconds freezes on one frame, and nothing
|
|
19
19
|
* here adapts to that — the beat is `core/easing.ts`'s, the one timing
|
|
20
20
|
* vocabulary, and a draw costs the same at `t = 0` and `t = 10⁶`.
|
|
21
21
|
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
*
|
|
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.
|
|
22
|
+
* A `FrameSequence` is the frames prepared once — the beat, the one width,
|
|
23
|
+
* each frame set into a line and padded — and an `Animation` of the frame
|
|
24
|
+
* shown (`core/animation.ts`), placed like any other: drawn, its work is one
|
|
25
|
+
* frame's — finding which, and copying it — so a draw costs the same over
|
|
26
|
+
* ninety frames as over one. The sequence is a value its holder keeps, as
|
|
27
|
+
* `Spinner` holds its two, not a memo here: nothing is looked up by key.
|
|
31
28
|
*
|
|
32
|
-
* The frame drawn is drawn until the next begins, and its cells say so:
|
|
33
|
-
*
|
|
34
|
-
*
|
|
29
|
+
* The frame drawn is drawn until the next begins, and its cells say so: a
|
|
30
|
+
* placed sequence stamps them with its hold (`Style.hold`,
|
|
31
|
+
* `placedRender` in `core/animation.ts`), which rides up
|
|
32
|
+
* through every container to whoever holds the composed frame
|
|
35
33
|
* (`Segment.nextChange`), so a host drawing at `t` knows when to draw again,
|
|
36
34
|
* and one drawing slower than the frames turn can see that it is skipping
|
|
37
|
-
* them.
|
|
38
|
-
*
|
|
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.
|
|
35
|
+
* them. Nothing an animation's `at` returns carries a stamp of its own: the
|
|
36
|
+
* stamp is put on where the frame's time is known.
|
|
41
37
|
*
|
|
42
38
|
* Every frame is drawn at one width, the widest frame's, each padded on the
|
|
43
39
|
* right to it, so whatever sits beside the frames never moves as they turn;
|
|
@@ -48,11 +44,11 @@
|
|
|
48
44
|
* binding has no console for, so the frame arrives read, as a `Group`'s
|
|
49
45
|
* children do.
|
|
50
46
|
*/
|
|
51
|
-
import
|
|
47
|
+
import { Animation } from "../core/animation.js";
|
|
52
48
|
import { type Beat } from "../core/easing.js";
|
|
53
|
-
import type {
|
|
49
|
+
import type { Motion, RenderOptions } from "../core/protocol.js";
|
|
54
50
|
import type { Segment } from "../core/segment.js";
|
|
55
|
-
import
|
|
51
|
+
import { RichText } from "../core/text.js";
|
|
56
52
|
/** One frame: what it shows, and how long it is held, in seconds. */
|
|
57
53
|
export interface Frame {
|
|
58
54
|
readonly text: RichText;
|
|
@@ -69,7 +65,7 @@ export declare class FrameSequence implements Animation<RichText> {
|
|
|
69
65
|
/**
|
|
70
66
|
* The frame in progress at `t`, at `width` cells, ending no line: a copy,
|
|
71
67
|
* the caller's to change, carrying no word on when it changes — that is
|
|
72
|
-
*
|
|
68
|
+
* stamped where it is placed, at the frame's time. `beat.at`
|
|
73
69
|
* refuses a `t` that is not finite.
|
|
74
70
|
*/
|
|
75
71
|
at(t: number): RichText;
|
|
@@ -77,40 +73,25 @@ export declare class FrameSequence implements Animation<RichText> {
|
|
|
77
73
|
nextChange(t: number): number;
|
|
78
74
|
/** When the frame in progress at `t` began: the beat's answer. */
|
|
79
75
|
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);
|
|
76
|
+
/** The frames with their motion taken out: the beat's first frame, held, a copy as `at`'s is. */
|
|
77
|
+
reduced(): Animation<RichText>;
|
|
106
78
|
render(options: RenderOptions): Iterable<Segment>;
|
|
107
79
|
/**
|
|
108
|
-
* One width both ways
|
|
109
|
-
*
|
|
110
|
-
* `Measurement.get`'s, as for every measurable.
|
|
80
|
+
* One width both ways, the same for every frame and reduced or not: a frame
|
|
81
|
+
* is one picture, never wrapped apart at a space or narrowed as the frames
|
|
82
|
+
* turn. Fitting it to the room is `Measurement.get`'s, as for every measurable.
|
|
111
83
|
*/
|
|
112
84
|
measure(): {
|
|
113
85
|
minimum: number;
|
|
114
86
|
maximum: number;
|
|
115
87
|
};
|
|
116
88
|
}
|
|
89
|
+
/**
|
|
90
|
+
* The text frame `animation` shows at host time `t` under `motion`
|
|
91
|
+
* (`shownAt`), copied and stamped with the hold it is in there: what the
|
|
92
|
+
* template `frames` and `glyphs` functions, which know the reader's
|
|
93
|
+
* preference before any render, splice into a line. The stamp is on the
|
|
94
|
+
* base style, which an empty text still draws as its one piece of no width,
|
|
95
|
+
* and on a copy, since an animation may hand back the one `RichText` it holds.
|
|
96
|
+
*/
|
|
97
|
+
export declare function textFrameAt(animation: Animation<RichText>, t: number, motion: Motion): RichText;
|
|
@@ -7,37 +7,33 @@
|
|
|
7
7
|
* (`./effect.ts`: "It changes how cells look, never which cells exist or who
|
|
8
8
|
* drew them"). A frame is the other kind of motion — what the element shows
|
|
9
9
|
* changes — so it is its own primitive and not a wider `Effect`, and the two
|
|
10
|
-
* compose by nesting: `new Effected(
|
|
11
|
-
*
|
|
10
|
+
* compose by nesting: `new Effected(sequence, …)` lights whichever frame is
|
|
11
|
+
* up.
|
|
12
12
|
*
|
|
13
|
-
* [LAW:no-ambient-temporal-coupling] `t` is
|
|
14
|
-
*
|
|
15
|
-
*
|
|
13
|
+
* [LAW:no-ambient-temporal-coupling] `t` is the frame's time, never a
|
|
14
|
+
* clock read: whoever draws frames hands each one its time
|
|
15
|
+
* (`RenderOptions.frame`), so the same `t` draws the same bytes at one
|
|
16
16
|
* redraw a second or sixty. The host's rate is the host's. At sixty a frame
|
|
17
17
|
* shows for exactly its hold; at one a second a hold shorter than a second is
|
|
18
18
|
* skipped and a period of whole seconds freezes on one frame, and nothing
|
|
19
19
|
* here adapts to that — the beat is `core/easing.ts`'s, the one timing
|
|
20
20
|
* vocabulary, and a draw costs the same at `t = 0` and `t = 10⁶`.
|
|
21
21
|
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
*
|
|
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.
|
|
22
|
+
* A `FrameSequence` is the frames prepared once — the beat, the one width,
|
|
23
|
+
* each frame set into a line and padded — and an `Animation` of the frame
|
|
24
|
+
* shown (`core/animation.ts`), placed like any other: drawn, its work is one
|
|
25
|
+
* frame's — finding which, and copying it — so a draw costs the same over
|
|
26
|
+
* ninety frames as over one. The sequence is a value its holder keeps, as
|
|
27
|
+
* `Spinner` holds its two, not a memo here: nothing is looked up by key.
|
|
31
28
|
*
|
|
32
|
-
* The frame drawn is drawn until the next begins, and its cells say so:
|
|
33
|
-
*
|
|
34
|
-
*
|
|
29
|
+
* The frame drawn is drawn until the next begins, and its cells say so: a
|
|
30
|
+
* placed sequence stamps them with its hold (`Style.hold`,
|
|
31
|
+
* `placedRender` in `core/animation.ts`), which rides up
|
|
32
|
+
* through every container to whoever holds the composed frame
|
|
35
33
|
* (`Segment.nextChange`), so a host drawing at `t` knows when to draw again,
|
|
36
34
|
* and one drawing slower than the frames turn can see that it is skipping
|
|
37
|
-
* them.
|
|
38
|
-
*
|
|
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.
|
|
35
|
+
* them. Nothing an animation's `at` returns carries a stamp of its own: the
|
|
36
|
+
* stamp is put on where the frame's time is known.
|
|
41
37
|
*
|
|
42
38
|
* Every frame is drawn at one width, the widest frame's, each padded on the
|
|
43
39
|
* right to it, so whatever sits beside the frames never moves as they turn;
|
|
@@ -48,9 +44,9 @@
|
|
|
48
44
|
* binding has no console for, so the frame arrives read, as a `Group`'s
|
|
49
45
|
* children do.
|
|
50
46
|
*/
|
|
47
|
+
import { Animation, holdOf, placedRender, shownAt, stamp } from "../core/animation.js";
|
|
51
48
|
import { beat } from "../core/easing.js";
|
|
52
|
-
import {
|
|
53
|
-
import { Style } from "../core/style.js";
|
|
49
|
+
import { layerStyle } from "../core/style.js";
|
|
54
50
|
import { setIntoLine } from "./embed.js";
|
|
55
51
|
/** A sequence of frames prepared to be drawn: built once, asked for the frame at a time. */
|
|
56
52
|
export class FrameSequence {
|
|
@@ -67,7 +63,7 @@ export class FrameSequence {
|
|
|
67
63
|
this.width = Math.max(...widths);
|
|
68
64
|
this._shown = texts.map((text, i) => {
|
|
69
65
|
// One picture: a slot narrower than the frame crops it, never folds
|
|
70
|
-
// or wraps it onto a second line, which `
|
|
66
|
+
// or wraps it onto a second line, which `measure` says it cannot take.
|
|
71
67
|
text.noWrap = true;
|
|
72
68
|
text.overflow = "crop";
|
|
73
69
|
return text.padRight(this.width - widths[i]);
|
|
@@ -76,7 +72,7 @@ export class FrameSequence {
|
|
|
76
72
|
/**
|
|
77
73
|
* The frame in progress at `t`, at `width` cells, ending no line: a copy,
|
|
78
74
|
* the caller's to change, carrying no word on when it changes — that is
|
|
79
|
-
*
|
|
75
|
+
* stamped where it is placed, at the frame's time. `beat.at`
|
|
80
76
|
* refuses a `t` that is not finite.
|
|
81
77
|
*/
|
|
82
78
|
at(t) {
|
|
@@ -90,44 +86,33 @@ export class FrameSequence {
|
|
|
90
86
|
lastChange(t) {
|
|
91
87
|
return this.beat.lastChange(t);
|
|
92
88
|
}
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
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);
|
|
89
|
+
/** The frames with their motion taken out: the beat's first frame, held, a copy as `at`'s is. */
|
|
90
|
+
reduced() {
|
|
91
|
+
return Animation.map(this.beat.reduced(), (i) => this._shown[i].copy());
|
|
121
92
|
}
|
|
122
93
|
render(options) {
|
|
123
|
-
return
|
|
94
|
+
return placedRender(this, options);
|
|
124
95
|
}
|
|
125
96
|
/**
|
|
126
|
-
* One width both ways
|
|
127
|
-
*
|
|
128
|
-
* `Measurement.get`'s, as for every measurable.
|
|
97
|
+
* One width both ways, the same for every frame and reduced or not: a frame
|
|
98
|
+
* is one picture, never wrapped apart at a space or narrowed as the frames
|
|
99
|
+
* turn. Fitting it to the room is `Measurement.get`'s, as for every measurable.
|
|
129
100
|
*/
|
|
130
101
|
measure() {
|
|
131
|
-
return { minimum: this.
|
|
102
|
+
return { minimum: this.width, maximum: this.width };
|
|
132
103
|
}
|
|
133
104
|
}
|
|
105
|
+
/**
|
|
106
|
+
* The text frame `animation` shows at host time `t` under `motion`
|
|
107
|
+
* (`shownAt`), copied and stamped with the hold it is in there: what the
|
|
108
|
+
* template `frames` and `glyphs` functions, which know the reader's
|
|
109
|
+
* preference before any render, splice into a line. The stamp is on the
|
|
110
|
+
* base style, which an empty text still draws as its one piece of no width,
|
|
111
|
+
* and on a copy, since an animation may hand back the one `RichText` it holds.
|
|
112
|
+
*/
|
|
113
|
+
export function textFrameAt(animation, t, motion) {
|
|
114
|
+
const shown = shownAt(animation, t, motion);
|
|
115
|
+
const stamped = shown.value.copy();
|
|
116
|
+
stamped.style = layerStyle(stamped.style, stamp(holdOf(shown, t)));
|
|
117
|
+
return stamped;
|
|
118
|
+
}
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GlyphEffected — a renderable whose finished cells' glyphs pass through a
|
|
3
|
+
* glyph effect at a moment `t`: the glyph half of `Effected` (`./effect.ts`),
|
|
4
|
+
* built to its contract.
|
|
5
|
+
*
|
|
6
|
+
* A glyph effect is the colour effect's two-stage shape with a glyph where
|
|
7
|
+
* the colours were: for the cells an element draws in a frame, an
|
|
8
|
+
* `Animation` (`../core/animation.ts`) of what is done to them. The first
|
|
9
|
+
* stage is handed every cell once a frame (`GlyphCell`), blanks included —
|
|
10
|
+
* rain and stars live there — and whether the output draws ASCII alone
|
|
11
|
+
* (`DrawnGlyphs`), and works out what holds for the whole frame:
|
|
12
|
+
* how many cells are typed, where a band is. The second, the function
|
|
13
|
+
* `at(t)` returns, maps each cell to the text it shows. A typewriter, a
|
|
14
|
+
* scramble, a wave of case changes and particles on blank cells are all this
|
|
15
|
+
* one shape (`./glyph-effects.ts`) [LAW:one-type-per-behavior].
|
|
16
|
+
*
|
|
17
|
+
* Colour and glyph are not two kinds of animation: each is an `Animation` of
|
|
18
|
+
* a per-cell map, and they differ only in what a cell is mapped to. The
|
|
19
|
+
* wrappers are two because the stages are handed different facts. A colour
|
|
20
|
+
* effect is settled against the depth, the terminal and the colours of the
|
|
21
|
+
* words (`Drawn`), and with no colour output there is nothing for it to
|
|
22
|
+
* change. A glyph effect needs none of that, and is written at every depth,
|
|
23
|
+
* with no colour too. Over one element the two compose by nesting:
|
|
24
|
+
* `new Effected(new GlyphEffected(child, glyphs, …), colours, …)` moves the
|
|
25
|
+
* colours of the glyphs the glyph effect left, since each wrapper measures
|
|
26
|
+
* what its child drew.
|
|
27
|
+
*
|
|
28
|
+
* A `GlyphEffected` is the element under its glyph effect over time, an
|
|
29
|
+
* `Animation<Renderable>` placed as an `Effected` is, its value at `t` the
|
|
30
|
+
* element through the effect at `t` (`Reglyphed`).
|
|
31
|
+
* [LAW:no-ambient-temporal-coupling] The time is the frame's, never a clock
|
|
32
|
+
* read, so the same time draws the same bytes at any frame rate.
|
|
33
|
+
*
|
|
34
|
+
* What a glyph effect may not do is the contract this module holds:
|
|
35
|
+
*
|
|
36
|
+
* - It changes what a cell shows, never which cells exist, where they are or
|
|
37
|
+
* who drew them. The text it returns for a cell is exactly as many cells
|
|
38
|
+
* wide (`cellLen`), carries no line break or control character, and does
|
|
39
|
+
* not join the cell beside it into one grapheme cluster, or the render
|
|
40
|
+
* throws naming the cell [LAW:single-enforcer]. So what sits beside the
|
|
41
|
+
* element never moves, and a wide glyph is changed whole — blanked as two
|
|
42
|
+
* spaces, scrambled as two one-cell glyphs — never cut.
|
|
43
|
+
* - A segment whose every glyph comes back as it was is yielded as it was,
|
|
44
|
+
* so the identity effect is byte-identical. A changed segment keeps its
|
|
45
|
+
* style whole, link, meta and anchor included; no cell has moved, so the
|
|
46
|
+
* anchor's offsets are still true and hit testing still finds the owner.
|
|
47
|
+
* - Placed as a `GlyphEffected`, every cell carries the hold the frame is in
|
|
48
|
+
* (`Style.hold`), under whatever the child said,
|
|
49
|
+
* as under `Effected`; drawn as a `Reglyphed`, a value, none.
|
|
50
|
+
*
|
|
51
|
+
* Positions are the child's own: row and column count from the top-left of
|
|
52
|
+
* what the child drew.
|
|
53
|
+
*/
|
|
54
|
+
import { Animation } from "../core/animation.js";
|
|
55
|
+
import type { Measurable, Renderable, RenderOptions } from "../core/protocol.js";
|
|
56
|
+
import { Segment } from "../core/segment.js";
|
|
57
|
+
import { type RichText } from "../core/text.js";
|
|
58
|
+
import { type Moved, type Placed } from "./effect.js";
|
|
59
|
+
/**
|
|
60
|
+
* A cell of the element a glyph effect wraps: the glyph it shows, where it
|
|
61
|
+
* sits and who drew it, its place in reading order among the cells handed
|
|
62
|
+
* (`DrawnGlyphs.cells[index]` is this cell), and its seed, a number in [0, 1) that is the
|
|
63
|
+
* same for that cell on every frame, as an `EffectCell`'s is.
|
|
64
|
+
*/
|
|
65
|
+
export interface GlyphCell extends Placed {
|
|
66
|
+
readonly glyph: string;
|
|
67
|
+
readonly index: number;
|
|
68
|
+
readonly seed: number;
|
|
69
|
+
}
|
|
70
|
+
/** What a glyph effect does to the cells of one frame: a cell in, the text it shows out, as many cells wide. Return `cell.glyph` to leave it be. */
|
|
71
|
+
export type GlyphFrame = (cell: GlyphCell) => string;
|
|
72
|
+
/**
|
|
73
|
+
* What the element a glyph effect wraps draws in one frame, and on what: the
|
|
74
|
+
* glyph half of `Drawn`.
|
|
75
|
+
*/
|
|
76
|
+
export interface DrawnGlyphs {
|
|
77
|
+
/** Every cell, in reading order; a line break is no cell. */
|
|
78
|
+
readonly cells: readonly GlyphCell[];
|
|
79
|
+
/**
|
|
80
|
+
* Whether the output draws ASCII alone (`RenderOptions.asciiOnly`). A glyph
|
|
81
|
+
* the effect chooses itself, rather than one the element drew, goes through
|
|
82
|
+
* `drawable` against it, as every glyph the library chooses does.
|
|
83
|
+
*/
|
|
84
|
+
readonly asciiOnly: boolean;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* For an element drawing `drawn`, the animation of what is done to its
|
|
88
|
+
* glyphs. Its `nextChange` is when the frame next changes, as an `Effect`'s is.
|
|
89
|
+
*/
|
|
90
|
+
export type GlyphEffect = (drawn: DrawnGlyphs) => Animation<GlyphFrame>;
|
|
91
|
+
export interface GlyphEffectedOptions {
|
|
92
|
+
/** Names the element for its seeds, as `EffectedOptions.key` does; under both wrappers, one key gives one seed a cell. */
|
|
93
|
+
readonly key: string;
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* A `GlyphEffected` at `t`, or an element through a glyph effect at a time an
|
|
97
|
+
* animation's `at` was handed: `renderable` with its cells' glyphs passed
|
|
98
|
+
* through `effect` at `t`, saying nothing of when that changes, as a
|
|
99
|
+
* `Recolored` is (`./effect.ts`). [LAW:one-type-per-behavior]
|
|
100
|
+
*/
|
|
101
|
+
export declare class Reglyphed implements Renderable, Measurable {
|
|
102
|
+
readonly renderable: Renderable;
|
|
103
|
+
readonly effect: GlyphEffect;
|
|
104
|
+
readonly t: number;
|
|
105
|
+
readonly key: string;
|
|
106
|
+
constructor(renderable: Renderable, effect: GlyphEffect, options: GlyphEffectedOptions & {
|
|
107
|
+
readonly t: number;
|
|
108
|
+
});
|
|
109
|
+
render(options: RenderOptions): Iterable<Segment>;
|
|
110
|
+
/** The frame the effect draws at `t`, and the hold it says that is in. */
|
|
111
|
+
moved(options: RenderOptions): Moved;
|
|
112
|
+
measure(options: RenderOptions): {
|
|
113
|
+
minimum: number;
|
|
114
|
+
maximum: number;
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* `renderable` under a glyph effect over time, an `Animation<Renderable>`
|
|
119
|
+
* as an `Effected` is (`./effect.ts`): its own answer is `t`, and placed,
|
|
120
|
+
* its cells carry the glyph effect's exact hold at the frame's time and the
|
|
121
|
+
* output's `asciiOnly`, under whatever the element already said.
|
|
122
|
+
*/
|
|
123
|
+
export declare class GlyphEffected implements Animation<Renderable> {
|
|
124
|
+
readonly renderable: Renderable;
|
|
125
|
+
readonly effect: GlyphEffect;
|
|
126
|
+
readonly key: string;
|
|
127
|
+
constructor(renderable: Renderable, effect: GlyphEffect, options: GlyphEffectedOptions);
|
|
128
|
+
/** The element through the glyph effect at `t`, unstamped. */
|
|
129
|
+
at(t: number): Reglyphed;
|
|
130
|
+
nextChange(t: number): number;
|
|
131
|
+
lastChange(t: number): number;
|
|
132
|
+
/** The element under the glyph effect with its motion taken out. */
|
|
133
|
+
reduced(): GlyphEffected;
|
|
134
|
+
/** Drawn at the frame's time, its cells stamped with the glyph effect's exact hold there. */
|
|
135
|
+
render(options: RenderOptions): Iterable<Segment>;
|
|
136
|
+
measure(options: RenderOptions): {
|
|
137
|
+
minimum: number;
|
|
138
|
+
maximum: number;
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* `text` with its glyphs passed through `effect`, before any render: the
|
|
143
|
+
* glyph half of a template fragment (`../template-bindings/animation-funcs.ts`),
|
|
144
|
+
* which is spliced into a line and drawn under a theme it does not know yet,
|
|
145
|
+
* so it cannot be rendered to cells first as `Reglyphed` renders its child.
|
|
146
|
+
* The cells are the text's own lines, at its own columns; the contract is
|
|
147
|
+
* the one `Reglyphed` is held to, through the same checks, over the text's
|
|
148
|
+
* own glyphs: a neighbour spliced beside it later, a combining mark leading
|
|
149
|
+
* the next fragment say, is outside what either check can see. The text keeps
|
|
150
|
+
* its every style and span, each moved to where its glyphs now sit, and a
|
|
151
|
+
* frame that changes nothing hands the text back as it was. What it says of
|
|
152
|
+
* when it changes is the effect's, unstamped: whoever draws it at a time
|
|
153
|
+
* stamps it (`textFrameAt`).
|
|
154
|
+
*/
|
|
155
|
+
export declare function reglyphText(text: RichText, effect: GlyphEffect, options: {
|
|
156
|
+
readonly key: string;
|
|
157
|
+
readonly asciiOnly: boolean;
|
|
158
|
+
}): Animation<RichText>;
|