@mapcomponents/react-maplibre 0.1.26 → 0.1.30

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 (108) hide show
  1. package/CHANGELOG.md +31 -0
  2. package/coverage/clover.xml +456 -479
  3. package/coverage/coverage-final.json +21 -20
  4. package/coverage/lcov-report/index.html +94 -79
  5. package/coverage/lcov-report/src/components/MapLibreMap/MapLibreMap.js.html +22 -22
  6. package/coverage/lcov-report/src/components/MapLibreMap/index.html +1 -1
  7. package/coverage/lcov-report/src/components/MlCreatePdfButton/MlCreatePdfButton.js.html +11 -11
  8. package/coverage/lcov-report/src/components/MlCreatePdfButton/index.html +11 -11
  9. package/coverage/lcov-report/src/components/MlFeatureEditor/MlFeatureEditor.js.html +1 -1
  10. package/coverage/lcov-report/src/components/MlFeatureEditor/index.html +1 -1
  11. package/coverage/lcov-report/src/components/MlFillExtrusionLayer/MlFillExtrusionLayer.js.html +4 -4
  12. package/coverage/lcov-report/src/components/MlFillExtrusionLayer/index.html +1 -1
  13. package/coverage/lcov-report/src/components/MlFollowGps/MlFollowGps.js.html +212 -26
  14. package/coverage/lcov-report/src/components/MlFollowGps/index.html +19 -19
  15. package/coverage/lcov-report/src/components/MlGPXViewer/MlGPXViewer.js.html +129 -165
  16. package/coverage/lcov-report/src/components/MlGPXViewer/gpxConverter.js.html +8 -8
  17. package/coverage/lcov-report/src/components/MlGPXViewer/index.html +20 -20
  18. package/coverage/lcov-report/src/components/MlGeoJsonLayer/MlGeoJsonLayer.js.html +45 -297
  19. package/coverage/lcov-report/src/components/MlGeoJsonLayer/index.html +19 -19
  20. package/coverage/lcov-report/src/components/MlImageMarkerLayer/MlImageMarkerLayer.js.html +2 -2
  21. package/coverage/lcov-report/src/components/MlImageMarkerLayer/index.html +1 -1
  22. package/coverage/lcov-report/src/components/MlLayer/MlLayer.js.html +2 -2
  23. package/coverage/lcov-report/src/components/MlLayer/index.html +1 -1
  24. package/coverage/lcov-report/src/components/MlLayerMagnify/MlLayerMagnify.js.html +4 -4
  25. package/coverage/lcov-report/src/components/MlLayerMagnify/index.html +1 -1
  26. package/coverage/lcov-report/src/components/MlLayerSwipe/MlLayerSwipe.js.html +3 -3
  27. package/coverage/lcov-report/src/components/MlLayerSwipe/index.html +1 -1
  28. package/coverage/lcov-report/src/components/MlLayerSwitcher/MlLayerSwitcher.js.html +1 -1
  29. package/coverage/lcov-report/src/components/MlLayerSwitcher/components/LayerBox.js.html +1 -1
  30. package/coverage/lcov-report/src/components/MlLayerSwitcher/components/index.html +1 -1
  31. package/coverage/lcov-report/src/components/MlLayerSwitcher/index.html +1 -1
  32. package/coverage/lcov-report/src/components/MlMarker/MlMarker.js.html +1 -1
  33. package/coverage/lcov-report/src/components/MlMarker/index.html +1 -1
  34. package/coverage/lcov-report/src/components/MlNavigationCompass/MlNavigationCompass.js.html +38 -104
  35. package/coverage/lcov-report/src/components/MlNavigationCompass/index.html +19 -19
  36. package/coverage/lcov-report/src/components/MlNavigationTools/MlNavigationTools.js.html +40 -139
  37. package/coverage/lcov-report/src/components/MlNavigationTools/index.html +15 -15
  38. package/coverage/lcov-report/src/components/MlOsmLayer/MlOsmLayer.js.html +32 -155
  39. package/coverage/lcov-report/src/components/MlOsmLayer/index.html +19 -19
  40. package/coverage/lcov-report/src/components/MlScaleReference/MlScaleReference.js.html +39 -198
  41. package/coverage/lcov-report/src/components/MlScaleReference/index.html +9 -9
  42. package/coverage/lcov-report/src/components/MlShareMapState/MlShareMapState.js.html +1 -1
  43. package/coverage/lcov-report/src/components/MlShareMapState/index.html +1 -1
  44. package/coverage/lcov-report/src/components/MlSpatialElevationProfile/MlSpatialElevationProfile.js.html +4 -4
  45. package/coverage/lcov-report/src/components/MlSpatialElevationProfile/index.html +1 -1
  46. package/coverage/lcov-report/src/components/MlThreeJsLayer/MlThreeJsLayer.js.html +1 -1
  47. package/coverage/lcov-report/src/components/MlThreeJsLayer/index.html +1 -1
  48. package/coverage/lcov-report/src/components/MlTransitionGeoJsonLayer/MlTransitionGeoJsonLayer.js.html +580 -0
  49. package/coverage/lcov-report/src/components/MlTransitionGeoJsonLayer/index.html +116 -0
  50. package/coverage/lcov-report/src/components/MlUseMapDebugger/MlUseMapDebugger.js.html +1 -1
  51. package/coverage/lcov-report/src/components/MlUseMapDebugger/index.html +1 -1
  52. package/coverage/lcov-report/src/components/MlVectorTileLayer/MlVectorTileLayer.js.html +3 -3
  53. package/coverage/lcov-report/src/components/MlVectorTileLayer/index.html +1 -1
  54. package/coverage/lcov-report/src/components/MlWmsFeatureInfoPopup/MlWmsFeatureInfoPopup.js.html +1 -1
  55. package/coverage/lcov-report/src/components/MlWmsFeatureInfoPopup/index.html +1 -1
  56. package/coverage/lcov-report/src/components/MlWmsLayer/MlWmsLayer.js.html +8 -11
  57. package/coverage/lcov-report/src/components/MlWmsLayer/index.html +1 -1
  58. package/coverage/lcov-report/src/components/MlWmsLoader/MlWmsLoader.js.html +1 -1
  59. package/coverage/lcov-report/src/components/MlWmsLoader/index.html +1 -1
  60. package/coverage/lcov-report/src/hooks/index.html +6 -6
  61. package/coverage/lcov-report/src/hooks/useMap.js.html +38 -26
  62. package/coverage/lcov-report/src/hooks/useMapState.js.html +47 -38
  63. package/coverage/lcov-report/src/hooks/useWms.js.html +1 -1
  64. package/coverage/lcov-report/src/i18n.js.html +1 -1
  65. package/coverage/lcov-report/src/index.html +1 -1
  66. package/coverage/lcov-report/src/translations/english.js.html +1 -1
  67. package/coverage/lcov-report/src/translations/german.js.html +1 -1
  68. package/coverage/lcov-report/src/translations/index.html +1 -1
  69. package/coverage/lcov.info +813 -858
  70. package/dist/index.esm.js +210 -425
  71. package/dist/index.esm.js.map +1 -1
  72. package/jsdoc.json +3 -3
  73. package/package.json +19 -13
  74. package/src/components/MapLibreMap/lib/MapLibreGlWrapper.js +6 -2
  75. package/src/components/MapLibreMap/lib/MapLibreGlWrapper.test.js +3 -3
  76. package/src/components/MlFeatureEditor/MlFeatureEditor.test.js +2 -2
  77. package/src/components/MlFollowGps/MlFollowGps.js +74 -12
  78. package/src/components/MlGPXViewer/MlGPXViewer.js +69 -81
  79. package/src/components/MlGeoJsonLayer/MlGeoJsonLayer.js +6 -90
  80. package/src/components/MlGeoJsonLayer/MlGeoJsonLayer.stories.js +4 -22
  81. package/src/components/MlGeoJsonLayer/util/getDefaultPaintPropsByType.js +2 -2
  82. package/src/components/MlNavigationCompass/MlNavigationCompass.js +17 -39
  83. package/src/components/MlNavigationCompass/MlNavigationCompass.test.js +3 -3
  84. package/src/components/MlNavigationTools/MlNavigationTools.js +30 -63
  85. package/src/components/MlOsmLayer/MlOsmLayer.js +15 -56
  86. package/src/components/MlOsmLayer/MlOsmLayer.stories.js +21 -10
  87. package/src/components/MlOsmLayer/MlOsmLayer.test.js +4 -4
  88. package/src/components/MlScaleReference/MlScaleReference.js +29 -82
  89. package/src/components/MlShareMapState/MlShareMapState.stories.js +1 -3
  90. package/src/components/MlThreeJsLayer/lib/GLTFLoader.js +2369 -2591
  91. package/src/components/MlTransitionGeoJsonLayer/MlTransitionGeoJsonLayer.doc.de.md +3 -0
  92. package/src/components/MlTransitionGeoJsonLayer/MlTransitionGeoJsonLayer.js +165 -0
  93. package/src/components/MlTransitionGeoJsonLayer/MlTransitionGeoJsonLayer.meta.json +15 -0
  94. package/src/components/MlTransitionGeoJsonLayer/MlTransitionGeoJsonLayer.stories.js +52 -0
  95. package/src/components/MlTransitionGeoJsonLayer/MlTransitionGeoJsonLayer.test.js +20 -0
  96. package/src/components/MlTransitionGeoJsonLayer/assets/sample_1.json +26 -0
  97. package/src/components/MlTransitionGeoJsonLayer/assets/sample_2.json +22 -0
  98. package/src/components/MlTransitionGeoJsonLayer/assets/sample_polygon_1.json +33 -0
  99. package/src/components/{MlGeoJsonLayer → MlTransitionGeoJsonLayer}/util/transitionFunctions.js +63 -97
  100. package/src/components/MlWmsLayer/MlWmsLayer.js +1 -2
  101. package/src/decorators/MapContextDecorator.js +5 -0
  102. package/src/decorators/MultiMapContextDecorator.js +6 -0
  103. package/src/hooks/useMap.js +8 -4
  104. package/src/hooks/useMapState.js +4 -1
  105. package/src/decorators/EmptyMapContextDecorator.js +0 -25
  106. package/src/decorators/MapContext3DDecorator.js +0 -39
  107. package/src/decorators/MapContextDashboardDecorator.js +0 -19
  108. package/src/decorators/MapContextKlokantechBasicDecorator.js +0 -39
