@simon_he/vue-tui 0.0.8 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (249) hide show
  1. package/README.md +142 -30
  2. package/dist/TSelect-BwJJbuTt.js +6089 -0
  3. package/dist/TTree-DK_DQBYm.js +6480 -0
  4. package/dist/agent.cjs +39416 -0
  5. package/dist/agent.d.cts +44 -0
  6. package/dist/agent.d.ts +44 -0
  7. package/dist/agent.js +828 -0
  8. package/dist/ansi-palette-CNXqFciC.js +57 -0
  9. package/dist/ansi-styles.d.ts +200 -0
  10. package/dist/block-source-CKUOnkgT.js +1663 -0
  11. package/dist/cli/headless-renderer.d.ts +29 -0
  12. package/dist/cli/input.d.ts +49 -0
  13. package/dist/cli/node-file-writers.d.ts +13 -0
  14. package/dist/cli/node-module.d.ts +2 -0
  15. package/dist/cli/parse-kitty.d.ts +2 -0
  16. package/dist/cli/parse-mouse.d.ts +2 -0
  17. package/dist/cli/parse-utils.d.ts +14 -0
  18. package/dist/cli/parse-xterm.d.ts +2 -0
  19. package/dist/cli/path-provider-types.d.ts +1 -0
  20. package/dist/cli/path-provider.d.ts +4 -0
  21. package/dist/cli/path-suggest-core.d.ts +1 -0
  22. package/dist/cli/path-suggest.d.ts +15 -0
  23. package/dist/cli/recording.d.ts +4 -0
  24. package/dist/cli/stdin-buffer.d.ts +33 -0
  25. package/dist/cli.cjs +11061 -0
  26. package/dist/cli.d.cts +23 -0
  27. package/dist/cli.d.ts +23 -0
  28. package/dist/cli.js +9875 -0
  29. package/dist/core/ansi/capability.d.ts +20 -0
  30. package/dist/core/ansi/colors.d.ts +41 -0
  31. package/dist/core/ansi/sgr.d.ts +7 -0
  32. package/dist/core/ansi/theme.d.ts +6 -0
  33. package/dist/core/ansi-palette.d.ts +14 -0
  34. package/dist/core/buffer/buffer.d.ts +54 -0
  35. package/dist/core/buffer/width.d.ts +4 -0
  36. package/dist/core/debug-logger.d.ts +18 -0
  37. package/dist/core/hyperlink.d.ts +9 -0
  38. package/dist/core/index.d.ts +4 -0
  39. package/dist/core/path-provider-types.d.ts +24 -0
  40. package/dist/core/path-suggest.d.ts +35 -0
  41. package/dist/core/render-plane.d.ts +3 -0
  42. package/dist/core/terminal/create-terminal.d.ts +8 -0
  43. package/dist/core/terminal/emitter.d.ts +7 -0
  44. package/dist/core/types.d.ts +107 -0
  45. package/dist/core.cjs +3153 -0
  46. package/dist/core.d.cts +14 -0
  47. package/dist/core.d.ts +14 -0
  48. package/dist/core.js +424 -0
  49. package/dist/create-terminal-C2oiWFJU.js +1434 -0
  50. package/dist/create-terminal-app.d.ts +36 -0
  51. package/dist/dom-renderer-BqGijQID.js +1173 -0
  52. package/dist/env-Cl8qmNFN.js +19 -0
  53. package/dist/events/index.d.ts +6 -0
  54. package/dist/events/manager/cli-event-manager.d.ts +22 -0
  55. package/dist/events/manager/event-manager.d.ts +30 -0
  56. package/dist/events/manager/selection-suppression.d.ts +3 -0
  57. package/dist/events/manager/types.d.ts +108 -0
  58. package/dist/events/recording.d.ts +44 -0
  59. package/dist/experimental.cjs +4412 -1641
  60. package/dist/experimental.d.cts +42 -0
  61. package/dist/experimental.d.ts +42 -825
  62. package/dist/experimental.js +31 -7392
  63. package/dist/frame-perf-C6Xfg85O.js +24 -0
  64. package/dist/hyperlink-Bn02UXJb.js +419 -0
  65. package/dist/index.cjs +14765 -17582
  66. package/dist/index.d.cts +35 -0
  67. package/dist/index.d.ts +35 -1528
  68. package/dist/index.js +17 -20026
  69. package/dist/linkify-D_gzn9Xq.js +562 -0
  70. package/dist/markdown.cjs +9321 -7623
  71. package/dist/markdown.d.cts +11 -0
  72. package/dist/markdown.d.ts +11 -112
  73. package/dist/markdown.js +36 -1427
  74. package/dist/observability/cli-latency-node.d.ts +3 -0
  75. package/dist/observability/cli-latency-types.d.ts +41 -0
  76. package/dist/observability/cli-latency.d.ts +3 -0
  77. package/dist/observability/frame-perf-store.d.ts +18 -0
  78. package/dist/observability/frame-perf.d.ts +40 -0
  79. package/dist/observability/perf-sink.d.ts +56 -0
  80. package/dist/observability/trace.d.ts +40 -0
  81. package/dist/observability/tui-profiler.d.ts +33 -0
  82. package/dist/observability.cjs +221 -0
  83. package/dist/observability.d.cts +8 -0
  84. package/dist/observability.d.ts +8 -0
  85. package/dist/observability.js +4 -0
  86. package/dist/path-mnSgEpCm.js +81 -0
  87. package/dist/path-suggest-BNqcuE3-.js +274 -0
  88. package/dist/path-suggest-Dk9TRLh5.js +3 -0
  89. package/dist/{path-suggest-DmrmeueH.js → path-suggest-bvR9SY6Q.js} +86 -18
  90. package/dist/renderer/capabilities.d.ts +13 -0
  91. package/dist/renderer/cli/index.d.ts +2 -0
  92. package/dist/renderer/cli/stdout-metrics.d.ts +18 -0
  93. package/dist/renderer/cli/stdout-renderer.d.ts +48 -0
  94. package/dist/renderer/dom/dom-renderer.d.ts +157 -0
  95. package/dist/renderer/dom/index.d.ts +2 -0
  96. package/dist/renderer/index.d.ts +2 -0
  97. package/dist/renderer-dom.cjs +1505 -0
  98. package/dist/renderer-dom.d.cts +4 -0
  99. package/dist/renderer-dom.d.ts +4 -0
  100. package/dist/renderer-dom.js +7 -0
  101. package/dist/runtime/index.d.ts +36 -0
  102. package/dist/runtime/osc52.d.ts +9 -0
  103. package/dist/runtime-rfcZCyJq.js +1197 -0
  104. package/dist/runtime.cjs +1698 -0
  105. package/dist/runtime.d.cts +9 -0
  106. package/dist/runtime.d.ts +9 -0
  107. package/dist/runtime.js +4 -0
  108. package/dist/selection/terminal-selection.d.ts +123 -0
  109. package/dist/sgr-BmzxEjAO.js +304 -0
  110. package/dist/terminal-selection-DBinO6p5.js +330 -0
  111. package/dist/tlog-theme-qPBt5rge.js +9254 -0
  112. package/dist/trace-CjzYeIxN.js +182 -0
  113. package/dist/utils/env.d.ts +3 -0
  114. package/dist/utils/grapheme.d.ts +5 -0
  115. package/dist/utils/newlines.d.ts +1 -0
  116. package/dist/utils/path.d.ts +7 -0
  117. package/dist/utils/url-safety.d.ts +2 -0
  118. package/dist/vue/agent/view-models.d.ts +98 -0
  119. package/dist/vue/components/TAnchor.d.ts +108 -0
  120. package/dist/vue/components/TBox.d.ts +144 -0
  121. package/dist/vue/components/TCommandPalette.d.ts +587 -0
  122. package/dist/vue/components/TDataTable.d.ts +367 -0
  123. package/dist/vue/components/TDebugOverlay.d.ts +43 -0
  124. package/dist/vue/components/TDialog.d.ts +255 -0
  125. package/dist/vue/components/TFeedback.d.ts +635 -0
  126. package/dist/vue/components/TFlow.d.ts +85 -0
  127. package/dist/vue/components/TForm.d.ts +1230 -0
  128. package/dist/vue/components/TInput.d.ts +545 -0
  129. package/dist/vue/components/TInputBox.d.ts +158 -0
  130. package/dist/vue/components/TJsonEditor.d.ts +165 -0
  131. package/dist/vue/components/TLink.d.ts +239 -0
  132. package/dist/vue/components/TLinkifyText.d.ts +141 -0
  133. package/dist/vue/components/TList.d.ts +119 -0
  134. package/dist/vue/components/TLogLinksPanel.d.ts +238 -0
  135. package/dist/vue/components/TLogMinimap.d.ts +263 -0
  136. package/dist/vue/components/TLogScrollbar.d.ts +236 -0
  137. package/dist/vue/components/TLogSearchBar.d.ts +267 -0
  138. package/dist/vue/components/TLogSearchPager.d.ts +162 -0
  139. package/dist/vue/components/TLogSearchResults.d.ts +200 -0
  140. package/dist/vue/components/TLogView.d.ts +536 -0
  141. package/dist/vue/components/TLogVirtualLinksPanel.d.ts +141 -0
  142. package/dist/vue/components/TLogVirtualSearchResults.d.ts +146 -0
  143. package/dist/vue/components/TMarkdownText.d.ts +134 -0
  144. package/dist/vue/components/TMultilineModal.d.ts +62 -0
  145. package/dist/vue/components/TNavigation.d.ts +324 -0
  146. package/dist/vue/components/TOverlay.d.ts +366 -0
  147. package/dist/vue/components/TPanels.d.ts +244 -0
  148. package/dist/vue/components/TPathPicker.d.ts +213 -0
  149. package/dist/vue/components/TRenderLayer.d.ts +16 -0
  150. package/dist/vue/components/TRenderPlane.d.ts +17 -0
  151. package/dist/vue/components/TSelect.d.ts +335 -0
  152. package/dist/vue/components/TTable.d.ts +317 -0
  153. package/dist/vue/components/TText.d.ts +116 -0
  154. package/dist/vue/components/TThinkingView.d.ts +233 -0
  155. package/dist/vue/components/TToolCallView.d.ts +384 -0
  156. package/dist/vue/components/TTranscriptView.d.ts +221 -0
  157. package/dist/vue/components/TTransition.d.ts +83 -0
  158. package/dist/vue/components/TTree.d.ts +200 -0
  159. package/dist/vue/components/TUserMessageView.d.ts +344 -0
  160. package/dist/vue/components/TView.d.ts +127 -0
  161. package/dist/vue/components/TVirtualList.d.ts +182 -0
  162. package/dist/vue/components/TVirtualMarkdown.d.ts +168 -0
  163. package/dist/vue/components/TVirtualRows.d.ts +247 -0
  164. package/dist/vue/components/TerminalProvider.d.ts +218 -0
  165. package/dist/vue/components/input/host.d.ts +17 -0
  166. package/dist/vue/components/input/plugins/hostPlugin.d.ts +7 -0
  167. package/dist/vue/components/input/plugins/hostPlugin.node.d.ts +15 -0
  168. package/dist/vue/components/input/plugins/mentionUtils.d.ts +17 -0
  169. package/dist/vue/components/input/plugins/nodeMentionPathProvider.d.ts +2 -0
  170. package/dist/vue/components/input/plugins/promptMentionPlugin.d.ts +8 -0
  171. package/dist/vue/components/input/plugins/promptMentionState.d.ts +98 -0
  172. package/dist/vue/components/input/plugins/restrictText.d.ts +27 -0
  173. package/dist/vue/components/input/plugins/types.d.ts +90 -0
  174. package/dist/vue/components/input/utils/inlineText.d.ts +57 -0
  175. package/dist/vue/components/input/utils/inlineTextTokens.d.ts +34 -0
  176. package/dist/vue/components/input/utils/primitives.d.ts +3 -0
  177. package/dist/vue/components/input/utils/wordNavigation.d.ts +6 -0
  178. package/dist/vue/components/link/host.d.ts +15 -0
  179. package/dist/vue/components/list/list-geometry.d.ts +16 -0
  180. package/dist/vue/components/list/list-paint.d.ts +1 -0
  181. package/dist/vue/components/list/scroll-state.d.ts +25 -0
  182. package/dist/vue/components/list/selection-state.d.ts +6 -0
  183. package/dist/vue/components/simple-utils.d.ts +5 -0
  184. package/dist/vue/components/terminal-provider/copy-toast.d.ts +6 -0
  185. package/dist/vue/components/terminal-provider/portals.d.ts +17 -0
  186. package/dist/vue/components/terminal-provider/scheduler.d.ts +29 -0
  187. package/dist/vue/components/terminal-provider/selection-config.d.ts +15 -0
  188. package/dist/vue/components/terminal-provider/utils.d.ts +5 -0
  189. package/dist/vue/composables/use-layout.d.ts +2 -0
  190. package/dist/vue/composables/use-render-node.d.ts +19 -0
  191. package/dist/vue/composables/use-render-stack.d.ts +3 -0
  192. package/dist/vue/composables/use-runtime.d.ts +5 -0
  193. package/dist/vue/composables/use-terminal-node.d.ts +14 -0
  194. package/dist/vue/composables/use-terminal.d.ts +2 -0
  195. package/dist/vue/composables/use-visibility.d.ts +12 -0
  196. package/dist/vue/context.d.ts +153 -0
  197. package/dist/vue/index.d.ts +69 -0
  198. package/dist/vue/injection-key.d.ts +2 -0
  199. package/dist/vue/linkify.d.ts +11 -0
  200. package/dist/vue/log/append-only-log-store.d.ts +2 -0
  201. package/dist/vue/log/tlog-keymap.d.ts +28 -0
  202. package/dist/vue/log/tlog-plugins.d.ts +144 -0
  203. package/dist/vue/log/tlog-session.d.ts +81 -0
  204. package/dist/vue/log/tlog-theme.d.ts +68 -0
  205. package/dist/vue/log/types.d.ts +43 -0
  206. package/dist/vue/log/use-tlog-link-controller.d.ts +31 -0
  207. package/dist/vue/log/use-tlog-retained-index.d.ts +26 -0
  208. package/dist/vue/log/use-tlog-search-controller.d.ts +51 -0
  209. package/dist/vue/log/use-tlog-search-results-page.d.ts +31 -0
  210. package/dist/vue/log/use-tlog-virtual-search-results.d.ts +22 -0
  211. package/dist/vue/markdown/ast.d.ts +3 -0
  212. package/dist/vue/markdown/block-source.d.ts +22 -0
  213. package/dist/vue/markdown/document.d.ts +20 -0
  214. package/dist/vue/markdown/layout.d.ts +21 -0
  215. package/dist/vue/markdown/parser.d.ts +11 -0
  216. package/dist/vue/markdown/render.d.ts +10 -0
  217. package/dist/vue/markdown/theme.d.ts +186 -0
  218. package/dist/vue/markdown/types.d.ts +59 -0
  219. package/dist/vue/overlay.d.ts +27 -0
  220. package/dist/vue/render/context.d.ts +3 -0
  221. package/dist/vue/render/render-manager.d.ts +94 -0
  222. package/dist/vue/router/RouterView.d.ts +25 -0
  223. package/dist/vue/router/composables.d.ts +4 -0
  224. package/dist/vue/router/context.d.ts +4 -0
  225. package/dist/vue/router/router.d.ts +7 -0
  226. package/dist/vue/router/types.d.ts +29 -0
  227. package/dist/vue/scheduler/frame-mailbox.d.ts +55 -0
  228. package/dist/vue/scheduler/frame-scheduler.d.ts +51 -0
  229. package/dist/vue/theme.d.ts +48 -0
  230. package/dist/vue/transcript/hit-regions.d.ts +2 -0
  231. package/dist/vue/transcript/layout.d.ts +20 -0
  232. package/dist/vue/transcript/plain-text.d.ts +2 -0
  233. package/dist/vue/transcript/types.d.ts +122 -0
  234. package/dist/vue/utils/frame-task.d.ts +6 -0
  235. package/dist/vue/utils/rect.d.ts +4 -0
  236. package/dist/vue/utils/row-scroll.d.ts +25 -0
  237. package/dist/vue/utils/style-cache.d.ts +3 -0
  238. package/dist/vue/utils/text.d.ts +27 -0
  239. package/dist/vue/utils/wheel-scroll.d.ts +18 -0
  240. package/dist/vue.cjs +23668 -0
  241. package/dist/vue.d.cts +1 -0
  242. package/dist/vue.d.ts +1 -0
  243. package/dist/vue.js +3957 -0
  244. package/dist/{wheel-scroll-CiNsasLf.js → wheel-scroll-vBRaQ7p-.js} +404 -405
  245. package/package.json +185 -35
  246. package/dist/path-suggest-BeV6n7m-.js +0 -3
  247. package/dist/sgr-Tko2EQ0U.js +0 -484
  248. package/dist/theme-Bsm65g8k.d.ts +0 -32
  249. package/dist/types-ClIV2h1o.d.ts +0 -103
