├── .config
├── eslint.config.js
└── prettier.config.js
├── .editorconfig
├── .gitattributes
├── .github
├── codeowners
└── release.yml
├── .gitignore
├── .prettierignore
├── .vscode
├── extensions.json
└── settings.json
├── CHANGELOG.md
├── LICENSE.txt
├── README.md
├── bundler.config.ts
├── docs
├── README.md
├── club-plugins
│ └── README.md
├── extra-eases
│ └── README.md
├── extra-plugins
│ └── README.md
├── options
│ └── README.md
├── register-eases
│ └── README.md
└── register-effects
│ └── README.md
├── package-lock.json
├── package.json
├── playground
├── components
│ └── NavMain.vue
├── layouts
│ └── default.vue
├── nuxt.config.ts
├── package.json
└── pages
│ ├── about
│ └── index.vue
│ └── index.vue
├── src
├── meta.ts
├── module.ts
├── types
│ ├── module.ts
│ └── options
│ │ ├── club-plugins.ts
│ │ ├── extra-eases.ts
│ │ ├── extra-plugins.ts
│ │ └── index.ts
└── utils
│ ├── serialize.ts
│ └── templates.ts
└── tsconfig.json
/.config/eslint.config.js:
--------------------------------------------------------------------------------
1 | import { jsConfig, tsConfig, ignores } from '@hypernym/eslint-config'
2 |
3 | export default [
4 | jsConfig,
5 | tsConfig,
6 | {
7 | files: tsConfig.files,
8 | rules: {
9 | '@typescript-eslint/no-explicit-any': 'off',
10 | '@typescript-eslint/no-unused-vars': [
11 | 'error',
12 | { ignoreRestSiblings: true },
13 | ],
14 | },
15 | },
16 | {
17 | ignores: [...ignores, '**/.nuxt/**/*'],
18 | },
19 | ]
20 |
--------------------------------------------------------------------------------
/.config/prettier.config.js:
--------------------------------------------------------------------------------
1 | export { default } from '@hypernym/prettier-config'
2 |
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | root = true
2 |
3 | [*]
4 | charset = utf-8
5 | end_of_line = lf
6 | indent_size = 2
7 | indent_style = space
8 | insert_final_newline = true
9 | trim_trailing_whitespace = true
10 |
11 | [*.md]
12 | max_line_length = 0
13 | trim_trailing_whitespace = false
14 |
15 | [COMMIT_EDITMSG]
16 | max_line_length = 0
17 |
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | * linguist-vendored
2 | *.ts linguist-vendored=false
3 |
--------------------------------------------------------------------------------
/.github/codeowners:
--------------------------------------------------------------------------------
1 | * @ivodolenc
2 |
--------------------------------------------------------------------------------
/.github/release.yml:
--------------------------------------------------------------------------------
1 | changelog:
2 | categories:
3 | - title: Bug Fixes
4 | labels:
5 | - fix
6 | - title: New Features
7 | labels:
8 | - feat
9 | - title: Types
10 | labels:
11 | - types
12 | - title: Tests
13 | labels:
14 | - test
15 | - title: Documentation
16 | labels:
17 | - docs
18 | - title: Breaking Changes
19 | labels:
20 | - breaking-change
21 | - title: Other Changes
22 | labels:
23 | - '*'
24 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | node_modules
3 | .private
4 | *.log*
5 | .nuxt
6 | .output
7 | .cache
8 | .env
9 | .npmrc
10 | dist
11 |
--------------------------------------------------------------------------------
/.prettierignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | node_modules
3 | *-lock.*
4 | *.lock
5 | *.log*
6 | *.min.*
7 | *.d.ts
8 | .git
9 | .private
10 | .cache
11 | .nuxt
12 | .output
13 | .env*
14 | output
15 | out
16 | coverage
17 | temp
18 | cache
19 | dist
20 |
--------------------------------------------------------------------------------
/.vscode/extensions.json:
--------------------------------------------------------------------------------
1 | {
2 | "recommendations": [
3 | "dbaeumer.vscode-eslint",
4 | "esbenp.prettier-vscode",
5 | "EditorConfig.EditorConfig"
6 | ]
7 | }
8 |
--------------------------------------------------------------------------------
/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "editor.defaultFormatter": "esbenp.prettier-vscode",
3 | "editor.formatOnSave": true,
4 | "eslint.options": {
5 | "overrideConfigFile": ".config/eslint.config.js"
6 | },
7 | "prettier.configPath": ".config/prettier.config.js"
8 | }
9 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # What's New
2 |
3 | Check out the latest features and improvements.
4 |
5 | #### [Release Notes](https://github.com/hypernym-studio/nuxt-gsap/releases)
6 |
--------------------------------------------------------------------------------
/LICENSE.txt:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2024 Ivo Dolenc, Hypernym Studio
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Nuxt Gsap Module
2 |
3 | GSAP module for Nuxt.
4 |
5 | ## Features
6 |
7 | - Helps you integrate the GSAP animation library
8 | - Provides a solution for global use
9 | - Supports custom composables
10 | - Automatically registers plugins after activation
11 | - Allows you to easily register global effects & eases
12 | - Supports Club GreenSock premium plugins
13 | - Zero-config setup ready to go
14 | - TypeScript friendly
15 | - Super easy to use
16 |
17 | ## Quick Start
18 |
19 | 1. Install `@hypernym/nuxt-gsap` to your project
20 |
21 | ```sh
22 | npm i -D @hypernym/nuxt-gsap
23 | ```
24 |
25 | 2. Enable the module in the main config file
26 |
27 | ```ts
28 | // nuxt.config.ts
29 |
30 | {
31 | modules: ['@hypernym/nuxt-gsap']
32 | }
33 | ```
34 |
35 | That's it!
36 |
37 | ## Module
38 |
39 | The module comes with a zero-config setup so after activation it automatically adds the GSAP core and it is globally available without additional settings.
40 |
41 | ```html
42 |
43 |
44 |
45 |
46 |
Nuxt Gsap
47 |
48 |
49 |
50 |
57 | ```
58 |
59 | ## Options
60 |
61 | Nuxt Gsap Module is completely rewritten in TypeScript. It also improves the development experience with detailed descriptions, examples and code auto-completion.
62 |
63 | After plugin activation, it is immediately available globally, so there is no need to manually import or register.
64 |
65 | ```ts
66 | // nuxt.config.ts
67 |
68 | {
69 | modules: ['@hypernym/nuxt-gsap'],
70 |
71 | gsap: {
72 | // Module options
73 | }
74 | }
75 | ```
76 |
77 | ## GSAP Core
78 |
79 | It can be used via a `provide` helper that will be available globally or via a custom `composable` that you can import where you need it.
80 |
81 | ### Provide
82 |
83 | GSAP core is enabled by default on module activation.
84 |
85 | ```ts
86 | // nuxt.config.ts
87 |
88 | {
89 | modules: ['@hypernym/nuxt-gsap'],
90 | }
91 | ```
92 |
93 | **Available globally**
94 |
95 | ```html
96 |
103 | ```
104 |
105 | To disable the _provide_ helper completely, set it to `false`.
106 |
107 | ```ts
108 | // nuxt.config.ts
109 |
110 | {
111 | gsap: {
112 | provide: false
113 | }
114 | }
115 | ```
116 |
117 | ### Composable
118 |
119 | Imports the main `gsap` core as custom composable.
120 |
121 | To enable custom [_composables_](#composables), set it to `true`:
122 |
123 | ```ts
124 | // nuxt.config.ts
125 |
126 | {
127 | gsap: {
128 | composables: true
129 | }
130 | }
131 | ```
132 |
133 | #### useGsap
134 |
135 | - Custom composable
136 |
137 | ```html
138 |
139 |
140 |
141 | Nuxt Gsap Module
142 |
143 |
144 |
147 | ```
148 |
149 | ```ts
150 | // Explicit import (optional)
151 | import { useGsap } from '#gsap'
152 | ```
153 |
154 | ## Documentation
155 |
156 | Check the official [docs](./docs) for more info.
157 |
158 | ## Community
159 |
160 | Feel free to use the official [discussions](https://github.com/hypernym-studio/nuxt-gsap/discussions) for any additional questions.
161 |
162 | ## License
163 |
164 | ### Gsap Platform
165 |
166 | More details about GSAP licenses can be found in the official repository.
167 |
168 | ### Nuxt Gsap Module
169 |
170 | Developed in 🇭🇷 Croatia
171 |
172 | Released under the [MIT](LICENSE.txt) license.
173 |
174 | © Hypernym Studio
175 |
--------------------------------------------------------------------------------
/bundler.config.ts:
--------------------------------------------------------------------------------
1 | import { defineConfig } from '@hypernym/bundler'
2 | import { name, version } from './package.json'
3 | import { nuxtMetaTemplate, nuxtTypesTemplate } from './src/utils/templates.js'
4 |
5 | export default defineConfig({
6 | entries: [
7 | {
8 | input: './src/module.ts',
9 | externals: [/^@nuxt/],
10 | plugins: {
11 | replace: {
12 | preventAssignment: true,
13 | __name__: name,
14 | __version__: version,
15 | },
16 | },
17 | },
18 | {
19 | types: './src/types/module.ts',
20 | output: './dist/module.d.ts',
21 | },
22 | {
23 | template: true,
24 | output: './dist/module.json',
25 | content: nuxtMetaTemplate(),
26 | format: 'json',
27 | },
28 | {
29 | template: true,
30 | output: './dist/types.d.ts',
31 | content: nuxtTypesTemplate(),
32 | format: 'dts',
33 | },
34 | ],
35 | })
36 |
--------------------------------------------------------------------------------
/docs/README.md:
--------------------------------------------------------------------------------
1 | # Documentation
2 |
3 | - [Module Options](./options)
4 | - [Extra Plugins](./extra-plugins)
5 | - [Extra Eases](./extra-eases)
6 | - [Club Plugins](./club-plugins)
7 | - [Register Effects](./register-effects)
8 | - [Register Eases](./register-eases)
9 |
--------------------------------------------------------------------------------
/docs/club-plugins/README.md:
--------------------------------------------------------------------------------
1 | # Club Plugins
2 |
3 | - Type: `object`
4 | - Default: `undefined`
5 |
6 | Specifies GSAP premium plugins.
7 |
8 | This is only available to club members as it requires a paid license.
9 |
10 | Keep in mind that premium plugins must be installed according to the official GSAP guidelines before use.
11 |
12 | For more information about club plugins, check the official pages.
13 |
14 | ## DrawSvg
15 |
16 | - Type: `boolean`
17 | - Default: `undefined`
18 |
19 | ```ts
20 | // nuxt.config.ts
21 |
22 | {
23 | gsap: {
24 | clubPlugins: {
25 | drawSvg: true
26 | }
27 | }
28 | }
29 | ```
30 |
31 | **Available globally**
32 |
33 | ```ts
34 | const { $DrawSVGPlugin } = useNuxtApp()
35 | ```
36 |
37 | ## useDrawSVGPlugin
38 |
39 | - Custom composable
40 |
41 | ```ts
42 | // nuxt.config.ts
43 |
44 | {
45 | gsap: {
46 | composables: true,
47 | clubPlugins: {
48 | drawSvg: true
49 | }
50 | }
51 | }
52 | ```
53 |
54 | **Usage**
55 |
56 | ```ts
57 | useDrawSVGPlugin
58 | ```
59 |
60 | ```ts
61 | // Explicit import (optional)
62 | import { useDrawSVGPlugin } from '#gsap'
63 | ```
64 |
65 | ## ScrollSmoother
66 |
67 | - Type: `boolean`
68 | - Default: `undefined`
69 |
70 | ```ts
71 | // nuxt.config.ts
72 |
73 | {
74 | gsap: {
75 | clubPlugins: {
76 | scrollSmoother: true
77 | }
78 | }
79 | }
80 | ```
81 |
82 | **Available globally**
83 |
84 | ```ts
85 | const { $ScrollSmoother } = useNuxtApp()
86 | ```
87 |
88 | ## useScrollSmoother
89 |
90 | - Custom composable
91 |
92 | ```ts
93 | // nuxt.config.ts
94 |
95 | {
96 | gsap: {
97 | composables: true,
98 | clubPlugins: {
99 | scrollSmoother: true
100 | }
101 | }
102 | }
103 | ```
104 |
105 | **Usage**
106 |
107 | ```ts
108 | useScrollSmoother
109 | ```
110 |
111 | ```ts
112 | // Explicit import (optional)
113 | import { useScrollSmoother } from '#gsap'
114 | ```
115 |
116 | ## GsDevTools
117 |
118 | - Type: `boolean`
119 | - Default: `undefined`
120 |
121 | ```ts
122 | // nuxt.config.ts
123 |
124 | {
125 | gsap: {
126 | clubPlugins: {
127 | gsDevTools: true
128 | }
129 | }
130 | }
131 | ```
132 |
133 | **Available globally**
134 |
135 | ```ts
136 | const { $GSDevTools } = useNuxtApp()
137 | ```
138 |
139 | ## useGSDevTools
140 |
141 | - Custom composable
142 |
143 | ```ts
144 | // nuxt.config.ts
145 |
146 | {
147 | gsap: {
148 | composables: true,
149 | clubPlugins: {
150 | gsDevTools: true
151 | }
152 | }
153 | }
154 | ```
155 |
156 | **Usage**
157 |
158 | ```ts
159 | useGSDevTools
160 | ```
161 |
162 | ```ts
163 | // Explicit import (optional)
164 | import { useGSDevTools } from '#gsap'
165 | ```
166 |
167 | ## Inertia
168 |
169 | - Type: `boolean`
170 | - Default: `undefined`
171 |
172 | ```ts
173 | // nuxt.config.ts
174 |
175 | {
176 | gsap: {
177 | clubPlugins: {
178 | inertia: true
179 | }
180 | }
181 | }
182 | ```
183 |
184 | **Available globally**
185 |
186 | ```ts
187 | const { $InertiaPlugin } = useNuxtApp()
188 | ```
189 |
190 | ## useInertiaPlugin
191 |
192 | - Custom composable
193 |
194 | ```ts
195 | // nuxt.config.ts
196 |
197 | {
198 | gsap: {
199 | composables: true,
200 | clubPlugins: {
201 | inertia: true
202 | }
203 | }
204 | }
205 | ```
206 |
207 | **Usage**
208 |
209 | ```ts
210 | useInertiaPlugin
211 | ```
212 |
213 | ```ts
214 | // Explicit import (optional)
215 | import { useInertiaPlugin } from '#gsap'
216 | ```
217 |
218 | ## MorphSvg
219 |
220 | - Type: `boolean`
221 | - Default: `undefined`
222 |
223 | ```ts
224 | // nuxt.config.ts
225 |
226 | {
227 | gsap: {
228 | clubPlugins: {
229 | morphSvg: true
230 | }
231 | }
232 | }
233 | ```
234 |
235 | **Available globally**
236 |
237 | ```ts
238 | const { $MorphSVGPlugin } = useNuxtApp()
239 | ```
240 |
241 | ## useMorphSVGPlugin
242 |
243 | - Custom composable
244 |
245 | ```ts
246 | // nuxt.config.ts
247 |
248 | {
249 | gsap: {
250 | composables: true,
251 | clubPlugins: {
252 | morphSvg: true
253 | }
254 | }
255 | }
256 | ```
257 |
258 | **Usage**
259 |
260 | ```ts
261 | useMorphSVGPlugin
262 | ```
263 |
264 | ```ts
265 | // Explicit import (optional)
266 | import { useMorphSVGPlugin } from '#gsap'
267 | ```
268 |
269 | ## MotionPathHelper
270 |
271 | - Type: `boolean`
272 | - Default: `undefined`
273 |
274 | ```ts
275 | // nuxt.config.ts
276 |
277 | {
278 | gsap: {
279 | clubPlugins: {
280 | motionPathHelper: true
281 | }
282 | }
283 | }
284 | ```
285 |
286 | **Available globally**
287 |
288 | ```ts
289 | const { $MotionPathHelper } = useNuxtApp()
290 | ```
291 |
292 | ## useMotionPathHelper
293 |
294 | - Custom composable
295 |
296 | ```ts
297 | // nuxt.config.ts
298 |
299 | {
300 | gsap: {
301 | composables: true,
302 | clubPlugins: {
303 | motionPathHelper: true
304 | }
305 | }
306 | }
307 | ```
308 |
309 | **Usage**
310 |
311 | ```ts
312 | useMotionPathHelper
313 | ```
314 |
315 | ```ts
316 | // Explicit import (optional)
317 | import { useMotionPathHelper } from '#gsap'
318 | ```
319 |
320 | ## Physics2d
321 |
322 | - Type: `boolean`
323 | - Default: `undefined`
324 |
325 | ```ts
326 | // nuxt.config.ts
327 |
328 | {
329 | gsap: {
330 | clubPlugins: {
331 | physics2d: true
332 | }
333 | }
334 | }
335 | ```
336 |
337 | **Available globally**
338 |
339 | ```ts
340 | const { $Physics2DPlugin } = useNuxtApp()
341 | ```
342 |
343 | ## usePhysics2DPlugin
344 |
345 | - Custom composable
346 |
347 | ```ts
348 | // nuxt.config.ts
349 |
350 | {
351 | gsap: {
352 | composables: true,
353 | clubPlugins: {
354 | physics2d: true
355 | }
356 | }
357 | }
358 | ```
359 |
360 | **Usage**
361 |
362 | ```ts
363 | usePhysics2DPlugin
364 | ```
365 |
366 | ```ts
367 | // Explicit import (optional)
368 | import { usePhysics2DPlugin } from '#gsap'
369 | ```
370 |
371 | ## PhysicsProps
372 |
373 | - Type: `boolean`
374 | - Default: `undefined`
375 |
376 | ```ts
377 | // nuxt.config.ts
378 |
379 | {
380 | gsap: {
381 | clubPlugins: {
382 | physicsProps: true
383 | }
384 | }
385 | }
386 | ```
387 |
388 | **Available globally**
389 |
390 | ```ts
391 | const { $PhysicsPropsPlugin } = useNuxtApp()
392 | ```
393 |
394 | ## usePhysicsPropsPlugin
395 |
396 | - Custom composable
397 |
398 | ```ts
399 | // nuxt.config.ts
400 |
401 | {
402 | gsap: {
403 | composables: true,
404 | clubPlugins: {
405 | physicsProps: true
406 | }
407 | }
408 | }
409 | ```
410 |
411 | **Usage**
412 |
413 | ```ts
414 | usePhysicsPropsPlugin
415 | ```
416 |
417 | ```ts
418 | // Explicit import (optional)
419 | import { usePhysicsPropsPlugin } from '#gsap'
420 | ```
421 |
422 | ## ScrambleText
423 |
424 | - Type: `boolean`
425 | - Default: `undefined`
426 |
427 | ```ts
428 | // nuxt.config.ts
429 |
430 | {
431 | gsap: {
432 | clubPlugins: {
433 | scrambleText: true
434 | }
435 | }
436 | }
437 | ```
438 |
439 | **Available globally**
440 |
441 | ```ts
442 | const { $ScrambleText } = useNuxtApp()
443 | ```
444 |
445 | ## useScrambleText
446 |
447 | - Custom composable
448 |
449 | ```ts
450 | // nuxt.config.ts
451 |
452 | {
453 | gsap: {
454 | composables: true,
455 | clubPlugins: {
456 | scrambleText: true
457 | }
458 | }
459 | }
460 | ```
461 |
462 | **Usage**
463 |
464 | ```ts
465 | useScrambleText
466 | ```
467 |
468 | ```ts
469 | // Explicit import (optional)
470 | import { useScrambleText } from '#gsap'
471 | ```
472 |
473 | ## SplitText
474 |
475 | - Type: `boolean`
476 | - Default: `undefined`
477 |
478 | ```ts
479 | // nuxt.config.ts
480 |
481 | {
482 | gsap: {
483 | clubPlugins: {
484 | splitText: true
485 | }
486 | }
487 | }
488 | ```
489 |
490 | **Available globally**
491 |
492 | ```ts
493 | const { $SplitText } = useNuxtApp()
494 | ```
495 |
496 | ## useSplitText
497 |
498 | - Custom composable
499 |
500 | ```ts
501 | // nuxt.config.ts
502 |
503 | {
504 | gsap: {
505 | composables: true,
506 | clubPlugins: {
507 | splitText: true
508 | }
509 | }
510 | }
511 | ```
512 |
513 | **Usage**
514 |
515 | ```ts
516 | useSplitText
517 | ```
518 |
519 | ```ts
520 | // Explicit import (optional)
521 | import { useSplitText } from '#gsap'
522 | ```
523 |
524 | ## CustomBounce
525 |
526 | - Type: `boolean`
527 | - Default: `undefined`
528 |
529 | ```ts
530 | // nuxt.config.ts
531 |
532 | {
533 | gsap: {
534 | clubPlugins: {
535 | customBounce: true
536 | }
537 | }
538 | }
539 | ```
540 |
541 | **Available globally**
542 |
543 | ```ts
544 | const { $CustomBounce } = useNuxtApp()
545 | ```
546 |
547 | ## useCustomBounce
548 |
549 | - Custom composable
550 |
551 | ```ts
552 | // nuxt.config.ts
553 |
554 | {
555 | gsap: {
556 | composables: true,
557 | clubPlugins: {
558 | customBounce: true
559 | }
560 | }
561 | }
562 | ```
563 |
564 | **Usage**
565 |
566 | ```ts
567 | useCustomBounce
568 | ```
569 |
570 | ```ts
571 | // Explicit import (optional)
572 | import { useCustomBounce } from '#gsap'
573 | ```
574 |
575 | ## CustomWiggle
576 |
577 | - Type: `boolean`
578 | - Default: `undefined`
579 |
580 | ```ts
581 | // nuxt.config.ts
582 |
583 | {
584 | gsap: {
585 | clubPlugins: {
586 | customWiggle: true
587 | }
588 | }
589 | }
590 | ```
591 |
592 | **Available globally**
593 |
594 | ```ts
595 | const { $CustomWiggle } = useNuxtApp()
596 | ```
597 |
598 | ## useCustomWiggle
599 |
600 | - Custom composable
601 |
602 | ```ts
603 | // nuxt.config.ts
604 |
605 | {
606 | gsap: {
607 | composables: true,
608 | clubPlugins: {
609 | customWiggle: true
610 | }
611 | }
612 | }
613 | ```
614 |
615 | **Usage**
616 |
617 | ```ts
618 | useCustomWiggle
619 | ```
620 |
621 | ```ts
622 | // Explicit import (optional)
623 | import { useCustomWiggle } from '#gsap'
624 | ```
625 |
--------------------------------------------------------------------------------
/docs/extra-eases/README.md:
--------------------------------------------------------------------------------
1 | # Extra Eases
2 |
3 | - Type: `object`
4 | - Default: `undefined`
5 |
6 | Specifies GSAP extra eases.
7 |
8 | ## ExpoScale
9 |
10 | - Type: `boolean`
11 | - Default: `undefined`
12 |
13 | ```ts
14 | // nuxt.config.ts
15 |
16 | {
17 | gsap: {
18 | extraEases: {
19 | expoScale: true
20 | }
21 | }
22 | }
23 | ```
24 |
25 | **Available globally**
26 |
27 | ```ts
28 | const { $ExpoScaleEase } = useNuxtApp()
29 | ```
30 |
31 | ## useExpoScaleEase
32 |
33 | - Custom composable
34 |
35 | ```ts
36 | // nuxt.config.ts
37 |
38 | {
39 | gsap: {
40 | composables: true,
41 | extraEases: {
42 | expoScale: true
43 | }
44 | }
45 | }
46 | ```
47 |
48 | **Usage**
49 |
50 | ```ts
51 | useExpoScaleEase
52 | ```
53 |
54 | ```ts
55 | // Explicit import (optional)
56 | import { useExpoScaleEase } from '#gsap'
57 | ```
58 |
59 | ## Rough
60 |
61 | - Type: `boolean`
62 | - Default: `undefined`
63 |
64 | ```ts
65 | // nuxt.config.ts
66 |
67 | {
68 | gsap: {
69 | extraEases: {
70 | rough: true
71 | }
72 | }
73 | }
74 | ```
75 |
76 | **Available globally**
77 |
78 | ```ts
79 | const { $RoughEase } = useNuxtApp()
80 | ```
81 |
82 | ## useRoughEase
83 |
84 | - Custom composable
85 |
86 | ```ts
87 | // nuxt.config.ts
88 |
89 | {
90 | gsap: {
91 | composables: true,
92 | extraEases: {
93 | rough: true
94 | }
95 | }
96 | }
97 | ```
98 |
99 | **Usage**
100 |
101 | ```ts
102 | useRoughEase
103 | ```
104 |
105 | ```ts
106 | // Explicit import (optional)
107 | import { useRoughEase } from '#gsap'
108 | ```
109 |
110 | ## SlowMo
111 |
112 | - Type: `boolean`
113 | - Default: `undefined`
114 |
115 | ```ts
116 | // nuxt.config.ts
117 |
118 | {
119 | gsap: {
120 | extraEases: {
121 | slowMo: true
122 | }
123 | }
124 | }
125 | ```
126 |
127 | **Available globally**
128 |
129 | ```ts
130 | const { $SlowMo } = useNuxtApp()
131 | ```
132 |
133 | ## useSlowMo
134 |
135 | - Custom composable
136 |
137 | ```ts
138 | // nuxt.config.ts
139 |
140 | {
141 | gsap: {
142 | composables: true,
143 | extraEases: {
144 | slowMo: true
145 | }
146 | }
147 | }
148 | ```
149 |
150 | **Usage**
151 |
152 | ```ts
153 | useSlowMo
154 | ```
155 |
156 | ```ts
157 | // Explicit import (optional)
158 | import { useSlowMo } from '#gsap'
159 | ```
160 |
161 | ## Custom
162 |
163 | - Type: `boolean`
164 | - Default: `undefined`
165 |
166 | ```ts
167 | // nuxt.config.ts
168 |
169 | {
170 | gsap: {
171 | extraEases: {
172 | custom: true
173 | }
174 | }
175 | }
176 | ```
177 |
178 | **Available globally**
179 |
180 | ```ts
181 | const { $CustomEase } = useNuxtApp()
182 | ```
183 |
184 | ## useCustomEase
185 |
186 | - Custom composable
187 |
188 | ```ts
189 | // nuxt.config.ts
190 |
191 | {
192 | gsap: {
193 | composables: true,
194 | extraEases: {
195 | custom: true
196 | }
197 | }
198 | }
199 | ```
200 |
201 | **Usage**
202 |
203 | ```ts
204 | useCustomEase
205 | ```
206 |
207 | ```ts
208 | // Explicit import (optional)
209 | import { useCustomEase } from '#gsap'
210 | ```
211 |
--------------------------------------------------------------------------------
/docs/extra-plugins/README.md:
--------------------------------------------------------------------------------
1 | # Extra Plugins
2 |
3 | - Type: `object`
4 | - Default: `undefined`
5 |
6 | Specifies GSAP extra plugins.
7 |
8 | ## Flip
9 |
10 | - Type: `boolean`
11 | - Default: `undefined`
12 |
13 | ```ts
14 | // nuxt.config.ts
15 |
16 | {
17 | gsap: {
18 | extraPlugins: {
19 | flip: true
20 | }
21 | }
22 | }
23 | ```
24 |
25 | **Available globally**
26 |
27 | ```ts
28 | const { $Flip } = useNuxtApp()
29 | ```
30 |
31 | ## useFlip
32 |
33 | - Custom composable
34 |
35 | ```ts
36 | // nuxt.config.ts
37 |
38 | {
39 | gsap: {
40 | composables: true,
41 | extraPlugins: {
42 | flip: true
43 | }
44 | }
45 | }
46 | ```
47 |
48 | **Usage**
49 |
50 | ```ts
51 | useFlip
52 | ```
53 |
54 | ```ts
55 | // Explicit import (optional)
56 | import { useFlip } from '#gsap'
57 | ```
58 |
59 | ## ScrollTrigger
60 |
61 | - Type: `boolean`
62 | - Default: `undefined`
63 |
64 | ```ts
65 | // nuxt.config.ts
66 |
67 | {
68 | gsap: {
69 | extraPlugins: {
70 | scrollTrigger: true
71 | }
72 | }
73 | }
74 | ```
75 |
76 | **Available globally**
77 |
78 | ```ts
79 | const { $ScrollTrigger } = useNuxtApp()
80 | ```
81 |
82 | ## useScrollTrigger
83 |
84 | - Custom composable
85 |
86 | ```ts
87 | // nuxt.config.ts
88 |
89 | {
90 | gsap: {
91 | composables: true,
92 | extraPlugins: {
93 | scrollTrigger: true
94 | }
95 | }
96 | }
97 | ```
98 |
99 | **Usage**
100 |
101 | ```ts
102 | useScrollTrigger
103 | ```
104 |
105 | ```ts
106 | // Explicit import (optional)
107 | import { useScrollTrigger } from '#gsap'
108 | ```
109 |
110 | ## Observer
111 |
112 | - Type: `boolean`
113 | - Default: `undefined`
114 |
115 | ```ts
116 | // nuxt.config.ts
117 |
118 | {
119 | gsap: {
120 | extraPlugins: {
121 | observer: true
122 | }
123 | }
124 | }
125 | ```
126 |
127 | **Available globally**
128 |
129 | ```ts
130 | const { $Observer } = useNuxtApp()
131 | ```
132 |
133 | ## useObserver
134 |
135 | - Custom composable
136 |
137 | ```ts
138 | // nuxt.config.ts
139 |
140 | {
141 | gsap: {
142 | composables: true,
143 | extraPlugins: {
144 | observer: true
145 | }
146 | }
147 | }
148 | ```
149 |
150 | **Usage**
151 |
152 | ```ts
153 | useObserver
154 | ```
155 |
156 | ```ts
157 | // Explicit import (optional)
158 | import { useObserver } from '#gsap'
159 | ```
160 |
161 | ## ScrollTo
162 |
163 | - Type: `boolean`
164 | - Default: `undefined`
165 |
166 | ```ts
167 | // nuxt.config.ts
168 |
169 | {
170 | gsap: {
171 | extraPlugins: {
172 | scrollTo: true
173 | }
174 | }
175 | }
176 | ```
177 |
178 | **Available globally**
179 |
180 | ```ts
181 | const { $ScrollToPlugin } = useNuxtApp()
182 | ```
183 |
184 | ## useScrollToPlugin
185 |
186 | - Custom composable
187 |
188 | ```ts
189 | // nuxt.config.ts
190 |
191 | {
192 | gsap: {
193 | composables: true,
194 | extraPlugins: {
195 | scrollTo: true
196 | }
197 | }
198 | }
199 | ```
200 |
201 | **Usage**
202 |
203 | ```ts
204 | useScrollToPlugin
205 | ```
206 |
207 | ```ts
208 | // Explicit import (optional)
209 | import { useScrollToPlugin } from '#gsap'
210 | ```
211 |
212 | ## Draggable
213 |
214 | - Type: `boolean`
215 | - Default: `undefined`
216 |
217 | ```ts
218 | // nuxt.config.ts
219 |
220 | {
221 | gsap: {
222 | extraPlugins: {
223 | draggable: true
224 | }
225 | }
226 | }
227 | ```
228 |
229 | **Available globally**
230 |
231 | ```ts
232 | const { $Draggable } = useNuxtApp()
233 | ```
234 |
235 | ## useDraggable
236 |
237 | - Custom composable
238 |
239 | ```ts
240 | // nuxt.config.ts
241 |
242 | {
243 | gsap: {
244 | composables: true,
245 | extraPlugins: {
246 | draggable: true
247 | }
248 | }
249 | }
250 | ```
251 |
252 | **Usage**
253 |
254 | ```ts
255 | useDraggable
256 | ```
257 |
258 | ```ts
259 | // Explicit import (optional)
260 | import { useDraggable } from '#gsap'
261 | ```
262 |
263 | ## Easel
264 |
265 | - Type: `boolean`
266 | - Default: `undefined`
267 |
268 | ```ts
269 | // nuxt.config.ts
270 |
271 | {
272 | gsap: {
273 | extraPlugins: {
274 | easel: true
275 | }
276 | }
277 | }
278 | ```
279 |
280 | **Available globally**
281 |
282 | ```ts
283 | const { $EaselPlugin } = useNuxtApp()
284 | ```
285 |
286 | ## useEaselPlugin
287 |
288 | - Custom composable
289 |
290 | ```ts
291 | // nuxt.config.ts
292 |
293 | {
294 | gsap: {
295 | composables: true,
296 | extraPlugins: {
297 | easel: true
298 | }
299 | }
300 | }
301 | ```
302 |
303 | **Usage**
304 |
305 | ```ts
306 | useEaselPlugin
307 | ```
308 |
309 | ```ts
310 | // Explicit import (optional)
311 | import { useEaselPlugin } from '#gsap'
312 | ```
313 |
314 | ## MotionPath
315 |
316 | - Type: `boolean`
317 | - Default: `undefined`
318 |
319 | ```ts
320 | // nuxt.config.ts
321 |
322 | {
323 | gsap: {
324 | extraPlugins: {
325 | motionPath: true
326 | }
327 | }
328 | }
329 | ```
330 |
331 | **Available globally**
332 |
333 | ```ts
334 | const { $MotionPathPlugin } = useNuxtApp()
335 | ```
336 |
337 | ## useMotionPathPlugin
338 |
339 | - Custom composable
340 |
341 | ```ts
342 | // nuxt.config.ts
343 |
344 | {
345 | gsap: {
346 | composables: true,
347 | extraPlugins: {
348 | motionPath: true
349 | }
350 | }
351 | }
352 | ```
353 |
354 | **Usage**
355 |
356 | ```ts
357 | useMotionPathPlugin
358 | ```
359 |
360 | ```ts
361 | // Explicit import (optional)
362 | import { useMotionPathPlugin } from '#gsap'
363 | ```
364 |
365 | ## Pixi
366 |
367 | - Type: `boolean`
368 | - Default: `undefined`
369 |
370 | ```ts
371 | // nuxt.config.ts
372 |
373 | {
374 | gsap: {
375 | extraPlugins: {
376 | pixi: true
377 | }
378 | }
379 | }
380 | ```
381 |
382 | **Available globally**
383 |
384 | ```ts
385 | const { $PixiPlugin } = useNuxtApp()
386 | ```
387 |
388 | ## usePixiPlugin
389 |
390 | - Custom composable
391 |
392 | ```ts
393 | // nuxt.config.ts
394 |
395 | {
396 | gsap: {
397 | composables: true,
398 | extraPlugins: {
399 | pixi: true
400 | }
401 | }
402 | }
403 | ```
404 |
405 | **Usage**
406 |
407 | ```ts
408 | usePixiPlugin
409 | ```
410 |
411 | ```ts
412 | // Explicit import (optional)
413 | import { usePixiPlugin } from '#gsap'
414 | ```
415 |
416 | ## Text
417 |
418 | - Type: `boolean`
419 | - Default: `undefined`
420 |
421 | ```ts
422 | // nuxt.config.ts
423 |
424 | {
425 | gsap: {
426 | extraPlugins: {
427 | text: true
428 | }
429 | }
430 | }
431 | ```
432 |
433 | **Available globally**
434 |
435 | ```ts
436 | const { $TextPlugin } = useNuxtApp()
437 | ```
438 |
439 | ## useTextPlugin
440 |
441 | - Custom composable
442 |
443 | ```ts
444 | // nuxt.config.ts
445 |
446 | {
447 | gsap: {
448 | composables: true,
449 | extraPlugins: {
450 | text: true
451 | }
452 | }
453 | }
454 | ```
455 |
456 | **Usage**
457 |
458 | ```ts
459 | useTextPlugin
460 | ```
461 |
462 | ```ts
463 | // Explicit import (optional)
464 | import { useTextPlugin } from '#gsap'
465 | ```
466 |
--------------------------------------------------------------------------------
/docs/options/README.md:
--------------------------------------------------------------------------------
1 | # Module Options
2 |
3 | ## Provide
4 |
5 | - Type: `boolean`
6 | - Default: `true`
7 |
8 | Provides the main `$gsap` core with plugins globally.
9 |
10 | ```ts
11 | // nuxt.config.ts
12 |
13 | {
14 | gsap: {
15 | provide: true
16 | }
17 | }
18 | ```
19 |
20 | **Available globally**
21 |
22 | ```ts
23 | const { $gsap } = useNuxtApp()
24 |
25 | $gsap.to('.class', { rotation: 3, x: 100, duration: 1 })
26 | ```
27 |
28 | ## Composables
29 |
30 | - Type: `boolean`
31 | - Default: `undefined`
32 |
33 | Specifies custom composables.
34 |
35 | If enabled, allows the use of custom composables.
36 |
37 | ```ts
38 | // nuxt.config.ts
39 |
40 | {
41 | gsap: {
42 | composables: true
43 | }
44 | }
45 | ```
46 |
47 | It is possible to use _provide_ helper and _composables_ in combination or separately, depending on preference.
48 |
49 | When using _only_ composables, it is recommended to disable global import.
50 |
51 | ```ts
52 | // nuxt.config.ts
53 |
54 | {
55 | gsap: {
56 | composables: true
57 | provide: false // global import
58 | }
59 | }
60 | ```
61 |
62 | ## Auto Import
63 |
64 | - Type: `boolean`
65 | - Default: `true`
66 |
67 | Specifies the `auto-import` feature.
68 |
69 | If enabled, the composables will be available globally so there is no need to import them manually.
70 |
71 | Since this is an opinionated feature, you can disable global `auto-import` and use explicit import only where you need it.
72 |
73 | > [!NOTE]\
74 | > Works only if the option `composables: true` is enabled.
75 |
76 | ```ts
77 | // nuxt.config.ts
78 |
79 | {
80 | gsap: {
81 | autoImport: false
82 | }
83 | }
84 | ```
85 |
--------------------------------------------------------------------------------
/docs/register-eases/README.md:
--------------------------------------------------------------------------------
1 | # Register Eases
2 |
3 | - Type: `object[]`
4 | - Default: `undefined`
5 |
6 | Provides an easy way to register global eases.
7 |
8 | Once the ease is registered, it can be accessed directly on the `gsap` animations.
9 |
10 | ```ts
11 | // nuxt.config.ts
12 |
13 | {
14 | gsap: {
15 | registerEases: [
16 | {
17 | name: 'customEase',
18 | ease: (progress) => {
19 | return progress // linear
20 | },
21 | },
22 | {
23 | name: 'customEase2',
24 | // ...
25 | },
26 | ]
27 | }
28 | }
29 | ```
30 |
31 | **Available globally**
32 |
33 | ```ts
34 | const { $gsap } = useNuxtApp()
35 |
36 | $gsap.to('.class', { x: 100, ease: 'customEase' })
37 | $gsap.to('#id', { x: 200, ease: 'customEase2' })
38 | ```
39 |
--------------------------------------------------------------------------------
/docs/register-effects/README.md:
--------------------------------------------------------------------------------
1 | # Register Effects
2 |
3 | - Type: `object[]`
4 | - Default: `undefined`
5 |
6 | Provides an easy way to register global effects.
7 |
8 | Once the effect is registered, it can be accessed directly on the `gsap.effects` object.
9 |
10 | To avoid possible linting warnings, use `// eslint-disable-next-line` and `// @ts-ignore` comments.
11 |
12 | ```ts
13 | // nuxt.config.ts
14 |
15 | {
16 | gsap: {
17 | registerEffects: [
18 | {
19 | name: 'fade',
20 | defaults: {
21 | y: -100,
22 | opacity: 0,
23 | duration: 2,
24 | },
25 | // eslint-disable-next-line
26 | // @ts-ignore
27 | effect: (targets, config) => {
28 | return gsap.to(targets, {
29 | y: config.y,
30 | opacity: config.opacity,
31 | duration: config.duration,
32 | })
33 | },
34 | },
35 | {
36 | name: 'slideIn',
37 | // ...
38 | },
39 | ]
40 | }
41 | }
42 | ```
43 |
44 | **Available globally**
45 |
46 | ```ts
47 | const { $gsap } = useNuxtApp()
48 |
49 | $gsap.effects.fade('.class')
50 | $gsap.effects.slideIn('#id')
51 | ```
52 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@hypernym/nuxt-gsap",
3 | "version": "2.4.3",
4 | "author": "Hypernym Studio",
5 | "description": "GSAP module for Nuxt.",
6 | "license": "MIT",
7 | "repository": "hypernym-studio/nuxt-gsap",
8 | "homepage": "https://github.com/hypernym-studio/nuxt-gsap",
9 | "funding": "https://github.com/sponsors/ivodolenc",
10 | "type": "module",
11 | "types": "./dist/types.d.ts",
12 | "exports": {
13 | ".": {
14 | "import": "./dist/module.mjs",
15 | "types": "./dist/types.d.ts"
16 | }
17 | },
18 | "files": [
19 | "dist"
20 | ],
21 | "keywords": [
22 | "nuxt",
23 | "nuxt-gsap",
24 | "nuxt-module",
25 | "gsap-module",
26 | "nuxt-animations",
27 | "nuxt-gsap-module",
28 | "animations",
29 | "gsap"
30 | ],
31 | "scripts": {
32 | "dev": "nuxt dev playground",
33 | "build": "hyperbundler",
34 | "build:play": "nuxt build playground",
35 | "generate:play": "nuxt generate playground",
36 | "preview:play": "nuxt preview playground",
37 | "lint": "eslint -c .config/eslint.config.js .",
38 | "lint:fix": "eslint -c .config/eslint.config.js --fix .",
39 | "format": "prettier --config .config/prettier.config.js --write .",
40 | "prepublishOnly": "npm run build"
41 | },
42 | "dependencies": {
43 | "gsap": "^3.12.5"
44 | },
45 | "devDependencies": {
46 | "@hypernym/bundler": "^0.9.3",
47 | "@hypernym/eslint-config": "^3.0.2",
48 | "@hypernym/prettier-config": "^3.0.1",
49 | "@types/node": "^22.5.0",
50 | "eslint": "^9.9.1",
51 | "nuxt": "^3.13.0",
52 | "prettier": "^3.3.3",
53 | "typescript": "^5.5.4"
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/playground/components/NavMain.vue:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
--------------------------------------------------------------------------------
/playground/layouts/default.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
24 |
--------------------------------------------------------------------------------
/playground/nuxt.config.ts:
--------------------------------------------------------------------------------
1 | import { defineNuxtConfig } from 'nuxt/config'
2 | import Module from '../src/module'
3 |
4 | export default defineNuxtConfig({
5 | telemetry: false,
6 |
7 | modules: [Module],
8 |
9 | gsap: {
10 | extraPlugins: {
11 | scrollTrigger: true,
12 | },
13 | },
14 | })
15 |
--------------------------------------------------------------------------------
/playground/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "private": true,
3 | "name": "module-playground"
4 | }
5 |
--------------------------------------------------------------------------------
/playground/pages/about/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
About Page
4 |
5 |
6 |
--------------------------------------------------------------------------------
/playground/pages/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
Index Page
4 |
5 |
6 |
7 |
15 |
--------------------------------------------------------------------------------
/src/meta.ts:
--------------------------------------------------------------------------------
1 | export const name = '__name__'
2 | export const version = '__version__'
3 | export const configKey = 'gsap'
4 | export const compatibility = {
5 | nuxt: '>=3.0.0',
6 | }
7 |
--------------------------------------------------------------------------------
/src/module.ts:
--------------------------------------------------------------------------------
1 | import {
2 | defineNuxtModule,
3 | addTemplate,
4 | addPluginTemplate,
5 | addImports,
6 | resolveAlias,
7 | } from '@nuxt/kit'
8 | import { serialize } from './utils/serialize'
9 | import { name, version, configKey, compatibility } from './meta'
10 | import type { ModuleOptions } from './types/module'
11 |
12 | export default defineNuxtModule({
13 | meta: {
14 | name,
15 | version,
16 | configKey,
17 | compatibility,
18 | },
19 |
20 | defaults: {
21 | provide: true,
22 | autoImport: true,
23 | },
24 |
25 | setup(options, nuxt) {
26 | const {
27 | provide,
28 | composables,
29 | autoImport,
30 | extraPlugins: plugins,
31 | extraEases: eases,
32 | clubPlugins: club,
33 | registerEffects: regEffects,
34 | registerEases: regEases,
35 | } = options
36 |
37 | const fileBanner = `// Generated by ${name}`
38 | const pluginEffect: string[] = []
39 | const pluginEase: string[] = []
40 |
41 | // Global Effects
42 | if (regEffects) {
43 | for (const effect of regEffects) {
44 | pluginEffect.push(`gsap.registerEffect(${serialize(effect)});`)
45 | }
46 | }
47 |
48 | // Global Eases
49 | if (regEases) {
50 | for (const ease of regEases) {
51 | pluginEase.push(
52 | `gsap.registerEase(${serialize(ease.name)}, ${serialize(
53 | ease.ease,
54 | )});`,
55 | )
56 | }
57 | }
58 |
59 | if (provide) {
60 | const templateName = 'gsapPlugin'
61 | const pluginImport: string[] = []
62 | const pluginRegister: string[] = []
63 | const pluginType: string[] = []
64 | const pluginClient: string[] = []
65 |
66 | const addPlugin = ({
67 | name,
68 | subpath,
69 | }: {
70 | name: string
71 | subpath?: string
72 | }) => {
73 | pluginImport.push(
74 | `import { ${name} } from 'gsap/${subpath ? subpath : name}';`,
75 | )
76 | pluginRegister.push(`${name}`)
77 | pluginType.push(`${name}: typeof ${name};`)
78 | }
79 |
80 | // Extra Plugins
81 | if (plugins?.flip) addPlugin({ name: 'Flip' })
82 | if (plugins?.scrollTrigger) addPlugin({ name: 'ScrollTrigger' })
83 | if (plugins?.observer) addPlugin({ name: 'Observer' })
84 | if (plugins?.scrollTo) addPlugin({ name: 'ScrollToPlugin' })
85 | if (plugins?.draggable) addPlugin({ name: 'Draggable' })
86 | if (plugins?.easel) addPlugin({ name: 'EaselPlugin' })
87 | if (plugins?.motionPath) addPlugin({ name: 'MotionPathPlugin' })
88 | if (plugins?.pixi) addPlugin({ name: 'PixiPlugin' })
89 | if (plugins?.text) addPlugin({ name: 'TextPlugin' })
90 |
91 | // Extra Eases
92 | if (eases?.expoScale)
93 | addPlugin({ name: 'ExpoScaleEase', subpath: 'EasePack' })
94 | if (eases?.rough) addPlugin({ name: 'RoughEase', subpath: 'EasePack' })
95 | if (eases?.slowMo) addPlugin({ name: 'SlowMo', subpath: 'EasePack' })
96 | if (eases?.custom) addPlugin({ name: 'CustomEase' })
97 |
98 | // Club Plugins
99 | if (club?.drawSvg) addPlugin({ name: 'DrawSVGPlugin' })
100 | if (club?.scrollSmoother) addPlugin({ name: 'ScrollSmoother' })
101 | if (club?.gsDevTools) addPlugin({ name: 'GSDevTools' })
102 | if (club?.inertia) addPlugin({ name: 'InertiaPlugin' })
103 | if (club?.morphSvg) addPlugin({ name: 'MorphSVGPlugin' })
104 | if (club?.motionPathHelper) addPlugin({ name: 'MotionPathHelper' })
105 | if (club?.physics2d) addPlugin({ name: 'Physics2DPlugin' })
106 | if (club?.physicsProps) addPlugin({ name: 'PhysicsPropsPlugin' })
107 | if (club?.scrambleText) addPlugin({ name: 'ScrambleTextPlugin' })
108 | if (club?.splitText) addPlugin({ name: 'SplitText' })
109 | if (club?.customBounce) addPlugin({ name: 'CustomBounce' })
110 | if (club?.customWiggle) addPlugin({ name: 'CustomWiggle' })
111 |
112 | // Client mode
113 | if (plugins || eases || club || regEffects || regEases) {
114 | const registerPlugin = pluginRegister.length
115 | ? `gsap.registerPlugin(${pluginRegister.join(',')});`
116 | : ''
117 |
118 | pluginClient.push(
119 | `if(process.client) {`,
120 | ` ${registerPlugin}`,
121 | ` ${pluginEffect.join('\n')}`,
122 | ` ${pluginEase.join('\n')}`,
123 | `}`,
124 | )
125 | }
126 |
127 | addTemplate({
128 | filename: `${templateName}.d.ts`,
129 | write: true,
130 | getContents: () =>
131 | [
132 | fileBanner,
133 | `import { Plugin } from '#app';`,
134 | `import { gsap } from 'gsap';`,
135 | `${pluginImport.join('\n')}`,
136 | `declare const plugin: Plugin<{`,
137 | ` gsap: typeof gsap;`,
138 | ` ${pluginType.join('\n')}`,
139 | `}>;`,
140 | `export default plugin;`,
141 | ].join('\n'),
142 | })
143 |
144 | addPluginTemplate({
145 | filename: `${templateName}.mjs`,
146 | write: true,
147 | getContents: () =>
148 | [
149 | fileBanner,
150 | `import { defineNuxtPlugin } from '#app';`,
151 | `import { gsap } from 'gsap';`,
152 | `${pluginImport.join('\n')}`,
153 | `const plugin = defineNuxtPlugin(() => {`,
154 | ` ${pluginClient.join('\n')}`,
155 | ` return {`,
156 | ` provide: {`,
157 | ` gsap,`,
158 | ` ${pluginRegister.join(',\n')}`,
159 | ` }`,
160 | ` }`,
161 | `})`,
162 | `export default plugin;`,
163 | ].join('\n'),
164 | })
165 | }
166 |
167 | if (composables) {
168 | const templateName = 'gsapComposables'
169 | const pluginImport: string[] = []
170 | const pluginRegister: string[] = []
171 | const pluginDeclare: string[] = []
172 | const pluginType: string[] = []
173 |
174 | const addComposable = ({
175 | name,
176 | subpath,
177 | }: {
178 | name: string
179 | subpath?: string
180 | }) => {
181 | pluginImport.push(
182 | `import { ${name} } from 'gsap/${subpath ? subpath : name}';`,
183 | )
184 | pluginRegister.push(`${name}`)
185 | pluginDeclare.push(`export const use${name} = ${name};`)
186 | pluginType.push(`export declare const use${name}: typeof ${name};`)
187 | }
188 |
189 | const alias = resolveAlias(`${nuxt.options.buildDir}/${templateName}`)
190 | nuxt.options.alias[`#${configKey}`] = alias
191 |
192 | // Core
193 | if (autoImport) addImports({ name: 'useGsap', from: alias })
194 |
195 | // Extra Plugins
196 | if (plugins?.flip) {
197 | addComposable({ name: 'Flip' })
198 | if (autoImport) addImports({ name: 'useFlip', from: alias })
199 | }
200 | if (plugins?.scrollTrigger) {
201 | addComposable({ name: 'ScrollTrigger' })
202 | if (autoImport) addImports({ name: 'useScrollTrigger', from: alias })
203 | }
204 | if (plugins?.observer) {
205 | addComposable({ name: 'Observer' })
206 | if (autoImport) addImports({ name: 'useObserver', from: alias })
207 | }
208 | if (plugins?.scrollTo) {
209 | addComposable({ name: 'ScrollToPlugin' })
210 | if (autoImport) addImports({ name: 'useScrollToPlugin', from: alias })
211 | }
212 | if (plugins?.draggable) {
213 | addComposable({ name: 'Draggable' })
214 | if (autoImport) addImports({ name: 'useDraggable', from: alias })
215 | }
216 | if (plugins?.easel) {
217 | addComposable({ name: 'EaselPlugin' })
218 | if (autoImport) addImports({ name: 'useEaselPlugin', from: alias })
219 | }
220 | if (plugins?.motionPath) {
221 | addComposable({ name: 'MotionPathPlugin' })
222 | if (autoImport) addImports({ name: 'useMotionPathPlugin', from: alias })
223 | }
224 | if (plugins?.pixi) {
225 | addComposable({ name: 'PixiPlugin' })
226 | if (autoImport) addImports({ name: 'usePixiPlugin', from: alias })
227 | }
228 | if (plugins?.text) {
229 | addComposable({ name: 'TextPlugin' })
230 | if (autoImport) addImports({ name: 'useTextPlugin', from: alias })
231 | }
232 |
233 | // Extra Eases
234 | if (eases?.expoScale) {
235 | addComposable({ name: 'ExpoScaleEase', subpath: 'EasePack' })
236 | if (autoImport) addImports({ name: 'useExpoScaleEase', from: alias })
237 | }
238 | if (eases?.rough) {
239 | addComposable({ name: 'RoughEase', subpath: 'EasePack' })
240 | if (autoImport) addImports({ name: 'useRoughEase', from: alias })
241 | }
242 | if (eases?.slowMo) {
243 | addComposable({ name: 'SlowMo', subpath: 'EasePack' })
244 | if (autoImport) addImports({ name: 'useSlowMo', from: alias })
245 | }
246 | if (eases?.custom) {
247 | addComposable({ name: 'CustomEase' })
248 | if (autoImport) addImports({ name: 'useCustomEase', from: alias })
249 | }
250 |
251 | // Club Plugins
252 | if (club?.drawSvg) {
253 | addComposable({ name: 'DrawSVGPlugin' })
254 | if (autoImport) addImports({ name: 'useDrawSVGPlugin', from: alias })
255 | }
256 | if (club?.scrollSmoother) {
257 | addComposable({ name: 'ScrollSmoother' })
258 | if (autoImport) addImports({ name: 'useScrollSmoother', from: alias })
259 | }
260 | if (club?.gsDevTools) {
261 | addComposable({ name: 'GSDevTools' })
262 | if (autoImport) addImports({ name: 'useGSDevTools', from: alias })
263 | }
264 | if (club?.inertia) {
265 | addComposable({ name: 'InertiaPlugin' })
266 | if (autoImport) addImports({ name: 'useInertiaPlugin', from: alias })
267 | }
268 | if (club?.morphSvg) {
269 | addComposable({ name: 'MorphSVGPlugin' })
270 | if (autoImport) addImports({ name: 'useMorphSVGPlugin', from: alias })
271 | }
272 | if (club?.motionPathHelper) {
273 | addComposable({ name: 'MotionPathHelper' })
274 | if (autoImport) addImports({ name: 'useMotionPathHelper', from: alias })
275 | }
276 | if (club?.physics2d) {
277 | addComposable({ name: 'Physics2DPlugin' })
278 | if (autoImport) addImports({ name: 'usePhysics2DPlugin', from: alias })
279 | }
280 | if (club?.physicsProps) {
281 | addComposable({ name: 'PhysicsPropsPlugin' })
282 | if (autoImport)
283 | addImports({ name: 'usePhysicsPropsPlugin', from: alias })
284 | }
285 | if (club?.scrambleText) {
286 | addComposable({ name: 'ScrambleTextPlugin' })
287 | if (autoImport)
288 | addImports({ name: 'useScrambleTextPlugin', from: alias })
289 | }
290 | if (club?.splitText) {
291 | addComposable({ name: 'SplitText' })
292 | if (autoImport) addImports({ name: 'useSplitText', from: alias })
293 | }
294 | if (club?.customBounce) {
295 | addComposable({ name: 'CustomBounce' })
296 | if (autoImport) addImports({ name: 'useCustomBounce', from: alias })
297 | }
298 | if (club?.customWiggle) {
299 | addComposable({ name: 'CustomWiggle' })
300 | if (autoImport) addImports({ name: 'useCustomWiggle', from: alias })
301 | }
302 |
303 | addTemplate({
304 | filename: `${templateName}.d.ts`,
305 | write: true,
306 | getContents: () =>
307 | [
308 | fileBanner,
309 | `import { gsap } from 'gsap';`,
310 | `${pluginImport.join('\n')}`,
311 | `export declare const useGsap: typeof gsap;`,
312 | `${pluginType.join('\n')}`,
313 | ].join('\n'),
314 | })
315 |
316 | const registerPlugin = pluginRegister.length
317 | ? `gsap.registerPlugin(${pluginRegister.join(',')});`
318 | : ''
319 |
320 | addTemplate({
321 | filename: `${templateName}.mjs`,
322 | write: true,
323 | getContents: () =>
324 | [
325 | fileBanner,
326 | `import { gsap } from 'gsap';`,
327 | `${pluginImport.join('\n')}`,
328 | `${registerPlugin}`,
329 | `${pluginEffect.join('\n')}`,
330 | `${pluginEase.join('\n')}`,
331 | `export const useGsap = gsap;`,
332 | `${pluginDeclare.join('\n')}`,
333 | ].join('\n'),
334 | })
335 | }
336 | },
337 | })
338 |
--------------------------------------------------------------------------------
/src/types/module.ts:
--------------------------------------------------------------------------------
1 | import type { NuxtModule } from '@nuxt/schema'
2 | import type { ExtraPlugins, ExtraEases, ClubPlugins } from './options'
3 |
4 | export interface ModuleOptions {
5 | /**
6 | * Provides the main `$gsap` core with plugins globally.
7 | *
8 | * @example
9 | *
10 | * ```ts
11 | * const { $gsap } = useNuxtApp()
12 | *
13 | * $gsap.to('.class', { rotation: 3, x: 100, duration: 1 })
14 | * ```
15 | *
16 | * @default true
17 | *
18 | * @since 2.3.0
19 | */
20 | provide?: boolean
21 | /**
22 | * Specifies custom composables.
23 | *
24 | * If enabled, allows the use of custom composables.
25 | *
26 | * When using only composables, it is recommended to disable global import.
27 | *
28 | * @example
29 | *
30 | * ```ts
31 | * {
32 | * gsap: {
33 | * composables: true
34 | * provide: false // global import
35 | * }
36 | * }
37 | * ```
38 | *
39 | * @default undefined
40 | *
41 | * @since 2.3.0
42 | */
43 | composables?: boolean
44 | /**
45 | * Specifies the `auto-import` feature.
46 | *
47 | * If enabled, the composables will be available globally so there is no need to import them manually.
48 | *
49 | * Since this is an opinionated feature, you can disable global `auto-import` and use explicit import only where you need it.
50 | *
51 | * @note Works only if the option `composables: true` is enabled.
52 | *
53 | * @default true
54 | *
55 | * @since 2.3.0
56 | */
57 | autoImport?: boolean
58 | /**
59 | * Specifies GSAP extra plugins.
60 | *
61 | * @default undefined
62 | *
63 | * @since 2.0.0
64 | */
65 | extraPlugins?: ExtraPlugins
66 | /**
67 | * Specifies GSAP extra eases.
68 | *
69 | * @default undefined
70 | *
71 | * @since 2.0.0
72 | */
73 | extraEases?: ExtraEases
74 | /**
75 | * Specifies GSAP premium plugins.
76 | *
77 | * This is only available to club members as it requires a paid license.
78 | *
79 | * Keep in mind that premium plugins must be installed according to the official GSAP guidelines before use.
80 | *
81 | * For more information about club plugins, check the official pages.
82 | *
83 | * @default undefined
84 | *
85 | * @since 2.0.0
86 | */
87 | clubPlugins?: ClubPlugins
88 | /**
89 | * Provides an easy way to register global effects.
90 | *
91 | * Once the effect is registered, it can be accessed directly on the `gsap.effects` object.
92 | *
93 | * To avoid possible linting warnings, use `// @ts-ignore` and `// eslint-disable-next-line` comments.
94 | *
95 | * @example
96 | *
97 | * ```ts
98 | * {
99 | * registerEffects: [
100 | * {
101 | * name: 'fade',
102 | * defaults: {
103 | * y: -100,
104 | * opacity: 0,
105 | * duration: 2
106 | * },
107 | * // eslint-disable-next-line
108 | * // ts-ignore
109 | * effect: (targets, config) => {
110 | * return gsap.to(targets, {
111 | * y: config.y,
112 | * opacity: config.opacity,
113 | * duration: config.duration
114 | * })
115 | * }
116 | * }
117 | * ]
118 | * }
119 | * ```
120 | *
121 | * @default undefined
122 | *
123 | * @since 2.2.0
124 | */
125 | registerEffects?: object[]
126 | /**
127 | * Provides an easy way to register global eases.
128 | *
129 | * Once the ease is registered, it can be accessed directly on the `gsap` animations.
130 | *
131 | * @example
132 | *
133 | * ```ts
134 | * {
135 | * registerEases: [
136 | * {
137 | * name: 'customEase',
138 | * ease: progress => {
139 | * return progress // linear
140 | * },
141 | * }
142 | * ]
143 | * }
144 | * ```
145 | *
146 | * @default undefined
147 | *
148 | * @since 2.2.0
149 | */
150 | registerEases?: { name: string; ease: { (progress: number): number } }[]
151 | }
152 |
153 | declare const module: NuxtModule
154 |
155 | export { module as default }
156 |
--------------------------------------------------------------------------------
/src/types/options/club-plugins.ts:
--------------------------------------------------------------------------------
1 | export interface ClubPlugins {
2 | drawSvg?: boolean
3 | scrollSmoother?: boolean
4 | gsDevTools?: boolean
5 | inertia?: boolean
6 | morphSvg?: boolean
7 | motionPathHelper?: boolean
8 | physics2d?: boolean
9 | physicsProps?: boolean
10 | scrambleText?: boolean
11 | splitText?: boolean
12 | customBounce?: boolean
13 | customWiggle?: boolean
14 | }
15 |
--------------------------------------------------------------------------------
/src/types/options/extra-eases.ts:
--------------------------------------------------------------------------------
1 | export interface ExtraEases {
2 | expoScale?: boolean
3 | rough?: boolean
4 | slowMo?: boolean
5 | custom?: boolean
6 | }
7 |
--------------------------------------------------------------------------------
/src/types/options/extra-plugins.ts:
--------------------------------------------------------------------------------
1 | export interface ExtraPlugins {
2 | flip?: boolean
3 | scrollTrigger?: boolean
4 | observer?: boolean
5 | scrollTo?: boolean
6 | draggable?: boolean
7 | easel?: boolean
8 | motionPath?: boolean
9 | pixi?: boolean
10 | text?: boolean
11 | }
12 |
--------------------------------------------------------------------------------
/src/types/options/index.ts:
--------------------------------------------------------------------------------
1 | export * from './extra-plugins'
2 | export * from './extra-eases'
3 | export * from './club-plugins'
4 |
--------------------------------------------------------------------------------
/src/utils/serialize.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Serializes data.
3 | *
4 | * @since 2.2.0
5 | */
6 | export function serialize(data: unknown): string {
7 | const type = (v: string) => typeof data === v
8 |
9 | if (data === null || data === undefined)
10 | return data === null ? 'null' : 'undefined'
11 |
12 | if (type('boolean') || type('number') || type('function'))
13 | return data.toString()
14 |
15 | if (Array.isArray(data)) return `[${data.map((v) => serialize(v)).join(',')}]`
16 |
17 | if (type('object'))
18 | return `{${Object.entries(data)
19 | .map(([key, val]) => `${key}: ${serialize(val)}`)
20 | .join(',')}}`
21 |
22 | return `'${data}'`
23 | }
24 |
--------------------------------------------------------------------------------
/src/utils/templates.ts:
--------------------------------------------------------------------------------
1 | import { name, description, version, homepage } from '../../package.json'
2 | import { configKey, compatibility } from '../meta'
3 |
4 | /**
5 | * Generates `module.json` meta template.
6 | */
7 | export function nuxtMetaTemplate() {
8 | const metaContent = JSON.stringify(
9 | {
10 | name,
11 | version,
12 | configKey,
13 | compatibility,
14 | },
15 | null,
16 | 2,
17 | )
18 |
19 | return metaContent
20 | }
21 |
22 | /**
23 | * Generates `shims` for `nuxt.config` auto-completion.
24 | */
25 | export function nuxtTypesTemplate() {
26 | const comment = `/**
27 | * Nuxt Gsap Module
28 | *
29 | * ${description}
30 | *
31 | * @see [Repository](${homepage})
32 | */`
33 |
34 | const typesContent = `import { ModuleOptions } from './module'
35 |
36 | declare module '@nuxt/schema' {
37 | interface NuxtConfig {
38 | ${comment}
39 | ['${configKey}']?: Partial
40 | }
41 | interface NuxtOptions {
42 | ${comment}
43 | ['${configKey}']?: ModuleOptions
44 | }
45 | }
46 | declare module 'nuxt/schema' {
47 | interface NuxtConfig { ['${configKey}']?: Partial }
48 | interface NuxtOptions { ['${configKey}']?: ModuleOptions }
49 | }
50 |
51 | export { ModuleOptions, default } from './module'`
52 |
53 | return typesContent
54 | }
55 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./playground/.nuxt/tsconfig.json"
3 | }
4 |
--------------------------------------------------------------------------------