@mapcomponents/react-maplibre 0.1.12 → 0.1.13

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 (120) hide show
  1. package/coverage/clover.xml +727 -608
  2. package/coverage/coverage-final.json +19 -14
  3. package/coverage/lcov-report/index.html +156 -96
  4. package/coverage/lcov-report/{components → src/components}/MapLibreMap/MapLibreMap.js.html +10 -10
  5. package/coverage/lcov-report/{components → src/components}/MapLibreMap/index.html +10 -10
  6. package/coverage/lcov-report/{components → src/components}/MlCreatePdfButton/MlCreatePdfButton.js.html +10 -10
  7. package/coverage/lcov-report/{components → src/components}/MlCreatePdfButton/index.html +10 -10
  8. package/coverage/lcov-report/{components → src/components}/MlFeatureEditor/MlFeatureEditor.js.html +10 -10
  9. package/coverage/lcov-report/{components → src/components}/MlFeatureEditor/index.html +10 -10
  10. package/coverage/lcov-report/{components → src/components}/MlFillExtrusionLayer/MlFillExtrusionLayer.js.html +10 -10
  11. package/coverage/lcov-report/{components → src/components}/MlFillExtrusionLayer/index.html +10 -10
  12. package/coverage/lcov-report/{components → src/components}/MlFollowGps/MlFollowGps.js.html +61 -55
  13. package/coverage/lcov-report/{components → src/components}/MlFollowGps/index.html +10 -10
  14. package/coverage/lcov-report/{components → src/components}/MlGPXViewer/MlGPXViewer.js.html +66 -60
  15. package/coverage/lcov-report/{components → src/components}/MlGPXViewer/gpxConverter.js.html +49 -70
  16. package/coverage/lcov-report/{components → src/components}/MlGPXViewer/index.html +25 -25
  17. package/coverage/lcov-report/{components → src/components}/MlGeoJsonLayer/MlGeoJsonLayer.js.html +70 -28
  18. package/coverage/lcov-report/{components → src/components}/MlGeoJsonLayer/index.html +27 -27
  19. package/coverage/lcov-report/{components → src/components}/MlImageMarkerLayer/MlImageMarkerLayer.js.html +19 -22
  20. package/coverage/lcov-report/{components → src/components}/MlImageMarkerLayer/index.html +19 -19
  21. package/coverage/lcov-report/{components → src/components}/MlLayer/MlLayer.js.html +30 -30
  22. package/coverage/lcov-report/{components → src/components}/MlLayer/index.html +26 -26
  23. package/coverage/lcov-report/{components → src/components}/MlLayerMagnify/MlLayerMagnify.js.html +41 -41
  24. package/coverage/lcov-report/{components → src/components}/MlLayerMagnify/index.html +24 -24
  25. package/coverage/lcov-report/{components → src/components}/MlLayerSwipe/MlLayerSwipe.js.html +38 -41
  26. package/coverage/lcov-report/{components → src/components}/MlLayerSwipe/index.html +24 -24
  27. package/coverage/lcov-report/src/components/MlLayerSwitcher/MlLayerSwitcher.js.html +755 -0
  28. package/coverage/lcov-report/src/components/MlLayerSwitcher/components/LayerBox.js.html +380 -0
  29. package/coverage/lcov-report/src/components/MlLayerSwitcher/components/index.html +117 -0
  30. package/coverage/lcov-report/src/components/MlLayerSwitcher/index.html +117 -0
  31. package/coverage/lcov-report/{components → src/components}/MlMarker/MlMarker.js.html +11 -11
  32. package/coverage/lcov-report/{components → src/components}/MlMarker/index.html +10 -10
  33. package/coverage/lcov-report/{components → src/components}/MlNavigationCompass/MlNavigationCompass.js.html +10 -10
  34. package/coverage/lcov-report/{components → src/components}/MlNavigationCompass/index.html +10 -10
  35. package/coverage/lcov-report/{components → src/components}/MlNavigationTools/MlNavigationTools.js.html +48 -36
  36. package/coverage/lcov-report/{components → src/components}/MlNavigationTools/index.html +16 -16
  37. package/coverage/lcov-report/{components → src/components}/MlOsmLayer/MlOsmLayer.js.html +10 -10
  38. package/coverage/lcov-report/{components → src/components}/MlOsmLayer/index.html +10 -10
  39. package/coverage/lcov-report/{components → src/components}/MlScaleReference/MlScaleReference.js.html +10 -10
  40. package/coverage/lcov-report/{components → src/components}/MlScaleReference/index.html +10 -10
  41. package/coverage/lcov-report/{components → src/components}/MlShareMapState/MlShareMapState.js.html +10 -10
  42. package/coverage/lcov-report/{components → src/components}/MlShareMapState/index.html +10 -10
  43. package/coverage/lcov-report/{components → src/components}/MlSpatialElevationProfile/MlSpatialElevationProfile.js.html +10 -10
  44. package/coverage/lcov-report/{components → src/components}/MlSpatialElevationProfile/index.html +10 -10
  45. package/coverage/lcov-report/{components → src/components}/MlThreeJsLayer/MlThreeJsLayer.js.html +30 -54
  46. package/coverage/lcov-report/{components → src/components}/MlThreeJsLayer/index.html +24 -24
  47. package/coverage/lcov-report/{components → src/components}/MlUseMapDebugger/MlUseMapDebugger.js.html +10 -10
  48. package/coverage/lcov-report/{components → src/components}/MlUseMapDebugger/index.html +10 -10
  49. package/coverage/lcov-report/{components → src/components}/MlVectorTileLayer/MlVectorTileLayer.js.html +10 -10
  50. package/coverage/lcov-report/{components → src/components}/MlVectorTileLayer/index.html +10 -10
  51. package/coverage/lcov-report/{components → src/components}/MlWmsFeatureInfoPopup/MlWmsFeatureInfoPopup.js.html +10 -10
  52. package/coverage/lcov-report/{components → src/components}/MlWmsFeatureInfoPopup/index.html +10 -10
  53. package/coverage/lcov-report/{components → src/components}/MlWmsLayer/MlWmsLayer.js.html +13 -13
  54. package/coverage/lcov-report/{components → src/components}/MlWmsLayer/index.html +14 -14
  55. package/coverage/lcov-report/{components → src/components}/MlWmsLoader/MlWmsLoader.js.html +31 -19
  56. package/coverage/lcov-report/{components → src/components}/MlWmsLoader/index.html +16 -16
  57. package/coverage/lcov-report/{hooks → src/hooks}/index.html +10 -10
  58. package/coverage/lcov-report/{hooks → src/hooks}/useMap.js.html +10 -10
  59. package/coverage/lcov-report/{hooks → src/hooks}/useMapState.js.html +10 -10
  60. package/coverage/lcov-report/{hooks → src/hooks}/useWms.js.html +18 -18
  61. package/coverage/lcov-report/src/i18n.js.html +167 -0
  62. package/coverage/lcov-report/src/index.html +117 -0
  63. package/coverage/lcov-report/src/translations/english.js.html +95 -0
  64. package/coverage/lcov-report/src/translations/german.js.html +95 -0
  65. package/coverage/lcov-report/src/translations/index.html +132 -0
  66. package/coverage/lcov.info +1240 -976
  67. package/dist/b556faa3bc6829d2.png +0 -0
  68. package/dist/index.esm.js +102 -71
  69. package/dist/index.esm.js.map +1 -1
  70. package/package.json +3 -1
  71. package/public/assets/dop.png +0 -0
  72. package/public/assets/historic.png +0 -0
  73. package/public/assets/osm.png +0 -0
  74. package/public/thumbnails/MlFollowGps.png +0 -0
  75. package/public/thumbnails/MlThreeJsLayer.png +0 -0
  76. package/src/components/MapLibreMap/lib/MapLibreGlWrapper.js +58 -73
  77. package/src/components/MlFeatureEditor/MlFeatureEditor.meta.json +2 -2
  78. package/src/components/MlFollowGps/MlFollowGps.js +45 -43
  79. package/src/components/MlFollowGps/MlFollowGps.meta.json +2 -2
  80. package/src/components/MlFollowGps/assets/marker.png +0 -0
  81. package/src/components/MlGPXViewer/MlGPXViewer.js +45 -43
  82. package/src/components/MlGPXViewer/gpxConverter.js +22 -29
  83. package/src/components/MlGeoJsonLayer/MlGeoJsonLayer.js +22 -8
  84. package/src/components/MlImageMarkerLayer/MlImageMarkerLayer.js +3 -4
  85. package/src/components/MlImageMarkerLayer/MlImageMarkerLayer.test.js +6 -7
  86. package/src/components/MlLayer/MlLayer.js +2 -2
  87. package/src/components/MlLayer/MlLayer.test.js +12 -10
  88. package/src/components/MlLayerMagnify/MlLayerMagnify.js +3 -3
  89. package/src/components/MlLayerSwipe/MlLayerSwipe.js +4 -5
  90. package/src/components/MlLayerSwitcher/MlLayerSwitcher.css +17 -0
  91. package/src/components/MlLayerSwitcher/MlLayerSwitcher.doc.de.md +3 -0
  92. package/src/components/MlLayerSwitcher/MlLayerSwitcher.js +223 -0
  93. package/src/components/MlLayerSwitcher/MlLayerSwitcher.meta_.json +15 -0
  94. package/src/components/MlLayerSwitcher/MlLayerSwitcher.stories.js +106 -0
  95. package/src/components/MlLayerSwitcher/assets/sample_1.json +26 -0
  96. package/src/components/MlLayerSwitcher/assets/sample_2.json +22 -0
  97. package/src/components/MlLayerSwitcher/components/LayerBox.js +98 -0
  98. package/src/components/MlMarker/MlMarker.js +1 -1
  99. package/src/components/MlNavigationTools/MlNavigationTools.js +26 -22
  100. package/src/components/MlScaleReference/MlScaleReference.meta.json +1 -1
  101. package/src/components/MlScaleReference/MlScaleReference.stories.js +25 -21
  102. package/src/components/MlSpatialElevationProfile/MlSpatialElevationProfile.stories.js +12 -6
  103. package/src/components/MlThreeJsLayer/MlThreeJsLayer.js +8 -15
  104. package/src/components/MlWmsLayer/MlWmsLayer.js +1 -1
  105. package/src/components/MlWmsLoader/MlWmsLoader.js +8 -4
  106. package/src/components/MlWmsLoader/MlWmsLoader.meta.json +1 -1
  107. package/src/components/MlWmsLoader/MlWmsLoader.stories.js +5 -4
  108. package/src/decorators/EmptyMapContextDecorator.js +11 -6
  109. package/src/decorators/MapContext3DDecorator.js +25 -20
  110. package/src/decorators/MapContextDashboardDecorator.js +7 -2
  111. package/src/decorators/MapContextDecorator.js +7 -3
  112. package/src/decorators/MapContextKlokantechBasicDecorator.js +8 -4
  113. package/src/decorators/MultiMapContextDecorator.js +2 -1
  114. package/src/hooks/useWms.js +7 -6
  115. package/src/i18n.js +28 -0
  116. package/src/translations/english.js +4 -0
  117. package/src/translations/german.js +4 -0
  118. package/src/ui_components/ImageLoader.js +73 -0
  119. package/src/ui_components/Sidebar.js +75 -20
  120. package/src/ui_components/TopToolbar.js +18 -18
