@octanejs/recharts 0.1.16 → 0.1.18

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,340 @@
1
+ import * as React from 'octane';
2
+ import { ReactElement } from 'octane';
3
+ import { Series } from 'victory-vendor/d3-shape';
4
+ import { RadialBarSectorProps } from '../util/RadialBarUtils';
5
+ import { Props as SectorProps } from '../shape/Sector';
6
+ import { ImplicitLabelListType } from '../component/LabelList';
7
+ import { BarPositionPosition } from '../util/ChartUtils';
8
+ import {
9
+ ActiveShape,
10
+ AnimationDuration,
11
+ EasingInput,
12
+ DataConsumer,
13
+ DataKey,
14
+ LayoutType,
15
+ LegendType,
16
+ PolarViewBoxRequired,
17
+ PresentationAttributesAdaptChildEvent,
18
+ TickItem,
19
+ TooltipType,
20
+ PolarLayout,
21
+ } from '../util/types';
22
+ import { TooltipTriggerInfo } from '../context/tooltipContext';
23
+ import { Formatter } from '../component/DefaultTooltipContent';
24
+ import { BaseAxisWithScale } from '../state/selectors/axisSelectors';
25
+ import { ChartData } from '../state/chartDataSlice';
26
+ import { AnimationInterpolateFn } from '../animation/AnimatedItems';
27
+ import { AnimationMatchByProp } from '../animation/matchBy';
28
+ import { AxisId } from '../state/cartesianAxisSlice';
29
+ import { ZIndexable } from '../zIndex/ZIndexLayer';
30
+ export type RadialBarDataItem = SectorProps &
31
+ PolarViewBoxRequired &
32
+ TooltipTriggerInfo & {
33
+ value?: any;
34
+ payload?: any;
35
+ background?: SectorProps;
36
+ };
37
+ type RadialBarBackground = boolean | (ActiveShape<SectorProps> & ZIndexable);
38
+ interface InternalRadialBarProps<DataPointType = any, DataValueType = any>
39
+ extends DataConsumer<DataPointType, DataValueType>, ZIndexable {
40
+ activeShape?: ActiveShape<RadialBarSectorProps, SVGPathElement>;
41
+ /**
42
+ * @defaultValue 0
43
+ */
44
+ angleAxisId?: AxisId;
45
+ /**
46
+ * Specifies when the animation should begin, the unit of this option is ms.
47
+ * @defaultValue 0
48
+ */
49
+ animationBegin?: number;
50
+ /**
51
+ * Specifies the duration of animation, the unit of this option is ms.
52
+ * @defaultValue 1500
53
+ */
54
+ animationDuration?: AnimationDuration;
55
+ /**
56
+ * The type of easing function.
57
+ * @defaultValue ease
58
+ */
59
+ animationEasing?: EasingInput;
60
+ /**
61
+ * Custom animation function for interpolating data items.
62
+ * When provided, this replaces the default animation interpolation.
63
+ *
64
+ * @param prevItems The items from the previous animation frame, or null on first render
65
+ * @param nextItems The target items to animate towards
66
+ * @param animationElapsedTime A normalized time value (0 = start, 1 = end)
67
+ * @returns The interpolated items at time animationElapsedTime
68
+ *
69
+ * @since 3.9
70
+ * @see {@link https://recharts.github.io/en-US/guide/animations/ Animations guide}
71
+ */
72
+ animationInterpolateFn?: AnimationInterpolateFn<RadialBarDataItem, PolarLayout>;
73
+ /**
74
+ * Strategy for matching previous items to next items during animation.
75
+ * Determines how Recharts pairs old data points with new data points
76
+ * to create smooth transitions.
77
+ *
78
+ * - `matchAppend` (default): match sequentially by index and treat newly appended items as new
79
+ * - `matchByIndex`: match by array position with proportional stretching
80
+ * - `matchByDataKey('someKey')`: match by a data key from the payload
81
+ * - Custom function `(item, index) => key`: match by the returned key
82
+ *
83
+ * @defaultValue append
84
+ * @see matchByIndex
85
+ * @see matchByDataKey
86
+ * @see matchAppend
87
+ */
88
+ animationMatchBy?: AnimationMatchByProp<RadialBarDataItem>;
89
+ /**
90
+ * Renders a background for each bar. Options:
91
+ * - `false`: no background;
92
+ * - `true`: renders default background;
93
+ * - `object`: the props of background rectangle;
94
+ * - `ReactElement`: a custom background element;
95
+ * - `function`: a render function of custom background.
96
+ *
97
+ * @defaultValue false
98
+ */
99
+ background?: RadialBarBackground;
100
+ /**
101
+ * The width or height of each bar. If the barSize is not specified, the size of the bar will be calculated by the barCategoryGap, barGap and the quantity of bar groups.
102
+ */
103
+ barSize?: number;
104
+ className?: string;
105
+ /**
106
+ * @defaultValue false
107
+ */
108
+ cornerIsExternal?: boolean;
109
+ /**
110
+ * @defaultValue 0
111
+ */
112
+ cornerRadius?: string | number;
113
+ /**
114
+ * Calculated radial bar sectors
115
+ */
116
+ sectors: ReadonlyArray<RadialBarDataItem>;
117
+ /**
118
+ * @defaultValue false
119
+ */
120
+ forceCornerRadius?: boolean;
121
+ /**
122
+ * @defaultValue false
123
+ */
124
+ hide?: boolean;
125
+ /**
126
+ * If set false, animation of radial bars will be disabled.
127
+ * If set "auto", the animation will be disabled in SSR and will respect the user's prefers-reduced-motion system preference for accessibility.
128
+ * @defaultValue auto
129
+ */
130
+ isAnimationActive?: boolean | 'auto';
131
+ /**
132
+ * Renders one label for each data point. Options:
133
+ * - `true`: renders default labels;
134
+ * - `false`: no labels are rendered;
135
+ * - `object`: the props of LabelList component;
136
+ * - `ReactElement`: a custom SVG label element, such as `<text>` or `<g>`.
137
+ * HTML elements such as `<div>` are not valid inside the chart SVG and may trigger React DOM warnings.
138
+ * - `function`: a render function of custom label.
139
+ *
140
+ * @defaultValue false
141
+ */
142
+ label?: ImplicitLabelListType;
143
+ /**
144
+ * The type of icon in legend. If set to 'none', no legend item will be rendered.
145
+ * @defaultValue rect
146
+ */
147
+ legendType?: LegendType;
148
+ maxBarSize?: number;
149
+ /**
150
+ * @defaultValue 0
151
+ */
152
+ minPointSize?: number;
153
+ /**
154
+ * The customized event handler of animation end
155
+ */
156
+ onAnimationEnd?: () => void;
157
+ /**
158
+ * The customized event handler of animation start
159
+ */
160
+ onAnimationStart?: () => void;
161
+ /**
162
+ * The customized event handler of click in this chart.
163
+ */
164
+ onClick?: (
165
+ data: RadialBarDataItem,
166
+ index: number,
167
+ e: React.MouseEvent<SVGGraphicsElement>,
168
+ ) => void;
169
+ /**
170
+ * The customized event handler of mousedown in this chart.
171
+ */
172
+ onMouseDown?: (
173
+ data: RadialBarDataItem,
174
+ index: number,
175
+ e: React.MouseEvent<SVGGraphicsElement>,
176
+ ) => void;
177
+ /**
178
+ * The customized event handler of mouseup in this chart.
179
+ */
180
+ onMouseUp?: (
181
+ data: RadialBarDataItem,
182
+ index: number,
183
+ e: React.MouseEvent<SVGGraphicsElement>,
184
+ ) => void;
185
+ /**
186
+ * The customized event handler of mousemove in this chart.
187
+ */
188
+ onMouseMove?: (
189
+ data: RadialBarDataItem,
190
+ index: number,
191
+ e: React.MouseEvent<SVGGraphicsElement>,
192
+ ) => void;
193
+ /**
194
+ * The customized event handler of mouseover in this chart.
195
+ */
196
+ onMouseOver?: (
197
+ data: RadialBarDataItem,
198
+ index: number,
199
+ e: React.MouseEvent<SVGGraphicsElement>,
200
+ ) => void;
201
+ /**
202
+ * The customized event handler of mouseout in this chart.
203
+ */
204
+ onMouseOut?: (
205
+ data: RadialBarDataItem,
206
+ index: number,
207
+ e: React.MouseEvent<SVGGraphicsElement>,
208
+ ) => void;
209
+ /**
210
+ * The customized event handler of mouseenter in this chart.
211
+ */
212
+ onMouseEnter?: (
213
+ data: RadialBarDataItem,
214
+ index: number,
215
+ e: React.MouseEvent<SVGGraphicsElement>,
216
+ ) => void;
217
+ /**
218
+ * The customized event handler of mouseleave in this chart.
219
+ */
220
+ onMouseLeave?: (
221
+ data: RadialBarDataItem,
222
+ index: number,
223
+ e: React.MouseEvent<SVGGraphicsElement>,
224
+ ) => void;
225
+ onTouchStart?: (
226
+ data: RadialBarDataItem,
227
+ index: number,
228
+ e: React.TouchEvent<SVGGraphicsElement>,
229
+ ) => void;
230
+ onTouchMove?: (
231
+ data: RadialBarDataItem,
232
+ index: number,
233
+ e: React.TouchEvent<SVGGraphicsElement>,
234
+ ) => void;
235
+ onTouchEnd?: (
236
+ data: RadialBarDataItem,
237
+ index: number,
238
+ e: React.TouchEvent<SVGGraphicsElement>,
239
+ ) => void;
240
+ /**
241
+ * @defaultValue 0
242
+ */
243
+ radiusAxisId?: AxisId;
244
+ /**
245
+ * If set a ReactElement, the shape of radial bar sectors can be customized.
246
+ * If set a function, the function will be called to render customized shape.
247
+ * During animations, the function shape also receives `animationElapsedTime`, `isAnimating`, and `isEntrance`.
248
+ * By default, renders a sector.
249
+ */
250
+ shape?: ActiveShape<RadialBarSectorProps, SVGPathElement>;
251
+ stackId?: string | number;
252
+ tooltipType?: TooltipType;
253
+ /**
254
+ * Formats the value displayed in the tooltip for this RadialBar.
255
+ * When set, takes precedence over the `formatter` prop on the Tooltip component.
256
+ */
257
+ formatter?: Formatter;
258
+ /**
259
+ * @defaultValue 300
260
+ */
261
+ zIndex?: number;
262
+ }
263
+ export type RadialBarProps<DataPointType = any, DataValueType = any> = Omit<
264
+ PresentationAttributesAdaptChildEvent<RadialBarDataItem, SVGElement>,
265
+ 'ref' | keyof InternalRadialBarProps<DataPointType, DataValueType>
266
+ > &
267
+ Omit<InternalRadialBarProps<DataPointType, DataValueType>, 'sectors'>;
268
+ export declare const defaultRadialBarProps: {
269
+ readonly angleAxisId: 0;
270
+ readonly animationBegin: 0;
271
+ readonly animationDuration: 1500;
272
+ readonly animationEasing: 'ease';
273
+ readonly animationMatchBy: 'append';
274
+ readonly animationInterpolateFn: AnimationInterpolateFn<RadialBarDataItem, PolarLayout>;
275
+ readonly background: false;
276
+ readonly cornerIsExternal: false;
277
+ readonly cornerRadius: 0;
278
+ readonly forceCornerRadius: false;
279
+ readonly hide: false;
280
+ readonly isAnimationActive: 'auto';
281
+ readonly label: false;
282
+ readonly legendType: 'rect';
283
+ readonly minPointSize: 0;
284
+ readonly radiusAxisId: 0;
285
+ readonly shape: React.FC<SectorProps>;
286
+ readonly zIndex: 300;
287
+ };
288
+ export declare function computeRadialBarDataItems({
289
+ displayedData,
290
+ stackedData,
291
+ dataStartIndex,
292
+ stackedDomain,
293
+ dataKey,
294
+ baseValue,
295
+ layout,
296
+ radiusAxis,
297
+ radiusAxisTicks,
298
+ bandSize,
299
+ pos,
300
+ angleAxis,
301
+ minPointSize,
302
+ cx,
303
+ cy,
304
+ angleAxisTicks,
305
+ cells,
306
+ startAngle: rootStartAngle,
307
+ endAngle: rootEndAngle,
308
+ }: {
309
+ displayedData: ChartData;
310
+ stackedData: Series<Record<number, number>, DataKey<any>> | undefined;
311
+ dataStartIndex: number;
312
+ stackedDomain: ReadonlyArray<unknown> | null;
313
+ dataKey: DataKey<any> | undefined;
314
+ baseValue: number | unknown;
315
+ layout: LayoutType;
316
+ radiusAxis: BaseAxisWithScale;
317
+ radiusAxisTicks: ReadonlyArray<TickItem> | undefined;
318
+ bandSize: number;
319
+ pos: BarPositionPosition;
320
+ angleAxis: BaseAxisWithScale;
321
+ minPointSize: number;
322
+ cx: number;
323
+ cy: number;
324
+ angleAxisTicks: ReadonlyArray<TickItem> | undefined;
325
+ cells: ReadonlyArray<ReactElement> | undefined;
326
+ startAngle: number;
327
+ endAngle: number;
328
+ }): ReadonlyArray<RadialBarDataItem>;
329
+ /**
330
+ * @consumes PolarChartContext
331
+ * @provides LabelListContext
332
+ * @provides CellReader
333
+ */
334
+ export declare function RadialBar<DataPointType = any, DataValueType = any>(
335
+ outsideProps: RadialBarProps<DataPointType, DataValueType>,
336
+ ): React.JSX.Element;
337
+ export declare namespace RadialBar {
338
+ var displayName: string;
339
+ }
340
+ export {};
@@ -0,0 +1,11 @@
1
+ import { useEffect } from 'octane';
2
+ import { useAppDispatch } from './hooks';
3
+ import { PolarChartOptions, updatePolarOptions } from './polarOptionsSlice';
4
+
5
+ export function ReportPolarOptions(props: PolarChartOptions): null {
6
+ const dispatch = useAppDispatch();
7
+ useEffect(() => {
8
+ dispatch(updatePolarOptions(props));
9
+ }, [dispatch, props]);
10
+ return null;
11
+ }
@@ -0,0 +1,257 @@
1
+ // @ts-nocheck -- retained upstream selector typing is outside the initial Area runtime port.
2
+ import { createSelector } from 'reselect';
3
+ import { SeriesPoint } from 'victory-vendor/d3-shape';
4
+ import { NullableCoordinate } from '../../util/types';
5
+ import { computeArea } from '../../cartesian/Area';
6
+ import {
7
+ selectAxisWithScale,
8
+ selectStackGroups,
9
+ selectTicksOfGraphicalItem,
10
+ selectUnfilteredCartesianItems,
11
+ } from './axisSelectors';
12
+ import { RechartsRootState } from '../store';
13
+ import { AxisId } from '../cartesianAxisSlice';
14
+ import { selectChartLayout } from '../../context/chartLayoutContext';
15
+ import { selectChartDataWithIndexesIfNotInPanoramaPosition3 } from './dataSelectors';
16
+ import { getBandSizeOfAxis, isCategoricalAxis, StackId } from '../../util/ChartUtils';
17
+ import { ChartData } from '../chartDataSlice';
18
+ import { getStackSeriesIdentifier } from '../../util/stacks/getStackSeriesIdentifier';
19
+ import type {
20
+ StackDataPoint,
21
+ StackGroup,
22
+ StackSeries,
23
+ StackSeriesIdentifier,
24
+ } from '../../util/stacks/stackTypes';
25
+ import type { AreaSettings } from '../types/AreaSettings';
26
+ import { GraphicalItemId } from '../graphicalItemsSlice';
27
+ import { selectChartBaseValue } from './rootPropsSelectors';
28
+ import {
29
+ selectXAxisIdFromGraphicalItemId,
30
+ selectYAxisIdFromGraphicalItemId,
31
+ } from './graphicalItemSelectors';
32
+
33
+ export interface AreaPointItem extends NullableCoordinate {
34
+ x: number | null;
35
+ y: number | null;
36
+ value?: ReadonlyArray<unknown>;
37
+ payload?: any;
38
+ }
39
+
40
+ export type ComputedArea = {
41
+ points: ReadonlyArray<AreaPointItem>;
42
+ baseLine: number | ReadonlyArray<AreaPointItem>;
43
+ isRange: boolean;
44
+ };
45
+
46
+ const selectXAxisWithScale = (
47
+ state: RechartsRootState,
48
+ graphicalItemId: GraphicalItemId,
49
+ isPanorama: boolean,
50
+ ) =>
51
+ selectAxisWithScale(
52
+ state,
53
+ 'xAxis',
54
+ selectXAxisIdFromGraphicalItemId(state, graphicalItemId),
55
+ isPanorama,
56
+ );
57
+
58
+ const selectXAxisTicks = (
59
+ state: RechartsRootState,
60
+ graphicalItemId: GraphicalItemId,
61
+ isPanorama: boolean,
62
+ ) =>
63
+ selectTicksOfGraphicalItem(
64
+ state,
65
+ 'xAxis',
66
+ selectXAxisIdFromGraphicalItemId(state, graphicalItemId),
67
+ isPanorama,
68
+ );
69
+
70
+ const selectYAxisWithScale = (
71
+ state: RechartsRootState,
72
+ graphicalItemId: GraphicalItemId,
73
+ isPanorama: boolean,
74
+ ) =>
75
+ selectAxisWithScale(
76
+ state,
77
+ 'yAxis',
78
+ selectYAxisIdFromGraphicalItemId(state, graphicalItemId),
79
+ isPanorama,
80
+ );
81
+
82
+ const selectYAxisTicks = (
83
+ state: RechartsRootState,
84
+ graphicalItemId: GraphicalItemId,
85
+ isPanorama: boolean,
86
+ ) =>
87
+ selectTicksOfGraphicalItem(
88
+ state,
89
+ 'yAxis',
90
+ selectYAxisIdFromGraphicalItemId(state, graphicalItemId),
91
+ isPanorama,
92
+ );
93
+
94
+ const selectBandSize = createSelector(
95
+ [
96
+ selectChartLayout,
97
+ selectXAxisWithScale,
98
+ selectYAxisWithScale,
99
+ selectXAxisTicks,
100
+ selectYAxisTicks,
101
+ ],
102
+ (layout, xAxis, yAxis, xAxisTicks, yAxisTicks) => {
103
+ if (isCategoricalAxis(layout, 'xAxis')) {
104
+ return getBandSizeOfAxis(xAxis, xAxisTicks, false);
105
+ }
106
+ return getBandSizeOfAxis(yAxis, yAxisTicks, false);
107
+ },
108
+ );
109
+
110
+ const pickAreaId = (_state: RechartsRootState, id: GraphicalItemId): GraphicalItemId => id;
111
+
112
+ /*
113
+ * There is a race condition problem because we read some data from props and some from the state.
114
+ * The state is updated through a dispatch and is one render behind,
115
+ * and so we have this weird one tick render where the displayedData in one selector have the old dataKey
116
+ * but the new dataKey in another selector.
117
+ *
118
+ * A proper fix is to either move everything into the state, or read the dataKey always from props
119
+ * - but this is a smaller change.
120
+ */
121
+ const selectSynchronisedAreaSettings: (
122
+ state: RechartsRootState,
123
+ id: GraphicalItemId,
124
+ isPanorama: boolean,
125
+ ) => AreaSettings | undefined = createSelector(
126
+ [selectUnfilteredCartesianItems, pickAreaId],
127
+ (graphicalItems, id: GraphicalItemId) =>
128
+ graphicalItems.filter((item) => item.type === 'area').find((item) => item.id === id),
129
+ );
130
+
131
+ const selectNumericalAxisType = (state: RechartsRootState): 'xAxis' | 'yAxis' => {
132
+ const layout = selectChartLayout(state);
133
+ const isXAxisCategorical = isCategoricalAxis(layout, 'xAxis');
134
+ return isXAxisCategorical ? 'yAxis' : 'xAxis';
135
+ };
136
+
137
+ const selectNumericalAxisIdFromGraphicalItemId = (
138
+ state: RechartsRootState,
139
+ graphicalItemId: GraphicalItemId,
140
+ ): AxisId => {
141
+ const axisType = selectNumericalAxisType(state);
142
+ if (axisType === 'yAxis') {
143
+ return selectYAxisIdFromGraphicalItemId(state, graphicalItemId);
144
+ }
145
+ return selectXAxisIdFromGraphicalItemId(state, graphicalItemId);
146
+ };
147
+
148
+ const selectNumericalAxisStackGroups = (
149
+ state: RechartsRootState,
150
+ graphicalItemId: GraphicalItemId,
151
+ isPanorama: boolean,
152
+ ): Record<StackId, StackGroup> | undefined =>
153
+ selectStackGroups(
154
+ state,
155
+ selectNumericalAxisType(state),
156
+ selectNumericalAxisIdFromGraphicalItemId(state, graphicalItemId),
157
+ isPanorama,
158
+ );
159
+
160
+ export const selectGraphicalItemStackedData: (
161
+ state: RechartsRootState,
162
+ id: GraphicalItemId,
163
+ isPanorama: boolean,
164
+ ) => ReadonlyArray<StackDataPoint> | undefined = createSelector(
165
+ [selectSynchronisedAreaSettings, selectNumericalAxisStackGroups],
166
+ (
167
+ areaSettings: AreaSettings | undefined,
168
+ stackGroups: Record<StackId, StackGroup> | undefined,
169
+ ) => {
170
+ if (areaSettings == null || stackGroups == null) {
171
+ return undefined;
172
+ }
173
+ const { stackId } = areaSettings;
174
+ const stackSeriesIdentifier: StackSeriesIdentifier | undefined =
175
+ getStackSeriesIdentifier(areaSettings);
176
+ if (stackId == null || stackSeriesIdentifier == null) {
177
+ return undefined;
178
+ }
179
+ const groups: ReadonlyArray<StackSeries> | undefined = stackGroups[stackId]?.stackedData;
180
+ const found: StackSeries | undefined = groups?.find((v) => v.key === stackSeriesIdentifier);
181
+ if (found == null) {
182
+ return undefined;
183
+ }
184
+ return found.map((item: SeriesPoint<StackDataPoint>): StackDataPoint => [item[0], item[1]]);
185
+ },
186
+ );
187
+
188
+ export const selectArea: (
189
+ state: RechartsRootState,
190
+ id: GraphicalItemId,
191
+ isPanorama: boolean,
192
+ ) => ComputedArea | undefined = createSelector(
193
+ [
194
+ selectChartLayout,
195
+ selectXAxisWithScale,
196
+ selectYAxisWithScale,
197
+ selectXAxisTicks,
198
+ selectYAxisTicks,
199
+ selectGraphicalItemStackedData,
200
+ selectChartDataWithIndexesIfNotInPanoramaPosition3,
201
+ selectBandSize,
202
+ selectSynchronisedAreaSettings,
203
+ selectChartBaseValue,
204
+ ],
205
+ (
206
+ layout,
207
+ xAxis,
208
+ yAxis,
209
+ xAxisTicks,
210
+ yAxisTicks,
211
+ stackedData: ReadonlyArray<StackDataPoint> | undefined,
212
+ { chartData, dataStartIndex, dataEndIndex },
213
+ bandSize,
214
+ areaSettings,
215
+ chartBaseValue,
216
+ ) => {
217
+ if (
218
+ areaSettings == null ||
219
+ (layout !== 'horizontal' && layout !== 'vertical') ||
220
+ xAxis == null ||
221
+ yAxis == null ||
222
+ xAxisTicks == null ||
223
+ yAxisTicks == null ||
224
+ xAxisTicks.length === 0 ||
225
+ yAxisTicks.length === 0 ||
226
+ bandSize == null
227
+ ) {
228
+ return undefined;
229
+ }
230
+ const { data } = areaSettings;
231
+
232
+ let displayedData: ChartData | undefined;
233
+ if (data && data.length > 0) {
234
+ displayedData = data;
235
+ } else {
236
+ displayedData = chartData?.slice(dataStartIndex, dataEndIndex + 1);
237
+ }
238
+
239
+ if (displayedData == null) {
240
+ return undefined;
241
+ }
242
+
243
+ return computeArea({
244
+ layout,
245
+ xAxis,
246
+ yAxis,
247
+ xAxisTicks,
248
+ yAxisTicks,
249
+ dataStartIndex,
250
+ areaSettings,
251
+ stackedData,
252
+ displayedData,
253
+ chartBaseValue,
254
+ bandSize,
255
+ });
256
+ },
257
+ );
@@ -0,0 +1,86 @@
1
+ import { createSelector } from 'reselect';
2
+ import { ReactElement } from 'octane';
3
+ import { computeFunnelTrapezoids, FunnelTrapezoidItem } from '../../cartesian/Funnel';
4
+ import { ChartData } from '../chartDataSlice';
5
+ import { RechartsRootState } from '../store';
6
+ import { selectChartOffsetInternal } from './selectChartOffsetInternal';
7
+ import { selectChartDataAndAlwaysIgnoreIndexes } from './dataSelectors';
8
+ import { ChartOffsetInternal, DataKey, TooltipType } from '../../util/types';
9
+ import { CellProps } from '../..';
10
+ import { GraphicalItemId } from '../graphicalItemsSlice';
11
+
12
+ export type ResolvedFunnelSettings = {
13
+ dataKey: DataKey<any>;
14
+ data: ChartData | undefined;
15
+ nameKey: DataKey<any>;
16
+ tooltipType?: TooltipType;
17
+ lastShapeType?: 'triangle' | 'rectangle';
18
+ reversed?: boolean;
19
+ customWidth?: string | number;
20
+ cells: ReadonlyArray<ReactElement>;
21
+ presentationProps: Record<string, any> | null;
22
+ id: GraphicalItemId;
23
+ };
24
+
25
+ const pickFunnelSettings = (
26
+ _state: RechartsRootState,
27
+ funnelSettings: ResolvedFunnelSettings,
28
+ ): ResolvedFunnelSettings => funnelSettings;
29
+
30
+ export const selectFunnelTrapezoids: (
31
+ state: RechartsRootState,
32
+ funnelSettings: ResolvedFunnelSettings,
33
+ ) => ReadonlyArray<FunnelTrapezoidItem> = createSelector(
34
+ [selectChartOffsetInternal, pickFunnelSettings, selectChartDataAndAlwaysIgnoreIndexes],
35
+ (
36
+ offset: ChartOffsetInternal,
37
+ {
38
+ data,
39
+ dataKey,
40
+ nameKey,
41
+ tooltipType,
42
+ lastShapeType,
43
+ reversed,
44
+ customWidth,
45
+ cells,
46
+ presentationProps,
47
+ id: graphicalItemId,
48
+ },
49
+ { chartData },
50
+ ): ReadonlyArray<FunnelTrapezoidItem> => {
51
+ let displayedData: ChartData | undefined;
52
+ if (data != null && data.length > 0) {
53
+ displayedData = data;
54
+ } else if (chartData != null && chartData.length > 0) {
55
+ displayedData = chartData;
56
+ }
57
+
58
+ if (displayedData && displayedData.length) {
59
+ displayedData = displayedData.map((entry: any, index: number) => ({
60
+ payload: entry,
61
+ ...presentationProps,
62
+ ...entry,
63
+ ...(cells && cells[index] && cells[index].props),
64
+ }));
65
+ } else if (cells && cells.length) {
66
+ displayedData = cells.map((cell: ReactElement<CellProps>) => ({
67
+ ...presentationProps,
68
+ ...cell.props,
69
+ }));
70
+ } else {
71
+ return [];
72
+ }
73
+
74
+ return computeFunnelTrapezoids({
75
+ dataKey,
76
+ nameKey,
77
+ displayedData,
78
+ tooltipType,
79
+ lastShapeType,
80
+ reversed,
81
+ offset,
82
+ customWidth,
83
+ graphicalItemId,
84
+ });
85
+ },
86
+ );