@jupytergis/base 0.4.5 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (192) hide show
  1. package/lib/annotations/components/Annotation.d.ts +2 -2
  2. package/lib/annotations/components/Annotation.js +3 -3
  3. package/lib/annotations/components/AnnotationFloater.d.ts +1 -1
  4. package/lib/annotations/components/AnnotationFloater.js +2 -2
  5. package/lib/annotations/components/Message.d.ts +2 -1
  6. package/lib/annotations/components/Message.js +3 -3
  7. package/lib/annotations/model.js +5 -5
  8. package/lib/commands/BaseCommandIDs.d.ts +32 -0
  9. package/lib/commands/BaseCommandIDs.js +43 -0
  10. package/lib/{commands.d.ts → commands/index.d.ts} +1 -1
  11. package/lib/{commands.js → commands/index.js} +76 -319
  12. package/lib/console/consoleview.d.ts +3 -3
  13. package/lib/console/consoleview.js +5 -5
  14. package/lib/constants.d.ts +2 -51
  15. package/lib/constants.js +6 -65
  16. package/lib/dialogs/ProcessingFormDialog.d.ts +4 -4
  17. package/lib/dialogs/ProcessingFormDialog.js +9 -11
  18. package/lib/dialogs/layerBrowserDialog.d.ts +1 -1
  19. package/lib/dialogs/layerBrowserDialog.js +7 -7
  20. package/lib/dialogs/layerCreationFormDialog.d.ts +4 -4
  21. package/lib/dialogs/layerCreationFormDialog.js +6 -6
  22. package/lib/dialogs/symbology/components/color_ramp/CanvasSelectComponent.d.ts +1 -1
  23. package/lib/dialogs/symbology/components/color_ramp/CanvasSelectComponent.js +3 -3
  24. package/lib/dialogs/symbology/components/color_ramp/ColorRamp.d.ts +3 -2
  25. package/lib/dialogs/symbology/components/color_ramp/ColorRamp.js +6 -7
  26. package/lib/dialogs/symbology/components/color_ramp/ColorRampEntry.d.ts +1 -1
  27. package/lib/dialogs/symbology/components/color_ramp/ColorRampEntry.js +1 -1
  28. package/lib/dialogs/symbology/components/color_ramp/ModeSelectRow.d.ts +1 -1
  29. package/lib/dialogs/symbology/components/color_ramp/ModeSelectRow.js +1 -1
  30. package/lib/dialogs/symbology/components/color_stops/StopContainer.d.ts +2 -2
  31. package/lib/dialogs/symbology/components/color_stops/StopContainer.js +4 -4
  32. package/lib/dialogs/symbology/components/color_stops/StopRow.d.ts +3 -3
  33. package/lib/dialogs/symbology/components/color_stops/StopRow.js +2 -2
  34. package/lib/dialogs/symbology/hooks/useGetBandInfo.js +5 -5
  35. package/lib/dialogs/symbology/hooks/useGetProperties.d.ts +1 -1
  36. package/lib/dialogs/symbology/hooks/useGetProperties.js +4 -4
  37. package/lib/dialogs/symbology/symbologyDialog.d.ts +8 -0
  38. package/lib/dialogs/symbology/symbologyDialog.js +1 -1
  39. package/lib/dialogs/symbology/symbologyUtils.js +38 -31
  40. package/lib/dialogs/symbology/tiff_layer/TiffRendering.d.ts +2 -2
  41. package/lib/dialogs/symbology/tiff_layer/TiffRendering.js +2 -2
  42. package/lib/dialogs/symbology/tiff_layer/components/BandRow.d.ts +2 -2
  43. package/lib/dialogs/symbology/tiff_layer/components/BandRow.js +4 -4
  44. package/lib/dialogs/symbology/tiff_layer/types/MultibandColor.d.ts +2 -2
  45. package/lib/dialogs/symbology/tiff_layer/types/MultibandColor.js +30 -20
  46. package/lib/dialogs/symbology/tiff_layer/types/SingleBandPseudoColor.d.ts +2 -2
  47. package/lib/dialogs/symbology/tiff_layer/types/SingleBandPseudoColor.js +23 -21
  48. package/lib/dialogs/symbology/vector_layer/VectorRendering.d.ts +2 -2
  49. package/lib/dialogs/symbology/vector_layer/VectorRendering.js +81 -39
  50. package/lib/dialogs/symbology/vector_layer/components/ValueSelect.d.ts +1 -1
  51. package/lib/dialogs/symbology/vector_layer/components/ValueSelect.js +1 -1
  52. package/lib/dialogs/symbology/vector_layer/types/Canonical.d.ts +4 -0
  53. package/lib/dialogs/symbology/vector_layer/types/Canonical.js +66 -0
  54. package/lib/dialogs/symbology/vector_layer/types/Categorized.d.ts +2 -2
  55. package/lib/dialogs/symbology/vector_layer/types/Categorized.js +142 -47
  56. package/lib/dialogs/symbology/vector_layer/types/Graduated.d.ts +2 -2
  57. package/lib/dialogs/symbology/vector_layer/types/Graduated.js +193 -99
  58. package/lib/dialogs/symbology/vector_layer/types/Heatmap.d.ts +2 -2
  59. package/lib/dialogs/symbology/vector_layer/types/Heatmap.js +7 -6
  60. package/lib/dialogs/symbology/vector_layer/types/SimpleSymbol.d.ts +2 -2
  61. package/lib/dialogs/symbology/vector_layer/types/SimpleSymbol.js +33 -30
  62. package/lib/formbuilder/creationform.js +3 -3
  63. package/lib/formbuilder/editform.js +3 -3
  64. package/lib/formbuilder/formselectors.d.ts +1 -1
  65. package/lib/formbuilder/formselectors.js +2 -2
  66. package/lib/formbuilder/objectform/baseform.d.ts +5 -4
  67. package/lib/formbuilder/objectform/baseform.js +16 -14
  68. package/lib/formbuilder/objectform/fileselectorwidget.d.ts +1 -1
  69. package/lib/formbuilder/objectform/fileselectorwidget.js +5 -5
  70. package/lib/formbuilder/objectform/layer/heatmapLayerForm.js +2 -2
  71. package/lib/formbuilder/objectform/layer/hillshadeLayerForm.js +1 -1
  72. package/lib/formbuilder/objectform/layer/layerform.d.ts +1 -1
  73. package/lib/formbuilder/objectform/layer/layerform.js +3 -2
  74. package/lib/formbuilder/objectform/process/dissolveProcessForm.d.ts +1 -1
  75. package/lib/formbuilder/objectform/process/dissolveProcessForm.js +5 -5
  76. package/lib/formbuilder/objectform/source/geojsonsource.js +4 -4
  77. package/lib/formbuilder/objectform/source/geotiffsource.js +4 -4
  78. package/lib/formbuilder/objectform/source/pathbasedsource.js +6 -6
  79. package/lib/formbuilder/objectform/source/sourceform.d.ts +1 -1
  80. package/lib/formbuilder/objectform/source/sourceform.js +1 -1
  81. package/lib/formbuilder/objectform/source/tilesourceform.js +3 -3
  82. package/lib/gdal.js +2 -2
  83. package/lib/icons.js +29 -29
  84. package/lib/index.d.ts +4 -2
  85. package/lib/index.js +4 -2
  86. package/lib/mainview/CollaboratorPointers.d.ts +1 -1
  87. package/lib/mainview/CollaboratorPointers.js +5 -5
  88. package/lib/mainview/FollowIndicator.d.ts +2 -2
  89. package/lib/mainview/FollowIndicator.js +3 -3
  90. package/lib/mainview/TemporalSlider.d.ts +1 -1
  91. package/lib/mainview/TemporalSlider.js +7 -7
  92. package/lib/mainview/mainView.d.ts +4 -2
  93. package/lib/mainview/mainView.js +232 -137
  94. package/lib/menus.d.ts +4 -0
  95. package/lib/menus.js +45 -0
  96. package/lib/panelview/annotationPanel.d.ts +2 -2
  97. package/lib/panelview/annotationPanel.js +1 -1
  98. package/lib/panelview/components/filter-panel/Filter.d.ts +2 -2
  99. package/lib/panelview/components/filter-panel/Filter.js +5 -5
  100. package/lib/panelview/components/filter-panel/FilterRow.d.ts +2 -2
  101. package/lib/panelview/components/identify-panel/IdentifyPanel.d.ts +1 -1
  102. package/lib/panelview/components/identify-panel/IdentifyPanel.js +5 -5
  103. package/lib/panelview/components/layers.d.ts +1 -1
  104. package/lib/panelview/components/layers.js +12 -12
  105. package/lib/panelview/leftpanel.d.ts +4 -2
  106. package/lib/panelview/leftpanel.js +24 -14
  107. package/lib/panelview/model.d.ts +1 -1
  108. package/lib/panelview/objectproperties.d.ts +1 -1
  109. package/lib/panelview/objectproperties.js +3 -3
  110. package/lib/panelview/rightpanel.d.ts +2 -1
  111. package/lib/panelview/rightpanel.js +13 -5
  112. package/lib/{processing.d.ts → processing/index.d.ts} +4 -4
  113. package/lib/{processing.js → processing/index.js} +19 -24
  114. package/lib/processing/processingCommands.d.ts +6 -0
  115. package/lib/processing/processingCommands.js +47 -0
  116. package/lib/processing/processingFormToParam.d.ts +2 -0
  117. package/lib/processing/processingFormToParam.js +15 -0
  118. package/lib/shared/components/Badge.d.ts +7 -0
  119. package/lib/shared/components/Badge.js +19 -0
  120. package/lib/shared/components/Button.d.ts +9 -0
  121. package/lib/shared/components/Button.js +20 -0
  122. package/lib/shared/components/Calendar.d.ts +47 -0
  123. package/lib/shared/components/Calendar.js +184 -0
  124. package/lib/shared/components/Checkbox.d.ts +4 -0
  125. package/lib/shared/components/Checkbox.js +25 -0
  126. package/lib/shared/components/DropdownMenu.d.ts +27 -0
  127. package/lib/shared/components/DropdownMenu.js +92 -0
  128. package/lib/shared/components/Pagination.d.ts +25 -0
  129. package/lib/shared/components/Pagination.js +68 -0
  130. package/lib/shared/components/Popover.d.ts +7 -0
  131. package/lib/shared/components/Popover.js +32 -0
  132. package/lib/shared/components/Tabs.d.ts +7 -0
  133. package/lib/shared/components/Tabs.js +31 -0
  134. package/lib/shared/components/ToggleGroup.d.ts +12 -0
  135. package/lib/shared/components/ToggleGroup.js +52 -0
  136. package/lib/shared/components/loading.d.ts +12 -0
  137. package/lib/shared/components/loading.js +6 -0
  138. package/lib/shared/components/utils.d.ts +2 -0
  139. package/lib/shared/components/utils.js +4 -0
  140. package/lib/shared/hooks/useIsFirstRender.d.ts +2 -0
  141. package/lib/shared/hooks/useIsFirstRender.js +10 -0
  142. package/lib/stacBrowser/StacBrowser.d.ts +7 -0
  143. package/lib/stacBrowser/StacBrowser.js +16 -0
  144. package/lib/stacBrowser/StacPanel.d.ts +14 -0
  145. package/lib/stacBrowser/StacPanel.js +16 -0
  146. package/lib/stacBrowser/components/StacFilterSection.d.ts +23 -0
  147. package/lib/stacBrowser/components/StacFilterSection.js +49 -0
  148. package/lib/stacBrowser/components/StacPanelFilters.d.ts +14 -0
  149. package/lib/stacBrowser/components/StacPanelFilters.js +65 -0
  150. package/lib/stacBrowser/components/StacPanelResults.d.ts +13 -0
  151. package/lib/stacBrowser/components/StacPanelResults.js +48 -0
  152. package/lib/stacBrowser/components/StacPanelView.d.ts +7 -0
  153. package/lib/stacBrowser/components/StacPanelView.js +20 -0
  154. package/lib/stacBrowser/constants.d.ts +25 -0
  155. package/lib/stacBrowser/constants.js +197 -0
  156. package/lib/stacBrowser/hooks/useStacSearch.d.ts +30 -0
  157. package/lib/stacBrowser/hooks/useStacSearch.js +221 -0
  158. package/lib/stacBrowser/index.d.ts +1 -0
  159. package/lib/stacBrowser/index.js +1 -0
  160. package/lib/stacBrowser/types/types.d.ts +124 -0
  161. package/lib/stacBrowser/types/types.js +1 -0
  162. package/lib/statusbar/StatusBar.d.ts +1 -1
  163. package/lib/statusbar/StatusBar.js +3 -3
  164. package/lib/toolbar/index.d.ts +0 -1
  165. package/lib/toolbar/index.js +0 -1
  166. package/lib/toolbar/widget.js +28 -64
  167. package/lib/tools.d.ts +30 -5
  168. package/lib/tools.js +82 -69
  169. package/lib/types.d.ts +2 -0
  170. package/lib/widget.d.ts +2 -1
  171. package/lib/widget.js +8 -5
  172. package/package.json +22 -8
  173. package/style/base.css +26 -0
  174. package/style/layerBrowser.css +10 -0
  175. package/style/leftPanel.css +0 -1
  176. package/style/shared/badge.css +61 -0
  177. package/style/shared/button.css +164 -0
  178. package/style/shared/calendar.css +274 -0
  179. package/style/shared/checkbox.css +28 -0
  180. package/style/shared/dropdownMenu.css +240 -0
  181. package/style/shared/pagination.css +167 -0
  182. package/style/shared/popover.css +53 -0
  183. package/style/shared/tabs.css +57 -0
  184. package/style/shared/toggle.css +85 -0
  185. package/style/stacBrowser.css +74 -0
  186. package/style/symbologyDialog.css +0 -7
  187. package/lib/mainview/spinner.d.ts +0 -6
  188. package/lib/mainview/spinner.js +0 -5
  189. package/lib/panelview/components/sources.d.ts +0 -10
  190. package/lib/panelview/components/sources.js +0 -147
  191. package/lib/toolbar/usertoolbaritem.d.ts +0 -19
  192. package/lib/toolbar/usertoolbaritem.js +0 -59
