@promptctl/rich-js 0.24.0 → 0.25.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.
Files changed (163) hide show
  1. package/README.md +7 -0
  2. package/THIRD-PARTY-NOTICES +29 -1
  3. package/dist/core/anchor.d.ts +5 -0
  4. package/dist/core/anchor.js +11 -4
  5. package/dist/core/animation.d.ts +243 -0
  6. package/dist/core/animation.js +375 -0
  7. package/dist/core/ansi.js +2 -2
  8. package/dist/core/box.d.ts +7 -7
  9. package/dist/core/cell-widths.d.ts +9 -0
  10. package/dist/core/cell-widths.js +140 -0
  11. package/dist/core/cells.d.ts +40 -24
  12. package/dist/core/cells.js +151 -66
  13. package/dist/core/clock.d.ts +2 -2
  14. package/dist/core/clock.js +6 -4
  15. package/dist/core/color.d.ts +27 -10
  16. package/dist/core/color.js +21 -29
  17. package/dist/core/console.d.ts +28 -17
  18. package/dist/core/console.js +48 -43
  19. package/dist/core/easing.d.ts +140 -10
  20. package/dist/core/easing.js +328 -50
  21. package/dist/core/emoji.d.ts +1 -1
  22. package/dist/core/emoji.js +1 -2
  23. package/dist/core/export-html.js +2 -1
  24. package/dist/core/export-lines.js +3 -3
  25. package/dist/core/highlighter.d.ts +9 -8
  26. package/dist/core/highlighter.js +3 -2
  27. package/dist/core/json.js +3 -2
  28. package/dist/core/markup.js +16 -12
  29. package/dist/core/measure.js +3 -3
  30. package/dist/core/memo.d.ts +11 -2
  31. package/dist/core/memo.js +16 -0
  32. package/dist/core/oklch.js +17 -6
  33. package/dist/core/osc8.d.ts +1 -1
  34. package/dist/core/osc8.js +4 -5
  35. package/dist/core/paint.d.ts +2 -1
  36. package/dist/core/paint.js +4 -3
  37. package/dist/core/pattern.d.ts +21 -0
  38. package/dist/core/pattern.js +21 -0
  39. package/dist/core/place.js +2 -1
  40. package/dist/core/pretty.js +11 -12
  41. package/dist/core/protocol.d.ts +136 -21
  42. package/dist/core/protocol.js +203 -16
  43. package/dist/core/render.d.ts +15 -2
  44. package/dist/core/render.js +27 -6
  45. package/dist/core/segment.d.ts +31 -6
  46. package/dist/core/segment.js +68 -53
  47. package/dist/core/spinnerData.d.ts +1 -1
  48. package/dist/core/state.d.ts +53 -0
  49. package/dist/core/state.js +82 -0
  50. package/dist/core/strip.d.ts +11 -13
  51. package/dist/core/strip.js +126 -113
  52. package/dist/core/style.d.ts +47 -14
  53. package/dist/core/style.js +74 -34
  54. package/dist/core/text.d.ts +5 -8
  55. package/dist/core/text.js +133 -133
  56. package/dist/core/timeline.d.ts +109 -0
  57. package/dist/core/timeline.js +180 -0
  58. package/dist/core/tween.d.ts +49 -0
  59. package/dist/core/tween.js +71 -0
  60. package/dist/core/view.d.ts +92 -0
  61. package/dist/core/view.js +83 -0
  62. package/dist/host/app.d.ts +49 -21
  63. package/dist/host/app.js +72 -38
  64. package/dist/host/input.js +3 -4
  65. package/dist/index.d.ts +30 -15
  66. package/dist/index.js +20 -6
  67. package/dist/node/traceback.js +4 -3
  68. package/dist/renderables/change.d.ts +42 -0
  69. package/dist/renderables/change.js +112 -0
  70. package/dist/renderables/columns.d.ts +1 -1
  71. package/dist/renderables/columns.js +3 -3
  72. package/dist/renderables/constrain.js +2 -1
  73. package/dist/renderables/effect.d.ts +155 -92
  74. package/dist/renderables/effect.js +203 -136
  75. package/dist/renderables/effects.d.ts +137 -24
  76. package/dist/renderables/effects.js +276 -113
  77. package/dist/renderables/embed.d.ts +1 -1
  78. package/dist/renderables/embed.js +18 -9
  79. package/dist/renderables/flexStrip.js +2 -1
  80. package/dist/renderables/frames.d.ts +45 -43
  81. package/dist/renderables/frames.js +57 -45
  82. package/dist/renderables/glyph-effect.d.ts +158 -0
  83. package/dist/renderables/glyph-effect.js +237 -0
  84. package/dist/renderables/glyph-effects.d.ts +147 -0
  85. package/dist/renderables/glyph-effects.js +283 -0
  86. package/dist/renderables/group.d.ts +1 -1
  87. package/dist/renderables/group.js +2 -2
  88. package/dist/renderables/html-entities.d.ts +8 -0
  89. package/dist/renderables/html-entities.js +386 -0
  90. package/dist/renderables/layout.d.ts +10 -9
  91. package/dist/renderables/layout.js +42 -35
  92. package/dist/renderables/lifecycle.d.ts +77 -0
  93. package/dist/renderables/lifecycle.js +132 -0
  94. package/dist/renderables/list-view.d.ts +2 -2
  95. package/dist/renderables/list-view.js +11 -8
  96. package/dist/renderables/live.d.ts +36 -21
  97. package/dist/renderables/live.js +89 -42
  98. package/dist/renderables/markdown-parse.d.ts +109 -0
  99. package/dist/renderables/markdown-parse.js +1427 -0
  100. package/dist/renderables/markdown-url.d.ts +19 -0
  101. package/dist/renderables/markdown-url.js +314 -0
  102. package/dist/renderables/markdown.d.ts +5 -7
  103. package/dist/renderables/markdown.js +356 -683
  104. package/dist/renderables/padding.d.ts +7 -20
  105. package/dist/renderables/padding.js +29 -50
  106. package/dist/renderables/panel.d.ts +30 -32
  107. package/dist/renderables/panel.js +65 -109
  108. package/dist/renderables/progress.d.ts +83 -32
  109. package/dist/renderables/progress.js +186 -90
  110. package/dist/renderables/progressBar.d.ts +22 -12
  111. package/dist/renderables/progressBar.js +33 -10
  112. package/dist/renderables/prompt.js +3 -2
  113. package/dist/renderables/python-space.d.ts +13 -0
  114. package/dist/renderables/python-space.js +25 -0
  115. package/dist/renderables/scroll.d.ts +50 -0
  116. package/dist/renderables/scroll.js +106 -0
  117. package/dist/renderables/spinner.d.ts +57 -24
  118. package/dist/renderables/spinner.js +101 -49
  119. package/dist/renderables/status.js +1 -1
  120. package/dist/renderables/syntax.d.ts +10 -9
  121. package/dist/renderables/syntax.js +5 -3
  122. package/dist/renderables/table.d.ts +48 -46
  123. package/dist/renderables/table.js +170 -208
  124. package/dist/renderables/traceback.d.ts +3 -3
  125. package/dist/renderables/traceback.js +12 -10
  126. package/dist/renderables/tree.d.ts +28 -25
  127. package/dist/renderables/tree.js +108 -58
  128. package/dist/renderables/viewport.d.ts +77 -38
  129. package/dist/renderables/viewport.js +156 -72
  130. package/dist/template-bindings/animation-funcs.d.ts +78 -9
  131. package/dist/template-bindings/animation-funcs.js +132 -14
  132. package/dist/template-bindings/index.d.ts +5 -5
  133. package/dist/template-bindings/index.js +7 -6
  134. package/dist/themes/ramp.d.ts +62 -4
  135. package/dist/themes/ramp.js +82 -4
  136. package/dist/themes/registry.js +5 -7
  137. package/dist/widgets/button.js +3 -2
  138. package/dist/widgets/checkbox.js +4 -3
  139. package/dist/widgets/dropdown.d.ts +3 -1
  140. package/dist/widgets/dropdown.js +20 -15
  141. package/dist/widgets/event-router.js +4 -2
  142. package/dist/widgets/focus-manager.d.ts +23 -14
  143. package/dist/widgets/focus-manager.js +34 -33
  144. package/dist/widgets/hit.d.ts +6 -0
  145. package/dist/widgets/hit.js +8 -1
  146. package/dist/widgets/index.d.ts +1 -1
  147. package/dist/widgets/observable.d.ts +23 -0
  148. package/dist/widgets/observable.js +43 -0
  149. package/dist/widgets/slider.d.ts +1 -1
  150. package/dist/widgets/slider.js +12 -3
  151. package/dist/widgets/static-item.d.ts +1 -1
  152. package/dist/widgets/static-item.js +6 -7
  153. package/dist/widgets/text-input.d.ts +53 -47
  154. package/dist/widgets/text-input.js +456 -399
  155. package/dist/widgets/themed-widget.js +2 -1
  156. package/dist/widgets/toggle.js +4 -3
  157. package/dist/widgets/types.d.ts +10 -4
  158. package/dist/widgets/types.js +8 -2
  159. package/dist/widgets/widget-app.d.ts +32 -6
  160. package/dist/widgets/widget-app.js +74 -27
  161. package/dist/widgets/widget-base.d.ts +2 -2
  162. package/dist/widgets/widget-base.js +29 -21
  163. package/package.json +9 -5
