@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
@@ -0,0 +1,168 @@
1
+ import {default as React, useContext, useEffect, useRef, useState} from 'react';
2
+ import {
3
+ Animated,
4
+ LayoutChangeEvent,
5
+ StyleSheet,
6
+ TouchableOpacity,
7
+ View,
8
+ } from 'react-native';
9
+ import {ApplicationContext} from '../Application';
10
+ import {Icon} from '../Icon';
11
+
12
+ export interface FloatingButtonProps {
13
+ label?: string;
14
+ onPress?: () => void;
15
+ position?: 'center' | 'right';
16
+ icon?: string;
17
+ iconColor?: string;
18
+ size?: 'small' | 'large';
19
+ animatedValue?: Animated.Value;
20
+ bottom?: number;
21
+ renderComponent?: () => React.ReactNode;
22
+ }
23
+
24
+ export const FloatingButton: React.FC<FloatingButtonProps> = ({
25
+ renderComponent,
26
+ label = '',
27
+ onPress = () => {},
28
+ position = 'right',
29
+ icon = '',
30
+ iconColor = '',
31
+ size = 'small',
32
+ animatedValue,
33
+ bottom = 12,
34
+ }: FloatingButtonProps) => {
35
+ const {theme} = useContext(ApplicationContext);
36
+ const maxWidth = useRef(0);
37
+ const minWidth = size == 'small' ? 36 : 48;
38
+ const [opacityAnimated] = useState(new Animated.Value(0)); // Initial opacity set to 0
39
+ const [widthAnimated, setWidthAnimated] = useState<Animated.Value>();
40
+ const lastOffset = useRef(0);
41
+ const lastDirection = useRef<string>();
42
+ const [showText, setShowText] = React.useState(true);
43
+
44
+ useEffect(() => {
45
+ if (!label) return;
46
+
47
+ Animated.timing(opacityAnimated, {
48
+ toValue: 1,
49
+ duration: 100,
50
+ useNativeDriver: true,
51
+ }).start();
52
+
53
+ const listener = animatedValue?.addListener(({value}) => {
54
+ if (value !== lastOffset.current && value > 0) {
55
+ const direction = value > lastOffset.current ? 'down' : 'up';
56
+ lastOffset.current = value;
57
+ if (lastDirection.current !== direction) {
58
+ lastDirection.current = direction;
59
+ if (direction === 'down') {
60
+ Animated.timing(opacityAnimated, {
61
+ toValue: 0,
62
+ duration: 100,
63
+ useNativeDriver: true,
64
+ }).start();
65
+ Animated.timing(widthAnimated!, {
66
+ toValue: minWidth,
67
+ duration: 100,
68
+ useNativeDriver: false,
69
+ }).start(() => setShowText(false));
70
+ } else {
71
+ Animated.timing(opacityAnimated, {
72
+ toValue: 1,
73
+ duration: 100,
74
+ useNativeDriver: true,
75
+ }).start();
76
+ Animated.timing(widthAnimated!, {
77
+ toValue: maxWidth.current,
78
+ duration: 100,
79
+ useNativeDriver: false,
80
+ }).start(() => setShowText(true));
81
+ }
82
+ }
83
+ }
84
+ });
85
+
86
+ return () => {
87
+ if (listener != null) {
88
+ animatedValue?.removeListener(listener);
89
+ }
90
+ };
91
+ }, [label, widthAnimated]);
92
+
93
+ const handleLayout = (event: LayoutChangeEvent) => {
94
+ const layout = event.nativeEvent.layout;
95
+ if (widthAnimated) return;
96
+ maxWidth.current = layout.width;
97
+ setWidthAnimated(new Animated.Value(layout.width));
98
+ };
99
+
100
+ if (renderComponent) {
101
+ return (
102
+ <View
103
+ onLayout={handleLayout}
104
+ style={[
105
+ styles.container,
106
+ {
107
+ right: position === 'right' ? 12 : undefined,
108
+ alignSelf: position === 'center' ? 'center' : 'flex-end',
109
+ bottom,
110
+ },
111
+ ]}>
112
+ {renderComponent()}
113
+ </View>
114
+ );
115
+ }
116
+
117
+ return (
118
+ <Animated.View
119
+ onLayout={handleLayout}
120
+ style={[
121
+ styles.container,
122
+ {
123
+ right: position === 'right' ? 12 : undefined,
124
+ alignSelf: position === 'center' ? 'center' : 'flex-end',
125
+ width: widthAnimated,
126
+ height: size == 'small' ? 36 : 48,
127
+ backgroundColor: theme.colors.primary,
128
+ bottom,
129
+ },
130
+ ]}>
131
+ <TouchableOpacity
132
+ style={{flexDirection: 'row', alignItems: 'center'}}
133
+ onPress={onPress}>
134
+ <Icon
135
+ source={icon}
136
+ size={size === 'small' ? 12 : 24}
137
+ color={iconColor}
138
+ />
139
+ {showText && !!label && (
140
+ <Animated.Text
141
+ style={[styles.label, {opacity: opacityAnimated, color: 'white'}]}
142
+ numberOfLines={1}>
143
+ {label}
144
+ </Animated.Text>
145
+ )}
146
+ </TouchableOpacity>
147
+ </Animated.View>
148
+ );
149
+ };
150
+
151
+ const styles = StyleSheet.create({
152
+ container: {
153
+ flexDirection: 'row',
154
+ alignContent: 'center',
155
+ alignItems: 'center',
156
+ position: 'absolute',
157
+ borderRadius: 100,
158
+ paddingHorizontal: 12,
159
+ flexWrap: 'wrap',
160
+ alignSelf: 'flex-end',
161
+ },
162
+ label: {
163
+ marginLeft: 8,
164
+ fontSize: 16,
165
+ lineHeight: 22,
166
+ fontWeight: '700',
167
+ },
168
+ });
@@ -6,20 +6,24 @@ import {Colors, Spacing} from '../Consts';
6
6
  import {GridContextProps} from './types';
