Skip to content

Commit 450d898

Browse files
committed
feat: add borderRadius option to bar-y series (#47)
1 parent 280d5ae commit 450d898

File tree

14 files changed

+128
-31
lines changed

14 files changed

+128
-31
lines changed

src/__stories__/__data__/bar-y/playground.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ function prepareData(): ChartData {
2121
dataLabels: {
2222
enabled: true,
2323
},
24+
borderRadius: 4,
2425
},
2526
],
2627
},

src/hooks/useSeries/prepare-bar-y.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import type {ScaleOrdinal} from 'd3';
22
import get from 'lodash/get';
33

4-
import type {BarYSeries} from '../../types';
4+
import type {BarYSeries, ChartSeriesOptions} from '../../types';
55
import {getLabelsSize, getUniqId} from '../../utils';
66

77
import {DEFAULT_DATALABELS_STYLE} from './constants';
@@ -12,6 +12,7 @@ type PrepareBarYSeriesArgs = {
1212
colorScale: ScaleOrdinal<string, string>;
1313
series: BarYSeries[];
1414
legend: PreparedLegend;
15+
seriesOptions?: ChartSeriesOptions;
1516
};
1617

1718
function prepareDataLabels(series: BarYSeries) {
@@ -37,7 +38,7 @@ function prepareDataLabels(series: BarYSeries) {
3738
}
3839

3940
export function prepareBarYSeries(args: PrepareBarYSeriesArgs): PreparedSeries[] {
40-
const {colorScale, series: seriesList, legend} = args;
41+
const {colorScale, series: seriesList, seriesOptions, legend} = args;
4142

4243
return seriesList.map<PreparedBarYSeries>((series) => {
4344
const name = series.name || '';
@@ -58,6 +59,7 @@ export function prepareBarYSeries(args: PrepareBarYSeriesArgs): PreparedSeries[]
5859
stackId: getSeriesStackId(series),
5960
dataLabels: prepareDataLabels(series),
6061
cursor: get(series, 'cursor', null),
62+
borderRadius: series.borderRadius ?? seriesOptions?.['bar-y']?.borderRadius ?? 0,
6163
};
6264
}, []);
6365
}

src/hooks/useSeries/prepareSeries.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,12 @@ export function prepareSeries(args: {
5353
});
5454
}
5555
case 'bar-y': {
56-
return prepareBarYSeries({series: series as BarYSeries[], legend, colorScale});
56+
return prepareBarYSeries({
57+
series: series as BarYSeries[],
58+
legend,
59+
colorScale,
60+
seriesOptions,
61+
});
5762
}
5863
case 'scatter': {
5964
return prepareScatterSeries({series: series as ScatterSeries[], legend, colorScale});

src/hooks/useSeries/types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,7 @@ export type PreparedBarYSeries = {
165165
maxWidth: number;
166166
html: boolean;
167167
};
168+
borderRadius: number;
168169
} & BasePreparedSeries;
169170