@@ -1,66 +1,78 @@
1
- import { JupyterGISModel } from '@jupytergis/schema';
1
+ import { JupyterGISModel, } from '@jupytergis/schema';
2
2
  import { showErrorMessage } from '@jupyterlab/apputils';
3
3
  import { CommandRegistry } from '@lumino/commands';
4
4
  import { UUID } from '@lumino/coreutils';
5
5
  import { ContextMenu } from '@lumino/widgets';
6
6
  import { Collection, Map as OlMap, View, getUid } from 'ol';
7
- //@ts-expect-error no types for ol-pmtiles
8
- import { PMTilesRasterSource, PMTilesVectorSource } from 'ol-pmtiles';
9
7
  import Feature from 'ol/Feature';
10
- import { ScaleLine } from 'ol/control';
8
+ import { FullScreen, ScaleLine } from 'ol/control';
11
9
  import { singleClick } from 'ol/events/condition';
12
10
  import { GeoJSON, MVT } from 'ol/format';
11
+ import { Point } from 'ol/geom';
13
12
  import { DragAndDrop, Select } from 'ol/interaction';
14
- import { Heatmap as HeatmapLayer, Image as ImageLayer, Vector as VectorLayer, VectorTile as VectorTileLayer, WebGLTile as WebGlTileLayer } from 'ol/layer';
13
+ import { Heatmap as HeatmapLayer, Image as ImageLayer, Layer, Vector as VectorLayer, VectorTile as VectorTileLayer, WebGLTile as WebGlTileLayer, } from 'ol/layer';
15
14
  import TileLayer from 'ol/layer/Tile';
