@momo-kits/foundation 0.77.8-beta.4 → 0.77.8-beta.5
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/ModalScreen.tsx +6 -33
- package/Application/types.ts +1 -1
- package/Button/index.tsx +20 -0
- package/Input/Input.tsx +126 -107
- package/Input/InputMoney.tsx +118 -111
- package/Input/InputSearch.tsx +129 -124
- package/Input/InputTextArea.tsx +126 -119
- package/Input/index.tsx +5 -0
- package/Loader/DotLoader.tsx +10 -12
- package/Loader/Loader.tsx +3 -4
- package/Loader/Spinner.tsx +8 -10
- package/Loader/types.ts +2 -0
- package/Text/utils.ts +1 -1
- package/package.json +1 -1
|
@@ -1,12 +1,6 @@
|
|
|
1
|
-
import React, {
|
|
2
|
-
useCallback,
|
|
3
|
-
useContext,
|
|
4
|
-
useEffect,
|
|
5
|
-
useMemo,
|
|
6
|
-
useRef,
|
|
7
|
-
useState,
|
|
8
|
-
} from 'react';
|
|
1
|
+
import React, {useContext, useEffect, useRef} from 'react';
|
|
9
2
|
import {
|
|
3
|
+
Dimensions,
|
|
10
4
|
KeyboardAvoidingView,
|
|
11
5
|
Platform,
|
|
12
6
|
Pressable,
|
|
@@ -91,10 +85,11 @@ const Modal: React.FC<ModalParams> = props => {
|
|
|
91
85
|
|
|
92
86
|
const BottomSheet: React.FC<BottomSheetParams> = props => {
|
|
93
87
|
const {theme, navigator} = useContext(ApplicationContext);
|
|
88
|
+
const {height} = Dimensions.get('window');
|
|
94
89
|
const {
|
|
95
90
|
screen,
|
|
96
91
|
options,
|
|
97
|
-
|
|
92
|
+
snapPoints = [height * 0.5, height * 0.9],
|
|
98
93
|
}: BottomSheetParams = props.route.params;
|
|
99
94
|
const Component = useRef(screen).current;
|
|
100
95
|
const navigation = new Navigation(props.navigation, theme);
|
|
@@ -105,31 +100,9 @@ const BottomSheet: React.FC<BottomSheetParams> = props => {
|
|
|
105
100
|
|
|
106
101
|
delete params.screen;
|
|
107
102
|
|
|
108
|
-
const [contentHeight, setContentHeight] = useState(undefined);
|
|
109
|
-
const snapPoints = useMemo(() => {
|
|
110
|
-
if (useSnap) {
|
|
111
|
-
return ['50%', '90%'];
|
|
112
|
-
}
|
|
113
|
-
return [contentHeight ?? '50%'];
|
|
114
|
-
}, [contentHeight]);
|
|
115
|
-
|
|
116
103
|
const bottomSheetRef = useRef<any>(null);
|
|
117
104
|
const mountedRef = useRef(true);
|
|
118
105
|
|
|
119
|
-
let handleOnLayout;
|
|
120
|
-
if (useSnap) {
|
|
121
|
-
handleOnLayout = useCallback(
|
|
122
|
-
({
|
|
123
|
-
nativeEvent: {
|
|
124
|
-
layout: {height},
|
|
125
|
-
},
|
|
126
|
-
}) => {
|
|
127
|
-
setContentHeight(height);
|
|
128
|
-
},
|
|
129
|
-
[],
|
|
130
|
-
);
|
|
131
|
-
}
|
|
132
|
-
|
|
133
106
|
let backgroundColor = theme.colors.background.default;
|
|
134
107
|
if (options?.surface) {
|
|
135
108
|
backgroundColor = theme.colors.background.surface;
|
|
@@ -154,7 +127,7 @@ const BottomSheet: React.FC<BottomSheetParams> = props => {
|
|
|
154
127
|
<SafeAreaView style={Styles.flex}>
|
|
155
128
|
<BottomSheetModal
|
|
156
129
|
ref={bottomSheetRef}
|
|
157
|
-
snapPoints={snapPoints}
|
|
130
|
+
snapPoints={snapPoints?.map(item => item + 68)}
|
|
158
131
|
onDismiss={() => {
|
|
159
132
|
if (mountedRef.current) {
|
|
160
133
|
navigator?.pop();
|
|
@@ -162,7 +135,7 @@ const BottomSheet: React.FC<BottomSheetParams> = props => {
|
|
|
162
135
|
}}
|
|
163
136
|
handleComponent={null}
|
|
164
137
|
backdropComponent={backdropComponent}>
|
|
165
|
-
<View
|
|
138
|
+
<View accessibilityLabel={'BottomSheet'}>
|
|
166
139
|
<View style={[styles.sheetContainer, {backgroundColor}]}>
|
|
167
140
|
<View style={styles.indicatorContainer}>
|
|
168
141
|
<View
|
package/Application/types.ts
CHANGED
|
@@ -108,7 +108,7 @@ export interface ModalParams extends ScreenParams {
|
|
|
108
108
|
export interface BottomSheetParams extends ScreenParams {
|
|
109
109
|
[key: string]: any;
|
|
110
110
|
onDismiss?: () => void;
|
|
111
|
-
|
|
111
|
+
snapPoints?: ReadonlyArray<number>;
|
|
112
112
|
}
|
|
113
113
|
|
|
114
114
|
export type NavigationButtonProps = {
|
package/Button/index.tsx
CHANGED
|
@@ -11,6 +11,7 @@ import {Typography} from '../Text/types';
|
|
|
11
11
|
import {Colors} from '../Consts';
|
|
12
12
|
import styles from './styles';
|
|
13
13
|
import {Icon} from '../Icon';
|
|
14
|
+
import {Loader} from '../Loader';
|
|
14
15
|
|
|
15
16
|
export interface ButtonProps extends TouchableOpacityProps {
|
|
16
17
|
/**
|
|
@@ -55,6 +56,11 @@ export interface ButtonProps extends TouchableOpacityProps {
|
|
|
55
56
|
*/
|
|
56
57
|
useTintColor?: boolean;
|
|
57
58
|
|
|
59
|
+
/**
|
|
60
|
+
* If true, the icon of button will use be show indicator loading.
|
|
61
|
+
*/
|
|
62
|
+
loading?: boolean;
|
|
63
|
+
|
|
58
64
|
/**
|
|
59
65
|
* A callback function that is called when the button is pressed.
|
|
60
66
|
*/
|
|
@@ -68,6 +74,7 @@ const Button: FC<ButtonProps> = ({
|
|
|
68
74
|
full = true,
|
|
69
75
|
iconRight,
|
|
70
76
|
iconLeft,
|
|
77
|
+
loading = false,
|
|
71
78
|
title = 'Button',
|
|
72
79
|
onPress,
|
|
73
80
|
...rest
|
|
@@ -223,6 +230,19 @@ const Button: FC<ButtonProps> = ({
|
|
|
223
230
|
const renderTrailing = () => {
|
|
224
231
|
const marginLeft = getIconSpace();
|
|
225
232
|
const color = useTintColor ? getTextColor() : undefined;
|
|
233
|
+
if (loading) {
|
|
234
|
+
const iconSize = getIconSize();
|
|
235
|
+
const color = getTextColor();
|
|
236
|
+
return (
|
|
237
|
+
<View
|
|
238
|
+
style={[
|
|
239
|
+
styles.trailing,
|
|
240
|
+
{width: iconSize, height: iconSize, marginLeft},
|
|
241
|
+
]}>
|
|
242
|
+
<Loader type="spinner" color={color} />
|
|
243
|
+
</View>
|
|
244
|
+
);
|
|
245
|
+
}
|
|
226
246
|
if (iconRight) {
|
|
227
247
|
const iconSize = getIconSize();
|
|
228
248
|
return (
|
package/Input/Input.tsx
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, {FC, useContext, useRef, useState} from 'react';
|
|
1
|
+
import React, {FC, forwardRef, useContext, useRef, useState} from 'react';
|
|
2
2
|
import {
|
|
3
3
|
NativeSyntheticEvent,
|
|
4
4
|
TextInput,
|
|
@@ -12,125 +12,144 @@ import {ErrorView, FloatingView, getBorderColor, getSizeStyle} from './common';
|
|
|
12
12
|
import {InputProps} from './index';
|
|
13
13
|
import {Icon} from '../Icon';
|
|
14
14
|
import {checkTyping} from './utils';
|
|
15
|
+
import {Loader} from '../Loader';
|
|
15
16
|
|
|
16
|
-
const Input: FC<InputProps> = (
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
17
|
+
const Input: FC<InputProps> = forwardRef(
|
|
18
|
+
(
|
|
19
|
+
{
|
|
20
|
+
value,
|
|
21
|
+
onChangeText,
|
|
22
|
+
floatingValue,
|
|
23
|
+
floatingIcon,
|
|
24
|
+
size,
|
|
25
|
+
placeholder,
|
|
26
|
+
onBlur,
|
|
27
|
+
onFocus,
|
|
28
|
+
errorMessage,
|
|
29
|
+
icon,
|
|
30
|
+
disabled,
|
|
31
|
+
floatingIconColor,
|
|
32
|
+
iconColor,
|
|
33
|
+
required,
|
|
34
|
+
errorSpacing,
|
|
35
|
+
loading,
|
|
36
|
+
...props
|
|
37
|
+
},
|
|
38
|
+
ref,
|
|
39
|
+
) => {
|
|
40
|
+
const {theme} = useContext(ApplicationContext);
|
|
41
|
+
const [focused, setFocused] = useState(false);
|
|
42
|
+
const [haveValue, setHaveValue] = useState(!!value || !!props.defaultValue);
|
|
43
|
+
const inputRef = (ref as React.RefObject<TextInput>) ?? useRef<TextInput>();
|
|
37
44
|
|
|
38
|
-
|
|
45
|
+
const onClearText = () => {
|
|
46
|
+
inputRef?.current?.clear();
|
|
47
|
+
_onChangeText('');
|
|
48
|
+
};
|
|
39
49
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
50
|
+
const _onChangeText = (text: string) => {
|
|
51
|
+
checkTyping(text, haveValue, setHaveValue);
|
|
52
|
+
onChangeText?.(text);
|
|
53
|
+
};
|
|
44
54
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
55
|
+
const _onFocus = (e: NativeSyntheticEvent<TextInputFocusEventData>) => {
|
|
56
|
+
setFocused(true);
|
|
57
|
+
onFocus?.(e);
|
|
58
|
+
};
|
|
49
59
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
60
|
+
const _onBlur = (e: NativeSyntheticEvent<TextInputFocusEventData>) => {
|
|
61
|
+
setFocused(false);
|
|
62
|
+
onBlur?.(e);
|
|
63
|
+
};
|
|
54
64
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
65
|
+
const renderIcon = (color: string | undefined) => {
|
|
66
|
+
if (loading) {
|
|
67
|
+
return <Loader type={'spinner'} color={color} />;
|
|
68
|
+
}
|
|
69
|
+
if (icon) {
|
|
70
|
+
return <Icon color={color} source={icon} size={24} />;
|
|
71
|
+
}
|
|
72
|
+
};
|
|
59
73
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
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
|
+
let iconTintColor = iconColor;
|
|
65
79
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
80
|
+
if (disabled) {
|
|
81
|
+
textColor = disabledColor;
|
|
82
|
+
placeholderColor = disabledColor;
|
|
83
|
+
iconTintColor = disabledColor;
|
|
84
|
+
}
|
|
71
85
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
/>
|
|
87
|
-
<View style={styles.inputView}>
|
|
88
|
-
<TextInput
|
|
89
|
-
{...props}
|
|
90
|
-
accessibilityLabel={`TextInput`}
|
|
91
|
-
editable={!disabled}
|
|
92
|
-
textAlignVertical="top"
|
|
93
|
-
ref={inputRef}
|
|
94
|
-
style={[
|
|
95
|
-
styles.input,
|
|
96
|
-
{
|
|
97
|
-
color: textColor,
|
|
98
|
-
fontFamily: `${theme.font}-Regular`,
|
|
99
|
-
},
|
|
100
|
-
]}
|
|
101
|
-
textBreakStrategy="highQuality"
|
|
102
|
-
value={value}
|
|
103
|
-
onChangeText={_onChangeText}
|
|
104
|
-
onFocus={_onFocus}
|
|
105
|
-
onBlur={_onBlur}
|
|
106
|
-
placeholder={placeholder}
|
|
107
|
-
selectionColor={theme.colors.primary}
|
|
108
|
-
placeholderTextColor={placeholderColor}
|
|
86
|
+
return (
|
|
87
|
+
<View
|
|
88
|
+
style={[
|
|
89
|
+
styles.inputWrapper,
|
|
90
|
+
{backgroundColor: theme.colors.background.surface},
|
|
91
|
+
getSizeStyle(size),
|
|
92
|
+
getBorderColor(theme, focused, errorMessage, disabled),
|
|
93
|
+
]}>
|
|
94
|
+
<FloatingView
|
|
95
|
+
floatingValue={floatingValue}
|
|
96
|
+
floatingIconColor={floatingIconColor}
|
|
97
|
+
disabled={disabled}
|
|
98
|
+
required={required}
|
|
99
|
+
floatingIcon={floatingIcon}
|
|
109
100
|
/>
|
|
101
|
+
<View style={styles.inputView}>
|
|
102
|
+
<TextInput
|
|
103
|
+
{...props}
|
|
104
|
+
accessibilityLabel={`TextInput`}
|
|
105
|
+
editable={!disabled}
|
|
106
|
+
textAlignVertical="top"
|
|
107
|
+
ref={inputRef}
|
|
108
|
+
style={[
|
|
109
|
+
styles.input,
|
|
110
|
+
{
|
|
111
|
+
color: textColor,
|
|
112
|
+
fontFamily: `${theme.font}-Regular`,
|
|
113
|
+
},
|
|
114
|
+
]}
|
|
115
|
+
textBreakStrategy="highQuality"
|
|
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
|
+
<View style={styles.iconView}>
|
|
126
|
+
{focused && haveValue && (
|
|
127
|
+
<TouchableOpacity
|
|
128
|
+
style={styles.iconWrapper}
|
|
129
|
+
onPress={onClearText}>
|
|
130
|
+
<Icon
|
|
131
|
+
source="24_navigation_close_circle_full"
|
|
132
|
+
size={16}
|
|
133
|
+
color={theme.colors.text.hint}
|
|
134
|
+
/>
|
|
135
|
+
</TouchableOpacity>
|
|
136
|
+
)}
|
|
137
|
+
{renderIcon(iconTintColor)}
|
|
138
|
+
</View>
|
|
110
139
|
</View>
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
)}
|
|
121
|
-
{!!icon && <Icon color={iconTintColor} source={icon} size={24} />}
|
|
122
|
-
</View>
|
|
140
|
+
);
|
|
141
|
+
};
|
|
142
|
+
|
|
143
|
+
return (
|
|
144
|
+
<View
|
|
145
|
+
style={styles.wrapper}
|
|
146
|
+
accessibilityLabel={`Input/${floatingValue}`}>
|
|
147
|
+
{renderInputView()}
|
|
148
|
+
<ErrorView errorMessage={errorMessage} errorSpacing={errorSpacing} />
|
|
123
149
|
</View>
|
|
124
150
|
);
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
return (
|
|
128
|
-
<View style={styles.wrapper} accessibilityLabel={`Input/${floatingValue}`}>
|
|
129
|
-
{renderInputView()}
|
|
130
|
-
<ErrorView errorMessage={errorMessage} errorSpacing={errorSpacing} />
|
|
131
|
-
</View>
|
|
132
|
-
);
|
|
133
|
-
};
|
|
151
|
+
},
|
|
152
|
+
);
|
|
134
153
|
|
|
135
154
|
Input.defaultProps = {
|
|
136
155
|
size: 'small',
|
package/Input/InputMoney.tsx
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, {FC, useContext, useRef, useState} from 'react';
|
|
1
|
+
import React, {FC, forwardRef, useContext, useRef, useState} from 'react';
|
|
2
2
|
import {
|
|
3
3
|
NativeSyntheticEvent,
|
|
4
4
|
TextInput,
|
|
@@ -13,124 +13,131 @@ import {InputMoneyProps} from './index';
|
|
|
13
13
|
import {Icon} from '../Icon';
|
|
14
14
|
import {formatMoneyToNumber, formatNumberToMoney} from './utils';
|
|
15
15
|
|
|
16
|
-
const InputMoney: FC<InputMoneyProps> = (
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
}
|
|
45
|
-
const
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
16
|
+
const InputMoney: FC<InputMoneyProps> = forwardRef(
|
|
17
|
+
(
|
|
18
|
+
{
|
|
19
|
+
onChangeText,
|
|
20
|
+
floatingValue,
|
|
21
|
+
floatingIcon,
|
|
22
|
+
size = 'small',
|
|
23
|
+
onBlur,
|
|
24
|
+
onFocus,
|
|
25
|
+
errorMessage,
|
|
26
|
+
icon,
|
|
27
|
+
disabled,
|
|
28
|
+
floatingIconColor,
|
|
29
|
+
iconColor,
|
|
30
|
+
required,
|
|
31
|
+
errorSpacing,
|
|
32
|
+
...props
|
|
33
|
+
},
|
|
34
|
+
ref,
|
|
35
|
+
) => {
|
|
36
|
+
const {theme} = useContext(ApplicationContext);
|
|
37
|
+
const [focused, setFocused] = useState(false);
|
|
38
|
+
const inputRef = (ref as React.RefObject<TextInput>) ?? useRef<TextInput>();
|
|
39
|
+
const [value, setValue] = useState('');
|
|
40
|
+
const onClearText = () => {
|
|
41
|
+
inputRef?.current?.clear();
|
|
42
|
+
setValue('');
|
|
43
|
+
onChangeText?.('');
|
|
44
|
+
};
|
|
45
|
+
const _onChangeText = (text: string) => {
|
|
46
|
+
if (text.length < value.length && value.indexOf(text) === 0) {
|
|
47
|
+
text = value.slice(0, -2) + 'đ';
|
|
48
|
+
}
|
|
49
|
+
const valueFormat = formatMoneyToNumber(text, 'đ');
|
|
50
|
+
setValue(formatNumberToMoney(valueFormat, 'đ'));
|
|
51
|
+
onChangeText?.(formatMoneyToNumber(text, 'đ').toString());
|
|
52
|
+
};
|
|
49
53
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
+
const _onFocus = (e: NativeSyntheticEvent<TextInputFocusEventData>) => {
|
|
55
|
+
setFocused(true);
|
|
56
|
+
onFocus?.(e);
|
|
57
|
+
};
|
|
54
58
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
+
const _onBlur = (e: NativeSyntheticEvent<TextInputFocusEventData>) => {
|
|
60
|
+
setFocused(false);
|
|
61
|
+
onBlur?.(e);
|
|
62
|
+
};
|
|
59
63
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
64
|
+
const renderInputView = () => {
|
|
65
|
+
const disabledColor = theme.colors.text.disable;
|
|
66
|
+
let textColor = theme.colors.text.default;
|
|
67
|
+
let placeholderColor = theme.colors.text.hint;
|
|
68
|
+
let iconTintColor = iconColor;
|
|
65
69
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
70
|
+
if (disabled) {
|
|
71
|
+
textColor = disabledColor;
|
|
72
|
+
placeholderColor = disabledColor;
|
|
73
|
+
iconTintColor = disabledColor;
|
|
74
|
+
}
|
|
71
75
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
/>
|
|
87
|
-
<View style={styles.inputView}>
|
|
88
|
-
<TextInput
|
|
89
|
-
{...props}
|
|
90
|
-
accessibilityLabel={`TextInput`}
|
|
91
|
-
editable={!disabled}
|
|
92
|
-
textAlignVertical="top"
|
|
93
|
-
ref={inputRef}
|
|
94
|
-
keyboardType={'number-pad'}
|
|
95
|
-
style={[
|
|
96
|
-
styles.moneyInput,
|
|
97
|
-
{
|
|
98
|
-
color: textColor,
|
|
99
|
-
},
|
|
100
|
-
]}
|
|
101
|
-
value={value}
|
|
102
|
-
onChangeText={_onChangeText}
|
|
103
|
-
onFocus={_onFocus}
|
|
104
|
-
onBlur={_onBlur}
|
|
105
|
-
selectionColor={theme.colors.primary}
|
|
106
|
-
placeholderTextColor={placeholderColor}
|
|
107
|
-
placeholder={'0đ'}
|
|
76
|
+
return (
|
|
77
|
+
<View
|
|
78
|
+
style={[
|
|
79
|
+
styles.inputWrapper,
|
|
80
|
+
{backgroundColor: theme.colors.background.surface},
|
|
81
|
+
getSizeStyle(size),
|
|
82
|
+
getBorderColor(theme, focused, errorMessage, disabled),
|
|
83
|
+
]}>
|
|
84
|
+
<FloatingView
|
|
85
|
+
floatingValue={floatingValue}
|
|
86
|
+
floatingIconColor={floatingIconColor}
|
|
87
|
+
disabled={disabled}
|
|
88
|
+
required={required}
|
|
89
|
+
floatingIcon={floatingIcon}
|
|
108
90
|
/>
|
|
91
|
+
<View style={styles.inputView}>
|
|
92
|
+
<TextInput
|
|
93
|
+
{...props}
|
|
94
|
+
accessibilityLabel={`TextInput`}
|
|
95
|
+
editable={!disabled}
|
|
96
|
+
textAlignVertical="top"
|
|
97
|
+
ref={inputRef}
|
|
98
|
+
keyboardType={'number-pad'}
|
|
99
|
+
style={[
|
|
100
|
+
styles.moneyInput,
|
|
101
|
+
{
|
|
102
|
+
color: textColor,
|
|
103
|
+
},
|
|
104
|
+
]}
|
|
105
|
+
value={value}
|
|
106
|
+
onChangeText={_onChangeText}
|
|
107
|
+
onFocus={_onFocus}
|
|
108
|
+
onBlur={_onBlur}
|
|
109
|
+
selectionColor={theme.colors.primary}
|
|
110
|
+
placeholderTextColor={placeholderColor}
|
|
111
|
+
placeholder={'0đ'}
|
|
112
|
+
/>
|
|
113
|
+
</View>
|
|
114
|
+
<View style={styles.iconView}>
|
|
115
|
+
{focused && (
|
|
116
|
+
<TouchableOpacity
|
|
117
|
+
style={styles.iconWrapper}
|
|
118
|
+
onPress={onClearText}>
|
|
119
|
+
<Icon
|
|
120
|
+
source="24_navigation_close_circle_full"
|
|
121
|
+
size={16}
|
|
122
|
+
color={theme.colors.text.hint}
|
|
123
|
+
/>
|
|
124
|
+
</TouchableOpacity>
|
|
125
|
+
)}
|
|
126
|
+
{!!icon && <Icon color={iconTintColor} source={icon} />}
|
|
127
|
+
</View>
|
|
109
128
|
</View>
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
)}
|
|
120
|
-
{!!icon && <Icon color={iconTintColor} source={icon} />}
|
|
121
|
-
</View>
|
|
129
|
+
);
|
|
130
|
+
};
|
|
131
|
+
|
|
132
|
+
return (
|
|
133
|
+
<View
|
|
134
|
+
style={styles.wrapper}
|
|
135
|
+
accessibilityLabel={`InputMoney/${floatingValue}`}>
|
|
136
|
+
{renderInputView()}
|
|
137
|
+
<ErrorView errorMessage={errorMessage} errorSpacing={errorSpacing} />
|
|
122
138
|
</View>
|
|
123
139
|
);
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
return (
|
|
127
|
-
<View
|
|
128
|
-
style={styles.wrapper}
|
|
129
|
-
accessibilityLabel={`InputMoney/${floatingValue}`}>
|
|
130
|
-
{renderInputView()}
|
|
131
|
-
<ErrorView errorMessage={errorMessage} errorSpacing={errorSpacing} />
|
|
132
|
-
</View>
|
|
133
|
-
);
|
|
134
|
-
};
|
|
140
|
+
},
|
|
141
|
+
);
|
|
135
142
|
|
|
136
143
|
export default InputMoney;
|
package/Input/InputSearch.tsx
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, {FC, useContext, useRef, useState} from 'react';
|
|
1
|
+
import React, {FC, forwardRef, useContext, useRef, useState} from 'react';
|
|
2
2
|
import {
|
|
3
3
|
NativeSyntheticEvent,
|
|
4
4
|
TextInput,
|
|
@@ -13,141 +13,146 @@ import {Icon} from '../Icon';
|
|
|
13
13
|
import {Text} from '../Text';
|
|
14
14
|
import {checkTyping} from './utils';
|
|
15
15
|
|
|
16
|
-
const InputSearch: FC<InputSearchProps> = (
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
16
|
+
const InputSearch: FC<InputSearchProps> = forwardRef(
|
|
17
|
+
(
|
|
18
|
+
{
|
|
19
|
+
placeholder,
|
|
20
|
+
onFocus,
|
|
21
|
+
onBlur,
|
|
22
|
+
iconColor,
|
|
23
|
+
value,
|
|
24
|
+
onChangeText,
|
|
25
|
+
icon,
|
|
26
|
+
buttonText = 'Hủy',
|
|
27
|
+
showButtonText = true,
|
|
28
|
+
showBorder = true,
|
|
29
|
+
style,
|
|
30
|
+
defaultValue,
|
|
31
|
+
onPressButtonText,
|
|
32
|
+
...props
|
|
33
|
+
},
|
|
34
|
+
ref,
|
|
35
|
+
) => {
|
|
36
|
+
const {theme} = useContext(ApplicationContext);
|
|
37
|
+
const [focused, setFocused] = useState(false);
|
|
38
|
+
const [haveValue, setHaveValue] = useState(!!value || !!defaultValue);
|
|
39
|
+
const inputRef = (ref as React.RefObject<TextInput>) ?? useRef<TextInput>();
|
|
40
|
+
let iconTintColor = iconColor;
|
|
37
41
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
+
const _onFocus = (e: NativeSyntheticEvent<TextInputFocusEventData>) => {
|
|
43
|
+
setFocused(true);
|
|
44
|
+
onFocus?.(e);
|
|
45
|
+
};
|
|
42
46
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
+
const _onBlur = (e: NativeSyntheticEvent<TextInputFocusEventData>) => {
|
|
48
|
+
setFocused(false);
|
|
49
|
+
onBlur?.(e);
|
|
50
|
+
};
|
|
47
51
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
+
const onClearText = () => {
|
|
53
|
+
inputRef?.current?.clear();
|
|
54
|
+
_onChangeText('');
|
|
55
|
+
};
|
|
52
56
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
+
const _onChangeText = (text: string) => {
|
|
58
|
+
checkTyping(text, haveValue, setHaveValue);
|
|
59
|
+
onChangeText?.(text);
|
|
60
|
+
};
|
|
57
61
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
62
|
+
const renderInputView = () => {
|
|
63
|
+
let textColor = theme.colors.text.default;
|
|
64
|
+
let placeholderColor = theme.colors.text.hint;
|
|
61
65
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
66
|
+
return (
|
|
67
|
+
<TextInput
|
|
68
|
+
{...props}
|
|
69
|
+
accessibilityLabel={`TextInput`}
|
|
70
|
+
textAlignVertical="top"
|
|
71
|
+
ref={inputRef}
|
|
72
|
+
style={[
|
|
73
|
+
styles.searchInput,
|
|
74
|
+
{
|
|
75
|
+
color: textColor,
|
|
76
|
+
},
|
|
77
|
+
]}
|
|
78
|
+
value={value}
|
|
79
|
+
onChangeText={_onChangeText}
|
|
80
|
+
onFocus={_onFocus}
|
|
81
|
+
onBlur={_onBlur}
|
|
82
|
+
placeholder={placeholder}
|
|
83
|
+
selectionColor={theme.colors.primary}
|
|
84
|
+
placeholderTextColor={placeholderColor}
|
|
85
|
+
/>
|
|
86
|
+
);
|
|
87
|
+
};
|
|
84
88
|
|
|
85
|
-
|
|
89
|
+
const renderIconView = () => {
|
|
90
|
+
return (
|
|
91
|
+
<View
|
|
92
|
+
style={{
|
|
93
|
+
flexDirection: 'row',
|
|
94
|
+
}}>
|
|
95
|
+
{focused && haveValue && (
|
|
96
|
+
<TouchableOpacity style={styles.iconWrapper} onPress={onClearText}>
|
|
97
|
+
<Icon
|
|
98
|
+
source="24_navigation_close_circle_full"
|
|
99
|
+
size={16}
|
|
100
|
+
color={theme.colors.text.hint}
|
|
101
|
+
/>
|
|
102
|
+
</TouchableOpacity>
|
|
103
|
+
)}
|
|
104
|
+
{!!icon && (
|
|
105
|
+
<View style={{flexDirection: 'row'}}>
|
|
106
|
+
<View
|
|
107
|
+
style={[
|
|
108
|
+
styles.divider,
|
|
109
|
+
{
|
|
110
|
+
backgroundColor: theme.colors.primary,
|
|
111
|
+
},
|
|
112
|
+
]}
|
|
113
|
+
/>
|
|
114
|
+
<Icon
|
|
115
|
+
color={iconTintColor}
|
|
116
|
+
source={icon}
|
|
117
|
+
style={styles.iconSearchInput}
|
|
118
|
+
/>
|
|
119
|
+
</View>
|
|
120
|
+
)}
|
|
121
|
+
</View>
|
|
122
|
+
);
|
|
123
|
+
};
|
|
86
124
|
return (
|
|
87
125
|
<View
|
|
88
|
-
style={
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
126
|
+
style={[style, styles.searchInputContainer]}
|
|
127
|
+
accessibilityLabel={`InputSearch/${placeholder}`}>
|
|
128
|
+
<View
|
|
129
|
+
style={[
|
|
130
|
+
styles.searchInputWrapper,
|
|
131
|
+
{
|
|
132
|
+
backgroundColor: theme.colors.background.surface,
|
|
133
|
+
borderColor: theme.colors.background.surface,
|
|
134
|
+
},
|
|
135
|
+
showBorder && {borderColor: theme.colors.border.default},
|
|
136
|
+
focused && {borderColor: theme.colors.primary},
|
|
137
|
+
]}>
|
|
138
|
+
<Icon
|
|
139
|
+
source={'navigation_search'}
|
|
140
|
+
size={24}
|
|
141
|
+
color={theme.colors.text.hint}
|
|
142
|
+
/>
|
|
143
|
+
{renderInputView()}
|
|
144
|
+
{renderIconView()}
|
|
145
|
+
</View>
|
|
146
|
+
{showButtonText && (
|
|
147
|
+
<TouchableOpacity onPress={onPressButtonText}>
|
|
148
|
+
<Text typography={'action_default'} style={styles.textButton}>
|
|
149
|
+
{buttonText}
|
|
150
|
+
</Text>
|
|
98
151
|
</TouchableOpacity>
|
|
99
152
|
)}
|
|
100
|
-
{!!icon && (
|
|
101
|
-
<View style={{flexDirection: 'row'}}>
|
|
102
|
-
<View
|
|
103
|
-
style={[
|
|
104
|
-
styles.divider,
|
|
105
|
-
{
|
|
106
|
-
backgroundColor: theme.colors.primary,
|
|
107
|
-
},
|
|
108
|
-
]}
|
|
109
|
-
/>
|
|
110
|
-
<Icon
|
|
111
|
-
color={iconTintColor}
|
|
112
|
-
source={icon}
|
|
113
|
-
style={styles.iconSearchInput}
|
|
114
|
-
/>
|
|
115
|
-
</View>
|
|
116
|
-
)}
|
|
117
153
|
</View>
|
|
118
154
|
);
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
<View
|
|
122
|
-
style={[style, styles.searchInputContainer]}
|
|
123
|
-
accessibilityLabel={`InputSearch/${placeholder}`}>
|
|
124
|
-
<View
|
|
125
|
-
style={[
|
|
126
|
-
styles.searchInputWrapper,
|
|
127
|
-
{
|
|
128
|
-
backgroundColor: theme.colors.background.surface,
|
|
129
|
-
borderColor: theme.colors.background.surface,
|
|
130
|
-
},
|
|
131
|
-
showBorder && {borderColor: theme.colors.border.default},
|
|
132
|
-
focused && {borderColor: theme.colors.primary},
|
|
133
|
-
]}>
|
|
134
|
-
<Icon
|
|
135
|
-
source={'navigation_search'}
|
|
136
|
-
size={24}
|
|
137
|
-
color={theme.colors.text.hint}
|
|
138
|
-
/>
|
|
139
|
-
{renderInputView()}
|
|
140
|
-
{renderIconView()}
|
|
141
|
-
</View>
|
|
142
|
-
{showButtonText && (
|
|
143
|
-
<TouchableOpacity onPress={onPressButtonText}>
|
|
144
|
-
<Text typography={'action_default'} style={styles.textButton}>
|
|
145
|
-
{buttonText}
|
|
146
|
-
</Text>
|
|
147
|
-
</TouchableOpacity>
|
|
148
|
-
)}
|
|
149
|
-
</View>
|
|
150
|
-
);
|
|
151
|
-
};
|
|
155
|
+
},
|
|
156
|
+
);
|
|
152
157
|
|
|
153
158
|
export default InputSearch;
|
package/Input/InputTextArea.tsx
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, {FC, useContext, useRef, useState} from 'react';
|
|
1
|
+
import React, {FC, forwardRef, useContext, useRef, useState} from 'react';
|
|
2
2
|
import {
|
|
3
3
|
NativeSyntheticEvent,
|
|
4
4
|
TextInput,
|
|
@@ -19,135 +19,142 @@ import {InputTextAreaProps} from './index';
|
|
|
19
19
|
import {Icon} from '../Icon';
|
|
20
20
|
import {ApplicationContext} from '../Application';
|
|
21
21
|
|
|
22
|
-
const InputTextArea: FC<InputTextAreaProps> = (
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
22
|
+
const InputTextArea: FC<InputTextAreaProps> = forwardRef(
|
|
23
|
+
(
|
|
24
|
+
{
|
|
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
|
+
errorSpacing,
|
|
40
|
+
...props
|
|
41
|
+
},
|
|
42
|
+
ref,
|
|
43
|
+
) => {
|
|
44
|
+
const {theme} = useContext(ApplicationContext);
|
|
45
|
+
const [focused, setFocused] = useState(false);
|
|
46
|
+
const [inputValue, setInputValue] = useState(defaultValue ?? '');
|
|
47
|
+
const inputRef = (ref as React.RefObject<TextInput>) ?? useRef<TextInput>();
|
|
44
48
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
+
const onClearText = () => {
|
|
50
|
+
inputRef?.current?.clear();
|
|
51
|
+
_onChangeText('');
|
|
52
|
+
};
|
|
49
53
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
+
const _onChangeText = (text: string) => {
|
|
55
|
+
onChangeText?.(text);
|
|
56
|
+
setInputValue(text);
|
|
57
|
+
};
|
|
54
58
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
+
const _onFocus = (e: NativeSyntheticEvent<TextInputFocusEventData>) => {
|
|
60
|
+
setFocused(true);
|
|
61
|
+
onFocus?.(e);
|
|
62
|
+
};
|
|
59
63
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
+
const _onBlur = (e: NativeSyntheticEvent<TextInputFocusEventData>) => {
|
|
65
|
+
setFocused(false);
|
|
66
|
+
onBlur?.(e);
|
|
67
|
+
};
|
|
64
68
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
69
|
+
const renderCountingView = () => {
|
|
70
|
+
return (
|
|
71
|
+
<View style={styles.countingView}>
|
|
72
|
+
<Text color={theme.colors.text.hint} typography={'description_xs'}>
|
|
73
|
+
{`${inputValue.length}/${maxLength}`}
|
|
74
|
+
</Text>
|
|
75
|
+
</View>
|
|
76
|
+
);
|
|
77
|
+
};
|
|
78
|
+
const renderInputView = () => {
|
|
79
|
+
const disabledColor = theme.colors.text.disable;
|
|
80
|
+
let textColor = theme.colors.text.default;
|
|
81
|
+
let placeholderColor = theme.colors.text.hint;
|
|
78
82
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
+
if (disabled) {
|
|
84
|
+
textColor = disabledColor;
|
|
85
|
+
placeholderColor = disabledColor;
|
|
86
|
+
}
|
|
83
87
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
/>
|
|
126
|
-
</View>
|
|
127
|
-
{focused && inputValue.length > 0 && (
|
|
128
|
-
<TouchableOpacity style={styles.iconWrapper} onPress={onClearText}>
|
|
129
|
-
<Icon
|
|
130
|
-
source="24_navigation_close_circle_full"
|
|
131
|
-
size={16}
|
|
132
|
-
color={theme.colors.text.hint}
|
|
88
|
+
return (
|
|
89
|
+
<View
|
|
90
|
+
style={[
|
|
91
|
+
styles.textAreaWrapper,
|
|
92
|
+
{
|
|
93
|
+
height: height || DEFAULT_HEIGHT,
|
|
94
|
+
backgroundColor: theme.colors.background.surface,
|
|
95
|
+
},
|
|
96
|
+
getBorderColor(theme, focused, errorMessage, disabled),
|
|
97
|
+
]}>
|
|
98
|
+
<FloatingView
|
|
99
|
+
floatingValue={floatingValue}
|
|
100
|
+
floatingIconColor={floatingIconColor}
|
|
101
|
+
disabled={disabled}
|
|
102
|
+
floatingIcon={floatingIcon}
|
|
103
|
+
required={required}
|
|
104
|
+
/>
|
|
105
|
+
<View style={styles.rowArea}>
|
|
106
|
+
<View style={styles.textAreaView}>
|
|
107
|
+
<TextInput
|
|
108
|
+
{...props}
|
|
109
|
+
accessibilityLabel={`TextInput`}
|
|
110
|
+
ref={inputRef}
|
|
111
|
+
editable={!disabled}
|
|
112
|
+
textAlignVertical="top"
|
|
113
|
+
style={[
|
|
114
|
+
styles.textArea,
|
|
115
|
+
{
|
|
116
|
+
color: textColor,
|
|
117
|
+
},
|
|
118
|
+
]}
|
|
119
|
+
maxLength={maxLength}
|
|
120
|
+
textBreakStrategy="highQuality"
|
|
121
|
+
multiline={true}
|
|
122
|
+
value={value}
|
|
123
|
+
onChangeText={_onChangeText}
|
|
124
|
+
onFocus={_onFocus}
|
|
125
|
+
onBlur={_onBlur}
|
|
126
|
+
placeholder={placeholder}
|
|
127
|
+
selectionColor={theme.colors.primary}
|
|
128
|
+
placeholderTextColor={placeholderColor}
|
|
133
129
|
/>
|
|
134
|
-
</
|
|
135
|
-
|
|
130
|
+
</View>
|
|
131
|
+
{focused && inputValue.length > 0 && (
|
|
132
|
+
<TouchableOpacity
|
|
133
|
+
style={styles.iconWrapper}
|
|
134
|
+
onPress={onClearText}>
|
|
135
|
+
<Icon
|
|
136
|
+
source="24_navigation_close_circle_full"
|
|
137
|
+
size={16}
|
|
138
|
+
color={theme.colors.text.hint}
|
|
139
|
+
/>
|
|
140
|
+
</TouchableOpacity>
|
|
141
|
+
)}
|
|
142
|
+
</View>
|
|
143
|
+
{renderCountingView()}
|
|
136
144
|
</View>
|
|
137
|
-
|
|
145
|
+
);
|
|
146
|
+
};
|
|
147
|
+
|
|
148
|
+
return (
|
|
149
|
+
<View
|
|
150
|
+
style={styles.wrapper}
|
|
151
|
+
accessibilityLabel={`InputTextArea/${floatingValue}`}>
|
|
152
|
+
{renderInputView()}
|
|
153
|
+
<ErrorView errorMessage={errorMessage} errorSpacing={errorSpacing} />
|
|
138
154
|
</View>
|
|
139
155
|
);
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
return (
|
|
143
|
-
<View
|
|
144
|
-
style={styles.wrapper}
|
|
145
|
-
accessibilityLabel={`InputTextArea/${floatingValue}`}>
|
|
146
|
-
{renderInputView()}
|
|
147
|
-
<ErrorView errorMessage={errorMessage} errorSpacing={errorSpacing} />
|
|
148
|
-
</View>
|
|
149
|
-
);
|
|
150
|
-
};
|
|
156
|
+
},
|
|
157
|
+
);
|
|
151
158
|
|
|
152
159
|
InputTextArea.defaultProps = {
|
|
153
160
|
maxLength: MAX_LENGTH,
|
package/Input/index.tsx
CHANGED
|
@@ -59,6 +59,11 @@ export interface InputProps extends TextInputProps {
|
|
|
59
59
|
* Defaults to `false` if not provided.
|
|
60
60
|
*/
|
|
61
61
|
errorSpacing?: boolean;
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* If true, the icon of input will use be show indicator loading.
|
|
65
|
+
*/
|
|
66
|
+
loading?: boolean;
|
|
62
67
|
}
|
|
63
68
|
|
|
64
69
|
type InputPropsWithoutSizeAndIcon = Omit<
|
package/Loader/DotLoader.tsx
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
import React, {FC, useContext} from 'react';
|
|
2
|
-
import {View, ViewProps} from 'react-native';
|
|
3
2
|
import AnimatedLottieView from 'lottie-react-native';
|
|
4
3
|
import animation from '../Assets/DotAnimation.json';
|
|
5
4
|
import {ApplicationContext} from '../Application';
|
|
6
5
|
import {hexToRGBA} from './utils';
|
|
6
|
+
import {LoaderProps} from './types';
|
|
7
7
|
|
|
8
|
-
const DotLoader: FC<
|
|
8
|
+
const DotLoader: FC<LoaderProps> = ({color}) => {
|
|
9
9
|
const {theme} = useContext(ApplicationContext);
|
|
10
10
|
|
|
11
11
|
const arrayColor = [
|
|
12
|
-
theme.colors.primary,
|
|
13
|
-
theme.colors.
|
|
14
|
-
theme.colors.primary,
|
|
12
|
+
color ?? theme.colors.primary,
|
|
13
|
+
theme.colors.background.surface,
|
|
14
|
+
color ?? theme.colors.primary,
|
|
15
15
|
];
|
|
16
16
|
|
|
17
17
|
let source: any = animation;
|
|
@@ -26,13 +26,11 @@ const DotLoader: FC<ViewProps> = ({style}) => {
|
|
|
26
26
|
});
|
|
27
27
|
|
|
28
28
|
return (
|
|
29
|
-
<
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
/>
|
|
35
|
-
</View>
|
|
29
|
+
<AnimatedLottieView
|
|
30
|
+
source={source}
|
|
31
|
+
style={{width: 52, height: 18}}
|
|
32
|
+
autoPlay
|
|
33
|
+
/>
|
|
36
34
|
);
|
|
37
35
|
};
|
|
38
36
|
|
package/Loader/Loader.tsx
CHANGED
|
@@ -3,12 +3,11 @@ import {LoaderProps} from './types';
|
|
|
3
3
|
import DotLoader from './DotLoader';
|
|
4
4
|
import Spinner from './Spinner';
|
|
5
5
|
|
|
6
|
-
const Loader: FC<LoaderProps> = ({type = 'dot',
|
|
6
|
+
const Loader: FC<LoaderProps> = ({type = 'dot', ...props}) => {
|
|
7
7
|
if (type === 'spinner') {
|
|
8
|
-
return <Spinner
|
|
8
|
+
return <Spinner {...props} key={props.color} />;
|
|
9
9
|
}
|
|
10
|
-
|
|
11
|
-
return <DotLoader style={style} />;
|
|
10
|
+
return <DotLoader {...props} key={props.color} />;
|
|
12
11
|
};
|
|
13
12
|
|
|
14
13
|
export default Loader;
|
package/Loader/Spinner.tsx
CHANGED
|
@@ -1,30 +1,28 @@
|
|
|
1
1
|
import React, {FC, useContext} from 'react';
|
|
2
|
-
import {View, ViewProps} from 'react-native';
|
|
3
2
|
import AnimatedLottieView from 'lottie-react-native';
|
|
4
3
|
import animation from '../Assets/SpinnerAnimation.json';
|
|
5
4
|
import {hexToRGBA} from './utils';
|
|
6
5
|
import {ApplicationContext} from '../Application';
|
|
6
|
+
import {LoaderProps} from './types';
|
|
7
7
|
|
|
8
|
-
const Spinner: FC<
|
|
8
|
+
const Spinner: FC<LoaderProps> = ({color}) => {
|
|
9
9
|
const {theme} = useContext(ApplicationContext);
|
|
10
10
|
|
|
11
11
|
let source: any = animation;
|
|
12
12
|
source.assets[0].layers.forEach((layer: any) => {
|
|
13
13
|
layer.shapes[0].it.forEach((item: any) => {
|
|
14
14
|
if (item.ty === 'fl' && item.c) {
|
|
15
|
-
item.c.k = hexToRGBA(theme.colors.primary);
|
|
15
|
+
item.c.k = hexToRGBA(color ?? theme.colors.primary);
|
|
16
16
|
}
|
|
17
17
|
});
|
|
18
18
|
});
|
|
19
19
|
|
|
20
20
|
return (
|
|
21
|
-
<
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
/>
|
|
27
|
-
</View>
|
|
21
|
+
<AnimatedLottieView
|
|
22
|
+
source={source}
|
|
23
|
+
style={{width: 24, height: 24}}
|
|
24
|
+
autoPlay
|
|
25
|
+
/>
|
|
28
26
|
);
|
|
29
27
|
};
|
|
30
28
|
|
package/Loader/types.ts
CHANGED
|
@@ -2,10 +2,12 @@ import {ViewStyle} from 'react-native';
|
|
|
2
2
|
|
|
3
3
|
export type LoaderProps = {
|
|
4
4
|
type?: 'dot' | 'spinner';
|
|
5
|
+
color?: string;
|
|
5
6
|
style?: ViewStyle | ViewStyle[];
|
|
6
7
|
};
|
|
7
8
|
|
|
8
9
|
export type ProgressBarProps = {
|
|
9
10
|
percent: number;
|
|
11
|
+
color?: string;
|
|
10
12
|
style?: ViewStyle | ViewStyle[];
|
|
11
13
|
};
|
package/Text/utils.ts
CHANGED