@momo-kits/foundation 0.92.28 → 0.92.29-beta.0

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.
@@ -65,7 +65,7 @@ const NavigationButton: React.FC<NavigationButtonProps> = ({
65
65
  }, [badgeType, badgeValue]);
66
66
 
67
67
  return (
68
- <View style={{width: scaleSize(28)}}>
68
+ <View style={{width: 28}}>
69
69
  <TouchableOpacity
70
70
  accessibilityLabel={accessibilityLabel}
71
71
  style={[styles.navigationButton, buttonStyle]}
@@ -113,7 +113,7 @@ const HeaderLeft: React.FC<HeaderBackProps> = ({
113
113
  useEffect(() => {
114
114
  const backHandler = BackHandler.addEventListener(
115
115
  'hardwareBackPress',
116
- goBackSafe,
116
+ goBackSafe
117
117
  );
118
118
 
119
119
  return () => backHandler.remove();
@@ -268,7 +268,7 @@ const HeaderRightAction: React.FC<any> = ({children, ...restProps}) => {
268
268
  const valid = child?.type === NavigationButton || child?.type === Fragment;
269
269
  if (__DEV__ && !valid) {
270
270
  console.warn(
271
- 'HeaderRightAction contains element type of NavigationButton, Please check again.',
271
+ 'HeaderRightAction contains element type of NavigationButton, Please check again.'
272
272
  );
273
273
  }
274
274
  return child;
@@ -327,7 +327,7 @@ const HeaderToolkitAction: React.FC<any> = ({
327
327
  (config: any) => {
328
328
  navigator.toolkitConfig = config;
329
329
  setToolConfig(navigator?.toolkitConfig);
330
- },
330
+ }
331
331
  );
332
332
  };
333
333
 
@@ -340,7 +340,7 @@ const HeaderToolkitAction: React.FC<any> = ({
340
340
  const {item} = res;
341
341
  navigator?.toolkitCallback?.(item);
342
342
  getToolkitConfig();
343
- },
343
+ }
344
344
  );
345
345
  };
346
346
 
@@ -357,7 +357,7 @@ const HeaderToolkitAction: React.FC<any> = ({
357
357
  navigator?.maxApi?.dispatchFunction?.(
358
358
  'dismiss',
359
359
  undefined,
360
- undefined,
360
+ undefined
361
361
  );
362
362
  },
363
363
  }}
@@ -388,7 +388,7 @@ const HeaderToolkitAction: React.FC<any> = ({
388
388
  [pinTool?.key],
389
389
  () => {
390
390
  getToolkitConfig();
391
- },
391
+ }
392
392
  );
393
393
  navigator?.toolkitCallback?.(pinTool.key);
394
394
  }}
