@momo-kits/foundation 0.92.5 → 0.92.6-beta.11
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/types.ts +1 -1
- package/FloatingButton/FloatingButton.tsx +154 -0
- package/Icon/types.ts +2 -1
- package/Input/Input.tsx +26 -6
- package/Input/InputDropDown.tsx +10 -5
- package/Input/InputMoney.tsx +13 -4
- package/Input/InputOTP.tsx +14 -6
- package/Input/InputSearch.tsx +19 -4
- package/Input/InputTextArea.tsx +26 -6
- package/Input/common.tsx +27 -13
- package/Input/index.tsx +19 -5
- package/Layout/Screen.tsx +91 -19
- package/Layout/styles.ts +11 -7
- package/Layout/utils.ts +17 -2
- package/Popup/PopupNotify.tsx +30 -30
- package/Popup/types.ts +0 -6
- package/package.json +3 -3
package/Application/types.ts
CHANGED
|
@@ -120,7 +120,7 @@ export interface BottomSheetParams extends ScreenParams {
|
|
|
120
120
|
[key: string]: any;
|
|
121
121
|
onDismiss?: () => void;
|
|
122
122
|
footerComponent?: React.ReactNode;
|
|
123
|
-
flatListProps
|
|
123
|
+
flatListProps?: FlatListProps<any>;
|
|
124
124
|
}
|
|
125
125
|
|
|
126
126
|
export type NavigationButtonProps = {
|
|
@@ -0,0 +1,154 @@
|
|
|
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
|
+
});
|
package/Icon/types.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import {ImageStyle} from 'react-native-fast-image';
|
|
2
|
+
import {StyleProp} from "react-native";
|
|
2
3
|
|
|
3
4
|
export type IconProps = {
|
|
4
5
|
/**
|
|
@@ -23,5 +24,5 @@ export type IconProps = {
|
|
|
23
24
|
* Optional. Used to apply custom styling to the Icon component.
|
|
24
25
|
* Accepts an object of style properties.
|
|
25
26
|
*/
|
|
26
|
-
style?: ImageStyle
|
|
27
|
+
style?: StyleProp<ImageStyle>;
|
|
27
28
|
};
|
package/Input/Input.tsx
CHANGED
|
@@ -1,4 +1,10 @@
|
|
|
1
|
-
import React, {
|
|
1
|
+
import React, {
|
|
2
|
+
forwardRef,
|
|
3
|
+
useContext,
|
|
4
|
+
useImperativeHandle,
|
|
5
|
+
useRef,
|
|
6
|
+
useState,
|
|
7
|
+
} from 'react';
|
|
2
8
|
import {
|
|
3
9
|
NativeSyntheticEvent,
|
|
4
10
|
Platform,
|
|
@@ -8,12 +14,12 @@ import {
|
|
|
8
14
|
View,
|
|
9
15
|
} from 'react-native';
|
|
10
16
|
import {ApplicationContext, ComponentContext} from '../Application';
|
|
11
|
-
import
|
|
17
|
+
import {Icon} from '../Icon';
|
|
18
|
+
import {Loader} from '../Loader';
|
|
12
19
|
import {ErrorView, FloatingView, getBorderColor, getSizeStyle} from './common';
|
|
13
20
|
import {InputProps} from './index';
|
|
14
|
-
import
|
|
21
|
+
import styles from './styles';
|
|
15
22
|
import {checkTyping} from './utils';
|
|
16
|
-
import {Loader} from '../Loader';
|
|
17
23
|
|
|
18
24
|
const Input = forwardRef(
|
|
19
25
|
(
|
|
@@ -42,6 +48,7 @@ const Input = forwardRef(
|
|
|
42
48
|
keyboardType,
|
|
43
49
|
style,
|
|
44
50
|
params,
|
|
51
|
+
hintText,
|
|
45
52
|
accessibilityLabel,
|
|
46
53
|
...props
|
|
47
54
|
}: InputProps,
|
|
@@ -51,7 +58,7 @@ const Input = forwardRef(
|
|
|
51
58
|
const [focused, setFocused] = useState(false);
|
|
52
59
|
const [haveValue, setHaveValue] = useState(!!value || !!props.defaultValue);
|
|
53
60
|
const [secureTextInput, setSecureTextInput] = useState(secureTextEntry);
|
|
54
|
-
const inputRef =
|
|
61
|
+
const inputRef = useRef<TextInput | null>(null);
|
|
55
62
|
|
|
56
63
|
const onClearText = () => {
|
|
57
64
|
inputRef?.current?.clear();
|
|
@@ -73,6 +80,15 @@ const Input = forwardRef(
|
|
|
73
80
|
onBlur?.(e);
|
|
74
81
|
};
|
|
75
82
|
|
|
83
|
+
useImperativeHandle(ref, () => {
|
|
84
|
+
return {
|
|
85
|
+
clear: onClearText,
|
|
86
|
+
focus: () => inputRef.current?.focus(),
|
|
87
|
+
blur: () => inputRef.current?.blur(),
|
|
88
|
+
setText: (text: string) => _onChangeText(text),
|
|
89
|
+
};
|
|
90
|
+
});
|
|
91
|
+
|
|
76
92
|
const renderIcon = (color: string | undefined) => {
|
|
77
93
|
if (loading) {
|
|
78
94
|
return <Loader type={'spinner'} color={color} style={styles.icon} />;
|
|
@@ -217,7 +233,11 @@ const Input = forwardRef(
|
|
|
217
233
|
}}>
|
|
218
234
|
<View style={[style, styles.wrapper]}>
|
|
219
235
|
{renderInputView()}
|
|
220
|
-
<ErrorView
|
|
236
|
+
<ErrorView
|
|
237
|
+
errorMessage={errorMessage}
|
|
238
|
+
errorSpacing={errorSpacing}
|
|
239
|
+
hintText={hintText}
|
|
240
|
+
/>
|
|
221
241
|
</View>
|
|
222
242
|
</ComponentContext.Provider>
|
|
223
243
|
);
|
package/Input/InputDropDown.tsx
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import React, {useContext} from 'react';
|
|
2
2
|
import {TextInput, TouchableOpacity, View} from 'react-native';
|
|
3
3
|
import {ApplicationContext, ComponentContext} from '../Application';
|
|
4
|
-
import
|
|
5
|
-
import {ErrorView, FloatingView, getBorderColor, getSizeStyle} from './common';
|
|
6
|
-
import {InputDropDownProps} from './index';
|
|
4
|
+
import {Styles} from '../Consts';
|
|
7
5
|
import {Icon} from '../Icon';
|
|
8
6
|
import {Loader} from '../Loader';
|
|
9
|
-
import {
|
|
7
|
+
import {ErrorView, FloatingView, getBorderColor, getSizeStyle} from './common';
|
|
8
|
+
import {InputDropDownProps} from './index';
|
|
9
|
+
import styles from './styles';
|
|
10
10
|
|
|
11
11
|
const InputDropDown = ({
|
|
12
12
|
value,
|
|
@@ -28,6 +28,7 @@ const InputDropDown = ({
|
|
|
28
28
|
style,
|
|
29
29
|
params,
|
|
30
30
|
accessibilityLabel,
|
|
31
|
+
hintText,
|
|
31
32
|
...props
|
|
32
33
|
}: InputDropDownProps) => {
|
|
33
34
|
const {theme} = useContext(ApplicationContext);
|
|
@@ -118,7 +119,11 @@ const InputDropDown = ({
|
|
|
118
119
|
onPress={onPress}
|
|
119
120
|
style={[style, full && styles.wrapper]}>
|
|
120
121
|
{renderInputView()}
|
|
121
|
-
<ErrorView
|
|
122
|
+
<ErrorView
|
|
123
|
+
errorMessage={errorMessage}
|
|
124
|
+
errorSpacing={errorSpacing}
|
|
125
|
+
hintText={hintText}
|
|
126
|
+
/>
|
|
122
127
|
</TouchableOpacity>
|
|
123
128
|
</ComponentContext.Provider>
|
|
124
129
|
);
|
package/Input/InputMoney.tsx
CHANGED
|
@@ -13,10 +13,10 @@ import {
|
|
|
13
13
|
View,
|
|
14
14
|
} from 'react-native';
|
|
15
15
|
import {ApplicationContext, ComponentContext} from '../Application';
|
|
16
|
-
import
|
|
16
|
+
import {Icon} from '../Icon';
|
|
17
17
|
import {ErrorView, FloatingView, getBorderColor, getSizeStyle} from './common';
|
|
18
18
|
import {InputMoneyProps} from './index';
|
|
19
|
-
import
|
|
19
|
+
import styles from './styles';
|
|
20
20
|
import {formatMoneyToNumber, formatNumberToMoney} from './utils';
|
|
21
21
|
|
|
22
22
|
const InputMoney = forwardRef(
|
|
@@ -39,13 +39,14 @@ const InputMoney = forwardRef(
|
|
|
39
39
|
params,
|
|
40
40
|
defaultValue = '',
|
|
41
41
|
accessibilityLabel,
|
|
42
|
+
hintText,
|
|
42
43
|
...props
|
|
43
44
|
}: InputMoneyProps,
|
|
44
45
|
ref,
|
|
45
46
|
) => {
|
|
46
47
|
const {theme} = useContext(ApplicationContext);
|
|
47
48
|
const [focused, setFocused] = useState(false);
|
|
48
|
-
const inputRef =
|
|
49
|
+
const inputRef = useRef<TextInput>(null);
|
|
49
50
|
|
|
50
51
|
const validateText = (text: string) => {
|
|
51
52
|
const valueFormat = formatMoneyToNumber(text, 'đ');
|
|
@@ -72,6 +73,10 @@ const InputMoney = forwardRef(
|
|
|
72
73
|
|
|
73
74
|
useImperativeHandle(ref, () => {
|
|
74
75
|
return {
|
|
76
|
+
clear: onClearText,
|
|
77
|
+
focus: () => inputRef.current?.focus(),
|
|
78
|
+
blur: () => inputRef.current?.blur(),
|
|
79
|
+
changeText: (text: string) => _onChangeText(text),
|
|
75
80
|
setText: _onChangeText,
|
|
76
81
|
};
|
|
77
82
|
});
|
|
@@ -177,7 +182,11 @@ const InputMoney = forwardRef(
|
|
|
177
182
|
}}>
|
|
178
183
|
<View style={[style, styles.wrapper]}>
|
|
179
184
|
{renderInputView()}
|
|
180
|
-
<ErrorView
|
|
185
|
+
<ErrorView
|
|
186
|
+
errorMessage={errorMessage}
|
|
187
|
+
errorSpacing={errorSpacing}
|
|
188
|
+
hintText={hintText}
|
|
189
|
+
/>
|
|
181
190
|
</View>
|
|
182
191
|
</ComponentContext.Provider>
|
|
183
192
|
);
|
package/Input/InputOTP.tsx
CHANGED
|
@@ -15,12 +15,12 @@ import {
|
|
|
15
15
|
TouchableOpacity,
|
|
16
16
|
View,
|
|
17
17
|
} from 'react-native';
|
|
18
|
-
import {CaretProps, InputOTPProps} from './index';
|
|
19
|
-
import {scaleSize, Text} from '../Text';
|
|
20
|
-
import styles from './styles';
|
|
21
|
-
import {ErrorView, getBorderColor} from './common';
|
|
22
18
|
import {ApplicationContext, ComponentContext} from '../Application';
|
|
23
19
|
import {Spacing} from '../Consts';
|
|
20
|
+
import {scaleSize, Text} from '../Text';
|
|
21
|
+
import {ErrorView, getBorderColor} from './common';
|
|
22
|
+
import {CaretProps, InputOTPProps} from './index';
|
|
23
|
+
import styles from './styles';
|
|
24
24
|
|
|
25
25
|
const OTPCaret: FC<CaretProps> = ({index, length}) => {
|
|
26
26
|
const DURATION = 300;
|
|
@@ -81,6 +81,7 @@ const InputOTP = forwardRef(
|
|
|
81
81
|
params,
|
|
82
82
|
style,
|
|
83
83
|
accessibilityLabel,
|
|
84
|
+
hintText,
|
|
84
85
|
...props
|
|
85
86
|
}: InputOTPProps,
|
|
86
87
|
ref,
|
|
@@ -88,13 +89,16 @@ const InputOTP = forwardRef(
|
|
|
88
89
|
const MAX_LENGTH = 10;
|
|
89
90
|
const [value, setValue] = useState('');
|
|
90
91
|
const [focused, setFocused] = useState(false);
|
|
91
|
-
const inputRef = useRef<TextInput>(null);
|
|
92
|
+
const inputRef = useRef<TextInput | null>(null);
|
|
92
93
|
const {theme} = useContext(ApplicationContext);
|
|
93
94
|
|
|
94
95
|
useImperativeHandle(ref, () => ({
|
|
95
96
|
onChangeText: (text: string) => {
|
|
96
97
|
_onChangeText(text);
|
|
97
98
|
},
|
|
99
|
+
focus: () => inputRef.current?.focus(),
|
|
100
|
+
blur: () => inputRef.current?.blur(),
|
|
101
|
+
setText: (text: string) => _onChangeText(text),
|
|
98
102
|
}));
|
|
99
103
|
|
|
100
104
|
const onFocusInput = () => {
|
|
@@ -239,7 +243,11 @@ const InputOTP = forwardRef(
|
|
|
239
243
|
onPress={onFocusInput}
|
|
240
244
|
style={[style, styles.otpWrapper]}>
|
|
241
245
|
{renderInputView()}
|
|
242
|
-
<ErrorView
|
|
246
|
+
<ErrorView
|
|
247
|
+
errorMessage={errorMessage}
|
|
248
|
+
errorSpacing={errorSpacing}
|
|
249
|
+
hintText={hintText}
|
|
250
|
+
/>
|
|
243
251
|
</TouchableOpacity>
|
|
244
252
|
</ComponentContext.Provider>
|
|
245
253
|
);
|
package/Input/InputSearch.tsx
CHANGED
|
@@ -1,4 +1,10 @@
|
|
|
1
|
-
import React, {
|
|
1
|
+
import React, {
|
|
2
|
+
forwardRef,
|
|
3
|
+
useContext,
|
|
4
|
+
useImperativeHandle,
|
|
5
|
+
useRef,
|
|
6
|
+
useState,
|
|
7
|
+
} from 'react';
|
|
2
8
|
import {
|
|
3
9
|
NativeSyntheticEvent,
|
|
4
10
|
TextInput,
|
|
@@ -6,11 +12,11 @@ import {
|
|
|
6
12
|
TouchableOpacity,
|
|
7
13
|
View,
|
|
8
14
|
} from 'react-native';
|
|
9
|
-
import {InputSearchProps} from './index';
|
|
10
15
|
import {ApplicationContext, ComponentContext} from '../Application';
|
|
11
|
-
import styles from './styles';
|
|
12
16
|
import {Icon} from '../Icon';
|
|
13
17
|
import {Text} from '../Text';
|
|
18
|
+
import {InputSearchProps} from './index';
|
|
19
|
+
import styles from './styles';
|
|
14
20
|
import {checkTyping} from './utils';
|
|
15
21
|
|
|
16
22
|
const InputSearch = forwardRef(
|
|
@@ -38,7 +44,7 @@ const InputSearch = forwardRef(
|
|
|
38
44
|
const {theme} = useContext(ApplicationContext);
|
|
39
45
|
const [focused, setFocused] = useState(false);
|
|
40
46
|
const [haveValue, setHaveValue] = useState(!!value || !!defaultValue);
|
|
41
|
-
const inputRef =
|
|
47
|
+
const inputRef = useRef<TextInput | null>(null);
|
|
42
48
|
|
|
43
49
|
const _onFocus = (e: NativeSyntheticEvent<TextInputFocusEventData>) => {
|
|
44
50
|
setFocused(true);
|
|
@@ -60,6 +66,15 @@ const InputSearch = forwardRef(
|
|
|
60
66
|
onChangeText?.(text);
|
|
61
67
|
};
|
|
62
68
|
|
|
69
|
+
useImperativeHandle(ref, () => {
|
|
70
|
+
return {
|
|
71
|
+
clear: onClearText,
|
|
72
|
+
focus: () => inputRef.current?.focus(),
|
|
73
|
+
blur: () => inputRef.current?.blur(),
|
|
74
|
+
setText: (text: string) => _onChangeText(text),
|
|
75
|
+
};
|
|
76
|
+
});
|
|
77
|
+
|
|
63
78
|
const renderInputView = () => {
|
|
64
79
|
return (
|
|
65
80
|
<TextInput
|
package/Input/InputTextArea.tsx
CHANGED
|
@@ -1,4 +1,10 @@
|
|
|
1
|
-
import React, {
|
|
1
|
+
import React, {
|
|
2
|
+
forwardRef,
|
|
3
|
+
useContext,
|
|
4
|
+
useImperativeHandle,
|
|
5
|
+
useRef,
|
|
6
|
+
useState,
|
|
7
|
+
} from 'react';
|
|
2
8
|
import {
|
|
3
9
|
NativeSyntheticEvent,
|
|
4
10
|
TextInput,
|
|
@@ -6,7 +12,8 @@ import {
|
|
|
6
12
|
TouchableOpacity,
|
|
7
13
|
View,
|
|
8
14
|
} from 'react-native';
|
|
9
|
-
import
|
|
15
|
+
import {ApplicationContext} from '../Application';
|
|
16
|
+
import {Icon} from '../Icon';
|
|
10
17
|
import {Text} from '../Text';
|
|
11
18
|
import {
|
|
12
19
|
DEFAULT_HEIGHT,
|
|
@@ -16,8 +23,7 @@ import {
|
|
|
16
23
|
MAX_LENGTH,
|
|
17
24
|
} from './common';
|
|
18
25
|
import {InputTextAreaProps} from './index';
|
|
19
|
-
import
|
|
20
|
-
import {ApplicationContext} from '../Application';
|
|
26
|
+
import styles from './styles';
|
|
21
27
|
|
|
22
28
|
const InputTextArea = forwardRef(
|
|
23
29
|
(
|
|
@@ -39,6 +45,7 @@ const InputTextArea = forwardRef(
|
|
|
39
45
|
errorSpacing,
|
|
40
46
|
style,
|
|
41
47
|
accessibilityLabel,
|
|
48
|
+
hintText,
|
|
42
49
|
...props
|
|
43
50
|
}: InputTextAreaProps,
|
|
44
51
|
ref,
|
|
@@ -46,7 +53,7 @@ const InputTextArea = forwardRef(
|
|
|
46
53
|
const {theme} = useContext(ApplicationContext);
|
|
47
54
|
const [focused, setFocused] = useState(false);
|
|
48
55
|
const [inputValue, setInputValue] = useState(defaultValue ?? '');
|
|
49
|
-
const inputRef =
|
|
56
|
+
const inputRef = useRef<TextInput | null>(null);
|
|
50
57
|
|
|
51
58
|
const onClearText = () => {
|
|
52
59
|
inputRef?.current?.clear();
|
|
@@ -68,6 +75,15 @@ const InputTextArea = forwardRef(
|
|
|
68
75
|
onBlur?.(e);
|
|
69
76
|
};
|
|
70
77
|
|
|
78
|
+
useImperativeHandle(ref, () => {
|
|
79
|
+
return {
|
|
80
|
+
clear: onClearText,
|
|
81
|
+
focus: () => inputRef.current?.focus(),
|
|
82
|
+
blur: () => inputRef.current?.blur(),
|
|
83
|
+
setText: (text: string) => _onChangeText(text),
|
|
84
|
+
};
|
|
85
|
+
});
|
|
86
|
+
|
|
71
87
|
const renderCountingView = () => {
|
|
72
88
|
return (
|
|
73
89
|
<View style={styles.countingView}>
|
|
@@ -151,7 +167,11 @@ const InputTextArea = forwardRef(
|
|
|
151
167
|
return (
|
|
152
168
|
<View style={[style, styles.wrapper]}>
|
|
153
169
|
{renderInputView()}
|
|
154
|
-
<ErrorView
|
|
170
|
+
<ErrorView
|
|
171
|
+
errorMessage={errorMessage}
|
|
172
|
+
errorSpacing={errorSpacing}
|
|
173
|
+
hintText={hintText}
|
|
174
|
+
/>
|
|
155
175
|
</View>
|
|
156
176
|
);
|
|
157
177
|
},
|
package/Input/common.tsx
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import {View, ViewStyle} from 'react-native';
|
|
2
|
-
import styles from './styles';
|
|
3
|
-
import {scaleSize, Text} from '../Text';
|
|
4
1
|
import React, {FC, useContext} from 'react';
|
|
2
|
+
import {View, ViewStyle} from 'react-native';
|
|
5
3
|
import {ApplicationContext} from '../Application';
|
|
6
|
-
import {Icon} from '../Icon';
|
|
7
|
-
import {Styles} from '../Consts';
|
|
8
4
|
import {Theme} from '../Application/types';
|
|
5
|
+
import {Styles} from '../Consts';
|
|
6
|
+
import {Icon} from '../Icon';
|
|
7
|
+
import {scaleSize, Text} from '../Text';
|
|
8
|
+
import styles from './styles';
|
|
9
9
|
|
|
10
10
|
type FloatingViewProps = {
|
|
11
11
|
floatingValue?: string;
|
|
@@ -16,6 +16,13 @@ type FloatingViewProps = {
|
|
|
16
16
|
style?: ViewStyle;
|
|
17
17
|
};
|
|
18
18
|
|
|
19
|
+
export interface InputRef {
|
|
20
|
+
focus: () => void;
|
|
21
|
+
blur: () => void;
|
|
22
|
+
clear: () => void;
|
|
23
|
+
setText: (text: string) => void;
|
|
24
|
+
}
|
|
25
|
+
|
|
19
26
|
export const DEFAULT_HEIGHT = scaleSize(104);
|
|
20
27
|
export const MAX_LENGTH = 300;
|
|
21
28
|
|
|
@@ -48,24 +55,31 @@ export const getSizeStyle = (size?: 'small' | 'large') => {
|
|
|
48
55
|
}
|
|
49
56
|
return styles.container;
|
|
50
57
|
};
|
|
51
|
-
export const ErrorView: FC<{
|
|
52
|
-
errorMessage
|
|
53
|
-
errorSpacing
|
|
54
|
-
|
|
58
|
+
export const ErrorView: FC<{
|
|
59
|
+
errorMessage?: string;
|
|
60
|
+
errorSpacing?: boolean;
|
|
61
|
+
hintText?: string;
|
|
62
|
+
}> = ({errorMessage, errorSpacing, hintText}) => {
|
|
55
63
|
const {theme} = useContext(ApplicationContext);
|
|
56
64
|
const errorColor = theme.colors.error.primary;
|
|
57
|
-
|
|
65
|
+
const hintColor = theme.colors.text.hint;
|
|
66
|
+
const hintTextDefault = hintText ?? 'Không thể chỉnh sửa';
|
|
67
|
+
if (errorMessage || hintText) {
|
|
58
68
|
return (
|
|
59
69
|
<View style={styles.errorView}>
|
|
60
70
|
<View style={styles.errorIcon}>
|
|
61
|
-
<Icon
|
|
71
|
+
<Icon
|
|
72
|
+
color={errorMessage ? errorColor : hintColor}
|
|
73
|
+
source="ic_error"
|
|
74
|
+
size={16}
|
|
75
|
+
/>
|
|
62
76
|
</View>
|
|
63
77
|
<Text
|
|
64
78
|
style={Styles.flex}
|
|
65
|
-
color={errorColor}
|
|
79
|
+
color={errorMessage ? errorColor : hintColor}
|
|
66
80
|
numberOfLines={2}
|
|
67
81
|
typography={'description_default_regular'}>
|
|
68
|
-
{errorMessage}
|
|
82
|
+
{errorMessage ?? hintTextDefault}
|
|
69
83
|
</Text>
|
|
70
84
|
</View>
|
|
71
85
|
);
|
package/Input/index.tsx
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
+
import {TextInputProps, ViewStyle} from 'react-native';
|
|
1
2
|
import Input from './Input';
|
|
2
|
-
import
|
|
3
|
-
import InputSearch from './InputSearch';
|
|
3
|
+
import InputDropDown from './InputDropDown';
|
|
4
4
|
import InputMoney from './InputMoney';
|
|
5
5
|
import InputOTP from './InputOTP';
|
|
6
|
-
import
|
|
7
|
-
import
|
|
6
|
+
import InputSearch from './InputSearch';
|
|
7
|
+
import InputTextArea from './InputTextArea';
|
|
8
8
|
|
|
9
9
|
export interface InputProps extends TextInputProps {
|
|
10
10
|
/**
|
|
@@ -77,11 +77,25 @@ export interface InputProps extends TextInputProps {
|
|
|
77
77
|
*/
|
|
78
78
|
leadingIconColor?: string;
|
|
79
79
|
|
|
80
|
+
/**
|
|
81
|
+
* Optional. Represents the font weight of the text in the Input component.
|
|
82
|
+
*/
|
|
80
83
|
fontWeight?: 'Regular' | 'Bold';
|
|
81
84
|
|
|
85
|
+
/**
|
|
86
|
+
* Optional. callback function to be called when the icon is pressed.
|
|
87
|
+
*/
|
|
82
88
|
onPressIcon?: () => void;
|
|
83
89
|
|
|
90
|
+
/**
|
|
91
|
+
* Optional. params for element tracking.
|
|
92
|
+
*/
|
|
84
93
|
params?: any;
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Optional. Represents text below the Input component.
|
|
97
|
+
*/
|
|
98
|
+
hintText?: string;
|
|
85
99
|
}
|
|
86
100
|
|
|
87
101
|
type InputPropsWithoutSizeAndIcon = Omit<
|
|
@@ -267,4 +281,4 @@ export interface InputDropDownProps extends InputProps {
|
|
|
267
281
|
style?: ViewStyle | ViewStyle[];
|
|
268
282
|
}
|
|
269
283
|
|
|
270
|
-
export {Input,
|
|
284
|
+
export {Input, InputDropDown, InputMoney, InputOTP, InputSearch, InputTextArea};
|
package/Layout/Screen.tsx
CHANGED
|
@@ -1,6 +1,18 @@
|
|
|
1
|
+
import {useHeaderHeight} from '@react-navigation/stack';
|
|
2
|
+
import React, {
|
|
3
|
+
forwardRef,
|
|
4
|
+
Fragment,
|
|
5
|
+
ReactNode,
|
|
6
|
+
useCallback,
|
|
7
|
+
useContext,
|
|
8
|
+
useEffect,
|
|
9
|
+
useRef,
|
|
10
|
+
} from 'react';
|
|
1
11
|
import {
|
|
2
12
|
Animated,
|
|
13
|
+
Easing,
|
|
3
14
|
KeyboardAvoidingView,
|
|
15
|
+
LayoutChangeEvent,
|
|
4
16
|
NativeScrollEvent,
|
|
5
17
|
NativeSyntheticEvent,
|
|
6
18
|
Platform,
|
|
@@ -8,28 +20,24 @@ import {
|
|
|
8
20
|
View,
|
|
9
21
|
ViewProps,
|
|
10
22
|
} from 'react-native';
|
|
11
|
-
import {useHeaderHeight} from '@react-navigation/stack';
|
|
12
23
|
import {useSafeAreaInsets} from 'react-native-safe-area-context';
|
|
13
|
-
import React, {
|
|
14
|
-
forwardRef,
|
|
15
|
-
Fragment,
|
|
16
|
-
ReactNode,
|
|
17
|
-
useContext,
|
|
18
|
-
useEffect,
|
|
19
|
-
useRef,
|
|
20
|
-
} from 'react';
|
|
21
|
-
import {Colors, Spacing, Styles} from '../Consts';
|
|
22
|
-
import {Card, Section, validateChildren} from './index';
|
|
23
24
|
import {
|
|
24
25
|
ApplicationContext,
|
|
25
26
|
HeaderBackground,
|
|
26
27
|
HeaderTitle,
|
|
27
28
|
} from '../Application';
|
|
28
29
|
import Navigation from '../Application/Navigation';
|
|
29
|
-
import styles from './styles';
|
|
30
30
|
import {AnimatedHeader, NavigationOptions} from '../Application/types';
|
|
31
|
+
import {Colors, Spacing, Styles} from '../Consts';
|
|
32
|
+
import {
|
|
33
|
+
FloatingButton,
|
|
34
|
+
FloatingButtonProps,
|
|
35
|
+
} from '../FloatingButton/FloatingButton';
|
|
31
36
|
import {Image} from '../Image';
|
|
37
|
+
import {Card, Section, validateChildren} from './index';
|
|
38
|
+
import styles from './styles';
|
|
32
39
|
import {HeaderType} from './types';
|
|
40
|
+
import {debounce} from './utils';
|
|
33
41
|
|
|
34
42
|
export interface ScreenProps extends ViewProps {
|
|
35
43
|
children: React.ReactNode;
|
|
@@ -82,6 +90,11 @@ export interface ScreenProps extends ViewProps {
|
|
|
82
90
|
* Optional. layout card offset overlap header banner.
|
|
83
91
|
*/
|
|
84
92
|
layoutOffset?: -8 | -24 | -56;
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Optional. Props for the floating action button.
|
|
96
|
+
*/
|
|
97
|
+
floatingButtonProps?: Omit<FloatingButtonProps, 'animatedValue'>;
|
|
85
98
|
}
|
|
86
99
|
|
|
87
100
|
const Screen = forwardRef(
|
|
@@ -98,13 +111,18 @@ const Screen = forwardRef(
|
|
|
98
111
|
layoutOffset = -56,
|
|
99
112
|
backgroundColor,
|
|
100
113
|
headerType = 'default',
|
|
114
|
+
floatingButtonProps,
|
|
101
115
|
}: ScreenProps,
|
|
102
116
|
ref,
|
|
103
117
|
) => {
|
|
104
118
|
const animatedValue = useRef<Animated.Value | undefined>(undefined);
|
|
119
|
+
const lastScrollPosition = useRef(0);
|
|
120
|
+
const animatedFABValue = useRef(new Animated.Value(0)).current;
|
|
105
121
|
const {theme} = useContext(ApplicationContext);
|
|
106
122
|
const insets = useSafeAreaInsets();
|
|
107
123
|
const heightHeader = useHeaderHeight();
|
|
124
|
+
const layoutHeight = useRef(0);
|
|
125
|
+
const contentHeight = useRef(0);
|
|
108
126
|
const currentTint = useRef(Colors.black_01);
|
|
109
127
|
let styleAnimatedHeader: NavigationOptions;
|
|
110
128
|
let handleScroll;
|
|
@@ -155,7 +173,7 @@ const Screen = forwardRef(
|
|
|
155
173
|
|
|
156
174
|
useEffect(() => {
|
|
157
175
|
if (!animatedHeader) {
|
|
158
|
-
let headerOptions: NavigationOptions
|
|
176
|
+
let headerOptions: NavigationOptions;
|
|
159
177
|
switch (headerType) {
|
|
160
178
|
case 'none':
|
|
161
179
|
headerOptions = {
|
|
@@ -213,8 +231,9 @@ const Screen = forwardRef(
|
|
|
213
231
|
if (scrollable) {
|
|
214
232
|
Component = Animated.ScrollView;
|
|
215
233
|
handleScroll = scrollViewProps?.onScroll;
|
|
216
|
-
if (animatedHeader) {
|
|
234
|
+
if (animatedHeader || floatingButtonProps) {
|
|
217
235
|
animatedValue.current = new Animated.Value(0);
|
|
236
|
+
|
|
218
237
|
handleScroll = Animated.event(
|
|
219
238
|
[
|
|
220
239
|
{
|
|
@@ -224,9 +243,9 @@ const Screen = forwardRef(
|
|
|
224
243
|
},
|
|
225
244
|
],
|
|
226
245
|
{
|
|
227
|
-
useNativeDriver:
|
|
246
|
+
useNativeDriver: false,
|
|
228
247
|
listener: (e: NativeSyntheticEvent<NativeScrollEvent>) => {
|
|
229
|
-
if (animatedHeader
|
|
248
|
+
if (animatedHeader?.type == 'surface') {
|
|
230
249
|
const offsetY = e.nativeEvent.contentOffset.y;
|
|
231
250
|
let color = Colors.black_01;
|
|
232
251
|
if (offsetY > 50) {
|
|
@@ -239,13 +258,46 @@ const Screen = forwardRef(
|
|
|
239
258
|
});
|
|
240
259
|
}
|
|
241
260
|
}
|
|
242
|
-
|
|
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
|
+
}
|
|
243
283
|
},
|
|
244
284
|
},
|
|
245
285
|
);
|
|
246
286
|
}
|
|
247
287
|
}
|
|
248
288
|
|
|
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
|
+
|
|
249
301
|
/**
|
|
250
302
|
* render top navigation banner
|
|
251
303
|
*/
|
|
@@ -299,7 +351,6 @@ const Screen = forwardRef(
|
|
|
299
351
|
);
|
|
300
352
|
}
|
|
301
353
|
};
|
|
302
|
-
|
|
303
354
|
return (
|
|
304
355
|
<View style={[Styles.flex, {backgroundColor}]}>
|
|
305
356
|
{!!headerBackground && (
|
|
@@ -327,6 +378,12 @@ const Screen = forwardRef(
|
|
|
327
378
|
ref={ref}
|
|
328
379
|
showsVerticalScrollIndicator={false}
|
|
329
380
|
onScroll={handleScroll}
|
|
381
|
+
onContentSizeChange={(_: number, height: number) => {
|
|
382
|
+
contentHeight.current = height;
|
|
383
|
+
}}
|
|
384
|
+
onLayout={(event: LayoutChangeEvent) => {
|
|
385
|
+
layoutHeight.current = event.nativeEvent.layout.height;
|
|
386
|
+
}}
|
|
330
387
|
style={Styles.flex}>
|
|
331
388
|
<View
|
|
332
389
|
style={[styles.screenBanner, {maxHeight: 210 + layoutOffset}]}>
|
|
@@ -334,10 +391,25 @@ const Screen = forwardRef(
|
|
|
334
391
|
</View>
|
|
335
392
|
{renderContent(children)}
|
|
336
393
|
</Component>
|
|
394
|
+
<View>
|
|
395
|
+
{floatingButtonProps && (
|
|
396
|
+
<FloatingButton
|
|
397
|
+
label={floatingButtonProps?.label}
|
|
398
|
+
onPress={floatingButtonProps?.onPress}
|
|
399
|
+
size={floatingButtonProps?.size}
|
|
400
|
+
position={floatingButtonProps?.position}
|
|
401
|
+
icon={floatingButtonProps?.icon}
|
|
402
|
+
iconColor={floatingButtonProps?.iconColor}
|
|
403
|
+
isBottomTab={floatingButtonProps?.isBottomTab}
|
|
404
|
+
animatedValue={animatedFABValue}
|
|
405
|
+
isFooter={!!Footer}
|
|
406
|
+
/>
|
|
407
|
+
)}
|
|
408
|
+
</View>
|
|
337
409
|
{Footer && (
|
|
338
410
|
<View
|
|
339
411
|
style={[
|
|
340
|
-
styles.
|
|
412
|
+
styles.shadow,
|
|
341
413
|
{
|
|
342
414
|
paddingBottom: Math.min(insets.bottom, 21) + Spacing.S,
|
|
343
415
|
backgroundColor: theme.colors.background.surface,
|
package/Layout/styles.ts
CHANGED
|
@@ -80,17 +80,21 @@ export default StyleSheet.create({
|
|
|
80
80
|
paddingHorizontal: undefined,
|
|
81
81
|
paddingVertical: undefined,
|
|
82
82
|
},
|
|
83
|
-
|
|
83
|
+
shadow: {
|
|
84
84
|
paddingTop: Spacing.S,
|
|
85
85
|
...Platform.select({
|
|
86
|
-
android: {
|
|
87
|
-
elevation: 4,
|
|
88
|
-
},
|
|
89
86
|
ios: {
|
|
87
|
+
shadowColor: Colors.black_17,
|
|
88
|
+
shadowOffset: {
|
|
89
|
+
width: 2,
|
|
90
|
+
height: 2,
|
|
91
|
+
},
|
|
92
|
+
shadowOpacity: 0.25,
|
|
93
|
+
shadowRadius: 10,
|
|
94
|
+
},
|
|
95
|
+
android: {
|
|
90
96
|
shadowColor: Colors.black_20,
|
|
91
|
-
|
|
92
|
-
shadowOpacity: 0.1,
|
|
93
|
-
shadowRadius: 3,
|
|
97
|
+
elevation: 24,
|
|
94
98
|
},
|
|
95
99
|
}),
|
|
96
100
|
},
|
package/Layout/utils.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {Dimensions} from 'react-native';
|
|
2
1
|
import React, {Fragment, ReactElement, useEffect, useState} from 'react';
|
|
2
|
+
import {Dimensions} from 'react-native';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* validate children type
|
|
@@ -51,5 +51,20 @@ 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
|
+
|
|
60
|
+
return function (...args: Parameters<T>) {
|
|
61
|
+
if (timeout !== null) {
|
|
62
|
+
clearTimeout(timeout);
|
|
63
|
+
}
|
|
64
|
+
timeout = setTimeout(() => {
|
|
65
|
+
func(...args);
|
|
66
|
+
}, wait);
|
|
67
|
+
};
|
|
68
|
+
}
|
|
54
69
|
|
|
55
|
-
export {
|
|
70
|
+
export {debounce, useGridSystem, validateChildren};
|
package/Popup/PopupNotify.tsx
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import React, {useContext, useEffect, useRef, useState} from 'react';
|
|
2
2
|
import {ScrollView, StyleSheet, TouchableOpacity, View} from 'react-native';
|
|
3
|
-
import {PopupNotifyProps} from './types';
|
|
4
|
-
import {Radius, Spacing, Styles} from '../Consts';
|
|
5
|
-
import {Image} from '../Image';
|
|
6
|
-
import {Text} from '../Text';
|
|
7
3
|
import {ApplicationContext, MiniAppContext} from '../Application';
|
|
8
4
|
import {Button} from '../Button';
|
|
5
|
+
import {Radius, Spacing, Styles} from '../Consts';
|
|
9
6
|
import {Icon} from '../Icon';
|
|
7
|
+
import {Image} from '../Image';
|
|
8
|
+
import {Text} from '../Text';
|
|
9
|
+
import {PopupNotifyProps} from './types';
|
|
10
10
|
|
|
11
11
|
const PopupNotify: React.FC<PopupNotifyProps> = ({
|
|
12
12
|
id,
|
|
@@ -23,14 +23,12 @@ const PopupNotify: React.FC<PopupNotifyProps> = ({
|
|
|
23
23
|
const {theme, navigator, translate} = useContext(ApplicationContext);
|
|
24
24
|
const [scrollContent, setScrollContent] = useState(false);
|
|
25
25
|
const closeAction = useRef('touch_outside');
|
|
26
|
-
|
|
27
26
|
let descriptionStyle = {};
|
|
28
27
|
let Description: any = View;
|
|
29
28
|
if (scrollContent) {
|
|
30
29
|
Description = ScrollView;
|
|
31
30
|
descriptionStyle = {height: 80};
|
|
32
31
|
}
|
|
33
|
-
|
|
34
32
|
/**
|
|
35
33
|
* tracking
|
|
36
34
|
*/
|
|
@@ -160,30 +158,32 @@ const PopupNotify: React.FC<PopupNotifyProps> = ({
|
|
|
160
158
|
* build close action
|
|
161
159
|
*/
|
|
162
160
|
const buildCloseIcon = () => {
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
161
|
+
if (typeof onIconClose === 'function') {
|
|
162
|
+
return (
|
|
163
|
+
<TouchableOpacity
|
|
164
|
+
accessibilityLabel={'ic_popup_close'}
|
|
165
|
+
style={styles.iconCloseContainer}
|
|
166
|
+
onPress={() => {
|
|
167
|
+
closeAction.current = 'icon_close';
|
|
168
|
+
onAction(onIconClose);
|
|
169
|
+
}}>
|
|
170
|
+
<View
|
|
171
|
+
style={[
|
|
172
|
+
styles.iconClose,
|
|
173
|
+
{
|
|
174
|
+
backgroundColor: theme.colors.text.default,
|
|
175
|
+
borderColor: theme.colors.background.surface,
|
|
176
|
+
},
|
|
177
|
+
]}>
|
|
178
|
+
<Icon
|
|
179
|
+
source="navigation_close"
|
|
180
|
+
color={theme.colors.background.surface}
|
|
181
|
+
size={14}
|
|
182
|
+
/>
|
|
183
|
+
</View>
|
|
184
|
+
</TouchableOpacity>
|
|
185
|
+
);
|
|
186
|
+
}
|
|
187
187
|
};
|
|
188
188
|
|
|
189
189
|
return (
|
package/Popup/types.ts
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import {TextStyle} from 'react-native';
|
|
2
1
|
import React from 'react';
|
|
3
2
|
|
|
4
3
|
export type PopupNotifyProps = {
|
|
@@ -79,9 +78,4 @@ type PopupAction = {
|
|
|
79
78
|
onPress: () => void;
|
|
80
79
|
};
|
|
81
80
|
|
|
82
|
-
export type HighlightText = {
|
|
83
|
-
text: string;
|
|
84
|
-
style: TextStyle;
|
|
85
|
-
};
|
|
86
|
-
|
|
87
81
|
type PopupActionDirection = 'row' | 'column' | 'auto';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@momo-kits/foundation",
|
|
3
|
-
"version": "0.92.
|
|
3
|
+
"version": "0.92.6-beta.11",
|
|
4
4
|
"description": "React Native Component Kits",
|
|
5
5
|
"main": "index.ts",
|
|
6
6
|
"scripts": {
|
|
@@ -16,12 +16,12 @@
|
|
|
16
16
|
"react-native-gesture-handler": "1.10.3",
|
|
17
17
|
"react-native-modalize": "2.1.1",
|
|
18
18
|
"react-native-fast-image": "8.1.5",
|
|
19
|
-
"@react-navigation/bottom-tabs": "
|
|
19
|
+
"@react-navigation/bottom-tabs": "https://oauth2:5WXQLHPMxxCyvGt_Py4D@gitlab.mservice.com.vn/momo-platform/react-native-bottom-tabs.git",
|
|
20
20
|
"@react-navigation/core": "5.16.1",
|
|
21
21
|
"@react-navigation/native": "5.9.8",
|
|
22
22
|
"@react-navigation/routers": "5.7.4",
|
|
23
23
|
"lottie-react-native": "3.3.2",
|
|
24
|
-
"@react-navigation/stack": "
|
|
24
|
+
"@react-navigation/stack": "https://oauth2:eX-jVhzQdLc343AjD3Sc@gitlab.mservice.com.vn/momo-platform/react-navigation-stack.git"
|
|
25
25
|
},
|
|
26
26
|
"peerDependencies": {
|
|
27
27
|
"react-native": "*"
|