@@ -1,30 +1,42 @@
1
1
  /**
2
- * Effected — a renderable whose finished cells' colours pass through an
3
- * effect at a moment `t`.
2
+ * Effected — a renderable whose finished cells' looks — colours and text
3
+ * attributes — pass through an effect at a moment `t`.
4
4
  *
5
- * An effect is one pure function in two stages: a time and what the element
6
- * draws in that frame in, a function of the frame out; and into that, a
7
- * cell's colours and where the cell is, the cell's new colours out. Whatever
8
- * holds for the whole frame is worked out in the first stage, once, and every
9
- * cell of the frame is handed to the second, but for those a wrapper keeps
10
- * back: `confined` hands over only the cells its owners drew, so a second
11
- * stage never counts on seeing them all. Shimmer, pulse, fade and
12
- * dissolve are all this one shape, differing by what the function does with
13
- * its inputs [LAW:one-type-per-behavior]; two effects stack by nesting one
5
+ * An effect is, for what an element draws in a frame, an `Animation`
6
+ * (`core/animation.ts`) of what is done to its cells: its value at `t` is a
7
+ * function from a cell's look and where the cell is to the cell's new look
8
+ * (`EffectFrame`), and it says when that next changes as every
9
+ * animation does. Whatever holds for the whole frame is worked out once, in
10
+ * the effect and its `at(t)`, and every cell of the frame is handed to the
11
+ * function `at(t)` returns, but for those a wrapper keeps back: `confined`
12
+ * hands over only the cells its owners drew, so an effect never counts on
13
+ * seeing them all. Shimmer, pulse, fade, dissolve and a blinking attribute
14
+ * are all this one shape, differing by what the function does with its
15
+ * inputs [LAW:one-type-per-behavior]; two effects stack by nesting one
14
16
  * wrapper in another, which is the same as calling one after the other but
15
17
  * for what the outer one measures: the inner one's output.
16
18
  *
17
- * What the element draws (`Drawn`) — the cells the second stage will be
18
- * handed, and the colours of its words — is measured here, in the render, off
19
- * the same reading of each segment its cells are drawn from, and handed to the
20
- * effect's first stage, once a frame. It is what an effect keeping words legible is
21
- * settled against (`onColors`, `./effects.ts`), so no caller derives it a
22
- * second time from a render of its own.
19
+ * A cell's look is one value, its colours and its attributes together
20
+ * (`CellLook`), rather than an attribute stage beside the colour one, so
21
+ * everything that takes an `Effect` — `confined`, `onBeat`,
22
+ * `Animation.all`, nesting over a glyph effect — takes one that moves
23
+ * attributes with no second copy of itself. `reverse` is the one attribute
24
+ * a look leaves out (`CellAttributes`): it decides which of a style's slots
25
+ * a colour on screen is in, and a swap of the two is already a colour move.
23
26
  *
24
- * [LAW:no-ambient-temporal-coupling] `t` is a constructor argument, not a
25
- * clock read. Whoever draws frames builds the view for each frame's `t`, so
26
- * the same `t` always draws the same bytes, at 30 frames a second or one
27
- * every two seconds.
27
+ * What the element draws (`Drawn`) — the cells the effect will be handed,
28
+ * and the colours of its words — is measured here, in the render, off the
29
+ * same reading of each segment its cells are drawn from, and handed to the
30
+ * effect once a frame. It is what an effect keeping words legible is settled
31
+ * against (`onColors`, `./effects.ts`), so no caller derives it a second time
32
+ * from a render of its own.
33
+ *
34
+ * An `Effected` is the element under its effect over time: an
35
+ * `Animation<Renderable>`, placed wherever a renderable goes and drawn at
36
+ * the time of the frame it is drawn in. Its value at `t` is the element
37
+ * through the effect at `t` (`Recolored`). [LAW:no-ambient-temporal-coupling]
38
+ * The time is the frame's, never a clock read, so the same time always draws
39
+ * the same bytes, at 30 frames a second or one every two seconds.
28
40
  *
29
41
  * What an effect may not do is the contract this module holds:
30
42
  *
@@ -34,25 +46,30 @@
34
46
  * segment's link and meta and carries its anchor shifted to the run's first
35
47
  * cell (`Style.shiftedBy`), so hit testing still finds the owner.
36
48
  * - A cell whose colours come back unchanged keeps its original `ColorSpec`,
37
- * and a segment whose every cell is unchanged is yielded with its look as
38
- * it was, so the identity effect is byte-identical; what it gains is when
39
- * the frame next changes (`Style.nextChange`), which writes no byte.
49
+ * one whose attributes come back as its style set them keeps them, and a
50
+ * segment whose every cell is unchanged is yielded with its look as
51
+ * it was, so the identity effect is byte-identical; what an `Effected` gains is when
52
+ * the frame next changes (`Style.hold`), which writes no byte.
40
53
  * Neighbouring cells the output depth
41
54
  * writes alike stay one segment: a segment is cut only where the written
42
- * colours change, so two colours that land on one index are one run.
55
+ * colours or the attributes change, so two colours that land on one index
56
+ * are one run.
43
57
  * - New colours are built with `ColorSpec.fromRgba`, never parsed from a
44
58
  * string, so no frame adds an entry to a parse cache.
45
- * - With no colour output (`colorSystem: null`) there is nothing for an
46
- * effect to change, and the child's segments pass through untouched.
59
+ * - With no colour output (`colorSystem: null`) no style is written at all,
60
+ * attributes included, so there is nothing for an effect to change, and
61
+ * the child's segments pass through untouched.
47
62
  *
48
63
  * Positions are the child's own: row and column count from the top-left of
49
64
  * what the child drew, so a sweep crosses the element, not the screen.
50
65
  */
