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,9 +1,18 @@
1
1
  import React from "react";
2
2
  import PropTypes from "prop-types";
3
- import { flatten } from "lodash";
3
+ import { flatten, isNil } from "lodash";
4
4
  import {
5
- Helpers, VictoryLabel, addEvents, LineSegment, PropTypes as CustomPropTypes,
6
- VictoryContainer, VictoryTheme, Box, Whisker, DefaultTransitions, CommonProps
5
+ Helpers,
6
+ VictoryLabel,
7
+ addEvents,
8
+ LineSegment,
9
+ PropTypes as CustomPropTypes,
10
+ VictoryContainer,
11
+ VictoryTheme,
12
+ Box,
13
+ Whisker,
14
+ DefaultTransitions,
15
+ CommonProps
7
16
  } from "victory-core";
8
17
  import { getDomain, getData, getBaseProps } from "./helper-methods";
9
18
 
@@ -18,24 +27,29 @@ const fallbackProps = {
18
27
  }
19
28
  };
20
29
 
21
- const options = {
22
- components: [
23
- { name: "min" }, { name: "minLabels" }, { name: "max" }, { name: "maxLabels" },
24
- { name: "median" }, { name: "medianLabels" }, { name: "q1" }, { name: "q1Labels" },
25
- { name: "q3" }, { name: "q3Labels" }, { name: "parent", index: "parent" }
26
- ]
27
- };
28
-
29
30
  const defaultData = [
30
31
  { x: 1, min: 5, q1: 7, median: 12, q3: 18, max: 20 },
31
32
  { x: 2, min: 2, q1: 5, median: 8, q3: 12, max: 15 }
32
33
  ];
33
34
 
34
- const animationWhitelist = [
35
- "data", "domain", "height", "padding", "style", "width"
36
- ];
35
+ const options = {
36
+ components: [
37
+ { name: "min" },
38
+ { name: "minLabels" },
39
+ { name: "max" },
40
+ { name: "maxLabels" },
41
+ { name: "median" },
42
+ { name: "medianLabels" },
43
+ { name: "q1" },
44
+ { name: "q1Labels" },
45
+ { name: "q3" },
46
+ { name: "q3Labels" },
47
+ { name: "parent", index: "parent" }
48
+ ]
49
+ };
37
50
 
