@refokus-agency/navigation 1.0.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2022 YOUR_NAME_HERE
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.
package/README.md ADDED
@@ -0,0 +1,233 @@
1
+ # @refokus-agency/navigation
2
+
3
+ A TypeScript package for implementing smooth navbar animations with GSAP, featuring scroll-based show/hide behavior and customizable animation settings.
4
+
5
+ ## Features
6
+
7
+ - โœจ Smooth GSAP-powered animations
8
+ - ๐Ÿ“œ Scroll-based navbar show/hide behavior
9
+ - โš™๏ธ Configurable animation settings
10
+ - ๐ŸŽฏ Attribute-based element selection
11
+ - ๐Ÿ“ฆ ES Module-only package (no CommonJS support)
12
+ - ๐Ÿ”ง Modern TypeScript configuration with strict mode
13
+ - ๐Ÿงช Testing setup with Vitest
14
+ - ๐ŸŽจ Code formatting with Prettier
15
+ - ๐Ÿ” Linting with ESLint (flat config)
16
+ - ๐Ÿ—๏ธ Build pipeline with TypeScript compiler
17
+ - ๐Ÿ“ Source maps for debugging
18
+
19
+ ## Requirements
20
+
21
+ - Node.js >= 22.0.0
22
+
23
+ ## Installation
24
+
25
+ ```bash
26
+ npm install @refokus-agency/navigation
27
+ ```
28
+
29
+ ## Usage
30
+
31
+ ### Basic Setup
32
+
33
+ 1. Add the `r-navbar` attribute to your navbar element(s):
34
+
35
+ ```html
36
+ <nav r-navbar>
37
+ <!-- Your navbar content -->
38
+ </nav>
39
+ ```
40
+
41
+ 2. Initialize the navbar animation system:
42
+
43
+ ```typescript
44
+ import { initNavbarAnimation } from '@refokus-agency/navigation';
45
+
46
+ // Initialize with custom options
47
+ const success = initNavbarAnimation({
48
+ animationDuration: 0.3,
49
+ animationEasing: 'power2.inOut',
50
+ });
51
+
52
+ if (success) {
53
+ console.log('Navbar animation initialized');
54
+ }
55
+ ```
56
+
57
+ ### How It Works
58
+
59
+ - **Initial Animation**: Navbar slides in smoothly on page load
60
+ - **Scroll Down**: Navbar hides when scrolling down past threshold (50px)
61
+ - **Scroll Up**: Navbar shows when scrolling up
62
+ - **Multiple Navbars**: Supports multiple navbar elements with the same attribute
63
+
64
+ ## Development
65
+
66
+ ### Available Scripts
67
+
68
+ #### Building
69
+
70
+ ```bash
71
+ npm run build # Compile TypeScript
72
+ npm run build:clean # Clean and rebuild
73
+ npm run build:watch # Watch mode
74
+ ```
75
+
76
+ #### Testing
77
+
78
+ ```bash
79
+ npm test # Run tests
80
+ npm run test:watch # Watch mode
81
+ npm run test:coverage # With coverage
82
+ npm run test:ui # With UI
83
+ ```
84
+
85
+ #### Code Quality
86
+
87
+ ```bash
88
+ npm run check-types # Type checking
89
+ npm run lint # Lint and fix
90
+ npm run format # Format code
91
+ ```
92
+
93
+ ## Project Structure
94
+
95
+ ```
96
+ src/
97
+ โ”œโ”€โ”€ index.ts # Main entry point
98
+ โ””โ”€โ”€ nav-anim/
99
+ โ”œโ”€โ”€ index.ts # Navbar animation initialization
100
+ โ”œโ”€โ”€ config.ts # Configuration constants
101
+ โ”œโ”€โ”€ initial-animation.ts # Initial slide-in animation
102
+ โ”œโ”€โ”€ scroll-behaviour.ts # Scroll-based show/hide logic
103
+ โ””โ”€โ”€ __tests__/
104
+ โ”œโ”€โ”€ index.test.ts # Initialization tests
105
+ โ””โ”€โ”€ scroll-behaviour.test.ts # Scroll behavior tests
106
+ ```
107
+
108
+ ## Configuration
109
+
110
+ The package uses the following default configuration:
111
+
112
+ ```typescript
113
+ {
114
+ position: {
115
+ hidden: '-100%', // Y position when hidden
116
+ visible: '0%' // Y position when visible
117
+ },
118
+ scroll: {
119
+ threshold: 50 // Minimum scroll distance to trigger animation
120
+ },
121
+ selectors: {
122
+ navbar: '[r-navbar]' // Attribute selector for navbar elements
123
+ }
124
+ }
125
+ ```
126
+
127
+ ## Publishing
128
+
129
+ This package uses automated semantic versioning and publishing through GitHub Actions. The release process is triggered automatically on pushes to the `main` branch (or manually via the **Release** workflow's `workflow_dispatch`) and publishes to the **public npm registry** (`registry.npmjs.org`) under the `@refokus-agency` scope.
130
+
131
+ ### Release Process
132
+
133
+ The publishing workflow (`.github/workflows/main-release.yml`, named **Release**) calls the `refokus-agency/platform` reusable workflows (`ci.yml` then `release.yml`) and handles:
134
+
135
+ 1. **Automatic Triggering**: Release checks run on push to the `main` branch.
136
+
137
+ 2. **Authentication**: Publishing to npm uses **OIDC Trusted Publishing** โ€” there is **no `NPM_TOKEN`** secret. The caller grants `permissions: id-token: write`, which lets npm mint a short-lived credential at publish time. For this to work, a **Trusted Publisher** must be configured for `@refokus-agency/navigation` on [npmjs.com](https://docs.npmjs.com/trusted-publishers) (Package settings โ†’ Trusted Publisher), pointing at this repository (`refokus-agency/navigation`) with the **workflow filename `release.yml`**. Note: `release.yml` is the **reusable workflow in the `refokus-agency/platform` repo** โ€” *not* a file in this repo (this repo only has `main-release.yml`). npm matches the OIDC token's `job_workflow_ref` claim, which for a reusable workflow resolves to the reusable's path, so enter exactly `release.yml`.
138
+
139
+ ### Semantic Versioning
140
+
141
+ > **โš ๏ธ WARNING:**
142
+ > This repository uses automated semantic versioning and publishing.
143
+ > **Do not publish manually with `npm publish`.**
144
+ > All releases are handled by GitHub Actions via semantic-release.
145
+ >
146
+ > To trigger a release, push to the `main` branch or use the GitHub Actions workflow manually.
147
+ >
148
+ > Ensure your commits follow [Conventional Commits](https://www.conventionalcommits.org/) to enable correct versioning and changelog generation.
149
+ > In order to do that, you MUST run `npm run commit` to use the Commitizen wizard and stay compliant with our versioning standards.
150
+
151
+ The project uses [semantic-release](https://semantic-release.gitbook.io/) for automated version management based on conventional commits:
152
+
153
+ - **Major version** (`x.0.0`): Breaking changes (commits with `BREAKING CHANGE:` or `!:`)
154
+ - **Minor version** (`0.x.0`): New features (commits with `feat:`)
155
+ - **Patch version** (`0.0.x`): Bug fixes (commits with `fix:`)
156
+
157
+ ### Commit Message Format
158
+
159
+ Follow the [Conventional Commits](https://www.conventionalcommits.org/) specification:
160
+
161
+ ```bash
162
+ # Feature
163
+ feat: add new functionality
164
+
165
+ # Bug fix
166
+ fix: resolve issue with feature
167
+
168
+ # Breaking change
169
+ feat!: remove deprecated API
170
+ # or
171
+ feat: add new API
172
+ BREAKING CHANGE: old API has been removed
173
+
174
+ # Documentation
175
+ docs: update README
176
+
177
+ # Style changes
178
+ style: format code
179
+
180
+ # Refactoring
181
+ refactor: restructure code
182
+
183
+ # Performance
184
+ perf: improve performance
185
+
186
+ # Tests
187
+ test: add unit tests
188
+ ```
189
+
190
+ ### Publishing to public npm
191
+
192
+ The package is published to the **public npm registry** under the `@refokus-agency` scope, so consumers can `npm install @refokus-agency/navigation` with no auth or registry configuration. The release:
193
+
194
+ - Targets the public npm registry (`https://registry.npmjs.org`) via `publishConfig`
195
+ - Publishes as a **public** scoped package (`access: public`)
196
+ - Authenticates with **OIDC Trusted Publishing** โ€” no `NPM_TOKEN` secret; the workflow requires `id-token: write`
197
+ - Keeps npm **provenance disabled** because the repository is currently private (provenance requires a public repo). When the repo is made public, flip `provenance: true` on the `release.yml` caller to enable signed provenance
198
+
199
+ > **Peer dependency:** `gsap` is a **peer dependency** and is not bundled. Consumers must install it themselves (`npm install gsap`), or provide it globally as Webflow/CDN setups already do.
200
+
201
+ ### Manual Release
202
+
203
+ To trigger a release manually:
204
+
205
+ 1. Go to the GitHub repository
206
+ 2. Navigate to the **Actions** tab
207
+ 3. Select the **Release** workflow
208
+ 4. Click **Run workflow**
209
+ 5. Choose the branch (usually `main`)
210
+ 6. Click **Run workflow**
211
+
212
+ ### Prerequisites
213
+
214
+ Before publishing, ensure:
215
+
216
+ - All tests pass (`npm test`)
217
+ - Code is properly formatted (`npm run format`)
218
+ - Linting passes (`npm run lint`)
219
+ - Type checking passes (`npm run check-types`)
220
+ - Commit messages follow conventional commits format
221
+
222
+ ### Release Notes
223
+
224
+ Semantic-release automatically:
225
+
226
+ - Generates changelog based on commit messages
227
+ - Creates GitHub releases with release notes
228
+ - Tags releases in Git
229
+ - Updates package version in `package.json`
230
+
231
+ ## License
232
+
233
+ See [LICENSE](LICENSE) file.
@@ -0,0 +1 @@
1
+ export { initNavbarAnimation, type InitNavbarAnimationOptions, } from './nav-anim/index.ts';
package/dist/index.js ADDED
@@ -0,0 +1,2 @@
1
+ export { initNavbarAnimation, } from "./nav-anim/index.js";
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,12 @@
1
+ export declare const NAVBAR_CONFIG: {
2
+ position: {
3
+ hidden: string;
4
+ visible: string;
5
+ };
6
+ scroll: {
7
+ threshold: number;
8
+ };
9
+ selectors: {
10
+ navbar: string;
11
+ };
12
+ };
@@ -0,0 +1,13 @@
1
+ export const NAVBAR_CONFIG = {
2
+ position: {
3
+ hidden: '-100%',
4
+ visible: '0%',
5
+ },
6
+ scroll: {
7
+ threshold: 50,
8
+ },
9
+ selectors: {
10
+ navbar: '[r-navbar]',
11
+ },
12
+ };
13
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1,10 @@
1
+ export type NavbarAnimationOptions = {
2
+ animationDuration: number;
3
+ animationEasing: string;
4
+ };
5
+ export type InitNavbarAnimationOptions = Partial<NavbarAnimationOptions>;
6
+ /**
7
+ * Initializes navbar animation system
8
+ * @returns Whether initialization was successful
9
+ */
10
+ export declare function initNavbarAnimation(options?: InitNavbarAnimationOptions): boolean;
@@ -0,0 +1,25 @@
1
+ import { NAVBAR_CONFIG } from "./config.js";
2
+ import { performInitialAnimation } from "./initial-animation.js";
3
+ import { initScrollBehavior } from "./scroll-behaviour.js";
4
+ const DEFAULT_OPTIONS = {
5
+ animationDuration: 0.3,
6
+ animationEasing: 'power2.inOut',
7
+ };
8
+ /**
9
+ * Initializes navbar animation system
10
+ * @returns Whether initialization was successful
11
+ */
12
+ export function initNavbarAnimation(options = {}) {
13
+ const navbarElements = document.querySelectorAll(NAVBAR_CONFIG.selectors.navbar);
14
+ if (!navbarElements.length)
15
+ return false;
16
+ const resolvedOptions = {
17
+ ...DEFAULT_OPTIONS,
18
+ ...options,
19
+ };
20
+ const elements = Array.from(navbarElements);
21
+ performInitialAnimation(elements, resolvedOptions);
22
+ initScrollBehavior(elements, resolvedOptions);
23
+ return true;
24
+ }
25
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,14 @@
1
+ import type { NavbarAnimationOptions } from './index.ts';
2
+ /**
3
+ * Creates navbar slide animation
4
+ * @param elements - Navbar elements to animate
5
+ * @param targetY - Target Y position
6
+ * @returns GSAP tween instance
7
+ */
8
+ export declare function createNavbarAnimation(elements: Element[], targetY: string, options: NavbarAnimationOptions): gsap.core.Tween;
9
+ /**
10
+ * Performs initial navbar slide-in animation
11
+ * @param navbarElements - Navbar elements to animate
12
+ * @param options - Animation options
13
+ */
14
+ export declare function performInitialAnimation(navbarElements: Element[], options: NavbarAnimationOptions): void;
@@ -0,0 +1,26 @@
1
+ import { gsap } from 'gsap';
2
+ import { NAVBAR_CONFIG } from "./config.js";
3
+ /**
4
+ * Creates navbar slide animation
5
+ * @param elements - Navbar elements to animate
6
+ * @param targetY - Target Y position
7
+ * @returns GSAP tween instance
8
+ */
9
+ export function createNavbarAnimation(elements, targetY, options) {
10
+ return gsap.to(elements, {
11
+ y: targetY,
12
+ duration: options.animationDuration,
13
+ ease: options.animationEasing,
14
+ overwrite: true,
15
+ });
16
+ }
17
+ /**
18
+ * Performs initial navbar slide-in animation
19
+ * @param navbarElements - Navbar elements to animate
20
+ * @param options - Animation options
21
+ */
22
+ export function performInitialAnimation(navbarElements, options) {
23
+ gsap.set(navbarElements, { y: NAVBAR_CONFIG.position.hidden });
24
+ createNavbarAnimation(navbarElements, NAVBAR_CONFIG.position.visible, options);
25
+ }
26
+ //# sourceMappingURL=initial-animation.js.map
@@ -0,0 +1,9 @@
1
+ import type { NavbarAnimationOptions } from './index.ts';
2
+ /**
3
+ * Removes scroll event listener for cleanup
4
+ */
5
+ export declare function cleanupNavbarAnimation(): void;
6
+ /**
7
+ * Initializes navbar scroll behavior
8
+ */
9
+ export declare function initScrollBehavior(elements: Element[], options: NavbarAnimationOptions): void;
@@ -0,0 +1,83 @@
1
+ import { NAVBAR_CONFIG } from "./config.js";
2
+ import { createNavbarAnimation } from "./initial-animation.js";
3
+ let lastScrollY = 0;
4
+ let isNavbarVisible = true;
5
+ let scrollHandlerBound = null;
6
+ let currentOptions = null;
7
+ let navbarElements = [];
8
+ /**
9
+ * Shows the navbar by sliding it down
10
+ */
11
+ function showNavbar() {
12
+ if (isNavbarVisible || navbarElements.length === 0 || !currentOptions)
13
+ return;
14
+ createNavbarAnimation(navbarElements, NAVBAR_CONFIG.position.visible, currentOptions);
15
+ isNavbarVisible = true;
16
+ }
17
+ /**
18
+ * Hides the navbar by sliding it up
19
+ */
20
+ function hideNavbar() {
21
+ if (!isNavbarVisible || navbarElements.length === 0 || !currentOptions)
22
+ return;
23
+ createNavbarAnimation(navbarElements, NAVBAR_CONFIG.position.hidden, currentOptions);
24
+ isNavbarVisible = false;
25
+ }
26
+ /**
27
+ * Determines if scroll distance is significant enough to trigger animation
28
+ * @param currentScrollY - Current scroll position
29
+ * @returns Whether scroll is significant
30
+ */
31
+ function isSignificantScroll(currentScrollY) {
32
+ return (Math.abs(currentScrollY - lastScrollY) >= NAVBAR_CONFIG.scroll.threshold);
33
+ }
34
+ /**
35
+ * Determines if user is scrolling down past threshold
36
+ * @param currentScrollY - Current scroll position
37
+ * @returns Whether user is scrolling down past threshold
38
+ */
39
+ function isScrollingDownPastThreshold(currentScrollY) {
40
+ return (currentScrollY > lastScrollY &&
41
+ currentScrollY > NAVBAR_CONFIG.scroll.threshold);
42
+ }
43
+ /**
44
+ * Handles scroll events to show/hide navbar based on direction
45
+ */
46
+ function handleScroll() {
47
+ const currentScrollY = window.scrollY;
48
+ if (!isSignificantScroll(currentScrollY))
49
+ return;
50
+ if (isScrollingDownPastThreshold(currentScrollY)) {
51
+ hideNavbar();
52
+ }
53
+ else {
54
+ showNavbar();
55
+ }
56
+ lastScrollY = currentScrollY;
57
+ }
58
+ /**
59
+ * Removes scroll event listener for cleanup
60
+ */
61
+ export function cleanupNavbarAnimation() {
62
+ if (scrollHandlerBound) {
63
+ window.removeEventListener('scroll', scrollHandlerBound);
64
+ scrollHandlerBound = null;
65
+ }
66
+ navbarElements = [];
67
+ currentOptions = null;
68
+ }
69
+ /**
70
+ * Initializes navbar scroll behavior
71
+ */
72
+ export function initScrollBehavior(elements, options) {
73
+ if (scrollHandlerBound) {
74
+ window.removeEventListener('scroll', scrollHandlerBound);
75
+ }
76
+ currentOptions = options;
77
+ navbarElements = elements;
78
+ isNavbarVisible = true;
79
+ lastScrollY = window.scrollY;
80
+ scrollHandlerBound = handleScroll;
81
+ window.addEventListener('scroll', scrollHandlerBound, { passive: true });
82
+ }
83
+ //# sourceMappingURL=scroll-behaviour.js.map
@@ -0,0 +1,74 @@
1
+ import { gsap as d } from "gsap";
2
+ const t = {
3
+ position: {
4
+ hidden: "-100%",
5
+ visible: "0%"
6
+ },
7
+ scroll: {
8
+ threshold: 50
9
+ },
10
+ selectors: {
11
+ navbar: "[r-navbar]"
12
+ }
13
+ };
14
+ function c(n, i, e) {
15
+ return d.to(n, {
16
+ y: i,
17
+ duration: e.animationDuration,
18
+ ease: e.animationEasing,
19
+ overwrite: !0
20
+ });
21
+ }
22
+ function f(n, i) {
23
+ d.set(n, { y: t.position.hidden }), c(
24
+ n,
25
+ t.position.visible,
26
+ i
27
+ );
28
+ }
29
+ let a = 0, r = !0, s = null, o = null, l = [];
30
+ function h() {
31
+ r || l.length === 0 || !o || (c(
32
+ l,
33
+ t.position.visible,
34
+ o
35
+ ), r = !0);
36
+ }
37
+ function v() {
38
+ !r || l.length === 0 || !o || (c(
39
+ l,
40
+ t.position.hidden,
41
+ o
42
+ ), r = !1);
43
+ }
44
+ function m(n) {
45
+ return Math.abs(n - a) >= t.scroll.threshold;
46
+ }
47
+ function b(n) {
48
+ return n > a && n > t.scroll.threshold;
49
+ }
50
+ function p() {
51
+ const n = window.scrollY;
52
+ m(n) && (b(n) ? v() : h(), a = n);
53
+ }
54
+ function w(n, i) {
55
+ s && window.removeEventListener("scroll", s), o = i, l = n, r = !0, a = window.scrollY, s = p, window.addEventListener("scroll", s, { passive: !0 });
56
+ }
57
+ const g = {
58
+ animationDuration: 0.3,
59
+ animationEasing: "power2.inOut"
60
+ };
61
+ function N(n = {}) {
62
+ const i = document.querySelectorAll(
63
+ t.selectors.navbar
64
+ );
65
+ if (!i.length) return !1;
66
+ const e = {
67
+ ...g,
68
+ ...n
69
+ }, u = Array.from(i);
70
+ return f(u, e), w(u, e), !0;
71
+ }
72
+ export {
73
+ N as initNavbarAnimation
74
+ };
package/package.json ADDED
@@ -0,0 +1,87 @@
1
+ {
2
+ "name": "@refokus-agency/navigation",
3
+ "version": "1.0.2",
4
+ "type": "module",
5
+ "description": "A TypeScript package for GSAP-powered navbar animations with scroll-based show/hide behavior",
6
+ "main": "dist/index.js",
7
+ "module": "dist/index.js",
8
+ "types": "dist/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "types": "./dist/index.d.ts",
12
+ "import": "./dist/index.js"
13
+ }
14
+ },
15
+ "files": [
16
+ "dist/**/*",
17
+ "!dist/**/*.map",
18
+ "!dist/**/__tests__/**",
19
+ "README.md",
20
+ "LICENSE"
21
+ ],
22
+ "author": "Refokus Agency",
23
+ "keywords": [
24
+ "navbar",
25
+ "animation",
26
+ "gsap",
27
+ "scroll",
28
+ "typescript",
29
+ "webflow"
30
+ ],
31
+ "repository": {
32
+ "type": "git",
33
+ "url": "git+https://github.com/refokus-agency/navigation.git"
34
+ },
35
+ "bugs": {
36
+ "url": "https://github.com/refokus-agency/navigation/issues"
37
+ },
38
+ "homepage": "https://github.com/refokus-agency/navigation#readme",
39
+ "scripts": {
40
+ "build": "tsc && npm run build:browser",
41
+ "build:browser": "vite build",
42
+ "build:clean": "rimraf dist && npm run build",
43
+ "build:watch": "tsc --watch",
44
+ "prepublishOnly": "npm run check-types && npm run lint && npm run build:clean",
45
+ "check-types": "tsc --noEmit --strict --skipLibCheck",
46
+ "typecheck": "tsc --noEmit --strict --skipLibCheck",
47
+ "lint": "eslint src --ext .ts --fix",
48
+ "lint:report": "eslint src --ext .ts",
49
+ "format": "prettier --write \"src/**/*.{ts,js,json}\"",
50
+ "test": "vitest run",
51
+ "test:watch": "vitest",
52
+ "test:coverage": "vitest run --coverage",
53
+ "test:ui": "vitest --ui",
54
+ "commit": "cz"
55
+ },
56
+ "peerDependencies": {
57
+ "gsap": "^3.14.2"
58
+ },
59
+ "devDependencies": {
60
+ "@eslint/js": "^9.39.4",
61
+ "@total-typescript/tsconfig": "^1.0.4",
62
+ "@types/node": "^25.5.0",
63
+ "@types/webidl-conversions": "^7.0.3",
64
+ "@typescript-eslint/eslint-plugin": "^8.57.0",
65
+ "@typescript-eslint/parser": "^8.57.0",
66
+ "@vitest/ui": "^3.2.4",
67
+ "commitizen": "^4.3.1",
68
+ "cz-conventional-changelog": "3.3.0",
69
+ "eslint": "^10.0.3",
70
+ "eslint-config-prettier": "^10.1.8",
71
+ "eslint-plugin-n": "^17.21.0",
72
+ "gsap": "^3.14.2",
73
+ "jsdom": "^29.0.0",
74
+ "prettier": "^3.6.2",
75
+ "rimraf": "^6.1.3",
76
+ "typescript": "^5.8.3",
77
+ "vite": "^7.3.1",
78
+ "vitest": "^3.2.4"
79
+ },
80
+ "engines": {
81
+ "node": ">=22.0.0"
82
+ },
83
+ "publishConfig": {
84
+ "registry": "https://registry.npmjs.org",
85
+ "access": "public"
86
+ }
87
+ }