@octanejs/recharts 0.1.61 → 0.1.63

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 (73) hide show
  1. package/package.json +5 -5
  2. package/src/animation/AnimatedItems.tsrx +36 -31
  3. package/src/animation/CSSTransitionAnimate.tsrx +1 -2
  4. package/src/animation/JavascriptAnimate.tsrx +1 -2
  5. package/src/cartesian/Area.tsrx +414 -386
  6. package/src/cartesian/AreaRevealShape.tsrx +103 -84
  7. package/src/cartesian/Bar.tsrx +343 -317
  8. package/src/cartesian/BarStack.tsrx +33 -28
  9. package/src/cartesian/CartesianAxis.tsrx +168 -165
  10. package/src/cartesian/CartesianGrid.tsrx +256 -272
  11. package/src/cartesian/ErrorBar.tsrx +108 -104
  12. package/src/cartesian/Funnel.tsrx +405 -382
  13. package/src/cartesian/GraphicalItemClipPath.tsrx +4 -8
  14. package/src/cartesian/Line.tsrx +190 -177
  15. package/src/cartesian/LineDrawShape.tsrx +14 -15
  16. package/src/cartesian/ReferenceLine.tsrx +119 -105
  17. package/src/cartesian/Scatter.tsrx +416 -398
  18. package/src/cartesian/XAxis.tsrx +39 -32
  19. package/src/cartesian/YAxis.tsrx +47 -37
  20. package/src/cartesian/ZAxis.tsrx +76 -73
  21. package/src/chart/AreaChart.tsrx +15 -11
  22. package/src/chart/BarChart.tsrx +15 -11
  23. package/src/chart/CategoricalChart.tsrx +32 -26
  24. package/src/chart/ComposedChart.tsrx +15 -11
  25. package/src/chart/FunnelChart.tsrx +15 -11
  26. package/src/chart/LineChart.tsrx +15 -11
  27. package/src/chart/PieChart.tsrx +15 -11
  28. package/src/chart/PolarChart.tsrx +45 -48
  29. package/src/chart/RadarChart.tsrx +38 -32
  30. package/src/chart/RadialBarChart.tsrx +15 -11
  31. package/src/chart/RechartsWrapper.tsrx +214 -162
  32. package/src/chart/Sankey.tsrx +412 -378
  33. package/src/chart/ScatterChart.tsrx +15 -11
  34. package/src/chart/SunburstChart.tsrx +162 -155
  35. package/src/component/ActivePoints.tsrx +19 -13
  36. package/src/component/Cursor.tsrx +25 -18
  37. package/src/component/DefaultLegendContent.tsrx +131 -127
  38. package/src/component/DefaultTooltipContent.tsrx +46 -42
  39. package/src/component/Dots.tsrx +11 -5
  40. package/src/component/Label.tsrx +69 -55
  41. package/src/component/LabelList.tsrx +32 -27
  42. package/src/component/Legend.tsrx +120 -123
  43. package/src/component/ResponsiveContainer.tsrx +18 -11
  44. package/src/component/Text.tsrx +50 -43
  45. package/src/component/Tooltip.tsrx +234 -223
  46. package/src/component/TooltipBoundingBox.tsrx +34 -34
  47. package/src/container/ClipPathProvider.tsrx +1 -3
  48. package/src/container/Layer.tsrx +5 -1
  49. package/src/container/RootSurface.tsrx +31 -21
  50. package/src/container/Surface.tsrx +15 -13
  51. package/src/context/ErrorBarContext.tsrx +5 -5
  52. package/src/polar/Pie.tsrx +541 -487
  53. package/src/polar/PolarAngleAxis.tsrx +245 -227
  54. package/src/polar/PolarGrid.tsrx +139 -127
  55. package/src/polar/PolarRadiusAxis.tsrx +204 -185
  56. package/src/polar/Radar.tsrx +274 -264
  57. package/src/polar/RadialBar.tsrx +408 -361
  58. package/src/shape/Cross.tsrx +13 -7
  59. package/src/shape/Curve.tsrx +54 -44
  60. package/src/shape/Dot.tsrx +10 -8
  61. package/src/shape/Polygon.tsrx +38 -29
  62. package/src/shape/Rectangle.tsrx +73 -28
  63. package/src/shape/Sector.tsrx +30 -18
  64. package/src/shape/Symbols.tsrx +13 -11
  65. package/src/shape/Trapezoid.tsrx +16 -11
  66. package/src/state/RechartsStoreProvider.tsrx +5 -1
  67. package/src/synchronisation/useChartSynchronisation.tsrx +8 -7
  68. package/src/util/BarUtils.tsrx +43 -40
  69. package/src/util/FunnelUtils.tsrx +5 -5
  70. package/src/util/RadialBarUtils.tsrx +3 -4
  71. package/src/util/ScatterUtils.tsrx +13 -8
  72. package/src/zIndex/ZIndexLayer.tsrx +2 -2
  73. package/src/zIndex/ZIndexPortal.tsrx +2 -8
@@ -69,8 +69,8 @@ import { SetLegendPayload } from '../state/SetLegendPayload';
69
69
  import { CellsContext, useCellRegistry } from '../context/CellsContext';
70
70
  import { useCartesianChartLayout } from '../context/chartLayoutContext';
71
71
 
