@momo-kits/foundation 0.74.2-react-native.1

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 (105) hide show
  1. package/Application/BottomTab.tsx +120 -0
  2. package/Application/Components.tsx +534 -0
  3. package/Application/ModalScreen.tsx +268 -0
  4. package/Application/Navigation.ts +50 -0
  5. package/Application/NavigationContainer.tsx +120 -0
  6. package/Application/Navigator.ts +131 -0
  7. package/Application/StackScreen.tsx +71 -0
  8. package/Application/index.ts +41 -0
  9. package/Application/types.ts +216 -0
  10. package/Application/utils.tsx +151 -0
  11. package/Assets/DotAnimation.json +256 -0
  12. package/Assets/SpinnerAnimation.json +1027 -0
  13. package/Assets/icon.json +4031 -0
  14. package/Assets/icon_bank.json +506 -0
  15. package/Assets/language.json +202 -0
  16. package/Badge/Badge.tsx +56 -0
  17. package/Badge/BadgeDot.tsx +11 -0
  18. package/Badge/BadgeRibbon.tsx +125 -0
  19. package/Badge/Shape.tsx +29 -0
  20. package/Badge/index.tsx +7 -0
  21. package/Badge/styles.ts +58 -0
  22. package/Badge/types.ts +63 -0
  23. package/Button/index.tsx +310 -0
  24. package/Button/styles.ts +60 -0
  25. package/CheckBox/index.tsx +65 -0
  26. package/CheckBox/styles.ts +15 -0
  27. package/CheckBox/types.ts +38 -0
  28. package/Consts/colors+spacing+radius.ts +218 -0
  29. package/Consts/index.ts +4 -0
  30. package/Consts/styles.ts +52 -0
  31. package/Consts/theme.ts +125 -0
  32. package/Divider/index.tsx +21 -0
  33. package/Icon/index.tsx +41 -0
  34. package/Icon/types.ts +27 -0
  35. package/IconButton/index.tsx +139 -0
  36. package/IconButton/styles.ts +19 -0
  37. package/Image/index.tsx +83 -0
  38. package/Image/styles.ts +5 -0
  39. package/Image/types.ts +5 -0
  40. package/Input/Input.tsx +192 -0
  41. package/Input/InputDropDown.tsx +114 -0
  42. package/Input/InputMoney.tsx +163 -0
  43. package/Input/InputOTP.tsx +235 -0
  44. package/Input/InputSearch.tsx +151 -0
  45. package/Input/InputTextArea.tsx +159 -0
  46. package/Input/common.tsx +129 -0
  47. package/Input/index.tsx +251 -0
  48. package/Input/styles.ts +160 -0
  49. package/Input/utils.ts +69 -0
  50. package/Layout/Card.tsx +180 -0
  51. package/Layout/GridSystem.tsx +136 -0
  52. package/Layout/Item.tsx +56 -0
  53. package/Layout/ItemList.tsx +55 -0
  54. package/Layout/ItemSectionList.tsx +39 -0
  55. package/Layout/Screen.tsx +355 -0
  56. package/Layout/Section.tsx +179 -0
  57. package/Layout/index.ts +29 -0
  58. package/Layout/styles.ts +97 -0
  59. package/Layout/types.ts +23 -0
  60. package/Layout/utils.ts +55 -0
  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 +28 -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/Dot.tsx +16 -0
  70. package/Pagination/PaginationDot.tsx +38 -0
  71. package/Pagination/PaginationNumber.tsx +24 -0
  72. package/Pagination/PaginationScroll.tsx +88 -0
  73. package/Pagination/PaginationWhiteDot.tsx +35 -0
  74. package/Pagination/index.tsx +25 -0
  75. package/Pagination/styles.ts +50 -0
  76. package/Pagination/types.ts +40 -0
  77. package/Popup/PopupNotify.tsx +266 -0
  78. package/Popup/PopupPromotion.tsx +120 -0
  79. package/Popup/index.tsx +4 -0
  80. package/Popup/types.ts +87 -0
  81. package/Radio/index.tsx +64 -0
  82. package/Radio/styles.ts +11 -0
  83. package/Radio/types.ts +38 -0
  84. package/Skeleton/index.tsx +72 -0
  85. package/Skeleton/styles.ts +5 -0
  86. package/Skeleton/types.ts +6 -0
  87. package/Switch/index.tsx +37 -0
  88. package/Switch/styles.ts +23 -0
  89. package/Switch/types.ts +26 -0
  90. package/Tag/index.tsx +79 -0
  91. package/Tag/styles.ts +24 -0
  92. package/Tag/types.ts +36 -0
  93. package/Text/index.tsx +110 -0
  94. package/Text/styles.ts +73 -0
  95. package/Text/types.ts +34 -0
  96. package/Text/utils.ts +14 -0
  97. package/Title/index.tsx +132 -0
  98. package/Title/styles.ts +52 -0
  99. package/Title/types.ts +52 -0
  100. package/code-scanner.js +51 -0
  101. package/index.ts +51 -0
  102. package/package.json +36 -0
  103. package/publish.sh +23 -0
  104. package/tsconfig.json +24 -0
  105. package/verify.js +44 -0
