@react-x11/components 0.9.0 → 0.11.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 (579) hide show
  1. package/README.md +10 -4
  2. package/dist/charts/node.d.ts +11 -1
  3. package/dist/charts/node.d.ts.map +1 -1
  4. package/dist/charts/node.js +44 -14
  5. package/dist/charts/node.js.map +1 -1
  6. package/dist/charts/render.d.ts +12 -3
  7. package/dist/charts/render.d.ts.map +1 -1
  8. package/dist/charts/render.js +94 -25
  9. package/dist/charts/render.js.map +1 -1
  10. package/dist/code/index.d.ts.map +1 -1
  11. package/dist/code/index.js +27 -24
  12. package/dist/code/index.js.map +1 -1
  13. package/dist/code-editor/completion.d.ts.map +1 -1
  14. package/dist/code-editor/completion.js +3 -2
  15. package/dist/code-editor/completion.js.map +1 -1
  16. package/dist/code-editor/index.d.ts.map +1 -1
  17. package/dist/code-editor/index.js +19 -0
  18. package/dist/code-editor/index.js.map +1 -1
  19. package/dist/code-editor/node.d.ts +177 -7
  20. package/dist/code-editor/node.d.ts.map +1 -1
  21. package/dist/code-editor/node.js +1329 -164
  22. package/dist/code-editor/node.js.map +1 -1
  23. package/dist/code-language/index.d.ts +1 -1
  24. package/dist/code-language/index.d.ts.map +1 -1
  25. package/dist/code-language/index.js +1 -1
  26. package/dist/code-language/index.js.map +1 -1
  27. package/dist/code-language/languages/glsl.d.ts.map +1 -1
  28. package/dist/code-language/languages/glsl.js +10 -2
  29. package/dist/code-language/languages/glsl.js.map +1 -1
  30. package/dist/code-language/languages/javascript.d.ts.map +1 -1
  31. package/dist/code-language/languages/javascript.js +18 -3
  32. package/dist/code-language/languages/javascript.js.map +1 -1
  33. package/dist/code-language/languages/json.d.ts.map +1 -1
  34. package/dist/code-language/languages/json.js +10 -2
  35. package/dist/code-language/languages/json.js.map +1 -1
  36. package/dist/code-language/languages/shell.d.ts.map +1 -1
  37. package/dist/code-language/languages/shell.js +10 -2
  38. package/dist/code-language/languages/shell.js.map +1 -1
  39. package/dist/code-language/languages/sql.d.ts.map +1 -1
  40. package/dist/code-language/languages/sql.js +20 -2
  41. package/dist/code-language/languages/sql.js.map +1 -1
  42. package/dist/code-language/runs.d.ts +31 -0
  43. package/dist/code-language/runs.d.ts.map +1 -1
  44. package/dist/code-language/runs.js +105 -0
  45. package/dist/code-language/runs.js.map +1 -1
  46. package/dist/code-language/stream.d.ts +22 -0
  47. package/dist/code-language/stream.d.ts.map +1 -1
  48. package/dist/code-language/stream.js +259 -9
  49. package/dist/code-language/stream.js.map +1 -1
  50. package/dist/code-language/types.d.ts +5 -4
  51. package/dist/code-language/types.d.ts.map +1 -1
  52. package/dist/codeblock/index.d.ts +26 -2
  53. package/dist/codeblock/index.d.ts.map +1 -1
  54. package/dist/codeblock/index.js +57 -4
  55. package/dist/codeblock/index.js.map +1 -1
  56. package/dist/flow/draw.d.ts +50 -0
  57. package/dist/flow/draw.d.ts.map +1 -1
  58. package/dist/flow/draw.js +132 -33
  59. package/dist/flow/draw.js.map +1 -1
  60. package/dist/flow/gl/color.d.ts +13 -0
  61. package/dist/flow/gl/color.d.ts.map +1 -0
  62. package/dist/flow/gl/color.js +82 -0
  63. package/dist/flow/gl/color.js.map +1 -0
  64. package/dist/flow/gl/index.d.ts +60 -0
  65. package/dist/flow/gl/index.d.ts.map +1 -0
  66. package/dist/flow/gl/index.js +283 -0
  67. package/dist/flow/gl/index.js.map +1 -0
  68. package/dist/flow/gl/pack.d.ts +133 -0
  69. package/dist/flow/gl/pack.d.ts.map +1 -0
  70. package/dist/flow/gl/pack.js +408 -0
  71. package/dist/flow/gl/pack.js.map +1 -0
  72. package/dist/flow/gl/renderer.d.ts +95 -0
  73. package/dist/flow/gl/renderer.d.ts.map +1 -0
  74. package/dist/flow/gl/renderer.js +459 -0
  75. package/dist/flow/gl/renderer.js.map +1 -0
  76. package/dist/flow/gl/shaders.d.ts +79 -0
  77. package/dist/flow/gl/shaders.d.ts.map +1 -0
  78. package/dist/flow/gl/shaders.js +346 -0
  79. package/dist/flow/gl/shaders.js.map +1 -0
  80. package/dist/flow/gl/text.d.ts +318 -0
  81. package/dist/flow/gl/text.d.ts.map +1 -0
  82. package/dist/flow/gl/text.js +1103 -0
  83. package/dist/flow/gl/text.js.map +1 -0
  84. package/dist/flow/index.d.ts +1 -1
  85. package/dist/flow/index.d.ts.map +1 -1
  86. package/dist/flow/index.js +619 -64
  87. package/dist/flow/index.js.map +1 -1
  88. package/dist/flow/node.d.ts +621 -72
  89. package/dist/flow/node.d.ts.map +1 -1
  90. package/dist/flow/node.js +2253 -1018
  91. package/dist/flow/node.js.map +1 -1
  92. package/dist/flow/paint.d.ts +35 -0
  93. package/dist/flow/paint.d.ts.map +1 -0
  94. package/dist/flow/paint.js +393 -0
  95. package/dist/flow/paint.js.map +1 -0
  96. package/dist/flow/paths.d.ts +14 -0
  97. package/dist/flow/paths.d.ts.map +1 -1
  98. package/dist/flow/paths.js +45 -19
  99. package/dist/flow/paths.js.map +1 -1
  100. package/dist/flow/scene.d.ts +584 -0
  101. package/dist/flow/scene.d.ts.map +1 -0
  102. package/dist/flow/scene.js +1453 -0
  103. package/dist/flow/scene.js.map +1 -0
  104. package/dist/flow/types.d.ts +111 -1
  105. package/dist/flow/types.d.ts.map +1 -1
  106. package/dist/html/controls.d.ts +28 -0
  107. package/dist/html/controls.d.ts.map +1 -1
  108. package/dist/html/controls.js +52 -2
  109. package/dist/html/controls.js.map +1 -1
  110. package/dist/html/css/calc.d.ts +14 -0
  111. package/dist/html/css/calc.d.ts.map +1 -0
  112. package/dist/html/css/calc.js +344 -0
  113. package/dist/html/css/calc.js.map +1 -0
  114. package/dist/html/css/cascade.d.ts +262 -6
  115. package/dist/html/css/cascade.d.ts.map +1 -1
  116. package/dist/html/css/cascade.js +1373 -67
  117. package/dist/html/css/cascade.js.map +1 -1
  118. package/dist/html/css/color.d.ts +23 -0
  119. package/dist/html/css/color.d.ts.map +1 -0
  120. package/dist/html/css/color.js +740 -0
  121. package/dist/html/css/color.js.map +1 -0
  122. package/dist/html/css/content.d.ts +92 -0
  123. package/dist/html/css/content.d.ts.map +1 -0
  124. package/dist/html/css/content.js +388 -0
  125. package/dist/html/css/content.js.map +1 -0
  126. package/dist/html/css/counter-styles.d.ts +76 -0
  127. package/dist/html/css/counter-styles.d.ts.map +1 -0
  128. package/dist/html/css/counter-styles.js +893 -0
  129. package/dist/html/css/counter-styles.js.map +1 -0
  130. package/dist/html/css/decode.d.ts +12 -0
  131. package/dist/html/css/decode.d.ts.map +1 -0
  132. package/dist/html/css/decode.js +116 -0
  133. package/dist/html/css/decode.js.map +1 -0
  134. package/dist/html/css/parse.d.ts +110 -10
  135. package/dist/html/css/parse.d.ts.map +1 -1
  136. package/dist/html/css/parse.js +1473 -180
  137. package/dist/html/css/parse.js.map +1 -1
  138. package/dist/html/css/style.d.ts +501 -15
  139. package/dist/html/css/style.d.ts.map +1 -1
  140. package/dist/html/css/style.js +3729 -206
  141. package/dist/html/css/style.js.map +1 -1
  142. package/dist/html/css/ua.d.ts.map +1 -1
  143. package/dist/html/css/ua.js +65 -16
  144. package/dist/html/css/ua.js.map +1 -1
  145. package/dist/html/css/values.d.ts +37 -3
  146. package/dist/html/css/values.d.ts.map +1 -1
  147. package/dist/html/css/values.js +122 -48
  148. package/dist/html/css/values.js.map +1 -1
  149. package/dist/html/css/vars.d.ts +52 -0
  150. package/dist/html/css/vars.d.ts.map +1 -0
  151. package/dist/html/css/vars.js +358 -0
  152. package/dist/html/css/vars.js.map +1 -0
  153. package/dist/html/dom.d.ts +30 -4
  154. package/dist/html/dom.d.ts.map +1 -1
  155. package/dist/html/dom.js +278 -17
  156. package/dist/html/dom.js.map +1 -1
  157. package/dist/html/fonts.d.ts +106 -0
  158. package/dist/html/fonts.d.ts.map +1 -0
  159. package/dist/html/fonts.js +565 -0
  160. package/dist/html/fonts.js.map +1 -0
  161. package/dist/html/gif.d.ts +15 -0
  162. package/dist/html/gif.d.ts.map +1 -0
  163. package/dist/html/gif.js +229 -0
  164. package/dist/html/gif.js.map +1 -0
  165. package/dist/html/index.d.ts +50 -11
  166. package/dist/html/index.d.ts.map +1 -1
  167. package/dist/html/index.js +115 -9
  168. package/dist/html/index.js.map +1 -1
  169. package/dist/html/layout/block.d.ts +226 -3
  170. package/dist/html/layout/block.d.ts.map +1 -1
  171. package/dist/html/layout/block.js +3077 -219
  172. package/dist/html/layout/block.js.map +1 -1
  173. package/dist/html/layout/boxes.d.ts +367 -17
  174. package/dist/html/layout/boxes.d.ts.map +1 -1
  175. package/dist/html/layout/boxes.js +1742 -182
  176. package/dist/html/layout/boxes.js.map +1 -1
  177. package/dist/html/layout/cache.d.ts +58 -0
  178. package/dist/html/layout/cache.d.ts.map +1 -0
  179. package/dist/html/layout/cache.js +224 -0
  180. package/dist/html/layout/cache.js.map +1 -0
  181. package/dist/html/layout/collapse.d.ts +45 -0
  182. package/dist/html/layout/collapse.d.ts.map +1 -0
  183. package/dist/html/layout/collapse.js +246 -0
  184. package/dist/html/layout/collapse.js.map +1 -0
  185. package/dist/html/layout/css-grid.d.ts +7 -0
  186. package/dist/html/layout/css-grid.d.ts.map +1 -0
  187. package/dist/html/layout/css-grid.js +900 -0
  188. package/dist/html/layout/css-grid.js.map +1 -0
  189. package/dist/html/layout/flex.d.ts.map +1 -1
  190. package/dist/html/layout/flex.js +1025 -89
  191. package/dist/html/layout/flex.js.map +1 -1
  192. package/dist/html/layout/floats.d.ts +45 -6
  193. package/dist/html/layout/floats.d.ts.map +1 -1
  194. package/dist/html/layout/floats.js +113 -14
  195. package/dist/html/layout/floats.js.map +1 -1
  196. package/dist/html/layout/grid-lines.d.ts +39 -0
  197. package/dist/html/layout/grid-lines.d.ts.map +1 -0
  198. package/dist/html/layout/grid-lines.js +119 -0
  199. package/dist/html/layout/grid-lines.js.map +1 -0
  200. package/dist/html/layout/grid.d.ts +53 -0
  201. package/dist/html/layout/grid.d.ts.map +1 -0
  202. package/dist/html/layout/grid.js +153 -0
  203. package/dist/html/layout/grid.js.map +1 -0
  204. package/dist/html/layout/inline.d.ts +154 -1
  205. package/dist/html/layout/inline.d.ts.map +1 -1
  206. package/dist/html/layout/inline.js +3598 -175
  207. package/dist/html/layout/inline.js.map +1 -1
  208. package/dist/html/layout/shaping.d.ts +6 -0
  209. package/dist/html/layout/shaping.d.ts.map +1 -0
  210. package/dist/html/layout/shaping.js +100 -0
  211. package/dist/html/layout/shaping.js.map +1 -0
  212. package/dist/html/layout/table.d.ts +3 -0
  213. package/dist/html/layout/table.d.ts.map +1 -1
  214. package/dist/html/layout/table.js +681 -175
  215. package/dist/html/layout/table.js.map +1 -1
  216. package/dist/html/layout/tracks.d.ts +44 -0
  217. package/dist/html/layout/tracks.d.ts.map +1 -0
  218. package/dist/html/layout/tracks.js +349 -0
  219. package/dist/html/layout/tracks.js.map +1 -0
  220. package/dist/html/node.d.ts +169 -4
  221. package/dist/html/node.d.ts.map +1 -1
  222. package/dist/html/node.js +1429 -137
  223. package/dist/html/node.js.map +1 -1
  224. package/dist/html/paint.d.ts +92 -3
  225. package/dist/html/paint.d.ts.map +1 -1
  226. package/dist/html/paint.js +3635 -107
  227. package/dist/html/paint.js.map +1 -1
  228. package/dist/html/resources.d.ts +60 -14
  229. package/dist/html/resources.d.ts.map +1 -1
  230. package/dist/html/resources.js +122 -36
  231. package/dist/html/resources.js.map +1 -1
  232. package/dist/html/surfaces.d.ts +23 -0
  233. package/dist/html/surfaces.d.ts.map +1 -0
  234. package/dist/html/surfaces.js +68 -0
  235. package/dist/html/surfaces.js.map +1 -0
  236. package/dist/html/svg.d.ts +80 -0
  237. package/dist/html/svg.d.ts.map +1 -0
  238. package/dist/html/svg.js +442 -0
  239. package/dist/html/svg.js.map +1 -0
  240. package/dist/html/url.d.ts +23 -0
  241. package/dist/html/url.d.ts.map +1 -0
  242. package/dist/html/url.js +80 -0
  243. package/dist/html/url.js.map +1 -0
  244. package/dist/index.d.ts +1 -1
  245. package/dist/index.d.ts.map +1 -1
  246. package/dist/index.js.map +1 -1
  247. package/dist/internal/codelines.d.ts +42 -0
  248. package/dist/internal/codelines.d.ts.map +1 -0
  249. package/dist/internal/codelines.js +170 -0
  250. package/dist/internal/codelines.js.map +1 -0
  251. package/dist/internal/collate.d.ts +3 -0
  252. package/dist/internal/collate.d.ts.map +1 -0
  253. package/dist/internal/collate.js +11 -0
  254. package/dist/internal/collate.js.map +1 -0
  255. package/dist/internal/markdown/ast.d.ts +11 -0
  256. package/dist/internal/markdown/ast.d.ts.map +1 -1
  257. package/dist/internal/markdown/parse.d.ts.map +1 -1
  258. package/dist/internal/markdown/parse.js +109 -8
  259. package/dist/internal/markdown/parse.js.map +1 -1
  260. package/dist/internal/prewarm.d.ts +18 -0
  261. package/dist/internal/prewarm.d.ts.map +1 -0
  262. package/dist/internal/prewarm.js +42 -0
  263. package/dist/internal/prewarm.js.map +1 -0
  264. package/dist/internal/sdf.d.ts +20 -0
  265. package/dist/internal/sdf.d.ts.map +1 -0
  266. package/dist/internal/sdf.js +216 -0
  267. package/dist/internal/sdf.js.map +1 -0
  268. package/dist/internal/splice.d.ts +12 -0
  269. package/dist/internal/splice.d.ts.map +1 -0
  270. package/dist/internal/splice.js +23 -0
  271. package/dist/internal/splice.js.map +1 -0
  272. package/dist/internal/window.d.ts +12 -0
  273. package/dist/internal/window.d.ts.map +1 -1
  274. package/dist/internal/window.js +23 -6
  275. package/dist/internal/window.js.map +1 -1
  276. package/dist/maps/anchors.d.ts +6 -1
  277. package/dist/maps/anchors.d.ts.map +1 -1
  278. package/dist/maps/anchors.js +260 -1
  279. package/dist/maps/anchors.js.map +1 -1
  280. package/dist/maps/controller.d.ts +57 -0
  281. package/dist/maps/controller.d.ts.map +1 -1
  282. package/dist/maps/controller.js +97 -18
  283. package/dist/maps/controller.js.map +1 -1
  284. package/dist/maps/gl/buckets.d.ts +5 -1
  285. package/dist/maps/gl/buckets.d.ts.map +1 -1
  286. package/dist/maps/gl/buckets.js +5 -2
  287. package/dist/maps/gl/buckets.js.map +1 -1
  288. package/dist/maps/gl/build-worker.d.ts +2 -0
  289. package/dist/maps/gl/build-worker.d.ts.map +1 -1
  290. package/dist/maps/gl/build-worker.js +1 -1
  291. package/dist/maps/gl/build-worker.js.map +1 -1
  292. package/dist/maps/gl/cover.d.ts +23 -4
  293. package/dist/maps/gl/cover.d.ts.map +1 -1
  294. package/dist/maps/gl/cover.js +61 -48
  295. package/dist/maps/gl/cover.js.map +1 -1
  296. package/dist/maps/gl/placement.d.ts +21 -8
  297. package/dist/maps/gl/placement.d.ts.map +1 -1
  298. package/dist/maps/gl/placement.js +133 -58
  299. package/dist/maps/gl/placement.js.map +1 -1
  300. package/dist/maps/gl/renderer.d.ts +36 -4
  301. package/dist/maps/gl/renderer.d.ts.map +1 -1
  302. package/dist/maps/gl/renderer.js +81 -24
  303. package/dist/maps/gl/renderer.js.map +1 -1
  304. package/dist/maps/gl/shaders.d.ts +18 -17
  305. package/dist/maps/gl/shaders.d.ts.map +1 -1
  306. package/dist/maps/gl/shaders.js +34 -32
  307. package/dist/maps/gl/shaders.js.map +1 -1
  308. package/dist/maps/gl/store.d.ts +10 -0
  309. package/dist/maps/gl/store.d.ts.map +1 -1
  310. package/dist/maps/gl/store.js +47 -4
  311. package/dist/maps/gl/store.js.map +1 -1
  312. package/dist/maps/gl/text.d.ts +153 -24
  313. package/dist/maps/gl/text.d.ts.map +1 -1
  314. package/dist/maps/gl/text.js +379 -63
  315. package/dist/maps/gl/text.js.map +1 -1
  316. package/dist/maps/gl/view.d.ts +293 -2
  317. package/dist/maps/gl/view.d.ts.map +1 -1
  318. package/dist/maps/gl/view.js +317 -82
  319. package/dist/maps/gl/view.js.map +1 -1
  320. package/dist/maps/icons.d.ts +32 -0
  321. package/dist/maps/icons.d.ts.map +1 -0
  322. package/dist/maps/icons.js +151 -0
  323. package/dist/maps/icons.js.map +1 -0
  324. package/dist/maps/index.d.ts +2 -0
  325. package/dist/maps/index.d.ts.map +1 -1
  326. package/dist/maps/index.js +2 -0
  327. package/dist/maps/index.js.map +1 -1
  328. package/dist/maps/labels.d.ts +56 -4
  329. package/dist/maps/labels.d.ts.map +1 -1
  330. package/dist/maps/labels.js +213 -46
  331. package/dist/maps/labels.js.map +1 -1
  332. package/dist/maps/node.d.ts +17 -0
  333. package/dist/maps/node.d.ts.map +1 -1
  334. package/dist/maps/node.js +64 -30
  335. package/dist/maps/node.js.map +1 -1
  336. package/dist/maps/proj.d.ts +48 -0
  337. package/dist/maps/proj.d.ts.map +1 -1
  338. package/dist/maps/proj.js +73 -0
  339. package/dist/maps/proj.js.map +1 -1
  340. package/dist/maps/sources.d.ts +5 -3
  341. package/dist/maps/sources.d.ts.map +1 -1
  342. package/dist/maps/sources.js +5 -3
  343. package/dist/maps/sources.js.map +1 -1
  344. package/dist/maps/style.d.ts +35 -0
  345. package/dist/maps/style.d.ts.map +1 -1
  346. package/dist/maps/style.js.map +1 -1
  347. package/dist/maps/styles.d.ts +12 -0
  348. package/dist/maps/styles.d.ts.map +1 -1
  349. package/dist/maps/styles.js +120 -6
  350. package/dist/maps/styles.js.map +1 -1
  351. package/dist/maps/tiles.d.ts +31 -11
  352. package/dist/maps/tiles.d.ts.map +1 -1
  353. package/dist/maps/tiles.js +61 -27
  354. package/dist/maps/tiles.js.map +1 -1
  355. package/dist/maps/types.d.ts +28 -4
  356. package/dist/maps/types.d.ts.map +1 -1
  357. package/dist/markdown/index.d.ts.map +1 -1
  358. package/dist/markdown/index.js +209 -68
  359. package/dist/markdown/index.js.map +1 -1
  360. package/dist/markdown/spans.d.ts.map +1 -1
  361. package/dist/markdown/spans.js +6 -0
  362. package/dist/markdown/spans.js.map +1 -1
  363. package/dist/qml/containers.d.ts.map +1 -1
  364. package/dist/qml/containers.js +6 -1
  365. package/dist/qml/containers.js.map +1 -1
  366. package/dist/qml/interaction.d.ts.map +1 -1
  367. package/dist/qml/interaction.js +38 -5
  368. package/dist/qml/interaction.js.map +1 -1
  369. package/dist/qml/layouts.d.ts.map +1 -1
  370. package/dist/qml/layouts.js +21 -6
  371. package/dist/qml/layouts.js.map +1 -1
  372. package/dist/qml/qtquick.d.ts.map +1 -1
  373. package/dist/qml/qtquick.js +9 -2
  374. package/dist/qml/qtquick.js.map +1 -1
  375. package/dist/qml/react.d.ts.map +1 -1
  376. package/dist/qml/react.js +9 -7
  377. package/dist/qml/react.js.map +1 -1
  378. package/dist/reorder/clock.d.ts +7 -0
  379. package/dist/reorder/clock.d.ts.map +1 -0
  380. package/dist/reorder/clock.js +26 -0
  381. package/dist/reorder/clock.js.map +1 -0
  382. package/dist/reorder/index.d.ts +25 -3
  383. package/dist/reorder/index.d.ts.map +1 -1
  384. package/dist/reorder/index.js +64 -19
  385. package/dist/reorder/index.js.map +1 -1
  386. package/dist/rich-text-editor/index.d.ts +0 -11
  387. package/dist/rich-text-editor/index.d.ts.map +1 -1
  388. package/dist/rich-text-editor/index.js +38 -9
  389. package/dist/rich-text-editor/index.js.map +1 -1
  390. package/dist/rich-text-editor/keymap.d.ts.map +1 -1
  391. package/dist/rich-text-editor/keymap.js +2 -1
  392. package/dist/rich-text-editor/keymap.js.map +1 -1
  393. package/dist/rich-text-editor/keys.d.ts +17 -6
  394. package/dist/rich-text-editor/keys.d.ts.map +1 -1
  395. package/dist/rich-text-editor/keys.js +135 -26
  396. package/dist/rich-text-editor/keys.js.map +1 -1
  397. package/dist/rich-text-editor/markdown.d.ts.map +1 -1
  398. package/dist/rich-text-editor/markdown.js +30 -1
  399. package/dist/rich-text-editor/markdown.js.map +1 -1
  400. package/dist/rich-text-editor/marks.d.ts +9 -0
  401. package/dist/rich-text-editor/marks.d.ts.map +1 -0
  402. package/dist/rich-text-editor/marks.js +83 -0
  403. package/dist/rich-text-editor/marks.js.map +1 -0
  404. package/dist/rich-text-editor/render.d.ts.map +1 -1
  405. package/dist/rich-text-editor/render.js +28 -10
  406. package/dist/rich-text-editor/render.js.map +1 -1
  407. package/dist/rich-text-editor/replace.d.ts +13 -0
  408. package/dist/rich-text-editor/replace.d.ts.map +1 -0
  409. package/dist/rich-text-editor/replace.js +64 -0
  410. package/dist/rich-text-editor/replace.js.map +1 -0
  411. package/dist/rich-text-editor/toolbar.d.ts.map +1 -1
  412. package/dist/rich-text-editor/toolbar.js +1 -1
  413. package/dist/rich-text-editor/toolbar.js.map +1 -1
  414. package/dist/rich-text-editor/virtual.d.ts.map +1 -1
  415. package/dist/rich-text-editor/virtual.js +17 -0
  416. package/dist/rich-text-editor/virtual.js.map +1 -1
  417. package/dist/richtext/node.d.ts +46 -2
  418. package/dist/richtext/node.d.ts.map +1 -1
  419. package/dist/richtext/node.js +187 -4
  420. package/dist/richtext/node.js.map +1 -1
  421. package/dist/richtext/runs.d.ts +13 -8
  422. package/dist/richtext/runs.d.ts.map +1 -1
  423. package/dist/richtext/runs.js +18 -8
  424. package/dist/richtext/runs.js.map +1 -1
  425. package/dist/table/index.d.ts.map +1 -1
  426. package/dist/table/index.js +23 -0
  427. package/dist/table/index.js.map +1 -1
  428. package/dist/table/rows.d.ts +3 -2
  429. package/dist/table/rows.d.ts.map +1 -1
  430. package/dist/table/rows.js +20 -6
  431. package/dist/table/rows.js.map +1 -1
  432. package/dist/terminal/index.d.ts.map +1 -1
  433. package/dist/terminal/index.js +4 -0
  434. package/dist/terminal/index.js.map +1 -1
  435. package/dist/terminal/vt/pty.d.ts +13 -2
  436. package/dist/terminal/vt/pty.d.ts.map +1 -1
  437. package/dist/terminal/vt/pty.js +18 -3
  438. package/dist/terminal/vt/pty.js.map +1 -1
  439. package/dist/terminal-output/index.d.ts.map +1 -1
  440. package/dist/terminal-output/index.js +103 -23
  441. package/dist/terminal-output/index.js.map +1 -1
  442. package/dist/terminal-output/runs.d.ts +4 -1
  443. package/dist/terminal-output/runs.d.ts.map +1 -1
  444. package/dist/terminal-output/runs.js +5 -1
  445. package/dist/terminal-output/runs.js.map +1 -1
  446. package/dist/three/canvas.d.ts.map +1 -1
  447. package/dist/three/canvas.js +85 -7
  448. package/dist/three/canvas.js.map +1 -1
  449. package/dist/three/events.d.ts +22 -4
  450. package/dist/three/events.d.ts.map +1 -1
  451. package/dist/three/events.js +34 -4
  452. package/dist/three/events.js.map +1 -1
  453. package/dist/tree/index.d.ts.map +1 -1
  454. package/dist/tree/index.js +17 -0
  455. package/dist/tree/index.js.map +1 -1
  456. package/package.json +42 -33
  457. package/src/charts/node.ts +62 -26
  458. package/src/charts/render.ts +120 -30
  459. package/src/code/index.ts +36 -32
  460. package/src/code-editor/completion.ts +3 -2
  461. package/src/code-editor/index.ts +19 -0
  462. package/src/code-editor/node.ts +1574 -184
  463. package/src/code-language/index.ts +1 -1
  464. package/src/code-language/languages/glsl.ts +12 -2
  465. package/src/code-language/languages/javascript.ts +21 -4
  466. package/src/code-language/languages/json.ts +12 -2
  467. package/src/code-language/languages/shell.ts +12 -2
  468. package/src/code-language/languages/sql.ts +22 -2
  469. package/src/code-language/runs.ts +111 -1
  470. package/src/code-language/stream.ts +257 -17
  471. package/src/code-language/types.ts +5 -4
  472. package/src/codeblock/index.ts +68 -4
  473. package/src/flow/draw.ts +167 -41
  474. package/src/flow/gl/color.ts +85 -0
  475. package/src/flow/gl/index.ts +342 -0
  476. package/src/flow/gl/pack.ts +585 -0
  477. package/src/flow/gl/renderer.ts +679 -0
  478. package/src/flow/gl/shaders.ts +371 -0
  479. package/src/flow/gl/text.ts +1295 -0
  480. package/src/flow/index.ts +794 -67
  481. package/src/flow/node.ts +2496 -1256
  482. package/src/flow/paint.ts +511 -0
  483. package/src/flow/paths.ts +80 -15
  484. package/src/flow/scene.ts +2199 -0
  485. package/src/flow/types.ts +113 -1
  486. package/src/html/controls.ts +73 -2
  487. package/src/html/css/calc.ts +385 -0
  488. package/src/html/css/cascade.ts +1481 -62
  489. package/src/html/css/color.ts +755 -0
  490. package/src/html/css/content.ts +417 -0
  491. package/src/html/css/counter-styles.ts +973 -0
  492. package/src/html/css/decode.ts +130 -0
  493. package/src/html/css/parse.ts +1514 -160
  494. package/src/html/css/style.ts +4131 -223
  495. package/src/html/css/ua.ts +66 -17
  496. package/src/html/css/values.ts +150 -50
  497. package/src/html/css/vars.ts +348 -0
  498. package/src/html/dom.ts +284 -17
  499. package/src/html/fonts.ts +641 -0
  500. package/src/html/gif.ts +233 -0
  501. package/src/html/index.ts +180 -20
  502. package/src/html/layout/block.ts +3560 -208
  503. package/src/html/layout/boxes.ts +2141 -190
  504. package/src/html/layout/cache.ts +289 -0
  505. package/src/html/layout/collapse.ts +317 -0
  506. package/src/html/layout/css-grid.ts +1063 -0
  507. package/src/html/layout/flex.ts +1115 -106
  508. package/src/html/layout/floats.ts +128 -14
  509. package/src/html/layout/grid-lines.ts +141 -0
  510. package/src/html/layout/grid.ts +181 -0
  511. package/src/html/layout/inline.ts +4187 -192
  512. package/src/html/layout/shaping.ts +140 -0
  513. package/src/html/layout/table.ts +696 -186
  514. package/src/html/layout/tracks.ts +437 -0
  515. package/src/html/node.ts +1585 -156
  516. package/src/html/paint.ts +4582 -267
  517. package/src/html/resources.ts +161 -50
  518. package/src/html/surfaces.ts +81 -0
  519. package/src/html/svg.ts +504 -0
  520. package/src/html/url.ts +86 -0
  521. package/src/index.ts +2 -0
  522. package/src/internal/codelines.ts +200 -0
  523. package/src/internal/collate.ts +12 -0
  524. package/src/internal/markdown/ast.ts +11 -0
  525. package/src/internal/markdown/parse.ts +154 -11
  526. package/src/internal/prewarm.ts +45 -0
  527. package/src/internal/sdf.ts +227 -0
  528. package/src/internal/splice.ts +25 -0
  529. package/src/internal/window.ts +36 -5
  530. package/src/maps/anchors.ts +307 -1
  531. package/src/maps/controller.ts +116 -31
  532. package/src/maps/gl/buckets.ts +5 -1
  533. package/src/maps/gl/build-worker.ts +13 -2
  534. package/src/maps/gl/cover.ts +79 -44
  535. package/src/maps/gl/placement.ts +221 -69
  536. package/src/maps/gl/renderer.ts +104 -20
  537. package/src/maps/gl/shaders.ts +35 -32
  538. package/src/maps/gl/store.ts +66 -17
  539. package/src/maps/gl/text.ts +444 -71
  540. package/src/maps/gl/view.ts +361 -96
  541. package/src/maps/icons.ts +183 -0
  542. package/src/maps/index.ts +4 -0
  543. package/src/maps/labels.ts +269 -49
  544. package/src/maps/node.ts +82 -49
  545. package/src/maps/proj.ts +87 -0
  546. package/src/maps/sources.ts +5 -3
  547. package/src/maps/style.ts +32 -0
  548. package/src/maps/styles.ts +215 -4
  549. package/src/maps/tiles.ts +64 -31
  550. package/src/maps/types.ts +28 -4
  551. package/src/markdown/index.ts +293 -92
  552. package/src/markdown/spans.ts +5 -0
  553. package/src/qml/containers.tsx +6 -1
  554. package/src/qml/interaction.tsx +42 -5
  555. package/src/qml/layouts.tsx +21 -6
  556. package/src/qml/qtquick.tsx +9 -2
  557. package/src/qml/react.tsx +7 -5
  558. package/src/reorder/clock.ts +27 -0
  559. package/src/reorder/index.ts +100 -27
  560. package/src/rich-text-editor/index.ts +37 -12
  561. package/src/rich-text-editor/keymap.ts +1 -1
  562. package/src/rich-text-editor/keys.ts +135 -26
  563. package/src/rich-text-editor/markdown.ts +36 -1
  564. package/src/rich-text-editor/marks.ts +101 -0
  565. package/src/rich-text-editor/render.ts +49 -12
  566. package/src/rich-text-editor/replace.ts +85 -0
  567. package/src/rich-text-editor/toolbar.ts +1 -1
  568. package/src/rich-text-editor/virtual.ts +25 -0
  569. package/src/richtext/node.ts +235 -14
  570. package/src/richtext/runs.ts +23 -12
  571. package/src/table/index.ts +29 -0
  572. package/src/table/rows.ts +18 -8
  573. package/src/terminal/index.ts +4 -0
  574. package/src/terminal/vt/pty.ts +16 -2
  575. package/src/terminal-output/index.ts +129 -31
  576. package/src/terminal-output/runs.ts +16 -2
  577. package/src/three/canvas.ts +102 -8
  578. package/src/three/events.ts +49 -9
  579. package/src/tree/index.ts +19 -0
