victory-box-plot 31.0.0 → 31.3.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/README.md +70 -71
- package/dist/victory-box-plot.js +1884 -1503
- package/dist/victory-box-plot.min.js +1 -1
- package/es/helper-methods.js +20 -9
- package/es/victory-box-plot.js +46 -21
- package/lib/helper-methods.js +22 -9
- package/lib/victory-box-plot.js +47 -21
- package/package.json +2 -2
- package/src/helper-methods.js +94 -44
- package/src/victory-box-plot.js +120 -55
package/es/helper-methods.js
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import _isNil from "lodash/isNil";
|
|
2
|
+
import _isNaN from "lodash/isNaN";
|
|
1
3
|
import _keys from "lodash/keys";
|
|
2
4
|
import _groupBy from "lodash/groupBy";
|
|
3
5
|
import _uniq from "lodash/uniq";
|
|
@@ -16,7 +18,7 @@ var checkProcessedData = function (props, data) {
|
|
|
16
18
|
all required quartile attributes. */
|
|
17
19
|
var hasQuartileAttributes = data.every(function (datum) {
|
|
18
20
|
return TYPES.every(function (val) {
|
|
19
|
-
return typeof datum["_".concat(val)]
|
|
21
|
+
return typeof datum["_".concat(val)] !== "undefined";
|
|
20
22
|
});
|
|
21
23
|
});
|
|
22
24
|
|
|
@@ -38,18 +40,22 @@ var checkProcessedData = function (props, data) {
|
|
|
38
40
|
return false;
|
|
39
41
|
};
|
|
40
42
|
|
|
43
|
+
var nanToNull = function (val) {
|
|
44
|
+
return _isNaN(val) ? null : val;
|
|
45
|
+
};
|
|
46
|
+
|
|
41
47
|
var getSummaryStatistics = function (data, horizontal) {
|
|
42
48
|
var dependentVars = data.map(function (datum) {
|
|
43
49
|
return horizontal ? datum._x : datum._y;
|
|
44
50
|
});
|
|
45
51
|
var quartiles = {
|
|
46
|
-
_q1: d3Quantile(dependentVars, 0.25),
|
|
52
|
+
_q1: nanToNull(d3Quantile(dependentVars, 0.25)),
|
|
47
53
|
// eslint-disable-line no-magic-numbers
|
|
48
|
-
_q3: d3Quantile(dependentVars, 0.75),
|
|
54
|
+
_q3: nanToNull(d3Quantile(dependentVars, 0.75)),
|
|
49
55
|
// eslint-disable-line no-magic-numbers
|
|
50
|
-
_min: d3Min(dependentVars),
|
|
51
|
-
_median: d3Quantile(dependentVars, 0.5),
|
|
52
|
-
_max: d3Max(dependentVars)
|
|
56
|
+
_min: nanToNull(d3Min(dependentVars)),
|
|
57
|
+
_median: nanToNull(d3Quantile(dependentVars, 0.5)),
|
|
58
|
+
_max: nanToNull(d3Max(dependentVars))
|
|
53
59
|
};
|
|
54
60
|
return horizontal ? _assign({}, quartiles, {
|
|
55
61
|
_y: data[0]._y
|
|
@@ -334,6 +340,10 @@ var getText = function (props, type) {
|
|
|
334
340
|
return Array.isArray(labelProp) ? labelProp[index] : labelProp;
|
|
335
341
|
};
|
|
336
342
|
|
|
343
|
+
var getOrientation = function (labelOrientation, type) {
|
|
344
|
+
return typeof labelOrientation === "object" && labelOrientation[type] || labelOrientation;
|
|
345
|
+
};
|
|
346
|
+
|
|
337
347
|
var getLabelProps = function (props, text, type) {
|
|
338
348
|
var datum = props.datum,
|
|
339
349
|
positions = props.positions,
|
|
@@ -342,6 +352,7 @@ var getLabelProps = function (props, text, type) {
|
|
|
342
352
|
horizontal = props.horizontal,
|
|
343
353
|
labelOrientation = props.labelOrientation,
|
|
344
354
|
style = props.style;
|
|
355
|
+
var orientation = getOrientation(labelOrientation, type);
|
|
345
356
|
var namespace = "".concat(type, "Labels");
|
|
346
357
|
var labelStyle = style[namespace] || style.labels;
|
|
347
358
|
var defaultVerticalAnchor = horizontal ? "end" : "middle";
|
|
@@ -351,8 +362,8 @@ var getLabelProps = function (props, text, type) {
|
|
|
351
362
|
|
|
352
363
|
var getDefaultPosition = function (coord) {
|
|
353
364
|
var sign = {
|
|
354
|
-
x:
|
|
355
|
-
y:
|
|
365
|
+
x: orientation === "left" ? -1 : 1,
|
|
366
|
+
y: orientation === "top" ? -1 : 1
|
|
356
367
|
};
|
|
357
368
|
return positions[coord] + sign[coord] * width / 2 + sign[coord] * (labelStyle.padding || 0);
|
|
358
369
|
};
|
|
@@ -415,7 +426,7 @@ var getBaseProps = function (props, fallbackProps) {
|
|
|
415
426
|
};
|
|
416
427
|
var boxScale = horizontal ? scale.x : scale.y;
|
|
417
428
|
return data.reduce(function (acc, datum, index) {
|
|
418
|
-
var eventKey = datum.eventKey
|
|
429
|
+
var eventKey = !_isNil(datum.eventKey) ? datum.eventKey : index;
|
|
419
430
|
var positions = {
|
|
420
431
|
x: scale.x(datum._x),
|
|
421
432
|
y: scale.y(datum._y),
|
package/es/victory-box-plot.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import _isNil from "lodash/isNil";
|
|
1
2
|
import _flatten from "lodash/flatten";
|
|
2
3
|
|
|
3
4
|
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; var ownKeys = Object.keys(source); if (typeof Object.getOwnPropertySymbols === 'function') { ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function (sym) { return Object.getOwnPropertyDescriptor(source, sym).enumerable; })); } ownKeys.forEach(function (key) { _defineProperty(target, key, source[key]); }); } return target; }
|
|
@@ -38,6 +39,21 @@ var fallbackProps = {
|
|
|
38
39
|
left: 20
|
|
39
40
|
}
|
|
40
41
|
};
|
|
42
|
+
var defaultData = [{
|
|
43
|
+
x: 1,
|
|
44
|
+
min: 5,
|
|
45
|
+
q1: 7,
|
|
46
|
+
median: 12,
|
|
47
|
+
q3: 18,
|
|
48
|
+
max: 20
|
|
49
|
+
}, {
|
|
50
|
+
x: 2,
|
|
51
|
+
min: 2,
|
|
52
|
+
q1: 5,
|
|
53
|
+
median: 8,
|
|
54
|
+
q3: 12,
|
|
55
|
+
max: 15
|
|
56
|
+
}];
|
|
41
57
|
var options = {
|
|
42
58
|
components: [{
|
|
43
59
|
name: "min"
|
|
@@ -64,22 +80,6 @@ var options = {
|
|
|
64
80
|
index: "parent"
|
|
65
81
|
}]
|
|
66
82
|
};
|
|
67
|
-
var defaultData = [{
|
|
68
|
-
x: 1,
|
|
69
|
-
min: 5,
|
|
70
|
-
q1: 7,
|
|
71
|
-
median: 12,
|
|
72
|
-
q3: 18,
|
|
73
|
-
max: 20
|
|
74
|
-
}, {
|
|
75
|
-
x: 2,
|
|
76
|
-
min: 2,
|
|
77
|
-
q1: 5,
|
|
78
|
-
median: 8,
|
|
79
|
-
q3: 12,
|
|
80
|
-
max: 15
|
|
81
|
-
}];
|
|
82
|
-
var animationWhitelist = ["data", "domain", "height", "padding", "style", "width"];
|
|
83
83
|
|
|
84
84
|
var VictoryBoxPlot =
|
|
85
85
|
/*#__PURE__*/
|
|
@@ -100,13 +100,17 @@ function (_React$Component) {
|
|
|
100
100
|
var types = ["q1", "q3", "max", "min", "median"];
|
|
101
101
|
|
|
102
102
|
var dataComponents = _flatten(types.map(function (type) {
|
|
103
|
-
return _this.dataKeys.
|
|
103
|
+
return _this.dataKeys.reduce(function (validDataComponents, _key, index) {
|
|
104
104
|
var baseComponent = props["".concat(type, "Component")];
|
|
105
105
|
|
|
106
106
|
var componentProps = _this.getComponentProps(baseComponent, type, index);
|
|
107
107
|
|
|
108
|
-
|
|
109
|
-
|
|
108
|
+
if (_this.shouldRenderDatum(componentProps.datum)) {
|
|
109
|
+
validDataComponents.push(React.cloneElement(baseComponent, componentProps));
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
return validDataComponents;
|
|
113
|
+
}, []);
|
|
110
114
|
}));
|
|
111
115
|
|
|
112
116
|
var labelComponents = _flatten(types.map(function (type) {
|
|
@@ -136,10 +140,19 @@ function (_React$Component) {
|
|
|
136
140
|
value: function shouldAnimate() {
|
|
137
141
|
return !!this.props.animate;
|
|
138
142
|
}
|
|
143
|
+
}, {
|
|
144
|
+
key: "shouldRenderDatum",
|
|
145
|
+
value: function shouldRenderDatum(datum) {
|
|
146
|
+
var hasX = !_isNil(datum._x);
|
|
147
|
+
var hasY = !_isNil(datum._y);
|
|
148
|
+
var hasSummaryStatistics = !_isNil(datum._min) && !_isNil(datum._max) && !_isNil(datum._median) && !_isNil(datum._q1) && !_isNil(datum._q3);
|
|
149
|
+
return hasSummaryStatistics && (this.props.horizontal ? hasY : hasX);
|
|
150
|
+
}
|
|
139
151
|
}, {
|
|
140
152
|
key: "render",
|
|
141
153
|
value: function render() {
|
|
142
|
-
var
|
|
154
|
+
var animationWhitelist = VictoryBoxPlot.animationWhitelist,
|
|
155
|
+
role = VictoryBoxPlot.role;
|
|
143
156
|
var props = Helpers.modifyProps(this.props, fallbackProps, role);
|
|
144
157
|
|
|
145
158
|
if (this.shouldAnimate()) {
|
|
@@ -154,6 +167,12 @@ function (_React$Component) {
|
|
|
154
167
|
return VictoryBoxPlot;
|
|
155
168
|
}(React.Component);
|
|
156
169
|
|
|
170
|
+
Object.defineProperty(VictoryBoxPlot, "animationWhitelist", {
|
|
171
|
+
configurable: true,
|
|
172
|
+
enumerable: true,
|
|
173
|
+
writable: true,
|
|
174
|
+
value: ["data", "domain", "height", "padding", "style", "width"]
|
|
175
|
+
});
|
|
157
176
|
Object.defineProperty(VictoryBoxPlot, "displayName", {
|
|
158
177
|
configurable: true,
|
|
159
178
|
enumerable: true,
|
|
@@ -184,7 +203,13 @@ Object.defineProperty(VictoryBoxPlot, "propTypes", {
|
|
|
184
203
|
eventHandlers: PropTypes.object
|
|
185
204
|
})),
|
|
186
205
|
horizontal: PropTypes.bool,
|
|
187
|
-
labelOrientation: PropTypes.oneOf(["top", "bottom", "left", "right"]),
|
|
206
|
+
labelOrientation: PropTypes.oneOfType([PropTypes.oneOf(["top", "bottom", "left", "right"]), PropTypes.exact({
|
|
207
|
+
q1: PropTypes.oneOf(["top", "bottom", "left", "right"]),
|
|
208
|
+
q3: PropTypes.oneOf(["top", "bottom", "left", "right"]),
|
|
209
|
+
min: PropTypes.oneOf(["top", "bottom", "left", "right"]),
|
|
210
|
+
max: PropTypes.oneOf(["top", "bottom", "left", "right"]),
|
|
211
|
+
median: PropTypes.oneOf(["top", "bottom", "left", "right"])
|
|
212
|
+
})]),
|
|
188
213
|
labels: PropTypes.bool,
|
|
189
214
|
max: PropTypes.oneOfType([PropTypes.func, CustomPropTypes.allOfType([CustomPropTypes.integer, CustomPropTypes.nonNegative]), PropTypes.string, PropTypes.arrayOf(PropTypes.string)]),
|
|
190
215
|
maxComponent: PropTypes.element,
|
package/lib/helper-methods.js
CHANGED
|
@@ -5,6 +5,10 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
5
5
|
});
|
|
6
6
|
exports.getBaseProps = exports.getData = exports.getDomain = void 0;
|
|
7
7
|
|
|
8
|
+
var _isNil2 = _interopRequireDefault(require("lodash/isNil"));
|
|
9
|
+
|
|
10
|
+
var _isNaN2 = _interopRequireDefault(require("lodash/isNaN"));
|
|
11
|
+
|
|
8
12
|
var _keys2 = _interopRequireDefault(require("lodash/keys"));
|
|
9
13
|
|
|
10
14
|
var _groupBy2 = _interopRequireDefault(require("lodash/groupBy"));
|
|
@@ -32,7 +36,7 @@ var checkProcessedData = function (props, data) {
|
|
|
32
36
|
all required quartile attributes. */
|
|
33
37
|
var hasQuartileAttributes = data.every(function (datum) {
|
|
34
38
|
return TYPES.every(function (val) {
|
|
35
|
-
return typeof datum["_".concat(val)]
|
|
39
|
+
return typeof datum["_".concat(val)] !== "undefined";
|
|
36
40
|
});
|
|
37
41
|
});
|
|
38
42
|
|
|
@@ -54,18 +58,22 @@ var checkProcessedData = function (props, data) {
|
|
|
54
58
|
return false;
|
|
55
59
|
};
|
|
56
60
|
|
|
61
|
+
var nanToNull = function (val) {
|
|
62
|
+
return (0, _isNaN2.default)(val) ? null : val;
|
|
63
|
+
};
|
|
64
|
+
|
|
57
65
|
var getSummaryStatistics = function (data, horizontal) {
|
|
58
66
|
var dependentVars = data.map(function (datum) {
|
|
59
67
|
return horizontal ? datum._x : datum._y;
|
|
60
68
|
});
|
|
61
69
|
var quartiles = {
|
|
62
|
-
_q1: (0, _d3Array.quantile)(dependentVars, 0.25),
|
|
70
|
+
_q1: nanToNull((0, _d3Array.quantile)(dependentVars, 0.25)),
|
|
63
71
|
// eslint-disable-line no-magic-numbers
|
|
64
|
-
_q3: (0, _d3Array.quantile)(dependentVars, 0.75),
|
|
72
|
+
_q3: nanToNull((0, _d3Array.quantile)(dependentVars, 0.75)),
|
|
65
73
|
// eslint-disable-line no-magic-numbers
|
|
66
|
-
_min: (0, _d3Array.min)(dependentVars),
|
|
67
|
-
_median: (0, _d3Array.quantile)(dependentVars, 0.5),
|
|
68
|
-
_max: (0, _d3Array.max)(dependentVars)
|
|
74
|
+
_min: nanToNull((0, _d3Array.min)(dependentVars)),
|
|
75
|
+
_median: nanToNull((0, _d3Array.quantile)(dependentVars, 0.5)),
|
|
76
|
+
_max: nanToNull((0, _d3Array.max)(dependentVars))
|
|
69
77
|
};
|
|
70
78
|
return horizontal ? (0, _assign3.default)({}, quartiles, {
|
|
71
79
|
_y: data[0]._y
|
|
@@ -354,6 +362,10 @@ var getText = function (props, type) {
|
|
|
354
362
|
return Array.isArray(labelProp) ? labelProp[index] : labelProp;
|
|
355
363
|
};
|
|
356
364
|
|
|
365
|
+
var getOrientation = function (labelOrientation, type) {
|
|
366
|
+
return typeof labelOrientation === "object" && labelOrientation[type] || labelOrientation;
|
|
367
|
+
};
|
|
368
|
+
|
|
357
369
|
var getLabelProps = function (props, text, type) {
|
|
358
370
|
var datum = props.datum,
|
|
359
371
|
positions = props.positions,
|
|
@@ -362,6 +374,7 @@ var getLabelProps = function (props, text, type) {
|
|
|
362
374
|
horizontal = props.horizontal,
|
|
363
375
|
labelOrientation = props.labelOrientation,
|
|
364
376
|
style = props.style;
|
|
377
|
+
var orientation = getOrientation(labelOrientation, type);
|
|
365
378
|
var namespace = "".concat(type, "Labels");
|
|
366
379
|
var labelStyle = style[namespace] || style.labels;
|
|
367
380
|
var defaultVerticalAnchor = horizontal ? "end" : "middle";
|
|
@@ -371,8 +384,8 @@ var getLabelProps = function (props, text, type) {
|
|
|
371
384
|
|
|
372
385
|
var getDefaultPosition = function (coord) {
|
|
373
386
|
var sign = {
|
|
374
|
-
x:
|
|
375
|
-
y:
|
|
387
|
+
x: orientation === "left" ? -1 : 1,
|
|
388
|
+
y: orientation === "top" ? -1 : 1
|
|
376
389
|
};
|
|
377
390
|
return positions[coord] + sign[coord] * width / 2 + sign[coord] * (labelStyle.padding || 0);
|
|
378
391
|
};
|
|
@@ -436,7 +449,7 @@ var getBaseProps = function (props, fallbackProps) {
|
|
|
436
449
|
};
|
|
437
450
|
var boxScale = horizontal ? scale.x : scale.y;
|
|
438
451
|
return data.reduce(function (acc, datum, index) {
|
|
439
|
-
var eventKey = datum.eventKey
|
|
452
|
+
var eventKey = !(0, _isNil2.default)(datum.eventKey) ? datum.eventKey : index;
|
|
440
453
|
var positions = {
|
|
441
454
|
x: scale.x(datum._x),
|
|
442
455
|
y: scale.y(datum._y),
|
package/lib/victory-box-plot.js
CHANGED
|
@@ -5,6 +5,8 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
5
5
|
});
|
|
6
6
|
exports.default = void 0;
|
|
7
7
|
|
|
8
|
+
var _isNil2 = _interopRequireDefault(require("lodash/isNil"));
|
|
9
|
+
|
|
8
10
|
var _flatten2 = _interopRequireDefault(require("lodash/flatten"));
|
|
9
11
|
|
|
10
12
|
var _react = _interopRequireDefault(require("react"));
|
|
@@ -51,6 +53,21 @@ var fallbackProps = {
|
|
|
51
53
|
left: 20
|
|
52
54
|
}
|
|
53
55
|
};
|
|
56
|
+
var defaultData = [{
|
|
57
|
+
x: 1,
|
|
58
|
+
min: 5,
|
|
59
|
+
q1: 7,
|
|
60
|
+
median: 12,
|
|
61
|
+
q3: 18,
|
|
62
|
+
max: 20
|
|
63
|
+
}, {
|
|
64
|
+
x: 2,
|
|
65
|
+
min: 2,
|
|
66
|
+
q1: 5,
|
|
67
|
+
median: 8,
|
|
68
|
+
q3: 12,
|
|
69
|
+
max: 15
|
|
70
|
+
}];
|
|
54
71
|
var options = {
|
|
55
72
|
components: [{
|
|
56
73
|
name: "min"
|
|
@@ -77,22 +94,6 @@ var options = {
|
|
|
77
94
|
index: "parent"
|
|
78
95
|
}]
|
|
79
96
|
};
|
|
80
|
-
var defaultData = [{
|
|
81
|
-
x: 1,
|
|
82
|
-
min: 5,
|
|
83
|
-
q1: 7,
|
|
84
|
-
median: 12,
|
|
85
|
-
q3: 18,
|
|
86
|
-
max: 20
|
|
87
|
-
}, {
|
|
88
|
-
x: 2,
|
|
89
|
-
min: 2,
|
|
90
|
-
q1: 5,
|
|
91
|
-
median: 8,
|
|
92
|
-
q3: 12,
|
|
93
|
-
max: 15
|
|
94
|
-
}];
|
|
95
|
-
var animationWhitelist = ["data", "domain", "height", "padding", "style", "width"];
|
|
96
97
|
|
|
97
98
|
var VictoryBoxPlot =
|
|
98
99
|
/*#__PURE__*/
|
|
@@ -112,13 +113,17 @@ function (_React$Component) {
|
|
|
112
113
|
|
|
113
114
|
var types = ["q1", "q3", "max", "min", "median"];
|
|
114
115
|
var dataComponents = (0, _flatten2.default)(types.map(function (type) {
|
|
115
|
-
return _this.dataKeys.
|
|
116
|
+
return _this.dataKeys.reduce(function (validDataComponents, _key, index) {
|
|
116
117
|
var baseComponent = props["".concat(type, "Component")];
|
|
117
118
|
|
|
118
119
|
var componentProps = _this.getComponentProps(baseComponent, type, index);
|
|
119
120
|
|
|
120
|
-
|
|
121
|
-
|
|
121
|
+
if (_this.shouldRenderDatum(componentProps.datum)) {
|
|
122
|
+
validDataComponents.push(_react.default.cloneElement(baseComponent, componentProps));
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
return validDataComponents;
|
|
126
|
+
}, []);
|
|
122
127
|
}));
|
|
123
128
|
var labelComponents = (0, _flatten2.default)(types.map(function (type) {
|
|
124
129
|
var components = _this.dataKeys.map(function (key, index) {
|
|
@@ -147,10 +152,19 @@ function (_React$Component) {
|
|
|
147
152
|
value: function shouldAnimate() {
|
|
148
153
|
return !!this.props.animate;
|
|
149
154
|
}
|
|
155
|
+
}, {
|
|
156
|
+
key: "shouldRenderDatum",
|
|
157
|
+
value: function shouldRenderDatum(datum) {
|
|
158
|
+
var hasX = !(0, _isNil2.default)(datum._x);
|
|
159
|
+
var hasY = !(0, _isNil2.default)(datum._y);
|
|
160
|
+
var hasSummaryStatistics = !(0, _isNil2.default)(datum._min) && !(0, _isNil2.default)(datum._max) && !(0, _isNil2.default)(datum._median) && !(0, _isNil2.default)(datum._q1) && !(0, _isNil2.default)(datum._q3);
|
|
161
|
+
return hasSummaryStatistics && (this.props.horizontal ? hasY : hasX);
|
|
162
|
+
}
|
|
150
163
|
}, {
|
|
151
164
|
key: "render",
|
|
152
165
|
value: function render() {
|
|
153
|
-
var
|
|
166
|
+
var animationWhitelist = VictoryBoxPlot.animationWhitelist,
|
|
167
|
+
role = VictoryBoxPlot.role;
|
|
154
168
|
|
|
155
169
|
var props = _victoryCore.Helpers.modifyProps(this.props, fallbackProps, role);
|
|
156
170
|
|
|
@@ -166,6 +180,12 @@ function (_React$Component) {
|
|
|
166
180
|
return VictoryBoxPlot;
|
|
167
181
|
}(_react.default.Component);
|
|
168
182
|
|
|
183
|
+
Object.defineProperty(VictoryBoxPlot, "animationWhitelist", {
|
|
184
|
+
configurable: true,
|
|
185
|
+
enumerable: true,
|
|
186
|
+
writable: true,
|
|
187
|
+
value: ["data", "domain", "height", "padding", "style", "width"]
|
|
188
|
+
});
|
|
169
189
|
Object.defineProperty(VictoryBoxPlot, "displayName", {
|
|
170
190
|
configurable: true,
|
|
171
191
|
enumerable: true,
|
|
@@ -196,7 +216,13 @@ Object.defineProperty(VictoryBoxPlot, "propTypes", {
|
|
|
196
216
|
eventHandlers: _propTypes.default.object
|
|
197
217
|
})),
|
|
198
218
|
horizontal: _propTypes.default.bool,
|
|
199
|
-
labelOrientation: _propTypes.default.oneOf(["top", "bottom", "left", "right"]),
|
|
219
|
+
labelOrientation: _propTypes.default.oneOfType([_propTypes.default.oneOf(["top", "bottom", "left", "right"]), _propTypes.default.exact({
|
|
220
|
+
q1: _propTypes.default.oneOf(["top", "bottom", "left", "right"]),
|
|
221
|
+
q3: _propTypes.default.oneOf(["top", "bottom", "left", "right"]),
|
|
222
|
+
min: _propTypes.default.oneOf(["top", "bottom", "left", "right"]),
|
|
223
|
+
max: _propTypes.default.oneOf(["top", "bottom", "left", "right"]),
|
|
224
|
+
median: _propTypes.default.oneOf(["top", "bottom", "left", "right"])
|
|
225
|
+
})]),
|
|
200
226
|
labels: _propTypes.default.bool,
|
|
201
227
|
max: _propTypes.default.oneOfType([_propTypes.default.func, _victoryCore.PropTypes.allOfType([_victoryCore.PropTypes.integer, _victoryCore.PropTypes.nonNegative]), _propTypes.default.string, _propTypes.default.arrayOf(_propTypes.default.string)]),
|
|
202
228
|
maxComponent: _propTypes.default.element,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "victory-box-plot",
|
|
3
|
-
"version": "31.
|
|
3
|
+
"version": "31.3.0",
|
|
4
4
|
"description": "Box Plot Component for Victory",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"data visualization",
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
"d3-array": "^1.2.0",
|
|
23
23
|
"lodash": "^4.17.5",
|
|
24
24
|
"prop-types": "^15.5.8",
|
|
25
|
-
"victory-core": "^31.
|
|
25
|
+
"victory-core": "^31.2.0"
|
|
26
26
|
},
|
|
27
27
|
"scripts": {
|
|
28
28
|
"version": "nps build-libs && nps build-dists"
|
package/src/helper-methods.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { orderBy, defaults, assign, uniq, groupBy, keys } from "lodash";
|
|
1
|
+
import { orderBy, defaults, assign, uniq, groupBy, keys, isNaN, isNil } from "lodash";
|
|
2
2
|
import { Helpers, Scale, Domain, Data, Collection } from "victory-core";
|
|
3
3
|
import { min as d3Min, max as d3Max, quantile as d3Quantile } from "d3-array";
|
|
4
4
|
|
|
@@ -8,12 +8,12 @@ const checkProcessedData = (props, data) => {
|
|
|
8
8
|
/* check if the data is pre-processed. start by checking that it has
|
|
9
9
|
all required quartile attributes. */
|
|
10
10
|
const hasQuartileAttributes = data.every((datum) => {
|
|
11
|
-
return TYPES.every((val) => typeof datum[`_${val}`]
|
|
11
|
+
return TYPES.every((val) => typeof datum[`_${val}`] !== "undefined");
|
|
12
12
|
});
|
|
13
13
|
|
|
14
14
|
if (hasQuartileAttributes) {
|
|
15
15
|
// check that the indepedent variable is distinct
|
|
16
|
-
const values = data.map(({ _x, _y }) => props.horizontal ? _y : _x);
|
|
16
|
+
const values = data.map(({ _x, _y }) => (props.horizontal ? _y : _x));
|
|
17
17
|
if (!uniq(values).length === values.length) {
|
|
18
18
|
throw new Error(`
|
|
19
19
|
data prop may only take an array of objects with a unique
|
|
@@ -25,19 +25,21 @@ const checkProcessedData = (props, data) => {
|
|
|
25
25
|
return false;
|
|
26
26
|
};
|
|
27
27
|
|
|
28
|
+
const nanToNull = (val) => (isNaN(val) ? null : val);
|
|
29
|
+
|
|
28
30
|
const getSummaryStatistics = (data, horizontal) => {
|
|
29
|
-
const dependentVars = data.map((datum) => horizontal ? datum._x : datum._y);
|
|
31
|
+
const dependentVars = data.map((datum) => (horizontal ? datum._x : datum._y));
|
|
30
32
|
const quartiles = {
|
|
31
|
-
_q1: d3Quantile(dependentVars, 0.25), // eslint-disable-line no-magic-numbers
|
|
32
|
-
_q3: d3Quantile(dependentVars, 0.75), // eslint-disable-line no-magic-numbers
|
|
33
|
-
_min: d3Min(dependentVars),
|
|
34
|
-
_median: d3Quantile(dependentVars, 0.5),
|
|
35
|
-
_max: d3Max(dependentVars)
|
|
33
|
+
_q1: nanToNull(d3Quantile(dependentVars, 0.25)), // eslint-disable-line no-magic-numbers
|
|
34
|
+
_q3: nanToNull(d3Quantile(dependentVars, 0.75)), // eslint-disable-line no-magic-numbers
|
|
35
|
+
_min: nanToNull(d3Min(dependentVars)),
|
|
36
|
+
_median: nanToNull(d3Quantile(dependentVars, 0.5)),
|
|
37
|
+
_max: nanToNull(d3Max(dependentVars))
|
|
36
38
|
};
|
|
37
39
|
|
|
38
|
-
return horizontal
|
|
39
|
-
assign({}, quartiles, { _y: data[0]._y })
|
|
40
|
-
assign({}, quartiles, { _x: data[0]._x });
|
|
40
|
+
return horizontal
|
|
41
|
+
? assign({}, quartiles, { _y: data[0]._y })
|
|
42
|
+
: assign({}, quartiles, { _x: data[0]._x });
|
|
41
43
|
};
|
|
42
44
|
|
|
43
45
|
const isHorizontal = (props, data) => {
|
|
@@ -93,28 +95,36 @@ const reduceDataset = (dataset, props, axis) => {
|
|
|
93
95
|
const minDomain = Domain.getMinFromProps(props, axis);
|
|
94
96
|
const maxDomain = Domain.getMaxFromProps(props, axis);
|
|
95
97
|
|
|
96
|
-
const minData =
|
|
97
|
-
minDomain
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
98
|
+
const minData =
|
|
99
|
+
minDomain !== undefined
|
|
100
|
+
? minDomain
|
|
101
|
+
: dataset.reduce((memo, datum) => {
|
|
102
|
+
return memo < datum[`_${axis}`] ? memo : datum[`_${axis}`];
|
|
103
|
+
}, Infinity);
|
|
104
|
+
const maxData =
|
|
105
|
+
maxDomain !== undefined
|
|
106
|
+
? maxDomain
|
|
107
|
+
: dataset.reduce((memo, datum) => {
|
|
108
|
+
return memo > datum[`_${axis}`] ? memo : datum[`_${axis}`];
|
|
109
|
+
}, -Infinity);
|
|
104
110
|
return Domain.getDomainFromMinMax(minData, maxData);
|
|
105
111
|
};
|
|
106
112
|
|
|
107
113
|
const getDomainFromMinMaxValues = (dataset, props, axis) => {
|
|
108
114
|
const minDomain = Domain.getMinFromProps(props, axis);
|
|
109
115
|
const maxDomain = Domain.getMaxFromProps(props, axis);
|
|
110
|
-
const minData =
|
|
111
|
-
minDomain
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
116
|
+
const minData =
|
|
117
|
+
minDomain !== undefined
|
|
118
|
+
? minDomain
|
|
119
|
+
: dataset.reduce((memo, datum) => {
|
|
120
|
+
return memo < datum._min ? memo : datum._min;
|
|
121
|
+
}, Infinity);
|
|
122
|
+
const maxData =
|
|
123
|
+
maxDomain !== undefined
|
|
124
|
+
? maxDomain
|
|
125
|
+
: dataset.reduce((memo, datum) => {
|
|
126
|
+
return memo > datum._max ? memo : datum._max;
|
|
127
|
+
}, -Infinity);
|
|
118
128
|
return Domain.getDomainFromMinMax(minData, maxData);
|
|
119
129
|
};
|
|
120
130
|
|
|
@@ -128,8 +138,9 @@ const getDomainFromData = (props, axis) => {
|
|
|
128
138
|
const max = maxDomain !== undefined ? maxDomain : Collection.getMaxValue(scaleDomain);
|
|
129
139
|
return Domain.getDomainFromMinMax(min, max);
|
|
130
140
|
}
|
|
131
|
-
return props.horizontal && axis === "x" || !props.horizontal && axis === "y"
|
|
132
|
-
getDomainFromMinMaxValues(dataset, props, axis)
|
|
141
|
+
return (props.horizontal && axis === "x") || (!props.horizontal && axis === "y")
|
|
142
|
+
? getDomainFromMinMaxValues(dataset, props, axis)
|
|
143
|
+
: reduceDataset(dataset, props, axis);
|
|
133
144
|
};
|
|
134
145
|
|
|
135
146
|
const getDomain = (props, axis) => {
|
|
@@ -174,8 +185,12 @@ const getCalculatedValues = (props) => {
|
|
|
174
185
|
y: getDomain(props, "y")
|
|
175
186
|
};
|
|
176
187
|
const scale = {
|
|
177
|
-
x: Scale.getBaseScale(props, "x")
|
|
178
|
-
|
|
188
|
+
x: Scale.getBaseScale(props, "x")
|
|
189
|
+
.domain(domain.x)
|
|
190
|
+
.range(range.x),
|
|
191
|
+
y: Scale.getBaseScale(props, "y")
|
|
192
|
+
.domain(domain.y)
|
|
193
|
+
.range(range.y)
|
|
179
194
|
};
|
|
180
195
|
const defaultStyles = theme && theme.boxplot && theme.boxplot.style ? theme.boxplot.style : {};
|
|
181
196
|
const style = getStyles(props, defaultStyles);
|
|
@@ -193,7 +208,9 @@ const getWhiskerProps = (props, type) => {
|
|
|
193
208
|
const whiskerValue = type === "min" ? min : max;
|
|
194
209
|
const width = typeof whiskerWidth === "number" ? whiskerWidth : boxWidth;
|
|
195
210
|
return {
|
|
196
|
-
datum,
|
|
211
|
+
datum,
|
|
212
|
+
index,
|
|
213
|
+
scale,
|
|
197
214
|
majorWhisker: {
|
|
198
215
|
x1: horizontal ? boxValue : x,
|
|
199
216
|
y1: horizontal ? y : boxValue,
|
|
@@ -218,7 +235,9 @@ const getBoxProps = (props, type) => {
|
|
|
218
235
|
const defaultWidth = type === "q1" ? median - q1 : q3 - median;
|
|
219
236
|
const defaultHeight = type === "q1" ? q1 - median : median - q3;
|
|
220
237
|
return {
|
|
221
|
-
datum,
|
|
238
|
+
datum,
|
|
239
|
+
scale,
|
|
240
|
+
index,
|
|
222
241
|
x: horizontal ? defaultX : x - boxWidth / 2,
|
|
223
242
|
y: horizontal ? y - boxWidth / 2 : defaultY,
|
|
224
243
|
width: horizontal ? defaultWidth : boxWidth,
|
|
@@ -231,7 +250,9 @@ const getMedianProps = (props) => {
|
|
|
231
250
|
const { boxWidth, horizontal, style, datum, scale, index } = props;
|
|
232
251
|
const { median, x, y } = props.positions;
|
|
233
252
|
return {
|
|
234
|
-
datum,
|
|
253
|
+
datum,
|
|
254
|
+
scale,
|
|
255
|
+
index,
|
|
235
256
|
x1: horizontal ? median : x - boxWidth / 2,
|
|
236
257
|
y1: horizontal ? y - boxWidth / 2 : median,
|
|
237
258
|
x2: horizontal ? median : x + boxWidth / 2,
|
|
@@ -253,8 +274,12 @@ const getText = (props, type) => {
|
|
|
253
274
|
return Array.isArray(labelProp) ? labelProp[index] : labelProp;
|
|
254
275
|
};
|
|
255
276
|
|
|
277
|
+
const getOrientation = (labelOrientation, type) =>
|
|
278
|
+
(typeof labelOrientation === "object" && labelOrientation[type]) || labelOrientation;
|
|
279
|
+
|
|
256
280
|
const getLabelProps = (props, text, type) => {
|
|
257
281
|
const { datum, positions, index, boxWidth, horizontal, labelOrientation, style } = props;
|
|
282
|
+
const orientation = getOrientation(labelOrientation, type);
|
|
258
283
|
const namespace = `${type}Labels`;
|
|
259
284
|
const labelStyle = style[namespace] || style.labels;
|
|
260
285
|
const defaultVerticalAnchor = horizontal ? "end" : "middle";
|
|
@@ -264,13 +289,16 @@ const getLabelProps = (props, text, type) => {
|
|
|
264
289
|
|
|
265
290
|
const getDefaultPosition = (coord) => {
|
|
266
291
|
const sign = {
|
|
267
|
-
x:
|
|
292
|
+
x: orientation === "left" ? -1 : 1,
|
|
293
|
+
y: orientation === "top" ? -1 : 1
|
|
268
294
|
};
|
|
269
|
-
return positions[coord] + (sign[coord] * width / 2
|
|
295
|
+
return positions[coord] + (sign[coord] * width) / 2 + sign[coord] * (labelStyle.padding || 0);
|
|
270
296
|
};
|
|
271
297
|
|
|
272
298
|
return {
|
|
273
|
-
text,
|
|
299
|
+
text,
|
|
300
|
+
datum,
|
|
301
|
+
index,
|
|
274
302
|
style: labelStyle,
|
|
275
303
|
y: horizontal ? getDefaultPosition("y") : positions[type],
|
|
276
304
|
x: horizontal ? positions[type] : getDefaultPosition("x"),
|
|
@@ -293,19 +321,40 @@ const getBaseProps = (props, fallbackProps) => {
|
|
|
293
321
|
const modifiedProps = Helpers.modifyProps(props, fallbackProps, "boxplot");
|
|
294
322
|
props = assign({}, modifiedProps, getCalculatedValues(modifiedProps));
|
|
295
323
|
const {
|
|
296
|
-
groupComponent,
|
|
297
|
-
|
|
324
|
+
groupComponent,
|
|
325
|
+
width,
|
|
326
|
+
height,
|
|
327
|
+
padding,
|
|
328
|
+
standalone,
|
|
329
|
+
theme,
|
|
330
|
+
events,
|
|
331
|
+
sharedEvents,
|
|
332
|
+
scale,
|
|
333
|
+
horizontal,
|
|
334
|
+
data,
|
|
335
|
+
style,
|
|
336
|
+
domain,
|
|
337
|
+
name
|
|
298
338
|
} = props;
|
|
299
339
|
const initialChildProps = {
|
|
300
340
|
parent: {
|
|
301
|
-
domain,
|
|
302
|
-
|
|
341
|
+
domain,
|
|
342
|
+
scale,
|
|
343
|
+
width,
|
|
344
|
+
height,
|
|
345
|
+
data,
|
|
346
|
+
standalone,
|
|
347
|
+
name,
|
|
348
|
+
theme,
|
|
349
|
+
style: style.parent || {},
|
|
350
|
+
padding,
|
|
351
|
+
groupComponent
|
|
303
352
|
}
|
|
304
353
|
};
|
|
305
354
|
const boxScale = horizontal ? scale.x : scale.y;
|
|
306
355
|
|
|
307
356
|
return data.reduce((acc, datum, index) => {
|
|
308
|
-
const eventKey = datum.eventKey
|
|
357
|
+
const eventKey = !isNil(datum.eventKey) ? datum.eventKey : index;
|
|
309
358
|
const positions = {
|
|
310
359
|
x: scale.x(datum._x),
|
|
311
360
|
y: scale.y(datum._y),
|
|
@@ -327,7 +376,8 @@ const getBaseProps = (props, fallbackProps) => {
|
|
|
327
376
|
const labelText = getText(dataProps, type);
|
|
328
377
|
const labelProp = props.labels || props[`${type}Labels`];
|
|
329
378
|
if (
|
|
330
|
-
labelText !== null && labelText !== undefined ||
|
|
379
|
+
(labelText !== null && labelText !== undefined) ||
|
|
380
|
+
(labelProp && (events || sharedEvents))
|
|
331
381
|
) {
|
|
332
382
|
const target = `${type}Labels`;
|
|
333
383
|
acc[eventKey][target] = getLabelProps(dataProps, labelText, type);
|