@momo-kits/foundation 0.75.1-beta.3

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.
Files changed (76) hide show
  1. package/Assets/header-background.png +0 -0
  2. package/Assets/icon.json +3947 -0
  3. package/Button/index.tsx +247 -0
  4. package/Button/styles.ts +41 -0
  5. package/CheckBox/index.tsx +61 -0
  6. package/CheckBox/styles.ts +15 -0
  7. package/CheckBox/types.ts +10 -0
  8. package/Consts/colors+spacing+radius.ts +214 -0
  9. package/Consts/index.ts +3 -0
  10. package/Consts/styles.ts +78 -0
  11. package/Consts/theme.ts +121 -0
  12. package/Divider/index.tsx +19 -0
  13. package/Icon/index.tsx +37 -0
  14. package/Icon/types.ts +8 -0
  15. package/IconButton/index.tsx +128 -0
  16. package/IconButton/styles.ts +19 -0
  17. package/Image/index.tsx +80 -0
  18. package/Image/styles.ts +13 -0
  19. package/Image/types.ts +3 -0
  20. package/Input/Input.tsx +142 -0
  21. package/Input/InputMoney.tsx +132 -0
  22. package/Input/InputSearch.tsx +161 -0
  23. package/Input/InputTextArea.tsx +152 -0
  24. package/Input/common.tsx +125 -0
  25. package/Input/index.tsx +41 -0
  26. package/Input/styles.ts +122 -0
  27. package/Input/utils.ts +63 -0
  28. package/Layout/Card.tsx +87 -0
  29. package/Layout/GridSystem.tsx +124 -0
  30. package/Layout/ScreenContainer.tsx +122 -0
  31. package/Layout/Section.tsx +143 -0
  32. package/Layout/index.ts +16 -0
  33. package/Layout/types.ts +21 -0
  34. package/Layout/utils.ts +50 -0
  35. package/Navigation/BottomTab.tsx +39 -0
  36. package/Navigation/Components.tsx +329 -0
  37. package/Navigation/ModalScreen.tsx +207 -0
  38. package/Navigation/Navigation.ts +38 -0
  39. package/Navigation/NavigationButton.tsx +54 -0
  40. package/Navigation/NavigationContainer.tsx +82 -0
  41. package/Navigation/Navigator.ts +66 -0
  42. package/Navigation/Observer.ts +79 -0
  43. package/Navigation/StackScreen.tsx +40 -0
  44. package/Navigation/index.ts +14 -0
  45. package/Navigation/types.ts +149 -0
  46. package/Navigation/utils.tsx +167 -0
  47. package/Pagination/Dot.tsx +16 -0
  48. package/Pagination/PaginationDot.tsx +33 -0
  49. package/Pagination/PaginationNumber.tsx +23 -0
  50. package/Pagination/PaginationScroll.tsx +88 -0
  51. package/Pagination/PaginationWhiteDot.tsx +32 -0
  52. package/Pagination/index.tsx +25 -0
  53. package/Pagination/styles.ts +47 -0
  54. package/Pagination/types.ts +19 -0
  55. package/Popup/PopupNotify.tsx +215 -0
  56. package/Popup/PopupPromotion.tsx +77 -0
  57. package/Popup/index.tsx +4 -0
  58. package/Popup/types.ts +22 -0
  59. package/Radio/index.tsx +65 -0
  60. package/Radio/styles.ts +11 -0
  61. package/Radio/types.ts +10 -0
  62. package/Skeleton/index.tsx +72 -0
  63. package/Skeleton/styles.ts +5 -0
  64. package/Skeleton/types.ts +3 -0
  65. package/Switch/index.tsx +40 -0
  66. package/Switch/styles.ts +23 -0
  67. package/Switch/types.ts +8 -0
  68. package/Tag/index.tsx +79 -0
  69. package/Tag/styles.ts +24 -0
  70. package/Tag/types.ts +10 -0
  71. package/Text/index.tsx +110 -0
  72. package/Text/styles.ts +35 -0
  73. package/Text/types.ts +40 -0
  74. package/index.ts +38 -0
  75. package/package.json +41 -0
  76. package/publish.sh +26 -0