38
51
  class VictoryBoxPlot extends React.Component {
52
+ static animationWhitelist = ["data", "domain", "height", "padding", "style", "width"];
39
53
 
40
54
  static displayName = "VictoryBoxPlot";
41
55
  static role = "boxplot";
@@ -44,20 +58,40 @@ class VictoryBoxPlot extends React.Component {
44
58
  ...CommonProps.baseProps,
45
59
  ...CommonProps.dataProps,
46
60
  boxWidth: PropTypes.number,
47
- events: PropTypes.arrayOf(PropTypes.shape({
48
- target: PropTypes.oneOf([
49
- "max", "maxLabels", "median", "medianLabels", "min", "minLabels",
50
- "q1", "q1Labels", "q3", "q3Labels", "parent"
51
- ]),
52
- eventKey: PropTypes.oneOfType([
53
- PropTypes.array,
54
- CustomPropTypes.allOfType([CustomPropTypes.integer, CustomPropTypes.nonNegative]),
55
- PropTypes.string
56
- ]),
57
- eventHandlers: PropTypes.object
58
- })),
61
+ events: PropTypes.arrayOf(
62
+ PropTypes.shape({
63
+ target: PropTypes.oneOf([
64
+ "max",
65
+ "maxLabels",
66
+ "median",
67
+ "medianLabels",
68
+ "min",
69
+ "minLabels",
70
+ "q1",
71
+ "q1Labels",
72
+ "q3",
73
+ "q3Labels",
74
+ "parent"
75
+ ]),
76
+ eventKey: PropTypes.oneOfType([
77
+ PropTypes.array,
78
+ CustomPropTypes.allOfType([CustomPropTypes.integer, CustomPropTypes.nonNegative]),
79
+ PropTypes.string
80
+ ]),
81
+ eventHandlers: PropTypes.object
82
+ })
83
+ ),
59
84
  horizontal: PropTypes.bool,
60
- labelOrientation: PropTypes.oneOf(["top", "bottom", "left", "right"]),
85
+ labelOrientation: PropTypes.oneOfType([
86
+ PropTypes.oneOf(["top", "bottom", "left", "right"]),
87
+ PropTypes.exact({
88
+ q1: PropTypes.oneOf(["top", "bottom", "left", "right"]),
89
+ q3: PropTypes.oneOf(["top", "bottom", "left", "right"]),
90
+ min: PropTypes.oneOf(["top", "bottom", "left", "right"]),
91
+ max: PropTypes.oneOf(["top", "bottom", "left", "right"]),
92
+ median: PropTypes.oneOf(["top", "bottom", "left", "right"])
93
+ })
94
+ ]),
61
95
  labels: PropTypes.bool,
62
96
  max: PropTypes.oneOfType([
63
97
  PropTypes.func,
@@ -121,13 +155,13 @@ class VictoryBoxPlot extends React.Component {
121
155
  whiskers: PropTypes.object
122
156
  }),
123
157
  whiskerWidth: PropTypes.number
124
- }
158
+ };
125
159
 
126
160
  static defaultProps = {
127
- containerComponent: <VictoryContainer/>,
161
+ containerComponent: <VictoryContainer />,
128
162
  data: defaultData,
129
- dataComponent: <Box/>,
130
- groupComponent: <g role="presentation"/>,
163
+ dataComponent: <Box />,
164
+ groupComponent: <g role="presentation" />,
131
165
  maxComponent: <Whisker />,
132
166
  maxLabelComponent: <VictoryLabel />,
133
167
  medianComponent: <LineSegment />,
@@ -150,33 +184,49 @@ class VictoryBoxPlot extends React.Component {
150
184
  static getData = getData;
151
185
  static getBaseProps = (props) => getBaseProps(props, fallbackProps);
152
186
  static expectedComponents = [
153
- "maxComponent", "maxLabelComponent", "medianComponent", "medianLabelComponent",
154
- "minComponent", "minLabelComponent", "q1Component", "q1LabelComponent",
155
- "q3Component", "q3LabelComponent", "groupComponent", "containerComponent"
187
+ "maxComponent",
188
+ "maxLabelComponent",
189
+ "medianComponent",
190
+ "medianLabelComponent",
191
+ "minComponent",
192
+ "minLabelComponent",
193
+ "q1Component",
194
+ "q1LabelComponent",
195
+ "q3Component",
196
+ "q3LabelComponent",
197
+ "groupComponent",
198
+ "containerComponent"
156
199
  ];
157
200
 
158
201
  renderBoxPlot(props) {
159
202
  const types = ["q1", "q3", "max", "min", "median"];
160
- const dataComponents = flatten(types.map((type) => {
161
- return this.dataKeys.map((key, index) => {
162
- const baseComponent = props[`${type}Component`];
163
- const componentProps = this.getComponentProps(baseComponent, type, index);
164
- return React.cloneElement(baseComponent, componentProps);
165
- });
166
- }));
167
-
168
- const labelComponents = flatten(types.map((type) => {
169
- const components = this.dataKeys.map((key, index) => {
170
- const name = `${type}Labels`;
171
- const baseComponent = props[`${type}LabelComponent`];
172
- const labelProps = this.getComponentProps(baseComponent, name, index);
173
- if (labelProps.text !== undefined && labelProps.text !== null) {
174
- return React.cloneElement(baseComponent, labelProps);
175
- }
176
- return undefined;
177
- });
178
- return components.filter(Boolean);
179
- }));
203
+ const dataComponents = flatten(
204
+ types.map((type) => {
205
+ return this.dataKeys.reduce((validDataComponents, _key, index) => {
206
+ const baseComponent = props[`${type}Component`];
207
+ const componentProps = this.getComponentProps(baseComponent, type, index);
208
+ if (this.shouldRenderDatum(componentProps.datum)) {
209
+ validDataComponents.push(React.cloneElement(baseComponent, componentProps));
210
+ }
211
+ return validDataComponents;
212
+ }, []);
213
+ })
214
+ );
215
+
216
+ const labelComponents = flatten(
217
+ types.map((type) => {
218
+ const components = this.dataKeys.map((key, index) => {
219
+ const name = `${type}Labels`;
220
+ const baseComponent = props[`${type}LabelComponent`];
221
+ const labelProps = this.getComponentProps(baseComponent, name, index);
222
+ if (labelProps.text !== undefined && labelProps.text !== null) {
223
+ return React.cloneElement(baseComponent, labelProps);
224
+ }
225
+ return undefined;
226
+ });
227
+ return components.filter(Boolean);
228
+ })
229
+ );
180
230
  const children = [...dataComponents, ...labelComponents];
181
231
  return this.renderContainer(props.groupComponent, children);
182
232
  }
@@ -186,12 +236,27 @@ class VictoryBoxPlot extends React.Component {
186
236
  return !!this.props.animate;
187
237
  }
188
238
 
239
+ shouldRenderDatum(datum) {
240
+ const hasX = !isNil(datum._x);
241
+ const hasY = !isNil(datum._y);
242
+ const hasSummaryStatistics =
243
+ !isNil(datum._min) &&
244
+ !isNil(datum._max) &&
245
+ !isNil(datum._median) &&
246
+ !isNil(datum._q1) &&
247
+ !isNil(datum._q3);
248
+
249
+ return hasSummaryStatistics && (this.props.horizontal ? hasY : hasX);
250
+ }
251
+
189
252
  render() {
190
- const { role } = this.constructor;
253
+ const { animationWhitelist, role } = VictoryBoxPlot;
191
254
  const props = Helpers.modifyProps(this.props, fallbackProps, role);
255
+
192
256
  if (this.shouldAnimate()) {
193
257
  return this.animateComponent(props, animationWhitelist);
194
258
  }
259
+
195
260
  const children = this.renderBoxPlot(props);
196
261
  return props.standalone ? this.renderContainer(props.containerComponent, children) : children;
197
262
  }