@momo-kits/foundation 0.92.6-rc.3 → 0.92.6-rc.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/Application/ModalScreen.tsx +3 -1
- package/Application/Navigation.ts +2 -2
- package/Application/StackScreen.tsx +1 -1
- package/Layout/FloatingButton.tsx +128 -0
- package/Layout/Screen.tsx +24 -68
- package/Layout/utils.ts +1 -16
- package/package.json +1 -1
- package/FloatingButton/FloatingButton.tsx +0 -154
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import React, {useContext, useEffect, useRef} from 'react';
|
|
2
2
|
import {
|
|
3
|
+
Dimensions,
|
|
3
4
|
KeyboardAvoidingView,
|
|
4
5
|
Platform,
|
|
5
6
|
Pressable,
|
|
@@ -10,7 +11,7 @@ import {
|
|
|
10
11
|
import {Modalize} from 'react-native-modalize';
|
|
11
12
|
import {SafeAreaView, useSafeAreaInsets} from 'react-native-safe-area-context';
|
|
12
13
|
|
|
13
|
-
import {ApplicationContext} from '
|
|
14
|
+
import {ApplicationContext} from './index';
|
|
14
15
|
import {Radius, Spacing, Styles} from '../Consts';
|
|
15
16
|
import {Icon} from '../Icon';
|
|
16
17
|
import {Text} from '../Text';
|
|
@@ -207,6 +208,7 @@ const styles = StyleSheet.create({
|
|
|
207
208
|
backgroundColor: 'white',
|
|
208
209
|
borderTopRightRadius: 16,
|
|
209
210
|
borderTopLeftRadius: 16,
|
|
211
|
+
maxHeight: Dimensions.get('window').height * 0.75,
|
|
210
212
|
},
|
|
211
213
|
header: {
|
|
212
214
|
height: 50,
|
|
@@ -6,8 +6,8 @@ import {getOptions} from './utils';
|
|
|
6
6
|
import {HeaderToolkitAction} from './Components';
|
|
7
7
|
|
|
8
8
|
class Navigation {
|
|
9
|
-
|
|
10
|
-
|
|
9
|
+
instance: NavigationProp<any>;
|
|
10
|
+
readonly theme: Theme;
|
|
11
11
|
|
|
12
12
|
constructor(instance: any, theme: Theme) {
|
|
13
13
|
this.instance = instance;
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import {default as React, useContext, useEffect, useRef, useState} from 'react';
|
|
2
|
+
import {
|
|
3
|
+
Animated,
|
|
4
|
+
LayoutChangeEvent,
|
|
5
|
+
StyleSheet,
|
|
6
|
+
TouchableOpacity,
|
|
7
|
+
} from 'react-native';
|
|
8
|
+
import {ApplicationContext} from '../Application';
|
|
9
|
+
import {Icon} from '../Icon';
|
|
10
|
+
import {Text} from '../Text';
|
|
11
|
+
|
|
12
|
+
export interface FloatingButtonProps {
|
|
13
|
+
label?: string;
|
|
14
|
+
onPress?: () => void;
|
|
15
|
+
position?: 'center' | 'right';
|
|
16
|
+
icon?: string;
|
|
17
|
+
iconColor?: string;
|
|
18
|
+
size?: 'small' | 'large';
|
|
19
|
+
animatedValue?: Animated.Value;
|
|
20
|
+
bottom?: number;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export const FloatingButton: React.FC<FloatingButtonProps> = ({
|
|
24
|
+
label = '',
|
|
25
|
+
onPress = () => {},
|
|
26
|
+
position = 'right',
|
|
27
|
+
icon = '',
|
|
28
|
+
iconColor = '',
|
|
29
|
+
size = 'small',
|
|
30
|
+
animatedValue,
|
|
31
|
+
bottom = 12,
|
|
32
|
+
}: FloatingButtonProps) => {
|
|
33
|
+
const {theme} = useContext(ApplicationContext);
|
|
34
|
+
const maxWidth = useRef(0);
|
|
35
|
+
const minWidth = size == 'small' ? 36 : 48;
|
|
36
|
+
const [widthAnimated, setWidthAnimated] = useState<Animated.Value>();
|
|
37
|
+
const lastOffset = useRef(0);
|
|
38
|
+
const debounce = useRef<any>();
|
|
39
|
+
const [showText, setShowText] = React.useState(true);
|
|
40
|
+
|
|
41
|
+
useEffect(() => {
|
|
42
|
+
if (!label) return;
|
|
43
|
+
|
|
44
|
+
const listener = animatedValue?.addListener(({value}) => {
|
|
45
|
+
clearTimeout(debounce.current);
|
|
46
|
+
debounce.current = setTimeout(() => {
|
|
47
|
+
const down = value > lastOffset.current;
|
|
48
|
+
lastOffset.current = value;
|
|
49
|
+
if (down) {
|
|
50
|
+
Animated.timing(widthAnimated!, {
|
|
51
|
+
toValue: minWidth,
|
|
52
|
+
duration: 300,
|
|
53
|
+
useNativeDriver: false,
|
|
54
|
+
}).start(() => setShowText(false));
|
|
55
|
+
} else {
|
|
56
|
+
Animated.timing(widthAnimated!, {
|
|
57
|
+
toValue: maxWidth.current,
|
|
58
|
+
duration: 300,
|
|
59
|
+
useNativeDriver: false,
|
|
60
|
+
}).start(() => setShowText(true));
|
|
61
|
+
}
|
|
62
|
+
}, 500);
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
return () => {
|
|
66
|
+
if (listener != null) {
|
|
67
|
+
animatedValue?.removeListener(listener);
|
|
68
|
+
}
|
|
69
|
+
};
|
|
70
|
+
}, [label, widthAnimated]);
|
|
71
|
+
|
|
72
|
+
const handleLayout = (event: LayoutChangeEvent) => {
|
|
73
|
+
const layout = event.nativeEvent.layout;
|
|
74
|
+
if (widthAnimated) return;
|
|
75
|
+
maxWidth.current = layout.width;
|
|
76
|
+
setWidthAnimated(new Animated.Value(layout.width));
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
return (
|
|
80
|
+
<Animated.View
|
|
81
|
+
onLayout={handleLayout}
|
|
82
|
+
style={[
|
|
83
|
+
styles.container,
|
|
84
|
+
{
|
|
85
|
+
right: position === 'right' ? 12 : undefined,
|
|
86
|
+
alignSelf: position === 'center' ? 'center' : 'flex-end',
|
|
87
|
+
width: widthAnimated,
|
|
88
|
+
height: size == 'small' ? 36 : 48,
|
|
89
|
+
backgroundColor: theme.colors.primary,
|
|
90
|
+
bottom,
|
|
91
|
+
},
|
|
92
|
+
]}>
|
|
93
|
+
<TouchableOpacity
|
|
94
|
+
style={{flexDirection: 'row', alignItems: 'center'}}
|
|
95
|
+
onPress={onPress}>
|
|
96
|
+
<Icon
|
|
97
|
+
source={icon}
|
|
98
|
+
size={size === 'small' ? 12 : 24}
|
|
99
|
+
color={iconColor}
|
|
100
|
+
/>
|
|
101
|
+
{showText && !!label && (
|
|
102
|
+
<Text
|
|
103
|
+
style={styles.label}
|
|
104
|
+
color="white"
|
|
105
|
+
typography="action_default_bold">
|
|
106
|
+
{label}
|
|
107
|
+
</Text>
|
|
108
|
+
)}
|
|
109
|
+
</TouchableOpacity>
|
|
110
|
+
</Animated.View>
|
|
111
|
+
);
|
|
112
|
+
};
|
|
113
|
+
|
|
114
|
+
const styles = StyleSheet.create({
|
|
115
|
+
container: {
|
|
116
|
+
flexDirection: 'row',
|
|
117
|
+
alignContent: 'center',
|
|
118
|
+
alignItems: 'center',
|
|
119
|
+
position: 'absolute',
|
|
120
|
+
borderRadius: 100,
|
|
121
|
+
paddingHorizontal: 12,
|
|
122
|
+
flexWrap: 'wrap',
|
|
123
|
+
alignSelf: 'flex-end',
|
|
124
|
+
},
|
|
125
|
+
label: {
|
|
126
|
+
marginLeft: 8,
|
|
127
|
+
},
|
|
128
|
+
});
|
package/Layout/Screen.tsx
CHANGED
|
@@ -3,16 +3,13 @@ import React, {
|
|
|
3
3
|
forwardRef,
|
|
4
4
|
Fragment,
|
|
5
5
|
ReactNode,
|
|
6
|
-
useCallback,
|
|
7
6
|
useContext,
|
|
8
7
|
useEffect,
|
|
9
8
|
useRef,
|
|
10
9
|
} from 'react';
|
|
11
10
|
import {
|
|
12
11
|
Animated,
|
|
13
|
-
Easing,
|
|
14
12
|
KeyboardAvoidingView,
|
|
15
|
-
LayoutChangeEvent,
|
|
16
13
|
NativeScrollEvent,
|
|
17
14
|
NativeSyntheticEvent,
|
|
18
15
|
Platform,
|
|
@@ -29,15 +26,11 @@ import {
|
|
|
29
26
|
import Navigation from '../Application/Navigation';
|
|
30
27
|
import {AnimatedHeader, NavigationOptions} from '../Application/types';
|
|
31
28
|
import {Colors, Spacing, Styles} from '../Consts';
|
|
32
|
-
import {
|
|
33
|
-
FloatingButton,
|
|
34
|
-
FloatingButtonProps,
|
|
35
|
-
} from '../FloatingButton/FloatingButton';
|
|
29
|
+
import {FloatingButton, FloatingButtonProps} from './FloatingButton';
|
|
36
30
|
import {Image} from '../Image';
|
|
37
31
|
import {Card, Section, validateChildren} from './index';
|
|
38
32
|
import styles from './styles';
|
|
39
33
|
import {HeaderType} from './types';
|
|
40
|
-
import {debounce} from './utils';
|
|
41
34
|
|
|
42
35
|
export interface ScreenProps extends ViewProps {
|
|
43
36
|
children: React.ReactNode;
|
|
@@ -94,7 +87,12 @@ export interface ScreenProps extends ViewProps {
|
|
|
94
87
|
/**
|
|
95
88
|
* Optional. Props for the floating action button.
|
|
96
89
|
*/
|
|
97
|
-
floatingButtonProps?: Omit<FloatingButtonProps, 'animatedValue'>;
|
|
90
|
+
floatingButtonProps?: Omit<FloatingButtonProps, 'animatedValue' | 'bottom'>;
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Optional. If `true`, the screen content is using grid layout by span.
|
|
94
|
+
*/
|
|
95
|
+
useGridLayout?: boolean;
|
|
98
96
|
}
|
|
99
97
|
|
|
100
98
|
const Screen = forwardRef(
|
|
@@ -112,24 +110,22 @@ const Screen = forwardRef(
|
|
|
112
110
|
backgroundColor,
|
|
113
111
|
headerType = 'default',
|
|
114
112
|
floatingButtonProps,
|
|
113
|
+
useGridLayout = true,
|
|
115
114
|
}: ScreenProps,
|
|
116
115
|
ref,
|
|
117
116
|
) => {
|
|
118
117
|
const animatedValue = useRef<Animated.Value | undefined>(undefined);
|
|
119
|
-
const lastScrollPosition = useRef(0);
|
|
120
|
-
const animatedFABValue = useRef(new Animated.Value(0)).current;
|
|
121
118
|
const {theme} = useContext(ApplicationContext);
|
|
122
119
|
const insets = useSafeAreaInsets();
|
|
123
120
|
const heightHeader = useHeaderHeight();
|
|
124
|
-
const layoutHeight = useRef(0);
|
|
125
|
-
const contentHeight = useRef(0);
|
|
126
121
|
const currentTint = useRef(Colors.black_01);
|
|
122
|
+
const isTab = navigation?.instance?.getState?.()?.type == 'tab';
|
|
123
|
+
|
|
127
124
|
let styleAnimatedHeader: NavigationOptions;
|
|
128
125
|
let handleScroll;
|
|
129
126
|
let headerBackground: string | undefined = undefined;
|
|
130
127
|
let Component: any = View;
|
|
131
128
|
let keyboardVerticalOffset = heightHeader - 20;
|
|
132
|
-
animatedValue.current = undefined;
|
|
133
129
|
|
|
134
130
|
if (headerType == 'extended' || animatedHeader) {
|
|
135
131
|
keyboardVerticalOffset = -20;
|
|
@@ -258,46 +254,12 @@ const Screen = forwardRef(
|
|
|
258
254
|
});
|
|
259
255
|
}
|
|
260
256
|
}
|
|
261
|
-
if (floatingButtonProps) {
|
|
262
|
-
const currentScrollPosition = e.nativeEvent.contentOffset.y;
|
|
263
|
-
const isScrollingDown =
|
|
264
|
-
currentScrollPosition > lastScrollPosition.current;
|
|
265
|
-
scrollViewProps?.onScroll?.(e);
|
|
266
|
-
|
|
267
|
-
if (currentScrollPosition < 0) {
|
|
268
|
-
return;
|
|
269
|
-
}
|
|
270
|
-
const isAtBottom =
|
|
271
|
-
currentScrollPosition +
|
|
272
|
-
layoutHeight.current +
|
|
273
|
-
Math.min(insets.bottom, 21) +
|
|
274
|
-
Spacing.S >=
|
|
275
|
-
contentHeight.current;
|
|
276
|
-
if (isAtBottom) {
|
|
277
|
-
return;
|
|
278
|
-
}
|
|
279
|
-
animateFAB(isScrollingDown);
|
|
280
|
-
|
|
281
|
-
lastScrollPosition.current = currentScrollPosition;
|
|
282
|
-
}
|
|
283
257
|
},
|
|
284
258
|
},
|
|
285
259
|
);
|
|
286
260
|
}
|
|
287
261
|
}
|
|
288
262
|
|
|
289
|
-
const animateFAB = useCallback(
|
|
290
|
-
debounce((isScrollingDown: boolean) => {
|
|
291
|
-
Animated.timing(animatedFABValue, {
|
|
292
|
-
toValue: isScrollingDown ? 1 : 0,
|
|
293
|
-
duration: 100,
|
|
294
|
-
useNativeDriver: false,
|
|
295
|
-
easing: Easing.linear,
|
|
296
|
-
}).start();
|
|
297
|
-
}, 300),
|
|
298
|
-
[],
|
|
299
|
-
);
|
|
300
|
-
|
|
301
263
|
/**
|
|
302
264
|
* render top navigation banner
|
|
303
265
|
*/
|
|
@@ -351,6 +313,7 @@ const Screen = forwardRef(
|
|
|
351
313
|
);
|
|
352
314
|
}
|
|
353
315
|
};
|
|
316
|
+
|
|
354
317
|
return (
|
|
355
318
|
<View style={[Styles.flex, {backgroundColor}]}>
|
|
356
319
|
{!!headerBackground && (
|
|
@@ -373,39 +336,32 @@ const Screen = forwardRef(
|
|
|
373
336
|
android: undefined,
|
|
374
337
|
})}>
|
|
375
338
|
{Header}
|
|
339
|
+
|
|
376
340
|
<Component
|
|
377
341
|
{...scrollViewProps}
|
|
378
342
|
ref={ref}
|
|
379
343
|
showsVerticalScrollIndicator={false}
|
|
380
344
|
onScroll={handleScroll}
|
|
381
|
-
onContentSizeChange={(_: number, height: number) => {
|
|
382
|
-
contentHeight.current = height;
|
|
383
|
-
}}
|
|
384
|
-
onLayout={(event: LayoutChangeEvent) => {
|
|
385
|
-
layoutHeight.current = event.nativeEvent.layout.height;
|
|
386
|
-
}}
|
|
387
345
|
style={Styles.flex}>
|
|
388
346
|
<View
|
|
389
347
|
style={[styles.screenBanner, {maxHeight: 210 + layoutOffset}]}>
|
|
390
348
|
{renderHeader()}
|
|
391
349
|
</View>
|
|
392
|
-
{renderContent(children)}
|
|
350
|
+
{useGridLayout ? renderContent(children) : children}
|
|
393
351
|
</Component>
|
|
394
|
-
|
|
395
|
-
|
|
352
|
+
|
|
353
|
+
{floatingButtonProps && (
|
|
354
|
+
<View>
|
|
396
355
|
<FloatingButton
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
iconColor={floatingButtonProps?.iconColor}
|
|
403
|
-
isBottomTab={floatingButtonProps?.isBottomTab}
|
|
404
|
-
animatedValue={animatedFABValue}
|
|
405
|
-
isFooter={!!Footer}
|
|
356
|
+
{...floatingButtonProps}
|
|
357
|
+
animatedValue={animatedValue.current}
|
|
358
|
+
bottom={
|
|
359
|
+
Footer || isTab ? 12 : Math.min(insets.bottom, 21) + Spacing.S
|
|
360
|
+
}
|
|
406
361
|
/>
|
|
407
|
-
|
|
408
|
-
|
|
362
|
+
</View>
|
|
363
|
+
)}
|
|
364
|
+
|
|
409
365
|
{Footer && (
|
|
410
366
|
<View
|
|
411
367
|
style={[
|
package/Layout/utils.ts
CHANGED
|
@@ -51,20 +51,5 @@ const useGridSystem = () => {
|
|
|
51
51
|
|
|
52
52
|
return {numberOfColumns};
|
|
53
53
|
};
|
|
54
|
-
function debounce<T extends (...args: any[]) => void>(
|
|
55
|
-
func: T,
|
|
56
|
-
wait: number,
|
|
57
|
-
): (...args: Parameters<T>) => void {
|
|
58
|
-
let timeout: NodeJS.Timeout | null = null;
|
|
59
54
|
|
|
60
|
-
|
|
61
|
-
if (timeout !== null) {
|
|
62
|
-
clearTimeout(timeout);
|
|
63
|
-
}
|
|
64
|
-
timeout = setTimeout(() => {
|
|
65
|
-
func(...args);
|
|
66
|
-
}, wait);
|
|
67
|
-
};
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
export {debounce, useGridSystem, validateChildren};
|
|
55
|
+
export {useGridSystem, validateChildren};
|
package/package.json
CHANGED
|
@@ -1,154 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
default as React,
|
|
3
|
-
useCallback,
|
|
4
|
-
useContext,
|
|
5
|
-
useEffect,
|
|
6
|
-
useRef,
|
|
7
|
-
useState,
|
|
8
|
-
} from 'react';
|
|
9
|
-
import {
|
|
10
|
-
Animated,
|
|
11
|
-
LayoutChangeEvent,
|
|
12
|
-
StyleSheet,
|
|
13
|
-
TouchableOpacity,
|
|
14
|
-
} from 'react-native';
|
|
15
|
-
import {useSafeAreaInsets} from 'react-native-safe-area-context';
|
|
16
|
-
import {ApplicationContext} from '../Application';
|
|
17
|
-
import {Spacing} from '../Consts';
|
|
18
|
-
import {Icon} from '../Icon';
|
|
19
|
-
import {Text} from '../Text';
|
|
20
|
-
|
|
21
|
-
export interface FloatingButtonProps {
|
|
22
|
-
label?: string;
|
|
23
|
-
onPress?: () => void;
|
|
24
|
-
position?: 'center' | 'right';
|
|
25
|
-
icon?: string;
|
|
26
|
-
iconColor?: string;
|
|
27
|
-
size?: 'small' | 'large';
|
|
28
|
-
animatedValue: Animated.Value;
|
|
29
|
-
isBottomTab?: boolean;
|
|
30
|
-
isFooter?: boolean;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
export const FloatingButton: React.FC<FloatingButtonProps> = ({
|
|
34
|
-
label = '',
|
|
35
|
-
onPress = () => {},
|
|
36
|
-
position = 'right',
|
|
37
|
-
icon = '',
|
|
38
|
-
iconColor = '',
|
|
39
|
-
size = 'small',
|
|
40
|
-
animatedValue,
|
|
41
|
-
isBottomTab = false,
|
|
42
|
-
isFooter = false,
|
|
43
|
-
}: FloatingButtonProps) => {
|
|
44
|
-
const {theme} = useContext(ApplicationContext);
|
|
45
|
-
const insets = useSafeAreaInsets();
|
|
46
|
-
const [isExpanded, setIsExpanded] = React.useState(true);
|
|
47
|
-
const [init, setInit] = useState(true);
|
|
48
|
-
const width = size == 'small' ? 36 : 48;
|
|
49
|
-
const widthAnim = useRef(new Animated.Value(width)).current;
|
|
50
|
-
const [textWidth, setTextWidth] = useState(0);
|
|
51
|
-
|
|
52
|
-
useEffect(() => {
|
|
53
|
-
if (!label) return;
|
|
54
|
-
|
|
55
|
-
const listener = animatedValue.addListener(({value}) => {
|
|
56
|
-
if (value === 1) {
|
|
57
|
-
setIsExpanded(false);
|
|
58
|
-
collapseFab();
|
|
59
|
-
} else {
|
|
60
|
-
setIsExpanded(true);
|
|
61
|
-
expandFab();
|
|
62
|
-
}
|
|
63
|
-
});
|
|
64
|
-
|
|
65
|
-
return () => {
|
|
66
|
-
animatedValue?.removeListener(listener);
|
|
67
|
-
};
|
|
68
|
-
}, [textWidth, label, init]);
|
|
69
|
-
|
|
70
|
-
// If the text width is greater than 0 and it's not initialized then expand the fab
|
|
71
|
-
useEffect(() => {
|
|
72
|
-
if (textWidth > 0 && !init) {
|
|
73
|
-
expandFab();
|
|
74
|
-
}
|
|
75
|
-
}, [textWidth]);
|
|
76
|
-
|
|
77
|
-
const handleLayout = (event: LayoutChangeEvent) => {
|
|
78
|
-
const {width} = event.nativeEvent.layout;
|
|
79
|
-
|
|
80
|
-
if (init) {
|
|
81
|
-
setTextWidth(width);
|
|
82
|
-
setInit(false);
|
|
83
|
-
}
|
|
84
|
-
};
|
|
85
|
-
|
|
86
|
-
const expandFab = useCallback(() => {
|
|
87
|
-
Animated.timing(widthAnim, {
|
|
88
|
-
toValue: width + textWidth + 8,
|
|
89
|
-
duration: 200,
|
|
90
|
-
useNativeDriver: false,
|
|
91
|
-
}).start();
|
|
92
|
-
}, [textWidth, widthAnim]);
|
|
93
|
-
|
|
94
|
-
const collapseFab = useCallback(() => {
|
|
95
|
-
Animated.timing(widthAnim, {
|
|
96
|
-
toValue: width,
|
|
97
|
-
duration: 200,
|
|
98
|
-
useNativeDriver: false,
|
|
99
|
-
}).start();
|
|
100
|
-
}, [widthAnim]);
|
|
101
|
-
|
|
102
|
-
return (
|
|
103
|
-
<Animated.View
|
|
104
|
-
style={[
|
|
105
|
-
styles.container,
|
|
106
|
-
{
|
|
107
|
-
right: position === 'right' ? 12 : undefined,
|
|
108
|
-
alignSelf: position === 'center' ? 'center' : 'flex-end',
|
|
109
|
-
width: init ? undefined : widthAnim,
|
|
110
|
-
height: width,
|
|
111
|
-
backgroundColor: theme.colors.primary,
|
|
112
|
-
bottom:
|
|
113
|
-
isFooter || isBottomTab
|
|
114
|
-
? 12
|
|
115
|
-
: Math.min(insets.bottom, 21) + Spacing.S,
|
|
116
|
-
},
|
|
117
|
-
]}>
|
|
118
|
-
<TouchableOpacity
|
|
119
|
-
style={{flexDirection: 'row', alignItems: 'center'}}
|
|
120
|
-
onPress={onPress}>
|
|
121
|
-
<Icon
|
|
122
|
-
source={icon}
|
|
123
|
-
size={size === 'small' ? 12 : 24}
|
|
124
|
-
color={iconColor}
|
|
125
|
-
/>
|
|
126
|
-
{isExpanded && !!label && (
|
|
127
|
-
<Text
|
|
128
|
-
onLayout={handleLayout}
|
|
129
|
-
style={styles.label}
|
|
130
|
-
color="white"
|
|
131
|
-
typography="action_default_bold">
|
|
132
|
-
Hello
|
|
133
|
-
</Text>
|
|
134
|
-
)}
|
|
135
|
-
</TouchableOpacity>
|
|
136
|
-
</Animated.View>
|
|
137
|
-
);
|
|
138
|
-
};
|
|
139
|
-
|
|
140
|
-
const styles = StyleSheet.create({
|
|
141
|
-
container: {
|
|
142
|
-
flexDirection: 'row',
|
|
143
|
-
alignContent: 'center',
|
|
144
|
-
alignItems: 'center',
|
|
145
|
-
position: 'absolute',
|
|
146
|
-
borderRadius: 100,
|
|
147
|
-
paddingHorizontal: 12,
|
|
148
|
-
flexWrap: 'wrap',
|
|
149
|
-
alignSelf: 'flex-end',
|
|
150
|
-
},
|
|
151
|
-
label: {
|
|
152
|
-
marginLeft: 8,
|
|
153
|
-
},
|
|
154
|
-
});
|