@momo-kits/foundation 0.81.1-beta.6 → 0.81.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 (77) hide show
  1. package/Application/BottomSheet.tsx +225 -0
  2. package/Application/BottomTab/BottomTabBar.tsx +291 -0
  3. package/Application/BottomTab/index.tsx +138 -0
  4. package/Application/Components.tsx +274 -211
  5. package/Application/ModalScreen.tsx +10 -226
  6. package/Application/Navigation.ts +17 -6
  7. package/Application/NavigationContainer.tsx +66 -65
  8. package/Application/Navigator.ts +106 -53
  9. package/Application/StackScreen.tsx +123 -28
  10. package/Application/index.ts +15 -9
  11. package/Application/types.ts +55 -31
  12. package/Application/utils.tsx +36 -6
  13. package/Assets/icon.json +83 -5
  14. package/Assets/icon_bank.json +506 -0
  15. package/Assets/language.json +3 -1
  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 +60 -24
  24. package/Button/styles.ts +19 -0
  25. package/CheckBox/index.tsx +37 -27
  26. package/CheckBox/types.ts +5 -3
  27. package/Consts/colors+spacing+radius.ts +17 -3
  28. package/Icon/index.tsx +14 -9
  29. package/Icon/types.ts +4 -3
  30. package/IconButton/index.tsx +24 -15
  31. package/Image/index.tsx +61 -55
  32. package/Image/styles.ts +1 -9
  33. package/Image/types.ts +5 -1
  34. package/Input/Input.tsx +102 -25
  35. package/Input/InputDropDown.tsx +32 -23
  36. package/Input/InputMoney.tsx +67 -18
  37. package/Input/InputOTP.tsx +194 -148
  38. package/Input/InputSearch.tsx +72 -36
  39. package/Input/InputTextArea.tsx +33 -18
  40. package/Input/common.tsx +25 -16
  41. package/Input/index.tsx +62 -16
  42. package/Input/styles.ts +5 -8
  43. package/Layout/Card.tsx +20 -11
  44. package/Layout/FloatingButton.tsx +168 -0
  45. package/Layout/GridSystem.tsx +1 -2
  46. package/Layout/Item.tsx +0 -1
  47. package/Layout/ItemList.tsx +39 -40
  48. package/Layout/ItemSectionList.tsx +39 -0
  49. package/Layout/Screen.tsx +151 -65
  50. package/Layout/Section.tsx +17 -19
  51. package/Layout/index.ts +2 -1
  52. package/Layout/styles.ts +20 -15
  53. package/Layout/types.ts +2 -5
  54. package/Layout/utils.ts +2 -2
  55. package/Pagination/PaginationNumber.tsx +1 -1
  56. package/Pagination/PaginationScroll.tsx +0 -1
  57. package/Popup/PopupNotify.tsx +105 -37
  58. package/Popup/PopupPromotion.tsx +44 -9
  59. package/Popup/types.ts +12 -9
  60. package/Radio/index.tsx +35 -21
  61. package/Radio/types.ts +5 -3
  62. package/Skeleton/index.tsx +1 -1
  63. package/Switch/index.tsx +32 -19
  64. package/Switch/types.ts +5 -3
  65. package/Tag/index.tsx +2 -4
  66. package/Text/index.tsx +26 -6
  67. package/Text/styles.ts +38 -0
  68. package/Text/types.ts +25 -13
  69. package/Title/index.tsx +172 -63
  70. package/Title/styles.ts +48 -15
  71. package/Title/types.ts +16 -47
  72. package/code-scanner.js +131 -39
  73. package/index.ts +9 -0
  74. package/migrate_typo.js +56 -0
  75. package/package.json +8 -8
  76. package/verify.js +24 -6
  77. package/Application/BottomTab.tsx +0 -65
