@flyingrobots/bijou-tui 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.
- package/README.md +64 -21
- package/dist/animate.d.ts +0 -2
- package/dist/animate.d.ts.map +1 -1
- package/dist/animate.js +17 -26
- package/dist/animate.js.map +1 -1
- package/dist/app-frame-actions.d.ts +1 -5
- package/dist/app-frame-actions.d.ts.map +1 -1
- package/dist/app-frame-actions.js +21 -17
- package/dist/app-frame-actions.js.map +1 -1
- package/dist/app-frame-render.d.ts +2 -0
- package/dist/app-frame-render.d.ts.map +1 -1
- package/dist/app-frame-render.js +55 -8
- package/dist/app-frame-render.js.map +1 -1
- package/dist/app-frame-types.d.ts +9 -0
- package/dist/app-frame-types.d.ts.map +1 -1
- package/dist/app-frame-types.js +4 -4
- package/dist/app-frame-types.js.map +1 -1
- package/dist/app-frame.d.ts +39 -2
- package/dist/app-frame.d.ts.map +1 -1
- package/dist/app-frame.js +195 -31
- package/dist/app-frame.js.map +1 -1
- package/dist/canvas.d.ts +37 -25
- package/dist/canvas.d.ts.map +1 -1
- package/dist/canvas.js +116 -30
- package/dist/canvas.js.map +1 -1
- package/dist/commands.d.ts.map +1 -1
- package/dist/commands.js +12 -4
- package/dist/commands.js.map +1 -1
- package/dist/css/install.d.ts +4 -0
- package/dist/css/install.d.ts.map +1 -0
- package/dist/css/install.js +24 -0
- package/dist/css/install.js.map +1 -0
- package/dist/css/parser.d.ts +14 -0
- package/dist/css/parser.d.ts.map +1 -0
- package/dist/css/parser.js +92 -0
- package/dist/css/parser.js.map +1 -0
- package/dist/css/resolver.d.ts +36 -0
- package/dist/css/resolver.d.ts.map +1 -0
- package/dist/css/resolver.js +130 -0
- package/dist/css/resolver.js.map +1 -0
- package/dist/css/text-style.d.ts +17 -0
- package/dist/css/text-style.d.ts.map +1 -0
- package/dist/css/text-style.js +59 -0
- package/dist/css/text-style.js.map +1 -0
- package/dist/css/types.d.ts +27 -0
- package/dist/css/types.d.ts.map +1 -0
- package/dist/css/types.js +5 -0
- package/dist/css/types.js.map +1 -0
- package/dist/driver.d.ts +14 -7
- package/dist/driver.d.ts.map +1 -1
- package/dist/driver.js +38 -17
- package/dist/driver.js.map +1 -1
- package/dist/eventbus.d.ts +42 -3
- package/dist/eventbus.d.ts.map +1 -1
- package/dist/eventbus.js +127 -3
- package/dist/eventbus.js.map +1 -1
- package/dist/focus-area.d.ts +4 -0
- package/dist/focus-area.d.ts.map +1 -1
- package/dist/focus-area.js +11 -1
- package/dist/focus-area.js.map +1 -1
- package/dist/index.d.ts +13 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +9 -0
- package/dist/index.js.map +1 -1
- package/dist/layout-v3.d.ts +10 -0
- package/dist/layout-v3.d.ts.map +1 -0
- package/dist/layout-v3.js +35 -0
- package/dist/layout-v3.js.map +1 -0
- package/dist/motion/motion.d.ts +14 -0
- package/dist/motion/motion.d.ts.map +1 -0
- package/dist/motion/motion.js +31 -0
- package/dist/motion/motion.js.map +1 -0
- package/dist/motion/reconciler.d.ts +15 -0
- package/dist/motion/reconciler.d.ts.map +1 -0
- package/dist/motion/reconciler.js +109 -0
- package/dist/motion/reconciler.js.map +1 -0
- package/dist/motion/types.d.ts +52 -0
- package/dist/motion/types.d.ts.map +1 -0
- package/dist/motion/types.js +2 -0
- package/dist/motion/types.js.map +1 -0
- package/dist/notification.d.ts +73 -0
- package/dist/notification.d.ts.map +1 -0
- package/dist/notification.js +693 -0
- package/dist/notification.js.map +1 -0
- package/dist/overlay.d.ts +3 -1
- package/dist/overlay.d.ts.map +1 -1
- package/dist/overlay.js.map +1 -1
- package/dist/pipeline/middleware/css.d.ts +20 -0
- package/dist/pipeline/middleware/css.d.ts.map +1 -0
- package/dist/pipeline/middleware/css.js +41 -0
- package/dist/pipeline/middleware/css.js.map +1 -0
- package/dist/pipeline/middleware/grayscale.d.ts +9 -0
- package/dist/pipeline/middleware/grayscale.d.ts.map +1 -0
- package/dist/pipeline/middleware/grayscale.js +39 -0
- package/dist/pipeline/middleware/grayscale.js.map +1 -0
- package/dist/pipeline/middleware/motion.d.ts +6 -0
- package/dist/pipeline/middleware/motion.d.ts.map +1 -0
- package/dist/pipeline/middleware/motion.js +19 -0
- package/dist/pipeline/middleware/motion.js.map +1 -0
- package/dist/pipeline/middleware/paint.d.ts +6 -0
- package/dist/pipeline/middleware/paint.d.ts.map +1 -0
- package/dist/pipeline/middleware/paint.js +21 -0
- package/dist/pipeline/middleware/paint.js.map +1 -0
- package/dist/pipeline/pipeline.d.ts +56 -0
- package/dist/pipeline/pipeline.d.ts.map +1 -0
- package/dist/pipeline/pipeline.js +45 -0
- package/dist/pipeline/pipeline.js.map +1 -0
- package/dist/runtime.d.ts +1 -1
- package/dist/runtime.d.ts.map +1 -1
- package/dist/runtime.js +180 -18
- package/dist/runtime.js.map +1 -1
- package/dist/screen.d.ts +12 -1
- package/dist/screen.d.ts.map +1 -1
- package/dist/screen.js +14 -1
- package/dist/screen.js.map +1 -1
- package/dist/subapp/mount.d.ts +67 -0
- package/dist/subapp/mount.d.ts.map +1 -0
- package/dist/subapp/mount.js +60 -0
- package/dist/subapp/mount.js.map +1 -0
- package/dist/types.d.ts +75 -8
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +9 -0
- package/dist/types.js.map +1 -1
- package/dist/view-output.d.ts +15 -0
- package/dist/view-output.d.ts.map +1 -0
- package/dist/view-output.js +53 -0
- package/dist/view-output.js.map +1 -0
- package/package.json +3 -3
package/dist/runtime.js
CHANGED
|
@@ -1,12 +1,18 @@
|
|
|
1
|
-
import { getDefaultContext } from '@flyingrobots/bijou';
|
|
2
|
-
import { isKeyMsg } from './types.js';
|
|
3
|
-
import { enterScreen, exitScreen,
|
|
1
|
+
import { getDefaultContext, createSurface, surfaceToString, resolveClock, installRuntimeViewportOverlay, readRuntimeViewport, updateRuntimeViewport, } from '@flyingrobots/bijou';
|
|
2
|
+
import { isKeyMsg, isPulseMsg, isResizeMsg } from './types.js';
|
|
3
|
+
import { clearAndHome, enterScreen, exitScreen, renderSurfaceFrame } from './screen.js';
|
|
4
4
|
import { createEventBus } from './eventbus.js';
|
|
5
|
+
import { createPipeline } from './pipeline/pipeline.js';
|
|
6
|
+
import { bcssMiddleware } from './pipeline/middleware/css.js';
|
|
7
|
+
import { motionMiddleware } from './pipeline/middleware/motion.js';
|
|
8
|
+
import { paintMiddleware } from './pipeline/middleware/paint.js';
|
|
9
|
+
import { installBCSSResolver } from './css/install.js';
|
|
10
|
+
import { normalizeViewOutput, wrapViewOutputAsLayoutRoot } from './view-output.js';
|
|
5
11
|
/**
|
|
6
12
|
* Disable mouse reporting sequences that terminals may send.
|
|
7
13
|
* Some terminals auto-enable mouse tracking in alt screen mode.
|
|
8
14
|
*/
|
|
9
|
-
const DISABLE_MOUSE = '\x1b[?1000l\x1b[?1002l\x1b[?
|
|
15
|
+
const DISABLE_MOUSE = '\x1b[?1000l\x1b[?1002l\x1b[?1006l';
|
|
10
16
|
/**
|
|
11
17
|
* Enable SGR mouse reporting.
|
|
12
18
|
* 1000 = basic press/release, 1002 = button-event tracking (drag),
|
|
@@ -31,30 +37,118 @@ const ENABLE_MOUSE = '\x1b[?1000h\x1b[?1002h\x1b[?1006h';
|
|
|
31
37
|
*/
|
|
32
38
|
export async function run(app, options) {
|
|
33
39
|
const ctx = options?.ctx ?? getDefaultContext();
|
|
40
|
+
const clock = resolveClock(ctx);
|
|
41
|
+
installRuntimeViewportOverlay(ctx);
|
|
34
42
|
const useAltScreen = options?.altScreen ?? true;
|
|
35
43
|
const useHideCursor = options?.hideCursor ?? true;
|
|
36
44
|
const useMouse = options?.mouse ?? false;
|
|
45
|
+
installBCSSResolver(ctx, options?.css);
|
|
46
|
+
const runtimeViewport = () => readRuntimeViewport(ctx.runtime);
|
|
37
47
|
const [initModel, initCmds] = app.init();
|
|
38
48
|
// Non-interactive: render once and return
|
|
39
49
|
if (ctx.mode !== 'interactive') {
|
|
40
|
-
|
|
50
|
+
const viewOutput = app.view(initModel);
|
|
51
|
+
let output;
|
|
52
|
+
if (typeof viewOutput === 'string') {
|
|
53
|
+
output = viewOutput;
|
|
54
|
+
}
|
|
55
|
+
else {
|
|
56
|
+
const viewport = runtimeViewport();
|
|
57
|
+
const normalized = normalizeViewOutput(viewOutput, {
|
|
58
|
+
width: viewport.columns,
|
|
59
|
+
height: viewport.rows,
|
|
60
|
+
});
|
|
61
|
+
output = surfaceToString(normalized.surface, ctx.style);
|
|
62
|
+
}
|
|
63
|
+
ctx.io.write(output);
|
|
41
64
|
return;
|
|
42
65
|
}
|
|
43
66
|
// Interactive mode
|
|
44
67
|
let model = initModel;
|
|
45
68
|
let running = true;
|
|
46
|
-
let lastCtrlC =
|
|
69
|
+
let lastCtrlC = null;
|
|
47
70
|
let resolveQuit = null;
|
|
71
|
+
let currentDt = 0.016; // Default to 60fps for first frame
|
|
72
|
+
let fatalError = null;
|
|
73
|
+
// Double Buffering: track what is currently on screen
|
|
74
|
+
const initialViewport = runtimeViewport();
|
|
75
|
+
let currentSurface = createSurface(initialViewport.columns, initialViewport.rows);
|
|
76
|
+
function routeRuntimeIssue(issue) {
|
|
77
|
+
const routed = app.routeRuntimeIssue?.(issue);
|
|
78
|
+
if (routed !== undefined) {
|
|
79
|
+
bus.emit(routed);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
48
82
|
const bus = createEventBus({
|
|
83
|
+
clock,
|
|
49
84
|
onCommandRejected(error) {
|
|
50
85
|
const message = error instanceof Error
|
|
51
86
|
? `${error.name}: ${error.message}`
|
|
52
87
|
: String(error);
|
|
53
88
|
writeErrorLine(ctx.io, `[EventBus] Command rejected: ${message}\n`);
|
|
89
|
+
routeRuntimeIssue({
|
|
90
|
+
level: 'error',
|
|
91
|
+
source: 'command',
|
|
92
|
+
message,
|
|
93
|
+
atMs: clock.now(),
|
|
94
|
+
error,
|
|
95
|
+
});
|
|
54
96
|
},
|
|
97
|
+
onError(message, error) {
|
|
98
|
+
const detail = error instanceof Error
|
|
99
|
+
? `${error.name}: ${error.message}`
|
|
100
|
+
: String(error);
|
|
101
|
+
writeErrorLine(ctx.io, `${message} ${detail}\n`);
|
|
102
|
+
routeRuntimeIssue({
|
|
103
|
+
level: 'warning',
|
|
104
|
+
source: 'eventbus',
|
|
105
|
+
message: `${message} ${detail}`,
|
|
106
|
+
atMs: clock.now(),
|
|
107
|
+
error,
|
|
108
|
+
});
|
|
109
|
+
},
|
|
110
|
+
});
|
|
111
|
+
// Setup Programmable Rendering Pipeline
|
|
112
|
+
const pipeline = createPipeline();
|
|
113
|
+
// 1. Layout Logic Stage
|
|
114
|
+
pipeline.use('Layout', (state, next) => {
|
|
115
|
+
const viewOutput = app.view(state.model);
|
|
116
|
+
const viewport = runtimeViewport();
|
|
117
|
+
state.layoutRoot = wrapViewOutputAsLayoutRoot(viewOutput, {
|
|
118
|
+
width: viewport.columns,
|
|
119
|
+
height: viewport.rows,
|
|
120
|
+
});
|
|
121
|
+
next();
|
|
122
|
+
});
|
|
123
|
+
// 2. Motion Interpolation Stage
|
|
124
|
+
pipeline.use('Layout', motionMiddleware());
|
|
125
|
+
if (options?.css) {
|
|
126
|
+
pipeline.use('Layout', bcssMiddleware(options.css));
|
|
127
|
+
}
|
|
128
|
+
// 3. Paint Stage
|
|
129
|
+
pipeline.use('Paint', paintMiddleware());
|
|
130
|
+
// Add default Diff stage (double-buffering)
|
|
131
|
+
pipeline.use('Diff', (state, next) => {
|
|
132
|
+
renderSurfaceFrame(state.ctx.io, state.currentSurface, state.targetSurface, state.ctx.style);
|
|
133
|
+
next();
|
|
134
|
+
});
|
|
135
|
+
// Add default Output stage (sync current surface)
|
|
136
|
+
pipeline.use('Output', (state, next) => {
|
|
137
|
+
currentSurface = state.targetSurface.clone();
|
|
138
|
+
next();
|
|
55
139
|
});
|
|
140
|
+
options?.configurePipeline?.(pipeline);
|
|
141
|
+
// Register user middleware
|
|
142
|
+
if (options?.middlewares) {
|
|
143
|
+
for (const mw of options.middlewares) {
|
|
144
|
+
bus.use(mw);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
56
147
|
/** Tear down the run loop and signal the quit promise. */
|
|
57
|
-
function shutdown() {
|
|
148
|
+
function shutdown(error) {
|
|
149
|
+
if (error !== undefined && fatalError === null) {
|
|
150
|
+
fatalError = error;
|
|
151
|
+
}
|
|
58
152
|
if (!running)
|
|
59
153
|
return;
|
|
60
154
|
running = false;
|
|
@@ -72,11 +166,49 @@ export async function run(app, options) {
|
|
|
72
166
|
ctx.io.write(DISABLE_MOUSE);
|
|
73
167
|
}
|
|
74
168
|
// Render helper
|
|
169
|
+
let renderRequested = false;
|
|
170
|
+
let renderHandle = null;
|
|
75
171
|
/** Render the current model's view to the terminal. */
|
|
76
172
|
function render() {
|
|
77
|
-
if (!running)
|
|
173
|
+
if (!running || renderRequested)
|
|
78
174
|
return;
|
|
79
|
-
|
|
175
|
+
renderRequested = true;
|
|
176
|
+
let scheduledHandle = null;
|
|
177
|
+
scheduledHandle = clock.setTimeout(() => {
|
|
178
|
+
try {
|
|
179
|
+
const viewport = runtimeViewport();
|
|
180
|
+
const targetSurface = createSurface(viewport.columns, viewport.rows);
|
|
181
|
+
const renderState = {
|
|
182
|
+
model,
|
|
183
|
+
ctx,
|
|
184
|
+
dt: currentDt,
|
|
185
|
+
currentSurface,
|
|
186
|
+
targetSurface,
|
|
187
|
+
layoutMap: new Map(),
|
|
188
|
+
data: {},
|
|
189
|
+
};
|
|
190
|
+
pipeline.execute(renderState);
|
|
191
|
+
}
|
|
192
|
+
catch (error) {
|
|
193
|
+
routeRuntimeIssue({
|
|
194
|
+
level: 'error',
|
|
195
|
+
source: 'runtime',
|
|
196
|
+
message: error instanceof Error ? error.message : String(error),
|
|
197
|
+
atMs: clock.now(),
|
|
198
|
+
error,
|
|
199
|
+
});
|
|
200
|
+
writeErrorLine(ctx.io, `[Runtime Error] ${error instanceof Error ? (error.stack ?? error.message) : String(error)}\n`);
|
|
201
|
+
shutdown(error);
|
|
202
|
+
}
|
|
203
|
+
finally {
|
|
204
|
+
renderRequested = false;
|
|
205
|
+
scheduledHandle?.dispose();
|
|
206
|
+
if (renderHandle === scheduledHandle) {
|
|
207
|
+
renderHandle = null;
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
}, 0);
|
|
211
|
+
renderHandle = scheduledHandle;
|
|
80
212
|
}
|
|
81
213
|
// Execute commands through the bus
|
|
82
214
|
/** Submit TEA commands to the event bus for async execution. */
|
|
@@ -89,14 +221,25 @@ export async function run(app, options) {
|
|
|
89
221
|
bus.connectIO(ctx.io, { mouse: useMouse });
|
|
90
222
|
// Handle quit signals from commands
|
|
91
223
|
bus.onQuit(shutdown);
|
|
224
|
+
// Start heartbeat for animations
|
|
225
|
+
bus.startPulse(ctx.runtime.refreshRate);
|
|
92
226
|
// Single subscription drives the entire update cycle
|
|
93
227
|
bus.on((msg) => {
|
|
94
228
|
if (!running)
|
|
95
229
|
return;
|
|
230
|
+
// Track time delta from pulse
|
|
231
|
+
if (isPulseMsg(msg)) {
|
|
232
|
+
currentDt = msg.dt;
|
|
233
|
+
}
|
|
234
|
+
if (isResizeMsg(msg)) {
|
|
235
|
+
const viewport = updateRuntimeViewport(ctx.runtime, msg.columns, msg.rows);
|
|
236
|
+
currentSurface = createSurface(viewport.columns, viewport.rows);
|
|
237
|
+
clearAndHome(ctx.io);
|
|
238
|
+
}
|
|
96
239
|
// Double Ctrl+C force-quit
|
|
97
240
|
if (isKeyMsg(msg) && msg.key === 'c' && msg.ctrl) {
|
|
98
|
-
const now =
|
|
99
|
-
if (now - lastCtrlC < 1000) {
|
|
241
|
+
const now = clock.now();
|
|
242
|
+
if (lastCtrlC !== null && now - lastCtrlC < 1000) {
|
|
100
243
|
shutdown();
|
|
101
244
|
return;
|
|
102
245
|
}
|
|
@@ -109,13 +252,18 @@ export async function run(app, options) {
|
|
|
109
252
|
});
|
|
110
253
|
// Apply an initial runtime-size sync before first render.
|
|
111
254
|
// This keeps framed apps sized from ports instead of process globals.
|
|
255
|
+
const syncedViewport = runtimeViewport();
|
|
112
256
|
const initialResize = {
|
|
113
257
|
type: 'resize',
|
|
114
|
-
columns:
|
|
115
|
-
rows:
|
|
258
|
+
columns: syncedViewport.columns,
|
|
259
|
+
rows: syncedViewport.rows,
|
|
116
260
|
};
|
|
117
261
|
const [resizedModel, resizeCmds] = app.update(initialResize, model);
|
|
118
262
|
model = resizedModel;
|
|
263
|
+
// After a potential resize in update, ensure currentSurface matches size
|
|
264
|
+
// to avoid diffing mismatched grids.
|
|
265
|
+
const postResizeViewport = runtimeViewport();
|
|
266
|
+
currentSurface = createSurface(postResizeViewport.columns, postResizeViewport.rows);
|
|
119
267
|
// Initial render + startup commands
|
|
120
268
|
render();
|
|
121
269
|
executeCommands(initCmds);
|
|
@@ -126,7 +274,21 @@ export async function run(app, options) {
|
|
|
126
274
|
if (!running)
|
|
127
275
|
resolve();
|
|
128
276
|
});
|
|
277
|
+
// Ensure any pending render is flushed before exiting
|
|
278
|
+
if (renderRequested) {
|
|
279
|
+
await new Promise((resolve) => {
|
|
280
|
+
let flushHandle = null;
|
|
281
|
+
flushHandle = clock.setTimeout(() => {
|
|
282
|
+
flushHandle?.dispose();
|
|
283
|
+
flushHandle = null;
|
|
284
|
+
resolve();
|
|
285
|
+
}, 0);
|
|
286
|
+
});
|
|
287
|
+
}
|
|
129
288
|
// Cleanup — bus disposes all I/O connections
|
|
289
|
+
disposeTimerHandle(renderHandle);
|
|
290
|
+
renderHandle = null;
|
|
291
|
+
bus.stopPulse();
|
|
130
292
|
bus.dispose();
|
|
131
293
|
if (useMouse) {
|
|
132
294
|
ctx.io.write(DISABLE_MOUSE);
|
|
@@ -134,12 +296,12 @@ export async function run(app, options) {
|
|
|
134
296
|
if (useAltScreen || useHideCursor) {
|
|
135
297
|
exitScreen(ctx.io);
|
|
136
298
|
}
|
|
299
|
+
if (fatalError != null) {
|
|
300
|
+
throw fatalError instanceof Error ? fatalError : new Error(String(fatalError));
|
|
301
|
+
}
|
|
137
302
|
}
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
if (!Number.isFinite(value))
|
|
141
|
-
return 0;
|
|
142
|
-
return Math.max(0, Math.floor(value));
|
|
303
|
+
function disposeTimerHandle(handle) {
|
|
304
|
+
handle?.dispose();
|
|
143
305
|
}
|
|
144
306
|
/** Write an error message to stderr if available, otherwise stdout. */
|
|
145
307
|
function writeErrorLine(io, data) {
|
package/dist/runtime.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runtime.js","sourceRoot":"","sources":["../src/runtime.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"runtime.js","sourceRoot":"","sources":["../src/runtime.ts"],"names":[],"mappings":"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"}
|
package/dist/screen.d.ts
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
*
|
|
7
7
|
* @module screen
|
|
8
8
|
*/
|
|
9
|
-
import { HIDE_CURSOR, SHOW_CURSOR, type IOPort } from '@flyingrobots/bijou';
|
|
9
|
+
import { HIDE_CURSOR, SHOW_CURSOR, type IOPort, type Surface, type StylePort } from '@flyingrobots/bijou';
|
|
10
10
|
/** ANSI escape: enter alternate screen buffer (DEC Private Mode 1049). */
|
|
11
11
|
export declare const ENTER_ALT_SCREEN = "\u001B[?1049h";
|
|
12
12
|
/** ANSI escape: exit alternate screen buffer (DEC Private Mode 1049). */
|
|
@@ -76,8 +76,19 @@ export declare function exitScreen(io: IOPort): void;
|
|
|
76
76
|
* @param io - The I/O port to write escape sequences to.
|
|
77
77
|
*/
|
|
78
78
|
export declare function clearAndHome(io: IOPort): void;
|
|
79
|
+
/**
|
|
80
|
+
* Optimized double-buffered render: diff two surfaces and write the minimal
|
|
81
|
+
* set of CUP/SGR escape codes to the terminal.
|
|
82
|
+
*
|
|
83
|
+
* @param io - The I/O port to write the composed frame to.
|
|
84
|
+
* @param current - The surface currently on screen.
|
|
85
|
+
* @param target - The new surface to render.
|
|
86
|
+
* @param style - Style port for color resolution.
|
|
87
|
+
*/
|
|
88
|
+
export declare function renderSurfaceFrame(io: IOPort, current: Surface, target: Surface, style: StylePort): void;
|
|
79
89
|
/**
|
|
80
90
|
* Flicker-free render: move cursor home, write content line-by-line,
|
|
91
|
+
...
|
|
81
92
|
* clearing from the end of each line to the terminal edge.
|
|
82
93
|
*
|
|
83
94
|
* Disabling wrap in enterScreen() ensures the terminal won't scroll
|
package/dist/screen.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"screen.d.ts","sourceRoot":"","sources":["../src/screen.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,WAAW,EAAE,WAAW,
|
|
1
|
+
{"version":3,"file":"screen.d.ts","sourceRoot":"","sources":["../src/screen.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,WAAW,EAAE,WAAW,EAAc,KAAK,MAAM,EAAE,KAAK,OAAO,EAAE,KAAK,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAEtH,0EAA0E;AAC1E,eAAO,MAAM,gBAAgB,kBAAgB,CAAC;AAC9C,yEAAyE;AACzE,eAAO,MAAM,eAAe,kBAAgB,CAAC;AAE7C,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,CAAC;AACpC,+DAA+D;AAC/D,eAAO,MAAM,YAAY,eAAa,CAAC;AACvC,8DAA8D;AAC9D,eAAO,MAAM,WAAW,eAAa,CAAC;AACtC,+CAA+C;AAC/C,eAAO,MAAM,YAAY,cAAY,CAAC;AACtC,8DAA8D;AAC9D,eAAO,MAAM,YAAY,aAAW,CAAC;AACrC,oEAAoE;AACpE,eAAO,MAAM,iBAAiB,aAAW,CAAC;AAC1C,yDAAyD;AACzD,eAAO,MAAM,IAAI,aAAW,CAAC;AAC7B,qDAAqD;AACrD,eAAO,MAAM,UAAU,cAAY,CAAC;AAIpC,oDAAoD;AACpD,MAAM,MAAM,WAAW,GAAG,OAAO,GAAG,WAAW,GAAG,KAAK,CAAC;AAExD,qDAAqD;AACrD,eAAO,MAAM,YAAY,eAAa,CAAC;AACvC,yDAAyD;AACzD,eAAO,MAAM,gBAAgB,eAAa,CAAC;AAC3C,mDAAmD;AACnD,eAAO,MAAM,UAAU,eAAa,CAAC;AACrC,wFAAwF;AACxF,eAAO,MAAM,YAAY,eAAa,CAAC;AASvC;;;;;;;;;GASG;AACH,wBAAgB,cAAc,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,WAAW,EAAE,OAAO,CAAC,EAAE;IAAE,KAAK,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG,IAAI,CAGlG;AAED;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAEjD;AAED;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAE5C;AAED;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAE3C;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAE7C;AACD;;;;;;;;GAQG;AACH,wBAAgB,kBAAkB,CAChC,EAAE,EAAE,MAAM,EACV,OAAO,EAAE,OAAO,EAChB,MAAM,EAAE,OAAO,EACf,KAAK,EAAE,SAAS,GACf,IAAI,CAEN;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,WAAW,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAI7D"}
|
package/dist/screen.js
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
*
|
|
7
7
|
* @module screen
|
|
8
8
|
*/
|
|
9
|
-
import { HIDE_CURSOR, SHOW_CURSOR } from '@flyingrobots/bijou';
|
|
9
|
+
import { HIDE_CURSOR, SHOW_CURSOR, renderDiff } from '@flyingrobots/bijou';
|
|
10
10
|
/** ANSI escape: enter alternate screen buffer (DEC Private Mode 1049). */
|
|
11
11
|
export const ENTER_ALT_SCREEN = '\x1b[?1049h';
|
|
12
12
|
/** ANSI escape: exit alternate screen buffer (DEC Private Mode 1049). */
|
|
@@ -89,8 +89,21 @@ export function exitScreen(io) {
|
|
|
89
89
|
export function clearAndHome(io) {
|
|
90
90
|
io.write(CLEAR_SCREEN + HOME);
|
|
91
91
|
}
|
|
92
|
+
/**
|
|
93
|
+
* Optimized double-buffered render: diff two surfaces and write the minimal
|
|
94
|
+
* set of CUP/SGR escape codes to the terminal.
|
|
95
|
+
*
|
|
96
|
+
* @param io - The I/O port to write the composed frame to.
|
|
97
|
+
* @param current - The surface currently on screen.
|
|
98
|
+
* @param target - The new surface to render.
|
|
99
|
+
* @param style - Style port for color resolution.
|
|
100
|
+
*/
|
|
101
|
+
export function renderSurfaceFrame(io, current, target, style) {
|
|
102
|
+
renderDiff(current, target, io, style);
|
|
103
|
+
}
|
|
92
104
|
/**
|
|
93
105
|
* Flicker-free render: move cursor home, write content line-by-line,
|
|
106
|
+
...
|
|
94
107
|
* clearing from the end of each line to the terminal edge.
|
|
95
108
|
*
|
|
96
109
|
* Disabling wrap in enterScreen() ensures the terminal won't scroll
|
package/dist/screen.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"screen.js","sourceRoot":"","sources":["../src/screen.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,WAAW,EAAE,WAAW,
|
|
1
|
+
{"version":3,"file":"screen.js","sourceRoot":"","sources":["../src/screen.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import type { App, Cmd } from '../types.js';
|
|
2
|
+
import type { ViewOutput } from '../view-output.js';
|
|
3
|
+
/**
|
|
4
|
+
* Options for mounting a sub-app.
|
|
5
|
+
*
|
|
6
|
+
* @template SubModel - The sub-app's model type.
|
|
7
|
+
* @template SubMsg - The sub-app's message type.
|
|
8
|
+
* @template ParentMsg - The parent app's message type.
|
|
9
|
+
*/
|
|
10
|
+
export interface MountOptions<SubModel, SubMsg, ParentMsg> {
|
|
11
|
+
/** The current state of the sub-app. */
|
|
12
|
+
model: SubModel;
|
|
13
|
+
/** Function to map a sub-app message into a parent message. */
|
|
14
|
+
onMsg: (msg: SubMsg) => ParentMsg;
|
|
15
|
+
/**
|
|
16
|
+
* Optional function to intercept and handle `Cmd`s emitted by the sub-app.
|
|
17
|
+
* If not provided, commands are automatically mapped using `onMsg`.
|
|
18
|
+
*/
|
|
19
|
+
mapCmd?: (cmd: Cmd<SubMsg>) => Cmd<ParentMsg>;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* A mounted sub-app instance ready to be rendered.
|
|
23
|
+
*
|
|
24
|
+
* This is typically returned by the parent's `view` function
|
|
25
|
+
* and blitted onto the parent's surface.
|
|
26
|
+
*/
|
|
27
|
+
export interface MountedApp<SubMsg> {
|
|
28
|
+
/** The rendered surface or layout tree of the sub-app. */
|
|
29
|
+
surfaceOrNode: ViewOutput;
|
|
30
|
+
/**
|
|
31
|
+
* Any TEA commands the sub-app needs to execute.
|
|
32
|
+
* These should be dispatched by the parent during its update cycle.
|
|
33
|
+
*/
|
|
34
|
+
cmds: Cmd<SubMsg>[];
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Mount a sub-app, returning its rendered surface and any pending commands.
|
|
38
|
+
*
|
|
39
|
+
* @template SubModel - The sub-app's model type.
|
|
40
|
+
* @template SubMsg - The sub-app's message type.
|
|
41
|
+
* @template ParentMsg - The parent app's message type.
|
|
42
|
+
*
|
|
43
|
+
* @param app - The TEA application to mount.
|
|
44
|
+
* @param options - Configuration for the mounted instance.
|
|
45
|
+
* @returns A tuple of `[Surface | LayoutNode, mapped Cmds]`.
|
|
46
|
+
*/
|
|
47
|
+
export declare function mount<SubModel, SubMsg, ParentMsg>(app: App<SubModel, SubMsg>, options: MountOptions<SubModel, SubMsg, ParentMsg>): [ViewOutput, Cmd<ParentMsg>[]];
|
|
48
|
+
export interface SubAppOptions<SubMsg, ParentMsg> {
|
|
49
|
+
/** Function to map a sub-app message into a parent message. */
|
|
50
|
+
onMsg: (msg: SubMsg) => ParentMsg;
|
|
51
|
+
/**
|
|
52
|
+
* Optional function to intercept and handle `Cmd`s emitted by the sub-app.
|
|
53
|
+
* If not provided, commands are automatically mapped using `onMsg`.
|
|
54
|
+
*/
|
|
55
|
+
mapCmd?: (cmd: Cmd<SubMsg>) => Cmd<ParentMsg>;
|
|
56
|
+
}
|
|
57
|
+
export declare function initSubApp<SubModel, SubMsg, ParentMsg>(app: App<SubModel, SubMsg>, options: SubAppOptions<SubMsg, ParentMsg>): [SubModel, Cmd<ParentMsg>[]];
|
|
58
|
+
export declare function updateSubApp<SubModel, SubMsg, ParentMsg>(app: App<SubModel, SubMsg>, msg: SubMsg, model: SubModel, options: SubAppOptions<SubMsg, ParentMsg>): [SubModel, Cmd<ParentMsg>[]];
|
|
59
|
+
/**
|
|
60
|
+
* Helper to map an array of sub-app commands into parent commands.
|
|
61
|
+
*
|
|
62
|
+
* @param cmds - The sub-app commands to map.
|
|
63
|
+
* @param mapper - The message mapping function.
|
|
64
|
+
* @returns An array of commands that emit parent messages.
|
|
65
|
+
*/
|
|
66
|
+
export declare function mapCmds<SubMsg, ParentMsg>(cmds: Cmd<SubMsg>[], mapper: (msg: SubMsg) => ParentMsg): Cmd<ParentMsg>[];
|
|
67
|
+
//# sourceMappingURL=mount.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mount.d.ts","sourceRoot":"","sources":["../../src/subapp/mount.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,GAAG,EAAc,MAAM,aAAa,CAAC;AACxD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAEpD;;;;;;GAMG;AACH,MAAM,WAAW,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS;IACvD,wCAAwC;IACxC,KAAK,EAAE,QAAQ,CAAC;IAChB,+DAA+D;IAC/D,KAAK,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,SAAS,CAAC;IAClC;;;OAGG;IACH,MAAM,CAAC,EAAE,CAAC,GAAG,EAAE,GAAG,CAAC,MAAM,CAAC,KAAK,GAAG,CAAC,SAAS,CAAC,CAAC;CAC/C;AAED;;;;;GAKG;AACH,MAAM,WAAW,UAAU,CAAC,MAAM;IAChC,0DAA0D;IAC1D,aAAa,EAAE,UAAU,CAAC;IAC1B;;;OAGG;IACH,IAAI,EAAE,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC;CACrB;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,KAAK,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,EAC/C,GAAG,EAAE,GAAG,CAAC,QAAQ,EAAE,MAAM,CAAC,EAC1B,OAAO,EAAE,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,CAAC,GACjD,CAAC,UAAU,EAAE,GAAG,CAAC,SAAS,CAAC,EAAE,CAAC,CAMhC;AAED,MAAM,WAAW,aAAa,CAAC,MAAM,EAAE,SAAS;IAC9C,+DAA+D;IAC/D,KAAK,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,SAAS,CAAC;IAClC;;;OAGG;IACH,MAAM,CAAC,EAAE,CAAC,GAAG,EAAE,GAAG,CAAC,MAAM,CAAC,KAAK,GAAG,CAAC,SAAS,CAAC,CAAC;CAC/C;AAED,wBAAgB,UAAU,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,EACpD,GAAG,EAAE,GAAG,CAAC,QAAQ,EAAE,MAAM,CAAC,EAC1B,OAAO,EAAE,aAAa,CAAC,MAAM,EAAE,SAAS,CAAC,GACxC,CAAC,QAAQ,EAAE,GAAG,CAAC,SAAS,CAAC,EAAE,CAAC,CAG9B;AAED,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,EACtD,GAAG,EAAE,GAAG,CAAC,QAAQ,EAAE,MAAM,CAAC,EAC1B,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,QAAQ,EACf,OAAO,EAAE,aAAa,CAAC,MAAM,EAAE,SAAS,CAAC,GACxC,CAAC,QAAQ,EAAE,GAAG,CAAC,SAAS,CAAC,EAAE,CAAC,CAG9B;AAED;;;;;;GAMG;AACH,wBAAgB,OAAO,CAAC,MAAM,EAAE,SAAS,EACvC,IAAI,EAAE,GAAG,CAAC,MAAM,CAAC,EAAE,EACnB,MAAM,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,SAAS,GACjC,GAAG,CAAC,SAAS,CAAC,EAAE,CAElB"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Mount a sub-app, returning its rendered surface and any pending commands.
|
|
3
|
+
*
|
|
4
|
+
* @template SubModel - The sub-app's model type.
|
|
5
|
+
* @template SubMsg - The sub-app's message type.
|
|
6
|
+
* @template ParentMsg - The parent app's message type.
|
|
7
|
+
*
|
|
8
|
+
* @param app - The TEA application to mount.
|
|
9
|
+
* @param options - Configuration for the mounted instance.
|
|
10
|
+
* @returns A tuple of `[Surface | LayoutNode, mapped Cmds]`.
|
|
11
|
+
*/
|
|
12
|
+
export function mount(app, options) {
|
|
13
|
+
const { model } = options;
|
|
14
|
+
const surfaceOrNode = app.view(model);
|
|
15
|
+
return [surfaceOrNode, []];
|
|
16
|
+
}
|
|
17
|
+
export function initSubApp(app, options) {
|
|
18
|
+
const [model, cmds] = app.init();
|
|
19
|
+
return [model, mapSubAppCmds(cmds, options)];
|
|
20
|
+
}
|
|
21
|
+
export function updateSubApp(app, msg, model, options) {
|
|
22
|
+
const [nextModel, cmds] = app.update(msg, model);
|
|
23
|
+
return [nextModel, mapSubAppCmds(cmds, options)];
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Helper to map an array of sub-app commands into parent commands.
|
|
27
|
+
*
|
|
28
|
+
* @param cmds - The sub-app commands to map.
|
|
29
|
+
* @param mapper - The message mapping function.
|
|
30
|
+
* @returns An array of commands that emit parent messages.
|
|
31
|
+
*/
|
|
32
|
+
export function mapCmds(cmds, mapper) {
|
|
33
|
+
return cmds.map((cmd) => mapSingleCmd(cmd, mapper));
|
|
34
|
+
}
|
|
35
|
+
function mapSubAppCmds(cmds, options) {
|
|
36
|
+
if (options.mapCmd != null) {
|
|
37
|
+
return cmds.map((cmd) => options.mapCmd(cmd));
|
|
38
|
+
}
|
|
39
|
+
return mapCmds(cmds, options.onMsg);
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Map a single sub-app command to a parent command.
|
|
43
|
+
*/
|
|
44
|
+
function mapSingleCmd(cmd, mapper) {
|
|
45
|
+
return async (emit, caps) => {
|
|
46
|
+
// We intercept the sub-app's `emit` call to wrap its messages
|
|
47
|
+
const mappedEmit = (subMsg) => {
|
|
48
|
+
emit(mapper(subMsg));
|
|
49
|
+
};
|
|
50
|
+
const result = await cmd(mappedEmit, caps);
|
|
51
|
+
// If the command resolves to a final message, map it.
|
|
52
|
+
// Quit signals are passed through unaltered.
|
|
53
|
+
if (result === undefined)
|
|
54
|
+
return undefined;
|
|
55
|
+
if (typeof result === 'symbol')
|
|
56
|
+
return result; // QUIT
|
|
57
|
+
return mapper(result);
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
//# sourceMappingURL=mount.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mount.js","sourceRoot":"","sources":["../../src/subapp/mount.ts"],"names":[],"mappings":"AAsCA;;;;;;;;;;GAUG;AACH,MAAM,UAAU,KAAK,CACnB,GAA0B,EAC1B,OAAkD;IAElD,MAAM,EAAE,KAAK,EAAE,GAAG,OAAO,CAAC;IAE1B,MAAM,aAAa,GAAG,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAEtC,OAAO,CAAC,aAAa,EAAE,EAAE,CAAC,CAAC;AAC7B,CAAC;AAYD,MAAM,UAAU,UAAU,CACxB,GAA0B,EAC1B,OAAyC;IAEzC,MAAM,CAAC,KAAK,EAAE,IAAI,CAAC,GAAG,GAAG,CAAC,IAAI,EAAE,CAAC;IACjC,OAAO,CAAC,KAAK,EAAE,aAAa,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC;AAC/C,CAAC;AAED,MAAM,UAAU,YAAY,CAC1B,GAA0B,EAC1B,GAAW,EACX,KAAe,EACf,OAAyC;IAEzC,MAAM,CAAC,SAAS,EAAE,IAAI,CAAC,GAAG,GAAG,CAAC,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;IACjD,OAAO,CAAC,SAAS,EAAE,aAAa,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC;AACnD,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,OAAO,CACrB,IAAmB,EACnB,MAAkC;IAElC,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,YAAY,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC,CAAC;AACtD,CAAC;AAED,SAAS,aAAa,CACpB,IAAmB,EACnB,OAAyC;IAEzC,IAAI,OAAO,CAAC,MAAM,IAAI,IAAI,EAAE,CAAC;QAC3B,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,OAAO,CAAC,MAAO,CAAC,GAAG,CAAC,CAAC,CAAC;IACjD,CAAC;IACD,OAAO,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,KAAK,CAAC,CAAC;AACtC,CAAC;AAED;;GAEG;AACH,SAAS,YAAY,CACnB,GAAgB,EAChB,MAAkC;IAElC,OAAO,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE;QAC1B,8DAA8D;QAC9D,MAAM,UAAU,GAAG,CAAC,MAAc,EAAE,EAAE;YACpC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC;QACvB,CAAC,CAAC;QAEF,MAAM,MAAM,GAAG,MAAM,GAAG,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC;QAE3C,sDAAsD;QACtD,6CAA6C;QAC7C,IAAI,MAAM,KAAK,SAAS;YAAE,OAAO,SAAS,CAAC;QAC3C,IAAI,OAAO,MAAM,KAAK,QAAQ;YAAE,OAAO,MAAoB,CAAC,CAAC,OAAO;QACpE,OAAO,MAAM,CAAC,MAAgB,CAAC,CAAC;IAClC,CAAC,CAAC;AACJ,CAAC"}
|