7
7
  import {useGridSystem} from './utils';
8
8
 
9
- const GridSystem: React.FC = () => {
9
+ const GridSystem: React.FC<any> = ({
10
+ width = Dimensions.get('window').width,
11
+ useMargin = true,
12
+ gutterSize = Spacing.M,
13
+ screenGrid = true,
14
+ gridColor = Colors.blue_07,
15
+ }) => {
10
16
  const {theme} = useContext(ApplicationContext);
11
17
  const {numberOfColumns} = useGridSystem();
12
18
 
13
- const gutterSize = 12;
14
- const margin = 12;
15
- const widthSection = Dimensions.get('window').width - margin * 2;
19
+ const margin = useMargin ? Spacing.M : 0;
20
+ const widthSection = width - margin * 2;
16
21
  const totalGutterSize = gutterSize * (numberOfColumns - 1);
17
22
  const sizePerSpan = (widthSection - totalGutterSize) / numberOfColumns;
18
23
 
19
24
  const grid: GridContextProps = {
20
25
  numberOfColumns,
21
26
  gutterSize,
22
- margin,
23
27
  sizePerSpan,
24
28
  getSizeSpan: span => {
25
29
  return span * sizePerSpan + (span - 1) * gutterSize;
@@ -27,7 +31,7 @@ const GridSystem: React.FC = () => {
27
31
  };
28
32
  const insets = useSafeAreaInsets();
29
33
 
30
- const list = [];
34
+ const list: number[] = [];
31
35
  for (let i = 1; i <= grid.numberOfColumns; i++) {
32
36
  list.push(i);
33
37
  }
@@ -38,23 +42,26 @@ const GridSystem: React.FC = () => {
38
42
  pointerEvents="none"
39
43
  style={[
40
44
  styles.gridContainer,
41
- insets,
45
+ screenGrid && insets,
42
46
  {
43
47
  borderColor: theme.colors.error.primary,
44
- marginHorizontal: grid.margin,
48
+ marginHorizontal: margin,
49
+ top: Spacing.M,
50
+ bottom: Spacing.M,
45
51
  },
46
52
  ]}>
47
- {list.map((i, index) => {
53
+ {list.map((_, index) => {
48
54
  return (
49
55
  <View style={{flexDirection: 'row'}} key={index.toString()}>
50
56
  {index != -0 && <View style={{width: grid.gutterSize}} />}
51
57
  <View
52
- key={index.toString()}
58
+ key={`Grid${index.toString()}`}
53
59
  pointerEvents="none"
54
60
  style={[
55
61
  styles.gridColumn,
56
62
  {
57
63
  width: grid.sizePerSpan,
64
+ backgroundColor: gridColor,
58
65
  },
59
66
  ]}
60
67
  />
@@ -62,16 +69,20 @@ const GridSystem: React.FC = () => {
62
69
  );
63
70
  })}
64
71
  </View>
65
- <View pointerEvents="none" style={styles.dangerLeftContainer} />
66
- <View pointerEvents="none" style={styles.dangerRightContainer} />
67
- <View
68
- pointerEvents="none"
69
- style={[styles.dangerTopContainer, {height: insets.top}]}
70
- />
71
- <View
72
- pointerEvents="none"
73
- style={[styles.dangerBottomContainer, {height: insets.bottom}]}
74
- />
72
+ {screenGrid && (
73
+ <>
74
+ <View pointerEvents="none" style={styles.dangerLeftContainer} />
75
+ <View pointerEvents="none" style={styles.dangerRightContainer} />
76
+ <View
77
+ pointerEvents="none"
78
+ style={[styles.dangerTopContainer, {height: Spacing.M}]}
79
+ />
80
+ <View
81
+ pointerEvents="none"
82
+ style={[styles.dangerBottomContainer, {height: insets.bottom}]}
83
+ />
84
+ </>
85
+ )}
75
86
  </>
76
87
  );
77
88
  };
@@ -89,7 +100,6 @@ const styles = StyleSheet.create({
89
100
  gridColumn: {
90
101
  height: '100%',
91
102
  opacity: 0.2,
92
- backgroundColor: Colors.blue_07,
93
103
  },
94
104
  dangerTopContainer: {
95
105
  opacity: 0.2,
package/Layout/Item.tsx CHANGED
@@ -1,9 +1,23 @@
1
1
  import React, {useContext} from 'react';
2
- import {View} from 'react-native';
2
+ import {View, ViewProps} from 'react-native';
3
3
 
4
- import {ItemProps} from './types';
5
4
  import {GridContext} from './index';
6
- import {GRIDVIEW} from '../Consts';
5
+ import {ApplicationContext} from '../Application';
6
+ import styles from './styles';
7
+
8
+ export type SpanNumber = 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12;
9
+
10
+ export interface ItemProps extends ViewProps {
11
+ /**
12
+ * Represents the width of the Card component in terms of span numbers (1-12).
13
+ */
14
+ widthSpan?: SpanNumber;
15
+
16
+ /**
17
+ * Optional. Represents the height of the Card component in terms of span numbers (1-12).
18
+ */
19
+ heightSpan?: SpanNumber;
20
+ }
7
21
 
8
22
  const Item: React.FC<ItemProps> = ({
9
23
  widthSpan,
@@ -11,46 +25,28 @@ const Item: React.FC<ItemProps> = ({
11
25
  children,
12
26
  style,
13
27
  }) => {
28
+ const {showGrid} = useContext(ApplicationContext);
14
29
  const grid = useContext(GridContext);
15
30
 
16
31
  /**
17
32
  * render overlay view only dev mode
18
33
  */
19
34
  const renderOverlay = () => {
20
- return (
21
- <View
22
- pointerEvents={'none'}
23
- style={{
24
- position: 'absolute',
25
- top: 0,
26
- bottom: 0,
27
- left: 0,
28
- right: 0,
29
- borderColor: 'red',
30
- borderWidth: 1,
31
- }}
32
- />
33
- );
35
+ return <View pointerEvents={'none'} style={styles.boxGrid} />;
34
36
  };
35
37
 
36
38
  return (
37
39
  <View
38
- accessibilityLabel={`Item`}
39
40
  style={[
40
41
  style,
42
+ styles.item,
41
43
  {
42
44
  width: grid.getSizeSpan(widthSpan ?? grid.numberOfColumns),
43
45
  height: heightSpan ? grid.getSizeSpan(heightSpan) : undefined,
44
- overflow: 'hidden',
45
- margin: undefined,
46
- marginTop: undefined,
47
- marginBottom: undefined,
48
- marginLeft: undefined,
49
- marginRight: undefined,
50
46
  },
51
47
  ]}>
52
48
  {children}
53
- {GRIDVIEW && renderOverlay()}
49
+ {showGrid && renderOverlay()}
54
50
  </View>
55
51
  );
56
52
  };
@@ -0,0 +1,55 @@
1
+ import React, {forwardRef, useContext} from 'react';
2
+ import {FlatList, FlatListProps, View} from 'react-native';
3
+ import Item, {SpanNumber} from './Item';
4
+ import {GridContext} from './index';
5
+ import styles from './styles';
6
+
7
+ export interface ItemListProps extends FlatListProps<any> {
8
+ /**
9
+ * Represents the width of the Card component in terms of span numbers (1-12).
10
+ */
11
+ widthSpan?: SpanNumber;
12
+ }
13
+
14
+ const ItemList = forwardRef(
15
+ (
16
+ {
17
+ renderItem,
18
+ widthSpan,
19
+ style,
20
+ contentContainerStyle,
21
+ ...props
22
+ }: ItemListProps,
23
+ ref,
24
+ ) => {
25
+ const {gutterSize, numberOfColumns} = useContext(GridContext);
26
+ const widthItem = (widthSpan ?? numberOfColumns) as SpanNumber;
27
+ const numColumns = Math.floor(numberOfColumns / widthItem);
28
+ const indexBegin = props?.data?.map((_i, index) => index * numColumns);
29
+ const _renderItem = (item: any) => {
30
+ if (indexBegin?.includes(item?.index)) {
31
+ return <Item widthSpan={widthItem}>{renderItem?.(item)}</Item>;
32
+ }
33
+ return (
34
+ <View style={{paddingLeft: gutterSize}}>
35
+ <Item widthSpan={widthItem}>{renderItem?.(item)}</Item>
36
+ </View>
37
+ );
38
+ };
39
+
40
+ return (
41
+ <FlatList
42
+ ref={ref as React.RefObject<FlatList>}
43
+ {...props}
44
+ numColumns={numColumns}
45
+ renderItem={_renderItem}
46
+ horizontal={false}
47
+ ItemSeparatorComponent={() => <View style={{height: gutterSize}} />}
48
+ style={[style, styles.protectedStyle]}
49
+ contentContainerStyle={[contentContainerStyle, styles.protectedStyle]}
50
+ />
51
+ );
52
+ },
53
+ );
54
+
55
+ export default ItemList;
@@ -0,0 +1,39 @@
1
+ import React, {FC, useContext} from 'react';
2
+ import {SectionList, SectionListProps, View} from 'react-native';
3
+ import Item, {SpanNumber} from './Item';
4
+ import {GridContext} from './index';
5
+ import styles from './styles';
6
+
7
+ export interface ItemSectionListProps extends SectionListProps<any> {
8
+ /**
9
+ * Represents the width of the Card component in terms of span numbers (1-12).
10
+ */
11
+ widthSpan?: SpanNumber;
12
+ }
13
+
14
+ const ItemSectionList: FC<ItemSectionListProps> = ({
15
+ renderItem,
16
+ widthSpan,
17
+ style,
18
+ contentContainerStyle,
19
+ ...props
20
+ }) => {
21
+ const {gutterSize, numberOfColumns} = useContext(GridContext);
22
+ const widthItem = (widthSpan ?? numberOfColumns) as SpanNumber;
23
+ const _renderItem = (item: any) => {
24
+ return <Item widthSpan={widthItem}>{renderItem?.(item)}</Item>;
25
+ };
26
+
27
+ return (
28
+ <SectionList
29
+ {...props}
30
+ renderItem={_renderItem}
31
+ horizontal={false}
32
+ ItemSeparatorComponent={() => <View style={{height: gutterSize}} />}
33
+ style={[style, styles.protectedStyle]}
34
+ contentContainerStyle={[contentContainerStyle, styles.protectedStyle]}
35
+ />
36
+ );
37
+ };
38
+
39
+ export default ItemSectionList;