@carto/kepler.gl 0.0.71-alpha.6 → 0.0.71-alpha.8

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.
@@ -478,41 +478,10 @@ export const StyledModalInputFootnote = styled.div.attrs({
478
478
  export const StyledMapContainer = styled.div`
479
479
  width: 100%;
480
480
  height: 100%;
481
- .mapboxgl-map {
482
- .mapboxgl-missing-css {
481
+ .maplibregl-ctrl {
482
+ &.maplibregl-ctrl-attrib {
483
483
  display: none;
484
484
  }
485
- .mapboxgl-ctrl-attrib {
486
- display: none;
487
- }
488
- }
489
- `;
490
-
491
- export const StyledAttrbution = styled.div.attrs({
492
- className: 'mapbox-attribution-container'
493
- })`
494
- bottom: 0;
495
- right: 0;
496
- position: absolute;
497
- display: block;
498
- margin: 0 10px 2px;
499
- z-index: 0;
500
-
501
- .attrition-logo {
502
- display: flex;
503
- font-size: 10px;
504
- justify-content: flex-end;
505
- align-items: center;
506
- color: ${props => props.theme.labelColor};
507
- margin-bottom: -4px;
508
-
509
- a.mapboxgl-ctrl-logo {
510
- width: 72px;
511
- margin-left: 6px;
512
- }
513
- }
514
- a {
515
- font-size: 10px;
516
485
  }
517
486
  `;
518
487
 
@@ -88,10 +88,6 @@ const GlobalStyle = styled.div`
88
88
  text-decoration: none;
89
89
  color: ${props => props.theme.labelColor};
90
90
  }
91
-
92
- .mapboxgl-ctrl .mapboxgl-ctrl-logo {
93
- display: none;
94
- }
95
91
  `;
96
92
 
97
93
  const BottomWidgetOuter = styled.div(
@@ -32,24 +32,19 @@ import {errorNotification} from 'utils/notifications-utils';
32
32
  // components
33
33
  import MapPopoverFactory from 'components/map/map-popover';
34
34
  import MapControlFactory from 'components/map/map-control';
35
- import {StyledMapContainer, StyledAttrbution} from 'components/common/styled-components';
35
+ import {StyledMapContainer} from 'components/common/styled-components';
36
36
 
37
37
  import EditorFactory from './editor/editor';
38
38
 
39
39
  // utils
40
- import {generateMapboxLayers, updateMapboxLayers} from 'layers/mapbox-utils';
40
+ import {generateMapboxLayers} from 'layers/mapbox-utils';
41
41
  import {setLayerBlending} from 'utils/gl-utils';
42
42
  import {transformRequest} from 'utils/map-style-utils/mapbox-utils';
43
43
  import {renderDeckGlLayer, prepareLayersToRender, prepareLayersForDeck} from 'utils/layer-utils';
44
44
 
45
45
  // default-settings
46
46
  import ThreeDBuildingLayer from 'deckgl-layers/3d-building-layer/3d-building-layer';
47
- import {
48
- FILTER_TYPES,
49
- GEOCODER_LAYER_ID,
50
- MASK_LAYER_ID,
51
- THROTTLE_NOTIFICATION_TIME
52
- } from 'constants/default-settings';
47
+ import {FILTER_TYPES, MASK_LAYER_ID, THROTTLE_NOTIFICATION_TIME} from 'constants/default-settings';
53
48
 
54
49
  import {observeDimensions, unobserveDimensions} from '../utils/observe-dimensions';
55
50
  import {LOCALE_CODES} from 'localization/locales';
@@ -81,39 +76,8 @@ const MAP_STYLE = {
81
76
  }
82
77
  };
83
78
 
84
- const MAPBOXGL_STYLE_UPDATE = 'style.load';
85
- const MAPBOXGL_RENDER = 'render';
86
79
  const TRANSITION_DURATION = 0;
87
80
 
88
- export const Attribution = () => (
89
- <StyledAttrbution>
90
- <div className="attrition-logo">
91
- Basemap by:
92
- <a
93
- className="mapboxgl-ctrl-logo"
94
- target="_blank"
95
- rel="noopener noreferrer"
96
- href="https://www.mapbox.com/"
97
- aria-label="Mapbox logo"
98
- />
99
- </div>
100
- <div className="attrition-link">
101
- <a href="https://kepler.gl/policy/" target="_blank" rel="noopener noreferrer">
102
- © kepler.gl |{' '}
103
- </a>
104
- <a href="https://www.mapbox.com/about/maps/" target="_blank" rel="noopener noreferrer">
105
- © Mapbox |{' '}
106
- </a>
107
- <a href="http://www.openstreetmap.org/copyright" target="_blank" rel="noopener noreferrer">
108
- © OpenStreetMap |{' '}
109
- </a>
110
- <a href="https://www.mapbox.com/map-feedback/" target="_blank" rel="noopener noreferrer">
111
- <strong>Improve this map</strong>
112
- </a>
113
- </div>
114
- </StyledAttrbution>
115
- );
116
-
117
81
  MapContainerFactory.deps = [MapPopoverFactory, MapControlFactory, EditorFactory];
118
82
 
119
83
  export default function MapContainerFactory(MapPopover, MapControl, Editor) {
@@ -145,7 +109,7 @@ export default function MapContainerFactory(MapPopover, MapControl, Editor) {
145
109
  mapLayers: PropTypes.object,
146
110
  onMapToggleLayer: PropTypes.func,
147
111
  onMapStyleLoaded: PropTypes.func,
148
- onMapRender: PropTypes.func,
112
+ generateThumbnail: PropTypes.func,
149
113
  getMapboxRef: PropTypes.func,
150
114
  index: PropTypes.number,
151
115
  popupSettings: PropTypes.object
@@ -161,10 +125,6 @@ export default function MapContainerFactory(MapPopover, MapControl, Editor) {
161
125
  constructor(props) {
162
126
  super(props);
163
127
 
164
- this.previousLayers = {
165
- // [layers.id]: mapboxLayerConfig
166
- };
167
-
168
128
  this._deck = null;
169
129
  this._ref = createRef();
170
130
 
@@ -187,11 +147,6 @@ export default function MapContainerFactory(MapPopover, MapControl, Editor) {
187
147
  }
188
148
 
189
149
  componentWillUnmount() {
190
- // unbind mapboxgl event listener
191
- if (this._map) {
192
- this._map.off(MAPBOXGL_STYLE_UPDATE);
193
- this._map.off(MAPBOXGL_RENDER);
194
- }
195
150
  unobserveDimensions(this._ref.current);
196
151
  }
197
152
 
@@ -252,41 +207,6 @@ export default function MapContainerFactory(MapPopover, MapControl, Editor) {
252
207
  visStateActions.toggleLayerForMap(mapIndex, layerId);
253
208
  };
254
209
 
255
- _onMapboxStyleUpdate = () => {
256
- // force refresh mapboxgl layers
257
- this.previousLayers = {};
258
- this._updateMapboxLayers();
259
-
260
- if (typeof this.props.onMapStyleLoaded === 'function') {
261
- this.props.onMapStyleLoaded(this._map);
262
- }
263
- };
264
-
265
- _setMapboxMap = mapbox => {
266
- if (!this._map && mapbox) {
267
- this._map = mapbox.getMap();
268
- // i noticed in certain context we don't access the actual map element
269
- if (!this._map) {
270
- return;
271
- }
272
- // bind mapboxgl event listener
273
- this._map.on(MAPBOXGL_STYLE_UPDATE, this._onMapboxStyleUpdate);
274
-
275
- this._map.on(MAPBOXGL_RENDER, () => {
276
- if (typeof this.props.onMapRender === 'function') {
277
- this.props.onMapRender(this._map);
278
- }
279
- });
280
- }
281
-
282
- if (this.props.getMapboxRef) {
283
- // The parent component can gain access to our MapboxGlMap by
284
- // providing this callback. Note that 'mapbox' will be null when the
285
- // ref is unset (e.g. when a split map is closed).
286
- this.props.getMapboxRef(mapbox, this.props.index);
287
- }
288
- };
289
-
290
210
  _onDeckInitialized(gl) {
291
211
  if (this.props.onDeckInitialized) {
292
212
  this.props.onDeckInitialized(this._deck, gl);
@@ -351,6 +271,9 @@ export default function MapContainerFactory(MapPopover, MapControl, Editor) {
351
271
  mapboxApiUrl,
352
272
  maskPolygon
353
273
  } = this.props;
274
+
275
+ const mousePosition = this._mousePosition;
276
+
354
277
  trackers.drawCount?.increment();
355
278
 
356
279
  // initialise layers from props if exists
@@ -407,10 +330,12 @@ export default function MapContainerFactory(MapPopover, MapControl, Editor) {
407
330
  // Limit renders
408
331
  const hasRendered = this._hasRendered;
409
332
  const resetHasRendered = () => (hasRendered.current = false);
333
+
410
334
  return (
411
335
  <DeckGL
412
336
  controller={true}
413
337
  {...this.props.deckGlProps}
338
+ glOptions={{preserveDrawingBuffer: true}}
414
339
  viewState={mapState}
415
340
  onViewStateChange={({viewState}) => {
416
341
  // Limit updates (prevents freezes when dev tools open)
@@ -425,8 +350,15 @@ export default function MapContainerFactory(MapPopover, MapControl, Editor) {
425
350
  resetHasRendered();
426
351
  this._onBeforeRender(opts);
427
352
  }}
428
- onHover={visStateActions.onLayerHover}
353
+ // onHover={visStateActions.onLayerHover}
354
+ onHover={info => {
355
+ visStateActions.onLayerHover(info);
356
+ mousePosition.current = {mousePosition: info.pixel};
357
+ }}
429
358
  onClick={visStateActions.onLayerClick}
359
+ onDragStart={() => {
360
+ mousePosition.current = null;
361
+ }}
430
362
  onError={this._onDeckError}
431
363
  ref={comp => {
432
364
  if (comp && comp.deck && comp.deck !== this._deck) {
@@ -452,23 +384,6 @@ export default function MapContainerFactory(MapPopover, MapControl, Editor) {
452
384
  );
453
385
  }
454
386
 
455
- _updateMapboxLayers() {
456
- const mapboxLayers = this.mapboxLayersSelector(this.props);
457
- if (!Object.keys(mapboxLayers).length && !Object.keys(this.previousLayers).length) {
458
- return;
459
- }
460
-
461
- updateMapboxLayers(this._map, mapboxLayers, this.previousLayers);
462
-
463
- this.previousLayers = mapboxLayers;
464
- }
465
-
466
- _renderMapboxOverlays() {
467
- if (this._map && this._map.isStyleLoaded()) {
468
- this._updateMapboxLayers();
469
- }
470
- }
471
-
472
387
  _onViewportChange = viewState => {
473
388
  trackers.viewportChangeCount?.increment();
474
389
  const {width, height, ...restViewState} = viewState;
@@ -504,8 +419,6 @@ export default function MapContainerFactory(MapPopover, MapControl, Editor) {
504
419
  layers,
505
420
  MapComponent,
506
421
  datasets,
507
- mapboxApiAccessToken,
508
- mapboxApiUrl,
509
422
  mapControls,
510
423
  isExport,
511
424
  locale,
@@ -514,7 +427,8 @@ export default function MapContainerFactory(MapPopover, MapControl, Editor) {
514
427
  interactionConfig,
515
428
  editor,
516
429
  index,
517
- primary
430
+ primary,
431
+ generateThumbnail
518
432
  } = this.props;
519
433
 
520
434
  const layersToRender = this.layersToRenderSelector(this.props);
@@ -525,16 +439,11 @@ export default function MapContainerFactory(MapPopover, MapControl, Editor) {
525
439
  width: '100%',
526
440
  height: '100%',
527
441
  preserveDrawingBuffer: true,
528
- mapboxApiAccessToken,
529
- mapboxApiUrl,
530
- transformRequest
442
+ transformRequest,
443
+ generateThumbnail
531
444
  };
532
445
 
533
- const isEdit = (mapControls.mapDraw || {}).active;
534
-
535
- const hasGeocoderLayer = layers.find(l => l.id === GEOCODER_LAYER_ID);
536
446
  const isSplit = Boolean(mapState.isSplit);
537
- const mousePosition = this._mousePosition;
538
447
 
539
448
  return (
540
449
  <>
@@ -562,50 +471,11 @@ export default function MapContainerFactory(MapPopover, MapControl, Editor) {
562
471
  onSetLocale={uiStateActions.setLocale}
563
472
  onToggleEditorVisibility={visStateActions.toggleEditorVisibility}
564
473
  />
565
- <MapComponent
566
- {...mapProps}
567
- key="bottom"
568
- ref={this._setMapboxMap}
569
- mapStyle={mapStyle.bottomMapStyle}
570
- getCursor={this.props.hoverInfo ? () => 'pointer' : undefined}
571
- onMouseMove={evt => {
572
- // Sending mouse move updates via Redux is expensive. Store
573
- // locally and rely on deck.gl to drive render updates
574
- // See Builder: features/builder/ui/KeplerGl/MapContainer/MapContainer.tsx
575
- mousePosition.current = {mousePosition: evt.point};
576
- }}
577
- >
474
+ <MapComponent {...mapProps} key="bottom" mapStyle={mapStyle.bottomMapStyle}>
578
475
  {PERF_DEBUG && renderPerformanceStats()}
579
476
  {this._renderDeckOverlay(layersForDeck)}
580
- {this._renderMapboxOverlays()}
581
- <Editor
582
- index={index}
583
- datasets={datasets}
584
- editor={editor}
585
- filters={this.polygonFilters(this.props)}
586
- isEnabled={isEdit}
587
- layers={layers}
588
- layersToRender={layersToRender}
589
- onDeleteFeature={visStateActions.deleteFeature}
590
- onSelect={visStateActions.setSelectedFeature}
591
- onUpdate={visStateActions.setFeatures}
592
- onTogglePolygonFilter={visStateActions.setPolygonFilterLayer}
593
- style={{
594
- pointerEvents: isEdit ? 'all' : 'none',
595
- position: 'absolute',
596
- display: editor.visible ? 'block' : 'none'
597
- }}
598
- />
599
477
  </MapComponent>
600
- {mapStyle.topMapStyle || hasGeocoderLayer ? (
601
- <div style={MAP_STYLE.top}>
602
- <MapComponent {...mapProps} key="top" mapStyle={mapStyle.topMapStyle}>
603
- {this._renderDeckOverlay({[GEOCODER_LAYER_ID]: true})}
604
- </MapComponent>
605
- </div>
606
- ) : null}
607
478
  {this._renderMapPopover(layersToRender)}
608
- {!isSplit || index === 1 ? <Attribution /> : null}
609
479
  </>
610
480
  );
611
481
  }
@@ -55,12 +55,6 @@ PlotContainerFactory.deps = [MapContainerFactory, MapsLayoutFactory];
55
55
 
56
56
  // Remove mapbox logo in exported map, because it contains non-ascii characters
57
57
  const StyledPlotContainer = styled.div`
58
- .mapboxgl-ctrl-bottom-left,
59
- .mapboxgl-ctrl-bottom-right,
60
- .mapbox-attribution-container {
61
- display: none;
62
- }
63
-
64
58
  position: absolute;
65
59
  top: ${OUT_OF_SCREEN_POSITION}px;
66
60
  left: ${OUT_OF_SCREEN_POSITION}px;
@@ -83,7 +77,8 @@ export default function PlotContainerFactory(MapContainer, MapsLayout) {
83
77
  class PlotContainer extends Component {
84
78
  constructor(props) {
85
79
  super(props);
86
- this._onMapRender = debounce(this._onMapRender, 500);
80
+ // _onMapRender defined in cloud-native
81
+ this._generateThumbnail = null;
87
82
  this._retrieveNewScreenshot = debounce(this._retrieveNewScreenshot, 500);
88
83
  }
89
84
 
@@ -133,12 +128,6 @@ export default function PlotContainerFactory(MapContainer, MapsLayout) {
133
128
  })
134
129
  );
135
130
 
136
- _onMapRender = map => {
137
- if (map.isStyleLoaded()) {
138
- this._retrieveNewScreenshot();
139
- }
140
- };
141
-
142
131
  _retrieveNewScreenshot = () => {
143
132
  if (this.plottingAreaRef.current) {
144
133
  convertToPng(this.plottingAreaRef.current, {filter: DOM_FILTER_FUNC})
@@ -203,7 +192,7 @@ export default function PlotContainerFactory(MapContainer, MapsLayout) {
203
192
  }
204
193
  },
205
194
  MapComponent: StaticMap,
206
- onMapRender: this._onMapRender,
195
+ generateThumbnail: this._generateThumbnail,
207
196
  isExport: true,
208
197
  deckGlProps,
209
198
  maskPolygon
@@ -25,6 +25,7 @@ import {COORDINATE_SYSTEM, Layer as DeckLayer} from '@deck.gl/core';
25
25
  import {_PointLabelLayer as PointLabelLayer} from '@deck.gl/carto';
26
26
  import DefaultLayerIcon from './default-layer-icon';
27
27
  import {diffUpdateTriggers} from './layer-update';
28
+ import {rgb} from 'd3-color';
28
29
 
29
30
  import {
30
31
  ALL_FIELD_TYPES,
@@ -53,7 +54,7 @@ import {generateHashId, isPlainObject} from 'utils/utils';
53
54
  import {getLatLngBounds, notNullorUndefined} from 'utils/data-utils';
54
55
  import {getSampleData} from 'utils/table-utils/data-container-utils';
55
56
 
56
- import {hexToRgb, getColorGroupByName, reverseColorRange} from 'utils/color-utils';
57
+ import {hexToRgb, getColorGroupByName, reverseColorRange, checkColorOrFallback} from 'utils/color-utils';
57
58
  import {getMaskExtensionProps} from 'utils/layer-utils';
58
59
  import {scaleOrdinal} from 'd3-scale';
59
60
 
@@ -834,7 +835,8 @@ class Layer {
834
835
  getColorScale(colorScale, colorDomain, colorRange) {
835
836
  if (colorRange.type === hexColor) {
836
837
  return (_, color) => {
837
- return hexToRgb(color);
838
+ const {r, g, b} = rgb(color);
839
+ return [r, g, b].some(isNaN) ? UNKNOWN_COLOR : [r, g, b];
838
840
  };
839
841
  } else if (Array.isArray(colorRange.colorMap)) {
840
842
  const cMap = new Map();
@@ -1286,9 +1288,12 @@ class Layer {
1286
1288
 
1287
1289
  if (channelConfig?.type === hexColor) {
1288
1290
  const dataSetField = dataset.fields.find(f => f.name === field.colorColumn);
1289
- const colors = dataset.getColumnLayerDomain(dataSetField, SCALE_TYPES.ordinal);
1291
+ const colors = dataset
1292
+ .getColumnLayerDomain(dataSetField, SCALE_TYPES.ordinal)
1293
+ .slice(0, 20)
1294
+ .map(c => checkColorOrFallback(c));
1290
1295
  this.updateLayerVisConfig({
1291
- [channel.range]: {...channelConfig, colors: colors.slice(0, 20)}
1296
+ [channel.range]: {...channelConfig, colors}
1292
1297
  });
1293
1298
  }
1294
1299
  });
@@ -18,6 +18,9 @@
18
18
  // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
19
  // THE SOFTWARE.
20
20
 
21
+ import {UNKNOWN_COLOR} from 'constants/default-settings';
22
+ import {rgb as d3Rgb} from 'd3-color';
23
+
21
24
  /**
22
25
  * get r g b from hex code
23
26
  *
@@ -104,3 +107,9 @@ export function createLinearGradient(direction, colors) {
104
107
 
105
108
  return `linear-gradient(to ${direction}, ${bands.join(',')})`;
106
109
  }
110
+
111
+ export function checkColorOrFallback(hexColor, fallback = UNKNOWN_COLOR) {
112
+ const color = d3Rgb(hexColor);
113
+ const {r, g, b} = color;
114
+ return [r, g, b].some(isNaN) ? d3Rgb(...fallback).formatHex() : hexColor;
115
+ }
@@ -515,6 +515,11 @@ function newImages() {
515
515
  return Promise.resolve(nd);
516
516
  }
517
517
 
518
+ if (background.search(/url\("data:image\/svg\+xml[^"]*"\)/) !== -1) {
519
+ nd.style.removeProperty('background');
520
+ return Promise.resolve(nd);
521
+ }
522
+
518
523
  return inliner
519
524
  .inlineAll(background)
520
525
  .then(inlined => {
@@ -27,7 +27,7 @@ export {
27
27
  FIELD_DISPLAY_FORMAT
28
28
  } from './data-utils';
29
29
  export {createNewDataEntry, datasetColorMaker, findDefaultColorField} from './dataset-utils';
30
- export {hexToRgb} from './color-utils';
30
+ export {hexToRgb, checkColorOrFallback} from './color-utils';
31
31
  export {errorNotification} from './notifications-utils';
32
32
  export {dataURItoBlob, downloadFile} from './export-utils';
33
33
  export {
@@ -46,6 +46,7 @@ import {ALL_FIELD_TYPES, SCALE_TYPES} from 'constants/default-settings';
46
46
 
47
47
  import {createDataContainer} from './data-container-utils';
48
48
  import {uniqueSortedPairByFrequency} from 'utils/data-utils';
49
+ import {checkColorOrFallback} from 'utils/color-utils';
49
50
 
50
51
  // Unique identifier of each field
51
52
  const FID_KEY = 'name';
@@ -351,7 +352,15 @@ class KeplerTable {
351
352
  previous.push([current, rightValues[idx]]);
352
353
  return previous;
353
354
  }, []);
354
- return uniqueSortedPairByFrequency(pairing).map(row => ({label: row.left, color: row.right}));
355
+
356
+ return uniqueSortedPairByFrequency(pairing)
357
+ .map(row => {
358
+ return {
359
+ label: row.left,
360
+ color: checkColorOrFallback(row.right)
361
+ };
362
+ })
363
+ .slice(0, 20);
355
364
  }
356
365
 
357
366
  /**