Skip to content

Commit f0eb00c

Browse files
authored
Typescript/stack aggregator (#1339)
* file js -> ts * .ts -> .tsx * moved component to typescript * demo screen .js -> .tsx * added ButtonSize export * StackAggregator screen to typescript * fix export * deleted .d.ts file * PR comments
1 parent f151399 commit f0eb00c

File tree

5 files changed

+94
-104
lines changed

5 files changed

+94
-104
lines changed

demo/src/screens/componentScreens/StackAggregatorScreen.js renamed to demo/src/screens/componentScreens/StackAggregatorScreen.tsx

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,30 @@
11
import _ from 'lodash';
22
import React, {Component} from 'react';
33
import {ScrollView} from 'react-native';
4-
import {/* Colors, Typography, */View, Text, Button, StackAggregator} from 'react-native-ui-lib'; //eslint-disable-line
4+
import {View, Text, Button, ButtonSize, StackAggregator} from 'react-native-ui-lib';
55

66

77
const contents = [
88
'Lorem Ipsum is simply dummy text of the printing and typesetting industry.',
99
'Lorem Ipsum is simply dummy text of the printing and typesetting industry.',
1010
'Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum is simply dummy text of the printing and typesetting industry.',
1111
'Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum is simply dummy text of the printing and typesetting industry.'
12-
]
12+
];
1313

