gsap-nuxt-module 1.1.8 → 1.1.9
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 +26 -2
- package/dist/module.json +1 -1
- package/dist/runtime/composables/createGsapComposable.d.ts +45 -12
- package/dist/runtime/composables/createGsapComposable.js +27 -9
- package/dist/runtime/create-gsap-composable.d.ts +3 -2
- package/dist/runtime/gsap-plugins.d.ts +4 -0
- package/dist/runtime/gsap-plugins.js +3 -4
- package/package.json +1 -1
- package/dist/runtime/gsap-loaders.d.ts +0 -3
- package/dist/runtime/gsap-loaders.js +0 -7
package/README.md
CHANGED
|
@@ -120,6 +120,31 @@ onMounted(() => {
|
|
|
120
120
|
</script>
|
|
121
121
|
```
|
|
122
122
|
|
|
123
|
+
### Context form (recommended)
|
|
124
|
+
|
|
125
|
+
Pass a `setup` function to wrap animations in a [`gsap.context()`](https://gsap.com/docs/v3/GSAP/gsap.context/).
|
|
126
|
+
The context reverts automatically when the component unmounts — no `onUnmounted` boilerplate needed.
|
|
127
|
+
During page navigation, cleanup is deferred until after the leave transition finishes.
|
|
128
|
+
|
|
129
|
+
```ts
|
|
130
|
+
<script setup lang="ts">
|
|
131
|
+
const containerRef = ref<HTMLElement | null>(null)
|
|
132
|
+
|
|
133
|
+
useGsap(() => {
|
|
134
|
+
gsap.from('.box', { opacity: 0, y: 30, duration: 0.6 })
|
|
135
|
+
}, { scope: containerRef })
|
|
136
|
+
</script>
|
|
137
|
+
|
|
138
|
+
<template>
|
|
139
|
+
<div ref="containerRef">
|
|
140
|
+
<div class="box">I animate in safely</div>
|
|
141
|
+
</div>
|
|
142
|
+
</template>
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
Returns `{ contextSafe }` for wrapping event handlers that add animations after mount.
|
|
146
|
+
See the [full docs](https://lucaargentieri.github.io/gsap-nuxt-module/composables/use-gsap) for all options.
|
|
147
|
+
|
|
123
148
|
## Available composables
|
|
124
149
|
|
|
125
150
|
| Composable | Plugin | `nuxt.config.ts` key |
|
|
@@ -154,8 +179,7 @@ export default defineNuxtConfig({
|
|
|
154
179
|
|
|
155
180
|
## Cleanup
|
|
156
181
|
|
|
157
|
-
|
|
158
|
-
Use `onUnmounted` to prevent memory leaks.
|
|
182
|
+
When using `useGsap()` with a setup function, cleanup is automatic. When using the zero-arg form, use `onUnmounted` to prevent memory leaks.
|
|
159
183
|
|
|
160
184
|
Plugin registration is handled once by the module at app startup — never call `gsap.registerPlugin()` manually.
|
|
161
185
|
In components, clean up only the instances your component created (tweens, timelines, ScrollTrigger instances, Draggable instances, etc.).
|
package/dist/module.json
CHANGED
|
@@ -1,10 +1,43 @@
|
|
|
1
1
|
import { gsap } from 'gsap';
|
|
2
2
|
import type { ComputedRef, Ref, WatchSource } from 'vue';
|
|
3
|
-
|
|
3
|
+
/**
|
|
4
|
+
* Wraps an event handler so it runs inside the active GSAP context.
|
|
5
|
+
*
|
|
6
|
+
* **Note:** return values are discarded when a context exists — `ctx.add()`
|
|
7
|
+
* returns `void`. Use `contextSafe` only for void side-effect handlers
|
|
8
|
+
* (DOM events, pointer callbacks, etc.).
|
|
9
|
+
*/
|
|
10
|
+
type ContextSafeFn = <F extends (...args: unknown[]) => void>(fn: F) => F;
|
|
4
11
|
export interface UseGsapOptions {
|
|
5
12
|
scope?: Ref<HTMLElement | null> | ComputedRef<HTMLElement | null>;
|
|
6
13
|
dependencies?: WatchSource | WatchSource[];
|
|
7
14
|
revertOnUpdate?: boolean;
|
|
15
|
+
/**
|
|
16
|
+
* When to revert the GSAP context during page navigation.
|
|
17
|
+
*
|
|
18
|
+
* @deprecated This option has no behavioral effect. Both `'unmount'` and
|
|
19
|
+
* `'route-leave'` produce identical behavior: the GSAP context is reverted
|
|
20
|
+
* after the leave transition finishes, when the component unmounts via
|
|
21
|
+
* `onScopeDispose`. Kept for backward compatibility only.
|
|
22
|
+
*
|
|
23
|
+
* - `'unmount'` (default) — reverts after the leave transition finishes,
|
|
24
|
+
* when the component is unmounted via `onScopeDispose`.
|
|
25
|
+
* - `'route-leave'` — semantically identical to `'unmount'`.
|
|
26
|
+
*
|
|
27
|
+
* In both cases, animations continue to play during the leave transition,
|
|
28
|
+
* then are reverted once the component unmounts.
|
|
29
|
+
*
|
|
30
|
+
* **Note:** if a `router.beforeEach` guard rejects navigation *after*
|
|
31
|
+
* `onBeforeRouteLeave` is registered, the `onBeforeRouteLeave` hook will still
|
|
32
|
+
* have fired and set `isLeavingViaRoute` to `true`, but the component will not unmount.
|
|
33
|
+
* The context remains active and animations continue until the next successful
|
|
34
|
+
* navigation.
|
|
35
|
+
*
|
|
36
|
+
* @example
|
|
37
|
+
* // Continuous animation that should play through the page-leave transition
|
|
38
|
+
* useGsap(() => { ... }, { cleanupOn: 'route-leave' })
|
|
39
|
+
*/
|
|
40
|
+
cleanupOn?: 'unmount' | 'route-leave';
|
|
8
41
|
}
|
|
9
42
|
/**
|
|
10
43
|
* Zero-argument overload — returns the raw GSAP instance.
|
|
@@ -92,7 +125,7 @@ export declare const useScrollTrigger: () => {
|
|
|
92
125
|
snapDirectional(incrementOrArray: number | number[]): ScrollTrigger.SnapDirectionalFunc;
|
|
93
126
|
sort(func?: Function): ScrollTrigger[];
|
|
94
127
|
update(): void;
|
|
95
|
-
}
|
|
128
|
+
};
|
|
96
129
|
export declare const useScrollSmoother: () => {
|
|
97
130
|
new (vars: ScrollSmoother.Vars): {
|
|
98
131
|
readonly scrollTrigger: ScrollTrigger;
|
|
@@ -120,7 +153,7 @@ export declare const useScrollSmoother: () => {
|
|
|
120
153
|
create(vars: ScrollSmoother.Vars): ScrollSmoother;
|
|
121
154
|
get(): ScrollSmoother | undefined;
|
|
122
155
|
refresh(safe?: boolean): void;
|
|
123
|
-
}
|
|
156
|
+
};
|
|
124
157
|
export declare const useSplitText: () => {
|
|
125
158
|
new (target: gsap.DOMTarget, vars?: SplitText.Vars): {
|
|
126
159
|
readonly chars: Element[];
|
|
@@ -134,14 +167,14 @@ export declare const useSplitText: () => {
|
|
|
134
167
|
split(vars: SplitText.Vars): SplitText;
|
|
135
168
|
};
|
|
136
169
|
create(target: gsap.DOMTarget, vars?: SplitText.Vars): SplitText;
|
|
137
|
-
}
|
|
170
|
+
};
|
|
138
171
|
export declare const useMotionPathHelper: () => {
|
|
139
172
|
new (target: gsap.DOMTarget, vars?: MotionPathHelper.Vars): {
|
|
140
173
|
kill(): void;
|
|
141
174
|
};
|
|
142
175
|
create(target: gsap.DOMTarget, vars?: MotionPathHelper.Vars): MotionPathHelper;
|
|
143
176
|
editPath(target: gsap.DOMTarget, vars?: MotionPathHelper.EditPathVars): MotionPathHelper;
|
|
144
|
-
}
|
|
177
|
+
};
|
|
145
178
|
export declare const useDraggable: () => {
|
|
146
179
|
new (target: gsap.DOMTarget, vars?: Draggable.Vars): {
|
|
147
180
|
readonly autoScroll: number;
|
|
@@ -194,7 +227,7 @@ export declare const useDraggable: () => {
|
|
|
194
227
|
get(target: gsap.DOMTarget): Draggable;
|
|
195
228
|
hitTest(testObject1: Draggable.TestObject, testObject2: Draggable.TestObject, threshold?: number | string): boolean;
|
|
196
229
|
timeSinceDrag(): number;
|
|
197
|
-
}
|
|
230
|
+
};
|
|
198
231
|
export declare const useFlip: () => {
|
|
199
232
|
new (): {};
|
|
200
233
|
readonly version: string;
|
|
@@ -212,7 +245,7 @@ export declare const useFlip: () => {
|
|
|
212
245
|
register(core: typeof globalThis.gsap): void;
|
|
213
246
|
ElementState: typeof Flip.ElementState;
|
|
214
247
|
FlipState: typeof Flip.FlipState;
|
|
215
|
-
}
|
|
248
|
+
};
|
|
216
249
|
export declare const useObserver: () => {
|
|
217
250
|
new (): {
|
|
218
251
|
readonly deltaX: number;
|
|
@@ -244,14 +277,14 @@ export declare const useObserver: () => {
|
|
|
244
277
|
create(vars: Observer.ObserverVars): Observer;
|
|
245
278
|
getAll(): Observer[];
|
|
246
279
|
getById(id: string): Observer | undefined;
|
|
247
|
-
}
|
|
280
|
+
};
|
|
248
281
|
export declare const useGSDevTools: () => {
|
|
249
282
|
new (target: gsap.DOMTarget, vars?: GSDevTools.Vars): {
|
|
250
283
|
kill(): void;
|
|
251
284
|
};
|
|
252
285
|
create(vars?: GSDevTools.Vars): GSDevTools;
|
|
253
286
|
getById(id: string): GSDevTools | null;
|
|
254
|
-
}
|
|
287
|
+
};
|
|
255
288
|
export declare const useCustomEase: () => {
|
|
256
289
|
new (id: string, data?: string | number[], config?: CustomEaseConfig): {
|
|
257
290
|
id: string;
|
|
@@ -265,19 +298,19 @@ export declare const useCustomEase: () => {
|
|
|
265
298
|
register(core: object): void;
|
|
266
299
|
get(id: string): EaseFunction;
|
|
267
300
|
getSVGData(ease: CustomEase | EaseFunction | string, config?: CustomEaseConfig): string;
|
|
268
|
-
}
|
|
301
|
+
};
|
|
269
302
|
export declare const useCustomWiggle: () => {
|
|
270
303
|
new (id: string, vars?: CustomWiggleVars): {
|
|
271
304
|
ease: EaseFunction;
|
|
272
305
|
};
|
|
273
306
|
create(id: string, vars?: CustomWiggleVars): EaseFunction;
|
|
274
307
|
register(core: object): void;
|
|
275
|
-
}
|
|
308
|
+
};
|
|
276
309
|
export declare const useCustomBounce: () => {
|
|
277
310
|
new (id: string, vars?: CustomBounceVars): {
|
|
278
311
|
ease: EaseFunction;
|
|
279
312
|
};
|
|
280
313
|
create(id: string, vars?: CustomBounceVars): EaseFunction;
|
|
281
314
|
register(core: object): void;
|
|
282
|
-
}
|
|
315
|
+
};
|
|
283
316
|
export {};
|
|
@@ -1,5 +1,7 @@
|
|
|
1
|
+
import { useNuxtApp } from "#app";
|
|
1
2
|
import { gsap } from "gsap";
|
|
2
3
|
import { onMounted, onScopeDispose, watch } from "vue";
|
|
4
|
+
import { onBeforeRouteLeave } from "vue-router";
|
|
3
5
|
import { createGsapComposable } from "../create-gsap-composable.js";
|
|
4
6
|
export function useGsap(setup, options) {
|
|
5
7
|
if (!setup) return gsap;
|
|
@@ -7,31 +9,47 @@ export function useGsap(setup, options) {
|
|
|
7
9
|
return { contextSafe: (fn) => fn };
|
|
8
10
|
}
|
|
9
11
|
let ctx = null;
|
|
12
|
+
let isLeavingViaRoute = false;
|
|
10
13
|
const runSetup = () => {
|
|
11
14
|
const scope = options?.scope?.value ?? void 0;
|
|
12
15
|
ctx = gsap.context(setup, scope);
|
|
13
16
|
};
|
|
17
|
+
onBeforeRouteLeave(() => {
|
|
18
|
+
isLeavingViaRoute = true;
|
|
19
|
+
const nuxtApp = useNuxtApp();
|
|
20
|
+
nuxtApp.hooks.hookOnce("page:transition:finish", () => {
|
|
21
|
+
ctx?.revert();
|
|
22
|
+
ctx = null;
|
|
23
|
+
});
|
|
24
|
+
});
|
|
14
25
|
onMounted(() => {
|
|
15
26
|
runSetup();
|
|
16
27
|
});
|
|
17
28
|
if (options?.dependencies !== void 0) {
|
|
18
29
|
const deps = Array.isArray(options.dependencies) ? options.dependencies : [options.dependencies];
|
|
19
|
-
watch(
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
30
|
+
watch(
|
|
31
|
+
deps,
|
|
32
|
+
() => {
|
|
33
|
+
if (options.revertOnUpdate === false) return;
|
|
34
|
+
ctx?.revert();
|
|
35
|
+
runSetup();
|
|
36
|
+
},
|
|
37
|
+
{ flush: "post" }
|
|
38
|
+
);
|
|
24
39
|
}
|
|
25
40
|
onScopeDispose(() => {
|
|
26
|
-
|
|
27
|
-
|
|
41
|
+
if (!isLeavingViaRoute) {
|
|
42
|
+
ctx?.revert();
|
|
43
|
+
ctx = null;
|
|
44
|
+
}
|
|
28
45
|
});
|
|
29
46
|
const contextSafe = (fn) => {
|
|
30
47
|
return ((...args) => {
|
|
31
48
|
if (ctx) {
|
|
32
|
-
|
|
49
|
+
ctx.add(() => fn(...args));
|
|
50
|
+
} else {
|
|
51
|
+
fn(...args);
|
|
33
52
|
}
|
|
34
|
-
return fn(...args);
|
|
35
53
|
});
|
|
36
54
|
};
|
|
37
55
|
return { contextSafe };
|
|
@@ -2,7 +2,8 @@
|
|
|
2
2
|
* Factory that creates a composable returning a registered GSAP plugin.
|
|
3
3
|
*
|
|
4
4
|
* The returned composable reads the plugin from `nuxtApp` at call time.
|
|
5
|
-
*
|
|
5
|
+
* This is a client-only composable — it is safe to call on the server but
|
|
6
|
+
* will return an inert value (the plugin is never registered server-side).
|
|
6
7
|
* Throws on the client if the plugin was not enabled in `nuxt.config.ts`.
|
|
7
8
|
*
|
|
8
9
|
* **Cleanup is the caller's responsibility.**
|
|
@@ -12,4 +13,4 @@
|
|
|
12
13
|
* @param pluginName - Name of the GSAP plugin as registered in nuxtApp.
|
|
13
14
|
* @param fallbackMessage - Optional custom error message for missing plugin.
|
|
14
15
|
*/
|
|
15
|
-
export declare function createGsapComposable<T>(pluginName: string, fallbackMessage?: string): () => T
|
|
16
|
+
export declare function createGsapComposable<T>(pluginName: string, fallbackMessage?: string): () => NonNullable<T>;
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { loadDraggable, loadFlip, loadObserver } from "./gsap-loaders.js";
|
|
2
1
|
export const gsapPlugins = {
|
|
3
2
|
// Scroll Plugins
|
|
4
3
|
ScrollTrigger: () => import("gsap/ScrollTrigger").then((mod) => mod.ScrollTrigger),
|
|
@@ -14,10 +13,10 @@ export const gsapPlugins = {
|
|
|
14
13
|
MotionPathPlugin: () => import("gsap/MotionPathPlugin").then((mod) => mod.MotionPathPlugin),
|
|
15
14
|
MotionPathHelper: () => import("gsap/MotionPathHelper").then((mod) => mod.MotionPathHelper),
|
|
16
15
|
// UI Plugins
|
|
17
|
-
Flip: () =>
|
|
18
|
-
Draggable: () =>
|
|
16
|
+
Flip: () => import("gsap/Flip").then((mod) => mod.Flip),
|
|
17
|
+
Draggable: () => import("gsap/Draggable").then((mod) => mod.Draggable),
|
|
19
18
|
InertiaPlugin: () => import("gsap/InertiaPlugin").then((mod) => mod.InertiaPlugin),
|
|
20
|
-
Observer: () =>
|
|
19
|
+
Observer: () => import("gsap/Observer").then((mod) => mod.Observer),
|
|
21
20
|
// Other Plugins
|
|
22
21
|
PixiPlugin: () => import("gsap/PixiPlugin").then((mod) => mod.PixiPlugin),
|
|
23
22
|
EaselPlugin: () => import("gsap/EaselPlugin").then((mod) => mod.EaselPlugin),
|
package/package.json
CHANGED