@sakuzu/maplibre-gl-draw 1.0.0 → 2.0.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 (540) hide show
  1. package/CHANGELOG.md +1016 -2
  2. package/README.ja.md +39 -19
  3. package/README.md +41 -21
  4. package/dist/api/datasets.d.ts +258 -0
  5. package/dist/api/document.d.ts +66 -0
  6. package/dist/api/draw.d.ts +135 -0
  7. package/dist/api/draw.js +18 -0
  8. package/dist/api/drawing.d.ts +87 -0
  9. package/dist/api/errors.d.ts +35 -0
  10. package/dist/api/errors.js +35 -0
  11. package/dist/api/events.d.ts +306 -0
  12. package/dist/api/extension/context.d.ts +247 -0
  13. package/dist/api/extension/feature-type.d.ts +129 -0
  14. package/dist/api/extension/mode.d.ts +123 -0
  15. package/dist/api/extension/plugin.d.ts +51 -0
  16. package/dist/api/extension/plugin.js +3 -0
  17. package/dist/api/extension/provider.d.ts +119 -0
  18. package/dist/api/extension/provider.js +3 -0
  19. package/dist/api/extension/render.d.ts +176 -0
  20. package/dist/api/extension/render.js +3 -0
  21. package/dist/api/extension/store.d.ts +190 -0
  22. package/dist/api/extension/store.js +3 -0
  23. package/dist/api/extensions.d.ts +306 -0
  24. package/dist/api/extensions.js +3 -0
  25. package/dist/api/features.d.ts +188 -0
  26. package/dist/api/features.js +3 -0
  27. package/dist/api/groups.d.ts +111 -0
  28. package/dist/api/groups.js +3 -0
  29. package/dist/api/hidden.d.ts +45 -0
  30. package/dist/api/hidden.js +3 -0
  31. package/dist/api/impl/adapters.js +463 -0
  32. package/dist/api/impl/contexts.js +466 -0
  33. package/dist/api/impl/create-draw.js +124 -0
  34. package/dist/api/impl/datasets.js +404 -0
  35. package/dist/api/impl/destroy-guard.js +74 -0
  36. package/dist/api/impl/document.js +280 -0
  37. package/dist/api/impl/drawing.js +180 -0
  38. package/dist/api/impl/engine-context.d.ts +7 -0
  39. package/dist/api/{context.js → impl/engine-context.js} +49 -38
  40. package/dist/{maplibre-gl-draw.js → api/impl/engine.js} +145 -177
  41. package/dist/api/impl/events.js +422 -0
  42. package/dist/api/impl/extension-host.js +361 -0
  43. package/dist/api/impl/extensions.js +229 -0
  44. package/dist/api/impl/features.js +445 -0
  45. package/dist/api/impl/geometry/apply.d.ts +32 -0
  46. package/dist/api/{geometry → impl/geometry}/apply.js +10 -27
  47. package/dist/api/{geometry → impl/geometry}/buffer.d.ts +4 -3
  48. package/dist/api/{geometry → impl/geometry}/buffer.js +12 -23
  49. package/dist/api/{geometry → impl/geometry}/split.d.ts +4 -3
  50. package/dist/api/{geometry → impl/geometry}/split.js +10 -21
  51. package/dist/api/{geometry → impl/geometry}/targets.d.ts +2 -20
  52. package/dist/api/{geometry → impl/geometry}/targets.js +8 -35
  53. package/dist/api/impl/geometry/types.js +3 -0
  54. package/dist/api/impl/groups.d.ts +3 -0
  55. package/dist/api/impl/groups.js +268 -0
  56. package/dist/api/impl/hidden.js +60 -0
  57. package/dist/api/impl/import-export/constants.d.ts +22 -0
  58. package/dist/api/impl/import-export/constants.js +24 -0
  59. package/dist/api/{import-export → impl/import-export}/embedded-file.js +2 -2
  60. package/dist/api/{import-export → impl/import-export}/format-detection.d.ts +1 -1
  61. package/dist/api/{import-export → impl/import-export}/format-detection.js +2 -1
  62. package/dist/api/impl/import-export/geojson-export.d.ts +19 -0
  63. package/dist/api/{import-export → impl/import-export}/geojson-export.js +71 -104
  64. package/dist/api/{import-export → impl/import-export}/geojson-import.d.ts +11 -7
  65. package/dist/api/{import-export → impl/import-export}/geojson-import.js +139 -97
  66. package/dist/api/{import-export → impl/import-export}/geometry-validation.d.ts +14 -0
  67. package/dist/api/{import-export → impl/import-export}/geometry-validation.js +45 -0
  68. package/dist/api/impl/import-export/image-import.d.ts +16 -0
  69. package/dist/api/impl/import-export/image-import.js +73 -0
  70. package/dist/api/impl/import-export/legacy-image-style.d.ts +16 -0
  71. package/dist/api/impl/import-export/legacy-image-style.js +49 -0
  72. package/dist/api/impl/import-export/native-format.d.ts +14 -0
  73. package/dist/api/{import-export → impl/import-export}/native-format.js +32 -22
  74. package/dist/api/impl/import-export/native-upgrade.d.ts +8 -0
  75. package/dist/api/impl/import-export/native-upgrade.js +139 -0
  76. package/dist/api/{import-export → impl/import-export}/native-validation.d.ts +1 -1
  77. package/dist/api/{import-export → impl/import-export}/native-validation.js +15 -14
  78. package/dist/api/impl/import-export/style-validation.d.ts +24 -0
  79. package/dist/api/impl/import-export/style-validation.js +86 -0
  80. package/dist/api/impl/import-export/types.d.ts +52 -0
  81. package/dist/api/impl/import-export/types.js +3 -0
  82. package/dist/api/impl/input.js +180 -0
  83. package/dist/api/impl/layers.js +307 -0
  84. package/dist/api/impl/metadata.d.ts +1 -0
  85. package/dist/api/impl/metadata.js +22 -0
  86. package/dist/api/impl/options.d.ts +1 -0
  87. package/dist/api/impl/options.js +822 -0
  88. package/dist/api/impl/placement.d.ts +1 -0
  89. package/dist/api/impl/placement.js +138 -0
  90. package/dist/api/impl/render-context.d.ts +13 -0
  91. package/dist/api/impl/render-context.js +272 -0
  92. package/dist/api/impl/rows.d.ts +1 -0
  93. package/dist/api/impl/rows.js +46 -0
  94. package/dist/api/impl/selection.d.ts +1 -0
  95. package/dist/api/impl/selection.js +186 -0
  96. package/dist/api/impl/shared.d.ts +64 -0
  97. package/dist/api/impl/shared.js +178 -0
  98. package/dist/api/impl/validate-extension.d.ts +1 -0
  99. package/dist/api/impl/validate-extension.js +159 -0
  100. package/dist/api/layers.d.ts +130 -0
  101. package/dist/api/layers.js +3 -0
  102. package/dist/api/metadata.d.ts +18 -0
  103. package/dist/api/metadata.js +3 -0
  104. package/dist/api/model.d.ts +487 -0
  105. package/dist/api/model.js +47 -0
  106. package/dist/api/options.d.ts +466 -0
  107. package/dist/api/options.js +3 -0
  108. package/dist/api/selection.d.ts +94 -0
  109. package/dist/api/selection.js +3 -0
  110. package/dist/api/state.d.ts +155 -0
  111. package/dist/api/state.js +12 -0
  112. package/dist/{display → dataset}/chunk.d.ts +1 -1
  113. package/dist/{display → dataset}/chunk.js +4 -3
  114. package/dist/{display → dataset}/dataset.js +18 -21
  115. package/dist/dataset/interaction.d.ts +1 -0
  116. package/dist/{display → dataset}/interaction.js +18 -6
  117. package/dist/dataset/manager.d.ts +1 -0
  118. package/dist/dataset/provider.d.ts +1 -0
  119. package/dist/{display → dataset}/retained.d.ts +1 -1
  120. package/dist/{display → dataset}/retained.js +8 -7
  121. package/dist/dataset/source.d.ts +1 -0
  122. package/dist/{display → dataset}/source.js +17 -4
  123. package/dist/dataset/spatial.d.ts +1 -0
  124. package/dist/{display → dataset}/spatial.js +1 -1
  125. package/dist/dataset/style.d.ts +1 -0
  126. package/dist/{display → dataset}/style.js +1 -1
  127. package/dist/dataset/table-source.d.ts +1 -0
  128. package/dist/{display/columnar/source.js → dataset/table-source.js} +53 -25
  129. package/dist/{display → dataset}/thinning.d.ts +0 -10
  130. package/dist/{display → dataset}/thinning.js +3 -2
  131. package/dist/dataset/triangulation.d.ts +1 -0
  132. package/dist/{display → dataset}/triangulation.js +0 -0
  133. package/dist/{display → dataset}/types.d.ts +82 -121
  134. package/dist/dataset/types.js +61 -0
  135. package/dist/dispatcher/hit-test/box-strategies.js +13 -13
  136. package/dist/dispatcher/hit-test/box-strategy.d.ts +2 -15
  137. package/dist/dispatcher/hit-test/globe-shape.js +5 -4
  138. package/dist/dispatcher/hit-test/service.d.ts +17 -0
  139. package/dist/dispatcher/hit-test/service.js +80 -16
  140. package/dist/dispatcher/hit-test/strategies/base.d.ts +13 -19
  141. package/dist/dispatcher/hit-test/strategies/circle.js +3 -2
  142. package/dist/dispatcher/hit-test/strategies/image.js +6 -18
  143. package/dist/dispatcher/hit-test/strategies/line.d.ts +0 -6
  144. package/dist/dispatcher/hit-test/strategies/line.js +9 -2
  145. package/dist/dispatcher/hit-test/strategies/multi.d.ts +0 -8
  146. package/dist/dispatcher/hit-test/strategies/multi.js +17 -8
  147. package/dist/dispatcher/hit-test/strategies/point.d.ts +9 -7
  148. package/dist/dispatcher/hit-test/strategies/point.js +8 -4
  149. package/dist/dispatcher/hit-test/strategies/polygon.d.ts +0 -7
  150. package/dist/dispatcher/hit-test/strategies/polygon.js +11 -3
  151. package/dist/dispatcher/hit-test/topmost.d.ts +1 -1
  152. package/dist/dispatcher/input-router.js +152 -69
  153. package/dist/dispatcher/normalizer.js +6 -2
  154. package/dist/dispatcher/types.d.ts +6 -1
  155. package/dist/extension/feature-handler.d.ts +1 -182
  156. package/dist/extension/index.d.ts +4 -7
  157. package/dist/extension/renderers.d.ts +1 -208
  158. package/dist/geometry/angle.d.ts +0 -8
  159. package/dist/geometry/angle.js +0 -8
  160. package/dist/geometry/bbox.d.ts +4 -12
  161. package/dist/geometry/bbox.js +4 -12
  162. package/dist/geometry/boolean.d.ts +0 -51
  163. package/dist/geometry/boolean.js +0 -51
  164. package/dist/geometry/buffer.d.ts +0 -26
  165. package/dist/geometry/buffer.js +0 -26
  166. package/dist/geometry/circle.d.ts +0 -9
  167. package/dist/geometry/circle.js +0 -9
  168. package/dist/geometry/coords.d.ts +0 -16
  169. package/dist/geometry/coords.js +0 -16
  170. package/dist/geometry/distance.d.ts +0 -24
  171. package/dist/geometry/distance.js +0 -24
  172. package/dist/geometry/errors.d.ts +21 -36
  173. package/dist/geometry/errors.js +49 -29
  174. package/dist/geometry/geojson.d.ts +81 -0
  175. package/dist/geometry/geojson.js +164 -0
  176. package/dist/geometry/index.d.ts +38 -23
  177. package/dist/geometry/index.js +43 -31
  178. package/dist/geometry/measure.d.ts +0 -27
  179. package/dist/geometry/measure.js +0 -27
  180. package/dist/geometry/predicates.d.ts +0 -9
  181. package/dist/geometry/predicates.js +0 -9
  182. package/dist/geometry/public-bounds.d.ts +26 -0
  183. package/dist/geometry/public-bounds.js +30 -0
  184. package/dist/geometry/public-combine.d.ts +78 -0
  185. package/dist/geometry/public-combine.js +82 -0
  186. package/dist/geometry/public-create.d.ts +54 -0
  187. package/dist/geometry/public-create.js +70 -0
  188. package/dist/geometry/public-measure.d.ts +170 -0
  189. package/dist/geometry/public-measure.js +283 -0
  190. package/dist/geometry/public-predicates.d.ts +54 -0
  191. package/dist/geometry/public-predicates.js +144 -0
  192. package/dist/geometry/public-repair.d.ts +75 -0
  193. package/dist/geometry/public-repair.js +77 -0
  194. package/dist/geometry/simplify.d.ts +0 -7
  195. package/dist/geometry/simplify.js +0 -7
  196. package/dist/geometry/split.d.ts +0 -20
  197. package/dist/geometry/split.js +0 -20
  198. package/dist/geometry/units.d.ts +20 -12
  199. package/dist/geometry/units.js +20 -12
  200. package/dist/index.d.ts +52 -66
  201. package/dist/index.js +6 -18
  202. package/dist/messages.d.ts +7 -7
  203. package/dist/modes/draw/circle.js +83 -207
  204. package/dist/modes/draw/commit-layer.d.ts +5 -16
  205. package/dist/modes/draw/commit-layer.js +2 -13
  206. package/dist/modes/draw/freehand.js +108 -246
  207. package/dist/modes/draw/image.js +4 -2
  208. package/dist/modes/draw/index.d.ts +5 -5
  209. package/dist/modes/draw/index.js +5 -5
  210. package/dist/modes/draw/line.js +18 -354
  211. package/dist/modes/draw/point.js +29 -78
  212. package/dist/modes/draw/polygon.js +23 -368
  213. package/dist/modes/draw/trace-support.d.ts +43 -36
  214. package/dist/modes/draw/trace-support.js +95 -98
  215. package/dist/modes/draw/vertex-drawing.d.ts +1 -0
  216. package/dist/modes/draw/vertex-drawing.js +176 -0
  217. package/dist/modes/handler.d.ts +1 -285
  218. package/dist/modes/manager.d.ts +2 -2
  219. package/dist/modes/manager.js +3 -0
  220. package/dist/modes/select/box-selection.d.ts +3 -3
  221. package/dist/modes/select/box-selection.js +2 -1
  222. package/dist/modes/select/click-handler.d.ts +5 -5
  223. package/dist/modes/select/click-handler.js +22 -20
  224. package/dist/modes/select/cursor-handler.d.ts +2 -2
  225. package/dist/modes/select/drag/intermediate-writes.js +1 -1
  226. package/dist/modes/select/drag/move.js +3 -3
  227. package/dist/modes/select/drag/operation.d.ts +3 -3
  228. package/dist/modes/select/drag/radius.js +5 -4
  229. package/dist/modes/select/drag/transform.d.ts +2 -2
  230. package/dist/modes/select/drag/transform.js +11 -5
  231. package/dist/modes/select/drag/vertex.d.ts +2 -2
  232. package/dist/modes/select/drag/vertex.js +13 -8
  233. package/dist/modes/select/drag-handler.js +44 -25
  234. package/dist/modes/select/mode.js +17 -17
  235. package/dist/modes/select/shortcut-handler.d.ts +8 -8
  236. package/dist/modes/select/shortcut-handler.js +9 -7
  237. package/dist/operations/layer-operations.js +29 -168
  238. package/dist/operations/resize.d.ts +2 -2
  239. package/dist/operations/resize.js +5 -5
  240. package/dist/operations/rotate.js +5 -5
  241. package/dist/operations/selection-operations.d.ts +16 -1
  242. package/dist/operations/selection-operations.js +28 -13
  243. package/dist/operations/shared-vertex.js +4 -2
  244. package/dist/operations/trace-graph.d.ts +0 -18
  245. package/dist/operations/trace-graph.js +0 -18
  246. package/dist/operations/vertex.js +36 -35
  247. package/dist/shared/color.d.ts +1 -0
  248. package/dist/shared/color.js +245 -0
  249. package/dist/shared/config/constants.d.ts +1 -54
  250. package/dist/shared/config/constants.js +1 -58
  251. package/dist/shared/config/feature-style.d.ts +16 -13
  252. package/dist/shared/config/feature-style.js +9 -0
  253. package/dist/shared/config/rendering.d.ts +3 -3
  254. package/dist/shared/config/selection-highlight.d.ts +0 -15
  255. package/dist/shared/config/selection-highlight.js +4 -7
  256. package/dist/shared/config/selection.d.ts +2 -32
  257. package/dist/shared/config/selection.js +0 -18
  258. package/dist/shared/config/topology.d.ts +2 -2
  259. package/dist/shared/config/trace.d.ts +4 -4
  260. package/dist/shared/math/angle.d.ts +1 -1
  261. package/dist/shared/math/angle.js +1 -1
  262. package/dist/shared/math/circle.d.ts +1 -1
  263. package/dist/shared/math/circle.js +1 -1
  264. package/dist/shared/math/distance.d.ts +2 -1
  265. package/dist/shared/math/distance.js +3 -2
  266. package/dist/shared/math/index.d.ts +1 -1
  267. package/dist/shared/math/index.js +1 -1
  268. package/dist/shared/math/transform.d.ts +23 -0
  269. package/dist/shared/math/transform.js +47 -28
  270. package/dist/shared/properties.d.ts +18 -0
  271. package/dist/shared/properties.js +129 -0
  272. package/dist/shared/types/events.d.ts +15 -7
  273. package/dist/shared/types/model.d.ts +109 -159
  274. package/dist/shared/types/style.d.ts +1 -1
  275. package/dist/shared/utils/color.d.ts +2 -36
  276. package/dist/shared/utils/color.js +13 -70
  277. package/dist/shared/utils/coordinates.d.ts +30 -4
  278. package/dist/shared/utils/coordinates.js +56 -10
  279. package/dist/shared/utils/event-emitter.d.ts +1 -262
  280. package/dist/shared/utils/event-emitter.js +4 -3
  281. package/dist/shared/utils/feature-bbox.js +8 -7
  282. package/dist/shared/utils/feature-segments.js +5 -4
  283. package/dist/shared/utils/image.d.ts +0 -4
  284. package/dist/shared/utils/image.js +0 -6
  285. package/dist/shared/utils/name-generator.d.ts +14 -20
  286. package/dist/shared/utils/name-generator.js +20 -3
  287. package/dist/shared/utils/pixel-ratio.d.ts +9 -3
  288. package/dist/shared/utils/pixel-ratio.js +13 -4
  289. package/dist/shared/utils/property.d.ts +7 -50
  290. package/dist/shared/utils/property.js +22 -87
  291. package/dist/snapping/custom-targets.js +21 -4
  292. package/dist/snapping/indicator.js +20 -11
  293. package/dist/snapping/providers/display.d.ts +6 -1
  294. package/dist/snapping/providers/display.js +2 -1
  295. package/dist/snapping/providers/guide.d.ts +3 -43
  296. package/dist/snapping/providers/guide.js +1 -44
  297. package/dist/snapping/providers/intersection.js +1 -1
  298. package/dist/snapping/providers/store.js +3 -3
  299. package/dist/snapping/service.js +18 -7
  300. package/dist/snapping/types.d.ts +9 -35
  301. package/dist/store/draw-store.js +233 -142
  302. package/dist/store/local-visibility.d.ts +11 -6
  303. package/dist/store/local-visibility.js +38 -7
  304. package/dist/store/lock.d.ts +0 -6
  305. package/dist/store/lock.js +0 -6
  306. package/dist/store/memory/change-bus.d.ts +3 -3
  307. package/dist/store/memory/change-bus.js +12 -0
  308. package/dist/store/memory/file-store.d.ts +2 -2
  309. package/dist/store/memory/ui-state.d.ts +1 -51
  310. package/dist/store/memory/ui-state.js +122 -134
  311. package/dist/store/memory.d.ts +1 -8
  312. package/dist/store/memory.js +249 -45
  313. package/dist/store/ordering.d.ts +9 -0
  314. package/dist/store/ordering.js +17 -0
  315. package/dist/store/spatial/spatial-index.d.ts +1 -1
  316. package/dist/store/spatial/spatial-index.js +1 -1
  317. package/dist/store/spatial/store-spatial-index.d.ts +3 -1
  318. package/dist/store/spatial/store-spatial-index.js +9 -3
  319. package/dist/store/store.d.ts +66 -107
  320. package/dist/store/types.d.ts +1 -1
  321. package/dist/store/writable-layer.d.ts +1 -1
  322. package/dist/store/writable-layer.js +2 -2
  323. package/dist/table/builder.d.ts +83 -0
  324. package/dist/table/builder.js +381 -0
  325. package/dist/table/index.d.ts +37 -0
  326. package/dist/table/index.js +5 -0
  327. package/dist/table/packed-rtree.d.ts +1 -0
  328. package/dist/{display → table}/packed-rtree.js +1 -1
  329. package/dist/table/partition.d.ts +1 -0
  330. package/dist/{display → table}/partition.js +3 -3
  331. package/dist/table/prepare.d.ts +44 -0
  332. package/dist/table/prepare.js +136 -0
  333. package/dist/table/table.d.ts +1 -0
  334. package/dist/{display/columnar → table}/table.js +29 -25
  335. package/dist/{display/columnar → table}/types.d.ts +68 -72
  336. package/dist/table/types.js +3 -0
  337. package/dist/view/coordinator.js +4 -3
  338. package/dist/view/feature-companion.d.ts +13 -7
  339. package/dist/view/feature-companion.js +11 -3
  340. package/dist/view/globe-subdivision.js +3 -3
  341. package/dist/view/layer/attach.d.ts +1 -1
  342. package/dist/view/layer/attach.js +1 -1
  343. package/dist/view/layer/custom-layer.js +40 -11
  344. package/dist/view/layer/display-list.js +2 -1
  345. package/dist/view/layer/drape-planner.d.ts +2 -2
  346. package/dist/view/layer/frame-render.d.ts +3 -3
  347. package/dist/view/layer/frame-render.js +7 -2
  348. package/dist/view/layer/frame-state.d.ts +6 -6
  349. package/dist/view/layer/index.d.ts +2 -2
  350. package/dist/view/layer/index.js +1 -1
  351. package/dist/view/layer/render.d.ts +4 -4
  352. package/dist/view/layer/render.js +3 -8
  353. package/dist/view/layer/renderers.d.ts +2 -2
  354. package/dist/view/layer/renderers.js +1 -1
  355. package/dist/view/layer/slot-manager.d.ts +2 -2
  356. package/dist/view/layer/slot-manager.js +4 -4
  357. package/dist/view/layer/slots.d.ts +2 -2
  358. package/dist/view/layer/slots.js +1 -1
  359. package/dist/view/layer/store-retained-bbox.js +3 -2
  360. package/dist/view/layer/store-retained-classify.d.ts +5 -7
  361. package/dist/view/layer/store-retained-classify.js +19 -7
  362. package/dist/view/layer/store-retained-collect.js +8 -7
  363. package/dist/view/layer/store-retained-coord-patch.d.ts +0 -8
  364. package/dist/view/layer/store-retained-coord-patch.js +13 -4
  365. package/dist/view/layer/store-retained-immediate.d.ts +3 -3
  366. package/dist/view/layer/store-retained-immediate.js +3 -8
  367. package/dist/view/layer/store-retained-invalidation.d.ts +2 -2
  368. package/dist/view/layer/store-retained.d.ts +2 -2
  369. package/dist/view/layer/store-retained.js +1 -1
  370. package/dist/view/renderers/batch-manager.js +8 -7
  371. package/dist/view/renderers/drawer.js +21 -15
  372. package/dist/view/renderers/image.js +13 -39
  373. package/dist/view/renderers/line/line-types.d.ts +3 -3
  374. package/dist/view/renderers/line/sdf-line.js +3 -1
  375. package/dist/view/renderers/point/billboard-depth.js +1 -1
  376. package/dist/view/renderers/point/point-instance.js +1 -1
  377. package/dist/view/renderers/point/point-shape.js +2 -2
  378. package/dist/view/renderers/point/point-style.js +48 -4
  379. package/dist/view/renderers/polygon/batch.js +1 -2
  380. package/dist/view/renderers/polygon/fill.js +3 -1
  381. package/dist/view/renderers/polygon/sdf-polygon.js +2 -3
  382. package/dist/view/renderers/polygon/triangulator.d.ts +1 -1
  383. package/dist/view/renderers/stroke.js +3 -1
  384. package/dist/view/shaders/helpers.d.ts +2 -42
  385. package/dist/view/shaders/helpers.js +0 -6
  386. package/dist/view/shaders/projection.d.ts +15 -7
  387. package/dist/view/shaders/projection.js +23 -6
  388. package/dist/view/shaders/quad.d.ts +16 -12
  389. package/dist/view/shaders/quad.js +34 -13
  390. package/dist/view/style-rule.d.ts +5 -42
  391. package/dist/view/style-rule.js +20 -44
  392. package/dist/view/terrain/binding.d.ts +1 -0
  393. package/dist/view/terrain/binding.js +29 -0
  394. package/dist/view/terrain/context.d.ts +3 -4
  395. package/dist/view/terrain/context.js +4 -5
  396. package/dist/view/terrain/drape/geometry.js +1 -1
  397. package/dist/view/terrain/drape/pass.d.ts +1 -1
  398. package/dist/view/terrain/drape/pass.js +8 -7
  399. package/dist/view/terrain/polygon.d.ts +9 -5
  400. package/dist/view/terrain/polygon.js +16 -2
  401. package/dist/view/terrain/state.d.ts +1 -1
  402. package/dist/view/terrain/state.js +1 -1
  403. package/dist/view/terrain/tessellation.d.ts +2 -2
  404. package/dist/view/terrain/tessellation.js +1 -1
  405. package/dist/view/ui/auxiliary-handles.d.ts +6 -29
  406. package/dist/view/ui/bounds.js +8 -12
  407. package/dist/view/ui/handle-test.js +2 -2
  408. package/dist/view/ui/handle-thinning.js +17 -17
  409. package/dist/view/ui/handles.js +21 -13
  410. package/dist/view/ui/helper.d.ts +1 -1
  411. package/dist/view/ui/helper.js +1 -1
  412. package/dist/view/ui/index.d.ts +1 -1
  413. package/dist/view/ui/selection-scope.js +4 -2
  414. package/dist/view/ui/selection-ui/bounding-box.js +6 -6
  415. package/dist/view/ui/selection-ui/extension-registry.d.ts +31 -20
  416. package/dist/view/ui/selection-ui/extension-registry.js +70 -7
  417. package/dist/view/ui/selection-ui/index.d.ts +2 -2
  418. package/dist/view/ui/selection-ui/index.js +1 -1
  419. package/dist/view/ui/selection-ui/renderer.js +15 -38
  420. package/dist/view/ui/selection-ui/types.d.ts +17 -2
  421. package/dist/view/ui/selection-ui-drawer.d.ts +8 -0
  422. package/dist/view/ui/selection-ui-drawer.js +63 -2
  423. package/dist/view/ui/tentative.js +1 -1
  424. package/dist/webgl/index.d.ts +65 -0
  425. package/dist/webgl/index.js +62 -0
  426. package/package.json +20 -9
  427. package/dist/api/api.d.ts +0 -1259
  428. package/dist/api/api.js +0 -86
  429. package/dist/api/context.d.ts +0 -173
  430. package/dist/api/display-api.js +0 -23
  431. package/dist/api/event-api.d.ts +0 -13
  432. package/dist/api/event-api.js +0 -17
  433. package/dist/api/extension-api.d.ts +0 -46
  434. package/dist/api/extension-api.js +0 -85
  435. package/dist/api/feature-api.d.ts +0 -11
  436. package/dist/api/feature-api.js +0 -101
  437. package/dist/api/geometry/apply.d.ts +0 -51
  438. package/dist/api/geometry/boolean.d.ts +0 -28
  439. package/dist/api/geometry/boolean.js +0 -65
  440. package/dist/api/geometry/types.d.ts +0 -31
  441. package/dist/api/geometry-operations.d.ts +0 -162
  442. package/dist/api/geometry-operations.js +0 -94
  443. package/dist/api/group-api.d.ts +0 -10
  444. package/dist/api/group-api.js +0 -78
  445. package/dist/api/import-export/constants.d.ts +0 -29
  446. package/dist/api/import-export/constants.js +0 -40
  447. package/dist/api/import-export/file-name.d.ts +0 -10
  448. package/dist/api/import-export/file-name.js +0 -20
  449. package/dist/api/import-export/geojson-export.d.ts +0 -19
  450. package/dist/api/import-export/image-import.d.ts +0 -12
  451. package/dist/api/import-export/image-import.js +0 -53
  452. package/dist/api/import-export/index.d.ts +0 -9
  453. package/dist/api/import-export/index.js +0 -107
  454. package/dist/api/import-export/native-format.d.ts +0 -15
  455. package/dist/api/import-export/style-validation.d.ts +0 -27
  456. package/dist/api/import-export/style-validation.js +0 -49
  457. package/dist/api/import-export/types.d.ts +0 -26
  458. package/dist/api/index.d.ts +0 -15
  459. package/dist/api/index.js +0 -3
  460. package/dist/api/input-api.d.ts +0 -158
  461. package/dist/api/input-api.js +0 -144
  462. package/dist/api/instance-api.d.ts +0 -38
  463. package/dist/api/instance-api.js +0 -136
  464. package/dist/api/layer-api.d.ts +0 -12
  465. package/dist/api/layer-api.js +0 -62
  466. package/dist/api/selection-api.d.ts +0 -7
  467. package/dist/api/selection-api.js +0 -78
  468. package/dist/api/snapping-api.d.ts +0 -125
  469. package/dist/api/snapping-api.js +0 -50
  470. package/dist/api/topology-api.d.ts +0 -30
  471. package/dist/api/topology-api.js +0 -16
  472. package/dist/api/tracing-api.d.ts +0 -31
  473. package/dist/api/tracing-api.js +0 -16
  474. package/dist/dispatcher/hit-test/index.d.ts +0 -14
  475. package/dist/dispatcher/hit-test/index.js +0 -9
  476. package/dist/dispatcher/index.d.ts +0 -15
  477. package/dist/dispatcher/index.js +0 -3
  478. package/dist/display/columnar/index.d.ts +0 -12
  479. package/dist/display/columnar/index.js +0 -13
  480. package/dist/display/columnar/prepare.d.ts +0 -42
  481. package/dist/display/columnar/prepare.js +0 -116
  482. package/dist/display/index.d.ts +0 -13
  483. package/dist/display/types.js +0 -43
  484. package/dist/maplibre-gl-draw.d.ts +0 -47
  485. package/dist/modes/cursor.js +0 -72
  486. package/dist/modes/index.d.ts +0 -7
  487. package/dist/operations/index.d.ts +0 -9
  488. package/dist/operations/index.js +0 -3
  489. package/dist/plugins/index.d.ts +0 -10
  490. package/dist/plugins/mutation-hooks.d.ts +0 -28
  491. package/dist/plugins/mutation-hooks.js +0 -84
  492. package/dist/plugins/plugin-context.js +0 -367
  493. package/dist/plugins/plugin-manager.d.ts +0 -103
  494. package/dist/plugins/plugin-manager.js +0 -316
  495. package/dist/plugins/plugin.d.ts +0 -529
  496. package/dist/shared/config/index.d.ts +0 -17
  497. package/dist/shared/config/index.js +0 -8
  498. package/dist/shared/utils/index.d.ts +0 -15
  499. package/dist/shared/utils/index.js +0 -24
  500. package/dist/snapping/index.d.ts +0 -14
  501. package/dist/snapping/index.js +0 -4
  502. package/dist/store/change-merger.js +0 -102
  503. package/dist/store/event-bridge.js +0 -161
  504. package/dist/store/index.d.ts +0 -12
  505. package/dist/store/index.js +0 -4
  506. package/dist/view/index.d.ts +0 -47
  507. package/dist/view/index.js +0 -20
  508. /package/dist/api/{geometry/types.js → datasets.js} +0 -0
  509. /package/dist/api/{import-export/types.js → document.js} +0 -0
  510. /package/dist/{display/columnar/types.js → api/drawing.js} +0 -0
  511. /package/dist/{display/index.js → api/events.js} +0 -0
  512. /package/dist/{modes/index.js → api/extension/context.js} +0 -0
  513. /package/dist/{plugins/index.js → api/extension/feature-type.js} +0 -0
  514. /package/dist/{plugins/plugin.js → api/extension/mode.js} +0 -0
  515. /package/dist/api/{display-api.d.ts → impl/adapters.d.ts} +0 -0
  516. /package/dist/{display/columnar/source.d.ts → api/impl/contexts.d.ts} +0 -0
  517. /package/dist/{display/columnar/table.d.ts → api/impl/create-draw.d.ts} +0 -0
  518. /package/dist/{display/interaction.d.ts → api/impl/datasets.d.ts} +0 -0
  519. /package/dist/{display/manager.d.ts → api/impl/destroy-guard.d.ts} +0 -0
  520. /package/dist/{display/packed-rtree.d.ts → api/impl/document.d.ts} +0 -0
  521. /package/dist/{display/partition.d.ts → api/impl/drawing.d.ts} +0 -0
  522. /package/dist/{display/provider.d.ts → api/impl/engine.d.ts} +0 -0
  523. /package/dist/{display/source.d.ts → api/impl/events.d.ts} +0 -0
  524. /package/dist/{display/spatial.d.ts → api/impl/extension-host.d.ts} +0 -0
  525. /package/dist/{display/style.d.ts → api/impl/extensions.d.ts} +0 -0
  526. /package/dist/{display/triangulation.d.ts → api/impl/features.d.ts} +0 -0
  527. /package/dist/{modes/cursor.d.ts → api/impl/geometry/types.d.ts} +0 -0
  528. /package/dist/{plugins/plugin-context.d.ts → api/impl/hidden.d.ts} +0 -0
  529. /package/dist/api/{import-export → impl/import-export}/embedded-file.d.ts +0 -0
  530. /package/dist/api/{import-export → impl/import-export}/own-property.d.ts +0 -0
  531. /package/dist/api/{import-export → impl/import-export}/own-property.js +0 -0
  532. /package/dist/{store/change-merger.d.ts → api/impl/input.d.ts} +0 -0
  533. /package/dist/{store/event-bridge.d.ts → api/impl/layers.d.ts} +0 -0
  534. /package/dist/{display → dataset}/chunk-set.d.ts +0 -0
  535. /package/dist/{display → dataset}/chunk-set.js +0 -0
  536. /package/dist/{display → dataset}/dataset.d.ts +0 -0
  537. /package/dist/{display → dataset}/manager.js +0 -0
  538. /package/dist/{display → dataset}/provider.js +0 -0
  539. /package/dist/{display → dataset}/selection.d.ts +0 -0
  540. /package/dist/{display → dataset}/selection.js +0 -0