51
66
  import { type Anchor } from "../core/anchor.js";
67
+ import { Animation } from "../core/animation.js";
68
+ import type { Hold } from "../core/style.js";
52
69
  import { ColorDepth, type ColorRgba, type TerminalTheme } from "../core/color.js";
53
- import type { Beat } from "../core/easing.js";
54
70
  import type { Measurable, Renderable, RenderOptions } from "../core/protocol.js";
55
71
  import { Segment } from "../core/segment.js";
72
+ import { type Attributes } from "../core/style.js";
56
73
  /**
57
74
  * A cell's foreground and background as they appear on screen — the glyph's
58
75
  * colour and the colour behind it — which are the colours an effect moves.
@@ -62,6 +79,16 @@ export interface CellColors {
62
79
  readonly fg: ColorRgba;
63
80
  readonly bg: ColorRgba;
64
81
  }
82
+ /**
83
+ * The text attributes an effect moves: every one a style sets but
84
+ * `reverse`, each on, off or unset as the cell's style has it. An unset
85
+ * one lets a style laid beneath show through, as it does undrawn.
86
+ */
87
+ export type CellAttributes = Omit<Attributes, "reverse">;
88
+ /** What an effect moves in a cell: its colours as the screen shows them, and its attributes. */
89
+ export interface CellLook extends CellColors {
90
+ readonly attributes: CellAttributes;
91
+ }
65
92
  /**
66
93
  * Where a cell is in the output of the renderable an effect wraps, its seed:
67
94
  * a number in [0, 1) that is the same for that cell on every frame, for an
@@ -119,7 +146,7 @@ export interface Drawn {
119
146
  /**
120
147
  * Every cell the element shows something in this frame — a glyph, a
121
148
  * ground that is not the terminal's, or a line its style draws — where it
122
- * sits and who drew it, listed before the second stage is handed any: what
149
+ * sits and who drew it, listed before the effect is handed any: what
123
150
  * an effect spread over the element — a transition, which has its last cell
124
151
  * settle as it ends — is spread over. A blank cell on the terminal's ground
125
152
  * that draws no line is handed but not listed, since nothing in it shows.
@@ -138,45 +165,24 @@ export interface Drawn {
138
165
  /** The terminal the frame is drawn on. */
