@open-pioneer/measurement 1.4.0-dev.20260625074633 → 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.
- package/CHANGELOG.md +9 -2
- package/Measurement.js.map +1 -1
- package/MeasurementController.d.ts +2 -44
- package/MeasurementController.js +92 -92
- package/MeasurementController.js.map +1 -1
- package/MeasurementTooltip.js.map +1 -1
- package/package.json +8 -8
package/CHANGELOG.md
CHANGED
|
@@ -1,10 +1,16 @@
|
|
|
1
1
|
# @open-pioneer/measurement
|
|
2
2
|
|
|
3
|
-
## 1.4.0
|
|
3
|
+
## 1.4.0
|
|
4
4
|
|
|
5
5
|
### Minor Changes
|
|
6
6
|
|
|
7
|
-
- c30396d: Update Chakra to 3.36.
|
|
7
|
+
- c30396d: Update Chakra to 3.36.1
|
|
8
|
+
- d862003: Update to trails core-packages 4.7.0
|
|
9
|
+
|
|
10
|
+
### Patch Changes
|
|
11
|
+
|
|
12
|
+
- 078bef5: Use private JavaScript properties (#) instead of TypeScript keyword.
|
|
13
|
+
- c16a401: Migrated from eslint to oxlint and from prettier to oxfmt.
|
|
8
14
|
|
|
9
15
|
## 1.3.0
|
|
10
16
|
|
|
@@ -128,6 +134,7 @@
|
|
|
128
134
|
|
|
129
135
|
- b152428: Update trails dependencies
|
|
130
136
|
- 23b48ad: Add two new optional properties:
|
|
137
|
+
|
|
131
138
|
- `predefinedMeasurements`: an array of measurements that will be added to the map (without user interaction)
|
|
132
139
|
- `onMeasurementsChange`: an event listener that will be called when measurements are added or removed
|
|
133
140
|
|
package/Measurement.js.map
CHANGED
|
@@ -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 { 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
|
+
{"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\n\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,6 +1,6 @@
|
|
|
1
1
|
import { LayerFactory, MapModel } from "@open-pioneer/map";
|
|
2
|
-
import OlMap from "ol/Map";
|
|
3
2
|
import { Vector as VectorLayer } from "ol/layer";
|
|
3
|
+
import OlMap from "ol/Map";
|
|
4
4
|
import { StyleLike } from "ol/style/Style";
|
|
5
5
|
import { type MeasurementGeometry, type MeasurementProps } from "./Measurement";
|
|
6
6
|
type MeasurementsChangeHandler = NonNullable<MeasurementProps["onMeasurementsChange"]>;
|
|
@@ -11,49 +11,10 @@ export interface Messages {
|
|
|
11
11
|
formatNumber(value: number): string;
|
|
12
12
|
}
|
|
13
13
|
export declare class MeasurementController {
|
|
14
|
+
#private;
|
|
14
15
|
readonly map: MapModel;
|
|
15
16
|
readonly olMap: OlMap;
|
|
16
17
|
readonly messages: Messages;
|
|
17
|
-
private activeFeatureStyle;
|
|
18
|
-
/**
|
|
19
|
-
* The layer rendering the measurement "features".
|
|
20
|
-
*/
|
|
21
|
-
private layer;
|
|
22
|
-
/**
|
|
23
|
-
* Source of {@link layer}.
|
|
24
|
-
*/
|
|
25
|
-
private source;
|
|
26
|
-
/**
|
|
27
|
-
* Stores the current `Draw` interaction.
|
|
28
|
-
*/
|
|
29
|
-
private draw;
|
|
30
|
-
/**
|
|
31
|
-
* The active measurement manipulated by the `draw` interaction.
|
|
32
|
-
*/
|
|
33
|
-
private activeMeasurement;
|
|
34
|
-
/**
|
|
35
|
-
* Map that is used to track all predefined measurements currently added to the source.
|
|
36
|
-
* It associates the measurement geometry (key) with the corresponding measurement instance.
|
|
37
|
-
*
|
|
38
|
-
* The measurement instances here must also be contained in `finishedMeasurements`.
|
|
39
|
-
*/
|
|
40
|
-
private predefinedMeasurements;
|
|
41
|
-
/**
|
|
42
|
-
* Measurement instances that were finished.
|
|
43
|
-
*/
|
|
44
|
-
private finishedMeasurements;
|
|
45
|
-
/**
|
|
46
|
-
* Overlay for help tooltip.
|
|
47
|
-
*/
|
|
48
|
-
private helpTooltip;
|
|
49
|
-
/**
|
|
50
|
-
* Keeps track of registered event handlers.
|
|
51
|
-
*/
|
|
52
|
-
private resources;
|
|
53
|
-
/**
|
|
54
|
-
* Called when a measurement is added to or removed from the source.
|
|
55
|
-
*/
|
|
56
|
-
private measurementChangedHandler;
|
|
57
18
|
constructor(map: MapModel, layerFactory: LayerFactory, messages: Messages);
|
|
58
19
|
destroy(): void;
|
|
59
20
|
/** Returns the vector layer used for finished features. */
|
|
@@ -70,8 +31,5 @@ export declare class MeasurementController {
|
|
|
70
31
|
startMeasurement(type: MeasurementType): void;
|
|
71
32
|
/** Stops the current measuring started by `startMeasurement`. */
|
|
72
33
|
stopMeasurement(): void;
|
|
73
|
-
private updateTooltip;
|
|
74
|
-
private updatePredefinedMeasurements;
|
|
75
|
-
private raiseMeasurementsChangeEvent;
|
|
76
34
|
}
|
|
77
35
|
export {};
|
package/MeasurementController.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { destroyResource } from '@open-pioneer/core';
|
|
2
2
|
import { SimpleLayer } from '@open-pioneer/map';
|
|
3
3
|
import Feature from 'ol/Feature.js';
|
|
4
|
-
import { unByKey } from 'ol/Observable.js';
|
|
5
4
|
import { Polygon, LineString } from 'ol/geom.js';
|
|
6
5
|
import Draw from 'ol/interaction/Draw.js';
|
|
7
6
|
import { Vector as Vector$1 } from 'ol/layer.js';
|
|
7
|
+
import { unByKey } from 'ol/Observable.js';
|
|
8
8
|
import { Vector } from 'ol/source.js';
|
|
9
9
|
import { getArea, getLength } from 'ol/sphere.js';
|
|
10
10
|
import { toFunction } from 'ol/style/Style.js';
|
|
@@ -15,52 +15,52 @@ class MeasurementController {
|
|
|
15
15
|
map;
|
|
16
16
|
olMap;
|
|
17
17
|
messages;
|
|
18
|
-
activeFeatureStyle;
|
|
18
|
+
#activeFeatureStyle;
|
|
19
19
|
/**
|
|
20
20
|
* The layer rendering the measurement "features".
|
|
21
21
|
*/
|
|
22
|
-
layer;
|
|
22
|
+
#layer;
|
|
23
23
|
/**
|
|
24
24
|
* Source of {@link layer}.
|
|
25
25
|
*/
|
|
26
|
-
source;
|
|
26
|
+
#source;
|
|
27
27
|
/**
|
|
28
28
|
* Stores the current `Draw` interaction.
|
|
29
29
|
*/
|
|
30
|
-
draw = void 0;
|
|
30
|
+
#draw = void 0;
|
|
31
31
|
/**
|
|
32
32
|
* The active measurement manipulated by the `draw` interaction.
|
|
33
33
|
*/
|
|
34
|
-
activeMeasurement;
|
|
34
|
+
#activeMeasurement;
|
|
35
35
|
/**
|
|
36
36
|
* Map that is used to track all predefined measurements currently added to the source.
|
|
37
37
|
* It associates the measurement geometry (key) with the corresponding measurement instance.
|
|
38
38
|
*
|
|
39
39
|
* The measurement instances here must also be contained in `finishedMeasurements`.
|
|
40
40
|
*/
|
|
41
|
-
predefinedMeasurements = /* @__PURE__ */ new Map();
|
|
41
|
+
#predefinedMeasurements = /* @__PURE__ */ new Map();
|
|
42
42
|
/**
|
|
43
43
|
* Measurement instances that were finished.
|
|
44
44
|
*/
|
|
45
|
-
finishedMeasurements = /* @__PURE__ */ new Set();
|
|
45
|
+
#finishedMeasurements = /* @__PURE__ */ new Set();
|
|
46
46
|
/**
|
|
47
47
|
* Overlay for help tooltip.
|
|
48
48
|
*/
|
|
49
|
-
helpTooltip;
|
|
49
|
+
#helpTooltip;
|
|
50
50
|
/**
|
|
51
51
|
* Keeps track of registered event handlers.
|
|
52
52
|
*/
|
|
53
|
-
resources = [];
|
|
53
|
+
#resources = [];
|
|
54
54
|
/**
|
|
55
55
|
* Called when a measurement is added to or removed from the source.
|
|
56
56
|
*/
|
|
57
|
-
measurementChangedHandler;
|
|
57
|
+
#measurementChangedHandler;
|
|
58
58
|
constructor(map, layerFactory, messages) {
|
|
59
59
|
this.map = map;
|
|
60
60
|
this.olMap = map.olMap;
|
|
61
61
|
this.messages = messages;
|
|
62
|
-
const source = this
|
|
63
|
-
this
|
|
62
|
+
const source = this.#source = new Vector();
|
|
63
|
+
this.#layer = layerFactory.create({
|
|
64
64
|
type: SimpleLayer,
|
|
65
65
|
internal: true,
|
|
66
66
|
title: "measurement-layer",
|
|
@@ -68,77 +68,77 @@ class MeasurementController {
|
|
|
68
68
|
source
|
|
69
69
|
})
|
|
70
70
|
});
|
|
71
|
-
map.layers.addLayer(this
|
|
72
|
-
this
|
|
71
|
+
map.layers.addLayer(this.#layer, { at: "topmost" });
|
|
72
|
+
this.#helpTooltip = createHelpTooltip(this.map);
|
|
73
73
|
}
|
|
74
74
|
destroy() {
|
|
75
75
|
this.stopMeasurement();
|
|
76
|
-
for (const resource of this
|
|
76
|
+
for (const resource of this.#resources) {
|
|
77
77
|
resource.destroy();
|
|
78
78
|
}
|
|
79
|
-
this
|
|
80
|
-
this
|
|
81
|
-
for (const measurement of this
|
|
79
|
+
this.#resources = [];
|
|
80
|
+
this.#activeMeasurement = destroyResource(this.#activeMeasurement);
|
|
81
|
+
for (const measurement of this.#finishedMeasurements) {
|
|
82
82
|
measurement.destroy();
|
|
83
83
|
}
|
|
84
|
-
this
|
|
85
|
-
this
|
|
86
|
-
this.map.layers.removeLayer(this
|
|
87
|
-
this
|
|
88
|
-
this
|
|
89
|
-
this
|
|
84
|
+
this.#finishedMeasurements.clear();
|
|
85
|
+
this.#helpTooltip.destroy();
|
|
86
|
+
this.map.layers.removeLayer(this.#layer);
|
|
87
|
+
this.#layer.destroy();
|
|
88
|
+
this.#measurementChangedHandler = void 0;
|
|
89
|
+
this.#predefinedMeasurements.clear();
|
|
90
90
|
}
|
|
91
91
|
/** Returns the vector layer used for finished features. */
|
|
92
92
|
getOlVectorLayer() {
|
|
93
|
-
return this
|
|
93
|
+
return this.#layer.olLayer;
|
|
94
94
|
}
|
|
95
95
|
/** Updates the style used for finished features. */
|
|
96
96
|
setFinishedFeatureStyle(style) {
|
|
97
97
|
this.getOlVectorLayer().setStyle(style);
|
|
98
98
|
}
|
|
99
99
|
setMeasurementSourceChangedHandler(handler) {
|
|
100
|
-
this
|
|
100
|
+
this.#measurementChangedHandler = handler;
|
|
101
101
|
}
|
|
102
102
|
setPredefinedMeasurements(geometries) {
|
|
103
|
-
this
|
|
103
|
+
this.#updatePredefinedMeasurements(geometries);
|
|
104
104
|
}
|
|
105
105
|
/** Updates the style used for active measurements. */
|
|
106
106
|
setActiveFeatureStyle(style) {
|
|
107
107
|
const styleFunction = toFunction(style);
|
|
108
|
-
this
|
|
108
|
+
this.#activeFeatureStyle = (feature, ...args) => {
|
|
109
109
|
const ft = feature?.getGeometry()?.getType();
|
|
110
110
|
if (ft === "Polygon" || ft === "LineString" || ft === "Point") {
|
|
111
111
|
return styleFunction(feature, ...args);
|
|
112
112
|
}
|
|
113
113
|
};
|
|
114
|
-
this
|
|
114
|
+
this.#draw?.getOverlay().setStyle(this.#activeFeatureStyle);
|
|
115
115
|
}
|
|
116
116
|
/** Removes all finished measurements. */
|
|
117
117
|
clearMeasurements() {
|
|
118
|
-
const currentFeatures = this
|
|
119
|
-
this
|
|
118
|
+
const currentFeatures = this.#source.getFeatures();
|
|
119
|
+
this.#source.clear();
|
|
120
120
|
currentFeatures.forEach((feature) => {
|
|
121
|
-
this
|
|
121
|
+
this.#raiseMeasurementsChangeEvent("remove-measurement", feature);
|
|
122
122
|
});
|
|
123
|
-
this
|
|
124
|
-
for (const measurement of this
|
|
123
|
+
this.#predefinedMeasurements.clear();
|
|
124
|
+
for (const measurement of this.#finishedMeasurements) {
|
|
125
125
|
measurement.destroy();
|
|
126
126
|
}
|
|
127
|
-
this
|
|
127
|
+
this.#finishedMeasurements.clear();
|
|
128
128
|
}
|
|
129
129
|
/** Starts measuring using the provided type. */
|
|
130
130
|
startMeasurement(type) {
|
|
131
|
-
if (this
|
|
131
|
+
if (this.#draw) {
|
|
132
132
|
throw new Error("Internal error: another measurement interaction is still active.");
|
|
133
133
|
}
|
|
134
134
|
const geometryType = type === "area" ? "Polygon" : "LineString";
|
|
135
|
-
const draw = this
|
|
136
|
-
source: this
|
|
135
|
+
const draw = this.#draw = new Draw({
|
|
136
|
+
source: this.#source,
|
|
137
137
|
type: geometryType,
|
|
138
|
-
style: this
|
|
138
|
+
style: this.#activeFeatureStyle
|
|
139
139
|
});
|
|
140
140
|
this.olMap.addInteraction(draw);
|
|
141
|
-
this
|
|
141
|
+
this.#updateTooltip();
|
|
142
142
|
let measurement;
|
|
143
143
|
let changeListenerKey = void 0;
|
|
144
144
|
draw.on("drawstart", (evt) => {
|
|
@@ -146,32 +146,32 @@ class MeasurementController {
|
|
|
146
146
|
if (!sketch) {
|
|
147
147
|
return;
|
|
148
148
|
}
|
|
149
|
-
measurement = this
|
|
149
|
+
measurement = this.#activeMeasurement = new MeasurementInstance("active", sketch, this);
|
|
150
150
|
changeListenerKey = sketch.getGeometry()?.on("change", () => {
|
|
151
151
|
measurement?.updateTooltipContent();
|
|
152
152
|
measurement?.updateTooltipPosition();
|
|
153
153
|
});
|
|
154
|
-
this
|
|
154
|
+
this.#updateTooltip();
|
|
155
155
|
});
|
|
156
156
|
draw.on("drawend", () => {
|
|
157
|
-
if (measurement && measurement === this
|
|
157
|
+
if (measurement && measurement === this.#activeMeasurement) {
|
|
158
158
|
const newMeasurement = measurement;
|
|
159
159
|
newMeasurement.updateState("finished");
|
|
160
|
-
this
|
|
161
|
-
this
|
|
162
|
-
this
|
|
160
|
+
this.#finishedMeasurements.add(newMeasurement);
|
|
161
|
+
this.#raiseMeasurementsChangeEvent("add-measurement", newMeasurement.feature);
|
|
162
|
+
this.#activeMeasurement = measurement = void 0;
|
|
163
163
|
}
|
|
164
164
|
measurement = void 0;
|
|
165
165
|
if (changeListenerKey) {
|
|
166
166
|
unByKey(changeListenerKey);
|
|
167
167
|
}
|
|
168
|
-
this
|
|
168
|
+
this.#updateTooltip();
|
|
169
169
|
});
|
|
170
170
|
draw.on("drawabort", () => {
|
|
171
171
|
if (measurement) {
|
|
172
172
|
measurement.destroy();
|
|
173
|
-
if (measurement === this
|
|
174
|
-
this
|
|
173
|
+
if (measurement === this.#activeMeasurement) {
|
|
174
|
+
this.#activeMeasurement = void 0;
|
|
175
175
|
}
|
|
176
176
|
measurement = void 0;
|
|
177
177
|
}
|
|
@@ -182,53 +182,53 @@ class MeasurementController {
|
|
|
182
182
|
}
|
|
183
183
|
/** Stops the current measuring started by `startMeasurement`. */
|
|
184
184
|
stopMeasurement() {
|
|
185
|
-
if (this
|
|
186
|
-
this.olMap.removeInteraction(this
|
|
187
|
-
this
|
|
188
|
-
this
|
|
189
|
-
this
|
|
185
|
+
if (this.#draw) {
|
|
186
|
+
this.olMap.removeInteraction(this.#draw);
|
|
187
|
+
this.#draw.abortDrawing();
|
|
188
|
+
this.#draw.dispose();
|
|
189
|
+
this.#draw = void 0;
|
|
190
190
|
}
|
|
191
|
-
this
|
|
191
|
+
this.#activeMeasurement = destroyResource(this.#activeMeasurement);
|
|
192
192
|
}
|
|
193
|
-
updateTooltip() {
|
|
194
|
-
const overlay = this
|
|
195
|
-
const helpMessage = getHelpMessage(this.messages, this
|
|
193
|
+
#updateTooltip() {
|
|
194
|
+
const overlay = this.#helpTooltip;
|
|
195
|
+
const helpMessage = getHelpMessage(this.messages, this.#activeMeasurement);
|
|
196
196
|
const newContent = createElement(MeasurementTooltipContent, { content: helpMessage });
|
|
197
197
|
overlay.setContent(newContent);
|
|
198
198
|
}
|
|
199
|
-
updatePredefinedMeasurements(geometries) {
|
|
199
|
+
#updatePredefinedMeasurements(geometries) {
|
|
200
200
|
const addedMeasurements = geometries.filter(
|
|
201
|
-
(geom) => !this
|
|
201
|
+
(geom) => !this.#predefinedMeasurements.has(geom)
|
|
202
202
|
);
|
|
203
203
|
const removedMeasurements = [];
|
|
204
|
-
for (const geom of this
|
|
204
|
+
for (const geom of this.#predefinedMeasurements.keys()) {
|
|
205
205
|
if (!geometries.includes(geom)) {
|
|
206
206
|
removedMeasurements.push(geom);
|
|
207
207
|
}
|
|
208
208
|
}
|
|
209
209
|
addedMeasurements.forEach((geom) => {
|
|
210
210
|
const measurementFeature = new Feature(geom);
|
|
211
|
-
this
|
|
211
|
+
this.#source.addFeature(measurementFeature);
|
|
212
212
|
const measurement = new MeasurementInstance("finished", measurementFeature, this);
|
|
213
|
-
this
|
|
214
|
-
this
|
|
215
|
-
this
|
|
213
|
+
this.#finishedMeasurements.add(measurement);
|
|
214
|
+
this.#predefinedMeasurements.set(geom, measurement);
|
|
215
|
+
this.#raiseMeasurementsChangeEvent("add-measurement", measurementFeature);
|
|
216
216
|
});
|
|
217
217
|
removedMeasurements.forEach((geom) => {
|
|
218
|
-
const measurement = this
|
|
218
|
+
const measurement = this.#predefinedMeasurements.get(geom);
|
|
219
219
|
if (measurement) {
|
|
220
|
-
this
|
|
221
|
-
this
|
|
220
|
+
this.#source.removeFeature(measurement.feature);
|
|
221
|
+
this.#finishedMeasurements.delete(measurement);
|
|
222
222
|
measurement.destroy();
|
|
223
|
-
this
|
|
223
|
+
this.#raiseMeasurementsChangeEvent("remove-measurement", measurement.feature);
|
|
224
224
|
}
|
|
225
|
-
this
|
|
225
|
+
this.#predefinedMeasurements.delete(geom);
|
|
226
226
|
});
|
|
227
227
|
}
|
|
228
|
-
raiseMeasurementsChangeEvent(kind, measurementFeature) {
|
|
228
|
+
#raiseMeasurementsChangeEvent(kind, measurementFeature) {
|
|
229
229
|
const measurementGeom = measurementFeature.getGeometry();
|
|
230
|
-
if (this
|
|
231
|
-
this
|
|
230
|
+
if (this.#measurementChangedHandler && measurementGeom) {
|
|
231
|
+
this.#measurementChangedHandler({
|
|
232
232
|
kind,
|
|
233
233
|
geometry: measurementGeom instanceof Polygon ? measurementGeom : measurementGeom
|
|
234
234
|
});
|
|
@@ -238,28 +238,28 @@ class MeasurementController {
|
|
|
238
238
|
class MeasurementInstance {
|
|
239
239
|
controller;
|
|
240
240
|
feature;
|
|
241
|
-
|
|
242
|
-
tooltip;
|
|
241
|
+
#state;
|
|
242
|
+
#tooltip;
|
|
243
243
|
constructor(state, feature, controller) {
|
|
244
244
|
this.controller = controller;
|
|
245
|
-
this
|
|
245
|
+
this.#state = state;
|
|
246
246
|
this.feature = feature;
|
|
247
|
-
this
|
|
247
|
+
this.#tooltip = createMeasureTooltip(this.controller.map, state === "finished");
|
|
248
248
|
this.updateTooltipContent();
|
|
249
249
|
this.updateTooltipPosition();
|
|
250
250
|
}
|
|
251
251
|
destroy() {
|
|
252
|
-
this
|
|
252
|
+
this.#tooltip.destroy();
|
|
253
253
|
}
|
|
254
254
|
get state() {
|
|
255
|
-
return this
|
|
255
|
+
return this.#state;
|
|
256
256
|
}
|
|
257
257
|
updateState(state) {
|
|
258
|
-
if (this
|
|
258
|
+
if (this.#state === state) {
|
|
259
259
|
return;
|
|
260
260
|
}
|
|
261
|
-
this
|
|
262
|
-
if (this
|
|
261
|
+
this.#state = state;
|
|
262
|
+
if (this.#state === "finished") {
|
|
263
263
|
this.finishTooltip();
|
|
264
264
|
}
|
|
265
265
|
}
|
|
@@ -269,15 +269,15 @@ class MeasurementInstance {
|
|
|
269
269
|
if (!geometry) {
|
|
270
270
|
return;
|
|
271
271
|
}
|
|
272
|
-
const projection = this
|
|
272
|
+
const projection = this.#olMap.getView().getProjection();
|
|
273
273
|
let output;
|
|
274
274
|
if (geometry instanceof Polygon) {
|
|
275
|
-
output = formatArea(geometry, projection, this
|
|
275
|
+
output = formatArea(geometry, projection, this.#messages);
|
|
276
276
|
} else if (geometry instanceof LineString) {
|
|
277
|
-
output = formatLength(geometry, projection, this
|
|
277
|
+
output = formatLength(geometry, projection, this.#messages);
|
|
278
278
|
}
|
|
279
279
|
if (output) {
|
|
280
|
-
this
|
|
280
|
+
this.#tooltip.setContent(createElement(MeasurementTooltipContent, { content: output }));
|
|
281
281
|
}
|
|
282
282
|
}
|
|
283
283
|
// Updates the tooltip's position.
|
|
@@ -294,18 +294,18 @@ class MeasurementInstance {
|
|
|
294
294
|
} else {
|
|
295
295
|
return;
|
|
296
296
|
}
|
|
297
|
-
this
|
|
297
|
+
this.#tooltip.setPosition(tooltipCoord);
|
|
298
298
|
}
|
|
299
299
|
finishTooltip() {
|
|
300
|
-
this
|
|
301
|
-
this
|
|
300
|
+
this.#tooltip.element.className = FINISHED_MEASUREMENT_CLASSNAME;
|
|
301
|
+
this.#tooltip.setOffset(FINISHED_MEASUREMENT_OFFSET);
|
|
302
302
|
this.updateTooltipContent();
|
|
303
303
|
this.updateTooltipPosition();
|
|
304
304
|
}
|
|
305
|
-
get olMap() {
|
|
305
|
+
get #olMap() {
|
|
306
306
|
return this.controller.olMap;
|
|
307
307
|
}
|
|
308
|
-
get messages() {
|
|
308
|
+
get #messages() {
|
|
309
309
|
return this.controller.messages;
|
|
310
310
|
}
|
|
311
311
|
}
|
|
@@ -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 { LayerFactory, MapModel, Overlay, SimpleLayer } from \"@open-pioneer/map\";\nimport Feature from \"ol/Feature\";\nimport OlMap from \"ol/Map\";\nimport { unByKey } from \"ol/Observable\";\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 {\n type MeasurementsChangeEvent,\n type MeasurementGeometry,\n type MeasurementProps\n} from \"./Measurement\";\nimport { createElement } from \"react\";\nimport { MeasurementTooltipContent } from \"./MeasurementTooltip\";\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 * Overlay for help tooltip.\n */\n private helpTooltip: Overlay;\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 this.helpTooltip = createHelpTooltip(this.map);\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();\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();\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();\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 updateTooltip() {\n const overlay = this.helpTooltip;\n const helpMessage = getHelpMessage(this.messages, this.activeMeasurement);\n const newContent = createElement(MeasurementTooltipContent, { content: helpMessage });\n overlay.setContent(newContent);\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 tooltip: Overlay;\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.controller.map, state === \"finished\");\n this.updateTooltipContent();\n this.updateTooltipPosition();\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 if (this._state === \"finished\") {\n this.finishTooltip();\n }\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 output;\n if (geometry instanceof Polygon) {\n output = formatArea(geometry, projection, this.messages);\n } else if (geometry instanceof LineString) {\n output = formatLength(geometry, projection, this.messages);\n }\n if (output) {\n this.tooltip.setContent(createElement(MeasurementTooltipContent, { content: output }));\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.setPosition(tooltipCoord);\n }\n\n finishTooltip() {\n this.tooltip.element.className = FINISHED_MEASUREMENT_CLASSNAME;\n this.tooltip.setOffset(FINISHED_MEASUREMENT_OFFSET);\n this.updateTooltipContent();\n this.updateTooltipPosition();\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];\nconst ACTIVE_MEASUREMENT_CLASSNAME = \"measurement-tooltip measurement-active-tooltip printing-hide\";\nconst FINISHED_MEASUREMENT_CLASSNAME = \"measurement-tooltip measurement-finished-tooltip\";\n\nfunction createHelpTooltip(map: MapModel): Overlay {\n const helpOverlay = map.overlays.add({\n className: \"measurement-tooltip printing-hide\",\n position: \"follow-pointer\",\n tag: \"measurement-help-overlay\",\n offset: [15, 0],\n positioning: \"center-left\",\n ariaRole: \"tooltip\",\n content: createElement(MeasurementTooltipContent)\n });\n\n return helpOverlay;\n}\n\nfunction createMeasureTooltip(map: MapModel, isFinished = false): Overlay {\n const overlay = map.overlays.add({\n content: createElement(MeasurementTooltipContent),\n offset: !isFinished ? DEFAULT_MEASUREMENT_OFFSET : FINISHED_MEASUREMENT_OFFSET,\n positioning: \"bottom-center\",\n className: !isFinished ? ACTIVE_MEASUREMENT_CLASSNAME : FINISHED_MEASUREMENT_CLASSNAME,\n stopEvent: false,\n ariaRole: \"tooltip\",\n advanced: {\n insertFirst: false\n }\n });\n\n return overlay;\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\\u00B2`;\n } else {\n output = `${messages.formatNumber(area)} m\\u00B2`;\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\n\nimport { destroyResource, Resource } from \"@open-pioneer/core\";\nimport { LayerFactory, MapModel, Overlay, SimpleLayer } from \"@open-pioneer/map\";\nimport { Coordinate } from \"ol/coordinate\";\nimport { EventsKey } from \"ol/events\";\nimport Feature from \"ol/Feature\";\nimport { LineString, Polygon } from \"ol/geom\";\nimport Draw from \"ol/interaction/Draw\";\nimport { Vector as VectorLayer } from \"ol/layer\";\nimport OlMap from \"ol/Map\";\nimport { unByKey } from \"ol/Observable\";\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 { createElement } from \"react\";\nimport {\n type MeasurementsChangeEvent,\n type MeasurementGeometry,\n type MeasurementProps\n} from \"./Measurement\";\nimport { MeasurementTooltipContent } from \"./MeasurementTooltip\";\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 #activeFeatureStyle: StyleFunction | undefined;\n /**\n * The layer rendering the measurement \"features\".\n */\n #layer: SimpleLayer;\n\n /**\n * Source of {@link layer}.\n */\n #source: VectorSource;\n\n /**\n * Stores the current `Draw` interaction.\n */\n #draw: Draw | undefined = undefined;\n\n /**\n * The active measurement manipulated by the `draw` interaction.\n */\n #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 #predefinedMeasurements = new Map<MeasurementGeometry, MeasurementInstance>();\n\n /**\n * Measurement instances that were finished.\n */\n #finishedMeasurements = new Set<MeasurementInstance>();\n\n /**\n * Overlay for help tooltip.\n */\n #helpTooltip: Overlay;\n\n /**\n * Keeps track of registered event handlers.\n */\n #resources: Resource[] = [];\n\n /**\n * Called when a measurement is added to or removed from the source.\n */\n #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 this.#helpTooltip = createHelpTooltip(this.map);\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();\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();\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();\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 #updateTooltip() {\n const overlay = this.#helpTooltip;\n const helpMessage = getHelpMessage(this.messages, this.#activeMeasurement);\n const newContent = createElement(MeasurementTooltipContent, { content: helpMessage });\n overlay.setContent(newContent);\n }\n\n #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 #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 #state: \"active\" | \"finished\";\n #tooltip: Overlay;\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.controller.map, state === \"finished\");\n this.updateTooltipContent();\n this.updateTooltipPosition();\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 if (this.#state === \"finished\") {\n this.finishTooltip();\n }\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 output;\n if (geometry instanceof Polygon) {\n output = formatArea(geometry, projection, this.#messages);\n } else if (geometry instanceof LineString) {\n output = formatLength(geometry, projection, this.#messages);\n }\n if (output) {\n this.#tooltip.setContent(createElement(MeasurementTooltipContent, { content: output }));\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.setPosition(tooltipCoord);\n }\n\n finishTooltip() {\n this.#tooltip.element.className = FINISHED_MEASUREMENT_CLASSNAME;\n this.#tooltip.setOffset(FINISHED_MEASUREMENT_OFFSET);\n this.updateTooltipContent();\n this.updateTooltipPosition();\n }\n\n get #olMap(): OlMap {\n return this.controller.olMap;\n }\n\n get #messages(): Messages {\n return this.controller.messages;\n }\n}\n\nconst DEFAULT_MEASUREMENT_OFFSET = [0, -15];\nconst FINISHED_MEASUREMENT_OFFSET = [0, -7];\nconst ACTIVE_MEASUREMENT_CLASSNAME = \"measurement-tooltip measurement-active-tooltip printing-hide\";\nconst FINISHED_MEASUREMENT_CLASSNAME = \"measurement-tooltip measurement-finished-tooltip\";\n\nfunction createHelpTooltip(map: MapModel): Overlay {\n const helpOverlay = map.overlays.add({\n className: \"measurement-tooltip printing-hide\",\n position: \"follow-pointer\",\n tag: \"measurement-help-overlay\",\n offset: [15, 0],\n positioning: \"center-left\",\n ariaRole: \"tooltip\",\n content: createElement(MeasurementTooltipContent)\n });\n\n return helpOverlay;\n}\n\nfunction createMeasureTooltip(map: MapModel, isFinished = false): Overlay {\n const overlay = map.overlays.add({\n content: createElement(MeasurementTooltipContent),\n offset: !isFinished ? DEFAULT_MEASUREMENT_OFFSET : FINISHED_MEASUREMENT_OFFSET,\n positioning: \"bottom-center\",\n className: !isFinished ? ACTIVE_MEASUREMENT_CLASSNAME : FINISHED_MEASUREMENT_CLASSNAME,\n stopEvent: false,\n ariaRole: \"tooltip\",\n advanced: {\n insertFirst: false\n }\n });\n\n return overlay;\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\\u00B2`;\n } else {\n output = `${messages.formatNumber(area)} m\\u00B2`;\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 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MeasurementTooltip.js","sources":["MeasurementTooltip.tsx"],"sourcesContent":["// SPDX-FileCopyrightText: 2023-2025 Open Pioneer project (https://github.com/open-pioneer)\n// SPDX-License-Identifier: Apache-2.0\nimport { Span } from \"@chakra-ui/react\";\nimport { ReactNode } from \"react\";\n\nexport function MeasurementTooltipContent(props: { content?: ReactNode }) {\n const { content } = props;\n return <Span>{content}</Span>;\n}\n"],"names":[],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"MeasurementTooltip.js","sources":["MeasurementTooltip.tsx"],"sourcesContent":["// SPDX-FileCopyrightText: 2023-2025 Open Pioneer project (https://github.com/open-pioneer)\n// SPDX-License-Identifier: Apache-2.0\n\nimport { Span } from \"@chakra-ui/react\";\nimport { ReactNode } from \"react\";\n\nexport function MeasurementTooltipContent(props: { content?: ReactNode }) {\n const { content } = props;\n return <Span>{content}</Span>;\n}\n"],"names":[],"mappings":";;;AAMO,SAAS,0BAA0B,KAAA,EAAgC;AACtE,EAAA,MAAM,EAAE,SAAQ,GAAI,KAAA;AACpB,EAAA,uBAAO,GAAA,CAAC,QAAM,QAAA,EAAA,OAAA,EAAQ,CAAA;AAC1B;;;;"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"type": "module",
|
|
3
3
|
"name": "@open-pioneer/measurement",
|
|
4
|
-
"version": "1.4.0
|
|
4
|
+
"version": "1.4.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"
|
|
@@ -14,14 +14,14 @@
|
|
|
14
14
|
"directory": "src/packages/measurement"
|
|
15
15
|
},
|
|
16
16
|
"dependencies": {
|
|
17
|
-
"@chakra-ui/react": "^3.36.
|
|
18
|
-
"@open-pioneer/
|
|
19
|
-
"@open-pioneer/
|
|
20
|
-
"@open-pioneer/
|
|
21
|
-
"@open-pioneer/
|
|
17
|
+
"@chakra-ui/react": "^3.36.1",
|
|
18
|
+
"@open-pioneer/chakra-snippets": "^4.7.0",
|
|
19
|
+
"@open-pioneer/core": "^4.7.0",
|
|
20
|
+
"@open-pioneer/react-utils": "^4.7.0",
|
|
21
|
+
"@open-pioneer/runtime": "^4.7.0",
|
|
22
22
|
"ol": "^10.9.0",
|
|
23
|
-
"react": "^19.2.
|
|
24
|
-
"@open-pioneer/map": "1.4.0
|
|
23
|
+
"react": "^19.2.8",
|
|
24
|
+
"@open-pioneer/map": "1.4.0"
|
|
25
25
|
},
|
|
26
26
|
"exports": {
|
|
27
27
|
"./package.json": "./package.json",
|