@mihirsarya/manim-scroll-react 0.2.0 → 0.2.2

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 ADDED
@@ -0,0 +1,230 @@
1
+ # @mihirsarya/manim-scroll-react
2
+
3
+ React components and hooks for scroll-driven Manim animations.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install @mihirsarya/manim-scroll-react
9
+ ```
10
+
11
+ Or use the unified package (recommended):
12
+
13
+ ```bash
14
+ npm install @mihirsarya/manim-scroll
15
+ ```
16
+
17
+ ## Requirements
18
+
19
+ - React 18+
20
+ - `@mihirsarya/manim-scroll-runtime` (peer dependency, installed automatically)
21
+
22
+ ## Quick Start
23
+
24
+ ### With Next.js Plugin (Recommended)
25
+
26
+ When using with `@mihirsarya/manim-scroll-next`, animations are automatically resolved:
27
+
28
+ ```tsx
29
+ import { ManimScroll } from "@mihirsarya/manim-scroll-react";
30
+
31
+ export default function Page() {
32
+ return (
33
+ <ManimScroll
34
+ scene="TextScene"
35
+ fontSize={72}
36
+ color="#ffffff"
37
+ scrollRange="viewport"
38
+ >
39
+ Welcome to my site
40
+ </ManimScroll>
41
+ );
42
+ }
43
+ ```
44
+
45
+ ### Manual Mode
46
+
47
+ Without the Next.js plugin, provide an explicit manifest URL:
48
+
49
+ ```tsx
50
+ import { ManimScroll } from "@mihirsarya/manim-scroll-react";
51
+
52
+ export default function Page() {
53
+ return (
54
+ <ManimScroll
55
+ manifestUrl="/assets/scene/manifest.json"
56
+ scrollRange="viewport"
57
+ >
58
+ Scroll-driven text
59
+ </ManimScroll>
60
+ );
61
+ }
62
+ ```
63
+
64
+ ### Native Mode
65
+
66
+ For text animations without pre-rendered assets:
67
+
68
+ ```tsx
69
+ <ManimScroll mode="native" fontSize={48} color="#ffffff">
70
+ Animate this text
71
+ </ManimScroll>
72
+ ```
73
+
74
+ ## Exports
75
+
76
+ ### Components
77
+
78
+ - **`ManimScroll`** - Scroll-driven animation component
79
+
80
+ ### Hooks
81
+
82
+ - **`useManimScroll`** - Hook for custom integrations with pre-rendered assets
83
+ - **`useNativeAnimation`** - Hook for native SVG text animation
84
+
85
+ ### Utilities
86
+
87
+ - **`computePropsHash`** - Compute hash for animation props
88
+ - **`extractChildrenText`** - Extract text from React children
89
+
90
+ ### Types
91
+
92
+ - `ManimScrollProps`, `ManimAnimationProps`
93
+ - `UseManimScrollOptions`, `UseManimScrollResult`
94
+ - `UseNativeAnimationOptions`, `UseNativeAnimationResult`
95
+
96
+ ## ManimScroll Props
97
+
98
+ | Prop | Type | Default | Description |
99
+ |------|------|---------|-------------|
100
+ | `scene` | `string` | `"TextScene"` | Manim scene name |
101
+ | `fontSize` | `number` | - | Font size for text animations |
102
+ | `color` | `string` | - | Color as hex string |
103
+ | `font` | `string` | - | Font family |
104
+ | `inline` | `boolean` | `false` | Enable inline mode |
105
+ | `padding` | `number` | `0.2` | Padding in inline mode (Manim units) |
106
+ | `mode` | `"auto" \| "video" \| "frames" \| "native"` | `"auto"` | Playback mode |
107
+ | `scrollRange` | `ScrollRangeValue` | `"viewport"` | Scroll range configuration |
108
+ | `manifestUrl` | `string` | - | Explicit manifest URL |
109
+ | `fontUrl` | `string` | - | Font file URL for native mode |
110
+ | `strokeWidth` | `number` | `2` | Stroke width for native mode |
111
+ | `onReady` | `() => void` | - | Called when animation is loaded |
112
+ | `onProgress` | `(progress: number) => void` | - | Called on scroll progress |
113
+ | `canvas` | `{ width?, height? }` | - | Canvas dimensions |
114
+ | `className` | `string` | - | CSS class |
115
+ | `style` | `CSSProperties` | - | Inline styles |
116
+ | `children` | `ReactNode` | - | Text content |
117
+
118
+ ## useManimScroll Hook
119
+
120
+ For advanced use cases requiring custom control:
121
+
122
+ ```tsx
123
+ import { useRef } from "react";
124
+ import { useManimScroll } from "@mihirsarya/manim-scroll-react";
125
+
126
+ function CustomAnimation() {
127
+ const containerRef = useRef<HTMLDivElement>(null);
128
+
129
+ const { progress, isReady, error, pause, resume, seek } = useManimScroll({
130
+ ref: containerRef,
131
+ manifestUrl: "/assets/scene/manifest.json",
132
+ scrollRange: "viewport",
133
+ });
134
+
135
+ return (
136
+ <div ref={containerRef} style={{ height: "100vh" }}>
137
+ {!isReady && <div>Loading...</div>}
138
+ {error && <div>Error: {error.message}</div>}
139
+ <div>Progress: {Math.round(progress * 100)}%</div>
140
+ <button onClick={pause}>Pause</button>
141
+ <button onClick={resume}>Resume</button>
142
+ </div>
143
+ );
144
+ }
145
+ ```
146
+
147
+ ### Hook Options
148
+
149
+ | Option | Type | Description |
150
+ |--------|------|-------------|
151
+ | `ref` | `RefObject<HTMLElement>` | Container element ref (required) |
152
+ | `manifestUrl` | `string` | Explicit manifest URL |
153
+ | `scene` | `string` | Scene name for auto-resolution |
154
+ | `animationProps` | `Record<string, unknown>` | Props for auto-resolution |
155
+ | `mode` | `"auto" \| "frames" \| "video"` | Playback mode |
156
+ | `scrollRange` | `ScrollRangeValue` | Scroll range configuration |
157
+ | `canvasDimensions` | `{ width?, height? }` | Canvas size |
158
+ | `enabled` | `boolean` | Whether the hook is active |
159
+
160
+ ### Hook Return Value
161
+
162
+ | Property | Type | Description |
163
+ |----------|------|-------------|
164
+ | `progress` | `number` | Current scroll progress (0 to 1) |
165
+ | `isReady` | `boolean` | Whether animation is loaded |
166
+ | `error` | `Error \| null` | Loading error, if any |
167
+ | `canvasRef` | `RefObject<HTMLCanvasElement>` | Canvas element ref |
168
+ | `seek` | `(progress: number) => void` | Seek to specific progress |
169
+ | `pause` | `() => void` | Pause scroll-driven updates |
170
+ | `resume` | `() => void` | Resume scroll-driven updates |
171
+ | `isPaused` | `boolean` | Whether updates are paused |
172
+
173
+ ## useNativeAnimation Hook
174
+
175
+ For native SVG text animation without pre-rendered assets:
176
+
177
+ ```tsx
178
+ import { useRef } from "react";
179
+ import { useNativeAnimation } from "@mihirsarya/manim-scroll-react";
180
+
181
+ function NativeTextAnimation() {
182
+ const containerRef = useRef<HTMLDivElement>(null);
183
+
184
+ const { progress, isReady } = useNativeAnimation({
185
+ ref: containerRef,
186
+ text: "Hello World",
187
+ fontSize: 48,
188
+ color: "#ffffff",
189
+ });
190
+
191
+ return (
192
+ <div ref={containerRef} style={{ height: "100vh" }}>
193
+ {!isReady && <div>Loading...</div>}
194
+ </div>
195
+ );
196
+ }
197
+ ```
198
+
199
+ ### Hook Options
200
+
201
+ | Option | Type | Description |
202
+ |--------|------|-------------|
203
+ | `ref` | `RefObject<HTMLElement>` | Container element ref (required) |
204
+ | `text` | `string` | Text to animate (required) |
205
+ | `fontSize` | `number` | Font size in pixels (inherits from parent if not set) |
206
+ | `color` | `string` | Text color |
207
+ | `fontUrl` | `string` | URL to font file for opentype.js |
208
+ | `strokeWidth` | `number` | Stroke width for drawing phase |
209
+ | `scrollRange` | `ScrollRangeValue` | Scroll range configuration |
210
+ | `enabled` | `boolean` | Whether the hook is active |
211
+
212
+ ## Scroll Range Configuration
213
+
214
+ ```tsx
215
+ // Presets
216
+ scrollRange="viewport" // Animation plays as element crosses viewport
217
+ scrollRange="element" // Tied to element's own scroll position
218
+ scrollRange="full" // Spans entire document scroll
219
+
220
+ // Relative units
221
+ scrollRange={["100vh", "-50%"]}
222
+
223
+ // Pixel values
224
+ scrollRange={[800, -400]}
225
+ scrollRange={{ start: 800, end: -400 }}
226
+ ```
227
+
228
+ ## License
229
+
230
+ MIT
@@ -34,7 +34,7 @@ export type ManimScrollProps = ManimAnimationProps & {
34
34
  * - "native": Uses native SVG animation (no pre-rendered assets)
35
35
  */
36
36
  mode?: "auto" | "frames" | "video" | "native";
37
- /** Scroll range configuration (preset, tuple, or legacy object) */
37
+ /** Scroll range configuration (preset, tuple, or legacy object). Ignored when progress is provided. */
38
38
  scrollRange?: ScrollRangeValue;
39
39
  /** Called when animation is loaded and ready */
40
40
  onReady?: () => void;
@@ -49,6 +49,12 @@ export type ManimScrollProps = ManimAnimationProps & {
49
49
  fontUrl?: string;
50
50
  /** Stroke width for native mode drawing phase */
51
51
  strokeWidth?: number;
52
+ /**
53
+ * Explicit progress value (0 to 1). When provided, disables scroll-based control
54
+ * and renders the animation at this exact progress (controlled mode).
55
+ * Works with native mode. For advanced control, use useNativeAnimation hook.
56
+ */
57
+ progress?: number;
52
58
  className?: string;
53
59
  style?: React.CSSProperties;
54
60
  children?: React.ReactNode;
@@ -78,4 +84,4 @@ export type ManimScrollProps = ManimAnimationProps & {
78
84
  * </ManimScroll>
79
85
  * ```
