@open-pioneer/feature-editing 1.4.0-dev.20260727093741 → 1.4.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 (60) hide show
  1. package/CHANGELOG.md +3 -1
  2. package/api/editor/context.js.map +1 -1
  3. package/api/editor/editor.d.ts +2 -2
  4. package/api/editor/editor.js.map +1 -1
  5. package/api/model/InteractionOptions.d.ts +1 -1
  6. package/implementation/FeatureEditor.js.map +1 -1
  7. package/implementation/components/action-selector/ActionSelector.js.map +1 -1
  8. package/implementation/components/action-selector/DrawingControls.js.map +1 -1
  9. package/implementation/components/action-selector/SelectButton.js.map +1 -1
  10. package/implementation/components/action-selector/TemplateItem.js.map +1 -1
  11. package/implementation/components/action-selector/TemplateSelector.js.map +1 -1
  12. package/implementation/components/controls/ColorPickerControl.js +1 -1
  13. package/implementation/components/controls/ColorPickerControl.js.map +1 -1
  14. package/implementation/components/controls/ComboBoxControl.js.map +1 -1
  15. package/implementation/components/controls/DefaultControl.js +1 -1
  16. package/implementation/components/controls/DefaultControl.js.map +1 -1
  17. package/implementation/components/controls/NumberFieldControl.js.map +1 -1
  18. package/implementation/components/controls/RadioGroupControl.js.map +1 -1
  19. package/implementation/components/controls/SelectControl.js.map +1 -1
  20. package/implementation/components/controls/option-hooks.js.map +1 -1
  21. package/implementation/components/property-editor/ButtonRow.js +1 -1
  22. package/implementation/components/property-editor/ButtonRow.js.map +1 -1
  23. package/implementation/components/property-editor/CancelConfirmationDialog.js.map +1 -1
  24. package/implementation/components/property-editor/DeleteConfirmationDialog.js.map +1 -1
  25. package/implementation/components/property-editor/PropertyEditor.js +6 -3
  26. package/implementation/components/property-editor/PropertyEditor.js.map +1 -1
  27. package/implementation/components/property-editor/PropertyField.js.map +1 -1
  28. package/implementation/components/property-editor/PropertyForm.js +1 -1
  29. package/implementation/components/property-editor/PropertyForm.js.map +1 -1
  30. package/implementation/context/PropertyFormContext.js.map +1 -1
  31. package/implementation/context/usePropertyFormContext.js.map +1 -1
  32. package/implementation/editor/editorHooks.d.ts +1 -1
  33. package/implementation/editor/editorHooks.js +1 -1
  34. package/implementation/editor/editorHooks.js.map +1 -1
  35. package/implementation/editor/useEditingCallbacks.d.ts +1 -1
  36. package/implementation/editor/useEditingCallbacks.js +1 -1
  37. package/implementation/editor/useEditingCallbacks.js.map +1 -1
  38. package/implementation/geometry-editing/controller/DrawingSession.js.map +1 -1
  39. package/implementation/geometry-editing/controller/EditingController.d.ts +2 -2
  40. package/implementation/geometry-editing/controller/EditingController.js.map +1 -1
  41. package/implementation/geometry-editing/controller/UndoManager.js.map +1 -1
  42. package/implementation/geometry-editing/controller/geometryState.js.map +1 -1
  43. package/implementation/geometry-editing/interactions/BaseInteraction.js.map +1 -1
  44. package/implementation/geometry-editing/interactions/DoubleClickInteraction.js.map +1 -1
  45. package/implementation/geometry-editing/interactions/DrawingInteraction.d.ts +4 -4
  46. package/implementation/geometry-editing/interactions/DrawingInteraction.js +2 -2
  47. package/implementation/geometry-editing/interactions/DrawingInteraction.js.map +1 -1
  48. package/implementation/geometry-editing/interactions/HighlightingInteraction.js.map +1 -1
  49. package/implementation/geometry-editing/interactions/KeyboardInteraction.d.ts +1 -1
  50. package/implementation/geometry-editing/interactions/KeyboardInteraction.js.map +1 -1
  51. package/implementation/geometry-editing/interactions/ModificationInteraction.d.ts +1 -1
  52. package/implementation/geometry-editing/interactions/ModificationInteraction.js.map +1 -1
  53. package/implementation/geometry-editing/interactions/SelectionInteraction.d.ts +2 -2
  54. package/implementation/geometry-editing/interactions/SelectionInteraction.js +1 -1
  55. package/implementation/geometry-editing/interactions/SelectionInteraction.js.map +1 -1
  56. package/implementation/geometry-editing/interactions/SnappingInteraction.d.ts +1 -1
  57. package/implementation/geometry-editing/interactions/SnappingInteraction.js.map +1 -1
  58. package/implementation/geometry-editing/useGeometryEditing.d.ts +1 -1
  59. package/implementation/geometry-editing/useGeometryEditing.js.map +1 -1
  60. package/package.json +9 -9
@@ -1 +1 @@
1
- {"version":3,"file":"HighlightingInteraction.js","sources":["HighlightingInteraction.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2023-2025 Open Pioneer project (https://github.com/open-pioneer)\n// SPDX-License-Identifier: Apache-2.0\nimport type { Highlight, HighlightOptions } from \"@open-pioneer/map\";\nimport type { Feature } from \"ol\";\nimport { Circle, Fill, Stroke, Style } from \"ol/style\";\nimport { BaseInteraction } from \"./BaseInteraction\";\n\nexport interface HighlightingParameters {\n readonly feature: Feature;\n readonly highlightOptions?: HighlightOptions;\n}\n\ninterface Data {\n readonly highlight?: Highlight;\n}\n\nexport class HighlightingInteraction extends BaseInteraction<HighlightingParameters, Data> {\n protected override startInteraction(parameters: HighlightingParameters): Data {\n const { feature, highlightOptions } = parameters;\n const geometry = feature.getGeometry();\n\n if (geometry != null) {\n const options = this.#getHighlightOptions(highlightOptions);\n const highlight = this.mapModel.highlights.add([geometry], options);\n return { highlight };\n } else {\n return {};\n }\n }\n\n protected override stopInteraction({ highlight }: Data): void {\n highlight?.destroy();\n }\n\n #getHighlightOptions(highlightOptions: HighlightOptions | undefined): HighlightOptions {\n return {\n ...highlightOptions,\n highlightStyle: {\n Point: HighlightingInteraction.#DEFAULT_POINT_HIGHLIGHT_STYLE,\n ...highlightOptions?.highlightStyle\n }\n };\n }\n\n static readonly #DEFAULT_POINT_HIGHLIGHT_STYLE = new Style({\n image: new Circle({\n stroke: new Stroke({\n color: \"cyan\",\n width: 4.0\n }),\n fill: new Fill({\n color: \"rgba(224,255,255,0.35)\"\n }),\n radius: 12.0\n })\n });\n}\n"],"names":[],"mappings":";;;AAgBO,MAAM,gCAAgC,eAAA,CAA8C;AAAA,EACpE,iBAAiB,UAAA,EAA0C;AAC1E,IAAA,MAAM,EAAE,OAAA,EAAS,gBAAA,EAAiB,GAAI,UAAA;AACtC,IAAA,MAAM,QAAA,GAAW,QAAQ,WAAA,EAAY;AAErC,IAAA,IAAI,YAAY,IAAA,EAAM;AAClB,MAAA,MAAM,OAAA,GAAU,IAAA,CAAK,oBAAA,CAAqB,gBAAgB,CAAA;AAC1D,MAAA,MAAM,SAAA,GAAY,KAAK,QAAA,CAAS,UAAA,CAAW,IAAI,CAAC,QAAQ,GAAG,OAAO,CAAA;AAClE,MAAA,OAAO,EAAE,SAAA,EAAU;AAAA,IACvB,CAAA,MAAO;AACH,MAAA,OAAO,EAAC;AAAA,IACZ;AAAA,EACJ;AAAA,EAEmB,eAAA,CAAgB,EAAE,SAAA,EAAU,EAAe;AAC1D,IAAA,SAAA,EAAW,OAAA,EAAQ;AAAA,EACvB;AAAA,EAEA,qBAAqB,gBAAA,EAAkE;AACnF,IAAA,OAAO;AAAA,MACH,GAAG,gBAAA;AAAA,MACH,cAAA,EAAgB;AAAA,QACZ,OAAO,uBAAA,CAAwB,8BAAA;AAAA,QAC/B,GAAG,gBAAA,EAAkB;AAAA;AACzB,KACJ;AAAA,EACJ;AAAA,EAEA,OAAgB,8BAAA,GAAiC,IAAI,KAAA,CAAM;AAAA,IACvD,KAAA,EAAO,IAAI,MAAA,CAAO;AAAA,MACd,MAAA,EAAQ,IAAI,MAAA,CAAO;AAAA,QACf,KAAA,EAAO,MAAA;AAAA,QACP,KAAA,EAAO;AAAA,OACV,CAAA;AAAA,MACD,IAAA,EAAM,IAAI,IAAA,CAAK;AAAA,QACX,KAAA,EAAO;AAAA,OACV,CAAA;AAAA,MACD,MAAA,EAAQ;AAAA,KACX;AAAA,GACJ,CAAA;AACL;;;;"}
1
+ {"version":3,"file":"HighlightingInteraction.js","sources":["HighlightingInteraction.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2023-2025 Open Pioneer project (https://github.com/open-pioneer)\n// SPDX-License-Identifier: Apache-2.0\n\nimport type { Highlight, HighlightOptions } from \"@open-pioneer/map\";\nimport type { Feature } from \"ol\";\nimport { Circle, Fill, Stroke, Style } from \"ol/style\";\nimport { BaseInteraction } from \"./BaseInteraction\";\n\nexport interface HighlightingParameters {\n readonly feature: Feature;\n readonly highlightOptions?: HighlightOptions;\n}\n\ninterface Data {\n readonly highlight?: Highlight;\n}\n\nexport class HighlightingInteraction extends BaseInteraction<HighlightingParameters, Data> {\n protected override startInteraction(parameters: HighlightingParameters): Data {\n const { feature, highlightOptions } = parameters;\n const geometry = feature.getGeometry();\n\n if (geometry != null) {\n const options = this.#getHighlightOptions(highlightOptions);\n const highlight = this.mapModel.highlights.add([geometry], options);\n return { highlight };\n } else {\n return {};\n }\n }\n\n protected override stopInteraction({ highlight }: Data): void {\n highlight?.destroy();\n }\n\n #getHighlightOptions(highlightOptions: HighlightOptions | undefined): HighlightOptions {\n return {\n ...highlightOptions,\n highlightStyle: {\n Point: HighlightingInteraction.#DEFAULT_POINT_HIGHLIGHT_STYLE,\n ...highlightOptions?.highlightStyle\n }\n };\n }\n\n static readonly #DEFAULT_POINT_HIGHLIGHT_STYLE = new Style({\n image: new Circle({\n stroke: new Stroke({\n color: \"cyan\",\n width: 4.0\n }),\n fill: new Fill({\n color: \"rgba(224,255,255,0.35)\"\n }),\n radius: 12.0\n })\n });\n}\n"],"names":[],"mappings":";;;AAiBO,MAAM,gCAAgC,eAAA,CAA8C;AAAA,EACpE,iBAAiB,UAAA,EAA0C;AAC1E,IAAA,MAAM,EAAE,OAAA,EAAS,gBAAA,EAAiB,GAAI,UAAA;AACtC,IAAA,MAAM,QAAA,GAAW,QAAQ,WAAA,EAAY;AAErC,IAAA,IAAI,YAAY,IAAA,EAAM;AAClB,MAAA,MAAM,OAAA,GAAU,IAAA,CAAK,oBAAA,CAAqB,gBAAgB,CAAA;AAC1D,MAAA,MAAM,SAAA,GAAY,KAAK,QAAA,CAAS,UAAA,CAAW,IAAI,CAAC,QAAQ,GAAG,OAAO,CAAA;AAClE,MAAA,OAAO,EAAE,SAAA,EAAU;AAAA,IACvB,CAAA,MAAO;AACH,MAAA,OAAO,EAAC;AAAA,IACZ;AAAA,EACJ;AAAA,EAEmB,eAAA,CAAgB,EAAE,SAAA,EAAU,EAAe;AAC1D,IAAA,SAAA,EAAW,OAAA,EAAQ;AAAA,EACvB;AAAA,EAEA,qBAAqB,gBAAA,EAAkE;AACnF,IAAA,OAAO;AAAA,MACH,GAAG,gBAAA;AAAA,MACH,cAAA,EAAgB;AAAA,QACZ,OAAO,uBAAA,CAAwB,8BAAA;AAAA,QAC/B,GAAG,gBAAA,EAAkB;AAAA;AACzB,KACJ;AAAA,EACJ;AAAA,EAEA,OAAgB,8BAAA,GAAiC,IAAI,KAAA,CAAM;AAAA,IACvD,KAAA,EAAO,IAAI,MAAA,CAAO;AAAA,MACd,MAAA,EAAQ,IAAI,MAAA,CAAO;AAAA,QACf,KAAA,EAAO,MAAA;AAAA,QACP,KAAA,EAAO;AAAA,OACV,CAAA;AAAA,MACD,IAAA,EAAM,IAAI,IAAA,CAAK;AAAA,QACX,KAAA,EAAO;AAAA,OACV,CAAA;AAAA,MACD,MAAA,EAAQ;AAAA,KACX;AAAA,GACJ,CAAA;AACL;;;;"}
@@ -1,5 +1,5 @@
1
- import { BaseInteraction } from "./BaseInteraction";
2
1
  import { type DrawingState } from "../useGeometryEditing";
