@momo-kits/foundation 0.92.29 → 0.92.31

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
 
@@ -338,9 +338,9 @@ const HeaderToolkitAction: React.FC<any> = ({
338
338
  {runtimeTools},
339
339
  (res: {item: {action?: string; key: string}}) => {
340
340
  const {item} = res;
341
- navigator?.toolkitCallback?.(item);
341
+ navigator?.toolkitCallback?.(item.key);
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
  }}
@@ -12,7 +12,7 @@ class Navigator {
12
12
  toolkitConfig?: HeaderToolkitProps;
13
13
  maxApi?: any;
14
14
  dismissData?: any;
15
- toolkitCallback?: (item: any) => void;
15
+ toolkitCallback?: (key: string) => void;
16
16
 
17
17
  constructor(navigation: any, isReady: any) {
18
18
  this.ref = navigation;
@@ -78,7 +78,7 @@ class Navigator {
78
78
  StackActions.push('Modal', {
79
79
  ...params,
80
80
  isBottomSheet: true,
81
- }),
81
+ })
82
82
  );
83
83
  }
84
84
  };
@@ -103,7 +103,7 @@ class Navigator {
103
103
  CommonActions.navigate({
104
104
  name,
105
105
  params,
106
- }),
106
+ })
107
107
  );
108
108
  }
109
109
  };
@@ -124,7 +124,7 @@ class Navigator {
124
124
  params,
125
125
  },
126
126
  ],
127
- }),
127
+ })
128
128
  );
129
129
  }
130
130
  };
@@ -141,9 +141,7 @@ class Navigator {
141
141
  * set callback function for toolkit
142
142
  * @param callback
143
143
  */
144
- setToolkitCallback = (
145
- callback: (item: {key: string; action: string}) => void,
146
- ) => {
144
+ setToolkitCallback = (callback: (key: string) => void) => {
147
145
  this.toolkitCallback = callback;
148
146
  };
149
147
  }
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,
@@ -51,9 +59,10 @@ const Input = forwardRef(
51
59
  hintText,
52
60
  accessibilityLabel,
53
61
  editable = true,
62
+ onPressFloatingIcon,
54
63
  ...props
55
64
  }: InputProps,
56
- ref,
65
+ ref
57
66
  ) => {
58
67
  const {theme} = useContext(ApplicationContext);
59
68
  const [focused, setFocused] = useState(false);
@@ -90,7 +99,11 @@ const Input = forwardRef(
90
99
  };
91
100
  });
92
101
 
93
- const renderIcon = (color: string | undefined) => {
102
+ /**
103
+ * Render trailing icon or text
104
+ * @param color
105
+ */
106
+ const renderTrailing = (color?: string) => {
94
107
  if (loading) {
95
108
  return <Loader type={'spinner'} color={color} style={styles.icon} />;
96
109
  }
@@ -109,24 +122,46 @@ const Input = forwardRef(
109
122
  </TouchableOpacity>
110
123
  );
111
124
  }
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>
125
+ if (icon || trailing) {
126
+ const renderIconTouchable = (icon: ReactNode) => {
127
+ return (
128
+ <TouchableOpacity
129
+ onPress={onPressTrailing ?? onPressIcon}
130
+ style={styles.icon}>
131
+ {icon}
132
+ </TouchableOpacity>
133
+ );
134
+ };
135
+ const trailingValue = icon || trailing;
136
+ if (trailingValue?.includes('_') || trailingValue?.includes('http')) {
137
+ return renderIconTouchable(
138
+ <Icon
139
+ color={color}
140
+ source={(icon || trailing) as string}
141
+ size={24}
142
+ />
143
+ );
144
+ }
145
+ return renderIconTouchable(
146
+ <Text
147
+ typography="action_xs_bold"
148
+ color={color ?? theme.colors.primary}
149
+ numberOfLines={1}>
150
+ {trailingValue!.substring(0, 15)}
151
+ </Text>
120
152
  );
121
153
  }
122
154
  };
123
155
 
