Skip to content

Commit

Permalink
Merge pull request #465 from adobe/idField
Browse files Browse the repository at this point in the history
idField
  • Loading branch information
Bryant-Curtis authored Nov 21, 2024
2 parents 31b3539 + 455cf0a commit 533d81d
Show file tree
Hide file tree
Showing 37 changed files with 236 additions and 169 deletions.
10 changes: 9 additions & 1 deletion src/Chart.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,13 @@ import { FC, forwardRef, useEffect, useMemo, useRef, useState } from 'react';

import { EmptyState } from '@components/EmptyState';
import { LoadingState } from '@components/LoadingState';
import { DEFAULT_BACKGROUND_COLOR, DEFAULT_COLOR_SCHEME, DEFAULT_LINE_TYPES, DEFAULT_LOCALE } from '@constants';
import {
DEFAULT_BACKGROUND_COLOR,
DEFAULT_COLOR_SCHEME,
DEFAULT_LINE_TYPES,
DEFAULT_LOCALE,
MARK_ID,
} from '@constants';
import useChartHeight from '@hooks/useChartHeight';
import useChartImperativeHandle from '@hooks/useChartImperativeHandle';
import useChartWidth from '@hooks/useChartWidth';
Expand Down Expand Up @@ -51,6 +57,7 @@ export const Chart = forwardRef<ChartHandle, ChartProps>(
height = 300,
hiddenSeries = [],
highlightedSeries,
idKey = MARK_ID,
lineTypes = DEFAULT_LINE_TYPES as LineType[],
lineWidths = ['M'],
loading,
Expand Down Expand Up @@ -124,6 +131,7 @@ export const Chart = forwardRef<ChartHandle, ChartProps>(
debug,
hiddenSeries,
highlightedSeries,
idKey,
lineTypes,
lineWidths,
locale,
Expand Down
9 changes: 5 additions & 4 deletions src/RscChart.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ import {
FILTERED_TABLE,
GROUP_DATA,
LEGEND_TOOLTIP_DELAY,
MARK_ID,
SELECTED_ITEM,
SELECTED_SERIES,
SERIES_ID,
Expand Down Expand Up @@ -98,6 +97,7 @@ export const RscChart = forwardRef<ChartHandle, RscChartProps>(
chartWidth,
UNSAFE_vegaSpec,
chartId,
idKey,
...props
},
forwardedRef
Expand Down Expand Up @@ -191,7 +191,7 @@ export const RscChart = forwardRef<ChartHandle, RscChartProps>(
const tooltip = tooltips.find((t) => t.name === value[COMPONENT_NAME]);
if (tooltip?.callback && !('index' in value)) {
if (controlledHoveredIdSignal) {
chartView.current?.signal(controlledHoveredIdSignal.name, value?.[MARK_ID] ?? null);
chartView.current?.signal(controlledHoveredIdSignal.name, value?.[idKey] ?? null);
}
if (controlledHoveredGroupSignal) {
const key = Object.keys(value).find((k) => k.endsWith('_highlightGroupId'));
Expand Down Expand Up @@ -221,11 +221,11 @@ export const RscChart = forwardRef<ChartHandle, RscChartProps>(
if (legendIsToggleable) {
signals.hiddenSeries = legendHiddenSeries;
}
signals[SELECTED_ITEM] = selectedData?.[MARK_ID] ?? null;
signals[SELECTED_ITEM] = selectedData?.[idKey] ?? null;
signals[SELECTED_SERIES] = selectedData?.[SERIES_ID] ?? null;

return signals;
}, [colorScheme, legendHiddenSeries, legendIsToggleable]);
}, [colorScheme, idKey, legendHiddenSeries, legendIsToggleable]);

return (
<>
Expand Down Expand Up @@ -272,6 +272,7 @@ export const RscChart = forwardRef<ChartHandle, RscChartProps>(
view.signal('hiddenSeries', legendHiddenSeries);
}
setSelectedSignals({
idKey,
selectedData: selectedData.current,
view,
});
Expand Down
5 changes: 3 additions & 2 deletions src/specBuilder/area/areaSpecBuilder.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ const defaultAreaProps: AreaSpecProps = {
colorScheme: DEFAULT_COLOR_SCHEME,
color: DEFAULT_COLOR,
dimension: DEFAULT_TIME_DIMENSION,
idKey: MARK_ID,
index: 0,
markType: 'area',
metric: DEFAULT_METRIC,
Expand Down Expand Up @@ -167,11 +168,11 @@ const defaultPointScale = {
describe('areaSpecBuilder', () => {
describe('addArea()', () => {
test('should add area', () => {
expect(addArea(startingSpec, {})).toStrictEqual(defaultSpec);
expect(addArea(startingSpec, { idKey: MARK_ID })).toStrictEqual(defaultSpec);
});

test('metricStart defined but valueEnd not defined, should default to value', () => {
expect(addArea(startingSpec, { metricStart: 'test' })).toStrictEqual(defaultSpec);
expect(addArea(startingSpec, { idKey: MARK_ID, metricStart: 'test' })).toStrictEqual(defaultSpec);
});
});

Expand Down
16 changes: 10 additions & 6 deletions src/specBuilder/area/areaSpecBuilder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ import {
DEFAULT_METRIC,
DEFAULT_TIME_DIMENSION,
FILTERED_TABLE,
MARK_ID,
SELECTED_ITEM,
SELECTED_SERIES,
} from '@constants';
Expand All @@ -44,7 +43,7 @@ import { addTimeTransform, getFilteredTableData, getTableData, getTransformSort
import { addContinuousDimensionScale, addFieldToFacetScaleDomain, addMetricScale } from '../scale/scaleSpecBuilder';
import { getAreaMark, getX } from './areaUtils';

export const addArea = produce<Spec, [AreaProps & { colorScheme?: ColorScheme; index?: number }]>(
export const addArea = produce<Spec, [AreaProps & { colorScheme?: ColorScheme; index?: number; idKey: string }]>(
(
spec,
{
Expand Down Expand Up @@ -123,7 +122,7 @@ export const addData = produce<Data[], [AreaSpecProps]>((data, props) => {

if (children.length) {
const areaHasPopover = hasPopover(children);
data.push(getAreaHighlightedData(name, areaHasPopover, isHighlightedByGroup(props)));
data.push(getAreaHighlightedData(name, props.idKey, areaHasPopover, isHighlightedByGroup(props)));
if (areaHasPopover) {
data.push({
name: `${name}_selectedDataSeries`,
Expand All @@ -140,12 +139,17 @@ export const addData = produce<Data[], [AreaSpecProps]>((data, props) => {
addTooltipData(data, props, false);
});

export const getAreaHighlightedData = (name: string, hasPopover: boolean, hasGroupId: boolean): SourceData => {
export const getAreaHighlightedData = (
name: string,
idKey: string,
hasPopover: boolean,
hasGroupId: boolean
): SourceData => {
const highlightedExpr = hasGroupId
? `${name}_controlledHoveredGroup === datum.${name}_highlightGroupId`
: `${name}_controlledHoveredId === datum.${MARK_ID}`;
: `${name}_controlledHoveredId === datum.${idKey}`;
const expr = hasPopover
? `${SELECTED_ITEM} && ${SELECTED_ITEM} === datum.${MARK_ID} || !${SELECTED_ITEM} && ${highlightedExpr}`
? `${SELECTED_ITEM} && ${SELECTED_ITEM} === datum.${idKey} || !${SELECTED_ITEM} && ${highlightedExpr}`
: highlightedExpr;
return {
name: `${name}_highlightedData`,
Expand Down
2 changes: 1 addition & 1 deletion src/specBuilder/bar/barSpecBuilder.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -233,7 +233,7 @@ const defaultSpec: Spec = {
describe('barSpecBuilder', () => {
describe('addBar()', () => {
test('no props', () => {
expect(addBar(startingSpec, {})).toStrictEqual(defaultSpec);
expect(addBar(startingSpec, { idKey: MARK_ID })).toStrictEqual(defaultSpec);
});
});

Expand Down
6 changes: 3 additions & 3 deletions src/specBuilder/bar/barSpecBuilder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ import { getDodgedMark } from './dodgedBarUtils';
import { getDodgedAndStackedBarMark, getStackedBarMarks } from './stackedBarUtils';
import { addTrellisScale, getTrellisGroupMark, isTrellised } from './trellisedBarUtils';

export const addBar = produce<Spec, [BarProps & { colorScheme?: ColorScheme; index?: number }]>(
export const addBar = produce<Spec, [BarProps & { colorScheme?: ColorScheme; index?: number; idKey: string }]>(
(
spec,
{
Expand Down Expand Up @@ -107,15 +107,15 @@ export const addBar = produce<Spec, [BarProps & { colorScheme?: ColorScheme; ind
);

export const addSignals = produce<Signal[], [BarSpecProps]>((signals, props) => {
const { children, name, paddingRatio, paddingOuter: barPaddingOuter } = props;
const { children, idKey, name, paddingRatio, paddingOuter: barPaddingOuter } = props;
// We use this value to calculate ReferenceLine positions.
const { paddingInner } = getBarPadding(paddingRatio, barPaddingOuter);
signals.push(getGenericValueSignal('paddingInner', paddingInner));

if (!children.length) {
return;
}
addHighlightedItemSignalEvents(signals, name, 1, getTooltipProps(children)?.excludeDataKeys);
addHighlightedItemSignalEvents(signals, name, idKey, 1, getTooltipProps(children)?.excludeDataKeys);
addTooltipSignals(signals, props);
setTrendlineSignals(signals, props);
});
Expand Down
2 changes: 2 additions & 0 deletions src/specBuilder/bar/barTestUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import {
DEFAULT_METRIC,
DEFAULT_SECONDARY_COLOR,
FILTERED_TABLE,
MARK_ID,
PADDING_RATIO,
STACK_ID,
TRELLIS_PADDING,
Expand All @@ -34,6 +35,7 @@ export const defaultBarProps: BarSpecProps = {
dimension: DEFAULT_CATEGORICAL_DIMENSION,
dimensionScaleType: 'band',
hasSquareCorners: false,
idKey: MARK_ID,
index: 0,
interactiveMarkName: 'bar0',
lineType: { value: 'solid' },
Expand Down
28 changes: 13 additions & 15 deletions src/specBuilder/bar/barUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,7 @@
* OF ANY KIND, either express or implied. See the License for the specific language
* governing permissions and limitations under the License.
*/
import {
CORNER_RADIUS,
DISCRETE_PADDING,
FILTERED_TABLE,
MARK_ID,
SELECTED_GROUP,
SELECTED_ITEM,
STACK_ID,
} from '@constants';
import { CORNER_RADIUS, DISCRETE_PADDING, FILTERED_TABLE, SELECTED_GROUP, SELECTED_ITEM, STACK_ID } from '@constants';
import { getPopovers } from '@specBuilder/chartPopover/chartPopoverUtils';
import {
getColorProductionRule,
Expand Down Expand Up @@ -247,15 +239,21 @@ export const getBarUpdateEncodings = (props: BarSpecProps): EncodeEntry => ({
strokeWidth: getStrokeWidth(props),
});

export const getStroke = ({ name, children, color, colorScheme }: BarSpecProps): ProductionRule<ColorValueRef> => {
export const getStroke = ({
name,
children,
color,
colorScheme,
idKey,
}: BarSpecProps): ProductionRule<ColorValueRef> => {
const defaultProductionRule = getColorProductionRule(color, colorScheme);
if (!hasPopover(children)) {
return [defaultProductionRule];
}

return [
{
test: `(${SELECTED_ITEM} && ${SELECTED_ITEM} === datum.${MARK_ID}) || (${SELECTED_GROUP} && ${SELECTED_GROUP} === datum.${name}_selectedGroupId)`,
test: `(${SELECTED_ITEM} && ${SELECTED_ITEM} === datum.${idKey}) || (${SELECTED_GROUP} && ${SELECTED_GROUP} === datum.${name}_selectedGroupId)`,
value: getColorValue('static-blue', colorScheme),
},
defaultProductionRule,
Expand Down Expand Up @@ -299,17 +297,17 @@ export const getDimensionSelectionRing = (props: BarSpecProps): RectMark => {
};
};

export const getStrokeDash = ({ children, lineType }: BarSpecProps): ProductionRule<ArrayValueRef> => {
export const getStrokeDash = ({ children, idKey, lineType }: BarSpecProps): ProductionRule<ArrayValueRef> => {
const defaultProductionRule = getStrokeDashProductionRule(lineType);
if (!hasPopover(children)) {
return [defaultProductionRule];
}

return [{ test: `${SELECTED_ITEM} && ${SELECTED_ITEM} === datum.${MARK_ID}`, value: [] }, defaultProductionRule];
return [{ test: `${SELECTED_ITEM} && ${SELECTED_ITEM} === datum.${idKey}`, value: [] }, defaultProductionRule];
};

export const getStrokeWidth = (props: BarSpecProps): ProductionRule<NumericValueRef> => {
const { lineWidth, name } = props;
const { idKey, lineWidth, name } = props;
const lineWidthValue = getLineWidthPixelsFromLineWidth(lineWidth);
const defaultProductionRule = { value: lineWidthValue };
const popovers = getPopovers(props);
Expand All @@ -323,7 +321,7 @@ export const getStrokeWidth = (props: BarSpecProps): ProductionRule<NumericValue

return [
{
test: `(${SELECTED_ITEM} && ${SELECTED_ITEM} === datum.${MARK_ID}) || (${SELECTED_GROUP} && ${SELECTED_GROUP} === datum.${name}_selectedGroupId)`,
test: `(${SELECTED_ITEM} && ${SELECTED_ITEM} === datum.${idKey}) || (${SELECTED_GROUP} && ${SELECTED_GROUP} === datum.${name}_selectedGroupId)`,
value: Math.max(lineWidthValue, 2),
},
defaultProductionRule,
Expand Down
5 changes: 3 additions & 2 deletions src/specBuilder/chartPopover/chartPopoverUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
* governing permissions and limitations under the License.
*/
import { ChartPopover } from '@components/ChartPopover';
import { FILTERED_TABLE, MARK_ID, SELECTED_GROUP, SERIES_ID } from '@constants';
import { FILTERED_TABLE, SELECTED_GROUP, SERIES_ID } from '@constants';
import { getFilteredTableData } from '@specBuilder/data/dataUtils';
import { Data, FormulaTransform, SourceData } from 'vega';

Expand All @@ -21,6 +21,7 @@ type PopoverParentProps = {
markType?: string;
name: string;
dimension: string;
idKey: string;
};

/**
Expand Down Expand Up @@ -73,7 +74,7 @@ export const addPopoverData = (data: Data[], markProps: PopoverParentProps, addH
} else if (Array.isArray(UNSAFE_highlightBy)) {
filteredTable.transform.push(getGroupIdTransform(UNSAFE_highlightBy, markName));
} else {
filteredTable.transform.push(getGroupIdTransform([MARK_ID], markName));
filteredTable.transform.push(getGroupIdTransform([markProps.idKey], markName));
}

if (addHighlightedData) {
Expand Down
25 changes: 15 additions & 10 deletions src/specBuilder/chartSpecBuilder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import {
LINEAR_COLOR_SCALE,
LINE_TYPE_SCALE,
LINE_WIDTH_SCALE,
MARK_ID,
OPACITY_SCALE,
SELECTED_GROUP,
SELECTED_ITEM,
Expand Down Expand Up @@ -89,15 +90,16 @@ export function buildSpec({
backgroundColor = DEFAULT_BACKGROUND_COLOR,
children,
colors = 'categorical12',
colorScheme = DEFAULT_COLOR_SCHEME,
description,
hiddenSeries,
highlightedSeries,
idKey = MARK_ID,
lineTypes = DEFAULT_LINE_TYPES as LineType[],
lineWidths = ['M'],
opacities,
symbolShapes = ['rounded-square'],
symbolSizes = ['XS', 'XL'],
colorScheme = DEFAULT_COLOR_SCHEME,
title,
}: SanitizedSpecProps) {
let spec = initializeSpec(null, { backgroundColor, colorScheme, description, title });
Expand All @@ -124,8 +126,9 @@ export function buildSpec({
buildOrder.set(Axis, 2);
buildOrder.set(Title, 3);

let { areaCount, axisCount, barCount, donutCount, legendCount, lineCount, scatterCount } =
let { areaCount, axisCount, barCount, comboCount, donutCount, legendCount, lineCount, scatterCount } =
initializeComponentCounts();
const specProps = { colorScheme, idKey };
spec = [...children]
.sort((a, b) => buildOrder.get(a.type) - buildOrder.get(b.type))
.reduce((acc: Spec, cur) => {
Expand All @@ -141,39 +144,40 @@ export function buildSpec({
switch (cur.type.displayName) {
case Area.displayName:
areaCount++;
return addArea(acc, { ...(cur as AreaElement).props, colorScheme, index: areaCount });
return addArea(acc, { ...(cur as AreaElement).props, ...specProps, index: areaCount });
case Axis.displayName:
axisCount++;
return addAxis(acc, { ...(cur as AxisElement).props, colorScheme, index: axisCount });
return addAxis(acc, { ...(cur as AxisElement).props, ...specProps, index: axisCount });
case Bar.displayName:
barCount++;
return addBar(acc, { ...(cur as BarElement).props, colorScheme, index: barCount });
return addBar(acc, { ...(cur as BarElement).props, ...specProps, index: barCount });
case Donut.displayName:
donutCount++;
return addDonut(acc, { ...(cur as DonutElement).props, colorScheme, index: donutCount });
return addDonut(acc, { ...(cur as DonutElement).props, ...specProps, index: donutCount });
case Legend.displayName:
legendCount++;
return addLegend(acc, {
...(cur as LegendElement).props,
colorScheme,
...specProps,
index: legendCount,
hiddenSeries,
highlightedSeries,
});
case Line.displayName:
lineCount++;
return addLine(acc, { ...(cur as LineElement).props, colorScheme, index: lineCount });
return addLine(acc, { ...(cur as LineElement).props, ...specProps, index: lineCount });
case Scatter.displayName:
scatterCount++;
return addScatter(acc, { ...(cur as ScatterElement).props, colorScheme, index: scatterCount });
return addScatter(acc, { ...(cur as ScatterElement).props, ...specProps, index: scatterCount });
case Title.displayName:
// No title count. There can only be one title.
return addTitle(acc, { ...(cur as TitleElement).props });
case BigNumber.displayName:
// Do nothing and do not throw an error
return acc;
case Combo.displayName:
return addCombo(acc, { ...(cur as ComboElement).props });
comboCount++;
return addCombo(acc, { ...(cur as ComboElement).props, ...specProps, index: comboCount });
default:
console.error(`Invalid component type: ${cur.type.displayName} is not a supported <Chart> child`);
return acc;
Expand Down Expand Up @@ -206,6 +210,7 @@ const initializeComponentCounts = () => {
areaCount: -1,
axisCount: -1,
barCount: -1,
comboCount: -1,
donutCount: -1,
legendCount: -1,
lineCount: -1,
Expand Down
Loading

0 comments on commit 533d81d

Please sign in to comment.