@momo-kits/foundation 0.76.1-beta.2 → 0.77.1-optimize.2

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 +478 -0
  2. package/Application/BottomTab/index.tsx +134 -0
  3. package/Application/Components.tsx +339 -161
  4. package/Application/ModalScreen.tsx +113 -99
  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 +126 -8
  9. package/Application/index.ts +23 -4
  10. package/Application/types.ts +84 -33
  11. package/Application/utils.tsx +90 -50
  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 +90 -39
  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 +13 -9
  34. package/Icon/types.ts +4 -3
  35. package/IconButton/index.tsx +24 -15
  36. package/Image/index.tsx +60 -48
  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 +174 -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 +42 -17
  46. package/Input/index.tsx +204 -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 +128 -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 +348 -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 +102 -44
  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 +8 -1
  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,111 +85,87 @@ 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 {
89
+ screen: Screen,
90
+ options,
91
+ footerComponent,
92
+ flatListProps,
93
+ }: BottomSheetParams = props.route.params;
94
+
90
95
  const navigation = new Navigation(props.navigation, theme);
96
+
91
97
  const params = {
92
98
  ...props.route.params,
93
99
  navigation,
94
100
  };
95
101
 
96
102
  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);
103
+ const modalizeRef = useRef<Modalize>(null);
102
104
 
103
105
  useEffect(() => {
104
- bottomSheetRef.current?.present();
105
- return () => {
106
- mountedRef.current = false;
107
- };
106
+ modalizeRef.current?.open();
108
107
  }, []);
109
108
 
110
- const backdropComponent = (backdropProps: any) => (
111
- <BottomSheetBackdrop
112
- disappearsOnIndex={-1}
113
- appearsOnIndex={0}
114
- {...backdropProps}
115
- />
116
- );
117
-
118
- let backgroundColor = theme.colors.background.default;
119
- if (options?.surface) {
120
- backgroundColor = theme.colors.background.surface;
121
- }
109
+ const handleClose = () => {
110
+ modalizeRef?.current?.close();
111
+ };
122
112
 
123
113
  return (
124
114
  <SafeAreaView style={Styles.flex}>
125
- <BottomSheetModal
126
- ref={bottomSheetRef}
127
- snapPoints={snapPoints}
128
- onDismiss={() => {
129
- if (mountedRef.current) {
130
- navigator?.pop();
131
- }
115
+ <Modalize
116
+ keyboardAvoidingOffset={-20}
117
+ adjustToContentHeight
118
+ closeOnOverlayTap
119
+ closeSnapPointStraightEnabled
120
+ onClosed={() => {
121
+ navigator?.pop();
132
122
  }}
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>
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} />
187
133
  </View>
188
- </BottomSheetModal>
134
+ </Modalize>
189
135
  </SafeAreaView>
190
136
  );
191
137
  };
192
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
+
193
169
  const styles = StyleSheet.create({
194
170
  container: {flex: 1, flexDirection: 'row'},
195
171
  modalContent: {
@@ -217,14 +193,52 @@ const styles = StyleSheet.create({
217
193
  indicatorContainer: {
218
194
  width: '100%',
219
195
  paddingTop: Spacing.S,
196
+ paddingBottom: Spacing.XS,
220
197
  alignItems: 'center',
221
198
  justifyContent: 'center',
222
199
  },
223
200
  indicator: {
224
- width: 64,
201
+ width: 40,
225
202
  height: 4,
226
203
  borderRadius: Radius.S,
227
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
+ },
228
242
  });
229
243
 
230
244
  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
  };