156
+ /**
157
+ * Render input view
158
+ */
124
159
  const renderInputView = () => {
125
160
  const disabledColor = theme.colors.text.disable;
126
161
  const secure = secureTextInput && secureTextEntry;
127
162
  let textColor = theme.colors.text.default;
128
163
  let placeholderColor = theme.colors.text.hint;
129
- let iconTintColor = iconColor;
164
+ let iconTintColor = trailingColor ?? iconColor;
130
165
 
131
166
  if (disabled) {
132
167
  textColor = disabledColor;
@@ -155,6 +190,7 @@ const Input = forwardRef(
155
190
  disabled={disabled}
156
191
  required={required}
157
192
  floatingIcon={floatingIcon}
193
+ onPress={onPressFloatingIcon}
158
194
  />
159
195
  <View style={styles.inputView}>
160
196
  {!!leadingIcon && (
@@ -204,21 +240,19 @@ const Input = forwardRef(
204
240
  />
205
241
  </TouchableOpacity>
206
242
  )}
207
- {renderIcon(iconTintColor)}
243
+ {renderTrailing(iconTintColor)}
208
244
  </View>
209
245
  </View>
210
246
  );
211
247
  };
212
248
 
213
249
  let inputState = 'active';
214
-
215
250
  if (value && value?.length > 0) {
216
251
  inputState = 'filled';
217
252
  }
218
253
  if (errorMessage && errorMessage?.length > 0) {
219
254
  inputState = 'error';
220
255
  }
221
-
222
256
  if (disabled) {
223
257
  inputState = 'disabled';
224
258
  }
@@ -242,7 +276,7 @@ const Input = forwardRef(
242
276
  </View>
243
277
  </ComponentContext.Provider>
244
278
  );
245
- },
279
+ }
246
280
  );
247
281
 
248
282
  export default Input;
@@ -1,66 +1,55 @@
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,
13
13
  floatingValue,
14
14
  floatingIcon,
15
+ onPressFloatingIcon,
15
16
  size = 'small',
16
17
  onPress,
17
18
  placeholder,
18
19
  errorMessage,
19
- icon = 'arrow_chevron_down_small',
20
20
  disabled = false,
21
21
  floatingIconColor,
22
- iconColor,
23
22
  required = false,
24
23
  errorSpacing,
25
- loading = false,
26
24
  leadingIcon,
27
25
  leadingIconColor,
28
26
  style,
29
27
  params,
30
28
  accessibilityLabel,
31
29
  hintText,
