@open-pioneer/map 0.6.1 → 0.8.0-dev.20241120115147

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.
Files changed (81) hide show
  1. package/CHANGELOG.md +214 -0
  2. package/README.md +127 -12
  3. package/api/MapModel.d.ts +50 -17
  4. package/api/index.d.ts +2 -1
  5. package/api/layers/GroupLayer.d.ts +50 -0
  6. package/api/layers/GroupLayer.js +6 -0
  7. package/api/layers/GroupLayer.js.map +1 -0
  8. package/api/layers/SimpleLayer.d.ts +5 -2
  9. package/api/layers/SimpleLayer.js.map +1 -1
  10. package/api/layers/WMSLayer.d.ts +6 -3
  11. package/api/layers/WMSLayer.js.map +1 -1
  12. package/api/layers/WMTSLayer.d.ts +4 -2
  13. package/api/layers/WMTSLayer.js.map +1 -1
  14. package/api/layers/base.d.ts +77 -18
  15. package/api/layers/base.js +9 -0
  16. package/api/layers/base.js.map +1 -0
  17. package/api/layers/index.d.ts +1 -0
  18. package/index.js +3 -0
  19. package/index.js.map +1 -1
  20. package/model/AbstractLayer.d.ts +4 -3
  21. package/model/AbstractLayer.js +16 -23
  22. package/model/AbstractLayer.js.map +1 -1
  23. package/model/AbstractLayerBase.d.ts +21 -5
  24. package/model/AbstractLayerBase.js +48 -35
  25. package/model/AbstractLayerBase.js.map +1 -1
  26. package/model/Highlights.d.ts +11 -4
  27. package/model/Highlights.js +5 -1
  28. package/model/Highlights.js.map +1 -1
  29. package/model/LayerCollectionImpl.d.ts +10 -10
  30. package/model/LayerCollectionImpl.js +39 -37
  31. package/model/LayerCollectionImpl.js.map +1 -1
  32. package/model/MapModelImpl.d.ts +16 -3
  33. package/model/MapModelImpl.js +94 -25
  34. package/model/MapModelImpl.js.map +1 -1
  35. package/model/SublayersCollectionImpl.d.ts +6 -3
  36. package/model/SublayersCollectionImpl.js +6 -4
  37. package/model/SublayersCollectionImpl.js.map +1 -1
  38. package/model/layers/GroupLayerImpl.d.ts +39 -0
  39. package/model/layers/GroupLayerImpl.js +88 -0
  40. package/model/layers/GroupLayerImpl.js.map +1 -0
  41. package/model/layers/SimpleLayerImpl.d.ts +4 -1
  42. package/model/layers/SimpleLayerImpl.js +6 -0
  43. package/model/layers/SimpleLayerImpl.js.map +1 -1
  44. package/model/layers/WMSLayerImpl.d.ts +11 -7
  45. package/model/layers/WMSLayerImpl.js +64 -51
  46. package/model/layers/WMSLayerImpl.js.map +1 -1
  47. package/model/layers/WMTSLayerImpl.d.ts +4 -5
  48. package/model/layers/WMTSLayerImpl.js +16 -13
  49. package/model/layers/WMTSLayerImpl.js.map +1 -1
  50. package/package.json +11 -12
  51. package/ui/CssProps.d.ts +9 -0
  52. package/ui/CssProps.js +13 -0
  53. package/ui/CssProps.js.map +1 -0
  54. package/ui/DefaultMapProvider.d.ts +39 -0
  55. package/ui/DefaultMapProvider.js +24 -0
  56. package/ui/DefaultMapProvider.js.map +1 -0
  57. package/ui/MapAnchor.d.ts +0 -3
  58. package/ui/MapAnchor.js +5 -49
  59. package/ui/MapAnchor.js.map +1 -1
  60. package/ui/MapContainer.d.ts +3 -3
  61. package/ui/MapContainer.js +30 -25
  62. package/ui/MapContainer.js.map +1 -1
  63. package/ui/MapContainerContext.d.ts +7 -0
  64. package/ui/MapContainerContext.js +17 -0
  65. package/ui/MapContainerContext.js.map +1 -0
  66. package/ui/computeMapAnchorStyles.d.ts +3 -0
  67. package/ui/computeMapAnchorStyles.js +51 -0
  68. package/ui/computeMapAnchorStyles.js.map +1 -0
  69. package/ui/hooks.d.ts +10 -0
  70. package/ui/hooks.js.map +1 -1
  71. package/ui/styles.css +7 -0
  72. package/ui/styles.css.map +1 -1
  73. package/ui/useMapModel.d.ts +33 -6
  74. package/ui/useMapModel.js +40 -2
  75. package/ui/useMapModel.js.map +1 -1
  76. package/ui/MapContext.d.ts +0 -11
  77. package/ui/MapContext.js +0 -17
  78. package/ui/MapContext.js.map +0 -1
  79. package/util/defer.d.ts +0 -18
  80. package/util/defer.js +0 -21
  81. package/util/defer.js.map +0 -1
package/ui/MapAnchor.js CHANGED
@@ -2,22 +2,16 @@ import { jsx } from 'react/jsx-runtime';
2
2
  import { Box } from '@open-pioneer/chakra-integration';
3
3
  import { useCommonComponentProps } from '@open-pioneer/react-utils';
4
4
  import { createPortal } from 'react-dom';
5
- import { useMapContext } from './MapContext.js';
5
+ import { computeMapAnchorStyles } from './computeMapAnchorStyles.js';
6
+ import { useMapContainerContext } from './MapContainerContext.js';
6
7
 
7
8
  const defaultPosition = "top-right";
8
9
  function MapAnchor(props) {
9
10
  const { position = defaultPosition, children, horizontalGap, verticalGap } = props;
10
11
  const { containerProps } = useCommonComponentProps("map-anchor", props);
11
- const { padding, mapAnchorsHost } = useMapContext();
12
+ const { mapAnchorsHost } = useMapContainerContext();
12
13
  return createPortal(
13
- /* @__PURE__ */ jsx(
14
- Box,
15
- {
16
- ...containerProps,
17
- ...computePositionStyles(position, padding, horizontalGap, verticalGap),
18
- children
19
- }
20
- ),
14
+ /* @__PURE__ */ jsx(Box, { ...containerProps, ...computeMapAnchorStyles(position, horizontalGap, verticalGap), children }),
21
15
  mapAnchorsHost
22
16
  );
23
17
  }
@@ -29,44 +23,6 @@ function computeAttributionGap(verticalGap) {
29
23
  space
30
24
  };
31
25
  }
