@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
@@ -13,30 +13,54 @@
13
13
  // A label is rasterized **whole**, not glyph by glyph: placement sets every
14
14
  // line label on a straight stretch, so a label is one rigid piece of type —
15
15
  // one textured quad, rotated as a unit — and shaping, kerning and scripts
16
- // stay the text engine's business. What is stored is **coverage**, drawn in
17
- // white and read from the alpha channel; colour and halo are the shader's
18
- // (see `./shaders.ts`), so one raster serves every palette and a
19
- // light-to-dark switch re-rasterizes nothing.
16
+ // stay the text engine's business.
17
+ //
18
+ // **One raster per string, at every size.** The engine sets a string once,
19
+ // at the atlas's `base` size, as coverage; what is stored is its signed
20
+ // distance field (`src/internal/sdf.ts`), one byte a texel. A name drawn at 11 pixels
21
+ // and the same name at 20 are one raster scaled, so a zoom ramp that grows
22
+ // the type asks for nothing new, and a halo of any width is a threshold on
23
+ // the same distances. Colour and halo are the shader's (see `./shaders.ts`),
24
+ // so one raster serves every palette and a light-to-dark switch
25
+ // re-rasterizes nothing. What it costs is the engine's hinting — the text
26
+ // is its outline, scaled — which at map-label sizes is the right trade:
27
+ // one shaping and one readback per name for the life of the atlas.
28
+ //
29
+ // An icon's two pieces (`../icons.ts`) are fields here too, drawn as
30
+ // coverage from the same paths the retained renderer fills, at the same
31
+ // base size, and coloured by the same shader.
20
32
  import { Surface } from 'react-x11/ntk';
21
33
 
34
+ import { traceGlyph, tracePlate } from '../icons.js';
35
+ import type { IconPathContext, MapIcon } from '../icons.js';
36
+ import { SDF_EDGE, distanceField } from '../../internal/sdf.js';
37
+
22
38
  /** A set string's box, in device pixels. */
23
39
  export interface TextBox {
24
40
  width: number;
25
41
  height: number;
26
42
  }
27
43
 
28
- /** One string to set, at `size` device pixels. */
44
+ /** Which of an icon's two single-colour rasters. */
45
+ export type IconPart = 'plate' | 'glyph';
46
+
47
+ /** One string to set, at `size` device pixels — or, with `icon`, one piece
48
+ * of an icon `size` pixels across, and `text` empty. */
29
49
  export interface TextItem {
30
50
  text: string;
31
51
  size: number;
52
+ icon?: { name: MapIcon; part: IconPart };
32
53
  }
33
54
 
34
- /** A rasterized string: RGBA as read back, coverage in alpha, `pad`
35
- * pixels of clear margin included. */
55
+ /** A rasterized string, `pad` pixels of clear margin included: RGBA as
56
+ * read back, coverage in alpha — or, with `stride` 1, the text engine's own
57
+ * coverage, one byte a pixel. */
36
58
  export interface TextRaster {
37
59
  width: number;
38
60
  height: number;
39
61
  pixels: Uint8Array;
62
+ /** Bytes a pixel: 4 (the default) for a readback, 1 for coverage. */
63
+ stride?: 1 | 4;
40
64
  }
41
65
 
42
66
  /** What the atlas asks of a text engine. */
@@ -52,6 +76,13 @@ export interface TextEngine {
52
76
  items: readonly TextItem[],
53
77
  pad: number,
54
78
  ): Promise<(TextRaster | null | undefined)[]>;
79
+ /**
80
+ * One item set now, synchronously, where the engine can: a raster;
81
+ * `null` for one that can never be drawn; `undefined` for one it can only
82
+ * set through {@link rasterize} (an icon's paths, or an engine whose
83
+ * layouts answer no coverage of their own). Optional.
84
+ */
85
+ rasterizeNow?(item: TextItem, pad: number): TextRaster | null | undefined;
55
86
  dispose(): void;
56
87
  }
57
88
 