1414
export default class StackAggregatorScreen extends Component {
1515

16-
onItemPress = (index) => {
16+
onItemPress = (index: number) => {
1717
console.warn('item pressed: ', index);
1818
}
1919

20-
onPress = (index) => {
20+
onPress = (index: number) => {
2121
console.warn('item\'s button pressed: ', index);
2222
}
2323

24-
renderItem = (item, index) => {
24+
renderItem = (_: string, index: number) => {
2525
return (
2626
<View key={index} center padding-12>
27-
<Button label={`${index}`} marginB-10 size={'small'} onPress={() => this.onPress(index)}/>
27+
<Button label={`${index}`} marginB-10 size={ButtonSize.small} onPress={() => this.onPress(index)}/>
2828
<Text>{contents[index]}</Text>
2929
</View>
3030
);

generatedTypes/index.d.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ export {default as Constants} from './helpers/Constants';
3131
export {default as View, ViewPropTypes, ViewProps} from './components/view';
3232
export {default as Text, TextPropTypes, TextProps} from './components/text';
3333
export {default as TouchableOpacity, TouchableOpacityProps} from './components/touchableOpacity';
34-
export {default as Button, ButtonPropTypes, ButtonProps} from './components/button';
34+
export {default as Button, ButtonPropTypes, ButtonSize, ButtonProps} from './components/button';
3535
export {default as Checkbox, CheckboxPropTypes, CheckboxProps} from './components/checkbox';
3636
export {default as Chip, ChipPropTypes, ChipProps} from './components/chip';
3737
export {default as Drawer, DrawerProps, DrawerItemProps} from './components/drawer';

src/components/stackAggregator/index.js renamed to src/components/stackAggregator/index.tsx

Lines changed: 85 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -1,108 +1,115 @@
11
import _ from 'lodash';
2-
import PropTypes from 'prop-types';
3-
import React from 'react';
4-
import {StyleSheet, Animated, Easing, LayoutAnimation} from 'react-native';
2+
import React, {PureComponent} from 'react';
3+
import {StyleSheet, Animated, Easing, LayoutAnimation, StyleProp, ViewStyle, LayoutChangeEvent} from 'react-native';
54
import {Constants} from '../../helpers';
65
import {Colors} from '../../style';
7-
import {PureBaseComponent} from '../../commons';
8-
import View from '../view';
6+
import View, {ViewProps} from '../view';
97
import TouchableOpacity from '../touchableOpacity';
10-
import Button from '../button';
8+
import Button, {ButtonSize, ButtonProps} from '../button';
119
import Card from '../card';
10+
import {asBaseComponent} from '../../commons/new';
1211

1312
const PEEP = 8;
1413
const DURATION = 300;
1514
const MARGIN_BOTTOM = 24;
1615
const buttonStartValue = 0.8;
1716
const icon = require('./assets/arrow-down.png');
1817

19-
/**
20-
* @description: Stack aggregator component
21-
* @modifiers: margin, padding
22-
* @example: https://github.com/wix/react-native-ui-lib/blob/master/demo/src/screens/componentScreens/StackAggregatorScreen.js
23-
* @gif: https://github.com/wix/react-native-ui-lib/blob/master/demo/showcase/StackAggregator/StackAggregator.gif?raw=true
24-
*/
25-
export default class StackAggregator extends PureBaseComponent {
26-
static displayName = 'StackAggregator';
27-
28-
static propTypes = {
29-
/**
18+
export type StackAggregatorProps = ViewProps & {
19+
/**
3020
* The initial state of the stack
3121
*/
32-
collapsed: PropTypes.bool,
22+
collapsed: boolean;
23+
/**
24+
* Component Children
25+
*/
26+
children: JSX.Element | JSX.Element[]
3327
/**
3428
* The container style
3529
*/
36-
containerStyle: PropTypes.oneOfType([PropTypes.object, PropTypes.number, PropTypes.array]),
30+
containerStyle?: StyleProp<ViewStyle>;
3731
/**
3832
* The content container style
3933
*/
40-
contentContainerStyle: PropTypes.oneOfType([PropTypes.object, PropTypes.number, PropTypes.array]),
34+
contentContainerStyle?: StyleProp<ViewStyle>;
4135
/**
4236
* The items border radius
4337
*/
44-
itemBorderRadius: PropTypes.number,
38+
itemBorderRadius?: number;
4539
/**
4640
* Props passed to the 'show less' button
4741
*/
48-
buttonProps: PropTypes.object,
42+
buttonProps?: ButtonProps;
4943
/**
5044
* A callback for item press
5145
*/
52-
onItemPress: PropTypes.func,
46+
onItemPress?: (index: number) => void;
5347
/**
5448
* A callback for collapse state will change (value is future collapsed state)
5549
*/
56-
onCollapseWillChange: PropTypes.func,
50+
onCollapseWillChange?: (changed: boolean) => void;
5751
/**
58-
* A callback for collapse state change (value is collapsed state)
59-
*/
60-
onCollapseChanged: PropTypes.func,
52+
* A callback for collapse state change (value is collapsed state)
53+
*/
54+
onCollapseChanged?: (changed: boolean) => void;
6155
/**
6256
* A setting that disables pressability on cards
6357
*/
64-
disablePresses: PropTypes.boolean
65-
}
58+
disablePresses?: boolean;
59+
};
60+
61+
62+
type State = {
63+
collapsed: boolean;
64+
firstItemHeight?: number;
65+
};
66+
67+
/**
68+
* @description: Stack aggregator component
69+
* @modifiers: margin, padding
70+
* @example: https://github.com/wix/react-native-ui-lib/blob/master/demo/src/screens/componentScreens/StackAggregatorScreen.js
71+
*/
72+
class StackAggregator extends PureComponent<StackAggregatorProps, State> {
73+
static displayName = 'StackAggregator';
74+
75+
animatedScale: Animated.Value;
76+
animatedOpacity: any;
77+
animatedContentOpacity: any;
78+
itemsCount = React.Children.count(this.props.children);
79+
easeOut = Easing.bezier(0, 0, 0.58, 1);
80+
animatedScaleArray: Animated.Value[];
6681

6782
static defaultProps = {
6883
disablePresses: false,
6984
collapsed: true,
7085
itemBorderRadius: 0
7186
};
7287

73-
constructor(props) {
88+
constructor(props: StackAggregatorProps) {
7489
super(props);
75-
7690
this.state = {
7791
collapsed: props.collapsed,
7892
firstItemHeight: undefined
7993
};
80-
81-
this.itemsCount = React.Children.count(props.children);
82-
this.easeOut = Easing.bezier(0, 0, 0.58, 1);
8394
this.animatedScale = new Animated.Value(this.state.collapsed ? buttonStartValue : 1);
8495
this.animatedOpacity = new Animated.Value(this.state.collapsed ? buttonStartValue : 1);
85-
this.animatedScaleArray = this.getAnimatedScales();
8696
this.animatedContentOpacity = new Animated.Value(this.state.collapsed ? 0 : 1);
97+
this.animatedScaleArray = this.getAnimatedScales();
8798
}
8899

89-
componentDidUpdate(_prevProps, prevState) {
90-
if (prevState.collapsed !== this.state.collapsed) {
100+
componentDidUpdate(_prevProps: StackAggregatorProps, prevState: State) {
101+
if (prevState.collapsed !== this.state?.collapsed) {
91102
LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut);
92103
}
93104
}
94105

95-
generateStyles() {
96-
this.styles = createStyles(this.getThemeProps());
97-
}
98-
99-
getAnimatedScales() {
106+
getAnimatedScales = (): Animated.Value[] => {
100107
return React.Children.map(this.props.children, (_item, index) => {
101108
return new Animated.Value(this.getItemScale(index));
102109
});
103110
}
104111

105-
getItemScale(index) {
112+
getItemScale = (index: number) => {
106113
if (this.state.collapsed) {
107114
if (index === this.itemsCount - 2) {
108115
return 0.95;
@@ -116,12 +123,12 @@ export default class StackAggregator extends PureBaseComponent {
116123

117124
animate = async () => {
118125
return Promise.all([this.animateValues(), this.animateCards()]);
119-
}
126+
};
120127

121128
animateValues() {
122129
const {collapsed} = this.state;
123130
const newValue = collapsed ? buttonStartValue : 1;
124-
return new Promise((resolve) => {
131+
return new Promise(resolve => {
125132
Animated.parallel([
126133
Animated.timing(this.animatedOpacity, {
127134
duration: DURATION,
@@ -144,13 +151,13 @@ export default class StackAggregator extends PureBaseComponent {
144151
});
145152
}
146153

147-
animateCards() {
154+
animateCards() {
148155
const promises = [];
149156
for (let index = 0; index < this.itemsCount; index++) {
150157
const newScale = this.getItemScale(index);
151158

152159
promises.push(
153-
new Promise((resolve) => {
160+
new Promise(resolve => {
154161
Animated.timing(this.animatedScaleArray[index], {
155162
toValue: Number(newScale),
156163
easing: this.easeOut,
@@ -173,7 +180,7 @@ export default class StackAggregator extends PureBaseComponent {
173180
this.animate();
174181
}
175182
});
176-
}
183+
};
177184

178185
open = () => {
179186
this.setState({collapsed: false}, async () => {
@@ -185,9 +192,9 @@ export default class StackAggregator extends PureBaseComponent {
185192
this.animate();
186193
}
187194
});
188-
}
195+
};
189196

190-
getTop(index) {
197+
getTop(index: number) {
191198
let start = 0;
192199

193200
if (index === this.itemsCount - 2) {
@@ -200,7 +207,7 @@ export default class StackAggregator extends PureBaseComponent {
200207
return start;
201208
}
202209

203-
getStyle(index) {
210+
getStyle(index: number): StyleProp<ViewStyle> {
204211
const {collapsed} = this.state;
205212
const top = this.getTop(index);
206213

@@ -216,19 +223,19 @@ export default class StackAggregator extends PureBaseComponent {
216223
};
217224
}
218225

219-
onLayout = event => {
226+
onLayout = (event: LayoutChangeEvent) => {
220227
const height = event.nativeEvent.layout.height;
221228

222229
if (height) {
223230
this.setState({firstItemHeight: height});
224231
}
225232
};
226233

227-
onItemPress = index => {
234+
onItemPress = (index: number) => {
228235
_.invoke(this.props, 'onItemPress', index);
229236
};
230237

231-
renderItem = (item, index) => {
238+
renderItem = (item: JSX.Element | JSX.Element[], index: number) => {
232239
const {contentContainerStyle, itemBorderRadius} = this.props;
233240
const {firstItemHeight, collapsed} = this.state;
234241

@@ -237,7 +244,7 @@ export default class StackAggregator extends PureBaseComponent {
237244
key={index}
238245
onLayout={index === 0 ? this.onLayout : undefined}
239246
style={[
240-
Constants.isIOS && this.styles.containerShadow,
247+
Constants.isIOS && styles.containerShadow,
241248
this.getStyle(index),
242249
{
243250
borderRadius: Constants.isIOS ? itemBorderRadius : undefined,
@@ -251,8 +258,8 @@ export default class StackAggregator extends PureBaseComponent {
251258
collapsable={false}
252259
>
253260
<Card
254-
style={[contentContainerStyle, this.styles.card]}
255-
onPress={this.props.disablePresses ? false : () => this.onItemPress(index)}
261+
style={[contentContainerStyle, styles.card]}
262+
onPress={() => this.props.disablePresses && this.onItemPress(index)}
256263
borderRadius={itemBorderRadius}
257264
elevation={5}
258265
>
@@ -283,7 +290,7 @@ export default class StackAggregator extends PureBaseComponent {
283290
label={'Show less'}
284291
iconSource={icon}
285292
link
286-
size={'small'}
293+
size={ButtonSize.small}
287294
{...buttonProps}
288295
marginH-24
289296
marginB-20
@@ -300,7 +307,7 @@ export default class StackAggregator extends PureBaseComponent {
300307
onPress={this.open}
301308
activeOpacity={1}
302309
style={[
303-
this.styles.touchable,
310+
styles.touchable,
304311
{
305312
height: firstItemHeight ? firstItemHeight + PEEP * 2 : undefined,
306313
zIndex: this.itemsCount
@@ -314,22 +321,22 @@ export default class StackAggregator extends PureBaseComponent {
314321
}
315322
}
316323

317-
function createStyles() {
318-
return StyleSheet.create({
319-
touchable: {
320-
position: 'absolute',
321-
width: '100%'
322-
},
323-
containerShadow: {
324-
backgroundColor: Colors.white,
325-
shadowColor: Colors.dark40,
326-
shadowOpacity: 0.25,
327-
shadowRadius: 12,
328-
shadowOffset: {height: 5, width: 0}
329-
},
330-
card: {
331-
overflow: 'hidden',
332-
flexShrink: 1
333-
}
334-
});
335-
}
324+
const styles = StyleSheet.create({
325+
touchable: {
326+
position: 'absolute',
327+
width: '100%'
328+
},
329+
containerShadow: {
330+
backgroundColor: Colors.white,
331+
shadowColor: Colors.dark40,
332+
shadowOpacity: 0.25,
333+
shadowRadius: 12,
334+
shadowOffset: {height: 5, width: 0}
335+
},
336+
card: {
337+
overflow: 'hidden',
338+
flexShrink: 1
339+
}
340+
});
341+
342+
export default asBaseComponent<StackAggregatorProps>(StackAggregator);

src/index.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ export {default as Modal, ModalProps, ModalTopBarProps} from './components/modal
5151
export {default as PanGestureView, PanGestureViewProps} from './components/panningViews/panGestureView';
5252
export {default as PanningContext} from './components/panningViews/panningContext';
5353
export {default as asPanViewConsumer} from './components/panningViews/asPanViewConsumer';
54+
export {default as StackAggregator, StackAggregatorProps} from './components/stackAggregator';
5455
export {
5556
default as PanningProvider,
5657
PanningDirections,
@@ -73,7 +74,7 @@ export {
7374
ActionSheet, ConnectionStatusBar, ChipsInput,
7475
FeatureHighlight, BaseInput, TextArea, TextField, MaskedInput, ListItem, Picker,
7576
PickerProps, ProgressBar, Slider, GradientSlider, ColorSliderGroup, Stepper,
76-
TagsInput, SharedTransition, StackAggregator, Toast, WheelPickerDialog, Assets,
77+
TagsInput, SharedTransition, Toast, WheelPickerDialog, Assets,
7778
BaseComponent, PureBaseComponent, UIComponent, forwardRef, AvatarHelper,
7879
LoaderScreen, StateScreen, WheelPicker, WheelPickerProps
7980
} from '../typings';

0 commit comments

Comments
 (0)