@open-pioneer/map 1.4.0-dev.20260625074633 → 1.4.0-dev.20260727093741
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 +8 -2
- package/MapRegistry.js +1 -1
- package/MapRegistry.js.map +1 -1
- package/README.md +8 -14
- package/_virtual/source-info.js +8 -6
- package/_virtual/source-info.js.map +1 -1
- package/layers/WMSLayer.js +1 -1
- package/layers/WMTSLayer.js +1 -1
- package/layers/wms/getLegendUrl.js +1 -1
- package/layers/wmts/getLegendUrl.js +1 -1
- package/model/createMapModel.js +21 -21
- package/model/createMapModel.js.map +1 -1
- package/package.json +10 -10
- package/ui/MapContainer.js +1 -1
- package/ui/hooks/useMapModel.d.ts +7 -0
- package/ui/hooks/useMapModel.js +10 -1
- package/ui/hooks/useMapModel.js.map +1 -1
- package/ui/styles.css +0 -2
- package/ui/styles.css.map +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,14 +1,20 @@
|
|
|
1
1
|
# @open-pioneer/map
|
|
2
2
|
|
|
3
|
-
## 1.4.0-dev.
|
|
3
|
+
## 1.4.0-dev.20260727093741
|
|
4
4
|
|
|
5
5
|
### Minor Changes
|
|
6
6
|
|
|
7
|
-
- c30396d: Update Chakra to 3.36.
|
|
7
|
+
- c30396d: Update Chakra to 3.36.1
|
|
8
|
+
- e4b47f1: `useMapModel` now prints an error message if the map model could not be created.
|
|
9
|
+
This error was previously returned and was easy to silently ignore.
|
|
10
|
+
|
|
11
|
+
Use the option `quiet: true` to suppress this error message.
|
|
12
|
+
|
|
8
13
|
- c9b3ced: Provide reactive rotation in MapModel
|
|
9
14
|
|
|
10
15
|
### Patch Changes
|
|
11
16
|
|
|
17
|
+
- 078bef5: Use private JavaScript properties (#) instead of TypeScript keyword.
|
|
12
18
|
- b58a50f: Use new `shallowEqual` function to compare attribution arrays.
|
|
13
19
|
|
|
14
20
|
## 1.3.0
|
package/MapRegistry.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { batch } from '@conterra/reactivity-core';
|
|
2
2
|
import { on } from '@conterra/reactivity-events';
|
|
3
3
|
import { createLogger } from '@open-pioneer/core';
|
|
4
|
-
import { sourceId$
|
|
4
|
+
import { sourceId$11 as sourceId } from './_virtual/source-info.js';
|
|
5
5
|
import { createMapModel } from './model/createMapModel.js';
|
|
6
6
|
|
|
7
7
|
const LOG = createLogger(sourceId);
|
package/MapRegistry.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MapRegistry.js","sources":["MapRegistry.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2023-2025 Open Pioneer project (https://github.com/open-pioneer)\n// SPDX-License-Identifier: Apache-2.0\nimport { batch, ReadonlyReactive } from \"@conterra/reactivity-core\";\nimport { on } from \"@conterra/reactivity-events\";\nimport { createLogger, Resource } from \"@open-pioneer/core\";\nimport { HttpService } from \"@open-pioneer/http\";\nimport {\n DECLARE_SERVICE_INTERFACE,\n PackageIntl,\n Service,\n ServiceOptions\n} from \"@open-pioneer/runtime\";\nimport OlMap from \"ol/Map\";\nimport { sourceId } from \"open-pioneer:source-info\";\nimport { LayerFactory } from \"./LayerFactory\";\nimport { createMapModel } from \"./model/createMapModel\";\nimport { MapConfig } from \"./model/MapConfig\";\nimport { MapModel } from \"./model/MapModel\";\n\nconst LOG = createLogger(sourceId);\n\n/**\n * Options passed to the {@link MapConfigProvider.getMapConfig} method.\n *\n * @group Services\n */\nexport interface MapConfigProviderOptions {\n /**\n * A reference to the layer factory, for the construction of new layer instances.\n */\n layerFactory: LayerFactory;\n}\n\n/**\n * Provides an OpenLayers map configuration with a given map id.\n *\n * The implementor must also provide the interface name `\"map.MapConfigProvider\"`.\n *\n * @group Services\n */\nexport interface MapConfigProvider {\n /**\n * Unique identifier of the map.\n */\n readonly mapId: string;\n\n /**\n * Returns the map configuration for this map.\n *\n * Called by the {@link MapRegistry} when the map is requested for the first time.\n *\n * See {@link MapConfig} for supported options during map creation.\n * Use {@link MapConfigProviderOptions.layerFactory} to construct new layers.\n */\n getMapConfig(options: MapConfigProviderOptions): Promise<MapConfig>;\n}\n\ninterface References {\n providers: MapConfigProvider[];\n httpService: HttpService;\n layerFactory: LayerFactory;\n}\n\ntype ModelJobResult =\n | { kind: \"model\"; model: MapModel; listener: Resource }\n | { kind: \"error\"; error: Error };\n\n/**\n * Provides access to registered map instances.\n *\n * Maps are identified by a unique id.\n *\n * Inject an instance of this service by referencing the interface name `\"map.MapRegistry\"`.\n *\n * @group Services\n */\nexport class MapRegistry implements Service {\n declare [DECLARE_SERVICE_INTERFACE]: \"map.MapRegistry\";\n\n #currentIntl: ReadonlyReactive<PackageIntl>;\n #httpService: HttpService;\n #layerFactory: LayerFactory;\n\n #configProviders = new Map<string, MapConfigProvider>();\n #entries = new Map<string, ModelJobResult>();\n #modelCreationJobs = new Map<string, Promise<ModelJobResult>>();\n #modelsByOlMap = new WeakMap<OlMap, MapModel>();\n #destroyed = false;\n\n constructor({ references, currentIntl }: ServiceOptions<References>) {\n this.#currentIntl = currentIntl;\n this.#httpService = references.httpService;\n this.#layerFactory = references.layerFactory;\n\n const providers = references.providers;\n for (const provider of providers) {\n this.#configProviders.set(provider.mapId, provider);\n }\n }\n\n destroy(): void {\n if (this.#destroyed) {\n return;\n }\n\n batch(() => {\n LOG.debug(`Destroy map registry and all maps`);\n this.#destroyed = true;\n this.#entries.forEach((entry) => {\n if (entry.kind === \"model\") {\n entry.listener.destroy();\n entry.model.destroy();\n }\n });\n this.#entries.clear();\n this.#modelCreationJobs.clear();\n });\n }\n\n /**\n * Returns the map model associated with the given id.\n * Returns undefined if there is no such model.\n */\n async getMapModel(mapId: string): Promise<MapModel | undefined> {\n if (this.#destroyed) {\n throw new Error(\"MapRegistry has already been destroyed.\");\n }\n\n const entry = this.#entries.get(mapId);\n if (entry) {\n return unbox(entry);\n }\n\n const creationJob = this.#modelCreationJobs.get(mapId);\n if (creationJob) {\n return await waitForResult(creationJob);\n }\n\n const provider = this.#configProviders.get(mapId);\n if (!provider) {\n LOG.debug(`Failed to find a config provider for map id '${mapId}'.`);\n return undefined;\n }\n\n return await this.#createMapModel(mapId, () =>\n provider.getMapConfig({\n layerFactory: this.#layerFactory\n })\n );\n }\n\n /**\n * Like {@link getMapModel}, but throws if no model exists for the given `mapId`.\n */\n async expectMapModel(mapId: string): Promise<MapModel> {\n const model = await this.getMapModel(mapId);\n if (!model) {\n throw new Error(`No configuration available for map with id '${mapId}'.`);\n }\n return model;\n }\n\n /**\n * Creates a MapModel without the need to provide a {@link MapConfigProvider}.\n * Throws an error if a map with the given id already exists or if the map config is invalid.\n */\n async createMapModel(mapId: string, options?: MapConfig): Promise<MapModel> {\n if (this.#destroyed) {\n throw new Error(\"MapRegistry has already been destroyed.\");\n }\n if (this.#entries.has(mapId)) {\n throw new Error(`Map id '${mapId}' is not unique.`);\n }\n if (this.#modelCreationJobs.has(mapId)) {\n throw new Error(`A map with the id '${mapId}' is already under construction.`);\n }\n return await this.#createMapModel(mapId, () => Promise.resolve(options ?? {}));\n }\n\n /**\n * Given a raw OpenLayers map instance, returns the associated {@link MapModel} - or undefined\n * if the map is unknown to this registry.\n *\n * All OpenLayers maps created by this registry (e.g. via {@link MapConfigProvider} or {@link createMapModel}) have an associated map model.\n */\n getMapModelByRawInstance(olMap: OlMap): MapModel | undefined {\n return this.#modelsByOlMap.get(olMap);\n }\n\n // Wrapper method to ensure that in-progress construction of maps can be observed.\n #createMapModel(mapId: string, configProvider: () => Promise<MapConfig>): Promise<MapModel> {\n const creationJob = this.#modelCreationJobs.get(mapId);\n if (creationJob) {\n throw new Error(\"Internal error: a map model is already being created for this mapId\");\n }\n\n const modelPromise = this.#createMapModelImpl(mapId, configProvider)\n .then((mapModel) => {\n if (this.#destroyed) {\n mapModel.destroy();\n throw new Error(`MapRegistry has been destroyed.`);\n }\n\n const listener = on(\n mapModel.destroyed,\n () => {\n // Allow id reuse for dynamically created maps\n if (this.#isDynamic(mapId)) {\n const currentEntry = this.#entries.get(mapId);\n if (currentEntry === entry) {\n this.#entries.delete(mapId);\n }\n }\n },\n { dispatch: \"sync\" }\n );\n\n const entry: ModelJobResult = { kind: \"model\", model: mapModel, listener };\n this.#entries.set(mapId, entry);\n this.#modelCreationJobs.delete(mapId);\n this.#modelsByOlMap.set(mapModel.olMap, mapModel);\n return entry;\n })\n .catch((cause) => {\n const error = new Error(`Failed to construct map '${mapId}'`, { cause });\n const entry: ModelJobResult = { kind: \"error\", error };\n this.#modelCreationJobs.delete(mapId);\n if (!this.#isDynamic(mapId)) {\n // Don't store errors for dynamically created maps (the caller already got the error via promise).\n this.#entries.set(mapId, entry);\n }\n return entry;\n });\n this.#modelCreationJobs.set(mapId, modelPromise);\n return waitForResult(modelPromise);\n }\n\n async #createMapModelImpl(\n mapId: string,\n configProvider: () => Promise<MapConfig>\n ): Promise<MapModel> {\n LOG.info(`Creating map with id '${mapId}'`);\n const mapConfig = await configProvider();\n const mapModel = await createMapModel(\n mapId,\n mapConfig,\n this.#currentIntl,\n this.#httpService\n );\n return mapModel;\n }\n\n #isDynamic(mapId: string): boolean {\n return !this.#configProviders.has(mapId);\n }\n}\n\nasync function waitForResult(job: Promise<ModelJobResult>): Promise<MapModel> {\n return unbox(await job);\n}\n\nfunction unbox(entry: ModelJobResult): MapModel {\n if (entry.kind === \"error\") {\n throw entry.error;\n }\n return entry.model;\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"MapRegistry.js","sources":["MapRegistry.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2023-2025 Open Pioneer project (https://github.com/open-pioneer)\n// SPDX-License-Identifier: Apache-2.0\nimport { batch, ReadonlyReactive } from \"@conterra/reactivity-core\";\nimport { on } from \"@conterra/reactivity-events\";\nimport { createLogger, Resource } from \"@open-pioneer/core\";\nimport { HttpService } from \"@open-pioneer/http\";\nimport {\n DECLARE_SERVICE_INTERFACE,\n PackageIntl,\n Service,\n ServiceOptions\n} from \"@open-pioneer/runtime\";\nimport OlMap from \"ol/Map\";\nimport { sourceId } from \"open-pioneer:source-info\";\nimport { LayerFactory } from \"./LayerFactory\";\nimport { createMapModel } from \"./model/createMapModel\";\nimport { MapConfig } from \"./model/MapConfig\";\nimport { MapModel } from \"./model/MapModel\";\n\nconst LOG = createLogger(sourceId);\n\n/**\n * Options passed to the {@link MapConfigProvider.getMapConfig} method.\n *\n * @group Services\n */\nexport interface MapConfigProviderOptions {\n /**\n * A reference to the layer factory, for the construction of new layer instances.\n */\n layerFactory: LayerFactory;\n}\n\n/**\n * Provides an OpenLayers map configuration with a given map id.\n *\n * The implementor must also provide the interface name `\"map.MapConfigProvider\"`.\n *\n * @group Services\n */\nexport interface MapConfigProvider {\n /**\n * Unique identifier of the map.\n */\n readonly mapId: string;\n\n /**\n * Returns the map configuration for this map.\n *\n * Called by the {@link MapRegistry} when the map is requested for the first time.\n *\n * See {@link MapConfig} for supported options during map creation.\n * Use {@link MapConfigProviderOptions.layerFactory} to construct new layers.\n */\n getMapConfig(options: MapConfigProviderOptions): Promise<MapConfig>;\n}\n\ninterface References {\n providers: MapConfigProvider[];\n httpService: HttpService;\n layerFactory: LayerFactory;\n}\n\ntype ModelJobResult =\n { kind: \"model\"; model: MapModel; listener: Resource } | { kind: \"error\"; error: Error };\n\n/**\n * Provides access to registered map instances.\n *\n * Maps are identified by a unique id.\n *\n * Inject an instance of this service by referencing the interface name `\"map.MapRegistry\"`.\n *\n * @group Services\n */\nexport class MapRegistry implements Service {\n declare [DECLARE_SERVICE_INTERFACE]: \"map.MapRegistry\";\n\n #currentIntl: ReadonlyReactive<PackageIntl>;\n #httpService: HttpService;\n #layerFactory: LayerFactory;\n\n #configProviders = new Map<string, MapConfigProvider>();\n #entries = new Map<string, ModelJobResult>();\n #modelCreationJobs = new Map<string, Promise<ModelJobResult>>();\n #modelsByOlMap = new WeakMap<OlMap, MapModel>();\n #destroyed = false;\n\n constructor({ references, currentIntl }: ServiceOptions<References>) {\n this.#currentIntl = currentIntl;\n this.#httpService = references.httpService;\n this.#layerFactory = references.layerFactory;\n\n const providers = references.providers;\n for (const provider of providers) {\n this.#configProviders.set(provider.mapId, provider);\n }\n }\n\n destroy(): void {\n if (this.#destroyed) {\n return;\n }\n\n batch(() => {\n LOG.debug(`Destroy map registry and all maps`);\n this.#destroyed = true;\n this.#entries.forEach((entry) => {\n if (entry.kind === \"model\") {\n entry.listener.destroy();\n entry.model.destroy();\n }\n });\n this.#entries.clear();\n this.#modelCreationJobs.clear();\n });\n }\n\n /**\n * Returns the map model associated with the given id.\n * Returns undefined if there is no such model.\n */\n async getMapModel(mapId: string): Promise<MapModel | undefined> {\n if (this.#destroyed) {\n throw new Error(\"MapRegistry has already been destroyed.\");\n }\n\n const entry = this.#entries.get(mapId);\n if (entry) {\n return unbox(entry);\n }\n\n const creationJob = this.#modelCreationJobs.get(mapId);\n if (creationJob) {\n return await waitForResult(creationJob);\n }\n\n const provider = this.#configProviders.get(mapId);\n if (!provider) {\n LOG.debug(`Failed to find a config provider for map id '${mapId}'.`);\n return undefined;\n }\n\n return await this.#createMapModel(mapId, () =>\n provider.getMapConfig({\n layerFactory: this.#layerFactory\n })\n );\n }\n\n /**\n * Like {@link getMapModel}, but throws if no model exists for the given `mapId`.\n */\n async expectMapModel(mapId: string): Promise<MapModel> {\n const model = await this.getMapModel(mapId);\n if (!model) {\n throw new Error(`No configuration available for map with id '${mapId}'.`);\n }\n return model;\n }\n\n /**\n * Creates a MapModel without the need to provide a {@link MapConfigProvider}.\n * Throws an error if a map with the given id already exists or if the map config is invalid.\n */\n async createMapModel(mapId: string, options?: MapConfig): Promise<MapModel> {\n if (this.#destroyed) {\n throw new Error(\"MapRegistry has already been destroyed.\");\n }\n if (this.#entries.has(mapId)) {\n throw new Error(`Map id '${mapId}' is not unique.`);\n }\n if (this.#modelCreationJobs.has(mapId)) {\n throw new Error(`A map with the id '${mapId}' is already under construction.`);\n }\n return await this.#createMapModel(mapId, () => Promise.resolve(options ?? {}));\n }\n\n /**\n * Given a raw OpenLayers map instance, returns the associated {@link MapModel} - or undefined\n * if the map is unknown to this registry.\n *\n * All OpenLayers maps created by this registry (e.g. via {@link MapConfigProvider} or {@link createMapModel}) have an associated map model.\n */\n getMapModelByRawInstance(olMap: OlMap): MapModel | undefined {\n return this.#modelsByOlMap.get(olMap);\n }\n\n // Wrapper method to ensure that in-progress construction of maps can be observed.\n #createMapModel(mapId: string, configProvider: () => Promise<MapConfig>): Promise<MapModel> {\n const creationJob = this.#modelCreationJobs.get(mapId);\n if (creationJob) {\n throw new Error(\"Internal error: a map model is already being created for this mapId\");\n }\n\n const modelPromise = this.#createMapModelImpl(mapId, configProvider)\n .then((mapModel) => {\n if (this.#destroyed) {\n mapModel.destroy();\n throw new Error(`MapRegistry has been destroyed.`);\n }\n\n const listener = on(\n mapModel.destroyed,\n () => {\n // Allow id reuse for dynamically created maps\n if (this.#isDynamic(mapId)) {\n const currentEntry = this.#entries.get(mapId);\n if (currentEntry === entry) {\n this.#entries.delete(mapId);\n }\n }\n },\n { dispatch: \"sync\" }\n );\n\n const entry: ModelJobResult = { kind: \"model\", model: mapModel, listener };\n this.#entries.set(mapId, entry);\n this.#modelCreationJobs.delete(mapId);\n this.#modelsByOlMap.set(mapModel.olMap, mapModel);\n return entry;\n })\n .catch((cause) => {\n const error = new Error(`Failed to construct map '${mapId}'`, { cause });\n const entry: ModelJobResult = { kind: \"error\", error };\n this.#modelCreationJobs.delete(mapId);\n if (!this.#isDynamic(mapId)) {\n // Don't store errors for dynamically created maps (the caller already got the error via promise).\n this.#entries.set(mapId, entry);\n }\n return entry;\n });\n this.#modelCreationJobs.set(mapId, modelPromise);\n return waitForResult(modelPromise);\n }\n\n async #createMapModelImpl(\n mapId: string,\n configProvider: () => Promise<MapConfig>\n ): Promise<MapModel> {\n LOG.info(`Creating map with id '${mapId}'`);\n const mapConfig = await configProvider();\n const mapModel = await createMapModel(\n mapId,\n mapConfig,\n this.#currentIntl,\n this.#httpService\n );\n return mapModel;\n }\n\n #isDynamic(mapId: string): boolean {\n return !this.#configProviders.has(mapId);\n }\n}\n\nasync function waitForResult(job: Promise<ModelJobResult>): Promise<MapModel> {\n return unbox(await job);\n}\n\nfunction unbox(entry: ModelJobResult): MapModel {\n if (entry.kind === \"error\") {\n throw entry.error;\n }\n return entry.model;\n}\n"],"names":[],"mappings":"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"}
|
package/README.md
CHANGED
|
@@ -149,13 +149,9 @@ export class AppModel implements Service {
|
|
|
149
149
|
declare [DECLARE_SERVICE_INTERFACE]: "example.AppModel";
|
|
150
150
|
constructor({ references }: ServiceOptions<References>) {
|
|
151
151
|
this._mapRegistry = references.mapRegistry;
|
|
152
|
-
this._mapRegistry
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
})
|
|
156
|
-
.then((map) => {
|
|
157
|
-
// use the map model instance
|
|
158
|
-
});
|
|
152
|
+
this._mapRegistry.createMapModel("myMapModelId", {/* map config */}).then((map) => {
|
|
153
|
+
// use the map model instance
|
|
154
|
+
});
|
|
159
155
|
}
|
|
160
156
|
}
|
|
161
157
|
```
|
|
@@ -193,9 +189,7 @@ import { MapConfig, MapConfigProvider } from "@open-pioneer/map";
|
|
|
193
189
|
|
|
194
190
|
export class MapConfigProviderImpl implements MapConfigProvider {
|
|
195
191
|
async getMapConfig(): Promise<MapConfig> {
|
|
196
|
-
return {
|
|
197
|
-
/* map config */
|
|
198
|
-
};
|
|
192
|
+
return {/* map config */};
|
|
199
193
|
}
|
|
200
194
|
}
|
|
201
195
|
```
|
|
@@ -995,19 +989,19 @@ interface References {
|
|
|
995
989
|
}
|
|
996
990
|
|
|
997
991
|
export class TestService {
|
|
998
|
-
|
|
992
|
+
#registry: MapRegistry;
|
|
999
993
|
|
|
1000
994
|
constructor(options: ServiceOptions<References>) {
|
|
1001
|
-
this
|
|
995
|
+
this.#registry = options.references.mapRegistry;
|
|
1002
996
|
}
|
|
1003
997
|
|
|
1004
998
|
async centerBerlin() {
|
|
1005
|
-
const model = await this
|
|
999
|
+
const model = await this.#registry.getMapModel(MAP_ID);
|
|
1006
1000
|
model?.olMap?.getView().fit([1489200, 6894026, 1489200, 6894026], { maxZoom: 13 });
|
|
1007
1001
|
}
|
|
1008
1002
|
|
|
1009
1003
|
async setLayerVisible() {
|
|
1010
|
-
const model = await this
|
|
1004
|
+
const model = await this.#registry.getMapModel(MAP_ID);
|
|
1011
1005
|
const layer = model?.layers.getLayerById("abe0e3f8-0ba2-409c-b6b4-9d8429c732e3");
|
|
1012
1006
|
layer?.setVisible(true);
|
|
1013
1007
|
}
|
package/_virtual/source-info.js
CHANGED
|
@@ -1,12 +1,14 @@
|
|
|
1
|
-
const sourceId$
|
|
1
|
+
const sourceId$b = "@open-pioneer/map/ui/MapContainer";
|
|
2
2
|
|
|
3
|
-
const sourceId$
|
|
3
|
+
const sourceId$a = "@open-pioneer/map/model/MapModel";
|
|
4
4
|
|
|
5
|
-
const sourceId$
|
|
5
|
+
const sourceId$9 = "@open-pioneer/map/layers/AbstractLayer";
|
|
6
6
|
|
|
7
|
-
const sourceId$
|
|
7
|
+
const sourceId$8 = "@open-pioneer/map/model/LayerCollection";
|
|
8
8
|
|
|
9
|
-
const sourceId$
|
|
9
|
+
const sourceId$7 = "@open-pioneer/map/model/Overlays";
|
|
10
|
+
|
|
11
|
+
const sourceId$6 = "@open-pioneer/map/ui/hooks/useMapModel";
|
|
10
12
|
|
|
11
13
|
const sourceId$5 = "@open-pioneer/map/layers/WMSLayer";
|
|
12
14
|
|
|
@@ -20,5 +22,5 @@ const sourceId$1 = "@open-pioneer/map/MapRegistry";
|
|
|
20
22
|
|
|
21
23
|
const sourceId = "@open-pioneer/map/model/createMapModel";
|
|
22
24
|
|
|
23
|
-
export { sourceId$
|
|
25
|
+
export { sourceId$9 as sourceId, sourceId$8 as sourceId$1, sourceId as sourceId$10, sourceId$1 as sourceId$11, sourceId$7 as sourceId$2, sourceId$a as sourceId$3, sourceId$6 as sourceId$4, sourceId$b as sourceId$5, sourceId$4 as sourceId$6, sourceId$5 as sourceId$7, sourceId$2 as sourceId$8, sourceId$3 as sourceId$9 };
|
|
24
26
|
//# sourceMappingURL=source-info.js.map
|
|
@@ -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/layers/WMSLayer.js
CHANGED
|
@@ -3,7 +3,7 @@ import { createLogger, deprecated, destroyResource, isAbortError } from '@open-p
|
|
|
3
3
|
import WMSCapabilities from 'ol/format/WMSCapabilities.js';
|
|
4
4
|
import ImageLayer from 'ol/layer/Image.js';
|
|
5
5
|
import ImageWMS from 'ol/source/ImageWMS.js';
|
|
6
|
-
import { sourceId$
|
|
6
|
+
import { sourceId$7 as sourceId } from '../_virtual/source-info.js';
|
|
7
7
|
import { fetchText } from '../utils/fetch.js';
|
|
8
8
|
import { INTERNAL_CONSTRUCTOR_TAG } from '../utils/InternalConstructorTag.js';
|
|
9
9
|
import { AbstractLayer } from './AbstractLayer.js';
|
package/layers/WMTSLayer.js
CHANGED
|
@@ -5,7 +5,7 @@ import TileState from 'ol/TileState.js';
|
|
|
5
5
|
import WMTSCapabilities from 'ol/format/WMTSCapabilities.js';
|
|
6
6
|
import TileLayer from 'ol/layer/Tile.js';
|
|
7
7
|
import WMTS, { optionsFromCapabilities } from 'ol/source/WMTS.js';
|
|
8
|
-
import { sourceId$
|
|
8
|
+
import { sourceId$9 as sourceId } from '../_virtual/source-info.js';
|
|
9
9
|
import { fetchText } from '../utils/fetch.js';
|
|
10
10
|
import { AbstractLayer } from './AbstractLayer.js';
|
|
11
11
|
import { ATTACH_TO_MAP, GET_DEPS } from './shared/internals.js';
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { createLogger } from '@open-pioneer/core';
|
|
2
|
-
import { sourceId$
|
|
2
|
+
import { sourceId$6 as sourceId } from '../../_virtual/source-info.js';
|
|
3
3
|
|
|
4
4
|
const LOG = createLogger(sourceId);
|
|
5
5
|
function getLegendUrl(capabilities, layerName) {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { createLogger } from '@open-pioneer/core';
|
|
2
|
-
import { sourceId$
|
|
2
|
+
import { sourceId$8 as sourceId } from '../../_virtual/source-info.js';
|
|
3
3
|
|
|
4
4
|
const LOG = createLogger(sourceId);
|
|
5
5
|
function getLegendUrl(capabilities, activeLayerId, activeStyleId) {
|
package/model/createMapModel.js
CHANGED
|
@@ -7,7 +7,7 @@ import { defaults, DragZoom } from 'ol/interaction.js';
|
|
|
7
7
|
import TileLayer from 'ol/layer/Tile.js';
|
|
8
8
|
import { get } from 'ol/proj.js';
|
|
9
9
|
import OSM from 'ol/source/OSM.js';
|
|
10
|
-
import { sourceId$
|
|
10
|
+
import { sourceId$10 as sourceId } from '../_virtual/source-info.js';
|
|
11
11
|
import { INTERNAL_CONSTRUCTOR_TAG } from '../utils/InternalConstructorTag.js';
|
|
12
12
|
import { patchOpenLayersClassesForTesting } from '../utils/ol-test-support.js';
|
|
13
13
|
import { registerProjections } from '../utils/projections.js';
|
|
@@ -22,19 +22,19 @@ async function createMapModel(mapId, mapConfig, currentIntl, httpService) {
|
|
|
22
22
|
return await new MapModelFactory(mapId, mapConfig, currentIntl, httpService).createMapModel();
|
|
23
23
|
}
|
|
24
24
|
class MapModelFactory {
|
|
25
|
-
mapId;
|
|
26
|
-
mapConfig;
|
|
27
|
-
currentIntl;
|
|
28
|
-
httpService;
|
|
25
|
+
#mapId;
|
|
26
|
+
#mapConfig;
|
|
27
|
+
#currentIntl;
|
|
28
|
+
#httpService;
|
|
29
29
|
constructor(mapId, mapConfig, currentIntl, httpService) {
|
|
30
|
-
this
|
|
31
|
-
this
|
|
32
|
-
this
|
|
33
|
-
this
|
|
30
|
+
this.#mapId = mapId;
|
|
31
|
+
this.#mapConfig = mapConfig;
|
|
32
|
+
this.#currentIntl = currentIntl;
|
|
33
|
+
this.#httpService = httpService;
|
|
34
34
|
}
|
|
35
35
|
async createMapModel() {
|
|
36
|
-
const mapId = this
|
|
37
|
-
const mapConfig = this
|
|
36
|
+
const mapId = this.#mapId;
|
|
37
|
+
const mapConfig = this.#mapConfig;
|
|
38
38
|
const { view: viewOption, ...rawOlOptions } = mapConfig.advanced ?? {};
|
|
39
39
|
const showDefaultAttributions = mapConfig.showAttributions ?? (rawOlOptions.controls ? false : true);
|
|
40
40
|
const mapOptions = {
|
|
@@ -56,7 +56,7 @@ class MapModelFactory {
|
|
|
56
56
|
}).extend([new DragZoom({ out: true, condition: shiftCtrlKeysOnly })]);
|
|
57
57
|
}
|
|
58
58
|
const view = await viewOption ?? {};
|
|
59
|
-
this
|
|
59
|
+
this.#initializeViewOptions(view);
|
|
60
60
|
mapOptions.view = view instanceof View ? view : new View(view);
|
|
61
61
|
if (!mapOptions.layers && !mapConfig.layers) {
|
|
62
62
|
mapOptions.layers = [
|
|
@@ -78,8 +78,8 @@ class MapModelFactory {
|
|
|
78
78
|
olMap,
|
|
79
79
|
initialExtent,
|
|
80
80
|
showDefaultAttributions,
|
|
81
|
-
currentIntl: this
|
|
82
|
-
httpService: this
|
|
81
|
+
currentIntl: this.#currentIntl,
|
|
82
|
+
httpService: this.#httpService
|
|
83
83
|
},
|
|
84
84
|
INTERNAL_CONSTRUCTOR_TAG
|
|
85
85
|
);
|
|
@@ -97,9 +97,9 @@ class MapModelFactory {
|
|
|
97
97
|
}
|
|
98
98
|
});
|
|
99
99
|
}
|
|
100
|
-
initializeViewOptions(view) {
|
|
101
|
-
const mapId = this
|
|
102
|
-
const mapConfig = this
|
|
100
|
+
#initializeViewOptions(view) {
|
|
101
|
+
const mapId = this.#mapId;
|
|
102
|
+
const mapConfig = this.#mapConfig;
|
|
103
103
|
if (view instanceof View) {
|
|
104
104
|
const warn = (prop) => {
|
|
105
105
|
LOG.warn(
|
|
@@ -115,7 +115,7 @@ Use ViewOptions instead of a View instance.`
|
|
|
115
115
|
}
|
|
116
116
|
return;
|
|
117
117
|
}
|
|
118
|
-
const projection = view.projection = this
|
|
118
|
+
const projection = view.projection = this.#initializeProjection(mapConfig.projection);
|
|
119
119
|
const initialView = mapConfig.initialView;
|
|
120
120
|
if (initialView) {
|
|
121
121
|
switch (initialView.kind) {
|
|
@@ -134,10 +134,10 @@ Use ViewOptions instead of a View instance.`
|
|
|
134
134
|
}
|
|
135
135
|
}
|
|
136
136
|
} else {
|
|
137
|
-
this
|
|
137
|
+
this.#setViewDefaults(view, projection);
|
|
138
138
|
}
|
|
139
139
|
}
|
|
140
|
-
setViewDefaults(view, projection) {
|
|
140
|
+
#setViewDefaults(view, projection) {
|
|
141
141
|
if (view.center == null) {
|
|
142
142
|
const extent = projection.getExtent();
|
|
143
143
|
if (!extent) {
|
|
@@ -153,7 +153,7 @@ Try to configure 'initialView' explicity.`
|
|
|
153
153
|
view.zoom = 0;
|
|
154
154
|
}
|
|
155
155
|
}
|
|
156
|
-
initializeProjection(projectionOption) {
|
|
156
|
+
#initializeProjection(projectionOption) {
|
|
157
157
|
if (projectionOption == null) {
|
|
158
158
|
return get("EPSG:3857");
|
|
159
159
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"createMapModel.js","sources":["createMapModel.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2023-2025 Open Pioneer project (https://github.com/open-pioneer)\n// SPDX-License-Identifier: Apache-2.0\nimport { batch, ReadonlyReactive } from \"@conterra/reactivity-core\";\nimport { createLogger } from \"@open-pioneer/core\";\nimport { HttpService } from \"@open-pioneer/http\";\nimport { PackageIntl } from \"@open-pioneer/runtime\";\nimport { MapBrowserEvent } from \"ol\";\nimport OlMap, { MapOptions } from \"ol/Map\";\nimport View, { ViewOptions } from \"ol/View\";\nimport { getCenter } from \"ol/extent\";\nimport { DragZoom, defaults as defaultInteractions } from \"ol/interaction\";\nimport TileLayer from \"ol/layer/Tile\";\nimport { Projection, get as getProjection } from \"ol/proj\";\nimport OSM from \"ol/source/OSM\";\nimport { sourceId } from \"open-pioneer:source-info\";\nimport { INTERNAL_CONSTRUCTOR_TAG } from \"../utils/InternalConstructorTag\";\nimport { patchOpenLayersClassesForTesting } from \"../utils/ol-test-support\";\nimport { registerProjections } from \"../utils/projections\";\nimport { MapConfig } from \"./MapConfig\";\nimport { MapModel } from \"./MapModel\";\n\n/**\n * Register custom projection to the global proj4js definitions. User can select `EPSG:25832`\n * and `EPSG:25833` from the predefined projections without calling `registerProjections`.\n */\nregisterProjections({\n \"EPSG:25832\":\n \"+proj=utm +zone=32 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs +type=crs\",\n \"EPSG:25833\":\n \"+proj=utm +zone=33 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs +type=crs\"\n});\nconst LOG = createLogger(sourceId);\n\nexport async function createMapModel(\n mapId: string,\n mapConfig: MapConfig,\n currentIntl: ReadonlyReactive<PackageIntl>,\n httpService: HttpService\n): Promise<MapModel> {\n return await new MapModelFactory(mapId, mapConfig, currentIntl, httpService).createMapModel();\n}\n\nclass MapModelFactory {\n private mapId: string;\n private mapConfig: MapConfig;\n private currentIntl: ReadonlyReactive<PackageIntl>;\n private httpService: HttpService;\n\n constructor(\n mapId: string,\n mapConfig: MapConfig,\n currentIntl: ReadonlyReactive<PackageIntl>,\n httpService: HttpService\n ) {\n this.mapId = mapId;\n this.mapConfig = mapConfig;\n this.currentIntl = currentIntl;\n this.httpService = httpService;\n }\n\n async createMapModel() {\n const mapId = this.mapId;\n const mapConfig = this.mapConfig;\n const { view: viewOption, ...rawOlOptions } = mapConfig.advanced ?? {};\n const showDefaultAttributions =\n mapConfig.showAttributions ?? (rawOlOptions.controls ? false : true);\n\n const mapOptions: MapOptions = {\n ...rawOlOptions\n };\n if (!mapOptions.controls) {\n mapOptions.controls = [];\n }\n if (!mapOptions.interactions) {\n const shiftCtrlKeysOnly = (\n mapBrowserEvent: MapBrowserEvent<KeyboardEvent | WheelEvent | PointerEvent>\n ) => {\n const originalEvent = mapBrowserEvent.originalEvent;\n return (originalEvent.metaKey || originalEvent.ctrlKey) && originalEvent.shiftKey;\n };\n\n // setting altShiftDragRotate to false disables or excludes DragRotate interaction\n mapOptions.interactions = defaultInteractions({\n dragPan: true,\n altShiftDragRotate: false,\n pinchRotate: false,\n mouseWheelZoom: true\n }).extend([new DragZoom({ out: true, condition: shiftCtrlKeysOnly })]);\n }\n\n const view = (await viewOption) ?? {};\n this.initializeViewOptions(view);\n mapOptions.view = view instanceof View ? view : new View(view);\n\n if (!mapOptions.layers && !mapConfig.layers) {\n mapOptions.layers = [\n new TileLayer({\n source: new OSM()\n })\n ];\n }\n\n const initialView = mapConfig.initialView;\n const initialExtent = initialView?.kind === \"extent\" ? initialView.extent : undefined;\n\n LOG.debug(`Constructing OpenLayers map with options`, mapOptions);\n\n if (import.meta.env.VITEST) {\n patchOpenLayersClassesForTesting();\n }\n\n const olMap = new OlMap(mapOptions);\n const mapModel = new MapModel(\n {\n id: mapId,\n olMap,\n initialExtent,\n showDefaultAttributions,\n currentIntl: this.currentIntl,\n httpService: this.httpService\n },\n INTERNAL_CONSTRUCTOR_TAG\n );\n\n return batch(() => {\n try {\n if (mapConfig.layers) {\n for (const layerConfig of mapConfig.layers) {\n mapModel.layers.addLayer(layerConfig);\n }\n }\n return mapModel;\n } catch (e) {\n mapModel.destroy();\n throw e;\n }\n });\n }\n\n private initializeViewOptions(view: View | ViewOptions) {\n const mapId = this.mapId;\n const mapConfig = this.mapConfig;\n if (view instanceof View) {\n const warn = (prop: string) => {\n LOG.warn(\n `The advanced configuration for map id '${mapId}' has provided a fully constructed view instance: ${prop} cannot be applied.\\n` +\n `Use ViewOptions instead of a View instance.`\n );\n };\n\n if (mapConfig.projection != null) {\n warn(\"projection\");\n }\n if (mapConfig.initialView != null) {\n warn(\"initialView\");\n }\n return;\n }\n\n const projection = (view.projection = this.initializeProjection(mapConfig.projection));\n const initialView = mapConfig.initialView;\n if (initialView) {\n switch (initialView.kind) {\n case \"position\":\n view.zoom = initialView.zoom;\n view.center = [initialView.center.x, initialView.center.y];\n break;\n case \"extent\": {\n /*\n OpenLayers does not support configuration of the initial map extent.\n The only relevant options here are center, zoom (and resolution).\n We must set those values because otherwise OpenLayers will not initialize layer sources.\n\n The actual initial extent is applied once tha map has loaded and its size is known.\n */\n const extent = initialView.extent;\n view.zoom = 0;\n view.center = [\n extent.xMin + (extent.xMax - extent.xMin) / 2,\n extent.yMin + (extent.yMax - extent.yMin) / 2\n ];\n break;\n }\n }\n } else {\n this.setViewDefaults(view, projection);\n }\n }\n\n private setViewDefaults(view: ViewOptions, projection: Projection) {\n if (view.center == null) {\n const extent = projection.getExtent(); // can be null\n if (!extent) {\n LOG.warn(\n `Cannot set default center coordinate because the current projection has no associated extent.\\n` +\n `Try to configure 'initialView' explicity.`\n );\n } else {\n view.center = getCenter(extent);\n }\n }\n\n if (view.zoom == null || view.resolution == null) {\n view.zoom = 0;\n }\n }\n\n private initializeProjection(projectionOption: MapConfig[\"projection\"]) {\n if (projectionOption == null) {\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n return getProjection(\"EPSG:3857\")!; // default OpenLayers projection\n }\n\n const projection = getProjection(projectionOption);\n if (!projection) {\n throw new Error(`Failed to retrieve projection for code '${projectionOption}'.`);\n }\n return projection;\n }\n}\n"],"names":["defaultInteractions","getProjection"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"createMapModel.js","sources":["createMapModel.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2023-2025 Open Pioneer project (https://github.com/open-pioneer)\n// SPDX-License-Identifier: Apache-2.0\nimport { batch, ReadonlyReactive } from \"@conterra/reactivity-core\";\nimport { createLogger } from \"@open-pioneer/core\";\nimport { HttpService } from \"@open-pioneer/http\";\nimport { PackageIntl } from \"@open-pioneer/runtime\";\nimport { MapBrowserEvent } from \"ol\";\nimport OlMap, { MapOptions } from \"ol/Map\";\nimport View, { ViewOptions } from \"ol/View\";\nimport { getCenter } from \"ol/extent\";\nimport { DragZoom, defaults as defaultInteractions } from \"ol/interaction\";\nimport TileLayer from \"ol/layer/Tile\";\nimport { Projection, get as getProjection } from \"ol/proj\";\nimport OSM from \"ol/source/OSM\";\nimport { sourceId } from \"open-pioneer:source-info\";\nimport { INTERNAL_CONSTRUCTOR_TAG } from \"../utils/InternalConstructorTag\";\nimport { patchOpenLayersClassesForTesting } from \"../utils/ol-test-support\";\nimport { registerProjections } from \"../utils/projections\";\nimport { MapConfig } from \"./MapConfig\";\nimport { MapModel } from \"./MapModel\";\n\n/**\n * Register custom projection to the global proj4js definitions. User can select `EPSG:25832`\n * and `EPSG:25833` from the predefined projections without calling `registerProjections`.\n */\nregisterProjections({\n \"EPSG:25832\":\n \"+proj=utm +zone=32 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs +type=crs\",\n \"EPSG:25833\":\n \"+proj=utm +zone=33 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs +type=crs\"\n});\nconst LOG = createLogger(sourceId);\n\nexport async function createMapModel(\n mapId: string,\n mapConfig: MapConfig,\n currentIntl: ReadonlyReactive<PackageIntl>,\n httpService: HttpService\n): Promise<MapModel> {\n return await new MapModelFactory(mapId, mapConfig, currentIntl, httpService).createMapModel();\n}\n\nclass MapModelFactory {\n #mapId: string;\n #mapConfig: MapConfig;\n #currentIntl: ReadonlyReactive<PackageIntl>;\n #httpService: HttpService;\n\n constructor(\n mapId: string,\n mapConfig: MapConfig,\n currentIntl: ReadonlyReactive<PackageIntl>,\n httpService: HttpService\n ) {\n this.#mapId = mapId;\n this.#mapConfig = mapConfig;\n this.#currentIntl = currentIntl;\n this.#httpService = httpService;\n }\n\n async createMapModel() {\n const mapId = this.#mapId;\n const mapConfig = this.#mapConfig;\n const { view: viewOption, ...rawOlOptions } = mapConfig.advanced ?? {};\n const showDefaultAttributions =\n mapConfig.showAttributions ?? (rawOlOptions.controls ? false : true);\n\n const mapOptions: MapOptions = {\n ...rawOlOptions\n };\n if (!mapOptions.controls) {\n mapOptions.controls = [];\n }\n if (!mapOptions.interactions) {\n const shiftCtrlKeysOnly = (\n mapBrowserEvent: MapBrowserEvent<KeyboardEvent | WheelEvent | PointerEvent>\n ) => {\n const originalEvent = mapBrowserEvent.originalEvent;\n return (originalEvent.metaKey || originalEvent.ctrlKey) && originalEvent.shiftKey;\n };\n\n // setting altShiftDragRotate to false disables or excludes DragRotate interaction\n mapOptions.interactions = defaultInteractions({\n dragPan: true,\n altShiftDragRotate: false,\n pinchRotate: false,\n mouseWheelZoom: true\n }).extend([new DragZoom({ out: true, condition: shiftCtrlKeysOnly })]);\n }\n\n const view = (await viewOption) ?? {};\n this.#initializeViewOptions(view);\n mapOptions.view = view instanceof View ? view : new View(view);\n\n if (!mapOptions.layers && !mapConfig.layers) {\n mapOptions.layers = [\n new TileLayer({\n source: new OSM()\n })\n ];\n }\n\n const initialView = mapConfig.initialView;\n const initialExtent = initialView?.kind === \"extent\" ? initialView.extent : undefined;\n\n LOG.debug(`Constructing OpenLayers map with options`, mapOptions);\n\n if (import.meta.env.VITEST) {\n patchOpenLayersClassesForTesting();\n }\n\n const olMap = new OlMap(mapOptions);\n const mapModel = new MapModel(\n {\n id: mapId,\n olMap,\n initialExtent,\n showDefaultAttributions,\n currentIntl: this.#currentIntl,\n httpService: this.#httpService\n },\n INTERNAL_CONSTRUCTOR_TAG\n );\n\n return batch(() => {\n try {\n if (mapConfig.layers) {\n for (const layerConfig of mapConfig.layers) {\n mapModel.layers.addLayer(layerConfig);\n }\n }\n return mapModel;\n } catch (e) {\n mapModel.destroy();\n throw e;\n }\n });\n }\n\n #initializeViewOptions(view: View | ViewOptions) {\n const mapId = this.#mapId;\n const mapConfig = this.#mapConfig;\n if (view instanceof View) {\n const warn = (prop: string) => {\n LOG.warn(\n `The advanced configuration for map id '${mapId}' has provided a fully constructed view instance: ${prop} cannot be applied.\\n` +\n `Use ViewOptions instead of a View instance.`\n );\n };\n\n if (mapConfig.projection != null) {\n warn(\"projection\");\n }\n if (mapConfig.initialView != null) {\n warn(\"initialView\");\n }\n return;\n }\n\n const projection = (view.projection = this.#initializeProjection(mapConfig.projection));\n const initialView = mapConfig.initialView;\n if (initialView) {\n switch (initialView.kind) {\n case \"position\":\n view.zoom = initialView.zoom;\n view.center = [initialView.center.x, initialView.center.y];\n break;\n case \"extent\": {\n /*\n OpenLayers does not support configuration of the initial map extent.\n The only relevant options here are center, zoom (and resolution).\n We must set those values because otherwise OpenLayers will not initialize layer sources.\n\n The actual initial extent is applied once tha map has loaded and its size is known.\n */\n const extent = initialView.extent;\n view.zoom = 0;\n view.center = [\n extent.xMin + (extent.xMax - extent.xMin) / 2,\n extent.yMin + (extent.yMax - extent.yMin) / 2\n ];\n break;\n }\n }\n } else {\n this.#setViewDefaults(view, projection);\n }\n }\n\n #setViewDefaults(view: ViewOptions, projection: Projection) {\n if (view.center == null) {\n const extent = projection.getExtent(); // can be null\n if (!extent) {\n LOG.warn(\n `Cannot set default center coordinate because the current projection has no associated extent.\\n` +\n `Try to configure 'initialView' explicity.`\n );\n } else {\n view.center = getCenter(extent);\n }\n }\n\n if (view.zoom == null || view.resolution == null) {\n view.zoom = 0;\n }\n }\n\n #initializeProjection(projectionOption: MapConfig[\"projection\"]) {\n if (projectionOption == null) {\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n return getProjection(\"EPSG:3857\")!; // default OpenLayers projection\n }\n\n const projection = getProjection(projectionOption);\n if (!projection) {\n throw new Error(`Failed to retrieve projection for code '${projectionOption}'.`);\n }\n return projection;\n }\n}\n"],"names":["defaultInteractions","getProjection"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"type": "module",
|
|
3
3
|
"name": "@open-pioneer/map",
|
|
4
|
-
"version": "1.4.0-dev.
|
|
4
|
+
"version": "1.4.0-dev.20260727093741",
|
|
5
5
|
"description": "This package integrates OpenLayers maps into an open pioneer trails application.",
|
|
6
6
|
"keywords": [
|
|
7
7
|
"open-pioneer-trails"
|
|
@@ -14,21 +14,21 @@
|
|
|
14
14
|
"directory": "src/packages/map"
|
|
15
15
|
},
|
|
16
16
|
"dependencies": {
|
|
17
|
-
"@chakra-ui/react": "^3.36.
|
|
17
|
+
"@chakra-ui/react": "^3.36.1",
|
|
18
18
|
"@conterra/reactivity-core": "^0.8.6",
|
|
19
19
|
"@conterra/reactivity-events": "^0.8.6",
|
|
20
20
|
"@esri/arcgis-html-sanitizer": "^4.1.0",
|
|
21
|
-
"@open-pioneer/core": "4.7.0-dev.
|
|
22
|
-
"@open-pioneer/http": "4.7.0-dev.
|
|
23
|
-
"@open-pioneer/react-utils": "4.7.0-dev.
|
|
24
|
-
"@open-pioneer/reactivity": "4.7.0-dev.
|
|
25
|
-
"@open-pioneer/runtime": "4.7.0-dev.
|
|
21
|
+
"@open-pioneer/core": "4.7.0-dev.20260727091735",
|
|
22
|
+
"@open-pioneer/http": "4.7.0-dev.20260727091735",
|
|
23
|
+
"@open-pioneer/react-utils": "4.7.0-dev.20260727091735",
|
|
24
|
+
"@open-pioneer/reactivity": "4.7.0-dev.20260727091735",
|
|
25
|
+
"@open-pioneer/runtime": "4.7.0-dev.20260727091735",
|
|
26
26
|
"ol": "^10.9.0",
|
|
27
27
|
"proj4": "^2.20.9",
|
|
28
|
-
"react-dom": "^19.2.
|
|
28
|
+
"react-dom": "^19.2.8",
|
|
29
29
|
"react-use": "^17.6.1",
|
|
30
|
-
"react": "^19.2.
|
|
31
|
-
"uuid": "^14.0.
|
|
30
|
+
"react": "^19.2.8",
|
|
31
|
+
"uuid": "^14.0.1"
|
|
32
32
|
},
|
|
33
33
|
"exports": {
|
|
34
34
|
"./package.json": "./package.json",
|
package/ui/MapContainer.js
CHANGED
|
@@ -3,7 +3,7 @@ import { chakra } from '@chakra-ui/react';
|
|
|
3
3
|
import { createLogger } from '@open-pioneer/core';
|
|
4
4
|
import { useCommonComponentProps, mergeChakraProps } from '@open-pioneer/react-utils';
|
|
5
5
|
import { useReactiveSnapshot } from '@open-pioneer/reactivity';
|
|
6
|
-
import { sourceId$
|
|
6
|
+
import { sourceId$5 as sourceId } from '../_virtual/source-info.js';
|
|
7
7
|
import { useRef, useState, useEffect, useMemo } from 'react';
|
|
8
8
|
import { DISPLAY_STATUS } from '../model/MapModel.js';
|
|
9
9
|
import { MapContainerContextProvider } from './MapContainerContext.js';
|
|
@@ -39,6 +39,9 @@ export declare function useMapModel(): UseMapModelResult;
|
|
|
39
39
|
*
|
|
40
40
|
* The map model cannot be returned directly because it may not have completed its initialization yet.
|
|
41
41
|
*
|
|
42
|
+
* An error message will be logged if the map model's creation has failed.
|
|
43
|
+
* Use the option `quiet: true` to suppress this message.
|
|
44
|
+
*
|
|
42
45
|
* @group UI Components and Hooks
|
|
43
46
|
*/
|
|
44
47
|
export declare function useMapModel(mapId: string): UseMapModelResult;
|
|
@@ -50,10 +53,14 @@ export declare function useMapModel(mapId: string): UseMapModelResult;
|
|
|
50
53
|
*
|
|
51
54
|
* The map model cannot be returned directly because it may not have completed its initialization yet.
|
|
52
55
|
*
|
|
56
|
+
* An error message will be logged if the map model's creation has failed.
|
|
57
|
+
* Use the option `quiet: true` to suppress this message.
|
|
58
|
+
*
|
|
53
59
|
* @group UI Components and Hooks
|
|
54
60
|
*/
|
|
55
61
|
export declare function useMapModel(props: {
|
|
56
62
|
mapId: string;
|
|
63
|
+
quiet?: boolean;
|
|
57
64
|
}): UseMapModelResult;
|
|
58
65
|
/**
|
|
59
66
|
* Options that specify which map to use. See {@link useMapModelValue}.
|
package/ui/hooks/useMapModel.js
CHANGED
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
import { useService } from '../../_virtual/hooks.js';
|
|
2
|
-
import { useMemo } from 'react';
|
|
2
|
+
import { useMemo, useEffect } from 'react';
|
|
3
3
|
import { useAsync } from 'react-use';
|
|
4
4
|
import { MapModel } from '../../model/MapModel.js';
|
|
5
5
|
import { useDefaultMap } from '../DefaultMapProvider.js';
|
|
6
|
+
import { createLogger } from '@open-pioneer/core';
|
|
7
|
+
import { sourceId$4 as sourceId } from '../../_virtual/source-info.js';
|
|
6
8
|
|
|
9
|
+
const LOG = createLogger(sourceId);
|
|
7
10
|
function useMapModel(props) {
|
|
8
11
|
if (props instanceof MapModel) {
|
|
9
12
|
throw new Error(
|
|
@@ -38,6 +41,12 @@ function useMapModel(props) {
|
|
|
38
41
|
}
|
|
39
42
|
return { kind: "resolved", map: state.value };
|
|
40
43
|
}, [state]);
|
|
44
|
+
const quiet = (typeof props === "object" ? props.quiet : void 0) ?? false;
|
|
45
|
+
useEffect(() => {
|
|
46
|
+
if (!quiet && result.error) {
|
|
47
|
+
LOG.error("Failed to construct map", result.error);
|
|
48
|
+
}
|
|
49
|
+
}, [quiet, result.error]);
|
|
41
50
|
return result;
|
|
42
51
|
}
|
|
43
52
|
function useMapModelValue(props) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useMapModel.js","sources":["useMapModel.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2023-2025 Open Pioneer project (https://github.com/open-pioneer)\n// SPDX-License-Identifier: Apache-2.0\nimport { useService } from \"open-pioneer:react-hooks\";\nimport { useMemo } from \"react\";\nimport { useAsync } from \"react-use\";\nimport { MapRegistry } from \"../../MapRegistry\";\nimport { MapModel } from \"../../model/MapModel\";\nimport { useDefaultMap } from \"../DefaultMapProvider\";\n\n/**\n * Return value of {@link useMapModel}.\n *\n * @group UI Components and Hooks\n **/\nexport type UseMapModelResult = UseMapModelLoading | UseMapModelResolved | UseMapModelRejected;\n\n/** @group UI Components and Hooks */\nexport interface UseMapModelLoading {\n kind: \"loading\";\n map?: undefined;\n error?: undefined;\n}\n\n/** @group UI Components and Hooks */\nexport interface UseMapModelResolved {\n kind: \"resolved\";\n map: MapModel;\n error?: undefined;\n}\n\n/** @group UI Components and Hooks */\nexport interface UseMapModelRejected {\n kind: \"rejected\";\n map?: undefined;\n error: Error;\n}\n\n/**\n * React hook that returns the default map model (if available, see {@link DefaultMapProvider}).\n *\n * @deprecated Use {@link useMapModelValue} instead.\n *\n * @group UI Components and Hooks\n */\nexport function useMapModel(): UseMapModelResult;\n\n/**\n * React hook that looks up the map with the given id in the `map.MapRegistry` service.\n *\n * Returns an object representing the progress, which will eventually represent either\n * the map model value or an initialization error.\n *\n * The map model cannot be returned directly because it may not have completed its initialization yet.\n *\n * @group UI Components and Hooks\n */\nexport function useMapModel(mapId: string): UseMapModelResult;\n\n/**\n * React hook that resolves a map model specified by the given `props`.\n *\n * Returns an object representing the progress, which will eventually represent either\n * the map model value or an initialization error.\n *\n * The map model cannot be returned directly because it may not have completed its initialization yet.\n *\n * @group UI Components and Hooks\n */\nexport function useMapModel(props: { mapId: string }): UseMapModelResult;\n\nexport function useMapModel(props?: undefined | string | { mapId: string }): UseMapModelResult {\n if (props instanceof MapModel) {\n // This cannot happen in valid typescript code, but it might be a common mistake.\n throw new Error(\n `Map model instances cannot be passed directly to 'useMapModel' (see TypeScript signature).`\n );\n }\n\n const defaultMap = useDefaultMap();\n const mapRegistry = useService<MapRegistry>(\"map.MapRegistry\");\n\n let mapId: string | undefined;\n if (typeof props === \"string\") {\n mapId = props;\n } else if (typeof props === \"object\") {\n mapId = props.mapId;\n }\n\n if (mapId == null && !defaultMap) {\n throw new Error(\n \"No map specified. Either configure a mapId or use the DefaultMapProvider.\"\n );\n }\n\n const state = useAsync(async () => {\n if (mapId == null) {\n // For backwards compatibility\n return defaultMap;\n }\n\n return await mapRegistry.expectMapModel(mapId);\n }, [mapRegistry, mapId]);\n\n const result = useMemo((): UseMapModelResult => {\n if (state.loading) {\n return { kind: \"loading\" };\n }\n if (state.error) {\n return { kind: \"rejected\", error: state.error };\n }\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n return { kind: \"resolved\", map: state.value! };\n }, [state]);\n return result;\n}\n\n/**\n * Options that specify which map to use. See {@link useMapModelValue}.\n *\n * When not setting any of these properties on a component, the default map (from the `DefaultMapProvider`) will be used.\n * If that is not available either, an error will be thrown.\n *\n * @see {@link DefaultMapProvider}\n *\n * @group UI Components and Hooks\n */\nexport interface MapModelProps {\n /**\n * The map model to use.\n */\n map?: MapModel | undefined;\n}\n\n/**\n * Returns the configured map model.\n *\n * The map model is either directly configured or specified via a {@link DefaultMapProvider}.\n * If neither has been specified, an error will be thrown.\n *\n * This hook is preferable to {@link useMapModel} because it can return the map model directly, without waiting.\n *\n * @group UI Components and Hooks\n */\nexport function useMapModelValue(props?: MapModelProps): MapModel {\n if (props instanceof MapModel) {\n // This cannot happen in valid typescript code, but it might be a common mistake.\n throw new Error(\n `Map model instances cannot be passed directly to 'useMapModelValue' (see TypeScript signature).`\n );\n }\n\n const localMap = props?.map;\n const defaultMap = useDefaultMap();\n const map = localMap ?? defaultMap;\n if (!map) {\n throw new Error(\n `No map specified. ` +\n `You must either specify the map via a DefaultMapProvider parent or configure it explicitly.`\n );\n }\n return map;\n}\n"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"useMapModel.js","sources":["useMapModel.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2023-2025 Open Pioneer project (https://github.com/open-pioneer)\n// SPDX-License-Identifier: Apache-2.0\nimport { useService } from \"open-pioneer:react-hooks\";\nimport { useEffect, useMemo } from \"react\";\nimport { useAsync } from \"react-use\";\nimport { MapRegistry } from \"../../MapRegistry\";\nimport { MapModel } from \"../../model/MapModel\";\nimport { useDefaultMap } from \"../DefaultMapProvider\";\nimport { createLogger } from \"@open-pioneer/core\";\nimport { sourceId } from \"open-pioneer:source-info\";\n\nconst LOG = createLogger(sourceId);\n\n/**\n * Return value of {@link useMapModel}.\n *\n * @group UI Components and Hooks\n **/\nexport type UseMapModelResult = UseMapModelLoading | UseMapModelResolved | UseMapModelRejected;\n\n/** @group UI Components and Hooks */\nexport interface UseMapModelLoading {\n kind: \"loading\";\n map?: undefined;\n error?: undefined;\n}\n\n/** @group UI Components and Hooks */\nexport interface UseMapModelResolved {\n kind: \"resolved\";\n map: MapModel;\n error?: undefined;\n}\n\n/** @group UI Components and Hooks */\nexport interface UseMapModelRejected {\n kind: \"rejected\";\n map?: undefined;\n error: Error;\n}\n\n/**\n * React hook that returns the default map model (if available, see {@link DefaultMapProvider}).\n *\n * @deprecated Use {@link useMapModelValue} instead.\n *\n * @group UI Components and Hooks\n */\nexport function useMapModel(): UseMapModelResult;\n\n/**\n * React hook that looks up the map with the given id in the `map.MapRegistry` service.\n *\n * Returns an object representing the progress, which will eventually represent either\n * the map model value or an initialization error.\n *\n * The map model cannot be returned directly because it may not have completed its initialization yet.\n *\n * An error message will be logged if the map model's creation has failed.\n * Use the option `quiet: true` to suppress this message.\n *\n * @group UI Components and Hooks\n */\nexport function useMapModel(mapId: string): UseMapModelResult;\n\n/**\n * React hook that resolves a map model specified by the given `props`.\n *\n * Returns an object representing the progress, which will eventually represent either\n * the map model value or an initialization error.\n *\n * The map model cannot be returned directly because it may not have completed its initialization yet.\n *\n * An error message will be logged if the map model's creation has failed.\n * Use the option `quiet: true` to suppress this message.\n *\n * @group UI Components and Hooks\n */\nexport function useMapModel(props: { mapId: string; quiet?: boolean }): UseMapModelResult;\n\nexport function useMapModel(\n props?: undefined | string | { mapId: string; quiet?: boolean }\n): UseMapModelResult {\n if (props instanceof MapModel) {\n // This cannot happen in valid typescript code, but it might be a common mistake.\n throw new Error(\n `Map model instances cannot be passed directly to 'useMapModel' (see TypeScript signature).`\n );\n }\n\n const defaultMap = useDefaultMap();\n const mapRegistry = useService<MapRegistry>(\"map.MapRegistry\");\n\n let mapId: string | undefined;\n if (typeof props === \"string\") {\n mapId = props;\n } else if (typeof props === \"object\") {\n mapId = props.mapId;\n }\n\n if (mapId == null && !defaultMap) {\n throw new Error(\n \"No map specified. Either configure a mapId or use the DefaultMapProvider.\"\n );\n }\n\n const state = useAsync(async () => {\n if (mapId == null) {\n // For backwards compatibility\n return defaultMap;\n }\n\n return await mapRegistry.expectMapModel(mapId);\n }, [mapRegistry, mapId]);\n\n const result = useMemo((): UseMapModelResult => {\n if (state.loading) {\n return { kind: \"loading\" };\n }\n if (state.error) {\n return { kind: \"rejected\", error: state.error };\n }\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n return { kind: \"resolved\", map: state.value! };\n }, [state]);\n\n const quiet = (typeof props === \"object\" ? props.quiet : undefined) ?? false;\n useEffect(() => {\n if (!quiet && result.error) {\n LOG.error(\"Failed to construct map\", result.error);\n }\n }, [quiet, result.error]);\n return result;\n}\n\n/**\n * Options that specify which map to use. See {@link useMapModelValue}.\n *\n * When not setting any of these properties on a component, the default map (from the `DefaultMapProvider`) will be used.\n * If that is not available either, an error will be thrown.\n *\n * @see {@link DefaultMapProvider}\n *\n * @group UI Components and Hooks\n */\nexport interface MapModelProps {\n /**\n * The map model to use.\n */\n map?: MapModel | undefined;\n}\n\n/**\n * Returns the configured map model.\n *\n * The map model is either directly configured or specified via a {@link DefaultMapProvider}.\n * If neither has been specified, an error will be thrown.\n *\n * This hook is preferable to {@link useMapModel} because it can return the map model directly, without waiting.\n *\n * @group UI Components and Hooks\n */\nexport function useMapModelValue(props?: MapModelProps): MapModel {\n if (props instanceof MapModel) {\n // This cannot happen in valid typescript code, but it might be a common mistake.\n throw new Error(\n `Map model instances cannot be passed directly to 'useMapModelValue' (see TypeScript signature).`\n );\n }\n\n const localMap = props?.map;\n const defaultMap = useDefaultMap();\n const map = localMap ?? defaultMap;\n if (!map) {\n throw new Error(\n `No map specified. ` +\n `You must either specify the map via a DefaultMapProvider parent or configure it explicitly.`\n );\n }\n return map;\n}\n"],"names":[],"mappings":";;;;;;;;AAWA,MAAM,GAAA,GAAM,aAAa,QAAQ,CAAA;AAqE1B,SAAS,YACZ,KAAA,EACiB;AACjB,EAAA,IAAI,iBAAiB,QAAA,EAAU;AAE3B,IAAA,MAAM,IAAI,KAAA;AAAA,MACN,CAAA,0FAAA;AAAA,KACJ;AAAA,EACJ;AAEA,EAAA,MAAM,aAAa,aAAA,EAAc;AACjC,EAAA,MAAM,WAAA,GAAc,WAAwB,iBAAiB,CAAA;AAE7D,EAAA,IAAI,KAAA;AACJ,EAAA,IAAI,OAAO,UAAU,QAAA,EAAU;AAC3B,IAAA,KAAA,GAAQ,KAAA;AAAA,EACZ,CAAA,MAAA,IAAW,OAAO,KAAA,KAAU,QAAA,EAAU;AAClC,IAAA,KAAA,GAAQ,KAAA,CAAM,KAAA;AAAA,EAClB;AAEA,EAAA,IAAI,KAAA,IAAS,IAAA,IAAQ,CAAC,UAAA,EAAY;AAC9B,IAAA,MAAM,IAAI,KAAA;AAAA,MACN;AAAA,KACJ;AAAA,EACJ;AAEA,EAAA,MAAM,KAAA,GAAQ,SAAS,YAAY;AAC/B,IAAA,IAAI,SAAS,IAAA,EAAM;AAEf,MAAA,OAAO,UAAA;AAAA,IACX;AAEA,IAAA,OAAO,MAAM,WAAA,CAAY,cAAA,CAAe,KAAK,CAAA;AAAA,EACjD,CAAA,EAAG,CAAC,WAAA,EAAa,KAAK,CAAC,CAAA;AAEvB,EAAA,MAAM,MAAA,GAAS,QAAQ,MAAyB;AAC5C,IAAA,IAAI,MAAM,OAAA,EAAS;AACf,MAAA,OAAO,EAAE,MAAM,SAAA,EAAU;AAAA,IAC7B;AACA,IAAA,IAAI,MAAM,KAAA,EAAO;AACb,MAAA,OAAO,EAAE,IAAA,EAAM,UAAA,EAAY,KAAA,EAAO,MAAM,KAAA,EAAM;AAAA,IAClD;AAEA,IAAA,OAAO,EAAE,IAAA,EAAM,UAAA,EAAY,GAAA,EAAK,MAAM,KAAA,EAAO;AAAA,EACjD,CAAA,EAAG,CAAC,KAAK,CAAC,CAAA;AAEV,EAAA,MAAM,SAAS,OAAO,KAAA,KAAU,QAAA,GAAW,KAAA,CAAM,QAAQ,MAAA,KAAc,KAAA;AACvE,EAAA,SAAA,CAAU,MAAM;AACZ,IAAA,IAAI,CAAC,KAAA,IAAS,MAAA,CAAO,KAAA,EAAO;AACxB,MAAA,GAAA,CAAI,KAAA,CAAM,yBAAA,EAA2B,MAAA,CAAO,KAAK,CAAA;AAAA,IACrD;AAAA,EACJ,CAAA,EAAG,CAAC,KAAA,EAAO,MAAA,CAAO,KAAK,CAAC,CAAA;AACxB,EAAA,OAAO,MAAA;AACX;AA6BO,SAAS,iBAAiB,KAAA,EAAiC;AAC9D,EAAA,IAAI,iBAAiB,QAAA,EAAU;AAE3B,IAAA,MAAM,IAAI,KAAA;AAAA,MACN,CAAA,+FAAA;AAAA,KACJ;AAAA,EACJ;AAEA,EAAA,MAAM,WAAW,KAAA,EAAO,GAAA;AACxB,EAAA,MAAM,aAAa,aAAA,EAAc;AACjC,EAAA,MAAM,MAAM,QAAA,IAAY,UAAA;AACxB,EAAA,IAAI,CAAC,GAAA,EAAK;AACN,IAAA,MAAM,IAAI,KAAA;AAAA,MACN,CAAA,6GAAA;AAAA,KAEJ;AAAA,EACJ;AACA,EAAA,OAAO,GAAA;AACX;;;;"}
|
package/ui/styles.css
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
@import "ol/ol.css";
|
|
2
2
|
|
|
3
3
|
/* Move attribution according to map view's padding */
|
|
4
|
-
|
|
5
4
|
.map-container-root .map-container .ol-viewport .ol-attribution {
|
|
6
5
|
bottom: var(--map-padding-bottom);
|
|
7
6
|
right: var(--map-padding-right);
|
|
@@ -35,7 +34,6 @@
|
|
|
35
34
|
}
|
|
36
35
|
|
|
37
36
|
/* Set map focus style on map-anchor container to respect map padding inset 0*/
|
|
38
|
-
|
|
39
37
|
.map-container-root:has(> .map-container:focus-visible) .map-anchors::after {
|
|
40
38
|
content: "";
|
|
41
39
|
position: absolute;
|
package/ui/styles.css.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["styles.css"],"names":[],"mappings":"AAAA,mBAAmB;;AAEnB,qDAAqD
|
|
1
|
+
{"version":3,"sources":["styles.css"],"names":[],"mappings":"AAAA,mBAAmB;;AAEnB,qDAAqD;AACrD;IACI,iCAAiC;IACjC,+BAA+B;AACnC;;AAEA;IACI,oBAAoB;IACpB,gBAAgB;;IAEhB,kBAAkB;IAClB,2BAA2B;IAC3B,iCAAiC;IACjC,6BAA6B;IAC7B,+BAA+B;;IAE/B,6CAA6C;IAC7C,0BAA0B;IAC1B,uCAAuC;AAC3C;;AAEA;IACI,UAAU;IACV,gBAAgB;;IAEhB,kBAAkB;IAClB,yFAAyF;AAC7F;;AAEA;IACI,oBAAoB;AACxB;;AAEA,8EAA8E;AAC9E;IACI,WAAW;IACX,kBAAkB;IAClB,QAAQ;IACR,aAAa;IACb,oDAAoD;IACpD,oBAAoB;AACxB;;AAEA;IACI,aAAa;AACjB","file":"styles.css","sourcesContent":["@import \"ol/ol.css\";\n\n/* Move attribution according to map view's padding */\n.map-container-root .map-container .ol-viewport .ol-attribution {\n bottom: var(--map-padding-bottom);\n right: var(--map-padding-right);\n}\n\n.map-container-root .map-anchors {\n pointer-events: none;\n overflow: hidden;\n\n position: absolute;\n top: var(--map-padding-top);\n bottom: var(--map-padding-bottom);\n left: var(--map-padding-left);\n right: var(--map-padding-right);\n\n transition-property: left, right, top, bottom;\n transition-duration: 200ms;\n transition-timing-function: ease-in-out;\n}\n\n.map-container-root .map-anchors .map-anchor {\n z-index: 1;\n overflow: hidden;\n\n position: absolute;\n /* positioned absolute in .map-anchors, but actual coordinates are currently set via JS */\n}\n\n.map-container-root .map-anchors > * {\n pointer-events: auto;\n}\n\n/* Set map focus style on map-anchor container to respect map padding inset 0*/\n.map-container-root:has(> .map-container:focus-visible) .map-anchors::after {\n content: \"\";\n position: absolute;\n inset: 0;\n z-index: 9999;\n outline: var(--chakra-colors-trails-solid) solid 2px;\n outline-offset: -2px;\n}\n\n.map-container:focus-visible {\n outline: none;\n}\n"]}
|