@momo-kits/foundation 0.75.1-beta.10
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/Assets/header-background.png +0 -0
- package/Assets/icon.json +3947 -0
- package/Button/index.tsx +278 -0
- package/Button/styles.ts +41 -0
- package/CheckBox/index.tsx +61 -0
- package/CheckBox/styles.ts +15 -0
- package/CheckBox/types.ts +38 -0
- package/Consts/colors+spacing+radius.ts +214 -0
- package/Consts/index.ts +4 -0
- package/Consts/styles.ts +78 -0
- package/Consts/theme.ts +121 -0
- package/Divider/index.tsx +19 -0
- package/Icon/index.tsx +37 -0
- package/Icon/types.ts +27 -0
- package/IconButton/index.tsx +140 -0
- package/IconButton/styles.ts +19 -0
- package/Image/index.tsx +80 -0
- package/Image/styles.ts +13 -0
- package/Image/types.ts +3 -0
- package/Input/Input.tsx +136 -0
- package/Input/InputMoney.tsx +132 -0
- package/Input/InputSearch.tsx +161 -0
- package/Input/InputTextArea.tsx +152 -0
- package/Input/common.tsx +118 -0
- package/Input/index.tsx +96 -0
- package/Input/styles.ts +122 -0
- package/Input/utils.ts +69 -0
- package/Layout/Card.tsx +141 -0
- package/Layout/GridSystem.tsx +124 -0
- package/Layout/Item.tsx +60 -0
- package/Layout/ScreenContainer.tsx +121 -0
- package/Layout/Section.tsx +141 -0
- package/Layout/index.ts +17 -0
- package/Layout/types.ts +59 -0
- package/Layout/utils.ts +60 -0
- package/Navigation/BottomTab.tsx +39 -0
- package/Navigation/Components.tsx +365 -0
- package/Navigation/ModalScreen.tsx +226 -0
- package/Navigation/Navigation.ts +44 -0
- package/Navigation/NavigationButton.tsx +54 -0
- package/Navigation/NavigationContainer.tsx +77 -0
- package/Navigation/Navigator.ts +82 -0
- package/Navigation/StackScreen.tsx +27 -0
- package/Navigation/index.ts +14 -0
- package/Navigation/types.ts +158 -0
- package/Navigation/utils.tsx +138 -0
- package/Pagination/Dot.tsx +16 -0
- package/Pagination/PaginationDot.tsx +33 -0
- package/Pagination/PaginationNumber.tsx +23 -0
- package/Pagination/PaginationScroll.tsx +88 -0
- package/Pagination/PaginationWhiteDot.tsx +32 -0
- package/Pagination/index.tsx +25 -0
- package/Pagination/styles.ts +47 -0
- package/Pagination/types.ts +38 -0
- package/Popup/PopupNotify.tsx +215 -0
- package/Popup/PopupPromotion.tsx +77 -0
- package/Popup/index.tsx +4 -0
- package/Popup/types.ts +70 -0
- package/Radio/index.tsx +65 -0
- package/Radio/styles.ts +11 -0
- package/Radio/types.ts +38 -0
- package/Skeleton/index.tsx +72 -0
- package/Skeleton/styles.ts +5 -0
- package/Skeleton/types.ts +3 -0
- package/Switch/index.tsx +40 -0
- package/Switch/styles.ts +23 -0
- package/Switch/types.ts +26 -0
- package/Tag/index.tsx +79 -0
- package/Tag/styles.ts +24 -0
- package/Tag/types.ts +36 -0
- package/Text/index.tsx +123 -0
- package/Text/styles.ts +35 -0
- package/Text/types.ts +40 -0
- package/index.ts +38 -0
- package/package.json +41 -0
- package/publish.sh +26 -0
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import React, {FC, useContext, useRef, useState} from 'react';
|
|
2
|
+
import {
|
|
3
|
+
NativeSyntheticEvent,
|
|
4
|
+
TextInput,
|
|
5
|
+
TextInputFocusEventData,
|
|
6
|
+
TouchableOpacity,
|
|
7
|
+
View,
|
|
8
|
+
} from 'react-native';
|
|
9
|
+
import {ApplicationContext} from '../Navigation';
|
|
10
|
+
import styles from './styles';
|
|
11
|
+
import {ErrorView, FloatingView, getBorderColor, getSizeStyle} from './common';
|
|
12
|
+
import {InputMoneyProps} from './index';
|
|
13
|
+
import {Icon} from '../Icon';
|
|
14
|
+
import {formatMoneyToNumber, formatNumberToMoney} from './utils';
|
|
15
|
+
|
|
16
|
+
const InputMoney: FC<InputMoneyProps> = ({
|
|
17
|
+
onChangeText,
|
|
18
|
+
floatingValue,
|
|
19
|
+
floatingIcon,
|
|
20
|
+
size = 'small',
|
|
21
|
+
onBlur,
|
|
22
|
+
onFocus,
|
|
23
|
+
errorMessage,
|
|
24
|
+
icon,
|
|
25
|
+
disabled,
|
|
26
|
+
floatingIconColor,
|
|
27
|
+
iconColor,
|
|
28
|
+
required,
|
|
29
|
+
...props
|
|
30
|
+
}) => {
|
|
31
|
+
const {theme} = useContext(ApplicationContext);
|
|
32
|
+
const [focused, setFocused] = useState(false);
|
|
33
|
+
const inputRef = useRef<any>(null);
|
|
34
|
+
const [value, setValue] = useState('');
|
|
35
|
+
const onClearText = () => {
|
|
36
|
+
inputRef?.current?.clear();
|
|
37
|
+
setValue('');
|
|
38
|
+
onChangeText?.('');
|
|
39
|
+
};
|
|
40
|
+
const _onChangeText = (text: string) => {
|
|
41
|
+
if (text.length < value.length && value.indexOf(text) === 0) {
|
|
42
|
+
text = value.slice(0, -2) + 'đ';
|
|
43
|
+
}
|
|
44
|
+
const valueFormat = formatMoneyToNumber(text, 'đ');
|
|
45
|
+
setValue(formatNumberToMoney(valueFormat, 'đ'));
|
|
46
|
+
onChangeText?.(formatMoneyToNumber(text, 'đ').toString());
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
const _onFocus = (e: NativeSyntheticEvent<TextInputFocusEventData>) => {
|
|
50
|
+
setFocused(true);
|
|
51
|
+
onFocus?.(e);
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
const _onBlur = (e: NativeSyntheticEvent<TextInputFocusEventData>) => {
|
|
55
|
+
setFocused(false);
|
|
56
|
+
onBlur?.(e);
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
const renderInputView = () => {
|
|
60
|
+
const disabledColor = theme.colors.text.disable;
|
|
61
|
+
let textColor = theme.colors.text.default;
|
|
62
|
+
let placeholderColor = theme.colors.text.hint;
|
|
63
|
+
let iconTintColor = iconColor;
|
|
64
|
+
|
|
65
|
+
if (disabled) {
|
|
66
|
+
textColor = disabledColor;
|
|
67
|
+
placeholderColor = disabledColor;
|
|
68
|
+
iconTintColor = disabledColor;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
return (
|
|
72
|
+
<View
|
|
73
|
+
style={[
|
|
74
|
+
getSizeStyle(size),
|
|
75
|
+
getBorderColor(focused, errorMessage, disabled),
|
|
76
|
+
styles.inputWrapper,
|
|
77
|
+
{backgroundColor: theme.colors.background.surface},
|
|
78
|
+
]}>
|
|
79
|
+
<FloatingView
|
|
80
|
+
floatingValue={floatingValue}
|
|
81
|
+
floatingIconColor={floatingIconColor}
|
|
82
|
+
disabled={disabled}
|
|
83
|
+
required={required}
|
|
84
|
+
floatingIcon={floatingIcon}
|
|
85
|
+
/>
|
|
86
|
+
<View style={styles.inputView}>
|
|
87
|
+
<TextInput
|
|
88
|
+
{...props}
|
|
89
|
+
editable={!disabled}
|
|
90
|
+
textAlignVertical="top"
|
|
91
|
+
ref={inputRef}
|
|
92
|
+
keyboardType={'number-pad'}
|
|
93
|
+
style={[
|
|
94
|
+
styles.moneyInput,
|
|
95
|
+
{
|
|
96
|
+
color: textColor,
|
|
97
|
+
},
|
|
98
|
+
]}
|
|
99
|
+
value={value}
|
|
100
|
+
onChangeText={_onChangeText}
|
|
101
|
+
onFocus={_onFocus}
|
|
102
|
+
onBlur={_onBlur}
|
|
103
|
+
selectionColor={theme.colors.primary}
|
|
104
|
+
placeholderTextColor={placeholderColor}
|
|
105
|
+
placeholder={'0đ'}
|
|
106
|
+
/>
|
|
107
|
+
</View>
|
|
108
|
+
<View style={styles.iconView}>
|
|
109
|
+
{focused && (
|
|
110
|
+
<TouchableOpacity style={styles.iconWrapper} onPress={onClearText}>
|
|
111
|
+
<Icon
|
|
112
|
+
source="24_navigation_close_circle_full"
|
|
113
|
+
size={16}
|
|
114
|
+
color={theme.colors.text.hint}
|
|
115
|
+
/>
|
|
116
|
+
</TouchableOpacity>
|
|
117
|
+
)}
|
|
118
|
+
{!!icon && <Icon color={iconTintColor} source={icon} />}
|
|
119
|
+
</View>
|
|
120
|
+
</View>
|
|
121
|
+
);
|
|
122
|
+
};
|
|
123
|
+
|
|
124
|
+
return (
|
|
125
|
+
<View style={styles.wrapper} accessibilityLabel={`InputMoney`}>
|
|
126
|
+
{renderInputView()}
|
|
127
|
+
<ErrorView errorMessage={errorMessage} />
|
|
128
|
+
</View>
|
|
129
|
+
);
|
|
130
|
+
};
|
|
131
|
+
|
|
132
|
+
export default InputMoney;
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
import React, {FC, useContext, useRef, useState} from 'react';
|
|
2
|
+
import {
|
|
3
|
+
NativeSyntheticEvent,
|
|
4
|
+
TextInput,
|
|
5
|
+
TextInputFocusEventData,
|
|
6
|
+
TouchableOpacity,
|
|
7
|
+
View,
|
|
8
|
+
} from 'react-native';
|
|
9
|
+
import {InputSearchProps} from './index';
|
|
10
|
+
import {ApplicationContext} from '../Navigation';
|
|
11
|
+
import styles from './styles';
|
|
12
|
+
import {Icon} from '../Icon';
|
|
13
|
+
import {Text} from '../Text';
|
|
14
|
+
import {checkTyping} from './utils';
|
|
15
|
+
|
|
16
|
+
const InputSearch: FC<InputSearchProps> = ({
|
|
17
|
+
placeholder,
|
|
18
|
+
onFocus,
|
|
19
|
+
onBlur,
|
|
20
|
+
iconColor,
|
|
21
|
+
value,
|
|
22
|
+
onChangeText,
|
|
23
|
+
icon,
|
|
24
|
+
buttonText = 'Hủy',
|
|
25
|
+
showButtonText = true,
|
|
26
|
+
showBorder = true,
|
|
27
|
+
style,
|
|
28
|
+
defaultValue,
|
|
29
|
+
...props
|
|
30
|
+
}) => {
|
|
31
|
+
const {theme} = useContext(ApplicationContext);
|
|
32
|
+
const [focused, setFocused] = useState(false);
|
|
33
|
+
const [haveValue, setHaveValue] = useState(!!value || !!defaultValue);
|
|
34
|
+
const inputRef = useRef<any>(null);
|
|
35
|
+
let iconTintColor = iconColor;
|
|
36
|
+
|
|
37
|
+
const _onFocus = (e: NativeSyntheticEvent<TextInputFocusEventData>) => {
|
|
38
|
+
setFocused(true);
|
|
39
|
+
onFocus?.(e);
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
const _onBlur = (e: NativeSyntheticEvent<TextInputFocusEventData>) => {
|
|
43
|
+
setFocused(false);
|
|
44
|
+
onBlur?.(e);
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
const onClearText = () => {
|
|
48
|
+
inputRef?.current?.clear();
|
|
49
|
+
_onChangeText('');
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
const _onChangeText = (text: string) => {
|
|
53
|
+
checkTyping(text, haveValue, setHaveValue);
|
|
54
|
+
onChangeText?.(text);
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
const getBorderColor = () => {
|
|
58
|
+
let borderColor = showBorder
|
|
59
|
+
? theme.colors.border.default
|
|
60
|
+
: theme.colors.background.surface;
|
|
61
|
+
|
|
62
|
+
if (focused) {
|
|
63
|
+
borderColor = theme.colors.primary;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
return {borderColor};
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
const renderInputView = () => {
|
|
70
|
+
let textColor = theme.colors.text.default;
|
|
71
|
+
let placeholderColor = theme.colors.text.hint;
|
|
72
|
+
|
|
73
|
+
return (
|
|
74
|
+
<TextInput
|
|
75
|
+
{...props}
|
|
76
|
+
textAlignVertical="top"
|
|
77
|
+
ref={inputRef}
|
|
78
|
+
style={[
|
|
79
|
+
styles.searchInput,
|
|
80
|
+
{
|
|
81
|
+
color: textColor,
|
|
82
|
+
},
|
|
83
|
+
]}
|
|
84
|
+
value={value}
|
|
85
|
+
onChangeText={_onChangeText}
|
|
86
|
+
onFocus={_onFocus}
|
|
87
|
+
onBlur={_onBlur}
|
|
88
|
+
placeholder={placeholder}
|
|
89
|
+
selectionColor={theme.colors.primary}
|
|
90
|
+
placeholderTextColor={placeholderColor}
|
|
91
|
+
/>
|
|
92
|
+
);
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
const renderIconView = () => {
|
|
96
|
+
return (
|
|
97
|
+
<View
|
|
98
|
+
style={{
|
|
99
|
+
flexDirection: 'row',
|
|
100
|
+
}}>
|
|
101
|
+
{focused && haveValue && (
|
|
102
|
+
<TouchableOpacity style={styles.iconWrapper} onPress={onClearText}>
|
|
103
|
+
<Icon
|
|
104
|
+
source="24_navigation_close_circle_full"
|
|
105
|
+
size={16}
|
|
106
|
+
color={theme.colors.text.hint}
|
|
107
|
+
/>
|
|
108
|
+
</TouchableOpacity>
|
|
109
|
+
)}
|
|
110
|
+
{!!icon && (
|
|
111
|
+
<View style={{flexDirection: 'row'}}>
|
|
112
|
+
<View
|
|
113
|
+
style={[
|
|
114
|
+
styles.divider,
|
|
115
|
+
{
|
|
116
|
+
backgroundColor: theme.colors.primary,
|
|
117
|
+
},
|
|
118
|
+
]}
|
|
119
|
+
/>
|
|
120
|
+
<Icon
|
|
121
|
+
color={iconTintColor}
|
|
122
|
+
source={icon}
|
|
123
|
+
style={styles.iconSearchInput}
|
|
124
|
+
/>
|
|
125
|
+
</View>
|
|
126
|
+
)}
|
|
127
|
+
</View>
|
|
128
|
+
);
|
|
129
|
+
};
|
|
130
|
+
return (
|
|
131
|
+
<View
|
|
132
|
+
style={[style, styles.searchInputContainer]}
|
|
133
|
+
accessibilityLabel={`InputSearch`}>
|
|
134
|
+
<View
|
|
135
|
+
style={[
|
|
136
|
+
getBorderColor(),
|
|
137
|
+
styles.searchInputWrapper,
|
|
138
|
+
{
|
|
139
|
+
backgroundColor: theme.colors.background.surface,
|
|
140
|
+
},
|
|
141
|
+
]}>
|
|
142
|
+
<Icon
|
|
143
|
+
source={'navigation_search'}
|
|
144
|
+
size={24}
|
|
145
|
+
color={theme.colors.text.hint}
|
|
146
|
+
/>
|
|
147
|
+
{renderInputView()}
|
|
148
|
+
{renderIconView()}
|
|
149
|
+
</View>
|
|
150
|
+
{showButtonText && (
|
|
151
|
+
<TouchableOpacity>
|
|
152
|
+
<Text typography={'action_default'} style={styles.textButton}>
|
|
153
|
+
{buttonText}
|
|
154
|
+
</Text>
|
|
155
|
+
</TouchableOpacity>
|
|
156
|
+
)}
|
|
157
|
+
</View>
|
|
158
|
+
);
|
|
159
|
+
};
|
|
160
|
+
|
|
161
|
+
export default InputSearch;
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
import React, {FC, useContext, useRef, useState} from 'react';
|
|
2
|
+
import {
|
|
3
|
+
NativeSyntheticEvent,
|
|
4
|
+
TextInput,
|
|
5
|
+
TextInputFocusEventData,
|
|
6
|
+
TouchableOpacity,
|
|
7
|
+
View,
|
|
8
|
+
} from 'react-native';
|
|
9
|
+
import styles from './styles';
|
|
10
|
+
import {Text} from '../Text';
|
|
11
|
+
import {ApplicationContext} from '../Navigation';
|
|
12
|
+
import {
|
|
13
|
+
DEFAULT_HEIGHT,
|
|
14
|
+
ErrorView,
|
|
15
|
+
FloatingView,
|
|
16
|
+
getBorderColor,
|
|
17
|
+
MAX_LENGTH,
|
|
18
|
+
} from './common';
|
|
19
|
+
import {InputTextAreaProps} from './index';
|
|
20
|
+
import {Icon} from '../Icon';
|
|
21
|
+
|
|
22
|
+
const InputTextArea: FC<InputTextAreaProps> = props => {
|
|
23
|
+
const {theme} = useContext(ApplicationContext);
|
|
24
|
+
const {
|
|
25
|
+
errorMessage,
|
|
26
|
+
onChangeText,
|
|
27
|
+
floatingIconColor,
|
|
28
|
+
floatingIcon,
|
|
29
|
+
floatingValue,
|
|
30
|
+
onFocus,
|
|
31
|
+
onBlur,
|
|
32
|
+
disabled,
|
|
33
|
+
value,
|
|
34
|
+
defaultValue,
|
|
35
|
+
height,
|
|
36
|
+
placeholder,
|
|
37
|
+
maxLength,
|
|
38
|
+
required,
|
|
39
|
+
} = props;
|
|
40
|
+
|
|
41
|
+
const [focused, setFocused] = useState(false);
|
|
42
|
+
const [inputValue, setInputValue] = useState(defaultValue ?? '');
|
|
43
|
+
const inputRef = useRef<any>(null);
|
|
44
|
+
|
|
45
|
+
const onClearText = () => {
|
|
46
|
+
inputRef?.current?.clear();
|
|
47
|
+
_onChangeText('');
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
const _onChangeText = (text: string) => {
|
|
51
|
+
onChangeText?.(text);
|
|
52
|
+
setInputValue(text);
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
const _onFocus = (e: NativeSyntheticEvent<TextInputFocusEventData>) => {
|
|
56
|
+
setFocused(true);
|
|
57
|
+
onFocus?.(e);
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
const _onBlur = (e: NativeSyntheticEvent<TextInputFocusEventData>) => {
|
|
61
|
+
setFocused(false);
|
|
62
|
+
onBlur?.(e);
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
const renderCountingView = () => {
|
|
66
|
+
return (
|
|
67
|
+
<View style={styles.countingView}>
|
|
68
|
+
<Text color={theme.colors.text.hint} typography={'description_xs'}>
|
|
69
|
+
{`${inputValue.length}/${maxLength}`}
|
|
70
|
+
</Text>
|
|
71
|
+
</View>
|
|
72
|
+
);
|
|
73
|
+
};
|
|
74
|
+
const renderInputView = () => {
|
|
75
|
+
const disabledColor = theme.colors.text.disable;
|
|
76
|
+
let textColor = theme.colors.text.default;
|
|
77
|
+
let placeholderColor = theme.colors.text.hint;
|
|
78
|
+
|
|
79
|
+
if (disabled) {
|
|
80
|
+
textColor = disabledColor;
|
|
81
|
+
placeholderColor = disabledColor;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
return (
|
|
85
|
+
<View
|
|
86
|
+
style={[
|
|
87
|
+
getBorderColor(focused, errorMessage, disabled),
|
|
88
|
+
styles.textAreaWrapper,
|
|
89
|
+
{
|
|
90
|
+
height: height || DEFAULT_HEIGHT,
|
|
91
|
+
backgroundColor: theme.colors.background.surface,
|
|
92
|
+
},
|
|
93
|
+
]}>
|
|
94
|
+
<FloatingView
|
|
95
|
+
floatingValue={floatingValue}
|
|
96
|
+
floatingIconColor={floatingIconColor}
|
|
97
|
+
disabled={disabled}
|
|
98
|
+
floatingIcon={floatingIcon}
|
|
99
|
+
required={required}
|
|
100
|
+
/>
|
|
101
|
+
<View style={styles.rowArea}>
|
|
102
|
+
<View style={styles.textAreaView}>
|
|
103
|
+
<TextInput
|
|
104
|
+
ref={inputRef}
|
|
105
|
+
editable={!disabled}
|
|
106
|
+
textAlignVertical="top"
|
|
107
|
+
style={[
|
|
108
|
+
styles.textArea,
|
|
109
|
+
{
|
|
110
|
+
color: textColor,
|
|
111
|
+
},
|
|
112
|
+
]}
|
|
113
|
+
maxLength={maxLength}
|
|
114
|
+
textBreakStrategy="highQuality"
|
|
115
|
+
multiline={true}
|
|
116
|
+
value={value}
|
|
117
|
+
onChangeText={_onChangeText}
|
|
118
|
+
onFocus={_onFocus}
|
|
119
|
+
onBlur={_onBlur}
|
|
120
|
+
placeholder={placeholder}
|
|
121
|
+
selectionColor={theme.colors.primary}
|
|
122
|
+
placeholderTextColor={placeholderColor}
|
|
123
|
+
/>
|
|
124
|
+
</View>
|
|
125
|
+
{focused && inputValue.length > 0 && (
|
|
126
|
+
<TouchableOpacity style={styles.iconWrapper} onPress={onClearText}>
|
|
127
|
+
<Icon
|
|
128
|
+
source="24_navigation_close_circle_full"
|
|
129
|
+
size={16}
|
|
130
|
+
color={theme.colors.text.hint}
|
|
131
|
+
/>
|
|
132
|
+
</TouchableOpacity>
|
|
133
|
+
)}
|
|
134
|
+
</View>
|
|
135
|
+
{renderCountingView()}
|
|
136
|
+
</View>
|
|
137
|
+
);
|
|
138
|
+
};
|
|
139
|
+
|
|
140
|
+
return (
|
|
141
|
+
<View style={styles.wrapper} accessibilityLabel={`InputTextArea`}>
|
|
142
|
+
{renderInputView()}
|
|
143
|
+
<ErrorView errorMessage={errorMessage} />
|
|
144
|
+
</View>
|
|
145
|
+
);
|
|
146
|
+
};
|
|
147
|
+
|
|
148
|
+
InputTextArea.defaultProps = {
|
|
149
|
+
maxLength: MAX_LENGTH,
|
|
150
|
+
};
|
|
151
|
+
|
|
152
|
+
export default InputTextArea;
|
package/Input/common.tsx
ADDED
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import {View} from 'react-native';
|
|
2
|
+
import styles from './styles';
|
|
3
|
+
import {Text} from '../Text';
|
|
4
|
+
import React, {FC, useContext} from 'react';
|
|
5
|
+
import {ApplicationContext} from '../Navigation';
|
|
6
|
+
import {Icon} from '../Icon';
|
|
7
|
+
import {Styles} from '../Consts';
|
|
8
|
+
|
|
9
|
+
type FloatingViewProps = {
|
|
10
|
+
floatingValue?: string;
|
|
11
|
+
floatingIconColor?: string;
|
|
12
|
+
disabled?: boolean;
|
|
13
|
+
floatingIcon?: string;
|
|
14
|
+
required?: boolean;
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
export const DEFAULT_HEIGHT = 112;
|
|
18
|
+
export const MAX_LENGTH = 300;
|
|
19
|
+
|
|
20
|
+
export const getBorderColor = (
|
|
21
|
+
focused: boolean,
|
|
22
|
+
errorMessage?: string,
|
|
23
|
+
disabled?: boolean,
|
|
24
|
+
) => {
|
|
25
|
+
const {theme} = useContext(ApplicationContext);
|
|
26
|
+
|
|
27
|
+
let borderColor = theme.colors.border.default;
|
|
28
|
+
|
|
29
|
+
if (focused) {
|
|
30
|
+
borderColor = theme.colors.primary;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
if (errorMessage) {
|
|
34
|
+
borderColor = theme.colors.error.primary;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
if (disabled) {
|
|
38
|
+
borderColor = theme.colors.border.disable;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
return {borderColor};
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
export const getSizeStyle = (size?: 'small' | 'large') => {
|
|
45
|
+
if (size === 'small') {
|
|
46
|
+
return styles.smallContainer;
|
|
47
|
+
}
|
|
48
|
+
return styles.container;
|
|
49
|
+
};
|
|
50
|
+
export const ErrorView: FC<{errorMessage?: string}> = ({errorMessage}) => {
|
|
51
|
+
const {theme} = useContext(ApplicationContext);
|
|
52
|
+
const errorColor = theme.colors.error.primary;
|
|
53
|
+
if (errorMessage) {
|
|
54
|
+
return (
|
|
55
|
+
<View style={styles.errorView}>
|
|
56
|
+
<View style={styles.errorIcon}>
|
|
57
|
+
<Icon color={errorColor} source="ic_error" size={16} />
|
|
58
|
+
</View>
|
|
59
|
+
<Text
|
|
60
|
+
style={Styles.flex}
|
|
61
|
+
color={errorColor}
|
|
62
|
+
numberOfLines={1}
|
|
63
|
+
typography={'description_s'}>
|
|
64
|
+
{errorMessage}
|
|
65
|
+
</Text>
|
|
66
|
+
</View>
|
|
67
|
+
);
|
|
68
|
+
}
|
|
69
|
+
return null;
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
export const FloatingView: FC<FloatingViewProps> = ({
|
|
73
|
+
floatingValue,
|
|
74
|
+
floatingIconColor,
|
|
75
|
+
disabled,
|
|
76
|
+
floatingIcon,
|
|
77
|
+
required,
|
|
78
|
+
}) => {
|
|
79
|
+
const {theme} = useContext(ApplicationContext);
|
|
80
|
+
|
|
81
|
+
if (floatingValue) {
|
|
82
|
+
let floatingTextColor = theme.colors.text.hint;
|
|
83
|
+
let floatingIconTintColor = floatingIconColor;
|
|
84
|
+
if (disabled) {
|
|
85
|
+
floatingTextColor = theme.colors.text.disable;
|
|
86
|
+
floatingIconTintColor = theme.colors.text.disable;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
return (
|
|
90
|
+
<View
|
|
91
|
+
style={[
|
|
92
|
+
styles.floatingView,
|
|
93
|
+
{
|
|
94
|
+
backgroundColor: theme.colors.background.surface,
|
|
95
|
+
zIndex: 10,
|
|
96
|
+
},
|
|
97
|
+
]}>
|
|
98
|
+
<Text color={floatingTextColor} typography={'label_s'}>
|
|
99
|
+
{floatingValue}
|
|
100
|
+
{required && (
|
|
101
|
+
<Text typography={'label_s'} color={theme.colors.error.primary}>
|
|
102
|
+
*
|
|
103
|
+
</Text>
|
|
104
|
+
)}
|
|
105
|
+
</Text>
|
|
106
|
+
{!!floatingIcon && (
|
|
107
|
+
<Icon
|
|
108
|
+
color={floatingIconTintColor}
|
|
109
|
+
source={floatingIcon}
|
|
110
|
+
size={16}
|
|
111
|
+
style={styles.floatingIcon}
|
|
112
|
+
/>
|
|
113
|
+
)}
|
|
114
|
+
</View>
|
|
115
|
+
);
|
|
116
|
+
}
|
|
117
|
+
return null;
|
|
118
|
+
};
|
package/Input/index.tsx
ADDED
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import Input from './Input';
|
|
2
|
+
import InputTextArea from './InputTextArea';
|
|
3
|
+
import InputSearch from './InputSearch';
|
|
4
|
+
import InputMoney from './InputMoney';
|
|
5
|
+
import {TextInputProps} from 'react-native';
|
|
6
|
+
|
|
7
|
+
export interface InputProps extends TextInputProps {
|
|
8
|
+
/**
|
|
9
|
+
* Optional. Defines the size of the Input component.
|
|
10
|
+
*/
|
|
11
|
+
size?: 'small' | 'large';
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Optional. Represents the value for the floating title in the Input component.
|
|
15
|
+
*/
|
|
16
|
+
floatingValue?: string;
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Optional. Represents the name or key of the floating icon to be displayed in the Input component.
|
|
20
|
+
*/
|
|
21
|
+
floatingIcon?: string;
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Optional. Represents the error message to be displayed below the Input component when there is an error.
|
|
25
|
+
*/
|
|
26
|
+
errorMessage?: string;
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Optional. Represents the name or key of the icon to be displayed in the Input component.
|
|
30
|
+
*/
|
|
31
|
+
icon?: string;
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Optional. If `true`, the user won't be able to interact with the Input component.
|
|
35
|
+
* Defaults to `false` if not provided.
|
|
36
|
+
*/
|
|
37
|
+
disabled?: boolean;
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Optional. Represents the color of the floating icon in the Input component.
|
|
41
|
+
*/
|
|
42
|
+
floatingIconColor?: string;
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Optional. Represents the color of the icon in the Input component.
|
|
46
|
+
*/
|
|
47
|
+
iconColor?: string;
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Optional. If `true`, the Input component is marked as required,
|
|
51
|
+
* indicating that the user must provide a value before submitting a form.
|
|
52
|
+
* Defaults to `false` if not provided.
|
|
53
|
+
*/
|
|
54
|
+
required?: boolean;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
type InputPropsWithoutSizeAndIcon = Omit<
|
|
58
|
+
InputProps,
|
|
59
|
+
'size' | 'icon' | 'iconColor'
|
|
60
|
+
>;
|
|
61
|
+
type InputPropsOmitForSearch = Omit<
|
|
62
|
+
InputProps,
|
|
63
|
+
'required' | 'size' | 'errorMessage' | 'disabled'
|
|
64
|
+
>;
|
|
65
|
+
type InputPropsWithoutPlaceholder = Omit<InputProps, 'placeholder'>;
|
|
66
|
+
|
|
67
|
+
export interface InputTextAreaProps extends InputPropsWithoutSizeAndIcon {
|
|
68
|
+
/**
|
|
69
|
+
* Optional. Defines the height of the InputTextArea component.
|
|
70
|
+
* It can be used to set a specific height for the text area.
|
|
71
|
+
*/
|
|
72
|
+
height?: number;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export interface InputSearchProps extends InputPropsOmitForSearch {
|
|
76
|
+
/**
|
|
77
|
+
* Optional. Represents the text to be displayed on the search button within the InputSearch component.
|
|
78
|
+
*/
|
|
79
|
+
buttonText?: string;
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Optional. If `true`, the text on the search button will be displayed.
|
|
83
|
+
* Defaults to `false` if not provided.
|
|
84
|
+
*/
|
|
85
|
+
showButtonText?: boolean;
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Optional. If `true`, a border will be displayed around the InputSearch component.
|
|
89
|
+
* Defaults to `true` if not provided.
|
|
90
|
+
*/
|
|
91
|
+
showBorder?: boolean;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
export interface InputMoneyProps extends InputPropsWithoutPlaceholder {}
|
|
95
|
+
|
|
96
|
+
export {Input, InputTextArea, InputSearch, InputMoney};
|