@open-pioneer/map 0.11.0 → 0.12.0-dev.20250905090001
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 +101 -5
- package/MapRegistryImpl.js.map +1 -1
- package/README.md +32 -20
- package/api/MapModel.d.ts +5 -0
- package/api/index.d.ts +1 -1
- package/api/layers/GroupLayer.js.map +1 -1
- package/api/layers/SimpleLayer.js.map +1 -1
- package/api/layers/WMSLayer.js.map +1 -1
- package/api/layers/WMTSLayer.js.map +1 -1
- package/api/layers/base.d.ts +17 -0
- package/api/layers/base.js.map +1 -1
- package/api/shared.d.ts +6 -4
- package/index.js +1 -1
- package/model/AbstractLayer.js.map +1 -1
- package/model/AbstractLayerBase.d.ts +3 -0
- package/model/AbstractLayerBase.js +8 -0
- package/model/AbstractLayerBase.js.map +1 -1
- package/model/Highlights.js +9 -1
- package/model/Highlights.js.map +1 -1
- package/model/LayerCollectionImpl.js +52 -24
- package/model/LayerCollectionImpl.js.map +1 -1
- package/model/MapModelImpl.js.map +1 -1
- package/model/SublayersCollectionImpl.js.map +1 -1
- package/model/createMapModel.js.map +1 -1
- package/model/getRecursiveLayers.js.map +1 -1
- package/model/layers/GroupLayerImpl.js.map +1 -1
- package/model/layers/SimpleLayerImpl.js.map +1 -1
- package/model/layers/WMSLayerImpl.js.map +1 -1
- package/model/layers/WMTSLayerImpl.js.map +1 -1
- package/package.json +6 -7
- package/projections.d.ts +3 -1
- package/projections.js.map +1 -1
- package/ui/DefaultMapProvider.d.ts +3 -2
- package/ui/DefaultMapProvider.js +7 -13
- package/ui/DefaultMapProvider.js.map +1 -1
- package/ui/MapAnchor.js.map +1 -1
- package/ui/MapContainer.d.ts +2 -0
- package/ui/MapContainer.js +4 -16
- package/ui/MapContainer.js.map +1 -1
- package/ui/MapContainerContext.js.map +1 -1
- package/ui/computeMapAnchorStyles.js.map +1 -1
- package/ui/useMapModel.d.ts +28 -22
- package/ui/useMapModel.js +31 -29
- package/ui/useMapModel.js.map +1 -1
- package/util/capabilities-utils.js.map +1 -1
- package/util/geometry-utils.js.map +1 -1
- package/util/ol-test-support.js.map +1 -1
|
@@ -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 { createLogger } from \"@open-pioneer/core\";\nimport OlMap, { MapOptions } from \"ol/Map\";\nimport View, { ViewOptions } from \"ol/View\";\nimport Attribution from \"ol/control/Attribution\";\nimport { getCenter } from \"ol/extent\";\nimport TileLayer from \"ol/layer/Tile\";\nimport { Projection, get as getProjection } from \"ol/proj\";\nimport OSM from \"ol/source/OSM\";\nimport { DragZoom, defaults as defaultInteractions } from \"ol/interaction\";\nimport { MapBrowserEvent } from \"ol\";\nimport { MapModelImpl } from \"./MapModelImpl\";\nimport { MapConfig } from \"../api\";\nimport { registerProjections } from \"../projections\";\nimport { patchOpenLayersClassesForTesting } from \"../util/ol-test-support\";\nimport { HttpService } from \"@open-pioneer/http\";\nimport { PackageIntl } from \"@open-pioneer/runtime\";\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(\"map:createMapModel\");\n\nexport async function createMapModel(\n mapId: string,\n mapConfig: MapConfig,\n intl: PackageIntl,\n httpService: HttpService\n): Promise<MapModelImpl> {\n return await new MapModelFactory(mapId, mapConfig, intl, httpService).createMapModel();\n}\n\nclass MapModelFactory {\n private mapId: string;\n private mapConfig: MapConfig;\n private intl: PackageIntl;\n private httpService: HttpService;\n\n constructor(mapId: string, mapConfig: MapConfig, intl: PackageIntl, httpService: HttpService) {\n this.mapId = mapId;\n this.mapConfig = mapConfig;\n this.intl = intl;\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 mapOptions: MapOptions = {\n ...rawOlOptions\n };\n\n if (!mapOptions.controls) {\n mapOptions.controls = [createDefaultAttribution(this.intl)];\n }\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 * */\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\n const mapModel = new MapModelImpl({\n id: mapId,\n olMap,\n initialExtent,\n httpService: this.httpService\n });\n\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 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 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\nfunction createDefaultAttribution(intl: PackageIntl): Attribution {\n const attr = new Attribution({ collapsible: false });\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const element = (attr as any).element as HTMLElement | undefined;\n if (element) {\n element.role = \"region\";\n element.ariaLabel = intl.formatMessage({ id: \"attribution.label\" });\n }\n return attr;\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 { createLogger } from \"@open-pioneer/core\";\nimport OlMap, { MapOptions } from \"ol/Map\";\nimport View, { ViewOptions } from \"ol/View\";\nimport Attribution from \"ol/control/Attribution\";\nimport { getCenter } from \"ol/extent\";\nimport TileLayer from \"ol/layer/Tile\";\nimport { Projection, get as getProjection } from \"ol/proj\";\nimport OSM from \"ol/source/OSM\";\nimport { DragZoom, defaults as defaultInteractions } from \"ol/interaction\";\nimport { MapBrowserEvent } from \"ol\";\nimport { MapModelImpl } from \"./MapModelImpl\";\nimport { MapConfig } from \"../api\";\nimport { registerProjections } from \"../projections\";\nimport { patchOpenLayersClassesForTesting } from \"../util/ol-test-support\";\nimport { HttpService } from \"@open-pioneer/http\";\nimport { PackageIntl } from \"@open-pioneer/runtime\";\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(\"map:createMapModel\");\n\nexport async function createMapModel(\n mapId: string,\n mapConfig: MapConfig,\n intl: PackageIntl,\n httpService: HttpService\n): Promise<MapModelImpl> {\n return await new MapModelFactory(mapId, mapConfig, intl, httpService).createMapModel();\n}\n\nclass MapModelFactory {\n private mapId: string;\n private mapConfig: MapConfig;\n private intl: PackageIntl;\n private httpService: HttpService;\n\n constructor(mapId: string, mapConfig: MapConfig, intl: PackageIntl, httpService: HttpService) {\n this.mapId = mapId;\n this.mapConfig = mapConfig;\n this.intl = intl;\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 mapOptions: MapOptions = {\n ...rawOlOptions\n };\n\n if (!mapOptions.controls) {\n mapOptions.controls = [createDefaultAttribution(this.intl)];\n }\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 * */\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\n const mapModel = new MapModelImpl({\n id: mapId,\n olMap,\n initialExtent,\n httpService: this.httpService\n });\n\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 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 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\nfunction createDefaultAttribution(intl: PackageIntl): Attribution {\n const attr = new Attribution({ collapsible: false });\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const element = (attr as any).element as HTMLElement | undefined;\n if (element) {\n element.role = \"region\";\n element.ariaLabel = intl.formatMessage({ id: \"attribution.label\" });\n }\n return attr;\n}\n"],"names":["defaultInteractions","getProjection"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"getRecursiveLayers.js","sources":["getRecursiveLayers.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2023-2025 Open Pioneer project (https://github.com/open-pioneer)\n// SPDX-License-Identifier: Apache-2.0\nimport { AnyLayer, ChildrenCollection, RecursiveRetrievalOptions } from \"../api\";\n\nexport interface RecursiveLayerOptions<LayerType> extends RecursiveRetrievalOptions {\n /**\n * Starting point(s) of the recursion.\n * The layers in this collections and their all of their children (recursively) will be included in the result.\n */\n from: ChildrenCollection<LayerType>;\n\n /**\n * If set to `true`, layers will be ordered by their display order:\n * Layers listed first in the returned array are shown _below_ layers listed at a later index.\n *\n * By default, layers are returned in arbitrary order.\n */\n sortByDisplayOrder?: boolean;\n}\n\nexport function getRecursiveLayers<LayerType extends AnyLayer>(\n options: RecursiveLayerOptions<LayerType>\n): AnyLayer[] {\n const filter = options.filter ?? (() => true);\n const sortByDisplayOrder = options.sortByDisplayOrder ?? false;\n const result: AnyLayer[] = [];\n gatherRecursiveLayers(options.from, filter, sortByDisplayOrder, result);\n return result;\n}\n\n// Walks the layer tree recursively and gathers matching layers into the result array.\nfunction gatherRecursiveLayers<LayerType extends AnyLayer>(\n from: ChildrenCollection<LayerType>,\n filter: (layer: AnyLayer) => boolean,\n sortByDisplayOrder: boolean,\n result: AnyLayer[]\n): void {\n const layers = from.getItems({ sortByDisplayOrder });\n for (const layer of layers) {\n if (!filter(layer)) {\n continue;\n }\n\n const children = layer.children;\n if (children) {\n // Pushes into result as a side effect\n gatherRecursiveLayers(children, filter, sortByDisplayOrder, result);\n }\n result.push(layer);\n }\n}\n"],"names":[],"mappings":"AAoBO,SAAS,mBACZ,
|
|
1
|
+
{"version":3,"file":"getRecursiveLayers.js","sources":["getRecursiveLayers.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2023-2025 Open Pioneer project (https://github.com/open-pioneer)\n// SPDX-License-Identifier: Apache-2.0\nimport { AnyLayer, ChildrenCollection, RecursiveRetrievalOptions } from \"../api\";\n\nexport interface RecursiveLayerOptions<LayerType> extends RecursiveRetrievalOptions {\n /**\n * Starting point(s) of the recursion.\n * The layers in this collections and their all of their children (recursively) will be included in the result.\n */\n from: ChildrenCollection<LayerType>;\n\n /**\n * If set to `true`, layers will be ordered by their display order:\n * Layers listed first in the returned array are shown _below_ layers listed at a later index.\n *\n * By default, layers are returned in arbitrary order.\n */\n sortByDisplayOrder?: boolean;\n}\n\nexport function getRecursiveLayers<LayerType extends AnyLayer>(\n options: RecursiveLayerOptions<LayerType>\n): AnyLayer[] {\n const filter = options.filter ?? (() => true);\n const sortByDisplayOrder = options.sortByDisplayOrder ?? false;\n const result: AnyLayer[] = [];\n gatherRecursiveLayers(options.from, filter, sortByDisplayOrder, result);\n return result;\n}\n\n// Walks the layer tree recursively and gathers matching layers into the result array.\nfunction gatherRecursiveLayers<LayerType extends AnyLayer>(\n from: ChildrenCollection<LayerType>,\n filter: (layer: AnyLayer) => boolean,\n sortByDisplayOrder: boolean,\n result: AnyLayer[]\n): void {\n const layers = from.getItems({ sortByDisplayOrder });\n for (const layer of layers) {\n if (!filter(layer)) {\n continue;\n }\n\n const children = layer.children;\n if (children) {\n // Pushes into result as a side effect\n gatherRecursiveLayers(children, filter, sortByDisplayOrder, result);\n }\n result.push(layer);\n }\n}\n"],"names":[],"mappings":"AAoBO,SAAS,mBACZ,OAAA,EACU;AACV,EAAA,MAAM,MAAA,GAAS,OAAA,CAAQ,MAAA,KAAW,MAAM,IAAA,CAAA;AACxC,EAAA,MAAM,kBAAA,GAAqB,QAAQ,kBAAA,IAAsB,KAAA;AACzD,EAAA,MAAM,SAAqB,EAAC;AAC5B,EAAA,qBAAA,CAAsB,OAAA,CAAQ,IAAA,EAAM,MAAA,EAAQ,kBAAA,EAAoB,MAAM,CAAA;AACtE,EAAA,OAAO,MAAA;AACX;AAGA,SAAS,qBAAA,CACL,IAAA,EACA,MAAA,EACA,kBAAA,EACA,MAAA,EACI;AACJ,EAAA,MAAM,MAAA,GAAS,IAAA,CAAK,QAAA,CAAS,EAAE,oBAAoB,CAAA;AACnD,EAAA,KAAA,MAAW,SAAS,MAAA,EAAQ;AACxB,IAAA,IAAI,CAAC,MAAA,CAAO,KAAK,CAAA,EAAG;AAChB,MAAA;AAAA,IACJ;AAEA,IAAA,MAAM,WAAW,KAAA,CAAM,QAAA;AACvB,IAAA,IAAI,QAAA,EAAU;AAEV,MAAA,qBAAA,CAAsB,QAAA,EAAU,MAAA,EAAQ,kBAAA,EAAoB,MAAM,CAAA;AAAA,IACtE;AACA,IAAA,MAAA,CAAO,KAAK,KAAK,CAAA;AAAA,EACrB;AACJ;;;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"GroupLayerImpl.js","sources":["GroupLayerImpl.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2023-2025 Open Pioneer project (https://github.com/open-pioneer)\n// SPDX-License-Identifier: Apache-2.0\nimport { Group } from \"ol/layer\";\nimport {\n AnyLayer,\n GroupLayerCollection,\n Layer,\n LayerRetrievalOptions,\n RecursiveRetrievalOptions\n} from \"../../api\";\nimport { GroupLayer, GroupLayerConfig } from \"../../api/layers/GroupLayer\";\nimport { AbstractLayer } from \"../AbstractLayer\";\nimport { AbstractLayerBase } from \"../AbstractLayerBase\";\nimport { MapModelImpl } from \"../MapModelImpl\";\nimport { getRecursiveLayers } from \"../getRecursiveLayers\";\n\nexport class GroupLayerImpl extends AbstractLayer implements GroupLayer {\n #children: GroupLayerCollectionImpl;\n\n constructor(config: GroupLayerConfig) {\n const groupLayers = config.layers;\n const olGroup = new Group({ layers: groupLayers.map((sublayer) => sublayer.olLayer) });\n super({ ...config, olLayer: olGroup });\n this.#children = new GroupLayerCollectionImpl(groupLayers, this);\n }\n\n get type() {\n return \"group\" as const;\n }\n\n get legend() {\n return undefined;\n }\n\n get layers(): GroupLayerCollectionImpl {\n return this.#children;\n }\n\n get sublayers(): undefined {\n return undefined;\n }\n\n /**\n * return raw OL LayerGroup\n * Warning: Do not manipulate the collection of layers in this group, changes are not synchronized!\n */\n get olLayer(): Group {\n return super.olLayer as Group;\n }\n\n __attachToMap(map: MapModelImpl): void {\n super.__attachToMap(map);\n this.layers.__getRawLayers().forEach((layer) => layer.__attachToMap(map));\n }\n}\n\n// NOTE: adding / removing currently not supported.\n// When adding support for dynamic content, make sure to also updating the layer indexing logic in the map (LayerCollectionImpl).\n// Nested children of a group layer must also be found in id-lookups.\nexport class GroupLayerCollectionImpl implements GroupLayerCollection {\n #layers: (AbstractLayer & Layer)[];\n #parent: GroupLayer;\n\n constructor(layers: Layer[], parent: GroupLayer) {\n layers = layers.slice(); // Don't modify the input\n for (const layer of layers) {\n if (layer instanceof AbstractLayer) {\n if (layer.isBaseLayer) {\n throw new Error(\n `Layer '${layer.id}' of group '${parent.id}' is marked as base layer. Layers that belong to a group layer cannot be a base layer.`\n );\n }\n layer.__attachToGroup(parent); //attach every layer to the parent group layer\n } else {\n throw new Error(\n `Layer '${layer.id}' of group '${parent.id}' does not implement abstract class '${AbstractLayerBase.name}`\n );\n }\n }\n this.#layers = layers as (Layer & AbstractLayer)[];\n this.#parent = parent;\n }\n\n /**\n * Destroys this collection, all contained layers are detached from their parent group layer\n */\n destroy() {\n for (const layer of this.#layers) {\n layer.__detachFromGroup();\n layer.destroy();\n }\n this.#layers = [];\n }\n\n // Generic method name for consistent interface\n getItems(options?: LayerRetrievalOptions): (AbstractLayer & Layer)[] {\n return this.getLayers(options);\n }\n\n getLayers(_options?: LayerRetrievalOptions | undefined): (AbstractLayer & Layer)[] {\n // NOTE: options are ignored because layers are always ordered at this time.\n return this.#layers.slice();\n }\n\n getRecursiveLayers(_options?: RecursiveRetrievalOptions): AnyLayer[] {\n return getRecursiveLayers({\n from: this,\n sortByDisplayOrder: _options?.sortByDisplayOrder,\n filter: _options?.filter\n });\n }\n\n /**\n * Returns a reference to the internal group layer array.\n *\n * NOTE: Do not modify directly!\n */\n __getRawLayers(): (AbstractLayer & Layer)[] {\n return this.#layers;\n }\n\n /**\n * Returns the parent group layer that owns this collection.\n */\n __getParent(): GroupLayer {\n return this.#parent;\n }\n}\n"],"names":[],"mappings":";;;;;AAgBO,MAAM,uBAAuB,
|
|
1
|
+
{"version":3,"file":"GroupLayerImpl.js","sources":["GroupLayerImpl.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2023-2025 Open Pioneer project (https://github.com/open-pioneer)\n// SPDX-License-Identifier: Apache-2.0\nimport { Group } from \"ol/layer\";\nimport {\n AnyLayer,\n GroupLayerCollection,\n Layer,\n LayerRetrievalOptions,\n RecursiveRetrievalOptions\n} from \"../../api\";\nimport { GroupLayer, GroupLayerConfig } from \"../../api/layers/GroupLayer\";\nimport { AbstractLayer } from \"../AbstractLayer\";\nimport { AbstractLayerBase } from \"../AbstractLayerBase\";\nimport { MapModelImpl } from \"../MapModelImpl\";\nimport { getRecursiveLayers } from \"../getRecursiveLayers\";\n\nexport class GroupLayerImpl extends AbstractLayer implements GroupLayer {\n #children: GroupLayerCollectionImpl;\n\n constructor(config: GroupLayerConfig) {\n const groupLayers = config.layers;\n const olGroup = new Group({ layers: groupLayers.map((sublayer) => sublayer.olLayer) });\n super({ ...config, olLayer: olGroup });\n this.#children = new GroupLayerCollectionImpl(groupLayers, this);\n }\n\n get type() {\n return \"group\" as const;\n }\n\n get legend() {\n return undefined;\n }\n\n get layers(): GroupLayerCollectionImpl {\n return this.#children;\n }\n\n get sublayers(): undefined {\n return undefined;\n }\n\n /**\n * return raw OL LayerGroup\n * Warning: Do not manipulate the collection of layers in this group, changes are not synchronized!\n */\n get olLayer(): Group {\n return super.olLayer as Group;\n }\n\n __attachToMap(map: MapModelImpl): void {\n super.__attachToMap(map);\n this.layers.__getRawLayers().forEach((layer) => layer.__attachToMap(map));\n }\n}\n\n// NOTE: adding / removing currently not supported.\n// When adding support for dynamic content, make sure to also updating the layer indexing logic in the map (LayerCollectionImpl).\n// Nested children of a group layer must also be found in id-lookups.\nexport class GroupLayerCollectionImpl implements GroupLayerCollection {\n #layers: (AbstractLayer & Layer)[];\n #parent: GroupLayer;\n\n constructor(layers: Layer[], parent: GroupLayer) {\n layers = layers.slice(); // Don't modify the input\n for (const layer of layers) {\n if (layer instanceof AbstractLayer) {\n if (layer.isBaseLayer) {\n throw new Error(\n `Layer '${layer.id}' of group '${parent.id}' is marked as base layer. Layers that belong to a group layer cannot be a base layer.`\n );\n }\n layer.__attachToGroup(parent); //attach every layer to the parent group layer\n } else {\n throw new Error(\n `Layer '${layer.id}' of group '${parent.id}' does not implement abstract class '${AbstractLayerBase.name}`\n );\n }\n }\n this.#layers = layers as (Layer & AbstractLayer)[];\n this.#parent = parent;\n }\n\n /**\n * Destroys this collection, all contained layers are detached from their parent group layer\n */\n destroy() {\n for (const layer of this.#layers) {\n layer.__detachFromGroup();\n layer.destroy();\n }\n this.#layers = [];\n }\n\n // Generic method name for consistent interface\n getItems(options?: LayerRetrievalOptions): (AbstractLayer & Layer)[] {\n return this.getLayers(options);\n }\n\n getLayers(_options?: LayerRetrievalOptions | undefined): (AbstractLayer & Layer)[] {\n // NOTE: options are ignored because layers are always ordered at this time.\n return this.#layers.slice();\n }\n\n getRecursiveLayers(_options?: RecursiveRetrievalOptions): AnyLayer[] {\n return getRecursiveLayers({\n from: this,\n sortByDisplayOrder: _options?.sortByDisplayOrder,\n filter: _options?.filter\n });\n }\n\n /**\n * Returns a reference to the internal group layer array.\n *\n * NOTE: Do not modify directly!\n */\n __getRawLayers(): (AbstractLayer & Layer)[] {\n return this.#layers;\n }\n\n /**\n * Returns the parent group layer that owns this collection.\n */\n __getParent(): GroupLayer {\n return this.#parent;\n }\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SimpleLayerImpl.js","sources":["SimpleLayerImpl.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2023-2025 Open Pioneer project (https://github.com/open-pioneer)\n// SPDX-License-Identifier: Apache-2.0\nimport { SimpleLayer } from \"../../api\";\nimport { AbstractLayer } from \"../AbstractLayer\";\n\n/**\n * A simple layer that accepts a custom OpenLayer's layer instance.\n *\n * Some API features (such as sublayers) will not be available.\n */\nexport class SimpleLayerImpl extends AbstractLayer implements SimpleLayer {\n get type() {\n return \"simple\" as const;\n }\n\n get legend(): undefined {\n return undefined;\n }\n\n get layers(): undefined {\n return undefined;\n }\n\n get sublayers(): undefined {\n return undefined;\n }\n}\n"],"names":[],"mappings":";;AAUO,MAAM,wBAAwB,
|
|
1
|
+
{"version":3,"file":"SimpleLayerImpl.js","sources":["SimpleLayerImpl.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2023-2025 Open Pioneer project (https://github.com/open-pioneer)\n// SPDX-License-Identifier: Apache-2.0\nimport { SimpleLayer } from \"../../api\";\nimport { AbstractLayer } from \"../AbstractLayer\";\n\n/**\n * A simple layer that accepts a custom OpenLayer's layer instance.\n *\n * Some API features (such as sublayers) will not be available.\n */\nexport class SimpleLayerImpl extends AbstractLayer implements SimpleLayer {\n get type() {\n return \"simple\" as const;\n }\n\n get legend(): undefined {\n return undefined;\n }\n\n get layers(): undefined {\n return undefined;\n }\n\n get sublayers(): undefined {\n return undefined;\n }\n}\n"],"names":[],"mappings":";;AAUO,MAAM,wBAAwB,aAAA,CAAqC;AAAA,EACtE,IAAI,IAAA,GAAO;AACP,IAAA,OAAO,QAAA;AAAA,EACX;AAAA,EAEA,IAAI,MAAA,GAAoB;AACpB,IAAA,OAAO,MAAA;AAAA,EACX;AAAA,EAEA,IAAI,MAAA,GAAoB;AACpB,IAAA,OAAO,MAAA;AAAA,EACX;AAAA,EAEA,IAAI,SAAA,GAAuB;AACvB,IAAA,OAAO,MAAA;AAAA,EACX;AACJ;;;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"WMSLayerImpl.js","sources":["WMSLayerImpl.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2023-2025 Open Pioneer project (https://github.com/open-pioneer)\n// SPDX-License-Identifier: Apache-2.0\nimport {\n batch,\n computed,\n Reactive,\n reactive,\n ReadonlyReactive,\n watch\n} from \"@conterra/reactivity-core\";\nimport { createLogger, destroyResource, isAbortError, Resource } from \"@open-pioneer/core\";\nimport { ImageWrapper } from \"ol\";\nimport WMSCapabilities from \"ol/format/WMSCapabilities\";\nimport ImageLayer from \"ol/layer/Image\";\nimport type ImageSource from \"ol/source/Image\";\nimport ImageWMS from \"ol/source/ImageWMS\";\nimport { WMSLayer, WMSLayerConfig, WMSSublayer, WMSSublayerConfig } from \"../../api\";\nimport { fetchCapabilities } from \"../../util/capabilities-utils\";\nimport { AbstractLayer } from \"../AbstractLayer\";\nimport { AbstractLayerBase } from \"../AbstractLayerBase\";\nimport { MapModelImpl } from \"../MapModelImpl\";\nimport { SublayersCollectionImpl } from \"../SublayersCollectionImpl\";\n\nconst LOG = createLogger(\"map:WMSLayer\");\n\nexport class WMSLayerImpl extends AbstractLayer implements WMSLayer {\n #url: string;\n #sublayers: SublayersCollectionImpl<WMSSublayerImpl>;\n #layer: ImageLayer<ImageSource>;\n #source: ImageWMS;\n #fetchCapabilities: boolean;\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n #capabilities: Record<string, any> | undefined;\n readonly #abortController = new AbortController();\n\n #visibleSublayers: ReadonlyReactive<string[]>;\n #sublayersWatch: Resource | undefined;\n\n constructor(config: WMSLayerConfig) {\n const layer = new ImageLayer();\n super({\n ...config,\n olLayer: layer\n });\n const source = new ImageWMS({\n ...config.sourceOptions,\n url: config.url,\n params: {\n ...config.sourceOptions?.params\n },\n // Use http service to load tiles; needed for authentication etc.\n imageLoadFunction: (wrapper, url) => {\n return this.#loadImage(wrapper, url).catch((error) => {\n LOG.error(`Failed to load tile at '${url}'`, error);\n });\n }\n });\n this.#url = config.url;\n this.#fetchCapabilities = config.fetchCapabilities ?? true;\n this.#source = source;\n this.#layer = layer;\n this.#sublayers = new SublayersCollectionImpl(constructSublayers(config.sublayers));\n this.#visibleSublayers = computed(() => this.#getVisibleLayerNames(), {\n equal(a, b) {\n return a.length === b.length && a.every((v, i) => v === b[i]);\n }\n });\n\n this.#sublayersWatch = watch(\n () => [this.#visibleSublayers.value],\n ([layers]) => {\n this.#updateLayersParam(layers);\n },\n {\n immediate: true\n }\n );\n }\n\n destroy() {\n this.#abortController.abort();\n this.#sublayersWatch = destroyResource(this.#sublayersWatch);\n super.destroy();\n }\n\n get type() {\n return \"wms\" as const;\n }\n\n get legend() {\n return undefined;\n }\n\n get url(): string {\n return this.#url;\n }\n\n get layers(): undefined {\n return undefined;\n }\n\n get sublayers(): SublayersCollectionImpl<WMSSublayerImpl> {\n return this.#sublayers;\n }\n\n get capabilities() {\n return this.#capabilities;\n }\n\n __attachToMap(map: MapModelImpl): void {\n super.__attachToMap(map);\n for (const sublayer of this.#sublayers.getSublayers()) {\n sublayer.__attach(map, this, this);\n }\n\n /** Find all leaf nodes representing a layer in the structure */\n const getNestedSublayer = (sublayers: WMSSublayerImpl[], layers: WMSSublayerImpl[]) => {\n for (const sublayer of sublayers) {\n const nested = sublayer.sublayers.getSublayers();\n if (nested.length) {\n getNestedSublayer(nested, layers);\n } else {\n if (sublayer.name) {\n layers.push(sublayer);\n }\n }\n }\n };\n\n if (!this.#fetchCapabilities) {\n return;\n }\n\n this.#fetchWMSCapabilities()\n .then((result: string) => {\n batch(() => {\n const parser = new WMSCapabilities();\n const capabilities = parser.read(result);\n this.#capabilities = capabilities;\n\n const layers: WMSSublayerImpl[] = [];\n getNestedSublayer(this.#sublayers.getSublayers(), layers);\n\n for (const layer of layers) {\n const legendUrl = getWMSLegendUrl(capabilities, layer.name!);\n layer.__setLegend(legendUrl);\n }\n });\n })\n .catch((error) => {\n if (isAbortError(error)) {\n LOG.debug(`Layer ${this.id} has been destroyed before fetching capabilities`);\n return;\n }\n LOG.error(`Failed to fetch WMS capabilities for layer ${this.id}`, error);\n });\n }\n\n /**\n * Gathers the visibility of _all_ sublayers and assembles the 'layers' WMS parameter.\n * The parameters are then applied to the WMS source.\n */\n #updateLayersParam(layers: string[]) {\n this.#source.updateParams({\n \"LAYERS\": layers\n });\n\n // only set source if there are visible sublayers, otherwise\n // we send an invalid http request\n const source = layers.length === 0 ? null : this.#source;\n if (this.#layer.getSource() !== source) {\n this.#layer.setSource(source);\n }\n }\n\n #getVisibleLayerNames() {\n const layers: string[] = [];\n const visitSublayer = (sublayer: WMSSublayerImpl) => {\n if (!sublayer.visible) {\n return;\n }\n\n const nestedSublayers = sublayer.sublayers.__getRawSublayers();\n if (nestedSublayers.length) {\n for (const nestedSublayer of nestedSublayers) {\n visitSublayer(nestedSublayer);\n }\n } else {\n /**\n * Push sublayer only, if layer name is not an empty string | undefined | ...\n */\n if (sublayer.name) {\n layers.push(sublayer.name);\n }\n }\n };\n\n for (const sublayer of this.sublayers.__getRawSublayers()) {\n visitSublayer(sublayer);\n }\n return layers;\n }\n\n async #fetchWMSCapabilities(): Promise<string> {\n const httpService = this.map.__sharedDependencies.httpService;\n const url = `${this.#url}?LANGUAGE=ger&SERVICE=WMS&REQUEST=GetCapabilities`;\n return fetchCapabilities(url, httpService, this.#abortController.signal);\n }\n\n async #loadImage(imageWrapper: ImageWrapper, imageUrl: string): Promise<void> {\n const httpService = this.map.__sharedDependencies.httpService;\n const image = imageWrapper.getImage() as HTMLImageElement;\n\n const response = await httpService.fetch(imageUrl);\n if (!response.ok) {\n throw new Error(`Request failed with status ${response.status}.`);\n }\n\n const blob = await response.blob();\n const objectUrl = URL.createObjectURL(blob);\n const finish = () => {\n // Cleanup object URL after load to prevent memory leaks.\n // https://stackoverflow.com/questions/62473876/openlayers-6-settileloadfunction-documented-example-uses-url-createobjecturld\n URL.revokeObjectURL(objectUrl);\n image.removeEventListener(\"load\", finish);\n image.removeEventListener(\"error\", finish);\n };\n\n image.addEventListener(\"load\", finish);\n image.addEventListener(\"error\", finish);\n image.src = objectUrl;\n }\n}\n\nclass WMSSublayerImpl extends AbstractLayerBase implements WMSSublayer {\n #parent: WMSSublayerImpl | WMSLayerImpl | undefined;\n #parentLayer: WMSLayerImpl | undefined;\n #name: string | undefined;\n #legend = reactive<string | undefined>();\n #sublayers: SublayersCollectionImpl<WMSSublayerImpl>;\n #visible: Reactive<boolean>;\n\n constructor(config: WMSSublayerConfig) {\n super(config);\n this.#name = config.name;\n this.#visible = reactive(config.visible ?? true);\n this.#sublayers = new SublayersCollectionImpl(constructSublayers(config.sublayers));\n }\n\n get type() {\n return \"wms-sublayer\" as const;\n }\n\n get name(): string | undefined {\n return this.#name;\n }\n\n get layers(): undefined {\n return undefined;\n }\n\n get sublayers(): SublayersCollectionImpl<WMSSublayerImpl> {\n return this.#sublayers;\n }\n\n get parent(): WMSSublayerImpl | WMSLayerImpl {\n const parent = this.#parent;\n if (!parent) {\n throw new Error(`WMS sublayer ${this.id} has not been attached to its parent yet.`);\n }\n return parent;\n }\n\n get parentLayer(): WMSLayerImpl {\n const parentLayer = this.#parentLayer;\n if (!parentLayer) {\n throw new Error(`WMS sublayer ${this.id} has not been attached to its parent yet.`);\n }\n return parentLayer;\n }\n\n get legend(): string | undefined {\n return this.#legend.value;\n }\n\n get visible(): boolean {\n return this.#visible.value;\n }\n\n /**\n * Called by the parent layer when it is attached to the map to attach all sublayers.\n */\n __attach(\n map: MapModelImpl,\n parentLayer: WMSLayerImpl,\n parent: WMSLayerImpl | WMSSublayerImpl\n ): void {\n super.__attachToMap(map);\n if (this.#parent) {\n throw new Error(\n `WMS sublayer '${this.id}' has already been attached to parent '${this.#parent.id}'`\n );\n }\n this.#parent = parent;\n if (this.#parentLayer) {\n throw new Error(\n `WMS sublayer '${this.id}' has already been attached to parent layer '${this.#parentLayer.id}'`\n );\n }\n this.#parentLayer = parentLayer;\n\n // Recurse into nested sublayers\n for (const sublayer of this.sublayers.__getRawSublayers()) {\n sublayer.__attach(map, parentLayer, this);\n }\n }\n\n /**\n * Called by the parent layer to update the legend on load.\n */\n __setLegend(legendUrl: string | undefined) {\n this.#legend.value = legendUrl;\n }\n\n setVisible(newVisibility: boolean): void {\n this.#visible.value = newVisibility;\n }\n}\n\nfunction constructSublayers(sublayerConfigs: WMSSublayerConfig[] = []): WMSSublayerImpl[] {\n const sublayers: WMSSublayerImpl[] = [];\n try {\n for (const sublayerConfig of sublayerConfigs) {\n sublayers.push(new WMSSublayerImpl(sublayerConfig));\n }\n return sublayers;\n } catch (e) {\n // Ensure previous sublayers are destroyed if a single constructor throws\n while (sublayers.length) {\n const layer = sublayers.pop()!;\n layer?.destroy();\n }\n throw new Error(\"Failed to construct sublayers.\", { cause: e });\n }\n}\n\n/** extract the legend url from the service capabilities */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function getWMSLegendUrl(capabilities: Record<string, any>, layerName: string) {\n const capabilitiesContent = capabilities?.Capability;\n const rootLayerCapabilities = capabilitiesContent?.Layer;\n let url: string | undefined = undefined;\n\n /** Recurse search for the currrent layer within the parsed capabilities service*/\n //eslint-disable-next-line @typescript-eslint/no-explicit-any\n const searchNestedLayer = (layer: Record<string, any>[]) => {\n for (const currentLayer of layer) {\n // spec. if, a layer has a <Name>, then it is a map layer\n if (currentLayer?.Name === layerName) {\n const activeLayer = currentLayer;\n const styles = activeLayer.Style;\n if (!styles || !styles.length) {\n LOG.debug(\"No style in WMS layer capabilities - giving up.\");\n return;\n }\n // by parsing of the service capabilities, every child inherits the parent's legend\n // theorfore, extract the legendURL from the first style object in the array (its own legend)\n const activeStyle = styles[0];\n url = activeStyle.LegendURL?.[0]?.OnlineResource;\n } else if (currentLayer.Layer) {\n searchNestedLayer(currentLayer.Layer);\n }\n }\n };\n if (rootLayerCapabilities) {\n searchNestedLayer(rootLayerCapabilities.Layer);\n }\n return url;\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"WMSLayerImpl.js","sources":["WMSLayerImpl.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2023-2025 Open Pioneer project (https://github.com/open-pioneer)\n// SPDX-License-Identifier: Apache-2.0\nimport {\n batch,\n computed,\n Reactive,\n reactive,\n ReadonlyReactive,\n watch\n} from \"@conterra/reactivity-core\";\nimport { createLogger, destroyResource, isAbortError, Resource } from \"@open-pioneer/core\";\nimport { ImageWrapper } from \"ol\";\nimport WMSCapabilities from \"ol/format/WMSCapabilities\";\nimport ImageLayer from \"ol/layer/Image\";\nimport type ImageSource from \"ol/source/Image\";\nimport ImageWMS from \"ol/source/ImageWMS\";\nimport { WMSLayer, WMSLayerConfig, WMSSublayer, WMSSublayerConfig } from \"../../api\";\nimport { fetchCapabilities } from \"../../util/capabilities-utils\";\nimport { AbstractLayer } from \"../AbstractLayer\";\nimport { AbstractLayerBase } from \"../AbstractLayerBase\";\nimport { MapModelImpl } from \"../MapModelImpl\";\nimport { SublayersCollectionImpl } from \"../SublayersCollectionImpl\";\n\nconst LOG = createLogger(\"map:WMSLayer\");\n\nexport class WMSLayerImpl extends AbstractLayer implements WMSLayer {\n #url: string;\n #sublayers: SublayersCollectionImpl<WMSSublayerImpl>;\n #layer: ImageLayer<ImageSource>;\n #source: ImageWMS;\n #fetchCapabilities: boolean;\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n #capabilities: Record<string, any> | undefined;\n readonly #abortController = new AbortController();\n\n #visibleSublayers: ReadonlyReactive<string[]>;\n #sublayersWatch: Resource | undefined;\n\n constructor(config: WMSLayerConfig) {\n const layer = new ImageLayer();\n super({\n ...config,\n olLayer: layer\n });\n const source = new ImageWMS({\n ...config.sourceOptions,\n url: config.url,\n params: {\n ...config.sourceOptions?.params\n },\n // Use http service to load tiles; needed for authentication etc.\n imageLoadFunction: (wrapper, url) => {\n return this.#loadImage(wrapper, url).catch((error) => {\n LOG.error(`Failed to load tile at '${url}'`, error);\n });\n }\n });\n this.#url = config.url;\n this.#fetchCapabilities = config.fetchCapabilities ?? true;\n this.#source = source;\n this.#layer = layer;\n this.#sublayers = new SublayersCollectionImpl(constructSublayers(config.sublayers));\n this.#visibleSublayers = computed(() => this.#getVisibleLayerNames(), {\n equal(a, b) {\n return a.length === b.length && a.every((v, i) => v === b[i]);\n }\n });\n\n this.#sublayersWatch = watch(\n () => [this.#visibleSublayers.value],\n ([layers]) => {\n this.#updateLayersParam(layers);\n },\n {\n immediate: true\n }\n );\n }\n\n destroy() {\n this.#abortController.abort();\n this.#sublayersWatch = destroyResource(this.#sublayersWatch);\n super.destroy();\n }\n\n get type() {\n return \"wms\" as const;\n }\n\n get legend() {\n return undefined;\n }\n\n get url(): string {\n return this.#url;\n }\n\n get layers(): undefined {\n return undefined;\n }\n\n get sublayers(): SublayersCollectionImpl<WMSSublayerImpl> {\n return this.#sublayers;\n }\n\n get capabilities() {\n return this.#capabilities;\n }\n\n __attachToMap(map: MapModelImpl): void {\n super.__attachToMap(map);\n for (const sublayer of this.#sublayers.getSublayers()) {\n sublayer.__attach(map, this, this);\n }\n\n /** Find all leaf nodes representing a layer in the structure */\n const getNestedSublayer = (sublayers: WMSSublayerImpl[], layers: WMSSublayerImpl[]) => {\n for (const sublayer of sublayers) {\n const nested = sublayer.sublayers.getSublayers();\n if (nested.length) {\n getNestedSublayer(nested, layers);\n } else {\n if (sublayer.name) {\n layers.push(sublayer);\n }\n }\n }\n };\n\n if (!this.#fetchCapabilities) {\n return;\n }\n\n this.#fetchWMSCapabilities()\n .then((result: string) => {\n batch(() => {\n const parser = new WMSCapabilities();\n const capabilities = parser.read(result);\n this.#capabilities = capabilities;\n\n const layers: WMSSublayerImpl[] = [];\n getNestedSublayer(this.#sublayers.getSublayers(), layers);\n\n for (const layer of layers) {\n const legendUrl = getWMSLegendUrl(capabilities, layer.name!);\n layer.__setLegend(legendUrl);\n }\n });\n })\n .catch((error) => {\n if (isAbortError(error)) {\n LOG.debug(`Layer ${this.id} has been destroyed before fetching capabilities`);\n return;\n }\n LOG.error(`Failed to fetch WMS capabilities for layer ${this.id}`, error);\n });\n }\n\n /**\n * Gathers the visibility of _all_ sublayers and assembles the 'layers' WMS parameter.\n * The parameters are then applied to the WMS source.\n */\n #updateLayersParam(layers: string[]) {\n this.#source.updateParams({\n \"LAYERS\": layers\n });\n\n // only set source if there are visible sublayers, otherwise\n // we send an invalid http request\n const source = layers.length === 0 ? null : this.#source;\n if (this.#layer.getSource() !== source) {\n this.#layer.setSource(source);\n }\n }\n\n #getVisibleLayerNames() {\n const layers: string[] = [];\n const visitSublayer = (sublayer: WMSSublayerImpl) => {\n if (!sublayer.visible) {\n return;\n }\n\n const nestedSublayers = sublayer.sublayers.__getRawSublayers();\n if (nestedSublayers.length) {\n for (const nestedSublayer of nestedSublayers) {\n visitSublayer(nestedSublayer);\n }\n } else {\n /**\n * Push sublayer only, if layer name is not an empty string | undefined | ...\n */\n if (sublayer.name) {\n layers.push(sublayer.name);\n }\n }\n };\n\n for (const sublayer of this.sublayers.__getRawSublayers()) {\n visitSublayer(sublayer);\n }\n return layers;\n }\n\n async #fetchWMSCapabilities(): Promise<string> {\n const httpService = this.map.__sharedDependencies.httpService;\n const url = `${this.#url}?LANGUAGE=ger&SERVICE=WMS&REQUEST=GetCapabilities`;\n return fetchCapabilities(url, httpService, this.#abortController.signal);\n }\n\n async #loadImage(imageWrapper: ImageWrapper, imageUrl: string): Promise<void> {\n const httpService = this.map.__sharedDependencies.httpService;\n const image = imageWrapper.getImage() as HTMLImageElement;\n\n const response = await httpService.fetch(imageUrl);\n if (!response.ok) {\n throw new Error(`Request failed with status ${response.status}.`);\n }\n\n const blob = await response.blob();\n const objectUrl = URL.createObjectURL(blob);\n const finish = () => {\n // Cleanup object URL after load to prevent memory leaks.\n // https://stackoverflow.com/questions/62473876/openlayers-6-settileloadfunction-documented-example-uses-url-createobjecturld\n URL.revokeObjectURL(objectUrl);\n image.removeEventListener(\"load\", finish);\n image.removeEventListener(\"error\", finish);\n };\n\n image.addEventListener(\"load\", finish);\n image.addEventListener(\"error\", finish);\n image.src = objectUrl;\n }\n}\n\nclass WMSSublayerImpl extends AbstractLayerBase implements WMSSublayer {\n #parent: WMSSublayerImpl | WMSLayerImpl | undefined;\n #parentLayer: WMSLayerImpl | undefined;\n #name: string | undefined;\n #legend = reactive<string | undefined>();\n #sublayers: SublayersCollectionImpl<WMSSublayerImpl>;\n #visible: Reactive<boolean>;\n\n constructor(config: WMSSublayerConfig) {\n super(config);\n this.#name = config.name;\n this.#visible = reactive(config.visible ?? true);\n this.#sublayers = new SublayersCollectionImpl(constructSublayers(config.sublayers));\n }\n\n get type() {\n return \"wms-sublayer\" as const;\n }\n\n get name(): string | undefined {\n return this.#name;\n }\n\n get layers(): undefined {\n return undefined;\n }\n\n get sublayers(): SublayersCollectionImpl<WMSSublayerImpl> {\n return this.#sublayers;\n }\n\n get parent(): WMSSublayerImpl | WMSLayerImpl {\n const parent = this.#parent;\n if (!parent) {\n throw new Error(`WMS sublayer ${this.id} has not been attached to its parent yet.`);\n }\n return parent;\n }\n\n get parentLayer(): WMSLayerImpl {\n const parentLayer = this.#parentLayer;\n if (!parentLayer) {\n throw new Error(`WMS sublayer ${this.id} has not been attached to its parent yet.`);\n }\n return parentLayer;\n }\n\n get legend(): string | undefined {\n return this.#legend.value;\n }\n\n get visible(): boolean {\n return this.#visible.value;\n }\n\n /**\n * Called by the parent layer when it is attached to the map to attach all sublayers.\n */\n __attach(\n map: MapModelImpl,\n parentLayer: WMSLayerImpl,\n parent: WMSLayerImpl | WMSSublayerImpl\n ): void {\n super.__attachToMap(map);\n if (this.#parent) {\n throw new Error(\n `WMS sublayer '${this.id}' has already been attached to parent '${this.#parent.id}'`\n );\n }\n this.#parent = parent;\n if (this.#parentLayer) {\n throw new Error(\n `WMS sublayer '${this.id}' has already been attached to parent layer '${this.#parentLayer.id}'`\n );\n }\n this.#parentLayer = parentLayer;\n\n // Recurse into nested sublayers\n for (const sublayer of this.sublayers.__getRawSublayers()) {\n sublayer.__attach(map, parentLayer, this);\n }\n }\n\n /**\n * Called by the parent layer to update the legend on load.\n */\n __setLegend(legendUrl: string | undefined) {\n this.#legend.value = legendUrl;\n }\n\n setVisible(newVisibility: boolean): void {\n this.#visible.value = newVisibility;\n }\n}\n\nfunction constructSublayers(sublayerConfigs: WMSSublayerConfig[] = []): WMSSublayerImpl[] {\n const sublayers: WMSSublayerImpl[] = [];\n try {\n for (const sublayerConfig of sublayerConfigs) {\n sublayers.push(new WMSSublayerImpl(sublayerConfig));\n }\n return sublayers;\n } catch (e) {\n // Ensure previous sublayers are destroyed if a single constructor throws\n while (sublayers.length) {\n const layer = sublayers.pop()!;\n layer?.destroy();\n }\n throw new Error(\"Failed to construct sublayers.\", { cause: e });\n }\n}\n\n/** extract the legend url from the service capabilities */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function getWMSLegendUrl(capabilities: Record<string, any>, layerName: string) {\n const capabilitiesContent = capabilities?.Capability;\n const rootLayerCapabilities = capabilitiesContent?.Layer;\n let url: string | undefined = undefined;\n\n /** Recurse search for the currrent layer within the parsed capabilities service*/\n //eslint-disable-next-line @typescript-eslint/no-explicit-any\n const searchNestedLayer = (layer: Record<string, any>[]) => {\n for (const currentLayer of layer) {\n // spec. if, a layer has a <Name>, then it is a map layer\n if (currentLayer?.Name === layerName) {\n const activeLayer = currentLayer;\n const styles = activeLayer.Style;\n if (!styles || !styles.length) {\n LOG.debug(\"No style in WMS layer capabilities - giving up.\");\n return;\n }\n // by parsing of the service capabilities, every child inherits the parent's legend\n // theorfore, extract the legendURL from the first style object in the array (its own legend)\n const activeStyle = styles[0];\n url = activeStyle.LegendURL?.[0]?.OnlineResource;\n } else if (currentLayer.Layer) {\n searchNestedLayer(currentLayer.Layer);\n }\n }\n };\n if (rootLayerCapabilities) {\n searchNestedLayer(rootLayerCapabilities.Layer);\n }\n return url;\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"WMTSLayerImpl.js","sources":["WMTSLayerImpl.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2023-2025 Open Pioneer project (https://github.com/open-pioneer)\n// SPDX-License-Identifier: Apache-2.0\nimport { createLogger, isAbortError } from \"@open-pioneer/core\";\nimport Tile from \"ol/Tile\";\nimport TileState from \"ol/TileState\";\nimport WMTSCapabilities from \"ol/format/WMTSCapabilities\";\nimport TileLayer from \"ol/layer/Tile\";\nimport type TileSourceType from \"ol/source/Tile\";\nimport WMTS, { optionsFromCapabilities } from \"ol/source/WMTS\";\nimport { WMTSLayer, WMTSLayerConfig } from \"../../api\";\nimport { fetchCapabilities } from \"../../util/capabilities-utils\";\nimport { AbstractLayer } from \"../AbstractLayer\";\nimport { MapModelImpl } from \"../MapModelImpl\";\nimport { ImageTile } from \"ol\";\nimport type { Options as WMSSourceOptions } from \"ol/source/ImageWMS\";\nimport { reactive } from \"@conterra/reactivity-core\";\n\nconst LOG = createLogger(\"map:WMTSLayer\");\n\nexport class WMTSLayerImpl extends AbstractLayer implements WMTSLayer {\n #url: string;\n #name: string;\n #matrixSet: string;\n #layer: TileLayer<TileSourceType>;\n #source: WMTS | undefined;\n #sourceOptions?: Partial<WMSSourceOptions>;\n #legend = reactive<string | undefined>();\n readonly #abortController = new AbortController();\n\n constructor(config: WMTSLayerConfig) {\n const layer = new TileLayer();\n super({\n ...config,\n olLayer: layer\n });\n this.#url = config.url;\n this.#name = config.name;\n this.#layer = layer;\n this.#matrixSet = config.matrixSet;\n this.#sourceOptions = config.sourceOptions;\n }\n\n get type() {\n return \"wmts\" as const;\n }\n\n destroy(): void {\n this.#abortController.abort();\n super.destroy();\n }\n\n get legend(): string | undefined {\n return this.#legend.value;\n }\n\n get sublayers(): undefined {\n return undefined;\n }\n\n get layers(): undefined {\n return undefined;\n }\n\n __attachToMap(map: MapModelImpl): void {\n super.__attachToMap(map);\n this.#fetchWMTSCapabilities()\n .then((result: string) => {\n const parser = new WMTSCapabilities();\n const capabilities = parser.read(result);\n const options = optionsFromCapabilities(capabilities, {\n layer: this.#name,\n matrixSet: this.#matrixSet\n });\n if (!options) {\n throw new Error(\"Layer was not found in capabilities\");\n }\n const source = new WMTS({\n ...options,\n ...this.#sourceOptions,\n tileLoadFunction: (tile, tileUrl) => {\n this.#loadTile(tile, tileUrl);\n }\n });\n this.#source = source;\n this.#layer.setSource(this.#source);\n const activeStyleId = source.getStyle();\n const legendUrl = getWMTSLegendUrl(capabilities, this.name, activeStyleId);\n this.#legend.value = legendUrl;\n })\n .catch((error) => {\n if (isAbortError(error)) {\n LOG.error(`Layer ${this.name} has been destroyed before fetching the data`);\n return;\n }\n LOG.error(`Failed fetching WMTS capabilities for Layer ${this.name}`, error);\n });\n }\n\n get url() {\n return this.#url;\n }\n\n get name() {\n return this.#name;\n }\n\n get matrixSet() {\n return this.#matrixSet;\n }\n\n async #fetchWMTSCapabilities(): Promise<string> {\n const httpService = this.map.__sharedDependencies.httpService;\n return fetchCapabilities(this.#url, httpService, this.#abortController.signal);\n }\n\n async #loadTile(tile: Tile, tileUrl: string): Promise<void> {\n const httpService = this.map.__sharedDependencies.httpService;\n try {\n if (!(tile instanceof ImageTile)) {\n throw new Error(\"Only 'ImageTile' is supported for now.\");\n }\n\n const image = tile.getImage();\n if (!isHtmlImage(image)) {\n // Could also be canvas or video\n throw new Error(\"Only <img> tags are supported as tiles for now.\");\n }\n\n const response = await httpService.fetch(tileUrl);\n if (!response.ok) {\n throw new Error(`Tile request failed with status ${response.status}.`);\n }\n\n const blob = await response.blob();\n const objectUrl = URL.createObjectURL(blob);\n const finish = () => {\n // Cleanup object URL after load to prevent memory leaks.\n // https://stackoverflow.com/questions/62473876/openlayers-6-settileloadfunction-documented-example-uses-url-createobjecturld\n URL.revokeObjectURL(objectUrl);\n image.removeEventListener(\"load\", finish);\n image.removeEventListener(\"error\", finish);\n };\n image.addEventListener(\"load\", finish);\n image.addEventListener(\"error\", finish);\n image.src = objectUrl;\n } catch (e) {\n tile.setState(TileState.ERROR);\n if (!isAbortError(e)) {\n LOG.error(\"Failed to load tile\", e);\n }\n }\n }\n}\n\nfunction isHtmlImage(htmlElement: HTMLElement): htmlElement is HTMLImageElement {\n return htmlElement.tagName === \"IMG\";\n}\n/* eslint-disable @typescript-eslint/no-explicit-any */\nexport function getWMTSLegendUrl(\n capabilities: Record<string, any>,\n activeLayerId: string | undefined,\n activeStyleId: string | undefined\n): string | undefined {\n const content = capabilities?.Contents;\n const layers = content?.Layer;\n\n let activeLayer = layers?.find((layer: any) => layer?.Identifier === activeLayerId);\n if (!activeLayer) {\n LOG.debug(\"Failed to find the active layer in WMTS layer capabilities.\");\n activeLayer = layers?.[0];\n if (!activeLayer) {\n LOG.debug(\"No layer in WMTS capabilities - giving up.\");\n return undefined;\n }\n }\n\n const styles = activeLayer.Style;\n let activeStyle = styles?.find((style: any) => style?.Identifier === activeStyleId);\n if (!activeStyle) {\n LOG.debug(\"Failed to find active style in WMTS layer.\");\n activeStyle = styles?.[0];\n if (!activeStyle) {\n LOG.debug(\"No style in WMTS layer capabilities - giving up.\");\n return undefined;\n }\n }\n\n const legendUrl = activeStyle.LegendURL?.[0]?.href;\n return legendUrl as string | undefined;\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"WMTSLayerImpl.js","sources":["WMTSLayerImpl.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2023-2025 Open Pioneer project (https://github.com/open-pioneer)\n// SPDX-License-Identifier: Apache-2.0\nimport { createLogger, isAbortError } from \"@open-pioneer/core\";\nimport Tile from \"ol/Tile\";\nimport TileState from \"ol/TileState\";\nimport WMTSCapabilities from \"ol/format/WMTSCapabilities\";\nimport TileLayer from \"ol/layer/Tile\";\nimport type TileSourceType from \"ol/source/Tile\";\nimport WMTS, { optionsFromCapabilities } from \"ol/source/WMTS\";\nimport { WMTSLayer, WMTSLayerConfig } from \"../../api\";\nimport { fetchCapabilities } from \"../../util/capabilities-utils\";\nimport { AbstractLayer } from \"../AbstractLayer\";\nimport { MapModelImpl } from \"../MapModelImpl\";\nimport { ImageTile } from \"ol\";\nimport type { Options as WMSSourceOptions } from \"ol/source/ImageWMS\";\nimport { reactive } from \"@conterra/reactivity-core\";\n\nconst LOG = createLogger(\"map:WMTSLayer\");\n\nexport class WMTSLayerImpl extends AbstractLayer implements WMTSLayer {\n #url: string;\n #name: string;\n #matrixSet: string;\n #layer: TileLayer<TileSourceType>;\n #source: WMTS | undefined;\n #sourceOptions?: Partial<WMSSourceOptions>;\n #legend = reactive<string | undefined>();\n readonly #abortController = new AbortController();\n\n constructor(config: WMTSLayerConfig) {\n const layer = new TileLayer();\n super({\n ...config,\n olLayer: layer\n });\n this.#url = config.url;\n this.#name = config.name;\n this.#layer = layer;\n this.#matrixSet = config.matrixSet;\n this.#sourceOptions = config.sourceOptions;\n }\n\n get type() {\n return \"wmts\" as const;\n }\n\n destroy(): void {\n this.#abortController.abort();\n super.destroy();\n }\n\n get legend(): string | undefined {\n return this.#legend.value;\n }\n\n get sublayers(): undefined {\n return undefined;\n }\n\n get layers(): undefined {\n return undefined;\n }\n\n __attachToMap(map: MapModelImpl): void {\n super.__attachToMap(map);\n this.#fetchWMTSCapabilities()\n .then((result: string) => {\n const parser = new WMTSCapabilities();\n const capabilities = parser.read(result);\n const options = optionsFromCapabilities(capabilities, {\n layer: this.#name,\n matrixSet: this.#matrixSet\n });\n if (!options) {\n throw new Error(\"Layer was not found in capabilities\");\n }\n const source = new WMTS({\n ...options,\n ...this.#sourceOptions,\n tileLoadFunction: (tile, tileUrl) => {\n this.#loadTile(tile, tileUrl);\n }\n });\n this.#source = source;\n this.#layer.setSource(this.#source);\n const activeStyleId = source.getStyle();\n const legendUrl = getWMTSLegendUrl(capabilities, this.name, activeStyleId);\n this.#legend.value = legendUrl;\n })\n .catch((error) => {\n if (isAbortError(error)) {\n LOG.error(`Layer ${this.name} has been destroyed before fetching the data`);\n return;\n }\n LOG.error(`Failed fetching WMTS capabilities for Layer ${this.name}`, error);\n });\n }\n\n get url() {\n return this.#url;\n }\n\n get name() {\n return this.#name;\n }\n\n get matrixSet() {\n return this.#matrixSet;\n }\n\n async #fetchWMTSCapabilities(): Promise<string> {\n const httpService = this.map.__sharedDependencies.httpService;\n return fetchCapabilities(this.#url, httpService, this.#abortController.signal);\n }\n\n async #loadTile(tile: Tile, tileUrl: string): Promise<void> {\n const httpService = this.map.__sharedDependencies.httpService;\n try {\n if (!(tile instanceof ImageTile)) {\n throw new Error(\"Only 'ImageTile' is supported for now.\");\n }\n\n const image = tile.getImage();\n if (!isHtmlImage(image)) {\n // Could also be canvas or video\n throw new Error(\"Only <img> tags are supported as tiles for now.\");\n }\n\n const response = await httpService.fetch(tileUrl);\n if (!response.ok) {\n throw new Error(`Tile request failed with status ${response.status}.`);\n }\n\n const blob = await response.blob();\n const objectUrl = URL.createObjectURL(blob);\n const finish = () => {\n // Cleanup object URL after load to prevent memory leaks.\n // https://stackoverflow.com/questions/62473876/openlayers-6-settileloadfunction-documented-example-uses-url-createobjecturld\n URL.revokeObjectURL(objectUrl);\n image.removeEventListener(\"load\", finish);\n image.removeEventListener(\"error\", finish);\n };\n image.addEventListener(\"load\", finish);\n image.addEventListener(\"error\", finish);\n image.src = objectUrl;\n } catch (e) {\n tile.setState(TileState.ERROR);\n if (!isAbortError(e)) {\n LOG.error(\"Failed to load tile\", e);\n }\n }\n }\n}\n\nfunction isHtmlImage(htmlElement: HTMLElement): htmlElement is HTMLImageElement {\n return htmlElement.tagName === \"IMG\";\n}\n/* eslint-disable @typescript-eslint/no-explicit-any */\nexport function getWMTSLegendUrl(\n capabilities: Record<string, any>,\n activeLayerId: string | undefined,\n activeStyleId: string | undefined\n): string | undefined {\n const content = capabilities?.Contents;\n const layers = content?.Layer;\n\n let activeLayer = layers?.find((layer: any) => layer?.Identifier === activeLayerId);\n if (!activeLayer) {\n LOG.debug(\"Failed to find the active layer in WMTS layer capabilities.\");\n activeLayer = layers?.[0];\n if (!activeLayer) {\n LOG.debug(\"No layer in WMTS capabilities - giving up.\");\n return undefined;\n }\n }\n\n const styles = activeLayer.Style;\n let activeStyle = styles?.find((style: any) => style?.Identifier === activeStyleId);\n if (!activeStyle) {\n LOG.debug(\"Failed to find active style in WMTS layer.\");\n activeStyle = styles?.[0];\n if (!activeStyle) {\n LOG.debug(\"No style in WMTS layer capabilities - giving up.\");\n return undefined;\n }\n }\n\n const legendUrl = activeStyle.LegendURL?.[0]?.href;\n return legendUrl as string | undefined;\n}\n"],"names":[],"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": "0.
|
|
4
|
+
"version": "0.12.0-dev.20250905090001",
|
|
5
5
|
"description": "This package integrates OpenLayers maps into an open pioneer trails application.",
|
|
6
6
|
"keywords": [
|
|
7
7
|
"open-pioneer-trails"
|
|
@@ -14,16 +14,15 @@
|
|
|
14
14
|
"directory": "src/packages/map"
|
|
15
15
|
},
|
|
16
16
|
"dependencies": {
|
|
17
|
-
"@chakra-ui/react": "^3.
|
|
17
|
+
"@chakra-ui/react": "^3.24.2",
|
|
18
18
|
"@open-pioneer/core": "^4.0.0",
|
|
19
19
|
"@open-pioneer/http": "^4.0.0",
|
|
20
20
|
"@open-pioneer/react-utils": "^4.0.0",
|
|
21
21
|
"@open-pioneer/runtime": "^4.0.0",
|
|
22
|
-
"
|
|
23
|
-
"
|
|
24
|
-
"
|
|
25
|
-
"react": "^19.1.
|
|
26
|
-
"react-dom": "^19.1.0",
|
|
22
|
+
"ol": "^10.6.1",
|
|
23
|
+
"proj4": "^2.19.10",
|
|
24
|
+
"react": "^19.1.1",
|
|
25
|
+
"react-dom": "^19.1.1",
|
|
27
26
|
"react-use": "^17.6.0",
|
|
28
27
|
"uuid": "^11.1.0",
|
|
29
28
|
"@conterra/reactivity-core": "^0.7.0"
|
package/projections.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import
|
|
1
|
+
import proj4 from "proj4";
|
|
2
|
+
type Proj4ProjectionDefinition = typeof proj4.defs extends infer R ? R extends (name: string) => unknown ? ReturnType<R> : never : never;
|
|
2
3
|
export type ProjectionDefinition = string | Proj4ProjectionDefinition;
|
|
3
4
|
/**
|
|
4
5
|
* Adds new registrations to the global [proj4js](https://github.com/proj4js/proj4js) definition set.
|
|
@@ -25,3 +26,4 @@ export declare function registerProjections(projections: Record<string, Projecti
|
|
|
25
26
|
* Searches the global [proj4js](https://github.com/proj4js/proj4js) definition set for a definition with the given name.
|
|
26
27
|
*/
|
|
27
28
|
export declare function getProjection(name: string): Proj4ProjectionDefinition;
|
|
29
|
+
export {};
|
package/projections.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"projections.js","sources":["projections.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2023-2025 Open Pioneer project (https://github.com/open-pioneer)\n// SPDX-License-Identifier: Apache-2.0\nimport { register } from \"ol/proj/proj4\";\nimport proj4
|
|
1
|
+
{"version":3,"file":"projections.js","sources":["projections.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2023-2025 Open Pioneer project (https://github.com/open-pioneer)\n// SPDX-License-Identifier: Apache-2.0\nimport { register } from \"ol/proj/proj4\";\nimport proj4 from \"proj4\";\n\n// Select return type of (name: string) => ProjectionDefinition overload since ProjectionDefinition is not exported\ntype Proj4ProjectionDefinition = typeof proj4.defs extends infer R\n ? R extends (name: string) => unknown\n ? ReturnType<R>\n : never\n : never;\n\nexport type ProjectionDefinition = string | Proj4ProjectionDefinition;\n\n/**\n * Adds new registrations to the global [proj4js](https://github.com/proj4js/proj4js) definition set.\n *\n * See the proj4js documentation for more details.\n *\n * Example:\n *\n * ```ts\n * import { registerProjections } from \"@open-pioneer/map\";\n *\n * registerProjections({\n * \"EPSG:25832\": \"+proj=utm +zone=32 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs +type=crs\",\n * // ... more projections\n * });\n * ```\n *\n * @param projections\n * An object containing (key, definition) pairs. The key must be projection name (such as `\"EPSG:4326\"`).\n * The value can be a string defining the projection or an existing proj4 definition object.\n */\nexport function registerProjections(projections: Record<string, ProjectionDefinition>): void {\n for (const [name, definition] of Object.entries(projections)) {\n proj4.defs(name, definition);\n }\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n register(proj4 as any);\n}\n\n/**\n * Searches the global [proj4js](https://github.com/proj4js/proj4js) definition set for a definition with the given name.\n */\nexport function getProjection(name: string): Proj4ProjectionDefinition {\n return proj4.defs(name);\n}\n"],"names":[],"mappings":";;;AAkCO,SAAS,oBAAoB,WAAA,EAAyD;AACzF,EAAA,KAAA,MAAW,CAAC,IAAA,EAAM,UAAU,KAAK,MAAA,CAAO,OAAA,CAAQ,WAAW,CAAA,EAAG;AAC1D,IAAA,KAAA,CAAM,IAAA,CAAK,MAAM,UAAU,CAAA;AAAA,EAC/B;AAEA,EAAA,QAAA,CAAS,KAAY,CAAA;AACzB;AAKO,SAAS,cAAc,IAAA,EAAyC;AACnE,EAAA,OAAO,KAAA,CAAM,KAAK,IAAI,CAAA;AAC1B;;;;"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { MapModel } from "../api";
|
|
1
2
|
import { MapModelProps } from "./useMapModel";
|
|
2
3
|
/**
|
|
3
4
|
* Configures the given map as the default map for all child components.
|
|
@@ -14,7 +15,7 @@ import { MapModelProps } from "./useMapModel";
|
|
|
14
15
|
* </DefaultMapProvider>
|
|
15
16
|
* ```
|
|
16
17
|
*/
|
|
17
|
-
export declare function DefaultMapProvider(props: MapModelProps & {
|
|
18
|
+
export declare function DefaultMapProvider(props: Required<MapModelProps> & {
|
|
18
19
|
children?: React.ReactNode;
|
|
19
20
|
}): import("react/jsx-runtime").JSX.Element;
|
|
20
21
|
/**
|
|
@@ -22,4 +23,4 @@ export declare function DefaultMapProvider(props: MapModelProps & {
|
|
|
22
23
|
*
|
|
23
24
|
* @internal
|
|
24
25
|
*/
|
|
25
|
-
export declare function
|
|
26
|
+
export declare function useDefaultMap(): MapModel | undefined;
|
package/ui/DefaultMapProvider.js
CHANGED
|
@@ -1,24 +1,18 @@
|
|
|
1
1
|
import { jsx } from 'react/jsx-runtime';
|
|
2
|
-
import { createContext,
|
|
2
|
+
import { createContext, useContext } from 'react';
|
|
3
3
|
|
|
4
4
|
const DefaultMapContext = createContext(void 0);
|
|
5
5
|
DefaultMapContext.displayName = "DefaultMapContext";
|
|
6
6
|
function DefaultMapProvider(props) {
|
|
7
|
-
const {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
throw new Error(
|
|
11
|
-
`Cannot specify both 'mapId' and 'map' in DefaultMapProvider at the same time.`
|
|
12
|
-
);
|
|
7
|
+
const { map, children } = props;
|
|
8
|
+
if (map == null) {
|
|
9
|
+
throw new Error(`DefaultMapProvider requires the 'map' property.`);
|
|
13
10
|
}
|
|
14
|
-
|
|
15
|
-
throw new Error(`Either 'mapId' or 'map' must be specified in DefaultMapProvider.`);
|
|
16
|
-
}
|
|
17
|
-
return /* @__PURE__ */ jsx(DefaultMapContext.Provider, { value, children });
|
|
11
|
+
return /* @__PURE__ */ jsx(DefaultMapContext.Provider, { value: map, children });
|
|
18
12
|
}
|
|
19
|
-
function
|
|
13
|
+
function useDefaultMap() {
|
|
20
14
|
return useContext(DefaultMapContext);
|
|
21
15
|
}
|
|
22
16
|
|
|
23
|
-
export { DefaultMapProvider,
|
|
17
|
+
export { DefaultMapProvider, useDefaultMap };
|
|
24
18
|
//# sourceMappingURL=DefaultMapProvider.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DefaultMapProvider.js","sources":["DefaultMapProvider.tsx"],"sourcesContent":["// SPDX-FileCopyrightText: 2023-2025 Open Pioneer project (https://github.com/open-pioneer)\n// SPDX-License-Identifier: Apache-2.0\nimport { createContext, useContext
|
|
1
|
+
{"version":3,"file":"DefaultMapProvider.js","sources":["DefaultMapProvider.tsx"],"sourcesContent":["// SPDX-FileCopyrightText: 2023-2025 Open Pioneer project (https://github.com/open-pioneer)\n// SPDX-License-Identifier: Apache-2.0\nimport { createContext, useContext } from \"react\";\nimport { MapModel } from \"../api\";\nimport { MapModelProps } from \"./useMapModel\";\n\nconst DefaultMapContext = createContext<MapModel | undefined>(undefined);\nDefaultMapContext.displayName = \"DefaultMapContext\";\n\n/**\n * Configures the given map as the default map for all child components.\n * Child components do not need to specify the map explicitly, unless they wish to use a different one.\n *\n * @example\n *\n * Using map model reference:\n *\n * ```tsx\n * <DefaultMapProvider map={myMapModel}>\n * <MapContainer />\n * <Toc />\n * </DefaultMapProvider>\n * ```\n */\nexport function DefaultMapProvider(\n props: Required<MapModelProps> & { children?: React.ReactNode }\n) {\n const { map, children } = props;\n if (map == null) {\n throw new Error(`DefaultMapProvider requires the 'map' property.`);\n }\n return <DefaultMapContext.Provider value={map}>{children}</DefaultMapContext.Provider>;\n}\n\n/**\n * Accesses the default map props provided by {@link DefaultMapProvider} (or returns undefined).\n *\n * @internal\n */\nexport function useDefaultMap(): MapModel | undefined {\n return useContext(DefaultMapContext);\n}\n"],"names":[],"mappings":";;;AAMA,MAAM,iBAAA,GAAoB,cAAoC,MAAS,CAAA;AACvE,iBAAA,CAAkB,WAAA,GAAc,mBAAA;AAiBzB,SAAS,mBACZ,KAAA,EACF;AACE,EAAA,MAAM,EAAE,GAAA,EAAK,QAAA,EAAS,GAAI,KAAA;AAC1B,EAAA,IAAI,OAAO,IAAA,EAAM;AACb,IAAA,MAAM,IAAI,MAAM,CAAA,+CAAA,CAAiD,CAAA;AAAA,EACrE;AACA,EAAA,2BAAQ,iBAAA,CAAkB,QAAA,EAAlB,EAA2B,KAAA,EAAO,KAAM,QAAA,EAAS,CAAA;AAC7D;AAOO,SAAS,aAAA,GAAsC;AAClD,EAAA,OAAO,WAAW,iBAAiB,CAAA;AACvC;;;;"}
|
package/ui/MapAnchor.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MapAnchor.js","sources":["MapAnchor.tsx"],"sourcesContent":["// SPDX-FileCopyrightText: 2023-2025 Open Pioneer project (https://github.com/open-pioneer)\n// SPDX-License-Identifier: Apache-2.0\nimport { Box } from \"@chakra-ui/react\";\nimport { CommonComponentProps, useCommonComponentProps } from \"@open-pioneer/react-utils\";\nimport { ReactNode, useMemo } from \"react\";\nimport { createPortal } from \"react-dom\";\nimport { computeMapAnchorStyles } from \"./computeMapAnchorStyles\";\nimport { useMapContainerContext } from \"./MapContainerContext\";\n\n/**\n * The position of an anchor on the map.\n *\n * This is either a predefined position (like a corner) or a completely manual position.\n */\nexport type MapAnchorPosition =\n | \"manual\"\n | \"top-left\"\n | \"top-right\"\n | \"top-center\"\n | \"bottom-left\"\n | \"bottom-right\"\n | \"bottom-center\"\n | \"left-center\"\n | \"right-center\"\n | \"center\";\n\nconst defaultPosition: MapAnchorPosition = \"top-right\";\n\nexport interface MapAnchorProps extends CommonComponentProps {\n /**\n * The position of the anchor container above the map.\n *\n * Use `manual` if you wish to position the anchor manually using absolute positioning.\n * This can be achieved by configuring a css class on the map anchor and using css properties like `left`, `top`, etc.\n *\n * @default \"top-right\"\n */\n position?: MapAnchorPosition;\n\n /**\n * Horizontal gap in pixel applied to anchor container.\n * Only interpreted if a non-manual position is used.\n *\n * @default 0\n */\n horizontalGap?: number;\n\n /**\n * Vertical gap in pixel applied to anchor container.\n * Only interpreted if a non-manual position is used.\n *\n * @default 0 (If positioned at the bottom, default verticalGap == `30`)\n */\n verticalGap?: number;\n\n children?: ReactNode;\n}\n\n/**\n * A map anchor is a layout component that sits on top of the map.\n *\n * It can be used to position widgets (such as zoom buttons) at a specific location.\n *\n * Map anchors respect the map's current _view padding_.\n */\nexport function MapAnchor(props: MapAnchorProps): ReactNode {\n const { position = defaultPosition, children, horizontalGap, verticalGap } = props;\n const { containerProps } = useCommonComponentProps(\"map-anchor\", props);\n const { mapAnchorsHost } = useMapContainerContext();\n const styleProps = useMemo(\n () => computeMapAnchorStyles(position, horizontalGap, verticalGap),\n [position, horizontalGap, verticalGap]\n );\n\n return createPortal(\n <Box {...containerProps} {...styleProps}>\n {children}\n </Box>,\n mapAnchorsHost\n );\n}\n"],"names":[],"mappings":";;;;;;;;AA0BA,MAAM,
|
|
1
|
+
{"version":3,"file":"MapAnchor.js","sources":["MapAnchor.tsx"],"sourcesContent":["// SPDX-FileCopyrightText: 2023-2025 Open Pioneer project (https://github.com/open-pioneer)\n// SPDX-License-Identifier: Apache-2.0\nimport { Box } from \"@chakra-ui/react\";\nimport { CommonComponentProps, useCommonComponentProps } from \"@open-pioneer/react-utils\";\nimport { ReactNode, useMemo } from \"react\";\nimport { createPortal } from \"react-dom\";\nimport { computeMapAnchorStyles } from \"./computeMapAnchorStyles\";\nimport { useMapContainerContext } from \"./MapContainerContext\";\n\n/**\n * The position of an anchor on the map.\n *\n * This is either a predefined position (like a corner) or a completely manual position.\n */\nexport type MapAnchorPosition =\n | \"manual\"\n | \"top-left\"\n | \"top-right\"\n | \"top-center\"\n | \"bottom-left\"\n | \"bottom-right\"\n | \"bottom-center\"\n | \"left-center\"\n | \"right-center\"\n | \"center\";\n\nconst defaultPosition: MapAnchorPosition = \"top-right\";\n\nexport interface MapAnchorProps extends CommonComponentProps {\n /**\n * The position of the anchor container above the map.\n *\n * Use `manual` if you wish to position the anchor manually using absolute positioning.\n * This can be achieved by configuring a css class on the map anchor and using css properties like `left`, `top`, etc.\n *\n * @default \"top-right\"\n */\n position?: MapAnchorPosition;\n\n /**\n * Horizontal gap in pixel applied to anchor container.\n * Only interpreted if a non-manual position is used.\n *\n * @default 0\n */\n horizontalGap?: number;\n\n /**\n * Vertical gap in pixel applied to anchor container.\n * Only interpreted if a non-manual position is used.\n *\n * @default 0 (If positioned at the bottom, default verticalGap == `30`)\n */\n verticalGap?: number;\n\n children?: ReactNode;\n}\n\n/**\n * A map anchor is a layout component that sits on top of the map.\n *\n * It can be used to position widgets (such as zoom buttons) at a specific location.\n *\n * Map anchors respect the map's current _view padding_.\n */\nexport function MapAnchor(props: MapAnchorProps): ReactNode {\n const { position = defaultPosition, children, horizontalGap, verticalGap } = props;\n const { containerProps } = useCommonComponentProps(\"map-anchor\", props);\n const { mapAnchorsHost } = useMapContainerContext();\n const styleProps = useMemo(\n () => computeMapAnchorStyles(position, horizontalGap, verticalGap),\n [position, horizontalGap, verticalGap]\n );\n\n return createPortal(\n <Box {...containerProps} {...styleProps}>\n {children}\n </Box>,\n mapAnchorsHost\n );\n}\n"],"names":[],"mappings":";;;;;;;;AA0BA,MAAM,eAAA,GAAqC,WAAA;AAuCpC,SAAS,UAAU,KAAA,EAAkC;AACxD,EAAA,MAAM,EAAE,QAAA,GAAW,eAAA,EAAiB,QAAA,EAAU,aAAA,EAAe,aAAY,GAAI,KAAA;AAC7E,EAAA,MAAM,EAAE,cAAA,EAAe,GAAI,uBAAA,CAAwB,cAAc,KAAK,CAAA;AACtE,EAAA,MAAM,EAAE,cAAA,EAAe,GAAI,sBAAA,EAAuB;AAClD,EAAA,MAAM,UAAA,GAAa,OAAA;AAAA,IACf,MAAM,sBAAA,CAAuB,QAAA,EAAU,aAAA,EAAe,WAAW,CAAA;AAAA,IACjE,CAAC,QAAA,EAAU,aAAA,EAAe,WAAW;AAAA,GACzC;AAEA,EAAA,OAAO,YAAA;AAAA,wBACF,GAAA,EAAA,EAAK,GAAG,cAAA,EAAiB,GAAG,YACxB,QAAA,EACL,CAAA;AAAA,IACA;AAAA,GACJ;AACJ;;;;"}
|
package/ui/MapContainer.d.ts
CHANGED
package/ui/MapContainer.js
CHANGED
|
@@ -4,7 +4,7 @@ import { createLogger } from '@open-pioneer/core';
|
|
|
4
4
|
import { useCommonComponentProps } from '@open-pioneer/react-utils';
|
|
5
5
|
import { useRef, useState, useEffect, useMemo } from 'react';
|
|
6
6
|
import { MapContainerContextProvider } from './MapContainerContext.js';
|
|
7
|
-
import {
|
|
7
|
+
import { useMapModelValue } from './useMapModel.js';
|
|
8
8
|
|
|
9
9
|
const LOG = createLogger("map:MapContainer");
|
|
10
10
|
function MapContainer(props) {
|
|
@@ -12,33 +12,21 @@ function MapContainer(props) {
|
|
|
12
12
|
viewPadding,
|
|
13
13
|
viewPaddingChangeBehavior,
|
|
14
14
|
children,
|
|
15
|
-
role,
|
|
15
|
+
role = "application",
|
|
16
16
|
"aria-label": ariaLabel,
|
|
17
17
|
"aria-labelledby": ariaLabelledBy
|
|
18
18
|
} = props;
|
|
19
19
|
const { containerProps } = useCommonComponentProps("map-container-root", props);
|
|
20
20
|
const mapContainer = useRef(null);
|
|
21
21
|
const mapAnchorsHost = useRef(null);
|
|
22
|
-
const
|
|
23
|
-
const map = modelState.map;
|
|
22
|
+
const map = useMapModelValue(props);
|
|
24
23
|
const [ready, setReady] = useState(false);
|
|
25
24
|
useEffect(() => {
|
|
26
|
-
if (modelState.kind === "loading") {
|
|
27
|
-
return;
|
|
28
|
-
}
|
|
29
|
-
if (modelState.kind === "rejected") {
|
|
30
|
-
LOG.error(`Cannot display the map. Caused by `, modelState.error);
|
|
31
|
-
return;
|
|
32
|
-
}
|
|
33
|
-
if (!map) {
|
|
34
|
-
LOG.error(`No configuration available for the configured map.`);
|
|
35
|
-
return;
|
|
36
|
-
}
|
|
37
25
|
if (mapContainer.current) {
|
|
38
26
|
const resource = registerMapTarget(map, mapContainer.current);
|
|
39
27
|
return () => resource?.destroy();
|
|
40
28
|
}
|
|
41
|
-
}, [
|
|
29
|
+
}, [map]);
|
|
42
30
|
useEffect(() => {
|
|
43
31
|
setReady(true);
|
|
44
32
|
}, []);
|
package/ui/MapContainer.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MapContainer.js","sources":["MapContainer.tsx"],"sourcesContent":["// SPDX-FileCopyrightText: 2023-2025 Open Pioneer project (https://github.com/open-pioneer)\n// SPDX-License-Identifier: Apache-2.0\nimport { chakra } from \"@chakra-ui/react\";\nimport { Resource, createLogger } from \"@open-pioneer/core\";\nimport { CommonComponentProps, useCommonComponentProps } from \"@open-pioneer/react-utils\";\nimport type OlMap from \"ol/Map\";\nimport { Extent } from \"ol/extent\";\nimport { ReactNode, useEffect, useMemo, useRef, useState } from \"react\";\nimport { MapModel, MapPadding } from \"../api\";\nimport { MapContainerContextProvider, MapContainerContextType } from \"./MapContainerContext\";\nimport { MapModelProps, useMapModel } from \"./useMapModel\";\nconst LOG = createLogger(\"map:MapContainer\");\n\nexport interface MapContainerProps extends CommonComponentProps, MapModelProps {\n /**\n * Sets the map's padding directly.\n * Do not use the view's padding property directly on the OL map.\n *\n * See: https://openlayers.org/en/latest/apidoc/module-ol_View-View.html#padding)\n */\n viewPadding?: MapPadding | undefined;\n\n /**\n * Behavior performed by the map when the view padding changes.\n *\n * - `none`: Do nothing.\n * - `preserve-center`: Ensures that the center point remains the same by animating the view.\n * - `preserve-extent`: Ensures that the extent remains the same by zooming.\n *\n * @default \"preserve-center\"\n */\n viewPaddingChangeBehavior?: \"none\" | \"preserve-center\" | \"preserve-extent\";\n\n children?: ReactNode;\n\n /**\n * Optional role property.\n *\n * This property is directly applied to the map's container div element.\n */\n role?: string;\n\n /**\n * Optional aria-labelledby property.\n * Do not use together with aria-label.\n *\n * This property is directly applied to the map's container div element.\n */\n \"aria-labelledby\"?: string;\n\n /**\n * Optional aria-label property.\n * Do not use together with aria-label.\n *\n * This property is directly applied to the map's container div element.\n */\n \"aria-label\"?: string;\n}\n\n/**\n * Displays the map with the given id.\n *\n * There can only be at most one MapContainer for every map.\n */\nexport function MapContainer(props: MapContainerProps) {\n const {\n viewPadding,\n viewPaddingChangeBehavior,\n children,\n role,\n \"aria-label\": ariaLabel,\n \"aria-labelledby\": ariaLabelledBy\n } = props;\n const { containerProps } = useCommonComponentProps(\"map-container-root\", props);\n const mapContainer = useRef<HTMLDivElement>(null);\n const mapAnchorsHost = useRef<HTMLDivElement>(null);\n const modelState = useMapModel(props);\n const map = modelState.map;\n\n const [ready, setReady] = useState(false);\n\n useEffect(() => {\n if (modelState.kind === \"loading\") {\n return;\n }\n\n if (modelState.kind === \"rejected\") {\n LOG.error(`Cannot display the map. Caused by `, modelState.error);\n return;\n }\n\n if (!map) {\n LOG.error(`No configuration available for the configured map.`);\n return;\n }\n\n // Mount the map into the DOM\n if (mapContainer.current) {\n const resource = registerMapTarget(map, mapContainer.current);\n return () => resource?.destroy();\n }\n }, [modelState, map]);\n\n // Wait for mount to make sure that the map anchors host is available\n useEffect(() => {\n setReady(true);\n }, []);\n\n const styleProps = useMemo(() => {\n return {\n height: \"100%\",\n position: \"relative\",\n\n // set css variables according to view padding\n \"--map-padding-top\": `${viewPadding?.top ?? 0}px`,\n \"--map-padding-bottom\": `${viewPadding?.bottom ?? 0}px`,\n \"--map-padding-left\": `${viewPadding?.left ?? 0}px`,\n \"--map-padding-right\": `${viewPadding?.right ?? 0}px`\n };\n }, [viewPadding]);\n\n return (\n <chakra.div {...containerProps} css={styleProps}>\n {/* Used by open layers to mount the map. This node receives the keyboard focus when interacting with the map. */}\n <chakra.div\n className=\"map-container\"\n ref={mapContainer}\n role={role}\n aria-label={ariaLabel}\n aria-labelledby={ariaLabelledBy}\n h=\"100%\"\n w=\"100%\"\n //eslint-disable-next-line jsx-a11y/no-noninteractive-tabindex\n tabIndex={0}\n />\n\n {/* Contains user widgets (map anchors and raw children). These are separate from the map so they don't interfere with mouse/keyboard events. */}\n <chakra.div ref={mapAnchorsHost} className=\"map-anchors\">\n {ready && map && (\n <MapContainerReady\n olMap={map.olMap}\n mapAnchorsHost={mapAnchorsHost.current!}\n viewPadding={viewPadding}\n viewPaddingChangeBehavior={viewPaddingChangeBehavior}\n >\n {children}\n </MapContainerReady>\n )}\n </chakra.div>\n </chakra.div>\n );\n}\n\n/**\n * This inner component is rendered when the map has been loaded.\n *\n * It provides the map instance and additional properties down the component tree.\n */\nfunction MapContainerReady(\n props: { olMap: OlMap; mapAnchorsHost: HTMLElement } & Omit<\n MapContainerProps,\n \"mapId\" | \"map\" | \"className\"\n >\n): ReactNode {\n const {\n olMap,\n mapAnchorsHost,\n viewPadding: viewPaddingProp,\n viewPaddingChangeBehavior = \"preserve-center\",\n children\n } = props;\n\n const viewPadding = useMemo<Required<MapPadding>>(() => {\n return {\n left: viewPaddingProp?.left ?? 0,\n right: viewPaddingProp?.right ?? 0,\n top: viewPaddingProp?.top ?? 0,\n bottom: viewPaddingProp?.bottom ?? 0\n };\n }, [viewPaddingProp]);\n\n // Apply view padding\n useEffect(() => {\n const mapView = olMap?.getView();\n if (!olMap || !mapView) {\n return;\n }\n\n const oldCenter = mapView.getCenter();\n const oldPadding = fromOlPadding(mapView.padding);\n const oldExtent = extentIncludingPadding(olMap, oldPadding);\n\n mapView.padding = toOlPadding(viewPadding);\n switch (viewPaddingChangeBehavior) {\n case \"preserve-center\":\n mapView.animate({ center: oldCenter, duration: 300 });\n break;\n case \"preserve-extent\": {\n if (oldExtent) {\n mapView.animate({\n center: oldCenter,\n resolution: mapView.getResolutionForExtent(oldExtent),\n duration: 300\n });\n }\n break;\n }\n case \"none\":\n }\n }, [viewPadding, olMap, viewPaddingChangeBehavior]);\n\n const mapContext = useMemo((): MapContainerContextType => {\n return {\n mapAnchorsHost\n };\n }, [mapAnchorsHost]);\n return <MapContainerContextProvider value={mapContext}>{children}</MapContainerContextProvider>;\n}\n\nfunction registerMapTarget(mapModel: MapModel, target: HTMLDivElement): Resource | undefined {\n const mapId = mapModel.id;\n const olMap = mapModel.olMap;\n if (olMap.getTarget()) {\n LOG.error(\n `Failed to display the map: the map already has a target. There may be more than one <MapContainer />.`\n );\n return undefined;\n }\n\n LOG.isDebug() && LOG.debug(`Setting target of map '${mapId}':`, target);\n if (!(\"keyboardEventTarget_\" in olMap)) {\n throw new Error(\n \"Internal error: failed to override keyboard event target. The property is no longer present.\"\n );\n }\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n (olMap as any).keyboardEventTarget_ = target;\n olMap.setTarget(target);\n\n let unregistered = false;\n return {\n destroy() {\n if (!unregistered) {\n LOG.isDebug() && LOG.debug(`Removing target of map '${mapId}':`, target);\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n (olMap as any).keyboardEventTarget_ = undefined;\n olMap.setTarget(undefined);\n unregistered = true;\n }\n }\n };\n}\n\n/**\n * Returns the extent visible in the non-padded region of the map.\n */\nfunction extentIncludingPadding(map: OlMap, padding: Required<MapPadding>): Extent | undefined {\n const size = map.getSize();\n if (!size || size.length < 2) {\n return undefined;\n }\n\n const [width, height] = size as [number, number];\n const bottomLeft = map.getCoordinateFromPixel([padding.left, padding.bottom]);\n const topRight = map.getCoordinateFromPixel([\n Math.max(0, width - padding.right),\n Math.max(0, height - padding.top)\n ]);\n if (!bottomLeft || !topRight) {\n return undefined;\n }\n\n const [xmin, ymin] = bottomLeft;\n const [xmax, ymax] = topRight;\n return [xmin, ymin, xmax, ymax] as Extent;\n}\n\nfunction fromOlPadding(padding: number[] | undefined): Required<MapPadding> {\n // top, right, bottom, left\n return {\n top: padding?.[0] ?? 0,\n right: padding?.[1] ?? 0,\n bottom: padding?.[2] ?? 0,\n left: padding?.[3] ?? 0\n };\n}\n\nfunction toOlPadding(padding: Required<MapPadding>): number[] {\n // top, right, bottom, left\n const { top, right, bottom, left } = padding;\n return [top, right, bottom, left];\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"MapContainer.js","sources":["MapContainer.tsx"],"sourcesContent":["// SPDX-FileCopyrightText: 2023-2025 Open Pioneer project (https://github.com/open-pioneer)\n// SPDX-License-Identifier: Apache-2.0\nimport { chakra } from \"@chakra-ui/react\";\nimport { Resource, createLogger } from \"@open-pioneer/core\";\nimport { CommonComponentProps, useCommonComponentProps } from \"@open-pioneer/react-utils\";\nimport type OlMap from \"ol/Map\";\nimport { Extent } from \"ol/extent\";\nimport { ReactNode, useEffect, useMemo, useRef, useState } from \"react\";\nimport { MapModel, MapPadding } from \"../api\";\nimport { MapContainerContextProvider, MapContainerContextType } from \"./MapContainerContext\";\nimport { MapModelProps, useMapModelValue } from \"./useMapModel\";\nconst LOG = createLogger(\"map:MapContainer\");\n\nexport interface MapContainerProps extends CommonComponentProps, MapModelProps {\n /**\n * Sets the map's padding directly.\n * Do not use the view's padding property directly on the OL map.\n *\n * See: https://openlayers.org/en/latest/apidoc/module-ol_View-View.html#padding)\n */\n viewPadding?: MapPadding | undefined;\n\n /**\n * Behavior performed by the map when the view padding changes.\n *\n * - `none`: Do nothing.\n * - `preserve-center`: Ensures that the center point remains the same by animating the view.\n * - `preserve-extent`: Ensures that the extent remains the same by zooming.\n *\n * @default \"preserve-center\"\n */\n viewPaddingChangeBehavior?: \"none\" | \"preserve-center\" | \"preserve-extent\";\n\n children?: ReactNode;\n\n /**\n * Optional role property.\n *\n * This property is directly applied to the map's container div element.\n *\n * @default \"application\"\n */\n role?: string;\n\n /**\n * Optional aria-labelledby property.\n * Do not use together with aria-label.\n *\n * This property is directly applied to the map's container div element.\n */\n \"aria-labelledby\"?: string;\n\n /**\n * Optional aria-label property.\n * Do not use together with aria-label.\n *\n * This property is directly applied to the map's container div element.\n */\n \"aria-label\"?: string;\n}\n\n/**\n * Displays the map with the given id.\n *\n * There can only be at most one MapContainer for every map.\n */\nexport function MapContainer(props: MapContainerProps) {\n const {\n viewPadding,\n viewPaddingChangeBehavior,\n children,\n role = \"application\",\n \"aria-label\": ariaLabel,\n \"aria-labelledby\": ariaLabelledBy\n } = props;\n const { containerProps } = useCommonComponentProps(\"map-container-root\", props);\n const mapContainer = useRef<HTMLDivElement>(null);\n const mapAnchorsHost = useRef<HTMLDivElement>(null);\n const map = useMapModelValue(props);\n\n const [ready, setReady] = useState(false);\n\n useEffect(() => {\n // Mount the map into the DOM\n if (mapContainer.current) {\n const resource = registerMapTarget(map, mapContainer.current);\n return () => resource?.destroy();\n }\n }, [map]);\n\n // Wait for mount to make sure that the map anchors host is available\n useEffect(() => {\n setReady(true);\n }, []);\n\n const styleProps = useMemo(() => {\n return {\n height: \"100%\",\n position: \"relative\",\n\n // set css variables according to view padding\n \"--map-padding-top\": `${viewPadding?.top ?? 0}px`,\n \"--map-padding-bottom\": `${viewPadding?.bottom ?? 0}px`,\n \"--map-padding-left\": `${viewPadding?.left ?? 0}px`,\n \"--map-padding-right\": `${viewPadding?.right ?? 0}px`\n };\n }, [viewPadding]);\n\n return (\n <chakra.div {...containerProps} css={styleProps}>\n {/* Used by open layers to mount the map. This node receives the keyboard focus when interacting with the map. */}\n <chakra.div\n className=\"map-container\"\n ref={mapContainer}\n role={role}\n aria-label={ariaLabel}\n aria-labelledby={ariaLabelledBy}\n h=\"100%\"\n w=\"100%\"\n //eslint-disable-next-line jsx-a11y/no-noninteractive-tabindex\n tabIndex={0}\n />\n\n {/* Contains user widgets (map anchors and raw children). These are separate from the map so they don't interfere with mouse/keyboard events. */}\n <chakra.div ref={mapAnchorsHost} className=\"map-anchors\">\n {ready && map && (\n <MapContainerReady\n olMap={map.olMap}\n mapAnchorsHost={mapAnchorsHost.current!}\n viewPadding={viewPadding}\n viewPaddingChangeBehavior={viewPaddingChangeBehavior}\n >\n {children}\n </MapContainerReady>\n )}\n </chakra.div>\n </chakra.div>\n );\n}\n\n/**\n * This inner component is rendered when the map has been loaded.\n *\n * It provides the map instance and additional properties down the component tree.\n */\nfunction MapContainerReady(\n props: { olMap: OlMap; mapAnchorsHost: HTMLElement } & Omit<\n MapContainerProps,\n \"mapId\" | \"map\" | \"className\"\n >\n): ReactNode {\n const {\n olMap,\n mapAnchorsHost,\n viewPadding: viewPaddingProp,\n viewPaddingChangeBehavior = \"preserve-center\",\n children\n } = props;\n\n const viewPadding = useMemo<Required<MapPadding>>(() => {\n return {\n left: viewPaddingProp?.left ?? 0,\n right: viewPaddingProp?.right ?? 0,\n top: viewPaddingProp?.top ?? 0,\n bottom: viewPaddingProp?.bottom ?? 0\n };\n }, [viewPaddingProp]);\n\n // Apply view padding\n useEffect(() => {\n const mapView = olMap?.getView();\n if (!olMap || !mapView) {\n return;\n }\n\n const oldCenter = mapView.getCenter();\n const oldPadding = fromOlPadding(mapView.padding);\n const oldExtent = extentIncludingPadding(olMap, oldPadding);\n\n mapView.padding = toOlPadding(viewPadding);\n switch (viewPaddingChangeBehavior) {\n case \"preserve-center\":\n mapView.animate({ center: oldCenter, duration: 300 });\n break;\n case \"preserve-extent\": {\n if (oldExtent) {\n mapView.animate({\n center: oldCenter,\n resolution: mapView.getResolutionForExtent(oldExtent),\n duration: 300\n });\n }\n break;\n }\n case \"none\":\n }\n }, [viewPadding, olMap, viewPaddingChangeBehavior]);\n\n const mapContext = useMemo((): MapContainerContextType => {\n return {\n mapAnchorsHost\n };\n }, [mapAnchorsHost]);\n return <MapContainerContextProvider value={mapContext}>{children}</MapContainerContextProvider>;\n}\n\nfunction registerMapTarget(mapModel: MapModel, target: HTMLDivElement): Resource | undefined {\n const mapId = mapModel.id;\n const olMap = mapModel.olMap;\n if (olMap.getTarget()) {\n LOG.error(\n `Failed to display the map: the map already has a target. There may be more than one <MapContainer />.`\n );\n return undefined;\n }\n\n LOG.isDebug() && LOG.debug(`Setting target of map '${mapId}':`, target);\n if (!(\"keyboardEventTarget_\" in olMap)) {\n throw new Error(\n \"Internal error: failed to override keyboard event target. The property is no longer present.\"\n );\n }\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n (olMap as any).keyboardEventTarget_ = target;\n olMap.setTarget(target);\n\n let unregistered = false;\n return {\n destroy() {\n if (!unregistered) {\n LOG.isDebug() && LOG.debug(`Removing target of map '${mapId}':`, target);\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n (olMap as any).keyboardEventTarget_ = undefined;\n olMap.setTarget(undefined);\n unregistered = true;\n }\n }\n };\n}\n\n/**\n * Returns the extent visible in the non-padded region of the map.\n */\nfunction extentIncludingPadding(map: OlMap, padding: Required<MapPadding>): Extent | undefined {\n const size = map.getSize();\n if (!size || size.length < 2) {\n return undefined;\n }\n\n const [width, height] = size as [number, number];\n const bottomLeft = map.getCoordinateFromPixel([padding.left, padding.bottom]);\n const topRight = map.getCoordinateFromPixel([\n Math.max(0, width - padding.right),\n Math.max(0, height - padding.top)\n ]);\n if (!bottomLeft || !topRight) {\n return undefined;\n }\n\n const [xmin, ymin] = bottomLeft;\n const [xmax, ymax] = topRight;\n return [xmin, ymin, xmax, ymax] as Extent;\n}\n\nfunction fromOlPadding(padding: number[] | undefined): Required<MapPadding> {\n // top, right, bottom, left\n return {\n top: padding?.[0] ?? 0,\n right: padding?.[1] ?? 0,\n bottom: padding?.[2] ?? 0,\n left: padding?.[3] ?? 0\n };\n}\n\nfunction toOlPadding(padding: Required<MapPadding>): number[] {\n // top, right, bottom, left\n const { top, right, bottom, left } = padding;\n return [top, right, bottom, left];\n}\n"],"names":[],"mappings":"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"}
|