@@ -1,4 +1,10 @@
1
- import React, {forwardRef, useContext, useRef, useState} from 'react';
1
+ import React, {
2
+ forwardRef,
3
+ useContext,
4
+ useImperativeHandle,
5
+ useRef,
6
+ useState,
7
+ } from 'react';
2
8
  import {
3
9
  NativeSyntheticEvent,
4
10
  TextInput,
@@ -6,7 +12,8 @@ import {
6
12
  TouchableOpacity,
7
13
  View,
8
14
  } from 'react-native';
9
- import styles from './styles';
15
+ import {ApplicationContext} from '../Application';
16
+ import {Icon} from '../Icon';
10
17
  import {Text} from '../Text';
11
18
  import {
12
19
  DEFAULT_HEIGHT,
@@ -16,8 +23,7 @@ import {
16
23
  MAX_LENGTH,
17
24
  } from './common';
18
25
  import {InputTextAreaProps} from './index';
19
- import {Icon} from '../Icon';
20
- import {ApplicationContext} from '../Application';
26
+ import styles from './styles';
21
27
 
22
28
  const InputTextArea = forwardRef(
23
29
  (
@@ -29,15 +35,17 @@ const InputTextArea = forwardRef(
29
35
  floatingValue,
30
36
  onFocus,
31
37
  onBlur,
32
- disabled,
38
+ disabled = false,
33
39
  value,
34
40
  defaultValue,
35
41
  height,
36
42
  placeholder,
37
- maxLength,
43
+ maxLength = MAX_LENGTH,
38
44
  required,
39
45
  errorSpacing,
40
46
  style,
47
+ accessibilityLabel,
48
+ hintText,
41
49
  ...props
42
50
  }: InputTextAreaProps,
43
51
  ref,
@@ -45,8 +53,7 @@ const InputTextArea = forwardRef(
45
53
  const {theme} = useContext(ApplicationContext);
46
54
  const [focused, setFocused] = useState(false);
47
55
  const [inputValue, setInputValue] = useState(defaultValue ?? '');
48
- const inputRef = (ref as React.RefObject<TextInput>) ?? useRef<TextInput>();
49
- const accessibilityLabel = `InputTextArea/${floatingValue ?? placeholder}`;
56
+ const inputRef = useRef<TextInput | null>(null);
50
57
 
51
58
  const onClearText = () => {
52
59
  inputRef?.current?.clear();
@@ -68,10 +75,21 @@ const InputTextArea = forwardRef(
68
75
  onBlur?.(e);
69
76
  };
70
77
 
78
+ useImperativeHandle(ref, () => {
79
+ return {
80
+ clear: onClearText,
81
+ focus: () => inputRef.current?.focus(),
82
+ blur: () => inputRef.current?.blur(),
83
+ setText: (text: string) => _onChangeText(text),
84
+ };
85
+ });
86
+
71
87
  const renderCountingView = () => {
72
88
  return (
73
89
  <View style={styles.countingView}>
74
- <Text color={theme.colors.text.hint} typography={'description_xs'}>
90
+ <Text
91
+ color={theme.colors.text.hint}
92
+ typography={'description_xs_regular'}>
75
93
  {`${inputValue.length}/${maxLength}`}
76
94
  </Text>
77
95
  </View>
@@ -108,7 +126,6 @@ const InputTextArea = forwardRef(
108
126
  <View style={styles.textAreaView}>
109
127
  <TextInput
110
128
  {...props}
111
- accessibilityLabel={accessibilityLabel}
112
129
  ref={inputRef}
113
130
  editable={!disabled}
114
131
  textAlignVertical="top"
@@ -148,18 +165,16 @@ const InputTextArea = forwardRef(
148
165
  };
149
166
 
150
167
  return (
151
- <View
152
- style={[style, styles.wrapper]}
153
- accessibilityLabel={accessibilityLabel}>
168
+ <View style={[style, styles.wrapper]}>
154
169
  {renderInputView()}
155
- <ErrorView errorMessage={errorMessage} errorSpacing={errorSpacing} />
170
+ <ErrorView
171
+ errorMessage={errorMessage}
172
+ errorSpacing={errorSpacing}
173
+ hintText={hintText}
174
+ />
156
175
  </View>
157
176
  );
158
177
  },
159
178
  );
160
179
 
161
- InputTextArea.defaultProps = {
162
- maxLength: MAX_LENGTH,
163
- };
164
-
165
180
  export default InputTextArea;
package/Input/common.tsx CHANGED
@@ -1,11 +1,11 @@
1
- import {View, ViewStyle} from 'react-native';
2
- import styles from './styles';
3
- import {scaleSize, Text} from '../Text';
4
1
  import React, {FC, useContext} from 'react';
2
+ import {View, ViewStyle} from 'react-native';
5
3
  import {ApplicationContext} from '../Application';
6
- import {Icon} from '../Icon';
7
- import {Styles} from '../Consts';
8
4
  import {Theme} from '../Application/types';
5
+ import {Styles} from '../Consts';
6
+ import {Icon} from '../Icon';
7
+ import {scaleSize, Text} from '../Text';
8
+ import styles from './styles';
9
9
 
10
10
  type FloatingViewProps = {
11
11
  floatingValue?: string;
@@ -48,24 +48,31 @@ export const getSizeStyle = (size?: 'small' | 'large') => {
48
48
  }
49
49
  return styles.container;
50
50
  };
51
- export const ErrorView: FC<{errorMessage?: string; errorSpacing?: boolean}> = ({
52
- errorMessage,
53
- errorSpacing,
54
- }) => {
51
+ export const ErrorView: FC<{
52
+ errorMessage?: string;
53
+ errorSpacing?: boolean;
54
+ hintText?: string;
55
+ }> = ({errorMessage, errorSpacing, hintText}) => {
55
56
  const {theme} = useContext(ApplicationContext);
56
57
  const errorColor = theme.colors.error.primary;
57
- if (errorMessage) {
58
+ const hintColor = theme.colors.text.hint;
59
+ const hintTextDefault = hintText ?? 'Không thể chỉnh sửa';
60
+ if (errorMessage || hintText) {
58
61
  return (
59
62
  <View style={styles.errorView}>
60
63
  <View style={styles.errorIcon}>
61
- <Icon color={errorColor} source="ic_error" size={16} />
64
+ <Icon
65
+ color={errorMessage ? errorColor : hintColor}
66
+ source="ic_error"
67
+ size={16}
68
+ />
62
69
  </View>
63
70
  <Text
64
71
  style={Styles.flex}
65
- color={errorColor}
72
+ color={errorMessage ? errorColor : hintColor}
66
73
  numberOfLines={2}
67
- typography={'description_s'}>
68
- {errorMessage}
74
+ typography={'description_default_regular'}>
75
+ {errorMessage ?? hintTextDefault}
69
76
  </Text>
70
77
  </View>
71
78
  );
@@ -104,10 +111,12 @@ export const FloatingView: FC<FloatingViewProps> = ({
104
111
  },
105
112
  style,
106
113
  ]}>
107
- <Text color={floatingTextColor} typography={'label_s'}>
114
+ <Text color={floatingTextColor} typography={'label_s_medium'}>
108
115
  {floatingValue}
109
116
  {required && (
110
- <Text typography={'label_s'} color={theme.colors.error.primary}>
117
+ <Text
118
+ typography={'label_s_medium'}
119
+ color={theme.colors.error.primary}>
111
120
  *
112
121
  </Text>
113
122
  )}
package/Input/index.tsx CHANGED
@@ -1,10 +1,17 @@
1
+ import {TextInputProps, ViewStyle} from 'react-native';
1
2
  import Input from './Input';
2
- import InputTextArea from './InputTextArea';
3
- import InputSearch from './InputSearch';
3
+ import InputDropDown from './InputDropDown';
4
4
  import InputMoney from './InputMoney';
5
5
  import InputOTP from './InputOTP';
6
- import InputDropDown from './InputDropDown';
7
- import {TextInputProps, ViewStyle} from 'react-native';
6
+ import InputSearch from './InputSearch';
7
+ import InputTextArea from './InputTextArea';
8
+
9
+ export interface InputRef {
10
+ focus: () => void;
11
+ blur: () => void;
12
+ clear: () => void;
13
+ setText: (text: string) => void;
14
+ }
8
15
 
9
16
  export interface InputProps extends TextInputProps {
10
17
  /**
@@ -76,6 +83,26 @@ export interface InputProps extends TextInputProps {
76
83
  * Optional. Represents the color of the leading icon in the Input component.
77
84
  */
78
85
  leadingIconColor?: string;
86
+
87
+ /**
88
+ * Optional. Represents the font weight of the text in the Input component.
89
+ */
90
+ fontWeight?: 'Regular' | 'Bold';
91
+
92
+ /**
93
+ * Optional. callback function to be called when the icon is pressed.
94
+ */
95
+ onPressIcon?: () => void;
96
+
97
+ /**
98
+ * Optional. params for element tracking.
99
+ */
100
+ params?: any;
101
+
102
+ /**
103
+ * Optional. Represents text below the Input component.
104
+ */
105
+ hintText?: string;
79
106
  }
80
107
 
81
108
  type InputPropsWithoutSizeAndIcon = Omit<
@@ -83,10 +110,6 @@ type InputPropsWithoutSizeAndIcon = Omit<
83
110
  'size' | 'icon' | 'iconColor'
84
111
  >;
85
112
 
86
- type InputPropsOmitForSearch = Omit<
87
- InputProps,
88
- 'required' | 'size' | 'errorMessage' | 'disabled'
89
- >;
90
113
  type InputPropsWithoutPlaceholder = Omit<InputProps, 'placeholder'>;
91
114
 
92
115
  export interface InputTextAreaProps extends InputPropsWithoutSizeAndIcon {
@@ -97,7 +120,7 @@ export interface InputTextAreaProps extends InputPropsWithoutSizeAndIcon {
97
120
  height?: number;
98
121
  }
99
122
 
100
- export interface InputSearchProps extends InputPropsOmitForSearch {
123
+ export interface InputSearchProps extends TextInputProps {
101
124
  /**
102
125
  * Optional. Represents the text to be displayed on the search button within the InputSearch component.
103
126
  */
@@ -109,13 +132,24 @@ export interface InputSearchProps extends InputPropsOmitForSearch {
109
132
  */
110
133
  showButtonText?: boolean;
111
134
 
135
+ onPressButtonText?: () => void;
136
+
112
137
  /**
113
- * Optional. If `true`, a border will be displayed around the InputSearch component.
114
- * Defaults to `true` if not provided.
138
+ * Optional. Represents the color of the icon in the Input component.
115
139
  */
116
- showBorder?: boolean;
140
+ iconColor?: string;
117
141
 
118
- onPressButtonText?: () => void;
142
+ /**
143
+ * Optional. Represents the name or key of the icon to be displayed in the Input component.
144
+ */
145
+ icon?: string;
146
+
147
+ /**
148
+ *
149
+ */
150
+ hasColorBG?: boolean;
151
+
152
+ params?: any;
119
153
  }
120
154
 
121
155
  export interface InputMoneyProps extends InputPropsWithoutPlaceholder {}
@@ -135,6 +169,8 @@ export interface InputOTPProps extends InputPropsWithoutSizeAndIcon {
135
169
  * 'number' - The OTP input will be treated as a number.
136
170
  */
137
171
  dataType?: 'string' | 'number';
172
+
173
+ floatingValue: string;
138
174
  }
139
175
 
140
176
  export type CaretProps = {
@@ -151,7 +187,7 @@ export type CaretProps = {
151
187
  length?: number;
152
188
  };
153
189
 
154
- export interface InputDropDownProps {
190
+ export interface InputDropDownProps extends InputProps {
155
191
  /**
156
192
  * Optional. Defines the size of the InputDropDown component.
157
193
  * 'small' - A smaller, less prominent input.
@@ -239,7 +275,17 @@ export interface InputDropDownProps {
239
275
  */
240
276
  leadingIconColor?: string;
241
277
 
242
- style: ViewStyle | ViewStyle[];
278
+ /**
279
+ * Optional. params for element tracking.
280
+ */
281
+ params?: {
282
+ [key: string]: any;
283
+ };
284
+
285
+ /**
286
+ * Optional. Represents the style of the InputDropDown component.
287
+ */
288
+ style?: ViewStyle | ViewStyle[];
243
289
  }
244
290
 
245
- export {Input, InputTextArea, InputSearch, InputMoney, InputOTP, InputDropDown};
291
+ export {Input, InputDropDown, InputMoney, InputOTP, InputSearch, InputTextArea};
package/Input/styles.ts CHANGED
@@ -7,8 +7,7 @@ export default StyleSheet.create({
7
7
  input: {
8
8
  flex: 1,
9
9
  paddingLeft: Spacing.M,
10
- height: '100%',
11
- fontSize: scaleSize(15),
10
+ fontSize: scaleSize(14),
12
11
  },
13
12
  wrapper: {
14
13
  width: '100%',
@@ -54,8 +53,7 @@ export default StyleSheet.create({
54
53
  marginRight: Spacing.M,
55
54
  },
56
55
  icon: {
57
- width: 24,
58
- height: 24,
56
+ marginLeft: Spacing.S,
59
57
  },
60
58
  iconWrapper: {
61
59
  width: 24,
@@ -77,7 +75,7 @@ export default StyleSheet.create({
77
75
  flex: 1,
78
76
  paddingRight: Spacing.XS,
79
77
  paddingVertical: Spacing.XS,
80
- fontSize: scaleSize(15),
78
+ fontSize: scaleSize(14),
81
79
  },
82
80
  textAreaWrapper: {
83
81
  borderWidth: 1,
@@ -102,7 +100,6 @@ export default StyleSheet.create({
102
100
  searchInputWrapper: {
103
101
  flexDirection: 'row',
104
102
  borderRadius: Radius.XL,
105
- borderWidth: 1,
106
103
  paddingHorizontal: Spacing.S,
107
104
  alignItems: 'center',
108
105
  flex: 1,
@@ -111,7 +108,7 @@ export default StyleSheet.create({
111
108
  height: 36,
112
109
  marginLeft: Spacing.S,
113
110
  flex: 1,
114
- fontSize: scaleSize(15),
111
+ fontSize: scaleSize(14),
115
112
  paddingVertical: Spacing.XS,
116
113
  },
117
114
  searchInputView: {
@@ -148,7 +145,7 @@ export default StyleSheet.create({
148
145
  },
149
146
  otpFloatingView: {
150
147
  position: 'absolute',
151
- top: -Spacing.S,
148
+ top: scaleSize(-Spacing.M + 2),
152
149
  alignSelf: 'center',
153
150
  paddingHorizontal: Spacing.S,
154
151
  },
package/Layout/Card.tsx CHANGED
@@ -7,7 +7,7 @@ import Item from './Item';
7
7
  import {Image} from '../Image';
8
8
  import {ApplicationContext} from '../Application';
9
9
  import styles from './styles';
10
- import {Colors, Shadow, Spacing} from '../Consts';
10
+ import {Colors, Radius, Shadow, Spacing} from '../Consts';
11
11
  import ItemList from './ItemList';
12
12
 
13
13
  export interface CardProps extends ViewProps {
@@ -27,8 +27,9 @@ const Card: React.FC<CardProps> = ({
27
27
  style,
28
28
  backgroundImage,
29
29
  useShadow = false,
30
+ ...props
30
31
  }) => {
31
- const {showGrid} = useContext(ApplicationContext);
32
+ const {showGrid, theme} = useContext(ApplicationContext);
32
33
  const {numberOfColumns} = useGridSystem();
33
34
 
34
35
  const gutterSize = 8;
@@ -41,12 +42,12 @@ const Card: React.FC<CardProps> = ({
41
42
  const gridContext: GridContextProps = {
42
43
  numberOfColumns,
43
44
  gutterSize,
44
- margin,
45
45
  sizePerSpan,
46
46
  getSizeSpan: span => {
47
47
  return span * sizePerSpan + (span - 1) * gutterSize;
48
48
  },
49
49
  };
50
+
50
51
  /**
51
52
  * render overlay only dev mode
52
53
  */
@@ -107,8 +108,9 @@ const Card: React.FC<CardProps> = ({
107
108
  if (Array.isArray(children)) {
108
109
  let cursor = 0;
109
110
  let rows: any[] = [];
110
- for (let i = 0; i < children.length; ++i) {
111
- const item = children[i];
111
+ const arrayChild = children.filter(item => !!item);
112
+ for (let i = 0; i < arrayChild.length; ++i) {
113
+ const item = arrayChild[i];
112
114
  const totalSpan = rows
113
115
  .concat([item])
114
116
  .map(i => i.props?.widthSpan)
@@ -124,7 +126,7 @@ const Card: React.FC<CardProps> = ({
124
126
  rows = [item];
125
127
  }
126
128
 
127
- if (i == children.length - 1) {
129
+ if (i == arrayChild.length - 1) {
128
130
  cursor += 1;
129
131
  element.push(addRowView(rows, cursor, true));
130
132
  }
@@ -138,25 +140,32 @@ const Card: React.FC<CardProps> = ({
138
140
  return element;
139
141
  };
140
142
 
141
- const {theme} = useContext(ApplicationContext);
142
143
  return (
143
144
  <GridContext.Provider value={gridContext}>
144
145
  <View
145
- accessibilityLabel={`Card`}
146
+ {...props}
146
147
  style={[
148
+ {backgroundColor: theme.colors.background.surface},
147
149
  style,
150
+ styles.protectedStyle,
148
151
  styles.card,
149
152
  {
150
153
  width: widthSection,
151
- marginHorizontal: gridContext.margin,
152
- backgroundColor: theme.colors.background.surface,
154
+ marginHorizontal: margin,
153
155
  },
156
+ !!backgroundImage && {backgroundColor: undefined},
154
157
  useShadow && Shadow.Light,
155
158
  ]}>
156
159
  {!!backgroundImage && (
157
160
  <Image
158
161
  source={{uri: backgroundImage}}
159
- style={styles.imageBackground}
162
+ style={[
163
+ styles.imageBackground,
164
+ {
165
+ width: widthSection,
166
+ borderRadius: Radius.M,
167
+ },
168
+ ]}
160
169
  />
161
170
  )}
162
171
  {renderView(validateChildren(children, [Item, ItemList]))}
@@ -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
+ });
@@ -24,7 +24,6 @@ const GridSystem: React.FC<any> = ({
24
24
  const grid: GridContextProps = {
25
25
  numberOfColumns,
26
26
  gutterSize,
27
- margin,
28
27
  sizePerSpan,
29
28
  getSizeSpan: span => {
30
29
  return span * sizePerSpan + (span - 1) * gutterSize;
@@ -46,7 +45,7 @@ const GridSystem: React.FC<any> = ({
46
45
  screenGrid && insets,
47
46
  {
48
47
  borderColor: theme.colors.error.primary,
49
- marginHorizontal: grid.margin,
48
+ marginHorizontal: margin,
50
49
  top: Spacing.M,
51
50
  bottom: Spacing.M,
52
51
  },
package/Layout/Item.tsx CHANGED
@@ -37,7 +37,6 @@ const Item: React.FC<ItemProps> = ({
37
37
 
38
38
  return (
39
39
  <View
40
- accessibilityLabel={`Item`}
41
40
  style={[
42
41
  style,
43
42
  styles.item,