170171
export type PreparedPieSeries = {

src/hooks/useShapes/bar-x/index.tsx

Lines changed: 13 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,21 @@
11
import React from 'react';
22

3-
import {color, path, select} from 'd3';
3+
import {color, select} from 'd3';
44
import type {Dispatch} from 'd3';
55
import get from 'lodash/get';
66

77
import type {LabelData} from '../../../types';
88
import {block, filterOverlappingLabels} from '../../../utils';
99
import type {PreparedSeriesOptions} from '../../useSeries/types';
1010
import {HtmlLayer} from '../HtmlLayer';
11+
import {getRectPath} from '../utils';
1112

1213
import type {PreparedBarXData} from './types';
1314

1415
export {prepareBarXData} from './prepare-data';
1516
export * from './types';
1617

17-
const b = block('d3-bar-x');
18+
const b = block('bar-x');
1819

1920
type Args = {
2021
dispatcher: Dispatch<object>;
@@ -42,26 +43,18 @@ export const BarXSeriesShapes = (args: Args) => {
4243
.data(preparedData)
4344
.join('path')
4445
.attr('d', (d) => {
45-
const borderRadius = d.isTopItem
46+
const borderRadius = d.isLastStackItem
4647
? Math.min(d.height, d.width / 2, d.series.borderRadius)
4748
: 0;
48-
const p = path();
49-
p.moveTo(d.x + borderRadius, d.y);
50-
p.lineTo(d.x + d.width - borderRadius, d.y);
51-
p.arc(
52-
d.x + d.width - borderRadius,
53-
d.y + borderRadius,
54-
borderRadius,
55-
-Math.PI / 2,
56-
0,
57-
false,
58-
);
59-
p.lineTo(d.x + d.width, d.y + d.height);
60-
p.lineTo(d.x, d.y + d.height);
61-
p.lineTo(d.x, d.y + borderRadius);
62-
p.arc(d.x + borderRadius, d.y + borderRadius, borderRadius, Math.PI, -Math.PI / 2);
63-
p.moveTo(d.x + borderRadius, d.y);
64-
p.closePath();
49+
50+
const p = getRectPath({
51+
x: d.x,
52+
y: d.y,
53+
width: d.width,
54+
height: d.height,
55+
borderRadius: [borderRadius, borderRadius, 0, 0],
56+
});
57+
6558
return p.toString();
6659
})
6760
.attr('class', b('segment'))

src/hooks/useShapes/bar-x/prepare-data.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,7 @@ export const prepareBarXData = (args: {
171171
data: yValue.data,
172172
series: yValue.series,
173173
htmlElements: [],
174-
isTopItem: yValueIndex === sortedData.length - 1,
174+
isLastStackItem: yValueIndex === sortedData.length - 1,
175175
};
176176

177177
const label = getLabelData(barData);

src/hooks/useShapes/bar-x/types.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,5 +10,5 @@ export type PreparedBarXData = Omit<TooltipDataChunkBarX, 'series'> & {
1010
series: PreparedBarXSeries;
1111
label?: LabelData;
1212
htmlElements: HtmlItem[];
13-
isTopItem: boolean;
13+
isLastStackItem: boolean;
1414
};

src/hooks/useShapes/bar-y/index.tsx

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,12 @@ import type {LabelData} from '../../../types';
88
import {block} from '../../../utils';
99
import type {PreparedSeriesOptions} from '../../useSeries/types';
1010
import {HtmlLayer} from '../HtmlLayer';
11+
import {getRectPath} from '../utils';
1112

1213
import type {PreparedBarYData} from './types';
1314
export {prepareBarYData} from './prepare-data';
1415

15-
const b = block('d3-bar-y');
16+
const b = block('bar-y');
1617

1718
type Args = {
1819
dispatcher: Dispatch<object>;
@@ -36,7 +37,22 @@ export const BarYSeriesShapes = (args: Args) => {
3637
const rectSelection = svgElement
3738
.selectAll('rect')
3839
.data(preparedData)
39-
.join('rect')
40+
.join('path')
41+
.attr('d', (d) => {
42+
const borderRadius = d.isLastStackItem
43+
? Math.min(d.height, d.width / 2, d.series.borderRadius)
44+
: 0;
45+
46+
const p = getRectPath({
47+
x: d.x,
48+
y: d.y,
49+
width: d.width,
50+
height: d.height,
51+
borderRadius: [0, borderRadius, borderRadius, 0],
52+
});
53+
54+
return p.toString();
55+
})
4056
.attr('class', b('segment'))
4157
.attr('x', (d) => d.x)
4258
.attr('y', (d) => d.y)

src/hooks/useShapes/bar-y/prepare-data.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,7 @@ export const prepareBarYData = (args: {
170170
const sortedData = sortKey
171171
? sort(measureValues, (a, b) => comparator(get(a, sortKey), get(b, sortKey)))
172172
: measureValues;
173-
sortedData.forEach(({data, series: s}) => {
173+
sortedData.forEach(({data, series: s}, xValueIndex) => {
174174
let center;
175175

176176
if (yAxis[0].type === 'category') {
@@ -196,6 +196,7 @@ export const prepareBarYData = (args: {
196196
data,
197197
series: s,
198198
htmlElements: [],
199+
isLastStackItem: xValueIndex === sortedData.length - 1,
199200
};
200201

201202
stackItems.push(item);

src/hooks/useShapes/bar-y/types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,4 +11,5 @@ export type PreparedBarYData = Omit<TooltipDataChunkBarX, 'series'> & {
1111
series: PreparedBarYSeries;
1212
label?: LabelData;
1313
htmlElements: HtmlItem[];
14+
isLastStackItem: boolean;
1415
};

0 commit comments

Comments
 (0)