@momo-kits/foundation 0.75.1-beta.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 (76) hide show
  1. package/Assets/header-background.png +0 -0
  2. package/Assets/icon.json +3947 -0
  3. package/Button/index.tsx +278 -0
  4. package/Button/styles.ts +41 -0
  5. package/CheckBox/index.tsx +61 -0
  6. package/CheckBox/styles.ts +15 -0
  7. package/CheckBox/types.ts +38 -0
  8. package/Consts/colors+spacing+radius.ts +214 -0
  9. package/Consts/index.ts +4 -0
  10. package/Consts/styles.ts +78 -0
  11. package/Consts/theme.ts +121 -0
  12. package/Divider/index.tsx +19 -0
  13. package/Icon/index.tsx +37 -0
  14. package/Icon/types.ts +27 -0
  15. package/IconButton/index.tsx +140 -0
  16. package/IconButton/styles.ts +19 -0
  17. package/Image/index.tsx +80 -0
  18. package/Image/styles.ts +13 -0
  19. package/Image/types.ts +3 -0
  20. package/Input/Input.tsx +136 -0
  21. package/Input/InputMoney.tsx +132 -0
  22. package/Input/InputSearch.tsx +161 -0
  23. package/Input/InputTextArea.tsx +152 -0
  24. package/Input/common.tsx +118 -0
  25. package/Input/index.tsx +96 -0
  26. package/Input/styles.ts +122 -0
  27. package/Input/utils.ts +69 -0
  28. package/Layout/Card.tsx +141 -0
  29. package/Layout/GridSystem.tsx +124 -0
  30. package/Layout/Item.tsx +60 -0
  31. package/Layout/ScreenContainer.tsx +121 -0
  32. package/Layout/Section.tsx +141 -0
  33. package/Layout/index.ts +17 -0
  34. package/Layout/types.ts +59 -0
  35. package/Layout/utils.ts +60 -0
  36. package/Navigation/BottomTab.tsx +39 -0
  37. package/Navigation/Components.tsx +365 -0
  38. package/Navigation/ModalScreen.tsx +226 -0
  39. package/Navigation/Navigation.ts +44 -0
  40. package/Navigation/NavigationButton.tsx +54 -0
  41. package/Navigation/NavigationContainer.tsx +77 -0
  42. package/Navigation/Navigator.ts +82 -0
  43. package/Navigation/StackScreen.tsx +27 -0
  44. package/Navigation/index.ts +14 -0
  45. package/Navigation/types.ts +158 -0
  46. package/Navigation/utils.tsx +138 -0
  47. package/Pagination/Dot.tsx +16 -0
  48. package/Pagination/PaginationDot.tsx +33 -0
  49. package/Pagination/PaginationNumber.tsx +23 -0
  50. package/Pagination/PaginationScroll.tsx +88 -0
  51. package/Pagination/PaginationWhiteDot.tsx +32 -0
  52. package/Pagination/index.tsx +25 -0
  53. package/Pagination/styles.ts +47 -0
  54. package/Pagination/types.ts +38 -0
  55. package/Popup/PopupNotify.tsx +215 -0
  56. package/Popup/PopupPromotion.tsx +77 -0
  57. package/Popup/index.tsx +4 -0
  58. package/Popup/types.ts +70 -0
  59. package/Radio/index.tsx +65 -0
  60. package/Radio/styles.ts +11 -0
  61. package/Radio/types.ts +38 -0
  62. package/Skeleton/index.tsx +72 -0
  63. package/Skeleton/styles.ts +5 -0
  64. package/Skeleton/types.ts +3 -0
  65. package/Switch/index.tsx +40 -0
  66. package/Switch/styles.ts +23 -0
  67. package/Switch/types.ts +26 -0
  68. package/Tag/index.tsx +79 -0
  69. package/Tag/styles.ts +24 -0
  70. package/Tag/types.ts +36 -0
  71. package/Text/index.tsx +123 -0
  72. package/Text/styles.ts +35 -0
  73. package/Text/types.ts +40 -0
  74. package/index.ts +38 -0
  75. package/package.json +41 -0
  76. package/publish.sh +26 -0
