rn-marquee-text 2.1.2-beta.1 → 3.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/README.md CHANGED
@@ -1,25 +1,19 @@
1
- # React Native Marquee Text 🏃‍♂️
1
+ ```markdown
2
+ # React Native Marquee Text 🚀
2
3
 
3
- [![npm version](https://img.shields.io/npm/v/rn-marquee-text?style=flat-square)](https://www.npmjs.com/package/rn-marquee-text)
4
- [![license](https://img.shields.io/npm/l/rn-marquee-text?style=flat-square)](https://github.com/yourusername/rn-marquee-text/blob/main/LICENSE)
5
- [![downloads](https://img.shields.io/npm/dt/rn-marquee-text?style=flat-square)](https://www.npmjs.com/package/rn-marquee-text)
6
- [![CI Status](https://img.shields.io/github/actions/workflow/status/yourusername/rn-marquee-text/ci.yml?style=flat-square)](https://github.com/yourusername/rn-marquee-text/actions)
7
-
8
- A high-performance, customizable marquee component for React Native with smooth animations and gesture support.
9
-
10
- ![Demo](https://github.com/yourusername/rn-marquee-text/blob/main/assets/demo.gif?raw=true)
4
+ ![Horizontal and Vertical Marquee Demo](demo-combined.gif)
11
5
 
12
6
  ## Features ✨
13
7
 
14
- - 🎭 Multiple animation modes (loop, bounce)
15
- - ↔️ Bidirectional scrolling (horizontal/vertical)
16
- - Touch gesture interaction
17
- - Optimized with Reanimated 2
18
- - 🎨 Customizable speed, spacing, and delays
19
- - 📱 Supports both iOS and Android
20
- - 🛠 TypeScript support included
8
+ - **Multi-directional scrolling**: Horizontal and vertical marquee effects
9
+ - **Animation modes**: Loop and bounce animations
10
+ - **Performance optimized**: Built with React Native Reanimated 2
11
+ - **Customizable**: Control speed, delay, spacing, and more
12
+ - **Interactive**: Gesture support for pausing/resuming
13
+ - **Flexible content**: Supports both text and custom components
14
+ - **TypeScript ready**: Complete type definitions included
21
15
 
22
- ## Installation 💻
16
+ ## Installation 📦
23
17
 
24
18
  ```bash
25
19
  # Using npm
@@ -29,188 +23,191 @@ npm install rn-marquee-text react-native-reanimated react-native-gesture-handler
29
23
  yarn add rn-marquee-text react-native-reanimated react-native-gesture-handler
30
24
  ```
31
25
 
32
- ### Peer Dependencies Setup
33
- - Follow [Reanimated installation guide](https://docs.swmansion.com/react-native-reanimated/docs/fundamentals/installation)
34
- - Configure [Gesture Handler](https://docs.swmansion.com/react-native-gesture-handler/docs/installation)
26
+ ### Peer Dependencies
27
+ Ensure you've properly installed and configured:
28
+ - [React Native Reanimated](https://docs.swmansion.com/react-native-reanimated/docs/fundamentals/installation)
29
+ - [React Native Gesture Handler](https://docs.swmansion.com/react-native-gesture-handler/docs/)
35
30
 
36
- ## Basic Usage 🚀
31
+ ## Usage 🚀
37
32
 
33
+ ### Basic Implementation
38
34
  ```jsx
