11import React from 'react' ;
2- import { useAmbientTRenderEngine } from 'react-native-render-html' ;
32import type { TNode } from 'react-native-render-html' ;
3+ import { HTMLContentModel , useAmbientTRenderEngine } from 'react-native-render-html' ;
44import { Pie } from 'victory-native' ;
5+ import VictoryTheme from '@components/Charts/VictoryTheme' ;
6+ import { useVictoryChartContext } from '@components/HTMLEngineProvider/HTMLRenderers/VictoryChartRenderer/context/VictoryChartContext' ;
7+ import parseShiftedLineSegmentNode from '@components/HTMLEngineProvider/HTMLRenderers/VictoryChartRenderer/parsers/shiftedLineSegmentParser' ;
58import parseVictoryLabelNode from '@components/HTMLEngineProvider/HTMLRenderers/VictoryChartRenderer/parsers/victoryLabelParser' ;
9+ import type { PolarChartData } from '@components/HTMLEngineProvider/HTMLRenderers/VictoryChartRenderer/types' ;
10+ import convertAngleToArcLength from '@components/HTMLEngineProvider/HTMLRenderers/VictoryChartRenderer/utils/convertAngleToArcLength' ;
611import parseAttribute from '@components/HTMLEngineProvider/HTMLRenderers/VictoryChartRenderer/utils/parseAttribute' ;
712import parseComponent from '@components/HTMLEngineProvider/HTMLRenderers/VictoryChartRenderer/utils/parseComponent' ;
813import VictoryChartPieLabel from './VictoryChartPieLabel' ;
@@ -12,14 +17,41 @@ type VictoryChartPieProps = {tnode: TNode};
1217// Victory Chart's 0° angle is equivalent to 270° in Victory Native
1318const START_ANGLE = 270 ;
1419
20+ /** Alternating multipliers for pie slice label distance (base `labelradius` from HTML). */
21+ const EVEN_SLICE_LABEL_RADIUS_FACTOR = 1 ;
22+ const ODD_SLICE_LABEL_RADIUS_FACTOR = 0.8 ;
23+
1524function VictoryChartPie ( { tnode} : VictoryChartPieProps ) {
25+ const { data, chartContainerStyles} = useVictoryChartContext ( ) ;
1626 const renderEngine = useAmbientTRenderEngine ( ) ;
17- const labelComponentNode = parseComponent ( tnode . attributes . labelcomponent , renderEngine , 'victorylabel' ) ;
18- const labelItemTemplate = labelComponentNode ? parseVictoryLabelNode ( labelComponentNode ) . labelItems ?. at ( 0 ) : undefined ;
19-
27+ const labelComponentNode = parseComponent ( tnode . attributes . labelcomponent , renderEngine , 'victorylabel' , HTMLContentModel . textual ) ;
28+ const baseLabelItem = labelComponentNode ? parseVictoryLabelNode ( labelComponentNode ) . labelItems ?. at ( 0 ) : undefined ;
29+ const pieLabels = parseAttribute < string [ ] > ( tnode . attributes . labels ) ;
30+ const labelRadius = tnode . attributes . labelradius !== undefined ? Number ( parseAttribute ( tnode . attributes . labelradius ) ) : undefined ;
2031 const innerRadius = tnode . attributes . innerradius !== undefined ? Number ( parseAttribute ( tnode . attributes . innerradius ) ) : undefined ;
32+ const padAngle = tnode . attributes . padangle !== undefined ? Number ( parseAttribute ( tnode . attributes . padangle ) ) : undefined ;
2133 const radius = tnode . attributes . radius !== undefined ? Number ( parseAttribute ( tnode . attributes . radius ) ) : undefined ;
2234 const size = radius ? radius * 2 : undefined ;
35+ const angularStrokeWidth = padAngle && radius ? 2 * convertAngleToArcLength ( padAngle , radius ) : 0 ;
36+ const angularStrokeColor = typeof chartContainerStyles . backgroundColor === 'string' ? chartContainerStyles . backgroundColor : VictoryTheme . colors . default ;
37+ const labelIndicatorNode = parseComponent ( tnode . attributes . labelindicator , renderEngine , 'shiftedlinesegment' , HTMLContentModel . block ) ;
38+ const labelIndicatorStyles = labelIndicatorNode ? parseShiftedLineSegmentNode ( labelIndicatorNode ) : undefined ;
39+ const { xShift : labelIndicatorXShift , yShift : labelIndicatorYShift , stroke : labelIndicatorStroke , strokeWidth : labelIndicatorStrokeWidth } = labelIndicatorStyles ?? { } ;
40+ const labelIndicatorInnerOffset = tnode . attributes . labelindicatorinneroffset !== undefined ? Number ( parseAttribute ( tnode . attributes . labelindicatorinneroffset ) ) : undefined ;
41+ const labelIndicatorOuterOffset = tnode . attributes . labelindicatorouteroffset !== undefined ? Number ( parseAttribute ( tnode . attributes . labelindicatorouteroffset ) ) : undefined ;
42+ const perSliceData = Object . values ( data )
43+ . map ( ( entry ) => ( entry as PolarChartData ) . label )
44+ . reduce (
45+ ( slicesData , dataLabel , index ) => {
46+ // eslint-disable-next-line no-param-reassign
47+ slicesData [ dataLabel ] = {
48+ customLabel : pieLabels ?. [ index ] ,
49+ customLabelRadius : labelRadius ? labelRadius * ( index % 2 === 0 ? EVEN_SLICE_LABEL_RADIUS_FACTOR : ODD_SLICE_LABEL_RADIUS_FACTOR ) : undefined ,
50+ } ;
51+ return slicesData ;
52+ } ,
53+ { } as Record < string , { customLabelRadius : number | undefined ; customLabel : string | undefined } > ,
54+ ) ;
2355
2456 return (
2557 < Pie . Chart
@@ -28,13 +60,30 @@ function VictoryChartPie({tnode}: VictoryChartPieProps) {
2860 size = { size }
2961 >
3062 { ( { slice} ) => (
31- < Pie . Slice >
32- < VictoryChartPieLabel
33- tnode = { tnode }
34- slice = { slice }
35- labelItemTemplate = { labelItemTemplate }
63+ < >
64+ < Pie . Slice >
65+ { ! ! baseLabelItem && (
66+ < VictoryChartPieLabel
67+ slice = { slice }
68+ baseLabelItem = { baseLabelItem }
69+ label = { perSliceData [ slice . label ] . customLabel ?? slice . label }
70+ labelRadius = { perSliceData [ slice . label ] . customLabelRadius }
71+ labelIndicatorXShift = { labelIndicatorXShift }
72+ labelIndicatorYShift = { labelIndicatorYShift }
73+ labelIndicatorStroke = { labelIndicatorStroke }
74+ labelIndicatorStrokeWidth = { labelIndicatorStrokeWidth }
75+ labelIndicatorInnerOffset = { labelIndicatorInnerOffset }
76+ labelIndicatorOuterOffset = { labelIndicatorOuterOffset }
77+ />
78+ ) }
79+ </ Pie . Slice >
80+ < Pie . SliceAngularInset
81+ angularInset = { {
82+ angularStrokeWidth,
83+ angularStrokeColor,
84+ } }
3685 />
37- </ Pie . Slice >
86+ </ >
3887 ) }
3988 </ Pie . Chart >
4089 ) ;
0 commit comments