@@ -0,0 +1,77 @@
1
+ import React, {useContext} from 'react';
2
+ import {StyleSheet, TouchableOpacity, View} from 'react-native';
3
+ import {PopupPromotionProps} from './types';
4
+ import {ApplicationContext} from '../Navigation';
5
+ import {Image} from '../Image';
6
+ import {Radius, Spacing} from '../Consts';
7
+ import {Icon} from '../Icon';
8
+
9
+ const PopupPromotion: React.FC<PopupPromotionProps> = ({image, onClose}) => {
10
+ const {theme, navigator} = useContext(ApplicationContext);
11
+
12
+ /**
13
+ * build close action
14
+ */
15
+ const buildCloseIcon = () => {
16
+ return (
17
+ <View style={styles.iconCloseContainer}>
18
+ <TouchableOpacity
19
+ onPress={() => {
20
+ navigator?.pop();
21
+ onClose?.();
22
+ }}
23
+ style={[
24
+ styles.iconClose,
25
+ {
26
+ backgroundColor: theme.colors.text.default,
27
+ borderColor: theme.colors.background.surface,
28
+ },
29
+ ]}>
30
+ <Icon
31
+ source="navigation_close"
32
+ color={theme.colors.background.surface}
33
+ size={14}
34
+ />
35
+ </TouchableOpacity>
36
+ </View>
37
+ );
38
+ };
39
+
40
+ return (
41
+ <View accessibilityLabel={'PopupPromotion'}>
42
+ <Image
43
+ style={styles.container}
44
+ source={{
45
+ uri: image,
46
+ }}
47
+ />
48
+ {buildCloseIcon()}
49
+ </View>
50
+ );
51
+ };
52
+
53
+ const styles = StyleSheet.create({
54
+ container: {
55
+ aspectRatio: 0.72,
56
+ },
57
+ iconCloseContainer: {
58
+ width: '100%',
59
+ flexDirection: 'row',
60
+ justifyContent: 'center',
61
+ marginTop: Spacing.L,
62
+ },
63
+ iconClose: {
64
+ width: 20,
65
+ height: 20,
66
+ alignItems: 'center',
67
+ justifyContent: 'center',
68
+ borderRadius: Radius.M,
69
+ borderWidth: 2,
70
+ },
71
+ });
72
+
73
+ PopupPromotion.defaultProps = {
74
+ image: 'https://google.com',
75
+ };
76
+
77
+ export default PopupPromotion;
@@ -0,0 +1,4 @@
1
+ import PopupNotify from './PopupNotify';
2
+ import PopupPromotion from './PopupPromotion';
3
+
4
+ export {PopupNotify, PopupPromotion};
package/Popup/types.ts ADDED
@@ -0,0 +1,70 @@
1
+ export type PopupNotifyProps = {
2
+ /**
3
+ * `image`: Optional. Represents the URL or path of the image to be displayed in the PopupNotify component.
4
+ */
5
+ image?: string;
6
+
7
+ /**
8
+ * `title`: Represents the title text to be displayed in the PopupNotify component.
9
+ */
10
+ title: string;
11
+
12
+ /**
13
+ * `description`: Represents the description text to be displayed in the PopupNotify component.
14
+ */
15
+ description: string;
16
+
17
+ /**
18
+ * `information`: Optional. Represents additional information text to be displayed in the PopupNotify component.
19
+ */
20
+ information?: string;
21
+
22
+ /**
23
+ * `secondary`: Optional. Represents the secondary action that can be performed from the PopupNotify component.
24
+ */
25
+ secondary?: PopupAction;
26
+
27
+ /**
28
+ * `primary`: Represents the primary action that can be performed from the PopupNotify component.
29
+ */
30
+ primary: PopupAction;
31
+
32
+ /**
33
+ * `buttonDirection`: Optional. Represents the direction in which the action buttons are laid out.
34
+ * - 'row': Buttons are laid out horizontally.
35
+ * - 'column': Buttons are laid out vertically.
36
+ * - 'auto': The layout is automatically determined by title length.
37
+ */
38
+ buttonDirection?: PopupActionDirection;
39
+
40
+ /**
41
+ * `onIconClose`: Optional. A callback function that is called when the close icon in the PopupNotify component is pressed.
42
+ */
43
+ onIconClose?: () => void;
44
+ };
45
+
46
+ export type PopupPromotionProps = {
47
+ /**
48
+ * `image`: Represents the URL or path of the image to be displayed in the PopupPromotion component.
49
+ */
50
+ image: string;
51
+
52
+ /**
53
+ * `onClose`: Optional. A callback function that is called when the PopupPromotion component is closed.
54
+ */
55
+ onClose?: () => void;
56
+ };
57
+
58
+ type PopupAction = {
59
+ /**
60
+ * `title`: Represents the title text of the action button.
61
+ */
62
+ title: string;
63
+
64
+ /**
65
+ * `onPress`: A callback function that is called when the action button is pressed.
66
+ */
67
+ onPress: () => void;
68
+ };
69
+
70
+ type PopupActionDirection = 'row' | 'column' | 'auto';
@@ -0,0 +1,65 @@
1
+ import React, {FC, useContext} from 'react';
2
+ import {TouchableOpacity, View} from 'react-native';
3
+
4
+ import {RadioProps} from './types';
5
+ import {Text} from '../Text';
6
+ import styles from './styles';
7
+ import {ApplicationContext} from '../Navigation';
8
+ import {Spacing} from '../Consts';
9
+
10
+ const Radio: FC<RadioProps> = ({
11
+ value,
12
+ groupValue,
13
+ disabled,
14
+ onChange,
15
+ label,
16
+ style,
17
+ }) => {
18
+ const {theme} = useContext(ApplicationContext);
19
+ const selected = value === groupValue;
20
+ let disabledStyle = {};
21
+ let checkBoxStyle = {
22
+ borderWidth: 2,
23
+ borderColor: theme.colors.text.default,
24
+ };
25
+
26
+ if (selected) {
27
+ checkBoxStyle = {
28
+ borderWidth: 6,
29
+ borderColor: theme.colors.primary,
30
+ };
31
+ }
32
+ if (disabled) {
33
+ disabledStyle = {
34
+ borderColor: selected
35
+ ? theme.colors.background.tonal
36
+ : theme.colors.text.disable,
37
+ };
38
+ }
39
+
40
+ return (
41
+ <TouchableOpacity
42
+ accessibilityLabel={`Radio/${label}`}
43
+ onPress={onChange}
44
+ disabled={disabled}
45
+ style={[
46
+ style,
47
+ {
48
+ flexDirection: 'row',
49
+ alignItems: 'center',
50
+ },
51
+ ]}>
52
+ <View
53
+ style={[
54
+ styles.radio,
55
+ checkBoxStyle,
56
+ disabledStyle,
57
+ {marginRight: label ? Spacing.XS : 0},
58
+ ]}
59
+ />
60
+ {!!label && <Text typography={'description_default'}>{label}</Text>}
61
+ </TouchableOpacity>
62
+ );
63
+ };
64
+
65
+ export {Radio};
@@ -0,0 +1,11 @@
1
+ import {StyleSheet} from 'react-native';
2
+ import {Radius} from '../Consts';
3
+
4
+ export default StyleSheet.create({
5
+ radio: {
6
+ height: 20,
7
+ width: 20,
8
+ borderRadius: Radius.M,
9
+ },
10
+ container: {flex: 1},
11
+ });
package/Radio/types.ts ADDED
@@ -0,0 +1,38 @@
1
+ import {ViewStyle} from 'react-native';
2
+
3
+ export type RadioProps = {
4
+ /**
5
+ * `value`: Represents the value associated with the Radio component.
6
+ * It is used to determine whether the Radio component is selected or not in comparison with the `groupValue`.
7
+ */
8
+ value: string;
9
+
10
+ /**
11
+ * `disabled`: Optional. If `true`, the user won't be able to interact with the Radio component.
12
+ * Defaults to `false` if not provided.
13
+ */
14
+ disabled?: boolean;
15
+
16
+ /**
17
+ * `label`: Optional. Represents the text label displayed next to the Radio component.
18
+ */
19
+ label?: string;
20
+
21
+ /**
22
+ * `onChange`: A callback function that is called when the value of the Radio component changes.
23
+ * It is triggered when the user interacts with the Radio component.
24
+ */
25
+ onChange: () => void;
26
+
27
+ /**
28
+ * `groupValue`: Represents the value of the selected Radio component within a group of Radio components.
29
+ * The Radio component for which `value` equals `groupValue` will be selected.
30
+ */
31
+ groupValue: string;
32
+
33
+ /**
34
+ * `style`: Optional. Used to apply custom styling to the Radio component.
35
+ * Accepts an object of style properties.
36
+ */
37
+ style?: ViewStyle;
38
+ };
@@ -0,0 +1,72 @@
1
+ import React, {useEffect, useMemo, useRef, useState} from 'react';
2
+ import {Animated, Easing, Platform, StyleSheet, View} from 'react-native';
3
+ import LinearGradient from 'react-native-linear-gradient';
4
+ import {SkeletonTypes} from './types';
5
+ import {Colors, Styles} from '../Consts';
6
+ import styles from './styles';
7
+
8
+ const Skeleton: React.FC<SkeletonTypes> = ({style}) => {
9
+ const [width, setWidth] = useState(0);
10
+ const PRIMARY_COLOR = Colors.black_05;
11
+ const HIGHLIGHT_COLOR1 = Colors.black_05;
12
+ const HIGHLIGHT_COLOR2 = Colors.black_03;
13
+ const beginShimmerPosition = useRef(new Animated.Value(0)).current;
14
+
15
+ const shimmerColors = [HIGHLIGHT_COLOR1, HIGHLIGHT_COLOR2, HIGHLIGHT_COLOR1];
16
+ const linearTranslate = beginShimmerPosition.interpolate({
17
+ inputRange: [0, 1],
18
+ outputRange: [-width, width],
19
+ });
20
+ const animatedValue = useMemo(() => {
21
+ return Animated.loop(
22
+ Animated.timing(beginShimmerPosition, {
23
+ toValue: 1,
24
+ duration: 1000,
25
+ easing: Easing.linear,
26
+ useNativeDriver: Platform.OS !== 'web',
27
+ }),
28
+ );
29
+ }, [beginShimmerPosition]);
30
+
31
+ useEffect(() => {
32
+ animatedValue.start();
33
+ return () => {
34
+ animatedValue.stop();
35
+ };
36
+ }, [animatedValue]);
37
+
38
+ const onLayout = (newWidth: number) => {
39
+ if (newWidth !== width) {
40
+ setWidth(newWidth);
41
+ }
42
+ };
43
+ return (
44
+ <View style={[styles.container, style]} accessibilityLabel={'Skeleton'}>
45
+ <View
46
+ onLayout={e => onLayout(e.nativeEvent.layout.width)}
47
+ style={[Styles.flex, {backgroundColor: PRIMARY_COLOR}]}>
48
+ <Animated.View
49
+ style={{
50
+ transform: [{translateX: linearTranslate}],
51
+ width: '60%',
52
+ height: '100%',
53
+ }}>
54
+ <LinearGradient
55
+ style={[StyleSheet.absoluteFill]}
56
+ colors={shimmerColors}
57
+ start={{
58
+ x: 0,
59
+ y: 0,
60
+ }}
61
+ end={{
62
+ x: 1,
63
+ y: 0,
64
+ }}
65
+ />
66
+ </Animated.View>
67
+ </View>
68
+ </View>
69
+ );
70
+ };
71
+
72
+ export {Skeleton};
@@ -0,0 +1,5 @@
1
+ import {StyleSheet} from 'react-native';
2
+
3
+ export default StyleSheet.create({
4
+ container: {overflow: 'hidden', width: '100%', height: '100%'},
5
+ });
@@ -0,0 +1,3 @@
1
+ export type SkeletonTypes = {
2
+ style?: object;
3
+ };
@@ -0,0 +1,40 @@
1
+ import React, {FC, useContext} from 'react';
2
+ import {TouchableOpacity, View} from 'react-native';
3
+ import {SwitchProps} from './types';
4
+ import styles from './styles';
5
+ import {ApplicationContext} from '../Navigation';
6
+ import {Colors} from '../Consts';
7
+
8
+ const Switch: FC<SwitchProps> = props => {
9
+ const {theme} = useContext(ApplicationContext);
10
+ const {value, onChange, disabled, style} = props;
11
+ const circleBackgroundColor = value ? Colors.black_01 : Colors.black_03;
12
+ const circleAlign = value ? 'flex-end' : 'flex-start';
13
+
14
+ let backgroundColor = value ? theme.colors.primary : Colors.black_07;
15
+ if (disabled) {
16
+ backgroundColor = value ? theme.colors.background.tonal : Colors.black_05;
17
+ }
18
+
19
+ return (
20
+ <TouchableOpacity
21
+ accessibilityLabel={'Switch'}
22
+ disabled={disabled}
23
+ onPress={() => onChange?.(!value)}
24
+ style={[
25
+ style,
26
+ styles.container,
27
+ {backgroundColor, alignItems: circleAlign},
28
+ ]}>
29
+ <View style={[styles.circle, {backgroundColor: circleBackgroundColor}]}>
30
+ <View style={[styles.circleSmall, {backgroundColor}]} />
31
+ </View>
32
+ </TouchableOpacity>
33
+ );
34
+ };
35
+
36
+ Switch.defaultProps = {
37
+ value: false,
38
+ disabled: false,
39
+ };
40
+ export {Switch};
@@ -0,0 +1,23 @@
1
+ import {StyleSheet} from 'react-native';
2
+
3
+ export default StyleSheet.create({
4
+ container: {
5
+ width: 38,
6
+ height: 24,
7
+ borderRadius: 20,
8
+ justifyContent: 'center',
9
+ paddingHorizontal: 4,
10
+ },
11
+ circle: {
12
+ width: 14,
13
+ height: 14,
14
+ borderRadius: 8,
15
+ alignItems: 'center',
16
+ justifyContent: 'center',
17
+ },
18
+ circleSmall: {
19
+ width: 6,
20
+ height: 6,
21
+ borderRadius: 4,
22
+ },
23
+ });
@@ -0,0 +1,26 @@
1
+ import {ViewStyle} from 'react-native';
2
+
3
+ export type SwitchProps = {
4
+ /**
5
+ * `value`: Represents whether the Switch component is currently in the 'on' (`true`) or 'off' (`false`) state.
6
+ */
7
+ value: boolean;
8
+
9
+ /**
10
+ * `onChange`: A callback function that is called when the value of the Switch component changes.
11
+ * It receives the new value of the Switch as a parameter.
12
+ */
13
+ onChange: (value: boolean) => void;
14
+
15
+ /**
16
+ * `disabled`: Optional. If `true`, the user won't be able to interact with the Switch component.
17
+ * Defaults to `false` if not provided.
18
+ */
19
+ disabled?: boolean;
20
+
21
+ /**
22
+ * `style`: Optional. Used to apply custom styling to the Switch component.
23
+ * Accepts an object of style properties.
24
+ */
25
+ style?: ViewStyle;
26
+ };
package/Tag/index.tsx ADDED
@@ -0,0 +1,79 @@
1
+ import React, {FC} from 'react';
2
+ import {View} from 'react-native';
3
+ import {TagProps} from './types';
4
+ import styles from './styles';
5
+ import {Colors} from '../Consts';
6
+ import {Icon} from '../Icon';
7
+ import {Text} from '../Text';
8
+
9
+ const backgroundColor = {
10
+ default: Colors.black_04,
11
+ orange: Colors.orange_08,
12
+ green: Colors.green_08,
13
+ red: Colors.red_08,
14
+ blue: Colors.blue_08,
15
+ grey: Colors.black_04,
16
+ };
17
+
18
+ const textColor = {
19
+ default: Colors.black_17,
20
+ orange: Colors.orange_03,
21
+ green: Colors.green_03,
22
+ red: Colors.red_03,
23
+ blue: Colors.blue_03,
24
+ grey: Colors.black_12,
25
+ };
26
+
27
+ const Tag: FC<TagProps> = ({
28
+ label = 'Label',
29
+ icon,
30
+ color = 'default',
31
+ size = 'large',
32
+ style,
33
+ customColor,
34
+ }) => {
35
+ let labelColor = textColor[color];
36
+ let tagColor = backgroundColor[color];
37
+ let sizeStyle = styles.mediumContainer;
38
+ //Check if custom color is [color]_03 (only check in dev mode)
39
+ const validateCustomColor = (color: string) => {
40
+ if (__DEV__) {
41
+ const colorCore: {[key: string]: string} = Colors;
42
+ const primaryColors = Object.keys(Colors)
43
+ .map(i => {
44
+ if (i.includes('_03')) {
45
+ return colorCore[i];
46
+ }
47
+ })
48
+ .filter(color => color);
49
+ return primaryColors.includes(color);
50
+ }
51
+ return true;
52
+ };
53
+
54
+ if (size === 'large') {
55
+ sizeStyle = styles.container;
56
+ }
57
+ if (customColor && validateCustomColor(customColor)) {
58
+ labelColor = Colors.black_01;
59
+ tagColor = customColor;
60
+ }
61
+
62
+ return (
63
+ <View style={[style, sizeStyle, {backgroundColor: tagColor}]}>
64
+ {!!icon && (
65
+ <Icon
66
+ style={styles.icon}
67
+ size={16}
68
+ source={icon as string}
69
+ color={labelColor}
70
+ />
71
+ )}
72
+ <Text color={labelColor} typography={'label_s'}>
73
+ {label}
74
+ </Text>
75
+ </View>
76
+ );
77
+ };
78
+
79
+ export {Tag};
package/Tag/styles.ts ADDED
@@ -0,0 +1,24 @@
1
+ import {StyleSheet} from 'react-native';
2
+ import {Radius, Spacing} from '../Consts';
3
+
4
+ export default StyleSheet.create({
5
+ container: {
6
+ paddingHorizontal: Spacing.S,
7
+ borderRadius: Radius.S,
8
+ flexDirection: 'row',
9
+ height: 24,
10
+ alignItems: 'center',
11
+ justifyContent: 'center',
12
+ },
13
+ mediumContainer: {
14
+ paddingHorizontal: Spacing.S,
15
+ borderRadius: Radius.S,
16
+ height: 18,
17
+ alignItems: 'center',
18
+ flexDirection: 'row',
19
+ justifyContent: 'center',
20
+ },
21
+ icon: {
22
+ marginRight: Spacing.XS,
23
+ },
24
+ });
package/Tag/types.ts ADDED
@@ -0,0 +1,36 @@
1
+ import {ViewStyle} from 'react-native';
2
+
3
+ export type TagProps = {
4
+ /**
5
+ * `label`: Represents the text label displayed on the Tag component.
6
+ */
7
+ label: string;
8
+
9
+ /**
10
+ * `size`: Optional. Defines the size of the Tag component.
11
+ * Defaults to 'medium' if not provided.
12
+ */
13
+ size?: 'medium' | 'large';
14
+
15
+ /**
16
+ * `icon`: Optional. Represents the name or key of the icon to be displayed in the Tag component.
17
+ */
18
+ icon?: string;
19
+
20
+ /**
21
+ * `color`: Optional. Defines the color style of the Tag component.
22
+ */
23
+ color?: 'default' | 'orange' | 'green' | 'red' | 'blue' | 'grey';
24
+
25
+ /**
26
+ * `style`: Optional. Used to apply custom styling to the Tag component.
27
+ * Accepts an object of style properties.
28
+ */
29
+ style?: ViewStyle;
30
+
31
+ /**
32
+ * `customColor`: Optional. Represents a custom color string (e.g., hex, rgb, rgba, etc.)
33
+ * that can be applied to the Tag component.
34
+ */
35
+ customColor?: string;
36
+ };