80
86
  */
81
- export declare function ManimScroll({ className, style, children, canvas, manifestUrl, mode, scrollRange, onReady, onProgress, fontUrl, strokeWidth, scene, fontSize, color, font, inline, padding, ...customProps }: ManimScrollProps): JSX.Element;
87
+ export declare function ManimScroll({ className, style, children, canvas, manifestUrl, mode, scrollRange, onReady, onProgress, fontUrl, strokeWidth, progress: controlledProgress, scene, fontSize, color, font, inline, padding, ...customProps }: ManimScrollProps): JSX.Element;
@@ -27,7 +27,7 @@ import { extractChildrenText } from "./hash";
27
27
  * </ManimScroll>
28
28
  * ```
29
29
  */
30
- export function ManimScroll({ className, style, children, canvas, manifestUrl, mode, scrollRange, onReady, onProgress, fontUrl, strokeWidth,
30
+ export function ManimScroll({ className, style, children, canvas, manifestUrl, mode, scrollRange, onReady, onProgress, fontUrl, strokeWidth, progress: controlledProgress,
31
31
  // Animation props
32
32
  scene = "TextScene", fontSize, color, font, inline, padding, ...customProps }) {
33
33
  const containerRef = useRef(null);
@@ -72,6 +72,7 @@ scene = "TextScene", fontSize, color, font, inline, padding, ...customProps }) {
72
72
  fontUrl,
73
73
  strokeWidth,
74
74
  scrollRange,
75
+ progress: controlledProgress, // Pass progress for controlled mode
75
76
  enabled: isNativeMode,
76
77
  });
77
78
  // Select the appropriate result based on mode
package/dist/hooks.d.ts CHANGED
@@ -100,27 +100,60 @@ export interface UseNativeAnimationOptions {
100
100
  fontUrl?: string;
101
101
  /** Stroke width for the drawing phase */
102
102
  strokeWidth?: number;
103
- /** Scroll range configuration */
103
+ /** Scroll range configuration. Ignored when progress is provided. */
104
104
  scrollRange?: ScrollRangeValue;
105
+ /**
106
+ * Explicit progress value (0 to 1). When provided, disables scroll-based control
107
+ * and renders the animation at this exact progress (controlled mode).
108
+ */
109
+ progress?: number;
105
110
  /** Whether the hook is enabled (default: true) */
106
111
  enabled?: boolean;
107
112
  }
113
+ /**
114
+ * Playback options for the play() method.
115
+ */
116
+ export interface NativePlaybackOptions {
117
+ /** Animation duration in milliseconds */
118
+ duration?: number;
119
+ /** Delay before starting in milliseconds */
120
+ delay?: number;
121
+ /** Easing preset or custom function */
122
+ easing?: "linear" | "ease-in" | "ease-out" | "ease-in-out" | "smooth" | ((t: number) => number);
123
+ /** Whether to loop the animation */
124
+ loop?: boolean;
125
+ /** Play direction: 1 for forward, -1 for reverse */
126
+ direction?: 1 | -1;
127
+ /** Callback when playback completes */
128
+ onComplete?: () => void;
129
+ }
108
130
  /**
109
131
  * Result returned by the useNativeAnimation hook.
110
132
  */
111
133
  export interface UseNativeAnimationResult {
112
- /** Current scroll progress (0 to 1) */
134
+ /** Current animation progress (0 to 1) */
113
135
  progress: number;
114
136
  /** Whether the animation is loaded and ready */
115
137
  isReady: boolean;
116
138
  /** Error if initialization failed */
117
139
  error: Error | null;
118
- /** Pause scroll-driven updates */
140
+ /** Pause scroll-driven updates (legacy, use pause() for playback) */
119
141
  pause: () => void;
120
- /** Resume scroll-driven updates */
142
+ /** Resume scroll-driven updates (legacy) */
121
143
  resume: () => void;
122
144
  /** Whether scroll updates are paused */
123
145
  isPaused: boolean;
146
+ /**
147
+ * Play animation over a duration.
148
+ * @param options - Duration in ms, or PlaybackOptions object
149
+ */
150
+ play: (options?: NativePlaybackOptions | number) => void;
151
+ /** Seek to specific progress (0-1). Doesn't affect playing state. */
152
+ seek: (progress: number) => void;
153
+ /** Set progress and stop any playback. For controlled mode. */
154
+ setProgress: (progress: number) => void;
155
+ /** Whether time-based animation is currently playing */
156
+ isPlaying: boolean;
124
157
  }
125
158
  /**
126
159
  * Hook for native text animation that renders directly in the browser
@@ -129,23 +162,34 @@ export interface UseNativeAnimationResult {
129
162
  * This hook bypasses the manifest resolution and pre-rendered assets,
130
163
  * instead animating text natively using opentype.js and SVG.
131
164
  *
165
+ * Supports three usage modes:
166
+ * 1. Scroll-driven (default): Animation driven by scroll position
167
+ * 2. Controlled: Pass progress prop for React-style controlled components
168
+ * 3. Imperative: Use play(), seek(), setProgress() for programmatic control
169
+ *
132
170
  * @example
133
171
  * ```tsx
