@sakuzu/maplibre-gl-draw 1.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 (636) hide show
  1. package/CHANGELOG.md +43 -0
  2. package/LICENSE +661 -0
  3. package/README.ja.md +248 -0
  4. package/README.md +255 -0
  5. package/THIRD_PARTY_NOTICES.md +275 -0
  6. package/dist/api/api.d.ts +1259 -0
  7. package/dist/api/api.js +86 -0
  8. package/dist/api/context.d.ts +173 -0
  9. package/dist/api/context.js +193 -0
  10. package/dist/api/display-api.d.ts +1 -0
  11. package/dist/api/display-api.js +23 -0
  12. package/dist/api/event-api.d.ts +13 -0
  13. package/dist/api/event-api.js +17 -0
  14. package/dist/api/extension-api.d.ts +46 -0
  15. package/dist/api/extension-api.js +85 -0
  16. package/dist/api/feature-api.d.ts +11 -0
  17. package/dist/api/feature-api.js +101 -0
  18. package/dist/api/geometry/apply.d.ts +51 -0
  19. package/dist/api/geometry/apply.js +114 -0
  20. package/dist/api/geometry/boolean.d.ts +28 -0
  21. package/dist/api/geometry/boolean.js +65 -0
  22. package/dist/api/geometry/buffer.d.ts +11 -0
  23. package/dist/api/geometry/buffer.js +105 -0
  24. package/dist/api/geometry/split.d.ts +16 -0
  25. package/dist/api/geometry/split.js +75 -0
  26. package/dist/api/geometry/targets.d.ts +76 -0
  27. package/dist/api/geometry/targets.js +158 -0
  28. package/dist/api/geometry/types.d.ts +31 -0
  29. package/dist/api/geometry/types.js +3 -0
  30. package/dist/api/geometry-operations.d.ts +162 -0
  31. package/dist/api/geometry-operations.js +94 -0
  32. package/dist/api/group-api.d.ts +10 -0
  33. package/dist/api/group-api.js +78 -0
  34. package/dist/api/import-export/constants.d.ts +29 -0
  35. package/dist/api/import-export/constants.js +40 -0
  36. package/dist/api/import-export/embedded-file.d.ts +13 -0
  37. package/dist/api/import-export/embedded-file.js +31 -0
  38. package/dist/api/import-export/file-name.d.ts +10 -0
  39. package/dist/api/import-export/file-name.js +20 -0
  40. package/dist/api/import-export/format-detection.d.ts +12 -0
  41. package/dist/api/import-export/format-detection.js +29 -0
  42. package/dist/api/import-export/geojson-export.d.ts +19 -0
  43. package/dist/api/import-export/geojson-export.js +262 -0
  44. package/dist/api/import-export/geojson-import.d.ts +34 -0
  45. package/dist/api/import-export/geojson-import.js +538 -0
  46. package/dist/api/import-export/geometry-validation.d.ts +20 -0
  47. package/dist/api/import-export/geometry-validation.js +107 -0
  48. package/dist/api/import-export/image-import.d.ts +12 -0
  49. package/dist/api/import-export/image-import.js +53 -0
  50. package/dist/api/import-export/index.d.ts +9 -0
  51. package/dist/api/import-export/index.js +107 -0
  52. package/dist/api/import-export/native-format.d.ts +15 -0
  53. package/dist/api/import-export/native-format.js +126 -0
  54. package/dist/api/import-export/native-validation.d.ts +28 -0
  55. package/dist/api/import-export/native-validation.js +212 -0
  56. package/dist/api/import-export/own-property.d.ts +10 -0
  57. package/dist/api/import-export/own-property.js +19 -0
  58. package/dist/api/import-export/style-validation.d.ts +27 -0
  59. package/dist/api/import-export/style-validation.js +49 -0
  60. package/dist/api/import-export/types.d.ts +26 -0
  61. package/dist/api/import-export/types.js +3 -0
  62. package/dist/api/index.d.ts +15 -0
  63. package/dist/api/index.js +3 -0
  64. package/dist/api/input-api.d.ts +158 -0
  65. package/dist/api/input-api.js +144 -0
  66. package/dist/api/instance-api.d.ts +38 -0
  67. package/dist/api/instance-api.js +136 -0
  68. package/dist/api/layer-api.d.ts +12 -0
  69. package/dist/api/layer-api.js +62 -0
  70. package/dist/api/selection-api.d.ts +7 -0
  71. package/dist/api/selection-api.js +78 -0
  72. package/dist/api/snapping-api.d.ts +125 -0
  73. package/dist/api/snapping-api.js +50 -0
  74. package/dist/api/topology-api.d.ts +30 -0
  75. package/dist/api/topology-api.js +16 -0
  76. package/dist/api/tracing-api.d.ts +31 -0
  77. package/dist/api/tracing-api.js +16 -0
  78. package/dist/dispatcher/hit-test/box-strategies.d.ts +19 -0
  79. package/dist/dispatcher/hit-test/box-strategies.js +275 -0
  80. package/dist/dispatcher/hit-test/box-strategy.d.ts +59 -0
  81. package/dist/dispatcher/hit-test/box-strategy.js +37 -0
  82. package/dist/dispatcher/hit-test/globe-shape.d.ts +46 -0
  83. package/dist/dispatcher/hit-test/globe-shape.js +70 -0
  84. package/dist/dispatcher/hit-test/index.d.ts +14 -0
  85. package/dist/dispatcher/hit-test/index.js +9 -0
  86. package/dist/dispatcher/hit-test/local-frame.d.ts +77 -0
  87. package/dist/dispatcher/hit-test/local-frame.js +112 -0
  88. package/dist/dispatcher/hit-test/segment-grid.d.ts +32 -0
  89. package/dist/dispatcher/hit-test/segment-grid.js +79 -0
  90. package/dist/dispatcher/hit-test/service.d.ts +120 -0
  91. package/dist/dispatcher/hit-test/service.js +333 -0
  92. package/dist/dispatcher/hit-test/strategies/base.d.ts +136 -0
  93. package/dist/dispatcher/hit-test/strategies/base.js +66 -0
  94. package/dist/dispatcher/hit-test/strategies/circle.d.ts +10 -0
  95. package/dist/dispatcher/hit-test/strategies/circle.js +56 -0
  96. package/dist/dispatcher/hit-test/strategies/image.d.ts +22 -0
  97. package/dist/dispatcher/hit-test/strategies/image.js +115 -0
  98. package/dist/dispatcher/hit-test/strategies/index.d.ts +11 -0
  99. package/dist/dispatcher/hit-test/strategies/index.js +10 -0
  100. package/dist/dispatcher/hit-test/strategies/line.d.ts +17 -0
  101. package/dist/dispatcher/hit-test/strategies/line.js +30 -0
  102. package/dist/dispatcher/hit-test/strategies/multi.d.ts +44 -0
  103. package/dist/dispatcher/hit-test/strategies/multi.js +141 -0
  104. package/dist/dispatcher/hit-test/strategies/point.d.ts +20 -0
  105. package/dist/dispatcher/hit-test/strategies/point.js +29 -0
  106. package/dist/dispatcher/hit-test/strategies/polygon.d.ts +52 -0
  107. package/dist/dispatcher/hit-test/strategies/polygon.js +138 -0
  108. package/dist/dispatcher/hit-test/topmost.d.ts +48 -0
  109. package/dist/dispatcher/hit-test/topmost.js +157 -0
  110. package/dist/dispatcher/hit-test/visibility-lookup.d.ts +23 -0
  111. package/dist/dispatcher/hit-test/visibility-lookup.js +40 -0
  112. package/dist/dispatcher/index.d.ts +15 -0
  113. package/dist/dispatcher/index.js +3 -0
  114. package/dist/dispatcher/input-router.d.ts +1 -0
  115. package/dist/dispatcher/input-router.js +288 -0
  116. package/dist/dispatcher/normalizer.d.ts +1 -0
  117. package/dist/dispatcher/normalizer.js +513 -0
  118. package/dist/dispatcher/types.d.ts +144 -0
  119. package/dist/dispatcher/types.js +15 -0
  120. package/dist/display/chunk-set.d.ts +24 -0
  121. package/dist/display/chunk-set.js +533 -0
  122. package/dist/display/chunk.d.ts +1 -0
  123. package/dist/display/chunk.js +104 -0
  124. package/dist/display/columnar/index.d.ts +12 -0
  125. package/dist/display/columnar/index.js +13 -0
  126. package/dist/display/columnar/prepare.d.ts +42 -0
  127. package/dist/display/columnar/prepare.js +116 -0
  128. package/dist/display/columnar/source.d.ts +1 -0
  129. package/dist/display/columnar/source.js +531 -0
  130. package/dist/display/columnar/table.d.ts +1 -0
  131. package/dist/display/columnar/table.js +471 -0
  132. package/dist/display/columnar/types.d.ts +223 -0
  133. package/dist/display/columnar/types.js +3 -0
  134. package/dist/display/dataset.d.ts +2 -0
  135. package/dist/display/dataset.js +891 -0
  136. package/dist/display/index.d.ts +13 -0
  137. package/dist/display/index.js +3 -0
  138. package/dist/display/interaction.d.ts +1 -0
  139. package/dist/display/interaction.js +90 -0
  140. package/dist/display/manager.d.ts +1 -0
  141. package/dist/display/manager.js +440 -0
  142. package/dist/display/packed-rtree.d.ts +1 -0
  143. package/dist/display/packed-rtree.js +244 -0
  144. package/dist/display/partition.d.ts +1 -0
  145. package/dist/display/partition.js +226 -0
  146. package/dist/display/provider.d.ts +1 -0
  147. package/dist/display/provider.js +342 -0
  148. package/dist/display/retained.d.ts +40 -0
  149. package/dist/display/retained.js +898 -0
  150. package/dist/display/selection.d.ts +13 -0
  151. package/dist/display/selection.js +226 -0
  152. package/dist/display/source.d.ts +1 -0
  153. package/dist/display/source.js +119 -0
  154. package/dist/display/spatial.d.ts +1 -0
  155. package/dist/display/spatial.js +71 -0
  156. package/dist/display/style.d.ts +1 -0
  157. package/dist/display/style.js +126 -0
  158. package/dist/display/thinning.d.ts +65 -0
  159. package/dist/display/thinning.js +910 -0
  160. package/dist/display/triangulation.d.ts +1 -0
  161. package/dist/display/triangulation.js +0 -0
  162. package/dist/display/types.d.ts +561 -0
  163. package/dist/display/types.js +43 -0
  164. package/dist/extension/feature-handler.d.ts +182 -0
  165. package/dist/extension/feature-handler.js +3 -0
  166. package/dist/extension/index.d.ts +9 -0
  167. package/dist/extension/index.js +3 -0
  168. package/dist/extension/renderers.d.ts +208 -0
  169. package/dist/extension/renderers.js +3 -0
  170. package/dist/geometry/angle.d.ts +47 -0
  171. package/dist/geometry/angle.js +44 -0
  172. package/dist/geometry/bbox.d.ts +48 -0
  173. package/dist/geometry/bbox.js +83 -0
  174. package/dist/geometry/boolean.d.ts +162 -0
  175. package/dist/geometry/boolean.js +331 -0
  176. package/dist/geometry/buffer.d.ts +72 -0
  177. package/dist/geometry/buffer.js +218 -0
  178. package/dist/geometry/circle.d.ts +55 -0
  179. package/dist/geometry/circle.js +107 -0
  180. package/dist/geometry/coords.d.ts +97 -0
  181. package/dist/geometry/coords.js +149 -0
  182. package/dist/geometry/distance.d.ts +79 -0
  183. package/dist/geometry/distance.js +111 -0
  184. package/dist/geometry/errors.d.ts +74 -0
  185. package/dist/geometry/errors.js +104 -0
  186. package/dist/geometry/index.d.ts +28 -0
  187. package/dist/geometry/index.js +38 -0
  188. package/dist/geometry/measure.d.ts +81 -0
  189. package/dist/geometry/measure.js +236 -0
  190. package/dist/geometry/predicates.d.ts +62 -0
  191. package/dist/geometry/predicates.js +132 -0
  192. package/dist/geometry/simplify.d.ts +74 -0
  193. package/dist/geometry/simplify.js +159 -0
  194. package/dist/geometry/split.d.ts +68 -0
  195. package/dist/geometry/split.js +430 -0
  196. package/dist/geometry/types.d.ts +95 -0
  197. package/dist/geometry/types.js +3 -0
  198. package/dist/geometry/units.d.ts +35 -0
  199. package/dist/geometry/units.js +41 -0
  200. package/dist/index.d.ts +72 -0
  201. package/dist/index.js +20 -0
  202. package/dist/maplibre-gl-draw.d.ts +47 -0
  203. package/dist/maplibre-gl-draw.js +407 -0
  204. package/dist/messages.d.ts +64 -0
  205. package/dist/messages.js +36 -0
  206. package/dist/modes/cursor.d.ts +1 -0
  207. package/dist/modes/cursor.js +72 -0
  208. package/dist/modes/draw/circle.d.ts +1 -0
  209. package/dist/modes/draw/circle.js +222 -0
  210. package/dist/modes/draw/commit-layer.d.ts +26 -0
  211. package/dist/modes/draw/commit-layer.js +31 -0
  212. package/dist/modes/draw/freehand.d.ts +1 -0
  213. package/dist/modes/draw/freehand.js +264 -0
  214. package/dist/modes/draw/image.d.ts +1 -0
  215. package/dist/modes/draw/image.js +60 -0
  216. package/dist/modes/draw/index.d.ts +9 -0
  217. package/dist/modes/draw/index.js +11 -0
  218. package/dist/modes/draw/line.d.ts +1 -0
  219. package/dist/modes/draw/line.js +363 -0
  220. package/dist/modes/draw/point.d.ts +1 -0
  221. package/dist/modes/draw/point.js +87 -0
  222. package/dist/modes/draw/polygon.d.ts +1 -0
  223. package/dist/modes/draw/polygon.js +378 -0
  224. package/dist/modes/draw/trace-support.d.ts +79 -0
  225. package/dist/modes/draw/trace-support.js +161 -0
  226. package/dist/modes/handler.d.ts +285 -0
  227. package/dist/modes/handler.js +3 -0
  228. package/dist/modes/index.d.ts +7 -0
  229. package/dist/modes/index.js +3 -0
  230. package/dist/modes/manager.d.ts +15 -0
  231. package/dist/modes/manager.js +196 -0
  232. package/dist/modes/select/box-selection.d.ts +52 -0
  233. package/dist/modes/select/box-selection.js +140 -0
  234. package/dist/modes/select/click-handler.d.ts +32 -0
  235. package/dist/modes/select/click-handler.js +166 -0
  236. package/dist/modes/select/cursor-handler.d.ts +15 -0
  237. package/dist/modes/select/cursor-handler.js +59 -0
  238. package/dist/modes/select/drag/auxiliary.d.ts +26 -0
  239. package/dist/modes/select/drag/auxiliary.js +56 -0
  240. package/dist/modes/select/drag/intermediate-writes.d.ts +1 -0
  241. package/dist/modes/select/drag/intermediate-writes.js +171 -0
  242. package/dist/modes/select/drag/move.d.ts +24 -0
  243. package/dist/modes/select/drag/move.js +59 -0
  244. package/dist/modes/select/drag/operation.d.ts +30 -0
  245. package/dist/modes/select/drag/operation.js +18 -0
  246. package/dist/modes/select/drag/radius.d.ts +15 -0
  247. package/dist/modes/select/drag/radius.js +49 -0
  248. package/dist/modes/select/drag/transform.d.ts +17 -0
  249. package/dist/modes/select/drag/transform.js +155 -0
  250. package/dist/modes/select/drag/vertex.d.ts +17 -0
  251. package/dist/modes/select/drag/vertex.js +163 -0
  252. package/dist/modes/select/drag-handler.d.ts +1 -0
  253. package/dist/modes/select/drag-handler.js +254 -0
  254. package/dist/modes/select/hit-helpers.d.ts +40 -0
  255. package/dist/modes/select/hit-helpers.js +51 -0
  256. package/dist/modes/select/mode.d.ts +1 -0
  257. package/dist/modes/select/mode.js +397 -0
  258. package/dist/modes/select/shortcut-handler.d.ts +40 -0
  259. package/dist/modes/select/shortcut-handler.js +128 -0
  260. package/dist/operations/index.d.ts +9 -0
  261. package/dist/operations/index.js +3 -0
  262. package/dist/operations/layer-operations.d.ts +1 -0
  263. package/dist/operations/layer-operations.js +350 -0
  264. package/dist/operations/resize.d.ts +71 -0
  265. package/dist/operations/resize.js +252 -0
  266. package/dist/operations/rotate.d.ts +17 -0
  267. package/dist/operations/rotate.js +166 -0
  268. package/dist/operations/selection-operations.d.ts +20 -0
  269. package/dist/operations/selection-operations.js +159 -0
  270. package/dist/operations/shared-vertex.d.ts +1 -0
  271. package/dist/operations/shared-vertex.js +210 -0
  272. package/dist/operations/trace-graph.d.ts +96 -0
  273. package/dist/operations/trace-graph.js +283 -0
  274. package/dist/operations/vertex.d.ts +1 -0
  275. package/dist/operations/vertex.js +538 -0
  276. package/dist/plugins/index.d.ts +10 -0
  277. package/dist/plugins/index.js +3 -0
  278. package/dist/plugins/mutation-hooks.d.ts +28 -0
  279. package/dist/plugins/mutation-hooks.js +84 -0
  280. package/dist/plugins/plugin-context.d.ts +1 -0
  281. package/dist/plugins/plugin-context.js +367 -0
  282. package/dist/plugins/plugin-manager.d.ts +103 -0
  283. package/dist/plugins/plugin-manager.js +316 -0
  284. package/dist/plugins/plugin.d.ts +529 -0
  285. package/dist/plugins/plugin.js +3 -0
  286. package/dist/shared/config/constants.d.ts +66 -0
  287. package/dist/shared/config/constants.js +60 -0
  288. package/dist/shared/config/feature-style.d.ts +155 -0
  289. package/dist/shared/config/feature-style.js +154 -0
  290. package/dist/shared/config/index.d.ts +17 -0
  291. package/dist/shared/config/index.js +8 -0
  292. package/dist/shared/config/rendering.d.ts +107 -0
  293. package/dist/shared/config/rendering.js +33 -0
  294. package/dist/shared/config/selection-highlight.d.ts +29 -0
  295. package/dist/shared/config/selection-highlight.js +35 -0
  296. package/dist/shared/config/selection.d.ts +273 -0
  297. package/dist/shared/config/selection.js +266 -0
  298. package/dist/shared/config/topology.d.ts +33 -0
  299. package/dist/shared/config/topology.js +17 -0
  300. package/dist/shared/config/trace.d.ts +40 -0
  301. package/dist/shared/config/trace.js +17 -0
  302. package/dist/shared/math/angle.d.ts +21 -0
  303. package/dist/shared/math/angle.js +34 -0
  304. package/dist/shared/math/circle.d.ts +6 -0
  305. package/dist/shared/math/circle.js +10 -0
  306. package/dist/shared/math/constants.d.ts +48 -0
  307. package/dist/shared/math/constants.js +59 -0
  308. package/dist/shared/math/distance.d.ts +78 -0
  309. package/dist/shared/math/distance.js +147 -0
  310. package/dist/shared/math/globe-subdivision.d.ts +62 -0
  311. package/dist/shared/math/globe-subdivision.js +99 -0
  312. package/dist/shared/math/index.d.ts +17 -0
  313. package/dist/shared/math/index.js +21 -0
  314. package/dist/shared/math/intersection.d.ts +63 -0
  315. package/dist/shared/math/intersection.js +236 -0
  316. package/dist/shared/math/longitude.d.ts +20 -0
  317. package/dist/shared/math/longitude.js +31 -0
  318. package/dist/shared/math/mercator-plane.d.ts +27 -0
  319. package/dist/shared/math/mercator-plane.js +26 -0
  320. package/dist/shared/math/obb.d.ts +65 -0
  321. package/dist/shared/math/obb.js +107 -0
  322. package/dist/shared/math/rotation.d.ts +93 -0
  323. package/dist/shared/math/rotation.js +186 -0
  324. package/dist/shared/math/segment-grid.d.ts +69 -0
  325. package/dist/shared/math/segment-grid.js +159 -0
  326. package/dist/shared/math/transform.d.ts +140 -0
  327. package/dist/shared/math/transform.js +189 -0
  328. package/dist/shared/types/events.d.ts +128 -0
  329. package/dist/shared/types/events.js +3 -0
  330. package/dist/shared/types/model.d.ts +950 -0
  331. package/dist/shared/types/model.js +3 -0
  332. package/dist/shared/types/selection-box.d.ts +23 -0
  333. package/dist/shared/types/selection-box.js +3 -0
  334. package/dist/shared/types/style.d.ts +68 -0
  335. package/dist/shared/types/style.js +3 -0
  336. package/dist/shared/utils/color.d.ts +49 -0
  337. package/dist/shared/utils/color.js +180 -0
  338. package/dist/shared/utils/coordinates.d.ts +52 -0
  339. package/dist/shared/utils/coordinates.js +75 -0
  340. package/dist/shared/utils/embedded-image.d.ts +34 -0
  341. package/dist/shared/utils/embedded-image.js +161 -0
  342. package/dist/shared/utils/event-emitter.d.ts +262 -0
  343. package/dist/shared/utils/event-emitter.js +44 -0
  344. package/dist/shared/utils/feature-bbox.d.ts +8 -0
  345. package/dist/shared/utils/feature-bbox.js +207 -0
  346. package/dist/shared/utils/feature-segments.d.ts +23 -0
  347. package/dist/shared/utils/feature-segments.js +179 -0
  348. package/dist/shared/utils/id.d.ts +1 -0
  349. package/dist/shared/utils/id.js +35 -0
  350. package/dist/shared/utils/image.d.ts +34 -0
  351. package/dist/shared/utils/image.js +106 -0
  352. package/dist/shared/utils/index.d.ts +15 -0
  353. package/dist/shared/utils/index.js +24 -0
  354. package/dist/shared/utils/map.d.ts +26 -0
  355. package/dist/shared/utils/map.js +35 -0
  356. package/dist/shared/utils/name-generator.d.ts +197 -0
  357. package/dist/shared/utils/name-generator.js +337 -0
  358. package/dist/shared/utils/pixel-ratio.d.ts +111 -0
  359. package/dist/shared/utils/pixel-ratio.js +85 -0
  360. package/dist/shared/utils/property.d.ts +88 -0
  361. package/dist/shared/utils/property.js +140 -0
  362. package/dist/shared/utils/vertex-ref.d.ts +23 -0
  363. package/dist/shared/utils/vertex-ref.js +20 -0
  364. package/dist/snapping/custom-targets.d.ts +1 -0
  365. package/dist/snapping/custom-targets.js +21 -0
  366. package/dist/snapping/geometry.d.ts +1 -0
  367. package/dist/snapping/geometry.js +61 -0
  368. package/dist/snapping/index.d.ts +14 -0
  369. package/dist/snapping/index.js +4 -0
  370. package/dist/snapping/indicator.d.ts +19 -0
  371. package/dist/snapping/indicator.js +145 -0
  372. package/dist/snapping/providers/display.d.ts +72 -0
  373. package/dist/snapping/providers/display.js +268 -0
  374. package/dist/snapping/providers/guide.d.ts +69 -0
  375. package/dist/snapping/providers/guide.js +187 -0
  376. package/dist/snapping/providers/intersection.d.ts +1 -0
  377. package/dist/snapping/providers/intersection.js +92 -0
  378. package/dist/snapping/providers/shared.d.ts +39 -0
  379. package/dist/snapping/providers/shared.js +146 -0
  380. package/dist/snapping/providers/store.d.ts +1 -0
  381. package/dist/snapping/providers/store.js +132 -0
  382. package/dist/snapping/service.d.ts +1 -0
  383. package/dist/snapping/service.js +272 -0
  384. package/dist/snapping/types.d.ts +267 -0
  385. package/dist/snapping/types.js +66 -0
  386. package/dist/store/change-merger.d.ts +1 -0
  387. package/dist/store/change-merger.js +102 -0
  388. package/dist/store/draw-store.d.ts +1 -0
  389. package/dist/store/draw-store.js +396 -0
  390. package/dist/store/event-bridge.d.ts +1 -0
  391. package/dist/store/event-bridge.js +161 -0
  392. package/dist/store/index.d.ts +12 -0
  393. package/dist/store/index.js +4 -0
  394. package/dist/store/local-visibility.d.ts +21 -0
  395. package/dist/store/local-visibility.js +27 -0
  396. package/dist/store/lock.d.ts +67 -0
  397. package/dist/store/lock.js +54 -0
  398. package/dist/store/memory/change-bus.d.ts +60 -0
  399. package/dist/store/memory/change-bus.js +232 -0
  400. package/dist/store/memory/file-store.d.ts +15 -0
  401. package/dist/store/memory/file-store.js +33 -0
  402. package/dist/store/memory/frozen.d.ts +21 -0
  403. package/dist/store/memory/frozen.js +51 -0
  404. package/dist/store/memory/ui-state.d.ts +51 -0
  405. package/dist/store/memory/ui-state.js +223 -0
  406. package/dist/store/memory.d.ts +26 -0
  407. package/dist/store/memory.js +708 -0
  408. package/dist/store/spatial/index.d.ts +6 -0
  409. package/dist/store/spatial/index.js +4 -0
  410. package/dist/store/spatial/spatial-index.d.ts +90 -0
  411. package/dist/store/spatial/spatial-index.js +148 -0
  412. package/dist/store/spatial/store-spatial-index.d.ts +60 -0
  413. package/dist/store/spatial/store-spatial-index.js +125 -0
  414. package/dist/store/store.d.ts +417 -0
  415. package/dist/store/store.js +3 -0
  416. package/dist/store/types.d.ts +8 -0
  417. package/dist/store/types.js +3 -0
  418. package/dist/store/writable-layer.d.ts +35 -0
  419. package/dist/store/writable-layer.js +20 -0
  420. package/dist/view/cache/buffer.d.ts +28 -0
  421. package/dist/view/cache/buffer.js +176 -0
  422. package/dist/view/cache/earcut.d.ts +1 -0
  423. package/dist/view/cache/earcut.js +122 -0
  424. package/dist/view/cache/style-rule.d.ts +1 -0
  425. package/dist/view/cache/style-rule.js +97 -0
  426. package/dist/view/cache/terrain-fill.d.ts +30 -0
  427. package/dist/view/cache/terrain-fill.js +60 -0
  428. package/dist/view/cache/texture.d.ts +14 -0
  429. package/dist/view/cache/texture.js +292 -0
  430. package/dist/view/coordinator.d.ts +27 -0
  431. package/dist/view/coordinator.js +72 -0
  432. package/dist/view/feature-companion.d.ts +173 -0
  433. package/dist/view/feature-companion.js +108 -0
  434. package/dist/view/globe-subdivision.d.ts +78 -0
  435. package/dist/view/globe-subdivision.js +128 -0
  436. package/dist/view/index.d.ts +47 -0
  437. package/dist/view/index.js +20 -0
  438. package/dist/view/layer/attach.d.ts +20 -0
  439. package/dist/view/layer/attach.js +47 -0
  440. package/dist/view/layer/blend.d.ts +57 -0
  441. package/dist/view/layer/blend.js +14 -0
  442. package/dist/view/layer/custom-layer.d.ts +1 -0
  443. package/dist/view/layer/custom-layer.js +509 -0
  444. package/dist/view/layer/depth-state.d.ts +14 -0
  445. package/dist/view/layer/depth-state.js +44 -0
  446. package/dist/view/layer/display-list.d.ts +1 -0
  447. package/dist/view/layer/display-list.js +111 -0
  448. package/dist/view/layer/drape-planner.d.ts +139 -0
  449. package/dist/view/layer/drape-planner.js +726 -0
  450. package/dist/view/layer/frame-render.d.ts +57 -0
  451. package/dist/view/layer/frame-render.js +209 -0
  452. package/dist/view/layer/frame-state.d.ts +147 -0
  453. package/dist/view/layer/frame-state.js +484 -0
  454. package/dist/view/layer/gl-state.d.ts +77 -0
  455. package/dist/view/layer/gl-state.js +132 -0
  456. package/dist/view/layer/index.d.ts +6 -0
  457. package/dist/view/layer/index.js +5 -0
  458. package/dist/view/layer/render-scope.d.ts +30 -0
  459. package/dist/view/layer/render-scope.js +28 -0
  460. package/dist/view/layer/render.d.ts +87 -0
  461. package/dist/view/layer/render.js +187 -0
  462. package/dist/view/layer/renderers.d.ts +81 -0
  463. package/dist/view/layer/renderers.js +142 -0
  464. package/dist/view/layer/slot-manager.d.ts +26 -0
  465. package/dist/view/layer/slot-manager.js +133 -0
  466. package/dist/view/layer/slots.d.ts +33 -0
  467. package/dist/view/layer/slots.js +50 -0
  468. package/dist/view/layer/store-retained-bbox.d.ts +36 -0
  469. package/dist/view/layer/store-retained-bbox.js +188 -0
  470. package/dist/view/layer/store-retained-chunk.d.ts +97 -0
  471. package/dist/view/layer/store-retained-chunk.js +94 -0
  472. package/dist/view/layer/store-retained-classify.d.ts +34 -0
  473. package/dist/view/layer/store-retained-classify.js +88 -0
  474. package/dist/view/layer/store-retained-collect.d.ts +24 -0
  475. package/dist/view/layer/store-retained-collect.js +121 -0
  476. package/dist/view/layer/store-retained-coord-patch.d.ts +119 -0
  477. package/dist/view/layer/store-retained-coord-patch.js +168 -0
  478. package/dist/view/layer/store-retained-immediate.d.ts +63 -0
  479. package/dist/view/layer/store-retained-immediate.js +49 -0
  480. package/dist/view/layer/store-retained-invalidation.d.ts +96 -0
  481. package/dist/view/layer/store-retained-invalidation.js +192 -0
  482. package/dist/view/layer/store-retained.d.ts +198 -0
  483. package/dist/view/layer/store-retained.js +430 -0
  484. package/dist/view/layer/terrain-resolver.d.ts +1 -0
  485. package/dist/view/layer/terrain-resolver.js +174 -0
  486. package/dist/view/renderers/batch-manager.d.ts +61 -0
  487. package/dist/view/renderers/batch-manager.js +718 -0
  488. package/dist/view/renderers/draw-factors.d.ts +60 -0
  489. package/dist/view/renderers/draw-factors.js +35 -0
  490. package/dist/view/renderers/drawer.d.ts +1 -0
  491. package/dist/view/renderers/drawer.js +346 -0
  492. package/dist/view/renderers/image.d.ts +1 -0
  493. package/dist/view/renderers/image.js +255 -0
  494. package/dist/view/renderers/line/dash.d.ts +31 -0
  495. package/dist/view/renderers/line/dash.js +152 -0
  496. package/dist/view/renderers/line/line-geometry.d.ts +39 -0
  497. package/dist/view/renderers/line/line-geometry.js +460 -0
  498. package/dist/view/renderers/line/line-gl.d.ts +1 -0
  499. package/dist/view/renderers/line/line-gl.js +236 -0
  500. package/dist/view/renderers/line/line-shader.d.ts +1 -0
  501. package/dist/view/renderers/line/line-shader.js +364 -0
  502. package/dist/view/renderers/line/line-types.d.ts +43 -0
  503. package/dist/view/renderers/line/line-types.js +3 -0
  504. package/dist/view/renderers/line/line-uniforms.d.ts +1 -0
  505. package/dist/view/renderers/line/line-uniforms.js +390 -0
  506. package/dist/view/renderers/line/sdf-line.d.ts +92 -0
  507. package/dist/view/renderers/line/sdf-line.js +567 -0
  508. package/dist/view/renderers/point/billboard-depth.d.ts +10 -0
  509. package/dist/view/renderers/point/billboard-depth.js +56 -0
  510. package/dist/view/renderers/point/point-instance.d.ts +124 -0
  511. package/dist/view/renderers/point/point-instance.js +738 -0
  512. package/dist/view/renderers/point/point-sdf.d.ts +58 -0
  513. package/dist/view/renderers/point/point-sdf.js +170 -0
  514. package/dist/view/renderers/point/point-shape.d.ts +99 -0
  515. package/dist/view/renderers/point/point-shape.js +504 -0
  516. package/dist/view/renderers/point/point-style.d.ts +1 -0
  517. package/dist/view/renderers/point/point-style.js +46 -0
  518. package/dist/view/renderers/polygon/batch.d.ts +26 -0
  519. package/dist/view/renderers/polygon/batch.js +336 -0
  520. package/dist/view/renderers/polygon/earcut-input.d.ts +37 -0
  521. package/dist/view/renderers/polygon/earcut-input.js +55 -0
  522. package/dist/view/renderers/polygon/earcut-sliced.d.ts +69 -0
  523. package/dist/view/renderers/polygon/earcut-sliced.js +960 -0
  524. package/dist/view/renderers/polygon/fill.d.ts +74 -0
  525. package/dist/view/renderers/polygon/fill.js +251 -0
  526. package/dist/view/renderers/polygon/sdf-polygon.d.ts +62 -0
  527. package/dist/view/renderers/polygon/sdf-polygon.js +919 -0
  528. package/dist/view/renderers/polygon/terrain-cull.d.ts +3 -0
  529. package/dist/view/renderers/polygon/terrain-cull.js +14 -0
  530. package/dist/view/renderers/polygon/triangulator.d.ts +41 -0
  531. package/dist/view/renderers/polygon/triangulator.js +3 -0
  532. package/dist/view/renderers/retained.d.ts +43 -0
  533. package/dist/view/renderers/retained.js +3 -0
  534. package/dist/view/renderers/stroke.d.ts +121 -0
  535. package/dist/view/renderers/stroke.js +621 -0
  536. package/dist/view/shaders/frame.d.ts +8 -0
  537. package/dist/view/shaders/frame.js +37 -0
  538. package/dist/view/shaders/helpers.d.ts +238 -0
  539. package/dist/view/shaders/helpers.js +611 -0
  540. package/dist/view/shaders/initializer.d.ts +27 -0
  541. package/dist/view/shaders/initializer.js +125 -0
  542. package/dist/view/shaders/projection.d.ts +123 -0
  543. package/dist/view/shaders/projection.js +299 -0
  544. package/dist/view/shaders/quad-grid.d.ts +77 -0
  545. package/dist/view/shaders/quad-grid.js +128 -0
  546. package/dist/view/shaders/quad.d.ts +189 -0
  547. package/dist/view/shaders/quad.js +582 -0
  548. package/dist/view/shaders/retained-origin.d.ts +50 -0
  549. package/dist/view/shaders/retained-origin.js +67 -0
  550. package/dist/view/shaders/terrain-shade.d.ts +23 -0
  551. package/dist/view/shaders/terrain-shade.js +93 -0
  552. package/dist/view/style-rule.d.ts +166 -0
  553. package/dist/view/style-rule.js +300 -0
  554. package/dist/view/terrain/anchor.d.ts +135 -0
  555. package/dist/view/terrain/anchor.js +226 -0
  556. package/dist/view/terrain/context.d.ts +132 -0
  557. package/dist/view/terrain/context.js +437 -0
  558. package/dist/view/terrain/dem-atlas.d.ts +97 -0
  559. package/dist/view/terrain/dem-atlas.js +534 -0
  560. package/dist/view/terrain/detect.d.ts +126 -0
  561. package/dist/view/terrain/detect.js +198 -0
  562. package/dist/view/terrain/drape/bin-store.d.ts +179 -0
  563. package/dist/view/terrain/drape/bin-store.js +529 -0
  564. package/dist/view/terrain/drape/binning.d.ts +259 -0
  565. package/dist/view/terrain/drape/binning.js +604 -0
  566. package/dist/view/terrain/drape/edge-constrain.d.ts +37 -0
  567. package/dist/view/terrain/drape/edge-constrain.js +175 -0
  568. package/dist/view/terrain/drape/geometry.d.ts +95 -0
  569. package/dist/view/terrain/drape/geometry.js +260 -0
  570. package/dist/view/terrain/drape/mesh.d.ts +50 -0
  571. package/dist/view/terrain/drape/mesh.js +86 -0
  572. package/dist/view/terrain/drape/pass.d.ts +122 -0
  573. package/dist/view/terrain/drape/pass.js +379 -0
  574. package/dist/view/terrain/drape/quad-glyphs.d.ts +64 -0
  575. package/dist/view/terrain/drape/quad-glyphs.js +117 -0
  576. package/dist/view/terrain/drape/quad.d.ts +249 -0
  577. package/dist/view/terrain/drape/quad.js +835 -0
  578. package/dist/view/terrain/drape/renderer.d.ts +184 -0
  579. package/dist/view/terrain/drape/renderer.js +706 -0
  580. package/dist/view/terrain/drape/shared.d.ts +80 -0
  581. package/dist/view/terrain/drape/shared.js +173 -0
  582. package/dist/view/terrain/drape/stitch.d.ts +155 -0
  583. package/dist/view/terrain/drape/stitch.js +228 -0
  584. package/dist/view/terrain/ground.d.ts +72 -0
  585. package/dist/view/terrain/ground.js +151 -0
  586. package/dist/view/terrain/metrics.d.ts +180 -0
  587. package/dist/view/terrain/metrics.js +231 -0
  588. package/dist/view/terrain/occlusion.d.ts +11 -0
  589. package/dist/view/terrain/occlusion.js +129 -0
  590. package/dist/view/terrain/polygon.d.ts +86 -0
  591. package/dist/view/terrain/polygon.js +301 -0
  592. package/dist/view/terrain/shade.d.ts +48 -0
  593. package/dist/view/terrain/shade.js +45 -0
  594. package/dist/view/terrain/state.d.ts +99 -0
  595. package/dist/view/terrain/state.js +186 -0
  596. package/dist/view/terrain/tessellation.d.ts +265 -0
  597. package/dist/view/terrain/tessellation.js +924 -0
  598. package/dist/view/terrain/tiling.d.ts +56 -0
  599. package/dist/view/terrain/tiling.js +155 -0
  600. package/dist/view/terrain/upstream-terrain.d.ts +82 -0
  601. package/dist/view/terrain/upstream-terrain.js +116 -0
  602. package/dist/view/ui/auxiliary-handles.d.ts +151 -0
  603. package/dist/view/ui/auxiliary-handles.js +22 -0
  604. package/dist/view/ui/bounds.d.ts +53 -0
  605. package/dist/view/ui/bounds.js +149 -0
  606. package/dist/view/ui/box-selection.d.ts +1 -0
  607. package/dist/view/ui/box-selection.js +83 -0
  608. package/dist/view/ui/handle-test.d.ts +1 -0
  609. package/dist/view/ui/handle-test.js +437 -0
  610. package/dist/view/ui/handle-thinning.d.ts +122 -0
  611. package/dist/view/ui/handle-thinning.js +430 -0
  612. package/dist/view/ui/handles.d.ts +25 -0
  613. package/dist/view/ui/handles.js +673 -0
  614. package/dist/view/ui/helper.d.ts +19 -0
  615. package/dist/view/ui/helper.js +76 -0
  616. package/dist/view/ui/index.d.ts +15 -0
  617. package/dist/view/ui/index.js +15 -0
  618. package/dist/view/ui/selection-scope.d.ts +25 -0
  619. package/dist/view/ui/selection-scope.js +34 -0
  620. package/dist/view/ui/selection-ui/bounding-box.d.ts +44 -0
  621. package/dist/view/ui/selection-ui/bounding-box.js +240 -0
  622. package/dist/view/ui/selection-ui/extension-registry.d.ts +76 -0
  623. package/dist/view/ui/selection-ui/extension-registry.js +78 -0
  624. package/dist/view/ui/selection-ui/index.d.ts +12 -0
  625. package/dist/view/ui/selection-ui/index.js +12 -0
  626. package/dist/view/ui/selection-ui/renderer.d.ts +29 -0
  627. package/dist/view/ui/selection-ui/renderer.js +227 -0
  628. package/dist/view/ui/selection-ui/types.d.ts +55 -0
  629. package/dist/view/ui/selection-ui/types.js +3 -0
  630. package/dist/view/ui/selection-ui-drawer.d.ts +52 -0
  631. package/dist/view/ui/selection-ui-drawer.js +329 -0
  632. package/dist/view/ui/tentative.d.ts +1 -0
  633. package/dist/view/ui/tentative.js +320 -0
  634. package/dist/view/viewport.d.ts +119 -0
  635. package/dist/view/viewport.js +254 -0
  636. package/package.json +113 -0
