victory-box-plot 36.9.2 → 37.0.0
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/CHANGELOG.md +6 -0
- package/dist/victory-box-plot.js +3764 -4910
- package/dist/victory-box-plot.min.js +1 -1
- package/es/helper-methods.js +268 -320
- package/es/victory-box-plot.js +87 -151
- package/lib/helper-methods.js +268 -334
- package/lib/index.js +0 -2
- package/lib/victory-box-plot.js +87 -158
- package/package.json +3 -3
package/es/helper-methods.js
CHANGED
|
@@ -2,47 +2,32 @@ import _groupBy from "lodash/groupBy";
|
|
|
2
2
|
import _uniq from "lodash/uniq";
|
|
3
3
|
import _defaults from "lodash/defaults";
|
|
4
4
|
import _orderBy from "lodash/orderBy";
|
|
5
|
-
|
|
6
|
-
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
|
|
7
|
-
|
|
8
5
|
import { Helpers, Scale, Domain, Data, Collection } from "victory-core";
|
|
9
6
|
import { min as d3Min, max as d3Max, quantile as d3Quantile } from "victory-vendor/d3-array";
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
var checkProcessedData = function (data) {
|
|
7
|
+
const TYPES = ["max", "min", "median", "q1", "q3"];
|
|
8
|
+
const checkProcessedData = data => {
|
|
13
9
|
/* check if the data is pre-processed. start by checking that it has
|
|
14
10
|
all required quartile attributes. */
|
|
15
|
-
|
|
16
|
-
return TYPES.every(
|
|
17
|
-
return typeof datum["_".concat(val)] !== "undefined";
|
|
18
|
-
});
|
|
11
|
+
const hasQuartileAttributes = data.every(datum => {
|
|
12
|
+
return TYPES.every(val => typeof datum[`_${val}`] !== "undefined");
|
|
19
13
|
});
|
|
20
|
-
|
|
21
14
|
if (hasQuartileAttributes) {
|
|
22
15
|
// check that the independent variable is distinct
|
|
23
|
-
|
|
24
|
-
return d._x;
|
|
25
|
-
});
|
|
26
|
-
|
|
16
|
+
const values = data.map(d => d._x);
|
|
27
17
|
if (!_uniq(values).length === values.length) {
|
|
28
|
-
throw new Error(
|
|
18
|
+
throw new Error(`
|
|
19
|
+
data prop may only take an array of objects with a unique
|
|
20
|
+
independent variable. Make sure your x values are distinct.
|
|
21
|
+
`);
|
|
29
22
|
}
|
|
30
|
-
|
|
31
23
|
return true;
|
|
32
24
|
}
|
|
33
|
-
|
|
34
25
|
return false;
|
|
35
26
|
};
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
var getSummaryStatistics = function (data) {
|
|
42
|
-
var dependentVars = data.map(function (datum) {
|
|
43
|
-
return datum._y;
|
|
44
|
-
});
|
|
45
|
-
var quartiles = {
|
|
27
|
+
const nanToNull = val => Number.isNaN(val) ? null : val;
|
|
28
|
+
const getSummaryStatistics = data => {
|
|
29
|
+
const dependentVars = data.map(datum => datum._y);
|
|
30
|
+
const quartiles = {
|
|
46
31
|
_q1: nanToNull(d3Quantile(dependentVars, 0.25)),
|
|
47
32
|
// eslint-disable-line no-magic-numbers
|
|
48
33
|
_q3: nanToNull(d3Quantile(dependentVars, 0.75)),
|
|
@@ -55,46 +40,36 @@ var getSummaryStatistics = function (data) {
|
|
|
55
40
|
_y: data[0]._y
|
|
56
41
|
});
|
|
57
42
|
};
|
|
58
|
-
|
|
59
|
-
var processData = function (data) {
|
|
43
|
+
const processData = data => {
|
|
60
44
|
/* check if the data is coming in a pre-processed form,
|
|
61
45
|
i.e. { x || y, min, max, q1, q3, median }. if not, process it. */
|
|
62
|
-
|
|
63
|
-
|
|
46
|
+
const isProcessed = checkProcessedData(data);
|
|
64
47
|
if (!isProcessed) {
|
|
65
48
|
// check if the data is coming with x or y values as an array
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
return Array.isArray(datum._y);
|
|
71
|
-
});
|
|
72
|
-
var sortKey = "_y";
|
|
73
|
-
var groupKey = "_x";
|
|
74
|
-
|
|
49
|
+
const arrayX = data.every(datum => Array.isArray(datum._x));
|
|
50
|
+
const arrayY = data.every(datum => Array.isArray(datum._y));
|
|
51
|
+
const sortKey = "_y";
|
|
52
|
+
const groupKey = "_x";
|
|
75
53
|
if (arrayX) {
|
|
76
|
-
throw new Error(
|
|
54
|
+
throw new Error(`
|
|
55
|
+
data should not be given as in array for x
|
|
56
|
+
`);
|
|
77
57
|
} else if (arrayY) {
|
|
78
58
|
/* generate summary statistics for each datum. to do this, flatten
|
|
79
59
|
the depedentVarArray and process each datum separately */
|
|
80
|
-
return data.map(
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
});
|
|
84
|
-
|
|
85
|
-
var sortedData = _orderBy(dataArray, sortKey);
|
|
86
|
-
|
|
60
|
+
return data.map(datum => {
|
|
61
|
+
const dataArray = datum[sortKey].map(d => Object.assign({}, datum, {
|
|
62
|
+
[sortKey]: d
|
|
63
|
+
}));
|
|
64
|
+
const sortedData = _orderBy(dataArray, sortKey);
|
|
87
65
|
return getSummaryStatistics(sortedData);
|
|
88
66
|
});
|
|
89
67
|
} else {
|
|
90
68
|
/* Group data by independent variable and generate summary statistics for each group */
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
var sortedData = _orderBy(datum, sortKey);
|
|
97
|
-
|
|
69
|
+
const groupedData = _groupBy(data, groupKey);
|
|
70
|
+
return Object.keys(groupedData).map(key => {
|
|
71
|
+
const datum = groupedData[key];
|
|
72
|
+
const sortedData = _orderBy(datum, sortKey);
|
|
98
73
|
return getSummaryStatistics(sortedData);
|
|
99
74
|
});
|
|
100
75
|
}
|
|
@@ -102,84 +77,69 @@ var processData = function (data) {
|
|
|
102
77
|
return data;
|
|
103
78
|
}
|
|
104
79
|
};
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
var formattedData = Data.formatData(props.data, props, accessorTypes);
|
|
80
|
+
export const getData = props => {
|
|
81
|
+
const accessorTypes = TYPES.concat("x", "y");
|
|
82
|
+
const formattedData = Data.formatData(props.data, props, accessorTypes);
|
|
109
83
|
return formattedData.length ? processData(formattedData) : [];
|
|
110
84
|
};
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
return memo < datum["_".concat(axis)] ? memo : datum["_".concat(axis)];
|
|
85
|
+
const reduceDataset = (dataset, props, axis) => {
|
|
86
|
+
const minDomain = Domain.getMinFromProps(props, axis);
|
|
87
|
+
const maxDomain = Domain.getMaxFromProps(props, axis);
|
|
88
|
+
const minData = minDomain !== undefined ? minDomain : dataset.reduce((memo, datum) => {
|
|
89
|
+
return memo < datum[`_${axis}`] ? memo : datum[`_${axis}`];
|
|
117
90
|
}, Infinity);
|
|
118
|
-
|
|
119
|
-
return memo > datum[
|
|
91
|
+
const maxData = maxDomain !== undefined ? maxDomain : dataset.reduce((memo, datum) => {
|
|
92
|
+
return memo > datum[`_${axis}`] ? memo : datum[`_${axis}`];
|
|
120
93
|
}, -Infinity);
|
|
121
94
|
return Domain.getDomainFromMinMax(minData, maxData);
|
|
122
95
|
};
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
var minData = minDomain !== undefined ? minDomain : dataset.reduce(function (memo, datum) {
|
|
96
|
+
const getDomainFromMinMaxValues = (dataset, props, axis) => {
|
|
97
|
+
const minDomain = Domain.getMinFromProps(props, axis);
|
|
98
|
+
const maxDomain = Domain.getMaxFromProps(props, axis);
|
|
99
|
+
const minData = minDomain !== undefined ? minDomain : dataset.reduce((memo, datum) => {
|
|
128
100
|
return memo < datum._min ? memo : datum._min;
|
|
129
101
|
}, Infinity);
|
|
130
|
-
|
|
102
|
+
const maxData = maxDomain !== undefined ? maxDomain : dataset.reduce((memo, datum) => {
|
|
131
103
|
return memo > datum._max ? memo : datum._max;
|
|
132
104
|
}, -Infinity);
|
|
133
105
|
return Domain.getDomainFromMinMax(minData, maxData);
|
|
134
106
|
};
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
var dataset = getData(props);
|
|
140
|
-
|
|
107
|
+
const getDomainFromData = (props, axis) => {
|
|
108
|
+
const minDomain = Domain.getMinFromProps(props, axis);
|
|
109
|
+
const maxDomain = Domain.getMaxFromProps(props, axis);
|
|
110
|
+
const dataset = getData(props);
|
|
141
111
|
if (dataset.length < 1) {
|
|
142
112
|
return minDomain !== undefined && maxDomain !== undefined ? Domain.getDomainFromMinMax(minDomain, maxDomain) : undefined;
|
|
143
113
|
}
|
|
144
|
-
|
|
145
114
|
return axis === "y" ? getDomainFromMinMaxValues(dataset, props, axis) : reduceDataset(dataset, props, axis);
|
|
146
115
|
};
|
|
147
|
-
|
|
148
|
-
export var getDomain = function (props, axis) {
|
|
116
|
+
export const getDomain = (props, axis) => {
|
|
149
117
|
return Domain.createDomainFunction(getDomainFromData)(props, axis);
|
|
150
118
|
};
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
var baseStyle = styleObject["".concat(namespace, "Labels")] || styleObject.labels;
|
|
155
|
-
|
|
119
|
+
const getLabelStyle = (props, styleObject, namespace) => {
|
|
120
|
+
const component = props[`${namespace}LabelComponent`] || props.labelComponent;
|
|
121
|
+
const baseStyle = styleObject[`${namespace}Labels`] || styleObject.labels;
|
|
156
122
|
if (!Helpers.isTooltip(component)) {
|
|
157
123
|
return baseStyle;
|
|
158
124
|
}
|
|
159
|
-
|
|
160
|
-
var tooltipTheme = props.theme && props.theme.tooltip || {};
|
|
125
|
+
const tooltipTheme = props.theme && props.theme.tooltip || {};
|
|
161
126
|
return _defaults({}, tooltipTheme.style, baseStyle);
|
|
162
127
|
};
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
128
|
+
const getStyles = function (props, styleObject) {
|
|
129
|
+
if (styleObject === void 0) {
|
|
130
|
+
styleObject = {};
|
|
131
|
+
}
|
|
167
132
|
if (props.disableInlineStyles) {
|
|
168
133
|
return {};
|
|
169
134
|
}
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
var parentStyles = {
|
|
135
|
+
const style = props.style || {};
|
|
136
|
+
const parentStyles = {
|
|
173
137
|
height: "100%",
|
|
174
138
|
width: "100%"
|
|
175
139
|
};
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
var boxStyles = _defaults({}, style.boxes, styleObject.boxes);
|
|
180
|
-
|
|
181
|
-
var whiskerStyles = _defaults({}, style.whiskers, styleObject.whiskers);
|
|
182
|
-
|
|
140
|
+
const labelStyles = _defaults({}, style.labels, getLabelStyle(props, styleObject));
|
|
141
|
+
const boxStyles = _defaults({}, style.boxes, styleObject.boxes);
|
|
142
|
+
const whiskerStyles = _defaults({}, style.whiskers, styleObject.whiskers);
|
|
183
143
|
return {
|
|
184
144
|
boxes: boxStyles,
|
|
185
145
|
labels: labelStyles,
|
|
@@ -197,63 +157,67 @@ var getStyles = function (props) {
|
|
|
197
157
|
whiskers: whiskerStyles
|
|
198
158
|
};
|
|
199
159
|
};
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
160
|
+
const getCalculatedValues = props => {
|
|
161
|
+
const {
|
|
162
|
+
theme,
|
|
163
|
+
horizontal
|
|
164
|
+
} = props;
|
|
165
|
+
const data = getData(props);
|
|
166
|
+
const range = {
|
|
206
167
|
x: Helpers.getRange(props, "x"),
|
|
207
168
|
y: Helpers.getRange(props, "y")
|
|
208
169
|
};
|
|
209
|
-
|
|
170
|
+
const domain = {
|
|
210
171
|
x: getDomain(props, "x"),
|
|
211
172
|
y: getDomain(props, "y")
|
|
212
173
|
};
|
|
213
|
-
|
|
174
|
+
const scale = {
|
|
214
175
|
x: Scale.getBaseScale(props, "x").domain(domain.x).range(props.horizontal ? range.y : range.x),
|
|
215
176
|
y: Scale.getBaseScale(props, "y").domain(domain.y).range(props.horizontal ? range.x : range.y)
|
|
216
177
|
};
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
178
|
+
const defaultStyles = theme && theme.boxplot && theme.boxplot.style ? theme.boxplot.style : {};
|
|
179
|
+
const style = getStyles(props, defaultStyles);
|
|
180
|
+
const defaultOrientation = props.horizontal ? "top" : "right";
|
|
181
|
+
const labelOrientation = props.labelOrientation || defaultOrientation;
|
|
182
|
+
const boxWidth = props.boxWidth || 1;
|
|
222
183
|
return {
|
|
223
|
-
data
|
|
224
|
-
horizontal
|
|
225
|
-
domain
|
|
226
|
-
scale
|
|
227
|
-
style
|
|
228
|
-
labelOrientation
|
|
229
|
-
boxWidth
|
|
184
|
+
data,
|
|
185
|
+
horizontal,
|
|
186
|
+
domain,
|
|
187
|
+
scale,
|
|
188
|
+
style,
|
|
189
|
+
labelOrientation,
|
|
190
|
+
boxWidth
|
|
230
191
|
};
|
|
231
|
-
};
|
|
232
|
-
|
|
192
|
+
};
|
|
233
193
|
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
194
|
+
// eslint-disable-next-line complexity
|
|
195
|
+
const getWhiskerProps = (props, type) => {
|
|
196
|
+
const {
|
|
197
|
+
horizontal,
|
|
198
|
+
style,
|
|
199
|
+
boxWidth,
|
|
200
|
+
whiskerWidth,
|
|
201
|
+
datum,
|
|
202
|
+
scale,
|
|
203
|
+
index,
|
|
204
|
+
disableInlineStyles
|
|
205
|
+
} = props;
|
|
206
|
+
const {
|
|
207
|
+
min,
|
|
208
|
+
max,
|
|
209
|
+
q1,
|
|
210
|
+
q3,
|
|
211
|
+
x,
|
|
212
|
+
y
|
|
213
|
+
} = props.positions;
|
|
214
|
+
const boxValue = type === "min" ? q1 : q3;
|
|
215
|
+
const whiskerValue = type === "min" ? min : max;
|
|
216
|
+
const width = typeof whiskerWidth === "number" ? whiskerWidth : boxWidth;
|
|
253
217
|
return {
|
|
254
|
-
datum
|
|
255
|
-
index
|
|
256
|
-
scale
|
|
218
|
+
datum,
|
|
219
|
+
index,
|
|
220
|
+
scale,
|
|
257
221
|
majorWhisker: {
|
|
258
222
|
x1: horizontal ? boxValue : x,
|
|
259
223
|
y1: horizontal ? y : boxValue,
|
|
@@ -267,128 +231,127 @@ var getWhiskerProps = function (props, type) {
|
|
|
267
231
|
y2: horizontal ? y + width / 2 : whiskerValue
|
|
268
232
|
},
|
|
269
233
|
style: disableInlineStyles ? {} : style[type] || style.whisker,
|
|
270
|
-
disableInlineStyles
|
|
234
|
+
disableInlineStyles
|
|
271
235
|
};
|
|
272
236
|
};
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
237
|
+
const getBoxProps = (props, type) => {
|
|
238
|
+
const {
|
|
239
|
+
horizontal,
|
|
240
|
+
boxWidth,
|
|
241
|
+
style,
|
|
242
|
+
scale,
|
|
243
|
+
datum,
|
|
244
|
+
index,
|
|
245
|
+
disableInlineStyles
|
|
246
|
+
} = props;
|
|
247
|
+
const {
|
|
248
|
+
median,
|
|
249
|
+
q1,
|
|
250
|
+
q3,
|
|
251
|
+
x,
|
|
252
|
+
y
|
|
253
|
+
} = props.positions;
|
|
254
|
+
const defaultX = type === "q1" ? q1 : median;
|
|
255
|
+
const defaultY = type === "q1" ? median : q3;
|
|
256
|
+
const defaultWidth = type === "q1" ? median - q1 : q3 - median;
|
|
257
|
+
const defaultHeight = type === "q1" ? q1 - median : median - q3;
|
|
292
258
|
return {
|
|
293
|
-
datum
|
|
294
|
-
scale
|
|
295
|
-
index
|
|
259
|
+
datum,
|
|
260
|
+
scale,
|
|
261
|
+
index,
|
|
296
262
|
x: horizontal ? defaultX : x - boxWidth / 2,
|
|
297
263
|
y: horizontal ? y - boxWidth / 2 : defaultY,
|
|
298
264
|
width: horizontal ? defaultWidth : boxWidth,
|
|
299
265
|
height: horizontal ? boxWidth : defaultHeight,
|
|
300
266
|
style: disableInlineStyles ? {} : style[type] || style.boxes,
|
|
301
|
-
disableInlineStyles
|
|
267
|
+
disableInlineStyles
|
|
302
268
|
};
|
|
303
269
|
};
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
270
|
+
const getMedianProps = props => {
|
|
271
|
+
const {
|
|
272
|
+
boxWidth,
|
|
273
|
+
horizontal,
|
|
274
|
+
style,
|
|
275
|
+
datum,
|
|
276
|
+
scale,
|
|
277
|
+
index,
|
|
278
|
+
disableInlineStyles
|
|
279
|
+
} = props;
|
|
280
|
+
const {
|
|
281
|
+
median,
|
|
282
|
+
x,
|
|
283
|
+
y
|
|
284
|
+
} = props.positions;
|
|
317
285
|
return {
|
|
318
|
-
datum
|
|
319
|
-
scale
|
|
320
|
-
index
|
|
286
|
+
datum,
|
|
287
|
+
scale,
|
|
288
|
+
index,
|
|
321
289
|
x1: horizontal ? median : x - boxWidth / 2,
|
|
322
290
|
y1: horizontal ? y - boxWidth / 2 : median,
|
|
323
291
|
x2: horizontal ? median : x + boxWidth / 2,
|
|
324
292
|
y2: horizontal ? y + boxWidth / 2 : median,
|
|
325
293
|
style: disableInlineStyles ? {} : style.median,
|
|
326
|
-
disableInlineStyles
|
|
294
|
+
disableInlineStyles
|
|
327
295
|
};
|
|
328
296
|
};
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
297
|
+
const getText = (props, type) => {
|
|
298
|
+
const {
|
|
299
|
+
datum,
|
|
300
|
+
index,
|
|
301
|
+
labels
|
|
302
|
+
} = props;
|
|
303
|
+
const propName = `${type}Labels`;
|
|
304
|
+
const labelProp = props[propName];
|
|
337
305
|
if (!labelProp && !labels) {
|
|
338
306
|
return null;
|
|
339
307
|
} else if (labelProp === true || labels === true) {
|
|
340
|
-
|
|
341
|
-
return
|
|
308
|
+
const dataName = `_${type}`;
|
|
309
|
+
return `${datum[dataName]}`;
|
|
342
310
|
}
|
|
343
|
-
|
|
344
311
|
return Array.isArray(labelProp) ? labelProp[index] : labelProp;
|
|
345
312
|
};
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
var labelStyle = style[namespace] || style.labels;
|
|
364
|
-
var defaultVerticalAnchors = {
|
|
313
|
+
const getOrientation = (labelOrientation, type) => typeof labelOrientation === "object" && labelOrientation[type] || labelOrientation;
|
|
314
|
+
const getLabelProps = (props, text, type) => {
|
|
315
|
+
const {
|
|
316
|
+
datum,
|
|
317
|
+
positions,
|
|
318
|
+
index,
|
|
319
|
+
boxWidth,
|
|
320
|
+
horizontal,
|
|
321
|
+
labelOrientation,
|
|
322
|
+
style,
|
|
323
|
+
theme,
|
|
324
|
+
disableInlineStyles
|
|
325
|
+
} = props;
|
|
326
|
+
const orientation = getOrientation(labelOrientation, type);
|
|
327
|
+
const namespace = `${type}Labels`;
|
|
328
|
+
const labelStyle = style[namespace] || style.labels;
|
|
329
|
+
const defaultVerticalAnchors = {
|
|
365
330
|
top: "end",
|
|
366
331
|
bottom: "start",
|
|
367
332
|
left: "middle",
|
|
368
333
|
right: "middle"
|
|
369
334
|
};
|
|
370
|
-
|
|
335
|
+
const defaultTextAnchors = {
|
|
371
336
|
left: "end",
|
|
372
337
|
right: "start",
|
|
373
338
|
top: "middle",
|
|
374
339
|
bottom: "middle"
|
|
375
340
|
};
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
var sign = {
|
|
341
|
+
const whiskerWidth = typeof props.whiskerWidth === "number" ? props.whiskerWidth : boxWidth;
|
|
342
|
+
const width = type === "min" || type === "max" ? whiskerWidth : boxWidth;
|
|
343
|
+
const getOffset = coord => {
|
|
344
|
+
const sign = {
|
|
381
345
|
x: orientation === "left" ? -1 : 1,
|
|
382
346
|
y: orientation === "top" ? -1 : 1
|
|
383
347
|
};
|
|
384
348
|
return sign[coord] * width / 2 + sign[coord] * (labelStyle.padding || 0);
|
|
385
349
|
};
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
orientation: orientation,
|
|
350
|
+
const labelProps = {
|
|
351
|
+
text,
|
|
352
|
+
datum,
|
|
353
|
+
index,
|
|
354
|
+
orientation,
|
|
392
355
|
style: disableInlineStyles ? {} : labelStyle,
|
|
393
356
|
y: horizontal ? positions.y : positions[type],
|
|
394
357
|
x: horizontal ? positions[type] : positions.x,
|
|
@@ -397,106 +360,92 @@ var getLabelProps = function (props, text, type) {
|
|
|
397
360
|
textAnchor: labelStyle.textAnchor || defaultTextAnchors[orientation],
|
|
398
361
|
verticalAnchor: labelStyle.verticalAnchor || defaultVerticalAnchors[orientation],
|
|
399
362
|
angle: labelStyle.angle,
|
|
400
|
-
horizontal
|
|
401
|
-
disableInlineStyles
|
|
363
|
+
horizontal,
|
|
364
|
+
disableInlineStyles
|
|
402
365
|
};
|
|
403
|
-
|
|
404
|
-
|
|
366
|
+
const component = props[`${type}LabelComponent`];
|
|
405
367
|
if (!Helpers.isTooltip(component)) {
|
|
406
368
|
return labelProps;
|
|
407
369
|
}
|
|
408
|
-
|
|
409
|
-
var tooltipTheme = theme && theme.tooltip || {};
|
|
370
|
+
const tooltipTheme = theme && theme.tooltip || {};
|
|
410
371
|
return _defaults({}, labelProps, Helpers.omit(tooltipTheme, ["style"]));
|
|
411
372
|
};
|
|
412
|
-
|
|
413
|
-
var getDataProps = function (props, type) {
|
|
373
|
+
const getDataProps = (props, type) => {
|
|
414
374
|
if (type === "median") {
|
|
415
375
|
return getMedianProps(props);
|
|
416
376
|
} else if (type === "min" || type === "max") {
|
|
417
377
|
return getWhiskerProps(props, type);
|
|
418
378
|
}
|
|
419
|
-
|
|
420
379
|
return getBoxProps(props, type);
|
|
421
|
-
};
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
var isDatumOutOfBounds = function (datum, domain) {
|
|
425
|
-
var exists = function (val) {
|
|
426
|
-
return val !== undefined;
|
|
427
|
-
};
|
|
428
|
-
|
|
429
|
-
var _x = datum._x,
|
|
430
|
-
_min = datum._min,
|
|
431
|
-
_max = datum._max;
|
|
432
|
-
var minDomainX = Collection.getMinValue(domain.x);
|
|
433
|
-
var maxDomainX = Collection.getMaxValue(domain.x);
|
|
434
|
-
var minDomainY = Collection.getMinValue(domain.y);
|
|
435
|
-
var maxDomainY = Collection.getMaxValue(domain.y);
|
|
436
|
-
|
|
437
|
-
var underMin = function (min) {
|
|
438
|
-
return function (val) {
|
|
439
|
-
return exists(val) && val < min;
|
|
440
|
-
};
|
|
441
|
-
};
|
|
442
|
-
|
|
443
|
-
var overMax = function (max) {
|
|
444
|
-
return function (val) {
|
|
445
|
-
return exists(val) && val > max;
|
|
446
|
-
};
|
|
447
|
-
};
|
|
448
|
-
|
|
449
|
-
var isUnderMinX = underMin(minDomainX);
|
|
450
|
-
var isUnderMinY = underMin(minDomainY);
|
|
451
|
-
var isOverMaxX = overMax(maxDomainX);
|
|
452
|
-
var isOverMaxY = overMax(maxDomainY);
|
|
453
|
-
var yOutOfBounds;
|
|
454
|
-
var xOutOfBounds; // if x is out of the bounds of the domain
|
|
455
|
-
|
|
456
|
-
if (isUnderMinX(_x) || isOverMaxX(_x)) xOutOfBounds = true; // if min/max are out of the bounds of the domain
|
|
380
|
+
};
|
|
457
381
|
|
|
382
|
+
// if all data points on an axis are out of bound of the domain, filter out this datum
|
|
383
|
+
const isDatumOutOfBounds = (datum, domain) => {
|
|
384
|
+
const exists = val => val !== undefined;
|
|
385
|
+
const {
|
|
386
|
+
_x,
|
|
387
|
+
_min,
|
|
388
|
+
_max
|
|
389
|
+
} = datum;
|
|
390
|
+
const minDomainX = Collection.getMinValue(domain.x);
|
|
391
|
+
const maxDomainX = Collection.getMaxValue(domain.x);
|
|
392
|
+
const minDomainY = Collection.getMinValue(domain.y);
|
|
393
|
+
const maxDomainY = Collection.getMaxValue(domain.y);
|
|
394
|
+
const underMin = min => val => exists(val) && val < min;
|
|
395
|
+
const overMax = max => val => exists(val) && val > max;
|
|
396
|
+
const isUnderMinX = underMin(minDomainX);
|
|
397
|
+
const isUnderMinY = underMin(minDomainY);
|
|
398
|
+
const isOverMaxX = overMax(maxDomainX);
|
|
399
|
+
const isOverMaxY = overMax(maxDomainY);
|
|
400
|
+
let yOutOfBounds;
|
|
401
|
+
let xOutOfBounds;
|
|
402
|
+
|
|
403
|
+
// if x is out of the bounds of the domain
|
|
404
|
+
if (isUnderMinX(_x) || isOverMaxX(_x)) xOutOfBounds = true;
|
|
405
|
+
// if min/max are out of the bounds of the domain
|
|
458
406
|
if (isUnderMinY(_min) && isUnderMinY(_max) || isOverMaxY(_min) && isOverMaxY(_max)) yOutOfBounds = true;
|
|
459
407
|
return yOutOfBounds || xOutOfBounds;
|
|
460
408
|
};
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
409
|
+
export const getBaseProps = (initialProps, fallbackProps) => {
|
|
410
|
+
const modifiedProps = Helpers.modifyProps(initialProps, fallbackProps, "boxplot");
|
|
411
|
+
const props = Object.assign({}, modifiedProps, getCalculatedValues(modifiedProps));
|
|
412
|
+
const {
|
|
413
|
+
groupComponent,
|
|
414
|
+
width,
|
|
415
|
+
height,
|
|
416
|
+
padding,
|
|
417
|
+
standalone,
|
|
418
|
+
theme,
|
|
419
|
+
events,
|
|
420
|
+
sharedEvents,
|
|
421
|
+
scale,
|
|
422
|
+
horizontal,
|
|
423
|
+
data,
|
|
424
|
+
style,
|
|
425
|
+
domain,
|
|
426
|
+
name
|
|
427
|
+
} = props;
|
|
428
|
+
const initialChildProps = {
|
|
480
429
|
parent: {
|
|
481
|
-
domain
|
|
482
|
-
scale
|
|
483
|
-
width
|
|
484
|
-
height
|
|
485
|
-
data
|
|
486
|
-
standalone
|
|
487
|
-
name
|
|
488
|
-
theme
|
|
430
|
+
domain,
|
|
431
|
+
scale,
|
|
432
|
+
width,
|
|
433
|
+
height,
|
|
434
|
+
data,
|
|
435
|
+
standalone,
|
|
436
|
+
name,
|
|
437
|
+
theme,
|
|
489
438
|
style: style.parent || {},
|
|
490
|
-
padding
|
|
491
|
-
groupComponent
|
|
492
|
-
horizontal
|
|
439
|
+
padding,
|
|
440
|
+
groupComponent,
|
|
441
|
+
horizontal
|
|
493
442
|
}
|
|
494
443
|
};
|
|
495
|
-
|
|
496
|
-
return data.reduce(
|
|
497
|
-
|
|
444
|
+
const boxScale = scale.y;
|
|
445
|
+
return data.reduce((acc, datum, index) => {
|
|
446
|
+
const eventKey = !Helpers.isNil(datum.eventKey) ? datum.eventKey : index;
|
|
498
447
|
if (isDatumOutOfBounds(datum, domain)) return acc;
|
|
499
|
-
|
|
448
|
+
const positions = {
|
|
500
449
|
x: horizontal ? scale.y(datum._y) : scale.x(datum._x),
|
|
501
450
|
y: horizontal ? scale.x(datum._x) : scale.y(datum._y),
|
|
502
451
|
min: boxScale(datum._min),
|
|
@@ -505,22 +454,21 @@ export var getBaseProps = function (initialProps, fallbackProps) {
|
|
|
505
454
|
q1: boxScale(datum._q1),
|
|
506
455
|
q3: boxScale(datum._q3)
|
|
507
456
|
};
|
|
508
|
-
|
|
509
|
-
index
|
|
510
|
-
datum
|
|
511
|
-
positions
|
|
457
|
+
const dataProps = Object.assign({
|
|
458
|
+
index,
|
|
459
|
+
datum,
|
|
460
|
+
positions
|
|
512
461
|
}, props);
|
|
513
|
-
|
|
462
|
+
const dataObj = TYPES.reduce((memo, type) => {
|
|
514
463
|
memo[type] = getDataProps(dataProps, type);
|
|
515
464
|
return memo;
|
|
516
465
|
}, {});
|
|
517
466
|
acc[eventKey] = dataObj;
|
|
518
|
-
TYPES.forEach(
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
467
|
+
TYPES.forEach(type => {
|
|
468
|
+
const labelText = getText(dataProps, type);
|
|
469
|
+
const labelProp = props.labels || props[`${type}Labels`];
|
|
522
470
|
if (labelText !== null && labelText !== undefined || labelProp && (events || sharedEvents)) {
|
|
523
|
-
|
|
471
|
+
const target = `${type}Labels`;
|
|
524
472
|
acc[eventKey][target] = getLabelProps(Object.assign({}, props, dataProps), labelText, type);
|
|
525
473
|
}
|
|
526
474
|
});
|