Skip to content

Commit 476ee89

Browse files
committed
merge master
Signed-off-by: Ihor Dykhta <[email protected]>
2 parents e2278aa + c5d42dd commit 476ee89

File tree

25 files changed

+714
-195
lines changed

25 files changed

+714
-195
lines changed

bindings/kepler.gl-jupyter/js/yarn.lock

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8382,8 +8382,8 @@ __metadata:
83828382
linkType: hard
83838383

83848384
"elliptic@npm:^6.5.3, elliptic@npm:^6.5.5":
8385-
version: 6.5.7
8386-
resolution: "elliptic@npm:6.5.7"
8385+
version: 6.6.1
8386+
resolution: "elliptic@npm:6.6.1"
83878387
dependencies:
83888388
bn.js: "npm:^4.11.9"
83898389
brorand: "npm:^1.1.0"
@@ -8392,7 +8392,7 @@ __metadata:
83928392
inherits: "npm:^2.0.4"
83938393
minimalistic-assert: "npm:^1.0.1"
83948394
minimalistic-crypto-utils: "npm:^1.0.1"
8395-
checksum: 10c0/799959b6c54ea3564e8961f35abdf8c77e37617f3051614b05ab1fb6a04ddb65bd1caa75ed1bae375b15dda312a0f79fed26ebe76ecf05c5a7af244152a601b8
8395+
checksum: 10c0/8b24ef782eec8b472053793ea1e91ae6bee41afffdfcb78a81c0a53b191e715cbe1292aa07165958a9bbe675bd0955142560b1a007ffce7d6c765bcaf951a867
83968396
languageName: node
83978397
linkType: hard
83988398

src/components/src/common/color-legend.tsx

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ import {Reset} from './icons';
1616
import {InlineInput} from './styled-components';
1717

1818
const ROW_H = 15;
19-
const GAP = 4;
19+
const GAP = 2;
2020
const RECT_W = 20;
2121

2222
const stopClickPropagation = e => e.stopPropagation();
@@ -224,15 +224,15 @@ function overrideByCustomLegend({colorLegends, currentLegends}: OverrideByCustom
224224
}
225225

