@open-pioneer/map 1.4.0-dev.20260625074633 → 1.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +46 -22
- package/LayerFactory.d.ts +1 -1
- package/LayerFactory.js.map +1 -1
- package/MapRegistry.js +1 -1
- package/MapRegistry.js.map +1 -1
- package/README.md +8 -14
- package/_virtual/source-info.js +8 -6
- package/_virtual/source-info.js.map +1 -1
- package/layers/AbstractLayer.d.ts +36 -3
- package/layers/AbstractLayer.js +123 -79
- package/layers/AbstractLayer.js.map +1 -1
- package/layers/AbstractLayerBase.d.ts +2 -2
- package/layers/AbstractLayerBase.js.map +1 -1
- package/layers/GroupLayer.d.ts +2 -1
- package/layers/GroupLayer.js +4 -1
- package/layers/GroupLayer.js.map +1 -1
- package/layers/SimpleLayer.d.ts +1 -1
- package/layers/SimpleLayer.js +1 -1
- package/layers/SimpleLayer.js.map +1 -1
- package/layers/WMSLayer.js +59 -11
- package/layers/WMSLayer.js.map +1 -1
- package/layers/WMTSLayer.d.ts +1 -1
- package/layers/WMTSLayer.js +11 -5
- package/layers/WMTSLayer.js.map +1 -1
- package/layers/group/GroupLayerCollection.d.ts +2 -2
- package/layers/group/GroupLayerCollection.js +1 -1
- package/layers/group/GroupLayerCollection.js.map +1 -1
- package/layers/shared/SublayerBaseType.d.ts +9 -0
- package/layers/shared/SublayersCollection.js.map +1 -1
- package/layers/shared/getRecursiveLayers.d.ts +1 -1
- package/layers/shared/getRecursiveLayers.js +12 -5
- package/layers/shared/getRecursiveLayers.js.map +1 -1
- package/layers/shared/internals.d.ts +3 -2
- package/layers/shared/internals.js +2 -1
- package/layers/shared/internals.js.map +1 -1
- package/layers/unions.js.map +1 -1
- package/layers/wms/WMSSublayer.d.ts +14 -1
- package/layers/wms/WMSSublayer.js +29 -2
- package/layers/wms/WMSSublayer.js.map +1 -1
- package/layers/wms/getAttributions.js.map +1 -1
- package/layers/wms/getLegendUrl.js +1 -1
- package/layers/wms/getLegendUrl.js.map +1 -1
- package/layers/wmts/getAttributions.js.map +1 -1
- package/layers/wmts/getLegendUrl.js +1 -1
- package/layers/wmts/getLegendUrl.js.map +1 -1
- package/model/Highlights.js.map +1 -1
- package/model/LayerCollection.js.map +1 -1
- package/model/MapAttributions.js.map +1 -1
- package/model/MapModel.d.ts +5 -5
- package/model/MapModel.js +4 -4
- package/model/MapModel.js.map +1 -1
- package/model/Overlays.d.ts +2 -2
- package/model/Overlays.js +2 -2
- package/model/Overlays.js.map +1 -1
- package/model/createMapModel.js +23 -23
- package/model/createMapModel.js.map +1 -1
- package/model/getGeometries.js.map +1 -1
- package/package.json +10 -10
- package/ui/DefaultMapProvider.js.map +1 -1
- package/ui/MapAnchor.js.map +1 -1
- package/ui/MapContainer.js +2 -2
- package/ui/MapContainer.js.map +1 -1
- package/ui/MapContainerContext.js.map +1 -1
- package/ui/OverlaysRenderer.js.map +1 -1
- package/ui/computeMapAnchorStyles.js.map +1 -1
- package/ui/hooks/useMapModel.d.ts +7 -0
- package/ui/hooks/useMapModel.js +10 -1
- package/ui/hooks/useMapModel.js.map +1 -1
- package/ui/styles.css +0 -2
- package/ui/styles.css.map +1 -1
- package/utils/fetch.js.map +1 -1
- package/utils/geometry-utils.js.map +1 -1
- package/utils/ol-test-support.js.map +1 -1
- package/utils/projections.js.map +1 -1
- package/utils/sanitize.js.map +1 -1
package/model/MapModel.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MapModel.js","sources":["MapModel.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2023-2025 Open Pioneer project (https://github.com/open-pioneer)\n// SPDX-License-Identifier: Apache-2.0\nimport { computed, reactive, ReadonlyReactive, synchronized } from \"@conterra/reactivity-core\";\nimport { emit, emitter, EventSource } from \"@conterra/reactivity-events\";\nimport {\n createAbortError,\n createLogger,\n createManualPromise,\n deprecated,\n isAbortError,\n ManualPromise\n} from \"@open-pioneer/core\";\nimport { HttpService } from \"@open-pioneer/http\";\nimport OlMap from \"ol/Map\";\nimport { unByKey } from \"ol/Observable\";\nimport OlView from \"ol/View\";\nimport { Coordinate } from \"ol/coordinate\";\nimport { EventsKey } from \"ol/events\";\nimport { createEmpty, extend, getArea, getCenter } from \"ol/extent\";\nimport { getPointResolution, Projection } from \"ol/proj\";\nimport { sourceId } from \"open-pioneer:source-info\";\nimport { LAYER_DEPS, LayerDependencies } from \"../layers/shared/internals\";\nimport {\n assertInternalConstructor,\n INTERNAL_CONSTRUCTOR_TAG,\n InternalConstructorTag\n} from \"../utils/InternalConstructorTag\";\nimport { calculateBufferedExtent } from \"../utils/geometry-utils\";\nimport {\n DESTROY_HIGHLIGHTS,\n Highlight,\n HighlightOptions,\n Highlights,\n HighlightZoomOptions\n} from \"./Highlights\";\nimport { LayerCollection } from \"./LayerCollection\";\nimport { ExtentConfig } from \"./MapConfig\";\nimport { Overlays } from \"./Overlays\";\nimport { getGeometries } from \"./getGeometries\";\nimport { BaseFeature } from \"../utils/BaseFeature\";\nimport { Geometry } from \"ol/geom\";\nimport { PackageIntl } from \"@open-pioneer/runtime\";\nimport { MapAttributions } from \"./MapAttributions\";\n\nconst LOG = createLogger(sourceId);\n\nconst DEFAULT_DPI = 25.4 / 0.28;\nconst INCHES_PER_METRE = 39.37;\n\nconst DEFAULT_OL_POINT_ZOOM_LEVEL = 17;\nconst DEFAULT_OL_MAX_ZOOM_LEVEL = 20;\nconst DEFAULT_VIEW_PADDING = { top: 50, right: 20, bottom: 10, left: 20 };\n\nexport const DISPLAY_STATUS = Symbol(\"DISPLAY_STATUS\");\n\nconst deprecatedHighlights = deprecated({\n name: \"MapModel highlight function called\",\n packageName: \"@open-pioneer/map\",\n since: \"v1.3.0\",\n alternative: \"call methods of myMapModel.highlights instead\"\n});\n\n/**\n * Options supported when calling {@link MapModel.zoom}.\n *\n * @group Map Model\n **/\nexport interface ZoomOptions {\n /**\n * The zoom-level used if there is no valid extend (such as for single points).\n */\n pointZoom?: number;\n\n /**\n * The maximum zoom-level for multiple points, line or polygon results.\n */\n maxZoom?: number;\n\n /**\n * The view padding to make all features visible.\n */\n viewPadding?: MapPadding;\n\n /**\n * The buffer factor around the extent of the zoomed features. E.g. a value of 1.1 will add\n * 10% to specify the size increase of the extent's width and height.\n */\n buffer?: number;\n}\n\n/**\n * Represents an object in the map.\n *\n * @group Map Model\n */\nexport type DisplayTarget = BaseFeature | Geometry;\n\n/**\n * Map padding, all values are pixels.\n *\n * See https://openlayers.org/en/latest/apidoc/module-ol_View-View.html#padding\n *\n * @group Map Model\n */\nexport interface MapPadding {\n left?: number;\n right?: number;\n top?: number;\n bottom?: number;\n}\n\n/**\n * An item that should be displayed as part of the attributions for the map.\n *\n * @group MapModel\n */\nexport interface AttributionItem {\n /**\n * The attribution's text.\n *\n * Note that this property contains raw HTML tags.\n * The HTML content has been sanitized, so it is safe to display in the user interface.\n */\n text: string;\n}\n\ntype DisplayStatus = \"waiting\" | \"ready\" | \"error\";\n\n/**\n * Represents a map.\n *\n * @group Map Model\n */\nexport class MapModel {\n readonly #id: string;\n readonly #olMap: OlMap;\n readonly #olView: ReadonlyReactive<OlView>;\n readonly #attributions: MapAttributions;\n readonly #layers = new LayerCollection(this, INTERNAL_CONSTRUCTOR_TAG);\n readonly #highlights: Highlights;\n readonly #tooltips: Overlays;\n readonly #layerDeps: LayerDependencies;\n readonly #destroyed = emitter();\n\n #loadStartEventHandler: EventsKey | undefined;\n #loadEndEventHandler: EventsKey | undefined;\n readonly #olLoading = reactive(false);\n\n #isDestroyed = false;\n readonly #container: ReadonlyReactive<HTMLElement | undefined>;\n readonly #initialExtent = reactive<ExtentConfig>();\n readonly #viewBindings: ReadonlyReactive<ViewBindings>;\n readonly #scale: ReadonlyReactive<number | undefined>;\n\n readonly #abortController = new AbortController();\n #displayStatus: DisplayStatus;\n #displayWaiter: ManualPromise<void> | undefined;\n\n /**\n * @internal\n */\n constructor(\n options: {\n id: string;\n olMap: OlMap;\n initialExtent: ExtentConfig | undefined;\n showDefaultAttributions: boolean;\n currentIntl: ReadonlyReactive<PackageIntl>;\n httpService: HttpService;\n },\n tag: InternalConstructorTag\n ) {\n assertInternalConstructor(tag);\n\n this.#id = options.id;\n this.#olMap = options.olMap;\n this.#attributions = new MapAttributions({\n intl: options.currentIntl,\n olMap: this.#olMap,\n showControl: options.showDefaultAttributions\n });\n\n this.#olView = synchronized(\n () => this.#olMap.getView(),\n (cb) => {\n const key = this.#olMap.on(\"change:view\", cb);\n return () => unByKey(key);\n }\n );\n\n // NOTE: As early as possible (before any async actions) so we don't miss any events.\n this.#watchLoadingState();\n\n this.#initialExtent.value = options.initialExtent;\n this.#layerDeps = {\n httpService: options.httpService\n };\n\n this.#displayStatus = \"waiting\";\n this.#initializeView().then(\n () => {\n this.#displayStatus = \"ready\";\n this.#displayWaiter?.resolve();\n this.#displayWaiter = undefined;\n },\n (error) => {\n if (!isAbortError(error)) {\n LOG.error(`Failed to initialize map`, error);\n }\n\n this.#displayStatus = \"error\";\n this.#displayWaiter?.reject(new Error(`Failed to initialize map.`));\n this.#displayWaiter = undefined;\n }\n );\n\n this.#container = synchronized(\n () => this.#olMap.getTargetElement() ?? undefined,\n (cb) => {\n const key = this.#olMap.on(\"change:target\", cb);\n return () => unByKey(key);\n }\n );\n\n this.#viewBindings = computed(() => createViewBindings(this.#olView.value));\n this.#scale = computed(() => {\n const { projection, resolution, center } = this;\n if (projection == null || resolution == null || center == null) {\n return undefined;\n }\n\n /**\n * Returns the appropriate scale for the given resolution and units, see OpenLayers function getScaleForResolution()\n * https://github.com/openlayers/openlayers/blob/7fa9df03431e9e1bc517e6c414565d9f848a3132/src/ol/control/ScaleLine.js#L454C3-L454C24\n */\n const pointResolution = getPointResolution(projection, resolution, center, \"m\"); //point resolution in meter per pixel\n const scale = Math.round(pointResolution * INCHES_PER_METRE * DEFAULT_DPI);\n return scale;\n });\n\n // expects fully constructed mapModel\n this.#highlights = new Highlights(this, this.#layerDeps);\n this.#tooltips = new Overlays(this);\n }\n\n /**\n * Destroys this objects, including all layers, highlights and the OL map itself.\n */\n destroy() {\n if (this.#isDestroyed) {\n return;\n }\n\n this.#isDestroyed = true;\n try {\n emit(this.#destroyed);\n } catch (e) {\n LOG.warn(`Unexpected error from event listener during map model destruction:`, e);\n }\n\n this.#loadStartEventHandler && unByKey(this.#loadStartEventHandler);\n this.#loadStartEventHandler = undefined;\n this.#loadEndEventHandler && unByKey(this.#loadEndEventHandler);\n this.#loadEndEventHandler = undefined;\n\n this.#abortController.abort();\n this.#displayWaiter?.reject(new Error(\"Map model was destroyed.\"));\n this.#layers.destroy();\n this.#highlights[DESTROY_HIGHLIGHTS]();\n this.#attributions.destroy();\n this.#olMap.dispose();\n }\n\n /**\n * Emitted when the map model is destroyed.\n */\n get destroyed(): EventSource<void> {\n return this.#destroyed;\n }\n\n /**\n * Returns the map's current display status.\n * This is `waiting` during initialization and `error` or `ready` when done.\n *\n * @internal\n */\n get [DISPLAY_STATUS](): DisplayStatus {\n return this.#displayStatus;\n }\n\n /**\n * The unique id of the map.\n */\n get id(): string {\n return this.#id;\n }\n\n /**\n * The initial map extent.\n *\n * May be undefined before the map is shown.\n * This is guaranteed to be initialized if the promise returned by {@link whenDisplayed} has resolved.\n */\n get initialExtent(): ExtentConfig | undefined {\n return this.#initialExtent.value;\n }\n\n /**\n * Returns the current projection of the map (reactive).\n */\n get projection(): Projection {\n return this.#viewBindings.value.projection;\n }\n\n /**\n * Returns the current center of the map.\n * Same as `olView.getCenter()`, but reactive.\n */\n get center(): Coordinate | undefined {\n return this.#viewBindings.value.center.value;\n }\n\n /**\n * Returns the current resolution of the map.\n * Same as `olView.getResolution()`, but reactive.\n */\n get resolution(): number | undefined {\n return this.#viewBindings.value.resolution.value;\n }\n\n /**\n * Returns the current zoom level of the map.\n * Same as `olView.getZoom()`, but reactive.\n */\n get zoomLevel(): number | undefined {\n return this.#viewBindings.value.zoom.value;\n }\n\n /**\n * Returns the current rotation of the map.\n * Same as `olView.getRotation()`, but reactive.\n */\n get rotation(): number | undefined {\n return this.#viewBindings.value.rotation.value;\n }\n\n /**\n * Returns the current scale of the map.\n *\n * The scale is a value derived from the current `center`, `resolution` and `projection` of the map.\n * The scale will change when the map is zoomed in our out, but depending on the projection, it may also\n * change when the map is _panned_.\n *\n * > NOTE: Technically, this is the _denominator_ of the current scale.\n * > In order to display it, use a format like `1:${scale}`.\n */\n get scale(): number | undefined {\n return this.#scale.value;\n }\n\n /**\n * Returns true if the map is currently loading.\n *\n * This is based on the OpenLayers events `loadstart` and `loadend`,\n * see [Documentation](https://openlayers.org/en/latest/apidoc/module-ol_MapEvent-MapEvent.html#event:loadstart).\n */\n get loading(): boolean {\n return this.#olLoading.value;\n }\n\n /**\n * Contains all known layers of this map.\n *\n * Note that not all layers in this collection may be active in the OpenLayers map.\n * Also note that not all layers in the OpenLayers map may be contained in this collection.\n */\n get layers(): LayerCollection {\n return this.#layers;\n }\n\n /**\n * The container in which the map is currently being rendered.\n * This is the same as the target element of the underlying OpenLayers map.\n *\n * May be undefined if the map is not being rendered at the moment.\n * May change at runtime.\n */\n get container(): HTMLElement | undefined {\n return this.#container.value;\n }\n\n /**\n * Returns attributions for the current content of the map.\n */\n get attributionItems(): AttributionItem[] {\n return this.#attributions.attributionItems;\n }\n\n /**\n * The raw OpenLayers map.\n */\n get olMap(): OlMap {\n return this.#olMap;\n }\n\n /**\n * Returns the current view of the OpenLayers map.\n */\n get olView(): OlView {\n return this.#olView.value;\n }\n\n /**\n * TODO: Can be removed once the LayerFactory is the only supported way of constructing a layer.\n *\n * @internal\n */\n get [LAYER_DEPS](): LayerDependencies {\n return this.#layerDeps;\n }\n\n /**\n * Create and receive map overlays\n */\n get overlays(): Overlays {\n return this.#tooltips;\n }\n\n /**\n * Create, receive and zoom to map highlights\n */\n get highlights(): Highlights {\n return this.#highlights;\n }\n\n /**\n * Changes the current scale of the map to the given value.\n *\n * Internally, this computes a new zoom level / resolution based on the scale\n * and the current center.\n * The new resolution is then applied to the current `olView`.\n *\n * See also {@link scale}.\n */\n setScale(newScale: number): void {\n const view = this.olView;\n const projection = this.projection;\n const center = this.center;\n if (!center) {\n return;\n }\n\n const mpu = projection.getMetersPerUnit() ?? 1;\n const resolution = INCHES_PER_METRE * DEFAULT_DPI * mpu;\n const pointResolution = newScale / getPointResolution(projection, resolution, center);\n view.setResolution(pointResolution);\n }\n\n /**\n * Zooms to the given targets.\n */\n zoom(displayTargets: DisplayTarget[], options?: ZoomOptions | undefined): void {\n const olView = this.olView;\n const geometries = getGeometries(displayTargets);\n if (geometries.length === 0) {\n return;\n }\n\n let extent = createEmpty();\n for (const geometry of geometries) {\n extent = extend(extent, geometry.getExtent());\n }\n\n const bufferParameter = options?.buffer;\n if (typeof bufferParameter === \"number\") {\n extent = calculateBufferedExtent(extent, bufferParameter);\n }\n\n const center = getCenter(extent);\n const isPoint = getArea(extent) === 0;\n const zoomLevel = isPoint\n ? (options?.pointZoom ?? DEFAULT_OL_POINT_ZOOM_LEVEL)\n : (options?.maxZoom ?? DEFAULT_OL_MAX_ZOOM_LEVEL);\n if (center && center.length) {\n olView.setCenter(center);\n }\n\n const {\n top = 0,\n right = 0,\n bottom = 0,\n left = 0\n } = options?.viewPadding ?? DEFAULT_VIEW_PADDING;\n const padding = [top, right, bottom, left];\n\n if (extent) {\n olView.fit(extent, { maxZoom: zoomLevel, padding });\n } else if (zoomLevel) {\n olView.setZoom(zoomLevel);\n }\n }\n\n /**\n * Creates a highlight at the given targets.\n *\n * A highlight is a temporary graphic on the map that calls attention to a point or an area.\n *\n * Call `destroy()` on the returned highlight object to remove the highlight.\n *\n * @deprecated Highlight functions will be removed in a future major release; call {@link Highlights.add} instead.\n */\n highlight(geometries: DisplayTarget[], options?: HighlightOptions | undefined): Highlight {\n deprecatedHighlights();\n return this.#highlights.add(geometries, options);\n }\n\n /**\n * Creates a highlight and zooms to the given targets.\n *\n * See also {@link highlight} and {@link zoom}.\n *\n * @deprecated Highlight functions will be removed in a future major release; call {@link Highlights.addAndZoom} instead.\n */\n highlightAndZoom(geometries: DisplayTarget[], options?: HighlightZoomOptions): Highlight {\n deprecatedHighlights();\n return this.#highlights.addAndZoom(geometries, options ?? {});\n }\n\n /**\n * Removes any existing highlights from the map.\n *\n * @deprecated Highlight functions wil be removed in a future major release; call {@link Highlights.clear} instead.\n */\n removeHighlights(): void {\n deprecatedHighlights();\n this.#highlights.clear();\n }\n\n /**\n * Returns a promise that resolves when the map has mounted in the DOM.\n */\n whenDisplayed(): Promise<void> {\n if (this.#isDestroyed) {\n return Promise.reject(new Error(\"Map model was destroyed.\"));\n }\n if (this.#displayStatus === \"error\") {\n return Promise.reject(new Error(`Failed to initialize map.`));\n }\n if (this.#displayStatus === \"ready\") {\n return Promise.resolve();\n }\n return (this.#displayWaiter ??= createManualPromise()).promise;\n }\n\n /**\n * Waits for the map to be displayed and then initializes the view (if necessary).\n *\n * May simply resolve when done, or throw an error when a problem occurs.\n * AbortError is thrown when cancelled via `this.#abortController`, for example\n * when the map model is destroyed before it has ever been displayed.\n */\n async #initializeView(): Promise<void> {\n try {\n await waitForMapSize(this.olMap, this.#abortController.signal); // may throw on cancel\n } catch (e) {\n if (isAbortError(e)) {\n throw e;\n }\n throw new Error(`Failed to wait for the map to be displayed.`, { cause: e });\n }\n\n try {\n const olMap = this.#olMap;\n const view = olMap.getView();\n\n if (this.#initialExtent.value) {\n // Initial extent was set from the outside. We simply ensure that it gets displayed by the map.\n const extent = this.#initialExtent.value;\n const olExtent = [extent.xMin, extent.yMin, extent.xMax, extent.yMax];\n\n const olCenter = getCenter(olExtent);\n const resolution = view.getResolutionForExtent(olExtent);\n LOG.debug(`Applying initial extent`, extent);\n LOG.debug(` Computed center:`, olCenter);\n LOG.debug(` Computed resolution:`, resolution);\n\n view.setCenter(olCenter);\n view.setResolution(resolution);\n } else {\n // Initial extent was NOT set from the outside.\n // We detect whatever the view is displaying and consider it to be the initial extent.\n const olExtent = view.calculateExtent();\n const [xMin = 0, yMin = 0, xMax = 0, yMax = 0] = olExtent;\n const extent: ExtentConfig = { xMin, yMin, xMax, yMax };\n LOG.debug(`Detected initial extent`, extent);\n\n this.#initialExtent.value = extent;\n }\n } catch (e) {\n throw new Error(`Failed to apply the initial extent.`, { cause: e });\n }\n }\n\n /**\n * Subscribes to the OpenLayers loading state.\n */\n #watchLoadingState() {\n this.#loadStartEventHandler = this.#olMap.on(\"loadstart\", () => {\n this.#olLoading.value = true;\n });\n this.#loadEndEventHandler = this.#olMap.on(\"loadend\", () => {\n this.#olLoading.value = false;\n });\n }\n}\n\ninterface ViewBindings {\n resolution: ReadonlyReactive<number | undefined>;\n center: ReadonlyReactive<Coordinate | undefined>;\n zoom: ReadonlyReactive<number | undefined>;\n rotation: ReadonlyReactive<number | undefined>;\n projection: Projection; // not reactive (change view to change projection)\n}\n\nfunction createViewBindings(view: OlView): ViewBindings {\n return {\n resolution: synchronized(\n () => view.getResolution(),\n (cb) => {\n const key = view.on(\"change:resolution\", cb);\n return () => unByKey(key);\n }\n ),\n center: synchronized(\n () => view.getCenter(),\n (cb) => {\n const key = view.on(\"change:center\", cb);\n return () => unByKey(key);\n }\n ),\n zoom: synchronized(\n () => view.getZoom(),\n (cb) => {\n const key = view.on(\"change:resolution\", cb);\n return () => unByKey(key);\n }\n ),\n rotation: synchronized(\n () => view.getRotation(),\n (cb) => {\n const key = view.on(\"change:rotation\", cb);\n return () => unByKey(key);\n }\n ),\n projection: view.getProjection()\n };\n}\n\nfunction waitForMapSize(olMap: OlMap, signal: AbortSignal): Promise<void> {\n const promise = new Promise<void>((resolve, reject) => {\n let eventKey: EventsKey | undefined;\n\n function checkSize() {\n const currentSize = olMap.getSize() ?? [];\n const [width = 0, height = 0] = currentSize;\n if (currentSize && width > 0 && height > 0) {\n finish();\n }\n }\n\n function onAbort() {\n finish(createAbortError());\n }\n\n function finish(error?: Error | undefined) {\n if (eventKey) {\n unByKey(eventKey);\n eventKey = undefined;\n }\n signal.removeEventListener(\"abort\", onAbort);\n\n if (error) {\n reject(error);\n } else {\n resolve(wait(25)); // Give the map some time to render\n }\n }\n\n if (signal.aborted) {\n finish(createAbortError());\n return;\n }\n\n signal.addEventListener(\"abort\", onAbort);\n eventKey = olMap.on(\"change:size\", checkSize);\n });\n return promise;\n}\n\nfunction wait(milliseconds: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, milliseconds));\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"MapModel.js","sources":["MapModel.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2023-2025 Open Pioneer project (https://github.com/open-pioneer)\n// SPDX-License-Identifier: Apache-2.0\n\nimport { computed, reactive, ReadonlyReactive, synchronized } from \"@conterra/reactivity-core\";\nimport { emit, emitter, EventSource } from \"@conterra/reactivity-events\";\nimport {\n createAbortError,\n createLogger,\n createManualPromise,\n deprecated,\n isAbortError,\n ManualPromise\n} from \"@open-pioneer/core\";\nimport { HttpService } from \"@open-pioneer/http\";\nimport { PackageIntl } from \"@open-pioneer/runtime\";\nimport { Coordinate } from \"ol/coordinate\";\nimport { EventsKey } from \"ol/events\";\nimport { createEmpty, extend, getArea, getCenter } from \"ol/extent\";\nimport { Geometry } from \"ol/geom\";\nimport OlMap from \"ol/Map\";\nimport { unByKey } from \"ol/Observable\";\nimport { getPointResolution, Projection } from \"ol/proj\";\nimport OlView from \"ol/View\";\nimport { sourceId } from \"open-pioneer:source-info\";\nimport { LAYER_DEPS, LayerDependencies } from \"../layers/shared/internals\";\nimport { BaseFeature } from \"../utils/BaseFeature\";\nimport { calculateBufferedExtent } from \"../utils/geometry-utils\";\nimport {\n assertInternalConstructor,\n INTERNAL_CONSTRUCTOR_TAG,\n InternalConstructorTag\n} from \"../utils/InternalConstructorTag\";\nimport { getGeometries } from \"./getGeometries\";\nimport {\n DESTROY_HIGHLIGHTS,\n Highlight,\n HighlightOptions,\n Highlights,\n HighlightZoomOptions\n} from \"./Highlights\";\nimport { LayerCollection } from \"./LayerCollection\";\nimport { MapAttributions } from \"./MapAttributions\";\nimport { ExtentConfig } from \"./MapConfig\";\nimport { Overlays } from \"./Overlays\";\n\nconst LOG = createLogger(sourceId);\n\nconst DEFAULT_DPI = 25.4 / 0.28;\nconst INCHES_PER_METRE = 39.37;\n\nconst DEFAULT_OL_POINT_ZOOM_LEVEL = 17;\nconst DEFAULT_OL_MAX_ZOOM_LEVEL = 20;\nconst DEFAULT_VIEW_PADDING = { top: 50, right: 20, bottom: 10, left: 20 };\n\nexport const DISPLAY_STATUS = Symbol(\"DISPLAY_STATUS\");\n\nconst deprecatedHighlights = deprecated({\n name: \"MapModel highlight function called\",\n packageName: \"@open-pioneer/map\",\n since: \"v1.3.0\",\n alternative: \"call methods of myMapModel.highlights instead\"\n});\n\n/**\n * Options supported when calling {@link MapModel.zoom}.\n *\n * @group Map Model\n **/\nexport interface ZoomOptions {\n /**\n * The zoom-level used if there is no valid extend (such as for single points).\n */\n pointZoom?: number;\n\n /**\n * The maximum zoom-level for multiple points, line or polygon results.\n */\n maxZoom?: number;\n\n /**\n * The view padding to make all features visible.\n */\n viewPadding?: MapPadding;\n\n /**\n * The buffer factor around the extent of the zoomed features. E.g. a value of 1.1 will add\n * 10% to specify the size increase of the extent's width and height.\n */\n buffer?: number;\n}\n\n/**\n * Represents an object in the map.\n *\n * @group Map Model\n */\nexport type DisplayTarget = BaseFeature | Geometry;\n\n/**\n * Map padding, all values are pixels.\n *\n * See https://openlayers.org/en/latest/apidoc/module-ol_View-View.html#padding\n *\n * @group Map Model\n */\nexport interface MapPadding {\n left?: number;\n right?: number;\n top?: number;\n bottom?: number;\n}\n\n/**\n * An item that should be displayed as part of the attributions for the map.\n *\n * @group MapModel\n */\nexport interface AttributionItem {\n /**\n * The attribution's text.\n *\n * Note that this property contains raw HTML tags.\n * The HTML content has been sanitized, so it is safe to display in the user interface.\n */\n text: string;\n}\n\ntype DisplayStatus = \"waiting\" | \"ready\" | \"error\";\n\n/**\n * Represents a map.\n *\n * @group Map Model\n */\nexport class MapModel {\n readonly #id: string;\n readonly #olMap: OlMap;\n readonly #olView: ReadonlyReactive<OlView>;\n readonly #attributions: MapAttributions;\n readonly #layers = new LayerCollection(this, INTERNAL_CONSTRUCTOR_TAG);\n readonly #highlights: Highlights;\n readonly #tooltips: Overlays;\n readonly #layerDeps: LayerDependencies;\n readonly #destroyed = emitter();\n\n #loadStartEventHandler: EventsKey | undefined;\n #loadEndEventHandler: EventsKey | undefined;\n readonly #olLoading = reactive(false);\n\n #isDestroyed = false;\n readonly #container: ReadonlyReactive<HTMLElement | undefined>;\n readonly #initialExtent = reactive<ExtentConfig>();\n readonly #viewBindings: ReadonlyReactive<ViewBindings>;\n readonly #scale: ReadonlyReactive<number | undefined>;\n\n readonly #abortController = new AbortController();\n #displayStatus: DisplayStatus;\n #displayWaiter: ManualPromise<void> | undefined;\n\n /**\n * @internal\n */\n constructor(\n options: {\n id: string;\n olMap: OlMap;\n initialExtent: ExtentConfig | undefined;\n showDefaultAttributions: boolean;\n currentIntl: ReadonlyReactive<PackageIntl>;\n httpService: HttpService;\n },\n tag: InternalConstructorTag\n ) {\n assertInternalConstructor(tag);\n\n this.#id = options.id;\n this.#olMap = options.olMap;\n this.#attributions = new MapAttributions({\n intl: options.currentIntl,\n olMap: this.#olMap,\n showControl: options.showDefaultAttributions\n });\n\n this.#olView = synchronized(\n () => this.#olMap.getView(),\n (cb) => {\n const key = this.#olMap.on(\"change:view\", cb);\n return () => unByKey(key);\n }\n );\n\n // NOTE: As early as possible (before any async actions) so we don't miss any events.\n this.#watchLoadingState();\n\n this.#initialExtent.value = options.initialExtent;\n this.#layerDeps = {\n httpService: options.httpService\n };\n\n this.#displayStatus = \"waiting\";\n this.#initializeView().then(\n () => {\n this.#displayStatus = \"ready\";\n this.#displayWaiter?.resolve();\n this.#displayWaiter = undefined;\n },\n (error) => {\n if (!isAbortError(error)) {\n LOG.error(`Failed to initialize map`, error);\n }\n\n this.#displayStatus = \"error\";\n this.#displayWaiter?.reject(new Error(`Failed to initialize map.`));\n this.#displayWaiter = undefined;\n }\n );\n\n this.#container = synchronized(\n () => this.#olMap.getTargetElement() ?? undefined,\n (cb) => {\n const key = this.#olMap.on(\"change:target\", cb);\n return () => unByKey(key);\n }\n );\n\n this.#viewBindings = computed(() => createViewBindings(this.#olView.value));\n this.#scale = computed(() => {\n const { projection, resolution, center } = this;\n if (projection == null || resolution == null || center == null) {\n return undefined;\n }\n\n /**\n * Returns the appropriate scale for the given resolution and units, see OpenLayers function getScaleForResolution()\n * https://github.com/openlayers/openlayers/blob/7fa9df03431e9e1bc517e6c414565d9f848a3132/src/ol/control/ScaleLine.js#L454C3-L454C24\n */\n const pointResolution = getPointResolution(projection, resolution, center, \"m\"); //point resolution in meter per pixel\n const scale = Math.round(pointResolution * INCHES_PER_METRE * DEFAULT_DPI);\n return scale;\n });\n\n // expects fully constructed mapModel\n this.#highlights = new Highlights(this, this.#layerDeps);\n this.#tooltips = new Overlays(this);\n }\n\n /**\n * Destroys this objects, including all layers, highlights and the OL map itself.\n */\n destroy() {\n if (this.#isDestroyed) {\n return;\n }\n\n this.#isDestroyed = true;\n try {\n emit(this.#destroyed);\n } catch (e) {\n LOG.warn(`Unexpected error from event listener during map model destruction:`, e);\n }\n\n this.#loadStartEventHandler && unByKey(this.#loadStartEventHandler);\n this.#loadStartEventHandler = undefined;\n this.#loadEndEventHandler && unByKey(this.#loadEndEventHandler);\n this.#loadEndEventHandler = undefined;\n\n this.#abortController.abort();\n this.#displayWaiter?.reject(new Error(\"Map model was destroyed.\"));\n this.#layers.destroy();\n this.#highlights[DESTROY_HIGHLIGHTS]();\n this.#attributions.destroy();\n this.#olMap.dispose();\n }\n\n /**\n * Emitted when the map model is destroyed.\n */\n get destroyed(): EventSource<void> {\n return this.#destroyed;\n }\n\n /**\n * Returns the map's current display status.\n * This is `waiting` during initialization and `error` or `ready` when done.\n *\n * @internal\n */\n get [DISPLAY_STATUS](): DisplayStatus {\n return this.#displayStatus;\n }\n\n /**\n * The unique id of the map.\n */\n get id(): string {\n return this.#id;\n }\n\n /**\n * The initial map extent.\n *\n * May be undefined before the map is shown.\n * This is guaranteed to be initialized if the promise returned by {@link whenDisplayed} has resolved.\n */\n get initialExtent(): ExtentConfig | undefined {\n return this.#initialExtent.value;\n }\n\n /**\n * Returns the current projection of the map (reactive).\n */\n get projection(): Projection {\n return this.#viewBindings.value.projection;\n }\n\n /**\n * Returns the current center of the map.\n * Same as `olView.getCenter()`, but reactive.\n */\n get center(): Coordinate | undefined {\n return this.#viewBindings.value.center.value;\n }\n\n /**\n * Returns the current resolution of the map.\n * Same as `olView.getResolution()`, but reactive.\n */\n get resolution(): number | undefined {\n return this.#viewBindings.value.resolution.value;\n }\n\n /**\n * Returns the current zoom level of the map.\n * Same as `olView.getZoom()`, but reactive.\n */\n get zoomLevel(): number | undefined {\n return this.#viewBindings.value.zoom.value;\n }\n\n /**\n * Returns the current rotation of the map.\n * Same as `olView.getRotation()`, but reactive.\n */\n get rotation(): number | undefined {\n return this.#viewBindings.value.rotation.value;\n }\n\n /**\n * Returns the current scale of the map.\n *\n * The scale is a value derived from the current `center`, `resolution` and `projection` of the map.\n * The scale will change when the map is zoomed in our out, but depending on the projection, it may also\n * change when the map is _panned_.\n *\n * > NOTE: Technically, this is the _denominator_ of the current scale.\n * > In order to display it, use a format like `1:${scale}`.\n */\n get scale(): number | undefined {\n return this.#scale.value;\n }\n\n /**\n * Returns true if the map is currently loading.\n *\n * This is based on the OpenLayers events `loadstart` and `loadend`,\n * see [Documentation](https://openlayers.org/en/latest/apidoc/module-ol_MapEvent-MapEvent.html#event:loadstart).\n */\n get loading(): boolean {\n return this.#olLoading.value;\n }\n\n /**\n * Contains all known layers of this map.\n *\n * Note that not all layers in this collection may be active in the OpenLayers map.\n * Also note that not all layers in the OpenLayers map may be contained in this collection.\n */\n get layers(): LayerCollection {\n return this.#layers;\n }\n\n /**\n * The container in which the map is currently being rendered.\n * This is the same as the target element of the underlying OpenLayers map.\n *\n * May be undefined if the map is not being rendered at the moment.\n * May change at runtime.\n */\n get container(): HTMLElement | undefined {\n return this.#container.value;\n }\n\n /**\n * Returns attributions for the current content of the map.\n */\n get attributionItems(): AttributionItem[] {\n return this.#attributions.attributionItems;\n }\n\n /**\n * The raw OpenLayers map.\n */\n get olMap(): OlMap {\n return this.#olMap;\n }\n\n /**\n * Returns the current view of the OpenLayers map.\n */\n get olView(): OlView {\n return this.#olView.value;\n }\n\n /**\n * TODO: Can be removed once the LayerFactory is the only supported way of constructing a layer.\n *\n * @internal\n */\n get [LAYER_DEPS](): LayerDependencies {\n return this.#layerDeps;\n }\n\n /**\n * Create and receive map overlays\n */\n get overlays(): Overlays {\n return this.#tooltips;\n }\n\n /**\n * Create, receive and zoom to map highlights\n */\n get highlights(): Highlights {\n return this.#highlights;\n }\n\n /**\n * Changes the current scale of the map to the given value.\n *\n * Internally, this computes a new zoom level / resolution based on the scale\n * and the current center.\n * The new resolution is then applied to the current `olView`.\n *\n * See also {@link scale}.\n */\n setScale(newScale: number): void {\n const view = this.olView;\n const projection = this.projection;\n const center = this.center;\n if (!center) {\n return;\n }\n\n const mpu = projection.getMetersPerUnit() ?? 1;\n const resolution = INCHES_PER_METRE * DEFAULT_DPI * mpu;\n const pointResolution = newScale / getPointResolution(projection, resolution, center);\n view.setResolution(pointResolution);\n }\n\n /**\n * Zooms to the given targets.\n */\n zoom(displayTargets: DisplayTarget[], options?: ZoomOptions | undefined): void {\n const olView = this.olView;\n const geometries = getGeometries(displayTargets);\n if (geometries.length === 0) {\n return;\n }\n\n let extent = createEmpty();\n for (const geometry of geometries) {\n extent = extend(extent, geometry.getExtent());\n }\n\n const bufferParameter = options?.buffer;\n if (typeof bufferParameter === \"number\") {\n extent = calculateBufferedExtent(extent, bufferParameter);\n }\n\n const center = getCenter(extent);\n const isPoint = getArea(extent) === 0;\n const zoomLevel = isPoint\n ? (options?.pointZoom ?? DEFAULT_OL_POINT_ZOOM_LEVEL)\n : (options?.maxZoom ?? DEFAULT_OL_MAX_ZOOM_LEVEL);\n if (center && center.length) {\n olView.setCenter(center);\n }\n\n const {\n top = 0,\n right = 0,\n bottom = 0,\n left = 0\n } = options?.viewPadding ?? DEFAULT_VIEW_PADDING;\n const padding = [top, right, bottom, left];\n\n if (extent) {\n olView.fit(extent, { maxZoom: zoomLevel, padding });\n } else if (zoomLevel) {\n olView.setZoom(zoomLevel);\n }\n }\n\n /**\n * Creates a highlight at the given targets.\n *\n * A highlight is a temporary graphic on the map that calls attention to a point or an area.\n *\n * Call `destroy()` on the returned highlight object to remove the highlight.\n *\n * @deprecated Highlight functions will be removed in a future major release; call {@link Highlights.add} instead.\n */\n highlight(geometries: DisplayTarget[], options?: HighlightOptions | undefined): Highlight {\n deprecatedHighlights();\n return this.#highlights.add(geometries, options);\n }\n\n /**\n * Creates a highlight and zooms to the given targets.\n *\n * See also {@link highlight} and {@link zoom}.\n *\n * @deprecated Highlight functions will be removed in a future major release; call {@link Highlights.addAndZoom} instead.\n */\n highlightAndZoom(geometries: DisplayTarget[], options?: HighlightZoomOptions): Highlight {\n deprecatedHighlights();\n return this.#highlights.addAndZoom(geometries, options ?? {});\n }\n\n /**\n * Removes any existing highlights from the map.\n *\n * @deprecated Highlight functions wil be removed in a future major release; call {@link Highlights.clear} instead.\n */\n removeHighlights(): void {\n deprecatedHighlights();\n this.#highlights.clear();\n }\n\n /**\n * Returns a promise that resolves when the map has mounted in the DOM.\n */\n whenDisplayed(): Promise<void> {\n if (this.#isDestroyed) {\n return Promise.reject(new Error(\"Map model was destroyed.\"));\n }\n if (this.#displayStatus === \"error\") {\n return Promise.reject(new Error(`Failed to initialize map.`));\n }\n if (this.#displayStatus === \"ready\") {\n return Promise.resolve();\n }\n return (this.#displayWaiter ??= createManualPromise()).promise;\n }\n\n /**\n * Waits for the map to be displayed and then initializes the view (if necessary).\n *\n * May simply resolve when done, or throw an error when a problem occurs.\n * AbortError is thrown when cancelled via `this.#abortController`, for example\n * when the map model is destroyed before it has ever been displayed.\n */\n async #initializeView(): Promise<void> {\n try {\n await waitForMapSize(this.olMap, this.#abortController.signal); // may throw on cancel\n } catch (e) {\n if (isAbortError(e)) {\n throw e;\n }\n throw new Error(`Failed to wait for the map to be displayed.`, { cause: e });\n }\n\n try {\n const olMap = this.#olMap;\n const view = olMap.getView();\n\n if (this.#initialExtent.value) {\n // Initial extent was set from the outside. We simply ensure that it gets displayed by the map.\n const extent = this.#initialExtent.value;\n const olExtent = [extent.xMin, extent.yMin, extent.xMax, extent.yMax];\n\n const olCenter = getCenter(olExtent);\n const resolution = view.getResolutionForExtent(olExtent);\n LOG.debug(`Applying initial extent`, extent);\n LOG.debug(` Computed center:`, olCenter);\n LOG.debug(` Computed resolution:`, resolution);\n\n view.setCenter(olCenter);\n view.setResolution(resolution);\n } else {\n // Initial extent was NOT set from the outside.\n // We detect whatever the view is displaying and consider it to be the initial extent.\n const olExtent = view.calculateExtent();\n const [xMin = 0, yMin = 0, xMax = 0, yMax = 0] = olExtent;\n const extent: ExtentConfig = { xMin, yMin, xMax, yMax };\n LOG.debug(`Detected initial extent`, extent);\n\n this.#initialExtent.value = extent;\n }\n } catch (e) {\n throw new Error(`Failed to apply the initial extent.`, { cause: e });\n }\n }\n\n /**\n * Subscribes to the OpenLayers loading state.\n */\n #watchLoadingState() {\n this.#loadStartEventHandler = this.#olMap.on(\"loadstart\", () => {\n this.#olLoading.value = true;\n });\n this.#loadEndEventHandler = this.#olMap.on(\"loadend\", () => {\n this.#olLoading.value = false;\n });\n }\n}\n\ninterface ViewBindings {\n resolution: ReadonlyReactive<number | undefined>;\n center: ReadonlyReactive<Coordinate | undefined>;\n zoom: ReadonlyReactive<number | undefined>;\n rotation: ReadonlyReactive<number | undefined>;\n projection: Projection; // not reactive (change view to change projection)\n}\n\nfunction createViewBindings(view: OlView): ViewBindings {\n return {\n resolution: synchronized(\n () => view.getResolution(),\n (cb) => {\n const key = view.on(\"change:resolution\", cb);\n return () => unByKey(key);\n }\n ),\n center: synchronized(\n () => view.getCenter(),\n (cb) => {\n const key = view.on(\"change:center\", cb);\n return () => unByKey(key);\n }\n ),\n zoom: synchronized(\n () => view.getZoom(),\n (cb) => {\n const key = view.on(\"change:resolution\", cb);\n return () => unByKey(key);\n }\n ),\n rotation: synchronized(\n () => view.getRotation(),\n (cb) => {\n const key = view.on(\"change:rotation\", cb);\n return () => unByKey(key);\n }\n ),\n projection: view.getProjection()\n };\n}\n\nfunction waitForMapSize(olMap: OlMap, signal: AbortSignal): Promise<void> {\n const promise = new Promise<void>((resolve, reject) => {\n let eventKey: EventsKey | undefined;\n\n function checkSize() {\n const currentSize = olMap.getSize() ?? [];\n const [width = 0, height = 0] = currentSize;\n if (currentSize && width > 0 && height > 0) {\n finish();\n }\n }\n\n function onAbort() {\n finish(createAbortError());\n }\n\n function finish(error?: Error | undefined) {\n if (eventKey) {\n unByKey(eventKey);\n eventKey = undefined;\n }\n signal.removeEventListener(\"abort\", onAbort);\n\n if (error) {\n reject(error);\n } else {\n resolve(wait(25)); // Give the map some time to render\n }\n }\n\n if (signal.aborted) {\n finish(createAbortError());\n return;\n }\n\n signal.addEventListener(\"abort\", onAbort);\n eventKey = olMap.on(\"change:size\", checkSize);\n });\n return promise;\n}\n\nfunction wait(milliseconds: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, milliseconds));\n}\n"],"names":[],"mappings":"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"}
|
package/model/Overlays.d.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { Overlay as OlOverlay } from "ol";
|
|
2
|
-
import { MapModel } from "./MapModel";
|
|
3
2
|
import { Coordinate } from "ol/coordinate";
|
|
4
|
-
import { ReactNode } from "react";
|
|
5
3
|
import { Options } from "ol/Overlay";
|
|
4
|
+
import { ReactNode } from "react";
|
|
6
5
|
import { InternalConstructorTag } from "../utils/InternalConstructorTag";
|
|
6
|
+
import { MapModel } from "./MapModel";
|
|
7
7
|
export declare const REGISTER_OVERLAY: unique symbol;
|
|
8
8
|
export declare const UNREGISTER_OVERLAY: unique symbol;
|
|
9
9
|
/**
|
package/model/Overlays.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { Overlay as Overlay$1 } from 'ol';
|
|
2
1
|
import { reactiveSet, reactive, synchronized, watchValue, batch } from '@conterra/reactivity-core';
|
|
3
|
-
import { v4 } from 'uuid';
|
|
4
2
|
import { createLogger, destroyResources } from '@open-pioneer/core';
|
|
3
|
+
import { Overlay as Overlay$1 } from 'ol';
|
|
5
4
|
import { unByKey } from 'ol/Observable.js';
|
|
6
5
|
import { sourceId$2 as sourceId } from '../_virtual/source-info.js';
|
|
6
|
+
import { v4 } from 'uuid';
|
|
7
7
|
import { INTERNAL_CONSTRUCTOR_TAG } from '../utils/InternalConstructorTag.js';
|
|
8
8
|
|
|
9
9
|
const REGISTER_OVERLAY = /* @__PURE__ */ Symbol("REGISTER_OVERLAY");
|
package/model/Overlays.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Overlays.js","sources":["Overlays.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2023-2025 Open Pioneer project (https://github.com/open-pioneer)\n// SPDX-License-Identifier: Apache-2.0\n\nimport { Map as OlMap, Overlay as OlOverlay } from \"ol\";\nimport { MapModel } from \"./MapModel\";\nimport { Coordinate } from \"ol/coordinate\";\nimport { ReactNode } from \"react\";\nimport {\n batch,\n reactive,\n Reactive,\n reactiveSet,\n synchronized,\n watchValue\n} from \"@conterra/reactivity-core\";\nimport { v4 as uuid4v } from \"uuid\";\nimport { createLogger, destroyResources, Resource } from \"@open-pioneer/core\";\nimport { EventsKey } from \"ol/events\";\nimport { unByKey } from \"ol/Observable\";\nimport { Options } from \"ol/Overlay\";\nimport { sourceId } from \"open-pioneer:source-info\";\nimport { INTERNAL_CONSTRUCTOR_TAG, InternalConstructorTag } from \"../utils/InternalConstructorTag\";\n\nexport const REGISTER_OVERLAY = Symbol(\"REGISTER_OVERLAY\");\nexport const UNREGISTER_OVERLAY = Symbol(\"UNREGISTER_OVERLAY\");\n\nconst LOG = createLogger(sourceId);\n\n/**\n * Manages active overlays on the map.\n *\n * @group Map Model\n */\nexport class Overlays {\n #olMap: OlMap;\n #overlays = reactiveSet<Overlay>();\n\n constructor(map: MapModel) {\n this.#olMap = map.olMap;\n }\n\n [REGISTER_OVERLAY](overlay: Overlay) {\n if (this.#overlays.has(overlay)) {\n throw new Error(\"Internal error: overlay is already registered\");\n }\n this.#overlays.add(overlay);\n this.#olMap.addOverlay(overlay.olOverlay);\n }\n\n [UNREGISTER_OVERLAY](overlay: Overlay) {\n if (!this.#overlays.has(overlay)) {\n throw new Error(\"Internal error: overlay was not registered\");\n }\n this.#overlays.delete(overlay);\n this.#olMap.removeOverlay(overlay.olOverlay);\n }\n\n /**\n * Add new overlay to the map. Returns the newly created overlay instance.\n */\n add(options: OverlayOptions): Overlay {\n const newModel = new Overlay(INTERNAL_CONSTRUCTOR_TAG, options, this);\n return newModel;\n }\n\n /**\n * Returns the list of all current overlays.\n */\n getAll(): Overlay[] {\n return Array.from(this.#overlays);\n }\n\n /**\n * Destroys all overlays.\n */\n clear(): void {\n for (const overlay of this.#overlays) {\n overlay.destroy();\n }\n }\n}\n\n/**\n * Options that define the initial state of an overlay.\n *\n * @group Map Model\n */\nexport interface OverlayOptions {\n /**\n * Optional, readonly tag that helps identifying the overlay instance.\n */\n tag?: string;\n\n /**\n * Displayed content of the overlay.\n *\n * @see {@link Overlay.setContent}.\n */\n content?: ReactNode;\n\n /**\n * CSS classes of the HTML element that wraps the overlay's content.\n */\n className?: string;\n\n /**\n * Role of the HTML element that wraps the overlay's content.\n */\n ariaRole?: string;\n\n /**\n * Configures the position of the overlay.\n * The overlay is not rendered if position is `undefined` (the default).\n *\n * See {@link OverlayPosition} for all supported position options.\n *\n * The following shorthands are available:\n * - A plain `Coordinate` array can be used to specify a static coordinate on the map.\n * - `undefined` hides the overlay.\n * - `\"follow-pointer\"` can be used as a shorthand to follow the user's cursor.\n *\n * @see {@link Overlay.setPosition} to reconfigure the position.\n * @see {@link Overlay.currentCoordinate} to retrieve the actual position on the map.\n */\n position?: Coordinate | \"follow-pointer\" | OverlayPosition;\n\n /**\n * Positioning of an overlay relative to its coordinates on the map.\n *\n * @see {@link Overlay.setPositioning}\n */\n positioning?: OverlayPositioning;\n\n /**\n * Offsets in _pixels_ relative to the overlay`s coordinates on the map.\n * The first element in the array is the horizontal offset.\n *\n * @see {@link Overlay.setOffset}\n */\n offset?: number[];\n\n /**\n * Determines if event propagation to the map viewport should be stopped.\n *\n * By default `stopEvent` is `true`.\n */\n stopEvent?: boolean;\n\n /**\n * Raw OpenLayers overlay properties. `OlOverlayOptions` override corresponding `OverlayProperties`, except for id and element.\n *\n * **warning** Using OpenLayers options can create inconsistencies that lead to errors.\n * The OpenLayers API can change with updates of OpenLayers.\n */\n advanced?: OlOverlayOptions;\n}\n\n/**\n * The configured position of an overlay.\n *\n * @group Map Model\n */\nexport type OverlayPosition =\n /** Explicit (static) coordinates on the map. */\n | OverlayPositionCoordinate\n /** Update coordinates based on pointer movements on the map, useful for tooltips. */\n | OverlayPositionFollowPointer;\n\n/**\n * Automatically positions the overlay on the mouse cursor's coordinates.\n *\n * This can be used, for example, to implement tooltips for map interactions.\n *\n * @group Map Model\n */\nexport interface OverlayPositionFollowPointer {\n kind: \"follow-pointer\";\n\n /**\n * The initial coordinates.\n *\n * Use `undefined` (the default) to hide until the first mouse event on the map.\n */\n initial?: Coordinate;\n}\n\n/**\n * Places the overlay at the given coordinates.\n *\n * @group Map Model\n */\nexport interface OverlayPositionCoordinate {\n kind: \"coordinate\";\n\n /**\n * The explicit coordinates of the overlay on the map.\n *\n * Using `undefined` hides the overlay.\n */\n coordinate?: Coordinate;\n}\n\n/**\n * Positioning of an overlay relative to its coordinates on the map.\n *\n * @group Map Model\n */\nexport type OverlayPositioning =\n | \"bottom-left\"\n | \"bottom-center\"\n | \"bottom-right\"\n | \"center-left\"\n | \"center-center\"\n | \"center-right\"\n | \"top-left\"\n | \"top-center\"\n | \"top-right\";\n\n/** @group Map Model */\nexport interface OlOverlayOptions extends Omit<Partial<Options>, \"id\" | \"element\"> {}\n\n/**\n * An overlay is an UI element that is displayed over the map.\n *\n * Overlays are tied to coordinates on the map and not to a position on the screen.\n * The overlay renders a react node at the specified coordinates.\n *\n * @group Map Model\n */\nexport class Overlay {\n /**\n * Unique, readonly id of the overlay.\n *\n * Automatically assigned when the overlay is created. Use the `tag` property for custom identifiers.\n */\n readonly id: string;\n\n /**\n * Optional, readonly tag that helps identifying the overlay instance.\n */\n readonly tag: string | undefined;\n\n /**\n * Raw, corresponding OpenLayers overlay object.\n *\n * **warning** Manipulation of the OpenLayers object can create inconsistencies that lead to errors. The OpenLayers API can change with updates of OpenLayers.\n *\n * @see https://openlayers.org/en/latest/apidoc/module-ol_Overlay-Overlay.html\n */\n readonly olOverlay: OlOverlay;\n\n #parent: Overlays;\n #isDestroyed = reactive(false);\n #position = reactive<OverlayPosition>({ kind: \"coordinate\" });\n #content: Reactive<ReactNode>;\n #overlayDiv: HTMLDivElement;\n #resources: Resource[] = [];\n\n #coordinate = synchronized(\n () => this.olOverlay.getPosition(),\n (cb) => {\n const key = this.olOverlay.on(\"change:position\", cb);\n return () => unByKey(key);\n }\n );\n #positioning = synchronized(\n () => this.olOverlay.getPositioning(),\n (cb) => {\n const key = this.olOverlay.on(\"change:positioning\", cb);\n return () => unByKey(key);\n }\n );\n #offset = synchronized(\n () => this.olOverlay.getOffset(),\n (cb) => {\n const key = this.olOverlay.on(\"change:offset\", cb);\n return () => unByKey(key);\n }\n );\n\n constructor(internalTag: InternalConstructorTag, options: OverlayOptions, parent: Overlays) {\n if (internalTag !== INTERNAL_CONSTRUCTOR_TAG) {\n throw new Error(\"The overlay constructor is private.\");\n }\n const {\n className,\n ariaRole,\n position,\n tag,\n content,\n offset,\n positioning,\n stopEvent,\n advanced\n } = options;\n this.id = uuid4v();\n this.tag = tag;\n this.#overlayDiv = createElement(ariaRole, className);\n\n this.olOverlay = new OlOverlay({\n element: this.#overlayDiv,\n id: this.id,\n offset,\n positioning,\n stopEvent,\n //simply override with advanced OL Options if set\n ...advanced\n });\n this.#parent = parent;\n this.#content = reactive(content);\n this.setPosition(position);\n\n parent[REGISTER_OVERLAY](this);\n\n this.#resources.push(\n // Update coordinate based on pointer movements when configured.\n // Automatically subscribes and unsubscribes on changes.\n watchValue(\n () => this.#position.value?.kind === \"follow-pointer\",\n (followPointer) => {\n if (!followPointer) {\n return;\n }\n\n // NOTE: If this turns out to be unstable we can also transport the map model reference here\n // to get our olMap.\n const olMap = this.olOverlay.getMap();\n if (!olMap) {\n LOG.error(\n `Overlay ${this.olOverlay.getId()} is not registered with a map.`\n );\n return;\n }\n\n const pointerMoveKey: EventsKey = olMap.on(\"pointermove\", (e) => {\n this.olOverlay.setPosition(e.coordinate);\n });\n return () => unByKey(pointerMoveKey);\n },\n { immediate: true, dispatch: \"sync\" }\n )\n );\n }\n\n /**\n * Destroys the overlay and removes it from the map.\n * An overlay that is destroyed cannot be added to the map again.\n */\n destroy(): void {\n if (this.isDestroyed) {\n return;\n }\n\n batch(() => {\n this.#isDestroyed.value = true;\n this.#parent[UNREGISTER_OVERLAY](this);\n this.olOverlay.dispose();\n destroyResources(this.#resources);\n });\n }\n\n /**\n * Indicates if the overlay instance has been destroyed.\n */\n get isDestroyed(): boolean {\n return this.#isDestroyed.value;\n }\n\n /**\n * Current coordinates of the overlay on the map.\n *\n * The coordinates on the map are configured via {@link OverlayOptions.position} or {@link setPosition}.\n *\n * - If configured with static coordinates (i.e. `position.kind === \"coordinate\"`), this is\n * the same as `position.coordinate`.\n * - If configured with `\"follow-pointer\"` position, this is the result of the user's pointer movements.\n */\n get currentCoordinate(): Coordinate | undefined {\n return this.#coordinate.value;\n }\n\n /**\n * The content of the overlay that is currently rendered.\n */\n get content(): ReactNode {\n return this.#content.value;\n }\n\n /**\n * The HTML element that that wraps the overlay's content.\n */\n get element(): HTMLElement {\n return this.#overlayDiv;\n }\n\n /**\n * Offset in _pixels_ relative to the overlay`s coordinates.\n *\n * The first element in the array is the horizontal offset.\n */\n get offset(): number[] {\n return this.#offset.value;\n }\n\n /**\n * The configured position of the overlay on the map.\n *\n * See also {@link currentCoordinate} to get the coordinate\n * that are the result of this configuration.\n *\n * > NOTE: The return value of the getter may not be the same\n * > as the input to the setter (or constructor) due to normalization.\n */\n get position(): OverlayPosition {\n return this.#position.value;\n }\n\n /**\n * Positioning of an overlay relative to its coordinates on the map.\n */\n get positioning(): OverlayPositioning {\n return this.#positioning.value;\n }\n\n /**\n * Set new content that is rendered on the overlay.\n */\n setContent(content: ReactNode): void {\n this.#content.value = content;\n }\n\n /**\n * Set the position of the overlay.\n *\n * This controls the coordinates of the map.\n * The overlay is not rendered if the coordinates are `undefined`.\n *\n * See also {@link currentCoordinate} to get the coordinates\n * that are the result of this configuration.\n *\n * @see {@link OverlayPosition}\n */\n setPosition(position: OverlayOptions[\"position\"]) {\n const normalized = normalizePosition(position);\n\n let newCoordinate: Coordinate | undefined;\n if (normalized) {\n if (normalized.kind === \"coordinate\") {\n newCoordinate = normalized.coordinate;\n } else {\n newCoordinate = normalized.initial;\n // mouse event handler will update this on its own\n }\n }\n\n batch(() => {\n this.#position.value = normalized;\n this.olOverlay.setPosition(newCoordinate);\n });\n }\n\n /**\n * Set offset in _pixels_ relative to the overlay`s coordinates on the map.\n * The first element in the array is the horizontal offset.\n */\n setOffset(offset: number[]) {\n this.olOverlay.setOffset(offset);\n }\n\n /**\n * Set positioning of an overlay relative to its coordinates on the map.\n */\n setPositioning(positioning: OverlayPositioning) {\n this.olOverlay.setPositioning(positioning);\n }\n}\n\nfunction normalizePosition(position: OverlayOptions[\"position\"]): OverlayPosition {\n if (!position || Array.isArray(position)) {\n return { kind: \"coordinate\", coordinate: position };\n }\n if (position === \"follow-pointer\") {\n return { kind: \"follow-pointer\" };\n }\n if (typeof position !== \"object\") {\n throw new Error(\"Unexpected position: \" + position);\n }\n return position;\n}\n\nfunction createElement(ariaRole: string | undefined, classNameProp: string | undefined) {\n const overlayDiv = document.createElement(\"div\");\n if (ariaRole) {\n overlayDiv.role = ariaRole;\n }\n\n let className = \"map-overlay\";\n if (classNameProp) {\n className += ` ${classNameProp}`;\n }\n overlayDiv.className = className;\n return overlayDiv;\n}\n"],"names":["uuid4v","OlOverlay"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"Overlays.js","sources":["Overlays.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2023-2025 Open Pioneer project (https://github.com/open-pioneer)\n// SPDX-License-Identifier: Apache-2.0\n\nimport {\n batch,\n reactive,\n Reactive,\n reactiveSet,\n synchronized,\n watchValue\n} from \"@conterra/reactivity-core\";\nimport { createLogger, destroyResources, Resource } from \"@open-pioneer/core\";\nimport { Map as OlMap, Overlay as OlOverlay } from \"ol\";\nimport { Coordinate } from \"ol/coordinate\";\nimport { EventsKey } from \"ol/events\";\nimport { unByKey } from \"ol/Observable\";\nimport { Options } from \"ol/Overlay\";\nimport { sourceId } from \"open-pioneer:source-info\";\nimport { ReactNode } from \"react\";\nimport { v4 as uuid4v } from \"uuid\";\nimport { INTERNAL_CONSTRUCTOR_TAG, InternalConstructorTag } from \"../utils/InternalConstructorTag\";\nimport { MapModel } from \"./MapModel\";\n\nexport const REGISTER_OVERLAY = Symbol(\"REGISTER_OVERLAY\");\nexport const UNREGISTER_OVERLAY = Symbol(\"UNREGISTER_OVERLAY\");\n\nconst LOG = createLogger(sourceId);\n\n/**\n * Manages active overlays on the map.\n *\n * @group Map Model\n */\nexport class Overlays {\n #olMap: OlMap;\n #overlays = reactiveSet<Overlay>();\n\n constructor(map: MapModel) {\n this.#olMap = map.olMap;\n }\n\n [REGISTER_OVERLAY](overlay: Overlay) {\n if (this.#overlays.has(overlay)) {\n throw new Error(\"Internal error: overlay is already registered\");\n }\n this.#overlays.add(overlay);\n this.#olMap.addOverlay(overlay.olOverlay);\n }\n\n [UNREGISTER_OVERLAY](overlay: Overlay) {\n if (!this.#overlays.has(overlay)) {\n throw new Error(\"Internal error: overlay was not registered\");\n }\n this.#overlays.delete(overlay);\n this.#olMap.removeOverlay(overlay.olOverlay);\n }\n\n /**\n * Add new overlay to the map. Returns the newly created overlay instance.\n */\n add(options: OverlayOptions): Overlay {\n const newModel = new Overlay(INTERNAL_CONSTRUCTOR_TAG, options, this);\n return newModel;\n }\n\n /**\n * Returns the list of all current overlays.\n */\n getAll(): Overlay[] {\n return Array.from(this.#overlays);\n }\n\n /**\n * Destroys all overlays.\n */\n clear(): void {\n for (const overlay of this.#overlays) {\n overlay.destroy();\n }\n }\n}\n\n/**\n * Options that define the initial state of an overlay.\n *\n * @group Map Model\n */\nexport interface OverlayOptions {\n /**\n * Optional, readonly tag that helps identifying the overlay instance.\n */\n tag?: string;\n\n /**\n * Displayed content of the overlay.\n *\n * @see {@link Overlay.setContent}.\n */\n content?: ReactNode;\n\n /**\n * CSS classes of the HTML element that wraps the overlay's content.\n */\n className?: string;\n\n /**\n * Role of the HTML element that wraps the overlay's content.\n */\n ariaRole?: string;\n\n /**\n * Configures the position of the overlay.\n * The overlay is not rendered if position is `undefined` (the default).\n *\n * See {@link OverlayPosition} for all supported position options.\n *\n * The following shorthands are available:\n * - A plain `Coordinate` array can be used to specify a static coordinate on the map.\n * - `undefined` hides the overlay.\n * - `\"follow-pointer\"` can be used as a shorthand to follow the user's cursor.\n *\n * @see {@link Overlay.setPosition} to reconfigure the position.\n * @see {@link Overlay.currentCoordinate} to retrieve the actual position on the map.\n */\n position?: Coordinate | \"follow-pointer\" | OverlayPosition;\n\n /**\n * Positioning of an overlay relative to its coordinates on the map.\n *\n * @see {@link Overlay.setPositioning}\n */\n positioning?: OverlayPositioning;\n\n /**\n * Offsets in _pixels_ relative to the overlay`s coordinates on the map.\n * The first element in the array is the horizontal offset.\n *\n * @see {@link Overlay.setOffset}\n */\n offset?: number[];\n\n /**\n * Determines if event propagation to the map viewport should be stopped.\n *\n * By default `stopEvent` is `true`.\n */\n stopEvent?: boolean;\n\n /**\n * Raw OpenLayers overlay properties. `OlOverlayOptions` override corresponding `OverlayProperties`, except for id and element.\n *\n * **warning** Using OpenLayers options can create inconsistencies that lead to errors.\n * The OpenLayers API can change with updates of OpenLayers.\n */\n advanced?: OlOverlayOptions;\n}\n\n/**\n * The configured position of an overlay.\n *\n * @group Map Model\n */\nexport type OverlayPosition =\n /** Explicit (static) coordinates on the map. */\n | OverlayPositionCoordinate\n /** Update coordinates based on pointer movements on the map, useful for tooltips. */\n | OverlayPositionFollowPointer;\n\n/**\n * Automatically positions the overlay on the mouse cursor's coordinates.\n *\n * This can be used, for example, to implement tooltips for map interactions.\n *\n * @group Map Model\n */\nexport interface OverlayPositionFollowPointer {\n kind: \"follow-pointer\";\n\n /**\n * The initial coordinates.\n *\n * Use `undefined` (the default) to hide until the first mouse event on the map.\n */\n initial?: Coordinate;\n}\n\n/**\n * Places the overlay at the given coordinates.\n *\n * @group Map Model\n */\nexport interface OverlayPositionCoordinate {\n kind: \"coordinate\";\n\n /**\n * The explicit coordinates of the overlay on the map.\n *\n * Using `undefined` hides the overlay.\n */\n coordinate?: Coordinate;\n}\n\n/**\n * Positioning of an overlay relative to its coordinates on the map.\n *\n * @group Map Model\n */\nexport type OverlayPositioning =\n | \"bottom-left\"\n | \"bottom-center\"\n | \"bottom-right\"\n | \"center-left\"\n | \"center-center\"\n | \"center-right\"\n | \"top-left\"\n | \"top-center\"\n | \"top-right\";\n\n/** @group Map Model */\nexport interface OlOverlayOptions extends Omit<Partial<Options>, \"id\" | \"element\"> {}\n\n/**\n * An overlay is an UI element that is displayed over the map.\n *\n * Overlays are tied to coordinates on the map and not to a position on the screen.\n * The overlay renders a react node at the specified coordinates.\n *\n * @group Map Model\n */\nexport class Overlay {\n /**\n * Unique, readonly id of the overlay.\n *\n * Automatically assigned when the overlay is created. Use the `tag` property for custom identifiers.\n */\n readonly id: string;\n\n /**\n * Optional, readonly tag that helps identifying the overlay instance.\n */\n readonly tag: string | undefined;\n\n /**\n * Raw, corresponding OpenLayers overlay object.\n *\n * **warning** Manipulation of the OpenLayers object can create inconsistencies that lead to errors. The OpenLayers API can change with updates of OpenLayers.\n *\n * @see https://openlayers.org/en/latest/apidoc/module-ol_Overlay-Overlay.html\n */\n readonly olOverlay: OlOverlay;\n\n #parent: Overlays;\n #isDestroyed = reactive(false);\n #position = reactive<OverlayPosition>({ kind: \"coordinate\" });\n #content: Reactive<ReactNode>;\n #overlayDiv: HTMLDivElement;\n #resources: Resource[] = [];\n\n #coordinate = synchronized(\n () => this.olOverlay.getPosition(),\n (cb) => {\n const key = this.olOverlay.on(\"change:position\", cb);\n return () => unByKey(key);\n }\n );\n #positioning = synchronized(\n () => this.olOverlay.getPositioning(),\n (cb) => {\n const key = this.olOverlay.on(\"change:positioning\", cb);\n return () => unByKey(key);\n }\n );\n #offset = synchronized(\n () => this.olOverlay.getOffset(),\n (cb) => {\n const key = this.olOverlay.on(\"change:offset\", cb);\n return () => unByKey(key);\n }\n );\n\n constructor(internalTag: InternalConstructorTag, options: OverlayOptions, parent: Overlays) {\n if (internalTag !== INTERNAL_CONSTRUCTOR_TAG) {\n throw new Error(\"The overlay constructor is private.\");\n }\n const {\n className,\n ariaRole,\n position,\n tag,\n content,\n offset,\n positioning,\n stopEvent,\n advanced\n } = options;\n this.id = uuid4v();\n this.tag = tag;\n this.#overlayDiv = createElement(ariaRole, className);\n\n this.olOverlay = new OlOverlay({\n element: this.#overlayDiv,\n id: this.id,\n offset,\n positioning,\n stopEvent,\n //simply override with advanced OL Options if set\n ...advanced\n });\n this.#parent = parent;\n this.#content = reactive(content);\n this.setPosition(position);\n\n parent[REGISTER_OVERLAY](this);\n\n this.#resources.push(\n // Update coordinate based on pointer movements when configured.\n // Automatically subscribes and unsubscribes on changes.\n watchValue(\n () => this.#position.value?.kind === \"follow-pointer\",\n (followPointer) => {\n if (!followPointer) {\n return;\n }\n\n // NOTE: If this turns out to be unstable we can also transport the map model reference here\n // to get our olMap.\n const olMap = this.olOverlay.getMap();\n if (!olMap) {\n LOG.error(\n `Overlay ${this.olOverlay.getId()} is not registered with a map.`\n );\n return;\n }\n\n const pointerMoveKey: EventsKey = olMap.on(\"pointermove\", (e) => {\n this.olOverlay.setPosition(e.coordinate);\n });\n return () => unByKey(pointerMoveKey);\n },\n { immediate: true, dispatch: \"sync\" }\n )\n );\n }\n\n /**\n * Destroys the overlay and removes it from the map.\n * An overlay that is destroyed cannot be added to the map again.\n */\n destroy(): void {\n if (this.isDestroyed) {\n return;\n }\n\n batch(() => {\n this.#isDestroyed.value = true;\n this.#parent[UNREGISTER_OVERLAY](this);\n this.olOverlay.dispose();\n destroyResources(this.#resources);\n });\n }\n\n /**\n * Indicates if the overlay instance has been destroyed.\n */\n get isDestroyed(): boolean {\n return this.#isDestroyed.value;\n }\n\n /**\n * Current coordinates of the overlay on the map.\n *\n * The coordinates on the map are configured via {@link OverlayOptions.position} or {@link setPosition}.\n *\n * - If configured with static coordinates (i.e. `position.kind === \"coordinate\"`), this is\n * the same as `position.coordinate`.\n * - If configured with `\"follow-pointer\"` position, this is the result of the user's pointer movements.\n */\n get currentCoordinate(): Coordinate | undefined {\n return this.#coordinate.value;\n }\n\n /**\n * The content of the overlay that is currently rendered.\n */\n get content(): ReactNode {\n return this.#content.value;\n }\n\n /**\n * The HTML element that that wraps the overlay's content.\n */\n get element(): HTMLElement {\n return this.#overlayDiv;\n }\n\n /**\n * Offset in _pixels_ relative to the overlay`s coordinates.\n *\n * The first element in the array is the horizontal offset.\n */\n get offset(): number[] {\n return this.#offset.value;\n }\n\n /**\n * The configured position of the overlay on the map.\n *\n * See also {@link currentCoordinate} to get the coordinate\n * that are the result of this configuration.\n *\n * > NOTE: The return value of the getter may not be the same\n * > as the input to the setter (or constructor) due to normalization.\n */\n get position(): OverlayPosition {\n return this.#position.value;\n }\n\n /**\n * Positioning of an overlay relative to its coordinates on the map.\n */\n get positioning(): OverlayPositioning {\n return this.#positioning.value;\n }\n\n /**\n * Set new content that is rendered on the overlay.\n */\n setContent(content: ReactNode): void {\n this.#content.value = content;\n }\n\n /**\n * Set the position of the overlay.\n *\n * This controls the coordinates of the map.\n * The overlay is not rendered if the coordinates are `undefined`.\n *\n * See also {@link currentCoordinate} to get the coordinates\n * that are the result of this configuration.\n *\n * @see {@link OverlayPosition}\n */\n setPosition(position: OverlayOptions[\"position\"]) {\n const normalized = normalizePosition(position);\n\n let newCoordinate: Coordinate | undefined;\n if (normalized) {\n if (normalized.kind === \"coordinate\") {\n newCoordinate = normalized.coordinate;\n } else {\n newCoordinate = normalized.initial;\n // mouse event handler will update this on its own\n }\n }\n\n batch(() => {\n this.#position.value = normalized;\n this.olOverlay.setPosition(newCoordinate);\n });\n }\n\n /**\n * Set offset in _pixels_ relative to the overlay`s coordinates on the map.\n * The first element in the array is the horizontal offset.\n */\n setOffset(offset: number[]) {\n this.olOverlay.setOffset(offset);\n }\n\n /**\n * Set positioning of an overlay relative to its coordinates on the map.\n */\n setPositioning(positioning: OverlayPositioning) {\n this.olOverlay.setPositioning(positioning);\n }\n}\n\nfunction normalizePosition(position: OverlayOptions[\"position\"]): OverlayPosition {\n if (!position || Array.isArray(position)) {\n return { kind: \"coordinate\", coordinate: position };\n }\n if (position === \"follow-pointer\") {\n return { kind: \"follow-pointer\" };\n }\n if (typeof position !== \"object\") {\n throw new Error(\"Unexpected position: \" + position);\n }\n return position;\n}\n\nfunction createElement(ariaRole: string | undefined, classNameProp: string | undefined) {\n const overlayDiv = document.createElement(\"div\");\n if (ariaRole) {\n overlayDiv.role = ariaRole;\n }\n\n let className = \"map-overlay\";\n if (classNameProp) {\n className += ` ${classNameProp}`;\n }\n overlayDiv.className = className;\n return overlayDiv;\n}\n"],"names":["uuid4v","OlOverlay"],"mappings":"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"}
|
package/model/createMapModel.js
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { batch } from '@conterra/reactivity-core';
|
|
2
2
|
import { createLogger } from '@open-pioneer/core';
|
|
3
|
-
import OlMap from 'ol/Map.js';
|
|
4
|
-
import View from 'ol/View.js';
|
|
5
3
|
import { getCenter } from 'ol/extent.js';
|
|
6
4
|
import { defaults, DragZoom } from 'ol/interaction.js';
|
|
7
5
|
import TileLayer from 'ol/layer/Tile.js';
|
|
6
|
+
import OlMap from 'ol/Map.js';
|
|
8
7
|
import { get } from 'ol/proj.js';
|
|
9
8
|
import OSM from 'ol/source/OSM.js';
|
|
10
|
-
import
|
|
9
|
+
import View from 'ol/View.js';
|
|
10
|
+
import { sourceId$10 as sourceId } from '../_virtual/source-info.js';
|
|
11
11
|
import { INTERNAL_CONSTRUCTOR_TAG } from '../utils/InternalConstructorTag.js';
|
|
12
12
|
import { patchOpenLayersClassesForTesting } from '../utils/ol-test-support.js';
|
|
13
13
|
import { registerProjections } from '../utils/projections.js';
|
|
@@ -22,19 +22,19 @@ async function createMapModel(mapId, mapConfig, currentIntl, httpService) {
|
|
|
22
22
|
return await new MapModelFactory(mapId, mapConfig, currentIntl, httpService).createMapModel();
|
|
23
23
|
}
|
|
24
24
|
class MapModelFactory {
|
|
25
|
-
mapId;
|
|
26
|
-
mapConfig;
|
|
27
|
-
currentIntl;
|
|
28
|
-
httpService;
|
|
25
|
+
#mapId;
|
|
26
|
+
#mapConfig;
|
|
27
|
+
#currentIntl;
|
|
28
|
+
#httpService;
|
|
29
29
|
constructor(mapId, mapConfig, currentIntl, httpService) {
|
|
30
|
-
this
|
|
31
|
-
this
|
|
32
|
-
this
|
|
33
|
-
this
|
|
30
|
+
this.#mapId = mapId;
|
|
31
|
+
this.#mapConfig = mapConfig;
|
|
32
|
+
this.#currentIntl = currentIntl;
|
|
33
|
+
this.#httpService = httpService;
|
|
34
34
|
}
|
|
35
35
|
async createMapModel() {
|
|
36
|
-
const mapId = this
|
|
37
|
-
const mapConfig = this
|
|
36
|
+
const mapId = this.#mapId;
|
|
37
|
+
const mapConfig = this.#mapConfig;
|
|
38
38
|
const { view: viewOption, ...rawOlOptions } = mapConfig.advanced ?? {};
|
|
39
39
|
const showDefaultAttributions = mapConfig.showAttributions ?? (rawOlOptions.controls ? false : true);
|
|
40
40
|
const mapOptions = {
|
|
@@ -56,7 +56,7 @@ class MapModelFactory {
|
|
|
56
56
|
}).extend([new DragZoom({ out: true, condition: shiftCtrlKeysOnly })]);
|
|
57
57
|
}
|
|
58
58
|
const view = await viewOption ?? {};
|
|
59
|
-
this
|
|
59
|
+
this.#initializeViewOptions(view);
|
|
60
60
|
mapOptions.view = view instanceof View ? view : new View(view);
|
|
61
61
|
if (!mapOptions.layers && !mapConfig.layers) {
|
|
62
62
|
mapOptions.layers = [
|
|
@@ -78,8 +78,8 @@ class MapModelFactory {
|
|
|
78
78
|
olMap,
|
|
79
79
|
initialExtent,
|
|
80
80
|
showDefaultAttributions,
|
|
81
|
-
currentIntl: this
|
|
82
|
-
httpService: this
|
|
81
|
+
currentIntl: this.#currentIntl,
|
|
82
|
+
httpService: this.#httpService
|
|
83
83
|
},
|
|
84
84
|
INTERNAL_CONSTRUCTOR_TAG
|
|
85
85
|
);
|
|
@@ -97,9 +97,9 @@ class MapModelFactory {
|
|
|
97
97
|
}
|
|
98
98
|
});
|
|
99
99
|
}
|
|
100
|
-
initializeViewOptions(view) {
|
|
101
|
-
const mapId = this
|
|
102
|
-
const mapConfig = this
|
|
100
|
+
#initializeViewOptions(view) {
|
|
101
|
+
const mapId = this.#mapId;
|
|
102
|
+
const mapConfig = this.#mapConfig;
|
|
103
103
|
if (view instanceof View) {
|
|
104
104
|
const warn = (prop) => {
|
|
105
105
|
LOG.warn(
|
|
@@ -115,7 +115,7 @@ Use ViewOptions instead of a View instance.`
|
|
|
115
115
|
}
|
|
116
116
|
return;
|
|
117
117
|
}
|
|
118
|
-
const projection = view.projection = this
|
|
118
|
+
const projection = view.projection = this.#initializeProjection(mapConfig.projection);
|
|
119
119
|
const initialView = mapConfig.initialView;
|
|
120
120
|
if (initialView) {
|
|
121
121
|
switch (initialView.kind) {
|
|
@@ -134,10 +134,10 @@ Use ViewOptions instead of a View instance.`
|
|
|
134
134
|
}
|
|
135
135
|
}
|
|
136
136
|
} else {
|
|
137
|
-
this
|
|
137
|
+
this.#setViewDefaults(view, projection);
|
|
138
138
|
}
|
|
139
139
|
}
|
|
140
|
-
setViewDefaults(view, projection) {
|
|
140
|
+
#setViewDefaults(view, projection) {
|
|
141
141
|
if (view.center == null) {
|
|
142
142
|
const extent = projection.getExtent();
|
|
143
143
|
if (!extent) {
|
|
@@ -153,7 +153,7 @@ Try to configure 'initialView' explicity.`
|
|
|
153
153
|
view.zoom = 0;
|
|
154
154
|
}
|
|
155
155
|
}
|
|
156
|
-
initializeProjection(projectionOption) {
|
|
156
|
+
#initializeProjection(projectionOption) {
|
|
157
157
|
if (projectionOption == null) {
|
|
158
158
|
return get("EPSG:3857");
|
|
159
159
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"createMapModel.js","sources":["createMapModel.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2023-2025 Open Pioneer project (https://github.com/open-pioneer)\n// SPDX-License-Identifier: Apache-2.0\nimport { batch, ReadonlyReactive } from \"@conterra/reactivity-core\";\nimport { createLogger } from \"@open-pioneer/core\";\nimport { HttpService } from \"@open-pioneer/http\";\nimport { PackageIntl } from \"@open-pioneer/runtime\";\nimport { MapBrowserEvent } from \"ol\";\nimport OlMap, { MapOptions } from \"ol/Map\";\nimport View, { ViewOptions } from \"ol/View\";\nimport { getCenter } from \"ol/extent\";\nimport { DragZoom, defaults as defaultInteractions } from \"ol/interaction\";\nimport TileLayer from \"ol/layer/Tile\";\nimport { Projection, get as getProjection } from \"ol/proj\";\nimport OSM from \"ol/source/OSM\";\nimport { sourceId } from \"open-pioneer:source-info\";\nimport { INTERNAL_CONSTRUCTOR_TAG } from \"../utils/InternalConstructorTag\";\nimport { patchOpenLayersClassesForTesting } from \"../utils/ol-test-support\";\nimport { registerProjections } from \"../utils/projections\";\nimport { MapConfig } from \"./MapConfig\";\nimport { MapModel } from \"./MapModel\";\n\n/**\n * Register custom projection to the global proj4js definitions. User can select `EPSG:25832`\n * and `EPSG:25833` from the predefined projections without calling `registerProjections`.\n */\nregisterProjections({\n \"EPSG:25832\":\n \"+proj=utm +zone=32 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs +type=crs\",\n \"EPSG:25833\":\n \"+proj=utm +zone=33 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs +type=crs\"\n});\nconst LOG = createLogger(sourceId);\n\nexport async function createMapModel(\n mapId: string,\n mapConfig: MapConfig,\n currentIntl: ReadonlyReactive<PackageIntl>,\n httpService: HttpService\n): Promise<MapModel> {\n return await new MapModelFactory(mapId, mapConfig, currentIntl, httpService).createMapModel();\n}\n\nclass MapModelFactory {\n private mapId: string;\n private mapConfig: MapConfig;\n private currentIntl: ReadonlyReactive<PackageIntl>;\n private httpService: HttpService;\n\n constructor(\n mapId: string,\n mapConfig: MapConfig,\n currentIntl: ReadonlyReactive<PackageIntl>,\n httpService: HttpService\n ) {\n this.mapId = mapId;\n this.mapConfig = mapConfig;\n this.currentIntl = currentIntl;\n this.httpService = httpService;\n }\n\n async createMapModel() {\n const mapId = this.mapId;\n const mapConfig = this.mapConfig;\n const { view: viewOption, ...rawOlOptions } = mapConfig.advanced ?? {};\n const showDefaultAttributions =\n mapConfig.showAttributions ?? (rawOlOptions.controls ? false : true);\n\n const mapOptions: MapOptions = {\n ...rawOlOptions\n };\n if (!mapOptions.controls) {\n mapOptions.controls = [];\n }\n if (!mapOptions.interactions) {\n const shiftCtrlKeysOnly = (\n mapBrowserEvent: MapBrowserEvent<KeyboardEvent | WheelEvent | PointerEvent>\n ) => {\n const originalEvent = mapBrowserEvent.originalEvent;\n return (originalEvent.metaKey || originalEvent.ctrlKey) && originalEvent.shiftKey;\n };\n\n // setting altShiftDragRotate to false disables or excludes DragRotate interaction\n mapOptions.interactions = defaultInteractions({\n dragPan: true,\n altShiftDragRotate: false,\n pinchRotate: false,\n mouseWheelZoom: true\n }).extend([new DragZoom({ out: true, condition: shiftCtrlKeysOnly })]);\n }\n\n const view = (await viewOption) ?? {};\n this.initializeViewOptions(view);\n mapOptions.view = view instanceof View ? view : new View(view);\n\n if (!mapOptions.layers && !mapConfig.layers) {\n mapOptions.layers = [\n new TileLayer({\n source: new OSM()\n })\n ];\n }\n\n const initialView = mapConfig.initialView;\n const initialExtent = initialView?.kind === \"extent\" ? initialView.extent : undefined;\n\n LOG.debug(`Constructing OpenLayers map with options`, mapOptions);\n\n if (import.meta.env.VITEST) {\n patchOpenLayersClassesForTesting();\n }\n\n const olMap = new OlMap(mapOptions);\n const mapModel = new MapModel(\n {\n id: mapId,\n olMap,\n initialExtent,\n showDefaultAttributions,\n currentIntl: this.currentIntl,\n httpService: this.httpService\n },\n INTERNAL_CONSTRUCTOR_TAG\n );\n\n return batch(() => {\n try {\n if (mapConfig.layers) {\n for (const layerConfig of mapConfig.layers) {\n mapModel.layers.addLayer(layerConfig);\n }\n }\n return mapModel;\n } catch (e) {\n mapModel.destroy();\n throw e;\n }\n });\n }\n\n private initializeViewOptions(view: View | ViewOptions) {\n const mapId = this.mapId;\n const mapConfig = this.mapConfig;\n if (view instanceof View) {\n const warn = (prop: string) => {\n LOG.warn(\n `The advanced configuration for map id '${mapId}' has provided a fully constructed view instance: ${prop} cannot be applied.\\n` +\n `Use ViewOptions instead of a View instance.`\n );\n };\n\n if (mapConfig.projection != null) {\n warn(\"projection\");\n }\n if (mapConfig.initialView != null) {\n warn(\"initialView\");\n }\n return;\n }\n\n const projection = (view.projection = this.initializeProjection(mapConfig.projection));\n const initialView = mapConfig.initialView;\n if (initialView) {\n switch (initialView.kind) {\n case \"position\":\n view.zoom = initialView.zoom;\n view.center = [initialView.center.x, initialView.center.y];\n break;\n case \"extent\": {\n /*\n OpenLayers does not support configuration of the initial map extent.\n The only relevant options here are center, zoom (and resolution).\n We must set those values because otherwise OpenLayers will not initialize layer sources.\n\n The actual initial extent is applied once tha map has loaded and its size is known.\n */\n const extent = initialView.extent;\n view.zoom = 0;\n view.center = [\n extent.xMin + (extent.xMax - extent.xMin) / 2,\n extent.yMin + (extent.yMax - extent.yMin) / 2\n ];\n break;\n }\n }\n } else {\n this.setViewDefaults(view, projection);\n }\n }\n\n private setViewDefaults(view: ViewOptions, projection: Projection) {\n if (view.center == null) {\n const extent = projection.getExtent(); // can be null\n if (!extent) {\n LOG.warn(\n `Cannot set default center coordinate because the current projection has no associated extent.\\n` +\n `Try to configure 'initialView' explicity.`\n );\n } else {\n view.center = getCenter(extent);\n }\n }\n\n if (view.zoom == null || view.resolution == null) {\n view.zoom = 0;\n }\n }\n\n private initializeProjection(projectionOption: MapConfig[\"projection\"]) {\n if (projectionOption == null) {\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n return getProjection(\"EPSG:3857\")!; // default OpenLayers projection\n }\n\n const projection = getProjection(projectionOption);\n if (!projection) {\n throw new Error(`Failed to retrieve projection for code '${projectionOption}'.`);\n }\n return projection;\n }\n}\n"],"names":["defaultInteractions","getProjection"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"createMapModel.js","sources":["createMapModel.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2023-2025 Open Pioneer project (https://github.com/open-pioneer)\n// SPDX-License-Identifier: Apache-2.0\n\nimport { batch, ReadonlyReactive } from \"@conterra/reactivity-core\";\nimport { createLogger } from \"@open-pioneer/core\";\nimport { HttpService } from \"@open-pioneer/http\";\nimport { PackageIntl } from \"@open-pioneer/runtime\";\nimport { MapBrowserEvent } from \"ol\";\nimport { getCenter } from \"ol/extent\";\nimport { DragZoom, defaults as defaultInteractions } from \"ol/interaction\";\nimport TileLayer from \"ol/layer/Tile\";\nimport OlMap, { MapOptions } from \"ol/Map\";\nimport { Projection, get as getProjection } from \"ol/proj\";\nimport OSM from \"ol/source/OSM\";\nimport View, { ViewOptions } from \"ol/View\";\nimport { sourceId } from \"open-pioneer:source-info\";\nimport { INTERNAL_CONSTRUCTOR_TAG } from \"../utils/InternalConstructorTag\";\nimport { patchOpenLayersClassesForTesting } from \"../utils/ol-test-support\";\nimport { registerProjections } from \"../utils/projections\";\nimport { MapConfig } from \"./MapConfig\";\nimport { MapModel } from \"./MapModel\";\n\n/**\n * Register custom projection to the global proj4js definitions. User can select `EPSG:25832`\n * and `EPSG:25833` from the predefined projections without calling `registerProjections`.\n */\nregisterProjections({\n \"EPSG:25832\":\n \"+proj=utm +zone=32 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs +type=crs\",\n \"EPSG:25833\":\n \"+proj=utm +zone=33 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs +type=crs\"\n});\nconst LOG = createLogger(sourceId);\n\nexport async function createMapModel(\n mapId: string,\n mapConfig: MapConfig,\n currentIntl: ReadonlyReactive<PackageIntl>,\n httpService: HttpService\n): Promise<MapModel> {\n return await new MapModelFactory(mapId, mapConfig, currentIntl, httpService).createMapModel();\n}\n\nclass MapModelFactory {\n #mapId: string;\n #mapConfig: MapConfig;\n #currentIntl: ReadonlyReactive<PackageIntl>;\n #httpService: HttpService;\n\n constructor(\n mapId: string,\n mapConfig: MapConfig,\n currentIntl: ReadonlyReactive<PackageIntl>,\n httpService: HttpService\n ) {\n this.#mapId = mapId;\n this.#mapConfig = mapConfig;\n this.#currentIntl = currentIntl;\n this.#httpService = httpService;\n }\n\n async createMapModel() {\n const mapId = this.#mapId;\n const mapConfig = this.#mapConfig;\n const { view: viewOption, ...rawOlOptions } = mapConfig.advanced ?? {};\n const showDefaultAttributions =\n mapConfig.showAttributions ?? (rawOlOptions.controls ? false : true);\n\n const mapOptions: MapOptions = {\n ...rawOlOptions\n };\n if (!mapOptions.controls) {\n mapOptions.controls = [];\n }\n if (!mapOptions.interactions) {\n const shiftCtrlKeysOnly = (\n mapBrowserEvent: MapBrowserEvent<KeyboardEvent | WheelEvent | PointerEvent>\n ) => {\n const originalEvent = mapBrowserEvent.originalEvent;\n return (originalEvent.metaKey || originalEvent.ctrlKey) && originalEvent.shiftKey;\n };\n\n // setting altShiftDragRotate to false disables or excludes DragRotate interaction\n mapOptions.interactions = defaultInteractions({\n dragPan: true,\n altShiftDragRotate: false,\n pinchRotate: false,\n mouseWheelZoom: true\n }).extend([new DragZoom({ out: true, condition: shiftCtrlKeysOnly })]);\n }\n\n const view = (await viewOption) ?? {};\n this.#initializeViewOptions(view);\n mapOptions.view = view instanceof View ? view : new View(view);\n\n if (!mapOptions.layers && !mapConfig.layers) {\n mapOptions.layers = [\n new TileLayer({\n source: new OSM()\n })\n ];\n }\n\n const initialView = mapConfig.initialView;\n const initialExtent = initialView?.kind === \"extent\" ? initialView.extent : undefined;\n\n LOG.debug(`Constructing OpenLayers map with options`, mapOptions);\n\n if (import.meta.env.VITEST) {\n patchOpenLayersClassesForTesting();\n }\n\n const olMap = new OlMap(mapOptions);\n const mapModel = new MapModel(\n {\n id: mapId,\n olMap,\n initialExtent,\n showDefaultAttributions,\n currentIntl: this.#currentIntl,\n httpService: this.#httpService\n },\n INTERNAL_CONSTRUCTOR_TAG\n );\n\n return batch(() => {\n try {\n if (mapConfig.layers) {\n for (const layerConfig of mapConfig.layers) {\n mapModel.layers.addLayer(layerConfig);\n }\n }\n return mapModel;\n } catch (e) {\n mapModel.destroy();\n throw e;\n }\n });\n }\n\n #initializeViewOptions(view: View | ViewOptions) {\n const mapId = this.#mapId;\n const mapConfig = this.#mapConfig;\n if (view instanceof View) {\n const warn = (prop: string) => {\n LOG.warn(\n `The advanced configuration for map id '${mapId}' has provided a fully constructed view instance: ${prop} cannot be applied.\\n` +\n `Use ViewOptions instead of a View instance.`\n );\n };\n\n if (mapConfig.projection != null) {\n warn(\"projection\");\n }\n if (mapConfig.initialView != null) {\n warn(\"initialView\");\n }\n return;\n }\n\n const projection = (view.projection = this.#initializeProjection(mapConfig.projection));\n const initialView = mapConfig.initialView;\n if (initialView) {\n switch (initialView.kind) {\n case \"position\":\n view.zoom = initialView.zoom;\n view.center = [initialView.center.x, initialView.center.y];\n break;\n case \"extent\": {\n /*\n OpenLayers does not support configuration of the initial map extent.\n The only relevant options here are center, zoom (and resolution).\n We must set those values because otherwise OpenLayers will not initialize layer sources.\n\n The actual initial extent is applied once tha map has loaded and its size is known.\n */\n const extent = initialView.extent;\n view.zoom = 0;\n view.center = [\n extent.xMin + (extent.xMax - extent.xMin) / 2,\n extent.yMin + (extent.yMax - extent.yMin) / 2\n ];\n break;\n }\n }\n } else {\n this.#setViewDefaults(view, projection);\n }\n }\n\n #setViewDefaults(view: ViewOptions, projection: Projection) {\n if (view.center == null) {\n const extent = projection.getExtent(); // can be null\n if (!extent) {\n LOG.warn(\n `Cannot set default center coordinate because the current projection has no associated extent.\\n` +\n `Try to configure 'initialView' explicity.`\n );\n } else {\n view.center = getCenter(extent);\n }\n }\n\n if (view.zoom == null || view.resolution == null) {\n view.zoom = 0;\n }\n }\n\n #initializeProjection(projectionOption: MapConfig[\"projection\"]) {\n if (projectionOption == null) {\n // oxlint-disable-next-line @typescript-eslint/no-non-null-assertion\n return getProjection(\"EPSG:3857\")!; // default OpenLayers projection\n }\n\n const projection = getProjection(projectionOption);\n if (!projection) {\n throw new Error(`Failed to retrieve projection for code '${projectionOption}'.`);\n }\n return projection;\n }\n}\n"],"names":["defaultInteractions","getProjection"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"getGeometries.js","sources":["getGeometries.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2023-2025 Open Pioneer project (https://github.com/open-pioneer)\n// SPDX-License-Identifier: Apache-2.0\nimport { Geometry } from \"ol/geom\";\nimport { DisplayTarget } from \"./MapModel\";\n\nexport function getGeometries(geoObjects: DisplayTarget[]): Geometry[] {\n const geometries: Geometry[] = [];\n geoObjects.forEach((item) => {\n if (\"getType\" in item) geometries.push(item);\n if (\"geometry\" in item && item.geometry) geometries.push(item.geometry);\n });\n return geometries;\n}\n"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"getGeometries.js","sources":["getGeometries.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2023-2025 Open Pioneer project (https://github.com/open-pioneer)\n// SPDX-License-Identifier: Apache-2.0\n\nimport { Geometry } from \"ol/geom\";\nimport { DisplayTarget } from \"./MapModel\";\n\nexport function getGeometries(geoObjects: DisplayTarget[]): Geometry[] {\n const geometries: Geometry[] = [];\n geoObjects.forEach((item) => {\n if (\"getType\" in item) geometries.push(item);\n if (\"geometry\" in item && item.geometry) geometries.push(item.geometry);\n });\n return geometries;\n}\n"],"names":[],"mappings":"AAMO,SAAS,cAAc,UAAA,EAAyC;AACnE,EAAA,MAAM,aAAyB,EAAC;AAChC,EAAA,UAAA,CAAW,OAAA,CAAQ,CAAC,IAAA,KAAS;AACzB,IAAA,IAAI,SAAA,IAAa,IAAA,EAAM,UAAA,CAAW,IAAA,CAAK,IAAI,CAAA;AAC3C,IAAA,IAAI,cAAc,IAAA,IAAQ,IAAA,CAAK,UAAU,UAAA,CAAW,IAAA,CAAK,KAAK,QAAQ,CAAA;AAAA,EAC1E,CAAC,CAAA;AACD,EAAA,OAAO,UAAA;AACX;;;;"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"type": "module",
|
|
3
3
|
"name": "@open-pioneer/map",
|
|
4
|
-
"version": "1.4.0
|
|
4
|
+
"version": "1.4.0",
|
|
5
5
|
"description": "This package integrates OpenLayers maps into an open pioneer trails application.",
|
|
6
6
|
"keywords": [
|
|
7
7
|
"open-pioneer-trails"
|
|
@@ -14,21 +14,21 @@
|
|
|
14
14
|
"directory": "src/packages/map"
|
|
15
15
|
},
|
|
16
16
|
"dependencies": {
|
|
17
|
-
"@chakra-ui/react": "^3.36.
|
|
17
|
+
"@chakra-ui/react": "^3.36.1",
|
|
18
18
|
"@conterra/reactivity-core": "^0.8.6",
|
|
19
19
|
"@conterra/reactivity-events": "^0.8.6",
|
|
20
20
|
"@esri/arcgis-html-sanitizer": "^4.1.0",
|
|
21
|
-
"@open-pioneer/core": "4.7.0
|
|
22
|
-
"@open-pioneer/http": "4.7.0
|
|
23
|
-
"@open-pioneer/react-utils": "4.7.0
|
|
24
|
-
"@open-pioneer/reactivity": "4.7.0
|
|
25
|
-
"@open-pioneer/runtime": "4.7.0
|
|
21
|
+
"@open-pioneer/core": "^4.7.0",
|
|
22
|
+
"@open-pioneer/http": "^4.7.0",
|
|
23
|
+
"@open-pioneer/react-utils": "^4.7.0",
|
|
24
|
+
"@open-pioneer/reactivity": "^4.7.0",
|
|
25
|
+
"@open-pioneer/runtime": "^4.7.0",
|
|
26
26
|
"ol": "^10.9.0",
|
|
27
27
|
"proj4": "^2.20.9",
|
|
28
|
-
"react
|
|
28
|
+
"react": "^19.2.8",
|
|
29
|
+
"react-dom": "^19.2.8",
|
|
29
30
|
"react-use": "^17.6.1",
|
|
30
|
-
"
|
|
31
|
-
"uuid": "^14.0.0"
|
|
31
|
+
"uuid": "^14.0.1"
|
|
32
32
|
},
|
|
33
33
|
"exports": {
|
|
34
34
|
"./package.json": "./package.json",
|
|
@@ -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 } from \"react\";\nimport { MapModel } from \"../model/MapModel\";\nimport { MapModelProps } from \"./hooks/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 *\n * @group UI Components and Hooks\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":";;;
|
|
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\n\nimport { createContext, useContext } from \"react\";\nimport { MapModel } from \"../model/MapModel\";\nimport { MapModelProps } from \"./hooks/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 *\n * @group UI Components and Hooks\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":";;;AAOA,MAAM,iBAAA,GAAoB,cAAoC,MAAS,CAAA;AACvE,iBAAA,CAAkB,WAAA,GAAc,mBAAA;AAmBzB,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, BoxProps } from \"@chakra-ui/react\";\nimport {\n CommonComponentProps,\n mergeChakraProps,\n useCommonComponentProps\n} 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 *\n * @group UI Components and Hooks\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\n/**\n * @group UI Components and Hooks\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 *\n * @group UI Components and Hooks\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 css = useMemo(\n () => computeMapAnchorStyles(position, horizontalGap, verticalGap),\n [position, horizontalGap, verticalGap]\n );\n\n const boxProps = mergeChakraProps<BoxProps>(\n {\n css\n },\n containerProps\n );\n return createPortal(<Box {...boxProps}>{children}</Box>, mapAnchorsHost);\n}\n"],"names":[],"mappings":";;;;;;;;
|
|
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\n\nimport { Box, BoxProps } from \"@chakra-ui/react\";\nimport {\n CommonComponentProps,\n mergeChakraProps,\n useCommonComponentProps\n} 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 *\n * @group UI Components and Hooks\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\n/**\n * @group UI Components and Hooks\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 *\n * @group UI Components and Hooks\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 css = useMemo(\n () => computeMapAnchorStyles(position, horizontalGap, verticalGap),\n [position, horizontalGap, verticalGap]\n );\n\n const boxProps = mergeChakraProps<BoxProps>(\n {\n css\n },\n containerProps\n );\n return createPortal(<Box {...boxProps}>{children}</Box>, mapAnchorsHost);\n}\n"],"names":[],"mappings":";;;;;;;;AAiCA,MAAM,eAAA,GAAqC,WAAA;AA4CpC,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,GAAA,GAAM,OAAA;AAAA,IACR,MAAM,sBAAA,CAAuB,QAAA,EAAU,aAAA,EAAe,WAAW,CAAA;AAAA,IACjE,CAAC,QAAA,EAAU,aAAA,EAAe,WAAW;AAAA,GACzC;AAEA,EAAA,MAAM,QAAA,GAAW,gBAAA;AAAA,IACb;AAAA,MACI;AAAA,KACJ;AAAA,IACA;AAAA,GACJ;AACA,EAAA,OAAO,6BAAa,GAAA,CAAC,GAAA,EAAA,EAAK,GAAG,QAAA,EAAW,QAAA,EAAS,GAAQ,cAAc,CAAA;AAC3E;;;;"}
|
package/ui/MapContainer.js
CHANGED
|
@@ -3,11 +3,11 @@ import { chakra } from '@chakra-ui/react';
|
|
|
3
3
|
import { createLogger } from '@open-pioneer/core';
|
|
4
4
|
import { useCommonComponentProps, mergeChakraProps } from '@open-pioneer/react-utils';
|
|
5
5
|
import { useReactiveSnapshot } from '@open-pioneer/reactivity';
|
|
6
|
-
import { sourceId$
|
|
6
|
+
import { sourceId$5 as sourceId } from '../_virtual/source-info.js';
|
|
7
7
|
import { useRef, useState, useEffect, useMemo } from 'react';
|
|
8
8
|
import { DISPLAY_STATUS } from '../model/MapModel.js';
|
|
9
|
-
import { MapContainerContextProvider } from './MapContainerContext.js';
|
|
10
9
|
import { useMapModelValue } from './hooks/useMapModel.js';
|
|
10
|
+
import { MapContainerContextProvider } from './MapContainerContext.js';
|
|
11
11
|
import { OverlaysRenderer } from './OverlaysRenderer.js';
|
|
12
12
|
|
|
13
13
|
const LOG = createLogger(sourceId);
|