@@ -64,6 +95,12 @@ interface FontsLike {
64
95
  width: number;
65
96
  height: number;
66
97
  draw(ctx: unknown, x: number, y: number): void;
98
+ /** The engine's own coverage of the layout, one byte a pixel, with
99
+ * `pad` round its box — where the engine answers it
100
+ * (sidorares/react-x11#673). */
101
+ coverage?(options?: {
102
+ pad?: number;
103
+ }): { width: number; height: number; data: Uint8Array } | null;
67
104
  };
68
105
  }
69
106
 
@@ -73,9 +110,22 @@ interface ImageLike {
73
110
  height: number;
74
111
  }
75
112
 
76
- interface ContextLike {
113
+ interface ContextLike extends Partial<IconPathContext> {
77
114
  getImageData(x: number, y: number, w: number, h: number): Promise<ImageLike>;
78
115
  destroy?(): void;
116
+ fillStyle?: unknown;
117
+ fill?(): void;
118
+ }
119
+
120
+ /** Whether a context can fill a path — what an icon is drawn with. */
121
+ function fills(
122
+ ctx: ContextLike,
123
+ ): ctx is ContextLike & IconPathContext & { fill(): void } {
124
+ return (
125
+ typeof ctx.beginPath === 'function' &&
126
+ typeof ctx.arc === 'function' &&
127
+ typeof ctx.fill === 'function'
128
+ );
79
129
  }
80
130
 
81
131
  interface SurfaceLike {
@@ -104,6 +154,9 @@ export class SurfaceTextEngine implements TextEngine {
104
154
  >();
105
155
  private _surface: SurfaceLike | null = null;
106
156
  private _ctx: ContextLike | null = null;
157
+ /** Whether the layouts answer their own coverage: unknown until a string
158
+ * asks, and false for good once one does not. */
159
+ private _coverage: boolean | null = null;
107
160
 
108
161
  constructor(app: unknown, fonts: FontsLike, family: string) {
109
162
  this._app = app;
@@ -143,9 +196,64 @@ export class SurfaceTextEngine implements TextEngine {
143
196
  return { width: Math.ceil(layout.width), height: Math.ceil(layout.height) };
144
197
  }
145
198
 
199
+ /**
200
+ * Strings the layouts set themselves, where the engine answers a layout's
201
+ * coverage (react-x11#673): no staging surface and no readback. The rest —
202
+ * icons, which are paths, and every string on an engine that cannot — go
203
+ * through the surface.
204
+ */
205
+ /**
206
+ * A string the layout sets itself, synchronously, where the engine
207
+ * answers a layout's coverage — no surface, no readback, nothing to wait
208
+ * for. `undefined` for an icon, and for every string once the engine has
209
+ * shown it cannot.
210
+ */
211
+ rasterizeNow(item: TextItem, pad: number): TextRaster | null | undefined {
212
+ if (item.icon || this._coverage === false) return undefined;
213
+ const coverage =
214
+ this._layout(item.text, item.size).coverage?.({ pad }) ?? null;
215
+ if (!coverage) {
216
+ if (this._coverage === null) this._coverage = false;
217
+ return undefined;
218
+ }
219
+ this._coverage = true;
220
+ return coverage.width > STAGING_WIDTH || coverage.height > STAGING_HEIGHT
221
+ ? null // wider than the surface could set: never drawn, as there
222
+ : {
223
+ width: coverage.width,
224
+ height: coverage.height,
225
+ pixels: coverage.data,
226
+ stride: 1,
227
+ };
228
+ }
229
+
146
230
  async rasterize(
147
231
  items: readonly TextItem[],
148
232
  pad: number,
233
+ ): Promise<(TextRaster | null | undefined)[]> {
234
+ if (this._coverage === false) return this._stage(items, pad);
235
+ const out: (TextRaster | null | undefined)[] = new Array(items.length);
236
+ const rest: number[] = [];
237
+ items.forEach((item, i) => {
238
+ const raster = this.rasterizeNow(item, pad);
239
+ if (raster === undefined) {
240
+ rest.push(i);
241
+ return;
242
+ }
243
+ out[i] = raster;
244
+ });
245
+ if (rest.length === 0) return out;
246
+ const staged = await this._stage(
247
+ rest.map((i) => items[i]),
248
+ pad,
249
+ );
250
+ rest.forEach((i, k) => (out[i] = staged[k]));
251
+ return out;
252
+ }
253
+
254
+ private async _stage(
255
+ items: readonly TextItem[],
256
+ pad: number,
149
257
  ): Promise<(TextRaster | null | undefined)[]> {
150
258
  const places: (
151
259
  { x: number; y: number; w: number; h: number } | null | undefined
@@ -154,7 +262,9 @@ export class SurfaceTextEngine implements TextEngine {
154
262
  let y = 0;
155
263
  let row = 0;
156
264
  for (const item of items) {
157
- const box = this.measure(item.text, item.size);
265
+ const box = item.icon
266
+ ? { width: Math.ceil(item.size), height: Math.ceil(item.size) }
267
+ : this.measure(item.text, item.size);
158
268
  const w = box.width + pad * 2;
159
269
  const h = box.height + pad * 2;
160
270
  if (w > STAGING_WIDTH || h > STAGING_HEIGHT) {
@@ -191,22 +301,48 @@ export class SurfaceTextEngine implements TextEngine {
191
301
  const started = now();
192
302
  // The rows drawn into: what is read back, and no more.
193
303
  let used = 0;
304
+ let drawn = 0;
194
305
  items.forEach((item, i) => {
195
306
  const place = places[i];
196
307
  if (!place) return;
197
308
  // Drawing is this thread's time; past the budget the rest wait for
198
- // the next batch.
199
- if (now() - started > DRAW_BUDGET_MS) {
309
+ // the next batch — all but the first. A pause before it, a collection
310
+ // or a slow runner, deferred every string: nothing drawn, a readback of
311
+ // no rows, and a throw out of the frame; and a machine that slow would
312
+ // never have set one.
313
+ if (drawn > 0 && now() - started > DRAW_BUDGET_MS) {
200
314
  places[i] = undefined;
201
315
  return;
202
316
  }
203
- this._layout(item.text, item.size).draw(
204
- ctx,
205
- place.x + pad,
206
- place.y + pad,
207
- );
317
+ if (item.icon) {
318
+ // White, like the strings: coverage, coloured by the shader.
319
+ if (!fills(ctx)) {
320
+ places[i] = null;
321
+ return;
322
+ }
323
+ const half = item.size / 2;
324
+ const cx = place.x + pad + half;
325
+ const cy = place.y + pad + half;
326
+ ctx.fillStyle = '#ffffff';
327
+ ctx.beginPath();
328
+ if (item.icon.part === 'plate') tracePlate(ctx, cx, cy, item.size);
329
+ else traceGlyph(ctx, item.icon.name, cx, cy, item.size);
330
+ ctx.fill();
331
+ } else {
332
+ this._layout(item.text, item.size).draw(
333
+ ctx,
334
+ place.x + pad,
335
+ place.y + pad,
336
+ );
337
+ }
208
338
  used = Math.max(used, place.y + place.h);
339
+ drawn += 1;
209
340
  });
341
+ // nothing drawn — every icon here had nothing to fill with — is nothing
342
+ // to read back
343
+ if (drawn === 0) {
344
+ return places.map((p) => (p === null ? null : undefined));
345
+ }
210
346
  const image = await ctx.getImageData(0, 0, STAGING_WIDTH, used);
211
347
  return places.map((place) => {
212
348
  if (!place) return place;
@@ -238,8 +374,8 @@ export interface AtlasEntry {
238
374
  y: number;
239
375
  width: number;
240
376
  height: number;
241
- /** The raster, kept to upload again — after a compaction moves it, or
242
- * into the texture of a new context. */
377
+ /** The distance field, one byte a texel — kept to upload again, after a
378
+ * compaction moves it or into the texture of a new context. */
243
379
  pixels: Uint8Array;
244
380
  /** In the texture where it is now; only then is it drawn. Set by the
245
381
  * renderer that uploads it. */
@@ -248,18 +384,37 @@ export interface AtlasEntry {
248
384
  used: number;
249
385
  }
250
386
 
251
- const keyOf = (text: string, size: number): string => `${size}|${text}`;
387
+ /** A string's key: the text alone, because one field serves every size. */
388
+ const keyOf = (text: string): string => `|${text}`;
389
+ /** An icon piece's key: `#` where a string's has `|`, so no string can
390
+ * be taken for one. */
391
+ const iconKey = (name: MapIcon, part: IconPart): string => `#${part}:${name}`;
252
392
 
253
393
  /**
254
- * The widest halo a raster's margin holds, in pixels. The drawn quad sits
255
- * {@link quadInset} inside the margin and a halo samples up to this far
256
- * past the quad, so its samples stay a texel inside the raster's own clear
257
- * margin and never reach a neighbour's.
394
+ * Texels the drawn quad leaves off each side of a field: bilinear samples
395
+ * at its edge then stay inside the field's own margin, never reaching the
396
+ * shelf's unwritten rows or a neighbour.
258
397
  */
259
- export const haloReach = (pad: number): number =>
260
- Math.max(0, Math.floor((pad - 2) / 2));
398
+ export const QUAD_INSET = 1;
261
399
 
262
- export const quadInset = (pad: number): number => pad - haloReach(pad) - 1;
400
+ /**
401
+ * How far past the glyphs' edge a field can see, in its own texels — the
402
+ * widest halo it holds, and the reach of its distances before they
403
+ * saturate — for a field set with `pad` texels of margin and `pad` of
404
+ * spread. Scale by the drawn size over the base for screen pixels.
405
+ */
406
+ export const fieldReach = (pad: number): number =>
407
+ Math.max(0, Math.min(pad * SDF_EDGE, pad - QUAD_INSET) - 0.5);
408
+
409
+ /** The base size a display scale sets fields at, in device pixels: 16 at
410
+ * 1x, 32 at 2x — the size most map labels are drawn at or just under, so
411
+ * a field is mostly sampled down, where it is sharpest. */
412
+ export const fieldBase = (scale: number): number =>
413
+ Math.round(16 * Math.min(2, Math.max(1, scale)));
414
+
415
+ /** A field's margin and spread at a base size: room for a halo of a
416
+ * quarter of the type's height. */
417
+ export const fieldPad = (base: number): number => Math.ceil(base * 0.375);
263
418
 
264
419
  /** Strings a frame measures however little budget it has left, so a frame
265
420
  * that starts late still makes progress. One: on X11 a string's first
@@ -294,8 +449,11 @@ const KEEP_FRAMES = 120;
294
449
  */
295
450
  export class LabelAtlas {
296
451
  readonly size: number;
297
- /** Clear margin rasterized around every string, in pixels — what a halo
298
- * grows into, and what keeps it from sampling a neighbour. */
452
+ /** The device-pixel size every string and icon is set at: a label drawn
453
+ * at `size` scales its field by `size / base`. */
454
+ readonly base: number;
455
+ /** The margin set around every field, in its texels, which is also the
456
+ * distance its values span — what a halo grows into. */
299
457
  readonly pad: number;
300
458
  /** A frame's measuring ran out of budget: there is more to place. */
301
459
  starved = false;
@@ -304,8 +462,15 @@ export class LabelAtlas {
304
462
  private readonly _entries = new Map<string, AtlasEntry>();
305
463
  /** Entries the texture does not have where they are, oldest first. */
306
464
  private _uploads: AtlasEntry[] = [];
465
+ /** Drawable entries a compaction moved: all of them go up in the next
466
+ * frame, ahead of any cap, before it draws. */
467
+ private _moved: AtlasEntry[] = [];
307
468
  private readonly _wanted = new Map<string, TextItem>();
308
469
  private readonly _failed = new Set<string>();
470
+ /** Rasters read back and waiting for their fields, oldest first — asked
471
+ * for as much as anything in `_wanted`, so a frame never asks again. */
472
+ private _fieldQueue: { key: string; raster: TextRaster }[] = [];
473
+ private readonly _queued = new Set<string>();
309
474
  private readonly _measured = new Map<string, TextBox>();
310
475
  private _busy = false;
311
476
  private _shelves: { y: number; height: number; x: number }[] = [];
@@ -316,16 +481,18 @@ export class LabelAtlas {
316
481
 
317
482
  constructor(
318
483
  engine: TextEngine | null,
319
- options: { size?: number; pad: number },
484
+ options: { size?: number; base?: number; pad?: number } = {},
320
485
  ) {
321
486
  this._engine = engine;
322
487
  this.size = options.size ?? 2048;
323
- this.pad = options.pad;
488
+ this.base = options.base ?? fieldBase(1);
489
+ this.pad = options.pad ?? fieldPad(this.base);
324
490
  }
325
491
 
326
- /** Strings asked for and not yet rasterized, or a batch in flight. */
492
+ /** Strings asked for and not yet set: waiting, being read back, or
493
+ * waiting for their fields. */
327
494
  get pending(): boolean {
328
- return this._busy || this._wanted.size > 0;
495
+ return this._busy || this._wanted.size > 0 || this._fieldQueue.length > 0;
329
496
  }
330
497
 
331
498
  /** Rasters waiting for the texture. */
@@ -345,45 +512,82 @@ export class LabelAtlas {
345
512
  this.starved = false;
346
513
  }
347
514
 
348
- /** The box a string sets in, or null when this frame's budget is spent. */
515
+ /** The box a string sets in at `size`, or null when this frame's budget
516
+ * is spent. Measured once, at the base size, and scaled — the same
517
+ * arithmetic that scales its field, so the box placement collides and
518
+ * the quad the frame draws are one size. */
349
519
  measure(text: string, size: number): TextBox | null {
350
- const key = keyOf(text, size);
351
- const hit = this._measured.get(key);
352
- if (hit) return hit;
353
- const engine = this._engine;
354
- if (!engine) return null;
355
- if (this._measures >= MIN_MEASURES && now() > this._deadline) {
356
- this.starved = true;
357
- return null;
520
+ const key = keyOf(text);
521
+ let box = this._measured.get(key);
522
+ if (!box) {
523
+ const engine = this._engine;
524
+ if (!engine) return null;
525
+ if (this._measures >= MIN_MEASURES && now() > this._deadline) {
526
+ this.starved = true;
527
+ return null;
528
+ }
529
+ this._measures++;
530
+ box = engine.measure(text, this.base);
531
+ if (this._measured.size > 20000) this._measured.clear();
532
+ this._measured.set(key, box);
358
533
  }
359
- this._measures++;
360
- const box = engine.measure(text, size);
361
- if (this._measured.size > 20000) this._measured.clear();
362
- this._measured.set(key, box);
363
- return box;
534
+ const k = size / this.base;
535
+ return { width: box.width * k, height: box.height * k };
536
+ }
537
+
538
+ /** The string's field, once the texture has it; null until then —
539
+ * asking is what gets it set. One field whatever size it is drawn at. */
540
+ entry(text: string): AtlasEntry | null {
541
+ return this._lookup(keyOf(text), text, null, 'plate');
364
542
  }
365
543
 
366
- /** The string's raster, once the texture has it; null until then —
367
- * asking is what gets it rasterized. */
368
- entry(text: string, size: number): AtlasEntry | null {
369
- const key = keyOf(text, size);
544
+ /** One piece of an icon, as {@link entry} answers for a string. */
545
+ icon(name: MapIcon, part: IconPart): AtlasEntry | null {
546
+ return this._lookup(iconKey(name, part), '', name, part);
547
+ }
548
+
549
+ private _lookup(
550
+ key: string,
551
+ text: string,
552
+ icon: MapIcon | null,
553
+ part: IconPart,
554
+ ): AtlasEntry | null {
370
555
  const entry = this._entries.get(key);
371
556
  if (entry) {
372
557
  entry.used = this._frame;
373
558
  return entry.ready ? entry : null;
374
559
  }
375
- if (!this._failed.has(key) && !this._wanted.has(key)) {
376
- this._wanted.set(key, { text, size });
560
+ if (
561
+ !this._failed.has(key) &&
562
+ !this._wanted.has(key) &&
563
+ !this._queued.has(key)
564
+ ) {
565
+ const size = this.base;
566
+ this._wanted.set(
567
+ key,
568
+ icon ? { text, size, icon: { name: icon, part } } : { text, size },
569
+ );
377
570
  }
378
571
  return null;
379
572
  }
380
573
 
574
+ /** Whether an icon can never be drawn — the engine has no path to fill
575
+ * it with. A name set beside it is then set alone. */
576
+ iconFailed(name: MapIcon): boolean {
577
+ return (
578
+ this._failed.has(iconKey(name, 'plate')) ||
579
+ this._failed.has(iconKey(name, 'glyph'))
580
+ );
581
+ }
582
+
381
583
  /** Start rasterizing what has been asked for, unless a batch is out. */
382
584
  pump(): void {
383
585
  const engine = this._engine;
384
586
  if (!engine || this._busy || this._wanted.size === 0) return;
587
+ const keys: string[] = [];
385
588
  const batch: TextItem[] = [];
386
- for (const item of this._wanted.values()) {
589
+ for (const [key, item] of this._wanted) {
590
+ keys.push(key);
387
591
  batch.push(item);
388
592
  if (batch.length >= BATCH) break;
389
593
  }
@@ -393,10 +597,22 @@ export class LabelAtlas {
393
597
  this._busy = false;
394
598
  rasters.forEach((raster, i) => {
395
599
  if (raster === undefined) return;
396
- const key = keyOf(batch[i].text, batch[i].size);
600
+ const key = keys[i];
397
601
  this._wanted.delete(key);
398
- if (raster === null || !this._add(key, raster)) this._failed.add(key);
602
+ // A string with no raster never will have one; a raster with no
603
+ // room is a fact about this moment, and the string is asked for
604
+ // again by the next frame that still shows it.
605
+ if (raster === null) {
606
+ this._failed.add(key);
607
+ } else {
608
+ this._fieldQueue.push({ key, raster });
609
+ this._queued.add(key);
610
+ }
399
611
  });
612
+ // The staging surface is free again as soon as the pixels are
613
+ // copied out, so the next batch is read back while this one waits
614
+ // for its fields; and a frame is asked for, to make them.
615
+ this.pump();
400
616
  this.onChange?.();
401
617
  },
402
618
  () => {
@@ -410,42 +626,138 @@ export class LabelAtlas {
410
626
  );
411
627
  }
412
628
 
413
- /** Up to `max` rasters for the texture, oldest first. The renderer marks
414
- * each `ready` once it is uploaded. */
629
+ /** Rasters for the texture: every one a compaction moved, then up to
630
+ * `max` new ones, oldest first. The renderer marks each `ready` once it
631
+ * is uploaded — a moved one already is, because the frame that takes it
632
+ * draws after taking it. */
415
633
  takeUploads(max: number): AtlasEntry[] {
416
- return this._uploads.splice(0, max);
634
+ const moved = this._moved;
635
+ this._moved = [];
636
+ return moved.length > 0
637
+ ? moved.concat(this._uploads.splice(0, max))
638
+ : this._uploads.splice(0, max);
417
639
  }
418
640
 
419
641
  /** The texture is new, and has none of it: everything goes up again. */
420
642
  restart(): void {
421
643
  for (const entry of this._entries.values()) entry.ready = false;
422
644
  this._uploads = [...this._entries.values()];
645
+ this._moved = [];
423
646
  }
424
647
 
425
648
  dispose(): void {
426
649
  this._engine?.dispose();
427
650
  this._engine = null;
651
+ this._fieldQueue = [];
652
+ this._queued.clear();
653
+ }
654
+
655
+ /** Read back and waiting for their fields: another frame is worth
656
+ * drawing, to make them. */
657
+ get fielding(): boolean {
658
+ return this._fieldQueue.length > 0;
659
+ }
660
+
661
+ /**
662
+ * Make fields for what has been read back until `deadline` — at least
663
+ * one — in the frame, whose own draw then takes them into the texture.
664
+ *
665
+ * A field is about 0.2 ms. A batch of them made as it landed was 4-9 ms
666
+ * beside the frames, measured as event-loop stalls on a jump to a view
667
+ * whose every name was new; slices on timers of their own each waited
668
+ * behind a frame, and names arrived late. In the frame, on a budget,
669
+ * they are made at a known cost and drawn the frame after.
670
+ */
671
+ /**
672
+ * Set what placement asked for, in the frame, until `deadline` (at least
673
+ * one): what was read back already, then every string the engine can set
674
+ * synchronously. What is set here is drawable in this frame — it goes
675
+ * into the texture ahead of any cap, before this frame draws (the
676
+ * `labelsWhileMoving` path, `view.ts`). Icons, and an engine with no
677
+ * synchronous path, still go through {@link pump}.
678
+ */
679
+ setNow(deadline: number): void {
680
+ const engine = this._engine;
681
+ if (!engine) return;
682
+ let made = 0;
683
+ while (this._fieldQueue.length > 0 && (made === 0 || now() < deadline)) {
684
+ const { key, raster } = this._fieldQueue.shift()!;
685
+ this._queued.delete(key);
686
+ this._add(key, raster.width, raster.height, this._field(raster), true);
687
+ made++;
688
+ }
689
+ if (!engine.rasterizeNow) return;
690
+ for (const [key, item] of this._wanted) {
691
+ if (made > 0 && now() >= deadline) {
692
+ this.starved = true;
693
+ break;
694
+ }
695
+ const raster = engine.rasterizeNow(item, this.pad);
696
+ if (raster === undefined) continue;
697
+ this._wanted.delete(key);
698
+ if (raster === null) {
699
+ this._failed.add(key);
700
+ continue;
701
+ }
702
+ this._add(key, raster.width, raster.height, this._field(raster), true);
703
+ made++;
704
+ }
428
705
  }
429
706
 
430
- private _add(key: string, raster: TextRaster): boolean {
431
- let place = this._allocate(raster.width, raster.height);
432
- if (!place) {
707
+ makeFields(deadline: number): void {
708
+ if (!this._engine) return;
709
+ let made = 0;
710
+ while (this._fieldQueue.length > 0 && (made === 0 || now() < deadline)) {
711
+ const { key, raster } = this._fieldQueue.shift()!;
712
+ this._queued.delete(key);
713
+ this._add(key, raster.width, raster.height, this._field(raster));
714
+ made++;
715
+ }
716
+ }
717
+
718
+ /** A raster's coverage as its distance field. The coverage is the
719
+ * readback's alpha; the field spans `pad` texels either side of the
720
+ * edge, which is the margin the engine set it with. */
721
+ private _field(raster: TextRaster): Uint8Array {
722
+ const stride = raster.stride ?? 4;
723
+ return distanceField(
724
+ raster.pixels,
725
+ raster.width,
726
+ raster.height,
727
+ this.pad,
728
+ stride,
729
+ stride === 4 ? 3 : 0,
730
+ );
731
+ }
732
+
733
+ private _add(
734
+ key: string,
735
+ width: number,
736
+ height: number,
737
+ pixels: Uint8Array,
738
+ /** Drawable in this frame: uploaded ahead of any cap before it draws. */
739
+ immediate = false,
740
+ ): boolean {
741
+ let place =
742
+ this._allocate(width, height) ?? this._reuseShelf(width, height);
743
+ if (!place && this._compactable()) {
433
744
  this._compact();
434
- place = this._allocate(raster.width, raster.height);
745
+ place = this._allocate(width, height);
435
746
  }
436
747
  if (!place) return false;
437
748
  const entry: AtlasEntry = {
438
749
  key,
439
750
  x: place.x,
440
751
  y: place.y,
441
- width: raster.width,
442
- height: raster.height,
443
- pixels: raster.pixels,
444
- ready: false,
752
+ width,
753
+ height,
754
+ pixels,
755
+ ready: immediate,
445
756
  used: this._frame,
446
757
  };
447
758
  this._entries.set(key, entry);
448
- this._uploads.push(entry);
759
+ if (immediate) this._moved.push(entry);
760
+ else this._uploads.push(entry);
449
761
  return true;
450
762
  }
451
763
 
@@ -468,9 +780,69 @@ export class LabelAtlas {
468
780
  return { x: 0, y: shelf.y };
469
781
  }
470
782
 
783
+ /**
784
+ * Room made in place: the shelf of this height whose rasters were drawn
785
+ * longest ago, emptied and filled again from its left.
786
+ *
787
+ * **Nothing that stays moves.** A compaction moves every raster it keeps,
788
+ * and a moved raster is not drawn until it is in the texture again — at
789
+ * {@link takeUploads}' pace, so every label on screen went out together
790
+ * and came back over the next few frames, at full opacity. A full atlas
791
+ * is the ordinary state of a session (a thousand strings at 1x, a quarter
792
+ * of that at 2x), so that was a flash of the whole label layer at the end
793
+ * of most settles. A shelf any label of the last two frames stands on is not
794
+ * taken: what is dropped is off screen, and asked for again if it
795
+ * returns.
796
+ */
797
+ private _reuseShelf(w: number, h: number): { x: number; y: number } | null {
798
+ if (w > this.size) return null;
799
+ const height = Math.ceil(h / 8) * 8;
800
+ const newest = new Map<number, number>();
801
+ for (const entry of this._entries.values()) {
802
+ const seen = newest.get(entry.y);
803
+ if (seen === undefined || entry.used > seen)
804
+ newest.set(entry.y, entry.used);
805
+ }
806
+ let shelf: { y: number; height: number; x: number } | null = null;
807
+ // Not a shelf any label of this frame or the last stands on: fields can
808
+ // be made before a frame's labels are batched (`setNow`), when a label
809
+ // still fading out has not been asked for yet.
810
+ let oldest = this._frame - 1;
811
+ for (const candidate of this._shelves) {
812
+ if (candidate.height !== height) continue;
813
+ const used = newest.get(candidate.y) ?? -Infinity;
814
+ if (used < oldest) {
815
+ oldest = used;
816
+ shelf = candidate;
817
+ }
818
+ }
819
+ if (!shelf) return null;
820
+ const y = shelf.y;
821
+ for (const [key, entry] of this._entries) {
822
+ if (entry.y === y) this._entries.delete(key);
823
+ }
824
+ this._uploads = this._uploads.filter((entry) => entry.y !== y);
825
+ this._moved = this._moved.filter((entry) => entry.y !== y);
826
+ shelf.x = w;
827
+ return { x: 0, y };
828
+ }
829
+
830
+ /** Whether a compaction would free anything: something kept past its
831
+ * last use. One that keeps everything only moves it — every label on
832
+ * screen out of the texture for the frames its upload takes, for no
833
+ * room at all. */
834
+ private _compactable(): boolean {
835
+ for (const entry of this._entries.values()) {
836
+ if (entry.used < this._frame - KEEP_FRAMES) return true;
837
+ }
838
+ return false;
839
+ }
840
+
471
841
  /** Drop what has not been drawn for a while and pack the rest again,
472
- * tallest first. Everything kept has moved, so none of it is drawn
473
- * until the renderer has uploaded it where it now is. */
842
+ * tallest first — the last resort, when no shelf of the height wanted
843
+ * can be taken in place. What was drawable stays drawable: it is
844
+ * uploaded where it now is, all of it, by the next frame before that
845
+ * frame draws ({@link takeUploads}); what was waiting still waits. */
474
846
  private _compact(): void {
475
847
  const keep = [...this._entries.values()]
476
848
  .filter((e) => e.used >= this._frame - KEEP_FRAMES)
@@ -479,14 +851,15 @@ export class LabelAtlas {
479
851
  this._shelves = [];
480
852
  this._top = 0;
481
853
  this._uploads = [];
854
+ this._moved = [];
482
855
  for (const entry of keep) {
483
856
  const place = this._allocate(entry.width, entry.height);
484
857
  if (!place) continue;
485
858
  entry.x = place.x;
486
859
  entry.y = place.y;
487
- entry.ready = false;
488
860
  this._entries.set(entry.key, entry);
489
- this._uploads.push(entry);
861
+ if (entry.ready) this._moved.push(entry);
862
+ else this._uploads.push(entry);
490
863
  }
491
864
  }
492
865
  }