@open-pioneer/map 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +12 -0
- package/LICENSE +202 -0
- package/MapRegistryImpl.d.ts +15 -0
- package/MapRegistryImpl.js +89 -0
- package/MapRegistryImpl.js.map +1 -0
- package/README.md +653 -0
- package/_virtual/_virtual-pioneer-module_react-hooks.js +7 -0
- package/_virtual/_virtual-pioneer-module_react-hooks.js.map +1 -0
- package/api/MapConfig.d.ts +111 -0
- package/api/MapModel.d.ts +112 -0
- package/api/MapRegistry.d.ts +54 -0
- package/api/index.d.ts +12 -0
- package/api/layers/SimpleLayer.d.ts +24 -0
- package/api/layers/SimpleLayer.js +6 -0
- package/api/layers/SimpleLayer.js.map +1 -0
- package/api/layers/WMSLayer.d.ts +42 -0
- package/api/layers/WMSLayer.js +6 -0
- package/api/layers/WMSLayer.js.map +1 -0
- package/api/layers/base.d.ts +170 -0
- package/api/layers/index.d.ts +3 -0
- package/api/shared.d.ts +10 -0
- package/index.d.ts +1 -0
- package/index.js +11 -0
- package/index.js.map +1 -0
- package/layers/BkgTopPlusOpen.d.ts +21 -0
- package/layers/BkgTopPlusOpen.js +61 -0
- package/layers/BkgTopPlusOpen.js.map +1 -0
- package/model/AbstractLayer.d.ts +24 -0
- package/model/AbstractLayer.js +133 -0
- package/model/AbstractLayer.js.map +1 -0
- package/model/AbstractLayerBase.d.ts +37 -0
- package/model/AbstractLayerBase.js +106 -0
- package/model/AbstractLayerBase.js.map +1 -0
- package/model/LayerCollectionImpl.d.ts +27 -0
- package/model/LayerCollectionImpl.js +226 -0
- package/model/LayerCollectionImpl.js.map +1 -0
- package/model/MapModelImpl.d.ts +19 -0
- package/model/MapModelImpl.js +179 -0
- package/model/MapModelImpl.js.map +1 -0
- package/model/SublayersCollectionImpl.d.ts +15 -0
- package/model/SublayersCollectionImpl.js +29 -0
- package/model/SublayersCollectionImpl.js.map +1 -0
- package/model/createMapModel.d.ts +3 -0
- package/model/createMapModel.js +154 -0
- package/model/createMapModel.js.map +1 -0
- package/model/layers/SimpleLayerImpl.d.ts +9 -0
- package/model/layers/SimpleLayerImpl.js +10 -0
- package/model/layers/SimpleLayerImpl.js.map +1 -0
- package/model/layers/WMSLayerImpl.d.ts +29 -0
- package/model/layers/WMSLayerImpl.js +177 -0
- package/model/layers/WMSLayerImpl.js.map +1 -0
- package/package.json +67 -0
- package/projections.d.ts +27 -0
- package/projections.js +15 -0
- package/projections.js.map +1 -0
- package/services.d.ts +1 -0
- package/services.js +2 -0
- package/services.js.map +1 -0
- package/ui/MapAnchor.d.ts +49 -0
- package/ui/MapAnchor.js +91 -0
- package/ui/MapAnchor.js.map +1 -0
- package/ui/MapContainer.d.ts +60 -0
- package/ui/MapContainer.js +192 -0
- package/ui/MapContainer.js.map +1 -0
- package/ui/MapContext.d.ts +11 -0
- package/ui/MapContext.js +17 -0
- package/ui/MapContext.js.map +1 -0
- package/ui/hooks.d.ts +24 -0
- package/ui/hooks.js +73 -0
- package/ui/hooks.js.map +1 -0
- package/ui/styles.css +3 -0
- package/ui/styles.css.map +1 -0
- package/ui/useMapModel.d.ts +31 -0
- package/ui/useMapModel.js +21 -0
- package/ui/useMapModel.js.map +1 -0
- package/util/defer.d.ts +18 -0
- package/util/defer.js +21 -0
- package/util/defer.js.map +1 -0
- package/util/ol-test-support.d.ts +2 -0
- package/util/ol-test-support.js +24 -0
- package/util/ol-test-support.js.map +1 -0
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
import { jsx } from 'react/jsx-runtime';
|
|
2
|
+
import { createLogger } from '@open-pioneer/core';
|
|
3
|
+
import { useCommonComponentProps } from '@open-pioneer/react-utils';
|
|
4
|
+
import { useRef, useEffect, useMemo } from 'react';
|
|
5
|
+
import { useMapModel } from './useMapModel.js';
|
|
6
|
+
import { MapContextProvider } from './MapContext.js';
|
|
7
|
+
|
|
8
|
+
const LOG = createLogger("map:MapContainer");
|
|
9
|
+
function MapContainer(props) {
|
|
10
|
+
const {
|
|
11
|
+
mapId,
|
|
12
|
+
viewPadding,
|
|
13
|
+
viewPaddingChangeBehavior,
|
|
14
|
+
children,
|
|
15
|
+
role,
|
|
16
|
+
"aria-label": ariaLabel,
|
|
17
|
+
"aria-labelledby": ariaLabelledBy
|
|
18
|
+
} = props;
|
|
19
|
+
const { containerProps } = useCommonComponentProps("map-container", props);
|
|
20
|
+
const mapElement = useRef(null);
|
|
21
|
+
const modelState = useMapModel(mapId);
|
|
22
|
+
const mapModel = modelState.map;
|
|
23
|
+
useEffect(() => {
|
|
24
|
+
if (modelState.kind === "loading") {
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
if (modelState.kind === "rejected") {
|
|
28
|
+
LOG.error(`Cannot display the map. Caused by `, modelState.error);
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
if (!mapModel) {
|
|
32
|
+
LOG.error(`No configuration available for map with id '${mapId}'.`);
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
if (mapElement.current) {
|
|
36
|
+
const resource = registerMapTarget(mapModel, mapElement.current);
|
|
37
|
+
return () => resource?.destroy();
|
|
38
|
+
}
|
|
39
|
+
}, [modelState, mapModel, mapId]);
|
|
40
|
+
useEffect(() => {
|
|
41
|
+
const mapView = mapModel?.olMap.getView();
|
|
42
|
+
if (viewPadding && mapView) {
|
|
43
|
+
const center = mapView.getCenter();
|
|
44
|
+
const { top = 0, right = 0, bottom = 0, left = 0 } = viewPadding;
|
|
45
|
+
mapView.padding = [top, right, bottom, left];
|
|
46
|
+
mapView.animate({ center, duration: 300 });
|
|
47
|
+
}
|
|
48
|
+
}, [viewPadding, mapModel]);
|
|
49
|
+
const mapContainerStyle = {
|
|
50
|
+
height: "100%"
|
|
51
|
+
};
|
|
52
|
+
return /* @__PURE__ */ jsx(
|
|
53
|
+
"div",
|
|
54
|
+
{
|
|
55
|
+
...containerProps,
|
|
56
|
+
role,
|
|
57
|
+
"aria-label": ariaLabel,
|
|
58
|
+
"aria-labelledby": ariaLabelledBy,
|
|
59
|
+
ref: mapElement,
|
|
60
|
+
style: mapContainerStyle,
|
|
61
|
+
tabIndex: 0,
|
|
62
|
+
children: mapModel && /* @__PURE__ */ jsx(
|
|
63
|
+
MapContainerReady,
|
|
64
|
+
{
|
|
65
|
+
map: mapModel.olMap,
|
|
66
|
+
viewPadding,
|
|
67
|
+
viewPaddingChangeBehavior,
|
|
68
|
+
children
|
|
69
|
+
}
|
|
70
|
+
)
|
|
71
|
+
}
|
|
72
|
+
);
|
|
73
|
+
}
|
|
74
|
+
function registerMapTarget(mapModel, target) {
|
|
75
|
+
const mapId = mapModel.id;
|
|
76
|
+
const olMap = mapModel.olMap;
|
|
77
|
+
if (olMap.getTarget()) {
|
|
78
|
+
LOG.error(
|
|
79
|
+
`Failed to display the map: the map already has a target. There may be more than one <MapContainer />.`
|
|
80
|
+
);
|
|
81
|
+
return void 0;
|
|
82
|
+
}
|
|
83
|
+
LOG.isDebug() && LOG.debug(`Setting target of map '${mapId}':`, target);
|
|
84
|
+
olMap.setTarget(target);
|
|
85
|
+
let unregistered = false;
|
|
86
|
+
return {
|
|
87
|
+
destroy() {
|
|
88
|
+
if (!unregistered) {
|
|
89
|
+
LOG.isDebug() && LOG.debug(`Removing target of map '${mapId}':`, target);
|
|
90
|
+
olMap.setTarget(void 0);
|
|
91
|
+
unregistered = true;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
function MapContainerReady(props) {
|
|
97
|
+
const {
|
|
98
|
+
map,
|
|
99
|
+
viewPadding: viewPaddingProp,
|
|
100
|
+
viewPaddingChangeBehavior = "preserve-center",
|
|
101
|
+
children
|
|
102
|
+
} = props;
|
|
103
|
+
const mapAnchorsHost = useMapAnchorsHost(map);
|
|
104
|
+
const viewPadding = useMemo(() => {
|
|
105
|
+
return {
|
|
106
|
+
left: viewPaddingProp?.left ?? 0,
|
|
107
|
+
right: viewPaddingProp?.right ?? 0,
|
|
108
|
+
top: viewPaddingProp?.top ?? 0,
|
|
109
|
+
bottom: viewPaddingProp?.bottom ?? 0
|
|
110
|
+
};
|
|
111
|
+
}, [viewPaddingProp]);
|
|
112
|
+
useEffect(() => {
|
|
113
|
+
const mapView = map?.getView();
|
|
114
|
+
if (!map || !mapView) {
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
const oldCenter = mapView.getCenter();
|
|
118
|
+
const oldPadding = fromOlPadding(mapView.padding);
|
|
119
|
+
const oldExtent = extentIncludingPadding(map, oldPadding);
|
|
120
|
+
mapView.padding = toOlPadding(viewPadding);
|
|
121
|
+
switch (viewPaddingChangeBehavior) {
|
|
122
|
+
case "preserve-center":
|
|
123
|
+
mapView.animate({ center: oldCenter, duration: 300 });
|
|
124
|
+
break;
|
|
125
|
+
case "preserve-extent": {
|
|
126
|
+
if (oldExtent) {
|
|
127
|
+
mapView.animate({
|
|
128
|
+
center: oldCenter,
|
|
129
|
+
resolution: mapView.getResolutionForExtent(oldExtent),
|
|
130
|
+
duration: 300
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
break;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
}, [viewPadding, map, viewPaddingChangeBehavior]);
|
|
137
|
+
const mapContext = useMemo(() => {
|
|
138
|
+
return {
|
|
139
|
+
map,
|
|
140
|
+
mapAnchorsHost,
|
|
141
|
+
padding: viewPadding
|
|
142
|
+
};
|
|
143
|
+
}, [map, viewPadding, mapAnchorsHost]);
|
|
144
|
+
return /* @__PURE__ */ jsx(MapContextProvider, { value: mapContext, children });
|
|
145
|
+
}
|
|
146
|
+
function useMapAnchorsHost(olMap) {
|
|
147
|
+
const div = useRef();
|
|
148
|
+
if (!div.current) {
|
|
149
|
+
div.current = document.createElement("div");
|
|
150
|
+
div.current.classList.add("map-anchors");
|
|
151
|
+
}
|
|
152
|
+
useEffect(() => {
|
|
153
|
+
const child = div.current;
|
|
154
|
+
const overlayContainer = olMap.getOverlayContainerStopEvent();
|
|
155
|
+
overlayContainer.insertBefore(child, overlayContainer.firstChild);
|
|
156
|
+
return () => child.remove();
|
|
157
|
+
}, [olMap]);
|
|
158
|
+
return div.current;
|
|
159
|
+
}
|
|
160
|
+
function extentIncludingPadding(map, padding) {
|
|
161
|
+
const size = map.getSize();
|
|
162
|
+
if (!size || size.length < 2) {
|
|
163
|
+
return void 0;
|
|
164
|
+
}
|
|
165
|
+
const [width, height] = size;
|
|
166
|
+
const bottomLeft = map.getCoordinateFromPixel([padding.left, padding.bottom]);
|
|
167
|
+
const topRight = map.getCoordinateFromPixel([
|
|
168
|
+
Math.max(0, width - padding.right),
|
|
169
|
+
Math.max(0, height - padding.top)
|
|
170
|
+
]);
|
|
171
|
+
if (!bottomLeft || !topRight) {
|
|
172
|
+
return void 0;
|
|
173
|
+
}
|
|
174
|
+
const [xmin, ymin] = bottomLeft;
|
|
175
|
+
const [xmax, ymax] = topRight;
|
|
176
|
+
return [xmin, ymin, xmax, ymax];
|
|
177
|
+
}
|
|
178
|
+
function fromOlPadding(padding) {
|
|
179
|
+
return {
|
|
180
|
+
top: padding?.[0] ?? 0,
|
|
181
|
+
right: padding?.[1] ?? 0,
|
|
182
|
+
bottom: padding?.[2] ?? 0,
|
|
183
|
+
left: padding?.[3] ?? 0
|
|
184
|
+
};
|
|
185
|
+
}
|
|
186
|
+
function toOlPadding(padding) {
|
|
187
|
+
const { top, right, bottom, left } = padding;
|
|
188
|
+
return [top, right, bottom, left];
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
export { MapContainer };
|
|
192
|
+
//# sourceMappingURL=MapContainer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MapContainer.js","sources":["MapContainer.tsx"],"sourcesContent":["// SPDX-FileCopyrightText: 2023 Open Pioneer project (https://github.com/open-pioneer)\n// SPDX-License-Identifier: Apache-2.0\nimport { Resource, createLogger } from \"@open-pioneer/core\";\nimport { CommonComponentProps, useCommonComponentProps } from \"@open-pioneer/react-utils\";\nimport type OlMap from \"ol/Map\";\nimport { Extent } from \"ol/extent\";\nimport { ReactNode, useEffect, useMemo, useRef } from \"react\";\nimport { useMapModel } from \"./useMapModel\";\nimport { MapModel } from \"../api\";\nimport { MapContextProvider, MapContextType } from \"./MapContext\";\nconst LOG = createLogger(\"map:MapContainer\");\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 */\nexport interface MapPadding {\n left?: number;\n right?: number;\n top?: number;\n bottom?: number;\n}\n\nexport interface MapContainerProps extends CommonComponentProps {\n /** The id of the map to display. */\n mapId: string;\n\n /**\n * Sets the map's padding directly.\n *\n * See: https://openlayers.org/en/latest/apidoc/module-ol_View-View.html#padding)\n */\n viewPadding?: MapPadding | undefined;\n\n /**\n * Behavior performed by the map when the view padding changes.\n *\n * - `none`: Do nothing.\n * - `preserve-center`: Ensures that the center point remains the same by animating the view.\n * - `preserve-extent`: Ensures that the extent remains the same by zooming.\n *\n * @default \"preserve-center\"\n */\n viewPaddingChangeBehavior?: \"none\" | \"preserve-center\" | \"preserve-extent\";\n\n children?: ReactNode;\n\n /**\n * Optional role property.\n *\n * This property is directly applied to the map's container div element.\n */\n role?: string;\n\n /**\n * Optional aria-labelledby property.\n * Do not use together with aria-label.\n *\n * This property is directly applied to the map's container div element.\n */\n \"aria-labelledby\"?: string;\n\n /**\n * Optional aria-label property.\n * Do not use together with aria-label.\n *\n * This property is directly applied to the map's container div element.\n */\n \"aria-label\"?: string;\n}\n\n/**\n * Displays the map with the given id.\n *\n * There can only be at most one MapContainer for every map.\n */\nexport function MapContainer(props: MapContainerProps) {\n const {\n mapId,\n viewPadding,\n viewPaddingChangeBehavior,\n children,\n role,\n \"aria-label\": ariaLabel,\n \"aria-labelledby\": ariaLabelledBy\n } = props;\n const { containerProps } = useCommonComponentProps(\"map-container\", props);\n const mapElement = useRef<HTMLDivElement>(null);\n const modelState = useMapModel(mapId);\n const mapModel = modelState.map;\n\n useEffect(() => {\n if (modelState.kind === \"loading\") {\n return;\n }\n\n if (modelState.kind === \"rejected\") {\n LOG.error(`Cannot display the map. Caused by `, modelState.error);\n return;\n }\n\n if (!mapModel) {\n LOG.error(`No configuration available for map with id '${mapId}'.`);\n return;\n }\n\n // Mount the map into the DOM\n if (mapElement.current) {\n const resource = registerMapTarget(mapModel, mapElement.current);\n return () => resource?.destroy();\n }\n }, [modelState, mapModel, mapId]);\n\n useEffect(() => {\n const mapView = mapModel?.olMap.getView();\n if (viewPadding && mapView) {\n const center = mapView.getCenter();\n const { top = 0, right = 0, bottom = 0, left = 0 } = viewPadding;\n mapView.padding = [top, right, bottom, left];\n mapView.animate({ center, duration: 300 });\n }\n }, [viewPadding, mapModel]);\n\n const mapContainerStyle: React.CSSProperties = {\n height: \"100%\"\n };\n return (\n <div\n {...containerProps}\n role={role}\n aria-label={ariaLabel}\n aria-labelledby={ariaLabelledBy}\n ref={mapElement}\n style={mapContainerStyle}\n //eslint-disable-next-line jsx-a11y/no-noninteractive-tabindex\n tabIndex={0}\n >\n {mapModel && (\n <MapContainerReady\n map={mapModel.olMap}\n viewPadding={viewPadding}\n viewPaddingChangeBehavior={viewPaddingChangeBehavior}\n >\n {children}\n </MapContainerReady>\n )}\n </div>\n );\n}\n\nfunction registerMapTarget(mapModel: MapModel, target: HTMLDivElement): Resource | undefined {\n const mapId = mapModel.id;\n const olMap = mapModel.olMap;\n if (olMap.getTarget()) {\n LOG.error(\n `Failed to display the map: the map already has a target. There may be more than one <MapContainer />.`\n );\n return undefined;\n }\n\n LOG.isDebug() && LOG.debug(`Setting target of map '${mapId}':`, target);\n olMap.setTarget(target);\n\n let unregistered = false;\n return {\n destroy() {\n if (!unregistered) {\n LOG.isDebug() && LOG.debug(`Removing target of map '${mapId}':`, target);\n olMap.setTarget(undefined);\n unregistered = true;\n }\n }\n };\n}\n\n/**\n * This inner component is rendered when the map has been loaded.\n *\n * It provides the map instance and additional properties down the component tree.\n */\nfunction MapContainerReady(\n props: { map: OlMap } & Omit<MapContainerProps, \"mapId\" | \"className\">\n): JSX.Element {\n const {\n map,\n viewPadding: viewPaddingProp,\n viewPaddingChangeBehavior = \"preserve-center\",\n children\n } = props;\n\n const mapAnchorsHost = useMapAnchorsHost(map);\n\n const viewPadding = useMemo<Required<MapPadding>>(() => {\n return {\n left: viewPaddingProp?.left ?? 0,\n right: viewPaddingProp?.right ?? 0,\n top: viewPaddingProp?.top ?? 0,\n bottom: viewPaddingProp?.bottom ?? 0\n };\n }, [viewPaddingProp]);\n\n // Apply view padding\n useEffect(() => {\n const mapView = map?.getView();\n if (!map || !mapView) {\n return;\n }\n\n const oldCenter = mapView.getCenter();\n const oldPadding = fromOlPadding(mapView.padding);\n const oldExtent = extentIncludingPadding(map, oldPadding);\n\n mapView.padding = toOlPadding(viewPadding);\n switch (viewPaddingChangeBehavior) {\n case \"preserve-center\":\n mapView.animate({ center: oldCenter, duration: 300 });\n break;\n case \"preserve-extent\": {\n if (oldExtent) {\n mapView.animate({\n center: oldCenter,\n resolution: mapView.getResolutionForExtent(oldExtent),\n duration: 300\n });\n }\n break;\n }\n case \"none\":\n }\n }, [viewPadding, map, viewPaddingChangeBehavior]);\n\n const mapContext = useMemo((): MapContextType => {\n return {\n map,\n mapAnchorsHost,\n padding: viewPadding\n };\n }, [map, viewPadding, mapAnchorsHost]);\n return <MapContextProvider value={mapContext}>{children}</MapContextProvider>;\n}\n\n/**\n * Creates a div to host the map anchors and mounts it as the first child\n * of the map's overlay container.\n *\n * The purpose of this wrapper div is only to ensure the correct tab order:\n * the map anchors should be focussed before the builtin attribution widget.\n */\nfunction useMapAnchorsHost(olMap: OlMap): HTMLDivElement {\n const div = useRef<HTMLDivElement>();\n if (!div.current) {\n div.current = document.createElement(\"div\");\n div.current.classList.add(\"map-anchors\");\n }\n\n useEffect(() => {\n const child = div.current!;\n const overlayContainer = olMap.getOverlayContainerStopEvent();\n overlayContainer.insertBefore(child, overlayContainer.firstChild);\n return () => child.remove();\n }, [olMap]);\n\n return div.current;\n}\n\n/**\n * Returns the extent visible in the non-padded region of the map.\n */\nfunction extentIncludingPadding(map: OlMap, padding: Required<MapPadding>): Extent | undefined {\n const size = map.getSize();\n if (!size || size.length < 2) {\n return undefined;\n }\n\n const [width, height] = size as [number, number];\n const bottomLeft = map.getCoordinateFromPixel([padding.left, padding.bottom]);\n const topRight = map.getCoordinateFromPixel([\n Math.max(0, width - padding.right),\n Math.max(0, height - padding.top)\n ]);\n if (!bottomLeft || !topRight) {\n return undefined;\n }\n\n const [xmin, ymin] = bottomLeft;\n const [xmax, ymax] = topRight;\n return [xmin, ymin, xmax, ymax] as Extent;\n}\n\nfunction fromOlPadding(padding: number[] | undefined): Required<MapPadding> {\n // top, right, bottom, left\n return {\n top: padding?.[0] ?? 0,\n right: padding?.[1] ?? 0,\n bottom: padding?.[2] ?? 0,\n left: padding?.[3] ?? 0\n };\n}\n\nfunction toOlPadding(padding: Required<MapPadding>): number[] {\n // top, right, bottom, left\n const { top, right, bottom, left } = padding;\n return [top, right, bottom, left];\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { Provider } from "react";
|
|
2
|
+
import { type MapPadding } from "./MapContainer";
|
|
3
|
+
import type OlMap from "ol/Map";
|
|
4
|
+
/** Values provided to children of {@link MapContainer}. */
|
|
5
|
+
export interface MapContextType {
|
|
6
|
+
map: OlMap;
|
|
7
|
+
mapAnchorsHost: HTMLDivElement;
|
|
8
|
+
padding: Required<MapPadding>;
|
|
9
|
+
}
|
|
10
|
+
export declare const MapContextProvider: Provider<MapContextType>;
|
|
11
|
+
export declare function useMapContext(): MapContextType;
|
package/ui/MapContext.js
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { createContext, useContext } from 'react';
|
|
2
|
+
|
|
3
|
+
const MapContext = createContext(void 0);
|
|
4
|
+
MapContext.displayName = "MapContext";
|
|
5
|
+
const MapContextProvider = MapContext.Provider;
|
|
6
|
+
function useMapContext() {
|
|
7
|
+
const contextValue = useContext(MapContext);
|
|
8
|
+
if (!contextValue) {
|
|
9
|
+
throw new Error(
|
|
10
|
+
`Map context is not available. The component must be a child of the <MapContainer /> component.`
|
|
11
|
+
);
|
|
12
|
+
}
|
|
13
|
+
return contextValue;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export { MapContextProvider, useMapContext };
|
|
17
|
+
//# sourceMappingURL=MapContext.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MapContext.js","sources":["MapContext.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2023 Open Pioneer project (https://github.com/open-pioneer)\n// SPDX-License-Identifier: Apache-2.0\nimport { Provider, createContext, useContext } from \"react\";\nimport { type MapPadding } from \"./MapContainer\";\nimport type OlMap from \"ol/Map\";\n\n/** Values provided to children of {@link MapContainer}. */\nexport interface MapContextType {\n map: OlMap;\n mapAnchorsHost: HTMLDivElement;\n padding: Required<MapPadding>;\n}\n\nconst MapContext = createContext<MapContextType | undefined>(undefined);\nMapContext.displayName = \"MapContext\";\n\nexport const MapContextProvider: Provider<MapContextType> =\n MapContext.Provider as Provider<MapContextType>;\n\nexport function useMapContext(): MapContextType {\n const contextValue = useContext(MapContext);\n if (!contextValue) {\n throw new Error(\n `Map context is not available. The component must be a child of the <MapContainer /> component.`\n );\n }\n return contextValue;\n}\n"],"names":[],"mappings":";;AAaA,MAAM,UAAA,GAAa,cAA0C,KAAS,CAAA,CAAA,CAAA;AACtE,UAAA,CAAW,WAAc,GAAA,YAAA,CAAA;AAElB,MAAM,qBACT,UAAW,CAAA,SAAA;AAER,SAAS,aAAgC,GAAA;AAC5C,EAAM,MAAA,YAAA,GAAe,WAAW,UAAU,CAAA,CAAA;AAC1C,EAAA,IAAI,CAAC,YAAc,EAAA;AACf,IAAA,MAAM,IAAI,KAAA;AAAA,MACN,CAAA,8FAAA,CAAA;AAAA,KACJ,CAAA;AAAA,GACJ;AACA,EAAO,OAAA,YAAA,CAAA;AACX;;;;"}
|
package/ui/hooks.d.ts
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import OlMap from "ol/Map";
|
|
2
|
+
import OlView from "ol/View";
|
|
3
|
+
import { Projection } from "ol/proj";
|
|
4
|
+
import { Coordinate } from "ol/coordinate";
|
|
5
|
+
/**
|
|
6
|
+
* Returns the current view of the given map.
|
|
7
|
+
*/
|
|
8
|
+
export declare function useView(map: OlMap | undefined): OlView | undefined;
|
|
9
|
+
/**
|
|
10
|
+
* Returns the current projection of the map.
|
|
11
|
+
*/
|
|
12
|
+
export declare function useProjection(map: OlMap | undefined): Projection | undefined;
|
|
13
|
+
/**
|
|
14
|
+
* Returns the current resolution of the map.
|
|
15
|
+
*/
|
|
16
|
+
export declare function useResolution(map: OlMap | undefined): number | undefined;
|
|
17
|
+
/**
|
|
18
|
+
* Returns the current center coordinates of the map.
|
|
19
|
+
*/
|
|
20
|
+
export declare function useCenter(map: OlMap | undefined): Coordinate | undefined;
|
|
21
|
+
/**
|
|
22
|
+
* Returns the current scale of the map.
|
|
23
|
+
*/
|
|
24
|
+
export declare function useScale(map: OlMap | undefined): number | undefined;
|
package/ui/hooks.js
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { unByKey } from 'ol/Observable';
|
|
2
|
+
import { getPointResolution } from 'ol/proj';
|
|
3
|
+
import { useMemo, useCallback, useSyncExternalStore } from 'react';
|
|
4
|
+
|
|
5
|
+
const DEFAULT_DPI = 25.4 / 0.28;
|
|
6
|
+
const INCHES_PER_METRE = 39.37;
|
|
7
|
+
function useView(map) {
|
|
8
|
+
return useOlProperty(map, getView, watchView);
|
|
9
|
+
}
|
|
10
|
+
function getView(map) {
|
|
11
|
+
return map.getView();
|
|
12
|
+
}
|
|
13
|
+
function watchView(map, cb) {
|
|
14
|
+
return map.on("change:view", cb);
|
|
15
|
+
}
|
|
16
|
+
function useProjection(map) {
|
|
17
|
+
const view = useView(map);
|
|
18
|
+
return view?.getProjection();
|
|
19
|
+
}
|
|
20
|
+
function useResolution(map) {
|
|
21
|
+
const view = useView(map);
|
|
22
|
+
return useOlProperty(view, getResolution, watchResolution);
|
|
23
|
+
}
|
|
24
|
+
function getResolution(view) {
|
|
25
|
+
return view.getResolution();
|
|
26
|
+
}
|
|
27
|
+
function watchResolution(view, cb) {
|
|
28
|
+
return view.on("change:resolution", cb);
|
|
29
|
+
}
|
|
30
|
+
function useCenter(map) {
|
|
31
|
+
const view = useView(map);
|
|
32
|
+
return useOlProperty(view, getCenter, watchCenter);
|
|
33
|
+
}
|
|
34
|
+
function getCenter(view) {
|
|
35
|
+
return view.getCenter();
|
|
36
|
+
}
|
|
37
|
+
function watchCenter(view, cb) {
|
|
38
|
+
return view.on("change:center", cb);
|
|
39
|
+
}
|
|
40
|
+
function useScale(map) {
|
|
41
|
+
const center = useCenter(map);
|
|
42
|
+
const resolution = useResolution(map);
|
|
43
|
+
const projection = useProjection(map);
|
|
44
|
+
const scale = useMemo(() => {
|
|
45
|
+
if (projection == null || resolution == null || center == null) {
|
|
46
|
+
return void 0;
|
|
47
|
+
}
|
|
48
|
+
const pointResolution = getPointResolution(projection, resolution, center);
|
|
49
|
+
const scale2 = Math.round(pointResolution * INCHES_PER_METRE * DEFAULT_DPI);
|
|
50
|
+
return scale2;
|
|
51
|
+
}, [projection, resolution, center]);
|
|
52
|
+
return scale;
|
|
53
|
+
}
|
|
54
|
+
function useOlProperty(object, accessor, watcher) {
|
|
55
|
+
const getSnapshot = useCallback(
|
|
56
|
+
() => object ? accessor(object) : void 0,
|
|
57
|
+
[object, accessor]
|
|
58
|
+
);
|
|
59
|
+
const subscribe = useCallback(
|
|
60
|
+
(cb) => {
|
|
61
|
+
if (!object) {
|
|
62
|
+
return () => void 0;
|
|
63
|
+
}
|
|
64
|
+
const key = watcher(object, cb);
|
|
65
|
+
return () => unByKey(key);
|
|
66
|
+
},
|
|
67
|
+
[object, watcher]
|
|
68
|
+
);
|
|
69
|
+
return useSyncExternalStore(subscribe, getSnapshot);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export { useCenter, useProjection, useResolution, useScale, useView };
|
|
73
|
+
//# sourceMappingURL=hooks.js.map
|
package/ui/hooks.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hooks.js","sources":["hooks.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2023 Open Pioneer project (https://github.com/open-pioneer)\n// SPDX-License-Identifier: Apache-2.0\nimport OlMap from \"ol/Map\";\nimport OlView from \"ol/View\";\nimport { unByKey } from \"ol/Observable\";\nimport { Projection, getPointResolution } from \"ol/proj\";\nimport { Coordinate } from \"ol/coordinate\";\nimport { EventsKey } from \"ol/events\";\nimport { useCallback, useMemo, useSyncExternalStore } from \"react\";\n\n/**\n * From Web Map Server Implementation Specification -> 7.2.4.6.9 Scale denominators\n *\n * For the purposes of this International Standard, the common pixel size is defined to be 0,28 mm × 0,28 mm.\n * Because arbitrary clients can request maps from a server, the true pixel size of the final rendering device is\n * unknown to the server.\n */\nconst DEFAULT_DPI = 25.4 / 0.28;\nconst INCHES_PER_METRE = 39.37;\n\n/**\n * Returns the current view of the given map.\n */\nexport function useView(map: OlMap | undefined): OlView | undefined {\n return useOlProperty(map, getView, watchView);\n}\n\nfunction getView(map: OlMap) {\n return map.getView();\n}\n\nfunction watchView(map: OlMap, cb: Callback) {\n return map.on(\"change:view\", cb);\n}\n\n/**\n * Returns the current projection of the map.\n */\nexport function useProjection(map: OlMap | undefined): Projection | undefined {\n const view = useView(map);\n return view?.getProjection();\n}\n\n/**\n * Returns the current resolution of the map.\n */\nexport function useResolution(map: OlMap | undefined): number | undefined {\n const view = useView(map);\n return useOlProperty(view, getResolution, watchResolution);\n}\n\nfunction getResolution(view: OlView): number | undefined {\n return view.getResolution();\n}\n\nfunction watchResolution(view: OlView, cb: Callback) {\n return view.on(\"change:resolution\", cb);\n}\n\n/**\n * Returns the current center coordinates of the map.\n */\nexport function useCenter(map: OlMap | undefined): Coordinate | undefined {\n const view = useView(map);\n return useOlProperty(view, getCenter, watchCenter);\n}\n\nfunction getCenter(view: OlView): Coordinate | undefined {\n return view.getCenter();\n}\n\nfunction watchCenter(view: OlView, cb: Callback) {\n return view.on(\"change:center\", cb);\n}\n\n/**\n * Returns the current scale of the map.\n */\nexport function useScale(map: OlMap | undefined): number | undefined {\n const center = useCenter(map);\n const resolution = useResolution(map);\n const projection = useProjection(map);\n const scale = useMemo(() => {\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);\n const scale = Math.round(pointResolution * INCHES_PER_METRE * DEFAULT_DPI);\n return scale;\n }, [projection, resolution, center]);\n return scale;\n}\n\ntype Callback = () => void;\n\n/**\n * Returns the value of an observable ol property.\n *\n * Make sure to keep `accessor` and `watcher` stable to reduce re-subscriptions:\n * either use global functions or wrap the functions into `useCallback`.\n */\nfunction useOlProperty<T, R>(\n object: T | undefined,\n accessor: (object: T) => R,\n watcher: (object: T, cb: Callback) => EventsKey\n): R | undefined {\n const getSnapshot = useCallback(\n () => (object ? accessor(object) : undefined),\n [object, accessor]\n );\n const subscribe = useCallback(\n (cb: Callback) => {\n if (!object) {\n return () => undefined;\n }\n\n const key = watcher(object, cb);\n return () => unByKey(key);\n },\n [object, watcher]\n );\n return useSyncExternalStore(subscribe, getSnapshot);\n}\n"],"names":["scale"],"mappings":"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"}
|
package/ui/styles.css
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["styles.css"],"names":[],"mappings":"AAAA,mBAAmB","file":"styles.css","sourcesContent":["@import \"ol/ol.css\";\n"]}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { MapModel } from "../api";
|
|
2
|
+
/** Return value of {@link useMapModel}. */
|
|
3
|
+
export type UseMapModelResult = {
|
|
4
|
+
kind: "loading" | "resolved" | "rejected";
|
|
5
|
+
map?: MapModel | undefined;
|
|
6
|
+
error?: Error | undefined;
|
|
7
|
+
} | UseMapModelLoading | UseMapModelResolved | UseMapModelRejected;
|
|
8
|
+
export interface UseMapModelLoading {
|
|
9
|
+
kind: "loading";
|
|
10
|
+
map?: undefined;
|
|
11
|
+
error?: undefined;
|
|
12
|
+
}
|
|
13
|
+
export interface UseMapModelResolved {
|
|
14
|
+
kind: "resolved";
|
|
15
|
+
map: MapModel;
|
|
16
|
+
error?: undefined;
|
|
17
|
+
}
|
|
18
|
+
export interface UseMapModelRejected {
|
|
19
|
+
kind: "rejected";
|
|
20
|
+
map?: undefined;
|
|
21
|
+
error: Error;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* React hooks that looks up the map with the given id in the `map.MapRegistry` service.
|
|
25
|
+
*
|
|
26
|
+
* Returns an object representing the progress, which will eventually represent either
|
|
27
|
+
* the map model value or an initialization error.
|
|
28
|
+
*
|
|
29
|
+
* The map model cannot be returned directly because it may not have completed its initialization yet.
|
|
30
|
+
*/
|
|
31
|
+
export declare function useMapModel(mapId: string): UseMapModelResult;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { useService } from '../_virtual/_virtual-pioneer-module_react-hooks.js';
|
|
2
|
+
import { useMemo } from 'react';
|
|
3
|
+
import { useAsync } from 'react-use';
|
|
4
|
+
|
|
5
|
+
function useMapModel(mapId) {
|
|
6
|
+
const mapRegistry = useService("map.MapRegistry");
|
|
7
|
+
const state = useAsync(() => mapRegistry.getMapModel(mapId), [mapRegistry, mapId]);
|
|
8
|
+
const result = useMemo(() => {
|
|
9
|
+
if (state.loading) {
|
|
10
|
+
return { kind: "loading" };
|
|
11
|
+
}
|
|
12
|
+
if (state.error) {
|
|
13
|
+
return { kind: "rejected", error: state.error };
|
|
14
|
+
}
|
|
15
|
+
return { kind: "resolved", map: state.value };
|
|
16
|
+
}, [state]);
|
|
17
|
+
return result;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export { useMapModel };
|
|
21
|
+
//# sourceMappingURL=useMapModel.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useMapModel.js","sources":["useMapModel.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2023 Open Pioneer project (https://github.com/open-pioneer)\n// SPDX-License-Identifier: Apache-2.0\nimport { useService } from \"open-pioneer:react-hooks\";\nimport { useMemo } from \"react\";\nimport { useAsync } from \"react-use\";\nimport { MapModel } from \"../api\";\n\n/** Return value of {@link useMapModel}. */\nexport type UseMapModelResult =\n | {\n kind: \"loading\" | \"resolved\" | \"rejected\";\n map?: MapModel | undefined;\n error?: Error | undefined;\n }\n | UseMapModelLoading\n | UseMapModelResolved\n | UseMapModelRejected;\n\nexport interface UseMapModelLoading {\n kind: \"loading\";\n map?: undefined;\n error?: undefined;\n}\n\nexport interface UseMapModelResolved {\n kind: \"resolved\";\n map: MapModel;\n error?: undefined;\n}\n\nexport interface UseMapModelRejected {\n kind: \"rejected\";\n map?: undefined;\n error: Error;\n}\n\n/**\n * React hooks that looks up the map with the given id in the `map.MapRegistry` service.\n *\n * Returns an object representing the progress, which will eventually represent either\n * the map model value or an initialization error.\n *\n * The map model cannot be returned directly because it may not have completed its initialization yet.\n */\nexport function useMapModel(mapId: string): UseMapModelResult {\n const mapRegistry = useService(\"map.MapRegistry\");\n const state = useAsync(() => mapRegistry.getMapModel(mapId), [mapRegistry, mapId]);\n const result = useMemo((): UseMapModelResult => {\n if (state.loading) {\n return { kind: \"loading\" };\n }\n if (state.error) {\n return { kind: \"rejected\", error: state.error };\n }\n return { kind: \"resolved\", map: state.value };\n }, [state]);\n return result;\n}\n"],"names":[],"mappings":";;;;AA4CO,SAAS,YAAY,KAAkC,EAAA;AAC1D,EAAM,MAAA,WAAA,GAAc,WAAW,iBAAiB,CAAA,CAAA;AAChD,EAAM,MAAA,KAAA,GAAQ,QAAS,CAAA,MAAM,WAAY,CAAA,WAAA,CAAY,KAAK,CAAG,EAAA,CAAC,WAAa,EAAA,KAAK,CAAC,CAAA,CAAA;AACjF,EAAM,MAAA,MAAA,GAAS,QAAQ,MAAyB;AAC5C,IAAA,IAAI,MAAM,OAAS,EAAA;AACf,MAAO,OAAA,EAAE,MAAM,SAAU,EAAA,CAAA;AAAA,KAC7B;AACA,IAAA,IAAI,MAAM,KAAO,EAAA;AACb,MAAA,OAAO,EAAE,IAAA,EAAM,UAAY,EAAA,KAAA,EAAO,MAAM,KAAM,EAAA,CAAA;AAAA,KAClD;AACA,IAAA,OAAO,EAAE,IAAA,EAAM,UAAY,EAAA,GAAA,EAAK,MAAM,KAAM,EAAA,CAAA;AAAA,GAChD,EAAG,CAAC,KAAK,CAAC,CAAA,CAAA;AACV,EAAO,OAAA,MAAA,CAAA;AACX;;;;"}
|
package/util/defer.d.ts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export interface DeferredExecution {
|
|
2
|
+
/**
|
|
3
|
+
* Re-schedule execution of `func` (if it was not already executed).
|
|
4
|
+
* Returns true on success, false otherwise.
|
|
5
|
+
*/
|
|
6
|
+
reschedule(): boolean;
|
|
7
|
+
/**
|
|
8
|
+
* Cancels the pending execution (if it is still pending).
|
|
9
|
+
*/
|
|
10
|
+
cancel(): void;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Calls `func` at a slightly later time.
|
|
14
|
+
*
|
|
15
|
+
* The returned object can be used to re-schedule or cancel the execution of `func`.
|
|
16
|
+
* However, `func` will be executed at most once.
|
|
17
|
+
*/
|
|
18
|
+
export declare function defer(func: () => void): DeferredExecution;
|
package/util/defer.js
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
function defer(func) {
|
|
2
|
+
let executed = false;
|
|
3
|
+
let timeout = setTimeout(() => {
|
|
4
|
+
executed = true;
|
|
5
|
+
timeout = void 0;
|
|
6
|
+
func();
|
|
7
|
+
});
|
|
8
|
+
return {
|
|
9
|
+
reschedule() {
|
|
10
|
+
return !executed;
|
|
11
|
+
},
|
|
12
|
+
cancel() {
|
|
13
|
+
if (timeout) {
|
|
14
|
+
clearTimeout(timeout);
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export { defer };
|
|
21
|
+
//# sourceMappingURL=defer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"defer.js","sources":["defer.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2023 Open Pioneer project (https://github.com/open-pioneer)\n// SPDX-License-Identifier: Apache-2.0\nexport interface DeferredExecution {\n /**\n * Re-schedule execution of `func` (if it was not already executed).\n * Returns true on success, false otherwise.\n */\n reschedule(): boolean;\n\n /**\n * Cancels the pending execution (if it is still pending).\n */\n cancel(): void;\n}\n\n/**\n * Calls `func` at a slightly later time.\n *\n * The returned object can be used to re-schedule or cancel the execution of `func`.\n * However, `func` will be executed at most once.\n */\nexport function defer(func: () => void): DeferredExecution {\n let executed = false;\n let timeout: ReturnType<typeof setTimeout> | undefined = setTimeout(() => {\n executed = true;\n timeout = undefined;\n func();\n });\n return {\n reschedule() {\n // Do nothing: if not executed, the timeout is still pending\n // and it will run in the future.\n return !executed;\n },\n cancel() {\n if (timeout) {\n clearTimeout(timeout);\n }\n }\n };\n}\n"],"names":[],"mappings":"AAqBO,SAAS,MAAM,IAAqC,EAAA;AACvD,EAAA,IAAI,QAAW,GAAA,KAAA,CAAA;AACf,EAAI,IAAA,OAAA,GAAqD,WAAW,MAAM;AACtE,IAAW,QAAA,GAAA,IAAA,CAAA;AACX,IAAU,OAAA,GAAA,KAAA,CAAA,CAAA;AACV,IAAK,IAAA,EAAA,CAAA;AAAA,GACR,CAAA,CAAA;AACD,EAAO,OAAA;AAAA,IACH,UAAa,GAAA;AAGT,MAAA,OAAO,CAAC,QAAA,CAAA;AAAA,KACZ;AAAA,IACA,MAAS,GAAA;AACL,MAAA,IAAI,OAAS,EAAA;AACT,QAAA,YAAA,CAAa,OAAO,CAAA,CAAA;AAAA,OACxB;AAAA,KACJ;AAAA,GACJ,CAAA;AACJ;;;;"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { equals } from 'ol/extent';
|
|
2
|
+
import OlMap from 'ol/Map';
|
|
3
|
+
|
|
4
|
+
let setupDone = false;
|
|
5
|
+
function patchOpenLayersClassesForTesting() {
|
|
6
|
+
if (setupDone) {
|
|
7
|
+
return;
|
|
8
|
+
}
|
|
9
|
+
OlMap.prototype.updateSize = function() {
|
|
10
|
+
const target = this.getTargetElement();
|
|
11
|
+
const height = 500;
|
|
12
|
+
const width = 500;
|
|
13
|
+
const size = target ? [width, height] : void 0;
|
|
14
|
+
const oldSize = this.getSize();
|
|
15
|
+
if (size && (!oldSize || !equals(size, oldSize))) {
|
|
16
|
+
this.setSize(size);
|
|
17
|
+
this.updateViewportSize_();
|
|
18
|
+
}
|
|
19
|
+
};
|
|
20
|
+
setupDone = true;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export { patchOpenLayersClassesForTesting };
|
|
24
|
+
//# sourceMappingURL=ol-test-support.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ol-test-support.js","sources":["ol-test-support.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2023 Open Pioneer project (https://github.com/open-pioneer)\n// SPDX-License-Identifier: Apache-2.0\nimport { equals as extentEquals } from \"ol/extent\";\nimport OlMap from \"ol/Map\";\n\nlet setupDone = false;\n\n/** @internal */\nexport function patchOpenLayersClassesForTesting() {\n if (setupDone) {\n return;\n }\n\n // Test support: open layers relies on div.offsetHeight (and Width)\n // plus getComputedStyle(div), which do not work as expected in happy dom.\n // The following snippet fakes a size so tests can work with the map.\n OlMap.prototype.updateSize = function () {\n const target = this.getTargetElement();\n const height = 500;\n const width = 500;\n const size = target ? [width, height] : undefined;\n const oldSize = this.getSize();\n if (size && (!oldSize || !extentEquals(size, oldSize))) {\n this.setSize(size);\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n (this as any).updateViewportSize_();\n }\n };\n setupDone = true;\n}\n"],"names":["extentEquals"],"mappings":";;;AAKA,IAAI,SAAY,GAAA,KAAA,CAAA;AAGT,SAAS,gCAAmC,GAAA;AAC/C,EAAA,IAAI,SAAW,EAAA;AACX,IAAA,OAAA;AAAA,GACJ;AAKA,EAAM,KAAA,CAAA,SAAA,CAAU,aAAa,WAAY;AACrC,IAAM,MAAA,MAAA,GAAS,KAAK,gBAAiB,EAAA,CAAA;AACrC,IAAA,MAAM,MAAS,GAAA,GAAA,CAAA;AACf,IAAA,MAAM,KAAQ,GAAA,GAAA,CAAA;AACd,IAAA,MAAM,IAAO,GAAA,MAAA,GAAS,CAAC,KAAA,EAAO,MAAM,CAAI,GAAA,KAAA,CAAA,CAAA;AACxC,IAAM,MAAA,OAAA,GAAU,KAAK,OAAQ,EAAA,CAAA;AAC7B,IAAA,IAAI,SAAS,CAAC,OAAA,IAAW,CAACA,MAAa,CAAA,IAAA,EAAM,OAAO,CAAI,CAAA,EAAA;AACpD,MAAA,IAAA,CAAK,QAAQ,IAAI,CAAA,CAAA;AAEjB,MAAC,KAAa,mBAAoB,EAAA,CAAA;AAAA,KACtC;AAAA,GACJ,CAAA;AACA,EAAY,SAAA,GAAA,IAAA,CAAA;AAChB;;;;"}
|