@momo-kits/foundation 0.76.1-beta.2 → 0.77.1-optimize.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.
Files changed (100) hide show
  1. package/Application/BottomTab/BottomTabBar.tsx +439 -0
  2. package/Application/BottomTab/index.tsx +138 -0
  3. package/Application/Components.tsx +348 -167
  4. package/Application/ModalScreen.tsx +135 -98
  5. package/Application/Navigation.ts +22 -16
  6. package/Application/NavigationContainer.tsx +99 -48
  7. package/Application/Navigator.ts +110 -41
  8. package/Application/StackScreen.tsx +129 -8
  9. package/Application/index.ts +23 -4
  10. package/Application/types.ts +86 -34
  11. package/Application/utils.tsx +67 -49
  12. package/Assets/DotAnimation.json +256 -0
  13. package/Assets/SpinnerAnimation.json +1027 -0
  14. package/Assets/icon.json +83 -5
  15. package/Assets/icon_bank.json +506 -0
  16. package/Assets/language.json +202 -0
  17. package/Badge/Badge.tsx +56 -0
  18. package/Badge/BadgeDot.tsx +11 -0
  19. package/Badge/BadgeRibbon.tsx +125 -0
  20. package/Badge/Shape.tsx +29 -0
  21. package/Badge/index.tsx +7 -0
  22. package/Badge/styles.ts +58 -0
  23. package/Badge/types.ts +63 -0
  24. package/Button/index.tsx +91 -40
  25. package/Button/styles.ts +19 -0
  26. package/CheckBox/index.tsx +58 -43
  27. package/CheckBox/styles.ts +1 -1
  28. package/CheckBox/types.ts +6 -4
  29. package/Consts/colors+spacing+radius.ts +18 -0
  30. package/Consts/styles.ts +0 -26
  31. package/Consts/theme.ts +4 -0
  32. package/Divider/index.tsx +2 -0
  33. package/Icon/index.tsx +14 -9
  34. package/Icon/types.ts +4 -3
  35. package/IconButton/index.tsx +24 -15
  36. package/Image/index.tsx +63 -47
  37. package/Image/styles.ts +1 -9
  38. package/Image/types.ts +5 -1
  39. package/Input/Input.tsx +227 -116
  40. package/Input/InputDropDown.tsx +132 -0
  41. package/Input/InputMoney.tsx +173 -111
  42. package/Input/InputOTP.tsx +257 -0
  43. package/Input/InputSearch.tsx +160 -132
  44. package/Input/InputTextArea.tsx +150 -123
  45. package/Input/common.tsx +35 -17
  46. package/Input/index.tsx +211 -18
  47. package/Input/styles.ts +44 -7
  48. package/Input/utils.ts +2 -2
  49. package/Layout/Card.tsx +67 -29
  50. package/Layout/FloatingButton.tsx +168 -0
  51. package/Layout/GridSystem.tsx +31 -21
  52. package/Layout/Item.tsx +21 -25
  53. package/Layout/ItemList.tsx +55 -0
  54. package/Layout/ItemSectionList.tsx +39 -0
  55. package/Layout/Screen.tsx +355 -153
  56. package/Layout/Section.tsx +66 -34
  57. package/Layout/index.ts +13 -3
  58. package/Layout/styles.ts +101 -0
  59. package/Layout/types.ts +1 -39
  60. package/Layout/utils.ts +27 -52
  61. package/Loader/DotLoader.tsx +37 -0
  62. package/Loader/Loader.tsx +13 -0
  63. package/Loader/ProgressBar.tsx +44 -0
  64. package/Loader/Spinner.tsx +29 -0
  65. package/Loader/index.tsx +4 -0
  66. package/Loader/styles.ts +10 -0
  67. package/Loader/types.ts +35 -0
  68. package/Loader/utils.ts +25 -0
  69. package/Pagination/PaginationDot.tsx +7 -2
  70. package/Pagination/PaginationNumber.tsx +8 -6
  71. package/Pagination/PaginationScroll.tsx +0 -1
  72. package/Pagination/PaginationWhiteDot.tsx +8 -5
  73. package/Pagination/styles.ts +3 -0
  74. package/Pagination/types.ts +2 -0
  75. package/Popup/PopupNotify.tsx +108 -46
  76. package/Popup/PopupPromotion.tsx +63 -22
  77. package/Popup/types.ts +15 -4
  78. package/Radio/index.tsx +35 -21
  79. package/Radio/types.ts +7 -5
  80. package/Skeleton/index.tsx +1 -1
  81. package/Skeleton/types.ts +3 -0
  82. package/Switch/index.tsx +35 -24
  83. package/Switch/types.ts +5 -3
  84. package/Tag/index.tsx +2 -4
  85. package/Text/index.tsx +27 -22
  86. package/Text/styles.ts +38 -0
  87. package/Text/types.ts +25 -13
  88. package/Text/utils.ts +1 -1
  89. package/Title/index.tsx +186 -0
  90. package/Title/styles.ts +79 -0
  91. package/Title/types.ts +20 -0
  92. package/code-scanner.js +143 -0
  93. package/index.ts +6 -0
  94. package/migrate_typo.js +56 -0
  95. package/package.json +14 -9
  96. package/tsconfig.json +24 -0
  97. package/verify.js +47 -0
  98. package/Application/BottomTab.tsx +0 -52
  99. package/Application/NavigationButton.tsx +0 -54
  100. package/Assets/header-background.png +0 -0