@@ -0,0 +1,37 @@
1
+ import React, {FC} from 'react';
2
+ import {TouchableOpacity, View} from 'react-native';
3
+ import {SwitchProps} from './types';
4
+ import styles from './styles';
5
+ import {Colors} from '../Consts';
6
+
7
+ const Switch: FC<SwitchProps> = props => {
8
+ const {value, onChange, disabled, style} = props;
9
+ const circleBackgroundColor = value ? Colors.black_01 : Colors.black_03;
10
+ const circleAlign = value ? 'flex-end' : 'flex-start';
11
+
12
+ let backgroundColor = value ? Colors.green_03 : Colors.black_07;
13
+ if (disabled) {
14
+ backgroundColor = value ? Colors.green_09 : Colors.black_05;
15
+ }
16
+
17
+ return (
18
+ <TouchableOpacity
19
+ disabled={disabled}
20
+ onPress={() => onChange?.(!value)}
21
+ style={[
22
+ style,
23
+ styles.container,
24
+ {backgroundColor, alignItems: circleAlign},
25
+ ]}>
26
+ <View style={[styles.circle, {backgroundColor: circleBackgroundColor}]}>
27
+ <View style={[styles.circleSmall, {backgroundColor}]} />
28
+ </View>
29
+ </TouchableOpacity>
30
+ );
31
+ };
32
+
33
+ Switch.defaultProps = {
34
+ value: false,
35
+ disabled: false,
36
+ };
37
+ 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_medium'}>
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
+ };
package/Text/index.tsx ADDED
@@ -0,0 +1,110 @@
1
+ import React, {useContext} from 'react';
2
+ import {Text as RNText, TextProps as RNTextProps} from 'react-native';
3
+ import styles from './styles';
4
+ import {Typography, TypographyWeight} from './types';
5
+ import {ApplicationContext} from '../Application';
6
+ import {scaleSize} from './utils';
7
+
8
+ const SFProText: TypographyWeight = {
9
+ 100: 'Thin',
10
+ 200: 'Ultralight',
11
+ 300: 'Light',
12
+ 400: 'Regular',
13
+ 500: 'Medium',
14
+ 600: 'Semibold',
15
+ 700: 'Bold',
16
+ 800: 'Heavy',
17
+ 900: 'Black',
18
+ normal: 'Regular',
19
+ bold: 'Bold',
20
+ };
21
+
22
+ const AlegreyaSans: TypographyWeight = {
23
+ 100: 'Thin',
24
+ 200: 'Thin',
25
+ 300: 'Thin',
26
+ 400: 'Regular',
27
+ 500: 'Medium',
28
+ 600: 'Medium',
29
+ 700: 'Bold',
30
+ 800: 'Black',
31
+ 900: 'Black',
32
+ normal: 'Regular',
33
+ bold: 'Bold',
34
+ };
35
+
36
+ const FontStyle: {[key: string]: string} = {
37
+ italic: 'Italic',
38
+ normal: '',
39
+ };
40
+
41
+ export interface TextProps extends RNTextProps {
42
+ /**
43
+ * Represents the typography style applied to the Text component.
44
+ * It defines the appearance of the text in terms of font size, weight, line height etc.
45
+ */
46
+ typography: Typography;
47
+
48
+ /**
49
+ * Optional. Represents the color of the text in the Text component.
50
+ * It can be any valid color string (e.g., hex, rgb, rgba, etc.).
51
+ */
52
+ color?: string;
53
+ }
54
+ const Text: React.FC<TextProps> = ({
55
+ typography,
56
+ color,
57
+ children,
58
+ style,
59
+ ...rest
60
+ }) => {
61
+ const {theme} = useContext(ApplicationContext);
62
+
63
+ const getTypoStyle = (typo: Typography) => {
64
+ const styleSheet: {
65
+ [key: string]: any;
66
+ } = styles;
67
+ const typoStyle = styleSheet[typo] ?? styleSheet.paragraph_default;
68
+ const {fontWeight, fontSize, fontStyle, lineHeight} = typoStyle;
69
+ const style = FontStyle[fontStyle ?? 'normal'];
70
+ let fontFamily: string;
71
+
72
+ switch (theme.font) {
73
+ case 'SFProText': {
74
+ fontFamily = `${theme.font}-${SFProText[fontWeight]}${style}`;
75
+ break;
76
+ }
77
+ case 'AlegreyaSans': {
78
+ fontFamily = `${theme.font}-${AlegreyaSans[fontWeight]}${style}`;
79
+ break;
80
+ }
81
+ default: {
82
+ fontFamily = `SFProText-${SFProText[fontWeight]}${style}`;
83
+ }
84
+ }
85
+
86
+ return {
87
+ ...typoStyle,
88
+ fontFamily,
89
+ fontSize: scaleSize(fontSize),
90
+ lineHeight: scaleSize(lineHeight),
91
+ fontStyle,
92
+ fontWeight,
93
+ };
94
+ };
95
+
96
+ const textStyle = getTypoStyle(typography);
97
+ return (
98
+ <RNText
99
+ {...rest}
100
+ style={[style, textStyle, {color: color ?? theme.colors.text.default}]}>
101
+ {children ?? ''}
102
+ </RNText>
103
+ );
104
+ };
105
+
106
+ Text.defaultProps = {
107
+ typography: 'body_default_regular',
108
+ };
109
+
110
+ export {Text, scaleSize};
package/Text/styles.ts ADDED
@@ -0,0 +1,73 @@
1
+ export default {
2
+ headline_default_bold: {fontSize: 24, lineHeight: 32, fontWeight: '700'},
3
+ header_m_bold: {fontSize: 18, lineHeight: 28, fontWeight: '700'},
4
+ header_default_bold: {fontSize: 16, lineHeight: 22, fontWeight: '700'},
5
+ header_s_semibold: {fontSize: 14, lineHeight: 20, fontWeight: '600'},
6
+ header_xs_semibold: {fontSize: 12, lineHeight: 16, fontWeight: '600'},
7
+ body_default_regular: {fontSize: 14, lineHeight: 20, fontWeight: '400'},
8
+ body_regularstrikethrought: {
9
+ fontSize: 14,
10
+ lineHeight: 20,
11
+ fontWeight: '400',
12
+ textDecorationLine: 'line-through',
13
+ },
14
+ description_default_regular: {
15
+ fontSize: 12,
16
+ lineHeight: 16,
17
+ fontWeight: '400',
18
+ },
19
+ description_default_regularstrikethrought: {
20
+ fontSize: 12,
21
+ lineHeight: 16,
22
+ fontWeight: '400',
23
+ textDecorationLine: 'line-through',
24
+ },
25
+ description_xs_regular: {fontSize: 10, lineHeight: 14, fontWeight: '400'},
26
+ description_xs_regularstrikethrought: {
27
+ fontSize: 10,
28
+ lineHeight: 14,
29
+ fontWeight: '400',
30
+ textDecorationLine: 'line-through',
31
+ },
32
+ label_default_medium: {fontSize: 14, lineHeight: 20, fontWeight: '500'},
33
+ label_s_medium: {fontSize: 12, lineHeight: 16, fontWeight: '500'},
34
+ label_xs_medium: {fontSize: 10, lineHeight: 14, fontWeight: '500'},
35
+ action_default_bold: {fontSize: 16, lineHeight: 22, fontWeight: '700'},
36
+ action_s_bold: {fontSize: 14, lineHeight: 20, fontWeight: '700'},
37
+ action_xs_bold: {fontSize: 12, lineHeight: 16, fontWeight: '700'},
38
+ action_xxs_bold: {fontSize: 10, lineHeight: 14, fontWeight: '700'},
39
+ /**non-support**/
40
+ headline_default: {
41
+ fontSize: 28,
42
+ lineHeight: 34,
43
+ fontWeight: '600',
44
+ },
45
+ headline_s: {fontSize: 24, lineHeight: 32, fontWeight: '600'},
46
+ headline_l: {fontSize: 32, lineHeight: 36, fontWeight: '600'},
47
+ headline_xl: {fontSize: 36, lineHeight: 44, fontWeight: '600'},
48
+ title_default: {fontSize: 20, lineHeight: 28, fontWeight: '700'},
49
+ title_xs: {fontSize: 16, lineHeight: 22, fontWeight: '700'},
50
+ title_s: {fontSize: 18, lineHeight: 28, fontWeight: '700'},
51
+ header_default: {fontSize: 15, lineHeight: 22, fontWeight: '600'},
52
+ header_xs: {fontSize: 12, lineHeight: 16, fontWeight: '600'},
53
+ header_s: {fontSize: 14, lineHeight: 20, fontWeight: '600'},
54
+ paragraph_default: {fontSize: 15, lineHeight: 22, fontWeight: '400'},
55
+ paragraph_bold: {fontSize: 15, lineHeight: 22, fontWeight: '700'},
56
+ paragraph_italic: {
57
+ fontSize: 15,
58
+ lineHeight: 22,
59
+ fontWeight: '400',
60
+ fontStyle: 'italic',
61
+ },
62
+ description_default: {fontSize: 14, lineHeight: 20, fontWeight: '400'},
63
+ description_xs: {fontSize: 10, lineHeight: 14, fontWeight: '400'},
64
+ description_s: {fontSize: 12, lineHeight: 16, fontWeight: '400'},
65
+ label_default: {fontSize: 14, lineHeight: 20, fontWeight: '500'},
66
+ label_xxs: {fontSize: 8, lineHeight: 12, fontWeight: '500'},
67
+ label_xs: {fontSize: 10, lineHeight: 14, fontWeight: '500'},
68
+ label_s: {fontSize: 12, lineHeight: 16, fontWeight: '500'},
69
+ action_default: {fontSize: 16, lineHeight: 22, fontWeight: '700'},
70
+ action_xxs: {fontSize: 10, lineHeight: 14, fontWeight: '700'},
71
+ action_xs: {fontSize: 12, lineHeight: 16, fontWeight: '700'},
72
+ action_s: {fontSize: 15, lineHeight: 22, fontWeight: '700'},
73
+ };
package/Text/types.ts ADDED
@@ -0,0 +1,34 @@
1
+ export type TypographyWeight = {
2
+ [key: string]: string;
3
+ 100: string;
4
+ 200: string;
5
+ 300: string;
6
+ 400: string;
7
+ 500: string;
8
+ 600: string;
9
+ 700: string;
10
+ 800: string;
11
+ 900: string;
12
+ normal: string;
13
+ bold: string;
14
+ };
15
+
16
+ export type Typography =
17
+ | 'headline_default_bold'
18
+ | 'header_m_bold'
19
+ | 'header_default_bold'
20
+ | 'header_s_semibold'
21
+ | 'header_xs_semibold'
22
+ | 'body_default_regular'
23
+ | 'body_regularstrikethrought'
24
+ | 'description_default_regular'
25
+ | 'description_default_regularstrikethrought'
26
+ | 'description_xs_regular'
27
+ | 'description_xs_regularstrikethrought'
28
+ | 'label_default_medium'
29
+ | 'label_s_medium'
30
+ | 'label_xs_medium'
31
+ | 'action_default_bold'
32
+ | 'action_s_bold'
33
+ | 'action_xs_bold'
34
+ | 'action_xxs_bold';
package/Text/utils.ts ADDED
@@ -0,0 +1,14 @@
1
+ import {Dimensions} from 'react-native';
2
+
3
+ const deviceWidth = Dimensions.get('window').width;
4
+ const DEFAULT_SCREEN_SIZE = 375;
5
+ const scaleSize = (size: number) => {
6
+ const scaleRate = deviceWidth / DEFAULT_SCREEN_SIZE;
7
+
8
+ if (scaleRate > 1) {
9
+ return Math.min(Math.round(size * scaleRate), size + 3);
10
+ }
11
+
12
+ return size;
13
+ };
14
+ export {scaleSize};
@@ -0,0 +1,132 @@
1
+ import React, {FC, useContext, useState} from 'react';
2
+ import {
3
+ LayoutChangeEvent,
4
+ NativeSyntheticEvent,
5
+ Text as RNText,
6
+ TextLayoutEventData,
7
+ TouchableOpacity,
8
+ View,
9
+ } from 'react-native';
10
+ import {TitleProps} from './types';
11
+ import {Icon} from '../Icon';
12
+ import styles from './styles';
13
+ import {ApplicationContext} from '../Application';
14
+ import {Colors, Spacing} from '../Consts';
15
+ import {scaleSize, Text} from '../Text';
16
+
17
+ const Title: FC<TitleProps> = ({
18
+ size = 'large',
19
+ type = 'section',
20
+ onPressAction,
21
+ actionTitle,
22
+ title = 'Title',
23
+ titleFlex = true,
24
+ showAction = true,
25
+ icon,
26
+ description,
27
+ usePadding = true,
28
+ }) => {
29
+ const {theme} = useContext(ApplicationContext);
30
+ const [containerWidth, setContainerWidth] = useState(0);
31
+ const [textLines, setTextLines] = useState(0);
32
+ const typeStyle =
33
+ type === 'screen' ? styles.screen : styles[`${type}_${size}`];
34
+ const titleWeight = type === 'screen' ? 'Semibold' : 'Bold';
35
+ const marginStyle =
36
+ type === 'section' && usePadding ? {marginTop: Spacing.S} : {};
37
+ const numberOfLines = type === 'section' ? 1 : 2;
38
+
39
+ const renderAction = () => {
40
+ return !!actionTitle && titleFlex ? (
41
+ <TouchableOpacity onPress={onPressAction}>
42
+ <Text typography={'action_s_bold'} color={theme.colors.primary}>
43
+ {actionTitle}
44
+ </Text>
45
+ </TouchableOpacity>
46
+ ) : (
47
+ <TouchableOpacity
48
+ style={[
49
+ {backgroundColor: theme.colors.primary + '0F'},
50
+ styles.actionIcon,
51
+ {width: scaleSize(22), height: scaleSize(22)},
52
+ ]}
53
+ onPress={onPressAction}>
54
+ <Icon
55
+ size={scaleSize(22)}
56
+ color={theme.colors.primary}
57
+ source={'arrow_chevron_right_small'}
58
+ />
59
+ </TouchableOpacity>
60
+ );
61
+ };
62
+
63
+ const renderSemiAction = () => {
64
+ if (textLines > 1) return null;
65
+ return (
66
+ <TouchableOpacity
67
+ style={[
68
+ {backgroundColor: Colors.black_06},
69
+ styles.actionIcon,
70
+ {width: scaleSize(18), height: scaleSize(18)},
71
+ ]}
72
+ onPress={onPressAction}>
73
+ <Icon
74
+ size={scaleSize(18)}
75
+ color={theme.colors.text.default}
76
+ source={'arrow_chevron_right_small'}
77
+ />
78
+ </TouchableOpacity>
79
+ );
80
+ };
81
+ const onLayout = (e: LayoutChangeEvent) => {
82
+ setContainerWidth(e.nativeEvent.layout.width);
83
+ };
84
+
85
+ const onTextLayout = (e: NativeSyntheticEvent<TextLayoutEventData>) => {
86
+ setTextLines(e.nativeEvent.lines.length);
87
+ };
88
+
89
+ return (
90
+ <View onLayout={onLayout} style={[styles.wrapper, marginStyle]}>
91
+ {!!icon && type !== 'screen' && (
92
+ <Icon style={styles.icon} source={icon} />
93
+ )}
94
+ <View style={{flex: 1, flexDirection: 'row'}}>
95
+ <View style={styles.textContent}>
96
+ <View
97
+ style={{
98
+ flexDirection: 'row',
99
+ maxWidth: containerWidth - scaleSize(22),
100
+ }}>
101
+ <RNText
102
+ onTextLayout={onTextLayout}
103
+ numberOfLines={numberOfLines}
104
+ style={[
105
+ typeStyle,
106
+ {
107
+ fontFamily: `${theme.font}-${titleWeight}`,
108
+ color: theme.colors.text.default,
109
+ marginRight: Spacing.S,
110
+ },
111
+ ]}>
112
+ {title}
113
+ </RNText>
114
+ {!titleFlex && renderSemiAction()}
115
+ </View>
116
+ {!!description && type !== 'screen' && (
117
+ <Text
118
+ numberOfLines={1}
119
+ typography={'description_default_regular'}
120
+ color={theme.colors.text.secondary}>
121
+ {description}
122
+ </Text>
123
+ )}
124
+ </View>
125
+ {showAction && titleFlex && type !== 'screen' && renderAction()}
126
+ </View>
127
+ </View>
128
+ );
129
+ };
130
+
131
+ export {Title};
132
+ export type {TitleProps};
@@ -0,0 +1,52 @@
1
+ import {StyleSheet} from 'react-native';
2
+ import {scaleSize} from '../Text';
3
+ import {Radius, Spacing} from '../Consts';
4
+
5
+ export default StyleSheet.create({
6
+ card_small: {
7
+ fontSize: scaleSize(14),
8
+ lineHeight: scaleSize(20),
9
+ },
10
+ card_medium: {
11
+ fontSize: scaleSize(16),
12
+ lineHeight: scaleSize(22),
13
+ },
14
+ card_large: {
15
+ fontSize: scaleSize(18),
16
+ lineHeight: scaleSize(26),
17
+ },
18
+ section_medium: {
19
+ fontSize: scaleSize(20),
20
+ lineHeight: scaleSize(28),
21
+ },
22
+ section_small: {
23
+ fontSize: scaleSize(16),
24
+ lineHeight: scaleSize(22),
25
+ },
26
+ section_large: {
27
+ fontSize: scaleSize(24),
28
+ lineHeight: scaleSize(34),
29
+ },
30
+ screen: {
31
+ fontSize: scaleSize(36),
32
+ lineHeight: scaleSize(44),
33
+ },
34
+ actionIcon: {
35
+ borderRadius: Radius.M,
36
+ alignItems: 'center',
37
+ justifyContent: 'center',
38
+ },
39
+ icon: {
40
+ marginRight: Spacing.S,
41
+ borderRadius: Radius.XS,
42
+ },
43
+ wrapper: {
44
+ width: '100%',
45
+ flexDirection: 'row',
46
+ alignItems: 'center',
47
+ },
48
+ textContent: {
49
+ marginRight: Spacing.S,
50
+ flex: 1,
51
+ },
52
+ });
package/Title/types.ts ADDED
@@ -0,0 +1,52 @@
1
+ export type TitleProps = {
2
+ /**
3
+ * Optional. Defines the type of Title component.
4
+ * 'screen' - Used for screen titles.
5
+ * 'section' - Used for section titles within a screen.
6
+ * 'card' - Used for titles within a card component.
7
+ */
8
+ type?: 'screen' | 'section' | 'card';
9
+
10
+ /**
11
+ * Required. The text of the title.
12
+ */
13
+ title: string;
14
+
15
+ /**
16
+ * Optional. A description or subtitle that appears below the title.
17
+ */
18
+ description?: string;
19
+
20
+ /**
21
+ * Optional. Defines the size of the Title component.
22
+ * 'large' - A larger, more prominent title.
23
+ * 'small' - A smaller, less prominent title.
24
+ */
25
+ size?: 'large' | 'medium' | 'small';
26
+
27
+ /**
28
+ * Optional. Represents the name or key of the icon to be displayed alongside the title.
29
+ */
30
+ icon?: string;
31
+
32
+ /**
33
+ * Optional. If `true`, the title will be flexible in its container, adjusting its width dynamically.
34
+ */
35
+ titleFlex?: boolean;
36
+
37
+ /**
38
+ * Optional. Text for an action button associated with the title.
39
+ */
40
+ actionTitle?: string;
41
+
42
+ /**
43
+ * Optional. Function to be called when the action associated with the title is pressed.
44
+ */
45
+ onPressAction?: () => void;
46
+
47
+ /**
48
+ * Optional. If `true`, an action button or icon is displayed alongside the title.
49
+ */
50
+ showAction?: boolean;
51
+ usePadding?: boolean;
52
+ };