@octanejs/recharts 0.1.15 → 0.1.17
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +5 -5
- package/src/animation/CSSTransitionAnimate.tsrx +142 -0
- package/src/cartesian/Area.tsrx +1096 -0
- package/src/cartesian/Area.tsrx.d.ts +340 -0
- package/src/cartesian/AreaRevealShape.tsrx +202 -0
- package/src/cartesian/CartesianGrid.tsrx +643 -0
- package/src/cartesian/CartesianGrid.tsrx.d.ts +219 -0
- package/src/cartesian/ErrorBar.tsrx +322 -0
- package/src/cartesian/ErrorBar.tsrx.d.ts +131 -0
- package/src/cartesian/Funnel.tsrx +833 -0
- package/src/cartesian/Funnel.tsrx.d.ts +274 -0
- package/src/cartesian/ReferenceLine.tsrx +452 -0
- package/src/cartesian/ReferenceLine.tsrx.d.ts +178 -0
- package/src/cartesian/Scatter.tsrx +1076 -0
- package/src/cartesian/Scatter.tsrx.d.ts +351 -0
- package/src/cartesian/ZAxis.tsrx +148 -0
- package/src/cartesian/ZAxis.tsrx.d.ts +102 -0
- package/src/chart/AreaChart.tsrx +22 -0
- package/src/chart/AreaChart.tsrx.d.ts +12 -0
- package/src/chart/ComposedChart.tsrx +22 -0
- package/src/chart/ComposedChart.tsrx.d.ts +12 -0
- package/src/chart/FunnelChart.tsrx +22 -0
- package/src/chart/FunnelChart.tsrx.d.ts +12 -0
- package/src/chart/PieChart.tsrx +31 -0
- package/src/chart/PieChart.tsrx.d.ts +31 -0
- package/src/chart/PolarChart.tsrx +121 -0
- package/src/chart/RadarChart.tsrx +53 -0
- package/src/chart/RadarChart.tsrx.d.ts +31 -0
- package/src/chart/RadialBarChart.tsrx +31 -0
- package/src/chart/RadialBarChart.tsrx.d.ts +31 -0
- package/src/chart/Sankey.tsrx +1542 -0
- package/src/chart/Sankey.tsrx.d.ts +253 -0
- package/src/chart/ScatterChart.tsrx +22 -0
- package/src/chart/ScatterChart.tsrx.d.ts +12 -0
- package/src/chart/SunburstChart.tsrx +495 -0
- package/src/chart/SunburstChart.tsrx.d.ts +146 -0
- package/src/chart/types.ts +19 -0
- package/src/component/Cursor.tsrx +157 -0
- package/src/component/DefaultLegendContent.tsrx +288 -0
- package/src/component/DefaultLegendContent.tsrx.d.ts +125 -0
- package/src/component/DefaultTooltipContent.tsrx +215 -0
- package/src/component/DefaultTooltipContent.tsrx.d.ts +87 -0
- package/src/component/Legend.tsrx +302 -0
- package/src/component/Legend.tsrx.d.ts +88 -0
- package/src/component/ResponsiveContainer.ts +1 -22
- package/src/component/ResponsiveContainer.tsrx +171 -0
- package/src/component/ResponsiveContainer.tsrx.d.ts +81 -0
- package/src/component/Tooltip.tsrx +425 -0
- package/src/component/Tooltip.tsrx.d.ts +246 -0
- package/src/component/TooltipBoundingBox.tsrx +135 -0
- package/src/context/CellsContext.ts +12 -0
- package/src/context/legendPayloadContext.tsrx +11 -0
- package/src/context/useTooltipAxis.ts +20 -0
- package/src/index.d.ts +236 -0
- package/src/index.ts +67 -0
- package/src/polar/Pie.tsrx +1224 -0
- package/src/polar/Pie.tsrx.d.ts +436 -0
- package/src/polar/PolarAngleAxis.tsrx +554 -0
- package/src/polar/PolarAngleAxis.tsrx.d.ts +215 -0
- package/src/polar/PolarGrid.tsrx +317 -0
- package/src/polar/PolarGrid.tsrx.d.ts +117 -0
- package/src/polar/PolarRadiusAxis.tsrx +463 -0
- package/src/polar/PolarRadiusAxis.tsrx.d.ts +209 -0
- package/src/polar/Radar.tsrx +696 -0
- package/src/polar/Radar.tsrx.d.ts +215 -0
- package/src/polar/RadialBar.tsrx +887 -0
- package/src/polar/RadialBar.tsrx.d.ts +340 -0
- package/src/state/ReportPolarOptions.tsrx +11 -0
- package/src/state/selectors/areaSelectors.ts +257 -0
- package/src/state/selectors/funnelSelectors.ts +86 -0
- package/src/state/selectors/pieSelectors.ts +134 -0
- package/src/state/selectors/polarGridSelectors.ts +43 -0
- package/src/state/selectors/polarScaleSelectors.ts +159 -0
- package/src/state/selectors/polarSelectors.ts +198 -0
- package/src/state/selectors/radarSelectors.ts +228 -0
- package/src/state/selectors/radialBarSelectors.ts +511 -0
- package/src/state/selectors/scatterSelectors.ts +168 -0
- package/src/util/FunnelUtils.tsrx +19 -0
- package/src/util/RadialBarUtils.tsrx +29 -0
- package/src/util/ScatterUtils.tsrx +34 -0
- package/src/util/cursor/getCursorPoints.ts +45 -0
- package/src/util/cursor/getCursorRectangle.ts +28 -0
- package/src/util/cursor/getRadialCursorPoints.ts +31 -0
- package/src/util/payload/getUniqPayload.ts +28 -0
- package/src/util/scale/CartesianScaleHelper.ts +71 -0
- package/src/util/tooltip/translate.ts +168 -0
- package/src/util/types.ts +3 -0
- package/src/util/useElementOffset.ts +147 -0
|
@@ -0,0 +1,643 @@
|
|
|
1
|
+
import * as React from 'octane';
|
|
2
|
+
import { ReactElement, SVGProps } from 'octane';
|
|
3
|
+
|
|
4
|
+
import { warn } from '../util/LogUtils';
|
|
5
|
+
import { isNumber } from '../util/DataUtils';
|
|
6
|
+
import { ChartOffsetInternal } from '../util/types';
|
|
7
|
+
|
|
8
|
+
import {
|
|
9
|
+
AxisPropsNeededForTicksGenerator,
|
|
10
|
+
getCoordinatesOfGrid,
|
|
11
|
+
getTicksOfAxis,
|
|
12
|
+
} from '../util/ChartUtils';
|
|
13
|
+
import { getTicks, GetTicksInput } from './getTicks';
|
|
14
|
+
import { defaultCartesianAxisProps } from './CartesianAxis';
|
|
15
|
+
import { useChartHeight, useChartWidth, useOffsetInternal } from '../context/chartLayoutContext';
|
|
16
|
+
import { AxisId } from '../state/cartesianAxisSlice';
|
|
17
|
+
import {
|
|
18
|
+
selectAxisPropsNeededForCartesianGridTicksGenerator,
|
|
19
|
+
} from '../state/selectors/axisSelectors';
|
|
20
|
+
import { useAppSelector } from '../state/hooks';
|
|
21
|
+
import { useIsPanorama } from '../context/PanoramaContext';
|
|
22
|
+
import { RequiresDefaultProps, resolveDefaultProps } from '../util/resolveDefaultProps';
|
|
23
|
+
import { svgPropertiesNoEvents } from '../util/svgPropertiesNoEvents';
|
|
24
|
+
import { isPositiveNumber } from '../util/isWellBehavedNumber';
|
|
25
|
+
import { ZIndexable, ZIndexLayer } from '../zIndex/ZIndexLayer';
|
|
26
|
+
import { DefaultZIndexes } from '../zIndex/DefaultZIndexes';
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* The <CartesianGrid horizontal
|
|
30
|
+
*/
|
|
31
|
+
export type GridLineTypeFunctionProps =
|
|
32
|
+
Omit<LineItemProps, 'key'> & {
|
|
33
|
+
// React does not pass the key through when calling cloneElement - so it might be undefined when cloning
|
|
34
|
+
key: LineItemProps['key'] | undefined;
|
|
35
|
+
// offset is not present in LineItemProps, but it is read from context and then passed to the GridLineType function and element
|
|
36
|
+
offset: ChartOffsetInternal;
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
export type AxisPropsForCartesianGridTicksGeneration =
|
|
40
|
+
AxisPropsNeededForTicksGenerator & Omit<GetTicksInput, 'ticks' | 'viewBox'>;
|
|
41
|
+
|
|
42
|
+
type GridLineType =
|
|
43
|
+
| SVGProps<SVGLineElement>
|
|
44
|
+
| ReactElement<SVGElement>
|
|
45
|
+
| ((props: GridLineTypeFunctionProps) => ReactElement<SVGElement>)
|
|
46
|
+
| boolean;
|
|
47
|
+
|
|
48
|
+
export type HorizontalCoordinatesGenerator =
|
|
49
|
+
(props: {
|
|
50
|
+
yAxis: AxisPropsForCartesianGridTicksGeneration | undefined;
|
|
51
|
+
width: number;
|
|
52
|
+
height: number;
|
|
53
|
+
offset: ChartOffsetInternal;
|
|
54
|
+
}, syncWithTicks: boolean) => number[];
|
|
55
|
+
|
|
56
|
+
export type VerticalCoordinatesGenerator =
|
|
57
|
+
(props: {
|
|
58
|
+
xAxis: AxisPropsForCartesianGridTicksGeneration | undefined;
|
|
59
|
+
width: number;
|
|
60
|
+
height: number;
|
|
61
|
+
offset: ChartOffsetInternal;
|
|
62
|
+
}, syncWithTicks: boolean) => number[];
|
|
63
|
+
|
|
64
|
+
interface CartesianGridProps extends ZIndexable {
|
|
65
|
+
/**
|
|
66
|
+
* The width of grid. If undefined, covers the full width of the chart plot area.
|
|
67
|
+
*/
|
|
68
|
+
width?: number;
|
|
69
|
+
/**
|
|
70
|
+
* The height of grid. If undefined, covers the full height of the chart plot area.
|
|
71
|
+
*/
|
|
72
|
+
height?: number;
|
|
73
|
+
/**
|
|
74
|
+
* A function that generates the y-coordinates of all horizontal lines.
|
|
75
|
+
*
|
|
76
|
+
* @see {@link https://codesandbox.io/p/sandbox/cartesian-grid-with-coordinate-generators-my38cg?file=%2Fsrc%2FApp.tsx Cartesian grid with coordinate generators}
|
|
77
|
+
*/
|
|
78
|
+
horizontalCoordinatesGenerator?: HorizontalCoordinatesGenerator;
|
|
79
|
+
/**
|
|
80
|
+
* A function that generates the x-coordinates of all vertical lines.
|
|
81
|
+
*
|
|
82
|
+
* @see {@link https://codesandbox.io/p/sandbox/cartesian-grid-with-coordinate-generators-my38cg?file=%2Fsrc%2FApp.tsx Cartesian grid with coordinate generators}
|
|
83
|
+
*/
|
|
84
|
+
verticalCoordinatesGenerator?: VerticalCoordinatesGenerator;
|
|
85
|
+
/**
|
|
86
|
+
* The x-coordinate of grid.
|
|
87
|
+
* If left undefined, it will be computed from the chart's offset and margins.
|
|
88
|
+
*/
|
|
89
|
+
x?: number;
|
|
90
|
+
/**
|
|
91
|
+
* The y-coordinate of grid.
|
|
92
|
+
* If left undefined, it will be computed from the chart's offset and margins.
|
|
93
|
+
*/
|
|
94
|
+
y?: number;
|
|
95
|
+
/**
|
|
96
|
+
* If set false, no horizontal grid lines will be drawn.
|
|
97
|
+
*
|
|
98
|
+
* @defaultValue true
|
|
99
|
+
*/
|
|
100
|
+
horizontal?: GridLineType;
|
|
101
|
+
/**
|
|
102
|
+
* If set false, no vertical grid lines will be drawn.
|
|
103
|
+
*
|
|
104
|
+
* @defaultValue true
|
|
105
|
+
*/
|
|
106
|
+
vertical?: GridLineType;
|
|
107
|
+
/**
|
|
108
|
+
* Array of coordinates in pixels where to draw horizontal grid lines.
|
|
109
|
+
* Has priority over syncWithTicks and horizontalValues.
|
|
110
|
+
*
|
|
111
|
+
* @defaultValue []
|
|
112
|
+
*/
|
|
113
|
+
horizontalPoints?: number[];
|
|
114
|
+
/**
|
|
115
|
+
* Array of coordinates in pixels where to draw vertical grid lines.
|
|
116
|
+
* Has priority over syncWithTicks and verticalValues.
|
|
117
|
+
*
|
|
118
|
+
* @defaultValue []
|
|
119
|
+
*/
|
|
120
|
+
verticalPoints?: number[];
|
|
121
|
+
/**
|
|
122
|
+
* The background color used to fill the space between grid lines
|
|
123
|
+
*
|
|
124
|
+
* @defaultValue none
|
|
125
|
+
* @example <CartesianGrid fill="red" />
|
|
126
|
+
* @example <CartesianGrid fill="#ccc" />
|
|
127
|
+
*/
|
|
128
|
+
fill?: string;
|
|
129
|
+
/**
|
|
130
|
+
* The opacity of the background used to fill the space between grid lines
|
|
131
|
+
*
|
|
132
|
+
* @example <CartesianGrid fill="red" fillOpacity={0.6} />
|
|
133
|
+
*/
|
|
134
|
+
fillOpacity?: number | string;
|
|
135
|
+
/**
|
|
136
|
+
* Defines background color of stripes.
|
|
137
|
+
*
|
|
138
|
+
* The values from this array will be passed in as the `fill` property in a `rect` SVG element.
|
|
139
|
+
* For possible values see: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill#rect
|
|
140
|
+
*
|
|
141
|
+
* In case there are more stripes than colors, the colors will start from beginning.
|
|
142
|
+
* So for example: verticalFill['yellow', 'black'] produces a pattern of yellow|black|yellow|black
|
|
143
|
+
*
|
|
144
|
+
* If this is undefined, or an empty array, then there is no background fill.
|
|
145
|
+
* Note: Grid lines will be rendered above these background stripes.
|
|
146
|
+
*
|
|
147
|
+
* @defaultValue []
|
|
148
|
+
*/
|
|
149
|
+
verticalFill?: string[];
|
|
150
|
+
/**
|
|
151
|
+
* Defines background color of stripes.
|
|
152
|
+
*
|
|
153
|
+
* The values from this array will be passed in as the `fill` property in a `rect` SVG element.
|
|
154
|
+
* For possible values see: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill#rect
|
|
155
|
+
*
|
|
156
|
+
* In case there are more stripes than colors, the colors will start from beginning.
|
|
157
|
+
* So for example: horizontalFill['yellow', 'black'] produces a pattern of yellow|black|yellow|black
|
|
158
|
+
*
|
|
159
|
+
* If this is undefined, or an empty array, then there is no background fill.
|
|
160
|
+
* Note: Grid lines will be rendered above these background stripes.
|
|
161
|
+
*
|
|
162
|
+
* @defaultValue []
|
|
163
|
+
*/
|
|
164
|
+
horizontalFill?: string[];
|
|
165
|
+
/**
|
|
166
|
+
* If true, only the lines that correspond to the axes ticks values will be drawn.
|
|
167
|
+
* If false, extra lines could be added for each axis (at min and max coordinates), if there will not such ticks.
|
|
168
|
+
* horizontalPoints, verticalPoints, horizontalValues, verticalValues have priority over syncWithTicks.
|
|
169
|
+
*
|
|
170
|
+
* @defaultValue false
|
|
171
|
+
*/
|
|
172
|
+
syncWithTicks?: boolean;
|
|
173
|
+
/**
|
|
174
|
+
* Array of values, where horizontal lines will be drawn. Numbers or strings, in dependence on axis type.
|
|
175
|
+
* Has priority over syncWithTicks but not over horizontalPoints.
|
|
176
|
+
*/
|
|
177
|
+
horizontalValues?: number[] | string[];
|
|
178
|
+
/**
|
|
179
|
+
* Array of values, where vertical lines will be drawn. Numbers or strings, in dependence on axis type.
|
|
180
|
+
* Has priority over syncWithTicks but not over verticalPoints.
|
|
181
|
+
*/
|
|
182
|
+
verticalValues?: number[] | string[];
|
|
183
|
+
/**
|
|
184
|
+
* The pattern of dashes and gaps used to paint the lines of the grid
|
|
185
|
+
*
|
|
186
|
+
* @example <CartesianGrid strokeDasharray="3 3" />
|
|
187
|
+
* @example <CartesianGrid strokeDasharray={[5, 5, 1, 5]} />
|
|
188
|
+
* @example <CartesianGrid strokeDasharray="5 5 1 5" />
|
|
189
|
+
* @see {@link https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dasharray stroke-dasharray on MDN}
|
|
190
|
+
*/
|
|
191
|
+
strokeDasharray?: string | number[];
|
|
192
|
+
/**
|
|
193
|
+
* The id of XAxis which is corresponding to the data. Required when there are multiple XAxes.
|
|
194
|
+
* @defaultValue 0
|
|
195
|
+
*/
|
|
196
|
+
xAxisId?: AxisId;
|
|
197
|
+
/**
|
|
198
|
+
* The id of YAxis which is corresponding to the data. Required when there are multiple YAxes.
|
|
199
|
+
* @defaultValue 0
|
|
200
|
+
*/
|
|
201
|
+
yAxisId?: AxisId;
|
|
202
|
+
/**
|
|
203
|
+
* @defaultValue -100
|
|
204
|
+
*/
|
|
205
|
+
zIndex?: number;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
type AcceptedSvgProps = Omit<SVGProps<SVGLineElement>, 'offset'>;
|
|
209
|
+
|
|
210
|
+
export type Props = AcceptedSvgProps & CartesianGridProps;
|
|
211
|
+
|
|
212
|
+
type CartesianGridInternalProps =
|
|
213
|
+
AcceptedSvgProps & RequiresDefaultProps<CartesianGridProps, typeof defaultCartesianGridProps> & {
|
|
214
|
+
// x,y,width,height are not declared directly in default props but are resolved using offset, if undefined
|
|
215
|
+
x: number;
|
|
216
|
+
y: number;
|
|
217
|
+
width: number;
|
|
218
|
+
height: number;
|
|
219
|
+
};
|
|
220
|
+
|
|
221
|
+
const Background = (
|
|
222
|
+
props: Pick<AcceptedSvgProps, 'fill' | 'fillOpacity' | 'x' | 'y' | 'width' | 'height' | 'ry'>,
|
|
223
|
+
) => {
|
|
224
|
+
const { fill } = props;
|
|
225
|
+
|
|
226
|
+
if (!fill || fill === 'none') {
|
|
227
|
+
return null;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
const { fillOpacity, x, y, width, height, ry } = props;
|
|
231
|
+
|
|
232
|
+
return <rect
|
|
233
|
+
x={x}
|
|
234
|
+
y={y}
|
|
235
|
+
ry={ry}
|
|
236
|
+
width={width}
|
|
237
|
+
height={height}
|
|
238
|
+
stroke="none"
|
|
239
|
+
fill={fill}
|
|
240
|
+
fillOpacity={fillOpacity}
|
|
241
|
+
className="recharts-cartesian-grid-bg"
|
|
242
|
+
/>;
|
|
243
|
+
};
|
|
244
|
+
|
|
245
|
+
type LineItemProps =
|
|
246
|
+
Props & {
|
|
247
|
+
offset: ChartOffsetInternal;
|
|
248
|
+
xAxis: undefined | AxisPropsForCartesianGridTicksGeneration;
|
|
249
|
+
yAxis: undefined | AxisPropsForCartesianGridTicksGeneration;
|
|
250
|
+
x1: number;
|
|
251
|
+
y1: number;
|
|
252
|
+
x2: number;
|
|
253
|
+
y2: number;
|
|
254
|
+
key: string;
|
|
255
|
+
index: number;
|
|
256
|
+
};
|
|
257
|
+
|
|
258
|
+
function LineItem({
|
|
259
|
+
option,
|
|
260
|
+
lineItemProps,
|
|
261
|
+
}: {
|
|
262
|
+
option: GridLineType;
|
|
263
|
+
lineItemProps: LineItemProps;
|
|
264
|
+
}) {
|
|
265
|
+
let lineItem;
|
|
266
|
+
|
|
267
|
+
if (React.isValidElement(option)) {
|
|
268
|
+
// @ts-expect-error typescript does not see the props type when cloning an element
|
|
269
|
+
lineItem = React.cloneElement(option, lineItemProps);
|
|
270
|
+
} else if (typeof option === 'function') {
|
|
271
|
+
lineItem = option(lineItemProps);
|
|
272
|
+
} else {
|
|
273
|
+
const { x1, y1, x2, y2, key, ...others } = lineItemProps;
|
|
274
|
+
const { offset: __, ...restOfFilteredProps } = svgPropertiesNoEvents(others) ?? {};
|
|
275
|
+
lineItem = <line
|
|
276
|
+
{...restOfFilteredProps}
|
|
277
|
+
x1={x1}
|
|
278
|
+
y1={y1}
|
|
279
|
+
x2={x2}
|
|
280
|
+
y2={y2}
|
|
281
|
+
fill="none"
|
|
282
|
+
key={key}
|
|
283
|
+
/>;
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
return lineItem;
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
type GridLinesProps =
|
|
290
|
+
CartesianGridInternalProps & {
|
|
291
|
+
offset: GridLineTypeFunctionProps['offset'];
|
|
292
|
+
xAxis: GridLineTypeFunctionProps['xAxis'];
|
|
293
|
+
yAxis: GridLineTypeFunctionProps['yAxis'];
|
|
294
|
+
};
|
|
295
|
+
|
|
296
|
+
function HorizontalGridLines(props: GridLinesProps) {
|
|
297
|
+
const { x, width, horizontal = true, horizontalPoints } = props;
|
|
298
|
+
|
|
299
|
+
if (!horizontal || !horizontalPoints || !horizontalPoints.length) {
|
|
300
|
+
return null;
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
const { xAxisId, yAxisId, ...otherLineItemProps } = props;
|
|
304
|
+
|
|
305
|
+
const items = horizontalPoints.map((entry, i) => {
|
|
306
|
+
const lineItemProps: LineItemProps = {
|
|
307
|
+
...otherLineItemProps,
|
|
308
|
+
x1: x,
|
|
309
|
+
y1: entry,
|
|
310
|
+
x2: x + width,
|
|
311
|
+
y2: entry,
|
|
312
|
+
key: `line-${i}`,
|
|
313
|
+
index: i,
|
|
314
|
+
};
|
|
315
|
+
|
|
316
|
+
return <LineItem key={`line-${i}`} option={horizontal} lineItemProps={lineItemProps} />;
|
|
317
|
+
});
|
|
318
|
+
|
|
319
|
+
return <g className="recharts-cartesian-grid-horizontal">{items}</g>;
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
function VerticalGridLines(props: GridLinesProps) {
|
|
323
|
+
const { y, height, vertical = true, verticalPoints } = props;
|
|
324
|
+
|
|
325
|
+
if (!vertical || !verticalPoints || !verticalPoints.length) {
|
|
326
|
+
return null;
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
const { xAxisId, yAxisId, ...otherLineItemProps } = props;
|
|
330
|
+
|
|
331
|
+
const items = verticalPoints.map((entry, i) => {
|
|
332
|
+
const lineItemProps: LineItemProps = {
|
|
333
|
+
...otherLineItemProps,
|
|
334
|
+
x1: entry,
|
|
335
|
+
y1: y,
|
|
336
|
+
x2: entry,
|
|
337
|
+
y2: y + height,
|
|
338
|
+
key: `line-${i}`,
|
|
339
|
+
index: i,
|
|
340
|
+
};
|
|
341
|
+
|
|
342
|
+
return <LineItem option={vertical} lineItemProps={lineItemProps} key={`line-${i}`} />;
|
|
343
|
+
});
|
|
344
|
+
|
|
345
|
+
return <g className="recharts-cartesian-grid-vertical">{items}</g>;
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
function HorizontalStripes(props: CartesianGridInternalProps) {
|
|
349
|
+
const {
|
|
350
|
+
horizontalFill,
|
|
351
|
+
fillOpacity,
|
|
352
|
+
x,
|
|
353
|
+
y,
|
|
354
|
+
width,
|
|
355
|
+
height,
|
|
356
|
+
horizontalPoints,
|
|
357
|
+
horizontal = true,
|
|
358
|
+
} = props;
|
|
359
|
+
if (!horizontal || !horizontalFill || !horizontalFill.length || horizontalPoints == null) {
|
|
360
|
+
return null;
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
const roundedSortedHorizontalPoints = horizontalPoints.map((e) => Math.round(e + y - y)).sort(
|
|
364
|
+
(a, b) => a - b,
|
|
365
|
+
);
|
|
366
|
+
// Why is this condition `!==` instead of `<=` ?
|
|
367
|
+
if (y !== roundedSortedHorizontalPoints[0]) {
|
|
368
|
+
roundedSortedHorizontalPoints.unshift(y);
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
const items = roundedSortedHorizontalPoints.map((entry, i) => {
|
|
372
|
+
// Why do we strip only the last stripe if it is invisible, and not all invisible stripes?
|
|
373
|
+
const nextPoint = roundedSortedHorizontalPoints[i + 1];
|
|
374
|
+
const lastStripe = nextPoint == null;
|
|
375
|
+
const lineHeight = lastStripe ? y + height - entry : nextPoint - entry;
|
|
376
|
+
if (lineHeight <= 0) {
|
|
377
|
+
return null;
|
|
378
|
+
}
|
|
379
|
+
const colorIndex = i % horizontalFill.length;
|
|
380
|
+
return <rect
|
|
381
|
+
key={`react-${i}`}
|
|
382
|
+
y={entry}
|
|
383
|
+
x={x}
|
|
384
|
+
height={lineHeight}
|
|
385
|
+
width={width}
|
|
386
|
+
stroke="none"
|
|
387
|
+
fill={horizontalFill[colorIndex]}
|
|
388
|
+
fillOpacity={fillOpacity}
|
|
389
|
+
className="recharts-cartesian-grid-bg"
|
|
390
|
+
/>;
|
|
391
|
+
});
|
|
392
|
+
|
|
393
|
+
return <g className="recharts-cartesian-gridstripes-horizontal">{items}</g>;
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
function VerticalStripes(props: CartesianGridInternalProps) {
|
|
397
|
+
const { vertical = true, verticalFill, fillOpacity, x, y, width, height, verticalPoints } = props;
|
|
398
|
+
if (!vertical || !verticalFill || !verticalFill.length || verticalPoints == null) {
|
|
399
|
+
return null;
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
const roundedSortedVerticalPoints = verticalPoints.map((e) => Math.round(e + x - x)).sort(
|
|
403
|
+
(a, b) => a - b,
|
|
404
|
+
);
|
|
405
|
+
|
|
406
|
+
if (x !== roundedSortedVerticalPoints[0]) {
|
|
407
|
+
roundedSortedVerticalPoints.unshift(x);
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
const items = roundedSortedVerticalPoints.map((entry, i) => {
|
|
411
|
+
const nextPoint = roundedSortedVerticalPoints[i + 1];
|
|
412
|
+
const lastStripe = nextPoint == null;
|
|
413
|
+
const lineWidth = lastStripe ? x + width - entry : nextPoint - entry;
|
|
414
|
+
|
|
415
|
+
if (lineWidth <= 0) {
|
|
416
|
+
return null;
|
|
417
|
+
}
|
|
418
|
+
const colorIndex = i % verticalFill.length;
|
|
419
|
+
return <rect
|
|
420
|
+
key={`react-${i}`}
|
|
421
|
+
x={entry}
|
|
422
|
+
y={y}
|
|
423
|
+
width={lineWidth}
|
|
424
|
+
height={height}
|
|
425
|
+
stroke="none"
|
|
426
|
+
fill={verticalFill[colorIndex]}
|
|
427
|
+
fillOpacity={fillOpacity}
|
|
428
|
+
className="recharts-cartesian-grid-bg"
|
|
429
|
+
/>;
|
|
430
|
+
});
|
|
431
|
+
|
|
432
|
+
return <g className="recharts-cartesian-gridstripes-vertical">{items}</g>;
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
const defaultVerticalCoordinatesGenerator: VerticalCoordinatesGenerator = (
|
|
436
|
+
{ xAxis, width, height, offset },
|
|
437
|
+
syncWithTicks,
|
|
438
|
+
) => getCoordinatesOfGrid(
|
|
439
|
+
getTicks({
|
|
440
|
+
...defaultCartesianAxisProps,
|
|
441
|
+
...xAxis,
|
|
442
|
+
ticks: getTicksOfAxis(xAxis, true),
|
|
443
|
+
viewBox: { x: 0, y: 0, width, height },
|
|
444
|
+
}),
|
|
445
|
+
offset.left,
|
|
446
|
+
offset.left + offset.width,
|
|
447
|
+
syncWithTicks,
|
|
448
|
+
);
|
|
449
|
+
|
|
450
|
+
const defaultHorizontalCoordinatesGenerator: HorizontalCoordinatesGenerator = (
|
|
451
|
+
{ yAxis, width, height, offset },
|
|
452
|
+
syncWithTicks,
|
|
453
|
+
) => getCoordinatesOfGrid(
|
|
454
|
+
getTicks({
|
|
455
|
+
...defaultCartesianAxisProps,
|
|
456
|
+
...yAxis,
|
|
457
|
+
ticks: getTicksOfAxis(yAxis, true),
|
|
458
|
+
viewBox: { x: 0, y: 0, width, height },
|
|
459
|
+
}),
|
|
460
|
+
offset.top,
|
|
461
|
+
offset.top + offset.height,
|
|
462
|
+
syncWithTicks,
|
|
463
|
+
);
|
|
464
|
+
|
|
465
|
+
export const defaultCartesianGridProps = {
|
|
466
|
+
horizontal: true,
|
|
467
|
+
vertical: true,
|
|
468
|
+
// The ordinates of horizontal grid lines
|
|
469
|
+
horizontalPoints: [],
|
|
470
|
+
// The abscissas of vertical grid lines
|
|
471
|
+
verticalPoints: [],
|
|
472
|
+
|
|
473
|
+
stroke: '#ccc',
|
|
474
|
+
fill: 'none',
|
|
475
|
+
// The fill of colors of grid lines
|
|
476
|
+
verticalFill: [],
|
|
477
|
+
horizontalFill: [],
|
|
478
|
+
xAxisId: 0,
|
|
479
|
+
yAxisId: 0,
|
|
480
|
+
syncWithTicks: false,
|
|
481
|
+
zIndex: DefaultZIndexes.grid,
|
|
482
|
+
} as const satisfies Partial<Props>;
|
|
483
|
+
|
|
484
|
+
/**
|
|
485
|
+
* Renders background grid with lines and fill colors in a Cartesian chart.
|
|
486
|
+
*
|
|
487
|
+
* @consumes CartesianChartContext
|
|
488
|
+
*/
|
|
489
|
+
export function CartesianGrid(props: Props) {
|
|
490
|
+
const chartWidth = useChartWidth();
|
|
491
|
+
const chartHeight = useChartHeight();
|
|
492
|
+
const offset = useOffsetInternal();
|
|
493
|
+
const propsIncludingDefaults: CartesianGridInternalProps = {
|
|
494
|
+
...resolveDefaultProps(props, defaultCartesianGridProps),
|
|
495
|
+
x: isNumber(props.x) ? props.x : offset.left,
|
|
496
|
+
y: isNumber(props.y) ? props.y : offset.top,
|
|
497
|
+
width: isNumber(props.width) ? props.width : offset.width,
|
|
498
|
+
height: isNumber(props.height) ? props.height : offset.height,
|
|
499
|
+
};
|
|
500
|
+
|
|
501
|
+
const {
|
|
502
|
+
xAxisId,
|
|
503
|
+
yAxisId,
|
|
504
|
+
x,
|
|
505
|
+
y,
|
|
506
|
+
width,
|
|
507
|
+
height,
|
|
508
|
+
syncWithTicks,
|
|
509
|
+
horizontalValues,
|
|
510
|
+
verticalValues,
|
|
511
|
+
} = propsIncludingDefaults;
|
|
512
|
+
|
|
513
|
+
const isPanorama = useIsPanorama();
|
|
514
|
+
const xAxis: AxisPropsForCartesianGridTicksGeneration | undefined = useAppSelector(
|
|
515
|
+
(state) => selectAxisPropsNeededForCartesianGridTicksGenerator(
|
|
516
|
+
state,
|
|
517
|
+
'xAxis',
|
|
518
|
+
xAxisId,
|
|
519
|
+
isPanorama,
|
|
520
|
+
),
|
|
521
|
+
);
|
|
522
|
+
const yAxis: AxisPropsForCartesianGridTicksGeneration | undefined = useAppSelector(
|
|
523
|
+
(state) => selectAxisPropsNeededForCartesianGridTicksGenerator(
|
|
524
|
+
state,
|
|
525
|
+
'yAxis',
|
|
526
|
+
yAxisId,
|
|
527
|
+
isPanorama,
|
|
528
|
+
),
|
|
529
|
+
);
|
|
530
|
+
|
|
531
|
+
if (!isPositiveNumber(width) || !isPositiveNumber(height) || !isNumber(x) || !isNumber(y)) {
|
|
532
|
+
return null;
|
|
533
|
+
}
|
|
534
|
+
|
|
535
|
+
/*
|
|
536
|
+
* verticalCoordinatesGenerator and horizontalCoordinatesGenerator are defined
|
|
537
|
+
* outside the propsIncludingDefaults because they were never part of the original props
|
|
538
|
+
* and they were never passed as a prop down to horizontal/vertical custom elements.
|
|
539
|
+
* If we add these two to propsIncludingDefaults then we are changing public API.
|
|
540
|
+
* Not a bad thing per se but also not necessary.
|
|
541
|
+
*/
|
|
542
|
+
const verticalCoordinatesGenerator =
|
|
543
|
+
propsIncludingDefaults.verticalCoordinatesGenerator || defaultVerticalCoordinatesGenerator;
|
|
544
|
+
const horizontalCoordinatesGenerator =
|
|
545
|
+
propsIncludingDefaults.horizontalCoordinatesGenerator || defaultHorizontalCoordinatesGenerator;
|
|
546
|
+
|
|
547
|
+
let { horizontalPoints, verticalPoints } = propsIncludingDefaults;
|
|
548
|
+
|
|
549
|
+
// No horizontal points are specified
|
|
550
|
+
if (
|
|
551
|
+
(!horizontalPoints || !horizontalPoints.length) &&
|
|
552
|
+
typeof horizontalCoordinatesGenerator === 'function'
|
|
553
|
+
) {
|
|
554
|
+
const isHorizontalValues = horizontalValues && horizontalValues.length;
|
|
555
|
+
|
|
556
|
+
const generatorResult = horizontalCoordinatesGenerator(
|
|
557
|
+
{
|
|
558
|
+
yAxis: yAxis
|
|
559
|
+
? {
|
|
560
|
+
...yAxis,
|
|
561
|
+
ticks: isHorizontalValues ? horizontalValues : yAxis.ticks,
|
|
562
|
+
}
|
|
563
|
+
: undefined,
|
|
564
|
+
width: chartWidth ?? width,
|
|
565
|
+
height: chartHeight ?? height,
|
|
566
|
+
offset,
|
|
567
|
+
},
|
|
568
|
+
isHorizontalValues ? true : syncWithTicks,
|
|
569
|
+
);
|
|
570
|
+
|
|
571
|
+
warn(
|
|
572
|
+
Array.isArray(generatorResult),
|
|
573
|
+
`horizontalCoordinatesGenerator should return Array but instead it returned [${typeof generatorResult}]`,
|
|
574
|
+
);
|
|
575
|
+
if (Array.isArray(generatorResult)) {
|
|
576
|
+
horizontalPoints = generatorResult;
|
|
577
|
+
}
|
|
578
|
+
}
|
|
579
|
+
|
|
580
|
+
// No vertical points are specified
|
|
581
|
+
if (
|
|
582
|
+
(!verticalPoints || !verticalPoints.length) &&
|
|
583
|
+
typeof verticalCoordinatesGenerator === 'function'
|
|
584
|
+
) {
|
|
585
|
+
const isVerticalValues = verticalValues && verticalValues.length;
|
|
586
|
+
const generatorResult = verticalCoordinatesGenerator(
|
|
587
|
+
{
|
|
588
|
+
xAxis: xAxis
|
|
589
|
+
? {
|
|
590
|
+
...xAxis,
|
|
591
|
+
ticks: isVerticalValues ? verticalValues : xAxis.ticks,
|
|
592
|
+
}
|
|
593
|
+
: undefined,
|
|
594
|
+
width: chartWidth ?? width,
|
|
595
|
+
height: chartHeight ?? height,
|
|
596
|
+
offset,
|
|
597
|
+
},
|
|
598
|
+
isVerticalValues ? true : syncWithTicks,
|
|
599
|
+
);
|
|
600
|
+
warn(
|
|
601
|
+
Array.isArray(generatorResult),
|
|
602
|
+
`verticalCoordinatesGenerator should return Array but instead it returned [${typeof generatorResult}]`,
|
|
603
|
+
);
|
|
604
|
+
if (Array.isArray(generatorResult)) {
|
|
605
|
+
verticalPoints = generatorResult;
|
|
606
|
+
}
|
|
607
|
+
}
|
|
608
|
+
|
|
609
|
+
return <ZIndexLayer zIndex={propsIncludingDefaults.zIndex}>
|
|
610
|
+
<g className="recharts-cartesian-grid">
|
|
611
|
+
<Background
|
|
612
|
+
fill={propsIncludingDefaults.fill}
|
|
613
|
+
fillOpacity={propsIncludingDefaults.fillOpacity}
|
|
614
|
+
x={propsIncludingDefaults.x}
|
|
615
|
+
y={propsIncludingDefaults.y}
|
|
616
|
+
width={propsIncludingDefaults.width}
|
|
617
|
+
height={propsIncludingDefaults.height}
|
|
618
|
+
ry={propsIncludingDefaults.ry}
|
|
619
|
+
/>
|
|
620
|
+
|
|
621
|
+
<HorizontalStripes {...propsIncludingDefaults} horizontalPoints={horizontalPoints} />
|
|
622
|
+
<VerticalStripes {...propsIncludingDefaults} verticalPoints={verticalPoints} />
|
|
623
|
+
|
|
624
|
+
<HorizontalGridLines
|
|
625
|
+
{...propsIncludingDefaults}
|
|
626
|
+
offset={offset}
|
|
627
|
+
horizontalPoints={horizontalPoints}
|
|
628
|
+
xAxis={xAxis}
|
|
629
|
+
yAxis={yAxis}
|
|
630
|
+
/>
|
|
631
|
+
|
|
632
|
+
<VerticalGridLines
|
|
633
|
+
{...propsIncludingDefaults}
|
|
634
|
+
offset={offset}
|
|
635
|
+
verticalPoints={verticalPoints}
|
|
636
|
+
xAxis={xAxis}
|
|
637
|
+
yAxis={yAxis}
|
|
638
|
+
/>
|
|
639
|
+
</g>
|
|
640
|
+
</ZIndexLayer>;
|
|
641
|
+
}
|
|
642
|
+
|
|
643
|
+
CartesianGrid.displayName = 'CartesianGrid';
|