@momo-kits/foundation 0.80.8 → 0.81.1-beta.0

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 (87) hide show
  1. package/Application/BottomSheet.tsx +212 -0
  2. package/Application/BottomTab/BottomTabBar.tsx +278 -0
  3. package/Application/BottomTab/index.tsx +143 -0
  4. package/Application/Components.tsx +384 -213
  5. package/Application/ModalScreen.tsx +14 -178
  6. package/Application/Navigation.ts +15 -19
  7. package/Application/NavigationContainer.tsx +66 -63
  8. package/Application/Navigator.ts +106 -53
  9. package/Application/StackScreen.tsx +123 -9
  10. package/Application/index.ts +19 -6
  11. package/Application/types.ts +83 -26
  12. package/Application/utils.tsx +62 -74
  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 +64 -28
  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 +18 -0
  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 +62 -47
  32. package/Image/styles.ts +1 -9
  33. package/Image/types.ts +5 -1
  34. package/Input/Input.tsx +104 -25
  35. package/Input/InputDropDown.tsx +115 -110
  36. package/Input/InputMoney.tsx +79 -18
  37. package/Input/InputOTP.tsx +190 -149
  38. package/Input/InputSearch.tsx +96 -44
  39. package/Input/InputTextArea.tsx +33 -17
  40. package/Input/common.tsx +26 -17
  41. package/Input/index.tsx +108 -41
  42. package/Input/styles.ts +5 -7
  43. package/Input/utils.ts +1 -1
  44. package/Layout/AnimatedInputSearch.tsx +44 -0
  45. package/Layout/Card.tsx +37 -13
  46. package/Layout/FloatingButton.tsx +168 -0
  47. package/Layout/GridSystem.tsx +2 -3
  48. package/Layout/Item.tsx +1 -2
  49. package/Layout/ItemList.tsx +55 -0
  50. package/Layout/ItemSectionList.tsx +39 -0
  51. package/Layout/Screen.tsx +404 -181
  52. package/Layout/Section.tsx +22 -22
  53. package/Layout/TextTyping.tsx +114 -0
  54. package/Layout/index.ts +12 -2
  55. package/Layout/styles.ts +46 -13
  56. package/Layout/types.ts +13 -5
  57. package/Layout/utils.ts +7 -12
  58. package/Loader/index.tsx +2 -0
  59. package/Pagination/PaginationDot.tsx +6 -1
  60. package/Pagination/PaginationNumber.tsx +7 -4
  61. package/Pagination/PaginationScroll.tsx +0 -1
  62. package/Pagination/PaginationWhiteDot.tsx +6 -1
  63. package/Pagination/styles.ts +3 -0
  64. package/Pagination/types.ts +2 -0
  65. package/Popup/PopupNotify.tsx +108 -40
  66. package/Popup/PopupPromotion.tsx +45 -10
  67. package/Popup/types.ts +13 -10
  68. package/Radio/index.tsx +35 -21
  69. package/Radio/types.ts +7 -5
  70. package/Skeleton/index.tsx +1 -1
  71. package/Switch/index.tsx +32 -19
  72. package/Switch/types.ts +5 -3
  73. package/Tag/index.tsx +2 -4
  74. package/Text/index.tsx +26 -6
  75. package/Text/styles.ts +38 -0
  76. package/Text/types.ts +25 -13
  77. package/Title/index.tsx +177 -64
  78. package/Title/styles.ts +48 -15
  79. package/Title/types.ts +16 -7
  80. package/code-scanner.js +125 -16
  81. package/index.ts +9 -0
  82. package/migrate_typo.js +56 -0
  83. package/package.json +8 -7
  84. package/publish.sh +21 -16
  85. package/tsconfig.json +1 -2
  86. package/verify.js +24 -6
  87. 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,14 +35,16 @@ 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,
46
+ style,
47
+ hintText,
40
48
  ...props
41
49
  }: InputTextAreaProps,
42
50
  ref,
