@momo-kits/foundation 0.161.2-test.1 → 0.162.2-test.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.tsx +2 -4
- package/Application/BottomTab/BottomTabBar.tsx +15 -15
- package/Application/BottomTab/index.tsx +55 -33
- package/Application/Components/BackgroundImageView.tsx +6 -22
- package/Application/Components/HeaderAnimated.tsx +29 -32
- package/Application/Components/HeaderBackground.tsx +26 -20
- package/Application/Components/HeaderExtendHeader.tsx +94 -114
- package/Application/Components/HeaderLeft.tsx +1 -1
- package/Application/Components/HeaderTitle.tsx +10 -39
- package/Application/Components/SearchHeader.tsx +21 -16
- package/Application/types.ts +4 -4
- package/Application/utils.tsx +3 -4
- package/Badge/BadgeDotAnimation.tsx +71 -53
- package/Button/index.tsx +4 -1
- package/Input/InputOTP.tsx +23 -38
- package/Layout/FloatingButton.tsx +59 -59
- package/Layout/Screen.tsx +57 -66
- package/Loader/ProgressBar.tsx +18 -20
- package/Pagination/Dot.tsx +2 -2
- package/Pagination/PaginationScroll.tsx +27 -31
- package/Skeleton/index.tsx +24 -32
- package/package.json +1 -1
package/Input/InputOTP.tsx
CHANGED
|
@@ -8,22 +8,13 @@ import React, {
|
|
|
8
8
|
useState,
|
|
9
9
|
} from 'react';
|
|
10
10
|
import {
|
|
11
|
+
Animated,
|
|
11
12
|
PixelRatio,
|
|
12
13
|
TextInput,
|
|
13
14
|
TextInputFocusEvent,
|
|
14
15
|
TouchableOpacity,
|
|
15
16
|
View,
|
|
16
17
|
} from 'react-native';
|
|
17
|
-
import Animated, {
|
|
18
|
-
cancelAnimation,
|
|
19
|
-
Easing,
|
|
20
|
-
useAnimatedStyle,
|
|
21
|
-
useSharedValue,
|
|
22
|
-
withDelay,
|
|
23
|
-
withRepeat,
|
|
24
|
-
withSequence,
|
|
25
|
-
withTiming,
|
|
26
|
-
} from 'react-native-reanimated';
|
|
27
18
|
import { useComponentId } from '../Application';
|
|
28
19
|
import { Spacing, Styles } from '../Consts';
|
|
29
20
|
import { useScaleSize, Text } from '../Text';
|
|
@@ -41,43 +32,37 @@ import {
|
|
|
41
32
|
const OTPCaret: FC<CaretProps> = ({ index, length }) => {
|
|
42
33
|
const DURATION = 300;
|
|
43
34
|
const { theme } = useContext(ApplicationContext);
|
|
44
|
-
const opacity =
|
|
35
|
+
const opacity = useRef(new Animated.Value(0)).current;
|
|
45
36
|
|
|
46
37
|
useEffect(() => {
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
DURATION
|
|
52
|
-
|
|
53
|
-
),
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
38
|
+
Animated.loop(
|
|
39
|
+
Animated.sequence([
|
|
40
|
+
Animated.timing(opacity, {
|
|
41
|
+
toValue: 1,
|
|
42
|
+
duration: DURATION,
|
|
43
|
+
useNativeDriver: true,
|
|
44
|
+
}),
|
|
45
|
+
Animated.delay(DURATION * 2),
|
|
46
|
+
Animated.timing(opacity, {
|
|
47
|
+
toValue: 0,
|
|
48
|
+
duration: DURATION,
|
|
49
|
+
useNativeDriver: true,
|
|
50
|
+
}),
|
|
51
|
+
]),
|
|
52
|
+
).start();
|
|
61
53
|
}, [opacity]);
|
|
62
|
-
|
|
63
|
-
const animatedStyle = useAnimatedStyle(() => ({
|
|
64
|
-
opacity: opacity.value,
|
|
65
|
-
}));
|
|
66
|
-
|
|
67
54
|
const spacingStyle = !isNaN(Number(length)) &&
|
|
68
55
|
index !== Number(length) - 1 && { marginRight: Spacing.L };
|
|
69
56
|
|
|
70
57
|
return (
|
|
71
58
|
<View style={[Styles.rowCenter, spacingStyle]}>
|
|
72
59
|
<Animated.View
|
|
73
|
-
style={
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
animatedStyle,
|
|
80
|
-
]}
|
|
60
|
+
style={{
|
|
61
|
+
height: useScaleSize(12),
|
|
62
|
+
width: 1,
|
|
63
|
+
backgroundColor: theme.colors.primary,
|
|
64
|
+
opacity,
|
|
65
|
+
}}
|
|
81
66
|
/>
|
|
82
67
|
<Text color={theme.colors.text.hint} typography={'body_default_regular'}>
|
|
83
68
|
-
|
|
@@ -1,18 +1,17 @@
|
|
|
1
|
-
import React, { useContext, useEffect, useState } from 'react';
|
|
2
1
|
import {
|
|
2
|
+
default as React,
|
|
3
|
+
useContext,
|
|
4
|
+
useEffect,
|
|
5
|
+
useRef,
|
|
6
|
+
useState,
|
|
7
|
+
} from 'react';
|
|
8
|
+
import {
|
|
9
|
+
Animated,
|
|
3
10
|
LayoutChangeEvent,
|
|
4
11
|
StyleSheet,
|
|
5
12
|
TouchableOpacity,
|
|
6
13
|
View,
|
|
7
14
|
} from 'react-native';
|
|
8
|
-
import Animated, {
|
|
9
|
-
useAnimatedReaction,
|
|
10
|
-
useAnimatedStyle,
|
|
11
|
-
useSharedValue,
|
|
12
|
-
withTiming,
|
|
13
|
-
runOnJS,
|
|
14
|
-
type SharedValue,
|
|
15
|
-
} from 'react-native-reanimated';
|
|
16
15
|
import { ApplicationContext } from '../Context';
|
|
17
16
|
import { Icon } from '../Icon';
|
|
18
17
|
import { useScaleSize } from '../Text';
|
|
@@ -24,7 +23,7 @@ export interface FloatingButtonProps {
|
|
|
24
23
|
icon?: string;
|
|
25
24
|
iconColor?: string;
|
|
26
25
|
size?: 'small' | 'large';
|
|
27
|
-
animatedValue?:
|
|
26
|
+
animatedValue?: Animated.Value;
|
|
28
27
|
bottom?: number;
|
|
29
28
|
renderComponent?: () => React.ReactNode;
|
|
30
29
|
}
|
|
@@ -43,67 +42,68 @@ export const FloatingButton: React.FC<FloatingButtonProps> = ({
|
|
|
43
42
|
const { theme } = useContext(ApplicationContext);
|
|
44
43
|
const scaledFontSize = useScaleSize(16);
|
|
45
44
|
const scaledLineHeight = useScaleSize(22);
|
|
46
|
-
const maxWidth =
|
|
45
|
+
const maxWidth = useRef(0);
|
|
47
46
|
const minWidth = size === 'small' ? 36 : 48;
|
|
48
|
-
const opacityAnimated =
|
|
49
|
-
const widthAnimated =
|
|
50
|
-
const lastOffset =
|
|
51
|
-
const lastDirection =
|
|
52
|
-
const [showText, setShowText] = useState(true);
|
|
47
|
+
const [opacityAnimated] = useState(new Animated.Value(0)); // Initial opacity set to 0
|
|
48
|
+
const [widthAnimated, setWidthAnimated] = useState<Animated.Value>();
|
|
49
|
+
const lastOffset = useRef(0);
|
|
50
|
+
const lastDirection = useRef<string>(null);
|
|
51
|
+
const [showText, setShowText] = React.useState(true);
|
|
53
52
|
|
|
54
53
|
useEffect(() => {
|
|
55
54
|
if (!label) return;
|
|
56
|
-
opacityAnimated.value = withTiming(1, { duration: 100 });
|
|
57
|
-
}, [label, opacityAnimated]);
|
|
58
55
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
56
|
+
Animated.timing(opacityAnimated, {
|
|
57
|
+
toValue: 1,
|
|
58
|
+
duration: 100,
|
|
59
|
+
useNativeDriver: true,
|
|
60
|
+
}).start();
|
|
61
|
+
|
|
62
|
+
const listener = animatedValue?.addListener(({ value }) => {
|
|
63
|
+
if (value !== lastOffset.current && value > 0) {
|
|
64
|
+
const direction = value > lastOffset.current ? 'down' : 'up';
|
|
65
|
+
lastOffset.current = value;
|
|
66
|
+
if (lastDirection.current !== direction) {
|
|
67
|
+
lastDirection.current = direction;
|
|
69
68
|
if (direction === 'down') {
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
69
|
+
Animated.timing(opacityAnimated, {
|
|
70
|
+
toValue: 0,
|
|
71
|
+
duration: 100,
|
|
72
|
+
useNativeDriver: true,
|
|
73
|
+
}).start();
|
|
74
|
+
Animated.timing(widthAnimated!, {
|
|
75
|
+
toValue: minWidth,
|
|
76
|
+
duration: 100,
|
|
77
|
+
useNativeDriver: false,
|
|
78
|
+
}).start(() => setShowText(false));
|
|
78
79
|
} else {
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
80
|
+
Animated.timing(opacityAnimated, {
|
|
81
|
+
toValue: 1,
|
|
82
|
+
duration: 100,
|
|
83
|
+
useNativeDriver: true,
|
|
84
|
+
}).start();
|
|
85
|
+
Animated.timing(widthAnimated!, {
|
|
86
|
+
toValue: maxWidth.current,
|
|
87
|
+
duration: 100,
|
|
88
|
+
useNativeDriver: false,
|
|
89
|
+
}).start(() => setShowText(true));
|
|
87
90
|
}
|
|
88
91
|
}
|
|
89
92
|
}
|
|
90
|
-
}
|
|
91
|
-
[label, animatedValue, minWidth],
|
|
92
|
-
);
|
|
93
|
-
|
|
94
|
-
const containerStyle = useAnimatedStyle(() => ({
|
|
95
|
-
width: widthAnimated.value ?? undefined,
|
|
96
|
-
}));
|
|
93
|
+
});
|
|
97
94
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
95
|
+
return () => {
|
|
96
|
+
if (listener) {
|
|
97
|
+
animatedValue?.removeListener(listener);
|
|
98
|
+
}
|
|
99
|
+
};
|
|
100
|
+
}, [animatedValue, label, minWidth, opacityAnimated, widthAnimated]);
|
|
101
101
|
|
|
102
102
|
const handleLayout = (event: LayoutChangeEvent) => {
|
|
103
103
|
const layout = event.nativeEvent.layout;
|
|
104
|
-
if (widthAnimated
|
|
105
|
-
maxWidth.
|
|
106
|
-
|
|
104
|
+
if (widthAnimated) return;
|
|
105
|
+
maxWidth.current = layout.width;
|
|
106
|
+
setWidthAnimated(new Animated.Value(layout.width));
|
|
107
107
|
};
|
|
108
108
|
|
|
109
109
|
if (renderComponent) {
|
|
@@ -132,11 +132,11 @@ export const FloatingButton: React.FC<FloatingButtonProps> = ({
|
|
|
132
132
|
{
|
|
133
133
|
right: position === 'right' ? 12 : undefined,
|
|
134
134
|
alignSelf: position === 'center' ? 'center' : 'flex-end',
|
|
135
|
+
width: widthAnimated,
|
|
135
136
|
height: size === 'small' ? 36 : 48,
|
|
136
137
|
backgroundColor: theme.colors.primary,
|
|
137
138
|
bottom,
|
|
138
139
|
},
|
|
139
|
-
containerStyle,
|
|
140
140
|
]}
|
|
141
141
|
>
|
|
142
142
|
<TouchableOpacity
|
|
@@ -156,9 +156,9 @@ export const FloatingButton: React.FC<FloatingButtonProps> = ({
|
|
|
156
156
|
{
|
|
157
157
|
fontSize: scaledFontSize,
|
|
158
158
|
lineHeight: scaledLineHeight,
|
|
159
|
+
opacity: opacityAnimated,
|
|
159
160
|
color: 'white',
|
|
160
161
|
},
|
|
161
|
-
labelStyle,
|
|
162
162
|
]}
|
|
163
163
|
numberOfLines={1}
|
|
164
164
|
>
|
package/Layout/Screen.tsx
CHANGED
|
@@ -12,6 +12,7 @@ import React, {
|
|
|
12
12
|
useRef,
|
|
13
13
|
} from 'react';
|
|
14
14
|
import {
|
|
15
|
+
Animated,
|
|
15
16
|
KeyboardAvoidingView,
|
|
16
17
|
NativeScrollEvent,
|
|
17
18
|
NativeSyntheticEvent,
|
|
@@ -24,13 +25,6 @@ import {
|
|
|
24
25
|
View,
|
|
25
26
|
ViewProps,
|
|
26
27
|
} from 'react-native';
|
|
27
|
-
import Animated, {
|
|
28
|
-
runOnJS,
|
|
29
|
-
useAnimatedScrollHandler,
|
|
30
|
-
useSharedValue,
|
|
31
|
-
withTiming,
|
|
32
|
-
type SharedValue,
|
|
33
|
-
} from 'react-native-reanimated';
|
|
34
28
|
import { useSafeAreaInsets } from 'react-native-safe-area-context';
|
|
35
29
|
import { ApplicationContext, ScreenContext } from '../Context';
|
|
36
30
|
import Navigation from '../Application/Navigation';
|
|
@@ -144,7 +138,7 @@ export interface ScreenProps extends ViewProps {
|
|
|
144
138
|
/**
|
|
145
139
|
* Optional. Animated value for header.
|
|
146
140
|
*/
|
|
147
|
-
animatedValue?:
|
|
141
|
+
animatedValue?: Animated.Value;
|
|
148
142
|
|
|
149
143
|
/**
|
|
150
144
|
* Optional. If `true`, use shadow header.
|
|
@@ -201,20 +195,16 @@ const Screen = forwardRef(
|
|
|
201
195
|
const screen: any = useContext(ScreenContext);
|
|
202
196
|
const insets = useSafeAreaInsets();
|
|
203
197
|
const heightHeader = useHeaderHeight();
|
|
204
|
-
const
|
|
205
|
-
|
|
198
|
+
const animatedValue = useRef<Animated.Value>(
|
|
199
|
+
customAnimatedValue || new Animated.Value(0),
|
|
200
|
+
);
|
|
206
201
|
const currentTint = useRef<string | undefined>(undefined);
|
|
207
202
|
const isTab = navigation?.instance?.getState?.()?.type === 'tab';
|
|
208
203
|
|
|
209
|
-
let handleScroll
|
|
204
|
+
let handleScroll;
|
|
210
205
|
let Component: any = View;
|
|
211
206
|
|
|
212
|
-
// AI-GENERATED START
|
|
213
|
-
// On iOS the home indicator is ~34pt but visual safe area needs only ~21pt cap.
|
|
214
|
-
// On Android 15+ edge-to-edge the nav bar can be 48dp — no cap needed.
|
|
215
207
|
const bottomInset = Platform.OS === 'ios' ? Math.min(insets.bottom, 21) : insets.bottom;
|
|
216
|
-
// AI-GENERATED END
|
|
217
|
-
|
|
218
208
|
let keyboardOffset = heightHeader - bottomInset;
|
|
219
209
|
if (headerType === 'extended' || animatedHeader || inputSearchProps) {
|
|
220
210
|
keyboardOffset = -bottomInset;
|
|
@@ -259,8 +249,9 @@ const Screen = forwardRef(
|
|
|
259
249
|
interpolate={{
|
|
260
250
|
inputRange: [0, 50],
|
|
261
251
|
outputRange: [1, 0],
|
|
252
|
+
extrapolate: 'clamp',
|
|
262
253
|
}}
|
|
263
|
-
animatedValue={animatedValue}
|
|
254
|
+
animatedValue={animatedValue.current}
|
|
264
255
|
/>
|
|
265
256
|
),
|
|
266
257
|
};
|
|
@@ -275,7 +266,7 @@ const Screen = forwardRef(
|
|
|
275
266
|
headerBackground: (props: any) => (
|
|
276
267
|
<HeaderBackground
|
|
277
268
|
{...props}
|
|
278
|
-
animatedValue={animatedValue}
|
|
269
|
+
animatedValue={animatedValue.current}
|
|
279
270
|
useShadowHeader={useShadowHeader}
|
|
280
271
|
headerBackground={headerBackground}
|
|
281
272
|
gradientColor={gradientColor}
|
|
@@ -294,8 +285,9 @@ const Screen = forwardRef(
|
|
|
294
285
|
interpolate={{
|
|
295
286
|
inputRange: [0, 50],
|
|
296
287
|
outputRange: [1, 0],
|
|
288
|
+
extrapolate: 'clamp',
|
|
297
289
|
}}
|
|
298
|
-
animatedValue={animatedValue}
|
|
290
|
+
animatedValue={animatedValue.current}
|
|
299
291
|
/>
|
|
300
292
|
),
|
|
301
293
|
};
|
|
@@ -330,7 +322,7 @@ const Screen = forwardRef(
|
|
|
330
322
|
headerBackground: (props: any) => (
|
|
331
323
|
<HeaderBackground
|
|
332
324
|
{...props}
|
|
333
|
-
animatedValue={animatedValue}
|
|
325
|
+
animatedValue={animatedValue.current}
|
|
334
326
|
useGradient={false}
|
|
335
327
|
useShadowHeader={useShadowHeader}
|
|
336
328
|
headerBackground={headerBackground}
|
|
@@ -368,8 +360,9 @@ const Screen = forwardRef(
|
|
|
368
360
|
interpolate={{
|
|
369
361
|
inputRange: [0, 50],
|
|
370
362
|
outputRange: [1, 0],
|
|
363
|
+
extrapolate: 'clamp',
|
|
371
364
|
}}
|
|
372
|
-
animatedValue={animatedValue}
|
|
365
|
+
animatedValue={animatedValue.current}
|
|
373
366
|
/>
|
|
374
367
|
),
|
|
375
368
|
};
|
|
@@ -398,7 +391,7 @@ const Screen = forwardRef(
|
|
|
398
391
|
headerLeft: (props: any) =>
|
|
399
392
|
params?.hiddenBack ? null : <HeaderLeft {...props} />,
|
|
400
393
|
headerTitle: () => (
|
|
401
|
-
<SearchHeader {...params} animatedValue={animatedValue} />
|
|
394
|
+
<SearchHeader {...params} animatedValue={animatedValue.current} />
|
|
402
395
|
),
|
|
403
396
|
};
|
|
404
397
|
|
|
@@ -449,51 +442,45 @@ const Screen = forwardRef(
|
|
|
449
442
|
});
|
|
450
443
|
});
|
|
451
444
|
|
|
452
|
-
const onTintColorChange = useCallback(
|
|
453
|
-
(offsetY: number) => {
|
|
454
|
-
if (!animatedHeader) return;
|
|
455
|
-
let color = animatedHeader?.headerTintColor ?? Colors.black_17;
|
|
456
|
-
if (offsetY > 50) {
|
|
457
|
-
color = Colors.black_17;
|
|
458
|
-
}
|
|
459
|
-
if (color !== currentTint.current) {
|
|
460
|
-
currentTint.current = color;
|
|
461
|
-
navigation?.setOptions({
|
|
462
|
-
headerTintColor: color,
|
|
463
|
-
});
|
|
464
|
-
let barStyle: StatusBarStyle = 'dark-content';
|
|
465
|
-
if (currentTint.current === Colors.black_01) {
|
|
466
|
-
barStyle = 'light-content';
|
|
467
|
-
}
|
|
468
|
-
StatusBar.setBarStyle(barStyle, true);
|
|
469
|
-
}
|
|
470
|
-
},
|
|
471
|
-
[animatedHeader, navigation],
|
|
472
|
-
);
|
|
473
|
-
|
|
474
|
-
const emitOnScroll = useCallback(
|
|
475
|
-
(offsetY: number) => {
|
|
476
|
-
scrollViewProps?.onScroll?.({
|
|
477
|
-
nativeEvent: { contentOffset: { x: 0, y: offsetY } },
|
|
478
|
-
} as NativeSyntheticEvent<NativeScrollEvent>);
|
|
479
|
-
},
|
|
480
|
-
[scrollViewProps],
|
|
481
|
-
);
|
|
482
|
-
|
|
483
|
-
const scrollHandler = useAnimatedScrollHandler({
|
|
484
|
-
onScroll: (event) => {
|
|
485
|
-
animatedValue.value = event.contentOffset.y;
|
|
486
|
-
runOnJS(emitOnScroll)(event.contentOffset.y);
|
|
487
|
-
runOnJS(onTintColorChange)(event.contentOffset.y);
|
|
488
|
-
},
|
|
489
|
-
});
|
|
490
|
-
|
|
491
445
|
/**
|
|
492
446
|
* animated when use scroll && animated value
|
|
493
447
|
*/
|
|
494
448
|
if (scrollable) {
|
|
495
449
|
Component = Animated.ScrollView;
|
|
496
|
-
handleScroll =
|
|
450
|
+
handleScroll = Animated.event(
|
|
451
|
+
[
|
|
452
|
+
{
|
|
453
|
+
nativeEvent: {
|
|
454
|
+
contentOffset: { y: animatedValue.current as Animated.Value },
|
|
455
|
+
},
|
|
456
|
+
},
|
|
457
|
+
],
|
|
458
|
+
{
|
|
459
|
+
useNativeDriver: true,
|
|
460
|
+
listener: (e: NativeSyntheticEvent<NativeScrollEvent>) => {
|
|
461
|
+
scrollViewProps?.onScroll?.(e);
|
|
462
|
+
if (animatedHeader) {
|
|
463
|
+
const offsetY = e.nativeEvent.contentOffset.y;
|
|
464
|
+
let color = animatedHeader?.headerTintColor ?? Colors.black_17;
|
|
465
|
+
if (offsetY > 50) {
|
|
466
|
+
color = Colors.black_17;
|
|
467
|
+
}
|
|
468
|
+
if (color !== currentTint.current) {
|
|
469
|
+
currentTint.current = color;
|
|
470
|
+
navigation?.setOptions({
|
|
471
|
+
headerTintColor: color,
|
|
472
|
+
});
|
|
473
|
+
|
|
474
|
+
let barStyle: StatusBarStyle = 'dark-content';
|
|
475
|
+
if (currentTint.current === Colors.black_01) {
|
|
476
|
+
barStyle = 'light-content';
|
|
477
|
+
}
|
|
478
|
+
StatusBar.setBarStyle(barStyle, true);
|
|
479
|
+
}
|
|
480
|
+
}
|
|
481
|
+
},
|
|
482
|
+
},
|
|
483
|
+
);
|
|
497
484
|
}
|
|
498
485
|
|
|
499
486
|
/**
|
|
@@ -503,7 +490,11 @@ const Screen = forwardRef(
|
|
|
503
490
|
const handleScrollEnd = (e: NativeSyntheticEvent<NativeScrollEvent>) => {
|
|
504
491
|
const offsetY = e.nativeEvent.contentOffset.y;
|
|
505
492
|
if (inputSearchProps && offsetY < 100 && offsetY > 0) {
|
|
506
|
-
animatedValue.
|
|
493
|
+
Animated.timing(animatedValue.current, {
|
|
494
|
+
toValue: 0,
|
|
495
|
+
useNativeDriver: true,
|
|
496
|
+
duration: 300,
|
|
497
|
+
}).start();
|
|
507
498
|
ref?.scrollTo?.({ y: 0, animated: true });
|
|
508
499
|
}
|
|
509
500
|
scrollViewProps?.onScrollEndDrag?.(e);
|
|
@@ -519,7 +510,7 @@ const Screen = forwardRef(
|
|
|
519
510
|
style={[styles.screenBanner, { maxHeight: 210 + layoutOffset }]}
|
|
520
511
|
>
|
|
521
512
|
{animatedHeader?.component({
|
|
522
|
-
animatedValue: animatedValue,
|
|
513
|
+
animatedValue: animatedValue.current,
|
|
523
514
|
})}
|
|
524
515
|
</View>
|
|
525
516
|
);
|
|
@@ -586,7 +577,7 @@ const Screen = forwardRef(
|
|
|
586
577
|
headerType={headerType}
|
|
587
578
|
heightHeader={heightHeader}
|
|
588
579
|
headerRightWidth={headerRightWidth}
|
|
589
|
-
animatedValue={animatedValue}
|
|
580
|
+
animatedValue={animatedValue.current}
|
|
590
581
|
inputSearchProps={inputSearchProps}
|
|
591
582
|
navigation={navigation}
|
|
592
583
|
inputSearchRef={inputSearchRef}
|
|
@@ -624,7 +615,7 @@ const Screen = forwardRef(
|
|
|
624
615
|
<View>
|
|
625
616
|
<FloatingButton
|
|
626
617
|
{...floatingButtonProps}
|
|
627
|
-
animatedValue={animatedValue}
|
|
618
|
+
animatedValue={animatedValue.current}
|
|
628
619
|
bottom={
|
|
629
620
|
Footer || isTab ? 12 : bottomInset + Spacing.S
|
|
630
621
|
}
|
package/Loader/ProgressBar.tsx
CHANGED
|
@@ -1,10 +1,5 @@
|
|
|
1
|
-
import React, { FC, useContext, useEffect } from 'react';
|
|
2
|
-
import { View } from 'react-native';
|
|
3
|
-
import Animated, {
|
|
4
|
-
useAnimatedStyle,
|
|
5
|
-
useSharedValue,
|
|
6
|
-
withTiming,
|
|
7
|
-
} from 'react-native-reanimated';
|
|
1
|
+
import React, { FC, useContext, useEffect, useRef } from 'react';
|
|
2
|
+
import { Animated, View } from 'react-native';
|
|
8
3
|
import styles from './styles';
|
|
9
4
|
import { ProgressBarProps } from './types';
|
|
10
5
|
import { ApplicationContext } from '../Context';
|
|
@@ -12,15 +7,20 @@ import { Radius } from '../Consts';
|
|
|
12
7
|
|
|
13
8
|
const ProgressBar: FC<ProgressBarProps> = ({ percent = 0, style }) => {
|
|
14
9
|
const { theme } = useContext(ApplicationContext);
|
|
15
|
-
const animation =
|
|
10
|
+
const animation = useRef(new Animated.Value(0)).current;
|
|
16
11
|
|
|
17
12
|
useEffect(() => {
|
|
18
|
-
|
|
13
|
+
Animated.timing(animation, {
|
|
14
|
+
toValue: percent,
|
|
15
|
+
duration: 200,
|
|
16
|
+
useNativeDriver: false,
|
|
17
|
+
}).start();
|
|
19
18
|
}, [percent, animation]);
|
|
20
19
|
|
|
21
|
-
const
|
|
22
|
-
|
|
23
|
-
|
|
20
|
+
const width = animation.interpolate({
|
|
21
|
+
inputRange: [0, 100],
|
|
22
|
+
outputRange: ['0%', '100%'],
|
|
23
|
+
});
|
|
24
24
|
|
|
25
25
|
return (
|
|
26
26
|
<View
|
|
@@ -31,14 +31,12 @@ const ProgressBar: FC<ProgressBarProps> = ({ percent = 0, style }) => {
|
|
|
31
31
|
]}
|
|
32
32
|
>
|
|
33
33
|
<Animated.View
|
|
34
|
-
style={
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
animatedStyle,
|
|
41
|
-
]}
|
|
34
|
+
style={{
|
|
35
|
+
height: 4,
|
|
36
|
+
borderRadius: Radius.XXS,
|
|
37
|
+
width,
|
|
38
|
+
backgroundColor: theme.colors.primary,
|
|
39
|
+
}}
|
|
42
40
|
/>
|
|
43
41
|
</View>
|
|
44
42
|
);
|
package/Pagination/Dot.tsx
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React, { FC, useContext } from 'react';
|
|
2
|
-
import {
|
|
2
|
+
import { Animated } from 'react-native';
|
|
3
3
|
import styles from './styles';
|
|
4
4
|
import { DotProps } from './types';
|
|
5
5
|
import { ApplicationContext } from '../Context';
|
|
@@ -13,7 +13,7 @@ const Dot: FC<DotProps> = ({ active, style }) => {
|
|
|
13
13
|
{ backgroundColor: theme.colors.background.pressed },
|
|
14
14
|
];
|
|
15
15
|
|
|
16
|
-
return <View style={[style, dotStyle]} />;
|
|
16
|
+
return <Animated.View style={[style, dotStyle]} />;
|
|
17
17
|
};
|
|
18
18
|
|
|
19
19
|
export default Dot;
|
|
@@ -1,12 +1,5 @@
|
|
|
1
|
-
import React, { FC, useContext, useState } from 'react';
|
|
2
|
-
import { View } from 'react-native';
|
|
3
|
-
import Animated, {
|
|
4
|
-
Extrapolation,
|
|
5
|
-
interpolate,
|
|
6
|
-
useAnimatedScrollHandler,
|
|
7
|
-
useAnimatedStyle,
|
|
8
|
-
useSharedValue,
|
|
9
|
-
} from 'react-native-reanimated';
|
|
1
|
+
import React, { FC, useContext, useRef, useState } from 'react';
|
|
2
|
+
import { Animated, View } from 'react-native';
|
|
10
3
|
import { ScrollIndicatorProps } from './types';
|
|
11
4
|
import styles from './styles';
|
|
12
5
|
import { ApplicationContext, MiniAppContext } from '../Context';
|
|
@@ -20,37 +13,40 @@ const PaginationScroll: FC<ScrollIndicatorProps> = ({
|
|
|
20
13
|
}) => {
|
|
21
14
|
const { theme } = useContext(ApplicationContext);
|
|
22
15
|
const context = useContext<any>(MiniAppContext);
|
|
23
|
-
const left =
|
|
16
|
+
const left = useRef(new Animated.Value(0)).current;
|
|
24
17
|
const [scrollViewWidth, setScrollViewWidth] = useState(0);
|
|
25
18
|
const [scrollContentWidth, setScrollContentWidth] = useState(0);
|
|
26
19
|
|
|
27
20
|
const showBaseLineDebug = context?.features?.showBaseLineDebug ?? false;
|
|
28
21
|
|
|
29
|
-
const
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
return {};
|
|
22
|
+
const translateX = () => {
|
|
23
|
+
if (scrollViewWidth && scrollContentWidth) {
|
|
24
|
+
const value = left.interpolate({
|
|
25
|
+
inputRange: [0, scrollContentWidth - scrollViewWidth],
|
|
26
|
+
outputRange: [0, INDICATOR_CONTAINER_WIDTH - INDICATOR_WIDTH],
|
|
27
|
+
extrapolate: 'clamp',
|
|
28
|
+
});
|
|
29
|
+
return { transform: [{ translateX: value }] };
|
|
38
30
|
}
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
[0, scrollContentWidth - scrollViewWidth],
|
|
42
|
-
[0, INDICATOR_CONTAINER_WIDTH - INDICATOR_WIDTH],
|
|
43
|
-
Extrapolation.CLAMP,
|
|
44
|
-
);
|
|
45
|
-
return { transform: [{ translateX: value }] };
|
|
46
|
-
});
|
|
31
|
+
return {};
|
|
32
|
+
};
|
|
47
33
|
|
|
48
34
|
const renderScrollView = () => {
|
|
49
35
|
return (
|
|
50
36
|
<Animated.ScrollView
|
|
51
|
-
ref={scrollViewRef
|
|
52
|
-
onScroll={
|
|
53
|
-
|
|
37
|
+
ref={scrollViewRef}
|
|
38
|
+
onScroll={Animated.event(
|
|
39
|
+
[
|
|
40
|
+
{
|
|
41
|
+
nativeEvent: {
|
|
42
|
+
contentOffset: {
|
|
43
|
+
x: left,
|
|
44
|
+
},
|
|
45
|
+
},
|
|
46
|
+
},
|
|
47
|
+
],
|
|
48
|
+
{ useNativeDriver: true },
|
|
49
|
+
)}
|
|
54
50
|
alwaysBounceHorizontal={false}
|
|
55
51
|
showsHorizontalScrollIndicator={false}
|
|
56
52
|
horizontal
|
|
@@ -80,7 +76,7 @@ const PaginationScroll: FC<ScrollIndicatorProps> = ({
|
|
|
80
76
|
{
|
|
81
77
|
backgroundColor: theme.colors.primary,
|
|
82
78
|
},
|
|
83
|
-
|
|
79
|
+
translateX(),
|
|
84
80
|
]}
|
|
85
81
|
/>
|
|
86
82
|
</View>
|