139
166
  readonly theme: TerminalTheme;
140
167
  }
168
+ /** What an effect does to the cells of one frame: each cell's look and where it is in, its look out. Return `look` to leave a cell be. */
169
+ export type EffectFrame = (look: CellLook, cell: EffectCell) => CellLook;
141
170
  /**
142
- * The frame at time `t`, in seconds, whose element draws `drawn`: each cell's
143
- * colours in that frame. Return `colors` to leave a cell be.
144
- * [LAW:types-are-the-program] Per-frame work is the outer stage, so it runs
145
- * once a frame by the shape of the call, never by a cache asking whether this
146
- * cell's frame is the last one's.
171
+ * For an element drawing `drawn`, the animation of what is done to its cells.
172
+ * [LAW:types-are-the-program] Per-frame work is `at(t)`, so it runs once a
173
+ * frame by the shape of the call, never by a cache asking whether this cell's
174
+ * frame is the last one's.
147
175
  *
148
- * An effect that knows when its frame next changes says so in `nextChange`,
149
- * asked with the same `t` and `drawn` its first stage is: a stepped one its
150
- * next step's start, a transition `t` until it is done and `Infinity` after,
151
- * a loop that holds every cell still at the frame's depth `Infinity` there.
152
- * [LAW:types-are-the-program] The answer is a fact about the frame, so it is
153
- * asked with everything the frame is drawn from; an answer asked with `t`
154
- * alone could not say that a frame is still because of its depth. A plain
155
- * function is an effect that moves every frame, and answers `t`
156
- * (`nextChangeOf`): the one true answer for a frame nothing has promised to
157
- * hold, so a loop needs no second shape.
158
- */
159
- export interface Effect {
160
- (t: number, drawn: Drawn): (colors: CellColors, cell: EffectCell) => CellColors;
161
- /** When the frame drawn at `t` of `drawn` next changes, in seconds on `t`'s timeline, never before `t`; absent, every frame. */
162
- readonly nextChange?: (t: number, drawn: Drawn) => number;
163
- }
164
- /**
165
- * When `effect`'s frame at `t` of `drawn` next changes: what it says, or `t`
166
- * for an effect that says nothing. [LAW:single-enforcer] The one reading of
167
- * an absent `nextChange`, so no caller holds its own default.
168
- */
169
- export declare function nextChangeOf(effect: Effect, t: number, drawn: Drawn): number;
170
- /**
171
- * An effect drawing as `effect` does, with `nextChange` as its answer to when
172
- * its frame next changes, in place of whatever `effect` answered; `effect`
173
- * itself is left as it was. A composer whose answer depends on the inner
174
- * effect's reads it with `nextChangeOf`, as `onBeat` and `confined` do.
176
+ * Its `nextChange` is when the frame next changes: a stepped effect its next
177
+ * step's start, a transition `t` until it is done and `Infinity` after, a
178
+ * loop that holds every cell still at the frame's depth `Infinity` there, and
179
+ * a loop that moves `t` (`Animation.continuous`). [LAW:types-are-the-program]
180
+ * The answer is a fact about the frame, so the animation is made from
181
+ * everything the frame is drawn from; one made from `t` alone could not say
182
+ * that a frame is still because of its depth.
175
183
  */
