Skip to content

Commit

Permalink
Rework LineChartPredictive to use in chart LineSeries
Browse files Browse the repository at this point in the history
  • Loading branch information
envex committed Jan 12, 2024
1 parent cdbf157 commit 23c02cc
Show file tree
Hide file tree
Showing 25 changed files with 343 additions and 146 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -42,13 +42,15 @@ export function LineSeries({
activeLineIndex = -1,
data,
hiddenIndexes = [],
index = 0,
index: lineSeriesIndex = 0,
svgDimensions,
theme,
type = 'default',
xScale,
yScale,
}: LineSeriesProps) {
const index = data?.metadata?.relatedIndex ?? lineSeriesIndex;

const {
// eslint-disable-next-line id-length
components: {Defs, Mask, G, Rect, Path},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ export function ComboLineChart({

const dataWithDefaults = getLineChartDataWithDefaults(data.series, colors);

const {reversedSeries, longestSeriesIndex} = useFormatData(dataWithDefaults);
const {longestSeriesIndex} = useFormatData(dataWithDefaults);

return (
<Fragment>
Expand All @@ -60,10 +60,10 @@ export function ComboLineChart({
})}
<PointsAndCrosshair
activeIndex={activeIndex}
data={dataWithDefaults}
drawableHeight={drawableHeight}
emptyState={false}
longestSeriesIndex={longestSeriesIndex}
reversedSeries={reversedSeries}
theme={theme}
tooltipId="none"
xScale={xScale}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ export function randomNumber(min: number, max: number) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}

function generateDayRange(numDays: number) {
export function generateDayRange(numDays: number) {
const currentDate = new Date('April 1, 2020');
const dayRange: string[] = [];

Expand Down
17 changes: 6 additions & 11 deletions packages/polaris-viz/src/components/LineChart/Chart.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -152,8 +152,7 @@ export function Chart({
verticalOverflow: selectedTheme.grid.verticalOverflow,
});

const {reversedSeries, longestSeriesLength, longestSeriesIndex} =
useFormatData(data);
const {longestSeriesLength, longestSeriesIndex} = useFormatData(data);

const {
drawableWidth,
Expand Down Expand Up @@ -208,11 +207,7 @@ export function Chart({
if (eventType === 'mouse') {
const point = eventPointNative(event!);

if (
point == null ||
xScale == null ||
reversedSeries[longestSeriesIndex] == null
) {
if (point == null || xScale == null || data[longestSeriesIndex] == null) {
return TOOLTIP_POSITION_DEFAULT_RETURN;
}

Expand All @@ -223,7 +218,7 @@ export function Chart({
const activeIndex = clamp({
amount: closestIndex,
min: 0,
max: reversedSeries[longestSeriesIndex].data.length - 1,
max: data[longestSeriesIndex].data.length - 1,
});

return {
Expand Down Expand Up @@ -340,13 +335,13 @@ export function Chart({
theme,
})}

{reversedSeries.map((singleSeries, index) => {
{data.map((singleSeries, index) => {
return (
<LineSeries
activeLineIndex={activeLineIndex}
data={singleSeries}
hiddenIndexes={hiddenLineIndexes}
index={reversedSeries.length - 1 - index}
index={index}
key={`${name}-${index}`}
svgDimensions={{height: drawableHeight, width: drawableWidth}}
theme={theme}
Expand All @@ -359,11 +354,11 @@ export function Chart({

<PointsAndCrosshair
activeIndex={activeIndex}
data={data}
drawableHeight={drawableHeight}
emptyState={emptyState}
hiddenIndexes={hiddenLineIndexes}
longestSeriesIndex={longestSeriesIndex}
reversedSeries={reversedSeries}
theme={theme}
tooltipId={tooltipId.current}
xScale={xScale}
Expand Down
14 changes: 12 additions & 2 deletions packages/polaris-viz/src/components/LineChart/LineChart.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import {Fragment, useRef} from 'react';
import {Fragment, useMemo, useRef} from 'react';
import type {
XAxisOptions,
YAxisOptions,
ChartProps,
DataSeries,
} from '@shopify/polaris-viz-core';
import {
InternalChartType,
Expand Down Expand Up @@ -72,7 +73,12 @@ export function LineChart(props: LineChartProps) {
...props,
};

const data = fillMissingDataPoints(dataSeries);
const data = useMemo(() => {
const filledData = fillMissingDataPoints(dataSeries);
const dataWithComparisonFirst = moveComparisonToStartOfArray(filledData);

return dataWithComparisonFirst;
}, [dataSeries]);

const selectedTheme = useTheme(theme);
const seriesColors = useThemeSeriesColors(data, selectedTheme);
Expand Down Expand Up @@ -126,3 +132,7 @@ export function LineChart(props: LineChartProps) {
</Fragment>
);
}

function moveComparisonToStartOfArray(data: DataSeries[]) {
return [...data.sort((_, dataSeries) => (dataSeries.isComparison ? 1 : -1))];
}
Original file line number Diff line number Diff line change
Expand Up @@ -64,10 +64,10 @@ export function Points({

return (
<Fragment>
{data.map((singleSeries, index) => {
const unreversedIndex = data.length - 1 - index;
{data.map((singleSeries, seriesIndex) => {
const index = singleSeries.metadata?.relatedIndex ?? seriesIndex;

if (hiddenIndexes.includes(unreversedIndex)) {
if (hiddenIndexes.includes(index)) {
return null;
}

Expand All @@ -85,11 +85,13 @@ export function Points({
: singleData[activeIndex ?? -1]?.value != null;

const isLineActive =
activeLineIndex !== -1 && activeLineIndex !== unreversedIndex;
activeLineIndex !== -1 && activeLineIndex !== index;

const hidePoint =
const isPointVisuallyHidden =
!hasValidData || animatedCoordinates == null || isLineActive;

const isPointActive = hasValidData && activeIndex != null;

const pointColor = isGradientType(color)
? `url(#${pointGradientId})`
: changeColorOpacity(color);
Expand All @@ -112,11 +114,11 @@ export function Points({
color={pointColor}
cx={getXPosition({isCrosshair: false})}
cy={animatedYPosition}
active={hasValidData && activeIndex != null}
active={isPointActive}
index={index}
tabIndex={-1}
isAnimated={shouldAnimate}
visuallyHidden={hidePoint}
visuallyHidden={isPointVisuallyHidden}
ariaHidden
/>
) : null}
Expand All @@ -131,7 +133,7 @@ export function Points({
key={`${name}-${index}-${dataIndex}`}
style={getColorVisionStylesForActiveIndex({
activeIndex: activeLineIndex,
index: data.length - 1 - index,
index,
fadedOpacity: 0,
})}
>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,24 +19,24 @@ import {Points} from '../Points';

interface PointsAndCrosshairProps {
activeIndex: number | null;
data: LineChartDataSeriesWithDefaults[];
drawableHeight: number;
emptyState: boolean;
hiddenIndexes?: number[];
longestSeriesIndex: number;
reversedSeries: LineChartDataSeriesWithDefaults[];
theme: string;
tooltipId: string;
xScale: ScaleLinear<number, number>;
yScale: ScaleLinear<number, number>;
hiddenIndexes?: number[];
}

export function PointsAndCrosshair({
activeIndex,
data,
drawableHeight,
emptyState,
hiddenIndexes = [],
longestSeriesIndex,
reversedSeries,
theme,
tooltipId,
xScale,
Expand All @@ -59,7 +59,7 @@ export function PointsAndCrosshair({
}, [selectedTheme.line.hasSpline, xScale, yScale]);

const {animatedCoordinates} = useLinearChartAnimations({
data: reversedSeries,
data,
lineGenerator,
activeIndex,
});
Expand Down Expand Up @@ -97,7 +97,7 @@ export function PointsAndCrosshair({
<Points
activeIndex={emptyState ? null : activeIndex}
animatedCoordinates={animatedCoordinates}
data={reversedSeries}
data={data}
getXPosition={getXPosition}
gradientId={gradientId.current}
hiddenIndexes={hiddenIndexes}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,19 @@ import {useMemo} from 'react';
import type {LineChartDataSeriesWithDefaults} from '@shopify/polaris-viz-core';

export function useFormatData(data: LineChartDataSeriesWithDefaults[]) {
const reversedSeries = useMemo(() => data.slice().reverse(), [data]);

const longestSeriesIndex = useMemo(
() =>
reversedSeries.reduce((maxIndex, currentSeries, currentIndex) => {
return reversedSeries[maxIndex].data.length < currentSeries.data.length
data.reduce((maxIndex, currentSeries, currentIndex) => {
return data[maxIndex].data.length < currentSeries.data.length
? currentIndex
: maxIndex;
}, 0),
[reversedSeries],
[data],
);

const longestSeriesLength = reversedSeries[longestSeriesIndex]
? reversedSeries[longestSeriesIndex].data.length - 1
const longestSeriesLength = data[longestSeriesIndex]
? data[longestSeriesIndex].data.length - 1
: 0;

return {reversedSeries, longestSeriesLength, longestSeriesIndex};
return {longestSeriesLength, longestSeriesIndex};
}
Original file line number Diff line number Diff line change
@@ -1,14 +1,18 @@
import type {DataSeries} from '@shopify/polaris-viz-core';
import {
DEFAULT_CHART_PROPS,
DEFAULT_THEME_NAME,
useTheme,
useThemeSeriesColors,
} from '@shopify/polaris-viz-core';
import {useMemo} from 'react';
import type {RenderTooltipContentData} from 'types';

import {LineChart} from '../LineChart';

import type {LineChartPredictiveProps} from './types';
import {CustomLegend, PredictiveLineSeries} from './components';
import {CustomLegend, PredictiveLinePoints} from './components';
import {renderLinearPredictiveTooltipContent} from './utilities/renderLinearPredictiveTooltipContent';

export function LineChartPredictive(props: LineChartPredictiveProps) {
const {
Expand All @@ -22,7 +26,7 @@ export function LineChartPredictive(props: LineChartPredictiveProps) {
skipLinkText,
state,
theme,
tooltipOptions,
tooltipOptions: initialTooltipOptions,
xAxisOptions,
yAxisOptions,
} = {
Expand All @@ -41,19 +45,44 @@ export function LineChartPredictive(props: LineChartPredictiveProps) {
}
}

const selectedTheme = useTheme(theme);
const seriesColors = useThemeSeriesColors(nonPredictiveData, selectedTheme);

const predictiveSeriesNames = predictiveData
.map(({metadata}) => {
return data[metadata?.relatedIndex ?? -1].name;
})
.filter((value) => value != null) as string[];

const selectedTheme = useTheme(theme);
const seriesColors = useThemeSeriesColors(nonPredictiveData, selectedTheme);
const dataWithColors: DataSeries[] = [];
let index = -1;

for (const series of data) {
if (series.metadata?.relatedIndex == null) {
index += 1;
}

dataWithColors.push({
...series,
color: seriesColors[index],
});
}

const tooltipOptions = useMemo(() => {
function renderTooltipContent(tooltipData: RenderTooltipContentData) {
return renderLinearPredictiveTooltipContent(tooltipData);
}

return {
...initialTooltipOptions,
renderTooltipContent,
};
}, [initialTooltipOptions]);

return (
<LineChart
annotations={annotations}
data={nonPredictiveData}
data={dataWithColors}
emptyStateText={emptyStateText}
errorText={errorText}
id={id}
Expand All @@ -63,11 +92,10 @@ export function LineChartPredictive(props: LineChartPredictiveProps) {
slots={{
chart: ({xScale, yScale, drawableHeight, drawableWidth, theme}) => {
return (
<PredictiveLineSeries
data={predictiveData}
<PredictiveLinePoints
data={dataWithColors}
drawableHeight={drawableHeight}
drawableWidth={drawableWidth}
seriesColors={seriesColors}
theme={theme}
xScale={xScale}
yScale={yScale}
Expand All @@ -89,8 +117,7 @@ export function LineChartPredictive(props: LineChartPredictiveProps) {
getColorVisionStyles={getColorVisionStyles}
getColorVisionEventAttrs={getColorVisionEventAttrs}
predictiveSeriesNames={predictiveSeriesNames}
data={nonPredictiveData}
seriesColors={seriesColors}
data={dataWithColors}
theme={theme ?? DEFAULT_THEME_NAME}
/>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,3 @@
flex-wrap: wrap;
list-style: none;
}

.IconContainer {
display: flex;
align-items: center;
justify-items: center;
height: 12px;
width: 20px;
}
Loading

0 comments on commit 23c02cc

Please sign in to comment.