@open-pioneer/measurement 1.0.0-dev.20251021074813 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,20 +1,23 @@
1
1
  # @open-pioneer/measurement
2
2
 
3
- ## 1.0.0-dev.20251021074813
3
+ ## 1.0.0
4
4
 
5
5
  ### Minor Changes
6
6
 
7
- - 2abcaaf: Update to chakra-ui 3.27.1
7
+ - 2abcaaf: Update to chakra-ui 3.28.0
8
8
 
9
9
  ### Patch Changes
10
10
 
11
11
  - 10d2fe7: Update dependencies
12
- - 138d85b: Update core packages to 4.1.0
12
+ - 4f1e7bd: The highlight layer(s) created by this package now uses the map model's `topmost` option to register an (internal) layer.
13
+ The previous implementation was based on adding a "raw" OpenLayers layer to the `olMap`.
14
+ - 138d85b: Update core packages to 4.2.0
13
15
  - 030e657: The measurement tooltip was fixed to update its text even if the mouse is not moved.
14
16
  - da6a410: Update dependencies
15
17
  - Updated dependencies [c6180c6]
16
18
  - Updated dependencies [29a10df]
17
19
  - Updated dependencies [10d2fe7]
20
+ - Updated dependencies [4f1e7bd]
18
21
  - Updated dependencies [2702df4]
19
22
  - Updated dependencies [12561fe]
20
23
  - Updated dependencies [5df900f]
@@ -22,6 +25,7 @@
22
25
  - Updated dependencies [b3709f1]
23
26
  - Updated dependencies [14c484e]
24
27
  - Updated dependencies [138d85b]
28
+ - Updated dependencies [4f1e7bd]
25
29
  - Updated dependencies [aeb9000]
26
30
  - Updated dependencies [9e9bc6e]
27
31
  - Updated dependencies [b3709f1]
@@ -33,7 +37,7 @@
33
37
  - Updated dependencies [773fa2d]
34
38
  - Updated dependencies [2abcaaf]
35
39
  - Updated dependencies [da6a410]
36
- - @open-pioneer/map@1.0.0-dev.20251021074813
40
+ - @open-pioneer/map@1.0.0
37
41
 
38
42
  ## 0.11.0
39
43
 
package/Measurement.js CHANGED
@@ -4,7 +4,7 @@ import { NativeSelectRoot, NativeSelectField } from '@open-pioneer/chakra-snippe
4
4
  import { useMapModelValue } from '@open-pioneer/map';
5
5
  import { useCommonComponentProps } from '@open-pioneer/react-utils';
6
6
  import { Style, Stroke, Circle, Fill } from 'ol/style.js';
7
- import { useIntl } from './_virtual/_virtual-pioneer-module_react-hooks.js';
7
+ import { useIntl, useService } from './_virtual/_virtual-pioneer-module_react-hooks.js';
8
8
  import { useState, useEffect } from 'react';
9
9
  import { MeasurementController } from './MeasurementController.js';
10
10
 
@@ -71,8 +71,12 @@ function useController(map, props, intl) {
71
71
  predefinedMeasurements
72
72
  } = props;
73
73
  const [controller, setController] = useState(void 0);