16
- import { fromLonLat, get as getRegisteredProjection, toLonLat, transformExtent } from 'ol/proj';
17
- import { get as getProjection } from 'ol/proj.js';
15
+ import { fromLonLat, get as getProjection, toLonLat, transformExtent, } from 'ol/proj';
18
16
  import { register } from 'ol/proj/proj4.js';
19
17
  import RenderFeature from 'ol/render/Feature';
20
- import { GeoTIFF as GeoTIFFSource, ImageTile as ImageTileSource, Vector as VectorSource, VectorTile as VectorTileSource, XYZ as XYZSource } from 'ol/source';
18
+ import { GeoTIFF as GeoTIFFSource, ImageTile as ImageTileSource, Vector as VectorSource, VectorTile as VectorTileSource, XYZ as XYZSource, } from 'ol/source';
21
19
  import Static from 'ol/source/ImageStatic';
22
20
  import TileSource from 'ol/source/Tile';
23
21
  import { Circle, Fill, Stroke, Style } from 'ol/style';
22
+ //@ts-expect-error no types for ol-pmtiles
23
+ import { PMTilesRasterSource, PMTilesVectorSource } from 'ol-pmtiles';
24
+ import StacLayer from 'ol-stac';
24
25
  import proj4 from 'proj4';
25
26
  import proj4list from 'proj4-list';
26
27
  import * as React from 'react';
27
- import AnnotationFloater from '../annotations/components/AnnotationFloater';
28
- import { CommandIDs } from '../constants';
29
- import StatusBar from '../statusbar/StatusBar';
30
- import { isLightTheme, loadFile, throttle } from '../tools';
28
+ import AnnotationFloater from "../annotations/components/AnnotationFloater";
29
+ import { CommandIDs } from "../constants";
30
+ import { LoadingOverlay } from "../shared/components/loading";
31
+ import StatusBar from "../statusbar/StatusBar";
32
+ import { debounce, isLightTheme, loadFile, throttle } from "../tools";
31
33
  import CollaboratorPointers from './CollaboratorPointers';
32
34
  import { FollowIndicator } from './FollowIndicator';
33
35
  import TemporalSlider from './TemporalSlider';
34
- import { Spinner } from './spinner';
35
- import { Point } from 'ol/geom';
36
36
  export class MainView extends React.Component {
37
37
  constructor(props) {
38
38
  super(props);
39
+ this.updateCenter = () => {
40
+ const extentIn4326 = this.getViewBbox();
41
+ this._model.updateBboxSignal.emit(extentIn4326);
42
+ };
43
+ this.getViewBbox = (targetProjection = 'EPSG:4326') => {
44
+ const view = this._Map.getView();
45
+ const extent = view.calculateExtent(this._Map.getSize());
46
+ if (view.getProjection().getCode() === targetProjection) {
47
+ return extent;
48
+ }
49
+ return transformExtent(extent, view.getProjection(), targetProjection);
50
+ };
39
51
  this.createSelectInteraction = () => {
40
52
  const pointStyle = new Style({
41
53
  image: new Circle({
42
54
  radius: 5,
43
55
  fill: new Fill({
44
- color: '#C52707'
56
+ color: '#C52707',
45
57
  }),
46
58
  stroke: new Stroke({
47
59
  color: '#171717',
48
- width: 2
49
- })
50
- })
60
+ width: 2,
61
+ }),
62
+ }),
51
63
  });
52
64
  const lineStyle = new Style({
53
65
  stroke: new Stroke({
54
66
  color: '#171717',
55
- width: 2
56
- })
67
+ width: 2,
68
+ }),
57
69
  });
58
70
  const polygonStyle = new Style({
59
71
  fill: new Fill({ color: '#C5270780' }),
60
72
  stroke: new Stroke({
61
73
  color: '#171717',
62
- width: 2
63
- })
74
+ width: 2,
75
+ }),
64
76
  });
65
77
  const styleFunction = (feature) => {
66
78
  var _a;
@@ -93,7 +105,7 @@ export class MainView extends React.Component {
93
105
  condition: (event) => {
94
106
  return singleClick(event) && this._model.isIdentifying;
95
107
  },
96
- style: styleFunction
108
+ style: styleFunction,
97
109
  });
98
110
  selectInteraction.on('select', event => {
99
111
  const identifiedFeatures = [];
@@ -112,23 +124,26 @@ export class MainView extends React.Component {
112
124
  return;
113
125
  }
114
126
  this._mainViewModel.addAnnotation({
115
- position: { x: this._clickCoords[0], y: this._clickCoords[1] },
127
+ position: {
128
+ x: this._clickCoords[0],
129
+ y: this._clickCoords[1],
130
+ },
116
131
  zoom: (_a = this._Map.getView().getZoom()) !== null && _a !== void 0 ? _a : 0,
117
132
  label: 'New annotation',
118
133
  contents: [],
119
134
  parent: this._Map.getViewport().id,
120
- open: true
135
+ open: true,
121
136
  });
122
137
  },
123
138
  label: 'Add annotation',
124
139
  isEnabled: () => {
125
140
  return !!this._Map;
126
- }
141
+ },
127
142
  });
