victory-core 30.6.1 → 31.2.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.
Files changed (71) hide show
  1. package/README.md +13 -12
  2. package/dist/victory-core.js +1083 -842
  3. package/dist/victory-core.min.js +1 -1
  4. package/es/victory-animation/victory-animation.js +26 -21
  5. package/es/victory-label/victory-label.js +8 -2
  6. package/es/victory-primitives/path-helpers.js +1 -1
  7. package/es/victory-transition/victory-transition.js +11 -6
  8. package/es/victory-util/add-events.js +66 -38
  9. package/es/victory-util/axis.js +35 -9
  10. package/es/victory-util/data.js +24 -9
  11. package/es/victory-util/domain.js +15 -7
  12. package/es/victory-util/events.js +1 -1
  13. package/es/victory-util/helpers.js +17 -5
  14. package/es/victory-util/label-helpers.js +3 -5
  15. package/es/victory-util/textsize.js +20 -20
  16. package/es/victory-util/transitions.js +16 -16
  17. package/es/victory-util/wrapper.js +56 -19
  18. package/lib/victory-animation/victory-animation.js +27 -21
  19. package/lib/victory-label/victory-label.js +8 -2
  20. package/lib/victory-primitives/path-helpers.js +1 -1
  21. package/lib/victory-transition/victory-transition.js +12 -6
  22. package/lib/victory-util/add-events.js +66 -38
  23. package/lib/victory-util/axis.js +36 -9
  24. package/lib/victory-util/data.js +25 -9
  25. package/lib/victory-util/domain.js +16 -8
  26. package/lib/victory-util/events.js +1 -1
  27. package/lib/victory-util/helpers.js +17 -5
  28. package/lib/victory-util/label-helpers.js +3 -5
  29. package/lib/victory-util/textsize.js +20 -20
  30. package/lib/victory-util/transitions.js +16 -16
  31. package/lib/victory-util/wrapper.js +56 -19
  32. package/package.json +1 -1
  33. package/src/victory-animation/util.js +47 -45
  34. package/src/victory-animation/victory-animation.js +66 -38
  35. package/src/victory-clip-container/victory-clip-container.js +44 -31
  36. package/src/victory-container/victory-container.js +35 -21
  37. package/src/victory-label/victory-label.js +55 -71
  38. package/src/victory-portal/portal.js +1 -1
  39. package/src/victory-portal/victory-portal.js +10 -7
  40. package/src/victory-primitives/arc.js +15 -4
  41. package/src/victory-primitives/border.js +26 -5
  42. package/src/victory-primitives/circle.js +14 -3
  43. package/src/victory-primitives/clip-path.js +2 -7
  44. package/src/victory-primitives/line-segment.js +28 -5
  45. package/src/victory-primitives/line.js +15 -2
  46. package/src/victory-primitives/path-helpers.js +6 -7
  47. package/src/victory-primitives/point.js +30 -11
  48. package/src/victory-primitives/rect.js +19 -3
  49. package/src/victory-primitives/text.js +21 -11
  50. package/src/victory-primitives/tspan.js +6 -4
  51. package/src/victory-primitives/whisker.js +13 -6
  52. package/src/victory-theme/grayscale.js +153 -128
  53. package/src/victory-theme/material.js +178 -149
  54. package/src/victory-transition/victory-transition.js +31 -25
  55. package/src/victory-util/add-events.js +113 -75
  56. package/src/victory-util/axis.js +89 -35
  57. package/src/victory-util/collection.js +3 -8
  58. package/src/victory-util/common-props.js +42 -36
  59. package/src/victory-util/data.js +78 -43
  60. package/src/victory-util/domain.js +68 -46
  61. package/src/victory-util/events.js +129 -112
  62. package/src/victory-util/helpers.js +36 -16
  63. package/src/victory-util/immutable.js +12 -7
  64. package/src/victory-util/label-helpers.js +34 -18
  65. package/src/victory-util/prop-types.js +11 -23
  66. package/src/victory-util/scale.js +2 -3
  67. package/src/victory-util/selection.js +4 -5
  68. package/src/victory-util/style.js +17 -10
  69. package/src/victory-util/textsize.js +35 -31
  70. package/src/victory-util/transitions.js +53 -35
  71. package/src/victory-util/wrapper.js +112 -56
