Skip to content

Commit

Permalink
feat(D3 plugin): html labels for most of series (#527)
Browse files Browse the repository at this point in the history
* feat(D3 plugin): html labels for most of series

* fix
  • Loading branch information
kuzmadom authored Oct 10, 2024
1 parent 2163700 commit 9bddfef
Show file tree
Hide file tree
Showing 40 changed files with 629 additions and 103 deletions.
3 changes: 2 additions & 1 deletion .eslintrc
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
"@gravity-ui/eslint-config/import-order"
],
"rules": {
"valid-jsdoc": 0
"valid-jsdoc": 0,
"no-console": ["error", {"allow": ["warn", "error"]}]
},
"root": true,
"overrides": [{
Expand Down
80 changes: 80 additions & 0 deletions src/plugins/d3/__stories__/area/HtmlLabels.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
import React from 'react';

import {Col, Container, Row} from '@gravity-ui/uikit';
import type {StoryObj} from '@storybook/react';

import {ChartKit} from '../../../../components/ChartKit';
import {Loader} from '../../../../components/Loader/Loader';
import {settings} from '../../../../libs';
import type {ChartKitWidgetData} from '../../../../types';
import {ExampleWrapper} from '../../examples/ExampleWrapper';
import {D3Plugin} from '../../index';

const AreaWithHtmlLabels = () => {
const [loading, setLoading] = React.useState(true);

React.useEffect(() => {
settings.set({plugins: [D3Plugin]});
setLoading(false);
}, []);

if (loading) {
return <Loader />;
}

const getLabelData = (value: string, color: string) => {
const labelStyle = `background: ${color};color: #fff;padding: 4px;border-radius: 4px;`;
return {
label: `<span style="${labelStyle}">${value}</span>`,
};
};

const widgetData: ChartKitWidgetData = {
series: {
data: [
{
type: 'area',
name: 'Series 1',
dataLabels: {
enabled: true,
html: true,
},
data: [
{
x: 1,
y: Math.random() * 1000,
...getLabelData('First', '#4fc4b7'),
},
{
x: 100,
y: Math.random() * 1000,
...getLabelData('Last', '#8ccce3'),
},
],
},
],
},
title: {text: 'Area with html labels'},
};

return (
<Container spaceRow={5}>
<Row space={1}>
<Col s={4}>
<ExampleWrapper>
<ChartKit type="d3" data={widgetData} />
</ExampleWrapper>
</Col>
</Row>
</Container>
);
};

export const AreaWithHtmlLabelsStory: StoryObj<typeof AreaWithHtmlLabels> = {
name: 'Html in labels',
};

export default {
title: 'Plugins/D3/Area',
component: AreaWithHtmlLabels,
};
82 changes: 82 additions & 0 deletions src/plugins/d3/__stories__/bar-x/HtmlLabels.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
import React from 'react';

import {Col, Container, Row} from '@gravity-ui/uikit';
import type {StoryObj} from '@storybook/react';

import {ChartKit} from '../../../../components/ChartKit';
import {Loader} from '../../../../components/Loader/Loader';
import {settings} from '../../../../libs';
import type {ChartKitWidgetData} from '../../../../types';
import {ExampleWrapper} from '../../examples/ExampleWrapper';
import {D3Plugin} from '../../index';

const BarXWithHtmlLabels = () => {
const [loading, setLoading] = React.useState(true);

React.useEffect(() => {
settings.set({plugins: [D3Plugin]});
setLoading(false);
}, []);

if (loading) {
return <Loader />;
}

const getLabelData = (value: string, color: string) => {
const labelStyle = `background: ${color};color: #fff;padding: 4px;border-radius: 4px;border: 1px solid #fff;`;
return {
label: `<span style="${labelStyle}">${value}</span>`,
color,
};
};

const widgetData: ChartKitWidgetData = {
series: {
data: [
{
type: 'bar-x',
name: 'Series 1',
dataLabels: {
enabled: true,
html: true,
},
data: [
{
x: 0,
y: Math.random() * 1000,
...getLabelData('First', '#4fc4b7'),
},
{
x: 1,
y: Math.random() * 1000,
...getLabelData('Last', '#8ccce3'),
},
],
},
],
},
xAxis: {type: 'category', categories: ['First', 'Second']},
title: {text: 'Bar-x with html labels'},
};

return (
<Container spaceRow={5}>
<Row space={1}>
<Col s={4}>
<ExampleWrapper>
<ChartKit type="d3" data={widgetData} />
</ExampleWrapper>
</Col>
</Row>
</Container>
);
};

export const BarXWithHtmlLabelsStory: StoryObj<typeof BarXWithHtmlLabels> = {
name: 'Html in labels',
};

export default {
title: 'Plugins/D3/Bar-x',
component: BarXWithHtmlLabels,
};
82 changes: 82 additions & 0 deletions src/plugins/d3/__stories__/bar-y/HtmlLabels.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
import React from 'react';

import {Col, Container, Row} from '@gravity-ui/uikit';
import type {StoryObj} from '@storybook/react';

import {ChartKit} from '../../../../components/ChartKit';
import {Loader} from '../../../../components/Loader/Loader';
import {settings} from '../../../../libs';
import type {ChartKitWidgetData} from '../../../../types';
import {ExampleWrapper} from '../../examples/ExampleWrapper';
import {D3Plugin} from '../../index';

const BarYWithHtmlLabels = () => {
const [loading, setLoading] = React.useState(true);

React.useEffect(() => {
settings.set({plugins: [D3Plugin]});
setLoading(false);
}, []);

if (loading) {
return <Loader />;
}

const getLabelData = (value: string, color: string) => {
const labelStyle = `background: ${color};color: #fff;padding: 4px;border-radius: 4px;border: 1px solid #fff;`;
return {
label: `<span style="${labelStyle}">${value}</span>`,
color,
};
};

const widgetData: ChartKitWidgetData = {
series: {
data: [
{
type: 'bar-y',
name: 'Series 1',
dataLabels: {
enabled: true,
html: true,
},
data: [
{
y: 0,
x: Math.random() * 1000,
...getLabelData('First', '#4fc4b7'),
},
{
y: 1,
x: Math.random() * 1000,
...getLabelData('Last', '#8ccce3'),
},
],
},
],
},
yAxis: [{type: 'category', categories: ['First', 'Second']}],
title: {text: 'Bar-y with html labels'},
};

return (
<Container spaceRow={5}>
<Row space={1}>
<Col s={4}>
<ExampleWrapper>
<ChartKit type="d3" data={widgetData} />
</ExampleWrapper>
</Col>
</Row>
</Container>
);
};

export const BarYWithHtmlLabelsStory: StoryObj<typeof BarYWithHtmlLabels> = {
name: 'Html in labels',
};

export default {
title: 'Plugins/D3/Bar-y',
component: BarYWithHtmlLabels,
};
80 changes: 80 additions & 0 deletions src/plugins/d3/__stories__/line/HtmlLabels.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
import React from 'react';

import {Col, Container, Row} from '@gravity-ui/uikit';
import type {StoryObj} from '@storybook/react';

import {ChartKit} from '../../../../components/ChartKit';
import {Loader} from '../../../../components/Loader/Loader';
import {settings} from '../../../../libs';
import type {ChartKitWidgetData} from '../../../../types';
import {ExampleWrapper} from '../../examples/ExampleWrapper';
import {D3Plugin} from '../../index';

const LineWithHtmlLabels = () => {
const [loading, setLoading] = React.useState(true);

React.useEffect(() => {
settings.set({plugins: [D3Plugin]});
setLoading(false);
}, []);

if (loading) {
return <Loader />;
}

const getLabelData = (value: string, color: string) => {
const labelStyle = `background: ${color};color: #fff;padding: 4px;border-radius: 4px;`;
return {
label: `<span style="${labelStyle}">${value}</span>`,
};
};

const widgetData: ChartKitWidgetData = {
series: {
data: [
{
type: 'line',
name: 'Series 1',
dataLabels: {
enabled: true,
html: true,
},
data: [
{
x: 1,
y: Math.random() * 1000,
...getLabelData('First', '#4fc4b7'),
},
{
x: 100,
y: Math.random() * 1000,
...getLabelData('Last', '#8ccce3'),
},
],
},
],
},
title: {text: 'Line with html labels'},
};

return (
<Container spaceRow={5}>
<Row space={1}>
<Col s={4}>
<ExampleWrapper>
<ChartKit type="d3" data={widgetData} />
</ExampleWrapper>
</Col>
</Row>
</Container>
);
};

export const LineWithHtmlLabelsStory: StoryObj<typeof LineWithHtmlLabels> = {
name: 'Html in labels',
};

export default {
title: 'Plugins/D3/Line',
component: LineWithHtmlLabels,
};
1 change: 1 addition & 0 deletions src/plugins/d3/renderer/hooks/useSeries/prepare-area.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ export function prepareArea(args: PrepareAreaSeriesArgs) {
style: Object.assign({}, DEFAULT_DATALABELS_STYLE, series.dataLabels?.style),
padding: get(series, 'dataLabels.padding', DEFAULT_DATALABELS_PADDING),
allowOverlap: get(series, 'dataLabels.allowOverlap', false),
html: get(series, 'dataLabels.html', false),
},
marker: prepareMarker(series, seriesOptions),
cursor: get(series, 'cursor', null),
Expand Down
1 change: 1 addition & 0 deletions src/plugins/d3/renderer/hooks/useSeries/prepare-bar-x.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ export function prepareBarXSeries(args: PrepareBarXSeriesArgs): PreparedSeries[]
style: Object.assign({}, DEFAULT_DATALABELS_STYLE, series.dataLabels?.style),
allowOverlap: series.dataLabels?.allowOverlap || false,
padding: get(series, 'dataLabels.padding', DEFAULT_DATALABELS_PADDING),
html: get(series, 'dataLabels.html', false),
},
cursor: get(series, 'cursor', null),
yAxis: get(series, 'yAxis', 0),
Expand Down
14 changes: 8 additions & 6 deletions src/plugins/d3/renderer/hooks/useSeries/prepare-bar-y.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,13 @@ type PrepareBarYSeriesArgs = {
function prepareDataLabels(series: BarYSeries) {
const enabled = get(series, 'dataLabels.enabled', false);
const style = Object.assign({}, DEFAULT_DATALABELS_STYLE, series.dataLabels?.style);
const {maxHeight = 0, maxWidth = 0} = enabled
? getLabelsSize({
labels: series.data.map((d) => String(d.label || d.x)),
style,
})
: {};
const html = get(series, 'dataLabels.html', false);
const labels = enabled ? series.data.map((d) => String(d.label || d.x)) : [];
const {maxHeight = 0, maxWidth = 0} = getLabelsSize({
labels,
style,
html,
});
const inside = series.stacking === 'percent' ? true : get(series, 'dataLabels.inside', false);

return {
Expand All @@ -32,6 +33,7 @@ function prepareDataLabels(series: BarYSeries) {
style,
maxHeight,
maxWidth,
html,
};
}

Expand Down
1 change: 1 addition & 0 deletions src/plugins/d3/renderer/hooks/useSeries/prepare-line.ts
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ export function prepareLineSeries(args: PrepareLineSeriesArgs) {
style: Object.assign({}, DEFAULT_DATALABELS_STYLE, series.dataLabels?.style),
padding: get(series, 'dataLabels.padding', DEFAULT_DATALABELS_PADDING),
allowOverlap: get(series, 'dataLabels.allowOverlap', false),
html: get(series, 'dataLabels.html', false),
},
marker: prepareMarker(series, seriesOptions),
dashStyle: dashStyle as DashStyle,
Expand Down
1 change: 1 addition & 0 deletions src/plugins/d3/renderer/hooks/useSeries/prepare-treemap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ export function prepareTreemap(args: PrepareTreemapSeriesArgs) {
style: Object.assign({}, DEFAULT_DATALABELS_STYLE, s.dataLabels?.style),
padding: get(s, 'dataLabels.padding', DEFAULT_DATALABELS_PADDING),
allowOverlap: get(s, 'dataLabels.allowOverlap', false),
html: get(series, 'dataLabels.html', false),
},
id,
type: s.type,
Expand Down
Loading

0 comments on commit 9bddfef

Please sign in to comment.