@momo-kits/foundation 1.0.14 → 1.0.16

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.
package/Button/index.tsx CHANGED
@@ -27,6 +27,7 @@ export interface ButtonProps extends TouchableOpacityProps {
27
27
  iconLeft?: string;
28
28
  title: string;
29
29
  useTintColor?: boolean;
30
+ onPress: () => void;
30
31
  }
31
32
 
32
33
  const Button: FC<ButtonProps> = ({
@@ -211,11 +212,11 @@ const Button: FC<ButtonProps> = ({
211
212
  full && {width: '100%'},
212
213
  ]);
213
214
 
214
- const onPressButton = (e: any) => {
215
+ const onPressButton = () => {
215
216
  if (type === 'disabled') {
216
217
  return () => {};
217
218
  }
218
- onPress?.(e);
219
+ onPress?.();
219
220
  };
220
221
 
221
222
  const activeOpacity = type === 'disabled' ? 0.75 : 0.5;
package/Consts/theme.ts CHANGED
@@ -10,7 +10,7 @@ const defaultTheme: Theme = {
10
10
  default: '#f2f2f6',
11
11
  surface: Colors.black_01,
12
12
  tonal: Colors.pink_09,
13
- pressed: '#fef4fa',
13
+ pressed: '#dfdfe6',
14
14
  selected: Colors.pink_10,
15
15
  disable: '#ebebf2',
16
16
  },
@@ -22,7 +22,6 @@ const InputSearch: FC<InputSearchProps> = ({
22
22
  icon,
23
23
  buttonText = 'Hủy',
24
24
  showButtonText = true,
25
- showIcon = true,
26
25
  showBorder = true,
27
26
  style,
28
27
  ...props
@@ -104,7 +103,7 @@ const InputSearch: FC<InputSearchProps> = ({
104
103
  />
105
104
  </TouchableOpacity>
106
105
  )}
107
- {showIcon && icon && (
106
+ {icon || (
108
107
  <View style={{flexDirection: 'row'}}>
109
108
  <View
110
109
  style={[
@@ -116,7 +115,7 @@ const InputSearch: FC<InputSearchProps> = ({
116
115
  />
117
116
  <Icon
118
117
  color={iconTintColor}
119
- source={icon}
118
+ source={icon as string}
120
119
  style={styles.iconSearchInput}
121
120
  />
122
121
  </View>
package/Input/common.tsx CHANGED
@@ -1,10 +1,10 @@
1
1
  import {View} from 'react-native';
2
2
  import styles from './styles';
3
3
  import {Text} from '../Text';
4
- import {Image} from '../Image';
5
4
  import React, {FC, useContext} from 'react';
6
5
  import {ApplicationContext} from '../Navigation';
7
6
  import {Icon} from '../Icon';
7
+ import {Styles} from '../Consts';
8
8
 
9
9
  type FloatingViewProps = {
10
10
  floatingValue?: string;
@@ -56,7 +56,11 @@ export const ErrorView: FC<{errorMessage?: string}> = ({errorMessage}) => {
56
56
  <View style={styles.errorIcon}>
57
57
  <Icon color={errorColor} source="ic_error" size={16} />
58
58
  </View>
59
- <Text color={errorColor} typography={'description_s'}>
59
+ <Text
60
+ style={Styles.flex}
61
+ color={errorColor}
62
+ numberOfLines={1}
63
+ typography={'description_s'}>
60
64
  {errorMessage}
61
65
  </Text>
62
66
  </View>
@@ -99,10 +103,10 @@ export const FloatingView: FC<FloatingViewProps> = ({
99
103
  </Text>
100
104
  )}
101
105
  </Text>
102
- {floatingIcon && (
106
+ {floatingIcon || (
103
107
  <Icon
104
108
  color={floatingIconTintColor}
105
- source={floatingIcon}
109
+ source={floatingIcon as string}
106
110
  size={16}
107
111
  style={styles.floatingIcon}
108
112
  />
package/Input/index.tsx CHANGED
@@ -33,7 +33,6 @@ export interface InputTextAreaProps extends InputPropsWithoutSizeAndIcon {
33
33
  export interface InputSearchProps extends InputPropsOmitForSearch {
34
34
  buttonText?: string;
35
35
  showButtonText?: boolean;
36
- showIcon?: boolean;
37
36
  showBorder?: boolean;
38
37
  }
39
38
 
@@ -30,7 +30,7 @@ const ScreenContainer: React.FC<ScreenContainerProps> = ({
30
30
  transform: [
31
31
  {
32
32
  scale: scrollY.interpolate?.({
33
- inputRange: [-300, -110, 100],
33
+ inputRange: [-300, 0, 1],
34
34
  outputRange: [1.75, 1, 1],
35
35
  extrapolate: 'clamp',
36
36
  }),
@@ -76,7 +76,7 @@ const ScreenContainer: React.FC<ScreenContainerProps> = ({
76
76
  height: 300,
77
77
  width: '100%',
78
78
  }}>
79
- {headerBackground && (
79
+ {headerBackground || (
80
80
  <Animated.Image
81
81
  source={{
82
82
  uri: headerBackground,
@@ -8,7 +8,7 @@ import {
8
8
  View,
9
9
  } from 'react-native';
10
10
  import {ApplicationContext, NavigationButton} from './index';
11
- import {Colors, Spacing, Styles} from '../Consts';
11
+ import {Colors, Radius, Spacing, Styles} from '../Consts';
12
12
  import {Image} from '../Image';
13
13
  import {HeaderBackgroundProps, TitleCustomProps} from './types';
14
14
  import {Text} from '../Text';
@@ -26,7 +26,8 @@ const styles = StyleSheet.create({
26
26
  justifyContent: 'center',
27
27
  width: '100%',
28
28
  },
29
- avatar: {width: 36, height: 36, borderRadius: 18},
29
+ circle: {width: 36, height: 36, borderRadius: 18},
30
+ square: {width: 36, height: 36, borderRadius: Radius.XS},
30
31
  dotAvatar: {
31
32
  position: 'absolute',
32
33
  width: 12,
@@ -138,7 +139,7 @@ const HeaderBackground: React.FC<HeaderBackgroundProps> = ({
138
139
  <StatusBar
139
140
  barStyle={headerImage || theme.dark ? 'light-content' : 'dark-content'}
140
141
  />
141
- {headerImage && (
142
+ {headerImage || (
142
143
  <Image style={styles.headerBackground} source={{uri: headerImage}} />
143
144
  )}
144
145
  </Animated.View>
@@ -149,15 +150,17 @@ const HeaderCustom: React.FC<TitleCustomProps> = ({
149
150
  title,
150
151
  subTitle,
151
152
  image,
153
+ imageShape = 'circle',
152
154
  content,
153
155
  tintColor,
154
156
  dotColor,
155
157
  }) => {
158
+ const avatarStyle = imageShape == 'circle' ? styles.square : styles.square;
156
159
  const header = (
157
160
  <View style={Styles.row}>
158
161
  <View>
159
- <Image source={{uri: image}} style={styles.avatar} />
160
- {dotColor && (
162
+ <Image source={{uri: image}} style={avatarStyle} />
163
+ {dotColor || (
161
164
  <View style={[styles.dotAvatar, {backgroundColor: dotColor}]} />
162
165
  )}
163
166
  </View>
@@ -124,6 +124,7 @@ export type TitleCustomProps = {
124
124
  title?: string;
125
125
  subTitle?: string;
126
126
  image?: string;
127
+ imageShape?: 'circle' | 'square';
127
128
  dotColor?: string;
128
129
  tintColor?: string;
129
130
  content?: React.ReactNode;
@@ -0,0 +1,16 @@
1
+ import React, {FC, useContext} from 'react';
2
+ import {Animated} from 'react-native';
3
+ import styles from './styles';
4
+ import {DotProps} from './types';
5
+ import {ApplicationContext} from '../Navigation';
6
+
7
+ const Dot: FC<DotProps> = ({active, style}) => {
8
+ const {theme} = useContext(ApplicationContext);
9
+ const dotStyle = active
10
+ ? [styles.activeDot]
11
+ : [styles.inactiveDot, {backgroundColor: theme.colors.background.pressed}];
12
+
13
+ return <Animated.View style={[style, dotStyle]} />;
14
+ };
15
+
16
+ export default Dot;
@@ -0,0 +1,33 @@
1
+ import React, {FC, useContext} from 'react';
2
+ import {View} from 'react-native';
3
+ import {ChildPaginationProps} from './types';
4
+ import Dot from './Dot';
5
+ import styles from './styles';
6
+ import {Spacing} from '../Consts';
7
+ import {ApplicationContext} from '../Navigation';
8
+
9
+ const PaginationDot: FC<ChildPaginationProps> = ({
10
+ dataLength = 2,
11
+ activeIndex = 0,
12
+ }) => {
13
+ const {theme} = useContext(ApplicationContext);
14
+ const renderDots = () => {
15
+ const dots = [];
16
+ for (let i = 0; i < dataLength; i++) {
17
+ dots.push(
18
+ <Dot
19
+ key={`Dot${i}`}
20
+ style={[
21
+ i !== dataLength - 1 ? {marginRight: Spacing.XS} : {},
22
+ {backgroundColor: theme.colors.primary},
23
+ ]}
24
+ active={activeIndex === i}
25
+ />,
26
+ );
27
+ }
28
+ return dots;
29
+ };
30
+ return <View style={styles.paginationPinkContainer}>{renderDots()}</View>;
31
+ };
32
+
33
+ export default PaginationDot;
@@ -0,0 +1,22 @@
1
+ import React, {FC, useContext} from 'react';
2
+ import {View} from 'react-native';
3
+ import {ChildPaginationProps} from './types';
4
+ import styles from './styles';
5
+ import {Text} from '../Text';
6
+ import {ApplicationContext} from '../Navigation';
7
+
8
+ const PaginationNumber: FC<ChildPaginationProps> = ({
9
+ activeIndex = 0,
10
+ dataLength = 2,
11
+ }) => {
12
+ const {theme} = useContext(ApplicationContext);
13
+ return (
14
+ <View style={[styles.paginationNumberContainer]}>
15
+ <Text
16
+ color={theme.colors.background.surface}
17
+ typography={'label_default'}>{`${activeIndex + 1}/${dataLength}`}</Text>
18
+ </View>
19
+ );
20
+ };
21
+
22
+ export default PaginationNumber;
@@ -0,0 +1,88 @@
1
+ import React, {FC, useContext, useRef, useState} from 'react';
2
+ import {Animated, View} from 'react-native';
3
+ import {ScrollIndicatorProps} from './types';
4
+ import styles from './styles';
5
+ import {ApplicationContext} from '../Navigation';
6
+
7
+ const INDICATOR_WIDTH = 24;
8
+ const INDICATOR_CONTAINER_WIDTH = 72;
9
+ const PaginationScroll: FC<ScrollIndicatorProps> = ({
10
+ style,
11
+ children,
12
+ scrollViewRef,
13
+ }) => {
14
+ const {theme} = useContext(ApplicationContext);
15
+ const left = useRef(new Animated.Value(0)).current;
16
+ const [scrollViewWidth, setScrollViewWidth] = useState(0);
17
+ const [scrollContentWidth, setScrollContentWidth] = useState(0);
18
+
19
+ const translateX = () => {
20
+ if (scrollViewWidth && scrollContentWidth) {
21
+ const value = left.interpolate({
22
+ inputRange: [0, scrollContentWidth - scrollViewWidth],
23
+ outputRange: [0, INDICATOR_CONTAINER_WIDTH - INDICATOR_WIDTH],
24
+ extrapolate: 'clamp',
25
+ });
26
+ return {transform: [{translateX: value}]};
27
+ }
28
+ return {};
29
+ };
30
+
31
+ const renderScrollView = () => {
32
+ return (
33
+ <Animated.ScrollView
34
+ ref={scrollViewRef}
35
+ onScroll={Animated.event(
36
+ [
37
+ {
38
+ nativeEvent: {
39
+ contentOffset: {
40
+ x: left,
41
+ },
42
+ },
43
+ },
44
+ ],
45
+ {useNativeDriver: true},
46
+ )}
47
+ alwaysBounceHorizontal={false}
48
+ showsHorizontalScrollIndicator={false}
49
+ horizontal
50
+ style={styles.scrollView}
51
+ onContentSizeChange={width => {
52
+ setScrollContentWidth(width);
53
+ }}
54
+ onLayout={e => {
55
+ setScrollViewWidth(e.nativeEvent.layout.width);
56
+ }}>
57
+ {children}
58
+ </Animated.ScrollView>
59
+ );
60
+ };
61
+ const renderIndicator = () => {
62
+ return (
63
+ <View
64
+ style={[
65
+ styles.indicatorContainer,
66
+ {backgroundColor: theme.colors.background.pressed},
67
+ ]}>
68
+ <Animated.View
69
+ style={[
70
+ styles.indicator,
71
+ {
72
+ backgroundColor: theme.colors.primary,
73
+ },
74
+ translateX(),
75
+ ]}
76
+ />
77
+ </View>
78
+ );
79
+ };
80
+ return (
81
+ <View style={[style, styles.scrollContainer]}>
82
+ {renderScrollView()}
83
+ {renderIndicator()}
84
+ </View>
85
+ );
86
+ };
87
+
88
+ export default PaginationScroll;
@@ -0,0 +1,32 @@
1
+ import React, {FC, useContext} from 'react';
2
+ import {View} from 'react-native';
3
+ import {ChildPaginationProps} from './types';
4
+ import styles from './styles';
5
+ import Dot from './Dot';
6
+ import {Spacing} from '../Consts';
7
+ import {ApplicationContext} from '../Navigation';
8
+
9
+ const PaginationWhiteDot: FC<ChildPaginationProps> = ({
10
+ dataLength = 2,
11
+ activeIndex = 0,
12
+ }) => {
13
+ const {theme} = useContext(ApplicationContext);
14
+ const renderDots = () => {
15
+ const dots = [];
16
+ for (let i = 0; i < dataLength; i++) {
17
+ dots.push(
18
+ <Dot
19
+ style={[
20
+ i !== dataLength - 1 ? {marginRight: Spacing.XS} : {},
21
+ {backgroundColor: theme.colors.background.surface},
22
+ ]}
23
+ active={activeIndex === i}
24
+ />,
25
+ );
26
+ }
27
+ return dots;
28
+ };
29
+ return <View style={[styles.paginationWhiteContainer]}>{renderDots()}</View>;
30
+ };
31
+
32
+ export default PaginationWhiteDot;
@@ -0,0 +1,25 @@
1
+ import React, {FC} from 'react';
2
+ import {PaginationProps} from './types';
3
+ import PaginationWhiteDot from './PaginationWhiteDot';
4
+ import PaginationDot from './PaginationDot';
5
+ import PaginationNumber from './PaginationNumber';
6
+ import PaginationScroll from './PaginationScroll';
7
+
8
+ const Pagination: FC<PaginationProps> = props => {
9
+ const {type} = props;
10
+
11
+ const getComponent = (): any => {
12
+ switch (type) {
13
+ case 'black_white':
14
+ return <PaginationWhiteDot {...props} />;
15
+ case 'number':
16
+ return <PaginationNumber {...props} />;
17
+ default:
18
+ return <PaginationDot {...props} />;
19
+ }
20
+ };
21
+
22
+ return getComponent();
23
+ };
24
+
25
+ export {Pagination, PaginationScroll};
@@ -0,0 +1,47 @@
1
+ import {StyleSheet} from 'react-native';
2
+ import {Colors, Radius, Spacing} from '../Consts';
3
+
4
+ export default StyleSheet.create({
5
+ activeDot: {
6
+ height: 4,
7
+ width: 12,
8
+ borderRadius: Radius.XS,
9
+ },
10
+ inactiveDot: {
11
+ height: 4,
12
+ width: 4,
13
+ borderRadius: Radius.XS,
14
+ },
15
+ paginationPinkContainer: {
16
+ flexDirection: 'row',
17
+ },
18
+ paginationWhiteContainer: {
19
+ flexDirection: 'row',
20
+ padding: Spacing.XS,
21
+ borderRadius: Radius.S,
22
+ backgroundColor: Colors.black_20 + '33',
23
+ },
24
+ paginationNumberContainer: {
25
+ paddingHorizontal: Spacing.S,
26
+ backgroundColor: Colors.black_20 + '33',
27
+ borderRadius: Radius.L,
28
+ },
29
+ scrollContainer: {
30
+ alignItems: 'center',
31
+ width: '100%',
32
+ },
33
+ scrollView: {
34
+ marginBottom: Spacing.L,
35
+ },
36
+
37
+ indicator: {
38
+ width: 24,
39
+ height: 4,
40
+ borderRadius: Radius.XS,
41
+ },
42
+ indicatorContainer: {
43
+ width: 72,
44
+ height: 4,
45
+ borderRadius: Radius.XS,
46
+ },
47
+ });
@@ -0,0 +1,19 @@
1
+ import {ScrollView, ScrollViewProps, ViewStyle} from 'react-native';
2
+ import {Ref} from 'react';
3
+
4
+ export type PaginationProps = {
5
+ type?: 'default' | 'black_white' | 'number' | 'scroll';
6
+ activeIndex: number;
7
+ dataLength: number;
8
+ };
9
+
10
+ export type DotProps = {
11
+ active: boolean;
12
+ style: ViewStyle | ViewStyle[];
13
+ };
14
+
15
+ export interface ScrollIndicatorProps extends ScrollViewProps {
16
+ scrollViewRef?: Ref<ScrollView>;
17
+ }
18
+
19
+ export type ChildPaginationProps = Omit<PaginationProps, 'type'>;
@@ -36,11 +36,11 @@ const PopupNotify: React.FC<PopupNotifyProps> = ({
36
36
  const renderRow = () => {
37
37
  return (
38
38
  <View style={Styles.row}>
39
- {secondary?.title && (
39
+ {secondary?.title || (
40
40
  <>
41
41
  <View style={Styles.flex}>
42
42
  <Button
43
- title={secondary.title}
43
+ title={secondary?.title as string}
44
44
  type="text"
45
45
  size="medium"
46
46
  onPress={() => {
@@ -73,11 +73,11 @@ const PopupNotify: React.FC<PopupNotifyProps> = ({
73
73
  onAction(primary.onPress);
74
74
  }}
75
75
  />
76
- {secondary?.title && (
76
+ {secondary?.title || (
77
77
  <>
78
78
  <View style={styles.buttonSpace} />
79
79
  <Button
80
- title={secondary.title}
80
+ title={secondary?.title as string}
81
81
  type="text"
82
82
  size="medium"
83
83
  onPress={() => {
@@ -147,7 +147,7 @@ const PopupNotify: React.FC<PopupNotifyProps> = ({
147
147
  {description}
148
148
  </Text>
149
149
  </View>
150
- {information && (
150
+ {information || (
151
151
  <View style={styles.information}>
152
152
  <Text
153
153
  typography={'description_xs'}
package/Radio/styles.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import {StyleSheet} from 'react-native';
2
- import {Radius, Spacing} from '../Consts';
2
+ import {Radius} from '../Consts';
3
3
 
4
4
  export default StyleSheet.create({
5
5
  radio: {
@@ -7,5 +7,5 @@ export default StyleSheet.create({
7
7
  width: 20,
8
8
  borderRadius: Radius.M,
9
9
  },
10
- container: {flex: 1, backgroundColor: 'red'},
10
+ container: {flex: 1},
11
11
  });
@@ -2,9 +2,8 @@ import React, {useEffect, useMemo, useRef, useState} from 'react';
2
2
  import {Animated, Easing, Platform, StyleSheet, View} from 'react-native';
3
3
  import LinearGradient from 'react-native-linear-gradient';
4
4
  import {SkeletonTypes} from './types';
5
- import {Styles} from '../Consts';
5
+ import {Colors, Styles} from '../Consts';
6
6
  import styles from './styles';
7
- import {Colors} from '@momo-kits/foundation';
8
7
 
9
8
  const Skeleton: React.FC<SkeletonTypes> = ({style}) => {
10
9
  const [width, setWidth] = useState(0);
package/Tag/index.tsx ADDED
@@ -0,0 +1,74 @@
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
+
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
+ const sizeStyle =
55
+ size === 'large' ? styles.container : styles.mediumContainer;
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 style={styles.icon} size={16} source={icon} color={labelColor} />
66
+ )}
67
+ <Text color={labelColor} typography={'label_s'}>
68
+ {label}
69
+ </Text>
70
+ </View>
71
+ );
72
+ };
73
+
74
+ 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,10 @@
1
+ import {ViewStyle} from 'react-native';
2
+
3
+ export type TagProps = {
4
+ label: string;
5
+ size?: 'medium' | 'large';
6
+ icon?: string;
7
+ color?: 'default' | 'orange' | 'green' | 'red' | 'blue' | 'grey';
8
+ style?: ViewStyle;
9
+ customColor?: string;
10
+ };
package/index.ts CHANGED
@@ -32,3 +32,7 @@ export * from './Switch';
32
32
  export * from './Switch/types';
33
33
  export * from './Input';
34
34
  export * from './Divider';
35
+ export * from './Tag';
36
+ export * from './Tag/types';
37
+ export * from './Pagination';
38
+ export * from './Pagination/types';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@momo-kits/foundation",
3
- "version": "1.0.14",
3
+ "version": "1.0.16",
4
4
  "description": "React Native Component Kits",
5
5
  "main": "index.ts",
6
6
  "scripts": {