@@ -1,26 +1,26 @@
1
- import React, {useContext, useEffect, useMemo, useRef} from 'react';
1
+ import React, {useContext, useEffect, useRef} from 'react';
2
2
  import {
3
3
  KeyboardAvoidingView,
4
4
  Platform,
5
5
  Pressable,
6
6
  StyleSheet,
7
+ TouchableOpacity,
7
8
  View,
8
9
  } from 'react-native';
10
+ import {Modalize} from 'react-native-modalize';
9
11
  import {SafeAreaView, useSafeAreaInsets} from 'react-native-safe-area-context';
10
- import {BottomSheetBackdrop, BottomSheetModal} from '@gorhom/bottom-sheet';
11
- import {BottomSheetModalMethods} from '@gorhom/bottom-sheet/lib/typescript/types';
12
+
13
+ import {ApplicationContext} from './index';
14
+ import {Radius, Spacing, Styles} from '../Consts';
15
+ import {Icon} from '../Icon';
16
+ import {Text} from '../Text';
12
17
  import Navigation from './Navigation';
13
18
  import {BottomSheetParams, ModalParams} from './types';
14
- import {Radius, Spacing, Styles} from '../Consts';
15
- import {
16
- ApplicationContext,
17
- HeaderRightAction,
18
- NavigationButton,
19
- NavigationContainer,
20
- } from './index';
21
- import {HeaderBackground, HeaderLeft} from './Components';
22
19
 
