@element-editor/ui 0.0.0-stage → 0.2.1

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 (244) hide show
  1. package/AGENTS.md +65 -0
  2. package/LICENSE +21 -0
  3. package/README.md +46 -2
  4. package/dist/BooleanOperations-BRO7NHUY.js +111 -0
  5. package/dist/BooleanOperations-C2uOHRu3.cjs +1 -0
  6. package/dist/DataTable-B-2VjBEz.cjs +2 -0
  7. package/dist/DataTable-CS-3dIqY.js +510 -0
  8. package/dist/DataTablePanel-58LwzXQR.cjs +1 -0
  9. package/dist/DataTablePanel-DDFUmMaM.js +208 -0
  10. package/dist/EditToolbarBtn-Ch9HCLHq.cjs +3 -0
  11. package/dist/EditToolbarBtn-SR4xHd8G.js +378 -0
  12. package/dist/FeatureEditModal-Cc8N6vei.cjs +1 -0
  13. package/dist/FeatureEditModal-Dr10p3nE.js +77 -0
  14. package/dist/FeatureList-Bo9w9nre.js +520 -0
  15. package/dist/FeatureList-VRYesXCq.cjs +1 -0
  16. package/dist/FeatureRowContextMenu-CtBqdC1j.cjs +1 -0
  17. package/dist/FeatureRowContextMenu-DCUIiDwc.js +130 -0
  18. package/dist/GeoJSONModal-BV9Tamf4.js +886 -0
  19. package/dist/GeoJSONModal-Dd-nBufy.cjs +9 -0
  20. package/dist/SchemaEditor-B4L17K1e.cjs +1 -0
  21. package/dist/SchemaEditor-ryoTgaLb.js +293 -0
  22. package/dist/SchemaModal-DvMbWskS.js +95 -0
  23. package/dist/SchemaModal-gAuDkd-L.cjs +1 -0
  24. package/dist/SettingsModal-BScVTjpn.js +237 -0
  25. package/dist/SettingsModal-CqaSFxxR.cjs +1 -0
  26. package/dist/ShortcutsModal-D1Y2bGT8.cjs +1 -0
  27. package/dist/ShortcutsModal-ozuS2Ysb.js +299 -0
  28. package/dist/components/ActiveDrawingToolbar.d.cts +1 -0
  29. package/dist/components/ActiveDrawingToolbar.d.ts +1 -0
  30. package/dist/components/BasemapPicker.d.cts +26 -0
  31. package/dist/components/BasemapPicker.d.ts +26 -0
  32. package/dist/components/BooleanOperations.d.cts +1 -0
  33. package/dist/components/BooleanOperations.d.ts +1 -0
  34. package/dist/components/BufferPanel.d.cts +1 -0
  35. package/dist/components/BufferPanel.d.ts +1 -0
  36. package/dist/components/DataTable.d.cts +9 -0
  37. package/dist/components/DataTable.d.ts +9 -0
  38. package/dist/components/DataTablePanel.d.cts +10 -0
  39. package/dist/components/DataTablePanel.d.ts +10 -0
  40. package/dist/components/EditingToolbar.d.cts +1 -0
  41. package/dist/components/EditingToolbar.d.ts +1 -0
  42. package/dist/components/ElementEditorErrorBoundary.d.cts +28 -0
  43. package/dist/components/ElementEditorErrorBoundary.d.ts +28 -0
  44. package/dist/components/ElementEditorUIProvider.d.cts +50 -0
  45. package/dist/components/ElementEditorUIProvider.d.ts +50 -0
  46. package/dist/components/FeatureMapContextMenu.d.cts +23 -0
  47. package/dist/components/FeatureMapContextMenu.d.ts +23 -0
  48. package/dist/components/FitBoundsButton.d.cts +6 -0
  49. package/dist/components/FitBoundsButton.d.ts +6 -0
  50. package/dist/components/FloatingToolbar.d.cts +3 -0
  51. package/dist/components/FloatingToolbar.d.ts +3 -0
  52. package/dist/components/LocateButton.d.cts +11 -0
  53. package/dist/components/LocateButton.d.ts +11 -0
  54. package/dist/components/ReadonlyBanner.d.cts +1 -0
  55. package/dist/components/ReadonlyBanner.d.ts +1 -0
  56. package/dist/components/ShortcutsModal.d.cts +1 -0
  57. package/dist/components/ShortcutsModal.d.ts +1 -0
  58. package/dist/components/SimplifyPanel.d.cts +1 -0
  59. package/dist/components/SimplifyPanel.d.ts +1 -0
  60. package/dist/components/SmoothPanel.d.cts +1 -0
  61. package/dist/components/SmoothPanel.d.ts +1 -0
  62. package/dist/components/UndoRedoToolbar.d.cts +20 -0
  63. package/dist/components/UndoRedoToolbar.d.ts +20 -0
  64. package/dist/components/VertexSelectionBar.d.cts +12 -0
  65. package/dist/components/VertexSelectionBar.d.ts +12 -0
  66. package/dist/components/ZoomIndicator.d.cts +15 -0
  67. package/dist/components/ZoomIndicator.d.ts +15 -0
  68. package/dist/components/dialogs/DynamicFieldRenderer.d.cts +11 -0
  69. package/dist/components/dialogs/DynamicFieldRenderer.d.ts +11 -0
  70. package/dist/components/dialogs/SettingsModal.d.cts +1 -0
  71. package/dist/components/dialogs/SettingsModal.d.ts +1 -0
  72. package/dist/components/lazyParts.d.cts +12 -0
  73. package/dist/components/lazyParts.d.ts +12 -0
  74. package/dist/components/sidebar/FeatureEditModal.d.cts +6 -0
  75. package/dist/components/sidebar/FeatureEditModal.d.ts +6 -0
  76. package/dist/components/sidebar/FeatureList.d.cts +4 -0
  77. package/dist/components/sidebar/FeatureList.d.ts +4 -0
  78. package/dist/components/sidebar/FeatureRow.d.cts +38 -0
  79. package/dist/components/sidebar/FeatureRow.d.ts +38 -0
  80. package/dist/components/sidebar/FeatureRowContextMenu.d.cts +12 -0
  81. package/dist/components/sidebar/FeatureRowContextMenu.d.ts +12 -0
  82. package/dist/components/sidebar/FeatureSidePanel.d.cts +8 -0
  83. package/dist/components/sidebar/FeatureSidePanel.d.ts +8 -0
  84. package/dist/components/sidebar/GeoJSONModal.d.cts +5 -0
  85. package/dist/components/sidebar/GeoJSONModal.d.ts +5 -0
  86. package/dist/components/sidebar/GroupRow.d.cts +21 -0
  87. package/dist/components/sidebar/GroupRow.d.ts +21 -0
  88. package/dist/components/sidebar/HideLayersToggle.d.cts +2 -0
  89. package/dist/components/sidebar/HideLayersToggle.d.ts +2 -0
  90. package/dist/components/sidebar/LayersPanel.d.cts +5 -0
  91. package/dist/components/sidebar/LayersPanel.d.ts +5 -0
  92. package/dist/components/sidebar/PartSubRow.d.cts +9 -0
  93. package/dist/components/sidebar/PartSubRow.d.ts +9 -0
  94. package/dist/components/sidebar/SchemaEditor.d.cts +4 -0
  95. package/dist/components/sidebar/SchemaEditor.d.ts +4 -0
  96. package/dist/components/sidebar/SchemaModal.d.cts +5 -0
  97. package/dist/components/sidebar/SchemaModal.d.ts +5 -0
  98. package/dist/components/sidebar/codeDock.d.cts +21 -0
  99. package/dist/components/sidebar/codeDock.d.ts +21 -0
  100. package/dist/components/ui/Button.d.cts +9 -0
  101. package/dist/components/ui/Button.d.ts +9 -0
  102. package/dist/components/ui/CloseButton.d.cts +6 -0
  103. package/dist/components/ui/CloseButton.d.ts +6 -0
  104. package/dist/components/ui/ContextMenu.d.cts +28 -0
  105. package/dist/components/ui/ContextMenu.d.ts +28 -0
  106. package/dist/components/ui/EditToolbarBtn.d.cts +13 -0
  107. package/dist/components/ui/EditToolbarBtn.d.ts +13 -0
  108. package/dist/components/ui/ElementToaster.d.cts +3 -0
  109. package/dist/components/ui/ElementToaster.d.ts +3 -0
  110. package/dist/components/ui/GeometryTypeIcon.d.cts +7 -0
  111. package/dist/components/ui/GeometryTypeIcon.d.ts +7 -0
  112. package/dist/components/ui/IconButton.d.cts +28 -0
  113. package/dist/components/ui/IconButton.d.ts +28 -0
  114. package/dist/components/ui/Input.d.cts +14 -0
  115. package/dist/components/ui/Input.d.ts +14 -0
  116. package/dist/components/ui/JsonCode.d.cts +4 -0
  117. package/dist/components/ui/JsonCode.d.ts +4 -0
  118. package/dist/components/ui/Kbd.d.cts +16 -0
  119. package/dist/components/ui/Kbd.d.ts +16 -0
  120. package/dist/components/ui/NoFeaturesEmptyState.d.cts +1 -0
  121. package/dist/components/ui/NoFeaturesEmptyState.d.ts +1 -0
  122. package/dist/components/ui/SearchDropdown.d.cts +28 -0
  123. package/dist/components/ui/SearchDropdown.d.ts +28 -0
  124. package/dist/components/ui/ToolButton.d.cts +19 -0
  125. package/dist/components/ui/ToolButton.d.ts +19 -0
  126. package/dist/components/ui/Tooltip.d.cts +12 -0
  127. package/dist/components/ui/Tooltip.d.ts +12 -0
  128. package/dist/components/ui/panelHeader.d.cts +2 -0
  129. package/dist/components/ui/panelHeader.d.ts +2 -0
  130. package/dist/components/ui/resizeEdge.d.cts +4 -0
  131. package/dist/components/ui/resizeEdge.d.ts +4 -0
  132. package/dist/contexts/ElementEditorConfigContext.d.cts +351 -0
  133. package/dist/contexts/ElementEditorConfigContext.d.ts +351 -0
  134. package/dist/contexts/EventContext.d.cts +69 -0
  135. package/dist/contexts/EventContext.d.ts +69 -0
  136. package/dist/contexts/MapControllerContext.d.cts +24 -0
  137. package/dist/contexts/MapControllerContext.d.ts +24 -0
  138. package/dist/contexts/ShortcutConfigContext.d.cts +16 -0
  139. package/dist/contexts/ShortcutConfigContext.d.ts +16 -0
  140. package/dist/contexts/ThemeContext.d.cts +12 -0
  141. package/dist/contexts/ThemeContext.d.ts +12 -0
  142. package/dist/element-editor-ui.cjs +1 -0
  143. package/dist/element-editor-ui.es.js +102 -0
  144. package/dist/geometryWorker-CCwg4tNC.cjs +1 -0
  145. package/dist/geometryWorker-DgQCFSmD.js +25 -0
  146. package/dist/hooks/dragShield.d.cts +7 -0
  147. package/dist/hooks/dragShield.d.ts +7 -0
  148. package/dist/hooks/themeInputs.d.cts +14 -0
  149. package/dist/hooks/themeInputs.d.ts +14 -0
  150. package/dist/hooks/useAccentPalette.d.cts +15 -0
  151. package/dist/hooks/useAccentPalette.d.ts +15 -0
  152. package/dist/hooks/useAccentStyle.d.cts +39 -0
  153. package/dist/hooks/useAccentStyle.d.ts +39 -0
  154. package/dist/hooks/useAdapterControls.d.cts +280 -0
  155. package/dist/hooks/useAdapterControls.d.ts +280 -0
  156. package/dist/hooks/useBalancedWrap.d.cts +8 -0
  157. package/dist/hooks/useBalancedWrap.d.ts +8 -0
  158. package/dist/hooks/useContextMenu.d.cts +11 -0
  159. package/dist/hooks/useContextMenu.d.ts +11 -0
  160. package/dist/hooks/useDataChangeSubscription.d.cts +9 -0
  161. package/dist/hooks/useDataChangeSubscription.d.ts +9 -0
  162. package/dist/hooks/useDragWindow.d.cts +9 -0
  163. package/dist/hooks/useDragWindow.d.ts +9 -0
  164. package/dist/hooks/useFocusTrap.d.cts +7 -0
  165. package/dist/hooks/useFocusTrap.d.ts +7 -0
  166. package/dist/hooks/useGeoJSONDrop.d.cts +40 -0
  167. package/dist/hooks/useGeoJSONDrop.d.ts +40 -0
  168. package/dist/hooks/useGeoJSONExport.d.cts +69 -0
  169. package/dist/hooks/useGeoJSONExport.d.ts +69 -0
  170. package/dist/hooks/useGeoJSONFileImport.d.cts +24 -0
  171. package/dist/hooks/useGeoJSONFileImport.d.ts +24 -0
  172. package/dist/hooks/useInlineRename.d.cts +26 -0
  173. package/dist/hooks/useInlineRename.d.ts +26 -0
  174. package/dist/hooks/useJumpToFeature.d.cts +3 -0
  175. package/dist/hooks/useJumpToFeature.d.ts +3 -0
  176. package/dist/hooks/useKeyboardShortcuts.d.cts +9 -0
  177. package/dist/hooks/useKeyboardShortcuts.d.ts +9 -0
  178. package/dist/hooks/useNominatim.d.cts +24 -0
  179. package/dist/hooks/useNominatim.d.ts +24 -0
  180. package/dist/hooks/usePanelOffset.d.cts +14 -0
  181. package/dist/hooks/usePanelOffset.d.ts +14 -0
  182. package/dist/hooks/useResizablePanel.d.cts +4 -0
  183. package/dist/hooks/useResizablePanel.d.ts +4 -0
  184. package/dist/hooks/useRootTokens.d.cts +27 -0
  185. package/dist/hooks/useRootTokens.d.ts +27 -0
  186. package/dist/hooks/useSearchState.d.cts +23 -0
  187. package/dist/hooks/useSearchState.d.ts +23 -0
  188. package/dist/hooks/useServiceAttribution.d.cts +13 -0
  189. package/dist/hooks/useServiceAttribution.d.ts +13 -0
  190. package/dist/hooks/useWindowEscape.d.cts +25 -0
  191. package/dist/hooks/useWindowEscape.d.ts +25 -0
  192. package/dist/hooks/useWindowFocus.d.cts +4 -0
  193. package/dist/hooks/useWindowFocus.d.ts +4 -0
  194. package/dist/hooks/useWorkerGeometryPreview.d.cts +22 -0
  195. package/dist/hooks/useWorkerGeometryPreview.d.ts +22 -0
  196. package/dist/index-CILw1Du5.js +3165 -0
  197. package/dist/index-DG4wEjGj.cjs +1 -0
  198. package/dist/index.d.cts +89 -0
  199. package/dist/index.d.ts +89 -0
  200. package/dist/internal.cjs +1 -0
  201. package/dist/internal.d.cts +16 -0
  202. package/dist/internal.d.ts +16 -0
  203. package/dist/internal.es.js +42 -0
  204. package/dist/primitives.cjs +1 -0
  205. package/dist/primitives.d.cts +19 -0
  206. package/dist/primitives.d.ts +19 -0
  207. package/dist/primitives.es.js +17 -0
  208. package/dist/store/StoreContext.d.cts +17 -0
  209. package/dist/store/StoreContext.d.ts +17 -0
  210. package/dist/types/events.d.cts +95 -0
  211. package/dist/types/events.d.ts +95 -0
  212. package/dist/useAccentStyle-CPo2XqAn.js +412 -0
  213. package/dist/useAccentStyle-hsGvyHZc.cjs +1 -0
  214. package/dist/useAdapterControls-BBObhzVX.cjs +1 -0
  215. package/dist/useAdapterControls-DVjkwRZ_.js +691 -0
  216. package/dist/useContextMenu-DJ2Cti85.js +10 -0
  217. package/dist/useContextMenu-DbxMvb1s.cjs +1 -0
  218. package/dist/useFocusTrap-BBjPCfDR.cjs +1 -0
  219. package/dist/useFocusTrap-CKxKT8De.js +25 -0
  220. package/dist/useJumpToFeature-Bdz2hqOC.js +16 -0
  221. package/dist/useJumpToFeature-LwjxGzfy.cjs +1 -0
  222. package/dist/useWindowFocus-DuQVjnHE.js +80 -0
  223. package/dist/useWindowFocus-EemgNOuz.cjs +1 -0
  224. package/dist/utils/booleanValue.d.cts +4 -0
  225. package/dist/utils/booleanValue.d.ts +4 -0
  226. package/dist/utils/clipboardError.d.cts +3 -0
  227. package/dist/utils/clipboardError.d.ts +3 -0
  228. package/dist/utils/download.d.cts +42 -0
  229. package/dist/utils/download.d.ts +42 -0
  230. package/dist/utils/geojsonDocument.d.cts +168 -0
  231. package/dist/utils/geojsonDocument.d.ts +168 -0
  232. package/dist/utils/geometryWorkerClient.d.cts +6 -0
  233. package/dist/utils/geometryWorkerClient.d.ts +6 -0
  234. package/dist/utils/layerOrder.d.cts +9 -0
  235. package/dist/utils/layerOrder.d.ts +9 -0
  236. package/dist/utils/lazyWithPreload.d.cts +24 -0
  237. package/dist/utils/lazyWithPreload.d.ts +24 -0
  238. package/dist/utils/lineSmooth.d.cts +7 -0
  239. package/dist/utils/lineSmooth.d.ts +7 -0
  240. package/dist/utils/platform.d.cts +2 -0
  241. package/dist/utils/platform.d.ts +2 -0
  242. package/dist/workers/geometryWorker.d.cts +1 -0
  243. package/dist/workers/geometryWorker.d.ts +1 -0
  244. package/package.json +133 -3