32
- ...props
30
+ multiline,
33
31
  }: InputDropDownProps) => {
34
32
  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
33
 
34
+ /**
35
+ * Render the input view
36
+ */
46
37
  const renderInputView = () => {
47
38
  const disabledColor = theme.colors.text.disable;
48
39
  let textColor = theme.colors.text.default;
49
40
  let placeholderColor = theme.colors.text.hint;
50
- let iconTintColor = iconColor;
51
41
 
52
42
  if (disabled) {
53
43
  textColor = disabledColor;
54
44
  placeholderColor = disabledColor;
55
- iconTintColor = disabledColor;
56
45
  }
57
46
 
58
47
  return (
59
48
  <View
60
49
  style={[
61
- styles.inputWrapper,
50
+ styles.inputDropDownWrapper,
62
51
  {backgroundColor: theme.colors.background.surface},
63
- getSizeStyle(size),
52
+ getSizeStyle(size, multiline),
64
53
  getBorderColor(theme, false, errorMessage, disabled),
65
54
  ]}>
66
55
  <FloatingView
@@ -69,10 +58,18 @@ const InputDropDown = ({
69
58
  disabled={disabled}
70
59
  required={required}
71
60
  floatingIcon={floatingIcon}
61
+ onPress={onPressFloatingIcon}
72
62
  />
73
- <View style={full ? styles.inputView : Styles.row}>
63
+ <View style={styles.inputDropDownView}>
74
64
  {!!leadingIcon && (
75
- <View style={styles.leadingIconContainer}>
65
+ <View
66
+ style={[
67
+ styles.leadingIconContainerDropDown,
68
+ {
69
+ marginTop: Spacing.M,
70
+ marginRight: Spacing.S,
71
+ },
72
+ ]}>
76
73
  <Icon
77
74
  color={leadingIconColor}
78
75
  source={leadingIcon}
@@ -80,28 +77,27 @@ const InputDropDown = ({
80
77
  />
81
78
  </View>
82
79
  )}
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
- )}
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'} />
103
100
  </View>
104
- <View style={styles.iconView}>{renderIcon(iconTintColor)}</View>
105
101
  </View>
106
102
  );
107
103
  };
@@ -116,8 +112,9 @@ const InputDropDown = ({
116
112
  componentId: accessibilityLabel,
117
113
  }}>
118
114
  <TouchableOpacity
115
+ activeOpacity={0.6}
119
116
  onPress={onPress}
120
- style={[style, full && styles.wrapper]}>
117
+ style={[style, styles.wrapper]}>
121
118
  {renderInputView()}
122
119
  <ErrorView
123
120
  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,
@@ -42,9 +50,10 @@ const InputMoney = forwardRef(
42
50
  accessibilityLabel,
43
51
  hintText,
44
52
  value: _value,
53
+ onPressFloatingIcon,
45
54
  ...props
46
55
  }: InputMoneyProps,
47
- ref,
56
+ ref
48
57
  ) => {
49
58
  const {theme} = useContext(ApplicationContext);
50
59
  const [focused, setFocused] = useState(false);
@@ -63,7 +72,7 @@ const InputMoney = forwardRef(
63
72
  };
64
73
 
65
74
  const [value, setValue] = useState(
66
- defaultValue ? validateText(defaultValue) : '',
75
+ defaultValue ? validateText(defaultValue) : ''
67
76
  );
68
77
 
69
78
  const onClearText = () => {
@@ -99,11 +108,51 @@ const InputMoney = forwardRef(
99
108
  onBlur?.(e);
100
109
  };
101
110
 
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
+
102
151
  const renderInputView = () => {
103
152
  const disabledColor = theme.colors.text.disable;
104
153
  let textColor = theme.colors.text.default;
105
154
  let placeholderColor = theme.colors.text.hint;
106
- let iconTintColor = iconColor;
155
+ let iconTintColor = trailingColor ?? iconColor;
107
156
 
108
157
  if (disabled) {
109
158
  textColor = disabledColor;
@@ -125,6 +174,7 @@ const InputMoney = forwardRef(
125
174
  disabled={disabled}
126
175
  required={required}
127
176
  floatingIcon={floatingIcon}
177
+ onPress={onPressFloatingIcon}
128
178
  />
129
179
  <View style={styles.inputView}>
130
180
  <TextInput
@@ -160,7 +210,7 @@ const InputMoney = forwardRef(
160
210
  />
161
211
  </TouchableOpacity>
162
212
  )}
163
- {!!icon && <Icon color={iconTintColor} source={icon} />}
213
+ {renderTrailing(iconTintColor)}
164
214
  </View>
165
215
  </View>
166
216
  );
@@ -198,7 +248,7 @@ const InputMoney = forwardRef(
198
248
  </View>
199
249
  </ComponentContext.Provider>
200
250
  );
201
- },
251
+ }
202
252
  );
203
253
 
204
254
  export default InputMoney;
@@ -94,7 +94,10 @@ const InputOTP = forwardRef(
94
94
  onChangeText: (text: string) => {
95
95
  _onChangeText(text);
96
96
  },
97
- focus: () => inputRef.current?.focus(),
97
+ focus: () => {
98
+ setFocused(true);
99
+ inputRef.current?.focus()
100
+ },
98
101
  blur: () => inputRef.current?.blur(),
99
102
  setText: (text: string) => _onChangeText(text),
100
103
  }));
@@ -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
@@ -1,5 +1,10 @@
1
1
  import React, {FC, useContext} from 'react';
2
- import {View, ViewStyle} from 'react-native';
2
+ import {
3
+ GestureResponderEvent,
4
+ TouchableOpacity,
5
+ View,
6
+ ViewStyle,
7
+ } from 'react-native';
3
8
  import {ApplicationContext} from '../Application';
4
9
  import {Theme} from '../Application/types';
5
10
  import {Styles} from '../Consts';
@@ -14,6 +19,7 @@ type FloatingViewProps = {
14
19
  floatingIcon?: string;
15
20
  required?: boolean;
16
21
  style?: ViewStyle;
22
+ onPress?: (e: GestureResponderEvent) => void;
17
23
  };
18
24
 
19
25
  export const DEFAULT_HEIGHT = scaleSize(104);
