@carto/kepler.gl 0.0.71 → 0.0.72-alpha.2

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 (44) hide show
  1. package/dist/components/common/item-selector/accessor.js +2 -2
  2. package/dist/components/common/item-selector/dropdown-list.js +12 -9
  3. package/dist/components/common/item-selector/item-selector.js +2 -2
  4. package/dist/components/side-panel/layer-panel/color-range-selector.js +28 -7
  5. package/dist/components/side-panel/layer-panel/color-selector.js +4 -1
  6. package/dist/components/side-panel/layer-panel/hex-column-config.js +97 -0
  7. package/dist/components/side-panel/layer-panel/layer-configurator.js +45 -11
  8. package/dist/constants/color-ranges.js +12 -2
  9. package/dist/constants/default-settings.js +7 -4
  10. package/dist/layers/base-layer.js +197 -49
  11. package/dist/layers/point-layer/point-layer.js +2 -3
  12. package/dist/localization/en.js +5 -2
  13. package/dist/reducers/vis-state-merger.js +16 -2
  14. package/dist/schemas/vis-state-schema.js +69 -34
  15. package/dist/utils/color-utils.js +17 -21
  16. package/dist/utils/custom-scales.js +28 -0
  17. package/dist/utils/data-utils.js +31 -1
  18. package/dist/utils/index.js +7 -1
  19. package/dist/utils/layer-utils.js +2 -1
  20. package/dist/utils/table-utils/kepler-table.js +20 -1
  21. package/package.json +2 -1
  22. package/src/components/common/item-selector/accessor.js +1 -1
  23. package/src/components/common/item-selector/dropdown-list.js +23 -15
  24. package/src/components/common/item-selector/item-selector.js +1 -1
  25. package/src/components/side-panel/layer-panel/color-range-selector.js +30 -7
  26. package/src/components/side-panel/layer-panel/color-selector.js +3 -0
  27. package/src/components/side-panel/layer-panel/hex-column-config.js +45 -0
  28. package/src/components/side-panel/layer-panel/layer-configurator.js +52 -7
  29. package/src/constants/color-ranges.js +9 -0
  30. package/src/constants/default-settings.js +5 -2
  31. package/src/layers/base-layer.js +138 -30
  32. package/src/layers/index.d.ts +3 -1
  33. package/src/layers/layer-factory.d.ts +1 -0
  34. package/src/layers/point-layer/point-layer.js +1 -1
  35. package/src/localization/en.js +4 -1
  36. package/src/reducers/vis-state-merger.js +13 -1
  37. package/src/schemas/vis-state-schema.js +24 -1
  38. package/src/utils/color-utils.js +9 -0
  39. package/src/utils/custom-scales.js +20 -0
  40. package/src/utils/data-utils.d.ts +1 -0
  41. package/src/utils/data-utils.js +19 -0
  42. package/src/utils/index.js +1 -1
  43. package/src/utils/layer-utils.js +1 -0
  44. package/src/utils/table-utils/kepler-table.js +22 -0
@@ -35,7 +35,13 @@ export const classList = {
35
35
  listItemAnchor: 'list__item__anchor'
36
36
  };
37
37
 
38
- const defaultDisplay = d => d;
38
+ const defaultDisplay = d => d.value || d;
39
+
40
+ const Divider = styled.div`
41
+ border-top: 1px solid rgba(44, 48, 50, 0.12);
42
+ margin: 8px 0;
43
+ `;
44
+
39
45
  export const ListItem = ({value, displayOption = defaultDisplay}) => (
40
46
  <span className={classList.listItemAnchor}>{displayOption(value)}</span>
41
47
  );
@@ -112,7 +118,7 @@ export default class DropdownList extends Component {
112
118
  submenuPosition: {}
113
119
  };
114
120
 
115
- hasSubOptions = !!this.props.subOptions
121
+ hasSubOptions = !!this.props.subOptions;
116
122
 
117
123
  ref = createRef();
118
124
 
