rn-marquee-text 2.1.1-beta.1 → 2.1.2-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.
@@ -1,119 +1,33 @@
1
1
  import * as React from "react";
2
2
  import { ViewStyle, TextStyle } from "react-native";
3
- /**
4
- * Animation modes for the marquee text
5
- */
6
3
  declare enum AnimationMode {
7
4
  LOOP = "loop",
8
5
  BOUNCE = "bounce"
9
6
  }
10
- /**
11
- * Direction of the marquee animation
12
- */
13
7
  type MarqueeDirection = "horizontal" | "vertical";
14
- /**
15
- * Props for the MarqueeText component
16
- */
17
8
  interface MarqueeTextProps {
18
- /**
19
- * Content to be scrolled (string or React nodes)
20
- */
21
9
  children: React.ReactNode;
22
- /**
23
- * The animation mode: 'loop' for continuous scrolling or 'bounce' for back-and-forth
24
- * @default AnimationMode.LOOP
25
- */
26
10
  mode?: AnimationMode;
27
- /**
28
- * Speed of the scrolling animation in pixels per second
29
- * @default 30
30
- */
31
11
  speed?: number;
32
- /**
33
- * Delay in milliseconds before starting the animation
34
- * @default 1500
35
- */
36
12
  delay?: number;
37
- /**
38
- * Duration in milliseconds to pause at the end of the content (only for bounce mode)
39
- * @default 1000
40
- */
41
13
  endPauseDuration?: number;
42
- /**
43
- * Container style
44
- */
45
14
  style?: ViewStyle;
46
- /**
47
- * Text style (when children is a string)
48
- */
49
15
  textStyle?: TextStyle;
50
- /**
51
- * Whether to enable the animation
52
- * @default true
53
- */
54
16
  enabled?: boolean;
55
- /**
56
- * Direction of scrolling ('horizontal' or 'vertical')
57
- * @default 'horizontal'
58
- */
59
17
  direction?: MarqueeDirection;
60
- /**
61
- * Spacing between cloned elements
62
- * @default 20
63
- */
64
18
  spacing?: number;
65
- /**
66
- * Allow user interaction with gesture handling
67
- * @default true
68
- */
69
19
  withGesture?: boolean;
70
- /**
71
- * Custom frame rate for animation
72
- */
73
20
  frameRate?: number;
74
- /**
75
- * Reverse the animation direction
76
- * @default false
77
- */
78
21
  reverse?: boolean;
79
- /**
80
- * Background color for the container
81
- * @default 'transparent'
82
- */
83
22
  backgroundColor?: string;
84
- /**
85
- * Callback when animation starts
86
- */
87
23
  onAnimationStart?: () => void;
88
- /**
89
- * Callback when animation stops
90
- */
91
24
  onAnimationStop?: () => void;
92
25
  }
93
- /**
94
- * Reference handle for the MarqueeText component
95
- */
96
26
  export interface MarqueeTextRef {
97
- /**
98
- * Start the marquee animation
99
- */
100
27
  start: () => void;
101
- /**
102
- * Stop the marquee animation
103
- */
104
28
  stop: () => void;
105
- /**
106
- * Whether the animation is currently active
107
- */
108
29
  isActive: boolean;
109
30
  }
110
- /**
111
- * MarqueeText component for scrolling text or content
112
- *
113
- * This component creates a scrolling effect for text or other content.
114
- * It supports both horizontal and vertical scrolling, different animation
115
- * modes, and user interaction via gestures.
116
- */
117
31
  declare const MarqueeText: React.ForwardRefExoticComponent<MarqueeTextProps & React.RefAttributes<MarqueeTextRef>>;
118
32
  export { AnimationMode };
119
33
  export type { MarqueeDirection, MarqueeTextProps };
@@ -2,17 +2,11 @@ import * as React from "react";
2
2
  import { StyleSheet, View, Text, } from "react-native";
3
3
  import { Gesture, GestureDetector } from "react-native-gesture-handler";
4
4
  import Animated, { runOnJS, useAnimatedReaction, useAnimatedStyle, useSharedValue, useFrameCallback, withDecay, } from "react-native-reanimated";
5
- /**
6
- * Animation modes for the marquee text
7
- */
8
5
  var AnimationMode;
9
6
  (function (AnimationMode) {
10
7
  AnimationMode["LOOP"] = "loop";
11
8
  AnimationMode["BOUNCE"] = "bounce";
12
9
  })(AnimationMode || (AnimationMode = {}));
