@momo-kits/foundation 0.89.5 → 0.89.6-rc.2
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/BottomSheet.tsx +216 -0
- package/Application/BottomTab/BottomTabBar.tsx +278 -0
- package/Application/{BottomTab.tsx → BottomTab/index.tsx} +42 -18
- package/Application/Components.tsx +350 -86
- package/Application/Localize.ts +44 -0
- package/Application/ModalScreen.tsx +14 -185
- package/Application/Navigation.ts +5 -19
- package/Application/NavigationContainer.tsx +62 -72
- package/Application/Navigator.ts +53 -35
- package/Application/StackScreen.tsx +289 -32
- package/Application/index.ts +13 -15
- package/Application/types.ts +64 -35
- package/Application/utils.tsx +76 -30
- package/Assets/icon_bank.json +1 -1
- package/Badge/Badge.tsx +1 -1
- package/Badge/BadgeDotAnimation.tsx +95 -0
- package/Badge/index.tsx +2 -1
- package/Badge/styles.ts +50 -6
- package/Button/index.tsx +44 -26
- package/CheckBox/index.tsx +37 -26
- package/CheckBox/types.ts +5 -3
- package/Consts/colors+spacing+radius.ts +14 -0
- package/Icon/index.tsx +9 -8
- package/Icon/types.ts +2 -2
- package/IconButton/index.tsx +24 -14
- package/Image/index.tsx +23 -8
- package/Image/types.ts +2 -0
- package/Input/Input.tsx +116 -26
- package/Input/InputDropDown.tsx +66 -51
- package/Input/InputMoney.tsx +106 -15
- package/Input/InputOTP.tsx +49 -26
- package/Input/InputSearch.tsx +252 -99
- package/Input/InputTextArea.tsx +26 -6
- package/Input/TextTyping.tsx +113 -0
- package/Input/common.tsx +48 -22
- package/Input/index.tsx +112 -77
- package/Input/styles.ts +48 -11
- package/Input/utils.ts +1 -1
- package/Layout/Card.tsx +4 -3
- package/Layout/FloatingButton.tsx +168 -0
- package/Layout/GridSystem.tsx +1 -1
- package/Layout/ItemList.tsx +3 -2
- package/Layout/Screen.tsx +242 -121
- package/Layout/Section.tsx +4 -3
- package/Layout/styles.ts +11 -13
- package/Layout/types.ts +1 -1
- package/Layout/utils.ts +4 -4
- package/Loader/index.tsx +2 -0
- package/Pagination/PaginationScroll.tsx +2 -2
- package/Pagination/styles.ts +1 -1
- package/Popup/PopupNotify.tsx +56 -45
- package/Popup/PopupPromotion.tsx +5 -7
- package/Popup/types.ts +1 -7
- package/Radio/index.tsx +35 -20
- package/Radio/types.ts +5 -3
- package/Switch/index.tsx +32 -18
- package/Switch/types.ts +5 -3
- package/Tag/index.tsx +9 -2
- package/Tag/styles.ts +3 -2
- package/Tag/types.ts +12 -0
- package/Text/index.tsx +24 -5
- package/Text/styles.ts +8 -8
- package/Text/types.ts +19 -1
- package/Title/index.tsx +170 -103
- package/Title/styles.ts +36 -9
- package/Title/types.ts +16 -48
- package/code-scanner.js +125 -16
- package/index.ts +7 -0
- package/migrate_typo.js +56 -0
- package/package.json +11 -10
- package/publish.sh +16 -21
- package/tsconfig.json +1 -1
- package/verify.js +37 -40
package/Input/InputMoney.tsx
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import React, {
|
|
2
2
|
forwardRef,
|
|
3
|
+
ReactNode,
|
|
3
4
|
useContext,
|
|
5
|
+
useEffect,
|
|
4
6
|
useImperativeHandle,
|
|
5
7
|
useRef,
|
|
6
8
|
useState,
|
|
@@ -12,12 +14,14 @@ import {
|
|
|
12
14
|
TouchableOpacity,
|
|
13
15
|
View,
|
|
14
16
|
} from 'react-native';
|
|
15
|
-
import {ApplicationContext} from '../Application';
|
|
16
|
-
import
|
|
17
|
+
import {ApplicationContext, ComponentContext} from '../Application';
|
|
18
|
+
import {Icon} from '../Icon';
|
|
17
19
|
import {ErrorView, FloatingView, getBorderColor, getSizeStyle} from './common';
|
|
18
20
|
import {InputMoneyProps} from './index';
|
|
19
|
-
import
|
|
21
|
+
import styles from './styles';
|
|
20
22
|
import {formatMoneyToNumber, formatNumberToMoney} from './utils';
|
|
23
|
+
import {Text} from '../Text';
|
|
24
|
+
import {Loader} from '../Loader';
|
|
21
25
|
|
|
22
26
|
const InputMoney = forwardRef(
|
|
23
27
|
(
|
|
@@ -26,24 +30,41 @@ const InputMoney = forwardRef(
|
|
|
26
30
|
floatingValue,
|
|
27
31
|
floatingIcon,
|
|
28
32
|
size = 'small',
|
|
33
|
+
loading,
|
|
29
34
|
onBlur,
|
|
30
35
|
onFocus,
|
|
31
36
|
errorMessage,
|
|
32
37
|
icon,
|
|
38
|
+
iconColor,
|
|
39
|
+
onPressIcon,
|
|
40
|
+
trailing,
|
|
41
|
+
trailingColor,
|
|
42
|
+
onPressTrailing,
|
|
33
43
|
disabled = false,
|
|
34
44
|
floatingIconColor,
|
|
35
|
-
iconColor,
|
|
36
45
|
required = false,
|
|
37
46
|
errorSpacing,
|
|
38
47
|
style,
|
|
48
|
+
params,
|
|
39
49
|
defaultValue = '',
|
|
50
|
+
accessibilityLabel,
|
|
51
|
+
hintText,
|
|
52
|
+
value: _value,
|
|
53
|
+
onPressFloatingIcon,
|
|
40
54
|
...props
|
|
41
55
|
}: InputMoneyProps,
|
|
42
|
-
ref
|
|
56
|
+
ref
|
|
43
57
|
) => {
|
|
44
58
|
const {theme} = useContext(ApplicationContext);
|
|
45
59
|
const [focused, setFocused] = useState(false);
|
|
46
|
-
const inputRef =
|
|
60
|
+
const inputRef = useRef<TextInput>(null);
|
|
61
|
+
|
|
62
|
+
useEffect(() => {
|
|
63
|
+
if (_value) {
|
|
64
|
+
setValue(validateText(_value));
|
|
65
|
+
onChangeText?.(formatMoneyToNumber(_value, 'đ').toString());
|
|
66
|
+
}
|
|
67
|
+
}, [_value]);
|
|
47
68
|
|
|
48
69
|
const validateText = (text: string) => {
|
|
49
70
|
const valueFormat = formatMoneyToNumber(text, 'đ');
|
|
@@ -51,7 +72,7 @@ const InputMoney = forwardRef(
|
|
|
51
72
|
};
|
|
52
73
|
|
|
53
74
|
const [value, setValue] = useState(
|
|
54
|
-
defaultValue ? validateText(defaultValue) : ''
|
|
75
|
+
defaultValue ? validateText(defaultValue) : ''
|
|
55
76
|
);
|
|
56
77
|
|
|
57
78
|
const onClearText = () => {
|
|
@@ -70,6 +91,9 @@ const InputMoney = forwardRef(
|
|
|
70
91
|
|
|
71
92
|
useImperativeHandle(ref, () => {
|
|
72
93
|
return {
|
|
94
|
+
clear: onClearText,
|
|
95
|
+
focus: () => inputRef.current?.focus(),
|
|
96
|
+
blur: () => inputRef.current?.blur(),
|
|
73
97
|
setText: _onChangeText,
|
|
74
98
|
};
|
|
75
99
|
});
|
|
@@ -84,11 +108,51 @@ const InputMoney = forwardRef(
|
|
|
84
108
|
onBlur?.(e);
|
|
85
109
|
};
|
|
86
110
|
|
|
111
|
+
/**
|
|
112
|
+
* Render trailing icon or text
|
|
113
|
+
* @param color
|
|
114
|
+
*/
|
|
115
|
+
const renderTrailing = (color?: string) => {
|
|
116
|
+
if (loading) {
|
|
117
|
+
return <Loader type={'spinner'} color={color} style={styles.icon} />;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
if (icon || trailing) {
|
|
121
|
+
const renderIconTouchable = (icon: ReactNode) => {
|
|
122
|
+
return (
|
|
123
|
+
<TouchableOpacity
|
|
124
|
+
onPress={onPressTrailing ?? onPressIcon}
|
|
125
|
+
style={styles.icon}>
|
|
126
|
+
{icon}
|
|
127
|
+
</TouchableOpacity>
|
|
128
|
+
);
|
|
129
|
+
};
|
|
130
|
+
const trailingValue = icon || trailing;
|
|
131
|
+
if (trailingValue?.includes('_') || trailingValue?.includes('http')) {
|
|
132
|
+
return renderIconTouchable(
|
|
133
|
+
<Icon
|
|
134
|
+
color={color}
|
|
135
|
+
source={(icon || trailing) as string}
|
|
136
|
+
size={24}
|
|
137
|
+
/>
|
|
138
|
+
);
|
|
139
|
+
}
|
|
140
|
+
return renderIconTouchable(
|
|
141
|
+
<Text
|
|
142
|
+
typography="action_xs_bold"
|
|
143
|
+
color={color ?? theme.colors.primary}
|
|
144
|
+
numberOfLines={1}>
|
|
145
|
+
{trailingValue!.substring(0, 15)}
|
|
146
|
+
</Text>
|
|
147
|
+
);
|
|
148
|
+
}
|
|
149
|
+
};
|
|
150
|
+
|
|
87
151
|
const renderInputView = () => {
|
|
88
152
|
const disabledColor = theme.colors.text.disable;
|
|
89
153
|
let textColor = theme.colors.text.default;
|
|
90
154
|
let placeholderColor = theme.colors.text.hint;
|
|
91
|
-
let iconTintColor = iconColor;
|
|
155
|
+
let iconTintColor = trailingColor ?? iconColor;
|
|
92
156
|
|
|
93
157
|
if (disabled) {
|
|
94
158
|
textColor = disabledColor;
|
|
@@ -110,12 +174,13 @@ const InputMoney = forwardRef(
|
|
|
110
174
|
disabled={disabled}
|
|
111
175
|
required={required}
|
|
112
176
|
floatingIcon={floatingIcon}
|
|
177
|
+
onPress={onPressFloatingIcon}
|
|
113
178
|
/>
|
|
114
179
|
<View style={styles.inputView}>
|
|
115
180
|
<TextInput
|
|
116
181
|
{...props}
|
|
182
|
+
accessibilityLabel={accessibilityLabel}
|
|
117
183
|
editable={!disabled}
|
|
118
|
-
textAlignVertical="top"
|
|
119
184
|
ref={inputRef}
|
|
120
185
|
keyboardType={'number-pad'}
|
|
121
186
|
style={[
|
|
@@ -145,19 +210,45 @@ const InputMoney = forwardRef(
|
|
|
145
210
|
/>
|
|
146
211
|
</TouchableOpacity>
|
|
147
212
|
)}
|
|
148
|
-
{
|
|
213
|
+
{renderTrailing(iconTintColor)}
|
|
149
214
|
</View>
|
|
150
215
|
</View>
|
|
151
216
|
);
|
|
152
217
|
};
|
|
153
218
|
|
|
219
|
+
let inputState = 'active';
|
|
220
|
+
|
|
221
|
+
if (value && value?.length > 0) {
|
|
222
|
+
inputState = 'filled';
|
|
223
|
+
}
|
|
224
|
+
if (errorMessage && errorMessage?.length > 0) {
|
|
225
|
+
inputState = 'error';
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
if (disabled) {
|
|
229
|
+
inputState = 'disabled';
|
|
230
|
+
}
|
|
231
|
+
|
|
154
232
|
return (
|
|
155
|
-
<
|
|
156
|
-
{
|
|
157
|
-
|
|
158
|
-
|
|
233
|
+
<ComponentContext.Provider
|
|
234
|
+
value={{
|
|
235
|
+
componentName: 'InputMoney',
|
|
236
|
+
params,
|
|
237
|
+
componentLabel: floatingValue,
|
|
238
|
+
state: inputState,
|
|
239
|
+
componentId: accessibilityLabel,
|
|
240
|
+
}}>
|
|
241
|
+
<View style={[style, styles.wrapper]}>
|
|
242
|
+
{renderInputView()}
|
|
243
|
+
<ErrorView
|
|
244
|
+
errorMessage={errorMessage}
|
|
245
|
+
errorSpacing={errorSpacing}
|
|
246
|
+
hintText={hintText}
|
|
247
|
+
/>
|
|
248
|
+
</View>
|
|
249
|
+
</ComponentContext.Provider>
|
|
159
250
|
);
|
|
160
|
-
}
|
|
251
|
+
}
|
|
161
252
|
);
|
|
162
253
|
|
|
163
254
|
export default InputMoney;
|
package/Input/InputOTP.tsx
CHANGED
|
@@ -15,12 +15,12 @@ import {
|
|
|
15
15
|
TouchableOpacity,
|
|
16
16
|
View,
|
|
17
17
|
} from 'react-native';
|
|
18
|
-
import {
|
|
18
|
+
import {ApplicationContext, ComponentContext} from '../Application';
|
|
19
|
+
import {Spacing} from '../Consts';
|
|
19
20
|
import {scaleSize, Text} from '../Text';
|
|
20
|
-
import styles from './styles';
|
|
21
21
|
import {ErrorView, getBorderColor} from './common';
|
|
22
|
-
import {
|
|
23
|
-
import
|
|
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;
|
|
@@ -41,7 +41,7 @@ const OTPCaret: FC<CaretProps> = ({index, length}) => {
|
|
|
41
41
|
duration: DURATION,
|
|
42
42
|
useNativeDriver: true,
|
|
43
43
|
}),
|
|
44
|
-
])
|
|
44
|
+
])
|
|
45
45
|
).start();
|
|
46
46
|
}, []);
|
|
47
47
|
const spacingStyle = !isNaN(Number(length)) &&
|
|
@@ -70,29 +70,36 @@ const InputOTP = forwardRef(
|
|
|
70
70
|
length,
|
|
71
71
|
errorMessage,
|
|
72
72
|
errorSpacing,
|
|
73
|
-
floatingValue,
|
|
74
|
-
floatingIconColor,
|
|
75
|
-
floatingIcon,
|
|
73
|
+
floatingValue = 'Label',
|
|
76
74
|
placeholder,
|
|
77
75
|
onChangeText,
|
|
78
|
-
onFocus,
|
|
79
76
|
onBlur,
|
|
77
|
+
onFocus,
|
|
80
78
|
dataType = 'number',
|
|
79
|
+
params,
|
|
81
80
|
style,
|
|
81
|
+
accessibilityLabel,
|
|
82
|
+
hintText,
|
|
82
83
|
...props
|
|
83
84
|
}: InputOTPProps,
|
|
84
|
-
ref
|
|
85
|
+
ref
|
|
85
86
|
) => {
|
|
86
87
|
const MAX_LENGTH = 10;
|
|
87
88
|
const [value, setValue] = useState('');
|
|
88
89
|
const [focused, setFocused] = useState(false);
|
|
89
|
-
const inputRef = useRef<TextInput>(null);
|
|
90
|
+
const inputRef = useRef<TextInput | null>(null);
|
|
90
91
|
const {theme} = useContext(ApplicationContext);
|
|
91
92
|
|
|
92
93
|
useImperativeHandle(ref, () => ({
|
|
93
94
|
onChangeText: (text: string) => {
|
|
94
95
|
_onChangeText(text);
|
|
95
96
|
},
|
|
97
|
+
focus: () => {
|
|
98
|
+
setFocused(true);
|
|
99
|
+
inputRef.current?.focus()
|
|
100
|
+
},
|
|
101
|
+
blur: () => inputRef.current?.blur(),
|
|
102
|
+
setText: (text: string) => _onChangeText(text),
|
|
96
103
|
}));
|
|
97
104
|
|
|
98
105
|
const onFocusInput = () => {
|
|
@@ -119,16 +126,16 @@ const InputOTP = forwardRef(
|
|
|
119
126
|
onChangeText?.(text);
|
|
120
127
|
};
|
|
121
128
|
|
|
122
|
-
const renderInputs = (
|
|
129
|
+
const renderInputs = (inputLength: number) => {
|
|
123
130
|
const TextInputs: React.ReactNode[] = [];
|
|
124
|
-
for (let i = 0; i <
|
|
131
|
+
for (let i = 0; i < inputLength; i++) {
|
|
125
132
|
TextInputs.push(
|
|
126
133
|
<View>
|
|
127
134
|
{focused && value.length === i ? (
|
|
128
|
-
<OTPCaret index={i} length={
|
|
135
|
+
<OTPCaret index={i} length={inputLength} />
|
|
129
136
|
) : (
|
|
130
137
|
<Text
|
|
131
|
-
style={i !==
|
|
138
|
+
style={i !== inputLength - 1 && {marginRight: Spacing.L}}
|
|
132
139
|
color={
|
|
133
140
|
!!value[i]
|
|
134
141
|
? theme.colors.text.default
|
|
@@ -140,7 +147,7 @@ const InputOTP = forwardRef(
|
|
|
140
147
|
{value[i] || '-'}
|
|
141
148
|
</Text>
|
|
142
149
|
)}
|
|
143
|
-
</View
|
|
150
|
+
</View>
|
|
144
151
|
);
|
|
145
152
|
}
|
|
146
153
|
return TextInputs;
|
|
@@ -194,7 +201,9 @@ const InputOTP = forwardRef(
|
|
|
194
201
|
styles.otpFloatingView,
|
|
195
202
|
{backgroundColor: theme.colors.background.surface},
|
|
196
203
|
]}>
|
|
197
|
-
<Text
|
|
204
|
+
<Text
|
|
205
|
+
typography={'description_default_regular'}
|
|
206
|
+
color={theme.colors.text.hint}>
|
|
198
207
|
{floatingValue}
|
|
199
208
|
</Text>
|
|
200
209
|
</View>
|
|
@@ -205,11 +214,12 @@ const InputOTP = forwardRef(
|
|
|
205
214
|
<View style={styles.inputView}>
|
|
206
215
|
<TextInput
|
|
207
216
|
{...props}
|
|
217
|
+
accessibilityLabel={accessibilityLabel}
|
|
208
218
|
ref={inputRef}
|
|
209
219
|
value={value}
|
|
210
220
|
onChangeText={_onChangeText}
|
|
211
221
|
keyboardType={dataType === 'number' ? 'number-pad' : 'default'}
|
|
212
|
-
onFocus={
|
|
222
|
+
onFocus={onFocus}
|
|
213
223
|
onBlur={onBlurInput}
|
|
214
224
|
style={{opacity: 0}}
|
|
215
225
|
selectionColor={theme.colors.primary}
|
|
@@ -221,15 +231,28 @@ const InputOTP = forwardRef(
|
|
|
221
231
|
};
|
|
222
232
|
|
|
223
233
|
return (
|
|
224
|
-
<
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
234
|
+
<ComponentContext.Provider
|
|
235
|
+
value={{
|
|
236
|
+
componentName: 'InputOTP',
|
|
237
|
+
params,
|
|
238
|
+
componentLabel: floatingValue,
|
|
239
|
+
state: 'enabled',
|
|
240
|
+
componentId: accessibilityLabel,
|
|
241
|
+
}}>
|
|
242
|
+
<TouchableOpacity
|
|
243
|
+
activeOpacity={1}
|
|
244
|
+
onPress={onFocusInput}
|
|
245
|
+
style={[style, styles.otpWrapper]}>
|
|
246
|
+
{renderInputView()}
|
|
247
|
+
<ErrorView
|
|
248
|
+
errorMessage={errorMessage}
|
|
249
|
+
errorSpacing={errorSpacing}
|
|
250
|
+
hintText={hintText}
|
|
251
|
+
/>
|
|
252
|
+
</TouchableOpacity>
|
|
253
|
+
</ComponentContext.Provider>
|
|
231
254
|
);
|
|
232
|
-
}
|
|
255
|
+
}
|
|
233
256
|
);
|
|
234
257
|
|
|
235
258
|
export default InputOTP;
|