128
143
  this._contextMenu.addItem({
129
144
  command: CommandIDs.addAnnotation,
130
145
  selector: '.ol-viewport',
131
- rank: 1
146
+ rank: 1,
132
147
  });
133
148
  };
134
149
  this.vectorLayerStyleRuleBuilder = (layer) => {
@@ -144,10 +159,10 @@ export class MainView extends React.Component {
144
159
  'circle-radius': 5,
145
160
  'circle-fill-color': 'rgba(255,255,255,0.4)',
146
161
  'circle-stroke-width': 1.25,
147
- 'circle-stroke-color': '#3399CC'
162
+ 'circle-stroke-color': '#3399CC',
148
163
  };
149
164
  const defaultRules = {
150
- style: defaultStyle
165
+ style: defaultStyle,
151
166
  };
152
167
  const layerStyle = Object.assign({}, defaultRules);
153
168
  if (((_a = layer.filters) === null || _a === void 0 ? void 0 : _a.logicalOp) && ((_b = layer.filters.appliedFilters) === null || _b === void 0 ? void 0 : _b.length) > 0) {
@@ -167,7 +182,7 @@ export class MainView extends React.Component {
167
182
  // Arguments for "Any" and 'All' need to be wrapped in brackets
168
183
  filterExpr = [
169
184
  layer.filters.logicalOp,
170
- ...layer.filters.appliedFilters.map(buildCondition)
185
+ ...layer.filters.appliedFilters.map(buildCondition),
171
186
  ];
172
187
  }
173
188
  layerStyle.filter = filterExpr;
@@ -202,7 +217,7 @@ export class MainView extends React.Component {
202
217
  ['*', 255 * 256, red],
203
218
  ['*', 255, green],
204
219
  ['*', 255 / 256, blue],
205
- -32768
220
+ -32768,
206
221
  ];
207
222
  }
208
223
  // Generates a shaded relief image given elevation data. Uses a 3x3
@@ -221,7 +236,7 @@ export class MainView extends React.Component {
221
236
  const cosIncidence = [
222
237
  '+',
223
238
  ['*', ['sin', sunEl], ['cos', slope]],
224
- ['*', ['cos', sunEl], ['sin', slope], ['cos', ['-', sunAz, aspect]]]
239
+ ['*', ['cos', sunEl], ['sin', slope], ['cos', ['-', sunAz, aspect]]],
225
240
  ];
226
241
  const scaled = ['*', 255, cosIncidence];
227
242
  return scaled;
@@ -319,7 +334,7 @@ export class MainView extends React.Component {
319
334
  if (pointer) {
320
335
  const pixel = this._Map.getPixelFromCoordinate([
321
336
  pointer.coordinates.x,
322
- pointer.coordinates.y
337
+ pointer.coordinates.y,
323
338
  ]);
324
339
  const lonLat = toLonLat([pointer.coordinates.x, pointer.coordinates.y]);
325
340
  if (!currentClientPointer) {
@@ -327,12 +342,24 @@ export class MainView extends React.Component {
327
342
  username: client.user.username,
328
343
  displayName: client.user.display_name,
329
344
  color: client.user.color,
330
- coordinates: { x: pixel[0], y: pixel[1] },
331
- lonLat: { longitude: lonLat[0], latitude: lonLat[1] }
345
+ coordinates: {
346
+ x: pixel[0],
347
+ y: pixel[1],
348
+ },
349
+ lonLat: {
350
+ longitude: lonLat[0],
351
+ latitude: lonLat[1],
352
+ },
332
353
  };
333
354
  }
334
355
  else {
335
- currentClientPointer = Object.assign(Object.assign({}, currentClientPointer), { coordinates: { x: pixel[0], y: pixel[1] }, lonLat: { longitude: lonLat[0], latitude: lonLat[1] } });
356
+ currentClientPointer = Object.assign(Object.assign({}, currentClientPointer), { coordinates: {
357
+ x: pixel[0],
358
+ y: pixel[1],
359
+ }, lonLat: {
360
+ longitude: lonLat[0],
361
+ latitude: lonLat[1],
362
+ } });
336
363
  }
337
364
  clientPointers[clientId] = currentClientPointer;
338
365
  }
@@ -373,24 +400,31 @@ export class MainView extends React.Component {
373
400
  return;
374
401
  }
375
402
  const data = this._model.sharedModel.getMetadata(key);
376
- let open = true;
377
- if (this.state.firstLoad) {
378
- open = false;
379
- }
380
403
  if (data && (val.action === 'add' || val.action === 'update')) {
381
- const jsonData = JSON.parse(data);
382
- jsonData['open'] = open;
404
+ let jsonData;
405
+ if (typeof data === 'string') {
406
+ try {
407
+ jsonData = JSON.parse(data);
408
+ }
409
+ catch (e) {
410
+ console.warn(`Failed to parse annotation data for ${key}:`, e);
411
+ return;
412
+ }
413
+ }
414
+ else {
415
+ jsonData = data;
416
+ }
383
417
  newState[key] = jsonData;
384
418
  }
385
419
  else if (val.action === 'delete') {
386
420
  delete newState[key];
387
421
  }
388
422
  });
389
- this.setState(old => (Object.assign(Object.assign({}, old), { annotations: newState, firstLoad: false })));
423
+ this.setState(old => (Object.assign(Object.assign({}, old), { annotations: newState })));
390
424
  };
391
425
  this._syncPointer = throttle((coordinates) => {
392
426
  const pointer = {
393
- coordinates: { x: coordinates[0], y: coordinates[1] }
427
+ coordinates: { x: coordinates[0], y: coordinates[1] },
394
428
  };
395
429
  this._model.syncPointer(pointer);
396
430
  });
