@momo-kits/foundation 0.89.6 → 0.92.1-rc.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/Button/index.tsx CHANGED
@@ -6,7 +6,6 @@ import {
6
6
  TouchableOpacityProps,
7
7
  View,
8
8
  } from 'react-native';
9
-
10
9
  import LinearGradient from 'react-native-linear-gradient';
11
10
  import {ApplicationContext} from '../Application';
12
11
  import {Text} from '../Text';
@@ -15,6 +14,12 @@ import {Colors, Spacing} from '../Consts';
15
14
  import styles from './styles';
16
15
  import {Icon} from '../Icon';
17
16
  import {Loader} from '../Loader';
17
+ import {formatComponentName, getAccessibilityID} from '../Application/utils';
18
+
19
+ const {
20
+ ScreenContext,
21
+ MiniAppContext,
22
+ } = require('react-native/Libraries/Components/ScreenContext');
18
23
 
19
24
  const AnimationLinear = Animated.createAnimatedComponent(LinearGradient);
20
25
 
@@ -70,6 +75,10 @@ export interface ButtonProps extends TouchableOpacityProps {
70
75
  * A callback function that is called when the button is pressed.
71
76
  */
72
77
  onPress: () => void;
78
+
79
+ params?: any;
80
+
81
+ componentId?: string;
73
82
  }
74
83
 
