@react-x11/components 0.8.0 → 0.10.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 (721) hide show
  1. package/README.md +105 -38
  2. package/dist/charts/node.d.ts +12 -2
  3. package/dist/charts/node.d.ts.map +1 -1
  4. package/dist/charts/node.js +50 -16
  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 +3 -1
  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/languages/glsl.d.ts.map +1 -1
  24. package/dist/code-language/languages/glsl.js +10 -2
  25. package/dist/code-language/languages/glsl.js.map +1 -1
  26. package/dist/code-language/languages/javascript.d.ts.map +1 -1
  27. package/dist/code-language/languages/javascript.js +18 -3
  28. package/dist/code-language/languages/javascript.js.map +1 -1
  29. package/dist/code-language/languages/json.d.ts.map +1 -1
  30. package/dist/code-language/languages/json.js +10 -2
  31. package/dist/code-language/languages/json.js.map +1 -1
  32. package/dist/code-language/languages/shell.d.ts.map +1 -1
  33. package/dist/code-language/languages/shell.js +10 -2
  34. package/dist/code-language/languages/shell.js.map +1 -1
  35. package/dist/code-language/languages/sql.d.ts.map +1 -1
  36. package/dist/code-language/languages/sql.js +20 -2
  37. package/dist/code-language/languages/sql.js.map +1 -1
  38. package/dist/code-language/stream.d.ts +22 -0
  39. package/dist/code-language/stream.d.ts.map +1 -1
  40. package/dist/code-language/stream.js +259 -9
  41. package/dist/code-language/stream.js.map +1 -1
  42. package/dist/code-language/types.d.ts +5 -4
  43. package/dist/code-language/types.d.ts.map +1 -1
  44. package/dist/codeblock/index.d.ts +13 -2
  45. package/dist/codeblock/index.d.ts.map +1 -1
  46. package/dist/codeblock/index.js +20 -3
  47. package/dist/codeblock/index.js.map +1 -1
  48. package/dist/embed/client.d.ts +48 -3
  49. package/dist/embed/client.d.ts.map +1 -1
  50. package/dist/embed/client.js +79 -5
  51. package/dist/embed/client.js.map +1 -1
  52. package/dist/embed/index.d.ts +1 -1
  53. package/dist/embed/index.d.ts.map +1 -1
  54. package/dist/embed/index.js +1 -1
  55. package/dist/embed/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 +240 -6
  115. package/dist/html/css/cascade.d.ts.map +1 -1
  116. package/dist/html/css/cascade.js +1327 -66
  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 +498 -15
  139. package/dist/html/css/style.d.ts.map +1 -1
  140. package/dist/html/css/style.js +3698 -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 +57 -11
  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 +2937 -197
  172. package/dist/html/layout/block.js.map +1 -1
  173. package/dist/html/layout/boxes.d.ts +340 -17
  174. package/dist/html/layout/boxes.d.ts.map +1 -1
  175. package/dist/html/layout/boxes.js +1714 -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 +151 -1
  205. package/dist/html/layout/inline.d.ts.map +1 -1
  206. package/dist/html/layout/inline.js +3375 -174
  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 +172 -5
  221. package/dist/html/node.d.ts.map +1 -1
  222. package/dist/html/node.js +1336 -103
  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 +3503 -141
  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 +435 -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 +2 -2
  245. package/dist/index.d.ts.map +1 -1
  246. package/dist/index.js +1 -1
  247. package/dist/index.js.map +1 -1
  248. package/dist/internal/collate.d.ts +3 -0
  249. package/dist/internal/collate.d.ts.map +1 -0
  250. package/dist/internal/collate.js +11 -0
  251. package/dist/internal/collate.js.map +1 -0
  252. package/dist/{markdown → internal/markdown}/ast.d.ts +23 -0
  253. package/dist/internal/markdown/ast.d.ts.map +1 -0
  254. package/dist/internal/markdown/ast.js +22 -0
  255. package/dist/internal/markdown/ast.js.map +1 -0
  256. package/dist/internal/markdown/parse.d.ts.map +1 -0
  257. package/dist/{markdown → internal/markdown}/parse.js +221 -30
  258. package/dist/internal/markdown/parse.js.map +1 -0
  259. package/dist/internal/markdown/stringify.d.ts +4 -0
  260. package/dist/internal/markdown/stringify.d.ts.map +1 -0
  261. package/dist/internal/markdown/stringify.js +684 -0
  262. package/dist/internal/markdown/stringify.js.map +1 -0
  263. package/dist/internal/markdown/tags.d.ts.map +1 -0
  264. package/dist/internal/markdown/tags.js.map +1 -0
  265. package/dist/internal/prewarm.d.ts +18 -0
  266. package/dist/internal/prewarm.d.ts.map +1 -0
  267. package/dist/internal/prewarm.js +42 -0
  268. package/dist/internal/prewarm.js.map +1 -0
  269. package/dist/internal/scroll.d.ts +3 -2
  270. package/dist/internal/scroll.d.ts.map +1 -1
  271. package/dist/internal/scroll.js +1 -0
  272. package/dist/internal/scroll.js.map +1 -1
  273. package/dist/internal/sdf.d.ts +20 -0
  274. package/dist/internal/sdf.d.ts.map +1 -0
  275. package/dist/internal/sdf.js +216 -0
  276. package/dist/internal/sdf.js.map +1 -0
  277. package/dist/internal/splice.d.ts +12 -0
  278. package/dist/internal/splice.d.ts.map +1 -0
  279. package/dist/internal/splice.js +23 -0
  280. package/dist/internal/splice.js.map +1 -0
  281. package/dist/internal/window.d.ts +12 -0
  282. package/dist/internal/window.d.ts.map +1 -1
  283. package/dist/internal/window.js +23 -6
  284. package/dist/internal/window.js.map +1 -1
  285. package/dist/maps/anchors.d.ts +103 -0
  286. package/dist/maps/anchors.d.ts.map +1 -0
  287. package/dist/maps/anchors.js +790 -0
  288. package/dist/maps/anchors.js.map +1 -0
  289. package/dist/maps/controller.d.ts +340 -0
  290. package/dist/maps/controller.d.ts.map +1 -0
  291. package/dist/maps/controller.js +822 -0
  292. package/dist/maps/controller.js.map +1 -0
  293. package/dist/maps/gl/buckets.d.ts +99 -0
  294. package/dist/maps/gl/buckets.d.ts.map +1 -0
  295. package/dist/maps/gl/buckets.js +365 -0
  296. package/dist/maps/gl/buckets.js.map +1 -0
  297. package/dist/maps/gl/build-worker.d.ts +15 -0
  298. package/dist/maps/gl/build-worker.d.ts.map +1 -0
  299. package/dist/maps/gl/build-worker.js +44 -0
  300. package/dist/maps/gl/build-worker.js.map +1 -0
  301. package/dist/maps/gl/color.d.ts +8 -0
  302. package/dist/maps/gl/color.d.ts.map +1 -0
  303. package/dist/maps/gl/color.js +57 -0
  304. package/dist/maps/gl/color.js.map +1 -0
  305. package/dist/maps/gl/cover.d.ts +70 -0
  306. package/dist/maps/gl/cover.d.ts.map +1 -0
  307. package/dist/maps/gl/cover.js +137 -0
  308. package/dist/maps/gl/cover.js.map +1 -0
  309. package/dist/maps/gl/index.d.ts +3 -0
  310. package/dist/maps/gl/index.d.ts.map +1 -0
  311. package/dist/maps/gl/index.js +20 -0
  312. package/dist/maps/gl/index.js.map +1 -0
  313. package/dist/maps/gl/markers.d.ts +28 -0
  314. package/dist/maps/gl/markers.d.ts.map +1 -0
  315. package/dist/maps/gl/markers.js +60 -0
  316. package/dist/maps/gl/markers.js.map +1 -0
  317. package/dist/maps/gl/overlays.d.ts +68 -0
  318. package/dist/maps/gl/overlays.d.ts.map +1 -0
  319. package/dist/maps/gl/overlays.js +300 -0
  320. package/dist/maps/gl/overlays.js.map +1 -0
  321. package/dist/maps/gl/pane.d.ts +12 -0
  322. package/dist/maps/gl/pane.d.ts.map +1 -0
  323. package/dist/maps/gl/pane.js +37 -0
  324. package/dist/maps/gl/pane.js.map +1 -0
  325. package/dist/maps/gl/placement.d.ts +124 -0
  326. package/dist/maps/gl/placement.d.ts.map +1 -0
  327. package/dist/maps/gl/placement.js +642 -0
  328. package/dist/maps/gl/placement.js.map +1 -0
  329. package/dist/maps/gl/renderer.d.ts +384 -0
  330. package/dist/maps/gl/renderer.d.ts.map +1 -0
  331. package/dist/maps/gl/renderer.js +1184 -0
  332. package/dist/maps/gl/renderer.js.map +1 -0
  333. package/dist/maps/gl/shaders.d.ts +121 -0
  334. package/dist/maps/gl/shaders.d.ts.map +1 -0
  335. package/dist/maps/gl/shaders.js +453 -0
  336. package/dist/maps/gl/shaders.js.map +1 -0
  337. package/dist/maps/gl/store.d.ts +125 -0
  338. package/dist/maps/gl/store.d.ts.map +1 -0
  339. package/dist/maps/gl/store.js +512 -0
  340. package/dist/maps/gl/store.js.map +1 -0
  341. package/dist/maps/gl/text.d.ts +283 -0
  342. package/dist/maps/gl/text.d.ts.map +1 -0
  343. package/dist/maps/gl/text.js +698 -0
  344. package/dist/maps/gl/text.js.map +1 -0
  345. package/dist/maps/gl/view.d.ts +345 -0
  346. package/dist/maps/gl/view.d.ts.map +1 -0
  347. package/dist/maps/gl/view.js +1209 -0
  348. package/dist/maps/gl/view.js.map +1 -0
  349. package/dist/maps/icons.d.ts +32 -0
  350. package/dist/maps/icons.d.ts.map +1 -0
  351. package/dist/maps/icons.js +151 -0
  352. package/dist/maps/icons.js.map +1 -0
  353. package/dist/maps/index.d.ts +3 -1
  354. package/dist/maps/index.d.ts.map +1 -1
  355. package/dist/maps/index.js +218 -52
  356. package/dist/maps/index.js.map +1 -1
  357. package/dist/maps/labels.d.ts +91 -18
  358. package/dist/maps/labels.d.ts.map +1 -1
  359. package/dist/maps/labels.js +376 -140
  360. package/dist/maps/labels.js.map +1 -1
  361. package/dist/maps/node.d.ts +179 -56
  362. package/dist/maps/node.d.ts.map +1 -1
  363. package/dist/maps/node.js +663 -537
  364. package/dist/maps/node.js.map +1 -1
  365. package/dist/maps/overlay.d.ts +72 -9
  366. package/dist/maps/overlay.d.ts.map +1 -1
  367. package/dist/maps/overlay.js +108 -28
  368. package/dist/maps/overlay.js.map +1 -1
  369. package/dist/maps/paint.d.ts +3 -0
  370. package/dist/maps/paint.d.ts.map +1 -1
  371. package/dist/maps/paint.js.map +1 -1
  372. package/dist/maps/proj.d.ts +62 -0
  373. package/dist/maps/proj.d.ts.map +1 -1
  374. package/dist/maps/proj.js +101 -0
  375. package/dist/maps/proj.js.map +1 -1
  376. package/dist/maps/renderer.d.ts +69 -0
  377. package/dist/maps/renderer.d.ts.map +1 -0
  378. package/dist/maps/renderer.js +66 -0
  379. package/dist/maps/renderer.js.map +1 -0
  380. package/dist/maps/sources.d.ts +30 -6
  381. package/dist/maps/sources.d.ts.map +1 -1
  382. package/dist/maps/sources.js +22 -3
  383. package/dist/maps/sources.js.map +1 -1
  384. package/dist/maps/style.d.ts +35 -0
  385. package/dist/maps/style.d.ts.map +1 -1
  386. package/dist/maps/style.js.map +1 -1
  387. package/dist/maps/styles.d.ts +12 -0
  388. package/dist/maps/styles.d.ts.map +1 -1
  389. package/dist/maps/styles.js +120 -6
  390. package/dist/maps/styles.js.map +1 -1
  391. package/dist/maps/theme.d.ts +19 -0
  392. package/dist/maps/theme.d.ts.map +1 -0
  393. package/dist/maps/theme.js +44 -0
  394. package/dist/maps/theme.js.map +1 -0
  395. package/dist/maps/tiles.d.ts +147 -27
  396. package/dist/maps/tiles.d.ts.map +1 -1
  397. package/dist/maps/tiles.js +221 -54
  398. package/dist/maps/tiles.js.map +1 -1
  399. package/dist/maps/types.d.ts +213 -21
  400. package/dist/maps/types.d.ts.map +1 -1
  401. package/dist/markdown/expressions.d.ts +1 -1
  402. package/dist/markdown/expressions.d.ts.map +1 -1
  403. package/dist/markdown/expressions.js.map +1 -1
  404. package/dist/markdown/index.d.ts +7 -6
  405. package/dist/markdown/index.d.ts.map +1 -1
  406. package/dist/markdown/index.js +121 -50
  407. package/dist/markdown/index.js.map +1 -1
  408. package/dist/markdown/spans.d.ts +1 -1
  409. package/dist/markdown/spans.d.ts.map +1 -1
  410. package/dist/markdown/spans.js +6 -0
  411. package/dist/markdown/spans.js.map +1 -1
  412. package/dist/media-player/index.d.ts +11 -3
  413. package/dist/media-player/index.d.ts.map +1 -1
  414. package/dist/media-player/index.js +13 -2
  415. package/dist/media-player/index.js.map +1 -1
  416. package/dist/qml/containers.d.ts.map +1 -1
  417. package/dist/qml/containers.js +6 -1
  418. package/dist/qml/containers.js.map +1 -1
  419. package/dist/qml/interaction.d.ts.map +1 -1
  420. package/dist/qml/interaction.js +38 -5
  421. package/dist/qml/interaction.js.map +1 -1
  422. package/dist/qml/layouts.d.ts.map +1 -1
  423. package/dist/qml/layouts.js +21 -6
  424. package/dist/qml/layouts.js.map +1 -1
  425. package/dist/qml/qtquick.d.ts.map +1 -1
  426. package/dist/qml/qtquick.js +9 -2
  427. package/dist/qml/qtquick.js.map +1 -1
  428. package/dist/qml/react.d.ts.map +1 -1
  429. package/dist/qml/react.js +9 -7
  430. package/dist/qml/react.js.map +1 -1
  431. package/dist/reorder/clock.d.ts +7 -0
  432. package/dist/reorder/clock.d.ts.map +1 -0
  433. package/dist/reorder/clock.js +26 -0
  434. package/dist/reorder/clock.js.map +1 -0
  435. package/dist/reorder/index.d.ts +25 -3
  436. package/dist/reorder/index.d.ts.map +1 -1
  437. package/dist/reorder/index.js +64 -19
  438. package/dist/reorder/index.js.map +1 -1
  439. package/dist/rich-text-editor/clipboard.d.ts +23 -0
  440. package/dist/rich-text-editor/clipboard.d.ts.map +1 -0
  441. package/dist/rich-text-editor/clipboard.js +307 -0
  442. package/dist/rich-text-editor/clipboard.js.map +1 -0
  443. package/dist/rich-text-editor/collab.d.ts +32 -0
  444. package/dist/rich-text-editor/collab.d.ts.map +1 -0
  445. package/dist/rich-text-editor/collab.js +55 -0
  446. package/dist/rich-text-editor/collab.js.map +1 -0
  447. package/dist/rich-text-editor/commands.d.ts +50 -0
  448. package/dist/rich-text-editor/commands.d.ts.map +1 -0
  449. package/dist/rich-text-editor/commands.js +376 -0
  450. package/dist/rich-text-editor/commands.js.map +1 -0
  451. package/dist/rich-text-editor/drag.d.ts +68 -0
  452. package/dist/rich-text-editor/drag.d.ts.map +1 -0
  453. package/dist/rich-text-editor/drag.js +148 -0
  454. package/dist/rich-text-editor/drag.js.map +1 -0
  455. package/dist/rich-text-editor/html.d.ts +145 -0
  456. package/dist/rich-text-editor/html.d.ts.map +1 -0
  457. package/dist/rich-text-editor/html.js +516 -0
  458. package/dist/rich-text-editor/html.js.map +1 -0
  459. package/dist/rich-text-editor/index.d.ts +252 -0
  460. package/dist/rich-text-editor/index.d.ts.map +1 -0
  461. package/dist/rich-text-editor/index.js +856 -0
  462. package/dist/rich-text-editor/index.js.map +1 -0
  463. package/dist/rich-text-editor/inline.d.ts +94 -0
  464. package/dist/rich-text-editor/inline.d.ts.map +1 -0
  465. package/dist/rich-text-editor/inline.js +252 -0
  466. package/dist/rich-text-editor/inline.js.map +1 -0
  467. package/dist/rich-text-editor/keymap.d.ts +71 -0
  468. package/dist/rich-text-editor/keymap.d.ts.map +1 -0
  469. package/dist/rich-text-editor/keymap.js +394 -0
  470. package/dist/rich-text-editor/keymap.js.map +1 -0
  471. package/dist/rich-text-editor/keys.d.ts +40 -0
  472. package/dist/rich-text-editor/keys.d.ts.map +1 -0
  473. package/dist/rich-text-editor/keys.js +202 -0
  474. package/dist/rich-text-editor/keys.js.map +1 -0
  475. package/dist/rich-text-editor/look.d.ts +71 -0
  476. package/dist/rich-text-editor/look.d.ts.map +1 -0
  477. package/dist/rich-text-editor/look.js +342 -0
  478. package/dist/rich-text-editor/look.js.map +1 -0
  479. package/dist/rich-text-editor/markdown.d.ts +18 -0
  480. package/dist/rich-text-editor/markdown.d.ts.map +1 -0
  481. package/dist/rich-text-editor/markdown.js +496 -0
  482. package/dist/rich-text-editor/markdown.js.map +1 -0
  483. package/dist/rich-text-editor/marks.d.ts +9 -0
  484. package/dist/rich-text-editor/marks.d.ts.map +1 -0
  485. package/dist/rich-text-editor/marks.js +83 -0
  486. package/dist/rich-text-editor/marks.js.map +1 -0
  487. package/dist/rich-text-editor/nodes.d.ts +135 -0
  488. package/dist/rich-text-editor/nodes.d.ts.map +1 -0
  489. package/dist/rich-text-editor/nodes.js +397 -0
  490. package/dist/rich-text-editor/nodes.js.map +1 -0
  491. package/dist/rich-text-editor/render.d.ts +68 -0
  492. package/dist/rich-text-editor/render.d.ts.map +1 -0
  493. package/dist/rich-text-editor/render.js +518 -0
  494. package/dist/rich-text-editor/render.js.map +1 -0
  495. package/dist/rich-text-editor/schema.d.ts +16 -0
  496. package/dist/rich-text-editor/schema.d.ts.map +1 -0
  497. package/dist/rich-text-editor/schema.js +386 -0
  498. package/dist/rich-text-editor/schema.js.map +1 -0
  499. package/dist/rich-text-editor/store.d.ts +11 -0
  500. package/dist/rich-text-editor/store.d.ts.map +1 -0
  501. package/dist/rich-text-editor/store.js +43 -0
  502. package/dist/rich-text-editor/store.js.map +1 -0
  503. package/dist/rich-text-editor/suggest.d.ts +127 -0
  504. package/dist/rich-text-editor/suggest.d.ts.map +1 -0
  505. package/dist/rich-text-editor/suggest.js +0 -0
  506. package/dist/rich-text-editor/suggest.js.map +1 -0
  507. package/dist/rich-text-editor/tables.d.ts +41 -0
  508. package/dist/rich-text-editor/tables.d.ts.map +1 -0
  509. package/dist/rich-text-editor/tables.js +204 -0
  510. package/dist/rich-text-editor/tables.js.map +1 -0
  511. package/dist/rich-text-editor/toolbar.d.ts +58 -0
  512. package/dist/rich-text-editor/toolbar.d.ts.map +1 -0
  513. package/dist/rich-text-editor/toolbar.js +548 -0
  514. package/dist/rich-text-editor/toolbar.js.map +1 -0
  515. package/dist/rich-text-editor/view.d.ts +368 -0
  516. package/dist/rich-text-editor/view.d.ts.map +1 -0
  517. package/dist/rich-text-editor/view.js +1968 -0
  518. package/dist/rich-text-editor/view.js.map +1 -0
  519. package/dist/rich-text-editor/virtual.d.ts +54 -0
  520. package/dist/rich-text-editor/virtual.d.ts.map +1 -0
  521. package/dist/rich-text-editor/virtual.js +279 -0
  522. package/dist/rich-text-editor/virtual.js.map +1 -0
  523. package/dist/richtext/node.d.ts +71 -4
  524. package/dist/richtext/node.d.ts.map +1 -1
  525. package/dist/richtext/node.js +233 -28
  526. package/dist/richtext/node.js.map +1 -1
  527. package/dist/richtext/runs.d.ts +13 -8
  528. package/dist/richtext/runs.d.ts.map +1 -1
  529. package/dist/richtext/runs.js +18 -8
  530. package/dist/richtext/runs.js.map +1 -1
  531. package/dist/table/index.d.ts.map +1 -1
  532. package/dist/table/index.js +23 -0
  533. package/dist/table/index.js.map +1 -1
  534. package/dist/table/rows.d.ts +3 -2
  535. package/dist/table/rows.d.ts.map +1 -1
  536. package/dist/table/rows.js +20 -6
  537. package/dist/table/rows.js.map +1 -1
  538. package/dist/terminal/backends.d.ts +4 -1
  539. package/dist/terminal/backends.d.ts.map +1 -1
  540. package/dist/terminal/backends.js.map +1 -1
  541. package/dist/terminal/index.d.ts +18 -7
  542. package/dist/terminal/index.d.ts.map +1 -1
  543. package/dist/terminal/index.js +32 -11
  544. package/dist/terminal/index.js.map +1 -1
  545. package/dist/terminal/vt/pty.d.ts +13 -2
  546. package/dist/terminal/vt/pty.d.ts.map +1 -1
  547. package/dist/terminal/vt/pty.js +18 -3
  548. package/dist/terminal/vt/pty.js.map +1 -1
  549. package/dist/terminal-output/index.d.ts.map +1 -1
  550. package/dist/terminal-output/index.js +6 -1
  551. package/dist/terminal-output/index.js.map +1 -1
  552. package/dist/three/canvas.d.ts.map +1 -1
  553. package/dist/three/canvas.js +85 -7
  554. package/dist/three/canvas.js.map +1 -1
  555. package/dist/three/events.d.ts +22 -4
  556. package/dist/three/events.d.ts.map +1 -1
  557. package/dist/three/events.js +34 -4
  558. package/dist/three/events.js.map +1 -1
  559. package/dist/tree/index.d.ts.map +1 -1
  560. package/dist/tree/index.js +17 -0
  561. package/dist/tree/index.js.map +1 -1
  562. package/package.json +59 -31
  563. package/src/charts/node.ts +68 -28
  564. package/src/charts/render.ts +120 -30
  565. package/src/code/index.ts +3 -1
  566. package/src/code-editor/completion.ts +3 -2
  567. package/src/code-editor/index.ts +19 -0
  568. package/src/code-editor/node.ts +1574 -184
  569. package/src/code-language/languages/glsl.ts +12 -2
  570. package/src/code-language/languages/javascript.ts +21 -4
  571. package/src/code-language/languages/json.ts +12 -2
  572. package/src/code-language/languages/shell.ts +12 -2
  573. package/src/code-language/languages/sql.ts +22 -2
  574. package/src/code-language/stream.ts +257 -17
  575. package/src/code-language/types.ts +5 -4
  576. package/src/codeblock/index.ts +20 -3
  577. package/src/embed/client.ts +102 -8
  578. package/src/embed/index.ts +2 -0
  579. package/src/flow/draw.ts +167 -41
  580. package/src/flow/gl/color.ts +85 -0
  581. package/src/flow/gl/index.ts +342 -0
  582. package/src/flow/gl/pack.ts +585 -0
  583. package/src/flow/gl/renderer.ts +679 -0
  584. package/src/flow/gl/shaders.ts +371 -0
  585. package/src/flow/gl/text.ts +1295 -0
  586. package/src/flow/index.ts +794 -67
  587. package/src/flow/node.ts +2496 -1256
  588. package/src/flow/paint.ts +511 -0
  589. package/src/flow/paths.ts +80 -15
  590. package/src/flow/scene.ts +2199 -0
  591. package/src/flow/types.ts +113 -1
  592. package/src/html/controls.ts +73 -2
  593. package/src/html/css/calc.ts +385 -0
  594. package/src/html/css/cascade.ts +1403 -62
  595. package/src/html/css/color.ts +755 -0
  596. package/src/html/css/content.ts +417 -0
  597. package/src/html/css/counter-styles.ts +973 -0
  598. package/src/html/css/decode.ts +130 -0
  599. package/src/html/css/parse.ts +1514 -160
  600. package/src/html/css/style.ts +4102 -222
  601. package/src/html/css/ua.ts +58 -12
  602. package/src/html/css/values.ts +150 -50
  603. package/src/html/css/vars.ts +348 -0
  604. package/src/html/dom.ts +284 -17
  605. package/src/html/fonts.ts +641 -0
  606. package/src/html/gif.ts +233 -0
  607. package/src/html/index.ts +180 -20
  608. package/src/html/layout/block.ts +3456 -230
  609. package/src/html/layout/boxes.ts +2100 -190
  610. package/src/html/layout/cache.ts +289 -0
  611. package/src/html/layout/collapse.ts +317 -0
  612. package/src/html/layout/css-grid.ts +1063 -0
  613. package/src/html/layout/flex.ts +1115 -106
  614. package/src/html/layout/floats.ts +128 -14
  615. package/src/html/layout/grid-lines.ts +141 -0
  616. package/src/html/layout/grid.ts +181 -0
  617. package/src/html/layout/inline.ts +3943 -192
  618. package/src/html/layout/shaping.ts +140 -0
  619. package/src/html/layout/table.ts +696 -186
  620. package/src/html/layout/tracks.ts +437 -0
  621. package/src/html/node.ts +1486 -121
  622. package/src/html/paint.ts +4293 -169
  623. package/src/html/resources.ts +161 -50
  624. package/src/html/surfaces.ts +81 -0
  625. package/src/html/svg.ts +493 -0
  626. package/src/html/url.ts +86 -0
  627. package/src/index.ts +4 -0
  628. package/src/internal/collate.ts +12 -0
  629. package/src/{markdown → internal/markdown}/ast.ts +35 -7
  630. package/src/{markdown → internal/markdown}/parse.ts +288 -35
  631. package/src/internal/markdown/stringify.ts +772 -0
  632. package/src/internal/prewarm.ts +45 -0
  633. package/src/internal/scroll.ts +5 -3
  634. package/src/internal/sdf.ts +227 -0
  635. package/src/internal/splice.ts +25 -0
  636. package/src/internal/window.ts +36 -5
  637. package/src/maps/anchors.ts +913 -0
  638. package/src/maps/controller.ts +1084 -0
  639. package/src/maps/gl/buckets.ts +461 -0
  640. package/src/maps/gl/build-worker.ts +66 -0
  641. package/src/maps/gl/color.ts +62 -0
  642. package/src/maps/gl/cover.ts +205 -0
  643. package/src/maps/gl/index.ts +23 -0
  644. package/src/maps/gl/markers.ts +83 -0
  645. package/src/maps/gl/overlays.ts +379 -0
  646. package/src/maps/gl/pane.ts +42 -0
  647. package/src/maps/gl/placement.ts +968 -0
  648. package/src/maps/gl/renderer.ts +1660 -0
  649. package/src/maps/gl/shaders.ts +489 -0
  650. package/src/maps/gl/store.ts +615 -0
  651. package/src/maps/gl/text.ts +868 -0
  652. package/src/maps/gl/view.ts +1489 -0
  653. package/src/maps/icons.ts +183 -0
  654. package/src/maps/index.ts +274 -81
  655. package/src/maps/labels.ts +457 -144
  656. package/src/maps/node.ts +832 -665
  657. package/src/maps/overlay.ts +148 -43
  658. package/src/maps/paint.ts +3 -0
  659. package/src/maps/proj.ts +118 -0
  660. package/src/maps/renderer.ts +155 -0
  661. package/src/maps/sources.ts +43 -6
  662. package/src/maps/style.ts +32 -0
  663. package/src/maps/styles.ts +215 -4
  664. package/src/maps/theme.ts +51 -0
  665. package/src/maps/tiles.ts +253 -62
  666. package/src/maps/types.ts +213 -21
  667. package/src/markdown/expressions.ts +5 -1
  668. package/src/markdown/index.ts +163 -78
  669. package/src/markdown/spans.ts +6 -1
  670. package/src/media-player/index.ts +18 -4
  671. package/src/qml/containers.tsx +6 -1
  672. package/src/qml/interaction.tsx +42 -5
  673. package/src/qml/layouts.tsx +21 -6
  674. package/src/qml/qtquick.tsx +9 -2
  675. package/src/qml/react.tsx +7 -5
  676. package/src/reorder/clock.ts +27 -0
  677. package/src/reorder/index.ts +100 -27
  678. package/src/rich-text-editor/clipboard.ts +439 -0
  679. package/src/rich-text-editor/collab.ts +91 -0
  680. package/src/rich-text-editor/commands.ts +448 -0
  681. package/src/rich-text-editor/dom-globals.d.ts +23 -0
  682. package/src/rich-text-editor/drag.ts +211 -0
  683. package/src/rich-text-editor/html.ts +619 -0
  684. package/src/rich-text-editor/index.ts +1364 -0
  685. package/src/rich-text-editor/inline.ts +345 -0
  686. package/src/rich-text-editor/keymap.ts +510 -0
  687. package/src/rich-text-editor/keys.ts +228 -0
  688. package/src/rich-text-editor/look.ts +427 -0
  689. package/src/rich-text-editor/markdown.ts +653 -0
  690. package/src/rich-text-editor/marks.ts +101 -0
  691. package/src/rich-text-editor/nodes.ts +497 -0
  692. package/src/rich-text-editor/render.ts +837 -0
  693. package/src/rich-text-editor/schema.ts +431 -0
  694. package/src/rich-text-editor/store.ts +39 -0
  695. package/src/rich-text-editor/suggest.ts +597 -0
  696. package/src/rich-text-editor/tables.ts +272 -0
  697. package/src/rich-text-editor/toolbar.ts +724 -0
  698. package/src/rich-text-editor/view.ts +2287 -0
  699. package/src/rich-text-editor/virtual.ts +372 -0
  700. package/src/richtext/node.ts +294 -44
  701. package/src/richtext/runs.ts +23 -12
  702. package/src/table/index.ts +29 -0
  703. package/src/table/rows.ts +18 -8
  704. package/src/terminal/backends.ts +4 -1
  705. package/src/terminal/index.ts +47 -15
  706. package/src/terminal/vt/pty.ts +16 -2
  707. package/src/terminal-output/index.ts +6 -1
  708. package/src/three/canvas.ts +102 -8
  709. package/src/three/events.ts +49 -9
  710. package/src/tree/index.ts +19 -0
  711. package/dist/markdown/ast.d.ts.map +0 -1
  712. package/dist/markdown/ast.js +0 -17
  713. package/dist/markdown/ast.js.map +0 -1
  714. package/dist/markdown/parse.d.ts.map +0 -1
  715. package/dist/markdown/parse.js.map +0 -1
  716. package/dist/markdown/tags.d.ts.map +0 -1
  717. package/dist/markdown/tags.js.map +0 -1
  718. /package/dist/{markdown → internal/markdown}/parse.d.ts +0 -0
  719. /package/dist/{markdown → internal/markdown}/tags.d.ts +0 -0
  720. /package/dist/{markdown → internal/markdown}/tags.js +0 -0
  721. /package/src/{markdown → internal/markdown}/tags.ts +0 -0
