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

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.
@@ -5,6 +5,16 @@ import styles from './styles';
5
5
  import {ApplicationContext} from '../Application';
6
6
  import {Text} from '../Text';
7
7
  import {Icon} from '../Icon';
8
+ import {
9
+ cleanNameForTracking,
10
+ formatNameLength,
11
+ getAccessibilityID,
12
+ } from '../Application/utils';
13
+
14
+ const {
15
+ ScreenContext,
16
+ MiniAppContext,
17
+ } = require('react-native/Libraries/Components/ScreenContext');
8
18
 
9
19
  const CheckBox: FC<CheckBoxProps> = ({
10
20
  value,
@@ -13,8 +23,12 @@ const CheckBox: FC<CheckBoxProps> = ({
13
23
  style,
14
24
  label,
15
25
  indeterminate,
26
+ params,
27
+ componentId,
16
28
  }) => {
29
+ const {appId, code} = useContext<any>(MiniAppContext);
17
30
  const {theme} = useContext(ApplicationContext);
31
+ const screenInfo = useContext<any>(ScreenContext);
18
32
  const haveValue = value || indeterminate;
19
33
  const iconSource = indeterminate ? 'ic_minus' : 'ic_checked';
20
34
  let borderColor = theme.colors.text.default;
@@ -34,27 +48,46 @@ const CheckBox: FC<CheckBoxProps> = ({
34
48
  }
35
49
  }
36
50
 
51
+ const accessibilityID = getAccessibilityID(
52
+ `${appId}/${code}/${screenInfo.screenName}/cbx_${cleanNameForTracking(
53
+ label,
54
+ )}_${indeterminate ? 'na' : value}`,
55
+ );
56
+
37
57
  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>
58
+ <ScreenContext.Provider
59
+ value={{
60
+ ...screenInfo,
61
+ componentName: 'Button',
62
+ params,
63
+ state: disabled ? 'disabled' : 'filled',
64
+ componentId,
65
+ action: 'click',
66
+ componentLabel: formatNameLength(label || ''),
67
+ componentValue: indeterminate ? 'indetermine' : value,
68
+ }}>
69
+ <TouchableOpacity
70
+ {...accessibilityID}
71
+ activeOpacity={0.8}
72
+ onPress={() => onChange?.(!value)}
73
+ disabled={disabled}
74
+ style={[style, styles.container]}>
75
+ <View
76
+ style={[
77
+ {borderColor, backgroundColor, borderWidth: 1},
78
+ styles.checkbox,
79
+ ]}>
80
+ {haveValue && (
81
+ <Icon
82
+ color={theme.colors.background.surface}
83
+ size={20}
84
+ source={iconSource}
85
+ />
86
+ )}
87
+ </View>
88
+ {!!label && <Text typography={'body_default_regular'}>{label}</Text>}
89
+ </TouchableOpacity>
90
+ </ScreenContext.Provider>
58
91
  );
59
92
  };
60
93
 
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,16 @@ import {InputProps} from './index';
13
14
  import {Icon} from '../Icon';
14
15
  import {checkTyping} from './utils';
15
16
  import {Loader} from '../Loader';
17
+ import {
18
+ formatComponentName,
19
+ getAccessibilityID,
20
+ cleanNameForTracking,
21
+ } from '../Application/utils';
22
+
23
+ const {
24
+ ScreenContext,
25
+ MiniAppContext,
26
+ } = require('react-native/Libraries/Components/ScreenContext');
16
27
 
17
28
  const Input = forwardRef(
18
29
  (
@@ -38,16 +49,21 @@ const Input = forwardRef(
38
49
  fontWeight = 'Regular',
39
50
  onPressIcon,
40
51
  secureTextEntry,
52
+ keyboardType,
41
53
  style,
54
+ params,
55
+ componentId,
42
56
  ...props
43
57
  }: InputProps,
44
58
  ref,
45
59
  ) => {
46
60
  const {theme} = useContext(ApplicationContext);
61
+ const {appId, code} = useContext<any>(MiniAppContext);
47
62
  const [focused, setFocused] = useState(false);
48
63
  const [haveValue, setHaveValue] = useState(!!value || !!props.defaultValue);
49
64
  const [secureTextInput, setSecureTextInput] = useState(secureTextEntry);
50
65
  const inputRef = (ref as React.RefObject<TextInput>) ?? useRef<TextInput>();
66
+ const screenInfo = useContext<any>(ScreenContext);
51
67
 
52
68
  const onClearText = () => {
53
69
  inputRef?.current?.clear();
@@ -106,6 +122,19 @@ const Input = forwardRef(
106
122
  let textColor = theme.colors.text.default;
107
123
  let placeholderColor = theme.colors.text.hint;
108
124
  let iconTintColor = iconColor;
125
+ const accessibilityID = disabled
126
+ ? getAccessibilityID(
127
+ `${appId}/${code}/${
128
+ screenInfo.screenName
129
+ }/input_${cleanNameForTracking(
130
+ floatingValue ?? placeholder,
131
+ )}_disabled`,
132
+ )
133
+ : getAccessibilityID(
134
+ `${appId}/${code}/${
135
+ screenInfo.screenName
136
+ }/input_${cleanNameForTracking(floatingValue ?? placeholder)}`,
137
+ );
109
138
 
110
139
  if (disabled) {
111
140
  textColor = disabledColor;
@@ -113,6 +142,13 @@ const Input = forwardRef(
113
142
  iconTintColor = disabledColor;
114
143
  }
115
144
 
145
+ if (secureTextEntry) {
146
+ keyboardType = Platform.select({
147
+ ios: 'ascii-capable',
148
+ android: 'visible-password',
149
+ });
150
+ }
151
+
116
152
  return (
117
153
  <View
118
154
  style={[
@@ -140,7 +176,8 @@ const Input = forwardRef(
140
176
  )}
141
177
  <TextInput
142
178
  {...props}
143
- editable={!disabled}
179
+ {...accessibilityID}
180
+ editable={props.editable && !disabled}
144
181
  secureTextEntry={secure}
145
182
  textAlignVertical="center"
146
183
  ref={inputRef}
@@ -160,6 +197,7 @@ const Input = forwardRef(
160
197
  placeholder={placeholder}
161
198
  selectionColor={theme.colors.primary}
162
199
  placeholderTextColor={placeholderColor}
200
+ keyboardType={keyboardType}
163
201
  />
164
202
  </View>
165
203
  <View style={styles.iconView}>
@@ -180,11 +218,34 @@ const Input = forwardRef(
180
218
  );
181
219
  };
182
220
 
221
+ let inputState = 'active';
222
+
223
+ if (value && value?.length > 0) {
224
+ inputState = 'filled';
225
+ }
226
+ if (errorMessage && errorMessage?.length > 0) {
227
+ inputState = 'error';
228
+ }
229
+
230
+ if (disabled) {
231
+ inputState = 'disabled';
232
+ }
233
+
183
234
  return (
184
- <View style={[style, styles.wrapper]}>
185
- {renderInputView()}
186
- <ErrorView errorMessage={errorMessage} errorSpacing={errorSpacing} />
187
- </View>
235
+ <ScreenContext.Provider
236
+ value={{
237
+ ...screenInfo,
238
+ componentName: 'Input',
239
+ params,
240
+ componentLabel: formatComponentName(floatingValue || ''),
241
+ state: inputState,
242
+ componentId,
243
+ }}>
244
+ <View style={[style, styles.wrapper]}>
245
+ {renderInputView()}
246
+ <ErrorView errorMessage={errorMessage} errorSpacing={errorSpacing} />
247
+ </View>
248
+ </ScreenContext.Provider>
188
249
  );
189
250
  },
190
251
  );
@@ -7,6 +7,16 @@ import {InputDropDownProps} from './index';
7
7
  import {Icon} from '../Icon';
8
8
  import {Loader} from '../Loader';
9
9
  import {Styles} from '../Consts';
10
+ import {
11
+ cleanNameForTracking,
12
+ formatComponentName,
13
+ getAccessibilityID,
14
+ } from '../Application/utils';
15
+
16
+ const {
17
+ ScreenContext,
18
+ MiniAppContext,
19
+ } = require('react-native/Libraries/Components/ScreenContext');
10
20
 
11
21
  const InputDropDown = ({
12
22
  value,
@@ -26,10 +36,14 @@ const InputDropDown = ({
26
36
  leadingIcon,
27
37
  leadingIconColor,
28
38
  style,
39
+ params,
40
+ componentId,
29
41
  ...props
30
42
  }: InputDropDownProps) => {
43
+ const {appId, code} = useContext<any>(MiniAppContext);
31
44
  const {theme} = useContext(ApplicationContext);
32
45
  const full = !!value || !!placeholder;
46
+ const screenInfo = useContext<any>(ScreenContext);
33
47
 
34
48
  const renderIcon = (color: string | undefined) => {
35
49
  if (loading) {
@@ -45,6 +59,19 @@ const InputDropDown = ({
45
59
  let textColor = theme.colors.text.default;
46
60
  let placeholderColor = theme.colors.text.hint;
47
61
  let iconTintColor = iconColor;
62
+ const accessibilityID = disabled
63
+ ? getAccessibilityID(
64
+ `${appId}/${code}/${
65
+ screenInfo.screenName
66
+ }/input_${cleanNameForTracking(
67
+ floatingValue ?? placeholder,
68
+ )}_disabled`,
69
+ )
70
+ : getAccessibilityID(
71
+ `${appId}/${code}/${
72
+ screenInfo.screenName
73
+ }/input_${cleanNameForTracking(floatingValue ?? placeholder)}`,
74
+ );
48
75
 
49
76
  if (disabled) {
50
77
  textColor = disabledColor;
@@ -80,6 +107,7 @@ const InputDropDown = ({
80
107
  {full && (
81
108
  <TextInput
82
109
  {...props}
110
+ {...accessibilityID}
83
111
  onPressIn={onPress}
84
112
  editable={false}
85
113
  textAlignVertical="top"
@@ -104,10 +132,22 @@ const InputDropDown = ({
104
132
  };
105
133
 
106
134
  return (
107
- <TouchableOpacity onPress={onPress} style={[style, full && styles.wrapper]}>
108
- {renderInputView()}
109
- <ErrorView errorMessage={errorMessage} errorSpacing={errorSpacing} />
110
- </TouchableOpacity>
135
+ <ScreenContext.Provider
136
+ value={{
137
+ ...screenInfo,
138
+ componentName: 'InputOTP',
139
+ params,
140
+ state: 'enabled',
141
+ componentLabel: formatComponentName(floatingValue || ''),
142
+ componentId,
143
+ }}>
144
+ <TouchableOpacity
145
+ onPress={onPress}
146
+ style={[style, full && styles.wrapper]}>
147
+ {renderInputView()}
148
+ <ErrorView errorMessage={errorMessage} errorSpacing={errorSpacing} />
149
+ </TouchableOpacity>
150
+ </ScreenContext.Provider>
111
151
  );
112
152
  };
113
153
 
@@ -18,6 +18,16 @@ 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 {
22
+ cleanNameForTracking,
23
+ formatComponentName,
24
+ getAccessibilityID,
25
+ } from '../Application/utils';
26
+
27
+ const {
28
+ ScreenContext,
29
+ MiniAppContext,
30
+ } = require('react-native/Libraries/Components/ScreenContext');
21
31
 
22
32
  const InputMoney = forwardRef(
23
33
  (
@@ -36,14 +46,18 @@ const InputMoney = forwardRef(
36
46
  required = false,
37
47
  errorSpacing,
38
48
  style,
49
+ params,
39
50
  defaultValue = '',
51
+ componentId,
40
52
  ...props
41
53
  }: InputMoneyProps,
42
54
  ref,
43
55
  ) => {
44
56
  const {theme} = useContext(ApplicationContext);
57
+ const {appId, code} = useContext<any>(MiniAppContext);
45
58
  const [focused, setFocused] = useState(false);
46
59
  const inputRef = (ref as React.RefObject<TextInput>) ?? useRef<TextInput>();
60
+ const screenInfo = useContext<any>(ScreenContext);
47
61
 
48
62
  const validateText = (text: string) => {
49
63
  const valueFormat = formatMoneyToNumber(text, 'đ');
@@ -89,6 +103,17 @@ const InputMoney = forwardRef(
89
103
  let textColor = theme.colors.text.default;
90
104
  let placeholderColor = theme.colors.text.hint;
91
105
  let iconTintColor = iconColor;
106
+ const accessibilityID = disabled
107
+ ? getAccessibilityID(
108
+ `${appId}/${code}/${
109
+ screenInfo.screenName
110
+ }/input_${cleanNameForTracking(floatingValue)}_disabled`,
111
+ )
112
+ : getAccessibilityID(
113
+ `${appId}/${code}/${
114
+ screenInfo.screenName
115
+ }/input_${cleanNameForTracking(floatingValue)}`,
116
+ );
92
117
 
93
118
  if (disabled) {
94
119
  textColor = disabledColor;
@@ -114,6 +139,7 @@ const InputMoney = forwardRef(
114
139
  <View style={styles.inputView}>
115
140
  <TextInput
116
141
  {...props}
142
+ {...accessibilityID}
117
143
  editable={!disabled}
118
144
  textAlignVertical="top"
119
145
  ref={inputRef}
@@ -151,11 +177,34 @@ const InputMoney = forwardRef(
151
177
  );
152
178
  };
153
179
 
180
+ let inputState = 'active';
181
+
182
+ if (value && value?.length > 0) {
183
+ inputState = 'filled';
184
+ }
185
+ if (errorMessage && errorMessage?.length > 0) {
186
+ inputState = 'error';
187
+ }
188
+
189
+ if (disabled) {
190
+ inputState = 'disabled';
191
+ }
192
+
154
193
  return (
155
- <View style={[style, styles.wrapper]}>
156
- {renderInputView()}
157
- <ErrorView errorMessage={errorMessage} errorSpacing={errorSpacing} />
158
- </View>
194
+ <ScreenContext.Provider
195
+ value={{
196
+ ...screenInfo,
197
+ componentName: 'InputMoney',
198
+ params,
199
+ componentLabel: formatComponentName(floatingValue || ''),
200
+ state: inputState,
201
+ componentId,
202
+ }}>
203
+ <View style={[style, styles.wrapper]}>
204
+ {renderInputView()}
205
+ <ErrorView errorMessage={errorMessage} errorSpacing={errorSpacing} />
206
+ </View>
207
+ </ScreenContext.Provider>
159
208
  );
160
209
  },
161
210
  );
@@ -21,6 +21,16 @@ import styles from './styles';
21
21
  import {ErrorView, getBorderColor} from './common';
22
22
  import {ApplicationContext} from '../Application';
23
23
  import {Spacing} from '../Consts';
24
+ import {
25
+ cleanNameForTracking,
26
+ formatComponentName,
27
+ getAccessibilityID,
28
+ } from '../Application/utils';
29
+
30
+ const {
31
+ ScreenContext,
32
+ MiniAppContext,
33
+ } = require('react-native/Libraries/Components/ScreenContext');
24
34
 
25
35
  const OTPCaret: FC<CaretProps> = ({index, length}) => {
26
36
  const DURATION = 300;
@@ -78,16 +88,21 @@ const InputOTP = forwardRef(
78
88
  onFocus,
79
89
  onBlur,
80
90
  dataType = 'number',
91
+ params,
81
92
  style,
93
+ componentId,
82
94
  ...props
83
95
  }: InputOTPProps,
84
96
  ref,
85
97
  ) => {
86
98
  const MAX_LENGTH = 10;
99
+ const {appId, code} = useContext<any>(MiniAppContext);
100
+
87
101
  const [value, setValue] = useState('');
88
102
  const [focused, setFocused] = useState(false);
89
103
  const inputRef = useRef<TextInput>(null);
90
104
  const {theme} = useContext(ApplicationContext);
105
+ const screenInfo = useContext<any>(ScreenContext);
91
106
 
92
107
  useImperativeHandle(ref, () => ({
93
108
  onChangeText: (text: string) => {
@@ -180,6 +195,12 @@ const InputOTP = forwardRef(
180
195
  );
181
196
  };
182
197
 
198
+ const accessibilityID = getAccessibilityID(
199
+ `${appId}/${code}/${screenInfo.screenName}/input_${cleanNameForTracking(
200
+ floatingValue,
201
+ )}`,
202
+ );
203
+
183
204
  const renderInputView = () => {
184
205
  return (
185
206
  <View
@@ -205,6 +226,7 @@ const InputOTP = forwardRef(
205
226
  <View style={styles.inputView}>
206
227
  <TextInput
207
228
  {...props}
229
+ {...accessibilityID}
208
230
  ref={inputRef}
209
231
  value={value}
210
232
  onChangeText={_onChangeText}
@@ -221,13 +243,23 @@ const InputOTP = forwardRef(
221
243
  };
222
244
 
223
245
  return (
224
- <TouchableOpacity
225
- activeOpacity={1}
226
- onPress={onFocusInput}
227
- style={[style, styles.otpWrapper]}>
228
- {renderInputView()}
229
- <ErrorView errorMessage={errorMessage} errorSpacing={errorSpacing} />
230
- </TouchableOpacity>
246
+ <ScreenContext.Provider
247
+ value={{
248
+ ...screenInfo,
249
+ componentName: 'InputOTP',
250
+ params,
251
+ componentLabel: formatComponentName(floatingValue || ''),
252
+ state: 'enabled',
253
+ componentId,
254
+ }}>
255
+ <TouchableOpacity
256
+ activeOpacity={1}
257
+ onPress={onFocusInput}
258
+ style={[style, styles.otpWrapper]}>
259
+ {renderInputView()}
260
+ <ErrorView errorMessage={errorMessage} errorSpacing={errorSpacing} />
261
+ </TouchableOpacity>
262
+ </ScreenContext.Provider>
231
263
  );
232
264
  },
233
265
  );