74
+ const layerFactory = useService("map.LayerFactory");
74
75
  useEffect(() => {
75
- const controller2 = new MeasurementController(map.olMap, {
76
+ if (!map) {
77
+ return;
78
+ }
79
+ const controller2 = new MeasurementController(map, layerFactory, {
76
80
  getContinueMessage() {
77
81
  return intl.formatMessage({ id: "tooltips.continue" });
78
82
  },
@@ -90,7 +94,7 @@ function useController(map, props, intl) {
90
94
  controller2.destroy();
91
95
  setController(void 0);
92
96
  };
93
- }, [map, intl]);
97
+ }, [map, intl, layerFactory]);
94
98
  useEffect(() => {
95
99
  controller?.setActiveFeatureStyle(activeFeatureStyle ?? getDefaultActiveFeatureStyle());
96
100
  }, [controller, activeFeatureStyle]);
@@ -1 +1 @@
1
- {"version":3,"file":"Measurement.js","sources":["Measurement.tsx"],"sourcesContent":["// SPDX-FileCopyrightText: 2023-2025 Open Pioneer project (https://github.com/open-pioneer)\n// SPDX-License-Identifier: Apache-2.0\nimport { Box, Button, Field, HStack, Text } from \"@chakra-ui/react\";\nimport { NativeSelectField, NativeSelectRoot } from \"@open-pioneer/chakra-snippets/native-select\";\nimport { MapModel, MapModelProps, useMapModelValue } from \"@open-pioneer/map\";\nimport { CommonComponentProps, useCommonComponentProps } from \"@open-pioneer/react-utils\";\nimport { PackageIntl } from \"@open-pioneer/runtime\";\nimport LineString from \"ol/geom/LineString\";\nimport Polygon from \"ol/geom/Polygon\";\nimport { Circle as CircleStyle, Fill, Stroke, Style } from \"ol/style\";\nimport { StyleLike } from \"ol/style/Style\";\nimport { useIntl } from \"open-pioneer:react-hooks\";\nimport { FC, useEffect, useState } from \"react\";\nimport { MeasurementController, MeasurementType } from \"./MeasurementController\";\n\n/** Emitted when a new measurement is being added to the map. */\nexport interface MeasurementsAddEvent {\n kind: \"add-measurement\";\n geometry: MeasurementGeometry;\n}\n\n/** Emitted when a measurement is being removed from the map. */\nexport interface MeasurementsRemoveEvent {\n kind: \"remove-measurement\";\n geometry: MeasurementGeometry;\n}\n\n/**\n * A change event emitted by {@link Measurement} when measurements change.\n *\n * NOTE: Non-exhaustive. More event types may be added in a future version.\n **/\nexport type MeasurementsChangeEvent = MeasurementsAddEvent | MeasurementsRemoveEvent;\n\n/**\n * Represents the geometry of a measurement.\n */\nexport type MeasurementGeometry = LineString | Polygon;\n\n/**\n * This is for special properties of the Measurement.\n */\nexport interface MeasurementProps extends CommonComponentProps, MapModelProps {\n /**\n * The style for the active drawing feature's geometry.\n */\n activeFeatureStyle?: StyleLike;\n\n /**\n * The style for the finished drawn feature's geometry.\n */\n finishedFeatureStyle?: StyleLike;\n\n /**\n * List of measurements to be rendered when the component is initialized.\n */\n predefinedMeasurements?: MeasurementGeometry[];\n\n /**\n * Event handler that is called whenever a measurement is added or removed.\n */\n onMeasurementsChange?: (event: MeasurementsChangeEvent) => void;\n}\n\n/**\n * The `Measurement` component can be used in an app to measure geometries (areas or lines) on the map.\n */\nexport const Measurement: FC<MeasurementProps> = (props) => {\n const intl = useIntl();\n const { containerProps } = useCommonComponentProps(\"measurement\", props);\n const [selectedMeasurement, setMeasurement] = useState<MeasurementType>(\"distance\");\n const label = (id: string) => intl.formatMessage({ id: id });\n const map = useMapModelValue(props);\n const controller = useController(map, props, intl);\n\n // Start / Stop measurement on selection change\n useEffect(() => {\n if (!controller) {\n return;\n }\n\n controller.startMeasurement(selectedMeasurement);\n return () => {\n controller.stopMeasurement();\n };\n }, [controller, selectedMeasurement]);\n\n function changeMeasurement(measurementType: string) {\n if (measurementType === \"distance\" || measurementType === \"area\") {\n setMeasurement(measurementType);\n } else {\n throw new Error(`Unexpected measurement type: '${measurementType}'.`);\n }\n }\n\n function removeMeasurements() {\n controller?.clearMeasurements();\n }\n\n return (\n <Box {...containerProps}>\n <Text mb={3}>{intl.formatMessage({ id: \"measurementInfoText\" })}</Text>\n <Field.Root mb={4} asChild>\n <HStack mb={2} alignItems=\"center\">\n <Field.Label mb={1}>{label(\"measurementLabel\")}</Field.Label>\n <NativeSelectRoot>\n <NativeSelectField\n value={selectedMeasurement}\n onChange={(e) => changeMeasurement(e.target.value)}\n className=\"measurement-select\"\n >\n <option value={\"distance\"}>{label(\"distance\")}</option>\n <option value={\"area\"}>{label(\"area\")}</option>\n </NativeSelectField>\n </NativeSelectRoot>\n </HStack>\n </Field.Root>\n <Button\n padding={2}\n className=\"measurement-delete-button\"\n onClick={removeMeasurements}\n width=\"100%\"\n >\n {label(\"deleteMeasurementLabel\")}\n </Button>\n </Box>\n );\n};\n\n/** Creates a MeasurementController instance for the given map. */\nfunction useController(map: MapModel, props: MeasurementProps, intl: PackageIntl) {\n const {\n activeFeatureStyle,\n finishedFeatureStyle,\n onMeasurementsChange,\n predefinedMeasurements\n } = props;\n const [controller, setController] = useState<MeasurementController | undefined>(undefined);\n useEffect(() => {\n const controller = new MeasurementController(map.olMap, {\n getContinueMessage() {\n return intl.formatMessage({ id: \"tooltips.continue\" });\n },\n getHelpMessage() {\n return intl.formatMessage({ id: \"tooltips.help\" });\n },\n formatNumber(value) {\n return intl.formatNumber(value, {\n maximumFractionDigits: 2\n });\n }\n });\n\n setController(controller);\n return () => {\n controller.destroy();\n setController(undefined);\n };\n }, [map, intl]);\n\n // Synchronize styles with controller\n useEffect(() => {\n controller?.setActiveFeatureStyle(activeFeatureStyle ?? getDefaultActiveFeatureStyle());\n }, [controller, activeFeatureStyle]);\n useEffect(() => {\n controller?.setFinishedFeatureStyle(\n finishedFeatureStyle ?? getDefaultFinishedFeatureStyle()\n );\n }, [controller, finishedFeatureStyle]);\n useEffect(() => {\n controller?.setMeasurementSourceChangedHandler(onMeasurementsChange);\n }, [controller, onMeasurementsChange]);\n\n useEffect(() => {\n controller?.setPredefinedMeasurements(predefinedMeasurements ?? []);\n }, [controller, predefinedMeasurements]);\n return controller;\n}\n\nfunction getDefaultActiveFeatureStyle() {\n return [\n new Style({\n stroke: new Stroke({\n color: \"#fff\",\n lineDash: [10, 10],\n width: 5\n })\n }),\n new Style({\n fill: new Fill({\n color: \"rgba(0,0,0,0.15)\"\n }),\n stroke: new Stroke({\n color: \"rgba(0, 0, 0, 0.7)\",\n lineDash: [10, 10],\n width: 3\n }),\n image: new CircleStyle({\n radius: 5,\n stroke: new Stroke({\n color: \"rgba(0, 0, 0, 0.7)\",\n width: 2\n }),\n fill: new Fill({\n color: \"rgba(255, 255, 255, 0.2)\"\n })\n })\n })\n ];\n}\n\nfunction getDefaultFinishedFeatureStyle() {\n return [\n new Style({\n stroke: new Stroke({\n color: \"#fff\",\n width: 5\n })\n }),\n new Style({\n stroke: new Stroke({\n color: \"#0b96fc\",\n width: 3\n }),\n fill: new Fill({\n color: \"rgba(11,150,252,0.15)\"\n })\n })\n ];\n}\n"],"names":["controller","CircleStyle"],"mappings":"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"}
1
+ {"version":3,"file":"Measurement.js","sources":["Measurement.tsx"],"sourcesContent":["// SPDX-FileCopyrightText: 2023-2025 Open Pioneer project (https://github.com/open-pioneer)\n// SPDX-License-Identifier: Apache-2.0\nimport { Box, Button, Field, HStack, Text } from \"@chakra-ui/react\";\nimport { NativeSelectField, NativeSelectRoot } from \"@open-pioneer/chakra-snippets/native-select\";\nimport { LayerFactory, MapModel, MapModelProps, useMapModelValue } from \"@open-pioneer/map\";\nimport { CommonComponentProps, useCommonComponentProps } from \"@open-pioneer/react-utils\";\nimport { PackageIntl } from \"@open-pioneer/runtime\";\nimport LineString from \"ol/geom/LineString\";\nimport Polygon from \"ol/geom/Polygon\";\nimport { Circle as CircleStyle, Fill, Stroke, Style } from \"ol/style\";\nimport { StyleLike } from \"ol/style/Style\";\nimport { useIntl, useService } from \"open-pioneer:react-hooks\";\nimport { FC, useEffect, useState } from \"react\";\nimport { MeasurementController, MeasurementType } from \"./MeasurementController\";\n\n/** Emitted when a new measurement is being added to the map. */\nexport interface MeasurementsAddEvent {\n kind: \"add-measurement\";\n geometry: MeasurementGeometry;\n}\n\n/** Emitted when a measurement is being removed from the map. */\nexport interface MeasurementsRemoveEvent {\n kind: \"remove-measurement\";\n geometry: MeasurementGeometry;\n}\n\n/**\n * A change event emitted by {@link Measurement} when measurements change.\n *\n * NOTE: Non-exhaustive. More event types may be added in a future version.\n **/\nexport type MeasurementsChangeEvent = MeasurementsAddEvent | MeasurementsRemoveEvent;\n\n/**\n * Represents the geometry of a measurement.\n */\nexport type MeasurementGeometry = LineString | Polygon;\n\n/**\n * This is for special properties of the Measurement.\n */\nexport interface MeasurementProps extends CommonComponentProps, MapModelProps {\n /**\n * The style for the active drawing feature's geometry.\n */\n activeFeatureStyle?: StyleLike;\n\n /**\n * The style for the finished drawn feature's geometry.\n */\n finishedFeatureStyle?: StyleLike;\n\n /**\n * List of measurements to be rendered when the component is initialized.\n */\n predefinedMeasurements?: MeasurementGeometry[];\n\n /**\n * Event handler that is called whenever a measurement is added or removed.\n */\n onMeasurementsChange?: (event: MeasurementsChangeEvent) => void;\n}\n\n/**\n * The `Measurement` component can be used in an app to measure geometries (areas or lines) on the map.\n */\nexport const Measurement: FC<MeasurementProps> = (props) => {\n const intl = useIntl();\n const { containerProps } = useCommonComponentProps(\"measurement\", props);\n const [selectedMeasurement, setMeasurement] = useState<MeasurementType>(\"distance\");\n const label = (id: string) => intl.formatMessage({ id: id });\n const map = useMapModelValue(props);\n const controller = useController(map, props, intl);\n\n // Start / Stop measurement on selection change\n useEffect(() => {\n if (!controller) {\n return;\n }\n\n controller.startMeasurement(selectedMeasurement);\n return () => {\n controller.stopMeasurement();\n };\n }, [controller, selectedMeasurement]);\n\n function changeMeasurement(measurementType: string) {\n if (measurementType === \"distance\" || measurementType === \"area\") {\n setMeasurement(measurementType);\n } else {\n throw new Error(`Unexpected measurement type: '${measurementType}'.`);\n }\n }\n\n function removeMeasurements() {\n controller?.clearMeasurements();\n }\n\n return (\n <Box {...containerProps}>\n <Text mb={3}>{intl.formatMessage({ id: \"measurementInfoText\" })}</Text>\n <Field.Root mb={4} asChild>\n <HStack mb={2} alignItems=\"center\">\n <Field.Label mb={1}>{label(\"measurementLabel\")}</Field.Label>\n <NativeSelectRoot>\n <NativeSelectField\n value={selectedMeasurement}\n onChange={(e) => changeMeasurement(e.target.value)}\n className=\"measurement-select\"\n >\n <option value={\"distance\"}>{label(\"distance\")}</option>\n <option value={\"area\"}>{label(\"area\")}</option>\n </NativeSelectField>\n </NativeSelectRoot>\n </HStack>\n </Field.Root>\n <Button\n padding={2}\n className=\"measurement-delete-button\"\n onClick={removeMeasurements}\n width=\"100%\"\n >\n {label(\"deleteMeasurementLabel\")}\n </Button>\n </Box>\n );\n};\n\n/** Creates a MeasurementController instance for the given map. */\nfunction useController(map: MapModel, props: MeasurementProps, intl: PackageIntl) {\n const {\n activeFeatureStyle,\n finishedFeatureStyle,\n onMeasurementsChange,\n predefinedMeasurements\n } = props;\n const [controller, setController] = useState<MeasurementController | undefined>(undefined);\n const layerFactory = useService<LayerFactory>(\"map.LayerFactory\");\n useEffect(() => {\n if (!map) {\n return;\n }\n const controller = new MeasurementController(map, layerFactory, {\n getContinueMessage() {\n return intl.formatMessage({ id: \"tooltips.continue\" });\n },\n getHelpMessage() {\n return intl.formatMessage({ id: \"tooltips.help\" });\n },\n formatNumber(value) {\n return intl.formatNumber(value, {\n maximumFractionDigits: 2\n });\n }\n });\n\n setController(controller);\n return () => {\n controller.destroy();\n setController(undefined);\n };\n }, [map, intl, layerFactory]);\n\n // Synchronize styles with controller\n useEffect(() => {\n controller?.setActiveFeatureStyle(activeFeatureStyle ?? getDefaultActiveFeatureStyle());\n }, [controller, activeFeatureStyle]);\n useEffect(() => {\n controller?.setFinishedFeatureStyle(\n finishedFeatureStyle ?? getDefaultFinishedFeatureStyle()\n );\n }, [controller, finishedFeatureStyle]);\n useEffect(() => {\n controller?.setMeasurementSourceChangedHandler(onMeasurementsChange);\n }, [controller, onMeasurementsChange]);\n\n useEffect(() => {\n controller?.setPredefinedMeasurements(predefinedMeasurements ?? []);\n }, [controller, predefinedMeasurements]);\n return controller;\n}\n\nfunction getDefaultActiveFeatureStyle() {\n return [\n new Style({\n stroke: new Stroke({\n color: \"#fff\",\n lineDash: [10, 10],\n width: 5\n })\n }),\n new Style({\n fill: new Fill({\n color: \"rgba(0,0,0,0.15)\"\n }),\n stroke: new Stroke({\n color: \"rgba(0, 0, 0, 0.7)\",\n lineDash: [10, 10],\n width: 3\n }),\n image: new CircleStyle({\n radius: 5,\n stroke: new Stroke({\n color: \"rgba(0, 0, 0, 0.7)\",\n width: 2\n }),\n fill: new Fill({\n color: \"rgba(255, 255, 255, 0.2)\"\n })\n })\n })\n ];\n}\n\nfunction getDefaultFinishedFeatureStyle() {\n return [\n new Style({\n stroke: new Stroke({\n color: \"#fff\",\n width: 5\n })\n }),\n new Style({\n stroke: new Stroke({\n color: \"#0b96fc\",\n width: 3\n }),\n fill: new Fill({\n color: \"rgba(11,150,252,0.15)\"\n })\n })\n ];\n}\n"],"names":["controller","CircleStyle"],"mappings":"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"}
@@ -1,7 +1,6 @@
1
- import Feature from "ol/Feature";
1
+ import { LayerFactory, MapModel } from "@open-pioneer/map";
2
2
  import OlMap from "ol/Map";
3
3
  import { Vector as VectorLayer } from "ol/layer";
4
- import { Vector as VectorSource } from "ol/source";
5
4
  import { StyleLike } from "ol/style/Style";
6
5
  import type { MeasurementGeometry, MeasurementProps } from "./Measurement";
7
6
  type MeasurementsChangeHandler = NonNullable<MeasurementProps["onMeasurementsChange"]>;
@@ -12,6 +11,7 @@ export interface Messages {
12
11
  formatNumber(value: number): string;
13
12
  }
14
13
  export declare class MeasurementController {
14
+ readonly map: MapModel;
15
15
  readonly olMap: OlMap;
16
16
  readonly messages: Messages;
17
17
  private activeFeatureStyle;
@@ -54,10 +54,10 @@ export declare class MeasurementController {
54
54
  * Called when a measurement is added to or removed from the source.
55
55
  */
56
56
  private measurementChangedHandler;
57
- constructor(olMap: OlMap, messages: Messages);
57
+ constructor(map: MapModel, layerFactory: LayerFactory, messages: Messages);
58
58
  destroy(): void;
59
59
  /** Returns the vector layer used for finished features. */
60
- getVectorLayer(): VectorLayer<VectorSource<Feature<import("ol/geom").Geometry>>, Feature<import("ol/geom").Geometry>>;
60
+ getOlVectorLayer(): VectorLayer;
61
61
  /** Updates the style used for finished features. */
62
62
  setFinishedFeatureStyle(style: StyleLike): void;
63
63
  setMeasurementSourceChangedHandler(handler: MeasurementsChangeHandler | undefined): void;
@@ -1,5 +1,5 @@
1
1
  import { destroyResource } from '@open-pioneer/core';
2
- import { TOPMOST_LAYER_Z } from '@open-pioneer/map';
2
+ import { SimpleLayer } from '@open-pioneer/map';
3
3
  import Feature from 'ol/Feature.js';
4
4
  import { unByKey } from 'ol/Observable.js';
5
5
  import Overlay from 'ol/Overlay.js';
@@ -11,6 +11,7 @@ import { getArea, getLength } from 'ol/sphere.js';
11
11
  import { toFunction } from 'ol/style/Style.js';
12
12
 
13
13
  class MeasurementController {
14
+ map;
14
15
  olMap;
15
16
  messages;
16
17
  activeFeatureStyle;
@@ -53,19 +54,21 @@ class MeasurementController {
53
54
  * Called when a measurement is added to or removed from the source.
54
55
  */
55
56
  measurementChangedHandler;
56
- constructor(olMap, messages) {
57
- this.olMap = olMap;
57
+ constructor(map, layerFactory, messages) {
58
+ this.map = map;
59
+ this.olMap = map.olMap;
58
60
  this.messages = messages;
59
61
  const source = this.source = new Vector();
60
- this.layer = new Vector$1({
61
- source,
62
- zIndex: TOPMOST_LAYER_Z,
63
- properties: {
64
- name: "measurement-layer"
65
- }
62
+ this.layer = layerFactory.create({
63
+ type: SimpleLayer,
64
+ internal: true,
65
+ title: "measurement-layer",
66
+ olLayer: new Vector$1({
67
+ source
68
+ })
66
69
  });
67
- olMap.addLayer(this.layer);
68
- const pointerMoveKey = olMap.on(
70
+ map.layers.addLayer(this.layer, { at: "topmost" });
71
+ const pointerMoveKey = this.olMap.on(
69
72
  // @ts-expect-error pointermove not declared
70
73
  "pointermove",
71
74
  this.handlePointerMove.bind(this)
@@ -89,19 +92,18 @@ class MeasurementController {
89
92
  }
90
93
  this.finishedMeasurements.clear();
91
94
  this.helpTooltip.destroy();
92
- this.olMap.removeLayer(this.layer);
93
- this.layer.dispose();
94
- this.source.dispose();
95
+ this.map.layers.removeLayer(this.layer);
96
+ this.layer.destroy();
95
97
  this.measurementChangedHandler = void 0;
96
98
  this.predefinedMeasurements.clear();
97
99
  }
98
100
  /** Returns the vector layer used for finished features. */
99
- getVectorLayer() {
100
- return this.layer;
101
+ getOlVectorLayer() {
102
+ return this.layer.olLayer;
101
103
  }
102
104
  /** Updates the style used for finished features. */
103
105
  setFinishedFeatureStyle(style) {
104
- this.layer.setStyle(style);
106
+ this.getOlVectorLayer().setStyle(style);
105
107
  }
106
108
  setMeasurementSourceChangedHandler(handler) {
107
109
  this.measurementChangedHandler = handler;
@@ -1 +1 @@
1
- {"version":3,"file":"MeasurementController.js","sources":["MeasurementController.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2023-2025 Open Pioneer project (https://github.com/open-pioneer)\n// SPDX-License-Identifier: Apache-2.0\nimport { destroyResource, Resource } from \"@open-pioneer/core\";\nimport { TOPMOST_LAYER_Z } from \"@open-pioneer/map\";\nimport Feature from \"ol/Feature\";\nimport OlMap from \"ol/Map\";\nimport MapBrowserEvent from \"ol/MapBrowserEvent\";\nimport { unByKey } from \"ol/Observable\";\nimport Overlay from \"ol/Overlay\";\nimport { Coordinate } from \"ol/coordinate\";\nimport { EventsKey } from \"ol/events\";\nimport { LineString, Polygon } from \"ol/geom\";\nimport Draw from \"ol/interaction/Draw\";\nimport { Vector as VectorLayer } from \"ol/layer\";\nimport { Projection } from \"ol/proj\";\nimport { Vector as VectorSource } from \"ol/source\";\nimport { getArea, getLength } from \"ol/sphere\";\nimport { StyleFunction, StyleLike, toFunction as toStyleFunction } from \"ol/style/Style\";\nimport type { MeasurementsChangeEvent, MeasurementGeometry, MeasurementProps } from \"./Measurement\";\n\ntype MeasurementsChangeHandler = NonNullable<MeasurementProps[\"onMeasurementsChange\"]>;\n\nexport type MeasurementType = \"area\" | \"distance\";\n\nexport interface Messages {\n getContinueMessage(): string;\n getHelpMessage(): string;\n formatNumber(value: number): string;\n}\n\nexport class MeasurementController {\n readonly olMap: OlMap;\n readonly messages: Messages;\n\n private activeFeatureStyle: StyleFunction | undefined;\n /**\n * The layer rendering the measurement \"features\".\n */\n private layer: VectorLayer<VectorSource, Feature>;\n\n /**\n * Source of {@link layer}.\n */\n private source: VectorSource;\n\n /**\n * Stores the current `Draw` interaction.\n */\n private draw: Draw | undefined = undefined;\n\n /**\n * The active measurement manipulated by the `draw` interaction.\n */\n private activeMeasurement: MeasurementInstance | undefined;\n\n /**\n * Map that is used to track all predefined measurements currently added to the source.\n * It associates the measurement geometry (key) with the corresponding measurement instance.\n *\n * The measurement instances here must also be contained in `finishedMeasurements`.\n */\n private predefinedMeasurements = new Map<MeasurementGeometry, MeasurementInstance>();\n\n /**\n * Measurement instances that were finished.\n */\n private finishedMeasurements = new Set<MeasurementInstance>();\n\n /**\n * The help tooltip element.\n */\n private helpTooltip: Tooltip;\n\n /**\n * Keeps track of registered event handlers.\n */\n private resources: Resource[] = [];\n\n /**\n * Called when a measurement is added to or removed from the source.\n */\n private measurementChangedHandler: MeasurementsChangeHandler | undefined;\n\n constructor(olMap: OlMap, messages: Messages) {\n this.olMap = olMap;\n this.messages = messages;\n const source = (this.source = new VectorSource());\n this.layer = new VectorLayer({\n source: source,\n zIndex: TOPMOST_LAYER_Z,\n properties: {\n name: \"measurement-layer\"\n }\n });\n olMap.addLayer(this.layer);\n\n // \"pointermove\" is documented but produces a typescript error.\n // See https://openlayers.org/en/latest/apidoc/module-ol_MapBrowserEvent-MapBrowserEvent.html#event:pointermove\n const pointerMoveKey: EventsKey = olMap.on(\n // @ts-expect-error pointermove not declared\n \"pointermove\",\n this.handlePointerMove.bind(this)\n );\n this.resources.push({\n destroy() {\n unByKey(pointerMoveKey);\n }\n });\n\n this.helpTooltip = createHelpTooltip(this.olMap);\n }\n\n destroy() {\n this.stopMeasurement();\n\n // Cleanup registered event handlers etc.\n for (const resource of this.resources) {\n resource.destroy();\n }\n this.resources = [];\n\n // Cleanup measurements and tooltips.\n this.activeMeasurement = destroyResource(this.activeMeasurement);\n for (const measurement of this.finishedMeasurements) {\n measurement.destroy();\n }\n this.finishedMeasurements.clear();\n this.helpTooltip.destroy();\n\n // Cleanup layer\n this.olMap.removeLayer(this.layer);\n this.layer.dispose();\n this.source.dispose();\n\n this.measurementChangedHandler = undefined;\n this.predefinedMeasurements.clear();\n }\n\n /** Returns the vector layer used for finished features. */\n getVectorLayer() {\n return this.layer;\n }\n\n /** Updates the style used for finished features. */\n setFinishedFeatureStyle(style: StyleLike) {\n this.layer.setStyle(style);\n }\n\n setMeasurementSourceChangedHandler(handler: MeasurementsChangeHandler | undefined) {\n this.measurementChangedHandler = handler;\n }\n\n setPredefinedMeasurements(geometries: MeasurementGeometry[]) {\n this.updatePredefinedMeasurements(geometries);\n }\n\n /** Updates the style used for active measurements. */\n setActiveFeatureStyle(style: StyleLike) {\n const styleFunction = toStyleFunction(style);\n this.activeFeatureStyle = (feature, ...args) => {\n const ft = feature?.getGeometry()?.getType();\n if (ft === \"Polygon\" || ft === \"LineString\" || ft === \"Point\") {\n return styleFunction(feature, ...args);\n }\n };\n // Update style on current draw instance (if any)\n this.draw?.getOverlay().setStyle(this.activeFeatureStyle);\n }\n\n /** Removes all finished measurements. */\n clearMeasurements() {\n const currentFeatures = this.source.getFeatures(); //returns snapshot copy of the features on the source\n this.source.clear();\n currentFeatures.forEach((feature) => {\n //raise remove-measurement event for each measurement after the source was cleared\n this.raiseMeasurementsChangeEvent(\"remove-measurement\", feature);\n });\n this.predefinedMeasurements.clear();\n for (const measurement of this.finishedMeasurements) {\n measurement.destroy();\n }\n this.finishedMeasurements.clear();\n }\n\n /** Starts measuring using the provided type. */\n startMeasurement(type: MeasurementType) {\n if (this.draw) {\n throw new Error(\"Internal error: another measurement interaction is still active.\");\n }\n\n const geometryType = type === \"area\" ? \"Polygon\" : \"LineString\";\n const draw = (this.draw = new Draw({\n source: this.source,\n type: geometryType,\n style: this.activeFeatureStyle\n }));\n this.olMap.addInteraction(draw);\n\n // update tooltip if user changed drawing mode (and did not move the mouse yet)\n // currently this does not work when the tool is initially activated as the tooltip has no position yet\n this.updateTooltip(undefined);\n\n let measurement: MeasurementInstance | undefined;\n let changeListenerKey: EventsKey | undefined = undefined;\n draw.on(\"drawstart\", (evt) => {\n // set sketch\n const sketch = evt.feature;\n if (!sketch) {\n return;\n }\n\n measurement = this.activeMeasurement = new MeasurementInstance(\"active\", sketch, this);\n changeListenerKey = sketch.getGeometry()?.on(\"change\", () => {\n measurement?.updateTooltipContent();\n measurement?.updateTooltipPosition();\n });\n\n // update tooltip message if user started drawing but did not yet move the mouse\n this.updateTooltip(undefined);\n });\n\n draw.on(\"drawend\", () => {\n if (measurement && measurement === this.activeMeasurement) {\n const newMeasurement = measurement;\n newMeasurement.updateState(\"finished\");\n this.finishedMeasurements.add(newMeasurement);\n this.raiseMeasurementsChangeEvent(\"add-measurement\", newMeasurement.feature);\n this.activeMeasurement = measurement = undefined;\n }\n\n measurement = undefined;\n if (changeListenerKey) {\n unByKey(changeListenerKey);\n }\n\n // update tooltip if user finished drawing but did not yet move the mouse\n this.updateTooltip(undefined);\n });\n\n draw.on(\"drawabort\", () => {\n if (measurement) {\n measurement.destroy();\n if (measurement === this.activeMeasurement) {\n this.activeMeasurement = undefined;\n }\n measurement = undefined;\n }\n\n if (changeListenerKey) {\n unByKey(changeListenerKey);\n }\n });\n }\n\n /** Stops the current measuring started by `startMeasurement`. */\n stopMeasurement() {\n if (this.draw) {\n this.olMap.removeInteraction(this.draw);\n this.draw.abortDrawing();\n this.draw.dispose();\n this.draw = undefined;\n }\n\n this.activeMeasurement = destroyResource(this.activeMeasurement);\n }\n\n private handlePointerMove(evt: MapBrowserEvent<PointerEvent>) {\n if (evt.dragging) {\n return;\n }\n this.updateTooltip(evt.coordinate);\n }\n\n private updateTooltip(coordinate: number[] | undefined) {\n const tooltip = this.helpTooltip;\n const helpMessage = getHelpMessage(this.messages, this.activeMeasurement);\n tooltip.setText(helpMessage);\n if (coordinate) {\n tooltip.overlay.setPosition(coordinate);\n }\n }\n\n private updatePredefinedMeasurements(geometries: MeasurementGeometry[]) {\n const addedMeasurements = geometries.filter(\n (geom) => !this.predefinedMeasurements.has(geom)\n );\n const removedMeasurements: MeasurementGeometry[] = [];\n for (const geom of this.predefinedMeasurements.keys()) {\n if (!geometries.includes(geom)) {\n removedMeasurements.push(geom);\n }\n }\n\n addedMeasurements.forEach((geom) => {\n const measurementFeature = new Feature(geom);\n this.source.addFeature(measurementFeature);\n\n const measurement = new MeasurementInstance(\"finished\", measurementFeature, this);\n this.finishedMeasurements.add(measurement);\n this.predefinedMeasurements.set(geom, measurement);\n this.raiseMeasurementsChangeEvent(\"add-measurement\", measurementFeature);\n });\n\n removedMeasurements.forEach((geom) => {\n const measurement = this.predefinedMeasurements.get(geom);\n if (measurement) {\n //remove measurement feature from source and destroy associated tooltip\n this.source.removeFeature(measurement.feature);\n this.finishedMeasurements.delete(measurement);\n measurement.destroy();\n this.raiseMeasurementsChangeEvent(\"remove-measurement\", measurement.feature);\n }\n this.predefinedMeasurements.delete(geom);\n });\n }\n\n private raiseMeasurementsChangeEvent(\n kind: MeasurementsChangeEvent[\"kind\"],\n measurementFeature: Feature\n ) {\n const measurementGeom = measurementFeature.getGeometry();\n if (this.measurementChangedHandler && measurementGeom) {\n this.measurementChangedHandler({\n kind: kind,\n geometry:\n measurementGeom instanceof Polygon\n ? (measurementGeom as Polygon)\n : (measurementGeom as LineString)\n });\n }\n }\n}\n\n// Encapsulates the display state of a measurement.\n//\n// More ideas for further improvements:\n// - Resolve duplicate source of truths (feature source and map of measurements).\n// - Add and remove the feature here as well (instead of in the controller).\n// - Perhaps use reactivity API and watch for state consistency.\n// The current implementations relies on the update*() functions being called at the correct time.\nclass MeasurementInstance {\n readonly controller: MeasurementController;\n readonly feature: Feature;\n\n private _state: \"active\" | \"finished\";\n private readonly tooltip: ReturnType<typeof createMeasureTooltip>;\n\n constructor(state: \"active\" | \"finished\", feature: Feature, controller: MeasurementController) {\n this.controller = controller;\n this._state = state;\n this.feature = feature;\n this.tooltip = createMeasureTooltip(this.olMap);\n this.updateTooltipContent();\n this.updateTooltipPosition();\n this.tooltip.setActive(state === \"active\");\n }\n\n destroy() {\n this.tooltip.destroy();\n }\n\n get state(): \"active\" | \"finished\" {\n return this._state;\n }\n\n updateState(state: \"active\" | \"finished\") {\n if (this._state === state) {\n return;\n }\n\n this._state = state;\n this.tooltip.setActive(state === \"active\");\n }\n\n // Updates the tooltip content based on the current state and the feature's geometry.\n updateTooltipContent() {\n const geometry = this.feature.getGeometry();\n if (!geometry) {\n return;\n }\n\n const projection = this.olMap.getView().getProjection();\n let outputHtml;\n if (geometry instanceof Polygon) {\n outputHtml = formatArea(geometry, projection, this.messages);\n } else if (geometry instanceof LineString) {\n outputHtml = formatLength(geometry, projection, this.messages);\n }\n if (outputHtml) {\n this.tooltip.setHtml(outputHtml);\n }\n }\n\n // Updates the tooltip's position.\n updateTooltipPosition() {\n const geometry = this.feature.getGeometry();\n if (!geometry) {\n return;\n }\n\n let tooltipCoord: Coordinate;\n if (geometry instanceof Polygon) {\n tooltipCoord = geometry.getInteriorPoint().getCoordinates() || null;\n } else if (geometry instanceof LineString) {\n tooltipCoord = geometry.getLastCoordinate() || null;\n } else {\n return;\n }\n this.tooltip.overlay.setPosition(tooltipCoord);\n }\n\n private get olMap(): OlMap {\n return this.controller.olMap;\n }\n\n private get messages(): Messages {\n return this.controller.messages;\n }\n}\n\nconst DEFAULT_MEASUREMENT_OFFSET = [0, -15];\nconst FINISHED_MEASUREMENT_OFFSET = [0, -7];\n\n/** Represents a tooltip rendered on the OpenLayers map. */\ninterface Tooltip extends Resource {\n overlay: Overlay;\n element: HTMLDivElement;\n\n setText(value: string): void;\n setHtml(value: string): void;\n}\n\nfunction createHelpTooltip(olMap: OlMap): Tooltip {\n const element = document.createElement(\"div\");\n element.className = \"measurement-tooltip printing-hide\";\n element.role = \"tooltip\";\n\n const content = document.createElement(\"span\");\n element.appendChild(content);\n\n const overlay = new Overlay({\n element: element,\n offset: [15, 0],\n positioning: \"center-left\"\n });\n\n olMap.addOverlay(overlay);\n return {\n overlay,\n element,\n destroy() {\n olMap.removeOverlay(overlay);\n },\n setText(value) {\n content.textContent = value;\n },\n setHtml(value) {\n content.innerHTML = value;\n }\n };\n}\n\nfunction createMeasureTooltip(olMap: OlMap): Tooltip & { setActive(active: boolean): void } {\n const element = document.createElement(\"div\");\n element.role = \"tooltip\";\n element.className = \"measurement-tooltip measurement-active-tooltip printing-hide\";\n\n const content = document.createElement(\"span\");\n element.appendChild(content);\n\n const overlay = new Overlay({\n element: element,\n offset: DEFAULT_MEASUREMENT_OFFSET,\n positioning: \"bottom-center\",\n stopEvent: false,\n insertFirst: false\n });\n\n olMap.addOverlay(overlay);\n return {\n overlay,\n element,\n destroy() {\n olMap.removeOverlay(overlay);\n },\n setActive(active) {\n if (active) {\n element.className = \"measurement-tooltip measurement-active-tooltip printing-hide\";\n overlay.setOffset(DEFAULT_MEASUREMENT_OFFSET);\n } else {\n element.className = \"measurement-tooltip measurement-finished-tooltip\";\n overlay.setOffset(FINISHED_MEASUREMENT_OFFSET);\n }\n },\n setText(value) {\n content.textContent = value;\n },\n setHtml(value) {\n content.innerHTML = value;\n }\n };\n}\n\nfunction getHelpMessage(messages: Messages, activeMeasurement: MeasurementInstance | undefined) {\n if (activeMeasurement) {\n const geom = activeMeasurement.feature.getGeometry();\n if (geom instanceof Polygon || geom instanceof LineString) {\n return messages.getContinueMessage();\n }\n }\n return messages.getHelpMessage();\n}\n\nfunction formatArea(polygon: Polygon, projection: Projection, messages: Messages) {\n const area = getArea(polygon, { projection });\n let output;\n if (area >= 1000000) {\n output = `${messages.formatNumber(area / 1000000)} km<sup>2</sup>`;\n } else {\n output = `${messages.formatNumber(area)} m<sup>2</sup>`;\n }\n return output;\n}\n\nfunction formatLength(line: LineString, projection: Projection, messages: Messages) {\n const length = getLength(line, { projection });\n let output;\n if (length >= 1000) {\n output = `${messages.formatNumber(length / 1000)} km`;\n } else {\n output = `${messages.formatNumber(length)} m`;\n }\n return output;\n}\n"],"names":["VectorSource","VectorLayer","toStyleFunction"],"mappings":"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"}
1
+ {"version":3,"file":"MeasurementController.js","sources":["MeasurementController.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2023-2025 Open Pioneer project (https://github.com/open-pioneer)\n// SPDX-License-Identifier: Apache-2.0\nimport { destroyResource, Resource } from \"@open-pioneer/core\";\nimport { LayerFactory, MapModel, SimpleLayer } from \"@open-pioneer/map\";\nimport Feature from \"ol/Feature\";\nimport OlMap from \"ol/Map\";\nimport MapBrowserEvent from \"ol/MapBrowserEvent\";\nimport { unByKey } from \"ol/Observable\";\nimport Overlay from \"ol/Overlay\";\nimport { Coordinate } from \"ol/coordinate\";\nimport { EventsKey } from \"ol/events\";\nimport { LineString, Polygon } from \"ol/geom\";\nimport Draw from \"ol/interaction/Draw\";\nimport { Vector as VectorLayer } from \"ol/layer\";\nimport { Projection } from \"ol/proj\";\nimport { Vector as VectorSource } from \"ol/source\";\nimport { getArea, getLength } from \"ol/sphere\";\nimport { StyleFunction, StyleLike, toFunction as toStyleFunction } from \"ol/style/Style\";\nimport type { MeasurementsChangeEvent, MeasurementGeometry, MeasurementProps } from \"./Measurement\";\n\ntype MeasurementsChangeHandler = NonNullable<MeasurementProps[\"onMeasurementsChange\"]>;\n\nexport type MeasurementType = \"area\" | \"distance\";\n\nexport interface Messages {\n getContinueMessage(): string;\n getHelpMessage(): string;\n formatNumber(value: number): string;\n}\n\nexport class MeasurementController {\n readonly map: MapModel;\n readonly olMap: OlMap;\n readonly messages: Messages;\n\n private activeFeatureStyle: StyleFunction | undefined;\n /**\n * The layer rendering the measurement \"features\".\n */\n private layer: SimpleLayer;\n\n /**\n * Source of {@link layer}.\n */\n private source: VectorSource;\n\n /**\n * Stores the current `Draw` interaction.\n */\n private draw: Draw | undefined = undefined;\n\n /**\n * The active measurement manipulated by the `draw` interaction.\n */\n private activeMeasurement: MeasurementInstance | undefined;\n\n /**\n * Map that is used to track all predefined measurements currently added to the source.\n * It associates the measurement geometry (key) with the corresponding measurement instance.\n *\n * The measurement instances here must also be contained in `finishedMeasurements`.\n */\n private predefinedMeasurements = new Map<MeasurementGeometry, MeasurementInstance>();\n\n /**\n * Measurement instances that were finished.\n */\n private finishedMeasurements = new Set<MeasurementInstance>();\n\n /**\n * The help tooltip element.\n */\n private helpTooltip: Tooltip;\n\n /**\n * Keeps track of registered event handlers.\n */\n private resources: Resource[] = [];\n\n /**\n * Called when a measurement is added to or removed from the source.\n */\n private measurementChangedHandler: MeasurementsChangeHandler | undefined;\n\n constructor(map: MapModel, layerFactory: LayerFactory, messages: Messages) {\n this.map = map;\n this.olMap = map.olMap;\n this.messages = messages;\n const source = (this.source = new VectorSource());\n this.layer = layerFactory.create({\n type: SimpleLayer,\n internal: true,\n title: \"measurement-layer\",\n olLayer: new VectorLayer<VectorSource, Feature>({\n source: source\n })\n });\n map.layers.addLayer(this.layer, { at: \"topmost\" });\n\n // \"pointermove\" is documented but produces a typescript error.\n // See https://openlayers.org/en/latest/apidoc/module-ol_MapBrowserEvent-MapBrowserEvent.html#event:pointermove\n const pointerMoveKey: EventsKey = this.olMap.on(\n // @ts-expect-error pointermove not declared\n \"pointermove\",\n this.handlePointerMove.bind(this)\n );\n this.resources.push({\n destroy() {\n unByKey(pointerMoveKey);\n }\n });\n\n this.helpTooltip = createHelpTooltip(this.olMap);\n }\n\n destroy() {\n this.stopMeasurement();\n\n // Cleanup registered event handlers etc.\n for (const resource of this.resources) {\n resource.destroy();\n }\n this.resources = [];\n\n // Cleanup measurements and tooltips.\n this.activeMeasurement = destroyResource(this.activeMeasurement);\n for (const measurement of this.finishedMeasurements) {\n measurement.destroy();\n }\n this.finishedMeasurements.clear();\n this.helpTooltip.destroy();\n\n // Cleanup layer\n this.map.layers.removeLayer(this.layer);\n this.layer.destroy();\n\n this.measurementChangedHandler = undefined;\n this.predefinedMeasurements.clear();\n }\n\n /** Returns the vector layer used for finished features. */\n getOlVectorLayer() {\n return this.layer.olLayer as VectorLayer;\n }\n\n /** Updates the style used for finished features. */\n setFinishedFeatureStyle(style: StyleLike) {\n this.getOlVectorLayer().setStyle(style);\n }\n\n setMeasurementSourceChangedHandler(handler: MeasurementsChangeHandler | undefined) {\n this.measurementChangedHandler = handler;\n }\n\n setPredefinedMeasurements(geometries: MeasurementGeometry[]) {\n this.updatePredefinedMeasurements(geometries);\n }\n\n /** Updates the style used for active measurements. */\n setActiveFeatureStyle(style: StyleLike) {\n const styleFunction = toStyleFunction(style);\n this.activeFeatureStyle = (feature, ...args) => {\n const ft = feature?.getGeometry()?.getType();\n if (ft === \"Polygon\" || ft === \"LineString\" || ft === \"Point\") {\n return styleFunction(feature, ...args);\n }\n };\n // Update style on current draw instance (if any)\n this.draw?.getOverlay().setStyle(this.activeFeatureStyle);\n }\n\n /** Removes all finished measurements. */\n clearMeasurements() {\n const currentFeatures = this.source.getFeatures(); //returns snapshot copy of the features on the source\n this.source.clear();\n currentFeatures.forEach((feature) => {\n //raise remove-measurement event for each measurement after the source was cleared\n this.raiseMeasurementsChangeEvent(\"remove-measurement\", feature);\n });\n this.predefinedMeasurements.clear();\n for (const measurement of this.finishedMeasurements) {\n measurement.destroy();\n }\n this.finishedMeasurements.clear();\n }\n\n /** Starts measuring using the provided type. */\n startMeasurement(type: MeasurementType) {\n if (this.draw) {\n throw new Error(\"Internal error: another measurement interaction is still active.\");\n }\n\n const geometryType = type === \"area\" ? \"Polygon\" : \"LineString\";\n const draw = (this.draw = new Draw({\n source: this.source,\n type: geometryType,\n style: this.activeFeatureStyle\n }));\n this.olMap.addInteraction(draw);\n\n // update tooltip if user changed drawing mode (and did not move the mouse yet)\n // currently this does not work when the tool is initially activated as the tooltip has no position yet\n this.updateTooltip(undefined);\n\n let measurement: MeasurementInstance | undefined;\n let changeListenerKey: EventsKey | undefined = undefined;\n draw.on(\"drawstart\", (evt) => {\n // set sketch\n const sketch = evt.feature;\n if (!sketch) {\n return;\n }\n\n measurement = this.activeMeasurement = new MeasurementInstance(\"active\", sketch, this);\n changeListenerKey = sketch.getGeometry()?.on(\"change\", () => {\n measurement?.updateTooltipContent();\n measurement?.updateTooltipPosition();\n });\n\n // update tooltip message if user started drawing but did not yet move the mouse\n this.updateTooltip(undefined);\n });\n\n draw.on(\"drawend\", () => {\n if (measurement && measurement === this.activeMeasurement) {\n const newMeasurement = measurement;\n newMeasurement.updateState(\"finished\");\n this.finishedMeasurements.add(newMeasurement);\n this.raiseMeasurementsChangeEvent(\"add-measurement\", newMeasurement.feature);\n this.activeMeasurement = measurement = undefined;\n }\n\n measurement = undefined;\n if (changeListenerKey) {\n unByKey(changeListenerKey);\n }\n\n // update tooltip if user finished drawing but did not yet move the mouse\n this.updateTooltip(undefined);\n });\n\n draw.on(\"drawabort\", () => {\n if (measurement) {\n measurement.destroy();\n if (measurement === this.activeMeasurement) {\n this.activeMeasurement = undefined;\n }\n measurement = undefined;\n }\n\n if (changeListenerKey) {\n unByKey(changeListenerKey);\n }\n });\n }\n\n /** Stops the current measuring started by `startMeasurement`. */\n stopMeasurement() {\n if (this.draw) {\n this.olMap.removeInteraction(this.draw);\n this.draw.abortDrawing();\n this.draw.dispose();\n this.draw = undefined;\n }\n\n this.activeMeasurement = destroyResource(this.activeMeasurement);\n }\n\n private handlePointerMove(evt: MapBrowserEvent<PointerEvent>) {\n if (evt.dragging) {\n return;\n }\n this.updateTooltip(evt.coordinate);\n }\n\n private updateTooltip(coordinate: number[] | undefined) {\n const tooltip = this.helpTooltip;\n const helpMessage = getHelpMessage(this.messages, this.activeMeasurement);\n tooltip.setText(helpMessage);\n if (coordinate) {\n tooltip.overlay.setPosition(coordinate);\n }\n }\n\n private updatePredefinedMeasurements(geometries: MeasurementGeometry[]) {\n const addedMeasurements = geometries.filter(\n (geom) => !this.predefinedMeasurements.has(geom)\n );\n const removedMeasurements: MeasurementGeometry[] = [];\n for (const geom of this.predefinedMeasurements.keys()) {\n if (!geometries.includes(geom)) {\n removedMeasurements.push(geom);\n }\n }\n\n addedMeasurements.forEach((geom) => {\n const measurementFeature = new Feature(geom);\n this.source.addFeature(measurementFeature);\n\n const measurement = new MeasurementInstance(\"finished\", measurementFeature, this);\n this.finishedMeasurements.add(measurement);\n this.predefinedMeasurements.set(geom, measurement);\n this.raiseMeasurementsChangeEvent(\"add-measurement\", measurementFeature);\n });\n\n removedMeasurements.forEach((geom) => {\n const measurement = this.predefinedMeasurements.get(geom);\n if (measurement) {\n //remove measurement feature from source and destroy associated tooltip\n this.source.removeFeature(measurement.feature);\n this.finishedMeasurements.delete(measurement);\n measurement.destroy();\n this.raiseMeasurementsChangeEvent(\"remove-measurement\", measurement.feature);\n }\n this.predefinedMeasurements.delete(geom);\n });\n }\n\n private raiseMeasurementsChangeEvent(\n kind: MeasurementsChangeEvent[\"kind\"],\n measurementFeature: Feature\n ) {\n const measurementGeom = measurementFeature.getGeometry();\n if (this.measurementChangedHandler && measurementGeom) {\n this.measurementChangedHandler({\n kind: kind,\n geometry:\n measurementGeom instanceof Polygon\n ? (measurementGeom as Polygon)\n : (measurementGeom as LineString)\n });\n }\n }\n}\n\n// Encapsulates the display state of a measurement.\n//\n// More ideas for further improvements:\n// - Resolve duplicate source of truths (feature source and map of measurements).\n// - Add and remove the feature here as well (instead of in the controller).\n// - Perhaps use reactivity API and watch for state consistency.\n// The current implementations relies on the update*() functions being called at the correct time.\nclass MeasurementInstance {\n readonly controller: MeasurementController;\n readonly feature: Feature;\n\n private _state: \"active\" | \"finished\";\n private readonly tooltip: ReturnType<typeof createMeasureTooltip>;\n\n constructor(state: \"active\" | \"finished\", feature: Feature, controller: MeasurementController) {\n this.controller = controller;\n this._state = state;\n this.feature = feature;\n this.tooltip = createMeasureTooltip(this.olMap);\n this.updateTooltipContent();\n this.updateTooltipPosition();\n this.tooltip.setActive(state === \"active\");\n }\n\n destroy() {\n this.tooltip.destroy();\n }\n\n get state(): \"active\" | \"finished\" {\n return this._state;\n }\n\n updateState(state: \"active\" | \"finished\") {\n if (this._state === state) {\n return;\n }\n\n this._state = state;\n this.tooltip.setActive(state === \"active\");\n }\n\n // Updates the tooltip content based on the current state and the feature's geometry.\n updateTooltipContent() {\n const geometry = this.feature.getGeometry();\n if (!geometry) {\n return;\n }\n\n const projection = this.olMap.getView().getProjection();\n let outputHtml;\n if (geometry instanceof Polygon) {\n outputHtml = formatArea(geometry, projection, this.messages);\n } else if (geometry instanceof LineString) {\n outputHtml = formatLength(geometry, projection, this.messages);\n }\n if (outputHtml) {\n this.tooltip.setHtml(outputHtml);\n }\n }\n\n // Updates the tooltip's position.\n updateTooltipPosition() {\n const geometry = this.feature.getGeometry();\n if (!geometry) {\n return;\n }\n\n let tooltipCoord: Coordinate;\n if (geometry instanceof Polygon) {\n tooltipCoord = geometry.getInteriorPoint().getCoordinates() || null;\n } else if (geometry instanceof LineString) {\n tooltipCoord = geometry.getLastCoordinate() || null;\n } else {\n return;\n }\n this.tooltip.overlay.setPosition(tooltipCoord);\n }\n\n private get olMap(): OlMap {\n return this.controller.olMap;\n }\n\n private get messages(): Messages {\n return this.controller.messages;\n }\n}\n\nconst DEFAULT_MEASUREMENT_OFFSET = [0, -15];\nconst FINISHED_MEASUREMENT_OFFSET = [0, -7];\n\n/** Represents a tooltip rendered on the OpenLayers map. */\ninterface Tooltip extends Resource {\n overlay: Overlay;\n element: HTMLDivElement;\n\n setText(value: string): void;\n setHtml(value: string): void;\n}\n\nfunction createHelpTooltip(olMap: OlMap): Tooltip {\n const element = document.createElement(\"div\");\n element.className = \"measurement-tooltip printing-hide\";\n element.role = \"tooltip\";\n\n const content = document.createElement(\"span\");\n element.appendChild(content);\n\n const overlay = new Overlay({\n element: element,\n offset: [15, 0],\n positioning: \"center-left\"\n });\n\n olMap.addOverlay(overlay);\n return {\n overlay,\n element,\n destroy() {\n olMap.removeOverlay(overlay);\n },\n setText(value) {\n content.textContent = value;\n },\n setHtml(value) {\n content.innerHTML = value;\n }\n };\n}\n\nfunction createMeasureTooltip(olMap: OlMap): Tooltip & { setActive(active: boolean): void } {\n const element = document.createElement(\"div\");\n element.role = \"tooltip\";\n element.className = \"measurement-tooltip measurement-active-tooltip printing-hide\";\n\n const content = document.createElement(\"span\");\n element.appendChild(content);\n\n const overlay = new Overlay({\n element: element,\n offset: DEFAULT_MEASUREMENT_OFFSET,\n positioning: \"bottom-center\",\n stopEvent: false,\n insertFirst: false\n });\n\n olMap.addOverlay(overlay);\n return {\n overlay,\n element,\n destroy() {\n olMap.removeOverlay(overlay);\n },\n setActive(active) {\n if (active) {\n element.className = \"measurement-tooltip measurement-active-tooltip printing-hide\";\n overlay.setOffset(DEFAULT_MEASUREMENT_OFFSET);\n } else {\n element.className = \"measurement-tooltip measurement-finished-tooltip\";\n overlay.setOffset(FINISHED_MEASUREMENT_OFFSET);\n }\n },\n setText(value) {\n content.textContent = value;\n },\n setHtml(value) {\n content.innerHTML = value;\n }\n };\n}\n\nfunction getHelpMessage(messages: Messages, activeMeasurement: MeasurementInstance | undefined) {\n if (activeMeasurement) {\n const geom = activeMeasurement.feature.getGeometry();\n if (geom instanceof Polygon || geom instanceof LineString) {\n return messages.getContinueMessage();\n }\n }\n return messages.getHelpMessage();\n}\n\nfunction formatArea(polygon: Polygon, projection: Projection, messages: Messages) {\n const area = getArea(polygon, { projection });\n let output;\n if (area >= 1000000) {\n output = `${messages.formatNumber(area / 1000000)} km<sup>2</sup>`;\n } else {\n output = `${messages.formatNumber(area)} m<sup>2</sup>`;\n }\n return output;\n}\n\nfunction formatLength(line: LineString, projection: Projection, messages: Messages) {\n const length = getLength(line, { projection });\n let output;\n if (length >= 1000) {\n output = `${messages.formatNumber(length / 1000)} km`;\n } else {\n output = `${messages.formatNumber(length)} m`;\n }\n return output;\n}\n"],"names":["VectorSource","VectorLayer","toStyleFunction"],"mappings":"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"}
@@ -1,7 +1,8 @@
1
- import { useIntlInternal } from '@open-pioneer/runtime/react-integration';
1
+ import { useIntlInternal, useServiceInternal } from '@open-pioneer/runtime/react-integration';
2
2
 
3
3
  const PACKAGE_NAME = "@open-pioneer/measurement";
4
+ const useService = /*@__PURE__*/ useServiceInternal.bind(undefined, PACKAGE_NAME);
4
5
  const useIntl = /*@__PURE__*/ useIntlInternal.bind(undefined, PACKAGE_NAME);
5
6
 
6
- export { useIntl };
7
+ export { useIntl, useService };
7
8
  //# sourceMappingURL=_virtual-pioneer-module_react-hooks.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"_virtual-pioneer-module_react-hooks.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;"}
1
+ {"version":3,"file":"_virtual-pioneer-module_react-hooks.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "type": "module",
3
3
  "name": "@open-pioneer/measurement",
4
- "version": "1.0.0-dev.20251021074813",
4
+ "version": "1.0.0",
5
5
  "description": "This package provides a UI component that allows the user to perform area and distance measurements on the map.",
6
6
  "keywords": [
7
7
  "open-pioneer-trails"
@@ -15,14 +15,14 @@
15
15
  },
16
16
  "dependencies": {
17
17
  "@chakra-ui/react": "^3.28.0",
18
- "@open-pioneer/core": "4.2.0-dev.20251021072202",
19
- "@open-pioneer/react-utils": "4.2.0-dev.20251021072202",
20
- "@open-pioneer/runtime": "4.2.0-dev.20251021072202",
21
- "@open-pioneer/chakra-snippets": "4.2.0-dev.20251021072202",
18
+ "@open-pioneer/core": "^4.2.0",
19
+ "@open-pioneer/react-utils": "^4.2.0",
20
+ "@open-pioneer/runtime": "^4.2.0",
21
+ "@open-pioneer/chakra-snippets": "^4.2.0",
22
22
  "classnames": "^2.5.1",
23
23
  "ol": "^10.6.1",
24
24
  "react": "^19.2.0",
25
- "@open-pioneer/map": "1.0.0-dev.20251021074813"
25
+ "@open-pioneer/map": "^1.0.0"
26
26
  },
27
27
  "exports": {
28
28
  "./package.json": "./package.json",
@@ -42,7 +42,12 @@
42
42
  ]
43
43
  },
44
44
  "ui": {
45
- "references": []
45
+ "references": [
46
+ {
47
+ "type": "unique",
48
+ "interfaceName": "map.LayerFactory"
49
+ }
50
+ ]
46
51
  },
47
52
  "properties": [],
48
53
  "packageFormatVersion": "1.0.0"