@momo-kits/foundation 0.169.1 → 0.169.3-beta.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.
- package/Application/BottomSheet.hooks.ts +17 -37
- package/Application/BottomSheet.parts.tsx +81 -165
- package/Application/BottomSheet.styles.ts +7 -23
- package/Application/BottomSheet.tsx +15 -67
- package/Application/BottomTab/ActiveIndicator.tsx +90 -0
- package/Application/BottomTab/BottomTabBar.styles.ts +48 -43
- package/Application/BottomTab/BottomTabBar.tsx +229 -223
- package/Application/BottomTab/BottomTabInset.tsx +14 -0
- package/Application/BottomTab/CurvedContainer.tsx +153 -0
- package/Application/BottomTab/CustomBottomTabItem.tsx +132 -108
- package/Application/BottomTab/DuoBarCompression.tsx +4 -12
- package/Application/BottomTab/DuoRailTabBar.tsx +174 -96
- package/Application/BottomTab/DuoTabBar.styles.ts +42 -84
- package/Application/BottomTab/DuoTabBar.tsx +35 -115
- package/Application/BottomTab/TabBarIcon.tsx +160 -72
- package/Application/BottomTab/TabScreen.tsx +48 -61
- package/Application/BottomTab/index.tsx +85 -125
- package/Application/BottomTab/metrics.ts +164 -0
- package/Application/BottomTab/tabItems.ts +46 -0
- package/Application/BottomTab/usePressLift.ts +32 -0
- package/Application/ModalIconButton.tsx +66 -0
- package/Application/ModalScreen.tsx +32 -15
- package/Application/__tests__/modalLayout.test.ts +128 -0
- package/Application/index.ts +10 -0
- package/Application/modalLayout.ts +177 -0
- package/Application/types.tabs.ts +5 -0
- package/Application/utils.ts +0 -36
- package/Layout/ReservedRegions.tsx +21 -4
- package/Layout/Screen.tsx +11 -2
- package/Layout/index.ts +2 -0
- package/Popup/PopupNotify.tsx +38 -68
- package/Popup/PopupPromotion.tsx +5 -4
- package/Popup/utils.ts +1 -26
- package/package.json +2 -1
- package/Application/BottomTab/DuoTabBar.parts.tsx +0 -202
- package/Application/BottomTab/badge.ts +0 -41
- package/Application/BottomTab/hooks.ts +0 -358
- package/Application/BottomTab/index.styles.ts +0 -30
package/Popup/PopupNotify.tsx
CHANGED
|
@@ -1,19 +1,15 @@
|
|
|
1
1
|
import React, { useContext, useRef, useState } from 'react';
|
|
2
|
-
import { ScrollView, StyleSheet,
|
|
2
|
+
import { ScrollView, StyleSheet, View } from 'react-native';
|
|
3
3
|
import { ApplicationContext, MiniAppContext } from '../Context';
|
|
4
4
|
import { Button } from '../Button';
|
|
5
|
-
import { Colors,
|
|
6
|
-
import { Icon } from '../Icon';
|
|
5
|
+
import { Colors, Spacing, Styles } from '../Consts';
|
|
7
6
|
import { Image } from '../Image';
|
|
8
7
|
import { Text, useScaleSize } from '../Text';
|
|
9
8
|
import { PopupNotifyProps } from './types';
|
|
10
9
|
import { scheduleOnRN } from 'react-native-worklets';
|
|
11
|
-
import {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
usePopupMaxHeight,
|
|
15
|
-
usePopupWidth,
|
|
16
|
-
} from './utils';
|
|
10
|
+
import { useModalLayout } from '../Application/modalLayout';
|
|
11
|
+
import { ModalIconButton } from '../Application/ModalIconButton';
|
|
12
|
+
import { splitHighlightText } from './utils';
|
|
17
13
|
|
|
18
14
|
const PopupNotify: React.FC<PopupNotifyProps> = ({
|
|
19
15
|
image,
|
|
@@ -30,16 +26,19 @@ const PopupNotify: React.FC<PopupNotifyProps> = ({
|
|
|
30
26
|
const context = useContext<any>(MiniAppContext);
|
|
31
27
|
const { theme, navigator, translate } = useContext(ApplicationContext);
|
|
32
28
|
const [scrollContent, setScrollContent] = useState(false);
|
|
33
|
-
const
|
|
34
|
-
const maxHeight =
|
|
35
|
-
const radius = getPopupRadius();
|
|
29
|
+
const { isFoldable, popup } = useModalLayout();
|
|
30
|
+
const { width: popupWidth, maxHeight, radius } = popup;
|
|
36
31
|
const scaledMaxHeight = useScaleSize(172);
|
|
37
32
|
|
|
38
33
|
const showBaseLineDebug = context?.features?.showBaseLineDebug ?? false;
|
|
39
34
|
const closeAction = useRef('touch_outside');
|
|
40
35
|
let descriptionStyle = {};
|
|
41
36
|
let Description: any = View;
|
|
42
|
-
if (
|
|
37
|
+
if (isFoldable) {
|
|
38
|
+
// foldables cap the popup height, the description takes what is left
|
|
39
|
+
Description = ScrollView;
|
|
40
|
+
descriptionStyle = styles.shrink;
|
|
41
|
+
} else if (scrollContent) {
|
|
43
42
|
Description = ScrollView;
|
|
44
43
|
descriptionStyle = { maxHeight: scaledMaxHeight };
|
|
45
44
|
}
|
|
@@ -165,34 +164,20 @@ const PopupNotify: React.FC<PopupNotifyProps> = ({
|
|
|
165
164
|
* build close action
|
|
166
165
|
*/
|
|
167
166
|
const buildCloseIcon = () => {
|
|
168
|
-
if (typeof onIconClose
|
|
169
|
-
return
|
|
170
|
-
<TouchableOpacity
|
|
171
|
-
accessibilityLabel={'ic_popup_close'}
|
|
172
|
-
style={styles.iconCloseContainer}
|
|
173
|
-
onPress={() => {
|
|
174
|
-
closeAction.current = 'icon_close';
|
|
175
|
-
onAction(onIconClose);
|
|
176
|
-
}}
|
|
177
|
-
>
|
|
178
|
-
<View
|
|
179
|
-
style={[
|
|
180
|
-
styles.iconClose,
|
|
181
|
-
{
|
|
182
|
-
backgroundColor: theme.colors.text.default,
|
|
183
|
-
borderColor: theme.colors.background.surface,
|
|
184
|
-
},
|
|
185
|
-
]}
|
|
186
|
-
>
|
|
187
|
-
<Icon
|
|
188
|
-
source="navigation_close"
|
|
189
|
-
color={theme.colors.background.surface}
|
|
190
|
-
size={14}
|
|
191
|
-
/>
|
|
192
|
-
</View>
|
|
193
|
-
</TouchableOpacity>
|
|
194
|
-
);
|
|
167
|
+
if (typeof onIconClose !== 'function') {
|
|
168
|
+
return null;
|
|
195
169
|
}
|
|
170
|
+
return (
|
|
171
|
+
<ModalIconButton
|
|
172
|
+
icon="navigation_close"
|
|
173
|
+
accessibilityLabel={'ic_popup_close'}
|
|
174
|
+
style={styles.iconClose}
|
|
175
|
+
onPress={() => {
|
|
176
|
+
closeAction.current = 'icon_close';
|
|
177
|
+
onAction(onIconClose);
|
|
178
|
+
}}
|
|
179
|
+
/>
|
|
180
|
+
);
|
|
196
181
|
};
|
|
197
182
|
|
|
198
183
|
const body = (
|
|
@@ -206,11 +191,17 @@ const PopupNotify: React.FC<PopupNotifyProps> = ({
|
|
|
206
191
|
]}
|
|
207
192
|
/>
|
|
208
193
|
)}
|
|
209
|
-
<View style={styles.content}>
|
|
194
|
+
<View style={[styles.content, isFoldable && styles.shrink]}>
|
|
210
195
|
<Text
|
|
211
196
|
typography={'header_default_bold'}
|
|
212
197
|
numberOfLines={3}
|
|
213
198
|
accessibilityLabel={'title_popup_notify'}
|
|
199
|
+
// keeps the title clear of the close button on a text only popup
|
|
200
|
+
style={
|
|
201
|
+
!image &&
|
|
202
|
+
typeof onIconClose === 'function' &&
|
|
203
|
+
styles.titleClearClose
|
|
204
|
+
}
|
|
214
205
|
>
|
|
215
206
|
{title}
|
|
216
207
|
</Text>
|
|
@@ -262,20 +253,7 @@ const PopupNotify: React.FC<PopupNotifyProps> = ({
|
|
|
262
253
|
showBaseLineDebug && styles.debugBaseLine,
|
|
263
254
|
]}
|
|
264
255
|
>
|
|
265
|
-
{
|
|
266
|
-
body
|
|
267
|
-
) : (
|
|
268
|
-
// scrolls when iPhone Duo landscape is too short; actions stay visible
|
|
269
|
-
<ScrollView
|
|
270
|
-
style={[
|
|
271
|
-
styles.body,
|
|
272
|
-
{ borderTopLeftRadius: radius, borderTopRightRadius: radius },
|
|
273
|
-
]}
|
|
274
|
-
bounces={false}
|
|
275
|
-
>
|
|
276
|
-
{body}
|
|
277
|
-
</ScrollView>
|
|
278
|
-
)}
|
|
256
|
+
{body}
|
|
279
257
|
<View style={styles.contentAction}>{buildAction()}</View>
|
|
280
258
|
{buildCloseIcon()}
|
|
281
259
|
</View>
|
|
@@ -288,7 +266,7 @@ const styles = StyleSheet.create({
|
|
|
288
266
|
aspectRatio: 1.7777,
|
|
289
267
|
overflow: 'hidden',
|
|
290
268
|
},
|
|
291
|
-
|
|
269
|
+
shrink: { flexShrink: 1 },
|
|
292
270
|
content: { padding: Spacing.XL },
|
|
293
271
|
description: {
|
|
294
272
|
marginTop: Spacing.S,
|
|
@@ -304,19 +282,11 @@ const styles = StyleSheet.create({
|
|
|
304
282
|
width: Spacing.S,
|
|
305
283
|
height: Spacing.S,
|
|
306
284
|
},
|
|
307
|
-
|
|
308
|
-
position: 'absolute',
|
|
309
|
-
top: -Spacing.M,
|
|
310
|
-
right: -Spacing.M,
|
|
311
|
-
padding: Spacing.XS,
|
|
312
|
-
},
|
|
285
|
+
titleClearClose: { paddingRight: Spacing.XL },
|
|
313
286
|
iconClose: {
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
justifyContent: 'center',
|
|
318
|
-
borderRadius: Radius.M,
|
|
319
|
-
borderWidth: 2,
|
|
287
|
+
position: 'absolute',
|
|
288
|
+
top: Spacing.M,
|
|
289
|
+
right: Spacing.M,
|
|
320
290
|
},
|
|
321
291
|
});
|
|
322
292
|
|
package/Popup/PopupPromotion.tsx
CHANGED
|
@@ -5,7 +5,7 @@ import { ApplicationContext, MiniAppContext } from '../Context';
|
|
|
5
5
|
import { Image } from '../Image';
|
|
6
6
|
import { Colors, Radius, Spacing } from '../Consts';
|
|
7
7
|
import { Icon } from '../Icon';
|
|
8
|
-
import {
|
|
8
|
+
import { useModalLayout } from '../Application/modalLayout';
|
|
9
9
|
|
|
10
10
|
const ASPECT_RATIO = 0.72;
|
|
11
11
|
const ICON_CLOSE_SIZE = 20;
|
|
@@ -20,9 +20,10 @@ const PopupPromotion: React.FC<PopupPromotionProps> = ({
|
|
|
20
20
|
}) => {
|
|
21
21
|
const context = useContext<any>(MiniAppContext);
|
|
22
22
|
const { theme, navigator } = useContext(ApplicationContext);
|
|
23
|
-
const
|
|
24
|
-
|
|
25
|
-
|
|
23
|
+
const {
|
|
24
|
+
popup: { width: popupWidth, maxHeight },
|
|
25
|
+
} = useModalLayout();
|
|
26
|
+
// fit the portrait image by height when a foldable leaves too little room
|
|
26
27
|
let imageWidth = popupWidth;
|
|
27
28
|
if (maxHeight !== undefined) {
|
|
28
29
|
const heightFitWidth = (maxHeight - CLOSE_ROW_HEIGHT) * ASPECT_RATIO;
|
package/Popup/utils.ts
CHANGED
|
@@ -1,30 +1,5 @@
|
|
|
1
|
-
import { Dimensions, useWindowDimensions } from 'react-native';
|
|
2
|
-
import { useSafeAreaInsets } from 'react-native-safe-area-context';
|
|
3
|
-
import { Radius, Spacing } from '../Consts';
|
|
4
|
-
import { getDuoModalBounds, isIPhoneDuo } from '../Application/utils';
|
|
5
|
-
|
|
6
1
|
type HighlightSegment = { text: string; highlight: boolean };
|
|
7
2
|
|
|
8
|
-
const usePopupWidth = () => {
|
|
9
|
-
const insets = useSafeAreaInsets();
|
|
10
|
-
const { width, height } = useWindowDimensions();
|
|
11
|
-
if (!isIPhoneDuo()) {
|
|
12
|
-
return Dimensions.get('window').width - Spacing.XL * 2;
|
|
13
|
-
}
|
|
14
|
-
return getDuoModalBounds(insets, width, height).maxWidth;
|
|
15
|
-
};
|
|
16
|
-
|
|
17
|
-
const usePopupMaxHeight = () => {
|
|
18
|
-
const insets = useSafeAreaInsets();
|
|
19
|
-
const { width, height } = useWindowDimensions();
|
|
20
|
-
if (!isIPhoneDuo()) {
|
|
21
|
-
return undefined;
|
|
22
|
-
}
|
|
23
|
-
return getDuoModalBounds(insets, width, height).maxHeight;
|
|
24
|
-
};
|
|
25
|
-
|
|
26
|
-
const getPopupRadius = () => (isIPhoneDuo() ? Radius.XL : Radius.L);
|
|
27
|
-
|
|
28
3
|
const isWordChar = (char?: string) => {
|
|
29
4
|
if (!char) {
|
|
30
5
|
return false;
|
|
@@ -76,4 +51,4 @@ const splitHighlightText = (
|
|
|
76
51
|
return segments;
|
|
77
52
|
};
|
|
78
53
|
|
|
79
|
-
export {
|
|
54
|
+
export { splitHighlightText };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@momo-kits/foundation",
|
|
3
|
-
"version": "0.169.1",
|
|
3
|
+
"version": "0.169.3-beta.1",
|
|
4
4
|
"description": "React Native Component Kits",
|
|
5
5
|
"main": "index.ts",
|
|
6
6
|
"scripts": {},
|
|
@@ -26,6 +26,7 @@
|
|
|
26
26
|
},
|
|
27
27
|
"peerDependencies": {
|
|
28
28
|
"react-native": "*",
|
|
29
|
+
"react-native-svg": "*",
|
|
29
30
|
"react-native-worklets": "0.6.1"
|
|
30
31
|
},
|
|
31
32
|
"devDependencies": {
|
|
@@ -1,202 +0,0 @@
|
|
|
1
|
-
import { CommonActions, Route } from '@react-navigation/native';
|
|
2
|
-
import { BottomTabBarProps } from '@react-navigation/bottom-tabs';
|
|
3
|
-
import React, { ReactNode, useContext, useMemo, useRef } from 'react';
|
|
4
|
-
import {
|
|
5
|
-
StyleProp,
|
|
6
|
-
StyleSheet,
|
|
7
|
-
TouchableOpacity,
|
|
8
|
-
View,
|
|
9
|
-
ViewStyle,
|
|
10
|
-
} from 'react-native';
|
|
11
|
-
import Animated from 'react-native-reanimated';
|
|
12
|
-
import { Colors } from '../../Consts';
|
|
13
|
-
import { ApplicationContext, MiniAppContext } from '../../Context';
|
|
14
|
-
import { Icon } from '../../Icon';
|
|
15
|
-
import { Text } from '../../Text';
|
|
16
|
-
import { FloatingButtonProps } from '../types';
|
|
17
|
-
import { TabBarIcon } from './TabBarIcon';
|
|
18
|
-
import { LiquidSelection, useLiquidItem } from './hooks';
|
|
19
|
-
import { styles } from './DuoTabBar.styles';
|
|
20
|
-
|
|
21
|
-
export type Props = BottomTabBarProps & {
|
|
22
|
-
activeTintColor: string;
|
|
23
|
-
inactiveTintColor: string;
|
|
24
|
-
floatingButton?: FloatingButtonProps;
|
|
25
|
-
};
|
|
26
|
-
|
|
27
|
-
export const BarMaterial: React.FC<{ radius: number }> = ({ radius }) => {
|
|
28
|
-
const { theme } = useContext(ApplicationContext);
|
|
29
|
-
return (
|
|
30
|
-
<View
|
|
31
|
-
pointerEvents={'none'}
|
|
32
|
-
style={[
|
|
33
|
-
StyleSheet.absoluteFill,
|
|
34
|
-
styles.barMaterial,
|
|
35
|
-
{
|
|
36
|
-
borderRadius: radius,
|
|
37
|
-
backgroundColor: theme.colors.background.surface,
|
|
38
|
-
borderColor: theme.colors.border.default,
|
|
39
|
-
},
|
|
40
|
-
]}
|
|
41
|
-
/>
|
|
42
|
-
);
|
|
43
|
-
};
|
|
44
|
-
|
|
45
|
-
// Figma Home-2026 tab bar "Selection": brand pink at 8%
|
|
46
|
-
const SELECTION_TINT_ALPHA = '14';
|
|
47
|
-
|
|
48
|
-
/**
|
|
49
|
-
* pink tinted capsule under the selected tab
|
|
50
|
-
*/
|
|
51
|
-
export const SelectionMaterial: React.FC<{ radius: number }> = ({ radius }) => {
|
|
52
|
-
const { theme } = useContext(ApplicationContext);
|
|
53
|
-
return (
|
|
54
|
-
<View
|
|
55
|
-
pointerEvents={'none'}
|
|
56
|
-
style={[
|
|
57
|
-
StyleSheet.absoluteFill,
|
|
58
|
-
{
|
|
59
|
-
borderRadius: radius,
|
|
60
|
-
backgroundColor: theme.colors.primary + SELECTION_TINT_ALPHA,
|
|
61
|
-
},
|
|
62
|
-
]}
|
|
63
|
-
/>
|
|
64
|
-
);
|
|
65
|
-
};
|
|
66
|
-
|
|
67
|
-
/**
|
|
68
|
-
* tab label at its design size: like the system tab bar it doesn't grow with the wide
|
|
69
|
-
* Duo displays, which Text otherwise scales up to 5pt
|
|
70
|
-
*/
|
|
71
|
-
export const TabLabel: React.FC<{
|
|
72
|
-
label: string;
|
|
73
|
-
color: string;
|
|
74
|
-
typography: 'label_xs_medium';
|
|
75
|
-
}> = ({ label, color, typography }) => {
|
|
76
|
-
const context = useContext<any>(MiniAppContext);
|
|
77
|
-
return (
|
|
78
|
-
<MiniAppContext.Provider
|
|
79
|
-
value={{
|
|
80
|
-
...context,
|
|
81
|
-
fontScale: { useOSScaleRate: false, userScaleRate: 1 },
|
|
82
|
-
}}
|
|
83
|
-
>
|
|
84
|
-
<Text numberOfLines={1} typography={typography} color={color}>
|
|
85
|
-
{label}
|
|
86
|
-
</Text>
|
|
87
|
-
</MiniAppContext.Provider>
|
|
88
|
-
);
|
|
89
|
-
};
|
|
90
|
-
|
|
91
|
-
export const getTabItems = ({
|
|
92
|
-
state,
|
|
93
|
-
descriptors,
|
|
94
|
-
navigation,
|
|
95
|
-
activeTintColor,
|
|
96
|
-
inactiveTintColor,
|
|
97
|
-
}: Props) => {
|
|
98
|
-
return state.routes.map((route: Route<string>, index: number) => {
|
|
99
|
-
const { options } = descriptors[route.key];
|
|
100
|
-
const focused = index === state.index;
|
|
101
|
-
const label = options.title ?? route.name;
|
|
102
|
-
|
|
103
|
-
const onPress = () => {
|
|
104
|
-
const event = navigation.emit({
|
|
105
|
-
type: 'tabPress',
|
|
106
|
-
target: route.key,
|
|
107
|
-
canPreventDefault: true,
|
|
108
|
-
});
|
|
109
|
-
if (!focused && !event.defaultPrevented) {
|
|
110
|
-
navigation.dispatch({
|
|
111
|
-
...CommonActions.navigate(route.name),
|
|
112
|
-
target: state.key,
|
|
113
|
-
});
|
|
114
|
-
}
|
|
115
|
-
};
|
|
116
|
-
|
|
117
|
-
const onLongPress = () => {
|
|
118
|
-
navigation.emit({ type: 'tabLongPress', target: route.key });
|
|
119
|
-
};
|
|
120
|
-
|
|
121
|
-
const renderIcon = (active: boolean) =>
|
|
122
|
-
options.tabBarIcon && (
|
|
123
|
-
<TabBarIcon
|
|
124
|
-
route={route}
|
|
125
|
-
badge={options.tabBarBadge}
|
|
126
|
-
badgeStyle={options.tabBarBadgeStyle}
|
|
127
|
-
activeOpacity={active ? 1 : 0}
|
|
128
|
-
inactiveOpacity={active ? 0 : 1}
|
|
129
|
-
activeTintColor={activeTintColor}
|
|
130
|
-
inactiveTintColor={inactiveTintColor}
|
|
131
|
-
renderIcon={options.tabBarIcon}
|
|
132
|
-
style={styles.icon}
|
|
133
|
-
/>
|
|
134
|
-
);
|
|
135
|
-
|
|
136
|
-
return { route, focused, label, onPress, onLongPress, renderIcon };
|
|
137
|
-
});
|
|
138
|
-
};
|
|
139
|
-
|
|
140
|
-
export const QrIcon: React.FC<{
|
|
141
|
-
icon: FloatingButtonProps['icon'];
|
|
142
|
-
size: number;
|
|
143
|
-
}> = ({ icon, size }) => {
|
|
144
|
-
if (typeof icon === 'string') {
|
|
145
|
-
return <Icon source={icon} size={size} color={Colors.black_01} />;
|
|
146
|
-
}
|
|
147
|
-
return <>{icon}</>;
|
|
148
|
-
};
|
|
149
|
-
|
|
150
|
-
export type TabItem = ReturnType<typeof getTabItems>[number];
|
|
151
|
-
|
|
152
|
-
/**
|
|
153
|
-
* tab item: a tap is handled here as before, a drag over the bar is handled by the bar's
|
|
154
|
-
* gesture. The active layer fades in as the lens passes over it
|
|
155
|
-
*/
|
|
156
|
-
export const LiquidTabItem: React.FC<{
|
|
157
|
-
item: TabItem;
|
|
158
|
-
itemIndex: number;
|
|
159
|
-
selection: LiquidSelection;
|
|
160
|
-
onSelect: () => void;
|
|
161
|
-
renderContent: (active: boolean) => ReactNode;
|
|
162
|
-
style: StyleProp<ViewStyle>;
|
|
163
|
-
}> = ({ item, itemIndex, selection, onSelect, renderContent, style }) => {
|
|
164
|
-
const { activeStyle, popStyle } = useLiquidItem(selection, itemIndex);
|
|
165
|
-
const activeLayerStyle = useMemo(
|
|
166
|
-
() => [StyleSheet.absoluteFill, styles.itemLayer, activeStyle],
|
|
167
|
-
[activeStyle],
|
|
168
|
-
);
|
|
169
|
-
// like the system tab bar, a held tab is still picked when released
|
|
170
|
-
const longPressed = useRef(false);
|
|
171
|
-
|
|
172
|
-
return (
|
|
173
|
-
<TouchableOpacity
|
|
174
|
-
accessibilityRole={'tab'}
|
|
175
|
-
accessibilityLabel={item.label}
|
|
176
|
-
accessibilityState={{ selected: item.focused }}
|
|
177
|
-
activeOpacity={1}
|
|
178
|
-
onPressIn={() => {
|
|
179
|
-
longPressed.current = false;
|
|
180
|
-
selection.handlePressIn(itemIndex);
|
|
181
|
-
}}
|
|
182
|
-
onPressOut={() => {
|
|
183
|
-
if (selection.handlePressOut() && longPressed.current) {
|
|
184
|
-
onSelect();
|
|
185
|
-
}
|
|
186
|
-
}}
|
|
187
|
-
onPress={onSelect}
|
|
188
|
-
onLongPress={() => {
|
|
189
|
-
longPressed.current = true;
|
|
190
|
-
item.onLongPress();
|
|
191
|
-
}}
|
|
192
|
-
style={style}
|
|
193
|
-
>
|
|
194
|
-
<Animated.View style={popStyle}>
|
|
195
|
-
<View style={styles.itemLayer}>{renderContent(false)}</View>
|
|
196
|
-
<Animated.View style={activeLayerStyle}>
|
|
197
|
-
{renderContent(true)}
|
|
198
|
-
</Animated.View>
|
|
199
|
-
</Animated.View>
|
|
200
|
-
</TouchableOpacity>
|
|
201
|
-
);
|
|
202
|
-
};
|
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
import { Colors } from '../../Consts';
|
|
2
|
-
|
|
3
|
-
export const getBadgeProps = (itemBadgeLabel: string | number | undefined) => {
|
|
4
|
-
const isNum = !isNaN(parseInt(`${itemBadgeLabel}`, 10));
|
|
5
|
-
const isDot = typeof itemBadgeLabel === 'string' && !itemBadgeLabel;
|
|
6
|
-
const isNumZero = isNum && Number(itemBadgeLabel) === 0;
|
|
7
|
-
|
|
8
|
-
let badgeLabel = itemBadgeLabel;
|
|
9
|
-
if (isNumZero) {
|
|
10
|
-
badgeLabel = undefined;
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
let badgeStyle: {
|
|
14
|
-
marginRight: number;
|
|
15
|
-
top: number;
|
|
16
|
-
backgroundColor: string;
|
|
17
|
-
width?: number;
|
|
18
|
-
} = {
|
|
19
|
-
marginRight: -8,
|
|
20
|
-
top: -4,
|
|
21
|
-
backgroundColor: Colors.orange_03,
|
|
22
|
-
};
|
|
23
|
-
|
|
24
|
-
if (isNum) {
|
|
25
|
-
badgeStyle = {
|
|
26
|
-
marginRight: -4,
|
|
27
|
-
top: -4,
|
|
28
|
-
backgroundColor: Colors.red_03,
|
|
29
|
-
};
|
|
30
|
-
}
|
|
31
|
-
if (isDot) {
|
|
32
|
-
badgeStyle = {
|
|
33
|
-
marginRight: -2,
|
|
34
|
-
top: -2,
|
|
35
|
-
backgroundColor: Colors.orange_03,
|
|
36
|
-
width: 12,
|
|
37
|
-
};
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
return { badgeLabel, badgeStyle };
|
|
41
|
-
};
|