Skip to content

Capstone/venn spec builder & react component #576

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 18 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .eslintrc.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ module.exports = {
message: 'Please use relative path import for types instead (ex. ../types/locales).',
},
],
'no-duplicate-imports': 'error',
'header/header': [
2,
'block',
Expand Down
9 changes: 9 additions & 0 deletions packages/constants/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,15 @@ export const DONUT_SUMMARY_FONT_SIZE_RATIO = 0.35;
/** Min inner radius to display the summary metric. If the inner radius is less than this, the summary metric is hidden. */
export const DONUT_SUMMARY_MIN_RADIUS = 45;

/** Default delimiter for set ids */
export const SET_ID_DELIMITER = '∩';

export const DEFAULT_VENN_COLOR = 'sets';
/** default key in data for the metric in the venn diagram */
export const DEFAULT_VENN_METRIC = 'size';
/** default key in data for the label inside the venn*/
export const DEFAULT_VENN_LABEL = 'label';

// ratio that each opacity is divded by when hovering or highlighting from legend
export const HIGHLIGHT_CONTRAST_RATIO = 5;

Expand Down
4 changes: 2 additions & 2 deletions packages/react-spectrum-charts/src/Chart.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ import {
MARK_ID,
} from '@spectrum-charts/constants';
import { getColorValue } from '@spectrum-charts/themes';
import { ChartHandle, LineType, LineWidth } from '@spectrum-charts/vega-spec-builder';
import { ChartData, ChartHandle, LineType, LineWidth } from '@spectrum-charts/vega-spec-builder';

import './Chart.css';
import { RscChart } from './RscChart';
Expand All @@ -38,7 +38,7 @@ import useChartImperativeHandle from './hooks/useChartImperativeHandle';
import useChartWidth from './hooks/useChartWidth';
import { useResizeObserver } from './hooks/useResizeObserver';
import { BigNumberInternal } from './rc/components/BigNumber/BigNumber';
import { ChartData, ChartProps, RscChartProps } from './types';
import { ChartProps, RscChartProps } from './types';
import { getBigNumberElementsFromChildren, toArray } from './utils';

interface PlaceholderContentProps {
Expand Down
2 changes: 2 additions & 0 deletions packages/react-spectrum-charts/src/RscChart.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,8 @@ export const RscChart = forwardRef<ChartHandle, RscChartProps>((props, forwarded
backgroundColor,
children: sanitizedChildren,
colors,
chartWidth,
chartHeight,
data,
description,
idKey,
Expand Down
3 changes: 2 additions & 1 deletion packages/react-spectrum-charts/src/VegaChart.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,12 @@ import embed from 'vega-embed';
import { Options as TooltipOptions } from 'vega-tooltip';

import { TABLE } from '@spectrum-charts/constants';
import { ChartData } from '@spectrum-charts/vega-spec-builder';

import { expressionFunctions, formatLocaleCurrency, formatTimeDurationLabels } from './expressionFunctions';
import { useDebugSpec } from './hooks/useDebugSpec';
import { extractValues, isVegaData } from './hooks/useSpec';
import { ChartData, ChartProps } from './types';
import { ChartProps } from './types';
import { getLocale } from './utils/locale';

export interface VegaChartProps {
Expand Down
31 changes: 31 additions & 0 deletions packages/react-spectrum-charts/src/alpha/components/Venn/Venn.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/*
* Copyright 2025 Adobe. All rights reserved.
* This file is licensed to you under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. You may obtain a copy
* of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under
* the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
* OF ANY KIND, either express or implied. See the License for the specific language
* governing permissions and limitations under the License.
*/

/* eslint-disable @typescript-eslint/no-unused-vars */
import { FC } from 'react';

import { DEFAULT_VENN_COLOR, DEFAULT_VENN_LABEL, DEFAULT_VENN_METRIC } from '@spectrum-charts/constants';

import { VennProps } from '../../../types';

const Venn: FC<VennProps> = ({
orientation = '0deg',
metric = DEFAULT_VENN_METRIC,
label = DEFAULT_VENN_LABEL,
color = DEFAULT_VENN_COLOR,
}) => {
return null;
};

Venn.displayName = 'Venn';

export { Venn };
13 changes: 13 additions & 0 deletions packages/react-spectrum-charts/src/alpha/components/Venn/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
/*
* Copyright 2025 Adobe. All rights reserved.
* This file is licensed to you under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. You may obtain a copy
* of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under
* the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
* OF ANY KIND, either express or implied. See the License for the specific language
* governing permissions and limitations under the License.
*/

export * from './Venn';
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,4 @@

export * from './Bullet';
export * from './Combo';
export * from './Venn';
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,3 @@
* OF ANY KIND, either express or implied. See the License for the specific language
* governing permissions and limitations under the License.
*/

58 changes: 52 additions & 6 deletions packages/react-spectrum-charts/src/hooks/useSpec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,22 @@
* OF ANY KIND, either express or implied. See the License for the specific language
* governing permissions and limitations under the License.
*/
import { useMemo } from 'react';
import { useEffect, useMemo, useRef } from 'react';

import { Data, Spec, ValuesData } from 'vega';

import { getColorValue } from '@spectrum-charts/themes';
import { ChartSpecOptions, baseData, buildSpec } from '@spectrum-charts/vega-spec-builder';
import { ChartData, ChartSpecOptions, baseData, buildSpec } from '@spectrum-charts/vega-spec-builder';

import { Venn } from '../alpha';
import { rscPropsToSpecBuilderOptions } from '../rscToSbAdapter';
import { ChartData, SanitizedSpecProps } from '../types';
import { SanitizedSpecProps } from '../types';
import { chartHasChild } from '../utils';

export default function useSpec({
backgroundColor,
chartHeight,
chartWidth,
children,
colors,
colorScheme,
Expand All @@ -38,7 +42,38 @@ export default function useSpec({
title,
UNSAFE_vegaSpec,
}: SanitizedSpecProps): Spec {
const prevSpec = useRef<Spec | null>(null);
const hasVenn = useMemo(() => chartHasChild({ children, displayName: Venn.displayName as string }), [children]);

// invalidate cache if changes to props other than width, height change
useEffect(() => {
prevSpec.current = null
}, [
UNSAFE_vegaSpec,
backgroundColor,
children,
colors,
colorScheme,
description,
hiddenSeries,
highlightedItem,
highlightedSeries,
idKey,
lineTypes,
lineWidths,
opacities,
symbolShapes,
symbolSizes,
title,
data,
]);

return useMemo(() => {
// returned cached spec if there is a cached spec and if venn is not a child element
if (!hasVenn && prevSpec.current !== null) {
return prevSpec.current;
}

// They already supplied a spec, fill it in with defaults
if (UNSAFE_vegaSpec) {
const vegaSpecWithDefaults = initializeSpec(UNSAFE_vegaSpec, {
Expand All @@ -50,15 +85,20 @@ export default function useSpec({
});

// copy the spec so we don't mutate the original
return JSON.parse(JSON.stringify(vegaSpecWithDefaults));
const spec = JSON.parse(JSON.stringify(vegaSpecWithDefaults));
prevSpec.current = spec;
return spec;
}

// or we need to build their spec
const chartOptions = rscPropsToSpecBuilderOptions({
backgroundColor,
chartHeight,
chartWidth,
children,
colors,
colorScheme,
colors,
data,
description,
hiddenSeries,
highlightedItem,
Expand All @@ -73,7 +113,10 @@ export default function useSpec({
});

// stringify-parse so that all immer stuff gets cleared out
return JSON.parse(JSON.stringify(buildSpec(chartOptions)));
const spec = JSON.parse(JSON.stringify(buildSpec(chartOptions)));
prevSpec.current = spec;

return spec;
}, [
UNSAFE_vegaSpec,
backgroundColor,
Expand All @@ -92,6 +135,9 @@ export default function useSpec({
symbolSizes,
title,
data,
chartHeight,
chartWidth,
hasVenn,
]);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,11 @@
import { CSSProperties, FC, cloneElement } from 'react';

import { Flex, FlexProps, IconProps } from '@adobe/react-spectrum';
import { BigNumberMethod, Orientation } from '@spectrum-charts/vega-spec-builder';
import { BigNumberMethod, ChartData, Orientation } from '@spectrum-charts/vega-spec-builder';

import { RscChart } from '../../../RscChart';
import { Line } from '../../../components';
import { BigNumberProps, ChartData, LineProps, RscChartProps } from '../../../types';
import { BigNumberProps, LineProps, RscChartProps } from '../../../types';
import { sanitizeBigNumberChildren } from '../../../utils';
import { getLocale } from '../../../utils/locale';
import './BigNumber.css';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,4 @@
* OF ANY KIND, either express or implied. See the License for the specific language
* governing permissions and limitations under the License.
*/
export * from "./SegmentLabel";
export * from './SegmentLabel';
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ import {
TrendlineOptions,
} from '@spectrum-charts/vega-spec-builder';

import { Bullet, Combo } from '../alpha';
import { Bullet, Combo, Venn } from '../alpha';
import { Annotation } from '../components/Annotation';
import { Area } from '../components/Area';
import { Axis } from '../components/Axis';
Expand Down Expand Up @@ -66,6 +66,7 @@ import {
TitleProps,
TrendlineAnnotationProps,
TrendlineProps,
VennProps,
} from '../types';
import { sanitizeChildren } from '../utils';
import { getAreaOptions } from './areaAdapter';
Expand All @@ -79,6 +80,7 @@ import { getLegendOptions } from './legendAdapter';
import { getLineOptions } from './lineAdapter';
import { getScatterOptions } from './scatterAdapter';
import { getTrendlineOptions } from './trendlineAdapter';
import { getVennOptions } from './vennAdapter';

export const childrenToOptions = (
children: React.ReactNode
Expand Down Expand Up @@ -208,6 +210,10 @@ export const childrenToOptions = (
trendlineAnnotations.push(child.props as TrendlineAnnotationProps);
break;

case Venn.displayName:
marks.push(getVennOptions(child.props as VennProps));
break;

default:
console.error('Invalid component type: ', child.type.displayName);
}
Expand Down
25 changes: 25 additions & 0 deletions packages/react-spectrum-charts/src/rscToSbAdapter/vennAdapter.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/*
* Copyright 2025 Adobe. All rights reserved.
* This file is licensed to you under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. You may obtain a copy
* of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under
* the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
* OF ANY KIND, either express or implied. See the License for the specific language
* governing permissions and limitations under the License.
*/
import { VennOptions } from '@spectrum-charts/vega-spec-builder';

import { VennProps } from '../types';
import { childrenToOptions } from './childrenAdapter';

export const getVennOptions = ({ children, ...vennProps }: VennProps): VennOptions => {
const { chartPopovers, chartTooltips } = childrenToOptions(children);
return {
...vennProps,
chartPopovers,
chartTooltips,
markType: 'venn',
};
};
12 changes: 10 additions & 2 deletions packages/react-spectrum-charts/src/stories/ChartExamples.story.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,15 @@ import GraphPathing from '@spectrum-icons/workflow/GraphPathing';
import UsersAdd from '@spectrum-icons/workflow/UsersAdd';
import ViewDetail from '@spectrum-icons/workflow/ViewDetail';

import { Colors, Datum, LegendDescription, LegendLabel, SpectrumColor, SubLabel } from '../../../vega-spec-builder';
import {
ChartData,
Colors,
Datum,
LegendDescription,
LegendLabel,
SpectrumColor,
SubLabel,
} from '../../../vega-spec-builder';
import { Annotation } from '../components/Annotation';
import { ReferenceLine } from '../components/ReferenceLine';
import useChartProps from '../hooks/useChartProps';
Expand All @@ -40,7 +48,7 @@ import {
categorical16,
} from '../index';
import { bindWithProps } from '../test-utils';
import { ChartData, ChartProps } from '../types';
import { ChartProps } from '../types';
import {
funnelConversionData,
funnelConversionTimeComparisonData,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -355,4 +355,4 @@ export const topEventsFeatureMatrixData = [
isTopItem: true,
},
...multipleSegmentFeatureMatrixData.map((d) => ({ ...d, isSegmentData: true })),
];
];
Original file line number Diff line number Diff line change
Expand Up @@ -142,12 +142,4 @@ OnClick.args = {
color: 'operatingSystem',
};

export {
Color,
DodgedStacked,
DodgedStackedWithLabels,
LineType,
Opacity,
Popover,
OnClick,
};
export { Color, DodgedStacked, DodgedStackedWithLabels, LineType, Opacity, Popover, OnClick };
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ import { Chart } from '../../../Chart';
import { Line } from '../../../components';
import { BigNumber } from '../../../rc';
import { getBigNumberChartDimensions, getBigNumberSize, getFontSize } from '../../../rc/components/BigNumber/BigNumber';
import { simpleSparklineData } from '../../../stories/data/data';
import { simpleSparklineData as data } from '../../../stories/data/data';
import { findAllMarksByGroupName, findChart, render, screen } from '../../../test-utils';
import {
Expand Down Expand Up @@ -107,7 +106,7 @@ describe('BigNumber', () => {
describe('Chart with BigNumber children', () => {
test('Chart with BigNumber and Line as children should only display BigNumber', async () => {
render(
<Chart data={simpleSparklineData}>
<Chart data={data}>
<BigNumber
dataKey="y"
orientation="horizontal"
Expand Down
Loading