72
- export type FunnelTrapezoidItem =
73
- TrapezoidProps & TrapezoidViewBox & {
72
+ export type FunnelTrapezoidItem = TrapezoidProps &
73
+ TrapezoidViewBox & {
74
74
  value?: number | string;
75
75
  payload?: any;
76
76
  tooltipPosition: Coordinate;
@@ -84,247 +84,258 @@ export type FunnelTrapezoidItem =
84
84
  /**
85
85
  * Internal props, combination of external props + defaultProps + private Recharts state
86
86
  */
87
- type InternalFunnelProps =
88
- RequiresDefaultProps<FunnelProps, typeof defaultFunnelProps> & {
89
- id: GraphicalItemId;
90
- trapezoids: ReadonlyArray<FunnelTrapezoidItem>;
91
- };
87
+ type InternalFunnelProps = RequiresDefaultProps<FunnelProps, typeof defaultFunnelProps> & {
88
+ id: GraphicalItemId;
89
+ trapezoids: ReadonlyArray<FunnelTrapezoidItem>;
90
+ };
92
91
 
93
92
  /**
94
93
  * External props, intended for end users to fill in
95
94
  */
96
- interface FunnelProps<DataPointType = any, DataValueType = any> extends DataProvider<
97
- DataPointType
98
- >, Required<DataConsumer<DataPointType, DataValueType>> {
95
+ interface FunnelProps<DataPointType = any, DataValueType = any>
96
+ extends DataProvider<DataPointType>, Required<DataConsumer<DataPointType, DataValueType>> {
99
97
  /**
100
- * This component is rendered when this graphical item is activated
101
- * (could be by mouse hover, touch, keyboard, programmatically).
102
- */
98
+ * This component is rendered when this graphical item is activated
99
+ * (could be by mouse hover, touch, keyboard, programmatically).
100
+ */
103
101
  activeShape?: ActiveShape<FunnelTrapezoidItem, SVGPathElement>;
104
102
  /**
105
- * Specifies when the animation should begin, the unit of this option is ms.
106
- * @defaultValue 400
107
- */
103
+ * Specifies when the animation should begin, the unit of this option is ms.
104
+ * @defaultValue 400
105
+ */
108
106
  animationBegin?: number;
109
107
  /**
110
- * Specifies the duration of animation, the unit of this option is ms.
111
- * @defaultValue 1500
112
- */
108
+ * Specifies the duration of animation, the unit of this option is ms.
109
+ * @defaultValue 1500
110
+ */
113
111
  animationDuration?: AnimationDuration;
114
112
  /**
115
- * The type of easing function.
116
- * @defaultValue ease
117
- */
113
+ * The type of easing function.
114
+ * @defaultValue ease
115
+ */
118
116
  animationEasing?: EasingInput;
119
117
  /**
120
- * Custom animation function for interpolating data items.
121
- * When provided, this replaces the default animation interpolation.
122
- *
123
- * @param prevItems The items from the previous animation frame, or null on first render
124
- * @param nextItems The target items to animate towards
125
- * @param animationElapsedTime A normalized time value (0 = start, 1 = end)
126
- * @returns The interpolated items at time animationElapsedTime
127
- *
128
- * @since 3.9
129
- * @see {@link https://recharts.github.io/en-US/guide/animations/ Animations guide}
130
- */
118
+ * Custom animation function for interpolating data items.
119
+ * When provided, this replaces the default animation interpolation.
120
+ *
121
+ * @param prevItems The items from the previous animation frame, or null on first render
122
+ * @param nextItems The target items to animate towards
123
+ * @param animationElapsedTime A normalized time value (0 = start, 1 = end)
124
+ * @returns The interpolated items at time animationElapsedTime
125
+ *
126
+ * @since 3.9
127
+ * @see {@link https://recharts.github.io/en-US/guide/animations/ Animations guide}
128
+ */
131
129
  animationInterpolateFn?: AnimationInterpolateFn<FunnelTrapezoidItem, CartesianLayout>;
132
130
  /**
133
- * Strategy for matching previous items to next items during animation.
134
- * Determines how Recharts pairs old data points with new data points
135
- * to create smooth transitions.
136
- *
137
- * - `matchAppend` (default): match sequentially by index and treat newly appended items as new
138
- * - `matchByIndex`: match by array position with proportional stretching
139
- * - `matchByDataKey('someKey')`: match by a data key from the payload
140
- * - Custom function `(item, index) => key`: match by the returned key
141
- *
142
- * @defaultValue append
143
- * @see matchByIndex
144
- * @see matchByDataKey
145
- * @see matchAppend
146
- *
147
- * @since 3.9
148
- * @see {@link https://recharts.github.io/en-US/guide/animations/ Animations guide}
149
- */
131
+ * Strategy for matching previous items to next items during animation.
132
+ * Determines how Recharts pairs old data points with new data points
133
+ * to create smooth transitions.
134
+ *
135
+ * - `matchAppend` (default): match sequentially by index and treat newly appended items as new
136
+ * - `matchByIndex`: match by array position with proportional stretching
137
+ * - `matchByDataKey('someKey')`: match by a data key from the payload
138
+ * - Custom function `(item, index) => key`: match by the returned key
139
+ *
140
+ * @defaultValue append
141
+ * @see matchByIndex
142
+ * @see matchByDataKey
143
+ * @see matchAppend
144
+ *
145
+ * @since 3.9
146
+ * @see {@link https://recharts.github.io/en-US/guide/animations/ Animations guide}
147
+ */
150
148
  animationMatchBy?: AnimationMatchByProp<FunnelTrapezoidItem>;
151
149
  className?: string;
152
150
  /**
153
- * Hides the whole graphical element when true.
154
- *
155
- * Hiding an element is different from removing it from the chart:
156
- * Hidden graphical elements are still visible in Legend,
157
- * and can be included in axis domain calculations,
158
- * depending on `includeHidden` props of your XAxis/YAxis.
159
- *
160
- * @defaultValue false
161
- */
151
+ * Hides the whole graphical element when true.
152
+ *
153
+ * Hiding an element is different from removing it from the chart:
154
+ * Hidden graphical elements are still visible in Legend,
155
+ * and can be included in axis domain calculations,
156
+ * depending on `includeHidden` props of your XAxis/YAxis.
157
+ *
158
+ * @defaultValue false
159
+ */
162
160
  hide?: boolean;
163
161
  /**
164
- * Unique identifier of this component.
165
- * Used as an HTML attribute `id`, and also to identify this element internally.
166
- *
167
- * If undefined, Recharts will generate a unique ID automatically.
168
- */
162
+ * Unique identifier of this component.
163
+ * Used as an HTML attribute `id`, and also to identify this element internally.
164
+ *
165
+ * If undefined, Recharts will generate a unique ID automatically.
166
+ */
169
167
  id?: string;
170
168
  /**
171
- * If set false, animation of funnel will be disabled.
172
- * If set "auto", the animation will be disabled in SSR and will respect the user's prefers-reduced-motion system preference for accessibility.
173
- * @defaultValue auto
174
- */
169
+ * If set false, animation of funnel will be disabled.
170
+ * If set "auto", the animation will be disabled in SSR and will respect the user's prefers-reduced-motion system preference for accessibility.
171
+ * @defaultValue auto
172
+ */
175
173
  isAnimationActive?: boolean | 'auto';
176
174
  label?: ImplicitLabelListType;
177
175
  /**
178
- * @defaultValue triangle
179
- */
176
+ * @defaultValue triangle
177
+ */
180
178
  lastShapeType?: 'triangle' | 'rectangle';
181
179
  /**
182
- * The type of icon in legend. If set to 'none', no legend item will be rendered.
183
- * @defaultValue rect
184
- */
180
+ * The type of icon in legend. If set to 'none', no legend item will be rendered.
181
+ * @defaultValue rect
182
+ */
185
183
  legendType?: LegendType;
186
184
  /**
187
- * Name represents each sector in the tooltip.
188
- * This allows you to extract the name from the data:
189
- *
190
- * - `string`: the name of the field in the data object;
191
- * - `number`: the index of the field in the data;
192
- * - `function`: a function that receives the data object and returns the name.
193
- *
194
- * @defaultValue name
195
- */
185
+ * Name represents each sector in the tooltip.
186
+ * This allows you to extract the name from the data:
187
+ *
188
+ * - `string`: the name of the field in the data object;
189
+ * - `number`: the index of the field in the data;
190
+ * - `function`: a function that receives the data object and returns the name.
191
+ *
192
+ * @defaultValue name
193
+ */
196
194
  nameKey?: DataKey<DataPointType, DataValueType>;
197
195
  /**
198
- * The customized event handler of animation end
199
- */
196
+ * The customized event handler of animation end
197
+ */
200
198
  onAnimationEnd?: () => void;
201
199
  /**
202
- * The customized event handler of animation start
203
- */
200
+ * The customized event handler of animation start
201
+ */
204
202
  onAnimationStart?: () => void;
205
203
  reversed?: boolean;
206
204
  /**
207
- * If set a OctaneElement, the shape of funnel can be customized.
208
- * If set a function, the function will be called to render customized shape.
209
- * During animations, the function shape also receives `animationElapsedTime`, `isAnimating`, and `isEntrance`.
210
- * By default, renders a trapezoid.
211
- */
205
+ * If set a OctaneElement, the shape of funnel can be customized.
206
+ * If set a function, the function will be called to render customized shape.
207
+ * During animations, the function shape also receives `animationElapsedTime`, `isAnimating`, and `isEntrance`.
208
+ * By default, renders a trapezoid.
209
+ */
212
210
  shape?: ActiveShape<FunnelTrapezoidItem & ShapeAnimationProps, SVGPathElement>;
213
211
  tooltipType?: TooltipType;
214
212
  /**
215
- * Formats the value displayed in the tooltip for this Funnel.
216
- * When set, takes precedence over the `formatter` prop on the Tooltip component.
217
- */
213
+ * Formats the value displayed in the tooltip for this Funnel.
214
+ * When set, takes precedence over the `formatter` prop on the Tooltip component.
215
+ */
218
216
  formatter?: Formatter;
219
217
  /**
220
- * The customized event handler of click on the area in this group
221
- */
218
+ * The customized event handler of click on the area in this group
219
+ */
222
220
  onClick?: (data: FunnelTrapezoidItem, index: number, e: NativeMouseEvent<SVGGElement>) => void;
223
221
  /**
224
- * The customized event handler of mousedown on the area in this group
225
- */
226
- onMouseDown?: (data: FunnelTrapezoidItem, index: number, e: NativeMouseEvent<
227
- SVGGElement
228
- >) => void;
222
+ * The customized event handler of mousedown on the area in this group
223
+ */
224
+ onMouseDown?: (
225
+ data: FunnelTrapezoidItem,
226
+ index: number,
227
+ e: NativeMouseEvent<SVGGElement>,
228
+ ) => void;
229
229
  /**
230
- * The customized event handler of mouseup on the area in this group
231
- */
230
+ * The customized event handler of mouseup on the area in this group
231
+ */
232
232
  onMouseUp?: (data: FunnelTrapezoidItem, index: number, e: NativeMouseEvent<SVGGElement>) => void;
233
233
  /**
234
- * The customized event handler of mousemove on the area in this group
235
- */
236
- onMouseMove?: (data: FunnelTrapezoidItem, index: number, e: NativeMouseEvent<
237
- SVGGElement
238
- >) => void;
234
+ * The customized event handler of mousemove on the area in this group
235
+ */
236
+ onMouseMove?: (
237
+ data: FunnelTrapezoidItem,
238
+ index: number,
239
+ e: NativeMouseEvent<SVGGElement>,
240
+ ) => void;
239
241
  /**
240
- * The customized event handler of mouseover on the area in this group
241
- */
242
- onMouseOver?: (data: FunnelTrapezoidItem, index: number, e: NativeMouseEvent<
243
- SVGGElement
244
- >) => void;
242
+ * The customized event handler of mouseover on the area in this group
243
+ */
244
+ onMouseOver?: (
245
+ data: FunnelTrapezoidItem,
246
+ index: number,
247
+ e: NativeMouseEvent<SVGGElement>,
248
+ ) => void;
245
249
  /**
246
- * The customized event handler of mouseout on the area in this group
247
- */
250
+ * The customized event handler of mouseout on the area in this group
251
+ */
248
252
  onMouseOut?: (data: FunnelTrapezoidItem, index: number, e: NativeMouseEvent<SVGGElement>) => void;
249
253
  /**
250
- * The customized event handler of mouseenter on the area in this group
251
- */
252
- onMouseEnter?: (data: FunnelTrapezoidItem, index: number, e: NativeMouseEvent<
253
- SVGGElement
254
- >) => void;
254
+ * The customized event handler of mouseenter on the area in this group
255
+ */
256
+ onMouseEnter?: (
257
+ data: FunnelTrapezoidItem,
258
+ index: number,
259
+ e: NativeMouseEvent<SVGGElement>,
260
+ ) => void;
255
261
  /**
256
- * The customized event handler of mouseleave on the area in this group
257
- */
258
- onMouseLeave?: (data: FunnelTrapezoidItem, index: number, e: NativeMouseEvent<
259
- SVGGElement
260
- >) => void;
262
+ * The customized event handler of mouseleave on the area in this group
263
+ */
264
+ onMouseLeave?: (
265
+ data: FunnelTrapezoidItem,
266
+ index: number,
267
+ e: NativeMouseEvent<SVGGElement>,
268
+ ) => void;
261
269
  }
262
270
 
263
- type FunnelSvgProps =
264
- Omit<PresentationAttributesAdaptChildEvent<FunnelTrapezoidItem, SVGPathElement>, 'ref'>;
271
+ type FunnelSvgProps = Omit<
272
+ PresentationAttributesAdaptChildEvent<FunnelTrapezoidItem, SVGPathElement>,
273
+ 'ref'
274
+ >;
265
275
 
266
276
  type InternalProps = FunnelSvgProps & InternalFunnelProps;
267
277
 
268
- export type Props<DataPointType = any, DataValueType = any> =
269
- FunnelSvgProps & FunnelProps<DataPointType, DataValueType>;
278
+ export type Props<DataPointType = any, DataValueType = any> = FunnelSvgProps &
279
+ FunnelProps<DataPointType, DataValueType>;
270
280
 
271
281
  type RealFunnelData = unknown;
272
282
 
273
- type FunnelTrapezoidsProps =
274
- ShapeAnimationProps & {
275
- trapezoids: ReadonlyArray<FunnelTrapezoidItem>;
276
- allOtherFunnelProps: InternalProps;
277
- };
283
+ type FunnelTrapezoidsProps = ShapeAnimationProps & {
284
+ trapezoids: ReadonlyArray<FunnelTrapezoidItem>;
285
+ allOtherFunnelProps: InternalProps;
286
+ };
278
287
 
279
- const SetFunnelTooltipEntrySettings = React.memo(({
280
- dataKey,
281
- nameKey,
282
- stroke,
283
- strokeWidth,
284
- fill,
285
- name,
286
- hide,
287
- tooltipType,
288
- formatter,
289
- data,
290
- trapezoids,
291
- id,
292
- }: Pick<
293
- InternalProps,
294
- | 'dataKey'
295
- | 'nameKey'
296
- | 'stroke'
297
- | 'strokeWidth'
298
- | 'fill'
299
- | 'name'
300
- | 'hide'
301
- | 'tooltipType'
302
- | 'formatter'
303
- | 'data'
304
- | 'id'
305
- > & {
306
- trapezoids: ReadonlyArray<FunnelTrapezoidItem> | undefined;
307
- }) => {
308
- const tooltipEntrySettings: TooltipPayloadConfiguration = {
309
- dataDefinedOnItem: data,
310
- getPosition: (index) => trapezoids?.[Number(index)]?.tooltipPosition,
311
- settings: {
312
- stroke,
313
- strokeWidth,
314
- fill,
315
- dataKey,
316
- name,
317
- nameKey,
318
- hide,
319
- type: tooltipType,
320
- color: fill,
321
- unit: '', // Funnel does not have unit, why?
322
- formatter,
323
- graphicalItemId: id,
324
- },
325
- };
326
- return <SetTooltipEntrySettings tooltipEntrySettings={tooltipEntrySettings} />;
327
- });
288
+ const SetFunnelTooltipEntrySettings = React.memo(
289
+ ({
290
+ dataKey,
291
+ nameKey,
292
+ stroke,
293
+ strokeWidth,
294
+ fill,
295
+ name,
296
+ hide,
297
+ tooltipType,
298
+ formatter,
299
+ data,
300
+ trapezoids,
301
+ id,
302
+ }: Pick<
303
+ InternalProps,
304
+ | 'dataKey'
305
+ | 'nameKey'
306
+ | 'stroke'
307
+ | 'strokeWidth'
308
+ | 'fill'
309
+ | 'name'
310
+ | 'hide'
311
+ | 'tooltipType'
312
+ | 'formatter'
313
+ | 'data'
314
+ | 'id'
315
+ > & {
316
+ trapezoids: ReadonlyArray<FunnelTrapezoidItem> | undefined;
317
+ }) => {
318
+ const tooltipEntrySettings: TooltipPayloadConfiguration = {
319
+ dataDefinedOnItem: data,
320
+ getPosition: (index) => trapezoids?.[Number(index)]?.tooltipPosition,
321
+ settings: {
322
+ stroke,
323
+ strokeWidth,
324
+ fill,
325
+ dataKey,
326
+ name,
327
+ nameKey,
328
+ hide,
329
+ type: tooltipType,
330
+ color: fill,
331
+ unit: '', // Funnel does not have unit, why?
332
+ formatter,
333
+ graphicalItemId: id,
334
+ },
335
+ };
336
+ return <SetTooltipEntrySettings tooltipEntrySettings={tooltipEntrySettings} />;
337
+ },
338
+ );
328
339
 
329
340
  function FunnelLabelListProvider({
330
341
  showLabels,
@@ -353,15 +364,17 @@ function FunnelLabelListProvider({
353
364
  });
354
365
  }, [showLabels, trapezoids]);
355
366
 
356
- return <CartesianLabelListContextProvider
357
- value={labelListEntries}
358
- >{children}</CartesianLabelListContextProvider>;
367
+ return (
368
+ <CartesianLabelListContextProvider value={labelListEntries}>
369
+ {children}
370
+ </CartesianLabelListContextProvider>
371
+ );
359
372
  }
360
373
 
361
374
  function FunnelTrapezoids(props: FunnelTrapezoidsProps) {
362
375
  const { trapezoids, allOtherFunnelProps, animationElapsedTime, isAnimating, isEntrance } = props;
363
- const activeItemIndex = useAppSelector(
364
- (state) => selectActiveIndex(state, 'item', state.tooltip.settings.trigger, undefined),
376
+ const activeItemIndex = useAppSelector((state) =>
377
+ selectActiveIndex(state, 'item', state.tooltip.settings.trigger, undefined),
365
378
  );
366
379
  const {
367
380
  onMouseEnter: onMouseEnterFromProps,
@@ -384,32 +397,36 @@ function FunnelTrapezoids(props: FunnelTrapezoidsProps) {
384
397
  allOtherFunnelProps.id,
385
398
  );
386
399
 
387
- return <>
388
- {trapezoids.map((entry: FunnelTrapezoidItem, i: number) => {
389
- const isActiveIndex = Boolean(activeShape) && activeItemIndex === String(i);
390
- const trapezoidOptions = isActiveIndex ? activeShape : shape;
391
- const { id, ...trapezoidProps }: FunnelTrapezoidProps = {
392
- ...entry,
393
- option: trapezoidOptions,
394
- isActive: isActiveIndex,
395
- stroke: entry.stroke,
396
- animationElapsedTime,
397
- isAnimating,
398
- isEntrance,
399
- };
400
-
401
- return <Layer
402
- key={`trapezoid-${entry?.x}-${entry?.y}-${entry?.name}-${entry?.value}`}
403
- className="recharts-funnel-trapezoid"
404
- {...adaptEventsOfChild(restOfAllOtherProps, entry, i)}
405
- onMouseEnter={onMouseEnterFromContext(entry, i)}
406
- onMouseLeave={onMouseLeaveFromContext(entry, i)}
407
- onClick={onClickFromContext(entry, i)}
408
- >
409
- <FunnelTrapezoid {...trapezoidProps} />
410
- </Layer>;
411
- })}
412
- </>;
400
+ return (
401
+ <>
402
+ {trapezoids.map((entry: FunnelTrapezoidItem, i: number) => {
403
+ const isActiveIndex = Boolean(activeShape) && activeItemIndex === String(i);
404
+ const trapezoidOptions = isActiveIndex ? activeShape : shape;
405
+ const { id, ...trapezoidProps }: FunnelTrapezoidProps = {
406
+ ...entry,
407
+ option: trapezoidOptions,
408
+ isActive: isActiveIndex,
409
+ stroke: entry.stroke,
410
+ animationElapsedTime,
411
+ isAnimating,
412
+ isEntrance,
413
+ };
414
+
415
+ return (
416
+ <Layer
417
+ key={`trapezoid-${entry?.x}-${entry?.y}-${entry?.name}-${entry?.value}`}
418
+ className="recharts-funnel-trapezoid"
419
+ {...adaptEventsOfChild(restOfAllOtherProps, entry, i)}
420
+ onMouseEnter={onMouseEnterFromContext(entry, i)}
421
+ onMouseLeave={onMouseLeaveFromContext(entry, i)}
422
+ onClick={onClickFromContext(entry, i)}
423
+ >
424
+ <FunnelTrapezoid {...trapezoidProps} />
425
+ </Layer>
426
+ );
427
+ })}
428
+ </>
429
+ );
413
430
  }
414
431
 
415
432
  const defaultFunnelAnimateItems: AnimationInterpolateFn<FunnelTrapezoidItem, CartesianLayout> = (
@@ -473,35 +490,39 @@ function TrapezoidsWithAnimation({
473
490
 
474
491
  if (layout == null) return null;
475
492
 
476
- return <FunnelLabelListProvider showLabels={!isAnimating} trapezoids={trapezoids}>
477
- <AnimatedItems
478
- animationInput={trapezoids}
479
- animationIdPrefix="recharts-funnel-"
480
- items={trapezoids}
481
- previousItemsRef={previousTrapezoidsRef}
482
- isAnimationActive={isAnimationActive}
483
- animationBegin={animationBegin}
484
- animationDuration={animationDuration}
485
- animationEasing={animationEasing}
486
- onAnimationStart={handleAnimationStart}
487
- onAnimationEnd={handleAnimationEnd}
488
- animationInterpolateFn={animationInterpolateFn}
489
- animationMatchBy={props.animationMatchBy}
490
- layout={layout}
491
- >
492
- {(stepData, animationElapsedTime, isEntrance) => <Layer>
493
- <FunnelTrapezoids
494
- trapezoids={stepData}
495
- allOtherFunnelProps={props}
496
- animationElapsedTime={animationElapsedTime}
497
- isAnimating={isAnimating || animationElapsedTime < 1}
498
- isEntrance={isEntrance}
499
- />
500
- </Layer>}
501
- </AnimatedItems>
502
- <LabelListFromLabelProp label={props.label} />
503
- {props.children}
504
- </FunnelLabelListProvider>;
493
+ return (
494
+ <FunnelLabelListProvider showLabels={!isAnimating} trapezoids={trapezoids}>
495
+ <AnimatedItems
496
+ animationInput={trapezoids}
497
+ animationIdPrefix="recharts-funnel-"
498
+ items={trapezoids}
499
+ previousItemsRef={previousTrapezoidsRef}
500
+ isAnimationActive={isAnimationActive}
501
+ animationBegin={animationBegin}
502
+ animationDuration={animationDuration}
503
+ animationEasing={animationEasing}
504
+ onAnimationStart={handleAnimationStart}
505
+ onAnimationEnd={handleAnimationEnd}
506
+ animationInterpolateFn={animationInterpolateFn}
507
+ animationMatchBy={props.animationMatchBy}
508
+ layout={layout}
509
+ >
510
+ {(stepData, animationElapsedTime, isEntrance) => (
511
+ <Layer>
512
+ <FunnelTrapezoids
513
+ trapezoids={stepData}
514
+ allOtherFunnelProps={props}
515
+ animationElapsedTime={animationElapsedTime}
516
+ isAnimating={isAnimating || animationElapsedTime < 1}
517
+ isEntrance={isEntrance}
518
+ />
519
+ </Layer>
520
+ )}
521
+ </AnimatedItems>
522
+ <LabelListFromLabelProp label={props.label} />
523
+ {props.children}
524
+ </FunnelLabelListProvider>
525
+ );
505
526
  }
506
527
 
507
528
  function RenderTrapezoids(props: InternalProps) {
@@ -601,20 +622,44 @@ function FunnelImpl(props: WithIdRequired<RequiresDefaultProps<Props, typeof def
601
622
  if (legendType === 'none' || !trapezoids) {
602
623
  return [];
603
624
  }
604
- return trapezoids.map(
605
- (entry) => ({
606
- inactive: hide,
607
- value: entry.name,
608
- dataKey: props.dataKey,
609
- color: typeof entry.fill === 'string' ? entry.fill : fill,
610
- type: legendType,
611
- payload: entry.payload != null && typeof entry.payload === 'object' ? entry.payload : entry,
612
- }),
613
- );
625
+ return trapezoids.map((entry) => ({
626
+ inactive: hide,
627
+ value: entry.name,
628
+ dataKey: props.dataKey,
629
+ color: typeof entry.fill === 'string' ? entry.fill : fill,
630
+ type: legendType,
631
+ payload: entry.payload != null && typeof entry.payload === 'object' ? entry.payload : entry,
632
+ }));
614
633
  }, [fill, hide, legendType, props.dataKey, trapezoids]);
615
634
 
616
635
  if (hide || !trapezoids || !trapezoids.length || !plotArea) {
617
- return <CellsContext value={cellRegistry}>
636
+ return (
637
+ <CellsContext value={cellRegistry}>
638
+ <SetLegendPayload legendPayload={legendPayload} />
639
+ <SetFunnelTooltipEntrySettings
640
+ dataKey={props.dataKey}
641
+ nameKey={props.nameKey}
642
+ stroke={props.stroke}
643
+ strokeWidth={props.strokeWidth}
644
+ fill={props.fill}
645
+ name={props.name}
646
+ hide={props.hide}
647
+ tooltipType={props.tooltipType}
648
+ formatter={props.formatter}
649
+ data={props.data}
650
+ trapezoids={trapezoids}
651
+ id={id}
652
+ />
653
+ {props.children}
654
+ </CellsContext>
655
+ );
656
+ }
657
+ const { height, width } = plotArea;
658
+
659
+ const layerClass = clsx('recharts-trapezoids', props.className);
660
+
661
+ return (
662
+ <CellsContext value={cellRegistry}>
618
663
  <SetLegendPayload legendPayload={legendPayload} />
619
664
  <SetFunnelTooltipEntrySettings
620
665
  dataKey={props.dataKey}
@@ -630,49 +675,27 @@ function FunnelImpl(props: WithIdRequired<RequiresDefaultProps<Props, typeof def
630
675
  trapezoids={trapezoids}
631
676
  id={id}
632
677
  />
633
- {props.children}
634
- </CellsContext>;
635
- }
636
- const { height, width } = plotArea;
637
-
638
- const layerClass = clsx('recharts-trapezoids', props.className);
639
-
640
- return <CellsContext value={cellRegistry}>
641
- <SetLegendPayload legendPayload={legendPayload} />
642
- <SetFunnelTooltipEntrySettings
643
- dataKey={props.dataKey}
644
- nameKey={props.nameKey}
645
- stroke={props.stroke}
646
- strokeWidth={props.strokeWidth}
647
- fill={props.fill}
648
- name={props.name}
649
- hide={props.hide}
650
- tooltipType={props.tooltipType}
651
- formatter={props.formatter}
652
- data={props.data}
653
- trapezoids={trapezoids}
654
- id={id}
655
- />
656
- <Layer className={layerClass}>
657
- <RenderTrapezoids
658
- {...everythingElse}
659
- id={id}
660
- stroke={stroke}
661
- fill={fill}
662
- nameKey={nameKey}
663
- lastShapeType={lastShapeType}
664
- animationBegin={animationBegin}
665
- animationDuration={animationDuration}
666
- animationEasing={animationEasing}
667
- isAnimationActive={isAnimationActive}
668
- hide={hide}
669
- legendType={legendType}
670
- height={height}
671
- width={width}
672
- trapezoids={trapezoids}
673
- />
674
- </Layer>
675
- </CellsContext>;
678
+ <Layer className={layerClass}>
679
+ <RenderTrapezoids
680
+ {...everythingElse}
681
+ id={id}
682
+ stroke={stroke}
683
+ fill={fill}
684
+ nameKey={nameKey}
685
+ lastShapeType={lastShapeType}
686
+ animationBegin={animationBegin}
687
+ animationDuration={animationDuration}
688
+ animationEasing={animationEasing}
689
+ isAnimationActive={isAnimationActive}
690
+ hide={hide}
691
+ legendType={legendType}
692
+ height={height}
693
+ width={width}
694
+ trapezoids={trapezoids}
695
+ />
696
+ </Layer>
697
+ </CellsContext>
698
+ );
676
699
  }
677
700
 
678
701
  function normalizeFunnelValue(value: unknown): {
@@ -687,9 +710,8 @@ function normalizeFunnelValue(value: unknown): {
687
710
  const nextValue = value[1];
688
711
  return {
689
712
  value: typeof currentValue === 'number' && Number.isFinite(currentValue) ? currentValue : 0,
690
- rangedNextValue: typeof nextValue === 'number' && Number.isFinite(nextValue)
691
- ? nextValue
692
- : undefined,
713
+ rangedNextValue:
714
+ typeof nextValue === 'number' && Number.isFinite(nextValue) ? nextValue : undefined,
693
715
  };
694
716
  }
695
717
  return { value: 0, rangedNextValue: undefined };
@@ -717,10 +739,13 @@ export function computeFunnelTrapezoids({
717
739
  graphicalItemId: GraphicalItemId;
718
740
  }): ReadonlyArray<FunnelTrapezoidItem> {
719
741
  const { realHeight, realWidth, offsetX, offsetY } = getRealWidthHeight(customWidth, offset);
720
- const values = displayedData.map(
721
- (entry: unknown) => normalizeFunnelValue(getValueByDataKey(entry, dataKey, 0)),
742
+ const values = displayedData.map((entry: unknown) =>
743
+ normalizeFunnelValue(getValueByDataKey(entry, dataKey, 0)),
744
+ );
745
+ const maxValue = Math.max.apply(
746
+ null,
747
+ values.map((entry) => entry.value),
722
748
  );
723
- const maxValue = Math.max.apply(null, values.map((entry) => entry.value));
724
749
  const len = displayedData.length;
725
750
  const rowHeight = realHeight / len;
726
751
  const parentViewBox = {
@@ -730,88 +755,84 @@ export function computeFunnelTrapezoids({
730
755
  height: offset.height,
731
756
  };
732
757
 
733
- let trapezoids: ReadonlyArray<FunnelTrapezoidItem> = displayedData.map((
734
- entry: unknown,
735
- i: number,
736
- ): FunnelTrapezoidItem => {
737
- const name: string = String(getValueByDataKey(entry, nameKey, i));
738
- const normalizedValue = values[i];
739
- const val = normalizedValue.value;
740
- let nextVal: number;
741
-
742
- if (normalizedValue.rangedNextValue !== undefined) {
743
- nextVal = normalizedValue.rangedNextValue;
744
- } else if (i !== len - 1) {
745
- nextVal = values[i + 1].value;
746
- } else if (lastShapeType === 'rectangle') {
747
- nextVal = val;
748
- } else {
749
- nextVal = 0;
750
- }
751
-
752
- const x =
753
- maxValue === 0 ? offsetX : ((maxValue - val) * realWidth) / (2 * maxValue) + offsetX;
754
- const y = rowHeight * i + offsetY;
755
- const upperWidth =
756
- maxValue === 0 ? 0 : (val / maxValue) * realWidth;
757
- const lowerWidth =
758
- maxValue === 0 ? 0 : (nextVal / maxValue) * realWidth;
759
-
760
- const tooltipPayload: TooltipPayload = [
761
- { name, value: val, payload: entry, dataKey, type: tooltipType, graphicalItemId },
762
- ];
763
- const tooltipPosition: Coordinate = {
764
- x: x + upperWidth / 2,
765
- y: y + rowHeight / 2,
766
- };
767
-
768
- const trapezoidViewBox: TrapezoidViewBox = {
769
- x,
770
- y,
771
- upperWidth,
772
- lowerWidth,
773
- width: Math.max(upperWidth, lowerWidth),
774
- height: rowHeight,
775
- };
776
-
777
- return {
778
- ...(entry != null && typeof entry === 'object' ? omit(entry, ['width']) : {}),
779
- ...trapezoidViewBox,
780
- name,
781
- val,
782
- value: val,
783
- tooltipPayload,
784
- tooltipPosition,
785
- payload: entry,
786
- parentViewBox,
787
- labelViewBox: trapezoidViewBox,
788
- };
789
- });
758
+ let trapezoids: ReadonlyArray<FunnelTrapezoidItem> = displayedData.map(
759
+ (entry: unknown, i: number): FunnelTrapezoidItem => {
760
+ const name: string = String(getValueByDataKey(entry, nameKey, i));
761
+ const normalizedValue = values[i];
762
+ const val = normalizedValue.value;
763
+ let nextVal: number;
764
+
765
+ if (normalizedValue.rangedNextValue !== undefined) {
766
+ nextVal = normalizedValue.rangedNextValue;
767
+ } else if (i !== len - 1) {
768
+ nextVal = values[i + 1].value;
769
+ } else if (lastShapeType === 'rectangle') {
770
+ nextVal = val;
771
+ } else {
772
+ nextVal = 0;
773
+ }
774
+
775
+ const x =
776
+ maxValue === 0 ? offsetX : ((maxValue - val) * realWidth) / (2 * maxValue) + offsetX;
777
+ const y = rowHeight * i + offsetY;
778
+ const upperWidth = maxValue === 0 ? 0 : (val / maxValue) * realWidth;
779
+ const lowerWidth = maxValue === 0 ? 0 : (nextVal / maxValue) * realWidth;
780
+
781
+ const tooltipPayload: TooltipPayload = [
782
+ { name, value: val, payload: entry, dataKey, type: tooltipType, graphicalItemId },
783
+ ];
784
+ const tooltipPosition: Coordinate = {
785
+ x: x + upperWidth / 2,
786
+ y: y + rowHeight / 2,
787
+ };
790
788
 
791
- if (reversed) {
792
- trapezoids = trapezoids.map((
793
- entry: FunnelTrapezoidItem,
794
- index: number,
795
- ): FunnelTrapezoidItem => {
796
- const reversedViewBox: TrapezoidViewBox = {
797
- x: entry.x - (entry.lowerWidth - entry.upperWidth) / 2,
798
- y: entry.y - index * rowHeight + (len - 1 - index) * rowHeight,
799
- upperWidth: entry.lowerWidth,
800
- lowerWidth: entry.upperWidth,
801
- width: Math.max(entry.lowerWidth, entry.upperWidth),
789
+ const trapezoidViewBox: TrapezoidViewBox = {
790
+ x,
791
+ y,
792
+ upperWidth,
793
+ lowerWidth,
794
+ width: Math.max(upperWidth, lowerWidth),
802
795
  height: rowHeight,
803
796
  };
804
797
 
805
798
  return {
806
- ...entry,
807
- ...reversedViewBox,
808
- tooltipPosition: {
809
- ...entry.tooltipPosition,
810
- y: entry.y - index * rowHeight + (len - 1 - index) * rowHeight + rowHeight / 2,
811
- },
812
- labelViewBox: reversedViewBox,
799
+ ...(entry != null && typeof entry === 'object' ? omit(entry, ['width']) : {}),
800
+ ...trapezoidViewBox,
801
+ name,
802
+ val,
803
+ value: val,
804
+ tooltipPayload,
805
+ tooltipPosition,
806
+ payload: entry,
807
+ parentViewBox,
808
+ labelViewBox: trapezoidViewBox,
813
809
  };
814
- });
810
+ },
811
+ );
812
+
813
+ if (reversed) {
814
+ trapezoids = trapezoids.map(
815
+ (entry: FunnelTrapezoidItem, index: number): FunnelTrapezoidItem => {
816
+ const reversedViewBox: TrapezoidViewBox = {
817
+ x: entry.x - (entry.lowerWidth - entry.upperWidth) / 2,
818
+ y: entry.y - index * rowHeight + (len - 1 - index) * rowHeight,
819
+ upperWidth: entry.lowerWidth,
820
+ lowerWidth: entry.upperWidth,
821
+ width: Math.max(entry.lowerWidth, entry.upperWidth),
822
+ height: rowHeight,
823
+ };
824
+
825
+ return {
826
+ ...entry,
827
+ ...reversedViewBox,
828
+ tooltipPosition: {
829
+ ...entry.tooltipPosition,
830
+ y: entry.y - index * rowHeight + (len - 1 - index) * rowHeight + rowHeight / 2,
831
+ },
832
+ labelViewBox: reversedViewBox,
833
+ };
834
+ },
835
+ );
815
836
  }
816
837
 
817
838
  return trapezoids;
@@ -830,9 +851,11 @@ function FunnelFn<DataPointType = any, DataValueType = any>(
830
851
  outsideProps,
831
852
  defaultFunnelProps,
832
853
  );
833
- return <RegisterGraphicalItemId id={externalId} type="funnel">
834
- {(id) => <FunnelImpl {...props} id={id} />}
835
- </RegisterGraphicalItemId>;
854
+ return (
855
+ <RegisterGraphicalItemId id={externalId} type="funnel">
856
+ {(id) => <FunnelImpl {...props} id={id} />}
857
+ </RegisterGraphicalItemId>
858
+ );
836
859
  }
837
860
 
838
861
  export const Funnel = FunnelFn as typeof FunnelFn & { displayName?: string };