victory-stack 35.11.2 → 36.1.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "victory-stack",
3
- "version": "35.11.2",
3
+ "version": "36.1.0",
4
4
  "description": "Stack Layout Component for Victory",
5
5
  "keywords": [
6
6
  "data visualization",
@@ -22,14 +22,15 @@
22
22
  "lodash": "^4.17.19",
23
23
  "prop-types": "^15.5.8",
24
24
  "react-fast-compare": "^2.0.0",
25
- "victory-core": "^35.11.2",
26
- "victory-shared-events": "^35.11.2"
25
+ "victory-core": "^36.1.0",
26
+ "victory-shared-events": "^36.1.0"
27
27
  },
28
28
  "peerDependencies": {
29
29
  "react": "^16.6.0 || ^17.0.0"
30
30
  },
31
31
  "scripts": {
32
- "version": "nps build-libs && nps build-dists"
32
+ "version": "yarn run nps build-libs && nps build-dists"
33
33
  },
34
- "sideEffects": false
34
+ "sideEffects": false,
35
+ "gitHead": "038cd9b70d9ce54ac6b861014165583760734c99"
35
36
  }
@@ -7,7 +7,9 @@ import {
7
7
  VictoryTheme,
8
8
  CommonProps,
9
9
  Wrapper,
10
- PropTypes as CustomPropTypes
10
+ PropTypes as CustomPropTypes,
11
+ useAnimationState,
12
+ usePreviousProps
11
13
  } from "victory-core";
12
14
  import { VictorySharedEvents } from "victory-shared-events";
13
15
  import { getChildren, getCalculatedProps } from "./helper-methods";
@@ -19,102 +21,38 @@ const fallbackProps = {
19
21
  padding: 50
20
22
  };
21
23
 
