@textui/core 0.2.0 → 0.3.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.
package/dist/app/app.d.ts CHANGED
@@ -120,6 +120,34 @@ export declare class App implements TextUIApp {
120
120
  setRoot(node: ComponentNode): void;
121
121
  private requestRender;
122
122
  flush(): void;
123
+ /**
124
+ * Render until there is nothing left to render.
125
+ *
126
+ * `flush` forces one frame; this is the other question - *has it finished?* -
127
+ * and there was no way to ask it. What a program wanting one true frame did
128
+ * instead was guess: every example that writes a still ended with a sleep
129
+ * loop of four milliseconds times a number somebody tried until the picture
130
+ * looked right. Eight, mostly. Four in one, twelve in another. A number too
131
+ * small does not fail; it writes a half-drawn frame.
132
+ *
133
+ * A frame settles in more than one pass by design - an effect may mark
134
+ * something dirty, and a measurement changing runs the layout again - so the
135
+ * answer is a loop rather than a flag. Each turn yields to the task queue
136
+ * first, because what has not run yet cannot have marked anything.
137
+ *
138
+ * It returns as soon as a pass finds nothing pending, so an application that
139
+ * animates settles *between* its frames - which is what makes a still of one
140
+ * possible at all, and why the answer is not "has it stopped moving".
141
+ *
142
+ * `false` is the other thing: passes that kept producing work until the
143
+ * limit ran out, which is a render loop that does not converge - an effect
144
+ * with no dependency list setting the state it reads. Worth reporting rather
145
+ * than hanging on, and worth a number rather than a promise a caller can
146
+ * wait on for ever.
147
+ */
148
+ settled(options?: {
149
+ limit?: number;
150
+ }): Promise<boolean>;
123
151
  /**
124
152
  * The tree the frame renders: the shell, always, when one is registered.
125
153
  *
@@ -1 +1 @@
1
- {"version":3,"file":"app.d.ts","sourceRoot":"","sources":["../../src/app/app.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"app.d.ts","sourceRoot":"","sources":["../../src/app/app.ts"],"names":[],"mappings":"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"}
package/dist/app/app.js CHANGED
@@ -255,6 +255,20 @@ export class App {
255
255
  const shell = this.shells.get(id);
256
256
  if (shell?.theme && this.themes.get(shell.theme))
257
257
  this.setTheme(shell.theme);
258
+ // `root` reaches the screen two ways, and this is the moment it changes
259
+ // which. With no shell registered at boot it was never opened into `main` -
260
+ // `rootNode` wraps it directly, which is the path an application built out
261
+ // of primitives takes. A shell arriving afterwards makes `rootNode` return
262
+ // the shell instead, and the application's entire content was simply gone:
263
+ // a framed, themed, empty screen.
264
+ //
265
+ // `setRoot` has always handled both paths, and says why - "setting one and
266
+ // not the other works in exactly half of the programs that can exist". This
267
+ // is the other half of the same sentence. Opening the same key twice
268
+ // replaces the mount rather than stacking one, so no guard is needed.
269
+ if (this.options.root) {
270
+ this.surfaces.open({ surface: 'main', key: ROOT_KEY, target: this.options.root });
271
+ }
258
272
  this.buffer_.invalidate();
259
273
  this.requestRender(true);
260
274
  }
@@ -401,6 +415,44 @@ export class App {
401
415
  this.frameScheduled = false;
402
416
  this.renderFrame();
403
417
  }
418
+ /**
419
+ * Render until there is nothing left to render.
420
+ *
421
+ * `flush` forces one frame; this is the other question - *has it finished?* -
422
+ * and there was no way to ask it. What a program wanting one true frame did
423
+ * instead was guess: every example that writes a still ended with a sleep
424
+ * loop of four milliseconds times a number somebody tried until the picture
425
+ * looked right. Eight, mostly. Four in one, twelve in another. A number too
426
+ * small does not fail; it writes a half-drawn frame.
427
+ *
428
+ * A frame settles in more than one pass by design - an effect may mark
429
+ * something dirty, and a measurement changing runs the layout again - so the
430
+ * answer is a loop rather than a flag. Each turn yields to the task queue
431
+ * first, because what has not run yet cannot have marked anything.
432
+ *
433
+ * It returns as soon as a pass finds nothing pending, so an application that
434
+ * animates settles *between* its frames - which is what makes a still of one
435
+ * possible at all, and why the answer is not "has it stopped moving".
436
+ *
437
+ * `false` is the other thing: passes that kept producing work until the
438
+ * limit ran out, which is a render loop that does not converge - an effect
439
+ * with no dependency list setting the state it reads. Worth reporting rather
440
+ * than hanging on, and worth a number rather than a promise a caller can
441
+ * wait on for ever.
442
+ */
443
+ async settled(options = {}) {
444
+ const limit = options.limit ?? 100;
445
+ for (let i = 0; i < limit; i++) {
446
+ // Deliberately not `unref`'d: this timer is what keeps the process alive
447
+ // while a still is being rendered, and one that lets it exit would leave
448
+ // the await unresolved and the frame unwritten.
449
+ await new Promise((resolve) => setTimeout(resolve, 0));
450
+ if (!this.frameScheduled && !this.isDirty())
451
+ return true;
452
+ this.flush();
453
+ }
454
+ return false;
455
+ }
404
456
  /**
405
457
  * The tree the frame renders: the shell, always, when one is registered.
406
458
  *
@@ -1 +1 @@
1
- {"version":3,"file":"bindings.d.ts","sourceRoot":"","sources":["../../src/runtime/bindings.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,MAAM,EAAE,WAAW,EAAE,aAAa,EACnC,MAAM,mBAAmB,CAAC;AAC3B,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAIvD;;;;;;;GAOG;AACH,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,aAAa,CAAC;IACrB,2CAA2C;IAC3C,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,gCAAgC;IAChC,OAAO,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC;IAC7D,gCAAgC;IAChC,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,GAAG,IAAI,CAAC;IAC5C,oEAAoE;IACpE,KAAK,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;CACpB;AAsCD;;;;GAIG;AACH,wBAAgB,aAAa,CAC3B,GAAG,EAAE,cAAc,EACnB,MAAM,EAAE,MAAM,GAAG,CAAC,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,OAAO,CAAC,GAAG,SAAS,GAC7D,CAAC,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,OAAO,CAAC,GAAG,SAAS,CAW/C;AAED,gEAAgE;AAChE,wBAAgB,YAAY,CAAC,GAAG,EAAE,cAAc,EAAE,KAAK,EAAE,OAAO,GAAG,OAAO,CAkBzE;AAED;;;;;;;;;GASG;AACH,wBAAgB,YAAY,CAC1B,GAAG,EAAE,cAAc,EACnB,IAAI,EAAE,aAAa,GAClB,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAezB;AAOD,4EAA4E;AAC5E,wBAAgB,kBAAkB,CAChC,CAAC,EAAE,OAAO,GACT,CAAC,IAAI;IAAE,QAAQ,EAAE,aAAa,CAAC;IAAC,IAAI,EAAE,WAAW,CAAA;CAAE,CAMrD"}
1
+ {"version":3,"file":"bindings.d.ts","sourceRoot":"","sources":["../../src/runtime/bindings.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,MAAM,EAAE,WAAW,EAAE,aAAa,EACnC,MAAM,mBAAmB,CAAC;AAC3B,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAIvD;;;;;;;GAOG;AACH,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,aAAa,CAAC;IACrB,2CAA2C;IAC3C,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,gCAAgC;IAChC,OAAO,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC;IAC7D,gCAAgC;IAChC,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,GAAG,IAAI,CAAC;IAC5C,oEAAoE;IACpE,KAAK,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;CACpB;AAsCD;;;;GAIG;AACH,wBAAgB,aAAa,CAC3B,GAAG,EAAE,cAAc,EACnB,MAAM,EAAE,MAAM,GAAG,CAAC,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,OAAO,CAAC,GAAG,SAAS,GAC7D,CAAC,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,OAAO,CAAC,GAAG,SAAS,CAW/C;AAED,gEAAgE;AAChE,wBAAgB,YAAY,CAAC,GAAG,EAAE,cAAc,EAAE,KAAK,EAAE,OAAO,GAAG,OAAO,CA4CzE;AAED;;;;;;;;;GASG;AACH,wBAAgB,YAAY,CAC1B,GAAG,EAAE,cAAc,EACnB,IAAI,EAAE,aAAa,GAClB,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAezB;AAOD,4EAA4E;AAC5E,wBAAgB,kBAAkB,CAChC,CAAC,EAAE,OAAO,GACT,CAAC,IAAI;IAAE,QAAQ,EAAE,aAAa,CAAC;IAAC,IAAI,EAAE,WAAW,CAAA;CAAE,CAMrD"}
@@ -69,13 +69,40 @@ export function resolveValue(ctx, value) {
69
69
  return value;
70
70
  if (isAction(value))
71
71
  return value;
72
- if (Array.isArray(value))
73
- return value.map((v) => resolveValue(ctx, v));
72
+ /*
73
+ * The same array back when there was nothing in it to resolve.
74
+ *
75
+ * Identity is what the reconciler compares - a component whose props are
76
+ * all unchanged is not re-run, and neither is anything under it - so
77
+ * copying unconditionally made that test impossible to pass for exactly
78
+ * the props worth passing it for. A list of four hundred rows arrived as a
79
+ * new array on every pass, its holder re-rendered every frame whatever it
80
+ * had been told, and the memoisation callers wrote to prevent that could
81
+ * not reach this far.
82
+ *
83
+ * Copying at all is for the bindings: a `{ path }` inside an array has to
84
+ * become the value it names, and that is a different array. So the copy is
85
+ * kept and returned only when something in it actually changed.
86
+ */
87
+ if (Array.isArray(value)) {
88
+ let changed = false;
89
+ const items = value.map((v) => {
90
+ const resolved = resolveValue(ctx, v);
91
+ if (resolved !== v)
92
+ changed = true;
93
+ return resolved;
94
+ });
95
+ return changed ? items : value;
96
+ }
97
+ let changed = false;
74
98
  const out = {};
75
99
  for (const [k, v] of Object.entries(value)) {
76
- out[k] = resolveValue(ctx, v);
100
+ const resolved = resolveValue(ctx, v);
101
+ if (resolved !== v)
102
+ changed = true;
103
+ out[k] = resolved;
77
104
  }
78
- return out;
105
+ return changed ? out : value;
79
106
  }
