@simon_he/vue-tui 1.1.1 → 1.1.2

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 (66) hide show
  1. package/README.md +68 -28
  2. package/dist/{TMermaidText-CXm_L969.js → TMermaidText-frVr8Ysb.js} +1 -1
  3. package/dist/{TSelect-CiyMvwl-.js → TSelect-tJ87rKPM.js} +6 -168
  4. package/dist/{TTree-DKGiuIcM.js → TTree-CGdE-CYu.js} +12 -13
  5. package/dist/agent.cjs +9 -5
  6. package/dist/agent.js +15 -1197
  7. package/dist/{block-source-5CQp4tF8.js → block-source-CrlmaBM5.js} +7 -601
  8. package/dist/cli/input.d.ts +8 -0
  9. package/dist/cli/video/ffmpeg-frame-source.d.ts +10 -0
  10. package/dist/cli/video/png-frame-parser.d.ts +4 -0
  11. package/dist/cli/video/raw-frame-parser.d.ts +1 -0
  12. package/dist/cli/video/yt-dlp-frame-source.d.ts +11 -0
  13. package/dist/cli.cjs +142 -33
  14. package/dist/cli.d.cts +1 -1
  15. package/dist/cli.d.ts +1 -1
  16. package/dist/cli.js +167 -37
  17. package/dist/core.js +5 -6
  18. package/dist/create-terminal-app.d.ts +24 -1
  19. package/dist/{debug-logger-ChY_PXVk.js → debug-logger-CmsGI4of.js} +1 -1
  20. package/dist/{dom-renderer-DNzmg2As.js → dom-renderer-DXx8fWzD.js} +2 -3
  21. package/dist/experimental/3d/bun/contributor-avatar-atlas.d.ts +12 -0
  22. package/dist/experimental/3d/bun/png.d.ts +1 -0
  23. package/dist/experimental/3d/bun/terminal-badge-scene.d.ts +11 -0
  24. package/dist/experimental/3d/bun/terminal-badge.wgsl.d.ts +1 -0
  25. package/dist/experimental/3d/bun/webgpu-renderer.d.ts +26 -0
  26. package/dist/experimental/3d/bun.cjs +7271 -0
  27. package/dist/experimental/3d/bun.d.cts +4 -0
  28. package/dist/experimental/3d/bun.d.ts +4 -0
  29. package/dist/experimental/3d/bun.js +7390 -0
  30. package/dist/experimental/video/node.cjs +497 -0
  31. package/dist/experimental/video/node.d.cts +4 -0
  32. package/dist/experimental/video/node.d.ts +4 -0
  33. package/dist/experimental/video/node.js +610 -0
  34. package/dist/experimental.cjs +3064 -567
  35. package/dist/experimental.d.cts +5 -0
  36. package/dist/experimental.d.ts +5 -0
  37. package/dist/experimental.js +1524 -9
  38. package/dist/{create-terminal-DXuZ2fci.js → hyperlink-_1FAj7Wq.js} +403 -2
  39. package/dist/index.js +15 -16
  40. package/dist/{linkify-CuuquMQT.js → linkify-D68T7rdW.js} +164 -3
  41. package/dist/markdown.js +8 -8
  42. package/dist/{mermaid-CWto52Wk.js → mermaid-BNhM1jAZ.js} +1 -1
  43. package/dist/mermaid.js +3 -3
  44. package/dist/observability.js +2 -2
  45. package/dist/{path-suggest-fPzRsgPv.js → path-suggest-Dndu4dTi.js} +1 -1
  46. package/dist/renderer/terminal-graphics.d.ts +1 -0
  47. package/dist/renderer-dom.js +3 -4
  48. package/dist/runtime.js +2 -2
  49. package/dist/terminal-graphics-Bbe83wSr.js +597 -0
  50. package/dist/{tlog-theme-CopRt9SC.js → tlog-theme-Bul2Na3u.js} +1206 -12
  51. package/dist/{trace-CYHDKM1m.js → trace-Bh8WnoMo.js} +1 -1
  52. package/dist/vue/components/T3DViewport.d.ts +473 -0
  53. package/dist/vue/components/TAgentTerminalGraphic.d.ts +13 -0
  54. package/dist/vue/components/TVideo.d.ts +291 -0
  55. package/dist/vue/video/types.d.ts +39 -0
  56. package/dist/vue.js +17 -18
  57. package/package.json +38 -1
  58. package/dist/hyperlink-B35-O-cW.js +0 -403
  59. /package/dist/{ansi-palette-CNXqFciC.js → ansi-palette-CH6jc2Z7.js} +0 -0
  60. /package/dist/{env-DNCzvX8b.js → env-Cl8qmNFN.js} +0 -0
  61. /package/dist/{frame-perf-BBhE-iuS.js → frame-perf-CHpWhbC4.js} +0 -0
  62. /package/dist/{path-BI9W15Zt.js → path-mnSgEpCm.js} +0 -0
  63. /package/dist/{rect-Ng-3eKzF.js → rect-DUpeDfBg.js} +0 -0
  64. /package/dist/{runtime-D77C03RM.js → runtime-Byf8XXOT.js} +0 -0
  65. /package/dist/{terminal-selection-CQYr--26.js → terminal-selection-4W1SJj4c.js} +0 -0
  66. /package/dist/{wheel-scroll-CQ22Hcyj.js → wheel-scroll-DASkEZr-.js} +0 -0
@@ -17,6 +17,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: !0
17
17
  // src/experimental.ts
18
18
  var experimental_exports = {};