134
- * function NativeTextAnimation() {
135
- * const containerRef = useRef<HTMLDivElement>(null);
136
- * const { progress, isReady } = useNativeAnimation({
137
- * ref: containerRef,
138
- * text: "Hello World",
139
- * fontSize: 48,
140
- * color: "#ffffff",
141
- * });
172
+ * // Scroll-driven mode (default)
173
+ * const { progress, isReady } = useNativeAnimation({
174
+ * ref: containerRef,
175
+ * text: "Hello World",
176
+ * fontSize: 48,
177
+ * });
142
178
  *
143
- * return (
144
- * <div ref={containerRef} style={{ height: "100vh" }}>
145
- * {!isReady && <div>Loading...</div>}
146
- * </div>
147
- * );
148
- * }
179
+ * // Controlled mode
180
+ * const [progress, setProgress] = useState(0);
181
+ * useNativeAnimation({
182
+ * ref: containerRef,
183
+ * text: "Hello World",
184
+ * progress, // Animation renders at this exact progress
185
+ * });
186
+ *
187
+ * // Imperative mode
188
+ * const { play, isReady } = useNativeAnimation({
189
+ * ref: containerRef,
190
+ * text: "Hello World",
191
+ * });
192
+ * useEffect(() => { if (isReady) play(2000); }, [isReady]); // Play over 2s
149
193
  * ```
150
194
  */
151
195
  export declare function useNativeAnimation(options: UseNativeAnimationOptions): UseNativeAnimationResult;
package/dist/hooks.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { useEffect, useRef, useState, useMemo, useCallback } from "react";
2
- import { registerScrollAnimation, registerNativeAnimation } from "@mihirsarya/manim-scroll-runtime";
2
+ import { registerScrollAnimation, NativeTextPlayer } from "@mihirsarya/manim-scroll-runtime";
3
3
  import { computePropsHash } from "./hash";
4
4
  // Global cache manifest state
5
5
  let cachedManifest = null;
@@ -234,43 +234,55 @@ export { loadCacheManifest, resolveManifestUrl };
234
234
  * This hook bypasses the manifest resolution and pre-rendered assets,
235
235
  * instead animating text natively using opentype.js and SVG.
236
236
  *
237
+ * Supports three usage modes:
238
+ * 1. Scroll-driven (default): Animation driven by scroll position
239
+ * 2. Controlled: Pass progress prop for React-style controlled components
240
+ * 3. Imperative: Use play(), seek(), setProgress() for programmatic control
241
+ *
237
242
  * @example
238
243
  * ```tsx
