@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,445 @@
1
+ // SPDX-FileCopyrightText: 2026 SAKAIDA Atsushi
2
+ // SPDX-License-Identifier: AGPL-3.0-only
3
+ /**
4
+ * `draw.features`: the features of the document
5
+ */
6
+ import { differenceAll, intersectionAll, unionAll } from '../../geometry/boolean.js';
7
+ import { getBoundingBox } from '../../shared/utils/feature-bbox.js';
8
+ import { isFeatureLocked } from '../../store/lock.js';
9
+ import { listEveryFeatureInOrder } from '../../store/ordering.js';
10
+ import { getStyleRuleChannel, resolveFeatureStyle } from '../../view/style-rule.js';
11
+ import { DrawError } from '../errors.js';
12
+ import { applyResult } from './geometry/apply.js';
13
+ import { runBuffer } from './geometry/buffer.js';
14
+ import { runSplit } from './geometry/split.js';
15
+ import { isAreaFeature, isBufferableFeature, isSplitLineFeature, toAreaCoordinates, toResultGeometry, } from './geometry/targets.js';
16
+ import { describeGeometryProblem } from './import-export/geometry-validation.js';
17
+ import { setOwnProperty } from './import-export/own-property.js';
18
+ import { describeStyleProblem } from './import-export/style-validation.js';
19
+ import { toAppliedDefaults } from './options.js';
20
+ import { moveFeatures, resolveMoveTarget } from './placement.js';
21
+ import { featureLocked, filterEntries, invalidInput, isRecord, isTaken, matches, notFound, onlyKeys, onlyLockOrVisibility, optionalBoolean, requireId, requireIds, requireRecord, } from './shared.js';
22
+ const INPUT_KEYS = [
23
+ 'type',
24
+ 'geometry',
25
+ 'id',
26
+ 'layerId',
27
+ 'groupId',
28
+ 'properties',
29
+ 'style',
30
+ 'visible',
31
+ 'locked',
32
+ ];
33
+ const PATCH_KEYS = ['geometry', 'properties', 'style', 'visible', 'locked'];
34
+ const FILTER_KEYS = ['layerId', 'groupId', 'type', 'visible', 'shown', 'locked', 'bbox'];
35
+ /**
36
+ * Creates `draw.features`
37
+ *
38
+ * @internal
39
+ */
40
+ export function createFeatures(deps) {
41
+ const { store } = deps;
42
+ const geometryDeps = {
43
+ store,
44
+ generateFeatureId: deps.generateId,
45
+ };
46
+ const require = (id) => {
47
+ const feature = typeof id === 'string' ? store.getFeature(id) : undefined;
48
+ if (!feature)
49
+ throw notFound('feature', id);
50
+ return feature;
51
+ };
52
+ const requireAll = (ids) => requireIds(ids).map(require);
53
+ /** The features in stacking order, from the back */
54
+ const inStackingOrder = (features) => {
55
+ const position = new Map(listEveryFeatureInOrder(store).map((f, index) => [f.id, index]));
56
+ return [...features].sort((a, b) => (position.get(a.id) ?? 0) - (position.get(b.id) ?? 0));
57
+ };
58
+ /**
59
+ * The checks of a filter: the entries compared as they are, and the IDs within the extent
60
+ * when the filter has one
61
+ */
62
+ const filterOf = (filter) => {
63
+ const all = filterEntries(filter, FILTER_KEYS);
64
+ const shown = all.find(([key]) => key === 'shown')?.[1];
65
+ if (shown !== undefined && typeof shown !== 'boolean') {
66
+ throw invalidInput('shown must be a boolean');
67
+ }
68
+ const entries = all.filter(([key]) => key !== 'shown');
69
+ const bbox = entries.find(([key]) => key === 'bbox')?.[1];
70
+ if (bbox === undefined)
71
+ return { entries, inside: null, shown };
72
+ if (!Array.isArray(bbox) ||
73
+ bbox.length !== 4 ||
74
+ bbox.some((value) => typeof value !== 'number' || !Number.isFinite(value))) {
75
+ throw invalidInput('bbox must be [west, south, east, north] in degrees');
76
+ }
77
+ const [minX, minY, maxX, maxY] = bbox;
78
+ const bounds = { minX, minY, maxX, maxY };
79
+ const inside = new Set(deps.spatialIndex
80
+ ? deps.spatialIndex.findInBounds(bounds)
81
+ : store
82
+ .listFeatures()
83
+ .filter((feature) => {
84
+ const box = getBoundingBox(feature);
85
+ return box.minX <= maxX && box.maxX >= minX && box.minY <= maxY && box.maxY >= minY;
86
+ })
87
+ .map((feature) => feature.id));
88
+ return { entries: entries.filter(([key]) => key !== 'bbox'), inside, shown };
89
+ };
90
+ /** Whether the feature, its group and its layer are all visible in the document */
91
+ const isShown = (feature) => feature.visible &&
92
+ (feature.groupId === undefined || store.getGroup(feature.groupId)?.visible !== false) &&
93
+ store.getLayer(feature.layerId)?.visible !== false;
94
+ const keep = (feature, { entries, inside, shown }) => (inside === null || inside.has(feature.id)) &&
95
+ (shown === undefined || isShown(feature) === shown) &&
96
+ matches(feature, entries);
97
+ const list = (filter) => {
98
+ const checks = filterOf(filter);
99
+ return listEveryFeatureInOrder(store).filter((feature) => keep(feature, checks));
100
+ };
101
+ return {
102
+ get: (id) => store.getFeature(id),
103
+ getMany(ids) {
104
+ if (!Array.isArray(ids))
105
+ throw invalidInput('The IDs must be an array');
106
+ return ids.map((id) => store.getFeature(id));
107
+ },
108
+ list,
109
+ count(filter) {
110
+ const checks = filterOf(filter);
111
+ if (checks.entries.length === 0 && checks.inside === null && checks.shown === undefined) {
112
+ return store.listFeatures().length;
113
+ }
114
+ return store.listFeatures().filter((feature) => keep(feature, checks)).length;
115
+ },
116
+ has: (id) => store.getFeature(id) !== undefined,
117
+ create(input) {
118
+ const feature = prepareFeature(deps, input, new Set());
119
+ if (store.isReadOnly())
120
+ return null;
121
+ store.createFeature(feature);
122
+ return store.getFeature(feature.id) ?? null;
123
+ },
124
+ createMany(inputs) {
125
+ if (!Array.isArray(inputs))
126
+ throw invalidInput('The inputs must be an array');
127
+ const pending = new Set();
128
+ const features = inputs.map((input) => {
129
+ const feature = prepareFeature(deps, input, pending);
130
+ pending.add(feature.id);
131
+ return feature;
132
+ });
133
+ if (store.isReadOnly())
134
+ return null;
135
+ store.transact(() => {
136
+ for (const feature of features)
137
+ store.createFeature(feature);
138
+ });
139
+ return features.map((feature) => store.getFeature(feature.id));
140
+ },
141
+ update(id, patch) {
142
+ const feature = require(id);
143
+ const updates = preparePatch(feature, patch);
144
+ if (store.isReadOnly())
145
+ return null;
146
+ if (featureLocked(store, feature) && !onlyLockOrVisibility(patch))
147
+ return null;
148
+ store.updateFeature(feature.id, updates);
149
+ return store.getFeature(feature.id) ?? null;
150
+ },
151
+ updateMany(patches) {
152
+ if (!Array.isArray(patches))
153
+ throw invalidInput('The patches must be an array');
154
+ const seen = new Set();
155
+ const prepared = patches.map((entry) => {
156
+ requireRecord(entry, 'Each entry');
157
+ const feature = require(entry.id);
158
+ if (seen.has(feature.id))
159
+ throw invalidInput(`The ID ${feature.id} is given twice`);
160
+ seen.add(feature.id);
161
+ return { feature, patch: entry.patch, updates: preparePatch(feature, entry.patch) };
162
+ });
163
+ if (store.isReadOnly())
164
+ return null;
165
+ const refused = prepared.some(({ feature, patch }) => featureLocked(store, feature) && !onlyLockOrVisibility(patch));
166
+ if (refused)
167
+ return null;
168
+ store.transact(() => {
169
+ for (const { feature, updates } of prepared)
170
+ store.updateFeature(feature.id, updates);
171
+ });
172
+ return prepared.map(({ feature }) => store.getFeature(feature.id));
173
+ },
174
+ delete(id) {
175
+ const feature = require(id);
176
+ if (store.isReadOnly() || featureLocked(store, feature))
177
+ return false;
178
+ return store.deleteFeature(feature.id);
179
+ },
180
+ deleteMany(ids) {
181
+ const features = requireAll(ids);
182
+ if (store.isReadOnly())
183
+ return false;
184
+ if (features.some((feature) => featureLocked(store, feature)))
185
+ return false;
186
+ store.transact(() => {
187
+ for (const feature of features) {
188
+ if (store.getFeature(feature.id))
189
+ store.deleteFeature(feature.id);
190
+ }
191
+ });
192
+ return true;
193
+ },
194
+ move(id, to) {
195
+ return moveMany([id], to);
196
+ },
197
+ moveMany,
198
+ isEditable(id) {
199
+ const feature = require(id);
200
+ return !store.isReadOnly() && !isFeatureLocked(feature, store);
201
+ },
202
+ getAppliedStyle(id) {
203
+ const feature = store.getFeature(id);
204
+ if (!feature)
205
+ return undefined;
206
+ return appliedStyle(store, feature, deps.getStyleOptions());
207
+ },
208
+ union(ids) {
209
+ const inputs = requireAreas(ids, 2);
210
+ if (refuseChange(inputs))
211
+ return null;
212
+ return runAreaOperation(inputs, inputs[inputs.length - 1], inputs, unionAll);
213
+ },
214
+ difference(id, subtractIds) {
215
+ const [subject] = requireAreas([id], 1);
216
+ const others = requireAreas(subtractIds, 1);
217
+ if (others.some((other) => other.id === subject.id)) {
218
+ throw invalidInput('An area cannot be subtracted from itself');
219
+ }
220
+ if (refuseChange([subject]))
221
+ return null;
222
+ const inputs = inStackingOrder([subject, ...others]);
223
+ return runAreaOperation(inputs, subject, [subject], (areas) => differenceAll(areas[inputs.indexOf(subject)], areas.filter((_, index) => inputs[index] !== subject)));
224
+ },
225
+ intersection(ids) {
226
+ const inputs = requireAreas(ids, 2);
227
+ if (refuseChange(inputs))
228
+ return null;
229
+ return runAreaOperation(inputs, inputs[inputs.length - 1], inputs, intersectionAll);
230
+ },
231
+ split(id, lineId) {
232
+ const area = require(id);
233
+ const line = require(lineId);
234
+ if (!isAreaFeature(area))
235
+ throw invalidInput(`The feature ${area.id} is not an area`);
236
+ if (!isSplitLineFeature(line))
237
+ throw invalidInput(`The feature ${line.id} is not a line`);
238
+ if (refuseChange([area]))
239
+ return null;
240
+ return runSplit(geometryDeps, area, line, false).map((resultId) => store.getFeature(resultId));
241
+ },
242
+ buffer(ids, options) {
243
+ const inputs = inStackingOrder(requireAll(ids));
244
+ requireRecord(options, 'The options');
245
+ const { distanceMeters, segments } = options;
246
+ if (typeof distanceMeters !== 'number' || !Number.isFinite(distanceMeters)) {
247
+ throw invalidInput('distanceMeters must be a finite number');
248
+ }
249
+ if (segments !== undefined && (typeof segments !== 'number' || !(segments > 0))) {
250
+ throw invalidInput('segments must be a positive number');
251
+ }
252
+ for (const input of inputs) {
253
+ if (!isBufferableFeature(input)) {
254
+ throw invalidInput(`The feature ${input.id} cannot be buffered`);
255
+ }
256
+ }
257
+ if (refuseChange(inputs))
258
+ return null;
259
+ if (distanceMeters === 0 || inputs.length === 0)
260
+ return [];
261
+ return runBuffer(geometryDeps, inputs, { distanceMeters, segments }, false).map((resultId) => store.getFeature(resultId));
262
+ },
263
+ };
264
+ function moveMany(ids, to) {
265
+ const features = inStackingOrder(requireAll(ids));
266
+ const target = resolveMoveTarget(store, to);
267
+ if (store.isReadOnly())
268
+ return false;
269
+ if (features.some((feature) => featureLocked(store, feature)))
270
+ return false;
271
+ if (target.locked)
272
+ return false;
273
+ moveFeatures(store, features, target);
274
+ return true;
275
+ }
276
+ /** The features as areas in stacking order, at least `min` of them */
277
+ function requireAreas(ids, min) {
278
+ const features = inStackingOrder(requireAll(ids));
279
+ if (features.length < min) {
280
+ throw invalidInput(`At least ${min} areas are needed`);
281
+ }
282
+ for (const feature of features) {
283
+ if (!isAreaFeature(feature))
284
+ throw invalidInput(`The feature ${feature.id} is not an area`);
285
+ }
286
+ return features;
287
+ }
288
+ /** Whether a change of these features is refused: read-only, or one of them is locked */
289
+ function refuseChange(features) {
290
+ return store.isReadOnly() || features.some((feature) => featureLocked(store, feature));
291
+ }
292
+ /**
293
+ * Runs a boolean operation on areas and puts the result in the place of `anchor`
294
+ *
295
+ * @returns The result, or null when the result has no area (nothing changes then)
296
+ */
297
+ function runAreaOperation(inputs, anchor, removed, compute) {
298
+ const areas = inputs.map((feature) => toAreaCoordinates(feature));
299
+ const geometry = toResultGeometry(compute(areas));
300
+ if (geometry === null)
301
+ return null;
302
+ const resultId = store.transact(() => applyResult(geometryDeps, {
303
+ anchor,
304
+ removedIds: removed.map((feature) => feature.id),
305
+ geometry,
306
+ }));
307
+ return store.getFeature(resultId) ?? null;
308
+ }
309
+ }
310
+ // ============================================================================
311
+ // Inputs and patches
312
+ // ============================================================================
313
+ /** Checks an input and builds the feature to store; throws DrawError on a wrong input */
314
+ function prepareFeature(deps, input, pending) {
315
+ const { store } = deps;
316
+ requireRecord(input, 'The input');
317
+ const record = input;
318
+ onlyKeys(record, INPUT_KEYS, 'The input');
319
+ if (typeof input.type !== 'string' || input.type === '') {
320
+ throw invalidInput('type must be a non-empty string');
321
+ }
322
+ const geometryProblem = describeGeometryProblem(input.type, input.geometry);
323
+ if (geometryProblem)
324
+ throw invalidInput(`The input has ${geometryProblem}`);
325
+ if (input.properties !== undefined && !isRecord(input.properties)) {
326
+ throw invalidInput('properties must be an object');
327
+ }
328
+ if (input.style !== undefined) {
329
+ const styleProblem = describeStyleProblem(input.style);
330
+ if (styleProblem)
331
+ throw invalidInput(`The input has ${styleProblem}`);
332
+ }
333
+ optionalBoolean(record, 'visible');
334
+ optionalBoolean(record, 'locked');
335
+ let id;
336
+ if (input.id === undefined) {
337
+ id = deps.generateId();
338
+ }
339
+ else {
340
+ id = requireId(input.id);
341
+ if (isTaken(store, id) || pending.has(id)) {
342
+ throw new DrawError('already-exists', `The ID ${JSON.stringify(id)} is already taken`, {
343
+ id,
344
+ });
345
+ }
346
+ }
347
+ const group = input.groupId === undefined ? undefined : store.getGroup(requireId(input.groupId));
348
+ if (input.groupId !== undefined && !group)
349
+ throw notFound('group', input.groupId);
350
+ let layerId;
351
+ if (input.layerId !== undefined) {
352
+ layerId = requireId(input.layerId);
353
+ if (!store.getLayer(layerId))
354
+ throw notFound('layer', layerId);
355
+ if (group && group.layerId !== layerId) {
356
+ throw invalidInput(`The group ${group.id} is not in the layer ${layerId}`);
357
+ }
358
+ }
359
+ else if (group) {
360
+ layerId = group.layerId;
361
+ }
362
+ else {
363
+ layerId = deps.getActiveLayerId();
364
+ if (!store.getLayer(layerId)) {
365
+ throw new DrawError('invalid-state', 'There is no layer to put the feature in');
366
+ }
367
+ }
368
+ return {
369
+ id,
370
+ type: input.type,
371
+ geometry: input.geometry,
372
+ layerId,
373
+ groupId: group?.id,
374
+ properties: withoutUndefined(input.properties ?? {}),
375
+ style: withoutUndefined(input.style ?? {}),
376
+ visible: input.visible ?? true,
377
+ locked: input.locked ?? false,
378
+ };
379
+ }
380
+ /**
381
+ * Checks a patch and builds the updates of the Store; throws DrawError on a wrong patch
382
+ *
383
+ * @internal
384
+ */
385
+ export function preparePatch(feature, patch) {
386
+ requireRecord(patch, 'The patch');
387
+ const record = patch;
388
+ onlyKeys(record, PATCH_KEYS, 'The patch');
389
+ optionalBoolean(record, 'visible');
390
+ optionalBoolean(record, 'locked');
391
+ const updates = {};
392
+ if (patch.geometry !== undefined) {
393
+ const problem = describeGeometryProblem(feature.type, patch.geometry);
394
+ if (problem)
395
+ throw invalidInput(`The patch has ${problem}`);
396
+ updates.geometry = patch.geometry;
397
+ }
398
+ if (patch.properties !== undefined) {
399
+ if (!isRecord(patch.properties))
400
+ throw invalidInput('properties must be an object');
401
+ updates.properties = merged(feature.properties, patch.properties);
402
+ }
403
+ if (patch.style !== undefined) {
404
+ const problem = describeStyleProblem(patch.style);
405
+ if (problem)
406
+ throw invalidInput(`The patch has ${problem}`);
407
+ updates.style = merged(feature.style, patch.style);
408
+ }
409
+ if (patch.visible !== undefined)
410
+ updates.visible = patch.visible;
411
+ if (patch.locked !== undefined)
412
+ updates.locked = patch.locked;
413
+ return updates;
414
+ }
415
+ /** The keys of `base` with the keys of `patch` set, and removed where they are undefined */
416
+ function merged(base, patch) {
417
+ const result = {};
418
+ for (const [key, value] of Object.entries(base))
419
+ setOwnProperty(result, key, value);
420
+ for (const [key, value] of Object.entries(patch)) {
421
+ if (value === undefined)
422
+ delete result[key];
423
+ else
424
+ setOwnProperty(result, key, value);
425
+ }
426
+ return result;
427
+ }
428
+ /** A copy without the keys whose value is undefined */
429
+ function withoutUndefined(value) {
430
+ return merged({}, value);
431
+ }
432
+ // ============================================================================
433
+ // The applied style
434
+ // ============================================================================
435
+ /**
436
+ * The look a feature is drawn with: the defaults of the options, the color of the layer rule
437
+ * and the style of the feature, in that order. The colors of the options and of the feature
438
+ * are the strings given, never rounded
439
+ */
440
+ function appliedStyle(store, feature, style) {
441
+ const defaults = toAppliedDefaults(style, feature.type);
442
+ const layer = store.getLayer(feature.layerId);
443
+ const own = resolveFeatureStyle(feature, layer?.styleRule, getStyleRuleChannel(feature.type)) ?? {};
444
+ return { ...defaults, ...withoutUndefined(own) };
445
+ }
@@ -0,0 +1,32 @@
1
+ import type { Feature, FeatureCoordinates, FeatureType } from '../../../store/types.js';
2
+ import type { GeometryDeps } from './types.js';
3
+ export interface CommitParams {
4
+ /**
5
+ * The input whose style, properties and placement are inherited (in a boolean operation, the
6
+ * frontmost in z order)
7
+ */
8
+ anchor: Feature;
9
+ /**
10
+ * The IDs of the inputs to delete. Left empty in an operation that keeps the inputs, such as
11
+ * the buffer
12
+ */
13
+ removedIds: string[];
14
+ geometry: {
15
+ type: FeatureType;
16
+ coordinates: FeatureCoordinates;
17
+ };
18
+ /**
19
+ * The properties of the result. When omitted, they are inherited from the anchor with the
20
+ * Circle-specific properties removed.
21
+ * It is given explicitly only when the result stays a Circle (the Circle special case of the
22
+ * buffer).
23
+ */
24
+ properties?: Record<string, unknown>;
25
+ }
26
+ /**
27
+ * Creates one result feature, deletes the inputs and places it.
28
+ *
29
+ * It does not open a transaction. Because the caller wraps it in store.transact, even a case
30
+ * with several results, such as the buffer, is gathered into one StoreChange.
31
+ */
32
+ export declare function applyResult(deps: GeometryDeps, params: CommitParams): string;
@@ -1,5 +1,7 @@
1
1
  // SPDX-FileCopyrightText: 2026 SAKAIDA Atsushi
