@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
@@ -0,0 +1,375 @@
1
+ /**
2
+ * Animation — a value for a time, and when it next changes: the one type
3
+ * anything in rich-js that changes with time is an instance of.
4
+ *
5
+ * `at(t)` is the value at `t` seconds. `nextChange(t)` is the first moment,
6
+ * on `t`'s own timeline, at which the value may stop being `at(t)`: never
7
+ * before `t`. A later time says the value is held until then, `Infinity`
8
+ * that it never changes again, and `t` itself that it is moving at `t` — it
9
+ * changes every frame, however close together they are drawn. An early
10
+ * answer costs a host a frame that draws what the last one did; a late one
11
+ * skips a change. So an animation that cannot say answers `t`, as
12
+ * `continuous` does. A value drawn as cells carries this answer on every
13
+ * cell (`Style.hold`, both ends of the hold below), so a host holding
14
+ * the composed frame reads it there (`Segment.nextChange`); a value that is
15
+ * not drawn — a number, a colour — has `nextChange` as its only way to say
16
+ * when to look again.
17
+ *
18
+ * `lastChange(t)` is the other end of the same hold: the last moment, never
19
+ * after `t`, at which the value may have become `at(t)` — `-Infinity` if it
20
+ * always was, `t` while it moves. Together they bound the hold, `[lastChange(t),
21
+ * nextChange(t))`, and the answer may be narrower than the truth and never
22
+ * wider. It is what a host running the animation backwards reads
23
+ * (`./timeline.ts`): run down the timeline, the value next changes where it
24
+ * began. An animation that cannot say answers `t` here too.
25
+ *
26
+ * `reduced()` is the same animation with its motion taken out: what it shows,
27
+ * and when it starts and stops showing it, kept; every moment between two
28
+ * values skipped. A loop holds its first value, a one-shot cuts to its end
29
+ * when it starts, a transition to its new state, a stagger has everyone arrived, and an element is
30
+ * there from when it entered until it is told to leave. Terminals have no
31
+ * `prefers-reduced-motion`, so a host is told (`reducedMotion`,
32
+ * `./protocol.ts`), and under it draws every animation's reduced form, which
33
+ * wakes it only where content changes. It is the one place the preference is
34
+ * honoured for every kind at once, because every kind is this type, and each
35
+ * combinator says its reduced form so a built animation answers it too.
36
+ * [LAW:types-are-the-program] It is an animation and not a value because
37
+ * which content shows is a fact about time that motion is not: a value with
38
+ * no time could only show a scheduled exit as already gone.
39
+ *
40
+ * The instances already in the tree: a `Beat` is an animation of which hold
41
+ * is in progress (`./easing.ts`), a `FrameSequence` of the frame shown and a
42
+ * `Spinner` of the spinner drawn (`../renderables/`), and an `Effect` is, for
43
+ * what an element draws in a frame, an animation of how its cells' colours
44
+ * move (`../renderables/effect.ts`). Every kind of motion is one more.
45
+ *
46
+ * An animation of renderables is a renderable — its face, `placedRender`:
47
+ * placed as the child of any container — a `Panel`, a `Table` cell, a
48
+ * `Group`, a container a user wrote — it draws at the time of the frame it
49
+ * is drawn in (`RenderOptions.frame`; 0, its own start, when printed) and
50
+ * stamps its cells with its hold there, under whatever its value's cells
51
+ * already say, so a frame's hold is the intersection of its cells' holds.
52
+ * [LAW:composability] No time is threaded through the code that places it,
53
+ * and no container knows animations exist. An animation placed inside
54
+ * another's value draws at the frame's time too: a combinator remaps the
55
+ * time it hands its parts, never a value's contents, so content that should
56
+ * follow a part's clock is composed into the part (`map`, `all`) and the
57
+ * result placed. [LAW:one-source-of-truth]
58
+ *
59
+ * [LAW:no-ambient-temporal-coupling] Pure: `t` is an argument and never a
60
+ * clock read (`./clock.ts`), the same `t` gives the same value, nothing is
61
+ * kept between calls, and a call costs the same at `t = 0` and `t = 10⁶`, so
62
+ * a host sampling once a second and one sampling sixty times see the same
63
+ * value at every `t` they share.
64
+ *
65
+ * [LAW:one-type-per-behavior] The combinators here are the ones every kind
66
+ * of motion is built from — a constant, a value moving every moment, a map
67
+ * over the value, several at once, one animation after another, and one
68
+ * played again every period — and each says how
69
+ * `nextChange` composes, so an animation built from them answers it without
70
+ * its author doing anything.
71
+ *
72
+ * Tier 5 of `src/core/`: `./easing.ts`, `./measure.ts`, `./protocol.ts`,
73
+ * `./segment.ts` and `./style.ts`, nothing else. [LAW:one-way-deps]
74
+ */
75
+ import { beat, firstReaching, passAt, positiveSeconds } from "./easing.js";
76
+ import { Measurement } from "./measure.js";
77
+ import { isRenderable, render } from "./protocol.js";
78
+ import { Segment } from "./segment.js";
79
+ import { Style } from "./style.js";
80
+ /**
81
+ * What a frame drawn at `t` shows of `animation` under `motion`, and when
82
+ * that changes: the animation's, or under reduced motion its reduced form's
83
+ * (`reduced`). [LAW:single-enforcer] The one place the preference is read:
84
+ * every placed animation (`placedRender`), every effect, a spinner and
85
+ * the template functions choose here, so a host told once
86
+ * reduces every one.
87
+ */
88
+ export function shownAt(animation, t, motion) {
89
+ const reduced = motion.reducedMotion === true;
90
+ const drawn = reduced ? animation.reduced() : animation;
91
+ return { value: drawn.at(t), nextChange: drawn.nextChange(t), drawn, reduced };
92
+ }
93
+ /** The hold `shown`, drawn at `t`, is in: its animation's two answers there. */
94
+ export function holdOf(shown, t) {
95
+ return { lastChange: shown.drawn.lastChange(t), nextChange: shown.nextChange };
96
+ }
97
+ /** The style saying a cell is in `hold`. */
98
+ export function stamp(hold) {
99
+ return new Style({ hold });
100
+ }
101
+ /**
102
+ * `segments`, every one carrying `hold` under whatever it already said: the
103
+ * later `lastChange` and the sooner `nextChange` win (`Style.add`), so a
104
+ * frame's hold is the intersection of its cells', narrower than the truth
105
+ * and never wider. [LAW:single-enforcer] The one way a time is put on drawn
106
+ * cells, by whatever draws for a time it knows.
107
+ */
108
+ export function stampFrame(segments, hold) {
109
+ return Segment.applyStyle(segments, stamp(hold));
110
+ }
111
+ /**
112
+ * The moment a frame drawn under `options` is drawn for: the frame's time,
113
+ * which the host writes once a frame (`RenderOptions.frame`), or with no
114
+ * frame — a `print` — 0, the start of an animation's own clock, the one
115
+ * moment it can name without reading one. [LAW:one-source-of-truth] Nothing
116
+ * else hands a placed animation its time, so an animation inside another's
117
+ * value draws at the frame's time too, never at a time a combinator mapped.
118
+ */
119
+ export function frameTimeOf(options) {
120
+ return options.frame?.time ?? 0;
121
+ }
122
+ /** `value` as what an animation's face draws. [LAW:no-silent-failure] An animation of numbers made through `Animation.of` has a face at runtime and nothing to draw. */
123
+ function drawable(value) {
124
+ if (!isRenderable(value))
125
+ throw new TypeError("an Animation is drawn only when its values are renderables; place what it maps to (Animation.map)");
126
+ return value;
127
+ }
128
+ /**
129
+ * An animation's face, `render`: drawn at the time of the frame it is drawn
130
+ * in (`frameTimeOf`), the value `shownAt` picks, every segment stamped with
131
+ * its hold there under whatever its own cells say, and the hold told to the
132
+ * frame (`RenderOptions.onHold`), because a frame of no cells — an element
133
+ * not yet entered — may have cells later, and must say when without taking a
134
+ * row to say it in. A container — the library's or a user's — that draws its
135
+ * children through `render` draws an animation among them with no word about
136
+ * time: the hold goes back the way the time came in. [LAW:composability]
137
+ */
138
+ export function* placedRender(animation, options) {
139
+ const t = frameTimeOf(options);
140
+ const shown = shownAt(animation, t, options);
141
+ const value = drawable(shown.value);
142
+ const hold = holdOf(shown, t);
143
+ options.onHold?.(hold);
144
+ yield* stampFrame(render(value, options), hold);
145
+ }
146
+ /**
147
+ * An animation's face, `measure`: what it shows at the frame's time, measured,
148
+ * and its hold there told (`RenderOptions.onHold`), because a container lays
149
+ * out from the measurement and must lay out again when it changes.
150
+ */
151
+ export function placedMeasure(animation, options) {
152
+ const t = frameTimeOf(options);
153
+ const shown = shownAt(animation, t, options);
154
+ options.onHold?.(holdOf(shown, t));
155
+ return Measurement.get(options, drawable(shown.value));
156
+ }
157
+ /**
158
+ * Every member of `source`, its own and its class's, as own properties of a
159
+ * new object: a method bound to `source`, a getter read off it live, a field
160
+ * as it is. So a class instance keeps its methods, and a spread of the copy
161
+ * is whole.
162
+ */
163
+ function membersOf(source) {
164
+ const copy = {};
165
+ for (let layer = source; layer !== null && layer !== Object.prototype; layer = Object.getPrototypeOf(layer)) {
166
+ for (const key of Reflect.ownKeys(layer)) {
167
+ if (key === "constructor" || Object.hasOwn(copy, key))
168
+ continue;
169
+ const member = Object.getOwnPropertyDescriptor(layer, key);
170
+ Object.defineProperty(copy, key, member.get !== undefined
171
+ ? { enumerable: true, configurable: true, get: () => Reflect.get(source, key) }
172
+ : { enumerable: true, configurable: true, writable: true, value: typeof member.value === "function" ? member.value.bind(source) : member.value });
173
+ }
174
+ }
175
+ return copy;
176
+ }
177
+ export const Animation = {
178
+ /**
179
+ * `timed` as an animation: every member it carries kept (`membersOf`),
180
+ * with the face its values call for — `render` and `measure`,
181
+ * drawing it at the frame's time. Every animation made from a literal is
182
+ * made here, the library's and a user's alike. [LAW:single-enforcer] The
183
+ * one cast in the type: a literal's `T` is not known at runtime, so every
184
+ * animation made here has the face, and one whose values are not
185
+ * renderables throws when it is drawn.
186
+ */
187
+ of(timed) {
188
+ const faced = Object.assign(membersOf(timed), {
189
+ render: (options) => placedRender(faced, options),
190
+ measure: (options) => placedMeasure(faced, options),
191
+ });
192
+ return faced;
193
+ },
194
+ /** `value` at every time, never changing. */
195
+ constant(value) {
196
+ const still = Animation.of({ at: () => value, nextChange: () => Number.POSITIVE_INFINITY, lastChange: () => Number.NEGATIVE_INFINITY, reduced: () => still });
197
+ return still;
198
+ },
199
+ /**
200
+ * `before` until 0, then `after`: an instant change at 0 — a cut, what a
201
+ * one-shot is with its motion taken out, its start kept and its end at once.
202
+ */
203
+ cut(before, after) {
204
+ const cut = Animation.of({
205
+ at: (t) => (t < 0 ? before : after),
206
+ nextChange: (t) => (t < 0 ? 0 : Number.POSITIVE_INFINITY),
207
+ lastChange: (t) => (t < 0 ? Number.NEGATIVE_INFINITY : 0),
208
+ reduced: () => cut,
209
+ });
210
+ return cut;
211
+ },
212
+ /**
213
+ * The value `at` gives, taken to move at every moment: what an animation
214
+ * that cannot say when it holds still is, so a host draws it every frame.
215
+ * Reduced, it holds its first value, as a loop does; a one-shot built on
216
+ * it says its own end (`transition`, `../renderables/effects.ts`).
217
+ */
218
+ continuous(at) {
219
+ return Animation.of({ at, nextChange: (t) => t, lastChange: (t) => t, reduced: () => Animation.constant(at(0)) });
220
+ },
221
+ /**
222
+ * The time itself, in seconds, moving at every moment: what a clock, a
223
+ * counter or anything else that reports the time is mapped from. It is
224
+ * information and not motion, so reduced it is itself, and a clock shown
225
+ * to a reader who wants no motion still keeps the time; motion computed
226
+ * from the time is `continuous`, which reduced holds still.
227
+ * [LAW:types-are-the-program]
228
+ */
229
+ time() {
230
+ const time = Animation.of({ at: (t) => t, nextChange: (t) => t, lastChange: (t) => t, reduced: () => time });
231
+ return time;
232
+ },
233
+ /**
234
+ * `animation`'s value through `f`, changing when it does. Two values `f`
235
+ * maps alike make an early answer, which the contract allows.
236
+ */
237
+ map(animation, f) {
238
+ return Animation.of({
239
+ at: (t) => f(animation.at(t)),
240
+ nextChange: (t) => animation.nextChange(t),
241
+ lastChange: (t) => animation.lastChange(t),
242
+ reduced: () => Animation.map(animation.reduced(), f),
243
+ });
244
+ },
245
+ /**
246
+ * Every one of `animations` at once, their values in order, changing when
247
+ * the soonest of them does — so a stack of effects drawn together holds
248
+ * still exactly while each of them does, and reduced each reduced — a
249
+ * stagger with every child arrived. None never changes.
250
+ */
251
+ all(animations) {
252
+ return Animation.of({
253
+ // [LAW:types-are-the-program] Each value at its own place in the tuple,
254
+ // which `map` cannot say of its array.
255
+ at: (t) => animations.map((animation) => animation.at(t)),
256
+ // A fold, not a spread: a stagger over a table's rows is a list as long
257
+ // as the table, past what an engine takes as arguments.
258
+ nextChange: (t) => animations.reduce((soonest, animation) => Math.min(soonest, animation.nextChange(t)), Number.POSITIVE_INFINITY),
259
+ lastChange: (t) => animations.reduce((latest, animation) => Math.max(latest, animation.lastChange(t)), Number.NEGATIVE_INFINITY),
260
+ reduced: () => Animation.all(animations.map((animation) => animation.reduced())),
261
+ });
262
+ },
263
+ /**
264
+ * `animation` sampled once a hold of `beat`: within a hold, its value at
265
+ * the hold's start, and at each hold's start it moves on. It changes at the
266
+ * first hold's start the sampled animation has moved by: the end of this
267
+ * hold for one that moves every moment, the hold its next change falls in
268
+ * for one that holds longer, and never for one that never changes again.
269
+ * The answer is read off what the animation says, never a comparison of
270
+ * values, so one that is back on the same value by the next hold still
271
+ * turns the beat there, an early answer the contract allows.
272
+ * [LAW:one-source-of-truth] The one stepping rule, for an effect's frames
273
+ * and a transition's schedule alike.
274
+ */
275
+ onBeat(animation, beat) {
276
+ return Animation.of({
277
+ at: (t) => animation.at(beat.lastChange(t)),
278
+ nextChange(t) {
279
+ const moved = animation.nextChange(beat.lastChange(t));
280
+ if (moved === Number.POSITIVE_INFINITY)
281
+ return moved;
282
+ const end = beat.nextChange(t);
283
+ // The hold boundaries after `t` are `end`, then each hold's end in turn;
284
+ // the value turns at the first one the animation has moved by.
285
+ return moved <= end ? end : beat.lastChange(moved) === moved ? moved : beat.nextChange(moved);
286
+ },
287
+ // The value held now began at this hold's start at the latest: an early
288
+ // answer where the animation had not moved by it, which the contract allows.
289
+ lastChange: (t) => beat.lastChange(t),
290
+ // Reduced, nothing moves between beats, so there is nothing to sample on them.
291
+ reduced: () => animation.reduced(),
292
+ });
293
+ },
294
+ /**
295
+ * `first` until `seconds`, then `then`, handed the time since it began —
296
+ * each part on its own clock from 0, as every effect is. Before the switch
297
+ * the value next changes when `first`'s does or at the switch, whichever is
298
+ * sooner; after it, when `then`'s does, carried back onto this timeline.
299
+ * Reduced, each part is reduced and the switch kept, so what either shows
300
+ * shows on time; a one-shot that is the motion into what follows says its
301
+ * own end (`transition`, `../renderables/effects.ts`).
302
+ */
303
+ sequence(first, seconds, then) {
304
+ positiveSeconds("Animation.sequence seconds", seconds);
305
+ // `then`'s moment `local`, on its own clock, carried back onto this
306
+ // timeline: the first moment whose time since the switch reaches
307
+ // `local`, which the sum `local + seconds` can round to either side of —
308
+ // under it, where `at` still shows the old value, or over it, a float
309
+ // after the change showed.
310
+ const carried = (local) => (Number.isFinite(local) ? firstReaching(local + seconds, (x) => x - seconds >= local) : local);
311
+ return Animation.of({
312
+ at: (t) => (t - seconds >= 0 ? then.at(t - seconds) : first.at(t)),
313
+ nextChange(t) {
314
+ const into = t - seconds;
315
+ if (into < 0)
316
+ return Math.min(first.nextChange(t), seconds);
317
+ return Math.max(t, carried(then.nextChange(into)));
318
+ },
319
+ // After the switch the value became what it is at the switch or when
320
+ // `then`'s did since, whichever is later; before it, when `first`'s did.
321
+ lastChange(t) {
322
+ const into = t - seconds;
323
+ if (into < 0)
324
+ return first.lastChange(t);
325
+ return Math.min(t, Math.max(seconds, carried(then.lastChange(into))));
326
+ },
327
+ reduced: () => Animation.sequence(first.reduced(), seconds, then.reduced()),
328
+ });
329
+ },
330
+ /**
331
+ * `nth(n)` for every time in the `n`th turn, `[n·period, (n+1)·period)`,
332
+ * handed the time since that turn began — a one-shot played again every
333
+ * `period` seconds, a different one each turn if `nth` says so. `n` is any
334
+ * integer, so a timeline run back past 0 is in turn −1. Within a turn the
335
+ * value next changes when the turn's does or at the next turn, whichever is
336
+ * sooner, and became what it is when the turn's did or at this turn's start,
337
+ * whichever is later: run backwards, a host wakes where the turn began.
338
+ * Reduced, each turn is reduced and the turns kept, so a turn showing
339
+ * something new still shows it on time and a one-shot inside cuts to its
340
+ * end there. Nothing is walked through: a call reads only its turn.
341
+ */
342
+ repeat(period, nth) {
343
+ positiveSeconds("Animation.repeat period", period);
344
+ // [LAW:single-enforcer] Which turn a time is in, and how far into it, is
345
+ // `passAt`, the wrap a `beat` and `Phase.loop` read time through, so a
346
+ // repeat beside a loop of the same period turns on the same float; where
347
+ // a turn begins and the next begins are a one-hold beat's two ends.
348
+ const turns = beat([period]);
349
+ // The turn's moment `local`, on its own clock, carried onto this one: the
350
+ // first float the wrap places at or past `local` in turn `n`, or in a
351
+ // later turn, found as `sequence` carries its second part's.
352
+ const carried = (n, began, local) => Number.isFinite(local)
353
+ ? firstReaching(began + local, (x) => {
354
+ const { pass, into } = passAt("Animation.repeat", x, period);
355
+ return pass > n || (pass === n && into >= local);
356
+ })
357
+ : local;
358
+ return Animation.of({
359
+ at: (t) => {
360
+ const { pass, into } = passAt("Animation.repeat", t, period);
361
+ return nth(pass).at(into);
362
+ },
363
+ nextChange(t) {
364
+ const { pass, into } = passAt("Animation.repeat", t, period);
365
+ return Math.max(t, Math.min(turns.nextChange(t), carried(pass, turns.lastChange(t), nth(pass).nextChange(into))));
366
+ },
367
+ lastChange(t) {
368
+ const { pass, into } = passAt("Animation.repeat", t, period);
369
+ const began = turns.lastChange(t);
370
+ return Math.min(t, Math.max(began, carried(pass, began, nth(pass).lastChange(into))));
371
+ },
372
+ reduced: () => Animation.repeat(period, (n) => nth(n).reduced()),
373
+ });
374
+ },
375
+ };
package/dist/core/ansi.js CHANGED
@@ -51,10 +51,10 @@ import { RichText } from "./text.js";
51
51
  * and one final byte (`\x1b(B`, `\x1b)0`, `\x1b#8`, `\x1bc`). Only the first