@@ -24,6 +24,7 @@ import PropTypes from "prop-types";
24
24
  import * as d3Ease from "d3-ease";
25
25
  import { victoryInterpolator } from "./util";
26
26
  import Timer from "../victory-util/timer";
27
+ import isEqual from "react-fast-compare";
27
28
 
28
29
  var VictoryAnimation =
29
30
  /*#__PURE__*/
@@ -68,31 +69,35 @@ function (_React$Component) {
68
69
  this.traverseQueue();
69
70
  }
70
71
  }
71
- /* lifecycle */
72
-
73
72
  }, {
74
- key: "componentWillReceiveProps",
75
- value: function componentWillReceiveProps(nextProps) {
76
- /* cancel existing loop if it exists */
77
- this.getTimer().unsubscribe(this.loopID);
78
- /* If an object was supplied */
79
-
80
- if (!Array.isArray(nextProps.data)) {
81
- // Replace the tween queue. Could set `this.queue = [nextProps.data]`,
82
- // but let's reuse the same array.
83
- this.queue.length = 0;
84
- this.queue.push(nextProps.data);
85
- /* If an array was supplied */
86
- } else {
87
- var _queue;
73
+ key: "shouldComponentUpdate",
74
+ value: function shouldComponentUpdate(nextProps, nextState) {
75
+ var equalProps = isEqual(this.props, nextProps);
88
76
 
89
- /* Extend the tween queue */
90
- (_queue = this.queue).push.apply(_queue, _toConsumableArray(nextProps.data));
91
- }
92
- /* Start traversing the tween queue */
77
+ if (!equalProps) {
78
+ /* cancel existing loop if it exists */
79
+ this.getTimer().unsubscribe(this.loopID);
80
+ /* If an object was supplied */
81
+
82
+ if (!Array.isArray(nextProps.data)) {
83
+ // Replace the tween queue. Could set `this.queue = [nextProps.data]`,
84
+ // but let's reuse the same array.
85
+ this.queue.length = 0;
86
+ this.queue.push(nextProps.data);
87
+ /* If an array was supplied */
88
+ } else {
89
+ var _queue;
93
90
 
91
+ /* Extend the tween queue */
92
+ (_queue = this.queue).push.apply(_queue, _toConsumableArray(nextProps.data));
93
+ }
94
+ /* Start traversing the tween queue */
95
+
96
+
97
+ this.traverseQueue();
98
+ }
94
99
 
95
- this.traverseQueue();
100
+ return nextState.animationInfo.animating || !equalProps;
96
101
  }
97
102
  }, {
98
103
  key: "componentWillUnmount",
@@ -104,11 +104,11 @@ function (_React$Component) {
104
104
  }
105
105
 
106
106
  return "".concat(child).split("\n");
107
- }
107
+ } //eslint-disable-next-line max-params
108
+
108
109
  }, {
109
110
  key: "getDy",
110
111
  value: function getDy(props, style, content, lineHeight) {
111
- //eslint-disable-line max-params
112
112
  style = Array.isArray(style) ? style[0] : style;
113
113
  lineHeight = this.checkLineHeight(lineHeight, lineHeight[0], 1);
114
114
  var fontSize = style.fontSize;
@@ -261,6 +261,12 @@ Object.defineProperty(VictoryLabel, "role", {
261
261
  writable: true,
262
262
  value: "label"
263
263
  });
264
+ Object.defineProperty(VictoryLabel, "defaultStyles", {
265
+ configurable: true,
266
+ enumerable: true,
267
+ writable: true,
268
+ value: defaultStyles
269
+ });
264
270
  Object.defineProperty(VictoryLabel, "propTypes", {
265
271
  configurable: true,
266
272
  enumerable: true,
@@ -54,9 +54,9 @@ export default {
54
54
  var baseSize = 1.35 * size; // eslint-disable-line no-magic-numbers
55
55
 
56
56
  var angle = Math.PI / 5; // eslint-disable-line no-magic-numbers
57
+ // eslint-disable-next-line no-magic-numbers
57
58
 
58
59
  var starCoords = _range(10).map(function (index) {
59
- // eslint-disable-line no-magic-numbers
60
60
  var length = index % 2 === 0 ? baseSize : baseSize / 2;
61
61
  return "".concat(length * Math.sin(angle * (index + 1)) + x, ",\n ").concat(length * Math.cos(angle * (index + 1)) + y);
62
62
  });
@@ -24,6 +24,7 @@ import Collection from "../victory-util/collection";
24
24
  import Helpers from "../victory-util/helpers";
25
25
  import Timer from "../victory-util/timer";
26
26
  import Transitions from "../victory-util/transitions";
27
+ import isEqual from "react-fast-compare";
27
28
 
28
29
  var VictoryTransition =
29
30
  /*#__PURE__*/
@@ -56,14 +57,18 @@ function (_React$Component) {
56
57
  }); //eslint-disable-line react/no-did-mount-set-state
57
58
  }
58
59
  }, {
59
- key: "componentWillReceiveProps",
60
- value: function componentWillReceiveProps(nextProps) {
60
+ key: "shouldComponentUpdate",
61
+ value: function shouldComponentUpdate(nextProps) {
61
62
  var _this2 = this;
62
63
 
63
- this.getTimer().bypassAnimation();
64
- this.setState(this.getTransitionState(this.props, nextProps), function () {
65
- return _this2.getTimer().resumeAnimation();
66
- });
64
+ if (!isEqual(this.props, nextProps)) {
65
+ this.getTimer().bypassAnimation();
66
+ this.setState(this.getTransitionState(this.props, nextProps), function () {
67
+ return _this2.getTimer().resumeAnimation();
68
+ });
69
+ }
70
+
71
+ return true;
67
72
  }
68
73
  }, {
69
74
  key: "componentWillUnmount",
@@ -1,3 +1,4 @@
1
+ import _isNil from "lodash/isNil";
1
2
  import _isEmpty from "lodash/isEmpty";
2
3
  import _without from "lodash/without";
3
4
  import _pick from "lodash/pick";
@@ -29,7 +30,12 @@ function _assertThisInitialized(self) { if (self === void 0) { throw new Referen
29
30
  import React from "react";
30
31
  import Events from "./events";
31
32
  import isEqual from "react-fast-compare";
32
- import VictoryTransition from "../victory-transition/victory-transition"; // used for checking state changes. Expected components can be passed in via options
33
+ import VictoryTransition from "../victory-transition/victory-transition";
34
+
35
+ var datumHasXandY = function (datum) {
36
+ return !_isNil(datum._x) && !_isNil(datum._y);
37
+ }; // used for checking state changes. Expected components can be passed in via options
38
+
33
39
 
34
40
  var defaultComponents = [{
35
41
  name: "parent",
@@ -66,39 +72,39 @@ export default (function (WrappedComponent, options) {
66
72
  _this.cacheValues(calculatedValues);
67
73
 
68
74
  _this.externalMutations = _this.getExternalMutations(props);
75
+ _this.calculatedState = _this.getStateChanges(props, calculatedValues);
69
76
  return _this;
70
77
  }
71
78
 
72
79
  _createClass(addEvents, [{
73
- key: "componentDidUpdate",
74
- value: function componentDidUpdate() {
75
- var externalMutations = this.getExternalMutations(this.props);
76
-
77
- if (!isEqual(this.externalMutations, externalMutations)) {
80
+ key: "shouldComponentUpdate",
81
+ value: function shouldComponentUpdate(nextProps) {
82
+ var calculatedValues = this.getCalculatedValues(nextProps);
83
+ var externalMutations = this.getExternalMutations(nextProps);
84
+ var animating = this.props.animating || this.props.animate;
85
+ var newMutation = !isEqual(externalMutations, this.externalMutations);
86
+
87
+ if (animating || newMutation) {
88
+ this.cacheValues(calculatedValues);
78
89
  this.externalMutations = externalMutations;
79
- this.applyExternalMutations(this.props, externalMutations);
90
+ this.applyExternalMutations(nextProps, externalMutations);
91
+ return true;
80
92
  }
81
- }
82
- }, {
83
- key: "componentWillReceiveProps",
84
- value: function componentWillReceiveProps(nextProps) {
85
- this.cacheValues(this.getCalculatedValues(nextProps));
86
- }
87
- }, {
88
- key: "applyExternalMutations",
89
- value: function applyExternalMutations(props, externalMutations) {
90
- if (!_isEmpty(externalMutations)) {
91
- var callbacks = props.externalEventMutations.reduce(function (memo, mutation) {
92
- memo = _isFunction(mutation.callback) ? memo.concat(mutation.callback) : memo;
93
- return memo;
94
- }, []);
95
- var compiledCallbacks = callbacks.length ? function () {
96
- callbacks.forEach(function (c) {
97
- return c();
98
- });
99
- } : undefined;
100
- this.setState(externalMutations, compiledCallbacks);
93
+
94
+ var calculatedState = this.getStateChanges(nextProps, calculatedValues);
95
+
96
+ if (!isEqual(this.calculatedState, calculatedState)) {
97
+ this.calculatedState = calculatedState;
98
+ this.cacheValues(calculatedValues);
99
+ return true;
100
+ }
101
+
102
+ if (!isEqual(this.props, nextProps)) {
103
+ this.cacheValues(calculatedValues);
104
+ return true;
101
105
  }
106
+
107
+ return false;
102
108
  } // compile all state changes from own and parent state. Order doesn't matter, as any state
103
109
  // state change should trigger a re-render
104
110
 
@@ -114,25 +120,41 @@ export default (function (WrappedComponent, options) {
114
120
  return {};
115
121
  }
116
122
 
117
- options = options || {};
118
- var components = options.components || defaultComponents;
119
-
120
123
  var getState = function (key, type) {
121
- var baseState = _defaults({}, _this2.getEventState(key, type), getSharedEventState(key, type));
124
+ var result = _defaults({}, _this2.getEventState(key, type), getSharedEventState(key, type));
122
125
 
123
- return _isEmpty(baseState) ? undefined : baseState;
126
+ return _isEmpty(result) ? undefined : result;
124
127
  };
125
128
 
126
- return components.map(function (component) {
129
+ options = options || {};
130
+ var components = options.components || defaultComponents;
131
+ var stateChanges = components.map(function (component) {
127
132
  if (!props.standalone && component.name === "parent") {
128
133
  // don't check for changes on parent props for non-standalone components
129
134
  return undefined;
130
135
  } else {
131
136
  return component.index !== undefined ? getState(component.index, component.name) : calculatedValues.dataKeys.map(function (key) {
132
137
  return getState(key, component.name);
133
- });
138
+ }).filter(Boolean);
134
139
  }
135
140
  }).filter(Boolean);
141
+ return stateChanges;
142
+ }
143
+ }, {
144
+ key: "applyExternalMutations",
145
+ value: function applyExternalMutations(props, externalMutations) {
146
+ if (!_isEmpty(externalMutations)) {
147
+ var callbacks = props.externalEventMutations.reduce(function (memo, mutation) {
148
+ memo = _isFunction(mutation.callback) ? memo.concat(mutation.callback) : memo;
149
+ return memo;
150
+ }, []);
151
+ var compiledCallbacks = callbacks.length ? function () {
152
+ callbacks.forEach(function (c) {
153
+ return c();
154
+ });
155
+ } : undefined;
156
+ this.setState(externalMutations, compiledCallbacks);
157
+ }
136
158
  }
137
159
  }, {
138
160
  key: "getCalculatedValues",
@@ -248,7 +270,8 @@ export default (function (WrappedComponent, options) {
248
270
  }
249
271
  }, {
250
272
  key: "animateComponent",
251
- value: function animateComponent(props, animationWhitelist) {
273
+ value: function animateComponent(props, defaultAnimationWhitelist) {
274
+ var animationWhitelist = props.animate && props.animate.animationWhitelist ? props.animate.animationWhitelist : defaultAnimationWhitelist;
252
275
  return React.createElement(VictoryTransition, {
253
276
  animate: props.animate,
254
277
  animationWhitelist: animationWhitelist
@@ -284,14 +307,19 @@ export default (function (WrappedComponent, options) {
284
307
  value: function renderData(props) {
285
308
  var _this5 = this;
286
309
 
310
+ var shouldRenderDatum = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : datumHasXandY;
287
311
  var dataComponent = props.dataComponent,
288
312
  labelComponent = props.labelComponent,
289
313
  groupComponent = props.groupComponent;
290
- var dataComponents = this.dataKeys.map(function (_dataKey, index) {
314
+ var dataComponents = this.dataKeys.reduce(function (validDataComponents, _dataKey, index) {
291
315
  var dataProps = _this5.getComponentProps(dataComponent, "data", index);
292
316
 
293
- return React.cloneElement(dataComponent, dataProps);
294
- });
317
+ if (shouldRenderDatum(dataProps.datum)) {
318
+ validDataComponents.push(React.cloneElement(dataComponent, dataProps));
319
+ }
320
+
321
+ return validDataComponents;
322
+ }, []);
295
323
  var labelComponents = this.dataKeys.map(function (_dataKey, index) {
296
324
  var labelProps = _this5.getComponentProps(labelComponent, "labels", index);
297
325
 
@@ -5,6 +5,7 @@ import _orderBy from "lodash/orderBy";
5
5
  import _range from "lodash/range";
6
6
  import _uniq from "lodash/uniq";
7
7
  import _invert from "lodash/invert";
8
+ import _isObject from "lodash/isObject";
8
9
  import _isFunction from "lodash/isFunction";
9
10
  import _identity from "lodash/identity";
10
11
 
@@ -211,8 +212,10 @@ function stringTicks(props) {
211
212
  }
212
213
 
213
214
  function getDefaultTickFormat(props) {
214
- var tickValues = props.tickValues,
215
- stringMap = props.stringMap;
215
+ var tickValues = props.tickValues;
216
+ var axis = getAxis(props);
217
+ var currentAxis = getCurrentAxis(axis, props.horizontal);
218
+ var stringMap = props.stringMap && props.stringMap[currentAxis];
216
219
  var fallbackFormat = tickValues && !Collection.containsDates(tickValues) ? function (x) {
217
220
  return x;
218
221
  } : undefined;
@@ -240,8 +243,10 @@ function getDefaultTickFormat(props) {
240
243
  }
241
244
 
242
245
  function getTickFormat(props, scale) {
243
- var tickFormat = props.tickFormat,
244
- stringMap = props.stringMap;
246
+ var tickFormat = props.tickFormat;
247
+ var axis = getAxis(props);
248
+ var currentAxis = getCurrentAxis(axis, props.horizontal);
249
+ var stringMap = props.stringMap && props.stringMap[currentAxis];
245
250
 
246
251
  if (!tickFormat) {
247
252
  var defaultTickFormat = getDefaultTickFormat(props);
@@ -272,8 +277,9 @@ function getTickFormat(props, scale) {
272
277
  }
273
278
 
274
279
  function getStringTicks(props) {
275
- var stringMap = props.stringMap;
276
280
  var axis = getAxis(props);
281
+ var currentAxis = getCurrentAxis(axis, props.horizontal);
282
+ var stringMap = props.stringMap && props.stringMap[currentAxis];
277
283
  var categories = Array.isArray(props.categories) ? props.categories : props.categories && props.categories[axis];
278
284
  var ticksFromCategories = categories && Collection.containsOnlyStrings(categories) ? categories.map(function (tick) {
279
285
  return stringMap[tick];
@@ -286,8 +292,10 @@ function getStringTicks(props) {
286
292
 
287
293
  function getTickArray(props) {
288
294
  var tickValues = props.tickValues,
289
- tickFormat = props.tickFormat,
290
- stringMap = props.stringMap;
295
+ tickFormat = props.tickFormat;
296
+ var axis = getAxis(props);
297
+ var currentAxis = getCurrentAxis(axis, props.horizontal);
298
+ var stringMap = props.stringMap && props.stringMap[currentAxis];
291
299
 
292
300
  var getTicksFromFormat = function () {
293
301
  if (!tickFormat || !Array.isArray(tickFormat)) {
@@ -314,7 +322,6 @@ function getTickArray(props) {
314
322
  var tickArray = ticks ? _uniq(ticks) : getTicksFromFormat(props);
315
323
 
316
324
  var filterArray = function (arr) {
317
- var axis = getAxis(props);
318
325
  var domain = props.domain && props.domain[axis] || props.domain;
319
326
  return Array.isArray(domain) ? arr.filter(function (t) {
320
327
  return t >= Math.min.apply(Math, _toConsumableArray(domain)) && t <= Math.max.apply(Math, _toConsumableArray(domain));
@@ -410,6 +417,24 @@ function getDomain(props, axis) {
410
417
  return Domain.createDomainFunction(getDomainFromData)(props, inherentAxis);
411
418
  }
412
419
 
420
+ function getAxisValue(props, axis) {
421
+ if (!props.axisValue) {
422
+ return undefined;
423
+ }
424
+
425
+ var scaleAxis = axis === "x" ? "y" : "x";
426
+ var scale = _isObject(props.scale) && _isFunction(props.scale[scaleAxis]) ? props.scale[scaleAxis] : undefined;
427
+
428
+ if (!scale) {
429
+ return undefined;
430
+ }
431
+
432
+ var stringMapAxis = getCurrentAxis(axis, props.horizontal) === "x" ? "y" : "x";
433
+ var stringMap = _isObject(props.stringMap) && props.stringMap[stringMapAxis];
434
+ var axisValue = stringMap && typeof props.axisValue === "string" ? stringMap[props.axisValue] : props.axisValue;
435
+ return scale(axisValue);
436
+ }
437
+
413
438
  export default {
414
439
  getTicks: getTicks,
415
440
  getTickFormat: getTickFormat,
@@ -423,5 +448,6 @@ export default {
423
448
  getOriginSign: getOriginSign,
424
449
  getDomain: getDomain,
425
450
  isVertical: isVertical,
426
- stringTicks: stringTicks
451
+ stringTicks: stringTicks,
452
+ getAxisValue: getAxisValue
427
453
  };
@@ -1,4 +1,5 @@
1
1
  import _includes from "lodash/includes";
2
+ import _isEqual from "lodash/isEqual";
2
3
  import _isEmpty from "lodash/isEmpty";
3
4
  import _orderBy from "lodash/orderBy";
4
5
  import _property from "lodash/property";
@@ -107,12 +108,19 @@ function getEventKey(key) {
107
108
 
108
109
 
109
110
  function addEventKeys(props, data) {
111
+ var hasEventKeyAccessor = !!props.eventKey;
110
112
  var eventKeyAccessor = getEventKey(props.eventKey);
111
- return data.map(function (datum, index) {
112
- var eventKey = datum.eventKey || eventKeyAccessor(datum) || index;
113
- return _assign({
114
- eventKey: eventKey
115
- }, datum);
113
+ return data.map(function (datum) {
114
+ if (datum.eventKey !== undefined) {
115
+ return datum;
116
+ } else if (hasEventKeyAccessor) {
117
+ var eventKey = eventKeyAccessor(datum);
118
+ return eventKey !== undefined ? _assign({
119
+ eventKey: eventKey
120
+ }, datum) : datum;
121
+ } else {
122
+ return datum;
123
+ }
116
124
  });
117
125
  } // Exported Functions
118
126
 
@@ -180,7 +188,8 @@ function formatData(dataset, props, expectedKeys) {
180
188
  return [];
181
189
  }
182
190
 
183
- expectedKeys = Array.isArray(expectedKeys) ? expectedKeys : ["x", "y", "y0"];
191
+ var defaultKeys = ["x", "y", "y0"];
192
+ expectedKeys = Array.isArray(expectedKeys) ? expectedKeys : defaultKeys;
184
193
  var stringMap = {
185
194
  x: expectedKeys.indexOf("x") !== -1 ? createStringMap(props, "x") : undefined,
186
195
  y: expectedKeys.indexOf("y") !== -1 ? createStringMap(props, "y") : undefined,
@@ -195,7 +204,8 @@ function formatData(dataset, props, expectedKeys) {
195
204
  memo[type] = createAccessor(type);
196
205
  return memo;
197
206
  }, {});
198
- var data = dataset.reduce(function (dataArr, datum, index) {
207
+ var preformattedData = _isEqual(expectedKeys, defaultKeys) && props.x === "_x" && props.y === "_y" && props.y0 === "_y0";
208
+ var data = preformattedData ? dataset : dataset.reduce(function (dataArr, datum, index) {
199
209
  // eslint-disable-line complexity
200
210
  datum = parseDatum(datum);
201
211
  var fallbackValues = {
@@ -328,8 +338,13 @@ function getStringsFromData(props, axis) {
328
338
  }
329
339
 
330
340
  var key = props[axis] === undefined ? axis : props[axis];
331
- var accessor = Helpers.createAccessor(key);
332
- var sortedData = sortData(props.data, props.sortKey, props.sortOrder);
341
+ var accessor = Helpers.createAccessor(key); // support immutable data
342
+
343
+ var data = props.data.reduce(function (memo, d) {
344
+ memo.push(parseDatum(d));
345
+ return memo;
346
+ }, []);
347
+ var sortedData = sortData(data, props.sortKey, props.sortOrder);
333
348
  var dataStrings = sortedData.reduce(function (dataArr, datum) {
334
349
  datum = parseDatum(datum);
335
350
  dataArr.push(accessor(datum));
@@ -315,27 +315,35 @@ function getDomainWithZero(props, axis) {
315
315
  return propsDomain;
316
316
  }
317
317
 
318
+ var dataset = Data.getData(props);
319
+ var y0Min = dataset.reduce(function (min, datum) {
320
+ return datum._y0 < min ? datum._y0 : min;
321
+ }, Infinity);
322
+
318
323
  var ensureZero = function (domain) {
319
324
  var currentAxis = Helpers.getCurrentAxis(axis, props.horizontal);
320
- var minDomain = getMinFromProps(props, axis);
321
- var maxDomain = getMaxFromProps(props, axis);
322
325
 
323
326
  if (currentAxis === "x") {
324
327
  return domain;
325
328
  }
326
329
 
327
- var defaultMin = minDomain || 0;
328
- var defaultMax = maxDomain || 0;
329
- var min = minDomain !== undefined ? minDomain : Collection.getMinValue(domain, defaultMin);
330
- var max = maxDomain !== undefined ? maxDomain : Collection.getMaxValue(domain, defaultMax);
330
+ var defaultMin = y0Min !== Infinity ? y0Min : 0;
331
+ var maxDomainProp = getMaxFromProps(props, axis);
332
+ var minDomainProp = getMinFromProps(props, axis);
333
+ var max = maxDomainProp !== undefined ? maxDomainProp : Collection.getMaxValue(domain, defaultMin);
334
+ var min = minDomainProp !== undefined ? minDomainProp : Collection.getMinValue(domain, defaultMin);
331
335
  return getDomainFromMinMax(min, max);
332
336
  };
333
337
 
338
+ var getDomainFunction = function () {
339
+ return getDomainFromData(props, axis, dataset);
340
+ };
341
+
334
342
  var formatDomainFunction = function (domain) {
335
343
  return formatDomain(ensureZero(domain), props, axis);
336
344
  };
337
345
 
338
- return createDomainFunction(null, formatDomainFunction)(props, axis);
346
+ return createDomainFunction(getDomainFunction, formatDomainFunction)(props, axis);
339
347
  }
340
348
  /**
341
349
  * Returns the maxDomain from props if it exists
@@ -413,7 +413,7 @@ export default {
413
413
 
414
414
  /* Returns an array of defaultEvents from sub-components of a given component.
415
415
  * i.e. any static `defaultEvents` on `labelComponent` will be returned
416
- */
416
+ */
417
417
  getComponentEvents: function (props, components) {
418
418
  var events = Array.isArray(components) && components.reduce(function (memo, componentName) {
419
419
  var _memo;
@@ -164,11 +164,11 @@ function evaluateStyle(style, data, active) {
164
164
  }
165
165
 
166
166
  function degreesToRadians(degrees) {
167
- return degrees * (Math.PI / 180);
167
+ return typeof degrees === "number" ? degrees * (Math.PI / 180) : degrees;
168
168
  }
169
169
 
170
170
  function radiansToDegrees(radians) {
171
- return radians / (Math.PI / 180);
171
+ return typeof radians === "number" ? radians / (Math.PI / 180) : radians;
172
172
  }
173
173
 
174
174
  function getRadius(props) {
@@ -249,12 +249,21 @@ function getCurrentAxis(axis, horizontal) {
249
249
  * @param {Array} children: an array of child components
250
250
  * @param {Function} iteratee: a function with arguments "child", "childName", and "parent"
251
251
  * @param {Object} parentProps: props from the parent that are applied to children
252
+ * @param {any} initialMemo: The object in which the iteration results are combined.
253
+ * @param {Function} combine: Combines the result of the iteratee with the current memo
254
+ * to the memo for the next iteration step
252
255
  * @returns {Array} returns an array of results from calling the iteratee on all nested children
253
256
  */
254
257
 
258
+ /* eslint-disable max-params */
259
+
255
260
 
256
261
  function reduceChildren(children, iteratee) {
257
262
  var parentProps = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
263
+ var initialMemo = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : [];
264
+ var combine = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : function (memo, item) {
265
+ return memo.concat(item);
266
+ };
258
267
  var sharedProps = ["data", "domain", "categories", "polar", "startAngle", "endAngle", "minDomain", "maxDomain"];
259
268
 
260
269
  var traverseChildren = function (childArray, names, parent) {
@@ -276,14 +285,17 @@ function reduceChildren(children, iteratee) {
276
285
  });
277
286
 
278
287
  var nestedResults = traverseChildren(nestedChildren, _childNames, child);
279
- memo = memo.concat(nestedResults);
288
+ memo = combine(memo, nestedResults);
280
289
  } else {
281
290
  var result = iteratee(child, childName, parent);
282
- memo = result ? memo.concat(result) : memo;
291
+
292
+ if (result) {
293
+ memo = combine(memo, result);
294
+ }
283
295
  }
284
296
 
285
297
  return memo;
286
- }, []);
298
+ }, initialMemo);
287
299
  };
288
300
 
289
301
  var childNames = children.map(function (c, i) {
@@ -99,14 +99,12 @@ function getLabelPlacement(props) {
99
99
  }
100
100
 
101
101
  function getPolarOrientation(degrees) {
102
+ // eslint-disable-next-line no-magic-numbers
102
103
  if (degrees < 45 || degrees > 315) {
103
- // eslint-disable-line no-magic-numbers
104
- return "right";
104
+ return "right"; // eslint-disable-next-line no-magic-numbers
105
105
  } else if (degrees >= 45 && degrees <= 135) {
106
- // eslint-disable-line no-magic-numbers
107
- return "top";
106
+ return "top"; // eslint-disable-next-line no-magic-numbers
108
107
  } else if (degrees > 135 && degrees < 225) {
109
- // eslint-disable-line no-magic-numbers
110
108
  return "left";
111
109
  } else {
112
110
  return "bottom";