@promptctl/rich-js 0.26.0 → 0.28.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 (132) hide show
  1. package/README.md +1 -0
  2. package/THIRD-PARTY-NOTICES +42 -0
  3. package/dist/core/animation.d.ts +52 -15
  4. package/dist/core/animation.js +82 -37
  5. package/dist/core/ansi.d.ts +15 -8
  6. package/dist/core/ansi.js +106 -28
  7. package/dist/core/bidi-data.d.ts +14 -0
  8. package/dist/core/bidi-data.js +385 -0
  9. package/dist/core/bidi.d.ts +89 -0
  10. package/dist/core/bidi.js +615 -0
  11. package/dist/core/box.d.ts +9 -1
  12. package/dist/core/box.js +11 -0
  13. package/dist/core/cell-widths.d.ts +3 -2
  14. package/dist/core/cell-widths.js +93 -93
  15. package/dist/core/cells.d.ts +20 -0
  16. package/dist/core/cells.js +93 -5
  17. package/dist/core/color.d.ts +26 -18
  18. package/dist/core/color.js +37 -34
  19. package/dist/core/console.d.ts +26 -1
  20. package/dist/core/console.js +26 -6
  21. package/dist/core/control-codes.d.ts +61 -0
  22. package/dist/core/control-codes.js +157 -0
  23. package/dist/core/easing.js +6 -1
  24. package/dist/core/env.d.ts +6 -0
  25. package/dist/core/env.js +9 -1
  26. package/dist/core/export-html.js +4 -3
  27. package/dist/core/export-lines.d.ts +2 -0
  28. package/dist/core/export-lines.js +7 -3
  29. package/dist/core/export-svg.js +6 -5
  30. package/dist/core/json.js +9 -2
  31. package/dist/core/markup.js +4 -3
  32. package/dist/core/oklch.d.ts +2 -0
  33. package/dist/core/oklch.js +3 -3
  34. package/dist/core/orient.d.ts +68 -0
  35. package/dist/core/orient.js +224 -0
  36. package/dist/core/osc8.d.ts +12 -5
  37. package/dist/core/osc8.js +14 -7
  38. package/dist/core/pretty.js +22 -18
  39. package/dist/core/protocol.d.ts +53 -22
  40. package/dist/core/protocol.js +14 -6
  41. package/dist/core/render.d.ts +8 -3
  42. package/dist/core/render.js +19 -5
  43. package/dist/core/seal.d.ts +26 -0
  44. package/dist/core/seal.js +75 -0
  45. package/dist/core/segment.d.ts +9 -1
  46. package/dist/core/segment.js +11 -1
  47. package/dist/core/style.d.ts +29 -1
  48. package/dist/core/style.js +41 -5
  49. package/dist/core/text-order.d.ts +51 -0
  50. package/dist/core/text-order.js +50 -0
  51. package/dist/core/text.d.ts +10 -0
  52. package/dist/core/text.js +133 -87
  53. package/dist/core/timeline.js +6 -6
  54. package/dist/core/view.d.ts +23 -9
  55. package/dist/core/view.js +37 -12
  56. package/dist/core/wrap.d.ts +24 -6
  57. package/dist/core/wrap.js +82 -16
  58. package/dist/host/app.d.ts +48 -7
  59. package/dist/host/app.js +116 -11
  60. package/dist/host/index.d.ts +3 -2
  61. package/dist/host/index.js +1 -0
  62. package/dist/host/input.d.ts +35 -2
  63. package/dist/host/input.js +88 -4
  64. package/dist/host/terminal-colors.d.ts +18 -0
  65. package/dist/host/terminal-colors.js +46 -0
  66. package/dist/host/terminal-host.d.ts +2 -1
  67. package/dist/index.d.ts +10 -8
  68. package/dist/index.js +2 -2
  69. package/dist/renderables/change.d.ts +1 -3
  70. package/dist/renderables/change.js +4 -6
  71. package/dist/renderables/effect.d.ts +61 -60
  72. package/dist/renderables/effect.js +91 -81
  73. package/dist/renderables/effects.d.ts +37 -8
  74. package/dist/renderables/effects.js +193 -55
  75. package/dist/renderables/frames.d.ts +1 -10
  76. package/dist/renderables/frames.js +1 -16
  77. package/dist/renderables/glyph-effect.d.ts +12 -13
  78. package/dist/renderables/glyph-effect.js +34 -32
  79. package/dist/renderables/glyph-effects.d.ts +27 -8
  80. package/dist/renderables/glyph-effects.js +75 -7
  81. package/dist/renderables/lifecycle.d.ts +40 -32
  82. package/dist/renderables/lifecycle.js +87 -48
  83. package/dist/renderables/live.d.ts +3 -3
  84. package/dist/renderables/live.js +4 -4
  85. package/dist/renderables/markdown.js +4 -2
  86. package/dist/renderables/panel.js +6 -4
  87. package/dist/renderables/progress.d.ts +11 -4
  88. package/dist/renderables/progress.js +29 -17
  89. package/dist/renderables/progressBar.d.ts +3 -3
  90. package/dist/renderables/progressBar.js +16 -13
  91. package/dist/renderables/syntax.js +7 -2
  92. package/dist/renderables/table.js +2 -1
  93. package/dist/template-bindings/animation-funcs.d.ts +49 -18
  94. package/dist/template-bindings/animation-funcs.js +115 -32
  95. package/dist/template-bindings/index.d.ts +7 -5
  96. package/dist/template-bindings/index.js +8 -5
  97. package/dist/template-bindings/palette-funcs.d.ts +1 -1
  98. package/dist/template-bindings/palette-funcs.js +1 -1
  99. package/dist/themes/buildPalette.d.ts +15 -39
  100. package/dist/themes/buildPalette.js +196 -67
  101. package/dist/themes/colorMath.d.ts +10 -4
  102. package/dist/themes/colorMath.js +33 -1
  103. package/dist/themes/data/index.js +1 -4
  104. package/dist/themes/data/textual-ansi.js +0 -143
  105. package/dist/themes/data/types.d.ts +3 -1
  106. package/dist/themes/palette.d.ts +22 -6
  107. package/dist/themes/palette.js +13 -21
  108. package/dist/themes/ramp.d.ts +1 -1
  109. package/dist/themes/ramp.js +1 -1
  110. package/dist/themes/registry.d.ts +7 -10
  111. package/dist/themes/registry.js +9 -30
  112. package/dist/themes/terminalThemes.d.ts +4 -10
  113. package/dist/themes/terminalThemes.js +31 -46
  114. package/dist/themes/transpose.d.ts +5 -10
  115. package/dist/themes/transpose.js +13 -24
  116. package/dist/widgets/button.d.ts +1 -1
  117. package/dist/widgets/button.js +6 -6
  118. package/dist/widgets/checkbox.js +4 -4
  119. package/dist/widgets/dropdown.d.ts +1 -1
  120. package/dist/widgets/dropdown.js +7 -5
  121. package/dist/widgets/event-router.js +2 -2
  122. package/dist/widgets/ink.d.ts +5 -4
  123. package/dist/widgets/ink.js +6 -9
  124. package/dist/widgets/text-input.d.ts +1 -1
  125. package/dist/widgets/text-input.js +41 -32
  126. package/dist/widgets/themed-widget.js +3 -3
  127. package/dist/widgets/toggle.d.ts +1 -1
  128. package/dist/widgets/toggle.js +5 -5
  129. package/dist/widgets/types.d.ts +2 -2
  130. package/dist/widgets/widget-app.d.ts +3 -3
  131. package/dist/widgets/widget-app.js +5 -5
  132. package/package.json +5 -4
