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 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(0, .4, .4, .9)
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 / 4 });
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 / 4), entering: props.charSizes[0] ? FadeInUp.duration(props.animationDuration / 2) : undefined, exiting: FadeOutDown.duration(props.animationDuration / 2), children: isMeasured
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',
@@ -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
- const easing = Easing.bezier(0, 0.4, 0.4, .8);
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, easing }, () => {
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, easing }), withTiming(0, { duration: props.animationDuration }, () => {
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, easing }), withTiming(0, { duration: props.animationDuration }, () => {
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
@@ -0,0 +1,3 @@
1
+ export declare const bezier_points: {
2
+ [key: string]: [number, number, number, number];
3
+ };
package/constants.js ADDED
@@ -0,0 +1,5 @@
1
+ export const bezier_points = {
2
+ 'in-out': [.23, 0, .23, .99],
3
+ 'linear': [0, 0, 1, 1],
4
+ 'out': [0, .4, .4, .9]
5
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-slot-text",
3
- "version": "3.0.0",
3
+ "version": "3.1.0",
4
4
  "author": "sc-mitton <scm.mitton@gmail.com> (https://github.com/sc-mitton)",
5
5
  "main": "index.js",
6
6
  "module": "index.ts",
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 {};