react-native-slot-text 3.0.0 → 3.1.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/ContinuousSlot.js +8 -4
- package/ContinuousSlots.js +1 -1
- package/Slot.js +11 -10
- package/Slots.js +1 -1
- package/constants.d.ts +3 -0
- package/constants.js +5 -0
- package/package.json +1 -1
- package/types.d.ts +4 -0
package/ContinuousSlot.js
CHANGED
@@ -3,17 +3,19 @@ import { useEffect, useRef, useState } from 'react';
|
|
3
3
|
import { Text, StyleSheet, Animated, useAnimatedValue, Easing } from 'react-native';
|
4
4
|
import MaskedView from "@react-native-masked-view/masked-view";
|
5
5
|
import { easeGradient } from "react-native-easing-gradient";
|
6
|
-
import ReAnimated, { LinearTransition, FadeOutDown, FadeInUp, useSharedValue, withTiming } from 'react-native-reanimated';
|
6
|
+
import ReAnimated, { LinearTransition, FadeOutDown, FadeInUp, useSharedValue, withTiming, Easing as ReEasing } from 'react-native-reanimated';
|
7
7
|
import { LinearGradient } from "expo-linear-gradient";
|
8
8
|
import styles from './styles';
|
9
|
+
import { bezier_points } from './constants';
|
9
10
|
const GAP = 12;
|
10
11
|
const PADDING_FRACTION = .25;
|
11
12
|
const AnimatedMaskView = Animated.createAnimatedComponent(MaskedView);
|
12
13
|
const ContinuousSlot = (props) => {
|
14
|
+
const easing = bezier_points[props.easing || 'linear'];
|
13
15
|
const config = {
|
14
16
|
useNativeDriver: true,
|
15
17
|
duration: props.animationDuration,
|
16
|
-
easing: Easing.bezier(
|
18
|
+
easing: Easing.bezier(...easing)
|
17
19
|
};
|
18
20
|
const id = useRef(`rn-slottext-slot-${Math.random().toString(36).slice(0, 9)}`);
|
19
21
|
const width = useSharedValue(0);
|
@@ -35,7 +37,7 @@ const ContinuousSlot = (props) => {
|
|
35
37
|
: props.slot[0] === ',' ? 10 : 11];
|
36
38
|
width.value = newWidth > width.value
|
37
39
|
? newWidth // Growing
|
38
|
-
: withTiming(newWidth, { duration: props.animationDuration
|
40
|
+
: withTiming(newWidth, { duration: props.animationDuration });
|
39
41
|
if (typeof props.slot[0] === 'number') {
|
40
42
|
Animated.timing(slotOpacity, { toValue: 1, ...config }).start();
|
41
43
|
Animated.timing(y, {
|
@@ -70,7 +72,9 @@ const ContinuousSlot = (props) => {
|
|
70
72
|
1: { color: 'transparent' }
|
71
73
|
},
|
72
74
|
});
|
73
|
-
return (_jsx(ReAnimated.View, { layout: LinearTransition.duration(props.animationDuration
|
75
|
+
return (_jsx(ReAnimated.View, { layout: LinearTransition.duration(props.animationDuration).easing(ReEasing.bezier(...easing).factory()), entering: props.charSizes[0]
|
76
|
+
? FadeInUp.duration(props.animationDuration / 1.5).easing(ReEasing.bezier(...easing).factory())
|
77
|
+
: undefined, exiting: FadeOutDown.duration(props.animationDuration / 1.5).easing(ReEasing.bezier(...easing).factory()), children: isMeasured
|
74
78
|
?
|
75
79
|
_jsx(ReAnimated.View, { style: { height, width }, children: _jsxs(AnimatedMaskView, { maskElement: _jsx(LinearGradient, { locations: locations, colors: colors, style: StyleSheet.absoluteFill }), style: [styles.mask, { top: maskTop, bottom: maskTop }], children: [_jsx(Animated.View, { style: {
|
76
80
|
position: 'absolute',
|
package/ContinuousSlots.js
CHANGED
@@ -54,7 +54,7 @@ const ContinuousSlots = (props) => {
|
|
54
54
|
});
|
55
55
|
setSlots(parseFromLeft ? newSlots : newSlots.reverse());
|
56
56
|
}, [props.value]);
|
57
|
-
return (_jsxs(_Fragment, { children: [_jsxs(View, { style: styles.slotsContainer, children: [props.prefix && (_jsx(Animated.Text, { style: props.fontStyle, layout: LinearTransition, children: props.prefix })), slots.map((slot, i) => (_jsx(ContinuousSlot, { slot: slot, index: i, charSizes: charSizes, fontStyle: props.fontStyle, animationDuration: DEFAULT_DURATION }, `${idRef.current}-${slot[1]}`))), _jsx(Text, { style: [styles.spacer, props.fontStyle], children: "1" })] }), !sizesMeasured &&
|
57
|
+
return (_jsxs(_Fragment, { children: [_jsxs(View, { style: styles.slotsContainer, children: [props.prefix && (_jsx(Animated.Text, { style: props.fontStyle, layout: LinearTransition, children: props.prefix })), slots.map((slot, i) => (_jsx(ContinuousSlot, { slot: slot, index: i, charSizes: charSizes, fontStyle: props.fontStyle, easing: props.easing, animationDuration: DEFAULT_DURATION }, `${idRef.current}-${slot[1]}`))), _jsx(Text, { style: [styles.spacer, props.fontStyle], children: "1" })] }), !sizesMeasured &&
|
58
58
|
Array.from({ length: 10 }, (_, i) => i)
|
59
59
|
.concat([',', '.'])
|
60
60
|
.map((char, i) => (_jsx(Fragment, { children: _jsx(Text, { style: [styles.hiddenSlot, props.fontStyle], onLayout: (e) => {
|
package/Slot.js
CHANGED
@@ -4,8 +4,9 @@ import { View } from 'react-native';
|
|
4
4
|
import { Text } from 'react-native';
|
5
5
|
import Animated, { useSharedValue, withTiming, withSequence, useAnimatedStyle, interpolate, runOnJS, Easing } from 'react-native-reanimated';
|
6
6
|
import styles from './styles';
|
7
|
-
|
7
|
+
import { bezier_points } from './constants';
|
8
8
|
const Slot = (props) => {
|
9
|
+
const easing = Easing.bezier(...bezier_points[props.easing || 'linear']);
|
9
10
|
const margin = useSharedValue(0);
|
10
11
|
const y = useSharedValue(0);
|
11
12
|
const incomingY = useSharedValue(0);
|
@@ -28,12 +29,12 @@ const Slot = (props) => {
|
|
28
29
|
y.value = withTiming(-1 * props.height, { duration: props.animationDuration, easing }, () => {
|
29
30
|
props.onCompleted && runOnJS(props.onCompleted)();
|
30
31
|
});
|
31
|
-
margin.value = withTiming(-1 * props.charSizes[currentValue], { duration: props.animationDuration / 2 });
|
32
|
+
margin.value = withTiming(-1 * props.charSizes[currentValue], { duration: props.animationDuration / 2, easing });
|
32
33
|
}
|
33
34
|
// Adding slot
|
34
35
|
else if (currentValue === null) {
|
35
|
-
margin.value = withTiming(props.charSizes[incomingValue], { duration: props.animationDuration / 2 });
|
36
|
-
incomingY.value = withSequence(withTiming(-1 * props.height, { duration: 0 }), withTiming(0, { duration: props.animationDuration
|
36
|
+
margin.value = withTiming(props.charSizes[incomingValue], { duration: props.animationDuration / 2, easing });
|
37
|
+
incomingY.value = withSequence(withTiming(-1 * props.height, { duration: 0, easing }), withTiming(0, { duration: props.animationDuration }, () => {
|
37
38
|
props.onCompleted && runOnJS(props.onCompleted)();
|
38
39
|
}));
|
39
40
|
}
|
@@ -42,13 +43,13 @@ const Slot = (props) => {
|
|
42
43
|
margin.value = withTiming((props.charSizes[incomingValue] - props.charSizes[currentValue]), { duration: props.animationDuration / 2 });
|
43
44
|
if (incomingValue > currentValue) {
|
44
45
|
y.value = withTiming(props.height, { duration: props.animationDuration, easing });
|
45
|
-
incomingY.value = withSequence(withTiming(-1 * props.height, { duration: 0
|
46
|
+
incomingY.value = withSequence(withTiming(-1 * props.height, { duration: 0 }), withTiming(0, { duration: props.animationDuration }, () => {
|
46
47
|
props.onCompleted && runOnJS(props.onCompleted)();
|
47
48
|
}));
|
48
49
|
}
|
49
50
|
else if (incomingValue < currentValue) {
|
50
51
|
y.value = withTiming(-1 * props.height, { duration: props.animationDuration, easing });
|
51
|
-
incomingY.value = withSequence(withTiming(1 * props.height, { duration: 0
|
52
|
+
incomingY.value = withSequence(withTiming(1 * props.height, { duration: 0 }), withTiming(0, { duration: props.animationDuration, easing }, () => {
|
52
53
|
props.onCompleted && runOnJS(props.onCompleted)();
|
53
54
|
}));
|
54
55
|
}
|
@@ -56,13 +57,13 @@ const Slot = (props) => {
|
|
56
57
|
}, [props.slot]);
|
57
58
|
useLayoutEffect(() => {
|
58
59
|
if (props.commaPositions?.[props.index] === 1) {
|
59
|
-
commaScale.value = withTiming(1, { duration: props.animationDuration });
|
60
|
-
commaWidth.value = withSequence(withTiming(0, { duration: 0 }), withTiming(props.commaWidth, { duration: props.animationDuration }));
|
60
|
+
commaScale.value = withTiming(1, { duration: props.animationDuration, easing });
|
61
|
+
commaWidth.value = withSequence(withTiming(0, { duration: 0 }), withTiming(props.commaWidth, { duration: props.animationDuration, easing }));
|
61
62
|
}
|
62
63
|
else if (props.commaPositions?.[props.index] === -1) {
|
63
|
-
commaScale.value = withSequence(withTiming(1, { duration: 0 }), withTiming(0, { duration: props.animationDuration }));
|
64
|
+
commaScale.value = withSequence(withTiming(1, { duration: 0 }), withTiming(0, { duration: props.animationDuration, easing }));
|
64
65
|
const timeout = setTimeout(() => {
|
65
|
-
commaWidth.value = withTiming(0, { duration: props.animationDuration });
|
66
|
+
commaWidth.value = withTiming(0, { duration: props.animationDuration, easing });
|
66
67
|
}, 0);
|
67
68
|
return () => clearTimeout(timeout);
|
68
69
|
}
|
package/Slots.js
CHANGED
@@ -59,7 +59,7 @@ const Slots = (props) => {
|
|
59
59
|
const animationDuration = "animationDuration" in props
|
60
60
|
? props.animationDuration || DEFAULT_DURATION
|
61
61
|
: DEFAULT_DURATION;
|
62
|
-
return (_jsxs(Fragment, { children: [_jsx(Slot, { slot: slot, index: i, height: slotHeight, charSizes: charSizes, commaWidth: commaWidth, periodWidth: periodWidth, commaPositions: props.includeComma && commaPositions.length ? commaPositions : undefined, onCompleted: callback, animationDuration: animationDuration, fontStyle: props.fontStyle }), (props.precision || 0) > 0 && props.precision === (slots.length - 1 - i) &&
|
62
|
+
return (_jsxs(Fragment, { children: [_jsx(Slot, { slot: slot, easing: props.easing, index: i, height: slotHeight, charSizes: charSizes, commaWidth: commaWidth, periodWidth: periodWidth, commaPositions: props.includeComma && commaPositions.length ? commaPositions : undefined, onCompleted: callback, animationDuration: animationDuration, fontStyle: props.fontStyle }), (props.precision || 0) > 0 && props.precision === (slots.length - 1 - i) &&
|
63
63
|
_jsx(Text, { style: props.fontStyle, children: "." })] }, `${idRef.current}-${keys[i]}`));
|
64
64
|
})] }), !sizesMeasured &&
|
65
65
|
Array.from({ length: 10 }, (_, i) => i)
|
package/constants.d.ts
ADDED
package/constants.js
ADDED
package/package.json
CHANGED
package/types.d.ts
CHANGED
@@ -2,9 +2,11 @@ import type { StyleProp, TextStyle } from 'react-native';
|
|
2
2
|
import type { SharedValue } from 'react-native-reanimated';
|
3
3
|
export type Position = -1 | 0 | 1;
|
4
4
|
export type SlotValue = [number] | [number | null, number | null];
|
5
|
+
type EasingT = 'linear' | 'in-out' | 'out';
|
5
6
|
export interface SlotProps {
|
6
7
|
slot: SlotValue;
|
7
8
|
index: number;
|
9
|
+
easing?: EasingT;
|
8
10
|
animationDuration: number;
|
9
11
|
fontStyle?: StyleProp<TextStyle>;
|
10
12
|
commaWidth: number;
|
@@ -17,6 +19,7 @@ export interface SlotProps {
|
|
17
19
|
type Shared = 'fontStyle' | 'index' | 'charSizes' | 'animationDuration';
|
18
20
|
export interface ContinuousSlotProps extends Pick<SlotProps, Shared> {
|
19
21
|
slot: [number | string, string];
|
22
|
+
easing?: EasingT;
|
20
23
|
}
|
21
24
|
export type CommaPosition = 1 | -1 | 0 | null;
|
22
25
|
export interface CommaProps {
|
@@ -36,5 +39,6 @@ export interface AnimatedNumbersProps {
|
|
36
39
|
precision?: number;
|
37
40
|
animationDuration?: number;
|
38
41
|
animateIntermediateValues?: true;
|
42
|
+
easing?: EasingT;
|
39
43
|
}
|
40
44
|
export {};
|