package/jsdoc.json CHANGED
@@ -8,9 +8,9 @@
8
8
  },
9
9
  "recurseDepth": 10,
10
10
  "opts": {
11
- "template": "node_modules/better-docs",
12
- "destination": "docs/"
13
- },
11
+ "template": "node_modules/better-docs",
12
+ "destination": "docs/jsdocs"
13
+ },
14
14
  "source": {
15
15
  "include": ["./src/"],
16
16
  "excludePattern": ".*/(utils|MlFeatureEditor\/lib)/.*"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mapcomponents/react-maplibre",
3
- "version": "0.1.26",
3
+ "version": "0.1.30",
4
4
  "license": "MIT",
5
5
  "private": false,
6
6
  "module": "dist/index.esm.js",
@@ -13,17 +13,17 @@
13
13
  "@mapbox/mapbox-gl-draw": "^1.2.0",
14
14
  "@mapbox/mapbox-gl-sync-move": "^0.3.0",
15
15
  "@mapcomponents/react-core": "^0.1.7",
16
- "@mui/icons-material": "^5.0.1",
17
- "@mui/material": "5.0.0",
18
- "@mui/styles": "^5.0.1",
16
+ "@mui/icons-material": "^5.3.1",
17
+ "@mui/material": "5.4.0",
18
+ "@mui/styles": "^5.3.0",
19
19
  "@turf/turf": "^6.5.0",
20
- "jspdf": "^2.3.0",
21
- "maplibre-gl": "^1.13.0-rc.5",
20
+ "jspdf": "^2.5.1",
21
+ "maplibre-gl": "^2.1.6",
22
22
  "react-i18next": "^11.14.3",
23
- "three": "^0.126.1",
23
+ "three": "^0.137.5",
24
24
  "uuid": "^8.3.2",
25
25
  "wms-capabilities": "^0.5.1",
26
- "xmldom": "^0.5.0"
26
+ "xmldom": "^0.6.0"
27
27
  },
