@dkkoval/tui-preview 0.1.1 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,93 +1,474 @@
1
- var H = Object.defineProperty;
2
- var $ = (e, t, n) => t in e ? H(e, t, { enumerable: !0, configurable: !0, writable: !0, value: n }) : e[t] = n;
3
- var k = (e, t, n) => $(e, typeof t != "symbol" ? t + "" : t, n);
4
- import { jsxs as D, jsx as L } from "react/jsx-runtime";
5
- import { useMemo as Y, useRef as M, useState as R, useEffect as T } from "react";
6
- let p = null;
7
- function q() {
8
- return p || (p = import("./ghostty-web-BfBVpf8G.js").then(async (e) => (await e.init(), e))), p;
1
+ var it = Object.defineProperty;
2
+ var ot = (e, t, n) => t in e ? it(e, t, { enumerable: !0, configurable: !0, writable: !0, value: n }) : e[t] = n;
3
+ var F = (e, t, n) => ot(e, typeof t != "symbol" ? t + "" : t, n);
4
+ import { jsxs as O, jsx as H } from "react/jsx-runtime";
5
+ import { useMemo as at, useRef as P, useState as $, useEffect as N } from "react";
6
+ const S = 16, T = 80, tt = "/ghostty-vt.wasm", ct = 1, lt = 2, ht = 4, W = 8, K = 16, ut = 32, R = 64, Y = 128, ft = [
7
+ "black",
8
+ "red",
9
+ "green",
10
+ "yellow",
11
+ "blue",
12
+ "magenta",
13
+ "cyan",
14
+ "white",
15
+ "brightBlack",
16
+ "brightRed",
17
+ "brightGreen",
18
+ "brightYellow",
19
+ "brightBlue",
20
+ "brightMagenta",
21
+ "brightCyan",
22
+ "brightWhite"
23
+ ], wt = {
24
+ background: "#1a1b26",
25
+ foreground: "#a9b1d6",
26
+ cursor: "#c0caf5",
27
+ selectionBackground: "#33467c",
28
+ selectionForeground: "#c0caf5",
29
+ black: "#15161e",
30
+ red: "#f7768e",
31
+ green: "#9ece6a",
32
+ yellow: "#e0af68",
33
+ blue: "#7aa2f7",
34
+ magenta: "#bb9af7",
35
+ cyan: "#7dcfff",
36
+ white: "#a9b1d6",
37
+ brightBlack: "#414868",
38
+ brightRed: "#f7768e",
39
+ brightGreen: "#9ece6a",
40
+ brightYellow: "#e0af68",
41
+ brightBlue: "#7aa2f7",
42
+ brightMagenta: "#bb9af7",
43
+ brightCyan: "#7dcfff",
44
+ brightWhite: "#c0caf5"
45
+ };
46
+ class mt {
47
+ constructor(t, n) {
48
+ this.wasm = t, this.abi = n;
49
+ }
50
+ createTerminal(t, n, r) {
51
+ const o = this.wasm.ghostty_wasm_alloc_u8_array(this.abi.terminalConfigSize);
52
+ if (!o)
53
+ throw new Error("Failed to allocate terminal config.");
54
+ try {
55
+ const i = new DataView(this.wasm.memory.buffer);
56
+ let s = o;
57
+ i.setUint32(s, 1e4, !0), s += 4, i.setUint32(s, z(r.foreground), !0), s += 4, i.setUint32(s, z(r.background), !0), s += 4, i.setUint32(s, z(r.cursor), !0), s += 4;
58
+ for (const c of ft)
59
+ i.setUint32(s, z(r[c]), !0), s += 4;
60
+ const a = this.wasm.ghostty_terminal_new_with_config(t, n, o);
61
+ if (!a)
62
+ throw new Error("Failed to create libghostty terminal.");
63
+ return new dt(this.wasm, a, t, n, this.abi.cellSize);
64
+ } finally {
65
+ this.wasm.ghostty_wasm_free_u8_array(o, this.abi.terminalConfigSize);
66
+ }
67
+ }
9
68
  }
10
- const S = { cols: 80, rows: 24 }, P = {}, Z = [];
11
- function J(e) {
12
- return "wasm" in e;
69
+ class dt {
70
+ constructor(t, n, r, o, i) {
71
+ F(this, "viewportPtr", 0);
72
+ F(this, "viewportLen", 0);
73
+ this.wasm = t, this.handle = n, this.cols = r, this.rows = o, this.cellSize = i;
74
+ }
75
+ write(t) {
76
+ const n = typeof t == "string" ? new TextEncoder().encode(t) : t;
77
+ if (n.length === 0) return;
78
+ const r = this.wasm.ghostty_wasm_alloc_u8_array(n.length);
79
+ if (!r)
80
+ throw new Error("Failed to allocate libghostty write buffer.");
81
+ try {
82
+ new Uint8Array(this.wasm.memory.buffer).set(n, r), this.wasm.ghostty_terminal_write(this.handle, r, n.length);
83
+ } finally {
84
+ this.wasm.ghostty_wasm_free_u8_array(r, n.length);
85
+ }
86
+ }
87
+ resize(t, n) {
88
+ t === this.cols && n === this.rows || (this.cols = t, this.rows = n, this.wasm.ghostty_terminal_resize(this.handle, t, n), this.releaseViewport());
89
+ }
90
+ hasResponse() {
91
+ return this.wasm.ghostty_terminal_has_response(this.handle);
92
+ }
93
+ isDirty() {
94
+ return this.wasm.ghostty_render_state_update(this.handle) !== 0;
95
+ }
96
+ readResponse(t = 4096) {
97
+ const n = this.wasm.ghostty_wasm_alloc_u8_array(t);
98
+ if (!n)
99
+ throw new Error("Failed to allocate libghostty response buffer.");
100
+ try {
101
+ const r = this.wasm.ghostty_terminal_read_response(this.handle, n, t);
102
+ if (r <= 0) return null;
103
+ const o = new Uint8Array(this.wasm.memory.buffer, n, r);
104
+ return new TextDecoder().decode(o);
105
+ } finally {
106
+ this.wasm.ghostty_wasm_free_u8_array(n, t);
107
+ }
108
+ }
109
+ getViewportData() {
110
+ const t = this.wasm.ghostty_render_state_get_cols(this.handle), n = this.wasm.ghostty_render_state_get_rows(this.handle);
111
+ this.cols = t, this.rows = n;
112
+ const r = Math.max(1, t * n * this.cellSize);
113
+ if ((r > this.viewportLen || this.viewportPtr === 0) && (this.releaseViewport(), this.viewportPtr = this.wasm.ghostty_wasm_alloc_u8_array(r), this.viewportLen = r, !this.viewportPtr))
114
+ throw new Error("Failed to allocate libghostty viewport buffer.");
115
+ const o = this.wasm.ghostty_render_state_get_viewport(this.handle, this.viewportPtr, this.viewportLen), i = new Uint8Array(o);
116
+ if (o > 0) {
117
+ const s = new Uint8Array(this.wasm.memory.buffer, this.viewportPtr, o);
118
+ i.set(s);
119
+ }
120
+ return this.wasm.ghostty_render_state_mark_clean(this.handle), {
121
+ cols: t,
122
+ rows: n,
123
+ buffer: i
124
+ };
125
+ }
126
+ dispose() {
127
+ this.releaseViewport(), this.wasm.ghostty_terminal_free(this.handle);
128
+ }
129
+ releaseViewport() {
130
+ this.viewportPtr !== 0 && (this.wasm.ghostty_wasm_free_u8_array(this.viewportPtr, this.viewportLen), this.viewportPtr = 0, this.viewportLen = 0);
131
+ }
13
132
  }
14
- function I(e) {
15
- const t = e ?? Z;
16
- return typeof t == "function" ? t : () => t;
133
+ class gt {
134
+ constructor(t, n, r, o, i, s) {
135
+ F(this, "ctx");
136
+ F(this, "dpr");
137
+ F(this, "metrics");
138
+ this.canvas = t, this.cols = n, this.rows = r, this.fontSize = o, this.fontFamily = i, this.theme = s;
139
+ const a = t.getContext("2d");
140
+ if (!a)
141
+ throw new Error("Failed to create 2D canvas context.");
142
+ this.ctx = a, this.dpr = window.devicePixelRatio || 1, this.metrics = this.measureFont(), this.resizeCanvas(n, r);
143
+ }
144
+ get cellSize() {
145
+ return { w: this.metrics.width, h: this.metrics.height };
146
+ }
147
+ render(t) {
148
+ (t.cols !== this.cols || t.rows !== this.rows) && (this.cols = t.cols, this.rows = t.rows, this.resizeCanvas(t.cols, t.rows));
149
+ const { cols: n, rows: r, buffer: o } = t, i = new DataView(o.buffer, o.byteOffset, o.byteLength), s = this.ctx, a = this.metrics.width, c = this.metrics.height;
150
+ s.fillStyle = this.theme.background, s.fillRect(0, 0, n * a, r * c);
151
+ for (let l = 0; l < r; l++)
152
+ for (let u = 0; u < n; u++) {
153
+ const h = (l * n + u) * S, f = i.getUint8(h + 11);
154
+ if (f === 0) continue;
155
+ const w = i.getUint8(h + 10), b = L(i, h + 4), y = L(i, h + 7), _ = x(w, K), g = x(w, W) ? D(b) : this.theme.foreground, d = x(w, R) ? D(y) : this.theme.background;
156
+ (_ || x(w, R)) && (s.fillStyle = _ ? g : d, s.fillRect(u * a, l * c, f * a, c));
157
+ }
158
+ for (let l = 0; l < r; l++)
159
+ for (let u = 0; u < n; u++) {
160
+ const h = (l * n + u) * S, f = i.getUint8(h + 11);
161
+ if (f === 0) continue;
162
+ const w = i.getUint8(h + 10);
163
+ if (x(w, ut)) continue;
164
+ const b = i.getUint32(h, !0);
165
+ if (b === 0) continue;
166
+ const y = x(w, K), _ = L(i, h + 4), g = L(i, h + 7), d = x(w, W) ? D(_) : this.theme.foreground, m = x(w, R) ? D(g) : this.theme.background;
167
+ s.fillStyle = y ? m : d;
168
+ let p = "";
169
+ x(w, lt) && (p += "italic "), x(w, ct) && (p += "bold "), s.font = `${p}${this.fontSize}px ${this.fontFamily}`, x(w, Y) && (s.globalAlpha = 0.5);
170
+ const E = Et(b);
171
+ if (s.fillText(E, u * a, l * c + this.metrics.baseline), x(w, Y) && (s.globalAlpha = 1), x(w, ht)) {
172
+ const v = l * c + this.metrics.baseline + 2;
173
+ s.strokeStyle = s.fillStyle, s.lineWidth = 1, s.beginPath(), s.moveTo(u * a, v), s.lineTo(u * a + f * a, v), s.stroke();
174
+ }
175
+ }
176
+ }
177
+ dispose() {
178
+ this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
179
+ }
180
+ measureFont() {
181
+ this.ctx.font = `${this.fontSize}px ${this.fontFamily}`;
182
+ const t = this.ctx.measureText("M"), n = Math.ceil(t.width), r = t.actualBoundingBoxAscent || this.fontSize * 0.8, o = t.actualBoundingBoxDescent || this.fontSize * 0.2;
183
+ return {
184
+ width: n,
185
+ height: Math.ceil(r + o) + 2,
186
+ baseline: Math.ceil(r) + 1
187
+ };
188
+ }
189
+ resizeCanvas(t, n) {
190
+ const r = t * this.metrics.width, o = n * this.metrics.height;
191
+ this.canvas.width = Math.max(1, Math.floor(r * this.dpr)), this.canvas.height = Math.max(1, Math.floor(o * this.dpr)), this.canvas.style.width = `${r}px`, this.canvas.style.height = `${o}px`, this.ctx.setTransform(this.dpr, 0, 0, this.dpr, 0, 0), this.ctx.textBaseline = "alphabetic", this.ctx.textAlign = "left";
192
+ }
17
193
  }
18
- function K(e) {
19
- return e.cols !== void 0 || e.rows !== void 0 ? {
20
- fit: "none",
21
- size: {
22
- cols: Math.max(1, e.cols ?? S.cols),
23
- rows: Math.max(1, e.rows ?? S.rows)
194
+ function et(e, t) {
195
+ const r = document.createElement("canvas").getContext("2d");
196
+ if (!r)
197
+ return {
198
+ w: Math.ceil(e * 0.6),
199
+ h: Math.ceil(e * 1.2)
200
+ };
201
+ r.font = `${e}px ${t}`;
202
+ const o = r.measureText("M"), i = Math.ceil(o.width), s = o.actualBoundingBoxAscent || e * 0.8, a = o.actualBoundingBoxDescent || e * 0.2;
203
+ return { w: i, h: Math.ceil(s + a) + 2 };
204
+ }
205
+ const Q = /* @__PURE__ */ new Map();
206
+ function yt(e = tt) {
207
+ const t = e.toString(), n = Q.get(t);
208
+ if (n)
209
+ return n;
210
+ const r = (async () => {
211
+ const o = await fetch(e);
212
+ if (!o.ok)
213
+ throw new Error(`Failed to load libghostty wasm: ${o.status} ${o.statusText}`);
214
+ const i = await o.arrayBuffer();
215
+ if (i.byteLength === 0)
216
+ throw new Error("libghostty wasm is empty.");
217
+ const s = await WebAssembly.compile(i), c = (await WebAssembly.instantiate(s, {
218
+ env: {
219
+ log: () => {
220
+ }
221
+ }
222
+ })).exports;
223
+ if (!c.memory || !c.ghostty_terminal_new || !c.ghostty_render_state_get_viewport)
224
+ throw new Error("Invalid libghostty wasm exports.");
225
+ return bt(c), new mt(c, {
226
+ cellSize: S,
227
+ terminalConfigSize: T
228
+ });
229
+ })();
230
+ return Q.set(t, r), r;
231
+ }
232
+ async function _t(e) {
233
+ var _, g;
234
+ const t = await yt(e.wasmUrl ?? tt), n = { ...wt, ...e.theme };
235
+ let r, o;
236
+ const i = et(e.fontSize, e.fontFamily);
237
+ e.widthPx != null && e.heightPx != null ? (r = Math.max(1, Math.floor(e.widthPx / i.w)), o = Math.max(1, Math.floor(e.heightPx / i.h))) : (r = e.cols ?? 80, o = e.rows ?? 24), e.container.innerHTML = "";
238
+ const s = document.createElement("canvas");
239
+ s.style.display = "block", s.style.outline = "none", s.tabIndex = e.interactive ? 0 : -1, e.container.appendChild(s);
240
+ const a = t.createTerminal(r, o, n), c = new gt(
241
+ s,
242
+ r,
243
+ o,
244
+ e.fontSize,
245
+ e.fontFamily,
246
+ n
247
+ );
248
+ e.showCursor || a.write("\x1B[?25l"), c.render(a.getViewportData());
249
+ const l = ((_ = window.requestAnimationFrame) == null ? void 0 : _.bind(window)) ?? ((d) => window.setTimeout(d, 16)), u = ((g = window.cancelAnimationFrame) == null ? void 0 : g.bind(window)) ?? window.clearTimeout.bind(window);
250
+ let h = null, f = !1;
251
+ const w = () => {
252
+ h = null, !(f || !a.isDirty()) && c.render(a.getViewportData());
253
+ }, b = () => {
254
+ h !== null || f || (h = l(w));
255
+ }, y = e.interactive ? vt(s, (d) => {
256
+ var m;
257
+ return (m = e.onInput) == null ? void 0 : m.call(e, d);
258
+ }) : () => {
259
+ };
260
+ return {
261
+ cols: r,
262
+ rows: o,
263
+ cellSize: c.cellSize,
264
+ write(d) {
265
+ if (f) return;
266
+ const m = e.convertEol ? pt(d) : d;
267
+ a.write(m), b();
268
+ },
269
+ drainResponses() {
270
+ if (f) return [];
271
+ const d = [];
272
+ for (; a.hasResponse(); ) {
273
+ const m = a.readResponse();
274
+ if (!m) break;
275
+ d.push(m);
276
+ }
277
+ return d;
278
+ },
279
+ dispose() {
280
+ f = !0, h !== null && (u(h), h = null), y(), c.dispose(), a.dispose(), s.parentElement === e.container && e.container.removeChild(s);
24
281
  }
25
- } : { fit: "container", size: S };
282
+ };
283
+ }
284
+ function bt(e) {
285
+ const t = e.ghostty_wasm_alloc_u8_array(T);
286
+ if (!t)
287
+ throw new Error("Failed to allocate ABI probe config buffer.");
288
+ let n = 0, r = 0, o = 0, i = 0;
289
+ const s = 1122867, a = 4478310, [c, l, u] = X(s), [h, f, w] = X(a);
290
+ try {
291
+ new Uint8Array(e.memory.buffer, t, T).fill(0);
292
+ const b = new DataView(e.memory.buffer, t, T);
293
+ if (b.setUint32(0, 16, !0), b.setUint32(4, s, !0), b.setUint32(8, a, !0), b.setUint32(12, 7833753, !0), n = e.ghostty_terminal_new_with_config(2, 1, t), !n)
294
+ throw new Error("Failed to create ABI probe terminal.");
295
+ const y = new TextEncoder().encode("\x1B[7mX");
296
+ if (o = y.length, r = e.ghostty_wasm_alloc_u8_array(o), !r)
297
+ throw new Error("Failed to allocate ABI probe write buffer.");
298
+ if (new Uint8Array(e.memory.buffer, r, o).set(y), e.ghostty_terminal_write(n, r, o), i = e.ghostty_wasm_alloc_u8_array(S), !i)
299
+ throw new Error("Failed to allocate ABI probe viewport buffer.");
300
+ const _ = e.ghostty_render_state_get_viewport(n, i, S);
301
+ if (_ !== S)
302
+ throw new Error(
303
+ `Incompatible libghostty ABI: expected cell size ${S}, got ${_}.`
304
+ );
305
+ const g = new DataView(e.memory.buffer, i, S), d = g.getUint8(10), m = x(d, W), p = x(d, R), E = g.getUint8(4) === c && g.getUint8(5) === l && g.getUint8(6) === u, v = g.getUint8(7) === h && g.getUint8(8) === f && g.getUint8(9) === w;
306
+ if (!m || !p || !E || !v)
307
+ throw new Error("Incompatible libghostty ABI: terminal config layout mismatch.");
308
+ } finally {
309
+ i && e.ghostty_wasm_free_u8_array(i, S), r && o > 0 && e.ghostty_wasm_free_u8_array(r, o), n && e.ghostty_terminal_free(n), e.ghostty_wasm_free_u8_array(t, T);
310
+ }
311
+ }
312
+ function pt(e) {
313
+ return e.replace(/\r?\n/g, `\r
314
+ `);
315
+ }
316
+ function z(e) {
317
+ if (e.startsWith("#")) {
318
+ let i = e.slice(1);
319
+ i.length === 3 && (i = `${i[0]}${i[0]}${i[1]}${i[1]}${i[2]}${i[2]}`);
320
+ const s = Number.parseInt(i, 16);
321
+ return Number.isNaN(s) ? 0 : s;
322
+ }
323
+ const t = e.match(/rgb\((\d+),\s*(\d+),\s*(\d+)\)/);
324
+ if (!t) return 0;
325
+ const n = Number.parseInt(t[1], 10), r = Number.parseInt(t[2], 10), o = Number.parseInt(t[3], 10);
326
+ return n << 16 | r << 8 | o;
26
327
  }
27
- let W = !1;
28
328
  function X(e) {
29
- !e || W || (W = !0, console.warn(
30
- "[tui-preview] Legacy props (`app`, `args`, `cols`, `rows`, `fontSize`, `fontFamily`, `theme`) are deprecated. Use `wasm`, `argv`, `fit`, `size`, and `terminal`."
31
- ));
329
+ return [e >> 16 & 255, e >> 8 & 255, e & 255];
32
330
  }
33
- function tt(e) {
34
- var i, s, r, o, c, u, a, h, m;
35
- if (J(e)) {
36
- const v = e.fit ?? (e.size ? "none" : "container"), w = v === "none" ? {
37
- cols: Math.max(1, ((i = e.size) == null ? void 0 : i.cols) ?? S.cols),
38
- rows: Math.max(1, ((s = e.size) == null ? void 0 : s.rows) ?? S.rows)
39
- } : {
40
- cols: Math.max(1, ((r = e.size) == null ? void 0 : r.cols) ?? S.cols),
41
- rows: Math.max(1, ((o = e.size) == null ? void 0 : o.rows) ?? S.rows)
42
- }, y = e.mode ?? "terminal";
43
- return {
44
- wasm: e.wasm,
45
- env: e.env ?? P,
46
- interactive: y === "static" ? !1 : e.interactive ?? !0,
47
- mode: y,
48
- fit: v,
49
- size: w,
50
- terminal: {
51
- fontSize: ((c = e.terminal) == null ? void 0 : c.fontSize) ?? 14,
52
- fontFamily: ((u = e.terminal) == null ? void 0 : u.fontFamily) ?? "monospace",
53
- cursorBlink: ((a = e.terminal) == null ? void 0 : a.cursorBlink) ?? !0,
54
- convertEol: ((h = e.terminal) == null ? void 0 : h.convertEol) ?? !0,
55
- theme: (m = e.terminal) == null ? void 0 : m.theme
56
- },
57
- resolveArgv: I(e.argv),
58
- onExit: e.onExit,
59
- onError: e.onError,
60
- onStatusChange: e.onStatusChange,
61
- usedLegacyProps: !1
62
- };
331
+ function L(e, t) {
332
+ return {
333
+ r: e.getUint8(t),
334
+ g: e.getUint8(t + 1),
335
+ b: e.getUint8(t + 2)
336
+ };
337
+ }
338
+ function x(e, t) {
339
+ return (e & t) !== 0;
340
+ }
341
+ function D(e) {
342
+ return `rgb(${e.r}, ${e.g}, ${e.b})`;
343
+ }
344
+ function Et(e) {
345
+ try {
346
+ return String.fromCodePoint(e);
347
+ } catch {
348
+ return " ";
63
349
  }
64
- const { fit: t, size: n } = K(e);
350
+ }
351
+ function vt(e, t) {
352
+ const n = () => e.focus(), r = (i) => {
353
+ var a;
354
+ const s = (a = i.clipboardData) == null ? void 0 : a.getData("text");
355
+ s && (i.preventDefault(), t(s));
356
+ }, o = (i) => {
357
+ const s = xt(i);
358
+ s && (i.preventDefault(), t(s));
359
+ };
360
+ return e.addEventListener("mousedown", n), e.addEventListener("paste", r), e.addEventListener("keydown", o), () => {
361
+ e.removeEventListener("mousedown", n), e.removeEventListener("paste", r), e.removeEventListener("keydown", o);
362
+ };
363
+ }
364
+ function xt(e) {
365
+ if (e.isComposing || e.metaKey) return null;
366
+ let t = null;
367
+ switch (e.key) {
368
+ case "Enter":
369
+ t = "\r";
370
+ break;
371
+ case "Backspace":
372
+ t = "";
373
+ break;
374
+ case "Tab":
375
+ t = e.shiftKey ? "\x1B[Z" : " ";
376
+ break;
377
+ case "Escape":
378
+ t = "\x1B";
379
+ break;
380
+ case "ArrowUp":
381
+ t = "\x1B[A";
382
+ break;
383
+ case "ArrowDown":
384
+ t = "\x1B[B";
385
+ break;
386
+ case "ArrowRight":
387
+ t = "\x1B[C";
388
+ break;
389
+ case "ArrowLeft":
390
+ t = "\x1B[D";
391
+ break;
392
+ case "Home":
393
+ t = "\x1B[H";
394
+ break;
395
+ case "End":
396
+ t = "\x1B[F";
397
+ break;
398
+ case "Delete":
399
+ t = "\x1B[3~";
400
+ break;
401
+ case "PageUp":
402
+ t = "\x1B[5~";
403
+ break;
404
+ case "PageDown":
405
+ t = "\x1B[6~";
406
+ break;
407
+ }
408
+ return !t && e.ctrlKey && (t = At(e.key)), !t && e.key.length === 1 && !e.ctrlKey && (t = e.key), t ? e.altKey && !t.startsWith("\x1B") ? `\x1B${t}` : t : null;
409
+ }
410
+ function At(e) {
411
+ if (e.length !== 1) return null;
412
+ const t = e.toUpperCase();
413
+ if (t >= "A" && t <= "Z")
414
+ return String.fromCharCode(t.charCodeAt(0) - 64);
415
+ switch (e) {
416
+ case "@":
417
+ case " ":
418
+ return "\0";
419
+ case "[":
420
+ return "\x1B";
421
+ case "\\":
422
+ return "";
423
+ case "]":
424
+ return "";
425
+ case "^":
426
+ return "";
427
+ case "_":
428
+ return "";
429
+ default:
430
+ return null;
431
+ }
432
+ }
433
+ const Z = { cols: 80, rows: 24 }, Ut = {}, St = [];
434
+ function Ft(e) {
435
+ return e === "static" ? "static" : "interactive";
436
+ }
437
+ function Bt(e) {
438
+ const t = e ?? St;
439
+ return typeof t == "function" ? t : () => t;
440
+ }
441
+ function Ct(e) {
442
+ var o, i, s, a, c, l, u;
443
+ const t = e.fit ?? (e.size ? "none" : "container"), n = {
444
+ cols: Math.max(1, ((o = e.size) == null ? void 0 : o.cols) ?? Z.cols),
445
+ rows: Math.max(1, ((i = e.size) == null ? void 0 : i.rows) ?? Z.rows)
446
+ }, r = Ft(e.mode);
65
447
  return {
66
- wasm: e.app,
67
- env: e.env ?? P,
68
- interactive: e.interactive ?? !0,
69
- mode: "terminal",
448
+ wasm: e.wasm,
449
+ env: e.env ?? Ut,
450
+ interactive: r === "static" ? !1 : e.interactive ?? !0,
451
+ mode: r,
70
452
  fit: t,
71
453
  size: n,
72
454
  terminal: {
73
- fontSize: e.fontSize ?? 14,
74
- fontFamily: e.fontFamily ?? "monospace",
75
- cursorBlink: !0,
76
- convertEol: !0,
77
- theme: e.theme
455
+ fontSize: ((s = e.terminal) == null ? void 0 : s.fontSize) ?? 14,
456
+ fontFamily: ((a = e.terminal) == null ? void 0 : a.fontFamily) ?? "monospace",
457
+ wasmUrl: (c = e.terminal) == null ? void 0 : c.wasmUrl,
458
+ convertEol: ((l = e.terminal) == null ? void 0 : l.convertEol) ?? !0,
459
+ theme: (u = e.terminal) == null ? void 0 : u.theme
78
460
  },
79
- resolveArgv: I(e.args),
461
+ resolveArgv: Bt(e.argv),
80
462
  onExit: e.onExit,
81
463
  onError: e.onError,
82
- onStatusChange: e.onStatusChange,
83
- usedLegacyProps: !0
464
+ onStatusChange: e.onStatusChange
84
465
  };
85
466
  }
86
- const d = 0, et = 6, x = 8, nt = 0, O = 1, rt = 2;
87
- class it {
467
+ const A = 0, Tt = 6, C = 8, Mt = 1, kt = 0, j = 1, It = 2;
468
+ class zt {
88
469
  constructor(t) {
89
- k(this, "inputQueue", []);
90
- k(this, "memory");
470
+ F(this, "inputQueue", []);
471
+ F(this, "memory");
91
472
  this.opts = t;
92
473
  }
93
474
  /** Push keyboard data from the terminal into the app's stdin */
@@ -109,83 +490,83 @@ class it {
109
490
  get imports() {
110
491
  return {
111
492
  args_sizes_get: (t, n) => {
112
- const { args: i } = this.opts, s = new TextEncoder(), r = i.reduce((o, c) => o + s.encode(c).length + 1, 0);
113
- return this.view().setUint32(t, i.length, !0), this.view().setUint32(n, r, !0), d;
493
+ const { args: r } = this.opts, o = new TextEncoder(), i = r.reduce((s, a) => s + o.encode(a).length + 1, 0);
494
+ return this.view().setUint32(t, r.length, !0), this.view().setUint32(n, i, !0), A;
114
495
  },
115
496
  args_get: (t, n) => {
116
- const i = new TextEncoder(), s = this.u8(), r = this.view();
117
- let o = n;
118
- return this.opts.args.forEach((c, u) => {
119
- const a = i.encode(c);
120
- s.set(a, o), s[o + a.length] = 0, r.setUint32(t + u * 4, o, !0), o += a.length + 1;
121
- }), d;
497
+ const r = new TextEncoder(), o = this.u8(), i = this.view();
498
+ let s = n;
499
+ return this.opts.args.forEach((a, c) => {
500
+ const l = r.encode(a);
501
+ o.set(l, s), o[s + l.length] = 0, i.setUint32(t + c * 4, s, !0), s += l.length + 1;
502
+ }), A;
122
503
  },
123
504
  environ_sizes_get: (t, n) => {
124
- const i = this.envEntries(), s = new TextEncoder(), r = i.reduce((o, c) => o + s.encode(c).length + 1, 0);
125
- return this.view().setUint32(t, i.length, !0), this.view().setUint32(n, r, !0), d;
505
+ const r = this.envEntries(), o = new TextEncoder(), i = r.reduce((s, a) => s + o.encode(a).length + 1, 0);
506
+ return this.view().setUint32(t, r.length, !0), this.view().setUint32(n, i, !0), A;
126
507
  },
127
508
  environ_get: (t, n) => {
128
- const i = new TextEncoder(), s = this.u8(), r = this.view();
129
- let o = n;
130
- return this.envEntries().forEach((c, u) => {
131
- const a = i.encode(c);
132
- s.set(a, o), s[o + a.length] = 0, r.setUint32(t + u * 4, o, !0), o += a.length + 1;
133
- }), d;
509
+ const r = new TextEncoder(), o = this.u8(), i = this.view();
510
+ let s = n;
511
+ return this.envEntries().forEach((a, c) => {
512
+ const l = r.encode(a);
513
+ o.set(l, s), o[s + l.length] = 0, i.setUint32(t + c * 4, s, !0), s += l.length + 1;
514
+ }), A;
134
515
  },
135
- fd_write: (t, n, i, s) => {
136
- if (t !== O && t !== rt) return x;
137
- const r = this.view(), o = this.u8();
138
- let c = 0;
139
- const u = [];
140
- for (let m = 0; m < i; m++) {
141
- const v = r.getUint32(n + m * 8, !0), w = r.getUint32(n + m * 8 + 4, !0);
142
- u.push(o.slice(v, v + w)), c += w;
516
+ fd_write: (t, n, r, o) => {
517
+ if (t !== j && t !== It) return C;
518
+ const i = this.view(), s = this.u8();
519
+ let a = 0;
520
+ const c = [];
521
+ for (let h = 0; h < r; h++) {
522
+ const f = i.getUint32(n + h * 8, !0), w = i.getUint32(n + h * 8 + 4, !0);
523
+ c.push(s.slice(f, f + w)), a += w;
143
524
  }
144
- const a = new Uint8Array(c);
145
- let h = 0;
146
- for (const m of u)
147
- a.set(m, h), h += m.length;
148
- return t === O ? this.opts.stdout(a) : this.opts.stderr(a), r.setUint32(s, c, !0), d;
149
- },
150
- fd_read: (t, n, i, s) => {
151
- if (t !== nt) return x;
152
- const r = this.inputQueue.shift();
153
- if (!r) return et;
154
- const o = this.view(), c = this.u8();
525
+ const l = new Uint8Array(a);
155
526
  let u = 0;
156
- for (let a = 0; a < i && u < r.length; a++) {
157
- const h = o.getUint32(n + a * 8, !0), m = o.getUint32(n + a * 8 + 4, !0), v = Math.min(m, r.length - u);
158
- c.set(r.subarray(u, u + v), h), u += v;
527
+ for (const h of c)
528
+ l.set(h, u), u += h.length;
529
+ return t === j ? this.opts.stdout(l) : this.opts.stderr(l), i.setUint32(o, a, !0), A;
530
+ },
531
+ fd_read: (t, n, r, o) => {
532
+ if (t !== kt) return C;
533
+ const i = this.inputQueue[0];
534
+ if (!i) return Tt;
535
+ const s = this.view(), a = this.u8();
536
+ let c = 0;
537
+ for (let l = 0; l < r && c < i.length; l++) {
538
+ const u = s.getUint32(n + l * 8, !0), h = s.getUint32(n + l * 8 + 4, !0), f = Math.min(h, i.length - c);
539
+ a.set(i.subarray(c, c + f), u), c += f;
159
540
  }
160
- return o.setUint32(s, u, !0), d;
541
+ return c >= i.length ? this.inputQueue.shift() : c > 0 && (this.inputQueue[0] = i.subarray(c)), s.setUint32(o, c, !0), A;
161
542
  },
162
- poll_oneoff: (t, n, i, s) => {
163
- const r = this.view();
164
- let o = 0;
165
- for (let c = 0; c < i; c++) {
166
- const u = t + c * 48, a = r.getUint8(u + 8);
167
- if (a === 0 && this.inputQueue.length > 0) {
168
- const h = n + o * 32;
169
- r.setBigUint64(h, r.getBigUint64(u, !0), !0), r.setUint16(h + 8, 0, !0), r.setUint8(h + 10, a), o++;
543
+ poll_oneoff: (t, n, r, o) => {
544
+ const i = this.view();
545
+ let s = 0;
546
+ for (let a = 0; a < r; a++) {
547
+ const c = t + a * 48, l = i.getUint8(c + 8);
548
+ if (l === Mt && this.inputQueue.length > 0) {
549
+ const u = n + s * 32;
550
+ i.setBigUint64(u, i.getBigUint64(c, !0), !0), i.setUint16(u + 8, 0, !0), i.setUint8(u + 10, l), s++;
170
551
  }
171
552
  }
172
- return r.setUint32(s, o, !0), d;
553
+ return i.setUint32(o, s, !0), A;
173
554
  },
174
555
  proc_exit: (t) => {
175
- throw this.opts.onExit(t), new Q(t);
556
+ throw this.opts.onExit(t), new nt(t);
176
557
  },
177
- random_get: (t, n) => (crypto.getRandomValues(new Uint8Array(this.memory.buffer, t, n)), d),
558
+ random_get: (t, n) => (crypto.getRandomValues(new Uint8Array(this.memory.buffer, t, n)), A),
178
559
  // Stubs for calls TUI apps may make but we don't need to implement.
179
- fd_close: () => d,
180
- fd_seek: () => d,
181
- fd_fdstat_get: (t, n) => (this.view().setUint8(n, t <= 2 ? 2 : 0), d),
182
- fd_prestat_get: () => x,
183
- fd_prestat_dir_name: () => x,
184
- path_open: () => x,
185
- sched_yield: () => d,
186
- clock_time_get: (t, n, i) => {
187
- const s = BigInt(Date.now()) * 1000000n;
188
- return this.view().setBigUint64(i, s, !0), d;
560
+ fd_close: () => A,
561
+ fd_seek: () => A,
562
+ fd_fdstat_get: (t, n) => (this.view().setUint8(n, t <= 2 ? 2 : 0), A),
563
+ fd_prestat_get: () => C,
564
+ fd_prestat_dir_name: () => C,
565
+ path_open: () => C,
566
+ sched_yield: () => A,
567
+ clock_time_get: (t, n, r) => {
568
+ const o = BigInt(Date.now()) * 1000000n;
569
+ return this.view().setBigUint64(r, o, !0), A;
189
570
  }
190
571
  };
191
572
  }
@@ -195,123 +576,128 @@ class it {
195
576
  COLORTERM: "truecolor",
196
577
  ...this.opts.env
197
578
  };
198
- return Object.entries(t).map(([n, i]) => `${n}=${i}`);
579
+ return Object.entries(t).map(([n, r]) => `${n}=${r}`);
199
580
  }
200
581
  }
201
- class Q extends Error {
582
+ class nt extends Error {
202
583
  constructor(t) {
203
584
  super(`WASI exit: ${t}`), this.code = t;
204
585
  }
205
586
  }
206
- const N = /* @__PURE__ */ new Map();
207
- async function ot(e, t) {
587
+ const q = /* @__PURE__ */ new Map();
588
+ async function Lt(e, t) {
208
589
  const n = e.toString();
209
- let i = N.get(n);
210
- if (!i) {
211
- const u = await (await fetch(e)).arrayBuffer();
212
- i = await WebAssembly.compile(u), N.set(n, i);
590
+ let r = q.get(n);
591
+ if (!r) {
592
+ const a = await fetch(e);
593
+ if (!a.ok)
594
+ throw new Error(`Failed to load app wasm: ${a.status} ${a.statusText}`);
595
+ const c = await a.arrayBuffer();
596
+ if (c.byteLength === 0)
597
+ throw new Error("App wasm is empty.");
598
+ r = await WebAssembly.compile(c), q.set(n, r);
213
599
  }
214
- const s = {
600
+ const o = {
215
601
  wasi_snapshot_preview1: t.imports
216
- }, r = await WebAssembly.instantiate(i, s);
217
- t.attachMemory(r.exports.memory);
218
- const o = r.exports._start;
219
- if (!o) throw new Error("WASM module has no _start export");
602
+ }, i = await WebAssembly.instantiate(r, o);
603
+ t.attachMemory(i.exports.memory);
604
+ const s = i.exports._start;
605
+ if (!s) throw new Error("WASM module has no _start export");
220
606
  return {
221
607
  run: async () => {
222
608
  try {
223
- o();
224
- } catch (c) {
225
- if (!(c instanceof Q)) throw c;
609
+ s();
610
+ } catch (a) {
611
+ if (!(a instanceof nt)) throw a;
226
612
  }
227
613
  }
228
614
  };
229
615
  }
230
- function ut(e) {
231
- var v;
232
- const t = Y(() => tt(e), [e]), n = M(null), i = M(null), s = M(null), [r, o] = R("loading"), [c, u] = R(""), a = M(null), [h, m] = R(t.size);
233
- return T(() => {
234
- X(t.usedLegacyProps);
235
- }, [t.usedLegacyProps]), T(() => {
236
- m(t.size);
237
- }, [t.fit, t.size.cols, t.size.rows]), T(() => {
616
+ function $t(e) {
617
+ var h;
618
+ const t = at(() => Ct(e), [e]), n = P(null), r = P(null), [o, i] = $("loading"), [s, a] = $(""), c = P(null), [l, u] = $(
619
+ t.fit === "container" ? null : t.size
620
+ );
621
+ return N(() => {
622
+ u(t.fit === "container" ? null : t.size);
623
+ }, [t.fit, t.size.cols, t.size.rows]), N(() => {
238
624
  if (t.fit !== "container" || !n.current) return;
239
- const w = new ResizeObserver(([y]) => {
240
- var z, b;
241
- const { width: _, height: E } = y.contentRect;
242
- if (_ > 0 && E > 0) {
243
- const f = ((z = a.current) == null ? void 0 : z.w) ?? t.terminal.fontSize * 0.6, l = ((b = a.current) == null ? void 0 : b.h) ?? t.terminal.fontSize * 1.2;
244
- m({
245
- cols: Math.max(1, Math.floor(_ / f)),
246
- rows: Math.max(1, Math.floor(E / l))
247
- });
248
- }
625
+ const f = n.current, w = et(t.terminal.fontSize, t.terminal.fontFamily), b = (g, d) => {
626
+ var M, k;
627
+ const m = ((M = c.current) == null ? void 0 : M.w) ?? w.w, p = ((k = c.current) == null ? void 0 : k.h) ?? w.h, E = Math.max(1, Math.floor(g / m)), v = Math.max(1, Math.floor(d / p));
628
+ u((B) => B && B.cols === E && B.rows === v ? B : { cols: E, rows: v });
629
+ }, y = f.getBoundingClientRect();
630
+ y.width > 0 && y.height > 0 && b(y.width, y.height);
631
+ const _ = new ResizeObserver(([g]) => {
632
+ const { width: d, height: m } = g.contentRect;
633
+ d > 0 && m > 0 && b(d, m);
249
634
  });
250
- return w.observe(n.current), () => w.disconnect();
251
- }, [t.fit, t.terminal.fontSize]), T(() => {
252
- if (!h || !i.current) return;
253
- let w = !1;
254
- const y = i.current, _ = h, E = (f) => {
255
- var l;
256
- o(f), (l = t.onStatusChange) == null || l.call(t, f);
257
- }, z = (f) => {
258
- var l;
259
- E("error"), u(f instanceof Error ? f.message : String(f)), (l = t.onError) == null || l.call(t, f);
635
+ return _.observe(f), () => _.disconnect();
636
+ }, [t.fit, t.terminal.fontSize, t.terminal.fontFamily]), N(() => {
637
+ if (!l || !r.current) return;
638
+ let f = !1, w = null;
639
+ const b = r.current, y = l, _ = (m) => {
640
+ var p;
641
+ i(m), (p = t.onStatusChange) == null || p.call(t, m);
642
+ }, g = (m) => {
643
+ var p;
644
+ _("error"), a(m instanceof Error ? m.message : String(m)), (p = t.onError) == null || p.call(t, m);
260
645
  };
261
- E("loading"), u("");
262
- async function b() {
646
+ _("loading"), a("");
647
+ async function d() {
263
648
  try {
264
- const f = await q();
265
- if (w) return;
266
- y.innerHTML = "";
267
- const l = new f.Terminal({
268
- cols: _.cols,
269
- rows: _.rows,
649
+ let m = y.cols, p = y.rows, E = null;
650
+ const v = await _t({
651
+ container: b,
652
+ cols: y.cols,
653
+ rows: y.rows,
270
654
  fontSize: t.terminal.fontSize,
271
655
  fontFamily: t.terminal.fontFamily,
272
656
  theme: t.terminal.theme,
273
- disableStdin: !t.interactive,
274
- cursorBlink: t.terminal.cursorBlink,
275
- convertEol: t.terminal.convertEol
657
+ convertEol: t.terminal.convertEol,
658
+ interactive: t.mode !== "static" && t.interactive,
659
+ showCursor: t.mode !== "static",
660
+ wasmUrl: t.terminal.wasmUrl,
661
+ onInput: (U) => E == null ? void 0 : E.pushInput(U)
276
662
  });
277
- s.current = l, l.open(y), t.mode === "static" && l.write("\x1B[?25l");
278
- let A = l.cols, U = l.rows;
279
- if (t.fit === "container") {
280
- const g = new f.FitAddon();
281
- l.loadAddon(g), g.fit(), A = l.cols, U = l.rows, n.current && A > 0 && U > 0 && (a.current = {
282
- w: n.current.clientWidth / A,
283
- h: n.current.clientHeight / U
284
- });
663
+ if (f) {
664
+ v.dispose();
665
+ return;
285
666
  }
286
- const V = t.resolveArgv({ cols: A, rows: U }), F = new TextDecoder(), B = new it({
287
- args: [t.wasm.toString(), ...V],
667
+ w = () => v.dispose(), m = v.cols, p = v.rows, c.current = v.cellSize;
668
+ const M = t.resolveArgv({ cols: m, rows: p }), k = new TextDecoder(), B = new TextDecoder(), G = (U, I) => {
669
+ const V = I.decode(U, { stream: !0 });
670
+ V && v.write(V);
671
+ for (const st of v.drainResponses())
672
+ E == null || E.pushInput(st);
673
+ };
674
+ E = new zt({
675
+ args: [t.wasm.toString(), ...M],
288
676
  env: t.env,
289
- stdout: (g) => l.write(F.decode(g)),
290
- stderr: (g) => l.write(F.decode(g)),
291
- onExit: (g) => {
292
- var C;
293
- w || (E("exited"), (C = t.onExit) == null || C.call(t, g));
677
+ stdout: (U) => G(U, k),
678
+ stderr: (U) => G(U, B),
679
+ onExit: (U) => {
680
+ var I;
681
+ f || (_("exited"), (I = t.onExit) == null || I.call(t, U));
294
682
  }
295
683
  });
296
- t.interactive && l.onData((g) => B.pushInput(g));
297
- const G = await ot(t.wasm, B);
298
- if (w) return;
299
- E("running"), queueMicrotask(() => {
300
- w || G.run().catch((g) => {
301
- w || z(g);
684
+ const rt = await Lt(t.wasm, E);
685
+ if (f) return;
686
+ _("running"), queueMicrotask(() => {
687
+ f || rt.run().catch((U) => {
688
+ f || g(U);
302
689
  });
303
690
  });
304
- } catch (f) {
305
- w || z(f);
691
+ } catch (m) {
692
+ f || g(m);
306
693
  }
307
694
  }
308
- return b(), () => {
309
- var f;
310
- w = !0, (f = s.current) == null || f.dispose(), s.current = null;
695
+ return d(), () => {
696
+ f = !0, w == null || w(), w = null;
311
697
  };
312
698
  }, [
313
699
  t.mode,
314
- h,
700
+ l,
315
701
  t.wasm,
316
702
  t.resolveArgv,
317
703
  t.env,
@@ -323,41 +709,41 @@ function ut(e) {
323
709
  t.terminal.fontSize,
324
710
  t.terminal.fontFamily,
325
711
  t.terminal.theme,
326
- t.terminal.cursorBlink,
712
+ t.terminal.wasmUrl,
327
713
  t.terminal.convertEol
328
- ]), /* @__PURE__ */ D(
714
+ ]), /* @__PURE__ */ O(
329
715
  "div",
330
716
  {
331
717
  ref: n,
332
718
  className: e.className,
333
719
  style: {
334
720
  position: "relative",
335
- display: "inline-block",
336
- background: ((v = t.terminal.theme) == null ? void 0 : v.background) ?? "#1a1b26",
721
+ display: t.fit === "container" ? "block" : "inline-block",
722
+ background: ((h = t.terminal.theme) == null ? void 0 : h.background) ?? "#1a1b26",
337
723
  borderRadius: 6,
338
724
  overflow: "hidden",
339
725
  ...e.style
340
726
  },
341
727
  children: [
342
- /* @__PURE__ */ L("div", { ref: i, style: { display: r === "error" ? "none" : void 0 } }),
343
- r === "loading" && /* @__PURE__ */ L("div", { style: j, children: "Loading…" }),
344
- r === "error" && /* @__PURE__ */ D("div", { style: { ...j, color: "#f7768e" }, children: [
728
+ /* @__PURE__ */ H("div", { ref: r, style: { display: o === "error" ? "none" : void 0 } }),
729
+ o === "loading" && /* @__PURE__ */ H("div", { style: J, children: "Loading…" }),
730
+ o === "error" && /* @__PURE__ */ O("div", { style: { ...J, color: "#f7768e" }, children: [
345
731
  "Error: ",
346
- c
732
+ s
347
733
  ] })
348
734
  ]
349
735
  }
350
736
  );
351
737
  }
352
- const j = {
738
+ const J = {
353
739
  padding: "1rem",
354
740
  fontFamily: "monospace",
355
741
  fontSize: 14,
356
742
  color: "#a9b1d6"
357
743
  };
358
744
  export {
359
- ut as TuiPreview,
360
- it as WasiBridge,
361
- Q as WasiExitError,
362
- ot as instantiateApp
745
+ $t as TuiPreview,
746
+ zt as WasiBridge,
747
+ nt as WasiExitError,
748
+ Lt as instantiateApp
363
749
  };