@octanejs/recharts 0.1.16 → 0.1.17

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (88) hide show
  1. package/package.json +4 -4
  2. package/src/animation/CSSTransitionAnimate.tsrx +142 -0
  3. package/src/cartesian/Area.tsrx +1096 -0
  4. package/src/cartesian/Area.tsrx.d.ts +340 -0
  5. package/src/cartesian/AreaRevealShape.tsrx +202 -0
  6. package/src/cartesian/CartesianGrid.tsrx +643 -0
  7. package/src/cartesian/CartesianGrid.tsrx.d.ts +219 -0
  8. package/src/cartesian/ErrorBar.tsrx +322 -0
  9. package/src/cartesian/ErrorBar.tsrx.d.ts +131 -0
  10. package/src/cartesian/Funnel.tsrx +833 -0
  11. package/src/cartesian/Funnel.tsrx.d.ts +274 -0
  12. package/src/cartesian/ReferenceLine.tsrx +452 -0
  13. package/src/cartesian/ReferenceLine.tsrx.d.ts +178 -0
  14. package/src/cartesian/Scatter.tsrx +1076 -0
  15. package/src/cartesian/Scatter.tsrx.d.ts +351 -0
  16. package/src/cartesian/ZAxis.tsrx +148 -0
  17. package/src/cartesian/ZAxis.tsrx.d.ts +102 -0
  18. package/src/chart/AreaChart.tsrx +22 -0
  19. package/src/chart/AreaChart.tsrx.d.ts +12 -0
  20. package/src/chart/ComposedChart.tsrx +22 -0
  21. package/src/chart/ComposedChart.tsrx.d.ts +12 -0
  22. package/src/chart/FunnelChart.tsrx +22 -0
  23. package/src/chart/FunnelChart.tsrx.d.ts +12 -0
  24. package/src/chart/PieChart.tsrx +31 -0
  25. package/src/chart/PieChart.tsrx.d.ts +31 -0
  26. package/src/chart/PolarChart.tsrx +121 -0
  27. package/src/chart/RadarChart.tsrx +53 -0
  28. package/src/chart/RadarChart.tsrx.d.ts +31 -0
  29. package/src/chart/RadialBarChart.tsrx +31 -0
  30. package/src/chart/RadialBarChart.tsrx.d.ts +31 -0
  31. package/src/chart/Sankey.tsrx +1542 -0
  32. package/src/chart/Sankey.tsrx.d.ts +253 -0
  33. package/src/chart/ScatterChart.tsrx +22 -0
  34. package/src/chart/ScatterChart.tsrx.d.ts +12 -0
  35. package/src/chart/SunburstChart.tsrx +495 -0
  36. package/src/chart/SunburstChart.tsrx.d.ts +146 -0
  37. package/src/chart/types.ts +19 -0
  38. package/src/component/Cursor.tsrx +157 -0
  39. package/src/component/DefaultLegendContent.tsrx +288 -0
  40. package/src/component/DefaultLegendContent.tsrx.d.ts +125 -0
  41. package/src/component/DefaultTooltipContent.tsrx +215 -0
  42. package/src/component/DefaultTooltipContent.tsrx.d.ts +87 -0
  43. package/src/component/Legend.tsrx +302 -0
  44. package/src/component/Legend.tsrx.d.ts +88 -0
  45. package/src/component/ResponsiveContainer.ts +1 -22
  46. package/src/component/ResponsiveContainer.tsrx +171 -0
  47. package/src/component/ResponsiveContainer.tsrx.d.ts +81 -0
  48. package/src/component/Tooltip.tsrx +425 -0
  49. package/src/component/Tooltip.tsrx.d.ts +246 -0
  50. package/src/component/TooltipBoundingBox.tsrx +135 -0
  51. package/src/context/CellsContext.ts +12 -0
  52. package/src/context/legendPayloadContext.tsrx +11 -0
  53. package/src/context/useTooltipAxis.ts +20 -0
  54. package/src/index.d.ts +236 -0
  55. package/src/index.ts +67 -0
  56. package/src/polar/Pie.tsrx +1224 -0
  57. package/src/polar/Pie.tsrx.d.ts +436 -0
  58. package/src/polar/PolarAngleAxis.tsrx +554 -0
  59. package/src/polar/PolarAngleAxis.tsrx.d.ts +215 -0
  60. package/src/polar/PolarGrid.tsrx +317 -0
  61. package/src/polar/PolarGrid.tsrx.d.ts +117 -0
  62. package/src/polar/PolarRadiusAxis.tsrx +463 -0
  63. package/src/polar/PolarRadiusAxis.tsrx.d.ts +209 -0
  64. package/src/polar/Radar.tsrx +696 -0
  65. package/src/polar/Radar.tsrx.d.ts +215 -0
  66. package/src/polar/RadialBar.tsrx +887 -0
  67. package/src/polar/RadialBar.tsrx.d.ts +340 -0
  68. package/src/state/ReportPolarOptions.tsrx +11 -0
  69. package/src/state/selectors/areaSelectors.ts +257 -0
  70. package/src/state/selectors/funnelSelectors.ts +86 -0
  71. package/src/state/selectors/pieSelectors.ts +134 -0
  72. package/src/state/selectors/polarGridSelectors.ts +43 -0
  73. package/src/state/selectors/polarScaleSelectors.ts +159 -0
  74. package/src/state/selectors/polarSelectors.ts +198 -0
  75. package/src/state/selectors/radarSelectors.ts +228 -0
  76. package/src/state/selectors/radialBarSelectors.ts +511 -0
  77. package/src/state/selectors/scatterSelectors.ts +168 -0
  78. package/src/util/FunnelUtils.tsrx +19 -0
  79. package/src/util/RadialBarUtils.tsrx +29 -0
  80. package/src/util/ScatterUtils.tsrx +34 -0
  81. package/src/util/cursor/getCursorPoints.ts +45 -0
  82. package/src/util/cursor/getCursorRectangle.ts +28 -0
  83. package/src/util/cursor/getRadialCursorPoints.ts +31 -0
  84. package/src/util/payload/getUniqPayload.ts +28 -0
  85. package/src/util/scale/CartesianScaleHelper.ts +71 -0
  86. package/src/util/tooltip/translate.ts +168 -0
  87. package/src/util/types.ts +3 -0
  88. package/src/util/useElementOffset.ts +147 -0