23
20
  const ModalScreen: React.FC<any> = props => {
21
+ /**
22
+ * dismiss callback when modal | bottom sheet dismissed
23
+ */
24
24
  useEffect(() => {
25
25
  return () => {
26
26
  props.route.params?.onDismiss?.();
@@ -35,7 +35,7 @@ const ModalScreen: React.FC<any> = props => {
35
35
 
36
36
  const Modal: React.FC<ModalParams> = props => {
37
37
  const {theme, navigator} = useContext(ApplicationContext);
38
- const {screen, barrierDismissible}: ModalParams = props.route.params;
38
+ const {screen, barrierDismissible} = props.route.params;
39
39
  const Component = useRef(screen).current;
40
40
  const navigation = new Navigation(props.navigation, theme);
41
41
  const params = {
@@ -66,7 +66,7 @@ const Modal: React.FC<ModalParams> = props => {
66
66
  style={styles.modalSpaceVertical}
67
67
  onPress={() => onDismiss()}
68
68
  />
69
- <View style={styles.modalContent} accessibilityLabel={'Modal'}>
69
+ <View style={styles.modalContent}>
70
70
  <Component {...params} />
71
71
  </View>
72
72
  <Pressable
@@ -85,107 +85,112 @@ const Modal: React.FC<ModalParams> = props => {
85
85
 
86
86
  const BottomSheet: React.FC<BottomSheetParams> = props => {
87
87
  const {theme, navigator} = useContext(ApplicationContext);
88
- const {screen, options}: BottomSheetParams = props.route.params;
89
- const Component = useRef(screen).current;
88
+ const insets = useSafeAreaInsets();
89
+
90
+ const {
91
+ screen: Screen,
92
+ options,
93
+ footerComponent,
94
+ scrollViewProps,
95
+ surface,
96
+ }: BottomSheetParams = props.route.params;
97
+
90
98
  const navigation = new Navigation(props.navigation, theme);
99
+
91
100
  const params = {
92
101
  ...props.route.params,
93
102
  navigation,
94
103
  };
95
104
 
96
105
  delete params.screen;
97
-
98
- const snapPoints = useMemo(() => ['50%', '90%'], []);
99
- const {bottom} = useSafeAreaInsets();
100
- const bottomSheetRef = useRef<BottomSheetModalMethods>(null);
101
- const mountedRef = useRef(true);
106
+ const modalRef = useRef<Modalize>(null);
102
107
 
103
108
  useEffect(() => {
104
- bottomSheetRef.current?.present();
105
- return () => {
106
- mountedRef.current = false;
107
- };
109
+ modalRef.current?.open();
108
110
  }, []);
109
111
 
110
- const backdropComponent = (backdropProps: any) => (
111
- <BottomSheetBackdrop
112
- disappearsOnIndex={-1}
113
- appearsOnIndex={0}
114
- {...backdropProps}
115
- />
116
- );
112
+ const handleClose = () => {
113
+ modalRef?.current?.close();
114
+ };
117
115
 
118
- let backgroundColor = theme.colors.background.default;
119
- if (options?.surface) {
120
- backgroundColor = theme.colors.background.surface;
121
- }
116
+ /**
117
+ * build header
118
+ * @param title
119
+ * @param onClose
120
+ */
121
+ const headerDefault = (title: string, onClose: () => void) => {
122
+ return (
123
+ <View
124
+ style={[
125
+ styles.header,
126
+ surface && {
127
+ borderBottomColor: theme.colors.border.default,
128
+ borderBottomWidth: 1,
129
+ },
130
+ ]}>
131
+ <View style={styles.iconButton} />
132
+ <Text
133
+ style={styles.textOption}
134
+ numberOfLines={1}
135
+ typography="header_default_bold">
136
+ {title ?? ''}
137
+ </Text>
138
+ <TouchableOpacity style={styles.iconButton} onPress={onClose}>
139
+ <Icon source="navigation_close" />
140
+ </TouchableOpacity>
141
+ </View>
142
+ );
143
+ };
144
+
145
+ /**
146
+ * build footer
147
+ * @param footerComponent
148
+ */
149
+ const footerDefault = (footerComponent: React.ReactNode) => {
150
+ if (footerComponent) {
151
+ return (
152
+ <View
153
+ style={{
154
+ marginBottom: Math.min(insets.bottom, 21),
155
+ paddingHorizontal: Spacing.M,
156
+ paddingVertical: Spacing.S,
157
+ }}>
158
+ {footerComponent}
159
+ </View>
160
+ );
161
+ }
162
+ };
122
163
 
123
164
  return (
124
165
  <SafeAreaView style={Styles.flex}>
125
- <BottomSheetModal
126
- ref={bottomSheetRef}
127
- snapPoints={snapPoints}
128
- onDismiss={() => {
129
- if (mountedRef.current) {
130
- navigator?.pop();
131
- }
166
+ <Modalize
167
+ keyboardAvoidingOffset={-20}
168
+ adjustToContentHeight
169
+ closeOnOverlayTap
170
+ closeSnapPointStraightEnabled
171
+ onClosed={() => {
172
+ navigator?.pop();
132
173
  }}
133
- handleComponent={null}
134
- backdropComponent={backdropComponent}>
135
- <View
136
- style={{paddingBottom: bottom}}
137
- accessibilityLabel={'BottomSheet'}>
138
- <View style={[styles.sheetContainer, {backgroundColor}]}>
139
- <View style={styles.indicatorContainer}>
140
- <View
141
- style={[
142
- styles.indicator,
143
- {backgroundColor: theme.colors.text.disable},
144
- ]}
145
- />
146
- </View>
147
- <NavigationContainer
148
- theme={{
149
- ...theme,
150
- assets: {...theme.assets, headerBackground: undefined},
151
- }}
152
- screen={props => <Component {...props} {...params} />}
153
- options={{
154
- ...options,
155
- ...{
156
- headerLeft: (props: any) => {
157
- if (props.canGoBack) {
158
- return (
159
- <HeaderLeft
160
- {...props}
161
- useBorder={false}
162
- backgroundColor="transparent"
163
- />
164
- );
165
- }
166
- },
167
- headerBackground: () => (
168
- <HeaderBackground backgroundColor={backgroundColor} />
169
- ),
170
- headerTransparent: false,
171
- },
172
- headerTitleAlign: 'center',
173
- headerRight: props => (
174
- <HeaderRightAction>
175
- <NavigationButton
176
- {...props}
177
- icon="24_navigation_close"
178
- backgroundColor="transparent"
179
- useBorder={false}
180
- onPress={bottomSheetRef.current?.dismiss}
181
- />
182
- </HeaderRightAction>
183
- ),
184
- }}
185
- />
186
- </View>
174
+ handlePosition="inside"
175
+ withHandle={true}
176
+ disableScrollIfPossible={true}
177
+ modalTopOffset={insets.top}
178
+ ref={modalRef}
179
+ scrollViewProps={scrollViewProps}
180
+ HeaderComponent={headerDefault(
181
+ options?.title ?? options?.customTitle?.title ?? '',
182
+ handleClose,
183
+ )}
184
+ modalStyle={{
185
+ backgroundColor: surface
186
+ ? theme.colors.background.surface
187
+ : theme.colors.background.default,
188
+ }}
189
+ FooterComponent={footerDefault(footerComponent)}>
190
+ <View style={styles.bottomSheetContainer}>
191
+ <Screen {...props} {...params} />
187
192
  </View>
188
- </BottomSheetModal>
193
+ </Modalize>
189
194
  </SafeAreaView>
190
195
  );
191
196
  };
@@ -217,14 +222,46 @@ const styles = StyleSheet.create({
217
222
  indicatorContainer: {
218
223
  width: '100%',
219
224
  paddingTop: Spacing.S,
225
+ paddingBottom: Spacing.XS,
220
226
  alignItems: 'center',
221
227
  justifyContent: 'center',
222
228
  },
223
229
  indicator: {
224
- width: 64,
230
+ width: 40,
225
231
  height: 4,
226
232
  borderRadius: Radius.S,
227
233
  },
234
+ bottomSheetContainer: {
235
+ width: '100%',
236
+ },
237
+ header: {
238
+ marginTop: 10,
239
+ height: 56,
240
+ width: '100%',
241
+ alignItems: 'center',
242
+ flexDirection: 'row',
243
+ },
244
+ textOption: {
245
+ fontSize: 16,
246
+ color: '#303233',
247
+ textAlign: 'center',
248
+ fontWeight: 'bold',
249
+ paddingHorizontal: Spacing.L,
250
+ flex: 1,
251
+ },
252
+ iconButton: {
253
+ width: 24,
254
+ height: 24,
255
+ alignItems: 'center',
256
+ justifyContent: 'center',
257
+ marginHorizontal: Spacing.M,
258
+ },
259
+ icon: {
260
+ width: 24,
261
+ height: 24,
262
+ tintColor: '#303233',
263
+ backgroundColor: 'red',
264
+ },
228
265
  });
229
266
 
230
267
  export default ModalScreen;
@@ -1,3 +1,4 @@
1
+ import React from 'react';
1
2
  import {NavigationProp} from '@react-navigation/native';
2
3
  import {NavigationOptions, Theme} from './types';
3
4
  import {HeaderRightAction} from './index';
@@ -5,38 +6,43 @@ import {getOptions} from './utils';
5
6
  import {HeaderToolkitAction} from './Components';
6
7
 
7
8
  class Navigation {
8
- private instance: NavigationProp<any>;
9
- private readonly theme: Theme;
9
+ instance: NavigationProp<any>;
10
+ readonly theme: Theme;
10
11
 
11
12
  constructor(instance: any, theme: Theme) {
12
13
  this.instance = instance;
13
14
  this.theme = theme;
14
15
  }
15
16
 
16
- private verifyParams = (params: NavigationOptions) => {
17
+ /**
18
+ * navigation options filter by design system rule
19
+ * @param params
20
+ */
21
+ private filterParams = (params: NavigationOptions) => {
17
22
  if (params.headerRight) {
18
- const headerRight = params.headerRight?.();
19
- if (
20
- headerRight?.type !== HeaderRightAction &&
21
- headerRight?.type !== HeaderToolkitAction
22
- ) {
23
+ const headerRight = params.headerRight?.({}) as React.ReactElement;
24
+ const type = headerRight?.type;
25
+ if (type !== HeaderRightAction && type !== HeaderToolkitAction) {
23
26
  console.warn(
24
- 'headerRight not return element type of HeaderRightAction | HeaderToolkitAction, Please migrate to use of kits.',
27
+ 'headerRight contains element type of HeaderRightAction | HeaderToolkitAction, Please check again.',
25
28
  );
26
29
  }
27
30
  }
28
- return params;
29
- };
30
31
 
31
- private filterParams = (params: NavigationOptions) => {
32
+ if (params.headerLeft) {
33
+ console.warn('headerLeft not allow override render by design system!');
34
+ delete params.headerLeft;
35
+ }
36
+
32
37
  return params;
33
38
  };
34
39
 
40
+ /**
41
+ * navigation setOptions support props NavigationOptions base on react-navigation options
42
+ * @param params
43
+ */
35
44
  setOptions = (params: NavigationOptions) => {
36
- if (__DEV__) {
37
- params = this.filterParams(params);
38
- }
39
- params = getOptions(params, this.theme);
45
+ params = getOptions(this.filterParams(params), this.theme);
40
46
  this.instance.setOptions(params);
41
47
  };
42
48
  }
@@ -1,19 +1,25 @@
1
- import React, {useRef} from 'react';
2
- import {BottomSheetModalProvider} from '@gorhom/bottom-sheet';
1
+ import React, {useEffect, useRef, useState} from 'react';
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
+ import {DeviceEventEmitter} from 'react-native';
9
10
  import StackScreen from './StackScreen';
10
11
  import ModalScreen from './ModalScreen';
11
12
  import Navigator from './Navigator';
12
13
  import {getDialogOptions, getModalOptions, getStackOptions} from './utils';
13
- import {GridSystem} from '../Layout';
14
- import {GRIDVIEW} from '../Consts';
15
- import {NavigationContainerProps} from './types';
14
+ import {LocalizationObject, NavigationContainerProps} from './types';
16
15
  import {ApplicationContext} from './index';
16
+ import kitLocalization from '../Assets/language.json';
17
+
18
+ /**
19
+ * link for deprecated
20
+ */
21
+
22
+ console.log(typeof BottomSheetModalProvider);
17
23
 
18
24
  const Stack = createStackNavigator();
19
25
 
@@ -22,54 +28,99 @@ const NavigationContainer: React.FC<NavigationContainerProps> = ({
22
28
  theme,
23
29
  options,
24
30
  maxApi,
31
+ localization,
32
+ initialParams,
25
33
  }) => {
26
- const navigationRef = React.useRef<NavigationContainerRef>(null);
27
- const navigator = useRef(new Navigator(navigationRef));
34
+ const navigationRef = useRef<NavigationContainerRef>(null);
35
+ const isReady = useRef(false);
36
+ const navigator = useRef(new Navigator(navigationRef, isReady));
37
+ const [showGrid, setShowGrid] = useState(false);
38
+ const config = useRef<any>();
39
+
40
+ /**
41
+ * handle mini language & listen change
42
+ * engine only shake to enable grid view
43
+ */
44
+ useEffect(() => {
45
+ const subscription = DeviceEventEmitter.addListener(
46
+ 'onChangeGrid',
47
+ enable => {
48
+ setShowGrid(!!enable);
49
+ },
50
+ );
51
+
52
+ return () => {
53
+ subscription?.remove?.();
54
+ };
55
+ }, []);
56
+
57
+ /**
58
+ * inject data for navigator
59
+ */
28
60
  navigator.current.maxApi = maxApi;
29
61
 
62
+ /**
63
+ * translate
64
+ * @param key
65
+ */
66
+ const translate = (key: string) => {
67
+ const language: 'vi' | 'en' = 'vi';
68
+ const mergedLocalization: LocalizationObject = {
69
+ vi: {...localization?.vi, ...kitLocalization.vi},
70
+ en: {...localization?.en, ...kitLocalization.en},
71
+ };
72
+ return mergedLocalization?.[language]?.[key] || key;
73
+ };
74
+
30
75
  return (
31
76
  <SafeAreaProvider>
32
- <BottomSheetModalProvider>
33
- <ApplicationContext.Provider
34
- value={{theme, navigator: navigator.current}}>
35
- <ReactNavigationContainer
36
- theme={{
37
- ...theme,
38
- colors: {
39
- ...theme.colors,
40
- background: theme.colors.background.default,
41
- card: theme.colors.background.surface,
42
- text: theme.colors.text.default,
43
- border: theme.colors.border.default,
44
- notification: theme.colors.error.primary,
45
- },
46
- }}
47
- ref={navigator.current?.ref}
48
- independent={true}>
49
- <Stack.Navigator initialRouteName="Stack" headerMode="screen">
50
- <Stack.Screen
51
- name="Stack"
52
- component={StackScreen}
53
- initialParams={{screen}}
54
- options={{...getStackOptions(theme), ...options}}
55
- />
56
- <Stack.Screen
57
- name="Dialog"
58
- component={StackScreen}
59
- options={getDialogOptions(theme)}
60
- initialParams={{screen}}
61
- />
62
- <Stack.Screen
63
- name="Modal"
64
- component={ModalScreen}
65
- options={getModalOptions()}
66
- initialParams={{screen}}
67
- />
68
- </Stack.Navigator>
69
- </ReactNavigationContainer>
70
- </ApplicationContext.Provider>
71
- </BottomSheetModalProvider>
72
- {GRIDVIEW && <GridSystem />}
77
+ <ApplicationContext.Provider
78
+ value={{
79
+ navigator: navigator.current,
80
+ config: config.current,
81
+ theme,
82
+ showGrid,
83
+ translate,
84
+ }}>
85
+ <ReactNavigationContainer
86
+ theme={{
87
+ ...theme,
88
+ colors: {
89
+ ...theme.colors,
90
+ background: theme.colors.background.default,
91
+ card: theme.colors.background.surface,
92
+ text: theme.colors.text.default,
93
+ border: theme.colors.border.default,
94
+ notification: theme.colors.error.primary,
95
+ },
96
+ }}
97
+ ref={navigator.current?.ref}
98
+ onReady={() => {
99
+ isReady.current = true;
100
+ }}
101
+ independent={true}>
102
+ <Stack.Navigator initialRouteName="Stack" headerMode="screen">
103
+ <Stack.Screen
104
+ name="Stack"
105
+ component={StackScreen}
106
+ initialParams={{screen, initialParams}}
107
+ options={{...getStackOptions(), ...options}}
108
+ />
109
+ <Stack.Screen
110
+ name="Dialog"
111
+ component={StackScreen}
112
+ options={getDialogOptions()}
113
+ initialParams={{screen}}
114
+ />
115
+ <Stack.Screen
116
+ name="Modal"
117
+ component={ModalScreen}
118
+ options={getModalOptions()}
119
+ initialParams={{screen}}
120
+ />
121
+ </Stack.Navigator>
122
+ </ReactNavigationContainer>
123
+ </ApplicationContext.Provider>
73
124
  </SafeAreaProvider>
74
125
  );
75
126
  };