@carto/kepler.gl 0.0.71-alpha.3 → 0.0.71-alpha.5
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/dist/components/common/item-selector/dropdown-list.js +4 -3
- package/dist/components/side-panel/layer-panel/color-range-selector.js +8 -22
- package/dist/components/side-panel/layer-panel/color-selector.js +2 -5
- package/dist/components/side-panel/layer-panel/layer-configurator.js +22 -19
- package/dist/constants/default-settings.js +1 -1
- package/dist/layers/base-layer.js +56 -11
- package/dist/schemas/vis-state-schema.js +68 -33
- package/dist/utils/data-utils.js +31 -1
- package/dist/utils/layer-utils.js +2 -1
- package/dist/utils/table-utils/kepler-table.js +17 -1
- package/package.json +2 -1
- package/src/components/common/item-selector/dropdown-list.js +2 -3
- package/src/components/side-panel/layer-panel/color-range-selector.js +7 -17
- package/src/components/side-panel/layer-panel/color-selector.js +1 -5
- package/src/components/side-panel/layer-panel/layer-configurator.js +11 -24
- package/src/layers/base-layer.js +42 -6
- package/src/layers/index.d.ts +3 -1
- package/src/schemas/vis-state-schema.js +23 -0
- package/src/utils/data-utils.d.ts +1 -0
- package/src/utils/data-utils.js +19 -0
- package/src/utils/layer-utils.js +1 -0
- package/src/utils/table-utils/kepler-table.js +12 -0
|
@@ -125,10 +125,6 @@ function ColorSelectorFactory(SingleColorPalette, ColorRangeSelector) {
|
|
|
125
125
|
}
|
|
126
126
|
};
|
|
127
127
|
|
|
128
|
-
_onSelectColorColumn = column => {
|
|
129
|
-
this.props.onSelectHexColorColumn(column);
|
|
130
|
-
};
|
|
131
|
-
|
|
132
128
|
_showDropdown = (e, i) => {
|
|
133
129
|
e.stopPropagation();
|
|
134
130
|
e.preventDefault();
|
|
@@ -177,7 +173,7 @@ function ColorSelectorFactory(SingleColorPalette, ColorRangeSelector) {
|
|
|
177
173
|
<ColorRangeSelector
|
|
178
174
|
selectedColorRange={colorSets[editing].selectedColor}
|
|
179
175
|
onSelectColorRange={this._onSelectColor}
|
|
180
|
-
onSelectColorColumn={this.
|
|
176
|
+
onSelectColorColumn={this.props.onSelectHexColorColumn}
|
|
181
177
|
setColorPaletteUI={this.props.setColorUI}
|
|
182
178
|
fields={this.props.fields}
|
|
183
179
|
colorPaletteUI={colorUI}
|
|
@@ -177,8 +177,6 @@ export default function LayerConfiguratorFactory(
|
|
|
177
177
|
channel={layer.visualChannels.color}
|
|
178
178
|
{...layerChannelConfigProps}
|
|
179
179
|
/>
|
|
180
|
-
</ConfigGroupCollapsibleContent>
|
|
181
|
-
<ConfigGroupCollapsibleContent>
|
|
182
180
|
<VisConfigSlider {...layer.visConfigSettings.opacity} {...visConfiguratorProps} />
|
|
183
181
|
</ConfigGroupCollapsibleContent>
|
|
184
182
|
</LayerConfigGroup>
|
|
@@ -192,11 +190,7 @@ export default function LayerConfiguratorFactory(
|
|
|
192
190
|
disabled={Boolean(layer.config.visConfig.customMarkers)}
|
|
193
191
|
>
|
|
194
192
|
{layer.config.strokeColorField ? (
|
|
195
|
-
<LayerColorRangeSelector
|
|
196
|
-
{...visConfiguratorProps}
|
|
197
|
-
property="strokeColorRange"
|
|
198
|
-
field="strokeColorField"
|
|
199
|
-
/>
|
|
193
|
+
<LayerColorRangeSelector {...visConfiguratorProps} channel="strokeColor" />
|
|
200
194
|
) : (
|
|
201
195
|
<LayerColorSelector
|
|
202
196
|
{...visConfiguratorProps}
|
|
@@ -712,11 +706,7 @@ export default function LayerConfiguratorFactory(
|
|
|
712
706
|
collapsible
|
|
713
707
|
>
|
|
714
708
|
{layer.config.strokeColorField ? (
|
|
715
|
-
<LayerColorRangeSelector
|
|
716
|
-
{...visConfiguratorProps}
|
|
717
|
-
property="strokeColorRange"
|
|
718
|
-
field="strokeColorField"
|
|
719
|
-
/>
|
|
709
|
+
<LayerColorRangeSelector {...visConfiguratorProps} channel="strokeColor" />
|
|
720
710
|
) : (
|
|
721
711
|
<LayerColorSelector
|
|
722
712
|
{...visConfiguratorProps}
|
|
@@ -899,11 +889,7 @@ export default function LayerConfiguratorFactory(
|
|
|
899
889
|
collapsible
|
|
900
890
|
>
|
|
901
891
|
{layer.config.strokeColorField ? (
|
|
902
|
-
<LayerColorRangeSelector
|
|
903
|
-
{...visConfiguratorProps}
|
|
904
|
-
property="strokeColorRange"
|
|
905
|
-
field="strokeColorField"
|
|
906
|
-
/>
|
|
892
|
+
<LayerColorRangeSelector {...visConfiguratorProps} channel="strokeColor" />
|
|
907
893
|
) : (
|
|
908
894
|
<LayerColorSelector
|
|
909
895
|
{...visConfiguratorProps}
|
|
@@ -1141,12 +1127,12 @@ export function LayerColorRangeSelectorFactory(ColorSelector) {
|
|
|
1141
1127
|
const {
|
|
1142
1128
|
layer,
|
|
1143
1129
|
onChange,
|
|
1144
|
-
|
|
1145
|
-
field = 'colorField',
|
|
1146
|
-
scale = 'colorScale',
|
|
1130
|
+
channel = 'color',
|
|
1147
1131
|
setColorUI,
|
|
1148
|
-
fields
|
|
1132
|
+
fields,
|
|
1133
|
+
handleCustomOnSelectHexColumn = () => null
|
|
1149
1134
|
} = this.props;
|
|
1135
|
+
const {range: property, field, scale} = layer.visualChannels[channel];
|
|
1150
1136
|
return (
|
|
1151
1137
|
<SidePanelSection>
|
|
1152
1138
|
<PanelLabel>
|
|
@@ -1159,20 +1145,21 @@ export function LayerColorRangeSelectorFactory(ColorSelector) {
|
|
|
1159
1145
|
selectedColor: layer.config.visConfig[property],
|
|
1160
1146
|
isRange: true,
|
|
1161
1147
|
setColor: colorRange => {
|
|
1162
|
-
layer.updateLayerConfig({
|
|
1163
|
-
[scale]: SCALE_TYPES.ordinal
|
|
1164
|
-
});
|
|
1165
1148
|
const {colorMap} = layer.config.visConfig[property];
|
|
1166
1149
|
const colorRangeUpdated = colorMap
|
|
1167
1150
|
? layer.updateColorMap(property, colorMap, colorRange)
|
|
1168
1151
|
: colorRange;
|
|
1169
1152
|
onChange({[property]: colorRangeUpdated});
|
|
1153
|
+
layer.validateScale(channel); // Validate scale to ensure that it changes from `identity` to the correct one.
|
|
1170
1154
|
}
|
|
1171
1155
|
}
|
|
1172
1156
|
]}
|
|
1173
1157
|
colorUI={layer.config.colorUI[property]}
|
|
1174
1158
|
setColorUI={newConfig => setColorUI(property, newConfig)}
|
|
1175
1159
|
onSelectHexColorColumn={colorColumn => {
|
|
1160
|
+
// It's defined in CN: see workspace-www/src/features/builder/ui/KeplerGl/SidePanel/LayerPanel/LayerColorRangeSelector.tsx
|
|
1161
|
+
handleCustomOnSelectHexColumn(layer, colorColumn);
|
|
1162
|
+
|
|
1176
1163
|
layer.updateLayerConfig({
|
|
1177
1164
|
[field]: {
|
|
1178
1165
|
...layer.config[field],
|
package/src/layers/base-layer.js
CHANGED
|
@@ -103,6 +103,9 @@ class Layer {
|
|
|
103
103
|
// meta
|
|
104
104
|
this.meta = {};
|
|
105
105
|
|
|
106
|
+
// legendSettings
|
|
107
|
+
this.legendSettings = {};
|
|
108
|
+
|
|
106
109
|
// visConfigSettings
|
|
107
110
|
this.visConfigSettings = {};
|
|
108
111
|
|
|
@@ -665,7 +668,8 @@ class Layer {
|
|
|
665
668
|
type: visConfig[prop].type,
|
|
666
669
|
steps: visConfig[prop].colors?.length,
|
|
667
670
|
reversed: Boolean(visConfig[prop].reversed),
|
|
668
|
-
hexColumn: this.
|
|
671
|
+
hexColumn: this.getHexColumn(prop),
|
|
672
|
+
isHexColumn: this.isColoredByColorColumn(prop)
|
|
669
673
|
}
|
|
670
674
|
}
|
|
671
675
|
}
|
|
@@ -1057,6 +1061,10 @@ class Layer {
|
|
|
1057
1061
|
this.meta = {...this.meta, ...meta};
|
|
1058
1062
|
}
|
|
1059
1063
|
|
|
1064
|
+
updateLayerLegend(settings) {
|
|
1065
|
+
this.legendSettings = {...this.legendSettings, ...settings};
|
|
1066
|
+
}
|
|
1067
|
+
|
|
1060
1068
|
getDataUpdateTriggers({filteredIndex, id, allData}) {
|
|
1061
1069
|
const {columns} = this.config;
|
|
1062
1070
|
|
|
@@ -1111,7 +1119,7 @@ class Layer {
|
|
|
1111
1119
|
updateVisualChannelFields(dataset) {
|
|
1112
1120
|
for (const {field, range} of Object.values(this.visualChannels)) {
|
|
1113
1121
|
const oldField = this.config[field];
|
|
1114
|
-
const isUsingHexColorCode = this.config.visConfig[range].hexColor
|
|
1122
|
+
const isUsingHexColorCode = this.config.visConfig[range].hexColor;
|
|
1115
1123
|
if (!oldField) {
|
|
1116
1124
|
return;
|
|
1117
1125
|
}
|
|
@@ -1194,8 +1202,11 @@ class Layer {
|
|
|
1194
1202
|
*/
|
|
1195
1203
|
validateScale(channel) {
|
|
1196
1204
|
const visualChannel = this.visualChannels[channel];
|
|
1197
|
-
const {scale} = visualChannel;
|
|
1198
|
-
if (
|
|
1205
|
+
const {scale, range} = visualChannel;
|
|
1206
|
+
if (
|
|
1207
|
+
!scale ||
|
|
1208
|
+
(this.isColoredByColorColumn(range) && this.config[scale] === SCALE_TYPES.identity)
|
|
1209
|
+
) {
|
|
1199
1210
|
// visualChannel doesn't have scale
|
|
1200
1211
|
return;
|
|
1201
1212
|
}
|
|
@@ -1283,6 +1294,27 @@ class Layer {
|
|
|
1283
1294
|
return this;
|
|
1284
1295
|
}
|
|
1285
1296
|
|
|
1297
|
+
calculateHexColumnLegend(datasets) {
|
|
1298
|
+
const dataset = this.getDataset(datasets);
|
|
1299
|
+
if (!datasets) {
|
|
1300
|
+
return;
|
|
1301
|
+
}
|
|
1302
|
+
|
|
1303
|
+
const legendSettings = Object.keys(this.visualChannels).reduce((legends, channel) => {
|
|
1304
|
+
const {range, field: channelField} = this.visualChannels[channel];
|
|
1305
|
+
const channelConfig = this.config.visConfig[range];
|
|
1306
|
+
const field = this.config[channelField];
|
|
1307
|
+
|
|
1308
|
+
if (channelConfig?.type === hexColor) {
|
|
1309
|
+
const dataSetField = dataset.fields.find(f => f.name === field.colorColumn);
|
|
1310
|
+
const legend = dataset.calculateLegend(field, dataSetField);
|
|
1311
|
+
legends[channel] = legend;
|
|
1312
|
+
}
|
|
1313
|
+
return legends;
|
|
1314
|
+
}, {});
|
|
1315
|
+
this.updateLayerLegend(legendSettings);
|
|
1316
|
+
}
|
|
1317
|
+
|
|
1286
1318
|
hasHoveredObject(objectInfo) {
|
|
1287
1319
|
return this.isLayerHovered(objectInfo) && objectInfo.object ? objectInfo.object : null;
|
|
1288
1320
|
}
|
|
@@ -1374,7 +1406,7 @@ class Layer {
|
|
|
1374
1406
|
{getPosition, getRadius, radiusScale, updateTriggers, sharedProps},
|
|
1375
1407
|
renderOpts
|
|
1376
1408
|
) {
|
|
1377
|
-
const {data
|
|
1409
|
+
const {data} = renderOpts;
|
|
1378
1410
|
const {textLabel, visibilityByZoom} = this.config;
|
|
1379
1411
|
const extensions = [...sharedProps.extensions, collisionFilterExtension];
|
|
1380
1412
|
|
|
@@ -1494,12 +1526,16 @@ class Layer {
|
|
|
1494
1526
|
return () => null;
|
|
1495
1527
|
}
|
|
1496
1528
|
|
|
1497
|
-
|
|
1529
|
+
getHexColumn(range) {
|
|
1498
1530
|
const field = Object.values(this.visualChannels)?.find(value => value.range === range)?.field;
|
|
1499
1531
|
if (field) {
|
|
1500
1532
|
return this.config[field].colorColumn;
|
|
1501
1533
|
}
|
|
1502
1534
|
}
|
|
1535
|
+
|
|
1536
|
+
isColoredByColorColumn(range) {
|
|
1537
|
+
return this.config.visConfig[range]?.hexColor;
|
|
1538
|
+
}
|
|
1503
1539
|
}
|
|
1504
1540
|
|
|
1505
1541
|
export default Layer;
|
package/src/layers/index.d.ts
CHANGED
|
@@ -92,6 +92,8 @@ export class Layer {
|
|
|
92
92
|
hasInteractivity: boolean;
|
|
93
93
|
hasAllColumns(): boolean;
|
|
94
94
|
updateLayerConfig(p: Partial<LayerConfig>): Layer;
|
|
95
|
+
updateLayerMeta(p: any): Layer
|
|
96
|
+
updateLayerLegend(p: any): Layer
|
|
95
97
|
updateLayerDomain(datasets: Datasets, filter?: Filter): Layer;
|
|
96
98
|
updateLayerVisualChannel(dataset: KeplerTable, channel: string): Layer;
|
|
97
99
|
shouldCalculateLayerData(props: string[]): boolean;
|
|
@@ -100,7 +102,7 @@ export class Layer {
|
|
|
100
102
|
isValidToSave(): boolean;
|
|
101
103
|
validateVisualChannel(channel: string);
|
|
102
104
|
getVisualChannelDescription(key: string): {label: string, measure: string};
|
|
103
|
-
|
|
105
|
+
calculateHexColumnLegend(datasets: Datasets): any;
|
|
104
106
|
static findDefaultLayerProps(dataset: KeplerTable, foundLayers?: any[]);
|
|
105
107
|
// static findDefaultColumnField(defaultFields, allFields)
|
|
106
108
|
}
|
|
@@ -365,6 +365,25 @@ class VisualChannelSchemaV1 extends Schema {
|
|
|
365
365
|
};
|
|
366
366
|
}
|
|
367
367
|
}
|
|
368
|
+
/**
|
|
369
|
+
* V1: save [channel]: [{ label, color }, ...] for legend
|
|
370
|
+
*/
|
|
371
|
+
class LegendSettingsV1 extends Schema {
|
|
372
|
+
save(legendSettings, parents) {
|
|
373
|
+
return {
|
|
374
|
+
[this.key]: Object.keys(legendSettings).reduce((accu, key) => {
|
|
375
|
+
accu[key] = legendSettings[key];
|
|
376
|
+
return accu;
|
|
377
|
+
}, {})
|
|
378
|
+
};
|
|
379
|
+
}
|
|
380
|
+
load(ls, parents, accumulator) {
|
|
381
|
+
return {
|
|
382
|
+
...accumulator,
|
|
383
|
+
[this.key]: ls
|
|
384
|
+
};
|
|
385
|
+
}
|
|
386
|
+
}
|
|
368
387
|
const visConfigModificationV1 = {
|
|
369
388
|
point: (visConfig, parents, accumulated) => {
|
|
370
389
|
const modified = {};
|
|
@@ -459,6 +478,10 @@ export const layerPropsV1 = {
|
|
|
459
478
|
})
|
|
460
479
|
}
|
|
461
480
|
}),
|
|
481
|
+
legendSettings: new LegendSettingsV1({
|
|
482
|
+
version: VERSIONS.v1,
|
|
483
|
+
key: 'legendSettings'
|
|
484
|
+
}),
|
|
462
485
|
visualChannels: new VisualChannelSchemaV1({
|
|
463
486
|
version: VERSIONS.v1,
|
|
464
487
|
key: 'visualChannels'
|
|
@@ -13,6 +13,7 @@ export function isPlainObject(d: any): boolean;
|
|
|
13
13
|
export function numberSort(a: any, b: any): any;
|
|
14
14
|
export function unique(values: any[]): any[];
|
|
15
15
|
export function uniqueSortedByFrequency(values: any[]): any[];
|
|
16
|
+
export function uniqueSortedPairByFrequency(values: any[]): any[];
|
|
16
17
|
export function arrayMove(array: any[], from: number, to: number);
|
|
17
18
|
export function getSortingFunction(fieldType: string): numberSort | undefined;
|
|
18
19
|
export function preciseRound(num: number, decimals: number): string;
|
package/src/utils/data-utils.js
CHANGED
|
@@ -426,3 +426,22 @@ export function datetimeFormatter(timezone) {
|
|
|
426
426
|
.format(format)
|
|
427
427
|
: format => ts => moment.utc(ts).format(format);
|
|
428
428
|
}
|
|
429
|
+
|
|
430
|
+
export function uniqueSortedPairByFrequency(values) {
|
|
431
|
+
const frequencies = values.reduce((res, value) => {
|
|
432
|
+
if (notNullorUndefined(value)) {
|
|
433
|
+
if (!res[value]) {
|
|
434
|
+
res[value] = {
|
|
435
|
+
key: value,
|
|
436
|
+
frequency: 1
|
|
437
|
+
};
|
|
438
|
+
}
|
|
439
|
+
res[value].frequency += 1;
|
|
440
|
+
}
|
|
441
|
+
return res;
|
|
442
|
+
}, {});
|
|
443
|
+
|
|
444
|
+
return Object.values(frequencies)
|
|
445
|
+
.sort((a, b) => b.frequency - a.frequency)
|
|
446
|
+
.map(({key: [left, right]}) => ({left, right}));
|
|
447
|
+
}
|
package/src/utils/layer-utils.js
CHANGED
|
@@ -45,6 +45,7 @@ import {
|
|
|
45
45
|
import {ALL_FIELD_TYPES, SCALE_TYPES} from 'constants/default-settings';
|
|
46
46
|
|
|
47
47
|
import {createDataContainer} from './data-container-utils';
|
|
48
|
+
import {uniqueSortedPairByFrequency} from 'utils/data-utils';
|
|
48
49
|
|
|
49
50
|
// Unique identifier of each field
|
|
50
51
|
const FID_KEY = 'name';
|
|
@@ -342,6 +343,17 @@ class KeplerTable {
|
|
|
342
343
|
}
|
|
343
344
|
}
|
|
344
345
|
|
|
346
|
+
calculateLegend(leftField, rightField) {
|
|
347
|
+
const leftValues = this.dataContainer.mapIndex(leftField.valueAccessor);
|
|
348
|
+
const rightValues = this.dataContainer.mapIndex(rightField.valueAccessor);
|
|
349
|
+
|
|
350
|
+
const pairing = leftValues.reduce((previous, current, idx) => {
|
|
351
|
+
previous.push([current, rightValues[idx]]);
|
|
352
|
+
return previous;
|
|
353
|
+
}, []);
|
|
354
|
+
return uniqueSortedPairByFrequency(pairing).map(row => ({label: row.left, color: row.right}));
|
|
355
|
+
}
|
|
356
|
+
|
|
345
357
|
/**
|
|
346
358
|
* Get a sample of rows to calculate layer boundaries
|
|
347
359
|
*/
|