@@ -407,6 +441,25 @@ export class MainView extends React.Component {
407
441
  this._ready = false;
408
442
  this._sourceToLayerMap = new Map();
409
443
  this._originalFeatures = {};
444
+ // Enforce the map to take the full available width in the case of Jupyter Notebook viewer
445
+ const el = document.getElementById('main-panel');
446
+ if (el) {
447
+ const setWidthOneHundred = (selector) => {
448
+ document.querySelector(selector).style.setProperty('width', '100%');
449
+ };
450
+ //We need to observe the size to counteract
451
+ //What the default jupyter plugin will try
452
+ //To do dynamically with the width
453
+ const resizeObserver = new ResizeObserver(_ => {
454
+ el.style.setProperty('width', '100%');
455
+ el.style.setProperty('max-width', '100%');
456
+ el === null || el === void 0 ? void 0 : el.style.setProperty('left', '0px');
457
+ setWidthOneHundred('#main-panel jp-toolbar');
458
+ setWidthOneHundred('#main-panel .lm-SplitPanel ');
459
+ setWidthOneHundred('#main-panel .lm-SplitPanel .lm-SplitPanel-child ');
460
+ });
461
+ resizeObserver.observe(el);
462
+ }
410
463
  this._mainViewModel = this.props.viewModel;
411
464
  this._mainViewModel.viewSettingChanged.connect(this._onViewChanged, this);
412
465
  this._model = this._mainViewModel.jGISModel;
@@ -436,7 +489,6 @@ export class MainView extends React.Component {
436
489
  id: this._mainViewModel.id,
437
490
  lightTheme: isLightTheme(),
438
491
  loading: true,
439
- firstLoad: true,
440
492
  annotations: {},
441
493
  clientPointers: {},
442
494
  viewProjection: { code: '', units: '' },
@@ -444,12 +496,15 @@ export class MainView extends React.Component {
444
496
  scale: 0,
445
497
  loadingErrors: [],
446
498
  displayTemporalController: false,
447
- filterStates: {}
499
+ filterStates: {},
448
500
  };
449
501
  this._sources = [];
450
502
  this._loadingLayers = new Set();
451
503
  this._commands = new CommandRegistry();
452
- this._contextMenu = new ContextMenu({ commands: this._commands });
504
+ this._contextMenu = new ContextMenu({
505
+ commands: this._commands,
506
+ });
507
+ this._updateCenter = debounce(this.updateCenter, 100);
453
508
  }
454
509
  async componentDidMount() {
455
510
  window.addEventListener('resize', this._handleWindowResize);
@@ -458,7 +513,7 @@ export class MainView extends React.Component {
458
513
  ? fromLonLat([options.longitude, options.latitude])
459
514
  : [0, 0];
460
515
  const zoom = options.zoom !== undefined ? options.zoom : 1;
461
- await this.generateScene(center, zoom);
516
+ await this.generateMap(center, zoom);
462
517
  this.addContextMenu();
463
518
  this._mainViewModel.initSignal();
464
519
  if (window.jupytergisMaps !== undefined && this._documentPath) {
@@ -476,27 +531,27 @@ export class MainView extends React.Component {
476
531
  this._model.clientStateChanged.disconnect(this._onClientSharedStateChanged, this);
477
532
  this._mainViewModel.dispose();
478
533
  }
479
- async generateScene(center, zoom) {
534
+ async generateMap(center, zoom) {
480
535
  if (this.divRef.current) {
481
536
  this._Map = new OlMap({
482
537
  target: this.divRef.current,
483
538
  layers: [],
484
539
  view: new View({
485
540
  center,
486
- zoom
541
+ zoom,
487
542
  }),
488
- controls: [new ScaleLine()]
543
+ controls: [new ScaleLine(), new FullScreen()],
489
544
  });
490
545
  // Add map interactions
491
546
  const dragAndDropInteraction = new DragAndDrop({
492
- formatConstructors: [GeoJSON]
547
+ formatConstructors: [GeoJSON],
493
548
  });
494
549
  dragAndDropInteraction.on('addfeatures', event => {
495
550
  const sourceId = UUID.uuid4();
496
551
  const sourceModel = {
497
552
  type: 'GeoJSONSource',
498
553
  name: 'Drag and Drop source',
499
- parameters: { path: event.file.name }
554
+ parameters: { path: event.file.name },
500
555
  };
501
556
  const layerId = UUID.uuid4();
502
557
  this.addSource(sourceId, sourceModel);
@@ -509,8 +564,8 @@ export class MainView extends React.Component {
509
564
  color: '#FF0000',
510
565
  opacity: 1.0,
511
566
  type: 'line',
512
- source: sourceId
513
- }
567
+ source: sourceId,
568
+ },
514
569
  };
515
570
  this.addLayer(layerId, layerModel, this.getLayerIDs().length);
516
571
  this._model.addLayer(layerId, layerModel);
@@ -518,6 +573,7 @@ export class MainView extends React.Component {
518
573
  this._Map.addInteraction(dragAndDropInteraction);
519
574
  this.createSelectInteraction();
520
575
  const view = this._Map.getView();
576
+ view.on('change:center', () => this._updateCenter());
521
577
  // TODO: Note for the future, will need to update listeners if view changes
522
578
  view.on('change:center', throttle(() => {
523
579
  var _a;
@@ -531,7 +587,13 @@ export class MainView extends React.Component {
531
587
  if (!center || !zoom) {
532
588
  return;
533
589
  }
534
- this._model.syncViewport({ coordinates: { x: center[0], y: center[1] }, zoom }, this._mainViewModel.id);
590
+ this._model.syncViewport({
591
+ coordinates: {
592
+ x: center[0],
593
+ y: center[1],
594
+ },
595
+ zoom,
596
+ }, this._mainViewModel.id);
535
597
  }));
536
598
  this._Map.on('postrender', () => {
537
599
  if (this.state.annotations) {
@@ -552,7 +614,7 @@ export class MainView extends React.Component {
552
614
  longitude: latLng[0],
553
615
  bearing,
554
616
  projection: projection.getCode(),
555
- zoom
617
+ zoom,
556
618
  };
557
619
  updatedOptions.extent = view.calculateExtent();
558
620
  this._model.setOptions(Object.assign(Object.assign({}, currentOptions), updatedOptions));
@@ -583,7 +645,7 @@ export class MainView extends React.Component {
583
645
  });
584
646
  this.setState(old => (Object.assign(Object.assign({}, old), { loading: false, viewProjection: {
585
647
  code: view.getProjection().getCode(),
586
- units: view.getProjection().getUnits()
648
+ units: view.getProjection().getUnits(),
587
649
  } })));
588
650
  }
589
651
  }
@@ -608,7 +670,7 @@ export class MainView extends React.Component {
608
670
  minZoom: sourceParameters.minZoom,
609
671
  maxZoom: sourceParameters.maxZoom,
610
672
  tileSize: 256,
611
- url: url
673
+ url: url,
612
674
  });
613
675
  }
614
676
  else {
@@ -616,7 +678,7 @@ export class MainView extends React.Component {
616
678
  interpolate: sourceParameters.interpolate,
617
679
  attributions: sourceParameters.attribution,
618
680
  tileSize: 256,
619
- url: url
681
+ url: url,
620
682
  });
621
683
  }
622
684
  break;
@@ -626,7 +688,7 @@ export class MainView extends React.Component {
626
688
  newSource = new ImageTileSource({
627
689
  interpolate: sourceParameters.interpolate,
628
690
  url: this.computeSourceUrl(source),
629
- attributions: sourceParameters.attribution
691
+ attributions: sourceParameters.attribution,
630
692
  });
631
693
  break;
632
694
  }
@@ -640,13 +702,15 @@ export class MainView extends React.Component {
640
702
  minZoom: sourceParameters.minZoom,
641
703
  maxZoom: sourceParameters.maxZoom,
642
704
  url: url,
643
- format: new MVT({ featureClass: RenderFeature })
705
+ format: new MVT({
706
+ featureClass: RenderFeature,
707
+ }),
644
708
  });
645
709
  }
646
710
  else {
647
711
  newSource = new PMTilesVectorSource({
648
712
  attributions: sourceParameters.attribution,
649
- url: url
713
+ url: url,
650
714
  });
651
715
  }
652
716
  break;
@@ -656,22 +720,22 @@ export class MainView extends React.Component {
656
720
  (await loadFile({
657
721
  filepath: (_b = source.parameters) === null || _b === void 0 ? void 0 : _b.path,
658
722
  type: 'GeoJSONSource',
659
- model: this._model
723
+ model: this._model,
660
724
  }));
661
725
  const format = new GeoJSON({
662
- featureProjection: this._Map.getView().getProjection()
726
+ featureProjection: this._Map.getView().getProjection(),
663
727
  });
664
728
  // TODO: Don't hardcode projection
665
729
  const featureArray = format.readFeatures(data, {
666
730
  dataProjection: 'EPSG:4326',
667
- featureProjection: this._Map.getView().getProjection()
731
+ featureProjection: this._Map.getView().getProjection(),
668
732
  });
669
733
  const featureCollection = new Collection(featureArray);
670
734
  featureCollection.forEach(feature => {
671
735
  feature.setId(getUid(feature));
672
736
  });
673
737
  newSource = new VectorSource({
674
- features: featureCollection
738
+ features: featureCollection,
675
739
  });
676
740
  break;
677
741
  }
@@ -680,15 +744,15 @@ export class MainView extends React.Component {
680
744
  const geojson = await loadFile({
681
745
  filepath: parameters.path,
682
746
  type: 'ShapefileSource',
683
- model: this._model
747
+ model: this._model,
684
748
  });
685
749
  const geojsonData = Array.isArray(geojson) ? geojson[0] : geojson;
686
750
  const format = new GeoJSON();
687
751
  newSource = new VectorSource({
688
752
  features: format.readFeatures(geojsonData, {
689
753
  dataProjection: 'EPSG:4326',
690
- featureProjection: this._Map.getView().getProjection()
691
- })
754
+ featureProjection: this._Map.getView().getProjection(),
755
+ }),
692
756
  });
693
757
  break;
694
758
  }
@@ -712,13 +776,13 @@ export class MainView extends React.Component {
712
776
  const imageUrl = await loadFile({
713
777
  filepath: sourceParameters.path,
714
778
  type: 'ImageSource',
715
- model: this._model
779
+ model: this._model,
716
780
  });
717
781
  newSource = new Static({
718
782
  interpolate: sourceParameters.interpolate,
719
783
  imageExtent: extent,
720
784
  url: imageUrl,
721
- crossOrigin: ''
785
+ crossOrigin: '',
722
786
  });
723
787
  break;
724
788
  }
@@ -742,7 +806,7 @@ export class MainView extends React.Component {
742
806
  const geotiff = await loadFile({
743
807
  filepath: (_c = sourceInfo.url) !== null && _c !== void 0 ? _c : '',
744
808
  type: 'GeoTiffSource',
745
- model: this._model
809
+ model: this._model,
746
810
  });
747
811
  return Object.assign(Object.assign({}, addNoData(sourceInfo)), { min: sourceInfo.min, max: sourceInfo.max, geotiff, url: URL.createObjectURL(geotiff.file) });
748
812
  }
@@ -751,7 +815,7 @@ export class MainView extends React.Component {
751
815
  interpolate: sourceParameters.interpolate,
752
816
  sources,
753
817
  normalize: sourceParameters.normalize,
754
- wrapX: sourceParameters.wrapX
818
+ wrapX: sourceParameters.wrapX,
755
819
  });
756
820
  break;
757
821
  }
