@open-pioneer/selection 0.1.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/package.json ADDED
@@ -0,0 +1,63 @@
1
+ {
2
+ "type": "module",
3
+ "name": "@open-pioneer/selection",
4
+ "version": "0.1.0",
5
+ "license": "Apache-2.0",
6
+ "peerDependencies": {
7
+ "@open-pioneer/chakra-integration": "^1.1.1",
8
+ "@open-pioneer/runtime": "^2.1.0",
9
+ "@open-pioneer/core": "^1.2.1",
10
+ "ol": "^8.2.0",
11
+ "react": "^18.2.0",
12
+ "classnames": "^2.3.2",
13
+ "chakra-react-select": "^4.7.6",
14
+ "@chakra-ui/icons": "^2.1.1",
15
+ "react-icons": "^4.12.0",
16
+ "@open-pioneer/map": "^0.3.0",
17
+ "@open-pioneer/notifier": "^0.3.0",
18
+ "@open-pioneer/react-utils": "^0.2.1"
19
+ },
20
+ "exports": {
21
+ "./package.json": "./package.json",
22
+ ".": {
23
+ "import": "./index.js",
24
+ "types": "./index.d.ts"
25
+ },
26
+ "./services": {
27
+ "import": "./services.js",
28
+ "types": "./services.d.ts"
29
+ },
30
+ "./selection.css": "./selection.css"
31
+ },
32
+ "openPioneerFramework": {
33
+ "styles": "./selection.css",
34
+ "services": [
35
+ {
36
+ "serviceName": "VectorSelectionSourceFactory",
37
+ "provides": [
38
+ {
39
+ "interfaceName": "selection.VectorSelectionSourceFactory"
40
+ }
41
+ ],
42
+ "references": []
43
+ }
44
+ ],
45
+ "servicesModule": "./services",
46
+ "i18n": {
47
+ "languages": [
48
+ "en",
49
+ "de"
50
+ ]
51
+ },
52
+ "ui": {
53
+ "references": [
54
+ {
55
+ "type": "unique",
56
+ "interfaceName": "notifier.NotificationService"
57
+ }
58
+ ]
59
+ },
60
+ "properties": [],
61
+ "packageFormatVersion": "1.0.0"
62
+ }
63
+ }
package/selection.css ADDED
@@ -0,0 +1,40 @@
1
+ .selection-drag-box {
2
+ background-color: rgba(255, 255, 255, 0.3) !important;
3
+ border: 3px solid var(--chakra-colors-background_primary) !important;
4
+ }
5
+
6
+ .selection-tooltip {
7
+ position: relative;
8
+ background: rgba(255, 255, 255, 0.8);
9
+ border-radius: 4px;
10
+ color: black;
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
+ .selection .react-select {
21
+ cursor: default;
22
+ }
23
+
24
+ .map-container .selection-active {
25
+ cursor: crosshair;
26
+ }
27
+
28
+ .map-container .selection-inactive {
29
+ cursor: no-drop;
30
+ }
31
+
32
+ .selection-source-value.selection-source-value--disabled {
33
+ opacity: 0.4;
34
+ }
35
+
36
+ .selection-source-value.selection-source-value--disabled span {
37
+ margin: 0px 6px 0px 0px;
38
+ }
39
+
40
+ /*# sourceMappingURL=selection.css.map */
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["selection.css"],"names":[],"mappings":"AAAA;IACI,qDAAqD;IACrD,oEAAoE;AACxE;;AAEA;IACI,kBAAkB;IAClB,oCAAoC;IACpC,kBAAkB;IAClB,YAAY;IACZ,gBAAgB;IAChB,UAAU;IACV,mBAAmB;IACnB,eAAe;IACf,eAAe;IACf,iBAAiB;IACjB,iBAAiB;AACrB;;AAEA;IACI,eAAe;AACnB;;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-background_primary) !important;\n}\n\n.selection-tooltip {\n position: relative;\n background: rgba(255, 255, 255, 0.8);\n border-radius: 4px;\n color: black;\n padding: 4px 8px;\n opacity: 1;\n white-space: nowrap;\n font-size: 12px;\n cursor: default;\n user-select: none;\n font-weight: bold;\n}\n\n.selection .react-select {\n cursor: default;\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"]}
@@ -0,0 +1,37 @@
1
+ import { SelectionSource, SelectionResult, SelectionOptions, SelectionSourceStatus, SelectionSourceEvents, SelectionKind, VectorLayerSelectionSource } from "./api";
2
+ import { Point } from "ol/geom";
3
+ import { EventEmitter } from "@open-pioneer/core";
4
+ import VectorSource from "ol/source/Vector";
5
+ import VectorLayer from "ol/layer/Vector";
6
+ export declare const fakeSelectedPointFeatures: Point[];
7
+ export declare class FakePointSelectionSource extends EventEmitter<SelectionSourceEvents> implements SelectionSource {
8
+ #private;
9
+ readonly label: string;
10
+ constructor(timeout?: number, status?: SelectionSourceStatus, pointFeatures?: Point[]);
11
+ get status(): SelectionSourceStatus;
12
+ set status(value: SelectionSourceStatus);
13
+ select(selectionKind: SelectionKind, options: SelectionOptions): Promise<SelectionResult[]>;
14
+ }
15
+ /**
16
+ * A SelectionSource to use an OpenLayers VectorLayer with an OpenLayers VectorSource (e.g. layer of the map).
17
+ * Features are:
18
+ * - using only the extent as selection kind
19
+ * - listening to layer visibility changes and updating the status of the source
20
+ * - limiting the number of returned selection results to the corresponding selection option
21
+ * - throwing an event `changed:status` when the status updates
22
+ */
23
+ export declare class VectorLayerSelectionSourceImpl extends EventEmitter<SelectionSourceEvents> implements VectorLayerSelectionSource {
24
+ #private;
25
+ readonly label: string;
26
+ constructor(vectorLayer: VectorLayer<VectorSource>, label: string, layerNotVisibleReason: string);
27
+ destroy(): void;
28
+ get status(): import("./api").SelectionSourceStatusObject;
29
+ select(selectionKind: SelectionKind, options: SelectionOptions): Promise<SelectionResult[]>;
30
+ }
31
+ /**
32
+ * For testing purposes only
33
+ */
34
+ export declare class NoStatusSelectionSource extends EventEmitter<SelectionSourceEvents> implements SelectionSource {
35
+ readonly label: string;
36
+ select(_: SelectionKind, __: SelectionOptions): Promise<SelectionResult[]>;
37
+ }
@@ -0,0 +1,64 @@
1
+ import { Point } from 'ol/geom';
2
+ import { EventEmitter } from '@open-pioneer/core';
3
+ import { unByKey } from 'ol/Observable';
4
+
5
+ [
6
+ new Point([407354, 5754673]),
7
+ // con terra (Bottom Right)
8
+ new Point([404740, 5757893])
9
+ // Schloss (Top Left)
10
+ ];
11
+ class VectorLayerSelectionSourceImpl extends EventEmitter {
12
+ label;
13
+ #status = { kind: "available" };
14
+ #vectorLayer;
15
+ #eventHandler;
16
+ #layerNotVisibleReason;
17
+ constructor(vectorLayer, label, layerNotVisibleReason) {
18
+ super();
19
+ this.label = label;
20
+ this.#vectorLayer = vectorLayer;
21
+ this.#layerNotVisibleReason = layerNotVisibleReason;
22
+ this.#updateStatus();
23
+ this.#eventHandler = this.#vectorLayer.on("change:visible", () => {
24
+ this.#updateStatus();
25
+ });
26
+ }
27
+ destroy() {
28
+ unByKey(this.#eventHandler);
29
+ }
30
+ get status() {
31
+ return this.#status;
32
+ }
33
+ async select(selectionKind, options) {
34
+ if (selectionKind.type !== "extent") {
35
+ throw new Error(`Unsupported selection kind: ${selectionKind.type}`);
36
+ }
37
+ if (this.#status.kind !== "available" || this.#vectorLayer.getSource() === null)
38
+ return [];
39
+ const allResults = [];
40
+ this.#vectorLayer.getSource().forEachFeatureIntersectingExtent(selectionKind.extent, (feature) => {
41
+ if (!feature.getGeometry())
42
+ return;
43
+ const result = {
44
+ id: feature.getId()?.toString() || feature.getGeometry.toString(),
45
+ geometry: feature.getGeometry()
46
+ };
47
+ allResults.push(result);
48
+ });
49
+ const selectedFeatures = allResults.filter((s) => s != null);
50
+ const limitedFeatures = selectedFeatures.length > options.maxResults ? selectedFeatures.slice(0, options.maxResults) : selectedFeatures;
51
+ return limitedFeatures;
52
+ }
53
+ #updateStatus() {
54
+ const layerIsVisible = this.#vectorLayer.getVisible();
55
+ const newStatus = layerIsVisible ? { kind: "available" } : { kind: "unavailable", reason: this.#layerNotVisibleReason };
56
+ if (newStatus.kind !== this.#status.kind) {
57
+ this.#status = newStatus;
58
+ this.emit("changed:status");
59
+ }
60
+ }
61
+ }
62
+
63
+ export { VectorLayerSelectionSourceImpl };
64
+ //# sourceMappingURL=selectionSources.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"selectionSources.js","sources":["selectionSources.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2023 Open Pioneer project (https://github.com/open-pioneer)\n// SPDX-License-Identifier: Apache-2.0\nimport {\n SelectionSource,\n SelectionResult,\n SelectionOptions,\n SelectionSourceStatus,\n SelectionSourceEvents,\n SelectionKind,\n VectorLayerSelectionSource\n} from \"./api\";\nimport { Point } from \"ol/geom\";\nimport { EventEmitter } from \"@open-pioneer/core\";\nimport VectorSource from \"ol/source/Vector\";\nimport VectorLayer from \"ol/layer/Vector\";\nimport { EventsKey } from \"ol/events\";\nimport { unByKey } from \"ol/Observable\";\n\nexport const fakeSelectedPointFeatures = [\n new Point([407354, 5754673]), // con terra (Bottom Right)\n new Point([404740, 5757893]) // Schloss (Top Left)\n];\n\nlet count = 0;\n\nexport class FakePointSelectionSource\n extends EventEmitter<SelectionSourceEvents>\n implements SelectionSource\n{\n readonly label = `Fake Selection Source #${++count}`;\n #timeout: number;\n #status: SelectionSourceStatus;\n #pointFeatures: Point[];\n\n constructor(\n timeout?: number,\n status?: SelectionSourceStatus,\n pointFeatures: Point[] = fakeSelectedPointFeatures\n ) {\n super();\n this.#timeout = timeout || 0;\n this.#status = status || \"unavailable\";\n this.#pointFeatures = pointFeatures;\n }\n\n get status(): SelectionSourceStatus {\n return this.#status;\n }\n\n set status(value: SelectionSourceStatus) {\n if (value !== this.#status) {\n this.#status = value;\n this.emit(\"changed:status\");\n }\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 !== \"available\") return [];\n\n await new Promise((resolve) => setTimeout(resolve, this.#timeout));\n\n const allPoints = this.#pointFeatures.map((point, index) => {\n const result: SelectionResult = {\n id: index,\n geometry: point\n };\n if (!point.intersectsExtent(selectionKind.extent)) {\n return undefined;\n }\n return result;\n });\n\n const selectedPoints = allPoints.filter((s): s is SelectionResult => s != null);\n const limitedResults =\n selectedPoints.length > options.maxResults\n ? selectedPoints.slice(0, options.maxResults)\n : selectedPoints;\n return limitedResults;\n }\n}\n\n/**\n * A SelectionSource to use an OpenLayers VectorLayer with an OpenLayers VectorSource (e.g. layer of the map).\n * Features are:\n * - using only the extent as selection kind\n * - listening to layer visibility changes and updating the status of the source\n * - limiting the number of returned selection results to the corresponding selection option\n * - throwing an event `changed:status` when the status updates\n */\nexport class VectorLayerSelectionSourceImpl\n extends EventEmitter<SelectionSourceEvents>\n implements VectorLayerSelectionSource\n{\n readonly label: string;\n #status: Exclude<SelectionSourceStatus, string> = { kind: \"available\" };\n #vectorLayer: VectorLayer<VectorSource>;\n #eventHandler: EventsKey;\n #layerNotVisibleReason: string;\n\n constructor(\n vectorLayer: VectorLayer<VectorSource>,\n label: string,\n layerNotVisibleReason: string\n ) {\n super();\n this.label = label;\n this.#vectorLayer = vectorLayer;\n this.#layerNotVisibleReason = layerNotVisibleReason;\n this.#updateStatus();\n this.#eventHandler = this.#vectorLayer.on(\"change:visible\", () => {\n this.#updateStatus();\n });\n }\n\n destroy() {\n unByKey(this.#eventHandler);\n }\n\n get status() {\n return this.#status;\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.kind !== \"available\" || this.#vectorLayer.getSource() === null) return [];\n\n const allResults: SelectionResult[] = [];\n this.#vectorLayer\n .getSource()!\n .forEachFeatureIntersectingExtent(selectionKind.extent, (feature) => {\n if (!feature.getGeometry()) return;\n const result: SelectionResult = {\n id: feature.getId()?.toString() || feature.getGeometry.toString(),\n geometry: feature.getGeometry()!\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 #updateStatus() {\n const layerIsVisible = this.#vectorLayer.getVisible();\n const newStatus: SelectionSourceStatus = layerIsVisible\n ? { kind: \"available\" }\n : { kind: \"unavailable\", reason: this.#layerNotVisibleReason };\n if (newStatus.kind !== this.#status.kind) {\n this.#status = newStatus;\n this.emit(\"changed:status\");\n }\n }\n}\n\n/**\n * For testing purposes only\n */\nexport class NoStatusSelectionSource\n extends EventEmitter<SelectionSourceEvents>\n implements SelectionSource\n{\n readonly label: string = \"Testlabel\";\n\n async select(_: SelectionKind, __: SelectionOptions): Promise<SelectionResult[]> {\n const allPoints = fakeSelectedPointFeatures.map((point, index) => {\n const result: SelectionResult = {\n id: index,\n geometry: point\n };\n return result;\n });\n return allPoints;\n }\n}\n"],"names":[],"mappings":"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"}
package/services.d.ts ADDED
@@ -0,0 +1,7 @@
1
+ import { type PackageIntl, ServiceOptions } from "@open-pioneer/runtime";
2
+ import { VectorLayerSelectionSource, VectorLayerSelectionSourceFactory, VectorLayerSelectionSourceOptions } from "./api";
3
+ export declare class VectorSelectionSourceFactory implements VectorLayerSelectionSourceFactory {
4
+ #private;
5
+ constructor({ intl }: ServiceOptions<PackageIntl>);
6
+ createSelectionSource(options: VectorLayerSelectionSourceOptions): VectorLayerSelectionSource;
7
+ }
package/services.js ADDED
@@ -0,0 +1,18 @@
1
+ import { VectorLayerSelectionSourceImpl } from './selectionSources.js';
2
+
3
+ class VectorSelectionSourceFactory {
4
+ #intl;
5
+ constructor({ intl }) {
6
+ this.#intl = intl;
7
+ }
8
+ createSelectionSource(options) {
9
+ return new VectorLayerSelectionSourceImpl(
10
+ options.vectorLayer,
11
+ options.label,
12
+ this.#intl.formatMessage({ id: "layerNotVisibleReason" })
13
+ );
14
+ }
15
+ }
16
+
17
+ export { VectorSelectionSourceFactory };
18
+ //# sourceMappingURL=services.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"services.js","sources":["services.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2023 Open Pioneer project (https://github.com/open-pioneer)\n// SPDX-License-Identifier: Apache-2.0\nimport { type PackageIntl, ServiceOptions } from \"@open-pioneer/runtime\";\nimport { VectorLayerSelectionSourceImpl } from \"./selectionSources\";\nimport {\n VectorLayerSelectionSource,\n VectorLayerSelectionSourceFactory,\n VectorLayerSelectionSourceOptions\n} from \"./api\";\n\nexport class VectorSelectionSourceFactory implements VectorLayerSelectionSourceFactory {\n #intl: PackageIntl;\n\n constructor({ intl }: ServiceOptions<PackageIntl>) {\n this.#intl = intl;\n }\n createSelectionSource(options: VectorLayerSelectionSourceOptions): VectorLayerSelectionSource {\n return new VectorLayerSelectionSourceImpl(\n options.vectorLayer,\n options.label,\n this.#intl.formatMessage({ id: \"layerNotVisibleReason\" })\n );\n }\n}\n"],"names":[],"mappings":";;AAUO,MAAM,4BAA0E,CAAA;AAAA,EACnF,KAAA,CAAA;AAAA,EAEA,WAAA,CAAY,EAAE,IAAA,EAAqC,EAAA;AAC/C,IAAA,IAAA,CAAK,KAAQ,GAAA,IAAA,CAAA;AAAA,GACjB;AAAA,EACA,sBAAsB,OAAwE,EAAA;AAC1F,IAAA,OAAO,IAAI,8BAAA;AAAA,MACP,OAAQ,CAAA,WAAA;AAAA,MACR,OAAQ,CAAA,KAAA;AAAA,MACR,KAAK,KAAM,CAAA,aAAA,CAAc,EAAE,EAAA,EAAI,yBAAyB,CAAA;AAAA,KAC5D,CAAA;AAAA,GACJ;AACJ;;;;"}