32
- function computePositionStyles(position, padding, horizontalGap, verticalGap) {
33
- const props = {
34
- position: "absolute",
35
- zIndex: 1,
36
- // above map
37
- transitionProperty: "left, right, top, bottom",
38
- transitionDuration: "200ms",
39
- transitionTimingFunction: "ease-out"
40
- };
41
- const defaultHorizontalGap = 0;
42
- const horizontal = horizontalGap ?? defaultHorizontalGap;
43
- const defaultVerticalGap = 0;
44
- const vertical = verticalGap ?? defaultVerticalGap;
45
- const attribution = computeAttributionGap(verticalGap);
46
- const gap = (n) => `${n}px`;
47
- switch (position) {
48
- case "top-left":
49
- props.left = gap(padding.left + horizontal);
50
- props.top = gap(padding.top + vertical);
51
- break;
52
- case "top-right":
53
- props.right = gap(padding.right + horizontal);
54
- props.top = gap(padding.top + vertical);
55
- break;
56
- case "bottom-left":
57
- props.left = gap(padding.left + horizontal);
58
- props.bottom = gap(padding.bottom + vertical + attribution.gap);
59
- break;
60
- case "bottom-right":
61
- props.right = gap(padding.right + horizontal);
62
- props.bottom = gap(padding.bottom + vertical + attribution.gap);
63
- break;
64
- }
65
- props.maxH = `calc((100%) - ${props.top ?? "0px"} - ${props.bottom ?? attribution.gap + "px"} - ${vertical + "px"} - ${attribution.space + "px"})`;
66
- props.maxW = `calc((100%) - ${props.left ?? "0px"} - ${props.right ?? "0px"} - ${horizontal + "px"})`;
67
- props.overflow = "hidden";
68
- return props;
69
- }
70
26
 
71
- export { MapAnchor, computeAttributionGap, computePositionStyles };
27
+ export { MapAnchor, computeAttributionGap };
72
28
  //# sourceMappingURL=MapAnchor.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"MapAnchor.js","sources":["MapAnchor.tsx"],"sourcesContent":["// SPDX-FileCopyrightText: 2023 Open Pioneer project (https://github.com/open-pioneer)\n// SPDX-License-Identifier: Apache-2.0\nimport { Box, StyleProps } from \"@open-pioneer/chakra-integration\";\nimport { CommonComponentProps, useCommonComponentProps } from \"@open-pioneer/react-utils\";\nimport { ReactNode } from \"react\";\nimport { createPortal } from \"react-dom\";\nimport { MapPadding } from \"../api\";\nimport { useMapContext } from \"./MapContext\";\n\nexport type MapAnchorPosition = \"top-left\" | \"top-right\" | \"bottom-left\" | \"bottom-right\";\n\nconst defaultPosition: MapAnchorPosition = \"top-right\";\n\nexport interface MapAnchorProps extends CommonComponentProps {\n /**\n * The position of the anchor container above the map.\n * @default \"top-right\"\n */\n position?: MapAnchorPosition;\n\n /**\n * Horizontal gap in pixel applied to anchor container.\n *\n * Applied:\n * - left, if position `*-left`\n * - right, if position `*-right`\n *\n * @default 0\n */\n horizontalGap?: number;\n\n /**\n * Vertical gap in pixel applied to anchor container.\n *\n * Applied:\n * - top, if position `top-*`\n * - bottom, if position `bottom-*`\n *\n * @default 0 (If position `bottom-*`, default verticalGap == `30`)\n */\n verticalGap?: number;\n\n children?: ReactNode;\n}\n\nexport function MapAnchor(props: MapAnchorProps): JSX.Element {\n const { position = defaultPosition, children, horizontalGap, verticalGap } = props;\n const { containerProps } = useCommonComponentProps(\"map-anchor\", props);\n const { padding, mapAnchorsHost } = useMapContext();\n\n return createPortal(\n <Box\n {...containerProps}\n {...computePositionStyles(position, padding, horizontalGap, verticalGap)}\n >\n {children}\n </Box>,\n mapAnchorsHost\n );\n}\n\nexport function computeAttributionGap(verticalGap?: number): {\n gap: number;\n space: number;\n} {\n /**\n * height of the ol attribution component\n * improvement: Get height directly from `Attribution` HTMLDivElement\n */\n const height = 20;\n\n /**\n * additional space between attribution and map anchor container\n */\n const space = 10;\n\n return {\n gap: verticalGap === undefined ? height + space : 0,\n space\n };\n}\n\nexport function computePositionStyles(\n position: MapAnchorPosition,\n padding: Required<MapPadding>,\n horizontalGap?: number | undefined,\n verticalGap?: number | undefined\n): StyleProps {\n const props: StyleProps = {\n position: \"absolute\",\n zIndex: 1, // above map\n transitionProperty: \"left, right, top, bottom\",\n transitionDuration: \"200ms\",\n transitionTimingFunction: \"ease-out\"\n };\n\n const defaultHorizontalGap = 0;\n const horizontal = horizontalGap ?? defaultHorizontalGap;\n\n const defaultVerticalGap = 0;\n const vertical = verticalGap ?? defaultVerticalGap;\n\n const attribution = computeAttributionGap(verticalGap);\n const gap = (n: number) => `${n}px`;\n\n switch (position) {\n case \"top-left\":\n props.left = gap(padding.left + horizontal);\n props.top = gap(padding.top + vertical);\n break;\n case \"top-right\":\n props.right = gap(padding.right + horizontal);\n props.top = gap(padding.top + vertical);\n break;\n case \"bottom-left\":\n props.left = gap(padding.left + horizontal);\n props.bottom = gap(padding.bottom + vertical + attribution.gap);\n break;\n case \"bottom-right\":\n props.right = gap(padding.right + horizontal);\n props.bottom = gap(padding.bottom + vertical + attribution.gap);\n break;\n }\n\n /**\n * Apply max-height and max-width to MapAnchor to avoid content overflow\n */\n props.maxH = `calc((100%) - ${props.top ?? \"0px\"} - ${\n props.bottom ?? attribution.gap + \"px\"\n } - ${vertical + \"px\"} - ${attribution.space + \"px\"})`;\n\n props.maxW = `calc((100%) - ${props.left ?? \"0px\"} - ${props.right ?? \"0px\"} - ${\n horizontal + \"px\"\n })`;\n props.overflow = \"hidden\";\n\n return props;\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"MapAnchor.js","sources":["MapAnchor.tsx"],"sourcesContent":["// SPDX-FileCopyrightText: 2023 Open Pioneer project (https://github.com/open-pioneer)\n// SPDX-License-Identifier: Apache-2.0\nimport { Box } from \"@open-pioneer/chakra-integration\";\nimport { CommonComponentProps, useCommonComponentProps } from \"@open-pioneer/react-utils\";\nimport { ReactNode } from \"react\";\nimport { createPortal } from \"react-dom\";\nimport { computeMapAnchorStyles } from \"./computeMapAnchorStyles\";\nimport { useMapContainerContext } from \"./MapContainerContext\";\n\nexport type MapAnchorPosition = \"top-left\" | \"top-right\" | \"bottom-left\" | \"bottom-right\";\n\nconst defaultPosition: MapAnchorPosition = \"top-right\";\n\nexport interface MapAnchorProps extends CommonComponentProps {\n /**\n * The position of the anchor container above the map.\n * @default \"top-right\"\n */\n position?: MapAnchorPosition;\n\n /**\n * Horizontal gap in pixel applied to anchor container.\n *\n * Applied:\n * - left, if position `*-left`\n * - right, if position `*-right`\n *\n * @default 0\n */\n horizontalGap?: number;\n\n /**\n * Vertical gap in pixel applied to anchor container.\n *\n * Applied:\n * - top, if position `top-*`\n * - bottom, if position `bottom-*`\n *\n * @default 0 (If position `bottom-*`, default verticalGap == `30`)\n */\n verticalGap?: number;\n\n children?: ReactNode;\n}\n\nexport function MapAnchor(props: MapAnchorProps): JSX.Element {\n const { position = defaultPosition, children, horizontalGap, verticalGap } = props;\n const { containerProps } = useCommonComponentProps(\"map-anchor\", props);\n const { mapAnchorsHost } = useMapContainerContext();\n\n return createPortal(\n <Box {...containerProps} {...computeMapAnchorStyles(position, horizontalGap, verticalGap)}>\n {children}\n </Box>,\n mapAnchorsHost\n );\n}\n\nexport function computeAttributionGap(verticalGap?: number): {\n gap: number;\n space: number;\n} {\n /**\n * height of the ol attribution component\n * improvement: Get height directly from `Attribution` HTMLDivElement\n */\n const height = 20;\n\n /**\n * additional space between attribution and map anchor container\n */\n const space = 10;\n\n return {\n gap: verticalGap === undefined ? height + space : 0,\n space\n };\n}\n"],"names":[],"mappings":";;;;;;;AAWA,MAAM,eAAqC,GAAA,WAAA,CAAA;AAkCpC,SAAS,UAAU,KAAoC,EAAA;AAC1D,EAAA,MAAM,EAAE,QAAW,GAAA,eAAA,EAAiB,QAAU,EAAA,aAAA,EAAe,aAAgB,GAAA,KAAA,CAAA;AAC7E,EAAA,MAAM,EAAE,cAAA,EAAmB,GAAA,uBAAA,CAAwB,cAAc,KAAK,CAAA,CAAA;AACtE,EAAM,MAAA,EAAE,cAAe,EAAA,GAAI,sBAAuB,EAAA,CAAA;AAElD,EAAO,OAAA,YAAA;AAAA,oBACH,GAAA,CAAC,GAAK,EAAA,EAAA,GAAG,cAAiB,EAAA,GAAG,uBAAuB,QAAU,EAAA,aAAA,EAAe,WAAW,CAAA,EACnF,QACL,EAAA,CAAA;AAAA,IACA,cAAA;AAAA,GACJ,CAAA;AACJ,CAAA;AAEO,SAAS,sBAAsB,WAGpC,EAAA;AAKE,EAAA,MAAM,MAAS,GAAA,EAAA,CAAA;AAKf,EAAA,MAAM,KAAQ,GAAA,EAAA,CAAA;AAEd,EAAO,OAAA;AAAA,IACH,GAAK,EAAA,WAAA,KAAgB,KAAY,CAAA,GAAA,MAAA,GAAS,KAAQ,GAAA,CAAA;AAAA,IAClD,KAAA;AAAA,GACJ,CAAA;AACJ;;;;"}