2
2
  // SPDX-License-Identifier: AGPL-3.0-only
3
+ import { setDrawProperty } from '../../../shared/properties.js';
4
+ import { geometryFromCoordinates } from '../../../shared/utils/coordinates.js';
3
5
  /**
4
6
  * The parametric properties of Circle. They are not inherited by a result that has been
5
7
  * reduced to a polygon (because a Circle becomes a polygon of 64 segments and loses the
@@ -17,7 +19,7 @@ const CIRCLE_ONLY_PROPERTIES = ['radiusMeters', 'radiusHandleAngle'];
17
19
  */
18
20
  function planPlacement(store, anchor, removedIds) {
19
21
  const group = anchor.groupId ? store.getGroup(anchor.groupId) : undefined;
20
- const container = group ? group.featureIds : (store.getLayer(anchor.layerId)?.order ?? []);
22
+ const container = group ? group.featureIds : (store.getLayer(anchor.layerId)?.items ?? []);
21
23
  const anchorIndex = container.indexOf(anchor.id);
22
24
  const precedingIds = anchorIndex < 0 ? container : container.slice(0, anchorIndex);
23
25
  const precedingCount = precedingIds.filter((id) => !removedIds.has(id)).length;
@@ -46,17 +48,17 @@ function moveToPlacement(store, resultId, placement) {
46
48
  const layer = store.getLayer(placement.layerId);
47
49
  if (!layer)
48
50
  return;
49
- const order = layer.order.filter((id) => id !== resultId);
51
+ const order = layer.items.filter((id) => id !== resultId);
50
52
  order.splice(placement.index, 0, resultId);
51
- store.updateLayer(placement.layerId, { order });
53
+ store.updateLayer(placement.layerId, { items: order });
52
54
  }
53
55
  /**
54
56
  * Inherits the style and the properties from the input it inherits from.
55
57
  */
56
58
  function inheritProperties(anchor) {
57
59
  const properties = { ...anchor.properties };
58
- for (const key of CIRCLE_ONLY_PROPERTIES) {
59
- delete properties[key];
60
+ for (const name of CIRCLE_ONLY_PROPERTIES) {
61
+ setDrawProperty(properties, name, undefined);
60
62
  }
61
63
  return properties;
62
64
  }
@@ -64,7 +66,7 @@ function inheritProperties(anchor) {
64
66
  * Creates one result feature, deletes the inputs and places it.
65
67
  *
66
68
  * It does not open a transaction. Because the caller wraps it in store.transact, even a case
67
- * with several results, such as the buffer, is gathered into one StateChanges.
69
+ * with several results, such as the buffer, is gathered into one StoreChange.
68
70
  */
69
71
  export function applyResult(deps, params) {
70
72
  const { store, generateFeatureId } = deps;
@@ -73,11 +75,11 @@ export function applyResult(deps, params) {
73
75
  const result = {
74
76
  id: generateFeatureId(),
75
77
  type: geometry.type,
76
- coordinates: geometry.coordinates,
78
+ geometry: geometryFromCoordinates(geometry.type, geometry.coordinates),
77
79
  layerId: placement.layerId,
78
80
  groupId: placement.groupId,
79
81
  properties: params.properties ?? inheritProperties(anchor),
80
- style: anchor.style ? { ...anchor.style } : undefined,
82
+ style: { ...anchor.style },
81
83
  locked: false,
82
84
  visible: true,
83
85
  };
@@ -93,22 +95,3 @@ export function applyResult(deps, params) {
93
95
  moveToPlacement(store, result.id, placement);
94
96
  return result.id;
95
97
  }
96
- /**
97
- * Creates the result feature and deletes the inputs in one transaction, and moves the
98
- * selection to the result.
99
- *
100
- * A subscriber receives it as one StateChanges, which is what makes it one step for anything
101
- * that records changes.
102
- */
103
- export function commitResult(deps, params) {
104
- const { store } = deps;
105
- return store.transact(() => {
106
- const resultId = applyResult(deps, params);
107
- store.setSelection('feature', [resultId]);
108
- return resultId;
109
- });
110
- }
111
- /** Emits draw.geometry.applied. */
112
- export function emitApplied(eventEmitter, payload) {
113
- eventEmitter.emit('geometry.applied', payload);
114
- }
@@ -1,5 +1,5 @@
1
- import type { Feature } from '../../store/types.js';
2
- import type { GeometryApiDeps, GeometryBufferOptions } from './types.js';
1
+ import type { Feature } from '../../../store/types.js';
2
+ import type { BufferOptions, GeometryDeps } from './types.js';
3
3
  /**
4
4
  * Runs the buffer and creates the result features.
5
5
  *
@@ -7,5 +7,6 @@ import type { GeometryApiDeps, GeometryBufferOptions } from './types.js';
7
7
  * gathered into one store.transact, so a single undo removes all of them.
8
8
  *
9
9
  * @param inputs The targets ordered in z order (the tail is the frontmost)
10
+ * @param select Whether the results become the selection
10
11
  */
11
- export declare function runBuffer(deps: GeometryApiDeps, inputs: Feature[], options: GeometryBufferOptions): string[];
12
+ export declare function runBuffer(deps: GeometryDeps, inputs: Feature[], options: BufferOptions, select?: boolean): string[];
@@ -8,10 +8,12 @@
8
8
  * creates one result per input, several applyResult calls are gathered into one
9
9
  * store.transact, and all the results are selected at the end.
10
10
  */
11
+ import { buffer as computeBuffer } from '../../../geometry/buffer.js';
11
12
  // buffer is imported under an alias so that the name reads as the geometry module's function.
12
- import { buffer as computeBuffer } from '../../geometry/index.js';
13
- import { getCircleRadius } from '../../shared/utils/property.js';
14
- import { applyResult, emitApplied } from './apply.js';
13
+ import { drawProperties } from '../../../shared/properties.js';
14
+ import { coordinatesOf } from '../../../shared/utils/coordinates.js';
15
+ import { getCircleRadius } from '../../../shared/utils/property.js';
16
+ import { applyResult } from './apply.js';
15
17
  import { toBufferGeometry, toResultGeometry } from './targets.js';
16
18
  /**
17
19
  * Plans the buffer of a Circle input.
@@ -29,10 +31,10 @@ function planCircleBuffer(input, distanceMeters) {
29
31
  return null;
30
32
  return {
31
33
  input,
32
- geometry: { type: 'Circle', coordinates: input.coordinates },
34
+ geometry: { type: 'Circle', coordinates: coordinatesOf(input) },
33
35
  // It stays a Circle, so the properties including radiusHandleAngle are inherited and only
34
36
  // the radius is replaced.
35
- properties: { ...input.properties, radiusMeters: nextRadius },
37
+ properties: { ...input.properties, ...drawProperties({ radiusMeters: nextRadius }) },
36
38
  };
37
39
  }
38
40
  /**
@@ -63,8 +65,9 @@ function planBuffer(input, options) {
63
65
  * gathered into one store.transact, so a single undo removes all of them.
64
66
  *
65
67
  * @param inputs The targets ordered in z order (the tail is the frontmost)
68
+ * @param select Whether the results become the selection
66
69
  */
67
- export function runBuffer(deps, inputs, options) {
70
+ export function runBuffer(deps, inputs, options, select = true) {
68
71
  const { store } = deps;
69
72
  const plans = [];
70
73
  for (const input of inputs) {
@@ -73,15 +76,7 @@ export function runBuffer(deps, inputs, options) {
73
76
  plans.push(plan);
74
77
  }
75
78
  if (plans.length === 0) {
76
- // Every input was skipped or had an empty result. The Store is not changed at all; only
77
- // the notification is emitted.
78
- emitApplied(deps.eventEmitter, {
79
- operation: 'buffer',
80
- inputIds: inputs.map((input) => input.id),
81
- resultId: null,
82
- resultIds: [],
83
- status: 'empty',
84
- });
79
+ // Every input was skipped or had an empty result. The Store is not changed at all.
85
80
  return [];
86
81
  }
87
82
  const resultIds = store.transact(() => {
@@ -91,15 +86,9 @@ export function runBuffer(deps, inputs, options) {
91
86
  geometry: plan.geometry,
92
87
  properties: plan.properties,
93
88
  }));
94
- store.setSelection('feature', ids);
89
+ if (select)
90
+ store.setSelection('feature', ids);
95
91
  return ids;
96
92
  });
97
- emitApplied(deps.eventEmitter, {
98
- operation: 'buffer',
99
- inputIds: plans.map((plan) => plan.input.id),
100
- resultId: resultIds[0],
101
- resultIds,
102
- status: 'applied',
103
- });
104
93
  return resultIds;
105
94
  }
@@ -1,5 +1,5 @@
1
- import type { Feature } from '../../store/types.js';
2
- import type { GeometryApiDeps } from './types.js';
1
+ import type { Feature } from '../../../store/types.js';
2
+ import type { GeometryDeps } from './types.js';
3
3
  /**
4
4
  * Runs the split and replaces the polygon with the group of features that result from the
5
5
  * split.
@@ -12,5 +12,6 @@ import type { GeometryApiDeps } from './types.js';
12
12
  *
13
13
  * @param area The polygon to be cut
14
14
  * @param line The cutting line (it is not deleted and remains)
15
+ * @param select Whether the results become the selection
15
16
  */
16
- export declare function runSplit(deps: GeometryApiDeps, area: Feature, line: Feature): string[];
17
+ export declare function runSplit(deps: GeometryDeps, area: Feature, line: Feature, select?: boolean): string[];