@carto/kepler.gl 0.0.65 → 0.0.66

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/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@carto/kepler.gl",
3
3
  "author": "CARTO",
4
4
  "homepage": "https://github.com/CartoDB/carto-kepler#readme",
5
- "version": "0.0.65",
5
+ "version": "0.0.66",
6
6
  "description": "kepler.gl is a webgl based application to visualize large scale location data in the browser",
7
7
  "license": "MIT",
8
8
  "main": "dist/index.js",
@@ -238,14 +238,13 @@
238
238
  "tough-cookie": "4.0.0"
239
239
  },
240
240
  "peerDependencies": {
241
- "@deck.gl/aggregation-layers": "^8.9.5",
242
- "@deck.gl/carto": "^8.9.5",
243
- "@deck.gl/core": "^8.9.5",
244
- "@deck.gl/extensions": "^8.9.5",
245
- "@deck.gl/geo-layers": "^8.9.5",
246
- "@deck.gl/layers": "^8.9.5",
247
- "@deck.gl/mesh-layers": "^8.9.5",
248
- "@deck.gl/react": "^8.9.5",
241
+ "@deck.gl/aggregation-layers": "^8.7.3",
242
+ "@deck.gl/core": "^8.7.3",
243
+ "@deck.gl/extensions": "^8.7.3",
244
+ "@deck.gl/geo-layers": "^8.7.3",
245
+ "@deck.gl/layers": "^8.7.3",
246
+ "@deck.gl/mesh-layers": "^8.7.3",
247
+ "@deck.gl/react": "^8.7.3",
249
248
  "@loaders.gl/core": "^3.1.5",
250
249
  "@loaders.gl/csv": "^3.1.5",
251
250
  "@loaders.gl/gltf": "^3.1.5",
@@ -271,10 +270,6 @@
271
270
  "engines": {
272
271
  "node": ">=12.0.0"
273
272
  },
274
- "maintainers": [
275
- "Shan He <heshan0131@gmail.com>",
276
- "Giuseppe Macri <gmacri@uber.com>"
277
- ],
278
273
  "volta": {
279
274
  "node": "12.19.0"
280
275
  }
@@ -40,7 +40,7 @@ export const ConfigGroupCollapsibleContent = styled.div.attrs({
40
40
  overflow: visible;
41
41
  transition: max-height 0.3s ease-out;
42
42
  height: max-content;
43
- max-height: 650px;
43
+ max-height: 600px;
44
44
  `;
45
45
 
46
46
  export const ConfigGroupCollapsibleHeader = styled.div.attrs({
@@ -62,7 +62,7 @@ export const StyledLayerConfigGroup = styled.div`
62
62
  &.collapsed {
63
63
  .layer-config-group__header__collapsible {
64
64
  overflow: visible;
65
- max-height: 650px;
65
+ max-height: 600px;
66
66
  }
67
67
  .layer-config-group__content {
68
68
  .layer-config-group__content__collapsible {
@@ -67,7 +67,6 @@ function TextLabelPanelFactory(RangeSlider, LayerConfigGroup, FieldSelector, Col
67
67
  render() {
68
68
  const {updateLayerTextLabel, textLabel, fields, AddButton} = this.props;
69
69
  const currentFields = textLabel.map(tl => tl.field && tl.field.name).filter(d => d);
70
-
71
70
  return (
72
71
  <LayerConfigGroup label={'panel.text.label'} collapsible>
73
72
  <ConfigGroupCollapsibleHeader>
@@ -81,11 +80,11 @@ function TextLabelPanelFactory(RangeSlider, LayerConfigGroup, FieldSelector, Col
81
80
  <ConfigGroupCollapsibleContent>
82
81
  {textLabel.map((tl, idx) => (
83
82
  <div
84
- key={`${tl.field ? tl.field.name : 'null'}-${idx}`}
83
+ key={tl.field ? tl.field.name : `null-${idx}`}
85
84
  className="side-panel-section-group"
86
85
  >
87
86
  <PanelLabel>
88
- <FormattedMessage id={`panel.text.${idx === 0 ? 'main' : 'secondary'}Label`} />
87
+ <FormattedMessage id={'panel.text.labelWithId'} values={{labelId: idx + 1}} />
89
88
  </PanelLabel>
90
89
  <SidePanelSection>
91
90
  <FieldSelector
@@ -121,51 +120,33 @@ function TextLabelPanelFactory(RangeSlider, LayerConfigGroup, FieldSelector, Col
121
120
  />
122
121
  </SidePanelSection>
123
122
  <SidePanelSection>
124
- <PanelLabel>
125
- <FormattedMessage id="panel.text.outlineColor" />
126
- </PanelLabel>
127
- <ColorSelector
128
- colorSets={[
129
- {
130
- selectedColor: tl.outlineColor,
131
- setColor: v => updateLayerTextLabel(idx, 'outlineColor', v)
132
- }
133
- ]}
134
- />
123
+ <SpaceBetweenFlexbox>
124
+ <SBFlexboxItem>
125
+ <PanelLabel>
126
+ <FormattedMessage id="panel.text.textAnchor" />
127
+ </PanelLabel>
128
+ <ItemSelector
129
+ {...LAYER_TEXT_CONFIGS.textAnchor}
130
+ selectedItems={tl.anchor}
131
+ onChange={val => updateLayerTextLabel(idx, 'anchor', val)}
132
+ />
133
+ </SBFlexboxItem>
134
+ <SBFlexboxItem>
135
+ <PanelLabel>
136
+ <FormattedMessage id="panel.text.alignment" />
137
+ </PanelLabel>
138
+ <ItemSelector
139
+ {...LAYER_TEXT_CONFIGS.textAlignment}
140
+ selectedItems={tl.alignment}
141
+ onChange={val => updateLayerTextLabel(idx, 'alignment', val)}
142
+ />
143
+ </SBFlexboxItem>
144
+ </SpaceBetweenFlexbox>
135
145
  </SidePanelSection>
136
- {idx === 0 && (
137
- <SidePanelSection>
138
- <SpaceBetweenFlexbox>
139
- <SBFlexboxItem>
140
- <PanelLabel>
141
- <FormattedMessage id="panel.text.textAnchor" />
142
- </PanelLabel>
143
- <ItemSelector
144
- {...LAYER_TEXT_CONFIGS.textAnchor}
145
- selectedItems={tl.anchor}
146
- onChange={val => updateLayerTextLabel(idx, 'anchor', val)}
147
- />
148
- </SBFlexboxItem>
149
- <SBFlexboxItem>
150
- <PanelLabel>
151
- <FormattedMessage id="panel.text.alignment" />
152
- </PanelLabel>
153
- <ItemSelector
154
- {...LAYER_TEXT_CONFIGS.textAlignment}
155
- selectedItems={tl.alignment}
156
- onChange={val => updateLayerTextLabel(idx, 'alignment', val)}
157
- />
158
- </SBFlexboxItem>
159
- </SpaceBetweenFlexbox>
160
- </SidePanelSection>
161
- )}
162
146
  </div>
163
147
  ))}
164
148
  <SidePanelSection>
165
- <AddButton
166
- disabled={textLabel.length >= 2}
167
- onClick={val => updateLayerTextLabel(textLabel.length)}
168
- />
149
+ <AddButton onClick={val => updateLayerTextLabel(textLabel.length)} />
169
150
  </SidePanelSection>
170
151
  </ConfigGroupCollapsibleContent>
171
152
  </LayerConfigGroup>
@@ -20,9 +20,40 @@
20
20
 
21
21
  import {console as Console} from 'global/window';
22
22
  import keymirror from 'keymirror';
23
- import {CollisionFilterExtension, DataFilterExtension} from '@deck.gl/extensions';
23
+ import {DataFilterExtension} from '@deck.gl/extensions';
24
24
  import {COORDINATE_SYSTEM, Layer as DeckLayer} from '@deck.gl/core';
25
- import {_PointLabelLayer as PointLabelLayer} from '@deck.gl/carto';
25
+ import {TextLayer} from '@deck.gl/layers';
26
+
27
+ // Workaround until https://github.com/visgl/deck.gl/pull/7513 is released
28
+ DeckLayer.defaultProps.getFilterValue = {type: 'accessor', value: 0};
29
+
30
+ // Workaround until https://github.com/visgl/deck.gl/pull/7507 is released
31
+ function deepEqual(a, b) {
32
+ if (a === b) {
33
+ return true;
34
+ }
35
+ if (!a || !b) {
36
+ return false;
37
+ }
38
+ for (const key in a) {
39
+ const aValue = a[key];
40
+ const bValue = b[key];
41
+ const equals = aValue === bValue || deepEqual(aValue, bValue);
42
+ if (!equals) {
43
+ return false;
44
+ }
45
+ }
46
+ return true;
47
+ }
48
+
49
+ DeckLayer.defaultProps.loadOptions = {
50
+ type: 'object',
51
+ value: {},
52
+ optional: true,
53
+ compare: true,
54
+ equal: deepEqual
55
+ };
56
+
26
57
  import DefaultLayerIcon from './default-layer-icon';
27
58
  import {diffUpdateTriggers} from './layer-update';
28
59
 
@@ -72,7 +103,6 @@ const FALLBACK_ICON =
72
103
  const MAX_SAMPLE_SIZE = 5000;
73
104
  const defaultDomain = [0, 1];
74
105
  const dataFilterExtension = new DataFilterExtension({filterSize: MAX_GPU_FILTERS});
75
- const collisionFilterExtension = new CollisionFilterExtension();
76
106
 
77
107
  const defaultDataAccessor = dc => d => d;
78
108
  const defaultGetFieldValue = (field, d) => field.valueAccessor(d);
@@ -1311,89 +1341,51 @@ class Layer {
1311
1341
  };
1312
1342
  }
1313
1343
 
1314
- renderTextLabelLayer(
1315
- {getPosition, getRadius, radiusScale, updateTriggers, sharedProps},
1316
- renderOpts
1317
- ) {
1344
+ renderTextLabelLayer({getPosition, getPixelOffset, updateTriggers, sharedProps}, renderOpts) {
1318
1345
  const {data, mapState} = renderOpts;
1319
1346
  const {textLabel, visibilityByZoom} = this.config;
1320
- const extensions = [...sharedProps.extensions, collisionFilterExtension];
1321
-
1322
- if (!data || !data.textLabels || !data.textLabels[0] || !data.textLabels[0].getText) {
1323
- return [];
1324
- }
1325
1347
 
1326
- const [mainLabel, secondaryLabel] = textLabel;
1327
- const {
1328
- alignment,
1329
- anchor,
1330
- color: getColor,
1331
- field: mainField,
1332
- outlineColor,
1333
- size: sizeScale
1334
- } = mainLabel;
1335
- const {
1336
- color: getSecondaryColor,
1337
- field: secondaryField,
1338
- outlineColor: secondaryOutlineColor,
1339
- size: secondarySizeScale
1340
- } = secondaryLabel || {};
1341
-
1342
- return [
1343
- new PointLabelLayer({
1344
- ...sharedProps,
1345
-
1346
- // Recreate layer when labels change otherwise rendering breaks
1347
- // TODO could be more efficient with updateTriggers?
1348
- id: `${this.id}-${mainField?.name}-${secondaryField?.name}-label`,
1349
- data: data.data,
1350
- visibilityByZoom,
1351
- extensions,
1352
-
1353
- characterSet: 'auto',
1354
- collisionEnabled: true,
1355
- collisionGroup: `${this.id}-labels`,
1356
-
1357
- getText: data.textLabels[0].getText,
1358
- getColor,
1359
- sizeScale,
1360
- outlineColor,
1361
-
1362
- ...(secondaryField && {
1363
- getSecondaryText: data.textLabels[1].getText,
1364
- getSecondaryColor,
1365
- secondarySizeScale,
1366
- secondaryOutlineColor
1367
- }),
1368
-
1369
- // Position
1370
- getPosition,
1371
- getRadius,
1372
- radiusScale,
1373
- getTextAnchor: anchor,
1374
- getAlignmentBaseline: alignment,
1375
-
1376
- // Style
1377
- fontFamily: 'Inter, sans',
1378
- fontSettings: {sdf: true},
1379
- fontWeight: 500,
1380
- outlineWidth: 4,
1381
- parameters: {
1382
- // text will always show on top of all layers
1383
- depthTest: false
1384
- },
1385
-
1386
- getFilterValue: data.getFilterValue,
1387
- updateTriggers: {
1388
- ...updateTriggers,
1389
- getText: mainField?.name,
1390
- getColor: mainField?.color,
1391
- getTextAnchor: mainLabel.anchor,
1392
- getAlignmentBaseline: mainLabel.alignment,
1393
- getSecondaryText: secondaryField?.name
1394
- }
1395
- })
1396
- ];
1348
+ return data.textLabels.reduce((accu, d, i) => {
1349
+ if (d.getText) {
1350
+ accu.push(
1351
+ new TextLayer({
1352
+ ...sharedProps,
1353
+ id: `${this.id}-label-${textLabel[i].field?.name}`,
1354
+ data: data.data,
1355
+ visibilityByZoom,
1356
+ getText: d.getText,
1357
+ getPosition,
1358
+ characterSet: d.characterSet,
1359
+ getPixelOffset: getPixelOffset(textLabel[i]),
1360
+ getSize: 1,
1361
+ sizeScale: textLabel[i].size,
1362
+ getTextAnchor: textLabel[i].anchor,
1363
+ getAlignmentBaseline: textLabel[i].alignment,
1364
+ getColor: textLabel[i].color,
1365
+ parameters: {
1366
+ // text will always show on top of all layers
1367
+ depthTest: false
1368
+ },
1369
+
1370
+ getFilterValue: data.getFilterValue,
1371
+ updateTriggers: {
1372
+ ...updateTriggers,
1373
+ getText: textLabel[i].field?.name,
1374
+ getPixelOffset: {
1375
+ ...updateTriggers.getPixelOffset,
1376
+ ...updateTriggers.getRadius,
1377
+ anchor: textLabel[i].anchor,
1378
+ alignment: textLabel[i].alignment
1379
+ },
1380
+ getTextAnchor: textLabel[i].anchor,
1381
+ getAlignmentBaseline: textLabel[i].alignment,
1382
+ getColor: textLabel[i].color
1383
+ }
1384
+ })
1385
+ );
1386
+ }
1387
+ return accu;
1388
+ }, []);
1397
1389
  }
1398
1390
 
1399
1391
  /**
@@ -43,21 +43,13 @@ export {DEFAULT_COLOR_RANGE};
43
43
  /** @type {import('./layer-factory').LayerTextLabel} */
44
44
  export const DEFAULT_TEXT_LABEL = {
45
45
  field: null,
46
- color: [44, 48, 50],
47
- outlineColor: [255, 255, 255],
48
- size: 12,
46
+ color: [255, 255, 255],
47
+ size: 18,
49
48
  offset: [0, 0],
50
49
  anchor: 'start',
51
50
  alignment: 'center'
52
51
  };
53
52
 
54
- /** @type {import('./layer-factory').LayerTextLabel} */
55
- export const DEFAULT_SECONDARY_TEXT_LABEL = {
56
- ...DEFAULT_TEXT_LABEL,
57
- color: [128, 130, 132],
58
- size: 10
59
- };
60
-
61
53
  /** @type {import('./layer-factory').ColorRange} */
62
54
  export const DEFAULT_CUSTOM_PALETTE = {
63
55
  name: 'color.customPalette',
@@ -458,8 +450,8 @@ export const LAYER_VIS_CONFIGS = {
458
450
  export const LAYER_TEXT_CONFIGS = {
459
451
  fontSize: {
460
452
  type: 'number',
461
- range: [6, 32],
462
- value0: 6,
453
+ range: [1, 100],
454
+ value0: 1,
463
455
  step: 1,
464
456
  isRanged: false,
465
457
  label: 'Font size',
@@ -54,9 +54,40 @@ export const textLabelAccessor = textLabel => dc => d => {
54
54
  return notNullorUndefined(val) ? String(val) : '';
55
55
  };
56
56
 
57
- export const formatTextLabelData = ({textLabel, dataContainer}) => {
57
+ export const formatTextLabelData = ({
58
+ textLabel,
59
+ triggerChanged,
60
+ oldLayerData,
61
+ data,
62
+ dataContainer
63
+ }) => {
58
64
  return textLabel.map((tl, i) => {
59
- const getText = tl.field ? textLabelAccessor(tl)(dataContainer) : null;
60
- return {getText};
65
+ if (!tl.field) {
66
+ // if no field selected,
67
+ return {
68
+ getText: null,
69
+ characterSet: []
70
+ };
71
+ }
72
+
73
+ const getText = textLabelAccessor(tl)(dataContainer);
74
+ let characterSet;
75
+
76
+ if (
77
+ !triggerChanged[`getLabelCharacterSet-${i}`] &&
78
+ oldLayerData &&
79
+ oldLayerData.textLabels &&
80
+ oldLayerData.textLabels[i]
81
+ ) {
82
+ characterSet = oldLayerData.textLabels[i].characterSet;
83
+ } else {
84
+ const allLabels = tl.field ? data.map(getText) : [];
85
+ characterSet = uniq(allLabels.join(''));
86
+ }
87
+
88
+ return {
89
+ characterSet,
90
+ getText
91
+ };
61
92
  });
62
93
  };
@@ -29,7 +29,7 @@ import {findDefaultColorField} from 'utils/dataset-utils';
29
29
  import PointLayerIcon from './point-layer-icon';
30
30
  import {DEFAULT_LAYER_COLOR, CHANNEL_SCALES, UNKNOWN_COLOR} from 'constants/default-settings';
31
31
 
32
- import {formatTextLabelData} from '../layer-text-label';
32
+ import {getTextOffsetByRadius, formatTextLabelData} from '../layer-text-label';
33
33
 
34
34
  export const pointPosAccessor = ({lat, lng, altitude}) => dc => d => [
35
35
  dc.valueAt(d.index, lng.fieldIdx),
@@ -242,7 +242,13 @@ export default class PointLayer extends Layer {
242
242
  const getPosition = this.getPositionAccessor(dataContainer);
243
243
 
244
244
  // get all distinct characters in the text labels
245
- const textLabels = formatTextLabelData({textLabel, dataContainer});
245
+ const textLabels = formatTextLabelData({
246
+ textLabel,
247
+ triggerChanged,
248
+ oldLayerData,
249
+ data,
250
+ dataContainer
251
+ });
246
252
 
247
253
  const accessors = this.getAttributeAccessors({dataContainer});
248
254
 
@@ -272,12 +278,12 @@ export default class PointLayer extends Layer {
272
278
  // eslint-disable-next-line complexity, max-statements
273
279
  renderLayer(opts) {
274
280
  const {data, gpuFilter, objectHovered, interactionConfig} = opts;
275
- const {customMarkers, customMarkersUrl, customMarkersRange} = this.config.visConfig;
276
281
 
277
282
  const radiusScale = this.getRadiusScale();
278
283
 
279
284
  const defaultLayerProps = this.getDefaultDeckLayerProps(opts);
280
285
  const brushingProps = this.getBrushingExtensionProps(interactionConfig);
286
+ const getPixelOffset = getTextOffsetByRadius(radiusScale, data.getRadius);
281
287
  const extensions = [...defaultLayerProps.extensions, brushingExtension];
282
288
 
283
289
  const updateTriggers = {
@@ -290,7 +296,6 @@ export default class PointLayer extends Layer {
290
296
  getFilterValue: data.getFilterValue,
291
297
  extensions,
292
298
  filterRange: defaultLayerProps.filterRange,
293
- maskId: defaultLayerProps.maskId,
294
299
  visible: defaultLayerProps.visible,
295
300
  ...brushingProps
296
301
  };
@@ -300,9 +305,7 @@ export default class PointLayer extends Layer {
300
305
  {
301
306
  getPosition: data.getPosition,
302
307
  sharedProps,
303
- // TODO remove this scaling by half here and elsewhere
304
- radiusScale: customMarkers ? radiusScale / 2 : radiusScale,
305
- getRadius: data.getRadius,
308
+ getPixelOffset,
306
309
  updateTriggers
307
310
  },
308
311
  opts
@@ -316,6 +319,7 @@ export default class PointLayer extends Layer {
316
319
  };
317
320
 
318
321
  const customMarkersField = this.config.customMarkersField;
322
+ const {customMarkers, customMarkersUrl, customMarkersRange} = this.config.visConfig;
319
323
  const customMarkersConfigured =
320
324
  customMarkers && Boolean(customMarkersUrl || (customMarkersField && customMarkersRange));
321
325
  const customMarkersMisConfigured = customMarkers && !customMarkersConfigured;
@@ -68,14 +68,12 @@ export default {
68
68
  panel: {
69
69
  text: {
70
70
  label: 'label',
71
- mainLabel: 'Main Label',
72
- secondaryLabel: 'Secondary Label',
71
+ labelWithId: 'Label {labelId}',
73
72
  fontSize: 'Font size',
74
73
  fontColor: 'Font color',
75
- outlineColor: 'Outline color',
76
74
  textAnchor: 'Text anchor',
77
75
  alignment: 'Alignment',
78
- addMoreLabel: 'Add secondary label'
76
+ addMoreLabel: 'Add More Label'
79
77
  }
80
78
  },
81
79
  sidebar: {
@@ -83,7 +81,7 @@ export default {
83
81
  layer: 'Layers',
84
82
  filter: 'Filters',
85
83
  interaction: 'Interactions',
86
- basemap: 'Basemap'
84
+ basemap: 'Base map'
87
85
  }
88
86
  },
89
87
  layer: {
@@ -159,7 +157,6 @@ export default {
159
157
  highPrecisionRenderingDescription: 'High precision will result in slower performance',
160
158
  height: 'Height',
161
159
  heightDescription: 'Click button at top right of the map to switch to 3d view',
162
- labels: 'Labels',
163
160
  fill: 'Fill',
164
161
  enablePolygonHeight: 'Enable Polygon Height',
165
162
  showWireframe: 'Show Wireframe',
@@ -216,7 +213,7 @@ export default {
216
213
  hideLayerPanel: 'Hide layer panel',
217
214
  showLayerPanel: 'Show layer panel',
218
215
  moveToTop: 'Move to top of data layers',
219
- selectBaseMapStyle: 'Select Basemap Style',
216
+ selectBaseMapStyle: 'Select Base Map Style',
220
217
  delete: 'Delete',
221
218
  timePlayback: 'Time Playback',
222
219
  cloudStorage: 'Cloud Storage',
@@ -288,7 +288,10 @@ export function getFieldsFromData(data, fieldOrder) {
288
288
  // add a check for epoch timestamp
289
289
  const metadata = Analyzer.computeColMeta(
290
290
  data,
291
- [{regex: /.*geojson|all_points/g, dataType: 'GEOMETRY'}],
291
+ [
292
+ {regex: /.*geojson|all_points/g, dataType: 'GEOMETRY'},
293
+ {regex: /.*census/g, dataType: 'STRING'}
294
+ ],
292
295
  {ignoredDataTypes: IGNORE_DATA_TYPES}
293
296
  );
294
297
 
@@ -76,7 +76,7 @@ import {
76
76
  } from 'utils/split-map-utils';
77
77
 
78
78
  import {Layer, LayerClasses, LAYER_ID_LENGTH} from 'layers';
79
- import {DEFAULT_TEXT_LABEL, DEFAULT_SECONDARY_TEXT_LABEL} from 'layers/layer-factory';
79
+ import {DEFAULT_TEXT_LABEL} from 'layers/layer-factory';
80
80
  import {EDITOR_MODES, SORT_ORDER, FILTER_TYPES} from 'constants/default-settings';
81
81
  import {pick_, merge_, swap_} from './composer-helpers';
82
82
  import {processFileContent} from 'actions/vis-state-actions';
@@ -315,19 +315,16 @@ function addOrRemoveTextLabels(newFields, textLabel) {
315
315
 
316
316
  // delete
317
317
  newTextLabel = newTextLabel.filter(tl => tl.field && !deleteFields.includes(tl.field.name));
318
+ newTextLabel = !newTextLabel.length ? [DEFAULT_TEXT_LABEL] : newTextLabel;
318
319
 
319
320
  // add
320
- newTextLabel = newTextLabel.filter(tl => tl.field);
321
- const defaultLabel = newTextLabel.length ? DEFAULT_SECONDARY_TEXT_LABEL : DEFAULT_TEXT_LABEL;
322
- newTextLabel = [...newTextLabel, ...addFields.map(af => ({...defaultLabel, field: af}))];
323
-
324
- // limit to 2 labels (overwrite 2nd label with 3rd)
325
- if (newTextLabel.length > 2) {
326
- newTextLabel = [newTextLabel[0], newTextLabel[2]];
327
- }
328
-
329
- // default
330
- newTextLabel = !newTextLabel.length ? [DEFAULT_TEXT_LABEL] : newTextLabel;
321
+ newTextLabel = [
322
+ ...newTextLabel.filter(tl => tl.field),
323
+ ...addFields.map(af => ({
324
+ ...DEFAULT_TEXT_LABEL,
325
+ field: af
326
+ }))
327
+ ];
331
328
 
332
329
  return newTextLabel;
333
330
  }
@@ -362,7 +359,7 @@ export function layerTextLabelChangeUpdater(state, action) {
362
359
  let newTextLabel = textLabel.slice();
363
360
  if (!textLabel[idx] && idx === textLabel.length) {
364
361
  // if idx is set to length, add empty text label
365
- newTextLabel = [...textLabel, idx === 0 ? DEFAULT_TEXT_LABEL : DEFAULT_SECONDARY_TEXT_LABEL];
362
+ newTextLabel = [...textLabel, DEFAULT_TEXT_LABEL];
366
363
  }
367
364
 
368
365
  if (idx === 'all' && prop === 'fields') {