react-gsap-aos 1.4.1 → 1.4.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 CHANGED
@@ -1,383 +1,3 @@
1
1
  # react-gsap-aos
2
2
 
3
- [中文文檔](README.zh-TW.md) | English
4
-
5
- A lightweight GSAP + ScrollTrigger integration with an AOS-like API, specifically designed for React and Next.js applications.
6
-
7
- [![npm version](https://img.shields.io/npm/v/react-gsap-aos.svg)](https://www.npmjs.com/package/react-gsap-aos)
8
- [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT)
9
-
10
- [Live Demo](https://react-gsap-aos-nextjs.vercel.app) | [GitHub](https://github.com/GaiaYang/react-gsap-aos)
11
-
12
- ## What is react-gsap-aos?
13
-
14
- `react-gsap-aos` bridges the gap between GSAP's powerful animation capabilities and the simplicity of AOS (Animate On Scroll). It provides:
15
-
16
- - **Familiar API**: If you've used AOS, you already know how to use this
17
- - **GSAP Power**: Built on GSAP + ScrollTrigger for smooth, performant animations
18
- - **React-First**: Designed specifically for React and Next.js with proper SSR support
19
- - **TypeScript**: Full type safety for animations, easings, and anchor placements
20
- - **Automatic Cleanup**: Properly manages animation lifecycle with React's component lifecycle
21
-
22
- ### Problem It Solves
23
-
24
- While AOS is great for vanilla JavaScript, integrating it with React can be problematic:
25
-
26
- - Manual initialization and cleanup required
27
- - Not SSR-friendly
28
- - Limited TypeScript support
29
- - Difficult to use with dynamic content
30
-
31
- `react-gsap-aos` by React solution that automatically handles DOM mutations, component lifecycle, and SSR scenarios.
32
-
33
- ## Features
34
-
35
- - 🎬 Scroll-triggered animations powered by GSAP + ScrollTrigger
36
- - 🎯 AOS-like API with `data-aos` attributes
37
- - ⚛️ Built for React / Next.js with SSR support
38
- - 🔄 Automatic animation management with DOM mutations
39
- - 📦 Multiple parallel scopes without interference
40
- - 🎨 34 animation presets (fade, slide, flip, zoom variants)
41
- - 🎭 17 easing options from GSAP
42
- - 📍 9 anchor placement options for precise triggering
43
- - 🧹 Automatic cleanup on component unmount
44
- - 💪 Full TypeScript support
45
-
46
- ## Installation
47
-
48
- ```bash
49
- npm install react-gsap-aos gsap @gsap/react
50
- # or
51
- yarn add react-gsap-aos gsap @gsap/react
52
- # or
53
- pnpm add react-gsap-aos gsap @gsap/react
54
- ```
55
-
56
- ### Peer Dependencies
57
-
58
- - `react` >= 17
59
- - `gsap` ^3.12.5
60
- - `@gsap/react` ^2.1.2
61
-
62
- ## Quick Start
63
-
64
- ```tsx
65
- import { AOSProvider } from "react-gsap-aos/client";
66
-
67
- export default function Demo() {
68
- return (
69
- <AOSProvider className="overflow-hidden">
70
- <div data-aos-container>
71
- <div data-aos="fade-up" data-aos-offset="200">
72
- Hello AOS
73
- </div>
74
- </div>
75
- </AOSProvider>
76
- );
77
- }
78
- ```
79
-
80
- ## Usage
81
-
82
- ### Setting up AOSProvider
83
-
84
- Wrap your animated content with `AOSProvider`. All child elements with `data-aos` attributes will be automatically animated.
85
-
86
- ```tsx
87
- import { AOSProvider } from "react-gsap-aos/client";
88
-
89
- export default function Demo() {
90
- return (
91
- <AOSProvider className="overflow-hidden">
92
- {/* Your animated content */}
93
- </AOSProvider>
94
- );
95
- }
96
- ```
97
-
98
- > The `overflow-hidden` class prevents elements from overflowing during their initial animation state.
99
-
100
- ⚠️ **Important**: Do not nest `AOSProvider` components, as this will cause duplicate listeners and animations.
101
-
102
- ### Configuring Animations with Data Attributes
103
-
104
- Use `data-aos-*` attributes to configure animation behavior:
105
-
106
- ```tsx
107
- <div
108
- data-aos="fade-up"
109
- data-aos-offset={120}
110
- data-aos-delay={0}
111
- data-aos-duration={400}
112
- data-aos-easing="ease-out-cubic"
113
- data-aos-mirror={false}
114
- data-aos-once={false}
115
- data-aos-anchor-placement="top-bottom"
116
- >
117
- Animated content
118
- </div>
119
- ```
120
-
121
- ### Using toAOSProps Helper
122
-
123
- For better TypeScript support and validation, use the `toAOSProps` helper:
124
-
125
- ```tsx
126
- import { toAOSProps } from "react-gsap-aos";
127
-
128
- <div
129
- {...toAOSProps({
130
- animation: "fade-up",
131
- offset: 120,
132
- delay: 0,
133
- duration: 400,
134
- easing: "power2.out",
135
- once: false,
136
- mirror: false,
137
- anchorPlacement: "top-bottom",
138
- })}
139
- >
140
- Animated content
141
- </div>;
142
- ```
143
-
144
- ### Container Positioning with data-aos-container
145
-
146
- To ensure accurate ScrollTrigger calculations, mark parent containers with `data-aos-container`:
147
-
148
- ```tsx
149
- <AOSProvider className="overflow-hidden">
150
- {/* ✅ Correct: Container specified */}
151
- <div data-aos-container>
152
- <div data-aos="fade-up" data-aos-offset="200">
153
- Hello AOS
154
- </div>
155
- </div>
156
-
157
- {/* ❌ Incorrect: May cause offset issues */}
158
- <div data-aos="fade-up" data-aos-offset="200">
159
- Hello AOS
160
- </div>
161
- </AOSProvider>
162
- ```
163
-
164
- Nested containers are supported:
165
-
166
- ```tsx
167
- <div data-aos-container>
168
- <div data-aos="fade-up">Parent animation</div>
169
-
170
- <div data-aos-container>
171
- <div data-aos="zoom-in">Nested animation</div>
172
- </div>
173
- </div>
174
- ```
175
-
176
- ## API Reference
177
-
178
- ### AOSProvider
179
-
180
- A wrapper component that provides animation scope for its children.
181
-
182
- **Props:**
183
-
184
- | Prop | Type | Default | Description |
185
- | ----------- | --------------------------- | ----------- | ------------------------------------------ |
186
- | `component` | `React.ElementType` | `'div'` | The container element to render |
187
- | `className` | `string` | `undefined` | CSS classes for the container |
188
- | `options` | `Partial<AnimationOptions>` | `undefined` | Default animation options for all children |
189
- | `children` | `React.ReactNode` | - | Child elements |
190
-
191
- **Example:**
192
-
193
- ```tsx
194
- <AOSProvider
195
- component="section"
196
- className="overflow-hidden"
197
- options={{
198
- duration: 600,
199
- easing: "power2.out",
200
- once: true,
201
- }}
202
- >
203
- {/* Children will inherit these default options */}
204
- </AOSProvider>
205
- ```
206
-
207
- > The default options only affect animations generated subsequently. This is intentional behavior.
208
-
209
- ### useAOSScope
210
-
211
- The core hook that powers `AOSProvider`. Use this when you need direct control over the container ref.
212
-
213
- ```tsx
214
- function useAOSScope<E extends HTMLElement = HTMLElement>(
215
- options?: Partial<AnimationOptions>,
216
- ): { containerRef: React.RefObject<E> };
217
- ```
218
-
219
- **Example:**
220
-
221
- ```tsx
222
- "use client";
223
-
224
- import { useAOSScope } from "react-gsap-aos/client";
225
-
226
- export default function Demo() {
227
- const { containerRef } = useAOSScope<HTMLDivElement>({
228
- easing: "bounce.out",
229
- duration: 800,
230
- });
231
-
232
- return (
233
- <div ref={containerRef} className="overflow-hidden">
234
- <div data-aos="fade-up">Animated content</div>
235
- </div>
236
- );
237
- }
238
- ```
239
-
240
- ⚠️ **Important**:
241
-
242
- - Do not nest `useAOSScope` calls
243
- - Use in client components only (add `"use client"` directive)
244
- - Avoid placing in `app/layout.tsx` for proper cleanup
245
-
246
- **Parallel Usage:**
247
-
248
- ```tsx
249
- function Demo() {
250
- return (
251
- <div>
252
- <Section1 />
253
- <Section2 />
254
- </div>
255
- );
256
- }
257
-
258
- function Section1() {
259
- const { containerRef } = useAOSScope<HTMLDivElement>();
260
- return <div ref={containerRef}>...</div>;
261
- }
262
-
263
- function Section2() {
264
- const { containerRef } = useAOSScope<HTMLDivElement>();
265
- return <div ref={containerRef}>...</div>;
266
- }
267
- ```
268
-
269
- ### toAOSProps
270
-
271
- Converts animation options to data attributes with type safety.
272
-
273
- ```tsx
274
- import { toAOSProps } from "react-gsap-aos";
275
-
276
- const props = toAOSProps({
277
- animation: "fade-up",
278
- duration: 600,
279
- easing: "power2.out",
280
- });
281
- // Returns: { "data-aos": "fade-up", "data-aos-duration": 600, ... }
282
- ```
283
-
284
- ### refreshScrollTrigger
285
-
286
- Manually refresh AOS animation positions, wrapper around [`ScrollTrigger.refresh`](<https://gsap.com/docs/v3/Plugins/ScrollTrigger/refresh()>).
287
-
288
- ```tsx
289
- import { refreshScrollTrigger } from "react-gsap-aos";
290
-
291
- // Call after dynamic DOM changes
292
- refreshScrollTrigger();
293
- ```
294
-
295
- **Example with Dynamic Content:**
296
-
297
- ```tsx
298
- "use client";
299
-
300
- import { useState, useEffect } from "react";
301
- import { AOSProvider, refreshAOS } from "react-gsap-aos/client";
302
-
303
- export default function DynamicList() {
304
- const [visible, setVisible] = useState(true);
305
- const [items, setItems] = useState([1, 2, 3]);
306
-
307
- useEffect(() => {
308
- // Refresh after visible change
309
- refreshAOS();
310
- }, [visible]);
311
-
312
- return (
313
- <AOSProvider className="overflow-hidden">
314
- <button onClick={() => setVisible((e) => !e)}>switch visible</button>
315
- // When visible changes, the layout changes.
316
- {visible ? <div className="h-80" /> : null}
317
- <div data-aos-container>
318
- <div key={item} data-aos="fade-up">
319
- Hello AOS
320
- </div>
321
- </div>
322
- </AOSProvider>
323
- );
324
- }
325
- ```
326
-
327
- ## Animation Options
328
-
329
- | Option | Type | Data Attribute | Default | Description |
330
- | ----------------- | ----------------- | --------------------------- | -------------- | ------------------------------ |
331
- | `animation` | `Animation` | `data-aos` | `undefined` | Animation type |
332
- | `offset` | `number` | `data-aos-offset` | `120` | Offset (px) from trigger point |
333
- | `delay` | `number` | `data-aos-delay` | `0` | Animation delay (ms) |
334
- | `duration` | `number` | `data-aos-duration` | `400` | Animation duration (ms) |
335
- | `easing` | `Easing` | `data-aos-easing` | `"none"` | Easing function |
336
- | `once` | `boolean` | `data-aos-once` | `false` | Animate only once |
337
- | `mirror` | `boolean` | `data-aos-mirror` | `false` | Reverse animation on scroll up |
338
- | `anchorPlacement` | `AnchorPlacement` | `data-aos-anchor-placement` | `"top-bottom"` | Trigger position |
339
- | `markers` | `boolean` | `data-aos-markers` | `false` | ScrollTrigger markers |
340
-
341
- ## Available Types
342
-
343
- ### Animation Types (34 total)
344
-
345
- **Fade Animations:**
346
-
347
- - `fade`, `fade-up`, `fade-down`, `fade-left`, `fade-right`
348
- - `fade-up-right`, `fade-up-left`, `fade-down-right`, `fade-down-left`
349
-
350
- **Flip Animations:**
351
-
352
- - `flip-up`, `flip-down`, `flip-left`, `flip-right`
353
-
354
- **Slide Animations:**
355
-
356
- - `slide-up`, `slide-down`, `slide-left`, `slide-right`
357
-
358
- **Zoom Animations:**
359
-
360
- - `zoom-in`, `zoom-in-up`, `zoom-in-down`, `zoom-in-left`, `zoom-in-right`
361
- - `zoom-out`, `zoom-out-up`, `zoom-out-down`, `zoom-out-left`, `zoom-out-right`
362
-
363
- ### Easing Types (17 total)
364
-
365
- - `none`
366
- - `power1`, `power1.in`, `power1.out`, `power1.inOut`
367
- - `power2`, `power2.in`, `power2.out`, `power2.inOut`
368
- - `power3`, `power3.in`, `power3.out`, `power3.inOut`
369
- - `power4`, `power4.in`, `power4.out`, `power4.inOut`
370
- - `back`, `back.in`, `back.out`, `back.inOut`
371
- - `bounce`, `bounce.in`, `bounce.out`, `bounce.inOut`
372
- - `circ`, `circ.in`, `circ.out`, `circ.inOut`
373
- - `elastic`, `elastic.in`, `elastic.out`, `elastic.inOut`
374
- - `expo`, `expo.in`, `expo.out`, `expo.inOut`
375
- - `sine`, `sine.in`, `sine.out`, `sine.inOut`
376
-
377
- ### Anchor Placement Types (9 total)
378
-
379
- Format: `[element-position]-[viewport-position]`
380
-
381
- - `top-bottom`, `top-center`, `top-top`
382
- - `center-bottom`, `center-center`, `center-top`
383
- - `bottom-bottom`, `bottom-center`, `bottom-top`
3
+ [English](README.en.md) | [中文文檔](README.zh-TW.md)
package/README.zh-TW.md CHANGED
@@ -1,13 +1,13 @@
1
1
  # react-gsap-aos
2
2
 
3
- [English](README.md) | 中文文檔
3
+ [English](README.en.md) | 中文文檔
4
4
 
5
5
  輕量的 GSAP + ScrollTrigger 整合,用法類似 AOS,專為 React / Next.js 設計。
6
6
 
7
7
  [![npm version](https://img.shields.io/npm/v/react-gsap-aos.svg)](https://www.npmjs.com/package/react-gsap-aos)
8
8
  [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT)
9
9
 
10
- [線上展示](https://react-gsap-aos-nextjs.vercel.app) | [GitHub](https://github.com/GaiaYang/react-gsap-aos)
10
+ [線上展示](https://react-gsap-aos-nextjs.vercel.app)
11
11
 
12
12
  ## 什麼是 react-gsap-aos?
13
13
 
@@ -159,7 +159,7 @@ import { toAOSProps } from "react-gsap-aos";
159
159
  </AOSProvider>
160
160
  ```
161
161
 
162
- 支援巢狀容器:
162
+ ⚠️ **不建議**使用巢狀容器:
163
163
 
164
164
  ```tsx
165
165
  <div data-aos-container>
@@ -171,6 +171,8 @@ import { toAOSProps } from "react-gsap-aos";
171
171
  </div>
172
172
  ```
173
173
 
174
+ 巢狀容器會增加動畫初始化與 ScrollTrigger 刷新的複雜度。雖然仍可註冊動畫,但使用者需自行確保在適當時機呼叫 `ScrollTrigger.refresh()`。
175
+
174
176
  ## API 參考
175
177
 
176
178
  ### AOSProvider
@@ -296,7 +298,7 @@ refreshScrollTrigger();
296
298
  "use client";
297
299
 
298
300
  import { useState, useEffect } from "react";
299
- import { AOSProvider, refreshAOS } from "react-gsap-aos/client";
301
+ import { AOSProvider, refreshScrollTrigger } from "react-gsap-aos/client";
300
302
 
301
303
  export default function DynamicList() {
302
304
  const [visible, setVisible] = useState(true);
@@ -304,7 +306,7 @@ export default function DynamicList() {
304
306
 
305
307
  useEffect(() => {
306
308
  // 佈局變更後刷新
307
- refreshAOS();
309
+ refreshScrollTrigger();
308
310
  }, [visible]);
309
311
 
310
312
  return (
package/dist/client.d.mts CHANGED
@@ -2,6 +2,7 @@ import * as react from 'react';
2
2
  import { ComponentPropsWithoutRef } from 'react';
3
3
  import { A as AnimationOptions } from './types-CQ3qrMsE.mjs';
4
4
 
5
+ /** AOS hook 選項 */
5
6
  type UseAOSScopeOptions = Partial<AnimationOptions>;
6
7
  /**
7
8
  * 綁定 AOS 動畫範圍
package/dist/client.d.ts CHANGED
@@ -2,6 +2,7 @@ import * as react from 'react';
2
2
  import { ComponentPropsWithoutRef } from 'react';
3
3
  import { A as AnimationOptions } from './types-CQ3qrMsE.js';
4
4
 
5
+ /** AOS hook 選項 */
5
6
  type UseAOSScopeOptions = Partial<AnimationOptions>;
6
7
  /**
7
8
  * 綁定 AOS 動畫範圍
package/dist/client.js CHANGED
@@ -256,65 +256,42 @@ function verifyEnum(list, value) {
256
256
  }
257
257
 
258
258
  // src/animation/utils/createTweenVars.ts
259
- function translate3d(x, y, z) {
260
- return { x, y, z };
259
+ function perspective(transformPerspective) {
260
+ return { transformPerspective };
261
261
  }
262
- function rotateY(y) {
263
- return { rotateY: y };
262
+ function rotateX(rotationX) {
263
+ return { rotationX };
264
264
  }
265
- function rotateX(x) {
266
- return { rotateX: x };
265
+ function rotateY(rotationY) {
266
+ return { rotationY };
267
267
  }
268
- function scale(x, y) {
269
- return typeof y === "number" ? {
270
- scaleX: x,
271
- scaleY: y
272
- } : {
273
- scale: x
274
- };
268
+ function scale(scaleX, scaleY) {
269
+ return scaleY !== void 0 ? { scaleX, scaleY } : { scale: scaleX };
275
270
  }
276
- function perspective(value) {
277
- return {
278
- transformPerspective: value
279
- };
271
+ function translate3d(x, y, z) {
272
+ return { x, y, z };
273
+ }
274
+ function translate3dPercent(xPercent, yPercent, z) {
275
+ return { xPercent, yPercent, z };
280
276
  }
281
277
 
282
278
  // src/animation/definitions.ts
283
279
  var DISTANCE = 100;
284
280
  var presets = {
285
281
  fade: {
286
- from: {
287
- opacity: 0,
288
- transitionProperty: "opacity, transform"
289
- },
290
- to: {
291
- opacity: 1,
292
- transform: "none"
293
- }
282
+ from: { autoAlpha: 0 },
283
+ to: __spreadValues({ autoAlpha: 1 }, translate3d(0, 0, 0))
294
284
  },
295
285
  zoom: {
296
- from: {
297
- opacity: 0,
298
- transitionProperty: "opacity, transform"
299
- },
300
- to: __spreadValues(__spreadValues({
301
- opacity: 1
302
- }, translate3d(0, 0, 0)), scale(1))
286
+ from: { opacity: 0 },
287
+ to: __spreadValues(__spreadValues({ opacity: 1 }, translate3d(0, 0, 0)), scale(1))
303
288
  },
304
289
  slide: {
305
- from: {
306
- visibility: "hidden",
307
- transitionProperty: "transform"
308
- },
309
- to: __spreadValues({
310
- visibility: "visible"
311
- }, translate3d(0, 0, 0))
290
+ from: { visibility: "hidden" },
291
+ to: __spreadValues({ visibility: "visible" }, translate3dPercent(0, 0, 0))
312
292
  },
313
293
  flip: {
314
- from: {
315
- backfaceVisibility: "hidden",
316
- transitionProperty: "transform"
317
- },
294
+ from: { backfaceVisibility: "hidden" },
318
295
  to: {}
319
296
  }
320
297
  };
@@ -413,28 +390,28 @@ var definitions = {
413
390
  slideUp: {
414
391
  preset: presets.slide,
415
392
  vars: {
416
- from: translate3d(0, "100%", 0),
393
+ from: translate3dPercent(0, 100, 0),
417
394
  to: {}
418
395
  }
419
396
  },
420
397
  slideDown: {
421
398
  preset: presets.slide,
422
399
  vars: {
423
- from: translate3d(0, "-100%", 0),
400
+ from: translate3dPercent(0, -100, 0),
424
401
  to: {}
425
402
  }
426
403
  },
427
404
  slideLeft: {
428
405
  preset: presets.slide,
429
406
  vars: {
430
- from: translate3d("100%", 0, 0),
407
+ from: translate3dPercent(100, 0, 0),
431
408
  to: {}
432
409
  }
433
410
  },
434
411
  slideRight: {
435
412
  preset: presets.slide,
436
413
  vars: {
437
- from: translate3d("-100%", 0, 0),
414
+ from: translate3dPercent(-100, 0, 0),
438
415
  to: {}
439
416
  }
440
417
  },
@@ -514,7 +491,6 @@ function resolveToggleActions(once, mirror) {
514
491
  }
515
492
  var UNIT_MS = 1e3;
516
493
  function createScrollTriggerTween(element, preset, vars, options) {
517
- const { from, to } = vars;
518
494
  const { parentElement } = element;
519
495
  const {
520
496
  offset,
@@ -528,8 +504,8 @@ function createScrollTriggerTween(element, preset, vars, options) {
528
504
  } = mergeOptions(options);
529
505
  return import_gsap.default.fromTo(
530
506
  element,
531
- __spreadValues(__spreadValues({}, preset.from), from),
532
- __spreadProps(__spreadValues(__spreadValues({}, preset.to), to), {
507
+ __spreadValues(__spreadValues({}, preset.from), vars.from),
508
+ __spreadProps(__spreadValues(__spreadValues({}, preset.to), vars.to), {
533
509
  ease: easing,
534
510
  duration: duration / UNIT_MS,
535
511
  delay: delay / UNIT_MS,
@@ -596,6 +572,8 @@ function createAnimation(element, options) {
596
572
 
597
573
  // src/hooks/useAOSScope.ts
598
574
  import_gsap2.default.registerPlugin(import_react2.useGSAP, import_ScrollTrigger.ScrollTrigger);
575
+ var AOS_QUALIFIED_NAME = "data-aos";
576
+ var AOS_SELECTORS = `[${AOS_QUALIFIED_NAME}]`;
599
577
  var AOS_ATTRIBUTE_KEYS = [
600
578
  "data-aos",
601
579
  "data-aos-offset",
@@ -607,8 +585,6 @@ var AOS_ATTRIBUTE_KEYS = [
607
585
  "data-aos-anchor-placement",
608
586
  "data-aos-markers"
609
587
  ];
610
- var AOS_QUALIFIED_NAME = "data-aos";
611
- var AOS_SELECTORS = `[${AOS_QUALIFIED_NAME}]`;
612
588
  function useAOSScope(options) {
613
589
  const containerRef = (0, import_react.useRef)(null);
614
590
  const observerRef = (0, import_react.useRef)(null);
@@ -616,7 +592,7 @@ function useAOSScope(options) {
616
592
  /* @__PURE__ */ new WeakMap()
617
593
  );
618
594
  const currentOptionsRef = (0, import_react.useRef)(options);
619
- const rafIdRef = (0, import_react.useRef)(0);
595
+ const refreshRafIdRef = (0, import_react.useRef)(0);
620
596
  const shouldRefreshRef = (0, import_react.useRef)(false);
621
597
  (0, import_react.useLayoutEffect)(() => {
622
598
  currentOptionsRef.current = options;
@@ -624,10 +600,11 @@ function useAOSScope(options) {
624
600
  (0, import_react2.useGSAP)(
625
601
  (_, contextSafe) => {
626
602
  if (!containerRef.current || !contextSafe) return;
603
+ const safeCreateAnimation = contextSafe(createAnimation);
627
604
  const addAnimation = (element) => {
628
605
  const elementAnimations = elementAnimationsRef.current;
629
606
  if (elementAnimations.has(element)) return;
630
- const newAnimation = contextSafe(createAnimation)(
607
+ const newAnimation = safeCreateAnimation(
631
608
  element,
632
609
  currentOptionsRef.current
633
610
  );
@@ -638,7 +615,7 @@ function useAOSScope(options) {
638
615
  const elementAnimations = elementAnimationsRef.current;
639
616
  const animation = elementAnimations.get(element);
640
617
  if (!animation) return;
641
- animation.revert();
618
+ animation.revert().kill();
642
619
  elementAnimations.delete(element);
643
620
  };
644
621
  const updateAnimation = (element) => {
@@ -651,12 +628,19 @@ function useAOSScope(options) {
651
628
  const updatedElements = /* @__PURE__ */ new Set();
652
629
  for (const mutation of mutations) {
653
630
  const { type, target, addedNodes, removedNodes } = mutation;
654
- if (type === "attributes" && target instanceof HTMLElement) {
655
- if (!target.hasAttribute(AOS_QUALIFIED_NAME)) continue;
656
- updatedElements.add(target);
657
- } else if (type === "childList") {
658
- collectElements(addedNodes, addedElements);
659
- collectElements(removedNodes, removedElements);
631
+ switch (type) {
632
+ case "attributes":
633
+ if (target instanceof HTMLElement) {
634
+ if (!target.hasAttribute(AOS_QUALIFIED_NAME)) break;
635
+ updatedElements.add(target);
636
+ }
637
+ break;
638
+ case "childList":
639
+ collectElements(addedNodes, addedElements);
640
+ collectElements(removedNodes, removedElements);
641
+ break;
642
+ default:
643
+ break;
660
644
  }
661
645
  }
662
646
  for (const element of removedElements) removeAnimation(element);
@@ -667,16 +651,15 @@ function useAOSScope(options) {
667
651
  }
668
652
  };
669
653
  const updateScrollTrigger = () => {
670
- if (!shouldRefreshRef.current || rafIdRef.current) return;
671
- rafIdRef.current = requestAnimationFrame(() => {
654
+ if (!shouldRefreshRef.current || refreshRafIdRef.current) return;
655
+ refreshRafIdRef.current = requestAnimationFrame(() => {
672
656
  import_ScrollTrigger.ScrollTrigger.refresh();
673
657
  shouldRefreshRef.current = false;
674
- rafIdRef.current = 0;
658
+ refreshRafIdRef.current = 0;
675
659
  });
676
660
  };
677
- for (const element of import_gsap2.default.utils.toArray(
678
- AOS_SELECTORS,
679
- containerRef.current
661
+ for (const element of containerRef.current.querySelectorAll(
662
+ AOS_SELECTORS
680
663
  )) {
681
664
  addAnimation(element);
682
665
  }