react-spatial 1.10.1 → 1.10.2-beta.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/README.md CHANGED
@@ -16,7 +16,7 @@ Documentation and examples at https://react-spatial.geops.io.
16
16
  Install the [react-spatial](https://www.npmjs.com/package/react-spatial) package:
17
17
 
18
18
  ```bash
19
- yarn add mobility-toolbox-js mapbox-gl mapblibre-gl ol react-spatial
19
+ yarn add mapblibre-gl ol mobility-toolbox-js react-spatial
20
20
  ```
21
21
 
22
22
  Your build pipeline needs to support ES6 modules and SASS.
@@ -1,11 +1,11 @@
1
1
  import React, { useState, useEffect } from "react";
2
2
  import PropTypes from "prop-types";
3
3
  import { FaChevronLeft } from "react-icons/fa";
4
- import { Layer } from "mobility-toolbox-js/ol";
5
4
  import { unByKey } from "ol/Observable";
5
+ import Layer from "ol/layer/Layer";
6
6
  const propTypes = {
7
7
  /**
8
- * An array of [mobility-toolbox-js layers](https://mobility-toolbox-js.geops.io/api/identifiers%20html#ol-layers).
8
+ * An array of OpenLayers layers
9
9
  */
10
10
  layers: PropTypes.arrayOf(PropTypes.instanceOf(Layer)).isRequired,
11
11
  /**
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/components/BaseLayerSwitcher/BaseLayerSwitcher.js"],
4
- "sourcesContent": ["/* eslint-disable jsx-a11y/interactive-supports-focus */\nimport React, { useState, useEffect } from \"react\";\nimport PropTypes from \"prop-types\";\nimport { FaChevronLeft } from \"react-icons/fa\";\nimport { Layer } from \"mobility-toolbox-js/ol\";\nimport { unByKey } from \"ol/Observable\";\n\nconst propTypes = {\n /**\n * An array of [mobility-toolbox-js layers](https://mobility-toolbox-js.geops.io/api/identifiers%20html#ol-layers).\n */\n layers: PropTypes.arrayOf(PropTypes.instanceOf(Layer)).isRequired,\n\n /**\n * Object containing relative paths to the base layer images. Object\n * keys need to correspond to layer keys\n */\n layerImages: PropTypes.objectOf(PropTypes.string),\n\n /**\n * CSS class to apply on the container.\n */\n className: PropTypes.string,\n\n /**\n * Alternative text rendered if layer images can't be loaded\n */\n altText: PropTypes.string,\n\n /**\n * Button titles.\n */\n titles: PropTypes.shape({\n button: PropTypes.string,\n openSwitcher: PropTypes.string,\n closeSwitcher: PropTypes.string,\n }),\n\n /**\n * Image (node) rendered in the switcher close button.\n */\n closeButtonImage: PropTypes.node,\n\n /**\n * Translation function.\n * @param {function} Translation function returning the translated string.\n */\n t: PropTypes.func,\n};\n\nconst defaultProps = {\n className: \"rs-base-layer-switcher\",\n altText: \"Source not found\",\n titles: {\n button: \"Base layers\",\n openSwitcher: \"Open Baselayer-Switcher\",\n closeSwitcher: \"Close Baselayer-Switcher\",\n },\n closeButtonImage: <FaChevronLeft />,\n layerImages: undefined,\n t: (s) => {\n return s;\n },\n};\n\nconst getVisibleLayer = (layers) => {\n return layers.find((layer) => {\n return layer.visible;\n });\n};\n\nconst getNextImage = (currentLayer, layers, layerImages) => {\n const currentIndex = layers.indexOf(\n layers.find((layer) => {\n return layer === currentLayer;\n }),\n );\n const nextIndex = currentIndex + 1 === layers.length ? 0 : currentIndex + 1;\n return layerImages[nextIndex];\n};\n\nconst getImageStyle = (url) => {\n return url\n ? {\n backgroundImage: `url(${url})`,\n backgroundSize: \"cover\",\n backgroundRepeat: \"no-repeat\",\n backgroundPosition: \"center\",\n }\n : null;\n};\n\n/**\n * The BaseLayerSwitcher component renders a button interface for switching the visible\n * [mobility-toolbox-js layer](https://mobility-toolbox-js.geops.io/api/identifiers%20html#ol-layers)\n * when defined as base layer.\n */\n\nfunction BaseLayerSwitcher({\n layers,\n layerImages,\n className,\n altText,\n titles,\n closeButtonImage,\n t,\n}) {\n const [switcherOpen, setSwitcherOpen] = useState(false);\n const [isClosed, setIsClosed] = useState(true);\n const [currentLayer, setCurrentLayer] = useState(\n getVisibleLayer(layers) || layers[0],\n );\n\n useEffect(() => {\n // Update the layer selected when a visibility changes.\n const olKeys = (layers || []).map((layer) => {\n return layer.on(\"change:visible\", (evt) => {\n if (evt.target.visible && currentLayer !== evt.target) {\n setCurrentLayer(evt.target);\n }\n });\n });\n return () => {\n unByKey(olKeys);\n };\n }, [currentLayer, layers]);\n\n /* Images are loaded from props if provided, fallback from layer */\n const images = layerImages\n ? Object.keys(layerImages).map((layerImage) => {\n return layerImages[layerImage];\n })\n : layers.map((layer) => {\n return layer.get(\"previewImage\");\n });\n\n const openClass = switcherOpen ? \" rs-open\" : \"\";\n const hiddenStyle = switcherOpen && !isClosed ? \"visible\" : \"hidden\";\n\n const handleSwitcherClick = () => {\n if (layers.length === 2) {\n /* On only two layer options the opener becomes a layer toggle button */\n const nextLayer = layers.find((layer) => {\n return !layer.visible;\n });\n if (currentLayer.setVisible) {\n currentLayer.setVisible(false);\n } else {\n currentLayer.visible = false;\n }\n setCurrentLayer(nextLayer);\n if (nextLayer.setVisible) {\n nextLayer.setVisible(true);\n } else {\n nextLayer.visible = true;\n }\n return;\n }\n // eslint-disable-next-line consistent-return\n return setSwitcherOpen(true) && setIsClosed(false);\n };\n\n const onLayerSelect = (layer) => {\n if (!switcherOpen) {\n setSwitcherOpen(true);\n return;\n }\n setCurrentLayer(layer);\n if (layer.setVisible) {\n layer.setVisible(true);\n } else {\n // eslint-disable-next-line no-param-reassign\n layer.visible = true;\n }\n layers\n .filter((l) => {\n return l !== layer;\n })\n .forEach((l) => {\n if (l.setVisible) {\n l.setVisible(false);\n } else {\n // eslint-disable-next-line no-param-reassign\n l.visible = false;\n }\n });\n setSwitcherOpen(false);\n };\n\n /* Get next image for closed button */\n const nextImage = getNextImage(currentLayer, layers, images);\n\n useEffect(() => {\n /* Ensure correct layer is active on app load */\n if (currentLayer !== getVisibleLayer(layers)) {\n setCurrentLayer(getVisibleLayer(layers) || layers[0]);\n }\n }, [currentLayer, layers]);\n\n useEffect(() => {\n /* Used for correct layer image render with animation */\n let timeout;\n if (!switcherOpen) {\n timeout = setTimeout(() => {\n setIsClosed(true);\n }, 200);\n } else {\n timeout = setTimeout(() => {\n setIsClosed(false);\n }, 800);\n }\n return () => {\n return clearTimeout(timeout);\n };\n }, [switcherOpen]);\n\n if (!layers || layers.length < 2 || !currentLayer) {\n return null;\n }\n\n const toggleBtn = (\n <div className=\"rs-base-layer-switcher-btn-wrapper\">\n <div\n className=\"rs-base-layer-switcher-close-btn\"\n role=\"button\"\n onClick={() => {\n return setSwitcherOpen(false);\n }}\n onKeyPress={(e) => {\n return e.which === 13 && setSwitcherOpen(false);\n }}\n tabIndex={switcherOpen ? \"0\" : \"-1\"}\n aria-label={titles.closeSwitcher}\n title={titles.closeSwitcher}\n >\n {closeButtonImage}\n </div>\n </div>\n );\n\n return (\n <div className={`${className}${openClass}`}>\n <div\n className={`rs-base-layer-switcher-button rs-opener${openClass}`}\n role=\"button\"\n title={titles.openSwitcher}\n aria-label={titles.openSwitcher}\n onClick={handleSwitcherClick}\n onKeyPress={(e) => {\n if (e.which === 13) {\n handleSwitcherClick();\n }\n }}\n style={getImageStyle(nextImage)}\n tabIndex=\"0\"\n >\n <div className=\"rs-base-layer-switcher-title\">\n {layers.length !== 2\n ? titles.button\n : layers.find((layer) => {\n return !layer.visible;\n }) &&\n t(\n layers.find((layer) => {\n return !layer.visible;\n }).name,\n )}\n </div>\n {nextImage ? null : <span className=\"rs-alt-text\">{t(altText)}</span>}\n </div>\n {layers.map((layer, idx) => {\n const layerName = layer.name;\n const activeClass = layerName === currentLayer.name ? \" rs-active\" : \"\";\n const imageStyle = getImageStyle(\n layerImages ? layerImages[`${layer.key}`] : layer.get(\"previewImage\"),\n );\n return (\n <div\n key={layer.key}\n className=\"rs-base-layer-switcher-btn-wrapper\"\n style={{\n /* stylelint-disable-next-line value-keyword-case */\n overflow: hiddenStyle,\n /* stylelint-disable-next-line value-keyword-case */\n zIndex: layers.length - idx,\n }}\n >\n <div\n className={`rs-base-layer-switcher-button${openClass}`}\n role=\"button\"\n title={t(layerName)}\n aria-label={t(layerName)}\n onClick={() => {\n return onLayerSelect(layer);\n }}\n onKeyPress={(e) => {\n if (e.which === 13) {\n onLayerSelect(layer);\n }\n }}\n style={imageStyle}\n tabIndex={switcherOpen ? \"0\" : \"-1\"}\n >\n <div className={`rs-base-layer-switcher-title${activeClass}`}>\n {t(layerName)}\n </div>\n {imageStyle ? null : (\n <span className=\"rs-alt-text\">{t(altText)}</span>\n )}\n </div>\n </div>\n );\n })}\n {toggleBtn}\n </div>\n );\n}\n\nBaseLayerSwitcher.propTypes = propTypes;\nBaseLayerSwitcher.defaultProps = defaultProps;\n\nexport default BaseLayerSwitcher;\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["/* eslint-disable jsx-a11y/interactive-supports-focus */\nimport React, { useState, useEffect } from \"react\";\nimport PropTypes from \"prop-types\";\nimport { FaChevronLeft } from \"react-icons/fa\";\nimport { unByKey } from \"ol/Observable\";\nimport Layer from \"ol/layer/Layer\";\n\nconst propTypes = {\n /**\n * An array of OpenLayers layers\n */\n layers: PropTypes.arrayOf(PropTypes.instanceOf(Layer)).isRequired,\n\n /**\n * Object containing relative paths to the base layer images. Object\n * keys need to correspond to layer keys\n */\n layerImages: PropTypes.objectOf(PropTypes.string),\n\n /**\n * CSS class to apply on the container.\n */\n className: PropTypes.string,\n\n /**\n * Alternative text rendered if layer images can't be loaded\n */\n altText: PropTypes.string,\n\n /**\n * Button titles.\n */\n titles: PropTypes.shape({\n button: PropTypes.string,\n openSwitcher: PropTypes.string,\n closeSwitcher: PropTypes.string,\n }),\n\n /**\n * Image (node) rendered in the switcher close button.\n */\n closeButtonImage: PropTypes.node,\n\n /**\n * Translation function.\n * @param {function} Translation function returning the translated string.\n */\n t: PropTypes.func,\n};\n\nconst defaultProps = {\n className: \"rs-base-layer-switcher\",\n altText: \"Source not found\",\n titles: {\n button: \"Base layers\",\n openSwitcher: \"Open Baselayer-Switcher\",\n closeSwitcher: \"Close Baselayer-Switcher\",\n },\n closeButtonImage: <FaChevronLeft />,\n layerImages: undefined,\n t: (s) => {\n return s;\n },\n};\n\nconst getVisibleLayer = (layers) => {\n return layers.find((layer) => {\n return layer.visible;\n });\n};\n\nconst getNextImage = (currentLayer, layers, layerImages) => {\n const currentIndex = layers.indexOf(\n layers.find((layer) => {\n return layer === currentLayer;\n }),\n );\n const nextIndex = currentIndex + 1 === layers.length ? 0 : currentIndex + 1;\n return layerImages[nextIndex];\n};\n\nconst getImageStyle = (url) => {\n return url\n ? {\n backgroundImage: `url(${url})`,\n backgroundSize: \"cover\",\n backgroundRepeat: \"no-repeat\",\n backgroundPosition: \"center\",\n }\n : null;\n};\n\n/**\n * The BaseLayerSwitcher component renders a button interface for switching the visible\n * [mobility-toolbox-js layer](https://mobility-toolbox-js.geops.io/api/identifiers%20html#ol-layers)\n * when defined as base layer.\n */\n\nfunction BaseLayerSwitcher({\n layers,\n layerImages,\n className,\n altText,\n titles,\n closeButtonImage,\n t,\n}) {\n const [switcherOpen, setSwitcherOpen] = useState(false);\n const [isClosed, setIsClosed] = useState(true);\n const [currentLayer, setCurrentLayer] = useState(\n getVisibleLayer(layers) || layers[0],\n );\n\n useEffect(() => {\n // Update the layer selected when a visibility changes.\n const olKeys = (layers || []).map((layer) => {\n return layer.on(\"change:visible\", (evt) => {\n if (evt.target.visible && currentLayer !== evt.target) {\n setCurrentLayer(evt.target);\n }\n });\n });\n return () => {\n unByKey(olKeys);\n };\n }, [currentLayer, layers]);\n\n /* Images are loaded from props if provided, fallback from layer */\n const images = layerImages\n ? Object.keys(layerImages).map((layerImage) => {\n return layerImages[layerImage];\n })\n : layers.map((layer) => {\n return layer.get(\"previewImage\");\n });\n\n const openClass = switcherOpen ? \" rs-open\" : \"\";\n const hiddenStyle = switcherOpen && !isClosed ? \"visible\" : \"hidden\";\n\n const handleSwitcherClick = () => {\n if (layers.length === 2) {\n /* On only two layer options the opener becomes a layer toggle button */\n const nextLayer = layers.find((layer) => {\n return !layer.visible;\n });\n if (currentLayer.setVisible) {\n currentLayer.setVisible(false);\n } else {\n currentLayer.visible = false;\n }\n setCurrentLayer(nextLayer);\n if (nextLayer.setVisible) {\n nextLayer.setVisible(true);\n } else {\n nextLayer.visible = true;\n }\n return;\n }\n // eslint-disable-next-line consistent-return\n return setSwitcherOpen(true) && setIsClosed(false);\n };\n\n const onLayerSelect = (layer) => {\n if (!switcherOpen) {\n setSwitcherOpen(true);\n return;\n }\n setCurrentLayer(layer);\n if (layer.setVisible) {\n layer.setVisible(true);\n } else {\n // eslint-disable-next-line no-param-reassign\n layer.visible = true;\n }\n layers\n .filter((l) => {\n return l !== layer;\n })\n .forEach((l) => {\n if (l.setVisible) {\n l.setVisible(false);\n } else {\n // eslint-disable-next-line no-param-reassign\n l.visible = false;\n }\n });\n setSwitcherOpen(false);\n };\n\n /* Get next image for closed button */\n const nextImage = getNextImage(currentLayer, layers, images);\n\n useEffect(() => {\n /* Ensure correct layer is active on app load */\n if (currentLayer !== getVisibleLayer(layers)) {\n setCurrentLayer(getVisibleLayer(layers) || layers[0]);\n }\n }, [currentLayer, layers]);\n\n useEffect(() => {\n /* Used for correct layer image render with animation */\n let timeout;\n if (!switcherOpen) {\n timeout = setTimeout(() => {\n setIsClosed(true);\n }, 200);\n } else {\n timeout = setTimeout(() => {\n setIsClosed(false);\n }, 800);\n }\n return () => {\n return clearTimeout(timeout);\n };\n }, [switcherOpen]);\n\n if (!layers || layers.length < 2 || !currentLayer) {\n return null;\n }\n\n const toggleBtn = (\n <div className=\"rs-base-layer-switcher-btn-wrapper\">\n <div\n className=\"rs-base-layer-switcher-close-btn\"\n role=\"button\"\n onClick={() => {\n return setSwitcherOpen(false);\n }}\n onKeyPress={(e) => {\n return e.which === 13 && setSwitcherOpen(false);\n }}\n tabIndex={switcherOpen ? \"0\" : \"-1\"}\n aria-label={titles.closeSwitcher}\n title={titles.closeSwitcher}\n >\n {closeButtonImage}\n </div>\n </div>\n );\n\n return (\n <div className={`${className}${openClass}`}>\n <div\n className={`rs-base-layer-switcher-button rs-opener${openClass}`}\n role=\"button\"\n title={titles.openSwitcher}\n aria-label={titles.openSwitcher}\n onClick={handleSwitcherClick}\n onKeyPress={(e) => {\n if (e.which === 13) {\n handleSwitcherClick();\n }\n }}\n style={getImageStyle(nextImage)}\n tabIndex=\"0\"\n >\n <div className=\"rs-base-layer-switcher-title\">\n {layers.length !== 2\n ? titles.button\n : layers.find((layer) => {\n return !layer.visible;\n }) &&\n t(\n layers.find((layer) => {\n return !layer.visible;\n }).name,\n )}\n </div>\n {nextImage ? null : <span className=\"rs-alt-text\">{t(altText)}</span>}\n </div>\n {layers.map((layer, idx) => {\n const layerName = layer.name;\n const activeClass = layerName === currentLayer.name ? \" rs-active\" : \"\";\n const imageStyle = getImageStyle(\n layerImages ? layerImages[`${layer.key}`] : layer.get(\"previewImage\"),\n );\n return (\n <div\n key={layer.key}\n className=\"rs-base-layer-switcher-btn-wrapper\"\n style={{\n /* stylelint-disable-next-line value-keyword-case */\n overflow: hiddenStyle,\n /* stylelint-disable-next-line value-keyword-case */\n zIndex: layers.length - idx,\n }}\n >\n <div\n className={`rs-base-layer-switcher-button${openClass}`}\n role=\"button\"\n title={t(layerName)}\n aria-label={t(layerName)}\n onClick={() => {\n return onLayerSelect(layer);\n }}\n onKeyPress={(e) => {\n if (e.which === 13) {\n onLayerSelect(layer);\n }\n }}\n style={imageStyle}\n tabIndex={switcherOpen ? \"0\" : \"-1\"}\n >\n <div className={`rs-base-layer-switcher-title${activeClass}`}>\n {t(layerName)}\n </div>\n {imageStyle ? null : (\n <span className=\"rs-alt-text\">{t(altText)}</span>\n )}\n </div>\n </div>\n );\n })}\n {toggleBtn}\n </div>\n );\n}\n\nBaseLayerSwitcher.propTypes = propTypes;\nBaseLayerSwitcher.defaultProps = defaultProps;\n\nexport default BaseLayerSwitcher;\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -7,7 +7,7 @@ import OLCollection from "ol/Collection";
7
7
  import View from "ol/View";
8
8
  import { unByKey } from "ol/Observable";
9
9
  import Interaction from "ol/interaction/Interaction";
10
- import { Layer } from "mobility-toolbox-js/ol";
10
+ import Layer from "ol/layer/Layer";
11
11
  const propTypes = {
12
12
  /** Map animation options */
13
13
  animationOptions: PropTypes.shape({
@@ -224,33 +224,21 @@ class BasicMap extends PureComponent {
224
224
  }
225
225
  }
226
226
  initLayer(layer) {
227
- if (layer.attachToMap) {
228
- layer.attachToMap(this.map);
227
+ if (!this.map?.getLayers()?.getArray()?.includes(layer)) {
228
+ this.map.addLayer(layer);
229
229
  }
230
- if (layer.init) {
231
- layer.init(this.map);
232
- }
233
- if (layer.olLayer && this.map.getLayers() && !this.map.getLayers().getArray().includes(layer.olLayer)) {
234
- this.map.addLayer(layer.olLayer);
235
- }
236
- const layers = layer.children || [];
230
+ const layers = layer.children || layer.get("children") || [];
237
231
  for (let i = 0; i < layers.length; i += 1) {
238
232
  this.initLayer(layers[i]);
239
233
  }
240
234
  }
241
235
  terminateLayer(layer) {
242
- const layers = layer.children || [];
236
+ const layers = layer.children || layer.get("children") || [];
243
237
  for (let i = 0; i < layers.length; i += 1) {
244
238
  this.terminateLayer(layers[i]);
245
239
  }
246
- if (layer.olLayer && this.map.getLayers() && this.map.getLayers().getArray().includes(layer.olLayer)) {
247
- this.map.removeLayer(layer.olLayer);
248
- }
249
- if (layer.terminate) {
250
- layer.terminate(this.map);
251
- }
252
- if (layer.detachFromMap) {
253
- layer.detachFromMap(this.map);
240
+ if (this.map?.getLayers()?.getArray()?.includes(layer)) {
241
+ this.map.removeLayer(layer);
254
242
  }
255
243
  }
256
244
  listenMoveEnd() {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/components/BasicMap/BasicMap.js"],
4
- "sourcesContent": ["import React, { PureComponent } from \"react\";\nimport PropTypes from \"prop-types\";\nimport { defaults as defaultInteractions } from \"ol/interaction\";\nimport { equals } from \"ol/extent\";\nimport OLMap from \"ol/Map\";\nimport OLCollection from \"ol/Collection\";\nimport View from \"ol/View\";\nimport { unByKey } from \"ol/Observable\";\nimport Interaction from \"ol/interaction/Interaction\";\nimport { Layer } from \"mobility-toolbox-js/ol\";\n\nconst propTypes = {\n /** Map animation options */\n animationOptions: PropTypes.shape({\n center: PropTypes.arrayOf(PropTypes.number),\n resolution: PropTypes.number,\n zoom: PropTypes.number,\n }),\n\n /** Center of the [ol/View](https://openlayers.org/en/latest/apidoc/module-ol_View-View.html). */\n center: PropTypes.arrayOf(PropTypes.number),\n\n /** Class name of the map container */\n className: PropTypes.string,\n\n /** Map extent */\n extent: PropTypes.arrayOf(PropTypes.number),\n\n /** Openlayers [fit options](https://openlayers.org/en/latest/apidoc/module-ol_View-View.html#fit) when extent is updated */\n fitOptions: PropTypes.object,\n\n /** Array of [ol/interaction](https://openlayers.org/en/latest/apidoc/module-ol_interaction_Interaction-Interaction.html). */\n interactions: PropTypes.oneOfType([\n PropTypes.arrayOf(PropTypes.instanceOf(Interaction)),\n PropTypes.instanceOf(OLCollection),\n ]),\n\n /** Array of [mobility-toolbox-js layers](https://mobility-toolbox-js.geops.io/api/identifiers%20html#ol-layers) to display. */\n layers: PropTypes.arrayOf(PropTypes.instanceOf(Layer)),\n\n /** An [ol/map](https://openlayers.org/en/latest/apidoc/module-ol_Map-Map.html). */\n map: PropTypes.instanceOf(OLMap),\n\n /**\n * Callback when a [ol/Feature](https://openlayers.org/en/latest/apidoc/module-ol_Feature-Feature.html) is clicked.\n * @param {OLFeature[]} features An array of [ol/Feature](https://openlayers.org/en/latest/apidoc/module-ol_Feature-Feature.html).\n * @param {ol.MapBrowserEvent} event The singleclick [ol/MapBrowserEvent](https://openlayers.org/en/latest/apidoc/module-ol_MapBrowserEvent-MapBrowserEvent.html#event:singleclick).\n */\n onFeaturesClick: PropTypes.func,\n\n /**\n * Optional options to pass on feature click. Passed to ol's 'getFeaturesAtPixel' method.\n * https://openlayers.org/en/latest/apidoc/module-ol_Map-Map.html#getFeaturesAtPixel\n */\n featuresClickOptions: PropTypes.shape({\n layerFilter: PropTypes.func,\n hitTolerance: PropTypes.number,\n checkWrapped: PropTypes.bool,\n }),\n\n /**\n * Callback when a [ol/Feature](https://openlayers.org/en/latest/apidoc/module-ol_Feature-Feature.html) is hovered.\n * @param {OLFeature[]} features An array of [ol/Feature](https://openlayers.org/en/latest/apidoc/module-ol_Feature-Feature.html).\n * @param {ol.MapBrowserEvent} event The pointermove [ol/MapBrowserEvent](https://openlayers.org/en/latest/apidoc/module-ol_MapBrowserEvent-MapBrowserEvent.html#event:pointermove).\n */\n onFeaturesHover: PropTypes.func,\n\n /**\n * Callback when the map was moved.\n * @param {ol.MapEvent} event The movend [ol/MapEvent](https://openlayers.org/en/latest/apidoc/module-ol_MapBrowserEvent-MapBrowserEvent.html#event:moveend).\n */\n onMapMoved: PropTypes.func,\n\n /** Map resolution */\n resolution: PropTypes.number,\n\n /** The tabIndex of the map. */\n tabIndex: PropTypes.number,\n\n /** The style of the map. */\n style: PropTypes.object,\n\n /** HTML aria-label. */\n ariaLabel: PropTypes.string,\n\n /** [ol/View](https://openlayers.org/en/latest/apidoc/module-ol_View-View.html) constructor options */\n viewOptions: PropTypes.shape({\n minZoom: PropTypes.number,\n maxZoom: PropTypes.number,\n extent: PropTypes.array,\n projection: PropTypes.string,\n }),\n\n /** Map zoom level */\n zoom: PropTypes.number,\n};\n\nconst defaultProps = {\n animationOptions: undefined,\n center: [0, 0],\n className: \"rs-map\",\n extent: undefined,\n fitOptions: {\n duration: 1000,\n padding: [20, 20, 20, 20],\n maxZoom: 23,\n },\n style: undefined,\n interactions: null,\n layers: [],\n map: null,\n onFeaturesClick: undefined,\n featuresClickOptions: {\n hitTolerance: 0,\n },\n onFeaturesHover: undefined,\n onMapMoved: undefined,\n resolution: undefined,\n tabIndex: undefined,\n ariaLabel: \"map\",\n viewOptions: {\n minZoom: 0,\n maxZoom: 22,\n extent: undefined,\n projection: \"EPSG:3857\",\n },\n zoom: 1,\n};\n\n/**\n * The BasicMap component renders an [ol/map](https://openlayers.org/en/latest/apidoc/module-ol_Map-Map.html).\n *\n * The map's view is created with the following parameters for the view:\n * - projection: 'EPSG:3857'\n * - zoom: 0\n * - minZoom: 0\n * - maxZoom: 22\n *\n * These options can be overridden using the viewOptions property.\n */\nclass BasicMap extends PureComponent {\n constructor(props) {\n super(props);\n const { map, interactions } = this.props;\n\n this.map =\n map ||\n new OLMap({\n controls: [],\n interactions:\n interactions ||\n defaultInteractions({\n altShiftDragRotate: false,\n pinchRotate: false,\n }),\n });\n\n this.state = {\n node: null,\n };\n\n this.moveEndRef = null;\n this.singleClickRef = null;\n this.pointerMoveRef = null;\n this.setNode = this.setNode.bind(this);\n }\n\n componentDidMount() {\n const { layers, extent, viewOptions, center, zoom, resolution } =\n this.props;\n const { node } = this.state;\n this.map.setTarget(node);\n\n // We set the view here otherwise the map is not correctly zoomed.\n this.map.setView(new View({ ...viewOptions, center, zoom, resolution }));\n\n // // Since ol 6.1.0 touch-action is set to auto and creates a bad navigation experience on mobile,\n // // so we have to force it to none for mobile.\n // // https://github.com/openlayers/openlayers/pull/10187/files\n const viewPort = this.map.getViewport();\n viewPort.style.touchAction = \"none\";\n viewPort.style.msTouchAction = \"none\";\n viewPort.setAttribute(\"touch-action\", \"none\");\n\n // Fit only work if the map has a size.\n if (this.map.getSize() && extent) {\n this.map.getView().fit(extent);\n }\n\n this.setLayers(layers);\n this.listenMoveEnd();\n this.listenSingleClick();\n this.listenPointerMove();\n }\n\n componentDidUpdate(prevProps, prevState) {\n const {\n animationOptions,\n center,\n extent,\n fitOptions,\n layers,\n resolution,\n viewOptions,\n zoom,\n onMapMoved,\n onFeaturesClick,\n onFeaturesHover,\n } = this.props;\n const { node } = this.state;\n\n if (prevState.node !== node) {\n if (zoom) {\n this.map.getView().setZoom(zoom);\n }\n\n if (resolution) {\n this.map.getView().setResolution(resolution);\n }\n this.map.setTarget(node);\n\n // When the node is set we reinitialize the extent with the extent property.\n if (!prevState.node && node && extent) {\n this.map.getView().fit(extent);\n }\n }\n\n if (prevProps.layers !== layers) {\n this.setLayers(layers, prevProps.layers);\n }\n\n // Creates a new view if necessary before updating the others prop.\n if (\n viewOptions &&\n JSON.stringify(viewOptions) !== JSON.stringify(prevProps.viewOptions)\n ) {\n // Re-create a view, ol doesn't provide any method to setExtent of view.\n this.map.setView(\n new View({\n ...viewOptions,\n center,\n resolution,\n zoom,\n }),\n );\n }\n\n const view = this.map.getView();\n\n if (animationOptions && prevProps.animationOptions !== animationOptions) {\n view.animate(animationOptions);\n }\n\n if (prevProps.center !== center) {\n view.setCenter(center);\n }\n\n if (zoom !== prevProps.zoom) {\n view.setZoom(zoom);\n }\n\n if (resolution !== prevProps.resolution) {\n view.setResolution(resolution);\n }\n\n if (extent && !equals(extent, prevProps.extent || [])) {\n view.fit(extent, fitOptions);\n }\n\n if (onMapMoved !== prevProps.onMapMoved) {\n this.listenMoveEnd();\n }\n\n if (onFeaturesClick !== prevProps.onFeaturesClick) {\n this.listenSingleClick();\n }\n\n if (onFeaturesHover !== prevProps.onFeaturesHover) {\n this.listenPointerMove();\n }\n }\n\n componentWillUnmount() {\n unByKey([this.moveEndRef, this.singleClickRef, this.pointerMoveRef]);\n }\n\n setNode(node) {\n this.setState({ node });\n }\n\n setLayers(layers = [], prevLayers = []) {\n for (let i = 0; i < prevLayers.length; i += 1) {\n this.terminateLayer(prevLayers[i]);\n }\n for (let i = 0; i < layers.length; i += 1) {\n this.initLayer(layers[i]);\n }\n }\n\n initLayer(layer) {\n if (layer.attachToMap) {\n layer.attachToMap(this.map);\n }\n\n if (layer.init) {\n layer.init(this.map);\n }\n\n if (\n layer.olLayer &&\n this.map.getLayers() &&\n !this.map.getLayers().getArray().includes(layer.olLayer)\n ) {\n this.map.addLayer(layer.olLayer);\n }\n const layers = layer.children || [];\n for (let i = 0; i < layers.length; i += 1) {\n this.initLayer(layers[i]);\n }\n }\n\n terminateLayer(layer) {\n const layers = layer.children || [];\n for (let i = 0; i < layers.length; i += 1) {\n this.terminateLayer(layers[i]);\n }\n\n if (\n layer.olLayer &&\n this.map.getLayers() &&\n this.map.getLayers().getArray().includes(layer.olLayer)\n ) {\n this.map.removeLayer(layer.olLayer);\n }\n\n if (layer.terminate) {\n layer.terminate(this.map);\n }\n\n if (layer.detachFromMap) {\n layer.detachFromMap(this.map);\n }\n }\n\n listenMoveEnd() {\n const { onMapMoved } = this.props;\n unByKey(this.moveEndRef);\n\n if (!onMapMoved) {\n return;\n }\n\n this.moveEndRef = this.map.on(\"moveend\", (evt) => {\n return onMapMoved(evt);\n });\n }\n\n listenSingleClick() {\n const { onFeaturesClick, featuresClickOptions } = this.props;\n unByKey(this.singleClickRef);\n\n if (!onFeaturesClick) {\n return;\n }\n\n this.singleClickRef = this.map.on(\"singleclick\", (evt) => {\n const features = evt.map.getFeaturesAtPixel(\n evt.pixel,\n featuresClickOptions,\n );\n onFeaturesClick(features || [], evt);\n });\n }\n\n listenPointerMove() {\n const { onFeaturesHover } = this.props;\n unByKey(this.pointerMoveRef);\n\n if (!onFeaturesHover) {\n return;\n }\n\n this.pointerMoveRef = this.map.on(\"pointermove\", (evt) => {\n const features = evt.map.getFeaturesAtPixel(evt.pixel);\n onFeaturesHover(features || [], evt);\n });\n }\n\n render() {\n const { className, tabIndex, ariaLabel, style } = this.props;\n return (\n <div\n className={className}\n ref={this.setNode}\n role=\"presentation\"\n aria-label={ariaLabel}\n tabIndex={tabIndex}\n style={style}\n />\n );\n }\n}\n\nBasicMap.propTypes = propTypes;\nBasicMap.defaultProps = defaultProps;\n\nexport default BasicMap;\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import React, { PureComponent } from \"react\";\nimport PropTypes from \"prop-types\";\nimport { defaults as defaultInteractions } from \"ol/interaction\";\nimport { equals } from \"ol/extent\";\nimport OLMap from \"ol/Map\";\nimport OLCollection from \"ol/Collection\";\nimport View from \"ol/View\";\nimport { unByKey } from \"ol/Observable\";\nimport Interaction from \"ol/interaction/Interaction\";\nimport Layer from \"ol/layer/Layer\";\n\nconst propTypes = {\n /** Map animation options */\n animationOptions: PropTypes.shape({\n center: PropTypes.arrayOf(PropTypes.number),\n resolution: PropTypes.number,\n zoom: PropTypes.number,\n }),\n\n /** Center of the [ol/View](https://openlayers.org/en/latest/apidoc/module-ol_View-View.html). */\n center: PropTypes.arrayOf(PropTypes.number),\n\n /** Class name of the map container */\n className: PropTypes.string,\n\n /** Map extent */\n extent: PropTypes.arrayOf(PropTypes.number),\n\n /** Openlayers [fit options](https://openlayers.org/en/latest/apidoc/module-ol_View-View.html#fit) when extent is updated */\n fitOptions: PropTypes.object,\n\n /** Array of [ol/interaction](https://openlayers.org/en/latest/apidoc/module-ol_interaction_Interaction-Interaction.html). */\n interactions: PropTypes.oneOfType([\n PropTypes.arrayOf(PropTypes.instanceOf(Interaction)),\n PropTypes.instanceOf(OLCollection),\n ]),\n\n /** Array of [mobility-toolbox-js layers](https://mobility-toolbox-js.geops.io/api/identifiers%20html#ol-layers) to display. */\n layers: PropTypes.arrayOf(PropTypes.instanceOf(Layer)),\n\n /** An [ol/map](https://openlayers.org/en/latest/apidoc/module-ol_Map-Map.html). */\n map: PropTypes.instanceOf(OLMap),\n\n /**\n * Callback when a [ol/Feature](https://openlayers.org/en/latest/apidoc/module-ol_Feature-Feature.html) is clicked.\n * @param {OLFeature[]} features An array of [ol/Feature](https://openlayers.org/en/latest/apidoc/module-ol_Feature-Feature.html).\n * @param {ol.MapBrowserEvent} event The singleclick [ol/MapBrowserEvent](https://openlayers.org/en/latest/apidoc/module-ol_MapBrowserEvent-MapBrowserEvent.html#event:singleclick).\n */\n onFeaturesClick: PropTypes.func,\n\n /**\n * Optional options to pass on feature click. Passed to ol's 'getFeaturesAtPixel' method.\n * https://openlayers.org/en/latest/apidoc/module-ol_Map-Map.html#getFeaturesAtPixel\n */\n featuresClickOptions: PropTypes.shape({\n layerFilter: PropTypes.func,\n hitTolerance: PropTypes.number,\n checkWrapped: PropTypes.bool,\n }),\n\n /**\n * Callback when a [ol/Feature](https://openlayers.org/en/latest/apidoc/module-ol_Feature-Feature.html) is hovered.\n * @param {OLFeature[]} features An array of [ol/Feature](https://openlayers.org/en/latest/apidoc/module-ol_Feature-Feature.html).\n * @param {ol.MapBrowserEvent} event The pointermove [ol/MapBrowserEvent](https://openlayers.org/en/latest/apidoc/module-ol_MapBrowserEvent-MapBrowserEvent.html#event:pointermove).\n */\n onFeaturesHover: PropTypes.func,\n\n /**\n * Callback when the map was moved.\n * @param {ol.MapEvent} event The movend [ol/MapEvent](https://openlayers.org/en/latest/apidoc/module-ol_MapBrowserEvent-MapBrowserEvent.html#event:moveend).\n */\n onMapMoved: PropTypes.func,\n\n /** Map resolution */\n resolution: PropTypes.number,\n\n /** The tabIndex of the map. */\n tabIndex: PropTypes.number,\n\n /** The style of the map. */\n style: PropTypes.object,\n\n /** HTML aria-label. */\n ariaLabel: PropTypes.string,\n\n /** [ol/View](https://openlayers.org/en/latest/apidoc/module-ol_View-View.html) constructor options */\n viewOptions: PropTypes.shape({\n minZoom: PropTypes.number,\n maxZoom: PropTypes.number,\n extent: PropTypes.array,\n projection: PropTypes.string,\n }),\n\n /** Map zoom level */\n zoom: PropTypes.number,\n};\n\nconst defaultProps = {\n animationOptions: undefined,\n center: [0, 0],\n className: \"rs-map\",\n extent: undefined,\n fitOptions: {\n duration: 1000,\n padding: [20, 20, 20, 20],\n maxZoom: 23,\n },\n style: undefined,\n interactions: null,\n layers: [],\n map: null,\n onFeaturesClick: undefined,\n featuresClickOptions: {\n hitTolerance: 0,\n },\n onFeaturesHover: undefined,\n onMapMoved: undefined,\n resolution: undefined,\n tabIndex: undefined,\n ariaLabel: \"map\",\n viewOptions: {\n minZoom: 0,\n maxZoom: 22,\n extent: undefined,\n projection: \"EPSG:3857\",\n },\n zoom: 1,\n};\n\n/**\n * The BasicMap component renders an [ol/map](https://openlayers.org/en/latest/apidoc/module-ol_Map-Map.html).\n *\n * The map's view is created with the following parameters for the view:\n * - projection: 'EPSG:3857'\n * - zoom: 0\n * - minZoom: 0\n * - maxZoom: 22\n *\n * These options can be overridden using the viewOptions property.\n */\nclass BasicMap extends PureComponent {\n constructor(props) {\n super(props);\n const { map, interactions } = this.props;\n\n this.map =\n map ||\n new OLMap({\n controls: [],\n interactions:\n interactions ||\n defaultInteractions({\n altShiftDragRotate: false,\n pinchRotate: false,\n }),\n });\n\n this.state = {\n node: null,\n };\n\n this.moveEndRef = null;\n this.singleClickRef = null;\n this.pointerMoveRef = null;\n this.setNode = this.setNode.bind(this);\n }\n\n componentDidMount() {\n const { layers, extent, viewOptions, center, zoom, resolution } =\n this.props;\n const { node } = this.state;\n this.map.setTarget(node);\n\n // We set the view here otherwise the map is not correctly zoomed.\n this.map.setView(new View({ ...viewOptions, center, zoom, resolution }));\n\n // // Since ol 6.1.0 touch-action is set to auto and creates a bad navigation experience on mobile,\n // // so we have to force it to none for mobile.\n // // https://github.com/openlayers/openlayers/pull/10187/files\n const viewPort = this.map.getViewport();\n viewPort.style.touchAction = \"none\";\n viewPort.style.msTouchAction = \"none\";\n viewPort.setAttribute(\"touch-action\", \"none\");\n\n // Fit only work if the map has a size.\n if (this.map.getSize() && extent) {\n this.map.getView().fit(extent);\n }\n\n this.setLayers(layers);\n this.listenMoveEnd();\n this.listenSingleClick();\n this.listenPointerMove();\n }\n\n componentDidUpdate(prevProps, prevState) {\n const {\n animationOptions,\n center,\n extent,\n fitOptions,\n layers,\n resolution,\n viewOptions,\n zoom,\n onMapMoved,\n onFeaturesClick,\n onFeaturesHover,\n } = this.props;\n const { node } = this.state;\n\n if (prevState.node !== node) {\n if (zoom) {\n this.map.getView().setZoom(zoom);\n }\n\n if (resolution) {\n this.map.getView().setResolution(resolution);\n }\n this.map.setTarget(node);\n\n // When the node is set we reinitialize the extent with the extent property.\n if (!prevState.node && node && extent) {\n this.map.getView().fit(extent);\n }\n }\n\n if (prevProps.layers !== layers) {\n this.setLayers(layers, prevProps.layers);\n }\n\n // Creates a new view if necessary before updating the others prop.\n if (\n viewOptions &&\n JSON.stringify(viewOptions) !== JSON.stringify(prevProps.viewOptions)\n ) {\n // Re-create a view, ol doesn't provide any method to setExtent of view.\n this.map.setView(\n new View({\n ...viewOptions,\n center,\n resolution,\n zoom,\n }),\n );\n }\n\n const view = this.map.getView();\n\n if (animationOptions && prevProps.animationOptions !== animationOptions) {\n view.animate(animationOptions);\n }\n\n if (prevProps.center !== center) {\n view.setCenter(center);\n }\n\n if (zoom !== prevProps.zoom) {\n view.setZoom(zoom);\n }\n\n if (resolution !== prevProps.resolution) {\n view.setResolution(resolution);\n }\n\n if (extent && !equals(extent, prevProps.extent || [])) {\n view.fit(extent, fitOptions);\n }\n\n if (onMapMoved !== prevProps.onMapMoved) {\n this.listenMoveEnd();\n }\n\n if (onFeaturesClick !== prevProps.onFeaturesClick) {\n this.listenSingleClick();\n }\n\n if (onFeaturesHover !== prevProps.onFeaturesHover) {\n this.listenPointerMove();\n }\n }\n\n componentWillUnmount() {\n unByKey([this.moveEndRef, this.singleClickRef, this.pointerMoveRef]);\n }\n\n setNode(node) {\n this.setState({ node });\n }\n\n setLayers(layers = [], prevLayers = []) {\n for (let i = 0; i < prevLayers.length; i += 1) {\n this.terminateLayer(prevLayers[i]);\n }\n for (let i = 0; i < layers.length; i += 1) {\n this.initLayer(layers[i]);\n }\n }\n\n initLayer(layer) {\n if (!this.map?.getLayers()?.getArray()?.includes(layer)) {\n this.map.addLayer(layer);\n }\n\n const layers = layer.children || layer.get(\"children\") || [];\n for (let i = 0; i < layers.length; i += 1) {\n this.initLayer(layers[i]);\n }\n }\n\n terminateLayer(layer) {\n const layers = layer.children || layer.get(\"children\") || [];\n for (let i = 0; i < layers.length; i += 1) {\n this.terminateLayer(layers[i]);\n }\n\n if (this.map?.getLayers()?.getArray()?.includes(layer)) {\n this.map.removeLayer(layer);\n }\n }\n\n listenMoveEnd() {\n const { onMapMoved } = this.props;\n unByKey(this.moveEndRef);\n\n if (!onMapMoved) {\n return;\n }\n\n this.moveEndRef = this.map.on(\"moveend\", (evt) => {\n return onMapMoved(evt);\n });\n }\n\n listenSingleClick() {\n const { onFeaturesClick, featuresClickOptions } = this.props;\n unByKey(this.singleClickRef);\n\n if (!onFeaturesClick) {\n return;\n }\n\n this.singleClickRef = this.map.on(\"singleclick\", (evt) => {\n const features = evt.map.getFeaturesAtPixel(\n evt.pixel,\n featuresClickOptions,\n );\n onFeaturesClick(features || [], evt);\n });\n }\n\n listenPointerMove() {\n const { onFeaturesHover } = this.props;\n unByKey(this.pointerMoveRef);\n\n if (!onFeaturesHover) {\n return;\n }\n\n this.pointerMoveRef = this.map.on(\"pointermove\", (evt) => {\n const features = evt.map.getFeaturesAtPixel(evt.pixel);\n onFeaturesHover(features || [], evt);\n });\n }\n\n render() {\n const { className, tabIndex, ariaLabel, style } = this.props;\n return (\n <div\n className={className}\n ref={this.setNode}\n role=\"presentation\"\n aria-label={ariaLabel}\n tabIndex={tabIndex}\n style={style}\n />\n );\n }\n}\n\nBasicMap.propTypes = propTypes;\nBasicMap.defaultProps = defaultProps;\n\nexport default BasicMap;\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -24,43 +24,32 @@ const defaultProps = {
24
24
  className: "rs-copyright"
25
25
  };
26
26
  function Copyright({ map, format, ...other }) {
27
- const [copyrights, setCopyrights] = useState([]);
28
- const control = useMemo(
29
- () => {
30
- return new CopyrightControl({
31
- target: document.createElement("div"),
32
- element: document.createElement("div"),
33
- render() {
34
- const newCopyrights = this.getCopyrights();
35
- if (copyrights.toString() !== newCopyrights.toString()) {
36
- setCopyrights(newCopyrights);
37
- }
38
- }
39
- });
40
- },
41
- // eslint-disable-next-line react-hooks/exhaustive-deps
42
- []
43
- );
27
+ const [node, setNode] = useState(null);
28
+ const control = useMemo(() => {
29
+ if (!node) {
30
+ return null;
31
+ }
32
+ return new CopyrightControl({
33
+ target: node,
34
+ element: document.createElement("div"),
35
+ format
36
+ });
37
+ }, [node, format]);
44
38
  useEffect(() => {
45
39
  if (!control) {
46
40
  return () => {
47
41
  };
48
42
  }
49
- control.map = map;
43
+ map.addControl(control);
50
44
  return () => {
51
- control.map = null;
45
+ map.removeControl(control);
52
46
  };
53
47
  }, [map, control]);
54
- if (!control || !control.getCopyrights().length) {
55
- return null;
56
- }
57
48
  return /* @__PURE__ */ React.createElement(
58
49
  "div",
59
50
  {
60
- ...other,
61
- dangerouslySetInnerHTML: {
62
- __html: format(copyrights) || ""
63
- }
51
+ ref: (nod) => setNode(nod),
52
+ ...other
64
53
  }
65
54
  );
66
55
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/components/Copyright/Copyright.js"],
4
- "sourcesContent": ["import React, { useMemo, useEffect, useState } from \"react\";\nimport PropTypes from \"prop-types\";\nimport { Map } from \"ol\";\nimport { CopyrightControl } from \"mobility-toolbox-js/ol\";\n\nconst propTypes = {\n /**\n * A map.\n */\n map: PropTypes.instanceOf(Map).isRequired,\n\n /**\n * Format function. Called with an array of copyrights from visible layers\n * and returns the copyright.\n */\n format: PropTypes.func,\n\n /**\n * CSS class of th root element\n */\n className: PropTypes.string,\n};\n\nconst defaultProps = {\n format: (copyrights) => {\n return copyrights.join(\" | \");\n },\n className: \"rs-copyright\",\n};\n\n/**\n * The Copyright component uses the\n * [mobility-toolbox-js CopyrightControl](https://mobility-toolbox-js.geops.io/api/class/src/mapbox/controls/CopyrightControl%20js~CopyrightControl%20html-offset-anchor)\n * to render the layer copyrights.\n */\nfunction Copyright({ map, format, ...other }) {\n const [copyrights, setCopyrights] = useState([]);\n\n const control = useMemo(\n () => {\n return new CopyrightControl({\n target: document.createElement(\"div\"),\n element: document.createElement(\"div\"),\n render() {\n // eslint-disable-next-line react/no-this-in-sfc\n const newCopyrights = this.getCopyrights();\n if (copyrights.toString() !== newCopyrights.toString()) {\n setCopyrights(newCopyrights);\n }\n },\n });\n },\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [],\n );\n\n // Ensure the control is not associated to the wrong map\n useEffect(() => {\n if (!control) {\n return () => {};\n }\n\n control.map = map;\n\n return () => {\n control.map = null;\n };\n }, [map, control]);\n\n if (!control || !control.getCopyrights().length) {\n return null;\n }\n\n return (\n <div\n // eslint-disable-next-line react/jsx-props-no-spreading\n {...other}\n // eslint-disable-next-line react/no-danger\n dangerouslySetInnerHTML={{\n __html: format(copyrights) || \"\",\n }}\n />\n );\n}\n\nCopyright.propTypes = propTypes;\nCopyright.defaultProps = defaultProps;\n\nexport default React.memo(Copyright);\n"],
5
- "mappings": "AAAA,OAAO,SAAS,SAAS,WAAW,gBAAgB;AACpD,OAAO,eAAe;AACtB,SAAS,WAAW;AACpB,SAAS,wBAAwB;AAEjC,MAAM,YAAY;AAAA;AAAA;AAAA;AAAA,EAIhB,KAAK,UAAU,WAAW,GAAG,EAAE;AAAA;AAAA;AAAA;AAAA;AAAA,EAM/B,QAAQ,UAAU;AAAA;AAAA;AAAA;AAAA,EAKlB,WAAW,UAAU;AACvB;AAEA,MAAM,eAAe;AAAA,EACnB,QAAQ,CAAC,eAAe;AACtB,WAAO,WAAW,KAAK,KAAK;AAAA,EAC9B;AAAA,EACA,WAAW;AACb;AAOA,SAAS,UAAU,EAAE,KAAK,QAAQ,GAAG,MAAM,GAAG;AAC5C,QAAM,CAAC,YAAY,aAAa,IAAI,SAAS,CAAC,CAAC;AAE/C,QAAM,UAAU;AAAA,IACd,MAAM;AACJ,aAAO,IAAI,iBAAiB;AAAA,QAC1B,QAAQ,SAAS,cAAc,KAAK;AAAA,QACpC,SAAS,SAAS,cAAc,KAAK;AAAA,QACrC,SAAS;AAEP,gBAAM,gBAAgB,KAAK,cAAc;AACzC,cAAI,WAAW,SAAS,MAAM,cAAc,SAAS,GAAG;AACtD,0BAAc,aAAa;AAAA,UAC7B;AAAA,QACF;AAAA,MACF,CAAC;AAAA,IACH;AAAA;AAAA,IAEA,CAAC;AAAA,EACH;AAGA,YAAU,MAAM;AACd,QAAI,CAAC,SAAS;AACZ,aAAO,MAAM;AAAA,MAAC;AAAA,IAChB;AAEA,YAAQ,MAAM;AAEd,WAAO,MAAM;AACX,cAAQ,MAAM;AAAA,IAChB;AAAA,EACF,GAAG,CAAC,KAAK,OAAO,CAAC;AAEjB,MAAI,CAAC,WAAW,CAAC,QAAQ,cAAc,EAAE,QAAQ;AAC/C,WAAO;AAAA,EACT;AAEA,SACE;AAAA,IAAC;AAAA;AAAA,MAEE,GAAG;AAAA,MAEJ,yBAAyB;AAAA,QACvB,QAAQ,OAAO,UAAU,KAAK;AAAA,MAChC;AAAA;AAAA,EACF;AAEJ;AAEA,UAAU,YAAY;AACtB,UAAU,eAAe;AAEzB,eAAe,MAAM,KAAK,SAAS;",
4
+ "sourcesContent": ["import React, { useMemo, useEffect, useState } from \"react\";\nimport PropTypes from \"prop-types\";\nimport { Map } from \"ol\";\nimport { CopyrightControl } from \"mobility-toolbox-js/ol\";\n\nconst propTypes = {\n /**\n * A map.\n */\n map: PropTypes.instanceOf(Map).isRequired,\n\n /**\n * Format function. Called with an array of copyrights from visible layers\n * and returns the copyright.\n */\n format: PropTypes.func,\n\n /**\n * CSS class of th root element\n */\n className: PropTypes.string,\n};\n\nconst defaultProps = {\n format: (copyrights) => {\n return copyrights.join(\" | \");\n },\n className: \"rs-copyright\",\n};\n\n/**\n * The Copyright component uses the\n * [mobility-toolbox-js CopyrightControl](https://mobility-toolbox-js.geops.io/api/class/src/mapbox/controls/CopyrightControl%20js~CopyrightControl%20html-offset-anchor)\n * to render the layer copyrights.\n */\nfunction Copyright({ map, format, ...other }) {\n const [node, setNode] = useState(null);\n\n const control = useMemo(() => {\n if (!node) {\n return null;\n }\n return new CopyrightControl({\n target: node,\n element: document.createElement(\"div\"),\n format,\n });\n }, [node, format]);\n\n // Ensure the control is not associated to the wrong map\n useEffect(() => {\n if (!control) {\n return () => {};\n }\n\n map.addControl(control);\n\n return () => {\n map.removeControl(control);\n };\n }, [map, control]);\n\n return (\n <div\n ref={(nod) => setNode(nod)}\n // eslint-disable-next-line react/jsx-props-no-spreading\n {...other}\n />\n );\n}\n\nCopyright.propTypes = propTypes;\nCopyright.defaultProps = defaultProps;\n\nexport default React.memo(Copyright);\n"],
5
+ "mappings": "AAAA,OAAO,SAAS,SAAS,WAAW,gBAAgB;AACpD,OAAO,eAAe;AACtB,SAAS,WAAW;AACpB,SAAS,wBAAwB;AAEjC,MAAM,YAAY;AAAA;AAAA;AAAA;AAAA,EAIhB,KAAK,UAAU,WAAW,GAAG,EAAE;AAAA;AAAA;AAAA;AAAA;AAAA,EAM/B,QAAQ,UAAU;AAAA;AAAA;AAAA;AAAA,EAKlB,WAAW,UAAU;AACvB;AAEA,MAAM,eAAe;AAAA,EACnB,QAAQ,CAAC,eAAe;AACtB,WAAO,WAAW,KAAK,KAAK;AAAA,EAC9B;AAAA,EACA,WAAW;AACb;AAOA,SAAS,UAAU,EAAE,KAAK,QAAQ,GAAG,MAAM,GAAG;AAC5C,QAAM,CAAC,MAAM,OAAO,IAAI,SAAS,IAAI;AAErC,QAAM,UAAU,QAAQ,MAAM;AAC5B,QAAI,CAAC,MAAM;AACT,aAAO;AAAA,IACT;AACA,WAAO,IAAI,iBAAiB;AAAA,MAC1B,QAAQ;AAAA,MACR,SAAS,SAAS,cAAc,KAAK;AAAA,MACrC;AAAA,IACF,CAAC;AAAA,EACH,GAAG,CAAC,MAAM,MAAM,CAAC;AAGjB,YAAU,MAAM;AACd,QAAI,CAAC,SAAS;AACZ,aAAO,MAAM;AAAA,MAAC;AAAA,IAChB;AAEA,QAAI,WAAW,OAAO;AAEtB,WAAO,MAAM;AACX,UAAI,cAAc,OAAO;AAAA,IAC3B;AAAA,EACF,GAAG,CAAC,KAAK,OAAO,CAAC;AAEjB,SACE;AAAA,IAAC;AAAA;AAAA,MACC,KAAK,CAAC,QAAQ,QAAQ,GAAG;AAAA,MAExB,GAAG;AAAA;AAAA,EACN;AAEJ;AAEA,UAAU,YAAY;AACtB,UAAU,eAAe;AAEzB,eAAe,MAAM,KAAK,SAAS;",
6
6
  "names": []
7
7
  }
@@ -1,7 +1,7 @@
1
1
  import React, { PureComponent } from "react";
2
2
  import PropTypes from "prop-types";
3
3
  import KMLFormat from "ol/format/KML";
4
- import { Layer } from "mobility-toolbox-js/ol";
4
+ import Layer from "ol/layer/Layer";
5
5
  import KML from "../../utils/KML";
6
6
  const propTypes = {
7
7
  /**
@@ -33,7 +33,7 @@ class FeatureExportButton extends PureComponent {
33
33
  if (format === KMLFormat) {
34
34
  return KML.writeFeatures(layer, projection);
35
35
  }
36
- return new format().writeFeatures(layer.olLayer.getSource().getFeatures(), {
36
+ return new format().writeFeatures(layer.getSource().getFeatures(), {
37
37
  featureProjection: projection
38
38
  });
39
39
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/components/FeatureExportButton/FeatureExportButton.js"],
4
- "sourcesContent": ["import React, { PureComponent } from \"react\";\nimport PropTypes from \"prop-types\";\nimport KMLFormat from \"ol/format/KML\";\nimport { Layer } from \"mobility-toolbox-js/ol\";\nimport KML from \"../../utils/KML\";\n\nconst propTypes = {\n /**\n * Children content of the Feature export button.\n */\n children: PropTypes.node,\n\n /**\n * Format to export features (function).\n * Supported formats: https://openlayers.org/en/latest/apidoc/module-ol_format_Feature-FeatureFormat.html\n */\n format: PropTypes.func,\n\n /**\n * An existing [mobility-toolbox-js Layer](https://mobility-toolbox-js.geops.io/api/identifiers%20html#ol-layers),\n * using a valid [ol/source/Vector](https://openlayers.org/en/latest/apidoc/module-ol_source_Vector.html)\n */\n layer: PropTypes.instanceOf(Layer).isRequired,\n\n /**\n * Map projection.\n */\n projection: PropTypes.string,\n};\n\nconst defaultProps = {\n children: null,\n format: KMLFormat,\n projection: \"EPSG:3857\",\n};\n\n/**\n * The FeatureExportButton component creates a button that exports feature geometries\n * from a [[mobility-toolbox-js Layer](https://mobility-toolbox-js.geops.io/api/identifiers%20html#ol-layers)]\n * containing an [ol/layer/Vector](https://openlayers.org/en/latest/apidoc/module-ol_layer_Vector-VectorLayer.html)\n * with a [ol/source/Vector](https://openlayers.org/en/latest/apidoc/module-ol_source_Vector.html) on click.<br>\n * The default export format is KML, which supports the features' style export.<br>\n * Other formats do not always support style export (See specific format specs).\n */\nclass FeatureExportButton extends PureComponent {\n static createFeatureString(layer, projection, format) {\n if (format === KMLFormat) {\n return KML.writeFeatures(layer, projection);\n }\n\n // eslint-disable-next-line new-cap\n return new format().writeFeatures(layer.olLayer.getSource().getFeatures(), {\n featureProjection: projection,\n });\n }\n\n static exportFeatures(layer, projection, format) {\n const now = new Date()\n .toJSON()\n .slice(0, 20)\n .replace(/[.:T-]+/g, \"\");\n const featString = this.createFeatureString(layer, projection, format);\n\n const formatString = featString\n ? featString.match(/<(\\w+)\\s+\\w+.*?>/)[1]\n : \"xml\";\n\n const fileName = `exported_features_${now}.${formatString}`;\n const charset = document.characterSet || \"UTF-8\";\n const type = `${\n formatString === \"kml\"\n ? \"data:application/vnd.google-earth.kml+xml\"\n : \"data:text/xml\"\n };charset=${charset}`;\n\n if (featString) {\n if (window.navigator.msSaveBlob) {\n // ie 11 and higher\n window.navigator.msSaveBlob(new Blob([featString], { type }), fileName);\n } else {\n const link = document.createElement(\"a\");\n link.download = fileName;\n link.href = `${type},${encodeURIComponent(featString)}`;\n link.click();\n }\n }\n }\n\n render() {\n const { children, layer, projection, format, ...other } = this.props;\n\n return (\n <div\n role=\"button\"\n className=\"rs-feature-export-button\"\n tabIndex={0}\n // eslint-disable-next-line react/jsx-props-no-spreading\n {...other}\n onClick={() => {\n return FeatureExportButton.exportFeatures(layer, projection, format);\n }}\n onKeyPress={(evt) => {\n return (\n evt.which === 13 &&\n FeatureExportButton.exportFeatures(layer, projection, format)\n );\n }}\n >\n {children}\n </div>\n );\n }\n}\n\nFeatureExportButton.propTypes = propTypes;\nFeatureExportButton.defaultProps = defaultProps;\n\nexport default FeatureExportButton;\n"],
5
- "mappings": "AAAA,OAAO,SAAS,qBAAqB;AACrC,OAAO,eAAe;AACtB,OAAO,eAAe;AACtB,SAAS,aAAa;AACtB,OAAO,SAAS;AAEhB,MAAM,YAAY;AAAA;AAAA;AAAA;AAAA,EAIhB,UAAU,UAAU;AAAA;AAAA;AAAA;AAAA;AAAA,EAMpB,QAAQ,UAAU;AAAA;AAAA;AAAA;AAAA;AAAA,EAMlB,OAAO,UAAU,WAAW,KAAK,EAAE;AAAA;AAAA;AAAA;AAAA,EAKnC,YAAY,UAAU;AACxB;AAEA,MAAM,eAAe;AAAA,EACnB,UAAU;AAAA,EACV,QAAQ;AAAA,EACR,YAAY;AACd;AAUA,MAAM,4BAA4B,cAAc;AAAA,EAC9C,OAAO,oBAAoB,OAAO,YAAY,QAAQ;AACpD,QAAI,WAAW,WAAW;AACxB,aAAO,IAAI,cAAc,OAAO,UAAU;AAAA,IAC5C;AAGA,WAAO,IAAI,OAAO,EAAE,cAAc,MAAM,QAAQ,UAAU,EAAE,YAAY,GAAG;AAAA,MACzE,mBAAmB;AAAA,IACrB,CAAC;AAAA,EACH;AAAA,EAEA,OAAO,eAAe,OAAO,YAAY,QAAQ;AAC/C,UAAM,OAAM,oBAAI,KAAK,GAClB,OAAO,EACP,MAAM,GAAG,EAAE,EACX,QAAQ,YAAY,EAAE;AACzB,UAAM,aAAa,KAAK,oBAAoB,OAAO,YAAY,MAAM;AAErE,UAAM,eAAe,aACjB,WAAW,MAAM,kBAAkB,EAAE,CAAC,IACtC;AAEJ,UAAM,WAAW,qBAAqB,GAAG,IAAI,YAAY;AACzD,UAAM,UAAU,SAAS,gBAAgB;AACzC,UAAM,OAAO,GACX,iBAAiB,QACb,8CACA,eACN,YAAY,OAAO;AAEnB,QAAI,YAAY;AACd,UAAI,OAAO,UAAU,YAAY;AAE/B,eAAO,UAAU,WAAW,IAAI,KAAK,CAAC,UAAU,GAAG,EAAE,KAAK,CAAC,GAAG,QAAQ;AAAA,MACxE,OAAO;AACL,cAAM,OAAO,SAAS,cAAc,GAAG;AACvC,aAAK,WAAW;AAChB,aAAK,OAAO,GAAG,IAAI,IAAI,mBAAmB,UAAU,CAAC;AACrD,aAAK,MAAM;AAAA,MACb;AAAA,IACF;AAAA,EACF;AAAA,EAEA,SAAS;AACP,UAAM,EAAE,UAAU,OAAO,YAAY,QAAQ,GAAG,MAAM,IAAI,KAAK;AAE/D,WACE;AAAA,MAAC;AAAA;AAAA,QACC,MAAK;AAAA,QACL,WAAU;AAAA,QACV,UAAU;AAAA,QAET,GAAG;AAAA,QACJ,SAAS,MAAM;AACb,iBAAO,oBAAoB,eAAe,OAAO,YAAY,MAAM;AAAA,QACrE;AAAA,QACA,YAAY,CAAC,QAAQ;AACnB,iBACE,IAAI,UAAU,MACd,oBAAoB,eAAe,OAAO,YAAY,MAAM;AAAA,QAEhE;AAAA;AAAA,MAEC;AAAA,IACH;AAAA,EAEJ;AACF;AAEA,oBAAoB,YAAY;AAChC,oBAAoB,eAAe;AAEnC,eAAe;",
4
+ "sourcesContent": ["import React, { PureComponent } from \"react\";\nimport PropTypes from \"prop-types\";\nimport KMLFormat from \"ol/format/KML\";\nimport Layer from \"ol/layer/Layer\";\nimport KML from \"../../utils/KML\";\n\nconst propTypes = {\n /**\n * Children content of the Feature export button.\n */\n children: PropTypes.node,\n\n /**\n * Format to export features (function).\n * Supported formats: https://openlayers.org/en/latest/apidoc/module-ol_format_Feature-FeatureFormat.html\n */\n format: PropTypes.func,\n\n /**\n * An existing [mobility-toolbox-js Layer](https://mobility-toolbox-js.geops.io/api/identifiers%20html#ol-layers),\n * using a valid [ol/source/Vector](https://openlayers.org/en/latest/apidoc/module-ol_source_Vector.html)\n */\n layer: PropTypes.instanceOf(Layer).isRequired,\n\n /**\n * Map projection.\n */\n projection: PropTypes.string,\n};\n\nconst defaultProps = {\n children: null,\n format: KMLFormat,\n projection: \"EPSG:3857\",\n};\n\n/**\n * The FeatureExportButton component creates a button that exports feature geometries\n * from a [[mobility-toolbox-js Layer](https://mobility-toolbox-js.geops.io/api/identifiers%20html#ol-layers)]\n * containing an [ol/layer/Vector](https://openlayers.org/en/latest/apidoc/module-ol_layer_Vector-VectorLayer.html)\n * with a [ol/source/Vector](https://openlayers.org/en/latest/apidoc/module-ol_source_Vector.html) on click.<br>\n * The default export format is KML, which supports the features' style export.<br>\n * Other formats do not always support style export (See specific format specs).\n */\nclass FeatureExportButton extends PureComponent {\n static createFeatureString(layer, projection, format) {\n if (format === KMLFormat) {\n return KML.writeFeatures(layer, projection);\n }\n\n // eslint-disable-next-line new-cap\n return new format().writeFeatures(layer.getSource().getFeatures(), {\n featureProjection: projection,\n });\n }\n\n static exportFeatures(layer, projection, format) {\n const now = new Date()\n .toJSON()\n .slice(0, 20)\n .replace(/[.:T-]+/g, \"\");\n const featString = this.createFeatureString(layer, projection, format);\n\n const formatString = featString\n ? featString.match(/<(\\w+)\\s+\\w+.*?>/)[1]\n : \"xml\";\n\n const fileName = `exported_features_${now}.${formatString}`;\n const charset = document.characterSet || \"UTF-8\";\n const type = `${\n formatString === \"kml\"\n ? \"data:application/vnd.google-earth.kml+xml\"\n : \"data:text/xml\"\n };charset=${charset}`;\n\n if (featString) {\n if (window.navigator.msSaveBlob) {\n // ie 11 and higher\n window.navigator.msSaveBlob(new Blob([featString], { type }), fileName);\n } else {\n const link = document.createElement(\"a\");\n link.download = fileName;\n link.href = `${type},${encodeURIComponent(featString)}`;\n link.click();\n }\n }\n }\n\n render() {\n const { children, layer, projection, format, ...other } = this.props;\n\n return (\n <div\n role=\"button\"\n className=\"rs-feature-export-button\"\n tabIndex={0}\n // eslint-disable-next-line react/jsx-props-no-spreading\n {...other}\n onClick={() => {\n return FeatureExportButton.exportFeatures(layer, projection, format);\n }}\n onKeyPress={(evt) => {\n return (\n evt.which === 13 &&\n FeatureExportButton.exportFeatures(layer, projection, format)\n );\n }}\n >\n {children}\n </div>\n );\n }\n}\n\nFeatureExportButton.propTypes = propTypes;\nFeatureExportButton.defaultProps = defaultProps;\n\nexport default FeatureExportButton;\n"],
5
+ "mappings": "AAAA,OAAO,SAAS,qBAAqB;AACrC,OAAO,eAAe;AACtB,OAAO,eAAe;AACtB,OAAO,WAAW;AAClB,OAAO,SAAS;AAEhB,MAAM,YAAY;AAAA;AAAA;AAAA;AAAA,EAIhB,UAAU,UAAU;AAAA;AAAA;AAAA;AAAA;AAAA,EAMpB,QAAQ,UAAU;AAAA;AAAA;AAAA;AAAA;AAAA,EAMlB,OAAO,UAAU,WAAW,KAAK,EAAE;AAAA;AAAA;AAAA;AAAA,EAKnC,YAAY,UAAU;AACxB;AAEA,MAAM,eAAe;AAAA,EACnB,UAAU;AAAA,EACV,QAAQ;AAAA,EACR,YAAY;AACd;AAUA,MAAM,4BAA4B,cAAc;AAAA,EAC9C,OAAO,oBAAoB,OAAO,YAAY,QAAQ;AACpD,QAAI,WAAW,WAAW;AACxB,aAAO,IAAI,cAAc,OAAO,UAAU;AAAA,IAC5C;AAGA,WAAO,IAAI,OAAO,EAAE,cAAc,MAAM,UAAU,EAAE,YAAY,GAAG;AAAA,MACjE,mBAAmB;AAAA,IACrB,CAAC;AAAA,EACH;AAAA,EAEA,OAAO,eAAe,OAAO,YAAY,QAAQ;AAC/C,UAAM,OAAM,oBAAI,KAAK,GAClB,OAAO,EACP,MAAM,GAAG,EAAE,EACX,QAAQ,YAAY,EAAE;AACzB,UAAM,aAAa,KAAK,oBAAoB,OAAO,YAAY,MAAM;AAErE,UAAM,eAAe,aACjB,WAAW,MAAM,kBAAkB,EAAE,CAAC,IACtC;AAEJ,UAAM,WAAW,qBAAqB,GAAG,IAAI,YAAY;AACzD,UAAM,UAAU,SAAS,gBAAgB;AACzC,UAAM,OAAO,GACX,iBAAiB,QACb,8CACA,eACN,YAAY,OAAO;AAEnB,QAAI,YAAY;AACd,UAAI,OAAO,UAAU,YAAY;AAE/B,eAAO,UAAU,WAAW,IAAI,KAAK,CAAC,UAAU,GAAG,EAAE,KAAK,CAAC,GAAG,QAAQ;AAAA,MACxE,OAAO;AACL,cAAM,OAAO,SAAS,cAAc,GAAG;AACvC,aAAK,WAAW;AAChB,aAAK,OAAO,GAAG,IAAI,IAAI,mBAAmB,UAAU,CAAC;AACrD,aAAK,MAAM;AAAA,MACb;AAAA,IACF;AAAA,EACF;AAAA,EAEA,SAAS;AACP,UAAM,EAAE,UAAU,OAAO,YAAY,QAAQ,GAAG,MAAM,IAAI,KAAK;AAE/D,WACE;AAAA,MAAC;AAAA;AAAA,QACC,MAAK;AAAA,QACL,WAAU;AAAA,QACV,UAAU;AAAA,QAET,GAAG;AAAA,QACJ,SAAS,MAAM;AACb,iBAAO,oBAAoB,eAAe,OAAO,YAAY,MAAM;AAAA,QACrE;AAAA,QACA,YAAY,CAAC,QAAQ;AACnB,iBACE,IAAI,UAAU,MACd,oBAAoB,eAAe,OAAO,YAAY,MAAM;AAAA,QAEhE;AAAA;AAAA,MAEC;AAAA,IACH;AAAA,EAEJ;AACF;AAEA,oBAAoB,YAAY;AAChC,oBAAoB,eAAe;AAEnC,eAAe;",
6
6
  "names": []
7
7
  }
@@ -1,7 +1,8 @@
1
1
  import React, { Component } from "react";
2
2
  import PropTypes from "prop-types";
3
- import { Layer, getLayersAsFlatArray } from "mobility-toolbox-js/ol";
4
3
  import { unByKey } from "ol/Observable";
4
+ import Layer from "ol/layer/Layer";
5
+ import getLayersAsFlatArray from "../../utils/getLayersAsFlatArray";
5
6
  const propTypes = {
6
7
  /**
7
8
  * Layers provider.
@@ -139,20 +140,46 @@ const defaultProps = {
139
140
  expandChildren: false
140
141
  };
141
142
  class LayerTree extends Component {
143
+ static getChildren = (layer) => layer?.children || layer?.get("children") || // ol.layer.group
144
+ layer?.getLayers?.().getArray() || [];
145
+ static getVisible = (layer) => layer.getVisible ? layer.getVisible() : layer.visible;
146
+ static setVisible = (layer, visible) => {
147
+ if (layer.setVisible) {
148
+ layer.setVisible(visible);
149
+ return;
150
+ }
151
+ layer.visible = visible;
152
+ };
153
+ static listenGroups = (layers) => {
154
+ const flat = getLayersAsFlatArray(layers);
155
+ const keys = flat.map((layer) => {
156
+ return layer.on("change:visible", (e) => {
157
+ const { target } = e;
158
+ if (target.getVisible() && target.get("group")) {
159
+ flat.forEach((l) => {
160
+ if (l.get("group") === target.get("group") && l !== target) {
161
+ l.setVisible(false);
162
+ }
163
+ });
164
+ }
165
+ });
166
+ });
167
+ return keys;
168
+ };
142
169
  constructor(props) {
143
170
  super(props);
144
171
  const { layers, isItemHidden } = this.props;
145
172
  const initialExpandedLayers = layers ? this.getExpandedLayers(
146
173
  layers.filter((l) => {
147
- return !isItemHidden(l) && (l.children || []).filter((child) => {
148
- return child.visible;
174
+ return !isItemHidden(l) && LayerTree.getChildren(l).filter((child) => {
175
+ return LayerTree.getVisible(child);
149
176
  }).filter((c) => {
150
177
  return !isItemHidden(c);
151
178
  }).length;
152
179
  })
153
180
  ) : [];
154
181
  this.state = {
155
- rootLayer: new Layer(),
182
+ rootLayer: new Layer({}),
156
183
  expandedLayers: initialExpandedLayers,
157
184
  revision: 0
158
185
  };
@@ -174,10 +201,8 @@ class LayerTree extends Component {
174
201
  onInputClick(layer, toggle = false) {
175
202
  if (toggle) {
176
203
  this.onToggle(layer);
177
- } else if (layer.setVisible) {
178
- layer.setVisible(!layer.visible);
179
204
  } else {
180
- layer.visible = !layer.visible;
205
+ LayerTree.setVisible(layer, !LayerTree.getVisible(layer));
181
206
  }
182
207
  }
183
208
  onToggle(layer) {
@@ -200,7 +225,7 @@ class LayerTree extends Component {
200
225
  getExpandedLayers(layers) {
201
226
  const { isItemHidden } = this.props;
202
227
  const children = layers.flatMap((l) => {
203
- return l.children.filter((c) => {
228
+ return LayerTree.getChildren(l).filter((c) => {
204
229
  return !isItemHidden(c) && c.get("isAlwaysExpanded");
205
230
  });
206
231
  });
@@ -211,7 +236,7 @@ class LayerTree extends Component {
211
236
  }
212
237
  updateLayers() {
213
238
  const { layers, expandChildren } = this.props;
214
- let rootLayer = new Layer();
239
+ let rootLayer = new Layer({});
215
240
  if (Array.isArray(layers)) {
216
241
  if (layers.length === 1) {
217
242
  [rootLayer] = layers;
@@ -220,17 +245,59 @@ class LayerTree extends Component {
220
245
  } else {
221
246
  rootLayer = layers;
222
247
  }
223
- getLayersAsFlatArray(rootLayer).forEach((layer) => {
248
+ const flat = getLayersAsFlatArray(rootLayer);
249
+ flat.forEach((layer) => {
224
250
  this.olKeys.push(
225
251
  layer.on("propertychange", () => {
226
252
  const { revision } = this.state;
227
253
  this.setState({ revision: revision + 1 });
254
+ }),
255
+ // Manage group visibility
256
+ layer.on("change:visible", (evt) => {
257
+ const { target } = evt;
258
+ if (target.getVisible() && target.get("group")) {
259
+ flat.forEach((l) => {
260
+ if (l.get("group") === target.get("group") && l !== target) {
261
+ l.setVisible(false);
262
+ }
263
+ });
264
+ }
265
+ }),
266
+ // Manage parent/children visibility
267
+ layer.on("change:visible", (evt) => {
268
+ const { target } = evt;
269
+ const parent = target.get("parent");
270
+ const children = LayerTree.getChildren(target);
271
+ if (target.getVisible()) {
272
+ if (parent) {
273
+ parent.setVisible(true);
274
+ }
275
+ if (children && !children.some((child) => child.getVisible())) {
276
+ children.forEach((child) => {
277
+ child.setVisible(true);
278
+ });
279
+ }
280
+ } else {
281
+ children.forEach((child) => {
282
+ child.setVisible(false);
283
+ });
284
+ if (parent?.getVisible() && !parent?.get("children").find((child) => child.getVisible())) {
285
+ parent.setVisible(false);
286
+ }
287
+ }
228
288
  })
229
289
  );
230
290
  });
291
+ flat.forEach((layer) => {
292
+ const children = LayerTree.getChildren(layer);
293
+ children.forEach((child) => {
294
+ child.set("parent", layer);
295
+ });
296
+ });
231
297
  const state = { rootLayer };
232
298
  if (typeof expandChildren === "function" ? expandChildren(layers) : expandChildren) {
233
- state.expandedLayers = rootLayer.children.flatMap((l) => {
299
+ const children = LayerTree.getChildren(rootLayer);
300
+ state.expandedLayers = children.flatMap((l) => {
234
301
  return this.expandLayer(l);
235
302
  });
236
303
  }
@@ -238,8 +305,8 @@ class LayerTree extends Component {
238
305
  }
239
306
  expandLayer(layer, expLayers = []) {
240
307
  const { isItemHidden } = this.props;
241
- if (layer.visible && !isItemHidden(layer)) {
242
- const children = layer.children.filter((c) => {
308
+ if (LayerTree.getVisible(layer) && !isItemHidden(layer)) {
309
+ const children = LayerTree.getChildren(layer).filter((c) => {
243
310
  return !isItemHidden(c) && !c.get("isAlwaysExpanded");
244
311
  }).flatMap((c) => {
245
312
  return this.expandLayer(c, expLayers);
@@ -251,7 +318,7 @@ class LayerTree extends Component {
251
318
  renderInput(layer, inputProps) {
252
319
  const { titles, isItemHidden, renderCheckbox } = this.props;
253
320
  let tabIndex = 0;
254
- if (!(layer.children || []).filter((c) => {
321
+ if (!LayerTree.getChildren(layer).filter((c) => {
255
322
  return !isItemHidden(c);
256
323
  }).length) {
257
324
  tabIndex = -1;
@@ -264,8 +331,7 @@ class LayerTree extends Component {
264
331
  {
265
332
  className: `rs-layer-tree-input rs-layer-tree-input-${inputType} rs-${inputType}`,
266
333
  tabIndex,
267
- title: layer.visible ? titles.layerHide : titles.layerShow,
268
- "aria-label": layer.visible ? titles.layerHide : titles.layerShow,
334
+ title: LayerTree.getVisible(layer) ? titles.layerHide : titles.layerShow,
269
335
  onKeyPress: (e) => {
270
336
  if (e.which === 13) {
271
337
  this.onInputClick(layer);
@@ -277,7 +343,7 @@ class LayerTree extends Component {
277
343
  {
278
344
  type: inputType,
279
345
  tabIndex: -1,
280
- checked: layer.visible,
346
+ checked: LayerTree.getVisible(layer),
281
347
  readOnly: true,
282
348
  onClick: () => {
283
349
  return this.onInputClick(layer);
@@ -292,7 +358,7 @@ class LayerTree extends Component {
292
358
  renderArrow(layer) {
293
359
  const { isItemHidden } = this.props;
294
360
  const { expandedLayers } = this.state;
295
- if (!(layer.children || []).filter((c) => {
361
+ if (!LayerTree.getChildren(layer).filter((c) => {
296
362
  return !isItemHidden(c);
297
363
  }).length || layer.get("isAlwaysExpanded")) {
298
364
  return null;
@@ -312,7 +378,7 @@ class LayerTree extends Component {
312
378
  const onInputClick = () => {
313
379
  this.onInputClick(
314
380
  layer,
315
- (layer.children || []).filter((c) => {
381
+ LayerTree.getChildren(layer).filter((c) => {
316
382
  return !isItemHidden(c);
317
383
  }).length && !layer.get("isAlwaysExpanded")
318
384
  );
@@ -350,7 +416,7 @@ class LayerTree extends Component {
350
416
  getParentClassName
351
417
  } = this.props;
352
418
  const children = expandedLayers.includes(layer) ? [
353
- ...(layer.children || []).filter((c) => {
419
+ ...LayerTree.getChildren(layer).filter((c) => {
354
420
  return !isItemHidden(c);
355
421
  })
356
422
  ] : [];
@@ -360,7 +426,7 @@ class LayerTree extends Component {
360
426
  return /* @__PURE__ */ React.createElement("div", { className: getParentClassName(), key: layer.key }, /* @__PURE__ */ React.createElement(
361
427
  "div",
362
428
  {
363
- className: `rs-layer-tree-item ${layer.visible ? "rs-visible" : ""}`,
429
+ className: `rs-layer-tree-item ${LayerTree.getVisible(layer) ? "rs-visible" : ""}`,
364
430
  style: {
365
431
  paddingLeft: `${padding * level}px`
366
432
  }
@@ -373,10 +439,10 @@ class LayerTree extends Component {
373
439
  renderTree() {
374
440
  const { isItemHidden } = this.props;
375
441
  const { rootLayer } = this.state;
376
- if (!rootLayer?.children?.length) {
442
+ if (!LayerTree.getChildren(rootLayer).length) {
377
443
  return null;
378
444
  }
379
- return /* @__PURE__ */ React.createElement(React.Fragment, null, rootLayer.children.filter((l) => {
445
+ return /* @__PURE__ */ React.createElement(React.Fragment, null, LayerTree.getChildren(rootLayer).filter((l) => {
380
446
  return !isItemHidden(l);
381
447
  }).reverse().map((l) => {
382
448
  return this.renderItem(l, 0);