Skip to content

Commit

Permalink
feat(D3 plugin): add paginated legend (#289)
Browse files Browse the repository at this point in the history
* feat(D3 plugin): add paginated legend

* fix: getPreparedChart fixes

* fix: review fixes

* fix: fix big legend story
  • Loading branch information
korvin89 authored Sep 14, 2023
1 parent 4858235 commit 0846585
Show file tree
Hide file tree
Showing 22 changed files with 692 additions and 296 deletions.
79 changes: 79 additions & 0 deletions src/plugins/d3/__stories__/scatter/BigLegend.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
import React from 'react';
import range from 'lodash/range';
import random from 'lodash/random';
import {Meta, Story} from '@storybook/react';
import {boolean, number, select} from '@storybook/addon-knobs';
import {Button} from '@gravity-ui/uikit';
import {settings} from '../../../../libs';
import {ChartKit} from '../../../../components/ChartKit';
import {randomString} from '../../../../utils';
import type {ChartKitRef} from '../../../../types';
import type {ChartKitWidgetData, ScatterSeries} from '../../../../types/widget-data';
import {D3Plugin} from '../..';

const TEMPLATE_STRING = '0123456789abcdefghijklmnopqrstuvwxyz';

const generateSeriesData = (seriesCount = 5): ScatterSeries[] => {
return range(0, seriesCount).map(() => {
return {
type: 'scatter',
data: [
{
x: random(0, 1000),
y: random(0, 1000),
},
],
name: `${randomString(random(3, 15), TEMPLATE_STRING)}`,
};
});
};

const shapeData = (): ChartKitWidgetData => {
return {
legend: {
align: select('Align', ['left', 'right', 'center'], 'left', 'legend'),
margin: number('Margin', 15, undefined, 'legend'),
itemDistance: number('Item distance', 20, undefined, 'legend'),
},
series: {
data: generateSeriesData(number('Amount of series', 100, undefined, 'legend')),
},
xAxis: {
labels: {
enabled: boolean('Show labels', true, 'xAxis'),
},
},
yAxis: [
{
labels: {
enabled: boolean('Show labels', true, 'yAxis'),
},
},
],
};
};

const Template: Story = () => {
const [shown, setShown] = React.useState(false);
const chartkitRef = React.useRef<ChartKitRef>();
const data = shapeData();

if (!shown) {
settings.set({plugins: [D3Plugin]});
return <Button onClick={() => setShown(true)}>Show chart</Button>;
}

return (
<div style={{height: '300px', width: '100%'}}>
<ChartKit ref={chartkitRef} type="d3" data={data} />
</div>
);
};

export const BigLegend = Template.bind({});

const meta: Meta = {
title: 'Plugins/D3/Scatter',
};

export default meta;
43 changes: 27 additions & 16 deletions src/plugins/d3/renderer/components/Chart.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,21 @@ import React from 'react';
import type {ChartKitWidgetData} from '../../../../types';
import {block} from '../../../../utils/cn';

import {AxisY} from './AxisY';
import {AxisX} from './AxisX';
import {Legend} from './Legend';
import {Title} from './Title';
import {Tooltip} from './Tooltip';
import {
useAxisScales,
useChartDimensions,
useChartEvents,
useChartOptions,
useAxisScales,
useSeries,
useShapes,
useTooltip,
} from '../hooks';
import {isAxisRelatedSeries} from '../utils';
import {AxisY} from './AxisY';
import {AxisX} from './AxisX';
import {Legend} from './Legend';
import {Title} from './Title';
import {Tooltip} from './Tooltip';

import './styles.scss';

Expand All @@ -31,18 +32,29 @@ type Props = {
};

export const Chart = (props: Props) => {
const {top, left, width, height, data} = props;
// FIXME: add data validation
const {top, left, width, height, data} = props;
const svgRef = React.createRef<SVGSVGElement>();
const {chartHovered, handleMouseEnter, handleMouseLeave} = useChartEvents();
const {chart, legend, title, tooltip, xAxis, yAxis} = useChartOptions(data);
const {chart, title, tooltip, xAxis, yAxis} = useChartOptions(data);
const {legendItems, legendConfig, preparedSeries, preparedLegend, handleLegendItemClick} =
useSeries({
chartWidth: width,
chartHeight: height,
chartMargin: chart.margin,
series: data.series,
legend: data.legend,
preparedYAxis: yAxis,
});
const {boundsWidth, boundsHeight} = useChartDimensions({
hasAxisRelatedSeries: data.series.data.some(isAxisRelatedSeries),
width,
height,
margin: chart.margin,
yAxis,
preparedLegend,
preparedXAxis: xAxis,
preparedYAxis: yAxis,
});
const {preparedSeries, handleLegendItemClick} = useSeries({series: data.series, legend});
const {xScale, yScale} = useAxisScales({
boundsWidth,
boundsHeight,
Expand Down Expand Up @@ -106,14 +118,13 @@ export const Chart = (props: Props) => {
)}
{shapes}
</g>
{legend.enabled && (
{preparedLegend.enabled && (
<Legend
width={boundsWidth}
offsetWidth={chart.margin.left}
height={legend.height}
legend={legend}
offsetHeight={height - legend.height / 2}
chartSeries={preparedSeries}
boundsWidth={boundsWidth}
legend={preparedLegend}
items={legendItems}
config={legendConfig}
onItemClick={handleLegendItemClick}
/>
)}
Expand Down
Loading

0 comments on commit 0846585

Please sign in to comment.