react-native-slot-text 1.0.7 → 2.0.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/AnimatedNumbers.js +63 -98
- package/README.md +4 -1
- package/Slot.js +108 -22
- package/helpers.d.ts +3 -1
- package/helpers.js +78 -1
- package/package.json +1 -1
- package/styles.d.ts +7 -8
- package/styles.js +7 -8
- package/types.d.ts +19 -6
- package/types.js +1 -1
package/AnimatedNumbers.js
CHANGED
@@ -1,10 +1,10 @@
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
2
|
-
import {
|
3
|
-
import { View, Text
|
4
|
-
import
|
2
|
+
import { useState, useRef, Fragment, useLayoutEffect, useCallback } from "react";
|
3
|
+
import { View, Text } from "react-native";
|
4
|
+
import { useSharedValue } from 'react-native-reanimated';
|
5
5
|
import styles from './styles';
|
6
6
|
import Slot from './Slot';
|
7
|
-
import {
|
7
|
+
import { getNewSlots, getNewCommaPositions } from './helpers';
|
8
8
|
const DEFAULT_DURATION = 200;
|
9
9
|
/**
|
10
10
|
* AnimatedNumbers Component
|
@@ -22,108 +22,73 @@ const DEFAULT_DURATION = 200;
|
|
22
22
|
* @returns {JSX.Element} The animated number component with slots for digits and commas.
|
23
23
|
*/
|
24
24
|
const AnimatedNumbers = (props) => {
|
25
|
+
// [number] : static number
|
26
|
+
/// [number, null]: removing slot
|
27
|
+
// [null, number]: adding slot
|
28
|
+
// [number, number]: animating slot
|
25
29
|
const idRef = useRef(`slots-${Math.random().toString(36).substring(7)}`);
|
26
|
-
|
27
|
-
const
|
28
|
-
const
|
29
|
-
const [
|
30
|
-
|
31
|
-
|
32
|
-
const [
|
33
|
-
|
34
|
-
const [
|
35
|
-
const [
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
useEffect(() => {
|
40
|
-
setOldNumber(`${props.prefix || ''}${props.value}`
|
41
|
-
.split('')
|
42
|
-
.map((val, i) => isNaN(val) ? val : parseInt(val)));
|
43
|
-
}, []);
|
44
|
-
useEffect(() => {
|
45
|
-
// Animation is in progress, queue the new value
|
46
|
-
if (state === 'idle' && oldNumber.join('') !== formatString(props.value, props.prefix)) {
|
47
|
-
setAnimatingValue(formatString(props.value, props.prefix));
|
30
|
+
// Indexes of slots that have finished animating
|
31
|
+
const slotsTrashBin = useSharedValue([]);
|
32
|
+
const queuedNumber = useSharedValue(null);
|
33
|
+
const [slots, setSlots] = useState([]);
|
34
|
+
const [commaPositions, setCommaPositions] = useState([]);
|
35
|
+
const [commaWidth, setCommaWidth] = useState(0);
|
36
|
+
const [sizesMeasured, setSizesMeasured] = useState(false);
|
37
|
+
const [keys, setKeys] = useState(Array.from({ length: props.value.toString().length }).map((_, i) => i));
|
38
|
+
const [slotHeight, setSlotHeight] = useState(0);
|
39
|
+
const [charSizes, setCharSizes] = useState(Array.from({ length: 10 }).map((_, i) => 0));
|
40
|
+
useLayoutEffect(() => {
|
41
|
+
if (slots.some(s => s.length > 1)) {
|
42
|
+
queuedNumber.value = props.value;
|
48
43
|
}
|
49
|
-
}, [props.value, state]);
|
50
|
-
useEffect(() => {
|
51
|
-
if (!animatingValue)
|
52
|
-
return;
|
53
|
-
setState('animating');
|
54
|
-
// If the old number is not set, this means it's the initial rendering of this component
|
55
|
-
// and the value needs to be loaded
|
56
|
-
if (oldNumber?.length === 0) {
|
57
|
-
setOldNumber(animatingValue
|
58
|
-
.split('')
|
59
|
-
.map((val, i) => isNaN(val) ? val : parseInt(val)));
|
60
|
-
}
|
61
|
-
// Prepare the new number for animation
|
62
44
|
else {
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
let newValuePositions = Array(animatingValue.length).fill(0);
|
68
|
-
// Compare from the right to the left
|
69
|
-
// * If the slots are the same value, no animation is needed for the slot, just stick it in the -1 position
|
70
|
-
// * If one of the slots is a string, the new slot will move down
|
71
|
-
// * If the new slot is greater than the old slot, the new slot will move down
|
72
|
-
// or up depending on which is greater
|
73
|
-
for (let i = 0; i < newValuePositions.length; i++) {
|
74
|
-
const oldNum = oldNumber[i];
|
75
|
-
const newNum = isNaN(animatingValue.charAt(i))
|
76
|
-
? animatingValue.charAt(i)
|
77
|
-
: parseInt(animatingValue.charAt(i));
|
78
|
-
if (oldNum === newNum) {
|
79
|
-
newValuePositions[i] = undefined;
|
80
|
-
}
|
81
|
-
else {
|
82
|
-
newValuePositions[i] = typeof oldNum === 'string' || typeof newNum === 'string'
|
83
|
-
? -1
|
84
|
-
: oldNum === undefined ? -1 : newNum > oldNum ? -1 : 1;
|
85
|
-
}
|
45
|
+
const parseFromLeft = props.value.toString()[0] === slots[0]?.[0]?.toString();
|
46
|
+
if (props.includeComma) {
|
47
|
+
const newCommaPositions = getNewCommaPositions(props.value.toString(), commaPositions, parseFromLeft);
|
48
|
+
setCommaPositions(newCommaPositions);
|
86
49
|
}
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
...Array(Math.max(0, oldNumber.length - animatingValue.length)).fill(-1)
|
91
|
-
]);
|
50
|
+
const newSlots = getNewSlots(props.value, slots, parseFromLeft);
|
51
|
+
setKeys(Array.from({ length: newSlots.length }).map((_, i) => i));
|
52
|
+
setSlots(newSlots);
|
92
53
|
}
|
93
|
-
}, [
|
94
|
-
const
|
95
|
-
|
96
|
-
|
97
|
-
|
54
|
+
}, [props.value]);
|
55
|
+
const onCompleted = useCallback(() => {
|
56
|
+
const cleanedSlots = slots
|
57
|
+
.filter(s => (Number.isFinite(s[0]) && s[1] !== null) || Number.isFinite(s[1]))
|
58
|
+
.map(s => Number.isFinite(s[1]) ? [s[1]] : [s[0]]);
|
59
|
+
const numberOfSlotsRemoved = Math.max(slots.length - cleanedSlots.length, 0);
|
60
|
+
const cleanedCommas = commaPositions
|
61
|
+
.map(c => c === -1 ? null : c === 1 ? 0 : c)
|
62
|
+
.slice(slots[0]?.[1] === null ? numberOfSlotsRemoved : 0) // Trim from left
|
63
|
+
.slice(0, slots[slots.length - 1]?.[1] === null ? -1 * numberOfSlotsRemoved : undefined); // Trim from right
|
64
|
+
if (cleanedSlots.length < slots.length) {
|
65
|
+
setKeys(prev => prev.slice(-1 * cleanedSlots.length));
|
98
66
|
}
|
99
67
|
else {
|
100
|
-
|
101
|
-
toValue: e.nativeEvent.layout.width,
|
102
|
-
useNativeDriver: false,
|
103
|
-
duration: containerSize.width > e.nativeEvent.layout.width ? props.animationDuration || DEFAULT_DURATION : 0
|
104
|
-
}).start();
|
105
|
-
Animated.timing(containerHeight, {
|
106
|
-
toValue: e.nativeEvent.layout.height,
|
107
|
-
duration: 100,
|
108
|
-
useNativeDriver: false
|
109
|
-
}).start();
|
68
|
+
setKeys(Array.from({ length: cleanedSlots.length }).map((_, i) => i));
|
110
69
|
}
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
70
|
+
setSlots(cleanedSlots);
|
71
|
+
setCommaPositions(cleanedCommas);
|
72
|
+
slotsTrashBin.value = [];
|
73
|
+
}, [slots, commaPositions]);
|
74
|
+
return (_jsxs(_Fragment, { children: [_jsxs(View, { style: styles.slotsContainer, children: [props.prefix && (_jsx(Text, { style: props.fontStyle, children: props.prefix })), slots.map((slot, i) => {
|
75
|
+
const callback = i === slots.findIndex(s => s.length > 1) ? onCompleted : undefined;
|
76
|
+
return (_jsx(Slot, { slot: slot, index: i, height: slotHeight, charSizes: charSizes, commaWidth: commaWidth, commaPositions: props.includeComma && commaPositions.length ? commaPositions : undefined, onCompleted: callback, animationDuration: (props.animationDuration || DEFAULT_DURATION), fontStyle: props.fontStyle }, `${idRef.current}-${keys[i]}`));
|
77
|
+
}), _jsx(Text, { style: [styles.spacer, props.fontStyle], children: "1" })] }), !sizesMeasured && Array.from({ length: 10 }).concat(',').map((_, i) => (_jsx(Fragment, { children: _jsx(Text, { style: [styles.hiddenSlot, props.fontStyle], onLayout: (e) => {
|
78
|
+
setSlotHeight(e.nativeEvent.layout.height);
|
79
|
+
if (i === 10) {
|
80
|
+
setCommaWidth(e.nativeEvent.layout.width);
|
81
|
+
}
|
82
|
+
else {
|
83
|
+
const charSize = e.nativeEvent.layout.width;
|
84
|
+
setCharSizes(prev => {
|
85
|
+
const newSizes = [...prev];
|
86
|
+
newSizes[i] = charSize;
|
87
|
+
return newSizes;
|
88
|
+
});
|
89
|
+
setSizesMeasured(true);
|
90
|
+
}
|
91
|
+
}, children: i === 10 ? ',' : i }, `slot-${i}`) }, `measure-slot-${i}`)))] }));
|
127
92
|
};
|
128
93
|
/*
|
129
94
|
Basic logic:
|
package/README.md
CHANGED
@@ -10,7 +10,10 @@ This project was created using `bun init` in bun v1.1.21. [Bun](https://bun.sh)
|
|
10
10
|
|
11
11
|
|
12
12
|
|
13
|
-
|
13
|
+
|
14
|
+
https://github.com/user-attachments/assets/e2e22b9a-17a8-4b17-b069-0c6b4854c915
|
15
|
+
|
16
|
+
|
14
17
|
|
15
18
|
|
16
19
|
|
package/Slot.js
CHANGED
@@ -1,27 +1,113 @@
|
|
1
|
-
import { jsx as _jsx } from "react/jsx-runtime";
|
2
|
-
import {
|
3
|
-
import {
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
2
|
+
import { useLayoutEffect, useState } from 'react';
|
3
|
+
import { View } from 'react-native';
|
4
|
+
import { Text } from 'react-native';
|
5
|
+
import Animated, { useSharedValue, withTiming, withSequence, useAnimatedStyle, interpolate, runOnJS } from 'react-native-reanimated';
|
6
|
+
import styles from './styles';
|
4
7
|
const Slot = (props) => {
|
5
|
-
const
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
8
|
+
const [value1, setValue1] = useState();
|
9
|
+
const [value2, setValue2] = useState();
|
10
|
+
const margin = useSharedValue(0);
|
11
|
+
const y = useSharedValue(0);
|
12
|
+
const incomingY = useSharedValue(0);
|
13
|
+
const commaScale = useSharedValue(0);
|
14
|
+
const commaWidth = useSharedValue(0);
|
15
|
+
// React to slot value changes
|
16
|
+
useLayoutEffect(() => {
|
17
|
+
if (!props.slot) {
|
18
|
+
return;
|
19
|
+
}
|
20
|
+
const incomingValue = props.slot[1];
|
21
|
+
const currentValue = props.slot[0];
|
22
|
+
if (incomingValue === undefined) {
|
23
|
+
y.value = 0;
|
24
|
+
incomingY.value = props.height;
|
25
|
+
margin.value = 0;
|
26
|
+
}
|
27
|
+
// Removing slot
|
28
|
+
else if (incomingValue === null) {
|
29
|
+
y.value = withTiming(-1 * props.height, { duration: props.animationDuration }, () => {
|
30
|
+
props.onCompleted && runOnJS(props.onCompleted)();
|
16
31
|
});
|
32
|
+
margin.value = withTiming(-1 * props.charSizes[currentValue], { duration: props.animationDuration / 2 });
|
33
|
+
}
|
34
|
+
// Adding slot
|
35
|
+
else if (currentValue === null) {
|
36
|
+
margin.value = withTiming(props.charSizes[incomingValue], { duration: props.animationDuration / 2 });
|
37
|
+
incomingY.value = withSequence(withTiming(-1 * props.height, { duration: 0 }), withTiming(0, { duration: props.animationDuration }, () => {
|
38
|
+
props.onCompleted && runOnJS(props.onCompleted)();
|
39
|
+
}));
|
40
|
+
}
|
41
|
+
// Animating slot
|
42
|
+
else {
|
43
|
+
margin.value = withTiming((props.charSizes[incomingValue] - props.charSizes[currentValue]), { duration: props.animationDuration / 2 });
|
44
|
+
if (incomingValue > currentValue) {
|
45
|
+
y.value = withTiming(props.height, { duration: props.animationDuration });
|
46
|
+
incomingY.value = withSequence(withTiming(-1 * props.height, { duration: 0 }), withTiming(0, { duration: props.animationDuration }, () => { props.onCompleted && runOnJS(props.onCompleted)(); }));
|
47
|
+
}
|
48
|
+
else if (incomingValue < currentValue) {
|
49
|
+
y.value = withTiming(-1 * props.height, { duration: props.animationDuration });
|
50
|
+
incomingY.value = withSequence(withTiming(1 * props.height, { duration: 0 }), withTiming(0, { duration: props.animationDuration }, () => { props.onCompleted && runOnJS(props.onCompleted)(); }));
|
51
|
+
}
|
52
|
+
}
|
53
|
+
}, [props.slot]);
|
54
|
+
useLayoutEffect(() => {
|
55
|
+
if (props.slot) {
|
56
|
+
setValue1(props.slot[0]);
|
57
|
+
setValue2(props.slot[1]);
|
58
|
+
}
|
59
|
+
}, [props.slot]);
|
60
|
+
useLayoutEffect(() => {
|
61
|
+
if (props.commaPositions?.[props.index] === 1) {
|
62
|
+
commaScale.value = withTiming(1, { duration: props.animationDuration });
|
63
|
+
commaWidth.value = withSequence(withTiming(0, { duration: 0 }), withTiming(props.commaWidth, { duration: props.animationDuration }));
|
64
|
+
}
|
65
|
+
else if (props.commaPositions?.[props.index] === -1) {
|
66
|
+
commaScale.value = withSequence(withTiming(1, { duration: 0 }), withTiming(0, { duration: props.animationDuration }));
|
67
|
+
const timeout = setTimeout(() => {
|
68
|
+
commaWidth.value = withTiming(0, { duration: props.animationDuration });
|
69
|
+
}, 0);
|
70
|
+
return () => clearTimeout(timeout);
|
71
|
+
}
|
72
|
+
else if (props.commaPositions?.[props.index] === 0) {
|
73
|
+
commaScale.value = 1;
|
74
|
+
commaWidth.value = props.commaWidth;
|
75
|
+
}
|
76
|
+
else {
|
77
|
+
commaScale.value = 0;
|
78
|
+
commaWidth.value = 0;
|
17
79
|
}
|
18
|
-
}, [props.
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
80
|
+
}, [props.commaPositions, props.commaWidth]);
|
81
|
+
const commaStyle = useAnimatedStyle(() => ({
|
82
|
+
transform: [{ scale: commaScale.value }],
|
83
|
+
width: commaWidth.value
|
84
|
+
}));
|
85
|
+
const currentStyle = useAnimatedStyle(() => ({
|
86
|
+
transform: [
|
87
|
+
{ translateY: y.value },
|
88
|
+
{ scale: interpolate(y.value, [-1 * props.height, 0, props.height], [0, 1, 0]) }
|
89
|
+
],
|
90
|
+
marginRight: margin.value,
|
91
|
+
opacity: interpolate(y.value, [-1 * Math.pow(props.height, .95), 0, Math.pow(props.height, .95)], [0, 1, 0]),
|
92
|
+
}));
|
93
|
+
const incomingStyle = useAnimatedStyle(() => {
|
94
|
+
return ({
|
95
|
+
transform: [
|
96
|
+
{ translateY: incomingY.value },
|
97
|
+
{ scale: interpolate(incomingY.value, [-1 * props.height, 0, props.height], [0, 1, 0]) },
|
98
|
+
],
|
99
|
+
opacity: interpolate(incomingY.value, [-1 * Math.pow(props.height, .95), 0, Math.pow(props.height, .95)], [0, 1, 0]),
|
100
|
+
position: 'absolute'
|
101
|
+
});
|
102
|
+
});
|
103
|
+
const incomingTextStyle = useAnimatedStyle(() => ({
|
104
|
+
transform: [{ rotateX: `${interpolate(incomingY.value, [-1 * props.height / 2, 0, props.height / 2], [90, 0, -90])}deg` }]
|
105
|
+
}));
|
106
|
+
const currentTextStyle = useAnimatedStyle(() => ({
|
107
|
+
transform: [{ rotateX: `${interpolate(y.value, [-1 * props.height / 2, 0, props.height / 2], [90, 0, -90])}deg` }]
|
108
|
+
}));
|
109
|
+
return (_jsxs(View, { style: styles.slotContainer, children: [_jsx(Animated.View, { style: currentStyle, children: Number.isFinite(value1) &&
|
110
|
+
_jsx(Animated.Text, { style: [props.fontStyle, currentTextStyle], children: value1 }) }), _jsx(Animated.View, { style: incomingStyle, children: Number.isFinite(value2) &&
|
111
|
+
_jsx(Animated.Text, { style: [props.fontStyle, incomingTextStyle], children: value2 }) }), _jsx(Text, { style: styles.hiddenSlot, children: "1" }), _jsx(Animated.View, { style: commaStyle, children: _jsx(Text, { style: props.fontStyle, children: "," }) })] }));
|
26
112
|
};
|
27
113
|
export default Slot;
|
package/helpers.d.ts
CHANGED
@@ -1 +1,3 @@
|
|
1
|
-
|
1
|
+
import type { SlotValue, CommaPosition } from "./types";
|
2
|
+
export declare const getNewSlots: (newValue: number, currentSlots: SlotValue[], parseFromLeft: boolean) => SlotValue[];
|
3
|
+
export declare const getNewCommaPositions: (newValue: string, currentCommaPositions: CommaPosition[], parseFromLeft: boolean) => CommaPosition[];
|
package/helpers.js
CHANGED
@@ -1 +1,78 @@
|
|
1
|
-
export const
|
1
|
+
export const getNewSlots = (newValue, currentSlots, parseFromLeft) => {
|
2
|
+
const iterLength = Math.max(newValue.toString().length, currentSlots.length);
|
3
|
+
const shiftCurrent = parseFromLeft
|
4
|
+
? 0
|
5
|
+
: newValue.toString().length > currentSlots.length ? currentSlots.length - newValue.toString().length : 0;
|
6
|
+
const shiftIncoming = parseFromLeft
|
7
|
+
? 0
|
8
|
+
: currentSlots.length > newValue.toString().length ? newValue.toString().length - currentSlots.length : 0;
|
9
|
+
const newSlots = Array.from({ length: iterLength }, (_, i) => [i]);
|
10
|
+
Array.from({ length: iterLength }, (_, i) => parseFromLeft ? i : iterLength - i - 1).forEach(i => {
|
11
|
+
const newValueParsed = parseInt(`${newValue}`[i + shiftIncoming]);
|
12
|
+
const currentSlotValue = currentSlots[i + shiftCurrent]?.[0];
|
13
|
+
// First pass through, just set the slots since shared slots is empty
|
14
|
+
if (currentSlots.length === 0) {
|
15
|
+
return newSlots[i] = [newValueParsed];
|
16
|
+
}
|
17
|
+
// Removing slot
|
18
|
+
if (isNaN(newValueParsed)) {
|
19
|
+
newSlots[i] = [currentSlotValue, null];
|
20
|
+
}
|
21
|
+
// Adding slot
|
22
|
+
else if (currentSlotValue === undefined || currentSlotValue === null) {
|
23
|
+
newSlots[i] = [null, newValueParsed];
|
24
|
+
}
|
25
|
+
// Animating slot
|
26
|
+
else if (currentSlotValue !== newValueParsed) {
|
27
|
+
newSlots[i] = [currentSlotValue, newValueParsed];
|
28
|
+
}
|
29
|
+
// Static slot
|
30
|
+
else {
|
31
|
+
newSlots[i] = [newValueParsed];
|
32
|
+
}
|
33
|
+
});
|
34
|
+
return newSlots;
|
35
|
+
};
|
36
|
+
// Takes in a new value and spits out an array of comma positions
|
37
|
+
// for all of the commas being added, removed, or staying the sameM
|
38
|
+
export const getNewCommaPositions = (newValue, currentCommaPositions, parseFromLeft) => {
|
39
|
+
const parseLength = Math.max(newValue.length, currentCommaPositions.length);
|
40
|
+
// On first render, no size change
|
41
|
+
const sizeChange = currentCommaPositions.length === 0
|
42
|
+
? 0
|
43
|
+
: newValue.length - currentCommaPositions.length;
|
44
|
+
const windowSize = sizeChange > 0 ? parseLength : parseLength + sizeChange;
|
45
|
+
const newCommaPositions = Array.from({ length: parseLength }, (_, i) => null);
|
46
|
+
// Copy over the current comma positions
|
47
|
+
currentCommaPositions.forEach((c, i) => {
|
48
|
+
if (parseFromLeft || sizeChange < 0) {
|
49
|
+
newCommaPositions[i] = c;
|
50
|
+
}
|
51
|
+
else {
|
52
|
+
newCommaPositions[i + sizeChange] = c;
|
53
|
+
}
|
54
|
+
});
|
55
|
+
for (let i = 0; i < parseLength; i++) {
|
56
|
+
const index = parseFromLeft ? i : parseLength - i - 1;
|
57
|
+
const windowIndex = parseFromLeft ? i : windowSize - i - 1;
|
58
|
+
const isCommaIndex = (windowSize - windowIndex - 1) % 3 === 0 && (windowSize - windowIndex - 1) !== 0;
|
59
|
+
const outSizeVisibleWindow = parseFromLeft
|
60
|
+
? index > windowSize - 1
|
61
|
+
: index < parseLength - windowSize;
|
62
|
+
// If in the section that's being removed, animate out all commmas
|
63
|
+
if (outSizeVisibleWindow && currentCommaPositions.length > 0) {
|
64
|
+
newCommaPositions[index] = Number.isFinite(newCommaPositions[index]) ? -1 : null;
|
65
|
+
}
|
66
|
+
// If is a comma index
|
67
|
+
else if (isCommaIndex) {
|
68
|
+
newCommaPositions[index] = Number.isFinite(newCommaPositions[index])
|
69
|
+
? 0
|
70
|
+
: currentCommaPositions.length === 0 ? 0 : 1;
|
71
|
+
}
|
72
|
+
// Animate out since the comma doesn't match the new value's comma positions
|
73
|
+
else if (Number.isFinite(newCommaPositions[index])) {
|
74
|
+
newCommaPositions[index] = -1;
|
75
|
+
}
|
76
|
+
}
|
77
|
+
return newCommaPositions;
|
78
|
+
};
|
package/package.json
CHANGED
package/styles.d.ts
CHANGED
@@ -1,18 +1,17 @@
|
|
1
1
|
declare const styles: {
|
2
|
-
animatedNumbers: {
|
3
|
-
overflow: "hidden";
|
4
|
-
};
|
5
2
|
spacer: {
|
6
|
-
|
7
|
-
flexDirection: "row";
|
8
|
-
opacity: number;
|
3
|
+
width: number;
|
9
4
|
};
|
10
5
|
slotsContainer: {
|
11
|
-
position: "absolute";
|
12
6
|
flexDirection: "row";
|
13
7
|
justifyContent: "center";
|
14
8
|
};
|
15
|
-
|
9
|
+
slotContainer: {
|
10
|
+
flexDirection: "row";
|
11
|
+
alignItems: "flex-end";
|
12
|
+
};
|
13
|
+
hiddenSlot: {
|
14
|
+
position: "absolute";
|
16
15
|
opacity: number;
|
17
16
|
};
|
18
17
|
};
|
package/styles.js
CHANGED
@@ -1,19 +1,18 @@
|
|
1
1
|
import { StyleSheet } from 'react-native';
|
2
2
|
const styles = StyleSheet.create({
|
3
|
-
animatedNumbers: {
|
4
|
-
overflow: 'hidden',
|
5
|
-
},
|
6
3
|
spacer: {
|
7
|
-
|
8
|
-
flexDirection: 'row',
|
9
|
-
opacity: 0,
|
4
|
+
width: 0,
|
10
5
|
},
|
11
6
|
slotsContainer: {
|
12
|
-
position: 'absolute',
|
13
7
|
flexDirection: 'row',
|
14
8
|
justifyContent: 'center',
|
15
9
|
},
|
16
|
-
|
10
|
+
slotContainer: {
|
11
|
+
flexDirection: 'row',
|
12
|
+
alignItems: 'flex-end'
|
13
|
+
},
|
14
|
+
hiddenSlot: {
|
15
|
+
position: 'absolute',
|
17
16
|
opacity: 0,
|
18
17
|
}
|
19
18
|
});
|
package/types.d.ts
CHANGED
@@ -1,17 +1,30 @@
|
|
1
1
|
import type { StyleProp, TextStyle } from 'react-native';
|
2
|
+
import type { SharedValue } from 'react-native-reanimated';
|
2
3
|
export type Position = -1 | 0 | 1;
|
4
|
+
export type SlotValue = [number] | [number | null, number | null];
|
3
5
|
export interface SlotProps {
|
4
|
-
|
6
|
+
slot: SlotValue;
|
7
|
+
index: number;
|
5
8
|
animationDuration: number;
|
6
9
|
fontStyle?: StyleProp<TextStyle>;
|
7
|
-
|
8
|
-
final: Position;
|
9
|
-
height: number;
|
10
|
-
isNew?: boolean;
|
10
|
+
commaWidth: number;
|
11
11
|
onCompleted?: () => void;
|
12
|
+
commaPositions?: CommaPosition[];
|
13
|
+
charSizes: number[];
|
14
|
+
height: number;
|
15
|
+
}
|
16
|
+
export type CommaPosition = 1 | -1 | 0 | null;
|
17
|
+
export interface CommaProps {
|
18
|
+
isEntering: boolean;
|
19
|
+
isExiting: boolean;
|
20
|
+
width: SharedValue<number>;
|
21
|
+
animationDuration: number;
|
22
|
+
fontStyle?: StyleProp<TextStyle>;
|
23
|
+
onExited: () => void;
|
24
|
+
onEntered: () => void;
|
12
25
|
}
|
13
26
|
export interface AnimatedNumbersProps {
|
14
|
-
value:
|
27
|
+
value: number;
|
15
28
|
fontStyle?: StyleProp<TextStyle>;
|
16
29
|
animationDuration?: number;
|
17
30
|
prefix?: string;
|
package/types.js
CHANGED
@@ -1 +1 @@
|
|
1
|
-
|
1
|
+
export {};
|