@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.
@@ -21,6 +21,12 @@ 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 {formatComponentName, getAccessibilityID} from '../Application/utils';
25
+
26
+ const {
27
+ ScreenContext,
28
+ MiniAppContext,
29
+ } = require('react-native/Libraries/Components/ScreenContext');
24
30
 
25
31
  const OTPCaret: FC<CaretProps> = ({index, length}) => {
26
32
  const DURATION = 300;
@@ -78,16 +84,21 @@ const InputOTP = forwardRef(
78
84
  onFocus,
79
85
  onBlur,
80
86
  dataType = 'number',
87
+ params,
81
88
  style,
89
+ componentId,
82
90
  ...props
83
91
  }: InputOTPProps,
84
92
  ref,
85
93
  ) => {
86
94
  const MAX_LENGTH = 10;
95
+ const {appId, code} = useContext<any>(MiniAppContext);
96
+
87
97
  const [value, setValue] = useState('');
88
98
  const [focused, setFocused] = useState(false);
89
99
  const inputRef = useRef<TextInput>(null);
90
100
  const {theme} = useContext(ApplicationContext);
101
+ const screenInfo = useContext<any>(ScreenContext);
91
102
 
92
103
  useImperativeHandle(ref, () => ({
93
104
  onChangeText: (text: string) => {
@@ -180,6 +191,10 @@ const InputOTP = forwardRef(
180
191
  );
181
192
  };
182
193
 
194
+ const accessibilityID = getAccessibilityID(
195
+ `${appId}/${code}/${screenInfo.screenName}/input_${floatingValue}`,
196
+ );
197
+
183
198
  const renderInputView = () => {
184
199
  return (
185
200
  <View
@@ -205,6 +220,7 @@ const InputOTP = forwardRef(
205
220
  <View style={styles.inputView}>
206
221
  <TextInput
207
222
  {...props}
223
+ {...accessibilityID}
208
224
  ref={inputRef}
209
225
  value={value}
210
226
  onChangeText={_onChangeText}
@@ -221,13 +237,23 @@ const InputOTP = forwardRef(
221
237
  };
222
238
 
223
239
  return (
224
- <TouchableOpacity
225
- activeOpacity={1}
226
- onPress={onFocusInput}
227
- style={[style, styles.otpWrapper]}>
228
- {renderInputView()}
229
- <ErrorView errorMessage={errorMessage} errorSpacing={errorSpacing} />
230
- </TouchableOpacity>
240
+ <ScreenContext.Provider
241
+ value={{
242
+ ...screenInfo,
243
+ componentName: 'InputOTP',
244
+ params,
245
+ componentLabel: formatComponentName(floatingValue || ''),
246
+ state: 'enabled',
247
+ componentId,
248
+ }}>
249
+ <TouchableOpacity
250
+ activeOpacity={1}
251
+ onPress={onFocusInput}
252
+ style={[style, styles.otpWrapper]}>
253
+ {renderInputView()}
254
+ <ErrorView errorMessage={errorMessage} errorSpacing={errorSpacing} />
255
+ </TouchableOpacity>
256
+ </ScreenContext.Provider>
231
257
  );
232
258
  },
233
259
  );
@@ -12,6 +12,12 @@ import styles from './styles';
12
12
  import {Icon} from '../Icon';
13
13
  import {Text} from '../Text';
14
14
  import {checkTyping} from './utils';
15
+ import {getAccessibilityID} from '../Application/utils';
16
+
17
+ const {
18
+ ScreenContext,
19
+ MiniAppContext,
20
+ } = require('react-native/Libraries/Components/ScreenContext');
15
21
 
16
22
  const InputSearch = forwardRef(
17
23
  (
@@ -28,15 +34,19 @@ const InputSearch = forwardRef(
28
34
  style,
29
35
  defaultValue,
30
36
  onPressButtonText,
31
- hasColorBG = true,
37
+ hasColorBG = true,
38
+ params,
39
+ componentId,
32
40
  ...props
33
41
  }: InputSearchProps,
34
42
  ref,
35
43
  ) => {
36
44
  const {theme} = useContext(ApplicationContext);
45
+ const {appId, code} = useContext<any>(MiniAppContext);
37
46
  const [focused, setFocused] = useState(false);
38
47
  const [haveValue, setHaveValue] = useState(!!value || !!defaultValue);
39
48
  const inputRef = (ref as React.RefObject<TextInput>) ?? useRef<TextInput>();
49
+ const screenInfo = useContext<any>(ScreenContext);
40
50
 
41
51
  const _onFocus = (e: NativeSyntheticEvent<TextInputFocusEventData>) => {
42
52
  setFocused(true);
@@ -62,6 +72,9 @@ const InputSearch = forwardRef(
62
72
  return (
63
73
  <TextInput
64
74
  {...props}
75
+ {...getAccessibilityID(
76
+ `${appId}/${code}/${screenInfo.screenName}/input_search`,
77
+ )}
65
78
  textAlignVertical="center"
66
79
  ref={inputRef}
67
80
  style={[
@@ -117,33 +130,56 @@ const InputSearch = forwardRef(
117
130
  );
118
131
  };
119
132
 
120
- const backgroundColor = hasColorBG ? theme.colors.background.default : theme.colors.background.surface
133
+ let inputState = 'empty';
134
+
135
+ if (focused) {
136
+ inputState = 'focus';
137
+ }
138
+
139
+ if (value && value?.length > 0) {
140
+ inputState = 'filled';
141
+ }
142
+
143
+ const backgroundColor = hasColorBG
144
+ ? theme.colors.background.default
145
+ : theme.colors.background.surface;
121
146
 
122
147
  return (
123
- <View style={[style, styles.searchInputContainer]}>
124
- <View
125
- style={[
126
- styles.searchInputWrapper,
127
- {
128
- backgroundColor,
129
- }
130
- ]}>
131
- <Icon
132
- source={'navigation_search'}
133
- size={24}
134
- color={theme.colors.text.hint}
135
- />
136
- {renderInputView()}
137
- {renderIconView()}
148
+ <ScreenContext.Provider
149
+ value={{
150
+ ...screenInfo,
151
+ componentName: 'InputSearch',
152
+ params,
153
+ state: inputState,
154
+ componentId,
155
+ }}>
156
+ <View style={[style, styles.searchInputContainer]}>
157
+ <View
158
+ style={[
159
+ styles.searchInputWrapper,
160
+ {
161
+ backgroundColor,
162
+ },
163
+ ]}>
164
+ <Icon
165
+ source={'navigation_search'}
166
+ size={24}
167
+ color={theme.colors.text.hint}
168
+ />
169
+ {renderInputView()}
170
+ {renderIconView()}
171
+ </View>
172
+ {showButtonText && (
173
+ <TouchableOpacity onPress={onPressButtonText}>
174
+ <Text
175
+ typography={'action_default_bold'}
176
+ style={styles.textButton}>
177
+ {buttonText}
178
+ </Text>
179
+ </TouchableOpacity>
180
+ )}
138
181
  </View>
139
- {showButtonText && (
140
- <TouchableOpacity onPress={onPressButtonText}>
141
- <Text typography={'action_default_bold'} style={styles.textButton}>
142
- {buttonText}
143
- </Text>
144
- </TouchableOpacity>
145
- )}
146
- </View>
182
+ </ScreenContext.Provider>
147
183
  );
148
184
  },
149
185
  );
@@ -18,6 +18,12 @@ import {
18
18
  import {InputTextAreaProps} from './index';
19
19
  import {Icon} from '../Icon';
20
20
  import {ApplicationContext} from '../Application';
21
+ import {getAccessibilityID} from '../Application/utils';
22
+
23
+ const {
24
+ ScreenContext,
25
+ MiniAppContext,
26
+ } = require('react-native/Libraries/Components/ScreenContext');
21
27
 
22
28
  const InputTextArea = forwardRef(
23
29
  (
@@ -43,6 +49,8 @@ const InputTextArea = forwardRef(
43
49
  ref,
44
50
  ) => {
45
51
  const {theme} = useContext(ApplicationContext);
52
+ const screenInfo = useContext<any>(ScreenContext);
53
+ const {appId, code} = useContext<any>(MiniAppContext);
46
54
  const [focused, setFocused] = useState(false);
47
55
  const [inputValue, setInputValue] = useState(defaultValue ?? '');
48
56
  const inputRef = (ref as React.RefObject<TextInput>) ?? useRef<TextInput>();
@@ -88,6 +96,18 @@ const InputTextArea = forwardRef(
88
96
  placeholderColor = disabledColor;
89
97
  }
90
98
 
99
+ const accessibilityID = disabled
100
+ ? getAccessibilityID(
101
+ `${appId}/${code}/${screenInfo.screenName}/input_${
102
+ floatingValue ?? placeholder
103
+ }_disabled`,
104
+ )
105
+ : getAccessibilityID(
106
+ `${appId}/${code}/${screenInfo.screenName}/input_${
107
+ floatingValue ?? placeholder
108
+ }`,
109
+ );
110
+
91
111
  return (
92
112
  <View
93
113
  style={[
@@ -109,6 +129,7 @@ const InputTextArea = forwardRef(
109
129
  <View style={styles.textAreaView}>
110
130
  <TextInput
111
131
  {...props}
132
+ {...accessibilityID}
112
133
  ref={inputRef}
113
134
  editable={!disabled}
114
135
  textAlignVertical="top"
package/Input/index.tsx CHANGED
@@ -80,6 +80,9 @@ export interface InputProps extends TextInputProps {
80
80
  fontWeight?: 'Regular' | 'Bold';
81
81
 
82
82
  onPressIcon?: () => void;
83
+
84
+ params?: any;
85
+ componentId?: string;
83
86
  }
84
87
 
85
88
  type InputPropsWithoutSizeAndIcon = Omit<
@@ -121,7 +124,14 @@ export interface InputSearchProps extends TextInputProps {
121
124
  */
122
125
  icon?: string;
123
126
 
124
- hasColorBG?: boolean
127
+ /**
128
+ *
129
+ */
130
+ hasColorBG?: boolean;
131
+
132
+ params?: any;
133
+
134
+ componentId?: string;
125
135
  }
126
136
 
127
137
  export interface InputMoneyProps extends InputPropsWithoutPlaceholder {}
@@ -141,6 +151,8 @@ export interface InputOTPProps extends InputPropsWithoutSizeAndIcon {
141
151
  * 'number' - The OTP input will be treated as a number.
142
152
  */
143
153
  dataType?: 'string' | 'number';
154
+
155
+ floatingValue: string;
144
156
  }
145
157
 
146
158
  export type CaretProps = {
@@ -245,7 +257,22 @@ export interface InputDropDownProps {
245
257
  */
246
258
  leadingIconColor?: string;
247
259
 
248
- style: ViewStyle | ViewStyle[];
260
+ /**
261
+ * Optional. params for element tracking.
262
+ */
263
+ params?: {
264
+ [key: string]: any;
265
+ };
266
+
267
+ /**
268
+ * component id for element tracking.
269
+ */
270
+ componentId?: string;
271
+
272
+ /**
273
+ * Optional. Represents the style of the InputDropDown component.
274
+ */
275
+ style?: ViewStyle | ViewStyle[];
249
276
  }
250
277
 
251
278
  export {Input, InputTextArea, InputSearch, InputMoney, InputOTP, InputDropDown};
@@ -4,9 +4,14 @@ import {PopupNotifyProps} from './types';
4
4
  import {Radius, Spacing, Styles} from '../Consts';
5
5
  import {Image} from '../Image';
6
6
  import {Text} from '../Text';
7
- import {ApplicationContext, MiniAppContext} from '../Application';
7
+ import {ApplicationContext} from '../Application';
8
8
  import {Button} from '../Button';
9
9
  import {Icon} from '../Icon';
10
+ import {getAccessibilityID} from '../Application/utils';
11
+
12
+ const {
13
+ MiniAppContext,
14
+ } = require('react-native/Libraries/Components/ScreenContext');
10
15
 
11
16
  const PopupNotify: React.FC<PopupNotifyProps> = ({
12
17
  id,
@@ -19,7 +24,7 @@ const PopupNotify: React.FC<PopupNotifyProps> = ({
19
24
  buttonDirection = 'row',
20
25
  onIconClose,
21
26
  }) => {
22
- const context = useContext(MiniAppContext);
27
+ const context = useContext<any>(MiniAppContext);
23
28
  const {theme, navigator, translate} = useContext(ApplicationContext);
24
29
  const [scrollContent, setScrollContent] = useState(false);
25
30
  const closeAction = useRef('touch_outside');
@@ -89,6 +94,7 @@ const PopupNotify: React.FC<PopupNotifyProps> = ({
89
94
  closeAction.current = 'button_action';
90
95
  onAction(secondary?.onPress);
91
96
  }}
97
+ accessibilityLabel={'btn_popup_cancel'}
92
98
  />
93
99
  </View>
94
100
  <View style={styles.buttonSpace} />
@@ -102,6 +108,7 @@ const PopupNotify: React.FC<PopupNotifyProps> = ({
102
108
  closeAction.current = 'button_action';
103
109
  onAction(primary.onPress);
104
110
  }}
111
+ accessibilityLabel={'btn_popup_allow'}
105
112
  />
106
113
  </View>
107
114
  </View>
@@ -111,6 +118,7 @@ const PopupNotify: React.FC<PopupNotifyProps> = ({
111
118
  return (
112
119
  <View style={Styles.columnCenter}>
113
120
  <Button
121
+ accessibilityLabel={'btn_popup_allow'}
114
122
  title={primary.title}
115
123
  size="medium"
116
124
  onPress={() => {
@@ -122,6 +130,7 @@ const PopupNotify: React.FC<PopupNotifyProps> = ({
122
130
  <>
123
131
  <View style={styles.buttonSpace} />
124
132
  <Button
133
+ accessibilityLabel={'btn_popup_cancel'}
125
134
  title={secondary?.title}
126
135
  type="text"
127
136
  size="medium"
@@ -157,6 +166,7 @@ const PopupNotify: React.FC<PopupNotifyProps> = ({
157
166
  const buildCloseIcon = () => {
158
167
  return (
159
168
  <TouchableOpacity
169
+ {...getAccessibilityID?.('ic_popup_close')}
160
170
  style={styles.iconCloseContainer}
161
171
  onPress={() => {
162
172
  closeAction.current = 'icon_close';
@@ -182,6 +192,7 @@ const PopupNotify: React.FC<PopupNotifyProps> = ({
182
192
 
183
193
  return (
184
194
  <View
195
+ {...getAccessibilityID?.(`pu_${context.code}_notify`)}
185
196
  style={[
186
197
  styles.container,
187
198
  {backgroundColor: theme.colors.background.surface},
@@ -1,17 +1,22 @@
1
1
  import React, {useContext, useEffect, useRef} from 'react';
2
2
  import {StyleSheet, TouchableOpacity, View} from 'react-native';
3
3
  import {PopupPromotionProps} from './types';
4
- import {ApplicationContext, MiniAppContext} from '../Application';
4
+ import {ApplicationContext} from '../Application';
5
5
  import {Image} from '../Image';
6
6
  import {Radius, Spacing} from '../Consts';
7
7
  import {Icon} from '../Icon';
8
+ import {getAccessibilityID} from '../Application/utils';
9
+
10
+ const {
11
+ MiniAppContext,
12
+ } = require('react-native/Libraries/Components/ScreenContext');
8
13
 
9
14
  const PopupPromotion: React.FC<PopupPromotionProps> = ({
10
15
  id,
11
16
  image,
12
17
  onIconClose,
13
18
  }) => {
14
- const context = useContext(MiniAppContext);
19
+ const context = useContext<any>(MiniAppContext);
15
20
  const {theme, navigator} = useContext(ApplicationContext);
16
21
  const closeAction = useRef('touch_outside');
17
22
 
@@ -49,7 +54,9 @@ const PopupPromotion: React.FC<PopupPromotionProps> = ({
49
54
  */
50
55
  const buildCloseIcon = () => {
51
56
  return (
52
- <View style={styles.iconCloseContainer}>
57
+ <View
58
+ {...getAccessibilityID?.('ic_popup_close')}
59
+ style={styles.iconCloseContainer}>
53
60
  <TouchableOpacity
54
61
  onPress={() => {
55
62
  closeAction.current = 'icon_close';
@@ -77,7 +84,7 @@ const PopupPromotion: React.FC<PopupPromotionProps> = ({
77
84
  };
78
85
 
79
86
  return (
80
- <View>
87
+ <View {...getAccessibilityID?.(`pu_${context.code}_promotion`)}>
81
88
  <Image
82
89
  source={{
83
90
  uri: image,
package/Radio/index.tsx CHANGED
@@ -6,6 +6,12 @@ import {Text} from '../Text';
6
6
  import styles from './styles';
7
7
  import {ApplicationContext} from '../Application';
8
8
  import {Spacing} from '../Consts';
9
+ import {formatNameLength, getAccessibilityID} from '../Application/utils';
10
+
11
+ const {
12
+ ScreenContext,
13
+ MiniAppContext,
14
+ } = require('react-native/Libraries/Components/ScreenContext');
9
15
 
10
16
  const Radio: FC<RadioProps> = ({
11
17
  value,
@@ -14,8 +20,12 @@ const Radio: FC<RadioProps> = ({
14
20
  onChange,
15
21
  label,
16
22
  style,
23
+ params,
24
+ componentId,
17
25
  }) => {
26
+ const {appId, code} = useContext<any>(MiniAppContext);
18
27
  const {theme} = useContext(ApplicationContext);
28
+ const screenInfo = useContext<any>(ScreenContext);
19
29
  const selected = value === groupValue;
20
30
  let disabledStyle = {};
21
31
  let checkBoxStyle = {
@@ -37,27 +47,44 @@ const Radio: FC<RadioProps> = ({
37
47
  };
38
48
  }
39
49
 
50
+ const accessibilityID = getAccessibilityID?.(
51
+ `${appId}/${code}/${screenInfo.screenName}/rdo_${label}_${value}`,
52
+ );
53
+
40
54
  return (
41
- <TouchableOpacity
42
- onPress={onChange}
43
- disabled={disabled}
44
- style={[
45
- style,
46
- {
47
- flexDirection: 'row',
48
- alignItems: 'center',
49
- },
50
- ]}>
51
- <View
55
+ <ScreenContext.Provider
56
+ value={{
57
+ ...screenInfo,
58
+ componentName: 'Button',
59
+ params,
60
+ state: disabled ? 'disabled' : 'enabled',
61
+ componentId,
62
+ componentLabel: formatNameLength(label || ''),
63
+ componentValue: value,
64
+ action: 'click',
65
+ }}>
66
+ <TouchableOpacity
67
+ {...accessibilityID}
68
+ onPress={onChange}
69
+ disabled={disabled}
52
70
  style={[
53
- styles.radio,
54
- checkBoxStyle,
55
- disabledStyle,
56
- {marginRight: label ? Spacing.XS : 0},
57
- ]}
58
- />
59
- {!!label && <Text typography={'body_default_regular'}>{label}</Text>}
60
- </TouchableOpacity>
71
+ style,
72
+ {
73
+ flexDirection: 'row',
74
+ alignItems: 'center',
75
+ },
76
+ ]}>
77
+ <View
78
+ style={[
79
+ styles.radio,
80
+ checkBoxStyle,
81
+ disabledStyle,
82
+ {marginRight: label ? Spacing.XS : 0},
83
+ ]}
84
+ />
85
+ {!!label && <Text typography={'body_default_regular'}>{label}</Text>}
86
+ </TouchableOpacity>
87
+ </ScreenContext.Provider>
61
88
  );
62
89
  };
63
90
 
package/Radio/types.ts CHANGED
@@ -35,4 +35,9 @@ export type RadioProps = {
35
35
  * Accepts an object of style properties.
36
36
  */
37
37
  style?: ViewStyle;
38
+
39
+
40
+ params?: any
41
+
42
+ componentId?: string
38
43
  };
package/Switch/index.tsx CHANGED
@@ -1,11 +1,20 @@
1
- import React, {FC} from 'react';
1
+ import React, {FC, useContext} from 'react';
2
2
  import {TouchableOpacity, View} from 'react-native';
3
3
  import {SwitchProps} from './types';
4
4
  import styles from './styles';
5
5
  import {Colors} from '../Consts';
6
+ import {getAccessibilityID} from '../Application/utils';
7
+
8
+ const {
9
+ ScreenContext,
10
+ MiniAppContext,
11
+ } = require('react-native/Libraries/Components/ScreenContext');
6
12
 
7
13
  const Switch: FC<SwitchProps> = props => {
8
- const {value, onChange, disabled, style} = props;
14
+ const {appId, code} = useContext<any>(MiniAppContext);
15
+ const {value, onChange, disabled, style, params, componentId} = props;
16
+ const screenInfo = useContext<any>(ScreenContext);
17
+
9
18
  const circleBackgroundColor = value ? Colors.black_01 : Colors.black_03;
10
19
  const circleAlign = value ? 'flex-end' : 'flex-start';
11
20
 
@@ -14,19 +23,35 @@ const Switch: FC<SwitchProps> = props => {
14
23
  backgroundColor = value ? Colors.green_09 : Colors.black_05;
15
24
  }
16
25
 
26
+ const accessibilityID = getAccessibilityID?.(
27
+ `${appId}/${code}/${screenInfo.screenName}/swt_${value}`,
28
+ );
29
+
17
30
  return (
18
- <TouchableOpacity
19
- disabled={disabled}
20
- onPress={() => onChange?.(!value)}
21
- style={[
22
- style,
23
- styles.container,
24
- {backgroundColor, alignItems: circleAlign},
25
- ]}>
26
- <View style={[styles.circle, {backgroundColor: circleBackgroundColor}]}>
27
- <View style={[styles.circleSmall, {backgroundColor}]} />
28
- </View>
29
- </TouchableOpacity>
31
+ <ScreenContext.Provider
32
+ value={{
33
+ ...screenInfo,
34
+ componentName: 'Button',
35
+ params,
36
+ state: disabled ? 'disabled' : 'enabled',
37
+ componentId,
38
+ componentValue: value,
39
+ action: 'click',
40
+ }}>
41
+ <TouchableOpacity
42
+ {...accessibilityID}
43
+ disabled={disabled}
44
+ onPress={() => onChange?.(!value)}
45
+ style={[
46
+ style,
47
+ styles.container,
48
+ {backgroundColor, alignItems: circleAlign},
49
+ ]}>
50
+ <View style={[styles.circle, {backgroundColor: circleBackgroundColor}]}>
51
+ <View style={[styles.circleSmall, {backgroundColor}]} />
52
+ </View>
53
+ </TouchableOpacity>
54
+ </ScreenContext.Provider>
30
55
  );
31
56
  };
32
57
 
package/Switch/types.ts CHANGED
@@ -23,4 +23,8 @@ export type SwitchProps = {
23
23
  * Accepts an object of style properties.
24
24
  */
25
25
  style?: ViewStyle;
26
+
27
+ params?: any
28
+
29
+ componentId?: string
26
30
  };
package/Text/index.tsx CHANGED
@@ -95,6 +95,7 @@ const Text: React.FC<TextProps> = ({
95
95
  };
96
96
 
97
97
  const textStyle = getTypoStyle(typography);
98
+
98
99
  return (
99
100
  <RNText
100
101
  {...rest}