176
- export declare function withNextChange(effect: Effect, nextChange: (t: number, drawn: Drawn) => number): Effect;
184
+ export type Effect = (drawn: Drawn) => Animation<EffectFrame>;
177
185
  export interface EffectedOptions {
178
- /** The moment to draw, in seconds. */
179
- readonly t: number;
180
186
  /**
181
187
  * Names the element for its seeds, so two elements showing the same text do
182
188
  * not twinkle in lockstep. The same key gives the same seeds on every frame.
@@ -189,20 +195,71 @@ export interface EffectedOptions {
189
195
  */
190
196
  readonly theme: TerminalTheme;
191
197
  }
192
- export declare class Effected implements Renderable, Measurable {
198
+ /** A frame an effect drew at a moment, and the hold the effect says it is in there. */
199
+ export interface Moved {
200
+ readonly segments: Iterable<Segment>;
201
+ readonly hold: Hold;
202
+ }
203
+ /**
204
+ * An `Effected` at `t`, or an element through an effect at a time an
205
+ * animation's `at` was handed — a lifecycle's time since it entered: `renderable`
206
+ * with its cells' looks passed through `effect` at `t`, saying nothing of
207
+ * when that changes, since whatever placed the animation stamps its hold.
208
+ * [LAW:one-type-per-behavior]
209
+ */
210
+ export declare class Recolored implements Renderable, Measurable {
193
211
  readonly renderable: Renderable;
194
212
  readonly effect: Effect;
195
213
  readonly t: number;
196
214
  readonly key: string;
197
215
  readonly theme: TerminalTheme;
198
- constructor(renderable: Renderable, effect: Effect, options: EffectedOptions);
216
+ constructor(renderable: Renderable, effect: Effect, options: EffectedOptions & {
217
+ readonly t: number;
218
+ });
199
219
  render(options: RenderOptions): Iterable<Segment>;
200
- private _moved;
220
+ /** The frame the effect draws at `t`, and the hold it says that is in. */
221
+ moved(options: RenderOptions): Moved;
201
222
  private _recolored;
202
223
  measure(options: RenderOptions): {
203
224
  minimum: number;
204
225
  maximum: number;
205
226
  };
227
+ /**
228
+ * The specs that draw a cell's slot colours `to` where the segment drew
229
+ * `from` with `wire`: each moved slot in the spec `movedSpecs` writes it
230
+ * in, the rest as `wire` wrote them.
231
+ */
232
+ private respec;
233
+ }
234
+ /**
235
+ * `renderable` under `effect` over time: an `Animation<Renderable>` whose
236
+ * value at `t` is the element through the effect at `t`, placed wherever a
237
+ * renderable goes. Its own answer to when it changes is `t`, at every time:
238
+ * an `Effect` is made from what the element draws, so with nothing drawn
239
+ * nothing can say more — early, never false. Placed, it says exactly: its
240
+ * cells carry the effect's own hold at the frame's time and the output's
241
+ * depth (`stampFrame`), under whatever the element already said, so at a
242
+ * depth that shows no motion a loop says it never changes there and the
243
+ * host sleeps.
244
+ */
245
+ export declare class Effected implements Animation<Renderable> {
246
+ readonly renderable: Renderable;
247
+ readonly effect: Effect;
248
+ readonly key: string;
249
+ readonly theme: TerminalTheme;
250
+ constructor(renderable: Renderable, effect: Effect, options: EffectedOptions);
251
+ /** The element through the effect at `t`, unstamped. */
252
+ at(t: number): Recolored;
253
+ nextChange(t: number): number;
254
+ lastChange(t: number): number;
255
+ /** The element under the effect with its motion taken out. */
256
+ reduced(): Effected;
257
+ /** Drawn at the frame's time, its cells stamped with the effect's exact hold there. */
258
+ render(options: RenderOptions): Iterable<Segment>;
259
+ measure(options: RenderOptions): {
260
+ minimum: number;
261
+ maximum: number;
262
+ };
206
263
  /**
207
264
  * The colours the screen shows for `pair` once it is drawn moved to `to`,
208
265
  * both as the screen shows them, at `depth` on `theme`: what an effect
@@ -211,34 +268,34 @@ export declare class Effected implements Renderable, Measurable {
211
268
  * moved slot is written with.
212
269
  */
213
270
  static shows(pair: Pair, to: CellColors, depth: ColorDepth, theme: TerminalTheme): CellColors;
214
- /**
215
- * The specs that draw a cell's slot colours `to` where the segment drew
216
- * `from` with `wire`: each moved slot in the spec `movedSpecs` writes it
217
- * in, the rest as `wire` wrote them.
218
- */
219
- private respec;
220
- /** A cell's seed: FNV-1a of the key and the position, scaled into [0, 1). */
221
- private seed;
222
271
  }
223
272
  /**
224
- * `effect` sampled and held on `beat`: drawn at the moment the hold in
225
- * progress began (`Beat.start`), so within a hold every frame is the frame
226
- * at its start, and at each hold's start it moves on. A continuous effect
227
- * given a short curve becomes one that steps — a `wheel` turning a sixth of
228
- * a turn once a second — and at one redraw a second a hold shorter than a
229
- * second is skipped, as frames are. [LAW:no-ambient-temporal-coupling] The
230
- * held time is a function of `t`, so the same `t` draws the same bytes at
231
- * any rate. The frame next changes at a hold's start, and only one the
232
- * sampled effect has moved by: the first hold start at or after what it
233
- * answers for the frame held now (`Beat.end`). An effect that moves every
234
- * frame makes the beat's own answer, the end of this hold; one that is done
235
- * and says never leaves the beat saying never too, since the hold after this
236
- * one would draw the same frame. The answer is read off what the effect
237
- * says, never off a comparison of frames: an effect that steps and is back
238
- * on the same colour by the next hold still turns the beat there, an early
239
- * answer the contract allows.
273
+ * A cell's seed: FNV-1a of the element's key and the cell's position, scaled
274
+ * into [0, 1). [LAW:one-source-of-truth] One rule for a colour effect's seeds
275
+ * and a glyph effect's, so one element under both twinkles from one seed.
240
276
  */
241
- export declare function onBeat(effect: Effect, beat: Beat): Effect;
277
+ export declare function cellSeed(key: string, row: number, col: number): number;
278
+ /** A glyph of a segment, placed where its cell is drawn — or none for a newline, which is no cell. */
279
+ export interface WalkedGlyph {
280
+ readonly glyph: string;
281
+ readonly cell: Placed | undefined;
282
+ }
283
+ /**
284
+ * Each glyph of each of `segments`, where its cell sits: rows and columns
285
+ * from the top-left of the output, a wide glyph one cell at its first
286
+ * column, and its anchor shifted to that column as `Style.shiftedBy` shifts
287
+ * a run's. A control segment draws nothing and has none.
288
+ * [LAW:one-source-of-truth] The one walk: what `Drawn.cells` lists, what the
289
+ * render hands a colour effect, and what a glyph effect (`./glyph-effect.ts`)
290
+ * is handed are all read off it.
291
+ */
292
+ export declare function walkGlyphs(segments: readonly Segment[]): (readonly WalkedGlyph[])[];
293
+ /**
294
+ * Whether `text` draws ink: anything but blanks. [LAW:one-source-of-truth]
295
+ * The one test, so the words a colour effect lights are the words a glyph
296
+ * effect (`./glyph-effects.ts`) scrambles and its particles pass behind.
297
+ */
298
+ export declare function inked(text: string): boolean;
242
299
  /**
243
300
  * `effect` on the colours any of `owners` drew, itself or through an owner
244
301
  * nested in its output, and every other colour left as it is: one item of a
@@ -257,3 +314,9 @@ export declare function confined(effect: Effect, ...owners: readonly object[]):
257
314
  * output under an effect to read the contrast its words are left at.
258
315
  */
259
316
  export declare function drawnOf(segments: Iterable<Segment>, depth: ColorDepth, theme: TerminalTheme): Drawn;
317
+ /**
318
+ * The attributes a look carries, read off anything that sets them — a
319
+ * `Style`, or a look a frame returned with more on it than `CellAttributes`
320
+ * names. [LAW:one-source-of-truth] The one place `reverse` is left out.
321
+ */
322
+ export declare function cellAttributes(of: CellAttributes): CellAttributes;