@mapcomponents/deck-gl 0.0.7

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 (129) hide show
  1. package/.babelrc +22 -0
  2. package/.editorconfig +19 -0
  3. package/.eslintignore +12 -0
  4. package/.eslintrc.js +30 -0
  5. package/.prettierignore +11 -0
  6. package/.prettierrc.json +6 -0
  7. package/.storybook/.babelrc +26 -0
  8. package/.storybook/main.js +40 -0
  9. package/.storybook/manager.js +6 -0
  10. package/.storybook/mapcomponents_logo.png +0 -0
  11. package/.storybook/preview.js +33 -0
  12. package/.storybook/style.css +15 -0
  13. package/.storybook/wheregroupTheme.js +9 -0
  14. package/CHANGELOG.md +1 -0
  15. package/LICENSE +21 -0
  16. package/README.md +1 -0
  17. package/config/env.js +106 -0
  18. package/config/jest/babelTransform.js +29 -0
  19. package/config/jest/cssTransform.js +14 -0
  20. package/config/jest/fileTransform.js +40 -0
  21. package/config/paths.js +75 -0
  22. package/coverage/clover.xml +6 -0
  23. package/coverage/coverage-final.json +1 -0
  24. package/coverage/lcov-report/base.css +224 -0
  25. package/coverage/lcov-report/block-navigation.js +87 -0
  26. package/coverage/lcov-report/favicon.png +0 -0
  27. package/coverage/lcov-report/index.html +101 -0
  28. package/coverage/lcov-report/prettify.css +1 -0
  29. package/coverage/lcov-report/prettify.js +2 -0
  30. package/coverage/lcov-report/sort-arrow-sprite.png +0 -0
  31. package/coverage/lcov-report/sorter.js +196 -0
  32. package/coverage/lcov.info +0 -0
  33. package/cypress/support/commands.ts +37 -0
  34. package/cypress/support/component-index.html +12 -0
  35. package/cypress/support/component.ts +46 -0
  36. package/cypress.config.ts +101 -0
  37. package/dist/components/MlHexagonMap/MlHexagonMap.d.ts +19 -0
  38. package/dist/components/MlHexagonMap/MlHexagonMap.stories.d.ts +14 -0
  39. package/dist/contexts/DeckGlContext.d.ts +15 -0
  40. package/dist/decorators/MapContextDecorator.d.ts +2 -0
  41. package/dist/hooks/useDeckGl.d.ts +7 -0
  42. package/dist/index.d.ts +2 -0
  43. package/dist/index.esm.js +105 -0
  44. package/dist/index.esm.js.map +1 -0
  45. package/dist/setupTests.d.ts +13 -0
  46. package/dist/stories/components/Readme.d.ts +2 -0
  47. package/dist/util/BubbleForInstructions.d.ts +2 -0
  48. package/dist/util/Instructions.d.ts +14 -0
  49. package/dist/util/index.d.ts +3 -0
  50. package/dist/util/layerRemovalTest.d.ts +2 -0
  51. package/dist/util/sourceRemovalTest.d.ts +2 -0
  52. package/eslintErrorTest.js +10 -0
  53. package/package.json +199 -0
  54. package/public/assets/3D/godzilla_simple.glb +0 -0
  55. package/public/assets/3D/hexa.json +4 -0
  56. package/public/assets/3D/laerm_points.json +1 -0
  57. package/public/assets/dop.png +0 -0
  58. package/public/assets/historic.png +0 -0
  59. package/public/assets/marker.png +0 -0
  60. package/public/assets/osm.png +0 -0
  61. package/public/assets/sample.gpx +716 -0
  62. package/public/assets/sample1.gpx +3003 -0
  63. package/public/assets/sample2.gpx +1264 -0
  64. package/public/assets/sample3.gpx +912 -0
  65. package/public/assets/wg-marker.png +0 -0
  66. package/public/catalogue/.gitkeep +0 -0
  67. package/public/catalogue/mc_meta.json +1 -0
  68. package/public/favicon.ico +0 -0
  69. package/public/index.html +39 -0
  70. package/public/logo.png +0 -0
  71. package/public/manifest.json +25 -0
  72. package/public/robots.txt +3 -0
  73. package/public/thumbnails/MapLibreMap.png +0 -0
  74. package/public/thumbnails/MlCameraFollowPath.png +0 -0
  75. package/public/thumbnails/MlCreatePdfButton.png +0 -0
  76. package/public/thumbnails/MlCreatePdfForm.png +0 -0
  77. package/public/thumbnails/MlDeckGlLayer.png +0 -0
  78. package/public/thumbnails/MlDeckGlTerrainLayer.png +0 -0
  79. package/public/thumbnails/MlDemoDashboard.png +0 -0
  80. package/public/thumbnails/MlFeatureEditor.png +0 -0
  81. package/public/thumbnails/MlFillExtrusionLayer.png +0 -0
  82. package/public/thumbnails/MlFollowGps.png +0 -0
  83. package/public/thumbnails/MlGeoJsonLayer.png +0 -0
  84. package/public/thumbnails/MlGpxViewer.png +0 -0
  85. package/public/thumbnails/MlHillshadeLayer.png +0 -0
  86. package/public/thumbnails/MlIconLayer.png +0 -0
  87. package/public/thumbnails/MlLaermkarte.png +0 -0
  88. package/public/thumbnails/MlLayerMagnify.png +0 -0
  89. package/public/thumbnails/MlLayerSwipe.png +0 -0
  90. package/public/thumbnails/MlMapDrawTools.png +0 -0
  91. package/public/thumbnails/MlMeasureTool.png +0 -0
  92. package/public/thumbnails/MlMobilerImker.png +0 -0
  93. package/public/thumbnails/MlNavigationCompass.png +0 -0
  94. package/public/thumbnails/MlNavigationTools.png +0 -0
  95. package/public/thumbnails/MlOsmLayer.png +0 -0
  96. package/public/thumbnails/MlScaleReference.png +0 -0
  97. package/public/thumbnails/MlSketchTool.png +0 -0
  98. package/public/thumbnails/MlSpatialElevationProfile.png +0 -0
  99. package/public/thumbnails/MlThreeJsLayer.png +0 -0
  100. package/public/thumbnails/MlTransitionGeoJsonLayer.png +0 -0
  101. package/public/thumbnails/MlVectorTileLayer.png +0 -0
  102. package/public/thumbnails/MlWanderApp.png +0 -0
  103. package/public/thumbnails/MlWmsLayer.png +0 -0
  104. package/public/thumbnails/MlWmsLoader.png +0 -0
  105. package/public/thumbnails/useCameraFollowPath.png +0 -0
  106. package/rollup.config.js +67 -0
  107. package/scripts/build-catalogue-markdown-docs.js +28 -0
  108. package/scripts/build-catalogue-meta.js +42 -0
  109. package/scripts/create-map-component.sh +36 -0
  110. package/scripts/test.js +53 -0
  111. package/src/@types/assets/index.d.ts +20 -0
  112. package/src/App.css +0 -0
  113. package/src/components/MlHexagonMap/MlHexagonMap.meta_.json +14 -0
  114. package/src/components/MlHexagonMap/MlHexagonMap.stories.tsx +29 -0
  115. package/src/components/MlHexagonMap/MlHexagonMap.tsx +143 -0
  116. package/src/contexts/DeckGlContext.tsx +66 -0
  117. package/src/custom.d.ts +4 -0
  118. package/src/decorators/MapContextDecorator.js +41 -0
  119. package/src/decorators/style.css +34 -0
  120. package/src/hooks/useDeckGl.tsx +24 -0
  121. package/src/index.ts +2 -0
  122. package/src/setupTests.js +113 -0
  123. package/src/stories/components/Readme.js +7 -0
  124. package/src/util/BubbleForInstructions.js +48 -0
  125. package/src/util/Instructions.tsx +60 -0
  126. package/src/util/index.js +4 -0
  127. package/src/util/layerRemovalTest.js +121 -0
  128. package/src/util/sourceRemovalTest.js +113 -0
  129. package/tsconfig.json +34 -0