52
52
  * three become tokens.
53
53
  */
54
- const ESCAPE = /\r|\x1b\[([0-9;:]*)m|\x1b\[([012]?)K|\x1b\[[0-?]*[ -/]*[@-~]|\x1b[\]P_^X][\s\S]*?(?:\x07|\x1b\\|\x9c|$)|\x1b[ -/]*[0-~]/g;
54
+ const escapes = () => /\r|\x1b\[([0-9;:]*)m|\x1b\[([012]?)K|\x1b\[[0-?]*[ -/]*[@-~]|\x1b[\]P_^X][\s\S]*?(?:\x07|\x1b\\|\x9c|$)|\x1b[ -/]*[0-~]/g;
55
55
  function* escapeTokens(bytes) {
56
56
  let at = 0;
57
- for (const match of bytes.matchAll(ESCAPE)) {
57
+ for (const match of bytes.matchAll(escapes())) {
58
58
  if (match.index > at)
59
59
  yield { kind: "text", text: bytes.slice(at, match.index) };
60
60
  if (match[0] === "\r")
@@ -28,19 +28,19 @@ import { Segment } from "./segment.js";
28
28
  import type { Style } from "./style.js";
29
29
  /** A rule spanning the table: the top and bottom borders, and every separator. */
30
30
  export interface EdgeChars {
31
- left: string;
32
- horizontal: string;
33
- cross: string;
34
- right: string;
31
+ readonly left: string;
32
+ readonly horizontal: string;
33
+ readonly cross: string;
34
+ readonly right: string;
35
35
  }
36
36
  /**
37
37
  * The verticals framing a row of cells. A content line of the grid has no
38
38
  * horizontal of its own — its fill column is a placeholder the cells occupy.
39
39
  */
40
40
  export interface ContentChars {
41
- left: string;
42
- vertical: string;
43
- right: string;
41
+ readonly left: string;
42
+ readonly vertical: string;
43
+ readonly right: string;
44
44
  }
45
45
  export type RowLevel = "head" | "row" | "foot" | "mid";
46
46
  export interface SubstituteOptions {
@@ -0,0 +1,9 @@
1
+ /**
2
+ * The cells Rich's `cell_len` gives each code point, and the code points VS16
3
+ * widens. Generated by scripts/cell-widths.py from Rich 15.0.0's Unicode 17.0.0
4
+ * table, which Rich builds from wcwidth's data; regenerate rather than edit.
5
+ */
6
+ /** The cells Rich gives `codePoint` on its own: none for a C0 or C1 control. */
7
+ export declare function codePointWidth(codePoint: number): 0 | 1 | 2;
8
+ /** Whether VS16 after `codePoint` widens it from one cell to two. */
9
+ export declare function widensToEmoji(codePoint: number): boolean;
@@ -0,0 +1,140 @@
1
+ /**
2
+ * The cells Rich's `cell_len` gives each code point, and the code points VS16
3
+ * widens. Generated by scripts/cell-widths.py from Rich 15.0.0's Unicode 17.0.0
4
+ * table, which Rich builds from wcwidth's data; regenerate rather than edit.
5
+ */
6
+ // Every range of code points that does not take one cell, as [first, last,
7
+ // cells]: ascending, disjoint, adjacent ranges of one width merged.
8
+ const RANGES = [
9
+ [0x0, 0x0, 0], [0x300, 0x36f, 0], [0x483, 0x489, 0], [0x591, 0x5bd, 0], [0x5bf, 0x5bf, 0], [0x5c1, 0x5c2, 0],
10
+ [0x5c4, 0x5c5, 0], [0x5c7, 0x5c7, 0], [0x610, 0x61a, 0], [0x61c, 0x61c, 0], [0x64b, 0x65f, 0], [0x670, 0x670, 0],
11
+ [0x6d6, 0x6dc, 0], [0x6df, 0x6e4, 0], [0x6e7, 0x6e8, 0], [0x6ea, 0x6ed, 0], [0x711, 0x711, 0], [0x730, 0x74a, 0],
12
+ [0x7a6, 0x7b0, 0], [0x7eb, 0x7f3, 0], [0x7fd, 0x7fd, 0], [0x816, 0x819, 0], [0x81b, 0x823, 0], [0x825, 0x827, 0],
13
+ [0x829, 0x82d, 0], [0x859, 0x85b, 0], [0x897, 0x89f, 0], [0x8ca, 0x8e1, 0], [0x8e3, 0x903, 0], [0x93a, 0x93c, 0],
14
+ [0x93e, 0x94f, 0], [0x951, 0x957, 0], [0x962, 0x963, 0], [0x981, 0x983, 0], [0x9bc, 0x9bc, 0], [0x9be, 0x9c4, 0],
15
+ [0x9c7, 0x9c8, 0], [0x9cb, 0x9cd, 0], [0x9d7, 0x9d7, 0], [0x9e2, 0x9e3, 0], [0x9fe, 0x9fe, 0], [0xa01, 0xa03, 0],
16
+ [0xa3c, 0xa3c, 0], [0xa3e, 0xa42, 0], [0xa47, 0xa48, 0], [0xa4b, 0xa4d, 0], [0xa51, 0xa51, 0], [0xa70, 0xa71, 0],
17
+ [0xa75, 0xa75, 0], [0xa81, 0xa83, 0], [0xabc, 0xabc, 0], [0xabe, 0xac5, 0], [0xac7, 0xac9, 0], [0xacb, 0xacd, 0],
18
+ [0xae2, 0xae3, 0], [0xafa, 0xaff, 0], [0xb01, 0xb03, 0], [0xb3c, 0xb3c, 0], [0xb3e, 0xb44, 0], [0xb47, 0xb48, 0],
19
+ [0xb4b, 0xb4d, 0], [0xb55, 0xb57, 0], [0xb62, 0xb63, 0], [0xb82, 0xb82, 0], [0xbbe, 0xbc2, 0], [0xbc6, 0xbc8, 0],
20
+ [0xbca, 0xbcd, 0], [0xbd7, 0xbd7, 0], [0xc00, 0xc04, 0], [0xc3c, 0xc3c, 0], [0xc3e, 0xc44, 0], [0xc46, 0xc48, 0],
21
+ [0xc4a, 0xc4d, 0], [0xc55, 0xc56, 0], [0xc62, 0xc63, 0], [0xc81, 0xc83, 0], [0xcbc, 0xcbc, 0], [0xcbe, 0xcc4, 0],
22
+ [0xcc6, 0xcc8, 0], [0xcca, 0xccd, 0], [0xcd5, 0xcd6, 0], [0xce2, 0xce3, 0], [0xcf3, 0xcf3, 0], [0xd00, 0xd03, 0],
23
+ [0xd3b, 0xd3c, 0], [0xd3e, 0xd44, 0], [0xd46, 0xd48, 0], [0xd4a, 0xd4d, 0], [0xd57, 0xd57, 0], [0xd62, 0xd63, 0],
24
+ [0xd81, 0xd83, 0], [0xdca, 0xdca, 0], [0xdcf, 0xdd4, 0], [0xdd6, 0xdd6, 0], [0xdd8, 0xddf, 0], [0xdf2, 0xdf3, 0],
25
+ [0xe31, 0xe31, 0], [0xe34, 0xe3a, 0], [0xe47, 0xe4e, 0], [0xeb1, 0xeb1, 0], [0xeb4, 0xebc, 0], [0xec8, 0xece, 0],
26
+ [0xf18, 0xf19, 0], [0xf35, 0xf35, 0], [0xf37, 0xf37, 0], [0xf39, 0xf39, 0], [0xf3e, 0xf3f, 0], [0xf71, 0xf84, 0],
27
+ [0xf86, 0xf87, 0], [0xf8d, 0xf97, 0], [0xf99, 0xfbc, 0], [0xfc6, 0xfc6, 0], [0x102b, 0x103e, 0], [0x1056, 0x1059, 0],
28
+ [0x105e, 0x1060, 0], [0x1062, 0x1064, 0], [0x1067, 0x106d, 0], [0x1071, 0x1074, 0], [0x1082, 0x108d, 0],
29
+ [0x108f, 0x108f, 0], [0x109a, 0x109d, 0], [0x1100, 0x115f, 2], [0x1160, 0x11ff, 0], [0x135d, 0x135f, 0],
30
+ [0x1712, 0x1715, 0], [0x1732, 0x1734, 0], [0x1752, 0x1753, 0], [0x1772, 0x1773, 0], [0x17b4, 0x17d3, 0],
31
+ [0x17dd, 0x17dd, 0], [0x180b, 0x180f, 0], [0x1885, 0x1886, 0], [0x18a9, 0x18a9, 0], [0x1920, 0x192b, 0],
32
+ [0x1930, 0x193b, 0], [0x1a17, 0x1a1b, 0], [0x1a55, 0x1a5e, 0], [0x1a60, 0x1a7c, 0], [0x1a7f, 0x1a7f, 0],
33
+ [0x1ab0, 0x1add, 0], [0x1ae0, 0x1aeb, 0], [0x1b00, 0x1b04, 0], [0x1b34, 0x1b44, 0], [0x1b6b, 0x1b73, 0],
34
+ [0x1b80, 0x1b82, 0], [0x1ba1, 0x1bad, 0], [0x1be6, 0x1bf3, 0], [0x1c24, 0x1c37, 0], [0x1cd0, 0x1cd2, 0],
35
+ [0x1cd4, 0x1ce8, 0], [0x1ced, 0x1ced, 0], [0x1cf4, 0x1cf4, 0], [0x1cf7, 0x1cf9, 0], [0x1dc0, 0x1dff, 0],
36
+ [0x200b, 0x200f, 0], [0x2028, 0x202e, 0], [0x2060, 0x206f, 0], [0x20d0, 0x20f0, 0], [0x231a, 0x231b, 2],
37
+ [0x2329, 0x232a, 2], [0x23e9, 0x23ec, 2], [0x23f0, 0x23f0, 2], [0x23f3, 0x23f3, 2], [0x25fd, 0x25fe, 2],
38
+ [0x2614, 0x2615, 2], [0x2630, 0x2637, 2], [0x2648, 0x2653, 2], [0x267f, 0x267f, 2], [0x268a, 0x268f, 2],
39
+ [0x2693, 0x2693, 2], [0x26a1, 0x26a1, 2], [0x26aa, 0x26ab, 2], [0x26bd, 0x26be, 2], [0x26c4, 0x26c5, 2],
40
+ [0x26ce, 0x26ce, 2], [0x26d4, 0x26d4, 2], [0x26ea, 0x26ea, 2], [0x26f2, 0x26f3, 2], [0x26f5, 0x26f5, 2],
41
+ [0x26fa, 0x26fa, 2], [0x26fd, 0x26fd, 2], [0x2705, 0x2705, 2], [0x270a, 0x270b, 2], [0x2728, 0x2728, 2],
42
+ [0x274c, 0x274c, 2], [0x274e, 0x274e, 2], [0x2753, 0x2755, 2], [0x2757, 0x2757, 2], [0x2795, 0x2797, 2],
43
+ [0x27b0, 0x27b0, 2], [0x27bf, 0x27bf, 2], [0x2b1b, 0x2b1c, 2], [0x2b50, 0x2b50, 2], [0x2b55, 0x2b55, 2],
44
+ [0x2cef, 0x2cf1, 0], [0x2d7f, 0x2d7f, 0], [0x2de0, 0x2dff, 0], [0x2e80, 0x2e99, 2], [0x2e9b, 0x2ef3, 2],
45
+ [0x2f00, 0x2fd5, 2], [0x2ff0, 0x3029, 2], [0x302a, 0x302f, 0], [0x3030, 0x303e, 2], [0x3041, 0x3096, 2],
46
+ [0x3099, 0x309a, 0], [0x309b, 0x30ff, 2], [0x3105, 0x312f, 2], [0x3131, 0x3163, 2], [0x3164, 0x3164, 0],
47
+ [0x3165, 0x318e, 2], [0x3190, 0x31e5, 2], [0x31ef, 0x321e, 2], [0x3220, 0x3247, 2], [0x3250, 0xa48c, 2],
48
+ [0xa490, 0xa4c6, 2], [0xa66f, 0xa672, 0], [0xa674, 0xa67d, 0], [0xa69e, 0xa69f, 0], [0xa6f0, 0xa6f1, 0],
49
+ [0xa802, 0xa802, 0], [0xa806, 0xa806, 0], [0xa80b, 0xa80b, 0], [0xa823, 0xa827, 0], [0xa82c, 0xa82c, 0],
50
+ [0xa880, 0xa881, 0], [0xa8b4, 0xa8c5, 0], [0xa8e0, 0xa8f1, 0], [0xa8ff, 0xa8ff, 0], [0xa926, 0xa92d, 0],
51
+ [0xa947, 0xa953, 0], [0xa960, 0xa97c, 2], [0xa980, 0xa983, 0], [0xa9b3, 0xa9c0, 0], [0xa9e5, 0xa9e5, 0],
52
+ [0xaa29, 0xaa36, 0], [0xaa43, 0xaa43, 0], [0xaa4c, 0xaa4d, 0], [0xaa7b, 0xaa7d, 0], [0xaab0, 0xaab0, 0],
53
+ [0xaab2, 0xaab4, 0], [0xaab7, 0xaab8, 0], [0xaabe, 0xaabf, 0], [0xaac1, 0xaac1, 0], [0xaaeb, 0xaaef, 0],
54
+ [0xaaf5, 0xaaf6, 0], [0xabe3, 0xabea, 0], [0xabec, 0xabed, 0], [0xac00, 0xd7a3, 2], [0xd7b0, 0xd7ff, 0],
55
+ [0xf900, 0xfaff, 2], [0xfb1e, 0xfb1e, 0], [0xfe00, 0xfe0f, 0], [0xfe10, 0xfe19, 2], [0xfe20, 0xfe2f, 0],
56
+ [0xfe30, 0xfe52, 2], [0xfe54, 0xfe66, 2], [0xfe68, 0xfe6b, 2], [0xfeff, 0xfeff, 0], [0xff01, 0xff60, 2],
57
+ [0xffa0, 0xffa0, 0], [0xffe0, 0xffe6, 2], [0xfff0, 0xfffb, 0], [0x101fd, 0x101fd, 0], [0x102e0, 0x102e0, 0],
58
+ [0x10376, 0x1037a, 0], [0x10a01, 0x10a03, 0], [0x10a05, 0x10a06, 0], [0x10a0c, 0x10a0f, 0], [0x10a38, 0x10a3a, 0],
59
+ [0x10a3f, 0x10a3f, 0], [0x10ae5, 0x10ae6, 0], [0x10d24, 0x10d27, 0], [0x10d69, 0x10d6d, 0], [0x10eab, 0x10eac, 0],
60
+ [0x10efa, 0x10eff, 0], [0x10f46, 0x10f50, 0], [0x10f82, 0x10f85, 0], [0x11000, 0x11002, 0], [0x11038, 0x11046, 0],
61
+ [0x11070, 0x11070, 0], [0x11073, 0x11074, 0], [0x1107f, 0x11082, 0], [0x110b0, 0x110ba, 0], [0x110c2, 0x110c2, 0],
62
+ [0x11100, 0x11102, 0], [0x11127, 0x11134, 0], [0x11145, 0x11146, 0], [0x11173, 0x11173, 0], [0x11180, 0x11182, 0],
63
+ [0x111b3, 0x111c0, 0], [0x111c9, 0x111cc, 0], [0x111ce, 0x111cf, 0], [0x1122c, 0x11237, 0], [0x1123e, 0x1123e, 0],
64
+ [0x11241, 0x11241, 0], [0x112df, 0x112ea, 0], [0x11300, 0x11303, 0], [0x1133b, 0x1133c, 0], [0x1133e, 0x11344, 0],
65
+ [0x11347, 0x11348, 0], [0x1134b, 0x1134d, 0], [0x11357, 0x11357, 0], [0x11362, 0x11363, 0], [0x11366, 0x1136c, 0],
66
+ [0x11370, 0x11374, 0], [0x113b8, 0x113c0, 0], [0x113c2, 0x113c2, 0], [0x113c5, 0x113c5, 0], [0x113c7, 0x113ca, 0],
67
+ [0x113cc, 0x113d0, 0], [0x113d2, 0x113d2, 0], [0x113e1, 0x113e2, 0], [0x11435, 0x11446, 0], [0x1145e, 0x1145e, 0],
68
+ [0x114b0, 0x114c3, 0], [0x115af, 0x115b5, 0], [0x115b8, 0x115c0, 0], [0x115dc, 0x115dd, 0], [0x11630, 0x11640, 0],
69
+ [0x116ab, 0x116b7, 0], [0x1171d, 0x1172b, 0], [0x1182c, 0x1183a, 0], [0x11930, 0x11935, 0], [0x11937, 0x11938, 0],
70
+ [0x1193b, 0x1193e, 0], [0x11940, 0x11940, 0], [0x11942, 0x11943, 0], [0x119d1, 0x119d7, 0], [0x119da, 0x119e0, 0],
71
+ [0x119e4, 0x119e4, 0], [0x11a01, 0x11a0a, 0], [0x11a33, 0x11a39, 0], [0x11a3b, 0x11a3e, 0], [0x11a47, 0x11a47, 0],
72
+ [0x11a51, 0x11a5b, 0], [0x11a8a, 0x11a99, 0], [0x11b60, 0x11b67, 0], [0x11c2f, 0x11c36, 0], [0x11c38, 0x11c3f, 0],
73
+ [0x11c92, 0x11ca7, 0], [0x11ca9, 0x11cb6, 0], [0x11d31, 0x11d36, 0], [0x11d3a, 0x11d3a, 0], [0x11d3c, 0x11d3d, 0],
74
+ [0x11d3f, 0x11d45, 0], [0x11d47, 0x11d47, 0], [0x11d8a, 0x11d8e, 0], [0x11d90, 0x11d91, 0], [0x11d93, 0x11d97, 0],
75
+ [0x11ef3, 0x11ef6, 0], [0x11f00, 0x11f01, 0], [0x11f03, 0x11f03, 0], [0x11f34, 0x11f3a, 0], [0x11f3e, 0x11f42, 0],
76
+ [0x11f5a, 0x11f5a, 0], [0x13430, 0x13440, 0], [0x13447, 0x13455, 0], [0x1611e, 0x1612f, 0], [0x16af0, 0x16af4, 0],
77
+ [0x16b30, 0x16b36, 0], [0x16f4f, 0x16f4f, 0], [0x16f51, 0x16f87, 0], [0x16f8f, 0x16f92, 0], [0x16fe0, 0x16fe3, 2],
78
+ [0x16fe4, 0x16fe4, 0], [0x16ff0, 0x16ff1, 0], [0x16ff2, 0x16ff6, 2], [0x17000, 0x18cd5, 2], [0x18cff, 0x18d1e, 2],
79
+ [0x18d80, 0x18df2, 2], [0x1aff0, 0x1aff3, 2], [0x1aff5, 0x1affb, 2], [0x1affd, 0x1affe, 2], [0x1b000, 0x1b122, 2],
80
+ [0x1b132, 0x1b132, 2], [0x1b150, 0x1b152, 2], [0x1b155, 0x1b155, 2], [0x1b164, 0x1b167, 2], [0x1b170, 0x1b2fb, 2],
81
+ [0x1bc9d, 0x1bc9e, 0], [0x1bca0, 0x1bca3, 0], [0x1cf00, 0x1cf2d, 0], [0x1cf30, 0x1cf46, 0], [0x1d165, 0x1d169, 0],
82
+ [0x1d16d, 0x1d182, 0], [0x1d185, 0x1d18b, 0], [0x1d1aa, 0x1d1ad, 0], [0x1d242, 0x1d244, 0], [0x1d300, 0x1d356, 2],
83
+ [0x1d360, 0x1d376, 2], [0x1da00, 0x1da36, 0], [0x1da3b, 0x1da6c, 0], [0x1da75, 0x1da75, 0], [0x1da84, 0x1da84, 0],
84
+ [0x1da9b, 0x1da9f, 0], [0x1daa1, 0x1daaf, 0], [0x1e000, 0x1e006, 0], [0x1e008, 0x1e018, 0], [0x1e01b, 0x1e021, 0],
85
+ [0x1e023, 0x1e024, 0], [0x1e026, 0x1e02a, 0], [0x1e08f, 0x1e08f, 0], [0x1e130, 0x1e136, 0], [0x1e2ae, 0x1e2ae, 0],
86
+ [0x1e2ec, 0x1e2ef, 0], [0x1e4ec, 0x1e4ef, 0], [0x1e5ee, 0x1e5ef, 0], [0x1e6e3, 0x1e6e3, 0], [0x1e6e6, 0x1e6e6, 0],
87
+ [0x1e6ee, 0x1e6ef, 0], [0x1e6f5, 0x1e6f5, 0], [0x1e8d0, 0x1e8d6, 0], [0x1e944, 0x1e94a, 0], [0x1f004, 0x1f004, 2],
88
+ [0x1f0cf, 0x1f0cf, 2], [0x1f18e, 0x1f18e, 2], [0x1f191, 0x1f19a, 2], [0x1f200, 0x1f202, 2], [0x1f210, 0x1f23b, 2],
89
+ [0x1f240, 0x1f248, 2], [0x1f250, 0x1f251, 2], [0x1f260, 0x1f265, 2], [0x1f300, 0x1f320, 2], [0x1f32d, 0x1f335, 2],
90
+ [0x1f337, 0x1f37c, 2], [0x1f37e, 0x1f393, 2], [0x1f3a0, 0x1f3ca, 2], [0x1f3cf, 0x1f3d3, 2], [0x1f3e0, 0x1f3f0, 2],
91
+ [0x1f3f4, 0x1f3f4, 2], [0x1f3f8, 0x1f3fa, 2], [0x1f3fb, 0x1f3ff, 0], [0x1f400, 0x1f43e, 2], [0x1f440, 0x1f440, 2],
92
+ [0x1f442, 0x1f4fc, 2], [0x1f4ff, 0x1f53d, 2], [0x1f54b, 0x1f54e, 2], [0x1f550, 0x1f567, 2], [0x1f57a, 0x1f57a, 2],
93
+ [0x1f595, 0x1f596, 2], [0x1f5a4, 0x1f5a4, 2], [0x1f5fb, 0x1f64f, 2], [0x1f680, 0x1f6c5, 2], [0x1f6cc, 0x1f6cc, 2],
94
+ [0x1f6d0, 0x1f6d2, 2], [0x1f6d5, 0x1f6d8, 2], [0x1f6dc, 0x1f6df, 2], [0x1f6eb, 0x1f6ec, 2], [0x1f6f4, 0x1f6fc, 2],
95
+ [0x1f7e0, 0x1f7eb, 2], [0x1f7f0, 0x1f7f0, 2], [0x1f90c, 0x1f93a, 2], [0x1f93c, 0x1f945, 2], [0x1f947, 0x1f9ff, 2],
96
+ [0x1fa70, 0x1fa7c, 2], [0x1fa80, 0x1fa8a, 2], [0x1fa8e, 0x1fac6, 2], [0x1fac8, 0x1fac8, 2], [0x1facd, 0x1fadc, 2],
97
+ [0x1fadf, 0x1faea, 2], [0x1faef, 0x1faf8, 2], [0x20000, 0x2fffd, 2], [0x30000, 0x3fffd, 2], [0xe0000, 0xe0fff, 0],
98
+ ];
99
+ // The code points one cell wide on their own and two when VARIATION SELECTOR-16
100
+ // asks for emoji presentation.
101
+ const NARROW_TO_WIDE = new Set([
102
+ 0x23, 0x2a, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0xa9, 0xae, 0x203c, 0x2049, 0x2122, 0x2139,
103
+ 0x2194, 0x2195, 0x2196, 0x2197, 0x2198, 0x2199, 0x21a9, 0x21aa, 0x2328, 0x23cf, 0x23ed, 0x23ee, 0x23ef, 0x23f1,
104
+ 0x23f2, 0x23f8, 0x23f9, 0x23fa, 0x24c2, 0x25aa, 0x25ab, 0x25b6, 0x25c0, 0x25fb, 0x25fc, 0x2600, 0x2601, 0x2602,
105
+ 0x2603, 0x2604, 0x260e, 0x2611, 0x2618, 0x261d, 0x2620, 0x2622, 0x2623, 0x2626, 0x262a, 0x262e, 0x262f, 0x2638,
106
+ 0x2639, 0x263a, 0x2640, 0x2642, 0x265f, 0x2660, 0x2663, 0x2665, 0x2666, 0x2668, 0x267b, 0x267e, 0x2692, 0x2694,
107
+ 0x2695, 0x2696, 0x2697, 0x2699, 0x269b, 0x269c, 0x26a0, 0x26a7, 0x26b0, 0x26b1, 0x26c8, 0x26cf, 0x26d1, 0x26d3,
108
+ 0x26e9, 0x26f0, 0x26f1, 0x26f4, 0x26f7, 0x26f8, 0x26f9, 0x2702, 0x2708, 0x2709, 0x270c, 0x270d, 0x270f, 0x2712,
109
+ 0x2714, 0x2716, 0x271d, 0x2721, 0x2733, 0x2734, 0x2744, 0x2747, 0x2763, 0x2764, 0x27a1, 0x2934, 0x2935, 0x2b05,
110
+ 0x2b06, 0x2b07, 0x1f170, 0x1f171, 0x1f17e, 0x1f17f, 0x1f321, 0x1f324, 0x1f325, 0x1f326, 0x1f327, 0x1f328, 0x1f329,
111
+ 0x1f32a, 0x1f32b, 0x1f32c, 0x1f336, 0x1f37d, 0x1f396, 0x1f397, 0x1f399, 0x1f39a, 0x1f39b, 0x1f39e, 0x1f39f, 0x1f3cb,
112
+ 0x1f3cc, 0x1f3cd, 0x1f3ce, 0x1f3d4, 0x1f3d5, 0x1f3d6, 0x1f3d7, 0x1f3d8, 0x1f3d9, 0x1f3da, 0x1f3db, 0x1f3dc, 0x1f3dd,
113
+ 0x1f3de, 0x1f3df, 0x1f3f3, 0x1f3f5, 0x1f3f7, 0x1f43f, 0x1f441, 0x1f4fd, 0x1f549, 0x1f54a, 0x1f56f, 0x1f570, 0x1f573,
114
+ 0x1f574, 0x1f575, 0x1f576, 0x1f577, 0x1f578, 0x1f579, 0x1f587, 0x1f58a, 0x1f58b, 0x1f58c, 0x1f58d, 0x1f590, 0x1f5a5,
115
+ 0x1f5a8, 0x1f5b1, 0x1f5b2, 0x1f5bc, 0x1f5c2, 0x1f5c3, 0x1f5c4, 0x1f5d1, 0x1f5d2, 0x1f5d3, 0x1f5dc, 0x1f5dd, 0x1f5de,
116
+ 0x1f5e1, 0x1f5e3, 0x1f5e8, 0x1f5ef, 0x1f5f3, 0x1f5fa, 0x1f6cb, 0x1f6cd, 0x1f6ce, 0x1f6cf, 0x1f6e0, 0x1f6e1, 0x1f6e2,
117
+ 0x1f6e3, 0x1f6e4, 0x1f6e5, 0x1f6e9, 0x1f6f0, 0x1f6f3,
118
+ ]);
119
+ /** The cells Rich gives `codePoint` on its own: none for a C0 or C1 control. */
120
+ export function codePointWidth(codePoint) {
121
+ if (codePoint < 0x20 || (codePoint >= 0x7f && codePoint < 0xa0))
122
+ return 0;
123
+ let low = 0;
124
+ let high = RANGES.length - 1;
125
+ while (low <= high) {
126
+ const mid = (low + high) >> 1;
127
+ const [first, last, cells] = RANGES[mid];
128
+ if (codePoint < first)
129
+ high = mid - 1;
130
+ else if (codePoint > last)
131
+ low = mid + 1;
132
+ else
133
+ return cells;
134
+ }
135
+ return 1;
136
+ }
137
+ /** Whether VS16 after `codePoint` widens it from one cell to two. */
138
+ export function widensToEmoji(codePoint) {
139
+ return NARROW_TO_WIDE.has(codePoint);
140
+ }