@octanejs/recharts 0.1.62 → 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.
- package/package.json +5 -5
- package/src/animation/AnimatedItems.tsrx +36 -31
- package/src/animation/CSSTransitionAnimate.tsrx +1 -2
- package/src/animation/JavascriptAnimate.tsrx +1 -2
- package/src/cartesian/Area.tsrx +414 -386
- package/src/cartesian/AreaRevealShape.tsrx +103 -84
- package/src/cartesian/Bar.tsrx +343 -317
- package/src/cartesian/BarStack.tsrx +33 -28
- package/src/cartesian/CartesianAxis.tsrx +168 -165
- package/src/cartesian/CartesianGrid.tsrx +256 -272
- package/src/cartesian/ErrorBar.tsrx +108 -104
- package/src/cartesian/Funnel.tsrx +405 -382
- package/src/cartesian/GraphicalItemClipPath.tsrx +4 -8
- package/src/cartesian/Line.tsrx +190 -177
- package/src/cartesian/LineDrawShape.tsrx +14 -15
- package/src/cartesian/ReferenceLine.tsrx +119 -105
- package/src/cartesian/Scatter.tsrx +416 -398
- package/src/cartesian/XAxis.tsrx +39 -32
- package/src/cartesian/YAxis.tsrx +47 -37
- package/src/cartesian/ZAxis.tsrx +76 -73
- package/src/chart/AreaChart.tsrx +15 -11
- package/src/chart/BarChart.tsrx +15 -11
- package/src/chart/CategoricalChart.tsrx +32 -26
- package/src/chart/ComposedChart.tsrx +15 -11
- package/src/chart/FunnelChart.tsrx +15 -11
- package/src/chart/LineChart.tsrx +15 -11
- package/src/chart/PieChart.tsrx +15 -11
- package/src/chart/PolarChart.tsrx +45 -48
- package/src/chart/RadarChart.tsrx +38 -32
- package/src/chart/RadialBarChart.tsrx +15 -11
- package/src/chart/RechartsWrapper.tsrx +214 -162
- package/src/chart/Sankey.tsrx +412 -378
- package/src/chart/ScatterChart.tsrx +15 -11
- package/src/chart/SunburstChart.tsrx +162 -155
- package/src/component/ActivePoints.tsrx +19 -13
- package/src/component/Cursor.tsrx +25 -18
- package/src/component/DefaultLegendContent.tsrx +131 -127
- package/src/component/DefaultTooltipContent.tsrx +46 -42
- package/src/component/Dots.tsrx +11 -5
- package/src/component/Label.tsrx +69 -55
- package/src/component/LabelList.tsrx +32 -27
- package/src/component/Legend.tsrx +120 -123
- package/src/component/ResponsiveContainer.tsrx +18 -11
- package/src/component/Text.tsrx +50 -43
- package/src/component/Tooltip.tsrx +234 -223
- package/src/component/TooltipBoundingBox.tsrx +34 -34
- package/src/container/ClipPathProvider.tsrx +1 -3
- package/src/container/Layer.tsrx +5 -1
- package/src/container/RootSurface.tsrx +31 -21
- package/src/container/Surface.tsrx +15 -13
- package/src/context/ErrorBarContext.tsrx +5 -5
- package/src/polar/Pie.tsrx +541 -487
- package/src/polar/PolarAngleAxis.tsrx +245 -227
- package/src/polar/PolarGrid.tsrx +139 -127
- package/src/polar/PolarRadiusAxis.tsrx +204 -185
- package/src/polar/Radar.tsrx +274 -264
- package/src/polar/RadialBar.tsrx +408 -361
- package/src/shape/Cross.tsrx +13 -7
- package/src/shape/Curve.tsrx +54 -44
- package/src/shape/Dot.tsrx +10 -8
- package/src/shape/Polygon.tsrx +38 -29
- package/src/shape/Rectangle.tsrx +73 -28
- package/src/shape/Sector.tsrx +30 -18
- package/src/shape/Symbols.tsrx +13 -11
- package/src/shape/Trapezoid.tsrx +16 -11
- package/src/state/RechartsStoreProvider.tsrx +5 -1
- package/src/synchronisation/useChartSynchronisation.tsrx +8 -7
- package/src/util/BarUtils.tsrx +43 -40
- package/src/util/FunnelUtils.tsrx +5 -5
- package/src/util/RadialBarUtils.tsrx +3 -4
- package/src/util/ScatterUtils.tsrx +13 -8
- package/src/zIndex/ZIndexLayer.tsrx +2 -2
- 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
|
-
|
|
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
|
-
|
|
89
|
-
|
|
90
|
-
|
|
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>
|
|
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
|
-
|
|
101
|
-
|
|
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
|
-
|
|
106
|
-
|
|
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
|
-
|
|
111
|
-
|
|
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
|
-
|
|
116
|
-
|
|
117
|
-
|
|
113
|
+
* The type of easing function.
|
|
114
|
+
* @defaultValue ease
|
|
115
|
+
*/
|
|
118
116
|
animationEasing?: EasingInput;
|
|
119
117
|
/**
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
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
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
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
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
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
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
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
|
-
|
|
172
|
-
|
|
173
|
-
|
|
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
|
-
|
|
179
|
-
|
|
176
|
+
* @defaultValue triangle
|
|
177
|
+
*/
|
|
180
178
|
lastShapeType?: 'triangle' | 'rectangle';
|
|
181
179
|
/**
|
|
182
|
-
|
|
183
|
-
|
|
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
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
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
|
-
|
|
199
|
-
|
|
196
|
+
* The customized event handler of animation end
|
|
197
|
+
*/
|
|
200
198
|
onAnimationEnd?: () => void;
|
|
201
199
|
/**
|
|
202
|
-
|
|
203
|
-
|
|
200
|
+
* The customized event handler of animation start
|
|
201
|
+
*/
|
|
204
202
|
onAnimationStart?: () => void;
|
|
205
203
|
reversed?: boolean;
|
|
206
204
|
/**
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
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
|
-
|
|
216
|
-
|
|
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
|
-
|
|
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
|
-
|
|
225
|
-
|
|
226
|
-
onMouseDown?: (
|
|
227
|
-
|
|
228
|
-
|
|
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
|
-
|
|
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
|
-
|
|
235
|
-
|
|
236
|
-
onMouseMove?: (
|
|
237
|
-
|
|
238
|
-
|
|
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
|
-
|
|
241
|
-
|
|
242
|
-
onMouseOver?: (
|
|
243
|
-
|
|
244
|
-
|
|
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
|
-
|
|
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
|
-
|
|
251
|
-
|
|
252
|
-
onMouseEnter?: (
|
|
253
|
-
|
|
254
|
-
|
|
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
|
-
|
|
257
|
-
|
|
258
|
-
onMouseLeave?: (
|
|
259
|
-
|
|
260
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
};
|
|
283
|
+
type FunnelTrapezoidsProps = ShapeAnimationProps & {
|
|
284
|
+
trapezoids: ReadonlyArray<FunnelTrapezoidItem>;
|
|
285
|
+
allOtherFunnelProps: InternalProps;
|
|
286
|
+
};
|
|
278
287
|
|
|
279
|
-
const SetFunnelTooltipEntrySettings = React.memo(
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
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
|
|
357
|
-
value={labelListEntries}
|
|
358
|
-
|
|
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
|
-
|
|
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
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
...
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
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
|
|
477
|
-
<
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
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
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
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
|
|
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
|
-
{
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
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:
|
|
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
|
-
|
|
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
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
maxValue === 0 ?
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
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
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
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
|
-
...
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
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
|
|
834
|
-
|
|
835
|
-
|
|
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 };
|