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.
@@ -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)] === "number";
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: labelOrientation === "left" ? -1 : 1,
355
- y: labelOrientation === "top" ? -1 : 1
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 !== undefined ? datum.eventKey : index;
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),
@@ -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.map(function (key, index) {
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
- return React.cloneElement(baseComponent, componentProps);
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 role = this.constructor.role;
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,
@@ -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)] === "number";
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: labelOrientation === "left" ? -1 : 1,
375
- y: labelOrientation === "top" ? -1 : 1
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 !== undefined ? datum.eventKey : index;
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),
@@ -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.map(function (key, index) {
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
- return _react.default.cloneElement(baseComponent, componentProps);
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 role = this.constructor.role;
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.0.0",
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.0.0"
25
+ "victory-core": "^31.2.0"
26
26
  },
27
27
  "scripts": {
28
28
  "version": "nps build-libs && nps build-dists"
@@ -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}`] === "number");
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 = minDomain !== undefined ?
97
- minDomain : dataset.reduce((memo, datum) => {
98
- return memo < datum[`_${axis}`] ? memo : datum[`_${axis}`];
99
- }, Infinity);
100
- const maxData = maxDomain !== undefined ?
101
- maxDomain : dataset.reduce((memo, datum) => {
102
- return memo > datum[`_${axis}`] ? memo : datum[`_${axis}`];
103
- }, -Infinity);
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 = minDomain !== undefined ?
111
- minDomain : dataset.reduce((memo, datum) => {
112
- return memo < datum._min ? memo : datum._min;
113
- }, Infinity);
114
- const maxData = maxDomain !== undefined ?
115
- maxDomain : dataset.reduce((memo, datum) => {
116
- return memo > datum._max ? memo : datum._max;
117
- }, -Infinity);
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) : reduceDataset(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").domain(domain.x).range(range.x),
178
- y: Scale.getBaseScale(props, "y").domain(domain.y).range(range.y)
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, index, scale,
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, scale, index,
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, scale, index,
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: labelOrientation === "left" ? -1 : 1, y: labelOrientation === "top" ? -1 : 1
292
+ x: orientation === "left" ? -1 : 1,
293
+ y: orientation === "top" ? -1 : 1
268
294
  };
269
- return positions[coord] + (sign[coord] * width / 2) + (sign[coord] * (labelStyle.padding || 0));
295
+ return positions[coord] + (sign[coord] * width) / 2 + sign[coord] * (labelStyle.padding || 0);
270
296
  };
271
297
 
272
298
  return {
273
- text, datum, index,
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, width, height, padding, standalone, theme, events, sharedEvents,
297
- scale, horizontal, data, style, domain, name
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, scale, width, height, data, standalone, name,
302
- theme, style: style.parent || {}, padding, groupComponent
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 !== undefined ? datum.eventKey : index;
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 || (labelProp && (events || sharedEvents))
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);