@react-x11/components 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (783) hide show
  1. package/README.md +979 -21
  2. package/dist/ansi/cast.d.ts +48 -0
  3. package/dist/ansi/cast.d.ts.map +1 -0
  4. package/dist/ansi/cast.js +135 -0
  5. package/dist/ansi/cast.js.map +1 -0
  6. package/dist/ansi/index.d.ts +10 -0
  7. package/dist/ansi/index.d.ts.map +1 -0
  8. package/dist/ansi/index.js +27 -0
  9. package/dist/ansi/index.js.map +1 -0
  10. package/dist/ansi/palette.d.ts +79 -0
  11. package/dist/ansi/palette.d.ts.map +1 -0
  12. package/dist/ansi/palette.js +155 -0
  13. package/dist/ansi/palette.js.map +1 -0
  14. package/dist/ansi/parse.d.ts +114 -0
  15. package/dist/ansi/parse.d.ts.map +1 -0
  16. package/dist/ansi/parse.js +687 -0
  17. package/dist/ansi/parse.js.map +1 -0
  18. package/dist/ansi/sgr.d.ts +87 -0
  19. package/dist/ansi/sgr.d.ts.map +1 -0
  20. package/dist/ansi/sgr.js +302 -0
  21. package/dist/ansi/sgr.js.map +1 -0
  22. package/dist/ansi/utf8.d.ts +15 -0
  23. package/dist/ansi/utf8.d.ts.map +1 -0
  24. package/dist/ansi/utf8.js +82 -0
  25. package/dist/ansi/utf8.js.map +1 -0
  26. package/dist/calendar/Calendar.d.ts +136 -0
  27. package/dist/calendar/Calendar.d.ts.map +1 -0
  28. package/dist/calendar/Calendar.js +460 -0
  29. package/dist/calendar/Calendar.js.map +1 -0
  30. package/dist/calendar/DatePicker.d.ts +52 -0
  31. package/dist/calendar/DatePicker.d.ts.map +1 -0
  32. package/dist/calendar/DatePicker.js +257 -0
  33. package/dist/calendar/DatePicker.js.map +1 -0
  34. package/dist/calendar/dates.d.ts +90 -0
  35. package/dist/calendar/dates.d.ts.map +1 -0
  36. package/dist/calendar/dates.js +236 -0
  37. package/dist/calendar/dates.js.map +1 -0
  38. package/dist/calendar/index.d.ts +8 -0
  39. package/dist/calendar/index.d.ts.map +1 -0
  40. package/dist/calendar/index.js +15 -0
  41. package/dist/calendar/index.js.map +1 -0
  42. package/dist/charts/components.d.ts +141 -0
  43. package/dist/charts/components.d.ts.map +1 -0
  44. package/dist/charts/components.js +580 -0
  45. package/dist/charts/components.js.map +1 -0
  46. package/dist/charts/data.d.ts +198 -0
  47. package/dist/charts/data.d.ts.map +1 -0
  48. package/dist/charts/data.js +616 -0
  49. package/dist/charts/data.js.map +1 -0
  50. package/dist/charts/hx.d.ts +21 -0
  51. package/dist/charts/hx.d.ts.map +1 -0
  52. package/dist/charts/hx.js +15 -0
  53. package/dist/charts/hx.js.map +1 -0
  54. package/dist/charts/index.d.ts +27 -0
  55. package/dist/charts/index.d.ts.map +1 -0
  56. package/dist/charts/index.js +38 -0
  57. package/dist/charts/index.js.map +1 -0
  58. package/dist/charts/node.d.ts +96 -0
  59. package/dist/charts/node.d.ts.map +1 -0
  60. package/dist/charts/node.js +720 -0
  61. package/dist/charts/node.js.map +1 -0
  62. package/dist/charts/render.d.ts +153 -0
  63. package/dist/charts/render.d.ts.map +1 -0
  64. package/dist/charts/render.js +762 -0
  65. package/dist/charts/render.js.map +1 -0
  66. package/dist/charts/scale.d.ts +42 -0
  67. package/dist/charts/scale.d.ts.map +1 -0
  68. package/dist/charts/scale.js +173 -0
  69. package/dist/charts/scale.js.map +1 -0
  70. package/dist/charts/spec.d.ts +91 -0
  71. package/dist/charts/spec.d.ts.map +1 -0
  72. package/dist/charts/spec.js +33 -0
  73. package/dist/charts/spec.js.map +1 -0
  74. package/dist/charts/timers.d.ts +6 -0
  75. package/dist/charts/timers.d.ts.map +1 -0
  76. package/dist/charts/timers.js +14 -0
  77. package/dist/charts/timers.js.map +1 -0
  78. package/dist/code/hx.d.ts +24 -0
  79. package/dist/code/hx.d.ts.map +1 -0
  80. package/dist/code/hx.js +25 -0
  81. package/dist/code/hx.js.map +1 -0
  82. package/dist/code/index.d.ts +45 -0
  83. package/dist/code/index.d.ts.map +1 -0
  84. package/dist/code/index.js +93 -0
  85. package/dist/code/index.js.map +1 -0
  86. package/dist/code-editor/completion.d.ts +26 -0
  87. package/dist/code-editor/completion.d.ts.map +1 -0
  88. package/dist/code-editor/completion.js +129 -0
  89. package/dist/code-editor/completion.js.map +1 -0
  90. package/dist/code-editor/doc.d.ts +35 -0
  91. package/dist/code-editor/doc.d.ts.map +1 -0
  92. package/dist/code-editor/doc.js +162 -0
  93. package/dist/code-editor/doc.js.map +1 -0
  94. package/dist/code-editor/hx.d.ts +13 -0
  95. package/dist/code-editor/hx.d.ts.map +1 -0
  96. package/dist/code-editor/hx.js +10 -0
  97. package/dist/code-editor/hx.js.map +1 -0
  98. package/dist/code-editor/index.d.ts +88 -0
  99. package/dist/code-editor/index.d.ts.map +1 -0
  100. package/dist/code-editor/index.js +401 -0
  101. package/dist/code-editor/index.js.map +1 -0
  102. package/dist/code-editor/node.d.ts +343 -0
  103. package/dist/code-editor/node.d.ts.map +1 -0
  104. package/dist/code-editor/node.js +1521 -0
  105. package/dist/code-editor/node.js.map +1 -0
  106. package/dist/code-language/hljs.d.ts +47 -0
  107. package/dist/code-language/hljs.d.ts.map +1 -0
  108. package/dist/code-language/hljs.js +211 -0
  109. package/dist/code-language/hljs.js.map +1 -0
  110. package/dist/code-language/index.d.ts +22 -0
  111. package/dist/code-language/index.d.ts.map +1 -0
  112. package/dist/code-language/index.js +20 -0
  113. package/dist/code-language/index.js.map +1 -0
  114. package/dist/code-language/languages/glsl.d.ts +4 -0
  115. package/dist/code-language/languages/glsl.d.ts.map +1 -0
  116. package/dist/code-language/languages/glsl.js +99 -0
  117. package/dist/code-language/languages/glsl.js.map +1 -0
  118. package/dist/code-language/languages/javascript.d.ts +10 -0
  119. package/dist/code-language/languages/javascript.d.ts.map +1 -0
  120. package/dist/code-language/languages/javascript.js +360 -0
  121. package/dist/code-language/languages/javascript.js.map +1 -0
  122. package/dist/code-language/languages/json.d.ts +4 -0
  123. package/dist/code-language/languages/json.d.ts.map +1 -0
  124. package/dist/code-language/languages/json.js +68 -0
  125. package/dist/code-language/languages/json.js.map +1 -0
  126. package/dist/code-language/languages/shell.d.ts +4 -0
  127. package/dist/code-language/languages/shell.d.ts.map +1 -0
  128. package/dist/code-language/languages/shell.js +189 -0
  129. package/dist/code-language/languages/shell.js.map +1 -0
  130. package/dist/code-language/languages/sql.d.ts +11 -0
  131. package/dist/code-language/languages/sql.d.ts.map +1 -0
  132. package/dist/code-language/languages/sql.js +133 -0
  133. package/dist/code-language/languages/sql.js.map +1 -0
  134. package/dist/code-language/lezer.d.ts +24 -0
  135. package/dist/code-language/lezer.d.ts.map +1 -0
  136. package/dist/code-language/lezer.js +148 -0
  137. package/dist/code-language/lezer.js.map +1 -0
  138. package/dist/code-language/registry.d.ts +19 -0
  139. package/dist/code-language/registry.d.ts.map +1 -0
  140. package/dist/code-language/registry.js +56 -0
  141. package/dist/code-language/registry.js.map +1 -0
  142. package/dist/code-language/runs.d.ts +35 -0
  143. package/dist/code-language/runs.d.ts.map +1 -0
  144. package/dist/code-language/runs.js +88 -0
  145. package/dist/code-language/runs.js.map +1 -0
  146. package/dist/code-language/stream.d.ts +70 -0
  147. package/dist/code-language/stream.d.ts.map +1 -0
  148. package/dist/code-language/stream.js +243 -0
  149. package/dist/code-language/stream.js.map +1 -0
  150. package/dist/code-language/textmate.d.ts +27 -0
  151. package/dist/code-language/textmate.d.ts.map +1 -0
  152. package/dist/code-language/textmate.js +86 -0
  153. package/dist/code-language/textmate.js.map +1 -0
  154. package/dist/code-language/theme.d.ts +26 -0
  155. package/dist/code-language/theme.d.ts.map +1 -0
  156. package/dist/code-language/theme.js +108 -0
  157. package/dist/code-language/theme.js.map +1 -0
  158. package/dist/code-language/timers.d.ts +7 -0
  159. package/dist/code-language/timers.d.ts.map +1 -0
  160. package/dist/code-language/timers.js +22 -0
  161. package/dist/code-language/timers.js.map +1 -0
  162. package/dist/code-language/types.d.ts +173 -0
  163. package/dist/code-language/types.d.ts.map +1 -0
  164. package/dist/code-language/types.js +41 -0
  165. package/dist/code-language/types.js.map +1 -0
  166. package/dist/codeblock/index.d.ts +69 -0
  167. package/dist/codeblock/index.d.ts.map +1 -0
  168. package/dist/codeblock/index.js +85 -0
  169. package/dist/codeblock/index.js.map +1 -0
  170. package/dist/color-picker/ColorField.d.ts +39 -0
  171. package/dist/color-picker/ColorField.d.ts.map +1 -0
  172. package/dist/color-picker/ColorField.js +239 -0
  173. package/dist/color-picker/ColorField.js.map +1 -0
  174. package/dist/color-picker/ColorPicker.d.ts +109 -0
  175. package/dist/color-picker/ColorPicker.d.ts.map +1 -0
  176. package/dist/color-picker/ColorPicker.js +757 -0
  177. package/dist/color-picker/ColorPicker.js.map +1 -0
  178. package/dist/color-picker/color.d.ts +105 -0
  179. package/dist/color-picker/color.d.ts.map +1 -0
  180. package/dist/color-picker/color.js +313 -0
  181. package/dist/color-picker/color.js.map +1 -0
  182. package/dist/color-picker/index.d.ts +8 -0
  183. package/dist/color-picker/index.d.ts.map +1 -0
  184. package/dist/color-picker/index.js +19 -0
  185. package/dist/color-picker/index.js.map +1 -0
  186. package/dist/desktop-calendar/eds.d.ts +102 -0
  187. package/dist/desktop-calendar/eds.d.ts.map +1 -0
  188. package/dist/desktop-calendar/eds.js +356 -0
  189. package/dist/desktop-calendar/eds.js.map +1 -0
  190. package/dist/desktop-calendar/ical.d.ts +63 -0
  191. package/dist/desktop-calendar/ical.d.ts.map +1 -0
  192. package/dist/desktop-calendar/ical.js +57 -0
  193. package/dist/desktop-calendar/ical.js.map +1 -0
  194. package/dist/desktop-calendar/index.d.ts +72 -0
  195. package/dist/desktop-calendar/index.d.ts.map +1 -0
  196. package/dist/desktop-calendar/index.js +213 -0
  197. package/dist/desktop-calendar/index.js.map +1 -0
  198. package/dist/embed/client.d.ts +121 -0
  199. package/dist/embed/client.d.ts.map +1 -0
  200. package/dist/embed/client.js +203 -0
  201. package/dist/embed/client.js.map +1 -0
  202. package/dist/embed/host.d.ts +96 -0
  203. package/dist/embed/host.d.ts.map +1 -0
  204. package/dist/embed/host.js +266 -0
  205. package/dist/embed/host.js.map +1 -0
  206. package/dist/embed/index.d.ts +5 -0
  207. package/dist/embed/index.d.ts.map +1 -0
  208. package/dist/embed/index.js +13 -0
  209. package/dist/embed/index.js.map +1 -0
  210. package/dist/embed/timers.d.ts +6 -0
  211. package/dist/embed/timers.d.ts.map +1 -0
  212. package/dist/embed/timers.js +16 -0
  213. package/dist/embed/timers.js.map +1 -0
  214. package/dist/flow/draw.d.ts +45 -0
  215. package/dist/flow/draw.d.ts.map +1 -0
  216. package/dist/flow/draw.js +295 -0
  217. package/dist/flow/draw.js.map +1 -0
  218. package/dist/flow/index.d.ts +64 -0
  219. package/dist/flow/index.d.ts.map +1 -0
  220. package/dist/flow/index.js +306 -0
  221. package/dist/flow/index.js.map +1 -0
  222. package/dist/flow/model.d.ts +158 -0
  223. package/dist/flow/model.d.ts.map +1 -0
  224. package/dist/flow/model.js +566 -0
  225. package/dist/flow/model.js.map +1 -0
  226. package/dist/flow/node.d.ts +429 -0
  227. package/dist/flow/node.d.ts.map +1 -0
  228. package/dist/flow/node.js +3025 -0
  229. package/dist/flow/node.js.map +1 -0
  230. package/dist/flow/paths.d.ts +43 -0
  231. package/dist/flow/paths.d.ts.map +1 -0
  232. package/dist/flow/paths.js +327 -0
  233. package/dist/flow/paths.js.map +1 -0
  234. package/dist/flow/types.d.ts +561 -0
  235. package/dist/flow/types.d.ts.map +1 -0
  236. package/dist/flow/types.js +2 -0
  237. package/dist/flow/types.js.map +1 -0
  238. package/dist/formula/hx.d.ts +24 -0
  239. package/dist/formula/hx.d.ts.map +1 -0
  240. package/dist/formula/hx.js +25 -0
  241. package/dist/formula/hx.js.map +1 -0
  242. package/dist/formula/index.d.ts +74 -0
  243. package/dist/formula/index.d.ts.map +1 -0
  244. package/dist/formula/index.js +155 -0
  245. package/dist/formula/index.js.map +1 -0
  246. package/dist/formula/katex.d.ts +78 -0
  247. package/dist/formula/katex.d.ts.map +1 -0
  248. package/dist/formula/katex.js +130 -0
  249. package/dist/formula/katex.js.map +1 -0
  250. package/dist/formula/layout.d.ts +103 -0
  251. package/dist/formula/layout.d.ts.map +1 -0
  252. package/dist/formula/layout.js +716 -0
  253. package/dist/formula/layout.js.map +1 -0
  254. package/dist/formula/node.d.ts +50 -0
  255. package/dist/formula/node.d.ts.map +1 -0
  256. package/dist/formula/node.js +351 -0
  257. package/dist/formula/node.js.map +1 -0
  258. package/dist/html/controls.d.ts +48 -0
  259. package/dist/html/controls.d.ts.map +1 -0
  260. package/dist/html/controls.js +195 -0
  261. package/dist/html/controls.js.map +1 -0
  262. package/dist/html/css/cascade.d.ts +51 -0
  263. package/dist/html/css/cascade.d.ts.map +1 -0
  264. package/dist/html/css/cascade.js +552 -0
  265. package/dist/html/css/cascade.js.map +1 -0
  266. package/dist/html/css/parse.d.ts +74 -0
  267. package/dist/html/css/parse.d.ts.map +1 -0
  268. package/dist/html/css/parse.js +464 -0
  269. package/dist/html/css/parse.js.map +1 -0
  270. package/dist/html/css/style.d.ts +142 -0
  271. package/dist/html/css/style.d.ts.map +1 -0
  272. package/dist/html/css/style.js +1145 -0
  273. package/dist/html/css/style.js.map +1 -0
  274. package/dist/html/css/ua.d.ts +5 -0
  275. package/dist/html/css/ua.d.ts.map +1 -0
  276. package/dist/html/css/ua.js +171 -0
  277. package/dist/html/css/ua.js.map +1 -0
  278. package/dist/html/css/values.d.ts +78 -0
  279. package/dist/html/css/values.d.ts.map +1 -0
  280. package/dist/html/css/values.js +330 -0
  281. package/dist/html/css/values.js.map +1 -0
  282. package/dist/html/dom.d.ts +112 -0
  283. package/dist/html/dom.d.ts.map +1 -0
  284. package/dist/html/dom.js +374 -0
  285. package/dist/html/dom.js.map +1 -0
  286. package/dist/html/hx.d.ts +24 -0
  287. package/dist/html/hx.d.ts.map +1 -0
  288. package/dist/html/hx.js +29 -0
  289. package/dist/html/hx.js.map +1 -0
  290. package/dist/html/index.d.ts +137 -0
  291. package/dist/html/index.d.ts.map +1 -0
  292. package/dist/html/index.js +339 -0
  293. package/dist/html/index.js.map +1 -0
  294. package/dist/html/layout/block.d.ts +58 -0
  295. package/dist/html/layout/block.d.ts.map +1 -0
  296. package/dist/html/layout/block.js +724 -0
  297. package/dist/html/layout/block.js.map +1 -0
  298. package/dist/html/layout/boxes.d.ts +261 -0
  299. package/dist/html/layout/boxes.d.ts.map +1 -0
  300. package/dist/html/layout/boxes.js +725 -0
  301. package/dist/html/layout/boxes.js.map +1 -0
  302. package/dist/html/layout/flex.d.ts +16 -0
  303. package/dist/html/layout/flex.d.ts.map +1 -0
  304. package/dist/html/layout/flex.js +242 -0
  305. package/dist/html/layout/flex.js.map +1 -0
  306. package/dist/html/layout/floats.d.ts +50 -0
  307. package/dist/html/layout/floats.d.ts.map +1 -0
  308. package/dist/html/layout/floats.js +110 -0
  309. package/dist/html/layout/floats.js.map +1 -0
  310. package/dist/html/layout/inline.d.ts +44 -0
  311. package/dist/html/layout/inline.d.ts.map +1 -0
  312. package/dist/html/layout/inline.js +700 -0
  313. package/dist/html/layout/inline.js.map +1 -0
  314. package/dist/html/layout/table.d.ts +5 -0
  315. package/dist/html/layout/table.d.ts.map +1 -0
  316. package/dist/html/layout/table.js +340 -0
  317. package/dist/html/layout/table.js.map +1 -0
  318. package/dist/html/node.d.ts +149 -0
  319. package/dist/html/node.d.ts.map +1 -0
  320. package/dist/html/node.js +861 -0
  321. package/dist/html/node.js.map +1 -0
  322. package/dist/html/paint.d.ts +48 -0
  323. package/dist/html/paint.d.ts.map +1 -0
  324. package/dist/html/paint.js +495 -0
  325. package/dist/html/paint.js.map +1 -0
  326. package/dist/html/resources.d.ts +48 -0
  327. package/dist/html/resources.d.ts.map +1 -0
  328. package/dist/html/resources.js +156 -0
  329. package/dist/html/resources.js.map +1 -0
  330. package/dist/index.d.ts +48 -0
  331. package/dist/index.d.ts.map +1 -0
  332. package/dist/index.js +92 -0
  333. package/dist/index.js.map +1 -0
  334. package/dist/internal/heights.d.ts +81 -0
  335. package/dist/internal/heights.d.ts.map +1 -0
  336. package/dist/internal/heights.js +193 -0
  337. package/dist/internal/heights.js.map +1 -0
  338. package/dist/internal/hx.d.ts +24 -0
  339. package/dist/internal/hx.d.ts.map +1 -0
  340. package/dist/internal/hx.js +27 -0
  341. package/dist/internal/hx.js.map +1 -0
  342. package/dist/internal/text.d.ts +6 -0
  343. package/dist/internal/text.d.ts.map +1 -0
  344. package/dist/internal/text.js +44 -0
  345. package/dist/internal/text.js.map +1 -0
  346. package/dist/internal/timers.d.ts +8 -0
  347. package/dist/internal/timers.d.ts.map +1 -0
  348. package/dist/internal/timers.js +22 -0
  349. package/dist/internal/timers.js.map +1 -0
  350. package/dist/internal/widget.d.ts +40 -0
  351. package/dist/internal/widget.d.ts.map +1 -0
  352. package/dist/internal/widget.js +44 -0
  353. package/dist/internal/widget.js.map +1 -0
  354. package/dist/markdown/ast.d.ts +126 -0
  355. package/dist/markdown/ast.d.ts.map +1 -0
  356. package/dist/markdown/ast.js +8 -0
  357. package/dist/markdown/ast.js.map +1 -0
  358. package/dist/markdown/hx.d.ts +24 -0
  359. package/dist/markdown/hx.d.ts.map +1 -0
  360. package/dist/markdown/hx.js +25 -0
  361. package/dist/markdown/hx.js.map +1 -0
  362. package/dist/markdown/index.d.ts +90 -0
  363. package/dist/markdown/index.d.ts.map +1 -0
  364. package/dist/markdown/index.js +413 -0
  365. package/dist/markdown/index.js.map +1 -0
  366. package/dist/markdown/parse.d.ts +8 -0
  367. package/dist/markdown/parse.d.ts.map +1 -0
  368. package/dist/markdown/parse.js +911 -0
  369. package/dist/markdown/parse.js.map +1 -0
  370. package/dist/markdown/spans.d.ts +20 -0
  371. package/dist/markdown/spans.d.ts.map +1 -0
  372. package/dist/markdown/spans.js +96 -0
  373. package/dist/markdown/spans.js.map +1 -0
  374. package/dist/media-player/backends.d.ts +64 -0
  375. package/dist/media-player/backends.d.ts.map +1 -0
  376. package/dist/media-player/backends.js +110 -0
  377. package/dist/media-player/backends.js.map +1 -0
  378. package/dist/media-player/control.d.ts +40 -0
  379. package/dist/media-player/control.d.ts.map +1 -0
  380. package/dist/media-player/control.js +44 -0
  381. package/dist/media-player/control.js.map +1 -0
  382. package/dist/media-player/hx.d.ts +24 -0
  383. package/dist/media-player/hx.d.ts.map +1 -0
  384. package/dist/media-player/hx.js +25 -0
  385. package/dist/media-player/hx.js.map +1 -0
  386. package/dist/media-player/index.d.ts +107 -0
  387. package/dist/media-player/index.d.ts.map +1 -0
  388. package/dist/media-player/index.js +219 -0
  389. package/dist/media-player/index.js.map +1 -0
  390. package/dist/media-player/mpv.d.ts +4 -0
  391. package/dist/media-player/mpv.d.ts.map +1 -0
  392. package/dist/media-player/mpv.js +120 -0
  393. package/dist/media-player/mpv.js.map +1 -0
  394. package/dist/media-player/vlc.d.ts +8 -0
  395. package/dist/media-player/vlc.d.ts.map +1 -0
  396. package/dist/media-player/vlc.js +83 -0
  397. package/dist/media-player/vlc.js.map +1 -0
  398. package/dist/richtext/index.d.ts +19 -0
  399. package/dist/richtext/index.d.ts.map +1 -0
  400. package/dist/richtext/index.js +4 -0
  401. package/dist/richtext/index.js.map +1 -0
  402. package/dist/richtext/links.d.ts +12 -0
  403. package/dist/richtext/links.d.ts.map +1 -0
  404. package/dist/richtext/links.js +64 -0
  405. package/dist/richtext/links.js.map +1 -0
  406. package/dist/richtext/menu.d.ts +11 -0
  407. package/dist/richtext/menu.d.ts.map +1 -0
  408. package/dist/richtext/menu.js +43 -0
  409. package/dist/richtext/menu.js.map +1 -0
  410. package/dist/richtext/node.d.ts +151 -0
  411. package/dist/richtext/node.d.ts.map +1 -0
  412. package/dist/richtext/node.js +255 -0
  413. package/dist/richtext/node.js.map +1 -0
  414. package/dist/richtext/runs.d.ts +92 -0
  415. package/dist/richtext/runs.d.ts.map +1 -0
  416. package/dist/richtext/runs.js +158 -0
  417. package/dist/richtext/runs.js.map +1 -0
  418. package/dist/table/hx.d.ts +24 -0
  419. package/dist/table/hx.d.ts.map +1 -0
  420. package/dist/table/hx.js +25 -0
  421. package/dist/table/hx.js.map +1 -0
  422. package/dist/table/index.d.ts +169 -0
  423. package/dist/table/index.d.ts.map +1 -0
  424. package/dist/table/index.js +844 -0
  425. package/dist/table/index.js.map +1 -0
  426. package/dist/table/rows.d.ts +136 -0
  427. package/dist/table/rows.d.ts.map +1 -0
  428. package/dist/table/rows.js +146 -0
  429. package/dist/table/rows.js.map +1 -0
  430. package/dist/terminal/backends.d.ts +105 -0
  431. package/dist/terminal/backends.d.ts.map +1 -0
  432. package/dist/terminal/backends.js +185 -0
  433. package/dist/terminal/backends.js.map +1 -0
  434. package/dist/terminal/hx.d.ts +24 -0
  435. package/dist/terminal/hx.d.ts.map +1 -0
  436. package/dist/terminal/hx.js +25 -0
  437. package/dist/terminal/hx.js.map +1 -0
  438. package/dist/terminal/index.d.ts +160 -0
  439. package/dist/terminal/index.d.ts.map +1 -0
  440. package/dist/terminal/index.js +344 -0
  441. package/dist/terminal/index.js.map +1 -0
  442. package/dist/terminal/title.d.ts +24 -0
  443. package/dist/terminal/title.d.ts.map +1 -0
  444. package/dist/terminal/title.js +129 -0
  445. package/dist/terminal/title.js.map +1 -0
  446. package/dist/terminal/vt/colors.d.ts +63 -0
  447. package/dist/terminal/vt/colors.d.ts.map +1 -0
  448. package/dist/terminal/vt/colors.js +203 -0
  449. package/dist/terminal/vt/colors.js.map +1 -0
  450. package/dist/terminal/vt/diff.d.ts +117 -0
  451. package/dist/terminal/vt/diff.d.ts.map +1 -0
  452. package/dist/terminal/vt/diff.js +358 -0
  453. package/dist/terminal/vt/diff.js.map +1 -0
  454. package/dist/terminal/vt/fonts.d.ts +92 -0
  455. package/dist/terminal/vt/fonts.d.ts.map +1 -0
  456. package/dist/terminal/vt/fonts.js +178 -0
  457. package/dist/terminal/vt/fonts.js.map +1 -0
  458. package/dist/terminal/vt/index.d.ts +78 -0
  459. package/dist/terminal/vt/index.d.ts.map +1 -0
  460. package/dist/terminal/vt/index.js +312 -0
  461. package/dist/terminal/vt/index.js.map +1 -0
  462. package/dist/terminal/vt/keys.d.ts +74 -0
  463. package/dist/terminal/vt/keys.d.ts.map +1 -0
  464. package/dist/terminal/vt/keys.js +309 -0
  465. package/dist/terminal/vt/keys.js.map +1 -0
  466. package/dist/terminal/vt/mouse.d.ts +44 -0
  467. package/dist/terminal/vt/mouse.d.ts.map +1 -0
  468. package/dist/terminal/vt/mouse.js +106 -0
  469. package/dist/terminal/vt/mouse.js.map +1 -0
  470. package/dist/terminal/vt/node.d.ts +246 -0
  471. package/dist/terminal/vt/node.d.ts.map +1 -0
  472. package/dist/terminal/vt/node.js +1068 -0
  473. package/dist/terminal/vt/node.js.map +1 -0
  474. package/dist/terminal/vt/pty.d.ts +81 -0
  475. package/dist/terminal/vt/pty.d.ts.map +1 -0
  476. package/dist/terminal/vt/pty.js +201 -0
  477. package/dist/terminal/vt/pty.js.map +1 -0
  478. package/dist/terminal/vt/renderer.d.ts +179 -0
  479. package/dist/terminal/vt/renderer.d.ts.map +1 -0
  480. package/dist/terminal/vt/renderer.js +357 -0
  481. package/dist/terminal/vt/renderer.js.map +1 -0
  482. package/dist/terminal/vt/timers.d.ts +6 -0
  483. package/dist/terminal/vt/timers.d.ts.map +1 -0
  484. package/dist/terminal/vt/timers.js +16 -0
  485. package/dist/terminal/vt/timers.js.map +1 -0
  486. package/dist/terminal/vt/xterm.d.ts +142 -0
  487. package/dist/terminal/vt/xterm.d.ts.map +1 -0
  488. package/dist/terminal/vt/xterm.js +32 -0
  489. package/dist/terminal/vt/xterm.js.map +1 -0
  490. package/dist/terminal-output/hx.d.ts +24 -0
  491. package/dist/terminal-output/hx.d.ts.map +1 -0
  492. package/dist/terminal-output/hx.js +25 -0
  493. package/dist/terminal-output/hx.js.map +1 -0
  494. package/dist/terminal-output/index.d.ts +92 -0
  495. package/dist/terminal-output/index.d.ts.map +1 -0
  496. package/dist/terminal-output/index.js +179 -0
  497. package/dist/terminal-output/index.js.map +1 -0
  498. package/dist/terminal-output/runs.d.ts +27 -0
  499. package/dist/terminal-output/runs.d.ts.map +1 -0
  500. package/dist/terminal-output/runs.js +66 -0
  501. package/dist/terminal-output/runs.js.map +1 -0
  502. package/dist/three/canvas.d.ts +46 -0
  503. package/dist/three/canvas.d.ts.map +1 -0
  504. package/dist/three/canvas.js +305 -0
  505. package/dist/three/canvas.js.map +1 -0
  506. package/dist/three/events.d.ts +64 -0
  507. package/dist/three/events.d.ts.map +1 -0
  508. package/dist/three/events.js +146 -0
  509. package/dist/three/events.js.map +1 -0
  510. package/dist/three/geometries.d.ts +89 -0
  511. package/dist/three/geometries.d.ts.map +1 -0
  512. package/dist/three/geometries.js +345 -0
  513. package/dist/three/geometries.js.map +1 -0
  514. package/dist/three/globals.d.ts +7 -0
  515. package/dist/three/globals.d.ts.map +1 -0
  516. package/dist/three/globals.js +20 -0
  517. package/dist/three/globals.js.map +1 -0
  518. package/dist/three/hx.d.ts +9 -0
  519. package/dist/three/hx.d.ts.map +1 -0
  520. package/dist/three/hx.js +10 -0
  521. package/dist/three/hx.js.map +1 -0
  522. package/dist/three/index.d.ts +22 -0
  523. package/dist/three/index.d.ts.map +1 -0
  524. package/dist/three/index.js +24 -0
  525. package/dist/three/index.js.map +1 -0
  526. package/dist/three/jsx-dev-runtime.d.ts +19 -0
  527. package/dist/three/jsx-dev-runtime.d.ts.map +1 -0
  528. package/dist/three/jsx-dev-runtime.js +2 -0
  529. package/dist/three/jsx-dev-runtime.js.map +1 -0
  530. package/dist/three/jsx-runtime.d.ts +19 -0
  531. package/dist/three/jsx-runtime.d.ts.map +1 -0
  532. package/dist/three/jsx-runtime.js +2 -0
  533. package/dist/three/jsx-runtime.js.map +1 -0
  534. package/dist/three/jsx.d.ts +198 -0
  535. package/dist/three/jsx.d.ts.map +1 -0
  536. package/dist/three/jsx.js +2 -0
  537. package/dist/three/jsx.js.map +1 -0
  538. package/dist/three/materials.d.ts +125 -0
  539. package/dist/three/materials.d.ts.map +1 -0
  540. package/dist/three/materials.js +229 -0
  541. package/dist/three/materials.js.map +1 -0
  542. package/dist/three/math.d.ts +146 -0
  543. package/dist/three/math.d.ts.map +1 -0
  544. package/dist/three/math.js +464 -0
  545. package/dist/three/math.js.map +1 -0
  546. package/dist/three/objects.d.ts +185 -0
  547. package/dist/three/objects.d.ts.map +1 -0
  548. package/dist/three/objects.js +309 -0
  549. package/dist/three/objects.js.map +1 -0
  550. package/dist/three/passes.d.ts +54 -0
  551. package/dist/three/passes.d.ts.map +1 -0
  552. package/dist/three/passes.js +78 -0
  553. package/dist/three/passes.js.map +1 -0
  554. package/dist/three/postprocess.d.ts +85 -0
  555. package/dist/three/postprocess.d.ts.map +1 -0
  556. package/dist/three/postprocess.js +503 -0
  557. package/dist/three/postprocess.js.map +1 -0
  558. package/dist/three/raycast.d.ts +24 -0
  559. package/dist/three/raycast.d.ts.map +1 -0
  560. package/dist/three/raycast.js +138 -0
  561. package/dist/three/raycast.js.map +1 -0
  562. package/dist/three/reconciler.d.ts +48 -0
  563. package/dist/three/reconciler.d.ts.map +1 -0
  564. package/dist/three/reconciler.js +416 -0
  565. package/dist/three/reconciler.js.map +1 -0
  566. package/dist/three/renderer-direct.d.ts +102 -0
  567. package/dist/three/renderer-direct.d.ts.map +1 -0
  568. package/dist/three/renderer-direct.js +782 -0
  569. package/dist/three/renderer-direct.js.map +1 -0
  570. package/dist/three/renderer-indirect.d.ts +68 -0
  571. package/dist/three/renderer-indirect.d.ts.map +1 -0
  572. package/dist/three/renderer-indirect.js +438 -0
  573. package/dist/three/renderer-indirect.js.map +1 -0
  574. package/dist/three/store.d.ts +81 -0
  575. package/dist/three/store.d.ts.map +1 -0
  576. package/dist/three/store.js +110 -0
  577. package/dist/three/store.js.map +1 -0
  578. package/dist/timeline/hx.d.ts +18 -0
  579. package/dist/timeline/hx.d.ts.map +1 -0
  580. package/dist/timeline/hx.js +10 -0
  581. package/dist/timeline/hx.js.map +1 -0
  582. package/dist/timeline/index.d.ts +152 -0
  583. package/dist/timeline/index.d.ts.map +1 -0
  584. package/dist/timeline/index.js +383 -0
  585. package/dist/timeline/index.js.map +1 -0
  586. package/dist/tray-host/hx.d.ts +24 -0
  587. package/dist/tray-host/hx.d.ts.map +1 -0
  588. package/dist/tray-host/hx.js +25 -0
  589. package/dist/tray-host/hx.js.map +1 -0
  590. package/dist/tray-host/index.d.ts +110 -0
  591. package/dist/tray-host/index.d.ts.map +1 -0
  592. package/dist/tray-host/index.js +191 -0
  593. package/dist/tray-host/index.js.map +1 -0
  594. package/dist/tray-host/manager.d.ts +137 -0
  595. package/dist/tray-host/manager.d.ts.map +1 -0
  596. package/dist/tray-host/manager.js +462 -0
  597. package/dist/tray-host/manager.js.map +1 -0
  598. package/dist/tray-host/notify.d.ts +22 -0
  599. package/dist/tray-host/notify.d.ts.map +1 -0
  600. package/dist/tray-host/notify.js +74 -0
  601. package/dist/tray-host/notify.js.map +1 -0
  602. package/dist/tray-host/protocol.d.ts +106 -0
  603. package/dist/tray-host/protocol.d.ts.map +1 -0
  604. package/dist/tray-host/protocol.js +191 -0
  605. package/dist/tray-host/protocol.js.map +1 -0
  606. package/dist/tree/hx.d.ts +24 -0
  607. package/dist/tree/hx.d.ts.map +1 -0
  608. package/dist/tree/hx.js +25 -0
  609. package/dist/tree/hx.js.map +1 -0
  610. package/dist/tree/index.d.ts +221 -0
  611. package/dist/tree/index.d.ts.map +1 -0
  612. package/dist/tree/index.js +716 -0
  613. package/dist/tree/index.js.map +1 -0
  614. package/dist/tree/internal.d.ts +18 -0
  615. package/dist/tree/internal.d.ts.map +1 -0
  616. package/dist/tree/internal.js +66 -0
  617. package/dist/tree/internal.js.map +1 -0
  618. package/dist/tree/rows.d.ts +177 -0
  619. package/dist/tree/rows.d.ts.map +1 -0
  620. package/dist/tree/rows.js +179 -0
  621. package/dist/tree/rows.js.map +1 -0
  622. package/package.json +166 -12
  623. package/src/ansi/cast.ts +159 -0
  624. package/src/ansi/index.ts +53 -0
  625. package/src/ansi/palette.ts +226 -0
  626. package/src/ansi/parse.ts +780 -0
  627. package/src/ansi/sgr.ts +380 -0
  628. package/src/ansi/utf8.ts +84 -0
  629. package/src/calendar/Calendar.ts +744 -0
  630. package/src/calendar/DatePicker.ts +368 -0
  631. package/src/calendar/dates.ts +307 -0
  632. package/src/calendar/index.ts +51 -0
  633. package/src/charts/components.ts +864 -0
  634. package/src/charts/data.ts +776 -0
  635. package/src/charts/hx.ts +39 -0
  636. package/src/charts/index.ts +99 -0
  637. package/src/charts/node.ts +932 -0
  638. package/src/charts/render.ts +982 -0
  639. package/src/charts/scale.ts +214 -0
  640. package/src/charts/spec.ts +122 -0
  641. package/src/charts/timers.ts +24 -0
  642. package/src/code/hx.ts +51 -0
  643. package/src/code/index.ts +174 -0
  644. package/src/code-editor/completion.ts +161 -0
  645. package/src/code-editor/doc.ts +198 -0
  646. package/src/code-editor/hx.ts +26 -0
  647. package/src/code-editor/index.ts +615 -0
  648. package/src/code-editor/node.ts +1926 -0
  649. package/src/code-language/hljs.ts +302 -0
  650. package/src/code-language/index.ts +51 -0
  651. package/src/code-language/languages/glsl.ts +120 -0
  652. package/src/code-language/languages/javascript.ts +419 -0
  653. package/src/code-language/languages/json.ts +72 -0
  654. package/src/code-language/languages/shell.ts +221 -0
  655. package/src/code-language/languages/sql.ts +165 -0
  656. package/src/code-language/lezer.ts +190 -0
  657. package/src/code-language/registry.ts +66 -0
  658. package/src/code-language/runs.ts +128 -0
  659. package/src/code-language/stream.ts +306 -0
  660. package/src/code-language/textmate.ts +134 -0
  661. package/src/code-language/theme.ts +124 -0
  662. package/src/code-language/timers.ts +36 -0
  663. package/src/code-language/types.ts +252 -0
  664. package/src/codeblock/index.ts +146 -0
  665. package/src/color-picker/ColorField.ts +333 -0
  666. package/src/color-picker/ColorPicker.ts +1069 -0
  667. package/src/color-picker/color.ts +399 -0
  668. package/src/color-picker/index.ts +50 -0
  669. package/src/desktop-calendar/eds.ts +484 -0
  670. package/src/desktop-calendar/ical.ts +119 -0
  671. package/src/desktop-calendar/index.ts +287 -0
  672. package/src/embed/client.ts +311 -0
  673. package/src/embed/host.ts +432 -0
  674. package/src/embed/index.ts +33 -0
  675. package/src/embed/timers.ts +32 -0
  676. package/src/flow/draw.ts +418 -0
  677. package/src/flow/index.ts +473 -0
  678. package/src/flow/model.ts +687 -0
  679. package/src/flow/node.ts +3694 -0
  680. package/src/flow/paths.ts +403 -0
  681. package/src/flow/types.ts +634 -0
  682. package/src/formula/hx.ts +51 -0
  683. package/src/formula/index.ts +243 -0
  684. package/src/formula/katex.ts +209 -0
  685. package/src/formula/layout.ts +876 -0
  686. package/src/formula/node.ts +467 -0
  687. package/src/html/controls.ts +244 -0
  688. package/src/html/css/cascade.ts +606 -0
  689. package/src/html/css/parse.ts +500 -0
  690. package/src/html/css/style.ts +1371 -0
  691. package/src/html/css/ua.ts +174 -0
  692. package/src/html/css/values.ts +358 -0
  693. package/src/html/dom.ts +410 -0
  694. package/src/html/hx.ts +55 -0
  695. package/src/html/index.ts +545 -0
  696. package/src/html/layout/block.ts +876 -0
  697. package/src/html/layout/boxes.ts +981 -0
  698. package/src/html/layout/flex.ts +297 -0
  699. package/src/html/layout/floats.ts +125 -0
  700. package/src/html/layout/inline.ts +870 -0
  701. package/src/html/layout/table.ts +380 -0
  702. package/src/html/node.ts +967 -0
  703. package/src/html/paint.ts +605 -0
  704. package/src/html/resources.ts +214 -0
  705. package/src/index.ts +638 -0
  706. package/src/internal/heights.ts +211 -0
  707. package/src/internal/hx.ts +53 -0
  708. package/src/internal/text.ts +44 -0
  709. package/src/internal/timers.ts +44 -0
  710. package/src/internal/widget.ts +92 -0
  711. package/src/markdown/ast.ts +163 -0
  712. package/src/markdown/hx.ts +51 -0
  713. package/src/markdown/index.ts +686 -0
  714. package/src/markdown/parse.ts +1037 -0
  715. package/src/markdown/spans.ts +143 -0
  716. package/src/media-player/backends.ts +155 -0
  717. package/src/media-player/control.ts +70 -0
  718. package/src/media-player/hx.ts +51 -0
  719. package/src/media-player/index.ts +378 -0
  720. package/src/media-player/mpv.ts +146 -0
  721. package/src/media-player/vlc.ts +97 -0
  722. package/src/richtext/index.ts +42 -0
  723. package/src/richtext/links.ts +78 -0
  724. package/src/richtext/menu.ts +49 -0
  725. package/src/richtext/node.ts +406 -0
  726. package/src/richtext/runs.ts +253 -0
  727. package/src/table/hx.ts +51 -0
  728. package/src/table/index.ts +1219 -0
  729. package/src/table/rows.ts +275 -0
  730. package/src/terminal/backends.ts +242 -0
  731. package/src/terminal/hx.ts +51 -0
  732. package/src/terminal/index.ts +574 -0
  733. package/src/terminal/title.ts +172 -0
  734. package/src/terminal/vt/colors.ts +247 -0
  735. package/src/terminal/vt/diff.ts +467 -0
  736. package/src/terminal/vt/fonts.ts +233 -0
  737. package/src/terminal/vt/index.ts +443 -0
  738. package/src/terminal/vt/keys.ts +369 -0
  739. package/src/terminal/vt/mouse.ts +144 -0
  740. package/src/terminal/vt/node.ts +1242 -0
  741. package/src/terminal/vt/pty.ts +334 -0
  742. package/src/terminal/vt/renderer.ts +555 -0
  743. package/src/terminal/vt/timers.ts +31 -0
  744. package/src/terminal/vt/xterm.ts +193 -0
  745. package/src/terminal-output/hx.ts +51 -0
  746. package/src/terminal-output/index.ts +340 -0
  747. package/src/terminal-output/runs.ts +79 -0
  748. package/src/three/canvas.ts +451 -0
  749. package/src/three/events.ts +197 -0
  750. package/src/three/geometries.ts +429 -0
  751. package/src/three/globals.ts +34 -0
  752. package/src/three/hx.ts +22 -0
  753. package/src/three/index.ts +98 -0
  754. package/src/three/jsx-dev-runtime.ts +27 -0
  755. package/src/three/jsx-runtime.ts +38 -0
  756. package/src/three/jsx.ts +275 -0
  757. package/src/three/materials.ts +270 -0
  758. package/src/three/math.ts +585 -0
  759. package/src/three/objects.ts +397 -0
  760. package/src/three/passes.ts +90 -0
  761. package/src/three/postprocess.ts +677 -0
  762. package/src/three/raycast.ts +189 -0
  763. package/src/three/react-reconciler.d.ts +50 -0
  764. package/src/three/reconciler.ts +624 -0
  765. package/src/three/renderer-direct.ts +1055 -0
  766. package/src/three/renderer-indirect.ts +570 -0
  767. package/src/three/store.ts +207 -0
  768. package/src/timeline/hx.ts +31 -0
  769. package/src/timeline/index.ts +603 -0
  770. package/src/tray-host/hx.ts +51 -0
  771. package/src/tray-host/index.ts +331 -0
  772. package/src/tray-host/manager.ts +639 -0
  773. package/src/tray-host/notify.ts +102 -0
  774. package/src/tray-host/protocol.ts +235 -0
  775. package/src/tree/hx.ts +51 -0
  776. package/src/tree/index.ts +1087 -0
  777. package/src/tree/internal.ts +87 -0
  778. package/src/tree/rows.ts +334 -0
  779. package/src/index.d.ts +0 -2
  780. package/src/index.js +0 -9
  781. package/src/sparkline/index.d.ts +0 -29
  782. package/src/sparkline/index.js +0 -50
  783. package/src/sparkline/node.js +0 -72
