@simon_he/vue-tui 1.1.5 → 1.1.7

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 (42) hide show
  1. package/README.md +1 -0
  2. package/dist/TAgentTerminalGraphic-B8-YZfuP.js +1198 -0
  3. package/dist/{TSelect-CMBOOFwK.js → TSelect-CCsjjCOr.js} +41 -12
  4. package/dist/{TTree-kk8ntrpg.js → TTree-3W5A2_EH.js} +4 -3
  5. package/dist/TVideo-D9AOiyq2.js +948 -0
  6. package/dist/agent.cjs +5204 -4312
  7. package/dist/agent.js +11 -9
  8. package/dist/{block-source-DhzajB9H.js → block-source-BhvdZomx.js} +246 -53
  9. package/dist/cli.cjs +41 -26
  10. package/dist/cli.js +68 -18
  11. package/dist/core.js +2 -2
  12. package/dist/experimental/browser.cjs +3705 -0
  13. package/dist/experimental/browser.d.cts +3 -0
  14. package/dist/experimental/browser.d.ts +3 -0
  15. package/dist/experimental/browser.js +413 -0
  16. package/dist/experimental.cjs +2 -1
  17. package/dist/experimental.js +9 -947
  18. package/dist/{linkify-CL9wwnZN.js → frame-mailbox-DaTrfyaF.js} +2 -297
  19. package/dist/index.cjs +25 -8
  20. package/dist/index.js +6 -5
  21. package/dist/linkify-CklfA1vp.js +298 -0
  22. package/dist/markdown.cjs +5196 -4322
  23. package/dist/markdown.js +4 -4
  24. package/dist/{mermaid-N3kGTHFy.js → mermaid-D0ov4_A1.js} +93 -9
  25. package/dist/mermaid.cjs +78 -7
  26. package/dist/mermaid.js +4 -4
  27. package/dist/{path-suggest-Dndu4dTi.js → path-suggest-fPzRsgPv.js} +1 -1
  28. package/dist/renderer/terminal-graphics.d.ts +1 -1
  29. package/dist/{terminal-graphics-2FTRg9x3.js → terminal-graphics-DpSL29OQ.js} +3 -3
  30. package/dist/{tlog-theme-B91Wv7Zj.js → tlog-theme-BnILsD3n.js} +10 -1203
  31. package/dist/vue/browser/types.d.ts +52 -0
  32. package/dist/vue/components/TAgentTerminalGraphic.d.ts +3 -0
  33. package/dist/vue/components/TBrowser.d.ts +231 -0
  34. package/dist/vue/components/TVirtualMarkdown.d.ts +10 -0
  35. package/dist/vue/markdown/render.d.ts +18 -1
  36. package/dist/vue.cjs +25 -8
  37. package/dist/vue.js +8 -7
  38. package/package.json +27 -2
  39. /package/dist/{TMermaidText-wLnMMvVS.js → TMermaidText-C1akgJPU.js} +0 -0
  40. /package/dist/{math-image-BZhmfUeu.js → math-image-CcUpBnW0.js} +0 -0
  41. /package/dist/{path-mnSgEpCm.js → path-BI9W15Zt.js} +0 -0
  42. /package/dist/{wheel-scroll-DASkEZr-.js → wheel-scroll-CQ22Hcyj.js} +0 -0