226226
export function useLayerColorLegends(
227-
layer,
228-
scaleType,
229-
domain,
230-
range,
231-
isFixed,
232-
fieldType,
233-
labelFormat,
234-
mapState
235-
) {
227+
layer: ColorLegendProps['layer'],
228+
scaleType: ColorLegendProps['scaleType'],
229+
domain: ColorLegendProps['domain'],
230+
range: ColorLegendProps['range'],
231+
isFixed: ColorLegendProps['isFixed'],
232+
fieldType: ColorLegendProps['fieldType'],
233+
labelFormat: ColorLegendProps['labelFormat'],
234+
mapState: ColorLegendProps['mapState']
235+
): Legend[] {
236236
const scale = useMemo(
237237
() => getLayerColorScale({range, domain, scaleType, isFixed, layer}),
238238
[range, domain, scaleType, isFixed, layer]
@@ -260,7 +260,7 @@ export function useLayerColorLegends(
260260
return LegendsWithCustomLegends;
261261
}
262262

263-
type ColorLegendProps = {
263+
export type ColorLegendProps = {
264264
layer: Layer;
265265
scaleType: string;
266266
domain: number[] | string[];
@@ -274,6 +274,12 @@ type ColorLegendProps = {
274274
onUpdateColorLegend?: (colorLegends: {[key: HexColor]: string}) => void;
275275
};
276276

277+
export type Legend = {
278+
data: string;
279+
label: string;
280+
override?: boolean;
281+
};
282+
277283
ColorLegendFactory.deps = [LegendRowFactory];
278284
function ColorLegendFactory(LegendRow: ReturnType<typeof LegendRowFactory>) {
279285
const ColorLegend: React.FC<ColorLegendProps> = ({

src/components/src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -369,6 +369,7 @@ export type {
369369
LayerTypeListItemType
370370
} from './side-panel/layer-panel/layer-type-list-item';
371371
export type {SingleColorPaletteProps} from './side-panel/layer-panel/single-color-palette';
372+
export type {SupportedColumnModeConfig} from './side-panel/layer-panel/layer-column-mode-config';
372373
export type {MapManagerProps} from './side-panel/map-manager';
373374
export type {LayerGroupColorPickerProps} from './side-panel/map-style-panel/map-layer-group-color-picker';
374375
export type {LayerGroupSelectorProps} from './side-panel/map-style-panel/map-layer-selector';

src/components/src/map/layer-hover-info.tsx

Lines changed: 57 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,22 @@
33

44
import React, {useMemo} from 'react';
55
import styled from 'styled-components';
6-
import {TooltipField} from '@kepler.gl/types';
6+
import {CompareType, Field, Merge, TooltipField} from '@kepler.gl/types';
77
import {CenterFlexbox} from '../common/styled-components';
88
import {Layers} from '../common/icons';
99
import PropTypes from 'prop-types';
1010
import {notNullorUndefined} from '@kepler.gl/common-utils';
11+
import {DataRow} from '@kepler.gl/utils';
1112
import {Layer} from '@kepler.gl/layers';
1213
import {
1314
AggregationLayerHoverData,
15+
LayerHoverProp,
1416
getTooltipDisplayDeltaValue,
1517
getTooltipDisplayValue
1618
} from '@kepler.gl/reducers';
1719
import {useIntl} from 'react-intl';
20+
import {VisState} from '@kepler.gl/schemas';
21+
import {capitalizeFirstLetter} from '@kepler.gl/utils';
1822

1923
export const StyledLayerName = styled(CenterFlexbox)`
2024
color: ${props => props.theme.textColorHl};
@@ -98,36 +102,55 @@ const Row: React.FC<RowProps> = ({name, value, deltaValue, url}) => {
98102
);
99103
};
100104

101-
const EntryInfo = ({fieldsToShow, fields, data, primaryData, compareType}) => (
105+
export type EntryInfoProps = Merge<LayerHoverProp, {fieldsToShow: TooltipField[]}>;
106+
107+
const EntryInfo: React.FC<EntryInfoProps> = ({fieldsToShow, ...props}) => (
102108
<tbody>
103109
{fieldsToShow.map(item => (
104-
<EntryInfoRow
105-
key={item.name}
106-
item={item}
107-
fields={fields}
108-
data={data}
109-
primaryData={primaryData}
110-
compareType={compareType}
111-
/>
110+
<EntryInfoRow key={item.name} item={item} {...props} />
112111
))}
113112
</tbody>
114113
);
115114

116-
const EntryInfoRow = ({item, fields, data, primaryData, compareType}) => {
115+
export type EntryInfoRowProps = {
116+
data: LayerHoverProp['data'];
117+
fields: Field[];
118+
layer: Layer;
119+
primaryData?: LayerHoverProp['primaryData'];
120+
compareType?: CompareType;
121+
currentTime?: VisState['animationConfig']['currentTime'];
122+
item: TooltipField;
123+
};
124+
125+
const EntryInfoRow: React.FC<EntryInfoRowProps> = ({
126+
layer,
127+
item,
128+
fields,
129+
data,
130+
primaryData,
131+
compareType,
132+
currentTime
133+
}) => {
117134
const fieldIdx = fields.findIndex(f => f.name === item.name);
118135
if (fieldIdx < 0) {
119136
return null;
120137
}
121138
const field = fields[fieldIdx];
122-
const value = data.valueAt(fieldIdx);
139+
const fieldValueAccessor = layer.accessVSFieldValue(field, currentTime);
140+
const value = fieldValueAccessor(field, data instanceof DataRow ? {index: data._rowIndex} : data);
141+
const primaryValue = primaryData
142+
? fieldValueAccessor(
143+
field,
144+
primaryData instanceof DataRow ? {index: primaryData._rowIndex} : primaryData
145+
)
146+
: null;
123147
const displayValue = getTooltipDisplayValue({item, field, value});
124148

125149
const displayDeltaValue = primaryData
126150
? getTooltipDisplayDeltaValue({
127151
field,
128-
data,
129-
fieldIdx,
130-
primaryData,
152+
value,
153+
primaryValue,
131154
compareType
132155
})
133156
: null;
@@ -169,6 +192,22 @@ const CellInfo = ({
169192
return null;
170193
}, [fieldsToShow, sizeField, layer, data.elevationValue]);
171194

195+
const aggregatedData = useMemo(() => {
196+
if (data.aggregatedData && fieldsToShow) {
197+
return fieldsToShow.reduce((acc, field) => {
198+
const dataForField = data.aggregatedData?.[field.name];
199+
if (dataForField?.measure && field.name !== colorField?.name) {
200+
acc.push({
201+
name: `${capitalizeFirstLetter(dataForField.measure)} of ${field.name}`,
202+
value: dataForField.value
203+
});
204+
}
205+
return acc;
206+
}, [] as {name: string; value?: string}[]);
207+
}
208+
return [];
209+
}, [data.aggregatedData, fieldsToShow, colorField?.name]);
210+
172211
const colorMeasure = layer.getVisualChannelDescription('color').measure;
173212
const sizeMeasure = layer.getVisualChannelDescription('size').measure;
174213
return (
@@ -180,6 +219,9 @@ const CellInfo = ({
180219
{sizeField && layer.visualChannels.size && sizeMeasure ? (
181220
<Row name={sizeMeasure} key="size" value={elevationValue || 'N/A'} />
182221
) : null}
222+
{aggregatedData.map((dataForField, idx) => (
223+
<Row name={dataForField.name} key={`data_${idx}`} value={dataForField.value || 'N/A'} />
224+
))}
183225
</tbody>
184226
);
185227
};

src/components/src/map/map-legend.tsx

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,7 @@ export type LayerColorLegendProps = {
118118
onLayerVisConfigChange?: (oldLayer: Layer, newVisConfig: Partial<LayerVisConfig>) => void;
119119
layer: Layer;
120120
disableEdit?: boolean;
121+
mapState?: MapState;
121122
};
122123

123124
LayerColorLegendFactory.deps = [ColorLegendFactory, SingleColorLegendFactory];
@@ -131,11 +132,14 @@ export function LayerColorLegendFactory(
131132
layer,
132133
colorChannel,
133134
disableEdit,
134-
onLayerVisConfigChange
135+
onLayerVisConfigChange,
136+
mapState
135137
}) => {
136138
const enableColorBy = description.measure;
137-
const {scale, field, domain, range, property} = colorChannel;
139+
const {scale, field, domain, range, property, fixed} = colorChannel;
138140
const [colorScale, colorField, colorDomain] = [scale, field, domain].map(k => config[k]);
141+
const isFixed = fixed && config.visConfig[fixed];
142+
139143
const colorRange = config.visConfig[range];
140144
const onUpdateColorLegend = useCallback(
141145
colorLegends => {
@@ -166,6 +170,8 @@ export function LayerColorLegendFactory(
166170
range={colorRange}
167171
onUpdateColorLegend={onUpdateColorLegend}
168172
disableEdit={disableEdit}
173+
isFixed={isFixed}
174+
mapState={mapState}
169175
/>
170176
) : (
171177
<SingleColorLegend
@@ -304,6 +310,7 @@ export function LayerLegendContentFactory(
304310
description={layer.getVisualChannelDescription(colorChannel.key)}
305311
layer={layer}
306312
disableEdit={disableEdit}
313+
mapState={mapState}
307314
onLayerVisConfigChange={onLayerVisConfigChange}
308315
/>
309316
))}

src/components/src/side-panel/layer-panel/layer-column-mode-config.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ const ConfigPanesContainer = styled.div`
7979
interface FieldOption extends MinimalField {
8080
fieldIdx: number;
8181
}
82-
type ColumnModeConfig = {
82+
export type SupportedColumnModeConfig = {
8383
key: string;
8484
label: string;
8585
columns: LayerColumns;
@@ -93,8 +93,8 @@ export type ColumnModeConfigProps = {
9393
mode: {key: string; label: string; columns: any},
9494
selected: boolean
9595
) => JSX.Element;
96-
selectColumnMode: (mode: ColumnModeConfig) => void;
97-
getHelpHandler?: (mode: ColumnModeConfig) => (() => void) | null;
96+
selectColumnMode: (mode: SupportedColumnModeConfig) => void;
97+
getHelpHandler?: (mode: SupportedColumnModeConfig) => (() => void) | null;
9898
};
9999

100100
ColumnModeConfigFactory.deps = [PanelHeaderActionFactory];

src/layers/src/aggregation-layer.ts

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,15 @@ import Layer, {
1010
VisualChannelDescription,
1111
VisualChannels
1212
} from './base-layer';
13-
import {hexToRgb, aggregate} from '@kepler.gl/utils';
13+
import {hexToRgb, aggregate, DataContainerInterface} from '@kepler.gl/utils';
1414
import {
1515
HIGHLIGH_COLOR_3D,
1616
CHANNEL_SCALES,
1717
FIELD_OPTS,
1818
DEFAULT_AGGREGATION,
1919
ColorRange
2020
} from '@kepler.gl/constants';
21-
import {Merge, LayerColumn} from '@kepler.gl/types';
21+
import {Field, LayerColumn, Merge} from '@kepler.gl/types';
2222
import {KeplerTable, Datasets} from '@kepler.gl/table';
2323

2424
type AggregationLayerColumns = {
@@ -171,9 +171,22 @@ export default class AggregationLayer extends Layer {
171171
};
172172
}
173173

174-
getHoverData(object) {
174+
getHoverData(object: any, dataContainer: DataContainerInterface, fields: Field[]): any {
175+
if (!object) return object;
176+
const measure = this.config.visConfig.colorAggregation;
177+
// aggregate all fields for the hovered group
178+
const aggregatedData = fields.reduce((accu, field) => {
179+
accu[field.name] = {
180+
measure,
181+
value: aggregate(object.points, measure, (d: {index: number}) => {
182+
return dataContainer.valueAt(d.index, field.fieldIdx);
183+
})
184+
};
185+
return accu;
186+
}, {});
187+
175188
// return aggregated object
176-
return object;
189+
return {aggregatedData, ...object};
177190
}
178191

179192
getFilteredItemCount() {

src/layers/src/arc-layer/arc-layer.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// Copyright contributors to the kepler.gl project
33

44
import * as arrow from 'apache-arrow';
5+
import {h3ToGeo} from 'h3-js';
56

67
import Layer, {
78
LayerBaseConfig,
@@ -14,7 +15,6 @@ import {BrushingExtension} from '@deck.gl/extensions';
1415
import {GeoArrowArcLayer} from '@kepler.gl/deckgl-arrow-layers';
1516
import {FilterArrowExtension} from '@kepler.gl/deckgl-layers';
1617
import {ArcLayer as DeckArcLayer} from '@deck.gl/layers';
17-
import {h3ToGeo} from 'h3-js';
1818

1919
import {hexToRgb, DataContainerInterface, ArrowDataContainer} from '@kepler.gl/utils';
2020
import ArcLayerIcon from './arc-layer-icon';

0 commit comments

Comments
 (0)