@jupytergis/base 0.1.2 → 0.1.4

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.
Binary file
@@ -1,8 +1,6 @@
1
1
  import { IJGISLayer, IJGISSource } from '@jupytergis/schema';
2
2
  import { User } from '@jupyterlab/services';
3
- import { FeatureLike } from 'ol/Feature';
4
3
  import BaseLayer from 'ol/layer/Base';
5
- import { Style } from 'ol/style';
6
4
  import * as React from 'react';
7
5
  import { MainViewModel } from './mainviewmodel';
8
6
  interface IProps {
@@ -49,6 +47,14 @@ export declare class MainView extends React.Component<IProps, IStates> {
49
47
  */
50
48
  updateLayers(layerIds: string[]): void;
51
49
  private _updateLayersImpl;
50
+ /**
51
+ * Build the map layer.
52
+ *
53
+ * @param id - id of the layer.
54
+ * @param layer - the layer object.
55
+ * @returns - the map layer.
56
+ */
57
+ private _buildMapLayer;
52
58
  /**
53
59
  * Add a layer to the map.
54
60
  *
@@ -57,19 +63,16 @@ export declare class MainView extends React.Component<IProps, IStates> {
57
63
  * @param index - expected index of the layer.
58
64
  */
59
65
  addLayer(id: string, layer: IJGISLayer, index: number): Promise<void>;
60
- vectorLayerStyleFunc: (currentFeature: FeatureLike, layer: IJGISLayer) => Style | undefined;
66
+ vectorLayerStyleRuleBuilder: (layer: IJGISLayer) => {
67
+ style: import("ol/style/flat").FlatStyle | Array<import("ol/style/flat").FlatStyle>;
68
+ filter?: import("ol/expr/expression").EncodedExpression | undefined;
69
+ else?: boolean | undefined;
70
+ }[] | undefined;
61
71
  /**
62
72
  * Taken from https://openlayers.org/en/latest/examples/webgl-shaded-relief.html
63
73
  * @returns
64
74
  */
65
75
  private hillshadeMath;
66
- /**
67
- * Move a layer in the stack.
68
- *
69
- * @param id - id of the layer.
70
- * @param index - expected index of the layer.
71
- */
72
- moveLayer(id: string, index: number | undefined): void;
73
76
  /**
74
77
  * Update a layer of the map.
75
78
  *
@@ -10,7 +10,6 @@ import { fromLonLat, toLonLat } from 'ol/proj';
10
10
  import Feature from 'ol/render/Feature';
11
11
  import { GeoTIFF as GeoTIFFSource, ImageTile as ImageTileSource, Vector as VectorSource, VectorTile as VectorTileSource, XYZ as XYZSource } from 'ol/source';
12
12
  import Static from 'ol/source/ImageStatic';
13
- import { Circle, Fill, Stroke, Style } from 'ol/style';
14
13
  //@ts-expect-error no types for ol-pmtiles
15
14
  import { PMTilesRasterSource, PMTilesVectorSource } from 'ol-pmtiles';
16
15
  import * as React from 'react';
@@ -20,73 +19,52 @@ import { Spinner } from './spinner';
20
19
  export class MainView extends React.Component {
21
20
  constructor(props) {
22
21
  super(props);
23
- this.vectorLayerStyleFunc = (currentFeature, layer) => {
24
- var _a;
25
- const layerParameters = layer.parameters;
26
- // const flatStyle = {
27
- // 'fill-color': 'rgba(255,255,255,0.4)',
28
- // 'stroke-color': '#3399CC',
29
- // 'stroke-width': 1.25,
30
- // 'circle-radius': 5,
31
- // 'circle-fill-color': 'rgba(255,255,255,0.4)',
32
- // 'circle-stroke-width': 1.25,
33
- // 'circle-stroke-color': '#3399CC'
34
- // };
35
- // TODO: Need to make a version that works with strings as well
36
- const operators = {
37
- '>': (a, b) => a > b,
38
- '<': (a, b) => a < b,
39
- '>=': (a, b) => a >= b,
40
- '<=': (a, b) => a <= b,
41
- '==': (a, b) => a === b,
42
- '!=': (a, b) => a !== b
22
+ this.vectorLayerStyleRuleBuilder = (layer) => {
23
+ const layerParams = layer.parameters;
24
+ if (!layerParams) {
25
+ return;
26
+ }
27
+ const defaultStyle = {
28
+ 'fill-color': 'rgba(255,255,255,0.4)',
29
+ 'stroke-color': '#3399CC',
30
+ 'stroke-width': 1.25,
31
+ 'circle-radius': 5,
32
+ 'circle-fill-color': 'rgba(255,255,255,0.4)',
33
+ 'circle-stroke-width': 1.25,
34
+ 'circle-stroke-color': '#3399CC'
43
35
  };
44
- // TODO: I don't think this will work with fancy color expressions
45
- const fill = new Fill({
46
- color: layerParameters.type === 'fill' || layerParameters.type === 'circle'
47
- ? layerParameters.color
48
- : 'rgba(0, 0, 0, 0)'
49
- });
50
- const stroke = new Stroke({
51
- color: layerParameters.type === 'line' || layerParameters.type === 'circle'
52
- ? layerParameters.color
53
- : '#392F5A',
54
- width: 2
55
- });
56
- const style = new Style({
57
- fill,
58
- stroke,
59
- image: new Circle({
60
- radius: 5,
61
- fill,
62
- stroke
63
- })
64
- });
65
- if (layer.filters && ((_a = layer.filters) === null || _a === void 0 ? void 0 : _a.appliedFilters.length) !== 0) {
66
- const props = currentFeature.getProperties();
67
- let shouldDisplayFeature = true;
68
- switch (layer.filters.logicalOp) {
69
- case 'any': {
70
- // Display the feature if any filter conditions apply
71
- shouldDisplayFeature = layer.filters.appliedFilters.some(({ feature, operator, value }) => operators[operator](props[feature], value));
72
- break;
73
- }
74
- case 'all': {
75
- // Display the feature only if all the filter conditions apply
76
- shouldDisplayFeature = layer.filters.appliedFilters.every(({ feature, operator, value }) => operators[operator](props[feature], value));
77
- break;
78
- }
79
- }
80
- if (shouldDisplayFeature) {
81
- return style;
36
+ const defaultRules = {
37
+ style: defaultStyle
38
+ };
39
+ const layerStyle = Object.assign({}, defaultRules);
40
+ if (layer.filters && layer.filters.appliedFilters.length !== 0) {
41
+ const filterExpr = [];
42
+ // 'Any' and 'All' operators require more than one argument
43
+ // So if there's only one filter, skip that part to avoid error
44
+ if (layer.filters.appliedFilters.length === 1) {
45
+ layer.filters.appliedFilters.forEach(filter => {
46
+ filterExpr.push(filter.operator, ['get', filter.feature], filter.value);
47
+ });
82
48
  }
83
49
  else {
84
- return undefined;
50
+ filterExpr.push(layer.filters.logicalOp);
51
+ // Arguments for "Any" and 'All' need to be wrapped in brackets
52
+ layer.filters.appliedFilters.forEach(filter => {
53
+ filterExpr.push([
54
+ filter.operator,
55
+ ['get', filter.feature],
56
+ filter.value
57
+ ]);
58
+ });
85
59
  }
60
+ layerStyle.filter = filterExpr;
86
61
  }
87
- else {
88
- return style;
62
+ if (!layerParams.color) {
63
+ return [layerStyle];
89
64
  }
65
+ const newStyle = Object.assign(Object.assign({}, defaultStyle), layerParams.color);
66
+ layerStyle.style = newStyle;
67
+ return [layerStyle];
90
68
  };
91
69
  /**
92
70
  * Taken from https://openlayers.org/en/latest/examples/webgl-shaded-relief.html
@@ -237,16 +215,14 @@ export class MainView extends React.Component {
237
215
  projection: projection.getCode(),
238
216
  zoom
239
217
  };
240
- // Update the extent only if has been initially provided.
241
- if (currentOptions.extent) {
242
- updatedOptions.extent = view.calculateExtent();
243
- }
218
+ updatedOptions.extent = view.calculateExtent();
244
219
  this._model.setOptions(Object.assign(Object.assign({}, currentOptions), updatedOptions));
245
220
  });
246
221
  if (JupyterGISModel.getOrderedLayerIds(this._model).length !== 0) {
247
222
  await this._updateLayersImpl(JupyterGISModel.getOrderedLayerIds(this._model));
248
223
  const options = this._model.getOptions();
249
224
  this.updateOptions(options);
225
+ this._initializedPosition = true;
250
226
  }
251
227
  this.setState(old => (Object.assign(Object.assign({}, old), { loading: false })));
252
228
  }
@@ -447,59 +423,30 @@ export class MainView extends React.Component {
447
423
  this._updateLayersImpl(layerIds);
448
424
  }
449
425
  async _updateLayersImpl(layerIds) {
450
- const previousLayerIds = this.getLayers();
451
- // We use the reverse order of the list to add the layer from the top to the
452
- // bottom.
453
- // This is to ensure that the beforeId (layer on top of the one we add/move)
454
- // is already added/moved in the map.
455
- const reversedLayerIds = layerIds.slice().reverse();
456
- for (const layerId of reversedLayerIds) {
426
+ const mapLayers = [];
427
+ for (const layerId of layerIds) {
457
428
  const layer = this._model.sharedModel.getLayer(layerId);
458
429
  if (!layer) {
459
430
  console.log(`Layer id ${layerId} does not exist`);
460
- return;
431
+ continue;
461
432
  }
462
- // Get the expected index in the map.
463
- const currentLayerIds = [...previousLayerIds];
464
- let indexInMap = currentLayerIds.length;
465
- const nextLayer = layerIds[layerIds.indexOf(layerId) + 1];
466
- if (nextLayer !== undefined) {
467
- indexInMap = currentLayerIds.indexOf(nextLayer);
468
- if (indexInMap === -1) {
469
- indexInMap = currentLayerIds.length;
470
- }
471
- }
472
- if (this.getLayer(layerId)) {
473
- this.moveLayer(layerId, indexInMap);
474
- }
475
- else {
476
- await this.addLayer(layerId, layer, indexInMap);
477
- }
478
- // Remove the element of the previous list as treated.
479
- const index = previousLayerIds.indexOf(layerId);
480
- if (index > -1) {
481
- previousLayerIds.splice(index, 1);
433
+ const newMapLayer = await this._buildMapLayer(layerId, layer);
434
+ if (newMapLayer !== undefined) {
435
+ mapLayers.push(newMapLayer);
482
436
  }
483
437
  }
484
- // Remove the layers not used anymore.
485
- previousLayerIds.forEach(layerId => {
486
- this._Map.removeLayer(layerId);
487
- });
438
+ this._Map.setLayers(mapLayers);
488
439
  this._ready = true;
489
440
  }
490
441
  /**
491
- * Add a layer to the map.
442
+ * Build the map layer.
492
443
  *
493
444
  * @param id - id of the layer.
494
445
  * @param layer - the layer object.
495
- * @param index - expected index of the layer.
446
+ * @returns - the map layer.
496
447
  */
497
- async addLayer(id, layer, index) {
448
+ async _buildMapLayer(id, layer) {
498
449
  var _a;
499
- if (this.getLayer(id)) {
500
- // Layer already exists
501
- return;
502
- }
503
450
  const sourceId = (_a = layer.parameters) === null || _a === void 0 ? void 0 : _a.source;
504
451
  const source = this._model.sharedModel.getSource(sourceId);
505
452
  if (!source) {
@@ -508,14 +455,14 @@ export class MainView extends React.Component {
508
455
  if (!this._sources[sourceId]) {
509
456
  await this.addSource(sourceId, source);
510
457
  }
511
- let newLayer;
458
+ let newMapLayer;
512
459
  let layerParameters;
513
460
  // TODO: OpenLayers provides a bunch of sources for specific tile
514
461
  // providers, so maybe set up some way to use those
515
462
  switch (layer.type) {
516
463
  case 'RasterLayer': {
517
464
  layerParameters = layer.parameters;
518
- newLayer = new TileLayer({
465
+ newMapLayer = new TileLayer({
519
466
  opacity: layerParameters.opacity,
520
467
  visible: layer.visible,
521
468
  source: this._sources[layerParameters.source]
@@ -524,26 +471,29 @@ export class MainView extends React.Component {
524
471
  }
525
472
  case 'VectorLayer': {
526
473
  layerParameters = layer.parameters;
527
- newLayer = new VectorLayer({
474
+ newMapLayer = new VectorLayer({
528
475
  opacity: layerParameters.opacity,
529
476
  visible: layer.visible,
530
477
  source: this._sources[layerParameters.source],
531
- style: currentFeature => this.vectorLayerStyleFunc(currentFeature, layer)
478
+ style: this.vectorLayerStyleRuleBuilder(layer)
532
479
  });
533
480
  break;
534
481
  }
535
482
  case 'VectorTileLayer': {
536
483
  layerParameters = layer.parameters;
537
- newLayer = new VectorTileLayer({
484
+ if (!layerParameters.color) {
485
+ return;
486
+ }
487
+ newMapLayer = new VectorTileLayer({
538
488
  opacity: layerParameters.opacity,
539
- source: this._sources[layerParameters.source],
540
- style: currentFeature => this.vectorLayerStyleFunc(currentFeature, layer)
489
+ source: this._sources[layerParameters.source]
541
490
  });
491
+ this.updateLayer(id, layer, newMapLayer);
542
492
  break;
543
493
  }
544
494
  case 'HillshadeLayer': {
545
495
  layerParameters = layer.parameters;
546
- newLayer = new WebGlTileLayer({
496
+ newMapLayer = new WebGlTileLayer({
547
497
  opacity: 0.3,
548
498
  source: this._sources[layerParameters.source],
549
499
  style: {
@@ -554,7 +504,7 @@ export class MainView extends React.Component {
554
504
  }
555
505
  case 'ImageLayer': {
556
506
  layerParameters = layer.parameters;
557
- newLayer = new ImageLayer({
507
+ newMapLayer = new ImageLayer({
558
508
  opacity: layerParameters.opacity,
559
509
  source: this._sources[layerParameters.source]
560
510
  });
@@ -570,43 +520,32 @@ export class MainView extends React.Component {
570
520
  if (layerParameters.color) {
571
521
  layerOptions['style'] = { color: layerParameters.color };
572
522
  }
573
- newLayer = new WebGlTileLayer(layerOptions);
523
+ newMapLayer = new WebGlTileLayer(layerOptions);
574
524
  break;
575
525
  }
576
526
  }
577
527
  // OpenLayers doesn't have name/id field so add it
578
- newLayer.set('id', id);
528
+ newMapLayer.set('id', id);
579
529
  // we need to keep track of which source has which layers
580
530
  this._sourceToLayerMap.set(layerParameters.source, id);
581
- this._Map.getLayers().insertAt(index, newLayer);
531
+ return newMapLayer;
582
532
  }
583
533
  /**
584
- * Move a layer in the stack.
534
+ * Add a layer to the map.
585
535
  *
586
536
  * @param id - id of the layer.
537
+ * @param layer - the layer object.
587
538
  * @param index - expected index of the layer.
588
539
  */
589
- moveLayer(id, index) {
590
- // Get the beforeId value according to the expected index.
591
- const currentLayerIds = this.getLayers();
592
- let beforeId = undefined;
593
- if (!(index === undefined) && index < currentLayerIds.length) {
594
- beforeId = currentLayerIds[index];
595
- }
596
- const layerArray = this._Map.getLayers().getArray();
597
- const movingLayer = this.getLayer(id);
598
- if (!movingLayer || !index || !beforeId) {
540
+ async addLayer(id, layer, index) {
541
+ if (this.getLayer(id)) {
542
+ // Layer already exists
599
543
  return;
600
544
  }
601
- const indexOfMovingLayer = layerArray.indexOf(movingLayer);
602
- layerArray.splice(indexOfMovingLayer, 1);
603
- const beforeLayer = this.getLayer(beforeId);
604
- if (!beforeLayer) {
605
- return;
545
+ const newMapLayer = await this._buildMapLayer(id, layer);
546
+ if (newMapLayer !== undefined) {
547
+ this._Map.getLayers().insertAt(index, newMapLayer);
606
548
  }
607
- const indexOfBeforeLayer = layerArray.indexOf(beforeLayer);
608
- layerArray.splice(indexOfBeforeLayer, 0, movingLayer);
609
- this._Map.setLayers(layerArray);
610
549
  }
611
550
  /**
612
551
  * Update a layer of the map.
@@ -633,13 +572,13 @@ export class MainView extends React.Component {
633
572
  case 'VectorLayer': {
634
573
  const layerParams = layer.parameters;
635
574
  mapLayer.setOpacity(layerParams.opacity || 1);
636
- mapLayer.setStyle(currentFeature => this.vectorLayerStyleFunc(currentFeature, layer));
575
+ mapLayer.setStyle(this.vectorLayerStyleRuleBuilder(layer));
637
576
  break;
638
577
  }
639
578
  case 'VectorTileLayer': {
640
579
  const layerParams = layer.parameters;
641
580
  mapLayer.setOpacity(layerParams.opacity || 1);
642
- mapLayer.setStyle(currentFeature => this.vectorLayerStyleFunc(currentFeature, layer));
581
+ mapLayer.setStyle(this.vectorLayerStyleRuleBuilder(layer));
643
582
  break;
644
583
  }
645
584
  case 'HillshadeLayer': {
@@ -680,14 +619,19 @@ export class MainView extends React.Component {
680
619
  }
681
620
  updateOptions(options) {
682
621
  const view = this._Map.getView();
683
- // use the extent if provided.
684
- if (options.extent) {
622
+ // Use the extent only if explicitly requested (QGIS files).
623
+ if (options.extent && options.useExtent) {
685
624
  view.fit(options.extent);
686
625
  }
687
626
  else {
688
627
  const centerCoord = fromLonLat([options.longitude || 0, options.latitude || 0], this._Map.getView().getProjection());
689
628
  this._Map.getView().setZoom(options.zoom || 0);
690
629
  this._Map.getView().setCenter(centerCoord);
630
+ // Save the extent if it does not exists, to allow proper export to qgis.
631
+ if (options.extent === undefined) {
632
+ options.extent = view.calculateExtent();
633
+ this._model.setOptions(options);
634
+ }
691
635
  }
692
636
  view.setRotation(options.bearing || 0);
693
637
  }
@@ -727,12 +671,14 @@ export class MainView extends React.Component {
727
671
  }
728
672
  else {
729
673
  const mapLayer = this.getLayer(change.id);
730
- if (mapLayer &&
731
- JupyterGISModel.getOrderedLayerIds(this._model).includes(change.id)) {
732
- this.updateLayer(change.id, layer, mapLayer);
733
- }
734
- else {
735
- this.updateLayers(JupyterGISModel.getOrderedLayerIds(this._model));
674
+ const layerTree = JupyterGISModel.getOrderedLayerIds(this._model);
675
+ if (mapLayer) {
676
+ if (layerTree.includes(change.id)) {
677
+ this.updateLayer(change.id, layer, mapLayer);
678
+ }
679
+ else {
680
+ this.updateLayers(layerTree);
681
+ }
736
682
  }
737
683
  }
738
684
  });
@@ -132,8 +132,8 @@ function LayerGroupComponent(props) {
132
132
  setId(DOMUtils.createDomID());
133
133
  const getExpandedState = async () => {
134
134
  var _a;
135
- const groupState = await state.fetch(group.name);
136
- setOpen(groupState ? ((_a = groupState['expanded']) !== null && _a !== void 0 ? _a : false) : false);
135
+ const groupState = await state.fetch(`jupytergis:${group.name}`);
136
+ setOpen((_a = groupState.expanded) !== null && _a !== void 0 ? _a : false);
137
137
  };
138
138
  getExpandedState();
139
139
  }, []);
@@ -156,7 +156,7 @@ function LayerGroupComponent(props) {
156
156
  onClick({ type: 'group', item: name, nodeId: childId, event });
157
157
  };
158
158
  const handleExpand = async () => {
159
- state.save(group.name, { expanded: !open });
159
+ state.save(`jupytergis:${group.name}`, { expanded: !open });
160
160
  setOpen(!open);
161
161
  };
162
162
  return (React.createElement("div", { className: `${LAYER_ITEM_CLASS} ${LAYER_GROUP_CLASS}`, draggable: true, onDragStart: Private.onDragStart, onDragEnd: Private.onDragEnd, "data-id": name },
package/lib/tools.d.ts CHANGED
@@ -23,3 +23,12 @@ export declare function deepCopy<T = IDict<any>>(value: T): T;
23
23
  export declare function createDefaultLayerRegistry(layerBrowserRegistry: IJGISLayerBrowserRegistry): void;
24
24
  export declare function getLayerTileInfo(tileUrl: string, mapOptions: Pick<IJGISOptions, 'latitude' | 'longitude' | 'extent' | 'zoom'>, urlParameters?: IDict<string>): Promise<VectorTile>;
25
25
  export declare function getSourceLayerNames(tileUrl: string, urlParameters?: IDict<string>): Promise<string[]>;
26
+ export interface IParsedStyle {
27
+ fillColor: string;
28
+ strokeColor: string;
29
+ strokeWidth: number;
30
+ joinStyle: string;
31
+ capStyle: string;
32
+ radius?: number;
33
+ }
34
+ export declare function parseColor(type: string, style: any): IParsedStyle | undefined;
package/lib/tools.js CHANGED
@@ -170,6 +170,10 @@ function getTileCoordinates(latDeg, lonDeg, zoom) {
170
170
  const n = 1 << zoom;
171
171
  const xTile = Math.floor(((lonDeg + 180.0) / 360.0) * n);
172
172
  const yTile = Math.floor((n * (1 - Math.log(Math.tan(latRad) + 1 / Math.cos(latRad)) / Math.PI)) / 2);
173
+ // Check if either xTile or yTile is NaN
174
+ if (isNaN(xTile) || isNaN(yTile)) {
175
+ return { xTile: 0, yTile: 0 };
176
+ }
173
177
  return { xTile, yTile };
174
178
  }
175
179
  export async function getLayerTileInfo(tileUrl, mapOptions, urlParameters) {
@@ -213,3 +217,37 @@ export async function getSourceLayerNames(tileUrl, urlParameters) {
213
217
  const layerNames = Object.keys(tile.layers);
214
218
  return layerNames;
215
219
  }
220
+ export function parseColor(type, style) {
221
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l;
222
+ if (!type || !style) {
223
+ return;
224
+ }
225
+ const type2 = type === 'circle' ? 'circle' : 'default';
226
+ const shapeStyles = {
227
+ circle: {
228
+ radius: (_a = style['circle-radius']) !== null && _a !== void 0 ? _a : 5,
229
+ fillColor: (_b = style['circle-fill-color']) !== null && _b !== void 0 ? _b : '#3399CC',
230
+ strokeColor: (_c = style['circle-stroke-color']) !== null && _c !== void 0 ? _c : '#3399CC',
231
+ strokeWidth: (_d = style['circle-stroke-width']) !== null && _d !== void 0 ? _d : 1.25,
232
+ joinStyle: (_e = style['circle-stroke-line-join']) !== null && _e !== void 0 ? _e : 'round',
233
+ capStyle: (_f = style['circle-stroke-line-cap']) !== null && _f !== void 0 ? _f : 'round'
234
+ },
235
+ default: {
236
+ fillColor: (_g = style['fill-color']) !== null && _g !== void 0 ? _g : '[255, 255, 255, 0.4]',
237
+ strokeColor: (_h = style['stroke-color']) !== null && _h !== void 0 ? _h : '#3399CC',
238
+ strokeWidth: (_j = style['stroke-width']) !== null && _j !== void 0 ? _j : 1.25,
239
+ capStyle: (_k = style['stroke-line-cap']) !== null && _k !== void 0 ? _k : 'round',
240
+ joinStyle: (_l = style['stroke-line-join']) !== null && _l !== void 0 ? _l : 'round'
241
+ }
242
+ };
243
+ const parsedStyle = shapeStyles[type2];
244
+ Object.assign(parsedStyle, {
245
+ radius: parsedStyle.radius,
246
+ fillColor: parsedStyle.fillColor,
247
+ strokeColor: parsedStyle.strokeColor,
248
+ strokeWidth: parsedStyle.strokeWidth,
249
+ joinStyle: parsedStyle.joinStyle,
250
+ capStyle: parsedStyle.capStyle
251
+ });
252
+ return parsedStyle;
253
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jupytergis/base",
3
- "version": "0.1.2",
3
+ "version": "0.1.4",
4
4
  "description": "A JupyterLab extension for 3D modelling.",
5
5
  "keywords": [
6
6
  "jupyter",
@@ -16,7 +16,7 @@
16
16
  "name": "JupyterGIS contributors"
17
17
  },
18
18
  "files": [
19
- "lib/**/*.{d.ts,eot,gif,html,jpg,js,js.map,json,png,svg,woff2,ttf}",
19
+ "lib/**/*.{d.ts,eot,gif,html,jpg,js,js.map,json,png,svg,woff2,ttf,data,wasm}",
20
20
  "style/**/*.{css,js,eot,gif,html,jpg,json,png,svg,woff2,ttf}"
21
21
  ],
22
22
  "main": "lib/index.js",
@@ -27,10 +27,11 @@
27
27
  "url": "https://github.com/geojupyter/jupytergis.git"
28
28
  },
29
29
  "scripts": {
30
- "build": "jlpm run build:gallery && tsc -b",
30
+ "build": "jlpm run build:gallery && tsc -b && jlpm run cp:gdal",
31
31
  "build:gallery": "python rasterlayer_gallery_generator.py",
32
+ "cp:gdal": "cp ../../node_modules/gdal3.js/dist/package/gdal3WebAssembly.data lib && cp ../../node_modules/gdal3.js/dist/package/gdal3WebAssembly.wasm lib",
32
33
  "build:prod": "jlpm run clean && jlpm run build",
33
- "build:dev": "tsc -b",
34
+ "build:dev": "tsc -b && jlpm run cp:gdal",
34
35
  "clean": "rimraf tsconfig.tsbuildinfo",
35
36
  "clean:lib": "rimraf lib tsconfig.tsbuildinfo",
36
37
  "clean:all": "jlpm run clean:lib",
@@ -40,7 +41,7 @@
40
41
  "@deathbeds/jupyterlab-rjsf": "^1.1.0",
41
42
  "@jupyter/docprovider": "^2.0.0",
42
43
  "@jupyter/ydoc": "^1.0.0",
43
- "@jupytergis/schema": "^0.1.2",
44
+ "@jupytergis/schema": "^0.1.4",
44
45
  "@jupyterlab/application": "^4.0.0",
45
46
  "@jupyterlab/apputils": "^4.0.0",
46
47
  "@jupyterlab/completer": "^4.2.4",
@@ -21,7 +21,8 @@
21
21
  flex: 0 1 20%;
22
22
  }
23
23
 
24
- .jp-gis-symbology-row > .jp-select-wrapper {
24
+ .jp-gis-symbology-row > .jp-select-wrapper,
25
+ .jp-gis-symbology-row > .jp-mod-styled {
25
26
  flex: 1 0 50%;
26
27
  max-width: 50%;
27
28
  }
@@ -35,6 +36,13 @@
35
36
  .jp-gis-layer-symbology-container {
36
37
  display: flex;
37
38
  flex-direction: column;
39
+ gap: 13px;
40
+ border-top: 1px solid var(--jp-border-color2);
41
+ padding-top: 8px;
42
+ }
43
+
44
+ .jp-gis-layer-symbology-container .jp-select-wrapper {
45
+ margin-bottom: unset;
38
46
  }
39
47
 
40
48
  .jp-gis-band-container .jp-gis-symbology-row:last-child {
@@ -66,12 +74,12 @@
66
74
  height: 32px;
67
75
  }
68
76
 
69
- .jp-gis-color-row > input[type='number'] {
77
+ .jp-gis-color-row-value-input {
70
78
  flex: 0 1 18%;
71
79
  min-width: 0px;
72
80
  }
73
81
 
74
- .jp-gis-color-row > input[type='color'] {
82
+ .jp-gis-color-row-output-input {
75
83
  flex-grow: 1;
76
84
  }
77
85