@@ -0,0 +1,280 @@
1
+ import { FeatureCollection, FeatureCollectionInput, FeaturePatch, FlyToOptions, GeoJSONFeature, GeoJSONFeatureInput, Schema } from '@element-editor/core';
2
+ import { DrawTool } from '../contexts/ElementEditorConfigContext.js';
3
+ /**
4
+ * `useAdapterControls` — single source of truth for the editor-shell wiring
5
+ * shared by `@element-editor/adapter-leaflet`, `@element-editor/adapter-maplibre`, and
6
+ * `@element-editor/react`.
7
+ *
8
+ * Owns:
9
+ * - prop → store sync (readonly / tools / maxFeatures / layout; network-disabled tools)
10
+ * - one-time mounts (initialData, schema)
11
+ * - data-change subscription (onChange / per-feature callbacks / selection)
12
+ * - onZoomChange + onFeatureSelect subscriptions
13
+ * - the FC-shaped imperative API (return value — caller wires it through
14
+ * `useImperativeHandle`)
15
+ *
16
+ * Caller still owns: bounds / maxBounds (different APIs across map libs),
17
+ * the map-bridge wiring, the layer tree, and any wrapper-only concerns
18
+ * (slots, tile layer, theme persistence, dev affordances).
19
+ */
20
+ export interface ImportResult {
21
+ /** Features skipped due to unsupported geometry type. */
22
+ skipped: number;
23
+ /** Features skipped because their id collided with an existing feature. */
24
+ duplicates: number;
25
+ /** True if the import was capped by `maxFeatures` / internal safety limits. */
26
+ truncated: boolean;
27
+ }
28
+ /**
29
+ * Options of the ref's data-changing methods (`addFeature`, `updateFeature(s)`, `removeFeatures`).
30
+ */
31
+ export interface MutationOptions {
32
+ /**
33
+ * Default `true`: the change is one undo step, like the same edit made by the user.
34
+ * `false` (e.g. applying a change from your server): no undo step, and the change is also
35
+ * applied to every undo/redo snapshot, so undoing an earlier user edit doesn't revert it.
36
+ */
37
+ undoable?: boolean;
38
+ }
39
+ /** Options of `ref.setFeatureCollection`. */
40
+ export interface SetFeatureCollectionOptions {
41
+ /**
42
+ * Default `false`: the load fires `onChange` (and `onFeatureAdd` / `onFeatureUpdate` /
43
+ * `onFeatureDelete`) like any other change. `true`: those callbacks don't fire for this load,
44
+ * so data you just fetched from your backend isn't saved straight back. `onSelectionChange`
45
+ * still fires when the load clears a selection.
46
+ */
47
+ silent?: boolean;
48
+ /**
49
+ * Default `true`: the load is one undo step (undo restores the previous data). `false`: no undo
50
+ * step, and the undo/redo history is cleared, so the user can't undo back past the loaded data
51
+ * (what `initialData` does).
52
+ */
53
+ undoable?: boolean;
54
+ }
55
+ /** What `ref.validate()` returns. */
56
+ export interface ValidationReport {
57
+ /** `true` when no feature has a validation error. */
58
+ valid: boolean;
59
+ /**
60
+ * Error messages per feature id, only for features that have errors (e.g.
61
+ * `'Missing required property: Owner'`): the same object `onValidationError` receives.
62
+ */
63
+ errors: Record<string, string[]>;
64
+ }
65
+ /**
66
+ * Imperative handle of `<ElementEditor ref>` and both adapters' `<ElementEditorControls ref>`.
67
+ * Coordinates are GeoJSON order, `[lng, lat]`, unless a method says otherwise.
68
+ * Map methods (`flyTo`, `setZoom`, `fitBounds`, `select`'s `fit`) do nothing until the map has mounted.
69
+ *
70
+ * Data-changing methods go through the same store actions as the UI: `maxFeatures`, schema
71
+ * validation, undo and the `onChange` / `onFeature*` / `onSelectionChange` callbacks behave as
72
+ * for the user's own edits (callbacks fire synchronously, before the method returns). They work
73
+ * in `readonly` mode too (the host app is in charge); only `setTool` is refused there.
74
+ *
75
+ * `TMap` is the engine's map type: `maplibregl.Map` on `@element-editor/react` and
76
+ * `@element-editor/adapter-maplibre`, `L.Map` on `@element-editor/react/leaflet` and
77
+ * `@element-editor/adapter-leaflet`.
78
+ */
79
+ export interface ElementEditorImperativeAPI<TMap = unknown> {
80
+ /**
81
+ * Snapshot of the current data as a FeatureCollection: every feature (hidden ones included,
82
+ * internal validation state stripped) plus `metadata.schemas` / `metadata.groups`.
83
+ */
84
+ getFeatureCollection: () => FeatureCollection;
85
+ /**
86
+ * One feature by id, as `getFeatureCollection()` would return it (hidden features included), or
87
+ * `null` for an unknown id.
88
+ */
89
+ getFeature: (id: string) => GeoJSONFeature | null;
90
+ /**
91
+ * Replaces all data with `data` (like `importGeoJSON(data, 'replace')`). Plain GeoJSON is fine:
92
+ * missing ids get UUIDs, no `metadata` means the default schema. Features without a usable
93
+ * geometry (`geometry: null`, unknown types) are skipped and reported through `onError` /
94
+ * the `error` event.
95
+ *
96
+ * By default this fires `onChange` (and `onFeatureAdd` / `onFeatureDelete`) like any change and is
97
+ * one undo step. When you load data from your backend and save it in `onChange`, pass
98
+ * `{ silent: true }` so the load isn't saved straight back (see `SetFeatureCollectionOptions`).
99
+ *
100
+ * ```ts
101
+ * const fc = await (await fetch('/api/map')).json()
102
+ * ref.current?.setFeatureCollection(fc, { silent: true, undoable: false })
103
+ * ```
104
+ */
105
+ setFeatureCollection: (data: FeatureCollectionInput, options?: SetFeatureCollectionOptions) => void;
106
+ /** The current data serialised as a GeoJSON string (what "Export" downloads). */
107
+ exportGeoJSON: () => string;
108
+ /** Triggers a browser download of the current data. Only `'geojson'` is supported. */
109
+ exportAs: (format: 'geojson') => void;
110
+ /**
111
+ * Imports a FeatureCollection (or anything parseable as one). `'replace'` (default) swaps the
112
+ * data, `'merge'` appends. It is one undo step (undo restores the previous features, schemas and
113
+ * groups; no file backup). Returns counts of skipped (unsupported
114
+ * geometry) / duplicate (repeated id) features and whether the import was truncated
115
+ * (`maxFeatures` or the internal 50,000-feature limit).
116
+ */
117
+ importGeoJSON: (raw: FeatureCollectionInput | unknown, mode?: 'replace' | 'merge') => ImportResult;
118
+ /**
119
+ * Updates many features in one commit: one store update, one `onChange`, and `onFeatureUpdate`
120
+ * once per feature whose geometry or properties changed. Each `patch` may set `properties`
121
+ * (replaces the whole object), `geometry`, `schemaId` or `hidden`; features are re-validated
122
+ * against their schema. The batch is one undo step (see `MutationOptions.undoable`). Unknown ids
123
+ * and malformed patches are skipped (with a development warning).
124
+ *
125
+ * ```ts
126
+ * ref.current.updateFeatures(ids.map((id) => ({ id, patch: { properties: { ...props(id), status: 'done' } } })))
127
+ * ```
128
+ */
129
+ updateFeatures: (updates: ReadonlyArray<{
130
+ id: string;
131
+ patch: FeaturePatch;
132
+ }>, options?: MutationOptions) => void;
133
+ /**
134
+ * Adds a feature and returns it as stored (with its `id`; a missing id gets a UUID), or `null`
135
+ * when nothing was added: the geometry isn't valid GeoJSON, the id is already used (both warn
136
+ * in development), or `maxFeatures` is reached (reported like a user add). The feature goes on
137
+ * top of the layer list; the selection is left alone. `groupId` is kept only if that group exists.
138
+ * Fires `onFeatureAdd` and `onChange`.
139
+ */
140
+ addFeature: (feature: GeoJSONFeatureInput, options?: MutationOptions) => GeoJSONFeature | null;
141
+ /**
142
+ * Updates one feature. `patch` may set `properties` (replaces the whole object), `geometry`,
143
+ * `schemaId` or `hidden`; other keys are ignored. The feature is re-validated against its schema
144
+ * (schema errors don't block the write). Returns `false`, changing nothing, for an unknown id or
145
+ * a malformed patch (both warn in development). Fires `onFeatureUpdate` and `onChange`.
146
+ */
147
+ updateFeature: (id: string, patch: FeaturePatch, options?: MutationOptions) => boolean;
148
+ /**
149
+ * Removes the features with these ids in one undo step and returns how many were removed
150
+ * (unknown ids are skipped, with a development warning). Removed ids leave the selection.
151
+ * Fires `onFeatureDelete` per feature and `onChange` once.
152
+ */
153
+ removeFeatures: (ids: string[], options?: MutationOptions) => number;
154
+ /** Ids of the selected features (a copy). */
155
+ getSelection: () => string[];
156
+ /**
157
+ * Replaces the selection with these features (`[]` clears it) and fires `onSelectionChange`.
158
+ * Unknown ids, group ids and hidden features (or features in a hidden group) are left out, with a
159
+ * development warning. `fit: true` also fits the map to the selected features.
160
+ */
161
+ select: (ids: string[], options?: {
162
+ fit?: boolean;
163
+ }) => void;
164
+ /**
165
+ * Turns a drawing tool on, as its toolbar button does (an unfinished shape of another tool is
166
+ * discarded); `null` turns the active tool off. Returns `false`, changing nothing, when the tool
167
+ * isn't available: unknown or `'search'`, left out by `tools`, `maxFeatures` reached (tools that
168
+ * add features), or `readonly` (every tool but `'measure'`, which the readonly toolbar keeps).
169
+ */
170
+ setTool: (tool: DrawTool | null) => boolean;
171
+ /**
172
+ * The drawing tool that is on (as `setTool` takes it), or `null` when none is. Shape operations
173
+ * (cut, slice, simplify, smooth, buffer) aren't tools: `null` while they run.
174
+ */
175
+ getTool: () => DrawTool | null;
176
+ /** `true` when `undo()` would change something (there is an edit to undo). */
177
+ canUndo: () => boolean;
178
+ /** `true` when `redo()` would change something (there is an undone edit to redo). */
179
+ canRedo: () => boolean;
180
+ /**
181
+ * Validates every feature against its schema (required fields, number `min` / `max`) and its
182
+ * geometry (zero-area polygons), and returns the result. Changes nothing and calls no callback:
183
+ * use it to check before your own save, or to show errors. `submit()` runs the same check.
184
+ *
185
+ * ```ts
186
+ * const { valid, errors } = ref.current!.validate()
187
+ * if (!valid) ref.current!.select(Object.keys(errors), { fit: true })
188
+ * ```
189
+ */
190
+ validate: () => ValidationReport;
191
+ /**
192
+ * The underlying map: `maplibregl.Map` or `L.Map` (see `TMap`), or `null` until the map has
193
+ * mounted (the MapLibre drop-in creates it once its basemap style has loaded).
194
+ *
195
+ * On a MapLibre map, switch basemaps with the `basemap` prop or `setBasemap`: they keep your
196
+ * layers. After your own `map.setStyle()` Element restores its own layers; re-add yours on `style.load`.
197
+ */
198
+ getMap: () => TMap | null;
199
+ /**
200
+ * Animates the map to a centre and zoom.
201
+ *
202
+ * - `flyTo({ center: [lng, lat], zoom? })` — preferred; GeoJSON order. Zoom defaults to 15.
203
+ * - `flyTo([lat, lng], zoom?)` — deprecated `[lat, lng]` tuple form; still works, warns once
204
+ * in development.
205
+ */
206
+ flyTo: {
207
+ (options: FlyToOptions): void;
208
+ /** @deprecated `[lat, lng]` order. Use `flyTo({ center: [lng, lat], zoom })`. */
209
+ (latlng: [number, number], zoom?: number): void;
210
+ };
211
+ /**
212
+ * Sets the zoom immediately (no animation), clamped to the map's min/max zoom.
213
+ * Returns `false` when the map is not mounted yet (nothing happened), `true` otherwise.
214
+ */
215
+ setZoom: (zoom: number) => boolean;
216
+ /**
217
+ * Animates the map to fit a box, with padding, never zooming in past 16. Accepts:
218
+ *
219
+ * - a GeoJSON bbox `[minLng, minLat, maxLng, maxLat]` (= `[west, south, east, north]`), or
220
+ * - an array of `[lng, lat]` points (fits their bounding box).
221
+ *
222
+ * Empty input or input without finite coordinates is ignored.
223
+ */
224
+ fitBounds: (target: [number, number][] | [number, number, number, number]) => void;
225
+ /**
226
+ * Validates every feature (as `validate()` does), then submits. Returns `false` if any feature
227
+ * has validation errors: `onValidationError` is called with them (keyed by feature id) and
228
+ * `onSubmit` is not. Returns `true` when the data is valid: `onSubmit` (if set) is called
229
+ * with the current FeatureCollection.
230
+ */
231
+ submit: () => boolean;
232
+ /** Undoes the last edit (no-op when there is nothing to undo; see `canUndo`). */
233
+ undo: () => void;
234
+ /** Redoes the last undone edit (no-op when there is nothing to redo; see `canRedo`). */
235
+ redo: () => void;
236
+ /** Deselects all features. */
237
+ clearSelection: () => void;
238
+ }
239
+ export interface UseAdapterControlsOptions {
240
+ /**
241
+ * Plain GeoJSON is fine (see `FeatureCollectionInput`); a single Feature is wrapped in a collection.
242
+ * Applied on mount. A value that arrives later (`null` / `undefined` → data, e.g. after a fetch) is
243
+ * applied once too, if the editor is still empty and unedited; any other change is ignored, with a
244
+ * development warning.
245
+ */
246
+ initialData?: FeatureCollectionInput | GeoJSONFeatureInput | null;
247
+ schema?: Schema;
248
+ layout?: 'panel' | 'minimal' | 'split';
249
+ readonly?: boolean;
250
+ tools?: DrawTool[] | null;
251
+ maxFeatures?: number;
252
+ /**
253
+ * The map engine; the adapters pass it. With it, the tools `config.network` turns off are
254
+ * synced to `uiStore.unavailableTools` (the Picker needs Overpass only on Leaflet).
255
+ */
256
+ engine?: 'leaflet' | 'maplibre';
257
+ onChange?: (data: FeatureCollection) => void;
258
+ onSubmit?: (data: FeatureCollection) => void;
259
+ onValidationError?: (errors: Record<string, string[]>) => void;
260
+ onFeatureAdd?: (feature: GeoJSONFeature) => void;
261
+ onFeatureUpdate?: (id: string, feature: GeoJSONFeature) => void;
262
+ onFeatureDelete?: (id: string) => void;
263
+ onSelectionChange?: (ids: string[]) => void;
264
+ onFeatureSelect?: (feature: GeoJSONFeature | null) => void;
265
+ onZoomChange?: (zoom: number) => void;
266
+ /** Called with the tool that turned on (as `ref.getTool()` reports it), or `null` when it turned off. */
267
+ onToolChange?: (tool: DrawTool | null) => void;
268
+ /**
269
+ * @internal Called after `initialData` was applied: `late` is true for data that arrived after
270
+ * mount. The drop-in uses it to fit the late data.
271
+ */
272
+ onInitialDataApplied?: (data: FeatureCollectionInput, late: boolean) => void;
273
+ }
274
+ /** The tools `network` turns off: no routing → Route, no geocoder → search, no Overpass → Picker on Leaflet (MapLibre still picks from the vector tiles). */
275
+ export declare function networkUnavailableTools(network: {
276
+ routing?: unknown;
277
+ nominatim?: unknown;
278
+ overpass?: unknown;
279
+ }, engine: 'leaflet' | 'maplibre'): string[];
280
+ export declare function useAdapterControls<TMap = unknown>(opts: UseAdapterControlsOptions): ElementEditorImperativeAPI<TMap>;
@@ -0,0 +1,8 @@
1
+ import { RefObject } from 'react';
2
+ /**
3
+ * `text-wrap: balance` for a `flex-wrap` toolbar: when its buttons don't fit
4
+ * on one row, it's narrowed to the least width that still needs no more rows,
5
+ * so a narrow screen shows 4 + 4 buttons rather than 7 + a lone Delete.
6
+ * Re-runs when the room around it or `key` (what the toolbar holds) changes.
7
+ */
8
+ export declare function useBalancedWrap(ref: RefObject<HTMLElement | null>, key: unknown): void;
@@ -0,0 +1,8 @@
1
+ import { RefObject } from 'react';
2
+ /**
3
+ * `text-wrap: balance` for a `flex-wrap` toolbar: when its buttons don't fit
4
+ * on one row, it's narrowed to the least width that still needs no more rows,
5
+ * so a narrow screen shows 4 + 4 buttons rather than 7 + a lone Delete.
6
+ * Re-runs when the room around it or `key` (what the toolbar holds) changes.
7
+ */
8
+ export declare function useBalancedWrap(ref: RefObject<HTMLElement | null>, key: unknown): void;
@@ -0,0 +1,11 @@
1
+ interface ContextMenuState<T> {
2
+ x: number;
3
+ y: number;
4
+ data: T;
5
+ }
6
+ export declare function useContextMenu<T>(): {
7
+ state: ContextMenuState<T> | null;
8
+ open: (x: number, y: number, data: T) => void;
9
+ close: () => void;
10
+ };
11
+ export {};
@@ -0,0 +1,11 @@
1
+ interface ContextMenuState<T> {
2
+ x: number;
3
+ y: number;
4
+ data: T;
5
+ }
6
+ export declare function useContextMenu<T>(): {
7
+ state: ContextMenuState<T> | null;
8
+ open: (x: number, y: number, data: T) => void;
9
+ close: () => void;
10
+ };
11
+ export {};
@@ -0,0 +1,9 @@
1
+ import { StoreApi } from 'zustand';
2
+ import { DataStore, DataChangeCallbacks } from '@element-editor/core';
3
+ /**
4
+ * React wrapper around `subscribeToDataChanges`. Owns the callback ref
5
+ * plumbing so hosts can pass a fresh object each render without resubscribing.
6
+ *
7
+ * The subscription only tears down when `store` itself changes.
8
+ */
9
+ export declare function useDataChangeSubscription(store: StoreApi<DataStore>, callbacks: DataChangeCallbacks): void;
@@ -0,0 +1,9 @@
1
+ import { StoreApi } from 'zustand';
2
+ import { DataStore, DataChangeCallbacks } from '@element-editor/core';
3
+ /**
4
+ * React wrapper around `subscribeToDataChanges`. Owns the callback ref
5
+ * plumbing so hosts can pass a fresh object each render without resubscribing.
6
+ *
7
+ * The subscription only tears down when `store` itself changes.
8
+ */
9
+ export declare function useDataChangeSubscription(store: StoreApi<DataStore>, callbacks: DataChangeCallbacks): void;
@@ -0,0 +1,9 @@
1
+ interface Position {
2
+ x: number;
3
+ y: number;
4
+ }
5
+ export declare function useDragWindow(storageKey: string, defaultPos: Position): {
6
+ pos: Position;
7
+ onHandleMouseDown: (e: React.MouseEvent) => void;
8
+ };
9
+ export {};
@@ -0,0 +1,9 @@
1
+ interface Position {
2
+ x: number;
3
+ y: number;
4
+ }
5
+ export declare function useDragWindow(storageKey: string, defaultPos: Position): {
6
+ pos: Position;
7
+ onHandleMouseDown: (e: React.MouseEvent) => void;
8
+ };
9
+ export {};
@@ -0,0 +1,7 @@
1
+ import { RefObject } from 'react';
2
+ /**
3
+ * Traps keyboard focus within a container element.
4
+ * Tab and Shift+Tab cycle through focusable elements without leaving the container.
5
+ * Automatically focuses the first focusable element on mount.
6
+ */
7
+ export declare function useFocusTrap(containerRef: RefObject<HTMLElement | null>, enabled?: boolean): void;
@@ -0,0 +1,7 @@
1
+ import { RefObject } from 'react';
2
+ /**
3
+ * Traps keyboard focus within a container element.
4
+ * Tab and Shift+Tab cycle through focusable elements without leaving the container.
5
+ * Automatically focuses the first focusable element on mount.
6
+ */
7
+ export declare function useFocusTrap(containerRef: RefObject<HTMLElement | null>, enabled?: boolean): void;
@@ -0,0 +1,40 @@
1
+ import { DragEvent as ReactDragEvent, ChangeEvent } from 'react';
2
+ import { FeatureCollection, ParseGeoJSONError } from '@element-editor/core';
3
+ export type GeoJSONDropError = {
4
+ kind: 'wrong-type';
5
+ file: File;
6
+ } | ParseGeoJSONError;
7
+ export interface UseGeoJSONDropOptions {
8
+ /** Called with the parsed FeatureCollection + original File handle. */
9
+ onImport: (fc: FeatureCollection, file: File) => void;
10
+ /** Called for any reject reason (wrong MIME/extension, too big, malformed, not a FC). */
11
+ onError?: (err: GeoJSONDropError) => void;
12
+ /** Max accepted byte length of the file. Defaults to core's DEFAULT_MAX_IMPORT_BYTES (100 MB). */
13
+ maxBytes?: number;
14
+ /** File extensions + MIME types to accept. Defaults to `.geojson`, `.json`, and their MIME equivalents. */
15
+ accept?: string[];
16
+ /** When true, drag/drop + file picker become no-ops and `isDragActive` stays false. */
17
+ disabled?: boolean;
18
+ }
19
+ export interface UseGeoJSONDropReturn {
20
+ getRootProps: () => {
21
+ onDragEnter: (e: ReactDragEvent) => void;
22
+ onDragOver: (e: ReactDragEvent) => void;
23
+ onDragLeave: (e: ReactDragEvent) => void;
24
+ onDrop: (e: ReactDragEvent) => void;
25
+ };
26
+ getInputProps: () => {
27
+ type: 'file';
28
+ accept: string;
29
+ style: {
30
+ display: 'none';
31
+ };
32
+ ref: (el: HTMLInputElement | null) => void;
33
+ onChange: (e: ChangeEvent<HTMLInputElement>) => void;
34
+ };
35
+ isDragActive: boolean;
36
+ isProcessing: boolean;
37
+ /** Programmatically open the native file picker. No-op when `disabled`. */
38
+ open: () => void;
39
+ }
40
+ export declare function useGeoJSONDrop(options: UseGeoJSONDropOptions): UseGeoJSONDropReturn;
@@ -0,0 +1,40 @@
1
+ import { DragEvent as ReactDragEvent, ChangeEvent } from 'react';
2
+ import { FeatureCollection, ParseGeoJSONError } from '@element-editor/core';
3
+ export type GeoJSONDropError = {
4
+ kind: 'wrong-type';
5
+ file: File;
6
+ } | ParseGeoJSONError;
7
+ export interface UseGeoJSONDropOptions {
8
+ /** Called with the parsed FeatureCollection + original File handle. */
9
+ onImport: (fc: FeatureCollection, file: File) => void;
10
+ /** Called for any reject reason (wrong MIME/extension, too big, malformed, not a FC). */
11
+ onError?: (err: GeoJSONDropError) => void;
12
+ /** Max accepted byte length of the file. Defaults to core's DEFAULT_MAX_IMPORT_BYTES (100 MB). */
13
+ maxBytes?: number;
14
+ /** File extensions + MIME types to accept. Defaults to `.geojson`, `.json`, and their MIME equivalents. */
15
+ accept?: string[];
16
+ /** When true, drag/drop + file picker become no-ops and `isDragActive` stays false. */
17
+ disabled?: boolean;
18
+ }
19
+ export interface UseGeoJSONDropReturn {
20
+ getRootProps: () => {
21
+ onDragEnter: (e: ReactDragEvent) => void;
22
+ onDragOver: (e: ReactDragEvent) => void;
23
+ onDragLeave: (e: ReactDragEvent) => void;
24
+ onDrop: (e: ReactDragEvent) => void;
25
+ };
26
+ getInputProps: () => {
27
+ type: 'file';
28
+ accept: string;
29
+ style: {
30
+ display: 'none';
31
+ };
32
+ ref: (el: HTMLInputElement | null) => void;
33
+ onChange: (e: ChangeEvent<HTMLInputElement>) => void;
34
+ };
35
+ isDragActive: boolean;
36
+ isProcessing: boolean;
37
+ /** Programmatically open the native file picker. No-op when `disabled`. */
38
+ open: () => void;
39
+ }
40
+ export declare function useGeoJSONDrop(options: UseGeoJSONDropOptions): UseGeoJSONDropReturn;
@@ -0,0 +1,69 @@
1
+ import { FeatureCollection } from '@element-editor/core';
2
+ /**
3
+ * Headless primitive for exporting the current Element state as GeoJSON.
4
+ * Symmetric to {@link useGeoJSONDrop}: the caller supplies a way to read the
5
+ * current FeatureCollection, the hook handles serialization, filename, Blob
6
+ * construction, and the programmatic anchor-click download.
7
+ *
8
+ * Three return shapes because different apps want different things:
9
+ * - `exportToFile()` — trigger a browser download (the 99% path).
10
+ * - `exportToString()` — POST the text to a backend, copy to clipboard, etc.
11
+ * - `exportToBlob()` — wrap in FormData, upload as multipart, pipe to a
12
+ * Worker, hand off to `navigator.share`, etc.
13
+ *
14
+ * All three share the same serialization and error handling.
15
+ */
16
+ export type GeoJSONExportError = {
17
+ kind: 'empty';
18
+ } | {
19
+ kind: 'serialization-error';
20
+ cause: Error;
21
+ };
22
+ export interface UseGeoJSONExportOptions {
23
+ /**
24
+ * Returns the FeatureCollection to export. Read lazily on every call so
25
+ * the hook doesn't re-render when features mutate. Typical usage:
26
+ * `() => ref.current?.getFeatureCollection()`.
27
+ */
28
+ getFeatureCollection: () => FeatureCollection | null | undefined;
29
+ /**
30
+ * File name (without extension) or a function of the FC. Default: "features".
31
+ * The `.geojson` extension is appended automatically.
32
+ */
33
+ filename?: string | ((fc: FeatureCollection) => string);
34
+ /**
35
+ * Called after the user has CONFIRMED the save (Chromium's
36
+ * `showSaveFilePicker` resolved with a chosen path). Great for toasts.
37
+ *
38
+ * Note: in Firefox / Safari the legacy `<a download>` flow has no
39
+ * confirmation signal, so `onExport` is NOT called there — a pre-mature
40
+ * "exported!" toast for an action the user may have cancelled in the OS
41
+ * Save dialog is worse than no toast. See {@link saveGeoJSONFile}.
42
+ */
43
+ onExport?: (fc: FeatureCollection, file: {
44
+ name: string;
45
+ bytes: number;
46
+ }) => void;
47
+ /** Called on empty FC or serialization errors. */
48
+ onError?: (err: GeoJSONExportError) => void;
49
+ /** Pretty-print indent. Default 2. Pass 0 for compact output. */
50
+ indent?: number;
51
+ /** When true, export methods become no-ops. Useful for readonly modes. */
52
+ disabled?: boolean;
53
+ }
54
+ export interface UseGeoJSONExportReturn {
55
+ /**
56
+ * Serialize, build a Blob, and trigger a browser download. Returns the
57
+ * suggested filename immediately (`null` only when there's nothing to
58
+ * export). Fires `onExport` ONLY after the user confirms the save in the
59
+ * OS dialog (Chromium); Firefox / Safari fall back to the legacy
60
+ * `<a download>` flow silently — see `onExport` doc above for why.
61
+ * Fires `onError({ kind: 'empty' })` when the FC has no features.
62
+ */
63
+ exportToFile: () => string | null;
64
+ /** Return the serialized GeoJSON text, or `null` if the FC is empty. */
65
+ exportToString: () => string | null;
66
+ /** Return a `Blob` of the serialized GeoJSON, or `null` if the FC is empty. */
67
+ exportToBlob: () => Blob | null;
68
+ }
69
+ export declare function useGeoJSONExport(options: UseGeoJSONExportOptions): UseGeoJSONExportReturn;
@@ -0,0 +1,69 @@
1
+ import { FeatureCollection } from '@element-editor/core';
2
+ /**
3
+ * Headless primitive for exporting the current Element state as GeoJSON.
4
+ * Symmetric to {@link useGeoJSONDrop}: the caller supplies a way to read the
5
+ * current FeatureCollection, the hook handles serialization, filename, Blob
6
+ * construction, and the programmatic anchor-click download.
7
+ *
8
+ * Three return shapes because different apps want different things:
9
+ * - `exportToFile()` — trigger a browser download (the 99% path).
10
+ * - `exportToString()` — POST the text to a backend, copy to clipboard, etc.
11
+ * - `exportToBlob()` — wrap in FormData, upload as multipart, pipe to a
12
+ * Worker, hand off to `navigator.share`, etc.
13
+ *
14
+ * All three share the same serialization and error handling.
15
+ */
16
+ export type GeoJSONExportError = {
17
+ kind: 'empty';
18
+ } | {
19
+ kind: 'serialization-error';
20
+ cause: Error;
21
+ };
22
+ export interface UseGeoJSONExportOptions {
23
+ /**
24
+ * Returns the FeatureCollection to export. Read lazily on every call so
25
+ * the hook doesn't re-render when features mutate. Typical usage:
26
+ * `() => ref.current?.getFeatureCollection()`.
27
+ */
28
+ getFeatureCollection: () => FeatureCollection | null | undefined;
29
+ /**
30
+ * File name (without extension) or a function of the FC. Default: "features".
31
+ * The `.geojson` extension is appended automatically.
32
+ */
33
+ filename?: string | ((fc: FeatureCollection) => string);
34
+ /**
35
+ * Called after the user has CONFIRMED the save (Chromium's
36
+ * `showSaveFilePicker` resolved with a chosen path). Great for toasts.
37
+ *
38
+ * Note: in Firefox / Safari the legacy `<a download>` flow has no
39
+ * confirmation signal, so `onExport` is NOT called there — a pre-mature
40
+ * "exported!" toast for an action the user may have cancelled in the OS
41
+ * Save dialog is worse than no toast. See {@link saveGeoJSONFile}.
42
+ */
43
+ onExport?: (fc: FeatureCollection, file: {
44
+ name: string;
45
+ bytes: number;
46
+ }) => void;
47
+ /** Called on empty FC or serialization errors. */
48
+ onError?: (err: GeoJSONExportError) => void;
49
+ /** Pretty-print indent. Default 2. Pass 0 for compact output. */
50
+ indent?: number;
51
+ /** When true, export methods become no-ops. Useful for readonly modes. */
52
+ disabled?: boolean;
53
+ }
54
+ export interface UseGeoJSONExportReturn {
55
+ /**
56
+ * Serialize, build a Blob, and trigger a browser download. Returns the
57
+ * suggested filename immediately (`null` only when there's nothing to
58
+ * export). Fires `onExport` ONLY after the user confirms the save in the
59
+ * OS dialog (Chromium); Firefox / Safari fall back to the legacy
60
+ * `<a download>` flow silently — see `onExport` doc above for why.
61
+ * Fires `onError({ kind: 'empty' })` when the FC has no features.
62
+ */
63
+ exportToFile: () => string | null;
64
+ /** Return the serialized GeoJSON text, or `null` if the FC is empty. */
65
+ exportToString: () => string | null;
66
+ /** Return a `Blob` of the serialized GeoJSON, or `null` if the FC is empty. */
67
+ exportToBlob: () => Blob | null;
68
+ }
69
+ export declare function useGeoJSONExport(options: UseGeoJSONExportOptions): UseGeoJSONExportReturn;
@@ -0,0 +1,24 @@
1
+ import { ErrorCode } from '@element-editor/core';
2
+ type ImportFn = (raw: unknown, mode: 'replace' | 'merge') => {
3
+ skipped: number;
4
+ duplicates: number;
5
+ };
6
+ /** Reads, parses and imports (replace) a GeoJSON file. Exported for tests; the UI uses `useGeoJSONFileImport`. */
7
+ export declare function importGeoJSONFromFile(file: File, importFn: ImportFn, countAfter: () => number): Promise<{
8
+ ok: true;
9
+ count: number;
10
+ skipped: number;
11
+ duplicates: number;
12
+ } | {
13
+ ok: false;
14
+ code: ErrorCode;
15
+ reason: string;
16
+ cause?: unknown;
17
+ }>;
18
+ /**
19
+ * The one user-initiated file import (Cmd+O, dropping a file on the map): replaces the data in one
20
+ * undo step (`maxFeatures` truncates and reports), fits the map to what was imported, and reports
21
+ * the result as events (toasts). Refused in readonly.
22
+ */
23
+ export declare function useGeoJSONFileImport(): (file: File) => Promise<void>;
24
+ export {};
@@ -0,0 +1,24 @@
1
+ import { ErrorCode } from '@element-editor/core';
2
+ type ImportFn = (raw: unknown, mode: 'replace' | 'merge') => {
3
+ skipped: number;
4
+ duplicates: number;
5
+ };
6
+ /** Reads, parses and imports (replace) a GeoJSON file. Exported for tests; the UI uses `useGeoJSONFileImport`. */
7
+ export declare function importGeoJSONFromFile(file: File, importFn: ImportFn, countAfter: () => number): Promise<{
8
+ ok: true;
9
+ count: number;
10
+ skipped: number;
11
+ duplicates: number;
12
+ } | {
13
+ ok: false;
14
+ code: ErrorCode;
15
+ reason: string;
16
+ cause?: unknown;
17
+ }>;
18
+ /**
19
+ * The one user-initiated file import (Cmd+O, dropping a file on the map): replaces the data in one
20
+ * undo step (`maxFeatures` truncates and reports), fits the map to what was imported, and reports
21
+ * the result as events (toasts). Refused in readonly.
22
+ */
23
+ export declare function useGeoJSONFileImport(): (file: File) => Promise<void>;
24
+ export {};