@momo-kits/foundation 0.81.1-beta.6 → 0.81.1-optimize.1
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/BottomTab.tsx +76 -23
- package/Application/Components.tsx +243 -198
- package/Application/ModalScreen.tsx +20 -65
- package/Application/Navigation.ts +15 -4
- package/Application/NavigationContainer.tsx +20 -20
- package/Application/Navigator.ts +61 -28
- package/Application/StackScreen.tsx +41 -23
- package/Application/index.ts +16 -6
- package/Application/types.ts +34 -19
- package/Application/utils.tsx +26 -0
- package/Assets/icon.json +83 -5
- package/Assets/icon_bank.json +506 -0
- package/Assets/language.json +3 -1
- package/Badge/Badge.tsx +56 -0
- package/Badge/BadgeDot.tsx +11 -0
- package/Badge/BadgeRibbon.tsx +125 -0
- package/Badge/Shape.tsx +29 -0
- package/Badge/index.tsx +7 -0
- package/Badge/styles.ts +58 -0
- package/Badge/types.ts +63 -0
- package/Button/index.tsx +26 -9
- package/Button/styles.ts +19 -0
- package/CheckBox/index.tsx +1 -2
- package/Consts/colors+spacing+radius.ts +3 -3
- package/Icon/index.tsx +7 -3
- package/Icon/types.ts +3 -3
- package/IconButton/index.tsx +0 -1
- package/Image/index.tsx +39 -49
- package/Image/styles.ts +1 -9
- package/Image/types.ts +3 -1
- package/Input/Input.tsx +37 -16
- package/Input/InputDropDown.tsx +5 -14
- package/Input/InputMoney.tsx +28 -11
- package/Input/InputOTP.tsx +169 -145
- package/Input/InputSearch.tsx +9 -13
- package/Input/InputTextArea.tsx +6 -12
- package/Input/common.tsx +5 -3
- package/Input/index.tsx +15 -9
- package/Input/styles.ts +1 -4
- package/Layout/Card.tsx +20 -11
- package/Layout/GridSystem.tsx +1 -2
- package/Layout/Item.tsx +0 -1
- package/Layout/ItemList.tsx +39 -40
- package/Layout/ItemSectionList.tsx +39 -0
- package/Layout/Screen.tsx +96 -45
- package/Layout/Section.tsx +17 -19
- package/Layout/index.ts +2 -1
- package/Layout/styles.ts +16 -15
- package/Layout/types.ts +2 -5
- package/Pagination/PaginationNumber.tsx +1 -1
- package/Pagination/PaginationScroll.tsx +0 -1
- package/Popup/PopupNotify.tsx +71 -14
- package/Popup/PopupPromotion.tsx +43 -6
- package/Popup/types.ts +12 -3
- package/Radio/index.tsx +1 -2
- package/Skeleton/index.tsx +1 -1
- package/Switch/index.tsx +0 -1
- package/Tag/index.tsx +2 -4
- package/Text/index.tsx +3 -2
- package/Text/styles.ts +38 -0
- package/Text/types.ts +25 -13
- package/Title/index.tsx +82 -38
- package/Title/styles.ts +16 -10
- package/Title/types.ts +2 -1
- package/index.ts +2 -0
- package/package.json +6 -6
- package/verify.js +15 -0
package/Input/Input.tsx
CHANGED
|
@@ -21,20 +21,23 @@ const Input = forwardRef(
|
|
|
21
21
|
onChangeText,
|
|
22
22
|
floatingValue,
|
|
23
23
|
floatingIcon,
|
|
24
|
-
size,
|
|
24
|
+
size = 'small',
|
|
25
25
|
placeholder,
|
|
26
26
|
onBlur,
|
|
27
27
|
onFocus,
|
|
28
28
|
errorMessage,
|
|
29
29
|
icon,
|
|
30
|
-
disabled,
|
|
30
|
+
disabled = false,
|
|
31
31
|
floatingIconColor,
|
|
32
32
|
iconColor,
|
|
33
|
-
required,
|
|
33
|
+
required = false,
|
|
34
34
|
errorSpacing,
|
|
35
|
-
loading,
|
|
35
|
+
loading = false,
|
|
36
36
|
leadingIcon,
|
|
37
37
|
leadingIconColor,
|
|
38
|
+
fontWeight = 'Regular',
|
|
39
|
+
onPressIcon,
|
|
40
|
+
secureTextEntry,
|
|
38
41
|
style,
|
|
39
42
|
...props
|
|
40
43
|
}: InputProps,
|
|
@@ -43,8 +46,8 @@ const Input = forwardRef(
|
|
|
43
46
|
const {theme} = useContext(ApplicationContext);
|
|
44
47
|
const [focused, setFocused] = useState(false);
|
|
45
48
|
const [haveValue, setHaveValue] = useState(!!value || !!props.defaultValue);
|
|
49
|
+
const [secureTextInput, setSecureTextInput] = useState(secureTextEntry);
|
|
46
50
|
const inputRef = (ref as React.RefObject<TextInput>) ?? useRef<TextInput>();
|
|
47
|
-
const accessibilityLabel = `Input/${floatingValue ?? placeholder}`;
|
|
48
51
|
|
|
49
52
|
const onClearText = () => {
|
|
50
53
|
inputRef?.current?.clear();
|
|
@@ -68,15 +71,38 @@ const Input = forwardRef(
|
|
|
68
71
|
|
|
69
72
|
const renderIcon = (color: string | undefined) => {
|
|
70
73
|
if (loading) {
|
|
71
|
-
return <Loader type={'spinner'} color={color} />;
|
|
74
|
+
return <Loader type={'spinner'} color={color} style={styles.icon} />;
|
|
75
|
+
}
|
|
76
|
+
if (secureTextEntry) {
|
|
77
|
+
return (
|
|
78
|
+
<TouchableOpacity
|
|
79
|
+
onPress={() => setSecureTextInput(!secureTextInput)}
|
|
80
|
+
style={styles.icon}>
|
|
81
|
+
<Icon
|
|
82
|
+
color={color}
|
|
83
|
+
size={24}
|
|
84
|
+
source={
|
|
85
|
+
secureTextInput ? '24_security_eye_off' : '24_security_eye_open'
|
|
86
|
+
}
|
|
87
|
+
/>
|
|
88
|
+
</TouchableOpacity>
|
|
89
|
+
);
|
|
72
90
|
}
|
|
73
91
|
if (icon) {
|
|
74
|
-
return
|
|
92
|
+
return (
|
|
93
|
+
<TouchableOpacity
|
|
94
|
+
onPress={onPressIcon}
|
|
95
|
+
disabled={!onPressIcon}
|
|
96
|
+
style={styles.icon}>
|
|
97
|
+
<Icon color={color} source={icon} size={24} />
|
|
98
|
+
</TouchableOpacity>
|
|
99
|
+
);
|
|
75
100
|
}
|
|
76
101
|
};
|
|
77
102
|
|
|
78
103
|
const renderInputView = () => {
|
|
79
104
|
const disabledColor = theme.colors.text.disable;
|
|
105
|
+
const secure = secureTextInput && secureTextEntry;
|
|
80
106
|
let textColor = theme.colors.text.default;
|
|
81
107
|
let placeholderColor = theme.colors.text.hint;
|
|
82
108
|
let iconTintColor = iconColor;
|
|
@@ -114,16 +140,17 @@ const Input = forwardRef(
|
|
|
114
140
|
)}
|
|
115
141
|
<TextInput
|
|
116
142
|
{...props}
|
|
117
|
-
accessibilityLabel={accessibilityLabel}
|
|
118
143
|
editable={!disabled}
|
|
144
|
+
secureTextEntry={secure}
|
|
119
145
|
textAlignVertical="center"
|
|
120
146
|
ref={inputRef}
|
|
121
147
|
style={[
|
|
122
148
|
styles.input,
|
|
123
149
|
{
|
|
124
150
|
color: textColor,
|
|
125
|
-
fontFamily: `${theme.font}
|
|
151
|
+
fontFamily: `${theme.font}-${fontWeight}`,
|
|
126
152
|
},
|
|
153
|
+
secure && haveValue && {fontSize: size === 'small' ? 18 : 22},
|
|
127
154
|
]}
|
|
128
155
|
textBreakStrategy="highQuality"
|
|
129
156
|
value={value}
|
|
@@ -154,9 +181,7 @@ const Input = forwardRef(
|
|
|
154
181
|
};
|
|
155
182
|
|
|
156
183
|
return (
|
|
157
|
-
<View
|
|
158
|
-
style={[style, styles.wrapper]}
|
|
159
|
-
accessibilityLabel={accessibilityLabel}>
|
|
184
|
+
<View style={[style, styles.wrapper]}>
|
|
160
185
|
{renderInputView()}
|
|
161
186
|
<ErrorView errorMessage={errorMessage} errorSpacing={errorSpacing} />
|
|
162
187
|
</View>
|
|
@@ -164,8 +189,4 @@ const Input = forwardRef(
|
|
|
164
189
|
},
|
|
165
190
|
);
|
|
166
191
|
|
|
167
|
-
Input.defaultProps = {
|
|
168
|
-
size: 'small',
|
|
169
|
-
};
|
|
170
|
-
|
|
171
192
|
export default Input;
|
package/Input/InputDropDown.tsx
CHANGED
|
@@ -12,17 +12,17 @@ const InputDropDown = ({
|
|
|
12
12
|
value,
|
|
13
13
|
floatingValue,
|
|
14
14
|
floatingIcon,
|
|
15
|
-
size,
|
|
15
|
+
size = 'small',
|
|
16
16
|
onPress,
|
|
17
17
|
placeholder,
|
|
18
18
|
errorMessage,
|
|
19
19
|
icon = 'arrow_chevron_down_small',
|
|
20
|
-
disabled,
|
|
20
|
+
disabled = false,
|
|
21
21
|
floatingIconColor,
|
|
22
22
|
iconColor,
|
|
23
|
-
required,
|
|
23
|
+
required = false,
|
|
24
24
|
errorSpacing,
|
|
25
|
-
loading,
|
|
25
|
+
loading = false,
|
|
26
26
|
leadingIcon,
|
|
27
27
|
leadingIconColor,
|
|
28
28
|
style,
|
|
@@ -30,7 +30,6 @@ const InputDropDown = ({
|
|
|
30
30
|
}: InputDropDownProps) => {
|
|
31
31
|
const {theme} = useContext(ApplicationContext);
|
|
32
32
|
const full = !!value || !!placeholder;
|
|
33
|
-
const accessibilityLabel = `InputDropDown/${floatingValue ?? placeholder}`;
|
|
34
33
|
|
|
35
34
|
const renderIcon = (color: string | undefined) => {
|
|
36
35
|
if (loading) {
|
|
@@ -82,7 +81,6 @@ const InputDropDown = ({
|
|
|
82
81
|
<TextInput
|
|
83
82
|
{...props}
|
|
84
83
|
onPressIn={onPress}
|
|
85
|
-
accessibilityLabel={accessibilityLabel}
|
|
86
84
|
editable={false}
|
|
87
85
|
textAlignVertical="top"
|
|
88
86
|
style={[
|
|
@@ -106,18 +104,11 @@ const InputDropDown = ({
|
|
|
106
104
|
};
|
|
107
105
|
|
|
108
106
|
return (
|
|
109
|
-
<TouchableOpacity
|
|
110
|
-
onPress={onPress}
|
|
111
|
-
style={[style, full && styles.wrapper]}
|
|
112
|
-
accessibilityLabel={accessibilityLabel}>
|
|
107
|
+
<TouchableOpacity onPress={onPress} style={[style, full && styles.wrapper]}>
|
|
113
108
|
{renderInputView()}
|
|
114
109
|
<ErrorView errorMessage={errorMessage} errorSpacing={errorSpacing} />
|
|
115
110
|
</TouchableOpacity>
|
|
116
111
|
);
|
|
117
112
|
};
|
|
118
113
|
|
|
119
|
-
InputDropDown.defaultProps = {
|
|
120
|
-
size: 'small',
|
|
121
|
-
};
|
|
122
|
-
|
|
123
114
|
export default InputDropDown;
|
package/Input/InputMoney.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,
|
|
@@ -24,12 +30,13 @@ const InputMoney = forwardRef(
|
|
|
24
30
|
onFocus,
|
|
25
31
|
errorMessage,
|
|
26
32
|
icon,
|
|
27
|
-
disabled,
|
|
33
|
+
disabled = false,
|
|
28
34
|
floatingIconColor,
|
|
29
35
|
iconColor,
|
|
30
|
-
required,
|
|
36
|
+
required = false,
|
|
31
37
|
errorSpacing,
|
|
32
38
|
style,
|
|
39
|
+
defaultValue = '',
|
|
33
40
|
...props
|
|
34
41
|
}: InputMoneyProps,
|
|
35
42
|
ref,
|
|
@@ -37,23 +44,36 @@ const InputMoney = forwardRef(
|
|
|
37
44
|
const {theme} = useContext(ApplicationContext);
|
|
38
45
|
const [focused, setFocused] = useState(false);
|
|
39
46
|
const inputRef = (ref as React.RefObject<TextInput>) ?? useRef<TextInput>();
|
|
40
|
-
|
|
41
|
-
const
|
|
47
|
+
|
|
48
|
+
const validateText = (text: string) => {
|
|
49
|
+
const valueFormat = formatMoneyToNumber(text, 'đ');
|
|
50
|
+
return formatNumberToMoney(valueFormat, 'đ');
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
const [value, setValue] = useState(
|
|
54
|
+
defaultValue ? validateText(defaultValue) : '',
|
|
55
|
+
);
|
|
42
56
|
|
|
43
57
|
const onClearText = () => {
|
|
44
58
|
inputRef?.current?.clear();
|
|
45
59
|
setValue('');
|
|
46
60
|
onChangeText?.('');
|
|
47
61
|
};
|
|
62
|
+
|
|
48
63
|
const _onChangeText = (text: string) => {
|
|
49
64
|
if (text.length < value.length && value.indexOf(text) === 0) {
|
|
50
65
|
text = value.slice(0, -2) + 'đ';
|
|
51
66
|
}
|
|
52
|
-
|
|
53
|
-
setValue(formatNumberToMoney(valueFormat, 'đ'));
|
|
67
|
+
setValue(validateText(text));
|
|
54
68
|
onChangeText?.(formatMoneyToNumber(text, 'đ').toString());
|
|
55
69
|
};
|
|
56
70
|
|
|
71
|
+
useImperativeHandle(ref, () => {
|
|
72
|
+
return {
|
|
73
|
+
setText: _onChangeText,
|
|
74
|
+
};
|
|
75
|
+
});
|
|
76
|
+
|
|
57
77
|
const _onFocus = (e: NativeSyntheticEvent<TextInputFocusEventData>) => {
|
|
58
78
|
setFocused(true);
|
|
59
79
|
onFocus?.(e);
|
|
@@ -94,7 +114,6 @@ const InputMoney = forwardRef(
|
|
|
94
114
|
<View style={styles.inputView}>
|
|
95
115
|
<TextInput
|
|
96
116
|
{...props}
|
|
97
|
-
accessibilityLabel={accessibilityLabel}
|
|
98
117
|
editable={!disabled}
|
|
99
118
|
textAlignVertical="top"
|
|
100
119
|
ref={inputRef}
|
|
@@ -133,9 +152,7 @@ const InputMoney = forwardRef(
|
|
|
133
152
|
};
|
|
134
153
|
|
|
135
154
|
return (
|
|
136
|
-
<View
|
|
137
|
-
style={[style, styles.wrapper]}
|
|
138
|
-
accessibilityLabel={accessibilityLabel}>
|
|
155
|
+
<View style={[style, styles.wrapper]}>
|
|
139
156
|
{renderInputView()}
|
|
140
157
|
<ErrorView errorMessage={errorMessage} errorSpacing={errorSpacing} />
|
|
141
158
|
</View>
|
package/Input/InputOTP.tsx
CHANGED
|
@@ -1,4 +1,12 @@
|
|
|
1
|
-
import React, {
|
|
1
|
+
import React, {
|
|
2
|
+
FC,
|
|
3
|
+
forwardRef,
|
|
4
|
+
useContext,
|
|
5
|
+
useEffect,
|
|
6
|
+
useImperativeHandle,
|
|
7
|
+
useRef,
|
|
8
|
+
useState,
|
|
9
|
+
} from 'react';
|
|
2
10
|
import {
|
|
3
11
|
Animated,
|
|
4
12
|
NativeSyntheticEvent,
|
|
@@ -49,163 +57,179 @@ const OTPCaret: FC<CaretProps> = ({index, length}) => {
|
|
|
49
57
|
opacity,
|
|
50
58
|
}}
|
|
51
59
|
/>
|
|
52
|
-
<Text color={theme.colors.text.hint} typography={'
|
|
60
|
+
<Text color={theme.colors.text.hint} typography={'body_default_regular'}>
|
|
53
61
|
-
|
|
54
62
|
</Text>
|
|
55
63
|
</View>
|
|
56
64
|
);
|
|
57
65
|
};
|
|
58
66
|
|
|
59
|
-
const InputOTP
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
inputRef.current?.focus();
|
|
84
|
-
};
|
|
85
|
-
|
|
86
|
-
const onBlurInput = (e: NativeSyntheticEvent<TextInputFocusEventData>) => {
|
|
87
|
-
setFocused(false);
|
|
88
|
-
onBlur?.(e);
|
|
89
|
-
};
|
|
90
|
-
|
|
91
|
-
const _onChangeText = (text: string) => {
|
|
92
|
-
if (text.length > MAX_LENGTH) return;
|
|
93
|
-
if (dataType === 'number' && isNaN(Number(text))) return;
|
|
94
|
-
if (
|
|
95
|
-
!isNaN(Number(text)) &&
|
|
96
|
-
value.length >= Number(length) &&
|
|
97
|
-
text.length >= value.length
|
|
98
|
-
)
|
|
99
|
-
return;
|
|
100
|
-
|
|
101
|
-
setValue(text);
|
|
102
|
-
onChangeText?.(text);
|
|
103
|
-
};
|
|
104
|
-
|
|
105
|
-
const renderInputs = (length: number) => {
|
|
106
|
-
const TextInputs: React.ReactNode[] = [];
|
|
107
|
-
for (let i = 0; i < length; i++) {
|
|
108
|
-
TextInputs.push(
|
|
109
|
-
<View>
|
|
110
|
-
{focused && value.length === i ? (
|
|
111
|
-
<OTPCaret index={i} length={length} />
|
|
112
|
-
) : (
|
|
113
|
-
<Text
|
|
114
|
-
style={i !== length - 1 && {marginRight: Spacing.L}}
|
|
115
|
-
color={
|
|
116
|
-
!!value[i] ? theme.colors.text.default : theme.colors.text.hint
|
|
117
|
-
}
|
|
118
|
-
typography={!!value[i] ? 'title_s' : 'paragraph_default'}>
|
|
119
|
-
{value[i] || '-'}
|
|
120
|
-
</Text>
|
|
121
|
-
)}
|
|
122
|
-
</View>,
|
|
123
|
-
);
|
|
124
|
-
}
|
|
125
|
-
return TextInputs;
|
|
126
|
-
};
|
|
67
|
+
const InputOTP = forwardRef(
|
|
68
|
+
(
|
|
69
|
+
{
|
|
70
|
+
length,
|
|
71
|
+
errorMessage,
|
|
72
|
+
errorSpacing,
|
|
73
|
+
floatingValue,
|
|
74
|
+
floatingIconColor,
|
|
75
|
+
floatingIcon,
|
|
76
|
+
placeholder,
|
|
77
|
+
onChangeText,
|
|
78
|
+
onFocus,
|
|
79
|
+
onBlur,
|
|
80
|
+
dataType = 'number',
|
|
81
|
+
style,
|
|
82
|
+
...props
|
|
83
|
+
}: InputOTPProps,
|
|
84
|
+
ref,
|
|
85
|
+
) => {
|
|
86
|
+
const MAX_LENGTH = 10;
|
|
87
|
+
const [value, setValue] = useState('');
|
|
88
|
+
const [focused, setFocused] = useState(false);
|
|
89
|
+
const inputRef = useRef<TextInput>(null);
|
|
90
|
+
const {theme} = useContext(ApplicationContext);
|
|
127
91
|
|
|
128
|
-
|
|
129
|
-
|
|
92
|
+
useImperativeHandle(ref, () => ({
|
|
93
|
+
onChangeText: (text: string) => {
|
|
94
|
+
_onChangeText(text);
|
|
95
|
+
},
|
|
96
|
+
}));
|
|
130
97
|
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
</Text>
|
|
136
|
-
);
|
|
137
|
-
}
|
|
98
|
+
const onFocusInput = () => {
|
|
99
|
+
setFocused(true);
|
|
100
|
+
inputRef.current?.focus();
|
|
101
|
+
};
|
|
138
102
|
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
103
|
+
const onBlurInput = (e: NativeSyntheticEvent<TextInputFocusEventData>) => {
|
|
104
|
+
setFocused(false);
|
|
105
|
+
onBlur?.(e);
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
const _onChangeText = (text: string) => {
|
|
109
|
+
if (text.length > MAX_LENGTH) return;
|
|
110
|
+
if (dataType === 'number' && isNaN(Number(text))) return;
|
|
111
|
+
if (
|
|
112
|
+
!isNaN(Number(text)) &&
|
|
113
|
+
value.length >= Number(length) &&
|
|
114
|
+
text.length >= value.length
|
|
115
|
+
)
|
|
116
|
+
return;
|
|
117
|
+
|
|
118
|
+
setValue(text);
|
|
119
|
+
onChangeText?.(text);
|
|
120
|
+
};
|
|
121
|
+
|
|
122
|
+
const renderInputs = (length: number) => {
|
|
123
|
+
const TextInputs: React.ReactNode[] = [];
|
|
124
|
+
for (let i = 0; i < length; i++) {
|
|
125
|
+
TextInputs.push(
|
|
126
|
+
<View>
|
|
127
|
+
{focused && value.length === i ? (
|
|
128
|
+
<OTPCaret index={i} length={length} />
|
|
129
|
+
) : (
|
|
130
|
+
<Text
|
|
131
|
+
style={i !== length - 1 && {marginRight: Spacing.L}}
|
|
132
|
+
color={
|
|
133
|
+
!!value[i]
|
|
134
|
+
? theme.colors.text.default
|
|
135
|
+
: theme.colors.text.hint
|
|
148
136
|
}
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
137
|
+
typography={
|
|
138
|
+
!!value[i] ? 'header_m_bold' : 'body_default_regular'
|
|
139
|
+
}>
|
|
140
|
+
{value[i] || '-'}
|
|
141
|
+
</Text>
|
|
142
|
+
)}
|
|
143
|
+
</View>,
|
|
144
|
+
);
|
|
145
|
+
}
|
|
146
|
+
return TextInputs;
|
|
147
|
+
};
|
|
159
148
|
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
149
|
+
const renderUnidentifiedInputs = () => {
|
|
150
|
+
const splitValue = value.split('');
|
|
151
|
+
|
|
152
|
+
if (!focused && value.length === 0 && !!placeholder) {
|
|
153
|
+
return (
|
|
154
|
+
<Text
|
|
155
|
+
color={theme.colors.text.hint}
|
|
156
|
+
typography={'description_default_regular'}>
|
|
157
|
+
{placeholder}
|
|
158
|
+
</Text>
|
|
159
|
+
);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
return (
|
|
163
|
+
<View style={{flexDirection: 'row'}}>
|
|
164
|
+
{splitValue.map((letter, index) => {
|
|
165
|
+
return (
|
|
166
|
+
<Text
|
|
167
|
+
style={
|
|
168
|
+
(index !== value.length - 1 ||
|
|
169
|
+
(focused && value.length !== MAX_LENGTH)) && {
|
|
170
|
+
marginRight: Spacing.L,
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
typography={'header_m_bold'}>
|
|
174
|
+
{letter}
|
|
175
|
+
</Text>
|
|
176
|
+
);
|
|
177
|
+
})}
|
|
178
|
+
{focused && value.length !== MAX_LENGTH && <OTPCaret />}
|
|
179
179
|
</View>
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
180
|
+
);
|
|
181
|
+
};
|
|
182
|
+
|
|
183
|
+
const renderInputView = () => {
|
|
184
|
+
return (
|
|
185
|
+
<View
|
|
186
|
+
style={[
|
|
187
|
+
styles.otpInput,
|
|
188
|
+
{backgroundColor: theme.colors.background.surface},
|
|
189
|
+
getBorderColor(theme, focused, errorMessage),
|
|
190
|
+
]}>
|
|
191
|
+
{!!floatingValue && (
|
|
192
|
+
<View
|
|
193
|
+
style={[
|
|
194
|
+
styles.otpFloatingView,
|
|
195
|
+
{backgroundColor: theme.colors.background.surface},
|
|
196
|
+
]}>
|
|
197
|
+
<Text typography={'description_default_regular'}>
|
|
198
|
+
{floatingValue}
|
|
199
|
+
</Text>
|
|
200
|
+
</View>
|
|
201
|
+
)}
|
|
202
|
+
<View style={styles.otpInputsView}>
|
|
203
|
+
{length ? renderInputs(length) : renderUnidentifiedInputs()}
|
|
204
|
+
</View>
|
|
205
|
+
<View style={styles.inputView}>
|
|
206
|
+
<TextInput
|
|
207
|
+
{...props}
|
|
208
|
+
ref={inputRef}
|
|
209
|
+
value={value}
|
|
210
|
+
onChangeText={_onChangeText}
|
|
211
|
+
keyboardType={dataType === 'number' ? 'number-pad' : 'default'}
|
|
212
|
+
onFocus={onFocusInput}
|
|
213
|
+
onBlur={onBlurInput}
|
|
214
|
+
style={{opacity: 0}}
|
|
215
|
+
selectionColor={theme.colors.primary}
|
|
216
|
+
placeholderTextColor={theme.colors.text.hint}
|
|
217
|
+
/>
|
|
218
|
+
</View>
|
|
194
219
|
</View>
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
};
|
|
220
|
+
);
|
|
221
|
+
};
|
|
198
222
|
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
223
|
+
return (
|
|
224
|
+
<TouchableOpacity
|
|
225
|
+
activeOpacity={1}
|
|
226
|
+
onPress={onFocusInput}
|
|
227
|
+
style={[style, styles.otpWrapper]}>
|
|
228
|
+
{renderInputView()}
|
|
229
|
+
<ErrorView errorMessage={errorMessage} errorSpacing={errorSpacing} />
|
|
230
|
+
</TouchableOpacity>
|
|
231
|
+
);
|
|
232
|
+
},
|
|
233
|
+
);
|
|
210
234
|
|
|
211
235
|
export default InputOTP;
|
package/Input/InputSearch.tsx
CHANGED
|
@@ -25,10 +25,10 @@ const InputSearch = forwardRef(
|
|
|
25
25
|
icon,
|
|
26
26
|
buttonText = 'Hủy',
|
|
27
27
|
showButtonText = true,
|
|
28
|
-
showBorder = true,
|
|
29
28
|
style,
|
|
30
29
|
defaultValue,
|
|
31
30
|
onPressButtonText,
|
|
31
|
+
hasColorBG = true,
|
|
32
32
|
...props
|
|
33
33
|
}: InputSearchProps,
|
|
34
34
|
ref,
|
|
@@ -37,7 +37,6 @@ const InputSearch = forwardRef(
|
|
|
37
37
|
const [focused, setFocused] = useState(false);
|
|
38
38
|
const [haveValue, setHaveValue] = useState(!!value || !!defaultValue);
|
|
39
39
|
const inputRef = (ref as React.RefObject<TextInput>) ?? useRef<TextInput>();
|
|
40
|
-
const accessibilityLabel = `InputMoney/${placeholder}`;
|
|
41
40
|
|
|
42
41
|
const _onFocus = (e: NativeSyntheticEvent<TextInputFocusEventData>) => {
|
|
43
42
|
setFocused(true);
|
|
@@ -63,8 +62,7 @@ const InputSearch = forwardRef(
|
|
|
63
62
|
return (
|
|
64
63
|
<TextInput
|
|
65
64
|
{...props}
|
|
66
|
-
|
|
67
|
-
textAlignVertical="top"
|
|
65
|
+
textAlignVertical="center"
|
|
68
66
|
ref={inputRef}
|
|
69
67
|
style={[
|
|
70
68
|
styles.searchInput,
|
|
@@ -118,19 +116,17 @@ const InputSearch = forwardRef(
|
|
|
118
116
|
</View>
|
|
119
117
|
);
|
|
120
118
|
};
|
|
119
|
+
|
|
120
|
+
const backgroundColor = hasColorBG ? theme.colors.background.default : theme.colors.background.surface
|
|
121
|
+
|
|
121
122
|
return (
|
|
122
|
-
<View
|
|
123
|
-
style={[style, styles.searchInputContainer]}
|
|
124
|
-
accessibilityLabel={accessibilityLabel}>
|
|
123
|
+
<View style={[style, styles.searchInputContainer]}>
|
|
125
124
|
<View
|
|
126
125
|
style={[
|
|
127
126
|
styles.searchInputWrapper,
|
|
128
127
|
{
|
|
129
|
-
backgroundColor
|
|
130
|
-
|
|
131
|
-
},
|
|
132
|
-
showBorder && {borderColor: theme.colors.border.default},
|
|
133
|
-
focused && {borderColor: theme.colors.primary},
|
|
128
|
+
backgroundColor,
|
|
129
|
+
}
|
|
134
130
|
]}>
|
|
135
131
|
<Icon
|
|
136
132
|
source={'navigation_search'}
|
|
@@ -142,7 +138,7 @@ const InputSearch = forwardRef(
|
|
|
142
138
|
</View>
|
|
143
139
|
{showButtonText && (
|
|
144
140
|
<TouchableOpacity onPress={onPressButtonText}>
|
|
145
|
-
<Text typography={'
|
|
141
|
+
<Text typography={'action_default_bold'} style={styles.textButton}>
|
|
146
142
|
{buttonText}
|
|
147
143
|
</Text>
|
|
148
144
|
</TouchableOpacity>
|