@@ -0,0 +1,53 @@
1
+ // SPDX-FileCopyrightText: 2026 SAKAIDA Atsushi
2
+ // SPDX-License-Identifier: AGPL-3.0-only
3
+ /**
4
+ * Import of image files (creates an Image feature)
5
+ */
6
+ import { processImageFile } from '../../shared/utils/image.js';
7
+ /**
8
+ * Imports an image file and creates an Image feature
9
+ */
10
+ export async function loadImage(file, options, deps) {
11
+ if (!options.coordinate) {
12
+ throw new Error('Image files require coordinate option');
13
+ }
14
+ const { store, autoNameGenerator, generateFeatureId, getCurrentLayerId } = deps;
15
+ const processed = await processImageFile(file);
16
+ // Create the FileData
17
+ const fileId = generateFeatureId();
18
+ const fileData = {
19
+ id: fileId,
20
+ mimeType: processed.mimeType,
21
+ dataURL: processed.dataUrl,
22
+ };
23
+ // Create the Image feature
24
+ const featureId = generateFeatureId();
25
+ const layerId = options.layerId || getCurrentLayerId();
26
+ const autoName = autoNameGenerator.generateName('Image');
27
+ const feature = {
28
+ id: featureId,
29
+ type: 'Image',
30
+ coordinates: options.coordinate,
31
+ layerId,
32
+ properties: {
33
+ imageFileId: fileId,
34
+ imageWidth: processed.width,
35
+ imageHeight: processed.height,
36
+ createdZoom: options.zoom ?? 1,
37
+ ...(autoName !== undefined && { name: autoName }),
38
+ },
39
+ locked: false,
40
+ visible: true,
41
+ };
42
+ // Create the file and the feature in a transaction
43
+ store.transact(() => {
44
+ store.createFile(fileData);
45
+ store.createFeature(feature);
46
+ store.setSelection('feature', [featureId]);
47
+ });
48
+ return {
49
+ format: 'image',
50
+ featureIds: [featureId],
51
+ replaced: false,
52
+ };
53
+ }
@@ -0,0 +1,9 @@
1
+ import type { ExportFormat, ExportOptions, ExportResult, LoadOptions, LoadResult } from '../../store/types.js';
2
+ /**
3
+ * Import/Export API interface
4
+ */
5
+ export interface ImportExportAPI {
6
+ load(source: File | unknown, options?: LoadOptions): Promise<LoadResult>;
7
+ export(format: ExportFormat, options?: ExportOptions): ExportResult;
8
+ getSuggestedFileName(): string;
9
+ }
@@ -0,0 +1,107 @@
1
+ // SPDX-FileCopyrightText: 2026 SAKAIDA Atsushi
2
+ // SPDX-License-Identifier: AGPL-3.0-only
3
+ /**
4
+ * Orchestrator of the Import/Export API
5
+ *
6
+ * createImportExportAPI is a thin orchestrator that detects the format and then delegates
7
+ * to each import/export function. The implementation is spread across format-detection /
8
+ * geojson-import / geojson-export / native-format / image-import / file-name.
9
+ */
10
+ import { isImageFile } from '../../shared/utils/image.js';
11
+ import { buildExportFileName } from './file-name.js';
12
+ import { isGeoJSONFeatureCollection, isNativeFormat } from './format-detection.js';
13
+ import { exportGeoJSON } from './geojson-export.js';
14
+ import { loadGeoJSON } from './geojson-import.js';
15
+ import { loadImage } from './image-import.js';
16
+ import { exportNative, loadNative } from './native-format.js';
17
+ /**
18
+ * Creates the Import/Export API
19
+ *
20
+ * @internal
21
+ */
22
+ export function createImportExportAPI(context) {
23
+ const { store, generateFeatureId, getCurrentLayerId, autoNameGenerator } = context;
24
+ const importDeps = {
25
+ store,
26
+ autoNameGenerator,
27
+ generateFeatureId,
28
+ getCurrentLayerId,
29
+ };
30
+ const api = {
31
+ /**
32
+ * Loads data or a file.
33
+ *
34
+ * Detects the kind of source automatically and handles it accordingly:
35
+ * - File: detects the file kind automatically (image / .json / .geojson)
36
+ * - object: detects the data format automatically (native format /
37
+ * GeoJSON FeatureCollection)
38
+ */
39
+ async load(source, options) {
40
+ if (source instanceof File) {
41
+ if (isImageFile(source)) {
42
+ return loadImage(source, options || {}, importDeps);
43
+ }
44
+ const fileName = source.name.toLowerCase();
45
+ const mimeType = source.type;
46
+ const isJsonFile = fileName.endsWith('.json') ||
47
+ fileName.endsWith('.geojson') ||
48
+ mimeType === 'application/json' ||
49
+ mimeType === 'application/geo+json';
50
+ if (isJsonFile) {
51
+ const text = await source.text();
52
+ let data;
53
+ try {
54
+ data = JSON.parse(text);
55
+ }
56
+ catch (error) {
57
+ const detail = error instanceof Error ? error.message : String(error);
58
+ throw new Error(`Invalid JSON file "${source.name}": ${detail}`);
59
+ }
60
+ return api.load(data, options);
61
+ }
62
+ throw new Error(`Unsupported file type: ${source.type || source.name}`);
63
+ }
64
+ if (isNativeFormat(source)) {
65
+ return loadNative(source, { store });
66
+ }
67
+ if (isGeoJSONFeatureCollection(source)) {
68
+ return loadGeoJSON(source, importDeps, { flattenMulti: options?.flattenMulti });
69
+ }
70
+ throw new Error('Unsupported data format. Expected native format or GeoJSON FeatureCollection.');
71
+ },
72
+ /**
73
+ * Exports the data
74
+ */
75
+ export(format, options) {
76
+ const metadata = store.getMetadata();
77
+ if (format === 'native') {
78
+ const data = exportNative(store, options);
79
+ const fileName = options?.fileName || buildExportFileName(metadata, '.maplibre-gl-draw.json');
80
+ return {
81
+ format: 'native',
82
+ data: JSON.stringify(data, null, 2),
83
+ mimeType: 'application/json',
84
+ fileName,
85
+ };
86
+ }
87
+ if (format === 'geojson') {
88
+ const data = exportGeoJSON(store, options);
89
+ const fileName = options?.fileName || buildExportFileName(metadata, '.geojson');
90
+ return {
91
+ format: 'geojson',
92
+ data: JSON.stringify(data, null, 2),
93
+ mimeType: 'application/geo+json',
94
+ fileName,
95
+ };
96
+ }
97
+ throw new Error(`Unsupported export format: ${format}`);
98
+ },
99
+ /**
100
+ * Generates a suggested export file name
101
+ */
102
+ getSuggestedFileName() {
103
+ return buildExportFileName(store.getMetadata(), '.maplibre-gl-draw.json');
104
+ },
105
+ };
106
+ return api;
107
+ }
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Import / export of the native format
3
+ */
4
+ import type { Store } from '../../store/store.js';
5
+ import type { Data, ExportOptions, LoadResult } from '../../store/types.js';
6
+ /**
7
+ * Exports the current data in the native format
8
+ */
9
+ export declare function exportNative(store: Store, options?: ExportOptions): Data;
10
+ /**
11
+ * Imports the native format (replaces the existing data)
12
+ */
13
+ export declare function loadNative(data: Data, deps: {
14
+ store: Store;
15
+ }): Promise<LoadResult>;
@@ -0,0 +1,126 @@
1
+ // SPDX-FileCopyrightText: 2026 SAKAIDA Atsushi
2
+ // SPDX-License-Identifier: AGPL-3.0-only
3
+ import { NATIVE_VERSION } from './constants.js';
4
+ import { validateNativeData } from './native-validation.js';
5
+ /** The layer that survives the replacement (it is updated in place when the data has it) */
6
+ const DEFAULT_LAYER_ID = 'default-layer';
7
+ /**
8
+ * Exports the current data in the native format
9
+ */
10
+ export function exportNative(store, options) {
11
+ let features = store.getAllFeatures();
12
+ const layers = store.getAllLayers();
13
+ const groups = store.getAllGroups();
14
+ if (options?.featureIds && options.featureIds.length > 0) {
15
+ const featureIdSet = new Set(options.featureIds);
16
+ features = features.filter((f) => featureIdSet.has(f.id));
17
+ }
18
+ if (options?.layerIds && options.layerIds.length > 0) {
19
+ const layerIdSet = new Set(options.layerIds);
20
+ features = features.filter((f) => layerIdSet.has(f.layerId));
21
+ }
22
+ // Get only the files that are in use
23
+ const usedFileIds = new Set();
24
+ for (const feature of features) {
25
+ if (feature.type === 'Image' && feature.properties.imageFileId) {
26
+ usedFileIds.add(feature.properties.imageFileId);
27
+ }
28
+ }
29
+ const files = store.getAllFiles();
30
+ const filesRecord = {};
31
+ for (const file of files) {
32
+ if (usedFileIds.has(file.id)) {
33
+ filesRecord[file.id] = file;
34
+ }
35
+ }
36
+ const metadata = store.getMetadata();
37
+ const now = new Date().toISOString();
38
+ return {
39
+ version: NATIVE_VERSION,
40
+ created: now,
41
+ modified: now,
42
+ metadata: Object.keys(metadata).length > 0 ? metadata : undefined,
43
+ layers,
44
+ // The whole stacking order, entries of the application that are not layers included
45
+ layerOrder: [...store.getLayerOrder()],
46
+ groups,
47
+ features,
48
+ files: Object.keys(filesRecord).length > 0 ? filesRecord : undefined,
49
+ };
50
+ }
51
+ /**
52
+ * Imports the native format (replaces the existing data)
53
+ */
54
+ export async function loadNative(data, deps) {
55
+ const { store } = deps;
56
+ // Validate before applying. Since store.transact does not roll back, if an exception
57
+ // is thrown on invalid data after the existing data has been cleared, the existing data
58
+ // is lost. Everything the steps below rely on (the shape of the layers, groups, features
59
+ // and files, the references between them, and the uniqueness of the ids) is checked
60
+ // before the destructive operation, so a problem throws while the existing data is
61
+ // still intact.
62
+ const retainedLayerIds = new Set();
63
+ if (store.getLayer(DEFAULT_LAYER_ID))
64
+ retainedLayerIds.add(DEFAULT_LAYER_ID);
65
+ const { layers, layerOrder, groups, features, files } = await validateNativeData(data, retainedLayerIds);
66
+ const featureIds = features.map((f) => f.id);
67
+ // A kept layer the data does not list goes to the back, where it stays when the data does
68
+ // not mention it (every layer must be on the stacking order to be drawn)
69
+ const retainedUnlisted = [...retainedLayerIds].filter((id) => !layerOrder.includes(id));
70
+ // Import atomically (silent, so a subscriber that records changes leaves it out)
71
+ store.transact(() => {
72
+ // 1. Clear the existing data
73
+ const existingFeatures = store.getAllFeatures();
74
+ for (const feature of existingFeatures) {
75
+ store.deleteFeature(feature.id);
76
+ }
77
+ const existingGroups = store.getAllGroups();
78
+ for (const group of existingGroups) {
79
+ store.deleteGroup(group.id);
80
+ }
81
+ const existingLayers = store.getAllLayers();
82
+ for (const layer of existingLayers) {
83
+ if (layer.id !== DEFAULT_LAYER_ID) {
84
+ store.deleteLayer(layer.id);
85
+ }
86
+ }
87
+ // The files belong to the features that were just removed, and the data brings its own
88
+ // (leaving them would also make a file id of the data collide)
89
+ for (const file of store.getAllFiles()) {
90
+ store.deleteFile(file.id);
91
+ }
92
+ // 2. Import the layers
93
+ for (const layer of layers) {
94
+ if (store.getLayer(layer.id)) {
95
+ store.updateLayer(layer.id, layer);
96
+ }
97
+ else {
98
+ store.createLayer(layer);
99
+ }
100
+ }
101
+ // 3. Import the groups
102
+ for (const group of groups) {
103
+ store.createGroup(group);
104
+ }
105
+ // 4. Import the features
106
+ for (const feature of features) {
107
+ store.createFeature(feature);
108
+ }
109
+ // 5. Import the files
110
+ for (const file of files) {
111
+ store.createFile(file);
112
+ }
113
+ // 6. Replace the whole stacking order. Entries that are not layers are replaced too, so
114
+ // nothing of the previous document is left on it
115
+ store.setLayerOrder([...retainedUnlisted, ...layerOrder]);
116
+ // 7. Import the metadata
117
+ if (data.metadata) {
118
+ store.setMetadata(data.metadata);
119
+ }
120
+ }, 'silent');
121
+ return {
122
+ format: 'native',
123
+ featureIds,
124
+ replaced: true,
125
+ };
126
+ }
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Validation of native-format data before it replaces the store
3
+ *
4
+ * Loading the native format clears the existing data first, and store.transact does not roll
5
+ * back. Every property the import relies on is therefore checked here, before anything is
6
+ * deleted: a problem throws while the existing data is still intact. The checks follow the
7
+ * native format described in docs/reference/data-format.md.
8
+ */
9
+ import type { Data, Feature, FileData, Group, Layer } from '../../store/types.js';
10
+ /** Native data that passed validation, with the files normalized */
11
+ export interface ValidatedNativeData {
12
+ layers: Layer[];
13
+ /** The stacking order, from the back */
14
+ layerOrder: string[];
15
+ groups: Group[];
16
+ /** The features in data order, each style reduced to its usable keys */
17
+ features: Feature[];
18
+ files: FileData[];
19
+ }
20
+ /**
21
+ * Validates native data before the destructive part of the import
22
+ *
23
+ * @param data - the data to load
24
+ * @param retainedLayerIds - IDs of the layers that remain in the store after it is cleared
25
+ * @throws when anything the import relies on is missing or malformed, or when the data has
26
+ * another major version
27
+ */
28
+ export declare function validateNativeData(data: Data, retainedLayerIds: ReadonlySet<string>): Promise<ValidatedNativeData>;
@@ -0,0 +1,212 @@
1
+ // SPDX-FileCopyrightText: 2026 SAKAIDA Atsushi
2
+ // SPDX-License-Identifier: AGPL-3.0-only
3
+ import { NATIVE_VERSION } from './constants.js';
4
+ import { normalizeEmbeddedFile } from './embedded-file.js';
5
+ import { describeCoordinateProblem } from './geometry-validation.js';
6
+ import { sanitizeFeatureStyle } from './style-validation.js';
7
+ function fail(message) {
8
+ throw new Error(`Invalid native data: ${message}`);
9
+ }
10
+ function isRecord(value) {
11
+ return typeof value === 'object' && value !== null && !Array.isArray(value);
12
+ }
13
+ function isNonEmptyString(value) {
14
+ return typeof value === 'string' && value !== '';
15
+ }
16
+ function validateLayer(layer, index) {
17
+ if (!isRecord(layer))
18
+ fail(`layers[${index}] is not an object`);
19
+ const where = `layer "${String(layer.id)}"`;
20
+ if (!isNonEmptyString(layer.id))
21
+ fail(`layers[${index}] has no valid string id`);
22
+ if (typeof layer.name !== 'string')
23
+ fail(`${where} has no string name`);
24
+ if (typeof layer.visible !== 'boolean')
25
+ fail(`${where} has no boolean visible`);
26
+ if (typeof layer.locked !== 'boolean')
27
+ fail(`${where} has no boolean locked`);
28
+ if (typeof layer.opacity !== 'number' || !Number.isFinite(layer.opacity)) {
29
+ fail(`${where} has no finite opacity`);
30
+ }
31
+ if (!Array.isArray(layer.order) || !layer.order.every((id) => typeof id === 'string')) {
32
+ fail(`${where} has no order array of strings`);
33
+ }
34
+ if (layer.metadata !== undefined && !isRecord(layer.metadata)) {
35
+ fail(`${where} has a metadata that is not an object`);
36
+ }
37
+ if (layer.styleRule !== undefined && !isRecord(layer.styleRule)) {
38
+ fail(`${where} has a styleRule that is not an object`);
39
+ }
40
+ return layer;
41
+ }
42
+ function validateGroup(group, index) {
43
+ if (!isRecord(group))
44
+ fail(`groups[${index}] is not an object`);
45
+ const where = `group "${String(group.id)}"`;
46
+ if (!isNonEmptyString(group.id))
47
+ fail(`groups[${index}] has no valid string id`);
48
+ if (typeof group.name !== 'string')
49
+ fail(`${where} has no string name`);
50
+ if (typeof group.visible !== 'boolean')
51
+ fail(`${where} has no boolean visible`);
52
+ if (typeof group.locked !== 'boolean')
53
+ fail(`${where} has no boolean locked`);
54
+ if (!Array.isArray(group.featureIds) || !group.featureIds.every((id) => typeof id === 'string')) {
55
+ fail(`${where} has no featureIds array of strings`);
56
+ }
57
+ return group;
58
+ }
59
+ /** Parses a semantic version (major.minor.patch, with an optional pre-release or build) */
60
+ function parseVersion(value) {
61
+ const match = /^(\d+)\.(\d+)\.(\d+)(?:[-+].*)?$/.exec(value);
62
+ return match ? [Number(match[1]), Number(match[2]), Number(match[3])] : null;
63
+ }
64
+ /**
65
+ * Checks the version of the data against the version this library writes
66
+ *
67
+ * Another major version is rejected, because it can change the meaning of any field. A newer
68
+ * minor version only adds fields, so it is read with a warning: the fields it adds are kept
69
+ * as they are but not interpreted.
70
+ */
71
+ function validateVersion(version) {
72
+ if (typeof version !== 'string')
73
+ fail('version is not a string');
74
+ const parsed = parseVersion(version);
75
+ if (!parsed)
76
+ fail(`version "${version}" is not a semantic version`);
77
+ const [major, minor] = parsed;
78
+ const [supportedMajor, supportedMinor] = parseVersion(NATIVE_VERSION);
79
+ if (major !== supportedMajor) {
80
+ fail(`version ${version} is not supported (this library reads ${supportedMajor}.x)`);
81
+ }
82
+ if (minor > supportedMinor) {
83
+ console.warn(`Native data version ${version} is newer than ${NATIVE_VERSION}; ` +
84
+ 'the fields it adds are kept but not interpreted');
85
+ }
86
+ }
87
+ /**
88
+ * Validates a feature and returns it with its style reduced to the usable keys
89
+ */
90
+ function validateFeature(feature, index, layerIds, groupIds) {
91
+ if (!isRecord(feature))
92
+ fail(`features[${index}] is not an object`);
93
+ if (!isNonEmptyString(feature.id))
94
+ fail('feature without a valid string id');
95
+ const where = `feature "${feature.id}"`;
96
+ if (!isNonEmptyString(feature.type))
97
+ fail(`${where} has no string type`);
98
+ const coordinateProblem = describeCoordinateProblem(feature.type, feature.coordinates);
99
+ if (coordinateProblem)
100
+ fail(`${where} has ${coordinateProblem}`);
101
+ if (typeof feature.layerId !== 'string' || !layerIds.has(feature.layerId)) {
102
+ fail(`${where} refers to a layer that does not exist`);
103
+ }
104
+ if (feature.groupId !== undefined &&
105
+ (typeof feature.groupId !== 'string' || !groupIds.has(feature.groupId))) {
106
+ fail(`${where} refers to a group that does not exist`);
107
+ }
108
+ if (!isRecord(feature.properties))
109
+ fail(`${where} has no properties object`);
110
+ if (feature.style !== undefined && !isRecord(feature.style)) {
111
+ fail(`${where} has a style that is not an object`);
112
+ }
113
+ if (typeof feature.visible !== 'boolean')
114
+ fail(`${where} has no boolean visible`);
115
+ if (typeof feature.locked !== 'boolean')
116
+ fail(`${where} has no boolean locked`);
117
+ // A style key of the wrong type or form is dropped rather than rejecting the file: the
118
+ // store accepts any value through its API, so the library's own export can carry one
119
+ if (feature.style === undefined)
120
+ return feature;
121
+ const { style: _style, ...rest } = feature;
122
+ const style = sanitizeFeatureStyle(feature.style);
123
+ return (style === undefined ? rest : { ...rest, style });
124
+ }
125
+ async function validateFiles(files) {
126
+ if (files === undefined)
127
+ return [];
128
+ if (!isRecord(files))
129
+ fail('files is not an object');
130
+ const result = [];
131
+ for (const [key, file] of Object.entries(files)) {
132
+ if (!isRecord(file) || !isNonEmptyString(file.id) || file.id !== key) {
133
+ fail(`file "${key}" is not an object whose id matches its key`);
134
+ }
135
+ const content = await normalizeEmbeddedFile(file.dataURL, file.mimeType);
136
+ if (!content) {
137
+ fail(`file "${key}" is not an embedded PNG / JPEG / WebP / GIF data URL of its declared type`);
138
+ }
139
+ result.push({ ...file, ...content });
140
+ }
141
+ return result;
142
+ }
143
+ /**
144
+ * Validates the stacking order: distinct non-empty strings that list every layer of the data
145
+ *
146
+ * Entries that are not layers belong to the application and are kept as they are.
147
+ */
148
+ function validateLayerOrder(value, layers) {
149
+ if (!Array.isArray(value))
150
+ fail('layerOrder is not an array');
151
+ const seen = new Set();
152
+ for (const [index, entry] of value.entries()) {
153
+ if (!isNonEmptyString(entry))
154
+ fail(`layerOrder[${index}] is not a non-empty string`);
155
+ if (seen.has(entry))
156
+ fail(`layerOrder lists "${entry}" twice`);
157
+ seen.add(entry);
158
+ }
159
+ for (const layer of layers) {
160
+ if (!seen.has(layer.id))
161
+ fail(`layerOrder does not list layer "${layer.id}"`);
162
+ }
163
+ return value;
164
+ }
165
+ /**
166
+ * Validates native data before the destructive part of the import
167
+ *
168
+ * @param data - the data to load
169
+ * @param retainedLayerIds - IDs of the layers that remain in the store after it is cleared
170
+ * @throws when anything the import relies on is missing or malformed, or when the data has
171
+ * another major version
172
+ */
173
+ export async function validateNativeData(data, retainedLayerIds) {
174
+ validateVersion(data.version);
175
+ if (!Array.isArray(data.features))
176
+ fail('features is not an array');
177
+ if (data.layers !== undefined && !Array.isArray(data.layers))
178
+ fail('layers is not an array');
179
+ if (data.groups !== undefined && !Array.isArray(data.groups))
180
+ fail('groups is not an array');
181
+ if (data.metadata !== undefined && !isRecord(data.metadata))
182
+ fail('metadata is not an object');
183
+ const layers = (data.layers ?? []).map(validateLayer);
184
+ const layerIds = new Set(retainedLayerIds);
185
+ const seenLayerIds = new Set();
186
+ for (const layer of layers) {
187
+ if (seenLayerIds.has(layer.id))
188
+ fail(`duplicate layer id "${layer.id}"`);
189
+ seenLayerIds.add(layer.id);
190
+ layerIds.add(layer.id);
191
+ }
192
+ const layerOrder = validateLayerOrder(data.layerOrder, layers);
193
+ // Feature and group IDs share the entries of layer.order, so they must not collide either
194
+ const itemIds = new Set();
195
+ const groups = (data.groups ?? []).map(validateGroup);
196
+ const groupIds = new Set();
197
+ for (const group of groups) {
198
+ if (itemIds.has(group.id))
199
+ fail(`duplicate group id "${group.id}"`);
200
+ itemIds.add(group.id);
201
+ groupIds.add(group.id);
202
+ }
203
+ const features = data.features.map((entry, index) => {
204
+ const feature = validateFeature(entry, index, layerIds, groupIds);
205
+ if (itemIds.has(feature.id))
206
+ fail(`duplicate feature id "${feature.id}"`);
207
+ itemIds.add(feature.id);
208
+ return feature;
209
+ });
210
+ const files = await validateFiles(data.files);
211
+ return { layers, layerOrder, groups, features, files };
212
+ }
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Copying of user-defined properties
3
+ *
4
+ * Property names come from the data being imported, so `__proto__` is an ordinary key there
5
+ * (JSON.parse creates it as an own property). Assigning it with `target[key] = value` would
6
+ * replace the prototype of the target instead, which hides the key, makes the other keys of
7
+ * the value appear as inherited properties and loses the key on the next export. Properties
8
+ * are therefore defined as own data properties, the same as JSON.parse does.
9
+ */
10
+ export declare function setOwnProperty(target: Record<string, unknown>, key: string, value: unknown): void;
@@ -0,0 +1,19 @@
1
+ // SPDX-FileCopyrightText: 2026 SAKAIDA Atsushi
2
+ // SPDX-License-Identifier: AGPL-3.0-only
3
+ /**
4
+ * Copying of user-defined properties
5
+ *
6
+ * Property names come from the data being imported, so `__proto__` is an ordinary key there
7
+ * (JSON.parse creates it as an own property). Assigning it with `target[key] = value` would
8
+ * replace the prototype of the target instead, which hides the key, makes the other keys of
9
+ * the value appear as inherited properties and loses the key on the next export. Properties
10
+ * are therefore defined as own data properties, the same as JSON.parse does.
11
+ */
12
+ export function setOwnProperty(target, key, value) {
13
+ Object.defineProperty(target, key, {
14
+ value,
15
+ writable: true,
16
+ enumerable: true,
17
+ configurable: true,
18
+ });
19
+ }
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Validation of an imported feature style
3
+ *
4
+ * A style arrives from a file (the maplibre-gl-draw:style property of GeoJSON, the style of a
5
+ * native feature, the simplestyle-spec keys) and reaches the renderer, which parses the
6
+ * colors as #rgb / #rrggbb and uses the numbers as they are. A value of the wrong type or
7
+ * form (a number or null for a color, `red`, an opacity of 5) would make the parsing throw or
8
+ * produce NaN, so each known key is checked here and a key that fails is dropped. Keys this
9
+ * library does not define are kept unchanged, whatever their value: they belong to the host or
10
+ * to an extension, which gives features keys of its own and checks their values where it reads
11
+ * them (values reach the Store through updateFeature and a replaced store as well, without
12
+ * passing here).
13
+ */
14
+ import type { FeatureStyle } from '../../store/types.js';
15
+ type Check = (value: unknown) => boolean;
16
+ /** A #rgb or #rrggbb color */
17
+ export declare const isHexColor: Check;
18
+ /**
19
+ * Returns the usable part of an imported style
20
+ *
21
+ * A key of FeatureStyle whose value fails its check is dropped; every other key is kept.
22
+ *
23
+ * @param value The style as read from the file
24
+ * @returns The style, or undefined when the value is not an object or nothing is left
25
+ */
26
+ export declare function sanitizeFeatureStyle(value: unknown): FeatureStyle | undefined;
27
+ export {};
@@ -0,0 +1,49 @@
1
+ // SPDX-FileCopyrightText: 2026 SAKAIDA Atsushi
2
+ // SPDX-License-Identifier: AGPL-3.0-only
3
+ import { setOwnProperty } from './own-property.js';
4
+ const HEX_COLOR = /^#(?:[0-9a-f]{3}|[0-9a-f]{6})$/i;
5
+ /** A #rgb or #rrggbb color */
6
+ export const isHexColor = (value) => typeof value === 'string' && HEX_COLOR.test(value);
7
+ const isFiniteNumber = (value) => typeof value === 'number' && Number.isFinite(value);
8
+ const isOpacity = (value) => isFiniteNumber(value) && value >= 0 && value <= 1;
9
+ const isNonNegative = (value) => isFiniteNumber(value) && value >= 0;
10
+ const oneOf = (...values) => (value) => typeof value === 'string' && values.includes(value);
11
+ /** The check of every key of FeatureStyle */
12
+ const STYLE_CHECK_TABLE = {
13
+ fillColor: isHexColor,
14
+ fillOpacity: isOpacity,
15
+ strokeColor: isHexColor,
16
+ strokeWidth: isNonNegative,
17
+ strokeOpacity: isOpacity,
18
+ lineStyle: oneOf('solid', 'dashed', 'dotted'),
19
+ pointRadius: isNonNegative,
20
+ pointColor: isHexColor,
21
+ pointShape: oneOf('circle', 'square', 'triangle', 'star'),
22
+ imageOpacity: isOpacity,
23
+ };
24
+ const STYLE_CHECKS = new Map(Object.entries(STYLE_CHECK_TABLE));
25
+ function isRecord(value) {
26
+ return typeof value === 'object' && value !== null && !Array.isArray(value);
27
+ }
28
+ /**
29
+ * Returns the usable part of an imported style
30
+ *
31
+ * A key of FeatureStyle whose value fails its check is dropped; every other key is kept.
32
+ *
33
+ * @param value The style as read from the file
34
+ * @returns The style, or undefined when the value is not an object or nothing is left
35
+ */
36
+ export function sanitizeFeatureStyle(value) {
37
+ if (!isRecord(value))
38
+ return undefined;
39
+ const style = {};
40
+ let kept = 0;
41
+ for (const [key, entry] of Object.entries(value)) {
42
+ const check = STYLE_CHECKS.get(key);
43
+ if (check && !check(entry))
44
+ continue;
45
+ setOwnProperty(style, key, entry);
46
+ kept++;
47
+ }
48
+ return kept > 0 ? style : undefined;
49
+ }