diff --git a/package.json b/package.json index 28299bc..7091f0a 100644 --- a/package.json +++ b/package.json @@ -172,6 +172,7 @@ "@storybook/addon-docs": "10.2.10", "@storybook/addon-links": "10.2.10", "@storybook/addon-themes": "10.2.10", + "@storybook/react": "10.2.10", "@storybook/react-vite": "10.2.10", "@storybook/test-runner": "0.24.2", "@storybook/testing-library": "0.2.2", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 87dadbe..b8050ca 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -48,6 +48,9 @@ importers: '@storybook/addon-themes': specifier: 10.2.10 version: 10.2.10(storybook@10.2.10(@testing-library/dom@9.3.4)(prettier@3.8.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)) + '@storybook/react': + specifier: 10.2.10 + version: 10.2.10(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(storybook@10.2.10(@testing-library/dom@9.3.4)(prettier@3.8.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(typescript@5.9.3) '@storybook/react-vite': specifier: 10.2.10 version: 10.2.10(esbuild@0.27.2)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rollup@4.57.1)(storybook@10.2.10(@testing-library/dom@9.3.4)(prettier@3.8.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(typescript@5.9.3)(vite@8.0.0-beta.10(@types/node@25.2.0)(esbuild@0.27.2)(terser@5.46.0)) @@ -3368,6 +3371,7 @@ packages: resolution: {integrity: sha512-/baBXDqkfW8x0UlqfYAfRCkmVWiH8qFZ4uhT6yLVBLssiypDTbe78W6lNBse7huBFv1ipR5PG9evkxEnIXDxjA==} peerDependencies: eslint: '>= 5' + bundledDependencies: [] eslint-plugin-compat@6.1.0: resolution: {integrity: sha512-xiwHz7mj6+Zj7NWOO/uaWdrQ6zP0zL5CPyKVCNlB4JaoUFeYPYwejf5toqyHGlXzhuPUdCpg31uBRiWqcgiS0A==} diff --git a/src/__mocks__/styleMock.ts b/src/__mocks__/styleMock.ts index f053ebf..ff8b4c5 100644 --- a/src/__mocks__/styleMock.ts +++ b/src/__mocks__/styleMock.ts @@ -1 +1 @@ -module.exports = {}; +export default {}; diff --git a/src/charts/barChart/barChart.type.ts b/src/charts/barChart/barChart.type.ts index b871eee..3a7f2ed 100644 --- a/src/charts/barChart/barChart.type.ts +++ b/src/charts/barChart/barChart.type.ts @@ -8,6 +8,7 @@ import type { TickData } from '@/components/tick/tick.types'; import type { CanvasConfig } from '@/types/canvas.type'; import type { ChartError, ChartErrorCollection, ErrorType } from '@/types/errors.type'; import type { Positions } from '@/types/position.enum'; +import type { ValueFormatter } from '@/types/valueFormatter.type'; export type BarChartChildrenType = ReactNode | ReactElement; @@ -121,6 +122,7 @@ export interface BarChartXAxisProps extends Omit, React.A */ ariaLabel?: string; tickValues?: BarChartTickValuesAxisProps; + valueFormatter?: ValueFormatter; } export interface BarChartYAxisProps extends Omit, React.AriaAttributes { /** @@ -128,6 +130,7 @@ export interface BarChartYAxisProps extends Omit, React.A */ ariaLabel?: string; tickValues?: BarChartTickValuesAxisProps; + valueFormatter?: ValueFormatter; } export interface BarChartSeparatorProps { topSeparator?: StyleProps; diff --git a/src/charts/barChart/fragments/__tests__/barChartXAxis.test.tsx b/src/charts/barChart/fragments/__tests__/barChartXAxis.test.tsx index 9937d69..75632a4 100644 --- a/src/charts/barChart/fragments/__tests__/barChartXAxis.test.tsx +++ b/src/charts/barChart/fragments/__tests__/barChartXAxis.test.tsx @@ -15,4 +15,20 @@ describe('LineChartXAxis', () => { const xAxis = getByTestId('testxAxis'); expect(xAxis).toBeInTheDocument(); }); + + it('renders formatted tick labels', () => { + const { getByText } = render( + + `Label ${value}`} + /> + + ); + + expect(getByText('Label 1')).toBeInTheDocument(); + expect(getByText('Label 2')).toBeInTheDocument(); + expect(getByText('Label 3')).toBeInTheDocument(); + }); }); diff --git a/src/charts/barChart/fragments/__tests__/barChartYAxis.test.tsx b/src/charts/barChart/fragments/__tests__/barChartYAxis.test.tsx index 5ea56be..60bc77a 100644 --- a/src/charts/barChart/fragments/__tests__/barChartYAxis.test.tsx +++ b/src/charts/barChart/fragments/__tests__/barChartYAxis.test.tsx @@ -15,4 +15,20 @@ describe('LineChartYAxis', () => { const yAxis = getByTestId('testyAxis'); expect(yAxis).toBeInTheDocument(); }); + + it('renders formatted tick labels', () => { + const { getByText } = render( + + `${value}%`} + /> + + ); + + expect(getByText('10%')).toBeInTheDocument(); + expect(getByText('20%')).toBeInTheDocument(); + expect(getByText('30%')).toBeInTheDocument(); + }); }); diff --git a/src/charts/barChart/fragments/barChartXAxis.tsx b/src/charts/barChart/fragments/barChartXAxis.tsx index abaa047..849b52f 100644 --- a/src/charts/barChart/fragments/barChartXAxis.tsx +++ b/src/charts/barChart/fragments/barChartXAxis.tsx @@ -1,6 +1,7 @@ import { type FC, type ReactElement, useContext } from 'react'; import { XAxis } from '@/components/axisChart/xAxis/xAxis'; +import { TickDataUtils } from '@/components/tick/tick.types'; import { Positions } from '@/types/position.enum'; import { getTickTextYCoordinate } from '@/utils/getTickTextCoordinate/getTickTextCoordinates'; @@ -12,6 +13,7 @@ export const BarChartXAxis: FC = ({ position = Positions.BOTTOM, tickLine, tickText, + valueFormatter = (value: string) => value, ...props }): ReactElement => { const { @@ -29,6 +31,9 @@ export const BarChartXAxis: FC = ({ const y1 = context.extraSpaceTopY; const y2 = Number(context.canvasHeight) - context.extraSpaceBottomY; + const formattedTickValues = tickText + ? TickDataUtils.formatTicksValues(tickValues, valueFormatter) + : undefined; return ( = ({ ...tickText, y: tickTextY, }} - tickValues={tickText ? tickValues : undefined} + tickValues={formattedTickValues} /> ); }; diff --git a/src/charts/barChart/fragments/barChartYAxis.tsx b/src/charts/barChart/fragments/barChartYAxis.tsx index 264be82..f0a5383 100644 --- a/src/charts/barChart/fragments/barChartYAxis.tsx +++ b/src/charts/barChart/fragments/barChartYAxis.tsx @@ -1,6 +1,7 @@ import { type FC, type ReactElement, useContext } from 'react'; import { YAxis } from '@/components/axisChart/yAxis/yAxis'; +import { TickDataUtils } from '@/components/tick/tick.types'; import { Positions } from '@/types/position.enum'; import { ajustedTextSpace } from '@/utils/ajustedTextSpace/ajustedTextSpace'; import { getTickTextXCoordinate } from '@/utils/getTickTextCoordinate/getTickTextCoordinates'; @@ -13,6 +14,7 @@ export const BarChartYAxis: FC = ({ position = Positions.LEFT, tickLine, tickText, + valueFormatter = (value: string) => value, ...props }): ReactElement => { const { @@ -30,6 +32,9 @@ export const BarChartYAxis: FC = ({ coordinates.x1, ajustedText ); + const formattedTickValues = tickText + ? TickDataUtils.formatTicksValues(tickValues, valueFormatter) + : undefined; return ( = ({ x2: Number(context.canvasWidth) - context.extraSpaceRightX, }} tickText={{ ...tickText, x: xTickText }} - tickValues={tickText ? tickValues : undefined} + tickValues={formattedTickValues} /> ); }; diff --git a/src/charts/barChart/stories/barChart.stories.tsx b/src/charts/barChart/stories/barChart.stories.tsx index 773a63a..2913d9d 100644 --- a/src/charts/barChart/stories/barChart.stories.tsx +++ b/src/charts/barChart/stories/barChart.stories.tsx @@ -12,10 +12,7 @@ import { AXIS_WITH_HORIZONTAL_BARS } from './templates/axisWithHorizontalBars'; import { AXIS_WITH_VERTICAL_BARS } from './templates/axisWithVericalBars'; import { COMPARATIVE_DATA, MIXED_DATA } from './templates/data'; import { BarChartWithErrorHandlingWithHooks } from './templates/withErrorHandling'; -import { - BarChartWithTooltip, - BarChartHorizontalWithTooltip, -} from './templates/withTooltip'; +import { BarChartHorizontalWithTooltip, BarChartWithTooltip } from './templates/withTooltip'; const meta = { argTypes: argtypes(), @@ -272,8 +269,8 @@ export const WithTooltipHorizontal: Story = { text={[

- This example shows a horizontal bar chart with a fixed info - panel that displays details about the hovered bar. + This example shows a horizontal bar chart with a fixed info panel + that displays details about the hovered bar.

Instead of a floating tooltip, this pattern uses a persistent panel that updates diff --git a/src/charts/barChart/stories/children/XAxis/xAxis.argtypes.ts b/src/charts/barChart/stories/children/XAxis/xAxis.argtypes.ts index b75f431..b5d3333 100644 --- a/src/charts/barChart/stories/children/XAxis/xAxis.argtypes.ts +++ b/src/charts/barChart/stories/children/XAxis/xAxis.argtypes.ts @@ -181,6 +181,26 @@ export const xAxisArgTypes = (): ArgTypes => { }, }, + valueFormatter: { + control: { + labels: { + currency: 'Currency ($)', + custom: 'Custom Format [val]', + millions: 'Millions (M)', + none: 'None (no formatting)', + percentage: 'Percentage (%)', + thousands: 'Thousands (K)', + }, + type: 'select', + }, + description: 'Select a formatting style for tick labels in this story.', + options: ['none', 'currency', 'percentage', 'thousands', 'millions', 'custom'], + table: { + category: CATEGORY_CONTROL.DATA, + type: { summary: 'ValueFormatter | undefined' }, + }, + }, + transform: { control: { type: 'text' }, description: 'SVG transform attribute for positioning and scaling.', diff --git a/src/charts/barChart/stories/children/XAxis/xAxis.stories.tsx b/src/charts/barChart/stories/children/XAxis/xAxis.stories.tsx index a3fece2..388a023 100644 --- a/src/charts/barChart/stories/children/XAxis/xAxis.stories.tsx +++ b/src/charts/barChart/stories/children/XAxis/xAxis.stories.tsx @@ -4,15 +4,18 @@ import { BarOrientation } from '@/components/bar/bar.type'; import { Note } from '@/storybook/components/note/note'; import { DefaultCanvasConfig } from '@/types/canvas.type'; import { Positions } from '@/types/position.enum'; +import type { ValueFormatter } from '@/types/valueFormatter.type'; import { BarChart } from '../../../barChart'; import type { BarChartXAxisProps } from '../../../barChart.type'; -import { BarChartXAxis } from '../../../fragments/barChartXAxis'; import { xAxisArgTypes } from './xAxis.argtypes'; +type XAxisStoryArgs = Omit & { + valueFormatter?: ValueFormatter | string; +}; + const meta = { argTypes: xAxisArgTypes(), - component: BarChartXAxis, decorators: [ (Story: React.ComponentType) => ( <> @@ -33,6 +36,11 @@ const meta = { • tickValues - Define custom tick positions using numeric or custom format , + <> + • valueFormatter - Format tick labels using a callback function{' '} + (val) => string. The dropdown below shows preset examples, but in your + code you'll pass actual functions. + , <> • tickText - Complete text styling control including font, color, and positioning @@ -61,10 +69,28 @@ const meta = { ], tags: ['autodocs'], title: 'Charts/BarChart/Child Components/BarChartXAxis', -} satisfies Meta; +} satisfies Meta; export default meta; -type Story = StoryObj; +type Story = StoryObj; + +const getValueFormatter = (formatterType: string) => { + switch (formatterType) { + case 'currency': + return val => `$${val}`; + case 'percentage': + return val => `${val}%`; + case 'thousands': + return val => `${val}K`; + case 'millions': + return val => `${val}M`; + case 'custom': + return val => `[${val}]`; + case 'none': + default: + return undefined; + } +}; export const XAxisCustomization: Story = { args: { @@ -159,11 +185,17 @@ export const XAxisCustomization: Story = { values: ['2001', '2002', '2003', '2004'], }, }, + valueFormatter: 'thousands', transform: undefined, }, - render: (args: BarChartXAxisProps) => { + render: (args: XAxisStoryArgs) => { + const actualArgs = { + ...args, + valueFormatter: getValueFormatter(args.valueFormatter as string), + }; + // Simplified data for better visualization (single series per year) const simplifiedData = [ { value: 50, year: 2001 }, @@ -208,7 +240,7 @@ export const XAxisCustomization: Story = { orientation={BarOrientation.VERTICAL} pKey="year" > - + {simplifiedData.map((dataPoint, index) => ( => { }, }, + valueFormatter: { + control: { + labels: { + currency: 'Currency ($)', + custom: 'Custom brackets [val]', + millions: 'Millions (M)', + none: 'None (no formatting)', + percentage: 'Percentage (%)', + thousands: 'Thousands (K)', + units: 'Units (k)', + }, + type: 'select', + }, + description: 'Select a formatting style for tick labels in this story.', + options: ['none', 'currency', 'percentage', 'units', 'thousands', 'millions', 'custom'], + table: { + category: CATEGORY_CONTROL.DATA, + defaultValue: { summary: 'undefined' }, + type: { summary: 'ValueFormatter' }, + }, + }, + transform: { control: { type: 'text' }, description: 'SVG transform attribute for positioning and scaling.', diff --git a/src/charts/barChart/stories/children/YAxis/yAxis.stories.tsx b/src/charts/barChart/stories/children/YAxis/yAxis.stories.tsx index 8efc5c4..4f910a5 100644 --- a/src/charts/barChart/stories/children/YAxis/yAxis.stories.tsx +++ b/src/charts/barChart/stories/children/YAxis/yAxis.stories.tsx @@ -4,16 +4,19 @@ import { BarOrientation } from '@/components/bar/bar.type'; import { Note } from '@/storybook/components/note/note'; import { DefaultCanvasConfig } from '@/types/canvas.type'; import { Positions } from '@/types/position.enum'; +import type { ValueFormatter } from '@/types/valueFormatter.type'; import { BarChart } from '../../../barChart'; import type { BarChartYAxisProps } from '../../../barChart.type'; -import { BarChartYAxis } from '../../../fragments/barChartYAxis'; import { simplifiedData } from '../../templates/data'; import { yAxisArgTypes } from './yAxis.argtypes'; +type YAxisStoryArgs = Omit & { + valueFormatter?: ValueFormatter | string; +}; + const meta = { argTypes: yAxisArgTypes(), - component: BarChartYAxis, decorators: [ (Story: React.ComponentType) => ( <> @@ -30,6 +33,11 @@ const meta = { <> Key Features: , + <> + • valueFormatter - Format tick labels using a callback function{' '} + (val) => string. The dropdown below shows preset examples, but in your + code you'll pass actual functions. + , <> • position - Axis placement (left or right, refresh story after setting in controls) @@ -68,10 +76,30 @@ const meta = { ], tags: ['autodocs'], title: 'Charts/BarChart/Child Components/BarChartYAxis', -} satisfies Meta; +} satisfies Meta; export default meta; -type Story = StoryObj; +type Story = StoryObj; + +const getValueFormatter = (formatterType: string) => { + switch (formatterType) { + case 'currency': + return val => `$${val}`; + case 'percentage': + return val => `${val}%`; + case 'thousands': + return val => `${val}K`; + case 'millions': + return val => `${val}M`; + case 'units': + return val => `${val}k`; + case 'custom': + return val => `[${val}]`; + case 'none': + default: + return undefined; + } +}; export const YAxisCustomization: Story = { args: { @@ -161,11 +189,17 @@ export const YAxisCustomization: Story = { step: 1, }, }, + valueFormatter: 'currency', transform: undefined, }, - render: (args: BarChartYAxisProps) => { + render: (args: YAxisStoryArgs) => { + const actualArgs = { + ...args, + valueFormatter: getValueFormatter(args.valueFormatter as string), + }; + const chartData = simplifiedData; const barConfigs = [ @@ -203,7 +237,7 @@ export const YAxisCustomization: Story = { orientation={BarOrientation.HORIZONTAL} pKey="year" > - + {chartData.map((dataPoint, index) => ( { yData: [], }); }); + + it('should use formatted X axis labels to calculate spacing while preserving raw xData', () => { + SVGElement.prototype.getBBox = vi.fn(function (this: SVGElement) { + return { + height: 50, + width: (this.textContent ?? '').length * 10, + x: 0, + y: 0, + }; + }); + + const children = [ + , + `Long ${value}`} + />, + ]; + + const result = getAxisExtraSpacing({ + ajustedX: 1, + ajustedY: 1, + canvasHeight: 100, + canvasWidth: 70, + children, + data: mockData, + gapBetweenBars: 5, + orientation: BarOrientation.VERTICAL, + pKey: 'key', + viewBox: '0 0 100, 80', + }); + + expect(result.securityXSpace).toBe(60); + expect(result.xData).toEqual(['A', 'B', 'C']); + }); + + it('should use formatted Y axis labels to calculate spacing while preserving raw yData', () => { + SVGElement.prototype.getBBox = vi.fn(function (this: SVGElement) { + return { + height: 50, + width: (this.textContent ?? '').length * 10, + x: 0, + y: 0, + }; + }); + + const children = [ + , + `${value}% growth`} + />, + ]; + + const result = getAxisExtraSpacing({ + ajustedX: 1, + ajustedY: 1, + canvasHeight: 100, + canvasWidth: 70, + children, + data: mockData, + gapBetweenBars: 5, + orientation: BarOrientation.HORIZONTAL, + pKey: 'key', + viewBox: '0 0 100, 80', + }); + + expect(result.extraSpaceLeftX).toBe(105); + expect(result.yAxisText).toBe(100); + expect(result.yData).toEqual(['10', '20', '30']); + }); }); diff --git a/src/charts/barChart/utils/getAxisExtraSpacing.ts b/src/charts/barChart/utils/getAxisExtraSpacing.ts index d446f2a..060dbda 100644 --- a/src/charts/barChart/utils/getAxisExtraSpacing.ts +++ b/src/charts/barChart/utils/getAxisExtraSpacing.ts @@ -1,4 +1,4 @@ -import { Children, type ReactElement, isValidElement } from 'react'; +import { Children, type ReactElement, type ReactNode, isValidElement } from 'react'; import { BarOrientation } from '@/components/bar/bar.type'; import { Positions } from '@/types/position.enum'; @@ -26,16 +26,17 @@ const handleBarChartXAxis = ( canvasHeight: number, canvasWidth: number ) => { - const { position, tickText, tickValues } = child.props as any; + const { position, tickText, tickValues, valueFormatter } = child.props as any; const fontSize = tickText?.fontSize ?? 0; const spaceFontSize = fontSize * ajustedX; const xData = tickValues ? (getBarDataValues(tickValues) as string[]) : (data.map(d => d[pKey]) as string[]); + const formattedXData: string[] = valueFormatter ? xData.map(valueFormatter) : xData; const fontSpacing = textBound({ bound: 'width', - data: xData, + data: formattedXData, fontSize, svgHeight: `${canvasHeight}`, svgWidth: `${canvasWidth}`, @@ -62,7 +63,7 @@ const handleBarChartXAxis = ( }; const handleBarChartYAxis = ( - child: React.ReactElement, + child: ReactElement, data: BarChartIDataPoint[], pKey: string, ajustedY: number, @@ -71,7 +72,7 @@ const handleBarChartYAxis = ( canvasHeight: number, canvasWidth: number ) => { - const { position, tickText, tickValues } = child.props as any; + const { position, tickText, tickValues, valueFormatter } = child.props as any; const fontSize = tickText?.fontSize ?? 0; const spaceFontSize = fontSize * ajustedY; //! review @@ -79,11 +80,12 @@ const handleBarChartYAxis = ( tickValues || buildTickValues([...new Set(getBarKeyRoundMaxValue(data, pKey) as unknown as string[])]); const yData = getBarDataValues(dataValues) as string[]; + const formattedYData: string[] = valueFormatter ? yData.map(valueFormatter) : yData; const securityYSpace = (() => (barSpacing > spaceFontSize ? barSpacing : spaceFontSize))(); const textWidth = textBound({ bound: 'width', - data: yData, + data: formattedYData, fontSize, svgHeight: `${canvasHeight}`, svgWidth: `${canvasWidth}`, @@ -133,7 +135,7 @@ export const getAxisExtraSpacing = ({ pKey, viewBox, }: GetExtraSpacing): BarChartExtraSpacings => { - let result = { + let result: BarChartExtraSpacings = { barChartXPosition: Positions.BOTTOM, barChartYPosition: Positions.LEFT, extraSpaceBottomY: 0, @@ -152,7 +154,7 @@ export const getAxisExtraSpacing = ({ let barsSpacing = gapBetweenBars; const reviews = [] as number[]; - Children.forEach(children, (child: React.ReactNode) => { + Children.forEach(children, (child: ReactNode) => { if (isValidElement(child)) { if (child.type === BarChartPath && !reviews.includes((child.props as any).order)) { reviews.push((child.props as any).order); diff --git a/src/charts/pieChart/fragments/__tests__/pieChartPath.test.tsx b/src/charts/pieChart/fragments/__tests__/pieChartPath.test.tsx index 4735206..3a07073 100644 --- a/src/charts/pieChart/fragments/__tests__/pieChartPath.test.tsx +++ b/src/charts/pieChart/fragments/__tests__/pieChartPath.test.tsx @@ -109,4 +109,28 @@ describe('PieChartPath', () => { const pathsFinal = segmentsFinal.map(s => s.getAttribute('d')); expect(pathsFinal).toEqual(pathsBefore); }); + + it('renders a single halfChart segment without mirrored singleStroke fallback', () => { + const data = { + testKey: [{ name: 'Empty', value: 400, color: '#d9d9d9' }], + }; + + const { getByTestId } = render( + + + + ); + + expect(getByTestId('testpath-0').getAttribute('d')).toBe( + 'M 100 100 A 50,50 0 0,0 0, 100 L 50,100 Z' + ); + }); }); diff --git a/src/charts/pieChart/utils/__tests__/calculateSegmentPath.test.ts b/src/charts/pieChart/utils/__tests__/calculateSegmentPath.test.ts index c08d7f2..4a0fd22 100644 --- a/src/charts/pieChart/utils/__tests__/calculateSegmentPath.test.ts +++ b/src/charts/pieChart/utils/__tests__/calculateSegmentPath.test.ts @@ -121,4 +121,19 @@ describe('calculateSegmentPath', () => { 'M 100 50 A 50,50 0 0,0 0, 49.99999999999999 M 50,50 M 100,50 A 50,50 0 0 1 0,49.99999999999999 M 50,50 A 0,0 0 0 0 50,50' ); }); + + it('should not mirror a single segment when halfChart is true', () => { + const path = calculateSegmentPath({ + canvasHeight: 100, + canvasWidth: 100, + gap: 0, + halfChart: true, + innerRadius: 0, + singleStroke: true, + startAngle: { current: 0 }, + total: 100, + value: 100, + }); + expect(path).toBe('M 100 100 A 50,50 0 0,0 0, 100 L 50,100 Z'); + }); }); diff --git a/src/charts/pieChart/utils/calculateSegmentPath.ts b/src/charts/pieChart/utils/calculateSegmentPath.ts index 8683d17..bc47453 100644 --- a/src/charts/pieChart/utils/calculateSegmentPath.ts +++ b/src/charts/pieChart/utils/calculateSegmentPath.ts @@ -46,6 +46,7 @@ export const calculateSegmentPath = ({ total, value, }: CalculateSegmanentPathProps): string => { + const useSingleStroke = singleStroke && !halfChart; const segmentCanvasHeight = halfChart ? canvasHeight * 2 : canvasHeight; const maxRadius = Math.min(canvasWidth, segmentCanvasHeight) / 2; const radius = customRadius && customRadius < maxRadius ? customRadius : maxRadius; @@ -53,7 +54,7 @@ export const calculateSegmentPath = ({ const center = { x: canvasWidth / 2, y: halfChart ? canvasHeight : canvasHeight / 2 }; // Total * 2 is needed when a single stroke is used, to prevent the segment from being drawn as a full circle - const segmentTotal = singleStroke ? total * 2 : total; + const segmentTotal = useSingleStroke ? total * 2 : total; const piePortion = (value * 100) / segmentTotal; const angleEquivalent = (piePortion * maxAngle) / 100; const gapAngle = gap / radius; @@ -84,6 +85,6 @@ export const calculateSegmentPath = ({ outerStart, radius, rotateDirection, - singleStroke, + singleStroke: useSingleStroke, }); };