@momo-kits/foundation 0.81.52 → 0.81.53-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.
- package/Application/BottomSheet.tsx +216 -0
- package/Application/BottomTab/BottomTabBar.tsx +278 -0
- package/Application/{BottomTab.tsx → BottomTab/index.tsx} +43 -18
- package/Application/Components.tsx +71 -53
- package/Application/ModalScreen.tsx +12 -183
- package/Application/Navigation.ts +2 -2
- package/Application/NavigationContainer.tsx +54 -53
- package/Application/Navigator.ts +53 -35
- package/Application/StackScreen.tsx +225 -30
- package/Application/index.ts +8 -12
- package/Application/types.ts +45 -27
- package/Application/utils.tsx +19 -15
- package/Assets/icon_bank.json +1 -1
- package/Badge/Badge.tsx +1 -1
- package/Button/index.tsx +44 -25
- package/CheckBox/index.tsx +37 -26
- package/CheckBox/types.ts +5 -3
- package/Consts/colors+spacing+radius.ts +14 -0
- package/Icon/index.tsx +9 -8
- package/Icon/types.ts +2 -2
- package/IconButton/index.tsx +24 -14
- package/Image/index.tsx +23 -8
- package/Image/types.ts +2 -0
- package/Input/Input.tsx +116 -26
- package/Input/InputDropDown.tsx +66 -51
- package/Input/InputMoney.tsx +106 -15
- package/Input/InputOTP.tsx +45 -22
- package/Input/InputSearch.tsx +92 -44
- package/Input/InputTextArea.tsx +26 -6
- package/Input/common.tsx +48 -22
- package/Input/index.tsx +94 -77
- package/Input/styles.ts +35 -5
- package/Input/utils.ts +1 -1
- package/Layout/Card.tsx +4 -3
- package/Layout/FloatingButton.tsx +168 -0
- package/Layout/GridSystem.tsx +1 -1
- package/Layout/ItemList.tsx +3 -2
- package/Layout/Screen.tsx +87 -49
- package/Layout/Section.tsx +4 -3
- package/Layout/styles.ts +11 -7
- package/Layout/utils.ts +4 -4
- package/Loader/index.tsx +2 -0
- package/Popup/PopupNotify.tsx +55 -44
- package/Popup/PopupPromotion.tsx +5 -7
- package/Popup/types.ts +1 -7
- package/Radio/index.tsx +35 -20
- package/Radio/types.ts +5 -3
- package/Switch/index.tsx +32 -18
- package/Switch/types.ts +5 -3
- package/Tag/styles.ts +3 -2
- package/Text/index.tsx +24 -5
- package/Text/styles.ts +8 -8
- package/Title/index.tsx +170 -103
- package/Title/styles.ts +36 -9
- package/Title/types.ts +16 -48
- package/code-scanner.js +125 -16
- package/index.ts +7 -0
- package/package.json +6 -6
- package/publish.sh +16 -21
- package/tsconfig.json +1 -1
package/Input/index.tsx
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
|
+
import {GestureResponderEvent, TextInputProps, ViewStyle} from 'react-native';
|
|
1
2
|
import Input from './Input';
|
|
2
|
-
import
|
|
3
|
-
import InputSearch from './InputSearch';
|
|
3
|
+
import InputDropDown from './InputDropDown';
|
|
4
4
|
import InputMoney from './InputMoney';
|
|
5
5
|
import InputOTP from './InputOTP';
|
|
6
|
-
import
|
|
7
|
-
import
|
|
6
|
+
import InputSearch from './InputSearch';
|
|
7
|
+
import InputTextArea from './InputTextArea';
|
|
8
|
+
|
|
9
|
+
export type OTPInputLength = 2 | 4 | 6 | 8 | 10;
|
|
8
10
|
|
|
9
11
|
export interface InputProps extends TextInputProps {
|
|
10
12
|
/**
|
|
@@ -28,15 +30,38 @@ export interface InputProps extends TextInputProps {
|
|
|
28
30
|
errorMessage?: string;
|
|
29
31
|
|
|
30
32
|
/**
|
|
33
|
+
* @deprecated Use `trailing` instead.
|
|
31
34
|
* Optional. Represents the name or key of the icon to be displayed in the Input component.
|
|
32
35
|
*/
|
|
33
36
|
icon?: string;
|
|
34
37
|
|
|
35
38
|
/**
|
|
39
|
+
* @deprecated Use `trailingColor` instead.
|
|
36
40
|
* Optional. Represents the color of the icon in the Input component.
|
|
37
41
|
*/
|
|
38
42
|
iconColor?: string;
|
|
39
43
|
|
|
44
|
+
/**
|
|
45
|
+
* @deprecated Use `onPressTrailing` instead.
|
|
46
|
+
* Optional. callback function to be called when the icon is pressed.
|
|
47
|
+
*/
|
|
48
|
+
onPressIcon?: () => void;
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Optional. Represents the name or key of the icon to be displayed in the Input component.
|
|
52
|
+
*/
|
|
53
|
+
trailing?: string;
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Optional. Represents the color of the icon in the Input component.
|
|
57
|
+
*/
|
|
58
|
+
trailingColor?: string;
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Optional. callback function to be called when the icon is pressed.
|
|
62
|
+
*/
|
|
63
|
+
onPressTrailing?: () => void;
|
|
64
|
+
|
|
40
65
|
/**
|
|
41
66
|
* Optional. If `true`, the user won't be able to interact with the Input component.
|
|
42
67
|
* Defaults to `false` if not provided.
|
|
@@ -77,19 +102,25 @@ export interface InputProps extends TextInputProps {
|
|
|
77
102
|
*/
|
|
78
103
|
leadingIconColor?: string;
|
|
79
104
|
|
|
105
|
+
/**
|
|
106
|
+
* Optional. Represents the font weight of the text in the Input component.
|
|
107
|
+
*/
|
|
80
108
|
fontWeight?: 'Regular' | 'Bold';
|
|
81
109
|
|
|
82
|
-
|
|
83
|
-
|
|
110
|
+
/**
|
|
111
|
+
* Optional. params for element tracking.
|
|
112
|
+
*/
|
|
113
|
+
params?: any;
|
|
84
114
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
115
|
+
/**
|
|
116
|
+
* Optional. Represents text below the Input component.
|
|
117
|
+
*/
|
|
118
|
+
hintText?: string;
|
|
89
119
|
|
|
90
|
-
|
|
120
|
+
onPressFloatingIcon?: (e: GestureResponderEvent) => void;
|
|
121
|
+
}
|
|
91
122
|
|
|
92
|
-
export interface InputTextAreaProps extends
|
|
123
|
+
export interface InputTextAreaProps extends Omit<InputProps, 'size'> {
|
|
93
124
|
/**
|
|
94
125
|
* Optional. Defines the height of the InputTextArea component.
|
|
95
126
|
* It can be used to set a specific height for the text area.
|
|
@@ -109,26 +140,59 @@ export interface InputSearchProps extends TextInputProps {
|
|
|
109
140
|
*/
|
|
110
141
|
showButtonText?: boolean;
|
|
111
142
|
|
|
143
|
+
/**
|
|
144
|
+
* Optional. Represents the value for the floating title in the InputSearch component.
|
|
145
|
+
*/
|
|
112
146
|
onPressButtonText?: () => void;
|
|
113
147
|
|
|
114
148
|
/**
|
|
149
|
+
* @deprecated Use `trailing` instead.
|
|
150
|
+
* Optional. Represents the name or key of the icon to be displayed in the Input component.
|
|
151
|
+
*/
|
|
152
|
+
icon?: string;
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* @deprecated Use `trailingColor` instead.
|
|
115
156
|
* Optional. Represents the color of the icon in the Input component.
|
|
116
157
|
*/
|
|
117
158
|
iconColor?: string;
|
|
118
159
|
|
|
160
|
+
/**
|
|
161
|
+
* @deprecated Use `onPressTrailing` instead.
|
|
162
|
+
* Optional. callback function to be called when the icon is pressed.
|
|
163
|
+
*/
|
|
164
|
+
onPressIcon?: () => void;
|
|
165
|
+
|
|
119
166
|
/**
|
|
120
167
|
* Optional. Represents the name or key of the icon to be displayed in the Input component.
|
|
121
168
|
*/
|
|
122
|
-
|
|
169
|
+
trailing?: string;
|
|
123
170
|
|
|
124
|
-
|
|
125
|
-
|
|
171
|
+
/**
|
|
172
|
+
* Optional. Represents the color of the icon in the Input component.
|
|
173
|
+
*/
|
|
174
|
+
trailingColor?: string;
|
|
126
175
|
|
|
127
|
-
|
|
176
|
+
/**
|
|
177
|
+
* Optional. callback function to be called when the icon is pressed.
|
|
178
|
+
*/
|
|
179
|
+
onPressTrailing?: () => void;
|
|
128
180
|
|
|
129
|
-
|
|
181
|
+
/**
|
|
182
|
+
* Optional. If `true`, the user won't be able to interact with the Input component.
|
|
183
|
+
*/
|
|
184
|
+
hasColorBG?: boolean;
|
|
130
185
|
|
|
131
|
-
|
|
186
|
+
/**
|
|
187
|
+
* Optional. Represents the style of the InputSearch component.
|
|
188
|
+
*/
|
|
189
|
+
params?: any;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
export interface InputMoneyProps extends Omit<InputProps, 'placeholder'> {}
|
|
193
|
+
|
|
194
|
+
export interface InputOTPProps
|
|
195
|
+
extends Omit<InputProps, 'size' | 'icon' | 'iconColor'> {
|
|
132
196
|
/**
|
|
133
197
|
* Optional. Defines the length of the OTP (One Time Password) input.
|
|
134
198
|
* Can be 2, 4, 6, 8, or 10.
|
|
@@ -141,6 +205,8 @@ export interface InputOTPProps extends InputPropsWithoutSizeAndIcon {
|
|
|
141
205
|
* 'number' - The OTP input will be treated as a number.
|
|
142
206
|
*/
|
|
143
207
|
dataType?: 'string' | 'number';
|
|
208
|
+
|
|
209
|
+
floatingValue: string;
|
|
144
210
|
}
|
|
145
211
|
|
|
146
212
|
export type CaretProps = {
|
|
@@ -157,7 +223,8 @@ export type CaretProps = {
|
|
|
157
223
|
length?: number;
|
|
158
224
|
};
|
|
159
225
|
|
|
160
|
-
export interface InputDropDownProps
|
|
226
|
+
export interface InputDropDownProps
|
|
227
|
+
extends Omit<InputProps, 'trailing' | 'trailingColor' | 'onPressTrailing'> {
|
|
161
228
|
/**
|
|
162
229
|
* Optional. Defines the size of the InputDropDown component.
|
|
163
230
|
* 'small' - A smaller, less prominent input.
|
|
@@ -165,57 +232,17 @@ export interface InputDropDownProps {
|
|
|
165
232
|
*/
|
|
166
233
|
size?: 'small' | 'large';
|
|
167
234
|
|
|
168
|
-
/**
|
|
169
|
-
* Optional. The current value of the InputDropDown.
|
|
170
|
-
*/
|
|
171
|
-
value?: string;
|
|
172
|
-
|
|
173
|
-
/**
|
|
174
|
-
* Optional. Text that is displayed when there is no value set in the InputDropDown.
|
|
175
|
-
*/
|
|
176
|
-
placeholder?: string;
|
|
177
|
-
|
|
178
235
|
/**
|
|
179
236
|
* Optional. Function to be called when the InputDropDown is pressed.
|
|
180
237
|
*/
|
|
181
238
|
onPress?: () => void;
|
|
182
239
|
|
|
183
|
-
/**
|
|
184
|
-
* Optional. Represents the value for the floating title in the InputDropDown component.
|
|
185
|
-
*/
|
|
186
|
-
floatingValue?: string;
|
|
187
|
-
|
|
188
|
-
/**
|
|
189
|
-
* Optional. Represents the name or key of the floating icon to be displayed in the InputDropDown component.
|
|
190
|
-
*/
|
|
191
|
-
floatingIcon?: string;
|
|
192
|
-
|
|
193
|
-
/**
|
|
194
|
-
* Optional. Represents the error message to be displayed below the InputDropDown component when there is an error.
|
|
195
|
-
*/
|
|
196
|
-
errorMessage?: string;
|
|
197
|
-
|
|
198
|
-
/**
|
|
199
|
-
* Optional. Represents the name or key of the icon to be displayed in the InputDropDown component.
|
|
200
|
-
*/
|
|
201
|
-
icon?: string;
|
|
202
|
-
|
|
203
|
-
/**
|
|
204
|
-
* Optional. Represents the color of the icon in the InputDropDown component.
|
|
205
|
-
*/
|
|
206
|
-
iconColor?: string;
|
|
207
|
-
|
|
208
240
|
/**
|
|
209
241
|
* Optional. If `true`, the user won't be able to interact with the InputDropDown component.
|
|
210
242
|
* Defaults to `false` if not provided.
|
|
211
243
|
*/
|
|
212
244
|
disabled?: boolean;
|
|
213
245
|
|
|
214
|
-
/**
|
|
215
|
-
* Optional. Represents the color of the floating icon in the InputDropDown component.
|
|
216
|
-
*/
|
|
217
|
-
floatingIconColor?: string;
|
|
218
|
-
|
|
219
246
|
/**
|
|
220
247
|
* Optional. If `true`, the InputDropDown component is marked as required,
|
|
221
248
|
* indicating that the user must provide a value before submitting a form.
|
|
@@ -224,28 +251,18 @@ export interface InputDropDownProps {
|
|
|
224
251
|
required?: boolean;
|
|
225
252
|
|
|
226
253
|
/**
|
|
227
|
-
* Optional.
|
|
228
|
-
* includes spacing when InputDropDown does not have an error message.
|
|
229
|
-
* Defaults to `false` if not provided.
|
|
230
|
-
*/
|
|
231
|
-
errorSpacing?: boolean;
|
|
232
|
-
|
|
233
|
-
/**
|
|
234
|
-
* If `true`, the icon of the input will show an indicator for loading.
|
|
254
|
+
* Optional. params for element tracking.
|
|
235
255
|
*/
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
* Optional. Represents the leading icon in the InputDropDown component.
|
|
240
|
-
*/
|
|
241
|
-
leadingIcon?: string;
|
|
256
|
+
params?: {
|
|
257
|
+
[key: string]: any;
|
|
258
|
+
};
|
|
242
259
|
|
|
243
260
|
/**
|
|
244
|
-
* Optional. Represents the
|
|
261
|
+
* Optional. Represents the style of the InputDropDown component.
|
|
245
262
|
*/
|
|
246
|
-
|
|
263
|
+
style?: ViewStyle | ViewStyle[];
|
|
247
264
|
|
|
248
|
-
|
|
265
|
+
multiline?: boolean;
|
|
249
266
|
}
|
|
250
267
|
|
|
251
|
-
export {Input,
|
|
268
|
+
export {Input, InputDropDown, InputMoney, InputOTP, InputSearch, InputTextArea};
|
package/Input/styles.ts
CHANGED
|
@@ -7,7 +7,8 @@ export default StyleSheet.create({
|
|
|
7
7
|
input: {
|
|
8
8
|
flex: 1,
|
|
9
9
|
paddingLeft: Spacing.M,
|
|
10
|
-
fontSize: scaleSize(
|
|
10
|
+
fontSize: scaleSize(14),
|
|
11
|
+
height: '100%',
|
|
11
12
|
},
|
|
12
13
|
wrapper: {
|
|
13
14
|
width: '100%',
|
|
@@ -53,7 +54,7 @@ export default StyleSheet.create({
|
|
|
53
54
|
marginRight: Spacing.M,
|
|
54
55
|
},
|
|
55
56
|
icon: {
|
|
56
|
-
marginLeft: Spacing.S
|
|
57
|
+
marginLeft: Spacing.S,
|
|
57
58
|
},
|
|
58
59
|
iconWrapper: {
|
|
59
60
|
width: 24,
|
|
@@ -75,7 +76,7 @@ export default StyleSheet.create({
|
|
|
75
76
|
flex: 1,
|
|
76
77
|
paddingRight: Spacing.XS,
|
|
77
78
|
paddingVertical: Spacing.XS,
|
|
78
|
-
fontSize: scaleSize(
|
|
79
|
+
fontSize: scaleSize(14),
|
|
79
80
|
},
|
|
80
81
|
textAreaWrapper: {
|
|
81
82
|
borderWidth: 1,
|
|
@@ -108,7 +109,7 @@ export default StyleSheet.create({
|
|
|
108
109
|
height: 36,
|
|
109
110
|
marginLeft: Spacing.S,
|
|
110
111
|
flex: 1,
|
|
111
|
-
fontSize: scaleSize(
|
|
112
|
+
fontSize: scaleSize(14),
|
|
112
113
|
paddingVertical: Spacing.XS,
|
|
113
114
|
},
|
|
114
115
|
searchInputView: {
|
|
@@ -145,7 +146,7 @@ export default StyleSheet.create({
|
|
|
145
146
|
},
|
|
146
147
|
otpFloatingView: {
|
|
147
148
|
position: 'absolute',
|
|
148
|
-
top: -Spacing.
|
|
149
|
+
top: scaleSize(-Spacing.M + 2),
|
|
149
150
|
alignSelf: 'center',
|
|
150
151
|
paddingHorizontal: Spacing.S,
|
|
151
152
|
},
|
|
@@ -156,4 +157,33 @@ export default StyleSheet.create({
|
|
|
156
157
|
alignItems: 'center',
|
|
157
158
|
justifyContent: 'center',
|
|
158
159
|
},
|
|
160
|
+
|
|
161
|
+
//DropDown
|
|
162
|
+
inputDropDownWrapper: {
|
|
163
|
+
flexDirection: 'row',
|
|
164
|
+
marginTop: Spacing.S,
|
|
165
|
+
},
|
|
166
|
+
inputDropDownView: {
|
|
167
|
+
flex: 1,
|
|
168
|
+
flexDirection: 'row',
|
|
169
|
+
paddingLeft: Spacing.M,
|
|
170
|
+
},
|
|
171
|
+
iconViewDropDown: {
|
|
172
|
+
flexDirection: 'row',
|
|
173
|
+
marginRight: Spacing.M,
|
|
174
|
+
},
|
|
175
|
+
textViewDropDown: {
|
|
176
|
+
flex: 1,
|
|
177
|
+
marginVertical: Spacing.M,
|
|
178
|
+
marginRight: Spacing.S,
|
|
179
|
+
justifyContent: 'center',
|
|
180
|
+
},
|
|
181
|
+
multilineContainer: {
|
|
182
|
+
borderWidth: 1,
|
|
183
|
+
borderRadius: Radius.S,
|
|
184
|
+
},
|
|
185
|
+
leadingIconContainerDropDown: {
|
|
186
|
+
borderRadius: Radius.XS,
|
|
187
|
+
overflow: 'hidden',
|
|
188
|
+
},
|
|
159
189
|
});
|
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
|
|
64
|
+
if (typing !== value) {
|
|
65
65
|
setValue(typing);
|
|
66
66
|
}
|
|
67
67
|
};
|
package/Layout/Card.tsx
CHANGED
|
@@ -86,7 +86,7 @@ const Card: React.FC<CardProps> = ({
|
|
|
86
86
|
{rows.map((i: React.ReactElement, index: number) => {
|
|
87
87
|
return (
|
|
88
88
|
<View key={`Item${cursor}${index}`} style={{flexDirection: 'row'}}>
|
|
89
|
-
{index
|
|
89
|
+
{index !== 0 && (
|
|
90
90
|
<View style={{width: gridContext.gutterSize}}></View>
|
|
91
91
|
)}
|
|
92
92
|
{i}
|
|
@@ -126,14 +126,14 @@ const Card: React.FC<CardProps> = ({
|
|
|
126
126
|
rows = [item];
|
|
127
127
|
}
|
|
128
128
|
|
|
129
|
-
if (i
|
|
129
|
+
if (i === arrayChild.length - 1) {
|
|
130
130
|
cursor += 1;
|
|
131
131
|
element.push(addRowView(rows, cursor, true));
|
|
132
132
|
}
|
|
133
133
|
}
|
|
134
134
|
} else {
|
|
135
135
|
element.push(children);
|
|
136
|
-
if (children?.type
|
|
136
|
+
if (children?.type === Fragment) {
|
|
137
137
|
return renderView(children?.props.children);
|
|
138
138
|
}
|
|
139
139
|
}
|
|
@@ -144,6 +144,7 @@ const Card: React.FC<CardProps> = ({
|
|
|
144
144
|
<GridContext.Provider value={gridContext}>
|
|
145
145
|
<View
|
|
146
146
|
{...props}
|
|
147
|
+
onLayout={undefined}
|
|
147
148
|
style={[
|
|
148
149
|
{backgroundColor: theme.colors.background.surface},
|
|
149
150
|
style,
|
|
@@ -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) {
|
|
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
|
+
});
|
package/Layout/GridSystem.tsx
CHANGED
|
@@ -53,7 +53,7 @@ const GridSystem: React.FC<any> = ({
|
|
|
53
53
|
{list.map((_, index) => {
|
|
54
54
|
return (
|
|
55
55
|
<View style={{flexDirection: 'row'}} key={index.toString()}>
|
|
56
|
-
{index
|
|
56
|
+
{index !== 0 && <View style={{width: grid.gutterSize}} />}
|
|
57
57
|
<View
|
|
58
58
|
key={`Grid${index.toString()}`}
|
|
59
59
|
pointerEvents="none"
|
package/Layout/ItemList.tsx
CHANGED
|
@@ -20,7 +20,7 @@ const ItemList = forwardRef(
|
|
|
20
20
|
contentContainerStyle,
|
|
21
21
|
...props
|
|
22
22
|
}: ItemListProps,
|
|
23
|
-
ref
|
|
23
|
+
ref
|
|
24
24
|
) => {
|
|
25
25
|
const {gutterSize, numberOfColumns} = useContext(GridContext);
|
|
26
26
|
const widthItem = (widthSpan ?? numberOfColumns) as SpanNumber;
|
|
@@ -41,6 +41,7 @@ const ItemList = forwardRef(
|
|
|
41
41
|
<FlatList
|
|
42
42
|
ref={ref as React.RefObject<FlatList>}
|
|
43
43
|
{...props}
|
|
44
|
+
key={`ItemList-${numColumns}`}
|
|
44
45
|
numColumns={numColumns}
|
|
45
46
|
renderItem={_renderItem}
|
|
46
47
|
horizontal={false}
|
|
@@ -49,7 +50,7 @@ const ItemList = forwardRef(
|
|
|
49
50
|
contentContainerStyle={[contentContainerStyle, styles.protectedStyle]}
|
|
50
51
|
/>
|
|
51
52
|
);
|
|
52
|
-
}
|
|
53
|
+
}
|
|
53
54
|
);
|
|
54
55
|
|
|
55
56
|
export default ItemList;
|