@momo-kits/foundation 1.0.1 → 1.0.4

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 (50) hide show
  1. package/Button/index.tsx +39 -23
  2. package/CheckBox/index.tsx +11 -7
  3. package/CheckBox/types.ts +6 -3
  4. package/Consts/theme.ts +57 -1
  5. package/ContentLoader/index.tsx +2 -3
  6. package/Icon/icon.json +3 -0
  7. package/Icon/index.tsx +9 -4
  8. package/Icon/types.ts +4 -1
  9. package/IconButton/index.tsx +24 -4
  10. package/Image/index.tsx +11 -12
  11. package/Image/types.ts +1 -3
  12. package/Input/Input.tsx +160 -0
  13. package/Input/TextArea.tsx +26 -65
  14. package/Input/common.tsx +70 -0
  15. package/Input/index.tsx +23 -197
  16. package/Input/styles.ts +1 -5
  17. package/Layout/GridSystem.tsx +1 -1
  18. package/Layout/ScreenContainer.tsx +5 -19
  19. package/Layout/ScreenSection.tsx +13 -0
  20. package/Layout/SectionItem.tsx +3 -0
  21. package/Layout/utils.ts +14 -0
  22. package/Navigation/Components.tsx +60 -12
  23. package/Navigation/ModalScreen.tsx +56 -43
  24. package/Navigation/Navigation.ts +8 -4
  25. package/Navigation/NavigationButton.tsx +5 -2
  26. package/Navigation/NavigationContainer.tsx +25 -58
  27. package/Navigation/StackScreen.tsx +12 -7
  28. package/Navigation/types.ts +20 -7
  29. package/Navigation/utils.tsx +77 -21
  30. package/Playground/index.tsx +249 -0
  31. package/Playground/styles.ts +16 -0
  32. package/Playground/types.ts +16 -0
  33. package/Popup/PopupNotify.tsx +210 -0
  34. package/Popup/PopupPromotion.tsx +62 -0
  35. package/Popup/index.tsx +4 -0
  36. package/Popup/types.ts +22 -0
  37. package/Radio/index.tsx +25 -9
  38. package/Radio/types.ts +5 -2
  39. package/Switch/index.tsx +8 -6
  40. package/Switch/types.ts +6 -3
  41. package/Text/index.tsx +9 -7
  42. package/Text/styles.ts +3 -3
  43. package/Text/types.ts +5 -14
  44. package/index.ts +6 -6
  45. package/package.json +4 -5
  46. package/publish.sh +6 -8
  47. package/ActivityIndicator.tsx +0 -244
  48. package/Button/types.ts +0 -27
  49. package/IconButton/types.ts +0 -16
  50. package/Input/types.ts +0 -23
@@ -12,16 +12,26 @@ import {BottomSheetModalMethods} from '@gorhom/bottom-sheet/lib/typescript/types
12
12
  import Navigation from './Navigation';
13
13
  import {ModalParams} from './types';
14
14
  import {Radius, Spacing, Styles} from '../Consts';
15
- import {ApplicationContext, NavigationContainer} from './index';
15
+ import {
16
+ ApplicationContext,
17
+ HeaderRightAction,
18
+ NavigationButton,
19
+ NavigationContainer,
20
+ } from './index';
16
21
 