package/Input/Input.tsx CHANGED
@@ -1,5 +1,6 @@
1
1
  import React, {
2
2
  forwardRef,
3
+ ReactNode,
3
4
  useContext,
4
5
  useImperativeHandle,
5
6
  useRef,
@@ -16,11 +17,15 @@ import {
16
17
  import {ApplicationContext, ComponentContext} from '../Application';
17
18
  import {Icon} from '../Icon';
18
19
  import {Loader} from '../Loader';
20
+ import {Text} from '../Text';
19
21
  import {ErrorView, FloatingView, getBorderColor, getSizeStyle} from './common';
20
22
  import {InputProps} from './index';
21
23
  import styles from './styles';
22
24
  import {checkTyping} from './utils';
23
25
 
26
+ /**
27
+ * Input default component
28
+ */
24
29
  const Input = forwardRef(
25
30
  (
26
31
  {
@@ -34,16 +39,19 @@ const Input = forwardRef(
34
39
  onFocus,
35
40
  errorMessage,
36
41
  icon,
42
+ iconColor,
43
+ onPressIcon,
44
+ trailing,
45
+ trailingColor,
46
+ onPressTrailing,
37
47
  disabled = false,
38
48
  floatingIconColor,
39
- iconColor,
40
49
  required = false,
41
50
  errorSpacing,
42
51
  loading = false,
43
52
  leadingIcon,
44
53
  leadingIconColor,
45
54
  fontWeight = 'Regular',
46
- onPressIcon,
47
55
  secureTextEntry,
48
56
  keyboardType,
49
57
  style,
@@ -53,7 +61,7 @@ const Input = forwardRef(
53
61
  editable = true,
54
62
  ...props
55
63
  }: InputProps,
56
- ref,
64
+ ref
57
65
  ) => {
58
66
  const {theme} = useContext(ApplicationContext);
59
67
  const [focused, setFocused] = useState(false);
@@ -90,7 +98,11 @@ const Input = forwardRef(
90
98
  };
91
99
  });
92
100
 
93
- const renderIcon = (color: string | undefined) => {
101
+ /**
102
+ * Render trailing icon or text
103
+ * @param color
104
+ */
105
+ const renderTrailing = (color?: string) => {
94
106
  if (loading) {
95
107
  return <Loader type={'spinner'} color={color} style={styles.icon} />;
96
108
  }
@@ -109,24 +121,46 @@ const Input = forwardRef(
109
121
  </TouchableOpacity>
110
122
  );
111
123
  }
112
- if (icon) {
113
- return (
114
- <TouchableOpacity
115
- onPress={onPressIcon}
116
- disabled={!onPressIcon}
117
- style={styles.icon}>
118
- <Icon color={color} source={icon} size={24} />
119
- </TouchableOpacity>
124
+ if (icon || trailing) {
125
+ const renderIconTouchable = (icon: ReactNode) => {
126
+ return (
127
+ <TouchableOpacity
128
+ onPress={onPressTrailing ?? onPressIcon}
129
+ style={styles.icon}>
130
+ {icon}
131
+ </TouchableOpacity>
132
+ );
133
+ };
134
+ const trailingValue = icon || trailing;
135
+ if (trailingValue?.includes('_') || trailingValue?.includes('http')) {
136
+ return renderIconTouchable(
137
+ <Icon
138
+ color={color}
139
+ source={(icon || trailing) as string}
140
+ size={24}
141
+ />
142
+ );
143
+ }
144
+ return renderIconTouchable(
145
+ <Text
146
+ typography="action_xs_bold"
147
+ color={color ?? theme.colors.primary}
148
+ numberOfLines={1}>
149
+ {trailingValue!.substring(0, 15)}
150
+ </Text>
120
151
  );
121
152
  }
122
153
  };
123
154
 
155
+ /**
156
+ * Render input view
157
+ */
124
158
  const renderInputView = () => {
125
159
  const disabledColor = theme.colors.text.disable;
126
160
  const secure = secureTextInput && secureTextEntry;
127
161
  let textColor = theme.colors.text.default;
128
162
  let placeholderColor = theme.colors.text.hint;
129
- let iconTintColor = iconColor;
163
+ let iconTintColor = trailingColor ?? iconColor;
130
164
 
131
165
  if (disabled) {
132
166
  textColor = disabledColor;
@@ -204,21 +238,19 @@ const Input = forwardRef(
204
238
  />
205
239
  </TouchableOpacity>
206
240
  )}
207
- {renderIcon(iconTintColor)}
241
+ {renderTrailing(iconTintColor)}
208
242
  </View>
209
243
  </View>
210
244
  );
211
245
  };
212
246
 
213
247
  let inputState = 'active';
214
-
215
248
  if (value && value?.length > 0) {
216
249
  inputState = 'filled';
217
250
  }
218
251
  if (errorMessage && errorMessage?.length > 0) {
219
252
  inputState = 'error';
220
253
  }
221
-
222
254
  if (disabled) {
223
255
  inputState = 'disabled';
224
256
  }
@@ -242,7 +274,7 @@ const Input = forwardRef(
242
274
  </View>
243
275
  </ComponentContext.Provider>
244
276
  );
245
- },
277
+ }
246
278
  );
247
279
 
248
280
  export default Input;
@@ -1,12 +1,12 @@
1
1
  import React, {useContext} from 'react';
2
- import {TextInput, TouchableOpacity, View} from 'react-native';
2
+ import {TouchableOpacity, View} from 'react-native';
3
3
  import {ApplicationContext, ComponentContext} from '../Application';
4
- import {Styles} from '../Consts';
5
4
  import {Icon} from '../Icon';
6
- import {Loader} from '../Loader';
7
5
  import {ErrorView, FloatingView, getBorderColor, getSizeStyle} from './common';
8
6
  import {InputDropDownProps} from './index';
7
+ import {Text} from '../Text';
9
8
  import styles from './styles';
9
+ import {Spacing} from '../Consts';
10
10
 
11
11
  const InputDropDown = ({
12
12
  value,
@@ -16,51 +16,39 @@ const InputDropDown = ({
16
16
  onPress,
17
17
  placeholder,
18
18
  errorMessage,
19
- icon = 'arrow_chevron_down_small',
20
19
  disabled = false,
21
20
  floatingIconColor,
22
- iconColor,
23
21
  required = false,
24
22
  errorSpacing,
25
- loading = false,
26
23
  leadingIcon,
27
24
  leadingIconColor,
28
25
  style,
29
26
  params,
30
27
  accessibilityLabel,
31
28
  hintText,
32
- ...props
29
+ multiline,
33
30
  }: InputDropDownProps) => {
34
31
  const {theme} = useContext(ApplicationContext);
35
- const full = !!value || !!placeholder;
36
-
37
- const renderIcon = (color: string | undefined) => {
38
- if (loading) {
39
- return <Loader type={'spinner'} color={color} />;
40
- }
41
- if (icon) {
42
- return <Icon color={color} source={icon} size={24} />;
43
- }
44
- };
45
32
 
33
+ /**
34
+ * Render the input view
35
+ */
46
36
  const renderInputView = () => {
47
37
  const disabledColor = theme.colors.text.disable;
48
38
  let textColor = theme.colors.text.default;
49
39
  let placeholderColor = theme.colors.text.hint;
50
- let iconTintColor = iconColor;
51
40
 
52
41
  if (disabled) {
53
42
  textColor = disabledColor;
54
43
  placeholderColor = disabledColor;
55
- iconTintColor = disabledColor;
56
44
  }
57
45
 
58
46
  return (
59
47
  <View
60
48
  style={[
61
- styles.inputWrapper,
49
+ styles.inputDropDownWrapper,
62
50
  {backgroundColor: theme.colors.background.surface},
63
- getSizeStyle(size),
51
+ getSizeStyle(size, multiline),
64
52
  getBorderColor(theme, false, errorMessage, disabled),
65
53
  ]}>
66
54
  <FloatingView
@@ -70,9 +58,16 @@ const InputDropDown = ({
70
58
  required={required}
71
59
  floatingIcon={floatingIcon}
72
60
  />
73
- <View style={full ? styles.inputView : Styles.row}>
61
+ <View style={styles.inputDropDownView}>
74
62
  {!!leadingIcon && (
75
- <View style={styles.leadingIconContainer}>
63
+ <View
64
+ style={[
65
+ styles.leadingIconContainerDropDown,
66
+ {
67
+ marginTop: Spacing.M,
68
+ marginRight: Spacing.S,
69
+ },
70
+ ]}>
76
71
  <Icon
77
72
  color={leadingIconColor}
78
73
  source={leadingIcon}
@@ -80,28 +75,27 @@ const InputDropDown = ({
80
75
  />
81
76
  </View>
82
77
  )}
83
- {full && (
84
- <TextInput
85
- {...props}
86
- accessibilityLabel={accessibilityLabel}
87
- onPressIn={onPress}
88
- editable={false}
89
- style={[
90
- styles.input,
91
- {
92
- color: textColor,
93
- fontFamily: `${theme.font}-Regular`,
94
- },
95
- ]}
96
- textBreakStrategy="highQuality"
97
- value={value}
98
- placeholder={placeholder}
99
- selectionColor={theme.colors.primary}
100
- placeholderTextColor={placeholderColor}
101
- />
102
- )}
78
+ <View
79
+ accessibilityLabel={accessibilityLabel}
80
+ style={styles.textViewDropDown}>
81
+ <Text
82
+ numberOfLines={multiline ? undefined : 1}
83
+ typography={'body_default_regular'}
84
+ color={value ? textColor : placeholderColor}>
85
+ {value || placeholder}
86
+ </Text>
87
+ </View>
88
+ </View>
89
+ <View
90
+ style={[
91
+ styles.iconViewDropDown,
92
+ {
93
+ alignItems: multiline ? 'flex-start' : 'center',
94
+ paddingTop: multiline ? Spacing.M : 0,
95
+ },
96
+ ]}>
97
+ <Icon source={'arrow_chevron_down_small'} />
103
98
  </View>
104
- <View style={styles.iconView}>{renderIcon(iconTintColor)}</View>
105
99
  </View>
106
100
  );
107
101
  };
@@ -116,8 +110,9 @@ const InputDropDown = ({
116
110
  componentId: accessibilityLabel,
117
111
  }}>
118
112
  <TouchableOpacity
113
+ activeOpacity={0.6}
119
114
  onPress={onPress}
120
- style={[style, full && styles.wrapper]}>
115
+ style={[style, styles.wrapper]}>
121
116
  {renderInputView()}
122
117
  <ErrorView
123
118
  errorMessage={errorMessage}
@@ -1,5 +1,6 @@
1
1
  import React, {
2
2
  forwardRef,
3
+ ReactNode,
3
4
  useContext,
4
5
  useEffect,
5
6
  useImperativeHandle,
@@ -19,6 +20,8 @@ import {ErrorView, FloatingView, getBorderColor, getSizeStyle} from './common';
19
20
  import {InputMoneyProps} from './index';
20
21
  import styles from './styles';
21
22
  import {formatMoneyToNumber, formatNumberToMoney} from './utils';
23
+ import {Text} from '../Text';
24
+ import {Loader} from '../Loader';
22
25
 
23
26
  const InputMoney = forwardRef(
24
27
  (
@@ -27,13 +30,18 @@ const InputMoney = forwardRef(
27
30
  floatingValue,
28
31
  floatingIcon,
29
32
  size = 'small',
33
+ loading,
30
34
  onBlur,
31
35
  onFocus,
32
36
  errorMessage,
33
37
  icon,
38
+ iconColor,
39
+ onPressIcon,
40
+ trailing,
41
+ trailingColor,
42
+ onPressTrailing,
34
43
  disabled = false,
35
44
  floatingIconColor,
36
- iconColor,
37
45
  required = false,
38
46
  errorSpacing,
39
47
  style,
@@ -44,7 +52,7 @@ const InputMoney = forwardRef(
44
52
  value: _value,
45
53
  ...props
46
54
  }: InputMoneyProps,
47
- ref,
55
+ ref
48
56
  ) => {
49
57
  const {theme} = useContext(ApplicationContext);
50
58
  const [focused, setFocused] = useState(false);
@@ -63,7 +71,7 @@ const InputMoney = forwardRef(
63
71
  };
64
72
 
65
73
  const [value, setValue] = useState(
66
- defaultValue ? validateText(defaultValue) : '',
74
+ defaultValue ? validateText(defaultValue) : ''
67
75
  );
68
76
 
69
77
  const onClearText = () => {
@@ -99,11 +107,51 @@ const InputMoney = forwardRef(
99
107
  onBlur?.(e);
100
108
  };
101
109
 
110
+ /**
111
+ * Render trailing icon or text
112
+ * @param color
113
+ */
114
+ const renderTrailing = (color?: string) => {
115
+ if (loading) {
116
+ return <Loader type={'spinner'} color={color} style={styles.icon} />;
117
+ }
118
+
119
+ if (icon || trailing) {
120
+ const renderIconTouchable = (icon: ReactNode) => {
121
+ return (
122
+ <TouchableOpacity
123
+ onPress={onPressTrailing ?? onPressIcon}
124
+ style={styles.icon}>
125
+ {icon}
126
+ </TouchableOpacity>
127
+ );
128
+ };
129
+ const trailingValue = icon || trailing;
130
+ if (trailingValue?.includes('_') || trailingValue?.includes('http')) {
131
+ return renderIconTouchable(
132
+ <Icon
133
+ color={color}
134
+ source={(icon || trailing) as string}
135
+ size={24}
136
+ />
137
+ );
138
+ }
139
+ return renderIconTouchable(
140
+ <Text
141
+ typography="action_xs_bold"
142
+ color={color ?? theme.colors.primary}
143
+ numberOfLines={1}>
144
+ {trailingValue!.substring(0, 15)}
145
+ </Text>
146
+ );
147
+ }
148
+ };
149
+
102
150
  const renderInputView = () => {
103
151
  const disabledColor = theme.colors.text.disable;
104
152
  let textColor = theme.colors.text.default;
105
153
  let placeholderColor = theme.colors.text.hint;
106
- let iconTintColor = iconColor;
154
+ let iconTintColor = trailingColor ?? iconColor;
107
155
 
108
156
  if (disabled) {
109
157
  textColor = disabledColor;
@@ -160,7 +208,7 @@ const InputMoney = forwardRef(
160
208
  />
161
209
  </TouchableOpacity>
162
210
  )}
163
- {!!icon && <Icon color={iconTintColor} source={icon} />}
211
+ {renderTrailing(iconTintColor)}
164
212
  </View>
165
213
  </View>
166
214
  );
@@ -198,7 +246,7 @@ const InputMoney = forwardRef(
198
246
  </View>
199
247
  </ComponentContext.Provider>
200
248
  );
201
- },
249
+ }
202
250
  );
203
251
 
204
252
  export default InputMoney;
@@ -74,6 +74,7 @@ const InputOTP = forwardRef(
74
74
  placeholder,
75
75
  onChangeText,
76
76
  onBlur,
77
+ onFocus,
77
78
  dataType = 'number',
78
79
  params,
79
80
  style,
@@ -93,7 +94,10 @@ const InputOTP = forwardRef(
93
94
  onChangeText: (text: string) => {
94
95
  _onChangeText(text);
95
96
  },
96
- focus: () => inputRef.current?.focus(),
97
+ focus: () => {
98
+ setFocused(true);
99
+ inputRef.current?.focus()
100
+ },
97
101
  blur: () => inputRef.current?.blur(),
98
102
  setText: (text: string) => _onChangeText(text),
99
103
  }));
@@ -215,7 +219,7 @@ const InputOTP = forwardRef(
215
219
  value={value}
216
220
  onChangeText={_onChangeText}
217
221
  keyboardType={dataType === 'number' ? 'number-pad' : 'default'}
218
- onFocus={onFocusInput}
222
+ onFocus={onFocus}
219
223
  onBlur={onBlurInput}
220
224
  style={{opacity: 0}}
221
225
  selectionColor={theme.colors.primary}
@@ -18,6 +18,7 @@ import {Text} from '../Text';
18
18
  import {InputSearchProps} from './index';
19
19
  import styles from './styles';
20
20
  import {checkTyping} from './utils';
21
+ import {Styles} from '../Consts';
21
22
 
22
23
  const InputSearch = forwardRef(
23
24
  (
@@ -25,10 +26,14 @@ const InputSearch = forwardRef(
25
26
  placeholder,
26
27
  onFocus,
27
28
  onBlur,
28
- iconColor,
29
29
  value,
30
- onChangeText,
31
30
  icon,
31
+ iconColor,
32
+ onPressIcon,
33
+ trailing,
34
+ trailingColor,
35
+ onPressTrailing,
36
+ onChangeText,
32
37
  buttonText = 'Hủy',
33
38
  showButtonText = true,
34
39
  style,
@@ -39,7 +44,7 @@ const InputSearch = forwardRef(
39
44
  accessibilityLabel,
40
45
  ...props
41
46
  }: InputSearchProps,
42
- ref,
47
+ ref
43
48
  ) => {
44
49
  const {theme} = useContext(ApplicationContext);
45
50
  const [focused, setFocused] = useState(false);
@@ -75,6 +80,9 @@ const InputSearch = forwardRef(
75
80
  };
76
81
  });
77
82
 
83
+ /**
84
+ * Render the input view
85
+ */
78
86
  const renderInputView = () => {
79
87
  return (
80
88
  <TextInput
@@ -99,12 +107,12 @@ const InputSearch = forwardRef(
99
107
  );
100
108
  };
101
109
 
102
- const renderIconView = () => {
110
+ /**
111
+ * Render trailing icon or text
112
+ */
113
+ const renderTrailing = () => {
103
114
  return (
104
- <View
105
- style={{
106
- flexDirection: 'row',
107
- }}>
115
+ <View style={Styles.row}>
108
116
  {focused && haveValue && (
109
117
  <TouchableOpacity style={styles.iconWrapper} onPress={onClearText}>
110
118
  <Icon
@@ -114,8 +122,10 @@ const InputSearch = forwardRef(
114
122
  />
115
123
  </TouchableOpacity>
116
124
  )}
117
- {!!icon && (
118
- <View style={{flexDirection: 'row'}}>
125
+ {!!(icon || trailing) && (
126
+ <TouchableOpacity
127
+ style={Styles.row}
128
+ onPress={onPressTrailing ?? onPressIcon}>
119
129
  <View
120
130
  style={[
121
131
  styles.divider,
@@ -125,22 +135,20 @@ const InputSearch = forwardRef(
125
135
  ]}
126
136
  />
127
137
  <Icon
128
- color={iconColor}
129
- source={icon}
138
+ color={iconColor || trailingColor}
139
+ source={(icon || trailing) as string}
130
140
  style={styles.iconSearchInput}
131
141
  />
132
- </View>
142
+ </TouchableOpacity>
133
143
  )}
134
144
  </View>
135
145
  );
136
146
  };
137
147
 
138
148
  let inputState = 'empty';
139
-
140
149
  if (focused) {
141
150
  inputState = 'focus';
142
151
  }
143
-
144
152
  if (value && value?.length > 0) {
145
153
  inputState = 'filled';
146
154
  }
@@ -171,7 +179,7 @@ const InputSearch = forwardRef(
171
179
  color={theme.colors.text.hint}
172
180
  />
173
181
  {renderInputView()}
174
- {renderIconView()}
182
+ {renderTrailing()}
175
183
  </View>
176
184
  {showButtonText && (
177
185
  <TouchableOpacity onPress={onPressButtonText}>
@@ -185,7 +193,7 @@ const InputSearch = forwardRef(
185
193
  </View>
186
194
  </ComponentContext.Provider>
187
195
  );
188
- },
196
+ }
189
197
  );
190
198
 
191
199
  export default InputSearch;
package/Input/common.tsx CHANGED
@@ -23,7 +23,7 @@ export const getBorderColor = (
23
23
  theme: Theme,
24
24
  focused: boolean,
25
25
  errorMessage?: string,
26
- disabled?: boolean,
26
+ disabled?: boolean
27
27
  ) => {
28
28
  let borderColor = theme.colors.border.default;
29
29
 
@@ -42,7 +42,18 @@ export const getBorderColor = (
42
42
  return {borderColor};
43
43
  };
44
44
 
45
- export const getSizeStyle = (size?: 'small' | 'large') => {
45
+ export const getSizeStyle = (
46
+ size?: 'small' | 'large',
47
+ multiline: boolean = false
48
+ ) => {
49
+ if (multiline)
50
+ return [
51
+ styles.multilineContainer,
52
+ {
53
+ minHeight: size === 'small' ? 48 : 56,
54
+ },
55
+ ];
56
+
46
57
  if (size === 'small') {
47
58
  return styles.smallContainer;
48
59
  }
package/Input/index.tsx CHANGED
@@ -6,6 +6,8 @@ import InputOTP from './InputOTP';
6
6
  import InputSearch from './InputSearch';
7
7
  import InputTextArea from './InputTextArea';
8
8
 
9
+ export type OTPInputLength = 2 | 4 | 6 | 8 | 10;
10
+
9
11
  export interface InputProps extends TextInputProps {
10
12
  /**
11
13
  * Optional. Defines the size of the Input component.
@@ -28,15 +30,38 @@ export interface InputProps extends TextInputProps {
28
30
  errorMessage?: string;
29
31
 
30
32
  /**
33
+ * @deprecated Use `trailing` instead.
31
34
  * Optional. Represents the name or key of the icon to be displayed in the Input component.
32
35
  */
33
36
  icon?: string;
34
37
 
35
38
  /**
39
+ * @deprecated Use `trailingColor` instead.
36
40
  * Optional. Represents the color of the icon in the Input component.
37
41
  */
38
42
  iconColor?: string;
39
43
 
44
+ /**
45
+ * @deprecated Use `onPressTrailing` instead.
46
+ * Optional. callback function to be called when the icon is pressed.
47
+ */
48
+ onPressIcon?: () => void;
49
+
50
+ /**
51
+ * Optional. Represents the name or key of the icon to be displayed in the Input component.
52
+ */
53
+ trailing?: string;
54
+
55
+ /**
56
+ * Optional. Represents the color of the icon in the Input component.
57
+ */
58
+ trailingColor?: string;
59
+
60
+ /**
61
+ * Optional. callback function to be called when the icon is pressed.
62
+ */
63
+ onPressTrailing?: () => void;
64
+
40
65
  /**
41
66
  * Optional. If `true`, the user won't be able to interact with the Input component.
42
67
  * Defaults to `false` if not provided.
@@ -82,11 +107,6 @@ export interface InputProps extends TextInputProps {
82
107
  */
83
108
  fontWeight?: 'Regular' | 'Bold';
84
109
 
85
- /**
86
- * Optional. callback function to be called when the icon is pressed.
87
- */
88
- onPressIcon?: () => void;
89
-
90
110
  /**
91
111
  * Optional. params for element tracking.
92
112
  */
@@ -98,8 +118,7 @@ export interface InputProps extends TextInputProps {
98
118
  hintText?: string;
99
119
  }
100
120
 
101
- export interface InputTextAreaProps
102
- extends Omit<InputProps, 'size' | 'icon' | 'iconColor'> {
121
+ export interface InputTextAreaProps extends Omit<InputProps, 'size'> {
103
122
  /**
104
123
  * Optional. Defines the height of the InputTextArea component.
105
124
  * It can be used to set a specific height for the text area.
@@ -125,14 +144,37 @@ export interface InputSearchProps extends TextInputProps {
125
144
  onPressButtonText?: () => void;
126
145
 
127
146
  /**
147
+ * @deprecated Use `trailing` instead.
148
+ * Optional. Represents the name or key of the icon to be displayed in the Input component.
149
+ */
150
+ icon?: string;
151
+
152
+ /**
153
+ * @deprecated Use `trailingColor` instead.
128
154
  * Optional. Represents the color of the icon in the Input component.
129
155
  */
130
156
  iconColor?: string;
131
157
 
158
+ /**
159
+ * @deprecated Use `onPressTrailing` instead.
160
+ * Optional. callback function to be called when the icon is pressed.
161
+ */
162
+ onPressIcon?: () => void;
163
+
132
164
  /**
133
165
  * Optional. Represents the name or key of the icon to be displayed in the Input component.
134
166
  */
135
- icon?: string;
167
+ trailing?: string;
168
+
169
+ /**
170
+ * Optional. Represents the color of the icon in the Input component.
171
+ */
172
+ trailingColor?: string;
173
+
174
+ /**
175
+ * Optional. callback function to be called when the icon is pressed.
176
+ */
177
+ onPressTrailing?: () => void;
136
178
 
137
179
  /**
138
180
  * Optional. If `true`, the user won't be able to interact with the Input component.
@@ -147,8 +189,6 @@ export interface InputSearchProps extends TextInputProps {
147
189
 
148
190
  export interface InputMoneyProps extends Omit<InputProps, 'placeholder'> {}
149
191
 
150
- export type OTPInputLength = 2 | 4 | 6 | 8 | 10;
151
-
152
192
  export interface InputOTPProps
153
193
  extends Omit<InputProps, 'size' | 'icon' | 'iconColor'> {
154
194
  /**
@@ -181,7 +221,8 @@ export type CaretProps = {
181
221
  length?: number;
182
222
  };
183
223
 
184
- export interface InputDropDownProps extends InputProps {
224
+ export interface InputDropDownProps
225
+ extends Omit<InputProps, 'trailing' | 'trailingColor' | 'onPressTrailing'> {
185
226
  /**
186
227
  * Optional. Defines the size of the InputDropDown component.
187
228
  * 'small' - A smaller, less prominent input.
@@ -189,57 +230,17 @@ export interface InputDropDownProps extends InputProps {
189
230
  */
190
231
  size?: 'small' | 'large';
191
232
 
192
- /**
193
- * Optional. The current value of the InputDropDown.
194
- */
195
- value?: string;
196
-
197
- /**
198
- * Optional. Text that is displayed when there is no value set in the InputDropDown.
199
- */
200
- placeholder?: string;
201
-
202
233
  /**
203
234
  * Optional. Function to be called when the InputDropDown is pressed.
204
235
  */
205
236
  onPress?: () => void;
206
237
 
207
- /**
208
- * Optional. Represents the value for the floating title in the InputDropDown component.
209
- */
210
- floatingValue?: string;
211
-
212
- /**
213
- * Optional. Represents the name or key of the floating icon to be displayed in the InputDropDown component.
214
- */
215
- floatingIcon?: string;
216
-
217
- /**
218
- * Optional. Represents the error message to be displayed below the InputDropDown component when there is an error.
219
- */
220
- errorMessage?: string;
221
-
222
- /**
223
- * Optional. Represents the name or key of the icon to be displayed in the InputDropDown component.
224
- */
225
- icon?: string;
226
-
227
- /**
228
- * Optional. Represents the color of the icon in the InputDropDown component.
229
- */
230
- iconColor?: string;
231
-
232
238
  /**
233
239
  * Optional. If `true`, the user won't be able to interact with the InputDropDown component.
234
240
  * Defaults to `false` if not provided.
235
241
  */
236
242
  disabled?: boolean;
237
243
 
238
- /**
239
- * Optional. Represents the color of the floating icon in the InputDropDown component.
240
- */
241
- floatingIconColor?: string;
242
-
243
244
  /**
244
245
  * Optional. If `true`, the InputDropDown component is marked as required,
245
246
  * indicating that the user must provide a value before submitting a form.
@@ -247,28 +248,6 @@ export interface InputDropDownProps extends InputProps {
247
248
  */
248
249
  required?: boolean;
249
250
 
250
- /**
251
- * Optional. If `true`,
252
- * includes spacing when InputDropDown does not have an error message.
253
- * Defaults to `false` if not provided.
254
- */
255
- errorSpacing?: boolean;
256
-
257
- /**
258
- * If `true`, the icon of the input will show an indicator for loading.
259
- */
260
- loading?: boolean;
261
-
262
- /**
263
- * Optional. Represents the leading icon in the InputDropDown component.
264
- */
265
- leadingIcon?: string;
266
-
267
- /**
268
- * Optional. Represents the color of the leading icon in the InputDropDown component.
269
- */
270
- leadingIconColor?: string;
271
-
272
251
  /**
273
252
  * Optional. params for element tracking.
274
253
  */
@@ -280,6 +259,8 @@ export interface InputDropDownProps extends InputProps {
280
259
  * Optional. Represents the style of the InputDropDown component.
281
260
  */
282
261
  style?: ViewStyle | ViewStyle[];
262
+
263
+ multiline?: boolean;
283
264
  }
284
265
 
285
266
  export {Input, InputDropDown, InputMoney, InputOTP, InputSearch, InputTextArea};
package/Input/styles.ts CHANGED
@@ -157,4 +157,33 @@ export default StyleSheet.create({
157
157
  alignItems: 'center',
158
158
  justifyContent: 'center',
159
159
  },
160
+
161
+ //DropDown
162
+ inputDropDownWrapper: {
163
+ flexDirection: 'row',
164
+ marginTop: Spacing.S,
165
+ },
166
+ inputDropDownView: {
167
+ flex: 1,
168
+ flexDirection: 'row',
169
+ paddingLeft: Spacing.M,
170
+ },
171
+ iconViewDropDown: {
172
+ flexDirection: 'row',
173
+ marginRight: Spacing.M,
174
+ },
175
+ textViewDropDown: {
176
+ flex: 1,
177
+ marginVertical: Spacing.M,
178
+ marginRight: Spacing.S,
179
+ justifyContent: 'center',
180
+ },
181
+ multilineContainer: {
182
+ borderWidth: 1,
183
+ borderRadius: Radius.S,
184
+ },
185
+ leadingIconContainerDropDown: {
186
+ borderRadius: Radius.XS,
187
+ overflow: 'hidden',
188
+ },
160
189
  });
package/Layout/Screen.tsx CHANGED
@@ -121,25 +121,25 @@ const Screen = forwardRef(
121
121
  useGridLayout = true,
122
122
  keyboardVerticalOffset,
123
123
  }: ScreenProps,
124
- ref,
124
+ ref
125
125
  ) => {
126
126
  const animatedValue = useRef<Animated.Value>(new Animated.Value(0));
127
127
  const {theme} = useContext(ApplicationContext);
128
128
  const insets = useSafeAreaInsets();
129
129
  const heightHeader = useHeaderHeight();
130
130
  const currentTint = useRef(Colors.black_01);
131
- const isTab = navigation?.instance?.getState?.()?.type == 'tab';
131
+ const isTab = navigation?.instance?.getState?.()?.type === 'tab';
132
132
 
133
133
  let styleAnimatedHeader: NavigationOptions;
134
134
  let handleScroll;
135
135
  let headerBackground: string | undefined = undefined;
136
136
  let Component: any = View;
137
137
  let keyboardOffset = heightHeader - 20;
138
- if (headerType == 'extended' || animatedHeader) {
138
+ if (headerType === 'extended' || animatedHeader) {
139
139
  keyboardOffset = -20;
140
140
  }
141
141
 
142
- if (headerType == 'extended') {
142
+ if (headerType === 'extended') {
143
143
  headerBackground = theme.assets?.headerBackground;
144
144
  }
145
145
 
@@ -157,7 +157,7 @@ const Screen = forwardRef(
157
157
  <HeaderTitle {...props} animatedValue={animatedValue.current} />
158
158
  ),
159
159
  };
160
- if (animatedHeader.type == 'surface') {
160
+ if (animatedHeader.type === 'surface') {
161
161
  styleAnimatedHeader = {
162
162
  ...styleAnimatedHeader,
163
163
  headerBackground: (props: any) => (
@@ -249,13 +249,13 @@ const Screen = forwardRef(
249
249
  useNativeDriver: true,
250
250
  listener: (e: NativeSyntheticEvent<NativeScrollEvent>) => {
251
251
  scrollViewProps?.onScroll?.(e);
252
- if (animatedHeader?.type == 'surface') {
252
+ if (animatedHeader?.type === 'surface') {
253
253
  const offsetY = e.nativeEvent.contentOffset.y;
254
254
  let color = Colors.black_01;
255
255
  if (offsetY > 50) {
256
256
  color = theme.colors.text.default;
257
257
  }
258
- if (color != currentTint.current) {
258
+ if (color !== currentTint.current) {
259
259
  currentTint.current = color;
260
260
  navigation?.setOptions({
261
261
  headerTintColor: color,
@@ -263,7 +263,7 @@ const Screen = forwardRef(
263
263
  }
264
264
  }
265
265
  },
266
- },
266
+ }
267
267
  );
268
268
  }
269
269
  }
@@ -287,7 +287,7 @@ const Screen = forwardRef(
287
287
  if (Array.isArray(results)) {
288
288
  return results.map((item, index) => {
289
289
  const space = item?.props?.useMargin === false ? 0 : Spacing.M;
290
- if (item?.type == Fragment) {
290
+ if (item?.type === Fragment) {
291
291
  return renderContent(item?.props?.children);
292
292
  }
293
293
  if (item) {
@@ -307,7 +307,7 @@ const Screen = forwardRef(
307
307
  } else {
308
308
  const item: any = children;
309
309
  const space = item?.props?.useMargin === false ? 0 : Spacing.M;
310
- if (item?.type == Fragment) {
310
+ if (item?.type === Fragment) {
311
311
  return renderContent(item?.props?.children);
312
312
  }
313
313
  return (
@@ -387,7 +387,7 @@ const Screen = forwardRef(
387
387
  </KeyboardAvoidingView>
388
388
  </View>
389
389
  );
390
- },
390
+ }
391
391
  );
392
392
 
393
393
  export default Screen;
@@ -5,7 +5,7 @@ import {Button} from '../Button';
5
5
  import {Radius, Spacing, Styles} from '../Consts';
6
6
  import {Icon} from '../Icon';
7
7
  import {Image} from '../Image';
8
- import {Text} from '../Text';
8
+ import {scaleSize, Text} from '../Text';
9
9
  import {PopupNotifyProps} from './types';
10
10
 
11
11
  const PopupNotify: React.FC<PopupNotifyProps> = ({
@@ -27,7 +27,7 @@ const PopupNotify: React.FC<PopupNotifyProps> = ({
27
27
  let Description: any = View;
28
28
  if (scrollContent) {
29
29
  Description = ScrollView;
30
- descriptionStyle = {height: 80};
30
+ descriptionStyle = {maxHeight: scaleSize(172)};
31
31
  }
32
32
  /**
33
33
  * tracking
package/Title/styles.ts CHANGED
@@ -46,16 +46,16 @@ export default StyleSheet.create({
46
46
  marginRight: Spacing.S,
47
47
  },
48
48
  iconRight: {
49
- width: scaleSize(22),
50
- height: scaleSize(22),
49
+ width: 22,
50
+ height: 22,
51
51
  borderRadius: Radius.M,
52
52
  alignItems: 'center',
53
53
  justifyContent: 'center',
54
54
  marginLeft: Spacing.S,
55
55
  },
56
56
  iconLeft: {
57
- width: scaleSize(18),
58
- height: scaleSize(18),
57
+ width: 18,
58
+ height: 18,
59
59
  borderRadius: Radius.M,
60
60
  alignItems: 'center',
61
61
  justifyContent: 'center',
package/code-scanner.js CHANGED
@@ -15,7 +15,7 @@ const calculateAdoptionRate = async (
15
15
  kitJsonPath,
16
16
  miniappJsonPath,
17
17
  reactNativeJsonPath,
18
- fsJsonPath,
18
+ fsJsonPath
19
19
  ) => {
20
20
  const kitJson = require(kitJsonPath);
21
21
  const miniAppJson = require(miniappJsonPath);
@@ -98,8 +98,8 @@ const main = async () => {
98
98
 
99
99
  const allKitsReg = /@momo-kits/;
100
100
  const fsReg =
101
- /^(?:@fs-mobile-platform\/(components|investment|screens)|@miniapp-platform\/(components|foundation))$/;
102
- const RNReg = 'react-native';
101
+ /^(?:@fs-mobile-platform\/(components(\/.*)?|investment(\/.*)?|screens(\/.*)?|foundation(\/.*)?)|@miniapp-platform\/(components(\/.*)?|foundation(\/.*)?))$/;
102
+ const RNReg = /react-native|react-native-svg/;
103
103
 
104
104
  const config1 = {
105
105
  crawlFrom: scanPath,
@@ -148,7 +148,7 @@ const main = async () => {
148
148
  kitJsonPath,
149
149
  miniappJsonPath,
150
150
  reactNativeJsonPath,
151
- fsJsonPath,
151
+ fsJsonPath
152
152
  );
153
153
  sendMessage(result);
154
154
  console.log(result);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@momo-kits/foundation",
3
- "version": "0.92.28",
3
+ "version": "0.92.29-beta.0",
4
4
  "description": "React Native Component Kits",
5
5
  "main": "index.ts",
6
6
  "scripts": {},
package/verify.js CHANGED
@@ -1,47 +1,41 @@
1
1
  const fs = require('fs');
2
2
  const path = require('path');
3
3
 
4
- try {
5
- const packageInfo = JSON.parse(
6
- fs.readFileSync(path.join(`${__dirname}`, 'package.json'), 'utf8'),
4
+ const packageInfo = JSON.parse(
5
+ fs.readFileSync(path.join(`${__dirname}`, 'package.json'), 'utf8')
6
+ );
7
+ const packageVersion = parseInt(packageInfo?.version.split('.')?.[1]);
8
+
9
+ const app = path.join(`${__dirname}/../../../`, 'app.json');
10
+ const miniJson = path.join(`${__dirname}/../../../`, 'package.json');
11
+
12
+ if (!fs.existsSync(app) || !fs.existsSync(miniJson)) {
13
+ return;
14
+ }
15
+
16
+ const appInfo = JSON.parse(fs.readFileSync(app, 'utf8'));
17
+ const miniInfo = JSON.parse(fs.readFileSync(miniJson, 'utf8'));
18
+
19
+ const iOSAppTarget = appInfo?.client?.ios.deploymentTarget;
20
+ const androidAppTarget = appInfo?.client?.android.deploymentTarget;
21
+
22
+ if (
23
+ miniInfo?.dependencies?.['@momo-platform/momo-core']?.includes('optimize')
24
+ ) {
25
+ return;
26
+ }
27
+
28
+ if (packageVersion > iOSAppTarget || packageVersion > androidAppTarget) {
29
+ throw new Error(
30
+ `\x1b[41m Package ${packageInfo.name} version: ${packageInfo.version} require deploymentTarget ${packageVersion}`
31
+ );
32
+ }
33
+
34
+ if (
35
+ miniInfo?.dependencies?.['@momo-platform/momo-core'] &&
36
+ miniInfo?.dependencies?.['@momo-platform/momo-core'] !== packageInfo?.version
37
+ ) {
38
+ throw new Error(
39
+ `\x1b[41m Package ${packageInfo.name} version: ${packageInfo.version} require install resolutions @momo-platform/momo-core ${packageInfo.version}`
7
40
  );
8
- const packageVersion = parseInt(packageInfo?.version.split('.')?.[1]);
9
-
10
- const app = path.join(`${__dirname}/../../../`, 'app.json');
11
- const miniJson = path.join(`${__dirname}/../../../`, 'package.json');
12
-
13
- if (!fs.existsSync(app) || fs.existsSync(miniJson)) {
14
- return;
15
- }
16
-
17
- const appInfo = JSON.parse(fs.readFileSync(app, 'utf8'));
18
- const miniInfo = JSON.parse(fs.readFileSync(miniJson, 'utf8'));
19
-
20
- const iOSAppTarget = appInfo?.client?.ios.deploymentTarget;
21
- const androidAppTarget = appInfo?.client?.android.deploymentTarget;
22
-
23
- if (packageVersion > iOSAppTarget || packageVersion > androidAppTarget) {
24
- console.error(
25
- `Package ${packageInfo.name} version: ${packageInfo.version} require deploymentTarget ${packageVersion}`,
26
- );
27
- throw new Error(
28
- `Package ${packageInfo.name} version: ${packageInfo.version} require deploymentTarget ${packageVersion}`,
29
- );
30
- }
31
-
32
- if (
33
- miniInfo?.dependencies?.['@momo-platform/momo-core'] &&
34
- miniInfo?.dependencies?.['@momo-platform/momo-core'] !==
35
- packageInfo?.version
36
- ) {
37
- console.error(
38
- `Package ${packageInfo.name} version: ${packageInfo.version} require install resolutions @momo-platform/momo-core ${packageInfo.version}`,
39
- );
40
- throw new Error(
41
- `Package ${packageInfo.name} version: ${packageInfo.version} require install resolutions @momo-platform/momo-core ${packageInfo.version}`,
42
- );
43
- }
44
- } catch (error) {
45
- console.error(`Installation failed: ${error.message}`);
46
- process.exit(1);
47
41
  }