@@ -863,19 +927,25 @@ export class MainView extends React.Component {
863
927
  */
864
928
  async _buildMapLayer(id, layer) {
865
929
  var _a, _b, _c;
866
- const sourceId = (_a = layer.parameters) === null || _a === void 0 ? void 0 : _a.source;
867
- const source = this._model.sharedModel.getLayerSource(sourceId);
868
- if (!source) {
869
- return;
870
- }
871
930
  this.setState(old => (Object.assign(Object.assign({}, old), { loadingLayer: true })));
872
931
  this._loadingLayers.add(id);
873
- if (!this._sources[sourceId]) {
874
- await this.addSource(sourceId, source);
875
- }
876
- this._loadingLayers.add(id);
877
932
  let newMapLayer;
878
933
  let layerParameters;
934
+ let sourceId;
935
+ let source;
936
+ if (layer.type !== 'StacLayer') {
937
+ sourceId = (_a = layer.parameters) === null || _a === void 0 ? void 0 : _a.source;
938
+ if (!sourceId) {
939
+ return;
940
+ }
941
+ source = this._model.sharedModel.getLayerSource(sourceId);
942
+ if (!source) {
943
+ return;
944
+ }
945
+ if (!this._sources[sourceId]) {
946
+ await this.addSource(sourceId, source);
947
+ }
948
+ }
879
949
  // TODO: OpenLayers provides a bunch of sources for specific tile
880
950
  // providers, so maybe set up some way to use those
881
951
  switch (layer.type) {
@@ -884,7 +954,7 @@ export class MainView extends React.Component {
884
954
  newMapLayer = new TileLayer({
885
955
  opacity: layerParameters.opacity,
886
956
  visible: layer.visible,
887
- source: this._sources[layerParameters.source]
957
+ source: this._sources[layerParameters.source],
888
958
  });
889
959
  break;
890
960
  }
@@ -894,7 +964,7 @@ export class MainView extends React.Component {
894
964
  opacity: layerParameters.opacity,
895
965
  visible: layer.visible,
896
966
  source: this._sources[layerParameters.source],
897
- style: this.vectorLayerStyleRuleBuilder(layer)
967
+ style: this.vectorLayerStyleRuleBuilder(layer),
898
968
  });
899
969
  break;
900
970
  }
@@ -902,7 +972,8 @@ export class MainView extends React.Component {
902
972
  layerParameters = layer.parameters;
903
973
  newMapLayer = new VectorTileLayer({
904
974
  opacity: layerParameters.opacity,
905
- source: this._sources[layerParameters.source]
975
+ source: this._sources[layerParameters.source],
976
+ style: this.vectorLayerStyleRuleBuilder(layer),
906
977
  });
907
978
  break;
908
979
  }
@@ -912,8 +983,8 @@ export class MainView extends React.Component {
912
983
  opacity: 0.3,
913
984
  source: this._sources[layerParameters.source],
914
985
  style: {
915
- color: ['color', this.hillshadeMath()]
916
- }
986
+ color: ['color', this.hillshadeMath()],
987
+ },
917
988
  });
918
989
  break;
919
990
  }
@@ -921,7 +992,7 @@ export class MainView extends React.Component {
921
992
  layerParameters = layer.parameters;
922
993
  newMapLayer = new ImageLayer({
923
994
  opacity: layerParameters.opacity,
924
- source: this._sources[layerParameters.source]
995
+ source: this._sources[layerParameters.source],
925
996
  });
926
997
  break;
927
998
  }