@@ -37,6 +37,7 @@ import {
37
37
  paintRunBackgrounds,
38
38
  paintRunRules,
39
39
  } from './runs.js';
40
+ import type { FillContext } from './runs.js';
40
41
  import { codeUnitOffsets } from '../internal/text.js';
41
42
 
42
43
  /** The element name — registration key, `node.kind` and JSX tag alike. */
@@ -81,6 +82,10 @@ export interface TextRun {
81
82
  weight?: number | 'normal' | 'bold';
82
83
  style?: 'normal' | 'italic';
83
84
  color?: string;
85
+ /** Pixels added after every glyph — CSS's `letter-spacing`. Both text
86
+ * engines take it on a span, and it passes through to them as the rest
87
+ * of the ntk vocabulary does. */
88
+ letterSpacing?: number;
84
89
  /** Fill painted behind the run — the inline-code chip. */
85
90
  bg?: string;
86
91
  /**
@@ -100,16 +105,37 @@ export interface TextRun {
100
105
  * sub-parameters, which a captured terminal session carries. Ignored
101
106
  * without `underline`, which is what says the rule exists at all. */
102
107
  underlineStyle?: 'single' | 'double' | 'curly' | 'dotted' | 'dashed';
108
+ /** How far below the baseline the underline's top is, and how thick it
109
+ * is, in the unit `size` is in — CSS's `text-underline-offset` and
110
+ * `text-decoration-thickness`. Unset, two pixels below and one thick. */
111
+ underlineOffset?: number;
112
+ underlineThickness?: number;
103
113
  /** 1px rule through the x-height, in this colour — `~~del~~`. */
104
114
  strike?: string;
105
115
  /** Link target. `null` is a link still streaming in (not clickable). */
106
116
  href?: string | null;
117
+ /** OpenType features the run is shaped with, by tag — `{ tnum: 1 }`,
118
+ * `{ liga: 0 }` — which both text engines take on a span. A run's fields
119
+ * are compared by identity (`sameRuns`), so the same features should be
120
+ * the same object. */
121
+ features?: Readonly<Record<string, number>>;
122
+ /** Runs that share a truthy `nowrap` have no break inside them or between
123
+ * them — the text of one element with `white-space: nowrap`, the element
124
+ * being the value. ntk's, from 8.13.0; CoreText breaks as it would. */
125
+ nowrap?: unknown;
126
+ /** Shaped on its own: ntk shapes a word that runs across spans shaped
127
+ * alike as one, kerned and joined across them, and a run marked so is
128
+ * kept apart from the ones either side of it — as CSS keeps the text
129
+ * either side of an inline box's margin, border or padding. ntk's, from
130
+ * 8.14.2. */
131
+ shapeApart?: boolean;
107
132
  }
