kepler.gl 3.1.10 → 3.2.1
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/src/ai-assistant/src/config/models.d.ts +8 -0
- package/dist/src/components/src/side-panel/layer-panel/vector-tile-layer-configurator.d.ts +3 -2
- package/dist/src/localization/src/translations/en.d.ts +1 -0
- package/package.json +2 -2
- package/src/actions/package.json +8 -8
- package/src/ai-assistant/dist/components/ai-assistant-config.js +40 -24
- package/src/ai-assistant/dist/config/models.d.ts +8 -0
- package/src/ai-assistant/dist/config/models.js +16 -8
- package/src/ai-assistant/dist/localization.js +7 -7
- package/src/ai-assistant/dist/reducers/index.js +3 -2
- package/src/ai-assistant/package.json +16 -16
- package/src/ai-assistant/src/components/ai-assistant-config.tsx +39 -28
- package/src/ai-assistant/src/config/models.ts +37 -25
- package/src/ai-assistant/src/localization.ts +6 -6
- package/src/ai-assistant/src/reducers/index.ts +2 -1
- package/src/cloud-providers/package.json +2 -2
- package/src/common-utils/package.json +3 -3
- package/src/components/dist/common/color-legend.js +8 -8
- package/src/components/dist/common/data-table/index.js +13 -9
- package/src/components/dist/map/map-legend-panel.js +10 -4
- package/src/components/dist/map/map-legend.js +2 -2
- package/src/components/dist/modal-container.js +3 -3
- package/src/components/dist/modals/tilesets-modals/tileset-raster-form.js +38 -9
- package/src/components/dist/plot-container.js +4 -2
- package/src/components/dist/side-panel/interaction-panel/interaction-panel.js +2 -2
- package/src/components/dist/side-panel/layer-panel/color-breaks-panel.js +11 -2
- package/src/components/dist/side-panel/layer-panel/color-scale-selector.js +65 -12
- package/src/components/dist/side-panel/layer-panel/custom-palette.js +18 -7
- package/src/components/dist/side-panel/layer-panel/raster-tile-layer-configurator.js +3 -3
- package/src/components/dist/side-panel/layer-panel/vector-tile-layer-configurator.d.ts +3 -2
- package/src/components/dist/side-panel/layer-panel/vector-tile-layer-configurator.js +18 -4
- package/src/components/package.json +15 -15
- package/src/components/src/common/color-legend.tsx +15 -2
- package/src/components/src/common/data-table/index.tsx +1 -1
- package/src/components/src/map/map-legend-panel.tsx +21 -2
- package/src/components/src/map/map-legend.tsx +1 -1
- package/src/components/src/modal-container.tsx +6 -2
- package/src/components/src/modals/tilesets-modals/tileset-raster-form.tsx +60 -4
- package/src/components/src/plot-container.tsx +2 -1
- package/src/components/src/side-panel/interaction-panel/interaction-panel.tsx +1 -0
- package/src/components/src/side-panel/layer-panel/color-breaks-panel.tsx +14 -3
- package/src/components/src/side-panel/layer-panel/color-scale-selector.tsx +62 -8
- package/src/components/src/side-panel/layer-panel/custom-palette.tsx +11 -5
- package/src/components/src/side-panel/layer-panel/raster-tile-layer-configurator.tsx +2 -1
- package/src/components/src/side-panel/layer-panel/vector-tile-layer-configurator.tsx +19 -2
- package/src/constants/dist/default-settings.js +2 -2
- package/src/constants/node_modules/.cache/terser-webpack-plugin/content-v2/sha512/56/48/71c2c5381c01c063c164e15fa04b4b1f3faae02e6727f2f2daf483e15205feca68334bad721af0c6f31abb20b56d60504623838127764aab6883912e7f71 +1 -0
- package/src/constants/node_modules/.cache/terser-webpack-plugin/content-v2/sha512/b3/bd/e4f91c7af9e320b979e29ad3b9e3a4dfcd61e4a09d6e4579104c40dcace7651b443fdd6d7ff5d947ed6c9df2c0bbbcc76a2ea86d6398e4945257eeb80dd5 +1 -0
- package/src/constants/node_modules/.cache/terser-webpack-plugin/index-v5/b4/c5/a43653dff3b380f7b0793080a57c980a9a136764933e79454de0fe43a5ca +2 -0
- package/src/constants/node_modules/.cache/terser-webpack-plugin/index-v5/bf/88/ea60c7619185516464a4ae21f51394966047bfdf190a5463de651c61931c +2 -0
- package/src/constants/package.json +2 -2
- package/src/constants/umd/keplergl.min.js +1 -1
- package/src/deckgl-arrow-layers/package.json +2 -2
- package/src/deckgl-layers/package.json +4 -4
- package/src/duckdb/dist/table/duckdb-table-utils.js +3 -2
- package/src/duckdb/package.json +6 -6
- package/src/duckdb/src/table/duckdb-table-utils.ts +5 -1
- package/src/effects/package.json +5 -5
- package/src/layers/dist/icon-layer/icon-layer.js +12 -2
- package/src/layers/dist/raster-tile/gpu-utils.d.ts +11 -10
- package/src/layers/dist/raster-tile/gpu-utils.js +7 -6
- package/src/layers/dist/raster-tile/image.d.ts +4 -0
- package/src/layers/dist/raster-tile/image.js +30 -16
- package/src/layers/dist/raster-tile/raster-tile-layer.d.ts +4 -0
- package/src/layers/dist/raster-tile/raster-tile-layer.js +18 -6
- package/src/layers/dist/raster-tile/request-throttle.d.ts +1 -1
- package/src/layers/dist/raster-tile/request-throttle.js +17 -16
- package/src/layers/dist/raster-tile/types.d.ts +16 -0
- package/src/layers/dist/raster-tile/types.js +1 -1
- package/src/layers/dist/raster-tile/url.d.ts +1 -1
- package/src/layers/dist/raster-tile/url.js +5 -4
- package/src/layers/dist/vector-tile/common-tile/tile-dataset.d.ts +4 -0
- package/src/layers/dist/vector-tile/common-tile/tile-dataset.js +10 -1
- package/src/layers/dist/vector-tile/vector-tile-layer.d.ts +11 -0
- package/src/layers/dist/vector-tile/vector-tile-layer.js +113 -7
- package/src/layers/package.json +9 -9
- package/src/layers/src/icon-layer/icon-layer.ts +49 -38
- package/src/layers/src/raster-tile/gpu-utils.ts +96 -78
- package/src/layers/src/raster-tile/image.ts +35 -9
- package/src/layers/src/raster-tile/raster-tile-layer.ts +23 -5
- package/src/layers/src/raster-tile/request-throttle.ts +10 -5
- package/src/layers/src/raster-tile/types.ts +19 -1
- package/src/layers/src/raster-tile/url.ts +10 -3
- package/src/layers/src/vector-tile/common-tile/tile-dataset.ts +7 -0
- package/src/layers/src/vector-tile/vector-tile-layer.ts +110 -6
- package/src/localization/dist/translations/en.d.ts +1 -0
- package/src/localization/dist/translations/en.js +2 -1
- package/src/localization/package.json +1 -1
- package/src/localization/src/translations/en.ts +1 -0
- package/src/processors/dist/data-processor.js +15 -5
- package/src/processors/package.json +7 -7
- package/src/processors/src/data-processor.ts +19 -4
- package/src/reducers/package.json +16 -16
- package/src/schemas/package.json +7 -7
- package/src/styles/node_modules/.cache/terser-webpack-plugin/content-v2/sha512/21/4a/50f77069dbf70c6792dd82d4e149375a888e25ddddd3209e2db013be62091f79082291fa06eb518cccb111b09a778e2946c1fb7a27bb6e32f72da0ccf250 +1 -0
- package/src/styles/node_modules/.cache/terser-webpack-plugin/content-v2/sha512/52/82/28cacf6fd462b779c22675964b655bf3a9f3ce9ec3c9b141a401a5bf90cb7d904ac65ab8e484570130b12771af0a0d5bab20e6976cfa773666763e046a6a +1 -0
- package/src/styles/node_modules/.cache/terser-webpack-plugin/index-v5/56/db/b5a812c56b0d1dcdcd33da37e464062a19c8752cb2296603dc72d2c54d31 +2 -0
- package/src/styles/node_modules/.cache/terser-webpack-plugin/index-v5/c5/b6/9c4bdb089acc30ac8a16a6b9b93898757537f7017b2f725ddb832b4614d6 +2 -0
- package/src/styles/package.json +2 -2
- package/src/styles/umd/keplergl.min.js +1 -1
- package/src/table/dist/tileset/vector-tile-utils.js +9 -5
- package/src/table/package.json +5 -5
- package/src/table/src/tileset/vector-tile-utils.ts +9 -6
- package/src/tasks/package.json +2 -2
- package/src/types/package.json +1 -1
- package/src/utils/dist/application-config.js +5 -5
- package/src/utils/package.json +4 -4
- package/src/utils/src/application-config.ts +4 -6
- package/umd/keplergl.min.js +1385 -1332
|
@@ -15,11 +15,12 @@ import {getApplicationConfig} from '@kepler.gl/utils';
|
|
|
15
15
|
import {default as useFetchJson} from '../../hooks/use-fetch-raster-tile-metadata';
|
|
16
16
|
import {DatasetCreationAttributes, MetaResponse} from './common';
|
|
17
17
|
import {InputLight} from '../../common';
|
|
18
|
+
import {Help} from '../../common/icons';
|
|
18
19
|
|
|
19
20
|
const TilesetInputContainer = styled.div`
|
|
20
21
|
display: grid;
|
|
21
22
|
grid-template-rows: repeat(3, 1fr);
|
|
22
|
-
row-gap:
|
|
23
|
+
row-gap: 0px;
|
|
23
24
|
font-size: 12px;
|
|
24
25
|
`;
|
|
25
26
|
|
|
@@ -29,6 +30,11 @@ const TilesetInputDescription = styled.div`
|
|
|
29
30
|
font-size: 11px;
|
|
30
31
|
`;
|
|
31
32
|
|
|
33
|
+
const LabelRow = styled.div`
|
|
34
|
+
display: flex;
|
|
35
|
+
align-items: center;
|
|
36
|
+
`;
|
|
37
|
+
|
|
32
38
|
export type RasterTilesetMeta = {
|
|
33
39
|
name: string;
|
|
34
40
|
metadataUrl: string;
|
|
@@ -40,12 +46,20 @@ export function getDatasetAttributesFromRasterTile({
|
|
|
40
46
|
metadataUrl,
|
|
41
47
|
rasterTileServerUrls
|
|
42
48
|
}: RasterTilesetMeta): DatasetCreationAttributes {
|
|
49
|
+
const appConfig = getApplicationConfig();
|
|
43
50
|
return {
|
|
44
51
|
name,
|
|
45
52
|
type: DatasetType.RASTER_TILE,
|
|
46
53
|
metadata: {
|
|
47
54
|
metadataUrl,
|
|
48
|
-
...(rasterTileServerUrls ? {rasterTileServerUrls} : {})
|
|
55
|
+
...(rasterTileServerUrls ? {rasterTileServerUrls} : {}),
|
|
56
|
+
// Persist raster server-related application config with the layer
|
|
57
|
+
rasterServerUseLatestTitiler: appConfig.rasterServerUseLatestTitiler,
|
|
58
|
+
rasterServerSupportsElevation: appConfig.rasterServerSupportsElevation,
|
|
59
|
+
rasterServerMaxRetries: appConfig.rasterServerMaxRetries,
|
|
60
|
+
rasterServerRetryDelay: appConfig.rasterServerRetryDelay,
|
|
61
|
+
rasterServerServerErrorsToRetry: appConfig.rasterServerServerErrorsToRetry,
|
|
62
|
+
rasterServerMaxPerServerRequests: appConfig.rasterServerMaxPerServerRequests
|
|
49
63
|
}
|
|
50
64
|
};
|
|
51
65
|
}
|
|
@@ -54,6 +68,28 @@ type RasterTileFormProps = {
|
|
|
54
68
|
setResponse: (response: MetaResponse) => void;
|
|
55
69
|
};
|
|
56
70
|
|
|
71
|
+
const InfoIconLink = styled.a`
|
|
72
|
+
margin-left: 4px;
|
|
73
|
+
color: ${props => props.theme.labelColor};
|
|
74
|
+
text-decoration: none;
|
|
75
|
+
display: inline-flex;
|
|
76
|
+
align-items: center;
|
|
77
|
+
line-height: 0;
|
|
78
|
+
vertical-align: middle;
|
|
79
|
+
opacity: 0.7;
|
|
80
|
+
|
|
81
|
+
&:hover {
|
|
82
|
+
opacity: 1;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
svg {
|
|
86
|
+
display: block;
|
|
87
|
+
}
|
|
88
|
+
`;
|
|
89
|
+
|
|
90
|
+
const RASTER_TILE_DOCUMENTATION_URL =
|
|
91
|
+
'https://docs.kepler.gl/docs/user-guides/c-types-of-layers/n-raster-tile-layer';
|
|
92
|
+
|
|
57
93
|
const parseMetadataAllowCollections = (
|
|
58
94
|
metadata: JsonObjectOrArray | PMTilesMetadata,
|
|
59
95
|
{metadataUrl, rasterTileType}: {metadataUrl: string; rasterTileType: RasterTileType}
|
|
@@ -201,7 +237,17 @@ const RasterTileForm: React.FC<RasterTileFormProps> = ({setResponse}) => {
|
|
|
201
237
|
/>
|
|
202
238
|
</div>
|
|
203
239
|
<div>
|
|
204
|
-
<
|
|
240
|
+
<LabelRow>
|
|
241
|
+
<label htmlFor="tile-metadata">Tileset metadata URL</label>
|
|
242
|
+
<InfoIconLink
|
|
243
|
+
href={RASTER_TILE_DOCUMENTATION_URL}
|
|
244
|
+
target="_blank"
|
|
245
|
+
rel="noopener noreferrer"
|
|
246
|
+
aria-label="Open Raster Tile Layer documentation"
|
|
247
|
+
>
|
|
248
|
+
<Help height="16px" />
|
|
249
|
+
</InfoIconLink>
|
|
250
|
+
</LabelRow>
|
|
205
251
|
<InputLight
|
|
206
252
|
id="tile-metadata"
|
|
207
253
|
placeholder="Tileset metadata URL"
|
|
@@ -214,7 +260,17 @@ const RasterTileForm: React.FC<RasterTileFormProps> = ({setResponse}) => {
|
|
|
214
260
|
</div>
|
|
215
261
|
{showServerInput && (
|
|
216
262
|
<div>
|
|
217
|
-
<
|
|
263
|
+
<LabelRow>
|
|
264
|
+
<label htmlFor="tileset-raster-servers">Raster tile servers</label>
|
|
265
|
+
<InfoIconLink
|
|
266
|
+
href={RASTER_TILE_DOCUMENTATION_URL}
|
|
267
|
+
target="_blank"
|
|
268
|
+
rel="noopener noreferrer"
|
|
269
|
+
aria-label="Open Raster Tile Layer documentation"
|
|
270
|
+
>
|
|
271
|
+
<Help height="16px" />
|
|
272
|
+
</InfoIconLink>
|
|
273
|
+
</LabelRow>
|
|
218
274
|
<InputLight
|
|
219
275
|
id="tileset-raster-servers"
|
|
220
276
|
placeholder="Raster tile servers (separated by commas)"
|
|
@@ -12,7 +12,7 @@ import {
|
|
|
12
12
|
colorMapToColorBreaks,
|
|
13
13
|
isNumericColorBreaks as notOrdinalColorBreaks
|
|
14
14
|
} from '@kepler.gl/utils';
|
|
15
|
-
import React, {useCallback, useMemo} from 'react';
|
|
15
|
+
import React, {useCallback, useMemo, useEffect} from 'react';
|
|
16
16
|
import styled from 'styled-components';
|
|
17
17
|
import ColumnStatsChartFactory from '../../common/column-stats-chart';
|
|
18
18
|
import {Edit} from '../../common/icons';
|
|
@@ -155,6 +155,17 @@ function ColorBreaksPanelFactory(
|
|
|
155
155
|
[customPalette.colorMap, isEditingCustomBreaks, colorBreaks]
|
|
156
156
|
);
|
|
157
157
|
|
|
158
|
+
// Update layers on editing custom breaks
|
|
159
|
+
useEffect(() => {
|
|
160
|
+
const {type} = customPalette || {};
|
|
161
|
+
if (
|
|
162
|
+
isEditingCustomBreaks &&
|
|
163
|
+
(type === SCALE_TYPES.customOrdinal || type === SCALE_TYPES.custom)
|
|
164
|
+
) {
|
|
165
|
+
onScaleChange(type, customPalette);
|
|
166
|
+
}
|
|
167
|
+
}, [isEditingCustomBreaks, customPalette, onScaleChange]);
|
|
168
|
+
|
|
158
169
|
const onClickEditCustomBreaks = useCallback(() => {
|
|
159
170
|
setColorUI({
|
|
160
171
|
colorRangeConfig: {
|
|
@@ -231,8 +242,8 @@ function ColorBreaksPanelFactory(
|
|
|
231
242
|
currentBreaks={currentBreaks}
|
|
232
243
|
onEdit={isCustomBreaks ? onClickEditCustomBreaks : null}
|
|
233
244
|
/>
|
|
234
|
-
) : customPalette.
|
|
235
|
-
customPalette.
|
|
245
|
+
) : (isCustomBreaks || customPalette.type === SCALE_TYPES.customOrdinal) &&
|
|
246
|
+
customPalette.colorMap &&
|
|
236
247
|
customPalette.name?.endsWith(colorField.name) ? (
|
|
237
248
|
<CategoricalColorDisplay
|
|
238
249
|
colorMap={customPalette.colorMap}
|
|
@@ -148,6 +148,28 @@ function ColorScaleSelectorFactory(
|
|
|
148
148
|
);
|
|
149
149
|
const [tippyInstance, setTippyInstance] = useState<TippyInstance>();
|
|
150
150
|
const isEditingColorBreaks = colorUIConfig?.colorRangeConfig?.customBreaks;
|
|
151
|
+
|
|
152
|
+
// Stores the previous selection for live preview: when choosing Custom/Custom Ordinal, we apply a temporary palette.
|
|
153
|
+
// Cancel restores {scale, range} from this ref; Confirm keeps the change and clears the ref.
|
|
154
|
+
// If the user switches between different custom scale types (e.g., from "Custom" to "Custom Ordinal") or is already in a custom scale state,
|
|
155
|
+
// this ref is updated to always store the most recent non-custom selection. Only the latest non-custom selection is restorable on cancel.
|
|
156
|
+
const prevSelectionRef = React.useRef<{scale: string; range: ColorRange} | null>(null);
|
|
157
|
+
|
|
158
|
+
// when custom color scale - but Confirm is not clicked yet
|
|
159
|
+
const pendingOption = useMemo(
|
|
160
|
+
() =>
|
|
161
|
+
isEditingColorBreaks
|
|
162
|
+
? (dropdownSelectProps.options || []).find(
|
|
163
|
+
o => getOptionValue(o) === colorUIConfig?.customPalette?.type
|
|
164
|
+
) || null
|
|
165
|
+
: null,
|
|
166
|
+
[
|
|
167
|
+
isEditingColorBreaks,
|
|
168
|
+
dropdownSelectProps.options,
|
|
169
|
+
getOptionValue,
|
|
170
|
+
colorUIConfig?.customPalette?.type
|
|
171
|
+
]
|
|
172
|
+
);
|
|
151
173
|
const colorScale = useMemo(
|
|
152
174
|
() =>
|
|
153
175
|
getLayerColorScale({
|
|
@@ -234,14 +256,16 @@ function ColorScaleSelectorFactory(
|
|
|
234
256
|
const onSelectScale = useCallback(
|
|
235
257
|
val => {
|
|
236
258
|
// highlight selected option
|
|
237
|
-
if (!val
|
|
259
|
+
if (!val) return;
|
|
260
|
+
|
|
238
261
|
const selectedScale = getOptionValue(val);
|
|
239
|
-
if (selectedScale === SCALE_TYPES.custom) {
|
|
262
|
+
if (selectedScale === SCALE_TYPES.custom || selectedScale === SCALE_TYPES.customOrdinal) {
|
|
240
263
|
const customPalette = initCustomPaletteByCustomScale({
|
|
241
264
|
scale: selectedScale,
|
|
242
265
|
field,
|
|
243
266
|
range,
|
|
244
|
-
colorBreaks
|
|
267
|
+
colorBreaks,
|
|
268
|
+
...(selectedScale === SCALE_TYPES.customOrdinal ? {ordinalDomain} : {})
|
|
245
269
|
});
|
|
246
270
|
setColorUI({
|
|
247
271
|
showColorChart: true,
|
|
@@ -250,28 +274,55 @@ function ColorScaleSelectorFactory(
|
|
|
250
274
|
},
|
|
251
275
|
customPalette
|
|
252
276
|
});
|
|
277
|
+
// store previous selection for cancel, then preview custom on the map
|
|
278
|
+
if (!prevSelectionRef.current) {
|
|
279
|
+
prevSelectionRef.current = {scale: scaleType, range};
|
|
280
|
+
}
|
|
253
281
|
onSelect(selectedScale, customPalette);
|
|
254
|
-
} else if (hasColorMap(range)
|
|
282
|
+
} else if (hasColorMap(range)) {
|
|
255
283
|
// not custom
|
|
256
284
|
// remove colorMap
|
|
257
285
|
// eslint-disable-next-line no-unused-vars
|
|
258
286
|
const {colorMap: _, ...newRange} = range;
|
|
287
|
+
// reset colorUI before changing the scale
|
|
288
|
+
setColorUI({
|
|
289
|
+
showColorChart: false,
|
|
290
|
+
colorRangeConfig: {
|
|
291
|
+
customBreaks: false
|
|
292
|
+
}
|
|
293
|
+
});
|
|
259
294
|
onSelect(selectedScale, newRange);
|
|
260
295
|
} else {
|
|
296
|
+
// reset colorUI before changing the scale
|
|
297
|
+
setColorUI({
|
|
298
|
+
showColorChart: false,
|
|
299
|
+
colorRangeConfig: {
|
|
300
|
+
customBreaks: false
|
|
301
|
+
}
|
|
302
|
+
});
|
|
261
303
|
onSelect(selectedScale);
|
|
262
304
|
}
|
|
263
305
|
},
|
|
264
|
-
[
|
|
306
|
+
[field, setColorUI, onSelect, range, getOptionValue, colorBreaks, ordinalDomain, scaleType]
|
|
265
307
|
);
|
|
266
308
|
|
|
267
309
|
const onApply = useCallback(() => {
|
|
268
|
-
|
|
310
|
+
// change scale type only if confirmed
|
|
311
|
+
const nextScaleType = colorUIConfig?.customPalette?.type || scaleType;
|
|
312
|
+
onSelect(nextScaleType, colorUIConfig.customPalette);
|
|
269
313
|
hideTippy(tippyInstance);
|
|
314
|
+
prevSelectionRef.current = null;
|
|
270
315
|
}, [onSelect, colorUIConfig.customPalette, tippyInstance, scaleType]);
|
|
271
316
|
|
|
272
317
|
const onCancel = useCallback(() => {
|
|
318
|
+
// restore previous selection if any
|
|
319
|
+
if (prevSelectionRef.current) {
|
|
320
|
+
const {scale: prevScale, range: prevRange} = prevSelectionRef.current;
|
|
321
|
+
onSelect(prevScale, prevRange);
|
|
322
|
+
}
|
|
273
323
|
hideTippy(tippyInstance);
|
|
274
|
-
|
|
324
|
+
prevSelectionRef.current = null;
|
|
325
|
+
}, [tippyInstance, onSelect]);
|
|
275
326
|
|
|
276
327
|
const isCustomBreaks =
|
|
277
328
|
scaleType === SCALE_TYPES.custom || scaleType === SCALE_TYPES.customOrdinal;
|
|
@@ -317,6 +368,9 @@ function ColorScaleSelectorFactory(
|
|
|
317
368
|
customListComponent={ColorScaleSelectDropdown}
|
|
318
369
|
searchable={false}
|
|
319
370
|
showOptionsWhenEmpty
|
|
371
|
+
selectedItems={
|
|
372
|
+
pendingOption ? [pendingOption] : dropdownSelectProps.selectedItems
|
|
373
|
+
}
|
|
320
374
|
/>
|
|
321
375
|
)}
|
|
322
376
|
</DropdownWrapper>
|
|
@@ -327,7 +381,7 @@ function ColorScaleSelectorFactory(
|
|
|
327
381
|
<DropdownSelect
|
|
328
382
|
{...dropdownSelectProps}
|
|
329
383
|
displayOption={displayOption}
|
|
330
|
-
value={dropdownSelectProps.selectedItems[0]}
|
|
384
|
+
value={pendingOption || dropdownSelectProps.selectedItems[0]}
|
|
331
385
|
/>
|
|
332
386
|
</div>
|
|
333
387
|
</LazyTippy>
|
|
@@ -377,8 +377,11 @@ export const EditableColorRange: React.FC<EditableColorRangeProps> = ({
|
|
|
377
377
|
editColorMap,
|
|
378
378
|
editable
|
|
379
379
|
}) => {
|
|
380
|
-
const
|
|
381
|
-
const
|
|
380
|
+
const hasInputs = Array.isArray(item?.inputs);
|
|
381
|
+
const leftInput = hasInputs ? item.inputs[0] : undefined;
|
|
382
|
+
const rightInput = hasInputs ? item.inputs[1] : undefined;
|
|
383
|
+
const noMinBound = !Number.isFinite(leftInput) && index === 0;
|
|
384
|
+
const noMaxBound = !Number.isFinite(rightInput) && isLast;
|
|
382
385
|
const onChangeLeft = useCallback(
|
|
383
386
|
val => {
|
|
384
387
|
if (editable && editColorMap) editColorMap(parseFloat(val), index - 1);
|
|
@@ -395,7 +398,7 @@ export const EditableColorRange: React.FC<EditableColorRangeProps> = ({
|
|
|
395
398
|
return (
|
|
396
399
|
<StyledRangeInput>
|
|
397
400
|
<ColorPaletteInput
|
|
398
|
-
value={noMinBound ? 'Less' :
|
|
401
|
+
value={noMinBound ? 'Less' : String(leftInput ?? '')}
|
|
399
402
|
id={`color-palette-input-${index}-left`}
|
|
400
403
|
width="50px"
|
|
401
404
|
textAlign="end"
|
|
@@ -404,7 +407,7 @@ export const EditableColorRange: React.FC<EditableColorRangeProps> = ({
|
|
|
404
407
|
/>
|
|
405
408
|
<Dash />
|
|
406
409
|
<ColorPaletteInput
|
|
407
|
-
value={noMaxBound ? 'More' :
|
|
410
|
+
value={noMaxBound ? 'More' : String(rightInput ?? '')}
|
|
408
411
|
id={`color-palette-input-${index}-right`}
|
|
409
412
|
width="50px"
|
|
410
413
|
textAlign="end"
|
|
@@ -468,7 +471,7 @@ export const CustomPaletteInput: React.FC<CustomPaletteInputProps> = ({
|
|
|
468
471
|
/>
|
|
469
472
|
</StyledColorHexInput>
|
|
470
473
|
) : null}
|
|
471
|
-
{isNumericColorBreaks(colorBreaks) ? (
|
|
474
|
+
{colorBreaks && index < colorBreaks.length && isNumericColorBreaks(colorBreaks) ? (
|
|
472
475
|
<EditableColorRange
|
|
473
476
|
item={colorBreaks[index]}
|
|
474
477
|
isLast={index === colorBreaks.length - 1}
|
|
@@ -719,6 +722,9 @@ export const CategoricalSelector: React.FC<CategoricalSelectorProps> = ({
|
|
|
719
722
|
listAnchor: 'list__item__anchor'
|
|
720
723
|
}}
|
|
721
724
|
options={allValues}
|
|
725
|
+
// add safe string casting for the Typeahead, so fuzzy search never receives non-strings, preventing the toLowerCase crash
|
|
726
|
+
displayOption={o => String(o ?? '')}
|
|
727
|
+
filterOption={(input, o) => String(o ?? '').includes(String(input ?? ''))}
|
|
722
728
|
placeholder={'Search'}
|
|
723
729
|
onOptionSelected={onOptionSelected}
|
|
724
730
|
customListComponent={ModifiedDropdownList}
|
|
@@ -336,7 +336,8 @@ function RasterTileLayerConfiguratorFactory(
|
|
|
336
336
|
|
|
337
337
|
const elevationUI = (
|
|
338
338
|
<>
|
|
339
|
-
{
|
|
339
|
+
{(stac.rasterServerSupportsElevation ??
|
|
340
|
+
getApplicationConfig().rasterServerSupportsElevation) &&
|
|
340
341
|
stac.rasterTileServerUrls?.length && (
|
|
341
342
|
<LayerConfigGroup
|
|
342
343
|
{...(layer.visConfigSettings.enableTerrain || {label: 'layer.color'})}
|
|
@@ -9,6 +9,7 @@ import {VectorTileLayer} from '@kepler.gl/layers';
|
|
|
9
9
|
import {KeplerTable as KeplerDataset} from '@kepler.gl/table';
|
|
10
10
|
|
|
11
11
|
import SourceDataSelectorFactory from '../common/source-data-selector';
|
|
12
|
+
import FieldSelectorFactory from '../../common/field-selector';
|
|
12
13
|
import ChannelByValueSelectorFactory from './channel-by-value-selector';
|
|
13
14
|
import LayerConfigGroupFactory, {ConfigGroupCollapsibleContent} from './layer-config-group';
|
|
14
15
|
import {LayerColorRangeSelectorFactory, LayerColorSelectorFactory} from './layer-color-selector';
|
|
@@ -37,7 +38,8 @@ VectorTileLayerConfiguratorFactory.deps = [
|
|
|
37
38
|
LayerConfigGroupFactory,
|
|
38
39
|
VisConfigSliderFactory,
|
|
39
40
|
VisConfigSwitchFactory,
|
|
40
|
-
SourceDataSelectorFactory
|
|
41
|
+
SourceDataSelectorFactory,
|
|
42
|
+
FieldSelectorFactory
|
|
41
43
|
];
|
|
42
44
|
|
|
43
45
|
function VectorTileLayerConfiguratorFactory(
|
|
@@ -46,7 +48,9 @@ function VectorTileLayerConfiguratorFactory(
|
|
|
46
48
|
LayerColorSelector: ReturnType<typeof LayerColorSelectorFactory>,
|
|
47
49
|
LayerConfigGroup: ReturnType<typeof LayerConfigGroupFactory>,
|
|
48
50
|
VisConfigSlider: ReturnType<typeof VisConfigSliderFactory>,
|
|
49
|
-
VisConfigSwitch: ReturnType<typeof VisConfigSwitchFactory
|
|
51
|
+
VisConfigSwitch: ReturnType<typeof VisConfigSwitchFactory>,
|
|
52
|
+
_SourceDataSelector: ReturnType<typeof SourceDataSelectorFactory>,
|
|
53
|
+
FieldSelector: ReturnType<typeof FieldSelectorFactory>
|
|
50
54
|
): React.FC<Props> {
|
|
51
55
|
const VectorTileLayerConfigurator = ({
|
|
52
56
|
layer,
|
|
@@ -190,6 +194,19 @@ function VectorTileLayerConfiguratorFactory(
|
|
|
190
194
|
<VisConfigSwitch {...layer.visConfigSettings.radiusUnits} {...visConfiguratorProps} />
|
|
191
195
|
</ConfigGroupCollapsibleContent>
|
|
192
196
|
</LayerConfigGroup>
|
|
197
|
+
|
|
198
|
+
{/* Unique ID Field */}
|
|
199
|
+
<LayerConfigGroup {...visConfiguratorProps} label="layer.uniqueIdField">
|
|
200
|
+
<FieldSelector
|
|
201
|
+
fields={layerChannelConfigProps.fields || []}
|
|
202
|
+
value={layer.config.uniqueIdField || null}
|
|
203
|
+
onSelect={(val: any) =>
|
|
204
|
+
layerConfiguratorProps.onChange?.({uniqueIdField: val?.name || null})
|
|
205
|
+
}
|
|
206
|
+
placeholder={'placeholder.selectField'}
|
|
207
|
+
erasable
|
|
208
|
+
/>
|
|
209
|
+
</LayerConfigGroup>
|
|
193
210
|
</StyledLayerConfigurator>
|
|
194
211
|
);
|
|
195
212
|
};
|