2
+ import { BaseInteraction } from "./BaseInteraction";
3
3
  interface KeyboardParameters {
4
4
  readonly actions: DrawingState;
5
5
  }
@@ -1 +1 @@
1
- {"version":3,"file":"KeyboardInteraction.js","sources":["KeyboardInteraction.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2023-2025 Open Pioneer project (https://github.com/open-pioneer)\n// SPDX-License-Identifier: Apache-2.0\nimport { BaseInteraction } from \"./BaseInteraction\";\nimport { type DrawingState } from \"../useGeometryEditing\";\n\ninterface KeyboardParameters {\n readonly actions: DrawingState;\n}\n\ninterface KeyboardData {\n readonly keyboardListener: KeyboardListener;\n}\n\ntype KeyboardListener = Parameters<typeof document.addEventListener<\"keydown\">>[1];\n\ninterface KeyboardShortcut {\n readonly key: string;\n readonly ctrlKey?: boolean;\n readonly shiftKey?: boolean;\n readonly action: () => void;\n}\n\ninterface NewNavigator extends Navigator {\n readonly userAgentData?: {\n readonly platform: string | undefined;\n };\n}\n\nexport class KeyboardInteraction extends BaseInteraction<KeyboardParameters, KeyboardData> {\n protected override startInteraction({ actions }: KeyboardParameters): KeyboardData {\n const keyboardListener = this.#addKeyboardListener([\n { key: \"Enter\", action: () => actions.finish() },\n { key: \"Escape\", action: () => actions.reset() },\n { key: \"Z\", ctrlKey: true, action: () => actions.undo() },\n { key: \"Z\", ctrlKey: true, shiftKey: true, action: () => actions.redo() },\n { key: \"Y\", ctrlKey: true, action: () => actions.redo() }\n ]);\n return { keyboardListener };\n }\n\n protected override stopInteraction({ keyboardListener }: KeyboardData): void {\n document.removeEventListener(\"keydown\", keyboardListener);\n }\n\n #addKeyboardListener(shortcuts: KeyboardShortcut[]) {\n const isApple = this.#isApplePlatform();\n const listener: KeyboardListener = (event) => {\n const shortcut = shortcuts.find((shortcut) =>\n this.#matchesShortcut(event, shortcut, isApple)\n );\n if (shortcut != null) {\n event.preventDefault();\n shortcut.action();\n }\n };\n document.addEventListener(\"keydown\", listener);\n return listener;\n }\n\n #matchesShortcut(event: KeyboardEvent, shortcut: KeyboardShortcut, isApple: boolean): boolean {\n if (isApple) {\n // On Apple platforms, the Command key is represented by 'metaKey'.\n return (\n event.key.toLowerCase() === shortcut.key.toLowerCase() &&\n event.metaKey === (shortcut.ctrlKey ?? false) &&\n event.shiftKey === (shortcut.shiftKey ?? false) &&\n !event.ctrlKey &&\n !event.altKey\n );\n } else {\n return (\n event.key.toLowerCase() === shortcut.key.toLowerCase() &&\n event.ctrlKey === (shortcut.ctrlKey ?? false) &&\n event.shiftKey === (shortcut.shiftKey ?? false) &&\n !event.metaKey &&\n !event.altKey\n );\n }\n }\n\n #isApplePlatform(): boolean {\n const platform = this.#getPlatform();\n return platform != null && KeyboardInteraction.#APPLE_REGEX.test(platform);\n }\n\n #getPlatform(): string | undefined {\n const platform = (navigator as NewNavigator).userAgentData?.platform;\n if (platform != null) {\n return platform;\n } else {\n return navigator.platform;\n }\n }\n\n static readonly #APPLE_REGEX = /(Mac|iPad|iPhone|iPod)/i;\n}\n"],"names":["shortcut"],"mappings":"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"}
1
+ {"version":3,"file":"KeyboardInteraction.js","sources":["KeyboardInteraction.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2023-2025 Open Pioneer project (https://github.com/open-pioneer)\n// SPDX-License-Identifier: Apache-2.0\n\nimport { type DrawingState } from \"../useGeometryEditing\";\nimport { BaseInteraction } from \"./BaseInteraction\";\n\ninterface KeyboardParameters {\n readonly actions: DrawingState;\n}\n\ninterface KeyboardData {\n readonly keyboardListener: KeyboardListener;\n}\n\ntype KeyboardListener = Parameters<typeof document.addEventListener<\"keydown\">>[1];\n\ninterface KeyboardShortcut {\n readonly key: string;\n readonly ctrlKey?: boolean;\n readonly shiftKey?: boolean;\n readonly action: () => void;\n}\n\ninterface NewNavigator extends Navigator {\n readonly userAgentData?: {\n readonly platform: string | undefined;\n };\n}\n\nexport class KeyboardInteraction extends BaseInteraction<KeyboardParameters, KeyboardData> {\n protected override startInteraction({ actions }: KeyboardParameters): KeyboardData {\n const keyboardListener = this.#addKeyboardListener([\n { key: \"Enter\", action: () => actions.finish() },\n { key: \"Escape\", action: () => actions.reset() },\n { key: \"Z\", ctrlKey: true, action: () => actions.undo() },\n { key: \"Z\", ctrlKey: true, shiftKey: true, action: () => actions.redo() },\n { key: \"Y\", ctrlKey: true, action: () => actions.redo() }\n ]);\n return { keyboardListener };\n }\n\n protected override stopInteraction({ keyboardListener }: KeyboardData): void {\n document.removeEventListener(\"keydown\", keyboardListener);\n }\n\n #addKeyboardListener(shortcuts: KeyboardShortcut[]) {\n const isApple = this.#isApplePlatform();\n const listener: KeyboardListener = (event) => {\n const shortcut = shortcuts.find((shortcut) =>\n this.#matchesShortcut(event, shortcut, isApple)\n );\n if (shortcut != null) {\n event.preventDefault();\n shortcut.action();\n }\n };\n document.addEventListener(\"keydown\", listener);\n return listener;\n }\n\n #matchesShortcut(event: KeyboardEvent, shortcut: KeyboardShortcut, isApple: boolean): boolean {\n if (isApple) {\n // On Apple platforms, the Command key is represented by 'metaKey'.\n return (\n event.key.toLowerCase() === shortcut.key.toLowerCase() &&\n event.metaKey === (shortcut.ctrlKey ?? false) &&\n event.shiftKey === (shortcut.shiftKey ?? false) &&\n !event.ctrlKey &&\n !event.altKey\n );\n } else {\n return (\n event.key.toLowerCase() === shortcut.key.toLowerCase() &&\n event.ctrlKey === (shortcut.ctrlKey ?? false) &&\n event.shiftKey === (shortcut.shiftKey ?? false) &&\n !event.metaKey &&\n !event.altKey\n );\n }\n }\n\n #isApplePlatform(): boolean {\n const platform = this.#getPlatform();\n return platform != null && KeyboardInteraction.#APPLE_REGEX.test(platform);\n }\n\n #getPlatform(): string | undefined {\n const platform = (navigator as NewNavigator).userAgentData?.platform;\n if (platform != null) {\n return platform;\n } else {\n return navigator.platform;\n }\n }\n\n static readonly #APPLE_REGEX = /(Mac|iPad|iPhone|iPod)/i;\n}\n"],"names":["shortcut"],"mappings":"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"}
@@ -3,8 +3,8 @@ import { type Feature } from "ol";
3
3
  import type { Geometry } from "ol/geom";
4
4
  import { Modify } from "ol/interaction";
5
5
  import type { ModificationOptions } from "../../../api/model/InteractionOptions";
6
- import { BaseInteraction } from "./BaseInteraction";
7
6
  import type { TooltipMessages } from "../controller/EditingController";
