@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,967 @@
1
+ // `<htmlview>` — the retained element behind `<Html>`.
2
+ //
3
+ // It owns the whole pipeline and, more importantly, owns **when each stage
4
+ // runs**. That is the component's reason to exist, so it is worth stating in
5
+ // one place:
6
+ //
7
+ // source changed → parse (incrementally), style, box, lay out, paint
8
+ // stylesheet arrived → style, box, lay out, paint
9
+ // DOM mutated → box, lay out, paint
10
+ // width changed → lay out, paint (no parse, no cascade)
11
+ // media band crossed → style, box, lay out, paint
12
+ // scrolled / exposed → paint, culled to the damage rect
13
+ //
14
+ // Each row is strictly cheaper than the one above it, and the two the
15
+ // component is measured on — first content painted, and what an expose or a
16
+ // resize costs — are the two cheapest. Nothing in a computed style depends on
17
+ // the width (see css/values.ts) and nothing in a box tree depends on the
18
+ // scroll, which is what makes the table true rather than aspirational.
19
+ //
20
+ // **Why one element rather than a tree of `<box>`es and `<richtext>`s**, the
21
+ // way `<Markdown>` is built. Two reasons, and the second is the load-bearing
22
+ // one:
23
+ //
24
+ // 1. A document of any size is thousands of elements. Reconciling them
25
+ // through React and laying them out through yoga, per keystroke of a
26
+ // streaming document, is the cost this is trying not to pay.
27
+ // 2. **CSS layout is not the host's layout.** react-x11 lays out with yoga,
28
+ // which is flexbox; block flow with margin collapsing, floats, an inline
29
+ // formatting context and table column sizing are not expressible in it.
30
+ // Composing would mean approximating the layout model, which is what
31
+ // ntk's `HtmlView` did and what makes it hard to trust. So the element
32
+ // draws — the same call `<Flow>` makes for a different reason — and the
33
+ // things that must be real widgets (form controls) are mounted beside it
34
+ // rather than inside it.
35
+ //
36
+ // What is reused from `<richtext>` is everything that was not about the
37
+ // element: the `TextRun` vocabulary, the per-run decoration painter, and the
38
+ // bidi-correct selection bands. See `src/richtext/runs.ts`.
39
+ import { registerElement, registeredElements } from 'react-x11/host';
40
+ import { Node } from 'react-x11/node';
41
+ import type {
42
+ Context2D,
43
+ MeasureConstraints,
44
+ MeasuredSize,
45
+ } from 'react-x11/node';
46
+ import type { MouseEvent as X11MouseEvent, Rect } from 'react-x11';
47
+ import type { Style } from 'react-x11/style';
48
+ import type { Element } from 'domhandler';
49
+
50
+ import { codePointAtOffset, codeUnitOffsets } from '../internal/text.js';
51
+ import { attr, HtmlSource, isElement, tagOf } from './dom.js';
52
+ import type { Document } from './dom.js';
53
+ import { Cascade } from './css/cascade.js';
54
+ import { parseStylesheet } from './css/parse.js';
55
+ import type { Stylesheet } from './css/parse.js';
56
+ import { uaStylesheet } from './css/ua.js';
57
+ import type { RootLook } from './css/style.js';
58
+ import { buildBoxes } from './layout/boxes.js';
59
+ import type { Box, BoxTree, ReplacedKind } from './layout/boxes.js';
60
+ import { layoutDocument } from './layout/block.js';
61
+ import type { FontsLike } from './layout/inline.js';
62
+ // Through the inline module rather than a second cache: the offsets table for
63
+ // a layout is built once, on the first selection that needs it.
64
+ import { layoutOffsets as layoutOffsetsOf } from './layout/inline.js';
65
+ import { lineBands as bandsFor } from '../richtext/runs.js';
66
+ import { paintDocument, queryChildIndex } from './paint.js';
67
+ import type { PaintContext } from './paint.js';
68
+ import { controlRectsOf, measureControl } from './controls.js';
69
+ import type { ControlRect } from './controls.js';
70
+ import { ResourceStore } from './resources.js';
71
+ import type { ResourceRequest, ResourceResult } from './resources.js';
72
+
73
+ /** The element name — registration key, `node.kind` and JSX tag alike. */
74
+ export const ELEMENT = 'htmlview';
75
+
76
+ /** The ntk connection a node is built against, derived from `Node`'s own
77
+ * constructor rather than named, so it cannot drift from core's. */
78
+ export type NtkApp = ConstructorParameters<typeof Node>[2];
79
+
80
+ /** What a `<script>` hands the host. Never parsed and never evaluated —
81
+ * the seam exists so an application can decide, not so this can pretend. */
82
+ export interface ScriptRequest {
83
+ /** The `type` attribute, lowercased; `'text/javascript'` when absent. */
84
+ type: string;
85
+ /** `src`, for an external script. */
86
+ src: string | null;
87
+ /** The element's text, for an inline one. Handed over verbatim. */
88
+ text: string;
89
+ element: Element;
90
+ }
91
+
92
+ export interface HtmlViewProps {
93
+ source: string;
94
+ /** False while more source may still arrive. */
95
+ complete?: boolean;
96
+ /** Author stylesheets applied after the document's own. */
97
+ stylesheet?: string | string[];
98
+ look: RootLook;
99
+ selectionColor?: string;
100
+ onResource?: (
101
+ request: ResourceRequest,
102
+ ) => Promise<ResourceResult | null> | ResourceResult | null;
103
+ onScript?: (script: ScriptRequest) => void;
104
+ /** Where the real widgets go, in the element's own coordinates. */
105
+ onControls?: (rects: ControlRect[]) => void;
106
+ /** The parsed document, once per parse — the DOM handle. */
107
+ onDocument?: (document: Document) => void;
108
+ /** Bumped by the component to force a re-read of a mutated DOM. */
109
+ domRevision?: number;
110
+ style?: Style | Style[];
111
+ }
112
+
113
+ export function registerHtmlView(): void {
114
+ if (registeredElements().includes(ELEMENT)) return;
115
+ registerElement(ELEMENT, {
116
+ create: (props, app) => new HtmlViewNode(props, app),
117
+ // `source` and `look` are this element's own vocabulary and neither is a
118
+ // style name today; declaring them keeps the DEV flat-style-prop
119
+ // assertion honest if core's vocabulary grows underneath us.
120
+ semanticNames: ['source', 'look', 'stylesheet', 'complete'],
121
+ childrenAllowed: false,
122
+ });
123
+ }
124
+
125
+ /** What changed, and therefore how far back up the pipeline to go. */
126
+ const enum Stale {
127
+ Nothing = 0,
128
+ Layout = 1,
129
+ Boxes = 2,
130
+ Style = 3,
131
+ Everything = 4,
132
+ }
133
+
134
+ export class HtmlViewNode extends Node {
135
+ private _source = new HtmlSource();
136
+ private _resources: ResourceStore;
137
+ private _cascade: Cascade | null = null;
138
+ private _tree: BoxTree | null = null;
139
+ private _stale: Stale = Stale.Everything;
140
+ private _laidOutAt = -1;
141
+ private _mediaBand = -1;
142
+ private _documentHeight = 0;
143
+ private _documentWidth = 0;
144
+ private _textPoints: number[] | null = null;
145
+ /** Whether code points and code units are the same index — true unless
146
+ * the text carries surrogate pairs. null until checked. */
147
+ private _pointsAreUnits: boolean | null = null;
148
+ private _hovered: Element[] = [];
149
+ private _scriptsSeen = new WeakSet<Element>();
150
+ private _controls: ControlRect[] = [];
151
+ private _reportedDomRevision = -1;
152
+
153
+ constructor(props: Record<string, unknown>, app: NtkApp) {
154
+ super(ELEMENT, props, app);
155
+ this._resources = new ResourceStore(
156
+ (request) => this._props().onResource?.(request) ?? null,
157
+ () => {
158
+ // A late resource changes intrinsic sizes, so the box tree is what
159
+ // has to be rebuilt — not merely repainted. An image that arrives
160
+ // after first paint is the ordinary case, not an error path.
161
+ this._invalidate(Stale.Boxes);
162
+ },
163
+ );
164
+ this._read();
165
+ }
166
+
167
+ private _props(): HtmlViewProps {
168
+ return this.props as unknown as HtmlViewProps;
169
+ }
170
+
171
+ // --- the pipeline ---------------------------------------------------------
172
+
173
+ private _invalidate(stale: Stale): void {
174
+ if (stale > this._stale) this._stale = stale;
175
+ if (stale >= Stale.Layout) this.invalidateMeasure('content');
176
+ this.invalidate(stale >= Stale.Layout, this, 'props');
177
+ }
178
+
179
+ /** Take the props' source into the parser. Cheap when nothing changed, and
180
+ * an append when the new source extends the old — see `HtmlSource`. */
181
+ private _read(): void {
182
+ const props = this._props();
183
+ const changed = this._source.setSource(
184
+ props.source ?? '',
185
+ props.complete !== false,
186
+ );
187
+ if (changed) {
188
+ this._invalidate(Stale.Style);
189
+ props.onDocument?.(this._source.document);
190
+ this._reportedDomRevision = props.domRevision ?? 0;
191
+ }
192
+ this._sweep();
193
+ }
194
+
195
+ /**
196
+ * Hand the document's own declarations to the host: every `<script>` once,
197
+ * and every resource that has not been asked for.
198
+ *
199
+ * Scripts are **never parsed and never run**. The seam is the whole of the
200
+ * feature: an application that wants scripting brings its own engine and
201
+ * its own policy, and one that does not gets a document that cannot
202
+ * surprise it. There is no configuration in between, because a renderer
203
+ * that half-runs a script is a renderer nobody can reason about.
204
+ */
205
+ private _sweep(): void {
206
+ const props = this._props();
207
+ const facts = this._source.facts();
208
+ if (props.onScript) {
209
+ for (const el of facts.scripts) {
210
+ if (this._scriptsSeen.has(el)) continue;
211
+ this._scriptsSeen.add(el);
212
+ props.onScript({
213
+ type: (attr(el, 'type') ?? 'text/javascript').toLowerCase(),
214
+ src: attr(el, 'src') ?? null,
215
+ text: textOf(el),
216
+ element: el,
217
+ });
218
+ }
219
+ }
220
+ for (const el of facts.resources) {
221
+ const tag = tagOf(el);
222
+ const url = tag === 'link' ? attr(el, 'href') : attr(el, 'src');
223
+ if (!url) continue;
224
+ this._resources.request({
225
+ url,
226
+ kind: tag === 'link' ? 'stylesheet' : 'image',
227
+ element: el,
228
+ });
229
+ }
230
+ }
231
+
232
+ /** Rebuild the cascade — the document's sheets plus the host's. */
233
+ private _restyle(width: number): void {
234
+ const props = this._props();
235
+ const sheets: Stylesheet[] = [uaStylesheet(props.look)];
236
+ let order = 0;
237
+ for (const ref of this._source.facts().sheets) {
238
+ const text =
239
+ ref.kind === 'inline'
240
+ ? ref.text
241
+ : this._resources.stylesheetText(ref.href);
242
+ if (!text) continue;
243
+ const sheet = parseStylesheet(text, order);
244
+ order += sheet.rules.length + 1;
245
+ // `@import` is a resource like any other, and its rules sit *before*
246
+ // the importing sheet's — so a fetched import is spliced in ahead.
247
+ for (const url of sheet.imports) {
248
+ this._resources.request({
249
+ url,
250
+ kind: 'stylesheet',
251
+ element: ref.element,
252
+ });
253
+ const imported = this._resources.stylesheetText(url);
254
+ if (imported) {
255
+ const parsed = parseStylesheet(imported, order);
256
+ order += parsed.rules.length + 1;
257
+ sheets.push(parsed);
258
+ }
259
+ }
260
+ sheets.push(sheet);
261
+ }
262
+ const extra = props.stylesheet;
263
+ for (const text of Array.isArray(extra) ? extra : extra ? [extra] : []) {
264
+ const sheet = parseStylesheet(text, order);
265
+ order += sheet.rules.length + 1;
266
+ sheets.push(sheet);
267
+ }
268
+ this._cascade = new Cascade(
269
+ sheets,
270
+ props.look,
271
+ width,
272
+ this._viewportHeight(),
273
+ );
274
+ this._cascade.setPointer({
275
+ hovered: new Set(this._hovered),
276
+ active: EMPTY_SET,
277
+ });
278
+ this._mediaBand = this._cascade.mediaBand(width);
279
+ }
280
+
281
+ private _viewportHeight(): number {
282
+ // The viewport a `vh` resolves against is the window's, not the
283
+ // document's — a document taller than the window does not make `100vh`
284
+ // taller with it.
285
+ const root = this.root;
286
+ const height = root?.abs?.height;
287
+ return height && height > 0 ? height : 600;
288
+ }
289
+
290
+ private _fonts(): FontsLike | null {
291
+ const fonts = (this.app as { fonts?: FontsLike } | null)?.fonts;
292
+ return fonts ?? null;
293
+ }
294
+
295
+ /** Bring the pipeline up to date for a width. */
296
+ private _prepare(width: number): void {
297
+ const target = Math.max(1, Math.floor(width));
298
+ const props = this._props();
299
+ if ((props.domRevision ?? 0) !== this._reportedDomRevision) {
300
+ this._reportedDomRevision = props.domRevision ?? 0;
301
+ this._source.touch();
302
+ this._sweep();
303
+ if (this._stale < Stale.Style) this._stale = Stale.Style;
304
+ }
305
+ if (this._stale === Stale.Nothing && this._laidOutAt === target) return;
306
+
307
+ if (this._stale >= Stale.Style || !this._cascade) {
308
+ this._restyle(target);
309
+ this._stale = Math.max(this._stale, Stale.Boxes) as Stale;
310
+ } else if (this._cascade.mediaBand(target) !== this._mediaBand) {
311
+ // A resize that crossed a `@media` breakpoint is the one resize that
312
+ // does have to restyle. Knowing which resizes those are is why the
313
+ // breakpoints are collected at parse time.
314
+ this._restyle(target);
315
+ this._stale = Math.max(this._stale, Stale.Boxes) as Stale;
316
+ }
317
+
318
+ const cascade = this._cascade;
319
+ if (!cascade) return;
320
+ cascade.viewportWidth = target;
321
+ cascade.viewportHeight = this._viewportHeight();
322
+
323
+ if (this._stale >= Stale.Boxes || !this._tree) {
324
+ const props = this._props();
325
+ this._tree = buildBoxes(this._source.document, {
326
+ cascade,
327
+ imageSize: (el) => this._resources.imageSize(attr(el, 'src') ?? ''),
328
+ controlSize: (el, kind, style) =>
329
+ measureControl(el, kind, style, this._fonts(), props.look),
330
+ });
331
+ this._textPoints = null;
332
+ this._pointsAreUnits = null;
333
+ this._laidOutAt = -1;
334
+ }
335
+
336
+ if (
337
+ this._tree &&
338
+ (this._laidOutAt !== target || this._stale >= Stale.Layout)
339
+ ) {
340
+ const result = layoutDocument(
341
+ this._tree,
342
+ this._fonts(),
343
+ target,
344
+ this._viewportHeight(),
345
+ );
346
+ this._documentWidth = result.width;
347
+ this._documentHeight = result.height;
348
+ this._laidOutAt = target;
349
+ this._reportControls();
350
+ }
351
+ this._stale = Stale.Nothing;
352
+ }
353
+
354
+ private _reportControls(): void {
355
+ const tree = this._tree;
356
+ const report = this._props().onControls;
357
+ if (!tree || !report) return;
358
+ const rects = controlRectsOf(tree);
359
+ if (sameRects(rects, this._controls)) return;
360
+ this._controls = rects;
361
+ report(rects);
362
+ }
363
+
364
+ // --- core's questions -----------------------------------------------------
365
+
366
+ /**
367
+ * The size the document comes to at the offered width.
368
+ *
369
+ * The element sizes to its content and the application scrolls it — a
370
+ * `<box overflow="scroll">` around it, the same shape `<Markdown>` uses.
371
+ * That keeps the form controls mounted beside it scrolling with it for
372
+ * free, and core's scroller already blits. Virtualizing a document taller
373
+ * than X11's 16-bit coordinate space is the phase-2 work; see the PRD.
374
+ */
375
+ override measureContent({ width }: MeasureConstraints): MeasuredSize {
376
+ const offered = Number.isFinite(width) ? width : 800;
377
+ this._prepare(offered);
378
+ return {
379
+ width: Math.ceil(Math.min(this._documentWidth, offered)),
380
+ height: Math.ceil(this._documentHeight),
381
+ };
382
+ }
383
+
384
+ override applyProps(
385
+ nextProps: Record<string, unknown>,
386
+ prevProps: Record<string, unknown>,
387
+ ): void {
388
+ super.applyProps(nextProps, prevProps);
389
+ const next = nextProps as unknown as HtmlViewProps;
390
+ const prev = prevProps as unknown as HtmlViewProps;
391
+ if (next.look !== prev.look || next.stylesheet !== prev.stylesheet) {
392
+ this._invalidate(Stale.Style);
393
+ }
394
+ if (next.source !== prev.source || next.complete !== prev.complete) {
395
+ this._read();
396
+ } else if ((next.domRevision ?? 0) !== (prev.domRevision ?? 0)) {
397
+ this._invalidate(Stale.Style);
398
+ }
399
+ }
400
+
401
+ override destroySubtree(): void {
402
+ this._resources.destroy();
403
+ this._source.destroy();
404
+ this._tree = null;
405
+ this._cascade = null;
406
+ super.destroySubtree();
407
+ }
408
+
409
+ // --- answering for our own text -------------------------------------------
410
+ //
411
+ // The four accessors from react-x11#291, over the whole document at once.
412
+ // A single element answering for every paragraph is what makes a drag from
413
+ // the first heading to the last table cell one contiguous selection with no
414
+ // per-block plumbing — and it is only possible because the box tree already
415
+ // gave every piece of text its slice of one index.
416
+ //
417
+ // Core counts in **code points**; the boxes count in code units, because
418
+ // that is what ntk's run geometry speaks. The conversion is here, once.
419
+
420
+ override textContent(): string {
421
+ return this._tree?.text ?? '';
422
+ }
423
+
424
+ /**
425
+ * Whether the document's code-point and code-unit indices coincide.
426
+ *
427
+ * They differ only where the text carries surrogate pairs (code points
428
+ * past U+FFFF — emoji, mostly), and the offsets table that converts
429
+ * between them costs O(text): tens of milliseconds and a table entry per
430
+ * character on a megabyte-scale document, rebuilt on every DOM change.
431
+ * A regex scan answers "are there any" in a fraction of that, with no
432
+ * allocation, so the common all-BMP document never builds the table.
433
+ */
434
+ private _identityIndex(): boolean {
435
+ if (this._pointsAreUnits === null) {
436
+ this._pointsAreUnits = !/[\uD800-\uDFFF]/.test(this.textContent());
437
+ }
438
+ return this._pointsAreUnits;
439
+ }
440
+
441
+ private _points(): number[] {
442
+ if (!this._textPoints)
443
+ this._textPoints = codeUnitOffsets(this.textContent());
444
+ return this._textPoints;
445
+ }
446
+
447
+ private _toUnits(codePoint: number): number {
448
+ if (this._identityIndex()) {
449
+ return Math.max(0, Math.min(codePoint, this.textContent().length));
450
+ }
451
+ const offsets = this._points();
452
+ const at = Math.max(0, Math.min(codePoint, offsets.length - 1));
453
+ return offsets[at];
454
+ }
455
+
456
+ private _toPoints(codeUnit: number): number {
457
+ if (this._identityIndex()) {
458
+ return Math.max(0, Math.min(codeUnit, this.textContent().length));
459
+ }
460
+ return codePointAtOffset(this._points(), codeUnit);
461
+ }
462
+
463
+ override textIndexAt(x: number, y: number): number {
464
+ const tree = this._tree;
465
+ if (!tree) return 0;
466
+ const local = this._toDocument(x, y);
467
+ const hit = nearestText(tree.root, local.x, local.y);
468
+ if (!hit) return 0;
469
+ return this._toPoints(hit);
470
+ }
471
+
472
+ override textCaretRect(index: number): Rect | null {
473
+ const tree = this._tree;
474
+ if (!tree) return null;
475
+ const units = this._toUnits(index);
476
+ const found = caretAt(tree.root, units);
477
+ if (!found) return null;
478
+ return {
479
+ x: this.abs.x + found.x,
480
+ y: this.abs.y + found.y,
481
+ width: 0,
482
+ height: found.height,
483
+ };
484
+ }
485
+
486
+ override textRangeRects(start: number, end: number): Rect[] {
487
+ const tree = this._tree;
488
+ if (!tree) return [];
489
+ const from = this._toUnits(start);
490
+ const to = this._toUnits(end);
491
+ if (to <= from) return [];
492
+ const out: Rect[] = [];
493
+ collectBands(tree.root, from, to, this.abs.x, this.abs.y, out);
494
+ return out;
495
+ }
496
+
497
+ // --- pointer --------------------------------------------------------------
498
+
499
+ /** The link under a point, if any. Not part of the selection seam: core
500
+ * deliberately left hover and `cursorAt` out of #291, so following a link
501
+ * stays this package's. */
502
+ hrefAtPoint(x: number, y: number): string | null {
503
+ const el = this.elementAtPoint(x, y);
504
+ let node: Element | null = el;
505
+ while (node) {
506
+ const href = attr(node, 'href');
507
+ if (href && (tagOf(node) === 'a' || tagOf(node) === 'area')) return href;
508
+ node = isElement(node.parent) ? node.parent : null;
509
+ }
510
+ return null;
511
+ }
512
+
513
+ /** The deepest element whose box contains a window-space point. */
514
+ elementAtPoint(x: number, y: number): Element | null {
515
+ const tree = this._tree;
516
+ if (!tree) return null;
517
+ const local = this._toDocument(x, y);
518
+ return deepestAt(tree.root, local.x, local.y);
519
+ }
520
+
521
+ /**
522
+ * The pointer moved. Returns true when the cascade's answer could have
523
+ * changed, so the caller knows whether to invalidate — which it only ever
524
+ * does for a document that actually contains a `:hover` rule.
525
+ */
526
+ setHover(x: number, y: number): boolean {
527
+ const cascade = this._cascade;
528
+ if (!cascade || !cascade.hoverSensitive) return false;
529
+ const chain: Element[] = [];
530
+ let node = this.elementAtPoint(x, y);
531
+ while (node) {
532
+ chain.push(node);
533
+ node = isElement(node.parent) ? node.parent : null;
534
+ }
535
+ if (sameChain(chain, this._hovered)) return false;
536
+ this._hovered = chain;
537
+ cascade.setPointer({ hovered: new Set(chain), active: EMPTY_SET });
538
+ this._invalidate(Stale.Boxes);
539
+ return true;
540
+ }
541
+
542
+ clearHover(): boolean {
543
+ if (!this._hovered.length) return false;
544
+ this._hovered = [];
545
+ this._cascade?.setPointer({ hovered: new Set(), active: EMPTY_SET });
546
+ this._invalidate(Stale.Boxes);
547
+ return true;
548
+ }
549
+
550
+ /** The document, for an application that wants to read or change it. */
551
+ get document(): Document {
552
+ return this._source.document;
553
+ }
554
+
555
+ /**
556
+ * An application changed the DOM under us. Restyles, re-lays-out and
557
+ * repaints — everything but the parse, which nothing that happened to the
558
+ * tree can invalidate.
559
+ *
560
+ * Explicit rather than observed: see `HtmlHandle.refresh`.
561
+ */
562
+ touchDocument(): void {
563
+ this._source.touch();
564
+ this._sweep();
565
+ this._invalidate(Stale.Style);
566
+ }
567
+
568
+ /** The document's `<title>`, when it had one. */
569
+ get title(): string | null {
570
+ return this._source.facts().title;
571
+ }
572
+
573
+ private _toDocument(x: number, y: number): { x: number; y: number } {
574
+ return { x: x - this.abs.x, y: y - this.abs.y };
575
+ }
576
+
577
+ // --- pointer defaults -----------------------------------------------------
578
+ //
579
+ // `:hover` is wired at the element rather than through React: the cascade
580
+ // already knows whether any rule in the document tests it, `setHover`
581
+ // returns without work when none does, and a document that does use it
582
+ // re-styles only when the hovered chain actually changed. The restyle is
583
+ // still document-wide — narrowing it to the affected subtree is the
584
+ // phase-2 item the PRD records.
585
+
586
+ override defaultMouseMove(ev: X11MouseEvent): void {
587
+ super.defaultMouseMove?.(ev);
588
+ this.setHover(ev.x, ev.y);
589
+ }
590
+
591
+ override defaultMouseLeave(ev: X11MouseEvent): void {
592
+ super.defaultMouseLeave?.(ev);
593
+ this.clearHover();
594
+ }
595
+
596
+ // --- paint ----------------------------------------------------------------
597
+
598
+ override paint(ctx: Context2D): void {
599
+ super.paint(ctx); // background, border, clip to `abs`
600
+ this._prepare(this.abs.width || 1);
601
+ const tree = this._tree;
602
+ if (!tree) return;
603
+ const range = this.selectionRange;
604
+ // Culling against the damage is what makes an expose of a strip cost the
605
+ // strip rather than the document. `paintDamage()` is null when the whole
606
+ // window is being repainted — but "the whole window" still bounds the
607
+ // paint, and the bound is load-bearing rather than an optimization: X
608
+ // carries glyph positions as Int16, so a document taller than ±32767
609
+ // *thrown to the server unculled* dies in the protocol encoder, not on
610
+ // the screen. The window node's rect is the tightest thing always known.
611
+ let damage = this.paintDamage();
612
+ if (!damage) {
613
+ const window = this.root?.abs;
614
+ if (window && window.height > 0) {
615
+ damage = { x: 0, y: 0, width: window.width, height: window.height };
616
+ }
617
+ }
618
+ paintDocument(ctx as PaintContext, tree, {
619
+ originX: this.abs.x,
620
+ originY: this.abs.y,
621
+ damage,
622
+ selection: range
623
+ ? { start: this._toUnits(range.start), end: this._toUnits(range.end) }
624
+ : null,
625
+ selectionColor: this.selectionColor,
626
+ imageFor: (box) =>
627
+ box.el ? this._resources.image(attr(box.el, 'src') ?? '') : null,
628
+ });
629
+ }
630
+ }
631
+
632
+ const EMPTY_SET: ReadonlySet<Element> = new Set();
633
+
634
+ function textOf(el: Element): string {
635
+ let out = '';
636
+ for (const child of el.children) {
637
+ if (child.type === 'text') out += child.data;
638
+ }
639
+ return out;
640
+ }
641
+
642
+ function sameChain(a: Element[], b: Element[]): boolean {
643
+ if (a.length !== b.length) return false;
644
+ for (let i = 0; i < a.length; i += 1) if (a[i] !== b[i]) return false;
645
+ return true;
646
+ }
647
+
648
+ function sameRects(a: ControlRect[], b: ControlRect[]): boolean {
649
+ if (a.length !== b.length) return false;
650
+ for (let i = 0; i < a.length; i += 1) {
651
+ const p = a[i];
652
+ const q = b[i];
653
+ if (
654
+ p.element !== q.element ||
655
+ p.x !== q.x ||
656
+ p.y !== q.y ||
657
+ p.width !== q.width ||
658
+ p.height !== q.height
659
+ ) {
660
+ return false;
661
+ }
662
+ }
663
+ return true;
664
+ }
665
+
666
+ // --- walks over the laid-out tree -------------------------------------------
667
+
668
+ /** Distance from a coordinate to an interval, zero inside it. */
669
+ function axisDistance(v: number, lo: number, span: number): number {
670
+ return v < lo ? lo - v : v > lo + span ? v - (lo + span) : 0;
671
+ }
672
+
673
+ /**
674
+ * The code-unit offset nearest a document-space point.
675
+ *
676
+ * Two prunes keep this the viewport's cost rather than the document's — it
677
+ * runs per pointer event during a selection drag, where an unpruned walk of
678
+ * a big document measured in the tens of milliseconds *per move*:
679
+ *
680
+ * - a subtree whose ink bounds cannot beat the best distance found so far
681
+ * is skipped whole (the metric `dy·4 + dx` is monotone in both axis
682
+ * distances, so the bounds give an exact lower bound);
683
+ * - within a box, lines are y-sorted, so the candidates are found by
684
+ * binary search and the scan stops the moment vertical distance alone
685
+ * rules a line out.
686
+ */
687
+ function nearestText(box: Box, x: number, y: number): number | null {
688
+ let best: number | null = null;
689
+ let bestDistance = Infinity;
690
+
691
+ const tryLine = (line: NonNullable<Box['lines']>[number]): void => {
692
+ const dy = axisDistance(y, line.y, line.height);
693
+ for (const text of line.texts) {
694
+ const natural = text.layout.lines[text.layoutLine];
695
+ if (!natural) continue;
696
+ const left = text.drawX + natural.x;
697
+ const dx = axisDistance(x, left, natural.width);
698
+ const distance = dy * 4 + dx;
699
+ if (distance >= bestDistance) continue;
700
+ bestDistance = distance;
701
+ const local = text.layout.indexAt(x - text.drawX, y - text.drawY);
702
+ const offsets = layoutOffsetsOf(text.layout);
703
+ const units = offsets.length
704
+ ? offsets[Math.max(0, Math.min(local, offsets.length - 1))]
705
+ : local;
706
+ best = text.textStart + Math.max(0, units - text.layoutStart);
707
+ }
708
+ };
709
+
710
+ const visit = (node: Box): void => {
711
+ const boundsDistance =
712
+ axisDistance(y, node.boundsY, node.boundsHeight) * 4 +
713
+ axisDistance(x, node.boundsX, node.boundsWidth);
714
+ if (boundsDistance >= bestDistance) return;
715
+
716
+ const lines = node.lines;
717
+ if (lines?.length) {
718
+ // The line nearest in y, by binary search; then outward both ways
719
+ // while vertical distance alone could still beat the best.
720
+ let lo = 0;
721
+ let hi = lines.length;
722
+ while (lo < hi) {
723
+ const mid = (lo + hi) >> 1;
724
+ if (lines[mid].y > y) hi = mid;
725
+ else lo = mid + 1;
726
+ }
727
+ for (let i = lo - 1; i >= 0; i -= 1) {
728
+ if (axisDistance(y, lines[i].y, lines[i].height) * 4 >= bestDistance)
729
+ break;
730
+ tryLine(lines[i]);
731
+ }
732
+ for (let i = lo; i < lines.length; i += 1) {
733
+ if (axisDistance(y, lines[i].y, lines[i].height) * 4 >= bestDistance)
734
+ break;
735
+ tryLine(lines[i]);
736
+ }
737
+ }
738
+ // Atomics are ordinary children of the box, so the child walk below
739
+ // reaches them; a per-line atomics pass would visit each twice.
740
+ //
741
+ // A wide child list goes through the sorted index, outward from the
742
+ // pointer's y — the bounds prune alone still *visits* every child to
743
+ // reject it, and twenty thousand rejections per pointer move is the
744
+ // cost being avoided. The expansion stops the moment vertical distance
745
+ // alone cannot beat the best hit.
746
+ const index = node.paintIndex;
747
+ if (index) {
748
+ const sorted = index.boxes;
749
+ let lo = 0;
750
+ let hi = sorted.length;
751
+ while (lo < hi) {
752
+ const mid = (lo + hi) >> 1;
753
+ if (sorted[mid].boundsY > y) hi = mid;
754
+ else lo = mid + 1;
755
+ }
756
+ for (let i = lo - 1; i >= 0; i -= 1) {
757
+ const child = sorted[i];
758
+ if (
759
+ axisDistance(y, child.boundsY, child.boundsHeight) * 4 >=
760
+ bestDistance
761
+ )
762
+ break;
763
+ visit(child);
764
+ }
765
+ for (let i = lo; i < sorted.length; i += 1) {
766
+ const child = sorted[i];
767
+ if (
768
+ axisDistance(y, child.boundsY, child.boundsHeight) * 4 >=
769
+ bestDistance
770
+ )
771
+ break;
772
+ visit(child);
773
+ }
774
+ if (node.positionedPaint) {
775
+ for (const child of node.positionedPaint) visit(child);
776
+ }
777
+ return;
778
+ }
779
+ for (const child of node.children) {
780
+ if (child.kind === 'text' || child.kind === 'break') continue;
781
+ visit(child);
782
+ }
783
+ };
784
+ visit(box);
785
+ return best;
786
+ }
787
+
788
+ /** Where a caret at a code-unit offset stands, in document coordinates.
789
+ * Subtrees whose text range cannot hold the offset are skipped whole, so
790
+ * the walk is the path to one paragraph, not the document. */
791
+ function caretAt(
792
+ box: Box,
793
+ units: number,
794
+ ): { x: number; y: number; height: number } | null {
795
+ let found: { x: number; y: number; height: number } | null = null;
796
+ const visit = (node: Box): void => {
797
+ if (found) return;
798
+ if (node.subtreeTextEnd <= node.subtreeTextStart) return;
799
+ if (units < node.subtreeTextStart || units > node.subtreeTextEnd) return;
800
+ const lines = node.lines;
801
+ if (lines?.length) {
802
+ // Lines are in document order, so their text starts are sorted:
803
+ // binary search the last line starting at or before the offset.
804
+ let lo = 0;
805
+ let hi = lines.length;
806
+ while (lo < hi) {
807
+ const mid = (lo + hi) >> 1;
808
+ if (lines[mid].textStart > units) hi = mid;
809
+ else lo = mid + 1;
810
+ }
811
+ for (let i = Math.max(0, lo - 1); i < lines.length; i += 1) {
812
+ const line = lines[i];
813
+ if (line.textStart > units) break;
814
+ for (const text of line.texts) {
815
+ if (units < text.textStart || units > text.textEnd) continue;
816
+ const offsets = layoutOffsetsOf(text.layout);
817
+ const layoutUnits = text.layoutStart + (units - text.textStart);
818
+ const caret = text.layout.caretPosition(
819
+ codePointAtOffset(offsets, layoutUnits),
820
+ );
821
+ found = { x: text.drawX + caret.x, y: line.y, height: line.height };
822
+ return;
823
+ }
824
+ }
825
+ }
826
+ for (const child of node.children) {
827
+ if (child.kind === 'text' || child.kind === 'break') continue;
828
+ visit(child);
829
+ if (found) return;
830
+ }
831
+ };
832
+ visit(box);
833
+ return found;
834
+ }
835
+
836
+ /** Every band a document range covers, in window coordinates. The subtree
837
+ * text ranges prune the walk to the boxes the range actually crosses, so a
838
+ * drag's small range costs its own paragraphs; only Ctrl+A pays for all. */
839
+ function collectBands(
840
+ box: Box,
841
+ from: number,
842
+ to: number,
843
+ dx: number,
844
+ dy: number,
845
+ out: Rect[],
846
+ ): void {
847
+ if (box.subtreeTextEnd <= box.subtreeTextStart) return;
848
+ if (box.subtreeTextEnd <= from || box.subtreeTextStart >= to) return;
849
+ if (box.lines) {
850
+ const lines = box.lines;
851
+ // First line whose text can reach `from`, by binary search over the
852
+ // sorted text starts; stop at the first line past `to`.
853
+ let lo = 0;
854
+ let hi = lines.length;
855
+ while (lo < hi) {
856
+ const mid = (lo + hi) >> 1;
857
+ if (lines[mid].textEnd > from) hi = mid;
858
+ else lo = mid + 1;
859
+ }
860
+ for (let i = lo; i < lines.length; i += 1) {
861
+ const line = lines[i];
862
+ if (line.textStart >= to) break;
863
+ if (line.textEnd > from && line.textStart < to) {
864
+ for (const text of line.texts) {
865
+ const natural = text.layout.lines[text.layoutLine];
866
+ if (!natural) continue;
867
+ const a = Math.max(from, text.textStart);
868
+ const b = Math.min(to, text.textEnd);
869
+ if (b <= a) continue;
870
+ const offsets = layoutOffsetsOf(text.layout);
871
+ for (const band of bandsFor(
872
+ text.layout,
873
+ natural,
874
+ offsets,
875
+ text.layoutStart + (a - text.textStart),
876
+ text.layoutStart + (b - text.textStart),
877
+ )) {
878
+ out.push({
879
+ x: dx + band.x + text.drawX,
880
+ y: dy + line.y,
881
+ width: band.width,
882
+ height: line.height,
883
+ });
884
+ }
885
+ }
886
+ }
887
+ }
888
+ }
889
+ // Atomics are ordinary children, reached below.
890
+ for (const child of box.children) {
891
+ if (child.kind === 'text' || child.kind === 'break') continue;
892
+ collectBands(child, from, to, dx, dy, out);
893
+ }
894
+ }
895
+
896
+ /** The deepest element box containing a document-space point. */
897
+ function deepestAt(box: Box, x: number, y: number): Element | null {
898
+ let found: Element | null = box.el;
899
+ const visit = (node: Box): void => {
900
+ // The paint index answers a point query too — the wide level of a flat
901
+ // document is the root's child list, and a hit test that walked all of
902
+ // it would run per pointer move once hover is in the picture.
903
+ const candidates = node.paintIndex
904
+ ? queryChildIndex(node.paintIndex, y, y + 1)
905
+ : node.children;
906
+ for (const child of candidates) {
907
+ if (child.kind === 'text' || child.kind === 'break') continue;
908
+ if (
909
+ x >= child.x &&
910
+ x < child.x + child.width &&
911
+ y >= child.y &&
912
+ y < child.y + child.height
913
+ ) {
914
+ if (child.el) found = child.el;
915
+ visit(child);
916
+ }
917
+ }
918
+ if (node.paintIndex && node.positionedPaint) {
919
+ for (const child of node.positionedPaint) {
920
+ if (
921
+ x >= child.x &&
922
+ x < child.x + child.width &&
923
+ y >= child.y &&
924
+ y < child.y + child.height
925
+ ) {
926
+ if (child.el) found = child.el;
927
+ visit(child);
928
+ }
929
+ }
930
+ }
931
+ if (node.lines) {
932
+ for (const line of node.lines) {
933
+ for (const placed of line.atomics) {
934
+ if (
935
+ x >= placed.box.x &&
936
+ x < placed.box.x + placed.box.width &&
937
+ y >= placed.box.y &&
938
+ y < placed.box.y + placed.box.height
939
+ ) {
940
+ if (placed.box.el) found = placed.box.el;
941
+ visit(placed.box);
942
+ }
943
+ }
944
+ // An inline box has no box of its own — its extent is the runs on
945
+ // this line — so the element under a point inside a paragraph is
946
+ // found from the run rather than from a rectangle.
947
+ if (y >= line.y && y < line.y + line.height) {
948
+ for (const text of line.texts) {
949
+ const natural = text.layout.lines[text.layoutLine];
950
+ if (!natural) continue;
951
+ for (const run of natural.runs) {
952
+ const left = text.drawX + natural.x + run.x;
953
+ if (x >= left && x < left + run.width) {
954
+ const owner = (run.span as { element?: Element }).element;
955
+ if (owner) found = owner;
956
+ }
957
+ }
958
+ }
959
+ }
960
+ }
961
+ }
962
+ };
963
+ visit(box);
964
+ return found;
965
+ }
966
+
967
+ export type { ControlRect, ReplacedKind, ResourceRequest, ResourceResult };