@@ -203,19 +209,21 @@ export default class DropdownList extends Component {
203
209
  ) : null}
204
210
 
205
211
  {this.props.options.map((value, i) => (
206
- <Item
207
- className={classNames(classList.listItem, {
208
- active: this.props.selectionIndex === i + valueOffset,
209
- hover: value.id && (this.state.currentOption?.id === value.id)
210
- })}
211
- key={`${display(value)}_${i}`}
212
- onMouseDown={e => !this.hasSubOptions && this._onClick(value, null, e)}
213
- onClick={e => !this.hasSubOptions && this._onClick(value, null, e)}
214
- onMouseEnter={e => this._onMouseOver(value, e)}
215
- >
216
- <this.props.customListItemComponent value={value} displayOption={display} />
217
- {this.props.withSubOptions && value.aggregators && <ChevronRight />}
218
- </Item>
212
+ <div key={`${display(value)}_${i}`}>
213
+ {value.divider && <Divider />}
214
+ <Item
215
+ className={classNames(classList.listItem, {
216
+ active: this.props.selectionIndex === i + valueOffset,
217
+ hover: value.id && (this.state.currentOption?.id === value.id)
218
+ })}
219
+ onMouseDown={e => !this.hasSubOptions && this._onClick(value, null, e)}
220
+ onClick={e => !this.hasSubOptions && this._onClick(value, null, e)}
221
+ onMouseEnter={e => this._onMouseOver(value, e)}
222
+ >
223
+ <this.props.customListItemComponent value={value} displayOption={display} />
224
+ {this.props.withSubOptions && value.aggregators && <ChevronRight />}
225
+ </Item>
226
+ </div>
219
227
  ))}
220
228
  </div>
221
229
  </DropdownListWrapper>
@@ -92,7 +92,7 @@ const DropdownSelectActionRight = styled.div`
92
92
 
93
93
  const DropdownWrapper = styled.div`
94
94
  border: 0;
95
- width: 100%;
95
+ width: auto;
96
96
  left: 0;
97
97
  z-index: ${props => props.theme.dropdownWrapperZ};
98
98
  position: absolute;
@@ -29,16 +29,18 @@ import {PanelLabel, Button, Tooltip} from 'components/common/styled-components';
29
29
  import Switch from 'components/common/switch';
30
30
  import ColorPalette from './color-palette';
31
31
  import CustomPalette from './custom-palette';
32
- import {COLOR_RANGES} from 'constants/color-ranges';
32
+ import {COLOR_RANGES, hexColor} from 'constants/color-ranges';
33
33
  import {numberSort} from 'utils/data-utils';
34
34
  import {reverseColorRange} from 'utils/color-utils';
35
35
  import {FormattedMessage} from 'localization';
36
36
  import {SwapHorizontal} from 'components/common/icons';
37
+ import {HexColumnConfigFactory} from './hex-column-config';
37
38
 
38
39
  export const ALL_TYPES = uniq([
39
40
  'all',
40
41
  ...COLOR_RANGES.map(c => c.type).filter(ctype => ctype),
41
- 'custom'
42
+ 'custom',
43
+ {value: hexColor, divider: true}
42
44
  ]);
43
45
 
44
46
  export const ALL_STEPS = uniq(COLOR_RANGES.map(d => d.colors.length)).sort(numberSort);
@@ -91,13 +93,19 @@ const CONFIG_SETTINGS = {
91
93
  }
92
94
  };
93
95
 