28
28
  "dependenciesComment": {
29
29
  "xmldom": "MlGPXLayer"
@@ -46,7 +46,7 @@
46
46
  "build-catalogue-meta": "node scripts/build-catalogue-meta.js",
47
47
  "build-catalogue-markdown-docs": "node scripts/build-catalogue-markdown-docs.js",
48
48
  "create-component": "./scripts/create-map-component.sh",
49
- "docs-create": "jsdoc -r -c ./jsdoc.json -d js-docs/react-map-components-maplibre/$npm_package_version",
49
+ "docs-create": "jsdoc -r -c ./jsdoc.json -d docs/jsdocs/react-map-components-maplibre/$npm_package_version",
50
50
  "docs-serve": "http-server ./js-docs/react-map-components-maplibre/$npm_package_version -p 3001"
51
51
  },
52
52
  "jest": {
@@ -76,13 +76,19 @@
76
76
  "custom\\-.*\\-mode\\.js$",
77
77
  "(.stories)\\.(ts|tsx|js)$",
78
78
  "/distribution/.*\\.(ts|js)$"
79
- ]
79
+ ],
80
+ "moduleNameMapper": {
81
+ "^!maplibre-gl$": "<rootDir>/node_modules/maplibre-gl"
82
+ }
80
83
  },
81
84
  "eslintConfig": {
82
85
  "extends": [
83
86
  "react-app",
84
87
  "react-app/jest"
85
- ]
88
+ ],
89
+ "rules": {
90
+ "import/no-webpack-loader-syntax": "off"
91
+ }
86
92
  },