19
19
  __export(experimental_exports, {
20
+ T3DViewport: () => T3DViewport,
20
21
  TCandlestickChart: () => TCandlestickChart,
21
22
  TContributionGraph: () => TContributionGraph,
22
23
  TLineChart: () => TLineChart,
@@ -31,6 +32,7 @@ __export(experimental_exports, {
31
32
  TLogVirtualSearchResults: () => TLogVirtualSearchResults,
32
33
  TPieChart: () => TPieChart,
33
34
  TTranscriptView: () => TTranscriptView,
35
+ TVideo: () => TVideo,
34
36
  TVirtualList: () => TVirtualList,
35
37
  captureTLogViewSessionState: () => captureTLogViewSessionState,
36
38
  createAppendOnlyLogStore: () => createAppendOnlyLogStore,
@@ -780,6 +782,14 @@ function hasInlineAsciiControl(text) {
780
782
  }
781
783
  return !1;
782
784
  }
785
+ function hasTextBlockAsciiControl(text) {
786
+ for (let i = 0; i < text.length; i++) {
787
+ let code = text.charCodeAt(i);
788
+ if (code === 9 || code <= 31 && code !== 10 || code === 127)
789
+ return !0;
790
+ }
791
+ return !1;
792
+ }
783
793
  function forEachGrapheme(text, cb) {
784
794
  if (!text)
785
795
  return;
@@ -842,6 +852,25 @@ function sanitizeInlineText(text) {
842
852
  }
843
853
  return out.join("");
844
854
  }
855
+ function sanitizeTextBlock(text) {
856
+ if (!text)
857
+ return "";
858
+ if (!UNSAFE_FORMAT_CONTROL_RE.test(text) && !hasTextBlockAsciiControl(text))
859
+ return text;
860
+ let out = [];
861
+ out.length = 0;
862
+ for (let ch of text) {
863
+ let cp = ch.codePointAt(0);
864
+ if (cp !== 13) {
865
+ if (cp === 9) {
866
+ out.push(" ");
867
+ continue;
868
+ }
869
+ cp <= 31 && cp !== 10 || cp === 127 || isUnsafeFormatControl(cp) || out.push(ch);
870
+ }
871
+ }
872
+ return out.join("");
873
+ }
845
874
  function textCellWidth(text, provider = currentTextWidthProvider()) {
846
875
  if (!text)
847
876
  return 0;
@@ -1393,8 +1422,8 @@ function applyWheelScroll(state, deltaY, scrollTop, maxTop, now = Date.now(), de
1393
1422
  }
1394
1423
 
1395
1424
  // src/vue/utils/row-scroll.ts
1396
- function exposedRowsForDelta(y0, h15, delta) {
1397
- let startY = Math.floor(y0), height = Math.max(0, Math.floor(h15)), lines = Math.trunc(delta), rows = [];
1425
+ function exposedRowsForDelta(y0, h19, delta) {
1426
+ let startY = Math.floor(y0), height = Math.max(0, Math.floor(h19)), lines = Math.trunc(delta), rows = [];
1398
1427
  if (height <= 0 || lines === 0 || Math.abs(lines) >= height)
1399
1428
  return rows;
1400
1429
  if (lines > 0)
@@ -1406,17 +1435,17 @@ function exposedRowsForDelta(y0, h15, delta) {
1406
1435
  return rows;
1407
1436
  }
1408
1437
  function prepareUnsafeFullRowScroll(options) {
1409
- let r = options.rect, x = Math.floor(r.x), y = Math.floor(r.y), w = Math.floor(r.w), h15 = Math.floor(r.h), rows = Math.floor(options.terminalSize.rows), cols = Math.floor(options.terminalSize.cols), delta = Math.trunc(options.delta);
1410
- if (delta === 0 || h15 <= 0 || cols <= 0 || rows <= 0)
1438
+ let r = options.rect, x = Math.floor(r.x), y = Math.floor(r.y), w = Math.floor(r.w), h19 = Math.floor(r.h), rows = Math.floor(options.terminalSize.rows), cols = Math.floor(options.terminalSize.cols), delta = Math.trunc(options.delta);
1439
+ if (delta === 0 || h19 <= 0 || cols <= 0 || rows <= 0)
1411
1440
  return null;
1412
- let ownsFullRows = x === 0 && w >= cols, withinTerminalRows = y >= 0 && y + h15 <= rows;
1413
- if (!((options.strategy ?? "auto") === "auto" && options.rowScrollMode === "unsafe-full-row" && options.rendererCapabilities.scrollOperations && ownsFullRows && withinTerminalRows && !options.isClipped && Math.abs(delta) < h15 && !options.hasPendingDirtyRows))
1441
+ let ownsFullRows = x === 0 && w >= cols, withinTerminalRows = y >= 0 && y + h19 <= rows;
1442
+ if (!((options.strategy ?? "auto") === "auto" && options.rowScrollMode === "unsafe-full-row" && options.rendererCapabilities.scrollOperations && ownsFullRows && withinTerminalRows && !options.isClipped && Math.abs(delta) < h19 && !options.hasPendingDirtyRows))
1414
1443
  return null;
1415
- let exposedRows = exposedRowsForDelta(y, h15, delta);
1444
+ let exposedRows = exposedRowsForDelta(y, h19, delta);
1416
1445
  return exposedRows.length ? {
1417
1446
  exposedRows,
1418
1447
  apply: () => {
1419
- options.render.unsafeScrollPlaneRows(options.plane, y, y + h15, delta);
1448
+ options.render.unsafeScrollPlaneRows(options.plane, y, y + h19, delta);
1420
1449
  }
1421
1450
  } : null;
1422
1451
  }
@@ -1824,115 +1853,2872 @@ var virtualListInstanceSeq = 0, TVirtualList = (0, import_vue9.defineComponent)(
1824
1853
  },
1825
1854
  keydown: onKeydown
1826
1855
  }
1827
- }));
1828
- (0, import_vue9.watchEffect)(() => {
1829
- if (!props.autoFocus || !visible.value)
1856
+ }));
1857
+ (0, import_vue9.watchEffect)(() => {
1858
+ if (!props.autoFocus || !visible.value)
1859
+ return;
1860
+ let manager = events.value, nodeId = eventNode.id.value;
1861
+ !manager || !nodeId || manager.getFocused() !== nodeId && manager.focus(nodeId);
1862
+ }), (0, import_vue9.watch)(
1863
+ () => visible.value,
1864
+ (nextVisible) => {
1865
+ nextVisible || cancelWheelScrollFrame();
1866
+ }
1867
+ ), (0, import_vue9.onBeforeUnmount)(() => {
1868
+ alive = !1, pendingWheelTop = null, resetWheelScrollState(wheelState), wheelMailbox.dispose(), terminalGraphicsActivity.dispose();
1869
+ });
1870
+ function viewportRows() {
1871
+ let r = normalizedRect(), rows = [];
1872
+ for (let y = r.y; y < r.y + r.h; y++)
1873
+ rows.push(y);
1874
+ return rows;
1875
+ }
1876
+ function unionDirtyRows(nextRows) {
1877
+ if (!dirtyRowsHint?.length)
1878
+ return nextRows.slice().sort((a, b) => a - b);
1879
+ let rows = new Set(dirtyRowsHint);
1880
+ for (let y of nextRows)
1881
+ rows.add(y);
1882
+ return Array.from(rows).sort((a, b) => a - b);
1883
+ }
1884
+ function markRowsDirty(nextRows) {
1885
+ return hasPaintableViewport() ? (dirtyRowsHint = unionDirtyRows(nextRows), renderNodeId && render.markDirtyRows(renderNodeId, dirtyRowsHint) ? !0 : (dirtyRowsHint = void 0, !1)) : !1;
1886
+ }
1887
+ function markViewportDirty() {
1888
+ return markRowsDirty(viewportRows());
1889
+ }
1890
+ function applyScrollTop(nextTop, options) {
1891
+ let controlled = isScrollControlled(), r = normalizedRect(), full = normalizedFullRect();
1892
+ if (r.h <= 0 || full.h <= 0)
1893
+ return { changed: !1, dirty: !1, top: scrollTop.value, controlled };
1894
+ let clampedTop = clampScrollTop(nextTop), delta = clampedTop - scrollTop.value;
1895
+ if (!delta)
1896
+ return { changed: !1, dirty: !1, top: scrollTop.value, controlled };
1897
+ if (controlled)
1898
+ return terminalGraphicsActivity.markScroll(), (options?.emitUpdate ?? !0) && emit("update:scrollTop", clampedTop), options?.emitScroll && emit("scroll", clampedTop), { changed: !0, dirty: !1, top: clampedTop, controlled };
1899
+ terminalGraphicsActivity.markScroll(), scrollTop.value = clampedTop, options?.emitUpdate && emit("update:scrollTop", clampedTop);
1900
+ let canUseTerminalRowScroll = rendererCapabilities.value.scrollOperations && rendererCapabilities.value.domRows !== !0, scrollPlan = prepareUnsafeFullRowScroll({
1901
+ render,
1902
+ plane: plane.value,
1903
+ rect: r,
1904
+ terminalSize: terminal.size(),
1905
+ delta,
1906
+ rowScrollMode: props.rowScrollMode,
1907
+ rendererCapabilities: {
1908
+ scrollOperations: canUseTerminalRowScroll
1909
+ },
1910
+ isClipped: isClipped(),
1911
+ hasPendingDirtyRows: !!dirtyRowsHint?.length,
1912
+ strategy: options?.strategy ?? "viewport-repaint"
1913
+ }), dirty = !1;
1914
+ return scrollPlan && markRowsDirty(scrollPlan.exposedRows) ? (scrollPlan.apply(), dirty = !0) : dirty = markViewportDirty(), options?.emitScroll && emit("scroll", clampedTop), options?.priority && dirty && invalidateSelf(options.priority, options.reason ?? "scroll"), { changed: !0, dirty, top: clampedTop, controlled };
1915
+ }
1916
+ let renderNode = useRenderNode(() => ({
1917
+ zIndex: props.zIndex,
1918
+ rect: visible.value ? normalizedRect() : { x: 0, y: 0, w: 0, h: 0 },
1919
+ deps: [
1920
+ visible.value,
1921
+ absRect.value,
1922
+ fullRect.value,
1923
+ itemCount.value,
1924
+ props.itemVersion,
1925
+ props.getItem,
1926
+ props.renderItem,
1927
+ active.value,
1928
+ focused.value,
1929
+ props.style,
1930
+ props.activeStyle,
1931
+ defaultStyle.value
1932
+ ],
1933
+ paint: (dirtyRows) => {
1934
+ if (dirtyRowsHint = void 0, !visible.value)
1935
+ return;
1936
+ let r = normalizedRect(), full = normalizedFullRect();
1937
+ if (r.w <= 0 || r.h <= 0)
1938
+ return;
1939
+ let base = props.style ?? defaultStyle.value, activeStyle = props.activeStyle ?? defaultActiveStyle(base), top = visibleWindow.value.top, { x: clipX, y: clipY } = clipOffsets(), paintRow = (y) => {
1940
+ if (y < r.y || y >= r.y + r.h)
1941
+ return;
1942
+ let idx = top + clipY + (y - r.y), fullLine = formatInlineCellLine(
1943
+ idx >= 0 && idx < itemCount.value ? itemText(idx) : "",
1944
+ full.w
1945
+ ), line = padEndByCells(sliceByCellsRange(fullLine, clipX, clipX + r.w), r.w), style = idx >= 0 && idx < itemCount.value && idx === active.value ? activeStyle : base;
1946
+ terminal.write(line, { x: r.x, y, style });
1947
+ }, rows = dirtyRows;
1948
+ if (rows?.length) {
1949
+ for (let y of rows)
1950
+ paintRow(y);
1951
+ return;
1952
+ }
1953
+ for (let y = r.y; y < r.y + r.h; y++)
1954
+ paintRow(y);
1955
+ }
1956
+ }));
1957
+ return (0, import_vue9.watchEffect)(() => {
1958
+ renderNodeId = renderNode.id.value;
1959
+ }), () => (0, import_vue9.h)("span", rootProps);
1960
+ }
1961
+ });
1962
+
1963
+ // src/vue/components/T3DViewport.ts
1964
+ var import_vue14 = require("vue");
1965
+
1966
+ // src/vue/components/TVideo.ts
1967
+ var import_vue13 = require("vue");
1968
+
1969
+ // src/core/ansi/sgr.ts
1970
+ var ESC = "\x1B";
1971
+ function ansi16ToColorName(code) {
1972
+ switch (code) {
1973
+ case 30:
1974
+ return "black";
1975
+ case 31:
1976
+ return "red";
1977
+ case 32:
1978
+ return "green";
1979
+ case 33:
1980
+ return "yellow";
1981
+ case 34:
1982
+ return "blue";
1983
+ case 35:
1984
+ return "magenta";
1985
+ case 36:
1986
+ return "cyan";
1987
+ case 37:
1988
+ return "white";
1989
+ case 90:
1990
+ return "blackBright";
1991
+ case 91:
1992
+ return "redBright";
1993
+ case 92:
1994
+ return "greenBright";
1995
+ case 93:
1996
+ return "yellowBright";
1997
+ case 94:
1998
+ return "blueBright";
1999
+ case 95:
2000
+ return "magentaBright";
2001
+ case 96:
2002
+ return "cyanBright";
2003
+ case 97:
2004
+ return "whiteBright";
2005
+ default:
2006
+ return;
2007
+ }
2008
+ }
2009
+ function ansi16BgToColorName(code) {
2010
+ let fgCode = code >= 40 && code <= 47 || code >= 100 && code <= 107 ? code - 10 : null;
2011
+ if (fgCode != null)
2012
+ return ansi16ToColorName(fgCode);
2013
+ }
2014
+ var ANSI16_RGB = {
2015
+ black: { r: 0, g: 0, b: 0 },
2016
+ red: { r: 201, g: 27, b: 0 },
2017
+ green: { r: 0, g: 194, b: 0 },
2018
+ yellow: { r: 199, g: 196, b: 0 },
2019
+ blue: { r: 2, g: 37, b: 199 },
2020
+ magenta: { r: 201, g: 48, b: 199 },
2021
+ cyan: { r: 0, g: 197, b: 199 },
2022
+ white: { r: 199, g: 199, b: 199 },
2023
+ blackBright: { r: 104, g: 104, b: 104 },
2024
+ redBright: { r: 255, g: 110, b: 103 },
2025
+ greenBright: { r: 95, g: 250, b: 104 },
2026
+ yellowBright: { r: 255, g: 252, b: 103 },
2027
+ blueBright: { r: 104, g: 113, b: 255 },
2028
+ magentaBright: { r: 255, g: 118, b: 255 },
2029
+ cyanBright: { r: 95, g: 253, b: 255 },
2030
+ whiteBright: { r: 255, g: 255, b: 255 }
2031
+ };
2032
+ function nearestAnsi16(r, g, b) {
2033
+ let best = "white", bestDist = Number.POSITIVE_INFINITY;
2034
+ for (let [name, rgb] of Object.entries(ANSI16_RGB)) {
2035
+ let dr = r - rgb.r, dg = g - rgb.g, db = b - rgb.b, d = dr * dr + dg * dg + db * db;
2036
+ d < bestDist && (bestDist = d, best = name);
2037
+ }
2038
+ return best;
2039
+ }
2040
+ function ansi256ToRgb(index) {
2041
+ let n = Math.max(0, Math.min(255, Math.trunc(index)));
2042
+ if (n < 16) {
2043
+ let name = [
2044
+ "black",
2045
+ "red",
2046
+ "green",
2047
+ "yellow",
2048
+ "blue",
2049
+ "magenta",
2050
+ "cyan",
2051
+ "white",
2052
+ "blackBright",
2053
+ "redBright",
2054
+ "greenBright",
2055
+ "yellowBright",
2056
+ "blueBright",
2057
+ "magentaBright",
2058
+ "cyanBright",
2059
+ "whiteBright"
2060
+ ][n] ?? "white";
2061
+ return ANSI16_RGB[name];
2062
+ }
2063
+ if (n >= 232) {
2064
+ let c = 8 + (n - 232) * 10;
2065
+ return { r: c, g: c, b: c };
2066
+ }
2067
+ let i = n - 16, rr = Math.floor(i / 36), gg = Math.floor(i % 36 / 6), bb = i % 6, toComponent = (v) => v === 0 ? 0 : 55 + v * 40;
2068
+ return { r: toComponent(rr), g: toComponent(gg), b: toComponent(bb) };
2069
+ }
2070
+ function applyAnsiSgrStyle(current, codes) {
2071
+ let next = { ...current };
2072
+ for (let i = 0; i < codes.length; i++) {
2073
+ let code = codes[i];
2074
+ if (code === 0) {
2075
+ next = {};
2076
+ continue;
2077
+ }
2078
+ if (code === 1)
2079
+ next = { ...next, bold: !0 };
2080
+ else if (code === 2)
2081
+ next = { ...next, dim: !0 };
2082
+ else if (code === 3)
2083
+ next = { ...next, italic: !0 };
2084
+ else if (code === 4)
2085
+ next = { ...next, underline: !0 };
2086
+ else if (code === 7)
2087
+ next = { ...next, inverse: !0 };
2088
+ else if (code === 22)
2089
+ next = { ...next, bold: !1, dim: !1 };
2090
+ else if (code === 23)
2091
+ next = { ...next, italic: !1 };
2092
+ else if (code === 24)
2093
+ next = { ...next, underline: !1 };
2094
+ else if (code === 27)
2095
+ next = { ...next, inverse: !1 };
2096
+ else if (code === 39)
2097
+ next = { ...next, fg: void 0 };
2098
+ else if (code === 49)
2099
+ next = { ...next, bg: void 0 };
2100
+ else if (code >= 30 && code <= 37 || code >= 90 && code <= 97) {
2101
+ let fg = ansi16ToColorName(code);
2102
+ next = { ...next, fg: fg ?? next.fg };
2103
+ } else if (code >= 40 && code <= 47 || code >= 100 && code <= 107) {
2104
+ let bg = ansi16BgToColorName(code);
2105
+ next = { ...next, bg: bg ?? next.bg };
2106
+ } else if (code === 38 || code === 48) {
2107
+ let mode = codes[i + 1];
2108
+ if (mode === 5) {
2109
+ let idx = codes[i + 2];
2110
+ if (idx != null) {
2111
+ let { r, g, b } = ansi256ToRgb(idx), name = nearestAnsi16(r, g, b);
2112
+ next = code === 38 ? { ...next, fg: name } : { ...next, bg: name };
2113
+ }
2114
+ i += 2;
2115
+ } else if (mode === 2) {
2116
+ let r = codes[i + 2], g = codes[i + 3], b = codes[i + 4];
2117
+ if (r != null && g != null && b != null) {
2118
+ let name = nearestAnsi16(r, g, b);
2119
+ next = code === 38 ? { ...next, fg: name } : { ...next, bg: name };
2120
+ }
2121
+ i += 4;
2122
+ }
2123
+ }
2124
+ }
2125
+ return next;
2126
+ }
2127
+ function parseAnsiSgr(input, baseStyle = {}) {
2128
+ let segments = [], style = { ...baseStyle }, lastIndex = 0;
2129
+ for (let i = 0; i < input.length; i++) {
2130
+ if (input[i] !== ESC || input[i + 1] !== "[")
2131
+ continue;
2132
+ let j = i + 2;
2133
+ for (; j < input.length; ) {
2134
+ let c = input.charCodeAt(j);
2135
+ if (c >= 48 && c <= 57 || c === 59) {
2136
+ j++;
2137
+ continue;
2138
+ }
2139
+ break;
2140
+ }
2141
+ if (j >= input.length || input[j] !== "m")
2142
+ continue;
2143
+ i > lastIndex && segments.push({ text: input.slice(lastIndex, i), style });
2144
+ let codes = input.slice(i + 2, j).split(";").filter(Boolean).map((n) => Number.parseInt(n, 10)).filter((n) => Number.isFinite(n));
2145
+ style = applyAnsiSgrStyle(style, codes.length ? codes : [0]), lastIndex = j + 1, i = j;
2146
+ }
2147
+ return lastIndex < input.length && segments.push({ text: input.slice(lastIndex), style }), segments;
2148
+ }
2149
+
2150
+ // src/core/terminal/create-terminal.ts
2151
+ 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");
2152
+ function getRootTerminal(terminal) {
2153
+ return terminal[TERMINAL_ROOT] ?? terminal;
2154
+ }
2155
+
2156
+ // src/renderer/terminal-graphics.ts
2157
+ var ESC2 = "\x1B", BEL = "\x07", ST = `${ESC2}\\`, 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 = 1e4, TERMINAL_GRAPHICS_REGISTRY = Symbol.for("@simon_he/vue-tui:v1:terminal-graphics"), terminalGraphicsGlobal = globalThis, terminalGraphicsRegistry = terminalGraphicsGlobal[TERMINAL_GRAPHICS_REGISTRY] ?? {
2158
+ outputs: /* @__PURE__ */ new WeakMap(),
2159
+ outputVersions: /* @__PURE__ */ new WeakMap(),
2160
+ outputListeners: /* @__PURE__ */ new WeakMap()
2161
+ };
2162
+ terminalGraphicsGlobal[TERMINAL_GRAPHICS_REGISTRY] = terminalGraphicsRegistry;
2163
+ var terminalGraphicsOutputs = terminalGraphicsRegistry.outputs, terminalGraphicsOutputVersions = terminalGraphicsRegistry.outputVersions, terminalGraphicsOutputListeners = terminalGraphicsRegistry.outputListeners;
2164
+ function getTerminalGraphicsOutput(terminal) {
2165
+ return terminalGraphicsOutputs.get(getRootTerminal(terminal)) ?? null;
2166
+ }
2167
+ function getTerminalGraphicsOutputVersion(terminal) {
2168
+ return terminalGraphicsOutputVersions.get(getRootTerminal(terminal)) ?? 0;
2169
+ }
2170
+ function subscribeTerminalGraphicsOutput(terminal, listener) {
2171
+ let rootTerminal = getRootTerminal(terminal), listeners = terminalGraphicsOutputListeners.get(rootTerminal);
2172
+ return listeners || (listeners = /* @__PURE__ */ new Set(), terminalGraphicsOutputListeners.set(rootTerminal, listeners)), listeners.add(listener), () => {
2173
+ listeners.delete(listener), listeners.size === 0 && terminalGraphicsOutputListeners.delete(rootTerminal);
2174
+ };
2175
+ }
2176
+ function isTerminalGraphicsProtocol(value) {
2177
+ return value === "kitty" || value === "iterm2" || value === "sixel";
2178
+ }
2179
+ function stableTerminalGraphicNumericId(input, options = {}) {
2180
+ let min = Math.floor(options.min ?? 1), max = Math.floor(options.max ?? 2147483647), span = Math.max(1, max - min + 1), hash = 2166136261;
2181
+ for (let index = 0; index < input.length; index += 1)
2182
+ hash ^= input.charCodeAt(index), hash = Math.imul(hash, 16777619);
2183
+ return min + (hash >>> 0) % span;
2184
+ }
2185
+ function positiveGraphicInt(value, max) {
2186
+ let n = Math.trunc(Number(value));
2187
+ return !Number.isFinite(n) || n <= 0 ? null : Math.min(max, n);
2188
+ }
2189
+ function normalizeTerminalGraphicSize(width, height) {
2190
+ let w = positiveGraphicInt(width, MAX_TERMINAL_GRAPHIC_CELLS), h19 = positiveGraphicInt(height, MAX_TERMINAL_GRAPHIC_CELLS);
2191
+ return w == null || h19 == null || w * h19 > MAX_TERMINAL_GRAPHIC_CELLS ? null : { width: w, height: h19 };
2192
+ }
2193
+ function canDrawTerminalGraphicRect(rect, size) {
2194
+ 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));
2195
+ return graphicSize != null && cols > 0 && rows > 0 && Number.isFinite(x) && Number.isFinite(y) && x >= 0 && y >= 0 && x < cols && y < rows;
2196
+ }
2197
+ function withoutNestedEscapes(body) {
2198
+ return !body.includes(ESC2) && !body.includes(BEL);
2199
+ }
2200
+ function isBase64ish(value) {
2201
+ return /^[A-Za-z0-9+/=]*$/.test(value);
2202
+ }
2203
+ function parseKittyControls(raw) {
2204
+ let out = /* @__PURE__ */ new Map();
2205
+ if (!/^[A-Za-z0-9_,=+.\-:]*$/.test(raw))
2206
+ return null;
2207
+ for (let part of raw.split(",")) {
2208
+ if (!part)
2209
+ continue;
2210
+ let eq = part.indexOf("=");
2211
+ if (eq <= 0)
2212
+ return null;
2213
+ let key = part.slice(0, eq), value = part.slice(eq + 1);
2214
+ if (!/^[A-Za-z]$/.test(key) || !/^[A-Za-z0-9+.\-:]*$/.test(value))
2215
+ return null;
2216
+ out.set(key, value);
2217
+ }
2218
+ return out;
2219
+ }
2220
+ function parseKittyPackets(sequence) {
2221
+ let packets = [], index = 0;
2222
+ for (; index < sequence.length; ) {
2223
+ if (!sequence.startsWith(`${ESC2}_G`, index))
2224
+ return null;
2225
+ let end = sequence.indexOf(ST, index + 3);
2226
+ if (end < 0)
2227
+ return null;
2228
+ let body = sequence.slice(index + 3, end);
2229
+ if (!withoutNestedEscapes(body))
2230
+ return null;
2231
+ let semicolon = body.indexOf(";"), rawControls = semicolon >= 0 ? body.slice(0, semicolon) : body, payload = semicolon >= 0 ? body.slice(semicolon + 1) : "", controls = parseKittyControls(rawControls);
2232
+ if (!controls || payload && !isBase64ish(payload))
2233
+ return null;
2234
+ packets.push({ controls, payload }), index = end + ST.length;
2235
+ }
2236
+ return packets.length ? packets : null;
2237
+ }
2238
+ var KITTY_DRAW_FIRST_CONTROL_KEYS = /* @__PURE__ */ new Set([
2239
+ "a",
2240
+ "f",
2241
+ "q",
2242
+ "C",
2243
+ "i",
2244
+ "I",
2245
+ "p",
2246
+ "c",
2247
+ "r",
2248
+ "x",
2249
+ "y",
2250
+ "w",
2251
+ "h",
2252
+ "z",
2253
+ "m",
2254
+ "t"
2255
+ ]), KITTY_DRAW_CONTINUATION_CONTROL_KEYS = /* @__PURE__ */ new Set(["a", "q", "m"]), KITTY_CLEAR_CONTROL_KEYS = /* @__PURE__ */ new Set(["a", "d", "i", "I", "p", "q"]);
2256
+ function kittyControlsUseOnly(controls, allowed) {
2257
+ for (let key of controls.keys())
2258
+ if (!allowed.has(key))
2259
+ return !1;
2260
+ return !0;
2261
+ }
2262
+ var KITTY_UINT32_MAX = 4294967295, KITTY_INT32_MIN = -2147483648, KITTY_INT32_MAX = 2147483647;
2263
+ function kittyControlIsUint32(controls, key, min = 0) {
2264
+ let value = controls.get(key);
2265
+ if (value == null)
2266
+ return !0;
2267
+ if (!/^\d+$/.test(value))
2268
+ return !1;
2269
+ let n = Number(value);
2270
+ return Number.isSafeInteger(n) && n >= min && n <= KITTY_UINT32_MAX;
2271
+ }
2272
+ function kittyControlIsInt32(controls, key) {
2273
+ let value = controls.get(key);
2274
+ if (value == null)
2275
+ return !0;
2276
+ if (!/^-?\d+$/.test(value))
2277
+ return !1;
2278
+ let n = Number(value);
2279
+ return Number.isSafeInteger(n) && n >= KITTY_INT32_MIN && n <= KITTY_INT32_MAX;
2280
+ }
2281
+ function kittyControlPositiveInt(controls, key, fallback) {
2282
+ let value = controls.get(key);
2283
+ if (value == null)
2284
+ return fallback;
2285
+ if (!/^\d+$/.test(value))
2286
+ return null;
2287
+ let n = Number(value);
2288
+ return Number.isSafeInteger(n) && n >= 1 ? n : null;
2289
+ }
2290
+ function kittyControlIsTerminalGraphicCellsBounded(controls) {
2291
+ let columns = kittyControlPositiveInt(controls, "c", 1), rows = kittyControlPositiveInt(controls, "r", 1);
2292
+ return columns != null && rows != null && columns * rows <= MAX_TERMINAL_GRAPHIC_CELLS;
2293
+ }
2294
+ function validateKittySharedSafeControls(controls) {
2295
+ let q = controls.get("q");
2296
+ if (q != null && !/^[0-2]$/.test(q))
2297
+ return !1;
2298
+ let cursorMove = controls.get("C");
2299
+ if (cursorMove != null && !/^[01]$/.test(cursorMove))
2300
+ return !1;
2301
+ for (let key of ["i", "I", "p"])
2302
+ if (!kittyControlIsUint32(controls, key))
2303
+ return !1;
2304
+ for (let key of ["c", "r"])
2305
+ if (!kittyControlIsUint32(controls, key, 1))
2306
+ return !1;
2307
+ if (!kittyControlIsTerminalGraphicCellsBounded(controls))
2308
+ return !1;
2309
+ for (let key of ["x", "y"])
2310
+ if (!kittyControlIsUint32(controls, key))
2311
+ return !1;
2312
+ for (let key of ["w", "h"])
2313
+ if (!kittyControlIsUint32(controls, key, 1))
2314
+ return !1;
2315
+ if (!kittyControlIsInt32(controls, "z"))
2316
+ return !1;
2317
+ let transmissionMedium = controls.get("t");
2318
+ return !(transmissionMedium != null && transmissionMedium !== "d");
2319
+ }
2320
+ function validateKittySequence(sequence, op = "draw") {
2321
+ let packets = parseKittyPackets(sequence);
2322
+ if (!packets)
2323
+ return !1;
2324
+ if (op === "clear") {
2325
+ if (packets.length !== 1)
2326
+ return !1;
2327
+ let packet = packets[0];
2328
+ if (!kittyControlsUseOnly(packet.controls, KITTY_CLEAR_CONTROL_KEYS) || !validateKittySharedSafeControls(packet.controls) || packet.payload || packet.controls.get("a") !== "d")
2329
+ return !1;
2330
+ let d = packet.controls.get("d");
2331
+ return d == null || /^[aAcCiI]$/.test(d);
2332
+ }
2333
+ let first = packets[0];
2334
+ if (!kittyControlsUseOnly(first.controls, KITTY_DRAW_FIRST_CONTROL_KEYS) || !validateKittySharedSafeControls(first.controls))
2335
+ return !1;
2336
+ if (first.controls.get("a") === "p")
2337
+ return !(packets.length !== 1 || first.payload || !first.controls.has("i") && !first.controls.has("I"));
2338
+ if (first.controls.get("a") !== "T" || !first.payload)
2339
+ return !1;
2340
+ let f = first.controls.get("f");
2341
+ if (f != null && f !== "24" && f !== "32" && f !== "100")
2342
+ return !1;
2343
+ let firstMore = first.controls.get("m");
2344
+ if (firstMore != null && firstMore !== "0" && firstMore !== "1" || packets.length > 1 && firstMore !== "1")
2345
+ return !1;
2346
+ for (let i = 1; i < packets.length; i++) {
2347
+ let packet = packets[i];
2348
+ if (!kittyControlsUseOnly(packet.controls, KITTY_DRAW_CONTINUATION_CONTROL_KEYS) || !validateKittySharedSafeControls(packet.controls))
2349
+ return !1;
2350
+ let action = packet.controls.get("a");
2351
+ if (action != null && action !== "T")
2352
+ return !1;
2353
+ let m = packet.controls.get("m");
2354
+ if (m !== "0" && m !== "1" || !packet.payload && !(i === packets.length - 1 && m === "0"))
2355
+ return !1;
2356
+ }
2357
+ return !(packets.length > 1 && packets[packets.length - 1].controls.get("m") === "1");
2358
+ }
2359
+ function validateIterm2Dimension(value) {
2360
+ return /^auto$/i.test(value) || /^(?:[1-9]\d{0,4})(?:px|%)?$/.test(value);
2361
+ }
2362
+ function validateIterm2Params(params) {
2363
+ let seen = /* @__PURE__ */ new Set(), inline = !1;
2364
+ for (let part of params.split(";").filter(Boolean)) {
2365
+ let eq = part.indexOf("=");
2366
+ if (eq <= 0)
2367
+ return !1;
2368
+ let key = part.slice(0, eq), value = part.slice(eq + 1);
2369
+ if (seen.has(key))
2370
+ return !1;
2371
+ switch (seen.add(key), key) {
2372
+ case "inline":
2373
+ if (value !== "1")
2374
+ return !1;
2375
+ inline = !0;
2376
+ break;
2377
+ case "width":
2378
+ case "height":
2379
+ if (!validateIterm2Dimension(value))
2380
+ return !1;
2381
+ break;
2382
+ case "preserveAspectRatio":
2383
+ case "doNotMoveCursor":
2384
+ if (!/^[01]$/.test(value))
2385
+ return !1;
2386
+ break;
2387
+ default:
2388
+ return !1;
2389
+ }
2390
+ }
2391
+ return inline;
2392
+ }
2393
+ function validateIterm2Sequence(sequence, op = "draw") {
2394
+ if (op === "clear")
2395
+ return !1;
2396
+ let index = 0;
2397
+ for (; index < sequence.length; ) {
2398
+ let prefix = `${ESC2}]1337;File=`;
2399
+ if (!sequence.startsWith(prefix, index))
2400
+ return !1;
2401
+ 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;
2402
+ if (end < 0)
2403
+ return !1;
2404
+ let body = sequence.slice(index + `${ESC2}]1337;`.length, end);
2405
+ if (!body.startsWith("File=") || !withoutNestedEscapes(body))
2406
+ return !1;
2407
+ let colon = body.indexOf(":");
2408
+ if (colon < 0)
2409
+ return !1;
2410
+ let params = body.slice(5, colon), payload = body.slice(colon + 1);
2411
+ if (!/^[A-Za-z0-9_=;,.%+\-:]*$/.test(params) || !payload || !isBase64ish(payload) || !validateIterm2Params(params))
2412
+ return !1;
2413
+ index = end + (end === stEnd ? ST.length : BEL.length);
2414
+ }
2415
+ return sequence.length > 0;
2416
+ }
2417
+ function validateSixelSequence(sequence, op = "draw") {
2418
+ if (op === "clear")
2419
+ return !1;
2420
+ let index = 0;
2421
+ for (; index < sequence.length; ) {
2422
+ if (!sequence.startsWith(`${ESC2}P`, index))
2423
+ return !1;
2424
+ let end = sequence.indexOf(ST, index + 2);
2425
+ if (end < 0)
2426
+ return !1;
2427
+ let body = sequence.slice(index + 2, end);
2428
+ if (!withoutNestedEscapes(body))
2429
+ return !1;
2430
+ for (let i = 0; i < body.length; i++) {
2431
+ let code = body.charCodeAt(i);
2432
+ if (code < 32 || code > 126)
2433
+ return !1;
2434
+ }
2435
+ let q = body.indexOf("q");
2436
+ if (q < 0 || q > 32)
2437
+ return !1;
2438
+ let introducer = body.slice(0, q);
2439
+ if (!/^[0-9;?]*$/.test(introducer) || !body.slice(q + 1).length)
2440
+ return !1;
2441
+ index = end + ST.length;
2442
+ }
2443
+ return sequence.length > 0;
2444
+ }
2445
+ function stripTerminalControlChars(value) {
2446
+ let out = "";
2447
+ for (let index = 0; index < value.length; index++) {
2448
+ let code = value.charCodeAt(index);
2449
+ code <= 8 || code === 11 || code === 12 || code >= 14 && code <= 31 || code === 127 || code >= 128 && code <= 159 || (out += value[index]);
2450
+ }
2451
+ return out;
2452
+ }
2453
+ function sanitizeTerminalFallbackText(text) {
2454
+ return stripTerminalControlChars(
2455
+ 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, "")
2456
+ ).slice(0, MAX_TERMINAL_GRAPHICS_FALLBACK_CHARS);
2457
+ }
2458
+ function isSafeTerminalGraphicsSequence(sequence, protocol, op = "draw") {
2459
+ 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);
2460
+ }
2461
+ function uint32Control(key, value, min = 0) {
2462
+ if (value == null)
2463
+ return "";
2464
+ let n = Math.floor(value);
2465
+ return Number.isSafeInteger(n) && n >= min && n <= KITTY_UINT32_MAX ? `${key}=${n}` : "";
2466
+ }
2467
+ function int32Control(key, value) {
2468
+ if (value == null)
2469
+ return "";
2470
+ let n = Math.floor(value);
2471
+ return Number.isSafeInteger(n) && n >= KITTY_INT32_MIN && n <= KITTY_INT32_MAX ? `${key}=${n}` : "";
2472
+ }
2473
+ function sanitizeBase64(value) {
2474
+ let data = String(value ?? "").replace(/\s+/g, "");
2475
+ return isBase64ish(data) ? data : "";
2476
+ }
2477
+ function kittyGraphicCellControls(columns, rows) {
2478
+ if (columns == null && rows == null)
2479
+ return [];
2480
+ let size = normalizeTerminalGraphicSize(columns ?? 1, rows ?? 1);
2481
+ return size ? [columns == null ? "" : `c=${size.width}`, rows == null ? "" : `r=${size.height}`] : [];
2482
+ }
2483
+ function kittyGraphicSourceControls(sourceX, sourceY, sourceWidth, sourceHeight) {
2484
+ return [
2485
+ uint32Control("x", sourceX),
2486
+ uint32Control("y", sourceY),
2487
+ uint32Control("w", sourceWidth, 1),
2488
+ uint32Control("h", sourceHeight, 1)
2489
+ ];
2490
+ }
2491
+ function chunkBase64(value, chunkSize) {
2492
+ let normalizedSize = Math.max(4, Math.floor(chunkSize / 4) * 4), chunks = [];
2493
+ for (let index = 0; index < value.length; index += normalizedSize)
2494
+ chunks.push(value.slice(index, index + normalizedSize));
2495
+ return chunks.length ? chunks : [""];
2496
+ }
2497
+ function createKittyPlacementSequence(options) {
2498
+ let imageId = uint32Control("i", options.imageId), imageNumber = uint32Control("I", options.imageNumber);
2499
+ if (!imageId && !imageNumber)
2500
+ return "";
2501
+ let controls = [
2502
+ "a=p",
2503
+ options.quiet === !1 ? "" : "q=2",
2504
+ options.noCursorMove === !1 ? "" : "C=1",
2505
+ imageId,
2506
+ imageNumber,
2507
+ uint32Control("p", options.placementId),
2508
+ ...kittyGraphicCellControls(options.columns, options.rows),
2509
+ ...kittyGraphicSourceControls(
2510
+ options.sourceX,
2511
+ options.sourceY,
2512
+ options.sourceWidth,
2513
+ options.sourceHeight
2514
+ ),
2515
+ int32Control("z", options.zIndex)
2516
+ ].filter(Boolean);
2517
+ return `${ESC2}_G${controls.join(",")}${ST}`;
2518
+ }
2519
+ function createKittyGraphicsSequence(base64Png, options = {}) {
2520
+ let data = sanitizeBase64(base64Png);
2521
+ if (!data)
2522
+ return "";
2523
+ let chunks = chunkBase64(data, options.chunkSize ?? 4096), baseControls = [
2524
+ "a=T",
2525
+ "f=100",
2526
+ options.quiet === !1 ? "" : "q=2",
2527
+ options.noCursorMove === !1 ? "" : "C=1",
2528
+ uint32Control("i", options.imageId),
2529
+ uint32Control("I", options.imageNumber),
2530
+ uint32Control("p", options.placementId),
2531
+ ...kittyGraphicCellControls(options.columns, options.rows),
2532
+ ...kittyGraphicSourceControls(
2533
+ options.sourceX,
2534
+ options.sourceY,
2535
+ options.sourceWidth,
2536
+ options.sourceHeight
2537
+ ),
2538
+ int32Control("z", options.zIndex)
2539
+ ].filter(Boolean);
2540
+ return chunks.map((chunk, index) => {
2541
+ 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);
2542
+ return `${ESC2}_G${controls.filter(Boolean).join(",")};${chunk}${ST}`;
2543
+ }).join("");
2544
+ }
2545
+ function createKittyDeleteGraphicsSequence(options = {}) {
2546
+ let controls = ["a=d"];
2547
+ if (options.allVisible)
2548
+ controls.push(`d=${options.freeImageData ? "A" : "a"}`);
2549
+ else if (options.imageId != null) {
2550
+ let imageId = uint32Control("i", options.imageId), placementId = uint32Control("p", options.placementId);
2551
+ if (!imageId || options.placementId != null && !placementId)
2552
+ return "";
2553
+ controls.push(`d=${options.freeImageData ? "I" : "i"}`), controls.push(imageId), controls.push(placementId);
2554
+ } else if (options.currentCell)
2555
+ controls.push(`d=${options.freeImageData ? "C" : "c"}`);
2556
+ else
2557
+ return "";
2558
+ return options.quiet !== !1 && controls.push("q=2"), `${ESC2}_G${controls.filter(Boolean).join(",")}${ST}`;
2559
+ }
2560
+ function createIterm2InlineImageSequence(base64Data, options = {}) {
2561
+ let data = sanitizeBase64(base64Data);
2562
+ if (!data)
2563
+ return "";
2564
+ let params = [
2565
+ "inline=1",
2566
+ options.width != null ? `width=${formatItermDimension(options.width)}` : "",
2567
+ options.height != null ? `height=${formatItermDimension(options.height)}` : "",
2568
+ `preserveAspectRatio=${options.preserveAspectRatio === !1 ? 0 : 1}`,
2569
+ options.doNotMoveCursor === !1 ? "" : "doNotMoveCursor=1"
2570
+ ].filter(Boolean);
2571
+ return `${ESC2}]1337;File=${params.join(";")}:${data}${BEL}`;
2572
+ }
2573
+ function formatItermDimension(value) {
2574
+ if (typeof value == "number") {
2575
+ let n = Math.floor(value);
2576
+ return Number.isFinite(n) ? String(Math.min(99999, Math.max(1, n))) : "auto";
2577
+ }
2578
+ let raw = String(value ?? "").trim();
2579
+ return validateIterm2Dimension(raw) ? raw : "auto";
2580
+ }
2581
+
2582
+ // src/vue/components/TAgentTerminalGraphic.ts
2583
+ var import_vue10 = require("vue");
2584
+ var NO_GRAPHICS_CAPABILITIES = Object.freeze({
2585
+ supported: !1,
2586
+ kitty: !1,
2587
+ iterm2: !1,
2588
+ sixel: !1,
2589
+ preferredProtocol: null,
2590
+ protocol: "unicode",
2591
+ candidates: [],
2592
+ stdoutIsTTY: !1,
2593
+ insideTmux: !1,
2594
+ insideScreen: !1,
2595
+ insideZellij: !1,
2596
+ multiplexer: null,
2597
+ passthrough: !1,
2598
+ forced: !1,
2599
+ reason: "no-terminal-graphics-output"
2600
+ });
2601
+ function splitTextOutput(value) {
2602
+ let lines = sanitizeTextBlock(sanitizeTerminalFallbackText(value).replace(/\r\n?/g, `
2603
+ `)).split(`
2604
+ `);
2605
+ return lines.length ? lines : [""];
2606
+ }
2607
+ function hasVisibleOutput(value) {
2608
+ return value.some((line) => line.trim().length > 0);
2609
+ }
2610
+ function errorMessage(error) {
2611
+ return error instanceof Error ? error.message : String(error);
2612
+ }
2613
+ function positiveInt(value) {
2614
+ let n = Math.floor(Number(value));
2615
+ return Number.isFinite(n) && n > 0 ? n : void 0;
2616
+ }
2617
+ function finiteInt(value) {
2618
+ let n = Math.floor(Number(value));
2619
+ return Number.isFinite(n) ? n : void 0;
2620
+ }
2621
+ function clampNumber(value, min, max) {
2622
+ return Math.max(min, Math.min(max, value));
2623
+ }
2624
+ function rectArea(rect) {
2625
+ return Math.max(0, rect.w) * Math.max(0, rect.h);
2626
+ }
2627
+ function sameRect(a, b) {
2628
+ return a.x === b.x && a.y === b.y && a.w === b.w && a.h === b.h;
2629
+ }
2630
+ function subtractRect(rect, cover) {
2631
+ let hit = intersectRect(rect, cover);
2632
+ if (!hit)
2633
+ return [rect];
2634
+ let out = [], rectRight = rect.x + rect.w, rectBottom = rect.y + rect.h, hitRight = hit.x + hit.w, hitBottom = hit.y + hit.h;
2635
+ 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);
2636
+ }
2637
+ function largestUncoveredRect(rect, covers) {
2638
+ let parts = [rect];
2639
+ for (let cover of covers)
2640
+ if (parts = parts.flatMap((part) => subtractRect(part, cover)), !parts.length)
2641
+ return null;
2642
+ return parts.sort((a, b) => rectArea(b) - rectArea(a) || a.y - b.y || a.x - b.x), parts[0] ?? null;
2643
+ }
2644
+ function parseKittyClearControls(sequence) {
2645
+ let prefix = "\x1B_G", terminator = "\x1B\\";
2646
+ if (!sequence.startsWith(prefix) || !sequence.endsWith(terminator))
2647
+ return null;
2648
+ let body = sequence.slice(prefix.length, -terminator.length);
2649
+ if (body.includes(terminator) || body.includes("\x1B") || body.includes("\x07"))
2650
+ return null;
2651
+ let semicolon = body.indexOf(";"), rawControls = semicolon >= 0 ? body.slice(0, semicolon) : body, controls = /* @__PURE__ */ new Map();
2652
+ for (let part of rawControls.split(",")) {
2653
+ let eq = part.indexOf("=");
2654
+ if (eq <= 0)
2655
+ return null;
2656
+ controls.set(part.slice(0, eq), part.slice(eq + 1));
2657
+ }
2658
+ return controls;
2659
+ }
2660
+ function kittyClearTargetsComponent(sequence, imageId, placementId) {
2661
+ let controls = parseKittyClearControls(sequence);
2662
+ if (!controls)
2663
+ return !1;
2664
+ let mode = controls.get("d");
2665
+ return mode !== "i" && mode !== "I" ? !1 : controls.get("i") === String(imageId) && controls.get("p") === String(placementId);
2666
+ }
2667
+ function isSafeComponentClearSequence(sequence, protocol, imageId, placementId) {
2668
+ return isSafeTerminalGraphicsSequence(sequence, protocol, "clear") ? protocol !== "kitty" || kittyClearTargetsComponent(sequence, imageId, placementId) : !1;
2669
+ }
2670
+ var textEncoder = null;
2671
+ function stringByteLength(value) {
2672
+ if (typeof TextEncoder < "u")
2673
+ return textEncoder ?? (textEncoder = new TextEncoder()), textEncoder.encode(value).length;
2674
+ let bytes = 0;
2675
+ for (let index = 0; index < value.length; index++) {
2676
+ let code = value.charCodeAt(index);
2677
+ code <= 127 ? bytes += 1 : code <= 2047 ? bytes += 2 : code >= 55296 && code <= 56319 && index + 1 < value.length ? (bytes += 4, index++) : bytes += 3;
2678
+ }
2679
+ return bytes;
2680
+ }
2681
+ function smallHash(input) {
2682
+ let hash = 2166136261;
2683
+ for (let i = 0; i < input.length; i++)
2684
+ hash ^= input.charCodeAt(i), hash = Math.imul(hash, 16777619);
2685
+ return (hash >>> 0).toString(36);
2686
+ }
2687
+ var tAgentTerminalGraphicProps = {
2688
+ x: { type: Number, required: !0 },
2689
+ y: { type: Number, required: !0 },
2690
+ w: { type: Number, required: !0 },
2691
+ h: { type: Number, default: void 0 },
2692
+ zIndex: { type: Number, default: 0 },
2693
+ content: { type: String, required: !0 },
2694
+ kind: {
2695
+ type: String,
2696
+ default: "image"
2697
+ },
2698
+ fallback: { type: String, default: void 0 },
2699
+ style: { type: Object, default: void 0 },
2700
+ loadingStyle: { type: Object, default: void 0 },
2701
+ errorStyle: { type: Object, default: void 0 },
2702
+ clear: { type: Boolean, default: !0 },
2703
+ final: { type: Boolean, default: !0 },
2704
+ streaming: { type: Boolean, default: !1 },
2705
+ renderer: {
2706
+ type: Function,
2707
+ default: void 0
2708
+ },
2709
+ loadingText: {
2710
+ type: String,
2711
+ default: "Rendering terminal graphic..."
2712
+ },
2713
+ deferRenderUntilVisible: { type: Boolean, default: !0 },
2714
+ suspendRawWhileScrolling: { type: Boolean, default: !0 },
2715
+ suspendRenderWhileScrolling: { type: Boolean, default: !0 },
2716
+ scrolling: { type: Boolean, default: !1 },
2717
+ scrollVersion: { type: Number, default: 0 },
2718
+ placementMoveWithoutClear: { type: Boolean, default: !1 },
2719
+ preserveRawWhileRendering: { type: Boolean, default: !1 },
2720
+ suspended: { type: Boolean, default: !1 },
2721
+ retainRawWhileCovered: { type: Boolean, default: !1 },
2722
+ ignoreRawCoverage: { type: Boolean, default: !1 },
2723
+ ignoreSamePlaneRawCoverage: { type: Boolean, default: !1 },
2724
+ cacheKey: { type: String, default: void 0 },
2725
+ placementKey: { type: String, default: void 0 },
2726
+ trace: {
2727
+ type: Function,
2728
+ default: void 0
2729
+ }
2730
+ };
2731
+ function terminalDrawKey(current, rect, clearSequence, resizeSequence) {
2732
+ return [
2733
+ current.protocol,
2734
+ rect.x,
2735
+ rect.y,
2736
+ rect.w,
2737
+ rect.h,
2738
+ current.sequenceHash,
2739
+ clearSequence === current.clearSequence ? current.clearSequenceHash ?? "" : smallHash(clearSequence ?? ""),
2740
+ resizeSequence === current.resizeSequence ? current.resizeSequenceHash ?? "" : smallHash(resizeSequence ?? "")
2741
+ ].join(":");
2742
+ }
2743
+ var TAgentTerminalGraphic = (0, import_vue10.defineComponent)({
2744
+ name: "TAgentTerminalGraphic",
2745
+ props: tAgentTerminalGraphicProps,
2746
+ setup(props) {
2747
+ let instance = (0, import_vue10.getCurrentInstance)(), { terminal, defaultStyle, scheduler, widthProvider, render } = useTerminal(), layout = useLayout(), { visible, rootProps } = useVisibility(), graphicsActivity = (0, import_vue10.inject)(TerminalGraphicsActivityKey, null), status = (0, import_vue10.shallowRef)("idle"), error = (0, import_vue10.shallowRef)(""), graphic = (0, import_vue10.shallowRef)(null), documentVersion = (0, import_vue10.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_vue10.shallowRef)(null), rawClearPendingRepaint = (0, import_vue10.shallowRef)(null), rawDrawRejectedKey = (0, import_vue10.shallowRef)(null), reservedTerminalGraphicSize = (0, import_vue10.shallowRef)(null), terminalSizeVersion = (0, import_vue10.shallowRef)(0), renderNodeId = (0, import_vue10.shallowRef)(null), lastRawSkipScrollKey = "", lastDeferTraceKey = "", isParentScrolling = (0, import_vue10.computed)(
2748
+ () => props.scrolling || !!graphicsActivity?.scrolling.value
2749
+ ), graphicsActivityVersion = (0, import_vue10.computed)(
2750
+ () => (graphicsActivity?.version.value ?? 0) + Math.floor(Number(props.scrollVersion ?? 0))
2751
+ ), graphicsOutput = () => getTerminalGraphicsOutput(terminal), graphicsOutputVersion = (0, import_vue10.shallowRef)(getTerminalGraphicsOutputVersion(terminal)), unsubscribeGraphicsOutput = subscribeTerminalGraphicsOutput(terminal, () => {
2752
+ graphicsOutputVersion.value = getTerminalGraphicsOutputVersion(terminal);
2753
+ }), unsubscribeTerminalResize = terminal.on("resize", () => {
2754
+ terminalSizeVersion.value++;
2755
+ }), fallbackText = () => props.fallback ?? (props.kind === "math" ? props.content : ""), contentIdentity = (0, import_vue10.computed)(() => `${props.content.length}:${smallHash(props.content)}`), stableGraphicKey = (0, import_vue10.computed)(
2756
+ () => [
2757
+ rawIdSeed,
2758
+ props.cacheKey ?? "",
2759
+ props.kind,
2760
+ contentIdentity.value,
2761
+ props.w,
2762
+ props.h ?? "",
2763
+ props.final ? "final" : "draft"
2764
+ ].join("")
2765
+ ), imageId = (0, import_vue10.computed)(
2766
+ () => stableTerminalGraphicNumericId(`image:${stableGraphicKey.value}`)
2767
+ ), placementId = (0, import_vue10.computed)(
2768
+ () => stableTerminalGraphicNumericId(`placement:${stableGraphicKey.value}`)
2769
+ );
2770
+ function rememberTerminalGraphicSize(current) {
2771
+ if (current.type !== "terminal")
2772
+ return;
2773
+ let rows = positiveInt(current.rows);
2774
+ rows && (reservedTerminalGraphicSize.value = {
2775
+ key: stableGraphicKey.value,
2776
+ rows
2777
+ });
2778
+ }
2779
+ function bump() {
2780
+ documentVersion.value++;
2781
+ }
2782
+ function currentCapabilities() {
2783
+ return graphicsOutput()?.capabilities ?? NO_GRAPHICS_CAPABILITIES;
2784
+ }
2785
+ function trace(type, extra = {}) {
2786
+ let capabilities = currentCapabilities();
2787
+ try {
2788
+ props.trace?.({
2789
+ type,
2790
+ id: rawId,
2791
+ kind: props.kind,
2792
+ protocol: capabilities.protocol,
2793
+ contentHash: smallHash(props.content),
2794
+ ...extra
2795
+ });
2796
+ } catch {
2797
+ }
2798
+ let protocol = isTerminalGraphicsProtocol(capabilities.protocol) ? capabilities.protocol : void 0, key = props.cacheKey ?? smallHash(props.content);
2799
+ type === "render-start" ? recordTerminalGraphicTrace({ type: "renderer-start", id: rawId, key, protocol }) : type === "render-end" ? recordTerminalGraphicTrace({
2800
+ type: extra.reason ? "renderer-error" : "renderer-end",
2801
+ id: rawId,
2802
+ key,
2803
+ protocol,
2804
+ durationMs: extra.durationMs,
2805
+ bytes: extra.sequenceBytes,
2806
+ error: extra.reason
2807
+ }) : type === "defer" ? recordTerminalGraphicTrace({
2808
+ type: extra.reason === "scrolling" ? "skip-scrolling" : "skip-hidden",
2809
+ id: rawId,
2810
+ key,
2811
+ protocol,
2812
+ reason: extra.reason
2813
+ }) : type === "raw-draw" || (type === "render-abort" ? recordTerminalGraphicTrace({
2814
+ type: "renderer-abort",
2815
+ id: rawId,
2816
+ key,
2817
+ protocol,
2818
+ reason: extra.reason
2819
+ }) : type === "raw-clear" ? recordTerminalGraphicTrace({ type: "clear", id: rawId, key, protocol }) : type === "raw-skip-scroll" && recordTerminalGraphicTrace({
2820
+ type: "skip-scrolling",
2821
+ id: rawId,
2822
+ key,
2823
+ protocol,
2824
+ reason: extra.reason
2825
+ }));
2826
+ }
2827
+ function traceDeferOnce(reason) {
2828
+ let key = [reason, graphicsActivityVersion.value, stableGraphicKey.value].join(":");
2829
+ lastDeferTraceKey !== key && (lastDeferTraceKey = key, trace("defer", { reason }));
2830
+ }
2831
+ function abortCurrentRender(reason) {
2832
+ renderAbort && (renderAbort.abort(), renderAbort = null, trace("render-abort", { reason }));
2833
+ }
2834
+ function normalizeResult(result) {
2835
+ if (result == null)
2836
+ return {
2837
+ type: "text",
2838
+ text: fallbackText()
2839
+ };
2840
+ if (typeof result == "string")
2841
+ return {
2842
+ type: "text",
2843
+ text: result
2844
+ };
2845
+ if (typeof result != "object")
2846
+ return {
2847
+ type: "text",
2848
+ text: fallbackText()
2849
+ };
2850
+ if ("type" in result && result.type === "text")
2851
+ return {
2852
+ type: "text",
2853
+ text: result.text
2854
+ };
2855
+ let maybeRaw = result;
2856
+ if (!(maybeRaw.type === "sequence" || "sequence" in result || "protocol" in result) && "text" in result)
2857
+ return {
2858
+ type: "text",
2859
+ text: result.text
2860
+ };
2861
+ 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";
2862
+ if (!sequence || !protocol || !isSafeTerminalGraphicsSequence(sequence, protocol, "draw"))
2863
+ return {
2864
+ type: "text",
2865
+ text: fallback
2866
+ };
2867
+ 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);
2868
+ return {
2869
+ type: "terminal",
2870
+ protocol,
2871
+ sequence,
2872
+ sequenceHash: smallHash(sequence),
2873
+ sequenceBytes: stringByteLength(sequence),
2874
+ fallback,
2875
+ fallbackFromProps,
2876
+ clearSequence,
2877
+ clearSequenceHash: clearSequence ? smallHash(clearSequence) : void 0,
2878
+ resizeSequence,
2879
+ resizeSequenceHash: resizeSequence ? smallHash(resizeSequence) : void 0,
2880
+ cols: declaredRows == null ? declaredCols : declaredSize?.width,
2881
+ rows: declaredSize?.height,
2882
+ sourceWidth,
2883
+ sourceHeight,
2884
+ zIndex
2885
+ };
2886
+ }
2887
+ function defaultClearSequence(protocol) {
2888
+ return protocol === "kitty" ? createKittyDeleteGraphicsSequence({
2889
+ imageId: imageId.value,
2890
+ placementId: placementId.value
2891
+ }) : "";
2892
+ }
2893
+ function resolveClearSequence(current) {
2894
+ if (current.clearSequence)
2895
+ return current.clearSequence;
2896
+ let candidate = defaultClearSequence(current.protocol);
2897
+ if (candidate)
2898
+ return isSafeComponentClearSequence(
2899
+ candidate,
2900
+ current.protocol,
2901
+ imageId.value,
2902
+ placementId.value
2903
+ ) ? candidate : void 0;
2904
+ }
2905
+ function resolveResizeSequence(current, rect, full) {
2906
+ if (current.protocol !== "kitty")
2907
+ return current.resizeSequence;
2908
+ let sourceWidth = positiveInt(current.sourceWidth), sourceHeight = positiveInt(current.sourceHeight);
2909
+ if (!sourceWidth || !sourceHeight || full.w <= 0 || full.h <= 0)
2910
+ return current.resizeSequence;
2911
+ 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(
2912
+ x0 + 1,
2913
+ clampNumber(Math.ceil((offsetX + visibleW) * sourceWidth / full.w), 1, sourceWidth)
2914
+ ), y1 = Math.max(
2915
+ y0 + 1,
2916
+ clampNumber(Math.ceil((offsetY + visibleH) * sourceHeight / full.h), 1, sourceHeight)
2917
+ );
2918
+ return createKittyPlacementSequence({
2919
+ imageId: imageId.value,
2920
+ placementId: placementId.value,
2921
+ columns: rect.w,
2922
+ rows: rect.h,
2923
+ sourceX: x0,
2924
+ sourceY: y0,
2925
+ sourceWidth: x1 - x0,
2926
+ sourceHeight: y1 - y0,
2927
+ zIndex: current.zIndex
2928
+ });
2929
+ }
2930
+ function queueClearLastGraphic(options = {}) {
2931
+ let previous = lastDrawnGraphic.value;
2932
+ if (!previous)
2933
+ return !1;
2934
+ let output = graphicsOutput(), accepted = !1;
2935
+ if (output?.clear && !previous.retainOnClear)
2936
+ try {
2937
+ accepted = !!output.clear(previous.id);
2938
+ } catch {
2939
+ accepted = !1;
2940
+ }
2941
+ if (!accepted && output && previous.clearSequence)
2942
+ try {
2943
+ accepted = output.queue({
2944
+ id: previous.id,
2945
+ x: previous.x,
2946
+ y: previous.y,
2947
+ w: previous.w,
2948
+ h: previous.h,
2949
+ protocol: previous.protocol,
2950
+ sequence: previous.clearSequence,
2951
+ deferFlush: !0,
2952
+ retainOnClear: previous.retainOnClear,
2953
+ op: "clear"
2954
+ });
2955
+ } catch {
2956
+ accepted = !1;
2957
+ }
2958
+ return accepted && ((options.markPendingRepaint ?? !0) && (rawClearPendingRepaint.value = previous), lastDrawnGraphic.value = null, trace("raw-clear", {
2959
+ x: previous.x,
2960
+ y: previous.y,
2961
+ w: previous.w,
2962
+ h: previous.h
2963
+ })), accepted;
2964
+ }
2965
+ function queueDrawGraphic(output, current, rect, full = rect, options = {}) {
2966
+ 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;
2967
+ if (!previousIsRetained && !options.force && previous?.drawKey === drawKey && previousStillActive)
2968
+ return !1;
2969
+ 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;
2970
+ 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)))
2971
+ return lastDrawnGraphic.value = {
2972
+ ...previous,
2973
+ w: rect.w,
2974
+ h: rect.h,
2975
+ clearSequence,
2976
+ resizeSequence,
2977
+ drawKey,
2978
+ activityVersion: graphicsActivityVersion.value,
2979
+ scrollVersion
2980
+ }, lastRawSkipScrollKey = "", !1;
2981
+ if (previousStillActive && !previousIsRetained && !canReusePlacementSequence && !preservePreviousForAtomicReplace) {
2982
+ if (!queueClearLastGraphic({ markPendingRepaint: !1 }))
2983
+ return !1;
2984
+ } else
2985
+ previous && (previousStillActive || (lastDrawnGraphic.value = null, rawClearPendingRepaint.value = null));
2986
+ let accepted = !1;
2987
+ try {
2988
+ accepted = output.queue({
2989
+ id: rawId,
2990
+ x: rect.x,
2991
+ y: rect.y,
2992
+ w: rect.w,
2993
+ h: rect.h,
2994
+ protocol: current.protocol,
2995
+ sequence: canReusePlacementSequence && resizeSequence ? resizeSequence : current.sequence,
2996
+ resizeSequence,
2997
+ clearSequence,
2998
+ retainOnClear: !!(props.cacheKey && resizeSequence),
2999
+ resizeRedraw: canReusePlacementSequence,
3000
+ placementMoveWithoutClear: canMoveWithoutClear,
3001
+ allowTextOverlay: options.allowTextOverlay,
3002
+ forceDraw: options.force,
3003
+ deferFlush: options.deferFlush ?? !0,
3004
+ fallbackText: current.fallback
3005
+ });
3006
+ } catch {
3007
+ accepted = !1;
3008
+ }
3009
+ return accepted ? (rawDrawRejectedKey.value = null, rawClearPendingRepaint.value = null, lastDrawnGraphic.value = {
3010
+ id: rawId,
3011
+ x: rect.x,
3012
+ y: rect.y,
3013
+ w: rect.w,
3014
+ h: rect.h,
3015
+ protocol: current.protocol,
3016
+ sequenceHash: current.sequenceHash,
3017
+ clearSequence,
3018
+ resizeSequence,
3019
+ retainOnClear: !!(props.cacheKey && resizeSequence),
3020
+ allowTextOverlay: !!options.allowTextOverlay,
3021
+ drawKey,
3022
+ activityVersion: graphicsActivityVersion.value,
3023
+ scrollVersion
3024
+ }, 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);
3025
+ }
3026
+ function hasRetainedActiveRawGraphic() {
3027
+ let output = graphicsOutput();
3028
+ return !!(status.value === "loading" && !graphic.value && output && typeof output.isActive == "function" && output.isActive(rawId));
3029
+ }
3030
+ let showingInitialLoadingText = (0, import_vue10.computed)(
3031
+ () => status.value === "loading" && !graphic.value && !hasRetainedActiveRawGraphic()
3032
+ ), fullRect = (0, import_vue10.computed)(() => {
3033
+ 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);
3034
+ return translateRect(
3035
+ { x: props.x, y: props.y, w: props.w, h: height },
3036
+ layout.originX,
3037
+ layout.originY
3038
+ );
3039
+ }), absRect = (0, import_vue10.computed)(() => {
3040
+ terminalSizeVersion.value;
3041
+ let translated = fullRect.value, size = terminal.size(), terminalClip = {
3042
+ x: 0,
3043
+ y: 0,
3044
+ w: Math.max(0, Math.floor(size.cols)),
3045
+ h: Math.max(0, Math.floor(size.rows))
3046
+ }, clip = layout.clipRect ? intersectRect(layout.clipRect, terminalClip) : terminalClip;
3047
+ return clip ? intersectRect(translated, clip) ?? { x: 0, y: 0, w: 0, h: 0 } : { x: 0, y: 0, w: 0, h: 0 };
3048
+ }), renderRect = (0, import_vue10.computed)(() => absRect.value);
3049
+ function rawRectFitsTerminalViewport(rect) {
3050
+ return canDrawTerminalGraphicRect(rect, terminal.size());
3051
+ }
3052
+ function rawCoveredByHigherRenderNode(rect = fullRect.value) {
3053
+ if (props.retainRawWhileCovered)
3054
+ return !1;
3055
+ let id = renderNodeId.value;
3056
+ return !props.ignoreRawCoverage && id != null && render.isRectCoveredByHigherNode(id, rect, {
3057
+ ignoreSamePlane: props.ignoreSamePlaneRawCoverage
3058
+ });
3059
+ }
3060
+ function retainedRawCoveredByHigherRenderNode(rect) {
3061
+ if (!props.retainRawWhileCovered)
3062
+ return !1;
3063
+ let id = renderNodeId.value;
3064
+ return !!(id != null && render.isRectCoveredByHigherNode(id, rect, {
3065
+ ignoreSamePlane: props.ignoreSamePlaneRawCoverage
3066
+ }));
3067
+ }
3068
+ function rawUncoveredRenderRect(rect) {
3069
+ if (props.retainRawWhileCovered)
3070
+ return rect;
3071
+ let id = renderNodeId.value;
3072
+ if (id == null)
3073
+ return rect;
3074
+ let covers = render.higherNodeCoverageRects(id, rect, {
3075
+ ignoreSamePlane: props.ignoreSamePlaneRawCoverage
3076
+ });
3077
+ return covers.length ? props.ignoreRawCoverage ? largestUncoveredRect(rect, covers) : null : rect;
3078
+ }
3079
+ let rawCanRender = (0, import_vue10.computed)(() => {
3080
+ graphicsOutputVersion.value, terminalSizeVersion.value;
3081
+ let current = graphic.value, output = graphicsOutput(), rect = absRect.value;
3082
+ return current?.type === "terminal" && rawRectFitsTerminalViewport(rect) && !!output?.capabilities.supported && output?.capabilities.preferredProtocol === current.protocol;
3083
+ }), rawOutputCanRenderValue = (0, import_vue10.computed)(() => (graphicsOutputVersion.value, terminalSizeVersion.value, rawOutputCanRender())), rawSuppressedByScroll = (0, import_vue10.computed)(
3084
+ () => props.suspended || props.suspendRawWhileScrolling && isParentScrolling.value
3085
+ ), rawCanQueue = (0, import_vue10.computed)(() => rawCanRender.value && !rawSuppressedByScroll.value);
3086
+ function traceRawSkipScrollOnce(reason) {
3087
+ let r = absRect.value, key = [
3088
+ reason,
3089
+ graphicsActivityVersion.value,
3090
+ stableGraphicKey.value,
3091
+ r.x,
3092
+ r.y,
3093
+ r.w,
3094
+ r.h
3095
+ ].join(":");
3096
+ lastRawSkipScrollKey !== key && (lastRawSkipScrollKey = key, trace("raw-skip-scroll", { reason }));
3097
+ }
3098
+ function hasPaintableRect() {
3099
+ let r = absRect.value;
3100
+ return visible.value && r.w > 0 && r.h > 0;
3101
+ }
3102
+ function rawOutputCanRender() {
3103
+ let output = graphicsOutput(), rect = absRect.value;
3104
+ return rawRectFitsTerminalViewport(rect) && !!output?.capabilities.supported;
3105
+ }
3106
+ function renderDeferReason() {
3107
+ return props.suspended ? "suspended" : props.deferRenderUntilVisible && !hasPaintableRect() ? "not-visible" : props.suspendRenderWhileScrolling && isParentScrolling.value ? "scrolling" : null;
3108
+ }
3109
+ function shouldDeferRender() {
3110
+ return renderDeferReason() != null;
3111
+ }
3112
+ function shouldRerenderForGraphicsOutputChange() {
3113
+ if (!props.renderer || !props.content.trim() || shouldDeferRender() || rawSuppressedByScroll.value)
3114
+ return !1;
3115
+ let protocol = currentCapabilities().protocol;
3116
+ return lastRenderProtocol != null && (lastRenderProtocol !== protocol || lastRenderGraphicsOutputVersion !== graphicsOutputVersion.value);
3117
+ }
3118
+ function shouldRetryTemporaryRawFallback(rawCovered = rawCoveredByHigherRenderNode()) {
3119
+ return !!props.renderer && props.content.trim().length > 0 && graphic.value?.type === "text" && status.value !== "loading" && !lastRenderRawVisible && rawOutputCanRenderValue.value && !rawSuppressedByScroll.value && !rawCovered;
3120
+ }
3121
+ function setDeferredFallback(content) {
3122
+ graphic.value = { type: "text", text: content.trim() ? fallbackText() : "" }, lastRenderedContent = content, status.value = "idle", error.value = "", bump();
3123
+ }
3124
+ function resolveRendererContext(signal) {
3125
+ let capabilities = currentCapabilities(), visibleNow = hasPaintableRect(), rawVisible = rawOutputCanRenderValue.value && !rawSuppressedByScroll.value && !rawCoveredByHigherRenderNode();
3126
+ return {
3127
+ kind: props.kind,
3128
+ width: props.w,
3129
+ height: props.h,
3130
+ final: props.final,
3131
+ streaming: props.streaming,
3132
+ protocol: capabilities.protocol,
3133
+ capabilities,
3134
+ signal,
3135
+ imageId: imageId.value,
3136
+ placementId: placementId.value,
3137
+ visible: visibleNow,
3138
+ rawVisible,
3139
+ scrolling: isParentScrolling.value,
3140
+ cacheKey: props.cacheKey,
3141
+ viewport: {
3142
+ visible: visibleNow,
3143
+ rawVisible,
3144
+ scrolling: isParentScrolling.value,
3145
+ rect: absRect.value,
3146
+ fullRect: fullRect.value
3147
+ }
3148
+ };
3149
+ }
3150
+ async function renderNow(version) {
3151
+ let protocol = currentCapabilities().protocol;
3152
+ recordTerminalGraphicTrace({
3153
+ type: "request",
3154
+ id: rawId,
3155
+ key: props.cacheKey ?? smallHash(props.content),
3156
+ protocol: isTerminalGraphicsProtocol(protocol) ? protocol : void 0
3157
+ });
3158
+ let content = props.content;
3159
+ if (!content.trim()) {
3160
+ if (abortCurrentRender("superseded"), !alive || version !== renderVersion)
3161
+ return;
3162
+ graphic.value = { type: "text", text: "" }, lastRenderedContent = content, status.value = "ready", error.value = "", bump();
3163
+ return;
3164
+ }
3165
+ let renderer = props.renderer;
3166
+ if (!renderer) {
3167
+ if (abortCurrentRender("superseded"), !alive || version !== renderVersion)
3168
+ return;
3169
+ graphic.value = { type: "text", text: fallbackText() }, lastRenderedContent = content, status.value = "ready", error.value = "", bump();
3170
+ return;
3171
+ }
3172
+ let deferred = renderDeferReason();
3173
+ if (deferred) {
3174
+ if (abortCurrentRender(deferred), !alive || version !== renderVersion)
3175
+ return;
3176
+ setDeferredFallback(content), traceDeferOnce(deferred);
3177
+ return;
3178
+ }
3179
+ abortCurrentRender("superseded"), lastDeferTraceKey = "";
3180
+ let abort = new AbortController();
3181
+ renderAbort = abort;
3182
+ let startedAt = nowTerminalGraphicTraceTime();
3183
+ status.value = "loading", error.value = "", trace("render-start"), bump();
3184
+ try {
3185
+ let contextGraphicsOutputVersion = graphicsOutputVersion.value, context = resolveRendererContext(abort.signal);
3186
+ lastRenderRawVisible = context.rawVisible, lastRenderProtocol = context.protocol, lastRenderGraphicsOutputVersion = contextGraphicsOutputVersion;
3187
+ let result = await renderer(content, context);
3188
+ if (abort.signal.aborted || !alive || version !== renderVersion)
3189
+ return;
3190
+ let normalized = normalizeResult(result);
3191
+ rememberTerminalGraphicSize(normalized), graphic.value = normalized, lastRenderedContent = content, status.value = "ready", error.value = "", trace("render-end", {
3192
+ durationMs: nowTerminalGraphicTraceTime() - startedAt,
3193
+ sequenceChars: normalized.type === "terminal" ? normalized.sequence.length : 0,
3194
+ sequenceBytes: normalized.type === "terminal" ? normalized.sequenceBytes : 0
3195
+ }), bump(), normalized.type === "terminal" && scheduler.invalidate({ priority: "low", reason: "data" });
3196
+ } catch (err) {
3197
+ if (abort.signal.aborted || !alive || version !== renderVersion)
3198
+ return;
3199
+ graphic.value = { type: "text", text: fallbackText() }, lastRenderedContent = content, status.value = "ready", error.value = errorMessage(err), trace("render-end", {
3200
+ durationMs: nowTerminalGraphicTraceTime() - startedAt,
3201
+ reason: error.value
3202
+ }), bump();
3203
+ } finally {
3204
+ renderAbort === abort && (renderAbort = null);
3205
+ }
3206
+ }
3207
+ function scheduleRender(options = {}) {
3208
+ let version = ++renderVersion;
3209
+ if ((options.clearLastGraphic ?? !props.preserveRawWhileRendering) && queueClearLastGraphic(), !builtOnce || !props.streaming) {
3210
+ builtOnce = !0, renderNow(version);
3211
+ return;
3212
+ }
3213
+ scheduler.queueFrameTask({
3214
+ id: frameTaskId,
3215
+ reason: "stream",
3216
+ priority: "low",
3217
+ sync: !1,
3218
+ run: () => {
3219
+ alive && version === renderVersion && renderNow(version);
3220
+ }
3221
+ }) === !1 && renderNow(version);
3222
+ }
3223
+ (0, import_vue10.watch)(
3224
+ [
3225
+ () => props.content,
3226
+ () => props.kind,
3227
+ () => props.renderer,
3228
+ () => props.w,
3229
+ () => props.h,
3230
+ () => props.streaming,
3231
+ () => props.final,
3232
+ () => props.deferRenderUntilVisible,
3233
+ () => props.suspendRawWhileScrolling,
3234
+ () => props.suspendRenderWhileScrolling,
3235
+ () => props.scrolling,
3236
+ () => props.preserveRawWhileRendering,
3237
+ () => props.suspended,
3238
+ () => props.retainRawWhileCovered,
3239
+ () => props.ignoreRawCoverage,
3240
+ () => props.ignoreSamePlaneRawCoverage,
3241
+ () => props.cacheKey,
3242
+ () => props.placementKey
3243
+ ],
3244
+ () => {
3245
+ scheduleRender();
3246
+ },
3247
+ { immediate: !0 }
3248
+ ), (0, import_vue10.watch)(
3249
+ () => props.fallback,
3250
+ () => {
3251
+ let current = graphic.value;
3252
+ if (current?.type === "terminal") {
3253
+ if (current.fallbackFromProps) {
3254
+ graphic.value = { ...current, fallback: fallbackText() }, bump(), scheduler.invalidate({ priority: "low", reason: "data" });
3255
+ return;
3256
+ }
3257
+ scheduleRender({ clearLastGraphic: !1 });
3258
+ return;
3259
+ }
3260
+ scheduleRender();
3261
+ }
3262
+ ), (0, import_vue10.watch)(
3263
+ () => [graphicsOutputVersion.value, rawOutputCanRenderValue.value],
3264
+ () => {
3265
+ !props.renderer || !props.content.trim() || graphic.value?.type !== "terminal" && (!rawOutputCanRenderValue.value || shouldDeferRender() || scheduleRender({ clearLastGraphic: !1 }));
3266
+ }
3267
+ ), (0, import_vue10.watch)(
3268
+ () => [props.x, props.y, props.w, props.h, props.scrollVersion],
3269
+ () => {
3270
+ if (graphic.value?.type === "terminal") {
3271
+ scheduler.invalidate({ priority: "low", reason: "data" });
3272
+ return;
3273
+ }
3274
+ props.kind !== "image" || status.value !== "loading" || !props.renderer || scheduleRender({ clearLastGraphic: !1 });
3275
+ },
3276
+ { flush: "sync" }
3277
+ ), (0, import_vue10.onBeforeUnmount)(() => {
3278
+ alive = !1, renderVersion++, unsubscribeTerminalResize(), unsubscribeGraphicsOutput(), abortCurrentRender("unmount"), scheduler.cancelFrameTask?.(frameTaskId), queueClearLastGraphic();
3279
+ });
3280
+ function resolveDisplayLines(rawPlaceholderAllowed) {
3281
+ if (showingInitialLoadingText.value)
3282
+ return splitTextOutput(props.loadingText);
3283
+ let current = graphic.value;
3284
+ if (!current)
3285
+ return splitTextOutput(fallbackText());
3286
+ if (current.type === "terminal" && rawPlaceholderAllowed) {
3287
+ let clearSequence = resolveClearSequence(current), drawKey = terminalDrawKey(
3288
+ current,
3289
+ absRect.value,
3290
+ clearSequence,
3291
+ resolveResizeSequence(current, absRect.value, fullRect.value)
3292
+ );
3293
+ if (rawDrawRejectedKey.value !== drawKey)
3294
+ return (0, import_vue10.markRaw)([""]);
3295
+ }
3296
+ let text = current.type === "terminal" ? current.fallback : current.text, lines = splitTextOutput(text);
3297
+ return text.trim().length > 0 && !hasVisibleOutput(lines) ? splitTextOutput(fallbackText()) : lines;
3298
+ }
3299
+ let displayLines = (0, import_vue10.computed)(() => resolveDisplayLines(rawCanQueue.value)), currentStyle = (0, import_vue10.computed)(() => error.value ? props.errorStyle ?? props.style ?? defaultStyle.value : showingInitialLoadingText.value ? props.loadingStyle ?? props.style ?? defaultStyle.value : props.style ?? defaultStyle.value), renderNode = useRenderNode(() => ({
3300
+ zIndex: props.zIndex,
3301
+ rect: visible.value ? renderRect.value : { x: 0, y: 0, w: 0, h: 0 },
3302
+ deps: [
3303
+ visible.value,
3304
+ renderRect.value,
3305
+ fullRect.value,
3306
+ displayLines.value,
3307
+ currentStyle.value,
3308
+ props.clear,
3309
+ status.value,
3310
+ error.value,
3311
+ documentVersion.value,
3312
+ rawOutputCanRenderValue.value,
3313
+ rawCanRender.value,
3314
+ rawCanQueue.value,
3315
+ rawClearPendingRepaint.value,
3316
+ rawDrawRejectedKey.value,
3317
+ rawSuppressedByScroll.value,
3318
+ props.placementMoveWithoutClear,
3319
+ props.retainRawWhileCovered,
3320
+ isParentScrolling.value,
3321
+ graphicsActivityVersion.value,
3322
+ graphicsOutputVersion.value
3323
+ ],
3324
+ paint: (dirtyRows) => {
3325
+ withTextWidthProvider(widthProvider, () => {
3326
+ if (!visible.value) {
3327
+ queueClearLastGraphic();
3328
+ return;
3329
+ }
3330
+ let r = absRect.value, full = fullRect.value;
3331
+ if (r.w <= 0 || r.h <= 0) {
3332
+ queueClearLastGraphic();
3333
+ return;
3334
+ }
3335
+ 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;
3336
+ if (rawCanQueueForPaint && output) {
3337
+ let previous = lastDrawnGraphic.value;
3338
+ if ((previous ? typeof output.isActive == "function" ? output.isActive(previous.id) : !0 : !1) && previous) {
3339
+ let clearSequence = resolveClearSequence(current), resizeSequence = resolveResizeSequence(current, rawRectForPaint, full);
3340
+ preserveActiveRawGraphic = rawClearPendingRepaint.value == null && previous.drawKey === terminalDrawKey(current, rawRectForPaint, clearSequence, resizeSequence), allowTextOverlay = retainedRawCoveredByHigherRenderNode(r), forceActiveRawRedraw = preserveActiveRawGraphic && (previous.activityVersion !== graphicsActivityVersion.value || previous.allowTextOverlay !== allowTextOverlay);
3341
+ }
3342
+ }
3343
+ 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) => {
3344
+ if (y < r.y || y >= r.y + r.h)
3345
+ return;
3346
+ let rowIndex = y - fullY;
3347
+ if (rowIndex < 0 || rowIndex >= out.length) {
3348
+ clearOwnedRegion && terminal.write(blank, { x: r.x, y, style });
3349
+ return;
3350
+ }
3351
+ let src = out[rowIndex] ?? "", clipped = dx > 0 ? sliceByCellsRange(src, dx, dx + r.w) : sliceByCells(src, r.w), value = clearOwnedRegion ? padEndByCells(clipped, r.w) : clipped;
3352
+ (value || clearOwnedRegion) && terminal.write(value, { x: r.x, y, style });
3353
+ }, paintRows = () => {
3354
+ if (dirtyRows?.length)
3355
+ for (let y of dirtyRows)
3356
+ paintRow(y);
3357
+ else
3358
+ for (let y = r.y; y < r.y + r.h; y++)
3359
+ paintRow(y);
3360
+ };
3361
+ if (paintRows(), current?.type === "terminal" && output?.capabilities.supported && output.capabilities.preferredProtocol === current.protocol && rawCanQueueForPaint) {
3362
+ let drawKey = terminalDrawKey(
3363
+ current,
3364
+ rawRectForPaint,
3365
+ resolveClearSequence(current),
3366
+ resolveResizeSequence(current, rawRectForPaint, full)
3367
+ );
3368
+ queueDrawGraphic(output, current, rawRectForPaint, full, {
3369
+ force: forceActiveRawRedraw,
3370
+ deferFlush: preserveActiveRawGraphicForPaint,
3371
+ placementMoveWithoutClear: props.placementMoveWithoutClear || rawCoverageClipped,
3372
+ allowTextOverlay
3373
+ }) ? trace("raw-draw", {
3374
+ sequenceChars: current.sequence.length,
3375
+ sequenceBytes: current.sequenceBytes,
3376
+ x: rawRectForPaint.x,
3377
+ y: rawRectForPaint.y,
3378
+ w: rawRectForPaint.w,
3379
+ h: rawRectForPaint.h
3380
+ }) : rawDrawRejectedKey.value === drawKey && (out = resolveDisplayLines(!1), paintRows());
3381
+ } else
3382
+ current?.type === "terminal" && rawSuppressedByScroll.value && traceRawSkipScrollOnce(isParentScrolling.value ? "scrolling" : "suspended"), queueClearLastGraphic({ markPendingRepaint: !1 }), !shouldDeferRender() && shouldRetryTemporaryRawFallback(rawCoveredForPaint) && scheduleRender({ clearLastGraphic: !1 });
3383
+ clearingRawGraphic && (rawClearPendingRepaint.value = null);
3384
+ });
3385
+ }
3386
+ }));
3387
+ return (0, import_vue10.watch)(
3388
+ renderNode.id,
3389
+ (id) => {
3390
+ renderNodeId.value = id;
3391
+ },
3392
+ { immediate: !0 }
3393
+ ), (0, import_vue10.watch)(
3394
+ [
3395
+ visible,
3396
+ rawOutputCanRenderValue,
3397
+ rawCanRender,
3398
+ rawCanQueue,
3399
+ rawSuppressedByScroll,
3400
+ isParentScrolling,
3401
+ graphicsActivityVersion,
3402
+ graphicsOutputVersion,
3403
+ () => renderRect.value.x,
3404
+ () => renderRect.value.y,
3405
+ () => renderRect.value.w,
3406
+ () => renderRect.value.h,
3407
+ () => fullRect.value.x,
3408
+ () => fullRect.value.y,
3409
+ () => fullRect.value.w,
3410
+ () => fullRect.value.h
3411
+ ],
3412
+ () => {
3413
+ if (!alive)
3414
+ return;
3415
+ let deferred = renderDeferReason();
3416
+ deferred && (abortCurrentRender(deferred), (status.value === "loading" || !graphic.value || lastRenderedContent !== props.content) && setDeferredFallback(props.content), traceDeferOnce(deferred)), (!visible.value || !rawCanQueue.value) && queueClearLastGraphic();
3417
+ let shouldRetryTemporaryFallback = shouldRetryTemporaryRawFallback(), shouldRerenderForOutputChange = shouldRerenderForGraphicsOutputChange();
3418
+ if (!shouldDeferRender() && (!graphic.value || status.value === "idle" || shouldRetryTemporaryFallback || shouldRerenderForOutputChange)) {
3419
+ scheduleRender();
3420
+ return;
3421
+ }
3422
+ scheduler.invalidate({ priority: "low", reason: "data" });
3423
+ },
3424
+ { flush: "post" }
3425
+ ), () => (0, import_vue10.h)("span", rootProps);
3426
+ }
3427
+ });
3428
+
3429
+ // src/vue/components/TText.ts
3430
+ var import_vue11 = require("vue");
3431
+ function fitText(text, max) {
3432
+ return max <= 0 ? "" : (text = sanitizeInlineText(text), sliceByCells(text, max));
3433
+ }
3434
+ function splitLines(text) {
3435
+ return sanitizeTextBlock(text).split(`
3436
+ `);
3437
+ }
3438
+ function computeDefaultWidth(text) {
3439
+ let lines = splitLines(text), max = 0;
3440
+ for (let line of lines)
3441
+ max = Math.max(max, textCellWidth(line));
3442
+ return max;
3443
+ }
3444
+ var TText = (0, import_vue11.defineComponent)({
3445
+ name: "TText",
3446
+ props: {
3447
+ x: { type: Number, required: !0 },
3448
+ y: { type: Number, required: !0 },
3449
+ zIndex: { type: Number, default: 0 },
3450
+ value: { type: String, required: !0 },
3451
+ w: { type: Number, default: void 0 },
3452
+ h: { type: Number, default: void 0 },
3453
+ style: { type: Object, default: void 0 },
3454
+ clear: { type: Boolean, default: !0 },
3455
+ wrap: { type: Boolean, default: !1 },
3456
+ /**
3457
+ * Optional key that participates in render-node dependency tracking.
3458
+ * Useful for forcing a repaint when the rendered output might change
3459
+ * even if `value`, `style`, and geometry are unchanged (e.g. external
3460
+ * terminal writes or higher-level virtualized row reuse).
3461
+ */
3462
+ depsKey: { type: null, default: void 0 }
3463
+ },
3464
+ setup(props) {
3465
+ let { terminal, defaultStyle } = useTerminal(), layout = useLayout(), { visible, rootProps } = useVisibility(), defaultWidth = (0, import_vue11.computed)(() => computeDefaultWidth(props.value)), lines = (0, import_vue11.computed)(() => {
3466
+ let w = props.w ?? defaultWidth.value;
3467
+ if (w <= 0)
3468
+ return [""];
3469
+ if (!props.wrap)
3470
+ return splitLines(props.value).map((l) => fitText(l, w));
3471
+ let safe = sanitizeTextBlock(props.value);
3472
+ return wrapByCells(safe, w).map((l) => fitText(l, w));
3473
+ }), absRect = (0, import_vue11.computed)(() => {
3474
+ 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);
3475
+ return layout.clipRect ? intersectRect(translated, layout.clipRect) ?? { x: 0, y: 0, w: 0, h: 0 } : translated;
3476
+ }), fullRect = (0, import_vue11.computed)(() => {
3477
+ let width = props.w ?? defaultWidth.value, height = props.h ?? (props.wrap, lines.value.length || 1);
3478
+ return translateRect(
3479
+ { x: props.x, y: props.y, w: width, h: height },
3480
+ layout.originX,
3481
+ layout.originY
3482
+ );
3483
+ });
3484
+ return useRenderNode(() => ({
3485
+ zIndex: props.zIndex,
3486
+ rect: visible.value ? absRect.value : { x: 0, y: 0, w: 0, h: 0 },
3487
+ deps: [
3488
+ visible.value,
3489
+ absRect.value,
3490
+ fullRect.value,
3491
+ props.value,
3492
+ props.w,
3493
+ props.h,
3494
+ props.wrap,
3495
+ props.style,
3496
+ defaultStyle.value,
3497
+ props.depsKey
3498
+ ],
3499
+ paint: (dirtyRows) => {
3500
+ if (!visible.value)
3501
+ return;
3502
+ let r = absRect.value;
3503
+ if (r.w <= 0 || r.h <= 0)
3504
+ return;
3505
+ 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) => {
3506
+ let relY = y - r.y;
3507
+ if (relY < 0 || relY >= r.h)
3508
+ return;
3509
+ let i = y - fullY;
3510
+ if (i < 0 || i >= out.length) {
3511
+ props.clear && terminal.write(blank, { x: r.x, y, style });
3512
+ return;
3513
+ }
3514
+ let src = out[i] ?? "", clipped = dx > 0 ? sliceByCellsRange(src, dx, dx + r.w) : sliceByCells(src, r.w);
3515
+ terminal.write(padEndByCells(clipped, r.w), { x: r.x, y, style });
3516
+ };
3517
+ if (!dirtyRows) {
3518
+ for (let i = 0; i < r.h; i++)
3519
+ paintRow(r.y + i);
3520
+ return;
3521
+ }
3522
+ for (let y of dirtyRows)
3523
+ paintRow(y);
3524
+ }
3525
+ })), () => (0, import_vue11.h)("span", rootProps);
3526
+ }
3527
+ });
3528
+
3529
+ // src/vue/components/TView.ts
3530
+ var import_vue12 = require("vue");
3531
+ var EMPTY_RECT = Object.freeze({ x: 0, y: 0, w: 0, h: 0 }), TView = (0, import_vue12.defineComponent)({
3532
+ name: "TView",
3533
+ props: {
3534
+ x: { type: Number, required: !0 },
3535
+ y: { type: Number, required: !0 },
3536
+ w: { type: Number, required: !0 },
3537
+ h: { type: Number, required: !0 },
3538
+ zIndex: { type: Number, default: 0 },
3539
+ scrollX: { type: Number, default: 0 },
3540
+ scrollY: { type: Number, default: 0 },
3541
+ focusable: { type: Boolean, default: !1 },
3542
+ selectable: { type: Boolean, default: void 0 },
3543
+ selectionScrollBy: {
3544
+ type: Function,
3545
+ default: void 0
3546
+ },
3547
+ autoFocus: { type: Boolean, default: !1 }
3548
+ },
3549
+ emits: [
3550
+ "clickCapture",
3551
+ "click",
3552
+ "dblclickCapture",
3553
+ "dblclick",
3554
+ "pointerdownCapture",
3555
+ "pointerdown",
3556
+ "pointerupCapture",
3557
+ "pointerup",
3558
+ "pointermoveCapture",
3559
+ "pointermove",
3560
+ "pointerenterCapture",
3561
+ "pointerenter",
3562
+ "pointerleaveCapture",
3563
+ "pointerleave",
3564
+ "wheelCapture",
3565
+ "wheel",
3566
+ "keydownCapture",
3567
+ "keydown",
3568
+ "keyupCapture",
3569
+ "keyup",
3570
+ "focusCapture",
3571
+ "focus",
3572
+ "blurCapture",
3573
+ "blur"
3574
+ ],
3575
+ setup(props, { emit, slots }) {
3576
+ let parent = useLayout(), { render, events } = useTerminal(), parentStack = useRenderStack(), { visible, rootProps } = useVisibility({ provide: !0 }), parentEventZ = (0, import_vue12.inject)(EventZIndexContextKey, (0, import_vue12.computed)(() => 0)), eventZ = (0, import_vue12.computed)(() => (parentEventZ.value ?? 0) + (props.zIndex ?? 0)), rawRect = (0, import_vue12.computed)(
3577
+ () => translateRect(
3578
+ { x: props.x, y: props.y, w: props.w, h: props.h },
3579
+ parent.originX,
3580
+ parent.originY
3581
+ )
3582
+ ), rect = (0, import_vue12.computed)(() => {
3583
+ let translated = rawRect.value;
3584
+ return parent.clipRect ? intersectRect(translated, parent.clipRect) ?? EMPTY_RECT : translated;
3585
+ }), { id } = useTerminalNode(() => ({
3586
+ rect: rect.value,
3587
+ zIndex: eventZ.value,
3588
+ visible: visible.value,
3589
+ focusable: props.focusable,
3590
+ selectable: props.selectable,
3591
+ selectionScrollBy: props.selectionScrollBy,
3592
+ handlers: {
3593
+ clickCapture: (e) => emit("clickCapture", e),
3594
+ click: (e) => emit("click", e),
3595
+ dblclickCapture: (e) => emit("dblclickCapture", e),
3596
+ dblclick: (e) => emit("dblclick", e),
3597
+ pointerdownCapture: (e) => emit("pointerdownCapture", e),
3598
+ pointerdown: (e) => emit("pointerdown", e),
3599
+ pointerupCapture: (e) => emit("pointerupCapture", e),
3600
+ pointerup: (e) => emit("pointerup", e),
3601
+ pointermoveCapture: (e) => emit("pointermoveCapture", e),
3602
+ pointermove: (e) => emit("pointermove", e),
3603
+ pointerenterCapture: (e) => emit("pointerenterCapture", e),
3604
+ pointerenter: (e) => emit("pointerenter", e),
3605
+ pointerleaveCapture: (e) => emit("pointerleaveCapture", e),
3606
+ pointerleave: (e) => emit("pointerleave", e),
3607
+ wheelCapture: (e) => emit("wheelCapture", e),
3608
+ wheel: (e) => emit("wheel", e),
3609
+ keydownCapture: (e) => emit("keydownCapture", e),
3610
+ keydown: (e) => emit("keydown", e),
3611
+ keyupCapture: (e) => emit("keyupCapture", e),
3612
+ keyup: (e) => emit("keyup", e),
3613
+ focusCapture: (e) => emit("focusCapture", e),
3614
+ focus: (e) => emit("focus", e),
3615
+ blurCapture: (e) => emit("blurCapture", e),
3616
+ blur: (e) => emit("blur", e)
3617
+ }
3618
+ }));
3619
+ (0, import_vue12.watchEffect)(() => {
3620
+ if (!props.autoFocus || !visible.value)
3621
+ return;
3622
+ let manager = events.value, nodeId = id.value;
3623
+ !manager || !nodeId || manager.getFocused() !== nodeId && manager.focus(nodeId);
3624
+ });
3625
+ let childLayout = (0, import_vue12.shallowReactive)({
3626
+ originX: 0,
3627
+ originY: 0,
3628
+ clipRect: null
3629
+ }), childStack = (0, import_vue12.computed)(() => render.createStack(parentStack.value, props.zIndex));
3630
+ return (0, import_vue12.watchEffect)(() => {
3631
+ let translated = rawRect.value;
3632
+ childLayout.originX = translated.x - Math.floor(props.scrollX), childLayout.originY = translated.y - Math.floor(props.scrollY), childLayout.clipRect = rect.value;
3633
+ }), (0, import_vue12.provide)(LayoutContextKey, childLayout), (0, import_vue12.provide)(RenderStackKey, childStack), (0, import_vue12.provide)(EventZIndexContextKey, eventZ), () => (0, import_vue12.h)("div", rootProps, slots.default?.());
3634
+ }
3635
+ });
3636
+
3637
+ // src/vue/components/TVideo.ts
3638
+ 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];
3639
+ function positiveInt2(value, fallback, max) {
3640
+ let parsed = Math.floor(Number(value));
3641
+ return !Number.isFinite(parsed) || parsed <= 0 ? Math.min(max, fallback) : Math.min(max, parsed);
3642
+ }
3643
+ function positiveNumber(value, fallback, max) {
3644
+ let parsed = Number(value);
3645
+ return !Number.isFinite(parsed) || parsed <= 0 ? fallback : Math.min(max, parsed);
3646
+ }
3647
+ function playbackRate(value) {
3648
+ return value === 2 || value === 3 ? value : 1;
3649
+ }
3650
+ function optionalDuration(value) {
3651
+ let parsed = Number(value);
3652
+ return Number.isFinite(parsed) && parsed > 0 ? parsed : void 0;
3653
+ }
3654
+ function formatPlaybackTime(valueMs, hourDigits = 0) {
3655
+ if (valueMs == null)
3656
+ return "--:--";
3657
+ let seconds = Math.max(0, Math.floor(valueMs / 1e3)), hours = Math.floor(seconds / 3600), minutes = Math.floor(seconds % 3600 / 60), remainder = seconds % 60;
3658
+ 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")}`;
3659
+ }
3660
+ function readUint32(bytes, offset) {
3661
+ return bytes[offset] * 16777216 + (bytes[offset + 1] << 16) + (bytes[offset + 2] << 8) + bytes[offset + 3] >>> 0;
3662
+ }
3663
+ function normalizeFrame(frame) {
3664
+ if (frame.format === "gray8") {
3665
+ let pixelWidth2 = Math.floor(Number(frame.pixelWidth)), pixelHeight2 = Math.floor(Number(frame.pixelHeight)), pixels = frame.pixels;
3666
+ 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)
3667
+ throw new Error("TVideo gray8 frame must match its bounded pixel dimensions");
3668
+ return {
3669
+ format: "gray8",
3670
+ pixels,
3671
+ timestampMs: Math.max(0, Number(frame.timestampMs) || 0),
3672
+ pixelWidth: pixelWidth2,
3673
+ pixelHeight: pixelHeight2,
3674
+ fingerprint: frame.fingerprint,
3675
+ durationMs: optionalDuration(frame.durationMs)
3676
+ };
3677
+ }
3678
+ let png = frame.png;
3679
+ if (!(png instanceof Uint8Array) || png.length < 24 || png.length > MAX_FRAME_BYTES)
3680
+ throw new Error("TVideo frame must contain a bounded PNG Uint8Array");
3681
+ 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)
3682
+ throw new Error("TVideo frame source emitted invalid PNG data");
3683
+ let pixelWidth = readUint32(png, 16), pixelHeight = readUint32(png, 20);
3684
+ if (pixelWidth <= 0 || pixelHeight <= 0 || pixelWidth > MAX_PIXEL_DIMENSION || pixelHeight > MAX_PIXEL_DIMENSION)
3685
+ throw new Error(`TVideo frame has an unsupported size: ${pixelWidth}x${pixelHeight}`);
3686
+ return {
3687
+ format: "png",
3688
+ png,
3689
+ timestampMs: Math.max(0, Number(frame.timestampMs) || 0),
3690
+ pixelWidth,
3691
+ pixelHeight,
3692
+ fingerprint: frame.fingerprint,
3693
+ durationMs: optionalDuration(frame.durationMs)
3694
+ };
3695
+ }
3696
+ function frameBytes(frame) {
3697
+ return frame.format === "gray8" ? frame.pixels : frame.png;
3698
+ }
3699
+ function gray8ToAscii(frame, cellWidth) {
3700
+ let lines = [], width = Math.max(1, Math.floor(cellWidth));
3701
+ for (let y = 0; y < frame.pixelHeight; y++) {
3702
+ let line = "", rowStart = y * frame.pixelWidth;
3703
+ for (let x = 0; x < frame.pixelWidth; x++) {
3704
+ let value = frame.pixels[rowStart + x], glyph = ASCII_RAMP[Math.min(ASCII_RAMP.length - 1, value * ASCII_RAMP.length >> 8)];
3705
+ line += `${glyph}${glyph}`;
3706
+ }
3707
+ lines.push(line.slice(0, width));
3708
+ }
3709
+ return lines.join(`
3710
+ `);
3711
+ }
3712
+ function sameBytes(left, right) {
3713
+ if (left.length !== right.length)
3714
+ return !1;
3715
+ for (let index = 0; index < left.length; index++)
3716
+ if (left[index] !== right[index])
3717
+ return !1;
3718
+ return !0;
3719
+ }
3720
+ function bytesToBase64(bytes) {
3721
+ let alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/", chunks = [], chunk = "";
3722
+ for (let index = 0; index < bytes.length; index += 3) {
3723
+ 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;
3724
+ 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 = "");
3725
+ }
3726
+ return chunk && chunks.push(chunk), chunks.join("");
3727
+ }
3728
+ function resolveKittyPlacement(frame, context) {
3729
+ let rect = context.viewport.rect, full = context.viewport.fullRect, columns = Math.max(1, Math.floor(rect.w)), rows = Math.max(1, Math.floor(rect.h));
3730
+ if (full.w <= 0 || full.h <= 0)
3731
+ return { columns, rows };
3732
+ 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));
3733
+ if (offsetX <= 0 && offsetY <= 0 && visibleW >= full.w && visibleH >= full.h)
3734
+ return { columns, rows };
3735
+ let sourceX = Math.max(
3736
+ 0,
3737
+ Math.min(frame.pixelWidth - 1, Math.floor(offsetX * frame.pixelWidth / full.w))
3738
+ ), sourceY = Math.max(
3739
+ 0,
3740
+ Math.min(frame.pixelHeight - 1, Math.floor(offsetY * frame.pixelHeight / full.h))
3741
+ ), sourceRight = Math.max(
3742
+ sourceX + 1,
3743
+ Math.min(frame.pixelWidth, Math.ceil((offsetX + visibleW) * frame.pixelWidth / full.w))
3744
+ ), sourceBottom = Math.max(
3745
+ sourceY + 1,
3746
+ Math.min(frame.pixelHeight, Math.ceil((offsetY + visibleH) * frame.pixelHeight / full.h))
3747
+ );
3748
+ return {
3749
+ columns,
3750
+ rows,
3751
+ sourceX,
3752
+ sourceY,
3753
+ sourceWidth: sourceRight - sourceX,
3754
+ sourceHeight: sourceBottom - sourceY
3755
+ };
3756
+ }
3757
+ function createFrameRenderer(frame, cellWidth) {
3758
+ if (frame.format === "gray8") {
3759
+ let text = gray8ToAscii(frame, cellWidth);
3760
+ return () => ({ type: "text", text });
3761
+ }
3762
+ let base64;
3763
+ return (_content, context) => {
3764
+ if (!context.visible || !context.rawVisible)
3765
+ return null;
3766
+ if (base64 ?? (base64 = bytesToBase64(frame.png)), context.protocol === "kitty") {
3767
+ let placement = resolveKittyPlacement(frame, context);
3768
+ return {
3769
+ type: "sequence",
3770
+ protocol: "kitty",
3771
+ sequence: createKittyGraphicsSequence(base64, {
3772
+ imageId: context.imageId,
3773
+ placementId: context.placementId,
3774
+ ...placement
3775
+ }),
3776
+ resizeSequence: createKittyPlacementSequence({
3777
+ imageId: context.imageId,
3778
+ placementId: context.placementId,
3779
+ ...placement
3780
+ }),
3781
+ clearSequence: createKittyDeleteGraphicsSequence({
3782
+ imageId: context.imageId,
3783
+ placementId: context.placementId,
3784
+ freeImageData: !0
3785
+ }),
3786
+ cols: context.width,
3787
+ rows: context.height,
3788
+ sourceWidth: frame.pixelWidth,
3789
+ sourceHeight: frame.pixelHeight
3790
+ };
3791
+ }
3792
+ return context.protocol === "iterm2" ? {
3793
+ type: "sequence",
3794
+ protocol: "iterm2",
3795
+ sequence: createIterm2InlineImageSequence(base64, {
3796
+ width: context.width,
3797
+ height: context.height,
3798
+ preserveAspectRatio: !0,
3799
+ doNotMoveCursor: !0
3800
+ }),
3801
+ cols: context.width,
3802
+ rows: context.height,
3803
+ sourceWidth: frame.pixelWidth,
3804
+ sourceHeight: frame.pixelHeight
3805
+ } : null;
3806
+ };
3807
+ }
3808
+ function errorMessage2(error) {
3809
+ return error instanceof Error ? error.message : String(error);
3810
+ }
3811
+ var tVideoProps = {
3812
+ x: { type: Number, required: !0 },
3813
+ y: { type: Number, required: !0 },
3814
+ w: { type: Number, required: !0 },
3815
+ h: { type: Number, required: !0 },
3816
+ zIndex: { type: Number, default: 0 },
3817
+ src: { type: String, required: !0 },
3818
+ frameSource: {
3819
+ type: Function,
3820
+ required: !0
3821
+ },
3822
+ paused: { type: Boolean, default: void 0 },
3823
+ playbackRate: { type: Number, default: void 0 },
3824
+ controls: { type: Boolean, default: !1 },
3825
+ controlsLayout: {
3826
+ type: String,
3827
+ default: "compact"
3828
+ },
3829
+ durationMs: { type: Number, default: void 0 },
3830
+ loop: { type: Boolean, default: !1 },
3831
+ maxFps: { type: Number, default: DEFAULT_MAX_FPS },
3832
+ pixelWidth: { type: Number, default: void 0 },
3833
+ pixelHeight: { type: Number, default: void 0 },
3834
+ fallback: { type: String, default: "[video]" },
3835
+ style: { type: Object, default: void 0 },
3836
+ clear: { type: Boolean, default: !0 }
3837
+ }, TVideo = (0, import_vue13.defineComponent)({
3838
+ name: "TVideo",
3839
+ props: tVideoProps,
3840
+ emits: {
3841
+ frame: (_event) => !0,
3842
+ ended: () => !0,
3843
+ error: (_error) => !0,
3844
+ seek: (_event) => !0,
3845
+ "update:paused": (_paused) => !0,
3846
+ "update:playbackRate": (_rate) => !0
3847
+ },
3848
+ setup(props, { emit }) {
3849
+ let instance = (0, import_vue13.getCurrentInstance)(), { terminal, scheduler } = useTerminal(), layout = useLayout(), { visible, rootProps } = useVisibility({ provide: !0 }), graphicsActivity = (0, import_vue13.inject)(TerminalGraphicsActivityKey, null), frameRenderer = (0, import_vue13.shallowRef)(), playbackError = (0, import_vue13.shallowRef)(""), internalPaused = (0, import_vue13.shallowRef)(props.paused ?? !1), internalPlaybackRate = (0, import_vue13.shallowRef)(playbackRate(props.playbackRate)), discoveredDurationMs = (0, import_vue13.shallowRef)(), displayedTimestampMs = (0, import_vue13.shallowRef)(0), seekPreviewMs = (0, import_vue13.shallowRef)(), seeking = (0, import_vue13.shallowRef)(!1), terminalSizeVersion = (0, import_vue13.shallowRef)(0), graphicsOutputVersion = (0, import_vue13.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", () => {
3850
+ terminalSizeVersion.value++;
3851
+ }), unsubscribeGraphicsOutput = subscribeTerminalGraphicsOutput(terminal, () => {
3852
+ graphicsOutputVersion.value = getTerminalGraphicsOutputVersion(terminal);
3853
+ }), showControls = (0, import_vue13.computed)(
3854
+ () => props.controls && Math.floor(props.w) >= 14 && Math.floor(props.h) >= 2
3855
+ ), resolvedControlsLayout = (0, import_vue13.computed)(
3856
+ () => props.controlsLayout === "cinema" && Math.floor(props.h) >= 3 ? "cinema" : "compact"
3857
+ ), controlRows = (0, import_vue13.computed)(
3858
+ () => showControls.value ? resolvedControlsLayout.value === "cinema" ? 2 : 1 : 0
3859
+ ), videoHeight = (0, import_vue13.computed)(() => Math.max(1, Math.floor(props.h) - controlRows.value)), resolvedMaxFps = (0, import_vue13.computed)(() => positiveNumber(props.maxFps, DEFAULT_MAX_FPS, 60)), resolvedPixelSize = (0, import_vue13.computed)(() => {
3860
+ let desiredWidth = Math.max(2, Math.floor(props.w) * 8), desiredHeight = Math.max(2, videoHeight.value * 16);
3861
+ if (props.pixelWidth == null && props.pixelHeight == null) {
3862
+ let scale = Math.min(
3863
+ 1,
3864
+ DEFAULT_MAX_PIXEL_WIDTH / desiredWidth,
3865
+ DEFAULT_MAX_PIXEL_HEIGHT / desiredHeight
3866
+ );
3867
+ return {
3868
+ width: Math.max(2, Math.floor(desiredWidth * scale)),
3869
+ height: Math.max(2, Math.floor(desiredHeight * scale))
3870
+ };
3871
+ }
3872
+ if (props.pixelWidth != null && props.pixelHeight == null) {
3873
+ let width = positiveInt2(props.pixelWidth, desiredWidth, MAX_PIXEL_DIMENSION), inferredHeight = width * desiredHeight / desiredWidth, scale = Math.min(1, MAX_PIXEL_DIMENSION / inferredHeight);
3874
+ return {
3875
+ width: Math.max(2, Math.floor(width * scale)),
3876
+ height: Math.max(2, Math.floor(inferredHeight * scale))
3877
+ };
3878
+ }
3879
+ if (props.pixelWidth == null && props.pixelHeight != null) {
3880
+ let height = positiveInt2(props.pixelHeight, desiredHeight, MAX_PIXEL_DIMENSION), inferredWidth = height * desiredWidth / desiredHeight, scale = Math.min(1, MAX_PIXEL_DIMENSION / inferredWidth);
3881
+ return {
3882
+ width: Math.max(2, Math.floor(inferredWidth * scale)),
3883
+ height: Math.max(2, Math.floor(height * scale))
3884
+ };
3885
+ }
3886
+ return {
3887
+ width: positiveInt2(props.pixelWidth, desiredWidth, MAX_PIXEL_DIMENSION),
3888
+ height: positiveInt2(props.pixelHeight, desiredHeight, MAX_PIXEL_DIMENSION)
3889
+ };
3890
+ }), resolvedPixelWidth = (0, import_vue13.computed)(() => resolvedPixelSize.value.width), resolvedPixelHeight = (0, import_vue13.computed)(() => resolvedPixelSize.value.height), paintable = (0, import_vue13.computed)(() => {
3891
+ if (terminalSizeVersion.value, !visible.value)
3892
+ return !1;
3893
+ let size = terminal.size(), terminalRect = {
3894
+ x: 0,
3895
+ y: 0,
3896
+ w: Math.max(0, Math.floor(size.cols)),
3897
+ h: Math.max(0, Math.floor(size.rows))
3898
+ }, clip = layout.clipRect ? intersectRect(layout.clipRect, terminalRect) : terminalRect;
3899
+ if (!clip)
3900
+ return !1;
3901
+ let rect = translateRect(
3902
+ { x: props.x, y: props.y, w: props.w, h: videoHeight.value },
3903
+ layout.originX,
3904
+ layout.originY
3905
+ ), visibleRect = intersectRect(rect, clip);
3906
+ return !!(visibleRect && visibleRect.w > 0 && visibleRect.h > 0);
3907
+ }), graphicsProtocol = (0, import_vue13.computed)(() => (graphicsOutputVersion.value, getTerminalGraphicsOutput(terminal)?.capabilities.preferredProtocol ?? null)), preferredFormat = (0, import_vue13.computed)(
3908
+ () => graphicsProtocol.value === "kitty" || graphicsProtocol.value === "iterm2" ? "png" : "gray8"
3909
+ ), resolvedDecodeFps = (0, import_vue13.computed)(
3910
+ () => preferredFormat.value === "gray8" ? Math.min(MAX_GRAY8_FPS, resolvedMaxFps.value) : resolvedMaxFps.value
3911
+ ), resolvedDecodeWidth = (0, import_vue13.computed)(
3912
+ () => preferredFormat.value === "gray8" ? positiveInt2(Math.ceil(props.w / 2), 1, MAX_GRAY8_WIDTH) : resolvedPixelWidth.value
3913
+ ), resolvedDecodeHeight = (0, import_vue13.computed)(
3914
+ () => preferredFormat.value === "gray8" ? positiveInt2(videoHeight.value, 1, MAX_GRAY8_HEIGHT) : resolvedPixelHeight.value
3915
+ ), resolvedDurationMs = (0, import_vue13.computed)(
3916
+ () => optionalDuration(props.durationMs) ?? discoveredDurationMs.value
3917
+ ), effectivePaused = (0, import_vue13.computed)(() => props.paused ?? internalPaused.value), effectivePlaybackRate = (0, import_vue13.computed)(
3918
+ () => props.playbackRate == null ? internalPlaybackRate.value : playbackRate(props.playbackRate)
3919
+ ), controlTimestampMs = (0, import_vue13.computed)(() => seekPreviewMs.value ?? displayedTimestampMs.value), timeHourDigits = (0, import_vue13.computed)(() => {
3920
+ let duration = resolvedDurationMs.value;
3921
+ return !duration || duration < 36e5 ? 0 : String(Math.floor(duration / 36e5)).length;
3922
+ }), currentTimeText = (0, import_vue13.computed)(
3923
+ () => formatPlaybackTime(controlTimestampMs.value, timeHourDigits.value)
3924
+ ), durationTimeText = (0, import_vue13.computed)(
3925
+ () => formatPlaybackTime(resolvedDurationMs.value, timeHourDigits.value)
3926
+ ), controlLayout = (0, import_vue13.computed)(() => {
3927
+ 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;
3928
+ if (resolvedControlsLayout.value === "cinema") {
3929
+ let ratesX2 = Math.max(3, width - ratesWidth), timeText = `${current} / ${duration}`;
3930
+ return {
3931
+ width,
3932
+ kind: "cinema",
3933
+ progressX: 0,
3934
+ progressY,
3935
+ progressWidth: width,
3936
+ actionY: progressY + 1,
3937
+ ratesX: ratesX2,
3938
+ showAllRates: !0,
3939
+ showTimes: 3 + textCellWidth(timeText) < ratesX2,
3940
+ current,
3941
+ duration,
3942
+ timeText,
3943
+ timeWidth,
3944
+ currentX: 3,
3945
+ totalX: 0
3946
+ };
3947
+ }
3948
+ let ratesX = width - ratesWidth, progressX = timeWidth + 4, totalX = ratesX - timeWidth - 1, progressWidth = totalX - progressX - 1;
3949
+ if (progressWidth >= 4)
3950
+ return {
3951
+ width,
3952
+ kind: "compact",
3953
+ progressX,
3954
+ progressY,
3955
+ progressWidth,
3956
+ actionY: progressY,
3957
+ ratesX,
3958
+ showAllRates: !0,
3959
+ showTimes: !0,
3960
+ current,
3961
+ duration,
3962
+ timeText: "",
3963
+ timeWidth,
3964
+ currentX: 3,
3965
+ totalX
3966
+ };
3967
+ let compactRatesX = Math.max(4, width - 2);
3968
+ return {
3969
+ width,
3970
+ kind: "compact",
3971
+ progressX: 3,
3972
+ progressY,
3973
+ progressWidth: Math.max(1, compactRatesX - 4),
3974
+ actionY: progressY,
3975
+ ratesX: compactRatesX,
3976
+ showAllRates: !1,
3977
+ showTimes: !1,
3978
+ current,
3979
+ duration,
3980
+ timeText: "",
3981
+ timeWidth,
3982
+ currentX: 0,
3983
+ totalX: 0
3984
+ };
3985
+ }), rateStyles = (0, import_vue13.computed)(
3986
+ () => PLAYBACK_RATES.map(
3987
+ (rate) => rate === effectivePlaybackRate.value ? { ...props.style, inverse: !0 } : props.style
3988
+ )
3989
+ ), remainingProgressStyle = (0, import_vue13.computed)(() => ({ ...props.style, dim: !0 })), progressThumbStyle = (0, import_vue13.computed)(() => ({ ...props.style, inverse: !0 })), progressSegments = (0, import_vue13.computed)(() => {
3990
+ let { progressWidth } = controlLayout.value, duration = resolvedDurationMs.value;
3991
+ if (!duration)
3992
+ return { playedWidth: 0, thumbWidth: 0, remainingWidth: progressWidth };
3993
+ let ratio = Math.max(0, Math.min(1, controlTimestampMs.value / duration)), marker = Math.round(ratio * Math.max(0, progressWidth - 1));
3994
+ return {
3995
+ playedWidth: marker,
3996
+ thumbWidth: 1,
3997
+ remainingWidth: progressWidth - marker - 1
3998
+ };
3999
+ }), controlFill = (0, import_vue13.computed)(() => " ".repeat(controlLayout.value.width)), progressGlyphs = (0, import_vue13.computed)(() => ({
4000
+ played: "\u2501".repeat(progressSegments.value.playedWidth),
4001
+ remaining: "\u2500".repeat(progressSegments.value.remainingWidth)
4002
+ })), playbackEnabled = (0, import_vue13.computed)(
4003
+ () => alive && !effectivePaused.value && !graphicsActivity?.scrolling.value && props.src.trim().length > 0 && paintable.value
4004
+ ), shouldPlay = (0, import_vue13.computed)(() => playbackEnabled.value && !seeking.value), visibleFallback = (0, import_vue13.computed)(
4005
+ () => playbackError.value ? `${props.fallback}: ${playbackError.value}` : props.fallback
4006
+ );
4007
+ function timelineTimestamp(timestampMs) {
4008
+ let duration = resolvedDurationMs.value;
4009
+ return duration ? props.loop ? Math.max(0, timestampMs) % duration : Math.max(0, Math.min(duration, timestampMs)) : Math.max(0, timestampMs);
4010
+ }
4011
+ function seekTimestamp(timestampMs) {
4012
+ let duration = resolvedDurationMs.value;
4013
+ if (!duration)
4014
+ return Math.max(0, timestampMs);
4015
+ let end = props.loop ? Math.max(0, duration - 1) : duration;
4016
+ return Math.max(0, Math.min(end, timestampMs));
4017
+ }
4018
+ function updateTimestamp(timestampMs, force = !1) {
4019
+ let next = timelineTimestamp(timestampMs);
4020
+ if (lastTimestampMs = next, !showControls.value)
4021
+ return;
4022
+ let threshold = CONTROL_REFRESH_MS * effectivePlaybackRate.value;
4023
+ (force || next < displayedTimestampMs.value || Math.abs(next - displayedTimestampMs.value) >= threshold) && (displayedTimestampMs.value = next);
4024
+ }
4025
+ function commitFrame(frame, dropped) {
4026
+ if (!alive)
4027
+ return;
4028
+ droppedFrames += dropped, frameRenderer.value = (0, import_vue13.markRaw)(createFrameRenderer(frame, props.w)), updateTimestamp(frame.timestampMs);
4029
+ let durationMs = resolvedDurationMs.value;
4030
+ emit("frame", {
4031
+ timestampMs: frame.timestampMs,
4032
+ pixelWidth: frame.pixelWidth,
4033
+ pixelHeight: frame.pixelHeight,
4034
+ droppedFrames,
4035
+ ...durationMs ? { durationMs } : {},
4036
+ playbackRate: effectivePlaybackRate.value
4037
+ });
4038
+ }
4039
+ let mailbox = createFrameMailbox({
4040
+ scheduler,
4041
+ id: mailboxId,
4042
+ reason: "stream",
4043
+ priority: "low",
4044
+ apply(frame, _context, meta) {
4045
+ commitFrame(frame, meta.dropped), pendingEndedGeneration === generation && (pendingEndedGeneration = null, emit("ended"));
4046
+ }
4047
+ });
4048
+ function stopPlayback() {
4049
+ generation++, pendingEndedGeneration = null;
4050
+ let discardedPendingFrame = mailbox.hasPending();
4051
+ mailbox.cancel(), discardedPendingFrame && (lastQueuedBytes = null, lastQueuedFormat = null, lastQueuedFingerprint = void 0), activeAbort?.abort(), activeAbort = null;
4052
+ }
4053
+ function resetQueuedFrameIdentity() {
4054
+ lastSourceBytes = null, lastQueuedBytes = null, lastQueuedFormat = null, lastQueuedFingerprint = void 0;
4055
+ }
4056
+ function setPaused(paused) {
4057
+ effectivePaused.value !== paused && (props.paused == null && (internalPaused.value = paused), emit("update:paused", paused));
4058
+ }
4059
+ function setPlaybackRate(rate) {
4060
+ let next = playbackRate(rate);
4061
+ effectivePlaybackRate.value !== next && (props.playbackRate == null && (internalPlaybackRate.value = next), emit("update:playbackRate", next));
4062
+ }
4063
+ function applySeek(timestampMs, restart) {
4064
+ let parsed = Number(timestampMs);
4065
+ if (!Number.isFinite(parsed))
4066
+ return;
4067
+ stopPlayback(), resetQueuedFrameIdentity();
4068
+ let next = seekTimestamp(parsed);
4069
+ updateTimestamp(next, !0), seekPreviewMs.value = void 0;
4070
+ let durationMs = resolvedDurationMs.value;
4071
+ emit("seek", {
4072
+ timestampMs: next,
4073
+ ...durationMs ? { durationMs } : {}
4074
+ }), restart && startPlayback(effectivePaused.value);
4075
+ }
4076
+ function controlCell(event) {
4077
+ return {
4078
+ x: Math.floor(event.cellX - layout.originX - props.x),
4079
+ y: Math.floor(event.cellY - layout.originY - props.y)
4080
+ };
4081
+ }
4082
+ function previewSeekAt(cellX) {
4083
+ let duration = resolvedDurationMs.value;
4084
+ if (!duration)
4085
+ return;
4086
+ let { progressX, progressWidth } = controlLayout.value, offset = Math.max(0, Math.min(progressWidth - 1, cellX - progressX));
4087
+ seekPreviewMs.value = progressWidth <= 1 ? 0 : offset / Math.max(1, progressWidth - 1) * duration;
4088
+ }
4089
+ function captureControlPointer(event) {
4090
+ let native = event.nativeEvent, pointerId = native?.pointerId, target = native?.target;
4091
+ pointerId == null || !target?.setPointerCapture || (target.setPointerCapture(pointerId), controlPointerCapture = { pointerId, target });
4092
+ }
4093
+ function releaseControlPointer() {
4094
+ controlPointerCapture && (controlPointerCapture.target.releasePointerCapture?.(controlPointerCapture.pointerId), controlPointerCapture = null);
4095
+ }
4096
+ function rateAt(cellX) {
4097
+ let { ratesX, showAllRates } = controlLayout.value, offset = cellX - ratesX;
4098
+ if (!showAllRates) {
4099
+ if (offset < 0 || offset >= 2)
4100
+ return;
4101
+ let index = PLAYBACK_RATES.indexOf(effectivePlaybackRate.value);
4102
+ return PLAYBACK_RATES[(index + 1) % PLAYBACK_RATES.length];
4103
+ }
4104
+ if (!(offset < 0 || offset % 3 >= 2))
4105
+ return PLAYBACK_RATES[Math.floor(offset / 3)];
4106
+ }
4107
+ function onInteractivePointerDown(event) {
4108
+ if (event.button != null && event.button !== 0)
4109
+ return;
4110
+ let { x: cellX, y: cellY } = controlCell(event);
4111
+ if (cellY < videoHeight.value) {
4112
+ suppressNextVideoClick = !1;
4113
+ return;
4114
+ }
4115
+ if (!showControls.value)
4116
+ return;
4117
+ let { actionY, progressY, progressX, progressWidth } = controlLayout.value, rate = rateAt(cellX);
4118
+ if (cellY === actionY && cellX <= 1) {
4119
+ event.preventDefault(), event.stopPropagation(), suppressNextVideoClick = !0, setPaused(!effectivePaused.value);
4120
+ return;
4121
+ }
4122
+ if (cellY === actionY && rate) {
4123
+ event.preventDefault(), event.stopPropagation(), suppressNextVideoClick = !0, setPlaybackRate(rate);
4124
+ return;
4125
+ }
4126
+ cellY !== progressY || !resolvedDurationMs.value || cellX < progressX || cellX >= progressX + progressWidth || (event.preventDefault(), event.stopPropagation(), suppressNextVideoClick = !0, seeking.value = !0, stopPlayback(), previewSeekAt(cellX), captureControlPointer(event));
4127
+ }
4128
+ function onInteractivePointerMove(event) {
4129
+ if (seeking.value) {
4130
+ if (event.buttons === 0) {
4131
+ onInteractivePointerUp(event);
4132
+ return;
4133
+ }
4134
+ event.preventDefault(), event.stopPropagation(), previewSeekAt(controlCell(event).x);
4135
+ }
4136
+ }
4137
+ function onInteractivePointerUp(event) {
4138
+ if (!seeking.value)
4139
+ return;
4140
+ event.preventDefault(), event.stopPropagation(), previewSeekAt(controlCell(event).x);
4141
+ let timestampMs = seekPreviewMs.value ?? lastTimestampMs;
4142
+ applySeek(timestampMs, !1), seeking.value = !1, releaseControlPointer(), startPlayback(effectivePaused.value);
4143
+ }
4144
+ function onVideoClick(event) {
4145
+ if (!(event.button != null && event.button !== 0)) {
4146
+ if (suppressNextVideoClick) {
4147
+ suppressNextVideoClick = !1, event.preventDefault(), event.stopPropagation();
4148
+ return;
4149
+ }
4150
+ controlCell(event).y >= videoHeight.value || (event.preventDefault(), event.stopPropagation(), setPaused(!effectivePaused.value));
4151
+ }
4152
+ }
4153
+ function finishControlSeek() {
4154
+ if (!seeking.value)
4155
+ return;
4156
+ let timestampMs = seekPreviewMs.value ?? lastTimestampMs;
4157
+ applySeek(timestampMs, !1), seeking.value = !1, releaseControlPointer(), startPlayback(effectivePaused.value);
4158
+ }
4159
+ function onControlKeydown(event) {
4160
+ if (event.key === "Enter" || event.key === " " || event.key === "Spacebar") {
4161
+ event.preventDefault(), event.stopPropagation(), setPaused(!effectivePaused.value);
4162
+ return;
4163
+ }
4164
+ if (event.key === "ArrowUp" || event.key === "ArrowDown") {
4165
+ event.preventDefault(), event.stopPropagation();
4166
+ let index = PLAYBACK_RATES.indexOf(effectivePlaybackRate.value), offset = event.key === "ArrowUp" ? 1 : -1;
4167
+ setPlaybackRate(PLAYBACK_RATES[Math.max(0, Math.min(2, index + offset))]);
4168
+ return;
4169
+ }
4170
+ if (!event.repeat && (event.key === "Home" || event.key === "End") && resolvedDurationMs.value) {
4171
+ event.preventDefault(), event.stopPropagation(), applySeek(event.key === "Home" ? 0 : resolvedDurationMs.value, !0);
4172
+ return;
4173
+ }
4174
+ (event.key === "1" || event.key === "2" || event.key === "3") && (event.preventDefault(), event.stopPropagation(), setPlaybackRate(Number(event.key)));
4175
+ }
4176
+ function queueFrame(frame, expectedFormat) {
4177
+ let normalized = normalizeFrame(frame);
4178
+ if (normalized.format !== expectedFormat)
4179
+ throw new Error(`TVideo frame source did not provide requested ${expectedFormat} frames`);
4180
+ normalized.durationMs != null && normalized.durationMs !== discoveredDurationMs.value && (discoveredDurationMs.value = normalized.durationMs), normalized = { ...normalized, timestampMs: timelineTimestamp(normalized.timestampMs) };
4181
+ let sourceBytes = frameBytes(normalized), reusesSourceBuffer = sourceBytes === lastSourceBytes;
4182
+ lastSourceBytes = sourceBytes;
4183
+ 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;
4184
+ if (sameFingerprint || canCompareBytes && normalized.format === lastQueuedFormat && lastQueuedBytes && sameBytes(lastQueuedBytes, sourceBytes)) {
4185
+ lastQueuedBytes = bytes, lastQueuedFormat = normalized.format, lastQueuedFingerprint = normalized.fingerprint, updateTimestamp(normalized.timestampMs), mailbox.hasPending() && mailbox.replacePending(stableFrame);
4186
+ return;
4187
+ }
4188
+ lastQueuedBytes = bytes, lastQueuedFormat = normalized.format, lastQueuedFingerprint = normalized.fingerprint, mailbox.queue(stableFrame) || (commitFrame(stableFrame, 0), scheduler.invalidate({ priority: "low", reason: "stream" }));
4189
+ }
4190
+ function startPlayback(oneFrame = !1) {
4191
+ if (stopPlayback(), !shouldPlay.value && !(oneFrame && alive && props.src.trim().length > 0 && paintable.value && !graphicsActivity?.scrolling.value))
4192
+ return;
4193
+ let currentGeneration = generation, abort = new AbortController();
4194
+ activeAbort = abort, playbackError.value = "";
4195
+ let source = props.frameSource, format = preferredFormat.value, context = {
4196
+ src: props.src,
4197
+ signal: abort.signal,
4198
+ maxFps: resolvedDecodeFps.value,
4199
+ pixelWidth: resolvedDecodeWidth.value,
4200
+ pixelHeight: resolvedDecodeHeight.value,
4201
+ startAtMs: lastTimestampMs,
4202
+ preferredFormat: format,
4203
+ playbackRate: effectivePlaybackRate.value,
4204
+ loop: props.loop
4205
+ };
4206
+ (async () => {
4207
+ try {
4208
+ let frames = await source(context);
4209
+ for await (let frame of frames)
4210
+ if (!alive || abort.signal.aborted || currentGeneration !== generation || (queueFrame(frame, format), oneFrame))
4211
+ return;
4212
+ if (!alive || abort.signal.aborted || currentGeneration !== generation)
4213
+ return;
4214
+ mailbox.hasPending() ? pendingEndedGeneration = currentGeneration : emit("ended");
4215
+ } catch (error) {
4216
+ if (!alive || abort.signal.aborted || currentGeneration !== generation)
4217
+ return;
4218
+ playbackError.value = errorMessage2(error), emit("error", error), scheduler.invalidate({ priority: "low", reason: "data" });
4219
+ } finally {
4220
+ activeAbort === abort && (activeAbort = null);
4221
+ }
4222
+ })();
4223
+ }
4224
+ return (0, import_vue13.watch)(
4225
+ () => props.paused,
4226
+ (paused) => {
4227
+ paused != null && (internalPaused.value = paused);
4228
+ }
4229
+ ), (0, import_vue13.watch)(
4230
+ () => props.playbackRate,
4231
+ (rate) => {
4232
+ rate != null && (internalPlaybackRate.value = playbackRate(rate));
4233
+ }
4234
+ ), (0, import_vue13.watch)(
4235
+ [
4236
+ () => props.src,
4237
+ () => props.frameSource,
4238
+ playbackEnabled,
4239
+ resolvedDecodeFps,
4240
+ resolvedDecodeWidth,
4241
+ resolvedDecodeHeight,
4242
+ preferredFormat,
4243
+ effectivePlaybackRate,
4244
+ () => props.loop
4245
+ ],
4246
+ (next, previous) => {
4247
+ let sourceChanged = !previous || next[0] !== previous[0] || next[1] !== previous[1], formatChanged = !previous || next[6] !== previous[6];
4248
+ (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();
4249
+ },
4250
+ { immediate: !0, flush: "post" }
4251
+ ), (0, import_vue13.onBeforeUnmount)(() => {
4252
+ alive = !1, stopPlayback(), releaseControlPointer(), mailbox.dispose(), unsubscribeTerminalResize(), unsubscribeGraphicsOutput();
4253
+ }), () => {
4254
+ let children = [
4255
+ (0, import_vue13.h)(TAgentTerminalGraphic, {
4256
+ x: props.x,
4257
+ y: props.y,
4258
+ w: props.w,
4259
+ h: videoHeight.value,
4260
+ zIndex: props.zIndex,
4261
+ content: props.src.trim() ? props.src : "video",
4262
+ fallback: visibleFallback.value,
4263
+ style: props.style,
4264
+ clear: props.clear,
4265
+ final: !1,
4266
+ streaming: !0,
4267
+ renderer: frameRenderer.value,
4268
+ placementKey,
4269
+ preserveRawWhileRendering: !0,
4270
+ ignoreSamePlaneRawCoverage: !0,
4271
+ suspended: !paintable.value
4272
+ })
4273
+ ];
4274
+ return props.controls && children.push(
4275
+ (0, import_vue13.h)(
4276
+ TView,
4277
+ {
4278
+ x: props.x,
4279
+ y: props.y,
4280
+ w: Math.max(0, Math.floor(props.w)),
4281
+ h: Math.max(0, Math.floor(props.h)),
4282
+ zIndex: props.zIndex,
4283
+ focusable: !0,
4284
+ selectable: !1,
4285
+ onClick: onVideoClick,
4286
+ onPointerdown: onInteractivePointerDown,
4287
+ onPointermove: onInteractivePointerMove,
4288
+ onPointerup: onInteractivePointerUp,
4289
+ onKeydown: onControlKeydown,
4290
+ onBlur: finishControlSeek
4291
+ },
4292
+ () => {
4293
+ if (!showControls.value)
4294
+ return [];
4295
+ let layout2 = controlLayout.value, segments = progressSegments.value, controls = Array.from(
4296
+ { length: controlRows.value },
4297
+ (_, index) => (0, import_vue13.h)(TText, {
4298
+ x: 0,
4299
+ y: videoHeight.value + index,
4300
+ w: layout2.width,
4301
+ value: controlFill.value,
4302
+ style: props.style
4303
+ })
4304
+ );
4305
+ return controls.push(
4306
+ (0, import_vue13.h)(TText, {
4307
+ x: 0,
4308
+ y: layout2.actionY,
4309
+ w: 2,
4310
+ value: effectivePaused.value ? "> " : "||",
4311
+ style: props.style
4312
+ })
4313
+ ), layout2.showTimes && (layout2.kind === "cinema" ? controls.push(
4314
+ (0, import_vue13.h)(TText, {
4315
+ x: layout2.currentX,
4316
+ y: layout2.actionY,
4317
+ w: textCellWidth(layout2.timeText),
4318
+ value: layout2.timeText,
4319
+ style: props.style
4320
+ })
4321
+ ) : controls.push(
4322
+ (0, import_vue13.h)(TText, {
4323
+ x: layout2.currentX,
4324
+ y: layout2.actionY,
4325
+ w: layout2.timeWidth,
4326
+ value: layout2.current,
4327
+ style: props.style
4328
+ }),
4329
+ (0, import_vue13.h)(TText, {
4330
+ x: layout2.totalX,
4331
+ y: layout2.actionY,
4332
+ w: layout2.timeWidth,
4333
+ value: layout2.duration,
4334
+ style: props.style
4335
+ })
4336
+ )), segments.playedWidth > 0 && controls.push(
4337
+ (0, import_vue13.h)(TText, {
4338
+ x: layout2.progressX,
4339
+ y: layout2.progressY,
4340
+ w: segments.playedWidth,
4341
+ value: progressGlyphs.value.played,
4342
+ style: props.style
4343
+ })
4344
+ ), segments.thumbWidth > 0 && controls.push(
4345
+ (0, import_vue13.h)(TText, {
4346
+ x: layout2.progressX + segments.playedWidth,
4347
+ y: layout2.progressY,
4348
+ w: 1,
4349
+ value: "\u254B",
4350
+ style: progressThumbStyle.value
4351
+ })
4352
+ ), segments.remainingWidth > 0 && controls.push(
4353
+ (0, import_vue13.h)(TText, {
4354
+ x: layout2.progressX + segments.playedWidth + segments.thumbWidth,
4355
+ y: layout2.progressY,
4356
+ w: segments.remainingWidth,
4357
+ value: progressGlyphs.value.remaining,
4358
+ style: remainingProgressStyle.value
4359
+ })
4360
+ ), layout2.showAllRates ? controls.push(
4361
+ ...PLAYBACK_RATES.map(
4362
+ (rate, index) => (0, import_vue13.h)(TText, {
4363
+ x: layout2.ratesX + index * 3,
4364
+ y: layout2.actionY,
4365
+ w: 2,
4366
+ value: `${rate}x`,
4367
+ style: rateStyles.value[index]
4368
+ })
4369
+ )
4370
+ ) : controls.push(
4371
+ (0, import_vue13.h)(TText, {
4372
+ x: layout2.ratesX,
4373
+ y: layout2.actionY,
4374
+ w: 2,
4375
+ value: `${effectivePlaybackRate.value}x`,
4376
+ style: rateStyles.value[PLAYBACK_RATES.indexOf(effectivePlaybackRate.value)]
4377
+ })
4378
+ ), controls;
4379
+ }
4380
+ )
4381
+ ), (0, import_vue13.h)("span", rootProps, children);
4382
+ };
4383
+ }
4384
+ });
4385
+
4386
+ // src/vue/components/T3DViewport.ts
4387
+ var DEFAULT_MAX_FPS2 = 24, DEFAULT_AUTO_ROTATE_SPEED = 0.35, DEFAULT_POINTER_SENSITIVITY = 0.055, VELOCITY_DAMPING_PER_SECOND = 5.5, ZOOM_DAMPING_PER_SECOND = 7, MAX_ZOOM_VELOCITY = 3, DEFAULT_MIN_ZOOM = 0.65, DEFAULT_MAX_ZOOM = 1.65, DEFAULT_ZOOM_SENSITIVITY = 0.1, MAX_PITCH = Math.PI * 0.42, t3DViewportProps = {
4388
+ /** Horizontal position in terminal cells. */
4389
+ x: { type: Number, required: !0 },
4390
+ /** Vertical position in terminal cells. */
4391
+ y: { type: Number, required: !0 },
4392
+ /** Width in terminal cells. */
4393
+ w: { type: Number, required: !0 },
4394
+ /** Height in terminal cells. */
4395
+ h: { type: Number, required: !0 },
4396
+ /** Paint and pointer hit-test stacking order. */
4397
+ zIndex: { type: Number, default: 0 },
4398
+ /** Pull renderer captured at mount; remount the component to replace it. */
4399
+ renderer: { type: Object, required: !0 },
4400
+ /** Stops frame pulling while true. */
4401
+ paused: { type: Boolean, default: !1 },
4402
+ /** Maximum requested frames per second. */
4403
+ maxFps: { type: Number, default: DEFAULT_MAX_FPS2 },
4404
+ /** Requested source width in pixels; TVideo may adapt it for ASCII output. */
4405
+ pixelWidth: { type: Number, default: void 0 },
4406
+ /** Requested source height in pixels; TVideo may adapt it for ASCII output. */
4407
+ pixelHeight: { type: Number, default: void 0 },
4408
+ /** Text displayed before a frame is available or after rendering fails. */
4409
+ fallback: { type: String, default: "[3D viewport]" },
4410
+ /** Terminal style applied to fallback and ASCII output. */
4411
+ style: { type: Object, default: void 0 },
4412
+ /** Clears cells underneath each video frame. */
4413
+ clear: { type: Boolean, default: !0 },
4414
+ /** Enables pointer orbit, wheel zoom, and hover motion tracking. */
4415
+ interactive: { type: Boolean, default: !0 },
4416
+ /** Initial yaw angle in radians, also restored by resetMotion(). */
4417
+ initialYaw: { type: Number, default: 0 },
4418
+ /** Initial pitch angle in radians, also restored by resetMotion(). */
4419
+ initialPitch: { type: Number, default: 0 },
4420
+ /** Enables continuous yaw rotation when not dragging. */
4421
+ autoRotate: { type: Boolean, default: !0 },
4422
+ /** Automatic yaw rotation speed in radians per second. */
4423
+ autoRotateSpeed: { type: Number, default: DEFAULT_AUTO_ROTATE_SPEED },
4424
+ /** Drag sensitivity in radians per terminal cell. */
4425
+ pointerSensitivity: { type: Number, default: DEFAULT_POINTER_SENSITIVITY },
4426
+ /** Initial camera zoom, also restored by resetMotion(). */
4427
+ initialZoom: { type: Number, default: 1 },
4428
+ /** Minimum camera zoom accepted from wheel and trackpad gestures. */
4429
+ minZoom: { type: Number, default: DEFAULT_MIN_ZOOM },
4430
+ /** Maximum camera zoom accepted from wheel and trackpad gestures. */
4431
+ maxZoom: { type: Number, default: DEFAULT_MAX_ZOOM },
4432
+ /** Zoom impulse per normalized wheel or trackpad unit. */
4433
+ zoomSensitivity: { type: Number, default: DEFAULT_ZOOM_SENSITIVITY }
4434
+ };
4435
+ function finite(value, fallback) {
4436
+ return Number.isFinite(value) ? value : fallback;
4437
+ }
4438
+ function clampPitch(value) {
4439
+ return Math.max(-MAX_PITCH, Math.min(MAX_PITCH, value));
4440
+ }
4441
+ function zoomBounds(minZoom, maxZoom) {
4442
+ let first = Math.max(0.01, finite(minZoom, DEFAULT_MIN_ZOOM)), second = Math.max(0.01, finite(maxZoom, DEFAULT_MAX_ZOOM));
4443
+ return first <= second ? { min: first, max: second } : { min: second, max: first };
4444
+ }
4445
+ function clampZoom(value, minZoom, maxZoom) {
4446
+ let { min, max } = zoomBounds(minZoom, maxZoom);
4447
+ return Math.max(min, Math.min(max, finite(value, 1)));
4448
+ }
4449
+ function normalizedWheelDelta(event) {
4450
+ let deltaY = Number(event.deltaY ?? 0);
4451
+ return !Number.isFinite(deltaY) || deltaY === 0 ? 0 : event.deltaMode === 1 ? deltaY : event.deltaMode === 2 ? Math.max(-3, Math.min(3, deltaY * 3)) : event.deltaMode === 0 ? deltaY / 100 : Number.isInteger(deltaY) && Math.abs(deltaY) <= 3 ? deltaY : deltaY / 100;
4452
+ }
4453
+ function nowMs() {
4454
+ return typeof performance < "u" ? performance.now() : Date.now();
4455
+ }
4456
+ function abortError() {
4457
+ let error = new Error("T3D viewport render aborted");
4458
+ return error.name = "AbortError", error;
4459
+ }
4460
+ function warnDev(message) {
4461
+ globalThis.process?.env?.NODE_ENV !== "production" && console.warn(message);
4462
+ }
4463
+ function waitFor(ms, signal) {
4464
+ return signal.aborted || ms <= 0 ? Promise.resolve() : new Promise((resolve) => {
4465
+ let timer = setTimeout(done, ms);
4466
+ function done() {
4467
+ clearTimeout(timer), signal.removeEventListener("abort", done), resolve();
4468
+ }
4469
+ signal.addEventListener("abort", done, { once: !0 });
4470
+ });
4471
+ }
4472
+ var T3DViewport = (0, import_vue14.defineComponent)({
4473
+ name: "T3DViewport",
4474
+ props: t3DViewportProps,
4475
+ emits: {
4476
+ /** A frame was committed by TVideo. */
4477
+ frame: (_event) => !0,
4478
+ /** Rendering or frame processing failed. */
4479
+ error: (_error) => !0,
4480
+ /** Hovered renderer object changed, or cleared to null. */
4481
+ objecthover: (_hit) => !0,
4482
+ /** Click-locked renderer object changed, or cleared to null. */
4483
+ objectselect: (_hit) => !0
4484
+ },
4485
+ setup(props, { emit, expose }) {
4486
+ let layout = useLayout(), renderer = props.renderer, alive = !0, yaw = finite(props.initialYaw, 0), pitch = clampPitch(finite(props.initialPitch, 0)), yawVelocity = 0, pitchVelocity = 0, pointerX = 0, pointerY = 0, pointerSpeed = 0, hovering = !1, zoom = clampZoom(props.initialZoom, props.minZoom, props.maxZoom), zoomVelocity = 0, hoveredObject = null, selectedObject = null, actualPixelWidth = Math.max(1, Math.floor(props.pixelWidth ?? props.w)), actualPixelHeight = Math.max(1, Math.floor(props.pixelHeight ?? props.h)), pointer = null, drag = null, renderTail = Promise.resolve();
4487
+ function motionSnapshot() {
4488
+ return {
4489
+ yaw,
4490
+ pitch,
4491
+ yawVelocity,
4492
+ pitchVelocity,
4493
+ pointerX,
4494
+ pointerY,
4495
+ pointerSpeed,
4496
+ hovering,
4497
+ zoom,
4498
+ zoomVelocity,
4499
+ hoveredObjectId: hoveredObject?.objectId ?? null,
4500
+ selectedObjectId: selectedObject?.objectId ?? null
4501
+ };
4502
+ }
4503
+ async function renderFrame(context) {
4504
+ let previous = renderTail, release = () => {
4505
+ };
4506
+ renderTail = new Promise((resolve) => {
4507
+ release = resolve;
4508
+ }), await previous;
4509
+ try {
4510
+ if (!alive || context.signal.aborted)
4511
+ throw abortError();
4512
+ return await renderer.render(context);
4513
+ } finally {
4514
+ release();
4515
+ }
4516
+ }
4517
+ function sameHit(left, right) {
4518
+ return left?.objectId === right?.objectId;
4519
+ }
4520
+ function setHoveredObject(hit) {
4521
+ sameHit(hoveredObject, hit) || (hoveredObject = hit, emit("objecthover", hit));
4522
+ }
4523
+ function setSelectedObject(hit) {
4524
+ sameHit(selectedObject, hit) || (selectedObject = hit, emit("objectselect", hit));
4525
+ }
4526
+ function resetMotion() {
4527
+ yaw = finite(props.initialYaw, 0), pitch = clampPitch(finite(props.initialPitch, 0)), yawVelocity = 0, pitchVelocity = 0, pointerX = 0, pointerY = 0, pointerSpeed = 0, zoom = clampZoom(props.initialZoom, props.minZoom, props.maxZoom), zoomVelocity = 0, setHoveredObject(null), setSelectedObject(null), pointer = null, drag = null;
4528
+ }
4529
+ expose({ resetMotion });
4530
+ function localCell(event) {
4531
+ return {
4532
+ x: Math.floor(event.cellX - layout.originX - props.x),
4533
+ y: Math.floor(event.cellY - layout.originY - props.y)
4534
+ };
4535
+ }
4536
+ function eventTime(event) {
4537
+ return Number.isFinite(event.timeStamp) ? event.timeStamp : nowMs();
4538
+ }
4539
+ function updatePointerPosition(point) {
4540
+ let width = Math.max(1, Math.floor(props.w)), height = Math.max(1, Math.floor(props.h));
4541
+ pointerX = Math.max(-1, Math.min(1, (point.x + 0.5) / width * 2 - 1)), pointerY = Math.max(-1, Math.min(1, (point.y + 0.5) / height * 2 - 1));
4542
+ }
4543
+ function hitTest() {
4544
+ if (!renderer.hitTest)
4545
+ return null;
4546
+ try {
4547
+ return renderer.hitTest({
4548
+ pointerX,
4549
+ pointerY,
4550
+ pixelWidth: actualPixelWidth,
4551
+ pixelHeight: actualPixelHeight,
4552
+ cellWidth: Math.max(1, Math.floor(props.w)),
4553
+ cellHeight: Math.max(1, Math.floor(props.h)),
4554
+ motion: motionSnapshot()
4555
+ });
4556
+ } catch (error) {
4557
+ return emit("error", error), null;
4558
+ }
4559
+ }
4560
+ function updateHoveredObject() {
4561
+ renderer.hitTest && setHoveredObject(hitTest());
4562
+ }
4563
+ function onPointerEnter(event) {
4564
+ if (!props.interactive)
4565
+ return;
4566
+ let point = localCell(event);
4567
+ hovering = !0, updatePointerPosition(point), pointer = { ...point, timeMs: eventTime(event) }, updateHoveredObject();
4568
+ }
4569
+ function onPointerDown(event) {
4570
+ if (!props.interactive || event.button != null && event.button !== 0)
4571
+ return;
4572
+ event.preventDefault(), event.stopPropagation();
4573
+ let point = localCell(event), timeMs = eventTime(event);
4574
+ hovering = !0, updatePointerPosition(point), yawVelocity = 0, pitchVelocity = 0, pointerSpeed = 0, pointer = { ...point, timeMs }, drag = { ...point, timeMs, moved: !1 }, updateHoveredObject();
4575
+ }
4576
+ function onPointerMove(event) {
4577
+ if (!props.interactive)
4578
+ return;
4579
+ hovering = !0;
4580
+ let point = localCell(event);
4581
+ updatePointerPosition(point);
4582
+ let timeMs = eventTime(event), previous = drag ?? pointer;
4583
+ if (pointer = { ...point, timeMs }, !previous)
4584
+ return;
4585
+ let dtMs = Math.max(1, timeMs - previous.timeMs), dx = point.x - previous.x, dy = point.y - previous.y, sensitivity = finite(props.pointerSensitivity, DEFAULT_POINTER_SENSITIVITY), deltaYaw = dx * sensitivity, deltaPitch = dy * sensitivity;
4586
+ if (pointerSpeed = Math.hypot(dx, dy) * 1e3 / dtMs, !drag) {
4587
+ if (renderer.hitTest) {
4588
+ yawVelocity = 0, pitchVelocity = 0, updateHoveredObject();
4589
+ return;
4590
+ }
4591
+ yawVelocity = deltaYaw * 650 / dtMs, pitchVelocity = deltaPitch * 450 / dtMs;
1830
4592
  return;
1831
- let manager = events.value, nodeId = eventNode.id.value;
1832
- !manager || !nodeId || manager.getFocused() !== nodeId && manager.focus(nodeId);
1833
- }), (0, import_vue9.watch)(
1834
- () => visible.value,
1835
- (nextVisible) => {
1836
- nextVisible || cancelWheelScrollFrame();
1837
4593
  }
1838
- ), (0, import_vue9.onBeforeUnmount)(() => {
1839
- alive = !1, pendingWheelTop = null, resetWheelScrollState(wheelState), wheelMailbox.dispose(), terminalGraphicsActivity.dispose();
1840
- });
1841
- function viewportRows() {
1842
- let r = normalizedRect(), rows = [];
1843
- for (let y = r.y; y < r.y + r.h; y++)
1844
- rows.push(y);
1845
- return rows;
4594
+ if (event.buttons === 0) {
4595
+ drag = null;
4596
+ return;
4597
+ }
4598
+ event.preventDefault(), event.stopPropagation(), yaw += deltaYaw, pitch = clampPitch(pitch + deltaPitch), yawVelocity = deltaYaw * 1e3 / dtMs, pitchVelocity = deltaPitch * 1e3 / dtMs, setHoveredObject(null), drag = { ...point, timeMs, moved: drag.moved || dx !== 0 || dy !== 0 };
1846
4599
  }
1847
- function unionDirtyRows(nextRows) {
1848
- if (!dirtyRowsHint?.length)
1849
- return nextRows.slice().sort((a, b) => a - b);
1850
- let rows = new Set(dirtyRowsHint);
1851
- for (let y of nextRows)
1852
- rows.add(y);
1853
- return Array.from(rows).sort((a, b) => a - b);
4600
+ function onPointerUp(event) {
4601
+ if (!drag)
4602
+ return;
4603
+ event.preventDefault(), event.stopPropagation();
4604
+ let moved = drag.moved;
4605
+ if (drag = null, !moved && renderer.hitTest) {
4606
+ let hit = hitTest();
4607
+ setHoveredObject(hit), setSelectedObject(hit);
4608
+ } else
4609
+ updateHoveredObject();
1854
4610
  }
1855
- function markRowsDirty(nextRows) {
1856
- return hasPaintableViewport() ? (dirtyRowsHint = unionDirtyRows(nextRows), renderNodeId && render.markDirtyRows(renderNodeId, dirtyRowsHint) ? !0 : (dirtyRowsHint = void 0, !1)) : !1;
4611
+ function onPointerLeave(event) {
4612
+ drag && (event.preventDefault(), event.stopPropagation(), drag = null), hovering = !1, pointer = null, setHoveredObject(null);
1857
4613
  }
1858
- function markViewportDirty() {
1859
- return markRowsDirty(viewportRows());
4614
+ function onWheel(event) {
4615
+ if (!props.interactive)
4616
+ return;
4617
+ let delta = normalizedWheelDelta(event), sensitivity = Math.max(0, finite(props.zoomSensitivity, DEFAULT_ZOOM_SENSITIVITY));
4618
+ delta === 0 || sensitivity === 0 || (event.preventDefault(), event.stopPropagation(), zoomVelocity = Math.max(
4619
+ -MAX_ZOOM_VELOCITY,
4620
+ Math.min(MAX_ZOOM_VELOCITY, zoomVelocity - delta * sensitivity * 6)
4621
+ ));
1860
4622
  }
1861
- function applyScrollTop(nextTop, options) {
1862
- let controlled = isScrollControlled(), r = normalizedRect(), full = normalizedFullRect();
1863
- if (r.h <= 0 || full.h <= 0)
1864
- return { changed: !1, dirty: !1, top: scrollTop.value, controlled };
1865
- let clampedTop = clampScrollTop(nextTop), delta = clampedTop - scrollTop.value;
1866
- if (!delta)
1867
- return { changed: !1, dirty: !1, top: scrollTop.value, controlled };
1868
- if (controlled)
1869
- return terminalGraphicsActivity.markScroll(), (options?.emitUpdate ?? !0) && emit("update:scrollTop", clampedTop), options?.emitScroll && emit("scroll", clampedTop), { changed: !0, dirty: !1, top: clampedTop, controlled };
1870
- terminalGraphicsActivity.markScroll(), scrollTop.value = clampedTop, options?.emitUpdate && emit("update:scrollTop", clampedTop);
1871
- let canUseTerminalRowScroll = rendererCapabilities.value.scrollOperations && rendererCapabilities.value.domRows !== !0, scrollPlan = prepareUnsafeFullRowScroll({
1872
- render,
1873
- plane: plane.value,
1874
- rect: r,
1875
- terminalSize: terminal.size(),
1876
- delta,
1877
- rowScrollMode: props.rowScrollMode,
1878
- rendererCapabilities: {
1879
- scrollOperations: canUseTerminalRowScroll
1880
- },
1881
- isClipped: isClipped(),
1882
- hasPendingDirtyRows: !!dirtyRowsHint?.length,
1883
- strategy: options?.strategy ?? "viewport-repaint"
1884
- }), dirty = !1;
1885
- return scrollPlan && markRowsDirty(scrollPlan.exposedRows) ? (scrollPlan.apply(), dirty = !0) : dirty = markViewportDirty(), options?.emitScroll && emit("scroll", clampedTop), options?.priority && dirty && invalidateSelf(options.priority, options.reason ?? "scroll"), { changed: !0, dirty, top: clampedTop, controlled };
4623
+ function advanceZoom(deltaMs) {
4624
+ if (deltaMs <= 0 || zoomVelocity === 0)
4625
+ return;
4626
+ let dt = Math.min(deltaMs, 100) / 1e3, next = zoom + zoomVelocity * dt;
4627
+ if (zoom = clampZoom(next, props.minZoom, props.maxZoom), zoom !== next) {
4628
+ zoomVelocity = 0;
4629
+ return;
4630
+ }
4631
+ zoomVelocity *= Math.exp(-ZOOM_DAMPING_PER_SECOND * dt), Math.abs(zoomVelocity) < 1e-3 && (zoomVelocity = 0);
1886
4632
  }
1887
- let renderNode = useRenderNode(() => ({
1888
- zIndex: props.zIndex,
1889
- rect: visible.value ? normalizedRect() : { x: 0, y: 0, w: 0, h: 0 },
1890
- deps: [
1891
- visible.value,
1892
- absRect.value,
1893
- fullRect.value,
1894
- itemCount.value,
1895
- props.itemVersion,
1896
- props.getItem,
1897
- props.renderItem,
1898
- active.value,
1899
- focused.value,
1900
- props.style,
1901
- props.activeStyle,
1902
- defaultStyle.value
1903
- ],
1904
- paint: (dirtyRows) => {
1905
- if (dirtyRowsHint = void 0, !visible.value)
1906
- return;
1907
- let r = normalizedRect(), full = normalizedFullRect();
1908
- if (r.w <= 0 || r.h <= 0)
1909
- return;
1910
- let base = props.style ?? defaultStyle.value, activeStyle = props.activeStyle ?? defaultActiveStyle(base), top = visibleWindow.value.top, { x: clipX, y: clipY } = clipOffsets(), paintRow = (y) => {
1911
- if (y < r.y || y >= r.y + r.h)
1912
- return;
1913
- let idx = top + clipY + (y - r.y), fullLine = formatInlineCellLine(
1914
- idx >= 0 && idx < itemCount.value ? itemText(idx) : "",
1915
- full.w
1916
- ), line = padEndByCells(sliceByCellsRange(fullLine, clipX, clipX + r.w), r.w), style = idx >= 0 && idx < itemCount.value && idx === active.value ? activeStyle : base;
1917
- terminal.write(line, { x: r.x, y, style });
1918
- }, rows = dirtyRows;
1919
- if (rows?.length) {
1920
- for (let y of rows)
1921
- paintRow(y);
4633
+ function advanceMotion(deltaMs) {
4634
+ if (deltaMs <= 0 || (advanceZoom(deltaMs), drag))
4635
+ return;
4636
+ let dt = Math.min(deltaMs, 100) / 1e3;
4637
+ if (hovering && !renderer.hitTest) {
4638
+ let targetPitch = clampPitch(-pointerY * 0.36);
4639
+ pitchVelocity += (targetPitch - pitch) * 4.5 * dt;
4640
+ } else
4641
+ hovering || (pointerX *= Math.exp(-7 * dt), pointerY *= Math.exp(-7 * dt));
4642
+ yaw += yawVelocity * dt, pitch = clampPitch(pitch + pitchVelocity * dt);
4643
+ let inspectingObject = !!(renderer.hitTest && (hoveredObject || selectedObject));
4644
+ if (props.autoRotate && !inspectingObject) {
4645
+ let baseSpeed = finite(props.autoRotateSpeed, DEFAULT_AUTO_ROTATE_SPEED), steering = hovering ? 0.85 + pointerX * 1.75 : 1;
4646
+ yaw += baseSpeed * steering * dt;
4647
+ }
4648
+ let decay = Math.exp(-VELOCITY_DAMPING_PER_SECOND * dt);
4649
+ yawVelocity *= decay, pitchVelocity *= decay, pointerSpeed *= decay;
4650
+ }
4651
+ let frameSource = async function* (videoContext) {
4652
+ let startedAt = nowMs(), previousAt = startedAt, frame = 0, frameIntervalMs = 1e3 / Math.max(1, finite(videoContext.maxFps, DEFAULT_MAX_FPS2));
4653
+ for (; alive && !videoContext.signal.aborted; ) {
4654
+ let pulledAt = nowMs(), deltaMs = frame === 0 ? 0 : Math.max(0, pulledAt - previousAt);
4655
+ advanceMotion(deltaMs), actualPixelWidth = videoContext.pixelWidth, actualPixelHeight = videoContext.pixelHeight;
4656
+ let result = await renderFrame({
4657
+ timeMs: Math.max(0, pulledAt - startedAt),
4658
+ deltaMs,
4659
+ frame,
4660
+ pixelWidth: videoContext.pixelWidth,
4661
+ pixelHeight: videoContext.pixelHeight,
4662
+ format: videoContext.preferredFormat,
4663
+ signal: videoContext.signal,
4664
+ motion: motionSnapshot()
4665
+ });
4666
+ if (!alive || videoContext.signal.aborted)
1922
4667
  return;
1923
- }
1924
- for (let y = r.y; y < r.y + r.h; y++)
1925
- paintRow(y);
4668
+ yield result, frame++, previousAt = pulledAt, await waitFor(frameIntervalMs - (nowMs() - pulledAt), videoContext.signal);
1926
4669
  }
1927
- }));
1928
- return (0, import_vue9.watchEffect)(() => {
1929
- renderNodeId = renderNode.id.value;
1930
- }), () => (0, import_vue9.h)("span", rootProps);
4670
+ };
4671
+ return (0, import_vue14.watch)(
4672
+ () => props.renderer,
4673
+ (next) => {
4674
+ next !== renderer && warnDev("[vue-tui] T3DViewport renderer is init-only. Remount T3DViewport to replace it.");
4675
+ }
4676
+ ), (0, import_vue14.watch)(
4677
+ () => props.interactive,
4678
+ (interactive) => {
4679
+ interactive || (hovering = !1, pointer = null, drag = null, setHoveredObject(null), setSelectedObject(null));
4680
+ }
4681
+ ), (0, import_vue14.onBeforeUnmount)(() => {
4682
+ alive = !1, pointer = null, drag = null;
4683
+ }), (0, import_vue14.onUnmounted)(() => renderer.dispose?.()), () => (0, import_vue14.h)("span", [
4684
+ (0, import_vue14.h)(TVideo, {
4685
+ x: props.x,
4686
+ y: props.y,
4687
+ w: props.w,
4688
+ h: props.h,
4689
+ zIndex: props.zIndex,
4690
+ src: "t3d://viewport",
4691
+ frameSource,
4692
+ paused: props.paused,
4693
+ maxFps: props.maxFps,
4694
+ pixelWidth: props.pixelWidth,
4695
+ pixelHeight: props.pixelHeight,
4696
+ fallback: props.fallback,
4697
+ style: props.style,
4698
+ clear: props.clear,
4699
+ onFrame: (event) => emit("frame", event),
4700
+ onError: (error) => emit("error", error)
4701
+ }),
4702
+ props.interactive ? (0, import_vue14.h)(TView, {
4703
+ x: props.x,
4704
+ y: props.y,
4705
+ w: Math.max(0, Math.floor(props.w)),
4706
+ h: Math.max(0, Math.floor(props.h)),
4707
+ zIndex: props.zIndex + 1,
4708
+ selectable: !1,
4709
+ onPointerenter: onPointerEnter,
4710
+ onPointermove: onPointerMove,
4711
+ onPointerleave: onPointerLeave,
4712
+ onPointerdown: onPointerDown,
4713
+ onPointerup: onPointerUp,
4714
+ onWheel
4715
+ }) : null
4716
+ ]);
1931
4717
  }
1932
4718
  });
1933
4719
 
1934
4720
  // src/vue/components/TCharts.ts
1935
- var import_vue10 = require("vue");
4721
+ var import_vue15 = require("vue");
1936
4722
 
1937
4723
  // src/vue/components/simple-utils.ts
1938
4724
  function mergeStyle(...styles) {
@@ -2271,7 +5057,7 @@ function chooseTooltipPlacement(cells, width, height, anchorX, anchorY, textWidt
2271
5057
  }
2272
5058
  function useChartVisibleRect(props, size) {
2273
5059
  let layout = useLayout();
2274
- return (0, import_vue10.computed)(() => {
5060
+ return (0, import_vue15.computed)(() => {
2275
5061
  let full = translateRect(
2276
5062
  {
2277
5063
  x: Math.floor(props.x),
@@ -2353,7 +5139,7 @@ function createSurface(width, height, clearStyle, cells) {
2353
5139
  return { width, height, clearStyle, rows };
2354
5140
  }
2355
5141
  function useChartRender(props, surface, options) {
2356
- let { terminal } = useTerminal(), layout = useLayout(), { visible, rootProps } = useVisibility(), parentEventZ = (0, import_vue10.inject)(EventZIndexContextKey, (0, import_vue10.computed)(() => 0)), eventZ = (0, import_vue10.computed)(() => (parentEventZ.value ?? 0) + (props.zIndex ?? 0)), fullRect = (0, import_vue10.computed)(
5142
+ let { terminal } = useTerminal(), layout = useLayout(), { visible, rootProps } = useVisibility(), parentEventZ = (0, import_vue15.inject)(EventZIndexContextKey, (0, import_vue15.computed)(() => 0)), eventZ = (0, import_vue15.computed)(() => (parentEventZ.value ?? 0) + (props.zIndex ?? 0)), fullRect = (0, import_vue15.computed)(
2357
5143
  () => translateRect(
2358
5144
  {
2359
5145
  x: Math.floor(props.x),
@@ -2364,10 +5150,10 @@ function useChartRender(props, surface, options) {
2364
5150
  layout.originX,
2365
5151
  layout.originY
2366
5152
  )
2367
- ), absRect = (0, import_vue10.computed)(() => {
5153
+ ), absRect = (0, import_vue15.computed)(() => {
2368
5154
  let translated = fullRect.value;
2369
5155
  return layout.clipRect ? intersectRect(translated, layout.clipRect) ?? { x: 0, y: 0, w: 0, h: 0 } : translated;
2370
- }), dirtyRowsHint = (0, import_vue10.computed)(() => {
5156
+ }), dirtyRowsHint = (0, import_vue15.computed)(() => {
2371
5157
  if (!visible.value)
2372
5158
  return [];
2373
5159
  let r = absRect.value;
@@ -2414,7 +5200,7 @@ function useChartRender(props, surface, options) {
2414
5200
  for (let y of dirtyRows)
2415
5201
  paintRow(y);
2416
5202
  }
2417
- })), () => (0, import_vue10.h)("span", rootProps);
5203
+ })), () => (0, import_vue15.h)("span", rootProps);
2418
5204
  }
2419
5205
  function positiveHeatmapStyle(value, max, styles) {
2420
5206
  if (!styles.length)
@@ -2424,7 +5210,7 @@ function positiveHeatmapStyle(value, max, styles) {
2424
5210
  let ratio = Math.max(0, Math.min(1, value / max)), index = Math.max(0, Math.min(styles.length - 1, Math.ceil(ratio * styles.length) - 1));
2425
5211
  return styles[index] ?? {};
2426
5212
  }
2427
- var TContributionGraph = (0, import_vue10.defineComponent)({
5213
+ var TContributionGraph = (0, import_vue15.defineComponent)({
2428
5214
  name: "TContributionGraph",
2429
5215
  props: {
2430
5216
  /** Left position in terminal cells. */
@@ -2471,7 +5257,7 @@ var TContributionGraph = (0, import_vue10.defineComponent)({
2471
5257
  style: { type: Object, default: void 0 }
2472
5258
  },
2473
5259
  setup(props) {
2474
- let { defaultStyle } = useTerminal(), baseStyle = (0, import_vue10.computed)(() => mergeStyle(defaultStyle.value, props.style)), hoverPointer = (0, import_vue10.ref)(null), graphLayout = (0, import_vue10.computed)(() => {
5260
+ let { defaultStyle } = useTerminal(), baseStyle = (0, import_vue15.computed)(() => mergeStyle(defaultStyle.value, props.style)), hoverPointer = (0, import_vue15.ref)(null), graphLayout = (0, import_vue15.computed)(() => {
2475
5261
  let rowCount = cellCount(props.rows, 7);
2476
5262
  if (rowCount <= 0)
2477
5263
  return {
@@ -2506,7 +5292,7 @@ var TContributionGraph = (0, import_vue10.defineComponent)({
2506
5292
  let label = props.labels?.[index] ?? `#${index + 1}`;
2507
5293
  return { x: cellX, y: localY, index, value, label };
2508
5294
  }
2509
- let surface = (0, import_vue10.computed)(() => {
5295
+ let surface = (0, import_vue15.computed)(() => {
2510
5296
  let current = graphLayout.value;
2511
5297
  if (current.rowCount <= 0)
2512
5298
  return createSurface(0, 0, baseStyle.value, []);
@@ -2556,7 +5342,7 @@ var TContributionGraph = (0, import_vue10.defineComponent)({
2556
5342
  })
2557
5343
  });
2558
5344
  }
2559
- }), TLineChart = (0, import_vue10.defineComponent)({
5345
+ }), TLineChart = (0, import_vue15.defineComponent)({
2560
5346
  name: "TLineChart",
2561
5347
  props: {
2562
5348
  /** Left position in terminal cells. */
@@ -2606,7 +5392,7 @@ var TContributionGraph = (0, import_vue10.defineComponent)({
2606
5392
  tooltipStyle: { type: Object, default: () => ({ fg: "whiteBright" }) }
2607
5393
  },
2608
5394
  setup(props) {
2609
- let { defaultStyle } = useTerminal(), clearStyle = (0, import_vue10.computed)(() => mergeStyle(defaultStyle.value, props.style)), lineStyle = (0, import_vue10.computed)(() => mergeStyle(clearStyle.value, props.lineStyle)), axisStyle = (0, import_vue10.computed)(() => mergeStyle(clearStyle.value, props.axisStyle)), labelStyle = (0, import_vue10.computed)(() => mergeStyle(clearStyle.value, props.labelStyle)), hoverPointer = (0, import_vue10.ref)(null), lineLayout = (0, import_vue10.computed)(() => {
5395
+ let { defaultStyle } = useTerminal(), clearStyle = (0, import_vue15.computed)(() => mergeStyle(defaultStyle.value, props.style)), lineStyle = (0, import_vue15.computed)(() => mergeStyle(clearStyle.value, props.lineStyle)), axisStyle = (0, import_vue15.computed)(() => mergeStyle(clearStyle.value, props.axisStyle)), labelStyle = (0, import_vue15.computed)(() => mergeStyle(clearStyle.value, props.labelStyle)), hoverPointer = (0, import_vue15.ref)(null), lineLayout = (0, import_vue15.computed)(() => {
2610
5396
  let width = cellCount(props.w, 0), height = cellCount(props.h, 0), runs = finiteLineRuns(props.values), sourceLength = props.values.length, { min, max } = domainFromValues(props.values, props.min, props.max), layout = resolveAxisLayout(width, height, min, max, props.showAxes);
2611
5397
  return { width, height, layout, runs, sourceLength, min, max };
2612
5398
  }), visibleRect = useChartVisibleRect(props, lineLayout);
@@ -2628,7 +5414,7 @@ var TContributionGraph = (0, import_vue10.defineComponent)({
2628
5414
  ), y = layout.plotY + valueToY(value, min, max, layout.plotH), label = props.labels?.[point.originalIndex] ?? `#${point.originalIndex + 1}`;
2629
5415
  return { x, y, index: point.originalIndex, label, value };
2630
5416
  }
2631
- let baseCells = (0, import_vue10.computed)(() => {
5417
+ let baseCells = (0, import_vue15.computed)(() => {
2632
5418
  let { width, height, layout, runs, sourceLength, min, max } = lineLayout.value, cells = [];
2633
5419
  if (layout.plotW > 0 && layout.plotH > 0 && runs.length > 0) {
2634
5420
  let occupiedLineCells = /* @__PURE__ */ new Set();
@@ -2677,7 +5463,7 @@ var TContributionGraph = (0, import_vue10.defineComponent)({
2677
5463
  props.startLabel || (sourceLength > 0 ? "1" : ""),
2678
5464
  props.endLabel || (sourceLength > 0 ? String(sourceLength) : "")
2679
5465
  ), cells;
2680
- }), surface = (0, import_vue10.computed)(() => {
5466
+ }), surface = (0, import_vue15.computed)(() => {
2681
5467
  let { width, height, layout } = lineLayout.value, cells = baseCells.value.slice(), pointer = hoverPointer.value, hovered = pointer ? hitLine(pointer.x, pointer.y) : null;
2682
5468
  hovered && cells.push({
2683
5469
  x: hovered.x,
@@ -2723,7 +5509,7 @@ var TContributionGraph = (0, import_vue10.defineComponent)({
2723
5509
  })
2724
5510
  });
2725
5511
  }
2726
- }), TCandlestickChart = (0, import_vue10.defineComponent)({
5512
+ }), TCandlestickChart = (0, import_vue15.defineComponent)({
2727
5513
  name: "TCandlestickChart",
2728
5514
  props: {
2729
5515
  /** Left position in terminal cells. */
@@ -2772,7 +5558,7 @@ var TContributionGraph = (0, import_vue10.defineComponent)({
2772
5558
  tooltipStyle: { type: Object, default: () => ({ fg: "whiteBright" }) }
2773
5559
  },
2774
5560
  setup(props) {
2775
- let { defaultStyle } = useTerminal(), baseStyle = (0, import_vue10.computed)(() => mergeStyle(defaultStyle.value, props.style)), axisStyle = (0, import_vue10.computed)(() => mergeStyle(baseStyle.value, props.axisStyle)), labelStyle = (0, import_vue10.computed)(() => mergeStyle(baseStyle.value, props.labelStyle)), hoverPointer = (0, import_vue10.ref)(null), candleLayout = (0, import_vue10.computed)(() => {
5561
+ let { defaultStyle } = useTerminal(), baseStyle = (0, import_vue15.computed)(() => mergeStyle(defaultStyle.value, props.style)), axisStyle = (0, import_vue15.computed)(() => mergeStyle(baseStyle.value, props.axisStyle)), labelStyle = (0, import_vue15.computed)(() => mergeStyle(baseStyle.value, props.labelStyle)), hoverPointer = (0, import_vue15.ref)(null), candleLayout = (0, import_vue15.computed)(() => {
2776
5562
  let width = cellCount(props.w, 0), height = cellCount(props.h, 0), min = 0, max = 0, layout = resolveAxisLayout(width, height, min, max, props.showAxes), startIndex = props.candles.length, visibleCandles = [];
2777
5563
  for (let capacity = Math.min(props.candles.length, width); capacity >= 0 && (startIndex = Math.max(0, props.candles.length - capacity), visibleCandles = props.candles.slice(startIndex), { min, max } = domainFromValues(
2778
5564
  candlestickDomainValues(visibleCandles),
@@ -2806,7 +5592,7 @@ var TContributionGraph = (0, import_vue10.defineComponent)({
2806
5592
  close
2807
5593
  };
2808
5594
  }
2809
- let surface = (0, import_vue10.computed)(() => {
5595
+ let surface = (0, import_vue15.computed)(() => {
2810
5596
  let current = candleLayout.value, { width, height, layout, visibleCandles, candleOffsetX, min, max } = current, cells = [], upStyle = mergeStyle(baseStyle.value, props.upStyle), downStyle = mergeStyle(baseStyle.value, props.downStyle), upWickStyle = mergeStyle(baseStyle.value, props.upStyle, props.wickStyle), downWickStyle = mergeStyle(baseStyle.value, props.downStyle, props.wickStyle), pointer = hoverPointer.value, hovered = pointer ? hitCandle(pointer.x, pointer.y) : null;
2811
5597
  for (let x = 0; x < visibleCandles.length; x++) {
2812
5598
  let candle = visibleCandles[x], values = normalizeCandlestick(candle);
@@ -2872,7 +5658,7 @@ var TContributionGraph = (0, import_vue10.defineComponent)({
2872
5658
  })
2873
5659
  });
2874
5660
  }
2875
- }), TPieChart = (0, import_vue10.defineComponent)({
5661
+ }), TPieChart = (0, import_vue15.defineComponent)({
2876
5662
  name: "TPieChart",
2877
5663
  props: {
2878
5664
  /** Left position in terminal cells. */
@@ -2902,7 +5688,7 @@ var TContributionGraph = (0, import_vue10.defineComponent)({
2902
5688
  legendStyle: { type: Object, default: () => ({ fg: "whiteBright" }) }
2903
5689
  },
2904
5690
  setup(props) {
2905
- let { defaultStyle } = useTerminal(), baseStyle = (0, import_vue10.computed)(() => mergeStyle(defaultStyle.value, props.style)), legendStyle = (0, import_vue10.computed)(() => mergeStyle(baseStyle.value, props.legendStyle)), surface = (0, import_vue10.computed)(() => {
5691
+ let { defaultStyle } = useTerminal(), baseStyle = (0, import_vue15.computed)(() => mergeStyle(defaultStyle.value, props.style)), legendStyle = (0, import_vue15.computed)(() => mergeStyle(baseStyle.value, props.legendStyle)), surface = (0, import_vue15.computed)(() => {
2906
5692
  let width = cellCount(props.w, 0), height = cellCount(props.h, 0), values = props.values.map((value) => {
2907
5693
  let n = Number(value);
2908
5694
  return Number.isFinite(n) ? Math.max(0, n) : 0;
@@ -2971,7 +5757,7 @@ var TContributionGraph = (0, import_vue10.defineComponent)({
2971
5757
  });
2972
5758
 
2973
5759
  // src/vue/components/TTranscriptView.ts
2974
- var import_vue13 = require("vue");
5760
+ var import_vue17 = require("vue");
2975
5761
 
2976
5762
  // src/observability/frame-perf.ts
2977
5763
  var EMPTY_METRIC_STATS = Object.freeze({ avg: 0, max: 0, min: 0 });
@@ -3118,147 +5904,39 @@ function layoutTranscriptRow(options) {
3118
5904
  rowIndex: options.rowIndex,
3119
5905
  payload: { row: options.row, rowKey: options.rowKey },
3120
5906
  hoverStyle: options.hoverStyle,
3121
- focusStyle: options.focusStyle
3122
- };
3123
- for (let i = 0; i < segments.length; i++)
3124
- appendTextSegment(segments[i], i, i === 0 ? foldRegion : toolRegion);
3125
- } else
3126
- for (let i = 0; i < segments.length; i++)
3127
- appendTextSegment(segments[i], i);
3128
- if ("actions" in options.row)
3129
- for (let action of options.row.actions ?? [])
3130
- appendAction(action);
3131
- return pushCurrentIfNeeded(), visualRows.length ? visualRows : [createVisualRow(0, 0)];
3132
- }
3133
-
3134
- // src/vue/transcript/plain-text.ts
3135
- function plainTextForTranscriptRow(row) {
3136
- if (row.selectableText != null)
3137
- return row.selectableText;
3138
- if (row.kind === "message")
3139
- return row.segments.map((segment) => segment.text).join("");
3140
- if (row.kind === "action")
3141
- return row.label;
3142
- if (row.kind === "approval") {
3143
- let description = row.description?.map((segment) => segment.text).join("") ?? "";
3144
- return description ? `${row.title}
3145
- ${description}` : row.title;
3146
- }
3147
- let summary = row.summary?.map((segment) => segment.text).join("") ?? "", body = row.collapsed ? "" : row.body?.map((segment) => segment.text).join("") ?? "";
3148
- return [row.title, summary, body].filter(Boolean).join(`
3149
- `);
3150
- }
3151
-
3152
- // src/vue/components/TView.ts
3153
- var import_vue11 = require("vue");
3154
- var EMPTY_RECT = Object.freeze({ x: 0, y: 0, w: 0, h: 0 }), TView = (0, import_vue11.defineComponent)({
3155
- name: "TView",
3156
- props: {
3157
- x: { type: Number, required: !0 },
3158
- y: { type: Number, required: !0 },
3159
- w: { type: Number, required: !0 },
3160
- h: { type: Number, required: !0 },
3161
- zIndex: { type: Number, default: 0 },
3162
- scrollX: { type: Number, default: 0 },
3163
- scrollY: { type: Number, default: 0 },
3164
- focusable: { type: Boolean, default: !1 },
3165
- selectable: { type: Boolean, default: void 0 },
3166
- selectionScrollBy: {
3167
- type: Function,
3168
- default: void 0
3169
- },
3170
- autoFocus: { type: Boolean, default: !1 }
3171
- },
3172
- emits: [
3173
- "clickCapture",
3174
- "click",
3175
- "dblclickCapture",
3176
- "dblclick",
3177
- "pointerdownCapture",
3178
- "pointerdown",
3179
- "pointerupCapture",
3180
- "pointerup",
3181
- "pointermoveCapture",
3182
- "pointermove",
3183
- "pointerenterCapture",
3184
- "pointerenter",
3185
- "pointerleaveCapture",
3186
- "pointerleave",
3187
- "wheelCapture",
3188
- "wheel",
3189
- "keydownCapture",
3190
- "keydown",
3191
- "keyupCapture",
3192
- "keyup",
3193
- "focusCapture",
3194
- "focus",
3195
- "blurCapture",
3196
- "blur"
3197
- ],
3198
- setup(props, { emit, slots }) {
3199
- let parent = useLayout(), { render, events } = useTerminal(), parentStack = useRenderStack(), { visible, rootProps } = useVisibility({ provide: !0 }), parentEventZ = (0, import_vue11.inject)(EventZIndexContextKey, (0, import_vue11.computed)(() => 0)), eventZ = (0, import_vue11.computed)(() => (parentEventZ.value ?? 0) + (props.zIndex ?? 0)), rawRect = (0, import_vue11.computed)(
3200
- () => translateRect(
3201
- { x: props.x, y: props.y, w: props.w, h: props.h },
3202
- parent.originX,
3203
- parent.originY
3204
- )
3205
- ), rect = (0, import_vue11.computed)(() => {
3206
- let translated = rawRect.value;
3207
- return parent.clipRect ? intersectRect(translated, parent.clipRect) ?? EMPTY_RECT : translated;
3208
- }), { id } = useTerminalNode(() => ({
3209
- rect: rect.value,
3210
- zIndex: eventZ.value,
3211
- visible: visible.value,
3212
- focusable: props.focusable,
3213
- selectable: props.selectable,
3214
- selectionScrollBy: props.selectionScrollBy,
3215
- handlers: {
3216
- clickCapture: (e) => emit("clickCapture", e),
3217
- click: (e) => emit("click", e),
3218
- dblclickCapture: (e) => emit("dblclickCapture", e),
3219
- dblclick: (e) => emit("dblclick", e),
3220
- pointerdownCapture: (e) => emit("pointerdownCapture", e),
3221
- pointerdown: (e) => emit("pointerdown", e),
3222
- pointerupCapture: (e) => emit("pointerupCapture", e),
3223
- pointerup: (e) => emit("pointerup", e),
3224
- pointermoveCapture: (e) => emit("pointermoveCapture", e),
3225
- pointermove: (e) => emit("pointermove", e),
3226
- pointerenterCapture: (e) => emit("pointerenterCapture", e),
3227
- pointerenter: (e) => emit("pointerenter", e),
3228
- pointerleaveCapture: (e) => emit("pointerleaveCapture", e),
3229
- pointerleave: (e) => emit("pointerleave", e),
3230
- wheelCapture: (e) => emit("wheelCapture", e),
3231
- wheel: (e) => emit("wheel", e),
3232
- keydownCapture: (e) => emit("keydownCapture", e),
3233
- keydown: (e) => emit("keydown", e),
3234
- keyupCapture: (e) => emit("keyupCapture", e),
3235
- keyup: (e) => emit("keyup", e),
3236
- focusCapture: (e) => emit("focusCapture", e),
3237
- focus: (e) => emit("focus", e),
3238
- blurCapture: (e) => emit("blurCapture", e),
3239
- blur: (e) => emit("blur", e)
3240
- }
3241
- }));
3242
- (0, import_vue11.watchEffect)(() => {
3243
- if (!props.autoFocus || !visible.value)
3244
- return;
3245
- let manager = events.value, nodeId = id.value;
3246
- !manager || !nodeId || manager.getFocused() !== nodeId && manager.focus(nodeId);
3247
- });
3248
- let childLayout = (0, import_vue11.shallowReactive)({
3249
- originX: 0,
3250
- originY: 0,
3251
- clipRect: null
3252
- }), childStack = (0, import_vue11.computed)(() => render.createStack(parentStack.value, props.zIndex));
3253
- return (0, import_vue11.watchEffect)(() => {
3254
- let translated = rawRect.value;
3255
- childLayout.originX = translated.x - Math.floor(props.scrollX), childLayout.originY = translated.y - Math.floor(props.scrollY), childLayout.clipRect = rect.value;
3256
- }), (0, import_vue11.provide)(LayoutContextKey, childLayout), (0, import_vue11.provide)(RenderStackKey, childStack), (0, import_vue11.provide)(EventZIndexContextKey, eventZ), () => (0, import_vue11.h)("div", rootProps, slots.default?.());
5907
+ focusStyle: options.focusStyle
5908
+ };
5909
+ for (let i = 0; i < segments.length; i++)
5910
+ appendTextSegment(segments[i], i, i === 0 ? foldRegion : toolRegion);
5911
+ } else
5912
+ for (let i = 0; i < segments.length; i++)
5913
+ appendTextSegment(segments[i], i);
5914
+ if ("actions" in options.row)
5915
+ for (let action of options.row.actions ?? [])
5916
+ appendAction(action);
5917
+ return pushCurrentIfNeeded(), visualRows.length ? visualRows : [createVisualRow(0, 0)];
5918
+ }
5919
+
5920
+ // src/vue/transcript/plain-text.ts
5921
+ function plainTextForTranscriptRow(row) {
5922
+ if (row.selectableText != null)
5923
+ return row.selectableText;
5924
+ if (row.kind === "message")
5925
+ return row.segments.map((segment) => segment.text).join("");
5926
+ if (row.kind === "action")
5927
+ return row.label;
5928
+ if (row.kind === "approval") {
5929
+ let description = row.description?.map((segment) => segment.text).join("") ?? "";
5930
+ return description ? `${row.title}
5931
+ ${description}` : row.title;
3257
5932
  }
3258
- });
5933
+ let summary = row.summary?.map((segment) => segment.text).join("") ?? "", body = row.collapsed ? "" : row.body?.map((segment) => segment.text).join("") ?? "";
5934
+ return [row.title, summary, body].filter(Boolean).join(`
5935
+ `);
5936
+ }
3259
5937
 
3260
5938
  // src/vue/components/TVirtualRows.ts
3261
- var import_vue12 = require("vue");
5939
+ var import_vue16 = require("vue");
3262
5940
  function clamp3(n, min, max) {
3263
5941
  return Math.max(min, Math.min(max, n));
3264
5942
  }
@@ -3276,7 +5954,7 @@ function getWheelScrollInput2(e) {
3276
5954
  let deltaY = Number(e.deltaY ?? 0), deltaMode = typeof e.deltaMode == "number" ? e.deltaMode : void 0;
3277
5955
  return Number.isInteger(deltaY) && deltaY !== 0 && Math.abs(deltaY) >= 100 && Math.abs(deltaY) % 100 === 0 && deltaMode == null ? { deltaY: deltaY / 100, mode: "line" } : deltaMode === 1 ? { deltaY, mode: "line" } : deltaMode === 0 ? { deltaY, mode: "pixel" } : { deltaY, mode: "auto" };
3278
5956
  }
3279
- var virtualRowsInstanceSeq = 0, EMPTY_RECT2 = Object.freeze({ x: 0, y: 0, w: 0, h: 0 }), TVirtualRows = (0, import_vue12.defineComponent)({
5957
+ var virtualRowsInstanceSeq = 0, EMPTY_RECT2 = Object.freeze({ x: 0, y: 0, w: 0, h: 0 }), TVirtualRows = (0, import_vue16.defineComponent)({
3280
5958
  name: "TVirtualRows",
3281
5959
  props: {
3282
5960
  x: { type: Number, required: !0 },
@@ -3340,27 +6018,27 @@ var virtualRowsInstanceSeq = 0, EMPTY_RECT2 = Object.freeze({ x: 0, y: 0, w: 0,
3340
6018
  "itemClick"
3341
6019
  ],
3342
6020
  setup(props, { emit, expose }) {
3343
- let { terminal, scheduler, render, rendererCapabilities, defaultStyle, events, selection } = useTerminal(), instance = (0, import_vue12.getCurrentInstance)(), layout = useLayout(), { visible, rootProps } = useVisibility(), plane = (0, import_vue12.inject)(RenderPlaneContextKey, (0, import_vue12.ref)("default")), parentEventZ = (0, import_vue12.inject)(EventZIndexContextKey, (0, import_vue12.computed)(() => 0)), eventZ = (0, import_vue12.computed)(() => (parentEventZ.value ?? 0) + (props.zIndex ?? 0)), parentStack = useRenderStack(), childLayout = (0, import_vue12.shallowReactive)({
6021
+ let { terminal, scheduler, render, rendererCapabilities, defaultStyle, events, selection } = useTerminal(), instance = (0, import_vue16.getCurrentInstance)(), layout = useLayout(), { visible, rootProps } = useVisibility(), plane = (0, import_vue16.inject)(RenderPlaneContextKey, (0, import_vue16.ref)("default")), parentEventZ = (0, import_vue16.inject)(EventZIndexContextKey, (0, import_vue16.computed)(() => 0)), eventZ = (0, import_vue16.computed)(() => (parentEventZ.value ?? 0) + (props.zIndex ?? 0)), parentStack = useRenderStack(), childLayout = (0, import_vue16.shallowReactive)({
3344
6022
  originX: 0,
3345
6023
  originY: 0,
3346
6024
  clipRect: null
3347
- }), childStack = (0, import_vue12.computed)(() => render.createStack(parentStack.value, props.zIndex));
3348
- (0, import_vue12.provide)(LayoutContextKey, childLayout), (0, import_vue12.provide)(RenderStackKey, childStack), (0, import_vue12.provide)(EventZIndexContextKey, eventZ);
3349
- let virtualRowsInstanceId = ++virtualRowsInstanceSeq, parentTerminalGraphicsActivity = (0, import_vue12.inject)(TerminalGraphicsActivityKey, null), terminalGraphicsActivity = createTerminalGraphicsActivity({
6025
+ }), childStack = (0, import_vue16.computed)(() => render.createStack(parentStack.value, props.zIndex));
6026
+ (0, import_vue16.provide)(LayoutContextKey, childLayout), (0, import_vue16.provide)(RenderStackKey, childStack), (0, import_vue16.provide)(EventZIndexContextKey, eventZ);
6027
+ let virtualRowsInstanceId = ++virtualRowsInstanceSeq, parentTerminalGraphicsActivity = (0, import_vue16.inject)(TerminalGraphicsActivityKey, null), terminalGraphicsActivity = createTerminalGraphicsActivity({
3350
6028
  scrollIdleMs: props.terminalGraphicScrollIdleMs,
3351
6029
  traceId: `TVirtualRows:${virtualRowsInstanceId}:terminal-graphics`
3352
6030
  });
3353
- (0, import_vue12.provide)(
6031
+ (0, import_vue16.provide)(
3354
6032
  TerminalGraphicsActivityKey,
3355
6033
  createCombinedTerminalGraphicsActivity(
3356
6034
  parentTerminalGraphicsActivity,
3357
6035
  terminalGraphicsActivity
3358
6036
  )
3359
- ), (0, import_vue12.watch)(
6037
+ ), (0, import_vue16.watch)(
3360
6038
  () => props.terminalGraphicScrollIdleMs,
3361
6039
  (value) => terminalGraphicsActivity.setScrollIdleMs(value)
3362
6040
  );
3363
- let frameTaskId = `TVirtualRows:${virtualRowsInstanceId}`, innerScrollTop = (0, import_vue12.ref)(0), controlledScrollTop = (0, import_vue12.ref)(0), focused = (0, import_vue12.ref)(!1), wheelState = createWheelScrollState(), initializedScrollTop = !1, dirtyRowsHint, renderNodeId = null, pendingWheelTop = null, pendingSelectionScrollFocusRemap = !1, alive = !0, itemCount = (0, import_vue12.computed)(() => Math.max(0, normalizeInt(props.itemCount))), fullRect = (0, import_vue12.computed)(
6041
+ let frameTaskId = `TVirtualRows:${virtualRowsInstanceId}`, innerScrollTop = (0, import_vue16.ref)(0), controlledScrollTop = (0, import_vue16.ref)(0), focused = (0, import_vue16.ref)(!1), wheelState = createWheelScrollState(), initializedScrollTop = !1, dirtyRowsHint, renderNodeId = null, pendingWheelTop = null, pendingSelectionScrollFocusRemap = !1, alive = !0, itemCount = (0, import_vue16.computed)(() => Math.max(0, normalizeInt(props.itemCount))), fullRect = (0, import_vue16.computed)(
3364
6042
  () => translateRect(
3365
6043
  {
3366
6044
  x: normalizeInt(props.x),
@@ -3371,7 +6049,7 @@ var virtualRowsInstanceSeq = 0, EMPTY_RECT2 = Object.freeze({ x: 0, y: 0, w: 0,
3371
6049
  layout.originX,
3372
6050
  layout.originY
3373
6051
  )
3374
- ), absRect = (0, import_vue12.computed)(() => {
6052
+ ), absRect = (0, import_vue16.computed)(() => {
3375
6053
  let translated = fullRect.value;
3376
6054
  return layout.clipRect ? intersectRect(translated, layout.clipRect) ?? EMPTY_RECT2 : translated;
3377
6055
  });
@@ -3437,10 +6115,10 @@ var virtualRowsInstanceSeq = 0, EMPTY_RECT2 = Object.freeze({ x: 0, y: 0, w: 0,
3437
6115
  rows.push(y);
3438
6116
  return rows;
3439
6117
  }
3440
- function exposedRowsForDelta2(y0, h15, delta) {
6118
+ function exposedRowsForDelta2(y0, h19, delta) {
3441
6119
  let rows = [];
3442
6120
  if (delta > 0)
3443
- for (let i = h15 - delta; i < h15; i++)
6121
+ for (let i = h19 - delta; i < h19; i++)
3444
6122
  rows.push(y0 + i);
3445
6123
  else
3446
6124
  for (let i = 0; i < -delta; i++)
@@ -3465,11 +6143,11 @@ var virtualRowsInstanceSeq = 0, EMPTY_RECT2 = Object.freeze({ x: 0, y: 0, w: 0,
3465
6143
  scheduler.invalidate({ priority, plane: plane.value, reason: "scroll" });
3466
6144
  }
3467
6145
  function markScrollDamage(prevTop, nextTop, strategy = "auto") {
3468
- let r = normalizedRect(), h15 = r.h, delta = nextTop - prevTop;
3469
- if (h15 <= 0 || !delta)
6146
+ let r = normalizedRect(), h19 = r.h, delta = nextTop - prevTop;
6147
+ if (h19 <= 0 || !delta)
3470
6148
  return;
3471
- let size = terminal.size(), ownsFullRows = Math.floor(r.x) === 0 && Math.floor(r.w) >= size.cols, withinTerminalRows = r.y >= 0 && r.y + h15 <= size.rows;
3472
- strategy === "auto" && props.rowScrollMode === "unsafe-full-row" && rendererCapabilities.value.scrollOperations && ownsFullRows && withinTerminalRows && !isClipped() && Math.abs(delta) < h15 && !dirtyRowsHint?.length ? (render.unsafeScrollPlaneRows(plane.value, r.y, r.y + h15, delta), markRowsDirty(exposedRowsForDelta2(r.y, h15, delta))) : markViewportDirty();
6149
+ let size = terminal.size(), ownsFullRows = Math.floor(r.x) === 0 && Math.floor(r.w) >= size.cols, withinTerminalRows = r.y >= 0 && r.y + h19 <= size.rows;
6150
+ strategy === "auto" && props.rowScrollMode === "unsafe-full-row" && rendererCapabilities.value.scrollOperations && ownsFullRows && withinTerminalRows && !isClipped() && Math.abs(delta) < h19 && !dirtyRowsHint?.length ? (render.unsafeScrollPlaneRows(plane.value, r.y, r.y + h19, delta), markRowsDirty(exposedRowsForDelta2(r.y, h19, delta))) : markViewportDirty();
3473
6151
  }
3474
6152
  function applyScrollTop(nextTop, options) {
3475
6153
  if (normalizedRect().h <= 0)
@@ -3614,7 +6292,7 @@ var virtualRowsInstanceSeq = 0, EMPTY_RECT2 = Object.freeze({ x: 0, y: 0, w: 0,
3614
6292
  getText: textForSelectionRange,
3615
6293
  getVisibleSpans: visibleSpansForSelectionRange
3616
6294
  }, unregisterSelectionTextProvider = selection.registerTextProvider(selectionTextProvider);
3617
- (0, import_vue12.onBeforeUnmount)(unregisterSelectionTextProvider);
6295
+ (0, import_vue16.onBeforeUnmount)(unregisterSelectionTextProvider);
3618
6296
  let eventNode = useTerminalNode(() => ({
3619
6297
  rect: normalizedRect(),
3620
6298
  zIndex: eventZ.value,
@@ -3666,15 +6344,15 @@ var virtualRowsInstanceSeq = 0, EMPTY_RECT2 = Object.freeze({ x: 0, y: 0, w: 0,
3666
6344
  }
3667
6345
  }
3668
6346
  }));
3669
- (0, import_vue12.watchEffect)(() => {
6347
+ (0, import_vue16.watchEffect)(() => {
3670
6348
  if (!props.autoFocus || !visible.value)
3671
6349
  return;
3672
6350
  let manager = events.value, nodeId = eventNode.id.value;
3673
6351
  !manager || !nodeId || manager.getFocused() !== nodeId && manager.focus(nodeId);
3674
- }), (0, import_vue12.watchEffect)(() => {
6352
+ }), (0, import_vue16.watchEffect)(() => {
3675
6353
  let full = normalizedFullRect();
3676
6354
  childLayout.originX = full.x, childLayout.originY = full.y, childLayout.clipRect = normalizedRect();
3677
- }), (0, import_vue12.watch)(
6355
+ }), (0, import_vue16.watch)(
3678
6356
  () => props.scrollTop,
3679
6357
  () => {
3680
6358
  if (!isScrollControlled())
@@ -3693,7 +6371,7 @@ var virtualRowsInstanceSeq = 0, EMPTY_RECT2 = Object.freeze({ x: 0, y: 0, w: 0,
3693
6371
  controlledScrollTop.value = nextTop, terminalGraphicsActivity.markScroll(), markScrollDamage(prevTop, nextTop), selection.refresh(pendingSelectionScrollFocusRemap ? { remapFocus: !0 } : void 0), pendingSelectionScrollFocusRemap = !1, invalidateSelf("high"), desiredTop !== nextTop && (emit("update:scrollTop", nextTop), emitScroll(nextTop));
3694
6372
  },
3695
6373
  { immediate: !0 }
3696
- ), (0, import_vue12.watch)(
6374
+ ), (0, import_vue16.watch)(
3697
6375
  [
3698
6376
  () => itemCount.value,
3699
6377
  () => props.itemVersion,
@@ -3719,12 +6397,12 @@ var virtualRowsInstanceSeq = 0, EMPTY_RECT2 = Object.freeze({ x: 0, y: 0, w: 0,
3719
6397
  markViewportDirty(), invalidateSelf("normal");
3720
6398
  },
3721
6399
  { immediate: !0 }
3722
- ), (0, import_vue12.watch)(
6400
+ ), (0, import_vue16.watch)(
3723
6401
  () => visible.value,
3724
6402
  (nextVisible) => {
3725
6403
  nextVisible || cancelWheelScrollFrame();
3726
6404
  }
3727
- ), (0, import_vue12.onBeforeUnmount)(() => {
6405
+ ), (0, import_vue16.onBeforeUnmount)(() => {
3728
6406
  alive = !1, pendingWheelTop = null, resetWheelScrollState(wheelState), wheelMailbox.dispose(), terminalGraphicsActivity.dispose();
3729
6407
  });
3730
6408
  let renderNode = useRenderNode(() => ({
@@ -3777,7 +6455,7 @@ var virtualRowsInstanceSeq = 0, EMPTY_RECT2 = Object.freeze({ x: 0, y: 0, w: 0,
3777
6455
  paintRow(y);
3778
6456
  }
3779
6457
  }));
3780
- return (0, import_vue12.watchEffect)(() => {
6458
+ return (0, import_vue16.watchEffect)(() => {
3781
6459
  renderNodeId = renderNode.id.value;
3782
6460
  }), () => {
3783
6461
  let children = [];
@@ -3798,7 +6476,7 @@ var virtualRowsInstanceSeq = 0, EMPTY_RECT2 = Object.freeze({ x: 0, y: 0, w: 0,
3798
6476
  );
3799
6477
  }
3800
6478
  }
3801
- return (0, import_vue12.h)("div", rootProps, children);
6479
+ return (0, import_vue16.h)("div", rootProps, children);
3802
6480
  };
3803
6481
  }
3804
6482
  });
@@ -3874,7 +6552,7 @@ function reindexVisualRows(rows, rowIndex) {
3874
6552
  function sameCachedLayout(entry, next, matchRowIndex = !0) {
3875
6553
  return !!entry && (next.usesSourceRowVersion || entry.version === next.version) && entry.rowVersion === next.rowVersion && entry.usesSourceRowVersion === next.usesSourceRowVersion && (next.usesSourceRowVersion || entry.row === next.row) && (!matchRowIndex || entry.rowIndex === next.rowIndex) && entry.rowKey === next.rowKey && entry.width === next.width && entry.wrap === next.wrap && entry.baseStyle === next.baseStyle && entry.hoverStyle === next.hoverStyle && entry.focusStyle === next.focusStyle && entry.hoverRegionId === next.hoverRegionId && entry.focusedRegionId === next.focusedRegionId;
3876
6554
  }
3877
- var TTranscriptView = (0, import_vue13.defineComponent)({
6555
+ var TTranscriptView = (0, import_vue17.defineComponent)({
3878
6556
  name: "TTranscriptView",
3879
6557
  props: {
3880
6558
  x: { type: Number, required: !0 },
@@ -3915,7 +6593,7 @@ var TTranscriptView = (0, import_vue13.defineComponent)({
3915
6593
  "hoverRegion"
3916
6594
  ],
3917
6595
  setup(props, { emit, expose }) {
3918
- let { defaultStyle, observability } = useTerminal(), instance = (0, import_vue13.getCurrentInstance)(), rowsRef = (0, import_vue13.ref)(null), innerScrollTop = (0, import_vue13.ref)(normalizeInt2(props.defaultScrollTop)), hoveredRegion = (0, import_vue13.ref)(null), focusedRegion = (0, import_vue13.ref)(null), rowLayoutCache = /* @__PURE__ */ new Map(), keyedRowLayoutCache = /* @__PURE__ */ new Map(), previousWrappedLayout = null, previousWrappedDeps = null, canUseWrappedChangedRangeRepaint = !1, warnedLargeFlattenedRows = !1;
6596
+ let { defaultStyle, observability } = useTerminal(), instance = (0, import_vue17.getCurrentInstance)(), rowsRef = (0, import_vue17.ref)(null), innerScrollTop = (0, import_vue17.ref)(normalizeInt2(props.defaultScrollTop)), hoveredRegion = (0, import_vue17.ref)(null), focusedRegion = (0, import_vue17.ref)(null), rowLayoutCache = /* @__PURE__ */ new Map(), keyedRowLayoutCache = /* @__PURE__ */ new Map(), previousWrappedLayout = null, previousWrappedDeps = null, canUseWrappedChangedRangeRepaint = !1, warnedLargeFlattenedRows = !1;
3919
6597
  function isScrollControlled() {
3920
6598
  return Object.prototype.hasOwnProperty.call(instance?.vnode.props ?? {}, "scrollTop");
3921
6599
  }
@@ -4023,7 +6701,7 @@ var TTranscriptView = (0, import_vue13.defineComponent)({
4023
6701
  };
4024
6702
  return previousWrappedLayout = state, { state, cacheHit, cacheMiss };
4025
6703
  }
4026
- let layoutState = (0, import_vue13.computed)(() => {
6704
+ let layoutState = (0, import_vue17.computed)(() => {
4027
6705
  props.version, canUseWrappedChangedRangeRepaint = !1;
4028
6706
  let perfEnabled = observability.framePerf.enabled.value, perfStartedAt = perfEnabled ? framePerfNow() : 0, width = Math.max(1, Math.floor(props.w)), count = Math.max(0, normalizeInt2(props.source.rowCount()));
4029
6707
  if (!count)
@@ -4113,7 +6791,7 @@ var TTranscriptView = (0, import_vue13.defineComponent)({
4113
6791
  });
4114
6792
  let state = { visualRows, rowStarts, rowEnds, regions, fixedRows, rowCount: count };
4115
6793
  return fixedRows ? (previousWrappedLayout = null, previousWrappedDeps = null) : (previousWrappedLayout = state, previousWrappedDeps = wrappedDeps), state;
4116
- }), maxScrollTop = (0, import_vue13.computed)(
6794
+ }), maxScrollTop = (0, import_vue17.computed)(
4117
6795
  () => Math.max(0, layoutState.value.visualRows.length - Math.max(0, normalizeInt2(props.h)))
4118
6796
  );
4119
6797
  function setScrollTop(top) {
@@ -4255,12 +6933,12 @@ var TTranscriptView = (0, import_vue13.defineComponent)({
4255
6933
  focusPreviousRegion,
4256
6934
  activateFocusedRegion,
4257
6935
  getHoveredRegion: () => hoveredRegion.value
4258
- }), (0, import_vue13.watch)(
6936
+ }), (0, import_vue17.watch)(
4259
6937
  () => props.defaultScrollTop,
4260
6938
  (top) => {
4261
6939
  isScrollControlled() || (innerScrollTop.value = clamp4(normalizeInt2(top), 0, maxScrollTop.value));
4262
6940
  }
4263
- ), (0, import_vue13.watch)(
6941
+ ), (0, import_vue17.watch)(
4264
6942
  () => layoutState.value.visualRows.length,
4265
6943
  (next, prev) => {
4266
6944
  if (!props.autoStickToBottom)
@@ -4271,7 +6949,7 @@ var TTranscriptView = (0, import_vue13.defineComponent)({
4271
6949
  let nextTop = Math.max(0, next - viewportRows);
4272
6950
  rowsRef.value?.scrollTo(nextTop), setScrollTop(nextTop);
4273
6951
  }
4274
- ), (0, import_vue13.watch)(
6952
+ ), (0, import_vue17.watch)(
4275
6953
  () => [layoutState.value.regions, currentScrollTop(), props.h],
4276
6954
  () => reconcileActiveRegions()
4277
6955
  );
@@ -4299,7 +6977,7 @@ var TTranscriptView = (0, import_vue13.defineComponent)({
4299
6977
  let nodes = [];
4300
6978
  for (let region of visualRow.hitRegions)
4301
6979
  nodes.push(
4302
- (0, import_vue13.h)(TView, {
6980
+ (0, import_vue17.h)(TView, {
4303
6981
  key: `${region.id}:${ctx.index}:${region.x0}`,
4304
6982
  x: region.x0,
4305
6983
  y: ctx.row,
@@ -4354,7 +7032,7 @@ var TTranscriptView = (0, import_vue13.defineComponent)({
4354
7032
  let visualRow = ctx.item;
4355
7033
  return visualRow ? visualRow.selectionSegments.length ? textForSelectionSegments(visualRow.selectionSegments, ctx.x0, ctx.x1) : sliceByCellsRange(selectionTextForVisualRow(visualRow), ctx.x0, ctx.x1) : "";
4356
7034
  }
4357
- return () => (0, import_vue13.h)(TVirtualRows, {
7035
+ return () => (0, import_vue17.h)(TVirtualRows, {
4358
7036
  ref: rowsRef,
4359
7037
  x: props.x,
4360
7038
  y: props.y,
@@ -4395,187 +7073,6 @@ var TTranscriptView = (0, import_vue13.defineComponent)({
4395
7073
  }
4396
7074
  });
4397
7075
 
4398
- // src/core/ansi/sgr.ts
4399
- var ESC = "\x1B";
4400
- function ansi16ToColorName(code) {
4401
- switch (code) {
4402
- case 30:
4403
- return "black";
4404
- case 31:
4405
- return "red";
4406
- case 32:
4407
- return "green";
4408
- case 33:
4409
- return "yellow";
4410
- case 34:
4411
- return "blue";
4412
- case 35:
4413
- return "magenta";
4414
- case 36:
4415
- return "cyan";
4416
- case 37:
4417
- return "white";
4418
- case 90:
4419
- return "blackBright";
4420
- case 91:
4421
- return "redBright";
4422
- case 92:
4423
- return "greenBright";
4424
- case 93:
4425
- return "yellowBright";
4426
- case 94:
4427
- return "blueBright";
4428
- case 95:
4429
- return "magentaBright";
4430
- case 96:
4431
- return "cyanBright";
4432
- case 97:
4433
- return "whiteBright";
4434
- default:
4435
- return;
4436
- }
4437
- }
4438
- function ansi16BgToColorName(code) {
4439
- let fgCode = code >= 40 && code <= 47 || code >= 100 && code <= 107 ? code - 10 : null;
4440
- if (fgCode != null)
4441
- return ansi16ToColorName(fgCode);
4442
- }
4443
- var ANSI16_RGB = {
4444
- black: { r: 0, g: 0, b: 0 },
4445
- red: { r: 201, g: 27, b: 0 },
4446
- green: { r: 0, g: 194, b: 0 },
4447
- yellow: { r: 199, g: 196, b: 0 },
4448
- blue: { r: 2, g: 37, b: 199 },
4449
- magenta: { r: 201, g: 48, b: 199 },
4450
- cyan: { r: 0, g: 197, b: 199 },
4451
- white: { r: 199, g: 199, b: 199 },
4452
- blackBright: { r: 104, g: 104, b: 104 },
4453
- redBright: { r: 255, g: 110, b: 103 },
4454
- greenBright: { r: 95, g: 250, b: 104 },
4455
- yellowBright: { r: 255, g: 252, b: 103 },
4456
- blueBright: { r: 104, g: 113, b: 255 },
4457
- magentaBright: { r: 255, g: 118, b: 255 },
4458
- cyanBright: { r: 95, g: 253, b: 255 },
4459
- whiteBright: { r: 255, g: 255, b: 255 }
4460
- };
4461
- function nearestAnsi16(r, g, b) {
4462
- let best = "white", bestDist = Number.POSITIVE_INFINITY;
4463
- for (let [name, rgb] of Object.entries(ANSI16_RGB)) {
4464
- let dr = r - rgb.r, dg = g - rgb.g, db = b - rgb.b, d = dr * dr + dg * dg + db * db;
4465
- d < bestDist && (bestDist = d, best = name);
4466
- }
4467
- return best;
4468
- }
4469
- function ansi256ToRgb(index) {
4470
- let n = Math.max(0, Math.min(255, Math.trunc(index)));
4471
- if (n < 16) {
4472
- let name = [
4473
- "black",
4474
- "red",
4475
- "green",
4476
- "yellow",
4477
- "blue",
4478
- "magenta",
4479
- "cyan",
4480
- "white",
4481
- "blackBright",
4482
- "redBright",
4483
- "greenBright",
4484
- "yellowBright",
4485
- "blueBright",
4486
- "magentaBright",
4487
- "cyanBright",
4488
- "whiteBright"
4489
- ][n] ?? "white";
4490
- return ANSI16_RGB[name];
4491
- }
4492
- if (n >= 232) {
4493
- let c = 8 + (n - 232) * 10;
4494
- return { r: c, g: c, b: c };
4495
- }
4496
- let i = n - 16, rr = Math.floor(i / 36), gg = Math.floor(i % 36 / 6), bb = i % 6, toComponent = (v) => v === 0 ? 0 : 55 + v * 40;
4497
- return { r: toComponent(rr), g: toComponent(gg), b: toComponent(bb) };
4498
- }
4499
- function applyAnsiSgrStyle(current, codes) {
4500
- let next = { ...current };
4501
- for (let i = 0; i < codes.length; i++) {
4502
- let code = codes[i];
4503
- if (code === 0) {
4504
- next = {};
4505
- continue;
4506
- }
4507
- if (code === 1)
4508
- next = { ...next, bold: !0 };
4509
- else if (code === 2)
4510
- next = { ...next, dim: !0 };
4511
- else if (code === 3)
4512
- next = { ...next, italic: !0 };
4513
- else if (code === 4)
4514
- next = { ...next, underline: !0 };
4515
- else if (code === 7)
4516
- next = { ...next, inverse: !0 };
4517
- else if (code === 22)
4518
- next = { ...next, bold: !1, dim: !1 };
4519
- else if (code === 23)
4520
- next = { ...next, italic: !1 };
4521
- else if (code === 24)
4522
- next = { ...next, underline: !1 };
4523
- else if (code === 27)
4524
- next = { ...next, inverse: !1 };
4525
- else if (code === 39)
4526
- next = { ...next, fg: void 0 };
4527
- else if (code === 49)
4528
- next = { ...next, bg: void 0 };
4529
- else if (code >= 30 && code <= 37 || code >= 90 && code <= 97) {
4530
- let fg = ansi16ToColorName(code);
4531
- next = { ...next, fg: fg ?? next.fg };
4532
- } else if (code >= 40 && code <= 47 || code >= 100 && code <= 107) {
4533
- let bg = ansi16BgToColorName(code);
4534
- next = { ...next, bg: bg ?? next.bg };
4535
- } else if (code === 38 || code === 48) {
4536
- let mode = codes[i + 1];
4537
- if (mode === 5) {
4538
- let idx = codes[i + 2];
4539
- if (idx != null) {
4540
- let { r, g, b } = ansi256ToRgb(idx), name = nearestAnsi16(r, g, b);
4541
- next = code === 38 ? { ...next, fg: name } : { ...next, bg: name };
4542
- }
4543
- i += 2;
4544
- } else if (mode === 2) {
4545
- let r = codes[i + 2], g = codes[i + 3], b = codes[i + 4];
4546
- if (r != null && g != null && b != null) {
4547
- let name = nearestAnsi16(r, g, b);
4548
- next = code === 38 ? { ...next, fg: name } : { ...next, bg: name };
4549
- }
4550
- i += 4;
4551
- }
4552
- }
4553
- }
4554
- return next;
4555
- }
4556
- function parseAnsiSgr(input, baseStyle = {}) {
4557
- let segments = [], style = { ...baseStyle }, lastIndex = 0;
4558
- for (let i = 0; i < input.length; i++) {
4559
- if (input[i] !== ESC || input[i + 1] !== "[")
4560
- continue;
4561
- let j = i + 2;
4562
- for (; j < input.length; ) {
4563
- let c = input.charCodeAt(j);
4564
- if (c >= 48 && c <= 57 || c === 59) {
4565
- j++;
4566
- continue;
4567
- }
4568
- break;
4569
- }
4570
- if (j >= input.length || input[j] !== "m")
4571
- continue;
4572
- i > lastIndex && segments.push({ text: input.slice(lastIndex, i), style });
4573
- let codes = input.slice(i + 2, j).split(";").filter(Boolean).map((n) => Number.parseInt(n, 10)).filter((n) => Number.isFinite(n));
4574
- style = applyAnsiSgrStyle(style, codes.length ? codes : [0]), lastIndex = j + 1, i = j;
4575
- }
4576
- return lastIndex < input.length && segments.push({ text: input.slice(lastIndex), style }), segments;
4577
- }
4578
-
4579
7076
  // src/utils/url-safety.ts
4580
7077
  var ENCODED_ASCII_CONTROL_RE = /%(?:0[0-9a-f]|1[0-9a-f]|7f)/i;
4581
7078
  function hasControlCodePoint(value) {
@@ -4660,7 +7157,7 @@ function sanitizeDomHref(value, options = {}) {
4660
7157
  }
4661
7158
 
4662
7159
  // src/vue/components/TLogView.ts
4663
- var import_vue14 = require("vue");
7160
+ var import_vue18 = require("vue");
4664
7161
 
4665
7162
  // src/vue/theme.ts
4666
7163
  var tuiDefaultTheme = Object.freeze({
@@ -5142,7 +7639,7 @@ function countAsciiAnsiTextCells(text) {
5142
7639
  }
5143
7640
  return cells;
5144
7641
  }
5145
- var TLogView = (0, import_vue14.defineComponent)({
7642
+ var TLogView = (0, import_vue18.defineComponent)({
5146
7643
  name: "TLogView",
5147
7644
  props: {
5148
7645
  x: { type: Number, required: !0 },
@@ -5251,19 +7748,19 @@ var TLogView = (0, import_vue14.defineComponent)({
5251
7748
  "keydown"
5252
7749
  ],
5253
7750
  setup(props, { emit, expose }) {
5254
- let { terminal, scheduler, render, rendererCapabilities, defaultStyle, events, selection } = useTerminal(), layout = useLayout(), { visible, rootProps } = useVisibility(), plane = (0, import_vue14.inject)(RenderPlaneContextKey, (0, import_vue14.ref)("default")), parentEventZ = (0, import_vue14.inject)(EventZIndexContextKey, (0, import_vue14.computed)(() => 0)), eventZ = (0, import_vue14.computed)(() => (parentEventZ.value ?? 0) + (props.zIndex ?? 0)), theme = (0, import_vue14.inject)(TuiThemeContextKey, (0, import_vue14.ref)(tuiDefaultTheme)), effectiveAnsiLinkStyle = (0, import_vue14.computed)(() => props.linkStyle ?? DEFAULT_LINK_STYLE), effectiveLinkStyle = (0, import_vue14.computed)(() => ({
7751
+ let { terminal, scheduler, render, rendererCapabilities, defaultStyle, events, selection } = useTerminal(), layout = useLayout(), { visible, rootProps } = useVisibility(), plane = (0, import_vue18.inject)(RenderPlaneContextKey, (0, import_vue18.ref)("default")), parentEventZ = (0, import_vue18.inject)(EventZIndexContextKey, (0, import_vue18.computed)(() => 0)), eventZ = (0, import_vue18.computed)(() => (parentEventZ.value ?? 0) + (props.zIndex ?? 0)), theme = (0, import_vue18.inject)(TuiThemeContextKey, (0, import_vue18.ref)(tuiDefaultTheme)), effectiveAnsiLinkStyle = (0, import_vue18.computed)(() => props.linkStyle ?? DEFAULT_LINK_STYLE), effectiveLinkStyle = (0, import_vue18.computed)(() => ({
5255
7752
  ...theme.value.components.TLink?.style ?? {},
5256
7753
  ...props.linkStyle ?? {}
5257
- })), focused = (0, import_vue14.ref)(!1), innerScrollTop = (0, import_vue14.ref)(0), stickToBottom = (0, import_vue14.ref)(!0), frameTaskId = `TLogView:${nextTLogViewTaskId++}`, dirtyRowsHint, renderNodeId = null, alive = !0, pendingWheelTop = null, pendingSelectionScrollFocusRemap = !1, initializedScrollTop = !1, lastLineCount = 0, lastFirstLineIndex = 0, lastPaintedBottom = null, cacheClock = 0, renderLineCache = /* @__PURE__ */ new Map(), wrapLineCache = /* @__PURE__ */ new Map(), ansiLineCache = /* @__PURE__ */ new Map(), ansiTextCache = /* @__PURE__ */ new Map(), ansiWrapCache = /* @__PURE__ */ new Map(), ansiRowCache = /* @__PURE__ */ new Map(), linkifyLineCache = /* @__PURE__ */ new Map(), linkifyWrapCache = /* @__PURE__ */ new Map(), searchLineCache = /* @__PURE__ */ new Map(), visibleLinksByRow = /* @__PURE__ */ new Map(), focusedVisibleLinkIndex = (0, import_vue14.ref)(-1), focusedLinkTarget = null, searchGeneration = 0, searchCursor = 0, searchStatus = "idle", searchError = null, compiledSearch = {
7754
+ })), focused = (0, import_vue18.ref)(!1), innerScrollTop = (0, import_vue18.ref)(0), stickToBottom = (0, import_vue18.ref)(!0), frameTaskId = `TLogView:${nextTLogViewTaskId++}`, dirtyRowsHint, renderNodeId = null, alive = !0, pendingWheelTop = null, pendingSelectionScrollFocusRemap = !1, initializedScrollTop = !1, lastLineCount = 0, lastFirstLineIndex = 0, lastPaintedBottom = null, cacheClock = 0, renderLineCache = /* @__PURE__ */ new Map(), wrapLineCache = /* @__PURE__ */ new Map(), ansiLineCache = /* @__PURE__ */ new Map(), ansiTextCache = /* @__PURE__ */ new Map(), ansiWrapCache = /* @__PURE__ */ new Map(), ansiRowCache = /* @__PURE__ */ new Map(), linkifyLineCache = /* @__PURE__ */ new Map(), linkifyWrapCache = /* @__PURE__ */ new Map(), searchLineCache = /* @__PURE__ */ new Map(), visibleLinksByRow = /* @__PURE__ */ new Map(), focusedVisibleLinkIndex = (0, import_vue18.ref)(-1), focusedLinkTarget = null, searchGeneration = 0, searchCursor = 0, searchStatus = "idle", searchError = null, compiledSearch = {
5258
7755
  key: '["text","",""]',
5259
7756
  query: "",
5260
7757
  mode: "text",
5261
7758
  error: null,
5262
7759
  findLineMatches: () => []
5263
- }, currentMatchIndex = -1, searchMatches = [], searchMarkersGeneration = 0, searchMarkersCacheGeneration = -1, searchMarkersCache = [], lastSearchMarkersPayloadKey = "", matchesByLine = /* @__PURE__ */ new Map(), wheelState = createWheelScrollState(), visualIndexWidth = 0, visualIndexLineCount = 0, visualIndexCapacity = 0, visualCounts = [], visualKeys = [], visualTree = [0], visualIndexStatus = "exact", visualMeasureGeneration = 0, visualMeasureCursor = 0, measuredLineCount = 0, measuredVisualRows = 0, lastVisualIndexPayloadKey = "", fullRect = (0, import_vue14.computed)(() => {
7760
+ }, currentMatchIndex = -1, searchMatches = [], searchMarkersGeneration = 0, searchMarkersCacheGeneration = -1, searchMarkersCache = [], lastSearchMarkersPayloadKey = "", matchesByLine = /* @__PURE__ */ new Map(), wheelState = createWheelScrollState(), visualIndexWidth = 0, visualIndexLineCount = 0, visualIndexCapacity = 0, visualCounts = [], visualKeys = [], visualTree = [0], visualIndexStatus = "exact", visualMeasureGeneration = 0, visualMeasureCursor = 0, measuredLineCount = 0, measuredVisualRows = 0, lastVisualIndexPayloadKey = "", fullRect = (0, import_vue18.computed)(() => {
5264
7761
  let raw = { x: props.x, y: props.y, w: props.w, h: props.h };
5265
7762
  return translateRect(raw, layout.originX, layout.originY);
5266
- }), absRect = (0, import_vue14.computed)(() => {
7763
+ }), absRect = (0, import_vue18.computed)(() => {
5267
7764
  let translated = fullRect.value;
5268
7765
  return layout.clipRect ? intersectRect(translated, layout.clipRect) ?? { x: 0, y: 0, w: 0, h: 0 } : translated;
5269
7766
  });
@@ -5327,7 +7824,7 @@ var TLogView = (0, import_vue14.defineComponent)({
5327
7824
  options.protocols ?? []
5328
7825
  ]);
5329
7826
  }
5330
- let linkifyOptionsKey = (0, import_vue14.computed)(() => linkifyOptionsCacheKey());
7827
+ let linkifyOptionsKey = (0, import_vue18.computed)(() => linkifyOptionsCacheKey());
5331
7828
  function linkStyleCacheKey() {
5332
7829
  return linksEnabled() ? styleCacheKey(effectiveAnsiLinkStyle.value) : "";
5333
7830
  }
@@ -6500,10 +8997,10 @@ var TLogView = (0, import_vue14.defineComponent)({
6500
8997
  function shiftVisibleLinksForScrollRegion(y0, y1, delta) {
6501
8998
  if (!visibleLinksByRow.size || delta === 0)
6502
8999
  return;
6503
- let h15 = y1 - y0;
6504
- if (h15 <= 0)
9000
+ let h19 = y1 - y0;
9001
+ if (h19 <= 0)
6505
9002
  return;
6506
- if (Math.abs(delta) >= h15) {
9003
+ if (Math.abs(delta) >= h19) {
6507
9004
  for (let y = y0; y < y1; y++)
6508
9005
  visibleLinksByRow.delete(y);
6509
9006
  return;
@@ -6597,8 +9094,8 @@ var TLogView = (0, import_vue14.defineComponent)({
6597
9094
  return props.wrap || delta <= 0 || delta >= r.h || prevCount <= 0 || nextCount <= prevCount || lastPaintedBottom?.index !== prevCount - 1 || lineKey(prevCount - 1) === lastPaintedBottom.lineKey ? null : r.y + r.h - delta - 1;
6598
9095
  }
6599
9096
  function applyScrollTop(nextTop, strategy = "auto", options) {
6600
- let r = normalizedRect(), full = normalizedFullRect(), h15 = r.h;
6601
- if (h15 <= 0 || full.h <= 0)
9097
+ let r = normalizedRect(), full = normalizedFullRect(), h19 = r.h;
9098
+ if (h19 <= 0 || full.h <= 0)
6602
9099
  return !1;
6603
9100
  options?.stickToBottom === !0 && props.wrap && ensureBottomMeasured();
6604
9101
  let prevTop = rawScrollTop(), clampedTop = normalizeScrollTop(nextTop), delta = clampedTop - prevTop;
@@ -6622,7 +9119,7 @@ var TLogView = (0, import_vue14.defineComponent)({
6622
9119
  if (scrollPlan) {
6623
9120
  let rows = options?.extraDirtyRows?.length ? [...scrollPlan.exposedRows, ...options.extraDirtyRows] : scrollPlan.exposedRows;
6624
9121
  if (markRowsDirty(rows))
6625
- return scrollPlan.apply(), shiftVisibleLinksForScrollRegion(r.y, r.y + h15, delta), options?.emitScroll && emitScroll(clampedTop), !0;
9122
+ return scrollPlan.apply(), shiftVisibleLinksForScrollRegion(r.y, r.y + h19, delta), options?.emitScroll && emitScroll(clampedTop), !0;
6626
9123
  }
6627
9124
  return markViewportDirty(), options?.emitScroll && emitScroll(clampedTop), !0;
6628
9125
  }
@@ -6851,8 +9348,8 @@ var TLogView = (0, import_vue14.defineComponent)({
6851
9348
  return;
6852
9349
  let lineIndex = clamp5(normalizeScrollNumber(index), 0, count - 1), target = lineIndex, visualCount = 1;
6853
9350
  props.wrap && (ensureVisualIndex(), measureVisualLine(lineIndex), target = visualStartForLine(lineIndex), visualCount = visualCounts[lineIndex] ?? 1);
6854
- let h15 = viewportHeight();
6855
- options?.align === "center" ? target -= Math.floor((h15 - visualCount) / 2) : options?.align === "end" && (target += visualCount - h15), scrollToVisualRow(target);
9351
+ let h19 = viewportHeight();
9352
+ options?.align === "center" ? target -= Math.floor((h19 - visualCount) / 2) : options?.align === "end" && (target += visualCount - h19), scrollToVisualRow(target);
6856
9353
  }
6857
9354
  function repaintInvalidatedViewport() {
6858
9355
  let nextTop = stickToBottom.value ? bottomScrollTop() : currentScrollTop(), changed = applyScrollTop(nextTop, "viewport-repaint", {
@@ -7066,7 +9563,7 @@ var TLogView = (0, import_vue14.defineComponent)({
7066
9563
  getText: textForSelectionRange,
7067
9564
  getVisibleSpans: visibleSpansForSelectionRange
7068
9565
  }, unregisterSelectionTextProvider = selection.registerTextProvider(selectionTextProvider);
7069
- (0, import_vue14.onBeforeUnmount)(unregisterSelectionTextProvider);
9566
+ (0, import_vue18.onBeforeUnmount)(unregisterSelectionTextProvider);
7070
9567
  let eventNode = useTerminalNode(() => ({
7071
9568
  rect: normalizedRect(),
7072
9569
  zIndex: eventZ.value,
@@ -7102,12 +9599,12 @@ var TLogView = (0, import_vue14.defineComponent)({
7102
9599
  keydown: onKeydown
7103
9600
  }
7104
9601
  }));
7105
- (0, import_vue14.watchEffect)(() => {
9602
+ (0, import_vue18.watchEffect)(() => {
7106
9603
  if (!props.autoFocus || !visible.value)
7107
9604
  return;
7108
9605
  let manager = events.value, nodeId = eventNode.id.value;
7109
9606
  !manager || !nodeId || manager.getFocused() !== nodeId && manager.focus(nodeId);
7110
- }), (0, import_vue14.watch)(
9607
+ }), (0, import_vue18.watch)(
7111
9608
  [
7112
9609
  () => visible.value,
7113
9610
  () => absRect.value.x,
@@ -7127,24 +9624,24 @@ var TLogView = (0, import_vue14.defineComponent)({
7127
9624
  let nextPendingTop = normalizeScrollTop(pendingWheelTop);
7128
9625
  nextPendingTop === currentScrollTop() ? cancelWheelScrollFrame() : nextPendingTop !== pendingWheelTop && replacePendingWheelTop(nextPendingTop);
7129
9626
  }
7130
- ), (0, import_vue14.watch)(
9627
+ ), (0, import_vue18.watch)(
7131
9628
  () => props.version,
7132
9629
  () => {
7133
9630
  resetWheelScrollState(wheelState), requestDataFrame(), requestSearchScan();
7134
9631
  }
7135
- ), (0, import_vue14.watch)(
9632
+ ), (0, import_vue18.watch)(
7136
9633
  () => [props.ansi, props.links, props.linkify],
7137
9634
  () => {
7138
9635
  visualLinksEnabled() || clearLinkFocus();
7139
9636
  }
7140
- ), (0, import_vue14.watch)(
9637
+ ), (0, import_vue18.watch)(
7141
9638
  () => props.scrollTop,
7142
9639
  () => {
7143
9640
  cancelWheelScrollFrame(), syncStickFromCurrentScrollTop();
7144
9641
  let remap = pendingSelectionScrollFocusRemap;
7145
9642
  pendingSelectionScrollFocusRemap = !1, selection.refresh(remap ? { remapFocus: !0 } : void 0), markViewportDirty(), invalidateSelf("high", "scroll");
7146
9643
  }
7147
- ), (0, import_vue14.watch)(
9644
+ ), (0, import_vue18.watch)(
7148
9645
  [
7149
9646
  () => props.source,
7150
9647
  () => props.wrap,
@@ -7167,7 +9664,7 @@ var TLogView = (0, import_vue14.defineComponent)({
7167
9664
  emitVisualIndex(!0);
7168
9665
  },
7169
9666
  { immediate: !0 }
7170
- ), (0, import_vue14.watch)(
9667
+ ), (0, import_vue18.watch)(
7171
9668
  [
7172
9669
  () => props.searchQuery,
7173
9670
  () => props.searchOptions?.mode,
@@ -7184,12 +9681,12 @@ var TLogView = (0, import_vue14.defineComponent)({
7184
9681
  requestSearchScan();
7185
9682
  },
7186
9683
  { immediate: !0 }
7187
- ), (0, import_vue14.watch)(
9684
+ ), (0, import_vue18.watch)(
7188
9685
  [() => props.highlightMatches, () => props.matchStyle, () => props.currentMatchStyle],
7189
9686
  () => {
7190
9687
  markViewportDirty(), invalidateSelf("normal", "data");
7191
9688
  }
7192
- ), (0, import_vue14.watch)(
9689
+ ), (0, import_vue18.watch)(
7193
9690
  [
7194
9691
  () => props.source,
7195
9692
  () => props.wrap,
@@ -7215,7 +9712,7 @@ var TLogView = (0, import_vue14.defineComponent)({
7215
9712
  changed && selection.refresh(), changed || markViewportDirty(), invalidateSelf("normal", "data");
7216
9713
  },
7217
9714
  { immediate: !0 }
7218
- ), (0, import_vue14.onBeforeUnmount)(() => {
9715
+ ), (0, import_vue18.onBeforeUnmount)(() => {
7219
9716
  alive = !1, searchGeneration++, visualMeasureGeneration++, cancelWheelScrollFrame(), wheelMailbox.dispose(), dataHighMailbox.dispose(), dataNormalMailbox.dispose();
7220
9717
  });
7221
9718
  let renderNode = useRenderNode(() => ({
@@ -7400,14 +9897,14 @@ var TLogView = (0, import_vue14.defineComponent)({
7400
9897
  syncFocusedVisibleLinkFromViewport(), trimRenderCache(), trimWrapCache(), trimAnsiLineCache(), trimAnsiWrapCache(), trimAnsiRowCache(), trimLinkifyLineCache(), trimLinkifyWrapCache();
7401
9898
  }
7402
9899
  }));
7403
- return (0, import_vue14.watchEffect)(() => {
9900
+ return (0, import_vue18.watchEffect)(() => {
7404
9901
  renderNodeId = renderNode.id.value;
7405
- }), lastLineCount = lineCount(), lastFirstLineIndex = firstLineIndex(), () => (0, import_vue14.h)("span", rootProps);
9902
+ }), lastLineCount = lineCount(), lastFirstLineIndex = firstLineIndex(), () => (0, import_vue18.h)("span", rootProps);
7406
9903
  }
7407
9904
  });
7408
9905
 
7409
9906
  // src/vue/components/TLogScrollbar.ts
7410
- var import_vue15 = require("vue");
9907
+ var import_vue19 = require("vue");
7411
9908
  var EMPTY_RECT3 = Object.freeze({ x: 0, y: 0, w: 0, h: 0 }), SCROLLBAR_WIDTH = 1, TRACK_CHAR = "\u2502", EXACT_THUMB_CHAR = "\u2588", MEASURING_THUMB_CHAR = "\u2592", ESTIMATED_THUMB_CHAR = "\u2591", MARKER_CHAR = "\u2022", ESTIMATED_MARKER_CHAR = "\xB7", CURRENT_MARKER_CHAR = "\u25C6", UP_ARROW_CHAR = "\u25B2", DOWN_ARROW_CHAR = "\u25BC";
7412
9909
  function clamp6(n, min, max) {
7413
9910
  return Math.max(min, Math.min(max, n));
@@ -7469,7 +9966,7 @@ function collectMarkersByRow(markers, metrics2, height, showArrows) {
7469
9966
  function mergeStyle3(base, overlay) {
7470
9967
  return overlay ? { ...base, ...overlay } : base;
7471
9968
  }
7472
- var TLogScrollbar = (0, import_vue15.defineComponent)({
9969
+ var TLogScrollbar = (0, import_vue19.defineComponent)({
7473
9970
  name: "TLogScrollbar",
7474
9971
  props: {
7475
9972
  x: { type: Number, required: !0 },
@@ -7501,7 +9998,7 @@ var TLogScrollbar = (0, import_vue15.defineComponent)({
7501
9998
  },
7502
9999
  emits: ["scrollTo", "scrollBy", "markerClick"],
7503
10000
  setup(props, { emit }) {
7504
- let { terminal, defaultStyle } = useTerminal(), parent = useLayout(), { visible, rootProps } = useVisibility(), parentEventZ = (0, import_vue15.inject)(EventZIndexContextKey, (0, import_vue15.computed)(() => 0)), eventZ = (0, import_vue15.computed)(() => (parentEventZ.value ?? 0) + (props.zIndex ?? 0)), fullRect = (0, import_vue15.computed)(
10001
+ let { terminal, defaultStyle } = useTerminal(), parent = useLayout(), { visible, rootProps } = useVisibility(), parentEventZ = (0, import_vue19.inject)(EventZIndexContextKey, (0, import_vue19.computed)(() => 0)), eventZ = (0, import_vue19.computed)(() => (parentEventZ.value ?? 0) + (props.zIndex ?? 0)), fullRect = (0, import_vue19.computed)(
7505
10002
  () => translateRect(
7506
10003
  {
7507
10004
  x: normalizeInt3(props.x),
@@ -7512,7 +10009,7 @@ var TLogScrollbar = (0, import_vue15.defineComponent)({
7512
10009
  parent.originX,
7513
10010
  parent.originY
7514
10011
  )
7515
- ), rect = (0, import_vue15.computed)(() => {
10012
+ ), rect = (0, import_vue19.computed)(() => {
7516
10013
  let translated = fullRect.value;
7517
10014
  return parent.clipRect ? intersectRect(translated, parent.clipRect) ?? EMPTY_RECT3 : translated;
7518
10015
  });
@@ -7615,12 +10112,12 @@ var TLogScrollbar = (0, import_vue15.defineComponent)({
7615
10112
  for (let y of dirtyRows)
7616
10113
  paintRow(y);
7617
10114
  }
7618
- })), () => (0, import_vue15.h)("span", rootProps);
10115
+ })), () => (0, import_vue19.h)("span", rootProps);
7619
10116
  }
7620
10117
  });
7621
10118
 
7622
10119
  // src/vue/components/TLogMinimap.ts
7623
- var import_vue16 = require("vue");
10120
+ var import_vue20 = require("vue");
7624
10121
  var EMPTY_RECT4 = Object.freeze({ x: 0, y: 0, w: 0, h: 0 }), CURRENT_MARKER_CHAR2 = "\u25C6", MARKER_CHAR2 = "\u2022", ESTIMATED_MARKER_CHAR2 = "\xB7", VIEWPORT_CHAR = "\u2588", DENSITY_HIGH_CHAR = "\u2593", DENSITY_MEDIUM_CHAR = "\u2592", DENSITY_LOW_CHAR = "\u2591";
7625
10122
  function clamp7(n, min, max) {
7626
10123
  return Math.max(min, Math.min(max, n));
@@ -7709,7 +10206,7 @@ function collectDensityByRow(density, metrics2, height) {
7709
10206
  function densityChar(value) {
7710
10207
  return value >= 0.66 ? DENSITY_HIGH_CHAR : value >= 0.33 ? DENSITY_MEDIUM_CHAR : value > 0 ? DENSITY_LOW_CHAR : " ";
7711
10208
  }
7712
- var TLogMinimap = (0, import_vue16.defineComponent)({
10209
+ var TLogMinimap = (0, import_vue20.defineComponent)({
7713
10210
  name: "TLogMinimap",
7714
10211
  props: {
7715
10212
  x: { type: Number, required: !0 },
@@ -7741,7 +10238,7 @@ var TLogMinimap = (0, import_vue16.defineComponent)({
7741
10238
  },
7742
10239
  emits: ["scrollTo", "markerClick"],
7743
10240
  setup(props, { emit }) {
7744
- let { terminal, defaultStyle } = useTerminal(), parent = useLayout(), { visible, rootProps } = useVisibility(), parentEventZ = (0, import_vue16.inject)(EventZIndexContextKey, (0, import_vue16.computed)(() => 0)), eventZ = (0, import_vue16.computed)(() => (parentEventZ.value ?? 0) + (props.zIndex ?? 0)), fullRect = (0, import_vue16.computed)(
10241
+ let { terminal, defaultStyle } = useTerminal(), parent = useLayout(), { visible, rootProps } = useVisibility(), parentEventZ = (0, import_vue20.inject)(EventZIndexContextKey, (0, import_vue20.computed)(() => 0)), eventZ = (0, import_vue20.computed)(() => (parentEventZ.value ?? 0) + (props.zIndex ?? 0)), fullRect = (0, import_vue20.computed)(
7745
10242
  () => translateRect(
7746
10243
  {
7747
10244
  x: normalizeInt4(props.x),
@@ -7752,7 +10249,7 @@ var TLogMinimap = (0, import_vue16.defineComponent)({
7752
10249
  parent.originX,
7753
10250
  parent.originY
7754
10251
  )
7755
- ), rect = (0, import_vue16.computed)(() => {
10252
+ ), rect = (0, import_vue20.computed)(() => {
7756
10253
  let translated = fullRect.value;
7757
10254
  return parent.clipRect ? intersectRect(translated, parent.clipRect) ?? EMPTY_RECT4 : translated;
7758
10255
  });
@@ -7847,12 +10344,12 @@ var TLogMinimap = (0, import_vue16.defineComponent)({
7847
10344
  for (let y of dirtyRows)
7848
10345
  paintRow(y);
7849
10346
  }
7850
- })), () => (0, import_vue16.h)("span", rootProps);
10347
+ })), () => (0, import_vue20.h)("span", rootProps);
7851
10348
  }
7852
10349
  });
7853
10350
 
7854
10351
  // src/vue/components/TLogSearchBar.ts
7855
- var import_vue17 = require("vue");
10352
+ var import_vue21 = require("vue");
7856
10353
  var EMPTY_RECT5 = Object.freeze({ x: 0, y: 0, w: 0, h: 0 }), PREVIOUS_CHAR = "\u25C0", NEXT_CHAR = "\u25B6";
7857
10354
  function clamp8(n, min, max) {
7858
10355
  return Math.max(min, Math.min(max, n));
@@ -7882,7 +10379,7 @@ function cellToStringIndex(text, cell) {
7882
10379
  function errorLabel(error) {
7883
10380
  return error?.kind === "invalid-regex" ? "Invalid regex" : "Search error";
7884
10381
  }
7885
- var TLogSearchBar = (0, import_vue17.defineComponent)({
10382
+ var TLogSearchBar = (0, import_vue21.defineComponent)({
7886
10383
  name: "TLogSearchBar",
7887
10384
  props: {
7888
10385
  x: { type: Number, required: !0 },
@@ -7933,7 +10430,7 @@ var TLogSearchBar = (0, import_vue17.defineComponent)({
7933
10430
  "keydown"
7934
10431
  ],
7935
10432
  setup(props, { emit }) {
7936
- let { terminal, scheduler, defaultStyle, events } = useTerminal(), parent = useLayout(), { visible, rootProps } = useVisibility(), parentEventZ = (0, import_vue17.inject)(EventZIndexContextKey, (0, import_vue17.computed)(() => 0)), eventZ = (0, import_vue17.computed)(() => (parentEventZ.value ?? 0) + (props.zIndex ?? 0)), focused = (0, import_vue17.ref)(!1), cursor = (0, import_vue17.ref)(0), scrollCellOffset = (0, import_vue17.ref)(0), pendingUpdate = (0, import_vue17.ref)(null), fullRect = (0, import_vue17.computed)(
10433
+ let { terminal, scheduler, defaultStyle, events } = useTerminal(), parent = useLayout(), { visible, rootProps } = useVisibility(), parentEventZ = (0, import_vue21.inject)(EventZIndexContextKey, (0, import_vue21.computed)(() => 0)), eventZ = (0, import_vue21.computed)(() => (parentEventZ.value ?? 0) + (props.zIndex ?? 0)), focused = (0, import_vue21.ref)(!1), cursor = (0, import_vue21.ref)(0), scrollCellOffset = (0, import_vue21.ref)(0), pendingUpdate = (0, import_vue21.ref)(null), fullRect = (0, import_vue21.computed)(
7937
10434
  () => translateRect(
7938
10435
  {
7939
10436
  x: normalizeInt5(props.x),
@@ -7944,7 +10441,7 @@ var TLogSearchBar = (0, import_vue17.defineComponent)({
7944
10441
  parent.originX,
7945
10442
  parent.originY
7946
10443
  )
7947
- ), rect = (0, import_vue17.computed)(() => {
10444
+ ), rect = (0, import_vue21.computed)(() => {
7948
10445
  let translated = fullRect.value;
7949
10446
  return parent.clipRect ? intersectRect(translated, parent.clipRect) ?? EMPTY_RECT5 : translated;
7950
10447
  });
@@ -7964,7 +10461,7 @@ var TLogSearchBar = (0, import_vue17.defineComponent)({
7964
10461
  let totalCells = textCellWidth(query), maxScroll = Math.max(0, totalCells - inputWidth), cursorCell = stringIndexToCell2(query, cursor.value), nextScroll = clamp8(scrollCellOffset.value, 0, maxScroll);
7965
10462
  cursorCell < nextScroll && (nextScroll = cursorCell), cursorCell >= nextScroll + inputWidth && (nextScroll = cursorCell - inputWidth + 1), scrollCellOffset.value = clamp8(nextScroll, 0, maxScroll);
7966
10463
  }
7967
- let statusText = (0, import_vue17.computed)(() => props.state.status === "error" ? errorLabel(props.state.error) : props.state.status === "scanning" ? !props.showCount || props.state.matchCount <= 0 ? "Scanning\u2026" : `Scanning\u2026 ${props.state.matchCount}` : !props.showCount || !props.state.query ? "" : `${props.state.matchCount > 0 && props.state.currentMatchIndex >= 0 ? props.state.currentMatchIndex + 1 : 0}/${props.state.matchCount}`), rowLayout = (0, import_vue17.computed)(() => {
10464
+ let statusText = (0, import_vue21.computed)(() => props.state.status === "error" ? errorLabel(props.state.error) : props.state.status === "scanning" ? !props.showCount || props.state.matchCount <= 0 ? "Scanning\u2026" : `Scanning\u2026 ${props.state.matchCount}` : !props.showCount || !props.state.query ? "" : `${props.state.matchCount > 0 && props.state.currentMatchIndex >= 0 ? props.state.currentMatchIndex + 1 : 0}/${props.state.matchCount}`), rowLayout = (0, import_vue21.computed)(() => {
7968
10465
  let width = Math.max(0, normalizeInt5(props.w)), base = props.style ?? defaultStyle.value, toggleBase = mergeStyle5(base, props.toggleStyle), active = mergeStyle5(toggleBase, props.activeStyle), disabled = mergeStyle5(toggleBase, props.disabledStyle), error = mergeStyle5(base, props.errorStyle), navigationEnabled = props.state.matchCount > 0 && props.state.status !== "error" && props.state.query.length > 0, prefixPieces = [], suffixSpecs = [], hits = [], prefixWidth = 0, pushPrefix = (text, style, action) => {
7969
10466
  if (!text)
7970
10467
  return;
@@ -8130,7 +10627,7 @@ var TLogSearchBar = (0, import_vue17.defineComponent)({
8130
10627
  );
8131
10628
  }
8132
10629
  }
8133
- (0, import_vue17.watch)(
10630
+ (0, import_vue21.watch)(
8134
10631
  () => [
8135
10632
  props.state.query,
8136
10633
  props.state.mode,
@@ -8228,7 +10725,7 @@ var TLogSearchBar = (0, import_vue17.defineComponent)({
8228
10725
  clipped && terminal.write(clipped, { x: Math.max(drawX, r.x), y: r.y, style: piece.style });
8229
10726
  }
8230
10727
  }
8231
- })), () => (0, import_vue17.h)(
10728
+ })), () => (0, import_vue21.h)(
8232
10729
  "div",
8233
10730
  {
8234
10731
  ...rootProps,
@@ -8240,7 +10737,7 @@ var TLogSearchBar = (0, import_vue17.defineComponent)({
8240
10737
  });
8241
10738
 
8242
10739
  // src/vue/components/TLogSearchResults.ts
8243
- var import_vue18 = require("vue");
10740
+ var import_vue22 = require("vue");
8244
10741
  var EMPTY_RECT6 = Object.freeze({ x: 0, y: 0, w: 0, h: 0 });
8245
10742
  function clamp9(n, min, max) {
8246
10743
  return Math.max(min, Math.min(max, n));
@@ -8258,7 +10755,7 @@ function normalizeActiveIndex(value, count) {
8258
10755
  let n = Math.floor(Number(value));
8259
10756
  return !Number.isFinite(n) || n < 0 ? -1 : clamp9(n, 0, count - 1);
8260
10757
  }
8261
- var TLogSearchResults = (0, import_vue18.defineComponent)({
10758
+ var TLogSearchResults = (0, import_vue22.defineComponent)({
8262
10759
  name: "TLogSearchResults",
8263
10760
  props: {
8264
10761
  x: { type: Number, required: !0 },
@@ -8289,7 +10786,7 @@ var TLogSearchResults = (0, import_vue18.defineComponent)({
8289
10786
  },
8290
10787
  emits: ["select", "activeChange", "keydown", "focus", "blur"],
8291
10788
  setup(props, { emit }) {
8292
- let { terminal, scheduler, defaultStyle, events } = useTerminal(), parent = useLayout(), { visible, rootProps } = useVisibility(), parentEventZ = (0, import_vue18.inject)(EventZIndexContextKey, (0, import_vue18.computed)(() => 0)), eventZ = (0, import_vue18.computed)(() => (parentEventZ.value ?? 0) + (props.zIndex ?? 0)), focused = (0, import_vue18.ref)(!1), internalActiveIndex = (0, import_vue18.ref)(-1), fullRect = (0, import_vue18.computed)(
10789
+ let { terminal, scheduler, defaultStyle, events } = useTerminal(), parent = useLayout(), { visible, rootProps } = useVisibility(), parentEventZ = (0, import_vue22.inject)(EventZIndexContextKey, (0, import_vue22.computed)(() => 0)), eventZ = (0, import_vue22.computed)(() => (parentEventZ.value ?? 0) + (props.zIndex ?? 0)), focused = (0, import_vue22.ref)(!1), internalActiveIndex = (0, import_vue22.ref)(-1), fullRect = (0, import_vue22.computed)(
8293
10790
  () => translateRect(
8294
10791
  {
8295
10792
  x: normalizeInt6(props.x),
@@ -8300,16 +10797,16 @@ var TLogSearchResults = (0, import_vue18.defineComponent)({
8300
10797
  parent.originX,
8301
10798
  parent.originY
8302
10799
  )
8303
- ), rect = (0, import_vue18.computed)(() => {
10800
+ ), rect = (0, import_vue22.computed)(() => {
8304
10801
  let translated = fullRect.value;
8305
10802
  return parent.clipRect ? intersectRect(translated, parent.clipRect) ?? EMPTY_RECT6 : translated;
8306
- }), lineNumberDigits = (0, import_vue18.computed)(
10803
+ }), lineNumberDigits = (0, import_vue22.computed)(
8307
10804
  () => props.showLineNumbers ? props.results.reduce(
8308
10805
  (max, result) => Math.max(max, String(result.absoluteLineIndex).length),
8309
10806
  1
8310
10807
  ) : 0
8311
10808
  );
8312
- (0, import_vue18.watch)(
10809
+ (0, import_vue22.watch)(
8313
10810
  [() => props.activeIndex, () => props.results.length],
8314
10811
  () => {
8315
10812
  internalActiveIndex.value = normalizeActiveIndex(props.activeIndex, props.results.length);
@@ -8440,12 +10937,12 @@ var TLogSearchResults = (0, import_vue18.defineComponent)({
8440
10937
  }), result.text || segments.push({ text: "", style: rowStyle }), writeSegments(y, rowStyle, segments);
8441
10938
  }
8442
10939
  }
8443
- })), () => (0, import_vue18.h)("span", rootProps);
10940
+ })), () => (0, import_vue22.h)("span", rootProps);
8444
10941
  }
8445
10942
  });
8446
10943
 
8447
10944
  // src/vue/components/TLogSearchPager.ts
8448
- var import_vue19 = require("vue");
10945
+ var import_vue23 = require("vue");
8449
10946
  var EMPTY_RECT7 = Object.freeze({ x: 0, y: 0, w: 0, h: 0 }), PREVIOUS_CHAR2 = "\u25C0", NEXT_CHAR2 = "\u25B6";
8450
10947
  function clamp10(n, min, max) {
8451
10948
  return Math.max(min, Math.min(max, n));
@@ -8463,7 +10960,7 @@ function formatCount(matchCount) {
8463
10960
  function errorLabel2(error) {
8464
10961
  return error?.kind === "invalid-regex" ? "Invalid regex" : "Search error";
8465
10962
  }
8466
- var TLogSearchPager = (0, import_vue19.defineComponent)({
10963
+ var TLogSearchPager = (0, import_vue23.defineComponent)({
8467
10964
  name: "TLogSearchPager",
8468
10965
  props: {
8469
10966
  x: { type: Number, required: !0 },
@@ -8488,7 +10985,7 @@ var TLogSearchPager = (0, import_vue19.defineComponent)({
8488
10985
  },
8489
10986
  emits: ["previousPage", "nextPage", "pageChange"],
8490
10987
  setup(props, { emit }) {
8491
- let { terminal, scheduler, defaultStyle, events } = useTerminal(), parent = useLayout(), { visible, rootProps } = useVisibility(), parentEventZ = (0, import_vue19.inject)(EventZIndexContextKey, (0, import_vue19.computed)(() => 0)), eventZ = (0, import_vue19.computed)(() => (parentEventZ.value ?? 0) + (props.zIndex ?? 0)), focused = (0, import_vue19.ref)(!1), fullRect = (0, import_vue19.computed)(
10988
+ let { terminal, scheduler, defaultStyle, events } = useTerminal(), parent = useLayout(), { visible, rootProps } = useVisibility(), parentEventZ = (0, import_vue23.inject)(EventZIndexContextKey, (0, import_vue23.computed)(() => 0)), eventZ = (0, import_vue23.computed)(() => (parentEventZ.value ?? 0) + (props.zIndex ?? 0)), focused = (0, import_vue23.ref)(!1), fullRect = (0, import_vue23.computed)(
8492
10989
  () => translateRect(
8493
10990
  {
8494
10991
  x: normalizeInt7(props.x),
@@ -8499,10 +10996,10 @@ var TLogSearchPager = (0, import_vue19.defineComponent)({
8499
10996
  parent.originX,
8500
10997
  parent.originY
8501
10998
  )
8502
- ), rect = (0, import_vue19.computed)(() => {
10999
+ ), rect = (0, import_vue23.computed)(() => {
8503
11000
  let translated = fullRect.value;
8504
11001
  return parent.clipRect ? intersectRect(translated, parent.clipRect) ?? EMPTY_RECT7 : translated;
8505
- }), viewState = (0, import_vue19.computed)(() => props.state), segments = (0, import_vue19.computed)(() => {
11002
+ }), viewState = (0, import_vue23.computed)(() => props.state), segments = (0, import_vue23.computed)(() => {
8506
11003
  let base = props.style ?? defaultStyle.value, active = mergeStyle7(base, props.activeStyle), disabled = mergeStyle7(base, props.disabledStyle), error = mergeStyle7(base, props.errorStyle), state = viewState.value;
8507
11004
  if (!state || state.status === "idle")
8508
11005
  return [{ text: "No search", style: base }];
@@ -8623,7 +11120,7 @@ var TLogSearchPager = (0, import_vue19.defineComponent)({
8623
11120
  break;
8624
11121
  }
8625
11122
  }
8626
- })), () => (0, import_vue19.h)(
11123
+ })), () => (0, import_vue23.h)(
8627
11124
  "div",
8628
11125
  {
8629
11126
  ...rootProps,
@@ -8635,7 +11132,7 @@ var TLogSearchPager = (0, import_vue19.defineComponent)({
8635
11132
  });
8636
11133
 
8637
11134
  // src/vue/components/TLogLinksPanel.ts
8638
- var import_vue20 = require("vue");
11135
+ var import_vue24 = require("vue");
8639
11136
  var EMPTY_RECT8 = Object.freeze({ x: 0, y: 0, w: 0, h: 0 }), EMPTY_LABEL = "No visible links";
8640
11137
  function clamp11(n, min, max) {
8641
11138
  return Math.max(min, Math.min(max, n));
@@ -8653,7 +11150,7 @@ function normalizeActiveIndex2(value, count) {
8653
11150
  let n = Math.floor(Number(value));
8654
11151
  return !Number.isFinite(n) || n < 0 ? -1 : clamp11(n, 0, count - 1);
8655
11152
  }
8656
- var TLogLinksPanel = (0, import_vue20.defineComponent)({
11153
+ var TLogLinksPanel = (0, import_vue24.defineComponent)({
8657
11154
  name: "TLogLinksPanel",
8658
11155
  props: {
8659
11156
  x: { type: Number, required: !0 },
@@ -8689,7 +11186,7 @@ var TLogLinksPanel = (0, import_vue20.defineComponent)({
8689
11186
  },
8690
11187
  emits: ["select", "activate", "activeChange", "focus", "blur", "keydown"],
8691
11188
  setup(props, { emit }) {
8692
- let { terminal, scheduler, defaultStyle, events } = useTerminal(), parent = useLayout(), { visible, rootProps } = useVisibility(), parentEventZ = (0, import_vue20.inject)(EventZIndexContextKey, (0, import_vue20.computed)(() => 0)), eventZ = (0, import_vue20.computed)(() => (parentEventZ.value ?? 0) + (props.zIndex ?? 0)), focused = (0, import_vue20.ref)(!1), internalActiveIndex = (0, import_vue20.ref)(-1), fullRect = (0, import_vue20.computed)(
11189
+ let { terminal, scheduler, defaultStyle, events } = useTerminal(), parent = useLayout(), { visible, rootProps } = useVisibility(), parentEventZ = (0, import_vue24.inject)(EventZIndexContextKey, (0, import_vue24.computed)(() => 0)), eventZ = (0, import_vue24.computed)(() => (parentEventZ.value ?? 0) + (props.zIndex ?? 0)), focused = (0, import_vue24.ref)(!1), internalActiveIndex = (0, import_vue24.ref)(-1), fullRect = (0, import_vue24.computed)(
8693
11190
  () => translateRect(
8694
11191
  {
8695
11192
  x: normalizeInt8(props.x),
@@ -8700,13 +11197,13 @@ var TLogLinksPanel = (0, import_vue20.defineComponent)({
8700
11197
  parent.originX,
8701
11198
  parent.originY
8702
11199
  )
8703
- ), rect = (0, import_vue20.computed)(() => {
11200
+ ), rect = (0, import_vue24.computed)(() => {
8704
11201
  let translated = fullRect.value;
8705
11202
  return parent.clipRect ? intersectRect(translated, parent.clipRect) ?? EMPTY_RECT8 : translated;
8706
- }), lineNumberDigits = (0, import_vue20.computed)(
11203
+ }), lineNumberDigits = (0, import_vue24.computed)(
8707
11204
  () => props.showLineNumbers ? props.links.reduce((max, link) => Math.max(max, String(link.absoluteLineIndex).length), 1) : 0
8708
11205
  );
8709
- (0, import_vue20.watch)(
11206
+ (0, import_vue24.watch)(
8710
11207
  [() => props.activeIndex, () => props.links.length],
8711
11208
  () => {
8712
11209
  internalActiveIndex.value = normalizeActiveIndex2(props.activeIndex, props.links.length);
@@ -8846,12 +11343,12 @@ var TLogLinksPanel = (0, import_vue20.defineComponent)({
8846
11343
  }), item.text && segments.push({ text: item.text, style: rowStyle }), props.showHref && item.href && (item.text && segments.push({ text: " ", style: rowStyle }), segments.push({ text: item.href, style: hrefRowStyle })), segments.length || segments.push({ text: "", style: rowStyle }), writeSegments(y, rowStyle, segments);
8847
11344
  }
8848
11345
  }
8849
- })), () => (0, import_vue20.h)("span", rootProps);
11346
+ })), () => (0, import_vue24.h)("span", rootProps);
8850
11347
  }
8851
11348
  });
8852
11349
 
8853
11350
  // src/vue/components/TLogVirtualSearchResults.ts
8854
- var import_vue21 = require("vue");
11351
+ var import_vue25 = require("vue");
8855
11352
  function sliceByCells2(text, start, end) {
8856
11353
  let cells = 0, out = "";
8857
11354
  for (let ch of text) {
@@ -8867,7 +11364,7 @@ function formatItem(item, width, showLineNumbers) {
8867
11364
  let currentPrefix = item.current ? "*" : " ", linePrefix = showLineNumbers ? `${String(item.absoluteLineIndex).padStart(5, " ")} ` : "", before = sliceByCells2(item.text, 0, item.matchStartCell), match = sliceByCells2(item.text, item.matchStartCell, item.matchEndCell), after = sliceByCells2(item.text, item.matchEndCell, Number.MAX_SAFE_INTEGER);
8868
11365
  return `${currentPrefix}${linePrefix}${before}[${match}]${after}`.slice(0, Math.max(0, width));
8869
11366
  }
8870
- var TLogVirtualSearchResults = (0, import_vue21.defineComponent)({
11367
+ var TLogVirtualSearchResults = (0, import_vue25.defineComponent)({
8871
11368
  name: "TLogVirtualSearchResults",
8872
11369
  props: {
8873
11370
  x: { type: Number, required: !0 },
@@ -8892,7 +11389,7 @@ var TLogVirtualSearchResults = (0, import_vue21.defineComponent)({
8892
11389
  },
8893
11390
  emits: ["update:modelValue", "activeChange", "select", "focus", "blur", "keydown", "scroll"],
8894
11391
  setup(props, { emit }) {
8895
- let model = (0, import_vue21.computed)({
11392
+ let model = (0, import_vue25.computed)({
8896
11393
  get: () => props.modelValue,
8897
11394
  set: (value) => {
8898
11395
  emit("update:modelValue", value), emit("activeChange", {
@@ -8901,7 +11398,7 @@ var TLogVirtualSearchResults = (0, import_vue21.defineComponent)({
8901
11398
  });
8902
11399
  }
8903
11400
  });
8904
- return () => (0, import_vue21.h)(TVirtualList, {
11401
+ return () => (0, import_vue25.h)(TVirtualList, {
8905
11402
  x: props.x,
8906
11403
  y: props.y,
8907
11404
  w: props.w,
@@ -8939,14 +11436,14 @@ var TLogVirtualSearchResults = (0, import_vue21.defineComponent)({
8939
11436
  });
8940
11437
 
8941
11438
  // src/vue/components/TLogVirtualLinksPanel.ts
8942
- var import_vue22 = require("vue");
11439
+ var import_vue26 = require("vue");
8943
11440
  function formatItem2(item, width, showLineNumbers) {
8944
11441
  if (!item)
8945
11442
  return "";
8946
11443
  let currentPrefix = item.current ? "*" : " ", linePrefix = showLineNumbers ? `${String(item.absoluteLineIndex).padStart(5, " ")} ` : "";
8947
11444
  return `${currentPrefix}${linePrefix}${item.text} -> ${item.href}`.slice(0, Math.max(0, width));
8948
11445
  }
8949
- var TLogVirtualLinksPanel = (0, import_vue22.defineComponent)({
11446
+ var TLogVirtualLinksPanel = (0, import_vue26.defineComponent)({
8950
11447
  name: "TLogVirtualLinksPanel",
8951
11448
  props: {
8952
11449
  x: { type: Number, required: !0 },
@@ -8978,7 +11475,7 @@ var TLogVirtualLinksPanel = (0, import_vue22.defineComponent)({
8978
11475
  "scroll"
8979
11476
  ],
8980
11477
  setup(props, { emit }) {
8981
- let model = (0, import_vue22.computed)({
11478
+ let model = (0, import_vue26.computed)({
8982
11479
  get: () => props.modelValue,
8983
11480
  set: (value) => {
8984
11481
  emit("update:modelValue", value), emit("activeChange", {
@@ -8987,7 +11484,7 @@ var TLogVirtualLinksPanel = (0, import_vue22.defineComponent)({
8987
11484
  });
8988
11485
  }
8989
11486
  });
8990
- return () => (0, import_vue22.h)(TVirtualList, {
11487
+ return () => (0, import_vue26.h)(TVirtualList, {
8991
11488
  x: props.x,
8992
11489
  y: props.y,
8993
11490
  w: props.w,
@@ -9025,7 +11522,7 @@ var TLogVirtualLinksPanel = (0, import_vue22.defineComponent)({
9025
11522
  });
9026
11523
 
9027
11524
  // src/vue/log/append-only-log-store.ts
9028
- var import_vue23 = require("vue");
11525
+ var import_vue27 = require("vue");
9029
11526
  function normalizeMaxLines(value) {
9030
11527
  if (value == null)
9031
11528
  return null;
@@ -9033,7 +11530,7 @@ function normalizeMaxLines(value) {
9033
11530
  return Number.isFinite(n) ? Math.max(1, n) : null;
9034
11531
  }
9035
11532
  function createAppendOnlyLogStore(options) {
9036
- let lines = [], version = (0, import_vue23.ref)(0), maxLines = normalizeMaxLines(options?.maxLines), head = 0, firstLineIndex = 0, tail = "", tailVersion = 0, nextLineId = 0;
11533
+ let lines = [], version = (0, import_vue27.ref)(0), maxLines = normalizeMaxLines(options?.maxLines), head = 0, firstLineIndex = 0, tail = "", tailVersion = 0, nextLineId = 0;
9037
11534
  function bump() {
9038
11535
  version.value++;
9039
11536
  }
@@ -9107,7 +11604,7 @@ function createAppendOnlyLogStore(options) {
9107
11604
  }
9108
11605
 
9109
11606
  // src/vue/log/use-tlog-link-controller.ts
9110
- var import_vue24 = require("vue");
11607
+ var import_vue28 = require("vue");
9111
11608
 
9112
11609
  // src/vue/log/tlog-plugins.ts
9113
11610
  function escapeRegExp(value) {
@@ -9414,7 +11911,7 @@ function actionKey(value) {
9414
11911
  ]);
9415
11912
  }
9416
11913
  function useTLogLinkController(logView, options = {}) {
9417
- let visibleLinks = (0, import_vue24.ref)([]), activeIndex = (0, import_vue24.ref)(-1), suppressedActivateKey = null;
11914
+ let visibleLinks = (0, import_vue28.ref)([]), activeIndex = (0, import_vue28.ref)(-1), suppressedActivateKey = null;
9418
11915
  function emitAction(action) {
9419
11916
  options.onAction?.(action), dispatchTLogPluginLinkAction(options.plugins, action);
9420
11917
  }
@@ -9479,7 +11976,7 @@ function useTLogLinkController(logView, options = {}) {
9479
11976
  }
9480
11977
  emitAction(action), refresh();
9481
11978
  }
9482
- return (0, import_vue24.watch)(
11979
+ return (0, import_vue28.watch)(
9483
11980
  () => logView.value,
9484
11981
  () => {
9485
11982
  refresh();
@@ -9501,10 +11998,10 @@ function useTLogLinkController(logView, options = {}) {
9501
11998
  }
9502
11999
 
9503
12000
  // src/vue/log/use-tlog-search-controller.ts
9504
- var import_vue26 = require("vue");
12001
+ var import_vue30 = require("vue");
9505
12002
 
9506
12003
  // src/vue/log/use-tlog-search-results-page.ts
9507
- var import_vue25 = require("vue"), DEFAULT_PAGE_SIZE = 20;
12004
+ var import_vue29 = require("vue"), DEFAULT_PAGE_SIZE = 20;
9508
12005
  function clamp12(n, min, max) {
9509
12006
  return Math.max(min, Math.min(max, n));
9510
12007
  }
@@ -9536,7 +12033,7 @@ function createEmptyState(pageSize, status = "idle", error = null) {
9536
12033
  };
9537
12034
  }
9538
12035
  function useTLogSearchResultsPage(logView, options = {}) {
9539
- let pageSize = normalizePageSize(options.pageSize), includePreview = options.includePreview === !0, currentPage = (0, import_vue25.ref)(0), state = (0, import_vue25.ref)(createEmptyState(pageSize));
12036
+ let pageSize = normalizePageSize(options.pageSize), includePreview = options.includePreview === !0, currentPage = (0, import_vue29.ref)(0), state = (0, import_vue29.ref)(createEmptyState(pageSize));
9540
12037
  function clear(status = "idle", error = null) {
9541
12038
  currentPage.value = 0, state.value = createEmptyState(pageSize, status, error);
9542
12039
  }
@@ -9596,7 +12093,7 @@ function useTLogSearchResultsPage(logView, options = {}) {
9596
12093
  let normalizedMatchIndex = normalizeInt9(matchIndex, -1);
9597
12094
  return handle.selectSearchMatch(normalizedMatchIndex) ? (currentPage.value = Math.floor(normalizedMatchIndex / pageSize), refresh(), !0) : (refresh(), !1);
9598
12095
  }
9599
- return (0, import_vue25.watch)(
12096
+ return (0, import_vue29.watch)(
9600
12097
  () => logView.value,
9601
12098
  () => {
9602
12099
  currentPage.value = 0, refresh();
@@ -9633,7 +12130,7 @@ function sameSavedSearch(a, b) {
9633
12130
  return a.query === b.query && a.mode === b.mode && !!a.caseSensitive == !!b.caseSensitive && !!a.wholeWord == !!b.wholeWord && (a.regexFlags ?? "") === (b.regexFlags ?? "");
9634
12131
  }
9635
12132
  function useTLogSearchController(logView, options = {}) {
9636
- let query = (0, import_vue26.ref)(options.initialQuery ?? ""), mode = (0, import_vue26.ref)(options.initialMode === "regex" ? "regex" : "text"), caseSensitive = (0, import_vue26.ref)(options.initialCaseSensitive === !0), wholeWord = (0, import_vue26.ref)(options.initialWholeWord === !0), regexFlags = (0, import_vue26.ref)(options.initialRegexFlags ?? ""), searchState = (0, import_vue26.ref)(normalizeSearchState(query.value)), markers = (0, import_vue26.ref)([]), metrics2 = (0, import_vue26.ref)(null), searchHistory = (0, import_vue26.ref)([]), savedSearches = (0, import_vue26.ref)(options.initialSavedSearches ?? []), historyLimit = normalizeHistoryLimit(options.maxHistory), resultsPage = useTLogSearchResultsPage(logView, options), nextSavedSearchId = 0;
12133
+ let query = (0, import_vue30.ref)(options.initialQuery ?? ""), mode = (0, import_vue30.ref)(options.initialMode === "regex" ? "regex" : "text"), caseSensitive = (0, import_vue30.ref)(options.initialCaseSensitive === !0), wholeWord = (0, import_vue30.ref)(options.initialWholeWord === !0), regexFlags = (0, import_vue30.ref)(options.initialRegexFlags ?? ""), searchState = (0, import_vue30.ref)(normalizeSearchState(query.value)), markers = (0, import_vue30.ref)([]), metrics2 = (0, import_vue30.ref)(null), searchHistory = (0, import_vue30.ref)([]), savedSearches = (0, import_vue30.ref)(options.initialSavedSearches ?? []), historyLimit = normalizeHistoryLimit(options.maxHistory), resultsPage = useTLogSearchResultsPage(logView, options), nextSavedSearchId = 0;
9637
12134
  function nextSavedSearchIdValue() {
9638
12135
  let id = "";
9639
12136
  do
@@ -9641,7 +12138,7 @@ function useTLogSearchController(logView, options = {}) {
9641
12138
  while (savedSearches.value.some((entry) => entry.id === id));
9642
12139
  return id;
9643
12140
  }
9644
- let searchBarState = (0, import_vue26.computed)(() => ({
12141
+ let searchBarState = (0, import_vue30.computed)(() => ({
9645
12142
  query: query.value,
9646
12143
  mode: mode.value,
9647
12144
  caseSensitive: caseSensitive.value,
@@ -9746,7 +12243,7 @@ function useTLogSearchController(logView, options = {}) {
9746
12243
  regexFlags: entry.regexFlags || void 0
9747
12244
  }));
9748
12245
  }
9749
- return (0, import_vue26.watch)(
12246
+ return (0, import_vue30.watch)(
9750
12247
  () => logView.value,
9751
12248
  () => {
9752
12249
  refresh();
@@ -9783,13 +12280,13 @@ function useTLogSearchController(logView, options = {}) {
9783
12280
  }
9784
12281
 
9785
12282
  // src/vue/log/use-tlog-virtual-search-results.ts
9786
- var import_vue27 = require("vue");
12283
+ var import_vue31 = require("vue");
9787
12284
  function normalizeInt10(value, fallback = 0) {
9788
12285
  let n = Math.floor(Number(value));
9789
12286
  return Number.isFinite(n) ? n : fallback;
9790
12287
  }
9791
12288
  function useTLogVirtualSearchResults(logView, options = {}) {
9792
- let state = (0, import_vue27.ref)({
12289
+ let state = (0, import_vue31.ref)({
9793
12290
  itemCount: 0,
9794
12291
  itemVersion: 0,
9795
12292
  activeIndex: -1,
@@ -9848,7 +12345,7 @@ function useTLogVirtualSearchResults(logView, options = {}) {
9848
12345
  let selected = handle.selectSearchMatch(normalizeInt10(matchIndex, -1));
9849
12346
  return refresh(), selected;
9850
12347
  }
9851
- return (0, import_vue27.watch)(() => logView.value, refresh, { immediate: !0 }), {
12348
+ return (0, import_vue31.watch)(() => logView.value, refresh, { immediate: !0 }), {
9852
12349
  state,
9853
12350
  refresh,
9854
12351
  getItem,
@@ -9857,7 +12354,7 @@ function useTLogVirtualSearchResults(logView, options = {}) {
9857
12354
  }
9858
12355
 
9859
12356
  // src/vue/log/use-tlog-retained-index.ts
9860
- var import_vue28 = require("vue");
12357
+ var import_vue32 = require("vue");
9861
12358
  var DEFAULT_BUDGET_MS = 4, DEFAULT_MAX_ITEMS = 1e4;
9862
12359
  function clamp13(n, min, max) {
9863
12360
  return Math.max(min, Math.min(max, n));
@@ -9874,7 +12371,7 @@ function sanitizeIndexedExternalHref(value, options = {}) {
9874
12371
  return sanitizeTerminalHref(value, options);
9875
12372
  }
9876
12373
  function useTLogRetainedIndex(logView, source, version, options = {}) {
9877
- let status = (0, import_vue28.ref)("idle"), links = (0, import_vue28.ref)([]), diagnostics = (0, import_vue28.ref)([]), density = (0, import_vue28.ref)([]), plugins = (0, import_vue28.computed)(() => {
12374
+ let status = (0, import_vue32.ref)("idle"), links = (0, import_vue32.ref)([]), diagnostics = (0, import_vue32.ref)([]), density = (0, import_vue32.ref)([]), plugins = (0, import_vue32.computed)(() => {
9878
12375
  let builtins = [];
9879
12376
  return options.links && builtins.push(createTLogOsc8LinkPlugin()), options.urls && builtins.push(createTLogUrlPlugin({ allowFileUrls: options.allowFileUrls })), options.levels && builtins.push(createTLogLevelPlugin({ bucketCount: options.bucketCount })), [...builtins, ...options.plugins ?? []];
9880
12377
  }), generation = 0, cursor = 0, rafHandle = null, indexedLines = [];
@@ -10004,7 +12501,7 @@ function useTLogRetainedIndex(logView, source, version, options = {}) {
10004
12501
  function refresh() {
10005
12502
  cancel(), indexedLines = [], links.value = [], diagnostics.value = [], density.value = [], cursor = 0, status.value = "indexing", schedule();
10006
12503
  }
10007
- return (0, import_vue28.watch)([() => source.value, () => version.value, () => logView.value], refresh, {
12504
+ return (0, import_vue32.watch)([() => source.value, () => version.value, () => logView.value], refresh, {
10008
12505
  immediate: !0
10009
12506
  }), {
10010
12507
  status,
@@ -10017,7 +12514,7 @@ function useTLogRetainedIndex(logView, source, version, options = {}) {
10017
12514
  }
10018
12515
 
10019
12516
  // src/vue/log/tlog-session.ts
10020
- var import_vue29 = require("vue");
12517
+ var import_vue33 = require("vue");
10021
12518
  function clamp14(n, min, max) {
10022
12519
  return Math.max(min, Math.min(max, n));
10023
12520
  }
@@ -10035,7 +12532,7 @@ function deserializeTLogViewSessionState(value) {
10035
12532
  }
10036
12533
  }
10037
12534
  function createTLogViewSessionStore(options = {}) {
10038
- let storageKey = options.storageKey ?? "@simon_he/vue-tui:tlog-session", storage = options.storage ?? globalThis.localStorage ?? null, state = (0, import_vue29.ref)(null);
12535
+ let storageKey = options.storageKey ?? "@simon_he/vue-tui:tlog-session", storage = options.storage ?? globalThis.localStorage ?? null, state = (0, import_vue33.ref)(null);
10039
12536
  function load() {
10040
12537
  let next = deserializeTLogViewSessionState(storage?.getItem(storageKey));
10041
12538
  return state.value = next, next;