239
- * function NativeTextAnimation() {
240
- * const containerRef = useRef<HTMLDivElement>(null);
241
- * const { progress, isReady } = useNativeAnimation({
242
- * ref: containerRef,
243
- * text: "Hello World",
244
- * fontSize: 48,
245
- * color: "#ffffff",
246
- * });
244
+ * // Scroll-driven mode (default)
245
+ * const { progress, isReady } = useNativeAnimation({
246
+ * ref: containerRef,
247
+ * text: "Hello World",
248
+ * fontSize: 48,
249
+ * });
247
250
  *
248
- * return (
249
- * <div ref={containerRef} style={{ height: "100vh" }}>
250
- * {!isReady && <div>Loading...</div>}
251
- * </div>
252
- * );
253
- * }
251
+ * // Controlled mode
252
+ * const [progress, setProgress] = useState(0);
253
+ * useNativeAnimation({
254
+ * ref: containerRef,
255
+ * text: "Hello World",
256
+ * progress, // Animation renders at this exact progress
257
+ * });
258
+ *
259
+ * // Imperative mode
260
+ * const { play, isReady } = useNativeAnimation({
261
+ * ref: containerRef,
262
+ * text: "Hello World",
263
+ * });
264
+ * useEffect(() => { if (isReady) play(2000); }, [isReady]); // Play over 2s
254
265
  * ```
255
266
  */
256
267
  export function useNativeAnimation(options) {
257
268
  const { ref, text, fontSize, // undefined means inherit from parent
258
269
  color = "#ffffff", fontUrl, strokeWidth = 2, // Manim's DrawBorderThenFill default
259
- scrollRange, enabled = true, } = options;
260
- const [progress, setProgress] = useState(0);
270
+ scrollRange, progress: controlledProgress, enabled = true, } = options;
271
+ const [progress, setProgressState] = useState(controlledProgress !== null && controlledProgress !== void 0 ? controlledProgress : 0);
261
272
  const [isReady, setIsReady] = useState(false);
262
273
  const [error, setError] = useState(null);
263
274
  const [isPaused, setIsPaused] = useState(false);
264
- const cleanupRef = useRef(null);
275
+ const [isPlaying, setIsPlaying] = useState(false);
276
+ const playerRef = useRef(null);
265
277
  const pausedRef = useRef(isPaused);
266
278
  // Keep pausedRef in sync
267
279
  useEffect(() => {
268
280
  pausedRef.current = isPaused;
269
281
  }, [isPaused]);
270
- // Handle progress updates (respects pause state)
282
+ // Handle progress updates (respects pause state for scroll-driven mode)
271
283
  const handleProgress = useCallback((p) => {
272
284
  if (!pausedRef.current) {
273
- setProgress(p);
285
+ setProgressState(p);
274
286
  }
275
287
  }, []);
276
288
  // Handle ready callback
@@ -285,7 +297,7 @@ export function useNativeAnimation(options) {
285
297
  if (!container || !text)
286
298
  return;
287
299
  let isMounted = true;
288
- const nativeOptions = {
300
+ const player = new NativeTextPlayer({
289
301
  container,
290
302
  text,
291
303
  fontSize,
@@ -293,16 +305,17 @@ export function useNativeAnimation(options) {
293
305
  fontUrl,
294
306
  strokeWidth,
295
307
  scrollRange,
308
+ progress: controlledProgress,
296
309
  onReady: handleReady,
297
310
  onProgress: handleProgress,
298
- };
299
- registerNativeAnimation(nativeOptions)
300
- .then((dispose) => {
311
+ });
312
+ player.init()
313
+ .then(() => {
301
314
  if (!isMounted) {
302
- dispose();
315
+ player.destroy();
303
316
  return;
304
317
  }
305
- cleanupRef.current = dispose;
318
+ playerRef.current = player;
306
319
  })
307
320
  .catch((err) => {
308
321
  if (isMounted) {
@@ -310,18 +323,60 @@ export function useNativeAnimation(options) {
310
323
  }
311
324
  });
312
325
  return () => {
313
- var _a;
314
326
  isMounted = false;
315
- (_a = cleanupRef.current) === null || _a === void 0 ? void 0 : _a.call(cleanupRef);
327
+ player.destroy();
328
+ playerRef.current = null;
316
329
  setIsReady(false);
317
330
  };
318
- }, [enabled, ref, text, fontSize, color, fontUrl, strokeWidth, scrollRange, handleProgress, handleReady]);
331
+ }, [enabled, ref, text, fontSize, color, fontUrl, strokeWidth, scrollRange, controlledProgress, handleProgress, handleReady]);
332
+ // Update progress when controlled prop changes
333
+ useEffect(() => {
334
+ if (controlledProgress !== undefined && playerRef.current) {
335
+ playerRef.current.setProgress(controlledProgress);
336
+ setProgressState(controlledProgress);
337
+ }
338
+ }, [controlledProgress]);
339
+ // Legacy pause/resume for scroll-driven mode
319
340
  const pause = useCallback(() => {
320
341
  setIsPaused(true);
321
342
  }, []);
322
343
  const resume = useCallback(() => {
323
344
  setIsPaused(false);
324
345
  }, []);
346
+ // Playback controls
347
+ const play = useCallback((playOptions) => {
348
+ const player = playerRef.current;
349
+ if (!player)
350
+ return;
351
+ setIsPlaying(true);
352
+ if (typeof playOptions === "number") {
353
+ player.play({
354
+ duration: playOptions,
355
+ onComplete: () => setIsPlaying(false),
356
+ });
357
+ }
358
+ else {
359
+ player.play({
360
+ ...playOptions,
361
+ onComplete: () => {
362
+ var _a;
363
+ (_a = playOptions === null || playOptions === void 0 ? void 0 : playOptions.onComplete) === null || _a === void 0 ? void 0 : _a.call(playOptions);
364
+ setIsPlaying(false);
365
+ },
366
+ });
367
+ }
368
+ }, []);
369
+ const seek = useCallback((targetProgress) => {
370
+ var _a;
371
+ (_a = playerRef.current) === null || _a === void 0 ? void 0 : _a.seek(targetProgress);
372
+ setProgressState(targetProgress);
373
+ }, []);
374
+ const setProgress = useCallback((targetProgress) => {
375
+ var _a;
376
+ (_a = playerRef.current) === null || _a === void 0 ? void 0 : _a.setProgress(targetProgress);
377
+ setProgressState(targetProgress);
378
+ setIsPlaying(false);
379
+ }, []);
325
380
  return {
326
381
  progress,
327
382
  isReady,
@@ -329,5 +384,9 @@ export function useNativeAnimation(options) {
329
384
  pause,
330
385
  resume,
331
386
  isPaused,
387
+ play,
388
+ seek,
389
+ setProgress,
390
+ isPlaying,
332
391
  };
333
392
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mihirsarya/manim-scroll-react",
3
- "version": "0.2.0",
3
+ "version": "0.2.2",
4
4
  "description": "React wrapper for scroll-driven Manim animations.",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -12,7 +12,7 @@
12
12
  "react-dom": ">=18.0.0"
13
13
  },
14
14
  "dependencies": {
15
- "@mihirsarya/manim-scroll-runtime": "0.2.0"
15
+ "@mihirsarya/manim-scroll-runtime": "0.2.2"
16
16
  },
17
17
  "devDependencies": {
18
18
  "@types/react": "^18.2.61",