@@ -34,11 +34,10 @@ const MlGeoJsonLayer = (props) => {
34
34
  let _componentId = componentId.current;
35
35
  return () => {
36
36
  // This is the cleanup function, it is called when this react component is removed from react-dom
37
- if(transitionTimeoutRef.current){
38
- clearTimeout(transitionTimeoutRef.current)
37
+ if (transitionTimeoutRef.current) {
38
+ clearTimeout(transitionTimeoutRef.current);
39
39
  }
40
40
  if (mapRef.current) {
41
-
42
41
  mapRef.current.cleanup(_componentId);
43
42
 
44
43
  mapRef.current = null;
@@ -48,11 +47,17 @@ const MlGeoJsonLayer = (props) => {
48
47
 
49
48
  useEffect(() => {
50
49
  if (!mapRef.current || !initializedRef.current) return;
51
- // the MapLibre-gl instance (mapContext.map) is accessible here
52
- // initialize the layer and add it to the MapLibre-gl instance or do something else with it
50
+
51
+ for (var key in props.layout) {
52
+ mapContext.getMap(props.mapId).setLayoutProperty(layerId.current, key, props.layout[key]);
53
+ }
54
+ }, [props.layout, mapContext, props.mapId]);
55
+
56
+ useEffect(() => {
57
+ if (!mapRef.current || !initializedRef.current) return;
53
58
 
54
59
  for (var key in props.paint) {
55
- mapContext.getMap(props.mapId).setPaintProperty(componentId.current, key, props.paint[key]);
60
+ mapContext.getMap(props.mapId).setPaintProperty(layerId.current, key, props.paint[key]);
56
61
  }
57
62
  }, [props.paint, mapContext, props.mapId]);
58
63
 
@@ -136,6 +141,7 @@ const MlGeoJsonLayer = (props) => {
136
141
  "line-color": "rgb(100,200,100)",
137
142
  "line-width": 10,
138
143
  },
144
+ layout: props.layout || {},
139
145
  },
140
146
  props.insertBeforeLayer,
141
147
  componentId.current
@@ -178,8 +184,16 @@ MlGeoJsonLayer.propTypes = {
178
184
  */
179
185
  type: PropTypes.string,
180
186
  /**
181
- * Paint object, that is passed to the addLayer call.
182
- * Possible propsdepend on the layer type.
187
+ * Layout property object, that is passed to the addLayer call.
188
+ * Possible props depend on the layer type.
189
+ * https://maplibre.org/maplibre-gl-js-docs/style-spec/layers/#line
190
+ * https://maplibre.org/maplibre-gl-js-docs/style-spec/layers/#circle
191
+ * https://maplibre.org/maplibre-gl-js-docs/style-spec/layers/#fill
192
+ */
193
+ layout: PropTypes.object,
194
+ /**
195
+ * Paint property object, that is passed to the addLayer call.
196
+ * Possible props depend on the layer type.
183
197
  * https://maplibre.org/maplibre-gl-js-docs/style-spec/layers/#line
184
198
  * https://maplibre.org/maplibre-gl-js-docs/style-spec/layers/#circle
185
199
  * https://maplibre.org/maplibre-gl-js-docs/style-spec/layers/#fill
@@ -6,14 +6,12 @@ import { MapContext } from "@mapcomponents/react-core";
6
6
  const MlImageMarkerLayer = (props) => {
7
7
  // Use a useRef hook to reference the layer object to be able to access it later inside useEffect hooks
8
8
  const mapRef = useRef(null);
9
- const componentId = useRef(
10
- (props.idPrefix ? props.idPrefix : "MlOsmLayer-") + uuidv4()
11
- );
9
+ const componentId = useRef((props.idPrefix ? props.idPrefix : "MlImageMarkerLayer-") + uuidv4());
12
10
  const mapContext = useContext(MapContext);
13
11
  const layerInitializedRef = useRef(false);
14
12
  const idSuffixRef = useRef(props.idSuffix || new Date().getTime());
15
13
  const imageIdRef = useRef(props.imageId || "img_" + new Date().getTime());
16
- const layerId = useRef((props.layerId || "MlImageMarkerLayer-") + idSuffixRef.current);
14
+ const layerId = useRef(props.layerId || componentId.current);
17
15
 
18
16
  useEffect(() => {
19
17
  let _componentId = componentId.current;
@@ -82,6 +80,7 @@ const MlImageMarkerLayer = (props) => {
82
80
 
83
81
  layerInitializedRef.current = true;
84
82
 
83
+ console.log(props.imgSrc);
85
84
  if (props.imgSrc) {
86
85
  mapRef.current.loadImage(props.imgSrc, function (error, image) {
87
86
  if (error) throw error;
@@ -1,20 +1,19 @@
1
1
  import { layerRemovalTest, sourceRemovalTest } from "../../util";
2
+ import { uuid_regex } from "../../setupTests";
2
3
 
3
4
  import MlImageMarkerLayer from "./MlImageMarkerLayer";
4
5
 
5
- const testComponent = (
6
- <MlImageMarkerLayer options={{ source: {} }} imgSrc="testImage" />
7
- );
6
+ const testComponent = <MlImageMarkerLayer options={{ source: {} }} imgSrc="testImage" />;
8
7
 
9
8
  layerRemovalTest(
10
9
  "<MlImageMarkerLayer />",
11
10
  testComponent,
12
- /^.*\"MlImageMarkerLayer\-[0-9]*\".*$/,
13
- "MlImageMarkerLayer-{unix-timestamp}"
11
+ new RegExp('^.*"MlImageMarkerLayer-' + uuid_regex + '".*$'),
12
+ "MlImageMarkerLayer-{uuid}"
14
13
  );
15
14
  sourceRemovalTest(
16
15
  "<MlImageMarkerLayer />",
17
16
  testComponent,
18
- /^.*\"MlImageMarkerLayer\-[0-9]*\".*$/,
19
- "MlImageMarkerLayer-{unix-timestamp}"
17
+ new RegExp('^.*"MlImageMarkerLayer-' + uuid_regex + '".*$'),
18
+ "MlImageMarkerLayer-{uuid}"
20
19
  );
@@ -12,7 +12,7 @@ const MlLayer = (props) => {
12
12
  (props.layerId ? props.layerId : "MlLayer-") + uuidv4()
13
13
  );
14
14
  const idSuffixRef = useRef(props.idSuffix || new Date().getTime());
15
- const layerId = (props.layerId || "MlLayer-") + idSuffixRef.current;
15
+ const layerId = useRef(props.layerId || componentId.current);
16
16
  const layerPaintConfRef = useRef(undefined);
17
17
  const layerLayoutConfRef = useRef(undefined);
18
18
 
@@ -65,7 +65,7 @@ const MlLayer = (props) => {
65
65
  layerInitializedRef.current = true;
66
66
  mapRef.current.addLayer(
67
67
  {
68
- id: layerId,
68
+ id: layerId.current,
69
69
  type: "background",
70
70
  paint: {
71
71
  "background-color": "rgba(0,0,0,0)",
@@ -5,6 +5,8 @@ import { MapContext, MapComponentsProvider } from "@mapcomponents/react-core";
5
5
  import MapLibreMap from "./../MapLibreMap/MapLibreMap";
6
6
  import MlLayer from "./MlLayer";
7
7
 
8
+ import { uuid_regex } from "../../setupTests";
9
+
8
10
  const MlLayerTestComponent = (props) => {
9
11
  const [layerVisible, setLayerVisible] = useState(true);
10
12
  const [refreshTrigger, setRefreshTrigger] = useState(0);
@@ -59,57 +61,57 @@ const createWrapper = () =>
59
61
  );
60
62
 
61
63
  describe("<MlLayer>", () => {
62
- it("should add a Layer with the id 'MlLayer-{unix-timestamp}' to the MapLibre instance", async () => {
64
+ it("should add a Layer with the id 'MlLayer-{uuid}' to the MapLibre instance", async () => {
63
65
  const wrapper = createWrapper();
64
66
 
65
67
  wrapper.find(".trigger_refresh").simulate("click");
66
68
 
67
69
  expect(
68
- /^.*\"MlLayer\-[0-9]*\".*$/.test(wrapper.find(".layers_json").text())
70
+ new RegExp('^.*"MlLayer-' + uuid_regex + '".*$').test(wrapper.find(".layers_json").text())
69
71
  ).toEqual(true);
70
72
  });
71
73
 
72
- it("should remove a Layer with the id 'MlLayer-{unix-timestamp}' from the MapLibre instance", async () => {
74
+ it("should remove a Layer with the id 'MlLayer-{uuid}' from the MapLibre instance", async () => {
73
75
  const wrapper = createWrapper();
74
76
 
75
77
  wrapper.find(".trigger_refresh").simulate("click");
76
78
 
77
79
  expect(
78
- /^.*\"MlLayer\-[0-9]*\".*$/.test(wrapper.find(".layers_json").text())
80
+ new RegExp('^.*"MlLayer-' + uuid_regex + '".*$').test(wrapper.find(".layers_json").text())
79
81
  ).toEqual(true);
80
82
 
81
83
  wrapper.find(".toggle_layer_visible").simulate("click");
82
84
  wrapper.find(".trigger_refresh").simulate("click");
83
85
 
84
86
  expect(
85
- /^.*\"MlLayer\-[0-9]*\".*$/.test(wrapper.find(".layers_json").text())
87
+ new RegExp('^.*"MlLayer-' + uuid_regex + '".*$').test(wrapper.find(".layers_json").text())
86
88
  ).toEqual(false);
87
89
  });
88
90
 
89
- it("should add a Source with the id 'MlLayer-{unix-timestamp}' to the MapLibre instance", async () => {
91
+ it("should add a Source with the id 'MlLayer-{uuid}' to the MapLibre instance", async () => {
90
92
  const wrapper = createWrapper();
91
93
 
92
94
  wrapper.find(".trigger_refresh").simulate("click");
93
95
 
94
96
  expect(
95
- /^.*\"MlLayer\-[0-9]*\".*$/.test(wrapper.find(".sources_json").text())
97
+ new RegExp('^.*"MlLayer-' + uuid_regex + '".*$').test(wrapper.find(".sources_json").text())
96
98
  ).toEqual(true);
97
99
  });
98
100
 
99
- it("should remove a Source with the id 'MlLayer-{unix-timestamp}' from the MapLibre instance", async () => {
101
+ it("should remove a Source with the id 'MlLayer-{uuid}' from the MapLibre instance", async () => {
100
102
  const wrapper = createWrapper();
101
103
 
102
104
  wrapper.find(".trigger_refresh").simulate("click");
103
105
 
104
106
  expect(
105
- /^.*\"MlLayer\-[0-9]*\".*$/.test(wrapper.find(".sources_json").text())
107
+ new RegExp('^.*"MlLayer-' + uuid_regex + '".*$').test(wrapper.find(".sources_json").text())
106
108
  ).toEqual(true);
107
109
 
108
110
  wrapper.find(".toggle_layer_visible").simulate("click");
109
111
  wrapper.find(".trigger_refresh").simulate("click");
110
112
 
111
113
  expect(
112
- /^.*\"MlLayer\-[0-9]*\".*$/.test(wrapper.find(".sources_json").text())
114
+ new RegExp('^.*"MlLayer-' + uuid_regex + '".*$').test(wrapper.find(".sources_json").text())
113
115
  ).toEqual(false);
114
116
  });
115
117
  });
@@ -29,7 +29,7 @@ const MlLayerMagnify = (props) => {
29
29
  if (!props.map1Id || !props.map2Id) {
30
30
  return false;
31
31
  }
32
- if (!mapContext.mapExists(props.map1Id) || !mapContext.mapExists(props.map2Id)) {
32
+ if (!mapContext.getMap(props.map1Id) || !mapContext.getMap(props.map2Id)) {
33
33
  return false;
34
34
  }
35
35
 
@@ -100,8 +100,8 @@ const MlLayerMagnify = (props) => {
100
100
 
101
101
  syncMoveInitializedRef.current = true;
102
102
  syncCleanupFunctionRef.current = syncMove(
103
- mapContext.getMap(props.map1Id),
104
- mapContext.getMap(props.map2Id)
103
+ mapContext.getMap(props.map1Id).map,
104
+ mapContext.getMap(props.map2Id).map
105
105
  );
106
106
 
107
107
  if (
@@ -22,7 +22,7 @@ const MlLayerSwipe = (props) => {
22
22
  if (!props.map1Id || !props.map2Id) {
23
23
  return false;
24
24
  }
25
- if (!mapContext.mapExists(props.map1Id) || !mapContext.mapExists(props.map2Id)) {
25
+ if (!mapContext.getMap(props.map1Id) || !mapContext.getMap(props.map2Id)) {
26
26
  return false;
27
27
  }
28
28
 
@@ -53,8 +53,7 @@ const MlLayerSwipe = (props) => {
53
53
  setSwipeX(swipeX_tmp);
54
54
  swipeXRef.current = swipeX_tmp;
55
55
 
56
- var clipA =
57
- "rect(0, " + (swipeXRef.current * bounds.width) / 100 + "px, 999em, 0)";
56
+ var clipA = "rect(0, " + (swipeXRef.current * bounds.width) / 100 + "px, 999em, 0)";
58
57
 
59
58
  mapContext.maps[props.map2Id].getContainer().style.clip = clipA;
60
59
  }
@@ -71,8 +70,8 @@ const MlLayerSwipe = (props) => {
71
70
 
72
71
  initializedRef.current = true;
73
72
  syncCleanupFunctionRef.current = syncMove(
74
- mapContext.getMap(props.map1Id),
75
- mapContext.getMap(props.map2Id)
73
+ mapContext.getMap(props.map1Id).map,
74
+ mapContext.getMap(props.map2Id).map
76
75
  );
77
76
  onMove({ clientX: mapContext.maps[props.map1Id].getCanvas().clientWidth / 2 });
78
77
  }, [mapContext.mapIds, mapContext, props, onMove, mapExists]);
@@ -0,0 +1,17 @@
1
+ .mllayerswitcher-layer-box.activeHighlight > .mllayerswitcher-layer-image {
2
+ border-color: rgb(181, 215, 238);
3
+ border-radius: 8px;
4
+ }
5
+ .mllayerswitcher-layer-box.activeHighlight > .mllayerswitcher-layer-text {
6
+ color: rgb(181, 215, 238) !important;
7
+
8
+ }
9
+
10
+ .mllayerswitcher-layer-box.active > .mllayerswitcher-layer-image {
11
+ border-color: rgb(196, 240, 0);
12
+ border-radius: 8px;
13
+ }
14
+ .mllayerswitcher-layer-box.active > .mllayerswitcher-layer-text {
15
+ color: rgb(252, 0, 0) !important;
16
+
17
+ }
@@ -0,0 +1,3 @@
1
+ # Component Beschreibung
2
+
3
+ Beschreibungstext
@@ -0,0 +1,223 @@
1
+ //CSS
2
+ import "@fontsource/roboto/300.css";
3
+ import "@fontsource/roboto/400.css";
4
+ import "@fontsource/roboto/500.css";
5
+ import { css, cx } from '@emotion/css'
6
+ import "./MlLayerSwitcher.css";
7
+ //External
8
+ import { useEffect, useContext, useState } from "react";
9
+ import PropTypes from "prop-types";
10
+ import { useTranslation } from "react-i18next";
11
+ import { Card, CardContent, Typography, Box } from "@mui/material";
12
+ //Internal
13
+ import { MapContext } from "@mapcomponents/react-core";
14
+ import LayerBox from "./components/LayerBox";
15
+ import Divider from "@mui/material/Divider";
16
+ import useMapState from "../../hooks/useMapState";
17
+ import LoadingOverlay from "../../ui_components/LoadingOverlay";
18
+ /**
19
+ * @component
20
+ *
21
+ *
22
+ */
23
+ const MlLayerSwitcher = (props) => {
24
+ const mapContext = useContext(MapContext);
25
+ const showBaseSources = !!props.baseSourceConfig?.layers?.length;
26
+ const showDetailLayer = !!props.detailLayerConfig?.layers?.length;
27
+ const { layers } = useMapState({
28
+ mapId: props.mapId,
29
+ watch: {
30
+ viewport: false,
31
+ layers: true,
32
+ sources: false,
33
+ },
34
+ filter: {},
35
+ });
36
+ const [activeLayers, setActiveLayers] = useState([]);
37
+ const [activeDetailLayers, setActiveDetailLayers] = useState([]);
38
+ const { t } = useTranslation();
39
+
40
+ useEffect(() => {
41
+ //Set base state to activate only the first layer
42
+ if (mapContext.map) {
43
+ const disableAllButFirst = (config, i) => {
44
+ const layers = getLayerListFromId(config.layerId);
45
+ const visible = i === 0 ? "visible" : "none";
46
+
47
+ layers.forEach((layer) => {
48
+ if (layer) {
49
+ changeLayerState(layer, visible);
50
+ }
51
+ });
52
+ };
53
+
54
+ props.baseSourceConfig.layers.forEach((config, i) => disableAllButFirst(config, i));
55
+ props.detailLayerConfig.layers.forEach((config, i) => disableAllButFirst(config, i));
56
+ }
57
+ return () => {
58
+ // This is the cleanup function, it is called when this react component is removed from react-dom
59
+ // try to remove anything this component has added to the MapLibre-gl instance
60
+ // e.g.: remove the layer
61
+ // mapContext.getMap(props.mapId).removeLayer(layerRef.current);
62
+ // check for the existence of map.style before calling getLayer or getSource
63
+ };
64
+ }, [mapContext.map]);
65
+
66
+ useEffect(() => {
67
+ if (mapContext.map?.style?._layers) {
68
+ let newactiveLayers = [];
69
+ let newactiveDetailLayers = [];
70
+ props.baseSourceConfig.layers.forEach((layerConfig) => {
71
+ const layers = getLayerListFromId(layerConfig.layerId);
72
+
73
+ layers.forEach((layer) => {
74
+ const visibilty = mapContext.map?.getLayoutProperty(layer, "visibility");
75
+ if (mapContext.map.baseLayers.indexOf(layer) !== -1) {
76
+ layer = "styleBase";
77
+ }
78
+
79
+ if (newactiveLayers.indexOf(layer) === -1 && visibilty === "visible") {
80
+ newactiveLayers.push(layer);
81
+ }
82
+ });
83
+ });
84
+ props.detailLayerConfig.layers.forEach(({ layerId }) => {
85
+ const visibilty = mapContext.map?.getLayoutProperty(layerId, "visibility");
86
+ if (newactiveDetailLayers.indexOf(layerId) === -1 && visibilty === "visible") {
87
+ newactiveDetailLayers.push(layerId);
88
+ }
89
+ });
90
+ setActiveLayers(newactiveLayers);
91
+
92
+ setActiveDetailLayers(newactiveDetailLayers);
93
+ }
94
+ }, [layers]);
95
+
96
+ const getLayerListFromId = (id) => {
97
+ return id === "styleBase" ? mapContext?.map.baseLayers : [id];
98
+ };
99
+
100
+ const handleDetailLayerBoxClick = (layerId) => {
101
+ const cfg = props.detailLayerConfig.layers.find((e) => e.layerId === layerId);
102
+ if (cfg.linkedTo) {
103
+ handleLayerBoxClick(cfg.linkedTo);
104
+ }
105
+ const nextVisiblityClickedLayer =
106
+ mapContext?.map.getLayer(layerId)?.getLayoutProperty("visibility") === "visible"
107
+ ? "none"
108
+ : "visible";
109
+ changeLayerState(layerId, nextVisiblityClickedLayer);
110
+ };
111
+
112
+ const handleLayerBoxClick = (id) => {
113
+ let layers = getLayerListFromId(id);
114
+ const nextVisiblityClickedLayer =
115
+ mapContext?.map.getLayer(layers[0])?.getLayoutProperty("visibility") === "visible"
116
+ ? "none"
117
+ : "visible";
118
+
119
+ props.baseSourceConfig.layers.forEach((config, i) => {
120
+ let layers = getLayerListFromId(config.layerId);
121
+ let visible = "none";
122
+ if (config.layerId === id) {
123
+ visible = nextVisiblityClickedLayer;
124
+ }
125
+
126
+ //To avoid disabling all base layers we activate the first one
127
+ if (nextVisiblityClickedLayer === "none" && i === 0) {
128
+ visible = "visible";
129
+ }
130
+ layers.forEach((layer) => {
131
+ if (layer) {
132
+ changeLayerState(layer, visible);
133
+ }
134
+ });
135
+ });
136
+ };
137
+
138
+ const changeLayerState = (layer, visible = "none") => {
139
+ mapContext.map?.setLayoutProperty(layer, "visibility", visible);
140
+ };
141
+
142
+ return (
143
+ <>
144
+ <Card sx={{ zIndex: 101, position: "absolute", minWidth: "200px" }}>
145
+ <CardContent>
146
+ {showBaseSources && (
147
+ <Box sx={{ minHeight: "150px" }}>
148
+ <Typography variant="h6">{t(props.baseSourceConfig.label || "Map type")}</Typography>
149
+ <Divider />
150
+ <Box sx={{ display: "flex", paddingTop: "1rem" }}>
151
+ {props.baseSourceConfig.layers.map(({ src, label, layerId }) => {
152
+ return (
153
+ <LayerBox
154
+ mapId={props.mapId}
155
+ key={layerId}
156
+ activeLayers={activeLayers}
157
+ label={t(label)}
158
+ layerId={layerId}
159
+ thumbnail={src}
160
+ handleLayerBoxClick={() => {
161
+ handleLayerBoxClick(layerId);
162
+ }}
163
+ />
164
+ );
165
+ })}
166
+ </Box>
167
+ </Box>
168
+ )}
169
+ {showDetailLayer && (
170
+ <Box sx={{ minHeight: "150px" }}>
171
+ <Typography variant="h6">{t("Map details")}</Typography>
172
+ <Divider />
173
+ <Box sx={{ display: "flex", paddingTop: "1rem" }}>
174
+ {props.detailLayerConfig.layers.map(({ src, label, layerId }) => {
175
+ return (
176
+ <LayerBox
177
+ mapId={props.mapId}
178
+ activeLayers={activeDetailLayers}
179
+ label={t(label)}
180
+ layerId={layerId}
181
+ key={layerId}
182
+ thumbnail={src}
183
+ handleLayerBoxClick={() => {
184
+ handleDetailLayerBoxClick(layerId);
185
+ }}
186
+ />
187
+ );
188
+ })}
189
+ </Box>
190
+ </Box>
191
+ )}
192
+ </CardContent>{" "}
193
+ </Card>
194
+ </>
195
+ );
196
+ };
197
+
198
+ MlLayerSwitcher.propTypes = {
199
+ baseSourceConfig: PropTypes.shape({
200
+ label: PropTypes.string,
201
+ layers: PropTypes.arrayOf(
202
+ PropTypes.shape({
203
+ layerId: PropTypes.string.isRequired,
204
+ src: PropTypes.string,
205
+ label: PropTypes.string.isRequired,
206
+ })
207
+ ),
208
+ }),
209
+ detailLayerConfig: PropTypes.shape({
210
+ label: PropTypes.string,
211
+ layers: PropTypes.arrayOf(
212
+ PropTypes.shape({
213
+ layerId: PropTypes.string.isRequired,
214
+ src: PropTypes.string,
215
+ label: PropTypes.string.isRequired,
216
+ linkedTo: PropTypes.string,
217
+ })
218
+ ),
219
+ }),
220
+ mapId: PropTypes.string,
221
+ };
222
+
223
+ export default MlLayerSwitcher;
@@ -0,0 +1,15 @@
1
+ {
2
+ "name": "MlLayerSwitcher",
3
+ "title": "Layer switcher",
4
+ "description": "",
5
+ "i18n": {
6
+ "de": {
7
+ "title": "Ebenen wechsler",
8
+ "description": ""
9
+ }
10
+ },
11
+ "tags": [],
12
+ "category": "",
13
+ "type": "component",
14
+ "price": 0
15
+ }
@@ -0,0 +1,106 @@
1
+ import React, { useState, useContext, useRef, useEffect } from "react";
2
+ import MlWmsLayer from "../MlWmsLayer/MlWmsLayer";
3
+ import MlLayerSwitcher from "./MlLayerSwitcher";
4
+ import MlGeoJsonLayer from '../MlGeoJsonLayer/MlGeoJsonLayer'
5
+ import mapContextDecorator from "../../decorators/MapContextDecorator";
6
+ import sample_geojson_1 from "./assets/sample_1.json";
7
+ import sample_geojson_2 from "./assets/sample_2.json";
8
+ import { Props } from "@storybook/addon-docs/blocks";
9
+
10
+ const storyoptions = {
11
+ title: "MapComponents/MlLayerSwitcher",
12
+ component: MlLayerSwitcher,
13
+ argTypes: {
14
+ url: {},
15
+ layer: {},
16
+ },
17
+ decorators: mapContextDecorator,
18
+ };
19
+ export default storyoptions;
20
+ const layerId = "nw_uraufnahme_rw";
21
+ const Template = (args) => {
22
+ const [geojson, setGeojson] = useState(sample_geojson_1);
23
+ return (
24
+ <>
25
+ <MlWmsLayer
26
+ url={args.url}
27
+ urlParameters={{ layers: args.layer }}
28
+ sourceOptions={args.sourceOptions}
29
+ layerId="historic"
30
+ visible={args.layerVisible}
31
+ />
32
+ <MlWmsLayer
33
+ url={args.url2}
34
+ urlParameters={{ layers: args.layer2 }}
35
+ sourceOptions={args.sourceOptions}
36
+ layerId={args.layer2}
37
+ visible={args.layer2Visible}
38
+ />
39
+ <MlGeoJsonLayer
40
+ type="line"
41
+ layout={{ visibility: args.geojsonLayerVisible ? "visible" : "none" }}
42
+ geojson={geojson}
43
+ layerId="geojson1"
44
+ />
45
+ <MlGeoJsonLayer
46
+ type="line"
47
+ layout={{ visibility: args.geojson2LayerVisible ? "visible" : "none" }}
48
+ geojson={sample_geojson_2}
49
+ layerId="geojson2"
50
+ />
51
+ <MlLayerSwitcher
52
+ baseSourceConfig={{
53
+ active: args.baseSourcesActive,
54
+ layers: args.layers,
55
+ }}
56
+ detailLayerConfig={args.detailLayerConfig}
57
+ />
58
+ ;
59
+ </>
60
+ );
61
+ };
62
+
63
+ export const ExampleConfig = Template.bind({});
64
+ ExampleConfig.parameters = {};
65
+ ExampleConfig.args = {
66
+ url: "https://www.wms.nrw.de/geobasis/wms_nw_uraufnahme",
67
+ layer: "nw_uraufnahme_rw",
68
+ layerVisible: true,
69
+ url2: "https://www.wms.nrw.de/geobasis/wms_nw_dop",
70
+ layer2: "WMS_NW_DOP",
71
+ layer2Visible: false,
72
+ geojsonLayerVisible: true,
73
+ geojson2LayerVisible: true,
74
+ sourceOptions: {
75
+ minzoom: 13,
76
+ maxzoom: 20,
77
+ },
78
+ baseSourcesActive: true,
79
+ layers: [
80
+ {
81
+ label: "Historic",
82
+ layerId: "historic",
83
+ src: "assets/historic.png",
84
+ },
85
+ {
86
+ label: "Straßenkarte",
87
+ layerId: "styleBase",
88
+ src: "assets/osm.png",
89
+ },
90
+ {
91
+ label: "DOP",
92
+ layerId: "WMS_NW_DOP",
93
+ src: "assets/dop.png",
94
+ },
95
+ ],
96
+ detailLayerConfig: {
97
+ layers: [
98
+ {
99
+ label: "GeoJson 1",
100
+ layerId: "geojson1",
101
+ src: "assets/historic.png",
102
+ active: true,
103
+ },
104
+ ],
105
+ },
106
+ };
@@ -0,0 +1,26 @@
1
+ {
2
+ "type": "Feature",
3
+ "properties": {},
4
+ "geometry": {
5
+ "type": "LineString",
6
+ "coordinates": [
7
+ [7.1074676513671875, 50.74340774029213],
8
+ [7.0992279052734375, 50.756441089372665],
9
+ [7.079315185546874, 50.764693667025014],
10
+ [7.045669555664062, 50.77945780529241],
11
+ [7.030563354492187, 50.79161300845443],
12
+ [7.0291900634765625, 50.80940599750376],
13
+ [7.0236968994140625, 50.820685846099174],
14
+ [7.0085906982421875, 50.825891011253546],
15
+ [6.9879913330078125, 50.826758482363275],
16
+ [6.97906494140625, 50.835432306955276],
17
+ [6.9824981689453125, 50.84583876895451],
18
+ [6.9962310791015625, 50.85147463352982],
19
+ [7.012023925781249, 50.85710981721644],
20
+ [7.021636962890625, 50.86664473085768],
21
+ [7.0367431640625, 50.872278081520406],
22
+ [7.0477294921875, 50.877044231111014],
23
+ [7.052536010742187, 50.88397594225127]
24
+ ]
25
+ }
26
+ }
@@ -0,0 +1,22 @@
1
+ {
2
+ "type": "Feature",
3
+ "properties": {},
4
+ "geometry": {
5
+ "type": "LineString",
6
+ "coordinates": [
7
+ [7.0635223388671875, 50.71385204707258],
8
+ [7.06146240234375, 50.709721458354075],
9
+ [7.063865661621094, 50.70298129536074],
10
+ [7.064552307128906, 50.69906720767511],
11
+ [7.059059143066406, 50.69428287906098],
12
+ [7.05596923828125, 50.68797551838366],
13
+ [7.0580291748046875, 50.680797145321655],
14
+ [7.062835693359375, 50.67514068397085],
15
+ [7.060432434082031, 50.6686131506577],
16
+ [7.051849365234375, 50.659255436656736],
17
+ [7.044639587402344, 50.6512019574539],
18
+ [7.0484161376953125, 50.64271166020676],
19
+ [7.0566558837890625, 50.63748609931014]
20
+ ]
21
+ }
22
+ }