80
107
  /**
81
108
  * Resolve every prop on a node. `component`, `id`, `key` and `$meta` are
@@ -274,8 +274,20 @@ export declare function useTicker(onTick: (frame: number, elapsedMs: number) =>
274
274
  fps?: number;
275
275
  enabled?: boolean;
276
276
  }): void;
277
- /** A frame counter, for spinners and marquees. Frozen when animation is off. */
278
- export declare function useFrame(fps?: number): number;
277
+ /**
278
+ * A frame counter, for spinners and marquees. Frozen when animation is off.
279
+ *
280
+ * `enabled` is not a convenience. A ticker is a standing invalidation - it
281
+ * marks its component dirty `fps` times a second for as long as it is
282
+ * mounted - so a component that animates only sometimes and calls this
283
+ * unconditionally keeps the whole application rendering while it sits still.
284
+ * That is invisible in a small tree and is the entire frame budget in a large
285
+ * one, which is the case nobody tests. Frozen at 0 while off, so a caret or a
286
+ * spinner drawn from it is steady rather than absent.
287
+ */
288
+ export declare function useFrame(fps?: number, options?: {
289
+ enabled?: boolean;
290
+ }): number;
279
291
  /** A value that eases towards its target. Snaps when animation is off. */
280
292
  export declare function useTween(target: number, durationMs?: number): number;
