gsap-nuxt-module 1.1.7 → 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 +30 -5
- package/dist/module.json +1 -1
- package/dist/runtime/composables/createGsapComposable.d.ts +70 -14
- package/dist/runtime/composables/createGsapComposable.js +53 -2
- 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 +2 -1
- package/dist/runtime/gsap-loaders.d.ts +0 -3
- package/dist/runtime/gsap-loaders.js +0 -7
package/README.md
CHANGED
|
@@ -18,7 +18,8 @@ Find and replace all on all files (CMD+SHIFT+F):
|
|
|
18
18
|
|
|
19
19
|
**Enhance your Nuxt application with powerful animations and transitions using GSAP!**
|
|
20
20
|
|
|
21
|
-
- [
|
|
21
|
+
- [📖 Documentation](https://lucaargentieri.github.io/gsap-nuxt-module/)
|
|
22
|
+
- [🏀 Online playground](https://stackblitz.com/edit/gsap-nuxt-module?file=README.md)
|
|
22
23
|
- [📖 GSAP](https://gsap.com/)
|
|
23
24
|
|
|
24
25
|
## Features
|
|
@@ -119,6 +120,31 @@ onMounted(() => {
|
|
|
119
120
|
</script>
|
|
120
121
|
```
|
|
121
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
|
+
|
|
122
148
|
## Available composables
|
|
123
149
|
|
|
124
150
|
| Composable | Plugin | `nuxt.config.ts` key |
|
|
@@ -153,11 +179,10 @@ export default defineNuxtConfig({
|
|
|
153
179
|
|
|
154
180
|
## Cleanup
|
|
155
181
|
|
|
156
|
-
|
|
157
|
-
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.
|
|
158
183
|
|
|
159
|
-
|
|
160
|
-
In components, clean up only the instances created
|
|
184
|
+
Plugin registration is handled once by the module at app startup — never call `gsap.registerPlugin()` manually.
|
|
185
|
+
In components, clean up only the instances your component created (tweens, timelines, ScrollTrigger instances, Draggable instances, etc.).
|
|
161
186
|
|
|
162
187
|
**Simple plugin instance cleanup (`Draggable`):**
|
|
163
188
|
|
package/dist/module.json
CHANGED
|
@@ -1,15 +1,70 @@
|
|
|
1
|
+
import { gsap } from 'gsap';
|
|
2
|
+
import type { ComputedRef, Ref, WatchSource } from 'vue';
|
|
1
3
|
/**
|
|
2
|
-
*
|
|
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;
|
|
11
|
+
export interface UseGsapOptions {
|
|
12
|
+
scope?: Ref<HTMLElement | null> | ComputedRef<HTMLElement | null>;
|
|
13
|
+
dependencies?: WatchSource | WatchSource[];
|
|
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';
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Zero-argument overload — returns the raw GSAP instance.
|
|
3
44
|
*
|
|
4
45
|
* Use it to call `gsap.timeline()`, `gsap.to()`, `gsap.set()`,
|
|
5
46
|
* utility methods (`gsap.utils`, `gsap.ticker`), and more.
|
|
6
47
|
*
|
|
7
48
|
* **Cleanup is the caller's responsibility.**
|
|
8
|
-
* Use `gsap.context()` + `ctx.revert()` in `onUnmounted` to avoid memory leaks.
|
|
9
49
|
*
|
|
10
50
|
* @see https://gsap.com/docs/v3/GSAP/
|
|
11
51
|
*/
|
|
12
|
-
export declare function useGsap(): typeof
|
|
52
|
+
export declare function useGsap(): typeof gsap;
|
|
53
|
+
/**
|
|
54
|
+
* Setup-function overload — wraps `gsap.context()` with automatic revert.
|
|
55
|
+
*
|
|
56
|
+
* Animations declared inside `setup` are scoped to the optional `scope` element
|
|
57
|
+
* and are reverted automatically when the component unmounts (or the effect scope
|
|
58
|
+
* is disposed). Pass `dependencies` to re-run `setup` reactively.
|
|
59
|
+
*
|
|
60
|
+
* Returns `{ contextSafe }` — a wrapper for event handlers that need to add
|
|
61
|
+
* animations to the existing context after mount.
|
|
62
|
+
*
|
|
63
|
+
* @see https://gsap.com/docs/v3/GSAP/gsap.context()
|
|
64
|
+
*/
|
|
65
|
+
export declare function useGsap(setup: (ctx: gsap.Context) => void, options?: UseGsapOptions): {
|
|
66
|
+
contextSafe: ContextSafeFn;
|
|
67
|
+
};
|
|
13
68
|
export declare const useScrollTrigger: () => {
|
|
14
69
|
new (vars: ScrollTrigger.StaticVars, animation?: gsap.core.Animation): {
|
|
15
70
|
readonly animation?: gsap.core.Animation | undefined;
|
|
@@ -70,7 +125,7 @@ export declare const useScrollTrigger: () => {
|
|
|
70
125
|
snapDirectional(incrementOrArray: number | number[]): ScrollTrigger.SnapDirectionalFunc;
|
|
71
126
|
sort(func?: Function): ScrollTrigger[];
|
|
72
127
|
update(): void;
|
|
73
|
-
}
|
|
128
|
+
};
|
|
74
129
|
export declare const useScrollSmoother: () => {
|
|
75
130
|
new (vars: ScrollSmoother.Vars): {
|
|
76
131
|
readonly scrollTrigger: ScrollTrigger;
|
|
@@ -98,7 +153,7 @@ export declare const useScrollSmoother: () => {
|
|
|
98
153
|
create(vars: ScrollSmoother.Vars): ScrollSmoother;
|
|
99
154
|
get(): ScrollSmoother | undefined;
|
|
100
155
|
refresh(safe?: boolean): void;
|
|
101
|
-
}
|
|
156
|
+
};
|
|
102
157
|
export declare const useSplitText: () => {
|
|
103
158
|
new (target: gsap.DOMTarget, vars?: SplitText.Vars): {
|
|
104
159
|
readonly chars: Element[];
|
|
@@ -112,14 +167,14 @@ export declare const useSplitText: () => {
|
|
|
112
167
|
split(vars: SplitText.Vars): SplitText;
|
|
113
168
|
};
|
|
114
169
|
create(target: gsap.DOMTarget, vars?: SplitText.Vars): SplitText;
|
|
115
|
-
}
|
|
170
|
+
};
|
|
116
171
|
export declare const useMotionPathHelper: () => {
|
|
117
172
|
new (target: gsap.DOMTarget, vars?: MotionPathHelper.Vars): {
|
|
118
173
|
kill(): void;
|
|
119
174
|
};
|
|
120
175
|
create(target: gsap.DOMTarget, vars?: MotionPathHelper.Vars): MotionPathHelper;
|
|
121
176
|
editPath(target: gsap.DOMTarget, vars?: MotionPathHelper.EditPathVars): MotionPathHelper;
|
|
122
|
-
}
|
|
177
|
+
};
|
|
123
178
|
export declare const useDraggable: () => {
|
|
124
179
|
new (target: gsap.DOMTarget, vars?: Draggable.Vars): {
|
|
125
180
|
readonly autoScroll: number;
|
|
@@ -172,7 +227,7 @@ export declare const useDraggable: () => {
|
|
|
172
227
|
get(target: gsap.DOMTarget): Draggable;
|
|
173
228
|
hitTest(testObject1: Draggable.TestObject, testObject2: Draggable.TestObject, threshold?: number | string): boolean;
|
|
174
229
|
timeSinceDrag(): number;
|
|
175
|
-
}
|
|
230
|
+
};
|
|
176
231
|
export declare const useFlip: () => {
|
|
177
232
|
new (): {};
|
|
178
233
|
readonly version: string;
|
|
@@ -190,7 +245,7 @@ export declare const useFlip: () => {
|
|
|
190
245
|
register(core: typeof globalThis.gsap): void;
|
|
191
246
|
ElementState: typeof Flip.ElementState;
|
|
192
247
|
FlipState: typeof Flip.FlipState;
|
|
193
|
-
}
|
|
248
|
+
};
|
|
194
249
|
export declare const useObserver: () => {
|
|
195
250
|
new (): {
|
|
196
251
|
readonly deltaX: number;
|
|
@@ -222,14 +277,14 @@ export declare const useObserver: () => {
|
|
|
222
277
|
create(vars: Observer.ObserverVars): Observer;
|
|
223
278
|
getAll(): Observer[];
|
|
224
279
|
getById(id: string): Observer | undefined;
|
|
225
|
-
}
|
|
280
|
+
};
|
|
226
281
|
export declare const useGSDevTools: () => {
|
|
227
282
|
new (target: gsap.DOMTarget, vars?: GSDevTools.Vars): {
|
|
228
283
|
kill(): void;
|
|
229
284
|
};
|
|
230
285
|
create(vars?: GSDevTools.Vars): GSDevTools;
|
|
231
286
|
getById(id: string): GSDevTools | null;
|
|
232
|
-
}
|
|
287
|
+
};
|
|
233
288
|
export declare const useCustomEase: () => {
|
|
234
289
|
new (id: string, data?: string | number[], config?: CustomEaseConfig): {
|
|
235
290
|
id: string;
|
|
@@ -243,18 +298,19 @@ export declare const useCustomEase: () => {
|
|
|
243
298
|
register(core: object): void;
|
|
244
299
|
get(id: string): EaseFunction;
|
|
245
300
|
getSVGData(ease: CustomEase | EaseFunction | string, config?: CustomEaseConfig): string;
|
|
246
|
-
}
|
|
301
|
+
};
|
|
247
302
|
export declare const useCustomWiggle: () => {
|
|
248
303
|
new (id: string, vars?: CustomWiggleVars): {
|
|
249
304
|
ease: EaseFunction;
|
|
250
305
|
};
|
|
251
306
|
create(id: string, vars?: CustomWiggleVars): EaseFunction;
|
|
252
307
|
register(core: object): void;
|
|
253
|
-
}
|
|
308
|
+
};
|
|
254
309
|
export declare const useCustomBounce: () => {
|
|
255
310
|
new (id: string, vars?: CustomBounceVars): {
|
|
256
311
|
ease: EaseFunction;
|
|
257
312
|
};
|
|
258
313
|
create(id: string, vars?: CustomBounceVars): EaseFunction;
|
|
259
314
|
register(core: object): void;
|
|
260
|
-
}
|
|
315
|
+
};
|
|
316
|
+
export {};
|
|
@@ -1,7 +1,58 @@
|
|
|
1
|
+
import { useNuxtApp } from "#app";
|
|
1
2
|
import { gsap } from "gsap";
|
|
3
|
+
import { onMounted, onScopeDispose, watch } from "vue";
|
|
4
|
+
import { onBeforeRouteLeave } from "vue-router";
|
|
2
5
|
import { createGsapComposable } from "../create-gsap-composable.js";
|
|
3
|
-
export function useGsap() {
|
|
4
|
-
return gsap;
|
|
6
|
+
export function useGsap(setup, options) {
|
|
7
|
+
if (!setup) return gsap;
|
|
8
|
+
if (import.meta.server) {
|
|
9
|
+
return { contextSafe: (fn) => fn };
|
|
10
|
+
}
|
|
11
|
+
let ctx = null;
|
|
12
|
+
let isLeavingViaRoute = false;
|
|
13
|
+
const runSetup = () => {
|
|
14
|
+
const scope = options?.scope?.value ?? void 0;
|
|
15
|
+
ctx = gsap.context(setup, scope);
|
|
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
|
+
});
|
|
25
|
+
onMounted(() => {
|
|
26
|
+
runSetup();
|
|
27
|
+
});
|
|
28
|
+
if (options?.dependencies !== void 0) {
|
|
29
|
+
const deps = Array.isArray(options.dependencies) ? options.dependencies : [options.dependencies];
|
|
30
|
+
watch(
|
|
31
|
+
deps,
|
|
32
|
+
() => {
|
|
33
|
+
if (options.revertOnUpdate === false) return;
|
|
34
|
+
ctx?.revert();
|
|
35
|
+
runSetup();
|
|
36
|
+
},
|
|
37
|
+
{ flush: "post" }
|
|
38
|
+
);
|
|
39
|
+
}
|
|
40
|
+
onScopeDispose(() => {
|
|
41
|
+
if (!isLeavingViaRoute) {
|
|
42
|
+
ctx?.revert();
|
|
43
|
+
ctx = null;
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
const contextSafe = (fn) => {
|
|
47
|
+
return ((...args) => {
|
|
48
|
+
if (ctx) {
|
|
49
|
+
ctx.add(() => fn(...args));
|
|
50
|
+
} else {
|
|
51
|
+
fn(...args);
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
};
|
|
55
|
+
return { contextSafe };
|
|
5
56
|
}
|
|
6
57
|
export const useScrollTrigger = createGsapComposable("ScrollTrigger");
|
|
7
58
|
export const useScrollSmoother = createGsapComposable("ScrollSmoother");
|
|
@@ -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
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "gsap-nuxt-module",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.9",
|
|
4
4
|
"description": "GSAP integration for Nuxt.",
|
|
5
5
|
"repository": "LucaArgentieri/gsap-nuxt-module",
|
|
6
6
|
"author": "Luca Argentieri",
|
|
@@ -29,6 +29,7 @@
|
|
|
29
29
|
"dev:prepare": "nuxt-module-build build --stub && nuxt-module-build prepare && nuxi prepare playground",
|
|
30
30
|
"release": "npm run lint && npm run prepack && changelogen --release --patch && npm publish && git push --follow-tags",
|
|
31
31
|
"lint": "eslint .",
|
|
32
|
+
"lint:fix": "eslint . --fix",
|
|
32
33
|
"test": "vitest run",
|
|
33
34
|
"test:watch": "vitest watch",
|
|
34
35
|
"test:types": "vue-tsc --noEmit && nuxi prepare playground && cd playground && vue-tsc --noEmit"
|