@@ -0,0 +1,361 @@
1
+ // SPDX-FileCopyrightText: 2026 SAKAIDA Atsushi
2
+ // SPDX-License-Identifier: AGPL-3.0-only
3
+ import { DrawError } from '../errors.js';
4
+ import { adaptCompanionProvider, adaptHandleProvider, adaptSnapProvider, installFeatureType, } from './adapters.js';
5
+ import { createExtensionContext, createModeContext, createScreenContext, createSubscriptions, createTerrainAnchors, toHit, } from './contexts.js';
6
+ import { createExtensionsCollections, createRegistry, OVERRIDABLE_TYPES } from './extensions.js';
7
+ import { preparePatch } from './features.js';
8
+ import { bridgeMode, createInputRoute, deliverPointerLeave, toPointerEvent } from './input.js';
9
+ import { createOverlayStack, terrainAnchorsOf } from './render-context.js';
10
+ import { validateExtension } from './validate-extension.js';
11
+ /** The feature types of the engine, which a custom type cannot take the name of */
12
+ const BUILT_IN_TYPES = new Set([
13
+ 'Point',
14
+ 'LineString',
15
+ 'Polygon',
16
+ 'MultiPoint',
17
+ 'MultiLineString',
18
+ 'MultiPolygon',
19
+ 'Image',
20
+ 'Circle',
21
+ 'Freehand',
22
+ ]);
23
+ /**
24
+ * Builds the host of the extensions of an engine
25
+ *
26
+ * @internal
27
+ */
28
+ export function createExtensionHost(deps) {
29
+ const { map, context, customLayer, modeManager, featureCompanions } = deps;
30
+ const { store } = context;
31
+ const terrain = customLayer.getTerrainContext();
32
+ let destroyed = false;
33
+ let attached = null;
34
+ const getDraw = () => {
35
+ if (!attached) {
36
+ throw new DrawError('invalid-state', 'The draw instance is not attached to its extensions yet');
37
+ }
38
+ return attached;
39
+ };
40
+ const screen = createScreenContext({
41
+ map,
42
+ pixelRatio: context.pixelRatioSource,
43
+ selectionExtensions: context.selectionScope.extensions,
44
+ });
45
+ const adapterDeps = {
46
+ map,
47
+ store,
48
+ screen,
49
+ clickTolerancePx: context.options.clickTolerance,
50
+ hitTestService: context.hitTestService,
51
+ boxSelectionRegistry: context.boxSelectionRegistry,
52
+ selectionExtensions: context.selectionScope.extensions,
53
+ auxiliaryHandles: context.selectionScope.auxiliaryHandles,
54
+ featureCompanions,
55
+ snapTargets: context.snapTargets,
56
+ customLayer,
57
+ spatialIndex: context.spatialIndex,
58
+ anchors: (state) => terrainAnchorsOf(state, createTerrainAnchors),
59
+ registerSnapProvider: (provider) => context.snapService.register(provider),
60
+ applyPatch(featureId, patch, final) {
61
+ const feature = store.getFeature(featureId);
62
+ if (!feature || store.isReadOnly())
63
+ return;
64
+ store.updateFeature(featureId, preparePatch(feature, patch), { isIntermediate: !final });
65
+ },
66
+ };
67
+ const overlays = createOverlayStack(customLayer, adapterDeps);
68
+ /** An installer that installs nothing once the instance is destroyed */
69
+ const guarded = (installer) => ({
70
+ ...installer,
71
+ install: (name, value) => (destroyed ? () => { } : installer.install(name, value)),
72
+ });
73
+ const registries = {
74
+ plugins: createRegistry(guarded({
75
+ kind: 'plugin',
76
+ validate: (_, plugin) => validateExtension('plugin', plugin),
77
+ install: (_, plugin) => installPlugin(plugin),
78
+ })),
79
+ modes: createRegistry(guarded({
80
+ kind: 'mode',
81
+ validate: (_, factory) => validateExtension('mode', factory),
82
+ isTakenElsewhere: (name) => modeManager.hasMode(name),
83
+ install: (name, factory) => modeManager.registerMode(name, () => {
84
+ const handle = createModeContext(modeServices, screen);
85
+ try {
86
+ return bridgeMode(name, factory(handle.context), handle.dispose, handle.entering);
87
+ }
88
+ catch (error) {
89
+ handle.dispose();
90
+ throw error;
91
+ }
92
+ }),
93
+ })),
94
+ featureTypes: createRegistry(guarded({
95
+ kind: 'feature type',
96
+ validate: (_, definition) => validateExtension('feature type', definition),
97
+ isTakenElsewhere: (name) => BUILT_IN_TYPES.has(name),
98
+ install: (name, definition) => installFeatureType(definition, adapterDeps, OVERRIDABLE_TYPES.has(name)),
99
+ })),
100
+ overlays: createRegistry(guarded({
101
+ kind: 'overlay',
102
+ validate: (_, overlay) => validateExtension('overlay', overlay),
103
+ install: (_, overlay) => overlays.add(overlay),
104
+ })),
105
+ snapProviders: createRegistry(guarded({
106
+ kind: 'snap provider',
107
+ validate: (_, provider) => validateExtension('snap provider', provider),
108
+ install: (_, provider) => context.snapService.register(adaptSnapProvider(provider, screen)),
109
+ })),
110
+ handleProviders: createRegistry(guarded({
111
+ kind: 'handle provider',
112
+ validate: (_, provider) => validateExtension('handle provider', provider),
113
+ isTakenElsewhere: (name) => context.selectionScope.auxiliaryHandles.get(name) !== undefined,
114
+ install: (_, provider) => context.selectionScope.auxiliaryHandles.register(adaptHandleProvider(provider, adapterDeps)),
115
+ })),
116
+ companionProviders: createRegistry(guarded({
117
+ kind: 'companion provider',
118
+ validate: (_, provider) => validateExtension('companion provider', provider),
119
+ isTakenElsewhere: (name) => featureCompanions.get(name) !== undefined,
120
+ install: (_, provider) => featureCompanions.register(adaptCompanionProvider(provider, adapterDeps)),
121
+ })),
122
+ };
123
+ const collections = createExtensionsCollections(registries);
124
+ const services = {
125
+ map,
126
+ store,
127
+ terrain,
128
+ pixelRatio: context.pixelRatioSource,
129
+ autoNameGenerator: context.autoNameGenerator,
130
+ selectionExtensions: context.selectionScope.extensions,
131
+ spatialIndex: context.spatialIndex,
132
+ modeManager,
133
+ getDraw,
134
+ collections,
135
+ };
136
+ const unproject = (point) => map.unproject([point.x, point.y]);
137
+ const modeServices = {
138
+ ...services,
139
+ hitTestTopmost(point, tolerancePx) {
140
+ const tester = tolerancePx === undefined || tolerancePx === context.options.clickTolerance
141
+ ? deps.hitTestTopmost
142
+ : deps.hitTestTopmostWith(tolerancePx);
143
+ return tester(point);
144
+ },
145
+ distanceToFeaturePx(feature, point) {
146
+ const hit = context.hitTestService.hitTestAll(point, unproject, [feature])[0];
147
+ if (!hit)
148
+ return 0;
149
+ const onePixel = Math.abs(unproject({ x: point.x + 1, y: point.y }).lng - unproject(point).lng);
150
+ return onePixel > 0 ? hit.distance / onePixel : 0;
151
+ },
152
+ snapPoint(point) {
153
+ const lngLat = unproject(point);
154
+ const handler = modeManager.getHandler();
155
+ const prefer = handler?.getSnapPreference?.() ?? undefined;
156
+ return context.snapService.resolve({ lng: lngLat.lng, lat: lngLat.lat }, point, {
157
+ zoom: map.getZoom(),
158
+ modifiers: { shift: false, ctrl: false, alt: false, meta: false },
159
+ ...(prefer && { preferFeature: prefer }),
160
+ });
161
+ },
162
+ listTraceRows(bbox) {
163
+ return deps.listTraceRows({ minX: bbox[0], minY: bbox[1], maxX: bbox[2], maxY: bbox[3] });
164
+ },
165
+ getWritableLayerId: context.getWritableLayerId,
166
+ generateId: context.generateFeatureId,
167
+ scaleWithZoom: context.options.scaleWithZoom,
168
+ selectionStyle: context.selectionStyle,
169
+ boxSelectionStyle: context.renderingConfig.boxSelectionStyle,
170
+ notifyDrawCommit: (feature) => announceDrawCommit(feature),
171
+ };
172
+ /**
173
+ * Installs a plugin: calls its onAdd with a context that records what the plugin adds, and
174
+ * returns the removal, which calls its onRemove and removes what it added
175
+ */
176
+ function installPlugin(plugin) {
177
+ const subscriptions = createSubscriptions();
178
+ const added = [];
179
+ const disposeAll = () => {
180
+ subscriptions.endAll();
181
+ for (let i = added.length - 1; i >= 0; i--)
182
+ added[i]();
183
+ added.length = 0;
184
+ };
185
+ const base = createExtensionContext(services, screen, subscriptions);
186
+ const pluginContext = {
187
+ get draw() {
188
+ return getDraw();
189
+ },
190
+ store: base.store,
191
+ on: base.on,
192
+ off: base.off,
193
+ once: base.once,
194
+ terrain: base.terrain,
195
+ names: base.names,
196
+ screen: base.screen,
197
+ invalidate: base.invalidate,
198
+ get drawing() {
199
+ return base.drawing;
200
+ },
201
+ extensions: createExtensionsCollections(registries, (remove) => added.push(remove)),
202
+ };
203
+ try {
204
+ plugin.onAdd(pluginContext);
205
+ }
206
+ catch (error) {
207
+ disposeAll();
208
+ throw error;
209
+ }
210
+ return () => {
211
+ try {
212
+ plugin.onRemove?.();
213
+ }
214
+ catch (error) {
215
+ console.error(`Error in plugin "${plugin.name}" onRemove:`, error);
216
+ }
217
+ finally {
218
+ disposeAll();
219
+ }
220
+ };
221
+ }
222
+ /** Calls a hook of every plugin in turn; one that throws is reported and skipped */
223
+ function eachPlugin(hook, call) {
224
+ for (const plugin of registries.plugins.values()) {
225
+ try {
226
+ if (call(plugin) === true)
227
+ return true;
228
+ }
229
+ catch (error) {
230
+ console.error(`Error in plugin "${plugin.name}" ${hook}:`, error);
231
+ }
232
+ }
233
+ return false;
234
+ }
235
+ /** Tells every plugin that a drawing mode created a feature */
236
+ function announceDrawCommit(feature) {
237
+ eachPlugin('onDrawCommit', (plugin) => {
238
+ plugin.interaction?.onDrawCommit?.(feature);
239
+ return false;
240
+ });
241
+ }
242
+ const featureOf = (id) => store.getFeature(id);
243
+ const click = (hook) => (featureId, event) => {
244
+ const feature = featureOf(featureId);
245
+ if (!feature || !event)
246
+ return false;
247
+ return eachPlugin(hook, (plugin) => {
248
+ const handler = plugin.interaction?.[hook];
249
+ return handler?.call(plugin.interaction, feature, toPointerEvent(event)) === true;
250
+ });
251
+ };
252
+ const interactions = {
253
+ filterSelectionCandidates(candidateIds) {
254
+ let filtered = candidateIds;
255
+ eachPlugin('filterSelection', (plugin) => {
256
+ const filter = plugin.interaction?.filterSelection;
257
+ if (filter)
258
+ filtered = filter.call(plugin.interaction, filtered);
259
+ return false;
260
+ });
261
+ return filtered;
262
+ },
263
+ handleFeatureClick: click('onFeatureClick'),
264
+ handleFeatureDoubleClick: click('onFeatureDoubleClick'),
265
+ isPluginInteracting: () => eachPlugin('isBusy', (plugin) => plugin.interaction?.isBusy?.() === true),
266
+ finishPluginInteraction() {
267
+ eachPlugin('finish', (plugin) => {
268
+ plugin.interaction?.finish?.();
269
+ return false;
270
+ });
271
+ },
272
+ cancelPluginInteraction() {
273
+ eachPlugin('cancel', (plugin) => {
274
+ plugin.interaction?.cancel?.();
275
+ return false;
276
+ });
277
+ },
278
+ getPluginInteractionContainer() {
279
+ let container = null;
280
+ eachPlugin('container', (plugin) => {
281
+ if (plugin.interaction?.isBusy?.() !== true)
282
+ return false;
283
+ container = plugin.interaction.container?.() ?? null;
284
+ return container !== null;
285
+ });
286
+ return container;
287
+ },
288
+ notifyFeatureCreated(featureId) {
289
+ const feature = featureOf(featureId);
290
+ if (feature)
291
+ announceDrawCommit(feature);
292
+ },
293
+ };
294
+ const input = createInputRoute(() => registries.plugins.values());
295
+ const onPointerLeave = () => deliverPointerLeave(registries.plugins.values(), modeManager.getHandler());
296
+ let listening = false;
297
+ const watches = [];
298
+ /**
299
+ * The image mode asks the application for a file (`image.requested`), and the application
300
+ * places the image by loading the file. The image that load places is the commit of the
301
+ * image mode, which the plugins hear of as the commits of the other drawing modes
302
+ */
303
+ function watchImageCommits(draw) {
304
+ let requested = false;
305
+ watches.push(draw.on('image.requested', () => {
306
+ requested = true;
307
+ }), draw.on('document.loaded', ({ result }) => {
308
+ if (!requested || result.format !== 'image')
309
+ return;
310
+ requested = false;
311
+ for (const id of result.featureIds) {
312
+ const feature = featureOf(id);
313
+ if (feature)
314
+ announceDrawCommit(feature);
315
+ }
316
+ }));
317
+ }
318
+ return {
319
+ collections,
320
+ input,
321
+ interactions,
322
+ hitAt: (point) => toHit(modeServices.hitTestTopmost(point), (feature) => modeServices.distanceToFeaturePx(feature, point)),
323
+ attach(draw, documentStore) {
324
+ attached = draw;
325
+ watchImageCommits(draw);
326
+ // A Store that replaces its whole document says so with `reset`: the mode drops what it
327
+ // was drawing, as it does for an Escape
328
+ if (documentStore) {
329
+ watches.push(documentStore.subscribe((changes) => {
330
+ if (changes.reset === true && !destroyed)
331
+ modeManager.notifyStateReset();
332
+ }));
333
+ }
334
+ },
335
+ start() {
336
+ if (listening || destroyed)
337
+ return;
338
+ listening = true;
339
+ map.getCanvasContainer().addEventListener('mouseleave', onPointerLeave);
340
+ },
341
+ destroy() {
342
+ if (destroyed)
343
+ return;
344
+ for (const stop of watches.splice(0))
345
+ stop();
346
+ if (listening) {
347
+ listening = false;
348
+ map.getCanvasContainer().removeEventListener('mouseleave', onPointerLeave);
349
+ }
350
+ // The plugins go first, with what they added, then the rest in the reverse order
351
+ registries.plugins.clear();
352
+ registries.companionProviders.clear();
353
+ registries.handleProviders.clear();
354
+ registries.snapProviders.clear();
355
+ registries.overlays.clear();
356
+ registries.featureTypes.clear();
357
+ registries.modes.clear();
358
+ destroyed = true;
359
+ },
360
+ };
361
+ }
@@ -0,0 +1,229 @@
1
+ // SPDX-FileCopyrightText: 2026 SAKAIDA Atsushi
2
+ // SPDX-License-Identifier: AGPL-3.0-only
3
+ import { DrawError } from '../errors.js';
4
+ import { invalidInput, notFound } from './shared.js';
5
+ /**
6
+ * Creates the registry of one kind of extension
7
+ *
8
+ * @internal
9
+ */
10
+ export function createRegistry(installer) {
11
+ const entries = new Map();
12
+ const requireName = (name) => {
13
+ if (typeof name !== 'string' || name === '') {
14
+ throw invalidInput(`The name of the ${installer.kind} must be a non-empty string`);
15
+ }
16
+ return name;
17
+ };
18
+ const uninstall = (name, entry) => {
19
+ if (entries.get(name) !== entry)
20
+ return;
21
+ entries.delete(name);
22
+ entry.uninstall();
23
+ };
24
+ return {
25
+ get: (name) => entries.get(name)?.value,
26
+ names: () => [...entries.keys()],
27
+ values: () => [...entries.values()].map((entry) => entry.value),
28
+ count: () => entries.size,
29
+ has: (name) => entries.has(name),
30
+ holds: (name, value) => entries.get(name)?.value === value,
31
+ add(list, options) {
32
+ if (!Array.isArray(list))
33
+ throw invalidInput(`The ${installer.kind}s must be an array`);
34
+ const seen = new Set();
35
+ for (const [rawName, value] of list) {
36
+ const name = requireName(rawName);
37
+ installer.validate(name, value);
38
+ const takenElsewhere = !options?.overriding && installer.isTakenElsewhere?.(name);
39
+ if (seen.has(name) || entries.has(name) || takenElsewhere) {
40
+ throw new DrawError('already-exists', `There is already a ${installer.kind} named ${JSON.stringify(name)}`, { name });
41
+ }
42
+ seen.add(name);
43
+ }
44
+ const added = [];
45
+ try {
46
+ for (const [name, value] of list) {
47
+ const entry = { value, uninstall: installer.install(name, value) };
48
+ entries.set(name, entry);
49
+ added.push([name, entry]);
50
+ }
51
+ }
52
+ catch (error) {
53
+ for (let i = added.length - 1; i >= 0; i--)
54
+ uninstall(added[i][0], added[i][1]);
55
+ throw error;
56
+ }
57
+ let removed = false;
58
+ return () => {
59
+ if (removed)
60
+ return;
61
+ removed = true;
62
+ for (let i = added.length - 1; i >= 0; i--)
63
+ uninstall(added[i][0], added[i][1]);
64
+ };
65
+ },
66
+ remove(names) {
67
+ if (!Array.isArray(names))
68
+ throw invalidInput('The names must be an array');
69
+ for (const name of names) {
70
+ if (!entries.has(name))
71
+ throw notFound(installer.kind, name);
72
+ }
73
+ for (const name of new Set(names)) {
74
+ const entry = entries.get(name);
75
+ if (entry)
76
+ uninstall(name, entry);
77
+ }
78
+ return true;
79
+ },
80
+ clear() {
81
+ for (const [name, entry] of [...entries].reverse())
82
+ uninstall(name, entry);
83
+ },
84
+ };
85
+ }
86
+ /** The name of an extension that carries one, as a checked string */
87
+ function nameOf(value, kind) {
88
+ const name = value?.name;
89
+ if (typeof name !== 'string' || name === '') {
90
+ throw invalidInput(`The ${kind} must have a non-empty name`);
91
+ }
92
+ return name;
93
+ }
94
+ /** The collection of the extensions that are named by a member */
95
+ function namedCollection(registry, kind, record) {
96
+ const addAll = (values) => {
97
+ if (!Array.isArray(values))
98
+ throw invalidInput(`The ${kind}s must be an array`);
99
+ const remove = registry.add(values.map((value) => [nameOf(value, kind), value]));
100
+ record?.(remove);
101
+ return remove;
102
+ };
103
+ return {
104
+ get: (name) => registry.get(name),
105
+ list: () => registry.names(),
106
+ count: () => registry.count(),
107
+ has: (name) => registry.has(name),
108
+ add: (value) => addAll([value]),
109
+ addMany: addAll,
110
+ remove: (name) => registry.remove([name]),
111
+ removeMany: (names) => registry.remove(names),
112
+ };
113
+ }
114
+ /**
115
+ * The collections of `draw.extensions` over the registries
116
+ *
117
+ * @param record - Receives the remover of every addition; a plugin context passes it to
118
+ * remove what the plugin added when the plugin is removed
119
+ * @internal
120
+ */
121
+ export function createExtensionsCollections(registries, record) {
122
+ const plugins = namedCollection(registries.plugins, 'plugin', record);
123
+ const pluginsCollection = {
124
+ get: (name) => registries.plugins.get(name),
125
+ list: () => registries.plugins.values(),
126
+ count: plugins.count,
127
+ has: plugins.has,
128
+ add: plugins.add,
129
+ addMany: plugins.addMany,
130
+ remove: plugins.remove,
131
+ removeMany: plugins.removeMany,
132
+ getApi: (name) => registries.plugins.get(name)?.api,
133
+ };
134
+ const modes = {
135
+ get: (name) => registries.modes.get(name),
136
+ list: () => registries.modes.names(),
137
+ count: () => registries.modes.count(),
138
+ has: (name) => registries.modes.has(name),
139
+ add: (name, factory) => modes.addMany([{ name, factory }]),
140
+ addMany(entries) {
141
+ if (!Array.isArray(entries))
142
+ throw invalidInput('The modes must be an array');
143
+ const remove = registries.modes.add(entries.map((entry) => {
144
+ if (typeof entry !== 'object' || entry === null) {
145
+ throw invalidInput('A mode must be given as { name, factory }');
146
+ }
147
+ return [entry.name, entry.factory];
148
+ }));
149
+ record?.(remove);
150
+ return remove;
151
+ },
152
+ remove: (name) => registries.modes.remove([name]),
153
+ removeMany: (names) => registries.modes.remove(names),
154
+ };
155
+ const byType = namedCollectionByType(registries.featureTypes, record);
156
+ const overlays = namedCollection(registries.overlays, 'overlay', record);
157
+ const snapProviders = namedCollection(registries.snapProviders, 'snap provider', record);
158
+ const handleProviders = namedCollection(registries.handleProviders, 'handle provider', record);
159
+ const companionProviders = namedCollection(registries.companionProviders, 'companion provider', record);
160
+ return {
161
+ plugins: pluginsCollection,
162
+ modes,
163
+ featureTypes: byType,
164
+ overlays,
165
+ snapProviders,
166
+ handleProviders,
167
+ companionProviders,
168
+ };
169
+ }
170
+ /**
171
+ * The built-in feature types a definition can override, with the kind of geometry their
172
+ * features hold
173
+ *
174
+ * @internal
175
+ */
176
+ export const OVERRIDABLE_TYPES = new Map([
177
+ ['Point', 'Point'],
178
+ ['LineString', 'LineString'],
179
+ ['Polygon', 'Polygon'],
180
+ ['Circle', 'Point'],
181
+ ['Freehand', 'LineString'],
182
+ ['Image', 'Point'],
183
+ ]);
184
+ /** The type of a feature type definition, as a checked string */
185
+ function typeOf(definition) {
186
+ const type = definition?.type;
187
+ if (typeof type !== 'string' || type === '') {
188
+ throw invalidInput('A feature type must have a non-empty type');
189
+ }
190
+ return type;
191
+ }
192
+ /** The feature types, named by their `type` */
193
+ function namedCollectionByType(registry, record) {
194
+ const addAll = (definitions) => {
195
+ if (!Array.isArray(definitions))
196
+ throw invalidInput('The feature types must be an array');
197
+ const remove = registry.add(definitions.map((definition) => [typeOf(definition), definition]));
198
+ record?.(remove);
199
+ return remove;
200
+ };
201
+ return {
202
+ override(definition) {
203
+ const type = typeOf(definition);
204
+ const geometry = OVERRIDABLE_TYPES.get(type);
205
+ if (geometry === undefined) {
206
+ throw invalidInput(`${JSON.stringify(type)} is not a built-in type that can be overridden`, {
207
+ type,
208
+ });
209
+ }
210
+ if (definition.geometry !== geometry) {
211
+ throw invalidInput(`A definition that overrides ${type} must have the geometry ${geometry}`, {
212
+ type,
213
+ geometry: definition.geometry,
214
+ });
215
+ }
216
+ const remove = registry.add([[type, definition]], { overriding: true });
217
+ record?.(remove);
218
+ return remove;
219
+ },
220
+ get: (name) => registry.get(name),
221
+ list: () => registry.names(),
222
+ count: () => registry.count(),
223
+ has: (name) => registry.has(name),
224
+ add: (definition) => addAll([definition]),
225
+ addMany: addAll,
226
+ remove: (name) => registry.remove([name]),
227
+ removeMany: (names) => registry.remove(names),
228
+ };
229
+ }