@momo-kits/foundation 0.89.5 → 0.92.1-beta.16

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,20 @@ const Shadow = {
213
213
  elevation: 6,
214
214
  },
215
215
  }),
216
+
217
+ Pink: Platform.select({
218
+ ios: {
219
+ shadowColor: '#e27eb5',
220
+ shadowOffset: {width: 0, height: 6},
221
+ shadowOpacity: 0.25,
222
+ shadowRadius: 8,
223
+ },
224
+ android: {
225
+ elevation: 16,
226
+ shadowColor: '#e27eb5',
227
+ shadowOpacity: 0.25,
228
+ },
229
+ }),
216
230
  };
217
231
 
218
232
  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,21 @@ 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(
137
+ floatingValue ?? placeholder ?? value,
138
+ )}`,
139
+ );
109
140
 
110
141
  if (disabled) {
111
142
  textColor = disabledColor;
@@ -113,6 +144,13 @@ const Input = forwardRef(
113
144
  iconTintColor = disabledColor;
114
145
  }
115
146
 
147
+ if (secureTextEntry) {
148
+ keyboardType = Platform.select({
149
+ ios: 'ascii-capable',
150
+ android: 'visible-password',
151
+ });
152
+ }
153
+
116
154
  return (
117
155
  <View
118
156
  style={[
@@ -140,7 +178,8 @@ const Input = forwardRef(
140
178
  )}
141
179
  <TextInput
142
180
  {...props}
143
- editable={!disabled}
181
+ {...accessibilityID}
182
+ editable={props.editable && !disabled}
144
183
  secureTextEntry={secure}
145
184
  textAlignVertical="center"
146
185
  ref={inputRef}
@@ -160,6 +199,7 @@ const Input = forwardRef(
160
199
  placeholder={placeholder}
161
200
  selectionColor={theme.colors.primary}
162
201
  placeholderTextColor={placeholderColor}
202
+ keyboardType={keyboardType}
163
203
  />
164
204
  </View>
165
205
  <View style={styles.iconView}>
@@ -180,11 +220,34 @@ const Input = forwardRef(
180
220
  );
181
221
  };
182
222
 
223
+ let inputState = 'active';
224
+
225
+ if (value && value?.length > 0) {
226
+ inputState = 'filled';
227
+ }
228
+ if (errorMessage && errorMessage?.length > 0) {
229
+ inputState = 'error';
230
+ }
231
+
232
+ if (disabled) {
233
+ inputState = 'disabled';
234
+ }
235
+
183
236
  return (
184
- <View style={[style, styles.wrapper]}>
185
- {renderInputView()}
186
- <ErrorView errorMessage={errorMessage} errorSpacing={errorSpacing} />
187
- </View>
237
+ <ScreenContext.Provider
238
+ value={{
239
+ ...screenInfo,
240
+ componentName: 'Input',
241
+ params,
242
+ componentLabel: formatComponentName(floatingValue || ''),
243
+ state: inputState,
244
+ componentId,
245
+ }}>
246
+ <View style={[style, styles.wrapper]}>
247
+ {renderInputView()}
248
+ <ErrorView errorMessage={errorMessage} errorSpacing={errorSpacing} />
249
+ </View>
250
+ </ScreenContext.Provider>
188
251
  );
189
252
  },
190
253
  );
@@ -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,9 +107,9 @@ const InputDropDown = ({
80
107
  {full && (
81
108
  <TextInput
82
109
  {...props}
110
+ {...accessibilityID}
83
111
  onPressIn={onPress}
84
112
  editable={false}
85
- textAlignVertical="top"
86
113
  style={[
87
114
  styles.input,
88
115
  {
@@ -104,10 +131,22 @@ const InputDropDown = ({
104
131
  };
105
132
 
106
133
  return (
107
- <TouchableOpacity onPress={onPress} style={[style, full && styles.wrapper]}>
108
- {renderInputView()}
109
- <ErrorView errorMessage={errorMessage} errorSpacing={errorSpacing} />
110
- </TouchableOpacity>
134
+ <ScreenContext.Provider
135
+ value={{
136
+ ...screenInfo,
137
+ componentName: 'InputOTP',
138
+ params,
139
+ state: 'enabled',
140
+ componentLabel: formatComponentName(floatingValue || ''),
141
+ componentId,
142
+ }}>
143
+ <TouchableOpacity
144
+ onPress={onPress}
145
+ style={[style, full && styles.wrapper]}>
146
+ {renderInputView()}
147
+ <ErrorView errorMessage={errorMessage} errorSpacing={errorSpacing} />
148
+ </TouchableOpacity>
149
+ </ScreenContext.Provider>
111
150
  );
112
151
  };
113
152
 
@@ -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,8 +139,8 @@ const InputMoney = forwardRef(
114
139
  <View style={styles.inputView}>
115
140
  <TextInput
116
141
  {...props}
142
+ {...accessibilityID}
117
143
  editable={!disabled}
118
- textAlignVertical="top"
119
144
  ref={inputRef}
120
145
  keyboardType={'number-pad'}
121
146
  style={[
@@ -151,11 +176,34 @@ const InputMoney = forwardRef(
151
176
  );
152
177
  };
153
178
 
179
+ let inputState = 'active';
180
+
181
+ if (value && value?.length > 0) {
182
+ inputState = 'filled';
183
+ }
184
+ if (errorMessage && errorMessage?.length > 0) {
185
+ inputState = 'error';
186
+ }
187
+
188
+ if (disabled) {
189
+ inputState = 'disabled';
190
+ }
191
+
154
192
  return (
155
- <View style={[style, styles.wrapper]}>
156
- {renderInputView()}
157
- <ErrorView errorMessage={errorMessage} errorSpacing={errorSpacing} />
158
- </View>
193
+ <ScreenContext.Provider
194
+ value={{
195
+ ...screenInfo,
196
+ componentName: 'InputMoney',
197
+ params,
198
+ componentLabel: formatComponentName(floatingValue || ''),
199
+ state: inputState,
200
+ componentId,
201
+ }}>
202
+ <View style={[style, styles.wrapper]}>
203
+ {renderInputView()}
204
+ <ErrorView errorMessage={errorMessage} errorSpacing={errorSpacing} />
205
+ </View>
206
+ </ScreenContext.Provider>
159
207
  );
160
208
  },
161
209
  );
@@ -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
  );