22
- export default class VictoryStack extends React.Component {
23
- static displayName = "VictoryStack";
24
-
25
- static role = "stack";
26
-
27
- static propTypes = {
28
- ...CommonProps.baseProps,
29
- bins: PropTypes.oneOfType([
30
- PropTypes.arrayOf(
31
- PropTypes.oneOfType([
32
- CustomPropTypes.nonNegative,
33
- PropTypes.instanceOf(Date)
34
- ])
35
- ),
36
- CustomPropTypes.nonNegative
37
- ]),
38
- categories: PropTypes.oneOfType([
39
- PropTypes.arrayOf(PropTypes.string),
40
- PropTypes.shape({
41
- x: PropTypes.arrayOf(PropTypes.string),
42
- y: PropTypes.arrayOf(PropTypes.string)
43
- })
44
- ]),
45
- children: PropTypes.oneOfType([
46
- PropTypes.arrayOf(PropTypes.node),
47
- PropTypes.node
48
- ]),
49
- colorScale: PropTypes.oneOfType([
50
- PropTypes.arrayOf(PropTypes.string),
51
- PropTypes.oneOf([
52
- "grayscale",
53
- "qualitative",
54
- "heatmap",
55
- "warm",
56
- "cool",
57
- "red",
58
- "green",
59
- "blue"
60
- ])
61
- ]),
62
- fillInMissingData: PropTypes.bool,
63
- horizontal: PropTypes.bool,
64
- labelComponent: PropTypes.element,
65
- labels: PropTypes.oneOfType([PropTypes.func, PropTypes.array]),
66
- style: PropTypes.shape({
67
- parent: PropTypes.object,
68
- data: PropTypes.object,
69
- labels: PropTypes.object
70
- }),
71
- xOffset: PropTypes.number
72
- };
73
-
74
- static defaultProps = {
75
- containerComponent: <VictoryContainer />,
76
- groupComponent: <g />,
77
- standalone: true,
78
- theme: VictoryTheme.grayscale,
79
- fillInMissingData: true
80
- };
81
-
82
- static expectedComponents = [
83
- "groupComponent",
84
- "containerComponent",
85
- "labelComponent"
86
- ];
87
-
88
- static getChildren = getChildren;
89
-
90
- constructor(props) {
91
- super(props);
92
- if (props.animate) {
93
- this.state = {
94
- nodesShouldLoad: false,
95
- nodesDoneLoad: false,
96
- animating: true
97
- };
98
- this.setAnimationState = Wrapper.setAnimationState.bind(this);
99
- }
100
- }
24
+ const VictoryStack = (initialProps) => {
25
+ // eslint-disable-next-line no-use-before-define
26
+ const { role } = VictoryStackMemo;
27
+ const { setAnimationState, getAnimationProps, getProps } =
28
+ useAnimationState();
101
29
 
102
- shouldComponentUpdate(nextProps) {
103
- if (this.props.animate) {
104
- if (!isEqual(this.props, nextProps)) {
105
- this.setAnimationState(this.props, nextProps);
106
- return false;
107
- }
108
- }
109
- return true;
110
- }
30
+ const props = getProps(initialProps);
31
+
32
+ const modifiedProps = Helpers.modifyProps(props, fallbackProps, role);
33
+ const {
34
+ eventKey,
35
+ containerComponent,
36
+ standalone,
37
+ groupComponent,
38
+ externalEventMutations,
39
+ width,
40
+ height,
41
+ theme,
42
+ polar,
43
+ horizontal,
44
+ name
45
+ } = modifiedProps;
46
+
47
+ const childComponents = React.Children.toArray(modifiedProps.children);
48
+ const calculatedProps = getCalculatedProps(modifiedProps, childComponents);
49
+ const { domain, scale, style, origin } = calculatedProps;
111
50
 
112
- getNewChildren(props, childComponents, calculatedProps) {
51
+ const newChildren = React.useMemo(() => {
113
52
  const children = getChildren(props, childComponents, calculatedProps);
114
- const getAnimationProps = Wrapper.getAnimationProps.bind(this);
115
- const newChildren = children.map((child, index) => {
53
+ const orderedChildren = children.map((child, index) => {
116
54
  const childProps = assign(
117
- { animate: getAnimationProps(props, child, index) },
55
+ { animate: getAnimationProps(props, child, index, "victory-stack") },
118
56
  child.props
119
57
  );
120
58
  return React.cloneElement(child, childProps);
@@ -124,73 +62,149 @@ export default class VictoryStack extends React.Component {
124
62
  are rendered behind lower children. This looks nicer for stacked bars with cornerRadius, and
125
63
  areas with strokes
126
64
  */
127
- return newChildren.reverse();
128
- }
129
-
130
- renderContainer(containerComponent, props) {
131
- const containerProps = defaults({}, containerComponent.props, props);
132
- return React.cloneElement(containerComponent, containerProps);
133
- }
65
+ return orderedChildren.reverse();
66
+ }, [props, childComponents, calculatedProps, getAnimationProps]);
134
67
 
135
- getContainerProps(props, calculatedProps) {
136
- const { width, height, standalone, theme, polar, horizontal, name } = props;
137
- const { domain, scale, style, origin } = calculatedProps;
138
- return {
139
- domain,
140
- scale,
141
- width,
142
- height,
143
- standalone,
144
- theme,
145
- style: style.parent,
146
- horizontal,
147
- polar,
148
- origin,
149
- name
150
- };
151
- }
68
+ const containerProps = React.useMemo(() => {
69
+ if (standalone) {
70
+ return {
71
+ domain,
72
+ scale,
73
+ width,
74
+ height,
75
+ standalone,
76
+ theme,
77
+ style: style.parent,
78
+ horizontal,
79
+ polar,
80
+ origin,
81
+ name
82
+ };
83
+ }
84
+ return {};
85
+ }, [
86
+ standalone,
87
+ domain,
88
+ scale,
89
+ width,
90
+ height,
91
+ theme,
92
+ style,
93
+ horizontal,
94
+ polar,
95
+ origin,
96
+ name
97
+ ]);
152
98
 
153
- render() {
154
- const { role } = this.constructor;
155
- const props =
156
- this.state && this.state.nodesWillExit
157
- ? this.state.oldProps || this.props
158
- : this.props;
159
- const modifiedProps = Helpers.modifyProps(props, fallbackProps, role);
160
- const {
161
- eventKey,
162
- containerComponent,
163
- standalone,
164
- groupComponent,
165
- externalEventMutations
166
- } = modifiedProps;
167
- const childComponents = React.Children.toArray(modifiedProps.children);
168
- const calculatedProps = getCalculatedProps(modifiedProps, childComponents);
169
- const newChildren = this.getNewChildren(
170
- modifiedProps,
171
- childComponents,
172
- calculatedProps
173
- );
174
- const containerProps = standalone
175
- ? this.getContainerProps(modifiedProps, calculatedProps)
176
- : {};
177
- const container = standalone
178
- ? this.renderContainer(containerComponent, containerProps)
179
- : groupComponent;
180
- const events = Wrapper.getAllEvents(props);
181
- if (!isEmpty(events)) {
182
- return (
183
- <VictorySharedEvents
184
- container={container}
185
- eventKey={eventKey}
186
- events={events}
187
- externalEventMutations={externalEventMutations}
188
- >
189
- {newChildren}
190
- </VictorySharedEvents>
99
+ const container = React.useMemo(() => {
100
+ if (standalone) {
101
+ const defaultContainerProps = defaults(
102
+ {},
103
+ containerComponent.props,
104
+ containerProps
191
105
  );
106
+ return React.cloneElement(containerComponent, defaultContainerProps);
192
107
  }
108
+ return groupComponent;
109
+ }, [groupComponent, standalone, containerComponent, containerProps]);
110
+
111
+ const events = React.useMemo(() => {
112
+ return Wrapper.getAllEvents(props);
113
+ }, [props]);
193
114
 
194
- return React.cloneElement(container, container.props, newChildren);
115
+ const previousProps = usePreviousProps(initialProps);
116
+
117
+ React.useEffect(() => {
118
+ // This is called before dismount to keep state in sync
119
+ return () => {
120
+ if (initialProps.animate) {
121
+ setAnimationState(previousProps, initialProps);
122
+ }
123
+ };
124
+ }, [setAnimationState, previousProps, initialProps]);
125
+
126
+ if (!isEmpty(events)) {
127
+ return (
128
+ <VictorySharedEvents
129
+ container={container}
130
+ eventKey={eventKey}
131
+ events={events}
132
+ externalEventMutations={externalEventMutations}
133
+ >
134
+ {newChildren}
135
+ </VictorySharedEvents>
136
+ );
195
137
  }
196
- }
138
+
139
+ return React.cloneElement(container, container.props, newChildren);
140
+ };
141
+
142
+ VictoryStack.propTypes = {
143
+ ...CommonProps.baseProps,
144
+ bins: PropTypes.oneOfType([
145
+ PropTypes.arrayOf(
146
+ PropTypes.oneOfType([
147
+ CustomPropTypes.nonNegative,
148
+ PropTypes.instanceOf(Date)
149
+ ])
150
+ ),
151
+ CustomPropTypes.nonNegative
152
+ ]),
153
+ categories: PropTypes.oneOfType([
154
+ PropTypes.arrayOf(PropTypes.string),
155
+ PropTypes.shape({
156
+ x: PropTypes.arrayOf(PropTypes.string),
157
+ y: PropTypes.arrayOf(PropTypes.string)
158
+ })
159
+ ]),
160
+ children: PropTypes.oneOfType([
161
+ PropTypes.arrayOf(PropTypes.node),
162
+ PropTypes.node
163
+ ]),
164
+ colorScale: PropTypes.oneOfType([
165
+ PropTypes.arrayOf(PropTypes.string),
166
+ PropTypes.oneOf([
167
+ "grayscale",
168
+ "qualitative",
169
+ "heatmap",
170
+ "warm",
171
+ "cool",
172
+ "red",
173
+ "green",
174
+ "blue"
175
+ ])
176
+ ]),
177
+ fillInMissingData: PropTypes.bool,
178
+ horizontal: PropTypes.bool,
179
+ labelComponent: PropTypes.element,
180
+ labels: PropTypes.oneOfType([PropTypes.func, PropTypes.array]),
181
+ style: PropTypes.shape({
182
+ parent: PropTypes.object,
183
+ data: PropTypes.object,
184
+ labels: PropTypes.object
185
+ }),
186
+ xOffset: PropTypes.number
187
+ };
188
+
189
+ VictoryStack.defaultProps = {
190
+ containerComponent: <VictoryContainer />,
191
+ groupComponent: <g />,
192
+ standalone: true,
193
+ theme: VictoryTheme.grayscale,
194
+ fillInMissingData: true
195
+ };
196
+
197
+ const VictoryStackMemo = React.memo(VictoryStack, isEqual);
198
+
199
+ VictoryStackMemo.displayName = "VictoryStack";
200
+ VictoryStackMemo.role = "stack";
201
+
202
+ VictoryStackMemo.expectedComponents = [
203
+ "groupComponent",
204
+ "containerComponent",
205
+ "labelComponent"
206
+ ];
207
+
208
+ VictoryStackMemo.getChildren = getChildren;
209
+
210
+ export default VictoryStackMemo;