@momo-kits/foundation 0.81.52 → 0.81.53-beta.0
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} +43 -18
- package/Application/Components.tsx +71 -53
- package/Application/ModalScreen.tsx +12 -183
- package/Application/Navigation.ts +2 -2
- package/Application/NavigationContainer.tsx +54 -53
- package/Application/Navigator.ts +53 -35
- package/Application/StackScreen.tsx +225 -30
- package/Application/index.ts +8 -12
- package/Application/types.ts +45 -27
- package/Application/utils.tsx +19 -15
- package/Assets/icon_bank.json +1 -1
- package/Badge/Badge.tsx +1 -1
- package/Button/index.tsx +44 -25
- 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 +45 -22
- package/Input/InputSearch.tsx +92 -44
- package/Input/InputTextArea.tsx +26 -6
- package/Input/common.tsx +48 -22
- package/Input/index.tsx +94 -77
- package/Input/styles.ts +35 -5
- 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 +87 -49
- package/Layout/Section.tsx +4 -3
- package/Layout/styles.ts +11 -7
- package/Layout/utils.ts +4 -4
- package/Loader/index.tsx +2 -0
- package/Popup/PopupNotify.tsx +55 -44
- 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/styles.ts +3 -2
- package/Text/index.tsx +24 -5
- package/Text/styles.ts +8 -8
- 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/package.json +6 -6
- package/publish.sh +16 -21
- package/tsconfig.json +1 -1
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;
|
|
@@ -70,15 +70,16 @@ 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
85
|
ref,
|
|
@@ -86,13 +87,19 @@ const InputOTP = forwardRef(
|
|
|
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
|
|
@@ -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,13 +231,26 @@ 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
|
);
|
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,12 +12,13 @@ import {
|
|
|
6
12
|
TouchableOpacity,
|
|
7
13
|
View,
|
|
8
14
|
} from 'react-native';
|
|
9
|
-
import {
|
|
10
|
-
import {ApplicationContext} from '../Application';
|
|
11
|
-
import styles from './styles';
|
|
15
|
+
import {ApplicationContext, ComponentContext} from '../Application';
|
|
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';
|
|
21
|
+
import {Styles} from '../Consts';
|
|
15
22
|
|
|
16
23
|
const InputSearch = forwardRef(
|
|
17
24
|
(
|
|
@@ -19,24 +26,30 @@ const InputSearch = forwardRef(
|
|
|
19
26
|
placeholder,
|
|
20
27
|
onFocus,
|
|
21
28
|
onBlur,
|
|
22
|
-
iconColor,
|
|
23
29
|
value,
|
|
24
|
-
onChangeText,
|
|
25
30
|
icon,
|
|
31
|
+
iconColor,
|
|
32
|
+
onPressIcon,
|
|
33
|
+
trailing,
|
|
34
|
+
trailingColor,
|
|
35
|
+
onPressTrailing,
|
|
36
|
+
onChangeText,
|
|
26
37
|
buttonText = 'Hủy',
|
|
27
38
|
showButtonText = true,
|
|
28
39
|
style,
|
|
29
40
|
defaultValue,
|
|
30
41
|
onPressButtonText,
|
|
31
|
-
|
|
42
|
+
params,
|
|
43
|
+
hasColorBG = false,
|
|
44
|
+
accessibilityLabel,
|
|
32
45
|
...props
|
|
33
46
|
}: InputSearchProps,
|
|
34
|
-
ref
|
|
47
|
+
ref
|
|
35
48
|
) => {
|
|
36
49
|
const {theme} = useContext(ApplicationContext);
|
|
37
50
|
const [focused, setFocused] = useState(false);
|
|
38
51
|
const [haveValue, setHaveValue] = useState(!!value || !!defaultValue);
|
|
39
|
-
const inputRef =
|
|
52
|
+
const inputRef = useRef<TextInput | null>(null);
|
|
40
53
|
|
|
41
54
|
const _onFocus = (e: NativeSyntheticEvent<TextInputFocusEventData>) => {
|
|
42
55
|
setFocused(true);
|
|
@@ -58,10 +71,23 @@ const InputSearch = forwardRef(
|
|
|
58
71
|
onChangeText?.(text);
|
|
59
72
|
};
|
|
60
73
|
|
|
74
|
+
useImperativeHandle(ref, () => {
|
|
75
|
+
return {
|
|
76
|
+
clear: onClearText,
|
|
77
|
+
focus: () => inputRef.current?.focus(),
|
|
78
|
+
blur: () => inputRef.current?.blur(),
|
|
79
|
+
setText: (text: string) => _onChangeText(text),
|
|
80
|
+
};
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Render the input view
|
|
85
|
+
*/
|
|
61
86
|
const renderInputView = () => {
|
|
62
87
|
return (
|
|
63
88
|
<TextInput
|
|
64
89
|
{...props}
|
|
90
|
+
accessibilityLabel={accessibilityLabel}
|
|
65
91
|
textAlignVertical="center"
|
|
66
92
|
ref={inputRef}
|
|
67
93
|
style={[
|
|
@@ -81,12 +107,12 @@ const InputSearch = forwardRef(
|
|
|
81
107
|
);
|
|
82
108
|
};
|
|
83
109
|
|
|
84
|
-
|
|
110
|
+
/**
|
|
111
|
+
* Render trailing icon or text
|
|
112
|
+
*/
|
|
113
|
+
const renderTrailing = () => {
|
|
85
114
|
return (
|
|
86
|
-
<View
|
|
87
|
-
style={{
|
|
88
|
-
flexDirection: 'row',
|
|
89
|
-
}}>
|
|
115
|
+
<View style={Styles.row}>
|
|
90
116
|
{focused && haveValue && (
|
|
91
117
|
<TouchableOpacity style={styles.iconWrapper} onPress={onClearText}>
|
|
92
118
|
<Icon
|
|
@@ -96,8 +122,10 @@ const InputSearch = forwardRef(
|
|
|
96
122
|
/>
|
|
97
123
|
</TouchableOpacity>
|
|
98
124
|
)}
|
|
99
|
-
{!!icon && (
|
|
100
|
-
<
|
|
125
|
+
{!!(icon || trailing) && (
|
|
126
|
+
<TouchableOpacity
|
|
127
|
+
style={Styles.row}
|
|
128
|
+
onPress={onPressTrailing ?? onPressIcon}>
|
|
101
129
|
<View
|
|
102
130
|
style={[
|
|
103
131
|
styles.divider,
|
|
@@ -107,45 +135,65 @@ const InputSearch = forwardRef(
|
|
|
107
135
|
]}
|
|
108
136
|
/>
|
|
109
137
|
<Icon
|
|
110
|
-
color={iconColor}
|
|
111
|
-
source={icon}
|
|
138
|
+
color={iconColor || trailingColor}
|
|
139
|
+
source={(icon || trailing) as string}
|
|
112
140
|
style={styles.iconSearchInput}
|
|
113
141
|
/>
|
|
114
|
-
</
|
|
142
|
+
</TouchableOpacity>
|
|
115
143
|
)}
|
|
116
144
|
</View>
|
|
117
145
|
);
|
|
118
146
|
};
|
|
119
147
|
|
|
120
|
-
|
|
148
|
+
let inputState = 'empty';
|
|
149
|
+
if (focused) {
|
|
150
|
+
inputState = 'focus';
|
|
151
|
+
}
|
|
152
|
+
if (value && value?.length > 0) {
|
|
153
|
+
inputState = 'filled';
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
const backgroundColor = hasColorBG
|
|
157
|
+
? theme.colors.background.default
|
|
158
|
+
: theme.colors.background.surface;
|
|
121
159
|
|
|
122
160
|
return (
|
|
123
|
-
<
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
<
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
161
|
+
<ComponentContext.Provider
|
|
162
|
+
value={{
|
|
163
|
+
componentName: 'InputSearch',
|
|
164
|
+
params,
|
|
165
|
+
state: inputState,
|
|
166
|
+
componentId: accessibilityLabel,
|
|
167
|
+
}}>
|
|
168
|
+
<View style={[style, styles.searchInputContainer]}>
|
|
169
|
+
<View
|
|
170
|
+
style={[
|
|
171
|
+
styles.searchInputWrapper,
|
|
172
|
+
{
|
|
173
|
+
backgroundColor,
|
|
174
|
+
},
|
|
175
|
+
]}>
|
|
176
|
+
<Icon
|
|
177
|
+
source={'navigation_search'}
|
|
178
|
+
size={24}
|
|
179
|
+
color={theme.colors.text.hint}
|
|
180
|
+
/>
|
|
181
|
+
{renderInputView()}
|
|
182
|
+
{renderTrailing()}
|
|
183
|
+
</View>
|
|
184
|
+
{showButtonText && (
|
|
185
|
+
<TouchableOpacity onPress={onPressButtonText}>
|
|
186
|
+
<Text
|
|
187
|
+
typography={'action_default_bold'}
|
|
188
|
+
style={styles.textButton}>
|
|
189
|
+
{buttonText}
|
|
190
|
+
</Text>
|
|
191
|
+
</TouchableOpacity>
|
|
192
|
+
)}
|
|
138
193
|
</View>
|
|
139
|
-
|
|
140
|
-
<TouchableOpacity onPress={onPressButtonText}>
|
|
141
|
-
<Text typography={'action_default_bold'} style={styles.textButton}>
|
|
142
|
-
{buttonText}
|
|
143
|
-
</Text>
|
|
144
|
-
</TouchableOpacity>
|
|
145
|
-
)}
|
|
146
|
-
</View>
|
|
194
|
+
</ComponentContext.Provider>
|
|
147
195
|
);
|
|
148
|
-
}
|
|
196
|
+
}
|
|
149
197
|
);
|
|
150
198
|
|
|
151
199
|
export default InputSearch;
|
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
|
(
|
|
@@ -38,6 +44,7 @@ const InputTextArea = forwardRef(
|
|
|
38
44
|
required,
|
|
39
45
|
errorSpacing,
|
|
40
46
|
style,
|
|
47
|
+
hintText,
|
|
41
48
|
...props
|
|
42
49
|
}: InputTextAreaProps,
|
|
43
50
|
ref,
|
|
@@ -45,7 +52,7 @@ const InputTextArea = forwardRef(
|
|
|
45
52
|
const {theme} = useContext(ApplicationContext);
|
|
46
53
|
const [focused, setFocused] = useState(false);
|
|
47
54
|
const [inputValue, setInputValue] = useState(defaultValue ?? '');
|
|
48
|
-
const inputRef =
|
|
55
|
+
const inputRef = useRef<TextInput | null>(null);
|
|
49
56
|
|
|
50
57
|
const onClearText = () => {
|
|
51
58
|
inputRef?.current?.clear();
|
|
@@ -67,6 +74,15 @@ const InputTextArea = forwardRef(
|
|
|
67
74
|
onBlur?.(e);
|
|
68
75
|
};
|
|
69
76
|
|
|
77
|
+
useImperativeHandle(ref, () => {
|
|
78
|
+
return {
|
|
79
|
+
clear: onClearText,
|
|
80
|
+
focus: () => inputRef.current?.focus(),
|
|
81
|
+
blur: () => inputRef.current?.blur(),
|
|
82
|
+
setText: (text: string) => _onChangeText(text),
|
|
83
|
+
};
|
|
84
|
+
});
|
|
85
|
+
|
|
70
86
|
const renderCountingView = () => {
|
|
71
87
|
return (
|
|
72
88
|
<View style={styles.countingView}>
|
|
@@ -150,7 +166,11 @@ const InputTextArea = forwardRef(
|
|
|
150
166
|
return (
|
|
151
167
|
<View style={[style, styles.wrapper]}>
|
|
152
168
|
{renderInputView()}
|
|
153
|
-
<ErrorView
|
|
169
|
+
<ErrorView
|
|
170
|
+
errorMessage={errorMessage}
|
|
171
|
+
errorSpacing={errorSpacing}
|
|
172
|
+
hintText={hintText}
|
|
173
|
+
/>
|
|
154
174
|
</View>
|
|
155
175
|
);
|
|
156
176
|
},
|
package/Input/common.tsx
CHANGED
|
@@ -1,11 +1,16 @@
|
|
|
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 {
|
|
3
|
+
GestureResponderEvent,
|
|
4
|
+
TouchableOpacity,
|
|
5
|
+
View,
|
|
6
|
+
ViewStyle,
|
|
7
|
+
} from 'react-native';
|
|
5
8
|
import {ApplicationContext} from '../Application';
|
|
6
|
-
import {Icon} from '../Icon';
|
|
7
|
-
import {Styles} from '../Consts';
|
|
8
9
|
import {Theme} from '../Application/types';
|
|
10
|
+
import {Styles} from '../Consts';
|
|
11
|
+
import {Icon} from '../Icon';
|
|
12
|
+
import {scaleSize, Text} from '../Text';
|
|
13
|
+
import styles from './styles';
|
|
9
14
|
|
|
10
15
|
type FloatingViewProps = {
|
|
11
16
|
floatingValue?: string;
|
|
@@ -14,6 +19,7 @@ type FloatingViewProps = {
|
|
|
14
19
|
floatingIcon?: string;
|
|
15
20
|
required?: boolean;
|
|
16
21
|
style?: ViewStyle;
|
|
22
|
+
onPress?: (e: GestureResponderEvent) => void;
|
|
17
23
|
};
|
|
18
24
|
|
|
19
25
|
export const DEFAULT_HEIGHT = scaleSize(104);
|
|
@@ -23,7 +29,7 @@ export const getBorderColor = (
|
|
|
23
29
|
theme: Theme,
|
|
24
30
|
focused: boolean,
|
|
25
31
|
errorMessage?: string,
|
|
26
|
-
disabled?: boolean
|
|
32
|
+
disabled?: boolean
|
|
27
33
|
) => {
|
|
28
34
|
let borderColor = theme.colors.border.default;
|
|
29
35
|
|
|
@@ -42,30 +48,47 @@ export const getBorderColor = (
|
|
|
42
48
|
return {borderColor};
|
|
43
49
|
};
|
|
44
50
|
|
|
45
|
-
export const getSizeStyle = (
|
|
51
|
+
export const getSizeStyle = (
|
|
52
|
+
size?: 'small' | 'large',
|
|
53
|
+
multiline: boolean = false
|
|
54
|
+
) => {
|
|
55
|
+
if (multiline)
|
|
56
|
+
return [
|
|
57
|
+
styles.multilineContainer,
|
|
58
|
+
{
|
|
59
|
+
minHeight: size === 'small' ? 48 : 56,
|
|
60
|
+
},
|
|
61
|
+
];
|
|
62
|
+
|
|
46
63
|
if (size === 'small') {
|
|
47
64
|
return styles.smallContainer;
|
|
48
65
|
}
|
|
49
66
|
return styles.container;
|
|
50
67
|
};
|
|
51
|
-
export const ErrorView: FC<{
|
|
52
|
-
errorMessage
|
|
53
|
-
errorSpacing
|
|
54
|
-
|
|
68
|
+
export const ErrorView: FC<{
|
|
69
|
+
errorMessage?: string;
|
|
70
|
+
errorSpacing?: boolean;
|
|
71
|
+
hintText?: string;
|
|
72
|
+
}> = ({errorMessage, errorSpacing, hintText}) => {
|
|
55
73
|
const {theme} = useContext(ApplicationContext);
|
|
56
74
|
const errorColor = theme.colors.error.primary;
|
|
57
|
-
|
|
75
|
+
const hintColor = theme.colors.text.hint;
|
|
76
|
+
const hintTextDefault = hintText ?? 'Không thể chỉnh sửa';
|
|
77
|
+
if (errorMessage || hintText) {
|
|
58
78
|
return (
|
|
59
79
|
<View style={styles.errorView}>
|
|
60
80
|
<View style={styles.errorIcon}>
|
|
61
|
-
<Icon
|
|
81
|
+
<Icon
|
|
82
|
+
color={errorMessage ? errorColor : hintColor}
|
|
83
|
+
source="ic_error"
|
|
84
|
+
size={16}
|
|
85
|
+
/>
|
|
62
86
|
</View>
|
|
63
87
|
<Text
|
|
64
88
|
style={Styles.flex}
|
|
65
|
-
color={errorColor}
|
|
66
|
-
numberOfLines={2}
|
|
89
|
+
color={errorMessage ? errorColor : hintColor}
|
|
67
90
|
typography={'description_default_regular'}>
|
|
68
|
-
{errorMessage}
|
|
91
|
+
{errorMessage ?? hintTextDefault}
|
|
69
92
|
</Text>
|
|
70
93
|
</View>
|
|
71
94
|
);
|
|
@@ -83,6 +106,7 @@ export const FloatingView: FC<FloatingViewProps> = ({
|
|
|
83
106
|
floatingIcon,
|
|
84
107
|
required,
|
|
85
108
|
style,
|
|
109
|
+
onPress,
|
|
86
110
|
}) => {
|
|
87
111
|
const {theme} = useContext(ApplicationContext);
|
|
88
112
|
|
|
@@ -115,12 +139,14 @@ export const FloatingView: FC<FloatingViewProps> = ({
|
|
|
115
139
|
)}
|
|
116
140
|
</Text>
|
|
117
141
|
{!!floatingIcon && (
|
|
118
|
-
<
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
142
|
+
<TouchableOpacity activeOpacity={onPress ? 0.6 : 1} onPress={onPress}>
|
|
143
|
+
<Icon
|
|
144
|
+
color={floatingIconTintColor}
|
|
145
|
+
source={floatingIcon}
|
|
146
|
+
size={16}
|
|
147
|
+
style={styles.floatingIcon}
|
|
148
|
+
/>
|
|
149
|
+
</TouchableOpacity>
|
|
124
150
|
)}
|
|
125
151
|
</View>
|
|
126
152
|
);
|