@@ -0,0 +1,1698 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/runtime.ts
21
+ var runtime_exports = {};
22
+ __export(runtime_exports, {
23
+ createEventManager: () => createEventManager,
24
+ createRuntime: () => createRuntime,
25
+ createTerminalSelectionController: () => createTerminalSelectionController,
26
+ terminalSelectionRowSpans: () => terminalSelectionRowSpans,
27
+ terminalSelectionVisibleRowSpans: () => terminalSelectionVisibleRowSpans
28
+ });
29
+ module.exports = __toCommonJS(runtime_exports);
30
+
31
+ // src/events/manager/selection-suppression.ts
32
+ var SUPPRESS_TERMINAL_POINTER_UP = "__vueTuiSuppressTerminalPointerUp";
33
+ var SUPPRESS_TERMINAL_POINTER_DOWN = "__vueTuiSuppressTerminalPointerDown";
34
+ var SUPPRESS_TERMINAL_POINTER_MOVE = "__vueTuiSuppressTerminalPointerMove";
35
+
36
+ // src/events/manager/event-manager.ts
37
+ function contains(rect, x, y) {
38
+ return x >= rect.x && y >= rect.y && x < rect.x + rect.w && y < rect.y + rect.h;
39
+ }
40
+ function isVisible(node) {
41
+ return node.visible !== false;
42
+ }
43
+ function containsRect(outer, inner) {
44
+ return inner.x >= outer.x && inner.y >= outer.y && inner.x + inner.w <= outer.x + outer.w && inner.y + inner.h <= outer.y + outer.h;
45
+ }
46
+ function area(rect) {
47
+ return Math.max(0, rect.w) * Math.max(0, rect.h);
48
+ }
49
+ function sameRect(a, b) {
50
+ return a.x === b.x && a.y === b.y && a.w === b.w && a.h === b.h;
51
+ }
52
+ function now() {
53
+ return typeof performance !== "undefined" ? performance.now() : Date.now();
54
+ }
55
+ function rectRowRange(rect) {
56
+ const y0 = Math.floor(rect.y);
57
+ const y1 = Math.ceil(rect.y + rect.h) - 1;
58
+ if (!Number.isFinite(y0) || !Number.isFinite(y1))
59
+ return null;
60
+ if (y1 < y0)
61
+ return null;
62
+ return { y0, y1 };
63
+ }
64
+ var nextId = 0;
65
+ function createEventManager(container, metrics, options) {
66
+ let currentMetrics = metrics;
67
+ const nodes = /* @__PURE__ */ new Map();
68
+ const rowBuckets = /* @__PURE__ */ new Map();
69
+ const rowRangeById = /* @__PURE__ */ new Map();
70
+ let focusedId = null;
71
+ let capturedId = null;
72
+ let hoverPath = [];
73
+ let lastPointerMoveEvent = null;
74
+ const rawRecord = options?.record;
75
+ const recordStart = now();
76
+ const record = rawRecord ? (event) => {
77
+ rawRecord({ ...event, time: now() - recordStart });
78
+ } : void 0;
79
+ const onFocusChange = options?.onFocusChange;
80
+ const textInputTarget = options?.textInputTarget ?? null;
81
+ const MODAL_FOCUS_Z_THRESHOLD = 100;
82
+ const MODAL_ROOT_MIN_AREA = 40;
83
+ function focusLockTarget() {
84
+ let bestRoot = null;
85
+ let bestAny = null;
86
+ for (const n of nodes.values()) {
87
+ if (!n.focusable || !isVisible(n))
88
+ continue;
89
+ const z = n.zIndex ?? 0;
90
+ if (z < MODAL_FOCUS_Z_THRESHOLD)
91
+ continue;
92
+ const a = area(n.rect);
93
+ if (!bestAny || z > bestAny.zIndex || z === bestAny.zIndex && a > bestAny.area) {
94
+ bestAny = { id: n.id, zIndex: z, area: a };
95
+ }
96
+ if (a >= MODAL_ROOT_MIN_AREA && (!bestRoot || z > bestRoot.zIndex || z === bestRoot.zIndex && a > bestRoot.area)) {
97
+ bestRoot = { id: n.id, zIndex: z, area: a };
98
+ }
99
+ }
100
+ const best = bestRoot ?? bestAny;
101
+ return best ? { id: best.id, zIndex: best.zIndex } : null;
102
+ }
103
+ function resolveLockedFocusTarget(type) {
104
+ const lock = focusLockTarget();
105
+ let target = focusedId ? nodes.get(focusedId) ?? null : null;
106
+ const shouldRetarget = lock && (!target || !isVisible(target) || (target.zIndex ?? 0) < lock.zIndex);
107
+ if (!shouldRetarget || !lock)
108
+ return target;
109
+ let best = null;
110
+ let bestScore = -Infinity;
111
+ for (const node of nodes.values()) {
112
+ if (!node.focusable || !isVisible(node))
113
+ continue;
114
+ const z = node.zIndex ?? 0;
115
+ if (z < lock.zIndex)
116
+ continue;
117
+ const handlers = node.handlers ?? {};
118
+ const canHandle = type ? typeof handlers[type] === "function" : false;
119
+ const a = area(node.rect);
120
+ const score = z * 1e9 + (canHandle ? 1e6 : 0) - a;
121
+ if (score > bestScore) {
122
+ bestScore = score;
123
+ best = node;
124
+ }
125
+ }
126
+ if (best) {
127
+ setFocus(best.id);
128
+ target = best;
129
+ }
130
+ return target;
131
+ }
132
+ function resolveModalLockNode() {
133
+ const lock = focusLockTarget();
134
+ if (!lock)
135
+ return null;
136
+ const node = nodes.get(lock.id) ?? null;
137
+ return node && isVisible(node) ? node : null;
138
+ }
139
+ function isAllowedModalPointerNode(node, target, lockNode) {
140
+ const nodeZ = node.zIndex ?? 0;
141
+ const targetZ = target.zIndex ?? 0;
142
+ const lockZ = lockNode.zIndex ?? 0;
143
+ if (nodeZ >= lockZ)
144
+ return true;
145
+ return targetZ < lockZ && nodeZ >= targetZ && containsRect(node.rect, lockNode.rect);
146
+ }
147
+ const shouldDebugIme = () => Boolean(options?.debugIme) || Boolean(globalThis.__VT_DEBUG_IME__);
148
+ const imeLog = (msg, extra) => {
149
+ if (!shouldDebugIme())
150
+ return;
151
+ console.debug(`[vue-terminal][ime] ${msg}`, extra ?? {});
152
+ };
153
+ let domComposing = false;
154
+ const defaultUserSelect = container.style.userSelect || "text";
155
+ if (!container.hasAttribute("tabindex"))
156
+ container.tabIndex = 0;
157
+ if (!container.style.userSelect)
158
+ container.style.userSelect = defaultUserSelect;
159
+ let containerRect = null;
160
+ let containerRectDirty = true;
161
+ function markContainerRectDirty() {
162
+ containerRectDirty = true;
163
+ }
164
+ function getContainerRect() {
165
+ if (!containerRect || containerRectDirty) {
166
+ containerRect = container.getBoundingClientRect();
167
+ containerRectDirty = false;
168
+ }
169
+ return containerRect;
170
+ }
171
+ function removeFromRowBuckets(id) {
172
+ const prev = rowRangeById.get(id);
173
+ if (!prev)
174
+ return;
175
+ for (let y = prev.y0; y <= prev.y1; y++) {
176
+ const bucket = rowBuckets.get(y);
177
+ if (!bucket)
178
+ continue;
179
+ bucket.delete(id);
180
+ if (bucket.size === 0)
181
+ rowBuckets.delete(y);
182
+ }
183
+ rowRangeById.delete(id);
184
+ }
185
+ function addToRowBuckets(id, node) {
186
+ if (!isVisible(node))
187
+ return;
188
+ const range = rectRowRange(node.rect);
189
+ if (!range)
190
+ return;
191
+ rowRangeById.set(id, range);
192
+ for (let y = range.y0; y <= range.y1; y++) {
193
+ let bucket = rowBuckets.get(y);
194
+ if (!bucket) {
195
+ bucket = /* @__PURE__ */ new Set();
196
+ rowBuckets.set(y, bucket);
197
+ }
198
+ bucket.add(id);
199
+ }
200
+ }
201
+ function updateRowBuckets(id, node) {
202
+ if (!isVisible(node)) {
203
+ removeFromRowBuckets(id);
204
+ return;
205
+ }
206
+ const next = rectRowRange(node.rect);
207
+ const prev = rowRangeById.get(id);
208
+ if (!next) {
209
+ removeFromRowBuckets(id);
210
+ return;
211
+ }
212
+ if (prev && prev.y0 === next.y0 && prev.y1 === next.y1)
213
+ return;
214
+ removeFromRowBuckets(id);
215
+ rowRangeById.set(id, next);
216
+ for (let y = next.y0; y <= next.y1; y++) {
217
+ let bucket = rowBuckets.get(y);
218
+ if (!bucket) {
219
+ bucket = /* @__PURE__ */ new Set();
220
+ rowBuckets.set(y, bucket);
221
+ }
222
+ bucket.add(id);
223
+ }
224
+ }
225
+ function candidatesAt(cellX, cellY) {
226
+ const list = [];
227
+ const bucket = rowBuckets.get(cellY);
228
+ if (!bucket)
229
+ return list;
230
+ for (const id of bucket) {
231
+ const node = nodes.get(id);
232
+ if (!node)
233
+ continue;
234
+ if (!isVisible(node))
235
+ continue;
236
+ if (contains(node.rect, cellX, cellY))
237
+ list.push(node);
238
+ }
239
+ return list.sort((a, b) => area(b.rect) - area(a.rect) || a.zIndex - b.zIndex);
240
+ }
241
+ function pickTarget(list) {
242
+ if (list.length === 0)
243
+ return null;
244
+ let target = list[0];
245
+ for (const n of list) {
246
+ if (n.zIndex > target.zIndex)
247
+ target = n;
248
+ else if (n.zIndex === target.zIndex && area(n.rect) <= area(target.rect))
249
+ target = n;
250
+ }
251
+ return target;
252
+ }
253
+ function pathOuterToInner(list, target) {
254
+ if (!target)
255
+ return [];
256
+ const filtered = list.filter(
257
+ (n) => n.id !== target.id && (!n.focusable || !target.focusable || n.zIndex !== target.zIndex || !sameRect(n.rect, target.rect))
258
+ );
259
+ return [...filtered, target];
260
+ }
261
+ function ancestorsForTarget(target) {
262
+ const range = rectRowRange(target.rect);
263
+ const seedBucket = range ? rowBuckets.get(range.y0) : null;
264
+ if (!seedBucket) {
265
+ const list2 = [];
266
+ for (const node of nodes.values()) {
267
+ if (!isVisible(node))
268
+ continue;
269
+ if (containsRect(node.rect, target.rect))
270
+ list2.push(node);
271
+ }
272
+ const sorted2 = list2.sort((a, b) => a.zIndex - b.zIndex || area(b.rect) - area(a.rect));
273
+ return pathOuterToInner(sorted2, target);
274
+ }
275
+ const list = [];
276
+ for (const id of seedBucket) {
277
+ const node = nodes.get(id);
278
+ if (!node)
279
+ continue;
280
+ if (!isVisible(node))
281
+ continue;
282
+ if (containsRect(node.rect, target.rect))
283
+ list.push(node);
284
+ }
285
+ const sorted = list.sort((a, b) => a.zIndex - b.zIndex || area(b.rect) - area(a.rect));
286
+ return pathOuterToInner(sorted, target);
287
+ }
288
+ function makeBaseEvent(type, path, nativeEvent) {
289
+ const e = {
290
+ type,
291
+ target: null,
292
+ currentTarget: null,
293
+ eventPhase: 2,
294
+ bubbles: true,
295
+ cancelable: true,
296
+ defaultPrevented: Boolean(nativeEvent?.defaultPrevented),
297
+ timeStamp: now(),
298
+ __stopped: false,
299
+ stopPropagation() {
300
+ this.__stopped = true;
301
+ },
302
+ preventDefault() {
303
+ this.defaultPrevented = true;
304
+ nativeEvent?.preventDefault?.();
305
+ },
306
+ composedPath() {
307
+ return [...path].reverse();
308
+ },
309
+ nativeEvent
310
+ };
311
+ return e;
312
+ }
313
+ function dispatchToNode(handlerKey, node, event) {
314
+ event.currentTarget = node;
315
+ if (!node)
316
+ return;
317
+ const handler = node.handlers[handlerKey];
318
+ handler?.(event);
319
+ }
320
+ function dispatchWithPhases(type, path, target, event) {
321
+ event.target = target;
322
+ const captureKey = `${type}Capture`;
323
+ event.eventPhase = 1;
324
+ for (const node of path) {
325
+ dispatchToNode(captureKey, node, event);
326
+ if (event.__stopped)
327
+ return;
328
+ }
329
+ if (target) {
330
+ event.eventPhase = 2;
331
+ dispatchToNode(type, target, event);
332
+ if (event.__stopped)
333
+ return;
334
+ }
335
+ if (!event.bubbles)
336
+ return;
337
+ event.eventPhase = 3;
338
+ for (let i = path.length - 2; i >= 0; i--) {
339
+ dispatchToNode(type, path[i], event);
340
+ if (event.__stopped)
341
+ return;
342
+ }
343
+ }
344
+ function sharedPrefixLenById(a, b) {
345
+ const min = Math.min(a.length, b.length);
346
+ let i = 0;
347
+ for (; i < min; i++) {
348
+ if (a[i].id !== b[i].id)
349
+ break;
350
+ }
351
+ return i;
352
+ }
353
+ function updateHover(nextTarget, native) {
354
+ const nextPath = nextTarget ? ancestorsForTarget(nextTarget) : [];
355
+ const shared = sharedPrefixLenById(hoverPath, nextPath);
356
+ for (let i = hoverPath.length - 1; i >= shared; i--) {
357
+ const target = hoverPath[i] ?? null;
358
+ if (!target)
359
+ continue;
360
+ const path = hoverPath.slice(0, i + 1);
361
+ const ev = buildPointerEvent("pointerleave", path, native);
362
+ ev.bubbles = false;
363
+ dispatchWithPhases("pointerleave", path, target, ev);
364
+ }
365
+ for (let i = shared; i < nextPath.length; i++) {
366
+ const target = nextPath[i] ?? null;
367
+ if (!target)
368
+ continue;
369
+ const path = nextPath.slice(0, i + 1);
370
+ const ev = buildPointerEvent("pointerenter", path, native);
371
+ ev.bubbles = false;
372
+ dispatchWithPhases("pointerenter", path, target, ev);
373
+ }
374
+ hoverPath = nextPath;
375
+ }
376
+ function setFocus(nextId2) {
377
+ const lock = focusLockTarget();
378
+ if (lock) {
379
+ if (!nextId2) {
380
+ nextId2 = lock.id;
381
+ } else {
382
+ const want = nodes.get(nextId2) ?? null;
383
+ const wantZ = want?.zIndex ?? 0;
384
+ if (want && isVisible(want) && wantZ < lock.zIndex) {
385
+ return;
386
+ }
387
+ }
388
+ }
389
+ if (focusedId === nextId2)
390
+ return;
391
+ const prev = focusedId ? nodes.get(focusedId) ?? null : null;
392
+ const nextRaw = nextId2 ? nodes.get(nextId2) ?? null : null;
393
+ const next = nextRaw && isVisible(nextRaw) ? nextRaw : null;
394
+ focusedId = next?.id ?? null;
395
+ onFocusChange?.(prev?.id ?? null, focusedId);
396
+ if (prev) {
397
+ const path = ancestorsForTarget(prev);
398
+ const ev = makeBaseEvent("blur", path);
399
+ dispatchWithPhases("blur", path, prev, ev);
400
+ }
401
+ if (next) {
402
+ const path = ancestorsForTarget(next);
403
+ const ev = makeBaseEvent("focus", path);
404
+ dispatchWithPhases("focus", path, next, ev);
405
+ }
406
+ }
407
+ function toCell(clientX, clientY) {
408
+ const rect = getContainerRect();
409
+ const x = clientX - rect.left;
410
+ const y = clientY - rect.top;
411
+ return {
412
+ cellX: Math.max(0, Math.floor(x / currentMetrics.cellWidth)),
413
+ cellY: Math.max(0, Math.floor(y / currentMetrics.cellHeight))
414
+ };
415
+ }
416
+ function buildPointerEvent(type, path, native) {
417
+ const base = makeBaseEvent(type, path, native);
418
+ const { cellX, cellY } = toCell(native.clientX, native.clientY);
419
+ return Object.assign(base, {
420
+ clientX: native.clientX,
421
+ clientY: native.clientY,
422
+ cellX,
423
+ cellY,
424
+ button: "button" in native ? native.button : void 0,
425
+ buttons: "buttons" in native ? native.buttons : void 0,
426
+ ctrlKey: native.ctrlKey,
427
+ shiftKey: native.shiftKey,
428
+ altKey: native.altKey,
429
+ metaKey: native.metaKey,
430
+ deltaY: "deltaY" in native ? native.deltaY : void 0,
431
+ deltaMode: "deltaMode" in native ? native.deltaMode : void 0
432
+ });
433
+ }
434
+ function keyCombo(native) {
435
+ let out = "";
436
+ if (native.metaKey)
437
+ out += "Meta+";
438
+ if (native.ctrlKey)
439
+ out += "Ctrl+";
440
+ if (native.altKey)
441
+ out += "Alt+";
442
+ if (native.shiftKey)
443
+ out += "Shift+";
444
+ out += native.key;
445
+ return out;
446
+ }
447
+ function buildKeyboardEvent(type, path, native) {
448
+ const base = makeBaseEvent(type, path, native);
449
+ return Object.assign(base, {
450
+ key: native.key,
451
+ code: native.code,
452
+ combo: keyCombo(native),
453
+ ctrlKey: native.ctrlKey,
454
+ shiftKey: native.shiftKey,
455
+ altKey: native.altKey,
456
+ metaKey: native.metaKey,
457
+ repeat: native.repeat
458
+ });
459
+ }
460
+ function dispatchPointer(type, native, targetOverride) {
461
+ const { cellX, cellY } = toCell(native.clientX, native.clientY);
462
+ const list = candidatesAt(cellX, cellY);
463
+ const target = targetOverride ?? pickTarget(list);
464
+ const lockNode = resolveModalLockNode();
465
+ if (lockNode && target && !isAllowedModalPointerNode(target, target, lockNode))
466
+ return;
467
+ let path = target ? ancestorsForTarget(target) : [];
468
+ if (lockNode && target && path.length > 0) {
469
+ path = path.filter((n) => isAllowedModalPointerNode(n, target, lockNode));
470
+ }
471
+ const ev = buildPointerEvent(type, path, native);
472
+ dispatchWithPhases(type, path, target, ev);
473
+ }
474
+ function dispatchToFocused(type, native) {
475
+ const target = resolveLockedFocusTarget(type);
476
+ const path = target ? ancestorsForTarget(target) : [];
477
+ const ev = buildKeyboardEvent(type, path, native);
478
+ dispatchWithPhases(type, path, target, ev);
479
+ if (ev.defaultPrevented)
480
+ native.preventDefault();
481
+ }
482
+ function buildInputEvent(type, path, native) {
483
+ const base = makeBaseEvent(type, path, native);
484
+ const anyNative = native;
485
+ const data = typeof anyNative.data === "string" ? anyNative.data : void 0;
486
+ const inputType = typeof anyNative.inputType === "string" ? anyNative.inputType : void 0;
487
+ const isComposing = Boolean(anyNative.isComposing);
488
+ let text;
489
+ if (type === "paste") {
490
+ const clipboard = anyNative.clipboardData;
491
+ if (clipboard?.getData) {
492
+ text = clipboard.getData("text/plain") || clipboard.getData("text") || "";
493
+ }
494
+ }
495
+ return Object.assign(base, { data, inputType, isComposing, text });
496
+ }
497
+ function dispatchToFocusedText(type, native) {
498
+ const target = resolveLockedFocusTarget(type);
499
+ const path = target ? ancestorsForTarget(target) : [];
500
+ const ev = buildInputEvent(type, path, native);
501
+ dispatchWithPhases(type, path, target, ev);
502
+ if (ev.defaultPrevented)
503
+ native.preventDefault?.();
504
+ }
505
+ function onPointerDown(e) {
506
+ if (e[SUPPRESS_TERMINAL_POINTER_DOWN]) {
507
+ if (textInputTarget && !container.contains(textInputTarget)) {
508
+ try {
509
+ textInputTarget.focus?.({ preventScroll: true });
510
+ } catch {
511
+ textInputTarget.focus?.();
512
+ }
513
+ } else {
514
+ try {
515
+ container.focus?.({ preventScroll: true });
516
+ } catch {
517
+ container.focus?.();
518
+ }
519
+ }
520
+ const { cellX: cellX2, cellY: cellY2 } = toCell(e.clientX, e.clientY);
521
+ const list2 = candidatesAt(cellX2, cellY2);
522
+ const target2 = pickTarget(list2);
523
+ if (target2?.focusable) {
524
+ setFocus(target2.id);
525
+ }
526
+ capturedId = target2?.id ?? null;
527
+ updateHover(target2, e);
528
+ record?.({
529
+ type: "pointerdown",
530
+ cellX: cellX2,
531
+ cellY: cellY2,
532
+ clientX: e.clientX,
533
+ clientY: e.clientY,
534
+ button: e.button,
535
+ buttons: e.buttons,
536
+ ctrlKey: e.ctrlKey,
537
+ shiftKey: e.shiftKey,
538
+ altKey: e.altKey,
539
+ metaKey: e.metaKey
540
+ });
541
+ return;
542
+ }
543
+ if (textInputTarget && !container.contains(textInputTarget)) {
544
+ try {
545
+ textInputTarget.focus?.({ preventScroll: true });
546
+ } catch {
547
+ textInputTarget.focus?.();
548
+ }
549
+ if (shouldDebugIme()) {
550
+ const active = typeof document !== "undefined" ? document.activeElement?.tagName ?? null : null;
551
+ imeLog("pointerdown focus textInputTarget", { active });
552
+ }
553
+ } else {
554
+ try {
555
+ container.focus?.({ preventScroll: true });
556
+ } catch {
557
+ container.focus?.();
558
+ }
559
+ }
560
+ const { cellX, cellY } = toCell(e.clientX, e.clientY);
561
+ const list = candidatesAt(cellX, cellY);
562
+ const target = pickTarget(list);
563
+ const lockNode = resolveModalLockNode();
564
+ if (lockNode && target && !isAllowedModalPointerNode(target, target, lockNode))
565
+ return;
566
+ let path = target ? ancestorsForTarget(target) : [];
567
+ if (lockNode && target && path.length > 0) {
568
+ path = path.filter((n) => isAllowedModalPointerNode(n, target, lockNode));
569
+ }
570
+ const allowSelection = target ? target.selectable ?? !target.focusable : true;
571
+ container.style.userSelect = allowSelection ? defaultUserSelect : "none";
572
+ if (target) {
573
+ if (target.focusable) {
574
+ setFocus(target.id);
575
+ } else {
576
+ for (let i = path.length - 2; i >= 0; i--) {
577
+ const n = path[i];
578
+ if (n?.focusable) {
579
+ setFocus(n.id);
580
+ break;
581
+ }
582
+ }
583
+ }
584
+ }
585
+ capturedId = target?.id ?? null;
586
+ updateHover(target, e);
587
+ record?.({
588
+ type: "pointerdown",
589
+ cellX,
590
+ cellY,
591
+ clientX: e.clientX,
592
+ clientY: e.clientY,
593
+ button: e.button,
594
+ buttons: e.buttons,
595
+ ctrlKey: e.ctrlKey,
596
+ shiftKey: e.shiftKey,
597
+ altKey: e.altKey,
598
+ metaKey: e.metaKey
599
+ });
600
+ const ev = buildPointerEvent("pointerdown", path, e);
601
+ dispatchWithPhases("pointerdown", path, target, ev);
602
+ }
603
+ function onMouseDown(e) {
604
+ onPointerDown(e);
605
+ }
606
+ function onMouseMove(e) {
607
+ lastPointerMoveEvent = e;
608
+ onPointerMove(e);
609
+ }
610
+ function onMouseUp(e) {
611
+ onPointerUp(e);
612
+ }
613
+ function onMouseLeave(e) {
614
+ const native = lastPointerMoveEvent ?? e;
615
+ updateHover(null, native);
616
+ }
617
+ function onPointerMove(e) {
618
+ if (e[SUPPRESS_TERMINAL_POINTER_MOVE]) {
619
+ return;
620
+ }
621
+ lastPointerMoveEvent = e;
622
+ const { cellX, cellY } = toCell(e.clientX, e.clientY);
623
+ record?.({
624
+ type: "pointermove",
625
+ cellX,
626
+ cellY,
627
+ clientX: e.clientX,
628
+ clientY: e.clientY,
629
+ button: e.button,
630
+ buttons: e.buttons,
631
+ ctrlKey: e.ctrlKey,
632
+ shiftKey: e.shiftKey,
633
+ altKey: e.altKey,
634
+ metaKey: e.metaKey
635
+ });
636
+ if (capturedId) {
637
+ const target2 = nodes.get(capturedId) ?? null;
638
+ if (!target2)
639
+ return;
640
+ updateHover(target2, e);
641
+ const path = ancestorsForTarget(target2);
642
+ const ev = buildPointerEvent("pointermove", path, e);
643
+ dispatchWithPhases("pointermove", path, target2, ev);
644
+ return;
645
+ }
646
+ const list = candidatesAt(cellX, cellY);
647
+ const target = pickTarget(list);
648
+ updateHover(target, e);
649
+ dispatchPointer("pointermove", e, target);
650
+ }
651
+ function onPointerUp(e) {
652
+ const { cellX, cellY } = toCell(e.clientX, e.clientY);
653
+ record?.({
654
+ type: "pointerup",
655
+ cellX,
656
+ cellY,
657
+ clientX: e.clientX,
658
+ clientY: e.clientY,
659
+ button: e.button,
660
+ buttons: e.buttons,
661
+ ctrlKey: e.ctrlKey,
662
+ shiftKey: e.shiftKey,
663
+ altKey: e.altKey,
664
+ metaKey: e.metaKey
665
+ });
666
+ if (e[SUPPRESS_TERMINAL_POINTER_UP]) {
667
+ capturedId = null;
668
+ container.style.userSelect = defaultUserSelect;
669
+ return;
670
+ }
671
+ if (capturedId) {
672
+ const target = nodes.get(capturedId) ?? null;
673
+ const path = target ? ancestorsForTarget(target) : [];
674
+ const ev = buildPointerEvent("pointerup", path, e);
675
+ dispatchWithPhases("pointerup", path, target, ev);
676
+ } else {
677
+ dispatchPointer("pointerup", e);
678
+ }
679
+ capturedId = null;
680
+ container.style.userSelect = defaultUserSelect;
681
+ }
682
+ function onClick(e) {
683
+ const { cellX, cellY } = toCell(e.clientX, e.clientY);
684
+ record?.({
685
+ type: "click",
686
+ cellX,
687
+ cellY,
688
+ clientX: e.clientX,
689
+ clientY: e.clientY,
690
+ button: e.button,
691
+ buttons: e.buttons,
692
+ ctrlKey: e.ctrlKey,
693
+ shiftKey: e.shiftKey,
694
+ altKey: e.altKey,
695
+ metaKey: e.metaKey
696
+ });
697
+ dispatchPointer("click", e);
698
+ }
699
+ function onDblClick(e) {
700
+ const { cellX, cellY } = toCell(e.clientX, e.clientY);
701
+ record?.({
702
+ type: "dblclick",
703
+ cellX,
704
+ cellY,
705
+ clientX: e.clientX,
706
+ clientY: e.clientY,
707
+ button: e.button,
708
+ buttons: e.buttons,
709
+ ctrlKey: e.ctrlKey,
710
+ shiftKey: e.shiftKey,
711
+ altKey: e.altKey,
712
+ metaKey: e.metaKey
713
+ });
714
+ dispatchPointer("dblclick", e);
715
+ }
716
+ function onContextMenu(e) {
717
+ const { cellX, cellY } = toCell(e.clientX, e.clientY);
718
+ record?.({
719
+ type: "contextmenu",
720
+ cellX,
721
+ cellY,
722
+ clientX: e.clientX,
723
+ clientY: e.clientY,
724
+ button: e.button,
725
+ buttons: e.buttons,
726
+ ctrlKey: e.ctrlKey,
727
+ shiftKey: e.shiftKey,
728
+ altKey: e.altKey,
729
+ metaKey: e.metaKey
730
+ });
731
+ const list = candidatesAt(cellX, cellY);
732
+ const target = pickTarget(list);
733
+ const path = target ? ancestorsForTarget(target) : [];
734
+ const ev = buildPointerEvent("contextmenu", path, e);
735
+ dispatchWithPhases("contextmenu", path, target, ev);
736
+ if (ev.defaultPrevented)
737
+ e.preventDefault();
738
+ }
739
+ function onWheel(e) {
740
+ const { cellX, cellY } = toCell(e.clientX, e.clientY);
741
+ const list = candidatesAt(cellX, cellY);
742
+ if (list.length > 0)
743
+ e.preventDefault();
744
+ record?.({
745
+ type: "wheel",
746
+ cellX,
747
+ cellY,
748
+ clientX: e.clientX,
749
+ clientY: e.clientY,
750
+ deltaY: e.deltaY,
751
+ ctrlKey: e.ctrlKey,
752
+ shiftKey: e.shiftKey,
753
+ altKey: e.altKey,
754
+ metaKey: e.metaKey,
755
+ deltaMode: e.deltaMode
756
+ });
757
+ dispatchPointer("wheel", e);
758
+ }
759
+ function onKeyDown(e) {
760
+ const targetIsTextInput = Boolean(
761
+ textInputTarget && (e.target === textInputTarget || e.target instanceof Node && textInputTarget.contains(e.target))
762
+ );
763
+ if (targetIsTextInput) {
764
+ const anyNative = e;
765
+ const isComposing = Boolean(anyNative.isComposing);
766
+ const keyCode = typeof anyNative.keyCode === "number" ? anyNative.keyCode : void 0;
767
+ const key = e.key;
768
+ const isImeKey = domComposing || isComposing || key === "Process" || key === "Unidentified" || keyCode === 229;
769
+ if (isImeKey) {
770
+ imeLog("keydown ignored (ime composing)", {
771
+ key,
772
+ code: e.code,
773
+ keyCode,
774
+ isComposing,
775
+ domComposing,
776
+ focusedId
777
+ });
778
+ return;
779
+ }
780
+ const isPlainTextKey = key.length === 1 && !e.ctrlKey && !e.metaKey && !e.altKey;
781
+ if (isPlainTextKey) {
782
+ imeLog("keydown ignored (textInput)", {
783
+ key,
784
+ code: e.code,
785
+ keyCode,
786
+ isComposing,
787
+ domComposing,
788
+ focusedId
789
+ });
790
+ return;
791
+ }
792
+ }
793
+ record?.({
794
+ type: "keydown",
795
+ key: e.key,
796
+ code: e.code,
797
+ ctrlKey: e.ctrlKey,
798
+ shiftKey: e.shiftKey,
799
+ altKey: e.altKey,
800
+ metaKey: e.metaKey,
801
+ repeat: e.repeat
802
+ });
803
+ dispatchToFocused("keydown", e);
804
+ }
805
+ function onKeyUp(e) {
806
+ const targetIsTextInput = Boolean(
807
+ textInputTarget && (e.target === textInputTarget || e.target instanceof Node && textInputTarget.contains(e.target))
808
+ );
809
+ if (targetIsTextInput) {
810
+ const anyNative = e;
811
+ const isComposing = Boolean(anyNative.isComposing);
812
+ const keyCode = typeof anyNative.keyCode === "number" ? anyNative.keyCode : void 0;
813
+ const key = e.key;
814
+ const isImeKey = domComposing || isComposing || key === "Process" || key === "Unidentified" || keyCode === 229;
815
+ if (isImeKey) {
816
+ imeLog("keyup ignored (ime composing)", {
817
+ key,
818
+ code: e.code,
819
+ keyCode,
820
+ isComposing,
821
+ domComposing,
822
+ focusedId
823
+ });
824
+ return;
825
+ }
826
+ const isPlainTextKey = key.length === 1 && !e.ctrlKey && !e.metaKey && !e.altKey;
827
+ if (isPlainTextKey) {
828
+ imeLog("keyup ignored (textInput)", {
829
+ key,
830
+ code: e.code,
831
+ keyCode,
832
+ isComposing,
833
+ domComposing,
834
+ focusedId
835
+ });
836
+ return;
837
+ }
838
+ }
839
+ record?.({
840
+ type: "keyup",
841
+ key: e.key,
842
+ code: e.code,
843
+ ctrlKey: e.ctrlKey,
844
+ shiftKey: e.shiftKey,
845
+ altKey: e.altKey,
846
+ metaKey: e.metaKey,
847
+ repeat: e.repeat
848
+ });
849
+ dispatchToFocused("keyup", e);
850
+ }
851
+ function onBeforeInput(e) {
852
+ const anyNative = e;
853
+ if (anyNative && typeof anyNative.isComposing === "boolean")
854
+ domComposing = anyNative.isComposing;
855
+ const targetIsTextInput = Boolean(
856
+ textInputTarget && (e.target === textInputTarget || e.target instanceof Node && textInputTarget.contains(e.target))
857
+ );
858
+ const data = typeof anyNative.data === "string" ? anyNative.data : void 0;
859
+ const inputType = typeof anyNative.inputType === "string" ? anyNative.inputType : void 0;
860
+ const isPasteLike = inputType === "insertFromPaste" || inputType === "insertFromDrop";
861
+ if (targetIsTextInput && isPasteLike) {
862
+ anyNative?.preventDefault?.();
863
+ e?.preventDefault?.();
864
+ return;
865
+ }
866
+ const isLineBreakLike = inputType === "insertLineBreak" || inputType === "insertParagraph" || data?.includes("\n") && !isPasteLike;
867
+ if (targetIsTextInput && isLineBreakLike) {
868
+ anyNative?.preventDefault?.();
869
+ e?.preventDefault?.();
870
+ return;
871
+ }
872
+ record?.({
873
+ type: "beforeinput",
874
+ data,
875
+ inputType,
876
+ isComposing: Boolean(anyNative.isComposing)
877
+ });
878
+ dispatchToFocusedText("beforeinput", e);
879
+ }
880
+ function onInput(e) {
881
+ const anyNative = e;
882
+ if (anyNative && typeof anyNative.isComposing === "boolean")
883
+ domComposing = anyNative.isComposing;
884
+ const targetIsTextInput = Boolean(
885
+ textInputTarget && (e.target === textInputTarget || e.target instanceof Node && textInputTarget.contains(e.target))
886
+ );
887
+ const data = typeof anyNative.data === "string" ? anyNative.data : void 0;
888
+ const inputType = typeof anyNative.inputType === "string" ? anyNative.inputType : void 0;
889
+ const isPasteLike = inputType === "insertFromPaste" || inputType === "insertFromDrop";
890
+ if (targetIsTextInput && isPasteLike) {
891
+ anyNative?.preventDefault?.();
892
+ e?.preventDefault?.();
893
+ return;
894
+ }
895
+ const isLineBreakLike = inputType === "insertLineBreak" || inputType === "insertParagraph" || data?.includes("\n") && !isPasteLike;
896
+ if (targetIsTextInput && isLineBreakLike) {
897
+ anyNative?.preventDefault?.();
898
+ e?.preventDefault?.();
899
+ return;
900
+ }
901
+ record?.({
902
+ type: "input",
903
+ data,
904
+ inputType,
905
+ isComposing: Boolean(anyNative.isComposing)
906
+ });
907
+ dispatchToFocusedText("input", e);
908
+ }
909
+ function onCompositionStart(e) {
910
+ const anyNative = e;
911
+ domComposing = true;
912
+ record?.({
913
+ type: "compositionstart",
914
+ data: typeof anyNative.data === "string" ? anyNative.data : void 0,
915
+ isComposing: Boolean(anyNative.isComposing)
916
+ });
917
+ imeLog("compositionstart", {
918
+ data: typeof anyNative.data === "string" ? anyNative.data : void 0,
919
+ isComposing: Boolean(anyNative.isComposing),
920
+ focusedId
921
+ });
922
+ dispatchToFocusedText("compositionstart", e);
923
+ }
924
+ function onCompositionUpdate(e) {
925
+ const anyNative = e;
926
+ record?.({
927
+ type: "compositionupdate",
928
+ data: typeof anyNative.data === "string" ? anyNative.data : void 0,
929
+ isComposing: Boolean(anyNative.isComposing)
930
+ });
931
+ imeLog("compositionupdate", {
932
+ data: typeof anyNative.data === "string" ? anyNative.data : void 0,
933
+ isComposing: Boolean(anyNative.isComposing),
934
+ focusedId
935
+ });
936
+ dispatchToFocusedText("compositionupdate", e);
937
+ }
938
+ function onCompositionEnd(e) {
939
+ const anyNative = e;
940
+ domComposing = false;
941
+ record?.({
942
+ type: "compositionend",
943
+ data: typeof anyNative.data === "string" ? anyNative.data : void 0,
944
+ isComposing: Boolean(anyNative.isComposing)
945
+ });
946
+ imeLog("compositionend", {
947
+ data: typeof anyNative.data === "string" ? anyNative.data : void 0,
948
+ isComposing: Boolean(anyNative.isComposing),
949
+ focusedId
950
+ });
951
+ dispatchToFocusedText("compositionend", e);
952
+ }
953
+ function onDragOver(e) {
954
+ e.preventDefault();
955
+ }
956
+ function onDrop(e) {
957
+ e.preventDefault();
958
+ let text = "";
959
+ if (e.dataTransfer) {
960
+ if (e.dataTransfer.files && e.dataTransfer.files.length > 0) {
961
+ const files = Array.from(e.dataTransfer.files);
962
+ const paths = files.map((file) => String(file?.path || file?.name || "").trim()).filter(Boolean);
963
+ text = paths.join("\n");
964
+ } else if (e.dataTransfer.types.includes("text/plain")) {
965
+ text = e.dataTransfer.getData("text/plain");
966
+ }
967
+ }
968
+ if (text) {
969
+ record?.({
970
+ type: "paste",
971
+ text
972
+ });
973
+ if (textInputTarget) {
974
+ try {
975
+ textInputTarget.focus?.({ preventScroll: true });
976
+ } catch {
977
+ textInputTarget.focus?.();
978
+ }
979
+ } else {
980
+ try {
981
+ container.focus?.({ preventScroll: true });
982
+ } catch {
983
+ container.focus?.();
984
+ }
985
+ }
986
+ const focusableNodes = Array.from(nodes.values()).filter((n) => n.focusable && isVisible(n));
987
+ if (focusableNodes.length > 0) {
988
+ const targetNode = focusableNodes[0];
989
+ setFocus(targetNode.id);
990
+ const path = targetNode ? ancestorsForTarget(targetNode) : [];
991
+ const ev = buildInputEvent("paste", path, e);
992
+ ev.text = text;
993
+ dispatchWithPhases("paste", path, targetNode, ev);
994
+ }
995
+ }
996
+ }
997
+ function onPaste(e) {
998
+ const anyNative = e;
999
+ const clipboard = anyNative.clipboardData;
1000
+ let text = "";
1001
+ if (clipboard?.files && clipboard.files.length > 0) {
1002
+ const file = clipboard.files[0];
1003
+ text = file.path || file.name;
1004
+ } else if (clipboard?.getData) {
1005
+ text = clipboard.getData("text/plain") || clipboard.getData("text") || "";
1006
+ }
1007
+ record?.({
1008
+ type: "paste",
1009
+ text
1010
+ });
1011
+ if (focusedId) {
1012
+ const targetNode = nodes.get(focusedId);
1013
+ if (targetNode) {
1014
+ const path = ancestorsForTarget(targetNode);
1015
+ const ev = buildInputEvent("paste", path, e);
1016
+ ev.text = text;
1017
+ dispatchWithPhases("paste", path, targetNode, ev);
1018
+ if (ev.defaultPrevented) {
1019
+ anyNative?.preventDefault?.();
1020
+ e?.preventDefault?.();
1021
+ }
1022
+ }
1023
+ }
1024
+ }
1025
+ const textTargets = [container];
1026
+ if (textInputTarget && textInputTarget !== container && !container.contains(textInputTarget)) {
1027
+ textTargets.push(textInputTarget);
1028
+ }
1029
+ const keyboardTargets = [container];
1030
+ if (textInputTarget && textInputTarget !== container && !container.contains(textInputTarget)) {
1031
+ keyboardTargets.push(textInputTarget);
1032
+ }
1033
+ let attached = false;
1034
+ function attach() {
1035
+ if (attached)
1036
+ return;
1037
+ attached = true;
1038
+ container.addEventListener("pointerdown", onPointerDown);
1039
+ container.addEventListener("pointermove", onPointerMove);
1040
+ container.addEventListener("pointerup", onPointerUp);
1041
+ container.addEventListener("mousedown", onMouseDown);
1042
+ container.addEventListener("mousemove", onMouseMove);
1043
+ container.addEventListener("mouseup", onMouseUp);
1044
+ container.addEventListener("mouseleave", onMouseLeave);
1045
+ container.addEventListener("click", onClick);
1046
+ container.addEventListener("dblclick", onDblClick);
1047
+ container.addEventListener("contextmenu", onContextMenu);
1048
+ container.addEventListener("wheel", onWheel, { passive: false });
1049
+ container.addEventListener("dragover", onDragOver);
1050
+ container.addEventListener("drop", onDrop);
1051
+ for (const target of keyboardTargets) {
1052
+ target.addEventListener("keydown", onKeyDown);
1053
+ target.addEventListener("keyup", onKeyUp);
1054
+ }
1055
+ for (const target of textTargets) {
1056
+ target.addEventListener("beforeinput", onBeforeInput);
1057
+ target.addEventListener("input", onInput);
1058
+ target.addEventListener("compositionstart", onCompositionStart);
1059
+ target.addEventListener("compositionupdate", onCompositionUpdate);
1060
+ target.addEventListener("compositionend", onCompositionEnd);
1061
+ target.addEventListener("paste", onPaste);
1062
+ }
1063
+ window.addEventListener("scroll", markContainerRectDirty, {
1064
+ capture: true,
1065
+ passive: true
1066
+ });
1067
+ window.addEventListener("resize", markContainerRectDirty, { passive: true });
1068
+ }
1069
+ if (!options?.deferAttach) {
1070
+ attach();
1071
+ }
1072
+ return {
1073
+ register(node) {
1074
+ const id = node.id ?? `n${nextId++}`;
1075
+ const focusable = node.focusable;
1076
+ const full = {
1077
+ id,
1078
+ rect: node.rect,
1079
+ zIndex: node.zIndex ?? 0,
1080
+ visible: node.visible ?? true,
1081
+ focusable,
1082
+ selectable: node.selectable ?? !focusable,
1083
+ selectionScrollBy: node.selectionScrollBy,
1084
+ handlers: node.handlers ?? {}
1085
+ };
1086
+ if (nodes.has(id))
1087
+ removeFromRowBuckets(id);
1088
+ nodes.set(id, full);
1089
+ addToRowBuckets(id, full);
1090
+ return full;
1091
+ },
1092
+ update(id, next) {
1093
+ const prev = nodes.get(id);
1094
+ if (!prev)
1095
+ return;
1096
+ const nextVisible = next.visible ?? prev.visible;
1097
+ if (nextVisible === false) {
1098
+ if (focusedId === id)
1099
+ setFocus(null);
1100
+ if (capturedId === id)
1101
+ capturedId = null;
1102
+ if (hoverPath.some((n) => n.id === id))
1103
+ hoverPath = [];
1104
+ }
1105
+ nodes.set(id, {
1106
+ ...prev,
1107
+ ...next,
1108
+ rect: next.rect ?? prev.rect,
1109
+ zIndex: next.zIndex ?? prev.zIndex,
1110
+ visible: nextVisible,
1111
+ handlers: next.handlers ?? prev.handlers
1112
+ });
1113
+ const updated = nodes.get(id);
1114
+ if (updated)
1115
+ updateRowBuckets(id, updated);
1116
+ },
1117
+ unregister(id) {
1118
+ if (capturedId === id)
1119
+ capturedId = null;
1120
+ if (hoverPath.some((n) => n.id === id))
1121
+ hoverPath = [];
1122
+ removeFromRowBuckets(id);
1123
+ nodes.delete(id);
1124
+ if (focusedId === id)
1125
+ setFocus(null);
1126
+ },
1127
+ setMetrics(next) {
1128
+ currentMetrics = next;
1129
+ markContainerRectDirty();
1130
+ },
1131
+ canSelectAt(cellX, cellY) {
1132
+ const list = candidatesAt(cellX, cellY);
1133
+ const target = pickTarget(list);
1134
+ const lockNode = resolveModalLockNode();
1135
+ if (lockNode) {
1136
+ if (!target)
1137
+ return false;
1138
+ if (!isAllowedModalPointerNode(target, target, lockNode))
1139
+ return false;
1140
+ }
1141
+ return target ? Boolean(target.selectable) : true;
1142
+ },
1143
+ autoScrollSelectionAt(originCellX, originCellY, pointerCellY) {
1144
+ const target = pickTarget(candidatesAt(originCellX, originCellY));
1145
+ if (!target)
1146
+ return 0;
1147
+ const lockNode = resolveModalLockNode();
1148
+ if (lockNode && !isAllowedModalPointerNode(target, target, lockNode))
1149
+ return 0;
1150
+ const path = ancestorsForTarget(target);
1151
+ let owner = null;
1152
+ for (let i = path.length - 1; i >= 0; i--) {
1153
+ const node = path[i];
1154
+ if (typeof node.selectionScrollBy === "function") {
1155
+ owner = node;
1156
+ break;
1157
+ }
1158
+ }
1159
+ if (!owner)
1160
+ return 0;
1161
+ const rect = owner.rect;
1162
+ const y = Math.floor(pointerCellY);
1163
+ let delta = 0;
1164
+ if (y <= rect.y)
1165
+ delta = -1;
1166
+ else if (y >= rect.y + rect.h - 1)
1167
+ delta = 1;
1168
+ if (!delta)
1169
+ return 0;
1170
+ const scrolled = owner.selectionScrollBy?.(delta);
1171
+ return scrolled === false ? 0 : delta;
1172
+ },
1173
+ focus(id) {
1174
+ setFocus(id);
1175
+ },
1176
+ getFocused() {
1177
+ return focusedId;
1178
+ },
1179
+ debugNodes() {
1180
+ return Array.from(nodes.values()).map((n) => ({
1181
+ id: n.id,
1182
+ rect: n.rect,
1183
+ zIndex: n.zIndex,
1184
+ visible: isVisible(n),
1185
+ focusable: Boolean(n.focusable)
1186
+ }));
1187
+ },
1188
+ attach,
1189
+ dispose() {
1190
+ window.removeEventListener("scroll", markContainerRectDirty, true);
1191
+ window.removeEventListener("resize", markContainerRectDirty);
1192
+ if (!attached)
1193
+ return;
1194
+ attached = false;
1195
+ container.removeEventListener("pointerdown", onPointerDown);
1196
+ container.removeEventListener("pointermove", onPointerMove);
1197
+ container.removeEventListener("pointerup", onPointerUp);
1198
+ container.removeEventListener("mousedown", onMouseDown);
1199
+ container.removeEventListener("mousemove", onMouseMove);
1200
+ container.removeEventListener("mouseup", onMouseUp);
1201
+ container.removeEventListener("mouseleave", onMouseLeave);
1202
+ container.removeEventListener("click", onClick);
1203
+ container.removeEventListener("dblclick", onDblClick);
1204
+ container.removeEventListener("contextmenu", onContextMenu);
1205
+ container.removeEventListener("wheel", onWheel);
1206
+ for (const target of keyboardTargets) {
1207
+ target.removeEventListener("keydown", onKeyDown);
1208
+ target.removeEventListener("keyup", onKeyUp);
1209
+ }
1210
+ for (const target of textTargets) {
1211
+ target.removeEventListener("beforeinput", onBeforeInput);
1212
+ target.removeEventListener("input", onInput);
1213
+ target.removeEventListener("compositionstart", onCompositionStart);
1214
+ target.removeEventListener("compositionupdate", onCompositionUpdate);
1215
+ target.removeEventListener("compositionend", onCompositionEnd);
1216
+ target.removeEventListener("paste", onPaste);
1217
+ }
1218
+ rowBuckets.clear();
1219
+ rowRangeById.clear();
1220
+ nodes.clear();
1221
+ focusedId = null;
1222
+ capturedId = null;
1223
+ hoverPath = [];
1224
+ }
1225
+ };
1226
+ }
1227
+
1228
+ // src/runtime/index.ts
1229
+ function isNodeLike() {
1230
+ const proc = globalThis.process;
1231
+ return typeof proc?.versions?.node === "string";
1232
+ }
1233
+ function detectEnv() {
1234
+ const isBrowser = typeof window !== "undefined" && typeof document !== "undefined";
1235
+ if (isBrowser)
1236
+ return "browser";
1237
+ if (isNodeLike())
1238
+ return "terminal";
1239
+ return "unknown";
1240
+ }
1241
+ function createUnsupportedClipboard() {
1242
+ return {
1243
+ supported: false,
1244
+ async readText() {
1245
+ throw new Error("Clipboard not available in this runtime");
1246
+ },
1247
+ async writeText() {
1248
+ throw new Error("Clipboard not available in this runtime");
1249
+ }
1250
+ };
1251
+ }
1252
+ function createClipboard(kind) {
1253
+ if (kind === "browser") {
1254
+ const supported = typeof navigator !== "undefined" && !!navigator.clipboard?.writeText && !!navigator.clipboard?.readText;
1255
+ return {
1256
+ supported,
1257
+ async readText() {
1258
+ if (!supported)
1259
+ throw new Error("Clipboard not available in this runtime");
1260
+ return navigator.clipboard.readText();
1261
+ },
1262
+ async writeText(text) {
1263
+ if (!supported)
1264
+ throw new Error("Clipboard not available in this runtime");
1265
+ await navigator.clipboard.writeText(text);
1266
+ }
1267
+ };
1268
+ }
1269
+ return createUnsupportedClipboard();
1270
+ }
1271
+ function nowMs() {
1272
+ return typeof performance !== "undefined" && typeof performance.now === "function" ? performance.now() : Date.now();
1273
+ }
1274
+ function createRaf(kind, timer) {
1275
+ const g = globalThis;
1276
+ if (kind === "browser" && typeof g.requestAnimationFrame === "function" && typeof g.cancelAnimationFrame === "function") {
1277
+ return {
1278
+ request: (cb) => g.requestAnimationFrame(cb),
1279
+ cancel: (id) => g.cancelAnimationFrame(id)
1280
+ };
1281
+ }
1282
+ return {
1283
+ request(cb) {
1284
+ return timer.setTimeout(() => cb(nowMs()), 16);
1285
+ },
1286
+ cancel(id) {
1287
+ timer.clearTimeout(id);
1288
+ }
1289
+ };
1290
+ }
1291
+ function createMeasureText(kind) {
1292
+ if (kind !== "browser")
1293
+ return () => null;
1294
+ return (text, opts) => {
1295
+ try {
1296
+ const doc = typeof document !== "undefined" ? document : null;
1297
+ if (!doc || !("createElement" in doc))
1298
+ return null;
1299
+ const canvas = doc.createElement("canvas");
1300
+ const ctx = canvas?.getContext?.("2d");
1301
+ if (!ctx)
1302
+ return null;
1303
+ if (opts?.font)
1304
+ ctx.font = opts.font;
1305
+ const m = ctx.measureText(text);
1306
+ return typeof m.width === "number" && Number.isFinite(m.width) ? m.width : null;
1307
+ } catch {
1308
+ return null;
1309
+ }
1310
+ };
1311
+ }
1312
+ function createRuntime(kind = detectEnv(), options = {}) {
1313
+ const timer = {
1314
+ setTimeout: globalThis.setTimeout.bind(globalThis),
1315
+ clearTimeout: globalThis.clearTimeout.bind(globalThis),
1316
+ setInterval: globalThis.setInterval.bind(globalThis),
1317
+ clearInterval: globalThis.clearInterval.bind(globalThis)
1318
+ };
1319
+ const env = Object.freeze({
1320
+ kind,
1321
+ isBrowser: kind === "browser",
1322
+ isTerminal: kind === "terminal"
1323
+ });
1324
+ return {
1325
+ env,
1326
+ now() {
1327
+ return nowMs();
1328
+ },
1329
+ timer,
1330
+ raf: createRaf(kind, timer),
1331
+ clipboard: options.clipboard ?? createClipboard(kind),
1332
+ getWindow() {
1333
+ return env.isBrowser && typeof window !== "undefined" ? window : null;
1334
+ },
1335
+ getDocument() {
1336
+ return env.isBrowser && typeof document !== "undefined" ? document : null;
1337
+ },
1338
+ measureText: createMeasureText(kind)
1339
+ };
1340
+ }
1341
+
1342
+ // src/selection/terminal-selection.ts
1343
+ var import_vue = require("vue");
1344
+ var EMPTY_STATE = Object.freeze({
1345
+ active: false,
1346
+ anchor: null,
1347
+ focus: null,
1348
+ text: "",
1349
+ hasRange: false
1350
+ });
1351
+ function clampPoint(point, cols, rows) {
1352
+ return {
1353
+ x: Math.max(0, Math.min(Math.max(0, cols - 1), Math.floor(point.x))),
1354
+ y: Math.max(0, Math.min(Math.max(0, rows - 1), Math.floor(point.y)))
1355
+ };
1356
+ }
1357
+ function comparePoints(a, b) {
1358
+ return a.y - b.y || a.x - b.x;
1359
+ }
1360
+ function pointKey(point) {
1361
+ return `${point.x}:${point.y}`;
1362
+ }
1363
+ function providerPointsDiffer(a, b) {
1364
+ return Boolean(
1365
+ a && b && a.providerId === b.providerId && pointKey(a.point) !== pointKey(b.point)
1366
+ );
1367
+ }
1368
+ function terminalSelectionRowSpans(range, cols, rows) {
1369
+ if (cols <= 0 || rows <= 0)
1370
+ return [];
1371
+ const anchor = clampPoint(range.anchor, cols, rows);
1372
+ const focus = clampPoint(range.focus, cols, rows);
1373
+ if (pointKey(anchor) === pointKey(focus))
1374
+ return [];
1375
+ const start = comparePoints(anchor, focus) <= 0 ? anchor : focus;
1376
+ const end = start === anchor ? focus : anchor;
1377
+ const spans = [];
1378
+ for (let y = start.y; y <= end.y; y++) {
1379
+ const x0 = y === start.y ? start.x : 0;
1380
+ const x1 = y === end.y ? end.x + 1 : cols;
1381
+ if (x1 > x0)
1382
+ spans.push({ y, x0, x1 });
1383
+ }
1384
+ return spans;
1385
+ }
1386
+ function terminalSelectionVisibleRowSpans(range, cols, rows, visibleStartY, visibleEndY) {
1387
+ if (cols <= 0 || rows <= 0)
1388
+ return [];
1389
+ const anchor = clampPoint(range.anchor, cols, rows);
1390
+ const focus = clampPoint(range.focus, cols, rows);
1391
+ if (pointKey(anchor) === pointKey(focus))
1392
+ return [];
1393
+ const start = comparePoints(anchor, focus) <= 0 ? anchor : focus;
1394
+ const end = start === anchor ? focus : anchor;
1395
+ const fromY = Math.max(start.y, Math.floor(visibleStartY), 0);
1396
+ const toY = Math.min(end.y, Math.ceil(visibleEndY) - 1, rows - 1);
1397
+ if (toY < fromY)
1398
+ return [];
1399
+ const spans = [];
1400
+ for (let y = fromY; y <= toY; y++) {
1401
+ const x0 = y === start.y ? start.x : 0;
1402
+ const x1 = y === end.y ? end.x + 1 : cols;
1403
+ if (x1 > x0)
1404
+ spans.push({ y, x0, x1 });
1405
+ }
1406
+ return spans;
1407
+ }
1408
+ function selectedRowText(row, x0, x1, cols) {
1409
+ let out = "";
1410
+ for (let x = x0; x < x1; x++) {
1411
+ const cell = row[x];
1412
+ if (!cell || cell.continuation)
1413
+ continue;
1414
+ out += cell.ch || " ";
1415
+ }
1416
+ return x1 >= cols ? out.trimEnd() : out;
1417
+ }
1418
+ function copyPayload(text, ok, error) {
1419
+ return {
1420
+ text,
1421
+ rows: text ? text.split("\n").length : 0,
1422
+ chars: text.length,
1423
+ ok,
1424
+ ...error === void 0 ? {} : { error }
1425
+ };
1426
+ }
1427
+ function clampPointToRect(point, rect) {
1428
+ return {
1429
+ x: Math.max(rect.x, Math.min(rect.x + Math.max(0, rect.w - 1), Math.floor(point.x))),
1430
+ y: Math.max(rect.y, Math.min(rect.y + Math.max(0, rect.h - 1), Math.floor(point.y)))
1431
+ };
1432
+ }
1433
+ function createTerminalSelectionController(options) {
1434
+ const state = (0, import_vue.shallowRef)(EMPTY_STATE);
1435
+ let range = null;
1436
+ let providerAnchor = null;
1437
+ let providerFocus = null;
1438
+ let overlaySpans = /* @__PURE__ */ new Map();
1439
+ let dirtyRows = /* @__PURE__ */ new Set();
1440
+ const readOptions = () => ({
1441
+ autoCopy: true,
1442
+ copyOnMouseUp: true,
1443
+ style: { inverse: true },
1444
+ ...options.getOptions?.() ?? {}
1445
+ });
1446
+ const markDirty = (prev, next) => {
1447
+ const rows = /* @__PURE__ */ new Set();
1448
+ for (const y of prev)
1449
+ rows.add(y);
1450
+ for (const y of next)
1451
+ rows.add(y);
1452
+ if (rows.size)
1453
+ options.onDirtyRows?.(Array.from(rows).sort((a, b) => a - b));
1454
+ };
1455
+ const providers = () => options.getTextProviders?.() ?? [];
1456
+ const getRow = (y) => options.getRow?.(y) ?? options.terminal.getRow(y);
1457
+ const providerById = (id) => providers().find((provider) => provider.id === id) ?? null;
1458
+ const providerForCell = (point) => {
1459
+ let best = null;
1460
+ let bestArea = Infinity;
1461
+ for (const provider of providers()) {
1462
+ const rect = provider.rect;
1463
+ if (point.x < rect.x || point.y < rect.y || point.x >= rect.x + rect.w || point.y >= rect.y + rect.h) {
1464
+ continue;
1465
+ }
1466
+ const area2 = Math.max(0, rect.w) * Math.max(0, rect.h);
1467
+ if (area2 < bestArea) {
1468
+ best = provider;
1469
+ bestArea = area2;
1470
+ }
1471
+ }
1472
+ return best;
1473
+ };
1474
+ const providerPointForCell = (provider, point, options2) => {
1475
+ const inputPoint = options2?.clampToRect ? clampPointToRect(point, provider.rect) : point;
1476
+ const providerPoint = provider.pointForCell?.(inputPoint) ?? inputPoint;
1477
+ return providerPoint ? { providerId: provider.id, point: providerPoint } : null;
1478
+ };
1479
+ const textFromTerminalBuffer = (nextRange) => {
1480
+ const size = options.terminal.size();
1481
+ const spans = terminalSelectionRowSpans(nextRange, size.cols, size.rows);
1482
+ const lines = [];
1483
+ for (const span of spans) {
1484
+ lines.push(selectedRowText(getRow(span.y), span.x0, span.x1, size.cols));
1485
+ }
1486
+ return lines.join("\n");
1487
+ };
1488
+ const providerRangeFor = (provider, screenRange, anchorOverride, focusOverride) => {
1489
+ if (anchorOverride && focusOverride && anchorOverride.providerId === provider.id && focusOverride.providerId === provider.id) {
1490
+ return {
1491
+ anchor: anchorOverride.point,
1492
+ focus: focusOverride.point,
1493
+ mode: screenRange.mode
1494
+ };
1495
+ }
1496
+ const anchor = providerPointForCell(provider, screenRange.anchor, { clampToRect: true });
1497
+ const focus = providerPointForCell(provider, screenRange.focus, { clampToRect: true });
1498
+ if (!anchor || !focus)
1499
+ return null;
1500
+ if (anchor.providerId !== provider.id || focus.providerId !== provider.id)
1501
+ return null;
1502
+ return {
1503
+ anchor: anchor.point,
1504
+ focus: focus.point,
1505
+ mode: screenRange.mode
1506
+ };
1507
+ };
1508
+ const selectedText = () => {
1509
+ if (!range)
1510
+ return "";
1511
+ const currentRange = range;
1512
+ if (providerAnchor && providerFocus && providerAnchor.providerId === providerFocus.providerId) {
1513
+ const provider2 = providerById(providerAnchor.providerId);
1514
+ if (provider2) {
1515
+ const providerRange = providerRangeFor(
1516
+ provider2,
1517
+ currentRange,
1518
+ providerAnchor,
1519
+ providerFocus
1520
+ );
1521
+ if (providerRange)
1522
+ return provider2.getText(providerRange);
1523
+ }
1524
+ }
1525
+ const provider = providers().find((candidate) => candidate.canHandle(currentRange));
1526
+ if (provider) {
1527
+ const providerRange = providerRangeFor(provider, currentRange);
1528
+ if (providerRange)
1529
+ return provider.getText(providerRange);
1530
+ }
1531
+ return textFromTerminalBuffer(currentRange);
1532
+ };
1533
+ const setResolvedText = (text) => {
1534
+ if (!range || !state.value.active || state.value.text === text)
1535
+ return;
1536
+ state.value = { ...state.value, text };
1537
+ };
1538
+ const resolveProvider = (nextRange, nextProviderAnchor) => {
1539
+ if (!nextRange)
1540
+ return null;
1541
+ if (nextProviderAnchor) {
1542
+ const provider = providerById(nextProviderAnchor.providerId);
1543
+ if (provider)
1544
+ return provider;
1545
+ }
1546
+ return providers().find((candidate) => candidate.canHandle(nextRange)) ?? null;
1547
+ };
1548
+ const rebuild = (nextRange, nextProviderAnchor, nextProviderFocus) => {
1549
+ const previousRows = dirtyRows;
1550
+ const size = options.terminal.size();
1551
+ const nextOverlaySpans = /* @__PURE__ */ new Map();
1552
+ const nextDirtyRows = /* @__PURE__ */ new Set();
1553
+ let hasRange = false;
1554
+ if (nextRange) {
1555
+ const activeProvider = resolveProvider(nextRange, nextProviderAnchor);
1556
+ let spans;
1557
+ const providerRange = activeProvider != null ? providerRangeFor(activeProvider, nextRange, nextProviderAnchor, nextProviderFocus) : null;
1558
+ if (activeProvider?.getVisibleSpans && providerRange) {
1559
+ spans = activeProvider.getVisibleSpans(providerRange, nextRange);
1560
+ } else {
1561
+ spans = terminalSelectionRowSpans(nextRange, size.cols, size.rows);
1562
+ }
1563
+ hasRange = spans.length > 0 || providerPointsDiffer(nextProviderAnchor, nextProviderFocus);
1564
+ for (const span of spans) {
1565
+ const x0 = Math.max(0, Math.min(size.cols, Math.floor(span.x0)));
1566
+ const x1 = Math.max(0, Math.min(size.cols, Math.floor(span.x1)));
1567
+ const y = Math.floor(span.y);
1568
+ if (y < 0 || y >= size.rows || x1 <= x0)
1569
+ continue;
1570
+ let list = nextOverlaySpans.get(y);
1571
+ if (!list) {
1572
+ list = [];
1573
+ nextOverlaySpans.set(y, list);
1574
+ }
1575
+ list.push({ y, x0, x1 });
1576
+ nextDirtyRows.add(y);
1577
+ }
1578
+ }
1579
+ range = nextRange;
1580
+ providerAnchor = nextProviderAnchor;
1581
+ providerFocus = nextProviderFocus;
1582
+ overlaySpans = nextOverlaySpans;
1583
+ dirtyRows = nextDirtyRows;
1584
+ state.value = nextRange ? {
1585
+ active: true,
1586
+ anchor: nextRange.anchor,
1587
+ focus: nextRange.focus,
1588
+ text: "",
1589
+ hasRange
1590
+ } : EMPTY_STATE;
1591
+ markDirty(previousRows, nextDirtyRows);
1592
+ };
1593
+ const controller = {
1594
+ state,
1595
+ start(point, startOptions) {
1596
+ const size = options.terminal.size();
1597
+ const focus = clampPoint(point, size.cols, size.rows);
1598
+ const anchor = startOptions?.extend && range?.anchor ? clampPoint(range.anchor, size.cols, size.rows) : focus;
1599
+ const anchorProvider = providerForCell(anchor);
1600
+ const focusProvider = providerForCell(focus);
1601
+ const activeProvider = startOptions?.extend && providerAnchor ? providerById(providerAnchor.providerId) : null;
1602
+ const nextProviderAnchor = startOptions?.extend && providerAnchor ? providerAnchor : anchorProvider ? providerPointForCell(anchorProvider, anchor) : null;
1603
+ const nextProviderFocus = activeProvider ? providerPointForCell(activeProvider, focus, { clampToRect: true }) : nextProviderAnchor && focusProvider?.id === nextProviderAnchor.providerId ? providerPointForCell(focusProvider, focus) : null;
1604
+ rebuild({ anchor, focus, mode: "linear" }, nextProviderAnchor, nextProviderFocus);
1605
+ },
1606
+ update(point) {
1607
+ if (!range)
1608
+ return;
1609
+ const size = options.terminal.size();
1610
+ const focus = clampPoint(point, size.cols, size.rows);
1611
+ const activeProvider = providerAnchor ? providerById(providerAnchor.providerId) : null;
1612
+ const nextProviderFocus = activeProvider ? providerPointForCell(activeProvider, focus, { clampToRect: true }) : null;
1613
+ rebuild(
1614
+ {
1615
+ ...range,
1616
+ focus
1617
+ },
1618
+ providerAnchor,
1619
+ nextProviderFocus
1620
+ );
1621
+ },
1622
+ async finish() {
1623
+ if (!range)
1624
+ return;
1625
+ if (!state.value.hasRange) {
1626
+ controller.clear();
1627
+ return;
1628
+ }
1629
+ const current = readOptions();
1630
+ if (!current.autoCopy || !current.copyOnMouseUp) {
1631
+ return;
1632
+ }
1633
+ await controller.copy();
1634
+ },
1635
+ clear() {
1636
+ if (!range && !dirtyRows.size)
1637
+ return;
1638
+ rebuild(null, null, null);
1639
+ },
1640
+ async copy() {
1641
+ const text = state.value.text || selectedText();
1642
+ if (!text)
1643
+ return false;
1644
+ setResolvedText(text);
1645
+ if (!options.clipboard.supported) {
1646
+ options.onCopy?.(copyPayload(text, false, new Error("Clipboard unavailable")));
1647
+ return false;
1648
+ }
1649
+ try {
1650
+ await options.clipboard.writeText(text);
1651
+ options.onCopy?.(copyPayload(text, true));
1652
+ return true;
1653
+ } catch (error) {
1654
+ options.onCopy?.(copyPayload(text, false, error));
1655
+ return false;
1656
+ }
1657
+ },
1658
+ paint(dirtyRowsHint) {
1659
+ const rows = dirtyRowsHint ?? Array.from(overlaySpans.keys());
1660
+ const selectionStyle = readOptions().style;
1661
+ for (const y of rows) {
1662
+ const spans = overlaySpans.get(y);
1663
+ if (!spans?.length)
1664
+ continue;
1665
+ const row = getRow(y);
1666
+ for (const span of spans) {
1667
+ for (let x = span.x0; x < span.x1; x++) {
1668
+ const cell = row[x];
1669
+ if (!cell || cell.continuation)
1670
+ continue;
1671
+ const { href: _href, ...baseStyle } = cell.style;
1672
+ options.overlayTerminal.put(x, y, cell.ch || " ", {
1673
+ ...baseStyle,
1674
+ ...selectionStyle
1675
+ });
1676
+ }
1677
+ }
1678
+ }
1679
+ },
1680
+ refresh(refreshOptions) {
1681
+ if (!range)
1682
+ return;
1683
+ if (refreshOptions?.remapFocus) {
1684
+ const activeProvider = providerAnchor ? providerById(providerAnchor.providerId) : resolveProvider(range, null);
1685
+ const nextProviderFocus = activeProvider ? providerPointForCell(activeProvider, range.focus, { clampToRect: true }) : providerFocus;
1686
+ rebuild(range, providerAnchor, nextProviderFocus);
1687
+ return;
1688
+ }
1689
+ rebuild(range, providerAnchor, providerFocus);
1690
+ },
1691
+ clearProvider(providerId) {
1692
+ if (providerAnchor?.providerId === providerId || providerFocus?.providerId === providerId) {
1693
+ controller.clear();
1694
+ }
1695
+ }
1696
+ };
1697
+ return controller;
1698
+ }