17
- const ModalScreen: React.FC<any> = props => {
18
- const {navigation, route} = props;
22
+ const ModalScreen: React.FC<ModalParams> = ({navigation, route, ...rest}) => {
19
23
  const {theme} = useContext(ApplicationContext);
20
- const {isBottomSheet, screen, onRequestClose}: ModalParams = route.params;
24
+ const {
25
+ isBottomSheet,
26
+ backgroundColor,
27
+ screen,
28
+ barrierDismissible,
29
+ options,
30
+ }: ModalParams = route.params;
21
31
  const Component = useRef(screen).current;
22
32
  const params = {
23
33
  ...route.params,
24
- navigation: new Navigation(navigation),
34
+ navigation: new Navigation(navigation, theme),
25
35
  };
26
36
  delete params.screen;
27
37
 
@@ -33,11 +43,7 @@ const ModalScreen: React.FC<any> = props => {
33
43
  if (!pop) {
34
44
  action = () => {};
35
45
  }
36
- if (typeof onRequestClose === 'function' && !isBottomSheet) {
37
- onRequestClose(() => {
38
- params?.onDismiss?.();
39
- action();
40
- });
46
+ if (barrierDismissible && !isBottomSheet) {
41
47
  return;
42
48
  }
43
49
  params?.onDismiss?.();
@@ -48,16 +54,36 @@ const ModalScreen: React.FC<any> = props => {
48
54
  * build bottom sheet
49
55
  */
50
56
  if (isBottomSheet) {
57
+ const bgColor = backgroundColor ?? theme.colors.background.surface;
58
+ const sheetTheme = {...theme, assets: undefined};
51
59
  return (
52
- <BottomSheet {...props} onDismiss={onDismiss}>
53
- <View style={{height: '100%'}}>
60
+ <BottomSheet {...rest} onDismiss={onDismiss}>
61
+ <View style={[styles.sheetContainer, {backgroundColor: bgColor}]}>
62
+ <View style={styles.indicatorContainer}>
63
+ <View
64
+ style={[
65
+ styles.indicator,
66
+ {backgroundColor: theme.colors.text.disable},
67
+ ]}
68
+ />
69
+ </View>
54
70
  <NavigationContainer
55
- theme={{...theme, assets: undefined}}
56
- screen={props => <Component {...params} {...props} />}
57
- onDismiss={() => {
58
- navigation.pop();
71
+ theme={sheetTheme}
72
+ screen={props => <Component {...props} {...params} />}
73
+ options={{
74
+ ...options,
75
+ hiddenBack: true,
76
+ headerTitleAlign: 'center',
77
+ headerRight: (props: any) => (
78
+ <HeaderRightAction>
79
+ <NavigationButton
80
+ icon="24_navigation_close"
81
+ {...props}
82
+ onPress={() => navigation.pop()}
83
+ />
84
+ </HeaderRightAction>
85
+ ),
59
86
  }}
60
- isBottomSheet={isBottomSheet}
61
87
  />
62
88
  </View>
63
89
  </BottomSheet>
@@ -96,7 +122,6 @@ const ModalScreen: React.FC<any> = props => {
96
122
  };
97
123
 
98
124
  const BottomSheet: React.FC<ModalParams> = ({children, onDismiss}) => {
99
- const {theme} = useContext(ApplicationContext);
100
125
  const snapPoints = useMemo(() => ['50%', '90%'], []);
101
126
  const {bottom} = useSafeAreaInsets();
102
127
  const bottomSheetRef = useRef<BottomSheetModalMethods>(null);
@@ -109,17 +134,6 @@ const BottomSheet: React.FC<ModalParams> = ({children, onDismiss}) => {
109
134
  };
110
135
  }, []);
111
136
 
112
- const handleComponent = () => (
113
- <View
114
- style={[
115
- styles.indicatorContainer,
116
- {backgroundColor: theme.colors.background.surface},
117
- ]}>
118
- <View
119
- style={[styles.indicator, {backgroundColor: theme.colors.text.disable}]}
120
- />
121
- </View>
122
- );
123
137
  const backdropComponent = (backdropProps: any) => (
124
138
  <BottomSheetBackdrop
125
139
  disappearsOnIndex={-1}
@@ -133,27 +147,22 @@ const BottomSheet: React.FC<ModalParams> = ({children, onDismiss}) => {
133
147
  <BottomSheetModal
134
148
  ref={bottomSheetRef}
135
149
  snapPoints={snapPoints}
136
- handleHeight={24}
137
150
  onDismiss={() => onDismiss?.(mountedRef.current)}
138
- handleComponent={handleComponent}
151
+ handleComponent={null}
139
152
  backdropComponent={backdropComponent}>
140
- <View
141
- style={{
142
- paddingBottom: bottom,
143
- backgroundColor: theme.colors.background.default,
144
- }}>
145
- {children}
146
- </View>
153
+ <View style={{paddingBottom: bottom}}>{children}</View>
147
154
  </BottomSheetModal>
148
155
  </SafeAreaView>
149
156
  );
150
157
  };
151
158
 
159
+ ModalScreen.defaultProps = {
160
+ barrierDismissible: false,
161
+ };
162
+
152
163
  const styles = StyleSheet.create({
153
164
  container: {flex: 1, flexDirection: 'row'},
154
165
  modalContent: {
155
- borderRadius: Radius.M,
156
- overflow: 'hidden',
157
166
  maxWidth: '100%',
158
167
  maxHeight: '80%',
159
168
  },
@@ -168,14 +177,18 @@ const styles = StyleSheet.create({
168
177
  flex: 1,
169
178
  minHeight: '10%',
170
179
  },
171
- indicatorContainer: {
180
+ sheetContainer: {
181
+ height: '100%',
172
182
  width: '100%',
173
- paddingTop: Spacing.S,
174
183
  borderTopLeftRadius: Radius.M,
175
184
  borderTopRightRadius: Radius.M,
176
185
  overflow: 'hidden',
177
- justifyContent: 'center',
186
+ },
187
+ indicatorContainer: {
188
+ width: '100%',
189
+ paddingTop: Spacing.S,
178
190
  alignItems: 'center',
191
+ justifyContent: 'center',
179
192
  },
180
193
  indicator: {
181
194
  width: 64,
@@ -1,12 +1,15 @@
1
1
  import {NavigationProp} from '@react-navigation/native';
2
- import {NavigationOptions} from './types';
2
+ import {NavigationOptions, Theme} from './types';
3
3
  import {HeaderRightAction} from './index';
4
+ import {getOptions} from './utils';
4
5
 
5
6
  class Navigation {
6
7
  instance: NavigationProp<any>;
8
+ theme: Theme;
7
9
 
8
- constructor(instance: any) {
10
+ constructor(instance: any, theme: Theme) {
9
11
  this.instance = instance;
12
+ this.theme = theme;
10
13
  }
11
14
 
12
15
  verifyParams = (params: NavigationOptions) => {
@@ -18,6 +21,7 @@ class Navigation {
18
21
  );
19
22
  }
20
23
  }
24
+ return params;
21
25
  };
22
26
 
23
27
  filterParams = (params: NavigationOptions) => {
@@ -25,8 +29,8 @@ class Navigation {
25
29
  };
26
30
 
27
31
  setOptions = (params: NavigationOptions) => {
28
- this.verifyParams(params);
29
- params = this.filterParams(params);
32
+ params = this.verifyParams(params);
33
+ params = getOptions(params, this.theme);
30
34
  this.instance.setOptions(params);
31
35
  };
32
36
  }
@@ -4,8 +4,11 @@ import {NavigationButtonProps} from './types';
4
4
  import {ApplicationContext} from './index';
5
5
  import {Icon} from '../Icon';
6
6
 
7
- const NavigationButton: React.FC<NavigationButtonProps> = props => {
8
- const {icon, tintColor, onPress} = props;
7
+ const NavigationButton: React.FC<NavigationButtonProps> = ({
8
+ icon,
9
+ tintColor,
10
+ onPress,
11
+ }) => {
9
12
  const {theme} = useContext(ApplicationContext);
10
13
  return (
11
14
  <TouchableOpacity style={styles.container} onPress={onPress}>
@@ -1,22 +1,18 @@
1
- import React, {createContext, useRef} from 'react';
1
+ import React, {createContext, useEffect, useRef} from 'react';
2
2
  import {BottomSheetModalProvider} from '@gorhom/bottom-sheet';
3
3
  import {SafeAreaProvider} from 'react-native-safe-area-context';
4
4
  import {
5
5
  NavigationContainer as ReactNavigationContainer,
6
6
  NavigationContainerRef,
7
7
  } from '@react-navigation/native';
8
- import {
9
- createStackNavigator,
10
- StackNavigationOptions,
11
- } from '@react-navigation/stack';
8
+ import {createStackNavigator} from '@react-navigation/stack';
12
9
  import StackScreen from './StackScreen';
13
10
  import ModalScreen from './ModalScreen';
14
11
  import Navigator from './Navigator';
15
12
  import {getDialogOptions, getModalOptions, getStackOptions} from './utils';
16
13
  import {GridSystem, useGridSystem} from '../Layout';
17
- import {defaultContext, defaultTheme} from '../Consts';
14
+ import {defaultContext} from '../Consts';
18
15
  import {NavigationContainerProps} from './types';
19
- import {HeaderRightAction, NavigationButton} from './index';
20
16
 
21
17
  const Stack = createStackNavigator();
22
18
 
@@ -24,35 +20,17 @@ const ApplicationContext = createContext(defaultContext);
24
20
  const NavigationContainer: React.FC<NavigationContainerProps> = ({
25
21
  screen,
26
22
  theme,
27
- onDismiss,
28
- isBottomSheet,
23
+ options,
29
24
  }) => {
30
25
  const grid = useGridSystem();
31
26
  const navigationRef = React.useRef<NavigationContainerRef>(null);
32
27
  const navigator = useRef(new Navigator(navigationRef));
33
- const themed: any = theme;
34
- let options: StackNavigationOptions = {};
35
- if (isBottomSheet) {
36
- options = {
37
- headerRight: (props: any) => (
38
- <HeaderRightAction {...props}>
39
- <NavigationButton
40
- icon="24_navigation_close"
41
- {...props}
42
- onPress={onDismiss}
43
- />
44
- </HeaderRightAction>
45
- ),
46
- };
47
- }
48
- const goBack = () => {
49
- const canGoBack = navigationRef?.current?.canGoBack();
50
- if (canGoBack) {
51
- navigationRef?.current?.goBack();
52
- } else {
53
- onDismiss?.();
28
+
29
+ useEffect(() => {
30
+ if (options) {
31
+ navigationRef.current?.setParams({options: options});
54
32
  }
55
- };
33
+ }, []);
56
34
 
57
35
  return (
58
36
  <SafeAreaProvider>
@@ -60,38 +38,32 @@ const NavigationContainer: React.FC<NavigationContainerProps> = ({
60
38
  <ApplicationContext.Provider
61
39
  value={{theme, navigator: navigator.current}}>
62
40
  <ReactNavigationContainer
63
- theme={themed}
41
+ theme={{
42
+ ...theme,
43
+ dark: false,
44
+ colors: {
45
+ ...theme.colors,
46
+ background: theme.colors.background.default,
47
+ card: theme.colors.background.surface,
48
+ text: theme.colors.text.default,
49
+ border: theme.colors.border.default,
50
+ notification: theme.colors.error.primary,
51
+ },
52
+ }}
64
53
  ref={navigator.current?.ref}
65
54
  independent={true}>
66
55
  <Stack.Navigator initialRouteName="Stack" headerMode="screen">
67
56
  <Stack.Screen
68
57
  name="Stack"
69
58
  component={StackScreen}
70
- initialParams={{screen, isBottomSheet}}
71
- options={getStackOptions(theme, {
72
- headerLeft: (props: any) => (
73
- <NavigationButton
74
- icon="ic_back"
75
- {...props}
76
- onPress={goBack}
77
- />
78
- ),
79
- ...options,
80
- })}
59
+ initialParams={{screen}}
60
+ options={getStackOptions(theme)}
81
61
  />
82
62
  <Stack.Screen
83
63
  name="Dialog"
84
64
  component={StackScreen}
85
- options={getDialogOptions(theme, {
86
- headerLeft: props => (
87
- <NavigationButton
88
- icon="ic_back"
89
- {...props}
90
- onPress={goBack}
91
- />
92
- ),
93
- })}
94
- initialParams={{screen, isBottomSheet}}
65
+ options={getDialogOptions(theme)}
66
+ initialParams={{screen}}
95
67
  />
96
68
  <Stack.Screen
97
69
  name="Modal"
@@ -108,9 +80,4 @@ const NavigationContainer: React.FC<NavigationContainerProps> = ({
108
80
  );
109
81
  };
110
82
 
111
- NavigationContainer.defaultProps = {
112
- theme: defaultTheme,
113
- isBottomSheet: false,
114
- };
115
-
116
83
  export {ApplicationContext, NavigationContainer};
@@ -1,23 +1,28 @@
1
- import React, {useLayoutEffect} from 'react';
1
+ import React, {useContext, useEffect} from 'react';
2
2
  import {ScreenParams} from './types';
3
3
  import Navigation from './Navigation';
4
+ import {ApplicationContext} from './NavigationContainer';
4
5
 
5
6
  const StackScreen: React.FC<any> = props => {
6
7
  const {route, navigation} = props;
7
- const {screen: Component, isBottomSheet}: ScreenParams = route.params;
8
+ const {screen: Component, options}: ScreenParams = route.params;
9
+ const {theme} = useContext(ApplicationContext);
8
10
 
9
11
  const params = {
10
12
  ...route.params,
11
- navigation: new Navigation(navigation),
13
+ navigation: new Navigation(navigation, theme),
12
14
  };
13
15
 
14
16
  delete params.screen;
15
17
 
16
- useLayoutEffect(() => {
17
- if (isBottomSheet && !navigation?.canGoBack()) {
18
- navigation?.setOptions({headerLeft: null});
18
+ /**
19
+ * handle set options for navigation if have props options
20
+ */
21
+ useEffect(() => {
22
+ if (options) {
23
+ params.navigation.setOptions(options);
19
24
  }
20
- }, []);
25
+ }, [navigation, options]);
21
26
 
22
27
  return <Component {...params} />;
23
28
  };
@@ -1,7 +1,6 @@
1
1
  import {ViewProps} from 'react-native';
2
2
  import React from 'react';
3
3
  import Navigator from './Navigator';
4
- import Navigation from './Navigation';
5
4
 
6
5
  export type Theme = {
7
6
  dark: boolean;
@@ -65,14 +64,11 @@ export type Context = {
65
64
 
66
65
  export type NavigationContainerProps = {
67
66
  screen: React.ElementType;
68
- isBottomSheet?: boolean;
67
+ options?: NavigationOptions;
69
68
  theme: Theme;
70
- onDismiss?: () => void;
71
69
  };
72
70
 
73
71
  export interface ScreenContainerProps extends ViewProps {
74
- navigation: Navigation;
75
- options?: NavigationOptions;
76
72
  edges?: any[];
77
73
  enableKeyboardAvoidingView?: boolean;
78
74
  scrollable: boolean;
@@ -88,7 +84,8 @@ export interface ModalParams extends ScreenParams {
88
84
  [key: string]: any;
89
85
  screen: React.ElementType;
90
86
  onDismiss?: (mounted?: boolean) => void;
91
- onRequestClose?: (onClose: () => void) => void;
87
+ barrierDismissible?: boolean;
88
+ backgroundColor?: string;
92
89
  }
93
90
 
94
91
  export type NavigationButtonProps = {
@@ -98,7 +95,23 @@ export type NavigationButtonProps = {
98
95
  };
99
96
 
100
97
  export type NavigationOptions = {
98
+ surface?: boolean;
99
+ hiddenBack?: boolean;
101
100
  title?: string;
102
- headerBackground?: string;
101
+ headerTitleAlign?: 'left' | 'center';
102
+ customTitle?: TitleCustomProps;
103
103
  headerRight?: (props?: any) => React.ReactElement;
104
104
  };
105
+
106
+ export type HeaderBackgroundProps = {
107
+ image?: string;
108
+ };
109
+
110
+ export type TitleCustomProps = {
111
+ title?: string;
112
+ subTitle?: string;
113
+ image?: string;
114
+ dotColor?: string;
115
+ tintColor?: string;
116
+ content?: React.ReactNode;
117
+ };
@@ -1,25 +1,36 @@
1
- import React from 'react';
1
+ import React, {useContext} from 'react';
2
2
  import {
3
3
  StackNavigationOptions,
4
4
  TransitionPresets,
5
5
  } from '@react-navigation/stack';
6
- import {HeaderBackground} from './Components';
7
- import {Theme} from './types';
6
+ import {HeaderBackground, HeaderCustom} from './Components';
7
+ import {NavigationOptions, Theme} from './types';
8
8
  import {Colors} from '../Consts';
9
- import {NavigationButton} from './index';
10
9
  import {Text} from '../Text';
10
+ import {ApplicationContext, NavigationButton} from './index';
11
11
 
12
- const renderTitle = (props: any) => {
12
+ const HeaderTitle = (props: any) => {
13
13
  return (
14
14
  <Text
15
15
  {...props}
16
- typography="headerText_default"
16
+ typography="header_default"
17
17
  weight="bold"
18
18
  color={props.tintColor}
19
19
  />
20
20
  );
21
21
  };
22
22
 
23
+ const HeaderLeft = (props: any) => {
24
+ const {navigator} = useContext(ApplicationContext);
25
+ const goBack = () => {
26
+ const canGoBack = navigator?.ref.current?.canGoBack();
27
+ if (canGoBack) {
28
+ navigator?.ref.current?.goBack();
29
+ }
30
+ };
31
+ return <NavigationButton icon="ic_back" {...props} onPress={goBack} />;
32
+ };
33
+
23
34
  const getTintColor = (theme: Theme): any => {
24
35
  if (theme.assets?.headerBackground) {
25
36
  return {
@@ -31,30 +42,28 @@ const getTintColor = (theme: Theme): any => {
31
42
  };
32
43
  };
33
44
 
34
- const getStackOptions = (
35
- theme: Theme,
36
- options: StackNavigationOptions,
37
- ): StackNavigationOptions => {
45
+ const getStackOptions = (theme: Theme): StackNavigationOptions => {
38
46
  return {
39
47
  headerTitleAlign: 'center',
40
- headerTitle: renderTitle,
41
- headerBackground: HeaderBackground,
48
+ headerTitle: HeaderTitle,
49
+ headerBackground: () => (
50
+ <HeaderBackground image={theme.assets?.headerBackground} />
51
+ ),
52
+ headerLeft: (props: any) => <HeaderLeft {...props} />,
42
53
  ...getTintColor(theme),
43
- ...options,
44
54
  };
45
55
  };
46
56
 
47
- const getDialogOptions = (
48
- theme: Theme,
49
- options: StackNavigationOptions,
50
- ): StackNavigationOptions => {
57
+ const getDialogOptions = (theme: Theme): StackNavigationOptions => {
51
58
  return {
52
59
  headerTitleAlign: 'center',
53
- headerTitle: renderTitle,
54
- headerBackground: HeaderBackground,
60
+ headerTitle: HeaderTitle,
61
+ headerLeft: (props: any) => <HeaderLeft {...props} />,
62
+ headerBackground: () => (
63
+ <HeaderBackground image={theme.assets?.headerBackground} />
64
+ ),
55
65
  ...getTintColor(theme),
56
66
  ...TransitionPresets.ModalTransition,
57
- ...options,
58
67
  };
59
68
  };
60
69
 
@@ -83,4 +92,51 @@ const getModalOptions = (): StackNavigationOptions => {
83
92
  };
84
93
  };
85
94
 
86
- export {getStackOptions, getDialogOptions, getModalOptions};
95
+ const getOptions = (params: NavigationOptions, theme: Theme) => {
96
+ let backTheme = {};
97
+ let surfaceTheme = {};
98
+ let titleTheme = {};
99
+
100
+ if (params.hiddenBack == true) {
101
+ backTheme = {
102
+ headerLeft: null,
103
+ };
104
+ } else {
105
+ backTheme = {
106
+ headerLeft: (props: any) => <HeaderLeft {...props} />,
107
+ };
108
+ }
109
+
110
+ if (params.surface == true) {
111
+ surfaceTheme = {
112
+ headerBackground: () => <HeaderBackground />,
113
+ ...getTintColor({
114
+ ...theme,
115
+ assets: {...theme.assets, headerBackground: undefined},
116
+ }),
117
+ };
118
+ } else {
119
+ surfaceTheme = {
120
+ headerBackground: () => (
121
+ <HeaderBackground image={theme.assets?.headerBackground} />
122
+ ),
123
+ ...getTintColor(theme),
124
+ };
125
+ }
126
+
127
+ if (params.customTitle) {
128
+ titleTheme = {
129
+ headerTitle: (props: any) => {
130
+ return <HeaderCustom {...params.customTitle} {...props} />;
131
+ },
132
+ };
133
+ } else {
134
+ titleTheme = {
135
+ headerTitle: HeaderTitle,
136
+ };
137
+ }
138
+
139
+ return {...params, ...backTheme, ...surfaceTheme, ...titleTheme};
140
+ };
141
+
142
+ export {getStackOptions, getDialogOptions, getModalOptions, getOptions};