@momo-kits/foundation 0.81.51-beta.0 → 0.81.52

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 (71) hide show
  1. package/Application/{BottomTab/index.tsx → BottomTab.tsx} +18 -42
  2. package/Application/Components.tsx +91 -356
  3. package/Application/ModalScreen.tsx +185 -14
  4. package/Application/Navigation.ts +19 -5
  5. package/Application/NavigationContainer.tsx +72 -62
  6. package/Application/Navigator.ts +48 -154
  7. package/Application/StackScreen.tsx +32 -289
  8. package/Application/index.ts +15 -13
  9. package/Application/types.ts +35 -81
  10. package/Application/utils.tsx +30 -76
  11. package/Assets/icon_bank.json +1 -1
  12. package/Badge/Badge.tsx +1 -1
  13. package/Badge/index.tsx +1 -2
  14. package/Badge/styles.ts +6 -50
  15. package/Button/index.tsx +26 -44
  16. package/CheckBox/index.tsx +26 -37
  17. package/CheckBox/types.ts +3 -5
  18. package/Consts/colors+spacing+radius.ts +0 -14
  19. package/Icon/index.tsx +8 -9
  20. package/Icon/types.ts +2 -2
  21. package/IconButton/index.tsx +14 -24
  22. package/Image/index.tsx +8 -23
  23. package/Image/types.ts +0 -2
  24. package/Input/Input.tsx +26 -116
  25. package/Input/InputDropDown.tsx +51 -66
  26. package/Input/InputMoney.tsx +15 -106
  27. package/Input/InputOTP.tsx +26 -49
  28. package/Input/InputSearch.tsx +99 -252
  29. package/Input/InputTextArea.tsx +6 -26
  30. package/Input/common.tsx +22 -48
  31. package/Input/index.tsx +77 -112
  32. package/Input/styles.ts +11 -48
  33. package/Input/utils.ts +1 -1
  34. package/Layout/Card.tsx +3 -4
  35. package/Layout/GridSystem.tsx +1 -1
  36. package/Layout/ItemList.tsx +2 -3
  37. package/Layout/Screen.tsx +121 -242
  38. package/Layout/Section.tsx +3 -4
  39. package/Layout/styles.ts +13 -11
  40. package/Layout/types.ts +1 -1
  41. package/Layout/utils.ts +4 -4
  42. package/Loader/index.tsx +0 -2
  43. package/Pagination/PaginationScroll.tsx +2 -2
  44. package/Pagination/styles.ts +1 -1
  45. package/Popup/PopupNotify.tsx +46 -57
  46. package/Popup/PopupPromotion.tsx +8 -6
  47. package/Popup/types.ts +7 -1
  48. package/Radio/index.tsx +20 -35
  49. package/Radio/types.ts +3 -5
  50. package/Switch/index.tsx +18 -32
  51. package/Switch/types.ts +3 -5
  52. package/Tag/index.tsx +2 -9
  53. package/Tag/styles.ts +2 -3
  54. package/Tag/types.ts +0 -12
  55. package/Text/index.tsx +5 -24
  56. package/Text/styles.ts +8 -8
  57. package/Title/index.tsx +103 -170
  58. package/Title/styles.ts +9 -36
  59. package/Title/types.ts +48 -16
  60. package/code-scanner.js +16 -125
  61. package/index.ts +0 -7
  62. package/package.json +7 -8
  63. package/publish.sh +21 -16
  64. package/tsconfig.json +1 -1
  65. package/Application/BottomSheet.tsx +0 -216
  66. package/Application/BottomTab/BottomTabBar.tsx +0 -278
  67. package/Application/Localize.ts +0 -44
  68. package/Application/constants.ts +0 -9
  69. package/Badge/BadgeDotAnimation.tsx +0 -95
  70. package/Input/TextTyping.tsx +0 -113
  71. package/Layout/FloatingButton.tsx +0 -168