@@ -107,7 +107,7 @@ import { Viewport } from "../renderables/viewport.js";
107
107
  import { Animation } from "../core/animation.js";
108
108
  import { beat } from "../core/easing.js";
109
109
  import { Timeline } from "../core/timeline.js";
110
- import { holdOf, shownAt, stampFrame } from "../core/animation.js";
110
+ import { placed } from "../core/animation.js";
111
111
  import { levelOf } from "../core/anchor.js";
112
112
  import { ThemedWidget } from "./themed-widget.js";
113
113
  import { ink } from "./ink.js";
@@ -244,8 +244,24 @@ function wordSpan(clusters, skipped, taken) {
244
244
  * for the next, on a `beat`. A loop, so with its motion taken out it holds lit.
245
245
  */
246
246
  const CARET_BLINK = Animation.map(beat([0.5, 0.5]), (hold) => hold === 0);
247
- /** The caret of a frame drawn for no moment — a `print` — which nothing moves: lit, and never changing. */
248
- const CARET_UNTIMED = { lit: true, hold: { lastChange: Number.NEGATIVE_INFINITY, nextChange: Number.POSITIVE_INFINITY } };
247
+ /**
248
+ * The caret's blink restarted at `from`, as one animation of the frame's
249
+ * time: `CARET_BLINK` run forward from `from` at and after it, and backward
250
+ * from it before, so a timeline played backwards also finds the caret lit
251
+ * just after a key. Each answer is the run the time falls in, bounded at
252
+ * `from` where the runs meet — early where it must guess, never late. A
253
+ * function of `from` alone, so the frame hands it its time (`placed`).
254
+ */
255
+ function caretBlink(from) {
256
+ const forward = Timeline.run(Timeline.play(from, 1), CARET_BLINK);
257
+ const backward = Timeline.run(Timeline.play(from, -1), CARET_BLINK);
258
+ return Animation.of({
259
+ at: (t) => (t >= from ? forward : backward).at(t),
260
+ nextChange: (t) => (t >= from ? forward.nextChange(t) : Math.min(backward.nextChange(t), from)),
261
+ lastChange: (t) => (t >= from ? Math.max(forward.lastChange(t), from) : backward.lastChange(t)),
262
+ reduced: () => CARET_BLINK.reduced(),
263
+ });
264
+ }
249
265
  let TextInput = (() => {
250
266
  let _classSuper = ThemedWidget;
251
267
  let _instanceExtraInitializers = [];
@@ -255,9 +271,9 @@ let TextInput = (() => {
255
271
  let __cursor_decorators;
256
272
  let __cursor_initializers = [];
257
273
  let __cursor_extraInitializers = [];
258
- let __blinkFrom_decorators;
259
- let __blinkFrom_initializers = [];
260
- let __blinkFrom_extraInitializers = [];
274
+ let __blink_decorators;
275
+ let __blink_initializers = [];
276
+ let __blink_extraInitializers = [];
261
277
  let _placeholder_decorators;
262
278
  let _placeholder_initializers = [];
263
279
  let _placeholder_extraInitializers = [];
@@ -298,7 +314,7 @@ let TextInput = (() => {
298
314
  const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
299
315
  __value_decorators = [observableRef];
300
316
  __cursor_decorators = [observableRef];
301
- __blinkFrom_decorators = [observableRef];
317
+ __blink_decorators = [observableRef];
302
318
  _placeholder_decorators = [observableRef];
303
319
  _indicatorStyleOverride_decorators = [observableRef];
304
320
  _cursorStyleOverride_decorators = [observableRef];
@@ -328,7 +344,7 @@ let TextInput = (() => {
328
344
  __insertText_decorators = [action];
329
345
  __esDecorate(this, null, __value_decorators, { kind: "accessor", name: "_value", static: false, private: false, access: { has: obj => "_value" in obj, get: obj => obj._value, set: (obj, value) => { obj._value = value; } }, metadata: _metadata }, __value_initializers, __value_extraInitializers);
330
346
  __esDecorate(this, null, __cursor_decorators, { kind: "accessor", name: "_cursor", static: false, private: false, access: { has: obj => "_cursor" in obj, get: obj => obj._cursor, set: (obj, value) => { obj._cursor = value; } }, metadata: _metadata }, __cursor_initializers, __cursor_extraInitializers);
331
- __esDecorate(this, null, __blinkFrom_decorators, { kind: "accessor", name: "_blinkFrom", static: false, private: false, access: { has: obj => "_blinkFrom" in obj, get: obj => obj._blinkFrom, set: (obj, value) => { obj._blinkFrom = value; } }, metadata: _metadata }, __blinkFrom_initializers, __blinkFrom_extraInitializers);
347
+ __esDecorate(this, null, __blink_decorators, { kind: "accessor", name: "_blink", static: false, private: false, access: { has: obj => "_blink" in obj, get: obj => obj._blink, set: (obj, value) => { obj._blink = value; } }, metadata: _metadata }, __blink_initializers, __blink_extraInitializers);
332
348
  __esDecorate(this, null, _placeholder_decorators, { kind: "accessor", name: "placeholder", static: false, private: false, access: { has: obj => "placeholder" in obj, get: obj => obj.placeholder, set: (obj, value) => { obj.placeholder = value; } }, metadata: _metadata }, _placeholder_initializers, _placeholder_extraInitializers);
333
349
  __esDecorate(this, null, _indicatorStyleOverride_decorators, { kind: "accessor", name: "indicatorStyleOverride", static: false, private: false, access: { has: obj => "indicatorStyleOverride" in obj, get: obj => obj.indicatorStyleOverride, set: (obj, value) => { obj.indicatorStyleOverride = value; } }, metadata: _metadata }, _indicatorStyleOverride_initializers, _indicatorStyleOverride_extraInitializers);
334
350
  __esDecorate(this, null, _cursorStyleOverride_decorators, { kind: "accessor", name: "cursorStyleOverride", static: false, private: false, access: { has: obj => "cursorStyleOverride" in obj, get: obj => obj.cursorStyleOverride, set: (obj, value) => { obj.cursorStyleOverride = value; } }, metadata: _metadata }, _cursorStyleOverride_initializers, _cursorStyleOverride_extraInitializers);
@@ -366,13 +382,12 @@ let TextInput = (() => {
366
382
  #_cursor_accessor_storage = (__runInitializers(this, __value_extraInitializers), __runInitializers(this, __cursor_initializers, void 0));
367
383
  get _cursor() { return this.#_cursor_accessor_storage; }
368
384
  set _cursor(value) { this.#_cursor_accessor_storage = value; }
369
- #_blinkFrom_accessor_storage = (__runInitializers(this, __cursor_extraInitializers), __runInitializers(this, __blinkFrom_initializers, 0));
370
- // When the field last took focus, a click, or a key it handled, on the
371
- // frame's clock (each event's `time`): where the caret's blink restarts.
372
- // The blink itself is a function of this and the time a frame is drawn
373
- // for, so nothing about it is kept.
374
- get _blinkFrom() { return this.#_blinkFrom_accessor_storage; }
375
- set _blinkFrom(value) { this.#_blinkFrom_accessor_storage = value; }
385
+ #_blink_accessor_storage = (__runInitializers(this, __cursor_extraInitializers), __runInitializers(this, __blink_initializers, caretBlink(0)));
386
+ // The caret's blink, restarted (`caretBlink`) when the field last took
387
+ // focus, a click, or a key it handled, at that event's `time` on the
388
+ // frame's clock. Built at the event, so a frame only reads it.
389
+ get _blink() { return this.#_blink_accessor_storage; }
390
+ set _blink(value) { this.#_blink_accessor_storage = value; }
376
391
  // [LAW:single-enforcer] Every write to either half of the pair passes
377
392
  // `graphemeBoundary`, so the cursor is a cluster boundary inside `value`
378
393
  // whoever set it last — a caller replacing `value`, a click, an insert that
@@ -388,7 +403,7 @@ let TextInput = (() => {
388
403
  }
389
404
  get cursorPosition() { return this._cursor; }
390
405
  set cursorPosition(p) { this._cursor = graphemeBoundary(this._value, p); }
391
- #placeholder_accessor_storage = (__runInitializers(this, __blinkFrom_extraInitializers), __runInitializers(this, _placeholder_initializers, void 0));
406
+ #placeholder_accessor_storage = (__runInitializers(this, __blink_extraInitializers), __runInitializers(this, _placeholder_initializers, void 0));
392
407
  get placeholder() { return this.#placeholder_accessor_storage; }
393
408
  set placeholder(value) { this.#placeholder_accessor_storage = value; }
394
409
  _maxLength = __runInitializers(this, _placeholder_extraInitializers);
@@ -468,7 +483,7 @@ let TextInput = (() => {
468
483
  this._edit(event);
469
484
  if (!event.stopped)
470
485
  return;
471
- this._blinkFrom = event.time;
486
+ this._blink = caretBlink(event.time);
472
487
  // An edit on the cursor's row moves no followed range, so the row is
473
488
  // brought into view here too: typing after the wheel scrolled away scrolls
474
489
  // back. The rows are the edited value's, at the width last drawn.
@@ -479,7 +494,7 @@ let TextInput = (() => {
479
494
  }
480
495
  handleFocus(event) {
481
496
  super.handleFocus(event);
482
- this._blinkFrom = event.time;
497
+ this._blink = caretBlink(event.time);
483
498
  }
484
499
  _edit(event) {
485
500
  if (this.disabled)
@@ -653,7 +668,7 @@ let TextInput = (() => {
653
668
  return;
654
669
  if (event.type !== "mouse_down")
655
670
  return;
656
- this._blinkFrom = event.time;
671
+ this._blink = caretBlink(event.time);
657
672
  // [LAW:no-silent-failure] Every cell the field draws carries its frame's
658
673
  // layout, so a press without one did not come off a frame it drew.
659
674
  const layout = layoutOn(event.cell);
@@ -1091,20 +1106,14 @@ let TextInput = (() => {
1091
1106
  return { lines: withArrows, layout: { drawn, kind: "rows", rows: visualRows, offset } };
1092
1107
  }
1093
1108
  // The caret's cell for the frame `options` draws: the blink restarted at the
1094
- // last touch, sampled at the frame's time (`shownAt`, so under reduced
1095
- // motion it holds lit). It runs away from the restart in either direction
1096
- // of time, so a timeline played backwards also finds it lit just after a
1097
- // key. Lit, the cell is the cursor's; dark, it is drawn as the
1098
- // text around it, since the cursor is a colour pair and no attribute hides
1099
- // it. The cell says when it next flips, which is when a host draws again.
1109
+ // last touch, placed as every animation is (`placed`), so it draws at the
1110
+ // frame's time, holds lit under reduced motion, and the cell says when it
1111
+ // next flips, which is when a host draws again. A print, drawn for no
1112
+ // moment, draws it at 0 like any placed animation. Lit, the cell is the
1113
+ // cursor's; dark, it is drawn as the text around it, since the cursor is a
1114
+ // colour pair and no attribute hides it.
1100
1115
  _caret(at, cursorStyle, contentStyle, options) {
1101
- const { frame } = options;
1102
- const blink = (time) => {
1103
- const shown = shownAt(Timeline.run(Timeline.play(this._blinkFrom, time < this._blinkFrom ? -1 : 1), CARET_BLINK), time, options);
1104
- return { lit: shown.value, hold: holdOf(shown, time) };
1105
- };
1106
- const { lit, hold } = frame === undefined ? CARET_UNTIMED : blink(frame.time);
1107
- return stampFrame([new Segment(at, lit ? cursorStyle : contentStyle)], hold);
1116
+ return placed(this._blink, options, (lit) => [new Segment(at, lit ? cursorStyle : contentStyle)]);
1108
1117
  }
1109
1118
  // Whether `rows` visual rows draw a scroll arrow in the last cell of a row.
1110
1119
  _drawsArrows(rows) {
@@ -80,10 +80,10 @@ let ThemedWidget = (() => {
80
80
  return new Style(ink(this.theme, "foreground", "background"));
81
81
  }
82
82
  // [LAW:one-source-of-truth] How every widget looks while disabled: the
83
- // palette's de-emphasized text on its ground. WCAG sets no contrast floor for
84
- // an inactive control, and this sits under the one for text on purpose.
83
+ // palette's disabled text on its ground. WCAG sets no contrast floor for an
84
+ // inactive control, and this sits under the one for text on purpose.
85
85
  get disabledInk() {
86
- return ink(this.theme, "foreground-muted", "background");
86
+ return ink(this.theme, "foreground-disabled", "background");
87
87
  }
88
88
  };
89
89
  })();
@@ -33,7 +33,7 @@ export declare class Toggle extends ThemedWidget {
33
33
  constructor(options: ToggleOptions);
34
34
  handleKey(event: KeyEvent): void;
35
35
  handleMouse(event: WidgetMouseEvent): void;
36
- protected draw(_options: RenderOptions): Iterable<Segment>;
36
+ protected draw(options: RenderOptions): Iterable<Segment>;
37
37
  measure(_options: RenderOptions): {
38
38
  minimum: number;
39
39
  maximum: number;
@@ -44,9 +44,9 @@ var __esDecorate = (this && this.__esDecorate) || function (ctor, descriptorIn,
44
44
  if (target) Object.defineProperty(target, contextIn.name, descriptor);
45
45
  done = true;
46
46
  };
47
+ import { labelled } from "../core/orient.js";
47
48
  import { action } from "mobx";
48
49
  import { observableRef } from "./observable.js";
49
- import { Segment } from "../core/segment.js";
50
50
  import { Style } from "../core/style.js";
51
51
  import { cellLen } from "../core/cells.js";
52
52
  import { ThemedWidget } from "./themed-widget.js";
@@ -137,16 +137,16 @@ let Toggle = (() => {
137
137
  }
138
138
  }
139
139
  // --- Rendering ---
140
- draw(_options) {
140
+ draw(options) {
141
141
  // Both indicators are exactly 5 cells: "[ON] " and "[OFF]".
142
142
  const indicator = this.on ? "[ON] " : "[OFF]";
143
- const text = `${indicator} ${this.label}`;
143
+ const drawn = (style) => labelled(`${indicator} `, this.label, "", style, options.textOrder);
144
144
  if (this.disabled) {
145
- return [new Segment(text, new Style(this.disabledInk))];
145
+ return drawn(new Style(this.disabledInk));
146
146
  }
147
147
  const keys = VARIANT_KEYS[this.variant];
148
148
  const colors = this.on ? ink(this.theme, keys.onFg, keys.onBg) : ink(this.theme, keys.offFg, keys.offBg);
149
- return [new Segment(text, new Style({ ...colors, underline: this.focused }))];
149
+ return drawn(new Style({ ...colors, underline: this.focused }));
150
150
  }
151
151
  measure(_options) {
152
152
  // [LAW:one-source-of-truth] cellLen — see button.ts.
@@ -5,7 +5,7 @@
5
5
  * producing Segment[] from current state. They have no knowledge of stdin,
6
6
  * terminal escape sequences, or their host environment.
7
7
  */
8
- import type { Renderable, Measurable, RenderOptions } from "../core/protocol.js";
8
+ import type { HostFrame, Renderable, Measurable, RenderOptions } from "../core/protocol.js";
9
9
  import type { Segment } from "../core/segment.js";
10
10
  import type { Anchor } from "../core/anchor.js";
11
11
  import type { Unsubscribe } from "../core/subscription.js";
@@ -71,6 +71,6 @@ export interface FocusManager {
71
71
  export interface FrameSource {
72
72
  readonly focusManager: FocusManager;
73
73
  readonly frame: readonly (readonly Segment[])[];
74
- readonly frameTime: number;
74
+ frameNow(): HostFrame;
75
75
  refresh(): void;
76
76
  }
@@ -26,7 +26,7 @@
26
26
  * hear the input.
27
27
  */
28
28
  import { Segment } from "../core/segment.js";
29
- import type { FrameHost, Presence } from "../core/protocol.js";
29
+ import type { HostFrame, FrameHost, Presence } from "../core/protocol.js";
30
30
  import type { Unsubscribe } from "../core/subscription.js";
31
31
  import type { Clock, FrameRate } from "../core/clock.js";
32
32
  import type { Timeline } from "../core/timeline.js";
@@ -72,8 +72,8 @@ export declare class WidgetApp implements FrameSource, FrameHost {
72
72
  private get widgets();
73
73
  /** The rows on screen now, as painted: what a pointer event lands on. */
74
74
  get frame(): readonly (readonly Segment[])[];
75
- /** The time a frame drawn now is drawn for, as `App.frameTime` reads it. */
76
- get frameTime(): number;
75
+ /** The frame this app draws now (`FrameHost`): the App's time, on a frame this app is the host of, as its frames say. */
76
+ frameNow(): HostFrame;
77
77
  /**
78
78
  * Take the terminal, paint the first frame, and route input to its widgets
79
79
  * until the app stops — `App.run`, with the input.
@@ -50,7 +50,7 @@ export class WidgetApp {
50
50
  // The view is drawn inside `compose`, where what it reads is tracked —
51
51
  // a function view asked there too — and when it changes is its own to
52
52
  // say, as it would be to the App.
53
- // Its frames are its own, drawn for its `frameTime`: what draws in them
53
+ // Its frames are its own, drawn for its `frameNow()`: what draws in them
54
54
  // is told this app is the host, not the App it paints through, so
55
55
  // `drawnBy: widgetApp` names the host its frames carry.
56
56
  this.app = new App({
@@ -65,7 +65,7 @@ export class WidgetApp {
65
65
  const owners = ownersOn(this.app.frame);
66
66
  return this.widgets.filter((widget) => owners.has(widget));
67
67
  },
68
- frameTime: () => this.frameTime,
68
+ frameTime: () => this.frameNow().time,
69
69
  });
70
70
  this.focusManager = this.focus;
71
71
  this.router = new EventRouter({ source: this, focusOnClick });
@@ -118,9 +118,9 @@ export class WidgetApp {
118
118
  get frame() {
119
119
  return this.app.frame;
120
120
  }
121
- /** The time a frame drawn now is drawn for, as `App.frameTime` reads it. */
122
- get frameTime() {
123
- return this.app.frameTime;
121
+ /** The frame this app draws now (`FrameHost`): the App's time, on a frame this app is the host of, as its frames say. */
122
+ frameNow() {
123
+ return { time: this.app.frameNow().time, host: this };
124
124
  }
125
125
  /**
126
126
  * Take the terminal, paint the first frame, and route input to its widgets
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@promptctl/rich-js",
3
- "version": "0.26.0",
3
+ "version": "0.28.0",
4
4
  "description": "Rich text and beautiful formatting in the terminal — a TypeScript port of Python's Rich",
5
5
  "repository": {
6
6
  "type": "git",
@@ -89,6 +89,7 @@
89
89
  "template-bindings": "node scripts/build-demos.ts && node dist-demo/examples/rich-template-bindings/main.js",
90
90
  "themes-and-color-studio": "node scripts/build-demos.ts && node dist-demo/examples/themes-and-color-studio/node.js",
91
91
  "terminal-host": "node scripts/build-demos.ts && node dist-demo/examples/terminal-host/main.js",
92
+ "terminal-colors": "node scripts/build-demos.ts && node dist-demo/examples/terminal-colors/index.js",
92
93
  "test:demos": "playwright test"
93
94
  },
94
95
  "keywords": [
@@ -123,14 +124,14 @@
123
124
  "@codemirror/view": "^6.43.13",
124
125
  "@lezer/highlight": "^1.2.5",
125
126
  "@playwright/test": "^1.63.0",
126
- "@promptctl/go-template-js": "^0.10.0",
127
+ "@promptctl/go-template-js": "0.12.0",
127
128
  "@types/markdown-it": "^14.2.0",
128
129
  "@types/node": "^26.5.1",
129
130
  "@types/semver": "^7.8.0",
130
131
  "@xterm/headless": "^6.0.0",
131
132
  "markdown-it": "^14.3.2",
132
133
  "markdown-it-container": "^4.0.0",
133
- "mobx": "^7.0.3",
134
+ "mobx": "7.0.3",
134
135
  "node-inspect-extracted": "^3.3.3",
135
136
  "semver": "^7.8.5",
136
137
  "strip-ansi": "^7.2.0",
@@ -141,7 +142,7 @@
141
142
  "vitest": "^5.0.0"
142
143
  },
143
144
  "peerDependencies": {
144
- "@promptctl/go-template-js": "^0.10.0",
145
+ "@promptctl/go-template-js": "^0.12.0",
145
146
  "mobx": "^7.0.3"
146
147
  },
147
148
  "peerDependenciesMeta": {