@@ -930,10 +1001,12 @@ export class MainView extends React.Component {
930
1001
  // This is to handle python sending a None for the color
931
1002
  const layerOptions = {
932
1003
  opacity: layerParameters.opacity,
933
- source: this._sources[layerParameters.source]
1004
+ source: this._sources[layerParameters.source],
934
1005
  };
935
1006
  if (layerParameters.color) {
936
- layerOptions['style'] = { color: layerParameters.color };
1007
+ layerOptions['style'] = {
1008
+ color: layerParameters.color,
1009
+ };
937
1010
  }
938
1011
  newMapLayer = new WebGlTileLayer(layerOptions);
939
1012
  break;
@@ -945,17 +1018,36 @@ export class MainView extends React.Component {
945
1018
  source: this._sources[layerParameters.source],
946
1019
  blur: (_b = layerParameters.blur) !== null && _b !== void 0 ? _b : 15,
947
1020
  radius: (_c = layerParameters.radius) !== null && _c !== void 0 ? _c : 8,
948
- gradient: layerParameters.color
1021
+ gradient: layerParameters.color,
1022
+ });
1023
+ break;
1024
+ }
1025
+ case 'StacLayer': {
1026
+ layerParameters = layer.parameters;
1027
+ newMapLayer = new StacLayer({
1028
+ displayPreview: true,
1029
+ data: layerParameters.data,
1030
+ opacity: layerParameters.opacity,
1031
+ visible: layer.visible,
1032
+ assets: Object.keys(layerParameters.data.assets),
1033
+ extent: layerParameters.data.bbox,
949
1034
  });
1035
+ this.setState(old => (Object.assign(Object.assign({}, old), { metadata: layerParameters.data.properties })));
950
1036
  break;
951
1037
  }
952
1038
  }
953
- await this._waitForSourceReady(newMapLayer);
954
1039
  // OpenLayers doesn't have name/id field so add it
955
1040
  newMapLayer.set('id', id);
956
- // we need to keep track of which source has which layers
957
- this._sourceToLayerMap.set(layerParameters.source, id);
958
- this.addProjection(newMapLayer);
1041
+ // STAC layers don't have source
1042
+ if (newMapLayer instanceof Layer) {
1043
+ // we need to keep track of which source has which layers
1044
+ // Only set sourceToLayerMap if 'source' exists on layerParameters
1045
+ if ('source' in layerParameters) {
1046
+ this._sourceToLayerMap.set(layerParameters.source, id);
1047
+ }
1048
+ this.addProjection(newMapLayer);
1049
+ await this._waitForSourceReady(newMapLayer);
1050
+ }
959
1051
  this._loadingLayers.delete(id);
960
1052
  return newMapLayer;
961
1053
  }
@@ -967,7 +1059,7 @@ export class MainView extends React.Component {
967
1059
  return;
968
1060
  }
969
1061
  const projectionCode = sourceProjection.getCode();
970
- const isProjectionRegistered = getRegisteredProjection(projectionCode);
1062
+ const isProjectionRegistered = getProjection(projectionCode);
971
1063
  if (!isProjectionRegistered) {
972
1064
  // Check if the projection exists in proj4list
973
1065
  if (!proj4list[projectionCode]) {
@@ -1016,7 +1108,7 @@ export class MainView extends React.Component {
1016
1108
  this.state.loadingErrors.push({
1017
1109
  id,
1018
1110
  error: error.message || 'invalid file path',
1019
- index
1111
+ index,
1020
1112
  });
1021
1113
  this._loadingLayers.delete(id);
1022
1114
  }
@@ -1029,18 +1121,10 @@ export class MainView extends React.Component {
1029
1121
  */
1030
1122
  async updateLayer(id, layer, mapLayer, oldLayer) {
1031
1123
  var _a, _b, _c, _d, _e, _f, _g, _h;
1032
- const sourceId = (_a = layer.parameters) === null || _a === void 0 ? void 0 : _a.source;
1033
- const source = this._model.sharedModel.getLayerSource(sourceId);
1034
- if (!source) {
1035
- return;
1036
- }
1037
- if (!this._sources[sourceId]) {
1038
- await this.addSource(sourceId, source);
1039
- }
1040
1124
  mapLayer.setVisible(layer.visible);
1041
1125
  switch (layer.type) {
1042
1126
  case 'RasterLayer': {
1043
- mapLayer.setOpacity(((_b = layer.parameters) === null || _b === void 0 ? void 0 : _b.opacity) || 1);
1127
+ mapLayer.setOpacity(((_a = layer.parameters) === null || _a === void 0 ? void 0 : _a.opacity) || 1);
1044
1128
  break;
1045
1129
  }
1046
1130
  case 'VectorLayer': {
@@ -1063,10 +1147,10 @@ export class MainView extends React.Component {
1063
1147
  break;
1064
1148
  }
1065
1149
  case 'WebGlLayer': {
1066
- mapLayer.setOpacity((_c = layer.parameters) === null || _c === void 0 ? void 0 : _c.opacity);
1067
- if ((_d = layer === null || layer === void 0 ? void 0 : layer.parameters) === null || _d === void 0 ? void 0 : _d.color) {
1150
+ mapLayer.setOpacity((_b = layer.parameters) === null || _b === void 0 ? void 0 : _b.opacity);
1151
+ if ((_c = layer === null || layer === void 0 ? void 0 : layer.parameters) === null || _c === void 0 ? void 0 : _c.color) {
1068
1152
  mapLayer.setStyle({
1069
- color: layer.parameters.color
1153
+ color: layer.parameters.color,
1070
1154
  });
1071
1155
  }
1072
1156
  break;
@@ -1074,13 +1158,16 @@ export class MainView extends React.Component {
1074
1158
  case 'HeatmapLayer': {
1075
1159
  const layerParams = layer.parameters;
1076
1160
  const heatmap = mapLayer;
1077
- heatmap.setOpacity((_e = layerParams.opacity) !== null && _e !== void 0 ? _e : 1);
1078
- heatmap.setBlur((_f = layerParams.blur) !== null && _f !== void 0 ? _f : 15);
1079
- heatmap.setRadius((_g = layerParams.radius) !== null && _g !== void 0 ? _g : 8);
1080
- heatmap.setGradient((_h = layerParams.color) !== null && _h !== void 0 ? _h : ['#00f', '#0ff', '#0f0', '#ff0', '#f00']);
1161
+ heatmap.setOpacity((_d = layerParams.opacity) !== null && _d !== void 0 ? _d : 1);
1162
+ heatmap.setBlur((_e = layerParams.blur) !== null && _e !== void 0 ? _e : 15);
1163
+ heatmap.setRadius((_f = layerParams.radius) !== null && _f !== void 0 ? _f : 8);
1164
+ heatmap.setGradient((_g = layerParams.color) !== null && _g !== void 0 ? _g : ['#00f', '#0ff', '#0f0', '#ff0', '#f00']);
1081
1165
  this.handleTemporalController(id, layer);
1082
1166
  break;
1083
1167
  }
1168
+ case 'StacLayer':
1169
+ mapLayer.setOpacity(((_h = layer.parameters) === null || _h === void 0 ? void 0 : _h.opacity) || 1);
1170
+ break;
1084
1171
  }
1085
1172
  }
1086
1173
  flyToGeometry(sender, geometry) {
@@ -1093,7 +1180,7 @@ export class MainView extends React.Component {
1093
1180
  view.fit(extent, {
1094
1181
  padding: [50, 50, 50, 50],
1095
1182
  duration: 1000,
1096
- maxZoom: 16
1183
+ maxZoom: 16,
1097
1184
  });
1098
1185
  }
1099
1186
  highlightFeatureOnMap(sender, featureOrGeometry) {
@@ -1108,7 +1195,7 @@ export class MainView extends React.Component {
1108
1195
  const parsedGeometry = isOlGeometry
1109
1196
  ? geometry
1110
1197
  : new GeoJSON().readGeometry(geometry, {
1111
- featureProjection: this._Map.getView().getProjection()
1198
+ featureProjection: this._Map.getView().getProjection(),
1112
1199
  });
1113
1200
  const olFeature = new Feature(Object.assign({ geometry: parsedGeometry }, (geometry !== featureOrGeometry ? featureOrGeometry : {})));
1114
1201
  if (!this._highlightLayer) {
@@ -1123,39 +1210,44 @@ export class MainView extends React.Component {
1123
1210
  return new Style({
1124
1211
  image: new Circle({
1125
1212
  radius: 6,
1126
- fill: new Fill({ color: 'rgba(255, 255, 0, 0.8)' }),
1127
- stroke: new Stroke({ color: '#ff0', width: 2 })
1128
- })
1213
+ fill: new Fill({
1214
+ color: 'rgba(255, 255, 0, 0.8)',
1215
+ }),
1216
+ stroke: new Stroke({
1217
+ color: '#ff0',
1218
+ width: 2,
1219
+ }),
1220
+ }),
1129
1221
  });
1130
1222
  case 'LineString':
1131
1223
  case 'MultiLineString':
1132
1224
  return new Style({
1133
1225
  stroke: new Stroke({
1134
1226
  color: 'rgba(255, 255, 0, 0.8)',
1135
- width: 3
1136
- })
1227
+ width: 3,
1228
+ }),
1137
1229
  });
1138
1230
  case 'Polygon':
1139
1231
  case 'MultiPolygon':
1140
1232
  return new Style({
1141
1233
  stroke: new Stroke({
1142
1234
  color: '#f00',
1143
- width: 2
1235
+ width: 2,
1144
1236
  }),
1145
1237
  fill: new Fill({
1146
- color: 'rgba(255, 255, 0, 0.8)'
1147
- })
1238
+ color: 'rgba(255, 255, 0, 0.8)',
1239
+ }),
1148
1240
  });
1149
1241
  default:
1150
1242
  return new Style({
1151
1243
  stroke: new Stroke({
1152
1244
  color: '#000',
1153
- width: 2
1154
- })
1245
+ width: 2,
1246
+ }),
1155
1247
  });
1156
1248
  }
1157
1249
  },
1158
- zIndex: 999
1250
+ zIndex: 999,
1159
1251
  });
