@flyingrobots/bijou 2.1.0 → 3.1.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 (157) hide show
  1. package/README.md +28 -20
  2. package/dist/adapters/test/clock.d.ts +36 -0
  3. package/dist/adapters/test/clock.d.ts.map +1 -0
  4. package/dist/adapters/test/clock.js +132 -0
  5. package/dist/adapters/test/clock.js.map +1 -0
  6. package/dist/adapters/test/index.d.ts +8 -1
  7. package/dist/adapters/test/index.d.ts.map +1 -1
  8. package/dist/adapters/test/index.js +24 -2
  9. package/dist/adapters/test/index.js.map +1 -1
  10. package/dist/adapters/test/io.d.ts +3 -0
  11. package/dist/adapters/test/io.d.ts.map +1 -1
  12. package/dist/adapters/test/io.js +5 -4
  13. package/dist/adapters/test/io.js.map +1 -1
  14. package/dist/adapters/test/runtime.d.ts +2 -0
  15. package/dist/adapters/test/runtime.d.ts.map +1 -1
  16. package/dist/adapters/test/runtime.js +1 -0
  17. package/dist/adapters/test/runtime.js.map +1 -1
  18. package/dist/core/ansi.d.ts +2 -0
  19. package/dist/core/ansi.d.ts.map +1 -1
  20. package/dist/core/ansi.js +2 -0
  21. package/dist/core/ansi.js.map +1 -1
  22. package/dist/core/clock.d.ts +12 -0
  23. package/dist/core/clock.d.ts.map +1 -0
  24. package/dist/core/clock.js +59 -0
  25. package/dist/core/clock.js.map +1 -0
  26. package/dist/core/components/alert-v3.d.ts +7 -0
  27. package/dist/core/components/alert-v3.d.ts.map +1 -0
  28. package/dist/core/components/alert-v3.js +37 -0
  29. package/dist/core/components/alert-v3.js.map +1 -0
  30. package/dist/core/components/alert.d.ts +4 -4
  31. package/dist/core/components/alert.d.ts.map +1 -1
  32. package/dist/core/components/alert.js +1 -1
  33. package/dist/core/components/alert.js.map +1 -1
  34. package/dist/core/components/badge.d.ts +6 -12
  35. package/dist/core/components/badge.d.ts.map +1 -1
  36. package/dist/core/components/badge.js +39 -24
  37. package/dist/core/components/badge.js.map +1 -1
  38. package/dist/core/components/bcss-style.d.ts +6 -0
  39. package/dist/core/components/bcss-style.d.ts.map +1 -0
  40. package/dist/core/components/bcss-style.js +44 -0
  41. package/dist/core/components/bcss-style.js.map +1 -0
  42. package/dist/core/components/box-v3.d.ts +17 -0
  43. package/dist/core/components/box-v3.d.ts.map +1 -0
  44. package/dist/core/components/box-v3.js +149 -0
  45. package/dist/core/components/box-v3.js.map +1 -0
  46. package/dist/core/components/box.d.ts +11 -4
  47. package/dist/core/components/box.d.ts.map +1 -1
  48. package/dist/core/components/box.js +37 -9
  49. package/dist/core/components/box.js.map +1 -1
  50. package/dist/core/components/index.d.ts +6 -0
  51. package/dist/core/components/index.d.ts.map +1 -1
  52. package/dist/core/components/index.js +4 -0
  53. package/dist/core/components/index.js.map +1 -1
  54. package/dist/core/components/log.d.ts.map +1 -1
  55. package/dist/core/components/log.js +6 -4
  56. package/dist/core/components/log.js.map +1 -1
  57. package/dist/core/components/overflow.d.ts +3 -0
  58. package/dist/core/components/overflow.d.ts.map +1 -0
  59. package/dist/core/components/overflow.js +33 -0
  60. package/dist/core/components/overflow.js.map +1 -0
  61. package/dist/core/components/progress.d.ts.map +1 -1
  62. package/dist/core/components/progress.js +3 -1
  63. package/dist/core/components/progress.js.map +1 -1
  64. package/dist/core/components/separator-v3.d.ts +7 -0
  65. package/dist/core/components/separator-v3.d.ts.map +1 -0
  66. package/dist/core/components/separator-v3.js +46 -0
  67. package/dist/core/components/separator-v3.js.map +1 -0
  68. package/dist/core/components/separator.d.ts +2 -4
  69. package/dist/core/components/separator.d.ts.map +1 -1
  70. package/dist/core/components/separator.js.map +1 -1
  71. package/dist/core/components/spinner.d.ts.map +1 -1
  72. package/dist/core/components/spinner.js +3 -1
  73. package/dist/core/components/spinner.js.map +1 -1
  74. package/dist/core/components/surface-text.d.ts +14 -0
  75. package/dist/core/components/surface-text.d.ts.map +1 -0
  76. package/dist/core/components/surface-text.js +95 -0
  77. package/dist/core/components/surface-text.js.map +1 -0
  78. package/dist/core/components/table-v3.d.ts +11 -0
  79. package/dist/core/components/table-v3.d.ts.map +1 -0
  80. package/dist/core/components/table-v3.js +148 -0
  81. package/dist/core/components/table-v3.js.map +1 -0
  82. package/dist/core/components/table.d.ts +2 -1
  83. package/dist/core/components/table.d.ts.map +1 -1
  84. package/dist/core/components/table.js +40 -11
  85. package/dist/core/components/table.js.map +1 -1
  86. package/dist/core/components/timer.d.ts.map +1 -1
  87. package/dist/core/components/timer.js +11 -9
  88. package/dist/core/components/timer.js.map +1 -1
  89. package/dist/core/components/types.d.ts +19 -0
  90. package/dist/core/components/types.d.ts.map +1 -0
  91. package/dist/core/components/types.js +2 -0
  92. package/dist/core/components/types.js.map +1 -0
  93. package/dist/core/layout/flex.d.ts +28 -0
  94. package/dist/core/layout/flex.d.ts.map +1 -0
  95. package/dist/core/layout/flex.js +126 -0
  96. package/dist/core/layout/flex.js.map +1 -0
  97. package/dist/core/render/differ.d.ts +49 -0
  98. package/dist/core/render/differ.d.ts.map +1 -0
  99. package/dist/core/render/differ.js +271 -0
  100. package/dist/core/render/differ.js.map +1 -0
  101. package/dist/core/runtime-viewport.d.ts +34 -0
  102. package/dist/core/runtime-viewport.d.ts.map +1 -0
  103. package/dist/core/runtime-viewport.js +74 -0
  104. package/dist/core/runtime-viewport.js.map +1 -0
  105. package/dist/core/text/index.d.ts +1 -0
  106. package/dist/core/text/index.d.ts.map +1 -1
  107. package/dist/core/text/index.js +1 -0
  108. package/dist/core/text/index.js.map +1 -1
  109. package/dist/core/text/wrap.d.ts +11 -0
  110. package/dist/core/text/wrap.d.ts.map +1 -0
  111. package/dist/core/text/wrap.js +90 -0
  112. package/dist/core/text/wrap.js.map +1 -0
  113. package/dist/core/theme/accessors.d.ts.map +1 -1
  114. package/dist/core/theme/accessors.js +21 -5
  115. package/dist/core/theme/accessors.js.map +1 -1
  116. package/dist/core/theme/graph-types.d.ts +58 -0
  117. package/dist/core/theme/graph-types.d.ts.map +1 -0
  118. package/dist/core/theme/graph-types.js +2 -0
  119. package/dist/core/theme/graph-types.js.map +1 -0
  120. package/dist/core/theme/graph.d.ts +27 -0
  121. package/dist/core/theme/graph.d.ts.map +1 -0
  122. package/dist/core/theme/graph.js +155 -0
  123. package/dist/core/theme/graph.js.map +1 -0
  124. package/dist/core/theme/index.d.ts +3 -0
  125. package/dist/core/theme/index.d.ts.map +1 -1
  126. package/dist/core/theme/index.js +2 -0
  127. package/dist/core/theme/index.js.map +1 -1
  128. package/dist/core/theme/resolve.d.ts +3 -0
  129. package/dist/core/theme/resolve.d.ts.map +1 -1
  130. package/dist/core/theme/resolve.js +3 -0
  131. package/dist/core/theme/resolve.js.map +1 -1
  132. package/dist/factory.d.ts +3 -0
  133. package/dist/factory.d.ts.map +1 -1
  134. package/dist/factory.js +8 -0
  135. package/dist/factory.js.map +1 -1
  136. package/dist/index.d.ts +10 -4
  137. package/dist/index.d.ts.map +1 -1
  138. package/dist/index.js +11 -3
  139. package/dist/index.js.map +1 -1
  140. package/dist/ports/clock.d.ts +29 -0
  141. package/dist/ports/clock.d.ts.map +1 -0
  142. package/dist/ports/clock.js +2 -0
  143. package/dist/ports/clock.js.map +1 -0
  144. package/dist/ports/context.d.ts +12 -0
  145. package/dist/ports/context.d.ts.map +1 -1
  146. package/dist/ports/index.d.ts +1 -0
  147. package/dist/ports/index.d.ts.map +1 -1
  148. package/dist/ports/index.js.map +1 -1
  149. package/dist/ports/io.d.ts +6 -0
  150. package/dist/ports/io.d.ts.map +1 -1
  151. package/dist/ports/runtime.d.ts +5 -0
  152. package/dist/ports/runtime.d.ts.map +1 -1
  153. package/dist/ports/surface.d.ts +152 -0
  154. package/dist/ports/surface.d.ts.map +1 -0
  155. package/dist/ports/surface.js +199 -0
  156. package/dist/ports/surface.js.map +1 -0
  157. package/package.json +2 -2
