@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
@@ -0,0 +1,1084 @@
1
+ // The camera and the input, which both of `<Map>`'s renderers drive.
2
+ //
3
+ // `<Map>` draws through one of two renderers — the retained one in
4
+ // `./node.ts`, which composites rasterized tile surfaces, and the GL one in
5
+ // `./gl/`, which draws every frame from vector buckets — and chooses between
6
+ // them at run time (`./renderer.ts`). What neither may own is the camera. A
7
+ // map that falls back from GL to the retained renderer in the middle of a pan
8
+ // has to keep the camera it was panned to, the handle an application holds
9
+ // has to keep working, and a gesture has to mean the same thing on both —
10
+ // which is only true if both renderers answer to one object. This is it: the
11
+ // camera and its controlled/uncontrolled fork, the settle window,
12
+ // `onCameraChange` and `onMoveEnd`, the gestures (drag, wheel, keys, double
13
+ // click, a press on a marker, the hover), the marker hit test, and the
14
+ // handle `<Map>`'s ref hands out. A renderer attaches to it as a
15
+ // {@link MapView} — where its pane is, what a camera move costs it — and
16
+ // holds no camera of its own.
17
+ //
18
+ // The camera lives on an object rather than in React state for the reason
19
+ // `AGENTS.md` gives under "A map, and the three caches under it": that is
20
+ // what makes a drag step two numbers and a blit, with no render and no commit
21
+ // in the loop. `<Map>` makes one controller per mount and hands it to
22
+ // whichever renderer is drawing; a bare `<mapview>` makes its own.
23
+ import type { A11ySceneItem } from 'react-x11/node';
24
+
25
+ import { markerAt, markerRect } from './overlay.js';
26
+ import type { MapMarker } from './overlay.js';
27
+ import {
28
+ DEFAULT_TILE_SIZE,
29
+ boundsOf,
30
+ cameraForBounds,
31
+ projectLngLat,
32
+ transformFor,
33
+ unprojectPoint,
34
+ visibleBounds,
35
+ } from './proj.js';
36
+ import type {
37
+ LngLat,
38
+ LngLatBounds,
39
+ MapCamera,
40
+ ScreenRect,
41
+ Transform,
42
+ } from './proj.js';
43
+ import type {
44
+ FitBoundsOptions,
45
+ MapFrameStats,
46
+ MapHandle,
47
+ MapPointerEvent,
48
+ } from './types.js';
49
+
50
+ /** Where a map with no camera given starts. */
51
+ export const DEFAULT_CAMERA: MapCamera = {
52
+ center: { lon: 0, lat: 20 },
53
+ zoom: 2,
54
+ };
55
+
56
+ /** Logical pixels the pointer may travel before a press becomes a drag. */
57
+ export const DRAG_THRESHOLD = 3;
58
+
59
+ /**
60
+ * How long after the last camera change the map counts as moving.
61
+ *
62
+ * One window for both renderers, and both ask it the same question — is this
63
+ * a gesture? The retained renderer rasterizes nothing inside it, so a drag or
64
+ * a wheel is composites only; the GL renderer draws at reduced detail inside
65
+ * it when adaptive quality asks, and admits no new labels. `onMoveEnd` fires
66
+ * when it closes. Long enough that a wheel zoom's many notches count as one
67
+ * gesture, short enough that the map sharpens before the user has finished
68
+ * looking. (The retained renderer had 140 ms and the GL proof of concept
69
+ * 180; the retained number was the one its tests had pinned.)
70
+ */
71
+ export const SETTLE_MS = 140;
72
+
73
+ /**
74
+ * Zoom is quantized to this, for the reason react-x11's docs/scale.md gives
75
+ * about a gesture-driven `scale`: every distinct value is a distinct set of
76
+ * font sizes to shape, and a wheel feeding a raw accumulator makes a new set
77
+ * per frame. A sixteenth of a level is finer than the eye reads as stepping.
78
+ */
79
+ const ZOOM_STEP = 1 / 16;
80
+
81
+ /** A zoom on the {@link ZOOM_STEP} grid — also what a label placement is
82
+ * keyed on, so a placement and the zooms a wheel produces agree. */
83
+ export function quantizeZoom(zoom: number): number {
84
+ return Math.round(zoom / ZOOM_STEP) * ZOOM_STEP;
85
+ }
86
+
87
+ /** A wheel notch is this much zoom. */
88
+ const WHEEL_ZOOM = 1 / 2.5;
89
+
90
+ /**
91
+ * How fast a wheel's zoom closes on where the notches asked it to go — the
92
+ * time constant of the exponential the glide follows, so it is all but over
93
+ * after three of these.
94
+ *
95
+ * A notch is 0.384 of a level, which is six of {@link ZOOM_STEP}, and
96
+ * applying it the moment it arrives is a jump: the map is one size, and a
97
+ * frame later it is another. The device cannot help with that. A wheel
98
+ * *clicks* — the core protocol reports it as a button, and even over XI2 a
99
+ * mouse reports one notch at a time — so the smoothness has to come from
100
+ * the map spreading a notch over the frames after it, which is what every
101
+ * map client does with one. `ev.smooth` tells that device from the one that
102
+ * measured the scroll; see {@link MapController.wheel}.
103
+ */
104
+ const WHEEL_EASE_MS = 55;
105
+
106
+ /** What the wheel event's own step is worth, in the absence of a frame to
107
+ * measure: one at 60Hz. The gesture has to move *now* — a wheel that waits
108
+ * for the next frame to do anything reads as lag — and this is the distance
109
+ * a frame would have moved it. */
110
+ const EASE_FIRST_MS = 16;
111
+
112
+ /**
113
+ * How often a glide steps: a 60Hz frame.
114
+ *
115
+ * A timer rather than the frame the step is drawn in, because a step *is* a
116
+ * camera move and the views already know what to do with one — the retained
117
+ * renderer claims the pane, the GL one asks for a frame — and that is the
118
+ * path a drag's every pointer step takes. Claiming from inside a frame is
119
+ * not: the claim lands on the frame being painted and brings nothing after
120
+ * it, which left a notch delivering its first step and then waiting for the
121
+ * settle timer to wake the map up.
122
+ *
123
+ * Nothing here outruns the display. The step is exponential in the *time*
124
+ * since the last one, so a view that paints at half this rate sees every
125
+ * other step and the same glide; what the timer decides is the finest the
126
+ * map can move, not how fast it gets there.
127
+ */
128
+ const GLIDE_TICK_MS = 16;
129
+
130
+ /**
131
+ * A zoom the wheel asked for and the frames are still delivering.
132
+ *
133
+ * The **target** is the whole of what the wheel has asked for, kept apart
134
+ * from the camera because the camera cannot hold it: the zoom is quantized
135
+ * to {@link ZOOM_STEP}, and a touchpad's fraction of a notch is smaller than
136
+ * that. Accumulating here is what stops a slow two-finger scroll rounding to
137
+ * nothing, event after event, and never moving the map at all.
138
+ */
139
+ interface ZoomGlide {
140
+ /** Where the zoom is going: every delta of this gesture, unrounded. */
141
+ target: number;
142
+ /** The camera zoom the last step produced. If the camera is not there any
143
+ * more, something else has moved it — an application that owns it,
144
+ * `setCamera`, a fit — and this gesture is no longer the authority on
145
+ * where the zoom goes. */
146
+ applied: number;
147
+ /** The point the zoom is about, in pane-local logical pixels: where the
148
+ * pointer was for the last notch, which is what must not move. */
149
+ x: number;
150
+ y: number;
151
+ /** When the last step was applied — what the next one's distance is
152
+ * measured from, so the glide is the same speed at any frame rate. */
153
+ at: number;
154
+ /**
155
+ * Whether the frames have anything left to deliver, or this is only the
156
+ * accumulator.
157
+ *
158
+ * `false` for a device that *measured* the scroll: a touchpad's stream of
159
+ * fractions is already as smooth as the hand that made it, and easing it
160
+ * would add lag to a gesture that has none. The record stays behind
161
+ * anyway, because the fractions still have to accumulate somewhere.
162
+ */
163
+ easing: boolean;
164
+ }
165
+
166
+ /** The props the controller reads — `<Map>`'s, whichever renderer draws. */
167
+ export interface MapControllerProps {
168
+ camera?: MapCamera;
169
+ onCameraChange?: (camera: MapCamera) => void;
170
+ onMoveEnd?: (camera: MapCamera) => void;
171
+ minZoom?: number;
172
+ maxZoom?: number;
173
+ interactive?: boolean;
174
+ markers?: readonly MapMarker[];
175
+ onMapClick?: (event: MapPointerEvent) => void;
176
+ onMarkerClick?: (marker: MapMarker, event: MapPointerEvent) => void;
177
+ onMarkerHover?: (
178
+ marker: MapMarker | null,
179
+ event: MapPointerEvent | null,
180
+ ) => void;
181
+ }
182
+
183
+ /**
184
+ * A renderer, as the controller sees it: where its pane is, and what a camera
185
+ * move costs it. Nothing about how it draws.
186
+ */
187
+ export interface MapView {
188
+ /** The pane, in the window's logical pixels — empty before layout. */
189
+ pane(): ScreenRect;
190
+ /** Device pixels per logical pixel. */
191
+ scale(): number;
192
+ /**
193
+ * The camera moved, and the view should show it. `blit` says whether the
194
+ * move is a translation of what is already on screen — a pan — rather
195
+ * than a zoom or a jump: the retained renderer's difference between a
196
+ * blit and a repaint.
197
+ */
198
+ moved(previous: MapCamera, next: MapCamera, blit: boolean): void;
199
+ /** The settle window closed: the map is still, and may sharpen. */
200
+ settled(): void;
201
+ /** `refresh()`: throw away everything derived from the style. */
202
+ refresh(): void;
203
+ stats(): MapFrameStats | null;
204
+ /** Take the keyboard focus — a pan is where the arrows start working. */
205
+ focus(): void;
206
+ }
207
+
208
+ /** A pointer event as the controller reads it: pane-local logical pixels,
209
+ * the button, the click count and the modifiers. */
210
+ export interface MapPointerInput {
211
+ x: number;
212
+ y: number;
213
+ /** `1` left, `2` middle, `3` right. */
214
+ button?: number;
215
+ /** The click count: `2` is the second press of a double click. */
216
+ detail?: number;
217
+ shiftKey?: boolean;
218
+ ctrlKey?: boolean;
219
+ altKey?: boolean;
220
+ metaKey?: boolean;
221
+ }
222
+
223
+ /** What a press began — see {@link MapController.pointerDown}. */
224
+ export type PressKind = 'marker' | 'pan' | 'frozen';
225
+
226
+ type Gesture =
227
+ | {
228
+ kind: 'pan';
229
+ startX: number;
230
+ startY: number;
231
+ lastX: number;
232
+ lastY: number;
233
+ moved: boolean;
234
+ }
235
+ | { kind: 'marker'; id: string; startX: number; startY: number };
236
+
237
+ const timers = globalThis as {
238
+ setTimeout?(fn: () => void, ms: number): unknown;
239
+ clearTimeout?(id: unknown): void;
240
+ performance?: { now(): number };
241
+ };
242
+
243
+ /**
244
+ * The settle timer, unref'd where the runtime allows it.
245
+ *
246
+ * A map that has just been panned holds a timer, and an unref'd one does not
247
+ * keep a process alive on its own — which matters for a script or a test that
248
+ * renders a map and expects to exit, and is the call core's caret blink makes
249
+ * for the same reason.
250
+ */
251
+ function arm(tick: () => void, ms: number): unknown {
252
+ const handle = timers.setTimeout?.(tick, ms) ?? null;
253
+ (handle as { unref?(): void } | null)?.unref?.();
254
+ return handle;
255
+ }
256
+
257
+ /**
258
+ * The clock a glide is measured on, and the timer that steps it.
259
+ *
260
+ * `performance.now()` rather than the `Date.now()` the settle window uses:
261
+ * this one is compared across two frames of a 60Hz display, and `Date.now()`
262
+ * counts whole milliseconds, so a sixth of the step would be error. Reached
263
+ * through `globalThis` because `src/` compiles with `types: []`.
264
+ *
265
+ * One object, exported from this module though not from the package, so a
266
+ * test can stand in for both and step a glide a frame at a time. The glide
267
+ * is wall-clock time on purpose, and a runner slow enough to spend the whole
268
+ * of one inside a single `await` finds it over before it can look.
269
+ */
270
+ export const glideClock = {
271
+ now(): number {
272
+ return timers.performance?.now() ?? Date.now();
273
+ },
274
+ arm,
275
+ disarm(handle: unknown): void {
276
+ timers.clearTimeout?.(handle);
277
+ },
278
+ };
279
+
280
+ function clamp(value: number, low: number, high: number): number {
281
+ return value < low ? low : value > high ? high : value;
282
+ }
283
+
284
+ const EMPTY_PANE: ScreenRect = { x: 0, y: 0, width: 0, height: 0 };
285
+
286
+ export class MapController {
287
+ /**
288
+ * What `<Map>`'s ref hands out. Made once, so it is the **same object**
289
+ * for the life of the mount — across a renderer switch too, which is
290
+ * what lets an application hold it in a ref and never look again.
291
+ */
292
+ readonly handle: MapHandle;
293
+
294
+ /**
295
+ * Set by the view for the length of a frame. A camera change made inside
296
+ * one — the fit that a `fitBounds` asked for before layout, applied at
297
+ * the first frame with a size — is already what the frame draws, so it
298
+ * claims nothing and starts no gesture.
299
+ */
300
+ painting = false;
301
+ /** A camera move made while `painting`, waiting for the frame to end —
302
+ * `previous` is the camera the *first* such move started from, so the
303
+ * view is told the whole delta however many were fused. */
304
+ private _paintMove: { previous: MapCamera } | null = null;
305
+
306
+ private _props: MapControllerProps = {};
307
+ /** The camera, when the application does not control it. */
308
+ private _camera: MapCamera;
309
+ private _view: MapView | null = null;
310
+ private _gesture: Gesture | null = null;
311
+ private _hover: string | null = null;
312
+ /** Wall-clock time the settle window closes at. */
313
+ private _settleAt = 0;
314
+ private _settleTimer: unknown = null;
315
+ private _glide: ZoomGlide | null = null;
316
+ private _glideTimer: unknown = null;
317
+ private _pendingFit: {
318
+ bounds: LngLatBounds;
319
+ options?: FitBoundsOptions;
320
+ } | null = null;
321
+
322
+ constructor(seed: MapCamera = DEFAULT_CAMERA) {
323
+ this._camera = { center: { ...seed.center }, zoom: seed.zoom };
324
+ this.handle = {
325
+ getCamera: () => this.getCamera(),
326
+ setCamera: (camera) => this.setCamera(camera),
327
+ panBy: (dx, dy) => this.panBy(dx, dy),
328
+ zoomIn: (step) => this.zoomIn(step),
329
+ zoomOut: (step) => this.zoomOut(step),
330
+ zoomTo: (zoom) => this.zoomTo(zoom),
331
+ fitBounds: (bounds, options) => this.fitBounds(bounds, options),
332
+ fitMarkers: (ids, options) => this.fitMarkers(ids, options),
333
+ getBounds: () => this.getBounds(),
334
+ project: (position) => this.project(position),
335
+ unproject: (x, y) => this.unproject(x, y),
336
+ markerAt: (x, y) => this.markerAt(x, y),
337
+ refresh: () => this._view?.refresh(),
338
+ stats: () => this._view?.stats() ?? null,
339
+ };
340
+ }
341
+
342
+ // --- props and views --------------------------------------------------------
343
+
344
+ /** The props to read from here on. Read lazily, at event and frame time,
345
+ * so a new object per render costs an assignment. */
346
+ setProps(props: MapControllerProps): void {
347
+ this._props = props;
348
+ }
349
+
350
+ get props(): MapControllerProps {
351
+ return this._props;
352
+ }
353
+
354
+ /** The renderer drawing the map from now on. */
355
+ attach(view: MapView): void {
356
+ this._view = view;
357
+ }
358
+
359
+ /** …and letting go, if it still is: during a renderer switch the new
360
+ * view can attach before the old one is torn down. */
361
+ detach(view: MapView): void {
362
+ if (this._view === view) this._view = null;
363
+ }
364
+
365
+ get view(): MapView | null {
366
+ return this._view;
367
+ }
368
+
369
+ /**
370
+ * Stop the timers — the settle window's, and a wheel glide in flight.
371
+ * They are the only things held that outlive a frame. The camera and the
372
+ * view stay, so a mount that React only pretends to tear down (a
373
+ * strict-mode double effect) comes back to a working controller; the next
374
+ * camera move arms the settle timer again, and the next notch a glide.
375
+ */
376
+ dispose(): void {
377
+ if (this._settleTimer !== null) timers.clearTimeout?.(this._settleTimer);
378
+ this._settleTimer = null;
379
+ if (this._glideTimer !== null) glideClock.disarm(this._glideTimer);
380
+ this._glideTimer = null;
381
+ this._glide = null;
382
+ }
383
+
384
+ private _minZoom(): number {
385
+ return this._props.minZoom ?? 0;
386
+ }
387
+
388
+ private _maxZoom(): number {
389
+ return this._props.maxZoom ?? 22;
390
+ }
391
+
392
+ private _interactive(): boolean {
393
+ return this._props.interactive !== false;
394
+ }
395
+
396
+ private _markers(): readonly MapMarker[] {
397
+ return this._props.markers ?? [];
398
+ }
399
+
400
+ // --- the camera ----------------------------------------------------------
401
+
402
+ /** The camera in effect: the application's when it controls one. */
403
+ camera(): MapCamera {
404
+ return this._props.camera ?? this._camera;
405
+ }
406
+
407
+ /** The camera this controller keeps for itself — the one in effect
408
+ * whenever the application is not controlling it. */
409
+ ownCamera(): MapCamera {
410
+ return this._camera;
411
+ }
412
+
413
+ /** The pane, in the window's logical pixels — empty with no view. */
414
+ pane(): ScreenRect {
415
+ return this._view?.pane() ?? EMPTY_PANE;
416
+ }
417
+
418
+ /** A camera resolved against the pane. */
419
+ transform(camera: MapCamera = this.camera()): Transform {
420
+ const pane = this.pane();
421
+ return transformFor(
422
+ camera,
423
+ { width: pane.width, height: pane.height },
424
+ DEFAULT_TILE_SIZE,
425
+ );
426
+ }
427
+
428
+ /**
429
+ * Move the camera — the one place it changes.
430
+ *
431
+ * Clamped (the zoom to the range, the latitude to what Web Mercator can
432
+ * represent; the longitude is not, because the map wraps and a camera just
433
+ * past the antimeridian is a camera in the next copy of the world),
434
+ * reported, and the settle window restarted: every camera move is a
435
+ * gesture, not only a pointer one, because an application animating the
436
+ * camera with `panBy` in a loop wants what a drag wants.
437
+ *
438
+ * A camera the application controls is only *asked* to move:
439
+ * `onCameraChange` is the request, and the view hears about the move when
440
+ * the new `camera` prop arrives. Telling it here as well was a double
441
+ * shift — the retained renderer blitted the pane for the request and then
442
+ * again for the prop, and `scrollContents` adds two shifts in a frame
443
+ * together.
444
+ */
445
+ apply(next: MapCamera, blit: boolean): void {
446
+ const previous = this.camera();
447
+ const camera: MapCamera = {
448
+ center: { lon: next.center.lon, lat: clamp(next.center.lat, -85, 85) },
449
+ zoom: clamp(next.zoom, this._minZoom(), this._maxZoom()),
450
+ };
451
+ if (
452
+ camera.zoom === previous.zoom &&
453
+ camera.center.lon === previous.center.lon &&
454
+ camera.center.lat === previous.center.lat
455
+ ) {
456
+ return;
457
+ }
458
+ const controlled = this._props.camera !== undefined;
459
+ if (!controlled) this._camera = camera;
460
+ this._props.onCameraChange?.(camera);
461
+ if (this.painting) {
462
+ // A camera set from **inside** a frame, which is how every camera
463
+ // animation is written: the map's own `onFrame` is the clock, and the
464
+ // GL view calls it while it is still painting. Re-entering the paint
465
+ // is not on, but returning here used to drop the move's *scheduling*
466
+ // as well as its redraw — so the animation had nothing to ask for the
467
+ // next frame with, and stopped until something unrelated re-rendered.
468
+ //
469
+ // In the maps-gl example that something was the status bar's
470
+ // half-second interval, and it showed as exactly that: frames every
471
+ // 11ms, then a 511ms hole with the next request arriving at +508 —
472
+ // nobody asking, rather than anyone being slow. Manual panning never
473
+ // hit it because an input event is not inside a paint.
474
+ //
475
+ // So the move is remembered, with the camera it started from, and
476
+ // finished when the frame ends.
477
+ this._paintMove ??= { previous };
478
+ return;
479
+ }
480
+ this.touch();
481
+ if (!controlled) this._view?.moved(previous, camera, blit);
482
+ }
483
+
484
+ /**
485
+ * A frame finished: do whatever `apply` deferred because it was painting.
486
+ * Called from both painters (`gl/view.ts`, `node.ts`) wherever `painting`
487
+ * goes back to false.
488
+ *
489
+ * Never a blit. A blit needs the exact transform it is shifting from, and
490
+ * what is flushed here may be several moves fused into one; a full redraw
491
+ * of a frame that was going to be drawn anyway costs nothing next to
492
+ * getting that wrong.
493
+ */
494
+ paintEnded(): void {
495
+ const move = this._paintMove;
496
+ if (!move) return;
497
+ this._paintMove = null;
498
+ this.touch();
499
+ if (this._props.camera === undefined) {
500
+ this._view?.moved(move.previous, this.camera(), false);
501
+ }
502
+ }
503
+
504
+ getCamera(): MapCamera {
505
+ const camera = this.camera();
506
+ return { center: { ...camera.center }, zoom: camera.zoom };
507
+ }
508
+
509
+ setCamera(camera: Partial<MapCamera>): void {
510
+ const current = this.camera();
511
+ this.apply(
512
+ {
513
+ center: camera.center ?? current.center,
514
+ zoom: camera.zoom ?? current.zoom,
515
+ },
516
+ false,
517
+ );
518
+ }
519
+
520
+ /** Move by a distance in pane-local logical pixels. */
521
+ panBy(dx: number, dy: number): void {
522
+ const t = this.transform();
523
+ this.apply(
524
+ {
525
+ zoom: t.zoom,
526
+ center: unprojectPoint(t, t.paneX + dx, t.paneY + dy),
527
+ },
528
+ true,
529
+ );
530
+ }
531
+
532
+ zoomIn(step = 1): void {
533
+ const pane = this.pane();
534
+ this.zoomAbout(step, pane.width / 2, pane.height / 2);
535
+ }
536
+
537
+ zoomOut(step = 1): void {
538
+ this.zoomIn(-step);
539
+ }
540
+
541
+ zoomTo(zoom: number): void {
542
+ this.setCamera({ zoom });
543
+ }
544
+
545
+ /**
546
+ * Zoom by `delta` levels about a pane-local point that must not move —
547
+ * the pointer under a wheel, the pane's centre for a key.
548
+ */
549
+ zoomAbout(delta: number, x: number, y: number): void {
550
+ const camera = this.camera();
551
+ const zoom = clamp(
552
+ quantizeZoom(camera.zoom + delta),
553
+ this._minZoom(),
554
+ this._maxZoom(),
555
+ );
556
+ if (zoom === camera.zoom) return;
557
+ this.apply(this._zoomedAbout(camera, zoom, x, y), false);
558
+ }
559
+
560
+ /** `camera` at `zoom`, with the point at pane-local `x`, `y` where it
561
+ * was: what {@link zoomAbout} moves to, and what a glide arrives at. */
562
+ private _zoomedAbout(
563
+ camera: MapCamera,
564
+ zoom: number,
565
+ x: number,
566
+ y: number,
567
+ ): MapCamera {
568
+ const before = this.transform(camera);
569
+ const anchor = unprojectPoint(before, x, y);
570
+ const after = this.transform({ center: camera.center, zoom });
571
+ // Where the anchor would land at the new zoom, and how far the centre
572
+ // has to move so it lands where it already is.
573
+ const moved = projectLngLat(after, anchor);
574
+ const dx = (moved.x - x) / after.world;
575
+ const dy = (moved.y - y) / after.world;
576
+ return {
577
+ zoom,
578
+ center: unprojectPoint(
579
+ {
580
+ ...after,
581
+ centerX: after.centerX + dx,
582
+ centerY: after.centerY + dy,
583
+ },
584
+ after.paneX,
585
+ after.paneY,
586
+ ),
587
+ };
588
+ }
589
+
590
+ /**
591
+ * Where the camera is going, when that is known before it gets there: the
592
+ * end of a wheel's glide. Null while nothing is gliding — a touchpad's
593
+ * stream, a drag or an application's own animation go wherever the next
594
+ * event says, and the view has only the camera to go on.
595
+ *
596
+ * What a renderer does with it is get there first: the tiles and label
597
+ * rasters of the view the glide stops at are asked for while the frames
598
+ * of the glide are still being drawn, so the settle has them in hand.
599
+ */
600
+ destination(): MapCamera | null {
601
+ const glide = this._glide;
602
+ if (!glide || !glide.easing) return null;
603
+ const camera = this.camera();
604
+ if (glide.applied !== camera.zoom) return null;
605
+ const zoom = clamp(
606
+ quantizeZoom(glide.target),
607
+ this._minZoom(),
608
+ this._maxZoom(),
609
+ );
610
+ if (zoom === camera.zoom) return null;
611
+ return this._zoomedAbout(camera, zoom, glide.x, glide.y);
612
+ }
613
+
614
+ /**
615
+ * A scroll, as a zoom: where the wheel wants the camera, and how the
616
+ * frames after it get there.
617
+ *
618
+ * **Two devices arrive here and they want opposite things.** A wheel
619
+ * *clicks*: one event carrying a whole notch, with nothing in between, so
620
+ * the notch becomes a target the frames after it glide towards. A touchpad
621
+ * *measures*: a stream of fractions that is already as smooth as the hand
622
+ * making it, which wants applying the moment it arrives and only needs
623
+ * keeping from rounding away. `ev.smooth` is core's word for which device
624
+ * this is — "a whole notch is worth easing towards, a stream of measured
625
+ * pixels is not" (react-x11's docs/events.md).
626
+ *
627
+ * Either way the *target* accumulates. A second notch arriving mid-glide
628
+ * lengthens the one gesture instead of starting another, and a fraction
629
+ * too small to move the quantized camera is still on the books when the
630
+ * next one arrives.
631
+ */
632
+ private _wheelZoom(
633
+ delta: number,
634
+ x: number,
635
+ y: number,
636
+ smooth: boolean,
637
+ ): void {
638
+ const at = glideClock.now();
639
+ const camera = this.camera();
640
+ const glide = this._glide;
641
+ // Where this delta counts from: the target the wheel has already asked
642
+ // for, or the camera when there is nothing outstanding. A record whose
643
+ // `applied` is not where the camera is belongs to a camera something
644
+ // else has since moved, and is not this gesture's to add to.
645
+ //
646
+ // Nothing expires it by age. A glide that is still owed frames is still
647
+ // owed them however long the frames take, and what is left of a
648
+ // touchpad's is under half a step of zoom — too little to be a jump
649
+ // whenever it is spent.
650
+ const from =
651
+ glide && glide.applied === camera.zoom ? glide.target : camera.zoom;
652
+ // Clamped here as well as in `apply`: an accumulator allowed past the
653
+ // limit records notches the map cannot answer, and the scroll back out
654
+ // then does nothing until they are spent.
655
+ this._glide = {
656
+ target: clamp(from + delta, this._minZoom(), this._maxZoom()),
657
+ applied: camera.zoom,
658
+ x,
659
+ y,
660
+ at,
661
+ easing: !smooth,
662
+ };
663
+ // The event's own step, so the map moves under the notch that asked
664
+ // rather than on the frame after it — and then the rest, a frame at a
665
+ // time, until the target is reached.
666
+ this.stepZoom(at, EASE_FIRST_MS);
667
+ this._armGlide();
668
+ }
669
+
670
+ /** Keep stepping a glide until it arrives. Idempotent: a notch arriving
671
+ * mid-glide moves the target and finds the timer already running. */
672
+ private _armGlide(): void {
673
+ if (this._glideTimer !== null || this._glide?.easing !== true) return;
674
+ const tick = (): void => {
675
+ this._glideTimer = null;
676
+ const glide = this._glide;
677
+ if (glide?.easing !== true) return;
678
+ const at = glideClock.now();
679
+ // `stepZoom` clears the record when the target is reached or the
680
+ // camera refuses a step, and this re-arms only while one is left.
681
+ this.stepZoom(at, at - glide.at);
682
+ this._armGlide();
683
+ };
684
+ this._glideTimer = glideClock.arm(tick, GLIDE_TICK_MS);
685
+ }
686
+
687
+ /**
688
+ * One step of a glide: how far the camera moves this frame.
689
+ *
690
+ * Exponential rather than a curve with a duration, because the distance is
691
+ * not known when it starts — a second notch moves the target while the
692
+ * first is still being delivered — and because `elapsed` being the real
693
+ * gap between two frames is what makes the glide the same speed on a
694
+ * display that paints 120 frames a second and one that manages 30.
695
+ *
696
+ * Returns whether the camera moved. The move itself is what brings the
697
+ * frame that shows it: `apply` tells the view, exactly as a drag's every
698
+ * pointer step does.
699
+ */
700
+ stepZoom(at: number, elapsed: number): boolean {
701
+ const glide = this._glide;
702
+ if (!glide) return false;
703
+ const camera = this.camera();
704
+ if (glide.applied !== camera.zoom) {
705
+ // The camera moved without this gesture: an application that owns it
706
+ // answering a wheel with something of its own, a `setCamera`, a fit.
707
+ // Whatever it was is more current than a notch from before it.
708
+ this._glide = null;
709
+ return false;
710
+ }
711
+ const remaining = glide.target - camera.zoom;
712
+ let step = glide.easing
713
+ ? remaining * (1 - Math.exp(-elapsed / WHEEL_EASE_MS))
714
+ : remaining;
715
+ // Never a step the quantized camera cannot show. The tail of an
716
+ // exponential is arbitrarily small, and a step that rounds to nothing
717
+ // would leave the glide asking for frames it has no use for — so the
718
+ // tail is walked a grid step at a time, and "the camera did not move" is
719
+ // left meaning what it says below.
720
+ if (Math.abs(step) < ZOOM_STEP) {
721
+ step =
722
+ Math.abs(remaining) < ZOOM_STEP
723
+ ? remaining
724
+ : Math.sign(remaining) * ZOOM_STEP;
725
+ }
726
+ const before = camera.zoom;
727
+ this.zoomAbout(step, glide.x, glide.y);
728
+ const zoom = this.camera().zoom;
729
+ glide.applied = zoom;
730
+ glide.at = at;
731
+ if (zoom === before) {
732
+ // The camera refused a step it cannot have rounded away — an
733
+ // application owns it and did not answer, or it is against its limit.
734
+ // A wheel's glide has nothing further to deliver; a touchpad's record
735
+ // stays behind as the accumulator, and the next fraction moves it on.
736
+ if (glide.easing) this._glide = null;
737
+ return false;
738
+ }
739
+ return true;
740
+ }
741
+
742
+ fitBounds(bounds: LngLatBounds, options?: FitBoundsOptions): void {
743
+ const pane = this.pane();
744
+ if (pane.width <= 0 || pane.height <= 0) {
745
+ // Asked before layout has run — which `fitBounds` in an effect always
746
+ // is. Remembered, and applied at the first frame that has a size.
747
+ this._pendingFit = { bounds, options };
748
+ return;
749
+ }
750
+ this._pendingFit = null;
751
+ this.apply(
752
+ cameraForBounds(
753
+ bounds,
754
+ { width: pane.width, height: pane.height },
755
+ {
756
+ padding: options?.padding ?? 24,
757
+ tileSize: DEFAULT_TILE_SIZE,
758
+ minZoom: this._minZoom(),
759
+ maxZoom: options?.maxZoom ?? this._maxZoom(),
760
+ },
761
+ ),
762
+ false,
763
+ );
764
+ }
765
+
766
+ fitMarkers(ids?: readonly string[], options?: FitBoundsOptions): void {
767
+ const wanted = ids ? new Set(ids) : null;
768
+ const positions: LngLat[] = [];
769
+ for (const marker of this._markers()) {
770
+ if (wanted && !wanted.has(marker.id)) continue;
771
+ positions.push(marker.position);
772
+ }
773
+ const bounds = boundsOf(positions);
774
+ if (bounds) this.fitBounds(bounds, options);
775
+ }
776
+
777
+ /** What the pane can see — the whole world before it has a size. */
778
+ getBounds(): LngLatBounds {
779
+ const pane = this.pane();
780
+ if (pane.width <= 0 || pane.height <= 0) {
781
+ return { west: -180, south: -85, east: 180, north: 85 };
782
+ }
783
+ return visibleBounds(this.transform());
784
+ }
785
+
786
+ project(position: LngLat): { x: number; y: number } {
787
+ return projectLngLat(this.transform(), position);
788
+ }
789
+
790
+ unproject(x: number, y: number): LngLat {
791
+ return unprojectPoint(this.transform(), x, y);
792
+ }
793
+
794
+ markerAt(x: number, y: number): MapMarker | null {
795
+ return markerAt(this._markers(), this.transform(), x, y);
796
+ }
797
+
798
+ /**
799
+ * A view is about to draw a frame: a `fitBounds` that arrived before the
800
+ * pane had a size is applied now, so the frame draws it.
801
+ */
802
+ beginFrame(): void {
803
+ const fit = this._pendingFit;
804
+ if (!fit) return;
805
+ const pane = this.pane();
806
+ if (pane.width <= 0 || pane.height <= 0) return;
807
+ this.fitBounds(fit.bounds, fit.options);
808
+ }
809
+
810
+ // --- the settle window ---------------------------------------------------
811
+
812
+ /** Whether the camera moved within the settle window. */
813
+ get moving(): boolean {
814
+ return Date.now() < this._settleAt;
815
+ }
816
+
817
+ /** …or a press is still down: what the retained renderer holds
818
+ * rasterization off for. */
819
+ get gesturing(): boolean {
820
+ return this._gesture !== null || this.moving;
821
+ }
822
+
823
+ /** Whether a pan gesture is under way — a press that may yet drag. */
824
+ get dragging(): boolean {
825
+ return this._gesture?.kind === 'pan';
826
+ }
827
+
828
+ /**
829
+ * Restart the settle window. When it closes the camera has held still for
830
+ * {@link SETTLE_MS}: `onMoveEnd` fires — the moment an application fetches
831
+ * what is now on screen — and the view is told it may sharpen.
832
+ *
833
+ * Wall-clock time rather than a frame clock: this is a window a hundred
834
+ * and forty milliseconds long compared inside a timer callback, and a
835
+ * timer is the one thing that runs when no frame does.
836
+ */
837
+ touch(): void {
838
+ this._settleAt = Date.now() + SETTLE_MS;
839
+ if (this._settleTimer !== null) return;
840
+ const tick = (): void => {
841
+ this._settleTimer = null;
842
+ const left = this._settleAt - Date.now();
843
+ if (left > 0) {
844
+ this._settleTimer = arm(tick, left);
845
+ return;
846
+ }
847
+ this._props.onMoveEnd?.(this.camera());
848
+ this._view?.settled();
849
+ };
850
+ this._settleTimer = arm(tick, SETTLE_MS);
851
+ }
852
+
853
+ // --- input ---------------------------------------------------------------
854
+
855
+ /**
856
+ * A press. Answers what it began, for the view to capture the pointer — and
857
+ * for a pan, to take the focus — or null when nothing is.
858
+ *
859
+ * A press on a marker is a marker gesture: its release is a marker click.
860
+ * A press anywhere else is a pan, or on a map that does not move a
861
+ * `'frozen'` press, which pans nothing and is still a click when it is
862
+ * released — an application listening for clicks on a frozen map gets
863
+ * them.
864
+ */
865
+ pointerDown(input: MapPointerInput): PressKind {
866
+ const marker = markerAt(
867
+ this._markers(),
868
+ this.transform(),
869
+ input.x,
870
+ input.y,
871
+ );
872
+ if (marker) {
873
+ this._gesture = {
874
+ kind: 'marker',
875
+ id: marker.id,
876
+ startX: input.x,
877
+ startY: input.y,
878
+ };
879
+ return 'marker';
880
+ }
881
+ this._gesture = {
882
+ kind: 'pan',
883
+ startX: input.x,
884
+ startY: input.y,
885
+ lastX: input.x,
886
+ lastY: input.y,
887
+ moved: false,
888
+ };
889
+ return this._interactive() ? 'pan' : 'frozen';
890
+ }
891
+
892
+ /** The pointer moved with the press still down. */
893
+ pointerDrag(input: MapPointerInput): void {
894
+ const gesture = this._gesture;
895
+ if (!gesture || gesture.kind !== 'pan') return;
896
+ if (!this._interactive()) return;
897
+ if (
898
+ !gesture.moved &&
899
+ Math.abs(input.x - gesture.startX) < DRAG_THRESHOLD &&
900
+ Math.abs(input.y - gesture.startY) < DRAG_THRESHOLD
901
+ ) {
902
+ return;
903
+ }
904
+ gesture.moved = true;
905
+ // Whole device pixels, because that is what the retained renderer's
906
+ // blit can shift — a fractional pan would decline it every frame and
907
+ // repaint the pane. Invisible on the GL renderer, which draws any shift.
908
+ const scale = this._view?.scale() ?? 1;
909
+ const dx = Math.round((input.x - gesture.lastX) * scale) / scale;
910
+ const dy = Math.round((input.y - gesture.lastY) * scale) / scale;
911
+ if (dx === 0 && dy === 0) return;
912
+ gesture.lastX += dx;
913
+ gesture.lastY += dy;
914
+ this.touch();
915
+ this.panBy(-dx, -dy);
916
+ }
917
+
918
+ /**
919
+ * The press let go. A release within the drag threshold of a marker press
920
+ * is that marker's click, then the map's; one that ended no drag is the
921
+ * map's click. And the second release of a double click zooms in about the
922
+ * pointer, Shift for out — the convention every map client has.
923
+ */
924
+ pointerUp(input: MapPointerInput): void {
925
+ const gesture = this._gesture;
926
+ this._gesture = null;
927
+ if (!gesture) return;
928
+ if (gesture.kind === 'marker') {
929
+ const marker = this._markers().find((m) => m.id === gesture.id);
930
+ if (
931
+ marker &&
932
+ Math.abs(input.x - gesture.startX) < DRAG_THRESHOLD &&
933
+ Math.abs(input.y - gesture.startY) < DRAG_THRESHOLD
934
+ ) {
935
+ const event = this.pointerEvent(input, marker);
936
+ this._props.onMarkerClick?.(marker, event);
937
+ this._props.onMapClick?.(event);
938
+ }
939
+ return;
940
+ }
941
+ if (gesture.moved) {
942
+ this.touch();
943
+ return;
944
+ }
945
+ this._props.onMapClick?.(this.pointerEvent(input, null));
946
+ if (input.detail === 2 && this._interactive()) {
947
+ this.zoomAbout(input.shiftKey ? -1 : 1, input.x, input.y);
948
+ }
949
+ }
950
+
951
+ /** The pointer moved with nothing pressed: the marker under it, if that
952
+ * changed, is `onMarkerHover`'s. */
953
+ pointerMove(input: MapPointerInput): void {
954
+ const notify = this._props.onMarkerHover;
955
+ if (!notify) return;
956
+ const marker = markerAt(
957
+ this._markers(),
958
+ this.transform(),
959
+ input.x,
960
+ input.y,
961
+ );
962
+ const id = marker?.id ?? null;
963
+ if (id === this._hover) return;
964
+ this._hover = id;
965
+ notify(marker, this.pointerEvent(input, marker));
966
+ }
967
+
968
+ /**
969
+ * The pointer left the map. No event: there is no position on the map to
970
+ * report, and inventing one would be worse than saying so.
971
+ */
972
+ pointerLeave(): void {
973
+ if (this._hover === null) return;
974
+ this._hover = null;
975
+ this._props.onMarkerHover?.(null, null);
976
+ }
977
+
978
+ /**
979
+ * The wheel, which is a zoom about the pointer. True when it was consumed
980
+ * — always, on a map that moves: a wheel over a map is never meant for
981
+ * whatever is behind it.
982
+ */
983
+ wheel(input: MapPointerInput, deltaY: number, smooth = false): boolean {
984
+ if (!this._interactive()) return false;
985
+ this.touch();
986
+ this._wheelZoom(-deltaY * WHEEL_ZOOM * 0.02, input.x, input.y, smooth);
987
+ return true;
988
+ }
989
+
990
+ /** A key: the arrows pan, +/− zoom about the centre. True when it was one
991
+ * of those, on a map that moves. */
992
+ keyDown(keysym: number, shiftKey: boolean): boolean {
993
+ if (!this._interactive()) return false;
994
+ const pane = this.pane();
995
+ const step = shiftKey ? 200 : 60;
996
+ switch (keysym) {
997
+ case 0xff51: // XK_Left
998
+ this.panBy(-step, 0);
999
+ return true;
1000
+ case 0xff53: // XK_Right
1001
+ this.panBy(step, 0);
1002
+ return true;
1003
+ case 0xff52: // XK_Up
1004
+ this.panBy(0, -step);
1005
+ return true;
1006
+ case 0xff54: // XK_Down
1007
+ this.panBy(0, step);
1008
+ return true;
1009
+ case 0x002b: // XK_plus
1010
+ case 0x003d: // XK_equal
1011
+ case 0xffab: // XK_KP_Add
1012
+ this.zoomAbout(1, pane.width / 2, pane.height / 2);
1013
+ return true;
1014
+ case 0x002d: // XK_minus
1015
+ case 0xffad: // XK_KP_Subtract
1016
+ this.zoomAbout(-1, pane.width / 2, pane.height / 2);
1017
+ return true;
1018
+ default:
1019
+ return false;
1020
+ }
1021
+ }
1022
+
1023
+ /** Where a pointer event happened, in every space that could be wanted. */
1024
+ pointerEvent(
1025
+ input: MapPointerInput,
1026
+ marker: MapMarker | null,
1027
+ ): MapPointerEvent {
1028
+ return {
1029
+ lngLat: unprojectPoint(this.transform(), input.x, input.y),
1030
+ x: input.x,
1031
+ y: input.y,
1032
+ marker,
1033
+ shiftKey: input.shiftKey ?? false,
1034
+ ctrlKey: input.ctrlKey ?? false,
1035
+ altKey: input.altKey ?? false,
1036
+ metaKey: input.metaKey ?? false,
1037
+ button: input.button ?? 1,
1038
+ };
1039
+ }
1040
+
1041
+ /**
1042
+ * What a screen reader meets: the markers in view, as buttons.
1043
+ *
1044
+ * A map is one painted rectangle to an assistive technology, and its
1045
+ * markers are the only things in it that are *objects* rather than
1046
+ * cartography — so those are the scene. Announcing every road would be
1047
+ * worse than announcing none. The same whichever renderer draws.
1048
+ */
1049
+ markerScene(): A11ySceneItem[] {
1050
+ const pane = this.pane();
1051
+ if (pane.width <= 0 || pane.height <= 0) return [];
1052
+ const transform = this.transform();
1053
+ const scale = this._view?.scale() ?? 1;
1054
+ const items: A11ySceneItem[] = [];
1055
+ for (const marker of this._markers()) {
1056
+ const rect = markerRect(marker, transform);
1057
+ if (
1058
+ rect.x + rect.width < 0 ||
1059
+ rect.y + rect.height < 0 ||
1060
+ rect.x > pane.width ||
1061
+ rect.y > pane.height
1062
+ ) {
1063
+ continue;
1064
+ }
1065
+ items.push({
1066
+ id: `marker:${marker.id}`,
1067
+ // Device pixels in the owning window's coordinates, which is what
1068
+ // an a11y scene rect is — the same space as `abs`.
1069
+ rect: {
1070
+ x: (pane.x + rect.x) * scale,
1071
+ y: (pane.y + rect.y) * scale,
1072
+ width: rect.width * scale,
1073
+ height: rect.height * scale,
1074
+ },
1075
+ role: 'button',
1076
+ name:
1077
+ marker.title ??
1078
+ `${marker.position.lat.toFixed(4)}, ${marker.position.lon.toFixed(4)}`,
1079
+ states: { selected: marker.selected ?? false },
1080
+ });
1081
+ }
1082
+ return items;
1083
+ }
1084
+ }