unicorn-demo-app 7.3.3 → 7.3.4
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 +1 -1
- package/src/screens/PlaygroundScreen.tsx +2 -1
- package/src/screens/componentScreens/ActionBarScreen.tsx +7 -3
- package/src/screens/componentScreens/AvatarsScreen.tsx +6 -6
- package/src/screens/componentScreens/BasicListScreen.tsx +1 -0
- package/src/screens/componentScreens/ButtonsScreen.tsx +13 -11
- package/src/screens/componentScreens/CarouselScreen.tsx +1 -1
- package/src/screens/componentScreens/ChipsInputScreen.tsx +1 -1
- package/src/screens/componentScreens/ColorPickerScreen.tsx +1 -1
- package/src/screens/componentScreens/DrawerScreen.tsx +56 -39
- package/src/screens/componentScreens/GridViewScreen.tsx +3 -3
- package/src/screens/componentScreens/HintsScreen.tsx +2 -2
- package/src/screens/componentScreens/ModalScreen.tsx +1 -1
- package/src/screens/componentScreens/OverlaysScreen.tsx +2 -2
- package/src/screens/componentScreens/PanDismissibleScreen.tsx +1 -1
- package/src/screens/componentScreens/PanListenerScreen.tsx +4 -3
- package/src/screens/componentScreens/ScrollBarScreen.tsx +3 -2
- package/src/screens/componentScreens/SectionsWheelPickerScreen.tsx +1 -1
- package/src/screens/componentScreens/SliderScreen.tsx +8 -24
- package/src/screens/componentScreens/TabControllerScreen/index.tsx +4 -3
- package/src/screens/componentScreens/TextFieldScreen.tsx +1 -1
- package/src/screens/componentScreens/WheelPickerScreen.tsx +2 -2
- package/src/screens/componentScreens/WizardScreen.tsx +3 -4
- package/src/screens/incubatorScreens/IncubatorExpandableOverlayScreen.tsx +6 -6
- package/src/screens/incubatorScreens/IncubatorSliderScreen.tsx +0 -5
- package/src/screens/incubatorScreens/IncubatorToastScreen.tsx +2 -3
- package/src/screens/realExamples/Pinterest/index.tsx +6 -14
- package/src/screens/realExamples/ProductPage/index.tsx +9 -17
- package/src/screens/realExamples/Twitter/index.tsx +1 -1
package/package.json
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import React, {Component} from 'react';
|
|
2
|
-
import {
|
|
2
|
+
import {StyleSheet} from 'react-native';
|
|
3
|
+
import {View, Text, Card, TextField, Button} from 'react-native-ui-lib'; //eslint-disable-line
|
|
3
4
|
|
|
4
5
|
export default class PlaygroundScreen extends Component {
|
|
5
6
|
render() {
|
|
@@ -9,9 +9,13 @@ import collections from '../../assets/icons/collections.png';
|
|
|
9
9
|
import richText from '../../assets/icons/richText.png';
|
|
10
10
|
|
|
11
11
|
export default class ActionBarScreen extends Component {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
12
|
+
constructor(props) {
|
|
13
|
+
super(props);
|
|
14
|
+
|
|
15
|
+
this.state = {
|
|
16
|
+
currentPage: 0
|
|
17
|
+
};
|
|
18
|
+
}
|
|
15
19
|
|
|
16
20
|
render() {
|
|
17
21
|
return (
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import _ from 'lodash';
|
|
2
2
|
import React, {Component} from 'react';
|
|
3
3
|
import {ScrollView, StyleSheet, Alert} from 'react-native';
|
|
4
|
-
import {Avatar, AvatarHelper, View, Text, Colors, Typography
|
|
4
|
+
import {Avatar, AvatarHelper, View, Text, Colors, Typography} from 'react-native-ui-lib'; //eslint-disable-line
|
|
5
5
|
|
|
6
6
|
|
|
7
7
|
const star = require('../../assets/icons/star.png');
|
|
@@ -25,7 +25,7 @@ const examples = [
|
|
|
25
25
|
'https://lh3.googleusercontent.com/-cw77lUnOvmI/AAAAAAAAAAI/AAAAAAAAAAA/WMNck32dKbc/s181-c/104220521160525129167.jpg'
|
|
26
26
|
},
|
|
27
27
|
badgeProps: {size: 10, backgroundColor: Colors.$backgroundWarningHeavy},
|
|
28
|
-
badgePosition: 'BOTTOM_RIGHT'
|
|
28
|
+
badgePosition: 'BOTTOM_RIGHT'
|
|
29
29
|
},
|
|
30
30
|
|
|
31
31
|
{
|
|
@@ -36,7 +36,7 @@ const examples = [
|
|
|
36
36
|
'https://lh3.googleusercontent.com/-CMM0GmT5tiI/AAAAAAAAAAI/AAAAAAAAAAA/-o9gKbC6FVo/s181-c/111308920004613908895.jpg'
|
|
37
37
|
},
|
|
38
38
|
badgeProps: {size: 10, backgroundColor: Colors.$backgroundDisabled},
|
|
39
|
-
badgePosition: 'BOTTOM_LEFT'
|
|
39
|
+
badgePosition: 'BOTTOM_LEFT'
|
|
40
40
|
},
|
|
41
41
|
{
|
|
42
42
|
title: 'Image with fade in animation',
|
|
@@ -53,7 +53,7 @@ const examples = [
|
|
|
53
53
|
uri: 'https://randomuser.me/api/portraits/women/24.jpg'
|
|
54
54
|
},
|
|
55
55
|
badgeProps: {size: 14, borderWidth: 0, backgroundColor: onlineColor},
|
|
56
|
-
badgePosition: 'TOP_LEFT'
|
|
56
|
+
badgePosition: 'TOP_LEFT'
|
|
57
57
|
},
|
|
58
58
|
{
|
|
59
59
|
title: 'Icon badge',
|
|
@@ -102,7 +102,7 @@ const examples = [
|
|
|
102
102
|
title: 'With custom badge label',
|
|
103
103
|
label: 'LD',
|
|
104
104
|
backgroundColor: Colors.$backgroundDangerLight,
|
|
105
|
-
badgePosition: 'BOTTOM_RIGHT'
|
|
105
|
+
badgePosition: 'BOTTOM_RIGHT',
|
|
106
106
|
badgeProps: {
|
|
107
107
|
label: '+2',
|
|
108
108
|
size: 24,
|
|
@@ -123,7 +123,7 @@ export default class AvatarsScreen extends Component {
|
|
|
123
123
|
patchedGravatar ? `Patched-uri: ${patchedGravatar}` : ''
|
|
124
124
|
}`;
|
|
125
125
|
Alert.alert(title, message);
|
|
126
|
-
}
|
|
126
|
+
}
|
|
127
127
|
|
|
128
128
|
render() {
|
|
129
129
|
return (
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import React, {Component} from 'react';
|
|
2
2
|
import {ScrollView, StyleSheet, Alert, Image} from 'react-native';
|
|
3
|
-
import {Text, View, Assets, Constants, Button, Colors, Typography
|
|
3
|
+
import {Text, View, Assets, Constants, Button, Colors, Typography} from 'react-native-ui-lib'; //eslint-disable-line
|
|
4
4
|
|
|
5
5
|
const ButtonSpace = 20;
|
|
6
6
|
const plusIcon = Assets.getAssetByPath('icons.demo.plus');
|
|
@@ -9,12 +9,16 @@ const labelButton = {label: 'Animated'};
|
|
|
9
9
|
const iconButton = {round: true};
|
|
10
10
|
|
|
11
11
|
export default class ButtonsScreen extends Component {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
12
|
+
constructor(props) {
|
|
13
|
+
super(props);
|
|
14
|
+
|
|
15
|
+
this.state = {
|
|
16
|
+
backgroundColor: Colors.yellow30,
|
|
17
|
+
label: 'Button',
|
|
18
|
+
// outline: true,
|
|
19
|
+
buttonProps: labelButton
|
|
20
|
+
};
|
|
21
|
+
}
|
|
18
22
|
|
|
19
23
|
changeProps = () => {
|
|
20
24
|
if (this.state.buttonProps === labelButton) {
|
|
@@ -237,11 +241,9 @@ export default class ButtonsScreen extends Component {
|
|
|
237
241
|
style={{
|
|
238
242
|
width: 20,
|
|
239
243
|
height: 20,
|
|
240
|
-
|
|
241
|
-
backgroundColor: iconStyle[0]?.tintColor,
|
|
244
|
+
backgroundColor: iconStyle[0].tintColor,
|
|
242
245
|
borderRadius: 10,
|
|
243
|
-
|
|
244
|
-
marginRight: iconStyle[0]?.marginRight
|
|
246
|
+
marginRight: iconStyle[0].marginRight
|
|
245
247
|
}}
|
|
246
248
|
/>
|
|
247
249
|
)}
|
|
@@ -117,7 +117,7 @@ class CarouselScreen extends Component<Props, State> {
|
|
|
117
117
|
pageControlProps={{onPagePress: this.onPagePress, limitShownPages}}
|
|
118
118
|
allowAccessibleLayout
|
|
119
119
|
>
|
|
120
|
-
{_.map([...Array(numberOfPagesShown)], (
|
|
120
|
+
{_.map([...Array(numberOfPagesShown)], (item, index) => (
|
|
121
121
|
<Page style={{backgroundColor: BACKGROUND_COLORS[index]}} key={index}>
|
|
122
122
|
<Text margin-15>CARD {index}</Text>
|
|
123
123
|
</Page>
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React, {Component} from 'react';
|
|
2
|
-
import {View, Text, Colors, ChipsInput} from 'react-native-ui-lib';
|
|
2
|
+
import {View, Text, Card, TextField, Button, Colors, ChipsInput} from 'react-native-ui-lib'; //eslint-disable-line
|
|
3
3
|
import _ from 'lodash';
|
|
4
4
|
|
|
5
5
|
export default class ChipsInputScreen extends Component {
|
|
@@ -1,48 +1,61 @@
|
|
|
1
1
|
import React, {Component} from 'react';
|
|
2
2
|
import {StyleSheet, ScrollView, LayoutAnimation} from 'react-native';
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
Assets,
|
|
5
|
+
Colors,
|
|
6
|
+
Typography,
|
|
7
|
+
View,
|
|
8
|
+
Drawer,
|
|
9
|
+
Text,
|
|
10
|
+
Button,
|
|
11
|
+
Avatar,
|
|
12
|
+
Badge
|
|
13
|
+
} from 'react-native-ui-lib'; //eslint-disable-line
|
|
4
14
|
import {gestureHandlerRootHOC} from 'react-native-gesture-handler';
|
|
5
15
|
import conversations from '../../data/conversations';
|
|
6
16
|
|
|
7
|
-
import {
|
|
17
|
+
import {
|
|
18
|
+
renderBooleanOption,
|
|
19
|
+
renderSliderOption,
|
|
20
|
+
renderColorOption
|
|
21
|
+
} from '../ExampleScreenPresenter';
|
|
8
22
|
|
|
9
23
|
const ITEMS = {
|
|
10
24
|
read: {
|
|
11
25
|
icon: require('../../assets/icons/mail.png'),
|
|
12
26
|
text: 'Read',
|
|
13
27
|
background: Colors.green30,
|
|
14
|
-
testID:
|
|
28
|
+
testID: "left_item_read"
|
|
15
29
|
},
|
|
16
30
|
archive: {
|
|
17
31
|
icon: require('../../assets/icons/archive.png'),
|
|
18
32
|
text: 'Archive',
|
|
19
33
|
background: Colors.blue30,
|
|
20
|
-
testID:
|
|
34
|
+
testID: "right_item_archive"
|
|
21
35
|
},
|
|
22
36
|
delete: {
|
|
23
37
|
icon: require('../../assets/icons/delete.png'),
|
|
24
38
|
text: 'Delete',
|
|
25
39
|
background: Colors.red30,
|
|
26
|
-
testID:
|
|
40
|
+
testID: "right_item_delete"
|
|
27
41
|
}
|
|
28
42
|
};
|
|
29
43
|
|
|
30
44
|
class DrawerScreen extends Component {
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
showRightItems: true,
|
|
34
|
-
fullSwipeRight: true,
|
|
35
|
-
showLeftItem: true,
|
|
36
|
-
fullSwipeLeft: true,
|
|
37
|
-
unread: true,
|
|
38
|
-
itemsTintColor: undefined,
|
|
39
|
-
bounciness: undefined,
|
|
40
|
-
itemsIconSize: undefined
|
|
41
|
-
};
|
|
45
|
+
constructor(props) {
|
|
46
|
+
super(props);
|
|
42
47
|
|
|
43
|
-
|
|
48
|
+
this.state = {
|
|
49
|
+
hideItem: false,
|
|
50
|
+
showRightItems: true,
|
|
51
|
+
fullSwipeRight: true,
|
|
52
|
+
showLeftItem: true,
|
|
53
|
+
fullSwipeLeft: true,
|
|
54
|
+
unread: true
|
|
55
|
+
};
|
|
56
|
+
}
|
|
44
57
|
|
|
45
|
-
componentDidUpdate(
|
|
58
|
+
componentDidUpdate(prevProps, prevState) {
|
|
46
59
|
if (this.state.hideItem && prevState.hideItem) {
|
|
47
60
|
this.showItem();
|
|
48
61
|
}
|
|
@@ -69,7 +82,7 @@ class DrawerScreen extends Component {
|
|
|
69
82
|
|
|
70
83
|
toggleReadState = () => {
|
|
71
84
|
this.setState({unread: !this.state.unread});
|
|
72
|
-
}
|
|
85
|
+
}
|
|
73
86
|
|
|
74
87
|
showItem = () => {
|
|
75
88
|
this.setState({hideItem: false});
|
|
@@ -77,37 +90,31 @@ class DrawerScreen extends Component {
|
|
|
77
90
|
|
|
78
91
|
openLeftDrawer = () => {
|
|
79
92
|
if (this.ref) {
|
|
80
|
-
// @ts-expect-error
|
|
81
93
|
this.ref.openLeft();
|
|
82
94
|
}
|
|
83
95
|
};
|
|
84
96
|
openLeftDrawerFull = () => {
|
|
85
97
|
if (this.ref) {
|
|
86
|
-
// @ts-expect-error
|
|
87
98
|
this.ref.openLeftFull();
|
|
88
99
|
}
|
|
89
100
|
};
|
|
90
101
|
toggleLeftDrawer = () => {
|
|
91
102
|
if (this.ref) {
|
|
92
|
-
// @ts-expect-error
|
|
93
103
|
this.ref.toggleLeft();
|
|
94
104
|
}
|
|
95
105
|
};
|
|
96
106
|
openRightDrawer = () => {
|
|
97
107
|
if (this.ref) {
|
|
98
|
-
// @ts-expect-error
|
|
99
108
|
this.ref.openRight();
|
|
100
109
|
}
|
|
101
110
|
};
|
|
102
111
|
openRightDrawerFull = () => {
|
|
103
112
|
if (this.ref) {
|
|
104
|
-
// @ts-expect-error
|
|
105
113
|
this.ref.openRightFull();
|
|
106
114
|
}
|
|
107
115
|
};
|
|
108
116
|
closeDrawer = () => {
|
|
109
117
|
if (this.ref) {
|
|
110
|
-
// @ts-expect-error
|
|
111
118
|
this.ref.closeDrawer();
|
|
112
119
|
}
|
|
113
120
|
};
|
|
@@ -142,7 +149,13 @@ class DrawerScreen extends Component {
|
|
|
142
149
|
</View>
|
|
143
150
|
|
|
144
151
|
<View marginH-20>
|
|
145
|
-
<Button
|
|
152
|
+
<Button
|
|
153
|
+
onPress={this.closeDrawer}
|
|
154
|
+
label="Close"
|
|
155
|
+
style={{margin: 3}}
|
|
156
|
+
size={'xSmall'}
|
|
157
|
+
testID="close_btn"
|
|
158
|
+
/>
|
|
146
159
|
</View>
|
|
147
160
|
|
|
148
161
|
<View>
|
|
@@ -179,14 +192,10 @@ class DrawerScreen extends Component {
|
|
|
179
192
|
style={{borderBottomWidth: 1, borderColor: Colors.grey60}}
|
|
180
193
|
testID="drawer_item"
|
|
181
194
|
>
|
|
182
|
-
{this.state.unread &&
|
|
183
|
-
<Badge testID="drawer_item_badge" size={6} backgroundColor={Colors.red30} containerStyle={{marginRight: 8}}/>
|
|
184
|
-
)}
|
|
195
|
+
{this.state.unread && <Badge testID="drawer_item_badge" size={6} backgroundColor={Colors.red30} containerStyle={{marginRight: 8}}/>}
|
|
185
196
|
<Avatar source={{uri: data.thumbnail}}/>
|
|
186
197
|
<View marginL-20>
|
|
187
|
-
<Text text70R={!this.state.unread} text70BO={this.state.unread}>
|
|
188
|
-
{data.name}
|
|
189
|
-
</Text>
|
|
198
|
+
<Text text70R={!this.state.unread} text70BO={this.state.unread}>{data.name}</Text>
|
|
190
199
|
<Text text80 marginT-2>
|
|
191
200
|
{data.text}
|
|
192
201
|
</Text>
|
|
@@ -207,12 +216,11 @@ class DrawerScreen extends Component {
|
|
|
207
216
|
hideItem
|
|
208
217
|
} = this.state;
|
|
209
218
|
|
|
210
|
-
const drawerProps
|
|
219
|
+
const drawerProps = {
|
|
211
220
|
itemsTintColor,
|
|
212
221
|
itemsIconSize,
|
|
213
222
|
bounciness,
|
|
214
|
-
|
|
215
|
-
ref: component => (this.ref = component),
|
|
223
|
+
ref: (component) => (this.ref = component),
|
|
216
224
|
fullSwipeRight,
|
|
217
225
|
onFullSwipeRight: this.deleteItem,
|
|
218
226
|
fullSwipeLeft,
|
|
@@ -228,7 +236,7 @@ class DrawerScreen extends Component {
|
|
|
228
236
|
drawerProps.leftItem = {
|
|
229
237
|
...ITEMS.read,
|
|
230
238
|
icon: this.state.unread ? require('../../assets/icons/mail.png') : require('../../assets/icons/refresh.png'),
|
|
231
|
-
text: !this.state.unread ? 'Unread' : 'Read',
|
|
239
|
+
text: !this.state.unread ? 'Unread' : 'Read',
|
|
232
240
|
background: this.state.unread ? Colors.green30 : Colors.orange30,
|
|
233
241
|
onPress: this.toggleReadState
|
|
234
242
|
};
|
|
@@ -257,13 +265,22 @@ class DrawerScreen extends Component {
|
|
|
257
265
|
</>
|
|
258
266
|
)}
|
|
259
267
|
|
|
260
|
-
<ScrollView
|
|
268
|
+
<ScrollView
|
|
269
|
+
style={styles.container}
|
|
270
|
+
contentContainerStyle={styles.contentContainer}
|
|
271
|
+
>
|
|
261
272
|
<View padding-20>
|
|
262
273
|
{this.renderActions()}
|
|
263
274
|
{renderBooleanOption.call(this, 'rightItems', 'showRightItems')}
|
|
264
|
-
{showRightItems &&
|
|
275
|
+
{showRightItems &&
|
|
276
|
+
renderBooleanOption.call(
|
|
277
|
+
this,
|
|
278
|
+
'fullSwipeRight',
|
|
279
|
+
'fullSwipeRight'
|
|
280
|
+
)}
|
|
265
281
|
{renderBooleanOption.call(this, 'leftItem', 'showLeftItem')}
|
|
266
|
-
{showLeftItem &&
|
|
282
|
+
{showLeftItem &&
|
|
283
|
+
renderBooleanOption.call(this, 'fullSwipeLeft', 'fullSwipeLeft')}
|
|
267
284
|
{renderColorOption.call(this, 'icon+text color', 'itemsTintColor')}
|
|
268
285
|
{renderSliderOption.call(this, 'bounciness', 'bounciness', {
|
|
269
286
|
min: 5,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import _ from 'lodash';
|
|
2
|
-
import {View, Text, Image, Colors, Constants, Avatar, GridView, Card
|
|
2
|
+
import {View, Text, Image, Colors, Constants, Avatar, GridView, Card} from 'react-native-ui-lib';
|
|
3
3
|
import React, {Component} from 'react';
|
|
4
4
|
import {Alert, ScrollView} from 'react-native';
|
|
5
5
|
import conversations from '../../data/conversations';
|
|
@@ -30,7 +30,7 @@ class GridViewScreen extends Component {
|
|
|
30
30
|
return <Text text={product.price} style={{alignSelf: 'center', marginTop: 3}}/>;
|
|
31
31
|
}
|
|
32
32
|
}
|
|
33
|
-
})))(products)
|
|
33
|
+
})))(products),
|
|
34
34
|
pairs: _.flow(products => _.take(products, 2),
|
|
35
35
|
(products: any[]) =>
|
|
36
36
|
_.map(products, product => ({
|
|
@@ -102,7 +102,7 @@ class GridViewScreen extends Component {
|
|
|
102
102
|
);
|
|
103
103
|
}
|
|
104
104
|
}
|
|
105
|
-
})))(products)
|
|
105
|
+
})))(products),
|
|
106
106
|
|
|
107
107
|
avatars: _.flow(products => _.take(products, 9),
|
|
108
108
|
(products: any[]) =>
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import _ from 'lodash';
|
|
2
2
|
import React, {Component} from 'react';
|
|
3
|
-
import {Alert
|
|
3
|
+
import {Alert} from 'react-native';
|
|
4
4
|
import {Colors, View, Text, Hint, Button, Assets, Incubator} from 'react-native-ui-lib';
|
|
5
5
|
import {renderMultipleSegmentOptions, renderBooleanOption} from '../ExampleScreenPresenter';
|
|
6
6
|
|
|
@@ -16,7 +16,7 @@ export default class HintsScreen extends Component<HintScreenProps> {
|
|
|
16
16
|
useShortMessage: false,
|
|
17
17
|
showBottomHint: false,
|
|
18
18
|
showIcon: false,
|
|
19
|
-
targetPosition: 'flex-start'
|
|
19
|
+
targetPosition: 'flex-start',
|
|
20
20
|
useBackdrop: true,
|
|
21
21
|
useTargetFrame: false,
|
|
22
22
|
useSideTip: false,
|
|
@@ -11,11 +11,11 @@ const uri = {
|
|
|
11
11
|
};
|
|
12
12
|
|
|
13
13
|
export default class OverlaysScreen extends Component {
|
|
14
|
-
getImageWithOverlay = (type
|
|
14
|
+
getImageWithOverlay = (type, text, customOverylay) => {
|
|
15
15
|
return (
|
|
16
16
|
<View centerH>
|
|
17
17
|
<Text grey10>{text}</Text>
|
|
18
|
-
<Image /* overlayColor={Colors.rgba(Colors.red40, 0.4)} */ style={styles.image} source={image} overlayType={type} customOverlayContent={
|
|
18
|
+
<Image /* overlayColor={Colors.rgba(Colors.red40, 0.4)} */ style={styles.image} source={image} overlayType={type} customOverlayContent={customOverylay}/>
|
|
19
19
|
</View>
|
|
20
20
|
);
|
|
21
21
|
};
|
|
@@ -64,7 +64,7 @@ export default class PanDismissibleScreen extends Component {
|
|
|
64
64
|
<PanningProvider>
|
|
65
65
|
{!isCoupled && panListener}
|
|
66
66
|
<PanDismissibleView
|
|
67
|
-
key={key
|
|
67
|
+
key={key}
|
|
68
68
|
style={[styles.panDismissible, {marginTop: isCoupled ? PAN_LISTENER_VIEW_HEIGHT : undefined}]}
|
|
69
69
|
>
|
|
70
70
|
{isCoupled && panListener}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
+
import _ from 'lodash';
|
|
1
2
|
import React, {Component} from 'react';
|
|
2
|
-
import {View, Text, PanListenerView, PanDirectionsProps, PanAmountsProps} from 'react-native-ui-lib';
|
|
3
|
+
import {View, Text, PanListenerView, PanningProvider, PanDirectionsProps, PanAmountsProps} from 'react-native-ui-lib'; //eslint-disable-line
|
|
3
4
|
|
|
4
5
|
export default class PanListenerScreen extends Component {
|
|
5
6
|
state = {
|
|
@@ -7,11 +8,11 @@ export default class PanListenerScreen extends Component {
|
|
|
7
8
|
endType: ''
|
|
8
9
|
};
|
|
9
10
|
|
|
10
|
-
onDrag = ({directions}: ({directions: PanDirectionsProps, deltas: PanAmountsProps})) => {
|
|
11
|
+
onDrag = ({directions, deltas}: ({directions: PanDirectionsProps, deltas: PanAmountsProps})) => {
|
|
11
12
|
this.setState({locationText: `Dragged: ${directions.x}, ${directions.y}`});
|
|
12
13
|
};
|
|
13
14
|
|
|
14
|
-
onSwipe = ({directions}: ({directions: PanDirectionsProps, velocities: PanAmountsProps})) => {
|
|
15
|
+
onSwipe = ({directions, velocities}: ({directions: PanDirectionsProps, velocities: PanAmountsProps})) => {
|
|
15
16
|
this.setState({locationText: `Swiped: ${directions.x}, ${directions.y}`});
|
|
16
17
|
};
|
|
17
18
|
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import React, {Component} from 'react';
|
|
2
2
|
import {View, Text, ScrollBar, Button} from 'react-native-ui-lib';
|
|
3
3
|
|
|
4
|
+
|
|
4
5
|
class ScrollBarScreen extends Component {
|
|
5
6
|
state = {
|
|
6
7
|
selectedIndex: 0
|
|
7
8
|
};
|
|
8
9
|
|
|
9
|
-
focus = ({
|
|
10
|
+
focus = ({index}) => {
|
|
10
11
|
this.setState({selectedIndex: index});
|
|
11
12
|
};
|
|
12
13
|
|
|
@@ -32,7 +33,7 @@ class ScrollBarScreen extends Component {
|
|
|
32
33
|
'November',
|
|
33
34
|
'December'
|
|
34
35
|
].map((item, index) => {
|
|
35
|
-
return <Button key={item}
|
|
36
|
+
return <Button key={item} index={index} label={item} size="small" onPress={this.focus} marginR-s2/>;
|
|
36
37
|
})}
|
|
37
38
|
</ScrollBar>
|
|
38
39
|
</View>
|
|
@@ -29,7 +29,7 @@ const SectionsWheelPickerScreen = () => {
|
|
|
29
29
|
return Constants.isRTL && disableRTL;
|
|
30
30
|
}, [disableRTL]);
|
|
31
31
|
|
|
32
|
-
const getItems = useCallback(
|
|
32
|
+
const getItems = useCallback(values => {
|
|
33
33
|
return _.map(values, item => ({label: '' + item, value: item}));
|
|
34
34
|
}, []);
|
|
35
35
|
|
|
@@ -1,16 +1,6 @@
|
|
|
1
1
|
import React, {Component, Fragment} from 'react';
|
|
2
2
|
import {StyleSheet, ScrollView} from 'react-native';
|
|
3
|
-
import {
|
|
4
|
-
Constants,
|
|
5
|
-
Colors,
|
|
6
|
-
View,
|
|
7
|
-
Text,
|
|
8
|
-
Button,
|
|
9
|
-
Icon,
|
|
10
|
-
Slider,
|
|
11
|
-
GradientSlider,
|
|
12
|
-
ColorSliderGroup
|
|
13
|
-
} from 'react-native-ui-lib';
|
|
3
|
+
import {Constants, Colors, View, Text, Button, Icon, Slider, GradientSlider, ColorSliderGroup} from 'react-native-ui-lib';
|
|
14
4
|
import {renderBooleanOption} from '../ExampleScreenPresenter';
|
|
15
5
|
|
|
16
6
|
interface SliderScreenProps {
|
|
@@ -51,20 +41,17 @@ export default class SliderScreen extends Component<SliderScreenProps, SliderScr
|
|
|
51
41
|
gradientSlider = React.createRef();
|
|
52
42
|
|
|
53
43
|
resetSlider = () => {
|
|
54
|
-
// @ts-expect-error
|
|
55
44
|
this.slider.current?.reset();
|
|
56
|
-
// @ts-expect-error
|
|
57
45
|
this.rangeSlider.current?.reset();
|
|
58
|
-
// @ts-expect-error
|
|
59
46
|
this.gradientSlider.current?.reset();
|
|
60
|
-
}
|
|
47
|
+
}
|
|
61
48
|
|
|
62
|
-
onSliderRangeChange = (values: {min: number
|
|
49
|
+
onSliderRangeChange = (values: {min: number, max: number}) => {
|
|
63
50
|
const {min, max} = values;
|
|
64
51
|
this.setState({sliderMinValue: min, sliderMaxValue: max});
|
|
65
52
|
};
|
|
66
53
|
|
|
67
|
-
onSliderRangeChange2 = (values: {min: number
|
|
54
|
+
onSliderRangeChange2 = (values: {min: number, max: number}) => {
|
|
68
55
|
const {min, max} = values;
|
|
69
56
|
this.setState({sliderMinValue2: min, sliderMaxValue2: max});
|
|
70
57
|
};
|
|
@@ -75,11 +62,11 @@ export default class SliderScreen extends Component<SliderScreenProps, SliderScr
|
|
|
75
62
|
|
|
76
63
|
onSliderReset = () => {
|
|
77
64
|
this.setState({sliderValue: INITIAL_VALUE});
|
|
78
|
-
}
|
|
65
|
+
}
|
|
79
66
|
|
|
80
67
|
onRangeSliderReset = () => {
|
|
81
68
|
this.setState({sliderMinValue: RANGE_INITIAL_MIN, sliderMaxValue: RANGE_INITIAL_MAX});
|
|
82
|
-
}
|
|
69
|
+
}
|
|
83
70
|
|
|
84
71
|
onGradientValueChange = (value: string, alpha: number) => {
|
|
85
72
|
this.setState({color: value, alpha});
|
|
@@ -91,7 +78,7 @@ export default class SliderScreen extends Component<SliderScreenProps, SliderScr
|
|
|
91
78
|
|
|
92
79
|
getReverseStyle = () => {
|
|
93
80
|
return Constants.isRTL && this.state.forceLTR && styles.ltr;
|
|
94
|
-
}
|
|
81
|
+
}
|
|
95
82
|
|
|
96
83
|
renderDefaultSliderExample() {
|
|
97
84
|
const {sliderValue, forceLTR} = this.state;
|
|
@@ -101,7 +88,7 @@ export default class SliderScreen extends Component<SliderScreenProps, SliderScr
|
|
|
101
88
|
<Text $textDefault text70BO>
|
|
102
89
|
Default slider
|
|
103
90
|
</Text>
|
|
104
|
-
|
|
91
|
+
|
|
105
92
|
<View row centerV style={this.getReverseStyle()}>
|
|
106
93
|
<Icon assetName={'search'} style={styles.image}/>
|
|
107
94
|
<Slider
|
|
@@ -112,7 +99,6 @@ export default class SliderScreen extends Component<SliderScreenProps, SliderScr
|
|
|
112
99
|
step={1}
|
|
113
100
|
containerStyle={styles.sliderContainer}
|
|
114
101
|
disableRTL={forceLTR}
|
|
115
|
-
// @ts-expect-error
|
|
116
102
|
ref={this.slider}
|
|
117
103
|
onReset={this.onSliderReset}
|
|
118
104
|
/>
|
|
@@ -202,7 +188,6 @@ export default class SliderScreen extends Component<SliderScreenProps, SliderScr
|
|
|
202
188
|
maximumValue={100}
|
|
203
189
|
step={1}
|
|
204
190
|
disableRTL={forceLTR}
|
|
205
|
-
// @ts-expect-error
|
|
206
191
|
ref={this.rangeSlider}
|
|
207
192
|
onReset={this.onRangeSliderReset}
|
|
208
193
|
/>
|
|
@@ -258,7 +243,6 @@ export default class SliderScreen extends Component<SliderScreenProps, SliderScr
|
|
|
258
243
|
color={color}
|
|
259
244
|
containerStyle={styles.gradientSliderContainer}
|
|
260
245
|
onValueChange={this.onGradientValueChange}
|
|
261
|
-
// @ts-expect-error
|
|
262
246
|
ref={this.gradientSlider}
|
|
263
247
|
/>
|
|
264
248
|
<View style={styles.box}>
|
|
@@ -39,13 +39,14 @@ class TabControllerScreen extends Component<{}, State> {
|
|
|
39
39
|
initialIndex: 0,
|
|
40
40
|
selectedIndex: 0,
|
|
41
41
|
key: Date.now(),
|
|
42
|
-
items:
|
|
42
|
+
items: []
|
|
43
43
|
};
|
|
44
|
+
|
|
45
|
+
this.state.items = this.generateTabItems();
|
|
44
46
|
}
|
|
45
47
|
tabController = React.createRef<TabControllerImperativeMethods>();
|
|
46
48
|
|
|
47
49
|
generateTabItems = (fewItems = this.state.fewItems): TabControllerItemProps[] => {
|
|
48
|
-
// @ts-expect-error
|
|
49
50
|
const items: TabControllerItemProps[] = _.flow(tabs => _.take(tabs, fewItems ? 3 : TABS.length),
|
|
50
51
|
(tabs: TabControllerItemProps[]) =>
|
|
51
52
|
_.map<TabControllerItemProps>(tabs, (tab: TabControllerItemProps, index: number) => ({
|
|
@@ -57,7 +58,7 @@ class TabControllerScreen extends Component<{}, State> {
|
|
|
57
58
|
trailingAccessory: index === 4 ? <Text marginL-4>{Assets.emojis.camera}</Text> : undefined
|
|
58
59
|
})))(TABS);
|
|
59
60
|
|
|
60
|
-
const addItem: TabControllerItemProps
|
|
61
|
+
const addItem: TabControllerItemProps = {
|
|
61
62
|
icon: Assets.icons.demo.add,
|
|
62
63
|
key: 'add',
|
|
63
64
|
ignore: true,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import _ from 'lodash';
|
|
2
2
|
import React, {Component} from 'react';
|
|
3
3
|
import {StyleSheet, ScrollView, ActivityIndicator} from 'react-native';
|
|
4
|
-
import {Assets, Colors, Spacings, View, Text, Button, Keyboard, TextField, TextFieldRef} from 'react-native-ui-lib';
|
|
4
|
+
import {Assets, Colors, Spacings, Typography, View, Text, Button, Keyboard, TextField, TextFieldRef} from 'react-native-ui-lib'; //eslint-disable-line
|
|
5
5
|
const {KeyboardAwareInsetsView} = Keyboard;
|
|
6
6
|
|
|
7
7
|
const priceFormatter = Intl.NumberFormat('en-US');
|
|
@@ -32,8 +32,8 @@ export default () => {
|
|
|
32
32
|
},
|
|
33
33
|
[yearsValue]);
|
|
34
34
|
|
|
35
|
-
const onChange = useCallback((value
|
|
36
|
-
setYearsValue(value
|
|
35
|
+
const onChange = useCallback((value) => {
|
|
36
|
+
setYearsValue(value);
|
|
37
37
|
}, []);
|
|
38
38
|
|
|
39
39
|
const onPickDaysPress = useCallback(() => {
|
|
@@ -83,7 +83,7 @@ export default class WizardScreen extends Component<{}, State> {
|
|
|
83
83
|
}
|
|
84
84
|
|
|
85
85
|
const activeIndex = prevActiveIndex + 1;
|
|
86
|
-
let completedStepIndex
|
|
86
|
+
let completedStepIndex = prevCompletedStepIndex;
|
|
87
87
|
if (!prevCompletedStepIndex || prevCompletedStepIndex < prevActiveIndex) {
|
|
88
88
|
completedStepIndex = prevActiveIndex;
|
|
89
89
|
}
|
|
@@ -150,11 +150,10 @@ export default class WizardScreen extends Component<{}, State> {
|
|
|
150
150
|
value={customerName}
|
|
151
151
|
validate={'required'}
|
|
152
152
|
validateOnChange
|
|
153
|
-
|
|
153
|
+
errorMessage="This is required"
|
|
154
154
|
onChangeText={this.onNameEntered}
|
|
155
155
|
/>
|
|
156
156
|
{this.renderPrevButton()}
|
|
157
|
-
{/* @ts-expect-error */}
|
|
158
157
|
{this.renderNextButton(_.isNil(customerName) || customerName.trim().length === 0)}
|
|
159
158
|
</View>
|
|
160
159
|
);
|
|
@@ -187,7 +186,7 @@ export default class WizardScreen extends Component<{}, State> {
|
|
|
187
186
|
getStepState(index: number) {
|
|
188
187
|
const {activeIndex, completedStepIndex} = this.state;
|
|
189
188
|
let state = Wizard.States.DISABLED;
|
|
190
|
-
if (completedStepIndex
|
|
189
|
+
if (completedStepIndex > index - 1) {
|
|
191
190
|
state = Wizard.States.COMPLETED;
|
|
192
191
|
} else if (activeIndex === index || completedStepIndex === index - 1) {
|
|
193
192
|
state = Wizard.States.ENABLED;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import React, {Component} from 'react';
|
|
2
2
|
import {StyleSheet, ScrollView} from 'react-native';
|
|
3
|
-
import {Colors, View, Text, Incubator, TouchableOpacity
|
|
3
|
+
import {Colors, View, Text, Incubator, TouchableOpacity} from 'react-native-ui-lib'; //eslint-disable-line
|
|
4
4
|
import _ from 'lodash';
|
|
5
5
|
|
|
6
6
|
const COLOR_OPTIONS: {[key: string]: string} = {
|
|
@@ -11,8 +11,8 @@ const COLOR_OPTIONS: {[key: string]: string} = {
|
|
|
11
11
|
};
|
|
12
12
|
|
|
13
13
|
export default class TextFieldScreen extends Component {
|
|
14
|
-
expandableInputRef = React.createRef
|
|
15
|
-
expandablePickerRef = React.createRef
|
|
14
|
+
expandableInputRef = React.createRef();
|
|
15
|
+
expandablePickerRef = React.createRef();
|
|
16
16
|
|
|
17
17
|
state = {
|
|
18
18
|
textFieldValueDraft: '',
|
|
@@ -24,16 +24,16 @@ export default class TextFieldScreen extends Component {
|
|
|
24
24
|
|
|
25
25
|
onDone = () => {
|
|
26
26
|
this.setState({textFieldValue: this.state.textFieldValueDraft});
|
|
27
|
-
this.expandableInputRef.current
|
|
27
|
+
this.expandableInputRef.current.closeExpandable();
|
|
28
28
|
};
|
|
29
29
|
onCancel = () => {
|
|
30
30
|
this.setState({textFieldValueDraft: this.state.textFieldValue});
|
|
31
|
-
this.expandableInputRef.current
|
|
31
|
+
this.expandableInputRef.current.closeExpandable();
|
|
32
32
|
};
|
|
33
33
|
|
|
34
34
|
onPickItem = ({customValue: color}: {customValue: string}) => {
|
|
35
35
|
this.setState({selectedColor: color});
|
|
36
|
-
this.expandablePickerRef.current
|
|
36
|
+
this.expandablePickerRef.current.closeExpandable();
|
|
37
37
|
};
|
|
38
38
|
|
|
39
39
|
renderInputModal = () => {
|
|
@@ -79,7 +79,6 @@ const IncubatorSliderScreen = () => {
|
|
|
79
79
|
</Text>
|
|
80
80
|
{renderValuesBox(sliderValue)}
|
|
81
81
|
<Incubator.Slider
|
|
82
|
-
// @ts-expect-error TODO: need to properly support SliderMethods type to use for ref
|
|
83
82
|
ref={slider}
|
|
84
83
|
onValueChange={onValueChange}
|
|
85
84
|
containerStyle={styles.container}
|
|
@@ -98,7 +97,6 @@ const IncubatorSliderScreen = () => {
|
|
|
98
97
|
<Text margin-10 text70BL $textDefault>
|
|
99
98
|
Disabled Slider
|
|
100
99
|
</Text>
|
|
101
|
-
{/* @ts-expect-error */}
|
|
102
100
|
<Incubator.Slider value={0.4} containerStyle={styles.container} disableRTL={disableRTL} disabled/>
|
|
103
101
|
</View>
|
|
104
102
|
);
|
|
@@ -112,7 +110,6 @@ const IncubatorSliderScreen = () => {
|
|
|
112
110
|
</Text>
|
|
113
111
|
{renderValuesBox(customSliderValue)}
|
|
114
112
|
<Incubator.Slider
|
|
115
|
-
// @ts-expect-error
|
|
116
113
|
ref={customSlider}
|
|
117
114
|
onValueChange={onCustomValueChange}
|
|
118
115
|
value={20}
|
|
@@ -140,7 +137,6 @@ const IncubatorSliderScreen = () => {
|
|
|
140
137
|
</Text>
|
|
141
138
|
{renderValuesBox(negativeSliderValue)}
|
|
142
139
|
<Incubator.Slider
|
|
143
|
-
// @ts-expect-error
|
|
144
140
|
ref={negativeSlider}
|
|
145
141
|
onValueChange={onNegativeValueChange}
|
|
146
142
|
value={-30}
|
|
@@ -163,7 +159,6 @@ const IncubatorSliderScreen = () => {
|
|
|
163
159
|
<View marginH-20>
|
|
164
160
|
{renderValuesBox(sliderMinValue, sliderMaxValue)}
|
|
165
161
|
<Incubator.Slider
|
|
166
|
-
// @ts-expect-error
|
|
167
162
|
ref={rangeSlider}
|
|
168
163
|
useRange
|
|
169
164
|
onRangeChange={onRangeChange}
|
|
@@ -6,7 +6,6 @@ import {renderMultipleSegmentOptions, renderBooleanOption, renderRadioGroup} fro
|
|
|
6
6
|
const {Toast} = Incubator;
|
|
7
7
|
|
|
8
8
|
const TOAST_ACTIONS = {
|
|
9
|
-
none: {},
|
|
10
9
|
label: {label: 'Undo', onPress: () => console.warn('undo')},
|
|
11
10
|
icon: {iconSource: Assets.icons.demo.plus, onPress: () => console.warn('add')}
|
|
12
11
|
};
|
|
@@ -25,9 +24,9 @@ export default class ToastsScreen extends Component {
|
|
|
25
24
|
toastPosition: 'bottom' as Incubator.ToastProps['position'],
|
|
26
25
|
isCustomContent: false,
|
|
27
26
|
showLoader: false,
|
|
28
|
-
selectedAction: '
|
|
27
|
+
selectedAction: '',
|
|
29
28
|
hasAttachment: false,
|
|
30
|
-
selectedPreset: '' as Incubator.ToastProps['preset']
|
|
29
|
+
selectedPreset: '' as Incubator.ToastProps['preset'],
|
|
31
30
|
isSwipeable: true
|
|
32
31
|
};
|
|
33
32
|
|
|
@@ -21,18 +21,11 @@ const IMAGES = [
|
|
|
21
21
|
'https://images.pexels.com/photos/3206153/pexels-photo-3206153.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500'
|
|
22
22
|
];
|
|
23
23
|
|
|
24
|
-
// @ts-expect-error
|
|
25
24
|
const GUTTER_SIZE = Spacings.page;
|
|
26
|
-
// @ts-expect-error
|
|
27
25
|
const COLUMN_SIZE = (Constants.screenWidth - 2 * Spacings.page - GUTTER_SIZE) / 2;
|
|
28
26
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
images?: ImageObject[];
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
class Pinterest extends Component<{}, State> {
|
|
35
|
-
constructor(props: any) {
|
|
27
|
+
class Pinterest extends Component {
|
|
28
|
+
constructor(props) {
|
|
36
29
|
super(props);
|
|
37
30
|
|
|
38
31
|
this.state = {};
|
|
@@ -53,11 +46,11 @@ class Pinterest extends Component<{}, State> {
|
|
|
53
46
|
}
|
|
54
47
|
|
|
55
48
|
loadImages() {
|
|
56
|
-
const images
|
|
49
|
+
const images = {};
|
|
57
50
|
|
|
58
51
|
_.map(IMAGES, (image, index) => {
|
|
59
52
|
Image.getSize(image,
|
|
60
|
-
(width
|
|
53
|
+
(width, height) => {
|
|
61
54
|
images[index] = {
|
|
62
55
|
uri: image,
|
|
63
56
|
width,
|
|
@@ -80,8 +73,7 @@ class Pinterest extends Component<{}, State> {
|
|
|
80
73
|
});
|
|
81
74
|
}
|
|
82
75
|
|
|
83
|
-
|
|
84
|
-
renderImage(image: ImageObject) {
|
|
76
|
+
renderImage(image) {
|
|
85
77
|
return (
|
|
86
78
|
<Card
|
|
87
79
|
key={image.uri}
|
|
@@ -106,7 +98,7 @@ class Pinterest extends Component<{}, State> {
|
|
|
106
98
|
);
|
|
107
99
|
}
|
|
108
100
|
|
|
109
|
-
renderColumn(columnIndex
|
|
101
|
+
renderColumn(columnIndex) {
|
|
110
102
|
const {images} = this.state;
|
|
111
103
|
return (
|
|
112
104
|
<View marginR-page={columnIndex === 0}>
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import React, {Component} from 'react';
|
|
2
2
|
import {ScrollView} from 'react-native';
|
|
3
|
-
import {Assets, View, Text, Icon, Colors, Image, Button, Carousel, Picker
|
|
3
|
+
import {Assets, View, Text, Icon, Colors, Image, Button, Carousel, Picker} from 'react-native-ui-lib';
|
|
4
4
|
import _ from 'lodash';
|
|
5
5
|
|
|
6
6
|
const colorOptions: {[key: string]: {name: string; color: string}} = {
|
|
@@ -76,27 +76,19 @@ class Product extends Component {
|
|
|
76
76
|
<Picker
|
|
77
77
|
migrate
|
|
78
78
|
value={selectedColor}
|
|
79
|
-
onChange={(value:
|
|
80
|
-
trailingAccessory={
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
borderRadius: 12
|
|
87
|
-
}}
|
|
88
|
-
/>
|
|
89
|
-
}
|
|
79
|
+
onChange={(value: string) => this.setState({selectedColor: value})}
|
|
80
|
+
trailingAccessory={<Icon {...{
|
|
81
|
+
width: 24,
|
|
82
|
+
height: 24,
|
|
83
|
+
backgroundColor: colorOptions[selectedColor].color,
|
|
84
|
+
borderRadius: 12
|
|
85
|
+
}} />}
|
|
90
86
|
>
|
|
91
87
|
{_.map(colorOptions, (colorOption, colorKey) => {
|
|
92
88
|
return <Picker.Item key={colorKey} value={colorKey} label={colorOption.name}/>;
|
|
93
89
|
})}
|
|
94
90
|
</Picker>
|
|
95
|
-
<Picker
|
|
96
|
-
migrate
|
|
97
|
-
value={selectedSize}
|
|
98
|
-
onChange={(value: PickerValue) => this.setState({selectedSize: value})}
|
|
99
|
-
>
|
|
91
|
+
<Picker migrate value={selectedSize} onChange={(value: string) => this.setState({selectedSize: value})}>
|
|
100
92
|
{_.map(sizeOptions, (sizeOption, sizeKey) => {
|
|
101
93
|
return <Picker.Item key={sizeKey} value={sizeKey} label={sizeOption.name}/>;
|
|
102
94
|
})}
|
|
@@ -90,7 +90,7 @@ class Twitter extends Component {
|
|
|
90
90
|
) : null}
|
|
91
91
|
<View row style={{justifyContent: 'space-between', marginVertical: 10}}>
|
|
92
92
|
{post.icons
|
|
93
|
-
? post.icons.map((icnSource: any, index
|
|
93
|
+
? post.icons.map((icnSource: any, index) => {
|
|
94
94
|
return (
|
|
95
95
|
<Button
|
|
96
96
|
key={index}
|