75
84
  const Button: FC<ButtonProps> = ({
@@ -82,9 +91,13 @@ const Button: FC<ButtonProps> = ({
82
91
  loading = false,
83
92
  title = 'Button',
84
93
  onPress,
94
+ params,
95
+ componentId,
96
+ accessibilityLabel,
85
97
  ...rest
86
98
  }) => {
87
99
  const {theme, config} = useContext(ApplicationContext);
100
+ const {appId, code} = useContext<any>(MiniAppContext);
88
101
  const {gradient, color} = config?.navigationBar?.buttonColors ?? {};
89
102
  let gradientPros;
90
103
  if (gradient?.length > 0 && type == 'primary') {
@@ -94,6 +107,8 @@ const Button: FC<ButtonProps> = ({
94
107
  end: {x: 0, y: 0.5},
95
108
  };
96
109
  }
110
+
111
+ const screenInfo = useContext<any>(ScreenContext);
97
112
  const getSizeStyle = () => {
98
113
  const styleSheet: {[key: string]: any} = styles;
99
114
  return styleSheet[size ?? 'small'];
@@ -291,19 +306,38 @@ const Button: FC<ButtonProps> = ({
291
306
  const activeOpacity = type === 'disabled' ? 0.75 : 0.5;
292
307
 
293
308
  return (
294
- <TouchableOpacity
295
- {...rest}
296
- activeOpacity={activeOpacity}
297
- onPress={onPressButton}
298
- style={buttonStyle}>
299
- {renderLeading()}
300
- {renderTitle()}
301
- {renderTrailing()}
302
- {gradientPros && (
303
- <AnimationLinear {...gradientPros} style={styles.gradientView} />
304
- )}
305
- {gradientPros && <View style={styles.strokeView} />}
306
- </TouchableOpacity>
309
+ <ScreenContext.Provider
310
+ value={{
311
+ ...screenInfo,
312
+ componentName: 'Button',
313
+ params,
314
+ state: loading
315
+ ? 'loading'
316
+ : type === 'disabled'
317
+ ? 'disabled'
318
+ : 'enabled',
319
+ componentId,
320
+ componentValue: formatComponentName(title),
321
+ action: 'click',
322
+ }}>
323
+ <TouchableOpacity
324
+ {...rest}
325
+ {...getAccessibilityID(
326
+ `${appId}/${code}/${screenInfo.screenName}/btn_${title}`,
327
+ accessibilityLabel,
328
+ )}
329
+ activeOpacity={activeOpacity}
330
+ onPress={onPressButton}
331
+ style={buttonStyle}>
332
+ {renderLeading()}
333
+ {renderTitle()}
334
+ {renderTrailing()}
335
+ {gradientPros && (
336
+ <AnimationLinear {...gradientPros} style={styles.gradientView} />
337
+ )}
338
+ {gradientPros && <View style={styles.strokeView} />}
339
+ </TouchableOpacity>
340
+ </ScreenContext.Provider>
307
341
  );
308
342
  };
309
343
 
@@ -5,6 +5,12 @@ import styles from './styles';
5
5
  import {ApplicationContext} from '../Application';
6
6
  import {Text} from '../Text';
7
7
  import {Icon} from '../Icon';
8
+ import {formatNameLength, getAccessibilityID} from '../Application/utils';
9
+
10
+ const {
11
+ ScreenContext,
12
+ MiniAppContext,
13
+ } = require('react-native/Libraries/Components/ScreenContext');
8
14
 
9
15
  const CheckBox: FC<CheckBoxProps> = ({
10
16
  value,
@@ -13,8 +19,12 @@ const CheckBox: FC<CheckBoxProps> = ({
13
19
  style,
14
20
  label,
15
21
  indeterminate,
22
+ params,
23
+ componentId,
16
24
  }) => {
25
+ const {appId} = useContext<any>(MiniAppContext);
17
26
  const {theme} = useContext(ApplicationContext);
27
+ const screenInfo = useContext<any>(ScreenContext);
18
28
  const haveValue = value || indeterminate;
19
29
  const iconSource = indeterminate ? 'ic_minus' : 'ic_checked';
20
30
  let borderColor = theme.colors.text.default;
@@ -34,27 +44,44 @@ const CheckBox: FC<CheckBoxProps> = ({
34
44
  }
35
45
  }
36
46
 
47
+ const accessibilityID = getAccessibilityID(
48
+ `${appId}/${screenInfo.screenName}/cbx_${label}_${value}`,
49
+ );
50
+
37
51
  return (
38
- <TouchableOpacity
39
- activeOpacity={0.8}
40
- onPress={() => onChange?.(!value)}
41
- disabled={disabled}
42
- style={[style, styles.container]}>
43
- <View
44
- style={[
45
- {borderColor, backgroundColor, borderWidth: 1},
46
- styles.checkbox,
47
- ]}>
48
- {haveValue && (
49
- <Icon
50
- color={theme.colors.background.surface}
51
- size={20}
52
- source={iconSource}
53
- />
54
- )}
55
- </View>
56
- {!!label && <Text typography={'body_default_regular'}>{label}</Text>}
57
- </TouchableOpacity>
52
+ <ScreenContext.Provider
53
+ value={{
54
+ ...screenInfo,
55
+ componentName: 'Button',
56
+ params,
57
+ state: disabled ? 'disabled' : 'filled',
58
+ componentId,
59
+ action: 'click',
60
+ componentLabel: formatNameLength(label || ''),
61
+ componentValue: indeterminate ? 'indetermine' : value,
62
+ }}>
63
+ <TouchableOpacity
64
+ {...accessibilityID}
65
+ activeOpacity={0.8}
66
+ onPress={() => onChange?.(!value)}
67
+ disabled={disabled}
68
+ style={[style, styles.container]}>
69
+ <View
70
+ style={[
71
+ {borderColor, backgroundColor, borderWidth: 1},
72
+ styles.checkbox,
73
+ ]}>
74
+ {haveValue && (
75
+ <Icon
76
+ color={theme.colors.background.surface}
77
+ size={20}
78
+ source={iconSource}
79
+ />
80
+ )}
81
+ </View>
82
+ {!!label && <Text typography={'body_default_regular'}>{label}</Text>}
83
+ </TouchableOpacity>
84
+ </ScreenContext.Provider>
58
85
  );
59
86
  };
60
87
 
package/CheckBox/types.ts CHANGED
@@ -35,4 +35,8 @@ export type CheckBoxProps = {
35
35
  * Accepts an object of style properties.
36
36
  */
37
37
  style?: ViewStyle;
38
+
39
+ params?: any
40
+
41
+ componentId?: string
38
42
  };
@@ -213,6 +213,19 @@ const Shadow = {
213
213
  elevation: 6,
214
214
  },
215
215
  }),
216
+
217
+ Pink: Platform.select({
218
+ ios: {
219
+ shadowColor: 'rgba(224, 128, 181, 0.25)',
220
+ shadowOffset: { width: 0, height: 6 },
221
+ shadowOpacity: 1,
222
+ shadowRadius: 8,
223
+ },
224
+ android: {
225
+ elevation: 16,
226
+ shadowColor: 'rgba(224, 128, 181, 0.25)',
227
+ },
228
+ }),
216
229
  };
217
230
 
218
231
  export {Colors, Spacing, Radius, Shadow};
@@ -9,6 +9,11 @@ import {ApplicationContext} from '../Application';
9
9
  import {Colors} from '../Consts';
10
10
  import {Icon} from '../Icon';
11
11
  import styles from './styles';
12
+ import {formatComponentName} from '../Application/utils';
13
+
14
+ const {
15
+ ScreenContext,
16
+ } = require('react-native/Libraries/Components/ScreenContext');
12
17
 
13
18
  export interface IconButtonProps extends TouchableOpacityProps {
14
19
  /**
@@ -26,6 +31,10 @@ export interface IconButtonProps extends TouchableOpacityProps {
26
31
  * Optional. Defines the size of the IconButton.
27
32
  */
28
33
  size?: 'large' | 'small';
34
+
35
+ params?: any;
36
+
37
+ componentId?: string;
29
38
  }
30
39
 
31
40
  const IconButton: React.FC<IconButtonProps> = ({
@@ -33,9 +42,12 @@ const IconButton: React.FC<IconButtonProps> = ({
33
42
  icon,
34
43
  size,
35
44
  onPress,
45
+ params,
46
+ componentId,
36
47
  ...rest
37
48
  }) => {
38
49
  const {theme} = useContext(ApplicationContext);
50
+ const screenInfo = useContext<any>(ScreenContext);
39
51
 
40
52
  /**
41
53
  * get size icon button
@@ -121,13 +133,24 @@ const IconButton: React.FC<IconButtonProps> = ({
121
133
  const iconSize = size === 'small' ? 16 : 24;
122
134
 
123
135
  return (
124
- <TouchableOpacity
125
- {...rest}
126
- activeOpacity={activeOpacity}
127
- onPress={onPressButton}
128
- style={buttonStyle}>
129
- <Icon size={iconSize} source={icon} color={getIconColor()} />
130
- </TouchableOpacity>
136
+ <ScreenContext.Provider
137
+ value={{
138
+ ...screenInfo,
139
+ componentName: 'IconButton',
140
+ params,
141
+ state: type === 'disabled' ? 'disabled' : 'enabled',
142
+ componentId,
143
+ componentValue: formatComponentName(icon),
144
+ action: 'click',
145
+ }}>
146
+ <TouchableOpacity
147
+ {...rest}
148
+ activeOpacity={activeOpacity}
149
+ onPress={onPressButton}
150
+ style={buttonStyle}>
151
+ <Icon size={iconSize} source={icon} color={getIconColor()} />
152
+ </TouchableOpacity>
153
+ </ScreenContext.Provider>
131
154
  );
132
155
  };
133
156
 
package/Image/index.tsx CHANGED
@@ -1,12 +1,13 @@
1
1
  import React, {useContext, useRef, useState} from 'react';
2
2
  import {StyleSheet, View} from 'react-native';
3
- import FastImage from 'react-native-fast-image';
3
+ import FastImage, {Source} from 'react-native-fast-image';
4
4
  import styles from './styles';
5
5
  import {ApplicationContext} from '../Application';
6
6
  import {Skeleton} from '../Skeleton';
7
7
  import {Icon} from '../Icon';
8
8
  import {Styles} from '../Consts';
9
9
  import {ImageProps} from './types';
10
+ import {getAccessibilityID} from '../Application/utils';
10
11
 
11
12
  type Status = 'success' | 'loading' | 'error';
12
13
 
@@ -44,6 +45,7 @@ const Image: React.FC<ImageProps> = ({
44
45
  return (
45
46
  <FastImage
46
47
  {...rest}
48
+ {...getAccessibilityID(`img|${(source as Source).uri}`)}
47
49
  source={source}
48
50
  style={[styles.container, style]}
49
51
  onProgress={() => {
package/Input/Input.tsx CHANGED
@@ -1,6 +1,7 @@
1
1
  import React, {forwardRef, useContext, useRef, useState} from 'react';
2
2
  import {
3
3
  NativeSyntheticEvent,
4
+ Platform,
4
5
  TextInput,
5
6
  TextInputFocusEventData,
6
7
  TouchableOpacity,
@@ -13,6 +14,12 @@ import {InputProps} from './index';
13
14
  import {Icon} from '../Icon';
14
15
  import {checkTyping} from './utils';
15
16
  import {Loader} from '../Loader';
17
+ import {formatComponentName, getAccessibilityID} from '../Application/utils';
18
+
19
+ const {
20
+ ScreenContext,
21
+ MiniAppContext,
22
+ } = require('react-native/Libraries/Components/ScreenContext');
16
23
 
17
24
  const Input = forwardRef(
18
25
  (
@@ -38,16 +45,21 @@ const Input = forwardRef(
38
45
  fontWeight = 'Regular',
39
46
  onPressIcon,
40
47
  secureTextEntry,
48
+ keyboardType,
41
49
  style,
50
+ params,
51
+ componentId,
42
52
  ...props
43
53
  }: InputProps,
44
54
  ref,
45
55
  ) => {
46
56
  const {theme} = useContext(ApplicationContext);
57
+ const {appId, code} = useContext<any>(MiniAppContext);
47
58
  const [focused, setFocused] = useState(false);
48
59
  const [haveValue, setHaveValue] = useState(!!value || !!props.defaultValue);
49
60
  const [secureTextInput, setSecureTextInput] = useState(secureTextEntry);
50
61
  const inputRef = (ref as React.RefObject<TextInput>) ?? useRef<TextInput>();
62
+ const screenInfo = useContext<any>(ScreenContext);
51
63
 
52
64
  const onClearText = () => {
53
65
  inputRef?.current?.clear();
@@ -106,6 +118,17 @@ const Input = forwardRef(
106
118
  let textColor = theme.colors.text.default;
107
119
  let placeholderColor = theme.colors.text.hint;
108
120
  let iconTintColor = iconColor;
121
+ const accessibilityID = disabled
122
+ ? getAccessibilityID(
123
+ `${appId}/${code}/${screenInfo.screenName}/input_${
124
+ floatingValue ?? placeholder
125
+ }_disabled`,
126
+ )
127
+ : getAccessibilityID(
128
+ `${appId}/${code}/${screenInfo.screenName}/input_${
129
+ floatingValue ?? placeholder
130
+ }`,
131
+ );
109
132
 
110
133
  if (disabled) {
111
134
  textColor = disabledColor;
@@ -113,6 +136,13 @@ const Input = forwardRef(
113
136
  iconTintColor = disabledColor;
114
137
  }
115
138
 
139
+ if (secureTextEntry) {
140
+ keyboardType = Platform.select({
141
+ ios: 'ascii-capable',
142
+ android: 'visible-password',
143
+ });
144
+ }
145
+
116
146
  return (
117
147
  <View
118
148
  style={[
@@ -140,7 +170,8 @@ const Input = forwardRef(
140
170
  )}
141
171
  <TextInput
142
172
  {...props}
143
- editable={!disabled}
173
+ {...accessibilityID}
174
+ editable={props.editable && !disabled}
144
175
  secureTextEntry={secure}
145
176
  textAlignVertical="center"
146
177
  ref={inputRef}
@@ -160,6 +191,7 @@ const Input = forwardRef(
160
191
  placeholder={placeholder}
161
192
  selectionColor={theme.colors.primary}
162
193
  placeholderTextColor={placeholderColor}
194
+ keyboardType={keyboardType}
163
195
  />
164
196
  </View>
165
197
  <View style={styles.iconView}>
@@ -180,11 +212,34 @@ const Input = forwardRef(
180
212
  );
181
213
  };
182
214
 
215
+ let inputState = 'active';
216
+
217
+ if (value && value?.length > 0) {
218
+ inputState = 'filled';
219
+ }
220
+ if (errorMessage && errorMessage?.length > 0) {
221
+ inputState = 'error';
222
+ }
223
+
224
+ if (disabled) {
225
+ inputState = 'disabled';
226
+ }
227
+
183
228
  return (
184
- <View style={[style, styles.wrapper]}>
185
- {renderInputView()}
186
- <ErrorView errorMessage={errorMessage} errorSpacing={errorSpacing} />
187
- </View>
229
+ <ScreenContext.Provider
230
+ value={{
231
+ ...screenInfo,
232
+ componentName: 'Input',
233
+ params,
234
+ componentLabel: formatComponentName(floatingValue || ''),
235
+ state: inputState,
236
+ componentId,
237
+ }}>
238
+ <View style={[style, styles.wrapper]}>
239
+ {renderInputView()}
240
+ <ErrorView errorMessage={errorMessage} errorSpacing={errorSpacing} />
241
+ </View>
242
+ </ScreenContext.Provider>
188
243
  );
189
244
  },
190
245
  );
@@ -7,6 +7,12 @@ import {InputDropDownProps} from './index';
7
7
  import {Icon} from '../Icon';
8
8
  import {Loader} from '../Loader';
9
9
  import {Styles} from '../Consts';
10
+ import {formatComponentName, getAccessibilityID} from '../Application/utils';
11
+
12
+ const {
13
+ ScreenContext,
14
+ MiniAppContext,
15
+ } = require('react-native/Libraries/Components/ScreenContext');
10
16
 
11
17
  const InputDropDown = ({
12
18
  value,
@@ -26,10 +32,14 @@ const InputDropDown = ({
26
32
  leadingIcon,
27
33
  leadingIconColor,
28
34
  style,
35
+ params,
36
+ componentId,
29
37
  ...props
30
38
  }: InputDropDownProps) => {
39
+ const {appId, code} = useContext<any>(MiniAppContext);
31
40
  const {theme} = useContext(ApplicationContext);
32
41
  const full = !!value || !!placeholder;
42
+ const screenInfo = useContext<any>(ScreenContext);
33
43
 
34
44
  const renderIcon = (color: string | undefined) => {
35
45
  if (loading) {
@@ -45,6 +55,17 @@ const InputDropDown = ({
45
55
  let textColor = theme.colors.text.default;
46
56
  let placeholderColor = theme.colors.text.hint;
47
57
  let iconTintColor = iconColor;
58
+ const accessibilityID = disabled
59
+ ? getAccessibilityID(
60
+ `${appId}/${code}/${screenInfo.screenName}/input_${
61
+ floatingValue ?? placeholder
62
+ }_disabled`,
63
+ )
64
+ : getAccessibilityID(
65
+ `${appId}/${code}/${screenInfo.screenName}/input_${
66
+ floatingValue ?? placeholder
67
+ }`,
68
+ );
48
69
 
49
70
  if (disabled) {
50
71
  textColor = disabledColor;
@@ -80,6 +101,7 @@ const InputDropDown = ({
80
101
  {full && (
81
102
  <TextInput
82
103
  {...props}
104
+ {...accessibilityID}
83
105
  onPressIn={onPress}
84
106
  editable={false}
85
107
  textAlignVertical="top"
@@ -104,10 +126,22 @@ const InputDropDown = ({
104
126
  };
105
127
 
106
128
  return (
107
- <TouchableOpacity onPress={onPress} style={[style, full && styles.wrapper]}>
108
- {renderInputView()}
109
- <ErrorView errorMessage={errorMessage} errorSpacing={errorSpacing} />
110
- </TouchableOpacity>
129
+ <ScreenContext.Provider
130
+ value={{
131
+ ...screenInfo,
132
+ componentName: 'InputOTP',
133
+ params,
134
+ state: 'enabled',
135
+ componentLabel: formatComponentName(floatingValue || ''),
136
+ componentId,
137
+ }}>
138
+ <TouchableOpacity
139
+ onPress={onPress}
140
+ style={[style, full && styles.wrapper]}>
141
+ {renderInputView()}
142
+ <ErrorView errorMessage={errorMessage} errorSpacing={errorSpacing} />
143
+ </TouchableOpacity>
144
+ </ScreenContext.Provider>
111
145
  );
112
146
  };
113
147
 
@@ -18,6 +18,12 @@ import {ErrorView, FloatingView, getBorderColor, getSizeStyle} from './common';
18
18
  import {InputMoneyProps} from './index';
19
19
  import {Icon} from '../Icon';
20
20
  import {formatMoneyToNumber, formatNumberToMoney} from './utils';
21
+ import {formatComponentName, getAccessibilityID} from '../Application/utils';
22
+
23
+ const {
24
+ ScreenContext,
25
+ MiniAppContext,
26
+ } = require('react-native/Libraries/Components/ScreenContext');
21
27
 
22
28
  const InputMoney = forwardRef(
23
29
  (
@@ -36,14 +42,18 @@ const InputMoney = forwardRef(
36
42
  required = false,
37
43
  errorSpacing,
38
44
  style,
45
+ params,
39
46
  defaultValue = '',
47
+ componentId,
40
48
  ...props
41
49
  }: InputMoneyProps,
42
50
  ref,
43
51
  ) => {
44
52
  const {theme} = useContext(ApplicationContext);
53
+ const {appId, code} = useContext<any>(MiniAppContext);
45
54
  const [focused, setFocused] = useState(false);
46
55
  const inputRef = (ref as React.RefObject<TextInput>) ?? useRef<TextInput>();
56
+ const screenInfo = useContext<any>(ScreenContext);
47
57
 
48
58
  const validateText = (text: string) => {
49
59
  const valueFormat = formatMoneyToNumber(text, 'đ');
@@ -89,6 +99,13 @@ const InputMoney = forwardRef(
89
99
  let textColor = theme.colors.text.default;
90
100
  let placeholderColor = theme.colors.text.hint;
91
101
  let iconTintColor = iconColor;
102
+ const accessibilityID = disabled
103
+ ? getAccessibilityID(
104
+ `${appId}/${code}/${screenInfo.screenName}/input_${floatingValue}_disabled`,
105
+ )
106
+ : getAccessibilityID(
107
+ `${appId}/${code}/${screenInfo.screenName}/input_${floatingValue}`,
108
+ );
92
109
 
93
110
  if (disabled) {
94
111
  textColor = disabledColor;
@@ -114,6 +131,7 @@ const InputMoney = forwardRef(
114
131
  <View style={styles.inputView}>
115
132
  <TextInput
116
133
  {...props}
134
+ {...accessibilityID}
117
135
  editable={!disabled}
118
136
  textAlignVertical="top"
119
137
  ref={inputRef}
@@ -151,11 +169,34 @@ const InputMoney = forwardRef(
151
169
  );
152
170
  };
153
171
 
172
+ let inputState = 'active';
173
+
174
+ if (value && value?.length > 0) {
175
+ inputState = 'filled';
176
+ }
177
+ if (errorMessage && errorMessage?.length > 0) {
178
+ inputState = 'error';
179
+ }
180
+
181
+ if (disabled) {
182
+ inputState = 'disabled';
183
+ }
184
+
154
185
  return (
155
- <View style={[style, styles.wrapper]}>
156
- {renderInputView()}
157
- <ErrorView errorMessage={errorMessage} errorSpacing={errorSpacing} />
158
- </View>
186
+ <ScreenContext.Provider
187
+ value={{
188
+ ...screenInfo,
189
+ componentName: 'InputMoney',
190
+ params,
191
+ componentLabel: formatComponentName(floatingValue || ''),
192
+ state: inputState,
193
+ componentId,
194
+ }}>
195
+ <View style={[style, styles.wrapper]}>
196
+ {renderInputView()}
197
+ <ErrorView errorMessage={errorMessage} errorSpacing={errorSpacing} />
198
+ </View>
199
+ </ScreenContext.Provider>
159
200
  );
160
201
  },
161
202
  );