@@ -0,0 +1,1242 @@
1
+ // `<vtterm>` — the registered element the vt backend draws into.
2
+ //
3
+ // The division of labour with `./index.ts` mirrors `../../code-editor/`: the
4
+ // component owns process things (resolve the optional dependencies, create
5
+ // the emulator and the pty, wire them together, flow control, the imperative
6
+ // handle), and this node owns pixels and input (cell metrics, layout, the
7
+ // renderer and the mirror, cursor blink, selection, key and mouse encoding
8
+ // through core's default-action seam, clipboard).
9
+ //
10
+ // The consequence worth having: the node is drivable with a fake `term` and
11
+ // no pty at all, which is what makes the whole renderer testable in CI.
12
+ import { CARET_BLINK_MS, Node } from 'react-x11/node';
13
+ import type {
14
+ Context2D,
15
+ MeasureConstraints,
16
+ MeasuredSize,
17
+ } from 'react-x11/node';
18
+ import type { KeyboardEvent, MouseEvent, WheelEvent } from 'react-x11';
19
+ import type { Style } from 'react-x11/style';
20
+ import { Surface } from 'react-x11/ntk';
21
+ import {
22
+ XK_ESCAPE,
23
+ XK_INSERT,
24
+ XK_TAB,
25
+ ctrlChordLetter,
26
+ } from 'react-x11/keysyms';
27
+
28
+ import type { TerminalColors } from '../backends.js';
29
+ import { buildPalette } from './colors.js';
30
+ import type { Palette } from './colors.js';
31
+ import {
32
+ DECO_OVERLINE,
33
+ DECO_STRIKE,
34
+ DECO_UNDERLINE,
35
+ VARIANT_BOLD,
36
+ VARIANT_ITALIC,
37
+ } from './colors.js';
38
+ import {
39
+ Mirror,
40
+ createSnapshot,
41
+ orderSelection,
42
+ readViewport,
43
+ } from './diff.js';
44
+ import type { CursorState, GridSnapshot, SelectionRange } from './diff.js';
45
+ import { FontSet, variantOf } from './fonts.js';
46
+ import type { NtkFonts } from './fonts.js';
47
+ import { encodeKey, encodePaste } from './keys.js';
48
+ import { ENCODING_MODES, encodeAlternateScroll, encodeMouse } from './mouse.js';
49
+ import type { MouseEncoding } from './mouse.js';
50
+ import { createRenderer } from './renderer.js';
51
+ import type {
52
+ CellContext,
53
+ RendererOps,
54
+ RendererStats,
55
+ SurfaceCtor,
56
+ } from './renderer.js';
57
+ import { microtask, startInterval, stopInterval } from './timers.js';
58
+ import type { TimerId } from './timers.js';
59
+ import type { XtermCell, XtermDisposable, XtermTerminal } from './xterm.js';
60
+
61
+ /** The element name — the registration key, `kind`, and the JSX tag. */
62
+ export const ELEMENT = 'vtterm';
63
+
64
+ const DEFAULT_FAMILY = 'monospace';
65
+ const DEFAULT_SIZE = 13;
66
+ /** What a bare `<Terminal>` measures to, in cells. */
67
+ const PREFERRED_COLS = 80;
68
+ const PREFERRED_ROWS = 24;
69
+ /** Wheel notches to lines, the way every terminal counts them. */
70
+ const WHEEL_LINES = 3;
71
+ /** OSC 52 payloads bigger than this are a program misbehaving, not a copy. */
72
+ const MAX_OSC52 = 1_000_000;
73
+ /** What counts as part of a word for double-click selection. */
74
+ const WORD_CHAR = /[\p{L}\p{N}_\-./~+@:]/u;
75
+
76
+ /** The props `<vtterm>` takes. Everything user-facing is on `<Terminal>`. */
77
+ export interface VtTermProps {
78
+ /** The live emulator. Null while the component is still resolving it. */
79
+ term?: XtermTerminal | null;
80
+ /** Bytes the user produced, on their way to the pty. */
81
+ onInput?: (data: string) => void;
82
+ /** The element's box changed size: this many cells now fit. */
83
+ onGridResize?: (cols: number, rows: number) => void;
84
+ onSelectionChange?: (text: string) => void;
85
+ colors?: TerminalColors;
86
+ cursorStyle?: 'block' | 'underline' | 'bar';
87
+ cursorBlink?: boolean;
88
+ /** OSC 52 writes to CLIPBOARD. Reads are never answered — see `_onOsc52`. */
89
+ allowClipboardWrite?: boolean;
90
+ /** The visual bell, mid-flash: the palette runs inverted for a moment.
91
+ * Held by the component so the flash is one state change, not a timer in
92
+ * the node. */
93
+ inverted?: boolean;
94
+ style?: Style | Style[];
95
+ }
96
+
97
+ /** ntk's clipboard, off `app.clipboard`. */
98
+ interface ClipboardLike {
99
+ write(text: string, options?: { selection?: string }): Promise<unknown>;
100
+ read(options?: { selection?: string }): Promise<unknown>;
101
+ }
102
+
103
+ type Grid = { col: number; row: number };
104
+
105
+ export class VtTermNode extends Node {
106
+ private _term: XtermTerminal | null = null;
107
+ private _disposables: XtermDisposable[] = [];
108
+ private _fonts: FontSet | null = null;
109
+ private _fontKey = '';
110
+ private _palette: Palette;
111
+ private _paletteKey = '';
112
+ private _renderer: RendererOps | null = null;
113
+ private _mirror = new Mirror();
114
+ private _snapshot: GridSnapshot | null = null;
115
+ private _workCell: XtermCell | null = null;
116
+ private _cols = 0;
117
+ private _rows = 0;
118
+ private _reportedCols = 0;
119
+ private _reportedRows = 0;
120
+ private _focused = false;
121
+ private _cursorOn = true;
122
+ private _blink: TimerId = null;
123
+ /** Selection anchor and head, in buffer-absolute coordinates. */
124
+ private _anchor: { line: number; col: number } | null = null;
125
+ private _head: { line: number; col: number } | null = null;
126
+ private _selection: SelectionRange | null = null;
127
+ private _dragMode: 'char' | 'word' | 'line' | null = null;
128
+ /** Escape armed one pass-through Tab — the way out of the keyboard trap. */
129
+ private _tabEscapes = false;
130
+ /** Not in `modes`: tracked from DECSET/DECRST (see `_watchModes`). */
131
+ private _mouseEncoding: MouseEncoding = 'default';
132
+ private _alternateScroll = true;
133
+
134
+ constructor(props: Record<string, unknown>, app: unknown) {
135
+ super(ELEMENT, props, app as ConstructorParameters<typeof Node>[2]);
136
+ // Without this nothing ever focuses the terminal and no key reaches it.
137
+ // An app's `focusable`/`tabIndex` prop still overrides either way.
138
+ this.focusableByDefault = true;
139
+ this.defaultCursor = 'text';
140
+ // A terminal drags out a selection of its own, over a cell grid nothing
141
+ // outside it can index (react-x11#291). Saying so keeps a `selectable`
142
+ // document around it from walking in, and keeps the two from both
143
+ // claiming to be showing the application's selection — the same
144
+ // declaration `<textinput>` and `<codeeditor>` make.
145
+ this.hasOwnSelection = true;
146
+ this._palette = buildPalette(paletteColors(this._props()));
147
+ this._paletteKey = paletteKey(this._props());
148
+ this._attach(this._props().term ?? null);
149
+ }
150
+
151
+ private _props(): VtTermProps {
152
+ return this.props as unknown as VtTermProps;
153
+ }
154
+
155
+ // --- props ---------------------------------------------------------------
156
+
157
+ override applyProps(
158
+ next: Record<string, unknown>,
159
+ prev: Record<string, unknown>,
160
+ ): void {
161
+ super.applyProps(next, prev);
162
+ const props = this._props();
163
+
164
+ if (props.term !== (prev.term as XtermTerminal | null | undefined)) {
165
+ this._attach(props.term ?? null);
166
+ }
167
+
168
+ const key = paletteKey(props);
169
+ if (key !== this._paletteKey) {
170
+ this._paletteKey = key;
171
+ this._palette = buildPalette(paletteColors(props));
172
+ // The palette generation is a signature input, so the ordinary diff
173
+ // repaints every cell whose colours actually moved. Nothing else here
174
+ // needs to know a theme changed.
175
+ this._repaint();
176
+ }
177
+
178
+ const { family, size } = this._fontStyle();
179
+ if (`${family}|${size}` !== this._fontKey) {
180
+ this._fonts = null;
181
+ this._mirror.invalidate();
182
+ this.invalidateMeasure('measure');
183
+ this._repaint();
184
+ }
185
+ if (props.cursorBlink !== (prev.cursorBlink as boolean | undefined)) {
186
+ this._syncBlink();
187
+ }
188
+ }
189
+
190
+ override destroySubtree(): void {
191
+ this._detach();
192
+ stopInterval(this._blink);
193
+ this._blink = null;
194
+ this._renderer?.destroy();
195
+ this._renderer = null;
196
+ super.destroySubtree();
197
+ }
198
+
199
+ // --- the emulator --------------------------------------------------------
200
+
201
+ /**
202
+ * Subscribe to everything that means "the screen may look different".
203
+ *
204
+ * Only render-relevant events: the component keeps `onData`, `onTitleChange`
205
+ * and `onBell`, which are about the process rather than about pixels.
206
+ */
207
+ private _attach(term: XtermTerminal | null): void {
208
+ this._detach();
209
+ this._term = term;
210
+ this._mirror.invalidate();
211
+ if (!term) return;
212
+ const dirty = (): void => this._repaint();
213
+ this._disposables.push(
214
+ term.onWriteParsed(dirty),
215
+ term.onScroll(dirty),
216
+ term.onCursorMove(dirty),
217
+ term.onResize(() => {
218
+ this._mirror.invalidate();
219
+ this._repaint();
220
+ }),
221
+ term.buffer.onBufferChange(() => {
222
+ // The alternate screen is a different buffer with a different
223
+ // coordinate origin; nothing on the surface survives the switch.
224
+ this._mirror.invalidate();
225
+ this.clearSelection();
226
+ this._repaint();
227
+ }),
228
+ );
229
+ this._watchModes(term);
230
+ this._workCell = term.buffer.active.getNullCell();
231
+ this._repaint();
232
+ }
233
+
234
+ private _detach(): void {
235
+ for (const d of this._disposables) {
236
+ try {
237
+ d.dispose();
238
+ } catch {
239
+ // a terminal already disposed
240
+ }
241
+ }
242
+ this._disposables.length = 0;
243
+ this._term = null;
244
+ this._workCell = null;
245
+ }
246
+
247
+ /**
248
+ * The two things `modes` does not carry.
249
+ *
250
+ * Mouse *encoding* (SGR 1006, urxvt 1015, UTF-8 1005) and alternate-scroll
251
+ * (1007) are set by DECSET/DECRST and read back nowhere, so a passive CSI
252
+ * observer records them and **returns false** — xterm still processes the
253
+ * sequence itself, and this handler is a listener rather than an
254
+ * implementation. Filed upstream as a request to expose `mouseEncoding`
255
+ * alongside `mouseTrackingMode`.
256
+ */
257
+ private _watchModes(term: XtermTerminal): void {
258
+ const observe = (set: boolean) => (params: (number | number[])[]) => {
259
+ for (const param of params) {
260
+ const value = Array.isArray(param) ? param[0] : param;
261
+ const encoding = ENCODING_MODES[value];
262
+ if (encoding) this._mouseEncoding = set ? encoding : 'default';
263
+ if (value === 1007) this._alternateScroll = set;
264
+ }
265
+ return false;
266
+ };
267
+ try {
268
+ this._disposables.push(
269
+ term.parser.registerCsiHandler(
270
+ { prefix: '?', final: 'h' },
271
+ observe(true),
272
+ ),
273
+ term.parser.registerCsiHandler(
274
+ { prefix: '?', final: 'l' },
275
+ observe(false),
276
+ ),
277
+ term.parser.registerOscHandler(52, (data) => this._onOsc52(data)),
278
+ );
279
+ } catch {
280
+ // a fake terminal in a test that implements only what it needs
281
+ }
282
+ }
283
+
284
+ // --- metrics and layout --------------------------------------------------
285
+
286
+ /**
287
+ * The font, off the **style** rather than off a prop of its own.
288
+ *
289
+ * `fontFamily` and `fontSize` are style properties, and core throws in
290
+ * development on an element that takes one as a flat prop — for good
291
+ * reason: a terminal inheriting the font from the tree above it is what
292
+ * makes `<box style={{ fontSize: 15 }}>` mean what it says. `<Terminal>`'s
293
+ * `fontFamily`/`fontSize` props are folded into this element's style.
294
+ */
295
+ private _fontStyle(): { family: string; size: number } {
296
+ const style = this.style as { fontFamily?: string; fontSize?: number };
297
+ return {
298
+ family: style.fontFamily ?? DEFAULT_FAMILY,
299
+ size: Number(style.fontSize ?? DEFAULT_SIZE),
300
+ };
301
+ }
302
+
303
+ private _fontSet(): FontSet | null {
304
+ const { family, size } = this._fontStyle();
305
+ const key = `${family}|${size}`;
306
+ if (this._fonts && key === this._fontKey) return this._fonts;
307
+ const fonts = (this.app as { fonts?: NtkFonts } | null | undefined)?.fonts;
308
+ if (!fonts) return null;
309
+ this._fontKey = key;
310
+ this._fonts = new FontSet(fonts, family, size);
311
+ this._mirror.invalidate();
312
+ return this._fonts;
313
+ }
314
+
315
+ /**
316
+ * 80×24, or as much of it as is on offer.
317
+ *
318
+ * A terminal in a dialog with nothing else to size it should be a terminal
319
+ * rather than a sliver; flex owns everything past that.
320
+ */
321
+ override measureContent({ width, height }: MeasureConstraints): MeasuredSize {
322
+ const fonts = this._fontSet();
323
+ const cellWidth = fonts?.metrics.cellWidth ?? DEFAULT_SIZE * 0.6;
324
+ const cellHeight = fonts?.metrics.cellHeight ?? DEFAULT_SIZE * 1.2;
325
+ return {
326
+ width: Math.min(PREFERRED_COLS * cellWidth, width),
327
+ height: Math.min(PREFERRED_ROWS * cellHeight, height),
328
+ };
329
+ }
330
+
331
+ /** Cells that fit the content box right now. */
332
+ gridSize(): { cols: number; rows: number } {
333
+ const fonts = this._fontSet();
334
+ const box = this.contentBox();
335
+ if (!fonts) return { cols: PREFERRED_COLS, rows: PREFERRED_ROWS };
336
+ return {
337
+ cols: Math.max(1, Math.floor(box.width / fonts.metrics.cellWidth)),
338
+ rows: Math.max(1, Math.floor(box.height / fonts.metrics.cellHeight)),
339
+ };
340
+ }
341
+
342
+ /**
343
+ * Tell the component the grid changed, off the paint stack.
344
+ *
345
+ * `onGridResize` ends in `term.resize` and `pty.resize`, and both of those
346
+ * can synchronously produce output — running them inside paint would have
347
+ * the emulator writing to a buffer the renderer is halfway through reading.
348
+ */
349
+ resizeToFit(): void {
350
+ const { cols, rows } = this.gridSize();
351
+ if (cols === this._reportedCols && rows === this._reportedRows) return;
352
+ this._reportedCols = cols;
353
+ this._reportedRows = rows;
354
+ const notify = this._props().onGridResize;
355
+ if (notify) microtask(() => !this.destroyed && notify(cols, rows));
356
+ }
357
+
358
+ get cols(): number {
359
+ return this._cols;
360
+ }
361
+
362
+ get rows(): number {
363
+ return this._rows;
364
+ }
365
+
366
+ // --- painting ------------------------------------------------------------
367
+
368
+ private _repaint(): void {
369
+ if (this.destroyed) return;
370
+ // The grid rect, not a tighter one: which cells are dirty is not known
371
+ // until the diff runs inside paint. Damage is a clip and a cull bound
372
+ // rather than a promise to redraw everything, and the diff still decides
373
+ // what is *rendered* — which is where the cost is.
374
+ this.invalidate(false, this, 'text');
375
+ }
376
+
377
+ override paint(ctx: Context2D): void {
378
+ // background, border, and the clip to this node's rect
379
+ super.paint(ctx);
380
+ const fonts = this._fontSet();
381
+ if (!fonts) return;
382
+ // Before the `term` check on purpose: the component sizes the emulator it
383
+ // is still building from what this reports, so the first layout has to
384
+ // reach it even though there is nothing to draw yet.
385
+ this.resizeToFit();
386
+
387
+ const term = this._term;
388
+ if (!term) return;
389
+
390
+ const cell = ctx as CellContext;
391
+ const renderer = this._ensureRenderer(cell);
392
+ if (!renderer) return; // mock backend: no pixel API, so nothing to draw
393
+
394
+ const box = this.contentBox();
395
+ const { cellWidth, cellHeight } = fonts.metrics;
396
+ const fitCols = Math.max(1, Math.floor(box.width / cellWidth));
397
+ const fitRows = Math.max(1, Math.floor(box.height / cellHeight));
398
+ // The emulator resizes a beat later (through the component, off this
399
+ // stack), so draw the intersection until it catches up.
400
+ const cols = Math.max(1, Math.min(fitCols, term.cols));
401
+ const rows = Math.max(1, Math.min(fitRows, term.rows));
402
+ this._cols = cols;
403
+ this._rows = rows;
404
+
405
+ if (!renderer.ensure(cols, rows, fonts.metrics)) this._mirror.invalidate();
406
+ if (
407
+ !this._snapshot ||
408
+ this._snapshot.cols !== cols ||
409
+ this._snapshot.rows !== rows
410
+ ) {
411
+ this._snapshot = createSnapshot(cols, rows);
412
+ this._mirror.invalidate();
413
+ }
414
+
415
+ const snapshot = readViewport(
416
+ term,
417
+ this._snapshot,
418
+ {
419
+ palette: this._palette,
420
+ selection: this._selection,
421
+ cursor: this._cursorState(term, rows),
422
+ brightBold: term.options.drawBoldTextInBrightColors !== false,
423
+ },
424
+ this._workCell ?? undefined,
425
+ );
426
+
427
+ const result = this._mirror.diff(snapshot);
428
+ renderer.begin(cell, {
429
+ originX: box.x,
430
+ originY: box.y,
431
+ cols,
432
+ rows,
433
+ metrics: fonts.metrics,
434
+ });
435
+ if (result.copy) {
436
+ const { srcRow, dstRow, count } = result.copy;
437
+ if (!renderer.copyRows(srcRow, dstRow, count)) {
438
+ // No buffer to move pixels inside: the mirror already moved, so drop
439
+ // it and take a full repaint on the next frame rather than believing
440
+ // a copy that did not happen.
441
+ this._mirror.invalidate();
442
+ this._repaint();
443
+ }
444
+ }
445
+ for (const span of result.spans) {
446
+ this._drawSpan(renderer, snapshot, span, fonts);
447
+ }
448
+ renderer.end();
449
+ }
450
+
451
+ private _ensureRenderer(ctx: CellContext): RendererOps | null {
452
+ if (this._renderer) return this._renderer;
453
+ // `react-x11/ntk` types its re-exports loosely on purpose — ntk ships no
454
+ // types of its own — so the shape this element needs is the structural
455
+ // one in `./renderer.ts`, and this is the one cast that says so.
456
+ this._renderer = createRenderer(
457
+ this.app,
458
+ ctx,
459
+ (Surface ?? null) as unknown as SurfaceCtor | null,
460
+ );
461
+ if (this._renderer?.kind === 'direct') {
462
+ // Nothing is retained between frames: `Node.paint` fills this node's
463
+ // background before we draw, so every frame starts from an empty box.
464
+ this._mirror.invalidate();
465
+ }
466
+ return this._renderer;
467
+ }
468
+
469
+ private _cursorState(term: XtermTerminal, rows: number): CursorState {
470
+ const buffer = term.buffer.active;
471
+ const row = buffer.baseY + buffer.cursorY - buffer.viewportY;
472
+ const props = this._props();
473
+ let shape: CursorState['shape'] =
474
+ props.cursorStyle ?? term.options.cursorStyle ?? 'block';
475
+ if (!this._focused) shape = 'hollow';
476
+ else if (!this._cursorOn) shape = 'none';
477
+ if (row < 0 || row >= rows || buffer.cursorX >= term.cols) {
478
+ shape = 'none';
479
+ }
480
+ return { col: buffer.cursorX, row, shape };
481
+ }
482
+
483
+ /**
484
+ * One dirty span, as three passes over the same cells: backgrounds merged
485
+ * into runs of one colour, one glyph run per non-blank cell, then the
486
+ * decorations. The renderer batches each pass into a single request per
487
+ * colour, so a span of 80 cells is a handful of requests however many
488
+ * colours it carries.
489
+ */
490
+ private _drawSpan(
491
+ renderer: RendererOps,
492
+ snapshot: GridSnapshot,
493
+ span: { row: number; col: number; count: number },
494
+ fonts: FontSet,
495
+ ): void {
496
+ const { row, col, count } = span;
497
+ const base = row * snapshot.cols;
498
+ const end = col + count;
499
+
500
+ let start = col;
501
+ let bg = snapshot.bg[base + col];
502
+ for (let i = col + 1; i < end; i++) {
503
+ const next = snapshot.bg[base + i];
504
+ if (next !== bg) {
505
+ renderer.fillCells(row, start, i - start, bg);
506
+ start = i;
507
+ bg = next;
508
+ }
509
+ }
510
+ renderer.fillCells(row, start, end - start, bg);
511
+
512
+ for (let i = col; i < end; i++) {
513
+ const index = base + i;
514
+ // Width 0 is the second half of a wide glyph: its background is part of
515
+ // the run above, and its glyph was drawn at the cell before it.
516
+ if (snapshot.width[index] === 0) continue;
517
+ const chars = snapshot.chars[index];
518
+ if (!chars || chars === ' ') continue;
519
+ const flags = snapshot.flags[index];
520
+ const run = fonts.run(
521
+ chars,
522
+ variantOf((flags & VARIANT_BOLD) !== 0, (flags & VARIANT_ITALIC) !== 0),
523
+ );
524
+ if (run) renderer.drawRun(row, i, run, snapshot.fg[index]);
525
+ }
526
+
527
+ this._decorateSpan(renderer, snapshot, row, col, end);
528
+ this._drawCursor(renderer, row, col, end);
529
+ }
530
+
531
+ private _decorateSpan(
532
+ renderer: RendererOps,
533
+ snapshot: GridSnapshot,
534
+ row: number,
535
+ col: number,
536
+ end: number,
537
+ ): void {
538
+ const base = row * snapshot.cols;
539
+ const DECO = DECO_UNDERLINE | DECO_STRIKE | DECO_OVERLINE;
540
+ let runStart = -1;
541
+ let runDeco = 0;
542
+ let runFg = 0;
543
+ const flush = (until: number): void => {
544
+ if (runStart < 0 || !runDeco) return;
545
+ const count = until - runStart;
546
+ if (runDeco & DECO_UNDERLINE) {
547
+ renderer.decorate(row, runStart, count, 'underline', runFg);
548
+ }
549
+ if (runDeco & DECO_STRIKE) {
550
+ renderer.decorate(row, runStart, count, 'strike', runFg);
551
+ }
552
+ if (runDeco & DECO_OVERLINE) {
553
+ renderer.decorate(row, runStart, count, 'overline', runFg);
554
+ }
555
+ runStart = -1;
556
+ };
557
+ for (let i = col; i < end; i++) {
558
+ const deco = snapshot.flags[base + i] & DECO;
559
+ const fg = snapshot.fg[base + i];
560
+ if (deco !== runDeco || fg !== runFg) {
561
+ flush(i);
562
+ runDeco = deco;
563
+ runFg = fg;
564
+ runStart = deco ? i : -1;
565
+ }
566
+ }
567
+ flush(end);
568
+ }
569
+
570
+ /** The shapes a colour swap cannot express: bar, underline, and the hollow
571
+ * box an unfocused terminal draws. */
572
+ private _drawCursor(
573
+ renderer: RendererOps,
574
+ row: number,
575
+ col: number,
576
+ end: number,
577
+ ): void {
578
+ const term = this._term;
579
+ if (!term) return;
580
+ const state = this._cursorState(term, this._rows);
581
+ if (state.row !== row || state.col < col || state.col >= end) return;
582
+ switch (state.shape) {
583
+ case 'bar':
584
+ renderer.decorate(row, state.col, 1, 'bar', this._palette.cursor);
585
+ break;
586
+ case 'underline':
587
+ renderer.decorate(
588
+ row,
589
+ state.col,
590
+ 1,
591
+ 'cursorUnderline',
592
+ this._palette.cursor,
593
+ );
594
+ break;
595
+ case 'hollow':
596
+ renderer.decorate(row, state.col, 1, 'box', this._palette.cursor);
597
+ break;
598
+ default:
599
+ break;
600
+ }
601
+ }
602
+
603
+ // --- focus and the cursor blink ------------------------------------------
604
+
605
+ override defaultFocus(): void {
606
+ this._focused = true;
607
+ this._cursorOn = true;
608
+ this._syncBlink();
609
+ this._reportFocus(true);
610
+ this._repaint();
611
+ }
612
+
613
+ override defaultBlur(): void {
614
+ this._focused = false;
615
+ this._cursorOn = true;
616
+ this._syncBlink();
617
+ this._reportFocus(false);
618
+ this._repaint();
619
+ }
620
+
621
+ private _reportFocus(focused: boolean): void {
622
+ if (this._term?.modes.sendFocusMode) {
623
+ this._send(focused ? '\x1b[I' : '\x1b[O');
624
+ }
625
+ }
626
+
627
+ private _syncBlink(): void {
628
+ stopInterval(this._blink);
629
+ this._blink = null;
630
+ const blink = this._props().cursorBlink !== false;
631
+ if (!this._focused || !blink) {
632
+ this._cursorOn = true;
633
+ return;
634
+ }
635
+ // Core's own interval, so two carets on one screen are in step.
636
+ this._blink = startInterval(() => {
637
+ this._cursorOn = !this._cursorOn;
638
+ this._repaint();
639
+ }, CARET_BLINK_MS);
640
+ }
641
+
642
+ // --- input: keyboard -----------------------------------------------------
643
+
644
+ /**
645
+ * The terminal's own key behaviour, run after the application's `onKeyDown`
646
+ * handlers and not at all if one of them called `preventDefault()` — so an
647
+ * app-level chord still beats the terminal, the same bargain the XEmbed
648
+ * path documents.
649
+ *
650
+ * **Tab and the way out.** Core cycles focus on Tab before default actions,
651
+ * and a terminal that consumes Tab owes the keyboard user an exit. The
652
+ * convention `docs/extending.md` asks for is "Escape arms one pass-through
653
+ * Tab", with one terminal-specific twist: Escape is *also* still sent to the
654
+ * program (arming is a side effect, not a swallow), and arming is off while
655
+ * the alternate screen is up — a full-screen vim owns Esc-then-Tab as real
656
+ * input, and a focus-trapped full-screen application is the expected shape.
657
+ * The pointer always leaves.
658
+ */
659
+ override defaultKeyDown(ev: KeyboardEvent): void {
660
+ const term = this._term;
661
+ if (!term) return;
662
+
663
+ if (this._clipboardChord(ev)) {
664
+ ev.preventDefault();
665
+ return;
666
+ }
667
+
668
+ if (ev.keysym === XK_TAB && this._tabEscapes) {
669
+ this._tabEscapes = false;
670
+ return; // this one belongs to the focus cycle
671
+ }
672
+ this._tabEscapes =
673
+ ev.keysym === XK_ESCAPE && term.buffer.active.type !== 'alternate';
674
+
675
+ const bytes = encodeKey(ev, term.modes);
676
+ if (bytes === null) return;
677
+ this._typed();
678
+ this._send(bytes);
679
+ ev.preventDefault();
680
+ }
681
+
682
+ /**
683
+ * The clipboard chords, and why a terminal's are not everyone else's.
684
+ *
685
+ * **Ctrl+C and Ctrl+V are not available.** Ctrl+C is SIGINT — the single
686
+ * most-pressed key in a terminal — and Ctrl+V is readline's literal-next.
687
+ * Both have to reach the program, so every terminal since xterm spells the
688
+ * clipboard with Shift: **Ctrl+Shift+C / Ctrl+Shift+V**, which is what
689
+ * gnome-terminal, konsole, kitty and alacritty all use.
690
+ *
691
+ * Three more are accepted because they cost the program nothing:
692
+ *
693
+ * - **Super+C / Super+V** (Command on a Mac keyboard under XQuartz).
694
+ * `keys.ts` never forwards a Super chord — those belong to the desktop —
695
+ * so nothing is taken from the program by answering them here, and it is
696
+ * the chord a Mac user's fingers already know.
697
+ * - **Shift+Insert** pastes PRIMARY and **Ctrl+Insert** copies to
698
+ * CLIPBOARD: the X convention that predates all of the above and still
699
+ * works everywhere.
700
+ * - **Ctrl+Shift+A** selects the screen. (Not Ctrl+A: that is
701
+ * beginning-of-line, and readline wants it.)
702
+ *
703
+ * The letter comes from core's `ctrlChordLetter`, which is public for
704
+ * exactly this and gets the subtlety right — ntk derives `codepoint` from
705
+ * the *shifted* keysym, so Ctrl+Shift+V arrives as `V` and Ctrl+V as `v`,
706
+ * while the keysym does not shift.
707
+ */
708
+ private _clipboardChord(ev: KeyboardEvent): boolean {
709
+ if (ev.keysym === XK_INSERT && (ev.shiftKey || ev.ctrlKey)) {
710
+ if (ev.shiftKey) this.paste('PRIMARY');
711
+ else this.copySelection();
712
+ return true;
713
+ }
714
+ const clipboardModifier = (ev.ctrlKey && ev.shiftKey) || ev.metaKey;
715
+ if (!clipboardModifier) return false;
716
+ switch (ctrlChordLetter(ev)) {
717
+ case 0x63: // c
718
+ this.copySelection();
719
+ return true;
720
+ case 0x76: // v
721
+ this.paste('CLIPBOARD');
722
+ return true;
723
+ case 0x61: // a
724
+ this.selectAll();
725
+ return true;
726
+ default:
727
+ return false;
728
+ }
729
+ }
730
+
731
+ /**
732
+ * A dead key or a Compose sequence finishing.
733
+ *
734
+ * Composition stays **on** for this element — unlike `<foreign>`, which
735
+ * turns it off because the embedded client has an input method of its own.
736
+ * Here there is no other side: the keys a composition takes never reach
737
+ * `defaultKeyDown`, so without this the text a Compose sequence produced
738
+ * would be typed into nothing. Only the commit is sent; the preedit is not
739
+ * drawn, which is the honest state of IME support in this component (see
740
+ * the PRD's non-goals).
741
+ */
742
+ override defaultComposition(ev: { type: string; data: string }): void {
743
+ if (ev.type !== 'compositionEnd' || !ev.data) return;
744
+ this._typed();
745
+ this._send(ev.data);
746
+ }
747
+
748
+ /** Input scrolls back to the prompt and drops the selection, like every
749
+ * other terminal. */
750
+ private _typed(): void {
751
+ const term = this._term;
752
+ if (!term) return;
753
+ if (term.buffer.active.viewportY !== term.buffer.active.baseY) {
754
+ term.scrollToBottom();
755
+ }
756
+ if (this._selection) this.clearSelection();
757
+ }
758
+
759
+ private _send(data: string): void {
760
+ if (!data) return;
761
+ this._props().onInput?.(data);
762
+ }
763
+
764
+ // --- input: pointer ------------------------------------------------------
765
+
766
+ private _cellAt(ev: { x: number; y: number }): Grid {
767
+ const fonts = this._fontSet();
768
+ const box = this.contentBox();
769
+ const cellWidth = fonts?.metrics.cellWidth ?? 1;
770
+ const cellHeight = fonts?.metrics.cellHeight ?? 1;
771
+ const col = Math.floor((ev.x - box.x) / cellWidth);
772
+ const row = Math.floor((ev.y - box.y) / cellHeight);
773
+ return {
774
+ col: Math.max(0, Math.min(this._cols - 1, col)),
775
+ row: Math.max(0, Math.min(this._rows - 1, row)),
776
+ };
777
+ }
778
+
779
+ private _absLine(row: number): number {
780
+ return (this._term?.buffer.active.viewportY ?? 0) + row;
781
+ }
782
+
783
+ /**
784
+ * Whether this gesture belongs to the program rather than to the user.
785
+ *
786
+ * Shift is the universal override: an application that grabbed the mouse
787
+ * still has to let the user select text, and Shift is how every terminal
788
+ * spells that.
789
+ */
790
+ private _reporting(ev: { shiftKey: boolean }): boolean {
791
+ const tracking = this._term?.modes.mouseTrackingMode ?? 'none';
792
+ return tracking !== 'none' && !ev.shiftKey;
793
+ }
794
+
795
+ override defaultMouseDown(ev: MouseEvent): void {
796
+ const term = this._term;
797
+ if (!term) return;
798
+ this.focus();
799
+ const { col, row } = this._cellAt(ev);
800
+
801
+ if (ev.button === 2 && !this._reporting(ev)) {
802
+ // The X convention: middle-click pastes PRIMARY, as `<textinput>` and
803
+ // `<codeeditor>` do.
804
+ this.paste('PRIMARY');
805
+ ev.preventDefault();
806
+ return;
807
+ }
808
+
809
+ if (this._reporting(ev)) {
810
+ this._send(
811
+ encodeMouse(
812
+ {
813
+ kind: 'down',
814
+ button: ev.button,
815
+ col,
816
+ row,
817
+ shiftKey: ev.shiftKey,
818
+ altKey: ev.altKey,
819
+ ctrlKey: ev.ctrlKey,
820
+ pressed: true,
821
+ },
822
+ {
823
+ tracking: term.modes.mouseTrackingMode,
824
+ encoding: this._mouseEncoding,
825
+ },
826
+ ) ?? '',
827
+ );
828
+ // A program in `drag` or `any` tracking wants the motion that follows,
829
+ // including the part of it that leaves this element — which is what
830
+ // capturing the pointer is for.
831
+ ev.capturePointer();
832
+ ev.preventDefault();
833
+ return;
834
+ }
835
+
836
+ if (ev.button !== 1) return;
837
+ const line = this._absLine(row);
838
+ this._dragMode =
839
+ ev.detail >= 3 ? 'line' : ev.detail === 2 ? 'word' : 'char';
840
+ if (ev.shiftKey && this._anchor) {
841
+ this._head = { line, col };
842
+ } else {
843
+ this._anchor = { line, col };
844
+ this._head = { line, col };
845
+ }
846
+ this._updateSelection();
847
+ ev.capturePointer();
848
+ ev.preventDefault();
849
+ }
850
+
851
+ override defaultMouseDrag(ev: MouseEvent): void {
852
+ const term = this._term;
853
+ if (!term) return;
854
+ const { col, row } = this._cellAt(ev);
855
+ if (this._dragMode === null) {
856
+ if (this._reporting(ev)) {
857
+ this._send(
858
+ encodeMouse(
859
+ {
860
+ kind: 'move',
861
+ button: ev.button,
862
+ col,
863
+ row,
864
+ shiftKey: ev.shiftKey,
865
+ altKey: ev.altKey,
866
+ ctrlKey: ev.ctrlKey,
867
+ pressed: true,
868
+ },
869
+ {
870
+ tracking: term.modes.mouseTrackingMode,
871
+ encoding: this._mouseEncoding,
872
+ },
873
+ ) ?? '',
874
+ );
875
+ }
876
+ return;
877
+ }
878
+ // Dragging past an edge scrolls the scrollback under the pointer.
879
+ const box = this.contentBox();
880
+ if (ev.y < box.y) term.scrollLines(-1);
881
+ else if (ev.y > box.y + box.height) term.scrollLines(1);
882
+ this._head = { line: this._absLine(row), col };
883
+ this._updateSelection();
884
+ }
885
+
886
+ override defaultMouseUp(ev: MouseEvent): void {
887
+ const term = this._term;
888
+ if (term && this._dragMode === null && this._reporting(ev)) {
889
+ const { col, row } = this._cellAt(ev);
890
+ this._send(
891
+ encodeMouse(
892
+ {
893
+ kind: 'up',
894
+ button: ev.button,
895
+ col,
896
+ row,
897
+ shiftKey: ev.shiftKey,
898
+ altKey: ev.altKey,
899
+ ctrlKey: ev.ctrlKey,
900
+ pressed: false,
901
+ },
902
+ {
903
+ tracking: term.modes.mouseTrackingMode,
904
+ encoding: this._mouseEncoding,
905
+ },
906
+ ) ?? '',
907
+ );
908
+ ev.releasePointer();
909
+ return;
910
+ }
911
+ if (this._dragMode === null) return;
912
+ this._dragMode = null;
913
+ ev.releasePointer?.();
914
+ const text = this.selectionText();
915
+ if (text) {
916
+ // PRIMARY on selection end, which is what the middle button pastes.
917
+ this._clipboard()
918
+ ?.write(text, { selection: 'PRIMARY' })
919
+ .catch(() => {});
920
+ this._props().onSelectionChange?.(text);
921
+ }
922
+ }
923
+
924
+ /**
925
+ * The wheel. No default-action seam exists for it, so the component wires
926
+ * `onWheel` to this — the same shape `<CodeEditor>` uses.
927
+ */
928
+ handleWheel(ev: WheelEvent): boolean {
929
+ const term = this._term;
930
+ if (!term) return false;
931
+ const notches = Math.round(ev.deltaY / 48) || (ev.deltaY > 0 ? 1 : -1);
932
+ const lines = notches * WHEEL_LINES;
933
+
934
+ if (this._reporting(ev)) {
935
+ const { col, row } = this._cellAt(ev);
936
+ this._send(
937
+ encodeMouse(
938
+ {
939
+ kind: 'wheel',
940
+ button: 0,
941
+ deltaY: ev.deltaY,
942
+ col,
943
+ row,
944
+ shiftKey: ev.shiftKey,
945
+ altKey: ev.altKey,
946
+ ctrlKey: ev.ctrlKey,
947
+ pressed: false,
948
+ },
949
+ {
950
+ tracking: term.modes.mouseTrackingMode,
951
+ encoding: this._mouseEncoding,
952
+ },
953
+ ) ?? '',
954
+ );
955
+ return true;
956
+ }
957
+
958
+ if (term.buffer.active.type === 'alternate') {
959
+ // An alternate-screen application has no scrollback of its own, so the
960
+ // wheel becomes arrow keys — which is what makes `less` and `man`
961
+ // scroll (DECSET 1007).
962
+ if (!this._alternateScroll) return false;
963
+ this._send(
964
+ encodeAlternateScroll(
965
+ Math.abs(lines),
966
+ lines < 0,
967
+ term.modes.applicationCursorKeysMode,
968
+ ),
969
+ );
970
+ return true;
971
+ }
972
+ term.scrollLines(lines);
973
+ this._repaint();
974
+ return true;
975
+ }
976
+
977
+ // --- selection -----------------------------------------------------------
978
+
979
+ private _updateSelection(): void {
980
+ const term = this._term;
981
+ if (!term || !this._anchor || !this._head) return;
982
+ let { line: aLine, col: aCol } = this._anchor;
983
+ let { line: hLine, col: hCol } = this._head;
984
+
985
+ if (this._dragMode === 'line') {
986
+ aCol = 0;
987
+ hCol = term.cols;
988
+ } else if (this._dragMode === 'word') {
989
+ const a = this._wordRange(aLine, aCol);
990
+ const h = this._wordRange(hLine, hCol);
991
+ const forward = hLine > aLine || (hLine === aLine && hCol >= aCol);
992
+ aCol = forward ? a.from : a.to;
993
+ hCol = forward ? h.to : h.from;
994
+ } else {
995
+ // A drag selects up to *and including* the cell the pointer is over
996
+ // when it moved forwards, which is what makes selecting one character
997
+ // possible at all.
998
+ const forward = hLine > aLine || (hLine === aLine && hCol >= aCol);
999
+ if (forward) hCol += 1;
1000
+ }
1001
+ this._selection = orderSelection(aLine, aCol, hLine, hCol);
1002
+ this._repaint();
1003
+ }
1004
+
1005
+ private _wordRange(line: number, col: number): { from: number; to: number } {
1006
+ const text = this._term?.buffer.active.getLine(line)?.translateToString();
1007
+ if (!text) return { from: col, to: col + 1 };
1008
+ let from = col;
1009
+ let to = col + 1;
1010
+ if (!WORD_CHAR.test(text.charAt(col) || ' ')) return { from, to };
1011
+ while (from > 0 && WORD_CHAR.test(text.charAt(from - 1))) from--;
1012
+ while (to < text.length && WORD_CHAR.test(text.charAt(to))) to++;
1013
+ return { from, to };
1014
+ }
1015
+
1016
+ /** The selected text, reflow-true: a wrapped line joins with no newline. */
1017
+ selectionText(): string | null {
1018
+ const term = this._term;
1019
+ const selection = this._selection;
1020
+ if (!term || !selection) return null;
1021
+ const buffer = term.buffer.active;
1022
+ let out = '';
1023
+ for (let line = selection.startLine; line <= selection.endLine; line++) {
1024
+ const buffered = buffer.getLine(line);
1025
+ if (!buffered) continue;
1026
+ const from = line === selection.startLine ? selection.startCol : 0;
1027
+ const to = line === selection.endLine ? selection.endCol : term.cols;
1028
+ const next = buffer.getLine(line + 1);
1029
+ const wrapped = line < selection.endLine && next?.isWrapped === true;
1030
+ out += buffered.translateToString(!wrapped, from, to);
1031
+ if (line < selection.endLine && !wrapped) out += '\n';
1032
+ }
1033
+ return out.length ? out : null;
1034
+ }
1035
+
1036
+ // `: this`, matching the base declarations core grew in #294 — a subclass
1037
+ // narrowing them to void stops being structurally a DrawnNode.
1038
+ override clearSelection(): this {
1039
+ if (!this._selection && !this._anchor) return this;
1040
+ this._selection = null;
1041
+ this._anchor = null;
1042
+ this._head = null;
1043
+ this._dragMode = null;
1044
+ this._repaint();
1045
+ return this;
1046
+ }
1047
+
1048
+ override selectAll(): this {
1049
+ const term = this._term;
1050
+ if (!term) return this;
1051
+ this._selection = {
1052
+ startLine: 0,
1053
+ startCol: 0,
1054
+ endLine: term.buffer.active.length - 1,
1055
+ endCol: term.cols,
1056
+ };
1057
+ this._repaint();
1058
+ return this;
1059
+ }
1060
+
1061
+ // --- clipboard -----------------------------------------------------------
1062
+
1063
+ private _clipboard(): ClipboardLike | null {
1064
+ return (
1065
+ (this.app as { clipboard?: ClipboardLike } | null | undefined)
1066
+ ?.clipboard ?? null
1067
+ );
1068
+ }
1069
+
1070
+ copySelection(selection = 'CLIPBOARD'): void {
1071
+ const text = this.selectionText();
1072
+ if (!text) return;
1073
+ this._clipboard()
1074
+ ?.write(text, { selection })
1075
+ .catch(() => {});
1076
+ }
1077
+
1078
+ paste(selection = 'CLIPBOARD'): void {
1079
+ const term = this._term;
1080
+ if (!term) return;
1081
+ this._clipboard()
1082
+ ?.read({ selection })
1083
+ .then((text) => {
1084
+ if (this.destroyed || typeof text !== 'string' || !text) return;
1085
+ this._typed();
1086
+ this._send(encodePaste(text, term.modes.bracketedPasteMode));
1087
+ })
1088
+ .catch(() => {});
1089
+ }
1090
+
1091
+ /**
1092
+ * OSC 52 — the program asking for the clipboard.
1093
+ *
1094
+ * **Writes** are honoured (that is how `tmux`, `vim` and `nvim` copy out of
1095
+ * an ssh session, and it is the whole point of the sequence), capped, and
1096
+ * CLIPBOARD only. **Reads are answered with nothing, always**: replying
1097
+ * would hand whatever the user last copied — a password, a token — to a
1098
+ * program that merely printed eight bytes, so the answer is the same one
1099
+ * kitty and iTerm ship by default.
1100
+ */
1101
+ private _onOsc52(data: string): boolean {
1102
+ if (this._props().allowClipboardWrite === false) return true;
1103
+ const semi = data.indexOf(';');
1104
+ if (semi < 0) return true;
1105
+ const payload = data.slice(semi + 1);
1106
+ if (payload === '?' || payload.length > MAX_OSC52) return true;
1107
+ const text = decodeBase64(payload);
1108
+ if (text === null) return true;
1109
+ this._clipboard()
1110
+ ?.write(text, { selection: 'CLIPBOARD' })
1111
+ .catch(() => {});
1112
+ return true;
1113
+ }
1114
+
1115
+ // --- the handle's half ---------------------------------------------------
1116
+
1117
+ scrollLines(amount: number): void {
1118
+ this._term?.scrollLines(amount);
1119
+ this._repaint();
1120
+ }
1121
+
1122
+ scrollToBottom(): void {
1123
+ this._term?.scrollToBottom();
1124
+ this._repaint();
1125
+ }
1126
+
1127
+ /** The visible screen as text — "copy all", and what the tests read. */
1128
+ serialize(): string | null {
1129
+ const term = this._term;
1130
+ if (!term) return null;
1131
+ const buffer = term.buffer.active;
1132
+ const lines: string[] = [];
1133
+ for (let row = 0; row < term.rows; row++) {
1134
+ lines.push(
1135
+ buffer.getLine(buffer.viewportY + row)?.translateToString(true) ?? '',
1136
+ );
1137
+ }
1138
+ // Trailing blank lines are the empty part of the screen, not content.
1139
+ while (lines.length && lines[lines.length - 1] === '') lines.pop();
1140
+ return lines.join('\n');
1141
+ }
1142
+
1143
+ /** The renderer in use, and what the last frame cost — the draw-op budget
1144
+ * assertions read this. */
1145
+ get rendererStats(): {
1146
+ kind: string;
1147
+ stats: RendererStats;
1148
+ totals: RendererStats;
1149
+ } {
1150
+ const empty: RendererStats = {
1151
+ fillRequests: 0,
1152
+ glyphRequests: 0,
1153
+ copies: 0,
1154
+ blits: 0,
1155
+ cellsFilled: 0,
1156
+ glyphsDrawn: 0,
1157
+ };
1158
+ const renderer = this._renderer;
1159
+ return {
1160
+ kind: renderer?.kind ?? 'none',
1161
+ stats: renderer?.stats ?? empty,
1162
+ totals: renderer?.totals ?? { ...empty },
1163
+ };
1164
+ }
1165
+ }
1166
+
1167
+ /**
1168
+ * The visual bell as a palette, rather than as a second drawing path: the
1169
+ * flash is background and foreground swapped, which every cell picks up
1170
+ * through the ordinary resolve-and-diff and nothing else has to know about.
1171
+ */
1172
+ function paletteColors(props: VtTermProps): TerminalColors | undefined {
1173
+ const colors = props.colors;
1174
+ if (!props.inverted) return colors;
1175
+ return {
1176
+ ...colors,
1177
+ background: colors?.foreground ?? '#e6e6e6',
1178
+ foreground: colors?.background ?? '#101014',
1179
+ };
1180
+ }
1181
+
1182
+ /** Everything about the palette that could change what a cell looks like. */
1183
+ function paletteKey(props: VtTermProps): string {
1184
+ const colors = props.colors;
1185
+ return [
1186
+ props.inverted ? 'inverted' : '',
1187
+ colors?.background ?? '',
1188
+ colors?.foreground ?? '',
1189
+ colors?.cursor ?? '',
1190
+ (colors?.palette ?? []).join(','),
1191
+ ].join('|');
1192
+ }
1193
+
1194
+ const B64 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
1195
+
1196
+ /**
1197
+ * Base64 to UTF-8, by hand.
1198
+ *
1199
+ * `atob` and `Buffer` are both globals the build may not name (`types: []`),
1200
+ * and reaching for one through `globalThis` for twenty lines of table lookup
1201
+ * is more machinery than the table.
1202
+ */
1203
+ function decodeBase64(input: string): string | null {
1204
+ const clean = input.replace(/[^A-Za-z0-9+/=]/g, '');
1205
+ const bytes: number[] = [];
1206
+ let buffer = 0;
1207
+ let bits = 0;
1208
+ for (const char of clean) {
1209
+ if (char === '=') break;
1210
+ const value = B64.indexOf(char);
1211
+ if (value < 0) return null;
1212
+ buffer = (buffer << 6) | value;
1213
+ bits += 6;
1214
+ if (bits >= 8) {
1215
+ bits -= 8;
1216
+ bytes.push((buffer >> bits) & 0xff);
1217
+ }
1218
+ }
1219
+ // UTF-8 by hand too, for the same reason `TextDecoder` is not named here.
1220
+ let out = '';
1221
+ for (let i = 0; i < bytes.length;) {
1222
+ const b = bytes[i];
1223
+ let cp = b;
1224
+ let extra = 0;
1225
+ if (b >= 0xf0) {
1226
+ cp = b & 0x07;
1227
+ extra = 3;
1228
+ } else if (b >= 0xe0) {
1229
+ cp = b & 0x0f;
1230
+ extra = 2;
1231
+ } else if (b >= 0xc0) {
1232
+ cp = b & 0x1f;
1233
+ extra = 1;
1234
+ }
1235
+ i++;
1236
+ for (let k = 0; k < extra && i < bytes.length; k++, i++) {
1237
+ cp = (cp << 6) | (bytes[i] & 0x3f);
1238
+ }
1239
+ out += String.fromCodePoint(cp);
1240
+ }
1241
+ return out;
1242
+ }