39
- import Marquee from 'rn-marquee-text';
40
-
41
- function App() {
42
- return (
43
- <Marquee.MarqueeText
44
- speed={50}
45
- style={{ height: 40 }}
46
- textStyle={{ fontSize: 16 }}
35
+ import React from 'react';
36
+ import { StyleSheet, View } from 'react-native';
37
+ import MarqueeText from 'rn-marquee-text';
38
+
39
+ const App = () => (
40
+ <View style={styles.container}>
41
+ <MarqueeText
42
+ style={styles.marquee}
43
+ speed={40}
44
+ textStyle={styles.text}
47
45
  >
48
- This text will scroll automatically!
49
- </Marquee.MarqueeText>
50
- );
51
- }
52
- ```
53
-
54
- ## Advanced Usage 🧠
46
+ Your scrolling text goes here
47
+ </MarqueeText>
48
+ </View>
49
+ );
55
50
 
56
- ### Custom Animation Configuration
57
- ```jsx
58
- <Marquee.MarqueeText
59
- mode="bounce"
60
- direction="vertical"
61
- speed={30}
62
- delay={2000}
63
- endPauseDuration={1500}
64
- spacing={30}
65
- >
66
- {yourCustomComponent}
67
- </Marquee.MarqueeText>
68
- ```
51
+ const styles = StyleSheet.create({
52
+ container: { flex: 1, justifyContent: 'center', padding: 20 },
53
+ marquee: { height: 50, backgroundColor: '#f5f5f5', borderRadius: 8 },
54
+ text: { fontSize: 16, color: '#333' }
55
+ });
69
56
 
70
- ### Imperative Control
71
- ```jsx
72
- const marqueeRef = useRef(null);
73
-
74
- // Start/pause programmatically
75
- <>
76
- <Marquee.MarqueeText ref={marqueeRef} />
77
- <Button
78
- title="Toggle"
79
- onPress={() => marqueeRef.current?.isActive
80
- ? marqueeRef.current.stop()
81
- : marqueeRef.current.start()
82
- }
83
- />
84
- </>
57
+ export default App;
85
58
  ```
86
59
 
87
60
  ## API Reference 📚
88
61
 
89
62
  ### Props
90
-
91
63
  | Prop | Type | Default | Description |
92
64
  |------|------|---------|-------------|
93
- | `mode` | `'loop' \| 'bounce'` | `'loop'` | Animation behavior |
94
- | `speed` | `number` | `30` | Scroll speed (px/sec) |
95
- | `direction` | `'horizontal' \| 'vertical'` | `'horizontal'` | Scroll axis |
96
- | `delay` | `number` | `1500` | Initial delay (ms) |
97
- | `endPauseDuration` | `number` | `1000` | Pause duration at end (bounce mode) |
98
- | `spacing` | `number` | `20` | Space between clones |
99
- | `enabled` | `boolean` | `true` | Animation state |
100
- | `withGesture` | `boolean` | `true` | Enable gesture interaction |
101
- | `reverse` | `boolean` | `false` | Reverse animation direction |
102
- | `backgroundColor` | `string` | `'transparent'` | Container background color |
103
- | `frameRate` | `number` | `60` | Animation frame rate |
104
- | `style` | `ViewStyle` | - | Container style |
105
- | `textStyle` | `TextStyle` | - | Text style (when children is string) |
106
- | `onAnimationStart` | `() => void` | - | Animation start callback |
107
- | `onAnimationStop` | `() => void` | - | Animation stop callback |
65
+ | `children` | React.ReactNode | Required | Content to scroll (string or components) |
66
+ | `mode` | 'loop' \| 'bounce' | 'loop' | Animation behavior |
67
+ | `speed` | number | 30 | Pixels per second |
68
+ | `direction` | 'horizontal' \| 'vertical' | 'horizontal' | Scroll direction |
69
+ | `enabled` | boolean | true | Animation active state |
70
+ | `delay` | number | 1500 | Initial delay (ms) before starting |
71
+ | `endPauseDuration` | number | 1000 | Pause at end (bounce mode only) |
72
+ | `gap` | number | 20 | Gap between repeating text loops |
73
+ | `spacing` | number | 20 | **Deprecated**: Use `gap` instead |
74
+ | `reverse` | boolean | false | Reverse the animation direction |
75
+ | `backgroundColor` | string | 'transparent' | Background color for the container |
76
+ | `withGesture` | boolean | true | Allow user interaction with gesture handling |
77
+ | `frameRate` | number | - | Custom frame rate for animation |
78
+ | `onAnimationStart` | function | - | Callback when animation starts |
79
+ | `onAnimationStop` | function | - | Callback when animation stops |
80
+ | `style` | ViewStyle | - | Container style |
81
+ | `textStyle` | TextStyle | - | Text style (when children is a string) |
108
82
 
109
83
  ### Methods (via ref)
84
+ ```jsx
85
+ const marqueeRef = useRef();
110
86
 
111
- ```typescript
112
- interface MarqueeTextRef {
113
- start: () => void;
114
- stop: () => void;
115
- isActive: boolean;
116
- }
117
- ```
118
-
119
- ## Examples 🎨
87
+ // Start animation
88
+ marqueeRef.current?.start();
120
89
 
121
- ### News Ticker
122
- ```jsx
123
- <Marquee.MarqueeText
124
- style={styles.ticker}
125
- textStyle={styles.tickerText}
126
- speed={40}
127
- >
128
- BREAKING: React Native Marquee Text released! • New version available • Check out the docs
129
- </Marquee.MarqueeText>
90
+ // Stop animation
91
+ marqueeRef.current?.stop();
130
92
 
131
- const styles = StyleSheet.create({
132
- ticker: {
133
- backgroundColor: '#ff0000',
134
- height: 30,
135
- },
136
- tickerText: {
137
- color: 'white',
138
- fontSize: 14,
139
- fontWeight: 'bold',
140
- },
141
- });
93
+ // Check if active
94
+ const isActive = marqueeRef.current?.isActive;
142
95
  ```
143
96
 
144
- ### Vertical Product Carousel
145
- ```jsx
146
- <Marquee.MarqueeText
147
- direction="vertical"
148
- mode="bounce"
149
- speed={20}
150
- style={styles.carousel}
151
- >
152
- <ProductCard {...item1} />
153
- <ProductCard {...item2} />
154
- <ProductCard {...item3} />
155
- </Marquee.MarqueeText>
156
- ```
97
+ ## Examples 🎨
157
98
 
158
- ### Custom Component with High Speed
99
+ ### Comprehensive Demo Example
159
100
  ```jsx
160
- <Marquee.MarqueeText
161
- style={styles.marquee}
162
- speed={500}
163
- textStyle={styles.text}
164
- >
165
- Smarty was created by the creators of React Native.
166
- </Marquee.MarqueeText>
101
+ import React from 'react';
102
+ import { SafeAreaView, View, Text, StyleSheet } from 'react-native';
103
+ import { AutoScroll, Marquee } from 'rn-marquee-text';
104
+
105
+ export default function App() {
106
+ return (
107
+ <SafeAreaView style={{ flex: 1, padding: 16, gap: 24 }}>
108
+ <Text style={{ fontSize: 20, fontWeight: 'bold' }}>Marquee Text Demo</Text>
109
+
110
+ <View style={{ borderRadius: 8, overflow: 'hidden' }}>
111
+ <Marquee speed={80}>
112
+ This is a long scrolling text that demonstrates the marquee functionality
113
+ </Marquee>
114
+ </View>
115
+
116
+ <View style={{ borderRadius: 8, overflow: 'hidden' }}>
117
+ <Marquee
118
+ speed={120}
119
+ backgroundColor="#1a365d"
120
+ textStyle={{ color: '#f0f4f8', fontSize: 14 }}
121
+ >
122
+ Faster scrolling example with different colors
123
+ </Marquee>
124
+ </View>
125
+
126
+ <View style={{ width: '100%', borderRadius: 8, overflow: 'hidden' }}>
127
+ <Marquee
128
+ speed={100}
129
+ backgroundColor="#7b341e"
130
+ textStyle={{ color: '#fffaf0', fontSize: 18 }}
131
+ >
132
+ Breaking News: This is a full-width marquee text component that scrolls horizontally
133
+ </Marquee>
134
+ </View>
135
+
136
+ <View style={{ marginVertical: 10, borderRadius: 8, overflow: 'hidden' }}>
137
+ <Marquee
138
+ speed={50}
139
+ backgroundColor="#fff"
140
+ textStyle={{ color: '#0000ff', fontSize: 16 }}
141
+ >
142
+ This text will scroll horizontally with bounce effect. It will pause for 2 seconds at each end.
143
+ </Marquee>
144
+ </View>
145
+
146
+ <AutoScroll endPauseDuration={2000} style={styles.cardScroller} direction="horizontal">
147
+ <div style={styles.contentContainer}>
148
+ {[1, 2, 3, 4, 5].map((item) => (
149
+ <div key={item} style={styles.card}>
150
+ <Text style={styles.cardText}>Card {item}</Text>
151
+ </div>
152
+ ))}
153
+ </div>
154
+ </AutoScroll>
155
+ <AutoScroll endPauseDuration={2000} style={styles.cardScroller} direction="horizontal">
156
+ <Text style={styles.cardText}>This text will scroll horizontally with bounce effect and pause for 2 seconds at each end 🎉</Text>
157
+ </AutoScroll>
158
+ </SafeAreaView>
159
+ );
160
+ }
167
161
 
168
162
  const styles = StyleSheet.create({
169
- marquee: {
163
+ cardScroller: {
164
+ height: 120,
170
165
  width: '100%',
171
- height: 30,
166
+ marginTop: 10,
167
+ },
168
+ contentContainer: {
169
+ flexDirection: 'row',
170
+ padding: 10,
171
+ },
172
+ card: {
173
+ width: 100,
174
+ height: 100,
175
+ backgroundColor: '#f0f0f0',
176
+ borderRadius: 8,
177
+ marginRight: 10,
178
+ justifyContent: 'center',
179
+ alignItems: 'center',
180
+ },
181
+ cardText: {
182
+ fontSize: 16,
183
+ fontWeight: 'bold',
172
184
  },
173
- text: {
174
- fontSize: 16,
175
- color: '#333'
176
- }
177
185
  });
178
186
  ```
179
187
 
180
- ## Troubleshooting ⚠️
181
-
182
- ### Animation not smooth?
183
- - Ensure you're using Reanimated 2+
184
- - Check for heavy renders in parent components
185
- - Try reducing the `frameRate` prop
188
+ ## Troubleshooting 🛠️
186
189
 
187
- ### Text not visible?
188
- - Verify container has explicit dimensions
189
- - Check text color contrast
190
- - Ensure `textStyle` is properly applied
190
+ **Animation not working?**
191
+ - Verify Reanimated installation
192
+ - Check babel.config.js for Reanimated plugin
191
193
 
192
- ### Gesture not working?
193
- - Confirm Gesture Handler installation
194
- - Wrap root component with `GestureHandlerRootView`
195
- - Set `withGesture={true}` (default)
194
+ **Text not visible?**
195
+ - Ensure container has proper dimensions
196
+ - Verify text color contrasts with background
196
197
 
197
- ### Performance Issues?
198
- - Reduce `speed` for smoother animation
199
- - Minimize `spacing` to reduce clone count
200
- - Use `enabled={false}` when not needed
198
+ **Performance issues?**
199
+ - Reduce animation speed
200
+ - Simplify marquee content
201
+ - Use `frameRate` prop to limit FPS
201
202
 
202
203
  ## Contributing 🤝
203
-
204
- We welcome contributions! Please:
205
-
206
- 1. Fork the repository
207
- 2. Create a feature branch
208
- 3. Submit a pull request
204
+ Contributions are welcome! Please:
205
+ 1. Open an issue to discuss changes
206
+ 2. Ensure tests are updated
207
+ 3. Maintain consistent code style
209
208
 
210
209
  ## License 📄
210
+ MIT © PareshChavda(https://github.com/pareshchavda)
211
211
 
212
- MIT © PARESH CHAVDA
213
212
 
214
- ---
215
213
 
216
- Made with ❤️ for the React Native community
@@ -1,6 +1,5 @@
1
1
  import React from 'react';
2
2
  import { TextStyle, ViewStyle } from 'react-native';
3
- import { AnimationMode } from './constants';
4
3
  /**
5
4
  * AutoScroll component that measures its content and container
6
5
  * dimensions and automatically sets up a scrolling animation if
@@ -16,9 +15,9 @@ import { AnimationMode } from './constants';
16
15
  * @prop {boolean} enabled - Whether the scrolling animation is enabled
17
16
  * @prop {'horizontal'|'vertical'} direction - The direction of the scrolling animation
18
17
  */
19
- declare const AutoScroll: ({ children, mode, speed, delay, endPauseDuration, style, textStyle, enabled, direction, }: {
18
+ export declare const AutoScroll: ({ children, mode, speed, delay, endPauseDuration, style, textStyle, enabled, direction, }: {
20
19
  children: React.ReactNode;
21
- mode?: AnimationMode;
20
+ mode?: "loop" | "bounce";
22
21
  speed?: number;
23
22
  delay?: number;
24
23
  endPauseDuration?: number;
@@ -27,4 +26,3 @@ declare const AutoScroll: ({ children, mode, speed, delay, endPauseDuration, sty
27
26
  enabled?: boolean;
28
27
  direction?: "horizontal" | "vertical";
29
28
  }) => React.JSX.Element;
30
- export default AutoScroll;
@@ -17,8 +17,8 @@ import { AnimationMode } from './constants';
17
17
  * @prop {boolean} enabled - Whether the scrolling animation is enabled
18
18
  * @prop {'horizontal'|'vertical'} direction - The direction of the scrolling animation
19
19
  */
20
- var AutoScroll = function (_a) {
21
- 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, _f = _a.style, style = _f === void 0 ? {} : _f, _g = _a.textStyle, textStyle = _g === void 0 ? {} : _g, _h = _a.enabled, enabled = _h === void 0 ? true : _h, _j = _a.direction, direction = _j === void 0 ? 'vertical' : _j;
20
+ export var AutoScroll = function (_a) {
21
+ var children = _a.children, _b = _a.mode, mode = _b === void 0 ? '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, _f = _a.style, style = _f === void 0 ? {} : _f, _g = _a.textStyle, textStyle = _g === void 0 ? {} : _g, _h = _a.enabled, enabled = _h === void 0 ? true : _h, _j = _a.direction, direction = _j === void 0 ? 'vertical' : _j;
22
22
  // References for measurement
23
23
  var containerRef = useRef(null);
24
24
  var contentRef = useRef(null);
@@ -88,7 +88,7 @@ var AutoScroll = function (_a) {
88
88
  console.log('Animation setup:', { distance: distance, duration: duration });
89
89
  // Reset position
90
90
  scrollPosition.value = 0;
91
- if (mode === AnimationMode.LOOP) {
91
+ if (mode === AnimationMode.LOOP || mode === 'loop') {
92
92
  // Continuous loop animation
93
93
  scrollPosition.value = withDelay(delay, withRepeat(withTiming(-distance, { duration: duration, easing: Easing.linear }), -1, false));
94
94
  }
@@ -143,4 +143,3 @@ var styles = StyleSheet.create({
143
143
  flexShrink: 0,
144
144
  },
145
145
  });
146
- export default AutoScroll;
@@ -1,34 +1,125 @@
1
- import * as React from "react";
2
- import { ViewStyle, TextStyle } from "react-native";
1
+ import * as React from 'react';
2
+ import { ViewStyle, TextStyle } from 'react-native';
3
+ /**
4
+ * Animation modes for the marquee text
5
+ */
3
6
  declare enum AnimationMode {
4
7
  LOOP = "loop",
5
8
  BOUNCE = "bounce"
6
9
  }
7
- type MarqueeDirection = "horizontal" | "vertical";
10
+ /**
11
+ * Direction of the marquee animation
12
+ */
13
+ type MarqueeDirection = 'horizontal' | 'vertical';
14
+ /**
15
+ * Props for the MarqueeText component
16
+ */
8
17
  interface MarqueeTextProps {
18
+ /**
19
+ * Content to be scrolled (string or React nodes)
20
+ */
9
21
  children: React.ReactNode;
22
+ /**
23
+ * The animation mode: 'loop' for continuous scrolling or 'bounce' for back-and-forth
24
+ * @default AnimationMode.LOOP
25
+ */
10
26
  mode?: AnimationMode;
27
+ /**
28
+ * Speed of the scrolling animation in pixels per second
29
+ * @default 30
30
+ */
11
31
  speed?: number;
32
+ /**
33
+ * Delay in milliseconds before starting the animation
34
+ * @default 1500
35
+ */
12
36
  delay?: number;
37
+ /**
38
+ * Duration in milliseconds to pause at the end of the content (only for bounce mode)
39
+ * @default 1000
40
+ */
13
41
  endPauseDuration?: number;
42
+ /**
43
+ * Container style
44
+ */
14
45
  style?: ViewStyle;
46
+ /**
47
+ * Text style (when children is a string)
48
+ */
15
49
  textStyle?: TextStyle;
50
+ /**
51
+ * Whether to enable the animation
52
+ * @default true
53
+ */
16
54
  enabled?: boolean;
55
+ /**
56
+ * Direction of scrolling ('horizontal' or 'vertical')
57
+ * @default 'horizontal'
58
+ */
17
59
  direction?: MarqueeDirection;
60
+ /**
61
+ * Spacing between cloned elements
62
+ * @default 20
63
+ * @deprecated Use `gap` instead
64
+ */
18
65
  spacing?: number;
66
+ /**
67
+ * Gap between repeating text loops
68
+ * @default 20
69
+ */
70
+ gap?: number;
71
+ /**
72
+ * Allow user interaction with gesture handling
73
+ * @default true
74
+ */
19
75
  withGesture?: boolean;
76
+ /**
77
+ * Custom frame rate for animation
78
+ */
20
79
  frameRate?: number;
80
+ /**
81
+ * Reverse the animation direction
82
+ * @default false
83
+ */
21
84
  reverse?: boolean;
85
+ /**
86
+ * Background color for the container
87
+ * @default 'transparent'
88
+ */
22
89
  backgroundColor?: string;
90
+ /**
91
+ * Callback when animation starts
92
+ */
23
93
  onAnimationStart?: () => void;
94
+ /**
95
+ * Callback when animation stops
96
+ */
24
97
  onAnimationStop?: () => void;
25
98
  }
99
+ /**
100
+ * Reference handle for the MarqueeText component
101
+ */
26
102
  export interface MarqueeTextRef {
103
+ /**
104
+ * Start the marquee animation
105
+ */
27
106
  start: () => void;
107
+ /**
108
+ * Stop the marquee animation
109
+ */
28
110
  stop: () => void;
111
+ /**
112
+ * Whether the animation is currently active
113
+ */
29
114
  isActive: boolean;
30
115
  }
116
+ /**
117
+ * MarqueeText component for scrolling text or content
118
+ *
119
+ * This component creates a scrolling effect for text or other content.
120
+ * It supports both horizontal and vertical scrolling, different animation
121
+ * modes, and user interaction via gestures.
122
+ */
31
123
  declare const MarqueeText: React.ForwardRefExoticComponent<MarqueeTextProps & React.RefAttributes<MarqueeTextRef>>;
32
- export { AnimationMode };
124
+ export { MarqueeText, AnimationMode };
33
125
  export type { MarqueeDirection, MarqueeTextProps };
34
- export default MarqueeText;
@@ -1,202 +1,186 @@
1
- import * as React from "react";
2
- import { StyleSheet, View, Text, } from "react-native";
3
- import { Gesture, GestureDetector } from "react-native-gesture-handler";
4
- import Animated, { runOnJS, useAnimatedReaction, useAnimatedStyle, useSharedValue, useFrameCallback, withDecay, } from "react-native-reanimated";
1
+ import * as React from 'react';
2
+ import { StyleSheet, View, Text } from 'react-native';
3
+ import { Gesture, GestureDetector } from 'react-native-gesture-handler';
4
+ import Animated, { runOnJS, useAnimatedReaction, useAnimatedStyle, useSharedValue, withDelay, withRepeat, withSequence, withTiming, Easing, cancelAnimation, runOnUI, } from 'react-native-reanimated';
5
+ /**
6
+ * Animation modes for the marquee text
7
+ */
5
8
  var AnimationMode;
6
9
  (function (AnimationMode) {
7
10
  AnimationMode["LOOP"] = "loop";
8
11
  AnimationMode["BOUNCE"] = "bounce";
9
12
  })(AnimationMode || (AnimationMode = {}));
10
- var AnimatedChild = React.memo(function (_a) {
11
- var index = _a.index, children = _a.children, anim = _a.anim, contentMeasurement = _a.contentMeasurement, spacing = _a.spacing, direction = _a.direction;
12
- var style = useAnimatedStyle(function () {
13
- var _a;
14
- var isVertical = direction === "vertical";
15
- var dimension = isVertical
16
- ? contentMeasurement.value.height
17
- : contentMeasurement.value.width;
18
- if (dimension <= 0)
19
- return {};
20
- var position = (index - 1) * (dimension + spacing);
21
- var translation = -(anim.value % (dimension + spacing));
22
- return _a = {
23
- position: "absolute"
24
- },
25
- _a[isVertical ? "top" : "left"] = position,
26
- _a.transform = isVertical
27
- ? [{ translateY: translation }]
28
- : [{ translateX: translation }],
29
- _a;
30
- }, [index, spacing, contentMeasurement, direction]);
31
- return <Animated.View style={style}>{children}</Animated.View>;
32
- });
13
+ // AnimatedChild removed in favor of simplified Flexbox layout
14
+ /**
15
+ * MarqueeText component for scrolling text or content
16
+ *
17
+ * This component creates a scrolling effect for text or other content.
18
+ * It supports both horizontal and vertical scrolling, different animation
19
+ * modes, and user interaction via gestures.
20
+ */
33
21
  var MarqueeText = React.forwardRef(function (_a, ref) {
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;
35
- var isVertical = direction === "vertical";
36
- var containerMeasurement = useSharedValue({
37
- width: 0,
38
- height: 0,
39
- x: 0,
40
- y: 0,
41
- });
42
- var contentMeasurement = useSharedValue({
43
- width: 0,
44
- height: 0,
45
- x: 0,
46
- y: 0,
47
- });
22
+ 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, gap = _a.gap, // New prop
23
+ _j = _a.withGesture, // New prop
24
+ 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;
25
+ var isVertical = direction === 'vertical';
26
+ var isBounceMode = mode === AnimationMode.BOUNCE;
27
+ // Resolve gap/spacing (prefer gap)
28
+ var effectiveSpacing = gap !== undefined ? gap : spacing;
29
+ // Shared values
30
+ var containerSize = useSharedValue(0);
31
+ var contentSize = useSharedValue(0);
32
+ var offset = useSharedValue(0);
33
+ var isAnimating = useSharedValue(false);
34
+ // State for cloning
48
35
  var _m = React.useState(0), cloneTimes = _m[0], setCloneTimes = _m[1];
49
- var anim = useSharedValue(0);
50
- var isMounted = React.useRef(true);
51
- var isActive = useSharedValue(false);
52
- var frameRateMs = frameRate ? 1000 / frameRate : 1000 / 60;
53
- var pixelsPerMs = speed / 10;
54
- var frameCallback = useFrameCallback(function (frameInfo) {
55
- if (!enabled || frameInfo.timeSincePreviousFrame === null)
56
- return;
57
- var deltaTime = frameRateMs
58
- ? frameInfo.timeSincePreviousFrame / frameRateMs
59
- : frameInfo.timeSincePreviousFrame;
60
- anim.value += (reverse ? -1 : 1) * pixelsPerMs * deltaTime;
61
- }, false);
36
+ // Calculate how many clones we need
62
37
  useAnimatedReaction(function () {
63
- var contentDim = isVertical
64
- ? contentMeasurement.value.height
65
- : contentMeasurement.value.width;
66
- var containerDim = isVertical
67
- ? containerMeasurement.value.height
68
- : containerMeasurement.value.width;
69
- if (contentDim <= 0 || containerDim <= 0)
38
+ if (contentSize.value === 0 || containerSize.value === 0)
39
+ return 0;
40
+ // Conditional Animation Check:
41
+ // Only loop if content exceeds container?
42
+ // If contentSize <= containerSize, we need 0 clones (just original).
43
+ if (contentSize.value <= containerSize.value) {
70
44
  return 0;
71
- return Math.ceil(containerDim / contentDim) + 2;
72
- }, function (times) {
73
- if (times > 0 && isMounted.current) {
74
- runOnJS(setCloneTimes)(times);
75
45
  }
76
- }, [direction]);
77
- var start = React.useCallback(function () {
78
- if (!enabled)
46
+ return Math.ceil(containerSize.value / contentSize.value) + 2;
47
+ }, function (result) {
48
+ if (result !== cloneTimes) {
49
+ runOnJS(setCloneTimes)(result);
50
+ }
51
+ }, [contentSize, containerSize]);
52
+ // Animation Logic
53
+ var startAnimation = React.useCallback(function () {
54
+ 'worklet';
55
+ if (!enabled || contentSize.value === 0 || containerSize.value === 0)
56
+ return;
57
+ // If no clones needed (fits in screen), don't animate
58
+ if (contentSize.value <= containerSize.value) {
59
+ cancelAnimation(offset);
60
+ offset.value = 0; // Reset position
61
+ isAnimating.value = false;
79
62
  return;
80
- frameCallback.setActive(true);
81
- isActive.value = true;
63
+ }
64
+ cancelAnimation(offset);
65
+ isAnimating.value = true;
66
+ var size = contentSize.value + effectiveSpacing;
67
+ if (mode === AnimationMode.LOOP) {
68
+ // Continuous Loop
69
+ var duration = (size / speed) * 1000;
70
+ // Initial delay handled by a separate sequence wrapper
71
+ // The repeating part must be seamless: 0 -> -size, then instant reset to 0
72
+ offset.value = withDelay(delay, withRepeat(withSequence(withTiming(-size, {
73
+ duration: duration,
74
+ easing: Easing.linear,
75
+ }), withTiming(0, { duration: 0 })), -1, // Infinite repeat
76
+ false // No reverse
77
+ ));
78
+ }
79
+ else {
80
+ // Bounce Mode
81
+ var distance = Math.abs(contentSize.value - containerSize.value);
82
+ if (distance <= 0)
83
+ return;
84
+ var target = contentSize.value > containerSize.value
85
+ ? -(contentSize.value - containerSize.value)
86
+ : (containerSize.value - contentSize.value);
87
+ var duration = (Math.abs(target) / speed) * 1000;
88
+ offset.value = withRepeat(withSequence(withDelay(delay, withTiming(target, { duration: duration, easing: Easing.linear })), withDelay(endPauseDuration, withTiming(0, { duration: duration, easing: Easing.linear }))), -1, false);
89
+ }
90
+ }, [enabled, mode, speed, delay, endPauseDuration, effectiveSpacing, containerSize, contentSize]);
91
+ // Start/Stop Controls
92
+ var start = React.useCallback(function () {
93
+ runOnUI(startAnimation)();
82
94
  onAnimationStart === null || onAnimationStart === void 0 ? void 0 : onAnimationStart();
83
- }, [frameCallback, enabled, onAnimationStart]);
95
+ }, [startAnimation, onAnimationStart]);
84
96
  var stop = React.useCallback(function () {
85
- frameCallback.setActive(false);
86
- isActive.value = false;
97
+ cancelAnimation(offset);
98
+ isAnimating.value = false;
87
99
  onAnimationStop === null || onAnimationStop === void 0 ? void 0 : onAnimationStop();
88
- }, [frameCallback, onAnimationStop]);
100
+ }, [offset, onAnimationStop]);
89
101
  React.useImperativeHandle(ref, function () { return ({
90
102
  start: start,
91
103
  stop: stop,
92
- get isActive() {
93
- return isActive.value;
94
- },
104
+ get isActive() { return isAnimating.value; }
95
105
  }); });
96
- var pan = React.useMemo(function () {
97
- return Gesture.Pan()
98
- .enabled(withGesture && enabled)
99
- .onBegin(function () { return runOnJS(stop)(); })
100
- .onChange(function (e) {
101
- anim.value += -(isVertical ? e.changeY : e.changeX);
102
- })
103
- .onFinalize(function (e) {
104
- anim.value = withDecay({
105
- velocity: -(isVertical ? e.velocityY : e.velocityX),
106
- }, function (finished) {
107
- if (finished)
108
- runOnJS(start)();
109
- });
110
- });
111
- }, [withGesture, isVertical, anim, start, stop, enabled]);
112
- React.useEffect(function () {
113
- return function () {
114
- isMounted.current = false;
115
- stop();
116
- };
117
- }, [stop]);
118
- React.useEffect(function () {
119
- if (enabled) {
120
- var timer_1 = setTimeout(function () { return start(); }, delay);
121
- return function () { return clearTimeout(timer_1); };
122
- }
123
- else {
124
- stop();
106
+ // Effect to auto-start when layout is ready
107
+ useAnimatedReaction(function () { return contentSize.value > 0 && containerSize.value > 0 && cloneTimes > 0; }, function (isReady) {
108
+ if (isReady && enabled) {
109
+ runOnJS(start)();
125
110
  }
126
- }, [enabled, start, stop, delay]);
111
+ }, [cloneTimes, enabled, start]);
112
+ // Gesture Handler
113
+ var pan = Gesture.Pan()
114
+ .enabled(withGesture && enabled)
115
+ .onBegin(function () {
116
+ cancelAnimation(offset);
117
+ isAnimating.value = false;
118
+ })
119
+ .onChange(function (e) {
120
+ offset.value += isVertical ? e.changeY : e.changeX;
121
+ })
122
+ .onFinalize(function () {
123
+ // Logic to resume?
124
+ // For simplicity in declaring "clean reset", we might just restart the loop
125
+ // OR we can calculate where we are and finish the current cycle.
126
+ // Restarting is safest to prevent being "out of phase".
127
+ runOnJS(start)();
128
+ });
129
+ var animatedStyle = useAnimatedStyle(function () {
130
+ return {
131
+ transform: [
132
+ isVertical
133
+ ? { translateY: offset.value }
134
+ : { translateX: offset.value }
135
+ ],
136
+ };
137
+ });
127
138
  var renderContent = function () {
128
- if (typeof children === "string") {
129
- return (<Text style={[styles.defaultText, textStyle]} numberOfLines={1} ellipsizeMode="tail">
130
- {children}
131
- </Text>);
139
+ if (typeof children === 'string') {
140
+ return <Text style={textStyle}>{children}</Text>;
132
141
  }
133
- return (<View style={styles.childContainer}>
134
- {children}
135
- </View>);
142
+ return children;
136
143
  };
137
- return (<Animated.View style={[
138
- styles.container,
139
- { backgroundColor: backgroundColor },
140
- style,
141
- {
142
- minHeight: isVertical ? 20 : undefined,
143
- minWidth: !isVertical ? 20 : undefined,
144
- height: isVertical ? 'auto' : undefined,
145
- width: !isVertical ? 'auto' : undefined,
146
- },
147
- ]} onLayout={function (ev) {
148
- containerMeasurement.value = ev.nativeEvent.layout;
149
- }} pointerEvents="box-none">
150
- <GestureDetector gesture={pan}>
151
- <Animated.View style={[
152
- isVertical ? styles.column : styles.row,
153
- styles.contentWrapper,
154
- ]} pointerEvents="box-none">
155
- <View style={styles.hidden} onLayout={function (ev) {
156
- contentMeasurement.value = ev.nativeEvent.layout;
144
+ return (<View style={[styles.container, { backgroundColor: backgroundColor }, style]} onLayout={function (ev) {
145
+ containerSize.value = isVertical ? ev.nativeEvent.layout.height : ev.nativeEvent.layout.width;
157
146
  }}>
158
- {renderContent()}
159
- </View>
160
-
161
- {cloneTimes > 0 &&
162
- Array.from({ length: cloneTimes }).map(function (_, index) { return (<AnimatedChild key={"clone-".concat(index)} index={index} anim={anim} contentMeasurement={contentMeasurement} spacing={spacing} direction={direction}>
147
+ <GestureDetector gesture={pan}>
148
+ <Animated.View style={[isVertical ? styles.column : styles.row, animatedStyle]}>
149
+ {/* Original Items + Clones */}
150
+ {/* We render a list of items based on cloneTimes */}
151
+ {Array.from({ length: Math.max(1, cloneTimes) }).map(function (_, index) {
152
+ var _a;
153
+ // We need to space them out.
154
+ // In this simplified declarative model, we just render them in a flex row/col with gaps/margins.
155
+ // We don't need absolute positioning if we use Flexbox layout properly!
156
+ return (<View key={index} style={_a = {},
157
+ _a[isVertical ? 'marginBottom' : 'marginRight'] = effectiveSpacing,
158
+ _a} onLayout={index === 0 ? function (ev) {
159
+ contentSize.value = isVertical ? ev.nativeEvent.layout.height : ev.nativeEvent.layout.width;
160
+ } : undefined}>
163
161
  {renderContent()}
164
- </AnimatedChild>); })}
162
+ </View>);
163
+ })}
165
164
  </Animated.View>
166
165
  </GestureDetector>
167
- </Animated.View>);
166
+ </View>);
168
167
  });
169
168
  var styles = StyleSheet.create({
170
169
  container: {
171
- overflow: "hidden",
170
+ overflow: 'hidden',
172
171
  },
173
172
  hidden: {
174
173
  opacity: 0,
175
- position: "absolute",
174
+ position: 'absolute',
176
175
  zIndex: -1,
177
176
  },
178
177
  row: {
179
- flexDirection: "row",
180
- position: "relative",
181
- alignItems: 'center',
178
+ flexDirection: 'row',
179
+ position: 'relative',
182
180
  },
183
181
  column: {
184
- flexDirection: "column",
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,
182
+ flexDirection: 'column',
183
+ position: 'relative',
199
184
  },
200
185
  });
201
- export { AnimationMode };
202
- export default MarqueeText;
186
+ export { MarqueeText, AnimationMode };
@@ -1,109 +1,4 @@
1
- import { ViewStyle, TextStyle } from "react-native";
2
- /**
3
- * Animation modes for the marquee text
4
- */
5
- export declare enum AnimationMode {
6
- LOOP = "loop",
7
- BOUNCE = "bounce"
8
- }
9
- /**
10
- * Direction of the marquee animation
11
- */
12
- type MarqueeDirection = 'horizontal' | 'vertical';
13
- /**
14
- * Props for the MarqueeText component
15
- */
16
- export interface MarqueeTextProps {
17
- /**
18
- * Content to be scrolled (string or React nodes)
19
- */
20
- children: React.ReactNode;
21
- /**
22
- * The animation mode: 'loop' for continuous scrolling or 'bounce' for back-and-forth
23
- * @default AnimationMode.LOOP
24
- */
25
- mode?: AnimationMode;
26
- /**
27
- * Speed of the scrolling animation in pixels per second
28
- * @default 30
29
- */
30
- speed?: number;
31
- /**
32
- * Delay in milliseconds before starting the animation
33
- * @default 1500
34
- */
35
- delay?: number;
36
- /**
37
- * Duration in milliseconds to pause at the end of the content (only for bounce mode)
38
- * @default 1000
39
- */
40
- endPauseDuration?: number;
41
- /**
42
- * Container style
43
- */
44
- style?: ViewStyle;
45
- /**
46
- * Text style (when children is a string)
47
- */
48
- textStyle?: TextStyle;
49
- /**
50
- * Whether to enable the animation
51
- * @default true
52
- */
53
- enabled?: boolean;
54
- /**
55
- * Direction of scrolling ('horizontal' or 'vertical')
56
- * @default 'horizontal'
57
- */
58
- direction?: MarqueeDirection;
59
- /**
60
- * Spacing between cloned elements
61
- * @default 20
62
- */
63
- spacing?: number;
64
- /**
65
- * Allow user interaction with gesture handling
66
- * @default true
67
- */
68
- withGesture?: boolean;
69
- /**
70
- * Custom frame rate for animation
71
- */
72
- frameRate?: number;
73
- /**
74
- * Reverse the animation direction
75
- * @default false
76
- */
77
- reverse?: boolean;
78
- /**
79
- * Background color for the container
80
- * @default 'transparent'
81
- */
82
- backgroundColor?: string;
83
- /**
84
- * Callback when animation starts
85
- */
86
- onAnimationStart?: () => void;
87
- /**
88
- * Callback when animation stops
89
- */
90
- onAnimationStop?: () => void;
91
- }
92
- /**
93
- * Reference handle for the MarqueeText component
94
- */
95
- export interface MarqueeTextRef {
96
- /**
97
- * Start the marquee animation
98
- */
99
- start: () => void;
100
- /**
101
- * Stop the marquee animation
102
- */
103
- stop: () => void;
104
- /**
105
- * Whether the animation is currently active
106
- */
107
- isActive: boolean;
108
- }
109
- export {};
1
+ export declare const AnimationMode: {
2
+ LOOP: string;
3
+ BOUNCE: string;
4
+ };
package/dist/constants.js CHANGED
@@ -1,12 +1,4 @@
1
- // export const AnimationMode = {
2
- // LOOP: 'loop',
3
- // BOUNCE: 'bounce',
4
- // };
5
- /**
6
- * Animation modes for the marquee text
7
- */
8
- export var AnimationMode;
9
- (function (AnimationMode) {
10
- AnimationMode["LOOP"] = "loop";
11
- AnimationMode["BOUNCE"] = "bounce";
12
- })(AnimationMode || (AnimationMode = {}));
1
+ export var AnimationMode = {
2
+ LOOP: 'loop',
3
+ BOUNCE: 'bounce',
4
+ };
package/dist/index.d.ts CHANGED
@@ -1,18 +1,6 @@
1
- import { AnimationMode } from './MarqueeText';
2
- export { AnimationMode } from './constants';
3
- declare const Marquee: {
4
- AutoScroll: ({ children, mode, speed, delay, endPauseDuration, style, textStyle, enabled, direction, }: {
5
- children: React.ReactNode;
6
- mode?: import("./constants").AnimationMode;
7
- speed?: number;
8
- delay?: number;
9
- endPauseDuration?: number;
10
- style?: import("react-native").ViewStyle;
11
- textStyle?: import("react-native").TextStyle;
12
- enabled?: boolean;
13
- direction?: "horizontal" | "vertical";
14
- }) => import("react").JSX.Element;
15
- MarqueeText: import("react").ForwardRefExoticComponent<import("./MarqueeText").MarqueeTextProps & import("react").RefAttributes<import("./MarqueeText").MarqueeTextRef>>;
16
- AnimationMode: typeof AnimationMode;
17
- };
18
- export default Marquee;
1
+ import { AutoScroll } from './AutoScroll';
2
+ import { AnimationMode } from './constants';
3
+ declare const MarqueeTextShim: any;
4
+ declare const MarqueeShim: any;
5
+ export { AutoScroll, AnimationMode, MarqueeTextShim as MarqueeText, MarqueeShim as Marquee };
6
+ export default AutoScroll;
package/dist/index.js CHANGED
@@ -1,10 +1,8 @@
1
- import AutoScroll from './AutoScroll';
2
- import MarqueeText, { AnimationMode } from './MarqueeText';
3
- export { AnimationMode } from './constants';
4
- // Optional: Default export (choose either AutoScroll or MarqueeText as default)
5
- var Marquee = {
6
- AutoScroll: AutoScroll,
7
- MarqueeText: MarqueeText,
8
- AnimationMode: AnimationMode,
9
- };
10
- export default Marquee;
1
+ import { AutoScroll } from './AutoScroll';
2
+ import { MarqueeText } from './MarqueeText';
3
+ import { AnimationMode } from './constants';
4
+ // @ts-ignore - Shim for React 18/19 compatibility
5
+ var MarqueeTextShim = MarqueeText;
6
+ var MarqueeShim = MarqueeText;
7
+ export { AutoScroll, AnimationMode, MarqueeTextShim as MarqueeText, MarqueeShim as Marquee };
8
+ export default AutoScroll;
package/package.json CHANGED
@@ -1,60 +1,58 @@
1
1
  {
2
- "name": "rn-marquee-text",
3
- "version": "2.1.2-beta.1",
4
- "description": "A customizable marquee (scrolling) text component for React Native",
5
- "main": "index.js",
6
- "types": "index.d.ts",
7
- "scripts": {
8
- "test": "echo \"Error: no test specified\" && exit 1",
9
- "build": "tsc",
10
- "prepare": "npm run build"
11
- },
12
- "publishConfig": {
13
- "tag": "beta"
14
- },
15
- "files": [
16
- "dist",
17
- "index.js",
18
- "README.md",
19
- "index.d.ts"
20
- ],
21
- "keywords": [
22
- "react-native",
23
- "marquee",
24
- "scrolling-text",
25
- "text",
26
- "animation",
27
- "react-native-component",
28
- "react",
29
- "native",
30
- "expo"
31
- ],
32
- "author": "Paresh Chavda",
33
- "license": "MIT",
34
- "repository": {
35
- "type": "git",
36
- "url": "git+https://github.com/pareshchavda/rn-marquee-text-public.git"
37
- },
38
- "bugs": {
39
- "url": "https://github.com/pareshchavda/rn-marquee-text-public/issues"
40
- },
41
- "homepage": "https://github.com/pareshchavda/rn-marquee-text-public#readme",
42
- "peerDependencies": {
43
- "prop-types": ">=15.0.0",
44
- "react": "*",
45
- "react-native": "*",
46
- "react-native-reanimated": ">=2.0.0"
47
- },
48
- "devDependencies": {
49
- "@types/react": "^19.1.2",
50
- "prop-types": "^15.8.1",
51
- "react": "^18.2.0",
52
- "react-native": "^0.72.17",
53
- "react-native-reanimated": "^3.17.5",
54
- "typescript": "^5.0.0"
55
- },
56
- "dependencies": {
57
- "@react-navigation/native": "^7.1.9",
58
- "react-native-gesture-handler": "^2.25.0"
59
- }
60
- }
2
+ "name": "rn-marquee-text",
3
+ "version": "3.0.0",
4
+ "description": "A customizable marquee (scrolling) text component for React Native",
5
+ "main": "dist/index.js",
6
+ "types": "dist/index.d.ts",
7
+ "scripts": {
8
+ "test": "echo \"Error: no test specified\" && exit 1",
9
+ "build": "tsc",
10
+ "prepare": "npm run build"
11
+ },
12
+ "files": [
13
+ "dist",
14
+ "index.js",
15
+ "README.md"
16
+ ],
17
+ "keywords": [
18
+ "react-native",
19
+ "marquee",
20
+ "scrolling-text",
21
+ "text",
22
+ "animation",
23
+ "react-native-component",
24
+ "react",
25
+ "native",
26
+ "expo",
27
+ "Marquee"
28
+ ],
29
+ "author": "Paresh Chavda",
30
+ "license": "MIT",
31
+ "repository": {
32
+ "type": "git",
33
+ "url": "git+https://github.com/pareshchavda/rn-marquee-text-public.git"
34
+ },
35
+ "bugs": {
36
+ "url": "https://github.com/pareshchavda/rn-marquee-text-public/issues"
37
+ },
38
+ "homepage": "https://github.com/pareshchavda/rn-marquee-text-public#readme",
39
+ "peerDependencies": {
40
+ "prop-types": ">=15.0.0",
41
+ "react": "*",
42
+ "react-native": "*",
43
+ "react-native-reanimated": ">=2.0.0",
44
+ "@react-navigation/native": ">=6.0.0"
45
+ },
46
+ "devDependencies": {
47
+ "@react-navigation/native": "^7.1.9",
48
+ "@types/react": "^19.1.2",
49
+ "prop-types": "^15.8.1",
50
+ "react": "^18.2.0",
51
+ "react-native": "^0.72.17",
52
+ "react-native-reanimated": "^3.17.5",
53
+ "typescript": "^5.0.0"
54
+ },
55
+ "dependencies": {
56
+ "react-native-gesture-handler": "^2.25.0"
57
+ }
58
+ }