@@ -1,55 +1,63 @@
1
1
  import React, {useContext} from 'react';
2
- import {TouchableOpacity, View} from 'react-native';
3
- import {ApplicationContext, ComponentContext} from '../Application';
4
- import {Icon} from '../Icon';
2
+ import {TextInput, TouchableOpacity, View} from 'react-native';
3
+ import {ApplicationContext} from '../Application';
4
+ import styles from './styles';
5
5
  import {ErrorView, FloatingView, getBorderColor, getSizeStyle} from './common';
6
6
  import {InputDropDownProps} from './index';
7
- import {Text} from '../Text';
8
- import styles from './styles';
9
- import {Spacing} from '../Consts';
7
+ import {Icon} from '../Icon';
8
+ import {Loader} from '../Loader';
9
+ import {Styles} from '../Consts';
10
10
 
11
11
  const InputDropDown = ({
12
12
  value,
13
13
  floatingValue,
14
14
  floatingIcon,
15
- onPressFloatingIcon,
16
15
  size = 'small',
17
16
  onPress,
18
17
  placeholder,
19
18
  errorMessage,
19
+ icon = 'arrow_chevron_down_small',
20
20
  disabled = false,
21
21
  floatingIconColor,
22
+ iconColor,
22
23
  required = false,
23
24
  errorSpacing,
25
+ loading = false,
24
26
  leadingIcon,
25
27
  leadingIconColor,
26
28
  style,
27
- params,
28
- accessibilityLabel,
29
- hintText,
30
- multiline,
29
+ ...props
31
30
  }: InputDropDownProps) => {
32
31
  const {theme} = useContext(ApplicationContext);
32
+ const full = !!value || !!placeholder;
33
+
34
+ const renderIcon = (color: string | undefined) => {
35
+ if (loading) {
36
+ return <Loader type={'spinner'} color={color} />;
37
+ }
38
+ if (icon) {
39
+ return <Icon color={color} source={icon} size={24} />;
40
+ }
41
+ };
33
42
 
34
- /**
35
- * Render the input view
36
- */
37
43
  const renderInputView = () => {
38
44
  const disabledColor = theme.colors.text.disable;
39
45
  let textColor = theme.colors.text.default;
40
46
  let placeholderColor = theme.colors.text.hint;
47
+ let iconTintColor = iconColor;
41
48
 
42
49
  if (disabled) {
43
50
  textColor = disabledColor;
44
51
  placeholderColor = disabledColor;
52
+ iconTintColor = disabledColor;
45
53
  }
46
54
 
47
55
  return (
48
56
  <View
49
57
  style={[
50
- styles.inputDropDownWrapper,
58
+ styles.inputWrapper,
51
59
  {backgroundColor: theme.colors.background.surface},
52
- getSizeStyle(size, multiline),
60
+ getSizeStyle(size),
53
61
  getBorderColor(theme, false, errorMessage, disabled),
54
62
  ]}>
55
63
  <FloatingView
@@ -58,18 +66,10 @@ const InputDropDown = ({
58
66
  disabled={disabled}
59
67
  required={required}
60
68
  floatingIcon={floatingIcon}
61
- onPress={onPressFloatingIcon}
62
69
  />
63
- <View style={styles.inputDropDownView}>
70
+ <View style={full ? styles.inputView : Styles.row}>
64
71
  {!!leadingIcon && (
65
- <View
66
- style={[
67
- styles.leadingIconContainerDropDown,
68
- {
69
- marginTop: Spacing.M,
70
- marginRight: Spacing.S,
71
- },
72
- ]}>
72
+ <View style={styles.leadingIconContainer}>
73
73
  <Icon
74
74
  color={leadingIconColor}
75
75
  source={leadingIcon}
@@ -77,52 +77,37 @@ const InputDropDown = ({
77
77
  />
78
78
  </View>
79
79
  )}
80
- <View
81
- accessibilityLabel={accessibilityLabel}
82
- style={styles.textViewDropDown}>
83
- <Text
84
- numberOfLines={multiline ? undefined : 1}
85
- typography={'body_default_regular'}
86
- color={value ? textColor : placeholderColor}>
87
- {value || placeholder}
88
- </Text>
89
- </View>
90
- </View>
91
- <View
92
- style={[
93
- styles.iconViewDropDown,
94
- {
95
- alignItems: multiline ? 'flex-start' : 'center',
96
- paddingTop: multiline ? Spacing.M : 0,
97
- },
98
- ]}>
99
- <Icon source={'arrow_chevron_down_small'} />
80
+ {full && (
81
+ <TextInput
82
+ {...props}
83
+ onPressIn={onPress}
84
+ editable={false}
85
+ textAlignVertical="top"
86
+ style={[
87
+ styles.input,
88
+ {
89
+ color: textColor,
90
+ fontFamily: `${theme.font}-Regular`,
91
+ },
92
+ ]}
93
+ textBreakStrategy="highQuality"
94
+ value={value}
95
+ placeholder={placeholder}
96
+ selectionColor={theme.colors.primary}
97
+ placeholderTextColor={placeholderColor}
98
+ />
99
+ )}
100
100
  </View>
101
+ <View style={styles.iconView}>{renderIcon(iconTintColor)}</View>
101
102
  </View>
102
103
  );
103
104
  };
104
105
 
105
106
  return (
106
- <ComponentContext.Provider
107
- value={{
108
- componentName: 'InputDropDown',
109
- params,
110
- state: 'enabled',
111
- componentLabel: floatingValue,
112
- componentId: accessibilityLabel,
113
- }}>
114
- <TouchableOpacity
115
- activeOpacity={0.6}
116
- onPress={onPress}
117
- style={[style, styles.wrapper]}>
118
- {renderInputView()}
119
- <ErrorView
120
- errorMessage={errorMessage}
121
- errorSpacing={errorSpacing}
122
- hintText={hintText}
123
- />
124
- </TouchableOpacity>
125
- </ComponentContext.Provider>
107
+ <TouchableOpacity onPress={onPress} style={[style, full && styles.wrapper]}>
108
+ {renderInputView()}
109
+ <ErrorView errorMessage={errorMessage} errorSpacing={errorSpacing} />
110
+ </TouchableOpacity>
126
111
  );
127
112
  };
128
113
 
@@ -1,8 +1,6 @@
1
1
  import React, {
2
2
  forwardRef,
3
- ReactNode,
4
3
  useContext,
5
- useEffect,
6
4
  useImperativeHandle,
7
5
  useRef,
8
6
  useState,
@@ -14,14 +12,12 @@ import {
14
12
  TouchableOpacity,
15
13
  View,
16
14
  } from 'react-native';
17
- import {ApplicationContext, ComponentContext} from '../Application';
18
- import {Icon} from '../Icon';
15
+ import {ApplicationContext} from '../Application';
16
+ import styles from './styles';
19
17
  import {ErrorView, FloatingView, getBorderColor, getSizeStyle} from './common';
20
18
  import {InputMoneyProps} from './index';
21
- import styles from './styles';
19
+ import {Icon} from '../Icon';
22
20
  import {formatMoneyToNumber, formatNumberToMoney} from './utils';
23
- import {Text} from '../Text';
24
- import {Loader} from '../Loader';
25
21
 
26
22
  const InputMoney = forwardRef(
27
23
  (
@@ -30,41 +26,24 @@ const InputMoney = forwardRef(
30
26
  floatingValue,
31
27
  floatingIcon,
32
28
  size = 'small',
33
- loading,
34
29
  onBlur,
35
30
  onFocus,
36
31
  errorMessage,
37
32
  icon,
38
- iconColor,
39
- onPressIcon,
40
- trailing,
41
- trailingColor,
42
- onPressTrailing,
43
33
  disabled = false,
44
34
  floatingIconColor,
35
+ iconColor,
45
36
  required = false,
46
37
  errorSpacing,
47
38
  style,
48
- params,
49
39
  defaultValue = '',
50
- accessibilityLabel,
51
- hintText,
52
- value: _value,
53
- onPressFloatingIcon,
54
40
  ...props
55
41
  }: InputMoneyProps,
56
- ref
42
+ ref,
57
43
  ) => {
58
44
  const {theme} = useContext(ApplicationContext);
59
45
  const [focused, setFocused] = useState(false);
60
- const inputRef = useRef<TextInput>(null);
61
-
62
- useEffect(() => {
63
- if (_value) {
64
- setValue(validateText(_value));
65
- onChangeText?.(formatMoneyToNumber(_value, 'đ').toString());
66
- }
67
- }, [_value]);
46
+ const inputRef = (ref as React.RefObject<TextInput>) ?? useRef<TextInput>();
68
47
 
69
48
  const validateText = (text: string) => {
70
49
  const valueFormat = formatMoneyToNumber(text, 'đ');
@@ -72,7 +51,7 @@ const InputMoney = forwardRef(
72
51
  };
73
52
 
74
53
  const [value, setValue] = useState(
75
- defaultValue ? validateText(defaultValue) : ''
54
+ defaultValue ? validateText(defaultValue) : '',
76
55
  );
77
56
 
78
57
  const onClearText = () => {
@@ -91,9 +70,6 @@ const InputMoney = forwardRef(
91
70
 
92
71
  useImperativeHandle(ref, () => {
93
72
  return {
94
- clear: onClearText,
95
- focus: () => inputRef.current?.focus(),
96
- blur: () => inputRef.current?.blur(),
97
73
  setText: _onChangeText,
98
74
  };
99
75
  });
@@ -108,51 +84,11 @@ const InputMoney = forwardRef(
108
84
  onBlur?.(e);
109
85
  };
110
86
 
111
- /**
112
- * Render trailing icon or text
113
- * @param color
114
- */
115
- const renderTrailing = (color?: string) => {
116
- if (loading) {
117
- return <Loader type={'spinner'} color={color} style={styles.icon} />;
118
- }
119
-
120
- if (icon || trailing) {
121
- const renderIconTouchable = (icon: ReactNode) => {
122
- return (
123
- <TouchableOpacity
124
- onPress={onPressTrailing ?? onPressIcon}
125
- style={styles.icon}>
126
- {icon}
127
- </TouchableOpacity>
128
- );
129
- };
130
- const trailingValue = icon || trailing;
131
- if (trailingValue?.includes('_') || trailingValue?.includes('http')) {
132
- return renderIconTouchable(
133
- <Icon
134
- color={color}
135
- source={(icon || trailing) as string}
136
- size={24}
137
- />
138
- );
139
- }
140
- return renderIconTouchable(
141
- <Text
142
- typography="action_xs_bold"
143
- color={color ?? theme.colors.primary}
144
- numberOfLines={1}>
145
- {trailingValue!.substring(0, 15)}
146
- </Text>
147
- );
148
- }
149
- };
150
-
151
87
  const renderInputView = () => {
152
88
  const disabledColor = theme.colors.text.disable;
153
89
  let textColor = theme.colors.text.default;
154
90
  let placeholderColor = theme.colors.text.hint;
155
- let iconTintColor = trailingColor ?? iconColor;
91
+ let iconTintColor = iconColor;
156
92
 
157
93
  if (disabled) {
158
94
  textColor = disabledColor;
@@ -174,13 +110,12 @@ const InputMoney = forwardRef(
174
110
  disabled={disabled}
175
111
  required={required}
176
112
  floatingIcon={floatingIcon}
177
- onPress={onPressFloatingIcon}
178
113
  />
179
114
  <View style={styles.inputView}>
180
115
  <TextInput
181
116
  {...props}
182
- accessibilityLabel={accessibilityLabel}
183
117
  editable={!disabled}
118
+ textAlignVertical="top"
184
119
  ref={inputRef}
185
120
  keyboardType={'number-pad'}
186
121
  style={[
@@ -210,45 +145,19 @@ const InputMoney = forwardRef(
210
145
  />
211
146
  </TouchableOpacity>
212
147
  )}
213
- {renderTrailing(iconTintColor)}
148
+ {!!icon && <Icon color={iconTintColor} source={icon} />}
214
149
  </View>
215
150
  </View>
216
151
  );
217
152
  };
218
153
 
219
- let inputState = 'active';
220
-
221
- if (value && value?.length > 0) {
222
- inputState = 'filled';
223
- }
224
- if (errorMessage && errorMessage?.length > 0) {
225
- inputState = 'error';
226
- }
227
-
228
- if (disabled) {
229
- inputState = 'disabled';
230
- }
231
-
232
154
  return (
233
- <ComponentContext.Provider
234
- value={{
235
- componentName: 'InputMoney',
236
- params,
237
- componentLabel: floatingValue,
238
- state: inputState,
239
- componentId: accessibilityLabel,
240
- }}>
241
- <View style={[style, styles.wrapper]}>
242
- {renderInputView()}
243
- <ErrorView
244
- errorMessage={errorMessage}
245
- errorSpacing={errorSpacing}
246
- hintText={hintText}
247
- />
248
- </View>
249
- </ComponentContext.Provider>
155
+ <View style={[style, styles.wrapper]}>
156
+ {renderInputView()}
157
+ <ErrorView errorMessage={errorMessage} errorSpacing={errorSpacing} />
158
+ </View>
250
159
  );
251
- }
160
+ },
252
161
  );
253
162
 
254
163
  export default InputMoney;
@@ -15,12 +15,12 @@ import {
15
15
  TouchableOpacity,
16
16
  View,
17
17
  } from 'react-native';
18
- import {ApplicationContext, ComponentContext} from '../Application';
19
- import {Spacing} from '../Consts';
20
- import {scaleSize, Text} from '../Text';
21
- import {ErrorView, getBorderColor} from './common';
22
18
  import {CaretProps, InputOTPProps} from './index';
19
+ import {scaleSize, Text} from '../Text';
23
20
  import styles from './styles';
21
+ import {ErrorView, getBorderColor} from './common';
22
+ import {ApplicationContext} from '../Application';
23
+ import {Spacing} from '../Consts';
24
24
 
25
25
  const OTPCaret: FC<CaretProps> = ({index, length}) => {
26
26
  const DURATION = 300;
@@ -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)) &&
@@ -70,36 +70,29 @@ const InputOTP = forwardRef(
70
70
  length,
71
71
  errorMessage,
72
72
  errorSpacing,
73
- floatingValue = 'Label',
73
+ floatingValue,
74
+ floatingIconColor,
75
+ floatingIcon,
74
76
  placeholder,
75
77
  onChangeText,
76
- onBlur,
77
78
  onFocus,
79
+ onBlur,
78
80
  dataType = 'number',
79
- params,
80
81
  style,
81
- accessibilityLabel,
82
- hintText,
83
82
  ...props
84
83
  }: InputOTPProps,
85
- ref
84
+ ref,
86
85
  ) => {
87
86
  const MAX_LENGTH = 10;
88
87
  const [value, setValue] = useState('');
89
88
  const [focused, setFocused] = useState(false);
90
- const inputRef = useRef<TextInput | null>(null);
89
+ const inputRef = useRef<TextInput>(null);
91
90
  const {theme} = useContext(ApplicationContext);
92
91
 
93
92
  useImperativeHandle(ref, () => ({
94
93
  onChangeText: (text: string) => {
95
94
  _onChangeText(text);
96
95
  },
97
- focus: () => {
98
- setFocused(true);
99
- inputRef.current?.focus()
100
- },
101
- blur: () => inputRef.current?.blur(),
102
- setText: (text: string) => _onChangeText(text),
103
96
  }));
104
97
 
105
98
  const onFocusInput = () => {
@@ -126,16 +119,16 @@ const InputOTP = forwardRef(
126
119
  onChangeText?.(text);
127
120
  };
128
121
 
129
- const renderInputs = (inputLength: number) => {
122
+ const renderInputs = (length: number) => {
130
123
  const TextInputs: React.ReactNode[] = [];
131
- for (let i = 0; i < inputLength; i++) {
124
+ for (let i = 0; i < length; i++) {
132
125
  TextInputs.push(
133
126
  <View>
134
127
  {focused && value.length === i ? (
135
- <OTPCaret index={i} length={inputLength} />
128
+ <OTPCaret index={i} length={length} />
136
129
  ) : (
137
130
  <Text
138
- style={i !== inputLength - 1 && {marginRight: Spacing.L}}
131
+ style={i !== length - 1 && {marginRight: Spacing.L}}
139
132
  color={
140
133
  !!value[i]
141
134
  ? theme.colors.text.default
@@ -147,7 +140,7 @@ const InputOTP = forwardRef(
147
140
  {value[i] || '-'}
148
141
  </Text>
149
142
  )}
150
- </View>
143
+ </View>,
151
144
  );
152
145
  }
153
146
  return TextInputs;
@@ -201,9 +194,7 @@ const InputOTP = forwardRef(
201
194
  styles.otpFloatingView,
202
195
  {backgroundColor: theme.colors.background.surface},
203
196
  ]}>
204
- <Text
205
- typography={'description_default_regular'}
206
- color={theme.colors.text.hint}>
197
+ <Text typography={'description_default_regular'}>
207
198
  {floatingValue}
208
199
  </Text>
209
200
  </View>
@@ -214,12 +205,11 @@ const InputOTP = forwardRef(
214
205
  <View style={styles.inputView}>
215
206
  <TextInput
216
207
  {...props}
217
- accessibilityLabel={accessibilityLabel}
218
208
  ref={inputRef}
219
209
  value={value}
220
210
  onChangeText={_onChangeText}
221
211
  keyboardType={dataType === 'number' ? 'number-pad' : 'default'}
222
- onFocus={onFocus}
212
+ onFocus={onFocusInput}
223
213
  onBlur={onBlurInput}
224
214
  style={{opacity: 0}}
225
215
  selectionColor={theme.colors.primary}
@@ -231,28 +221,15 @@ const InputOTP = forwardRef(
231
221
  };
232
222
 
233
223
  return (
234
- <ComponentContext.Provider
235
- value={{
236
- componentName: 'InputOTP',
237
- params,
238
- componentLabel: floatingValue,
239
- state: 'enabled',
240
- componentId: accessibilityLabel,
241
- }}>
242
- <TouchableOpacity
243
- activeOpacity={1}
244
- onPress={onFocusInput}
245
- style={[style, styles.otpWrapper]}>
246
- {renderInputView()}
247
- <ErrorView
248
- errorMessage={errorMessage}
249
- errorSpacing={errorSpacing}
250
- hintText={hintText}
251
- />
252
- </TouchableOpacity>
253
- </ComponentContext.Provider>
224
+ <TouchableOpacity
225
+ activeOpacity={1}
226
+ onPress={onFocusInput}
227
+ style={[style, styles.otpWrapper]}>
228
+ {renderInputView()}
229
+ <ErrorView errorMessage={errorMessage} errorSpacing={errorSpacing} />
230
+ </TouchableOpacity>
254
231
  );
255
- }
232
+ },
256
233
  );
257
234
 
258
235
  export default InputOTP;