@@ -62,7 +62,7 @@ import {
62
62
  import type { RichTextProps, TextRun } from '../richtext/index.js';
63
63
  import {
64
64
  codeBlockLook,
65
- codeBlockRuns,
65
+ CodeBlockRunCache,
66
66
  codeBlockStyle,
67
67
  codeTextStyle,
68
68
  } from '../codeblock/index.js';
@@ -77,6 +77,8 @@ import { runsOf, plainTextOf } from './spans.js';
77
77
  import type { InlineStyles } from './spans.js';
78
78
  import { useLinkClicks } from '../richtext/index.js';
79
79
  import { hx } from './hx.js';
80
+ import { CodeLines } from '../internal/codelines.js';
81
+ import { useFontPrewarm } from '../internal/prewarm.js';
80
82
 
81
83
  export type {
82
84
  AttributeValue,
@@ -365,7 +367,12 @@ function renderBlocks(blocks: BlockNode[], ctx: RenderCtx): ReactNode[] {
365
367
  return blocks.map((b, i) => renderBlock(b, ctx, i));
366
368
  }
367
369
 
368
- function renderBlock(block: BlockNode, ctx: RenderCtx, key: number): ReactNode {
370
+ function renderBlock(
371
+ block: BlockNode,
372
+ ctx: RenderCtx,
373
+ key: number,
374
+ first = key === 0,
375
+ ): ReactNode {
369
376
  const look = ctx.look;
370
377
  switch (block.type) {
371
378
  case 'paragraph':
@@ -378,7 +385,7 @@ function renderBlock(block: BlockNode, ctx: RenderCtx, key: number): ReactNode {
378
385
  weight: 700,
379
386
  });
380
387
  return richtext(key, runsOf(block.children, s), {
381
- marginTop: key === 0 ? 0 : Math.round(look.blockGap * 0.6),
388
+ marginTop: first ? 0 : Math.round(look.blockGap * 0.6),
382
389
  });
383
390
  }
384
391
 
@@ -493,24 +500,57 @@ function renderCode(
493
500
  custom({ lang, text, partial: ctx.live === true }),
494
501
  );
495
502
  }
496
- const code = ctx.look.code;
497
- const runs = codeBlockRuns(text, code, {
503
+ return h(CodeFence, {
504
+ key,
505
+ text,
498
506
  lang,
507
+ look: ctx.look.code,
499
508
  highlight: ctx.look.highlight,
500
- ...(ctx.resolveLanguage ? { resolveLanguage: ctx.resolveLanguage } : null),
509
+ resolveLanguage: ctx.resolveLanguage,
510
+ });
511
+ }
512
+
513
+ interface CodeFenceProps {
514
+ text: string;
515
+ lang: string;
516
+ look: CodeBlockLook;
517
+ highlight: boolean;
518
+ resolveLanguage?: MarkdownProps['resolveLanguage'];
519
+ }
520
+
521
+ /**
522
+ * A fenced block of code. A component rather than a render function so
523
+ * that it keeps a tokenizer between renders (`CodeBlockRunCache`): a fence
524
+ * being streamed is tokenized again from the line that changed, where it
525
+ * was tokenized whole for every token a model wrote.
526
+ */
527
+ function CodeFence(props: CodeFenceProps): ReactElement {
528
+ const { text, lang, look, highlight, resolveLanguage } = props;
529
+ const cache = React.useRef<CodeBlockRunCache | null>(null);
530
+ cache.current ??= new CodeBlockRunCache();
531
+ React.useEffect(() => () => cache.current?.dispose(), []);
532
+ const runs = cache.current.runs(text, look, {
533
+ lang,
534
+ highlight,
535
+ ...(resolveLanguage ? { resolveLanguage } : null),
501
536
  });
502
537
  // The block scrolls horizontally rather than wrapping — code is code.
503
538
  return hx(
504
539
  'box',
505
540
  {
506
- key,
507
541
  style: {
508
- ...codeBlockStyle(code),
542
+ ...codeBlockStyle(look),
509
543
  overflow: 'scroll',
510
544
  flexDirection: 'column',
511
545
  },
512
546
  },
513
- richtext('code', runs, codeTextStyle(code), false),
547
+ // in blocks of lines, so a fence that streams lays out the block its
548
+ // new lines land in (`../internal/codelines.ts`)
549
+ h(CodeLines, {
550
+ runs,
551
+ style: codeTextStyle(look, false),
552
+ wrap: false,
553
+ }),
514
554
  );
515
555
  }
516
556
 
@@ -553,38 +593,46 @@ function renderList(list: ListBlock, ctx: RenderCtx, key: number): ReactNode {
553
593
  ),
554
594
  );
555
595
  } else {
596
+ // the text itself, sized as the column the box around it used to be:
597
+ // a list is a few boxes per item, and at 600 KB there were 1,582 of
598
+ // these for yoga to lay out and absolutize on every width change
556
599
  marker = hx(
557
- 'box',
558
- { selectable: false, style: markerStyle },
559
- hx(
560
- 'text',
561
- {
562
- style: {
563
- color: look.dim,
564
- fontSize: look.inline.size,
565
- fontFamily: look.inline.family,
566
- },
600
+ 'text',
601
+ {
602
+ selectable: false,
603
+ style: {
604
+ flexShrink: 0,
605
+ width: markerWidth,
606
+ color: look.dim,
607
+ fontSize: look.inline.size,
608
+ fontFamily: look.inline.family,
567
609
  },
568
- list.ordered ? `${list.start + i}.` : '•',
569
- ),
610
+ },
611
+ list.ordered ? `${list.start + i}.` : '•',
570
612
  );
571
613
  }
614
+ const only = item.children.length === 1 ? item.children[0] : undefined;
572
615
  return hx(
573
616
  'box',
574
617
  { key: i, style: STYLES.itemRow },
575
618
  marker,
576
- hx(
577
- 'box',
578
- {
579
- style: {
580
- ...STYLES.column,
581
- gap: Math.round(look.blockGap * 0.4),
582
- flexGrow: 1,
583
- flexShrink: 1,
584
- },
585
- },
586
- ...renderBlocks(item.children, ctx),
587
- ),
619
+ // An item that is one paragraph — nearly every item — is the
620
+ // paragraph, taking the rest of the row; the column is for an item of
621
+ // several blocks, which needs the gap between them.
622
+ only?.type === 'paragraph'
623
+ ? richtext(0, runsOf(only.children, look.inline), STYLES.itemText)
624
+ : hx(
625
+ 'box',
626
+ {
627
+ style: {
628
+ ...STYLES.column,
629
+ gap: Math.round(look.blockGap * 0.4),
630
+ flexGrow: 1,
631
+ flexShrink: 1,
632
+ },
633
+ },
634
+ ...renderBlocks(item.children, ctx),
635
+ ),
588
636
  );
589
637
  });