13
- /**
14
- * Component to render a child item in the marquee
15
- */
16
10
  var AnimatedChild = React.memo(function (_a) {
17
11
  var index = _a.index, children = _a.children, anim = _a.anim, contentMeasurement = _a.contentMeasurement, spacing = _a.spacing, direction = _a.direction;
18
12
  var style = useAnimatedStyle(function () {
@@ -36,21 +30,9 @@ var AnimatedChild = React.memo(function (_a) {
36
30
  }, [index, spacing, contentMeasurement, direction]);
37
31
  return <Animated.View style={style}>{children}</Animated.View>;
38
32
  });
39
- /**
40
- * MarqueeText component for scrolling text or content
41
- *
42
- * This component creates a scrolling effect for text or other content.
43
- * It supports both horizontal and vertical scrolling, different animation
44
- * modes, and user interaction via gestures.
45
- */
46
33
  var MarqueeText = React.forwardRef(function (_a, ref) {
47
34
  var children = _a.children, _b = _a.mode, mode = _b === void 0 ? AnimationMode.LOOP : _b, _c = _a.speed, speed = _c === void 0 ? 30 : _c, _d = _a.delay, delay = _d === void 0 ? 1500 : _d, _e = _a.endPauseDuration, endPauseDuration = _e === void 0 ? 1000 : _e, style = _a.style, textStyle = _a.textStyle, _f = _a.enabled, enabled = _f === void 0 ? true : _f, _g = _a.direction, direction = _g === void 0 ? "horizontal" : _g, _h = _a.spacing, spacing = _h === void 0 ? 20 : _h, _j = _a.withGesture, withGesture = _j === void 0 ? true : _j, frameRate = _a.frameRate, _k = _a.reverse, reverse = _k === void 0 ? false : _k, _l = _a.backgroundColor, backgroundColor = _l === void 0 ? "transparent" : _l, onAnimationStart = _a.onAnimationStart, onAnimationStop = _a.onAnimationStop;
48
- var _m = React.useState({
49
- width: 0,
50
- height: 0,
51
- }), contentSize = _m[0], setContentSize = _m[1];
52
35
  var isVertical = direction === "vertical";
53
- var isBounceMode = mode === AnimationMode.BOUNCE;
54
36
  var containerMeasurement = useSharedValue({
55
37
  width: 0,
56
38
  height: 0,
@@ -63,13 +45,12 @@ var MarqueeText = React.forwardRef(function (_a, ref) {
63
45
  x: 0,
64
46
  y: 0,
65
47
  });
66
- var _o = React.useState(0), cloneTimes = _o[0], setCloneTimes = _o[1];
48
+ var _m = React.useState(0), cloneTimes = _m[0], setCloneTimes = _m[1];
67
49
  var anim = useSharedValue(0);
68
50
  var isMounted = React.useRef(true);
69
51
  var isActive = useSharedValue(false);
70
- var frameRateMs = frameRate ? 1000 / frameRate : 1000 / 60; // Default to 60fps
71
- var pixelsPerMs = speed / 1000;
72
- // Animation frame callback
52
+ var frameRateMs = frameRate ? 1000 / frameRate : 1000 / 60;
53
+ var pixelsPerMs = speed / 10;
73
54
  var frameCallback = useFrameCallback(function (frameInfo) {
74
55
  if (!enabled || frameInfo.timeSincePreviousFrame === null)
75
56
  return;
@@ -78,7 +59,6 @@ var MarqueeText = React.forwardRef(function (_a, ref) {
78
59
  : frameInfo.timeSincePreviousFrame;
79
60
  anim.value += (reverse ? -1 : 1) * pixelsPerMs * deltaTime;
80
61
  }, false);
81
- // Calculate how many clones we need to fill the screen
82
62
  useAnimatedReaction(function () {
83
63
  var contentDim = isVertical
84
64
  ? contentMeasurement.value.height
@@ -88,14 +68,12 @@ var MarqueeText = React.forwardRef(function (_a, ref) {
88
68
  : containerMeasurement.value.width;
89
69
  if (contentDim <= 0 || containerDim <= 0)
90
70
  return 0;
91
- // Need enough clones to fill the container plus buffer for continuous scrolling
92
71
  return Math.ceil(containerDim / contentDim) + 2;
93
72
  }, function (times) {
94
73
  if (times > 0 && isMounted.current) {
95
74
  runOnJS(setCloneTimes)(times);
96
75
  }
97
76
  }, [direction]);
98
- // Control functions
99
77
  var start = React.useCallback(function () {
100
78
  if (!enabled)
101
79
  return;
@@ -108,7 +86,6 @@ var MarqueeText = React.forwardRef(function (_a, ref) {
108
86
  isActive.value = false;
109
87
  onAnimationStop === null || onAnimationStop === void 0 ? void 0 : onAnimationStop();
110
88
  }, [frameCallback, onAnimationStop]);
111
- // Expose controls via ref
112
89
  React.useImperativeHandle(ref, function () { return ({
113
90
  start: start,
114
91
  stop: stop,
@@ -116,80 +93,71 @@ var MarqueeText = React.forwardRef(function (_a, ref) {
116
93
  return isActive.value;
117
94
  },
118
95
  }); });
119
- // Setup gesture handling
120
96
  var pan = React.useMemo(function () {
121
97
  return Gesture.Pan()
122
98
  .enabled(withGesture && enabled)
123
- .onBegin(function () {
124
- // Stop auto-animation when user interacts
125
- runOnJS(stop)();
126
- })
99
+ .onBegin(function () { return runOnJS(stop)(); })
127
100
  .onChange(function (e) {
128
- // Move according to user's gesture
129
101
  anim.value += -(isVertical ? e.changeY : e.changeX);
130
102
  })
131
103
  .onFinalize(function (e) {
132
- // Apply momentum scrolling when user releases
133
104
  anim.value = withDecay({
134
105
  velocity: -(isVertical ? e.velocityY : e.velocityX),
135
106
  }, function (finished) {
136
- // Restart auto-animation when decay finishes
137
107
  if (finished)
138
108
  runOnJS(start)();
139
109
  });
140
110
  });
141
111
  }, [withGesture, isVertical, anim, start, stop, enabled]);
142
- // Cleanup on unmount
143
112
  React.useEffect(function () {
144
113
  return function () {
145
114
  isMounted.current = false;
146
115
  stop();
147
116
  };
148
117
  }, [stop]);
149
- // Start/stop based on enabled prop changes
150
118
  React.useEffect(function () {
151
119
  if (enabled) {
152
- var timer_1 = setTimeout(function () {
153
- start();
154
- }, delay);
120
+ var timer_1 = setTimeout(function () { return start(); }, delay);
155
121
  return function () { return clearTimeout(timer_1); };
156
122
  }
157
123
  else {
158
124
  stop();
159
125
  }
160
126
  }, [enabled, start, stop, delay]);
161
- // Render the content
162
127
  var renderContent = function () {
163
128
  if (typeof children === "string") {
164
- return <Text style={textStyle}>{children}</Text>;
129
+ return (<Text style={[styles.defaultText, textStyle]} numberOfLines={1} ellipsizeMode="tail">
130
+ {children}
131
+ </Text>);
165
132
  }
166
- return children;
133
+ return (<View style={styles.childContainer}>
134
+ {children}
135
+ </View>);
167
136
  };
168
137
  return (<Animated.View style={[
169
138
  styles.container,
170
139
  { backgroundColor: backgroundColor },
171
140
  style,
172
141
  {
173
- height: isVertical && contentMeasurement.value.height > 0
174
- ? contentMeasurement.value.height
175
- : undefined,
176
- width: !isVertical && contentMeasurement.value.width > 0
177
- ? contentMeasurement.value.width
178
- : undefined,
142
+ minHeight: isVertical ? 20 : undefined,
143
+ minWidth: !isVertical ? 20 : undefined,
144
+ height: isVertical ? 'auto' : undefined,
145
+ width: !isVertical ? 'auto' : undefined,
179
146
  },
180
147
  ]} onLayout={function (ev) {
181
148
  containerMeasurement.value = ev.nativeEvent.layout;
182
149
  }} pointerEvents="box-none">
183
150
  <GestureDetector gesture={pan}>
184
- <Animated.View style={isVertical ? styles.column : styles.row} pointerEvents="box-none">
185
- {/* Hidden element for measuring original content size */}
151
+ <Animated.View style={[
152
+ isVertical ? styles.column : styles.row,
153
+ styles.contentWrapper,
154
+ ]} pointerEvents="box-none">
186
155
  <View style={styles.hidden} onLayout={function (ev) {
187
156
  contentMeasurement.value = ev.nativeEvent.layout;
188
157
  }}>
189
158
  {renderContent()}
190
159
  </View>
191
160
 
192
- {/* Visible cloned elements */}
193
161
  {cloneTimes > 0 &&
194
162
  Array.from({ length: cloneTimes }).map(function (_, index) { return (<AnimatedChild key={"clone-".concat(index)} index={index} anim={anim} contentMeasurement={contentMeasurement} spacing={spacing} direction={direction}>
195
163
  {renderContent()}
@@ -210,10 +178,24 @@ var styles = StyleSheet.create({
210
178
  row: {
211
179
  flexDirection: "row",
212
180
  position: "relative",
181
+ alignItems: 'center',
213
182
  },
214
183
  column: {
215
184
  flexDirection: "column",
216
185
  position: "relative",
186
+ justifyContent: 'center',
187
+ },
188
+ contentWrapper: {
189
+ flexShrink: 1,
190
+ },
191
+ defaultText: {
192
+ fontSize: 16,
193
+ color: 'black',
194
+ includeFontPadding: false,
195
+ textAlignVertical: 'center',
196
+ },
197
+ childContainer: {
198
+ flexShrink: 1,
217
199
  },
218
200
  });
219
201
  export { AnimationMode };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rn-marquee-text",
3
- "version": "2.1.1-beta.1",
3
+ "version": "2.1.2-beta.1",
4
4
  "description": "A customizable marquee (scrolling) text component for React Native",
5
5
  "main": "index.js",
6
6
  "types": "index.d.ts",