@@ -23,7 +29,7 @@ export const getBorderColor = (
23
29
  theme: Theme,
24
30
  focused: boolean,
25
31
  errorMessage?: string,
26
- disabled?: boolean,
32
+ disabled?: boolean
27
33
  ) => {
28
34
  let borderColor = theme.colors.border.default;
29
35
 
@@ -42,7 +48,18 @@ export const getBorderColor = (
42
48
  return {borderColor};
43
49
  };
44
50
 
45
- export const getSizeStyle = (size?: 'small' | 'large') => {
51
+ export const getSizeStyle = (
52
+ size?: 'small' | 'large',
53
+ multiline: boolean = false
54
+ ) => {
55
+ if (multiline)
56
+ return [
57
+ styles.multilineContainer,
58
+ {
59
+ minHeight: size === 'small' ? 48 : 56,
60
+ },
61
+ ];
62
+
46
63
  if (size === 'small') {
47
64
  return styles.smallContainer;
48
65
  }
@@ -70,7 +87,6 @@ export const ErrorView: FC<{
70
87
  <Text
71
88
  style={Styles.flex}
72
89
  color={errorMessage ? errorColor : hintColor}
73
- numberOfLines={2}
74
90
  typography={'description_default_regular'}>
75
91
  {errorMessage ?? hintTextDefault}
76
92
  </Text>
@@ -90,6 +106,7 @@ export const FloatingView: FC<FloatingViewProps> = ({
90
106
  floatingIcon,
91
107
  required,
92
108
  style,
109
+ onPress,
93
110
  }) => {
94
111
  const {theme} = useContext(ApplicationContext);
95
112
 
@@ -122,12 +139,14 @@ export const FloatingView: FC<FloatingViewProps> = ({
122
139
  )}
123
140
  </Text>
124
141
  {!!floatingIcon && (
125
- <Icon
126
- color={floatingIconTintColor}
127
- source={floatingIcon}
128
- size={16}
129
- style={styles.floatingIcon}
130
- />
142
+ <TouchableOpacity activeOpacity={onPress ? 0.6 : 1} onPress={onPress}>
143
+ <Icon
144
+ color={floatingIconTintColor}
145
+ source={floatingIcon}
146
+ size={16}
147
+ style={styles.floatingIcon}
148
+ />
149
+ </TouchableOpacity>
131
150
  )}
132
151
  </View>
133
152
  );
package/Input/index.tsx CHANGED
@@ -1,4 +1,4 @@
1
- import {TextInputProps, ViewStyle} from 'react-native';
1
+ import {GestureResponderEvent, TextInputProps, ViewStyle} from 'react-native';
2
2
  import Input from './Input';
3
3
  import InputDropDown from './InputDropDown';
4
4
  import InputMoney from './InputMoney';
@@ -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
  */
@@ -96,10 +116,11 @@ export interface InputProps extends TextInputProps {
96
116
  * Optional. Represents text below the Input component.
97
117
  */
98
118
  hintText?: string;
119
+
120
+ onPressFloatingIcon?: (e: GestureResponderEvent) => void;
99
121
  }
100
122
 
101
- export interface InputTextAreaProps
102
- extends Omit<InputProps, 'size' | 'icon' | 'iconColor'> {
123
+ export interface InputTextAreaProps extends Omit<InputProps, 'size'> {
103
124
  /**
104
125
  * Optional. Defines the height of the InputTextArea component.
105
126
  * It can be used to set a specific height for the text area.
@@ -125,14 +146,37 @@ export interface InputSearchProps extends TextInputProps {
125
146
  onPressButtonText?: () => void;
126
147
 
127
148
  /**
149
+ * @deprecated Use `trailing` instead.
150
+ * Optional. Represents the name or key of the icon to be displayed in the Input component.
151
+ */
152
+ icon?: string;
153
+
154
+ /**
155
+ * @deprecated Use `trailingColor` instead.
128
156
  * Optional. Represents the color of the icon in the Input component.
129
157
  */
130
158
  iconColor?: string;
131
159
 
160
+ /**
161
+ * @deprecated Use `onPressTrailing` instead.
162
+ * Optional. callback function to be called when the icon is pressed.
163
+ */
164
+ onPressIcon?: () => void;
165
+
132
166
  /**
133
167
  * Optional. Represents the name or key of the icon to be displayed in the Input component.
134
168
  */
135
- icon?: string;
169
+ trailing?: string;
170
+
171
+ /**
172
+ * Optional. Represents the color of the icon in the Input component.
173
+ */
174
+ trailingColor?: string;
175
+
176
+ /**
177
+ * Optional. callback function to be called when the icon is pressed.
178
+ */
179
+ onPressTrailing?: () => void;
136
180
 
137
181
  /**
138
182
  * Optional. If `true`, the user won't be able to interact with the Input component.
@@ -147,8 +191,6 @@ export interface InputSearchProps extends TextInputProps {
147
191
 
148
192
  export interface InputMoneyProps extends Omit<InputProps, 'placeholder'> {}
149
193
 
150
- export type OTPInputLength = 2 | 4 | 6 | 8 | 10;
151
-
152
194
  export interface InputOTPProps
153
195
  extends Omit<InputProps, 'size' | 'icon' | 'iconColor'> {
154
196
  /**
@@ -181,7 +223,8 @@ export type CaretProps = {
181
223
  length?: number;
182
224
  };
183
225
 
184
- export interface InputDropDownProps extends InputProps {
226
+ export interface InputDropDownProps
227
+ extends Omit<InputProps, 'trailing' | 'trailingColor' | 'onPressTrailing'> {
185
228
  /**
186
229
  * Optional. Defines the size of the InputDropDown component.
187
230
  * 'small' - A smaller, less prominent input.
@@ -189,57 +232,17 @@ export interface InputDropDownProps extends InputProps {
189
232
  */
190
233
  size?: 'small' | 'large';
191
234
 
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
235
  /**
203
236
  * Optional. Function to be called when the InputDropDown is pressed.
204
237
  */
205
238
  onPress?: () => void;
206
239
 
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
240
  /**
233
241
  * Optional. If `true`, the user won't be able to interact with the InputDropDown component.
234
242
  * Defaults to `false` if not provided.
235
243
  */
236
244
  disabled?: boolean;
237
245
 
238
- /**
239
- * Optional. Represents the color of the floating icon in the InputDropDown component.
240
- */
241
- floatingIconColor?: string;
242
-
243
246
  /**
244
247
  * Optional. If `true`, the InputDropDown component is marked as required,
245
248
  * indicating that the user must provide a value before submitting a form.
@@ -247,28 +250,6 @@ export interface InputDropDownProps extends InputProps {
247
250
  */
248
251
  required?: boolean;
249
252
 
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
253
  /**
273
254
  * Optional. params for element tracking.
274
255
  */
@@ -280,6 +261,8 @@ export interface InputDropDownProps extends InputProps {
280
261
  * Optional. Represents the style of the InputDropDown component.
281
262
  */
282
263
  style?: ViewStyle | ViewStyle[];
264
+
265
+ multiline?: boolean;
283
266
  }
284
267
 
285
268
  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.29",
3
+ "version": "0.92.31",
4
4
  "description": "React Native Component Kits",
5
5
  "main": "index.ts",
6
6
  "scripts": {},
package/publish.sh CHANGED
@@ -7,16 +7,16 @@ rsync -r --exclude=/dist ./* dist
7
7
  cd dist
8
8
 
9
9
  if [ "$1" == "stable" ]; then
10
- npm version $(npm view @momo-kits/foundation@stable version)
11
- npm version patch
10
+ #npm version $(npm view @momo-kits/foundation@stable version)
11
+ #npm version patch
12
12
  npm publish --tag stable --access=public
13
13
  elif [ "$1" == "latest" ]; then
14
- npm version $(npm view @momo-kits/foundation@latest version)
15
- npm version prerelease --preid=rc
14
+ #npm version $(npm view @momo-kits/foundation@latest version)
15
+ #npm version prerelease --preid=rc
16
16
  npm publish --tag latest --access=public
17
17
  else
18
- npm version $(npm view @momo-kits/foundation@beta version)
19
- npm version prerelease --preid=beta
18
+ #npm version $(npm view @momo-kits/foundation@beta version)
19
+ #npm version prerelease --preid=beta
20
20
  npm publish --tag beta --access=public
21
21
  fi
22
22
 
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(0);
47
41
  }