@open-pioneer/selection 1.5.0-dev.20260911123645 → 1.5.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 +39 -31
- package/_virtual/hooks.js.map +1 -1
- package/_virtual/source-info.js.map +1 -1
- package/i18n/de.yaml +1 -1
- package/i18n/en.yaml +2 -2
- package/interactions/ExtentSelectionInteraction.js.map +1 -1
- package/model/SelectionViewModel.js +8 -4
- package/model/SelectionViewModel.js.map +1 -1
- package/model/SelectionViewModelFactory.js.map +1 -1
- package/package.json +10 -9
- package/sources/VectorSelectionSource.js.map +1 -1
- package/sources/VectorSelectionSourceFactory.js.map +1 -1
- package/ui/Selection.js.map +1 -1
- package/ui/SelectionSourceItem.js.map +1 -1
- package/ui/selection.css +0 -14
- package/ui/selection.css.map +1 -1
- package/ui/useSelectionSourceId.js.map +1 -1
- package/ui/useSelectionViewModel.js.map +1 -1
- package/ui/useSourceStatus.js.map +1 -1
- package/ui/SelectionTooltipContent.d.ts +0 -4
- package/ui/SelectionTooltipContent.js +0 -10
- package/ui/SelectionTooltipContent.js.map +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,11 +1,17 @@
|
|
|
1
1
|
# @open-pioneer/selection
|
|
2
2
|
|
|
3
|
-
## 1.5.0
|
|
3
|
+
## 1.5.0
|
|
4
4
|
|
|
5
5
|
### Minor Changes
|
|
6
6
|
|
|
7
7
|
- f790fda: Update to Chakra 3.37.0
|
|
8
8
|
- fab4c36: Add the map model to the context of the selection source's `select` method.
|
|
9
|
+
- a9c1213: Rework the tooltips rendered on the map: help tooltips now look like chakra's tooltips, and the measurement tooltips (active and finished measurements) are also derived from chakra's tooltip styles.
|
|
10
|
+
|
|
11
|
+
The built-in styles of these tooltips are no longer shipped as plain css, chakra style props are used instead.
|
|
12
|
+
The existing css classes (`editing-tooltip`, `measurement-tooltip`, `measurement-active-tooltip`, `measurement-finished-tooltip`, `selection-tooltip`) remain on the overlay's element.
|
|
13
|
+
|
|
14
|
+
- a186f5d: Update core packages to 4.8.0.
|
|
9
15
|
- fab4c36: Add support for an `id` property on the selection source interface to identify sources. The property remains optional for the time being to preserve backwards compatibility.
|
|
10
16
|
|
|
11
17
|
### Patch Changes
|
|
@@ -15,7 +21,9 @@
|
|
|
15
21
|
If the user starts another selection while a request is still running, the previous request is cancelled
|
|
16
22
|
and only the results of the most recent selection are used.
|
|
17
23
|
- fab4c36: Use `synchronized` to watch the vector layer's visibility.
|
|
18
|
-
- fab4c36: Refactor internal state management
|
|
24
|
+
- fab4c36: Refactor the internal state management of the selection component: the widget state now lives in a
|
|
25
|
+
long lived, reactive view model instead of react state. This is an internal change; the component's
|
|
26
|
+
properties, events and behavior are unchanged.
|
|
19
27
|
- 09ec7c7: Updated dependencies
|
|
20
28
|
|
|
21
29
|
## 1.4.0
|
|
@@ -96,17 +104,17 @@
|
|
|
96
104
|
- 193068a: Deprecate the `mapId` property on React components.
|
|
97
105
|
Use the `MapModel` directly instead to pass a reference to the map.
|
|
98
106
|
|
|
99
|
-
|
|
107
|
+
Example:
|
|
100
108
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
109
|
+
```tsx
|
|
110
|
+
// Default map for entire component tree
|
|
111
|
+
<DefaultMapProvider map={mapModel}>
|
|
112
|
+
<Toc />
|
|
113
|
+
</DefaultMapProvider>
|
|
106
114
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
115
|
+
// Map for specific component
|
|
116
|
+
<Toc map={mapModel} />
|
|
117
|
+
```
|
|
110
118
|
|
|
111
119
|
### Patch Changes
|
|
112
120
|
|
|
@@ -127,33 +135,33 @@
|
|
|
127
135
|
- e7978a8: Support reactive changes on the `SelectionSource`'s `status` property using the reactivity API.
|
|
128
136
|
**Remove** support for the `changed:status"` event on the selection source: use signals instead.
|
|
129
137
|
|
|
130
|
-
|
|
138
|
+
For example, to implement a `SelectionSource` with changing availability:
|
|
131
139
|
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
140
|
+
```ts
|
|
141
|
+
class MySelectionSource implements SelectionSource {
|
|
142
|
+
private _status = reactive("available");
|
|
135
143
|
|
|
136
|
-
|
|
144
|
+
label = "My selection source";
|
|
137
145
|
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
146
|
+
get status() {
|
|
147
|
+
return this._status.value;
|
|
148
|
+
}
|
|
141
149
|
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
150
|
+
someEventHandler() {
|
|
151
|
+
// Change the status by updating the signal's value.
|
|
152
|
+
// The UI will update automatically.
|
|
153
|
+
this._status.value = "unavailable";
|
|
154
|
+
}
|
|
146
155
|
}
|
|
147
|
-
|
|
148
|
-
```
|
|
156
|
+
```
|
|
149
157
|
|
|
150
158
|
- b717121: Update from OL 9 to OL 10.
|
|
151
159
|
- b717121: Adjust the type the property `vectorLayer` of the exported interface `VectorLayerSelectionSourceOptions`.
|
|
152
160
|
The type is now `VectorLayer<VectorSource, Feature>` instead of `VectorLayer<Feature>`.
|
|
153
161
|
- 2fa8020: Update trails core package dependencies.
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
162
|
+
- Also updates Chakra UI to the latest 2.x version and Chakra React Select to version 5.
|
|
163
|
+
- Removes any obsolete references to `@chakra-ui/system`.
|
|
164
|
+
This dependency seems to be no longer required and may lead to duplicate packages in your dependency tree.
|
|
157
165
|
|
|
158
166
|
### Patch Changes
|
|
159
167
|
|
|
@@ -171,7 +179,7 @@
|
|
|
171
179
|
- 583f1d6: The `mapId` or `map` properties are now optional on individual components.
|
|
172
180
|
You can use the `DefaultMapProvider` to configure an implicit default value.
|
|
173
181
|
|
|
174
|
-
|
|
182
|
+
Note that configuring _neither_ a default _nor_ an explicit `map` or `mapId` will trigger a runtime error.
|
|
175
183
|
|
|
176
184
|
- 583f1d6: All UI components in this project now accept the `mapId` (a `string`) _or_ the `map` (a `MapModel`) directly.
|
|
177
185
|
- a8b3449: Switch to a new versioning strategy.
|
|
@@ -193,8 +201,8 @@
|
|
|
193
201
|
- 28e092a: Update dependencies
|
|
194
202
|
- 28e092a: Adapt to OpenLayers type changes.
|
|
195
203
|
|
|
196
|
-
|
|
197
|
-
|
|
204
|
+
When creating a selection source for a `VectorLayer`, the precise type of that vector layer must now be `VectorLayer<Feature>` (instead of `VectorLayer<VectorSource>`).
|
|
205
|
+
This is a TypeScript-only change that has no effects on the JavaScript code at runtime.
|
|
198
206
|
|
|
199
207
|
- 65a14f4: Open select-menu on enter (fixes issue [#320](https://github.com/open-pioneer/trails-openlayers-base-packages/issues/320))
|
|
200
208
|
- 484ad86: Add tooltip role to tooltip divs (See https://github.com/open-pioneer/trails-openlayers-base-packages/issues/309).
|
package/_virtual/hooks.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hooks.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"hooks.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"source-info.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"source-info.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;"}
|
package/i18n/de.yaml
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
messages:
|
|
2
2
|
selectSource: "Quelle auswählen"
|
|
3
|
-
tooltip: "Klicken Sie in die Karte, halten Sie die Maustaste gedrückt und ziehen Sie ein Rechteck auf"
|
|
3
|
+
tooltip: "Klicken Sie in die Karte, halten Sie die Maustaste gedrückt und ziehen Sie ein Rechteck auf."
|
|
4
4
|
disabledTooltip: "Die aktuelle Selektionsquelle ist nicht verfügbar."
|
|
5
5
|
noSourceTooltip: "Es ist keine Selektionsquelle ausgewählt. Zum Starten bitte Selektionsquelle auswählen."
|
|
6
6
|
sourceNotAvailable: "Quelle nicht verfügbar"
|
package/i18n/en.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
messages:
|
|
2
2
|
selectSource: "Select source"
|
|
3
|
-
tooltip: "Click on the map, hold down the mouse button and draw a rectangle"
|
|
4
|
-
disabledTooltip: "The current selection source is not available"
|
|
3
|
+
tooltip: "Click on the map, hold down the mouse button and draw a rectangle."
|
|
4
|
+
disabledTooltip: "The current selection source is not available."
|
|
5
5
|
noSourceTooltip: "No selection source selected. Please choose a selection source to start."
|
|
6
6
|
sourceNotAvailable: "Source not available"
|
|
7
7
|
selectionFailed: "Spatial selection failed"
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ExtentSelectionInteraction.js","sources":["ExtentSelectionInteraction.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2023-2025 Open Pioneer project (https://github.com/open-pioneer)\n// SPDX-License-Identifier: Apache-2.0\n\nimport { destroyResources, Resource } from \"@open-pioneer/core\";\nimport { MapModel } from \"@open-pioneer/map\";\nimport { mouseActionButton } from \"ol/events/condition\";\nimport { Geometry } from \"ol/geom\";\nimport { DragBox, DragPan } from \"ol/interaction\";\nimport MapBrowserEvent from \"ol/MapBrowserEvent\";\n\n/**\n * Registers interactions on the map for extent selection.\n *\n * Calls `onSuccess` whenever the user selected an extent.\n */\nexport class ExtentSelectionInteraction {\n #map: MapModel;\n #onSuccess: (geometry: Geometry) => void;\n\n #resources: Resource[];\n\n constructor(map: MapModel, onSuccess: (geometry: Geometry) => void) {\n this.#map = map;\n this.#onSuccess = onSuccess;\n\n this.#resources = [\n createDragboxInteraction(this.#map, this.#onSuccess),\n createPanningInteraction(this.#map)\n ];\n }\n\n destroy() {\n destroyResources(this.#resources);\n }\n}\n\nfunction createDragboxInteraction(\n map: MapModel,\n onSuccess: (geometry: Geometry) => void\n): Resource {\n const olMap = map.olMap;\n const dragbox = new DragBox({\n className: \"selection-drag-box\",\n condition: mouseActionButton\n });\n dragbox.on(\"boxend\", function () {\n onSuccess(dragbox.getGeometry());\n });\n\n olMap.addInteraction(dragbox);\n return {\n destroy() {\n olMap.removeInteraction(dragbox);\n dragbox.dispose();\n }\n };\n}\n\n// For panning using the right mouse button during selection interaction\nfunction createPanningInteraction(map: MapModel): Resource {\n const olMap = map.olMap;\n const rightClick = (mapBrowserEvent: MapBrowserEvent) => {\n const originalEvent = mapBrowserEvent.originalEvent;\n return \"button\" in originalEvent && originalEvent.button === 2;\n };\n const drag = new DragPan({\n condition: rightClick\n });\n\n olMap.addInteraction(drag);\n return {\n destroy() {\n olMap.removeInteraction(drag);\n drag.dispose();\n }\n };\n}\n"],"names":[],"mappings":";;;;AAeO,MAAM,0BAAA,CAA2B;AAAA,EACpC,IAAA;AAAA,EACA,UAAA;AAAA,EAEA,UAAA;AAAA,EAEA,WAAA,CAAY,KAAe,SAAA,EAAyC;AAChE,IAAA,IAAA,CAAK,IAAA,GAAO,GAAA;AACZ,IAAA,IAAA,CAAK,UAAA,GAAa,SAAA;AAElB,IAAA,IAAA,CAAK,UAAA,GAAa;AAAA,MACd,wBAAA,CAAyB,IAAA,CAAK,IAAA,EAAM,IAAA,CAAK,UAAU,CAAA;AAAA,MACnD,wBAAA,CAAyB,KAAK,IAAI;AAAA,KACtC;AAAA,EACJ;AAAA,EAEA,OAAA,GAAU;AACN,IAAA,gBAAA,CAAiB,KAAK,UAAU,CAAA;AAAA,EACpC;AACJ;AAEA,SAAS,wBAAA,CACL,KACA,SAAA,EACQ;AACR,EAAA,MAAM,QAAQ,GAAA,CAAI,KAAA;AAClB,EAAA,MAAM,OAAA,GAAU,IAAI,OAAA,CAAQ;AAAA,IACxB,SAAA,EAAW,oBAAA;AAAA,IACX,SAAA,EAAW;AAAA,GACd,CAAA;AACD,EAAA,OAAA,CAAQ,EAAA,CAAG,UAAU,WAAY;AAC7B,IAAA,SAAA,CAAU,OAAA,CAAQ,aAAa,CAAA;AAAA,EACnC,CAAC,CAAA;AAED,EAAA,KAAA,CAAM,eAAe,OAAO,CAAA;AAC5B,EAAA,OAAO;AAAA,IACH,OAAA,GAAU;AACN,MAAA,KAAA,CAAM,kBAAkB,OAAO,CAAA;AAC/B,MAAA,OAAA,CAAQ,OAAA,EAAQ;AAAA,IACpB;AAAA,GACJ;AACJ;AAGA,SAAS,yBAAyB,GAAA,EAAyB;AACvD,EAAA,MAAM,QAAQ,GAAA,CAAI,KAAA;AAClB,EAAA,MAAM,UAAA,GAAa,CAAC,eAAA,KAAqC;AACrD,IAAA,MAAM,gBAAgB,eAAA,CAAgB,aAAA;AACtC,IAAA,OAAO,QAAA,IAAY,aAAA,IAAiB,aAAA,CAAc,MAAA,KAAW,CAAA;AAAA,EACjE,CAAA;AACA,EAAA,MAAM,IAAA,GAAO,IAAI,OAAA,CAAQ;AAAA,IACrB,SAAA,EAAW;AAAA,GACd,CAAA;AAED,EAAA,KAAA,CAAM,eAAe,IAAI,CAAA;AACzB,EAAA,OAAO;AAAA,IACH,OAAA,GAAU;AACN,MAAA,KAAA,CAAM,kBAAkB,IAAI,CAAA;AAC5B,MAAA,IAAA,CAAK,OAAA,EAAQ;AAAA,IACjB;AAAA,GACJ;AACJ
|
|
1
|
+
{"version":3,"file":"ExtentSelectionInteraction.js","sources":["ExtentSelectionInteraction.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2023-2025 Open Pioneer project (https://github.com/open-pioneer)\n// SPDX-License-Identifier: Apache-2.0\n\nimport { destroyResources, Resource } from \"@open-pioneer/core\";\nimport { MapModel } from \"@open-pioneer/map\";\nimport { mouseActionButton } from \"ol/events/condition\";\nimport { Geometry } from \"ol/geom\";\nimport { DragBox, DragPan } from \"ol/interaction\";\nimport MapBrowserEvent from \"ol/MapBrowserEvent\";\n\n/**\n * Registers interactions on the map for extent selection.\n *\n * Calls `onSuccess` whenever the user selected an extent.\n */\nexport class ExtentSelectionInteraction {\n #map: MapModel;\n #onSuccess: (geometry: Geometry) => void;\n\n #resources: Resource[];\n\n constructor(map: MapModel, onSuccess: (geometry: Geometry) => void) {\n this.#map = map;\n this.#onSuccess = onSuccess;\n\n this.#resources = [\n createDragboxInteraction(this.#map, this.#onSuccess),\n createPanningInteraction(this.#map)\n ];\n }\n\n destroy() {\n destroyResources(this.#resources);\n }\n}\n\nfunction createDragboxInteraction(\n map: MapModel,\n onSuccess: (geometry: Geometry) => void\n): Resource {\n const olMap = map.olMap;\n const dragbox = new DragBox({\n className: \"selection-drag-box\",\n condition: mouseActionButton\n });\n dragbox.on(\"boxend\", function () {\n onSuccess(dragbox.getGeometry());\n });\n\n olMap.addInteraction(dragbox);\n return {\n destroy() {\n olMap.removeInteraction(dragbox);\n dragbox.dispose();\n }\n };\n}\n\n// For panning using the right mouse button during selection interaction\nfunction createPanningInteraction(map: MapModel): Resource {\n const olMap = map.olMap;\n const rightClick = (mapBrowserEvent: MapBrowserEvent) => {\n const originalEvent = mapBrowserEvent.originalEvent;\n return \"button\" in originalEvent && originalEvent.button === 2;\n };\n const drag = new DragPan({\n condition: rightClick\n });\n\n olMap.addInteraction(drag);\n return {\n destroy() {\n olMap.removeInteraction(drag);\n drag.dispose();\n }\n };\n}\n"],"names":[],"mappings":";;;;AAeO,MAAM,0BAAA,CAA2B;AAAA,EACpC,IAAA;AAAA,EACA,UAAA;AAAA,EAEA,UAAA;AAAA,EAEA,WAAA,CAAY,KAAe,SAAA,EAAyC;AAChE,IAAA,IAAA,CAAK,IAAA,GAAO,GAAA;AACZ,IAAA,IAAA,CAAK,UAAA,GAAa,SAAA;AAElB,IAAA,IAAA,CAAK,UAAA,GAAa;AAAA,MACd,wBAAA,CAAyB,IAAA,CAAK,IAAA,EAAM,IAAA,CAAK,UAAU,CAAA;AAAA,MACnD,wBAAA,CAAyB,KAAK,IAAI;AAAA,KACtC;AAAA,EACJ;AAAA,EAEA,OAAA,GAAU;AACN,IAAA,gBAAA,CAAiB,KAAK,UAAU,CAAA;AAAA,EACpC;AACJ;AAEA,SAAS,wBAAA,CACL,KACA,SAAA,EACQ;AACR,EAAA,MAAM,QAAQ,GAAA,CAAI,KAAA;AAClB,EAAA,MAAM,OAAA,GAAU,IAAI,OAAA,CAAQ;AAAA,IACxB,SAAA,EAAW,oBAAA;AAAA,IACX,SAAA,EAAW;AAAA,GACd,CAAA;AACD,EAAA,OAAA,CAAQ,EAAA,CAAG,UAAU,WAAY;AAC7B,IAAA,SAAA,CAAU,OAAA,CAAQ,aAAa,CAAA;AAAA,EACnC,CAAC,CAAA;AAED,EAAA,KAAA,CAAM,eAAe,OAAO,CAAA;AAC5B,EAAA,OAAO;AAAA,IACH,OAAA,GAAU;AACN,MAAA,KAAA,CAAM,kBAAkB,OAAO,CAAA;AAC/B,MAAA,OAAA,CAAQ,OAAA,EAAQ;AAAA,IACpB;AAAA,GACJ;AACJ;AAGA,SAAS,yBAAyB,GAAA,EAAyB;AACvD,EAAA,MAAM,QAAQ,GAAA,CAAI,KAAA;AAClB,EAAA,MAAM,UAAA,GAAa,CAAC,eAAA,KAAqC;AACrD,IAAA,MAAM,gBAAgB,eAAA,CAAgB,aAAA;AACtC,IAAA,OAAO,QAAA,IAAY,aAAA,IAAiB,aAAA,CAAc,MAAA,KAAW,CAAA;AAAA,EACjE,CAAA;AACA,EAAA,MAAM,IAAA,GAAO,IAAI,OAAA,CAAQ;AAAA,IACrB,SAAA,EAAW;AAAA,GACd,CAAA;AAED,EAAA,KAAA,CAAM,eAAe,IAAI,CAAA;AACzB,EAAA,OAAO;AAAA,IACH,OAAA,GAAU;AACN,MAAA,KAAA,CAAM,kBAAkB,IAAI,CAAA;AAC5B,MAAA,IAAA,CAAK,OAAA,EAAQ;AAAA,IACjB;AAAA,GACJ;AACJ;;"}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { reactive, linked, computed, watchValue, effect } from '@conterra/reactivity-core';
|
|
2
2
|
import { createLogger, shallowEqual, destroyResources, throwAbortError, isAbortError } from '@open-pioneer/core';
|
|
3
|
+
import { TooltipBox } from '@open-pioneer/map-ui-components';
|
|
3
4
|
import { sourceId } from '../_virtual/source-info.js';
|
|
4
5
|
import { createElement } from 'react';
|
|
5
6
|
import { ExtentSelectionInteraction } from '../interactions/ExtentSelectionInteraction.js';
|
|
6
|
-
import { SelectionTooltipContent } from '../ui/SelectionTooltipContent.js';
|
|
7
7
|
|
|
8
8
|
const LOG = createLogger(sourceId);
|
|
9
9
|
const DEFAULT_MAX_RESULTS = 1e4;
|
|
@@ -180,9 +180,13 @@ class SelectionViewModel {
|
|
|
180
180
|
watchValue(
|
|
181
181
|
() => this.ariaMessage,
|
|
182
182
|
(message) => {
|
|
183
|
-
const tooltipContent = createElement(
|
|
184
|
-
|
|
185
|
-
|
|
183
|
+
const tooltipContent = createElement(
|
|
184
|
+
TooltipBox,
|
|
185
|
+
{
|
|
186
|
+
maxW: "none"
|
|
187
|
+
},
|
|
188
|
+
message
|
|
189
|
+
);
|
|
186
190
|
tooltip.setContent(tooltipContent);
|
|
187
191
|
},
|
|
188
192
|
{ immediate: true }
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SelectionViewModel.js","sources":["SelectionViewModel.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2023-2025 Open Pioneer project (https://github.com/open-pioneer)\n// SPDX-License-Identifier: Apache-2.0\n\nimport { computed, effect, linked, reactive, watchValue } from \"@conterra/reactivity-core\";\nimport {\n createLogger,\n destroyResources,\n isAbortError,\n Resource,\n shallowEqual,\n throwAbortError\n} from \"@open-pioneer/core\";\nimport { MapModel, Overlay } from \"@open-pioneer/map\";\nimport { Extent } from \"ol/extent\";\nimport { Geometry } from \"ol/geom\";\nimport { sourceId } from \"open-pioneer:source-info\";\nimport { createElement } from \"react\";\nimport { SelectionResult, SelectionSource, SelectionSourceStatusObject } from \"../api\";\nimport { ExtentSelectionInteraction } from \"../interactions/ExtentSelectionInteraction\";\nimport { SelectionTooltipContent } from \"../ui/SelectionTooltipContent\";\n\nconst LOG = createLogger(sourceId);\n\nconst DEFAULT_MAX_RESULTS = 10000;\n\nconst ACTIVE_INTERACTION_CLASS = \"selection-active\";\nconst INACTIVE_INTERACTION_CLASS = \"selection-inactive\";\n\nexport interface Messages {\n active: string;\n inactive: string;\n noSource: string;\n}\n\n/**\n * Marker for a selection source that has been cleared.\n * The cleared state (when the selected source has been \"lost\") should be sticky, a new source\n * should not be selected automatically.\n */\nconst CLEARED = Symbol(\"cleared\");\n\nexport class SelectionViewModel {\n #map: MapModel;\n #messages: Messages;\n\n /** Limits the number of results from a source. */\n #maxResults: number;\n\n /** Called whenever results were obtained from a source. */\n #onComplete: (source: SelectionSource, results: SelectionResult[]) => void;\n\n /** Called whenever an error happens, to show a notification. */\n #onError: () => void;\n\n /** The set of available selection sources. */\n #sources = reactive<SelectionSource[]>([], { equal: shallowEqual });\n\n /**\n * The currently selected selection source (free choice within this.#sources).\n *\n * The state is linked to the set of sources:\n *\n * - while nothing has been selected yet, the first source is selected automatically\n * - if the current source is removed from the set of sources, the selection source is cleared\n *\n * Once the selection source has been cleared that way, it remains empty until a source is\n * selected explicitly again: later updates of the set of sources must not silently\n * re-enable the selection source behind the user's back.\n */\n #currentSource = linked(\n () => this.#sources.value,\n (\n sources: SelectionSource[],\n previousSource: SelectionSource | typeof CLEARED | undefined\n ): SelectionSource | typeof CLEARED | undefined => {\n if (previousSource === CLEARED) {\n return CLEARED;\n }\n if (previousSource) {\n return sources.includes(previousSource) ? previousSource : CLEARED;\n }\n return sources[0];\n }\n );\n\n #interactionActive = computed(() => {\n const source = this.currentSource;\n return !!source && getSourceStatus(source).kind === \"available\";\n });\n\n #ariaMessage = computed(() => {\n const messages = this.#messages;\n if (!this.currentSource) {\n return messages.noSource;\n }\n if (!this.isInteractionActive) {\n return messages.inactive;\n }\n return messages.active;\n });\n\n // For debugging\n // oxlint-disable-next-line no-unused-private-class-members\n #currentInteraction: ExtentSelectionInteraction | undefined;\n\n // For debugging\n // oxlint-disable-next-line no-unused-private-class-members\n #tooltip: Overlay | undefined;\n\n /** The abort controller of the selection request that is currently running (if any). */\n #currentAbortController: AbortController | undefined;\n\n /** Resources owned by this instance. */\n #resources: Resource[];\n\n constructor(options: {\n map: MapModel;\n messages: Messages;\n onSelectionComplete: (source: SelectionSource, results: SelectionResult[]) => void;\n onError: () => void;\n maxResults?: number;\n }) {\n this.#map = options.map;\n this.#messages = options.messages;\n this.#maxResults = options.maxResults ?? DEFAULT_MAX_RESULTS;\n this.#onComplete = options.onSelectionComplete;\n this.#onError = options.onError;\n this.#resources = [\n this.#initSelectionInteraction(),\n ...this.#initTooltip(),\n ...this.#initViewport()\n ];\n }\n\n destroy() {\n this.#abortPendingSelection();\n destroyResources(this.#resources);\n }\n\n get sources(): SelectionSource[] {\n return this.#sources.value;\n }\n\n set sources(newSources: SelectionSource[]) {\n this.#sources.value = newSources;\n }\n\n get currentSource(): SelectionSource | undefined {\n const source = this.#currentSource.value;\n return source === CLEARED ? undefined : source;\n }\n\n set currentSource(source: SelectionSource | undefined) {\n const sources = this.#sources.value;\n if (sources.length > 0) {\n if (!source) {\n throw new Error(\n \"Internal error: cannot select 'undefined' if there are sources present.\"\n );\n }\n if (!sources.includes(source)) {\n throw new Error(\"Internal error: cannot select unknown selection source.\");\n }\n this.#currentSource.value = source;\n } else {\n if (source) {\n throw new Error(\n \"Internal error: can only select 'undefined' if there are no sources present.\"\n );\n }\n // No source can be selected; the current state is already empty.\n }\n }\n\n /** Returns true if the selection interaction is currently active. */\n get isInteractionActive(): boolean {\n return this.#interactionActive.value;\n }\n\n /** Aria message to represent the current state. Also serves as the tooltip text. */\n get ariaMessage(): string {\n return this.#ariaMessage.value;\n }\n\n /** Runs the selection interaction while active. */\n #initSelectionInteraction(): Resource {\n return watchValue(\n () => this.isInteractionActive,\n (isActive) => {\n if (!isActive) {\n return;\n }\n\n const selection = (this.#currentInteraction = new ExtentSelectionInteraction(\n this.#map,\n (geometry) => this.#onGeometrySelected(geometry)\n ));\n return () => {\n selection.destroy();\n this.#abortPendingSelection();\n };\n },\n {\n immediate: true\n }\n );\n }\n\n /**\n * Disables the viewport's context menu\n * and marks the viewport with css classes when selection interaction is active or inactive.\n */\n #initViewport(): Resource[] {\n const viewport = this.#map.olMap.getViewport();\n const disableContextMenu = (e: MouseEvent) => {\n e.preventDefault();\n return false;\n };\n viewport.addEventListener(\"contextmenu\", disableContextMenu);\n\n return [\n {\n destroy() {\n viewport.removeEventListener(\"contextmenu\", disableContextMenu);\n }\n },\n effect(() => {\n const active = this.isInteractionActive;\n const className = active ? ACTIVE_INTERACTION_CLASS : INACTIVE_INTERACTION_CLASS;\n viewport.classList.add(className);\n return () => viewport.classList.remove(className);\n })\n ];\n }\n\n /**\n * Creates a tooltip that follows the cursor and updates the message depending on the current state.\n */\n #initTooltip(): Resource[] {\n const tooltip = (this.#tooltip = createHelpTooltip(this.#map));\n return [\n tooltip,\n watchValue(\n () => this.ariaMessage,\n (message) => {\n // Aria message doubles as tooltip text at this time\n const tooltipContent = createElement(SelectionTooltipContent, {\n content: message\n });\n tooltip.setContent(tooltipContent);\n },\n { immediate: true }\n )\n ];\n }\n\n /**\n * Called after a successful selection interaction on the map.\n * Triggers search on the currently selected selection source.\n */\n async #onGeometrySelected(geometry: Geometry) {\n const source = this.currentSource;\n if (!source) {\n return;\n }\n\n // Only the most recent selection is of interest; cancel the previous one (if any).\n this.#abortPendingSelection();\n\n const abortController = (this.#currentAbortController = new AbortController());\n try {\n LOG.debug(`Starting selection on source '${source.label}'`);\n\n const extent = geometry.getExtent();\n const results = await this.#selectFromSource(source, extent, abortController.signal);\n if (abortController.signal.aborted) {\n // Superseded by another selection, or the widget is gone.\n throwAbortError();\n }\n\n LOG.debug(`Found ${results.length} results on source '${source.label}'`);\n this.#onComplete(source, results);\n } catch (e) {\n if (!isAbortError(e)) {\n LOG.error(`selection from source ${source.label} failed`, e);\n if (!abortController.signal.aborted) {\n this.#onError();\n }\n }\n } finally {\n if (this.#currentAbortController === abortController) {\n this.#currentAbortController = undefined;\n }\n }\n }\n\n async #selectFromSource(source: SelectionSource, extent: Extent, signal: AbortSignal) {\n const map = this.#map;\n const maxResults = this.#maxResults;\n let results = await source.select(\n { type: \"extent\", extent },\n {\n maxResults,\n map: map,\n mapProjection: map.projection,\n signal\n }\n );\n if (results.length > maxResults) {\n results = results.slice(0, maxResults);\n }\n return results;\n }\n\n /** Cancels the current selection request (if any); its results will be ignored. */\n #abortPendingSelection(): void {\n this.#currentAbortController?.abort();\n this.#currentAbortController = undefined;\n }\n}\n\n/**\n * Normalizes the source's status into an object.\n */\nexport function getSourceStatus(source: SelectionSource): SelectionSourceStatusObject {\n const status = source.status;\n if (status == null) {\n return { kind: \"available\" };\n }\n if (typeof status == \"string\") {\n return { kind: status };\n }\n return status;\n}\n\nfunction createHelpTooltip(map: MapModel): Overlay {\n const overlay = map.overlays.add({\n position: \"follow-pointer\",\n offset: [15, 0],\n positioning: \"center-left\",\n ariaRole: \"tooltip\",\n className: \"selection-tooltip printing-hide\"\n });\n return overlay;\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"SelectionViewModel.js","sources":["SelectionViewModel.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2023-2025 Open Pioneer project (https://github.com/open-pioneer)\n// SPDX-License-Identifier: Apache-2.0\n\nimport { computed, effect, linked, reactive, watchValue } from \"@conterra/reactivity-core\";\nimport {\n createLogger,\n destroyResources,\n isAbortError,\n Resource,\n shallowEqual,\n throwAbortError\n} from \"@open-pioneer/core\";\nimport { MapModel, Overlay } from \"@open-pioneer/map\";\nimport { TooltipBox } from \"@open-pioneer/map-ui-components\";\nimport { Extent } from \"ol/extent\";\nimport { Geometry } from \"ol/geom\";\nimport { sourceId } from \"open-pioneer:source-info\";\nimport { createElement } from \"react\";\nimport { SelectionResult, SelectionSource, SelectionSourceStatusObject } from \"../api\";\nimport { ExtentSelectionInteraction } from \"../interactions/ExtentSelectionInteraction\";\n\nconst LOG = createLogger(sourceId);\n\nconst DEFAULT_MAX_RESULTS = 10000;\n\nconst ACTIVE_INTERACTION_CLASS = \"selection-active\";\nconst INACTIVE_INTERACTION_CLASS = \"selection-inactive\";\n\nexport interface Messages {\n active: string;\n inactive: string;\n noSource: string;\n}\n\n/**\n * Marker for a selection source that has been cleared.\n * The cleared state (when the selected source has been \"lost\") should be sticky, a new source\n * should not be selected automatically.\n */\nconst CLEARED = Symbol(\"cleared\");\n\nexport class SelectionViewModel {\n #map: MapModel;\n #messages: Messages;\n\n /** Limits the number of results from a source. */\n #maxResults: number;\n\n /** Called whenever results were obtained from a source. */\n #onComplete: (source: SelectionSource, results: SelectionResult[]) => void;\n\n /** Called whenever an error happens, to show a notification. */\n #onError: () => void;\n\n /** The set of available selection sources. */\n #sources = reactive<SelectionSource[]>([], { equal: shallowEqual });\n\n /**\n * The currently selected selection source (free choice within this.#sources).\n *\n * The state is linked to the set of sources:\n *\n * - while nothing has been selected yet, the first source is selected automatically\n * - if the current source is removed from the set of sources, the selection source is cleared\n *\n * Once the selection source has been cleared that way, it remains empty until a source is\n * selected explicitly again: later updates of the set of sources must not silently\n * re-enable the selection source behind the user's back.\n */\n #currentSource = linked(\n () => this.#sources.value,\n (\n sources: SelectionSource[],\n previousSource: SelectionSource | typeof CLEARED | undefined\n ): SelectionSource | typeof CLEARED | undefined => {\n if (previousSource === CLEARED) {\n return CLEARED;\n }\n if (previousSource) {\n return sources.includes(previousSource) ? previousSource : CLEARED;\n }\n return sources[0];\n }\n );\n\n #interactionActive = computed(() => {\n const source = this.currentSource;\n return !!source && getSourceStatus(source).kind === \"available\";\n });\n\n #ariaMessage = computed(() => {\n const messages = this.#messages;\n if (!this.currentSource) {\n return messages.noSource;\n }\n if (!this.isInteractionActive) {\n return messages.inactive;\n }\n return messages.active;\n });\n\n // For debugging\n // oxlint-disable-next-line no-unused-private-class-members\n #currentInteraction: ExtentSelectionInteraction | undefined;\n\n // For debugging\n // oxlint-disable-next-line no-unused-private-class-members\n #tooltip: Overlay | undefined;\n\n /** The abort controller of the selection request that is currently running (if any). */\n #currentAbortController: AbortController | undefined;\n\n /** Resources owned by this instance. */\n #resources: Resource[];\n\n constructor(options: {\n map: MapModel;\n messages: Messages;\n onSelectionComplete: (source: SelectionSource, results: SelectionResult[]) => void;\n onError: () => void;\n maxResults?: number;\n }) {\n this.#map = options.map;\n this.#messages = options.messages;\n this.#maxResults = options.maxResults ?? DEFAULT_MAX_RESULTS;\n this.#onComplete = options.onSelectionComplete;\n this.#onError = options.onError;\n this.#resources = [\n this.#initSelectionInteraction(),\n ...this.#initTooltip(),\n ...this.#initViewport()\n ];\n }\n\n destroy() {\n this.#abortPendingSelection();\n destroyResources(this.#resources);\n }\n\n get sources(): SelectionSource[] {\n return this.#sources.value;\n }\n\n set sources(newSources: SelectionSource[]) {\n this.#sources.value = newSources;\n }\n\n get currentSource(): SelectionSource | undefined {\n const source = this.#currentSource.value;\n return source === CLEARED ? undefined : source;\n }\n\n set currentSource(source: SelectionSource | undefined) {\n const sources = this.#sources.value;\n if (sources.length > 0) {\n if (!source) {\n throw new Error(\n \"Internal error: cannot select 'undefined' if there are sources present.\"\n );\n }\n if (!sources.includes(source)) {\n throw new Error(\"Internal error: cannot select unknown selection source.\");\n }\n this.#currentSource.value = source;\n } else {\n if (source) {\n throw new Error(\n \"Internal error: can only select 'undefined' if there are no sources present.\"\n );\n }\n // No source can be selected; the current state is already empty.\n }\n }\n\n /** Returns true if the selection interaction is currently active. */\n get isInteractionActive(): boolean {\n return this.#interactionActive.value;\n }\n\n /** Aria message to represent the current state. Also serves as the tooltip text. */\n get ariaMessage(): string {\n return this.#ariaMessage.value;\n }\n\n /** Runs the selection interaction while active. */\n #initSelectionInteraction(): Resource {\n return watchValue(\n () => this.isInteractionActive,\n (isActive) => {\n if (!isActive) {\n return;\n }\n\n const selection = (this.#currentInteraction = new ExtentSelectionInteraction(\n this.#map,\n (geometry) => this.#onGeometrySelected(geometry)\n ));\n return () => {\n selection.destroy();\n this.#abortPendingSelection();\n };\n },\n {\n immediate: true\n }\n );\n }\n\n /**\n * Disables the viewport's context menu\n * and marks the viewport with css classes when selection interaction is active or inactive.\n */\n #initViewport(): Resource[] {\n const viewport = this.#map.olMap.getViewport();\n const disableContextMenu = (e: MouseEvent) => {\n e.preventDefault();\n return false;\n };\n viewport.addEventListener(\"contextmenu\", disableContextMenu);\n\n return [\n {\n destroy() {\n viewport.removeEventListener(\"contextmenu\", disableContextMenu);\n }\n },\n effect(() => {\n const active = this.isInteractionActive;\n const className = active ? ACTIVE_INTERACTION_CLASS : INACTIVE_INTERACTION_CLASS;\n viewport.classList.add(className);\n return () => viewport.classList.remove(className);\n })\n ];\n }\n\n /**\n * Creates a tooltip that follows the cursor and updates the message depending on the current state.\n */\n #initTooltip(): Resource[] {\n const tooltip = (this.#tooltip = createHelpTooltip(this.#map));\n return [\n tooltip,\n watchValue(\n () => this.ariaMessage,\n (message) => {\n // Aria message doubles as tooltip text at this time\n const tooltipContent = createElement(\n TooltipBox,\n {\n maxW: \"none\"\n },\n message\n );\n tooltip.setContent(tooltipContent);\n },\n { immediate: true }\n )\n ];\n }\n\n /**\n * Called after a successful selection interaction on the map.\n * Triggers search on the currently selected selection source.\n */\n async #onGeometrySelected(geometry: Geometry) {\n const source = this.currentSource;\n if (!source) {\n return;\n }\n\n // Only the most recent selection is of interest; cancel the previous one (if any).\n this.#abortPendingSelection();\n\n const abortController = (this.#currentAbortController = new AbortController());\n try {\n LOG.debug(`Starting selection on source '${source.label}'`);\n\n const extent = geometry.getExtent();\n const results = await this.#selectFromSource(source, extent, abortController.signal);\n if (abortController.signal.aborted) {\n // Superseded by another selection, or the widget is gone.\n throwAbortError();\n }\n\n LOG.debug(`Found ${results.length} results on source '${source.label}'`);\n this.#onComplete(source, results);\n } catch (e) {\n if (!isAbortError(e)) {\n LOG.error(`selection from source ${source.label} failed`, e);\n if (!abortController.signal.aborted) {\n this.#onError();\n }\n }\n } finally {\n if (this.#currentAbortController === abortController) {\n this.#currentAbortController = undefined;\n }\n }\n }\n\n async #selectFromSource(source: SelectionSource, extent: Extent, signal: AbortSignal) {\n const map = this.#map;\n const maxResults = this.#maxResults;\n let results = await source.select(\n { type: \"extent\", extent },\n {\n maxResults,\n map: map,\n mapProjection: map.projection,\n signal\n }\n );\n if (results.length > maxResults) {\n results = results.slice(0, maxResults);\n }\n return results;\n }\n\n /** Cancels the current selection request (if any); its results will be ignored. */\n #abortPendingSelection(): void {\n this.#currentAbortController?.abort();\n this.#currentAbortController = undefined;\n }\n}\n\n/**\n * Normalizes the source's status into an object.\n */\nexport function getSourceStatus(source: SelectionSource): SelectionSourceStatusObject {\n const status = source.status;\n if (status == null) {\n return { kind: \"available\" };\n }\n if (typeof status == \"string\") {\n return { kind: status };\n }\n return status;\n}\n\nfunction createHelpTooltip(map: MapModel): Overlay {\n const overlay = map.overlays.add({\n position: \"follow-pointer\",\n offset: [15, 0],\n positioning: \"center-left\",\n ariaRole: \"tooltip\",\n className: \"selection-tooltip printing-hide\"\n });\n return overlay;\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SelectionViewModelFactory.js","sources":["SelectionViewModelFactory.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2023-2025 Open Pioneer project (https://github.com/open-pioneer)\n// SPDX-License-Identifier: Apache-2.0\n\nimport { ReadonlyReactive } from \"@conterra/reactivity-core\";\nimport { MapModel } from \"@open-pioneer/map\";\nimport { NotificationService } from \"@open-pioneer/notifier\";\nimport { FormattedMessage } from \"@open-pioneer/react-utils\";\nimport { DECLARE_SERVICE_INTERFACE, PackageIntl, ServiceOptions } from \"@open-pioneer/runtime\";\nimport { createElement } from \"react\";\nimport { SelectionResult, SelectionSource } from \"../api\";\nimport { Messages, SelectionViewModel } from \"./SelectionViewModel\";\n\ninterface References {\n notifier: NotificationService;\n}\n\n/**\n * @internal\n */\nexport class SelectionViewModelFactory {\n declare [DECLARE_SERVICE_INTERFACE]: \"selection.ViewModelFactory\";\n\n #notifier: NotificationService;\n #currentIntl: ReadonlyReactive<PackageIntl>;\n #messages: Messages;\n\n constructor({ references, currentIntl }: ServiceOptions<References>) {\n this.#notifier = references.notifier;\n this.#currentIntl = currentIntl;\n this.#messages = {\n get active() {\n return currentIntl.value.formatMessage({ id: \"tooltip\" });\n },\n get inactive() {\n return currentIntl.value.formatMessage({ id: \"disabledTooltip\" });\n },\n get noSource() {\n return currentIntl.value.formatMessage({ id: \"noSourceTooltip\" });\n }\n };\n }\n\n createViewModel(options: {\n map: MapModel;\n onSelectionComplete: (source: SelectionSource, results: SelectionResult[]) => void;\n }): SelectionViewModel {\n return new SelectionViewModel({\n map: options.map,\n messages: this.#messages,\n onSelectionComplete: options.onSelectionComplete,\n onError: () => {\n this.#notifier.notify({\n level: \"error\",\n message: createElement(FormattedMessage, {\n intl: this.#currentIntl,\n id: \"selectionFailed\"\n })\n });\n }\n });\n }\n}\n"],"names":[],"mappings":";;;;AAmBO,MAAM,yBAAA,CAA0B;AAAA,EAGnC,SAAA;AAAA,EACA,YAAA;AAAA,EACA,SAAA;AAAA,EAEA,WAAA,CAAY,EAAE,UAAA,EAAY,WAAA,EAAY,EAA+B;AACjE,IAAA,IAAA,CAAK,YAAY,UAAA,CAAW,QAAA;AAC5B,IAAA,IAAA,CAAK,YAAA,GAAe,WAAA;AACpB,IAAA,IAAA,CAAK,SAAA,GAAY;AAAA,MACb,IAAI,MAAA,GAAS;AACT,QAAA,OAAO,YAAY,KAAA,CAAM,aAAA,CAAc,EAAE,EAAA,EAAI,WAAW,CAAA;AAAA,MAC5D,CAAA;AAAA,MACA,IAAI,QAAA,GAAW;AACX,QAAA,OAAO,YAAY,KAAA,CAAM,aAAA,CAAc,EAAE,EAAA,EAAI,mBAAmB,CAAA;AAAA,MACpE,CAAA;AAAA,MACA,IAAI,QAAA,GAAW;AACX,QAAA,OAAO,YAAY,KAAA,CAAM,aAAA,CAAc,EAAE,EAAA,EAAI,mBAAmB,CAAA;AAAA,MACpE;AAAA,KACJ;AAAA,EACJ;AAAA,EAEA,gBAAgB,OAAA,EAGO;AACnB,IAAA,OAAO,IAAI,kBAAA,CAAmB;AAAA,MAC1B,KAAK,OAAA,CAAQ,GAAA;AAAA,MACb,UAAU,IAAA,CAAK,SAAA;AAAA,MACf,qBAAqB,OAAA,CAAQ,mBAAA;AAAA,MAC7B,SAAS,MAAM;AACX,QAAA,IAAA,CAAK,UAAU,MAAA,CAAO;AAAA,UAClB,KAAA,EAAO,OAAA;AAAA,UACP,OAAA,EAAS,cAAc,gBAAA,EAAkB;AAAA,YACrC,MAAM,IAAA,CAAK,YAAA;AAAA,YACX,EAAA,EAAI;AAAA,WACP;AAAA,SACJ,CAAA;AAAA,MACL;AAAA,KACH,CAAA;AAAA,EACL;AACJ
|
|
1
|
+
{"version":3,"file":"SelectionViewModelFactory.js","sources":["SelectionViewModelFactory.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2023-2025 Open Pioneer project (https://github.com/open-pioneer)\n// SPDX-License-Identifier: Apache-2.0\n\nimport { ReadonlyReactive } from \"@conterra/reactivity-core\";\nimport { MapModel } from \"@open-pioneer/map\";\nimport { NotificationService } from \"@open-pioneer/notifier\";\nimport { FormattedMessage } from \"@open-pioneer/react-utils\";\nimport { DECLARE_SERVICE_INTERFACE, PackageIntl, ServiceOptions } from \"@open-pioneer/runtime\";\nimport { createElement } from \"react\";\nimport { SelectionResult, SelectionSource } from \"../api\";\nimport { Messages, SelectionViewModel } from \"./SelectionViewModel\";\n\ninterface References {\n notifier: NotificationService;\n}\n\n/**\n * @internal\n */\nexport class SelectionViewModelFactory {\n declare [DECLARE_SERVICE_INTERFACE]: \"selection.ViewModelFactory\";\n\n #notifier: NotificationService;\n #currentIntl: ReadonlyReactive<PackageIntl>;\n #messages: Messages;\n\n constructor({ references, currentIntl }: ServiceOptions<References>) {\n this.#notifier = references.notifier;\n this.#currentIntl = currentIntl;\n this.#messages = {\n get active() {\n return currentIntl.value.formatMessage({ id: \"tooltip\" });\n },\n get inactive() {\n return currentIntl.value.formatMessage({ id: \"disabledTooltip\" });\n },\n get noSource() {\n return currentIntl.value.formatMessage({ id: \"noSourceTooltip\" });\n }\n };\n }\n\n createViewModel(options: {\n map: MapModel;\n onSelectionComplete: (source: SelectionSource, results: SelectionResult[]) => void;\n }): SelectionViewModel {\n return new SelectionViewModel({\n map: options.map,\n messages: this.#messages,\n onSelectionComplete: options.onSelectionComplete,\n onError: () => {\n this.#notifier.notify({\n level: \"error\",\n message: createElement(FormattedMessage, {\n intl: this.#currentIntl,\n id: \"selectionFailed\"\n })\n });\n }\n });\n }\n}\n"],"names":[],"mappings":";;;;AAmBO,MAAM,yBAAA,CAA0B;AAAA,EAGnC,SAAA;AAAA,EACA,YAAA;AAAA,EACA,SAAA;AAAA,EAEA,WAAA,CAAY,EAAE,UAAA,EAAY,WAAA,EAAY,EAA+B;AACjE,IAAA,IAAA,CAAK,YAAY,UAAA,CAAW,QAAA;AAC5B,IAAA,IAAA,CAAK,YAAA,GAAe,WAAA;AACpB,IAAA,IAAA,CAAK,SAAA,GAAY;AAAA,MACb,IAAI,MAAA,GAAS;AACT,QAAA,OAAO,YAAY,KAAA,CAAM,aAAA,CAAc,EAAE,EAAA,EAAI,WAAW,CAAA;AAAA,MAC5D,CAAA;AAAA,MACA,IAAI,QAAA,GAAW;AACX,QAAA,OAAO,YAAY,KAAA,CAAM,aAAA,CAAc,EAAE,EAAA,EAAI,mBAAmB,CAAA;AAAA,MACpE,CAAA;AAAA,MACA,IAAI,QAAA,GAAW;AACX,QAAA,OAAO,YAAY,KAAA,CAAM,aAAA,CAAc,EAAE,EAAA,EAAI,mBAAmB,CAAA;AAAA,MACpE;AAAA,KACJ;AAAA,EACJ;AAAA,EAEA,gBAAgB,OAAA,EAGO;AACnB,IAAA,OAAO,IAAI,kBAAA,CAAmB;AAAA,MAC1B,KAAK,OAAA,CAAQ,GAAA;AAAA,MACb,UAAU,IAAA,CAAK,SAAA;AAAA,MACf,qBAAqB,OAAA,CAAQ,mBAAA;AAAA,MAC7B,SAAS,MAAM;AACX,QAAA,IAAA,CAAK,UAAU,MAAA,CAAO;AAAA,UAClB,KAAA,EAAO,OAAA;AAAA,UACP,OAAA,EAAS,cAAc,gBAAA,EAAkB;AAAA,YACrC,MAAM,IAAA,CAAK,YAAA;AAAA,YACX,EAAA,EAAI;AAAA,WACP;AAAA,SACJ,CAAA;AAAA,MACL;AAAA,KACH,CAAA;AAAA,EACL;AACJ;;"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"type": "module",
|
|
3
3
|
"name": "@open-pioneer/selection",
|
|
4
|
-
"version": "1.5.0
|
|
4
|
+
"version": "1.5.0",
|
|
5
5
|
"description": "This package provides a UI component to perform a selection on given selection sources from the map.",
|
|
6
6
|
"keywords": [
|
|
7
7
|
"open-pioneer-trails"
|
|
@@ -16,15 +16,16 @@
|
|
|
16
16
|
"dependencies": {
|
|
17
17
|
"@chakra-ui/react": "^3.37.0",
|
|
18
18
|
"@conterra/reactivity-core": "^0.8.8",
|
|
19
|
-
"@open-pioneer/chakra-snippets": "4.8.0
|
|
20
|
-
"@open-pioneer/core": "4.8.0
|
|
21
|
-
"@open-pioneer/map": "1.5.0
|
|
22
|
-
"@open-pioneer/
|
|
23
|
-
"@open-pioneer/
|
|
24
|
-
"@open-pioneer/
|
|
25
|
-
"@open-pioneer/
|
|
19
|
+
"@open-pioneer/chakra-snippets": "^4.8.0",
|
|
20
|
+
"@open-pioneer/core": "^4.8.0",
|
|
21
|
+
"@open-pioneer/map": "1.5.0",
|
|
22
|
+
"@open-pioneer/map-ui-components": "1.5.0",
|
|
23
|
+
"@open-pioneer/notifier": "^4.8.0",
|
|
24
|
+
"@open-pioneer/react-utils": "^4.8.0",
|
|
25
|
+
"@open-pioneer/reactivity": "^4.8.0",
|
|
26
|
+
"@open-pioneer/runtime": "^4.8.0",
|
|
26
27
|
"ol": "^10.10.0",
|
|
27
|
-
"react": "^19.
|
|
28
|
+
"react": "^19.3.0",
|
|
28
29
|
"react-icons": "^5.7.0",
|
|
29
30
|
"uuid": "^14.0.2"
|
|
30
31
|
},
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"VectorSelectionSource.js","sources":["VectorSelectionSource.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2023-2025 Open Pioneer project (https://github.com/open-pioneer)\n// SPDX-License-Identifier: Apache-2.0\n\nimport { computed, ReadonlyReactive, synchronized } from \"@conterra/reactivity-core\";\nimport { PackageIntl } from \"@open-pioneer/runtime\";\nimport Feature from \"ol/Feature\";\nimport VectorLayer from \"ol/layer/Vector\";\nimport { unByKey } from \"ol/Observable\";\nimport VectorSource from \"ol/source/Vector\";\nimport { v4 as uuid4v } from \"uuid\";\nimport {\n SelectionKind,\n SelectionOptions,\n SelectionResult,\n SelectionSourceStatusObject,\n VectorLayerSelectionSource\n} from \"../api\";\n\n/**\n * A SelectionSource to use an OpenLayers VectorLayer with an OpenLayers VectorSource (e.g. layer of the map).\n */\nexport class VectorLayerSelectionSourceImpl implements VectorLayerSelectionSource {\n readonly id: string | undefined;\n readonly label: string;\n #vectorLayer: VectorLayer<VectorSource, Feature>;\n #currentIntl: ReadonlyReactive<PackageIntl>;\n #layerVisible: ReadonlyReactive<boolean>;\n #status: ReadonlyReactive<SelectionSourceStatusObject>;\n\n constructor(\n id: string | undefined,\n vectorLayer: VectorLayer<VectorSource, Feature>,\n label: string,\n currentIntl: ReadonlyReactive<PackageIntl>\n ) {\n this.id = id;\n this.label = label;\n this.#vectorLayer = vectorLayer;\n this.#currentIntl = currentIntl;\n this.#layerVisible = synchronized(\n () => vectorLayer.getVisible(),\n (cb) => {\n const key = vectorLayer.on(\"change:visible\", cb);\n return () => unByKey(key);\n }\n );\n this.#status = computed<SelectionSourceStatusObject>(() =>\n this.#layerVisible.value\n ? { kind: \"available\" }\n : {\n kind: \"unavailable\",\n reason: this.#currentIntl.value.formatMessage({ id: \"layerNotVisibleReason\" })\n }\n );\n }\n\n destroy() {}\n\n get status() {\n return this.#status.value;\n }\n\n async select(\n selectionKind: SelectionKind,\n options: SelectionOptions\n ): Promise<SelectionResult[]> {\n if (selectionKind.type !== \"extent\") {\n throw new Error(`Unsupported selection kind: ${selectionKind.type}`);\n }\n\n if (this.#status.value.kind !== \"available\" || this.#vectorLayer.getSource() === null)\n return [];\n\n const allResults: SelectionResult[] = [];\n // oxlint-disable-next-line @typescript-eslint/no-non-null-assertion\n this.#vectorLayer\n .getSource()!\n .forEachFeatureIntersectingExtent(selectionKind.extent, (feature) => {\n if (!feature.getGeometry()) return;\n\n // TODO: Think about where to implement Date-Formatting, if the dates are already\n // encoded as Strings...\n\n const filteredProperties = { ...feature.getProperties() };\n delete filteredProperties.geometries;\n\n const result: SelectionResult = {\n id: feature.getId()?.toString() || uuid4v(),\n // oxlint-disable-next-line @typescript-eslint/no-non-null-assertion\n geometry: feature.getGeometry()!,\n properties: filteredProperties\n };\n\n allResults.push(result);\n });\n const selectedFeatures = allResults.filter((s): s is SelectionResult => s != null);\n const limitedFeatures =\n selectedFeatures.length > options.maxResults\n ? selectedFeatures.slice(0, options.maxResults)\n : selectedFeatures;\n return limitedFeatures;\n }\n}\n"],"names":["uuid4v"],"mappings":";;;;AAqBO,MAAM,8BAAA,CAAqE;AAAA,EACrE,EAAA;AAAA,EACA,KAAA;AAAA,EACT,YAAA;AAAA,EACA,YAAA;AAAA,EACA,aAAA;AAAA,EACA,OAAA;AAAA,EAEA,WAAA,CACI,EAAA,EACA,WAAA,EACA,KAAA,EACA,WAAA,EACF;AACE,IAAA,IAAA,CAAK,EAAA,GAAK,EAAA;AACV,IAAA,IAAA,CAAK,KAAA,GAAQ,KAAA;AACb,IAAA,IAAA,CAAK,YAAA,GAAe,WAAA;AACpB,IAAA,IAAA,CAAK,YAAA,GAAe,WAAA;AACpB,IAAA,IAAA,CAAK,aAAA,GAAgB,YAAA;AAAA,MACjB,MAAM,YAAY,UAAA,EAAW;AAAA,MAC7B,CAAC,EAAA,KAAO;AACJ,QAAA,MAAM,GAAA,GAAM,WAAA,CAAY,EAAA,CAAG,gBAAA,EAAkB,EAAE,CAAA;AAC/C,QAAA,OAAO,MAAM,QAAQ,GAAG,CAAA;AAAA,MAC5B;AAAA,KACJ;AACA,IAAA,IAAA,CAAK,OAAA,GAAU,QAAA;AAAA,MAAsC,MACjD,IAAA,CAAK,aAAA,CAAc,QACb,EAAE,IAAA,EAAM,aAAY,GACpB;AAAA,QACI,IAAA,EAAM,aAAA;AAAA,QACN,MAAA,EAAQ,KAAK,YAAA,CAAa,KAAA,CAAM,cAAc,EAAE,EAAA,EAAI,yBAAyB;AAAA;AACjF,KACV;AAAA,EACJ;AAAA,EAEA,OAAA,GAAU;AAAA,EAAC;AAAA,EAEX,IAAI,MAAA,GAAS;AACT,IAAA,OAAO,KAAK,OAAA,CAAQ,KAAA;AAAA,EACxB;AAAA,EAEA,MAAM,MAAA,CACF,aAAA,EACA,OAAA,EAC0B;AAC1B,IAAA,IAAI,aAAA,CAAc,SAAS,QAAA,EAAU;AACjC,MAAA,MAAM,IAAI,KAAA,CAAM,CAAA,4BAAA,EAA+B,aAAA,CAAc,IAAI,CAAA,CAAE,CAAA;AAAA,IACvE;AAEA,IAAA,IAAI,IAAA,CAAK,QAAQ,KAAA,CAAM,IAAA,KAAS,eAAe,IAAA,CAAK,YAAA,CAAa,WAAU,KAAM,IAAA;AAC7E,MAAA,OAAO,EAAC;AAEZ,IAAA,MAAM,aAAgC,EAAC;AAEvC,IAAA,IAAA,CAAK,aACA,SAAA,EAAU,CACV,iCAAiC,aAAA,CAAc,MAAA,EAAQ,CAAC,OAAA,KAAY;AACjE,MAAA,IAAI,CAAC,OAAA,CAAQ,WAAA,EAAY,EAAG;AAK5B,MAAA,MAAM,kBAAA,GAAqB,EAAE,GAAG,OAAA,CAAQ,eAAc,EAAE;AACxD,MAAA,OAAO,kBAAA,CAAmB,UAAA;AAE1B,MAAA,MAAM,MAAA,GAA0B;AAAA,QAC5B,IAAI,OAAA,CAAQ,KAAA,EAAM,EAAG,QAAA,MAAcA,EAAA,EAAO;AAAA;AAAA,QAE1C,QAAA,EAAU,QAAQ,WAAA,EAAY;AAAA,QAC9B,UAAA,EAAY;AAAA,OAChB;AAEA,MAAA,UAAA,CAAW,KAAK,MAAM,CAAA;AAAA,IAC1B,CAAC,CAAA;AACL,IAAA,MAAM,mBAAmB,UAAA,CAAW,MAAA,CAAO,CAAC,CAAA,KAA4B,KAAK,IAAI,CAAA;AACjF,IAAA,MAAM,eAAA,GACF,gBAAA,CAAiB,MAAA,GAAS,OAAA,CAAQ,UAAA,GAC5B,iBAAiB,KAAA,CAAM,CAAA,EAAG,OAAA,CAAQ,UAAU,CAAA,GAC5C,gBAAA;AACV,IAAA,OAAO,eAAA;AAAA,EACX;AACJ
|
|
1
|
+
{"version":3,"file":"VectorSelectionSource.js","sources":["VectorSelectionSource.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2023-2025 Open Pioneer project (https://github.com/open-pioneer)\n// SPDX-License-Identifier: Apache-2.0\n\nimport { computed, ReadonlyReactive, synchronized } from \"@conterra/reactivity-core\";\nimport { PackageIntl } from \"@open-pioneer/runtime\";\nimport Feature from \"ol/Feature\";\nimport VectorLayer from \"ol/layer/Vector\";\nimport { unByKey } from \"ol/Observable\";\nimport VectorSource from \"ol/source/Vector\";\nimport { v4 as uuid4v } from \"uuid\";\nimport {\n SelectionKind,\n SelectionOptions,\n SelectionResult,\n SelectionSourceStatusObject,\n VectorLayerSelectionSource\n} from \"../api\";\n\n/**\n * A SelectionSource to use an OpenLayers VectorLayer with an OpenLayers VectorSource (e.g. layer of the map).\n */\nexport class VectorLayerSelectionSourceImpl implements VectorLayerSelectionSource {\n readonly id: string | undefined;\n readonly label: string;\n #vectorLayer: VectorLayer<VectorSource, Feature>;\n #currentIntl: ReadonlyReactive<PackageIntl>;\n #layerVisible: ReadonlyReactive<boolean>;\n #status: ReadonlyReactive<SelectionSourceStatusObject>;\n\n constructor(\n id: string | undefined,\n vectorLayer: VectorLayer<VectorSource, Feature>,\n label: string,\n currentIntl: ReadonlyReactive<PackageIntl>\n ) {\n this.id = id;\n this.label = label;\n this.#vectorLayer = vectorLayer;\n this.#currentIntl = currentIntl;\n this.#layerVisible = synchronized(\n () => vectorLayer.getVisible(),\n (cb) => {\n const key = vectorLayer.on(\"change:visible\", cb);\n return () => unByKey(key);\n }\n );\n this.#status = computed<SelectionSourceStatusObject>(() =>\n this.#layerVisible.value\n ? { kind: \"available\" }\n : {\n kind: \"unavailable\",\n reason: this.#currentIntl.value.formatMessage({ id: \"layerNotVisibleReason\" })\n }\n );\n }\n\n destroy() {}\n\n get status() {\n return this.#status.value;\n }\n\n async select(\n selectionKind: SelectionKind,\n options: SelectionOptions\n ): Promise<SelectionResult[]> {\n if (selectionKind.type !== \"extent\") {\n throw new Error(`Unsupported selection kind: ${selectionKind.type}`);\n }\n\n if (this.#status.value.kind !== \"available\" || this.#vectorLayer.getSource() === null)\n return [];\n\n const allResults: SelectionResult[] = [];\n // oxlint-disable-next-line @typescript-eslint/no-non-null-assertion\n this.#vectorLayer\n .getSource()!\n .forEachFeatureIntersectingExtent(selectionKind.extent, (feature) => {\n if (!feature.getGeometry()) return;\n\n // TODO: Think about where to implement Date-Formatting, if the dates are already\n // encoded as Strings...\n\n const filteredProperties = { ...feature.getProperties() };\n delete filteredProperties.geometries;\n\n const result: SelectionResult = {\n id: feature.getId()?.toString() || uuid4v(),\n // oxlint-disable-next-line @typescript-eslint/no-non-null-assertion\n geometry: feature.getGeometry()!,\n properties: filteredProperties\n };\n\n allResults.push(result);\n });\n const selectedFeatures = allResults.filter((s): s is SelectionResult => s != null);\n const limitedFeatures =\n selectedFeatures.length > options.maxResults\n ? selectedFeatures.slice(0, options.maxResults)\n : selectedFeatures;\n return limitedFeatures;\n }\n}\n"],"names":["uuid4v"],"mappings":";;;;AAqBO,MAAM,8BAAA,CAAqE;AAAA,EACrE,EAAA;AAAA,EACA,KAAA;AAAA,EACT,YAAA;AAAA,EACA,YAAA;AAAA,EACA,aAAA;AAAA,EACA,OAAA;AAAA,EAEA,WAAA,CACI,EAAA,EACA,WAAA,EACA,KAAA,EACA,WAAA,EACF;AACE,IAAA,IAAA,CAAK,EAAA,GAAK,EAAA;AACV,IAAA,IAAA,CAAK,KAAA,GAAQ,KAAA;AACb,IAAA,IAAA,CAAK,YAAA,GAAe,WAAA;AACpB,IAAA,IAAA,CAAK,YAAA,GAAe,WAAA;AACpB,IAAA,IAAA,CAAK,aAAA,GAAgB,YAAA;AAAA,MACjB,MAAM,YAAY,UAAA,EAAW;AAAA,MAC7B,CAAC,EAAA,KAAO;AACJ,QAAA,MAAM,GAAA,GAAM,WAAA,CAAY,EAAA,CAAG,gBAAA,EAAkB,EAAE,CAAA;AAC/C,QAAA,OAAO,MAAM,QAAQ,GAAG,CAAA;AAAA,MAC5B;AAAA,KACJ;AACA,IAAA,IAAA,CAAK,OAAA,GAAU,QAAA;AAAA,MAAsC,MACjD,IAAA,CAAK,aAAA,CAAc,QACb,EAAE,IAAA,EAAM,aAAY,GACpB;AAAA,QACI,IAAA,EAAM,aAAA;AAAA,QACN,MAAA,EAAQ,KAAK,YAAA,CAAa,KAAA,CAAM,cAAc,EAAE,EAAA,EAAI,yBAAyB;AAAA;AACjF,KACV;AAAA,EACJ;AAAA,EAEA,OAAA,GAAU;AAAA,EAAC;AAAA,EAEX,IAAI,MAAA,GAAS;AACT,IAAA,OAAO,KAAK,OAAA,CAAQ,KAAA;AAAA,EACxB;AAAA,EAEA,MAAM,MAAA,CACF,aAAA,EACA,OAAA,EAC0B;AAC1B,IAAA,IAAI,aAAA,CAAc,SAAS,QAAA,EAAU;AACjC,MAAA,MAAM,IAAI,KAAA,CAAM,CAAA,4BAAA,EAA+B,aAAA,CAAc,IAAI,CAAA,CAAE,CAAA;AAAA,IACvE;AAEA,IAAA,IAAI,IAAA,CAAK,QAAQ,KAAA,CAAM,IAAA,KAAS,eAAe,IAAA,CAAK,YAAA,CAAa,WAAU,KAAM,IAAA;AAC7E,MAAA,OAAO,EAAC;AAEZ,IAAA,MAAM,aAAgC,EAAC;AAEvC,IAAA,IAAA,CAAK,aACA,SAAA,EAAU,CACV,iCAAiC,aAAA,CAAc,MAAA,EAAQ,CAAC,OAAA,KAAY;AACjE,MAAA,IAAI,CAAC,OAAA,CAAQ,WAAA,EAAY,EAAG;AAK5B,MAAA,MAAM,kBAAA,GAAqB,EAAE,GAAG,OAAA,CAAQ,eAAc,EAAE;AACxD,MAAA,OAAO,kBAAA,CAAmB,UAAA;AAE1B,MAAA,MAAM,MAAA,GAA0B;AAAA,QAC5B,IAAI,OAAA,CAAQ,KAAA,EAAM,EAAG,QAAA,MAAcA,EAAA,EAAO;AAAA;AAAA,QAE1C,QAAA,EAAU,QAAQ,WAAA,EAAY;AAAA,QAC9B,UAAA,EAAY;AAAA,OAChB;AAEA,MAAA,UAAA,CAAW,KAAK,MAAM,CAAA;AAAA,IAC1B,CAAC,CAAA;AACL,IAAA,MAAM,mBAAmB,UAAA,CAAW,MAAA,CAAO,CAAC,CAAA,KAA4B,KAAK,IAAI,CAAA;AACjF,IAAA,MAAM,eAAA,GACF,gBAAA,CAAiB,MAAA,GAAS,OAAA,CAAQ,UAAA,GAC5B,iBAAiB,KAAA,CAAM,CAAA,EAAG,OAAA,CAAQ,UAAU,CAAA,GAC5C,gBAAA;AACV,IAAA,OAAO,eAAA;AAAA,EACX;AACJ;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"VectorSelectionSourceFactory.js","sources":["VectorSelectionSourceFactory.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2023-2025 Open Pioneer project (https://github.com/open-pioneer)\n// SPDX-License-Identifier: Apache-2.0\n\nimport { ReadonlyReactive } from \"@conterra/reactivity-core\";\nimport { type PackageIntl, ServiceOptions } from \"@open-pioneer/runtime\";\nimport {\n VectorLayerSelectionSource,\n VectorLayerSelectionSourceFactory,\n VectorLayerSelectionSourceOptions\n} from \"../api\";\nimport { VectorLayerSelectionSourceImpl } from \"./VectorSelectionSource\";\n\nexport class VectorSelectionSourceFactory implements VectorLayerSelectionSourceFactory {\n #currentIntl: ReadonlyReactive<PackageIntl>;\n\n constructor({ currentIntl }: ServiceOptions<PackageIntl>) {\n this.#currentIntl = currentIntl;\n }\n\n createSelectionSource(options: VectorLayerSelectionSourceOptions): VectorLayerSelectionSource {\n return new VectorLayerSelectionSourceImpl(\n options.id,\n options.vectorLayer,\n options.label,\n this.#currentIntl\n );\n }\n}\n"],"names":[],"mappings":";;AAYO,MAAM,4BAAA,CAA0E;AAAA,EACnF,YAAA;AAAA,EAEA,WAAA,CAAY,EAAE,WAAA,EAAY,EAAgC;AACtD,IAAA,IAAA,CAAK,YAAA,GAAe,WAAA;AAAA,EACxB;AAAA,EAEA,sBAAsB,OAAA,EAAwE;AAC1F,IAAA,OAAO,IAAI,8BAAA;AAAA,MACP,OAAA,CAAQ,EAAA;AAAA,MACR,OAAA,CAAQ,WAAA;AAAA,MACR,OAAA,CAAQ,KAAA;AAAA,MACR,IAAA,CAAK;AAAA,KACT;AAAA,EACJ;AACJ
|
|
1
|
+
{"version":3,"file":"VectorSelectionSourceFactory.js","sources":["VectorSelectionSourceFactory.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2023-2025 Open Pioneer project (https://github.com/open-pioneer)\n// SPDX-License-Identifier: Apache-2.0\n\nimport { ReadonlyReactive } from \"@conterra/reactivity-core\";\nimport { type PackageIntl, ServiceOptions } from \"@open-pioneer/runtime\";\nimport {\n VectorLayerSelectionSource,\n VectorLayerSelectionSourceFactory,\n VectorLayerSelectionSourceOptions\n} from \"../api\";\nimport { VectorLayerSelectionSourceImpl } from \"./VectorSelectionSource\";\n\nexport class VectorSelectionSourceFactory implements VectorLayerSelectionSourceFactory {\n #currentIntl: ReadonlyReactive<PackageIntl>;\n\n constructor({ currentIntl }: ServiceOptions<PackageIntl>) {\n this.#currentIntl = currentIntl;\n }\n\n createSelectionSource(options: VectorLayerSelectionSourceOptions): VectorLayerSelectionSource {\n return new VectorLayerSelectionSourceImpl(\n options.id,\n options.vectorLayer,\n options.label,\n this.#currentIntl\n );\n }\n}\n"],"names":[],"mappings":";;AAYO,MAAM,4BAAA,CAA0E;AAAA,EACnF,YAAA;AAAA,EAEA,WAAA,CAAY,EAAE,WAAA,EAAY,EAAgC;AACtD,IAAA,IAAA,CAAK,YAAA,GAAe,WAAA;AAAA,EACxB;AAAA,EAEA,sBAAsB,OAAA,EAAwE;AAC1F,IAAA,OAAO,IAAI,8BAAA;AAAA,MACP,OAAA,CAAQ,EAAA;AAAA,MACR,OAAA,CAAQ,WAAA;AAAA,MACR,OAAA,CAAQ,KAAA;AAAA,MACR,IAAA,CAAK;AAAA,KACT;AAAA,EACJ;AACJ;;"}
|
package/ui/Selection.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Selection.js","sources":["Selection.tsx"],"sourcesContent":["// SPDX-FileCopyrightText: 2023-2025 Open Pioneer project (https://github.com/open-pioneer)\n// SPDX-License-Identifier: Apache-2.0\n\nimport { createListCollection, Portal, Select, VStack } from \"@chakra-ui/react\";\nimport { MapModelProps, useMapModelValue } from \"@open-pioneer/map\";\nimport { CommonComponentProps, useCommonComponentProps } from \"@open-pioneer/react-utils\";\nimport { useReactiveSnapshot } from \"@open-pioneer/reactivity\";\nimport { useIntl } from \"open-pioneer:react-hooks\";\nimport { FC, useMemo } from \"react\";\nimport { SelectionResult, SelectionSource } from \"../api\";\nimport { SelectionViewModel } from \"../model\";\nimport { SelectionSourceItem } from \"./SelectionSourceItem\";\nimport { useSelectionSourceId } from \"./useSelectionSourceId\";\nimport { useSelectionViewModel } from \"./useSelectionViewModel\";\nimport { useSourceStatus } from \"./useSourceStatus\";\n\n/**\n * Properties supported by the {@link Selection} component.\n */\nexport interface SelectionProps extends CommonComponentProps, MapModelProps {\n /**\n * Array of selection sources available for spatial selection.\n */\n sources: SelectionSource[];\n\n /**\n * This handler is called whenever the user has successfully selected\n * some items.\n */\n onSelectionComplete?(event: SelectionCompleteEvent): void;\n\n /**\n * This handler is called whenever the user has changed the selected source\n */\n onSelectionSourceChanged?(event: SelectionSourceChangedEvent): void;\n}\n\nexport interface SelectionCompleteEvent {\n /** The source that returned the {@link results}. */\n source: SelectionSource;\n\n /** Results selected by the user. */\n results: SelectionResult[];\n}\n\nexport interface SelectionSourceChangedEvent {\n /** The new selected source */\n source: SelectionSource | undefined;\n}\n\n/**\n * A component that allows the user to perform a spatial selection on a given set of {@link SelectionSource}.\n */\nexport const Selection: FC<SelectionProps> = (props) => {\n const { sources, onSelectionComplete, onSelectionSourceChanged } = props;\n const map = useMapModelValue(props);\n const viewModel = useSelectionViewModel(\n map,\n sources,\n onSelectionComplete,\n onSelectionSourceChanged\n );\n return viewModel && <SelectionReady viewModel={viewModel} {...props} />;\n};\n\nfunction SelectionReady(props: CommonComponentProps & { viewModel: SelectionViewModel }) {\n const { viewModel } = props;\n const { containerProps } = useCommonComponentProps(\"selection\", props);\n const intl = useIntl();\n\n // Subscribe to relevant view model state.\n const sources = useReactiveSnapshot(() => viewModel.sources, [viewModel]);\n const currentSource = useReactiveSnapshot(() => viewModel.currentSource, [viewModel]);\n const ariaMessage = useReactiveSnapshot(() => viewModel.ariaMessage, [viewModel]);\n\n // Translate sources array to a collection for chakra's select control.\n const getSourceId = useSelectionSourceId();\n const sourceOptionsCollection = useMemo(\n () =>\n createListCollection({\n items: sources,\n isItemDisabled: () => {\n return false;\n },\n itemToString: (item) => item.label,\n itemToValue: (item) => getSourceId(item)\n }),\n [sources, getSourceId]\n );\n\n let triggerItem;\n if (currentSource) {\n triggerItem = <SelectionSourceItem source={currentSource} />;\n } else {\n triggerItem = null;\n }\n\n return (\n <VStack {...containerProps} gap={2}>\n <Select.Root\n className=\"selection-source\"\n collection={sourceOptionsCollection}\n value={currentSource ? [getSourceId(currentSource)] : []}\n onValueChange={(details) => {\n const source = details.items[0];\n if (source) {\n viewModel.currentSource = source;\n }\n }}\n lazyMount={true}\n unmountOnExit={true}\n >\n <Select.Label>{intl.formatMessage({ id: \"selectSource\" })}</Select.Label>\n\n <Select.Control>\n <Select.Trigger aria-description={ariaMessage}>\n <Select.ValueText\n placeholder={intl.formatMessage({ id: \"selectionPlaceholder\" })}\n >\n {triggerItem}\n </Select.ValueText>\n </Select.Trigger>\n <Select.IndicatorGroup>\n <Select.Indicator />\n </Select.IndicatorGroup>\n </Select.Control>\n\n <Portal>\n <Select.Positioner>\n <Select.Content className=\"selection-source-options\">\n {sourceOptionsCollection.items.map((item) => (\n <SelectionSourceItemContent source={item} key={getSourceId(item)} />\n ))}\n </Select.Content>\n </Select.Positioner>\n </Portal>\n </Select.Root>\n </VStack>\n );\n}\n\n/**\n * Renders a dropdown item in the menu.\n */\nfunction SelectionSourceItemContent(props: { source: SelectionSource }) {\n const { source } = props;\n const isDisabled = useSourceStatus(source).kind === \"unavailable\";\n return (\n <Select.Item\n className=\"selection-source-option\"\n item={source}\n justifyContent=\"flex-start\"\n // Override pointer-events: none rule for disabled items; we want to show the tooltip on hover\n pointerEvents=\"auto\"\n aria-disabled={isDisabled ? \"true\" : undefined}\n >\n <SelectionSourceItem source={source} />\n </Select.Item>\n );\n}\n"],"names":[],"mappings":";;;;;;;;;;;;AAqDO,MAAM,SAAA,GAAgC,CAAC,KAAA,KAAU;AACpD,EAAA,MAAM,EAAE,OAAA,EAAS,mBAAA,EAAqB,wBAAA,EAAyB,GAAI,KAAA;AACnE,EAAA,MAAM,GAAA,GAAM,iBAAiB,KAAK,CAAA;AAClC,EAAA,MAAM,SAAA,GAAY,qBAAA;AAAA,IACd,GAAA;AAAA,IACA,OAAA;AAAA,IACA,mBAAA;AAAA,IACA;AAAA,GACJ;AACA,EAAA,OAAO,SAAA,oBAAa,GAAA,CAAC,cAAA,EAAA,EAAe,SAAA,EAAuB,GAAG,KAAA,EAAO,CAAA;AACzE;AAEA,SAAS,eAAe,KAAA,EAAiE;AACrF,EAAA,MAAM,EAAE,WAAU,GAAI,KAAA;AACtB,EAAA,MAAM,EAAE,cAAA,EAAe,GAAI,uBAAA,CAAwB,aAAa,KAAK,CAAA;AACrE,EAAA,MAAM,OAAO,OAAA,EAAQ;AAGrB,EAAA,MAAM,UAAU,mBAAA,CAAoB,MAAM,UAAU,OAAA,EAAS,CAAC,SAAS,CAAC,CAAA;AACxE,EAAA,MAAM,gBAAgB,mBAAA,CAAoB,MAAM,UAAU,aAAA,EAAe,CAAC,SAAS,CAAC,CAAA;AACpF,EAAA,MAAM,cAAc,mBAAA,CAAoB,MAAM,UAAU,WAAA,EAAa,CAAC,SAAS,CAAC,CAAA;AAGhF,EAAA,MAAM,cAAc,oBAAA,EAAqB;AACzC,EAAA,MAAM,uBAAA,GAA0B,OAAA;AAAA,IAC5B,MACI,oBAAA,CAAqB;AAAA,MACjB,KAAA,EAAO,OAAA;AAAA,MACP,gBAAgB,MAAM;AAClB,QAAA,OAAO,KAAA;AAAA,MACX,CAAA;AAAA,MACA,YAAA,EAAc,CAAC,IAAA,KAAS,IAAA,CAAK,KAAA;AAAA,MAC7B,WAAA,EAAa,CAAC,IAAA,KAAS,WAAA,CAAY,IAAI;AAAA,KAC1C,CAAA;AAAA,IACL,CAAC,SAAS,WAAW;AAAA,GACzB;AAEA,EAAA,IAAI,WAAA;AACJ,EAAA,IAAI,aAAA,EAAe;AACf,IAAA,WAAA,mBAAc,GAAA,CAAC,mBAAA,EAAA,EAAoB,MAAA,EAAQ,aAAA,EAAe,CAAA;AAAA,EAC9D,CAAA,MAAO;AACH,IAAA,WAAA,GAAc,IAAA;AAAA,EAClB;AAEA,EAAA,uBACI,GAAA,CAAC,MAAA,EAAA,EAAQ,GAAG,cAAA,EAAgB,KAAK,CAAA,EAC7B,QAAA,kBAAA,IAAA;AAAA,IAAC,MAAA,CAAO,IAAA;AAAA,IAAP;AAAA,MACG,SAAA,EAAU,kBAAA;AAAA,MACV,UAAA,EAAY,uBAAA;AAAA,MACZ,OAAO,aAAA,GAAgB,CAAC,YAAY,aAAa,CAAC,IAAI,EAAC;AAAA,MACvD,aAAA,EAAe,CAAC,OAAA,KAAY;AACxB,QAAA,MAAM,MAAA,GAAS,OAAA,CAAQ,KAAA,CAAM,CAAC,CAAA;AAC9B,QAAA,IAAI,MAAA,EAAQ;AACR,UAAA,SAAA,CAAU,aAAA,GAAgB,MAAA;AAAA,QAC9B;AAAA,MACJ,CAAA;AAAA,MACA,SAAA,EAAW,IAAA;AAAA,MACX,aAAA,EAAe,IAAA;AAAA,MAEf,QAAA,EAAA;AAAA,wBAAA,GAAA,CAAC,MAAA,CAAO,OAAP,EAAc,QAAA,EAAA,IAAA,CAAK,cAAc,EAAE,EAAA,EAAI,cAAA,EAAgB,CAAA,EAAE,CAAA;AAAA,wBAE1D,IAAA,CAAC,MAAA,CAAO,OAAA,EAAP,EACG,QAAA,EAAA;AAAA,0BAAA,GAAA,CAAC,MAAA,CAAO,OAAA,EAAP,EAAe,kBAAA,EAAkB,WAAA,EAC9B,QAAA,kBAAA,GAAA;AAAA,YAAC,MAAA,CAAO,SAAA;AAAA,YAAP;AAAA,cACG,aAAa,IAAA,CAAK,aAAA,CAAc,EAAE,EAAA,EAAI,wBAAwB,CAAA;AAAA,cAE7D,QAAA,EAAA;AAAA;AAAA,WACL,EACJ,CAAA;AAAA,0BACA,GAAA,CAAC,OAAO,cAAA,EAAP,EACG,8BAAC,MAAA,CAAO,SAAA,EAAP,EAAiB,CAAA,EACtB;AAAA,SAAA,EACJ,CAAA;AAAA,wBAEA,GAAA,CAAC,MAAA,EAAA,EACG,QAAA,kBAAA,GAAA,CAAC,MAAA,CAAO,UAAA,EAAP,EACG,QAAA,kBAAA,GAAA,CAAC,MAAA,CAAO,OAAA,EAAP,EAAe,SAAA,EAAU,0BAAA,EACrB,QAAA,EAAA,uBAAA,CAAwB,KAAA,CAAM,GAAA,CAAI,CAAC,IAAA,qBAChC,GAAA,CAAC,0BAAA,EAAA,EAA2B,MAAA,EAAQ,IAAA,EAAA,EAAW,WAAA,CAAY,IAAI,CAAG,CACrE,CAAA,EACL,CAAA,EACJ,CAAA,EACJ;AAAA;AAAA;AAAA,GACJ,EACJ,CAAA;AAER;AAKA,SAAS,2BAA2B,KAAA,EAAoC;AACpE,EAAA,MAAM,EAAE,QAAO,GAAI,KAAA;AACnB,EAAA,MAAM,UAAA,GAAa,eAAA,CAAgB,MAAM,CAAA,CAAE,IAAA,KAAS,aAAA;AACpD,EAAA,uBACI,GAAA;AAAA,IAAC,MAAA,CAAO,IAAA;AAAA,IAAP;AAAA,MACG,SAAA,EAAU,yBAAA;AAAA,MACV,IAAA,EAAM,MAAA;AAAA,MACN,cAAA,EAAe,YAAA;AAAA,MAEf,aAAA,EAAc,MAAA;AAAA,MACd,eAAA,EAAe,aAAa,MAAA,GAAS,MAAA;AAAA,MAErC,QAAA,kBAAA,GAAA,CAAC,uBAAoB,MAAA,EAAgB;AAAA;AAAA,GACzC;AAER
|
|
1
|
+
{"version":3,"file":"Selection.js","sources":["Selection.tsx"],"sourcesContent":["// SPDX-FileCopyrightText: 2023-2025 Open Pioneer project (https://github.com/open-pioneer)\n// SPDX-License-Identifier: Apache-2.0\n\nimport { createListCollection, Portal, Select, VStack } from \"@chakra-ui/react\";\nimport { MapModelProps, useMapModelValue } from \"@open-pioneer/map\";\nimport { CommonComponentProps, useCommonComponentProps } from \"@open-pioneer/react-utils\";\nimport { useReactiveSnapshot } from \"@open-pioneer/reactivity\";\nimport { useIntl } from \"open-pioneer:react-hooks\";\nimport { FC, useMemo } from \"react\";\nimport { SelectionResult, SelectionSource } from \"../api\";\nimport { SelectionViewModel } from \"../model\";\nimport { SelectionSourceItem } from \"./SelectionSourceItem\";\nimport { useSelectionSourceId } from \"./useSelectionSourceId\";\nimport { useSelectionViewModel } from \"./useSelectionViewModel\";\nimport { useSourceStatus } from \"./useSourceStatus\";\n\n/**\n * Properties supported by the {@link Selection} component.\n */\nexport interface SelectionProps extends CommonComponentProps, MapModelProps {\n /**\n * Array of selection sources available for spatial selection.\n */\n sources: SelectionSource[];\n\n /**\n * This handler is called whenever the user has successfully selected\n * some items.\n */\n onSelectionComplete?(event: SelectionCompleteEvent): void;\n\n /**\n * This handler is called whenever the user has changed the selected source\n */\n onSelectionSourceChanged?(event: SelectionSourceChangedEvent): void;\n}\n\nexport interface SelectionCompleteEvent {\n /** The source that returned the {@link results}. */\n source: SelectionSource;\n\n /** Results selected by the user. */\n results: SelectionResult[];\n}\n\nexport interface SelectionSourceChangedEvent {\n /** The new selected source */\n source: SelectionSource | undefined;\n}\n\n/**\n * A component that allows the user to perform a spatial selection on a given set of {@link SelectionSource}.\n */\nexport const Selection: FC<SelectionProps> = (props) => {\n const { sources, onSelectionComplete, onSelectionSourceChanged } = props;\n const map = useMapModelValue(props);\n const viewModel = useSelectionViewModel(\n map,\n sources,\n onSelectionComplete,\n onSelectionSourceChanged\n );\n return viewModel && <SelectionReady viewModel={viewModel} {...props} />;\n};\n\nfunction SelectionReady(props: CommonComponentProps & { viewModel: SelectionViewModel }) {\n const { viewModel } = props;\n const { containerProps } = useCommonComponentProps(\"selection\", props);\n const intl = useIntl();\n\n // Subscribe to relevant view model state.\n const sources = useReactiveSnapshot(() => viewModel.sources, [viewModel]);\n const currentSource = useReactiveSnapshot(() => viewModel.currentSource, [viewModel]);\n const ariaMessage = useReactiveSnapshot(() => viewModel.ariaMessage, [viewModel]);\n\n // Translate sources array to a collection for chakra's select control.\n const getSourceId = useSelectionSourceId();\n const sourceOptionsCollection = useMemo(\n () =>\n createListCollection({\n items: sources,\n isItemDisabled: () => {\n return false;\n },\n itemToString: (item) => item.label,\n itemToValue: (item) => getSourceId(item)\n }),\n [sources, getSourceId]\n );\n\n let triggerItem;\n if (currentSource) {\n triggerItem = <SelectionSourceItem source={currentSource} />;\n } else {\n triggerItem = null;\n }\n\n return (\n <VStack {...containerProps} gap={2}>\n <Select.Root\n className=\"selection-source\"\n collection={sourceOptionsCollection}\n value={currentSource ? [getSourceId(currentSource)] : []}\n onValueChange={(details) => {\n const source = details.items[0];\n if (source) {\n viewModel.currentSource = source;\n }\n }}\n lazyMount={true}\n unmountOnExit={true}\n >\n <Select.Label>{intl.formatMessage({ id: \"selectSource\" })}</Select.Label>\n\n <Select.Control>\n <Select.Trigger aria-description={ariaMessage}>\n <Select.ValueText\n placeholder={intl.formatMessage({ id: \"selectionPlaceholder\" })}\n >\n {triggerItem}\n </Select.ValueText>\n </Select.Trigger>\n <Select.IndicatorGroup>\n <Select.Indicator />\n </Select.IndicatorGroup>\n </Select.Control>\n\n <Portal>\n <Select.Positioner>\n <Select.Content className=\"selection-source-options\">\n {sourceOptionsCollection.items.map((item) => (\n <SelectionSourceItemContent source={item} key={getSourceId(item)} />\n ))}\n </Select.Content>\n </Select.Positioner>\n </Portal>\n </Select.Root>\n </VStack>\n );\n}\n\n/**\n * Renders a dropdown item in the menu.\n */\nfunction SelectionSourceItemContent(props: { source: SelectionSource }) {\n const { source } = props;\n const isDisabled = useSourceStatus(source).kind === \"unavailable\";\n return (\n <Select.Item\n className=\"selection-source-option\"\n item={source}\n justifyContent=\"flex-start\"\n // Override pointer-events: none rule for disabled items; we want to show the tooltip on hover\n pointerEvents=\"auto\"\n aria-disabled={isDisabled ? \"true\" : undefined}\n >\n <SelectionSourceItem source={source} />\n </Select.Item>\n );\n}\n"],"names":[],"mappings":";;;;;;;;;;;;AAqDO,MAAM,SAAA,GAAgC,CAAC,KAAA,KAAU;AACpD,EAAA,MAAM,EAAE,OAAA,EAAS,mBAAA,EAAqB,wBAAA,EAAyB,GAAI,KAAA;AACnE,EAAA,MAAM,GAAA,GAAM,iBAAiB,KAAK,CAAA;AAClC,EAAA,MAAM,SAAA,GAAY,qBAAA;AAAA,IACd,GAAA;AAAA,IACA,OAAA;AAAA,IACA,mBAAA;AAAA,IACA;AAAA,GACJ;AACA,EAAA,OAAO,SAAA,oBAAa,GAAA,CAAC,cAAA,EAAA,EAAe,SAAA,EAAuB,GAAG,KAAA,EAAO,CAAA;AACzE;AAEA,SAAS,eAAe,KAAA,EAAiE;AACrF,EAAA,MAAM,EAAE,WAAU,GAAI,KAAA;AACtB,EAAA,MAAM,EAAE,cAAA,EAAe,GAAI,uBAAA,CAAwB,aAAa,KAAK,CAAA;AACrE,EAAA,MAAM,OAAO,OAAA,EAAQ;AAGrB,EAAA,MAAM,UAAU,mBAAA,CAAoB,MAAM,UAAU,OAAA,EAAS,CAAC,SAAS,CAAC,CAAA;AACxE,EAAA,MAAM,gBAAgB,mBAAA,CAAoB,MAAM,UAAU,aAAA,EAAe,CAAC,SAAS,CAAC,CAAA;AACpF,EAAA,MAAM,cAAc,mBAAA,CAAoB,MAAM,UAAU,WAAA,EAAa,CAAC,SAAS,CAAC,CAAA;AAGhF,EAAA,MAAM,cAAc,oBAAA,EAAqB;AACzC,EAAA,MAAM,uBAAA,GAA0B,OAAA;AAAA,IAC5B,MACI,oBAAA,CAAqB;AAAA,MACjB,KAAA,EAAO,OAAA;AAAA,MACP,gBAAgB,MAAM;AAClB,QAAA,OAAO,KAAA;AAAA,MACX,CAAA;AAAA,MACA,YAAA,EAAc,CAAC,IAAA,KAAS,IAAA,CAAK,KAAA;AAAA,MAC7B,WAAA,EAAa,CAAC,IAAA,KAAS,WAAA,CAAY,IAAI;AAAA,KAC1C,CAAA;AAAA,IACL,CAAC,SAAS,WAAW;AAAA,GACzB;AAEA,EAAA,IAAI,WAAA;AACJ,EAAA,IAAI,aAAA,EAAe;AACf,IAAA,WAAA,mBAAc,GAAA,CAAC,mBAAA,EAAA,EAAoB,MAAA,EAAQ,aAAA,EAAe,CAAA;AAAA,EAC9D,CAAA,MAAO;AACH,IAAA,WAAA,GAAc,IAAA;AAAA,EAClB;AAEA,EAAA,uBACI,GAAA,CAAC,MAAA,EAAA,EAAQ,GAAG,cAAA,EAAgB,KAAK,CAAA,EAC7B,QAAA,kBAAA,IAAA;AAAA,IAAC,MAAA,CAAO,IAAA;AAAA,IAAP;AAAA,MACG,SAAA,EAAU,kBAAA;AAAA,MACV,UAAA,EAAY,uBAAA;AAAA,MACZ,OAAO,aAAA,GAAgB,CAAC,YAAY,aAAa,CAAC,IAAI,EAAC;AAAA,MACvD,aAAA,EAAe,CAAC,OAAA,KAAY;AACxB,QAAA,MAAM,MAAA,GAAS,OAAA,CAAQ,KAAA,CAAM,CAAC,CAAA;AAC9B,QAAA,IAAI,MAAA,EAAQ;AACR,UAAA,SAAA,CAAU,aAAA,GAAgB,MAAA;AAAA,QAC9B;AAAA,MACJ,CAAA;AAAA,MACA,SAAA,EAAW,IAAA;AAAA,MACX,aAAA,EAAe,IAAA;AAAA,MAEf,QAAA,EAAA;AAAA,wBAAA,GAAA,CAAC,MAAA,CAAO,OAAP,EAAc,QAAA,EAAA,IAAA,CAAK,cAAc,EAAE,EAAA,EAAI,cAAA,EAAgB,CAAA,EAAE,CAAA;AAAA,wBAE1D,IAAA,CAAC,MAAA,CAAO,OAAA,EAAP,EACG,QAAA,EAAA;AAAA,0BAAA,GAAA,CAAC,MAAA,CAAO,OAAA,EAAP,EAAe,kBAAA,EAAkB,WAAA,EAC9B,QAAA,kBAAA,GAAA;AAAA,YAAC,MAAA,CAAO,SAAA;AAAA,YAAP;AAAA,cACG,aAAa,IAAA,CAAK,aAAA,CAAc,EAAE,EAAA,EAAI,wBAAwB,CAAA;AAAA,cAE7D,QAAA,EAAA;AAAA;AAAA,WACL,EACJ,CAAA;AAAA,0BACA,GAAA,CAAC,OAAO,cAAA,EAAP,EACG,8BAAC,MAAA,CAAO,SAAA,EAAP,EAAiB,CAAA,EACtB;AAAA,SAAA,EACJ,CAAA;AAAA,wBAEA,GAAA,CAAC,MAAA,EAAA,EACG,QAAA,kBAAA,GAAA,CAAC,MAAA,CAAO,UAAA,EAAP,EACG,QAAA,kBAAA,GAAA,CAAC,MAAA,CAAO,OAAA,EAAP,EAAe,SAAA,EAAU,0BAAA,EACrB,QAAA,EAAA,uBAAA,CAAwB,KAAA,CAAM,GAAA,CAAI,CAAC,IAAA,qBAChC,GAAA,CAAC,0BAAA,EAAA,EAA2B,MAAA,EAAQ,IAAA,EAAA,EAAW,WAAA,CAAY,IAAI,CAAG,CACrE,CAAA,EACL,CAAA,EACJ,CAAA,EACJ;AAAA;AAAA;AAAA,GACJ,EACJ,CAAA;AAER;AAKA,SAAS,2BAA2B,KAAA,EAAoC;AACpE,EAAA,MAAM,EAAE,QAAO,GAAI,KAAA;AACnB,EAAA,MAAM,UAAA,GAAa,eAAA,CAAgB,MAAM,CAAA,CAAE,IAAA,KAAS,aAAA;AACpD,EAAA,uBACI,GAAA;AAAA,IAAC,MAAA,CAAO,IAAA;AAAA,IAAP;AAAA,MACG,SAAA,EAAU,yBAAA;AAAA,MACV,IAAA,EAAM,MAAA;AAAA,MACN,cAAA,EAAe,YAAA;AAAA,MAEf,aAAA,EAAc,MAAA;AAAA,MACd,eAAA,EAAe,aAAa,MAAA,GAAS,MAAA;AAAA,MAErC,QAAA,kBAAA,GAAA,CAAC,uBAAoB,MAAA,EAAgB;AAAA;AAAA,GACzC;AAER;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SelectionSourceItem.js","sources":["SelectionSourceItem.tsx"],"sourcesContent":["// SPDX-FileCopyrightText: 2023-2025 Open Pioneer project (https://github.com/open-pioneer)\n// SPDX-License-Identifier: Apache-2.0\n\nimport { Box, chakra, Flex, Icon } from \"@chakra-ui/react\";\nimport { Tooltip } from \"@open-pioneer/chakra-snippets/tooltip\";\nimport { useReactiveSnapshot } from \"@open-pioneer/reactivity\";\nimport { LuTriangleAlert } from \"react-icons/lu\";\nimport { SelectionSource } from \"../api\";\nimport { useSourceStatus } from \"./useSourceStatus\";\n\n/**\n * Renders a selection source in the dropdown menu (option or current selection).\n */\nexport function SelectionSourceItem(props: { source: SelectionSource | undefined }) {\n const { source } = props;\n const label = useReactiveSnapshot(() => source?.label, [source]);\n const status = useSourceStatus(source);\n const isAvailable = status.kind === \"available\";\n const clazz = isAvailable\n ? \"selection-source-value\"\n : \"selection-source-value selection-source-value--disabled\";\n\n return (\n <Flex className={clazz} direction=\"row\" alignItems=\"center\" grow={1}>\n {label}\n {status.kind === \"unavailable\" && (\n <Box ml={2}>\n <Tooltip\n content={status.reason}\n positioning={{ placement: \"right\" }}\n openDelay={500}\n >\n <chakra.span>\n <Icon\n color=\"red\"\n className=\"warning-icon\"\n aria-label={status.reason}\n aria-hidden={undefined} // Overwrite icon default so the label gets read\n >\n <LuTriangleAlert />\n </Icon>\n </chakra.span>\n </Tooltip>\n </Box>\n )}\n </Flex>\n );\n}\n"],"names":[],"mappings":";;;;;;;AAaO,SAAS,oBAAoB,KAAA,EAAgD;AAChF,EAAA,MAAM,EAAE,QAAO,GAAI,KAAA;AACnB,EAAA,MAAM,QAAQ,mBAAA,CAAoB,MAAM,QAAQ,KAAA,EAAO,CAAC,MAAM,CAAC,CAAA;AAC/D,EAAA,MAAM,MAAA,GAAS,gBAAgB,MAAM,CAAA;AACrC,EAAA,MAAM,WAAA,GAAc,OAAO,IAAA,KAAS,WAAA;AACpC,EAAA,MAAM,KAAA,GAAQ,cACR,wBAAA,GACA,yDAAA;AAEN,EAAA,uBACI,IAAA,CAAC,QAAK,SAAA,EAAW,KAAA,EAAO,WAAU,KAAA,EAAM,UAAA,EAAW,QAAA,EAAS,IAAA,EAAM,CAAA,EAC7D,QAAA,EAAA;AAAA,IAAA,KAAA;AAAA,IACA,OAAO,IAAA,KAAS,aAAA,oBACb,GAAA,CAAC,GAAA,EAAA,EAAI,IAAI,CAAA,EACL,QAAA,kBAAA,GAAA;AAAA,MAAC,OAAA;AAAA,MAAA;AAAA,QACG,SAAS,MAAA,CAAO,MAAA;AAAA,QAChB,WAAA,EAAa,EAAE,SAAA,EAAW,OAAA,EAAQ;AAAA,QAClC,SAAA,EAAW,GAAA;AAAA,QAEX,QAAA,kBAAA,GAAA,CAAC,MAAA,CAAO,IAAA,EAAP,EACG,QAAA,kBAAA,GAAA;AAAA,UAAC,IAAA;AAAA,UAAA;AAAA,YACG,KAAA,EAAM,KAAA;AAAA,YACN,SAAA,EAAU,cAAA;AAAA,YACV,cAAY,MAAA,CAAO,MAAA;AAAA,YACnB,aAAA,EAAa,MAAA;AAAA,YAEb,8BAAC,eAAA,EAAA,EAAgB;AAAA;AAAA,SACrB,EACJ;AAAA;AAAA,KACJ,EACJ;AAAA,GAAA,EAER,CAAA;AAER
|
|
1
|
+
{"version":3,"file":"SelectionSourceItem.js","sources":["SelectionSourceItem.tsx"],"sourcesContent":["// SPDX-FileCopyrightText: 2023-2025 Open Pioneer project (https://github.com/open-pioneer)\n// SPDX-License-Identifier: Apache-2.0\n\nimport { Box, chakra, Flex, Icon } from \"@chakra-ui/react\";\nimport { Tooltip } from \"@open-pioneer/chakra-snippets/tooltip\";\nimport { useReactiveSnapshot } from \"@open-pioneer/reactivity\";\nimport { LuTriangleAlert } from \"react-icons/lu\";\nimport { SelectionSource } from \"../api\";\nimport { useSourceStatus } from \"./useSourceStatus\";\n\n/**\n * Renders a selection source in the dropdown menu (option or current selection).\n */\nexport function SelectionSourceItem(props: { source: SelectionSource | undefined }) {\n const { source } = props;\n const label = useReactiveSnapshot(() => source?.label, [source]);\n const status = useSourceStatus(source);\n const isAvailable = status.kind === \"available\";\n const clazz = isAvailable\n ? \"selection-source-value\"\n : \"selection-source-value selection-source-value--disabled\";\n\n return (\n <Flex className={clazz} direction=\"row\" alignItems=\"center\" grow={1}>\n {label}\n {status.kind === \"unavailable\" && (\n <Box ml={2}>\n <Tooltip\n content={status.reason}\n positioning={{ placement: \"right\" }}\n openDelay={500}\n >\n <chakra.span>\n <Icon\n color=\"red\"\n className=\"warning-icon\"\n aria-label={status.reason}\n aria-hidden={undefined} // Overwrite icon default so the label gets read\n >\n <LuTriangleAlert />\n </Icon>\n </chakra.span>\n </Tooltip>\n </Box>\n )}\n </Flex>\n );\n}\n"],"names":[],"mappings":";;;;;;;AAaO,SAAS,oBAAoB,KAAA,EAAgD;AAChF,EAAA,MAAM,EAAE,QAAO,GAAI,KAAA;AACnB,EAAA,MAAM,QAAQ,mBAAA,CAAoB,MAAM,QAAQ,KAAA,EAAO,CAAC,MAAM,CAAC,CAAA;AAC/D,EAAA,MAAM,MAAA,GAAS,gBAAgB,MAAM,CAAA;AACrC,EAAA,MAAM,WAAA,GAAc,OAAO,IAAA,KAAS,WAAA;AACpC,EAAA,MAAM,KAAA,GAAQ,cACR,wBAAA,GACA,yDAAA;AAEN,EAAA,uBACI,IAAA,CAAC,QAAK,SAAA,EAAW,KAAA,EAAO,WAAU,KAAA,EAAM,UAAA,EAAW,QAAA,EAAS,IAAA,EAAM,CAAA,EAC7D,QAAA,EAAA;AAAA,IAAA,KAAA;AAAA,IACA,OAAO,IAAA,KAAS,aAAA,oBACb,GAAA,CAAC,GAAA,EAAA,EAAI,IAAI,CAAA,EACL,QAAA,kBAAA,GAAA;AAAA,MAAC,OAAA;AAAA,MAAA;AAAA,QACG,SAAS,MAAA,CAAO,MAAA;AAAA,QAChB,WAAA,EAAa,EAAE,SAAA,EAAW,OAAA,EAAQ;AAAA,QAClC,SAAA,EAAW,GAAA;AAAA,QAEX,QAAA,kBAAA,GAAA,CAAC,MAAA,CAAO,IAAA,EAAP,EACG,QAAA,kBAAA,GAAA;AAAA,UAAC,IAAA;AAAA,UAAA;AAAA,YACG,KAAA,EAAM,KAAA;AAAA,YACN,SAAA,EAAU,cAAA;AAAA,YACV,cAAY,MAAA,CAAO,MAAA;AAAA,YACnB,aAAA,EAAa,MAAA;AAAA,YAEb,8BAAC,eAAA,EAAA,EAAgB;AAAA;AAAA,SACrB,EACJ;AAAA;AAAA,KACJ,EACJ;AAAA,GAAA,EAER,CAAA;AAER;;"}
|
package/ui/selection.css
CHANGED
|
@@ -3,20 +3,6 @@
|
|
|
3
3
|
border: 3px solid var(--chakra-colors-trails-solid) !important;
|
|
4
4
|
}
|
|
5
5
|
|
|
6
|
-
.selection-tooltip {
|
|
7
|
-
position: relative;
|
|
8
|
-
background: rgb(from var(--chakra-colors-bg) r g b / 80%);
|
|
9
|
-
border-radius: 4px;
|
|
10
|
-
color: var(--chakra-colors-fg);
|
|
11
|
-
padding: 4px 8px;
|
|
12
|
-
opacity: 1;
|
|
13
|
-
white-space: nowrap;
|
|
14
|
-
font-size: 12px;
|
|
15
|
-
cursor: default;
|
|
16
|
-
user-select: none;
|
|
17
|
-
font-weight: bold;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
6
|
.map-container .selection-active {
|
|
21
7
|
cursor: crosshair;
|
|
22
8
|
}
|
package/ui/selection.css.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["selection.css"],"names":[],"mappings":"AAAA;IACI,qDAAqD;IACrD,8DAA8D;AAClE;;AAEA;IACI,
|
|
1
|
+
{"version":3,"sources":["selection.css"],"names":[],"mappings":"AAAA;IACI,qDAAqD;IACrD,8DAA8D;AAClE;;AAEA;IACI,iBAAiB;AACrB;;AAEA;IACI,eAAe;AACnB;;AAEA;IACI,YAAY;AAChB;;AAEA;IACI,uBAAuB;AAC3B","file":"selection.css","sourcesContent":[".selection-drag-box {\n background-color: rgba(255, 255, 255, 0.3) !important;\n border: 3px solid var(--chakra-colors-trails-solid) !important;\n}\n\n.map-container .selection-active {\n cursor: crosshair;\n}\n\n.map-container .selection-inactive {\n cursor: no-drop;\n}\n\n.selection-source-value.selection-source-value--disabled {\n opacity: 0.4;\n}\n\n.selection-source-value.selection-source-value--disabled span {\n margin: 0px 6px 0px 0px;\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useSelectionSourceId.js","sources":["useSelectionSourceId.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2023-2025 Open Pioneer project (https://github.com/open-pioneer)\n// SPDX-License-Identifier: Apache-2.0\n\nimport { useCallback, useRef } from \"react\";\nimport { SelectionSource } from \"../api\";\n\nexport type GetSelectionSourceId = (selectionSource: SelectionSource) => string;\n\nconst GENERATED_ID_PREFIX = \"__anon_source_\";\n\n/**\n * Assigns unique IDs to selection sources.\n *\n * Sources that define their own {@link SelectionSource.id} keep that id;\n * for all other sources an id is generated.\n */\nexport function useSelectionSourceId(): GetSelectionSourceId {\n const sourceIds = useRef<WeakMap<SelectionSource, string>>(undefined);\n const counter = useRef(0);\n // oxlint-disable-next-line react/refs\n if (!sourceIds.current) {\n sourceIds.current = new WeakMap();\n }\n\n return useCallback((source: SelectionSource) => {\n if (source.id != null) {\n return source.id;\n }\n\n // oxlint-disable-next-line @typescript-eslint/no-non-null-assertion\n const ids = sourceIds.current!;\n if (!ids.has(source)) {\n ids.set(source, `${GENERATED_ID_PREFIX}${counter.current++}`);\n }\n // oxlint-disable-next-line @typescript-eslint/no-non-null-assertion\n return ids.get(source)!;\n }, []);\n}\n"],"names":[],"mappings":";;AAQA,MAAM,mBAAA,GAAsB,gBAAA;AAQrB,SAAS,oBAAA,GAA6C;AACzD,EAAA,MAAM,SAAA,GAAY,OAAyC,MAAS,CAAA;AACpE,EAAA,MAAM,OAAA,GAAU,OAAO,CAAC,CAAA;AAExB,EAAA,IAAI,CAAC,UAAU,OAAA,EAAS;AACpB,IAAA,SAAA,CAAU,OAAA,uBAAc,OAAA,EAAQ;AAAA,EACpC;AAEA,EAAA,OAAO,WAAA,CAAY,CAAC,MAAA,KAA4B;AAC5C,IAAA,IAAI,MAAA,CAAO,MAAM,IAAA,EAAM;AACnB,MAAA,OAAO,MAAA,CAAO,EAAA;AAAA,IAClB;AAGA,IAAA,MAAM,MAAM,SAAA,CAAU,OAAA;AACtB,IAAA,IAAI,CAAC,GAAA,CAAI,GAAA,CAAI,MAAM,CAAA,EAAG;AAClB,MAAA,GAAA,CAAI,IAAI,MAAA,EAAQ,CAAA,EAAG,mBAAmB,CAAA,EAAG,OAAA,CAAQ,SAAS,CAAA,CAAE,CAAA;AAAA,IAChE;AAEA,IAAA,OAAO,GAAA,CAAI,IAAI,MAAM,CAAA;AAAA,EACzB,CAAA,EAAG,EAAE,CAAA;AACT
|
|
1
|
+
{"version":3,"file":"useSelectionSourceId.js","sources":["useSelectionSourceId.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2023-2025 Open Pioneer project (https://github.com/open-pioneer)\n// SPDX-License-Identifier: Apache-2.0\n\nimport { useCallback, useRef } from \"react\";\nimport { SelectionSource } from \"../api\";\n\nexport type GetSelectionSourceId = (selectionSource: SelectionSource) => string;\n\nconst GENERATED_ID_PREFIX = \"__anon_source_\";\n\n/**\n * Assigns unique IDs to selection sources.\n *\n * Sources that define their own {@link SelectionSource.id} keep that id;\n * for all other sources an id is generated.\n */\nexport function useSelectionSourceId(): GetSelectionSourceId {\n const sourceIds = useRef<WeakMap<SelectionSource, string>>(undefined);\n const counter = useRef(0);\n // oxlint-disable-next-line react/refs\n if (!sourceIds.current) {\n sourceIds.current = new WeakMap();\n }\n\n return useCallback((source: SelectionSource) => {\n if (source.id != null) {\n return source.id;\n }\n\n // oxlint-disable-next-line @typescript-eslint/no-non-null-assertion\n const ids = sourceIds.current!;\n if (!ids.has(source)) {\n ids.set(source, `${GENERATED_ID_PREFIX}${counter.current++}`);\n }\n // oxlint-disable-next-line @typescript-eslint/no-non-null-assertion\n return ids.get(source)!;\n }, []);\n}\n"],"names":[],"mappings":";;AAQA,MAAM,mBAAA,GAAsB,gBAAA;AAQrB,SAAS,oBAAA,GAA6C;AACzD,EAAA,MAAM,SAAA,GAAY,OAAyC,MAAS,CAAA;AACpE,EAAA,MAAM,OAAA,GAAU,OAAO,CAAC,CAAA;AAExB,EAAA,IAAI,CAAC,UAAU,OAAA,EAAS;AACpB,IAAA,SAAA,CAAU,OAAA,uBAAc,OAAA,EAAQ;AAAA,EACpC;AAEA,EAAA,OAAO,WAAA,CAAY,CAAC,MAAA,KAA4B;AAC5C,IAAA,IAAI,MAAA,CAAO,MAAM,IAAA,EAAM;AACnB,MAAA,OAAO,MAAA,CAAO,EAAA;AAAA,IAClB;AAGA,IAAA,MAAM,MAAM,SAAA,CAAU,OAAA;AACtB,IAAA,IAAI,CAAC,GAAA,CAAI,GAAA,CAAI,MAAM,CAAA,EAAG;AAClB,MAAA,GAAA,CAAI,IAAI,MAAA,EAAQ,CAAA,EAAG,mBAAmB,CAAA,EAAG,OAAA,CAAQ,SAAS,CAAA,CAAE,CAAA;AAAA,IAChE;AAEA,IAAA,OAAO,GAAA,CAAI,IAAI,MAAM,CAAA;AAAA,EACzB,CAAA,EAAG,EAAE,CAAA;AACT;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useSelectionViewModel.js","sources":["useSelectionViewModel.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2023-2025 Open Pioneer project (https://github.com/open-pioneer)\n// SPDX-License-Identifier: Apache-2.0\n\nimport { watchValue } from \"@conterra/reactivity-core\";\nimport { MapModel } from \"@open-pioneer/map\";\nimport { useService } from \"open-pioneer:react-hooks\";\nimport { useEffect, useEffectEvent, useState } from \"react\";\nimport { SelectionResult, SelectionSource } from \"../api\";\nimport { SelectionViewModel } from \"../model\";\nimport { SelectionViewModelFactory } from \"../services\";\nimport { SelectionCompleteEvent, SelectionSourceChangedEvent } from \"./Selection\";\n\n/**\n * Initializes the (internal) view model used by the selection component.\n *\n * The view model contains the primary widget state.\n * It is a long lived instance that is updated in place when relevant react props are changed.\n */\nexport function useSelectionViewModel(\n map: MapModel,\n sources: SelectionSource[],\n onSelectionComplete: ((event: SelectionCompleteEvent) => void) | undefined,\n onSelectionSourceChanged: ((event: SelectionSourceChangedEvent) => void) | undefined\n): SelectionViewModel | undefined {\n const viewModelFactory = useService<SelectionViewModelFactory>(\"selection.ViewModelFactory\");\n const onComplete = useEffectEvent((source: SelectionSource, results: SelectionResult[]) => {\n onSelectionComplete?.({ source, results });\n });\n const onChange = useEffectEvent((source: SelectionSource | undefined) => {\n onSelectionSourceChanged?.({ source });\n });\n\n // Construct view model\n const [viewModel, setViewModel] = useState<SelectionViewModel>();\n useEffect(() => {\n const vm = viewModelFactory.createViewModel({\n map,\n onSelectionComplete: onComplete\n });\n\n setViewModel(vm);\n return () => {\n setViewModel(undefined);\n vm.destroy();\n };\n }, [viewModelFactory, map]);\n\n // Sync sources --> view model\n useEffect(() => {\n if (viewModel) {\n viewModel.sources = sources;\n }\n }, [viewModel, sources]);\n\n // Sync current source --> react callbacks\n useEffect(() => {\n if (!viewModel) {\n return;\n }\n\n const handle = watchValue(() => viewModel.currentSource, onChange, {\n immediate: true\n });\n return () => handle.destroy();\n }, [viewModel]);\n\n return viewModel;\n}\n"],"names":[],"mappings":";;;;AAkBO,SAAS,qBAAA,CACZ,GAAA,EACA,OAAA,EACA,mBAAA,EACA,wBAAA,EAC8B;AAC9B,EAAA,MAAM,gBAAA,GAAmB,WAAsC,4BAA4B,CAAA;AAC3F,EAAA,MAAM,UAAA,GAAa,cAAA,CAAe,CAAC,MAAA,EAAyB,OAAA,KAA+B;AACvF,IAAA,mBAAA,GAAsB,EAAE,MAAA,EAAQ,OAAA,EAAS,CAAA;AAAA,EAC7C,CAAC,CAAA;AACD,EAAA,MAAM,QAAA,GAAW,cAAA,CAAe,CAAC,MAAA,KAAwC;AACrE,IAAA,wBAAA,GAA2B,EAAE,QAAQ,CAAA;AAAA,EACzC,CAAC,CAAA;AAGD,EAAA,MAAM,CAAC,SAAA,EAAW,YAAY,CAAA,GAAI,QAAA,EAA6B;AAC/D,EAAA,SAAA,CAAU,MAAM;AACZ,IAAA,MAAM,EAAA,GAAK,iBAAiB,eAAA,CAAgB;AAAA,MACxC,GAAA;AAAA,MACA,mBAAA,EAAqB;AAAA,KACxB,CAAA;AAED,IAAA,YAAA,CAAa,EAAE,CAAA;AACf,IAAA,OAAO,MAAM;AACT,MAAA,YAAA,CAAa,MAAS,CAAA;AACtB,MAAA,EAAA,CAAG,OAAA,EAAQ;AAAA,IACf,CAAA;AAAA,EACJ,CAAA,EAAG,CAAC,gBAAA,EAAkB,GAAG,CAAC,CAAA;AAG1B,EAAA,SAAA,CAAU,MAAM;AACZ,IAAA,IAAI,SAAA,EAAW;AACX,MAAA,SAAA,CAAU,OAAA,GAAU,OAAA;AAAA,IACxB;AAAA,EACJ,CAAA,EAAG,CAAC,SAAA,EAAW,OAAO,CAAC,CAAA;AAGvB,EAAA,SAAA,CAAU,MAAM;AACZ,IAAA,IAAI,CAAC,SAAA,EAAW;AACZ,MAAA;AAAA,IACJ;AAEA,IAAA,MAAM,MAAA,GAAS,UAAA,CAAW,MAAM,SAAA,CAAU,eAAe,QAAA,EAAU;AAAA,MAC/D,SAAA,EAAW;AAAA,KACd,CAAA;AACD,IAAA,OAAO,MAAM,OAAO,OAAA,EAAQ;AAAA,EAChC,CAAA,EAAG,CAAC,SAAS,CAAC,CAAA;AAEd,EAAA,OAAO,SAAA;AACX
|
|
1
|
+
{"version":3,"file":"useSelectionViewModel.js","sources":["useSelectionViewModel.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2023-2025 Open Pioneer project (https://github.com/open-pioneer)\n// SPDX-License-Identifier: Apache-2.0\n\nimport { watchValue } from \"@conterra/reactivity-core\";\nimport { MapModel } from \"@open-pioneer/map\";\nimport { useService } from \"open-pioneer:react-hooks\";\nimport { useEffect, useEffectEvent, useState } from \"react\";\nimport { SelectionResult, SelectionSource } from \"../api\";\nimport { SelectionViewModel } from \"../model\";\nimport { SelectionViewModelFactory } from \"../services\";\nimport { SelectionCompleteEvent, SelectionSourceChangedEvent } from \"./Selection\";\n\n/**\n * Initializes the (internal) view model used by the selection component.\n *\n * The view model contains the primary widget state.\n * It is a long lived instance that is updated in place when relevant react props are changed.\n */\nexport function useSelectionViewModel(\n map: MapModel,\n sources: SelectionSource[],\n onSelectionComplete: ((event: SelectionCompleteEvent) => void) | undefined,\n onSelectionSourceChanged: ((event: SelectionSourceChangedEvent) => void) | undefined\n): SelectionViewModel | undefined {\n const viewModelFactory = useService<SelectionViewModelFactory>(\"selection.ViewModelFactory\");\n const onComplete = useEffectEvent((source: SelectionSource, results: SelectionResult[]) => {\n onSelectionComplete?.({ source, results });\n });\n const onChange = useEffectEvent((source: SelectionSource | undefined) => {\n onSelectionSourceChanged?.({ source });\n });\n\n // Construct view model\n const [viewModel, setViewModel] = useState<SelectionViewModel>();\n useEffect(() => {\n const vm = viewModelFactory.createViewModel({\n map,\n onSelectionComplete: onComplete\n });\n\n setViewModel(vm);\n return () => {\n setViewModel(undefined);\n vm.destroy();\n };\n }, [viewModelFactory, map]);\n\n // Sync sources --> view model\n useEffect(() => {\n if (viewModel) {\n viewModel.sources = sources;\n }\n }, [viewModel, sources]);\n\n // Sync current source --> react callbacks\n useEffect(() => {\n if (!viewModel) {\n return;\n }\n\n const handle = watchValue(() => viewModel.currentSource, onChange, {\n immediate: true\n });\n return () => handle.destroy();\n }, [viewModel]);\n\n return viewModel;\n}\n"],"names":[],"mappings":";;;;AAkBO,SAAS,qBAAA,CACZ,GAAA,EACA,OAAA,EACA,mBAAA,EACA,wBAAA,EAC8B;AAC9B,EAAA,MAAM,gBAAA,GAAmB,WAAsC,4BAA4B,CAAA;AAC3F,EAAA,MAAM,UAAA,GAAa,cAAA,CAAe,CAAC,MAAA,EAAyB,OAAA,KAA+B;AACvF,IAAA,mBAAA,GAAsB,EAAE,MAAA,EAAQ,OAAA,EAAS,CAAA;AAAA,EAC7C,CAAC,CAAA;AACD,EAAA,MAAM,QAAA,GAAW,cAAA,CAAe,CAAC,MAAA,KAAwC;AACrE,IAAA,wBAAA,GAA2B,EAAE,QAAQ,CAAA;AAAA,EACzC,CAAC,CAAA;AAGD,EAAA,MAAM,CAAC,SAAA,EAAW,YAAY,CAAA,GAAI,QAAA,EAA6B;AAC/D,EAAA,SAAA,CAAU,MAAM;AACZ,IAAA,MAAM,EAAA,GAAK,iBAAiB,eAAA,CAAgB;AAAA,MACxC,GAAA;AAAA,MACA,mBAAA,EAAqB;AAAA,KACxB,CAAA;AAED,IAAA,YAAA,CAAa,EAAE,CAAA;AACf,IAAA,OAAO,MAAM;AACT,MAAA,YAAA,CAAa,MAAS,CAAA;AACtB,MAAA,EAAA,CAAG,OAAA,EAAQ;AAAA,IACf,CAAA;AAAA,EACJ,CAAA,EAAG,CAAC,gBAAA,EAAkB,GAAG,CAAC,CAAA;AAG1B,EAAA,SAAA,CAAU,MAAM;AACZ,IAAA,IAAI,SAAA,EAAW;AACX,MAAA,SAAA,CAAU,OAAA,GAAU,OAAA;AAAA,IACxB;AAAA,EACJ,CAAA,EAAG,CAAC,SAAA,EAAW,OAAO,CAAC,CAAA;AAGvB,EAAA,SAAA,CAAU,MAAM;AACZ,IAAA,IAAI,CAAC,SAAA,EAAW;AACZ,MAAA;AAAA,IACJ;AAEA,IAAA,MAAM,MAAA,GAAS,UAAA,CAAW,MAAM,SAAA,CAAU,eAAe,QAAA,EAAU;AAAA,MAC/D,SAAA,EAAW;AAAA,KACd,CAAA;AACD,IAAA,OAAO,MAAM,OAAO,OAAA,EAAQ;AAAA,EAChC,CAAA,EAAG,CAAC,SAAS,CAAC,CAAA;AAEd,EAAA,OAAO,SAAA;AACX;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useSourceStatus.js","sources":["useSourceStatus.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2023-2025 Open Pioneer project (https://github.com/open-pioneer)\n// SPDX-License-Identifier: Apache-2.0\n\nimport { useReactiveSnapshot } from \"@open-pioneer/reactivity\";\nimport { useIntl } from \"open-pioneer:react-hooks\";\nimport { SelectionSource } from \"../api\";\nimport { getSourceStatus } from \"../model\";\n\nexport type SimpleStatus =\n | {\n kind: \"available\";\n }\n | {\n kind: \"unavailable\";\n reason: string;\n };\n\nexport function useSourceStatus(source: SelectionSource | undefined): SimpleStatus {\n const intl = useIntl();\n const sourceStatus = useReactiveSnapshot((): SimpleStatus => {\n if (!source) {\n return {\n kind: \"unavailable\",\n reason: intl.formatMessage({ id: \"sourceNotAvailable\" })\n };\n }\n\n const status = getSourceStatus(source);\n if (status.kind === \"available\") {\n return status;\n }\n return {\n kind: \"unavailable\",\n reason: status.reason ?? intl.formatMessage({ id: \"sourceNotAvailable\" })\n };\n }, [source, intl]);\n return sourceStatus;\n}\n"],"names":[],"mappings":";;;;AAiBO,SAAS,gBAAgB,MAAA,EAAmD;AAC/E,EAAA,MAAM,OAAO,OAAA,EAAQ;AACrB,EAAA,MAAM,YAAA,GAAe,oBAAoB,MAAoB;AACzD,IAAA,IAAI,CAAC,MAAA,EAAQ;AACT,MAAA,OAAO;AAAA,QACH,IAAA,EAAM,aAAA;AAAA,QACN,QAAQ,IAAA,CAAK,aAAA,CAAc,EAAE,EAAA,EAAI,sBAAsB;AAAA,OAC3D;AAAA,IACJ;AAEA,IAAA,MAAM,MAAA,GAAS,gBAAgB,MAAM,CAAA;AACrC,IAAA,IAAI,MAAA,CAAO,SAAS,WAAA,EAAa;AAC7B,MAAA,OAAO,MAAA;AAAA,IACX;AACA,IAAA,OAAO;AAAA,MACH,IAAA,EAAM,aAAA;AAAA,MACN,MAAA,EAAQ,OAAO,MAAA,IAAU,IAAA,CAAK,cAAc,EAAE,EAAA,EAAI,sBAAsB;AAAA,KAC5E;AAAA,EACJ,CAAA,EAAG,CAAC,MAAA,EAAQ,IAAI,CAAC,CAAA;AACjB,EAAA,OAAO,YAAA;AACX
|
|
1
|
+
{"version":3,"file":"useSourceStatus.js","sources":["useSourceStatus.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2023-2025 Open Pioneer project (https://github.com/open-pioneer)\n// SPDX-License-Identifier: Apache-2.0\n\nimport { useReactiveSnapshot } from \"@open-pioneer/reactivity\";\nimport { useIntl } from \"open-pioneer:react-hooks\";\nimport { SelectionSource } from \"../api\";\nimport { getSourceStatus } from \"../model\";\n\nexport type SimpleStatus =\n | {\n kind: \"available\";\n }\n | {\n kind: \"unavailable\";\n reason: string;\n };\n\nexport function useSourceStatus(source: SelectionSource | undefined): SimpleStatus {\n const intl = useIntl();\n const sourceStatus = useReactiveSnapshot((): SimpleStatus => {\n if (!source) {\n return {\n kind: \"unavailable\",\n reason: intl.formatMessage({ id: \"sourceNotAvailable\" })\n };\n }\n\n const status = getSourceStatus(source);\n if (status.kind === \"available\") {\n return status;\n }\n return {\n kind: \"unavailable\",\n reason: status.reason ?? intl.formatMessage({ id: \"sourceNotAvailable\" })\n };\n }, [source, intl]);\n return sourceStatus;\n}\n"],"names":[],"mappings":";;;;AAiBO,SAAS,gBAAgB,MAAA,EAAmD;AAC/E,EAAA,MAAM,OAAO,OAAA,EAAQ;AACrB,EAAA,MAAM,YAAA,GAAe,oBAAoB,MAAoB;AACzD,IAAA,IAAI,CAAC,MAAA,EAAQ;AACT,MAAA,OAAO;AAAA,QACH,IAAA,EAAM,aAAA;AAAA,QACN,QAAQ,IAAA,CAAK,aAAA,CAAc,EAAE,EAAA,EAAI,sBAAsB;AAAA,OAC3D;AAAA,IACJ;AAEA,IAAA,MAAM,MAAA,GAAS,gBAAgB,MAAM,CAAA;AACrC,IAAA,IAAI,MAAA,CAAO,SAAS,WAAA,EAAa;AAC7B,MAAA,OAAO,MAAA;AAAA,IACX;AACA,IAAA,OAAO;AAAA,MACH,IAAA,EAAM,aAAA;AAAA,MACN,MAAA,EAAQ,OAAO,MAAA,IAAU,IAAA,CAAK,cAAc,EAAE,EAAA,EAAI,sBAAsB;AAAA,KAC5E;AAAA,EACJ,CAAA,EAAG,CAAC,MAAA,EAAQ,IAAI,CAAC,CAAA;AACjB,EAAA,OAAO,YAAA;AACX;;"}
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import { jsx } from 'react/jsx-runtime';
|
|
2
|
-
import { Span } from '@chakra-ui/react';
|
|
3
|
-
|
|
4
|
-
function SelectionTooltipContent(props) {
|
|
5
|
-
const { content } = props;
|
|
6
|
-
return /* @__PURE__ */ jsx(Span, { children: content });
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
export { SelectionTooltipContent };
|
|
10
|
-
//# sourceMappingURL=SelectionTooltipContent.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"SelectionTooltipContent.js","sources":["SelectionTooltipContent.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 SelectionTooltipContent(props: { content?: ReactNode }) {\n const { content } = props;\n return <Span>{content}</Span>;\n}\n"],"names":[],"mappings":";;;AAMO,SAAS,wBAAwB,KAAA,EAAgC;AACpE,EAAA,MAAM,EAAE,SAAQ,GAAI,KAAA;AACpB,EAAA,uBAAO,GAAA,CAAC,QAAM,QAAA,EAAA,OAAA,EAAQ,CAAA;AAC1B;;;;"}
|