@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,691 @@
1
+ import { createContext as L, useState as W, useContext as v, useLayoutEffect as oe, useRef as p, useId as xe, useCallback as ee, useEffect as x, useMemo as he } from "react";
2
+ import { ElementEditorError as z, createDataStore as Ie, createUIStore as je, getFeatureCollectionBBox as Se, parseGeoJSONText as Ae, subscribeToDataChanges as Me, isGeometry as ye, validateFeature as Re } from "@element-editor/core";
3
+ import { warnOnce as C, httpErrorCode as Pe, normalizeFlyToTarget as De } from "@element-editor/core/internal";
4
+ import { a as Ue, d as Ge, e as Je, u as ie, f as ae } from "./useAccentStyle-CPo2XqAn.js";
5
+ import { jsx as M, jsxs as Be, Fragment as Le } from "react/jsx-runtime";
6
+ import { useStore as be } from "zustand";
7
+ import { Toaster as _e, toast as H } from "sonner";
8
+ const we = L("light"), qe = () => v(we), ke = L(null), ve = L(null);
9
+ function kt({ children: e }) {
10
+ const [t, a] = W("light"), [o, s] = W(void 0);
11
+ return /* @__PURE__ */ M(ke.Provider, { value: a, children: /* @__PURE__ */ M(ve.Provider, { value: s, children: /* @__PURE__ */ M(we.Provider, { value: t, children: /* @__PURE__ */ M(Ue.Provider, { value: o, children: e }) }) }) });
12
+ }
13
+ function vt(e) {
14
+ const t = v(ke), a = v(ve), o = Ge(a && e ? e.closest("[data-elm-theme]") : null);
15
+ oe(() => {
16
+ a == null || a(o);
17
+ }, [a, o]), oe(() => {
18
+ if (!t || !e) return;
19
+ const s = e.closest("[data-elm-theme]");
20
+ if (!s) {
21
+ C("adapter-no-theme-root", 'The map container is not inside an element with a `data-elm-theme` attribute, so the editor UI renders unstyled and keyboard shortcuts are off. Wrap the map and the editor UI in one element: <div data-elm-theme="light" style={{ position: \'relative\', height: 600 }}>…</div> ("dark" for dark mode).');
22
+ return;
23
+ }
24
+ const u = () => t(s.getAttribute("data-elm-theme") === "dark" ? "dark" : "light");
25
+ u();
26
+ const c = new MutationObserver(u);
27
+ return c.observe(s, { attributes: !0, attributeFilter: ["data-elm-theme"] }), () => c.disconnect();
28
+ }, [t, e]);
29
+ }
30
+ const Ze = { success: null, info: null, warning: null, error: null }, He = "ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Helvetica Neue, Arial, Noto Sans, sans-serif, Apple Color Emoji, Segoe UI Emoji, Segoe UI Symbol, Noto Color Emoji", We = {
31
+ light: { "--normal-bg": "var(--elm-surface, #ffffff)", "--normal-border": "var(--elm-border, rgb(0 0 0 / 0.1))", "--normal-text": "var(--elm-text, #171717)" },
32
+ dark: { "--normal-bg": "var(--elm-surface, #171717)", "--normal-border": "var(--elm-border, rgb(255 255 255 / 0.1))", "--normal-text": "var(--elm-text, #fafafa)" }
33
+ }, ze = { "--border-radius": "calc(var(--elm-radius-control, 6px) + 2px)", fontFamily: `var(--elm-font, ${He})` }, Ke = { light: "!text-(--elm-text-muted,#737373)", dark: "!text-(--elm-text-muted,#a3a3a3)" };
34
+ function Ve(e) {
35
+ var u, c, h;
36
+ const t = qe(), a = Je(), { toastOptions: o, style: s } = e;
37
+ return /* @__PURE__ */ M(
38
+ _e,
39
+ {
40
+ theme: t,
41
+ icons: Ze,
42
+ ...e,
43
+ style: { ...a, ...We[t], ...ze, ...s },
44
+ toastOptions: {
45
+ ...o,
46
+ classNames: {
47
+ ...o == null ? void 0 : o.classNames,
48
+ // Compact: sonner's default 16px padding → 11px; title 500 → 400.
49
+ toast: `!p-[11px] ${((u = o == null ? void 0 : o.classNames) == null ? void 0 : u.toast) ?? ""}`,
50
+ title: `!font-normal ${((c = o == null ? void 0 : o.classNames) == null ? void 0 : c.title) ?? ""}`,
51
+ description: `${Ke[t]} ${((h = o == null ? void 0 : o.classNames) == null ? void 0 : h.description) ?? ""}`
52
+ }
53
+ }
54
+ }
55
+ );
56
+ }
57
+ const Ye = /* @__PURE__ */ new Set(["feature:broken", "selection:copied", "selection:pasted", "error", "warning", "success"]);
58
+ function Qe(e) {
59
+ switch (e.type) {
60
+ case "feature:deleted":
61
+ return `Deleted "${e.label}"`;
62
+ case "features:deleted":
63
+ return `Deleted ${e.count} features`;
64
+ case "feature:duplicated":
65
+ return `Duplicated "${e.label}"`;
66
+ case "features:duplicated":
67
+ return `Duplicated ${e.count} features`;
68
+ case "feature:broken":
69
+ return `Broken into ${e.count} features`;
70
+ case "selection:copied":
71
+ return "Selection copied";
72
+ case "selection:pasted":
73
+ return e.count === 1 ? "Feature pasted" : `${e.count} features pasted`;
74
+ case "undo":
75
+ return "Undone";
76
+ case "redo":
77
+ return "Redone";
78
+ case "error":
79
+ return e.message;
80
+ case "warning":
81
+ return e.message;
82
+ case "success":
83
+ return e.message;
84
+ default:
85
+ return null;
86
+ }
87
+ }
88
+ const B = L(null), Te = L(null);
89
+ function Tt({
90
+ onEvent: e,
91
+ onError: t,
92
+ toaster: a = !1,
93
+ children: o
94
+ }) {
95
+ const s = p(e);
96
+ s.current = e;
97
+ const u = p(t);
98
+ u.current = t;
99
+ const c = v(B), h = p(c);
100
+ h.current = c;
101
+ const [y, E] = W(""), b = p(!!e), w = p(!!c && !e && !a), I = xe(), l = a && !b.current ? `elm-toaster-${I}` : void 0, g = w.current ? c == null ? void 0 : c.toasterId : l, _ = b.current || w.current && !!(c != null && c.managed), F = ee((j) => {
102
+ var R;
103
+ let m = j;
104
+ if (j.type === "error") {
105
+ const { cause: U, featureId: P, quiet: J, error: q, ...T } = j, Z = q ?? new z(T.code, T.source, T.description ? `${T.message}: ${T.description}` : T.message, { cause: U, featureId: P });
106
+ let O;
107
+ try {
108
+ O = (R = u.current) == null ? void 0 : R.call(u, Z);
109
+ } catch (G) {
110
+ console.error(G);
111
+ }
112
+ if (O === !1 || J) return;
113
+ m = typeof O == "string" ? { ...T, message: O, description: void 0 } : { ...T, error: Z };
114
+ }
115
+ if (w.current && h.current) {
116
+ h.current.emit(m);
117
+ return;
118
+ }
119
+ if (m.type === "error") {
120
+ const { error: U, ...P } = m;
121
+ m = P;
122
+ }
123
+ const A = Qe(m);
124
+ if (A && (s.current || !Ye.has(m.type)) && (E(""), requestAnimationFrame(() => E(A))), s.current) {
125
+ s.current(m);
126
+ return;
127
+ }
128
+ const k = { toasterId: g, description: m.description };
129
+ switch (m.type) {
130
+ case "feature:deleted":
131
+ case "features:deleted":
132
+ case "feature:duplicated":
133
+ case "features:duplicated":
134
+ break;
135
+ case "feature:broken":
136
+ H.success(`Broken into ${m.count} features`, {
137
+ ...k,
138
+ action: { label: "Undo", onClick: m.undo },
139
+ duration: 5e3
140
+ });
141
+ break;
142
+ case "selection:copied":
143
+ H.success("Copied selection", k);
144
+ break;
145
+ case "selection:pasted":
146
+ H.success(m.count === 1 ? "Pasted feature" : `Pasted ${m.count} features`, k);
147
+ break;
148
+ case "undo":
149
+ case "redo":
150
+ break;
151
+ case "error":
152
+ H.error(m.message, k);
153
+ break;
154
+ case "warning":
155
+ H.warning(m.message, k);
156
+ break;
157
+ case "success":
158
+ H.success(m.message, k);
159
+ break;
160
+ }
161
+ }, [g]), D = v(Te);
162
+ x(() => {
163
+ if (D)
164
+ return D((j, m) => F({ type: "error", code: j.code, source: j.source, message: j.message, error: j, quiet: m == null ? void 0 : m.quiet })), () => D(null);
165
+ }, [D, F]);
166
+ const K = he(() => ({ emit: F, managed: _, toasterId: g }), [F, _, g]);
167
+ return /* @__PURE__ */ Be(B.Provider, { value: K, children: [
168
+ o,
169
+ l && /* @__PURE__ */ M(Ve, { id: l, position: "bottom-right" }),
170
+ /* @__PURE__ */ M(
171
+ "div",
172
+ {
173
+ "aria-live": "polite",
174
+ "aria-atomic": "true",
175
+ role: "status",
176
+ style: {
177
+ position: "absolute",
178
+ width: 1,
179
+ height: 1,
180
+ padding: 0,
181
+ margin: -1,
182
+ overflow: "hidden",
183
+ clip: "rect(0, 0, 0, 0)",
184
+ whiteSpace: "nowrap",
185
+ border: 0
186
+ },
187
+ children: y
188
+ }
189
+ )
190
+ ] });
191
+ }
192
+ function Xe() {
193
+ const e = v(B);
194
+ if (!e) throw new Error("useEmit must be used within EventProvider");
195
+ return e.emit;
196
+ }
197
+ function Ft() {
198
+ var e;
199
+ return ((e = v(B)) == null ? void 0 : e.managed) ?? !1;
200
+ }
201
+ function $t() {
202
+ var e;
203
+ return (e = v(B)) == null ? void 0 : e.toasterId;
204
+ }
205
+ function Ct() {
206
+ var e;
207
+ return (e = v(B)) == null ? void 0 : e.emit;
208
+ }
209
+ const de = /* @__PURE__ */ new WeakSet(), te = L(null);
210
+ function Et({ children: e }) {
211
+ var y;
212
+ const t = p(null), a = p(null), o = (y = v(B)) == null ? void 0 : y.emit, s = p(o);
213
+ s.current = o;
214
+ const u = ee((E) => {
215
+ a.current = E;
216
+ }, []), c = ie(), h = c.ui.geojsonEditorOpen;
217
+ if (!t.current) {
218
+ const E = (l, g) => {
219
+ a.current ? a.current(l, g) : s.current ? s.current({ type: "error", code: l.code, source: l.source, message: l.message, error: l, quiet: g == null ? void 0 : g.quiet }) : g != null && g.quiet || H.error(l.message);
220
+ }, b = { persistKey: c.persistKey, persist: c.persist }, w = Ie({ onError: E, persist: b }), I = je(w, { onError: E, persist: b });
221
+ if (h) {
222
+ I.setState({ codeModalOpen: !0 }), de.add(I);
223
+ const l = I.subscribe((g) => {
224
+ g.codeModalOpen || (de.delete(I), l());
225
+ });
226
+ }
227
+ t.current = { dataStore: w, uiStore: I };
228
+ }
229
+ return /* @__PURE__ */ M(te.Provider, { value: t.current, children: /* @__PURE__ */ M(Te.Provider, { value: u, children: e }) });
230
+ }
231
+ function et(e) {
232
+ const t = v(te);
233
+ if (!t) throw new Error("useDataStore must be used within GeoStoreProvider");
234
+ return be(t.dataStore, e);
235
+ }
236
+ function X(e) {
237
+ const t = v(te);
238
+ if (!t) throw new Error("useUIStore must be used within GeoStoreProvider");
239
+ return be(t.uiStore, e);
240
+ }
241
+ function Fe() {
242
+ const e = v(te);
243
+ if (!e) throw new Error("useGeoStore must be used within GeoStoreProvider");
244
+ return e;
245
+ }
246
+ const $e = L({
247
+ flyTo: null,
248
+ panTo: null,
249
+ fitBounds: null,
250
+ getCenter: null,
251
+ setZoom: null,
252
+ getZoomBounds: null
253
+ }), Ce = () => {
254
+ }, se = L(Ce);
255
+ function Ot({ children: e }) {
256
+ const [t, a] = W({
257
+ flyTo: null,
258
+ panTo: null,
259
+ fitBounds: null,
260
+ getCenter: null,
261
+ setZoom: null,
262
+ getZoomBounds: null
263
+ });
264
+ return v(se) !== Ce ? /* @__PURE__ */ M(Le, { children: e }) : /* @__PURE__ */ M(se.Provider, { value: a, children: /* @__PURE__ */ M($e.Provider, { value: t, children: e }) });
265
+ }
266
+ function Ee() {
267
+ return v($e);
268
+ }
269
+ function Nt() {
270
+ return v(se);
271
+ }
272
+ function Oe(e, t = "features.geojson") {
273
+ const a = t.toLowerCase().endsWith(".geojson") ? t : `${t}.geojson`, o = new Blob([e], { type: "application/geo+json" }), s = URL.createObjectURL(o), u = document.createElement("a");
274
+ return u.href = s, u.download = a, u.rel = "noopener", document.body.appendChild(u), u.click(), document.body.removeChild(u), URL.revokeObjectURL(s), { name: a, bytes: o.size };
275
+ }
276
+ async function xt(e, t = "features.geojson") {
277
+ const a = t.toLowerCase().endsWith(".geojson") ? t : `${t}.geojson`, o = new Blob([e], { type: "application/geo+json" }), s = window;
278
+ if (typeof s.showSaveFilePicker == "function")
279
+ try {
280
+ const u = await s.showSaveFilePicker({
281
+ suggestedName: a,
282
+ types: [{ description: "GeoJSON", accept: { "application/geo+json": [".geojson", ".json"] } }]
283
+ }), c = await u.createWritable();
284
+ return await c.write(o), await c.close(), { name: u.name || a, bytes: o.size };
285
+ } catch (u) {
286
+ if (u instanceof Error && u.name === "AbortError") return null;
287
+ }
288
+ return Oe(e, t), null;
289
+ }
290
+ async function tt(e, t, a) {
291
+ let o;
292
+ try {
293
+ o = await e.text();
294
+ } catch (u) {
295
+ return { ok: !1, code: "unknown", reason: "The file could not be read", cause: u };
296
+ }
297
+ const s = Ae(o);
298
+ if (!s.ok) {
299
+ const u = s.error;
300
+ return u.kind === "too-large" ? { ok: !1, code: "too-large", reason: `The file is over the ${Math.round(u.maxBytes / 1024 / 1024)} MB import limit` } : u.kind === "invalid-json" ? { ok: !1, code: "invalid-data", reason: `Not valid JSON (${u.cause.message})`, cause: u.cause } : { ok: !1, code: "invalid-data", reason: "Not a FeatureCollection" };
301
+ }
302
+ try {
303
+ const { skipped: u, duplicates: c } = t(s.fc, "replace");
304
+ return { ok: !0, count: a(), skipped: u, duplicates: c };
305
+ } catch (u) {
306
+ return { ok: !1, code: "invalid-data", reason: u instanceof Error ? u.message : "Not a FeatureCollection", cause: u };
307
+ }
308
+ }
309
+ function It() {
310
+ const { dataStore: e, uiStore: t } = Fe(), a = Xe(), { fitBounds: o } = Ee();
311
+ return ee(async (s) => {
312
+ if (t.getState().readonly) return;
313
+ if (!/\.(geo)?json$/i.test(s.name) && !/json/i.test(s.type)) {
314
+ a({ type: "error", code: "invalid-data", source: "import", message: "Import failed", description: `${s.name} is not a .geojson or .json file` });
315
+ return;
316
+ }
317
+ const u = e.getState(), c = await tt(s, u.importGeoJSON, () => e.getState().features.length);
318
+ if (!c.ok) {
319
+ a({ type: "error", code: c.code, source: "import", message: "Import failed", description: c.reason, cause: c.cause });
320
+ return;
321
+ }
322
+ const { features: h, schemas: y, groups: E } = e.getState(), b = Se({ type: "FeatureCollection", metadata: { schemas: y, groups: E }, features: h });
323
+ b && (o == null || o(b)), a({
324
+ type: "success",
325
+ message: `Loaded ${s.name}`,
326
+ description: c.count === 1 ? "1 feature" : `${c.count} features`
327
+ });
328
+ const w = c.skipped + c.duplicates;
329
+ w > 0 && a({
330
+ type: "warning",
331
+ message: `Skipped ${w === 1 ? "1 feature" : `${w} features`} from ${s.name}`,
332
+ description: [
333
+ c.skipped > 0 && `${c.skipped} with a missing or unsupported geometry`,
334
+ c.duplicates > 0 && `${c.duplicates} with a repeated id`
335
+ ].filter(Boolean).join(", ")
336
+ });
337
+ }, [e, t, a, o]);
338
+ }
339
+ const rt = 400, nt = "https://nominatim.openstreetmap.org/search", jt = 'Geocoding by <a href="https://nominatim.org/" target="_blank" rel="noopener">Nominatim</a>';
340
+ function ot(e) {
341
+ return e instanceof z ? e : e instanceof SyntaxError ? new z("invalid-data", "search", "Search service sent an answer that could not be read. Try again later.", { cause: e }) : new z("network", "search", "Search unavailable. Check your connection.", { cause: e });
342
+ }
343
+ function at(e) {
344
+ const t = Pe(e), a = t === "rate-limited" ? "Too many searches — wait a moment and try again." : t === "busy" ? "Search service is busy — try again in a moment." : `Search failed (HTTP ${e}). Try again later.`;
345
+ return new z(t, "search", a);
346
+ }
347
+ function At(e) {
348
+ var _;
349
+ const [t, a] = W([]), [o, s] = W(!1), [u, c] = W(null), h = p(null), y = p(null), E = (_ = v(B)) == null ? void 0 : _.emit, b = p(E);
350
+ b.current = E;
351
+ const { network: w } = ie(), I = p(w);
352
+ I.current = w;
353
+ const l = p(null);
354
+ x(() => {
355
+ const F = e.trim();
356
+ if (F.length < 2) {
357
+ a([]), s(!1), c(null);
358
+ return;
359
+ }
360
+ s(!0), c(null), y.current && clearTimeout(y.current);
361
+ const D = async () => {
362
+ var K, j;
363
+ l.current = null, y.current && clearTimeout(y.current), (K = h.current) == null || K.abort(), h.current = new AbortController();
364
+ try {
365
+ const { nominatim: m, fetch: A = fetch } = I.current, k = m || {}, R = new URLSearchParams({
366
+ q: F,
367
+ format: "json",
368
+ limit: "6",
369
+ addressdetails: "0",
370
+ polygon_geojson: "1",
371
+ ...k.email && { email: k.email }
372
+ }), U = k.url ?? nt, P = await A(`${U}${U.includes("?") ? "&" : "?"}${R}`, { signal: h.current.signal });
373
+ if (!P.ok) throw at(P.status);
374
+ const J = await P.json(), q = /* @__PURE__ */ new Set(), T = /* @__PURE__ */ new Set(), Z = J.filter((O) => {
375
+ const G = `${O.lat},${O.lon}`;
376
+ return q.has(O.display_name) || T.has(G) ? !1 : (q.add(O.display_name), T.add(G), !0);
377
+ });
378
+ a(Z), c(null);
379
+ } catch (m) {
380
+ if (m instanceof Error && m.name === "AbortError") return;
381
+ const A = ot(m);
382
+ c(A.message), (j = b.current) == null || j.call(b, { type: "error", code: A.code, source: "search", message: A.message, error: A, quiet: !0 }), a([]);
383
+ } finally {
384
+ s(!1);
385
+ }
386
+ };
387
+ return l.current = D, y.current = setTimeout(D, rt), () => {
388
+ l.current = null, y.current && clearTimeout(y.current);
389
+ };
390
+ }, [e]), x(() => () => {
391
+ var F;
392
+ (F = h.current) == null || F.abort(), y.current && clearTimeout(y.current);
393
+ }, []);
394
+ const g = ee(() => {
395
+ var F;
396
+ (F = l.current) == null || F.call(l);
397
+ }, []);
398
+ return { results: t, loading: o, error: u, flush: g };
399
+ }
400
+ const fe = (e, t) => Object.is(e, t) || Array.isArray(e) && Array.isArray(t) && e.length === t.length && e.every((a, o) => Object.is(a, t[o]));
401
+ function st(e, t) {
402
+ return [
403
+ ...e.routing === !1 ? ["route"] : [],
404
+ ...e.nominatim === !1 ? ["search"] : [],
405
+ ...e.overpass === !1 && t === "leaflet" ? ["picker"] : []
406
+ ];
407
+ }
408
+ function V(e, t, a) {
409
+ const o = p({ has: !1, value: e });
410
+ o.current.has || (o.current = { has: !0, value: e }, e !== void 0 && !fe(a(), e) && t(e)), oe(() => {
411
+ fe(o.current.value, e) || (o.current = { has: !0, value: e }, t(e));
412
+ });
413
+ }
414
+ const ct = ["properties", "geometry", "schemaId", "hidden"];
415
+ function me(e, t) {
416
+ const a = e;
417
+ if (!a || typeof a != "object")
418
+ return C(`ref-${t}-patch`, `${t}: a patch must be an object; it was skipped.`), null;
419
+ const o = {};
420
+ for (const s of ct) a[s] !== void 0 && (o[s] = a[s]);
421
+ return o.geometry !== void 0 && !ye(o.geometry) ? (C(`ref-${t}-geometry`, `${t}: patch.geometry is not a valid GeoJSON geometry; the patch was skipped.`), null) : o.properties !== void 0 && (typeof o.properties != "object" || o.properties === null || Array.isArray(o.properties)) ? (C(`ref-${t}-properties`, `${t}: patch.properties must be an object; the patch was skipped.`), null) : o;
422
+ }
423
+ function re(e, t) {
424
+ C(`ref-${e}-unknown`, `${e}: no feature with id ${t.slice(0, 3).map((a) => JSON.stringify(a)).join(", ")}${t.length > 3 ? ", …" : ""}; skipped.`);
425
+ }
426
+ function ce(e) {
427
+ const { _validation: t, ...a } = e;
428
+ return a;
429
+ }
430
+ function it(e, t) {
431
+ const a = new Map(e.features.map((c) => [c.id, c])), o = new Set(e.groups.filter((c) => c.hidden).map((c) => c.id)), s = [], u = [];
432
+ for (const c of new Set(t)) {
433
+ const h = a.get(c);
434
+ h && !h.hidden && !(h.groupId && o.has(h.groupId)) ? s.push(h) : u.push(c);
435
+ }
436
+ return { keep: s, dropped: u };
437
+ }
438
+ function ut(e) {
439
+ const t = e;
440
+ return (t == null ? void 0 : t.type) === "Feature" ? { type: "FeatureCollection", features: [t] } : t;
441
+ }
442
+ const lt = Object.fromEntries(Object.entries(ae).map(([e, t]) => [t, e])), ne = (e) => lt[e] ?? null;
443
+ function ge(e) {
444
+ const t = new Map(e.schemas.map((s) => [s.id, s])), a = e.schemas[0] ?? e.getDefaultSchema(), o = {};
445
+ for (const s of e.features) {
446
+ const u = s.schemaId && t.get(s.schemaId) || a, c = Re(s, u).errors;
447
+ c.length > 0 && (o[s.id] = c);
448
+ }
449
+ return o;
450
+ }
451
+ function pe(e) {
452
+ return {
453
+ type: "FeatureCollection",
454
+ metadata: { schemas: e.schemas, groups: e.groups },
455
+ features: e.features.map(ce)
456
+ };
457
+ }
458
+ const dt = (e) => e.features.length === 0 && e.undoStack.length === 0 && e.redoStack.length === 0;
459
+ function ft(e, t) {
460
+ if (e === t) return !0;
461
+ const a = e == null ? void 0 : e.features, o = t == null ? void 0 : t.features;
462
+ return !Array.isArray(a) || !Array.isArray(o) ? !1 : a === o || a.length === o.length && a.every((s, u) => {
463
+ var c;
464
+ return (s == null ? void 0 : s.id) === ((c = o[u]) == null ? void 0 : c.id);
465
+ });
466
+ }
467
+ function Mt(e) {
468
+ const {
469
+ initialData: t,
470
+ schema: a,
471
+ onChange: o,
472
+ onSubmit: s,
473
+ onValidationError: u,
474
+ onFeatureAdd: c,
475
+ onFeatureUpdate: h,
476
+ onFeatureDelete: y,
477
+ onSelectionChange: E,
478
+ onFeatureSelect: b,
479
+ onZoomChange: w,
480
+ onToolChange: I
481
+ } = e, { dataStore: l, uiStore: g } = Fe(), _ = X((r) => r.setReadonly), F = X((r) => r.setEnabledTools), D = et((r) => r.setMaxFeatures), K = X((r) => r.setLayout), j = X((r) => r.setUnavailableTools), { network: m } = ie(), A = Ee(), k = p(A);
482
+ k.current = A;
483
+ const R = p(!1), U = p({});
484
+ U.current = { onChange: o, onFeatureAdd: c, onFeatureUpdate: h, onFeatureDelete: y, onSelectionChange: E }, x(() => Me(l, () => R.current ? { onSelectionChange: U.current.onSelectionChange } : U.current), [l]), V(e.readonly, (r) => _(r ?? !1), () => g.getState().readonly), V(e.tools, (r) => F(r ?? null), () => g.getState().enabledTools), V(e.maxFeatures, D, () => l.getState().maxFeatures), V(e.layout, (r) => K(r ?? "panel"), () => g.getState().layout), V(e.engine && st(m, e.engine), (r) => j(r ?? []), () => g.getState().unavailableTools), x(() => {
485
+ a && l.setState((r) => r.schemas.find((n) => n.id === a.id) ? r : { schemas: [...r.schemas, a] });
486
+ }, [a, l]);
487
+ const P = (r, n) => {
488
+ n !== 0 && g.getState().reportError(new z(
489
+ "invalid-data",
490
+ "import",
491
+ `${n} feature${n === 1 ? "" : "s"} in ${r} had no usable geometry (null or an unknown type) and ${n === 1 ? "was" : "were"} left out.`
492
+ ));
493
+ }, J = p(!1), q = p(t), T = p(e.onInitialDataApplied);
494
+ T.current = e.onInitialDataApplied;
495
+ const Z = (r, n) => {
496
+ var d;
497
+ const i = ut(r);
498
+ R.current = !0;
499
+ try {
500
+ const { skipped: f } = l.getState().importGeoJSON(i, "replace", { undoable: !1 });
501
+ R.current = !1, P("initialData", f), J.current = l.getState().features.length > 0, (d = T.current) == null || d.call(T, i, n);
502
+ } catch (f) {
503
+ const S = `initialData is not a valid FeatureCollection (${f instanceof Error ? f.message : String(f)}). The editor started empty.`;
504
+ console.error(`[element-editor] ${S}`), g.getState().reportError(new z("invalid-data", "import", S, { cause: f }));
505
+ } finally {
506
+ R.current = !1;
507
+ }
508
+ };
509
+ x(() => {
510
+ t && Z(t, !1);
511
+ }, []), x(() => {
512
+ const r = q.current;
513
+ if (ft(r, t) || (q.current = t, !t && !J.current)) return;
514
+ if (t && !J.current && dt(l.getState())) {
515
+ Z(t, !0);
516
+ return;
517
+ }
518
+ const n = J.current || !t;
519
+ C(n ? "initialData-changed" : "initialData-after-edit", n ? "`initialData` changed after the editor loaded its data; the change was ignored (`initialData` is the starting data). To replace the data, call `ref.current.setFeatureCollection(data, { silent: true })`, or remount the editor with a new `key` (e.g. key={projectId})." : "`initialData` arrived after the user started editing; it was ignored so their edits are kept. Render the editor once the data is there, call `ref.current.setFeatureCollection(data, { silent: true })`, or remount it with a new `key`.");
520
+ }, [t]);
521
+ const O = p(s), G = p(u), Y = p(w), ue = p(b);
522
+ x(() => {
523
+ O.current = s;
524
+ }, [s]), x(() => {
525
+ G.current = u;
526
+ }, [u]), x(() => {
527
+ Y.current = w;
528
+ }, [w]), x(() => {
529
+ ue.current = b;
530
+ }, [b]), x(() => l.subscribe((r, n) => {
531
+ var i;
532
+ r.currentZoom !== n.currentZoom && ((i = Y.current) == null || i.call(Y, r.currentZoom));
533
+ }), [l]), x(() => l.subscribe((r, n) => {
534
+ const i = ue.current;
535
+ if (!i) return;
536
+ const d = r.selectedIds.length === 1 ? r.selectedIds[0] : null, f = n.selectedIds.length === 1 ? n.selectedIds[0] : null, S = d ? r.features.find(($) => $.id === d) ?? null : null, N = f ? n.features.find(($) => $.id === f) ?? null : null;
537
+ S !== N && i(S);
538
+ }), [l]);
539
+ const Q = p(I);
540
+ return Q.current = I, x(() => g.subscribe((r, n) => {
541
+ var d;
542
+ if (r.editingMode === n.editingMode) return;
543
+ const i = ne(r.editingMode);
544
+ i !== ne(n.editingMode) && ((d = Q.current) == null || d.call(Q, i));
545
+ }), [g]), he(() => ({
546
+ getFeatureCollection: () => pe(l.getState()),
547
+ getFeature: (r) => {
548
+ const n = l.getState().features.find((i) => i.id === r);
549
+ return n ? ce(n) : null;
550
+ },
551
+ setFeatureCollection: (r, n) => {
552
+ R.current = !!(n != null && n.silent);
553
+ try {
554
+ const { skipped: i } = l.getState().importGeoJSON(r, "replace", { undoable: (n == null ? void 0 : n.undoable) !== !1 });
555
+ P("the data passed to setFeatureCollection", i);
556
+ } finally {
557
+ R.current = !1;
558
+ }
559
+ },
560
+ exportGeoJSON: () => l.getState().exportGeoJSON(),
561
+ exportAs: (r) => {
562
+ r === "geojson" && Oe(l.getState().exportGeoJSON());
563
+ },
564
+ importGeoJSON: (r, n = "replace") => l.getState().importGeoJSON(r, n),
565
+ updateFeatures: (r, n) => {
566
+ if (!Array.isArray(r)) {
567
+ C("ref-updateFeatures-array", "updateFeatures: expected an array of { id, patch }.");
568
+ return;
569
+ }
570
+ const i = l.getState(), d = new Set(i.features.map((N) => N.id)), f = [], S = [];
571
+ for (const N of r) {
572
+ const $ = me(N == null ? void 0 : N.patch, "updateFeatures");
573
+ if ($) {
574
+ if (!d.has(N.id)) {
575
+ S.push(String(N.id));
576
+ continue;
577
+ }
578
+ f.push({ id: N.id, patch: $ });
579
+ }
580
+ }
581
+ S.length && re("updateFeatures", S), f.length && i.updateFeatures(f, { undoable: (n == null ? void 0 : n.undoable) ?? !0 });
582
+ },
583
+ addFeature: (r, n) => {
584
+ const i = r;
585
+ if (!i || typeof i != "object" || !ye(i.geometry))
586
+ return C("ref-addFeature-geometry", "addFeature: the feature needs a valid GeoJSON geometry; nothing was added."), null;
587
+ const d = l.getState(), f = i.id !== void 0 && i.id !== null && String(i.id) !== "" ? String(i.id) : crypto.randomUUID();
588
+ if (d.features.some((Ne) => Ne.id === f))
589
+ return C("ref-addFeature-duplicate", `addFeature: a feature with id ${JSON.stringify(f)} already exists; nothing was added.`), null;
590
+ const { _validation: S, bbox: N, ...$ } = i, le = d.addFeature(
591
+ { ...$, type: "Feature", id: f, properties: i.properties ?? {} },
592
+ { programmatic: !0, undoable: n == null ? void 0 : n.undoable }
593
+ );
594
+ return le && ce(le);
595
+ },
596
+ updateFeature: (r, n, i) => {
597
+ const d = me(n, "updateFeature");
598
+ if (!d) return !1;
599
+ const f = l.getState();
600
+ return f.features.some((S) => S.id === r) ? (f.updateFeatures([{ id: r, patch: d }], { undoable: (i == null ? void 0 : i.undoable) ?? !0 }), !0) : (re("updateFeature", [String(r)]), !1);
601
+ },
602
+ removeFeatures: (r, n) => {
603
+ if (!Array.isArray(r))
604
+ return C("ref-removeFeatures-array", "removeFeatures: expected an array of ids."), 0;
605
+ const i = l.getState(), d = new Set(i.features.map((S) => S.id)), f = r.filter((S) => !d.has(S));
606
+ return f.length && re("removeFeatures", f.map(String)), i.deleteFeatures(r, { undoable: n == null ? void 0 : n.undoable });
607
+ },
608
+ getSelection: () => [...l.getState().selectedIds],
609
+ select: (r, n) => {
610
+ var S, N;
611
+ if (!Array.isArray(r)) {
612
+ C("ref-select-array", "select: expected an array of feature ids.");
613
+ return;
614
+ }
615
+ const i = l.getState(), { keep: d, dropped: f } = it(i, r);
616
+ if (f.length && C("ref-select-dropped", `select: left out ${f.slice(0, 3).map(($) => JSON.stringify($)).join(", ")}${f.length > 3 ? ", …" : ""}: unknown ids or hidden features (a group id isn't selectable; select its features).`), d.length === 0 ? i.clearSelection() : d.length === 1 ? i.selectFeature(d[0].id) : i.setSelection(d.map(($) => $.id)), n != null && n.fit && d.length > 0) {
617
+ const $ = Se({ type: "FeatureCollection", features: d });
618
+ $ && ((N = (S = k.current).fitBounds) == null || N.call(S, $));
619
+ }
620
+ },
621
+ setTool: (r) => {
622
+ const n = g.getState();
623
+ if (r === null)
624
+ return n.setEditingMode("none"), !0;
625
+ const i = r !== "search" && Object.prototype.hasOwnProperty.call(ae, r) ? ae[r] : null;
626
+ return i ? n.readonly && r !== "measure" ? (C("ref-setTool-readonly", `setTool(${JSON.stringify(r)}): the editor is readonly; only 'measure' is available.`), !1) : n.isToolAvailable(r) ? n.editingMode === i ? !0 : r !== "measure" && !l.getState().canAddFeatures(1) ? !1 : (n.setEditingMode(i), !0) : (C(`ref-setTool-disabled-${r}`, `setTool: ${JSON.stringify(r)} is not in the \`tools\` list${n.unavailableTools.includes(r) ? " (config.network turns it off)" : ""}.`), !1) : (C(`ref-setTool-${String(r)}`, `setTool: ${JSON.stringify(r)} is not a drawing tool${r === "search" ? " (search is a box in the toolbar, not a tool)" : ""}.`), !1);
627
+ },
628
+ getTool: () => ne(g.getState().editingMode),
629
+ canUndo: () => l.getState().undoStack.length > 0,
630
+ canRedo: () => l.getState().redoStack.length > 0,
631
+ validate: () => {
632
+ const r = ge(l.getState());
633
+ return { valid: Object.keys(r).length === 0, errors: r };
634
+ },
635
+ getMap: () => {
636
+ var r, n;
637
+ return ((n = (r = k.current).getMap) == null ? void 0 : n.call(r)) ?? null;
638
+ },
639
+ flyTo: (r, n) => {
640
+ var d, f;
641
+ const i = De(r, n);
642
+ i && ((f = (d = k.current).flyTo) == null || f.call(d, [i.center[1], i.center[0]], i.zoom));
643
+ },
644
+ setZoom: (r) => {
645
+ const n = k.current.setZoom;
646
+ return n ? (n(r), !0) : !1;
647
+ },
648
+ fitBounds: (r) => {
649
+ var n, i;
650
+ return (i = (n = k.current).fitBounds) == null ? void 0 : i.call(n, r);
651
+ },
652
+ submit: () => {
653
+ var i, d;
654
+ const r = l.getState(), n = ge(r);
655
+ return Object.keys(n).length > 0 ? ((i = G.current) == null || i.call(G, n), !1) : ((d = O.current) == null || d.call(O, pe(r)), !0);
656
+ },
657
+ undo: () => l.getState().undo(),
658
+ redo: () => l.getState().redo(),
659
+ clearSelection: () => l.getState().clearSelection()
660
+ }), [l, g]);
661
+ }
662
+ export {
663
+ B as E,
664
+ Et as G,
665
+ Ot as M,
666
+ nt as N,
667
+ te as S,
668
+ kt as T,
669
+ jt as a,
670
+ It as b,
671
+ Ct as c,
672
+ qe as d,
673
+ Fe as e,
674
+ et as f,
675
+ Ee as g,
676
+ Xe as h,
677
+ Ft as i,
678
+ $t as j,
679
+ de as k,
680
+ At as l,
681
+ Tt as m,
682
+ st as n,
683
+ Ve as o,
684
+ we as p,
685
+ Mt as q,
686
+ vt as r,
687
+ xt as s,
688
+ Oe as t,
689
+ X as u,
690
+ Nt as v
691
+ };