1160
1252
  this._Map.addLayer(this._highlightLayer);
1161
1253
  }
@@ -1222,7 +1314,7 @@ export class MainView extends React.Component {
1222
1314
  }
1223
1315
  }
1224
1316
  async updateOptions(options) {
1225
- const { projection, extent, useExtent, latitude, longitude, zoom, bearing } = options;
1317
+ const { projection, extent, useExtent, latitude, longitude, zoom, bearing, } = options;
1226
1318
  let view = this._Map.getView();
1227
1319
  const currentProjection = view.getProjection().getCode();
1228
1320
  // Need to recreate view if the projection changes
@@ -1339,9 +1431,6 @@ export class MainView extends React.Component {
1339
1431
  }
1340
1432
  const mapLayer = this.getLayer(id);
1341
1433
  const layerTree = JupyterGISModel.getOrderedLayerIds(this._model);
1342
- if (!mapLayer) {
1343
- return;
1344
- }
1345
1434
  if (layerTree.includes(id)) {
1346
1435
  this.updateLayer(id, newLayer, mapLayer, oldLayer);
1347
1436
  }
@@ -1416,6 +1505,9 @@ export class MainView extends React.Component {
1416
1505
  const tileGrid = source.getTileGrid();
1417
1506
  extent = tileGrid === null || tileGrid === void 0 ? void 0 : tileGrid.getExtent();
1418
1507
  }
1508
+ if (layer instanceof StacLayer) {
1509
+ extent = layer.getExtent();
1510
+ }
1419
1511
  if (!extent) {
1420
1512
  console.warn('Layer has no extent.');
1421
1513
  return;
@@ -1428,7 +1520,7 @@ export class MainView extends React.Component {
1428
1520
  : extent;
1429
1521
  this._Map.getView().fit(transformedExtent, {
1430
1522
  size: this._Map.getSize(),
1431
- duration: 500
1523
+ duration: 500,
1432
1524
  });
1433
1525
  }
1434
1526
  _moveToPosition(center, zoom, duration = 1000) {
@@ -1438,7 +1530,10 @@ export class MainView extends React.Component {
1438
1530
  // Zoom needs to be set before changing center
1439
1531
  if (!view.animate === undefined) {
1440
1532
  view.animate({ zoom, duration });
1441
- view.animate({ center: [center.x, center.y], duration });
1533
+ view.animate({
1534
+ center: [center.x, center.y],
1535
+ duration,
1536
+ });
1442
1537
  }
1443
1538
  }
1444
1539
  _flyToPosition(center, zoom, duration = 1000) {
@@ -1529,7 +1624,7 @@ export class MainView extends React.Component {
1529
1624
  const screenPosition = this._computeAnnotationPosition(annotation);
1530
1625
  return (screenPosition && (React.createElement("div", { key: key, id: key, style: {
1531
1626
  left: screenPosition.x,
1532
- top: screenPosition.y
1627
+ top: screenPosition.y,
1533
1628
  }, className: 'jGIS-Popup-Wrapper' },
1534
1629
  React.createElement(AnnotationFloater, { itemId: key, annotationModel: this._model.annotationModel }))));
1535
1630
  }),
@@ -1538,14 +1633,14 @@ export class MainView extends React.Component {
1538
1633
  React.createElement("div", { className: "jGIS-Mainview data-jgis-keybinding", tabIndex: -2, style: {
1539
1634
  border: this.state.remoteUser
1540
1635
  ? `solid 3px ${this.state.remoteUser.color}`
1541
- : 'unset'
1636
+ : 'unset',
1542
1637
  } },
1543
- React.createElement(Spinner, { loading: this.state.loading }),
1638
+ React.createElement(LoadingOverlay, { loading: this.state.loading }),
1544
1639
  React.createElement(FollowIndicator, { remoteUser: this.state.remoteUser }),
1545
1640
  React.createElement(CollaboratorPointers, { clients: this.state.clientPointers }),
1546
1641
  React.createElement("div", { ref: this.divRef, style: {
1547
1642
  width: '100%',
1548
- height: '100%'
1643
+ height: '100%',
1549
1644
  } })),
1550
1645
  React.createElement(StatusBar, { jgisModel: this._model, loading: this.state.loadingLayer, projection: this.state.viewProjection, scale: this.state.scale }))));
1551
1646
  }