590
638
  return hx('box', { key, style: { ...STYLES.column, gap } }, ...items);
@@ -595,34 +643,100 @@ function renderTable(
595
643
  ctx: RenderCtx,
596
644
  key: number,
597
645
  ): ReactNode {
598
- const look = ctx.look;
646
+ return h(MarkdownTable, { key, table, look: ctx.look, fonts: ctx.fonts });
647
+ }
648
+
649
+ interface MarkdownTableProps {
650
+ table: TableBlock;
651
+ look: Look;
652
+ fonts: FontsMeasureLike | null;
653
+ }
654
+
655
+ /** What a table keeps between renders. */
656
+ interface TableKept {
657
+ look: Look;
658
+ fonts: FontsMeasureLike | null;
659
+ /** Each cell's measured width, by what the cell holds. */
660
+ widthOf: Map<string, number>;
661
+ /** The column widths the rows were built at. */
662
+ widths: string;
663
+ /** Each row's element, by where it is and what it holds. */
664
+ rows: Map<string, ReactElement>;
665
+ }
666
+
667
+ /**
668
+ * A table. A component rather than a render function so that it keeps its
669
+ * rows between renders: a table that streams is a block whose source
670
+ * changes with every row, and it was measured cell by cell and rebuilt row
671
+ * by row for each — 115 ms a row at 800 rows, laying every row out again.
672
+ * Now a cell is measured once for what it holds, and a row keeps its
673
+ * element while it holds the same cells at the same column widths.
674
+ */
675
+ function MarkdownTable(props: MarkdownTableProps): ReactElement {
676
+ const { table, look, fonts } = props;
599
677
  const size = look.inline.size;
600
678
  const padX = Math.round(size * 0.6);
679
+ const padY = Math.round(size * 0.35);
601
680
  const cols = table.align.length;
602
681
 
682
+ const keptRef = React.useRef<TableKept | null>(null);
683
+ if (
684
+ !keptRef.current ||
685
+ keptRef.current.look !== look ||
686
+ keptRef.current.fonts !== fonts
687
+ ) {
688
+ keptRef.current = {
689
+ look,
690
+ fonts,
691
+ widthOf: new Map(),
692
+ widths: '',
693
+ rows: new Map(),
694
+ };
695
+ }
696
+ const kept = keptRef.current;
697
+
603
698
  // Column widths: max-content per column, measured through the app's font
604
699
  // manager, capped so one long cell cannot starve the rest. Without a
605
700
  // font manager (the mock backend) an even fallback keeps the shape.
606
701
  const widths: number[] = new Array<number>(cols).fill(0);
607
- const headStyles = inlineStyles(ctx, { weight: 700 });
608
- const measure = (cells: InlineNode[][], s: InlineStyles): void => {
702
+ const headStyles: InlineStyles = { ...look.inline, weight: 700 };
703
+ const widthOf = new Map<string, number>();
704
+ const measure = (
705
+ cells: InlineNode[][],
706
+ s: InlineStyles,
707
+ head: boolean,
708
+ ): string[] => {
709
+ const keys: string[] = [];
609
710
  for (let c = 0; c < cols; c += 1) {
610
- let w: number;
611
- if (ctx.fonts) {
612
- w = ctx.fonts.layout(runsOf(cells[c], s), {
613
- family: s.family,
614
- size: s.size,
615
- }).width;
616
- } else {
617
- w = plainTextOf(cells[c]).length * size * 0.55;
711
+ const cellKey = `${head ? 'h' : 'b'}${JSON.stringify(cells[c])}`;
712
+ keys.push(cellKey);
713
+ let w = widthOf.get(cellKey) ?? kept.widthOf.get(cellKey);
714
+ if (w === undefined) {
715
+ if (fonts) {
716
+ w = fonts.layout(runsOf(cells[c], s), {
717
+ family: s.family,
718
+ size: s.size,
719
+ }).width;
720
+ } else {
721
+ w = plainTextOf(cells[c]).length * size * 0.55;
722
+ }
618
723
  }
724
+ widthOf.set(cellKey, w);
619
725
  widths[c] = Math.max(widths[c], Math.min(Math.ceil(w), size * 26));
620
726
  }
727
+ return keys;
621
728
  };
622
- measure(table.header, headStyles);
623
- for (const row of table.rows) measure(row, look.inline);
729
+ const headKeys = measure(table.header, headStyles, true);
730
+ const rowKeys = table.rows.map((row) => measure(row, look.inline, false));
731
+ kept.widthOf = widthOf;
624
732
  for (let c = 0; c < cols; c += 1)
625
733
  widths[c] = Math.max(widths[c] + padX * 2 + 2, size * 2.5);
734
+ // a column that grew is every row laid out again
735
+ const widthsKey = `${widths.join(',')}|${table.align.join(',')}`;
736
+ if (widthsKey !== kept.widths) {
737
+ kept.widths = widthsKey;
738
+ kept.rows = new Map();
739
+ }
626
740
 
627
741
  // Nothing here says "these are cells and those are rows": a copy reads the
628
742
  // boxes below, where two cells share a band of pixels and the next row
@@ -633,7 +747,7 @@ function renderTable(
633
747
  rowKey: string | number,
634
748
  bg?: string,
635
749
  divided?: boolean,
636
- ): ReactNode =>
750
+ ): ReactElement =>
637
751
  hx(
638
752
  'box',
639
753
  {
@@ -645,38 +759,53 @@ function renderTable(
645
759
  borderTopColor: divided ? look.border : undefined,
646
760
  },
647
761
  },
762
+ // A cell is its text. The padding it needs is a margin: the cell has
763
+ // no background or border of its own — the row paints both — so the
764
+ // space around the text looks the same either way, and there is no
765
+ // box per cell for yoga to lay out.
648
766
  ...cells.map((cell, c) =>
649
- h(
650
- 'box',
651
- {
652
- key: c,
653
- style: {
654
- width: widths[c],
655
- paddingLeft: padX,
656
- paddingRight: padX,
657
- paddingTop: Math.round(size * 0.35),
658
- paddingBottom: Math.round(size * 0.35),
659
- },
660
- },
661
- richtext('c', runsOf(cell, s), {
662
- textAlign: table.align[c] ?? undefined,
663
- flexGrow: 1,
664
- }),
665
- ),
767
+ richtext(c, runsOf(cell, s), {
768
+ textAlign: table.align[c] ?? undefined,
769
+ width: widths[c] - padX * 2,
770
+ marginLeft: padX,
771
+ marginRight: padX,
772
+ marginTop: padY,
773
+ marginBottom: padY,
774
+ }),
666
775
  ),
667
776
  );
668
777
 
669
- const children: ReactNode[] = [];
670
- children.push(renderRow(table.header, headStyles, 'h', look.headerBg));
671
- table.rows.forEach((row, r) => {
672
- children.push(renderRow(row, look.inline, r, undefined, true));
778
+ const rows = new Map<string, ReactElement>();
779
+ const row = (
780
+ id: string,
781
+ cellKeys: string[],
782
+ make: () => ReactElement,
783
+ ): ReactElement => {
784
+ const rowKey = `${id}|${cellKeys.join('|')}`;
785
+ const element = kept.rows.get(rowKey) ?? make();
786
+ rows.set(rowKey, element);
787
+ return element;
788
+ };
789
+ const children: ReactElement[] = [];
790
+ children.push(
791
+ row('h', headKeys, () =>
792
+ renderRow(table.header, headStyles, 'h', look.headerBg),
793
+ ),
794
+ );
795
+ table.rows.forEach((cells, r) => {
796
+ children.push(
797
+ row(String(r), rowKeys[r]!, () =>
798
+ renderRow(cells, look.inline, r, undefined, true),
799
+ ),
800
+ );
673
801
  });
802
+ kept.rows = rows;
674
803
 
675
804
  // A wide table scrolls inside its own viewport instead of forcing the
676
805
  // document wider (the root stays vertical-only).
677
806
  return hx(
678
807
  'box',
679
- { key, style: { overflow: 'scroll', flexDirection: 'column' } },
808
+ { style: { overflow: 'scroll', flexDirection: 'column' } },
680
809
  hx(
681
810
  'box',
682
811
  {
@@ -696,14 +825,26 @@ function renderTable(
696
825
  const STYLES = {
697
826
  column: { flexDirection: 'column' },
698
827
  itemRow: { flexDirection: 'row' },
828
+ itemText: { flexGrow: 1, flexShrink: 1 },
699
829
  markerBox: { flexDirection: 'row', flexShrink: 0 },
700
830
  } as const satisfies Record<string, Style>;
701
831
 
702
832
  // --- the component ---------------------------------------------------------
703
833
 
834
+ /** What the last render made for one top-level block. */
835
+ interface RenderedBlock {
836
+ raw: string;
837
+ live: boolean;
838
+ first: boolean;
839
+ key: number;
840
+ element: ReactNode;
841
+ }
842
+
704
843
  interface BlockCache {
705
844
  epoch: string;
706
- map: Map<string, ReactNode>;
845
+ blocks: RenderedBlock[];
846
+ /** a key no block has had */
847
+ next: number;
707
848
  }
708
849
 
709
850
  /**
@@ -725,6 +866,14 @@ export function Markdown(props: MarkdownProps): ReactElement {
725
866
  // same widening `hx.ts` documents for the `theme` prop.
726
867
  const theme = useTheme() as unknown as Record<string, unknown>;
727
868
  const app = useApp() as { fonts?: FontsMeasureLike } | null;
869
+ // a document with code in it sets that code in the mono family, and its
870
+ // render is the head start (a fence or a code span needs a backtick or a
871
+ // tilde fence; an indented block is rare enough to find its own way)
872
+ useFontPrewarm(
873
+ source.includes('`') || source.includes('~~~')
874
+ ? (props.monoFamily ?? 'monospace')
875
+ : null,
876
+ );
728
877
 
729
878
  const links = useLinkClicks(onLink);
730
879
  const menu = useSelectionMenu(selectable);
@@ -760,12 +909,19 @@ export function Markdown(props: MarkdownProps): ReactElement {
760
909
  [scope],
761
910
  );
762
911
 
912
+ // The last parse, which the next one resumes from: an edit or a streamed
913
+ // chunk reads the blocks around the change, and a 600 KB document is not
914
+ // read again whole for one paragraph (ParseOptions.previous). Only ever a
915
+ // hint — a parse resumed from it answers what a parse from scratch would.
916
+ const lastParse = React.useRef<Document | null>(null);
763
917
  const doc: Document = React.useMemo(() => {
764
918
  const parsed = parse(source, {
765
919
  partial,
766
920
  ...(isComponent ? { isComponent } : null),
767
921
  ...(evaluate ? { expressions: true } : null),
922
+ ...(lastParse.current ? { previous: lastParse.current } : null),
768
923
  });
924
+ lastParse.current = parsed;
769
925
  // Expressions resolve to text here rather than during the render, so
770
926
  // every `runsOf` caller downstream keeps seeing an inline tree it
771
927
  // already understands. `raws` is carried through, so the block cache
@@ -774,10 +930,18 @@ export function Markdown(props: MarkdownProps): ReactElement {
774
930
  return evaluate ? resolveExpressions(parsed, evaluate) : parsed;
775
931
  }, [source, partial, isComponent, evaluate]);
776
932
 
777
- // Per-block element cache, keyed on the block's raw source (+ whether it
778
- // is the live tail). Streaming appends re-render only the block that
779
- // changed; everything else is the same ReactElement, so React bails out
780
- // and the retained nodes keep their layout caches.
933
+ // Per-block element cache: a block whose raw source is what it was (and
934
+ // is still the live tail, or not, and still first, or not) is the same
935
+ // ReactElement, so React bails out and the retained nodes keep their
936
+ // layout caches. Streaming appends re-render only the block that changed.
937
+ //
938
+ // Each block keeps its React key from one render to the next, found by
939
+ // lining the blocks up with the last render's from both ends: those the
940
+ // change left alone keep theirs, and the changed ones in the middle take
941
+ // the keys of the ones they replace, in order, so an edited paragraph is
942
+ // updated where it stands. Keyed by index, a paragraph inserted mid-way
943
+ // moved every block after it onto another block's key, and all of them
944
+ // were rendered and laid out again: a second, in a 600 KB document.
781
945
  const cacheRef = React.useRef<BlockCache | null>(null);
782
946
  const fonts = app?.fonts ?? null;
783
947
  // Neither the fences map nor `resolveLanguage` can be part of a string
@@ -812,13 +976,35 @@ export function Markdown(props: MarkdownProps): ReactElement {
812
976
  }
813
977
  const epoch = `${look.key}|${fonts ? 'f' : '-'}|${seamsRef.current.gen}`;
814
978
  if (!cacheRef.current || cacheRef.current.epoch !== epoch) {
815
- cacheRef.current = { epoch, map: new Map() };
979
+ // the keys carry over, so a new epoch updates each block in place
980
+ cacheRef.current = {
981
+ epoch,
982
+ blocks: (cacheRef.current?.blocks ?? []).map((b) => ({
983
+ ...b,
984
+ element: undefined,
985
+ })),
986
+ next: cacheRef.current?.next ?? 0,
987
+ };
816
988
  }
817
989
  const cache = cacheRef.current;
818
990
 
819
991
  const children: ReactNode[] = [];
820
992
  {
821
- const nextMap = new Map<string, ReactNode>();
993
+ const was = cache.blocks;
994
+ const n = doc.blocks.length;
995
+ let head = 0;
996
+ while (head < n && head < was.length && was[head].raw === doc.raws[head]) {
997
+ head += 1;
998
+ }
999
+ let tail = 0;
1000
+ while (
1001
+ tail < n - head &&
1002
+ tail < was.length - head &&
1003
+ was[was.length - 1 - tail].raw === doc.raws[n - 1 - tail]
1004
+ ) {
1005
+ tail += 1;
1006
+ }
1007
+ const kept: RenderedBlock[] = [];
822
1008
  const ctx: RenderCtx = {
823
1009
  look,
824
1010
  fonts,
@@ -827,24 +1013,39 @@ export function Markdown(props: MarkdownProps): ReactElement {
827
1013
  components: props.components,
828
1014
  ...(evaluate ? { evaluate } : null),
829
1015
  };
830
- for (let i = 0; i < doc.blocks.length; i += 1) {
831
- const live = partial && i === doc.blocks.length - 1;
832
- const cacheKey = `${i}|${live ? 'L' : '.'}|${doc.raws[i]}`;
833
- const hit = cache.map.get(cacheKey) ?? nextMap.get(cacheKey);
834
- if (hit !== undefined) {
835
- children.push(hit);
836
- nextMap.set(cacheKey, hit);
837
- continue;
838
- }
839
- const element = renderBlock(
840
- doc.blocks[i],
841
- live ? { ...ctx, live } : ctx,
842
- i,
843
- );
1016
+ for (let i = 0; i < n; i += 1) {
1017
+ const raw = doc.raws[i];
1018
+ const live = partial && i === n - 1;
1019
+ const first = i === 0;
1020
+ // the block this one stands for in the last render, if any
1021
+ const before =
1022
+ i < head
1023
+ ? was[i]
1024
+ : i >= n - tail
1025
+ ? was[was.length - n + i]
1026
+ : i < was.length - tail
1027
+ ? was[i]
1028
+ : undefined;
1029
+ const key = before ? before.key : cache.next++;
1030
+ const element =
1031
+ before &&
1032
+ before.element !== undefined &&
1033
+ before.raw === raw &&
1034
+ before.live === live &&
1035
+ before.first === first
1036
+ ? before.element
1037
+ : renderBlock(
1038
+ doc.blocks[i],
1039
+ live ? { ...ctx, live } : ctx,
1040
+ key,
1041
+ first,
1042
+ );
844
1043
  children.push(element);
845
- nextMap.set(cacheKey, element);
1044
+ kept.push({ raw, live, first, key, element });
846
1045
  }
847
- cache.map = nextMap; // old entries fall away with the text that made them
1046
+ // what the next render lines up against; the rest falls away with the
1047
+ // text that made it
1048
+ cache.blocks = kept;
848
1049
  }
849
1050
 
850
1051
  const rootStyle: Style = {
@@ -88,6 +88,11 @@ function pushRun(
88
88
  out: TextRun[],
89
89
  ): void {
90
90
  if (text.length === 0) return;
91
+ // A tab in running text reads as a space, as HTML sets it, and each text
92
+ // engine draws U+0009 as whatever its font has for it: a box in ntk's
93
+ // fonts, CoreText's own stops 28 points apart. It is laid out as the
94
+ // space it reads as, the same length, so every offset holds.
95
+ if (text.includes('\t')) text = text.replace(/\t/g, ' ');
91
96
  const inLink = st.href !== undefined;
92
97
  const color = st.code ? s.codeColor : inLink ? s.linkColor : s.color;
93
98
  const run: TextRun = {
@@ -25,6 +25,7 @@ import {
25
25
  } from './view-utils.js';
26
26
  import { delegateExtras, resolveModel } from './models.js';
27
27
  import { warn } from './globals.js';
28
+ import { scaleOf } from '../internal/units.js';
28
29
 
29
30
  // --- positioners -----------------------------------------------------------
30
31
 
@@ -126,7 +127,11 @@ function FlickableView({ inst }: { inst: QmlInstance }): ReactElement {
126
127
  useEffect(() => {
127
128
  const node = hostNode(inst) as ScrollableNode | null;
128
129
  if (!node || typeof node.scrollTo !== 'function') return;
129
- if (node.scrollX !== cx || node.scrollY !== cy)
130
+ // The node's offsets are device pixels; `contentX`/`contentY`,
131
+ // `scrollTo` and `onScroll`'s payload are logical. Compared raw, every
132
+ // scroll the pane made came back to it as a `scrollTo` to where it was.
133
+ const s = scaleOf(node);
134
+ if (node.scrollX / s !== cx || node.scrollY / s !== cy)
130
135
  node.scrollTo({ x: cx, y: cy });
131
136
  }, [inst, cx, cy]);
132
137
  return (
@@ -29,6 +29,7 @@ import {
29
29
  qmlColor,
30
30
  str,
31
31
  } from './view-utils.js';
32
+ import { scaleOf } from '../internal/units.js';
32
33
 
33
34
  // --- Keys + focus ----------------------------------------------------------
34
35
 
@@ -56,6 +57,7 @@ interface PointerEventLike {
56
57
  interface WheelEventLike extends PointerEventLike {
57
58
  deltaX?: number;
58
59
  deltaY?: number;
60
+ smooth?: boolean;
59
61
  }
60
62
 
61
63
  // Qt's modifier flags, so `mouse.modifiers & Qt.ShiftModifier` reads as
@@ -130,6 +132,20 @@ export function keyFocusProps(inst: QmlInstance): Record<string, unknown> {
130
132
 
131
133
  // --- MouseArea -------------------------------------------------------------
132
134
 
135
+ // The wheel, from react-x11's units into Qt's. react-x11 hands a handler
136
+ // logical pixels, 48 to a notch (its `WheelEvent` declaration), positive
137
+ // where the content advances: down, and right. Qt's `angleDelta` is eighths
138
+ // of a degree, 120 to a notch, positive where the wheel turns away from the
139
+ // user: up, and *left* — xcb's plugin maps button 6 to +120, and
140
+ // `QWheelEvent::inverted` and `QAbstractSlider` both say a scroll to the
141
+ // right is negative. (The QML WheelEvent page says "up/right"; every
142
+ // platform plugin disagrees.) So both axes flip, and a notch down is -120.
143
+ const ANGLE_PER_PX = 120 / 48;
144
+
145
+ /** One axis of Qt's wheel from react-x11's: flipped, times `per`. */
146
+ const qtWheelAxis = (px: number | undefined, per = 1): number =>
147
+ px ? -px * per : 0; // an axis that did not move is 0, not -0
148
+
133
149
  function MouseAreaView({ inst }: { inst: QmlInstance }): ReactElement {
134
150
  const enabled = inst.slot('enabled').peek() !== false;
135
151
  const hoverEnabled = inst.slot('hoverEnabled').peek() === true;
@@ -137,10 +153,16 @@ function MouseAreaView({ inst }: { inst: QmlInstance }): ReactElement {
137
153
  applyMotion(inst, style);
138
154
 
139
155
  const mouse = (e: PointerEventLike) => {
140
- const abs = hostNode(inst)?.abs;
156
+ // `e.x` is logical and `abs` device (react-x11's docs/scale.md), so the
157
+ // area's origin is divided into the event's unit first. Not
158
+ // `getClientRects()`, the same box already divided: it answers nothing
159
+ // for a box with no area, and a 0×0 MouseArea still hears a click on a
160
+ // child that hangs outside it.
161
+ const node = hostNode(inst);
162
+ const s = scaleOf(node);
141
163
  return {
142
- x: e.x - (abs?.x ?? 0),
143
- y: e.y - (abs?.y ?? 0),
164
+ x: e.x - (node?.abs.x ?? 0) / s,
165
+ y: e.y - (node?.abs.y ?? 0) / s,
144
166
  button: e.button,
145
167
  modifiers: modifiersOf(e),
146
168
  accepted: true,
@@ -170,7 +192,18 @@ function MouseAreaView({ inst }: { inst: QmlInstance }): ReactElement {
170
192
  handlers.onWheel = (e: WheelEventLike) => {
171
193
  inst.emit('wheel', {
172
194
  ...mouse(e),
173
- angleDelta: { x: e.deltaX ?? 0, y: e.deltaY ?? 0 },
195
+ angleDelta: {
196
+ x: qtWheelAxis(e.deltaX, ANGLE_PER_PX),
197
+ y: qtWheelAxis(e.deltaY, ANGLE_PER_PX),
198
+ },
199
+ // Pixels only where a device measured them — a touchpad, a
200
+ // high-resolution wheel: react-x11's `smooth`. A notch's 48 are a
201
+ // toolkit's choice rather than a measurement, so a notched wheel
202
+ // leaves (0, 0), as Qt's X11 plugin does, and a handler falls back
203
+ // to angleDelta the way Qt's docs tell it to.
204
+ pixelDelta: e.smooth
205
+ ? { x: qtWheelAxis(e.deltaX), y: qtWheelAxis(e.deltaY) }
206
+ : { x: 0, y: 0 },
174
207
  });
175
208
  };
176
209
  if (hoverEnabled) {
@@ -229,7 +262,11 @@ function useImplicitLineHeight(inst: QmlInstance, text: string): void {
229
262
  text || 'Mg',
230
263
  node.resolvedTextStyle(),
231
264
  );
232
- inst.slots.get('implicitHeight')?.assign(Math.ceil(probe.height) + 8);
265
+ // Laid out at the resolved size, which is the device one (TextView,
266
+ // in qtquick.tsx), so the height is divided back into logical pixels.
267
+ inst.slots
268
+ .get('implicitHeight')
269
+ ?.assign(Math.ceil(probe.height / scaleOf(node)) + 8);
233
270
  } catch {
234
271
  // No fonts loaded (headless without the fonts option): leave 0.
235
272
  }