@@ -0,0 +1,66 @@
1
+ import React, { ReactNode, useEffect, useRef, useState } from 'react';
2
+ import { useMap } from '@mapcomponents/react-maplibre';
3
+ import { Deck, Layer } from '@deck.gl/core/typed';
4
+ import { MapboxLayer } from '@deck.gl/mapbox/typed';
5
+
6
+ export interface DeckGlContextType {
7
+ deckGl: Deck | undefined;
8
+ deckGlLayerArray: Layer[];
9
+ setDeckGlLayerArray: React.Dispatch<React.SetStateAction<Layer[]>>;
10
+ }
11
+ interface DeckGlContextProviderProps {
12
+ mapId: string;
13
+ children: ReactNode;
14
+ }
15
+
16
+ const layerId = 'deckgl-layer';
17
+ const DeckGlContext = React.createContext({} as DeckGlContextType);
18
+
19
+ const DeckGlContextProvider = ({ mapId, children }: DeckGlContextProviderProps) => {
20
+ const mapHook = useMap({ mapId });
21
+
22
+ const [deckGl, setDeckGl] = useState<Deck | undefined>(undefined);
23
+ const layerRef = useRef<MapboxLayer<Layer> | undefined>(undefined);
24
+ const [deckGlLayerArray, setDeckGlLayerArray] = useState([]);
25
+
26
+ useEffect(() => {
27
+ if (!mapHook.map) return;
28
+
29
+ const deck = new Deck({
30
+ gl: mapHook.map.painter.context.gl,
31
+ layers: [],
32
+ });
33
+
34
+ layerRef.current = new MapboxLayer({
35
+ id: layerId,
36
+ deck: deck,
37
+ });
38
+
39
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
40
+ // @ts-ignore
41
+ mapHook.map.addLayer(layerRef.current);
42
+
43
+ setDeckGl(deck);
44
+ return () => {
45
+ mapHook.map?.removeLayer(layerId);
46
+ layerRef.current = undefined;
47
+ };
48
+ }, [mapHook.map]);
49
+
50
+ useEffect(() => {
51
+ if (!deckGl) return;
52
+ deckGl.setProps({
53
+ layers: [...deckGlLayerArray],
54
+ });
55
+ }, [deckGlLayerArray, deckGl]);
56
+
57
+ const value = {
58
+ deckGl,
59
+ deckGlLayerArray,
60
+ setDeckGlLayerArray,
61
+ };
62
+ return <DeckGlContext.Provider value={value}>{children}</DeckGlContext.Provider>;
63
+ };
64
+
65
+ export { DeckGlContextProvider };
66
+ export default DeckGlContext;
@@ -0,0 +1,4 @@
1
+ import { GeoJSONFeature } from "maplibre-gl";
2
+ import { GeoJSONObject } from '@turf/turf';
3
+
4
+ export type GeoJSON = (GeoJSONFeature & GeoJSONObject);
@@ -0,0 +1,41 @@
1
+ import React, { useMemo } from 'react';
2
+
3
+ import {
4
+ MapComponentsProvider,
5
+ MapLibreMap,
6
+ MlNavigationTools,
7
+ getTheme,
8
+ } from '@mapcomponents/react-maplibre';
9
+ import './style.css';
10
+ import { ThemeProvider as MUIThemeProvider } from '@mui/material/styles';
11
+
12
+ const decorators = [
13
+ (Story, context) => {
14
+ const theme = useMemo(() => getTheme(context?.globals?.theme), [context?.globals?.theme]);
15
+
16
+ return (
17
+ <div className="fullscreen_map">
18
+ <MapComponentsProvider>
19
+ <MUIThemeProvider theme={theme}>
20
+ <Story />
21
+ <MapLibreMap
22
+ options={{
23
+ zoom: 14.5,
24
+ style: 'https://wms.wheregroup.com/tileserver/style/osm-bright.json',
25
+ center: [7.0851268, 50.73884],
26
+ }}
27
+ mapId="map_1"
28
+ />
29
+ <MlNavigationTools
30
+ sx={{ bottom: '25px', right: '5px' }}
31
+ showZoomButtons={false}
32
+ mapId="map_1"
33
+ />
34
+ </MUIThemeProvider>
35
+ </MapComponentsProvider>
36
+ </div>
37
+ );
38
+ },
39
+ ];
40
+
41
+ export default decorators;
@@ -0,0 +1,34 @@
1
+ #root {
2
+ background-color: #000;
3
+ position: absolute;
4
+ min-height: 400px;
5
+ top: 0;
6
+ bottom: 0;
7
+ left: 0;
8
+ right: 0;
9
+ }
10
+ .docs-story {
11
+ min-height: 400px;
12
+ display: flex;
13
+ align-items: stretch;
14
+ }
15
+ .docs-story > div:first-child {
16
+ width: 100%;
17
+ }
18
+
19
+ .App {
20
+ position: absolute;
21
+ top: 0;
22
+ right: 0;
23
+ bottom: 0;
24
+ left: 0;
25
+ }
26
+ .fullscreen_map .mapContainer {
27
+ position: absolute;
28
+ top: 0;
29
+ right: 0;
30
+ left: 0;
31
+ bottom: 0;
32
+ z-index: 100;
33
+ }
34
+
@@ -0,0 +1,24 @@
1
+ import DeckGlContext from '../contexts/DeckGlContext';
2
+ import { useContext } from 'react';
3
+ import { Layer } from '@deck.gl/core/typed';
4
+
5
+ function useDeckGl() {
6
+ const deckGlContext = useContext(DeckGlContext);
7
+ const layerArray = deckGlContext.deckGlLayerArray;
8
+
9
+ function addLayer(layer: Layer) {
10
+ const newDeckGLLayerArray = [...layerArray];
11
+ newDeckGLLayerArray.push(layer);
12
+ deckGlContext.setDeckGlLayerArray(newDeckGLLayerArray);
13
+ }
14
+ function removeLayer(layer: Layer) {
15
+ const newDeckGLLayerArray = layerArray.filter((l) => l !== layer);
16
+ deckGlContext.setDeckGlLayerArray(newDeckGLLayerArray);
17
+ }
18
+ return {
19
+ addLayer,
20
+ removeLayer,
21
+ layerArray,
22
+ };
23
+ }
24
+ export default useDeckGl;
package/src/index.ts ADDED
@@ -0,0 +1,2 @@
1
+ export { default as DeckGlContext, DeckGlContextProvider } from './contexts/DeckGlContext';
2
+ export { default as useDeckGl } from './hooks/useDeckGl';
@@ -0,0 +1,113 @@
1
+ /* eslint-disable no-undef */
2
+ import 'jest-enzyme';
3
+ import Adapter from '@wojtekmaj/enzyme-adapter-react-17';
4
+
5
+ import { configure } from 'enzyme';
6
+
7
+ var uuid_regex = '[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}';
8
+ export { uuid_regex };
9
+
10
+ // MapLibre-gl mockup
11
+ var mockMapLibreMethods = {
12
+ on: jest.fn(),
13
+ off: jest.fn(),
14
+ addControl: jest.fn(),
15
+ removeControl: jest.fn(),
16
+ fitBounds: jest.fn(),
17
+ hasControl: jest.fn(() => true),
18
+ getCanvas: () => document.createElement('canvas'),
19
+ getContainer: () => ({
20
+ style: {},
21
+ }),
22
+ };
23
+ export { mockMapLibreMethods };
24
+
25
+ jest.mock('maplibre-gl/dist/maplibre-gl', () => {
26
+ const originalModule = jest.requireActual('maplibre-gl/dist/maplibre-gl');
27
+
28
+ return {
29
+ ...originalModule,
30
+ GeolocateControl: jest.fn(),
31
+ Map: function () {
32
+ // eslint-disable-next-line @typescript-eslint/no-this-alias
33
+ var self = this;
34
+ this.layers = [];
35
+ this.sources = [];
36
+ this.style = { sourceCaches: {} };
37
+
38
+ let styleFunctions = {
39
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
40
+ addSource: (id, source) => {
41
+ if (typeof id.id !== 'undefined') {
42
+ self.sources.push(id);
43
+ self.style.sourceCaches[id] = {};
44
+ } else if (typeof id !== 'undefined') {
45
+ self.sources.push(id);
46
+ }
47
+ },
48
+ getSource: (id) => {
49
+ if (self.sources.indexOf(id) !== -1) {
50
+ return { setData: jest.fn() };
51
+ }
52
+ return false;
53
+ },
54
+ removeSource: (id) => {
55
+ const sourcePosition = self.sources.indexOf(id);
56
+ if (sourcePosition !== -1) {
57
+ self.sources.splice(sourcePosition, 1);
58
+ delete self.style.sourceCaches[id];
59
+ }
60
+ },
61
+ addLayer: (layer) => {
62
+ if (typeof layer.id !== 'undefined') {
63
+ self.layers.push(layer.id);
64
+ if (typeof layer.source !== 'undefined' && typeof layer.source === 'object') {
65
+ self.sources.push(layer.id);
66
+ }
67
+ }
68
+ },
69
+ getLayer: (id) => {
70
+ if (self.layers.indexOf(id) !== -1) {
71
+ return {};
72
+ }
73
+ return false;
74
+ },
75
+ removeLayer: (id) => {
76
+ const layerPosition = self.layers.indexOf(id);
77
+ if (layerPosition !== -1) {
78
+ self.layers.splice(layerPosition, 1);
79
+ }
80
+ },
81
+ };
82
+
83
+ return {
84
+ ...styleFunctions,
85
+ once: (eventName, callback) => {
86
+ callback();
87
+ },
88
+ remove: jest.fn(),
89
+ setLayerZoomRange: jest.fn(),
90
+ setLayoutProperty: jest.fn(),
91
+ addImage: jest.fn(),
92
+ loadImage: jest.fn(),
93
+ removeImage: jest.fn(),
94
+ hasImage: jest.fn(),
95
+ project: jest.fn(),
96
+ setZoom: jest.fn(),
97
+ setPitch: jest.fn(),
98
+ setCenter: jest.fn(),
99
+ style: { ...styleFunctions },
100
+ layers: this.layers,
101
+ sources: this.sources,
102
+ _update: jest.fn(),
103
+ ...mockMapLibreMethods,
104
+ };
105
+ },
106
+ NavigationControl: jest.fn(),
107
+ };
108
+ });
109
+
110
+ configure({ adapter: new Adapter() });
111
+
112
+ window.URL.createObjectURL = function () {};
113
+ window.HTMLCanvasElement.prototype.getContext = () => {};
@@ -0,0 +1,7 @@
1
+ import { Description } from "@storybook/addon-docs/blocks";
2
+
3
+ import readme from "../README.md";
4
+
5
+ const Readme = () => <Description markdown={readme} />;
6
+
7
+ export default Readme;
@@ -0,0 +1,48 @@
1
+ import React from 'react';
2
+ import ReplyAllIcon from '@mui/icons-material/ReplyAll';
3
+ import { Box, Typography } from '@mui/material';
4
+
5
+ function BubbleForInstruction(props) {
6
+ return (
7
+ <>
8
+ <Box
9
+ sx={{
10
+ width: '475px',
11
+ height: '475px',
12
+ position: 'fixed',
13
+ display: 'block',
14
+ borderRadius: '360px',
15
+ bgcolor: 'primary.main',
16
+ right: props.bubbleRight,
17
+ bottom: props.bubbleBottom,
18
+ left: props.bubbleLeft,
19
+ top: props.bubbleTop,
20
+ zIndex: props.zIndex,
21
+ }}
22
+ >
23
+ <Typography
24
+ variant="h5"
25
+ sx={{
26
+ marginTop: props.textMarginTop,
27
+ marginLeft: props.textMarginLeft,
28
+ color: 'text.contrast',
29
+ textAlign: 'left',
30
+ }}
31
+ >
32
+ <b>{props.children}</b>
33
+ </Typography>
34
+ <ReplyAllIcon
35
+ sx={{
36
+ color: 'text.contrast',
37
+ fontSize: '80px',
38
+ position: 'absolute',
39
+ transform: props.iconTransform,
40
+ marginTop: props.iconMarginTop,
41
+ marginLeft: props.iconMarginLeft,
42
+ }}
43
+ />
44
+ </Box>
45
+ </>
46
+ );
47
+ }
48
+ export default BubbleForInstruction;
@@ -0,0 +1,60 @@
1
+ import React, { useEffect, useState, useRef } from 'react';
2
+ import {Fade, SxProps} from '@mui/material';
3
+ import BubbleStyle from './BubbleForInstructions';
4
+
5
+ interface StepObject {
6
+ duration: number;
7
+ props: SxProps;
8
+ content: JSX.Element;
9
+ }
10
+
11
+ interface InstructionProps {
12
+ steps: Array<StepObject>;
13
+ open: boolean;
14
+ callback?: () => void;
15
+ }
16
+
17
+ const Instructions = (props: InstructionProps) => {
18
+ const [activeStep, setActiveStep] = useState<number>();
19
+ const initializedRef = useRef(false);
20
+
21
+ const activateStep = (stepId?: number | undefined) => {
22
+ let _nextStep: number | undefined = typeof stepId === 'undefined' ? 0 : stepId + 1;
23
+ if (typeof _nextStep !== 'undefined') {
24
+ if (_nextStep > props.steps.length + 1) {
25
+ _nextStep = undefined;
26
+ } else {
27
+ setTimeout(() => {
28
+ activateStep(_nextStep);
29
+ }, props.steps[_nextStep].duration);
30
+ }
31
+ }
32
+ setActiveStep(_nextStep);
33
+ };
34
+ useEffect(() => {
35
+ if (props.open && !initializedRef.current) {
36
+ initializedRef.current = true;
37
+ activateStep();
38
+ }
39
+ if (!props.open) {
40
+ initializedRef.current = false;
41
+ setActiveStep(undefined);
42
+ }
43
+ }, [props.open]);
44
+
45
+ return (
46
+ <>
47
+ {typeof activeStep !== 'undefined' && (
48
+ <Fade in={true} timeout={150}>
49
+ <div>
50
+ <BubbleStyle {...props.steps[activeStep].props}>
51
+ {props.steps[activeStep].content}
52
+ </BubbleStyle>
53
+ </div>
54
+ </Fade>
55
+ )}
56
+ </>
57
+ );
58
+ };
59
+
60
+ export default Instructions;
@@ -0,0 +1,4 @@
1
+ import layerRemovalTest from "./layerRemovalTest";
2
+ import sourceRemovalTest from "./sourceRemovalTest";
3
+
4
+ export { layerRemovalTest, sourceRemovalTest };
@@ -0,0 +1,121 @@
1
+ import React, { useContext, useState } from "react";
2
+ import { mount } from "enzyme";
3
+ import { MapContext, MapComponentsProvider } from "../index";
4
+ import MapLibreMap from "./../components/MapLibreMap/MapLibreMap";
5
+
6
+ const layerRemovalTest = (
7
+ ComponentName,
8
+ Component,
9
+ regexLayerNameTest,
10
+ humanReadableLayerName,
11
+ beforeWrapperInit,
12
+ afterWrapperInit,
13
+ createWrapperFunction
14
+ ) => {
15
+ const TestComponent = (props) => {
16
+ const [layerVisible, setLayerVisible] = useState(true);
17
+ const [refreshTrigger, setRefreshTrigger] = useState(0);
18
+ const mapContext = useContext(MapContext);
19
+
20
+ return (
21
+ <>
22
+ <MapLibreMap />
23
+
24
+ {layerVisible && Component}
25
+
26
+ <button
27
+ className="toggle_layer_visible"
28
+ onClick={() => {
29
+ setLayerVisible(!layerVisible);
30
+ }}
31
+ >
32
+ toggle layer visible
33
+ </button>
34
+ <button
35
+ className="trigger_refresh"
36
+ onClick={() => {
37
+ setRefreshTrigger(refreshTrigger + 1);
38
+ }}
39
+ >
40
+ refresh
41
+ </button>
42
+ <div className="layers_json">
43
+ {mapContext.map &&
44
+ refreshTrigger &&
45
+ JSON.stringify(mapContext.map.map.layers)}
46
+ </div>
47
+ </>
48
+ );
49
+ };
50
+
51
+ const createWrapper =
52
+ (typeof createWrapperFunction === "function" && createWrapperFunction) ||
53
+ (() =>
54
+ mount(
55
+ <MapComponentsProvider>
56
+ <TestComponent />
57
+ </MapComponentsProvider>
58
+ ));
59
+
60
+ describe(ComponentName, () => {
61
+ it(
62
+ "should add a Layer with the id '" +
63
+ humanReadableLayerName +
64
+ "' to the MapLibre instance",
65
+ async () => {
66
+ if (typeof beforeWrapperInit === "function") {
67
+ await beforeWrapperInit();
68
+ }
69
+
70
+ const wrapper = createWrapper(TestComponent);
71
+
72
+ if (typeof afterWrapperInit === "function") {
73
+ await afterWrapperInit();
74
+ }
75
+
76
+ wrapper.find(".trigger_refresh").simulate("click");
77
+
78
+ // debug helper
79
+ //console.log('layer removal test')
80
+ //console.log(wrapper.find(".layers_json").text());
81
+ //console.log(regexLayerNameTest.toString());
82
+ //console.log(regexLayerNameTest.test(wrapper.find(".layers_json").text()));
83
+ expect(regexLayerNameTest.test(wrapper.find(".layers_json").text())).toEqual(
84
+ true
85
+ );
86
+ }
87
+ );
88
+
89
+ it(
90
+ "should remove a Layer with the id '" +
91
+ humanReadableLayerName +
92
+ "' from the MapLibre instance",
93
+ async () => {
94
+ if (typeof beforeWrapperInit === "function") {
95
+ await beforeWrapperInit();
96
+ }
97
+
98
+ const wrapper = createWrapper(TestComponent);
99
+
100
+ if (typeof afterWrapperInit === "function") {
101
+ await afterWrapperInit();
102
+ }
103
+
104
+ wrapper.find(".trigger_refresh").simulate("click");
105
+
106
+ expect(regexLayerNameTest.test(wrapper.find(".layers_json").text())).toEqual(
107
+ true
108
+ );
109
+
110
+ wrapper.find(".toggle_layer_visible").simulate("click");
111
+ wrapper.find(".trigger_refresh").simulate("click");
112
+
113
+ expect(regexLayerNameTest.test(wrapper.find(".layers_json").text())).toEqual(
114
+ false
115
+ );
116
+ }
117
+ );
118
+ });
119
+ };
120
+
121
+ export default layerRemovalTest;
@@ -0,0 +1,113 @@
1
+ import React, { useContext, useState } from "react";
2
+ import { mount, configure } from "enzyme";
3
+ import { MapContext, MapComponentsProvider } from "../index";
4
+ import MapLibreMap from "./../components/MapLibreMap/MapLibreMap";
5
+
6
+ const sourceRemovalTest = (
7
+ ComponentName,
8
+ Component,
9
+ regexLayerNameTest,
10
+ humanReadableLayerName,
11
+ beforeWrapperInit,
12
+ afterWrapperInit
13
+ ) => {
14
+ const TestComponent = (props) => {
15
+ const [layerVisible, setLayerVisible] = useState(true);
16
+ const [refreshTrigger, setRefreshTrigger] = useState(0);
17
+ const mapContext = useContext(MapContext);
18
+
19
+ return (
20
+ <>
21
+ <MapLibreMap />
22
+
23
+ {layerVisible && Component}
24
+
25
+ <button
26
+ className="toggle_layer_visible"
27
+ onClick={() => {
28
+ setLayerVisible(!layerVisible);
29
+ }}
30
+ >
31
+ toggle layer visible
32
+ </button>
33
+ <button
34
+ className="trigger_refresh"
35
+ onClick={() => {
36
+ setRefreshTrigger(refreshTrigger + 1);
37
+ }}
38
+ >
39
+ refresh
40
+ </button>
41
+ <div className="sources_json">
42
+ {mapContext.map &&
43
+ refreshTrigger &&
44
+ JSON.stringify(mapContext.map.map.sources)}
45
+ </div>
46
+ </>
47
+ );
48
+ };
49
+
50
+ const createWrapper = () =>
51
+ mount(
52
+ <MapComponentsProvider>
53
+ <TestComponent />
54
+ </MapComponentsProvider>
55
+ );
56
+
57
+ describe(ComponentName, () => {
58
+ it(
59
+ "should add a Source with the id '" +
60
+ humanReadableLayerName +
61
+ "' to the MapLibre instance",
62
+ async () => {
63
+ if (typeof beforeWrapperInit === "function") {
64
+ await beforeWrapperInit();
65
+ }
66
+
67
+ const wrapper = createWrapper();
68
+
69
+ if (typeof afterWrapperInit === "function") {
70
+ await afterWrapperInit();
71
+ }
72
+
73
+ wrapper.find(".trigger_refresh").simulate("click");
74
+
75
+ expect(
76
+ regexLayerNameTest.test(wrapper.find(".sources_json").text())
77
+ ).toEqual(true);
78
+ }
79
+ );
80
+
81
+ it(
82
+ "should remove a Source with the id '" +
83
+ humanReadableLayerName +
84
+ "' from the MapLibre instance",
85
+ async () => {
86
+ if (typeof beforeWrapperInit === "function") {
87
+ await beforeWrapperInit();
88
+ }
89
+
90
+ const wrapper = createWrapper();
91
+
92
+ if (typeof afterWrapperInit === "function") {
93
+ await afterWrapperInit();
94
+ }
95
+
96
+ wrapper.find(".trigger_refresh").simulate("click");
97
+
98
+ expect(
99
+ regexLayerNameTest.test(wrapper.find(".sources_json").text())
100
+ ).toEqual(true);
101
+
102
+ wrapper.find(".toggle_layer_visible").simulate("click");
103
+ wrapper.find(".trigger_refresh").simulate("click");
104
+
105
+ expect(
106
+ regexLayerNameTest.test(wrapper.find(".sources_json").text())
107
+ ).toEqual(false);
108
+ }
109
+ );
110
+ });
111
+ };
112
+
113
+ export default sourceRemovalTest;
package/tsconfig.json ADDED
@@ -0,0 +1,34 @@
1
+ {
2
+ "compilerOptions": {
3
+ "checkJs": false,
4
+ "esModuleInterop": true,
5
+ "importHelpers": false,
6
+ "isolatedModules": true,
7
+ "resolveJsonModule": true,
8
+ "skipLibCheck": true,
9
+ "sourceMap": true,
10
+ "strict": false,
11
+ "types": ["node", "jest", "geojson", "cypress"],
12
+ "typeRoots": ["./src/@types", "./node_modules/@types"],
13
+ "outDir": "build/esm",
14
+ "module": "esnext",
15
+ "target": "es5",
16
+ "lib": ["es6", "dom", "es2016", "es2017"],
17
+ "jsx": "react",
18
+ "declaration": true,
19
+ "declarationDir": "./dist",
20
+ "moduleResolution": "node",
21
+ "noUnusedLocals": true,
22
+ "noUnusedParameters": true,
23
+ "noImplicitReturns": true,
24
+ "noImplicitThis": true,
25
+ "noImplicitAny": true,
26
+ "strictNullChecks": true,
27
+ "suppressImplicitAnyIndexErrors": true,
28
+ "allowSyntheticDefaultImports": true,
29
+ "allowJs": true,
30
+ "baseUrl": "."
31
+ },
32
+ "include": ["src", "src/custom.d.tsx"],
33
+ "exclude": ["node_modules", "lib"]
34
+ }