chartLayoutContext.js
7.09 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
import React, { createContext, useContext } from 'react';
import invariant from 'tiny-invariant';
import find from 'lodash/find';
import every from 'lodash/every';
import { calculateViewBox } from '../util/calculateViewBox';
import { getAnyElementOfObject } from '../util/DataUtils';
export var XAxisContext = /*#__PURE__*/createContext(undefined);
export var YAxisContext = /*#__PURE__*/createContext(undefined);
export var ViewBoxContext = /*#__PURE__*/createContext(undefined);
export var OffsetContext = /*#__PURE__*/createContext({});
export var ClipPathIdContext = /*#__PURE__*/createContext(undefined);
export var ChartHeightContext = /*#__PURE__*/createContext(0);
export var ChartWidthContext = /*#__PURE__*/createContext(0);
/**
* Will add all the properties required to render all individual Recharts components into a React Context.
*
* If you want to read these properties, see the collection of hooks exported from this file.
*
* @param {object} props CategoricalChartState, plus children
* @returns {ReactElement} React Context Provider
*/
export var ChartLayoutContextProvider = function ChartLayoutContextProvider(props) {
var _props$state = props.state,
xAxisMap = _props$state.xAxisMap,
yAxisMap = _props$state.yAxisMap,
offset = _props$state.offset,
clipPathId = props.clipPathId,
children = props.children,
width = props.width,
height = props.height;
/**
* Perhaps we should compute this property when reading? Let's see what is more often used
*/
var viewBox = calculateViewBox(offset);
/*
* This pretends to be a single context but actually is split into multiple smaller ones.
* Why?
* Because one React Context only allows to set one value.
* But we need to set multiple values.
* If we do that with one context, then we force re-render on components that might not even be interested
* in the part of the state that has changed.
*
* By splitting into smaller contexts, we allow each components to be optimized and only re-render when its dependencies change.
*
* To actually achieve the optimal re-render, it is necessary to use React.memo().
* See the test file for details.
*/
return /*#__PURE__*/React.createElement(XAxisContext.Provider, {
value: xAxisMap
}, /*#__PURE__*/React.createElement(YAxisContext.Provider, {
value: yAxisMap
}, /*#__PURE__*/React.createElement(OffsetContext.Provider, {
value: offset
}, /*#__PURE__*/React.createElement(ViewBoxContext.Provider, {
value: viewBox
}, /*#__PURE__*/React.createElement(ClipPathIdContext.Provider, {
value: clipPathId
}, /*#__PURE__*/React.createElement(ChartHeightContext.Provider, {
value: height
}, /*#__PURE__*/React.createElement(ChartWidthContext.Provider, {
value: width
}, children)))))));
};
export var useClipPathId = function useClipPathId() {
return useContext(ClipPathIdContext);
};
function getKeysForDebug(object) {
var keys = Object.keys(object);
if (keys.length === 0) {
return 'There are no available ids.';
}
return "Available ids are: ".concat(keys, ".");
}
/**
* This either finds and returns Axis by the specified ID, or throws an exception if an axis with this ID does not exist.
*
* @param xAxisId identifier of the axis - it's either autogenerated ('0'), or passed via `id` prop as <XAxis id='foo' />
* @returns axis configuration object
* @throws Error if no axis with this ID exists
*/
export var useXAxisOrThrow = function useXAxisOrThrow(xAxisId) {
var xAxisMap = useContext(XAxisContext);
!(xAxisMap != null) ? process.env.NODE_ENV !== "production" ? invariant(false, 'Could not find Recharts context; are you sure this is rendered inside a Recharts wrapper component?') : invariant(false) : void 0;
var xAxis = xAxisMap[xAxisId];
!(xAxis != null) ? process.env.NODE_ENV !== "production" ? invariant(false, "Could not find xAxis by id \"".concat(xAxisId, "\" [").concat(_typeof(xAxisId), "]. ").concat(getKeysForDebug(xAxisMap))) : invariant(false) : void 0;
return xAxis;
};
/**
* This will find an arbitrary first XAxis. If there's exactly one it always returns that one
* - but if there are multiple then it can return any of those.
*
* If you want specific XAxis out of multiple then prefer using useXAxisOrThrow
*
* @returns X axisOptions, or undefined - if there are no X axes
*/
export var useArbitraryXAxis = function useArbitraryXAxis() {
var xAxisMap = useContext(XAxisContext);
return getAnyElementOfObject(xAxisMap);
};
/**
* This will find an arbitrary first YAxis. If there's exactly one it always returns that one
* - but if there are multiple then it can return any of those.
*
* If you want specific YAxis out of multiple then prefer using useXAxisOrThrow
*
* @returns Y axisOptions, or undefined - if there are no Y axes
*/
export var useArbitraryYAxis = function useArbitraryYAxis() {
var yAxisMap = useContext(YAxisContext);
return getAnyElementOfObject(yAxisMap);
};
/**
* This hooks will:
* 1st attempt to find an YAxis that has all elements in its domain finite
* If no such axis exists, it will return an arbitrary YAxis
* if there are no Y axes then it returns undefined
*
* @returns Either Y axisOptions, or undefined if there are no Y axes
*/
export var useYAxisWithFiniteDomainOrRandom = function useYAxisWithFiniteDomainOrRandom() {
var yAxisMap = useContext(YAxisContext);
var yAxisWithFiniteDomain = find(yAxisMap, function (axis) {
return every(axis.domain, Number.isFinite);
});
return yAxisWithFiniteDomain || getAnyElementOfObject(yAxisMap);
};
/**
* This either finds and returns Axis by the specified ID, or throws an exception if an axis with this ID does not exist.
*
* @param yAxisId identifier of the axis - it's either autogenerated ('0'), or passed via `id` prop as <YAxis id='foo' />
* @returns axis configuration object
* @throws Error if no axis with this ID exists
*/
export var useYAxisOrThrow = function useYAxisOrThrow(yAxisId) {
var yAxisMap = useContext(YAxisContext);
!(yAxisMap != null) ? process.env.NODE_ENV !== "production" ? invariant(false, 'Could not find Recharts context; are you sure this is rendered inside a Recharts wrapper component?') : invariant(false) : void 0;
var yAxis = yAxisMap[yAxisId];
!(yAxis != null) ? process.env.NODE_ENV !== "production" ? invariant(false, "Could not find yAxis by id \"".concat(yAxisId, "\" [").concat(_typeof(yAxisId), "]. ").concat(getKeysForDebug(yAxisMap))) : invariant(false) : void 0;
return yAxis;
};
export var useViewBox = function useViewBox() {
var viewBox = useContext(ViewBoxContext);
return viewBox;
};
export var useOffset = function useOffset() {
return useContext(OffsetContext);
};
export var useChartWidth = function useChartWidth() {
return useContext(ChartWidthContext);
};
export var useChartHeight = function useChartHeight() {
return useContext(ChartHeightContext);
};