7
+ import { BaseInteraction } from "./BaseInteraction";
8
8
  export interface ModificationParameters {
9
9
  readonly feature: Feature;
10
10
  readonly drawLayer?: Layer;
@@ -1 +1 @@
1
- {"version":3,"file":"ModificationInteraction.js","sources":["ModificationInteraction.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2023-2025 Open Pioneer project (https://github.com/open-pioneer)\n// SPDX-License-Identifier: Apache-2.0\nimport { type Layer, type MapModel, Overlay } from \"@open-pioneer/map\";\nimport { Collection, type Feature } from \"ol\";\nimport type { Geometry } from \"ol/geom\";\nimport type { Type as GeometryType } from \"ol/geom/Geometry\";\nimport { Modify } from \"ol/interaction\";\nimport type { ModificationOptions } from \"../../../api/model/InteractionOptions\";\nimport { BaseInteraction } from \"./BaseInteraction\";\nimport type { TooltipMessages } from \"../controller/EditingController\";\n\nexport interface ModificationParameters {\n readonly feature: Feature;\n readonly drawLayer?: Layer;\n readonly modificationOptions?: ModificationOptions;\n readonly tooltipMessages: TooltipMessages;\n}\n\ninterface Data {\n readonly feature: Feature;\n readonly modify: Modify;\n readonly drawLayer: Layer | undefined;\n readonly originalGeometry: Geometry | undefined;\n}\n\nexport class ModificationInteraction extends BaseInteraction<ModificationParameters, Data> {\n #tooltip: Overlay | undefined;\n\n protected override startInteraction(parameters: ModificationParameters): Data {\n const { feature, drawLayer, modificationOptions, tooltipMessages } = parameters;\n\n const features = new Collection([feature]);\n const modify = new Modify({ features, ...modificationOptions });\n const originalGeometry = feature.getGeometry()?.clone();\n\n if (drawLayer != null) {\n this.mapModel.layers.addLayer(drawLayer, { at: \"topmost\" });\n }\n\n this.#tooltip = this.#createHelpTooltip(\n this.mapModel,\n tooltipMessages,\n originalGeometry?.getType()\n );\n\n this.map.addInteraction(modify);\n\n return { feature, modify, drawLayer, originalGeometry };\n }\n\n protected override stopInteraction(data: Data): void {\n const { feature, modify, drawLayer, originalGeometry } = data;\n\n this.map.removeInteraction(modify);\n\n if (drawLayer != null) {\n this.mapModel.layers.removeLayer(drawLayer);\n drawLayer.destroy();\n }\n if (originalGeometry != null) {\n feature.setGeometry(originalGeometry);\n }\n\n this.#tooltip?.destroy();\n }\n\n #createHelpTooltip(\n mapModel: MapModel,\n tooltipMessages: TooltipMessages,\n geometryType?: GeometryType\n ): Overlay | undefined {\n const modificationMessages = tooltipMessages.getModificationMessages();\n const message =\n geometryType === \"Point\"\n ? modificationMessages.get(\"Point\")\n : modificationMessages.get(\"default\");\n\n const helpOverlay = mapModel.overlays.add({\n className: \"editing-tooltip printing-hide\",\n position: \"follow-pointer\",\n tag: \"editing-modification-overlay\",\n offset: [15, 0],\n positioning: \"center-left\",\n ariaRole: \"tooltip\",\n content: message\n });\n\n return helpOverlay;\n }\n}\n"],"names":[],"mappings":";;;;AAyBO,MAAM,gCAAgC,eAAA,CAA8C;AAAA,EACvF,QAAA;AAAA,EAEmB,iBAAiB,UAAA,EAA0C;AAC1E,IAAA,MAAM,EAAE,OAAA,EAAS,SAAA,EAAW,mBAAA,EAAqB,iBAAgB,GAAI,UAAA;AAErE,IAAA,MAAM,QAAA,GAAW,IAAI,UAAA,CAAW,CAAC,OAAO,CAAC,CAAA;AACzC,IAAA,MAAM,SAAS,IAAI,MAAA,CAAO,EAAE,QAAA,EAAU,GAAG,qBAAqB,CAAA;AAC9D,IAAA,MAAM,gBAAA,GAAmB,OAAA,CAAQ,WAAA,EAAY,EAAG,KAAA,EAAM;AAEtD,IAAA,IAAI,aAAa,IAAA,EAAM;AACnB,MAAA,IAAA,CAAK,SAAS,MAAA,CAAO,QAAA,CAAS,WAAW,EAAE,EAAA,EAAI,WAAW,CAAA;AAAA,IAC9D;AAEA,IAAA,IAAA,CAAK,WAAW,IAAA,CAAK,kBAAA;AAAA,MACjB,IAAA,CAAK,QAAA;AAAA,MACL,eAAA;AAAA,MACA,kBAAkB,OAAA;AAAQ,KAC9B;AAEA,IAAA,IAAA,CAAK,GAAA,CAAI,eAAe,MAAM,CAAA;AAE9B,IAAA,OAAO,EAAE,OAAA,EAAS,MAAA,EAAQ,SAAA,EAAW,gBAAA,EAAiB;AAAA,EAC1D;AAAA,EAEmB,gBAAgB,IAAA,EAAkB;AACjD,IAAA,MAAM,EAAE,OAAA,EAAS,MAAA,EAAQ,SAAA,EAAW,kBAAiB,GAAI,IAAA;AAEzD,IAAA,IAAA,CAAK,GAAA,CAAI,kBAAkB,MAAM,CAAA;AAEjC,IAAA,IAAI,aAAa,IAAA,EAAM;AACnB,MAAA,IAAA,CAAK,QAAA,CAAS,MAAA,CAAO,WAAA,CAAY,SAAS,CAAA;AAC1C,MAAA,SAAA,CAAU,OAAA,EAAQ;AAAA,IACtB;AACA,IAAA,IAAI,oBAAoB,IAAA,EAAM;AAC1B,MAAA,OAAA,CAAQ,YAAY,gBAAgB,CAAA;AAAA,IACxC;AAEA,IAAA,IAAA,CAAK,UAAU,OAAA,EAAQ;AAAA,EAC3B;AAAA,EAEA,kBAAA,CACI,QAAA,EACA,eAAA,EACA,YAAA,EACmB;AACnB,IAAA,MAAM,oBAAA,GAAuB,gBAAgB,uBAAA,EAAwB;AACrE,IAAA,MAAM,OAAA,GACF,iBAAiB,OAAA,GACX,oBAAA,CAAqB,IAAI,OAAO,CAAA,GAChC,oBAAA,CAAqB,GAAA,CAAI,SAAS,CAAA;AAE5C,IAAA,MAAM,WAAA,GAAc,QAAA,CAAS,QAAA,CAAS,GAAA,CAAI;AAAA,MACtC,SAAA,EAAW,+BAAA;AAAA,MACX,QAAA,EAAU,gBAAA;AAAA,MACV,GAAA,EAAK,8BAAA;AAAA,MACL,MAAA,EAAQ,CAAC,EAAA,EAAI,CAAC,CAAA;AAAA,MACd,WAAA,EAAa,aAAA;AAAA,MACb,QAAA,EAAU,SAAA;AAAA,MACV,OAAA,EAAS;AAAA,KACZ,CAAA;AAED,IAAA,OAAO,WAAA;AAAA,EACX;AACJ;;;;"}
1
+ {"version":3,"file":"ModificationInteraction.js","sources":["ModificationInteraction.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2023-2025 Open Pioneer project (https://github.com/open-pioneer)\n// SPDX-License-Identifier: Apache-2.0\n\nimport { type Layer, type MapModel, Overlay } from \"@open-pioneer/map\";\nimport { Collection, type Feature } from \"ol\";\nimport type { Geometry } from \"ol/geom\";\nimport type { Type as GeometryType } from \"ol/geom/Geometry\";\nimport { Modify } from \"ol/interaction\";\nimport type { ModificationOptions } from \"../../../api/model/InteractionOptions\";\nimport type { TooltipMessages } from \"../controller/EditingController\";\nimport { BaseInteraction } from \"./BaseInteraction\";\n\nexport interface ModificationParameters {\n readonly feature: Feature;\n readonly drawLayer?: Layer;\n readonly modificationOptions?: ModificationOptions;\n readonly tooltipMessages: TooltipMessages;\n}\n\ninterface Data {\n readonly feature: Feature;\n readonly modify: Modify;\n readonly drawLayer: Layer | undefined;\n readonly originalGeometry: Geometry | undefined;\n}\n\nexport class ModificationInteraction extends BaseInteraction<ModificationParameters, Data> {\n #tooltip: Overlay | undefined;\n\n protected override startInteraction(parameters: ModificationParameters): Data {\n const { feature, drawLayer, modificationOptions, tooltipMessages } = parameters;\n\n const features = new Collection([feature]);\n const modify = new Modify({ features, ...modificationOptions });\n const originalGeometry = feature.getGeometry()?.clone();\n\n if (drawLayer != null) {\n this.mapModel.layers.addLayer(drawLayer, { at: \"topmost\" });\n }\n\n this.#tooltip = this.#createHelpTooltip(\n this.mapModel,\n tooltipMessages,\n originalGeometry?.getType()\n );\n\n this.map.addInteraction(modify);\n\n return { feature, modify, drawLayer, originalGeometry };\n }\n\n protected override stopInteraction(data: Data): void {\n const { feature, modify, drawLayer, originalGeometry } = data;\n\n this.map.removeInteraction(modify);\n\n if (drawLayer != null) {\n this.mapModel.layers.removeLayer(drawLayer);\n drawLayer.destroy();\n }\n if (originalGeometry != null) {\n feature.setGeometry(originalGeometry);\n }\n\n this.#tooltip?.destroy();\n }\n\n #createHelpTooltip(\n mapModel: MapModel,\n tooltipMessages: TooltipMessages,\n geometryType?: GeometryType\n ): Overlay | undefined {\n const modificationMessages = tooltipMessages.getModificationMessages();\n const message =\n geometryType === \"Point\"\n ? modificationMessages.get(\"Point\")\n : modificationMessages.get(\"default\");\n\n const helpOverlay = mapModel.overlays.add({\n className: \"editing-tooltip printing-hide\",\n position: \"follow-pointer\",\n tag: \"editing-modification-overlay\",\n offset: [15, 0],\n positioning: \"center-left\",\n ariaRole: \"tooltip\",\n content: message\n });\n\n return helpOverlay;\n }\n}\n"],"names":[],"mappings":";;;;AA0BO,MAAM,gCAAgC,eAAA,CAA8C;AAAA,EACvF,QAAA;AAAA,EAEmB,iBAAiB,UAAA,EAA0C;AAC1E,IAAA,MAAM,EAAE,OAAA,EAAS,SAAA,EAAW,mBAAA,EAAqB,iBAAgB,GAAI,UAAA;AAErE,IAAA,MAAM,QAAA,GAAW,IAAI,UAAA,CAAW,CAAC,OAAO,CAAC,CAAA;AACzC,IAAA,MAAM,SAAS,IAAI,MAAA,CAAO,EAAE,QAAA,EAAU,GAAG,qBAAqB,CAAA;AAC9D,IAAA,MAAM,gBAAA,GAAmB,OAAA,CAAQ,WAAA,EAAY,EAAG,KAAA,EAAM;AAEtD,IAAA,IAAI,aAAa,IAAA,EAAM;AACnB,MAAA,IAAA,CAAK,SAAS,MAAA,CAAO,QAAA,CAAS,WAAW,EAAE,EAAA,EAAI,WAAW,CAAA;AAAA,IAC9D;AAEA,IAAA,IAAA,CAAK,WAAW,IAAA,CAAK,kBAAA;AAAA,MACjB,IAAA,CAAK,QAAA;AAAA,MACL,eAAA;AAAA,MACA,kBAAkB,OAAA;AAAQ,KAC9B;AAEA,IAAA,IAAA,CAAK,GAAA,CAAI,eAAe,MAAM,CAAA;AAE9B,IAAA,OAAO,EAAE,OAAA,EAAS,MAAA,EAAQ,SAAA,EAAW,gBAAA,EAAiB;AAAA,EAC1D;AAAA,EAEmB,gBAAgB,IAAA,EAAkB;AACjD,IAAA,MAAM,EAAE,OAAA,EAAS,MAAA,EAAQ,SAAA,EAAW,kBAAiB,GAAI,IAAA;AAEzD,IAAA,IAAA,CAAK,GAAA,CAAI,kBAAkB,MAAM,CAAA;AAEjC,IAAA,IAAI,aAAa,IAAA,EAAM;AACnB,MAAA,IAAA,CAAK,QAAA,CAAS,MAAA,CAAO,WAAA,CAAY,SAAS,CAAA;AAC1C,MAAA,SAAA,CAAU,OAAA,EAAQ;AAAA,IACtB;AACA,IAAA,IAAI,oBAAoB,IAAA,EAAM;AAC1B,MAAA,OAAA,CAAQ,YAAY,gBAAgB,CAAA;AAAA,IACxC;AAEA,IAAA,IAAA,CAAK,UAAU,OAAA,EAAQ;AAAA,EAC3B;AAAA,EAEA,kBAAA,CACI,QAAA,EACA,eAAA,EACA,YAAA,EACmB;AACnB,IAAA,MAAM,oBAAA,GAAuB,gBAAgB,uBAAA,EAAwB;AACrE,IAAA,MAAM,OAAA,GACF,iBAAiB,OAAA,GACX,oBAAA,CAAqB,IAAI,OAAO,CAAA,GAChC,oBAAA,CAAqB,GAAA,CAAI,SAAS,CAAA;AAE5C,IAAA,MAAM,WAAA,GAAc,QAAA,CAAS,QAAA,CAAS,GAAA,CAAI;AAAA,MACtC,SAAA,EAAW,+BAAA;AAAA,MACX,QAAA,EAAU,gBAAA;AAAA,MACV,GAAA,EAAK,8BAAA;AAAA,MACL,MAAA,EAAQ,CAAC,EAAA,EAAI,CAAC,CAAA;AAAA,MACd,WAAA,EAAa,aAAA;AAAA,MACb,QAAA,EAAU,SAAA;AAAA,MACV,OAAA,EAAS;AAAA,KACZ,CAAA;AAED,IAAA,OAAO,WAAA;AAAA,EACX;AACJ;;;;"}
@@ -1,10 +1,10 @@
1
1
  import { Layer } from "@open-pioneer/map";
2
- import { Select } from "ol/interaction";
3
2
  import type { Feature } from "ol";
4
3
  import type { EventsKey } from "ol/events";
5
- import { BaseInteraction } from "./BaseInteraction";
4
+ import { Select } from "ol/interaction";
6
5
  import type { SelectionOptions } from "../../../api/model/InteractionOptions";
7
6
  import { TooltipMessages } from "../controller/EditingController";
7
+ import { BaseInteraction } from "./BaseInteraction";
8
8
  export interface SelectionParameters {
9
9
  readonly layers: Layer[];
10
10
  readonly selectionOptions?: SelectionOptions;
@@ -1,6 +1,6 @@
1
1
  import { Select } from 'ol/interaction.js';
2
- import { unByKey } from 'ol/Observable.js';
3
2
  import { Layer } from 'ol/layer.js';
3
+ import { unByKey } from 'ol/Observable.js';
4
4
  import { BaseInteraction } from './BaseInteraction.js';
5
5
 
6
6
  class SelectionInteraction extends BaseInteraction {
@@ -1 +1 @@
1
- {"version":3,"file":"SelectionInteraction.js","sources":["SelectionInteraction.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2023-2025 Open Pioneer project (https://github.com/open-pioneer)\n// SPDX-License-Identifier: Apache-2.0\nimport { Layer, MapModel, Overlay } from \"@open-pioneer/map\";\nimport { Select } from \"ol/interaction\";\nimport { unByKey } from \"ol/Observable\";\nimport type { Feature } from \"ol\";\nimport type { EventsKey } from \"ol/events\";\nimport { Layer as OlLayer } from \"ol/layer\";\nimport { BaseInteraction } from \"./BaseInteraction\";\nimport type { SelectionOptions } from \"../../../api/model/InteractionOptions\";\nimport { TooltipMessages } from \"../controller/EditingController\";\n\nexport interface SelectionParameters {\n readonly layers: Layer[];\n readonly selectionOptions?: SelectionOptions;\n readonly completionHandler: (feature: Feature, layer: Layer | undefined) => void;\n readonly tooltipMessages: TooltipMessages;\n}\n\ninterface SelectionData {\n readonly select: Select;\n readonly eventsKey: EventsKey;\n}\n\ninterface InternalSelect {\n readonly featureLayerAssociation_?: Record<string, OlLayer>;\n}\n\ninterface InternalFeature extends Feature {\n readonly ol_uid?: string;\n}\n\nexport class SelectionInteraction extends BaseInteraction<SelectionParameters, SelectionData> {\n #tooltip?: Overlay;\n\n protected override startInteraction(parameters: SelectionParameters): SelectionData {\n const { layers, selectionOptions, completionHandler, tooltipMessages } = parameters;\n\n const olLayers = layers\n .map((layer) => layer.olLayer)\n .filter((olLayer) => olLayer instanceof OlLayer);\n\n const select = new Select({\n layers: olLayers,\n hitTolerance: SelectionInteraction.#DEFAULT_HIT_TOLERANCE,\n ...selectionOptions\n });\n\n const eventsKey = select.once(\"select\", ({ selected }) => {\n const feature = selected[0];\n if (feature != null) {\n const layer = this.#getLayer(select, feature);\n completionHandler(feature, layer);\n }\n });\n\n this.#tooltip = this.#createHelpTooltip(this.mapModel, tooltipMessages);\n\n this.map.addInteraction(select);\n\n return { select, eventsKey };\n }\n\n protected override stopInteraction({ select, eventsKey }: SelectionData): void {\n unByKey(eventsKey);\n this.map.removeInteraction(select);\n this.#tooltip?.destroy();\n }\n\n #getLayer(select: Select, feature: Feature): Layer | undefined {\n const olLayer = this.#getOlLayer(select, feature);\n return olLayer != null ? this.mapModel.layers.getLayerByRawInstance(olLayer) : undefined;\n }\n\n // Use internal properties to obtain the layer associated with the selected feature.\n #getOlLayer(select: Select, feature: Feature): OlLayer | undefined {\n const { featureLayerAssociation_ } = select as unknown as InternalSelect;\n const { ol_uid } = feature as InternalFeature;\n return ol_uid != null ? featureLayerAssociation_?.[ol_uid] : undefined;\n }\n\n #createHelpTooltip(mapModel: MapModel, tooltipMessages: TooltipMessages): Overlay | undefined {\n const helpOverlay = mapModel.overlays.add({\n className: \"editing-tooltip printing-hide\",\n position: \"follow-pointer\",\n tag: \"editing-selection-overlay\",\n offset: [15, 0],\n positioning: \"center-left\",\n ariaRole: \"tooltip\",\n content: tooltipMessages.getSelectionMessage()\n });\n\n return helpOverlay;\n }\n\n static readonly #DEFAULT_HIT_TOLERANCE = 22;\n}\n"],"names":["OlLayer"],"mappings":";;;;;AAgCO,MAAM,6BAA6B,eAAA,CAAoD;AAAA,EAC1F,QAAA;AAAA,EAEmB,iBAAiB,UAAA,EAAgD;AAChF,IAAA,MAAM,EAAE,MAAA,EAAQ,gBAAA,EAAkB,iBAAA,EAAmB,iBAAgB,GAAI,UAAA;AAEzE,IAAA,MAAM,QAAA,GAAW,MAAA,CACZ,GAAA,CAAI,CAAC,KAAA,KAAU,KAAA,CAAM,OAAO,CAAA,CAC5B,MAAA,CAAO,CAAC,OAAA,KAAY,OAAA,YAAmBA,KAAO,CAAA;AAEnD,IAAA,MAAM,MAAA,GAAS,IAAI,MAAA,CAAO;AAAA,MACtB,MAAA,EAAQ,QAAA;AAAA,MACR,cAAc,oBAAA,CAAqB,sBAAA;AAAA,MACnC,GAAG;AAAA,KACN,CAAA;AAED,IAAA,MAAM,YAAY,MAAA,CAAO,IAAA,CAAK,UAAU,CAAC,EAAE,UAAS,KAAM;AACtD,MAAA,MAAM,OAAA,GAAU,SAAS,CAAC,CAAA;AAC1B,MAAA,IAAI,WAAW,IAAA,EAAM;AACjB,QAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,SAAA,CAAU,MAAA,EAAQ,OAAO,CAAA;AAC5C,QAAA,iBAAA,CAAkB,SAAS,KAAK,CAAA;AAAA,MACpC;AAAA,IACJ,CAAC,CAAA;AAED,IAAA,IAAA,CAAK,QAAA,GAAW,IAAA,CAAK,kBAAA,CAAmB,IAAA,CAAK,UAAU,eAAe,CAAA;AAEtE,IAAA,IAAA,CAAK,GAAA,CAAI,eAAe,MAAM,CAAA;AAE9B,IAAA,OAAO,EAAE,QAAQ,SAAA,EAAU;AAAA,EAC/B;AAAA,EAEmB,eAAA,CAAgB,EAAE,MAAA,EAAQ,SAAA,EAAU,EAAwB;AAC3E,IAAA,OAAA,CAAQ,SAAS,CAAA;AACjB,IAAA,IAAA,CAAK,GAAA,CAAI,kBAAkB,MAAM,CAAA;AACjC,IAAA,IAAA,CAAK,UAAU,OAAA,EAAQ;AAAA,EAC3B;AAAA,EAEA,SAAA,CAAU,QAAgB,OAAA,EAAqC;AAC3D,IAAA,MAAM,OAAA,GAAU,IAAA,CAAK,WAAA,CAAY,MAAA,EAAQ,OAAO,CAAA;AAChD,IAAA,OAAO,WAAW,IAAA,GAAO,IAAA,CAAK,SAAS,MAAA,CAAO,qBAAA,CAAsB,OAAO,CAAA,GAAI,MAAA;AAAA,EACnF;AAAA;AAAA,EAGA,WAAA,CAAY,QAAgB,OAAA,EAAuC;AAC/D,IAAA,MAAM,EAAE,0BAAyB,GAAI,MAAA;AACrC,IAAA,MAAM,EAAE,QAAO,GAAI,OAAA;AACnB,IAAA,OAAO,MAAA,IAAU,IAAA,GAAO,wBAAA,GAA2B,MAAM,CAAA,GAAI,MAAA;AAAA,EACjE;AAAA,EAEA,kBAAA,CAAmB,UAAoB,eAAA,EAAuD;AAC1F,IAAA,MAAM,WAAA,GAAc,QAAA,CAAS,QAAA,CAAS,GAAA,CAAI;AAAA,MACtC,SAAA,EAAW,+BAAA;AAAA,MACX,QAAA,EAAU,gBAAA;AAAA,MACV,GAAA,EAAK,2BAAA;AAAA,MACL,MAAA,EAAQ,CAAC,EAAA,EAAI,CAAC,CAAA;AAAA,MACd,WAAA,EAAa,aAAA;AAAA,MACb,QAAA,EAAU,SAAA;AAAA,MACV,OAAA,EAAS,gBAAgB,mBAAA;AAAoB,KAChD,CAAA;AAED,IAAA,OAAO,WAAA;AAAA,EACX;AAAA,EAEA,OAAgB,sBAAA,GAAyB,EAAA;AAC7C;;;;"}
1
+ {"version":3,"file":"SelectionInteraction.js","sources":["SelectionInteraction.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2023-2025 Open Pioneer project (https://github.com/open-pioneer)\n// SPDX-License-Identifier: Apache-2.0\n\nimport { Layer, MapModel, Overlay } from \"@open-pioneer/map\";\nimport type { Feature } from \"ol\";\nimport type { EventsKey } from \"ol/events\";\nimport { Select } from \"ol/interaction\";\nimport { Layer as OlLayer } from \"ol/layer\";\nimport { unByKey } from \"ol/Observable\";\nimport type { SelectionOptions } from \"../../../api/model/InteractionOptions\";\nimport { TooltipMessages } from \"../controller/EditingController\";\nimport { BaseInteraction } from \"./BaseInteraction\";\n\nexport interface SelectionParameters {\n readonly layers: Layer[];\n readonly selectionOptions?: SelectionOptions;\n readonly completionHandler: (feature: Feature, layer: Layer | undefined) => void;\n readonly tooltipMessages: TooltipMessages;\n}\n\ninterface SelectionData {\n readonly select: Select;\n readonly eventsKey: EventsKey;\n}\n\ninterface InternalSelect {\n readonly featureLayerAssociation_?: Record<string, OlLayer>;\n}\n\ninterface InternalFeature extends Feature {\n readonly ol_uid?: string;\n}\n\nexport class SelectionInteraction extends BaseInteraction<SelectionParameters, SelectionData> {\n #tooltip?: Overlay;\n\n protected override startInteraction(parameters: SelectionParameters): SelectionData {\n const { layers, selectionOptions, completionHandler, tooltipMessages } = parameters;\n\n const olLayers = layers\n .map((layer) => layer.olLayer)\n .filter((olLayer) => olLayer instanceof OlLayer);\n\n const select = new Select({\n layers: olLayers,\n hitTolerance: SelectionInteraction.#DEFAULT_HIT_TOLERANCE,\n ...selectionOptions\n });\n\n const eventsKey = select.once(\"select\", ({ selected }) => {\n const feature = selected[0];\n if (feature != null) {\n const layer = this.#getLayer(select, feature);\n completionHandler(feature, layer);\n }\n });\n\n this.#tooltip = this.#createHelpTooltip(this.mapModel, tooltipMessages);\n\n this.map.addInteraction(select);\n\n return { select, eventsKey };\n }\n\n protected override stopInteraction({ select, eventsKey }: SelectionData): void {\n unByKey(eventsKey);\n this.map.removeInteraction(select);\n this.#tooltip?.destroy();\n }\n\n #getLayer(select: Select, feature: Feature): Layer | undefined {\n const olLayer = this.#getOlLayer(select, feature);\n return olLayer != null ? this.mapModel.layers.getLayerByRawInstance(olLayer) : undefined;\n }\n\n // Use internal properties to obtain the layer associated with the selected feature.\n #getOlLayer(select: Select, feature: Feature): OlLayer | undefined {\n const { featureLayerAssociation_ } = select as unknown as InternalSelect;\n const { ol_uid } = feature as InternalFeature;\n return ol_uid != null ? featureLayerAssociation_?.[ol_uid] : undefined;\n }\n\n #createHelpTooltip(mapModel: MapModel, tooltipMessages: TooltipMessages): Overlay | undefined {\n const helpOverlay = mapModel.overlays.add({\n className: \"editing-tooltip printing-hide\",\n position: \"follow-pointer\",\n tag: \"editing-selection-overlay\",\n offset: [15, 0],\n positioning: \"center-left\",\n ariaRole: \"tooltip\",\n content: tooltipMessages.getSelectionMessage()\n });\n\n return helpOverlay;\n }\n\n static readonly #DEFAULT_HIT_TOLERANCE = 22;\n}\n"],"names":["OlLayer"],"mappings":";;;;;AAiCO,MAAM,6BAA6B,eAAA,CAAoD;AAAA,EAC1F,QAAA;AAAA,EAEmB,iBAAiB,UAAA,EAAgD;AAChF,IAAA,MAAM,EAAE,MAAA,EAAQ,gBAAA,EAAkB,iBAAA,EAAmB,iBAAgB,GAAI,UAAA;AAEzE,IAAA,MAAM,QAAA,GAAW,MAAA,CACZ,GAAA,CAAI,CAAC,KAAA,KAAU,KAAA,CAAM,OAAO,CAAA,CAC5B,MAAA,CAAO,CAAC,OAAA,KAAY,OAAA,YAAmBA,KAAO,CAAA;AAEnD,IAAA,MAAM,MAAA,GAAS,IAAI,MAAA,CAAO;AAAA,MACtB,MAAA,EAAQ,QAAA;AAAA,MACR,cAAc,oBAAA,CAAqB,sBAAA;AAAA,MACnC,GAAG;AAAA,KACN,CAAA;AAED,IAAA,MAAM,YAAY,MAAA,CAAO,IAAA,CAAK,UAAU,CAAC,EAAE,UAAS,KAAM;AACtD,MAAA,MAAM,OAAA,GAAU,SAAS,CAAC,CAAA;AAC1B,MAAA,IAAI,WAAW,IAAA,EAAM;AACjB,QAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,SAAA,CAAU,MAAA,EAAQ,OAAO,CAAA;AAC5C,QAAA,iBAAA,CAAkB,SAAS,KAAK,CAAA;AAAA,MACpC;AAAA,IACJ,CAAC,CAAA;AAED,IAAA,IAAA,CAAK,QAAA,GAAW,IAAA,CAAK,kBAAA,CAAmB,IAAA,CAAK,UAAU,eAAe,CAAA;AAEtE,IAAA,IAAA,CAAK,GAAA,CAAI,eAAe,MAAM,CAAA;AAE9B,IAAA,OAAO,EAAE,QAAQ,SAAA,EAAU;AAAA,EAC/B;AAAA,EAEmB,eAAA,CAAgB,EAAE,MAAA,EAAQ,SAAA,EAAU,EAAwB;AAC3E,IAAA,OAAA,CAAQ,SAAS,CAAA;AACjB,IAAA,IAAA,CAAK,GAAA,CAAI,kBAAkB,MAAM,CAAA;AACjC,IAAA,IAAA,CAAK,UAAU,OAAA,EAAQ;AAAA,EAC3B;AAAA,EAEA,SAAA,CAAU,QAAgB,OAAA,EAAqC;AAC3D,IAAA,MAAM,OAAA,GAAU,IAAA,CAAK,WAAA,CAAY,MAAA,EAAQ,OAAO,CAAA;AAChD,IAAA,OAAO,WAAW,IAAA,GAAO,IAAA,CAAK,SAAS,MAAA,CAAO,qBAAA,CAAsB,OAAO,CAAA,GAAI,MAAA;AAAA,EACnF;AAAA;AAAA,EAGA,WAAA,CAAY,QAAgB,OAAA,EAAuC;AAC/D,IAAA,MAAM,EAAE,0BAAyB,GAAI,MAAA;AACrC,IAAA,MAAM,EAAE,QAAO,GAAI,OAAA;AACnB,IAAA,OAAO,MAAA,IAAU,IAAA,GAAO,wBAAA,GAA2B,MAAM,CAAA,GAAI,MAAA;AAAA,EACjE;AAAA,EAEA,kBAAA,CAAmB,UAAoB,eAAA,EAAuD;AAC1F,IAAA,MAAM,WAAA,GAAc,QAAA,CAAS,QAAA,CAAS,GAAA,CAAI;AAAA,MACtC,SAAA,EAAW,+BAAA;AAAA,MACX,QAAA,EAAU,gBAAA;AAAA,MACV,GAAA,EAAK,2BAAA;AAAA,MACL,MAAA,EAAQ,CAAC,EAAA,EAAI,CAAC,CAAA;AAAA,MACd,WAAA,EAAa,aAAA;AAAA,MACb,QAAA,EAAU,SAAA;AAAA,MACV,OAAA,EAAS,gBAAgB,mBAAA;AAAoB,KAChD,CAAA;AAED,IAAA,OAAO,WAAA;AAAA,EACX;AAAA,EAEA,OAAgB,sBAAA,GAAyB,EAAA;AAC7C;;;;"}
@@ -1,7 +1,7 @@
1
1
  import { Snap } from "ol/interaction";
2
2
  import type { Vector as VectorSource } from "ol/source";
3
- import { BaseInteraction } from "./BaseInteraction";
4
3
  import type { SnappingOptions } from "../../../api/model/InteractionOptions";
4
+ import { BaseInteraction } from "./BaseInteraction";
5
5
  export interface SnappingParameters {
6
6
  readonly snappingSources: VectorSource[];
7
7
  readonly snappingOptions?: SnappingOptions;
@@ -1 +1 @@
1
- {"version":3,"file":"SnappingInteraction.js","sources":["SnappingInteraction.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2023-2025 Open Pioneer project (https://github.com/open-pioneer)\n// SPDX-License-Identifier: Apache-2.0\nimport { Snap } from \"ol/interaction\";\nimport type { Vector as VectorSource } from \"ol/source\";\nimport { BaseInteraction } from \"./BaseInteraction\";\nimport type { SnappingOptions } from \"../../../api/model/InteractionOptions\";\n\nexport interface SnappingParameters {\n readonly snappingSources: VectorSource[];\n readonly snappingOptions?: SnappingOptions;\n}\n\ninterface SnappingData {\n readonly snaps: Snap[];\n}\n\nexport class SnappingInteraction extends BaseInteraction<SnappingParameters, SnappingData> {\n protected override startInteraction(parameters: SnappingParameters): SnappingData {\n const { snappingSources, snappingOptions } = parameters;\n\n const snaps = snappingSources.map((source) => new Snap({ source, ...snappingOptions }));\n\n for (const snap of snaps) {\n this.map.addInteraction(snap);\n }\n\n return { snaps };\n }\n\n protected override stopInteraction({ snaps }: SnappingData): void {\n for (const snap of snaps) {\n this.map.removeInteraction(snap);\n }\n }\n}\n"],"names":[],"mappings":";;;AAgBO,MAAM,4BAA4B,eAAA,CAAkD;AAAA,EACpE,iBAAiB,UAAA,EAA8C;AAC9E,IAAA,MAAM,EAAE,eAAA,EAAiB,eAAA,EAAgB,GAAI,UAAA;AAE7C,IAAA,MAAM,KAAA,GAAQ,eAAA,CAAgB,GAAA,CAAI,CAAC,MAAA,KAAW,IAAI,IAAA,CAAK,EAAE,MAAA,EAAQ,GAAG,eAAA,EAAiB,CAAC,CAAA;AAEtF,IAAA,KAAA,MAAW,QAAQ,KAAA,EAAO;AACtB,MAAA,IAAA,CAAK,GAAA,CAAI,eAAe,IAAI,CAAA;AAAA,IAChC;AAEA,IAAA,OAAO,EAAE,KAAA,EAAM;AAAA,EACnB;AAAA,EAEmB,eAAA,CAAgB,EAAE,KAAA,EAAM,EAAuB;AAC9D,IAAA,KAAA,MAAW,QAAQ,KAAA,EAAO;AACtB,MAAA,IAAA,CAAK,GAAA,CAAI,kBAAkB,IAAI,CAAA;AAAA,IACnC;AAAA,EACJ;AACJ;;;;"}
1
+ {"version":3,"file":"SnappingInteraction.js","sources":["SnappingInteraction.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2023-2025 Open Pioneer project (https://github.com/open-pioneer)\n// SPDX-License-Identifier: Apache-2.0\n\nimport { Snap } from \"ol/interaction\";\nimport type { Vector as VectorSource } from \"ol/source\";\nimport type { SnappingOptions } from \"../../../api/model/InteractionOptions\";\nimport { BaseInteraction } from \"./BaseInteraction\";\n\nexport interface SnappingParameters {\n readonly snappingSources: VectorSource[];\n readonly snappingOptions?: SnappingOptions;\n}\n\ninterface SnappingData {\n readonly snaps: Snap[];\n}\n\nexport class SnappingInteraction extends BaseInteraction<SnappingParameters, SnappingData> {\n protected override startInteraction(parameters: SnappingParameters): SnappingData {\n const { snappingSources, snappingOptions } = parameters;\n\n const snaps = snappingSources.map((source) => new Snap({ source, ...snappingOptions }));\n\n for (const snap of snaps) {\n this.map.addInteraction(snap);\n }\n\n return { snaps };\n }\n\n protected override stopInteraction({ snaps }: SnappingData): void {\n for (const snap of snaps) {\n this.map.removeInteraction(snap);\n }\n }\n}\n"],"names":[],"mappings":";;;AAiBO,MAAM,4BAA4B,eAAA,CAAkD;AAAA,EACpE,iBAAiB,UAAA,EAA8C;AAC9E,IAAA,MAAM,EAAE,eAAA,EAAiB,eAAA,EAAgB,GAAI,UAAA;AAE7C,IAAA,MAAM,KAAA,GAAQ,eAAA,CAAgB,GAAA,CAAI,CAAC,MAAA,KAAW,IAAI,IAAA,CAAK,EAAE,MAAA,EAAQ,GAAG,eAAA,EAAiB,CAAC,CAAA;AAEtF,IAAA,KAAA,MAAW,QAAQ,KAAA,EAAO;AACtB,MAAA,IAAA,CAAK,GAAA,CAAI,eAAe,IAAI,CAAA;AAAA,IAChC;AAEA,IAAA,OAAO,EAAE,KAAA,EAAM;AAAA,EACnB;AAAA,EAEmB,eAAA,CAAgB,EAAE,KAAA,EAAM,EAAuB;AAC9D,IAAA,KAAA,MAAW,QAAQ,KAAA,EAAO;AACtB,MAAA,IAAA,CAAK,GAAA,CAAI,kBAAkB,IAAI,CAAA;AAAA,IACnC;AAAA,EACJ;AACJ;;;;"}
@@ -1,4 +1,4 @@
1
- import type { MapModelProps } from "@open-pioneer/map";
1
+ import { type MapModelProps } from "@open-pioneer/map";
2
2
  import type { Vector as VectorSource } from "ol/source";
3
3
  import { EditingStep } from "../../api/model/EditingStep";
4
4
  import { InteractionOptions } from "../../api/model/InteractionOptions";
@@ -1 +1 @@
1
- {"version":3,"file":"useGeometryEditing.js","sources":["useGeometryEditing.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2023-2025 Open Pioneer project (https://github.com/open-pioneer)\n// SPDX-License-Identifier: Apache-2.0\nimport type { MapModelProps } from \"@open-pioneer/map\";\nimport { useMapModelValue, type LayerFactory, type MapModel } from \"@open-pioneer/map\";\nimport type { Vector as VectorSource } from \"ol/source\";\nimport { useService } from \"open-pioneer:react-hooks\";\nimport { useEffect, useMemo } from \"react\";\nimport { CreationStep, EditingStep, UpdateStep } from \"../../api/model/EditingStep\";\nimport { InteractionOptions } from \"../../api/model/InteractionOptions\";\nimport { EditingController, TooltipMessages } from \"./controller/EditingController\";\n\n/**\n * Options for the {@link useGeometryEditing} hook.\n *\n * Extends {@link MapModelProps} and {@link InteractionOptions} to provide map integration and\n * interaction configuration, along with editing workflow state management.\n */\nexport interface GeometryEditingOptions extends MapModelProps, InteractionOptions {\n /**\n * The current editing step in the workflow.\n *\n * Determines which interaction is active (drawing, selection, or modification) and what\n * feature is being edited. The hook responds to changes in this step by starting or stopping\n * the appropriate map interactions.\n */\n readonly editingStep: EditingStep;\n\n /**\n * Callback to update the editing step.\n *\n * Called by the editing interactions when the workflow should transition to a new step\n * (e.g., when a drawing is completed and should move to attribute editing).\n */\n readonly setEditingStep: (newEditingStep: EditingStep) => void;\n\n /**\n * Optional vector sources to enable snapping during drawing and modification.\n *\n * Features from these sources will be used as snap targets, allowing drawn geometries to\n * snap to existing features for precise alignment.\n */\n readonly snappingSources?: VectorSource[];\n\n /**\n * Messages shown in the help tooltips of selection, drawing and modification interactions.\n */\n readonly tooltipMessages: TooltipMessages;\n}\n\n/**\n * The state object returned by the `useGeometryEditing` hook, providing both operations and capabilities\n * for the current geometry drawing session.\n *\n * Use the capability flags to enable/disable UI controls, and call the action methods to perform\n * drawing actions.\n * All methods are safe to call at any time; they will have no effect if the corresponding capability flag is `false`.\n *\n * @example\n * ```tsx\n * const drawingState = useGeometryEditing({ map, editingStep, setEditingStep });\n *\n * // Check capabilities before enabling buttons\n * <Button disabled={!drawingState.canUndo} onClick={drawingState.undo}>\n * Undo\n * </Button>\n * ```\n */\nexport interface DrawingState {\n /**\n * Whether the undo operation is currently available.\n *\n * `true` when there are geometry modifications that can be reverted, typically during feature\n * creation workflows.\n */\n readonly canUndo: boolean;\n\n /**\n * Whether the redo operation is currently available.\n *\n * `true` when there are undone modifications that can be reapplied, typically after performing\n * an undo operation.\n */\n readonly canRedo: boolean;\n\n /**\n * Whether the finish operation is currently available.\n *\n * `true` when a polygon or line is being drawn and the minimum required points have been set\n * to form a valid geometry (two vertices for polylines, three vertices for polygons).\n */\n readonly canFinish: boolean;\n\n /**\n * Whether the reset operation is currently available.\n *\n * `true` when a drawing operation for polylines or polygons is in progress and at least one\n * vertex has been set. Allows resetting the drawn geometry to start over.\n */\n readonly canReset: boolean;\n\n /**\n * Undoes the last geometry modification.\n *\n * Only has an effect when `canUndo` is `true`. Typically enabled during feature creation when\n * there are changes to revert.\n */\n undo: () => void;\n\n /**\n * Redoes a previously undone geometry modification.\n *\n * Only has an effect when `canRedo` is `true`. Typically enabled after an undo operation has\n * been performed.\n */\n redo: () => void;\n\n /**\n * Completes the current drawing operation and commits the geometry.\n *\n * Only has an effect when `canFinish` is `true`. Used during polygon or line drawing to\n * finalize the geometry when the minimum required points have been set (two for polylines,\n * three for polygons).\n */\n finish: () => void;\n\n /**\n * Resets the currently drawn geometry to its initial state.\n *\n * Only has an effect when `canReset` is `true`. Used to clear the drawn vertices and start\n * over without completing the geometry.\n */\n reset: () => void;\n}\n\n/**\n * React hook for managing map feature editing interactions.\n *\n * Provides low-level control over the editing workflow by managing map interactions based on the\n * current editing step. This hook handles drawing, selection, and modification interactions, and\n * returns the current drawing state for controlling undo/redo/finish/reset actions.\n *\n * Use this hook when building custom editing implementations that don't use the {@link type }\n * component. For most use cases, the {@link type } component is recommended as it provides a\n * complete editing interface with built-in UI.\n *\n * @param options - Configuration options for the editing workflow\n * @returns The current {@link DrawingState} for the active drawing interaction\n *\n * @example\n * ```tsx\n * function CustomEditor() {\n * const map = useMapModel();\n * const [editingStep, setEditingStep] = useState<EditingStep>({ id: \"none\" });\n * const drawingState = useGeometryEditing({ map, editingStep, setEditingStep });\n *\n * // Render custom UI and controls...\n * }\n * ```\n *\n * @internal\n * Private API for now. Consider publishing this as an \"EditingInteraction\" (not based solely on hooks).\n */\nexport function useGeometryEditing({\n map,\n editingStep,\n setEditingStep,\n snappingSources,\n tooltipMessages,\n ...interactionOptions\n}: GeometryEditingOptions): DrawingState {\n const layerFactory = useService<LayerFactory>(\"map.LayerFactory\");\n const controller = useEditingController(map, layerFactory, tooltipMessages);\n\n useEffect(() => {\n controller.setSnappingSources(snappingSources);\n controller.setInteractionOptions(interactionOptions);\n }, [controller, snappingSources, interactionOptions]);\n\n useEffect(() => {\n switch (editingStep.id) {\n case \"initial\":\n break;\n\n case \"drawing\":\n controller.startDrawingFeature({\n geometryType: editingStep.template.geometryType,\n drawingOptions: editingStep.template.drawingOptions ?? {},\n completionHandler(feature, drawLayer) {\n const template = editingStep.template;\n feature.setProperties(template.defaultProperties ?? {});\n setEditingStep({\n id: \"creation\",\n feature,\n template,\n drawLayer: drawLayer\n } satisfies CreationStep);\n }\n });\n break;\n\n case \"selection\":\n controller.startSelectingFeature({\n layers: editingStep.layers,\n completionHandler(feature, layer) {\n setEditingStep({\n id: \"update\",\n feature,\n layer\n } satisfies UpdateStep);\n }\n });\n break;\n\n case \"creation\":\n controller.startModifyingFeature({\n feature: editingStep.feature,\n drawLayer: editingStep.drawLayer\n });\n break;\n\n case \"update\":\n controller.startModifyingFeature({\n feature: editingStep.feature\n });\n break;\n }\n return () => {\n controller.stopCurrentInteractions();\n };\n }, [controller, editingStep, setEditingStep, tooltipMessages]);\n\n return controller.drawingSession;\n}\n\nfunction useEditingController(\n map: MapModel | undefined,\n layerFactory: LayerFactory,\n tooltipMessages: TooltipMessages\n): EditingController {\n const mapModel = useMapModelValue({ map });\n return useMemo(\n () => new EditingController(mapModel, layerFactory, tooltipMessages),\n [mapModel, layerFactory, tooltipMessages]\n );\n}\n"],"names":[],"mappings":";;;;;AAkKO,SAAS,kBAAA,CAAmB;AAAA,EAC/B,GAAA;AAAA,EACA,WAAA;AAAA,EACA,cAAA;AAAA,EACA,eAAA;AAAA,EACA,eAAA;AAAA,EACA,GAAG;AACP,CAAA,EAAyC;AACrC,EAAA,MAAM,YAAA,GAAe,WAAyB,kBAAkB,CAAA;AAChE,EAAA,MAAM,UAAA,GAAa,oBAAA,CAAqB,GAAA,EAAK,YAAA,EAAc,eAAe,CAAA;AAE1E,EAAA,SAAA,CAAU,MAAM;AACZ,IAAA,UAAA,CAAW,mBAAmB,eAAe,CAAA;AAC7C,IAAA,UAAA,CAAW,sBAAsB,kBAAkB,CAAA;AAAA,EACvD,CAAA,EAAG,CAAC,UAAA,EAAY,eAAA,EAAiB,kBAAkB,CAAC,CAAA;AAEpD,EAAA,SAAA,CAAU,MAAM;AACZ,IAAA,QAAQ,YAAY,EAAA;AAAI,MACpB,KAAK,SAAA;AACD,QAAA;AAAA,MAEJ,KAAK,SAAA;AACD,QAAA,UAAA,CAAW,mBAAA,CAAoB;AAAA,UAC3B,YAAA,EAAc,YAAY,QAAA,CAAS,YAAA;AAAA,UACnC,cAAA,EAAgB,WAAA,CAAY,QAAA,CAAS,cAAA,IAAkB,EAAC;AAAA,UACxD,iBAAA,CAAkB,SAAS,SAAA,EAAW;AAClC,YAAA,MAAM,WAAW,WAAA,CAAY,QAAA;AAC7B,YAAA,OAAA,CAAQ,aAAA,CAAc,QAAA,CAAS,iBAAA,IAAqB,EAAE,CAAA;AACtD,YAAA,cAAA,CAAe;AAAA,cACX,EAAA,EAAI,UAAA;AAAA,cACJ,OAAA;AAAA,cACA,QAAA;AAAA,cACA;AAAA,aACoB,CAAA;AAAA,UAC5B;AAAA,SACH,CAAA;AACD,QAAA;AAAA,MAEJ,KAAK,WAAA;AACD,QAAA,UAAA,CAAW,qBAAA,CAAsB;AAAA,UAC7B,QAAQ,WAAA,CAAY,MAAA;AAAA,UACpB,iBAAA,CAAkB,SAAS,KAAA,EAAO;AAC9B,YAAA,cAAA,CAAe;AAAA,cACX,EAAA,EAAI,QAAA;AAAA,cACJ,OAAA;AAAA,cACA;AAAA,aACkB,CAAA;AAAA,UAC1B;AAAA,SACH,CAAA;AACD,QAAA;AAAA,MAEJ,KAAK,UAAA;AACD,QAAA,UAAA,CAAW,qBAAA,CAAsB;AAAA,UAC7B,SAAS,WAAA,CAAY,OAAA;AAAA,UACrB,WAAW,WAAA,CAAY;AAAA,SAC1B,CAAA;AACD,QAAA;AAAA,MAEJ,KAAK,QAAA;AACD,QAAA,UAAA,CAAW,qBAAA,CAAsB;AAAA,UAC7B,SAAS,WAAA,CAAY;AAAA,SACxB,CAAA;AACD,QAAA;AAAA;AAER,IAAA,OAAO,MAAM;AACT,MAAA,UAAA,CAAW,uBAAA,EAAwB;AAAA,IACvC,CAAA;AAAA,EACJ,GAAG,CAAC,UAAA,EAAY,WAAA,EAAa,cAAA,EAAgB,eAAe,CAAC,CAAA;AAE7D,EAAA,OAAO,UAAA,CAAW,cAAA;AACtB;AAEA,SAAS,oBAAA,CACL,GAAA,EACA,YAAA,EACA,eAAA,EACiB;AACjB,EAAA,MAAM,QAAA,GAAW,gBAAA,CAAiB,EAAE,GAAA,EAAK,CAAA;AACzC,EAAA,OAAO,OAAA;AAAA,IACH,MAAM,IAAI,iBAAA,CAAkB,QAAA,EAAU,cAAc,eAAe,CAAA;AAAA,IACnE,CAAC,QAAA,EAAU,YAAA,EAAc,eAAe;AAAA,GAC5C;AACJ;;;;"}
1
+ {"version":3,"file":"useGeometryEditing.js","sources":["useGeometryEditing.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2023-2025 Open Pioneer project (https://github.com/open-pioneer)\n// SPDX-License-Identifier: Apache-2.0\n\nimport {\n useMapModelValue,\n type LayerFactory,\n type MapModel,\n type MapModelProps\n} from \"@open-pioneer/map\";\nimport type { Vector as VectorSource } from \"ol/source\";\nimport { useService } from \"open-pioneer:react-hooks\";\nimport { useEffect, useMemo } from \"react\";\nimport { CreationStep, EditingStep, UpdateStep } from \"../../api/model/EditingStep\";\nimport { InteractionOptions } from \"../../api/model/InteractionOptions\";\nimport { EditingController, TooltipMessages } from \"./controller/EditingController\";\n\n/**\n * Options for the {@link useGeometryEditing} hook.\n *\n * Extends {@link MapModelProps} and {@link InteractionOptions} to provide map integration and\n * interaction configuration, along with editing workflow state management.\n */\nexport interface GeometryEditingOptions extends MapModelProps, InteractionOptions {\n /**\n * The current editing step in the workflow.\n *\n * Determines which interaction is active (drawing, selection, or modification) and what\n * feature is being edited. The hook responds to changes in this step by starting or stopping\n * the appropriate map interactions.\n */\n readonly editingStep: EditingStep;\n\n /**\n * Callback to update the editing step.\n *\n * Called by the editing interactions when the workflow should transition to a new step\n * (e.g., when a drawing is completed and should move to attribute editing).\n */\n readonly setEditingStep: (newEditingStep: EditingStep) => void;\n\n /**\n * Optional vector sources to enable snapping during drawing and modification.\n *\n * Features from these sources will be used as snap targets, allowing drawn geometries to\n * snap to existing features for precise alignment.\n */\n readonly snappingSources?: VectorSource[];\n\n /**\n * Messages shown in the help tooltips of selection, drawing and modification interactions.\n */\n readonly tooltipMessages: TooltipMessages;\n}\n\n/**\n * The state object returned by the `useGeometryEditing` hook, providing both operations and capabilities\n * for the current geometry drawing session.\n *\n * Use the capability flags to enable/disable UI controls, and call the action methods to perform\n * drawing actions.\n * All methods are safe to call at any time; they will have no effect if the corresponding capability flag is `false`.\n *\n * @example\n * ```tsx\n * const drawingState = useGeometryEditing({ map, editingStep, setEditingStep });\n *\n * // Check capabilities before enabling buttons\n * <Button disabled={!drawingState.canUndo} onClick={drawingState.undo}>\n * Undo\n * </Button>\n * ```\n */\nexport interface DrawingState {\n /**\n * Whether the undo operation is currently available.\n *\n * `true` when there are geometry modifications that can be reverted, typically during feature\n * creation workflows.\n */\n readonly canUndo: boolean;\n\n /**\n * Whether the redo operation is currently available.\n *\n * `true` when there are undone modifications that can be reapplied, typically after performing\n * an undo operation.\n */\n readonly canRedo: boolean;\n\n /**\n * Whether the finish operation is currently available.\n *\n * `true` when a polygon or line is being drawn and the minimum required points have been set\n * to form a valid geometry (two vertices for polylines, three vertices for polygons).\n */\n readonly canFinish: boolean;\n\n /**\n * Whether the reset operation is currently available.\n *\n * `true` when a drawing operation for polylines or polygons is in progress and at least one\n * vertex has been set. Allows resetting the drawn geometry to start over.\n */\n readonly canReset: boolean;\n\n /**\n * Undoes the last geometry modification.\n *\n * Only has an effect when `canUndo` is `true`. Typically enabled during feature creation when\n * there are changes to revert.\n */\n undo: () => void;\n\n /**\n * Redoes a previously undone geometry modification.\n *\n * Only has an effect when `canRedo` is `true`. Typically enabled after an undo operation has\n * been performed.\n */\n redo: () => void;\n\n /**\n * Completes the current drawing operation and commits the geometry.\n *\n * Only has an effect when `canFinish` is `true`. Used during polygon or line drawing to\n * finalize the geometry when the minimum required points have been set (two for polylines,\n * three for polygons).\n */\n finish: () => void;\n\n /**\n * Resets the currently drawn geometry to its initial state.\n *\n * Only has an effect when `canReset` is `true`. Used to clear the drawn vertices and start\n * over without completing the geometry.\n */\n reset: () => void;\n}\n\n/**\n * React hook for managing map feature editing interactions.\n *\n * Provides low-level control over the editing workflow by managing map interactions based on the\n * current editing step. This hook handles drawing, selection, and modification interactions, and\n * returns the current drawing state for controlling undo/redo/finish/reset actions.\n *\n * Use this hook when building custom editing implementations that don't use the {@link type }\n * component. For most use cases, the {@link type } component is recommended as it provides a\n * complete editing interface with built-in UI.\n *\n * @param options - Configuration options for the editing workflow\n * @returns The current {@link DrawingState} for the active drawing interaction\n *\n * @example\n * ```tsx\n * function CustomEditor() {\n * const map = useMapModel();\n * const [editingStep, setEditingStep] = useState<EditingStep>({ id: \"none\" });\n * const drawingState = useGeometryEditing({ map, editingStep, setEditingStep });\n *\n * // Render custom UI and controls...\n * }\n * ```\n *\n * @internal\n * Private API for now. Consider publishing this as an \"EditingInteraction\" (not based solely on hooks).\n */\nexport function useGeometryEditing({\n map,\n editingStep,\n setEditingStep,\n snappingSources,\n tooltipMessages,\n ...interactionOptions\n}: GeometryEditingOptions): DrawingState {\n const layerFactory = useService<LayerFactory>(\"map.LayerFactory\");\n const controller = useEditingController(map, layerFactory, tooltipMessages);\n\n useEffect(() => {\n controller.setSnappingSources(snappingSources);\n controller.setInteractionOptions(interactionOptions);\n }, [controller, snappingSources, interactionOptions]);\n\n useEffect(() => {\n switch (editingStep.id) {\n case \"initial\":\n break;\n\n case \"drawing\":\n controller.startDrawingFeature({\n geometryType: editingStep.template.geometryType,\n drawingOptions: editingStep.template.drawingOptions ?? {},\n completionHandler(feature, drawLayer) {\n const template = editingStep.template;\n feature.setProperties(template.defaultProperties ?? {});\n setEditingStep({\n id: \"creation\",\n feature,\n template,\n drawLayer: drawLayer\n } satisfies CreationStep);\n }\n });\n break;\n\n case \"selection\":\n controller.startSelectingFeature({\n layers: editingStep.layers,\n completionHandler(feature, layer) {\n setEditingStep({\n id: \"update\",\n feature,\n layer\n } satisfies UpdateStep);\n }\n });\n break;\n\n case \"creation\":\n controller.startModifyingFeature({\n feature: editingStep.feature,\n drawLayer: editingStep.drawLayer\n });\n break;\n\n case \"update\":\n controller.startModifyingFeature({\n feature: editingStep.feature\n });\n break;\n }\n return () => {\n controller.stopCurrentInteractions();\n };\n }, [controller, editingStep, setEditingStep, tooltipMessages]);\n\n return controller.drawingSession;\n}\n\nfunction useEditingController(\n map: MapModel | undefined,\n layerFactory: LayerFactory,\n tooltipMessages: TooltipMessages\n): EditingController {\n const mapModel = useMapModelValue({ map });\n return useMemo(\n () => new EditingController(mapModel, layerFactory, tooltipMessages),\n [mapModel, layerFactory, tooltipMessages]\n );\n}\n"],"names":[],"mappings":";;;;;AAuKO,SAAS,kBAAA,CAAmB;AAAA,EAC/B,GAAA;AAAA,EACA,WAAA;AAAA,EACA,cAAA;AAAA,EACA,eAAA;AAAA,EACA,eAAA;AAAA,EACA,GAAG;AACP,CAAA,EAAyC;AACrC,EAAA,MAAM,YAAA,GAAe,WAAyB,kBAAkB,CAAA;AAChE,EAAA,MAAM,UAAA,GAAa,oBAAA,CAAqB,GAAA,EAAK,YAAA,EAAc,eAAe,CAAA;AAE1E,EAAA,SAAA,CAAU,MAAM;AACZ,IAAA,UAAA,CAAW,mBAAmB,eAAe,CAAA;AAC7C,IAAA,UAAA,CAAW,sBAAsB,kBAAkB,CAAA;AAAA,EACvD,CAAA,EAAG,CAAC,UAAA,EAAY,eAAA,EAAiB,kBAAkB,CAAC,CAAA;AAEpD,EAAA,SAAA,CAAU,MAAM;AACZ,IAAA,QAAQ,YAAY,EAAA;AAAI,MACpB,KAAK,SAAA;AACD,QAAA;AAAA,MAEJ,KAAK,SAAA;AACD,QAAA,UAAA,CAAW,mBAAA,CAAoB;AAAA,UAC3B,YAAA,EAAc,YAAY,QAAA,CAAS,YAAA;AAAA,UACnC,cAAA,EAAgB,WAAA,CAAY,QAAA,CAAS,cAAA,IAAkB,EAAC;AAAA,UACxD,iBAAA,CAAkB,SAAS,SAAA,EAAW;AAClC,YAAA,MAAM,WAAW,WAAA,CAAY,QAAA;AAC7B,YAAA,OAAA,CAAQ,aAAA,CAAc,QAAA,CAAS,iBAAA,IAAqB,EAAE,CAAA;AACtD,YAAA,cAAA,CAAe;AAAA,cACX,EAAA,EAAI,UAAA;AAAA,cACJ,OAAA;AAAA,cACA,QAAA;AAAA,cACA;AAAA,aACoB,CAAA;AAAA,UAC5B;AAAA,SACH,CAAA;AACD,QAAA;AAAA,MAEJ,KAAK,WAAA;AACD,QAAA,UAAA,CAAW,qBAAA,CAAsB;AAAA,UAC7B,QAAQ,WAAA,CAAY,MAAA;AAAA,UACpB,iBAAA,CAAkB,SAAS,KAAA,EAAO;AAC9B,YAAA,cAAA,CAAe;AAAA,cACX,EAAA,EAAI,QAAA;AAAA,cACJ,OAAA;AAAA,cACA;AAAA,aACkB,CAAA;AAAA,UAC1B;AAAA,SACH,CAAA;AACD,QAAA;AAAA,MAEJ,KAAK,UAAA;AACD,QAAA,UAAA,CAAW,qBAAA,CAAsB;AAAA,UAC7B,SAAS,WAAA,CAAY,OAAA;AAAA,UACrB,WAAW,WAAA,CAAY;AAAA,SAC1B,CAAA;AACD,QAAA;AAAA,MAEJ,KAAK,QAAA;AACD,QAAA,UAAA,CAAW,qBAAA,CAAsB;AAAA,UAC7B,SAAS,WAAA,CAAY;AAAA,SACxB,CAAA;AACD,QAAA;AAAA;AAER,IAAA,OAAO,MAAM;AACT,MAAA,UAAA,CAAW,uBAAA,EAAwB;AAAA,IACvC,CAAA;AAAA,EACJ,GAAG,CAAC,UAAA,EAAY,WAAA,EAAa,cAAA,EAAgB,eAAe,CAAC,CAAA;AAE7D,EAAA,OAAO,UAAA,CAAW,cAAA;AACtB;AAEA,SAAS,oBAAA,CACL,GAAA,EACA,YAAA,EACA,eAAA,EACiB;AACjB,EAAA,MAAM,QAAA,GAAW,gBAAA,CAAiB,EAAE,GAAA,EAAK,CAAA;AACzC,EAAA,OAAO,OAAA;AAAA,IACH,MAAM,IAAI,iBAAA,CAAkB,QAAA,EAAU,cAAc,eAAe,CAAA;AAAA,IACnE,CAAC,QAAA,EAAU,YAAA,EAAc,eAAe;AAAA,GAC5C;AACJ;;;;"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "type": "module",
3
3
  "name": "@open-pioneer/feature-editing",
4
- "version": "1.4.0-dev.20260727093741",
4
+ "version": "1.4.0",
5
5
  "description": "Provides a component to create and edit feature geometries and properties.",
6
6
  "keywords": [
7
7
  "open-pioneer-trails"
@@ -17,16 +17,16 @@
17
17
  "@chakra-ui/react": "^3.36.1",
18
18
  "@conterra/reactivity-core": "^0.8.6",
19
19
  "@formatjs/intl": "^4.1.17",
20
- "@open-pioneer/chakra-snippets": "4.7.0-dev.20260727091735",
21
- "@open-pioneer/core": "4.7.0-dev.20260727091735",
22
- "@open-pioneer/notifier": "4.7.0-dev.20260727091735",
23
- "@open-pioneer/react-utils": "4.7.0-dev.20260727091735",
24
- "@open-pioneer/reactivity": "4.7.0-dev.20260727091735",
25
- "@open-pioneer/runtime": "4.7.0-dev.20260727091735",
26
- "react": "^19.2.8",
20
+ "@open-pioneer/chakra-snippets": "^4.7.0",
21
+ "@open-pioneer/core": "^4.7.0",
22
+ "@open-pioneer/notifier": "^4.7.0",
23
+ "@open-pioneer/react-utils": "^4.7.0",
24
+ "@open-pioneer/reactivity": "^4.7.0",
25
+ "@open-pioneer/runtime": "^4.7.0",
27
26
  "ol": "^10.9.0",
27
+ "react": "^19.2.8",
28
28
  "react-icons": "^5.7.0",
29
- "@open-pioneer/map": "1.4.0-dev.20260727093741"
29
+ "@open-pioneer/map": "1.4.0"
30
30
  },
31
31
  "exports": {
32
32
  "./package.json": "./package.json",