@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.
- package/CHANGELOG.md +4 -0
- package/dist/components/common/styled-components.js +13 -21
- package/dist/components/kepler-gl.js +2 -2
- package/dist/components/map-container.js +22 -148
- package/dist/components/plot-container.js +6 -10
- package/dist/constants/default-settings.js +1 -1
- package/dist/layers/base-layer.js +13 -4
- package/dist/utils/color-utils.js +17 -21
- package/dist/utils/dom-to-image.js +6 -1
- package/dist/utils/index.js +7 -1
- package/dist/utils/table-utils/kepler-table.js +5 -3
- package/package.json +2 -1
- package/src/components/common/styled-components.js +2 -33
- package/src/components/kepler-gl.js +0 -4
- package/src/components/map-container.js +22 -152
- package/src/components/plot-container.js +3 -14
- package/src/layers/base-layer.js +9 -4
- package/src/utils/color-utils.js +9 -0
- package/src/utils/dom-to-image.js +5 -0
- package/src/utils/index.js +1 -1
- package/src/utils/table-utils/kepler-table.js +10 -1
|
@@ -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
|
-
.
|
|
482
|
-
|
|
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
|
|
|
@@ -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
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
529
|
-
|
|
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
|
-
|
|
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
|
-
|
|
195
|
+
generateThumbnail: this._generateThumbnail,
|
|
207
196
|
isExport: true,
|
|
208
197
|
deckGlProps,
|
|
209
198
|
maskPolygon
|
package/src/layers/base-layer.js
CHANGED
|
@@ -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
|
-
|
|
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
|
|
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
|
|
1296
|
+
[channel.range]: {...channelConfig, colors}
|
|
1292
1297
|
});
|
|
1293
1298
|
}
|
|
1294
1299
|
});
|
package/src/utils/color-utils.js
CHANGED
|
@@ -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 => {
|
package/src/utils/index.js
CHANGED
|
@@ -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
|
-
|
|
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
|
/**
|