Skip to content

Commit a4ae160

Browse files
ethansharbneigher
andauthored
Feature/added stackaggregator on collapsed change (#1210)
* [StackAgregator] added onCollapsedChange watcher function as aon optional prop to stack aggregator. nice to respond to whether the stack is collapsed or not * [StackAggregator] - added optional prop to disable onPress effect on all children cards * add optional animation end promise support, added onCollapseWillchange handler * [StackAggregator] safe invoke function if in props * lint fixes * remove bat files Co-authored-by: bneigher <[email protected]>
1 parent a6bc27d commit a4ae160

File tree

2 files changed

+76
-38
lines changed

2 files changed

+76
-38
lines changed

src/components/stackAggregator/index.js

Lines changed: 73 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -48,10 +48,23 @@ export default class StackAggregator extends PureBaseComponent {
4848
/**
4949
* A callback for item press
5050
*/
51-
onItemPress: PropTypes.func
52-
};
51+
onItemPress: PropTypes.func,
52+
/**
53+
* A callback for collapse state will change (value is future collapsed state)
54+
*/
55+
onCollapseWillChange: PropTypes.func,
56+
/**
57+
* A callback for collapse state change (value is collapsed state)
58+
*/
59+
onCollapseChanged: PropTypes.func,
60+
/**
61+
* A setting that disables pressability on cards
62+
*/
63+
disablePresses: PropTypes.boolean
64+
}
5365

5466
static defaultProps = {
67+
disablePresses: false,
5568
collapsed: true,
5669
itemBorderRadius: 0
5770
};
@@ -100,56 +113,78 @@ export default class StackAggregator extends PureBaseComponent {
100113
return 1;
101114
}
102115

103-
animate = () => {
104-
this.animateValues();
105-
this.animateCards();
106-
};
116+
animate = async () => {
117+
return Promise.all([this.animateValues(), this.animateCards()]);
118+
}
107119

108120
animateValues() {
109121
const {collapsed} = this.state;
110122
const newValue = collapsed ? buttonStartValue : 1;
111-
112-
Animated.parallel([
113-
Animated.timing(this.animatedOpacity, {
114-
duration: DURATION,
115-
toValue: Number(newValue),
116-
useNativeDriver: true
117-
}),
118-
Animated.timing(this.animatedScale, {
119-
toValue: Number(newValue),
120-
easing: this.easeOut,
121-
duration: DURATION,
122-
useNativeDriver: true
123-
}),
124-
Animated.timing(this.animatedContentOpacity, {
125-
toValue: Number(collapsed ? 0 : 1),
126-
easing: this.easeOut,
127-
duration: DURATION,
128-
useNativeDriver: true
129-
})
130-
]).start();
123+
return new Promise((resolve) => {
124+
Animated.parallel([
125+
Animated.timing(this.animatedOpacity, {
126+
duration: DURATION,
127+
toValue: Number(newValue),
128+
useNativeDriver: true
129+
}),
130+
Animated.timing(this.animatedScale, {
131+
toValue: Number(newValue),
132+
easing: this.easeOut,
133+
duration: DURATION,
134+
useNativeDriver: true
135+
}),
136+
Animated.timing(this.animatedContentOpacity, {
137+
toValue: Number(collapsed ? 0 : 1),
138+
easing: this.easeOut,
139+
duration: DURATION,
140+
useNativeDriver: true
141+
})
142+
]).start(resolve);
143+
});
131144
}
132145

133-
animateCards() {
146+
animateCards() {
147+
const promises = [];
134148
for (let index = 0; index < this.itemsCount; index++) {
135149
const newScale = this.getItemScale(index);
136150

137-
Animated.timing(this.animatedScaleArray[index], {
138-
toValue: Number(newScale),
139-
easing: this.easeOut,
140-
duration: DURATION,
141-
useNativeDriver: true
142-
}).start();
151+
promises.push(
152+
new Promise((resolve) => {
153+
Animated.timing(this.animatedScaleArray[index], {
154+
toValue: Number(newScale),
155+
easing: this.easeOut,
156+
duration: DURATION,
157+
useNativeDriver: true
158+
}).start(resolve);
159+
})
160+
);
143161
}
162+
return Promise.all(promises);
144163
}
145164

146165
close = () => {
147-
this.setState({collapsed: true}, () => this.animate());
148-
};
166+
this.setState({collapsed: true}, async () => {
167+
_.invoke(this.props, 'onCollapseWillChange', true);
168+
if (this.props.onCollapseChanged) {
169+
await this.animate();
170+
this.props.onCollapseChanged(true);
171+
} else {
172+
this.animate();
173+
}
174+
});
175+
}
149176

150177
open = () => {
151-
this.setState({collapsed: false}, () => this.animate());
152-
};
178+
this.setState({collapsed: false}, async () => {
179+
_.invoke(this.props, 'onCollapseWillChange', false);
180+
if (this.props.onCollapseChanged) {
181+
await this.animate();
182+
this.props.onCollapseChanged(false);
183+
} else {
184+
this.animate();
185+
}
186+
});
187+
}
153188

154189
getTop(index) {
155190
let start = 0;
@@ -216,7 +251,7 @@ export default class StackAggregator extends PureBaseComponent {
216251
>
217252
<Card
218253
style={[contentContainerStyle, this.styles.card]}
219-
onPress={() => this.onItemPress(index)}
254+
onPress={this.props.disablePresses ? false : () => this.onItemPress(index)}
220255
borderRadius={itemBorderRadius}
221256
elevation={5}
222257
>

typings/components/StackAggregator.d.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,14 @@ import {ButtonProps} from './Button';
55

66
export interface StackAggregatorProps {
77
collapsed?: boolean;
8+
disablePresses?: boolean;
89
containerStyle?: StyleProp<ViewStyle>;
910
contentContainerStyle?: StyleProp<ViewStyle>;
1011
itemBorderRadius?: number;
1112
buttonProps?: ButtonProps;
1213
onItemPress?: (index: number) => void;
14+
onCollapseWillChange?: (future: boolean) => void;
15+
onCollapseChanged?: (collapsed: boolean) => void;
1316
}
1417

1518
export class StackAggregator extends PureBaseComponent<StackAggregatorProps> {}

0 commit comments

Comments
 (0)