@@ -1,11 +1,11 @@
1
1
  import { CommonComponentProps } from "@open-pioneer/react-utils";
2
2
  import { ReactNode } from "react";
3
3
  import { MapPadding } from "../api";
4
- export interface MapContainerProps extends CommonComponentProps {
5
- /** The id of the map to display. */
6
- mapId: string;
4
+ import { MapModelProps } from "./useMapModel";
5
+ export interface MapContainerProps extends CommonComponentProps, MapModelProps {
7
6
  /**
8
7
  * Sets the map's padding directly.
8
+ * Do not use the view's padding property directly on the OL map.
9
9
  *
10
10
  * See: https://openlayers.org/en/latest/apidoc/module-ol_View-View.html#padding)
11
11
  */
@@ -3,13 +3,13 @@ import { chakra } from '@open-pioneer/chakra-integration';
3
3
  import { createLogger } from '@open-pioneer/core';
4
4
  import { useCommonComponentProps } from '@open-pioneer/react-utils';
5
5
  import { useRef, useState, useEffect, useMemo } from 'react';
6
- import { MapContextProvider } from './MapContext.js';
6
+ import { MapContainerContextProvider } from './MapContainerContext.js';
7
7
  import { useMapModel } from './useMapModel.js';
8
+ import { PADDING_TOP, PADDING_BOTTOM, PADDING_LEFT, PADDING_RIGHT } from './CssProps.js';
8
9
 
9
10
  const LOG = createLogger("map:MapContainer");
10
11
  function MapContainer(props) {
11
12
  const {
12
- mapId,
13
13
  viewPadding,
14
14
  viewPaddingChangeBehavior,
15
15
  children,
@@ -20,8 +20,8 @@ function MapContainer(props) {
20
20
  const { containerProps } = useCommonComponentProps("map-container", props);
21
21
  const mapContainer = useRef(null);
22
22
  const mapAnchorsHost = useRef(null);
23
- const modelState = useMapModel(mapId);
24
- const mapModel = modelState.map;
23
+ const modelState = useMapModel(props);
24
+ const map = modelState.map;
25
25
  const [ready, setReady] = useState(false);
26
26
  useEffect(() => {
27
27
  if (modelState.kind === "loading") {
@@ -31,22 +31,29 @@ function MapContainer(props) {
31
31
  LOG.error(`Cannot display the map. Caused by `, modelState.error);
32
32
  return;
33
33
  }
34
- if (!mapModel) {
35
- LOG.error(`No configuration available for map with id '${mapId}'.`);
34
+ if (!map) {
35
+ LOG.error(`No configuration available for the configured map.`);
36
36
  return;
37
37
  }
38
38
  if (mapContainer.current) {
39
- const resource = registerMapTarget(mapModel, mapContainer.current);
39
+ const resource = registerMapTarget(map, mapContainer.current);
40
40
  return () => resource?.destroy();
41
41
  }
42
- }, [modelState, mapModel, mapId]);
42
+ }, [modelState, map]);
43
43
  useEffect(() => {
44
44
  setReady(true);
45
45
  }, []);
46
- const mapContainerStyle = {
47
- height: "100%",
48
- position: "relative"
49
- };
46
+ const styleProps = useMemo(() => {
47
+ return {
48
+ height: "100%",
49
+ position: "relative",
50
+ // set css variables according to view padding
51
+ [PADDING_TOP.definition]: viewPadding?.top != void 0 ? viewPadding.top + "px" : "0px",
52
+ [PADDING_BOTTOM.definition]: viewPadding?.bottom != void 0 ? viewPadding.bottom + "px" : "0px",
53
+ [PADDING_LEFT.definition]: viewPadding?.left != void 0 ? viewPadding.left + "px" : "0px",
54
+ [PADDING_RIGHT.definition]: viewPadding?.right != void 0 ? viewPadding.right + "px" : "0px"
55
+ };
56
+ }, [viewPadding]);
50
57
  return /* @__PURE__ */ jsxs(
51
58
  chakra.div,
52
59
  {
@@ -55,13 +62,13 @@ function MapContainer(props) {
55
62
  "aria-label": ariaLabel,
56
63
  "aria-labelledby": ariaLabelledBy,
57
64
  ref: mapContainer,
58
- style: mapContainerStyle,
65
+ style: styleProps,
59
66
  tabIndex: 0,
60
67
  children: [
61
- ready && mapModel && /* @__PURE__ */ jsx(
68
+ ready && map && /* @__PURE__ */ jsx(
62
69
  MapContainerReady,
63
70
  {
64
- map: mapModel.olMap,
71
+ olMap: map.olMap,
65
72
  mapAnchorsHost: mapAnchorsHost.current,
66
73
  viewPadding,
67
74
  viewPaddingChangeBehavior,
@@ -81,7 +88,7 @@ function MapContainer(props) {
81
88
  }
82
89
  function MapContainerReady(props) {
83
90
  const {
84
- map,
91
+ olMap,
85
92
  mapAnchorsHost,
86
93
  viewPadding: viewPaddingProp,
87
94
  viewPaddingChangeBehavior = "preserve-center",
@@ -96,13 +103,13 @@ function MapContainerReady(props) {
96
103
  };
97
104
  }, [viewPaddingProp]);
98
105
  useEffect(() => {
99
- const mapView = map?.getView();
100
- if (!map || !mapView) {
106
+ const mapView = olMap?.getView();
107
+ if (!olMap || !mapView) {
101
108
  return;
102
109
  }
103
110
  const oldCenter = mapView.getCenter();
104
111
  const oldPadding = fromOlPadding(mapView.padding);
105
- const oldExtent = extentIncludingPadding(map, oldPadding);
112
+ const oldExtent = extentIncludingPadding(olMap, oldPadding);
106
113
  mapView.padding = toOlPadding(viewPadding);
107
114
  switch (viewPaddingChangeBehavior) {
108
115
  case "preserve-center":
@@ -119,15 +126,13 @@ function MapContainerReady(props) {
119
126
  break;
120
127
  }
121
128
  }
122
- }, [viewPadding, map, viewPaddingChangeBehavior]);
129
+ }, [viewPadding, olMap, viewPaddingChangeBehavior]);
123
130
  const mapContext = useMemo(() => {
124
131
  return {
125
- map,
126
- mapAnchorsHost,
127
- padding: viewPadding
132
+ mapAnchorsHost
128
133
  };
129
- }, [map, viewPadding, mapAnchorsHost]);
130
- return /* @__PURE__ */ jsx(MapContextProvider, { value: mapContext, children });
134
+ }, [mapAnchorsHost]);
135
+ return /* @__PURE__ */ jsx(MapContainerContextProvider, { value: mapContext, children });
131
136
  }
132
137
  function registerMapTarget(mapModel, target) {
133
138
  const mapId = mapModel.id;
@@ -1 +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 { chakra } from \"@open-pioneer/chakra-integration\";\nimport { Resource, createLogger } from \"@open-pioneer/core\";\nimport { CommonComponentProps, useCommonComponentProps } from \"@open-pioneer/react-utils\";\nimport type OlMap from \"ol/Map\";\nimport { Extent } from \"ol/extent\";\nimport { ReactNode, useEffect, useMemo, useRef, useState } from \"react\";\nimport { MapModel, MapPadding } from \"../api\";\nimport { MapContextProvider, MapContextType } from \"./MapContext\";\nimport { useMapModel } from \"./useMapModel\";\nconst LOG = createLogger(\"map:MapContainer\");\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 mapContainer = useRef<HTMLDivElement>(null);\n const mapAnchorsHost = useRef<HTMLDivElement>(null);\n const modelState = useMapModel(mapId);\n const mapModel = modelState.map;\n\n const [ready, setReady] = useState(false);\n\n useEffect(() => {\n if (modelState.kind === \"loading\") {\n return;\n }\n\n if (modelState.kind === \"rejected\") {\n LOG.error(`Cannot display the map. Caused by `, modelState.error);\n return;\n }\n\n if (!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 (mapContainer.current) {\n const resource = registerMapTarget(mapModel, mapContainer.current);\n return () => resource?.destroy();\n }\n }, [modelState, mapModel, mapId]);\n\n // Wait for mount to make sure that the map anchors host is available\n useEffect(() => {\n setReady(true);\n }, []);\n\n const mapContainerStyle: React.CSSProperties = {\n height: \"100%\",\n position: \"relative\"\n };\n return (\n <chakra.div\n {...containerProps}\n role={role}\n aria-label={ariaLabel}\n aria-labelledby={ariaLabelledBy}\n ref={mapContainer}\n style={mapContainerStyle}\n //eslint-disable-next-line jsx-a11y/no-noninteractive-tabindex\n tabIndex={0}\n >\n {ready && mapModel && (\n <MapContainerReady\n map={mapModel.olMap}\n mapAnchorsHost={mapAnchorsHost.current!}\n viewPadding={viewPadding}\n viewPaddingChangeBehavior={viewPaddingChangeBehavior}\n >\n {children}\n </MapContainerReady>\n )}\n <chakra.div\n ref={mapAnchorsHost}\n className=\"map-anchors\"\n /* note: zero sized, children have a size and are positioned relative to the map-container */\n >\n {/* Map anchors will be mounted here via portal */}\n </chakra.div>\n </chakra.div>\n );\n}\n\n/**\n * This inner component is rendered when the map has been loaded.\n *\n * It provides the map instance and additional properties down the component tree.\n */\nfunction MapContainerReady(\n props: { map: OlMap; mapAnchorsHost: HTMLElement } & Omit<\n MapContainerProps,\n \"mapId\" | \"className\"\n >\n): JSX.Element {\n const {\n map,\n mapAnchorsHost,\n viewPadding: viewPaddingProp,\n viewPaddingChangeBehavior = \"preserve-center\",\n children\n } = props;\n\n const viewPadding = useMemo<Required<MapPadding>>(() => {\n return {\n left: viewPaddingProp?.left ?? 0,\n right: viewPaddingProp?.right ?? 0,\n top: viewPaddingProp?.top ?? 0,\n bottom: viewPaddingProp?.bottom ?? 0\n };\n }, [viewPaddingProp]);\n\n // Apply view padding\n useEffect(() => {\n const mapView = 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\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 * Returns the extent visible in the non-padded region of the map.\n */\nfunction extentIncludingPadding(map: OlMap, padding: Required<MapPadding>): Extent | undefined {\n const size = map.getSize();\n if (!size || size.length < 2) {\n return undefined;\n }\n\n const [width, height] = size as [number, number];\n const bottomLeft = map.getCoordinateFromPixel([padding.left, padding.bottom]);\n const topRight = map.getCoordinateFromPixel([\n Math.max(0, width - padding.right),\n Math.max(0, height - padding.top)\n ]);\n if (!bottomLeft || !topRight) {\n return undefined;\n }\n\n const [xmin, ymin] = bottomLeft;\n const [xmax, ymax] = topRight;\n return [xmin, ymin, xmax, ymax] as Extent;\n}\n\nfunction fromOlPadding(padding: number[] | undefined): Required<MapPadding> {\n // top, right, bottom, left\n return {\n top: padding?.[0] ?? 0,\n right: padding?.[1] ?? 0,\n bottom: padding?.[2] ?? 0,\n left: padding?.[3] ?? 0\n };\n}\n\nfunction toOlPadding(padding: Required<MapPadding>): number[] {\n // top, right, bottom, left\n const { top, right, bottom, left } = padding;\n return [top, right, bottom, left];\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"MapContainer.js","sources":["MapContainer.tsx"],"sourcesContent":["// SPDX-FileCopyrightText: 2023 Open Pioneer project (https://github.com/open-pioneer)\n// SPDX-License-Identifier: Apache-2.0\nimport { chakra } from \"@open-pioneer/chakra-integration\";\nimport { Resource, createLogger } from \"@open-pioneer/core\";\nimport { CommonComponentProps, useCommonComponentProps } from \"@open-pioneer/react-utils\";\nimport type OlMap from \"ol/Map\";\nimport { Extent } from \"ol/extent\";\nimport { ReactNode, useEffect, useMemo, useRef, useState, CSSProperties } from \"react\";\nimport { MapModel, MapPadding } from \"../api\";\nimport { MapContainerContextProvider, MapContainerContextType } from \"./MapContainerContext\";\nimport { MapModelProps, useMapModel } from \"./useMapModel\";\nimport { PADDING_BOTTOM, PADDING_LEFT, PADDING_RIGHT, PADDING_TOP } from \"./CssProps\";\nconst LOG = createLogger(\"map:MapContainer\");\n\nexport interface MapContainerProps extends CommonComponentProps, MapModelProps {\n /**\n * Sets the map's padding directly.\n * Do not use the view's padding property directly on the OL map.\n *\n * See: https://openlayers.org/en/latest/apidoc/module-ol_View-View.html#padding)\n */\n viewPadding?: MapPadding | undefined;\n\n /**\n * Behavior performed by the map when the view padding changes.\n *\n * - `none`: Do nothing.\n * - `preserve-center`: Ensures that the center point remains the same by animating the view.\n * - `preserve-extent`: Ensures that the extent remains the same by zooming.\n *\n * @default \"preserve-center\"\n */\n viewPaddingChangeBehavior?: \"none\" | \"preserve-center\" | \"preserve-extent\";\n\n children?: ReactNode;\n\n /**\n * Optional role property.\n *\n * This property is directly applied to the map's container div element.\n */\n role?: string;\n\n /**\n * Optional aria-labelledby property.\n * Do not use together with aria-label.\n *\n * This property is directly applied to the map's container div element.\n */\n \"aria-labelledby\"?: string;\n\n /**\n * Optional aria-label property.\n * Do not use together with aria-label.\n *\n * This property is directly applied to the map's container div element.\n */\n \"aria-label\"?: string;\n}\n\n/**\n * Displays the map with the given id.\n *\n * There can only be at most one MapContainer for every map.\n */\nexport function MapContainer(props: MapContainerProps) {\n const {\n viewPadding,\n viewPaddingChangeBehavior,\n children,\n role,\n \"aria-label\": ariaLabel,\n \"aria-labelledby\": ariaLabelledBy\n } = props;\n const { containerProps } = useCommonComponentProps(\"map-container\", props);\n const mapContainer = useRef<HTMLDivElement>(null);\n const mapAnchorsHost = useRef<HTMLDivElement>(null);\n const modelState = useMapModel(props);\n const map = modelState.map;\n\n const [ready, setReady] = useState(false);\n\n useEffect(() => {\n if (modelState.kind === \"loading\") {\n return;\n }\n\n if (modelState.kind === \"rejected\") {\n LOG.error(`Cannot display the map. Caused by `, modelState.error);\n return;\n }\n\n if (!map) {\n LOG.error(`No configuration available for the configured map.`);\n return;\n }\n\n // Mount the map into the DOM\n if (mapContainer.current) {\n const resource = registerMapTarget(map, mapContainer.current);\n return () => resource?.destroy();\n }\n }, [modelState, map]);\n\n // Wait for mount to make sure that the map anchors host is available\n useEffect(() => {\n setReady(true);\n }, []);\n\n const styleProps = useMemo(() => {\n return {\n height: \"100%\",\n position: \"relative\",\n\n // set css variables according to view padding\n [PADDING_TOP.definition]:\n viewPadding?.top != undefined ? viewPadding.top + \"px\" : \"0px\",\n [PADDING_BOTTOM.definition]:\n viewPadding?.bottom != undefined ? viewPadding.bottom + \"px\" : \"0px\",\n [PADDING_LEFT.definition]:\n viewPadding?.left != undefined ? viewPadding.left + \"px\" : \"0px\",\n [PADDING_RIGHT.definition]:\n viewPadding?.right != undefined ? viewPadding.right + \"px\" : \"0px\"\n } as CSSProperties;\n }, [viewPadding]);\n\n return (\n <chakra.div\n {...containerProps}\n role={role}\n aria-label={ariaLabel}\n aria-labelledby={ariaLabelledBy}\n ref={mapContainer}\n style={styleProps}\n //eslint-disable-next-line jsx-a11y/no-noninteractive-tabindex\n tabIndex={0}\n >\n {ready && map && (\n <MapContainerReady\n olMap={map.olMap}\n mapAnchorsHost={mapAnchorsHost.current!}\n viewPadding={viewPadding}\n viewPaddingChangeBehavior={viewPaddingChangeBehavior}\n >\n {children}\n </MapContainerReady>\n )}\n <chakra.div\n ref={mapAnchorsHost}\n className=\"map-anchors\"\n /* note: zero sized, children have a size and are positioned relative to the map-container */\n >\n {/* Map anchors will be mounted here via portal */}\n </chakra.div>\n </chakra.div>\n );\n}\n\n/**\n * This inner component is rendered when the map has been loaded.\n *\n * It provides the map instance and additional properties down the component tree.\n */\nfunction MapContainerReady(\n props: { olMap: OlMap; mapAnchorsHost: HTMLElement } & Omit<\n MapContainerProps,\n \"mapId\" | \"map\" | \"className\"\n >\n): JSX.Element {\n const {\n olMap,\n mapAnchorsHost,\n viewPadding: viewPaddingProp,\n viewPaddingChangeBehavior = \"preserve-center\",\n children\n } = props;\n\n const viewPadding = useMemo<Required<MapPadding>>(() => {\n return {\n left: viewPaddingProp?.left ?? 0,\n right: viewPaddingProp?.right ?? 0,\n top: viewPaddingProp?.top ?? 0,\n bottom: viewPaddingProp?.bottom ?? 0\n };\n }, [viewPaddingProp]);\n\n // Apply view padding\n useEffect(() => {\n const mapView = olMap?.getView();\n if (!olMap || !mapView) {\n return;\n }\n\n const oldCenter = mapView.getCenter();\n const oldPadding = fromOlPadding(mapView.padding);\n const oldExtent = extentIncludingPadding(olMap, oldPadding);\n\n mapView.padding = toOlPadding(viewPadding);\n switch (viewPaddingChangeBehavior) {\n case \"preserve-center\":\n mapView.animate({ center: oldCenter, duration: 300 });\n break;\n case \"preserve-extent\": {\n if (oldExtent) {\n mapView.animate({\n center: oldCenter,\n resolution: mapView.getResolutionForExtent(oldExtent),\n duration: 300\n });\n }\n break;\n }\n case \"none\":\n }\n }, [viewPadding, olMap, viewPaddingChangeBehavior]);\n\n const mapContext = useMemo((): MapContainerContextType => {\n return {\n mapAnchorsHost\n };\n }, [mapAnchorsHost]);\n return <MapContainerContextProvider value={mapContext}>{children}</MapContainerContextProvider>;\n}\n\nfunction registerMapTarget(mapModel: MapModel, target: HTMLDivElement): Resource | undefined {\n const mapId = mapModel.id;\n const olMap = mapModel.olMap;\n if (olMap.getTarget()) {\n LOG.error(\n `Failed to display the map: the map already has a target. There may be more than one <MapContainer />.`\n );\n return undefined;\n }\n\n LOG.isDebug() && LOG.debug(`Setting target of map '${mapId}':`, target);\n 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 * 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,7 @@
1
+ import { Provider } from "react";
2
+ /** Values provided to children of {@link MapContainer}. */
3
+ export interface MapContainerContextType {
4
+ mapAnchorsHost: HTMLElement;
5
+ }
6
+ export declare const MapContainerContextProvider: Provider<MapContainerContextType>;
7
+ export declare function useMapContainerContext(): MapContainerContextType;
@@ -0,0 +1,17 @@
1
+ import { createContext, useContext } from 'react';
2
+
3
+ const MapContainerContext = createContext(void 0);
4
+ MapContainerContext.displayName = "MapContainerContext";
5
+ const MapContainerContextProvider = MapContainerContext.Provider;
6
+ function useMapContainerContext() {
7
+ const contextValue = useContext(MapContainerContext);
8
+ if (!contextValue) {
9
+ throw new Error(
10
+ `Map container context is not available. The component must be a child of the <MapContainer /> component.`
11
+ );
12
+ }
13
+ return contextValue;
14
+ }
15
+
16
+ export { MapContainerContextProvider, useMapContainerContext };
17
+ //# sourceMappingURL=MapContainerContext.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MapContainerContext.js","sources":["MapContainerContext.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\";\n\n/** Values provided to children of {@link MapContainer}. */\nexport interface MapContainerContextType {\n mapAnchorsHost: HTMLElement;\n}\n\nconst MapContainerContext = createContext<MapContainerContextType | undefined>(undefined);\nMapContainerContext.displayName = \"MapContainerContext\";\n\nexport const MapContainerContextProvider: Provider<MapContainerContextType> =\n MapContainerContext.Provider as Provider<MapContainerContextType>;\n\nexport function useMapContainerContext(): MapContainerContextType {\n const contextValue = useContext(MapContainerContext);\n if (!contextValue) {\n throw new Error(\n `Map container context is not available. The component must be a child of the <MapContainer /> component.`\n );\n }\n return contextValue;\n}\n"],"names":[],"mappings":";;AASA,MAAM,mBAAA,GAAsB,cAAmD,KAAS,CAAA,CAAA,CAAA;AACxF,mBAAA,CAAoB,WAAc,GAAA,qBAAA,CAAA;AAE3B,MAAM,8BACT,mBAAoB,CAAA,SAAA;AAEjB,SAAS,sBAAkD,GAAA;AAC9D,EAAM,MAAA,YAAA,GAAe,WAAW,mBAAmB,CAAA,CAAA;AACnD,EAAA,IAAI,CAAC,YAAc,EAAA;AACf,IAAA,MAAM,IAAI,KAAA;AAAA,MACN,CAAA,wGAAA,CAAA;AAAA,KACJ,CAAA;AAAA,GACJ;AACA,EAAO,OAAA,YAAA,CAAA;AACX;;;;"}
@@ -0,0 +1,3 @@
1
+ import { StyleProps } from "@open-pioneer/chakra-integration";
2
+ import { MapAnchorPosition } from "./MapAnchor";
3
+ export declare function computeMapAnchorStyles(position: MapAnchorPosition, horizontalGap?: number | undefined, verticalGap?: number | undefined): StyleProps;
@@ -0,0 +1,51 @@
1
+ import { PADDING_RIGHT, PADDING_BOTTOM, PADDING_LEFT, PADDING_TOP } from './CssProps.js';
2
+ import { computeAttributionGap } from './MapAnchor.js';
3
+
4
+ function computeMapAnchorStyles(position, horizontalGap, verticalGap) {
5
+ const styleProps = {
6
+ position: "absolute",
7
+ zIndex: 1,
8
+ // above map
9
+ transitionProperty: "left, right, top, bottom",
10
+ transitionDuration: "200ms",
11
+ transitionTimingFunction: "ease-out",
12
+ overflow: "hidden"
13
+ };
14
+ const defaultHorizontalGap = 0;
15
+ const horizontal = horizontalGap ?? defaultHorizontalGap;
16
+ const defaultVerticalGap = 0;
17
+ const vertical = verticalGap ?? defaultVerticalGap;
18
+ const attribution = computeAttributionGap(verticalGap);
19
+ const gap = (paddingProp, pixels) => `(${paddingProp} + ${pixels}px)`;
20
+ const posExprs = {};
21
+ switch (position) {
22
+ case "top-left":
23
+ posExprs.left = gap(PADDING_LEFT.ref, horizontal);
24
+ posExprs.top = gap(PADDING_TOP.ref, vertical);
25
+ break;
26
+ case "top-right":
27
+ posExprs.right = gap(PADDING_RIGHT.ref, horizontal);
28
+ posExprs.top = gap(PADDING_TOP.ref, vertical);
29
+ break;
30
+ case "bottom-left":
31
+ posExprs.left = gap(PADDING_LEFT.ref, horizontal);
32
+ posExprs.bottom = gap(PADDING_BOTTOM.ref, vertical + attribution.gap);
33
+ break;
34
+ case "bottom-right":
35
+ posExprs.right = gap(PADDING_RIGHT.ref, horizontal);
36
+ posExprs.bottom = gap(PADDING_BOTTOM.ref, vertical + attribution.gap);
37
+ break;
38
+ }
39
+ for (const [key, value] of Object.entries(posExprs)) {
40
+ styleProps[key] = `calc(${value})`;
41
+ }
42
+ styleProps.maxH = `calc((100%) - ${defaultValue(posExprs.top, "0px")} - ${defaultValue(posExprs.bottom, attribution.gap + "px")} - ${vertical}px - ${attribution.space}px)`;
43
+ styleProps.maxW = `calc((100%) - ${defaultValue(posExprs.left, "0px")} - ${defaultValue(posExprs.right, "0px")} - ${horizontal}px)`;
44
+ return styleProps;
45
+ }
46
+ function defaultValue(value, defaultValue2) {
47
+ return value ?? defaultValue2;
48
+ }
49
+
50
+ export { computeMapAnchorStyles };
51
+ //# sourceMappingURL=computeMapAnchorStyles.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"computeMapAnchorStyles.js","sources":["computeMapAnchorStyles.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2023 Open Pioneer project (https://github.com/open-pioneer)\n// SPDX-License-Identifier: Apache-2.0\nimport { StyleProps } from \"@open-pioneer/chakra-integration\";\nimport { PADDING_BOTTOM, PADDING_LEFT, PADDING_RIGHT, PADDING_TOP } from \"./CssProps\";\nimport { computeAttributionGap, MapAnchorPosition } from \"./MapAnchor\";\n\nexport function computeMapAnchorStyles(\n position: MapAnchorPosition,\n horizontalGap?: number | undefined,\n verticalGap?: number | undefined\n): StyleProps {\n const styleProps: StyleProps = {\n position: \"absolute\",\n zIndex: 1, // above map\n transitionProperty: \"left, right, top, bottom\",\n transitionDuration: \"200ms\",\n transitionTimingFunction: \"ease-out\",\n overflow: \"hidden\"\n };\n\n const defaultHorizontalGap = 0;\n const horizontal = horizontalGap ?? defaultHorizontalGap;\n\n const defaultVerticalGap = 0;\n const vertical = verticalGap ?? defaultVerticalGap;\n\n const attribution = computeAttributionGap(verticalGap);\n const gap = (paddingProp: string, pixels: number) => `(${paddingProp} + ${pixels}px)`;\n\n interface PosExprs {\n left?: string;\n right?: string;\n top?: string;\n bottom?: string;\n }\n\n // CSS Expressions for inside calc(...)\n const posExprs: PosExprs = {};\n switch (position) {\n case \"top-left\":\n posExprs.left = gap(PADDING_LEFT.ref, horizontal);\n posExprs.top = gap(PADDING_TOP.ref, vertical);\n break;\n case \"top-right\":\n posExprs.right = gap(PADDING_RIGHT.ref, horizontal);\n posExprs.top = gap(PADDING_TOP.ref, vertical);\n break;\n case \"bottom-left\":\n posExprs.left = gap(PADDING_LEFT.ref, horizontal);\n posExprs.bottom = gap(PADDING_BOTTOM.ref, vertical + attribution.gap);\n break;\n case \"bottom-right\":\n posExprs.right = gap(PADDING_RIGHT.ref, horizontal);\n posExprs.bottom = gap(PADDING_BOTTOM.ref, vertical + attribution.gap);\n break;\n }\n\n for (const [key, value] of Object.entries(posExprs)) {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n (styleProps as any)[key] = `calc(${value})`;\n }\n\n /**\n * Apply max-height and max-width to MapAnchor to avoid content overflow\n */\n styleProps.maxH = `calc((100%) - ${defaultValue(posExprs.top, \"0px\")} - ${defaultValue(posExprs.bottom, attribution.gap + \"px\")} - ${vertical}px - ${attribution.space}px)`;\n styleProps.maxW = `calc((100%) - ${defaultValue(posExprs.left, \"0px\")} - ${defaultValue(posExprs.right, \"0px\")} - ${horizontal}px)`;\n return styleProps;\n}\n\nfunction defaultValue(value: string | undefined, defaultValue: string): string {\n return value ?? defaultValue;\n}\n"],"names":["defaultValue"],"mappings":"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"}
package/ui/hooks.d.ts CHANGED
@@ -4,21 +4,31 @@ import { Projection } from "ol/proj";
4
4
  import { Coordinate } from "ol/coordinate";
5
5
  /**
6
6
  * Returns the current view of the given map.
7
+ *
8
+ * @deprecated Use `mapModel.olView` instead.
7
9
  */
8
10
  export declare function useView(map: OlMap | undefined): OlView | undefined;
9
11
  /**
10
12
  * Returns the current projection of the map.
13
+ *
14
+ * @deprecated Use `mapModel.projection` instead.
11
15
  */
12
16
  export declare function useProjection(map: OlMap | undefined): Projection | undefined;
13
17
  /**
14
18
  * Returns the current resolution of the map.
19
+ *
20
+ * @deprecated Use `mapModel.resolution` instead.
15
21
  */
16
22
  export declare function useResolution(map: OlMap | undefined): number | undefined;
17
23
  /**
18
24
  * Returns the current center coordinates of the map.
25
+ *
26
+ * @deprecated Use `mapModel.center` instead.
19
27
  */
20
28
  export declare function useCenter(map: OlMap | undefined): Coordinate | undefined;
21
29
  /**
22
30
  * Returns the current scale of the map.
31
+ *
32
+ * @deprecated Use `mapModel.scale` instead.
23
33
  */
24
34
  export declare function useScale(map: OlMap | undefined): number | undefined;
package/ui/hooks.js.map CHANGED
@@ -1 +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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"}
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 *\n * @deprecated Use `mapModel.olView` instead.\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 *\n * @deprecated Use `mapModel.projection` instead.\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 *\n * @deprecated Use `mapModel.resolution` instead.\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 *\n * @deprecated Use `mapModel.center` instead.\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 *\n * @deprecated Use `mapModel.scale` instead.\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 CHANGED
@@ -1,3 +1,10 @@
1
1
  @import "ol/ol.css";
2
2
 
3
+ /* Move attribution according to map view's padding */
4
+
5
+ .map-container .ol-viewport .ol-attribution {
6
+ bottom: var(--map-padding-bottom);
7
+ right: var(--map-padding-right);
8
+ }
9
+
3
10
  /*# sourceMappingURL=styles.css.map */
package/ui/styles.css.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["styles.css"],"names":[],"mappings":"AAAA,mBAAmB","file":"styles.css","sourcesContent":["@import \"ol/ol.css\";\n"]}
1
+ {"version":3,"sources":["styles.css"],"names":[],"mappings":"AAAA,mBAAmB;;AAEnB,qDAAqD;;AACrD;IACI,iCAAiC;IACjC,+BAA+B;AACnC","file":"styles.css","sourcesContent":["@import \"ol/ol.css\";\n\n/* Move attribution according to map view's padding */\n.map-container .ol-viewport .ol-attribution {\n bottom: var(--map-padding-bottom);\n right: var(--map-padding-right);\n}\n"]}
@@ -1,10 +1,6 @@
1
1
  import { MapModel } from "../api";
2
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;
3
+ export type UseMapModelResult = UseMapModelLoading | UseMapModelResolved | UseMapModelRejected;
8
4
  export interface UseMapModelLoading {
9
5
  kind: "loading";
10
6
  map?: undefined;
@@ -21,7 +17,25 @@ export interface UseMapModelRejected {
21
17
  error: Error;
22
18
  }
23
19
  /**
24
- * React hooks that looks up the map with the given id in the `map.MapRegistry` service.
20
+ * Options that specify which map to use. See {@link useMapModel}.
21
+ *
22
+ * When not setting any of these properties on a component, the default map (from the `DefaultMapProvider`) will be used.
23
+ * If that is not available either, an error will be thrown.
24
+ */
25
+ export interface MapModelProps {
26
+ /**
27
+ * The id of the map.
28
+ * The map will be looked up in the MapRegistry service.
29
+ */
30
+ mapId?: string | undefined;
31
+ /**
32
+ * The direct map model reference to use.
33
+ * This property can be used as an alternative to the {@link mapId}.
34
+ */
35
+ map?: MapModel | undefined;
36
+ }
37
+ /**
38
+ * React hook that looks up the map with the given id in the `map.MapRegistry` service.
25
39
  *
26
40
  * Returns an object representing the progress, which will eventually represent either
27
41
  * the map model value or an initialization error.
@@ -29,3 +43,16 @@ export interface UseMapModelRejected {
29
43
  * The map model cannot be returned directly because it may not have completed its initialization yet.
30
44
  */
31
45
  export declare function useMapModel(mapId: string): UseMapModelResult;
46
+ /**
47
+ * React hook that resolves a map model specified by the given `props` (see {@link MapModelProps}).
48
+ *
49
+ * Returns an object representing the progress, which will eventually represent either
50
+ * the map model value or an initialization error.
51
+ *
52
+ * The map model cannot be returned directly because it may not have completed its initialization yet.
53
+ */
54
+ export declare function useMapModel(props: MapModelProps): UseMapModelResult;
55
+ /**
56
+ * React hook that returns the default map model (if available, see {@link DefaultMapProvider}).
57
+ */
58
+ export declare function useMapModel(): UseMapModelResult;
package/ui/useMapModel.js CHANGED
@@ -1,10 +1,18 @@
1
1
  import { useService } from '../_virtual/_virtual-pioneer-module_react-hooks.js';
2
2
  import { useMemo } from 'react';
3
3
  import { useAsync } from 'react-use';
4
+ import { MapModelImpl } from '../model/MapModelImpl.js';
5
+ import { useDefaultMapProps } from './DefaultMapProvider.js';
4
6
 
5
- function useMapModel(mapId) {
7
+ function useMapModel(props) {
8
+ const resolvedMapArg = useResolvedMapArg(props);
6
9
  const mapRegistry = useService("map.MapRegistry");
7
- const state = useAsync(() => mapRegistry.getMapModel(mapId), [mapRegistry, mapId]);
10
+ const state = useAsync(async () => {
11
+ if (typeof resolvedMapArg === "string") {
12
+ return await mapRegistry.expectMapModel(resolvedMapArg);
13
+ }
14
+ return Promise.resolve(resolvedMapArg);
15
+ }, [mapRegistry, resolvedMapArg]);
8
16
  const result = useMemo(() => {
9
17
  if (state.loading) {
10
18
  return { kind: "loading" };
@@ -16,6 +24,36 @@ function useMapModel(mapId) {
16
24
  }, [state]);
17
25
  return result;
18
26
  }
27
+ function useResolvedMapArg(props) {
28
+ if (typeof props === "object" && props.mapId != null && props.map != null) {
29
+ throw new Error(`Cannot specify both 'mapId' and 'map' in useMapModel at the same time.`);
30
+ }
31
+ if (props instanceof MapModelImpl) {
32
+ throw new Error(
33
+ `Map model instances cannot be passed directly to 'useMapModel' (see TypeScript signature).`
34
+ );
35
+ }
36
+ const localProps = useMemo(() => {
37
+ if (props == null) {
38
+ return {};
39
+ }
40
+ if (typeof props === "string") {
41
+ return { mapId: props };
42
+ }
43
+ return { mapId: props.mapId, map: props.map };
44
+ }, [...typeof props === "string" || props == null ? [props] : [props.mapId, props.map]]);
45
+ const defaultProps = useDefaultMapProps();
46
+ const resolvedMapArg = resolveMap(localProps) ?? resolveMap(defaultProps);
47
+ if (resolvedMapArg == null) {
48
+ throw new Error(
49
+ `No map specified. You must either specify the map (or its id) via a DefaultMapProvider parent or configure it explicitly.`
50
+ );
51
+ }
52
+ return resolvedMapArg;
53
+ }
54
+ function resolveMap(props) {
55
+ return props?.map ?? props?.mapId;
56
+ }
19
57
 
20
58
  export { useMapModel };
21
59
  //# sourceMappingURL=useMapModel.js.map