package/README.md CHANGED
@@ -1,16 +1,16 @@
1
1
  # @flyingrobots/bijou
2
2
 
3
- Themed terminal components for CLIs, loggers, and scripts — graceful degradation included.
3
+ The pure, zero-dependency core of Bijou.
4
4
 
5
- **Zero dependencies. Hexagonal architecture. Works everywhere.**
5
+ `@flyingrobots/bijou` is the degradation-first terminal toolkit in the Bijou stack. It contains components, prompts, themes, environment detection, test adapters, and the foundational `Surface` and `LayoutNode` primitives that the V3 runtime builds on.
6
6
 
7
- ## Documentation Status
7
+ ## What's New in v3.0.0
8
8
 
9
- This npm README is a quick overview and may lag behind the repository.
10
-
11
- - Canonical API details and usage live in [`GUIDE.md`](./GUIDE.md)
12
- - End-to-end examples live in [`/examples`](https://github.com/flyingrobots/bijou/tree/main/examples)
13
- - Release-level changes live in the [CHANGELOG](https://github.com/flyingrobots/bijou/blob/main/docs/CHANGELOG.md)
9
+ - **Truthful core/runtime split** the core package remains the right place for CLIs, prompts, logs, and portable terminal output, while `@flyingrobots/bijou-tui` owns the high-fidelity fullscreen runtime.
10
+ - **Surface primitives without abandoning strings** — V3 adds serious surface/layout infrastructure to the core package, but `3.0.0` does not pretend every component is now surface-native. String-oriented helpers remain first-class where they fit the toolkit identity.
11
+ - **Surface-first companions for common V3 chrome** — `boxSurface`, `headerBoxSurface`, `separatorSurface`, `alertSurface`, and `tableSurface` let runtime apps stay on the `Surface` path for the most common layout and status primitives.
12
+ - **Explicit compatibility boundaries** — when you mix surface-native helpers with legacy string APIs, you cross that seam explicitly with `surfaceToString(surface, ctx.style)`.
13
+ - **Same hexagonal core** — ports, themes, output-mode detection, and test adapters remain pure and dependency-free.
14
14
 
15
15
  ## Install
16
16
 
@@ -22,14 +22,21 @@ npm install @flyingrobots/bijou @flyingrobots/bijou-node
22
22
 
23
23
  ```typescript
24
24
  import { initDefaultContext } from '@flyingrobots/bijou-node';
25
- import { box, headerBox, gradientText, table } from '@flyingrobots/bijou';
25
+ import { badge, boxSurface, tableSurface } from '@flyingrobots/bijou';
26
26
 
27
27
  // Initialize Node.js adapters (auto-detects TTY, CI, NO_COLOR)
28
- initDefaultContext();
29
-
30
- // Use components
31
- console.log(headerBox('My CLI', { detail: 'v1.0.0' }));
32
- console.log(box('Hello, world!'));
28
+ const ctx = initDefaultContext();
29
+
30
+ const panel = boxSurface(
31
+ tableSurface({
32
+ columns: [{ header: 'Service' }, { header: 'Status' }],
33
+ rows: [['api', badge('LIVE', { variant: 'success', ctx })]],
34
+ ctx,
35
+ }),
36
+ { title: 'Runtime', padding: { top: 1, bottom: 1, left: 2, right: 2 }, ctx },
37
+ );
38
+
39
+ // Return `panel` from a V3 `view()` function or framed pane renderer.
33
40
  ```
34
41
 
35
42
  ## Features Breakdown
@@ -44,13 +51,13 @@ console.log(box('Hello, world!'));
44
51
  ## Components
45
52
 
46
53
  ### Layout
47
- `box()`, `headerBox()`, `separator()` — unicode box-drawing with automatic ASCII fallback.
54
+ `box()`, `headerBox()`, `separator()` plus `boxSurface()`, `headerBoxSurface()`, `separatorSurface()` legacy string helpers and V3-native surface companions for layout chrome.
48
55
 
49
56
  ### Elements
50
- `badge()`, `alert()`, `kbd()`, `skeleton()` — status indicators and UI primitives.
57
+ `badge()`, `alert()`, `alertSurface()`, `kbd()`, `skeleton()` — status indicators and UI primitives.
51
58
 
52
59
  ### Data
53
- `table()`, `tree()`, `accordion()`, `timeline()`, `dag()`, `dagSlice()`, `dagLayout()`, `dagStats()` — structured data display, DAG rendering with `DagSource` adapter, and graph statistics.
60
+ `table()`, `tableSurface()`, `tree()`, `accordion()`, `timeline()`, `dag()`, `dagSlice()`, `dagLayout()`, `dagStats()` — structured data display, DAG rendering with `DagSource` adapter, and graph statistics.
54
61
 
55
62
  ### Navigation
56
63
  `tabs()`, `breadcrumb()`, `stepper()`, `paginator()` — wayfinding components.
@@ -59,14 +66,14 @@ console.log(box('Hello, world!'));
59
66
  `spinner()`, `progressBar()`, `gradientText()` — live-updating output with color gradients.
60
67
 
61
68
  ### Forms
62
- `input()`, `select()`, `multiselect()`, `confirm()`, `group()`, `wizard()` — interactive prompts with validation that degrade to numbered-list selection in pipe/CI modes.
69
+ `input()`, `select()`, `multiselect()`, `confirm()`, `group()`, `wizard()`, `textarea()`, `filter()` — interactive prompts with validation that degrade to numbered-list selection in pipe/CI modes.
63
70
 
64
71
  ### Theme Engine
65
- DTCG (Design Tokens Community Group) interop. Built-in presets: `nord`, `catppuccin`, `cyan-magenta`. Load custom themes via `BIJOU_THEME` env var or `extendTheme()`.
72
+ DTCG (Design Tokens Community Group) interop. Built-in presets: `nord`, `catppuccin`, `cyan-magenta`, `teal-orange-pink`. Load custom themes via `BIJOU_THEME` env var or `extendTheme()`.
66
73
 
67
74
  ## Architecture
68
75
 
69
- bijou uses a Ports and Adapters (hexagonal) architecture. See [ARCHITECTURE.md](./ARCHITECTURE.md) for the full design.
76
+ bijou uses a Ports and Adapters (hexagonal) architecture. See [ARCHITECTURE.md](./ARCHITECTURE.md) for the package-level design and [`../../docs/ARCHITECTURE.md`](../../docs/ARCHITECTURE.md) for the monorepo-wide architecture.
70
77
 
71
78
  The core is pure TypeScript with zero runtime dependencies — all platform concerns flow through three ports:
72
79
 
@@ -99,6 +106,7 @@ const result = box('hello', { ctx });
99
106
  ```
100
107
 
101
108
  See [GUIDE.md](./GUIDE.md) for more on testing, theming, and component usage.
109
+ For upgrading existing apps, see the monorepo migration guide at [`../../docs/MIGRATING_TO_V3.md`](../../docs/MIGRATING_TO_V3.md).
102
110
 
103
111
  ## Related Packages
104
112
 
@@ -0,0 +1,36 @@
1
+ import type { ClockPort } from '../../ports/clock.js';
2
+ /**
3
+ * Configuration for {@link mockClock}.
4
+ */
5
+ export interface MockClockOptions {
6
+ /** Initial wall-clock time in milliseconds since the Unix epoch. */
7
+ nowMs?: number;
8
+ }
9
+ /**
10
+ * Deterministic in-memory clock for tests.
11
+ *
12
+ * Supports manual time advancement, interval/timeout scheduling, and queued
13
+ * microtasks without touching global timers.
14
+ */
15
+ export interface MockClock extends ClockPort {
16
+ /** Advance time and run all due timers/microtasks. */
17
+ advanceBy(ms: number): void;
18
+ /** Advance time while flushing native Promise continuations between timer chunks. */
19
+ advanceByAsync(ms: number): Promise<void>;
20
+ /** Run all queued microtasks without advancing wall-clock time. */
21
+ flushMicrotasks(): void;
22
+ /**
23
+ * Run all currently scheduled non-recurring timers to completion.
24
+ *
25
+ * Throws when an interval remains active after being given a chance to run,
26
+ * because recurring timers cannot be drained to completion automatically.
27
+ */
28
+ runAll(): void;
29
+ }
30
+ /**
31
+ * Create a deterministic {@link ClockPort} for unit and integration tests.
32
+ *
33
+ * The returned clock is manually driven through `advanceBy()` and `runAll()`.
34
+ */
35
+ export declare function mockClock(options?: MockClockOptions): MockClock;
36
+ //# sourceMappingURL=clock.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"clock.d.ts","sourceRoot":"","sources":["../../../src/adapters/test/clock.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAGtD;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,oEAAoE;IACpE,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAUD;;;;;GAKG;AACH,MAAM,WAAW,SAAU,SAAQ,SAAS;IAC1C,sDAAsD;IACtD,SAAS,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,qFAAqF;IACrF,cAAc,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1C,mEAAmE;IACnE,eAAe,IAAI,IAAI,CAAC;IACxB;;;;;OAKG;IACH,MAAM,IAAI,IAAI,CAAC;CAChB;AAOD;;;;GAIG;AACH,wBAAgB,SAAS,CAAC,OAAO,GAAE,gBAAqB,GAAG,SAAS,CAsInE"}
@@ -0,0 +1,132 @@
1
+ function normalizeDelay(ms) {
2
+ if (!Number.isFinite(ms))
3
+ return 0;
4
+ return Math.max(0, Math.floor(ms));
5
+ }
6
+ /**
7
+ * Create a deterministic {@link ClockPort} for unit and integration tests.
8
+ *
9
+ * The returned clock is manually driven through `advanceBy()` and `runAll()`.
10
+ */
11
+ export function mockClock(options = {}) {
12
+ let nowMs = options.nowMs ?? 0;
13
+ let nextId = 1;
14
+ const microtasks = [];
15
+ const tasks = [];
16
+ function sortTasks() {
17
+ tasks.sort((a, b) => a.at - b.at || a.id - b.id);
18
+ }
19
+ function disposeTask(id) {
20
+ const task = tasks.find((candidate) => candidate.id === id);
21
+ if (task) {
22
+ task.disposed = true;
23
+ }
24
+ }
25
+ function createHandle(id) {
26
+ return {
27
+ dispose() {
28
+ disposeTask(id);
29
+ },
30
+ };
31
+ }
32
+ function runQueuedMicrotasks() {
33
+ while (microtasks.length > 0) {
34
+ const pending = microtasks.splice(0, microtasks.length);
35
+ for (const callback of pending) {
36
+ callback();
37
+ }
38
+ }
39
+ }
40
+ function runNextTask(targetMs) {
41
+ sortTasks();
42
+ const next = tasks.find((task) => !task.disposed && task.at <= targetMs);
43
+ if (next === undefined)
44
+ return false;
45
+ nowMs = next.at;
46
+ if (next.intervalMs === null) {
47
+ next.disposed = true;
48
+ }
49
+ else {
50
+ next.at = nowMs + next.intervalMs;
51
+ }
52
+ next.callback();
53
+ runQueuedMicrotasks();
54
+ return true;
55
+ }
56
+ return {
57
+ now() {
58
+ return nowMs;
59
+ },
60
+ date(ms) {
61
+ return new Date(ms ?? nowMs);
62
+ },
63
+ setTimeout(callback, ms) {
64
+ const id = nextId++;
65
+ tasks.push({
66
+ id,
67
+ at: nowMs + normalizeDelay(ms),
68
+ callback,
69
+ intervalMs: null,
70
+ disposed: false,
71
+ });
72
+ sortTasks();
73
+ return createHandle(id);
74
+ },
75
+ setInterval(callback, ms) {
76
+ const intervalMs = Math.max(1, normalizeDelay(ms));
77
+ const id = nextId++;
78
+ tasks.push({
79
+ id,
80
+ at: nowMs + intervalMs,
81
+ callback,
82
+ intervalMs,
83
+ disposed: false,
84
+ });
85
+ sortTasks();
86
+ return createHandle(id);
87
+ },
88
+ queueMicrotask(callback) {
89
+ microtasks.push(callback);
90
+ },
91
+ advanceBy(ms) {
92
+ const targetMs = nowMs + normalizeDelay(ms);
93
+ runQueuedMicrotasks();
94
+ while (runNextTask(targetMs)) {
95
+ // Keep draining until there are no more timers due at or before targetMs.
96
+ }
97
+ nowMs = targetMs;
98
+ runQueuedMicrotasks();
99
+ },
100
+ async advanceByAsync(ms) {
101
+ const targetMs = nowMs + normalizeDelay(ms);
102
+ await Promise.resolve();
103
+ while (nowMs < targetMs) {
104
+ sortTasks();
105
+ const next = tasks.find((task) => !task.disposed && task.at <= targetMs);
106
+ const nextAt = next?.at ?? Math.min(targetMs, nowMs + 1);
107
+ this.advanceBy(Math.max(0, nextAt - nowMs));
108
+ await Promise.resolve();
109
+ }
110
+ await Promise.resolve();
111
+ },
112
+ flushMicrotasks() {
113
+ runQueuedMicrotasks();
114
+ },
115
+ runAll() {
116
+ runQueuedMicrotasks();
117
+ while (true) {
118
+ sortTasks();
119
+ const next = tasks.find((task) => !task.disposed);
120
+ if (next === undefined)
121
+ break;
122
+ this.advanceBy(Math.max(0, next.at - nowMs));
123
+ sortTasks();
124
+ const remaining = tasks.filter((task) => !task.disposed);
125
+ if (remaining.length > 0 && remaining.every((task) => task.intervalMs !== null)) {
126
+ throw new Error('mockClock.runAll() cannot drain active interval timers; dispose them or advance time manually.');
127
+ }
128
+ }
129
+ },
130
+ };
131
+ }
132
+ //# sourceMappingURL=clock.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"clock.js","sourceRoot":"","sources":["../../../src/adapters/test/clock.ts"],"names":[],"mappings":"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"}
@@ -11,10 +11,13 @@ import type { BijouContext } from '../../ports/context.js';
11
11
  import type { OutputMode, ColorScheme } from '../../core/detect/tty.js';
12
12
  import { type MockRuntimeOptions } from './runtime.js';
13
13
  import { type MockIOOptions, type MockIO } from './io.js';
14
+ import { type MockClockOptions, type MockClock } from './clock.js';
15
+ import type { ClockPort } from '../../ports/clock.js';
14
16
  import type { StylePort } from '../../ports/style.js';
15
17
  import type { Theme } from '../../core/theme/tokens.js';
16
18
  export { mockRuntime, type MockRuntimeOptions } from './runtime.js';
17
19
  export { mockIO, type MockIOOptions, type MockIO } from './io.js';
20
+ export { mockClock, type MockClockOptions, type MockClock } from './clock.js';
18
21
  export { plainStyle } from './style.js';
19
22
  export { auditStyle, type StyledCall, type AuditStylePort } from './audit-style.js';
20
23
  export { expectNoAnsi, expectNoAnsiSgr, expectContainsAnsi, expectHiddenCursor, expectShownCursor, expectWritten, } from './assertions.js';
@@ -30,6 +33,8 @@ export interface TestContextOptions {
30
33
  io?: MockIOOptions;
31
34
  /** Theme to resolve. Defaults to `CYAN_MAGENTA`. */
32
35
  theme?: Theme;
36
+ /** Clock override for deterministic time/scheduling. */
37
+ clock?: MockClockOptions | MockClock | ClockPort;
33
38
  /** Output mode. Defaults to `'interactive'`. */
34
39
  mode?: OutputMode;
35
40
  /** Whether to strip color from the resolved theme. Defaults to `false`. */
@@ -52,7 +57,9 @@ export interface TestContext extends BijouContext {
52
57
  *
53
58
  * Assemble a {@link mockRuntime}, {@link mockIO}, and {@link plainStyle}
54
59
  * together with a resolved theme so tests can exercise bijou components
55
- * without touching real terminals or filesystems.
60
+ * without touching real terminals or filesystems. When a clock override is
61
+ * provided, the same scheduler is threaded through the mock I/O adapter so
62
+ * interactive runtime tests can stay fully deterministic.
56
63
  *
57
64
  * @param options - Optional overrides for runtime, I/O, theme, mode, and color.
58
65
  * @returns A {@link TestContext} ready for use in tests.
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/adapters/test/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAC3D,OAAO,KAAK,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AACxE,OAAO,EAAe,KAAK,kBAAkB,EAAE,MAAM,cAAc,CAAC;AACpE,OAAO,EAAU,KAAK,aAAa,EAAE,KAAK,MAAM,EAAE,MAAM,SAAS,CAAC;AAClE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAKtD,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,4BAA4B,CAAC;AAExD,OAAO,EAAE,WAAW,EAAE,KAAK,kBAAkB,EAAE,MAAM,cAAc,CAAC;AACpE,OAAO,EAAE,MAAM,EAAE,KAAK,aAAa,EAAE,KAAK,MAAM,EAAE,MAAM,SAAS,CAAC;AAClE,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AACxC,OAAO,EAAE,UAAU,EAAE,KAAK,UAAU,EAAE,KAAK,cAAc,EAAE,MAAM,kBAAkB,CAAC;AACpF,OAAO,EACL,YAAY,EACZ,eAAe,EACf,kBAAkB,EAClB,kBAAkB,EAClB,iBAAiB,EACjB,aAAa,GACd,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAC3E,OAAO,EAAE,8BAA8B,EAAE,MAAM,kBAAkB,CAAC;AAElE;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,sEAAsE;IACtE,OAAO,CAAC,EAAE,kBAAkB,CAAC;IAC7B,wEAAwE;IACxE,EAAE,CAAC,EAAE,aAAa,CAAC;IACnB,oDAAoD;IACpD,KAAK,CAAC,EAAE,KAAK,CAAC;IACd,gDAAgD;IAChD,IAAI,CAAC,EAAE,UAAU,CAAC;IAClB,2EAA2E;IAC3E,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,0EAA0E;IAC1E,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,8DAA8D;IAC9D,KAAK,CAAC,EAAE,SAAS,CAAC;CACnB;AAED;;;GAGG;AACH,MAAM,WAAW,WAAY,SAAQ,YAAY;IAC/C,0DAA0D;IAC1D,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;CACrB;AAED;;;;;;;;;GASG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,GAAE,kBAAuB,GAAG,WAAW,CAe/E"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/adapters/test/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAC3D,OAAO,KAAK,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AACxE,OAAO,EAAe,KAAK,kBAAkB,EAAE,MAAM,cAAc,CAAC;AACpE,OAAO,EAAU,KAAK,aAAa,EAAE,KAAK,MAAM,EAAE,MAAM,SAAS,CAAC;AAClE,OAAO,EAAa,KAAK,gBAAgB,EAAE,KAAK,SAAS,EAAE,MAAM,YAAY,CAAC;AAC9E,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAOtD,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,4BAA4B,CAAC;AAGxD,OAAO,EAAE,WAAW,EAAE,KAAK,kBAAkB,EAAE,MAAM,cAAc,CAAC;AACpE,OAAO,EAAE,MAAM,EAAE,KAAK,aAAa,EAAE,KAAK,MAAM,EAAE,MAAM,SAAS,CAAC;AAClE,OAAO,EAAE,SAAS,EAAE,KAAK,gBAAgB,EAAE,KAAK,SAAS,EAAE,MAAM,YAAY,CAAC;AAC9E,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AACxC,OAAO,EAAE,UAAU,EAAE,KAAK,UAAU,EAAE,KAAK,cAAc,EAAE,MAAM,kBAAkB,CAAC;AACpF,OAAO,EACL,YAAY,EACZ,eAAe,EACf,kBAAkB,EAClB,kBAAkB,EAClB,iBAAiB,EACjB,aAAa,GACd,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAC3E,OAAO,EAAE,8BAA8B,EAAE,MAAM,kBAAkB,CAAC;AAElE;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,sEAAsE;IACtE,OAAO,CAAC,EAAE,kBAAkB,CAAC;IAC7B,wEAAwE;IACxE,EAAE,CAAC,EAAE,aAAa,CAAC;IACnB,oDAAoD;IACpD,KAAK,CAAC,EAAE,KAAK,CAAC;IACd,wDAAwD;IACxD,KAAK,CAAC,EAAE,gBAAgB,GAAG,SAAS,GAAG,SAAS,CAAC;IACjD,gDAAgD;IAChD,IAAI,CAAC,EAAE,UAAU,CAAC;IAClB,2EAA2E;IAC3E,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,0EAA0E;IAC1E,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,8DAA8D;IAC9D,KAAK,CAAC,EAAE,SAAS,CAAC;CACnB;AASD;;;GAGG;AACH,MAAM,WAAW,WAAY,SAAQ,YAAY;IAC/C,0DAA0D;IAC1D,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;CACrB;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,GAAE,kBAAuB,GAAG,WAAW,CAyB/E"}
@@ -1,38 +1,60 @@
1
1
  import { mockRuntime } from './runtime.js';
2
2
  import { mockIO } from './io.js';
3
+ import { mockClock } from './clock.js';
3
4
  import { plainStyle } from './style.js';
4
5
  import { createResolved } from '../../core/theme/resolve.js';
5
6
  import { CYAN_MAGENTA } from '../../core/theme/presets.js';
6
7
  import { createThemeAccessors } from '../../core/theme/accessors.js';
8
+ import { createTokenGraph } from '../../core/theme/graph.js';
9
+ import { systemClock } from '../../core/clock.js';
7
10
  export { mockRuntime } from './runtime.js';
8
11
  export { mockIO } from './io.js';
12
+ export { mockClock } from './clock.js';
9
13
  export { plainStyle } from './style.js';
10
14
  export { auditStyle } from './audit-style.js';
11
15
  export { expectNoAnsi, expectNoAnsiSgr, expectContainsAnsi, expectHiddenCursor, expectShownCursor, expectWritten, } from './assertions.js';
12
16
  export { COLOR_OPTIONS, FRUIT_OPTIONS, MANY_OPTIONS } from './fixtures.js';
13
17
  export { _resetDefaultContextForTesting } from '../../context.js';
18
+ function isClockPort(value) {
19
+ return typeof value === 'object'
20
+ && value !== null
21
+ && 'now' in value
22
+ && typeof value.now === 'function';
23
+ }
14
24
  /**
15
25
  * Create a fully-wired {@link BijouContext} for unit and integration tests.
16
26
  *
17
27
  * Assemble a {@link mockRuntime}, {@link mockIO}, and {@link plainStyle}
18
28
  * together with a resolved theme so tests can exercise bijou components
19
- * without touching real terminals or filesystems.
29
+ * without touching real terminals or filesystems. When a clock override is
30
+ * provided, the same scheduler is threaded through the mock I/O adapter so
31
+ * interactive runtime tests can stay fully deterministic.
20
32
  *
21
33
  * @param options - Optional overrides for runtime, I/O, theme, mode, and color.
22
34
  * @returns A {@link TestContext} ready for use in tests.
23
35
  */
24
36
  export function createTestContext(options = {}) {
25
37
  const runtime = mockRuntime(options.runtime);
26
- const io = mockIO(options.io);
38
+ const requestedClock = options.clock ?? options.io?.clock;
39
+ const clock = requestedClock === undefined
40
+ ? systemClock()
41
+ : (isClockPort(requestedClock) ? requestedClock : mockClock(requestedClock));
42
+ const io = mockIO(options.io?.clock === undefined
43
+ ? { ...(options.io ?? {}), clock }
44
+ : options.io);
27
45
  const style = options.style ?? plainStyle();
28
46
  const theme = createResolved(options.theme ?? CYAN_MAGENTA, options.noColor ?? false, options.colorScheme ?? 'dark');
47
+ const tokenGraph = createTokenGraph((options.theme ?? CYAN_MAGENTA));
29
48
  const mode = options.mode ?? 'interactive';
30
49
  return {
31
50
  theme,
32
51
  mode,
33
52
  runtime,
34
53
  io,
54
+ clock,
35
55
  style,
56
+ tokenGraph,
57
+ resolveBCSS: () => ({}),
36
58
  ...createThemeAccessors(theme),
37
59
  };
38
60
  }
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/adapters/test/index.ts"],"names":[],"mappings":"AAWA,OAAO,EAAE,WAAW,EAA2B,MAAM,cAAc,CAAC;AACpE,OAAO,EAAE,MAAM,EAAmC,MAAM,SAAS,CAAC;AAElE,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AACxC,OAAO,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAC7D,OAAO,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAC3D,OAAO,EAAE,oBAAoB,EAAE,MAAM,+BAA+B,CAAC;AAGrE,OAAO,EAAE,WAAW,EAA2B,MAAM,cAAc,CAAC;AACpE,OAAO,EAAE,MAAM,EAAmC,MAAM,SAAS,CAAC;AAClE,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AACxC,OAAO,EAAE,UAAU,EAAwC,MAAM,kBAAkB,CAAC;AACpF,OAAO,EACL,YAAY,EACZ,eAAe,EACf,kBAAkB,EAClB,kBAAkB,EAClB,iBAAiB,EACjB,aAAa,GACd,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAC3E,OAAO,EAAE,8BAA8B,EAAE,MAAM,kBAAkB,CAAC;AA+BlE;;;;;;;;;GASG;AACH,MAAM,UAAU,iBAAiB,CAAC,UAA8B,EAAE;IAChE,MAAM,OAAO,GAAG,WAAW,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;IAC7C,MAAM,EAAE,GAAG,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IAC9B,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,IAAI,UAAU,EAAE,CAAC;IAC5C,MAAM,KAAK,GAAG,cAAc,CAAC,OAAO,CAAC,KAAK,IAAI,YAAY,EAAE,OAAO,CAAC,OAAO,IAAI,KAAK,EAAE,OAAO,CAAC,WAAW,IAAI,MAAM,CAAC,CAAC;IACrH,MAAM,IAAI,GAAe,OAAO,CAAC,IAAI,IAAI,aAAa,CAAC;IAEvD,OAAO;QACL,KAAK;QACL,IAAI;QACJ,OAAO;QACP,EAAE;QACF,KAAK;QACL,GAAG,oBAAoB,CAAC,KAAK,CAAC;KAC/B,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/adapters/test/index.ts"],"names":[],"mappings":"AAWA,OAAO,EAAE,WAAW,EAA2B,MAAM,cAAc,CAAC;AACpE,OAAO,EAAE,MAAM,EAAmC,MAAM,SAAS,CAAC;AAClE,OAAO,EAAE,SAAS,EAAyC,MAAM,YAAY,CAAC;AAG9E,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AACxC,OAAO,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAC7D,OAAO,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAC3D,OAAO,EAAE,oBAAoB,EAAE,MAAM,+BAA+B,CAAC;AACrE,OAAO,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAG7D,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAElD,OAAO,EAAE,WAAW,EAA2B,MAAM,cAAc,CAAC;AACpE,OAAO,EAAE,MAAM,EAAmC,MAAM,SAAS,CAAC;AAClE,OAAO,EAAE,SAAS,EAAyC,MAAM,YAAY,CAAC;AAC9E,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AACxC,OAAO,EAAE,UAAU,EAAwC,MAAM,kBAAkB,CAAC;AACpF,OAAO,EACL,YAAY,EACZ,eAAe,EACf,kBAAkB,EAClB,kBAAkB,EAClB,iBAAiB,EACjB,aAAa,GACd,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAC3E,OAAO,EAAE,8BAA8B,EAAE,MAAM,kBAAkB,CAAC;AAwBlE,SAAS,WAAW,CAAC,KAA2D;IAC9E,OAAO,OAAO,KAAK,KAAK,QAAQ;WAC3B,KAAK,KAAK,IAAI;WACd,KAAK,IAAI,KAAK;WACd,OAAO,KAAK,CAAC,GAAG,KAAK,UAAU,CAAC;AACvC,CAAC;AAWD;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,iBAAiB,CAAC,UAA8B,EAAE;IAChE,MAAM,OAAO,GAAG,WAAW,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;IAC7C,MAAM,cAAc,GAAG,OAAO,CAAC,KAAK,IAAI,OAAO,CAAC,EAAE,EAAE,KAAK,CAAC;IAC1D,MAAM,KAAK,GAAG,cAAc,KAAK,SAAS;QACxC,CAAC,CAAC,WAAW,EAAE;QACf,CAAC,CAAC,CAAC,WAAW,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,SAAS,CAAC,cAAc,CAAC,CAAC,CAAC;IAC/E,MAAM,EAAE,GAAG,MAAM,CAAC,OAAO,CAAC,EAAE,EAAE,KAAK,KAAK,SAAS;QAC/C,CAAC,CAAC,EAAE,GAAG,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE;QAClC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IAChB,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,IAAI,UAAU,EAAE,CAAC;IAC5C,MAAM,KAAK,GAAG,cAAc,CAAC,OAAO,CAAC,KAAK,IAAI,YAAY,EAAE,OAAO,CAAC,OAAO,IAAI,KAAK,EAAE,OAAO,CAAC,WAAW,IAAI,MAAM,CAAC,CAAC;IACrH,MAAM,UAAU,GAAG,gBAAgB,CAAC,CAAC,OAAO,CAAC,KAAK,IAAI,YAAY,CAAgC,CAAC,CAAC;IACpG,MAAM,IAAI,GAAe,OAAO,CAAC,IAAI,IAAI,aAAa,CAAC;IAEvD,OAAO;QACL,KAAK;QACL,IAAI;QACJ,OAAO;QACP,EAAE;QACF,KAAK;QACL,KAAK;QACL,UAAU;QACV,WAAW,EAAE,GAAG,EAAE,CAAC,CAAC,EAAE,CAAC;QACvB,GAAG,oBAAoB,CAAC,KAAK,CAAC;KAC/B,CAAC;AACJ,CAAC"}
@@ -1,3 +1,4 @@
1
+ import type { ClockPort } from '../../ports/clock.js';
1
2
  import type { IOPort } from '../../ports/io.js';
2
3
  /**
3
4
  * Configuration for {@link mockIO}.
@@ -7,6 +8,8 @@ export interface MockIOOptions {
7
8
  answers?: string[];
8
9
  /** Pre-loaded keypress strings delivered by {@link MockIO.rawInput} via microtasks. */
9
10
  keys?: string[];
11
+ /** Clock override for deterministic timer and microtask scheduling in tests. */
12
+ clock?: ClockPort;
10
13
  /** Virtual filesystem entries (path to content) for {@link MockIO.readFile}. */
11
14
  files?: Record<string, string>;
12
15
  /** Virtual directory listings (path to entries) for {@link MockIO.readDir}. */
@@ -1 +1 @@
1
- {"version":3,"file":"io.d.ts","sourceRoot":"","sources":["../../../src/adapters/test/io.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAA+B,MAAM,mBAAmB,CAAC;AAG7E;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,4EAA4E;IAC5E,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,uFAAuF;IACvF,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,gFAAgF;IAChF,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC/B,+EAA+E;IAC/E,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;CACjC;AAED;;;;;GAKG;AACH,MAAM,WAAW,MAAO,SAAQ,MAAM;IACpC,yFAAyF;IACzF,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,gDAAgD;IAChD,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,mEAAmE;IACnE,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,2DAA2D;IAC3D,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC9B,iEAAiE;IACjE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;CAChC;AAED;;;;;;;;;GASG;AACH,wBAAgB,MAAM,CAAC,OAAO,GAAE,aAAkB,GAAG,MAAM,CAiH1D"}
1
+ {"version":3,"file":"io.d.ts","sourceRoot":"","sources":["../../../src/adapters/test/io.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,KAAK,EAAE,MAAM,EAA+B,MAAM,mBAAmB,CAAC;AAI7E;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,4EAA4E;IAC5E,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,uFAAuF;IACvF,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,gFAAgF;IAChF,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,gFAAgF;IAChF,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC/B,+EAA+E;IAC/E,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;CACjC;AAED;;;;;GAKG;AACH,MAAM,WAAW,MAAO,SAAQ,MAAM;IACpC,yFAAyF;IACzF,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,gDAAgD;IAChD,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,mEAAmE;IACnE,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,2DAA2D;IAC3D,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC9B,iEAAiE;IACjE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;CAChC;AAED;;;;;;;;;GASG;AACH,wBAAgB,MAAM,CAAC,OAAO,GAAE,aAAkB,GAAG,MAAM,CAiH1D"}
@@ -1,3 +1,4 @@
1
+ import { resolveClock } from '../../core/clock.js';
1
2
  import { join } from 'path';
2
3
  /**
3
4
  * Create an in-memory {@link IOPort} for tests.
@@ -15,6 +16,7 @@ export function mockIO(options = {}) {
15
16
  const answerQueue = [...(options.answers ?? [])];
16
17
  const files = { ...(options.files ?? {}) };
17
18
  const dirs = { ...(options.dirs ?? {}) };
19
+ const clock = resolveClock(options.clock);
18
20
  return {
19
21
  written,
20
22
  writtenErr,
@@ -63,9 +65,9 @@ export function mockIO(options = {}) {
63
65
  const key = keyQueue.shift();
64
66
  onKey(key);
65
67
  if (keyQueue.length > 0)
66
- queueMicrotask(deliver);
68
+ clock.queueMicrotask(deliver);
67
69
  }
68
- queueMicrotask(deliver);
70
+ clock.queueMicrotask(deliver);
69
71
  return { dispose() { disposed = true; } };
70
72
  },
71
73
  /**
@@ -83,8 +85,7 @@ export function mockIO(options = {}) {
83
85
  * @returns A handle whose `dispose()` cancels the timer.
84
86
  */
85
87
  setInterval(callback, ms) {
86
- const id = globalThis.setInterval(callback, ms);
87
- return { dispose() { clearInterval(id); } };
88
+ return clock.setInterval(callback, ms);
88
89
  },
89
90
  /**
90
91
  * Read a file from the virtual filesystem.
@@ -1 +1 @@
1
- {"version":3,"file":"io.js","sourceRoot":"","sources":["../../../src/adapters/test/io.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAmC5B;;;;;;;;;GASG;AACH,MAAM,UAAU,MAAM,CAAC,UAAyB,EAAE;IAChD,MAAM,OAAO,GAAa,EAAE,CAAC;IAC7B,MAAM,UAAU,GAAa,EAAE,CAAC;IAChC,MAAM,WAAW,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC,CAAC;IACjD,MAAM,KAAK,GAAG,EAAE,GAAG,CAAC,OAAO,CAAC,KAAK,IAAI,EAAE,CAAC,EAAE,CAAC;IAC3C,MAAM,IAAI,GAAG,EAAE,GAAG,CAAC,OAAO,CAAC,IAAI,IAAI,EAAE,CAAC,EAAE,CAAC;IAEzC,OAAO;QACL,OAAO;QACP,UAAU;QACV,WAAW;QACX,KAAK;QACL,IAAI;QAEJ;;;WAGG;QACH,KAAK,CAAC,IAAY;YAChB,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACrB,CAAC;QAED;;;WAGG;QACH,UAAU,CAAC,IAAY;YACrB,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACxB,CAAC;QAED;;;;WAIG;QACH,QAAQ,CAAC,MAAc;YACrB,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YACrB,OAAO,OAAO,CAAC,OAAO,CAAC,WAAW,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;QACpD,CAAC;QAED;;;;;;;;WAQG;QACH,QAAQ,CAAC,KAA4B;YACnC,MAAM,QAAQ,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,CAAC;YAC3C,IAAI,QAAQ,GAAG,KAAK,CAAC;YACrB,mEAAmE;YACnE,SAAS,OAAO;gBACd,IAAI,QAAQ,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC;oBAAE,OAAO;gBAC9C,MAAM,GAAG,GAAG,QAAQ,CAAC,KAAK,EAAG,CAAC;gBAC9B,KAAK,CAAC,GAAG,CAAC,CAAC;gBACX,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC;oBAAE,cAAc,CAAC,OAAO,CAAC,CAAC;YACnD,CAAC;YACD,cAAc,CAAC,OAAO,CAAC,CAAC;YACxB,OAAO,EAAE,OAAO,KAAK,QAAQ,GAAG,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;QAC5C,CAAC;QAED;;;;WAIG;QACH,QAAQ,CAAC,SAA+C;YACtD,OAAO,EAAE,OAAO,KAAI,CAAC,EAAE,CAAC;QAC1B,CAAC;QAED;;;;;WAKG;QACH,WAAW,CAAC,QAAoB,EAAE,EAAU;YAC1C,MAAM,EAAE,GAAG,UAAU,CAAC,WAAW,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;YAChD,OAAO,EAAE,OAAO,KAAK,aAAa,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QAC9C,CAAC;QAED;;;;;WAKG;QACH,QAAQ,CAAC,IAAY;YACnB,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC;YAC5B,IAAI,OAAO,KAAK,SAAS;gBAAE,MAAM,IAAI,KAAK,CAAC,yBAAyB,IAAI,EAAE,CAAC,CAAC;YAC5E,OAAO,OAAO,CAAC;QACjB,CAAC;QAED;;;;WAIG;QACH,OAAO,CAAC,IAAY;YAClB,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;QAC1B,CAAC;QAED;;;;WAIG;QACH,QAAQ,CAAC,GAAG,QAAkB;YAC5B,OAAO,IAAI,CAAC,GAAG,QAAQ,CAAC,CAAC;QAC3B,CAAC;KACF,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"io.js","sourceRoot":"","sources":["../../../src/adapters/test/io.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAqC5B;;;;;;;;;GASG;AACH,MAAM,UAAU,MAAM,CAAC,UAAyB,EAAE;IAChD,MAAM,OAAO,GAAa,EAAE,CAAC;IAC7B,MAAM,UAAU,GAAa,EAAE,CAAC;IAChC,MAAM,WAAW,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC,CAAC;IACjD,MAAM,KAAK,GAAG,EAAE,GAAG,CAAC,OAAO,CAAC,KAAK,IAAI,EAAE,CAAC,EAAE,CAAC;IAC3C,MAAM,IAAI,GAAG,EAAE,GAAG,CAAC,OAAO,CAAC,IAAI,IAAI,EAAE,CAAC,EAAE,CAAC;IACzC,MAAM,KAAK,GAAG,YAAY,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;IAE1C,OAAO;QACL,OAAO;QACP,UAAU;QACV,WAAW;QACX,KAAK;QACL,IAAI;QAEJ;;;WAGG;QACH,KAAK,CAAC,IAAY;YAChB,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACrB,CAAC;QAED;;;WAGG;QACH,UAAU,CAAC,IAAY;YACrB,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACxB,CAAC;QAED;;;;WAIG;QACH,QAAQ,CAAC,MAAc;YACrB,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YACrB,OAAO,OAAO,CAAC,OAAO,CAAC,WAAW,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;QACpD,CAAC;QAED;;;;;;;;WAQG;QACH,QAAQ,CAAC,KAA4B;YACnC,MAAM,QAAQ,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,CAAC;YAC3C,IAAI,QAAQ,GAAG,KAAK,CAAC;YACrB,mEAAmE;YACnE,SAAS,OAAO;gBACd,IAAI,QAAQ,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC;oBAAE,OAAO;gBAC9C,MAAM,GAAG,GAAG,QAAQ,CAAC,KAAK,EAAG,CAAC;gBAC9B,KAAK,CAAC,GAAG,CAAC,CAAC;gBACX,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC;oBAAE,KAAK,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC;YACzD,CAAC;YACD,KAAK,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC;YAC9B,OAAO,EAAE,OAAO,KAAK,QAAQ,GAAG,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;QAC5C,CAAC;QAED;;;;WAIG;QACH,QAAQ,CAAC,SAA+C;YACtD,OAAO,EAAE,OAAO,KAAI,CAAC,EAAE,CAAC;QAC1B,CAAC;QAED;;;;;WAKG;QACH,WAAW,CAAC,QAAoB,EAAE,EAAU;YAC1C,OAAO,KAAK,CAAC,WAAW,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;QACzC,CAAC;QAED;;;;;WAKG;QACH,QAAQ,CAAC,IAAY;YACnB,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC;YAC5B,IAAI,OAAO,KAAK,SAAS;gBAAE,MAAM,IAAI,KAAK,CAAC,yBAAyB,IAAI,EAAE,CAAC,CAAC;YAC5E,OAAO,OAAO,CAAC;QACjB,CAAC;QAED;;;;WAIG;QACH,OAAO,CAAC,IAAY;YAClB,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;QAC1B,CAAC;QAED;;;;WAIG;QACH,QAAQ,CAAC,GAAG,QAAkB;YAC5B,OAAO,IAAI,CAAC,GAAG,QAAQ,CAAC,CAAC;QAC3B,CAAC;KACF,CAAC;AACJ,CAAC"}
@@ -13,6 +13,8 @@ export interface MockRuntimeOptions {
13
13
  columns?: number;
14
14
  /** Terminal height in rows. Defaults to `24`. */
15
15
  rows?: number;
16
+ /** Refresh rate in FPS. Defaults to `60`. */
17
+ refreshRate?: number;
16
18
  }
17
19
  /**
18
20
  * Create an in-memory {@link RuntimePort} for tests.
@@ -1 +1 @@
1
- {"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../../../src/adapters/test/runtime.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAE1D;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,oEAAoE;IACpE,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC7B,mDAAmD;IACnD,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,kDAAkD;IAClD,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,mDAAmD;IACnD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,iDAAiD;IACjD,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED;;;;;;;;GAQG;AACH,wBAAgB,WAAW,CAAC,OAAO,GAAE,kBAAuB,GAAG,WAAW,CAgBzE"}
1
+ {"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../../../src/adapters/test/runtime.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAE1D;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,oEAAoE;IACpE,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC7B,mDAAmD;IACnD,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,kDAAkD;IAClD,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,mDAAmD;IACnD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,iDAAiD;IACjD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,6CAA6C;IAC7C,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;;;;;;;GAQG;AACH,wBAAgB,WAAW,CAAC,OAAO,GAAE,kBAAuB,GAAG,WAAW,CAiBzE"}
@@ -22,6 +22,7 @@ export function mockRuntime(options = {}) {
22
22
  stdinIsTTY: options.stdinIsTTY ?? true,
23
23
  columns: options.columns ?? 80,
24
24
  rows: options.rows ?? 24,
25
+ refreshRate: options.refreshRate ?? 60,
25
26
  };
26
27
  }
27
28
  //# sourceMappingURL=runtime.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"runtime.js","sourceRoot":"","sources":["../../../src/adapters/test/runtime.ts"],"names":[],"mappings":"AAkBA;;;;;;;;GAQG;AACH,MAAM,UAAU,WAAW,CAAC,UAA8B,EAAE;IAC1D,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,IAAI,EAAE,CAAC;IACjC,OAAO;QACL;;;;WAIG;QACH,GAAG,CAAC,GAAW;YACb,OAAO,MAAM,CAAC,GAAG,CAAC,CAAC;QACrB,CAAC;QACD,WAAW,EAAE,OAAO,CAAC,WAAW,IAAI,IAAI;QACxC,UAAU,EAAE,OAAO,CAAC,UAAU,IAAI,IAAI;QACtC,OAAO,EAAE,OAAO,CAAC,OAAO,IAAI,EAAE;QAC9B,IAAI,EAAE,OAAO,CAAC,IAAI,IAAI,EAAE;KACzB,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"runtime.js","sourceRoot":"","sources":["../../../src/adapters/test/runtime.ts"],"names":[],"mappings":"AAoBA;;;;;;;;GAQG;AACH,MAAM,UAAU,WAAW,CAAC,UAA8B,EAAE;IAC1D,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,IAAI,EAAE,CAAC;IACjC,OAAO;QACL;;;;WAIG;QACH,GAAG,CAAC,GAAW;YACb,OAAO,MAAM,CAAC,GAAG,CAAC,CAAC;QACrB,CAAC;QACD,WAAW,EAAE,OAAO,CAAC,WAAW,IAAI,IAAI;QACxC,UAAU,EAAE,OAAO,CAAC,UAAU,IAAI,IAAI;QACtC,OAAO,EAAE,OAAO,CAAC,OAAO,IAAI,EAAE;QAC9B,IAAI,EAAE,OAAO,CAAC,IAAI,IAAI,EAAE;QACxB,WAAW,EAAE,OAAO,CAAC,WAAW,IAAI,EAAE;KACvC,CAAC;AACJ,CAAC"}
@@ -12,4 +12,6 @@ export declare const CLEAR_LINE_RETURN = "\r\u001B[K";
12
12
  export declare const HIDE_CURSOR = "\u001B[?25l";
13
13
  /** ANSI escape: show the text cursor (DEC Private Mode 25). */
14
14
  export declare const SHOW_CURSOR = "\u001B[?25h";
15
+ /** ANSI escape: reset SGR style state. */
16
+ export declare const RESET_SGR = "\u001B[0m";
15
17
  //# sourceMappingURL=ansi.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ansi.d.ts","sourceRoot":"","sources":["../../src/core/ansi.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,yGAAyG;AACzG,eAAO,MAAM,iBAAiB,eAAa,CAAC;AAE5C,+DAA+D;AAC/D,eAAO,MAAM,WAAW,gBAAc,CAAC;AAEvC,+DAA+D;AAC/D,eAAO,MAAM,WAAW,gBAAc,CAAC"}
1
+ {"version":3,"file":"ansi.d.ts","sourceRoot":"","sources":["../../src/core/ansi.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,yGAAyG;AACzG,eAAO,MAAM,iBAAiB,eAAa,CAAC;AAE5C,+DAA+D;AAC/D,eAAO,MAAM,WAAW,gBAAc,CAAC;AAEvC,+DAA+D;AAC/D,eAAO,MAAM,WAAW,gBAAc,CAAC;AAEvC,0CAA0C;AAC1C,eAAO,MAAM,SAAS,cAAY,CAAC"}
package/dist/core/ansi.js CHANGED
@@ -12,4 +12,6 @@ export const CLEAR_LINE_RETURN = '\r\x1b[K';
12
12
  export const HIDE_CURSOR = '\x1b[?25l';
13
13
  /** ANSI escape: show the text cursor (DEC Private Mode 25). */
14
14
  export const SHOW_CURSOR = '\x1b[?25h';
15
+ /** ANSI escape: reset SGR style state. */
16
+ export const RESET_SGR = '\x1b[0m';
15
17
  //# sourceMappingURL=ansi.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"ansi.js","sourceRoot":"","sources":["../../src/core/ansi.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,yGAAyG;AACzG,MAAM,CAAC,MAAM,iBAAiB,GAAG,UAAU,CAAC;AAE5C,+DAA+D;AAC/D,MAAM,CAAC,MAAM,WAAW,GAAG,WAAW,CAAC;AAEvC,+DAA+D;AAC/D,MAAM,CAAC,MAAM,WAAW,GAAG,WAAW,CAAC"}
1
+ {"version":3,"file":"ansi.js","sourceRoot":"","sources":["../../src/core/ansi.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,yGAAyG;AACzG,MAAM,CAAC,MAAM,iBAAiB,GAAG,UAAU,CAAC;AAE5C,+DAA+D;AAC/D,MAAM,CAAC,MAAM,WAAW,GAAG,WAAW,CAAC;AAEvC,+DAA+D;AAC/D,MAAM,CAAC,MAAM,WAAW,GAAG,WAAW,CAAC;AAEvC,0CAA0C;AAC1C,MAAM,CAAC,MAAM,SAAS,GAAG,SAAS,CAAC"}
@@ -0,0 +1,12 @@
1
+ import type { ClockPort } from '../ports/clock.js';
2
+ /** Return the shared system-backed clock. */
3
+ export declare function systemClock(): ClockPort;
4
+ /** Resolve a clock from an explicit port or a context-like object. */
5
+ export declare function resolveClock(value?: ClockPort | {
6
+ clock?: ClockPort;
7
+ }): ClockPort;
8
+ /** Sleep for `ms` milliseconds using the provided clock port. */
9
+ export declare function sleep(clock: ClockPort, ms: number): Promise<void>;
10
+ /** Yield to the next microtask using the provided clock port. */
11
+ export declare function defer(clock: ClockPort): Promise<void>;
12
+ //# sourceMappingURL=clock.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"clock.d.ts","sourceRoot":"","sources":["../../src/core/clock.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAwCnD,6CAA6C;AAC7C,wBAAgB,WAAW,IAAI,SAAS,CAEvC;AAED,sEAAsE;AACtE,wBAAgB,YAAY,CAAC,KAAK,CAAC,EAAE,SAAS,GAAG;IAAE,KAAK,CAAC,EAAE,SAAS,CAAA;CAAE,GAAG,SAAS,CAMjF;AAED,iEAAiE;AACjE,wBAAgB,KAAK,CAAC,KAAK,EAAE,SAAS,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAIjE;AAED,iEAAiE;AACjE,wBAAgB,KAAK,CAAC,KAAK,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,CAIrD"}
@@ -0,0 +1,59 @@
1
+ /**
2
+ * Default system-backed clock implementation.
3
+ *
4
+ * This remains the runtime default, while tests can inject a deterministic
5
+ * implementation through `BijouContext.clock`.
6
+ */
7
+ const SYSTEM_CLOCK = {
8
+ now() {
9
+ return Date.now();
10
+ },
11
+ date(ms) {
12
+ return new Date(ms ?? Date.now());
13
+ },
14
+ setTimeout(callback, ms) {
15
+ const id = globalThis.setTimeout(callback, ms);
16
+ return {
17
+ dispose() {
18
+ globalThis.clearTimeout(id);
19
+ },
20
+ };
21
+ },
22
+ setInterval(callback, ms) {
23
+ const id = globalThis.setInterval(callback, ms);
24
+ return {
25
+ dispose() {
26
+ globalThis.clearInterval(id);
27
+ },
28
+ };
29
+ },
30
+ queueMicrotask(callback) {
31
+ globalThis.queueMicrotask(callback);
32
+ },
33
+ };
34
+ /** Return the shared system-backed clock. */
35
+ export function systemClock() {
36
+ return SYSTEM_CLOCK;
37
+ }
38
+ /** Resolve a clock from an explicit port or a context-like object. */
39
+ export function resolveClock(value) {
40
+ if (value === undefined)
41
+ return SYSTEM_CLOCK;
42
+ if (typeof value === 'object' && value !== null && 'now' in value) {
43
+ return value;
44
+ }
45
+ return value.clock ?? SYSTEM_CLOCK;
46
+ }
47
+ /** Sleep for `ms` milliseconds using the provided clock port. */
48
+ export function sleep(clock, ms) {
49
+ return new Promise((resolve) => {
50
+ clock.setTimeout(resolve, ms);
51
+ });
52
+ }
53
+ /** Yield to the next microtask using the provided clock port. */
54
+ export function defer(clock) {
55
+ return new Promise((resolve) => {
56
+ clock.queueMicrotask(resolve);
57
+ });
58
+ }
59
+ //# sourceMappingURL=clock.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"clock.js","sourceRoot":"","sources":["../../src/core/clock.ts"],"names":[],"mappings":"AAEA;;;;;GAKG;AACH,MAAM,YAAY,GAAc;IAC9B,GAAG;QACD,OAAO,IAAI,CAAC,GAAG,EAAE,CAAC;IACpB,CAAC;IAED,IAAI,CAAC,EAAW;QACd,OAAO,IAAI,IAAI,CAAC,EAAE,IAAI,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC;IACpC,CAAC;IAED,UAAU,CAAC,QAAoB,EAAE,EAAU;QACzC,MAAM,EAAE,GAAG,UAAU,CAAC,UAAU,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;QAC/C,OAAO;YACL,OAAO;gBACL,UAAU,CAAC,YAAY,CAAC,EAAE,CAAC,CAAC;YAC9B,CAAC;SACF,CAAC;IACJ,CAAC;IAED,WAAW,CAAC,QAAoB,EAAE,EAAU;QAC1C,MAAM,EAAE,GAAG,UAAU,CAAC,WAAW,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;QAChD,OAAO;YACL,OAAO;gBACL,UAAU,CAAC,aAAa,CAAC,EAAE,CAAC,CAAC;YAC/B,CAAC;SACF,CAAC;IACJ,CAAC;IAED,cAAc,CAAC,QAAoB;QACjC,UAAU,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAC;IACtC,CAAC;CACF,CAAC;AAEF,6CAA6C;AAC7C,MAAM,UAAU,WAAW;IACzB,OAAO,YAAY,CAAC;AACtB,CAAC;AAED,sEAAsE;AACtE,MAAM,UAAU,YAAY,CAAC,KAAyC;IACpE,IAAI,KAAK,KAAK,SAAS;QAAE,OAAO,YAAY,CAAC;IAC7C,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,IAAI,KAAK,EAAE,CAAC;QAClE,OAAO,KAAkB,CAAC;IAC5B,CAAC;IACD,OAAO,KAAK,CAAC,KAAK,IAAI,YAAY,CAAC;AACrC,CAAC;AAED,iEAAiE;AACjE,MAAM,UAAU,KAAK,CAAC,KAAgB,EAAE,EAAU;IAChD,OAAO,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,EAAE;QACnC,KAAK,CAAC,UAAU,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;IAChC,CAAC,CAAC,CAAC;AACL,CAAC;AAED,iEAAiE;AACjE,MAAM,UAAU,KAAK,CAAC,KAAgB;IACpC,OAAO,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,EAAE;QACnC,KAAK,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC;IAChC,CAAC,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,7 @@
1
+ import type { Surface } from '../../ports/surface.js';
2
+ import { type AlertOptions } from './alert.js';
3
+ /**
4
+ * Render an alert box as a Surface for V3-native composition.
5
+ */
6
+ export declare function alertSurface(message: string | Surface, options?: AlertOptions): Surface;
7
+ //# sourceMappingURL=alert-v3.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"alert-v3.d.ts","sourceRoot":"","sources":["../../../src/core/components/alert-v3.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAC;AAGtD,OAAO,EAAE,KAAK,YAAY,EAAqB,MAAM,YAAY,CAAC;AAkBlE;;GAEG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,EAAE,OAAO,GAAE,YAAiB,GAAG,OAAO,CAkB3F"}