@@ -0,0 +1,3705 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: !0 });
9
+ }, __copyProps = (to, from, except, desc) => {
10
+ if (from && typeof from == "object" || typeof from == "function")
11
+ for (let key of __getOwnPropNames(from))
12
+ !__hasOwnProp.call(to, key) && key !== except && __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
13
+ return to;
14
+ };
15
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: !0 }), mod);
16
+
17
+ // src/experimental/browser.ts
18
+ var browser_exports = {};
19
+ __export(browser_exports, {
20
+ TBrowser: () => TBrowser
21
+ });
22
+ module.exports = __toCommonJS(browser_exports);
23
+
24
+ // src/vue/components/TBrowser.ts
25
+ var import_vue12 = require("vue");
26
+
27
+ // src/vue/composables/use-layout.ts
28
+ var import_vue2 = require("vue");
29
+
30
+ // src/vue/context.ts
31
+ var import_vue = require("vue");
32
+
33
+ // src/renderer/terminal-graphics-trace.ts
34
+ var metrics = {
35
+ requests: 0,
36
+ skippedHidden: 0,
37
+ skippedScrolling: 0,
38
+ cacheHits: 0,
39
+ cacheMisses: 0,
40
+ cacheStores: 0,
41
+ rendererRuns: 0,
42
+ rendererAborts: 0,
43
+ rendererErrors: 0,
44
+ queued: 0,
45
+ queueWaits: 0,
46
+ queueDeduped: 0,
47
+ cleared: 0,
48
+ bytesQueued: 0,
49
+ totalRendererMs: 0,
50
+ totalValidateMs: 0,
51
+ totalQueueWaitMs: 0,
52
+ maxQueueWaitMs: 0,
53
+ maxActiveRenders: 0,
54
+ maxWaitingRenders: 0,
55
+ maxCacheEntries: 0,
56
+ maxCacheBytes: 0,
57
+ scrollStarts: 0,
58
+ scrollMarks: 0,
59
+ scrollIdles: 0,
60
+ totalScrollMs: 0,
61
+ maxScrollMs: 0
62
+ }, subscribers = /* @__PURE__ */ new Set();
63
+ function nowTerminalGraphicTraceTime() {
64
+ return typeof performance < "u" && typeof performance.now == "function" ? performance.now() : Date.now();
65
+ }
66
+ function recordTerminalGraphicTrace(event) {
67
+ let normalized = {
68
+ ...event,
69
+ timestamp: event.timestamp ?? nowTerminalGraphicTraceTime()
70
+ };
71
+ switch (normalized.type) {
72
+ case "request":
73
+ metrics.requests++;
74
+ break;
75
+ case "skip-hidden":
76
+ metrics.skippedHidden++;
77
+ break;
78
+ case "skip-scrolling":
79
+ metrics.skippedScrolling++;
80
+ break;
81
+ case "cache-hit":
82
+ metrics.cacheHits++;
83
+ break;
84
+ case "cache-miss":
85
+ metrics.cacheMisses++;
86
+ break;
87
+ case "cache-store":
88
+ metrics.cacheStores++;
89
+ break;
90
+ case "renderer-start":
91
+ metrics.rendererRuns++;
92
+ break;
93
+ case "renderer-end":
94
+ metrics.totalRendererMs += normalized.durationMs ?? 0;
95
+ break;
96
+ case "renderer-abort":
97
+ metrics.rendererAborts++;
98
+ break;
99
+ case "renderer-error":
100
+ metrics.rendererErrors++;
101
+ break;
102
+ case "validate-end":
103
+ metrics.totalValidateMs += normalized.durationMs ?? 0;
104
+ break;
105
+ case "queue":
106
+ metrics.queued++, metrics.bytesQueued += normalized.bytes ?? 0;
107
+ break;
108
+ case "queue-wait": {
109
+ let durationMs = normalized.durationMs ?? 0;
110
+ metrics.queueWaits++, metrics.totalQueueWaitMs += durationMs, metrics.maxQueueWaitMs = Math.max(metrics.maxQueueWaitMs, durationMs);
111
+ break;
112
+ }
113
+ case "queue-dedupe":
114
+ metrics.queueDeduped++;
115
+ break;
116
+ case "clear":
117
+ metrics.cleared++;
118
+ break;
119
+ case "scroll-start":
120
+ metrics.scrollStarts++;
121
+ break;
122
+ case "scroll-mark":
123
+ metrics.scrollMarks++;
124
+ break;
125
+ case "scroll-idle": {
126
+ let durationMs = normalized.durationMs ?? 0;
127
+ metrics.scrollIdles++, metrics.totalScrollMs += durationMs, metrics.maxScrollMs = Math.max(metrics.maxScrollMs, durationMs);
128
+ break;
129
+ }
130
+ }
131
+ normalized.active != null && Number.isFinite(normalized.active) && (metrics.maxActiveRenders = Math.max(metrics.maxActiveRenders, Math.max(0, normalized.active))), normalized.waiting != null && Number.isFinite(normalized.waiting) && (metrics.maxWaitingRenders = Math.max(
132
+ metrics.maxWaitingRenders,
133
+ Math.max(0, normalized.waiting)
134
+ )), normalized.cacheEntries != null && Number.isFinite(normalized.cacheEntries) && (metrics.maxCacheEntries = Math.max(
135
+ metrics.maxCacheEntries,
136
+ Math.max(0, normalized.cacheEntries)
137
+ )), normalized.cacheBytes != null && Number.isFinite(normalized.cacheBytes) && (metrics.maxCacheBytes = Math.max(metrics.maxCacheBytes, Math.max(0, normalized.cacheBytes)));
138
+ for (let subscriber of subscribers)
139
+ try {
140
+ subscriber(normalized);
141
+ } catch {
142
+ }
143
+ }
144
+
145
+ // src/vue/injection-key.ts
146
+ var VUE_TUI_INJECTION_PROTOCOL = "v1";
147
+ function injectionKey(name) {
148
+ return Symbol.for(`@simon_he/vue-tui:${VUE_TUI_INJECTION_PROTOCOL}:${name}`);
149
+ }
150
+
151
+ // src/vue/context.ts
152
+ var TerminalContextKey = injectionKey("TerminalContext"), LayoutContextKey = injectionKey("LayoutContext"), VisibilityContextKey = injectionKey("VisibilityContext"), EventZIndexContextKey = injectionKey("EventZIndex"), RenderPlaneContextKey = injectionKey("RenderPlane"), ImeAnchorContextKey = injectionKey("ImeAnchor"), TInputPluginsContextKey = injectionKey("TInputPlugins"), TPathPickerProviderContextKey = injectionKey("TPathPickerProvider"), TerminalGraphicsActivityKey = injectionKey(
153
+ "TerminalGraphicsActivity"
154
+ ), DialogContextKey = injectionKey("DialogContext");
155
+
156
+ // src/vue/composables/use-layout.ts
157
+ function useLayout() {
158
+ let ctx = (0, import_vue2.inject)(LayoutContextKey, null);
159
+ if (!ctx)
160
+ throw new Error("LayoutContext is missing (TerminalProvider/TView)");
161
+ return ctx;
162
+ }
163
+
164
+ // src/vue/composables/use-terminal-node.ts
165
+ var import_vue4 = require("vue");
166
+
167
+ // src/vue/composables/use-terminal.ts
168
+ var import_vue3 = require("vue");
169
+ function useTerminal() {
170
+ let ctx = (0, import_vue3.inject)(TerminalContextKey, null);
171
+ if (!ctx)
172
+ throw new Error("TerminalProvider is missing");
173
+ return ctx;
174
+ }
175
+
176
+ // src/core/buffer/eaw-ranges-unicode-17.ts
177
+ var fullWidthRanges = [
178
+ [4352, 4447],
179
+ [8986, 8987],
180
+ [9001, 9002],
181
+ [9193, 9196],
182
+ [9200, 9200],
183
+ [9203, 9203],
184
+ [9725, 9726],
185
+ [9748, 9749],
186
+ [9776, 9783],
187
+ [9800, 9811],
188
+ [9855, 9855],
189
+ [9866, 9871],
190
+ [9875, 9875],
191
+ [9889, 9889],
192
+ [9898, 9899],
193
+ [9917, 9918],
194
+ [9924, 9925],
195
+ [9934, 9934],
196
+ [9940, 9940],
197
+ [9962, 9962],
198
+ [9970, 9971],
199
+ [9973, 9973],
200
+ [9978, 9978],
201
+ [9981, 9981],
202
+ [9989, 9989],
203
+ [9994, 9995],
204
+ [10024, 10024],
205
+ [10060, 10060],
206
+ [10062, 10062],
207
+ [10067, 10069],
208
+ [10071, 10071],
209
+ [10133, 10135],
210
+ [10160, 10160],
211
+ [10175, 10175],
212
+ [11035, 11036],
213
+ [11088, 11088],
214
+ [11093, 11093],
215
+ [11904, 11929],
216
+ [11931, 12019],
217
+ [12032, 12245],
218
+ [12272, 12350],
219
+ [12353, 12438],
220
+ [12441, 12543],
221
+ [12549, 12591],
222
+ [12593, 12686],
223
+ [12688, 12773],
224
+ [12783, 12830],
225
+ [12832, 12871],
226
+ [12880, 42124],
227
+ [42128, 42182],
228
+ [43360, 43388],
229
+ [44032, 55203],
230
+ [63744, 64255],
231
+ [65040, 65049],
232
+ [65072, 65106],
233
+ [65108, 65126],
234
+ [65128, 65131],
235
+ [65281, 65376],
236
+ [65504, 65510],
237
+ [94176, 94180],
238
+ [94192, 94198],
239
+ [94208, 101589],
240
+ [101631, 101662],
241
+ [101760, 101874],
242
+ [110576, 110579],
243
+ [110581, 110587],
244
+ [110589, 110590],
245
+ [110592, 110882],
246
+ [110898, 110898],
247
+ [110928, 110930],
248
+ [110933, 110933],
249
+ [110948, 110951],
250
+ [110960, 111355],
251
+ [119552, 119638],
252
+ [119648, 119670],
253
+ [126980, 126980],
254
+ [127183, 127183],
255
+ [127374, 127374],
256
+ [127377, 127386],
257
+ [127488, 127490],
258
+ [127504, 127547],
259
+ [127552, 127560],
260
+ [127568, 127569],
261
+ [127584, 127589],
262
+ [127744, 127776],
263
+ [127789, 127797],
264
+ [127799, 127868],
265
+ [127870, 127891],
266
+ [127904, 127946],
267
+ [127951, 127955],
268
+ [127968, 127984],
269
+ [127988, 127988],
270
+ [127992, 128062],
271
+ [128064, 128064],
272
+ [128066, 128252],
273
+ [128255, 128317],
274
+ [128331, 128334],
275
+ [128336, 128359],
276
+ [128378, 128378],
277
+ [128405, 128406],
278
+ [128420, 128420],
279
+ [128507, 128591],
280
+ [128640, 128709],
281
+ [128716, 128716],
282
+ [128720, 128722],
283
+ [128725, 128728],
284
+ [128732, 128735],
285
+ [128747, 128748],
286
+ [128756, 128764],
287
+ [128992, 129003],
288
+ [129008, 129008],
289
+ [129292, 129338],
290
+ [129340, 129349],
291
+ [129351, 129535],
292
+ [129648, 129660],
293
+ [129664, 129674],
294
+ [129678, 129734],
295
+ [129736, 129736],
296
+ [129741, 129756],
297
+ [129759, 129770],
298
+ [129775, 129784],
299
+ [131072, 196605],
300
+ [196608, 262141]
301
+ ], ambiguousWidthRanges = [
302
+ [161, 161],
303
+ [164, 164],
304
+ [167, 168],
305
+ [170, 170],
306
+ [173, 174],
307
+ [176, 180],
308
+ [182, 186],
309
+ [188, 191],
310
+ [198, 198],
311
+ [208, 208],
312
+ [215, 216],
313
+ [222, 225],
314
+ [230, 230],
315
+ [232, 234],
316
+ [236, 237],
317
+ [240, 240],
318
+ [242, 243],
319
+ [247, 250],
320
+ [252, 252],
321
+ [254, 254],
322
+ [257, 257],
323
+ [273, 273],
324
+ [275, 275],
325
+ [283, 283],
326
+ [294, 295],
327
+ [299, 299],
328
+ [305, 307],
329
+ [312, 312],
330
+ [319, 322],
331
+ [324, 324],
332
+ [328, 331],
333
+ [333, 333],
334
+ [338, 339],
335
+ [358, 359],
336
+ [363, 363],
337
+ [462, 462],
338
+ [464, 464],
339
+ [466, 466],
340
+ [468, 468],
341
+ [470, 470],
342
+ [472, 472],
343
+ [474, 474],
344
+ [476, 476],
345
+ [593, 593],
346
+ [609, 609],
347
+ [708, 708],
348
+ [711, 711],
349
+ [713, 715],
350
+ [717, 717],
351
+ [720, 720],
352
+ [728, 731],
353
+ [733, 733],
354
+ [735, 735],
355
+ [768, 879],
356
+ [913, 929],
357
+ [931, 937],
358
+ [945, 961],
359
+ [963, 969],
360
+ [1025, 1025],
361
+ [1040, 1103],
362
+ [1105, 1105],
363
+ [8208, 8208],
364
+ [8211, 8214],
365
+ [8216, 8217],
366
+ [8220, 8221],
367
+ [8224, 8226],
368
+ [8228, 8231],
369
+ [8240, 8240],
370
+ [8242, 8243],
371
+ [8245, 8245],
372
+ [8251, 8251],
373
+ [8254, 8254],
374
+ [8308, 8308],
375
+ [8319, 8319],
376
+ [8321, 8324],
377
+ [8364, 8364],
378
+ [8451, 8451],
379
+ [8453, 8453],
380
+ [8457, 8457],
381
+ [8467, 8467],
382
+ [8470, 8470],
383
+ [8481, 8482],
384
+ [8486, 8486],
385
+ [8491, 8491],
386
+ [8531, 8532],
387
+ [8539, 8542],
388
+ [8544, 8555],
389
+ [8560, 8569],
390
+ [8585, 8585],
391
+ [8592, 8601],
392
+ [8632, 8633],
393
+ [8658, 8658],
394
+ [8660, 8660],
395
+ [8679, 8679],
396
+ [8704, 8704],
397
+ [8706, 8707],
398
+ [8711, 8712],
399
+ [8715, 8715],
400
+ [8719, 8719],
401
+ [8721, 8721],
402
+ [8725, 8725],
403
+ [8730, 8730],
404
+ [8733, 8736],
405
+ [8739, 8739],
406
+ [8741, 8741],
407
+ [8743, 8748],
408
+ [8750, 8750],
409
+ [8756, 8759],
410
+ [8764, 8765],
411
+ [8776, 8776],
412
+ [8780, 8780],
413
+ [8786, 8786],
414
+ [8800, 8801],
415
+ [8804, 8807],
416
+ [8810, 8811],
417
+ [8814, 8815],
418
+ [8834, 8835],
419
+ [8838, 8839],
420
+ [8853, 8853],
421
+ [8857, 8857],
422
+ [8869, 8869],
423
+ [8895, 8895],
424
+ [8978, 8978],
425
+ [9312, 9449],
426
+ [9451, 9547],
427
+ [9552, 9587],
428
+ [9600, 9615],
429
+ [9618, 9621],
430
+ [9632, 9633],
431
+ [9635, 9641],
432
+ [9650, 9651],
433
+ [9654, 9655],
434
+ [9660, 9661],
435
+ [9664, 9665],
436
+ [9670, 9672],
437
+ [9675, 9675],
438
+ [9678, 9681],
439
+ [9698, 9701],
440
+ [9711, 9711],
441
+ [9733, 9734],
442
+ [9737, 9737],
443
+ [9742, 9743],
444
+ [9756, 9756],
445
+ [9758, 9758],
446
+ [9792, 9792],
447
+ [9794, 9794],
448
+ [9824, 9825],
449
+ [9827, 9829],
450
+ [9831, 9834],
451
+ [9836, 9837],
452
+ [9839, 9839],
453
+ [9886, 9887],
454
+ [9919, 9919],
455
+ [9926, 9933],
456
+ [9935, 9939],
457
+ [9941, 9953],
458
+ [9955, 9955],
459
+ [9960, 9961],
460
+ [9963, 9969],
461
+ [9972, 9972],
462
+ [9974, 9977],
463
+ [9979, 9980],
464
+ [9982, 9983],
465
+ [10045, 10045],
466
+ [10102, 10111],
467
+ [11094, 11097],
468
+ [12872, 12879],
469
+ [57344, 63743],
470
+ [65024, 65039],
471
+ [65533, 65533],
472
+ [127232, 127242],
473
+ [127248, 127277],
474
+ [127280, 127337],
475
+ [127344, 127373],
476
+ [127375, 127376],
477
+ [127387, 127404],
478
+ [917760, 917999],
479
+ [983040, 1048573],
480
+ [1048576, 1114109]
481
+ ];
482
+
483
+ // src/core/buffer/width.ts
484
+ function isFullWidthCodePoint(codePoint) {
485
+ if (codePoint < 4352)
486
+ return !1;
487
+ for (let [start, end] of fullWidthRanges) {
488
+ if (codePoint < start)
489
+ return !1;
490
+ if (codePoint <= end)
491
+ return !0;
492
+ }
493
+ return !1;
494
+ }
495
+ function isAmbiguousWidthCodePoint(codePoint) {
496
+ let first = ambiguousWidthRanges[0], last = ambiguousWidthRanges[ambiguousWidthRanges.length - 1];
497
+ if (!first || !last || codePoint < first[0] || codePoint > last[1])
498
+ return !1;
499
+ for (let [start, end] of ambiguousWidthRanges) {
500
+ if (codePoint < start)
501
+ return !1;
502
+ if (codePoint <= end)
503
+ return !0;
504
+ }
505
+ return !1;
506
+ }
507
+ function isVariationSelectorCodePoint(codePoint) {
508
+ return codePoint >= 65024 && codePoint <= 65039 || codePoint >= 917760 && codePoint <= 917999;
509
+ }
510
+ function isCombiningMarkCodePoint(codePoint) {
511
+ return codePoint >= 768 && codePoint <= 879 || // Combining Diacritical Marks
512
+ codePoint >= 6832 && codePoint <= 6911 || // Combining Diacritical Marks Extended
513
+ codePoint >= 7616 && codePoint <= 7679 || // Combining Diacritical Marks Supplement
514
+ codePoint >= 8400 && codePoint <= 8447 || // Combining Diacritical Marks for Symbols
515
+ codePoint >= 65056 && codePoint <= 65071 || // Combining Half Marks
516
+ codePoint >= 12330 && codePoint <= 12335 || // EAW=W: Ideographic level tone marks
517
+ codePoint >= 12441 && codePoint <= 12442 || // EAW=W: Combining Katakana-Hiragana marks
518
+ codePoint === 94180;
519
+ }
520
+ function isEmojiLike(codePoint) {
521
+ return codePoint >= 127744 && codePoint <= 129791 || codePoint >= 127462 && codePoint <= 127487;
522
+ }
523
+ var extendedPictographicRe = null;
524
+ try {
525
+ extendedPictographicRe = new RegExp("\\p{Extended_Pictographic}", "u");
526
+ } catch {
527
+ extendedPictographicRe = null;
528
+ }
529
+ var emojiPresentationRe = null;
530
+ try {
531
+ emojiPresentationRe = new RegExp("\\p{Emoji_Presentation}", "u");
532
+ } catch {
533
+ emojiPresentationRe = null;
534
+ }
535
+ var emojiRe = null;
536
+ try {
537
+ emojiRe = new RegExp("\\p{Emoji}", "u");
538
+ } catch {
539
+ emojiRe = null;
540
+ }
541
+ function normalizeCustomWidth(width) {
542
+ return width === 2 ? 2 : 1;
543
+ }
544
+ function charCellWidth(text, provider = "default") {
545
+ if (!text)
546
+ return 1;
547
+ if (typeof provider == "function")
548
+ return normalizeCustomWidth(provider(text));
549
+ if (provider !== "cjk" && text.length === 1 && text.charCodeAt(0) < 4352)
550
+ return 1;
551
+ let codePoint = text.codePointAt(0);
552
+ if (codePoint == null)
553
+ return 1;
554
+ let hasVs16 = text.includes("\uFE0F");
555
+ return isVariationSelectorCodePoint(codePoint) || isCombiningMarkCodePoint(codePoint) || codePoint >= 9472 && codePoint <= 9599 ? 1 : isFullWidthCodePoint(codePoint) || provider === "cjk" && isAmbiguousWidthCodePoint(codePoint) || isEmojiLike(codePoint) || emojiPresentationRe?.test(text) || text.includes("\u20E3") || hasVs16 && emojiRe?.test(text) ? 2 : extendedPictographicRe?.test(text) ? codePoint <= 65535 ? hasVs16 ? 2 : 1 : 2 : 1;
556
+ }
557
+
558
+ // src/utils/grapheme.ts
559
+ var graphemeSegmenter = null;
560
+ try {
561
+ let Segmenter = typeof Intl < "u" ? Intl.Segmenter : void 0;
562
+ graphemeSegmenter = Segmenter ? new Segmenter(void 0, { granularity: "grapheme" }) : null;
563
+ } catch {
564
+ graphemeSegmenter = null;
565
+ }
566
+ var unicodeMarkRe = null;
567
+ try {
568
+ unicodeMarkRe = new RegExp("\\p{Mark}", "u");
569
+ } catch {
570
+ unicodeMarkRe = null;
571
+ }
572
+ function needsGraphemeSegmentation(text) {
573
+ for (let ch of text) {
574
+ let cp = ch.codePointAt(0);
575
+ if (cp === 8205 || cp >= 65024 && cp <= 65039 || cp >= 917760 && cp <= 917999 || isCombiningMark(cp) || cp >= 127995 && cp <= 127999 || cp >= 127462 && cp <= 127487 || cp >= 917504 && cp <= 917631)
576
+ return !0;
577
+ }
578
+ return !1;
579
+ }
580
+ function isVariationSelector(codePoint) {
581
+ return codePoint >= 65024 && codePoint <= 65039 || codePoint >= 917760 && codePoint <= 917999;
582
+ }
583
+ function isCombiningMark(codePoint) {
584
+ return codePoint >= 768 && codePoint <= 879 || codePoint >= 6832 && codePoint <= 6911 || codePoint >= 7616 && codePoint <= 7679 || codePoint >= 8400 && codePoint <= 8447 || codePoint >= 65056 && codePoint <= 65071 || isDevanagariMark(codePoint) || unicodeMarkRe?.test(String.fromCodePoint(codePoint)) === !0;
585
+ }
586
+ function isDevanagariMark(codePoint) {
587
+ return codePoint >= 2304 && codePoint <= 2307 || codePoint >= 2362 && codePoint <= 2364 || codePoint >= 2366 && codePoint <= 2383 || codePoint >= 2385 && codePoint <= 2391 || codePoint >= 2402 && codePoint <= 2403;
588
+ }
589
+ function isVirama(codePoint) {
590
+ return codePoint === 2381;
591
+ }
592
+ function isEmojiModifier(codePoint) {
593
+ return codePoint >= 127995 && codePoint <= 127999;
594
+ }
595
+ function isRegionalIndicator(codePoint) {
596
+ return codePoint >= 127462 && codePoint <= 127487;
597
+ }
598
+ function isEmojiTag(codePoint) {
599
+ return codePoint >= 917504 && codePoint <= 917631;
600
+ }
601
+ function fallbackGraphemeSegments(text) {
602
+ let out = [], segment = "", segmentStart = 0, pos = 0, regionalIndicators = 0, joinNext = !1, pushSegment = () => {
603
+ segment && out.push({ segment, index: segmentStart });
604
+ };
605
+ for (let ch of text) {
606
+ let codePoint = ch.codePointAt(0), chStart = pos;
607
+ pos += ch.length, segment !== "" && (joinNext || codePoint === 8205 || isVariationSelector(codePoint) || isCombiningMark(codePoint) || isEmojiModifier(codePoint) || isEmojiTag(codePoint) || isRegionalIndicator(codePoint) && regionalIndicators === 1) ? (segment += ch, isRegionalIndicator(codePoint) ? regionalIndicators++ : !isVariationSelector(codePoint) && !isCombiningMark(codePoint) && (regionalIndicators = 0)) : (pushSegment(), segment = ch, segmentStart = chStart, regionalIndicators = isRegionalIndicator(codePoint) ? 1 : 0), codePoint === 8205 || isVirama(codePoint) ? joinNext = !0 : joinNext && !isVariationSelector(codePoint) && !isCombiningMark(codePoint) && (joinNext = !1);
608
+ }
609
+ return pushSegment(), out;
610
+ }
611
+ function segmentedGraphemes(text) {
612
+ return needsGraphemeSegmentation(text) ? graphemeSegmenter ? graphemeSegmenter.segment(text) : fallbackGraphemeSegments(text) : null;
613
+ }
614
+
615
+ // src/vue/utils/text.ts
616
+ var renderPassDepth = 0, renderPassTextWidthCache = /* @__PURE__ */ new Map(), textWidthProviderStack = [];
617
+ function currentTextWidthProvider() {
618
+ return textWidthProviderStack[textWidthProviderStack.length - 1] ?? "default";
619
+ }
620
+ function hasAsciiFastPath(provider) {
621
+ return typeof provider != "function";
622
+ }
623
+ function canUseDefaultTextCache(provider) {
624
+ return provider === "default" || provider === "narrow-ambiguous";
625
+ }
626
+ function withTextWidthProvider(provider, fn) {
627
+ textWidthProviderStack.push(provider ?? "default");
628
+ try {
629
+ return fn();
630
+ } finally {
631
+ textWidthProviderStack.pop();
632
+ }
633
+ }
634
+ function isAscii(text) {
635
+ for (let i = 0; i < text.length; i++)
636
+ if (text.charCodeAt(i) > 127)
637
+ return !1;
638
+ return !0;
639
+ }
640
+ var UNSAFE_FORMAT_CONTROL_RE = /[\u061C\u00AD\u180E\u200B\u200C\u200E\u200F\u202A-\u202E\u2060-\u206F\uFEFF]/u;
641
+ function isUnsafeFormatControl(codePoint) {
642
+ return codePoint === 1564 || codePoint === 173 || codePoint === 6158 || codePoint === 8203 || codePoint === 8204 || codePoint === 8206 || codePoint === 8207 || codePoint >= 8234 && codePoint <= 8238 || codePoint >= 8288 && codePoint <= 8303 || codePoint === 65279;
643
+ }
644
+ function hasInlineAsciiControl(text) {
645
+ for (let i = 0; i < text.length; i++) {
646
+ let code = text.charCodeAt(i);
647
+ if (code === 10 || code === 13 || code === 9)
648
+ return !0;
649
+ }
650
+ return !1;
651
+ }
652
+ function hasTextBlockAsciiControl(text) {
653
+ for (let i = 0; i < text.length; i++) {
654
+ let code = text.charCodeAt(i);
655
+ if (code === 9 || code <= 31 && code !== 10 || code === 127)
656
+ return !0;
657
+ }
658
+ return !1;
659
+ }
660
+ function forEachGrapheme(text, cb) {
661
+ if (!text)
662
+ return;
663
+ let segments = segmentedGraphemes(text);
664
+ if (!segments) {
665
+ for (let ch of text)
666
+ if (cb(ch) === !1)
667
+ return;
668
+ return;
669
+ }
670
+ for (let part of segments)
671
+ if (cb(part.segment) === !1)
672
+ return;
673
+ }
674
+ function sanitizeInlineText(text) {
675
+ if (!text)
676
+ return "";
677
+ if (!UNSAFE_FORMAT_CONTROL_RE.test(text) && !hasInlineAsciiControl(text))
678
+ return text;
679
+ let out = [];
680
+ for (let ch of text) {
681
+ let cp = ch.codePointAt(0);
682
+ if (cp === 10 || cp === 13 || cp === 9) {
683
+ out.push(" ");
684
+ continue;
685
+ }
686
+ isUnsafeFormatControl(cp) || out.push(ch);
687
+ }
688
+ return out.join("");
689
+ }
690
+ function sanitizeTextBlock(text) {
691
+ if (!text)
692
+ return "";
693
+ if (!UNSAFE_FORMAT_CONTROL_RE.test(text) && !hasTextBlockAsciiControl(text))
694
+ return text;
695
+ let out = [];
696
+ out.length = 0;
697
+ for (let ch of text) {
698
+ let cp = ch.codePointAt(0);
699
+ if (cp !== 13) {
700
+ if (cp === 9) {
701
+ out.push(" ");
702
+ continue;
703
+ }
704
+ cp <= 31 && cp !== 10 || cp === 127 || isUnsafeFormatControl(cp) || out.push(ch);
705
+ }
706
+ }
707
+ return out.join("");
708
+ }
709
+ function textCellWidth(text, provider = currentTextWidthProvider()) {
710
+ if (!text)
711
+ return 0;
712
+ if (hasAsciiFastPath(provider) && isAscii(text))
713
+ return text.length;
714
+ let useCache = canUseDefaultTextCache(provider);
715
+ if (useCache && renderPassDepth > 0) {
716
+ let cached = renderPassTextWidthCache.get(text);
717
+ if (cached != null)
718
+ return cached;
719
+ }
720
+ if (useCache) {
721
+ let cached = textWidthCacheGet(text);
722
+ if (cached != null)
723
+ return cached;
724
+ }
725
+ let cells = 0;
726
+ return forEachGrapheme(text, (g) => {
727
+ cells += charCellWidth(g, provider);
728
+ }), useCache && renderPassDepth > 0 && renderPassTextWidthCache.set(text, cells), useCache && textWidthCacheSet(text, cells), cells;
729
+ }
730
+ var spaceCache = /* @__PURE__ */ new Map(), MAX_CACHED_SPACES = 256;
731
+ function spaces(count) {
732
+ if (count = Math.max(0, Math.floor(count)), count === 0)
733
+ return "";
734
+ let cached = spaceCache.get(count);
735
+ if (cached)
736
+ return cached;
737
+ let v = " ".repeat(count);
738
+ return spaceCache.size >= MAX_CACHED_SPACES && spaceCache.clear(), spaceCache.set(count, v), v;
739
+ }
740
+ function sliceByCells(text, maxCells, provider = currentTextWidthProvider()) {
741
+ if (maxCells = Math.max(0, Math.floor(maxCells)), maxCells <= 0)
742
+ return "";
743
+ if (text && hasAsciiFastPath(provider) && isAscii(text))
744
+ return text.slice(0, maxCells);
745
+ let out = [], cells = 0;
746
+ return forEachGrapheme(text, (g) => {
747
+ let w = charCellWidth(g, provider);
748
+ if (cells + w > maxCells)
749
+ return !1;
750
+ out.push(g), cells += w;
751
+ }), out.length ? out.join("") : "";
752
+ }
753
+ function sliceByCellsRange(text, startCells, endCells, provider = currentTextWidthProvider()) {
754
+ if (startCells = Math.max(0, Math.floor(startCells)), endCells = Math.max(0, Math.floor(endCells)), endCells <= startCells || !text)
755
+ return "";
756
+ if (hasAsciiFastPath(provider) && isAscii(text))
757
+ return text.slice(startCells, endCells);
758
+ let out = [], cells = 0;
759
+ return forEachGrapheme(text, (g) => {
760
+ let w = charCellWidth(g, provider), next = cells + w;
761
+ if (cells >= endCells)
762
+ return !1;
763
+ if (next <= startCells) {
764
+ cells = next;
765
+ return;
766
+ }
767
+ if (cells < startCells && next > startCells) {
768
+ out.push(spaces(Math.min(next, endCells) - startCells)), cells = next;
769
+ return;
770
+ }
771
+ if (next > endCells)
772
+ return out.push(spaces(endCells - cells)), !1;
773
+ out.push(g), cells = next;
774
+ }), out.length ? out.join("") : "";
775
+ }
776
+ function padEndByCells(text, width, provider = currentTextWidthProvider()) {
777
+ width = Math.max(0, Math.floor(width));
778
+ let cells = text && hasAsciiFastPath(provider) && isAscii(text) ? text.length : textCellWidth(text, provider);
779
+ return cells >= width ? text : `${text}${spaces(width - cells)}`;
780
+ }
781
+ var wrapCacheByWidth = /* @__PURE__ */ new Map(), MAX_WRAP_CACHE_BUCKETS = 32, MAX_WRAP_CACHE_PER_WIDTH = 256;
782
+ function getWrapBucket(width) {
783
+ let bucket = wrapCacheByWidth.get(width);
784
+ return bucket || (wrapCacheByWidth.size >= MAX_WRAP_CACHE_BUCKETS && wrapCacheByWidth.clear(), bucket = /* @__PURE__ */ new Map(), wrapCacheByWidth.set(width, bucket), bucket);
785
+ }
786
+ var textWidthCache = /* @__PURE__ */ new Map(), MAX_TEXT_WIDTH_CACHE = 1024;
787
+ function textWidthCacheGet(text) {
788
+ let cached = textWidthCache.get(text);
789
+ return cached == null ? null : (textWidthCache.delete(text), textWidthCache.set(text, cached), cached);
790
+ }
791
+ function textWidthCacheSet(text, cells) {
792
+ if (textWidthCache.set(text, cells), textWidthCache.size > MAX_TEXT_WIDTH_CACHE) {
793
+ let firstKey = textWidthCache.keys().next().value;
794
+ firstKey != null && textWidthCache.delete(firstKey);
795
+ }
796
+ }
797
+ function wrapByCells(text, width, provider = currentTextWidthProvider()) {
798
+ width = Math.max(1, Math.floor(width));
799
+ let bucket = canUseDefaultTextCache(provider) ? getWrapBucket(width) : null;
800
+ if (text && hasAsciiFastPath(provider) && isAscii(text)) {
801
+ if (bucket) {
802
+ let cached = bucket.get(text);
803
+ if (cached)
804
+ return cached;
805
+ }
806
+ let out2 = [];
807
+ for (let rawLine of text.replace(/\r/g, "").split(`
808
+ `)) {
809
+ if (rawLine.length === 0) {
810
+ out2.push("");
811
+ continue;
812
+ }
813
+ for (let i = 0; i < rawLine.length; i += width)
814
+ out2.push(rawLine.slice(i, i + width));
815
+ }
816
+ return bucket && (bucket.size >= MAX_WRAP_CACHE_PER_WIDTH && bucket.clear(), bucket.set(text, out2)), out2;
817
+ }
818
+ if (bucket) {
819
+ let cached = bucket.get(text);
820
+ if (cached)
821
+ return cached;
822
+ }
823
+ let out = [];
824
+ for (let rawLine of text.replace(/\r/g, "").split(`
825
+ `)) {
826
+ if (rawLine.length === 0) {
827
+ out.push("");
828
+ continue;
829
+ }
830
+ let segments = segmentedGraphemes(rawLine);
831
+ if (segments) {
832
+ let lineStart = 0, cells = 0;
833
+ for (let part of segments) {
834
+ let g = part.segment, gIdx = part.index, w = charCellWidth(g, provider);
835
+ if (cells > 0 && cells + w > width && (out.push(rawLine.slice(lineStart, gIdx)), lineStart = gIdx, cells = 0), cells += w, cells >= width) {
836
+ let end = gIdx + g.length;
837
+ out.push(rawLine.slice(lineStart, end)), lineStart = end, cells = 0;
838
+ }
839
+ }
840
+ lineStart < rawLine.length && out.push(rawLine.slice(lineStart));
841
+ } else {
842
+ let lineStart = 0, pos = 0, cells = 0;
843
+ for (let ch of rawLine) {
844
+ let w = charCellWidth(ch, provider);
845
+ cells > 0 && cells + w > width && (out.push(rawLine.slice(lineStart, pos)), lineStart = pos, cells = 0), pos += ch.length, cells += w, cells >= width && (out.push(rawLine.slice(lineStart, pos)), lineStart = pos, cells = 0);
846
+ }
847
+ lineStart < rawLine.length && out.push(rawLine.slice(lineStart));
848
+ }
849
+ }
850
+ let res = out.length ? out : [""];
851
+ return bucket && (bucket.size >= MAX_WRAP_CACHE_PER_WIDTH && bucket.clear(), bucket.set(text, res)), res;
852
+ }
853
+
854
+ // src/vue/composables/use-terminal-node.ts
855
+ function wrapHandlers(handlers, widthProvider) {
856
+ if (!handlers)
857
+ return {};
858
+ let out = {};
859
+ for (let key of Object.keys(handlers)) {
860
+ let handler = handlers[key];
861
+ handler && (out[key] = (event) => withTextWidthProvider(widthProvider, () => handler(event)));
862
+ }
863
+ return out;
864
+ }
865
+ function useTerminalNode(getOptions) {
866
+ let { events, widthProvider } = useTerminal(), id = (0, import_vue4.ref)(null), options = (0, import_vue4.computed)(() => withTextWidthProvider(widthProvider, getOptions)), stop = (0, import_vue4.watchEffect)(() => {
867
+ let manager = events.value;
868
+ if (!manager)
869
+ return;
870
+ let opt = options.value;
871
+ if (!id.value) {
872
+ let node = manager.register({
873
+ rect: opt.rect,
874
+ zIndex: opt.zIndex ?? 0,
875
+ visible: opt.visible,
876
+ focusable: opt.focusable,
877
+ selectable: opt.selectable,
878
+ selectionScrollBy: opt.selectionScrollBy,
879
+ handlers: wrapHandlers(opt.handlers, widthProvider)
880
+ });
881
+ id.value = node.id;
882
+ return;
883
+ }
884
+ manager.update(id.value, {
885
+ rect: opt.rect,
886
+ zIndex: opt.zIndex ?? 0,
887
+ visible: opt.visible,
888
+ focusable: opt.focusable,
889
+ selectable: opt.selectable,
890
+ selectionScrollBy: opt.selectionScrollBy,
891
+ handlers: wrapHandlers(opt.handlers, widthProvider)
892
+ });
893
+ });
894
+ return (0, import_vue4.onBeforeUnmount)(() => {
895
+ stop();
896
+ let manager = events.value;
897
+ manager && id.value && manager.unregister(id.value);
898
+ }), { id };
899
+ }
900
+
901
+ // src/vue/composables/use-visibility.ts
902
+ var import_vue5 = require("vue");
903
+ var VUE_TERMINAL_SHOW_CB = "__vueTerminalOnShow", vShowPatched = !1;
904
+ function patchVShow() {
905
+ if (vShowPatched)
906
+ return;
907
+ vShowPatched = !0;
908
+ let dir = import_vue5.vShow, origBeforeMount = dir.beforeMount, origUpdated = dir.updated, origBeforeUnmount = dir.beforeUnmount, notify = (el, value) => {
909
+ if (!el || typeof el != "object")
910
+ return;
911
+ let cb = el[VUE_TERMINAL_SHOW_CB];
912
+ cb?.(!!value);
913
+ };
914
+ typeof origBeforeMount == "function" && (dir.beforeMount = (el, binding, vnode) => {
915
+ origBeforeMount(el, binding, vnode), notify(el, binding?.value);
916
+ }), typeof origUpdated == "function" && (dir.updated = (el, binding, vnode) => {
917
+ origUpdated(el, binding, vnode), notify(el, binding?.value);
918
+ }), typeof origBeforeUnmount == "function" && (dir.beforeUnmount = (el, binding, vnode) => {
919
+ origBeforeUnmount(el, binding, vnode), notify(el, binding?.value);
920
+ });
921
+ }
922
+ var PLACEHOLDER_STYLE = Object.freeze({
923
+ position: "absolute",
924
+ left: "-9999px",
925
+ top: "0",
926
+ width: "0",
927
+ height: "0",
928
+ overflow: "hidden"
929
+ });
930
+ function useVisibility(options) {
931
+ patchVShow();
932
+ let { scheduler } = useTerminal(), parentVisible = (0, import_vue5.inject)(VisibilityContextKey, (0, import_vue5.ref)(!0)), localVisible = (0, import_vue5.ref)(!0), visible = (0, import_vue5.computed)(() => parentVisible.value && localVisible.value);
933
+ options?.provide && (0, import_vue5.provide)(VisibilityContextKey, visible);
934
+ let onShow = (value) => {
935
+ localVisible.value = value, scheduler.invalidate();
936
+ };
937
+ return { visible, rootProps: {
938
+ style: PLACEHOLDER_STYLE,
939
+ onVnodeBeforeMount: (vnode) => {
940
+ let el = vnode.el;
941
+ el && typeof el == "object" && (el[VUE_TERMINAL_SHOW_CB] = onShow);
942
+ },
943
+ onVnodeBeforeUnmount: (vnode) => {
944
+ let el = vnode.el;
945
+ el && typeof el == "object" && el[VUE_TERMINAL_SHOW_CB] === onShow && delete el[VUE_TERMINAL_SHOW_CB];
946
+ }
947
+ } };
948
+ }
949
+
950
+ // src/vue/utils/rect.ts
951
+ function intersectRect(a, b) {
952
+ let x0 = Math.max(a.x, b.x), y0 = Math.max(a.y, b.y), x1 = Math.min(a.x + a.w, b.x + b.w), y1 = Math.min(a.y + a.h, b.y + b.h);
953
+ return x1 <= x0 || y1 <= y0 ? null : { x: x0, y: y0, w: x1 - x0, h: y1 - y0 };
954
+ }
955
+ function translateRect(rect, dx, dy) {
956
+ return { x: rect.x + dx, y: rect.y + dy, w: rect.w, h: rect.h };
957
+ }
958
+
959
+ // src/vue/components/TVideo.ts
960
+ var import_vue11 = require("vue");
961
+
962
+ // src/core/terminal/create-terminal.ts
963
+ var TERMINAL_PLANE_INTERNALS = Symbol.for("@simon_he/vue-tui:v1:terminal-plane-internals"), TERMINAL_ROOT = Symbol.for("@simon_he/vue-tui:v1:terminal-root");
964
+ function getRootTerminal(terminal) {
965
+ return terminal[TERMINAL_ROOT] ?? terminal;
966
+ }
967
+
968
+ // src/renderer/terminal-graphics.ts
969
+ var ESC = "\x1B", BEL = "\x07", ST = `${ESC}\\`, ESC_RE = "\\u001B", BEL_RE = "\\u0007", CSI_RE = new RegExp(`${ESC_RE}\\[[0-?]*[ -/]*[@-~]`, "g"), OSC_RE = new RegExp(`${ESC_RE}\\][\\s\\S]*?(?:${BEL_RE}|${ESC_RE}\\\\)`, "g"), DCS_RE = new RegExp(`${ESC_RE}P[\\s\\S]*?${ESC_RE}\\\\`, "g"), APC_RE = new RegExp(`${ESC_RE}_[\\s\\S]*?${ESC_RE}\\\\`, "g"), C1_CSI_RE = new RegExp("\\u009B[0-?]*[ -/]*[@-~]", "g"), C1_OSC_RE = new RegExp(`\\u009D[\\s\\S]*?(?:${BEL_RE}|\\u009C)`, "g"), C1_DCS_RE = new RegExp("\\u0090[\\s\\S]*?\\u009C", "g"), C1_APC_RE = new RegExp("\\u009F[\\s\\S]*?\\u009C", "g"), MAX_TERMINAL_GRAPHICS_SEQUENCE_CHARS = 16 * 1024 * 1024, MAX_TERMINAL_GRAPHICS_FALLBACK_CHARS = 16384, MAX_TERMINAL_GRAPHIC_CELLS = 1e5, TERMINAL_GRAPHICS_REGISTRY = Symbol.for("@simon_he/vue-tui:v1:terminal-graphics"), terminalGraphicsGlobal = globalThis, terminalGraphicsRegistry = terminalGraphicsGlobal[TERMINAL_GRAPHICS_REGISTRY] ?? {
970
+ outputs: /* @__PURE__ */ new WeakMap(),
971
+ outputVersions: /* @__PURE__ */ new WeakMap(),
972
+ outputListeners: /* @__PURE__ */ new WeakMap()
973
+ };
974
+ terminalGraphicsGlobal[TERMINAL_GRAPHICS_REGISTRY] = terminalGraphicsRegistry;
975
+ var terminalGraphicsOutputs = terminalGraphicsRegistry.outputs, terminalGraphicsOutputVersions = terminalGraphicsRegistry.outputVersions, terminalGraphicsOutputListeners = terminalGraphicsRegistry.outputListeners;
976
+ function getTerminalGraphicsOutput(terminal) {
977
+ return terminalGraphicsOutputs.get(getRootTerminal(terminal)) ?? null;
978
+ }
979
+ function getTerminalGraphicsOutputVersion(terminal) {
980
+ return terminalGraphicsOutputVersions.get(getRootTerminal(terminal)) ?? 0;
981
+ }
982
+ function subscribeTerminalGraphicsOutput(terminal, listener) {
983
+ let rootTerminal = getRootTerminal(terminal), listeners = terminalGraphicsOutputListeners.get(rootTerminal);
984
+ return listeners || (listeners = /* @__PURE__ */ new Set(), terminalGraphicsOutputListeners.set(rootTerminal, listeners)), listeners.add(listener), () => {
985
+ listeners.delete(listener), listeners.size === 0 && terminalGraphicsOutputListeners.delete(rootTerminal);
986
+ };
987
+ }
988
+ function isTerminalGraphicsProtocol(value) {
989
+ return value === "kitty" || value === "iterm2" || value === "sixel";
990
+ }
991
+ function stableTerminalGraphicNumericId(input, options = {}) {
992
+ let min = Math.floor(options.min ?? 1), max = Math.floor(options.max ?? 2147483647), span = Math.max(1, max - min + 1), hash = 2166136261;
993
+ for (let index = 0; index < input.length; index += 1)
994
+ hash ^= input.charCodeAt(index), hash = Math.imul(hash, 16777619);
995
+ return min + (hash >>> 0) % span;
996
+ }
997
+ function positiveGraphicInt(value, max) {
998
+ let n = Math.trunc(Number(value));
999
+ return !Number.isFinite(n) || n <= 0 ? null : Math.min(max, n);
1000
+ }
1001
+ function normalizeTerminalGraphicSize(width, height) {
1002
+ let w = positiveGraphicInt(width, MAX_TERMINAL_GRAPHIC_CELLS), h6 = positiveGraphicInt(height, MAX_TERMINAL_GRAPHIC_CELLS);
1003
+ return w == null || h6 == null || w * h6 > MAX_TERMINAL_GRAPHIC_CELLS ? null : { width: w, height: h6 };
1004
+ }
1005
+ function canDrawTerminalGraphicRect(rect, size) {
1006
+ let x = Math.floor(rect.x), y = Math.floor(rect.y), graphicSize = normalizeTerminalGraphicSize(rect.w, rect.h), cols = Math.max(0, Math.floor(size.cols)), rows = Math.max(0, Math.floor(size.rows));
1007
+ return graphicSize != null && cols > 0 && rows > 0 && Number.isFinite(x) && Number.isFinite(y) && x >= 0 && y >= 0 && x < cols && y < rows;
1008
+ }
1009
+ function withoutNestedEscapes(body) {
1010
+ return !body.includes(ESC) && !body.includes(BEL);
1011
+ }
1012
+ function isBase64ish(value) {
1013
+ return /^[A-Za-z0-9+/=]*$/.test(value);
1014
+ }
1015
+ function parseKittyControls(raw) {
1016
+ let out = /* @__PURE__ */ new Map();
1017
+ if (!/^[A-Za-z0-9_,=+.\-:]*$/.test(raw))
1018
+ return null;
1019
+ for (let part of raw.split(",")) {
1020
+ if (!part)
1021
+ continue;
1022
+ let eq = part.indexOf("=");
1023
+ if (eq <= 0)
1024
+ return null;
1025
+ let key = part.slice(0, eq), value = part.slice(eq + 1);
1026
+ if (!/^[A-Za-z]$/.test(key) || !/^[A-Za-z0-9+.\-:]*$/.test(value))
1027
+ return null;
1028
+ out.set(key, value);
1029
+ }
1030
+ return out;
1031
+ }
1032
+ function parseKittyPackets(sequence) {
1033
+ let packets = [], index = 0;
1034
+ for (; index < sequence.length; ) {
1035
+ if (!sequence.startsWith(`${ESC}_G`, index))
1036
+ return null;
1037
+ let end = sequence.indexOf(ST, index + 3);
1038
+ if (end < 0)
1039
+ return null;
1040
+ let body = sequence.slice(index + 3, end);
1041
+ if (!withoutNestedEscapes(body))
1042
+ return null;
1043
+ let semicolon = body.indexOf(";"), rawControls = semicolon >= 0 ? body.slice(0, semicolon) : body, payload = semicolon >= 0 ? body.slice(semicolon + 1) : "", controls = parseKittyControls(rawControls);
1044
+ if (!controls || payload && !isBase64ish(payload))
1045
+ return null;
1046
+ packets.push({ controls, payload }), index = end + ST.length;
1047
+ }
1048
+ return packets.length ? packets : null;
1049
+ }
1050
+ var KITTY_DRAW_FIRST_CONTROL_KEYS = /* @__PURE__ */ new Set([
1051
+ "a",
1052
+ "f",
1053
+ "q",
1054
+ "C",
1055
+ "i",
1056
+ "I",
1057
+ "p",
1058
+ "c",
1059
+ "r",
1060
+ "x",
1061
+ "y",
1062
+ "w",
1063
+ "h",
1064
+ "z",
1065
+ "m",
1066
+ "t"
1067
+ ]), KITTY_DRAW_CONTINUATION_CONTROL_KEYS = /* @__PURE__ */ new Set(["a", "q", "m"]), KITTY_CLEAR_CONTROL_KEYS = /* @__PURE__ */ new Set(["a", "d", "i", "I", "p", "q"]);
1068
+ function kittyControlsUseOnly(controls, allowed) {
1069
+ for (let key of controls.keys())
1070
+ if (!allowed.has(key))
1071
+ return !1;
1072
+ return !0;
1073
+ }
1074
+ var KITTY_UINT32_MAX = 4294967295, KITTY_INT32_MIN = -2147483648, KITTY_INT32_MAX = 2147483647;
1075
+ function kittyControlIsUint32(controls, key, min = 0) {
1076
+ let value = controls.get(key);
1077
+ if (value == null)
1078
+ return !0;
1079
+ if (!/^\d+$/.test(value))
1080
+ return !1;
1081
+ let n = Number(value);
1082
+ return Number.isSafeInteger(n) && n >= min && n <= KITTY_UINT32_MAX;
1083
+ }
1084
+ function kittyControlIsInt32(controls, key) {
1085
+ let value = controls.get(key);
1086
+ if (value == null)
1087
+ return !0;
1088
+ if (!/^-?\d+$/.test(value))
1089
+ return !1;
1090
+ let n = Number(value);
1091
+ return Number.isSafeInteger(n) && n >= KITTY_INT32_MIN && n <= KITTY_INT32_MAX;
1092
+ }
1093
+ function kittyControlPositiveInt(controls, key, fallback) {
1094
+ let value = controls.get(key);
1095
+ if (value == null)
1096
+ return fallback;
1097
+ if (!/^\d+$/.test(value))
1098
+ return null;
1099
+ let n = Number(value);
1100
+ return Number.isSafeInteger(n) && n >= 1 ? n : null;
1101
+ }
1102
+ function kittyControlIsTerminalGraphicCellsBounded(controls) {
1103
+ let columns = kittyControlPositiveInt(controls, "c", 1), rows = kittyControlPositiveInt(controls, "r", 1);
1104
+ return columns != null && rows != null && columns * rows <= MAX_TERMINAL_GRAPHIC_CELLS;
1105
+ }
1106
+ function validateKittySharedSafeControls(controls) {
1107
+ let q = controls.get("q");
1108
+ if (q != null && !/^[0-2]$/.test(q))
1109
+ return !1;
1110
+ let cursorMove = controls.get("C");
1111
+ if (cursorMove != null && !/^[01]$/.test(cursorMove))
1112
+ return !1;
1113
+ for (let key of ["i", "I", "p"])
1114
+ if (!kittyControlIsUint32(controls, key))
1115
+ return !1;
1116
+ for (let key of ["c", "r"])
1117
+ if (!kittyControlIsUint32(controls, key, 1))
1118
+ return !1;
1119
+ if (!kittyControlIsTerminalGraphicCellsBounded(controls))
1120
+ return !1;
1121
+ for (let key of ["x", "y"])
1122
+ if (!kittyControlIsUint32(controls, key))
1123
+ return !1;
1124
+ for (let key of ["w", "h"])
1125
+ if (!kittyControlIsUint32(controls, key, 1))
1126
+ return !1;
1127
+ if (!kittyControlIsInt32(controls, "z"))
1128
+ return !1;
1129
+ let transmissionMedium = controls.get("t");
1130
+ return !(transmissionMedium != null && transmissionMedium !== "d");
1131
+ }
1132
+ function validateKittySequence(sequence, op = "draw") {
1133
+ let packets = parseKittyPackets(sequence);
1134
+ if (!packets)
1135
+ return !1;
1136
+ if (op === "clear") {
1137
+ if (packets.length !== 1)
1138
+ return !1;
1139
+ let packet = packets[0];
1140
+ if (!kittyControlsUseOnly(packet.controls, KITTY_CLEAR_CONTROL_KEYS) || !validateKittySharedSafeControls(packet.controls) || packet.payload || packet.controls.get("a") !== "d")
1141
+ return !1;
1142
+ let d = packet.controls.get("d");
1143
+ return d == null || /^[aAcCiI]$/.test(d);
1144
+ }
1145
+ let first = packets[0];
1146
+ if (!kittyControlsUseOnly(first.controls, KITTY_DRAW_FIRST_CONTROL_KEYS) || !validateKittySharedSafeControls(first.controls))
1147
+ return !1;
1148
+ if (first.controls.get("a") === "p")
1149
+ return !(packets.length !== 1 || first.payload || !first.controls.has("i") && !first.controls.has("I"));
1150
+ if (first.controls.get("a") !== "T" || !first.payload)
1151
+ return !1;
1152
+ let f = first.controls.get("f");
1153
+ if (f != null && f !== "24" && f !== "32" && f !== "100")
1154
+ return !1;
1155
+ let firstMore = first.controls.get("m");
1156
+ if (firstMore != null && firstMore !== "0" && firstMore !== "1" || packets.length > 1 && firstMore !== "1")
1157
+ return !1;
1158
+ for (let i = 1; i < packets.length; i++) {
1159
+ let packet = packets[i];
1160
+ if (!kittyControlsUseOnly(packet.controls, KITTY_DRAW_CONTINUATION_CONTROL_KEYS) || !validateKittySharedSafeControls(packet.controls))
1161
+ return !1;
1162
+ let action = packet.controls.get("a");
1163
+ if (action != null && action !== "T")
1164
+ return !1;
1165
+ let m = packet.controls.get("m");
1166
+ if (m !== "0" && m !== "1" || !packet.payload && !(i === packets.length - 1 && m === "0"))
1167
+ return !1;
1168
+ }
1169
+ return !(packets.length > 1 && packets[packets.length - 1].controls.get("m") === "1");
1170
+ }
1171
+ function validateIterm2Dimension(value) {
1172
+ return /^auto$/i.test(value) || /^(?:[1-9]\d{0,4})(?:px|%)?$/.test(value);
1173
+ }
1174
+ function validateIterm2Params(params) {
1175
+ let seen = /* @__PURE__ */ new Set(), inline = !1;
1176
+ for (let part of params.split(";").filter(Boolean)) {
1177
+ let eq = part.indexOf("=");
1178
+ if (eq <= 0)
1179
+ return !1;
1180
+ let key = part.slice(0, eq), value = part.slice(eq + 1);
1181
+ if (seen.has(key))
1182
+ return !1;
1183
+ switch (seen.add(key), key) {
1184
+ case "inline":
1185
+ if (value !== "1")
1186
+ return !1;
1187
+ inline = !0;
1188
+ break;
1189
+ case "width":
1190
+ case "height":
1191
+ if (!validateIterm2Dimension(value))
1192
+ return !1;
1193
+ break;
1194
+ case "preserveAspectRatio":
1195
+ case "doNotMoveCursor":
1196
+ if (!/^[01]$/.test(value))
1197
+ return !1;
1198
+ break;
1199
+ default:
1200
+ return !1;
1201
+ }
1202
+ }
1203
+ return inline;
1204
+ }
1205
+ function validateIterm2Sequence(sequence, op = "draw") {
1206
+ if (op === "clear")
1207
+ return !1;
1208
+ let index = 0;
1209
+ for (; index < sequence.length; ) {
1210
+ let prefix = `${ESC}]1337;File=`;
1211
+ if (!sequence.startsWith(prefix, index))
1212
+ return !1;
1213
+ let belEnd = sequence.indexOf(BEL, index + prefix.length), stEnd = sequence.indexOf(ST, index + prefix.length), end = belEnd >= 0 && stEnd >= 0 ? Math.min(belEnd, stEnd) : belEnd >= 0 ? belEnd : stEnd;
1214
+ if (end < 0)
1215
+ return !1;
1216
+ let body = sequence.slice(index + `${ESC}]1337;`.length, end);
1217
+ if (!body.startsWith("File=") || !withoutNestedEscapes(body))
1218
+ return !1;
1219
+ let colon = body.indexOf(":");
1220
+ if (colon < 0)
1221
+ return !1;
1222
+ let params = body.slice(5, colon), payload = body.slice(colon + 1);
1223
+ if (!/^[A-Za-z0-9_=;,.%+\-:]*$/.test(params) || !payload || !isBase64ish(payload) || !validateIterm2Params(params))
1224
+ return !1;
1225
+ index = end + (end === stEnd ? ST.length : BEL.length);
1226
+ }
1227
+ return sequence.length > 0;
1228
+ }
1229
+ function validateSixelSequence(sequence, op = "draw") {
1230
+ if (op === "clear")
1231
+ return !1;
1232
+ let index = 0;
1233
+ for (; index < sequence.length; ) {
1234
+ if (!sequence.startsWith(`${ESC}P`, index))
1235
+ return !1;
1236
+ let end = sequence.indexOf(ST, index + 2);
1237
+ if (end < 0)
1238
+ return !1;
1239
+ let body = sequence.slice(index + 2, end);
1240
+ if (!withoutNestedEscapes(body))
1241
+ return !1;
1242
+ for (let i = 0; i < body.length; i++) {
1243
+ let code = body.charCodeAt(i);
1244
+ if (code < 32 || code > 126)
1245
+ return !1;
1246
+ }
1247
+ let q = body.indexOf("q");
1248
+ if (q < 0 || q > 32)
1249
+ return !1;
1250
+ let introducer = body.slice(0, q);
1251
+ if (!/^[0-9;?]*$/.test(introducer) || !body.slice(q + 1).length)
1252
+ return !1;
1253
+ index = end + ST.length;
1254
+ }
1255
+ return sequence.length > 0;
1256
+ }
1257
+ function stripTerminalControlChars(value) {
1258
+ let out = "";
1259
+ for (let index = 0; index < value.length; index++) {
1260
+ let code = value.charCodeAt(index);
1261
+ code <= 8 || code === 11 || code === 12 || code >= 14 && code <= 31 || code === 127 || code >= 128 && code <= 159 || (out += value[index]);
1262
+ }
1263
+ return out;
1264
+ }
1265
+ function sanitizeTerminalFallbackText(text) {
1266
+ return stripTerminalControlChars(
1267
+ String(text ?? "").replace(OSC_RE, "").replace(CSI_RE, "").replace(DCS_RE, "").replace(APC_RE, "").replace(C1_OSC_RE, "").replace(C1_CSI_RE, "").replace(C1_DCS_RE, "").replace(C1_APC_RE, "")
1268
+ ).slice(0, MAX_TERMINAL_GRAPHICS_FALLBACK_CHARS);
1269
+ }
1270
+ function isSafeTerminalGraphicsSequence(sequence, protocol, op = "draw") {
1271
+ return !isTerminalGraphicsProtocol(protocol) || !sequence || sequence.length > MAX_TERMINAL_GRAPHICS_SEQUENCE_CHARS ? !1 : protocol === "kitty" ? validateKittySequence(sequence, op) : protocol === "iterm2" ? validateIterm2Sequence(sequence, op) : validateSixelSequence(sequence, op);
1272
+ }
1273
+ function uint32Control(key, value, min = 0) {
1274
+ if (value == null)
1275
+ return "";
1276
+ let n = Math.floor(value);
1277
+ return Number.isSafeInteger(n) && n >= min && n <= KITTY_UINT32_MAX ? `${key}=${n}` : "";
1278
+ }
1279
+ function int32Control(key, value) {
1280
+ if (value == null)
1281
+ return "";
1282
+ let n = Math.floor(value);
1283
+ return Number.isSafeInteger(n) && n >= KITTY_INT32_MIN && n <= KITTY_INT32_MAX ? `${key}=${n}` : "";
1284
+ }
1285
+ function sanitizeBase64(value) {
1286
+ let data = String(value ?? "").replace(/\s+/g, "");
1287
+ return isBase64ish(data) ? data : "";
1288
+ }
1289
+ function kittyGraphicCellControls(columns, rows) {
1290
+ if (columns == null && rows == null)
1291
+ return [];
1292
+ let size = normalizeTerminalGraphicSize(columns ?? 1, rows ?? 1);
1293
+ return size ? [columns == null ? "" : `c=${size.width}`, rows == null ? "" : `r=${size.height}`] : [];
1294
+ }
1295
+ function kittyGraphicSourceControls(sourceX, sourceY, sourceWidth, sourceHeight) {
1296
+ return [
1297
+ uint32Control("x", sourceX),
1298
+ uint32Control("y", sourceY),
1299
+ uint32Control("w", sourceWidth, 1),
1300
+ uint32Control("h", sourceHeight, 1)
1301
+ ];
1302
+ }
1303
+ function chunkBase64(value, chunkSize) {
1304
+ let normalizedSize = Math.max(4, Math.floor(chunkSize / 4) * 4), chunks = [];
1305
+ for (let index = 0; index < value.length; index += normalizedSize)
1306
+ chunks.push(value.slice(index, index + normalizedSize));
1307
+ return chunks.length ? chunks : [""];
1308
+ }
1309
+ function createKittyPlacementSequence(options) {
1310
+ let imageId = uint32Control("i", options.imageId), imageNumber = uint32Control("I", options.imageNumber);
1311
+ if (!imageId && !imageNumber)
1312
+ return "";
1313
+ let controls = [
1314
+ "a=p",
1315
+ options.quiet === !1 ? "" : "q=2",
1316
+ options.noCursorMove === !1 ? "" : "C=1",
1317
+ imageId,
1318
+ imageNumber,
1319
+ uint32Control("p", options.placementId),
1320
+ ...kittyGraphicCellControls(options.columns, options.rows),
1321
+ ...kittyGraphicSourceControls(
1322
+ options.sourceX,
1323
+ options.sourceY,
1324
+ options.sourceWidth,
1325
+ options.sourceHeight
1326
+ ),
1327
+ int32Control("z", options.zIndex)
1328
+ ].filter(Boolean);
1329
+ return `${ESC}_G${controls.join(",")}${ST}`;
1330
+ }
1331
+ function createKittyGraphicsSequence(base64Png, options = {}) {
1332
+ let data = sanitizeBase64(base64Png);
1333
+ if (!data)
1334
+ return "";
1335
+ let chunks = chunkBase64(data, options.chunkSize ?? 4096), baseControls = [
1336
+ "a=T",
1337
+ "f=100",
1338
+ options.quiet === !1 ? "" : "q=2",
1339
+ options.noCursorMove === !1 ? "" : "C=1",
1340
+ uint32Control("i", options.imageId),
1341
+ uint32Control("I", options.imageNumber),
1342
+ uint32Control("p", options.placementId),
1343
+ ...kittyGraphicCellControls(options.columns, options.rows),
1344
+ ...kittyGraphicSourceControls(
1345
+ options.sourceX,
1346
+ options.sourceY,
1347
+ options.sourceWidth,
1348
+ options.sourceHeight
1349
+ ),
1350
+ int32Control("z", options.zIndex)
1351
+ ].filter(Boolean);
1352
+ return chunks.map((chunk, index) => {
1353
+ let last = index === chunks.length - 1, controls = index === 0 ? [...baseControls, chunks.length > 1 ? `m=${last ? 0 : 1}` : ""] : [options.quiet === !1 ? "" : "q=2", `m=${last ? 0 : 1}`].filter(Boolean);
1354
+ return `${ESC}_G${controls.filter(Boolean).join(",")};${chunk}${ST}`;
1355
+ }).join("");
1356
+ }
1357
+ function createKittyDeleteGraphicsSequence(options = {}) {
1358
+ let controls = ["a=d"];
1359
+ if (options.allVisible)
1360
+ controls.push(`d=${options.freeImageData ? "A" : "a"}`);
1361
+ else if (options.imageId != null) {
1362
+ let imageId = uint32Control("i", options.imageId), placementId = uint32Control("p", options.placementId);
1363
+ if (!imageId || options.placementId != null && !placementId)
1364
+ return "";
1365
+ controls.push(`d=${options.freeImageData ? "I" : "i"}`), controls.push(imageId), controls.push(placementId);
1366
+ } else if (options.currentCell)
1367
+ controls.push(`d=${options.freeImageData ? "C" : "c"}`);
1368
+ else
1369
+ return "";
1370
+ return options.quiet !== !1 && controls.push("q=2"), `${ESC}_G${controls.filter(Boolean).join(",")}${ST}`;
1371
+ }
1372
+ function createIterm2InlineImageSequence(base64Data, options = {}) {
1373
+ let data = sanitizeBase64(base64Data);
1374
+ if (!data)
1375
+ return "";
1376
+ let params = [
1377
+ "inline=1",
1378
+ options.width != null ? `width=${formatItermDimension(options.width)}` : "",
1379
+ options.height != null ? `height=${formatItermDimension(options.height)}` : "",
1380
+ `preserveAspectRatio=${options.preserveAspectRatio === !1 ? 0 : 1}`,
1381
+ options.doNotMoveCursor === !1 ? "" : "doNotMoveCursor=1"
1382
+ ].filter(Boolean);
1383
+ return `${ESC}]1337;File=${params.join(";")}:${data}${BEL}`;
1384
+ }
1385
+ function formatItermDimension(value) {
1386
+ if (typeof value == "number") {
1387
+ let n = Math.floor(value);
1388
+ return Number.isFinite(n) ? String(Math.min(99999, Math.max(1, n))) : "auto";
1389
+ }
1390
+ let raw = String(value ?? "").trim();
1391
+ return validateIterm2Dimension(raw) ? raw : "auto";
1392
+ }
1393
+ function resolveKittyPngSourceCrop(rect, fullRect, sourceWidth, sourceHeight) {
1394
+ if (fullRect.w <= 0 || fullRect.h <= 0)
1395
+ return null;
1396
+ let offsetX = Math.max(0, rect.x - fullRect.x), offsetY = Math.max(0, rect.y - fullRect.y), visibleW = Math.max(0, Math.min(rect.w, fullRect.w - offsetX)), visibleH = Math.max(0, Math.min(rect.h, fullRect.h - offsetY));
1397
+ if (offsetX <= 0 && offsetY <= 0 && visibleW >= fullRect.w && visibleH >= fullRect.h)
1398
+ return null;
1399
+ let sourceX = Math.max(
1400
+ 0,
1401
+ Math.min(sourceWidth - 1, Math.floor(offsetX * sourceWidth / fullRect.w))
1402
+ ), sourceY = Math.max(
1403
+ 0,
1404
+ Math.min(sourceHeight - 1, Math.floor(offsetY * sourceHeight / fullRect.h))
1405
+ ), sourceRight = Math.max(
1406
+ sourceX + 1,
1407
+ Math.min(sourceWidth, Math.ceil((offsetX + visibleW) * sourceWidth / fullRect.w))
1408
+ ), sourceBottom = Math.max(
1409
+ sourceY + 1,
1410
+ Math.min(sourceHeight, Math.ceil((offsetY + visibleH) * sourceHeight / fullRect.h))
1411
+ );
1412
+ return {
1413
+ sourceX,
1414
+ sourceY,
1415
+ sourceWidth: sourceRight - sourceX,
1416
+ sourceHeight: sourceBottom - sourceY
1417
+ };
1418
+ }
1419
+ function createTerminalGraphicPngSequence(options) {
1420
+ if (options.protocol === "kitty") {
1421
+ let placement = {
1422
+ columns: options.placementColumns,
1423
+ rows: options.placementRows
1424
+ };
1425
+ if (options.rect && options.fullRect && options.sourceWidth && options.sourceHeight) {
1426
+ let crop = resolveKittyPngSourceCrop(
1427
+ options.rect,
1428
+ options.fullRect,
1429
+ options.sourceWidth,
1430
+ options.sourceHeight
1431
+ );
1432
+ crop && (placement = { ...placement, ...crop });
1433
+ }
1434
+ let transmissionPlacement = options.cropTransmission !== !1 ? placement : {
1435
+ columns: options.transmissionColumns ?? options.placementColumns,
1436
+ rows: options.transmissionRows ?? options.placementRows
1437
+ };
1438
+ return {
1439
+ type: "sequence",
1440
+ protocol: "kitty",
1441
+ sequence: createKittyGraphicsSequence(options.base64, {
1442
+ imageId: options.imageId,
1443
+ placementId: options.placementId,
1444
+ zIndex: options.zIndex,
1445
+ ...transmissionPlacement
1446
+ }),
1447
+ resizeSequence: createKittyPlacementSequence({
1448
+ imageId: options.imageId,
1449
+ placementId: options.placementId,
1450
+ zIndex: options.zIndex,
1451
+ ...placement
1452
+ }),
1453
+ clearSequence: createKittyDeleteGraphicsSequence({
1454
+ imageId: options.imageId,
1455
+ placementId: options.placementId,
1456
+ freeImageData: options.freeImageData
1457
+ }),
1458
+ ...options.fallback != null ? { fallback: options.fallback } : {},
1459
+ ...options.cols != null ? { cols: options.cols } : {},
1460
+ ...options.rows != null ? { rows: options.rows } : {},
1461
+ ...options.sourceWidth != null ? { sourceWidth: options.sourceWidth } : {},
1462
+ ...options.sourceHeight != null ? { sourceHeight: options.sourceHeight } : {},
1463
+ ...options.zIndex != null ? { zIndex: options.zIndex } : {}
1464
+ };
1465
+ }
1466
+ return options.protocol === "iterm2" ? {
1467
+ type: "sequence",
1468
+ protocol: "iterm2",
1469
+ sequence: createIterm2InlineImageSequence(options.base64, {
1470
+ width: options.cols,
1471
+ height: options.rows,
1472
+ preserveAspectRatio: !0,
1473
+ doNotMoveCursor: !0
1474
+ }),
1475
+ ...options.fallback != null ? { fallback: options.fallback } : {},
1476
+ ...options.cols != null ? { cols: options.cols } : {},
1477
+ ...options.rows != null ? { rows: options.rows } : {},
1478
+ ...options.sourceWidth != null ? { sourceWidth: options.sourceWidth } : {},
1479
+ ...options.sourceHeight != null ? { sourceHeight: options.sourceHeight } : {}
1480
+ } : null;
1481
+ }
1482
+
1483
+ // src/vue/scheduler/frame-mailbox.ts
1484
+ var EMPTY = Symbol("frame-mailbox-empty");
1485
+ function createFrameMailbox(options) {
1486
+ let disposed = !1, hasPending = !1, pending = EMPTY, queued = 0, pendingTaskId = null;
1487
+ function clearPending() {
1488
+ hasPending = !1, pending = EMPTY, queued = 0, pendingTaskId = null;
1489
+ }
1490
+ function currentTaskId() {
1491
+ if (pendingTaskId)
1492
+ return pendingTaskId;
1493
+ let id = typeof options.id == "function" ? options.id() : options.id;
1494
+ if (!id)
1495
+ throw new Error("createFrameMailbox requires a non-empty task id");
1496
+ return pendingTaskId = id, pendingTaskId;
1497
+ }
1498
+ function queue(value) {
1499
+ if (disposed)
1500
+ return !1;
1501
+ let wasPending = hasPending, taskId = wasPending ? pendingTaskId : currentTaskId(), nextPending;
1502
+ try {
1503
+ nextPending = hasPending && options.merge ? options.merge(pending, value) : value;
1504
+ } catch (error) {
1505
+ throw clearPending(), wasPending && options.scheduler.cancelFrameTask?.(taskId), error;
1506
+ }
1507
+ if (pending = nextPending, hasPending = !0, queued++, wasPending)
1508
+ return !0;
1509
+ let accepted;
1510
+ try {
1511
+ accepted = options.scheduler.queueFrameTask({
1512
+ id: taskId,
1513
+ reason: options.reason,
1514
+ priority: options.priority,
1515
+ sync: options.sync,
1516
+ run(ctx) {
1517
+ if (disposed || !hasPending)
1518
+ return;
1519
+ let value2 = pending, count = queued, dropped = Math.max(0, count - 1);
1520
+ clearPending(), ctx.reportMailboxDeliveryAttempt?.({
1521
+ id: taskId,
1522
+ queued: count,
1523
+ dropped
1524
+ }), options.apply(value2, ctx, {
1525
+ queued: count,
1526
+ dropped
1527
+ }), ctx.reportDroppedUpdates?.(dropped);
1528
+ }
1529
+ });
1530
+ } catch (error) {
1531
+ throw clearPending(), error;
1532
+ }
1533
+ return accepted === !1 ? (clearPending(), !1) : !0;
1534
+ }
1535
+ function replacePending(value) {
1536
+ return disposed ? !1 : hasPending ? (pending = value, !0) : queue(value);
1537
+ }
1538
+ function cancel() {
1539
+ let taskId = pendingTaskId;
1540
+ clearPending(), taskId && options.scheduler.cancelFrameTask?.(taskId);
1541
+ }
1542
+ function dispose() {
1543
+ cancel(), disposed = !0;
1544
+ }
1545
+ return {
1546
+ queue,
1547
+ replacePending,
1548
+ cancel,
1549
+ dispose,
1550
+ hasPending: () => hasPending,
1551
+ // Ambiguous when T includes undefined. Pair with hasPending() to
1552
+ // distinguish "pending undefined" from "no pending value".
1553
+ peek: () => hasPending ? pending : void 0
1554
+ };
1555
+ }
1556
+
1557
+ // src/vue/components/TAgentTerminalGraphic.ts
1558
+ var import_vue8 = require("vue");
1559
+
1560
+ // src/vue/composables/use-render-node.ts
1561
+ var import_vue7 = require("vue");
1562
+
1563
+ // src/vue/composables/use-render-stack.ts
1564
+ var import_vue6 = require("vue");
1565
+
1566
+ // src/vue/render/context.ts
1567
+ var RenderStackKey = injectionKey("RenderStack");
1568
+
1569
+ // src/vue/composables/use-render-stack.ts
1570
+ function useRenderStack() {
1571
+ let stack = (0, import_vue6.inject)(RenderStackKey, null);
1572
+ if (!stack)
1573
+ throw new Error("RenderStack is missing");
1574
+ return stack;
1575
+ }
1576
+
1577
+ // src/vue/composables/use-render-node.ts
1578
+ var pendingInvalidateByScheduler = /* @__PURE__ */ new WeakMap();
1579
+ function mergePriority(prev, next) {
1580
+ return prev === "high" || next === "high" ? "high" : prev === "normal" || next === "normal" ? "normal" : "low";
1581
+ }
1582
+ function requestBatchedInvalidate(scheduler, plane, priority) {
1583
+ let state = pendingInvalidateByScheduler.get(scheduler);
1584
+ if (state || (state = { queued: !1, plane: null, priority: "low" }, pendingInvalidateByScheduler.set(scheduler, state)), state.queued) {
1585
+ state.plane !== null && state.plane !== plane && (state.plane = null), state.priority = mergePriority(state.priority, priority);
1586
+ return;
1587
+ }
1588
+ state.plane = plane, state.priority = priority, state.queued = !0, queueMicrotask(() => {
1589
+ state.queued = !1;
1590
+ let queuedPlane = state.plane, queuedPriority = state.priority;
1591
+ state.plane = null, state.priority = "low", scheduler.invalidate({
1592
+ plane: queuedPlane ?? void 0,
1593
+ priority: queuedPriority
1594
+ });
1595
+ });
1596
+ }
1597
+ function sameRenderRect(a, b) {
1598
+ return a === b ? !0 : !a || !b ? !1 : a.x === b.x && a.y === b.y && a.w === b.w && a.h === b.h;
1599
+ }
1600
+ function sameDeps(a, b) {
1601
+ if (Object.is(a, b))
1602
+ return !0;
1603
+ if (!Array.isArray(a) || !Array.isArray(b) || a.length !== b.length)
1604
+ return !1;
1605
+ for (let i = 0; i < a.length; i++)
1606
+ if (!Object.is(a[i], b[i]))
1607
+ return !1;
1608
+ return !0;
1609
+ }
1610
+ function useRenderNode(getOptions) {
1611
+ let { scheduler, render, widthProvider } = useTerminal(), parentStack = useRenderStack(), plane = (0, import_vue7.inject)(RenderPlaneContextKey, (0, import_vue7.ref)("default")), id = (0, import_vue7.ref)(null), lastPlane = (0, import_vue7.ref)(plane.value), lastStack = null, lastZIndex = 0, lastHasRect = !1, lastRect = null, lastDeps, lastHasDeps = !1, options = (0, import_vue7.computed)(() => withTextWidthProvider(widthProvider, getOptions)), stop = (0, import_vue7.watchEffect)(
1612
+ () => {
1613
+ let opt = options.value;
1614
+ opt.deps;
1615
+ let stack = opt.stack ?? parentStack.value, nextPlane = plane.value, hasRect = Object.prototype.hasOwnProperty.call(opt, "rect"), nextRect = hasRect ? opt.rect ?? null : null, nextZIndex = opt.zIndex ?? 0, hasDeps = Object.prototype.hasOwnProperty.call(opt, "deps");
1616
+ if (!stack)
1617
+ return;
1618
+ if (!id.value) {
1619
+ let node = render.register({
1620
+ stack,
1621
+ zIndex: nextZIndex,
1622
+ rect: hasRect ? nextRect : void 0,
1623
+ plane: nextPlane,
1624
+ paint: opt.paint
1625
+ });
1626
+ id.value = node.id, lastPlane.value = nextPlane, lastStack = stack, lastZIndex = nextZIndex, lastHasRect = hasRect, lastRect = nextRect, lastHasDeps = hasDeps, lastDeps = opt.deps, requestBatchedInvalidate(scheduler, nextPlane, opt.priority ?? "normal");
1627
+ return;
1628
+ }
1629
+ let prevPlane = lastPlane.value;
1630
+ if (hasDeps && lastHasDeps && !opt.dirtyRowsHint?.length && lastStack === stack && lastZIndex === nextZIndex && prevPlane === nextPlane && lastHasRect === hasRect && (!hasRect || sameRenderRect(lastRect, nextRect)) && sameDeps(lastDeps, opt.deps))
1631
+ return;
1632
+ let updatePayload = {
1633
+ stack,
1634
+ zIndex: nextZIndex,
1635
+ dirtyRowsHint: opt.dirtyRowsHint,
1636
+ plane: nextPlane,
1637
+ paint: opt.paint
1638
+ };
1639
+ hasRect && (updatePayload.rect = nextRect), render.update(id.value, updatePayload), lastPlane.value = nextPlane, lastStack = stack, lastZIndex = nextZIndex, lastHasRect = hasRect, lastRect = nextRect, lastHasDeps = hasDeps, lastDeps = opt.deps;
1640
+ let priority = opt.priority ?? "normal";
1641
+ requestBatchedInvalidate(scheduler, prevPlane, priority), prevPlane !== nextPlane && requestBatchedInvalidate(scheduler, nextPlane, priority);
1642
+ },
1643
+ { flush: "sync" }
1644
+ );
1645
+ return (0, import_vue7.onBeforeUnmount)(() => {
1646
+ stop(), id.value && (render.unregister(id.value), requestBatchedInvalidate(scheduler, lastPlane.value, "normal"));
1647
+ }), { id };
1648
+ }
1649
+
1650
+ // src/vue/components/TAgentTerminalGraphic.ts
1651
+ var NO_GRAPHICS_CAPABILITIES = Object.freeze({
1652
+ supported: !1,
1653
+ kitty: !1,
1654
+ iterm2: !1,
1655
+ sixel: !1,
1656
+ preferredProtocol: null,
1657
+ protocol: "unicode",
1658
+ candidates: [],
1659
+ stdoutIsTTY: !1,
1660
+ insideTmux: !1,
1661
+ insideScreen: !1,
1662
+ insideZellij: !1,
1663
+ multiplexer: null,
1664
+ passthrough: !1,
1665
+ forced: !1,
1666
+ reason: "no-terminal-graphics-output"
1667
+ });
1668
+ function splitTextOutput(value) {
1669
+ let lines = sanitizeTextBlock(sanitizeTerminalFallbackText(value).replace(/\r\n?/g, `
1670
+ `)).split(`
1671
+ `);
1672
+ return lines.length ? lines : [""];
1673
+ }
1674
+ function hasVisibleOutput(value) {
1675
+ return value.some((line) => line.trim().length > 0);
1676
+ }
1677
+ function errorMessage(error) {
1678
+ return error instanceof Error ? error.message : String(error);
1679
+ }
1680
+ function positiveInt(value) {
1681
+ let n = Math.floor(Number(value));
1682
+ return Number.isFinite(n) && n > 0 ? n : void 0;
1683
+ }
1684
+ function finiteInt(value) {
1685
+ let n = Math.floor(Number(value));
1686
+ return Number.isFinite(n) ? n : void 0;
1687
+ }
1688
+ function clampNumber(value, min, max) {
1689
+ return Math.max(min, Math.min(max, value));
1690
+ }
1691
+ function rectArea(rect) {
1692
+ return Math.max(0, rect.w) * Math.max(0, rect.h);
1693
+ }
1694
+ function sameRect(a, b) {
1695
+ return a.x === b.x && a.y === b.y && a.w === b.w && a.h === b.h;
1696
+ }
1697
+ function subtractRect(rect, cover) {
1698
+ let hit = intersectRect(rect, cover);
1699
+ if (!hit)
1700
+ return [rect];
1701
+ let out = [], rectRight = rect.x + rect.w, rectBottom = rect.y + rect.h, hitRight = hit.x + hit.w, hitBottom = hit.y + hit.h;
1702
+ return hit.y > rect.y && out.push({ x: rect.x, y: rect.y, w: rect.w, h: hit.y - rect.y }), hitBottom < rectBottom && out.push({ x: rect.x, y: hitBottom, w: rect.w, h: rectBottom - hitBottom }), hit.x > rect.x && out.push({ x: rect.x, y: hit.y, w: hit.x - rect.x, h: hit.h }), hitRight < rectRight && out.push({ x: hitRight, y: hit.y, w: rectRight - hitRight, h: hit.h }), out.filter((part) => part.w > 0 && part.h > 0);
1703
+ }
1704
+ function largestUncoveredRect(rect, covers) {
1705
+ let parts = [rect];
1706
+ for (let cover of covers)
1707
+ if (parts = parts.flatMap((part) => subtractRect(part, cover)), !parts.length)
1708
+ return null;
1709
+ return parts.sort((a, b) => rectArea(b) - rectArea(a) || a.y - b.y || a.x - b.x), parts[0] ?? null;
1710
+ }
1711
+ function parseKittyClearControls(sequence) {
1712
+ let prefix = "\x1B_G", terminator = "\x1B\\";
1713
+ if (!sequence.startsWith(prefix) || !sequence.endsWith(terminator))
1714
+ return null;
1715
+ let body = sequence.slice(prefix.length, -terminator.length);
1716
+ if (body.includes(terminator) || body.includes("\x1B") || body.includes("\x07"))
1717
+ return null;
1718
+ let semicolon = body.indexOf(";"), rawControls = semicolon >= 0 ? body.slice(0, semicolon) : body, controls = /* @__PURE__ */ new Map();
1719
+ for (let part of rawControls.split(",")) {
1720
+ let eq = part.indexOf("=");
1721
+ if (eq <= 0)
1722
+ return null;
1723
+ controls.set(part.slice(0, eq), part.slice(eq + 1));
1724
+ }
1725
+ return controls;
1726
+ }
1727
+ function kittyClearTargetsComponent(sequence, imageId, placementId) {
1728
+ let controls = parseKittyClearControls(sequence);
1729
+ if (!controls)
1730
+ return !1;
1731
+ let mode = controls.get("d");
1732
+ return mode !== "i" && mode !== "I" ? !1 : controls.get("i") === String(imageId) && controls.get("p") === String(placementId);
1733
+ }
1734
+ function isSafeComponentClearSequence(sequence, protocol, imageId, placementId) {
1735
+ return isSafeTerminalGraphicsSequence(sequence, protocol, "clear") ? protocol !== "kitty" || kittyClearTargetsComponent(sequence, imageId, placementId) : !1;
1736
+ }
1737
+ var textEncoder = null;
1738
+ function stringByteLength(value) {
1739
+ if (typeof TextEncoder < "u")
1740
+ return textEncoder ?? (textEncoder = new TextEncoder()), textEncoder.encode(value).length;
1741
+ let bytes = 0;
1742
+ for (let index = 0; index < value.length; index++) {
1743
+ let code = value.charCodeAt(index);
1744
+ code <= 127 ? bytes += 1 : code <= 2047 ? bytes += 2 : code >= 55296 && code <= 56319 && index + 1 < value.length ? (bytes += 4, index++) : bytes += 3;
1745
+ }
1746
+ return bytes;
1747
+ }
1748
+ function smallHash(input) {
1749
+ let hash = 2166136261;
1750
+ for (let i = 0; i < input.length; i++)
1751
+ hash ^= input.charCodeAt(i), hash = Math.imul(hash, 16777619);
1752
+ return (hash >>> 0).toString(36);
1753
+ }
1754
+ var tAgentTerminalGraphicProps = {
1755
+ x: { type: Number, required: !0 },
1756
+ y: { type: Number, required: !0 },
1757
+ w: { type: Number, required: !0 },
1758
+ h: { type: Number, default: void 0 },
1759
+ zIndex: { type: Number, default: 0 },
1760
+ content: { type: String, required: !0 },
1761
+ kind: {
1762
+ type: String,
1763
+ default: "image"
1764
+ },
1765
+ fallback: { type: String, default: void 0 },
1766
+ style: { type: Object, default: void 0 },
1767
+ loadingStyle: { type: Object, default: void 0 },
1768
+ errorStyle: { type: Object, default: void 0 },
1769
+ clear: { type: Boolean, default: !0 },
1770
+ final: { type: Boolean, default: !0 },
1771
+ streaming: { type: Boolean, default: !1 },
1772
+ renderer: {
1773
+ type: Function,
1774
+ default: void 0
1775
+ },
1776
+ loadingText: {
1777
+ type: String,
1778
+ default: "Rendering terminal graphic..."
1779
+ },
1780
+ deferRenderUntilVisible: { type: Boolean, default: !0 },
1781
+ suspendRawWhileScrolling: { type: Boolean, default: !0 },
1782
+ suspendRenderWhileScrolling: { type: Boolean, default: !0 },
1783
+ scrolling: { type: Boolean, default: !1 },
1784
+ scrollVersion: { type: Number, default: 0 },
1785
+ /** Advanced Kitty-only opt-in for moving an unchanged image via a reusable placement sequence. */
1786
+ placementMoveWithoutClear: { type: Boolean, default: !1 },
1787
+ preserveRawWhileRendering: { type: Boolean, default: !1 },
1788
+ suspended: { type: Boolean, default: !1 },
1789
+ retainRawWhileCovered: { type: Boolean, default: !1 },
1790
+ ignoreRawCoverage: { type: Boolean, default: !1 },
1791
+ ignoreSamePlaneRawCoverage: { type: Boolean, default: !1 },
1792
+ cacheKey: { type: String, default: void 0 },
1793
+ placementKey: { type: String, default: void 0 },
1794
+ trace: {
1795
+ type: Function,
1796
+ default: void 0
1797
+ }
1798
+ };
1799
+ function terminalDrawKey(current, rect, clearSequence, resizeSequence) {
1800
+ return [
1801
+ current.protocol,
1802
+ rect.x,
1803
+ rect.y,
1804
+ rect.w,
1805
+ rect.h,
1806
+ current.sequenceHash,
1807
+ clearSequence === current.clearSequence ? current.clearSequenceHash ?? "" : smallHash(clearSequence ?? ""),
1808
+ resizeSequence === current.resizeSequence ? current.resizeSequenceHash ?? "" : smallHash(resizeSequence ?? "")
1809
+ ].join(":");
1810
+ }
1811
+ var TAgentTerminalGraphic = (0, import_vue8.defineComponent)({
1812
+ name: "TAgentTerminalGraphic",
1813
+ props: tAgentTerminalGraphicProps,
1814
+ setup(props) {
1815
+ let instance = (0, import_vue8.getCurrentInstance)(), { terminal, defaultStyle, scheduler, widthProvider, render } = useTerminal(), layout = useLayout(), { visible, rootProps } = useVisibility(), graphicsActivity = (0, import_vue8.inject)(TerminalGraphicsActivityKey, null), status = (0, import_vue8.shallowRef)("idle"), error = (0, import_vue8.shallowRef)(""), graphic = (0, import_vue8.shallowRef)(null), documentVersion = (0, import_vue8.shallowRef)(0), builtOnce = !1, renderVersion = 0, renderAbort = null, alive = !0, lastRenderedContent = "", lastRenderRawVisible = !1, lastRenderProtocol = null, lastRenderGraphicsOutputVersion = 0, rawIdSeed = props.placementKey ? `placement:${props.placementKey}` : props.cacheKey ? `cache:${props.cacheKey}` : `instance:${instance?.uid ?? "unknown"}`, rawId = `TAgentTerminalGraphic:${smallHash(rawIdSeed)}`, frameTaskId = `${rawId}:render`, lastDrawnGraphic = (0, import_vue8.shallowRef)(null), rawClearPendingRepaint = (0, import_vue8.shallowRef)(null), rawDrawRejectedKey = (0, import_vue8.shallowRef)(null), reservedTerminalGraphicSize = (0, import_vue8.shallowRef)(null), terminalSizeVersion = (0, import_vue8.shallowRef)(0), renderNodeId = (0, import_vue8.shallowRef)(null), lastRawSkipScrollKey = "", lastDeferTraceKey = "", isParentScrolling = (0, import_vue8.computed)(
1816
+ () => props.scrolling || !!graphicsActivity?.scrolling.value
1817
+ ), graphicsActivityVersion = (0, import_vue8.computed)(
1818
+ () => (graphicsActivity?.version.value ?? 0) + Math.floor(Number(props.scrollVersion ?? 0))
1819
+ ), graphicsOutput = () => getTerminalGraphicsOutput(terminal), graphicsOutputVersion = (0, import_vue8.shallowRef)(getTerminalGraphicsOutputVersion(terminal)), unsubscribeGraphicsOutput = subscribeTerminalGraphicsOutput(terminal, () => {
1820
+ graphicsOutputVersion.value = getTerminalGraphicsOutputVersion(terminal);
1821
+ }), unsubscribeTerminalResize = terminal.on("resize", () => {
1822
+ terminalSizeVersion.value++;
1823
+ }), fallbackText = () => props.fallback ?? (props.kind === "math" ? props.content : ""), contentIdentity = (0, import_vue8.computed)(() => `${props.content.length}:${smallHash(props.content)}`), stableGraphicKey = (0, import_vue8.computed)(
1824
+ () => [
1825
+ rawIdSeed,
1826
+ props.cacheKey ?? "",
1827
+ props.kind,
1828
+ contentIdentity.value,
1829
+ props.w,
1830
+ props.h ?? "",
1831
+ props.final ? "final" : "draft"
1832
+ ].join("")
1833
+ ), imageId = (0, import_vue8.computed)(
1834
+ () => stableTerminalGraphicNumericId(`image:${stableGraphicKey.value}`)
1835
+ ), placementId = (0, import_vue8.computed)(
1836
+ () => stableTerminalGraphicNumericId(`placement:${stableGraphicKey.value}`)
1837
+ );
1838
+ function rememberTerminalGraphicSize(current) {
1839
+ if (current.type !== "terminal")
1840
+ return;
1841
+ let rows = positiveInt(current.rows);
1842
+ rows && (reservedTerminalGraphicSize.value = {
1843
+ key: stableGraphicKey.value,
1844
+ rows
1845
+ });
1846
+ }
1847
+ function bump() {
1848
+ documentVersion.value++;
1849
+ }
1850
+ function currentCapabilities() {
1851
+ return graphicsOutput()?.capabilities ?? NO_GRAPHICS_CAPABILITIES;
1852
+ }
1853
+ function trace(type, extra = {}) {
1854
+ let capabilities = currentCapabilities();
1855
+ try {
1856
+ props.trace?.({
1857
+ type,
1858
+ id: rawId,
1859
+ kind: props.kind,
1860
+ protocol: capabilities.protocol,
1861
+ contentHash: smallHash(props.content),
1862
+ ...extra
1863
+ });
1864
+ } catch {
1865
+ }
1866
+ let protocol = isTerminalGraphicsProtocol(capabilities.protocol) ? capabilities.protocol : void 0, key = props.cacheKey ?? smallHash(props.content);
1867
+ type === "render-start" ? recordTerminalGraphicTrace({ type: "renderer-start", id: rawId, key, protocol }) : type === "render-end" ? recordTerminalGraphicTrace({
1868
+ type: extra.reason ? "renderer-error" : "renderer-end",
1869
+ id: rawId,
1870
+ key,
1871
+ protocol,
1872
+ durationMs: extra.durationMs,
1873
+ bytes: extra.sequenceBytes,
1874
+ error: extra.reason
1875
+ }) : type === "defer" ? recordTerminalGraphicTrace({
1876
+ type: extra.reason === "scrolling" ? "skip-scrolling" : "skip-hidden",
1877
+ id: rawId,
1878
+ key,
1879
+ protocol,
1880
+ reason: extra.reason
1881
+ }) : type === "raw-draw" || (type === "render-abort" ? recordTerminalGraphicTrace({
1882
+ type: "renderer-abort",
1883
+ id: rawId,
1884
+ key,
1885
+ protocol,
1886
+ reason: extra.reason
1887
+ }) : type === "raw-clear" ? recordTerminalGraphicTrace({ type: "clear", id: rawId, key, protocol }) : type === "raw-skip-scroll" && recordTerminalGraphicTrace({
1888
+ type: "skip-scrolling",
1889
+ id: rawId,
1890
+ key,
1891
+ protocol,
1892
+ reason: extra.reason
1893
+ }));
1894
+ }
1895
+ function traceDeferOnce(reason) {
1896
+ let key = [reason, graphicsActivityVersion.value, stableGraphicKey.value].join(":");
1897
+ lastDeferTraceKey !== key && (lastDeferTraceKey = key, trace("defer", { reason }));
1898
+ }
1899
+ function abortCurrentRender(reason) {
1900
+ renderAbort && (renderAbort.abort(), renderAbort = null, trace("render-abort", { reason }));
1901
+ }
1902
+ function normalizeResult(result) {
1903
+ if (result == null)
1904
+ return {
1905
+ type: "text",
1906
+ text: fallbackText()
1907
+ };
1908
+ if (typeof result == "string")
1909
+ return {
1910
+ type: "text",
1911
+ text: result
1912
+ };
1913
+ if (typeof result != "object")
1914
+ return {
1915
+ type: "text",
1916
+ text: fallbackText()
1917
+ };
1918
+ if ("type" in result && result.type === "text")
1919
+ return {
1920
+ type: "text",
1921
+ text: result.text
1922
+ };
1923
+ let maybeRaw = result;
1924
+ if (!(maybeRaw.type === "sequence" || "sequence" in result || "protocol" in result) && "text" in result)
1925
+ return {
1926
+ type: "text",
1927
+ text: result.text
1928
+ };
1929
+ let sequence = typeof maybeRaw.sequence == "string" ? maybeRaw.sequence : "", protocol = isTerminalGraphicsProtocol(maybeRaw.protocol) ? maybeRaw.protocol : null, fallback = typeof maybeRaw.fallback == "string" ? sanitizeTerminalFallbackText(maybeRaw.fallback) : fallbackText(), fallbackFromProps = typeof maybeRaw.fallback != "string";
1930
+ if (!sequence || !protocol || !isSafeTerminalGraphicsSequence(sequence, protocol, "draw"))
1931
+ return {
1932
+ type: "text",
1933
+ text: fallback
1934
+ };
1935
+ let rawClear = typeof maybeRaw.clearSequence == "string" ? maybeRaw.clearSequence : void 0, clearSequence = rawClear && isSafeComponentClearSequence(rawClear, protocol, imageId.value, placementId.value) ? rawClear : void 0, rawResize = typeof maybeRaw.resizeSequence == "string" ? maybeRaw.resizeSequence : void 0, resizeSequence = rawResize && isSafeTerminalGraphicsSequence(rawResize, protocol, "draw") ? rawResize : void 0, declaredRows = positiveInt(maybeRaw.rows), declaredCols = positiveInt(maybeRaw.cols), sourceWidth = positiveInt(maybeRaw.sourceWidth), sourceHeight = positiveInt(maybeRaw.sourceHeight), zIndex = finiteInt(maybeRaw.zIndex), declaredSize = declaredRows == null ? null : normalizeTerminalGraphicSize(declaredCols ?? props.w, declaredRows);
1936
+ return {
1937
+ type: "terminal",
1938
+ protocol,
1939
+ sequence,
1940
+ sequenceHash: smallHash(sequence),
1941
+ sequenceBytes: stringByteLength(sequence),
1942
+ fallback,
1943
+ fallbackFromProps,
1944
+ clearSequence,
1945
+ clearSequenceHash: clearSequence ? smallHash(clearSequence) : void 0,
1946
+ resizeSequence,
1947
+ resizeSequenceHash: resizeSequence ? smallHash(resizeSequence) : void 0,
1948
+ cols: declaredRows == null ? declaredCols : declaredSize?.width,
1949
+ rows: declaredSize?.height,
1950
+ sourceWidth,
1951
+ sourceHeight,
1952
+ zIndex
1953
+ };
1954
+ }
1955
+ function defaultClearSequence(protocol) {
1956
+ return protocol === "kitty" ? createKittyDeleteGraphicsSequence({
1957
+ imageId: imageId.value,
1958
+ placementId: placementId.value
1959
+ }) : "";
1960
+ }
1961
+ function resolveClearSequence(current) {
1962
+ if (current.clearSequence)
1963
+ return current.clearSequence;
1964
+ let candidate = defaultClearSequence(current.protocol);
1965
+ if (candidate)
1966
+ return isSafeComponentClearSequence(
1967
+ candidate,
1968
+ current.protocol,
1969
+ imageId.value,
1970
+ placementId.value
1971
+ ) ? candidate : void 0;
1972
+ }
1973
+ function resolveResizeSequence(current, rect, full) {
1974
+ if (current.protocol !== "kitty")
1975
+ return current.resizeSequence;
1976
+ let sourceWidth = positiveInt(current.sourceWidth), sourceHeight = positiveInt(current.sourceHeight);
1977
+ if (!sourceWidth || !sourceHeight || full.w <= 0 || full.h <= 0)
1978
+ return current.resizeSequence;
1979
+ let offsetX = Math.max(0, rect.x - full.x), offsetY = Math.max(0, rect.y - full.y), visibleW = Math.max(0, Math.min(rect.w, full.w - offsetX)), visibleH = Math.max(0, Math.min(rect.h, full.h - offsetY)), x0 = clampNumber(Math.floor(offsetX * sourceWidth / full.w), 0, sourceWidth - 1), y0 = clampNumber(Math.floor(offsetY * sourceHeight / full.h), 0, sourceHeight - 1), x1 = Math.max(
1980
+ x0 + 1,
1981
+ clampNumber(Math.ceil((offsetX + visibleW) * sourceWidth / full.w), 1, sourceWidth)
1982
+ ), y1 = Math.max(
1983
+ y0 + 1,
1984
+ clampNumber(Math.ceil((offsetY + visibleH) * sourceHeight / full.h), 1, sourceHeight)
1985
+ );
1986
+ return createKittyPlacementSequence({
1987
+ imageId: imageId.value,
1988
+ placementId: placementId.value,
1989
+ columns: rect.w,
1990
+ rows: rect.h,
1991
+ sourceX: x0,
1992
+ sourceY: y0,
1993
+ sourceWidth: x1 - x0,
1994
+ sourceHeight: y1 - y0,
1995
+ zIndex: current.zIndex
1996
+ });
1997
+ }
1998
+ function queueClearLastGraphic(options = {}) {
1999
+ let previous = lastDrawnGraphic.value;
2000
+ if (!previous)
2001
+ return !1;
2002
+ let output = graphicsOutput(), accepted = !1;
2003
+ if (output?.clear && !previous.retainOnClear)
2004
+ try {
2005
+ accepted = !!output.clear(previous.id);
2006
+ } catch {
2007
+ accepted = !1;
2008
+ }
2009
+ if (!accepted && output && previous.clearSequence)
2010
+ try {
2011
+ accepted = output.queue({
2012
+ id: previous.id,
2013
+ x: previous.x,
2014
+ y: previous.y,
2015
+ w: previous.w,
2016
+ h: previous.h,
2017
+ protocol: previous.protocol,
2018
+ sequence: previous.clearSequence,
2019
+ deferFlush: !0,
2020
+ retainOnClear: previous.retainOnClear,
2021
+ op: "clear"
2022
+ });
2023
+ } catch {
2024
+ accepted = !1;
2025
+ }
2026
+ return accepted && ((options.markPendingRepaint ?? !0) && (rawClearPendingRepaint.value = previous), lastDrawnGraphic.value = null, trace("raw-clear", {
2027
+ x: previous.x,
2028
+ y: previous.y,
2029
+ w: previous.w,
2030
+ h: previous.h
2031
+ })), accepted;
2032
+ }
2033
+ function queueDrawGraphic(output, current, rect, full = rect, options = {}) {
2034
+ let clearSequence = resolveClearSequence(current), resizeSequence = resolveResizeSequence(current, rect, full), drawKey = terminalDrawKey(current, rect, clearSequence, resizeSequence), activePrevious = lastDrawnGraphic.value, retainedPrevious = rawClearPendingRepaint.value, previous = activePrevious ?? retainedPrevious, previousIsRetained = activePrevious == null && retainedPrevious != null, previousStillActive = previous ? typeof output.isActive == "function" ? output.isActive(previous.id) : !0 : !1, preservePreviousForAtomicReplace = props.preserveRawWhileRendering && activePrevious != null && !previousIsRetained && previousStillActive;
2035
+ if (!previousIsRetained && !options.force && previous?.drawKey === drawKey && previousStillActive)
2036
+ return !1;
2037
+ let canReusePlacementSequence = previousStillActive && previous?.protocol === current.protocol && previous.sequenceHash === current.sequenceHash && current.protocol === "kitty" && !!resizeSequence, scrollVersion = Math.floor(Number(props.scrollVersion ?? 0)), canMoveWithoutClear = canReusePlacementSequence && !!options.placementMoveWithoutClear;
2038
+ if (!previousIsRetained && previousStillActive && !resizeSequence && previous?.protocol === current.protocol && previous.sequenceHash === current.sequenceHash && previous.x === rect.x && previous.y === rect.y && rect.w <= previous.w && rect.h <= previous.h && (options.force || !sameRect(rect, full)))
2039
+ return lastDrawnGraphic.value = {
2040
+ ...previous,
2041
+ w: rect.w,
2042
+ h: rect.h,
2043
+ clearSequence,
2044
+ resizeSequence,
2045
+ drawKey,
2046
+ activityVersion: graphicsActivityVersion.value,
2047
+ scrollVersion
2048
+ }, lastRawSkipScrollKey = "", !1;
2049
+ if (previousStillActive && !previousIsRetained && !canReusePlacementSequence && !preservePreviousForAtomicReplace) {
2050
+ if (!queueClearLastGraphic({ markPendingRepaint: !1 }))
2051
+ return !1;
2052
+ } else
2053
+ previous && (previousStillActive || (lastDrawnGraphic.value = null, rawClearPendingRepaint.value = null));
2054
+ let accepted = !1;
2055
+ try {
2056
+ accepted = output.queue({
2057
+ id: rawId,
2058
+ x: rect.x,
2059
+ y: rect.y,
2060
+ w: rect.w,
2061
+ h: rect.h,
2062
+ protocol: current.protocol,
2063
+ sequence: canReusePlacementSequence && resizeSequence ? resizeSequence : current.sequence,
2064
+ resizeSequence,
2065
+ clearSequence,
2066
+ retainOnClear: !!(props.cacheKey && resizeSequence),
2067
+ resizeRedraw: canReusePlacementSequence,
2068
+ placementMoveWithoutClear: canMoveWithoutClear,
2069
+ allowTextOverlay: options.allowTextOverlay,
2070
+ forceDraw: options.force,
2071
+ deferFlush: options.deferFlush ?? !0,
2072
+ fallbackText: current.fallback
2073
+ });
2074
+ } catch {
2075
+ accepted = !1;
2076
+ }
2077
+ return accepted ? (rawDrawRejectedKey.value = null, rawClearPendingRepaint.value = null, lastDrawnGraphic.value = {
2078
+ id: rawId,
2079
+ x: rect.x,
2080
+ y: rect.y,
2081
+ w: rect.w,
2082
+ h: rect.h,
2083
+ protocol: current.protocol,
2084
+ sequenceHash: current.sequenceHash,
2085
+ clearSequence,
2086
+ resizeSequence,
2087
+ retainOnClear: !!(props.cacheKey && resizeSequence),
2088
+ allowTextOverlay: !!options.allowTextOverlay,
2089
+ drawKey,
2090
+ activityVersion: graphicsActivityVersion.value,
2091
+ scrollVersion
2092
+ }, lastRawSkipScrollKey = "", !0) : (preservePreviousForAtomicReplace ? (lastDrawnGraphic.value = activePrevious, queueClearLastGraphic({ markPendingRepaint: !1 })) : lastDrawnGraphic.value = null, rawDrawRejectedKey.value !== drawKey && (rawDrawRejectedKey.value = drawKey, scheduler.invalidate({ priority: "low", reason: "data" })), !1);
2093
+ }
2094
+ function hasRetainedActiveRawGraphic() {
2095
+ let output = graphicsOutput();
2096
+ return !!(status.value === "loading" && !graphic.value && output && typeof output.isActive == "function" && output.isActive(rawId));
2097
+ }
2098
+ let showingInitialLoadingText = (0, import_vue8.computed)(
2099
+ () => status.value === "loading" && !graphic.value && !hasRetainedActiveRawGraphic()
2100
+ ), fullRect = (0, import_vue8.computed)(() => {
2101
+ let current = graphic.value, reserved = reservedTerminalGraphicSize.value, reservedRows = current?.type === "terminal" ? void 0 : status.value === "idle" && reserved?.key === stableGraphicKey.value ? reserved.rows : void 0, textLines = current?.type === "text" ? splitTextOutput(current.text) : splitTextOutput(fallbackText()), height = props.h ?? (current?.type === "terminal" ? current.rows : void 0) ?? reservedRows ?? Math.max(1, textLines.length);
2102
+ return translateRect(
2103
+ { x: props.x, y: props.y, w: props.w, h: height },
2104
+ layout.originX,
2105
+ layout.originY
2106
+ );
2107
+ }), absRect = (0, import_vue8.computed)(() => {
2108
+ terminalSizeVersion.value;
2109
+ let translated = fullRect.value, size = terminal.size(), terminalClip = {
2110
+ x: 0,
2111
+ y: 0,
2112
+ w: Math.max(0, Math.floor(size.cols)),
2113
+ h: Math.max(0, Math.floor(size.rows))
2114
+ }, clip = layout.clipRect ? intersectRect(layout.clipRect, terminalClip) : terminalClip;
2115
+ return clip ? intersectRect(translated, clip) ?? { x: 0, y: 0, w: 0, h: 0 } : { x: 0, y: 0, w: 0, h: 0 };
2116
+ }), renderRect = (0, import_vue8.computed)(() => absRect.value);
2117
+ function rawRectFitsTerminalViewport(rect) {
2118
+ return canDrawTerminalGraphicRect(rect, terminal.size());
2119
+ }
2120
+ function rawCoveredByHigherRenderNode(rect = fullRect.value) {
2121
+ if (props.retainRawWhileCovered)
2122
+ return !1;
2123
+ let id = renderNodeId.value;
2124
+ return !props.ignoreRawCoverage && id != null && render.isRectCoveredByHigherNode(id, rect, {
2125
+ ignoreSamePlane: props.ignoreSamePlaneRawCoverage
2126
+ });
2127
+ }
2128
+ function retainedRawCoveredByHigherRenderNode(rect) {
2129
+ if (!props.retainRawWhileCovered)
2130
+ return !1;
2131
+ let id = renderNodeId.value;
2132
+ return !!(id != null && render.isRectCoveredByHigherNode(id, rect, {
2133
+ ignoreSamePlane: props.ignoreSamePlaneRawCoverage
2134
+ }));
2135
+ }
2136
+ function rawUncoveredRenderRect(rect) {
2137
+ if (props.retainRawWhileCovered)
2138
+ return rect;
2139
+ let id = renderNodeId.value;
2140
+ if (id == null)
2141
+ return rect;
2142
+ let covers = render.higherNodeCoverageRects(id, rect, {
2143
+ ignoreSamePlane: props.ignoreSamePlaneRawCoverage
2144
+ });
2145
+ return covers.length ? props.ignoreRawCoverage ? largestUncoveredRect(rect, covers) : null : rect;
2146
+ }
2147
+ let rawCanRender = (0, import_vue8.computed)(() => {
2148
+ graphicsOutputVersion.value, terminalSizeVersion.value;
2149
+ let current = graphic.value, output = graphicsOutput(), rect = absRect.value;
2150
+ return current?.type === "terminal" && rawRectFitsTerminalViewport(rect) && !!output?.capabilities.supported && output?.capabilities.preferredProtocol === current.protocol;
2151
+ }), rawOutputCanRenderValue = (0, import_vue8.computed)(() => (graphicsOutputVersion.value, terminalSizeVersion.value, rawOutputCanRender())), rawSuppressedByScroll = (0, import_vue8.computed)(
2152
+ () => props.suspended || props.suspendRawWhileScrolling && isParentScrolling.value
2153
+ ), rawCanQueue = (0, import_vue8.computed)(() => rawCanRender.value && !rawSuppressedByScroll.value);
2154
+ function traceRawSkipScrollOnce(reason) {
2155
+ let r = absRect.value, key = [
2156
+ reason,
2157
+ graphicsActivityVersion.value,
2158
+ stableGraphicKey.value,
2159
+ r.x,
2160
+ r.y,
2161
+ r.w,
2162
+ r.h
2163
+ ].join(":");
2164
+ lastRawSkipScrollKey !== key && (lastRawSkipScrollKey = key, trace("raw-skip-scroll", { reason }));
2165
+ }
2166
+ function hasPaintableRect() {
2167
+ let r = absRect.value;
2168
+ return visible.value && r.w > 0 && r.h > 0;
2169
+ }
2170
+ function rawOutputCanRender() {
2171
+ let output = graphicsOutput(), rect = absRect.value;
2172
+ return rawRectFitsTerminalViewport(rect) && !!output?.capabilities.supported;
2173
+ }
2174
+ function renderDeferReason() {
2175
+ return props.suspended ? "suspended" : props.deferRenderUntilVisible && !hasPaintableRect() ? "not-visible" : props.suspendRenderWhileScrolling && isParentScrolling.value ? "scrolling" : null;
2176
+ }
2177
+ function shouldDeferRender() {
2178
+ return renderDeferReason() != null;
2179
+ }
2180
+ function shouldRerenderForGraphicsOutputChange() {
2181
+ if (!props.renderer || !props.content.trim() || shouldDeferRender() || rawSuppressedByScroll.value)
2182
+ return !1;
2183
+ let protocol = currentCapabilities().protocol;
2184
+ return lastRenderProtocol != null && (lastRenderProtocol !== protocol || lastRenderGraphicsOutputVersion !== graphicsOutputVersion.value);
2185
+ }
2186
+ function shouldRetryTemporaryRawFallback(rawCovered = rawCoveredByHigherRenderNode()) {
2187
+ return !!props.renderer && props.content.trim().length > 0 && graphic.value?.type === "text" && status.value !== "loading" && !lastRenderRawVisible && rawOutputCanRenderValue.value && !rawSuppressedByScroll.value && !rawCovered;
2188
+ }
2189
+ function setDeferredFallback(content) {
2190
+ graphic.value = { type: "text", text: content.trim() ? fallbackText() : "" }, lastRenderedContent = content, status.value = "idle", error.value = "", bump();
2191
+ }
2192
+ function resolveRendererContext(signal) {
2193
+ let capabilities = currentCapabilities(), visibleNow = hasPaintableRect(), rawVisible = rawOutputCanRenderValue.value && !rawSuppressedByScroll.value && !rawCoveredByHigherRenderNode();
2194
+ return {
2195
+ kind: props.kind,
2196
+ width: props.w,
2197
+ height: props.h,
2198
+ final: props.final,
2199
+ streaming: props.streaming,
2200
+ protocol: capabilities.protocol,
2201
+ capabilities,
2202
+ signal,
2203
+ imageId: imageId.value,
2204
+ placementId: placementId.value,
2205
+ visible: visibleNow,
2206
+ rawVisible,
2207
+ scrolling: isParentScrolling.value,
2208
+ cacheKey: props.cacheKey,
2209
+ viewport: {
2210
+ visible: visibleNow,
2211
+ rawVisible,
2212
+ scrolling: isParentScrolling.value,
2213
+ rect: absRect.value,
2214
+ fullRect: fullRect.value
2215
+ }
2216
+ };
2217
+ }
2218
+ async function renderNow(version) {
2219
+ let protocol = currentCapabilities().protocol;
2220
+ recordTerminalGraphicTrace({
2221
+ type: "request",
2222
+ id: rawId,
2223
+ key: props.cacheKey ?? smallHash(props.content),
2224
+ protocol: isTerminalGraphicsProtocol(protocol) ? protocol : void 0
2225
+ });
2226
+ let content = props.content;
2227
+ if (!content.trim()) {
2228
+ if (abortCurrentRender("superseded"), !alive || version !== renderVersion)
2229
+ return;
2230
+ graphic.value = { type: "text", text: "" }, lastRenderedContent = content, status.value = "ready", error.value = "", bump();
2231
+ return;
2232
+ }
2233
+ let renderer = props.renderer;
2234
+ if (!renderer) {
2235
+ if (abortCurrentRender("superseded"), !alive || version !== renderVersion)
2236
+ return;
2237
+ graphic.value = { type: "text", text: fallbackText() }, lastRenderedContent = content, status.value = "ready", error.value = "", bump();
2238
+ return;
2239
+ }
2240
+ let deferred = renderDeferReason();
2241
+ if (deferred) {
2242
+ if (abortCurrentRender(deferred), !alive || version !== renderVersion)
2243
+ return;
2244
+ setDeferredFallback(content), traceDeferOnce(deferred);
2245
+ return;
2246
+ }
2247
+ abortCurrentRender("superseded"), lastDeferTraceKey = "";
2248
+ let abort = new AbortController();
2249
+ renderAbort = abort;
2250
+ let startedAt = nowTerminalGraphicTraceTime();
2251
+ status.value = "loading", error.value = "", trace("render-start"), bump();
2252
+ try {
2253
+ let contextGraphicsOutputVersion = graphicsOutputVersion.value, context = resolveRendererContext(abort.signal);
2254
+ lastRenderRawVisible = context.rawVisible, lastRenderProtocol = context.protocol, lastRenderGraphicsOutputVersion = contextGraphicsOutputVersion;
2255
+ let result = await renderer(content, context);
2256
+ if (abort.signal.aborted || !alive || version !== renderVersion)
2257
+ return;
2258
+ let normalized = normalizeResult(result);
2259
+ rememberTerminalGraphicSize(normalized), graphic.value = normalized, lastRenderedContent = content, status.value = "ready", error.value = "", trace("render-end", {
2260
+ durationMs: nowTerminalGraphicTraceTime() - startedAt,
2261
+ sequenceChars: normalized.type === "terminal" ? normalized.sequence.length : 0,
2262
+ sequenceBytes: normalized.type === "terminal" ? normalized.sequenceBytes : 0
2263
+ }), bump(), normalized.type === "terminal" && scheduler.invalidate({ priority: "low", reason: "data" });
2264
+ } catch (err) {
2265
+ if (abort.signal.aborted || !alive || version !== renderVersion)
2266
+ return;
2267
+ graphic.value = { type: "text", text: fallbackText() }, lastRenderedContent = content, status.value = "ready", error.value = errorMessage(err), trace("render-end", {
2268
+ durationMs: nowTerminalGraphicTraceTime() - startedAt,
2269
+ reason: error.value
2270
+ }), bump();
2271
+ } finally {
2272
+ renderAbort === abort && (renderAbort = null);
2273
+ }
2274
+ }
2275
+ function scheduleRender(options = {}) {
2276
+ let version = ++renderVersion;
2277
+ if ((options.clearLastGraphic ?? !props.preserveRawWhileRendering) && queueClearLastGraphic(), !builtOnce || !props.streaming) {
2278
+ builtOnce = !0, renderNow(version);
2279
+ return;
2280
+ }
2281
+ scheduler.queueFrameTask({
2282
+ id: frameTaskId,
2283
+ reason: "stream",
2284
+ priority: "low",
2285
+ sync: !1,
2286
+ run: () => {
2287
+ alive && version === renderVersion && renderNow(version);
2288
+ }
2289
+ }) === !1 && renderNow(version);
2290
+ }
2291
+ (0, import_vue8.watch)(
2292
+ [
2293
+ () => props.content,
2294
+ () => props.kind,
2295
+ () => props.renderer,
2296
+ () => props.w,
2297
+ () => props.h,
2298
+ () => props.streaming,
2299
+ () => props.final,
2300
+ () => props.deferRenderUntilVisible,
2301
+ () => props.suspendRawWhileScrolling,
2302
+ () => props.suspendRenderWhileScrolling,
2303
+ () => props.scrolling,
2304
+ () => props.preserveRawWhileRendering,
2305
+ () => props.suspended,
2306
+ () => props.retainRawWhileCovered,
2307
+ () => props.ignoreRawCoverage,
2308
+ () => props.ignoreSamePlaneRawCoverage,
2309
+ () => props.cacheKey,
2310
+ () => props.placementKey
2311
+ ],
2312
+ () => {
2313
+ scheduleRender();
2314
+ },
2315
+ { immediate: !0 }
2316
+ ), (0, import_vue8.watch)(
2317
+ () => props.fallback,
2318
+ () => {
2319
+ let current = graphic.value;
2320
+ if (current?.type === "terminal") {
2321
+ if (current.fallbackFromProps) {
2322
+ graphic.value = { ...current, fallback: fallbackText() }, bump(), scheduler.invalidate({ priority: "low", reason: "data" });
2323
+ return;
2324
+ }
2325
+ scheduleRender({ clearLastGraphic: !1 });
2326
+ return;
2327
+ }
2328
+ scheduleRender();
2329
+ }
2330
+ ), (0, import_vue8.watch)(
2331
+ () => [graphicsOutputVersion.value, rawOutputCanRenderValue.value],
2332
+ () => {
2333
+ !props.renderer || !props.content.trim() || graphic.value?.type !== "terminal" && (!rawOutputCanRenderValue.value || shouldDeferRender() || scheduleRender({ clearLastGraphic: !1 }));
2334
+ }
2335
+ ), (0, import_vue8.watch)(
2336
+ () => [props.x, props.y, props.w, props.h, props.scrollVersion],
2337
+ () => {
2338
+ if (graphic.value?.type === "terminal") {
2339
+ scheduler.invalidate({ priority: "low", reason: "data" });
2340
+ return;
2341
+ }
2342
+ props.kind !== "image" || status.value !== "loading" || !props.renderer || scheduleRender({ clearLastGraphic: !1 });
2343
+ },
2344
+ { flush: "sync" }
2345
+ ), (0, import_vue8.onBeforeUnmount)(() => {
2346
+ alive = !1, renderVersion++, unsubscribeTerminalResize(), unsubscribeGraphicsOutput(), abortCurrentRender("unmount"), scheduler.cancelFrameTask?.(frameTaskId), queueClearLastGraphic();
2347
+ });
2348
+ function resolveDisplayLines(rawPlaceholderAllowed) {
2349
+ if (showingInitialLoadingText.value)
2350
+ return splitTextOutput(props.loadingText);
2351
+ let current = graphic.value;
2352
+ if (!current)
2353
+ return splitTextOutput(fallbackText());
2354
+ if (current.type === "terminal" && rawPlaceholderAllowed) {
2355
+ let clearSequence = resolveClearSequence(current), drawKey = terminalDrawKey(
2356
+ current,
2357
+ absRect.value,
2358
+ clearSequence,
2359
+ resolveResizeSequence(current, absRect.value, fullRect.value)
2360
+ );
2361
+ if (rawDrawRejectedKey.value !== drawKey)
2362
+ return (0, import_vue8.markRaw)([""]);
2363
+ }
2364
+ let text = current.type === "terminal" ? current.fallback : current.text, lines = splitTextOutput(text);
2365
+ return text.trim().length > 0 && !hasVisibleOutput(lines) ? splitTextOutput(fallbackText()) : lines;
2366
+ }
2367
+ let displayLines = (0, import_vue8.computed)(() => resolveDisplayLines(rawCanQueue.value)), currentStyle = (0, import_vue8.computed)(() => error.value ? props.errorStyle ?? props.style ?? defaultStyle.value : showingInitialLoadingText.value ? props.loadingStyle ?? props.style ?? defaultStyle.value : props.style ?? defaultStyle.value), renderNode = useRenderNode(() => ({
2368
+ zIndex: props.zIndex,
2369
+ rect: visible.value ? renderRect.value : { x: 0, y: 0, w: 0, h: 0 },
2370
+ deps: [
2371
+ visible.value,
2372
+ renderRect.value,
2373
+ fullRect.value,
2374
+ displayLines.value,
2375
+ currentStyle.value,
2376
+ props.clear,
2377
+ status.value,
2378
+ error.value,
2379
+ documentVersion.value,
2380
+ rawOutputCanRenderValue.value,
2381
+ rawCanRender.value,
2382
+ rawCanQueue.value,
2383
+ rawClearPendingRepaint.value,
2384
+ rawDrawRejectedKey.value,
2385
+ rawSuppressedByScroll.value,
2386
+ props.placementMoveWithoutClear,
2387
+ props.retainRawWhileCovered,
2388
+ isParentScrolling.value,
2389
+ graphicsActivityVersion.value,
2390
+ graphicsOutputVersion.value
2391
+ ],
2392
+ paint: (dirtyRows) => {
2393
+ withTextWidthProvider(widthProvider, () => {
2394
+ if (!visible.value) {
2395
+ queueClearLastGraphic();
2396
+ return;
2397
+ }
2398
+ let r = absRect.value, full = fullRect.value;
2399
+ if (r.w <= 0 || r.h <= 0) {
2400
+ queueClearLastGraphic();
2401
+ return;
2402
+ }
2403
+ let style = currentStyle.value, dx = Math.max(0, Math.floor(r.x - full.x)), fullY = Math.floor(full.y), current = graphic.value, output = graphicsOutput(), retainedActiveRawGraphic = hasRetainedActiveRawGraphic(), rawRectForPaint = rawUncoveredRenderRect(r), rawCoverageClipped = rawRectForPaint != null && props.ignoreRawCoverage && !sameRect(rawRectForPaint, r), rawCoveredForPaint = rawRectForPaint == null && rawCoveredByHigherRenderNode(r), rawCanQueueForPaint = current?.type === "terminal" && rawCanQueue.value && rawRectForPaint != null, preserveActiveRawGraphic = !1, forceActiveRawRedraw = !1, allowTextOverlay = !1;
2404
+ if (rawCanQueueForPaint && output) {
2405
+ let previous = lastDrawnGraphic.value;
2406
+ if ((previous ? typeof output.isActive == "function" ? output.isActive(previous.id) : !0 : !1) && previous) {
2407
+ let clearSequence = resolveClearSequence(current), resizeSequence = resolveResizeSequence(current, rawRectForPaint, full);
2408
+ preserveActiveRawGraphic = rawClearPendingRepaint.value == null && previous.drawKey === terminalDrawKey(current, rawRectForPaint, clearSequence, resizeSequence), allowTextOverlay = retainedRawCoveredByHigherRenderNode(r), forceActiveRawRedraw = preserveActiveRawGraphic && (previous.activityVersion !== graphicsActivityVersion.value || previous.allowTextOverlay !== allowTextOverlay);
2409
+ }
2410
+ }
2411
+ let preserveActiveRawGraphicForPaint = preserveActiveRawGraphic, out = rawCanQueueForPaint ? displayLines.value : resolveDisplayLines(!1), clearingRawGraphic = rawClearPendingRepaint.value != null || lastDrawnGraphic.value != null && !preserveActiveRawGraphicForPaint, clearOwnedRegion = preserveActiveRawGraphicForPaint || retainedActiveRawGraphic ? !1 : props.clear || clearingRawGraphic || !!rawCanQueueForPaint, blank = clearOwnedRegion ? spaces(r.w) : "", paintRow = (y) => {
2412
+ if (y < r.y || y >= r.y + r.h)
2413
+ return;
2414
+ let rowIndex = y - fullY;
2415
+ if (rowIndex < 0 || rowIndex >= out.length) {
2416
+ clearOwnedRegion && terminal.write(blank, { x: r.x, y, style });
2417
+ return;
2418
+ }
2419
+ let src = out[rowIndex] ?? "", clipped = dx > 0 ? sliceByCellsRange(src, dx, dx + r.w) : sliceByCells(src, r.w), value = clearOwnedRegion ? padEndByCells(clipped, r.w) : clipped;
2420
+ (value || clearOwnedRegion) && terminal.write(value, { x: r.x, y, style });
2421
+ }, paintRows = () => {
2422
+ if (dirtyRows?.length)
2423
+ for (let y of dirtyRows)
2424
+ paintRow(y);
2425
+ else
2426
+ for (let y = r.y; y < r.y + r.h; y++)
2427
+ paintRow(y);
2428
+ };
2429
+ if (paintRows(), current?.type === "terminal" && output?.capabilities.supported && output.capabilities.preferredProtocol === current.protocol && rawCanQueueForPaint) {
2430
+ let drawKey = terminalDrawKey(
2431
+ current,
2432
+ rawRectForPaint,
2433
+ resolveClearSequence(current),
2434
+ resolveResizeSequence(current, rawRectForPaint, full)
2435
+ );
2436
+ queueDrawGraphic(output, current, rawRectForPaint, full, {
2437
+ force: forceActiveRawRedraw,
2438
+ deferFlush: preserveActiveRawGraphicForPaint,
2439
+ placementMoveWithoutClear: props.placementMoveWithoutClear || rawCoverageClipped,
2440
+ allowTextOverlay
2441
+ }) ? trace("raw-draw", {
2442
+ sequenceChars: current.sequence.length,
2443
+ sequenceBytes: current.sequenceBytes,
2444
+ x: rawRectForPaint.x,
2445
+ y: rawRectForPaint.y,
2446
+ w: rawRectForPaint.w,
2447
+ h: rawRectForPaint.h
2448
+ }) : rawDrawRejectedKey.value === drawKey && (out = resolveDisplayLines(!1), paintRows());
2449
+ } else
2450
+ current?.type === "terminal" && rawSuppressedByScroll.value && traceRawSkipScrollOnce(isParentScrolling.value ? "scrolling" : "suspended"), queueClearLastGraphic({ markPendingRepaint: !1 }), !shouldDeferRender() && shouldRetryTemporaryRawFallback(rawCoveredForPaint) && scheduleRender({ clearLastGraphic: !1 });
2451
+ clearingRawGraphic && (rawClearPendingRepaint.value = null);
2452
+ });
2453
+ }
2454
+ }));
2455
+ return (0, import_vue8.watch)(
2456
+ renderNode.id,
2457
+ (id) => {
2458
+ renderNodeId.value = id;
2459
+ },
2460
+ { immediate: !0 }
2461
+ ), (0, import_vue8.watch)(
2462
+ [
2463
+ visible,
2464
+ rawOutputCanRenderValue,
2465
+ rawCanRender,
2466
+ rawCanQueue,
2467
+ rawSuppressedByScroll,
2468
+ isParentScrolling,
2469
+ graphicsActivityVersion,
2470
+ graphicsOutputVersion,
2471
+ () => renderRect.value.x,
2472
+ () => renderRect.value.y,
2473
+ () => renderRect.value.w,
2474
+ () => renderRect.value.h,
2475
+ () => fullRect.value.x,
2476
+ () => fullRect.value.y,
2477
+ () => fullRect.value.w,
2478
+ () => fullRect.value.h
2479
+ ],
2480
+ () => {
2481
+ if (!alive)
2482
+ return;
2483
+ let deferred = renderDeferReason();
2484
+ deferred && (abortCurrentRender(deferred), (status.value === "loading" || !graphic.value || lastRenderedContent !== props.content) && setDeferredFallback(props.content), traceDeferOnce(deferred)), (!visible.value || !rawCanQueue.value) && queueClearLastGraphic();
2485
+ let shouldRetryTemporaryFallback = shouldRetryTemporaryRawFallback(), shouldRerenderForOutputChange = shouldRerenderForGraphicsOutputChange();
2486
+ if (!shouldDeferRender() && (!graphic.value || status.value === "idle" || shouldRetryTemporaryFallback || shouldRerenderForOutputChange)) {
2487
+ scheduleRender();
2488
+ return;
2489
+ }
2490
+ scheduler.invalidate({ priority: "low", reason: "data" });
2491
+ },
2492
+ { flush: "post" }
2493
+ ), () => (0, import_vue8.h)("span", rootProps);
2494
+ }
2495
+ });
2496
+
2497
+ // src/vue/components/TText.ts
2498
+ var import_vue9 = require("vue");
2499
+ function fitText(text, max) {
2500
+ return max <= 0 ? "" : (text = sanitizeInlineText(text), sliceByCells(text, max));
2501
+ }
2502
+ function splitLines(text) {
2503
+ return sanitizeTextBlock(text).split(`
2504
+ `);
2505
+ }
2506
+ function computeDefaultWidth(text) {
2507
+ let lines = splitLines(text), max = 0;
2508
+ for (let line of lines)
2509
+ max = Math.max(max, textCellWidth(line));
2510
+ return max;
2511
+ }
2512
+ var TText = (0, import_vue9.defineComponent)({
2513
+ name: "TText",
2514
+ props: {
2515
+ x: { type: Number, required: !0 },
2516
+ y: { type: Number, required: !0 },
2517
+ zIndex: { type: Number, default: 0 },
2518
+ value: { type: String, required: !0 },
2519
+ w: { type: Number, default: void 0 },
2520
+ h: { type: Number, default: void 0 },
2521
+ style: { type: Object, default: void 0 },
2522
+ clear: { type: Boolean, default: !0 },
2523
+ wrap: { type: Boolean, default: !1 },
2524
+ /**
2525
+ * Optional key that participates in render-node dependency tracking.
2526
+ * Useful for forcing a repaint when the rendered output might change
2527
+ * even if `value`, `style`, and geometry are unchanged (e.g. external
2528
+ * terminal writes or higher-level virtualized row reuse).
2529
+ */
2530
+ depsKey: { type: null, default: void 0 }
2531
+ },
2532
+ setup(props) {
2533
+ let { terminal, defaultStyle } = useTerminal(), layout = useLayout(), { visible, rootProps } = useVisibility(), defaultWidth = (0, import_vue9.computed)(() => computeDefaultWidth(props.value)), lines = (0, import_vue9.computed)(() => {
2534
+ let w = props.w ?? defaultWidth.value;
2535
+ if (w <= 0)
2536
+ return [""];
2537
+ if (!props.wrap)
2538
+ return splitLines(props.value).map((l) => fitText(l, w));
2539
+ let safe = sanitizeTextBlock(props.value);
2540
+ return wrapByCells(safe, w).map((l) => fitText(l, w));
2541
+ }), absRect = (0, import_vue9.computed)(() => {
2542
+ let width = props.w ?? defaultWidth.value, height = props.h ?? (props.wrap, lines.value.length || 1), raw = { x: props.x, y: props.y, w: width, h: height }, translated = translateRect(raw, layout.originX, layout.originY);
2543
+ return layout.clipRect ? intersectRect(translated, layout.clipRect) ?? { x: 0, y: 0, w: 0, h: 0 } : translated;
2544
+ }), fullRect = (0, import_vue9.computed)(() => {
2545
+ let width = props.w ?? defaultWidth.value, height = props.h ?? (props.wrap, lines.value.length || 1);
2546
+ return translateRect(
2547
+ { x: props.x, y: props.y, w: width, h: height },
2548
+ layout.originX,
2549
+ layout.originY
2550
+ );
2551
+ });
2552
+ return useRenderNode(() => ({
2553
+ zIndex: props.zIndex,
2554
+ rect: visible.value ? absRect.value : { x: 0, y: 0, w: 0, h: 0 },
2555
+ deps: [
2556
+ visible.value,
2557
+ absRect.value,
2558
+ fullRect.value,
2559
+ props.value,
2560
+ props.w,
2561
+ props.h,
2562
+ props.wrap,
2563
+ props.style,
2564
+ defaultStyle.value,
2565
+ props.depsKey
2566
+ ],
2567
+ paint: (dirtyRows) => {
2568
+ if (!visible.value)
2569
+ return;
2570
+ let r = absRect.value;
2571
+ if (r.w <= 0 || r.h <= 0)
2572
+ return;
2573
+ let full = fullRect.value, style = props.style ?? defaultStyle.value, blank = props.clear ? spaces(r.w) : "", out = lines.value, dx = Math.max(0, Math.floor(r.x - full.x)), fullY = Math.floor(full.y), paintRow = (y) => {
2574
+ let relY = y - r.y;
2575
+ if (relY < 0 || relY >= r.h)
2576
+ return;
2577
+ let i = y - fullY;
2578
+ if (i < 0 || i >= out.length) {
2579
+ props.clear && terminal.write(blank, { x: r.x, y, style });
2580
+ return;
2581
+ }
2582
+ let src = out[i] ?? "", clipped = dx > 0 ? sliceByCellsRange(src, dx, dx + r.w) : sliceByCells(src, r.w);
2583
+ terminal.write(padEndByCells(clipped, r.w), { x: r.x, y, style });
2584
+ };
2585
+ if (!dirtyRows) {
2586
+ for (let i = 0; i < r.h; i++)
2587
+ paintRow(r.y + i);
2588
+ return;
2589
+ }
2590
+ for (let y of dirtyRows)
2591
+ paintRow(y);
2592
+ }
2593
+ })), () => (0, import_vue9.h)("span", rootProps);
2594
+ }
2595
+ });
2596
+
2597
+ // src/vue/components/TView.ts
2598
+ var import_vue10 = require("vue");
2599
+ var EMPTY_RECT = Object.freeze({ x: 0, y: 0, w: 0, h: 0 }), TView = (0, import_vue10.defineComponent)({
2600
+ name: "TView",
2601
+ props: {
2602
+ x: { type: Number, required: !0 },
2603
+ y: { type: Number, required: !0 },
2604
+ w: { type: Number, required: !0 },
2605
+ h: { type: Number, required: !0 },
2606
+ zIndex: { type: Number, default: 0 },
2607
+ scrollX: { type: Number, default: 0 },
2608
+ scrollY: { type: Number, default: 0 },
2609
+ focusable: { type: Boolean, default: !1 },
2610
+ selectable: { type: Boolean, default: void 0 },
2611
+ selectionScrollBy: {
2612
+ type: Function,
2613
+ default: void 0
2614
+ },
2615
+ autoFocus: { type: Boolean, default: !1 }
2616
+ },
2617
+ emits: [
2618
+ "clickCapture",
2619
+ "click",
2620
+ "dblclickCapture",
2621
+ "dblclick",
2622
+ "pointerdownCapture",
2623
+ "pointerdown",
2624
+ "pointerupCapture",
2625
+ "pointerup",
2626
+ "pointermoveCapture",
2627
+ "pointermove",
2628
+ "pointerenterCapture",
2629
+ "pointerenter",
2630
+ "pointerleaveCapture",
2631
+ "pointerleave",
2632
+ "wheelCapture",
2633
+ "wheel",
2634
+ "keydownCapture",
2635
+ "keydown",
2636
+ "keyupCapture",
2637
+ "keyup",
2638
+ "focusCapture",
2639
+ "focus",
2640
+ "blurCapture",
2641
+ "blur"
2642
+ ],
2643
+ setup(props, { emit, slots }) {
2644
+ let parent = useLayout(), { render, events } = useTerminal(), parentStack = useRenderStack(), { visible, rootProps } = useVisibility({ provide: !0 }), parentEventZ = (0, import_vue10.inject)(EventZIndexContextKey, (0, import_vue10.computed)(() => 0)), eventZ = (0, import_vue10.computed)(() => (parentEventZ.value ?? 0) + (props.zIndex ?? 0)), rawRect = (0, import_vue10.computed)(
2645
+ () => translateRect(
2646
+ { x: props.x, y: props.y, w: props.w, h: props.h },
2647
+ parent.originX,
2648
+ parent.originY
2649
+ )
2650
+ ), rect = (0, import_vue10.computed)(() => {
2651
+ let translated = rawRect.value;
2652
+ return parent.clipRect ? intersectRect(translated, parent.clipRect) ?? EMPTY_RECT : translated;
2653
+ }), { id } = useTerminalNode(() => ({
2654
+ rect: rect.value,
2655
+ zIndex: eventZ.value,
2656
+ visible: visible.value,
2657
+ focusable: props.focusable,
2658
+ selectable: props.selectable,
2659
+ selectionScrollBy: props.selectionScrollBy,
2660
+ handlers: {
2661
+ clickCapture: (e) => emit("clickCapture", e),
2662
+ click: (e) => emit("click", e),
2663
+ dblclickCapture: (e) => emit("dblclickCapture", e),
2664
+ dblclick: (e) => emit("dblclick", e),
2665
+ pointerdownCapture: (e) => emit("pointerdownCapture", e),
2666
+ pointerdown: (e) => emit("pointerdown", e),
2667
+ pointerupCapture: (e) => emit("pointerupCapture", e),
2668
+ pointerup: (e) => emit("pointerup", e),
2669
+ pointermoveCapture: (e) => emit("pointermoveCapture", e),
2670
+ pointermove: (e) => emit("pointermove", e),
2671
+ pointerenterCapture: (e) => emit("pointerenterCapture", e),
2672
+ pointerenter: (e) => emit("pointerenter", e),
2673
+ pointerleaveCapture: (e) => emit("pointerleaveCapture", e),
2674
+ pointerleave: (e) => emit("pointerleave", e),
2675
+ wheelCapture: (e) => emit("wheelCapture", e),
2676
+ wheel: (e) => emit("wheel", e),
2677
+ keydownCapture: (e) => emit("keydownCapture", e),
2678
+ keydown: (e) => emit("keydown", e),
2679
+ keyupCapture: (e) => emit("keyupCapture", e),
2680
+ keyup: (e) => emit("keyup", e),
2681
+ focusCapture: (e) => emit("focusCapture", e),
2682
+ focus: (e) => emit("focus", e),
2683
+ blurCapture: (e) => emit("blurCapture", e),
2684
+ blur: (e) => emit("blur", e)
2685
+ }
2686
+ }));
2687
+ (0, import_vue10.watchEffect)(() => {
2688
+ if (!props.autoFocus || !visible.value)
2689
+ return;
2690
+ let manager = events.value, nodeId = id.value;
2691
+ !manager || !nodeId || manager.getFocused() !== nodeId && manager.focus(nodeId);
2692
+ });
2693
+ let childLayout = (0, import_vue10.shallowReactive)({
2694
+ originX: 0,
2695
+ originY: 0,
2696
+ clipRect: null
2697
+ }), childStack = (0, import_vue10.computed)(() => render.createStack(parentStack.value, props.zIndex));
2698
+ return (0, import_vue10.watchEffect)(() => {
2699
+ let translated = rawRect.value;
2700
+ childLayout.originX = translated.x - Math.floor(props.scrollX), childLayout.originY = translated.y - Math.floor(props.scrollY), childLayout.clipRect = rect.value;
2701
+ }), (0, import_vue10.provide)(LayoutContextKey, childLayout), (0, import_vue10.provide)(RenderStackKey, childStack), (0, import_vue10.provide)(EventZIndexContextKey, eventZ), () => (0, import_vue10.h)("div", rootProps, slots.default?.());
2702
+ }
2703
+ });
2704
+
2705
+ // src/vue/components/TVideo.ts
2706
+ var DEFAULT_MAX_FPS = 12, DEFAULT_MAX_PIXEL_WIDTH = 640, DEFAULT_MAX_PIXEL_HEIGHT = 360, MAX_PIXEL_DIMENSION = 4096, MAX_FRAME_BYTES = 8 * 1024 * 1024, MAX_GRAY8_FPS = 10, MAX_GRAY8_WIDTH = 512, MAX_GRAY8_HEIGHT = 256, ASCII_RAMP = " .:-=+*#%@", CONTROL_REFRESH_MS = 250, PLAYBACK_RATES = [1, 2, 3];
2707
+ function positiveInt2(value, fallback, max) {
2708
+ let parsed = Math.floor(Number(value));
2709
+ return !Number.isFinite(parsed) || parsed <= 0 ? Math.min(max, fallback) : Math.min(max, parsed);
2710
+ }
2711
+ function positiveNumber(value, fallback, max) {
2712
+ let parsed = Number(value);
2713
+ return !Number.isFinite(parsed) || parsed <= 0 ? fallback : Math.min(max, parsed);
2714
+ }
2715
+ function playbackRate(value) {
2716
+ return value === 2 || value === 3 ? value : 1;
2717
+ }
2718
+ function optionalDuration(value) {
2719
+ let parsed = Number(value);
2720
+ return Number.isFinite(parsed) && parsed > 0 ? parsed : void 0;
2721
+ }
2722
+ function formatPlaybackTime(valueMs, hourDigits = 0) {
2723
+ if (valueMs == null)
2724
+ return "--:--";
2725
+ let seconds = Math.max(0, Math.floor(valueMs / 1e3)), hours = Math.floor(seconds / 3600), minutes = Math.floor(seconds % 3600 / 60), remainder = seconds % 60;
2726
+ return hours > 0 || hourDigits > 0 ? `${String(hours).padStart(Math.max(1, hourDigits), "0")}:${String(minutes).padStart(2, "0")}:${String(remainder).padStart(2, "0")}` : `${String(minutes).padStart(2, "0")}:${String(remainder).padStart(2, "0")}`;
2727
+ }
2728
+ function readUint32(bytes, offset) {
2729
+ return bytes[offset] * 16777216 + (bytes[offset + 1] << 16) + (bytes[offset + 2] << 8) + bytes[offset + 3] >>> 0;
2730
+ }
2731
+ function normalizeFrame(frame) {
2732
+ if (frame.format === "gray8") {
2733
+ let pixelWidth2 = Math.floor(Number(frame.pixelWidth)), pixelHeight2 = Math.floor(Number(frame.pixelHeight)), pixels = frame.pixels;
2734
+ if (!Number.isFinite(pixelWidth2) || !Number.isFinite(pixelHeight2) || pixelWidth2 <= 0 || pixelHeight2 <= 0 || pixelWidth2 > MAX_GRAY8_WIDTH || pixelHeight2 > MAX_GRAY8_HEIGHT || !(pixels instanceof Uint8Array) || pixels.length !== pixelWidth2 * pixelHeight2 || pixels.length > MAX_FRAME_BYTES)
2735
+ throw new Error("TVideo gray8 frame must match its bounded pixel dimensions");
2736
+ return {
2737
+ format: "gray8",
2738
+ pixels,
2739
+ timestampMs: Math.max(0, Number(frame.timestampMs) || 0),
2740
+ pixelWidth: pixelWidth2,
2741
+ pixelHeight: pixelHeight2,
2742
+ fingerprint: frame.fingerprint,
2743
+ durationMs: optionalDuration(frame.durationMs)
2744
+ };
2745
+ }
2746
+ let png = frame.png;
2747
+ if (!(png instanceof Uint8Array) || png.length < 24 || png.length > MAX_FRAME_BYTES)
2748
+ throw new Error("TVideo frame must contain a bounded PNG Uint8Array");
2749
+ if (png[0] !== 137 || png[1] !== 80 || png[2] !== 78 || png[3] !== 71 || png[4] !== 13 || png[5] !== 10 || png[6] !== 26 || png[7] !== 10)
2750
+ throw new Error("TVideo frame source emitted invalid PNG data");
2751
+ let pixelWidth = readUint32(png, 16), pixelHeight = readUint32(png, 20);
2752
+ if (pixelWidth <= 0 || pixelHeight <= 0 || pixelWidth > MAX_PIXEL_DIMENSION || pixelHeight > MAX_PIXEL_DIMENSION)
2753
+ throw new Error(`TVideo frame has an unsupported size: ${pixelWidth}x${pixelHeight}`);
2754
+ return {
2755
+ format: "png",
2756
+ png,
2757
+ timestampMs: Math.max(0, Number(frame.timestampMs) || 0),
2758
+ pixelWidth,
2759
+ pixelHeight,
2760
+ fingerprint: frame.fingerprint,
2761
+ durationMs: optionalDuration(frame.durationMs)
2762
+ };
2763
+ }
2764
+ function frameBytes(frame) {
2765
+ return frame.format === "gray8" ? frame.pixels : frame.png;
2766
+ }
2767
+ function gray8ToAscii(frame, cellWidth) {
2768
+ let lines = [], width = Math.max(1, Math.floor(cellWidth));
2769
+ for (let y = 0; y < frame.pixelHeight; y++) {
2770
+ let line = "", rowStart = y * frame.pixelWidth;
2771
+ for (let x = 0; x < frame.pixelWidth; x++) {
2772
+ let value = frame.pixels[rowStart + x], glyph = ASCII_RAMP[Math.min(ASCII_RAMP.length - 1, value * ASCII_RAMP.length >> 8)];
2773
+ line += `${glyph}${glyph}`;
2774
+ }
2775
+ lines.push(line.slice(0, width));
2776
+ }
2777
+ return lines.join(`
2778
+ `);
2779
+ }
2780
+ function sameBytes(left, right) {
2781
+ if (left.length !== right.length)
2782
+ return !1;
2783
+ for (let index = 0; index < left.length; index++)
2784
+ if (left[index] !== right[index])
2785
+ return !1;
2786
+ return !0;
2787
+ }
2788
+ function bytesToBase64(bytes) {
2789
+ let alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/", chunks = [], chunk = "";
2790
+ for (let index = 0; index < bytes.length; index += 3) {
2791
+ let a = bytes[index], hasB = index + 1 < bytes.length, hasC = index + 2 < bytes.length, b = hasB ? bytes[index + 1] : 0, c = hasC ? bytes[index + 2] : 0;
2792
+ chunk += alphabet[a >> 2] + alphabet[(a & 3) << 4 | b >> 4] + (hasB ? alphabet[(b & 15) << 2 | c >> 6] : "=") + (hasC ? alphabet[c & 63] : "="), chunk.length >= 16384 && (chunks.push(chunk), chunk = "");
2793
+ }
2794
+ return chunk && chunks.push(chunk), chunks.join("");
2795
+ }
2796
+ function createFrameRenderer(frame, cellWidth) {
2797
+ if (frame.format === "gray8") {
2798
+ let text = gray8ToAscii(frame, cellWidth);
2799
+ return () => ({ type: "text", text });
2800
+ }
2801
+ let base64;
2802
+ return (_content, context) => {
2803
+ if (!context.visible || !context.rawVisible)
2804
+ return null;
2805
+ base64 ?? (base64 = bytesToBase64(frame.png));
2806
+ let protocol = context.protocol;
2807
+ return protocol !== "kitty" && protocol !== "iterm2" ? null : createTerminalGraphicPngSequence({
2808
+ protocol,
2809
+ base64,
2810
+ imageId: context.imageId,
2811
+ placementId: context.placementId,
2812
+ cols: context.width,
2813
+ rows: context.height,
2814
+ sourceWidth: frame.pixelWidth,
2815
+ sourceHeight: frame.pixelHeight,
2816
+ placementColumns: Math.max(1, Math.floor(context.viewport.rect.w)),
2817
+ placementRows: Math.max(1, Math.floor(context.viewport.rect.h)),
2818
+ rect: context.viewport.rect,
2819
+ fullRect: context.viewport.fullRect,
2820
+ freeImageData: !0
2821
+ });
2822
+ };
2823
+ }
2824
+ function errorMessage2(error) {
2825
+ return error instanceof Error ? error.message : String(error);
2826
+ }
2827
+ var tVideoProps = {
2828
+ x: { type: Number, required: !0 },
2829
+ y: { type: Number, required: !0 },
2830
+ w: { type: Number, required: !0 },
2831
+ h: { type: Number, required: !0 },
2832
+ zIndex: { type: Number, default: 0 },
2833
+ src: { type: String, required: !0 },
2834
+ frameSource: {
2835
+ type: Function,
2836
+ required: !0
2837
+ },
2838
+ paused: { type: Boolean, default: void 0 },
2839
+ playbackRate: { type: Number, default: void 0 },
2840
+ controls: { type: Boolean, default: !1 },
2841
+ controlsLayout: {
2842
+ type: String,
2843
+ default: "compact"
2844
+ },
2845
+ durationMs: { type: Number, default: void 0 },
2846
+ loop: { type: Boolean, default: !1 },
2847
+ maxFps: { type: Number, default: DEFAULT_MAX_FPS },
2848
+ pixelWidth: { type: Number, default: void 0 },
2849
+ pixelHeight: { type: Number, default: void 0 },
2850
+ fallback: { type: String, default: "[video]" },
2851
+ style: { type: Object, default: void 0 },
2852
+ clear: { type: Boolean, default: !0 }
2853
+ }, TVideo = (0, import_vue11.defineComponent)({
2854
+ name: "TVideo",
2855
+ props: tVideoProps,
2856
+ emits: {
2857
+ frame: (_event) => !0,
2858
+ ended: () => !0,
2859
+ error: (_error) => !0,
2860
+ seek: (_event) => !0,
2861
+ "update:paused": (_paused) => !0,
2862
+ "update:playbackRate": (_rate) => !0
2863
+ },
2864
+ setup(props, { emit }) {
2865
+ let instance = (0, import_vue11.getCurrentInstance)(), { terminal, scheduler } = useTerminal(), layout = useLayout(), { visible, rootProps } = useVisibility({ provide: !0 }), graphicsActivity = (0, import_vue11.inject)(TerminalGraphicsActivityKey, null), frameRenderer = (0, import_vue11.shallowRef)(), playbackError = (0, import_vue11.shallowRef)(""), internalPaused = (0, import_vue11.shallowRef)(props.paused ?? !1), internalPlaybackRate = (0, import_vue11.shallowRef)(playbackRate(props.playbackRate)), discoveredDurationMs = (0, import_vue11.shallowRef)(), displayedTimestampMs = (0, import_vue11.shallowRef)(0), seekPreviewMs = (0, import_vue11.shallowRef)(), seeking = (0, import_vue11.shallowRef)(!1), terminalSizeVersion = (0, import_vue11.shallowRef)(0), graphicsOutputVersion = (0, import_vue11.shallowRef)(getTerminalGraphicsOutputVersion(terminal)), placementKey = `TVideo:${instance?.uid ?? "unknown"}`, mailboxId = `${placementKey}:frame`, alive = !0, generation = 0, activeAbort = null, lastSourceBytes = null, lastQueuedBytes = null, lastQueuedFormat = null, lastQueuedFingerprint, lastTimestampMs = 0, droppedFrames = 0, pendingEndedGeneration = null, suppressNextVideoClick = !1, controlPointerCapture = null, unsubscribeTerminalResize = terminal.on("resize", () => {
2866
+ terminalSizeVersion.value++;
2867
+ }), unsubscribeGraphicsOutput = subscribeTerminalGraphicsOutput(terminal, () => {
2868
+ graphicsOutputVersion.value = getTerminalGraphicsOutputVersion(terminal);
2869
+ }), showControls = (0, import_vue11.computed)(
2870
+ () => props.controls && Math.floor(props.w) >= 14 && Math.floor(props.h) >= 2
2871
+ ), resolvedControlsLayout = (0, import_vue11.computed)(
2872
+ () => props.controlsLayout === "cinema" && Math.floor(props.h) >= 3 ? "cinema" : "compact"
2873
+ ), controlRows = (0, import_vue11.computed)(
2874
+ () => showControls.value ? resolvedControlsLayout.value === "cinema" ? 2 : 1 : 0
2875
+ ), videoHeight = (0, import_vue11.computed)(() => Math.max(1, Math.floor(props.h) - controlRows.value)), resolvedMaxFps = (0, import_vue11.computed)(() => positiveNumber(props.maxFps, DEFAULT_MAX_FPS, 60)), resolvedPixelSize = (0, import_vue11.computed)(() => {
2876
+ let desiredWidth = Math.max(2, Math.floor(props.w) * 8), desiredHeight = Math.max(2, videoHeight.value * 16);
2877
+ if (props.pixelWidth == null && props.pixelHeight == null) {
2878
+ let scale = Math.min(
2879
+ 1,
2880
+ DEFAULT_MAX_PIXEL_WIDTH / desiredWidth,
2881
+ DEFAULT_MAX_PIXEL_HEIGHT / desiredHeight
2882
+ );
2883
+ return {
2884
+ width: Math.max(2, Math.floor(desiredWidth * scale)),
2885
+ height: Math.max(2, Math.floor(desiredHeight * scale))
2886
+ };
2887
+ }
2888
+ if (props.pixelWidth != null && props.pixelHeight == null) {
2889
+ let width = positiveInt2(props.pixelWidth, desiredWidth, MAX_PIXEL_DIMENSION), inferredHeight = width * desiredHeight / desiredWidth, scale = Math.min(1, MAX_PIXEL_DIMENSION / inferredHeight);
2890
+ return {
2891
+ width: Math.max(2, Math.floor(width * scale)),
2892
+ height: Math.max(2, Math.floor(inferredHeight * scale))
2893
+ };
2894
+ }
2895
+ if (props.pixelWidth == null && props.pixelHeight != null) {
2896
+ let height = positiveInt2(props.pixelHeight, desiredHeight, MAX_PIXEL_DIMENSION), inferredWidth = height * desiredWidth / desiredHeight, scale = Math.min(1, MAX_PIXEL_DIMENSION / inferredWidth);
2897
+ return {
2898
+ width: Math.max(2, Math.floor(inferredWidth * scale)),
2899
+ height: Math.max(2, Math.floor(height * scale))
2900
+ };
2901
+ }
2902
+ return {
2903
+ width: positiveInt2(props.pixelWidth, desiredWidth, MAX_PIXEL_DIMENSION),
2904
+ height: positiveInt2(props.pixelHeight, desiredHeight, MAX_PIXEL_DIMENSION)
2905
+ };
2906
+ }), resolvedPixelWidth = (0, import_vue11.computed)(() => resolvedPixelSize.value.width), resolvedPixelHeight = (0, import_vue11.computed)(() => resolvedPixelSize.value.height), paintable = (0, import_vue11.computed)(() => {
2907
+ if (terminalSizeVersion.value, !visible.value)
2908
+ return !1;
2909
+ let size = terminal.size(), terminalRect = {
2910
+ x: 0,
2911
+ y: 0,
2912
+ w: Math.max(0, Math.floor(size.cols)),
2913
+ h: Math.max(0, Math.floor(size.rows))
2914
+ }, clip = layout.clipRect ? intersectRect(layout.clipRect, terminalRect) : terminalRect;
2915
+ if (!clip)
2916
+ return !1;
2917
+ let rect = translateRect(
2918
+ { x: props.x, y: props.y, w: props.w, h: videoHeight.value },
2919
+ layout.originX,
2920
+ layout.originY
2921
+ ), visibleRect = intersectRect(rect, clip);
2922
+ return !!(visibleRect && visibleRect.w > 0 && visibleRect.h > 0);
2923
+ }), graphicsProtocol = (0, import_vue11.computed)(() => (graphicsOutputVersion.value, getTerminalGraphicsOutput(terminal)?.capabilities.preferredProtocol ?? null)), preferredFormat = (0, import_vue11.computed)(
2924
+ () => graphicsProtocol.value === "kitty" || graphicsProtocol.value === "iterm2" ? "png" : "gray8"
2925
+ ), resolvedDecodeFps = (0, import_vue11.computed)(
2926
+ () => preferredFormat.value === "gray8" ? Math.min(MAX_GRAY8_FPS, resolvedMaxFps.value) : resolvedMaxFps.value
2927
+ ), resolvedDecodeWidth = (0, import_vue11.computed)(
2928
+ () => preferredFormat.value === "gray8" ? positiveInt2(Math.ceil(props.w / 2), 1, MAX_GRAY8_WIDTH) : resolvedPixelWidth.value
2929
+ ), resolvedDecodeHeight = (0, import_vue11.computed)(
2930
+ () => preferredFormat.value === "gray8" ? positiveInt2(videoHeight.value, 1, MAX_GRAY8_HEIGHT) : resolvedPixelHeight.value
2931
+ ), resolvedDurationMs = (0, import_vue11.computed)(
2932
+ () => optionalDuration(props.durationMs) ?? discoveredDurationMs.value
2933
+ ), effectivePaused = (0, import_vue11.computed)(() => props.paused ?? internalPaused.value), effectivePlaybackRate = (0, import_vue11.computed)(
2934
+ () => props.playbackRate == null ? internalPlaybackRate.value : playbackRate(props.playbackRate)
2935
+ ), controlTimestampMs = (0, import_vue11.computed)(() => seekPreviewMs.value ?? displayedTimestampMs.value), timeHourDigits = (0, import_vue11.computed)(() => {
2936
+ let duration = resolvedDurationMs.value;
2937
+ return !duration || duration < 36e5 ? 0 : String(Math.floor(duration / 36e5)).length;
2938
+ }), currentTimeText = (0, import_vue11.computed)(
2939
+ () => formatPlaybackTime(controlTimestampMs.value, timeHourDigits.value)
2940
+ ), durationTimeText = (0, import_vue11.computed)(
2941
+ () => formatPlaybackTime(resolvedDurationMs.value, timeHourDigits.value)
2942
+ ), controlLayout = (0, import_vue11.computed)(() => {
2943
+ let width = Math.max(1, Math.floor(props.w)), progressY = videoHeight.value, current = currentTimeText.value, duration = durationTimeText.value, timeWidth = Math.max(textCellWidth(current), textCellWidth(duration)), ratesWidth = 8;
2944
+ if (resolvedControlsLayout.value === "cinema") {
2945
+ let ratesX2 = Math.max(3, width - ratesWidth), timeText = `${current} / ${duration}`;
2946
+ return {
2947
+ width,
2948
+ kind: "cinema",
2949
+ progressX: 0,
2950
+ progressY,
2951
+ progressWidth: width,
2952
+ actionY: progressY + 1,
2953
+ ratesX: ratesX2,
2954
+ showAllRates: !0,
2955
+ showTimes: 3 + textCellWidth(timeText) < ratesX2,
2956
+ current,
2957
+ duration,
2958
+ timeText,
2959
+ timeWidth,
2960
+ currentX: 3,
2961
+ totalX: 0
2962
+ };
2963
+ }
2964
+ let ratesX = width - ratesWidth, progressX = timeWidth + 4, totalX = ratesX - timeWidth - 1, progressWidth = totalX - progressX - 1;
2965
+ if (progressWidth >= 4)
2966
+ return {
2967
+ width,
2968
+ kind: "compact",
2969
+ progressX,
2970
+ progressY,
2971
+ progressWidth,
2972
+ actionY: progressY,
2973
+ ratesX,
2974
+ showAllRates: !0,
2975
+ showTimes: !0,
2976
+ current,
2977
+ duration,
2978
+ timeText: "",
2979
+ timeWidth,
2980
+ currentX: 3,
2981
+ totalX
2982
+ };
2983
+ let compactRatesX = Math.max(4, width - 2);
2984
+ return {
2985
+ width,
2986
+ kind: "compact",
2987
+ progressX: 3,
2988
+ progressY,
2989
+ progressWidth: Math.max(1, compactRatesX - 4),
2990
+ actionY: progressY,
2991
+ ratesX: compactRatesX,
2992
+ showAllRates: !1,
2993
+ showTimes: !1,
2994
+ current,
2995
+ duration,
2996
+ timeText: "",
2997
+ timeWidth,
2998
+ currentX: 0,
2999
+ totalX: 0
3000
+ };
3001
+ }), rateStyles = (0, import_vue11.computed)(
3002
+ () => PLAYBACK_RATES.map(
3003
+ (rate) => rate === effectivePlaybackRate.value ? { ...props.style, inverse: !0 } : props.style
3004
+ )
3005
+ ), remainingProgressStyle = (0, import_vue11.computed)(() => ({ ...props.style, dim: !0 })), progressThumbStyle = (0, import_vue11.computed)(() => ({ ...props.style, inverse: !0 })), progressSegments = (0, import_vue11.computed)(() => {
3006
+ let { progressWidth } = controlLayout.value, duration = resolvedDurationMs.value;
3007
+ if (!duration)
3008
+ return { playedWidth: 0, thumbWidth: 0, remainingWidth: progressWidth };
3009
+ let ratio = Math.max(0, Math.min(1, controlTimestampMs.value / duration)), marker = Math.round(ratio * Math.max(0, progressWidth - 1));
3010
+ return {
3011
+ playedWidth: marker,
3012
+ thumbWidth: 1,
3013
+ remainingWidth: progressWidth - marker - 1
3014
+ };
3015
+ }), controlFill = (0, import_vue11.computed)(() => " ".repeat(controlLayout.value.width)), progressGlyphs = (0, import_vue11.computed)(() => ({
3016
+ played: "\u2501".repeat(progressSegments.value.playedWidth),
3017
+ remaining: "\u2500".repeat(progressSegments.value.remainingWidth)
3018
+ })), playbackEnabled = (0, import_vue11.computed)(
3019
+ () => alive && !effectivePaused.value && !graphicsActivity?.scrolling.value && props.src.trim().length > 0 && paintable.value
3020
+ ), shouldPlay = (0, import_vue11.computed)(() => playbackEnabled.value && !seeking.value), visibleFallback = (0, import_vue11.computed)(
3021
+ () => playbackError.value ? `${props.fallback}: ${playbackError.value}` : props.fallback
3022
+ );
3023
+ function timelineTimestamp(timestampMs) {
3024
+ let duration = resolvedDurationMs.value;
3025
+ return duration ? props.loop ? Math.max(0, timestampMs) % duration : Math.max(0, Math.min(duration, timestampMs)) : Math.max(0, timestampMs);
3026
+ }
3027
+ function seekTimestamp(timestampMs) {
3028
+ let duration = resolvedDurationMs.value;
3029
+ if (!duration)
3030
+ return Math.max(0, timestampMs);
3031
+ let end = props.loop ? Math.max(0, duration - 1) : duration;
3032
+ return Math.max(0, Math.min(end, timestampMs));
3033
+ }
3034
+ function updateTimestamp(timestampMs, force = !1) {
3035
+ let next = timelineTimestamp(timestampMs);
3036
+ if (lastTimestampMs = next, !showControls.value)
3037
+ return;
3038
+ let threshold = CONTROL_REFRESH_MS * effectivePlaybackRate.value;
3039
+ (force || next < displayedTimestampMs.value || Math.abs(next - displayedTimestampMs.value) >= threshold) && (displayedTimestampMs.value = next);
3040
+ }
3041
+ function commitFrame(frame, dropped) {
3042
+ if (!alive)
3043
+ return;
3044
+ droppedFrames += dropped, frameRenderer.value = (0, import_vue11.markRaw)(createFrameRenderer(frame, props.w)), updateTimestamp(frame.timestampMs);
3045
+ let durationMs = resolvedDurationMs.value;
3046
+ emit("frame", {
3047
+ timestampMs: frame.timestampMs,
3048
+ pixelWidth: frame.pixelWidth,
3049
+ pixelHeight: frame.pixelHeight,
3050
+ droppedFrames,
3051
+ ...durationMs ? { durationMs } : {},
3052
+ playbackRate: effectivePlaybackRate.value
3053
+ });
3054
+ }
3055
+ let mailbox = createFrameMailbox({
3056
+ scheduler,
3057
+ id: mailboxId,
3058
+ reason: "stream",
3059
+ priority: "low",
3060
+ apply(frame, _context, meta) {
3061
+ commitFrame(frame, meta.dropped), pendingEndedGeneration === generation && (pendingEndedGeneration = null, emit("ended"));
3062
+ }
3063
+ });
3064
+ function stopPlayback() {
3065
+ generation++, pendingEndedGeneration = null;
3066
+ let discardedPendingFrame = mailbox.hasPending();
3067
+ mailbox.cancel(), discardedPendingFrame && (lastQueuedBytes = null, lastQueuedFormat = null, lastQueuedFingerprint = void 0), activeAbort?.abort(), activeAbort = null;
3068
+ }
3069
+ function resetQueuedFrameIdentity() {
3070
+ lastSourceBytes = null, lastQueuedBytes = null, lastQueuedFormat = null, lastQueuedFingerprint = void 0;
3071
+ }
3072
+ function setPaused(paused) {
3073
+ effectivePaused.value !== paused && (props.paused == null && (internalPaused.value = paused), emit("update:paused", paused));
3074
+ }
3075
+ function setPlaybackRate(rate) {
3076
+ let next = playbackRate(rate);
3077
+ effectivePlaybackRate.value !== next && (props.playbackRate == null && (internalPlaybackRate.value = next), emit("update:playbackRate", next));
3078
+ }
3079
+ function applySeek(timestampMs, restart) {
3080
+ let parsed = Number(timestampMs);
3081
+ if (!Number.isFinite(parsed))
3082
+ return;
3083
+ stopPlayback(), resetQueuedFrameIdentity();
3084
+ let next = seekTimestamp(parsed);
3085
+ updateTimestamp(next, !0), seekPreviewMs.value = void 0;
3086
+ let durationMs = resolvedDurationMs.value;
3087
+ emit("seek", {
3088
+ timestampMs: next,
3089
+ ...durationMs ? { durationMs } : {}
3090
+ }), restart && startPlayback(effectivePaused.value);
3091
+ }
3092
+ function controlCell(event) {
3093
+ return {
3094
+ x: Math.floor(event.cellX - layout.originX - props.x),
3095
+ y: Math.floor(event.cellY - layout.originY - props.y)
3096
+ };
3097
+ }
3098
+ function previewSeekAt(cellX) {
3099
+ let duration = resolvedDurationMs.value;
3100
+ if (!duration)
3101
+ return;
3102
+ let { progressX, progressWidth } = controlLayout.value, offset = Math.max(0, Math.min(progressWidth - 1, cellX - progressX));
3103
+ seekPreviewMs.value = progressWidth <= 1 ? 0 : offset / Math.max(1, progressWidth - 1) * duration;
3104
+ }
3105
+ function captureControlPointer(event) {
3106
+ let native = event.nativeEvent, pointerId = native?.pointerId, target = native?.target;
3107
+ pointerId == null || !target?.setPointerCapture || (target.setPointerCapture(pointerId), controlPointerCapture = { pointerId, target });
3108
+ }
3109
+ function releaseControlPointer() {
3110
+ controlPointerCapture && (controlPointerCapture.target.releasePointerCapture?.(controlPointerCapture.pointerId), controlPointerCapture = null);
3111
+ }
3112
+ function rateAt(cellX) {
3113
+ let { ratesX, showAllRates } = controlLayout.value, offset = cellX - ratesX;
3114
+ if (!showAllRates) {
3115
+ if (offset < 0 || offset >= 2)
3116
+ return;
3117
+ let index = PLAYBACK_RATES.indexOf(effectivePlaybackRate.value);
3118
+ return PLAYBACK_RATES[(index + 1) % PLAYBACK_RATES.length];
3119
+ }
3120
+ if (!(offset < 0 || offset % 3 >= 2))
3121
+ return PLAYBACK_RATES[Math.floor(offset / 3)];
3122
+ }
3123
+ function onInteractivePointerDown(event) {
3124
+ if (event.button != null && event.button !== 0)
3125
+ return;
3126
+ let { x: cellX, y: cellY } = controlCell(event);
3127
+ if (cellY < videoHeight.value) {
3128
+ suppressNextVideoClick = !1;
3129
+ return;
3130
+ }
3131
+ if (!showControls.value)
3132
+ return;
3133
+ let { actionY, progressY, progressX, progressWidth } = controlLayout.value, rate = rateAt(cellX);
3134
+ if (cellY === actionY && cellX <= 1) {
3135
+ event.preventDefault(), event.stopPropagation(), suppressNextVideoClick = !0, setPaused(!effectivePaused.value);
3136
+ return;
3137
+ }
3138
+ if (cellY === actionY && rate) {
3139
+ event.preventDefault(), event.stopPropagation(), suppressNextVideoClick = !0, setPlaybackRate(rate);
3140
+ return;
3141
+ }
3142
+ cellY !== progressY || !resolvedDurationMs.value || cellX < progressX || cellX >= progressX + progressWidth || (event.preventDefault(), event.stopPropagation(), suppressNextVideoClick = !0, seeking.value = !0, stopPlayback(), previewSeekAt(cellX), captureControlPointer(event));
3143
+ }
3144
+ function onInteractivePointerMove(event) {
3145
+ if (seeking.value) {
3146
+ if (event.buttons === 0) {
3147
+ onInteractivePointerUp(event);
3148
+ return;
3149
+ }
3150
+ event.preventDefault(), event.stopPropagation(), previewSeekAt(controlCell(event).x);
3151
+ }
3152
+ }
3153
+ function onInteractivePointerUp(event) {
3154
+ if (!seeking.value)
3155
+ return;
3156
+ event.preventDefault(), event.stopPropagation(), previewSeekAt(controlCell(event).x);
3157
+ let timestampMs = seekPreviewMs.value ?? lastTimestampMs;
3158
+ applySeek(timestampMs, !1), seeking.value = !1, releaseControlPointer(), startPlayback(effectivePaused.value);
3159
+ }
3160
+ function onVideoClick(event) {
3161
+ if (!(event.button != null && event.button !== 0)) {
3162
+ if (suppressNextVideoClick) {
3163
+ suppressNextVideoClick = !1, event.preventDefault(), event.stopPropagation();
3164
+ return;
3165
+ }
3166
+ controlCell(event).y >= videoHeight.value || (event.preventDefault(), event.stopPropagation(), setPaused(!effectivePaused.value));
3167
+ }
3168
+ }
3169
+ function finishControlSeek() {
3170
+ if (!seeking.value)
3171
+ return;
3172
+ let timestampMs = seekPreviewMs.value ?? lastTimestampMs;
3173
+ applySeek(timestampMs, !1), seeking.value = !1, releaseControlPointer(), startPlayback(effectivePaused.value);
3174
+ }
3175
+ function onControlKeydown(event) {
3176
+ if (event.key === "Enter" || event.key === " " || event.key === "Spacebar") {
3177
+ event.preventDefault(), event.stopPropagation(), setPaused(!effectivePaused.value);
3178
+ return;
3179
+ }
3180
+ if (event.key === "ArrowUp" || event.key === "ArrowDown") {
3181
+ event.preventDefault(), event.stopPropagation();
3182
+ let index = PLAYBACK_RATES.indexOf(effectivePlaybackRate.value), offset = event.key === "ArrowUp" ? 1 : -1;
3183
+ setPlaybackRate(PLAYBACK_RATES[Math.max(0, Math.min(2, index + offset))]);
3184
+ return;
3185
+ }
3186
+ if (!event.repeat && (event.key === "Home" || event.key === "End") && resolvedDurationMs.value) {
3187
+ event.preventDefault(), event.stopPropagation(), applySeek(event.key === "Home" ? 0 : resolvedDurationMs.value, !0);
3188
+ return;
3189
+ }
3190
+ (event.key === "1" || event.key === "2" || event.key === "3") && (event.preventDefault(), event.stopPropagation(), setPlaybackRate(Number(event.key)));
3191
+ }
3192
+ function queueFrame(frame, expectedFormat) {
3193
+ let normalized = normalizeFrame(frame);
3194
+ if (normalized.format !== expectedFormat)
3195
+ throw new Error(`TVideo frame source did not provide requested ${expectedFormat} frames`);
3196
+ normalized.durationMs != null && normalized.durationMs !== discoveredDurationMs.value && (discoveredDurationMs.value = normalized.durationMs), normalized = { ...normalized, timestampMs: timelineTimestamp(normalized.timestampMs) };
3197
+ let sourceBytes = frameBytes(normalized), reusesSourceBuffer = sourceBytes === lastSourceBytes;
3198
+ lastSourceBytes = sourceBytes;
3199
+ let stableFrame = reusesSourceBuffer ? normalized.format === "gray8" ? { ...normalized, pixels: new Uint8Array(normalized.pixels) } : { ...normalized, png: new Uint8Array(normalized.png) } : normalized, bytes = frameBytes(stableFrame), sameFingerprint = normalized.format === lastQueuedFormat && normalized.fingerprint != null && lastQueuedFingerprint != null && normalized.fingerprint === lastQueuedFingerprint, canCompareBytes = normalized.fingerprint == null && lastQueuedFingerprint == null && !reusesSourceBuffer;
3200
+ if (sameFingerprint || canCompareBytes && normalized.format === lastQueuedFormat && lastQueuedBytes && sameBytes(lastQueuedBytes, sourceBytes)) {
3201
+ lastQueuedBytes = bytes, lastQueuedFormat = normalized.format, lastQueuedFingerprint = normalized.fingerprint, updateTimestamp(normalized.timestampMs), mailbox.hasPending() && mailbox.replacePending(stableFrame);
3202
+ return;
3203
+ }
3204
+ lastQueuedBytes = bytes, lastQueuedFormat = normalized.format, lastQueuedFingerprint = normalized.fingerprint, mailbox.queue(stableFrame) || (commitFrame(stableFrame, 0), scheduler.invalidate({ priority: "low", reason: "stream" }));
3205
+ }
3206
+ function startPlayback(oneFrame = !1) {
3207
+ if (stopPlayback(), !shouldPlay.value && !(oneFrame && alive && props.src.trim().length > 0 && paintable.value && !graphicsActivity?.scrolling.value))
3208
+ return;
3209
+ let currentGeneration = generation, abort = new AbortController();
3210
+ activeAbort = abort, playbackError.value = "";
3211
+ let source = props.frameSource, format = preferredFormat.value, context = {
3212
+ src: props.src,
3213
+ signal: abort.signal,
3214
+ maxFps: resolvedDecodeFps.value,
3215
+ pixelWidth: resolvedDecodeWidth.value,
3216
+ pixelHeight: resolvedDecodeHeight.value,
3217
+ startAtMs: lastTimestampMs,
3218
+ preferredFormat: format,
3219
+ playbackRate: effectivePlaybackRate.value,
3220
+ loop: props.loop
3221
+ };
3222
+ (async () => {
3223
+ try {
3224
+ let frames = await source(context);
3225
+ for await (let frame of frames)
3226
+ if (!alive || abort.signal.aborted || currentGeneration !== generation || (queueFrame(frame, format), oneFrame))
3227
+ return;
3228
+ if (!alive || abort.signal.aborted || currentGeneration !== generation)
3229
+ return;
3230
+ mailbox.hasPending() ? pendingEndedGeneration = currentGeneration : emit("ended");
3231
+ } catch (error) {
3232
+ if (!alive || abort.signal.aborted || currentGeneration !== generation)
3233
+ return;
3234
+ playbackError.value = errorMessage2(error), emit("error", error), scheduler.invalidate({ priority: "low", reason: "data" });
3235
+ } finally {
3236
+ activeAbort === abort && (activeAbort = null);
3237
+ }
3238
+ })();
3239
+ }
3240
+ return (0, import_vue11.watch)(
3241
+ () => props.paused,
3242
+ (paused) => {
3243
+ paused != null && (internalPaused.value = paused);
3244
+ }
3245
+ ), (0, import_vue11.watch)(
3246
+ () => props.playbackRate,
3247
+ (rate) => {
3248
+ rate != null && (internalPlaybackRate.value = playbackRate(rate));
3249
+ }
3250
+ ), (0, import_vue11.watch)(
3251
+ [
3252
+ () => props.src,
3253
+ () => props.frameSource,
3254
+ playbackEnabled,
3255
+ resolvedDecodeFps,
3256
+ resolvedDecodeWidth,
3257
+ resolvedDecodeHeight,
3258
+ preferredFormat,
3259
+ effectivePlaybackRate,
3260
+ () => props.loop
3261
+ ],
3262
+ (next, previous) => {
3263
+ let sourceChanged = !previous || next[0] !== previous[0] || next[1] !== previous[1], formatChanged = !previous || next[6] !== previous[6];
3264
+ (sourceChanged || formatChanged) && (resetQueuedFrameIdentity(), sourceChanged && (lastTimestampMs = 0, displayedTimestampMs.value = 0, discoveredDurationMs.value = void 0, seekPreviewMs.value = void 0, seeking.value = !1, suppressNextVideoClick = !1, releaseControlPointer(), droppedFrames = 0), playbackError.value = "", frameRenderer.value = void 0), startPlayback();
3265
+ },
3266
+ { immediate: !0, flush: "post" }
3267
+ ), (0, import_vue11.onBeforeUnmount)(() => {
3268
+ alive = !1, stopPlayback(), releaseControlPointer(), mailbox.dispose(), unsubscribeTerminalResize(), unsubscribeGraphicsOutput();
3269
+ }), () => {
3270
+ let children = [
3271
+ (0, import_vue11.h)(TAgentTerminalGraphic, {
3272
+ x: props.x,
3273
+ y: props.y,
3274
+ w: props.w,
3275
+ h: videoHeight.value,
3276
+ zIndex: props.zIndex,
3277
+ content: props.src.trim() ? props.src : "video",
3278
+ fallback: visibleFallback.value,
3279
+ style: props.style,
3280
+ clear: props.clear,
3281
+ final: !1,
3282
+ streaming: !0,
3283
+ renderer: frameRenderer.value,
3284
+ placementKey,
3285
+ preserveRawWhileRendering: !0,
3286
+ ignoreSamePlaneRawCoverage: !0,
3287
+ suspended: !paintable.value
3288
+ })
3289
+ ];
3290
+ return props.controls && children.push(
3291
+ (0, import_vue11.h)(
3292
+ TView,
3293
+ {
3294
+ x: props.x,
3295
+ y: props.y,
3296
+ w: Math.max(0, Math.floor(props.w)),
3297
+ h: Math.max(0, Math.floor(props.h)),
3298
+ zIndex: props.zIndex,
3299
+ focusable: !0,
3300
+ selectable: !1,
3301
+ onClick: onVideoClick,
3302
+ onPointerdown: onInteractivePointerDown,
3303
+ onPointermove: onInteractivePointerMove,
3304
+ onPointerup: onInteractivePointerUp,
3305
+ onKeydown: onControlKeydown,
3306
+ onBlur: finishControlSeek
3307
+ },
3308
+ () => {
3309
+ if (!showControls.value)
3310
+ return [];
3311
+ let layout2 = controlLayout.value, segments = progressSegments.value, controls = Array.from(
3312
+ { length: controlRows.value },
3313
+ (_, index) => (0, import_vue11.h)(TText, {
3314
+ x: 0,
3315
+ y: videoHeight.value + index,
3316
+ w: layout2.width,
3317
+ value: controlFill.value,
3318
+ style: props.style
3319
+ })
3320
+ );
3321
+ return controls.push(
3322
+ (0, import_vue11.h)(TText, {
3323
+ x: 0,
3324
+ y: layout2.actionY,
3325
+ w: 2,
3326
+ value: effectivePaused.value ? "> " : "||",
3327
+ style: props.style
3328
+ })
3329
+ ), layout2.showTimes && (layout2.kind === "cinema" ? controls.push(
3330
+ (0, import_vue11.h)(TText, {
3331
+ x: layout2.currentX,
3332
+ y: layout2.actionY,
3333
+ w: textCellWidth(layout2.timeText),
3334
+ value: layout2.timeText,
3335
+ style: props.style
3336
+ })
3337
+ ) : controls.push(
3338
+ (0, import_vue11.h)(TText, {
3339
+ x: layout2.currentX,
3340
+ y: layout2.actionY,
3341
+ w: layout2.timeWidth,
3342
+ value: layout2.current,
3343
+ style: props.style
3344
+ }),
3345
+ (0, import_vue11.h)(TText, {
3346
+ x: layout2.totalX,
3347
+ y: layout2.actionY,
3348
+ w: layout2.timeWidth,
3349
+ value: layout2.duration,
3350
+ style: props.style
3351
+ })
3352
+ )), segments.playedWidth > 0 && controls.push(
3353
+ (0, import_vue11.h)(TText, {
3354
+ x: layout2.progressX,
3355
+ y: layout2.progressY,
3356
+ w: segments.playedWidth,
3357
+ value: progressGlyphs.value.played,
3358
+ style: props.style
3359
+ })
3360
+ ), segments.thumbWidth > 0 && controls.push(
3361
+ (0, import_vue11.h)(TText, {
3362
+ x: layout2.progressX + segments.playedWidth,
3363
+ y: layout2.progressY,
3364
+ w: 1,
3365
+ value: "\u254B",
3366
+ style: progressThumbStyle.value
3367
+ })
3368
+ ), segments.remainingWidth > 0 && controls.push(
3369
+ (0, import_vue11.h)(TText, {
3370
+ x: layout2.progressX + segments.playedWidth + segments.thumbWidth,
3371
+ y: layout2.progressY,
3372
+ w: segments.remainingWidth,
3373
+ value: progressGlyphs.value.remaining,
3374
+ style: remainingProgressStyle.value
3375
+ })
3376
+ ), layout2.showAllRates ? controls.push(
3377
+ ...PLAYBACK_RATES.map(
3378
+ (rate, index) => (0, import_vue11.h)(TText, {
3379
+ x: layout2.ratesX + index * 3,
3380
+ y: layout2.actionY,
3381
+ w: 2,
3382
+ value: `${rate}x`,
3383
+ style: rateStyles.value[index]
3384
+ })
3385
+ )
3386
+ ) : controls.push(
3387
+ (0, import_vue11.h)(TText, {
3388
+ x: layout2.ratesX,
3389
+ y: layout2.actionY,
3390
+ w: 2,
3391
+ value: `${effectivePlaybackRate.value}x`,
3392
+ style: rateStyles.value[PLAYBACK_RATES.indexOf(effectivePlaybackRate.value)]
3393
+ })
3394
+ ), controls;
3395
+ }
3396
+ )
3397
+ ), (0, import_vue11.h)("span", rootProps, children);
3398
+ };
3399
+ }
3400
+ });
3401
+
3402
+ // src/vue/components/TBrowser.ts
3403
+ var EMPTY_RECT2 = Object.freeze({ x: 0, y: 0, w: 0, h: 0 }), tBrowserProps = {
3404
+ x: { type: Number, required: !0 },
3405
+ y: { type: Number, required: !0 },
3406
+ w: { type: Number, required: !0 },
3407
+ h: { type: Number, required: !0 },
3408
+ zIndex: { type: Number, default: 0 },
3409
+ url: { type: String, required: !0 },
3410
+ sessionFactory: {
3411
+ type: Function,
3412
+ required: !0
3413
+ },
3414
+ autoFocus: { type: Boolean, default: !1 },
3415
+ maxFps: { type: Number, default: 60 },
3416
+ pixelWidth: { type: Number, default: void 0 },
3417
+ pixelHeight: { type: Number, default: void 0 },
3418
+ fallback: { type: String, default: "[browser requires terminal graphics]" },
3419
+ style: { type: Object, default: void 0 },
3420
+ clear: { type: Boolean, default: !0 }
3421
+ };
3422
+ function modifiers(event) {
3423
+ return {
3424
+ ctrl: !!event.ctrlKey,
3425
+ shift: !!event.shiftKey,
3426
+ alt: !!event.altKey,
3427
+ meta: !!event.metaKey
3428
+ };
3429
+ }
3430
+ function eventText(event) {
3431
+ return String(event.text ?? event.data ?? "");
3432
+ }
3433
+ function isBrowserShortcut(event) {
3434
+ let key = event.key.toLowerCase();
3435
+ return (event.ctrlKey || event.metaKey) && ["l", "r", "t", "w"].includes(key) || !!event.altKey && (event.key === "ArrowLeft" || event.key === "ArrowRight") || !!event.ctrlKey && (key === "c" || key === "q");
3436
+ }
3437
+ var TBrowser = (0, import_vue12.defineComponent)({
3438
+ name: "TBrowser",
3439
+ props: tBrowserProps,
3440
+ emits: {
3441
+ ready: (_session) => !0,
3442
+ frame: (_event) => !0,
3443
+ navigate: (_url) => !0,
3444
+ titleChange: (_title) => !0,
3445
+ requestAddress: () => !0,
3446
+ close: () => !0,
3447
+ error: (_error) => !0
3448
+ },
3449
+ setup(props, { emit }) {
3450
+ let layout = useLayout(), { events } = useTerminal(), { visible } = useVisibility(), activeSession = null, activePixelWidth = Math.max(1, Math.floor(props.pixelWidth ?? props.w * 8)), activePixelHeight = Math.max(1, Math.floor(props.pixelHeight ?? props.h * 16)), alive = !0, skipNextInput = !1, requestedUrl = props.url, sessionQueue = Promise.resolve(), continuousInputScheduled = !1, continuousInputGeneration = 0, pendingContinuousInput = [], initialUrl = props.url, initialPixelWidth = Math.max(2, Math.floor(props.pixelWidth ?? props.w * 8)), initialPixelHeight = Math.max(2, Math.floor(props.pixelHeight ?? props.h * 16)), rawRect = (0, import_vue12.computed)(
3451
+ () => translateRect(
3452
+ {
3453
+ x: Math.floor(props.x),
3454
+ y: Math.floor(props.y),
3455
+ w: Math.max(0, Math.floor(props.w)),
3456
+ h: Math.max(0, Math.floor(props.h))
3457
+ },
3458
+ layout.originX,
3459
+ layout.originY
3460
+ )
3461
+ ), rect = (0, import_vue12.computed)(() => {
3462
+ let value = rawRect.value;
3463
+ return layout.clipRect ? intersectRect(value, layout.clipRect) ?? EMPTY_RECT2 : value;
3464
+ }), frameSource = async function* (context) {
3465
+ activePixelWidth = context.pixelWidth, activePixelHeight = context.pixelHeight;
3466
+ let session = await props.sessionFactory({
3467
+ url: context.src,
3468
+ signal: context.signal,
3469
+ maxFps: context.maxFps,
3470
+ pixelWidth: context.pixelWidth,
3471
+ pixelHeight: context.pixelHeight,
3472
+ preferredFormat: context.preferredFormat,
3473
+ onNavigate: (url) => emit("navigate", url),
3474
+ onTitleChange: (title) => emit("titleChange", title)
3475
+ });
3476
+ if (context.signal.aborted || !alive) {
3477
+ await session.close();
3478
+ return;
3479
+ }
3480
+ clearContinuousInput(), sessionQueue = Promise.resolve(), activeSession = session;
3481
+ try {
3482
+ if (requestedUrl !== context.src && session.navigate && await session.navigate(requestedUrl), context.signal.aborted || !alive)
3483
+ return;
3484
+ emit("ready", session);
3485
+ for await (let frame of session.frames) {
3486
+ if (context.signal.aborted || !alive)
3487
+ return;
3488
+ yield frame;
3489
+ }
3490
+ } finally {
3491
+ activeSession === session && (activeSession = null, clearContinuousInput()), await session.close();
3492
+ }
3493
+ };
3494
+ function reportError(error) {
3495
+ alive && emit("error", error);
3496
+ }
3497
+ function clearContinuousInput() {
3498
+ pendingContinuousInput.length = 0, continuousInputGeneration++, continuousInputScheduled = !1;
3499
+ }
3500
+ function scheduleContinuousInput(session) {
3501
+ if (continuousInputScheduled || pendingContinuousInput.length === 0)
3502
+ return;
3503
+ let event = pendingContinuousInput.shift(), generation = continuousInputGeneration;
3504
+ continuousInputScheduled = !0;
3505
+ let pending = sessionQueue.then(() => {
3506
+ if (!(generation !== continuousInputGeneration || activeSession !== session))
3507
+ return session.dispatch(event);
3508
+ });
3509
+ sessionQueue = pending.catch((error) => {
3510
+ activeSession === session && reportError(error);
3511
+ });
3512
+ let finish = () => {
3513
+ generation === continuousInputGeneration && (continuousInputScheduled = !1, activeSession === session && scheduleContinuousInput(session));
3514
+ };
3515
+ pending.then(finish, finish);
3516
+ }
3517
+ function queueContinuousInput(session, event) {
3518
+ let index = pendingContinuousInput.findIndex((pending) => pending.type === event.type);
3519
+ if (index < 0)
3520
+ pendingContinuousInput.push(event);
3521
+ else if (event.type === "wheel") {
3522
+ let previous = pendingContinuousInput[index], deltaY = (previous?.type === "wheel" ? previous.deltaY : 0) + event.deltaY;
3523
+ deltaY === 0 ? pendingContinuousInput.splice(index, 1) : pendingContinuousInput[index] = { ...event, deltaY };
3524
+ } else
3525
+ pendingContinuousInput[index] = event;
3526
+ scheduleContinuousInput(session);
3527
+ }
3528
+ function dispatch(event) {
3529
+ let session = activeSession;
3530
+ if (!session)
3531
+ return;
3532
+ if (event.type === "wheel" || event.type === "pointermove") {
3533
+ queueContinuousInput(session, event);
3534
+ return;
3535
+ }
3536
+ clearContinuousInput(), sessionQueue = sessionQueue.then(() => {
3537
+ if (activeSession === session)
3538
+ return session.dispatch(event);
3539
+ }).catch((error) => {
3540
+ activeSession === session && reportError(error);
3541
+ });
3542
+ }
3543
+ function invoke(action) {
3544
+ let session = activeSession;
3545
+ if (!session)
3546
+ return;
3547
+ clearContinuousInput(), sessionQueue = sessionQueue.then(() => {
3548
+ if (activeSession === session)
3549
+ return action(session);
3550
+ }).catch((error) => {
3551
+ activeSession === session && reportError(error);
3552
+ });
3553
+ }
3554
+ function closeCurrentPage() {
3555
+ let session = activeSession;
3556
+ if (!session?.closePage) {
3557
+ emit("close");
3558
+ return;
3559
+ }
3560
+ clearContinuousInput(), sessionQueue = sessionQueue.then(() => {
3561
+ if (activeSession === session)
3562
+ return session.closePage?.();
3563
+ }).then((closed) => {
3564
+ closed === !1 && activeSession === session && emit("close");
3565
+ }).catch((error) => {
3566
+ activeSession === session && reportError(error);
3567
+ });
3568
+ }
3569
+ function point(event) {
3570
+ let bounds = rawRect.value, cellX = Math.max(0, Math.min(bounds.w - 1, Math.floor(event.cellX - bounds.x))), cellY = Math.max(0, Math.min(bounds.h - 1, Math.floor(event.cellY - bounds.y)));
3571
+ return {
3572
+ x: Math.max(
3573
+ 0,
3574
+ Math.min(activePixelWidth - 1, (cellX + 0.5) / bounds.w * activePixelWidth)
3575
+ ),
3576
+ y: Math.max(
3577
+ 0,
3578
+ Math.min(activePixelHeight - 1, (cellY + 0.5) / bounds.h * activePixelHeight)
3579
+ )
3580
+ };
3581
+ }
3582
+ function capture(event) {
3583
+ event.preventDefault(), event.stopPropagation();
3584
+ }
3585
+ function pointer(type, event) {
3586
+ type === "pointerdown" && id.value && events.value?.focus(id.value), capture(event), dispatch({
3587
+ type,
3588
+ ...point(event),
3589
+ button: event.button,
3590
+ buttons: event.buttons,
3591
+ modifiers: modifiers(event)
3592
+ });
3593
+ }
3594
+ let { id } = useTerminalNode(() => ({
3595
+ rect: rect.value,
3596
+ zIndex: props.zIndex,
3597
+ visible: visible.value,
3598
+ focusable: !0,
3599
+ selectable: !1,
3600
+ handlers: {
3601
+ pointerdown: (event) => pointer("pointerdown", event),
3602
+ pointerup: (event) => pointer("pointerup", event),
3603
+ pointermove: (event) => pointer("pointermove", event),
3604
+ wheel: (event) => {
3605
+ capture(event), dispatch({
3606
+ type: "wheel",
3607
+ ...point(event),
3608
+ deltaY: Number(event.deltaY ?? 0),
3609
+ modifiers: modifiers(event)
3610
+ });
3611
+ },
3612
+ keydown: (event) => {
3613
+ if (capture(event), (event.ctrlKey || event.metaKey) && event.key.toLowerCase() === "l") {
3614
+ emit("requestAddress");
3615
+ return;
3616
+ }
3617
+ if ((event.ctrlKey || event.metaKey) && event.key.toLowerCase() === "r") {
3618
+ invoke((session) => session.reload?.());
3619
+ return;
3620
+ }
3621
+ if ((event.ctrlKey || event.metaKey) && event.key.toLowerCase() === "t") {
3622
+ invoke((session) => session.newPage?.()), emit("requestAddress");
3623
+ return;
3624
+ }
3625
+ if ((event.ctrlKey || event.metaKey) && event.key.toLowerCase() === "w") {
3626
+ closeCurrentPage();
3627
+ return;
3628
+ }
3629
+ if (event.altKey && event.key === "ArrowLeft") {
3630
+ invoke((session) => session.back?.());
3631
+ return;
3632
+ }
3633
+ if (event.altKey && event.key === "ArrowRight") {
3634
+ invoke((session) => session.forward?.());
3635
+ return;
3636
+ }
3637
+ if (event.ctrlKey && ["c", "q"].includes(event.key.toLowerCase())) {
3638
+ emit("close");
3639
+ return;
3640
+ }
3641
+ dispatch({
3642
+ type: "keydown",
3643
+ key: event.key,
3644
+ code: event.code,
3645
+ repeat: !!event.repeat,
3646
+ modifiers: modifiers(event)
3647
+ });
3648
+ },
3649
+ keyup: (event) => {
3650
+ capture(event), !isBrowserShortcut(event) && dispatch({
3651
+ type: "keyup",
3652
+ key: event.key,
3653
+ code: event.code,
3654
+ repeat: !!event.repeat,
3655
+ modifiers: modifiers(event)
3656
+ });
3657
+ },
3658
+ paste: (event) => {
3659
+ capture(event);
3660
+ let text = eventText(event);
3661
+ text && dispatch({ type: "paste", text });
3662
+ },
3663
+ compositionend: (event) => {
3664
+ capture(event);
3665
+ let text = eventText(event);
3666
+ text && dispatch({ type: "text", text }), skipNextInput = !0, queueMicrotask(() => {
3667
+ skipNextInput = !1;
3668
+ });
3669
+ },
3670
+ input: (event) => {
3671
+ if (capture(event), skipNextInput)
3672
+ return;
3673
+ let text = eventText(event);
3674
+ text && dispatch({ type: "text", text });
3675
+ }
3676
+ }
3677
+ }));
3678
+ return (0, import_vue12.watchEffect)(() => {
3679
+ !props.autoFocus || !visible.value || !id.value || events.value?.getFocused() !== id.value && events.value?.focus(id.value);
3680
+ }), (0, import_vue12.watch)(
3681
+ () => props.url,
3682
+ (url) => {
3683
+ requestedUrl = url, activeSession?.navigate && invoke((session) => session.navigate?.(url));
3684
+ }
3685
+ ), (0, import_vue12.onBeforeUnmount)(() => {
3686
+ alive = !1, activeSession = null, clearContinuousInput();
3687
+ }), () => (0, import_vue12.h)(TVideo, {
3688
+ x: props.x,
3689
+ y: props.y,
3690
+ w: props.w,
3691
+ h: props.h,
3692
+ zIndex: props.zIndex,
3693
+ src: initialUrl,
3694
+ frameSource,
3695
+ maxFps: props.maxFps,
3696
+ pixelWidth: props.pixelWidth ?? initialPixelWidth,
3697
+ pixelHeight: props.pixelHeight ?? initialPixelHeight,
3698
+ fallback: props.fallback,
3699
+ style: props.style,
3700
+ clear: props.clear,
3701
+ onFrame: (event) => emit("frame", event),
3702
+ onError: (error) => emit("error", error)
3703
+ });
3704
+ }
3705
+ });