@@ -44,7 +52,7 @@ const InputTextArea = forwardRef(
44
52
  const {theme} = useContext(ApplicationContext);
45
53
  const [focused, setFocused] = useState(false);
46
54
  const [inputValue, setInputValue] = useState(defaultValue ?? '');
47
- const inputRef = (ref as React.RefObject<TextInput>) ?? useRef<TextInput>();
55
+ const inputRef = useRef<TextInput | null>(null);
48
56
 
49
57
  const onClearText = () => {
50
58
  inputRef?.current?.clear();
@@ -66,10 +74,21 @@ const InputTextArea = forwardRef(
66
74
  onBlur?.(e);
67
75
  };
68
76
 
77
+ useImperativeHandle(ref, () => {
78
+ return {
79
+ clear: onClearText,
80
+ focus: () => inputRef.current?.focus(),
81
+ blur: () => inputRef.current?.blur(),
82
+ setText: (text: string) => _onChangeText(text),
83
+ };
84
+ });
85
+
69
86
  const renderCountingView = () => {
70
87
  return (
71
88
  <View style={styles.countingView}>
72
- <Text color={theme.colors.text.hint} typography={'description_xs'}>
89
+ <Text
90
+ color={theme.colors.text.hint}
91
+ typography={'description_xs_regular'}>
73
92
  {`${inputValue.length}/${maxLength}`}
74
93
  </Text>
75
94
  </View>
@@ -106,7 +125,6 @@ const InputTextArea = forwardRef(
106
125
  <View style={styles.textAreaView}>
107
126
  <TextInput
108
127
  {...props}
109
- accessibilityLabel={`TextInput`}
110
128
  ref={inputRef}
111
129
  editable={!disabled}
112
130
  textAlignVertical="top"
@@ -146,18 +164,16 @@ const InputTextArea = forwardRef(
146
164
  };
147
165
 
148
166
  return (
149
- <View
150
- style={styles.wrapper}
151
- accessibilityLabel={`InputTextArea/${floatingValue}`}>
167
+ <View style={[style, styles.wrapper]}>
152
168
  {renderInputView()}
153
- <ErrorView errorMessage={errorMessage} errorSpacing={errorSpacing} />
169
+ <ErrorView
170
+ errorMessage={errorMessage}
171
+ errorSpacing={errorSpacing}
172
+ hintText={hintText}
173
+ />
154
174
  </View>
155
175
  );
156
176
  },
157
177
  );
158
178
 
159
- InputTextArea.defaultProps = {
160
- maxLength: MAX_LENGTH,
161
- };
162
-
163
179
  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 {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;
@@ -16,7 +16,7 @@ type FloatingViewProps = {
16
16
  style?: ViewStyle;
17
17
  };
18
18
 
19
- export const DEFAULT_HEIGHT = 112;
19
+ export const DEFAULT_HEIGHT = scaleSize(104);
20
20
  export const MAX_LENGTH = 300;
21
21
 
22
22
  export const getBorderColor = (
@@ -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,10 @@
1
+ import {GestureResponderEvent, 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} from 'react-native';
6
+ import InputSearch from './InputSearch';
7
+ import InputTextArea from './InputTextArea';
8
8
 
9
9
  export interface InputProps extends TextInputProps {
10
10
  /**
@@ -76,20 +76,30 @@ export interface InputProps extends TextInputProps {
76
76
  * Optional. Represents the color of the leading icon in the Input component.
77
77
  */
78
78
  leadingIconColor?: string;
79
- }
80
79
 
81
- type InputPropsWithoutSizeAndIcon = Omit<
82
- InputProps,
83
- 'size' | 'icon' | 'iconColor'
84
- >;
80
+ /**
81
+ * Optional. Represents the font weight of the text in the Input component.
82
+ */
83
+ fontWeight?: 'Regular' | 'Bold';
84
+
85
+ /**
86
+ * Optional. callback function to be called when the icon is pressed.
87
+ */
88
+ onPressIcon?: () => void;
85
89
 
86
- type InputPropsOmitForSearch = Omit<
87
- InputProps,
88
- 'required' | 'size' | 'errorMessage' | 'disabled'
89
- >;
90
- type InputPropsWithoutPlaceholder = Omit<InputProps, 'placeholder'>;
90
+ /**
91
+ * Optional. params for element tracking.
92
+ */
93
+ params?: any;
94
+
95
+ /**
96
+ * Optional. Represents text below the Input component.
97
+ */
98
+ hintText?: string;
99
+ }
91
100
 
92
- export interface InputTextAreaProps extends InputPropsWithoutSizeAndIcon {
101
+ export interface InputTextAreaProps
102
+ extends Omit<InputProps, 'size' | 'icon' | 'iconColor'> {
93
103
  /**
94
104
  * Optional. Defines the height of the InputTextArea component.
95
105
  * It can be used to set a specific height for the text area.
@@ -97,7 +107,7 @@ export interface InputTextAreaProps extends InputPropsWithoutSizeAndIcon {
97
107
  height?: number;
98
108
  }
99
109
 
100
- export interface InputSearchProps extends InputPropsOmitForSearch {
110
+ export interface InputSearchProps extends TextInputProps {
101
111
  /**
102
112
  * Optional. Represents the text to be displayed on the search button within the InputSearch component.
103
113
  */
@@ -110,86 +120,131 @@ export interface InputSearchProps extends InputPropsOmitForSearch {
110
120
  showButtonText?: boolean;
111
121
 
112
122
  /**
113
- * Optional. If `true`, a border will be displayed around the InputSearch component.
114
- * Defaults to `true` if not provided.
123
+ * Optional. Represents the value for the floating title in the InputSearch component.
115
124
  */
116
- showBorder?: boolean;
117
-
118
125
  onPressButtonText?: () => void;
126
+
127
+ /**
128
+ * Optional. Represents the color of the icon in the Input component.
129
+ */
130
+ iconColor?: string;
131
+
132
+ /**
133
+ * Optional. Represents the name or key of the icon to be displayed in the Input component.
134
+ */
135
+ icon?: string;
136
+
137
+ /**
138
+ * Optional. If `true`, the user won't be able to interact with the Input component.
139
+ */
140
+ hasColorBG?: boolean;
141
+
142
+ /**
143
+ * Optional. Represents the style of the InputSearch component.
144
+ */
145
+ params?: any;
146
+
147
+ typingData?: string[];
148
+ onPress?: (e: GestureResponderEvent) => void;
119
149
  }
120
150
 
121
- export interface InputMoneyProps extends InputPropsWithoutPlaceholder {}
151
+ export interface InputMoneyProps extends Omit<InputProps, 'placeholder'> {}
122
152
 
123
153
  export type OTPInputLength = 2 | 4 | 6 | 8 | 10;
124
154
 
125
- export interface InputOTPProps extends InputPropsWithoutSizeAndIcon {
155
+ export interface InputOTPProps
156
+ extends Omit<InputProps, 'size' | 'icon' | 'iconColor'> {
157
+ /**
158
+ * Optional. Defines the length of the OTP (One Time Password) input.
159
+ * Can be 2, 4, 6, 8, or 10.
160
+ */
126
161
  length?: OTPInputLength;
162
+
163
+ /**
164
+ * Optional. Defines the data type of the OTP input.
165
+ * 'string' - The OTP input will be treated as a string.
166
+ * 'number' - The OTP input will be treated as a number.
167
+ */
127
168
  dataType?: 'string' | 'number';
169
+
170
+ floatingValue: string;
128
171
  }
129
172
 
130
173
  export type CaretProps = {
174
+ /**
175
+ * Optional. The index of the caret in the input field.
176
+ * Represents the position where the caret is located.
177
+ */
131
178
  index?: number;
179
+
180
+ /**
181
+ * Optional. The total length of the input field in which the caret is present.
182
+ * This dictates the maximum value of the 'index' property.
183
+ */
132
184
  length?: number;
133
185
  };
134
186
 
135
- export type InputDropDownProps = {
187
+ export interface InputDropDownProps extends InputProps {
136
188
  /**
137
- * Optional. Defines the size of the Input component.
189
+ * Optional. Defines the size of the InputDropDown component.
190
+ * 'small' - A smaller, less prominent input.
191
+ * 'large' - A larger, more prominent input.
138
192
  */
139
193
  size?: 'small' | 'large';
140
194
 
141
195
  /**
142
- * Optional. Defines the value of InputDropDown.
196
+ * Optional. The current value of the InputDropDown.
143
197
  */
144
198
  value?: string;
145
199
 
146
200
  /**
147
- * Optional. Defines the placeholder of InputDropDown.
201
+ * Optional. Text that is displayed when there is no value set in the InputDropDown.
148
202
  */
149
203
  placeholder?: string;
150
204
 
151
205
  /**
152
- * Optional. Defines the onPress of InputDropDown.
206
+ * Optional. Function to be called when the InputDropDown is pressed.
153
207
  */
154
208
  onPress?: () => void;
209
+
155
210
  /**
156
- * Optional. Represents the value for the floating title in the Input component.
211
+ * Optional. Represents the value for the floating title in the InputDropDown component.
157
212
  */
158
213
  floatingValue?: string;
159
214
 
160
215
  /**
161
- * Optional. Represents the name or key of the floating icon to be displayed in the Input component.
216
+ * Optional. Represents the name or key of the floating icon to be displayed in the InputDropDown component.
162
217
  */
163
218
  floatingIcon?: string;
164
219
 
165
220
  /**
166
- * Optional. Represents the error message to be displayed below the Input component when there is an error.
221
+ * Optional. Represents the error message to be displayed below the InputDropDown component when there is an error.
167
222
  */
168
223
  errorMessage?: string;
169
224
 
170
225
  /**
171
- * Optional. Represents the name or key of the icon to be displayed in the Input component.
226
+ * Optional. Represents the name or key of the icon to be displayed in the InputDropDown component.
172
227
  */
173
228
  icon?: string;
174
229
 
175
230
  /**
176
- * Optional. Represents the color of the icon in the Input component.
231
+ * Optional. Represents the color of the icon in the InputDropDown component.
177
232
  */
178
233
  iconColor?: string;
179
234
 
180
235
  /**
181
- * Optional. If `true`, the user won't be able to interact with the Input component.
236
+ * Optional. If `true`, the user won't be able to interact with the InputDropDown component.
182
237
  * Defaults to `false` if not provided.
183
238
  */
184
239
  disabled?: boolean;
185
240
 
186
241
  /**
187
- * Optional. Represents the color of the floating icon in the Input component.
242
+ * Optional. Represents the color of the floating icon in the InputDropDown component.
188
243
  */
189
244
  floatingIconColor?: string;
190
245
 
191
246
  /**
192
- * Optional. If `true`, the Input component is marked as required,
247
+ * Optional. If `true`, the InputDropDown component is marked as required,
193
248
  * indicating that the user must provide a value before submitting a form.
194
249
  * Defaults to `false` if not provided.
195
250
  */
@@ -197,25 +252,37 @@ export type InputDropDownProps = {
197
252
 
198
253
  /**
199
254
  * Optional. If `true`,
200
- * include spacing when Input not have error message.
255
+ * includes spacing when InputDropDown does not have an error message.
201
256
  * Defaults to `false` if not provided.
202
257
  */
203
258
  errorSpacing?: boolean;
204
259
 
205
260
  /**
206
- * If true, the icon of input will use be show indicator loading.
261
+ * If `true`, the icon of the input will show an indicator for loading.
207
262
  */
208
263
  loading?: boolean;
209
264
 
210
265
  /**
211
- * Optional. Represents the leading icon in the Input component.
266
+ * Optional. Represents the leading icon in the InputDropDown component.
212
267
  */
213
268
  leadingIcon?: string;
214
269
 
215
270
  /**
216
- * Optional. Represents the color of the leading icon in the Input component.
271
+ * Optional. Represents the color of the leading icon in the InputDropDown component.
217
272
  */
218
273
  leadingIconColor?: string;
219
- };
220
274
 
221
- export {Input, InputTextArea, InputSearch, InputMoney, InputOTP, InputDropDown};
275
+ /**
276
+ * Optional. params for element tracking.
277
+ */
278
+ params?: {
279
+ [key: string]: any;
280
+ };
281
+
282
+ /**
283
+ * Optional. Represents the style of the InputDropDown component.
284
+ */
285
+ style?: ViewStyle | ViewStyle[];
286
+ }
287
+
288
+ export {Input, InputDropDown, InputMoney, InputOTP, InputSearch, InputTextArea};
package/Input/styles.ts CHANGED
@@ -7,8 +7,8 @@ export default StyleSheet.create({
7
7
  input: {
8
8
  flex: 1,
9
9
  paddingLeft: Spacing.M,
10
+ fontSize: scaleSize(14),
10
11
  height: '100%',
11
- fontSize: scaleSize(15),
12
12
  },
13
13
  wrapper: {
14
14
  width: '100%',
@@ -54,8 +54,7 @@ export default StyleSheet.create({
54
54
  marginRight: Spacing.M,
55
55
  },
56
56
  icon: {
57
- width: 24,
58
- height: 24,
57
+ marginLeft: Spacing.S,
59
58
  },
60
59
  iconWrapper: {
61
60
  width: 24,
@@ -77,7 +76,7 @@ export default StyleSheet.create({
77
76
  flex: 1,
78
77
  paddingRight: Spacing.XS,
79
78
  paddingVertical: Spacing.XS,
80
- fontSize: scaleSize(15),
79
+ fontSize: scaleSize(14),
81
80
  },
82
81
  textAreaWrapper: {
83
82
  borderWidth: 1,
@@ -102,7 +101,6 @@ export default StyleSheet.create({
102
101
  searchInputWrapper: {
103
102
  flexDirection: 'row',
104
103
  borderRadius: Radius.XL,
105
- borderWidth: 1,
106
104
  paddingHorizontal: Spacing.S,
107
105
  alignItems: 'center',
108
106
  flex: 1,
@@ -111,7 +109,7 @@ export default StyleSheet.create({
111
109
  height: 36,
112
110
  marginLeft: Spacing.S,
113
111
  flex: 1,
114
- fontSize: scaleSize(15),
112
+ fontSize: scaleSize(14),
115
113
  paddingVertical: Spacing.XS,
116
114
  },
117
115
  searchInputView: {
@@ -148,7 +146,7 @@ export default StyleSheet.create({
148
146
  },
149
147
  otpFloatingView: {
150
148
  position: 'absolute',
151
- top: -Spacing.S,
149
+ top: scaleSize(-Spacing.M + 2),
152
150
  alignSelf: 'center',
153
151
  paddingHorizontal: Spacing.S,
154
152
  },
package/Input/utils.ts CHANGED
@@ -61,7 +61,7 @@ const formatMoneyToNumber = (money: string, currencyUnit: string) => {
61
61
  };
62
62
  const checkTyping = (text: string, value: boolean, setValue: any) => {
63
63
  let typing = text?.length > 0;
64
- if (typing != value) {
64
+ if (typing !== value) {
65
65
  setValue(typing);
66
66
  }
67
67
  };
@@ -0,0 +1,44 @@
1
+ import React, {FC} from 'react';
2
+ import {InputSearch} from '../Input';
3
+ import {Animated, Dimensions} from 'react-native';
4
+ import {AnimatedInputSearchProps} from './types';
5
+ import {Spacing} from '../Consts';
6
+ import {scaleSize} from '../Text';
7
+
8
+ const {width: screenWidth} = Dimensions.get('window');
9
+ const SCREEN_PADDING = 12;
10
+ const BACK_WIDTH = scaleSize(28);
11
+
12
+ const AnimatedInputSearch: FC<AnimatedInputSearchProps> = ({
13
+ animatedValue,
14
+ headerRightWidth,
15
+ inputSearchProps,
16
+ }) => {
17
+ const translateX = animatedValue.interpolate({
18
+ inputRange: [0, 100],
19
+ outputRange: [SCREEN_PADDING, BACK_WIDTH + SCREEN_PADDING * 2],
20
+ extrapolate: 'clamp',
21
+ });
22
+
23
+ const width = animatedValue.interpolate({
24
+ inputRange: [0, 100],
25
+ outputRange: [
26
+ screenWidth - SCREEN_PADDING * 2,
27
+ screenWidth - SCREEN_PADDING * 3 - BACK_WIDTH - headerRightWidth,
28
+ ],
29
+ extrapolate: 'clamp',
30
+ });
31
+
32
+ return (
33
+ <Animated.View
34
+ style={{
35
+ transform: [{translateX}],
36
+ marginVertical: Spacing.S,
37
+ width,
38
+ }}>
39
+ <InputSearch {...inputSearchProps} showButtonText={false} />
40
+ </Animated.View>
41
+ );
42
+ };
43
+
44
+ export default AnimatedInputSearch;
package/Layout/Card.tsx CHANGED
@@ -7,17 +7,29 @@ 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, Spacing} from '../Consts';
10
+ import {Colors, Radius, Shadow, Spacing} from '../Consts';
11
+ import ItemList from './ItemList';
11
12
 
12
13
  export interface CardProps extends ViewProps {
13
14
  /**
14
15
  * Optional. Background image for the card.
15
16
  */
16
17
  backgroundImage?: string;
18
+
19
+ /**
20
+ * Optional. Use shadow for the card.
21
+ */
22
+ useShadow?: boolean;
17
23
  }
18
24
 
19
- const Card: React.FC<CardProps> = ({children, style, backgroundImage}) => {
20
- const {showGrid} = useContext(ApplicationContext);
25
+ const Card: React.FC<CardProps> = ({
26
+ children,
27
+ style,
28
+ backgroundImage,
29
+ useShadow = false,
30
+ ...props
31
+ }) => {
32
+ const {showGrid, theme} = useContext(ApplicationContext);
21
33
  const {numberOfColumns} = useGridSystem();
22
34
 
23
35
  const gutterSize = 8;
@@ -30,12 +42,12 @@ const Card: React.FC<CardProps> = ({children, style, backgroundImage}) => {
30
42
  const gridContext: GridContextProps = {
31
43
  numberOfColumns,
32
44
  gutterSize,
33
- margin,
34
45
  sizePerSpan,
35
46
  getSizeSpan: span => {
36
47
  return span * sizePerSpan + (span - 1) * gutterSize;
37
48
  },
38
49
  };
50
+
39
51
  /**
40
52
  * render overlay only dev mode
41
53
  */
@@ -74,7 +86,7 @@ const Card: React.FC<CardProps> = ({children, style, backgroundImage}) => {
74
86
  {rows.map((i: React.ReactElement, index: number) => {
75
87
  return (
76
88
  <View key={`Item${cursor}${index}`} style={{flexDirection: 'row'}}>
77
- {index != 0 && (
89
+ {index !== 0 && (
78
90
  <View style={{width: gridContext.gutterSize}}></View>
79
91
  )}
80
92
  {i}
@@ -96,8 +108,9 @@ const Card: React.FC<CardProps> = ({children, style, backgroundImage}) => {
96
108
  if (Array.isArray(children)) {
97
109
  let cursor = 0;
98
110
  let rows: any[] = [];
99
- for (let i = 0; i < children.length; ++i) {
100
- 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];
101
114
  const totalSpan = rows
102
115
  .concat([item])
103
116
  .map(i => i.props?.widthSpan)
@@ -113,14 +126,14 @@ const Card: React.FC<CardProps> = ({children, style, backgroundImage}) => {
113
126
  rows = [item];
114
127
  }
115
128
 
116
- if (i == children.length - 1) {
129
+ if (i === arrayChild.length - 1) {
117
130
  cursor += 1;
118
131
  element.push(addRowView(rows, cursor, true));
119
132
  }
120
133
  }
121
134
  } else {
122
135
  element.push(children);
123
- if (children?.type == Fragment) {
136
+ if (children?.type === Fragment) {
124
137
  return renderView(children?.props.children);
125
138
  }
126
139
  }
@@ -130,22 +143,33 @@ const Card: React.FC<CardProps> = ({children, style, backgroundImage}) => {
130
143
  return (
131
144
  <GridContext.Provider value={gridContext}>
132
145
  <View
133
- accessibilityLabel={`Card`}
146
+ {...props}
147
+ onLayout={undefined}
134
148
  style={[
149
+ {backgroundColor: theme.colors.background.surface},
135
150
  style,
151
+ styles.protectedStyle,
136
152
  styles.card,
137
153
  {
138
154
  width: widthSection,
139
- marginHorizontal: gridContext.margin,
155
+ marginHorizontal: margin,
140
156
  },
157
+ !!backgroundImage && {backgroundColor: undefined},
158
+ useShadow && Shadow.Light,
141
159
  ]}>
142
160
  {!!backgroundImage && (
143
161
  <Image
144
162
  source={{uri: backgroundImage}}
145
- style={[style, styles.imageBackground]}
163
+ style={[
164
+ styles.imageBackground,
165
+ {
166
+ width: widthSection,
167
+ borderRadius: Radius.M,
168
+ },
169
+ ]}
146
170
  />
147
171
  )}
148
- {renderView(validateChildren(children, [Item]))}
172
+ {renderView(validateChildren(children, [Item, ItemList]))}
149
173
  {showGrid && renderOverlay()}
150
174
  </View>
151
175
  </GridContext.Provider>