94
- ColorRangeSelectFactory.deps = [ColorPaletteGroupFactory, PaletteConfigFactory];
95
- export default function ColorRangeSelectFactory(ColorPaletteGroup, PaletteConfig) {
96
+ ColorRangeSelectFactory.deps = [
97
+ ColorPaletteGroupFactory,
98
+ PaletteConfigFactory,
99
+ HexColumnConfigFactory
100
+ ];
101
+ export default function ColorRangeSelectFactory(ColorPaletteGroup, PaletteConfig, HexColumnConfig) {
96
102
  class ColorRangeSelect extends Component {
97
103
  static propTypes = {
104
+ fields: PropTypes.arrayOf(PropTypes.any),
98
105
  colorPaletteUI: PropTypes.object.isRequired,
99
106
  selectedColorRange: PropTypes.object.isRequired,
100
107
  onSelectColorRange: PropTypes.func.isRequired,
108
+ onSelectColorColumn: PropTypes.func.isRequired,
101
109
  setColorPaletteUI: PropTypes.func.isRequired,
102
110
  // optional
103
111
  colorRanges: PropTypes.arrayOf(PropTypes.any)
@@ -129,7 +137,7 @@ export default function ColorRangeSelectFactory(ColorPaletteGroup, PaletteConfig
129
137
  _updateConfig = ({key, value}) => {
130
138
  this._setColorRangeConfig({
131
139
  [key]: value,
132
- ...(key === 'type' && {custom: value === 'custom'})
140
+ ...(key === 'type' && {custom: value === 'custom', isHexColumn: value === hexColor})
133
141
  });
134
142
  };
135
143
 
@@ -148,7 +156,7 @@ export default function ColorRangeSelectFactory(ColorPaletteGroup, PaletteConfig
148
156
  _onCustomPaletteCancel = newConfig => {
149
157
  this.props.setColorPaletteUI({
150
158
  showSketcher: false,
151
- colorRangeConfig: {custom: false}
159
+ colorRangeConfig: {custom: false, isHexColumn: false}
152
160
  });
153
161
  };
154
162
 
@@ -158,6 +166,14 @@ export default function ColorRangeSelectFactory(ColorPaletteGroup, PaletteConfig
158
166
  });
159
167
  };
160
168
 
169
+ _onSelectColumn = column => {
170
+ this.props.onSelectColorColumn(column);
171
+ this._setColorRangeConfig({
172
+ type: hexColor,
173
+ hexColumn: column?.name
174
+ });
175
+ };
176
+
161
177
  render() {
162
178
  const {customPalette, showSketcher, colorRangeConfig} = this.props.colorPaletteUI;
163
179
  const filteredColorRanges = this.filteredColorRange(this.props);
@@ -168,7 +184,8 @@ export default function ColorRangeSelectFactory(ColorPaletteGroup, PaletteConfig
168
184
  {Object.keys(colorRangeConfig)
169
185
  .filter(
170
186
  key =>
171
- Boolean(CONFIG_SETTINGS[key]) && (colorRangeConfig.custom ? key === 'type' : true)
187
+ Boolean(CONFIG_SETTINGS[key]) &&
188
+ (colorRangeConfig.custom || colorRangeConfig.isHexColumn ? key === 'type' : true)
172
189
  )
173
190
  .map(key => {
174
191
  return (
@@ -193,6 +210,12 @@ export default function ColorRangeSelectFactory(ColorPaletteGroup, PaletteConfig
193
210
  setCustomPalette={this._onSetCustomPalette}
194
211
  onCancel={this._onCustomPaletteCancel}
195
212
  />
213
+ ) : colorRangeConfig.isHexColumn ? (
214
+ <HexColumnConfig
215
+ fields={this.props.fields}
216
+ value={colorRangeConfig.hexColumn}
217
+ onSelectColumn={this._onSelectColumn}
218
+ />
196
219
  ) : (
197
220
  <ColorPaletteGroup
198
221
  colorRanges={filteredColorRanges}
@@ -64,6 +64,7 @@ ColorSelectorFactory.deps = [SingleColorPaletteFactory, ColorRangeSelectFactory]
64
64
  function ColorSelectorFactory(SingleColorPalette, ColorRangeSelector) {
65
65
  class ColorSelector extends Component {
66
66
  static propTypes = {
67
+ fields: PropTypes.arrayOf(PropTypes.any),
67
68
  colorSets: PropTypes.arrayOf(
68
69
  PropTypes.shape({
69
70
  selectedColor: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.any), PropTypes.object]),
@@ -172,7 +173,9 @@ function ColorSelectorFactory(SingleColorPalette, ColorRangeSelector) {
172
173
  <ColorRangeSelector
173
174
  selectedColorRange={colorSets[editing].selectedColor}
174
175
  onSelectColorRange={this._onSelectColor}
176
+ onSelectColorColumn={this.props.onSelectHexColorColumn}
175
177
  setColorPaletteUI={this.props.setColorUI}
178
+ fields={this.props.fields}
176
179
  colorPaletteUI={colorUI}
177
180
  />
178
181
  ) : (
@@ -0,0 +1,45 @@
1
+ import {FieldSelector} from 'components';
2
+ import PropTypes from 'prop-types';
3
+ import {PanelLabel} from 'components/common/styled-components';
4
+ import {FormattedMessage} from 'localization';
5
+ import React, {Component} from 'react';
6
+ import {ALL_FIELD_TYPES} from 'constants/default-settings';
7
+
8
+ export function HexColumnConfigFactory() {
9
+ class HexColumnConfig extends Component {
10
+ static propTypes = {
11
+ fields: PropTypes.arrayOf(PropTypes.any),
12
+ value: PropTypes.string,
13
+ onSelectColumn: PropTypes.func.isRequired
14
+ };
15
+
16
+ render() {
17
+ const {fields, value, onSelectColumn, iconComponent} = this.props;
18
+ const IconElement = () => iconComponent || null;
19
+
20
+ return (
21
+ <>
22
+ <div className="color-palette__config__label">
23
+ <PanelLabel>
24
+ <FormattedMessage id={`color.hexColumn.field`} />
25
+ <IconElement data-test="icon-help-button" />
26
+ </PanelLabel>
27
+ </div>
28
+ <div>
29
+ <FieldSelector
30
+ fields={fields.filter(f => f.type === ALL_FIELD_TYPES.string)}
31
+ value={value}
32
+ placeholder={''}
33
+ onSelect={onSelectColumn}
34
+ erasable={false}
35
+ onFocus={() => null}
36
+ onBlur={() => null}
37
+ />
38
+ </div>
39
+ </>
40
+ );
41
+ }
42
+ }
43
+
44
+ return HexColumnConfig;
45
+ }
@@ -41,12 +41,17 @@ import TextLabelPanelFactory from './text-label-panel';
41
41
 
42
42
  import {capitalizeFirstLetter} from 'utils/utils';
43
43
 
44
- import {CHANNEL_SCALES, CHANNEL_SCALE_SUPPORTED_FIELDS} from 'constants/default-settings';
44
+ import {
45
+ CHANNEL_SCALES,
46
+ CHANNEL_SCALE_SUPPORTED_FIELDS,
47
+ SCALE_TYPES
48
+ } from 'constants/default-settings';
45
49
  import {LAYER_TYPES} from 'layers/types';
46
50
  import {injectIntl} from 'react-intl';
47
51
  import ColorDimensionScaleSelectorFactory from './color-dimension-scale-selector';
48
52
  import ColorSelectorFactory from './color-selector';
49
53
  import LayerAggregationResolutionFactory from './layer-aggregation-resolution';
54
+ import {DEFAULT_COLOR_RANGE, hexColorCustomPalette} from 'constants/color-ranges';
50
55
 
51
56
  const StyledLayerConfigurator = styled.div.attrs({
52
57
  className: 'layer-panel__config'
@@ -185,7 +190,7 @@ export default function LayerConfiguratorFactory(
185
190
  disabled={Boolean(layer.config.visConfig.customMarkers)}
186
191
  >
187
192
  {layer.config.strokeColorField ? (
188
- <LayerColorRangeSelector {...visConfiguratorProps} property="strokeColorRange" />
193
+ <LayerColorRangeSelector {...visConfiguratorProps} channel="strokeColor" />
189
194
  ) : (
190
195
  <LayerColorSelector
191
196
  {...visConfiguratorProps}
@@ -701,7 +706,7 @@ export default function LayerConfiguratorFactory(
701
706
  collapsible
702
707
  >
703
708
  {layer.config.strokeColorField ? (
704
- <LayerColorRangeSelector {...visConfiguratorProps} property="strokeColorRange" />
709
+ <LayerColorRangeSelector {...visConfiguratorProps} channel="strokeColor" />
705
710
  ) : (
706
711
  <LayerColorSelector
707
712
  {...visConfiguratorProps}
@@ -884,7 +889,7 @@ export default function LayerConfiguratorFactory(
884
889
  collapsible
885
890
  >
886
891
  {layer.config.strokeColorField ? (
887
- <LayerColorRangeSelector {...visConfiguratorProps} property="strokeColorRange" />
892
+ <LayerColorRangeSelector {...visConfiguratorProps} channel="strokeColor" />
888
893
  ) : (
889
894
  <LayerColorSelector
890
895
  {...visConfiguratorProps}
@@ -1048,13 +1053,14 @@ LayerColorSelectorFactory.deps = [ColorSelectorFactory];
1048
1053
  export function LayerColorSelectorFactory(ColorSelector) {
1049
1054
  class LayerColorSelector extends Component {
1050
1055
  render() {
1051
- const {layer, onChange, selectedColor, property = 'color', setColorUI} = this.props;
1056
+ const {layer, onChange, selectedColor, property = 'color', setColorUI, fields} = this.props;
1052
1057
  return (
1053
1058
  <SidePanelSection>
1054
1059
  <PanelLabel>
1055
1060
  <FormattedMessage id="layer.color" />
1056
1061
  </PanelLabel>
1057
1062
  <ColorSelector
1063
+ fields={fields}
1058
1064
  colorSets={[
1059
1065
  {
1060
1066
  selectedColor: selectedColor || layer.config.color,
@@ -1076,13 +1082,22 @@ ArcLayerColorSelectorFactory.deps = [ColorSelectorFactory];
1076
1082
  export function ArcLayerColorSelectorFactory(ColorSelector) {
1077
1083
  class ArcLayerColorSelector extends Component {
1078
1084
  render() {
1079
- const {layer, onChangeConfig, onChangeVisConfig, property = 'color', setColorUI} = this.props;
1085
+ const {
1086
+ layer,
1087
+ onChangeConfig,
1088
+ onChangeVisConfig,
1089
+ property = 'color',
1090
+ setColorUI,
1091
+ fields
1092
+ } = this.props;
1093
+
1080
1094
  return (
1081
1095
  <SidePanelSection>
1082
1096
  <PanelLabel>
1083
1097
  <FormattedMessage id="layer.colorRange" />
1084
1098
  </PanelLabel>
1085
1099
  <ColorSelector
1100
+ fields={fields}
1086
1101
  colorSets={[
1087
1102
  {
1088
1103
  selectedColor: layer.config.color,
@@ -1109,13 +1124,22 @@ LayerColorRangeSelectorFactory.deps = [ColorSelectorFactory];
1109
1124
  export function LayerColorRangeSelectorFactory(ColorSelector) {
1110
1125
  class LayerColorRangeSelector extends Component {
1111
1126
  render() {
1112
- const {layer, onChange, property = 'colorRange', setColorUI} = this.props;
1127
+ const {
1128
+ layer,
1129
+ onChange,
1130
+ channel = 'color',
1131
+ setColorUI,
1132
+ fields,
1133
+ handleCustomOnSelectHexColumn = () => null
1134
+ } = this.props;
1135
+ const {range: property, field, scale} = layer.visualChannels[channel];
1113
1136
  return (
1114
1137
  <SidePanelSection>
1115
1138
  <PanelLabel>
1116
1139
  <FormattedMessage id="layer.colorRange" />
1117
1140
  </PanelLabel>
1118
1141
  <ColorSelector
1142
+ fields={fields}
1119
1143
  colorSets={[
1120
1144
  {
1121
1145
  selectedColor: layer.config.visConfig[property],
@@ -1126,11 +1150,27 @@ export function LayerColorRangeSelectorFactory(ColorSelector) {
1126
1150
  ? layer.updateColorMap(property, colorMap, colorRange)
1127
1151
  : colorRange;
1128
1152
  onChange({[property]: colorRangeUpdated});
1153
+ layer.validateScale(channel); // Validate scale to ensure that it changes from `identity` to the correct one.
1129
1154
  }
1130
1155
  }
1131
1156
  ]}
1132
1157
  colorUI={layer.config.colorUI[property]}
1133
1158
  setColorUI={newConfig => setColorUI(property, newConfig)}
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
+
1163
+ layer.updateLayerConfig({
1164
+ [field]: {
1165
+ ...layer.config[field],
1166
+ colorColumn: colorColumn?.name,
1167
+ colorColumnIdx: colorColumn?.fieldIdx
1168
+ },
1169
+ [scale]: SCALE_TYPES.identity
1170
+ });
1171
+
1172
+ onChange({[property]: hexColorCustomPalette});
1173
+ }}
1134
1174
  />
1135
1175
  </SidePanelSection>
1136
1176
  );
@@ -1206,6 +1246,11 @@ export function ChannelByValueSelectorFactory(VisConfigByFieldSelector) {
1206
1246
  if (visRange?.colorMap) {
1207
1247
  onChangeVisConfig({[range]: {...visRange, colorMap: undefined}});
1208
1248
  }
1249
+ if (!val) {
1250
+ // Clean everything and comeback to default behaviour
1251
+ onChange({[field]: null}, key);
1252
+ onChangeVisConfig({[range]: DEFAULT_COLOR_RANGE});
1253
+ }
1209
1254
  onChange(
1210
1255
  {
1211
1256
  [field]: val,
@@ -61,3 +61,12 @@ export const DEFAULT_COLOR_RANGE = colorRanges.find(({name}) => name === 'Global
61
61
  category: 'Uber',
62
62
  colors: ['#5A1846', '#900C3F', '#C70039', '#E3611C', '#F1920E', '#FFC300']
63
63
  };
64
+
65
+ export const hexColor = 'hexColor';
66
+ export const hexColorCustomPalette = {
67
+ name: hexColor,
68
+ type: hexColor,
69
+ colors: [],
70
+ category: 'CARTO',
71
+ hexColor: true
72
+ };
@@ -45,6 +45,7 @@ import {
45
45
  import {getHTMLMapModeTileUrl} from 'utils/utils';
46
46
  import {TOOLTIP_FORMAT_TYPES} from './tooltip';
47
47
  import {LAYER_TYPES} from 'layers/types';
48
+ import {scaleIdentity} from 'utils/custom-scales';
48
49
 
49
50
  export const ACTION_PREFIX = '@@kepler.gl/';
50
51
  export const CLOUDFRONT = 'https://d1a3f4spazzrp4.cloudfront.net/kepler.gl';
@@ -310,7 +311,8 @@ export const SCALE_TYPES = keyMirror({
310
311
  point: null,
311
312
  custom: null,
312
313
  // UI-only type, resolving as custom
313
- logarithmic: null
314
+ logarithmic: null,
315
+ identity: null
314
316
  });
315
317
 
316
318
  export const SCALE_FUNC = {
@@ -321,7 +323,8 @@ export const SCALE_FUNC = {
321
323
  [SCALE_TYPES.sqrt]: scaleSqrt,
322
324
  [SCALE_TYPES.log]: scaleLog,
323
325
  [SCALE_TYPES.point]: scalePoint,
324
- [SCALE_TYPES.custom]: scaleThreshold
326
+ [SCALE_TYPES.custom]: scaleThreshold,
327
+ [SCALE_TYPES.identity]: scaleIdentity
325
328
  };
326
329
 
327
330
  export const ALL_FIELD_TYPES = keyMirror({