@momo-kits/foundation 0.92.26-beta.2 → 0.92.26-beta.21
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 +24 -26
- package/Application/BottomTab/index.tsx +1 -2
- package/Application/Components.tsx +235 -39
- package/Application/ModalScreen.tsx +2 -2
- package/Application/Navigation.ts +4 -18
- package/Application/StackScreen.tsx +12 -3
- package/Application/index.ts +0 -2
- package/Application/types.ts +17 -6
- package/Application/utils.tsx +60 -18
- package/Button/index.tsx +0 -1
- package/Input/InputMoney.tsx +3 -3
- package/Input/InputOTP.tsx +4 -4
- package/Input/InputSearch.tsx +249 -144
- package/Input/TextTyping.tsx +113 -0
- package/Input/index.tsx +19 -1
- package/Input/styles.ts +10 -3
- package/Layout/Screen.tsx +171 -92
- package/Layout/styles.ts +0 -6
- package/Layout/types.ts +1 -1
- package/package.json +1 -1
package/Application/types.ts
CHANGED
|
@@ -115,6 +115,7 @@ export type BottomSheetParams = {
|
|
|
115
115
|
title: string;
|
|
116
116
|
surface?: boolean;
|
|
117
117
|
};
|
|
118
|
+
useNativeModal?: boolean;
|
|
118
119
|
surface?: boolean;
|
|
119
120
|
onDismiss?: (type?: string) => void;
|
|
120
121
|
barrierDismissible?: boolean;
|
|
@@ -145,19 +146,29 @@ export type RuntimeToolType = {
|
|
|
145
146
|
key: string;
|
|
146
147
|
};
|
|
147
148
|
|
|
148
|
-
export interface NavigationOptions
|
|
149
|
+
export interface NavigationOptions
|
|
150
|
+
extends Omit<StackNavigationOptions, 'headerRight'> {
|
|
149
151
|
preventBack?: PopupNotifyProps;
|
|
150
152
|
onPressLeftHeader?: () => void;
|
|
151
153
|
surface?: boolean;
|
|
152
154
|
hiddenBack?: boolean;
|
|
153
155
|
customTitle?: TitleCustomProps;
|
|
154
|
-
|
|
155
|
-
pinnedTool?: PinnedToolType;
|
|
156
|
-
runtimeTools?: RuntimeToolType[];
|
|
157
|
-
preventClose?: PopupNotifyProps;
|
|
158
|
-
};
|
|
156
|
+
headerRight?: HeaderRightToolkit | HeaderRightActions | any;
|
|
159
157
|
}
|
|
160
158
|
|
|
159
|
+
export type HeaderRightToolkit = {
|
|
160
|
+
type?: 'toolkit';
|
|
161
|
+
pinnedTool?: PinnedToolType;
|
|
162
|
+
runtimeTools?: RuntimeToolType[];
|
|
163
|
+
preventClose?: PopupNotifyProps;
|
|
164
|
+
useMore?: boolean;
|
|
165
|
+
};
|
|
166
|
+
|
|
167
|
+
export type HeaderRightActions = {
|
|
168
|
+
type?: 'icon';
|
|
169
|
+
buttons: NavigationButtonProps[];
|
|
170
|
+
};
|
|
171
|
+
|
|
161
172
|
export interface HeaderBackProps extends NavigationButtonProps {
|
|
162
173
|
preventBack?: PopupNotifyProps;
|
|
163
174
|
onPressLeftHeader?: () => void;
|
package/Application/utils.tsx
CHANGED
|
@@ -7,11 +7,13 @@ import {
|
|
|
7
7
|
HeaderBackground,
|
|
8
8
|
HeaderCustom,
|
|
9
9
|
HeaderLeft,
|
|
10
|
+
HeaderRight,
|
|
10
11
|
HeaderTitle,
|
|
11
|
-
HeaderToolkitAction,
|
|
12
12
|
} from './Components';
|
|
13
|
-
import {NavigationOptions
|
|
13
|
+
import {NavigationOptions} from './types';
|
|
14
14
|
import {Colors} from '../Consts';
|
|
15
|
+
import Navigation from './Navigation';
|
|
16
|
+
import {LayoutChangeEvent} from 'react-native';
|
|
15
17
|
|
|
16
18
|
/**
|
|
17
19
|
* default options for stack screen
|
|
@@ -22,7 +24,7 @@ const getStackOptions = (): StackNavigationOptions => {
|
|
|
22
24
|
headerTitle: HeaderTitle,
|
|
23
25
|
headerBackground: (props: any) => <HeaderBackground {...props} />,
|
|
24
26
|
headerLeft: (props: any) => <HeaderLeft {...props} />,
|
|
25
|
-
headerRight: (props: any) => <
|
|
27
|
+
headerRight: (props: any) => <HeaderRight {...props} />,
|
|
26
28
|
headerTintColor: Colors.black_01,
|
|
27
29
|
};
|
|
28
30
|
};
|
|
@@ -72,33 +74,42 @@ const getModalOptions = (): StackNavigationOptions => {
|
|
|
72
74
|
/**
|
|
73
75
|
* build react-navigation options
|
|
74
76
|
*/
|
|
75
|
-
const getOptions = (params: NavigationOptions,
|
|
77
|
+
const getOptions = (params: NavigationOptions, navigation?: Navigation) => {
|
|
76
78
|
let options = {};
|
|
77
79
|
|
|
80
|
+
/**
|
|
81
|
+
* left header factory
|
|
82
|
+
*/
|
|
78
83
|
if (
|
|
79
84
|
typeof params.onPressLeftHeader === 'function' ||
|
|
80
85
|
params.preventBack !== undefined ||
|
|
81
86
|
typeof params.hiddenBack === 'boolean'
|
|
82
87
|
) {
|
|
88
|
+
let headerLeft: any = (props: any) => (
|
|
89
|
+
<HeaderLeft
|
|
90
|
+
{...props}
|
|
91
|
+
preventBack={params.preventBack}
|
|
92
|
+
onPressLeftHeader={params.onPressLeftHeader}
|
|
93
|
+
/>
|
|
94
|
+
);
|
|
95
|
+
if (params.hiddenBack) {
|
|
96
|
+
headerLeft = null;
|
|
97
|
+
}
|
|
83
98
|
options = {
|
|
84
99
|
...options,
|
|
85
|
-
headerLeft
|
|
86
|
-
? null
|
|
87
|
-
: (props: any) => (
|
|
88
|
-
<HeaderLeft
|
|
89
|
-
{...props}
|
|
90
|
-
preventBack={params.preventBack}
|
|
91
|
-
onPressLeftHeader={params.onPressLeftHeader}
|
|
92
|
-
/>
|
|
93
|
-
),
|
|
100
|
+
headerLeft,
|
|
94
101
|
};
|
|
95
102
|
}
|
|
96
103
|
|
|
104
|
+
/**
|
|
105
|
+
* surface header style
|
|
106
|
+
*/
|
|
97
107
|
if (typeof params.surface === 'boolean') {
|
|
108
|
+
console.warn('surface options is deprecated, headerType instead in screen');
|
|
98
109
|
if (params.surface) {
|
|
99
110
|
options = {
|
|
100
111
|
...options,
|
|
101
|
-
headerTintColor:
|
|
112
|
+
headerTintColor: Colors.black_17,
|
|
102
113
|
headerBackground: () => (
|
|
103
114
|
<HeaderBackground image={null} useSurface={true} />
|
|
104
115
|
),
|
|
@@ -112,7 +123,13 @@ const getOptions = (params: NavigationOptions, theme: Theme) => {
|
|
|
112
123
|
}
|
|
113
124
|
}
|
|
114
125
|
|
|
126
|
+
/**
|
|
127
|
+
* custom title
|
|
128
|
+
*/
|
|
115
129
|
if (params.customTitle) {
|
|
130
|
+
console.warn(
|
|
131
|
+
'customTitle options is deprecated, please used headerTitle instead'
|
|
132
|
+
);
|
|
116
133
|
options = {
|
|
117
134
|
...options,
|
|
118
135
|
headerTitleAlign: 'left',
|
|
@@ -122,12 +139,37 @@ const getOptions = (params: NavigationOptions, theme: Theme) => {
|
|
|
122
139
|
};
|
|
123
140
|
}
|
|
124
141
|
|
|
125
|
-
|
|
142
|
+
/**
|
|
143
|
+
* header right
|
|
144
|
+
*/
|
|
145
|
+
if (params.headerRight) {
|
|
146
|
+
let headerRight: any = (props: any) => {
|
|
147
|
+
return (
|
|
148
|
+
<HeaderRight
|
|
149
|
+
{...props}
|
|
150
|
+
{...params.headerRight}
|
|
151
|
+
onLayout={(e: LayoutChangeEvent) => {
|
|
152
|
+
navigation?.onHeaderRightChange?.(e.nativeEvent.layout.width);
|
|
153
|
+
}}
|
|
154
|
+
/>
|
|
155
|
+
);
|
|
156
|
+
};
|
|
157
|
+
if (typeof params.headerRight === 'function') {
|
|
158
|
+
headerRight = (props: any) => {
|
|
159
|
+
return (
|
|
160
|
+
<HeaderRight
|
|
161
|
+
{...props}
|
|
162
|
+
onLayout={(e: LayoutChangeEvent) => {
|
|
163
|
+
navigation?.onHeaderRightChange?.(e.nativeEvent.layout.width);
|
|
164
|
+
}}>
|
|
165
|
+
{params.headerRight(props)}
|
|
166
|
+
</HeaderRight>
|
|
167
|
+
);
|
|
168
|
+
};
|
|
169
|
+
}
|
|
126
170
|
options = {
|
|
127
171
|
...options,
|
|
128
|
-
headerRight
|
|
129
|
-
return <HeaderToolkitAction {...params.toolkitParams} {...props} />;
|
|
130
|
-
},
|
|
172
|
+
headerRight,
|
|
131
173
|
};
|
|
132
174
|
}
|
|
133
175
|
|
package/Button/index.tsx
CHANGED
package/Input/InputMoney.tsx
CHANGED
|
@@ -44,7 +44,7 @@ const InputMoney = forwardRef(
|
|
|
44
44
|
value: _value,
|
|
45
45
|
...props
|
|
46
46
|
}: InputMoneyProps,
|
|
47
|
-
ref
|
|
47
|
+
ref
|
|
48
48
|
) => {
|
|
49
49
|
const {theme} = useContext(ApplicationContext);
|
|
50
50
|
const [focused, setFocused] = useState(false);
|
|
@@ -63,7 +63,7 @@ const InputMoney = forwardRef(
|
|
|
63
63
|
};
|
|
64
64
|
|
|
65
65
|
const [value, setValue] = useState(
|
|
66
|
-
defaultValue ? validateText(defaultValue) : ''
|
|
66
|
+
defaultValue ? validateText(defaultValue) : ''
|
|
67
67
|
);
|
|
68
68
|
|
|
69
69
|
const onClearText = () => {
|
|
@@ -198,7 +198,7 @@ const InputMoney = forwardRef(
|
|
|
198
198
|
</View>
|
|
199
199
|
</ComponentContext.Provider>
|
|
200
200
|
);
|
|
201
|
-
}
|
|
201
|
+
}
|
|
202
202
|
);
|
|
203
203
|
|
|
204
204
|
export default InputMoney;
|
package/Input/InputOTP.tsx
CHANGED
|
@@ -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)) &&
|
|
@@ -81,7 +81,7 @@ const InputOTP = forwardRef(
|
|
|
81
81
|
hintText,
|
|
82
82
|
...props
|
|
83
83
|
}: InputOTPProps,
|
|
84
|
-
ref
|
|
84
|
+
ref
|
|
85
85
|
) => {
|
|
86
86
|
const MAX_LENGTH = 10;
|
|
87
87
|
const [value, setValue] = useState('');
|
|
@@ -143,7 +143,7 @@ const InputOTP = forwardRef(
|
|
|
143
143
|
{value[i] || '-'}
|
|
144
144
|
</Text>
|
|
145
145
|
)}
|
|
146
|
-
</View
|
|
146
|
+
</View>
|
|
147
147
|
);
|
|
148
148
|
}
|
|
149
149
|
return TextInputs;
|
|
@@ -248,7 +248,7 @@ const InputOTP = forwardRef(
|
|
|
248
248
|
</TouchableOpacity>
|
|
249
249
|
</ComponentContext.Provider>
|
|
250
250
|
);
|
|
251
|
-
}
|
|
251
|
+
}
|
|
252
252
|
);
|
|
253
253
|
|
|
254
254
|
export default InputOTP;
|
package/Input/InputSearch.tsx
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import React, {
|
|
2
|
+
FC,
|
|
2
3
|
forwardRef,
|
|
4
|
+
ForwardRefRenderFunction,
|
|
3
5
|
useContext,
|
|
6
|
+
useEffect,
|
|
4
7
|
useImperativeHandle,
|
|
5
8
|
useRef,
|
|
6
9
|
useState,
|
|
@@ -15,177 +18,279 @@ import {
|
|
|
15
18
|
import {ApplicationContext, ComponentContext} from '../Application';
|
|
16
19
|
import {Icon} from '../Icon';
|
|
17
20
|
import {Text} from '../Text';
|
|
18
|
-
import {InputSearchProps} from './index';
|
|
21
|
+
import {InputRef, InputSearchProps} from './index';
|
|
19
22
|
import styles from './styles';
|
|
20
23
|
import {checkTyping} from './utils';
|
|
21
24
|
|
|
22
|
-
const
|
|
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
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
25
|
+
const TextTyping: FC<any> = ({
|
|
26
|
+
data = [],
|
|
27
|
+
timeDelayEnd = 2000,
|
|
28
|
+
timeDelayNextChar = 20,
|
|
29
|
+
}) => {
|
|
30
|
+
const textRef = useRef<TextInput>(null);
|
|
31
|
+
|
|
32
|
+
const currentIndex = useRef<number>(0);
|
|
33
|
+
const currentCharIndex = useRef<number>(0);
|
|
34
|
+
const currentText = useRef('');
|
|
35
|
+
|
|
36
|
+
useEffect(() => {
|
|
37
|
+
setTimeout(() => {
|
|
38
|
+
playAnimation();
|
|
39
|
+
}, 1000);
|
|
40
|
+
}, []);
|
|
41
|
+
|
|
42
|
+
const playAnimation = () => {
|
|
43
|
+
const handleResetList = () => {
|
|
44
|
+
currentIndex.current = 0;
|
|
45
|
+
handleAnimation();
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
const handleAnimation = () => {
|
|
49
|
+
const listChar = data?.[currentIndex.current]?.split('') || [];
|
|
50
|
+
listChar.length !== 0 && showChar(listChar?.[currentCharIndex.current]);
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
currentIndex.current >= data?.length
|
|
54
|
+
? handleResetList()
|
|
55
|
+
: handleAnimation();
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
const showChar = (char?: string) => {
|
|
59
|
+
const handleResetString = () => {
|
|
60
|
+
setTimeout(() => {
|
|
61
|
+
reset();
|
|
62
|
+
}, timeDelayEnd);
|
|
52
63
|
};
|
|
53
64
|
|
|
54
|
-
const
|
|
55
|
-
|
|
56
|
-
|
|
65
|
+
const handleShowChar = () => {
|
|
66
|
+
setTimeout(() => {
|
|
67
|
+
textRef.current?.setNativeProps?.({
|
|
68
|
+
text: currentText.current + char,
|
|
69
|
+
});
|
|
70
|
+
currentText.current += char;
|
|
71
|
+
currentCharIndex.current++;
|
|
72
|
+
playAnimation();
|
|
73
|
+
}, timeDelayNextChar);
|
|
57
74
|
};
|
|
58
75
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
76
|
+
currentCharIndex.current >= (data?.[currentIndex.current]?.length || 0)
|
|
77
|
+
? handleResetString()
|
|
78
|
+
: handleShowChar();
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
const reset = () => {
|
|
82
|
+
const handleNextString = () => {
|
|
83
|
+
currentIndex.current++;
|
|
84
|
+
playAnimation();
|
|
62
85
|
};
|
|
63
86
|
|
|
64
|
-
const
|
|
65
|
-
|
|
66
|
-
|
|
87
|
+
const handleReset = () => {
|
|
88
|
+
setTimeout(() => {
|
|
89
|
+
textRef.current?.setNativeProps?.({
|
|
90
|
+
text: currentText.current.slice(0, -1),
|
|
91
|
+
});
|
|
92
|
+
currentText.current = currentText.current.slice(0, -1);
|
|
93
|
+
currentCharIndex.current--;
|
|
94
|
+
reset();
|
|
95
|
+
}, timeDelayNextChar);
|
|
67
96
|
};
|
|
68
97
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
}
|
|
76
|
-
|
|
98
|
+
currentCharIndex.current <= 0 ? handleNextString() : handleReset();
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
return (
|
|
102
|
+
<TextInput
|
|
103
|
+
style={styles.inputStyle}
|
|
104
|
+
ref={textRef}
|
|
105
|
+
editable={false}
|
|
106
|
+
autoCorrect={false}
|
|
107
|
+
pointerEvents={'none'}
|
|
108
|
+
numberOfLines={1}
|
|
109
|
+
/>
|
|
110
|
+
);
|
|
111
|
+
};
|
|
112
|
+
|
|
113
|
+
const InputSearch: ForwardRefRenderFunction<InputRef, InputSearchProps> = (
|
|
114
|
+
{
|
|
115
|
+
placeholder,
|
|
116
|
+
onFocus,
|
|
117
|
+
onBlur,
|
|
118
|
+
iconColor,
|
|
119
|
+
value,
|
|
120
|
+
onChangeText,
|
|
121
|
+
icon,
|
|
122
|
+
buttonText = 'Hủy',
|
|
123
|
+
showButtonText = true,
|
|
124
|
+
style,
|
|
125
|
+
defaultValue,
|
|
126
|
+
onPressButtonText,
|
|
127
|
+
params,
|
|
128
|
+
hasColorBG = false,
|
|
129
|
+
accessibilityLabel,
|
|
130
|
+
typingData = [],
|
|
131
|
+
onPress,
|
|
132
|
+
...props
|
|
133
|
+
},
|
|
134
|
+
ref
|
|
135
|
+
) => {
|
|
136
|
+
const {theme} = useContext(ApplicationContext);
|
|
137
|
+
const [focused, setFocused] = useState(false);
|
|
138
|
+
const [haveValue, setHaveValue] = useState(!!value || !!defaultValue);
|
|
139
|
+
const inputRef = useRef<TextInput | null>(null);
|
|
77
140
|
|
|
78
|
-
|
|
141
|
+
const _onFocus = (e: NativeSyntheticEvent<TextInputFocusEventData>) => {
|
|
142
|
+
setFocused(true);
|
|
143
|
+
onFocus?.(e);
|
|
144
|
+
};
|
|
145
|
+
|
|
146
|
+
const _onBlur = (e: NativeSyntheticEvent<TextInputFocusEventData>) => {
|
|
147
|
+
setFocused(false);
|
|
148
|
+
onBlur?.(e);
|
|
149
|
+
};
|
|
150
|
+
|
|
151
|
+
const onClearText = () => {
|
|
152
|
+
inputRef?.current?.clear();
|
|
153
|
+
_onChangeText('');
|
|
154
|
+
};
|
|
155
|
+
|
|
156
|
+
const _onChangeText = (text: string) => {
|
|
157
|
+
checkTyping(text, haveValue, setHaveValue);
|
|
158
|
+
onChangeText?.(text);
|
|
159
|
+
};
|
|
160
|
+
|
|
161
|
+
useImperativeHandle(ref, () => {
|
|
162
|
+
return {
|
|
163
|
+
clear: onClearText,
|
|
164
|
+
focus: () => inputRef.current?.focus(),
|
|
165
|
+
blur: () => inputRef.current?.blur(),
|
|
166
|
+
setText: (text: string) => _onChangeText(text),
|
|
167
|
+
};
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
const renderInputView = () => {
|
|
171
|
+
if (typingData?.length > 0) {
|
|
79
172
|
return (
|
|
80
|
-
<
|
|
81
|
-
{...props}
|
|
82
|
-
accessibilityLabel={accessibilityLabel}
|
|
83
|
-
textAlignVertical="center"
|
|
84
|
-
ref={inputRef}
|
|
173
|
+
<TouchableOpacity
|
|
85
174
|
style={[
|
|
86
175
|
styles.searchInput,
|
|
87
176
|
{
|
|
88
|
-
|
|
177
|
+
justifyContent: 'center',
|
|
89
178
|
},
|
|
90
179
|
]}
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
placeholder={placeholder}
|
|
96
|
-
selectionColor={theme.colors.primary}
|
|
97
|
-
placeholderTextColor={theme.colors.text.hint}
|
|
98
|
-
/>
|
|
99
|
-
);
|
|
100
|
-
};
|
|
101
|
-
|
|
102
|
-
const renderIconView = () => {
|
|
103
|
-
return (
|
|
104
|
-
<View
|
|
105
|
-
style={{
|
|
106
|
-
flexDirection: 'row',
|
|
107
|
-
}}>
|
|
108
|
-
{focused && haveValue && (
|
|
109
|
-
<TouchableOpacity style={styles.iconWrapper} onPress={onClearText}>
|
|
110
|
-
<Icon
|
|
111
|
-
source="24_navigation_close_circle_full"
|
|
112
|
-
size={16}
|
|
113
|
-
color={theme.colors.text.hint}
|
|
114
|
-
/>
|
|
115
|
-
</TouchableOpacity>
|
|
116
|
-
)}
|
|
117
|
-
{!!icon && (
|
|
118
|
-
<View style={{flexDirection: 'row'}}>
|
|
119
|
-
<View
|
|
120
|
-
style={[
|
|
121
|
-
styles.divider,
|
|
122
|
-
{
|
|
123
|
-
backgroundColor: theme.colors.primary,
|
|
124
|
-
},
|
|
125
|
-
]}
|
|
126
|
-
/>
|
|
127
|
-
<Icon
|
|
128
|
-
color={iconColor}
|
|
129
|
-
source={icon}
|
|
130
|
-
style={styles.iconSearchInput}
|
|
131
|
-
/>
|
|
132
|
-
</View>
|
|
133
|
-
)}
|
|
134
|
-
</View>
|
|
180
|
+
onPress={onPress}
|
|
181
|
+
activeOpacity={onPress ? 0.6 : 1}>
|
|
182
|
+
<TextTyping data={typingData} />
|
|
183
|
+
</TouchableOpacity>
|
|
135
184
|
);
|
|
136
|
-
};
|
|
137
|
-
|
|
138
|
-
let inputState = 'empty';
|
|
139
|
-
|
|
140
|
-
if (focused) {
|
|
141
|
-
inputState = 'focus';
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
if (value && value?.length > 0) {
|
|
145
|
-
inputState = 'filled';
|
|
146
185
|
}
|
|
147
186
|
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
187
|
+
return (
|
|
188
|
+
<TextInput
|
|
189
|
+
{...props}
|
|
190
|
+
accessibilityLabel={accessibilityLabel}
|
|
191
|
+
textAlignVertical="center"
|
|
192
|
+
ref={inputRef}
|
|
193
|
+
style={[
|
|
194
|
+
styles.searchInput,
|
|
195
|
+
{
|
|
196
|
+
color: theme.colors.text.default,
|
|
197
|
+
},
|
|
198
|
+
]}
|
|
199
|
+
value={value}
|
|
200
|
+
onChangeText={_onChangeText}
|
|
201
|
+
onFocus={_onFocus}
|
|
202
|
+
onBlur={_onBlur}
|
|
203
|
+
placeholder={placeholder}
|
|
204
|
+
selectionColor={theme.colors.primary}
|
|
205
|
+
placeholderTextColor={theme.colors.text.hint}
|
|
206
|
+
/>
|
|
207
|
+
);
|
|
208
|
+
};
|
|
151
209
|
|
|
210
|
+
const renderIconView = () => {
|
|
152
211
|
return (
|
|
153
|
-
<
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
params,
|
|
157
|
-
state: inputState,
|
|
158
|
-
componentId: accessibilityLabel,
|
|
212
|
+
<View
|
|
213
|
+
style={{
|
|
214
|
+
flexDirection: 'row',
|
|
159
215
|
}}>
|
|
160
|
-
|
|
161
|
-
<
|
|
162
|
-
style={[
|
|
163
|
-
styles.searchInputWrapper,
|
|
164
|
-
{
|
|
165
|
-
backgroundColor,
|
|
166
|
-
},
|
|
167
|
-
]}>
|
|
216
|
+
{focused && haveValue && (
|
|
217
|
+
<TouchableOpacity style={styles.iconWrapper} onPress={onClearText}>
|
|
168
218
|
<Icon
|
|
169
|
-
source=
|
|
170
|
-
size={
|
|
219
|
+
source="24_navigation_close_circle_full"
|
|
220
|
+
size={16}
|
|
171
221
|
color={theme.colors.text.hint}
|
|
172
222
|
/>
|
|
173
|
-
|
|
174
|
-
|
|
223
|
+
</TouchableOpacity>
|
|
224
|
+
)}
|
|
225
|
+
{!!icon && (
|
|
226
|
+
<View style={{flexDirection: 'row'}}>
|
|
227
|
+
<View
|
|
228
|
+
style={[
|
|
229
|
+
styles.divider,
|
|
230
|
+
{
|
|
231
|
+
backgroundColor: theme.colors.primary,
|
|
232
|
+
},
|
|
233
|
+
]}
|
|
234
|
+
/>
|
|
235
|
+
<Icon
|
|
236
|
+
color={iconColor}
|
|
237
|
+
source={icon}
|
|
238
|
+
style={styles.iconSearchInput}
|
|
239
|
+
/>
|
|
175
240
|
</View>
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
<Text
|
|
179
|
-
typography={'action_default_bold'}
|
|
180
|
-
style={styles.textButton}>
|
|
181
|
-
{buttonText}
|
|
182
|
-
</Text>
|
|
183
|
-
</TouchableOpacity>
|
|
184
|
-
)}
|
|
185
|
-
</View>
|
|
186
|
-
</ComponentContext.Provider>
|
|
241
|
+
)}
|
|
242
|
+
</View>
|
|
187
243
|
);
|
|
188
|
-
}
|
|
189
|
-
|
|
244
|
+
};
|
|
245
|
+
|
|
246
|
+
let inputState = 'empty';
|
|
247
|
+
|
|
248
|
+
if (focused) {
|
|
249
|
+
inputState = 'focus';
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
if (value && value?.length > 0) {
|
|
253
|
+
inputState = 'filled';
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
const backgroundColor = hasColorBG
|
|
257
|
+
? theme.colors.background.default
|
|
258
|
+
: theme.colors.background.surface;
|
|
259
|
+
|
|
260
|
+
return (
|
|
261
|
+
<ComponentContext.Provider
|
|
262
|
+
value={{
|
|
263
|
+
componentName: 'InputSearch',
|
|
264
|
+
params,
|
|
265
|
+
state: inputState,
|
|
266
|
+
componentId: accessibilityLabel,
|
|
267
|
+
}}>
|
|
268
|
+
<View style={[style, styles.searchInputContainer]}>
|
|
269
|
+
<View
|
|
270
|
+
style={[
|
|
271
|
+
styles.searchInputWrapper,
|
|
272
|
+
{
|
|
273
|
+
backgroundColor,
|
|
274
|
+
},
|
|
275
|
+
]}>
|
|
276
|
+
<Icon
|
|
277
|
+
source={'navigation_search'}
|
|
278
|
+
size={24}
|
|
279
|
+
color={theme.colors.text.hint}
|
|
280
|
+
/>
|
|
281
|
+
{renderInputView()}
|
|
282
|
+
{renderIconView()}
|
|
283
|
+
</View>
|
|
284
|
+
{showButtonText && (
|
|
285
|
+
<TouchableOpacity onPress={onPressButtonText}>
|
|
286
|
+
<Text typography={'action_default_bold'} style={styles.textButton}>
|
|
287
|
+
{buttonText}
|
|
288
|
+
</Text>
|
|
289
|
+
</TouchableOpacity>
|
|
290
|
+
)}
|
|
291
|
+
</View>
|
|
292
|
+
</ComponentContext.Provider>
|
|
293
|
+
);
|
|
294
|
+
};
|
|
190
295
|
|
|
191
|
-
export default InputSearch;
|
|
296
|
+
export default forwardRef(InputSearch);
|