108
133
 
109
134
  /** The props `<richtext>` takes. */
110
135
  export interface RichTextProps {
111
- /** The styled runs. Give a stable array identity — the layout cache and
112
- * the streaming path both key off it. */
136
+ /** The styled runs. Give a stable array identity where you can — the
137
+ * streaming path keys off it; an equal new array keeps its layout, for
138
+ * one pass over the runs (`sameRuns`). */
113
139
  runs: TextRun[];
114
140
  /** False lays the text out at its natural width, unwrapped — code. */
115
141
  wrap?: boolean;
@@ -177,6 +203,113 @@ interface FontsLike {
177
203
  ): TextLayoutLike;
178
204
  }
179
205
 
206
+ /** Spacing that tells runs apart and moves nothing: an engine that merges
207
+ * adjacent runs alike (CoreText) keeps a tab's space to itself. */
208
+ const HAIR = 1e-6;
209
+
210
+ /**
211
+ * The runs with each tab laid out as a space of its own, letter-spaced to
212
+ * the next stop: every eight spaces from its line's start, and past one
213
+ * less than half a "0" on (CSS Text 3, 4.2's `tab-size`). Neither engine
214
+ * sets a tab so — ntk has no glyph for one and draws a box, and CoreText
215
+ * stops every 28 points — so a tab-indented fence in `<Markdown>` or a
216
+ * `<Code>` block came out boxed or ragged. The space is the tab's length,
217
+ * so every offset holds, and the text a selection copies keeps its tabs.
218
+ * Placed from a first layout that has each tab as an unspaced space; a
219
+ * later tab on a line moves by what the ones before it added.
220
+ */
221
+ function tabbedRuns(
222
+ fonts: FontsLike,
223
+ runs: TextRun[],
224
+ base: Record<string, unknown>,
225
+ ): TextRun[] {
226
+ const out: TextRun[] = [];
227
+ const tabs: { at: number; index: number }[] = [];
228
+ let units = 0;
229
+ for (const run of runs) {
230
+ const text = run.text;
231
+ if (!text.includes('\t')) {
232
+ out.push(run);
233
+ units += text.length;
234
+ continue;
235
+ }
236
+ let done = 0;
237
+ for (let p = text.indexOf('\t'); p >= 0; p = text.indexOf('\t', p + 1)) {
238
+ if (p > done) out.push({ ...run, text: text.slice(done, p) });
239
+ tabs.push({ at: units + p, index: out.length });
240
+ out.push({
241
+ ...run,
242
+ text: ' ',
243
+ letterSpacing: (run.letterSpacing ?? 0) + tabs.length * HAIR,
244
+ });
245
+ done = p + 1;
246
+ }
247
+ if (done < text.length) out.push({ ...run, text: text.slice(done) });
248
+ units += text.length;
249
+ }
250
+ const natural = fonts.layout(out, base, {});
251
+ const found = new Map<number, { x: number; line: number }>();
252
+ natural.lines.forEach((line, i) => {
253
+ for (const run of line.runs ?? []) {
254
+ found.set(run.start, { x: line.x + run.x, line: i });
255
+ }
256
+ });
257
+ /** The room tabs have added to each line so far. */
258
+ const added = new Map<number, number>();
259
+ for (const tab of tabs) {
260
+ const run = out[tab.index];
261
+ const face = {
262
+ ...base,
263
+ ...(run.family !== undefined ? { family: run.family } : null),
264
+ ...(run.size !== undefined ? { size: run.size } : null),
265
+ ...(run.weight !== undefined ? { weight: run.weight } : null),
266
+ ...(run.style !== undefined ? { style: run.style } : null),
267
+ };
268
+ const space = advanceOf(fonts, face, ' ');
269
+ const every = 8 * space;
270
+ const own = space + (run.letterSpacing ?? 0);
271
+ const at = found.get(tab.at) ?? natural.caretPosition(tab.at);
272
+ const before = added.get(at.line) ?? 0;
273
+ const x = at.x + before;
274
+ let advance = own;
275
+ if (every > 0) {
276
+ let stop = (Math.floor(x / every) + 1) * every;
277
+ if (stop - x < advanceOf(fonts, face, '0') / 2) stop += every;
278
+ advance = stop - x;
279
+ }
280
+ out[tab.index] = {
281
+ ...run,
282
+ letterSpacing: (run.letterSpacing ?? 0) + advance - own,
283
+ };
284
+ added.set(at.line, before + advance - own);
285
+ }
286
+ return out;
287
+ }
288
+
289
+ /** A character's advance in a face: between two letters, so that no engine
290
+ * drops it as a line's end. Kept per engine and face: a file indented with
291
+ * tabs asks for it thousands of times. */
292
+ function advanceOf(
293
+ fonts: FontsLike,
294
+ face: Record<string, unknown>,
295
+ char: string,
296
+ ): number {
297
+ let kept = ADVANCES.get(fonts);
298
+ if (!kept) ADVANCES.set(fonts, (kept = new Map()));
299
+ const key = `${face.family}|${face.size}|${face.weight}|${face.style}|${char}`;
300
+ let advance = kept.get(key);
301
+ if (advance === undefined) {
302
+ advance =
303
+ fonts.layout([{ ...face, text: `x${char}x` } as TextRun], face, {})
304
+ .width -
305
+ fonts.layout([{ ...face, text: 'xx' } as TextRun], face, {}).width;
306
+ kept.set(key, advance);
307
+ }
308
+ return advance;
309
+ }
310
+
311
+ const ADVANCES = new WeakMap<FontsLike, Map<string, number>>();
312
+
180
313
  /**
181
314
  * The bands a highlight over `[start, end)` fills, in layout coordinates —
182
315
  * one per line, and more than one on a line that changes direction. The
@@ -211,12 +344,51 @@ function rangeBands(
211
344
  return bands;
212
345
  }
213
346
 
347
+ /**
348
+ * Whether two `runs` props say the same thing. A component that builds its
349
+ * runs in render hands over a new array whenever it renders, whether or not
350
+ * the text changed — the rich text editor does on every keystroke, for
351
+ * paragraphs the keystroke never reached — and the array's identity was
352
+ * all a layout cache cleared on. A run's fields are all primitives, so one
353
+ * shallow pass decides it, where the layout it spares is a paragraph shaped
354
+ * and broken again.
355
+ */
356
+ function sameRuns(a: unknown, b: unknown): boolean {
357
+ if (a === b) return true;
358
+ if (!Array.isArray(a) || !Array.isArray(b) || a.length !== b.length) {
359
+ return false;
360
+ }
361
+ for (let i = 0; i < a.length; i++) {
362
+ const x = a[i] as Record<string, unknown>;
363
+ const y = b[i] as Record<string, unknown>;
364
+ if (x === y) continue;
365
+ if (!x || !y) return false;
366
+ const keys = Object.keys(x);
367
+ if (keys.length !== Object.keys(y).length) return false;
368
+ for (const key of keys) if (x[key] !== y[key]) return false;
369
+ }
370
+ return true;
371
+ }
372
+
214
373
  export class RichTextNode extends Node {
215
374
  private _layouts = new Map<string, TextLayoutLike | null>();
216
375
  private _text: string | null = null;
376
+ /** The runs as laid out where a tab is among them, and what from. */
377
+ private _tabbed: { from: TextRun[]; scale: number; to: TextRun[] } | null =
378
+ null;
217
379
 
218
- constructor(props: Record<string, unknown>, app: NtkApp) {
219
- super(ELEMENT, props, app);
380
+ /**
381
+ * `kind` is for a subclass registered under a name of its own — the rich
382
+ * text editor's text blocks are `<richtext>` plus a caret and a selection
383
+ * the editor owns (`src/rich-text-editor/nodes.ts`). A node's `kind` must be
384
+ * the name it was registered under, so the subclass passes its own.
385
+ */
386
+ constructor(
387
+ props: Record<string, unknown>,
388
+ app: NtkApp,
389
+ kind: string = ELEMENT,
390
+ ) {
391
+ super(kind, props, app);
220
392
  }
221
393
 
222
394
  /**
@@ -255,21 +427,36 @@ export class RichTextNode extends Node {
255
427
  let layout: TextLayoutLike | null = null;
256
428
  if (fonts) {
257
429
  const s = this._scale;
258
- layout = fonts.layout(
259
- this._deviceRuns(s),
260
- { family: 'sans-serif', size: 14 * s },
261
- {
262
- maxWidth: Number.isFinite(maxWidth) ? maxWidth : undefined,
263
- lineHeight: this.style.lineHeight,
264
- align: this.style.textAlign,
265
- },
266
- );
430
+ const base = { family: 'sans-serif', size: 14 * s };
431
+ layout = fonts.layout(this._tabRuns(fonts, base, s), base, {
432
+ maxWidth: Number.isFinite(maxWidth) ? maxWidth : undefined,
433
+ lineHeight: this.style.lineHeight,
434
+ align: this.style.textAlign,
435
+ });
267
436
  }
268
437
  if (this._layouts.size > 32) this._layouts.clear();
269
438
  this._layouts.set(key, layout);
270
439
  return layout;
271
440
  }
272
441
 
442
+ /** The runs with their tabs set to their stops (`tabbedRuns`), found
443
+ * once for a list of runs: most have none, and are handed on as they
444
+ * are. */
445
+ private _tabRuns(
446
+ fonts: FontsLike,
447
+ base: Record<string, unknown>,
448
+ scale: number,
449
+ ): TextRun[] {
450
+ const from = this._runs();
451
+ const runs = this._deviceRuns(scale);
452
+ if (!runs.some((run) => run.text.includes('\t'))) return runs;
453
+ const kept = this._tabbed;
454
+ if (kept && kept.from === from && kept.scale === scale) return kept.to;
455
+ const to = tabbedRuns(fonts, runs, base);
456
+ this._tabbed = { from, scale, to };
457
+ return to;
458
+ }
459
+
273
460
  // --- units ---------------------------------------------------------------
274
461
  //
275
462
  // The layout, `abs` and the paint are device pixels (react-x11's
@@ -294,7 +481,20 @@ export class RichTextNode extends Node {
294
481
  const runs = this._runs();
295
482
  if (scale === 1) return runs;
296
483
  return runs.map((r) =>
297
- typeof r.size === 'number' ? { ...r, size: r.size * scale } : r,
484
+ typeof r.size === 'number' ||
485
+ r.underlineOffset !== undefined ||
486
+ r.underlineThickness !== undefined
487
+ ? {
488
+ ...r,
489
+ ...(typeof r.size === 'number' ? { size: r.size * scale } : null),
490
+ ...(r.underlineOffset !== undefined
491
+ ? { underlineOffset: r.underlineOffset * scale }
492
+ : null),
493
+ ...(r.underlineThickness !== undefined
494
+ ? { underlineThickness: r.underlineThickness * scale }
495
+ : null),
496
+ }
497
+ : r,
298
498
  );
299
499
  }
300
500
 
@@ -302,8 +502,10 @@ export class RichTextNode extends Node {
302
502
  * The layout this node is currently painted with — and, because it is the
303
503
  * one thing every accessor below answers from, the reason a caret rect and
304
504
  * a glyph cannot disagree (docs/extending.md, "answer from what you draw").
505
+ * Protected rather than private for the editor's subclass, whose line-wise
506
+ * caret motion reads the lines off the same layout the glyphs came from.
305
507
  */
306
- private _paintLayout(): TextLayoutLike | null {
508
+ protected paintLayout(): TextLayoutLike | null {
307
509
  const wrap = (this.props as unknown as RichTextProps).wrap !== false;
308
510
  return this._layoutFor(wrap ? this.abs.width : Infinity);
309
511
  }
@@ -314,15 +516,34 @@ export class RichTextNode extends Node {
314
516
  ): void {
315
517
  super.applyProps(nextProps, prevProps);
316
518
  if (
317
- nextProps.runs !== prevProps.runs ||
318
- nextProps.wrap !== prevProps.wrap
519
+ nextProps.wrap !== prevProps.wrap ||
520
+ !sameRuns(nextProps.runs, prevProps.runs)
319
521
  ) {
320
522
  this._layouts.clear();
321
523
  this._text = null;
524
+ this._tabbed = null;
322
525
  this.invalidateMeasure('content');
323
526
  }
324
527
  }
325
528
 
529
+ /** A new `runs` array that says what the last one said changes nothing
530
+ * drawn — see `sameRuns`. */
531
+ override paintChanged(
532
+ nextProps: Record<string, unknown>,
533
+ prevProps: Record<string, unknown>,
534
+ ): boolean {
535
+ if (
536
+ nextProps.runs !== prevProps.runs &&
537
+ sameRuns(nextProps.runs, prevProps.runs)
538
+ ) {
539
+ return super.paintChanged(
540
+ { ...nextProps, runs: prevProps.runs },
541
+ prevProps,
542
+ );
543
+ }
544
+ return super.paintChanged(nextProps, prevProps);
545
+ }
546
+
326
547
  override destroySubtree(): void {
327
548
  this._layouts.clear();
328
549
  super.destroySubtree();
@@ -347,14 +568,14 @@ export class RichTextNode extends Node {
347
568
  }
348
569
 
349
570
  override textIndexAt(x: number, y: number): number {
350
- const layout = this._paintLayout();
571
+ const layout = this.paintLayout();
351
572
  if (!layout) return 0;
352
573
  const i = layout.indexAt(x - this.abs.x, y - this.abs.y);
353
574
  return Math.max(0, Math.min([...this.textContent()].length, i));
354
575
  }
355
576
 
356
577
  override textCaretRect(index: number): Rect | null {
357
- const layout = this._paintLayout();
578
+ const layout = this.paintLayout();
358
579
  if (!layout) return null;
359
580
  const caret = layout.caretPosition(index);
360
581
  return {
@@ -366,7 +587,7 @@ export class RichTextNode extends Node {
366
587
  }
367
588
 
368
589
  override textRangeRects(start: number, end: number): Rect[] {
369
- const layout = this._paintLayout();
590
+ const layout = this.paintLayout();
370
591
  if (!layout) return [];
371
592
  return rangeBands(layout, this.textContent(), start, end).map((band) => ({
372
593
  x: this.abs.x + band.x,
@@ -381,7 +602,7 @@ export class RichTextNode extends Node {
381
602
  * selection seam: core deliberately left hover and `cursorAt` out of
382
603
  * #291, so following a link stays this package's. */
383
604
  hrefAtPoint(x: number, y: number): string | null {
384
- const layout = this._paintLayout();
605
+ const layout = this.paintLayout();
385
606
  if (!layout) return null;
386
607
  const s = this._scale;
387
608
  const lx = x * s - this.abs.x;
@@ -401,7 +622,7 @@ export class RichTextNode extends Node {
401
622
 
402
623
  override paint(ctx: Context2D): void {
403
624
  super.paint(ctx); // background, border, clip to `abs`
404
- const layout = this._paintLayout();
625
+ const layout = this.paintLayout();
405
626
  if (!layout || !canFill(ctx)) return;
406
627
  const { x, y } = this.abs;
407
628
  const s = this._scale;
@@ -412,28 +633,8 @@ export class RichTextNode extends Node {
412
633
  // terminal's cell backgrounds
413
634
  for (const line of layout.lines) paintRunBackgrounds(ctx, line, x, y, s);
414
635
 
415
- // 2. the band the document selection has claimed of this element's text,
416
- // translucent so the ink keeps its contrast on either palette (the
417
- // same reasoning as `<textarea>`'s). The range and the colour both
418
- // arrive from the surface above; `textRangeRects` is what a custom
419
- // element and core's own `<text>` both fill, so they cannot drift.
420
- const range = this.selectionRange;
421
- // The colour is the condition, not just the range: core types it
422
- // `string | null` and defines it as what to fill the rectangles with
423
- // *while a selection is set*, so a null one is "nothing to draw"
424
- // rather than a band in the default ink.
425
- const selectionColor = this.selectionColor;
426
- if (selectionColor && range && range.end > range.start) {
427
- ctx.fillStyle = selectionColor;
428
- for (const r of this.textRangeRects(range.start, range.end)) {
429
- ctx.fillRect(
430
- Math.round(r.x),
431
- Math.round(r.y),
432
- Math.ceil(r.width),
433
- Math.ceil(r.height),
434
- );
435
- }
436
- }
636
+ // 2. the band a selection has claimed of this element's text
637
+ this.paintSelection(ctx);
437
638
 
438
639
  // 3. the ink
439
640
  layout.draw(ctx, x, y);
@@ -441,6 +642,55 @@ export class RichTextNode extends Node {
441
642
  // 4. rules over the ink: link underlines, strikethrough
442
643
  for (const line of layout.lines) paintRunRules(ctx, line, x, y, s);
443
644
 
645
+ // 5. anything that belongs over everything — a subclass's caret
646
+ this.paintOverlay(ctx);
647
+
444
648
  ctx.restore();
445
649
  }
650
+
651
+ /**
652
+ * How far this element draws past its box: a code chip is padded two
653
+ * pixels past the run behind it (`paintRunBackgrounds`), and at the start
654
+ * or the end of a line the pad is outside the box. Said for every
655
+ * paragraph, chips or not — core reads it when it rebuilds the paint
656
+ * bounds a claim covers, and the claim after an edit that took the last
657
+ * chip away still has to cover the chip the frame before drew. An older
658
+ * core never asks.
659
+ */
660
+ override paintOverhang(): number {
661
+ return Math.round(2 * this.scale);
662
+ }
663
+
664
+ /**
665
+ * The selection band, between the run backgrounds and the ink. The default
666
+ * is core's document selection: the band the `selectable` surface above
667
+ * has claimed of this element's text, translucent so the ink keeps its
668
+ * contrast on either palette (the same reasoning as `<textarea>`'s). The
669
+ * range and the colour both arrive from that surface; `textRangeRects` is
670
+ * what a custom element and core's own `<text>` both fill, so they cannot
671
+ * drift. An element with a selection of its own — the editor's text
672
+ * blocks — overrides this and fills that one instead.
673
+ */
674
+ protected paintSelection(ctx: FillContext): void {
675
+ const range = this.selectionRange;
676
+ // The colour is the condition, not just the range: core types it
677
+ // `string | null` and defines it as what to fill the rectangles with
678
+ // *while a selection is set*, so a null one is "nothing to draw"
679
+ // rather than a band in the default ink.
680
+ const selectionColor = this.selectionColor;
681
+ if (!selectionColor || !range || range.end <= range.start) return;
682
+ ctx.fillStyle = selectionColor;
683
+ for (const r of this.textRangeRects(range.start, range.end)) {
684
+ ctx.fillRect(
685
+ Math.round(r.x),
686
+ Math.round(r.y),
687
+ Math.ceil(r.width),
688
+ Math.ceil(r.height),
689
+ );
690
+ }
691
+ }
692
+
693
+ /** Drawn last, over the ink and the rules: nothing here, a caret in the
694
+ * editor's subclass. Inside the same save/restore as the rest. */
695
+ protected paintOverlay(_ctx: FillContext): void {}
446
696
  }
@@ -34,10 +34,10 @@ export function canFill(ctx: unknown): ctx is FillContext {
34
34
  *
35
35
  * `span` and `run` are what ntk's layout hands back and what every
36
36
  * decoration is read from: the span the run came from, markers and all, and
37
- * the face it was shaped with. Both are optional because react-x11's Cocoa
38
- * engine (2.3.x) reports only a run's geometry — `{ x, width, start, end }`
39
- * — and a paint that assumed the rest threw on the first paragraph on
40
- * macOS. A run without its span has no decoration to draw; a run without
37
+ * the face it was shaped with. Both are optional because an engine may
38
+ * report only a run's geometry — `{ x, width, start, end }` — as react-x11's
39
+ * Windows engine does and its Cocoa engine did before 2.22.8, and a paint
40
+ * that assumed the rest threw on the first paragraph on macOS. A run without its span has no decoration to draw; a run without
41
41
  * its face takes its vertical extent from the line, which both engines
42
42
  * report.
43
43
  */
@@ -102,7 +102,8 @@ let warnedSpanless = false;
102
102
  * Say so, once, when a laid-out run arrives without the span it came from:
103
103
  * every decoration is read off that span, so none will be drawn, and a
104
104
  * document that suddenly has no code chips or link underlines should not be
105
- * a mystery. react-x11's Cocoa engine (2.3.x) is the one that does this.
105
+ * a mystery. react-x11's Windows engine does this, and its Cocoa engine did
106
+ * before 2.22.8.
106
107
  *
107
108
  * `process` and `console` come off `globalThis` because `src/` compiles
108
109
  * with `types: []` — a Node global that wandered in would fail the build
@@ -120,7 +121,8 @@ function warnSpanless(): void {
120
121
  '@react-x11/components: the text engine handed back laid-out runs ' +
121
122
  'without their spans, so run decorations (backgrounds, underlines, ' +
122
123
  "strikethrough) and inline link hit-testing are off. react-x11's " +
123
- "Cocoa text engine (2.3.x) does this; ntk's does not.",
124
+ 'Windows text engine does this, as its Cocoa engine did before ' +
125
+ "2.22.8; ntk's does not.",
124
126
  );
125
127
  }
126
128
 
@@ -174,30 +176,39 @@ export function paintRunBackgrounds(
174
176
  }
175
177
  }
176
178
 
177
- /** The rules that sit **over** the glyphs: link underlines, strikethrough.
178
- * A rule is one logical pixel thick — `scale` device pixels, so a link on a
179
- * 2x panel is underlined as heavily as on a 1x one, not with a hairline. */
179
+ /** The rules drawn with a run: its underline and its strikethrough. A rule
180
+ * is one logical pixel thick — `scale` device pixels, so a link on a 2x
181
+ * panel is underlined as heavily as on a 1x one, not with a hairline —
182
+ * and an underline two below the baseline, where the run sets neither
183
+ * (`underlineThickness`, `underlineOffset`, in device pixels by now).
184
+ * `rules` picks a pass: CSS draws an underline under the glyphs and a
185
+ * line through over them (CSS 2.1 Appendix E), which is two passes around
186
+ * the glyphs'; drawn in one, both go over. */
180
187
  export function paintRunRules(
181
188
  ctx: FillContext,
182
189
  line: LaidLine,
183
190
  dx: number,
184
191
  dy: number,
185
192
  scale = 1,
193
+ rules: 'under' | 'over' | 'all' = 'all',
186
194
  ): void {
187
195
  const t = ruleThickness(scale);
188
196
  for (const r of line.runs) {
189
197
  const span = r.span;
190
198
  if (!span) continue;
191
- const { underline, strike } = span;
199
+ const underline = rules !== 'over' ? span.underline : undefined;
200
+ const strike = rules !== 'under' ? span.strike : undefined;
192
201
  if (underline) {
193
202
  ctx.fillStyle = underline;
194
203
  underlineRule(
195
204
  ctx,
196
205
  Math.round(dx + line.x + r.x),
197
- Math.round(dy + line.baseline + 2 * t),
206
+ Math.round(dy + line.baseline + (span.underlineOffset ?? 2 * t)),
198
207
  Math.ceil(r.width),
199
208
  span.underlineStyle ?? 'single',
200
- t,
209
+ span.underlineThickness === undefined
210
+ ? t
211
+ : Math.max(1, Math.round(span.underlineThickness)),
201
212
  );
202
213
  }
203
214
  if (strike) {
@@ -82,6 +82,7 @@ import {
82
82
  SETTLE_BUDGET,
83
83
  useVirtualWindow,
84
84
  } from '../internal/window.js';
85
+ import type { VirtualViewport } from '../internal/window.js';
85
86
  import {
86
87
  MIN_COLUMN,
87
88
  columnValue,
@@ -887,6 +888,33 @@ export function Table<Row = any>(props: TableProps<Row>): ReactElement {
887
888
  virtual === true ||
888
889
  (virtual === 'auto' && ordered.length > VIRTUAL_THRESHOLD);
889
890
 
891
+ /**
892
+ * One drawn row into the height index, for the window's trim: it may drop
893
+ * a row only once the index knows the height the row is laid out at, and
894
+ * a flick reaches the trailing rows long before `measureRows` does (see
895
+ * `measure` on the window's inputs). The gates are `measureRows`'s, for
896
+ * its reasons — no viewport yet, a row drawn against a list that has
897
+ * moved, a row laid out against a grid the columns no longer resolve to.
898
+ */
899
+ const measureDrawn = useCallback(
900
+ (id: TableRowId, at: number, viewport: VirtualViewport): boolean => {
901
+ const drawn = rowNodes.current.get(id);
902
+ if (!drawn || drawn.at !== at || viewport.width <= 0) return false;
903
+ const expected = resolveWidths(
904
+ columnsRef.current,
905
+ userWidthsRef.current,
906
+ Math.max(0, viewport.width - rowInsetRef.current * 2),
907
+ ).total;
908
+ const s = scaleOf(drawn.node);
909
+ if (Math.abs(drawn.node.abs.width / s - expected) >= 1) return false;
910
+ heights.measure(id, at, drawn.node.abs.height / s);
911
+ return heights.isMeasured(at);
912
+ },
913
+ // eslint-disable-next-line react-hooks/exhaustive-deps -- `heights` is a
914
+ // stable instance
915
+ [],
916
+ );
917
+
890
918
  /** The viewport, and the slice worth building from it — the machinery
891
919
  * shared with `<Tree>` (`../internal/window.ts`). */
892
920
  const win = useVirtualWindow({
@@ -902,6 +930,7 @@ export function Table<Row = any>(props: TableProps<Row>): ReactElement {
902
930
  threshold: catchup?.threshold ?? SKELETON_THRESHOLD,
903
931
  burstBudget: catchup?.burst ?? BURST_BUDGET,
904
932
  settleBudget: catchup?.settle ?? SETTLE_BUDGET,
933
+ measure: measureDrawn,
905
934
  });
906
935
  const { view, viewRef } = win;
907
936
  const { first, last, above, below } = win.slice;
package/src/table/rows.ts CHANGED
@@ -7,6 +7,7 @@
7
7
  // answer, and the tests assert on the answer directly.
8
8
 
9
9
  import type { ReactNode } from 'react';
10
+ import { compareText } from '../internal/collate.js';
10
11
 
11
12
  /** What a row is keyed by. Numbers are allowed because a row often comes
12
13
  * from a database, and stringifying an id is a chance to lose one. */
@@ -108,11 +109,12 @@ export function columnValue<Row>(row: Row, column: TableColumn<Row>): unknown {
108
109
  : (row as Record<string, unknown>)[column.id];
109
110
  }
110
111
 
111
- /** Core's comparator, verbatim: numbers numerically, everything else as
112
- * text, with `null`/`undefined` sorting as the empty string. */
112
+ /** Core's comparator: numbers numerically, everything else as text, with
113
+ * `null`/`undefined` sorting as the empty string. The text half is
114
+ * `localeCompare`'s, through one collator (`../internal/collate.ts`). */
113
115
  export function defaultCompare(a: unknown, b: unknown): number {
114
116
  if (typeof a === 'number' && typeof b === 'number') return a - b;
115
- return String(a ?? '').localeCompare(String(b ?? ''));
117
+ return compareText(String(a ?? ''), String(b ?? ''));
116
118
  }
117
119
 
118
120
  /**
@@ -165,11 +167,19 @@ export function orderRows<Row>(
165
167
  sort && !presorted ? columns.find((c) => c.id === sort.column) : undefined;
166
168
  if (sort && column) {
167
169
  const sign = sort.direction === 'desc' ? -1 : 1;
168
- const compare =
169
- column.compare ??
170
- ((a: Row, b: Row) =>
171
- defaultCompare(columnValue(a, column), columnValue(b, column)));
172
- entries.sort((a, b) => sign * compare(a.row, b.row));
170
+ const compare = column.compare;
171
+ if (compare) {
172
+ entries.sort((a, b) => sign * compare(a.row, b.row));
173
+ } else {
174
+ // each row's value read once rather than twice a comparison: a sort
175
+ // asks for about 17 of them a row at 100,000 rows
176
+ const keyed = entries.map((entry) => ({
177
+ entry,
178
+ key: columnValue(entry.row, column),
179
+ }));
180
+ keyed.sort((a, b) => sign * defaultCompare(a.key, b.key));
181
+ for (let i = 0; i < keyed.length; i++) entries[i] = keyed[i].entry;
182
+ }
173
183
  entries.forEach((entry, index) => {
174
184
  entry.index = index;
175
185
  });
@@ -21,7 +21,10 @@
21
21
  * program installed and is the only backend `write()` can work on.
22
22
  *
23
23
  * `'auto'` takes the first embeddable emulator that is installed and falls
24
- * back to `'vt'`. That order — rather than vt first — is deliberate: an
24
+ * back to `'vt'` — and on a react-x11 backend that cannot host an embedded
25
+ * window at all (the native macOS one) it takes `'vt'` without looking for
26
+ * the other three, because an emulator found on `PATH` there is one this app
27
+ * cannot show. That order — rather than vt first — is deliberate: an
25
28
  * external emulator is battle-tested, and a user who installed one expressed
26
29
  * a preference. Moving vt to the front is a later, deliberate decision.
27
30
  */