@map-colonies/react-components 3.11.0 → 3.12.3

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 (40) hide show
  1. package/CHANGELOG.md +290 -234
  2. package/dist/cesium-map/index.d.ts +1 -0
  3. package/dist/cesium-map/index.js +1 -0
  4. package/dist/cesium-map/layers/imagery.layer.js +9 -5
  5. package/dist/cesium-map/layers-manager.d.ts +10 -2
  6. package/dist/cesium-map/layers-manager.js +19 -1
  7. package/dist/cesium-map/map-legend/MapLegend.css +135 -0
  8. package/dist/cesium-map/map-legend/MapLegend.d.ts +15 -0
  9. package/dist/cesium-map/map-legend/MapLegend.js +57 -0
  10. package/dist/cesium-map/map-legend/MapLegendList.d.ts +13 -0
  11. package/dist/cesium-map/map-legend/MapLegendList.js +43 -0
  12. package/dist/cesium-map/map-legend/MapLegendSidebar.d.ts +16 -0
  13. package/dist/cesium-map/map-legend/MapLegendSidebar.js +20 -0
  14. package/dist/cesium-map/map-legend/MapLegendToggle.d.ts +7 -0
  15. package/dist/cesium-map/map-legend/MapLegendToggle.js +20 -0
  16. package/dist/cesium-map/map-legend/index.d.ts +3 -0
  17. package/dist/cesium-map/map-legend/index.js +14 -0
  18. package/dist/cesium-map/map.css +6 -1
  19. package/dist/cesium-map/map.d.ts +14 -1
  20. package/dist/cesium-map/map.js +53 -21
  21. package/dist/cesium-map/proxied.types.d.ts +9 -1
  22. package/dist/cesium-map/proxied.types.js +33 -1
  23. package/dist/cesium-map/settings/settings.css +5 -2
  24. package/package.json +3 -3
  25. package/src/lib/cesium-map/data-sources/drawings.data-source.tsx +0 -1
  26. package/src/lib/cesium-map/index.ts +1 -0
  27. package/src/lib/cesium-map/layers/imagery.layer.tsx +12 -7
  28. package/src/lib/cesium-map/layers-manager.ts +30 -1
  29. package/src/lib/cesium-map/map-legend/MapLegend.css +135 -0
  30. package/src/lib/cesium-map/map-legend/MapLegend.tsx +92 -0
  31. package/src/lib/cesium-map/map-legend/MapLegendList.tsx +47 -0
  32. package/src/lib/cesium-map/map-legend/MapLegendSidebar.tsx +55 -0
  33. package/src/lib/cesium-map/map-legend/MapLegendToggle.tsx +31 -0
  34. package/src/lib/cesium-map/map-legend/index.tsx +3 -0
  35. package/src/lib/cesium-map/map-legend/legends-sidebar.stories.tsx +201 -0
  36. package/src/lib/cesium-map/map.css +6 -1
  37. package/src/lib/cesium-map/map.tsx +85 -20
  38. package/src/lib/cesium-map/proxied.types.ts +19 -7
  39. package/src/lib/cesium-map/settings/settings.css +5 -2
  40. package/src/lib/cesium-map/terrain-providers/terrain-provider-heights-tool.stories.tsx +2 -2