281
293
  export declare function useInterval(fn: () => void, ms: number, enabled?: boolean): void;
@@ -1 +1 @@
1
- {"version":3,"file":"hooks.d.ts","sourceRoot":"","sources":["../../src/runtime/hooks.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"hooks.d.ts","sourceRoot":"","sources":["../../src/runtime/hooks.ts"],"names":[],"mappings":"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"}
@@ -796,13 +796,24 @@ export function useTicker(onTick, options = {}) {
796
796
  return () => ticker.dispose();
797
797
  }, [enabled, options.fps]);
798
798
  }
799
- /** A frame counter, for spinners and marquees. Frozen when animation is off. */
800
- export function useFrame(fps = 10) {
799
+ /**
800
+ * A frame counter, for spinners and marquees. Frozen when animation is off.
801
+ *
802
+ * `enabled` is not a convenience. A ticker is a standing invalidation - it
803
+ * marks its component dirty `fps` times a second for as long as it is
804
+ * mounted - so a component that animates only sometimes and calls this
805
+ * unconditionally keeps the whole application rendering while it sits still.
806
+ * That is invisible in a small tree and is the entire frame budget in a large
807
+ * one, which is the case nobody tests. Frozen at 0 while off, so a caret or a
808
+ * spinner drawn from it is steady rather than absent.
809
+ */
810
+ export function useFrame(fps = 10, options = {}) {
801
811
  const instance = currentInstance();
802
812
  const [frame, setFrame] = useState(0);
803
813
  const disabled = instance.runtime.animation.disabled;
804
- useTicker(() => setFrame((f) => f + 1), { fps, enabled: !disabled });
805
- return disabled ? 0 : frame;
814
+ const running = (options.enabled ?? true) && !disabled;
815
+ useTicker(() => setFrame((f) => f + 1), { fps, enabled: running });
816
+ return running ? frame : 0;
806
817
  }
807
818
  /** A value that eases towards its target. Snaps when animation is off. */
808
819
  export function useTween(target, durationMs = 200) {
@@ -64,6 +64,21 @@ export interface TextUIApp extends Disposable {
64
64
  stop(): Promise<void>;
65
65
  /** Force a frame now, outside the scheduler. Tests and screenshots use it. */
66
66
  flush(): void;
67
+ /**
68
+ * Render until nothing is left to render, and answer whether it went quiet.
69
+ *
70
+ * The question `flush` cannot answer. A frame settles in more than one pass -
71
+ * an effect marks something dirty, a measurement runs the layout again - so a
72
+ * program that wants one true frame has to wait rather than force one.
73
+ *
74
+ * It returns as soon as a pass finds nothing pending, so an animating
75
+ * application settles between its frames. `false` means the passes kept
76
+ * producing work until the limit ran out - a render loop that does not
77
+ * converge, rather than one that is merely busy.
78
+ */
79
+ settled(options?: {
80
+ limit?: number;
81
+ }): Promise<boolean>;
67
82
  /** The last painted frame. */
68
83
  buffer(): CellBuffer;
69
84
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"app.d.ts","sourceRoot":"","sources":["../../src/types/app.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"app.d.ts","sourceRoot":"","sources":["../../src/types/app.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@textui/core",
3
- "version": "0.2.0",
3
+ "version": "0.3.0",
4
4
  "description": "Graph-mounted terminal UI runtime - store, registries, renderer, host primitives",
5
5
  "keywords": [
6
6
  "terminal",
package/src/app/app.ts CHANGED
@@ -304,6 +304,22 @@ export class App implements TextUIApp {
304
304
  this.store.set('$/layout/shell', id);
305
305
  const shell = this.shells.get(id);
306
306
  if (shell?.theme && this.themes.get(shell.theme)) this.setTheme(shell.theme);
307
+
308
+ // `root` reaches the screen two ways, and this is the moment it changes
309
+ // which. With no shell registered at boot it was never opened into `main` -
310
+ // `rootNode` wraps it directly, which is the path an application built out
311
+ // of primitives takes. A shell arriving afterwards makes `rootNode` return
312
+ // the shell instead, and the application's entire content was simply gone:
313
+ // a framed, themed, empty screen.
314
+ //
315
+ // `setRoot` has always handled both paths, and says why - "setting one and
316
+ // not the other works in exactly half of the programs that can exist". This
317
+ // is the other half of the same sentence. Opening the same key twice
318
+ // replaces the mount rather than stacking one, so no guard is needed.
319
+ if (this.options.root) {
320
+ this.surfaces.open({ surface: 'main', key: ROOT_KEY, target: this.options.root });
321
+ }
322
+
307
323
  this.buffer_.invalidate();
308
324
  this.requestRender(true);
309
325
  }
@@ -466,6 +482,44 @@ export class App implements TextUIApp {
466
482
  this.renderFrame();
467
483
  }
468
484
 
485
+ /**
486
+ * Render until there is nothing left to render.
487
+ *
488
+ * `flush` forces one frame; this is the other question - *has it finished?* -
489
+ * and there was no way to ask it. What a program wanting one true frame did
490
+ * instead was guess: every example that writes a still ended with a sleep
491
+ * loop of four milliseconds times a number somebody tried until the picture
492
+ * looked right. Eight, mostly. Four in one, twelve in another. A number too
493
+ * small does not fail; it writes a half-drawn frame.
494
+ *
495
+ * A frame settles in more than one pass by design - an effect may mark
496
+ * something dirty, and a measurement changing runs the layout again - so the
497
+ * answer is a loop rather than a flag. Each turn yields to the task queue
498
+ * first, because what has not run yet cannot have marked anything.
499
+ *
500
+ * It returns as soon as a pass finds nothing pending, so an application that
501
+ * animates settles *between* its frames - which is what makes a still of one
502
+ * possible at all, and why the answer is not "has it stopped moving".
503
+ *
504
+ * `false` is the other thing: passes that kept producing work until the
505
+ * limit ran out, which is a render loop that does not converge - an effect
506
+ * with no dependency list setting the state it reads. Worth reporting rather
507
+ * than hanging on, and worth a number rather than a promise a caller can
508
+ * wait on for ever.
509
+ */
510
+ async settled(options: { limit?: number } = {}): Promise<boolean> {
511
+ const limit = options.limit ?? 100;
512
+ for (let i = 0; i < limit; i++) {
513
+ // Deliberately not `unref`'d: this timer is what keeps the process alive
514
+ // while a still is being rendered, and one that lets it exit would leave
515
+ // the await unresolved and the frame unwritten.
516
+ await new Promise<void>((resolve) => setTimeout(resolve, 0));
517
+ if (!this.frameScheduled && !this.isDirty()) return true;
518
+ this.flush();
519
+ }
520
+ return false;
521
+ }
522
+
469
523
  /**
470
524
  * The tree the frame renders: the shell, always, when one is registered.
471
525
  *
@@ -94,13 +94,39 @@ export function resolveValue(ctx: ResolveContext, value: unknown): unknown {
94
94
  if (isComponentNode(value)) return value;
95
95
  if (isAction(value)) return value;
96
96
 
97
- if (Array.isArray(value)) return value.map((v) => resolveValue(ctx, v));
97
+ /*
98
+ * The same array back when there was nothing in it to resolve.
99
+ *
100
+ * Identity is what the reconciler compares - a component whose props are
101
+ * all unchanged is not re-run, and neither is anything under it - so
102
+ * copying unconditionally made that test impossible to pass for exactly
103
+ * the props worth passing it for. A list of four hundred rows arrived as a
104
+ * new array on every pass, its holder re-rendered every frame whatever it
105
+ * had been told, and the memoisation callers wrote to prevent that could
106
+ * not reach this far.
107
+ *
108
+ * Copying at all is for the bindings: a `{ path }` inside an array has to
109
+ * become the value it names, and that is a different array. So the copy is
110
+ * kept and returned only when something in it actually changed.
111
+ */
112
+ if (Array.isArray(value)) {
113
+ let changed = false;
114
+ const items = value.map((v) => {
115
+ const resolved = resolveValue(ctx, v);
116
+ if (resolved !== v) changed = true;
117
+ return resolved;
118
+ });
119
+ return changed ? items : value;
120
+ }
98
121
 
122
+ let changed = false;
99
123
  const out: Record<string, unknown> = {};
100
124
  for (const [k, v] of Object.entries(value as Record<string, unknown>)) {
101
- out[k] = resolveValue(ctx, v);
125
+ const resolved = resolveValue(ctx, v);
126
+ if (resolved !== v) changed = true;
127
+ out[k] = resolved;
102
128
  }
103
- return out;
129
+ return changed ? out : value;
104
130
  }
105
131
 
106
132
  /**
@@ -1001,14 +1001,25 @@ export function useTicker(
1001
1001
  }, [enabled, options.fps]);
1002
1002
  }
1003
1003
 
1004
- /** A frame counter, for spinners and marquees. Frozen when animation is off. */
1005
- export function useFrame(fps = 10): number {
1004
+ /**
1005
+ * A frame counter, for spinners and marquees. Frozen when animation is off.
1006
+ *
1007
+ * `enabled` is not a convenience. A ticker is a standing invalidation - it
1008
+ * marks its component dirty `fps` times a second for as long as it is
1009
+ * mounted - so a component that animates only sometimes and calls this
1010
+ * unconditionally keeps the whole application rendering while it sits still.
1011
+ * That is invisible in a small tree and is the entire frame budget in a large
1012
+ * one, which is the case nobody tests. Frozen at 0 while off, so a caret or a
1013
+ * spinner drawn from it is steady rather than absent.
1014
+ */
1015
+ export function useFrame(fps = 10, options: { enabled?: boolean } = {}): number {
1006
1016
  const instance = currentInstance();
1007
1017
  const [frame, setFrame] = useState(0);
1008
1018
  const disabled = instance.runtime.animation.disabled;
1019
+ const running = (options.enabled ?? true) && !disabled;
1009
1020
 
1010
- useTicker(() => setFrame((f) => f + 1), { fps, enabled: !disabled });
1011
- return disabled ? 0 : frame;
1021
+ useTicker(() => setFrame((f) => f + 1), { fps, enabled: running });
1022
+ return running ? frame : 0;
1012
1023
  }
1013
1024
 
1014
1025
  /** A value that eases towards its target. Snaps when animation is off. */
package/src/types/app.ts CHANGED
@@ -69,6 +69,19 @@ export interface TextUIApp extends Disposable {
69
69
  stop(): Promise<void>;
70
70
  /** Force a frame now, outside the scheduler. Tests and screenshots use it. */
71
71
  flush(): void;
72
+ /**
73
+ * Render until nothing is left to render, and answer whether it went quiet.
74
+ *
75
+ * The question `flush` cannot answer. A frame settles in more than one pass -
76
+ * an effect marks something dirty, a measurement runs the layout again - so a
77
+ * program that wants one true frame has to wait rather than force one.
78
+ *
79
+ * It returns as soon as a pass finds nothing pending, so an animating
80
+ * application settles between its frames. `false` means the passes kept
81
+ * producing work until the limit ran out - a render loop that does not
82
+ * converge, rather than one that is merely busy.
83
+ */
84
+ settled(options?: { limit?: number }): Promise<boolean>;
72
85
  /** The last painted frame. */
73
86
  buffer(): CellBuffer;
74
87