@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.
@@ -15,7 +15,7 @@ import {
15
15
  View,
16
16
  ViewStyle,
17
17
  } from 'react-native';
18
- import {ApplicationContext, MiniAppContext} from './index';
18
+ import {ApplicationContext} from './index';
19
19
  import {Colors, Radius, Spacing, Styles} from '../Consts';
20
20
  import {Image} from '../Image';
21
21
  import {
@@ -29,6 +29,11 @@ import {scaleSize, Text} from '../Text';
29
29
  import {Icon} from '../Icon';
30
30
  import {PopupNotify} from '../Popup';
31
31
  import {Badge, BadgeDot} from '../Badge';
32
+ import {getAccessibilityID} from './utils';
33
+
34
+ const {
35
+ MiniAppContext,
36
+ } = require('react-native/Libraries/Components/ScreenContext');
32
37
 
33
38
  const NavigationButton: React.FC<NavigationButtonProps> = ({
34
39
  icon,
@@ -37,6 +42,7 @@ const NavigationButton: React.FC<NavigationButtonProps> = ({
37
42
  useBorder = true,
38
43
  badgeType,
39
44
  badgeValue,
45
+ accessibilityID = '',
40
46
  }) => {
41
47
  const {theme} = useContext(ApplicationContext);
42
48
  let buttonStyle: ViewStyle = {backgroundColor: '#00000066'};
@@ -64,7 +70,9 @@ const NavigationButton: React.FC<NavigationButtonProps> = ({
64
70
  }, [badgeType, badgeValue]);
65
71
 
66
72
  return (
67
- <View style={{width: scaleSize(28)}}>
73
+ <View
74
+ {...getAccessibilityID(accessibilityID)}
75
+ style={{width: scaleSize(28)}}>
68
76
  <TouchableOpacity
69
77
  style={[styles.navigationButton, buttonStyle]}
70
78
  onPress={onPress}>
@@ -90,6 +98,7 @@ const HeaderTitle: React.FC<any> = props => {
90
98
  return (
91
99
  <Animated.Text
92
100
  {...props}
101
+ {...getAccessibilityID('title_navigation_header')}
93
102
  style={[
94
103
  styles.title,
95
104
  {fontFamily: `${theme.font}-Bold`, opacity, color: props.tintColor},
@@ -104,7 +113,7 @@ const HeaderLeft: React.FC<HeaderBackProps> = ({
104
113
  onPressLeftHeader,
105
114
  useBorder,
106
115
  }) => {
107
- const context = useContext(MiniAppContext);
116
+ const context = useContext<any>(MiniAppContext);
108
117
  const {navigator} = useContext(ApplicationContext);
109
118
 
110
119
  useEffect(() => {
@@ -120,13 +129,19 @@ const HeaderLeft: React.FC<HeaderBackProps> = ({
120
129
  const goBack = () => {
121
130
  const canGoBack = navigator?.ref.current?.canGoBack();
122
131
  if (!canGoBack) {
123
- const currentRoute = navigator?.ref?.current.getCurrentRoute();
124
- navigator?.maxApi?.trackEvent?.('service_icon_clicked', {
132
+ const currentRoute = navigator?.ref?.current?.getCurrentRoute?.();
133
+ const params = {
125
134
  ...context,
126
135
  screen_name: currentRoute?.params?.screen?.name ?? currentRoute?.name,
127
136
  trigger_id: '111154000000000000',
128
137
  icon_name: 'back',
138
+ };
139
+ navigator?.maxApi?.showToastDebug?.({
140
+ appId: `auto - ${context.appId}`,
141
+ message: 'service_icon_clicked',
142
+ params,
129
143
  });
144
+ navigator?.maxApi?.trackEvent?.('service_icon_clicked', params);
130
145
  }
131
146
  if (canGoBack) {
132
147
  navigator?.ref.current?.goBack();
@@ -160,10 +175,10 @@ const HeaderLeft: React.FC<HeaderBackProps> = ({
160
175
  }
161
176
  return true;
162
177
  };
163
-
164
178
  return (
165
179
  <View style={styles.headerLeft}>
166
180
  <NavigationButton
181
+ accessibilityID="btn_navigation_back"
167
182
  icon="ic_back"
168
183
  tintColor={tintColor}
169
184
  onPress={goBackSafe}
@@ -237,7 +252,10 @@ const HeaderCustom: React.FC<TitleCustomProps> = ({
237
252
  )}
238
253
  </View>
239
254
  <View style={[Styles.flex, {paddingHorizontal: 8}]}>
240
- <Text typography="header_default_bold" color={tintColor}>
255
+ <Text
256
+ {...getAccessibilityID('title_navigation_header')}
257
+ typography="header_default_bold"
258
+ color={tintColor}>
241
259
  {title}
242
260
  </Text>
243
261
  <Text typography="description_default_regular" color={tintColor}>
@@ -284,10 +302,10 @@ const HeaderToolkitAction: React.FC<any> = ({
284
302
  tintColor,
285
303
  pinnedTool,
286
304
  runtimeTools = [],
287
- preventBack,
305
+ preventClose,
288
306
  }) => {
289
307
  const {theme, navigator} = useContext(ApplicationContext);
290
- const miniContext = useContext(MiniAppContext);
308
+ const miniContext = useContext<any>(MiniAppContext);
291
309
  const [toolConfig, setToolConfig] = useState<any>();
292
310
  const {onAction} = toolConfig ?? {};
293
311
 
@@ -331,15 +349,15 @@ const HeaderToolkitAction: React.FC<any> = ({
331
349
  };
332
350
 
333
351
  const onClose = () => {
334
- if (preventBack) {
352
+ if (preventClose) {
335
353
  navigator?.showModal({
336
354
  screen: () => (
337
355
  <PopupNotify
338
- {...preventBack}
356
+ {...preventClose}
339
357
  primary={{
340
- title: preventBack.primary.title,
358
+ title: preventClose.primary.title,
341
359
  onPress: () => {
342
- preventBack?.primary.onPress();
360
+ preventClose?.primary.onPress();
343
361
  navigator?.maxApi?.dispatchFunction?.(
344
362
  'dismiss',
345
363
  undefined,
@@ -363,6 +381,7 @@ const HeaderToolkitAction: React.FC<any> = ({
363
381
  if (pinTool)
364
382
  return (
365
383
  <NavigationButton
384
+ accessibilityID="btn_navigation_pin"
366
385
  icon={pinTool.icon as string}
367
386
  tintColor={tintColor}
368
387
  badgeValue={badgeValue}
@@ -380,7 +399,6 @@ const HeaderToolkitAction: React.FC<any> = ({
380
399
  />
381
400
  );
382
401
  };
383
-
384
402
  if (toolConfig) {
385
403
  return (
386
404
  <View style={styles.headerRightButton}>
@@ -393,11 +411,15 @@ const HeaderToolkitAction: React.FC<any> = ({
393
411
  borderWidth: backgroundColor ? 0.5 : 0,
394
412
  },
395
413
  ]}>
396
- <TouchableOpacity onPress={onMore}>
414
+ <TouchableOpacity
415
+ {...getAccessibilityID('btn_navigation_more')}
416
+ onPress={onMore}>
397
417
  <Icon color={tintColor} source="navigation_more_horiz" size={20} />
398
418
  </TouchableOpacity>
399
419
  <View style={[styles.divider, {backgroundColor: tintColor}]} />
400
- <TouchableOpacity onPress={onClose}>
420
+ <TouchableOpacity
421
+ {...getAccessibilityID('btn_navigation_close')}
422
+ onPress={onClose}>
401
423
  <Icon
402
424
  color={tintColor}
403
425
  source="16_navigation_close_circle"
@@ -415,7 +437,7 @@ const HeaderToolkitAction: React.FC<any> = ({
415
437
  const HeaderAnimated: React.FC<HeaderAnimatedProps> = ({
416
438
  animatedValue,
417
439
  image,
418
- onPress,
440
+ children,
419
441
  }) => {
420
442
  const scale = animatedValue.interpolate({
421
443
  inputRange: [-300, 0, 300],
@@ -434,21 +456,21 @@ const HeaderAnimated: React.FC<HeaderAnimatedProps> = ({
434
456
  });
435
457
 
436
458
  return (
437
- <TouchableOpacity onPress={onPress}>
438
- <Animated.View
439
- style={{
440
- height: 210,
441
- opacity: opacity,
442
- transform: [{scale}, {translateY}],
443
- }}>
459
+ <Animated.View
460
+ style={{
461
+ height: 210,
462
+ opacity: opacity,
463
+ transform: [{scale}, {translateY}],
464
+ }}>
465
+ {children ?? (
444
466
  <Image
445
467
  source={{
446
468
  uri: image,
447
469
  }}
448
470
  style={{width: '100%', height: '100%'}}
449
471
  />
450
- </Animated.View>
451
- </TouchableOpacity>
472
+ )}
473
+ </Animated.View>
452
474
  );
453
475
  };
454
476
 
@@ -1,29 +1,21 @@
1
- import React, {useContext, useEffect, useMemo, useRef, useState} from 'react';
1
+ import React, {useContext, useEffect, useRef} from 'react';
2
2
  import {
3
- Dimensions,
4
- Keyboard,
5
3
  KeyboardAvoidingView,
6
4
  Platform,
7
5
  Pressable,
8
6
  StyleSheet,
7
+ TouchableOpacity,
9
8
  View,
10
9
  } from 'react-native';
10
+ import {Modalize} from 'react-native-modalize';
11
11
  import {SafeAreaView, useSafeAreaInsets} from 'react-native-safe-area-context';
12
- import {
13
- BottomSheetBackdrop,
14
- BottomSheetModal,
15
- BottomSheetView,
16
- } from '@gorhom/bottom-sheet';
12
+
13
+ import {ApplicationContext} from '.';
14
+ import {Radius, Spacing, Styles} from '../Consts';
15
+ import {Icon} from '../Icon';
16
+ import {Text} from '../Text';
17
17
  import Navigation from './Navigation';
18
18
  import {BottomSheetParams, ModalParams} from './types';
19
- import {Radius, Spacing, Styles} from '../Consts';
20
- import {
21
- ApplicationContext,
22
- HeaderRightAction,
23
- NavigationButton,
24
- NavigationContainer,
25
- } from './index';
26
- import {HeaderBackground, HeaderLeft, HeaderTitle} from './Components';
27
19
 
28
20
  const ModalScreen: React.FC<any> = props => {
29
21
  /**
@@ -92,141 +84,88 @@ const Modal: React.FC<ModalParams> = props => {
92
84
  };
93
85
 
94
86
  const BottomSheet: React.FC<BottomSheetParams> = props => {
95
- const insets = useSafeAreaInsets();
96
87
  const {theme, navigator} = useContext(ApplicationContext);
97
- const [keyboardSnap, setKeyboardSnap] = useState(0);
98
- const {screen, options, snapPoint, indicatorColor}: BottomSheetParams =
99
- props.route.params;
100
- const Component = useRef(screen).current;
88
+ const {
89
+ screen: Screen,
90
+ options,
91
+ footerComponent,
92
+ flatListProps,
93
+ }: BottomSheetParams = props.route.params;
94
+
101
95
  const navigation = new Navigation(props.navigation, theme);
96
+
102
97
  const params = {
103
98
  ...props.route.params,
104
99
  navigation,
105
100
  };
106
101
 
107
102
  delete params.screen;
108
-
109
- const snapPoints = useMemo(() => {
110
- if (snapPoint) {
111
- const current = parseInt(snapPoint) + keyboardSnap * 100;
112
- return [`${current}%`];
113
- }
114
- return ['50%', '70%', '90%'];
115
- }, [keyboardSnap]);
116
-
117
- const bottomSheetRef = useRef<any>(null);
118
- const mountedRef = useRef(true);
119
-
120
- let backgroundColor = theme.colors.background.default;
121
- let bottomInset = keyboardSnap * Dimensions.get('window').height;
122
- if (bottomInset > 16) {
123
- bottomInset -= 16;
124
- }
125
- if (options?.surface) {
126
- backgroundColor = theme.colors.background.surface;
127
- }
103
+ const modalizeRef = useRef<Modalize>(null);
128
104
 
129
105
  useEffect(() => {
130
- const keyboardDidShow = Keyboard.addListener('keyboardDidShow', e => {
131
- setKeyboardSnap(
132
- e.endCoordinates.height / Dimensions.get('window').height,
133
- );
134
- bottomSheetRef.current?.expand();
135
- });
136
-
137
- const keyboardDidHide = Keyboard.addListener('keyboardDidHide', () => {
138
- setKeyboardSnap(0);
139
- });
140
-
141
- bottomSheetRef.current?.present();
142
- return () => {
143
- mountedRef.current = false;
144
- keyboardDidShow.remove();
145
- keyboardDidHide.remove();
146
- };
106
+ modalizeRef.current?.open();
147
107
  }, []);
148
108
 
149
- const backdropComponent = (backdropProps: any) => (
150
- <BottomSheetBackdrop
151
- disappearsOnIndex={-1}
152
- appearsOnIndex={0}
153
- {...backdropProps}
154
- />
155
- );
109
+ const handleClose = () => {
110
+ modalizeRef?.current?.close();
111
+ };
156
112
 
157
113
  return (
158
114
  <SafeAreaView style={Styles.flex}>
159
- <BottomSheetModal
160
- ref={bottomSheetRef}
161
- snapPoints={snapPoints}
162
- onDismiss={() => {
163
- if (mountedRef.current) {
164
- navigator?.pop();
165
- }
115
+ <Modalize
116
+ keyboardAvoidingOffset={-20}
117
+ adjustToContentHeight
118
+ closeOnOverlayTap
119
+ closeSnapPointStraightEnabled
120
+ onClosed={() => {
121
+ navigator?.pop();
166
122
  }}
167
- bottomInset={Platform.OS === 'ios' ? bottomInset : 0}
168
- handleComponent={null}
169
- backdropComponent={backdropComponent}>
170
- <BottomSheetView>
171
- <View style={[styles.sheetContainer, {backgroundColor}]}>
172
- <View style={styles.indicatorContainer}>
173
- <View
174
- style={[
175
- styles.indicator,
176
- {backgroundColor: theme.colors.text.disable},
177
- ]}
178
- />
179
- </View>
180
- <NavigationContainer
181
- maxApi={navigator?.maxApi}
182
- theme={{
183
- ...theme,
184
- assets: {...theme.assets, headerBackground: undefined},
185
- }}
186
- screen={props => <Component {...props} {...params} />}
187
- options={{
188
- ...options,
189
- ...{
190
- headerLeft: (props: any) => {
191
- if (props.canGoBack) {
192
- return <HeaderLeft {...props} useBorder={false} />;
193
- }
194
- },
195
- headerTitle: (props: any) => {
196
- return <HeaderTitle {...props} />;
197
- },
198
- headerTintColor: theme.colors.text.default,
199
- headerBackground: () => (
200
- <HeaderBackground backgroundColor={backgroundColor} />
201
- ),
202
- headerTransparent: false,
203
- },
204
- headerTitleAlign: 'center',
205
- headerRight: props => (
206
- <HeaderRightAction>
207
- <NavigationButton
208
- {...props}
209
- icon="24_navigation_close"
210
- useBorder={false}
211
- onPress={() => bottomSheetRef.current?.dismiss()}
212
- />
213
- </HeaderRightAction>
214
- ),
215
- }}
216
- />
217
- <View
218
- style={{
219
- height: Math.min(insets.bottom, 20),
220
- backgroundColor: indicatorColor ?? backgroundColor,
221
- }}
222
- />
223
- </View>
224
- </BottomSheetView>
225
- </BottomSheetModal>
123
+ ref={modalizeRef}
124
+ withHandle={false}
125
+ flatListProps={flatListProps}
126
+ HeaderComponent={headerDefault(
127
+ options?.title ?? options?.customTitle?.title ?? '',
128
+ handleClose,
129
+ )}
130
+ FooterComponent={footerDefault(footerComponent)}>
131
+ <View style={styles.bottomSheetContainer}>
132
+ <Screen {...props} {...params} />
133
+ </View>
134
+ </Modalize>
226
135
  </SafeAreaView>
227
136
  );
228
137
  };
229
138
 
139
+ const headerDefault = (title: string, onClose: () => void) => {
140
+ return (
141
+ <View style={styles.header}>
142
+ <Text
143
+ style={styles.textOption}
144
+ numberOfLines={2}
145
+ typography="header_default_bold">
146
+ {title ?? ''}
147
+ </Text>
148
+ <TouchableOpacity style={styles.buttonClose} onPress={onClose}>
149
+ <Icon source="navigation_close" />
150
+ </TouchableOpacity>
151
+ </View>
152
+ );
153
+ };
154
+
155
+ const footerDefault = (footerComponent: React.ReactNode) => {
156
+ const insets = useSafeAreaInsets();
157
+ if (!footerComponent) return;
158
+ return (
159
+ <View
160
+ style={{
161
+ marginBottom: Math.min(insets.bottom, 21) + Spacing.S,
162
+ paddingHorizontal: 12,
163
+ }}>
164
+ {footerComponent}
165
+ </View>
166
+ );
167
+ };
168
+
230
169
  const styles = StyleSheet.create({
231
170
  container: {flex: 1, flexDirection: 'row'},
232
171
  modalContent: {
@@ -263,6 +202,43 @@ const styles = StyleSheet.create({
263
202
  height: 4,
264
203
  borderRadius: Radius.S,
265
204
  },
205
+ bottomSheetContainer: {
206
+ width: '100%',
207
+ backgroundColor: 'white',
208
+ borderTopRightRadius: 16,
209
+ borderTopLeftRadius: 16,
210
+ },
211
+ header: {
212
+ height: 50,
213
+ width: '100%',
214
+ alignItems: 'center',
215
+ justifyContent: 'center',
216
+ },
217
+ textOption: {
218
+ fontSize: 16,
219
+ color: '#303233',
220
+ textAlign: 'center',
221
+ fontWeight: 'bold',
222
+ paddingHorizontal: 60,
223
+ },
224
+ imageOption: {
225
+ height: 1,
226
+ backgroundColor: '#ebebeb',
227
+ width: '100%',
228
+ position: 'absolute',
229
+ bottom: 1,
230
+ },
231
+ buttonClose: {
232
+ padding: 12,
233
+ position: 'absolute',
234
+ right: 0,
235
+ },
236
+ icon: {
237
+ width: 24,
238
+ height: 24,
239
+ tintColor: '#303233',
240
+ backgroundColor: 'red',
241
+ },
266
242
  });
267
243
 
268
244
  export default ModalScreen;
@@ -1,10 +1,10 @@
1
1
  import React, {useContext, useEffect, useRef, useState} from 'react';
2
- import {BottomSheetModalProvider} from '@gorhom/bottom-sheet';
3
2
  import {SafeAreaProvider} from 'react-native-safe-area-context';
4
3
  import {
5
4
  NavigationContainer as ReactNavigationContainer,
6
5
  NavigationContainerRef,
7
6
  } from '@react-navigation/native';
7
+ import {BottomSheetModalProvider} from '@gorhom/bottom-sheet';
8
8
  import {createStackNavigator} from '@react-navigation/stack';
9
9
  import {DeviceEventEmitter} from 'react-native';
10
10
  import StackScreen from './StackScreen';
@@ -12,9 +12,19 @@ import ModalScreen from './ModalScreen';
12
12
  import Navigator from './Navigator';
13
13
  import {getDialogOptions, getModalOptions, getStackOptions} from './utils';
14
14
  import {LocalizationObject, NavigationContainerProps} from './types';
15
- import {ApplicationContext, MiniAppContext} from './index';
15
+ import {ApplicationContext} from './index';
16
16
  import kitLocalization from '../Assets/language.json';
17
17
 
18
+ const {
19
+ MiniAppContext,
20
+ } = require('react-native/Libraries/Components/ScreenContext');
21
+
22
+ /**
23
+ * link for deprecated
24
+ */
25
+
26
+ console.log(typeof BottomSheetModalProvider);
27
+
18
28
  const Stack = createStackNavigator();
19
29
 
20
30
  const NavigationContainer: React.FC<NavigationContainerProps> = ({
@@ -23,10 +33,12 @@ const NavigationContainer: React.FC<NavigationContainerProps> = ({
23
33
  options,
24
34
  maxApi,
25
35
  localization,
36
+ initialParams,
26
37
  }) => {
27
- const context = useContext(MiniAppContext);
28
- const navigationRef = React.useRef<NavigationContainerRef>(null);
29
- const navigator = useRef(new Navigator(navigationRef));
38
+ const context = useContext<any>(MiniAppContext);
39
+ const navigationRef = useRef<NavigationContainerRef>(null);
40
+ const isReady = useRef(false);
41
+ const navigator = useRef(new Navigator(navigationRef, isReady));
30
42
  const [showGrid, setShowGrid] = useState(false);
31
43
  const config = useRef<any>();
32
44
 
@@ -67,52 +79,53 @@ const NavigationContainer: React.FC<NavigationContainerProps> = ({
67
79
 
68
80
  return (
69
81
  <SafeAreaProvider>
70
- <BottomSheetModalProvider>
71
- <ApplicationContext.Provider
72
- value={{
73
- navigator: navigator.current,
74
- config: config.current,
75
- theme,
76
- showGrid,
77
- translate,
78
- }}>
79
- <ReactNavigationContainer
80
- theme={{
81
- ...theme,
82
- colors: {
83
- ...theme.colors,
84
- background: theme.colors.background.default,
85
- card: theme.colors.background.surface,
86
- text: theme.colors.text.default,
87
- border: theme.colors.border.default,
88
- notification: theme.colors.error.primary,
89
- },
90
- }}
91
- ref={navigator.current?.ref}
92
- independent={true}>
93
- <Stack.Navigator initialRouteName="Stack" headerMode="screen">
94
- <Stack.Screen
95
- name="Stack"
96
- component={StackScreen}
97
- initialParams={{screen}}
98
- options={{...getStackOptions(), ...options}}
99
- />
100
- <Stack.Screen
101
- name="Dialog"
102
- component={StackScreen}
103
- options={getDialogOptions()}
104
- initialParams={{screen}}
105
- />
106
- <Stack.Screen
107
- name="Modal"
108
- component={ModalScreen}
109
- options={getModalOptions()}
110
- initialParams={{screen}}
111
- />
112
- </Stack.Navigator>
113
- </ReactNavigationContainer>
114
- </ApplicationContext.Provider>
115
- </BottomSheetModalProvider>
82
+ <ApplicationContext.Provider
83
+ value={{
84
+ navigator: navigator.current,
85
+ config: config.current,
86
+ theme,
87
+ showGrid,
88
+ translate,
89
+ }}>
90
+ <ReactNavigationContainer
91
+ theme={{
92
+ ...theme,
93
+ colors: {
94
+ ...theme.colors,
95
+ background: theme.colors.background.default,
96
+ card: theme.colors.background.surface,
97
+ text: theme.colors.text.default,
98
+ border: theme.colors.border.default,
99
+ notification: theme.colors.error.primary,
100
+ },
101
+ }}
102
+ ref={navigator.current?.ref}
103
+ onReady={() => {
104
+ isReady.current = true;
105
+ }}
106
+ independent={true}>
107
+ <Stack.Navigator initialRouteName="Stack" headerMode="screen">
108
+ <Stack.Screen
109
+ name="Stack"
110
+ component={StackScreen}
111
+ initialParams={{screen, initialParams}}
112
+ options={{...getStackOptions(), ...options}}
113
+ />
114
+ <Stack.Screen
115
+ name="Dialog"
116
+ component={StackScreen}
117
+ options={getDialogOptions()}
118
+ initialParams={{screen}}
119
+ />
120
+ <Stack.Screen
121
+ name="Modal"
122
+ component={ModalScreen}
123
+ options={getModalOptions()}
124
+ initialParams={{screen}}
125
+ />
126
+ </Stack.Navigator>
127
+ </ReactNavigationContainer>
128
+ </ApplicationContext.Provider>
116
129
  </SafeAreaProvider>
117
130
  );
118
131
  };