@@ -0,0 +1,121 @@
1
+ import {Context, Theme} from '../Navigation/types';
2
+ import {Colors} from './colors+spacing+radius';
3
+
4
+ const defaultTheme: Theme = {
5
+ dark: false,
6
+ colors: {
7
+ primary: Colors.pink_03,
8
+ secondary: Colors.pink_07,
9
+ background: {
10
+ default: '#f2f2f6',
11
+ surface: Colors.black_01,
12
+ tonal: Colors.pink_09,
13
+ pressed: '#dfdfe6',
14
+ selected: Colors.pink_10,
15
+ disable: '#ebebf2',
16
+ },
17
+ text: {
18
+ default: Colors.black_17,
19
+ secondary: Colors.black_15,
20
+ hint: Colors.black_12,
21
+ disable: Colors.black_08,
22
+ },
23
+ border: {
24
+ default: Colors.black_04,
25
+ disable: Colors.black_02,
26
+ },
27
+ success: {
28
+ primary: Colors.green_03,
29
+ secondary: Colors.green_07,
30
+ container: Colors.green_08,
31
+ },
32
+ warning: {
33
+ primary: Colors.orange_03,
34
+ secondary: Colors.orange_07,
35
+ container: Colors.orange_08,
36
+ },
37
+ error: {
38
+ primary: Colors.red_03,
39
+ secondary: Colors.red_07,
40
+ container: Colors.red_08,
41
+ },
42
+ highlight: {
43
+ primary: Colors.mint_03,
44
+ secondary: Colors.mint_07,
45
+ container: Colors.mint_08,
46
+ },
47
+ interactive: {
48
+ primary: Colors.blue_03,
49
+ secondary: Colors.blue_07,
50
+ container: Colors.blue_08,
51
+ },
52
+ },
53
+ font: 'SFProText',
54
+ assets: {
55
+ headerBackground:
56
+ 'https://static.momocdn.net/app/img/app/img/header-background.png',
57
+ },
58
+ };
59
+
60
+ const defaultDarkTheme: Theme = {
61
+ dark: true,
62
+ colors: {
63
+ primary: Colors.pink_04,
64
+ secondary: Colors.pink_08,
65
+ background: {
66
+ default: '#121212', // Dark background
67
+ surface: '#1e1e1e', // Slightly lighter surface background
68
+ tonal: Colors.pink_10,
69
+ pressed: '#1a1a1a', // Pressed state background
70
+ selected: Colors.pink_11,
71
+ disable: '#303030', // Disabled state background
72
+ },
73
+ text: {
74
+ default: '#ffffff', // White text for better contrast
75
+ secondary: '#b0b0b0', // Light gray secondary text
76
+ hint: '#727272', // Hint text color
77
+ disable: '#505050', // Disabled text color
78
+ },
79
+ border: {
80
+ default: '#2a2a2a', // Darker borders
81
+ disable: '#242424', // Disabled state border color
82
+ },
83
+ success: {
84
+ primary: Colors.green_03,
85
+ secondary: Colors.green_07,
86
+ container: Colors.green_08,
87
+ },
88
+ warning: {
89
+ primary: Colors.orange_03,
90
+ secondary: Colors.orange_07,
91
+ container: Colors.orange_08,
92
+ },
93
+ error: {
94
+ primary: Colors.red_03,
95
+ secondary: Colors.red_07,
96
+ container: Colors.red_08,
97
+ },
98
+ highlight: {
99
+ primary: Colors.mint_03,
100
+ secondary: Colors.mint_07,
101
+ container: Colors.mint_08,
102
+ },
103
+ interactive: {
104
+ primary: Colors.blue_03,
105
+ secondary: Colors.blue_07,
106
+ container: Colors.blue_08,
107
+ },
108
+ },
109
+ font: 'SFProText',
110
+ assets: {
111
+ headerBackground:
112
+ 'https://static.momocdn.net/app/img/app/img/header-background.png',
113
+ },
114
+ };
115
+
116
+ const defaultContext: Context = {
117
+ theme: defaultTheme,
118
+ navigator: undefined,
119
+ };
120
+
121
+ export {defaultContext, defaultTheme, defaultDarkTheme};
@@ -0,0 +1,19 @@
1
+ import React, {useContext} from 'react';
2
+ import {View} from 'react-native';
3
+ import {ApplicationContext} from '../Navigation';
4
+
5
+ const Divider = () => {
6
+ const {theme} = useContext(ApplicationContext);
7
+
8
+ return (
9
+ <View
10
+ style={{
11
+ height: 1,
12
+ width: '100%',
13
+ backgroundColor: theme.colors.border.default,
14
+ }}
15
+ />
16
+ );
17
+ };
18
+
19
+ export {Divider};
package/Icon/index.tsx ADDED
@@ -0,0 +1,37 @@
1
+ import React, {useContext} from 'react';
2
+ import IconSources from '../Assets/icon.json';
3
+ import {IconProps} from './types';
4
+ import {ApplicationContext} from '../Navigation';
5
+ import {Image} from '../Image';
6
+
7
+ const Icon: React.FC<IconProps> = ({source, size, color, style = {}}) => {
8
+ const {theme} = useContext(ApplicationContext);
9
+
10
+ /**
11
+ * get icon source maps or remote http
12
+ */
13
+ const getIconSource = (): any => {
14
+ if (source && !source.includes('http')) {
15
+ let icon: {[key: string]: {uri: string}} = IconSources;
16
+ return icon[source] ?? icon.ic_warning;
17
+ }
18
+ return {uri: source};
19
+ };
20
+
21
+ return (
22
+ <Image
23
+ accessibilityLabel={`Icon/${getIconSource()}`}
24
+ loading={false}
25
+ source={getIconSource()}
26
+ style={[style, {width: size, height: size}]}
27
+ tintColor={color ?? theme.colors.text.default}
28
+ />
29
+ );
30
+ };
31
+
32
+ Icon.defaultProps = {
33
+ source: 'ic_back',
34
+ size: 24,
35
+ };
36
+
37
+ export {Icon, IconSources};
package/Icon/types.ts ADDED
@@ -0,0 +1,8 @@
1
+ import {ViewStyle} from 'react-native';
2
+
3
+ export type IconProps = {
4
+ source: string;
5
+ size?: number;
6
+ color?: string;
7
+ style?: ViewStyle;
8
+ };
@@ -0,0 +1,128 @@
1
+ import React, {useContext} from 'react';
2
+ import {
3
+ GestureResponderEvent,
4
+ StyleSheet,
5
+ TouchableOpacity,
6
+ TouchableOpacityProps,
7
+ } from 'react-native';
8
+ import {ApplicationContext} from '../Navigation';
9
+ import {Colors} from '../Consts';
10
+ import {Icon} from '../Icon';
11
+ import styles from './styles';
12
+
13
+ export interface IconButtonProps extends TouchableOpacityProps {
14
+ icon: string;
15
+ type?: 'primary' | 'tonal' | 'secondary' | 'danger' | 'outline' | 'disabled';
16
+ size?: 'large' | 'small';
17
+ }
18
+
19
+ const IconButton: React.FC<IconButtonProps> = ({
20
+ type,
21
+ icon,
22
+ size,
23
+ onPress,
24
+ ...rest
25
+ }) => {
26
+ const {theme} = useContext(ApplicationContext);
27
+
28
+ /**
29
+ * get size icon button
30
+ */
31
+ const getSizeStyle = () => {
32
+ if (size === 'small') {
33
+ return styles.small;
34
+ }
35
+ return styles.large;
36
+ };
37
+
38
+ /**
39
+ * get style for icon button by type
40
+ */
41
+ const getTypeStyle = () => {
42
+ switch (type) {
43
+ case 'disabled':
44
+ return {
45
+ backgroundColor: theme.colors.background.disable,
46
+ };
47
+ case 'primary':
48
+ return {backgroundColor: theme.colors.primary};
49
+ case 'secondary':
50
+ return {
51
+ backgroundColor: theme.colors.background.surface,
52
+ borderWidth: 1,
53
+ borderColor: theme.colors.border.default,
54
+ };
55
+ case 'outline':
56
+ return {
57
+ backgroundColor: theme.colors.background.surface,
58
+ borderWidth: 1,
59
+ borderColor: theme.colors.primary,
60
+ };
61
+ case 'tonal':
62
+ return {
63
+ backgroundColor: theme.colors.background.tonal,
64
+ };
65
+ case 'danger':
66
+ return {
67
+ backgroundColor: theme.colors.error.primary,
68
+ };
69
+ default:
70
+ return {backgroundColor: theme.colors.primary};
71
+ }
72
+ };
73
+
74
+ /**
75
+ * get color for icon
76
+ */
77
+ const getIconColor = () => {
78
+ switch (type) {
79
+ case 'disabled':
80
+ return theme.colors.text.disable;
81
+ case 'primary':
82
+ return Colors.black_01;
83
+ case 'danger':
84
+ return Colors.black_01;
85
+ case 'tonal':
86
+ return theme.colors.primary;
87
+ case 'secondary':
88
+ return theme.colors.text.default;
89
+ case 'outline':
90
+ return theme.colors.primary;
91
+ default:
92
+ return Colors.black_01;
93
+ }
94
+ };
95
+
96
+ /**
97
+ * handle press
98
+ * @param e
99
+ */
100
+ const onPressButton = (e: GestureResponderEvent) => {
101
+ if (type === 'disabled') {
102
+ return () => {};
103
+ }
104
+ onPress?.(e);
105
+ };
106
+
107
+ const activeOpacity = type === 'disabled' ? 0.75 : 0.5;
108
+ const buttonStyle = StyleSheet.flatten([getTypeStyle(), getSizeStyle()]);
109
+ const iconSize = size === 'small' ? 16 : 24;
110
+
111
+ return (
112
+ <TouchableOpacity
113
+ {...rest}
114
+ accessibilityLabel={`IconButton/${icon}`}
115
+ activeOpacity={activeOpacity}
116
+ onPress={onPressButton}
117
+ style={buttonStyle}>
118
+ <Icon size={iconSize} source={icon} color={getIconColor()} />
119
+ </TouchableOpacity>
120
+ );
121
+ };
122
+
123
+ IconButton.defaultProps = {
124
+ type: 'primary',
125
+ disabled: false,
126
+ };
127
+
128
+ export {IconButton};
@@ -0,0 +1,19 @@
1
+ import {StyleSheet} from 'react-native';
2
+ import {Radius} from '../Consts';
3
+
4
+ export default StyleSheet.create({
5
+ large: {
6
+ width: 48,
7
+ height: 48,
8
+ borderRadius: Radius.XL,
9
+ justifyContent: 'center',
10
+ alignItems: 'center',
11
+ },
12
+ small: {
13
+ width: 40,
14
+ height: 40,
15
+ borderRadius: Radius.XL,
16
+ justifyContent: 'center',
17
+ alignItems: 'center',
18
+ },
19
+ });
@@ -0,0 +1,80 @@
1
+ import React, {useContext, useState} from 'react';
2
+ import {StyleProp, StyleSheet, View, ViewStyle} from 'react-native';
3
+ import FastImage from 'react-native-fast-image';
4
+ import styles from './styles';
5
+ import {ApplicationContext} from '../Navigation';
6
+ import {Skeleton} from '../Skeleton';
7
+ import {Icon} from '../Icon';
8
+ import {Styles} from '../Consts';
9
+ import {FastImagePropsWithoutStyle} from './types';
10
+
11
+ export interface ImageProps extends FastImagePropsWithoutStyle {
12
+ style?: StyleProp<ViewStyle>;
13
+ loading?: boolean;
14
+ accessibilityLabel?: string;
15
+ }
16
+
17
+ const Image: React.FC<ImageProps> = ({
18
+ style,
19
+ source,
20
+ accessibilityLabel,
21
+ ...rest
22
+ }) => {
23
+ const {theme} = useContext(ApplicationContext);
24
+ const [loading, setLoading] = useState(rest.loading);
25
+ const [fail, setFail] = useState(false);
26
+
27
+ /**
28
+ * render content loading | fail | rendered
29
+ * @returns {JSX.Element}
30
+ */
31
+ const renderContent = () => {
32
+ if (loading || fail) {
33
+ let content = (
34
+ <Skeleton style={[StyleSheet.absoluteFill, styles.image]} />
35
+ );
36
+ if (fail) {
37
+ content = (
38
+ <View style={Styles.flexCenter}>
39
+ <Icon source="media_fail" color={theme.colors.text.disable} />
40
+ </View>
41
+ );
42
+ }
43
+ return (
44
+ <View
45
+ style={[
46
+ StyleSheet.absoluteFill,
47
+ styles.image,
48
+ {backgroundColor: theme.colors.background.disable},
49
+ ]}>
50
+ {content}
51
+ </View>
52
+ );
53
+ }
54
+ };
55
+
56
+ return (
57
+ <View
58
+ style={[styles.container, style]}
59
+ accessibilityLabel={`Image/${accessibilityLabel ?? source}`}>
60
+ <FastImage
61
+ {...rest}
62
+ source={source}
63
+ style={styles.image}
64
+ onLoad={() => {
65
+ setFail(false);
66
+ setLoading(rest.loading);
67
+ }}
68
+ onLoadEnd={() => setLoading(false)}
69
+ onError={() => setFail(true)}
70
+ />
71
+ {renderContent()}
72
+ </View>
73
+ );
74
+ };
75
+
76
+ Image.defaultProps = {
77
+ loading: true,
78
+ };
79
+
80
+ export {Image};
@@ -0,0 +1,13 @@
1
+ import {StyleSheet} from 'react-native';
2
+
3
+ export default StyleSheet.create({
4
+ container: {
5
+ overflow: 'hidden',
6
+ alignItems: 'center',
7
+ justifyContent: 'center',
8
+ },
9
+ image: {
10
+ width: '100%',
11
+ height: '100%',
12
+ },
13
+ });
package/Image/types.ts ADDED
@@ -0,0 +1,3 @@
1
+ import {FastImageProps} from 'react-native-fast-image';
2
+
3
+ export type FastImagePropsWithoutStyle = Omit<FastImageProps, 'style'>;
@@ -0,0 +1,142 @@
1
+ import React, {FC, useContext, useEffect, 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 {
12
+ checkTyping,
13
+ ErrorView,
14
+ FloatingView,
15
+ getBorderColor,
16
+ getSizeStyle,
17
+ } from './common';
18
+ import {InputProps} from './index';
19
+ import {Icon} from '../Icon';
20
+
21
+ const Input: FC<InputProps> = ({
22
+ value,
23
+ onChangeText,
24
+ floatingValue,
25
+ floatingIcon,
26
+ size,
27
+ placeholder,
28
+ onBlur,
29
+ onFocus,
30
+ errorMessage,
31
+ icon,
32
+ disabled,
33
+ floatingIconColor,
34
+ iconColor,
35
+ required,
36
+ defaultValue,
37
+ ...props
38
+ }) => {
39
+ const {theme} = useContext(ApplicationContext);
40
+ const [focused, setFocused] = useState(false);
41
+ const [haveValue, setHaveValue] = useState(!!value || !!defaultValue);
42
+
43
+ const inputRef = useRef<any>(null);
44
+
45
+ const onClearText = () => {
46
+ inputRef?.current?.clear();
47
+ _onChangeText('');
48
+ };
49
+
50
+ const _onChangeText = (text: string) => {
51
+ checkTyping(text, haveValue, setHaveValue);
52
+ onChangeText?.(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 renderInputView = () => {
66
+ const disabledColor = theme.colors.text.disable;
67
+ let textColor = theme.colors.text.default;
68
+ let placeholderColor = theme.colors.text.hint;
69
+ let iconTintColor = iconColor;
70
+
71
+ if (disabled) {
72
+ textColor = disabledColor;
73
+ placeholderColor = disabledColor;
74
+ iconTintColor = disabledColor;
75
+ }
76
+
77
+ return (
78
+ <View
79
+ style={[
80
+ getSizeStyle(size),
81
+ getBorderColor(focused, errorMessage, disabled),
82
+ styles.inputWrapper,
83
+ {backgroundColor: theme.colors.background.surface},
84
+ ]}>
85
+ <FloatingView
86
+ floatingValue={floatingValue}
87
+ floatingIconColor={floatingIconColor}
88
+ disabled={disabled}
89
+ required={required}
90
+ floatingIcon={floatingIcon}
91
+ />
92
+ <View style={styles.inputView}>
93
+ <TextInput
94
+ {...props}
95
+ editable={!disabled}
96
+ textAlignVertical="top"
97
+ ref={inputRef}
98
+ style={[
99
+ styles.input,
100
+ {
101
+ color: textColor,
102
+ },
103
+ ]}
104
+ textBreakStrategy="highQuality"
105
+ value={value}
106
+ onChangeText={_onChangeText}
107
+ onFocus={_onFocus}
108
+ onBlur={_onBlur}
109
+ placeholder={placeholder}
110
+ selectionColor={theme.colors.primary}
111
+ placeholderTextColor={placeholderColor}
112
+ />
113
+ </View>
114
+ <View style={styles.iconView}>
115
+ {focused && haveValue && (
116
+ <TouchableOpacity style={styles.iconWrapper} onPress={onClearText}>
117
+ <Icon
118
+ source="24_navigation_close_circle_full"
119
+ size={16}
120
+ color={theme.colors.text.hint}
121
+ />
122
+ </TouchableOpacity>
123
+ )}
124
+ {!!icon && <Icon color={iconTintColor} source={icon} size={24} />}
125
+ </View>
126
+ </View>
127
+ );
128
+ };
129
+
130
+ return (
131
+ <View style={styles.wrapper} accessibilityLabel={`Input`}>
132
+ {renderInputView()}
133
+ <ErrorView errorMessage={errorMessage} />
134
+ </View>
135
+ );
136
+ };
137
+
138
+ Input.defaultProps = {
139
+ size: 'small',
140
+ };
141
+
142
+ export default Input;
@@ -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;