87
93
  "browserslist": {
88
94
  "production": [
@@ -102,7 +108,7 @@
102
108
  "peerDependencies": {},
103
109
  "devDependencies": {
104
110
  "@babel/cli": "^7.15.4",
105
- "@babel/core": "^7.15.5",
111
+ "@babel/core": "^7.17.5",
106
112
  "@babel/plugin-external-helpers": "^7.14.5",
107
113
  "@babel/plugin-syntax-jsx": "^7.14.5",
108
114
  "@babel/preset-env": "^7.13.9",
@@ -125,7 +131,7 @@
125
131
  "@testing-library/react": "^11.1.0",
126
132
  "@testing-library/user-event": "^12.1.10",
127
133
  "@wojtekmaj/enzyme-adapter-react-17": "^0.6.3",
128
- "babel-jest": "^26.6.3",
134
+ "babel-jest": "^27.5.1",
129
135
  "better-docs": "^2.3.2",
130
136
  "canvas": "^2.7.0",
131
137
  "enzyme": "^3.11.0",
@@ -1,5 +1,5 @@
1
1
  // @ts-ignore: TS export Problem to be fixed upstream
2
- import maplibregl from "maplibre-gl/dist/maplibre-gl";
2
+ import maplibregl from "!maplibre-gl";
3
3
 
4
4
  /**
5
5
  * Creates a MapLibre-gl-js instance and offers all of the native MapLibre functions and properties as well as additional functionality such as element registration & cleanup and more events.
@@ -413,7 +413,7 @@ const MapLibreGlWrapper = function (props) {
413
413
 
414
414
  this.addNativeMaplibreFunctionsAndProps = () => {
415
415
  // add MapLibre-gl functions
416
- Object.keys(this.map.__proto__).forEach((item) => {
416
+ Object.getOwnPropertyNames(Object.getPrototypeOf(this.map)).forEach((item) => {
417
417
  if (typeof this[item] === "undefined") {
418
418
  this[item] = (...props) => self.map[item](...props);
419
419
  }
@@ -504,6 +504,10 @@ const MapLibreGlWrapper = function (props) {
504
504
  self.wrapper.refreshViewport();
505
505
  self.wrapper.fire("viewportchange");
506
506
 
507
+ self.map.on("load", () => {
508
+ self.addNativeMaplibreFunctionsAndProps();
509
+ });
510
+
507
511
  self.map.on("move", () => {
508
512
  self.wrapper.viewportState = self.wrapper.getViewport();
509
513
  self.wrapper.fire("viewportchange");
@@ -297,7 +297,7 @@ describe("MapLibreGlWrapper - event tests", () => {
297
297
  );
298
298
 
299
299
  // MapLibreGlWrapper now subscribes to "data", "move" events on its own
300
- expect(mockMapLibreMethods.on).toHaveBeenCalledTimes(4);
300
+ expect(mockMapLibreMethods.on).toHaveBeenCalledTimes(5);
301
301
  });
302
302
 
303
303
  it("should remove an event using off from MapLibreGl using MapLibreGlWrapper.cleanup(componentId)", async () => {
@@ -310,7 +310,7 @@ describe("MapLibreGlWrapper - event tests", () => {
310
310
  );
311
311
 
312
312
  // MapLibreGlWrapper now subscribes to "data", "move" events on its own
313
- expect(mockMapLibreMethods.on).toHaveBeenCalledTimes(4);
313
+ expect(mockMapLibreMethods.on).toHaveBeenCalledTimes(5);
314
314
 
315
315
  wrapper.find(".toggle_children_are_visible").simulate("click");
316
316
 
@@ -327,7 +327,7 @@ describe("MapLibreGlWrapper - event tests", () => {
327
327
  );
328
328
 
329
329
  // MapLibreGlWrapper now subscribes to "data", "move" events on its own
330
- expect(mockMapLibreMethods.on).toHaveBeenCalledTimes(6);
330
+ expect(mockMapLibreMethods.on).toHaveBeenCalledTimes(7);
331
331
 
332
332
  wrapper.find(".toggle_children_are_visible").simulate("click");
333
333
 
@@ -82,7 +82,7 @@ describe("<MlFeatureEditor>", () => {
82
82
  );
83
83
 
84
84
  // MapLibreGlWrapper now subscribes to "data", "move" events on its own
85
- await waitFor(() => expect(mockMapLibreMethods.on).toHaveBeenCalledTimes(5));
85
+ await waitFor(() => expect(mockMapLibreMethods.on).toHaveBeenCalledTimes(6));
86
86
  });
87
87
 
88
88
  it("should deregister 2 event listeners to the maplibre instance", async () => {
@@ -93,7 +93,7 @@ describe("<MlFeatureEditor>", () => {
93
93
  );
94
94
 
95
95
  // MapLibreGlWrapper now subscribes to "data", "move" events on its own
96
- expect(mockMapLibreMethods.on).toHaveBeenCalledTimes(5);
96
+ expect(mockMapLibreMethods.on).toHaveBeenCalledTimes(6);
97
97
 
98
98
  wrapper.find(".toggle_layer_visible").simulate("click");
99
99
 
@@ -1,10 +1,10 @@
1
- import React, { useEffect, useState, useCallback } from "react";
1
+ import React, { useEffect, useState, useCallback, useMemo } from "react";
2
2
  import PropTypes from "prop-types";
3
3
  import useMap from "../../hooks/useMap";
4
4
 
5
5
  import Button from "@mui/material/Button";
6
- import RoomIcon from "@mui/icons-material/Room";
7
- import { point, circle } from "@turf/turf";
6
+ import GpsFixedIcon from "@mui/icons-material/GpsFixed";
7
+ import { point, circle, lineArc } from "@turf/turf";
8
8
  import MlGeoJsonLayer from "../MlGeoJsonLayer/MlGeoJsonLayer";
9
9
 
10
10
  /**
@@ -20,10 +20,10 @@ const MlFollowGps = (props) => {
20
20
  const mapHook = useMap({ mapId: props.mapId, waitForLayer: props.insertBeforeLayer });
21
21
 
22
22
  const [isFollowed, setIsFollowed] = useState(false);
23
- const [geoJson, setGeoJson] = useState(undefined);
23
+ const [userLocationGeoJson, setUserLocationGeoJson] = useState(undefined);
24
24
  const [locationAccessDenied, setLocationAccessDenied] = useState(false);
25
-
26
25
  const [accuracyGeoJson, setAccuracyGeoJson] = useState();
26
+ const [deviceOrientation, setDeviceOrientation] = useState(0);
27
27
 
28
28
  const getLocationSuccess = useCallback(
29
29
  (pos) => {
@@ -35,11 +35,12 @@ const MlFollowGps = (props) => {
35
35
  speed: 1,
36
36
  curve: 1,
37
37
  });
38
+ if (!props.showUserLocation) return;
38
39
  const geoJsonPoint = point([pos.coords.longitude, pos.coords.latitude]);
39
- setGeoJson(geoJsonPoint);
40
+ setUserLocationGeoJson(geoJsonPoint);
40
41
  setAccuracyGeoJson(circle(geoJsonPoint, pos.coords.accuracy / 1000));
41
42
  },
42
- [mapHook.map]
43
+ [mapHook.map, props]
43
44
  );
44
45
 
45
46
  const getLocationError = (err) => {
@@ -47,6 +48,37 @@ const MlFollowGps = (props) => {
47
48
  setLocationAccessDenied(true);
48
49
  };
49
50
 
51
+ const orientationCone = useMemo(
52
+ () => {
53
+ if (!userLocationGeoJson) {
54
+ return undefined;
55
+ }
56
+ let radius = 0.02;
57
+ let bearing1 = deviceOrientation - 15;
58
+ let bearing2 = deviceOrientation + 15;
59
+ const options = {steps: 65};
60
+ let arc = lineArc(userLocationGeoJson, radius, bearing1, bearing2, options);
61
+ let copy = arc;
62
+ copy.geometry.coordinates.push(userLocationGeoJson.geometry.coordinates);
63
+ copy.geometry.coordinates.slice(0, 0, userLocationGeoJson.geometry.coordinates);
64
+ return copy;
65
+ }, [deviceOrientation, userLocationGeoJson]
66
+ )
67
+
68
+ const handleOrientation = (event) => {
69
+ setDeviceOrientation(-event.alpha)
70
+ }
71
+
72
+ useEffect(() => {
73
+ if (isFollowed) {
74
+ let _handleOrientation = handleOrientation;
75
+ window.addEventListener('deviceorientation', _handleOrientation)
76
+ return () => {
77
+ window.removeEventListener('deviceorientation', _handleOrientation)
78
+ }
79
+ }
80
+ }, [isFollowed]);
81
+
50
82
  useEffect(() => {
51
83
  if (!mapHook.map) return;
52
84
 
@@ -57,11 +89,11 @@ const MlFollowGps = (props) => {
57
89
  navigator.geolocation.clearWatch(_watchId);
58
90
  };
59
91
  }
60
- }, [isFollowed, getLocationSuccess]);
92
+ }, [mapHook.map, isFollowed, getLocationSuccess]);
61
93
 
62
94
  return (
63
95
  <>
64
- {isFollowed && geoJson && (
96
+ {isFollowed && userLocationGeoJson && (
65
97
  <MlGeoJsonLayer
66
98
  geojson={accuracyGeoJson}
67
99
  type={"fill"}
@@ -74,9 +106,22 @@ const MlFollowGps = (props) => {
74
106
  />
75
107
  )}
76
108
 
77
- {isFollowed && geoJson && (
109
+ {isFollowed && orientationCone && (
78
110
  <MlGeoJsonLayer
79
- geojson={geoJson}
111
+ geojson={orientationCone}
112
+ type={"fill"}
113
+ paint={{
114
+ "fill-color": "#0000ff",
115
+ "fill-antialias": false,
116
+ "fill-opacity": 0.3,
117
+ }}
118
+ insertBeforeLayer={props.insertBeforeLayer}
119
+ />
120
+ )}
121
+
122
+ {isFollowed && userLocationGeoJson && (
123
+ <MlGeoJsonLayer
124
+ geojson={userLocationGeoJson}
80
125
  type={"circle"}
81
126
  paint={{
82
127
  "circle-color": "#009ee0",
@@ -97,7 +142,7 @@ const MlFollowGps = (props) => {
97
142
  }}
98
143
  >
99
144
  {" "}
100
- <RoomIcon sx={{ fontSize: props.style.fontSize }} />{" "}
145
+ <GpsFixedIcon sx={{ fontSize: props.style.fontSize }} />{" "}
101
146
  </Button>
102
147
  </>
103
148
  );
@@ -121,6 +166,9 @@ MlFollowGps.defaultProps = {
121
166
  },
122
167
  onColor: "#ececec",
123
168
  offColor: "#666",
169
+ showAccuracyCircle: true,
170
+ showUserLocation: true,
171
+ showOrientation: true
124
172
  };
125
173
 
126
174
  MlFollowGps.propTypes = {
@@ -152,5 +200,19 @@ MlFollowGps.propTypes = {
152
200
  * https://maplibre.org/maplibre-gl-js-docs/style-spec/layers/#fill
153
201
  */
154
202
  circlePaint: PropTypes.object,
203
+ /**
204
+ * By default, if showUserLocation is true, a transparent circle will be drawn around the user location
205
+ * indicating the accuracy (95% confidence level) of the user's location. Set to false to disable.
206
+ */
207
+ showAccuracyCircle: PropTypes.bool,
208
+ /**
209
+ * By default a dot will be shown on the map at the user's location. Set to false to disable.
210
+ */
211
+ showUserLocation: PropTypes.bool,
212
+ /**
213
+ * By default a cone will be shown on the map at the user's location to indicate the device's orientation.
214
+ * Set to false to disable.
215
+ */
216
+ showOrientation: PropTypes.bool,
155
217
  };
156
218
  export default MlFollowGps;
@@ -1,22 +1,20 @@
1
- import React, {useContext, useRef, useEffect, useState} from "react";
1
+ import React, { useContext, useRef, useEffect, useState } from "react";
2
2
  import PropTypes from "prop-types";
3
- import {MapContext} from "@mapcomponents/react-core";
4
- import {bbox} from "@turf/turf";
3
+ import { bbox } from "@turf/turf";
5
4
  import Divider from "@mui/material/Divider";
6
5
  import Typography from "@mui/material/Typography";
7
6
  import Drawer from "@mui/material/Drawer";
8
7
  import IconButton from "@mui/material/IconButton";
9
8
  import InfoIcon from "@mui/icons-material/Info";
10
9
  import FileCopy from "@mui/icons-material/FileCopy";
11
- import {Popup} from "maplibre-gl";
10
+ import { Popup } from "maplibre-gl";
12
11
  import List from "@mui/material/List";
13
12
  import ListItem from "@mui/material/ListItem";
14
13
  import ListItemText from "@mui/material/ListItemText";
15
14
  import GeoJsonContext from "./util/GeoJsonContext";
16
15
  import toGeoJSON from "./gpxConverter";
17
16
  import useMediaQuery from "@mui/material/useMediaQuery";
18
-
19
- import {v4 as uuidv4} from "uuid";
17
+ import useMap from "../../hooks/useMap";
20
18
 
21
19
  /**
22
20
  * MlGPXViewer returns a dropzone and a button to load a GPX Track into the map.
@@ -25,11 +23,8 @@ import {v4 as uuidv4} from "uuid";
25
23
  */
26
24
  const MlGPXViewer = (props) => {
27
25
  const dataSource = useContext(GeoJsonContext);
28
- const componentId = useRef((props.idPrefix ? props.idPrefix : "MlGpxViewer-") + uuidv4());
29
- const mapContext = useContext(MapContext);
30
- const mapId = props.mapId;
31
26
  const initializedRef = useRef(false);
32
- const mapRef = useRef(null);
27
+ const mapHook = useMap({ mapId: props.mapId, waitForLayer: props.insertBeforeLayer });
33
28
  const sourceName = "import-source";
34
29
  const layerNameLines = "importer-layer-lines";
35
30
  const layerNamePoints = "importer-layer-points";
@@ -49,36 +44,19 @@ const MlGPXViewer = (props) => {
49
44
  );
50
45
 
51
46
  useEffect(() => {
52
- let _componentId = componentId.current;
53
- let _popup = popup.current;
54
- return () => {
55
- // This is the cleanup function, it is called when this react component is removed from react-dom
56
- if (mapRef.current) {
57
- mapRef.current.cleanup(_componentId);
58
-
59
- mapRef.current.getCanvas().style.cursor = "";
60
-
61
- mapRef.current = null;
62
- }
63
- _popup.remove();
64
- };
65
- }, []);
66
-
67
- useEffect(() => {
68
- if (!mapContext.mapExists(mapId) || initializedRef.current) return;
47
+ if (!mapHook.map || initializedRef.current) return;
69
48
 
70
49
  initializedRef.current = true;
71
- mapRef.current = mapContext.getMap(mapId);
72
50
 
73
- mapRef.current.addSource(
51
+ mapHook.map.addSource(
74
52
  sourceName,
75
53
  {
76
54
  type: "geojson",
77
55
  data: dataSource.data,
78
56
  },
79
- componentId.current
57
+ mapHook.componentId
80
58
  );
81
- mapRef.current.addLayer(
59
+ mapHook.map.addLayer(
82
60
  {
83
61
  id: layerNameLines,
84
62
  source: sourceName,
@@ -89,9 +67,9 @@ const MlGPXViewer = (props) => {
89
67
  },
90
68
  },
91
69
  props.insertBeforeLayer,
92
- componentId.current
70
+ mapHook.componentId
93
71
  );
94
- mapRef.current.addLayer(
72
+ mapHook.map.addLayer(
95
73
  {
96
74
  id: layerNamePoints,
97
75
  source: sourceName,
@@ -103,40 +81,49 @@ const MlGPXViewer = (props) => {
103
81
  filter: ["==", "$type", "Point"],
104
82
  },
105
83
  props.insertBeforeLayer,
106
- componentId.current
84
+ mapHook.componentId
107
85
  );
108
86
 
109
87
  [layerNameLines, layerNamePoints].forEach((layerName) => {
110
- mapRef.current.setLayoutProperty(layerName, "visibility", "visible");
88
+ mapHook.map.setLayoutProperty(layerName, "visibility", "visible");
111
89
  });
112
- mapRef.current.on("mouseenter", layerNamePoints, (e) => {
113
- // Change the cursor style as a UI indicator.
114
- mapContext.getMap(props.mapId).getCanvas().style.cursor = "pointer";
115
-
116
- const coordinates = e.features[0].geometry.coordinates.slice();
117
- //const description = e.features[0].properties.desc;
118
- const name = e.features[0].properties.name;
119
-
120
- // Ensure that if the map is zoomed out such that multiple
121
- // copies of the feature are visible, the popup appears
122
- // over the copy being pointed to.
123
- while (Math.abs(e.lngLat.lng - coordinates[0]) > 180) {
124
- coordinates[0] += e.lngLat.lng > coordinates[0] ? 360 : -360;
125
- }
90
+ mapHook.map.on(
91
+ "mouseenter",
92
+ layerNamePoints,
93
+ (e) => {
94
+ // Change the cursor style as a UI indicator.
95
+
96
+ const coordinates = e.features[0].geometry.coordinates.slice();
97
+ //const description = e.features[0].properties.desc;
98
+ const name = e.features[0].properties.name;
99
+
100
+ // Ensure that if the map is zoomed out such that multiple
101
+ // copies of the feature are visible, the popup appears
102
+ // over the copy being pointed to.
103
+ while (Math.abs(e.lngLat.lng - coordinates[0]) > 180) {
104
+ coordinates[0] += e.lngLat.lng > coordinates[0] ? 360 : -360;
105
+ }
126
106
 
127
- // Populate the popup and set its coordinates
107
+ // Populate the popup and set its coordinates
128
108
 
129
- // based on the feature found.
130
- popup.current.setLngLat(coordinates).setHTML(name).addTo(mapRef.current);
131
- });
109
+ // based on the feature found.
110
+ popup.current.setLngLat(coordinates).setHTML(name).addTo(mapHook.map);
111
+ },
112
+ mapHook.componentId
113
+ );
132
114
 
133
- mapRef.current.on("mouseleave", "places", function () {
134
- mapRef.current.getCanvas().style.cursor = "";
135
- popup.current.remove();
136
- });
115
+ mapHook.map.on(
116
+ "mouseleave",
117
+ "places",
118
+ function () {
119
+ mapHook.map.getCanvas().style.cursor = "";
120
+ popup.current.remove();
121
+ },
122
+ mapHook.componentId
123
+ );
137
124
 
138
- mapRef.current.setZoom(10);
139
- }, [mapContext.mapIds, mapContext, dataSource.data, mapId, props]);
125
+ mapHook.map.setZoom(10);
126
+ }, [mapHook.map]);
140
127
 
141
128
  useEffect(() => {
142
129
  const dropZoneCurrent = dropZone.current;
@@ -162,9 +149,8 @@ const MlGPXViewer = (props) => {
162
149
  return () => {
163
150
  window.removeEventListener("dragenter", raiseDropZoneAndStopDefault);
164
151
  window.removeEventListener("dragover", stopDefault);
165
- window.removeEventListener("drop", stopDefault);
166
152
  dropZoneCurrent.removeEventListener("dragleave", lowerDropZone);
167
- window.removeEventListener("drop", (event) => lowerDropZoneAndStopDefault);
153
+ window.removeEventListener("drop", lowerDropZoneAndStopDefault);
168
154
  };
169
155
  });
170
156
 
@@ -174,12 +160,12 @@ const MlGPXViewer = (props) => {
174
160
  };
175
161
 
176
162
  useEffect(() => {
177
- if (!mapRef.current) return;
163
+ if (!mapHook.map) return;
178
164
 
179
165
  const visibility = props.visible ? "visible" : "none";
180
166
 
181
167
  [layerNameLines, layerNamePoints].forEach((layerName) => {
182
- mapRef.current.setLayoutProperty(layerName, "visibility", visibility);
168
+ mapHook.map.setLayoutProperty(layerName, "visibility", visibility);
183
169
  });
184
170
  }, [props.visible]);
185
171
 
@@ -205,7 +191,7 @@ const MlGPXViewer = (props) => {
205
191
  };
206
192
 
207
193
  const addGPXToMap = (gpxAsString) => {
208
- if (!mapRef.current) return;
194
+ if (!mapHook.map) return;
209
195
  try {
210
196
  setMetaData([]);
211
197
  const domParser = new DOMParser();
@@ -229,9 +215,9 @@ const MlGPXViewer = (props) => {
229
215
  });
230
216
  const data = toGeoJSON.gpx(gpxDoc);
231
217
  dataSource.setData(data);
232
- mapRef.current.getSource(sourceName).setData(data);
218
+ mapHook.map.getSource(sourceName).setData(data);
233
219
  const bounds = bbox(data);
234
- mapRef.current.fitBounds(bounds);
220
+ mapHook.map.fitBounds(bounds);
235
221
  } catch (e) {
236
222
  console.log(e);
237
223
  }
@@ -257,15 +243,17 @@ const MlGPXViewer = (props) => {
257
243
  };
258
244
  return (
259
245
  <>
260
- <div style={{
261
- position: "fixed",
262
- right: "5px",
263
- bottom: mediaIsMobile ? "40px" : "25px",
264
- display: "flex",
265
- flexDirection: "column",
266
- gap: "5px",
267
- zIndex: 1000,
268
- }}>
246
+ <div
247
+ style={{
248
+ position: "fixed",
249
+ right: "5px",
250
+ bottom: mediaIsMobile ? "40px" : "25px",
251
+ display: "flex",
252
+ flexDirection: "column",
253
+ gap: "5px",
254
+ zIndex: 1000,
255
+ }}
256
+ >
269
257
  <IconButton
270
258
  onClick={manualUpload}
271
259
  style={{
@@ -279,9 +267,9 @@ const MlGPXViewer = (props) => {
279
267
  type="file"
280
268
  id="input"
281
269
  multiple
282
- style={{display: "none"}}
270
+ style={{ display: "none" }}
283
271
  ></input>
284
- <FileCopy/>
272
+ <FileCopy />
285
273
  </IconButton>
286
274
  <IconButton
287
275
  onClick={toogleDrawer}
@@ -290,7 +278,7 @@ const MlGPXViewer = (props) => {
290
278
  }}
291
279
  size="large"
292
280
  >
293
- <InfoIcon/>
281
+ <InfoIcon />
294
282
  </IconButton>
295
283
  </div>
296
284
  <Drawer variant="persistent" anchor="left" open={open}>
@@ -304,11 +292,11 @@ const MlGPXViewer = (props) => {
304
292
  >
305
293
  Informationen zur Route
306
294
  </Typography>
307
- <Divider/>
295
+ <Divider />
308
296
  <List>
309
297
  {metaData.map((item) => (
310
298
  <ListItem key={`item--${item.id}`}>
311
- <ListItemText primary={item.value}/>
299
+ <ListItemText primary={item.value} />
312
300
  </ListItem>
313
301
  ))}
314
302
  </List>
@@ -350,7 +338,7 @@ MlGPXViewer.defaultProps = {
350
338
 
351
339
  MlGPXViewer.propTypes = {
352
340
  /**
353
- * Id of the target MapLibre instance in mapContext
341
+ * Id of the target MapLibre instance in mapHook
354
342
  */
355
343
  mapId: PropTypes.string,
356
344
  /**