reasonix 0.23.1 → 0.24.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 (36) hide show
  1. package/dashboard/dist/app.js +1723 -574
  2. package/dashboard/dist/app.js.map +1 -1
  3. package/dist/cli/.-3G6VX5S7.js +327 -0
  4. package/dist/cli/.-6YRPB2C7.js +329 -0
  5. package/dist/cli/.-6YRPB2C7.js.map +1 -0
  6. package/dist/cli/.-EYSVINK3.js +317 -0
  7. package/dist/cli/.-EYSVINK3.js.map +1 -0
  8. package/dist/cli/banner-demo-QKOPDSTL.js +77 -0
  9. package/dist/cli/banner-demo-QKOPDSTL.js.map +1 -0
  10. package/dist/cli/card-demo-5TVXJISK.js +944 -0
  11. package/dist/cli/card-demo-5TVXJISK.js.map +1 -0
  12. package/dist/cli/chunk-2H7UOFLK.js +11 -0
  13. package/dist/cli/chunk-2H7UOFLK.js.map +1 -0
  14. package/dist/cli/chunk-BGTXZKNY.js +197 -0
  15. package/dist/cli/chunk-BGTXZKNY.js.map +1 -0
  16. package/dist/cli/chunk-JHXQDL7B.js +2056 -0
  17. package/dist/cli/chunk-JHXQDL7B.js.map +1 -0
  18. package/dist/cli/flicker-demo-MOB6GAW4.js +165 -0
  19. package/dist/cli/flicker-demo-MOB6GAW4.js.map +1 -0
  20. package/dist/cli/index.js +3654 -2035
  21. package/dist/cli/index.js.map +1 -1
  22. package/dist/cli/preview-4FOEEE5G.js +224 -0
  23. package/dist/cli/preview-4FOEEE5G.js.map +1 -0
  24. package/dist/cli/{prompt-YUL7CYKY.js → prompt-VZQ2CPID.js} +2 -1
  25. package/dist/cli/prompt-VZQ2CPID.js.map +1 -0
  26. package/dist/cli/renderer-demo-2BIGEV2T.js +95 -0
  27. package/dist/cli/renderer-demo-2BIGEV2T.js.map +1 -0
  28. package/dist/cli/select-demo-OA5N34BJ.js +107 -0
  29. package/dist/cli/select-demo-OA5N34BJ.js.map +1 -0
  30. package/dist/cli/stress-demo-I7XRPQMM.js +211 -0
  31. package/dist/cli/stress-demo-I7XRPQMM.js.map +1 -0
  32. package/dist/index.d.ts +3 -2
  33. package/dist/index.js +22 -9
  34. package/dist/index.js.map +1 -1
  35. package/package.json +6 -4
  36. /package/dist/cli/{prompt-YUL7CYKY.js.map → .-3G6VX5S7.js.map} +0 -0