@@ -0,0 +1,201 @@
1
+ import React, { useState } from 'react';
2
+ import { Story, Meta } from '@storybook/react/types-6-0';
3
+ import { CesiumMap } from '../map';
4
+ import { CesiumXYZLayer } from '../layers/xyz.layer';
5
+ import { CesiumSceneMode } from '../map.types';
6
+
7
+ export default {
8
+ title: 'Cesium Map',
9
+ component: CesiumMap,
10
+ parameters: {
11
+ layout: 'fullscreen',
12
+ },
13
+ } as Meta;
14
+
15
+ const mapDivStyle = {
16
+ height: '100%',
17
+ width: '100%',
18
+ position: 'absolute' as const,
19
+ };
20
+
21
+ const optionsXYZSanDiego = {
22
+ url:
23
+ 'https://tiles.openaerialmap.org/5d73614588556200055f10d6/0/5d73614588556200055f10d7/{z}/{x}/{y}',
24
+ };
25
+
26
+ const BASE_MAPS = {
27
+ maps: [
28
+ {
29
+ id: '1st',
30
+ title: '1st Map Title',
31
+ isCurrent: true,
32
+ thumbnail:
33
+ 'https://nsw.digitaltwin.terria.io/build/3456d1802ab2ef330ae2732387726771.png',
34
+ baseRasteLayers: [
35
+ {
36
+ id: 'GOOGLE_TERRAIN',
37
+ type: 'XYZ_LAYER',
38
+ opacity: 1,
39
+ zIndex: 0,
40
+ options: {
41
+ url: 'https://mt1.google.com/vt/lyrs=s&x={x}&y={y}&z={z}',
42
+ layers: '',
43
+ credit: 'GOOGLE',
44
+ },
45
+ },
46
+ {
47
+ id: 'INFRARED_RASTER',
48
+ type: 'WMS_LAYER',
49
+ opacity: 0.6,
50
+ zIndex: 1,
51
+ options: {
52
+ url:
53
+ 'https://mesonet.agron.iastate.edu/cgi-bin/wms/goes/conus_ir.cgi?',
54
+ layers: 'goes_conus_ir',
55
+ credit: 'Infrared data courtesy Iowa Environmental Mesonet',
56
+ parameters: {
57
+ transparent: 'true',
58
+ format: 'image/png',
59
+ },
60
+ },
61
+ },
62
+ ],
63
+ baseVectorLayers: [],
64
+ },
65
+ {
66
+ id: '2nd',
67
+ title: '2nd Map Title',
68
+ thumbnail:
69
+ 'https://nsw.digitaltwin.terria.io/build/efa2f6c408eb790753a9b5fb2f3dc678.png',
70
+ baseRasteLayers: [
71
+ {
72
+ id: 'RADAR_RASTER',
73
+ type: 'WMS_LAYER',
74
+ opacity: 0.6,
75
+ zIndex: 1,
76
+ options: {
77
+ url:
78
+ 'https://mesonet.agron.iastate.edu/cgi-bin/wms/nexrad/n0r.cgi?',
79
+ layers: 'nexrad-n0r',
80
+ credit: 'Radar data courtesy Iowa Environmental Mesonet',
81
+ parameters: {
82
+ transparent: 'true',
83
+ format: 'image/png',
84
+ },
85
+ },
86
+ },
87
+ {
88
+ id: 'GOOGLE_TERRAIN',
89
+ type: 'XYZ_LAYER',
90
+ opacity: 1,
91
+ zIndex: 0,
92
+ options: {
93
+ url: 'https://mt1.google.com/vt/lyrs=s&x={x}&y={y}&z={z}',
94
+ layers: '',
95
+ credit: 'GOOGLE',
96
+ },
97
+ },
98
+ {
99
+ id: 'VECTOR_TILES_GPS',
100
+ type: 'XYZ_LAYER',
101
+ opacity: 1,
102
+ zIndex: 2,
103
+ options: {
104
+ url: 'https://gps.tile.openstreetmap.org/lines/{z}/{x}/{y}.png',
105
+ layers: '',
106
+ credit: 'openstreetmap',
107
+ },
108
+ },
109
+ ],
110
+ baseVectorLayers: [],
111
+ },
112
+ {
113
+ id: '3rd',
114
+ title: '3rd Map Title',
115
+ thumbnail:
116
+ 'https://nsw.digitaltwin.terria.io/build/d8b97d3e38a0d43e5a06dea9aae17a3e.png',
117
+ baseRasteLayers: [
118
+ {
119
+ id: 'VECTOR_TILES',
120
+ type: 'XYZ_LAYER',
121
+ opacity: 1,
122
+ zIndex: 0,
123
+ options: {
124
+ url:
125
+ 'https://{s}.tile.thunderforest.com/cycle/{z}/{x}/{y}.png?apikey=6170aad10dfd42a38d4d8c709a536f38',
126
+ layers: '',
127
+ credit: 'thunderforest',
128
+ },
129
+ },
130
+ {
131
+ id: 'VECTOR_TILES_GPS',
132
+ type: 'XYZ_LAYER',
133
+ opacity: 1,
134
+ zIndex: 1,
135
+ options: {
136
+ url: 'https://gps.tile.openstreetmap.org/lines/{z}/{x}/{y}.png',
137
+ layers: '',
138
+ credit: 'openstreetmap',
139
+ },
140
+ },
141
+ {
142
+ id: 'WMTS_POPULATION_TILES',
143
+ type: 'WMTS_LAYER',
144
+ opacity: 0.4,
145
+ zIndex: 2,
146
+ options: {
147
+ url:
148
+ 'https://services.arcgisonline.com/arcgis/rest/services/Demographics/USA_Population_Density/MapServer/WMTS/',
149
+ layer: 'USGSShadedReliefOnly',
150
+ style: 'default',
151
+ format: 'image/jpeg',
152
+ tileMatrixSetID: 'default028mm',
153
+ maximumLevel: 19,
154
+ credit: 'U. S. Geological Survey',
155
+ },
156
+ },
157
+ ],
158
+ baseVectorLayers: [],
159
+ },
160
+ ],
161
+ };
162
+
163
+ export const MapWithLegends: Story = () => {
164
+ const [center] = useState<[number, number]>([
165
+ -117.30644008676421,
166
+ 33.117098433617564,
167
+ ]); //Sandiego Poinsettia Park
168
+ return (
169
+ <div style={mapDivStyle}>
170
+ <CesiumMap
171
+ center={center}
172
+ zoom={14}
173
+ imageryProvider={false}
174
+ sceneModes={[CesiumSceneMode.SCENE3D, CesiumSceneMode.COLUMBUS_VIEW]}
175
+ // @ts-ignore
176
+ baseMaps={BASE_MAPS}
177
+ legends={{
178
+ legendsList: [
179
+ {
180
+ layer: 'bluemarble',
181
+ legendImg:
182
+ 'https://c8.alamy.com/comp/F5HF5D/map-icon-legend-symbol-sign-toolkit-element-F5HF5D.jpg',
183
+ legendDoc: 'http://www.africau.edu/images/default/sample.pdf',
184
+ },
185
+ {
186
+ layer: 'bluemarble2',
187
+ legendImg:
188
+ 'https://i.pinimg.com/564x/55/cf/a1/55cfa147dfef99d231ec95ab8cd3652d--outdoor-code-cub-scouts-brownie-hiking-badge.jpg',
189
+ legendDoc: 'http://www.africau.edu/images/default/sample.pdf',
190
+ },
191
+ ],
192
+ title: 'Map Legends',
193
+ emptyText: 'No legends for this basemap',
194
+ }}
195
+ >
196
+ <CesiumXYZLayer options={optionsXYZSanDiego} />
197
+ </CesiumMap>
198
+ </div>
199
+ );
200
+ };
201
+ MapWithLegends.storyName = 'Map with legends sidebar';
@@ -40,7 +40,7 @@ body[dir='rtl'] .toolsContainer {
40
40
 
41
41
  .sideToolsContainer {
42
42
  display: flex;
43
- flex-direction: column;
43
+ flex-direction: row;
44
44
  gap: 8px;
45
45
  z-index: 2000;
46
46
  position: absolute;
@@ -52,3 +52,8 @@ body[dir='rtl'] .sideToolsContainer {
52
52
  left: 40px;
53
53
  right: unset;
54
54
  }
55
+
56
+ .viewer {
57
+ display: flex;
58
+ flex-direction: row;
59
+ }
@@ -4,7 +4,9 @@ import React, {
4
4
  useEffect,
5
5
  useState,
6
6
  useRef,
7
+ useCallback,
7
8
  } from 'react';
9
+ import { createPortal } from 'react-dom';
8
10
  import { Viewer, CesiumComponentRef } from 'resium';
9
11
  import { ViewerProps } from 'resium/dist/types/src/Viewer/Viewer';
10
12
  import {
@@ -26,7 +28,8 @@ import { Proj } from '../utils/projections';
26
28
  import { CoordinatesTrackerTool } from './tools/coordinates-tracker.tool';
27
29
  import { ScaleTrackerTool } from './tools/scale-tracker.tool';
28
30
  import { CesiumSettings, IBaseMap, IBaseMaps } from './settings/settings';
29
- import LayerManager from './layers-manager';
31
+ import { IMapLegend, MapLegendSidebar, MapLegendToggle } from './map-legend';
32
+ import LayerManager, { LegendExtractor } from './layers-manager';
30
33
  import { CesiumSceneMode, CesiumSceneModeEnum } from './map.types';
31
34
 
32
35
  import './map.css';
@@ -54,6 +57,7 @@ interface ICameraState {
54
57
  }
55
58
  export class CesiumViewer extends CesiumViewerCls {
56
59
  public layersManager?: LayerManager;
60
+
57
61
  public constructor(
58
62
  container: string | Element,
59
63
  options?: CesiumViewerCls.ConstructorOptions
@@ -80,6 +84,14 @@ export interface IContextMenuData {
80
84
  handleClose: () => void;
81
85
  }
82
86
 
87
+ interface ILegends {
88
+ legendsList?: IMapLegend[];
89
+ emptyText?: string;
90
+ title?: string;
91
+ actionsTexts?: { docText: string; imgText: string };
92
+ mapLegendsExtractor?: LegendExtractor;
93
+ }
94
+
83
95
  export interface CesiumMapProps extends ViewerProps {
84
96
  showMousePosition?: boolean;
85
97
  showScale?: boolean;
@@ -96,6 +108,7 @@ export interface CesiumMapProps extends ViewerProps {
96
108
  width: number;
97
109
  dynamicHeightIncrement?: number;
98
110
  };
111
+ legends?: ILegends;
99
112
  }
100
113
 
101
114
  export const useCesiumMap = (): CesiumViewer => {
@@ -119,11 +132,15 @@ export const CesiumMap: React.FC<CesiumMapProps> = (props) => {
119
132
  const [sceneModes, setSceneModes] = useState<
120
133
  CesiumSceneModeEnum[] | undefined
121
134
  >();
135
+ const [legendsList, setLegendsList] = useState<IMapLegend[]>([]);
122
136
  const [baseMaps, setBaseMaps] = useState<IBaseMaps | undefined>();
123
137
  const [showImageryMenu, setShowImageryMenu] = useState<boolean>(false);
124
138
  const [imageryMenuPosition, setImageryMenuPosition] = useState<
125
139
  Record<string, unknown> | undefined
126
140
  >(undefined);
141
+ const [isLegendsSidebarOpen, setIsLegendsSidebarOpen] = useState<boolean>(
142
+ false
143
+ );
127
144
 
128
145
  const viewerProps = {
129
146
  fullscreenButton: true,
@@ -163,7 +180,7 @@ export const CesiumMap: React.FC<CesiumMapProps> = (props) => {
163
180
  useEffect(() => {
164
181
  if (ref.current) {
165
182
  const viewer = ref.current.cesiumElement as CesiumViewer;
166
- viewer.layersManager = new LayerManager(viewer);
183
+
167
184
  if (props.imageryContextMenu) {
168
185
  viewer.screenSpaceEventHandler.setInputAction(
169
186
  (evt: Record<string, unknown>) => {
@@ -179,6 +196,20 @@ export const CesiumMap: React.FC<CesiumMapProps> = (props) => {
179
196
  setMapViewRef(ref.current?.cesiumElement);
180
197
  }, [ref, props.imageryContextMenu]);
181
198
 
199
+ useEffect(() => {
200
+ if (mapViewRef) {
201
+ mapViewRef.layersManager = new LayerManager(
202
+ mapViewRef,
203
+ props.legends?.mapLegendsExtractor,
204
+ () => {
205
+ setLegendsList(
206
+ mapViewRef?.layersManager?.legendsList as IMapLegend[]
207
+ );
208
+ }
209
+ );
210
+ }
211
+ }, [mapViewRef]);
212
+
182
213
  useEffect(() => {
183
214
  setSceneModes(
184
215
  props.sceneModes ?? [
@@ -326,27 +357,61 @@ export const CesiumMap: React.FC<CesiumMapProps> = (props) => {
326
357
  }
327
358
  }, [props.zoom, props.center, mapViewRef]);
328
359
 
360
+ const bindCustomToolsToViewer = useCallback((): JSX.Element | undefined => {
361
+ return (
362
+ mapViewRef &&
363
+ createPortal(
364
+ <>
365
+ <Box className="sideToolsContainer">
366
+ <CesiumSettings
367
+ sceneModes={sceneModes as CesiumSceneModeEnum[]}
368
+ baseMaps={baseMaps}
369
+ locale={locale}
370
+ />
371
+ <MapLegendToggle
372
+ onClick={(): void =>
373
+ setIsLegendsSidebarOpen(!isLegendsSidebarOpen)
374
+ }
375
+ />
376
+ </Box>
377
+ <Box className="toolsContainer">
378
+ {showMousePosition === true ? (
379
+ <CoordinatesTrackerTool projection={projection} />
380
+ ) : (
381
+ <></>
382
+ )}
383
+ {showScale === true ? <ScaleTrackerTool locale={locale} /> : <></>}
384
+ </Box>
385
+ </>,
386
+ document.querySelector('.cesium-viewer') as Element
387
+ )
388
+ );
389
+ }, [
390
+ baseMaps,
391
+ locale,
392
+ mapViewRef,
393
+ projection,
394
+ sceneModes,
395
+ showMousePosition,
396
+ showScale,
397
+ isLegendsSidebarOpen,
398
+ ]);
399
+
329
400
  return (
330
- <Viewer full ref={ref} {...viewerProps}>
401
+ <Viewer className="viewer" full ref={ref} {...viewerProps}>
331
402
  <MapViewProvider value={mapViewRef as CesiumViewer}>
403
+ <MapLegendSidebar
404
+ title={props.legends?.title}
405
+ isOpen={isLegendsSidebarOpen}
406
+ toggleSidebar={(): void =>
407
+ setIsLegendsSidebarOpen(!isLegendsSidebarOpen)
408
+ }
409
+ noLegendsText={props.legends?.emptyText}
410
+ legends={props.legends?.legendsList ?? legendsList}
411
+ actionsTexts={props.legends?.actionsTexts}
412
+ />
332
413
  {props.children}
333
- <Box className="sideToolsContainer">
334
- <CesiumSettings
335
- sceneModes={sceneModes as CesiumSceneModeEnum[]}
336
- baseMaps={baseMaps}
337
- locale={locale}
338
- />
339
- </Box>
340
- <Box className="toolsContainer">
341
- {showMousePosition === true ? (
342
- <CoordinatesTrackerTool
343
- projection={projection}
344
- ></CoordinatesTrackerTool>
345
- ) : (
346
- <></>
347
- )}
348
- {showScale === true ? <ScaleTrackerTool locale={locale} /> : <></>}
349
- </Box>
414
+ {bindCustomToolsToViewer()}
350
415
  {props.imageryContextMenu &&
351
416
  showImageryMenu &&
352
417
  imageryMenuPosition &&
@@ -1,15 +1,19 @@
1
1
  import {
2
- PolylineDashMaterialProperty,
3
- ConstantProperty,
4
- VerticalOrigin,
5
- LabelStyle,
2
+ BoundingSphere,
6
3
  Cartesian2,
7
4
  Cartesian3,
8
- BoundingSphere,
9
- Ellipsoid,
5
+ Cartographic,
6
+ CesiumTerrainProvider,
10
7
  ConstantPositionProperty,
8
+ ConstantProperty,
9
+ Ellipsoid,
10
+ EllipsoidTerrainProvider,
11
11
  GeographicTilingScheme,
12
- Cartographic,
12
+ LabelStyle,
13
+ PolylineDashMaterialProperty,
14
+ Rectangle,
15
+ Resource,
16
+ VerticalOrigin,
13
17
  } from 'cesium';
14
18
 
15
19
  // PROXIED CLASSES
@@ -31,6 +35,14 @@ export class CesiumEllipsoid extends Ellipsoid {}
31
35
 
32
36
  export class CesiumGeographicTilingScheme extends GeographicTilingScheme {}
33
37
 
38
+ export class CesiumRectangle extends Rectangle {}
39
+
40
+ export class CesiumResource extends Resource {}
41
+
42
+ export class CesiumEllipsoidTerrainProvider extends EllipsoidTerrainProvider {}
43
+
44
+ export class CesiumCesiumTerrainProvider extends CesiumTerrainProvider {}
45
+
34
46
  // PROXIED ENUMS
35
47
  // eslint-disable-next-line @typescript-eslint/naming-convention
36
48
  export const CesiumVerticalOrigin = VerticalOrigin;
@@ -3,7 +3,8 @@
3
3
  gap: 8px;
4
4
  }
5
5
 
6
- .settingsIconContainer {
6
+ .settingsIconContainer,
7
+ .mapLegendToggleContainer {
7
8
  fill: #fff;
8
9
  width: 40px;
9
10
  height: 40px;
@@ -12,7 +13,8 @@
12
13
  border-radius: 4px;
13
14
  }
14
15
 
15
- .settingsIconContainer:hover {
16
+ .settingsIconContainer:hover,
17
+ .mapLegendToggleContainer:hover {
16
18
  background: #48b;
17
19
  border-color: #aef;
18
20
  }
@@ -35,6 +37,7 @@
35
37
  .settingsDialogPortal .mdc-dialog__container {
36
38
  align-items: unset;
37
39
  }
40
+
38
41
  .settingsDialogPortal .mdc-dialog .mdc-dialog__surface {
39
42
  max-height: unset;
40
43
  }
@@ -3,8 +3,8 @@ import React, { useState } from 'react';
3
3
  import {
4
4
  ArcGISTiledElevationTerrainProvider,
5
5
  EllipsoidTerrainProvider,
6
- CesiumTerrainProvider,
7
- Resource,
6
+ // CesiumTerrainProvider,
7
+ // Resource,
8
8
  TerrainProvider,
9
9
  } from 'cesium';
10
10
  import { Story, Meta } from '@storybook/react/types-6-0';