@@ -0,0 +1,554 @@
1
+ import * as React from 'octane';
2
+ import {
3
+ FunctionComponent,
4
+ ReactNode,
5
+ SVGProps,
6
+ useEffect,
7
+ useMemo,
8
+ type OctaneNode,
9
+ } from 'octane';
10
+ import { clsx } from 'clsx';
11
+ import { Layer } from '../container/Layer';
12
+ import { Dot } from '../shape/Dot';
13
+ import { Polygon } from '../shape/Polygon';
14
+ import { Text, TextAnchor, TextVerticalAnchor } from '../component/Text';
15
+ import {
16
+ adaptEventsOfChild,
17
+ AxisDomain,
18
+ AxisDomainTypeInput,
19
+ BaseTickContentProps,
20
+ EvaluatedAxisDomainType,
21
+ PresentationAttributesAdaptChildEvent,
22
+ RenderableAxisProps,
23
+ ScaleType,
24
+ TickItem,
25
+ TickProp,
26
+ } from '../util/types';
27
+ import { degreeToRadian, polarToCartesian } from '../util/PolarUtils';
28
+ import { addAngleAxis, AngleAxisSettings, removeAngleAxis } from '../state/polarAxisSlice';
29
+ import { NiceTicksAlgorithm } from '../state/cartesianAxisSlice';
30
+ import { useAppDispatch, useAppSelector } from '../state/hooks';
31
+ import {
32
+ selectPolarAngleAxisTicks,
33
+ selectPolarAxisScale,
34
+ } from '../state/selectors/polarScaleSelectors';
35
+ import { selectAngleAxis, selectPolarViewBox } from '../state/selectors/polarAxisSelectors';
36
+ import { defaultPolarAngleAxisProps } from './defaultPolarAngleAxisProps';
37
+ import { useIsPanorama } from '../context/PanoramaContext';
38
+ import {
39
+ svgPropertiesNoEvents,
40
+ svgPropertiesNoEventsFromUnknown,
41
+ } from '../util/svgPropertiesNoEvents';
42
+ import { RequiresDefaultProps, resolveDefaultProps } from '../util/resolveDefaultProps';
43
+ import { ZIndexable, ZIndexLayer } from '../zIndex/ZIndexLayer';
44
+ import { RechartsScale } from '../util/scale/RechartsScale';
45
+ import type { CustomScaleDefinition } from '../util/scale/CustomScaleDefinition';
46
+ import { usePolarChartLayout } from '../context/chartLayoutContext';
47
+ import { noop } from '../util/DataUtils';
48
+ import { getAxisTypeBasedOnLayout } from '../util/getAxisTypeBasedOnLayout';
49
+ import { getClassNameFromUnknown } from '../util/getClassNameFromUnknown';
50
+
51
+ const eps = 1e-5;
52
+ const COS_45 = Math.cos(degreeToRadian(45));
53
+
54
+ export interface PolarAngleAxisProps<DataPointType = any, DataValueType = any> extends Omit<
55
+ RenderableAxisProps<DataPointType, DataValueType>,
56
+ 'axisLine' | 'tickCount' | 'domain' | 'scale' | 'tick'
57
+ >, ZIndexable {
58
+ /**
59
+ * Controls axis line element. These are be passed as props to SVG `<line>` element representing the axis line.
60
+ * If `true` then the axis line is drawn using props of the PolarAngleAxis component.
61
+ * If `false` then the axis line is not drawn.
62
+ *
63
+ * Also see `axisLineType` prop to change the shape of the axis line.
64
+ *
65
+ * @defaultValue true
66
+ *
67
+ * @example <PolarAngleAxis axisLine={{ stroke: 'red', strokeWidth: 2 }} />
68
+ * @example <PolarAngleAxis axisLine={false} />
69
+ * @example <PolarAngleAxis stroke='red' strokeWidth={2} strokeDasharray={4} />
70
+ */
71
+ axisLine?: boolean | SVGProps<SVGLineElement>;
72
+ /**
73
+ * @defaultValue false
74
+ */
75
+ allowDecimals?: boolean;
76
+ /**
77
+ * Allow the axis has duplicated categories or not when the type of axis is "category".
78
+ * @defaultValue true
79
+ */
80
+ allowDuplicatedCategory?: boolean;
81
+ /**
82
+ * @defaultValue 0
83
+ */
84
+ angleAxisId?: string | number;
85
+ /**
86
+ * The type of axis line.
87
+ * @defaultValue polygon
88
+ */
89
+ axisLineType?: 'polygon' | 'circle';
90
+ /**
91
+ * The x-coordinate of center.
92
+ * When used inside a chart context, this prop is calculated based on the chart's dimensions,
93
+ * and this prop is ignored.
94
+ *
95
+ * This is only used when rendered outside a chart context.
96
+ */
97
+ cx?: number;
98
+ /**
99
+ * The y-coordinate of center.
100
+ * When used inside a chart context, this prop is calculated based on the chart's dimensions,
101
+ * and this prop is ignored.
102
+ *
103
+ * This is only used when rendered outside a chart context.
104
+ */
105
+ cy?: number;
106
+ /**
107
+ * The orientation of axis text.
108
+ * @defaultValue 'outer'
109
+ */
110
+ orientation?: 'inner' | 'outer';
111
+ /**
112
+ * Specify the domain of axis when the axis is a number axis.
113
+ *
114
+ * If undefined, then the domain is calculated based on the data and dataKeys.
115
+ *
116
+ * The length of domain should be 2, and we will validate the values in domain.
117
+ *
118
+ * Each element in the array can be a number, 'auto', 'dataMin', 'dataMax', a string like 'dataMin - 20', 'dataMax + 100',
119
+ * or a function that accepts a single argument and returns a number.
120
+ *
121
+ * If any element of domain is set to be 'auto', comprehensible scale ticks will be calculated, and the final domain of axis is generated by the ticks.
122
+ * If a function, receives '[dataMin, dataMax]', and must return a computed domain as '[min, max]'.
123
+ *
124
+ * @example <PolarAngleAxis type="number" domain={['dataMin', 'dataMax']} />
125
+ * @example <PolarAngleAxis type="number" domain={[0, 'dataMax']} />
126
+ * @example <PolarAngleAxis type="number" domain={['auto', 'auto']} />
127
+ * @example <PolarAngleAxis type="number" domain={[0, 'dataMax + 1000']} />
128
+ * @example <PolarAngleAxis type="number" domain={['dataMin - 100', 'dataMax + 100']} />
129
+ * @example <PolarAngleAxis type="number" domain={[dataMin => (0 - Math.abs(dataMin)), dataMax => (dataMax * 2)]} />
130
+ * @example <PolarAngleAxis type="number" domain={([dataMin, dataMax]) => { const absMax = Math.max(Math.abs(dataMin), Math.abs(dataMax)); return [-absMax, absMax]; }} />
131
+ * @example <PolarAngleAxis type="number" domain={[0, 100]} allowDataOverflow />
132
+ */
133
+ domain?: AxisDomain;
134
+ /**
135
+ * Scale function determines how data values are mapped to visual values.
136
+ * In other words, decided the mapping between data domain and coordinate range.
137
+ *
138
+ * If undefined, or 'auto', the scale function is created internally according to the type of axis and data.
139
+ *
140
+ * You can define a custom scale, either as a string shortcut to a d3 scale, or as a complete scale definition object.
141
+ *
142
+ * @defaultValue auto
143
+ * @example <PolarAngleAxis scale="log" />
144
+ * @example
145
+ * import { scaleLog } from 'd3-scale';
146
+ * const scale = scaleLog().base(Math.E);
147
+ * <PolarAngleAxis scale={scale} />
148
+ */
149
+ scale?: | ScaleType
150
+ | CustomScaleDefinition
151
+ | CustomScaleDefinition<string>
152
+ | CustomScaleDefinition<number>
153
+ | CustomScaleDefinition<Date>;
154
+ /**
155
+ * The outer radius of circle grid.
156
+ * If set a percentage, the final value is obtained by multiplying the percentage of maxRadius which is calculated by the width, height, cx, cy.
157
+ */
158
+ radius?: number | string;
159
+ /**
160
+ * Defines how the individual label text is rendered.
161
+ * This controls the settings for individual ticks; on a typical axis, there are multiple ticks, depending on your data.
162
+ *
163
+ * If you want to customize the overall axis label, use the `label` prop instead.
164
+ *
165
+ * Options:
166
+ * - `false`: Do not render any tick labels.
167
+ * - `true`: Render tick labels with default settings.
168
+ * - `object`: An object of props to be merged into the internally calculated tick props.
169
+ * - `ReactElement`: A custom React element to be used as the tick label.
170
+ * - `function`: A function that returns a React element for custom rendering of tick labels.
171
+ *
172
+ * @defaultValue true
173
+ */
174
+ tick?: TickProp<BaseTickContentProps>;
175
+ /**
176
+ * The count of axis ticks. Not used if 'type' is 'category'.
177
+ */
178
+ tickCount?: number;
179
+ /**
180
+ * Controls how Recharts calculates "nice" tick values for this axis.
181
+ * Options: `'none'`, `'auto'`, `'adaptive'`, `'snap125'`.
182
+ * See {@link NiceTicksAlgorithm} for a full description of each option.
183
+ *
184
+ * @defaultValue 'auto'
185
+ */
186
+ niceTicks?: NiceTicksAlgorithm;
187
+ /**
188
+ * The formatter function of ticks.
189
+ */
190
+ tickFormatter?: (value: any, index: number) => string;
191
+ /**
192
+ * The length of tick line.
193
+ * @defaultValue 8
194
+ */
195
+ tickSize?: number;
196
+ /**
197
+ * The array of every tick's value and angle.
198
+ */
199
+ ticks?: ReadonlyArray<TickItem>;
200
+ /**
201
+ * The type of axis.
202
+ *
203
+ * `category`: Treats data as distinct values.
204
+ * Each value is in the same distance from its neighbors, regardless of their actual numeric difference.
205
+ *
206
+ * `number`: Treats data as continuous range.
207
+ * Values that are numerically closer are placed closer together on the axis.
208
+ *
209
+ * `auto`: the type is inferred based on the chart layout.
210
+ *
211
+ * @defaultValue auto
212
+ */
213
+ type?: AxisDomainTypeInput;
214
+ /**
215
+ * Z-Index of this component and its children. The higher the value,
216
+ * the more on top it will be rendered.
217
+ * Components with higher zIndex will appear in front of components with lower zIndex.
218
+ * If undefined or 0, the content is rendered in the default layer without portals.
219
+ *
220
+ * @since 3.4
221
+ * @defaultValue 500
222
+ * @see {@link https://recharts.github.io/en-US/guide/zIndex/ Z-Index and layers guide}
223
+ */
224
+ zIndex?: number;
225
+ }
226
+
227
+ type PolarAngleAxisEvents = {
228
+ /**
229
+ * The customized event handler of click on the ticks of this axis
230
+ */
231
+ onClick?: (data: TickItem, index: number, e: React.MouseEvent<SVGTextElement>) => void;
232
+ /**
233
+ * The customized event handler of mousedown on the ticks of this axis
234
+ */
235
+ onMouseDown?: (data: TickItem, index: number, e: React.MouseEvent<SVGTextElement>) => void;
236
+ /**
237
+ * The customized event handler of mouseup on the ticks of this axis
238
+ */
239
+ onMouseUp?: (data: TickItem, index: number, e: React.MouseEvent<SVGTextElement>) => void;
240
+ /**
241
+ * The customized event handler of mousemove on the ticks of this axis
242
+ */
243
+ onMouseMove?: (data: TickItem, index: number, e: React.MouseEvent<SVGTextElement>) => void;
244
+ /**
245
+ * The customized event handler of mouseover on the ticks of this axis
246
+ */
247
+ onMouseOver?: (data: TickItem, index: number, e: React.MouseEvent<SVGTextElement>) => void;
248
+ /**
249
+ * The customized event handler of mouseout on the ticks of this axis
250
+ */
251
+ onMouseOut?: (data: TickItem, index: number, e: React.MouseEvent<SVGTextElement>) => void;
252
+ /**
253
+ * The customized event handler of mouseenter on the ticks of this axis
254
+ */
255
+ onMouseEnter?: (data: TickItem, index: number, e: React.MouseEvent<SVGTextElement>) => void;
256
+ /**
257
+ * The customized event handler of mouseleave on the ticks of this axis
258
+ */
259
+ onMouseLeave?: (data: TickItem, index: number, e: React.MouseEvent<SVGTextElement>) => void;
260
+ onTouchStart?: (data: TickItem, index: number, e: React.TouchEvent<SVGTextElement>) => void;
261
+ onTouchMove?: (data: TickItem, index: number, e: React.TouchEvent<SVGTextElement>) => void;
262
+ onTouchEnd?: (data: TickItem, index: number, e: React.TouchEvent<SVGTextElement>) => void;
263
+ };
264
+
265
+ type AxisSvgProps =
266
+ Omit<
267
+ PresentationAttributesAdaptChildEvent<TickItem, SVGTextElement>,
268
+ 'scale' | 'type' | 'dangerouslySetInnerHTML'
269
+ >;
270
+
271
+ export type Props<DataPointType = any, DataValueType = any> =
272
+ AxisSvgProps & PolarAngleAxisProps<DataPointType, DataValueType>;
273
+
274
+ type PropsWithDefaults<DataPointType = any, DataValueType = any> =
275
+ RequiresDefaultProps<Props<DataPointType, DataValueType>, typeof defaultPolarAngleAxisProps>;
276
+
277
+ type InternalPolarAngleAxisProps =
278
+ Omit<PropsWithDefaults, 'scale'> & {
279
+ cx: number;
280
+ cy: number;
281
+ radius: number;
282
+ ticks: ReadonlyArray<TickItem>;
283
+ scale: RechartsScale;
284
+ } & PolarAngleAxisEvents;
285
+
286
+ const AXIS_TYPE = 'angleAxis';
287
+
288
+ type AngleAxisSettingsReporter =
289
+ Omit<AngleAxisSettings, 'type'> & {
290
+ children: ReactNode;
291
+ type: AxisDomainTypeInput;
292
+ };
293
+
294
+ function SetAngleAxisSettings(props: AngleAxisSettingsReporter): ReactNode {
295
+ const dispatch = useAppDispatch();
296
+ const layout = usePolarChartLayout();
297
+ const settings: AngleAxisSettings | undefined = useMemo(() => {
298
+ const { children, type: typeFromProps, ...rest } = props;
299
+ const evaluatedType: EvaluatedAxisDomainType | undefined = getAxisTypeBasedOnLayout(
300
+ layout,
301
+ 'angleAxis',
302
+ typeFromProps,
303
+ );
304
+ if (evaluatedType == null) {
305
+ return undefined;
306
+ }
307
+ return { ...rest, type: evaluatedType };
308
+ }, [props, layout]);
309
+ const synchronizedSettings = useAppSelector((state) => selectAngleAxis(state, settings?.id));
310
+ const settingsAreSynchronized = settings === synchronizedSettings;
311
+ useEffect(() => {
312
+ if (settings == null) {
313
+ return noop;
314
+ }
315
+ dispatch(addAngleAxis(settings));
316
+ return () => {
317
+ dispatch(removeAngleAxis(settings));
318
+ };
319
+ }, [dispatch, settings]);
320
+
321
+ if (settingsAreSynchronized) {
322
+ return props.children;
323
+ }
324
+ return null;
325
+ }
326
+
327
+ /**
328
+ * Calculate the coordinate of line endpoint
329
+ * @param data The data if there are ticks
330
+ * @param props axis settings
331
+ * @return (x1, y1): The point close to text,
332
+ * (x2, y2): The point close to axis
333
+ */
334
+ const getTickLineCoord = (
335
+ data: TickItem,
336
+ props: InternalPolarAngleAxisProps,
337
+ ): {
338
+ x1: number;
339
+ y1: number;
340
+ x2: number;
341
+ y2: number;
342
+ } => {
343
+ const { cx, cy, radius, orientation, tickSize } = props;
344
+ const tickLineSize = tickSize || 8;
345
+ const p1 = polarToCartesian(cx, cy, radius, data.coordinate);
346
+ const p2 = polarToCartesian(
347
+ cx,
348
+ cy,
349
+ radius + (orientation === 'inner' ? -1 : 1) * tickLineSize,
350
+ data.coordinate,
351
+ );
352
+
353
+ return { x1: p1.x, y1: p1.y, x2: p2.x, y2: p2.y };
354
+ };
355
+
356
+ /**
357
+ * Get the text-anchor of each tick
358
+ * @param data Data of ticks
359
+ * @param orientation of the axis ticks
360
+ * @return text-anchor
361
+ */
362
+ const getTickTextAnchor = (data: TickItem, orientation: Props['orientation']): TextAnchor => {
363
+ const cos = Math.cos(degreeToRadian(-data.coordinate));
364
+
365
+ if (cos > eps) {
366
+ return orientation === 'outer' ? 'start' : 'end';
367
+ }
368
+ if (cos < -eps) {
369
+ return orientation === 'outer' ? 'end' : 'start';
370
+ }
371
+ return 'middle';
372
+ };
373
+
374
+ /**
375
+ * Get the text vertical anchor of each tick
376
+ * @param data Data of a tick
377
+ * @return text vertical anchor
378
+ */
379
+ const getTickTextVerticalAnchor = (data: TickItem): TextVerticalAnchor => {
380
+ const cos = Math.cos(degreeToRadian(-data.coordinate));
381
+ const sin = Math.sin(degreeToRadian(-data.coordinate));
382
+
383
+ // handle top and bottom sectors: 90±45deg and 270±45deg
384
+ if (Math.abs(cos) <= COS_45) {
385
+ // sin > 0: top sector, sin < 0: bottom sector
386
+ return sin > 0 ? 'start' : 'end';
387
+ }
388
+
389
+ return 'middle';
390
+ };
391
+
392
+ const AxisLine = (props: InternalPolarAngleAxisProps) => {
393
+ const { cx, cy, radius, axisLineType, axisLine, ticks } = props;
394
+ if (!axisLine) {
395
+ return null;
396
+ }
397
+ const axisLineProps = {
398
+ ...svgPropertiesNoEvents(props),
399
+ fill: 'none',
400
+ ...svgPropertiesNoEvents(axisLine),
401
+ };
402
+
403
+ if (axisLineType === 'circle') {
404
+ // @ts-expect-error wrong SVG element type
405
+ return <Dot
406
+ className="recharts-polar-angle-axis-line"
407
+ {...axisLineProps}
408
+ cx={cx}
409
+ cy={cy}
410
+ r={radius}
411
+ />;
412
+ }
413
+ const points = ticks.map((entry) => polarToCartesian(cx, cy, radius, entry.coordinate));
414
+
415
+ // @ts-expect-error wrong SVG element type
416
+ return <Polygon className="recharts-polar-angle-axis-line" {...axisLineProps} points={points} />;
417
+ };
418
+
419
+ type TickItemProps = {
420
+ tick: TickProp<BaseTickContentProps>;
421
+ tickProps: BaseTickContentProps;
422
+ value: string | number;
423
+ };
424
+
425
+ const TickItemText = ({ tick, tickProps, value }: TickItemProps): ReactNode => {
426
+ if (!tick) {
427
+ return null;
428
+ }
429
+ if (React.isValidElement(tick)) {
430
+ return React.cloneElement(tick, tickProps);
431
+ }
432
+ if (typeof tick === 'function') {
433
+ return tick(tickProps);
434
+ }
435
+ return <Text {...tickProps} className="recharts-polar-angle-axis-tick-value">{value}</Text>;
436
+ };
437
+
438
+ const Ticks = (props: InternalPolarAngleAxisProps) => {
439
+ const { tick, tickLine, tickFormatter, stroke, ticks } = props;
440
+ const { ref, ...axisProps } = svgPropertiesNoEvents(props);
441
+ const customTickProps = svgPropertiesNoEventsFromUnknown(tick);
442
+ const tickLineProps = {
443
+ ...axisProps,
444
+ fill: 'none',
445
+ ...svgPropertiesNoEvents(tickLine),
446
+ };
447
+
448
+ const items = ticks.map((entry, i) => {
449
+ const lineCoord = getTickLineCoord(entry, props);
450
+ const textAnchor: TextAnchor = getTickTextAnchor(entry, props.orientation);
451
+ const verticalAnchor: TextVerticalAnchor = getTickTextVerticalAnchor(entry);
452
+ const tickProps: BaseTickContentProps = {
453
+ ...axisProps,
454
+ // @ts-expect-error customTickProps is contributing unknown props
455
+ textAnchor,
456
+ verticalAnchor,
457
+ // @ts-expect-error customTickProps is contributing unknown props
458
+ stroke: 'none',
459
+ // @ts-expect-error customTickProps is contributing unknown props
460
+ fill: stroke,
461
+ ...customTickProps,
462
+ index: i,
463
+ payload: entry,
464
+ x: lineCoord.x2,
465
+ y: lineCoord.y2,
466
+ };
467
+
468
+ return <Layer
469
+ className={clsx('recharts-polar-angle-axis-tick', getClassNameFromUnknown(tick))}
470
+ key={`tick-${entry.coordinate}`}
471
+ {...adaptEventsOfChild(props, entry, i)}
472
+ >
473
+ {tickLine &&
474
+ <line className="recharts-polar-angle-axis-tick-line" {...tickLineProps} {...lineCoord} />}
475
+ <TickItemText
476
+ tick={tick}
477
+ tickProps={tickProps}
478
+ value={tickFormatter ? tickFormatter(entry.value, i) : entry.value}
479
+ />
480
+ </Layer>;
481
+ });
482
+
483
+ return <Layer className="recharts-polar-angle-axis-ticks">{items}</Layer>;
484
+ };
485
+
486
+ export const PolarAngleAxisWrapper: FunctionComponent<PropsWithDefaults> = (
487
+ defaultsAndInputs: PropsWithDefaults,
488
+ ) => {
489
+ const { angleAxisId } = defaultsAndInputs;
490
+
491
+ const viewBox = useAppSelector(selectPolarViewBox);
492
+ const scale = useAppSelector((state) => selectPolarAxisScale(state, 'angleAxis', angleAxisId));
493
+ const isPanorama = useIsPanorama();
494
+ const ticks = useAppSelector(
495
+ (state) => selectPolarAngleAxisTicks(state, 'angleAxis', angleAxisId, isPanorama),
496
+ );
497
+
498
+ if (viewBox == null || !ticks || !ticks.length || scale == null) {
499
+ return null;
500
+ }
501
+
502
+ const props: InternalPolarAngleAxisProps = {
503
+ ...defaultsAndInputs,
504
+ scale,
505
+ ...viewBox,
506
+ radius: viewBox.outerRadius,
507
+ ticks,
508
+ };
509
+
510
+ return <ZIndexLayer zIndex={props.zIndex}>
511
+ <Layer className={clsx('recharts-polar-angle-axis', AXIS_TYPE, props.className)}>
512
+ <AxisLine {...props} />
513
+ <Ticks {...props} />
514
+ </Layer>
515
+ </ZIndexLayer>;
516
+ };
517
+
518
+ /**
519
+ * @provides PolarLabelContext
520
+ * @consumes PolarViewBoxContext
521
+ */
522
+ export function PolarAngleAxis<DataPointType = any, DataValueType = any>(
523
+ outsideProps: Props<DataPointType, DataValueType>,
524
+ ): OctaneNode {
525
+ const props: PropsWithDefaults<DataPointType, DataValueType> = resolveDefaultProps(
526
+ outsideProps,
527
+ defaultPolarAngleAxisProps,
528
+ );
529
+
530
+ return <SetAngleAxisSettings
531
+ id={props.angleAxisId}
532
+ scale={props.scale}
533
+ type={props.type}
534
+ dataKey={props.dataKey}
535
+ unit={undefined}
536
+ name={props.name}
537
+ allowDuplicatedCategory={false}
538
+ // Ignoring the prop on purpose because axis calculation behaves as if it was false and Tooltip requires it to be true.
539
+ allowDataOverflow={false}
540
+ reversed={props.reversed}
541
+ includeHidden={false}
542
+ allowDecimals={props.allowDecimals}
543
+ tickCount={props.tickCount}
544
+ niceTicks={props.niceTicks ?? 'auto'}
545
+ // @ts-expect-error the type does not match. Is RadiusAxis really expecting what it says?
546
+ ticks={props.ticks}
547
+ tick={props.tick}
548
+ domain={props.domain}
549
+ >
550
+ <PolarAngleAxisWrapper {...props} />
551
+ </SetAngleAxisSettings>;
552
+ }
553
+
554
+ PolarAngleAxis.displayName = 'PolarAngleAxis';