@@ -0,0 +1,2056 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ __export
4
+ } from "./chunk-2H7UOFLK.js";
5
+
6
+ // src/renderer/react/components.ts
7
+ import React from "react";
8
+ var HOST_BOX = "rsx-box";
9
+ var HOST_TEXT = "rsx-text";
10
+ function Box(props) {
11
+ return React.createElement(HOST_BOX, props);
12
+ }
13
+ function Text(props) {
14
+ return React.createElement(HOST_TEXT, props);
15
+ }
16
+
17
+ // src/renderer/input/use-keystroke.ts
18
+ import { createContext, useContext, useEffect } from "react";
19
+ var KeystrokeContext = createContext(null);
20
+ function useKeystroke(handler, enabled = true) {
21
+ const reader = useContext(KeystrokeContext);
22
+ useEffect(() => {
23
+ if (!enabled || !reader) return;
24
+ const wrapped = (key) => handler(key);
25
+ return reader.subscribe(wrapped);
26
+ }, [reader, handler, enabled]);
27
+ }
28
+
29
+ // src/renderer/input/keystroke.ts
30
+ function emptyKeystroke() {
31
+ return {
32
+ input: "",
33
+ raw: "",
34
+ ctrl: false,
35
+ meta: false,
36
+ shift: false,
37
+ upArrow: false,
38
+ downArrow: false,
39
+ leftArrow: false,
40
+ rightArrow: false,
41
+ home: false,
42
+ end: false,
43
+ pageUp: false,
44
+ pageDown: false,
45
+ delete: false,
46
+ backspace: false,
47
+ return: false,
48
+ escape: false,
49
+ tab: false,
50
+ wheelUp: false,
51
+ wheelDown: false
52
+ };
53
+ }
54
+ var CSI_FINAL = {
55
+ A: { upArrow: true },
56
+ B: { downArrow: true },
57
+ C: { rightArrow: true },
58
+ D: { leftArrow: true },
59
+ H: { home: true },
60
+ F: { end: true }
61
+ };
62
+ var CSI_TILDE = {
63
+ "1": { home: true },
64
+ "3": { delete: true },
65
+ "4": { end: true },
66
+ "5": { pageUp: true },
67
+ "6": { pageDown: true },
68
+ "7": { home: true },
69
+ "8": { end: true }
70
+ };
71
+ function parseKeystrokes(chunk) {
72
+ const out = [];
73
+ let i = 0;
74
+ while (i < chunk.length) {
75
+ const consumed = parseOne(chunk, i);
76
+ if (consumed.length === 0) {
77
+ i++;
78
+ continue;
79
+ }
80
+ out.push(consumed.key);
81
+ i += consumed.length;
82
+ }
83
+ return out;
84
+ }
85
+ var PASTE_START = "\x1B[200~";
86
+ var PASTE_END = "\x1B[201~";
87
+ function parseOne(s, start) {
88
+ const ch = s[start];
89
+ if (ch === "\x1B" && s.startsWith(PASTE_START, start)) {
90
+ const bodyStart = start + PASTE_START.length;
91
+ const endIdx = s.indexOf(PASTE_END, bodyStart);
92
+ if (endIdx >= 0) {
93
+ const content = s.slice(bodyStart, endIdx);
94
+ return {
95
+ key: {
96
+ ...emptyKeystroke(),
97
+ raw: s.slice(start, endIdx + PASTE_END.length),
98
+ input: content
99
+ },
100
+ length: endIdx + PASTE_END.length - start
101
+ };
102
+ }
103
+ }
104
+ if (ch === "\x1B") {
105
+ return parseEscape(s, start);
106
+ }
107
+ if (ch === "\r" || ch === "\n") {
108
+ return { key: { ...emptyKeystroke(), raw: ch, return: true }, length: 1 };
109
+ }
110
+ if (ch === " ") {
111
+ return { key: { ...emptyKeystroke(), raw: ch, tab: true }, length: 1 };
112
+ }
113
+ if (ch === "\x7F" || ch === "\b") {
114
+ return { key: { ...emptyKeystroke(), raw: ch, backspace: true }, length: 1 };
115
+ }
116
+ const code = ch.charCodeAt(0);
117
+ if (code >= 1 && code <= 26 && ch !== " " && ch !== "\r" && ch !== "\n") {
118
+ const letter = String.fromCharCode(code + 96);
119
+ return {
120
+ key: { ...emptyKeystroke(), raw: ch, ctrl: true, input: letter },
121
+ length: 1
122
+ };
123
+ }
124
+ return { key: { ...emptyKeystroke(), raw: ch, input: ch }, length: 1 };
125
+ }
126
+ function parseEscape(s, start) {
127
+ if (start + 1 >= s.length) {
128
+ return { key: { ...emptyKeystroke(), raw: "\x1B", escape: true }, length: 1 };
129
+ }
130
+ const next = s[start + 1];
131
+ if (next === "[" || next === "O") {
132
+ return parseCsi(s, start);
133
+ }
134
+ if (next === "\r" || next === "\n") {
135
+ return {
136
+ key: { ...emptyKeystroke(), raw: `\x1B${next}`, meta: true, return: true },
137
+ length: 2
138
+ };
139
+ }
140
+ if (isPrintable(next)) {
141
+ return {
142
+ key: { ...emptyKeystroke(), raw: `\x1B${next}`, meta: true, input: next },
143
+ length: 2
144
+ };
145
+ }
146
+ return { key: { ...emptyKeystroke(), raw: "\x1B", escape: true }, length: 1 };
147
+ }
148
+ function parseCsi(s, start) {
149
+ let i = start + 2;
150
+ let params = "";
151
+ while (i < s.length) {
152
+ const c = s[i];
153
+ if (isCsiFinal(c)) {
154
+ const raw = s.slice(start, i + 1);
155
+ const key = decodeCsi(params, c, raw);
156
+ return { key, length: i - start + 1 };
157
+ }
158
+ params += c;
159
+ i++;
160
+ }
161
+ return {
162
+ key: { ...emptyKeystroke(), raw: s.slice(start), escape: true },
163
+ length: s.length - start
164
+ };
165
+ }
166
+ function decodeCsi(params, final, raw) {
167
+ const base = { ...emptyKeystroke(), raw };
168
+ if (params.startsWith("<") && (final === "M" || final === "m")) {
169
+ const mouse = params.slice(1).split(";");
170
+ const button = Number.parseInt(mouse[0] ?? "", 10);
171
+ if (button === 64) return { ...base, wheelUp: true };
172
+ if (button === 65) return { ...base, wheelDown: true };
173
+ return base;
174
+ }
175
+ const segments = params.split(";");
176
+ const modCode = segments[1] ? Number.parseInt(segments[1], 10) : 1;
177
+ const mods = decodeModifiers(modCode);
178
+ if (final === "~" && segments[0]) {
179
+ const part2 = CSI_TILDE[segments[0]];
180
+ if (part2) return { ...base, ...part2, ...mods };
181
+ }
182
+ const part = CSI_FINAL[final];
183
+ if (part) return { ...base, ...part, ...mods };
184
+ return { ...base, escape: true };
185
+ }
186
+ function decodeModifiers(code) {
187
+ const m = code - 1;
188
+ return {
189
+ shift: (m & 1) !== 0,
190
+ meta: (m & 2) !== 0,
191
+ ctrl: (m & 4) !== 0
192
+ };
193
+ }
194
+ function isCsiFinal(ch) {
195
+ const code = ch.charCodeAt(0);
196
+ return code >= 64 && code <= 126 && ch !== "[";
197
+ }
198
+ function isPrintable(ch) {
199
+ const code = ch.charCodeAt(0);
200
+ return code >= 32 && code <= 126;
201
+ }
202
+
203
+ // src/renderer/input/reader.ts
204
+ var KeystrokeReader = class {
205
+ constructor(opts) {
206
+ this.opts = opts;
207
+ this.onData = (chunk) => this.handle(chunk);
208
+ if (opts.rawMode !== false) {
209
+ opts.source.setRawMode?.(true);
210
+ }
211
+ opts.source.resume?.();
212
+ opts.source.on("data", this.onData);
213
+ }
214
+ opts;
215
+ listeners = [];
216
+ onData;
217
+ destroyed = false;
218
+ subscribe(listener) {
219
+ this.listeners.push(listener);
220
+ return () => {
221
+ const i = this.listeners.indexOf(listener);
222
+ if (i >= 0) this.listeners.splice(i, 1);
223
+ };
224
+ }
225
+ destroy() {
226
+ if (this.destroyed) return;
227
+ this.destroyed = true;
228
+ this.opts.source.off("data", this.onData);
229
+ if (this.opts.rawMode !== false) {
230
+ this.opts.source.setRawMode?.(false);
231
+ }
232
+ this.listeners.length = 0;
233
+ }
234
+ handle(chunk) {
235
+ if (this.destroyed) return;
236
+ const text = typeof chunk === "string" ? chunk : chunk.toString("utf8");
237
+ const keys = parseKeystrokes(text);
238
+ for (const key of keys) {
239
+ for (const cb of this.listeners) cb(key);
240
+ }
241
+ }
242
+ };
243
+
244
+ // src/renderer/pools/char-pool.ts
245
+ var ASCII_TABLE_SIZE = 128;
246
+ var SPACE_ID = 0;
247
+ var EMPTY_ID = 1;
248
+ var CharPool = class {
249
+ strings;
250
+ map;
251
+ ascii;
252
+ constructor() {
253
+ this.strings = [" ", ""];
254
+ this.map = /* @__PURE__ */ new Map([
255
+ [" ", SPACE_ID],
256
+ ["", EMPTY_ID]
257
+ ]);
258
+ this.ascii = new Int32Array(ASCII_TABLE_SIZE).fill(-1);
259
+ this.ascii[" ".charCodeAt(0)] = SPACE_ID;
260
+ }
261
+ intern(s) {
262
+ if (s.length === 1) {
263
+ const code = s.charCodeAt(0);
264
+ if (code < ASCII_TABLE_SIZE) {
265
+ const cached = this.ascii[code];
266
+ if (cached !== -1) return cached;
267
+ const id2 = this.strings.length;
268
+ this.strings.push(s);
269
+ this.ascii[code] = id2;
270
+ this.map.set(s, id2);
271
+ return id2;
272
+ }
273
+ }
274
+ const existing = this.map.get(s);
275
+ if (existing !== void 0) return existing;
276
+ const id = this.strings.length;
277
+ this.strings.push(s);
278
+ this.map.set(s, id);
279
+ return id;
280
+ }
281
+ get(id) {
282
+ return this.strings[id] ?? " ";
283
+ }
284
+ get size() {
285
+ return this.strings.length;
286
+ }
287
+ };
288
+
289
+ // src/renderer/pools/hyperlink-pool.ts
290
+ var NO_HYPERLINK = 0;
291
+ var HyperlinkPool = class {
292
+ strings = [""];
293
+ map = /* @__PURE__ */ new Map();
294
+ intern(uri) {
295
+ if (!uri) return NO_HYPERLINK;
296
+ const existing = this.map.get(uri);
297
+ if (existing !== void 0) return existing;
298
+ const id = this.strings.length;
299
+ this.strings.push(uri);
300
+ this.map.set(uri, id);
301
+ return id;
302
+ }
303
+ get(id) {
304
+ if (id === NO_HYPERLINK) return void 0;
305
+ return this.strings[id];
306
+ }
307
+ get size() {
308
+ return this.strings.length;
309
+ }
310
+ };
311
+
312
+ // src/renderer/pools/style-pool.ts
313
+ var EMPTY_KEY = "";
314
+ var StylePool = class {
315
+ stacks = [[]];
316
+ idsByKey = /* @__PURE__ */ new Map([[EMPTY_KEY, 0]]);
317
+ transitionCache = /* @__PURE__ */ new Map();
318
+ none = 0;
319
+ intern(codes) {
320
+ const key = stackKey(codes);
321
+ const existing = this.idsByKey.get(key);
322
+ if (existing !== void 0) return existing;
323
+ const id = this.stacks.length;
324
+ this.stacks.push(codes);
325
+ this.idsByKey.set(key, id);
326
+ return id;
327
+ }
328
+ transition(fromId, toId) {
329
+ if (fromId === toId) return "";
330
+ const cacheKey = fromId << 16 | toId;
331
+ const cached = this.transitionCache.get(cacheKey);
332
+ if (cached !== void 0) return cached;
333
+ const from = this.stacks[fromId] ?? [];
334
+ const to = this.stacks[toId] ?? [];
335
+ const fromApplies = new Set(from.map((c) => c.apply));
336
+ const toApplies = new Set(to.map((c) => c.apply));
337
+ let out = "";
338
+ for (const c of from) {
339
+ if (!toApplies.has(c.apply)) out += c.revert;
340
+ }
341
+ for (const c of to) {
342
+ if (!fromApplies.has(c.apply)) out += c.apply;
343
+ }
344
+ this.transitionCache.set(cacheKey, out);
345
+ return out;
346
+ }
347
+ get size() {
348
+ return this.stacks.length;
349
+ }
350
+ };
351
+ function stackKey(codes) {
352
+ if (codes.length === 0) return EMPTY_KEY;
353
+ const applies = codes.map((c) => c.apply);
354
+ applies.sort();
355
+ return applies.join("\0");
356
+ }
357
+
358
+ // src/renderer/reconciler/mount.ts
359
+ import { createElement as createElement3 } from "react";
360
+
361
+ // src/renderer/screen/cell.ts
362
+ var CellWidth = {
363
+ Single: 1,
364
+ Wide: 2,
365
+ /** Occupies the column following a Wide glyph; renderer must skip it. */
366
+ SpacerTail: 3
367
+ };
368
+ var EMPTY_CELL = Object.freeze({
369
+ charId: 0,
370
+ styleId: 0,
371
+ hyperlinkId: 0,
372
+ width: CellWidth.Single
373
+ });
374
+ function cellsEqual(a, b) {
375
+ return a.charId === b.charId && a.styleId === b.styleId && a.hyperlinkId === b.hyperlinkId && a.width === b.width;
376
+ }
377
+
378
+ // src/renderer/screen/diff.ts
379
+ function diffEach(prev, next, cb) {
380
+ const w = Math.max(prev.width, next.width);
381
+ const h = Math.max(prev.height, next.height);
382
+ for (let y = 0; y < h; y++) {
383
+ for (let x = 0; x < w; x++) {
384
+ const a = prev.cellAt(x, y);
385
+ const b = next.cellAt(x, y);
386
+ if (a === b) continue;
387
+ if (a !== void 0 && b !== void 0 && cellsEqual(a, b)) continue;
388
+ if (cb(x, y, a, b) === true) return true;
389
+ }
390
+ }
391
+ return false;
392
+ }
393
+
394
+ // src/renderer/diff/diff-frames.ts
395
+ function diffFrames(prev, next, pools) {
396
+ if (prev.viewportWidth !== next.viewportWidth || prev.viewportHeight !== next.viewportHeight) {
397
+ return fullReset(next, pools);
398
+ }
399
+ const out = [];
400
+ const cursor = {
401
+ x: prev.cursor.x,
402
+ y: prev.cursor.y,
403
+ styleId: pools.style.none,
404
+ hyperlinkId: 0
405
+ };
406
+ diffEach(prev.screen, next.screen, (x, y, _prevCell, nextCell) => {
407
+ moveTo(out, cursor, x, y, next.viewportWidth);
408
+ writeCell(out, cursor, nextCell, pools);
409
+ return void 0;
410
+ });
411
+ if (next.cursor.x !== cursor.x || next.cursor.y !== cursor.y) {
412
+ moveTo(out, cursor, next.cursor.x, next.cursor.y, next.viewportWidth);
413
+ }
414
+ if (prev.cursor.visible !== next.cursor.visible) {
415
+ out.push({ type: "cursorVisible", visible: next.cursor.visible });
416
+ }
417
+ resetTrailingState(out, cursor, pools);
418
+ return out;
419
+ }
420
+ function fullReset(next, pools) {
421
+ const out = [{ type: "clearTerminal" }];
422
+ const cursor = { x: 0, y: 0, styleId: pools.style.none, hyperlinkId: 0 };
423
+ for (let y = 0; y < next.screen.height; y++) {
424
+ for (let x = 0; x < next.screen.width; x++) {
425
+ const cell = next.screen.cellAt(x, y);
426
+ if (!cell) continue;
427
+ if (cell.width === CellWidth.SpacerTail) continue;
428
+ moveTo(out, cursor, x, y, next.viewportWidth);
429
+ writeCell(out, cursor, cell, pools);
430
+ }
431
+ }
432
+ resetTrailingState(out, cursor, pools);
433
+ return out;
434
+ }
435
+ function moveTo(out, cursor, targetX, targetY, viewportWidth) {
436
+ if (cursor.x === targetX && cursor.y === targetY) return;
437
+ if (cursor.x >= viewportWidth) {
438
+ out.push({ type: "carriageReturn" });
439
+ cursor.x = 0;
440
+ }
441
+ if (cursor.y !== targetY) {
442
+ const dy = targetY - cursor.y;
443
+ out.push({ type: "carriageReturn" });
444
+ out.push({ type: "cursorMove", dx: 0, dy });
445
+ cursor.x = 0;
446
+ cursor.y = targetY;
447
+ }
448
+ if (cursor.x !== targetX) {
449
+ out.push({ type: "cursorMove", dx: targetX - cursor.x, dy: 0 });
450
+ cursor.x = targetX;
451
+ }
452
+ }
453
+ function writeCell(out, cursor, cell, pools) {
454
+ if (!cell) {
455
+ transitionStyle(out, cursor, pools.style.none, pools);
456
+ transitionHyperlink(out, cursor, 0, pools);
457
+ out.push({ type: "stdout", content: " " });
458
+ cursor.x++;
459
+ return;
460
+ }
461
+ if (cell.width === CellWidth.SpacerTail) return;
462
+ transitionStyle(out, cursor, cell.styleId, pools);
463
+ transitionHyperlink(out, cursor, cell.hyperlinkId, pools);
464
+ const isWide = cell.width === CellWidth.Wide;
465
+ const charStr = pools.char.get(cell.charId);
466
+ if (isWide) {
467
+ out.push({ type: "cursorTo", col: cursor.x + 1 });
468
+ out.push({ type: "stdout", content: " " });
469
+ out.push({ type: "cursorTo", col: cursor.x });
470
+ out.push({ type: "stdout", content: charStr });
471
+ cursor.x += 2;
472
+ out.push({ type: "cursorTo", col: cursor.x });
473
+ } else {
474
+ out.push({ type: "stdout", content: charStr });
475
+ cursor.x += 1;
476
+ }
477
+ }
478
+ function transitionStyle(out, cursor, targetStyleId, pools) {
479
+ if (cursor.styleId === targetStyleId) return;
480
+ const str = pools.style.transition(cursor.styleId, targetStyleId);
481
+ if (str.length > 0) out.push({ type: "styleStr", str });
482
+ cursor.styleId = targetStyleId;
483
+ }
484
+ function transitionHyperlink(out, cursor, targetId, pools) {
485
+ if (cursor.hyperlinkId === targetId) return;
486
+ out.push({ type: "hyperlink", uri: pools.hyperlink.get(targetId) ?? "" });
487
+ cursor.hyperlinkId = targetId;
488
+ }
489
+ function resetTrailingState(out, cursor, pools) {
490
+ transitionStyle(out, cursor, pools.style.none, pools);
491
+ transitionHyperlink(out, cursor, 0, pools);
492
+ }
493
+
494
+ // src/renderer/screen/screen.ts
495
+ var Screen = class {
496
+ width;
497
+ height;
498
+ cells;
499
+ _damage;
500
+ constructor(width, height) {
501
+ this.width = Math.max(0, width | 0);
502
+ this.height = Math.max(0, height | 0);
503
+ this.cells = new Array(this.width * this.height);
504
+ for (let i = 0; i < this.cells.length; i++) this.cells[i] = EMPTY_CELL;
505
+ this._damage = void 0;
506
+ }
507
+ get damage() {
508
+ return this._damage;
509
+ }
510
+ resetDamage() {
511
+ this._damage = void 0;
512
+ }
513
+ cellAt(x, y) {
514
+ if (x < 0 || x >= this.width || y < 0 || y >= this.height) return void 0;
515
+ return this.cells[y * this.width + x];
516
+ }
517
+ writeCell(x, y, cell) {
518
+ if (x < 0 || x >= this.width || y < 0 || y >= this.height) return;
519
+ this.cells[y * this.width + x] = cell;
520
+ this.markDamage(x, y, 1, 1);
521
+ }
522
+ markDamage(x, y, w, h) {
523
+ if (w <= 0 || h <= 0) return;
524
+ if (this._damage === void 0) {
525
+ this._damage = { x, y, width: w, height: h };
526
+ return;
527
+ }
528
+ const d = this._damage;
529
+ const x1 = Math.min(d.x, x);
530
+ const y1 = Math.min(d.y, y);
531
+ const x2 = Math.max(d.x + d.width, x + w);
532
+ const y2 = Math.max(d.y + d.height, y + h);
533
+ d.x = x1;
534
+ d.y = y1;
535
+ d.width = x2 - x1;
536
+ d.height = y2 - y1;
537
+ }
538
+ };
539
+
540
+ // src/renderer/diff/frame.ts
541
+ function emptyFrame(viewportWidth, viewportHeight) {
542
+ return {
543
+ screen: new Screen(0, 0),
544
+ viewportWidth,
545
+ viewportHeight,
546
+ cursor: { x: 0, y: 0, visible: true }
547
+ };
548
+ }
549
+
550
+ // src/renderer/diff/serialize.ts
551
+ var ESC = "\x1B";
552
+ var CSI = `${ESC}[`;
553
+ var ST = `${ESC}\\`;
554
+ function serializePatches(patches) {
555
+ let out = "";
556
+ for (const patch of patches) {
557
+ out += serializeOne(patch);
558
+ }
559
+ return out;
560
+ }
561
+ function serializeOne(patch) {
562
+ switch (patch.type) {
563
+ case "stdout":
564
+ return patch.content;
565
+ case "cursorMove":
566
+ return cursorMove(patch.dx, patch.dy);
567
+ case "cursorTo":
568
+ return `${CSI}${patch.col + 1}G`;
569
+ case "cursorVisible":
570
+ return patch.visible ? `${CSI}?25h` : `${CSI}?25l`;
571
+ case "carriageReturn":
572
+ return "\r";
573
+ case "styleStr":
574
+ return patch.str;
575
+ case "hyperlink":
576
+ return `${ESC}]8;;${patch.uri}${ST}`;
577
+ case "clear":
578
+ return clearLines(patch.count);
579
+ case "clearTerminal":
580
+ return `${CSI}2J${CSI}H`;
581
+ }
582
+ }
583
+ function cursorMove(dx, dy) {
584
+ let out = "";
585
+ if (dy > 0) out += `${CSI}${dy}B`;
586
+ else if (dy < 0) out += `${CSI}${-dy}A`;
587
+ if (dx > 0) out += `${CSI}${dx}C`;
588
+ else if (dx < 0) out += `${CSI}${-dx}D`;
589
+ return out;
590
+ }
591
+ function clearLines(count) {
592
+ if (count <= 0) return `\r${CSI}J`;
593
+ return `\r${CSI}${count}A${CSI}J`;
594
+ }
595
+
596
+ // src/renderer/ink-compat/renderer-bridge.ts
597
+ import { createContext as createContext2 } from "react";
598
+ var RendererBridgeContext = createContext2(null);
599
+
600
+ // src/renderer/ink-compat/use-app.ts
601
+ import { createContext as createContext3, useContext as useContext2 } from "react";
602
+ var AppContext = createContext3({ exit: () => {
603
+ } });
604
+ function useApp() {
605
+ return useContext2(AppContext);
606
+ }
607
+
608
+ // src/renderer/ink-compat/viewport.ts
609
+ import { createContext as createContext4, createElement, useContext as useContext3, useMemo } from "react";
610
+ var ViewportContext = createContext4({ columns: 80, rows: 24 });
611
+ var StdoutContext = createContext4(
612
+ typeof process !== "undefined" ? process.stdout ?? null : null
613
+ );
614
+ function StdoutProvider({
615
+ stdout,
616
+ children
617
+ }) {
618
+ return createElement(StdoutContext.Provider, { value: stdout }, children);
619
+ }
620
+ function useStdout() {
621
+ const viewport = useContext3(ViewportContext);
622
+ const real = useContext3(StdoutContext);
623
+ return useMemo(() => {
624
+ const stdout = {
625
+ columns: viewport.columns,
626
+ rows: viewport.rows,
627
+ isTTY: real ? real.isTTY : void 0,
628
+ write: real ? (data) => real.write(data) : () => true,
629
+ on: real ? (event, listener) => real.on(event, listener) : () => void 0,
630
+ off: real ? (event, listener) => real.off(event, listener) : () => void 0
631
+ };
632
+ return { stdout, write: stdout.write };
633
+ }, [viewport.columns, viewport.rows, real]);
634
+ }
635
+
636
+ // src/renderer/layout/layout.ts
637
+ import stringWidthRaw from "string-width";
638
+
639
+ // src/renderer/layout/yoga-layout.ts
640
+ import Yoga, {
641
+ Align,
642
+ BoxSizing,
643
+ Direction,
644
+ Display,
645
+ Edge,
646
+ FlexDirection,
647
+ Gutter,
648
+ Justify,
649
+ MeasureMode,
650
+ Wrap
651
+ } from "yoga-layout";
652
+
653
+ // src/renderer/layout/borders.ts
654
+ var BORDER_PRESETS = {
655
+ single: {
656
+ topLeft: "\u250C",
657
+ top: "\u2500",
658
+ topRight: "\u2510",
659
+ left: "\u2502",
660
+ right: "\u2502",
661
+ bottomLeft: "\u2514",
662
+ bottom: "\u2500",
663
+ bottomRight: "\u2518"
664
+ },
665
+ double: {
666
+ topLeft: "\u2554",
667
+ top: "\u2550",
668
+ topRight: "\u2557",
669
+ left: "\u2551",
670
+ right: "\u2551",
671
+ bottomLeft: "\u255A",
672
+ bottom: "\u2550",
673
+ bottomRight: "\u255D"
674
+ },
675
+ round: {
676
+ topLeft: "\u256D",
677
+ top: "\u2500",
678
+ topRight: "\u256E",
679
+ left: "\u2502",
680
+ right: "\u2502",
681
+ bottomLeft: "\u2570",
682
+ bottom: "\u2500",
683
+ bottomRight: "\u256F"
684
+ },
685
+ bold: {
686
+ topLeft: "\u250F",
687
+ top: "\u2501",
688
+ topRight: "\u2513",
689
+ left: "\u2503",
690
+ right: "\u2503",
691
+ bottomLeft: "\u2517",
692
+ bottom: "\u2501",
693
+ bottomRight: "\u251B"
694
+ },
695
+ ascii: {
696
+ topLeft: "+",
697
+ top: "-",
698
+ topRight: "+",
699
+ left: "|",
700
+ right: "|",
701
+ bottomLeft: "+",
702
+ bottom: "-",
703
+ bottomRight: "+"
704
+ }
705
+ };
706
+ function resolveBorderStyle(style) {
707
+ if (style === void 0) return void 0;
708
+ if (typeof style === "string") return BORDER_PRESETS[style];
709
+ return style;
710
+ }
711
+
712
+ // src/renderer/layout/yoga-layout.ts
713
+ var ALIGN_MAP = {
714
+ "flex-start": Align.FlexStart,
715
+ "flex-end": Align.FlexEnd,
716
+ center: Align.Center,
717
+ stretch: Align.Stretch,
718
+ baseline: Align.Baseline
719
+ };
720
+ var JUSTIFY_MAP = {
721
+ "flex-start": Justify.FlexStart,
722
+ "flex-end": Justify.FlexEnd,
723
+ center: Justify.Center,
724
+ "space-between": Justify.SpaceBetween,
725
+ "space-around": Justify.SpaceAround,
726
+ "space-evenly": Justify.SpaceEvenly
727
+ };
728
+ function buildYogaTree(node, pools, measureText2) {
729
+ const meta = /* @__PURE__ */ new WeakMap();
730
+ const children = /* @__PURE__ */ new Map();
731
+ const root = build(node, pools, measureText2, meta, children);
732
+ return { root, meta, children };
733
+ }
734
+ function build(node, pools, measureText2, meta, children) {
735
+ if (node.kind === "text") {
736
+ return buildText(node, pools, measureText2, meta);
737
+ }
738
+ return buildBox(node, pools, measureText2, meta, children);
739
+ }
740
+ function buildText(node, pools, measureText2, meta) {
741
+ const yoga = Yoga.Node.create();
742
+ yoga.setBoxSizing(BoxSizing.BorderBox);
743
+ yoga.setFlexShrink(1);
744
+ const measure = (width, widthMode) => measureText2(node.content, width, widthMode);
745
+ yoga.setMeasureFunc(measure);
746
+ const styleId = node.style ? pools.style.intern(node.style) : pools.style.none;
747
+ const hyperlinkId = pools.hyperlink.intern(node.hyperlink);
748
+ meta.set(yoga, {
749
+ node,
750
+ useTop: false,
751
+ useBottom: false,
752
+ useLeft: false,
753
+ useRight: false,
754
+ styleId,
755
+ hyperlinkId
756
+ });
757
+ return yoga;
758
+ }
759
+ function buildBox(node, pools, measureText2, meta, children) {
760
+ const yoga = Yoga.Node.create();
761
+ yoga.setBoxSizing(BoxSizing.BorderBox);
762
+ yoga.setFlexShrink(1);
763
+ applyBoxStyle(yoga, node);
764
+ const border = resolveBorderStyle(node.borderStyle);
765
+ const useTop = border !== void 0 && node.borderTop !== false;
766
+ const useBottom = border !== void 0 && node.borderBottom !== false;
767
+ const useLeft = border !== void 0 && node.borderLeft !== false;
768
+ const useRight = border !== void 0 && node.borderRight !== false;
769
+ if (useTop) yoga.setBorder(Edge.Top, 1);
770
+ if (useBottom) yoga.setBorder(Edge.Bottom, 1);
771
+ if (useLeft) yoga.setBorder(Edge.Left, 1);
772
+ if (useRight) yoga.setBorder(Edge.Right, 1);
773
+ meta.set(yoga, {
774
+ node,
775
+ border,
776
+ useTop,
777
+ useBottom,
778
+ useLeft,
779
+ useRight,
780
+ styleId: 0,
781
+ hyperlinkId: 0
782
+ });
783
+ const childList = [];
784
+ for (let i = 0; i < node.children.length; i++) {
785
+ const childYoga = build(node.children[i], pools, measureText2, meta, children);
786
+ yoga.insertChild(childYoga, i);
787
+ childList.push(childYoga);
788
+ }
789
+ children.set(yoga, childList);
790
+ return yoga;
791
+ }
792
+ function applyBoxStyle(yoga, node) {
793
+ if (node.flexDirection === "row") yoga.setFlexDirection(FlexDirection.Row);
794
+ else if (node.flexDirection === "row-reverse") yoga.setFlexDirection(FlexDirection.RowReverse);
795
+ else if (node.flexDirection === "column-reverse")
796
+ yoga.setFlexDirection(FlexDirection.ColumnReverse);
797
+ else yoga.setFlexDirection(FlexDirection.Column);
798
+ if (node.flexGrow !== void 0) yoga.setFlexGrow(node.flexGrow);
799
+ if (node.flexShrink !== void 0) yoga.setFlexShrink(node.flexShrink);
800
+ if (node.flexBasis !== void 0) yoga.setFlexBasis(node.flexBasis);
801
+ if (node.flexWrap === "wrap") yoga.setFlexWrap(Wrap.Wrap);
802
+ else if (node.flexWrap === "wrap-reverse") yoga.setFlexWrap(Wrap.WrapReverse);
803
+ if (node.justifyContent) yoga.setJustifyContent(JUSTIFY_MAP[node.justifyContent]);
804
+ if (node.alignItems) yoga.setAlignItems(ALIGN_MAP[node.alignItems]);
805
+ if (node.alignSelf) yoga.setAlignSelf(ALIGN_MAP[node.alignSelf]);
806
+ if (node.alignContent) {
807
+ if (node.alignContent === "space-between") yoga.setAlignContent(Align.SpaceBetween);
808
+ else if (node.alignContent === "space-around") yoga.setAlignContent(Align.SpaceAround);
809
+ else yoga.setAlignContent(ALIGN_MAP[node.alignContent]);
810
+ }
811
+ if (node.width !== void 0) yoga.setWidth(node.width);
812
+ if (node.height !== void 0) yoga.setHeight(node.height);
813
+ if (node.minWidth !== void 0) yoga.setMinWidth(node.minWidth);
814
+ if (node.minHeight !== void 0) yoga.setMinHeight(node.minHeight);
815
+ if (node.maxWidth !== void 0) yoga.setMaxWidth(node.maxWidth);
816
+ if (node.maxHeight !== void 0) yoga.setMaxHeight(node.maxHeight);
817
+ if (node.gap !== void 0) yoga.setGap(Gutter.All, node.gap);
818
+ if (node.rowGap !== void 0) yoga.setGap(Gutter.Row, node.rowGap);
819
+ if (node.columnGap !== void 0) yoga.setGap(Gutter.Column, node.columnGap);
820
+ if (node.paddingTop !== void 0) yoga.setPadding(Edge.Top, node.paddingTop);
821
+ if (node.paddingBottom !== void 0) yoga.setPadding(Edge.Bottom, node.paddingBottom);
822
+ if (node.paddingLeft !== void 0) yoga.setPadding(Edge.Left, node.paddingLeft);
823
+ if (node.paddingRight !== void 0) yoga.setPadding(Edge.Right, node.paddingRight);
824
+ if (node.marginTop !== void 0) yoga.setMargin(Edge.Top, node.marginTop);
825
+ if (node.marginBottom !== void 0) yoga.setMargin(Edge.Bottom, node.marginBottom);
826
+ if (node.marginLeft !== void 0) yoga.setMargin(Edge.Left, node.marginLeft);
827
+ if (node.marginRight !== void 0) yoga.setMargin(Edge.Right, node.marginRight);
828
+ if (node.display === "none") yoga.setDisplay(Display.None);
829
+ }
830
+
831
+ // src/renderer/layout/layout.ts
832
+ function stringWidth(s) {
833
+ if (s.length === 0) return 0;
834
+ if (s.length === 1) {
835
+ const code = s.charCodeAt(0);
836
+ if (code >= 9472 && code <= 9631) return 1;
837
+ }
838
+ return stringWidthRaw(s, { ambiguousIsNarrow: false });
839
+ }
840
+ function renderToScreen(node, width, pools, maxHeight) {
841
+ const w = Math.max(0, width | 0);
842
+ if (w === 0) return new Screen(0, 0);
843
+ const laid = layout(node, w, pools);
844
+ const cap = maxHeight !== void 0 ? Math.max(0, Math.floor(maxHeight)) : laid.rows.length;
845
+ const skip = Math.max(0, laid.rows.length - cap);
846
+ return blitRowSlice(laid.rows, skip, laid.rows.length, w, pools);
847
+ }
848
+ function renderViewport(node, width, pools, maxHeight) {
849
+ const w = Math.max(0, width | 0);
850
+ if (w === 0) {
851
+ return {
852
+ screen: new Screen(0, 0),
853
+ skipped: 0,
854
+ totalRows: 0,
855
+ serializePromoted: () => ""
856
+ };
857
+ }
858
+ const laid = layout(node, w, pools);
859
+ const cap = Math.max(0, Math.floor(maxHeight));
860
+ const skipped = Math.max(0, laid.rows.length - cap);
861
+ const screen = blitRowSlice(laid.rows, skipped, laid.rows.length, w, pools);
862
+ return {
863
+ screen,
864
+ skipped,
865
+ totalRows: laid.rows.length,
866
+ serializePromoted: (fromRow, toRow) => serializeRowSlice(
867
+ laid.rows,
868
+ Math.max(0, fromRow),
869
+ Math.min(toRow, laid.rows.length),
870
+ w,
871
+ pools
872
+ )
873
+ };
874
+ }
875
+ function blitRowSlice(rows, fromRow, toRow, width, pools) {
876
+ const h = Math.max(0, toRow - fromRow);
877
+ const screen = new Screen(width, h);
878
+ for (let y = 0; y < h; y++) {
879
+ for (const frag of rows[y + fromRow]) blitFragment(screen, frag, y, pools);
880
+ }
881
+ screen.resetDamage();
882
+ return screen;
883
+ }
884
+ function renderVirtual(node, width, pools) {
885
+ const w = Math.max(0, width | 0);
886
+ if (w === 0) {
887
+ return {
888
+ totalRows: 0,
889
+ windowAt: () => new Screen(0, 0)
890
+ };
891
+ }
892
+ const laid = layout(node, w, pools);
893
+ return {
894
+ totalRows: laid.rows.length,
895
+ windowAt(scrollOffset, windowHeight) {
896
+ const start = Math.max(0, Math.min(laid.rows.length, Math.floor(scrollOffset)));
897
+ const end = Math.max(start, Math.min(laid.rows.length, start + Math.floor(windowHeight)));
898
+ return blitRowSlice(laid.rows, start, end, w, pools);
899
+ }
900
+ };
901
+ }
902
+ function serializeRowSlice(rows, fromRow, toRow, width, pools) {
903
+ if (toRow <= fromRow) return "";
904
+ const screen = blitRowSlice(rows, fromRow, toRow, width, pools);
905
+ let out = "";
906
+ let curStyle = pools.style.none;
907
+ let curLink = 0;
908
+ for (let y = 0; y < screen.height; y++) {
909
+ if (y > 0) {
910
+ out += pools.style.transition(curStyle, pools.style.none);
911
+ curStyle = pools.style.none;
912
+ if (curLink !== 0) {
913
+ out += "\x1B]8;;\x1B\\";
914
+ curLink = 0;
915
+ }
916
+ out += "\r\n";
917
+ }
918
+ for (let x = 0; x < screen.width; x++) {
919
+ const cell = screen.cellAt(x, y);
920
+ if (!cell) continue;
921
+ if (cell.width === CellWidth.SpacerTail) continue;
922
+ if (cell.styleId !== curStyle) {
923
+ out += pools.style.transition(curStyle, cell.styleId);
924
+ curStyle = cell.styleId;
925
+ }
926
+ if (cell.hyperlinkId !== curLink) {
927
+ const uri = pools.hyperlink.get(cell.hyperlinkId) ?? "";
928
+ out += `\x1B]8;;${uri}\x1B\\`;
929
+ curLink = cell.hyperlinkId;
930
+ }
931
+ out += pools.char.get(cell.charId);
932
+ }
933
+ }
934
+ out += pools.style.transition(curStyle, pools.style.none);
935
+ if (curLink !== 0) out += "\x1B]8;;\x1B\\";
936
+ out += "\r\n";
937
+ return out;
938
+ }
939
+ function layout(node, availableWidth, pools) {
940
+ if (availableWidth <= 0) return { rows: [], width: 0 };
941
+ const built = buildYogaTree(node, pools, measureText);
942
+ built.root.calculateLayout(availableWidth, "auto", Direction.LTR);
943
+ const rootTop = Math.max(0, Math.round(built.root.getComputedTop()));
944
+ const rootLeft = Math.max(0, Math.round(built.root.getComputedLeft()));
945
+ const innerHeight = Math.max(0, Math.ceil(built.root.getComputedHeight()));
946
+ const innerWidth = Math.max(0, Math.ceil(built.root.getComputedWidth()));
947
+ const bottomMargin = node.kind === "box" ? Math.max(0, node.marginBottom ?? 0) : 0;
948
+ const rightMargin = node.kind === "box" ? Math.max(0, node.marginRight ?? 0) : 0;
949
+ const totalHeight = rootTop + innerHeight + bottomMargin;
950
+ const totalWidth = rootLeft + innerWidth + rightMargin;
951
+ const rows = [];
952
+ for (let i = 0; i < totalHeight; i++) rows.push([]);
953
+ rasterize(built.root, built, 0, 0, rows, pools);
954
+ built.root.freeRecursive();
955
+ return { rows, width: totalWidth };
956
+ }
957
+ function rasterize(yoga, built, parentX, parentY, rows, pools) {
958
+ const meta = built.meta.get(yoga);
959
+ if (!meta) return;
960
+ const left = parentX + Math.round(yoga.getComputedLeft());
961
+ const top = parentY + Math.round(yoga.getComputedTop());
962
+ const width = Math.max(0, Math.round(yoga.getComputedWidth()));
963
+ const height = Math.max(0, Math.round(yoga.getComputedHeight()));
964
+ if (meta.node.kind === "text") {
965
+ rasterizeText(meta.node, left, top, width, height, meta.styleId, meta.hyperlinkId, rows);
966
+ return;
967
+ }
968
+ const box = meta.node;
969
+ if (meta.border) {
970
+ paintBorder(meta, box, left, top, width, height, rows, pools);
971
+ }
972
+ const childList = built.children.get(yoga) ?? [];
973
+ for (const child of childList) {
974
+ rasterize(child, built, left, top, rows, pools);
975
+ }
976
+ }
977
+ function rasterizeText(text, x, y, width, height, styleId, hyperlinkId, rows) {
978
+ if (width <= 0 || height <= 0 || y < 0) return;
979
+ const segmenter = getSegmenter();
980
+ let lineIdx = 0;
981
+ for (const rawLine of text.content.split("\n")) {
982
+ if (lineIdx >= height) break;
983
+ const wrapped = wrapLine(rawLine, width, segmenter);
984
+ if (wrapped.length === 0) {
985
+ pushFragment(rows, y + lineIdx, { graphemes: [], styleId, hyperlinkId, leftPad: x });
986
+ lineIdx++;
987
+ continue;
988
+ }
989
+ for (const row of wrapped) {
990
+ if (lineIdx >= height) break;
991
+ pushFragment(rows, y + lineIdx, { graphemes: row, styleId, hyperlinkId, leftPad: x });
992
+ lineIdx++;
993
+ }
994
+ }
995
+ }
996
+ function paintBorder(meta, box, left, top, width, height, rows, pools) {
997
+ if (!meta.border || width <= 0 || height <= 0) return;
998
+ const border = meta.border;
999
+ const topColor = pickStyleId(box.borderTopColor ?? box.borderColor, pools);
1000
+ const bottomColor = pickStyleId(box.borderBottomColor ?? box.borderColor, pools);
1001
+ const leftColor = pickStyleId(box.borderLeftColor ?? box.borderColor, pools);
1002
+ const rightColor = pickStyleId(box.borderRightColor ?? box.borderColor, pools);
1003
+ if (meta.useTop) {
1004
+ paintHorizontalEdge(
1005
+ rows,
1006
+ top,
1007
+ left,
1008
+ width,
1009
+ border,
1010
+ "top",
1011
+ meta.useLeft,
1012
+ meta.useRight,
1013
+ topColor
1014
+ );
1015
+ }
1016
+ if (meta.useBottom && height > 1) {
1017
+ paintHorizontalEdge(
1018
+ rows,
1019
+ top + height - 1,
1020
+ left,
1021
+ width,
1022
+ border,
1023
+ "bottom",
1024
+ meta.useLeft,
1025
+ meta.useRight,
1026
+ bottomColor
1027
+ );
1028
+ }
1029
+ const innerTop = top + (meta.useTop ? 1 : 0);
1030
+ const innerBottom = top + height - (meta.useBottom ? 2 : 1);
1031
+ for (let r = innerTop; r <= innerBottom; r++) {
1032
+ if (meta.useLeft) {
1033
+ pushFragment(rows, r, {
1034
+ graphemes: [{ glyph: border.left, width: Math.max(1, stringWidth(border.left)) }],
1035
+ styleId: leftColor,
1036
+ hyperlinkId: 0,
1037
+ leftPad: left
1038
+ });
1039
+ }
1040
+ if (meta.useRight && width > 1) {
1041
+ pushFragment(rows, r, {
1042
+ graphemes: [{ glyph: border.right, width: Math.max(1, stringWidth(border.right)) }],
1043
+ styleId: rightColor,
1044
+ hyperlinkId: 0,
1045
+ leftPad: left + width - 1
1046
+ });
1047
+ }
1048
+ }
1049
+ }
1050
+ function paintHorizontalEdge(rows, y, x, width, style, side, useLeft, useRight, styleId) {
1051
+ if (width <= 0 || y < 0) return;
1052
+ const corners = side === "top" ? [style.topLeft, style.topRight] : [style.bottomLeft, style.bottomRight];
1053
+ const edge = side === "top" ? style.top : style.bottom;
1054
+ const graphemes = [];
1055
+ for (let i = 0; i < width; i++) {
1056
+ let glyph;
1057
+ if (i === 0 && useLeft) glyph = corners[0];
1058
+ else if (i === width - 1 && useRight) glyph = corners[1];
1059
+ else glyph = edge;
1060
+ graphemes.push({ glyph, width: Math.max(1, stringWidth(glyph)) });
1061
+ }
1062
+ pushFragment(rows, y, { graphemes, styleId, hyperlinkId: 0, leftPad: x });
1063
+ }
1064
+ function pushFragment(rows, y, frag) {
1065
+ if (y < 0) return;
1066
+ while (rows.length <= y) rows.push([]);
1067
+ rows[y].push(frag);
1068
+ }
1069
+ function pickStyleId(color, pools) {
1070
+ return color ? pools.style.intern(color) : pools.style.none;
1071
+ }
1072
+ function measureText(content, width, widthMode) {
1073
+ const segmenter = getSegmenter();
1074
+ if (widthMode === MeasureMode.Undefined || width < 0) {
1075
+ let maxW2 = 0;
1076
+ let lines = 0;
1077
+ for (const line of content.split("\n")) {
1078
+ lines += 1;
1079
+ const w = stringWidth(line);
1080
+ if (w > maxW2) maxW2 = w;
1081
+ }
1082
+ return { width: maxW2, height: Math.max(1, lines) };
1083
+ }
1084
+ let maxW = 0;
1085
+ let totalLines = 0;
1086
+ for (const rawLine of content.split("\n")) {
1087
+ const wrapped = wrapLine(rawLine, Math.floor(width), segmenter);
1088
+ if (wrapped.length === 0) {
1089
+ totalLines += 1;
1090
+ continue;
1091
+ }
1092
+ totalLines += wrapped.length;
1093
+ for (const row of wrapped) {
1094
+ let w = 0;
1095
+ for (const g of row) w += g.width;
1096
+ if (w > maxW) maxW = w;
1097
+ }
1098
+ }
1099
+ return { width: maxW, height: Math.max(1, totalLines) };
1100
+ }
1101
+ function wrapLine(line, width, segmenter) {
1102
+ if (width <= 0) return [];
1103
+ const rows = [];
1104
+ let current = [];
1105
+ let used = 0;
1106
+ for (const seg of segmenter.segment(line)) {
1107
+ const glyph = seg.segment;
1108
+ const gw = Math.max(0, stringWidth(glyph));
1109
+ if (gw === 0) continue;
1110
+ if (used + gw > width) {
1111
+ if (current.length > 0) rows.push(current);
1112
+ current = [];
1113
+ used = 0;
1114
+ if (gw > width) continue;
1115
+ }
1116
+ current.push({ glyph, width: gw });
1117
+ used += gw;
1118
+ }
1119
+ if (current.length > 0) rows.push(current);
1120
+ return rows;
1121
+ }
1122
+ function blitFragment(screen, frag, y, pools) {
1123
+ let x = frag.leftPad;
1124
+ for (const { glyph, width } of frag.graphemes) {
1125
+ if (x >= screen.width) break;
1126
+ const charId = pools.char.intern(glyph);
1127
+ const cell = {
1128
+ charId,
1129
+ styleId: frag.styleId,
1130
+ hyperlinkId: frag.hyperlinkId,
1131
+ width: width === 2 ? CellWidth.Wide : CellWidth.Single
1132
+ };
1133
+ screen.writeCell(x, y, cell);
1134
+ if (width === 2 && x + 1 < screen.width) {
1135
+ screen.writeCell(x + 1, y, {
1136
+ charId: 1,
1137
+ styleId: frag.styleId,
1138
+ hyperlinkId: frag.hyperlinkId,
1139
+ width: CellWidth.SpacerTail
1140
+ });
1141
+ }
1142
+ x += width;
1143
+ }
1144
+ }
1145
+ var _segmenter;
1146
+ function getSegmenter() {
1147
+ if (_segmenter) return _segmenter;
1148
+ _segmenter = new Intl.Segmenter(void 0, { granularity: "grapheme" });
1149
+ return _segmenter;
1150
+ }
1151
+
1152
+ // src/renderer/runtime/render-to-bytes.ts
1153
+ import { createElement as createElement2 } from "react";
1154
+
1155
+ // src/renderer/reconciler/host-config.ts
1156
+ import ReactReconciler from "react-reconciler";
1157
+
1158
+ // src/renderer/reconciler/host-node.ts
1159
+ function makeHostBox(props) {
1160
+ return { type: "box", props, children: [], parent: null };
1161
+ }
1162
+ function makeHostText(props) {
1163
+ return { type: "text", props, children: [], parent: null };
1164
+ }
1165
+ function makeHostRawText(text) {
1166
+ return { type: "raw-text", text, parent: null };
1167
+ }
1168
+ function hostToLayoutNode(node) {
1169
+ if (node.type === "raw-text") {
1170
+ return { kind: "text", content: node.text };
1171
+ }
1172
+ if (node.type === "text") {
1173
+ return {
1174
+ kind: "text",
1175
+ content: collectText(node.children),
1176
+ ...node.props.style ? { style: node.props.style } : {},
1177
+ ...node.props.hyperlink ? { hyperlink: node.props.hyperlink } : {}
1178
+ };
1179
+ }
1180
+ const layoutChildren = [];
1181
+ for (const c of node.children) {
1182
+ const child = hostToLayoutNode(c);
1183
+ if (child) layoutChildren.push(child);
1184
+ }
1185
+ const p = node.props;
1186
+ const out = { kind: "box", children: layoutChildren };
1187
+ return assignBoxProps(out, p);
1188
+ }
1189
+ function collectText(children) {
1190
+ let out = "";
1191
+ for (const child of children) {
1192
+ if (child.type === "raw-text") out += child.text;
1193
+ else if (child.type === "text") out += collectText(child.children);
1194
+ }
1195
+ return out;
1196
+ }
1197
+ function assignBoxProps(node, props) {
1198
+ const result = { ...node };
1199
+ const padAll = props.padding;
1200
+ const padX = props.paddingX ?? padAll;
1201
+ const padY = props.paddingY ?? padAll;
1202
+ const padTop = props.paddingTop ?? padY;
1203
+ const padBottom = props.paddingBottom ?? padY;
1204
+ const padLeft = props.paddingLeft ?? padX;
1205
+ const padRight = props.paddingRight ?? padX;
1206
+ if (padTop !== void 0) result.paddingTop = padTop;
1207
+ if (padBottom !== void 0) result.paddingBottom = padBottom;
1208
+ if (padLeft !== void 0) result.paddingLeft = padLeft;
1209
+ if (padRight !== void 0) result.paddingRight = padRight;
1210
+ const marginAll = props.margin;
1211
+ const marginX = props.marginX ?? marginAll;
1212
+ const marginY = props.marginY ?? marginAll;
1213
+ const marginTop = props.marginTop ?? marginY;
1214
+ const marginBottom = props.marginBottom ?? marginY;
1215
+ const marginLeft = props.marginLeft ?? marginX;
1216
+ const marginRight = props.marginRight ?? marginX;
1217
+ if (marginTop !== void 0) result.marginTop = marginTop;
1218
+ if (marginBottom !== void 0) result.marginBottom = marginBottom;
1219
+ if (marginLeft !== void 0) result.marginLeft = marginLeft;
1220
+ if (marginRight !== void 0) result.marginRight = marginRight;
1221
+ if (props.flexDirection !== void 0) result.flexDirection = props.flexDirection;
1222
+ if (props.flexGrow !== void 0) result.flexGrow = props.flexGrow;
1223
+ if (props.flexShrink !== void 0) result.flexShrink = props.flexShrink;
1224
+ if (props.flexBasis !== void 0) result.flexBasis = props.flexBasis;
1225
+ if (props.flexWrap !== void 0) result.flexWrap = props.flexWrap;
1226
+ if (props.justifyContent !== void 0) result.justifyContent = props.justifyContent;
1227
+ if (props.alignItems !== void 0) result.alignItems = props.alignItems;
1228
+ if (props.alignSelf !== void 0) result.alignSelf = props.alignSelf;
1229
+ if (props.alignContent !== void 0) result.alignContent = props.alignContent;
1230
+ if (props.width !== void 0) result.width = props.width;
1231
+ if (props.height !== void 0) result.height = props.height;
1232
+ if (props.minWidth !== void 0) result.minWidth = props.minWidth;
1233
+ if (props.minHeight !== void 0) result.minHeight = props.minHeight;
1234
+ if (props.maxWidth !== void 0) result.maxWidth = props.maxWidth;
1235
+ if (props.maxHeight !== void 0) result.maxHeight = props.maxHeight;
1236
+ if (props.gap !== void 0) result.gap = props.gap;
1237
+ if (props.columnGap !== void 0) result.columnGap = props.columnGap;
1238
+ if (props.rowGap !== void 0) result.rowGap = props.rowGap;
1239
+ if (props.display !== void 0) result.display = props.display;
1240
+ if (props.borderStyle !== void 0) result.borderStyle = props.borderStyle;
1241
+ if (props.borderTop !== void 0) result.borderTop = props.borderTop;
1242
+ if (props.borderBottom !== void 0) result.borderBottom = props.borderBottom;
1243
+ if (props.borderLeft !== void 0) result.borderLeft = props.borderLeft;
1244
+ if (props.borderRight !== void 0) result.borderRight = props.borderRight;
1245
+ if (props.borderColor !== void 0) result.borderColor = props.borderColor;
1246
+ if (props.borderTopColor !== void 0) result.borderTopColor = props.borderTopColor;
1247
+ if (props.borderBottomColor !== void 0) result.borderBottomColor = props.borderBottomColor;
1248
+ if (props.borderLeftColor !== void 0) result.borderLeftColor = props.borderLeftColor;
1249
+ if (props.borderRightColor !== void 0) result.borderRightColor = props.borderRightColor;
1250
+ return result;
1251
+ }
1252
+
1253
+ // src/renderer/reconciler/host-config.ts
1254
+ var hostConfig = {
1255
+ supportsMutation: true,
1256
+ supportsPersistence: false,
1257
+ supportsHydration: false,
1258
+ // We're the only React renderer in this process. `false` would put us on
1259
+ // React's shared non-primary context-stack — re-entrant updateContainer
1260
+ // (the Static / emitStatic path) crashed against that. `true` gives us our
1261
+ // own context state, no shared-stack collisions.
1262
+ isPrimaryRenderer: true,
1263
+ noTimeout: -1,
1264
+ createInstance(type, props) {
1265
+ if (type === HOST_BOX) return makeHostBox(props);
1266
+ if (type === HOST_TEXT) return makeHostText(props);
1267
+ throw new Error(`Reasonix renderer: unsupported element type: ${String(type)}`);
1268
+ },
1269
+ createTextInstance(text) {
1270
+ return makeHostRawText(text);
1271
+ },
1272
+ appendInitialChild(parent, child) {
1273
+ parent.children.push(child);
1274
+ child.parent = parent;
1275
+ },
1276
+ appendChild(parent, child) {
1277
+ parent.children.push(child);
1278
+ child.parent = parent;
1279
+ },
1280
+ appendChildToContainer(container, child) {
1281
+ container.children.push(child);
1282
+ child.parent = null;
1283
+ },
1284
+ insertBefore(parent, child, beforeChild) {
1285
+ const idx = parent.children.indexOf(beforeChild);
1286
+ if (idx < 0) parent.children.push(child);
1287
+ else parent.children.splice(idx, 0, child);
1288
+ child.parent = parent;
1289
+ },
1290
+ insertInContainerBefore(container, child, beforeChild) {
1291
+ const idx = container.children.indexOf(beforeChild);
1292
+ if (idx < 0) container.children.push(child);
1293
+ else container.children.splice(idx, 0, child);
1294
+ child.parent = null;
1295
+ },
1296
+ removeChild(parent, child) {
1297
+ const idx = parent.children.indexOf(child);
1298
+ if (idx >= 0) parent.children.splice(idx, 1);
1299
+ child.parent = null;
1300
+ },
1301
+ removeChildFromContainer(container, child) {
1302
+ const idx = container.children.indexOf(child);
1303
+ if (idx >= 0) container.children.splice(idx, 1);
1304
+ },
1305
+ finalizeInitialChildren() {
1306
+ return false;
1307
+ },
1308
+ prepareUpdate(_instance, _type, _oldProps, newProps) {
1309
+ return newProps;
1310
+ },
1311
+ commitUpdate(instance, payload) {
1312
+ instance.props = payload;
1313
+ },
1314
+ commitTextUpdate(textInstance, _oldText, newText) {
1315
+ textInstance.text = newText;
1316
+ },
1317
+ resetTextContent() {
1318
+ },
1319
+ shouldSetTextContent() {
1320
+ return false;
1321
+ },
1322
+ getRootHostContext() {
1323
+ return {};
1324
+ },
1325
+ getChildHostContext() {
1326
+ return {};
1327
+ },
1328
+ getPublicInstance(instance) {
1329
+ return instance;
1330
+ },
1331
+ prepareForCommit() {
1332
+ return null;
1333
+ },
1334
+ resetAfterCommit(container) {
1335
+ container.onCommit();
1336
+ },
1337
+ preparePortalMount() {
1338
+ },
1339
+ scheduleTimeout: setTimeout,
1340
+ cancelTimeout: clearTimeout,
1341
+ getCurrentEventPriority() {
1342
+ return DefaultEventPriority;
1343
+ },
1344
+ getInstanceFromNode() {
1345
+ return null;
1346
+ },
1347
+ beforeActiveInstanceBlur() {
1348
+ },
1349
+ afterActiveInstanceBlur() {
1350
+ },
1351
+ prepareScopeUpdate() {
1352
+ },
1353
+ getInstanceFromScope() {
1354
+ return null;
1355
+ },
1356
+ detachDeletedInstance() {
1357
+ },
1358
+ clearContainer(container) {
1359
+ container.children.length = 0;
1360
+ }
1361
+ };
1362
+ var DefaultEventPriority = 16;
1363
+ var reconciler = ReactReconciler(hostConfig);
1364
+
1365
+ // src/renderer/runtime/render-to-bytes.ts
1366
+ var ESC2 = "\x1B";
1367
+ var ST2 = `${ESC2}\\`;
1368
+ function renderToBytes(element, width, pools) {
1369
+ const layout2 = renderTreeToLayout(element, width);
1370
+ const screen = renderToScreen(layout2, width, pools);
1371
+ if (screen.height === 0) return "";
1372
+ let out = "";
1373
+ let curStyle = pools.style.none;
1374
+ let curLink = 0;
1375
+ for (let y = 0; y < screen.height; y++) {
1376
+ if (y > 0) {
1377
+ out += pools.style.transition(curStyle, pools.style.none);
1378
+ curStyle = pools.style.none;
1379
+ if (curLink !== 0) {
1380
+ out += `${ESC2}]8;;${ST2}`;
1381
+ curLink = 0;
1382
+ }
1383
+ out += "\r\n";
1384
+ }
1385
+ for (let x = 0; x < screen.width; x++) {
1386
+ const cell = screen.cellAt(x, y);
1387
+ if (!cell) continue;
1388
+ if (cell.width === CellWidth.SpacerTail) continue;
1389
+ if (cell.styleId !== curStyle) {
1390
+ out += pools.style.transition(curStyle, cell.styleId);
1391
+ curStyle = cell.styleId;
1392
+ }
1393
+ if (cell.hyperlinkId !== curLink) {
1394
+ const uri = pools.hyperlink.get(cell.hyperlinkId) ?? "";
1395
+ out += `${ESC2}]8;;${uri}${ST2}`;
1396
+ curLink = cell.hyperlinkId;
1397
+ }
1398
+ out += pools.char.get(cell.charId);
1399
+ }
1400
+ }
1401
+ out += pools.style.transition(curStyle, pools.style.none);
1402
+ if (curLink !== 0) out += `${ESC2}]8;;${ST2}`;
1403
+ out += "\r\n";
1404
+ return out;
1405
+ }
1406
+ function renderTreeToLayout(element, width) {
1407
+ const root = {
1408
+ children: [],
1409
+ onCommit: () => {
1410
+ }
1411
+ };
1412
+ const container = reconciler.createContainer(
1413
+ root,
1414
+ 0,
1415
+ // LegacyMode — sync
1416
+ null,
1417
+ false,
1418
+ null,
1419
+ "rsx-static",
1420
+ () => {
1421
+ },
1422
+ null
1423
+ );
1424
+ const wrapped = createElement2(
1425
+ ViewportContext.Provider,
1426
+ { value: { columns: width, rows: 24 } },
1427
+ element
1428
+ );
1429
+ reconciler.updateContainer(wrapped, container, null, () => {
1430
+ });
1431
+ const layoutChildren = [];
1432
+ for (const c of root.children) {
1433
+ const child = hostToLayoutNode(c);
1434
+ if (child) layoutChildren.push(child);
1435
+ }
1436
+ const layout2 = layoutChildren.length === 1 ? layoutChildren[0] : { kind: "box", children: layoutChildren };
1437
+ reconciler.updateContainer(null, container, null, () => {
1438
+ });
1439
+ return layout2;
1440
+ }
1441
+
1442
+ // src/renderer/reconciler/cursor.ts
1443
+ import { createContext as createContext5, useContext as useContext4, useEffect as useEffect2 } from "react";
1444
+ var CursorContext = createContext5(null);
1445
+ function useCursor(target) {
1446
+ const setter = useContext4(CursorContext);
1447
+ const isSet = target !== null;
1448
+ const col = target?.col ?? 0;
1449
+ const rowFromBottom = target?.rowFromBottom ?? 0;
1450
+ const visible = target?.visible !== false;
1451
+ useEffect2(() => {
1452
+ if (!setter) return;
1453
+ if (!isSet) {
1454
+ setter(null);
1455
+ return;
1456
+ }
1457
+ setter({ col, rowFromBottom, visible });
1458
+ return () => setter(null);
1459
+ }, [setter, isSet, col, rowFromBottom, visible]);
1460
+ }
1461
+
1462
+ // src/renderer/reconciler/mount.ts
1463
+ var RESET_SGR = "\x1B[0m";
1464
+ var CLOSE_HYPERLINK = "\x1B]8;;\x1B\\";
1465
+ var ENTER_VIRTUAL = "\x1B[?1049h\x1B[2J\x1B[H\x1B[?1002h\x1B[?1006h";
1466
+ var LEAVE_VIRTUAL = "\x1B[?1006l\x1B[?1002l\x1B[?1000l\x1B[?1049l";
1467
+ function mount(element, opts) {
1468
+ const scrollMode = opts.scroll ?? "scrollback";
1469
+ let viewportWidth = opts.viewportWidth;
1470
+ let viewportHeight = opts.viewportHeight;
1471
+ let frame = emptyFrame(viewportWidth, viewportHeight);
1472
+ let reservedRows = 0;
1473
+ let promotedRows = 0;
1474
+ let scrollOffset = 0;
1475
+ let stickyBottom = true;
1476
+ let lastTotalRows = 0;
1477
+ let destroyed = false;
1478
+ let lastElement = element;
1479
+ const reader = opts.stdin ? new KeystrokeReader({ source: opts.stdin }) : null;
1480
+ let cursorTarget = null;
1481
+ const setCursorTarget = (next) => {
1482
+ cursorTarget = next;
1483
+ if (!destroyed && root.children.length > 0) root.onCommit();
1484
+ };
1485
+ const computeCursor = (screenHeight) => {
1486
+ if (cursorTarget) {
1487
+ const rowFromBottom = Math.max(0, cursorTarget.rowFromBottom ?? 0);
1488
+ const y = Math.max(0, screenHeight - 1 - rowFromBottom);
1489
+ return {
1490
+ x: Math.max(0, cursorTarget.col),
1491
+ y,
1492
+ visible: cursorTarget.visible !== false
1493
+ };
1494
+ }
1495
+ if (opts.cursor) return opts.cursor();
1496
+ return { x: 0, y: screenHeight, visible: true };
1497
+ };
1498
+ const scrollBy = (delta) => {
1499
+ if (scrollMode !== "virtual") return;
1500
+ const window = Math.max(1, viewportHeight - 1);
1501
+ const maxOffset = Math.max(0, lastTotalRows - window);
1502
+ const next = Math.max(0, Math.min(maxOffset, scrollOffset + delta));
1503
+ if (next === scrollOffset) return;
1504
+ scrollOffset = next;
1505
+ stickyBottom = next === maxOffset;
1506
+ if (root.children.length > 0) {
1507
+ root.onCommit();
1508
+ }
1509
+ };
1510
+ let exitCleanup = null;
1511
+ let signalCleanup = null;
1512
+ if (scrollMode === "virtual") {
1513
+ opts.write(ENTER_VIRTUAL);
1514
+ if (reader) {
1515
+ reader.subscribe((k) => {
1516
+ const window = Math.max(1, viewportHeight - 1);
1517
+ if (k.pageUp) scrollBy(-window);
1518
+ else if (k.pageDown) scrollBy(window);
1519
+ else if (k.home) scrollBy(-Number.MAX_SAFE_INTEGER);
1520
+ else if (k.end) scrollBy(Number.MAX_SAFE_INTEGER);
1521
+ else if (k.wheelUp) scrollBy(-3);
1522
+ else if (k.wheelDown) scrollBy(3);
1523
+ });
1524
+ }
1525
+ if (typeof process !== "undefined" && process.on) {
1526
+ exitCleanup = () => {
1527
+ try {
1528
+ opts.write(LEAVE_VIRTUAL);
1529
+ } catch {
1530
+ }
1531
+ };
1532
+ signalCleanup = () => process.exit(130);
1533
+ process.on("exit", exitCleanup);
1534
+ process.on("SIGINT", signalCleanup);
1535
+ process.on("SIGTERM", signalCleanup);
1536
+ }
1537
+ }
1538
+ const commitScrollback = (layout2) => {
1539
+ const maxHeight = Math.max(1, viewportHeight - 1);
1540
+ const split = renderViewport(layout2, viewportWidth, opts.pools, maxHeight);
1541
+ const newPromote = Math.max(0, split.skipped - promotedRows);
1542
+ let out = "";
1543
+ if (newPromote > 0) {
1544
+ if (frame.screen.height > 0) {
1545
+ out += `\r\x1B[${frame.screen.height}A\x1B[J`;
1546
+ } else if (reservedRows === 0) {
1547
+ out += "\r\x1B[J";
1548
+ }
1549
+ out += split.serializePromoted(promotedRows, split.skipped);
1550
+ promotedRows = split.skipped;
1551
+ frame = emptyFrame(viewportWidth, viewportHeight);
1552
+ reservedRows = 0;
1553
+ }
1554
+ const screen = split.screen;
1555
+ const targetReserve = Math.min(screen.height, Math.max(0, viewportHeight - 1));
1556
+ if (targetReserve > reservedRows) {
1557
+ const delta = targetReserve - reservedRows;
1558
+ if (reservedRows === 0) out += "\r";
1559
+ out += `${"\n".repeat(delta)}\x1B[${delta}A`;
1560
+ reservedRows = targetReserve;
1561
+ }
1562
+ const next = {
1563
+ screen,
1564
+ viewportWidth,
1565
+ viewportHeight,
1566
+ cursor: computeCursor(screen.height)
1567
+ };
1568
+ const patches = diffFrames(frame, next, opts.pools);
1569
+ if (patches.length > 0) out += serializePatches(patches);
1570
+ if (out.length > 0) opts.write(out);
1571
+ frame = next;
1572
+ };
1573
+ const commitVirtual = (layout2) => {
1574
+ const window = Math.max(1, viewportHeight - 1);
1575
+ const virt = renderVirtual(layout2, viewportWidth, opts.pools);
1576
+ const maxOffset = Math.max(0, virt.totalRows - window);
1577
+ if (stickyBottom || virt.totalRows < lastTotalRows) {
1578
+ scrollOffset = maxOffset;
1579
+ } else {
1580
+ scrollOffset = Math.min(scrollOffset, maxOffset);
1581
+ }
1582
+ lastTotalRows = virt.totalRows;
1583
+ const screen = virt.windowAt(scrollOffset, window);
1584
+ const targetReserve = Math.min(window, Math.max(0, viewportHeight - 1));
1585
+ let out = "";
1586
+ if (targetReserve > reservedRows) {
1587
+ const delta = targetReserve - reservedRows;
1588
+ if (reservedRows === 0) out += "\r";
1589
+ out += `${"\n".repeat(delta)}\x1B[${delta}A`;
1590
+ reservedRows = targetReserve;
1591
+ }
1592
+ const next = {
1593
+ screen,
1594
+ viewportWidth,
1595
+ viewportHeight,
1596
+ cursor: computeCursor(screen.height)
1597
+ };
1598
+ const patches = diffFrames(frame, next, opts.pools);
1599
+ if (patches.length > 0) out += serializePatches(patches);
1600
+ if (out.length > 0) opts.write(out);
1601
+ frame = next;
1602
+ };
1603
+ const root = {
1604
+ children: [],
1605
+ onCommit: () => {
1606
+ if (destroyed) return;
1607
+ const layout2 = collectRootLayout(root.children);
1608
+ if (scrollMode === "virtual") {
1609
+ commitVirtual(layout2);
1610
+ } else {
1611
+ commitScrollback(layout2);
1612
+ }
1613
+ }
1614
+ };
1615
+ const container = reconciler.createContainer(
1616
+ root,
1617
+ 0,
1618
+ null,
1619
+ false,
1620
+ null,
1621
+ "rsx",
1622
+ () => {
1623
+ },
1624
+ null
1625
+ );
1626
+ const emitStatic = (node) => {
1627
+ if (destroyed) return;
1628
+ queueMicrotask(() => {
1629
+ if (destroyed) return;
1630
+ const bytes = renderToBytes(node, viewportWidth, opts.pools);
1631
+ if (bytes.length === 0) return;
1632
+ let out = "";
1633
+ if (frame.screen.height > 0) {
1634
+ out += `\r\x1B[${frame.screen.height}A\x1B[J`;
1635
+ } else {
1636
+ out += "\r\x1B[J";
1637
+ }
1638
+ out += bytes;
1639
+ opts.write(out);
1640
+ frame = emptyFrame(viewportWidth, viewportHeight);
1641
+ reservedRows = 0;
1642
+ root.onCommit();
1643
+ });
1644
+ };
1645
+ const bridge = { emitStatic };
1646
+ const appApi = {
1647
+ exit: (error) => {
1648
+ if (destroyed) return;
1649
+ queueMicrotask(() => opts.onExit?.(error));
1650
+ }
1651
+ };
1652
+ const wrap = (node) => {
1653
+ const withApp = createElement3(AppContext.Provider, { value: appApi }, node);
1654
+ const withBridge = createElement3(
1655
+ RendererBridgeContext.Provider,
1656
+ { value: bridge },
1657
+ withApp
1658
+ );
1659
+ const withViewport = createElement3(
1660
+ ViewportContext.Provider,
1661
+ { value: { columns: viewportWidth, rows: viewportHeight } },
1662
+ withBridge
1663
+ );
1664
+ const stdoutForCtx = opts.stdout ?? (typeof process !== "undefined" ? process.stdout : void 0);
1665
+ const withStdout = stdoutForCtx ? createElement3(StdoutContext.Provider, { value: stdoutForCtx }, withViewport) : withViewport;
1666
+ const withCursor = createElement3(
1667
+ CursorContext.Provider,
1668
+ { value: setCursorTarget },
1669
+ withStdout
1670
+ );
1671
+ return reader ? createElement3(KeystrokeContext.Provider, { value: reader }, withCursor) : withCursor;
1672
+ };
1673
+ reconciler.updateContainer(wrap(element), container, null, () => {
1674
+ });
1675
+ return {
1676
+ update(nextElement) {
1677
+ if (destroyed) return;
1678
+ lastElement = nextElement;
1679
+ reconciler.updateContainer(wrap(nextElement), container, null, () => {
1680
+ });
1681
+ },
1682
+ resize(width, height) {
1683
+ if (destroyed) return;
1684
+ viewportWidth = width;
1685
+ viewportHeight = height;
1686
+ frame = emptyFrame(width, height);
1687
+ reservedRows = 0;
1688
+ promotedRows = 0;
1689
+ scrollOffset = 0;
1690
+ stickyBottom = true;
1691
+ lastTotalRows = 0;
1692
+ opts.write("\x1B[2J\x1B[H");
1693
+ reconciler.updateContainer(wrap(lastElement), container, null, () => {
1694
+ });
1695
+ },
1696
+ emitStatic,
1697
+ destroy() {
1698
+ if (destroyed) return;
1699
+ destroyed = true;
1700
+ reader?.destroy();
1701
+ reconciler.updateContainer(null, container, null, () => {
1702
+ });
1703
+ const teardown = scrollMode === "virtual" ? LEAVE_VIRTUAL : "";
1704
+ opts.write(`${teardown}${RESET_SGR}${CLOSE_HYPERLINK}`);
1705
+ if (exitCleanup && typeof process !== "undefined" && process.off) {
1706
+ process.off("exit", exitCleanup);
1707
+ exitCleanup = null;
1708
+ }
1709
+ if (signalCleanup && typeof process !== "undefined" && process.off) {
1710
+ process.off("SIGINT", signalCleanup);
1711
+ process.off("SIGTERM", signalCleanup);
1712
+ signalCleanup = null;
1713
+ }
1714
+ }
1715
+ };
1716
+ }
1717
+ function collectRootLayout(children) {
1718
+ const layoutChildren = [];
1719
+ for (const c of children) {
1720
+ const child = hostToLayoutNode(c);
1721
+ if (child) layoutChildren.push(child);
1722
+ }
1723
+ if (layoutChildren.length === 1) return layoutChildren[0];
1724
+ return { kind: "box", children: layoutChildren };
1725
+ }
1726
+
1727
+ // src/renderer/ink-compat/index.ts
1728
+ var ink_compat_exports = {};
1729
+ __export(ink_compat_exports, {
1730
+ AppContext: () => AppContext,
1731
+ Box: () => Box2,
1732
+ RendererBridgeContext: () => RendererBridgeContext,
1733
+ Spacer: () => Spacer,
1734
+ Static: () => Static,
1735
+ StdoutContext: () => StdoutContext,
1736
+ StdoutProvider: () => StdoutProvider,
1737
+ Text: () => Text2,
1738
+ ViewportContext: () => ViewportContext,
1739
+ bgCode: () => bgCode,
1740
+ fgCode: () => fgCode,
1741
+ render: () => render,
1742
+ useApp: () => useApp,
1743
+ useInput: () => useInput,
1744
+ useStdout: () => useStdout
1745
+ });
1746
+
1747
+ // src/renderer/ink-compat/Box.tsx
1748
+ import React2 from "react";
1749
+
1750
+ // src/renderer/ink-compat/colors.ts
1751
+ var FG_BASE = {
1752
+ black: 30,
1753
+ red: 31,
1754
+ green: 32,
1755
+ yellow: 33,
1756
+ blue: 34,
1757
+ magenta: 35,
1758
+ cyan: 36,
1759
+ white: 37,
1760
+ gray: 90,
1761
+ grey: 90,
1762
+ blackBright: 90,
1763
+ redBright: 91,
1764
+ greenBright: 92,
1765
+ yellowBright: 93,
1766
+ blueBright: 94,
1767
+ magentaBright: 95,
1768
+ cyanBright: 96,
1769
+ whiteBright: 97
1770
+ };
1771
+ var FG_RESET = 39;
1772
+ var BG_RESET = 49;
1773
+ function fgCode(color) {
1774
+ if (!color) return null;
1775
+ if (color.startsWith("#")) {
1776
+ const rgb = parseHex(color);
1777
+ if (!rgb) return null;
1778
+ return { apply: `\x1B[38;2;${rgb[0]};${rgb[1]};${rgb[2]}m`, revert: `\x1B[${FG_RESET}m` };
1779
+ }
1780
+ const code = FG_BASE[color];
1781
+ if (code === void 0) return null;
1782
+ return { apply: `\x1B[${code}m`, revert: `\x1B[${FG_RESET}m` };
1783
+ }
1784
+ function bgCode(color) {
1785
+ if (!color) return null;
1786
+ if (color.startsWith("#")) {
1787
+ const rgb = parseHex(color);
1788
+ if (!rgb) return null;
1789
+ return { apply: `\x1B[48;2;${rgb[0]};${rgb[1]};${rgb[2]}m`, revert: `\x1B[${BG_RESET}m` };
1790
+ }
1791
+ const base = FG_BASE[color];
1792
+ if (base === void 0) return null;
1793
+ const bg = base < 90 ? base + 10 : base + 10;
1794
+ return { apply: `\x1B[${bg}m`, revert: `\x1B[${BG_RESET}m` };
1795
+ }
1796
+ function parseHex(hex) {
1797
+ const s = hex.slice(1);
1798
+ if (s.length === 3) {
1799
+ const r = Number.parseInt(s[0] + s[0], 16);
1800
+ const g = Number.parseInt(s[1] + s[1], 16);
1801
+ const b = Number.parseInt(s[2] + s[2], 16);
1802
+ return Number.isNaN(r) ? null : [r, g, b];
1803
+ }
1804
+ if (s.length === 6) {
1805
+ const r = Number.parseInt(s.slice(0, 2), 16);
1806
+ const g = Number.parseInt(s.slice(2, 4), 16);
1807
+ const b = Number.parseInt(s.slice(4, 6), 16);
1808
+ return Number.isNaN(r) ? null : [r, g, b];
1809
+ }
1810
+ return null;
1811
+ }
1812
+
1813
+ // src/renderer/ink-compat/Box.tsx
1814
+ function Box2(props) {
1815
+ const borderColor = fgCode(props.borderColor);
1816
+ const borderTopColor = fgCode(props.borderTopColor);
1817
+ const borderBottomColor = fgCode(props.borderBottomColor);
1818
+ const borderLeftColor = fgCode(props.borderLeftColor);
1819
+ const borderRightColor = fgCode(props.borderRightColor);
1820
+ return /* @__PURE__ */ React2.createElement(
1821
+ Box,
1822
+ {
1823
+ flexDirection: props.flexDirection ?? "row",
1824
+ flexGrow: props.flexGrow,
1825
+ flexShrink: props.flexShrink,
1826
+ flexBasis: props.flexBasis,
1827
+ flexWrap: props.flexWrap,
1828
+ justifyContent: props.justifyContent,
1829
+ alignItems: props.alignItems,
1830
+ alignSelf: props.alignSelf,
1831
+ alignContent: props.alignContent,
1832
+ width: props.width,
1833
+ height: props.height,
1834
+ minWidth: props.minWidth,
1835
+ minHeight: props.minHeight,
1836
+ maxWidth: props.maxWidth,
1837
+ maxHeight: props.maxHeight,
1838
+ gap: props.gap,
1839
+ columnGap: props.columnGap,
1840
+ rowGap: props.rowGap,
1841
+ display: props.display,
1842
+ padding: props.padding,
1843
+ paddingX: props.paddingX,
1844
+ paddingY: props.paddingY,
1845
+ paddingTop: props.paddingTop,
1846
+ paddingBottom: props.paddingBottom,
1847
+ paddingLeft: props.paddingLeft,
1848
+ paddingRight: props.paddingRight,
1849
+ margin: props.margin,
1850
+ marginX: props.marginX,
1851
+ marginY: props.marginY,
1852
+ marginTop: props.marginTop,
1853
+ marginBottom: props.marginBottom,
1854
+ marginLeft: props.marginLeft,
1855
+ marginRight: props.marginRight,
1856
+ borderStyle: props.borderStyle,
1857
+ borderColor: borderColor ? [borderColor] : void 0,
1858
+ borderTopColor: borderTopColor ? [borderTopColor] : void 0,
1859
+ borderBottomColor: borderBottomColor ? [borderBottomColor] : void 0,
1860
+ borderLeftColor: borderLeftColor ? [borderLeftColor] : void 0,
1861
+ borderRightColor: borderRightColor ? [borderRightColor] : void 0,
1862
+ borderTop: props.borderTop,
1863
+ borderBottom: props.borderBottom,
1864
+ borderLeft: props.borderLeft,
1865
+ borderRight: props.borderRight
1866
+ },
1867
+ props.children
1868
+ );
1869
+ }
1870
+
1871
+ // src/renderer/ink-compat/Text.tsx
1872
+ import React3 from "react";
1873
+ var SGR = {
1874
+ bold: { apply: "\x1B[1m", revert: "\x1B[22m" },
1875
+ dim: { apply: "\x1B[2m", revert: "\x1B[22m" },
1876
+ italic: { apply: "\x1B[3m", revert: "\x1B[23m" },
1877
+ underline: { apply: "\x1B[4m", revert: "\x1B[24m" },
1878
+ inverse: { apply: "\x1B[7m", revert: "\x1B[27m" },
1879
+ strikethrough: { apply: "\x1B[9m", revert: "\x1B[29m" }
1880
+ };
1881
+ function Text2(props) {
1882
+ const codes = [];
1883
+ const fg = fgCode(props.color);
1884
+ if (fg) codes.push(fg);
1885
+ const bg = bgCode(props.backgroundColor);
1886
+ if (bg) codes.push(bg);
1887
+ if (props.bold) codes.push(SGR.bold);
1888
+ if (props.dimColor) codes.push(SGR.dim);
1889
+ if (props.italic) codes.push(SGR.italic);
1890
+ if (props.underline) codes.push(SGR.underline);
1891
+ if (props.inverse) codes.push(SGR.inverse);
1892
+ if (props.strikethrough) codes.push(SGR.strikethrough);
1893
+ return /* @__PURE__ */ React3.createElement(Text, { style: codes.length > 0 ? codes : void 0 }, props.children);
1894
+ }
1895
+
1896
+ // src/renderer/ink-compat/Spacer.tsx
1897
+ import React4 from "react";
1898
+ function Spacer() {
1899
+ return /* @__PURE__ */ React4.createElement(Box, { flexGrow: 1 });
1900
+ }
1901
+
1902
+ // src/renderer/ink-compat/Static.tsx
1903
+ import React5, { useContext as useContext5, useEffect as useEffect3, useRef } from "react";
1904
+ function Static(props) {
1905
+ const bridge = useContext5(RendererBridgeContext);
1906
+ const lastIndex = useRef(0);
1907
+ useEffect3(() => {
1908
+ if (!bridge) return;
1909
+ if (props.items.length < lastIndex.current) {
1910
+ lastIndex.current = props.items.length;
1911
+ return;
1912
+ }
1913
+ if (props.items.length === lastIndex.current) return;
1914
+ const fresh = props.items.slice(lastIndex.current);
1915
+ const startIndex = lastIndex.current;
1916
+ lastIndex.current = props.items.length;
1917
+ bridge.emitStatic(
1918
+ /* @__PURE__ */ React5.createElement(Box, { flexDirection: "column" }, fresh.map((item, i) => (
1919
+ // biome-ignore lint/suspicious/noArrayIndexKey: Static items are positional and append-only
1920
+ /* @__PURE__ */ React5.createElement(React5.Fragment, { key: `s-${startIndex + i}` }, props.children(item, startIndex + i))
1921
+ )))
1922
+ );
1923
+ }, [bridge, props.items, props.children]);
1924
+ if (bridge) return null;
1925
+ return /* @__PURE__ */ React5.createElement(Box, { flexDirection: "column" }, props.items.map((item, i) => (
1926
+ // biome-ignore lint/suspicious/noArrayIndexKey: fallback path with no bridge — positional keys are fine
1927
+ /* @__PURE__ */ React5.createElement(React5.Fragment, { key: `s-${i}` }, props.children(item, i))
1928
+ )));
1929
+ }
1930
+
1931
+ // src/renderer/ink-compat/use-input.ts
1932
+ function useInput(handler, options = {}) {
1933
+ const active = options.isActive !== false;
1934
+ useKeystroke((k) => {
1935
+ if (!active) return;
1936
+ handler(k.input ?? "", toInkKey(k));
1937
+ });
1938
+ }
1939
+ function toInkKey(k) {
1940
+ return {
1941
+ upArrow: k.upArrow,
1942
+ downArrow: k.downArrow,
1943
+ leftArrow: k.leftArrow,
1944
+ rightArrow: k.rightArrow,
1945
+ pageDown: k.pageDown,
1946
+ pageUp: k.pageUp,
1947
+ return: k.return,
1948
+ escape: k.escape,
1949
+ ctrl: k.ctrl,
1950
+ shift: k.shift,
1951
+ tab: k.tab,
1952
+ backspace: k.backspace,
1953
+ delete: k.delete,
1954
+ meta: k.meta
1955
+ };
1956
+ }
1957
+
1958
+ // src/renderer/ink-compat/render.tsx
1959
+ function render(element, opts = {}) {
1960
+ const stdout = opts.stdout ?? process.stdout;
1961
+ const stdin = opts.stdin ?? process.stdin;
1962
+ const exitOnCtrlC = opts.exitOnCtrlC !== false;
1963
+ const pools = {
1964
+ char: new CharPool(),
1965
+ style: new StylePool(),
1966
+ hyperlink: new HyperlinkPool()
1967
+ };
1968
+ let resolveExit = () => {
1969
+ };
1970
+ let exitError;
1971
+ const exitPromise = new Promise((resolve, reject) => {
1972
+ resolveExit = () => {
1973
+ if (exitError) reject(exitError);
1974
+ else resolve();
1975
+ };
1976
+ });
1977
+ let destroyed = false;
1978
+ let handle = null;
1979
+ const onResize = () => {
1980
+ if (destroyed || !handle) return;
1981
+ handle.resize(stdout.columns ?? 80, stdout.rows ?? 24);
1982
+ };
1983
+ const onCtrlCData = (chunk) => {
1984
+ if (destroyed || !exitOnCtrlC) return;
1985
+ const text = typeof chunk === "string" ? chunk : chunk.toString("utf8");
1986
+ if (text.includes("")) instance.unmount();
1987
+ };
1988
+ handle = mount(element, {
1989
+ viewportWidth: stdout.columns ?? 80,
1990
+ viewportHeight: stdout.rows ?? 24,
1991
+ pools,
1992
+ write: (bytes) => stdout.write(bytes),
1993
+ stdin,
1994
+ stdout,
1995
+ onExit: (err) => {
1996
+ if (destroyed) return;
1997
+ if (err) exitError = err;
1998
+ instance.unmount();
1999
+ }
2000
+ });
2001
+ stdout.on("resize", onResize);
2002
+ stdin.on("data", onCtrlCData);
2003
+ const sigintListener = () => {
2004
+ if (!destroyed) instance.unmount();
2005
+ };
2006
+ if (exitOnCtrlC) process.on("SIGINT", sigintListener);
2007
+ const instance = {
2008
+ rerender(next) {
2009
+ if (destroyed || !handle) return;
2010
+ handle.update(next);
2011
+ },
2012
+ unmount() {
2013
+ if (destroyed) return;
2014
+ destroyed = true;
2015
+ stdout.off("resize", onResize);
2016
+ stdin.off("data", onCtrlCData);
2017
+ if (exitOnCtrlC) process.off("SIGINT", sigintListener);
2018
+ handle?.destroy();
2019
+ handle = null;
2020
+ resolveExit();
2021
+ },
2022
+ waitUntilExit() {
2023
+ return exitPromise;
2024
+ },
2025
+ cleanup() {
2026
+ },
2027
+ clear() {
2028
+ if (destroyed) return;
2029
+ stdout.write("\x1B[2J\x1B[H");
2030
+ }
2031
+ };
2032
+ return instance;
2033
+ }
2034
+
2035
+ // src/renderer/react/render.ts
2036
+ import { Fragment, isValidElement } from "react";
2037
+
2038
+ export {
2039
+ Box,
2040
+ Text,
2041
+ Box2,
2042
+ Text2,
2043
+ Static,
2044
+ useStdout,
2045
+ useApp,
2046
+ useKeystroke,
2047
+ useInput,
2048
+ CharPool,
2049
+ HyperlinkPool,
2050
+ StylePool,
2051
+ useCursor,
2052
+ mount,
2053
+ render,
2054
+ ink_compat_exports
2055
+ };
2056
+ //# sourceMappingURL=chunk-JHXQDL7B.js.map