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.en.md +385 -0
- package/README.md +1 -381
- package/README.zh-TW.md +7 -5
- package/dist/client.d.mts +1 -0
- package/dist/client.d.ts +1 -0
- package/dist/client.js +50 -67
- package/dist/client.js.map +1 -1
- package/dist/client.mjs +50 -67
- package/dist/client.mjs.map +1 -1
- package/dist/index.d.mts +10 -2
- package/dist/index.d.ts +10 -2
- package/dist/index.js.map +1 -1
- package/dist/index.mjs.map +1 -1
- package/package.json +4 -4
package/README.md
CHANGED
|
@@ -1,383 +1,3 @@
|
|
|
1
1
|
# react-gsap-aos
|
|
2
2
|
|
|
3
|
-
[中文文檔](README.zh-TW.md)
|
|
4
|
-
|
|
5
|
-
A lightweight GSAP + ScrollTrigger integration with an AOS-like API, specifically designed for React and Next.js applications.
|
|
6
|
-
|
|
7
|
-
[](https://www.npmjs.com/package/react-gsap-aos)
|
|
8
|
-
[](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
|
[](https://www.npmjs.com/package/react-gsap-aos)
|
|
8
8
|
[](https://opensource.org/licenses/MIT)
|
|
9
9
|
|
|
10
|
-
[線上展示](https://react-gsap-aos-nextjs.vercel.app)
|
|
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,
|
|
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
|
-
|
|
309
|
+
refreshScrollTrigger();
|
|
308
310
|
}, [visible]);
|
|
309
311
|
|
|
310
312
|
return (
|
package/dist/client.d.mts
CHANGED
package/dist/client.d.ts
CHANGED
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
|
|
260
|
-
return {
|
|
259
|
+
function perspective(transformPerspective) {
|
|
260
|
+
return { transformPerspective };
|
|
261
261
|
}
|
|
262
|
-
function
|
|
263
|
-
return {
|
|
262
|
+
function rotateX(rotationX) {
|
|
263
|
+
return { rotationX };
|
|
264
264
|
}
|
|
265
|
-
function
|
|
266
|
-
return {
|
|
265
|
+
function rotateY(rotationY) {
|
|
266
|
+
return { rotationY };
|
|
267
267
|
}
|
|
268
|
-
function scale(
|
|
269
|
-
return
|
|
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
|
|
277
|
-
return {
|
|
278
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
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
|
|
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 =
|
|
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
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
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 ||
|
|
671
|
-
|
|
654
|
+
if (!shouldRefreshRef.current || refreshRafIdRef.current) return;
|
|
655
|
+
refreshRafIdRef.current = requestAnimationFrame(() => {
|
|
672
656
|
import_ScrollTrigger.ScrollTrigger.refresh();
|
|
673
657
|
shouldRefreshRef.current = false;
|
|
674
|
-
|
|
658
|
+
refreshRafIdRef.current = 0;
|
|
675
659
|
});
|
|
676
660
|
};
|
|
677
|
-
for (const element of
|
|
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
|
}
|