├── .gitignore
├── LICENSE
├── README.md
├── dist
├── featherScroll.esm.js
├── featherScroll.esm.js.map
├── featherScroll.min.js
└── featherScroll.min.js.map
├── package.json
└── src
└── featherScroll.js
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | demo/
3 | rollup.config.js
4 | package-lock.json
5 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2025 Ranvijay Raj
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
13 | all 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
21 | THE SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # FeatherScroll
2 |
3 | FeatherScroll is a lightweight, smooth scrolling library designed for full device support and easy integration. It provides advanced scrolling features such as parallax effects, sticky elements, and smooth animations without requiring additional dependencies.
4 |
5 | ## 🚀 Features
6 |
7 | - **Smooth Scrolling:** Automatically enables smooth scrolling when included.
8 | - **Supports Multiple Scrollable Areas:** Works with multiple content sections on a single page.
9 | - **Parallax Scrolling:** Apply horizontal and vertical scroll effects.
10 | - **Sticky Elements:** Keep elements fixed within their parent while scrolling.
11 | - **Scroll Direction Detection:** Identify whether the user is scrolling up or down.
12 | - **Fully Configurable:** Customize scroll speed, easing, and gestures.
13 | - **Integration with GSAP ScrollTrigger:** Seamless compatibility for advanced animations.
14 |
15 | ---
16 |
17 | ## 📦 Installation
18 |
19 | ### **Using npm**
20 |
21 | To install FeatherScroll via npm, run the following command:
22 |
23 | ```bash
24 | npm install scrollfeather
25 | ```
26 |
27 | Then import it in your JavaScript:
28 |
29 | ```js
30 | import FeatherScroll from 'scrollfeather';
31 |
32 | const scroll = new FeatherScroll();
33 | ```
34 |
35 | ### **Using JSDelivr (CDN)**
36 |
37 | You can also include FeatherScroll directly via CDN in your HTML:
38 |
39 | ```html
40 |
41 | ```
42 |
43 | Once included, FeatherScroll is available globally as `FeatherScroll`:
44 |
45 | ```js
46 | const scroll = new FeatherScroll();
47 | ```
48 | ---
49 |
50 | ## 🛠️ Basic Usage
51 |
52 | ### **1️⃣ Include FeatherScroll in Your Project**
53 |
54 | ```html
55 |
56 | ```
57 |
58 | ### **2️⃣ Initialize FeatherScroll**
59 |
60 | Feather Scroll doesn't need any extra options for basic smooth scrolling initialization
61 |
62 | ```js
63 | const scroll = new FeatherScroll();
64 | ```
65 |
66 | ---
67 |
68 | ## ⚙️ Options
69 |
70 | You can customize FeatherScroll with various options:
71 |
72 | ```js
73 | const scroll = new FeatherScroll({
74 | smooth: true, // Enable smooth scrolling
75 | duration: 1.2, // Scroll duration (seconds)
76 | easing: (t) => 1 - Math.pow(1 - t, 3), // Easing function
77 | direction: 'vertical', // 'vertical' | 'horizontal'
78 | gestureDirection: 'both', // Mouse/touch gesture control
79 | mouseSensitivity: 1, // Sensitivity for wheel scrolling
80 | touchSensitivity: 2, // Sensitivity for touch scrolling
81 | infinite: false // Infinite scrolling
82 | });
83 | ```
84 |
85 | ---
86 |
87 | ## 📌 Sticky Elements
88 |
89 | To make an element sticky within its parent, add the `data-scroll-sticky` attribute:
90 |
91 | ```html
92 |
93 |
I'm a sticky element!
94 |
95 | ```
96 |
97 | The element will remain fixed inside its parent container while scrolling.
98 |
99 | ---
100 |
101 | ## 🎭 Parallax Scrolling
102 |
103 | Apply a **scroll speed effect** using `data-scroll-speed`:
104 |
105 | ```html
106 | This moves slower.
107 | This moves faster.
108 | ```
109 |
110 | Apply **horizontal scrolling** using `data-scroll-direction="horizontal"`:
111 |
112 | ```html
113 | This moves sideways.
114 | ```
115 |
116 | You can combine both:
117 |
118 | ```html
119 | Moves in diagonally!
120 | ```
121 |
122 | ---
123 |
124 | ## 🔄 Scroll Direction Detection
125 |
126 | You can detect whether the user is scrolling up or down using an event listener:
127 |
128 | ```js
129 | document.addEventListener('scroll', () => {
130 | const direction = scroll.getScrollDirection();
131 | console.log(`Scrolling ${direction}`);
132 | });
133 | ```
134 |
135 | This will return `'up'` or `'down'` based on the user's scroll behavior.
136 |
137 | ---
138 |
139 | ## 🎯 Scroll to Specific Section
140 |
141 | You can scroll to any element or position programmatically:
142 |
143 | ```js
144 | scroll.scrollTo('#section', { offset: -50, duration: 1 });
145 | ```
146 |
147 | ---
148 |
149 | ## 🎬 GSAP ScrollTrigger Integration
150 |
151 | If GSAP ScrollTrigger is included, FeatherScroll will automatically sync with it
152 |
153 | The below code is useful when you have set a custom scroll container:
154 |
155 | ```js
156 | ScrollTrigger.defaults({ scroller: scroll.wrapper });
157 | //scroll is the variable in which FeatherScroll is initialized
158 | ```
159 |
160 | ---
161 |
162 | ## 🛑 Controlling Scroll Behavior
163 |
164 | ### **Start or Stop Smooth Scrolling**
165 |
166 | ```js
167 | scroll.start(); // Enable smooth scrolling
168 | scroll.stop(); // Disable smooth scrolling
169 | ```
170 |
171 | ### **Destroy FeatherScroll**
172 |
173 | ```js
174 | scroll.destroy();
175 | ```
176 |
177 | ---
178 |
179 | ## 🛠️ Updating Options Dynamically
180 |
181 | You can update the scroll options dynamically:
182 |
183 | ```js
184 | scroll.updateOptions({ duration: 2, smooth: false });
185 | ```
186 |
187 | This allows you to modify scroll settings without reinitializing the instance.
188 |
189 | ---
190 |
191 | ## 🌍 Supporting Multiple Scroll Instances
192 |
193 | FeatherScroll supports multiple scrolling areas:
194 |
195 | ```js
196 | const scroll1 = new FeatherScroll({ wrapper: '.container1', content: '.content1' });
197 | const scroll2 = new FeatherScroll({ wrapper: '.container2', content: '.content2' });
198 | ```
199 |
200 | ---
201 |
202 | ## 📜 License
203 |
204 | FeatherScroll is open-source under the [MIT License](LICENSE).
205 |
206 | ---
207 |
208 | ## 🤝 Contributing
209 |
210 | If you want to contribute, feel free to submit pull requests on [GitHub](https://github.com/yourusername/featherscroll).
211 |
212 | ---
213 |
214 | ## ❤️ Support FeatherScroll
215 |
216 | If you find FeatherScroll useful and would like to support its development, consider donating:
217 |
218 | - **PayPal:** [@RanvijayRaj7](https://www.paypal.me/RanvijayRaj7)
219 | - **UPI:** gamersuraj720@okhdfcbank
220 |
221 | Your support helps keep this project alive and improving! 🚀
222 |
223 | ---
224 | ## 📧 Need Help?
225 |
226 | For questions or issues, create a GitHub issue or reach out to me!
227 |
228 |
--------------------------------------------------------------------------------
/dist/featherScroll.esm.js:
--------------------------------------------------------------------------------
1 | // package.json
2 | var version = "1.3.1";
3 |
4 | // packages/core/src/maths.ts
5 | function clamp(min, input, max) {
6 | return Math.max(min, Math.min(input, max));
7 | }
8 | function lerp(x, y, t) {
9 | return (1 - t) * x + t * y;
10 | }
11 | function damp(x, y, lambda, deltaTime) {
12 | return lerp(x, y, 1 - Math.exp(-lambda * deltaTime));
13 | }
14 | function modulo(n, d) {
15 | return (n % d + d) % d;
16 | }
17 |
18 | // packages/core/src/animate.ts
19 | var Animate = class {
20 | isRunning = false;
21 | value = 0;
22 | from = 0;
23 | to = 0;
24 | currentTime = 0;
25 | // These are instanciated in the fromTo method
26 | lerp;
27 | duration;
28 | easing;
29 | onUpdate;
30 | /**
31 | * Advance the animation by the given delta time
32 | *
33 | * @param deltaTime - The time in seconds to advance the animation
34 | */
35 | advance(deltaTime) {
36 | if (!this.isRunning) return;
37 | let completed = false;
38 | if (this.duration && this.easing) {
39 | this.currentTime += deltaTime;
40 | const linearProgress = clamp(0, this.currentTime / this.duration, 1);
41 | completed = linearProgress >= 1;
42 | const easedProgress = completed ? 1 : this.easing(linearProgress);
43 | this.value = this.from + (this.to - this.from) * easedProgress;
44 | } else if (this.lerp) {
45 | this.value = damp(this.value, this.to, this.lerp * 60, deltaTime);
46 | if (Math.round(this.value) === this.to) {
47 | this.value = this.to;
48 | completed = true;
49 | }
50 | } else {
51 | this.value = this.to;
52 | completed = true;
53 | }
54 | if (completed) {
55 | this.stop();
56 | }
57 | this.onUpdate?.(this.value, completed);
58 | }
59 | /** Stop the animation */
60 | stop() {
61 | this.isRunning = false;
62 | }
63 | /**
64 | * Set up the animation from a starting value to an ending value
65 | * with optional parameters for lerping, duration, easing, and onUpdate callback
66 | *
67 | * @param from - The starting value
68 | * @param to - The ending value
69 | * @param options - Options for the animation
70 | */
71 | fromTo(from, to, { lerp: lerp2, duration, easing, onStart, onUpdate }) {
72 | this.from = this.value = from;
73 | this.to = to;
74 | this.lerp = lerp2;
75 | this.duration = duration;
76 | this.easing = easing;
77 | this.currentTime = 0;
78 | this.isRunning = true;
79 | onStart?.();
80 | this.onUpdate = onUpdate;
81 | }
82 | };
83 |
84 | // packages/core/src/debounce.ts
85 | function debounce(callback, delay) {
86 | let timer;
87 | return function(...args) {
88 | let context = this;
89 | clearTimeout(timer);
90 | timer = setTimeout(() => {
91 | timer = void 0;
92 | callback.apply(context, args);
93 | }, delay);
94 | };
95 | }
96 |
97 | // packages/core/src/dimensions.ts
98 | var Dimensions = class {
99 | constructor(wrapper, content, { autoResize = true, debounce: debounceValue = 250 } = {}) {
100 | this.wrapper = wrapper;
101 | this.content = content;
102 | if (autoResize) {
103 | this.debouncedResize = debounce(this.resize, debounceValue);
104 | if (this.wrapper instanceof Window) {
105 | window.addEventListener("resize", this.debouncedResize, false);
106 | } else {
107 | this.wrapperResizeObserver = new ResizeObserver(this.debouncedResize);
108 | this.wrapperResizeObserver.observe(this.wrapper);
109 | }
110 | this.contentResizeObserver = new ResizeObserver(this.debouncedResize);
111 | this.contentResizeObserver.observe(this.content);
112 | }
113 | this.resize();
114 | }
115 | width = 0;
116 | height = 0;
117 | scrollHeight = 0;
118 | scrollWidth = 0;
119 | // These are instanciated in the constructor as they need information from the options
120 | debouncedResize;
121 | wrapperResizeObserver;
122 | contentResizeObserver;
123 | destroy() {
124 | this.wrapperResizeObserver?.disconnect();
125 | this.contentResizeObserver?.disconnect();
126 | if (this.wrapper === window && this.debouncedResize) {
127 | window.removeEventListener("resize", this.debouncedResize, false);
128 | }
129 | }
130 | resize = () => {
131 | this.onWrapperResize();
132 | this.onContentResize();
133 | };
134 | onWrapperResize = () => {
135 | if (this.wrapper instanceof Window) {
136 | this.width = window.innerWidth;
137 | this.height = window.innerHeight;
138 | } else {
139 | this.width = this.wrapper.clientWidth;
140 | this.height = this.wrapper.clientHeight;
141 | }
142 | };
143 | onContentResize = () => {
144 | if (this.wrapper instanceof Window) {
145 | this.scrollHeight = this.content.scrollHeight;
146 | this.scrollWidth = this.content.scrollWidth;
147 | } else {
148 | this.scrollHeight = this.wrapper.scrollHeight;
149 | this.scrollWidth = this.wrapper.scrollWidth;
150 | }
151 | };
152 | get limit() {
153 | return {
154 | x: this.scrollWidth - this.width,
155 | y: this.scrollHeight - this.height
156 | };
157 | }
158 | };
159 |
160 | // packages/core/src/emitter.ts
161 | var Emitter = class {
162 | events = {};
163 | /**
164 | * Emit an event with the given data
165 | * @param event Event name
166 | * @param args Data to pass to the event handlers
167 | */
168 | emit(event, ...args) {
169 | let callbacks = this.events[event] || [];
170 | for (let i = 0, length = callbacks.length; i < length; i++) {
171 | callbacks[i]?.(...args);
172 | }
173 | }
174 | /**
175 | * Add a callback to the event
176 | * @param event Event name
177 | * @param cb Callback function
178 | * @returns Unsubscribe function
179 | */
180 | on(event, cb) {
181 | this.events[event]?.push(cb) || (this.events[event] = [cb]);
182 | return () => {
183 | this.events[event] = this.events[event]?.filter((i) => cb !== i);
184 | };
185 | }
186 | /**
187 | * Remove a callback from the event
188 | * @param event Event name
189 | * @param callback Callback function
190 | */
191 | off(event, callback) {
192 | this.events[event] = this.events[event]?.filter((i) => callback !== i);
193 | }
194 | /**
195 | * Remove all event listeners and clean up
196 | */
197 | destroy() {
198 | this.events = {};
199 | }
200 | };
201 |
202 | // packages/core/src/virtual-scroll.ts
203 | var LINE_HEIGHT = 100 / 6;
204 | var listenerOptions = { passive: false };
205 | var VirtualScroll = class {
206 | constructor(element, options = { wheelMultiplier: 1, touchMultiplier: 1 }) {
207 | this.element = element;
208 | this.options = options;
209 | window.addEventListener("resize", this.onWindowResize, false);
210 | this.onWindowResize();
211 | this.element.addEventListener("wheel", this.onWheel, listenerOptions);
212 | this.element.addEventListener(
213 | "touchstart",
214 | this.onTouchStart,
215 | listenerOptions
216 | );
217 | this.element.addEventListener(
218 | "touchmove",
219 | this.onTouchMove,
220 | listenerOptions
221 | );
222 | this.element.addEventListener("touchend", this.onTouchEnd, listenerOptions);
223 | }
224 | touchStart = {
225 | x: 0,
226 | y: 0
227 | };
228 | lastDelta = {
229 | x: 0,
230 | y: 0
231 | };
232 | window = {
233 | width: 0,
234 | height: 0
235 | };
236 | emitter = new Emitter();
237 | /**
238 | * Add an event listener for the given event and callback
239 | *
240 | * @param event Event name
241 | * @param callback Callback function
242 | */
243 | on(event, callback) {
244 | return this.emitter.on(event, callback);
245 | }
246 | /** Remove all event listeners and clean up */
247 | destroy() {
248 | this.emitter.destroy();
249 | window.removeEventListener("resize", this.onWindowResize, false);
250 | this.element.removeEventListener("wheel", this.onWheel, listenerOptions);
251 | this.element.removeEventListener(
252 | "touchstart",
253 | this.onTouchStart,
254 | listenerOptions
255 | );
256 | this.element.removeEventListener(
257 | "touchmove",
258 | this.onTouchMove,
259 | listenerOptions
260 | );
261 | this.element.removeEventListener(
262 | "touchend",
263 | this.onTouchEnd,
264 | listenerOptions
265 | );
266 | }
267 | /**
268 | * Event handler for 'touchstart' event
269 | *
270 | * @param event Touch event
271 | */
272 | onTouchStart = (event) => {
273 | const { clientX, clientY } = event.targetTouches ? event.targetTouches[0] : event;
274 | this.touchStart.x = clientX;
275 | this.touchStart.y = clientY;
276 | this.lastDelta = {
277 | x: 0,
278 | y: 0
279 | };
280 | this.emitter.emit("scroll", {
281 | deltaX: 0,
282 | deltaY: 0,
283 | event
284 | });
285 | };
286 | /** Event handler for 'touchmove' event */
287 | onTouchMove = (event) => {
288 | const { clientX, clientY } = event.targetTouches ? event.targetTouches[0] : event;
289 | const deltaX = -(clientX - this.touchStart.x) * this.options.touchMultiplier;
290 | const deltaY = -(clientY - this.touchStart.y) * this.options.touchMultiplier;
291 | this.touchStart.x = clientX;
292 | this.touchStart.y = clientY;
293 | this.lastDelta = {
294 | x: deltaX,
295 | y: deltaY
296 | };
297 | this.emitter.emit("scroll", {
298 | deltaX,
299 | deltaY,
300 | event
301 | });
302 | };
303 | onTouchEnd = (event) => {
304 | this.emitter.emit("scroll", {
305 | deltaX: this.lastDelta.x,
306 | deltaY: this.lastDelta.y,
307 | event
308 | });
309 | };
310 | /** Event handler for 'wheel' event */
311 | onWheel = (event) => {
312 | let { deltaX, deltaY, deltaMode } = event;
313 | const multiplierX = deltaMode === 1 ? LINE_HEIGHT : deltaMode === 2 ? this.window.width : 1;
314 | const multiplierY = deltaMode === 1 ? LINE_HEIGHT : deltaMode === 2 ? this.window.height : 1;
315 | deltaX *= multiplierX;
316 | deltaY *= multiplierY;
317 | deltaX *= this.options.wheelMultiplier;
318 | deltaY *= this.options.wheelMultiplier;
319 | this.emitter.emit("scroll", { deltaX, deltaY, event });
320 | };
321 | onWindowResize = () => {
322 | this.window = {
323 | width: window.innerWidth,
324 | height: window.innerHeight
325 | };
326 | };
327 | };
328 |
329 | // packages/core/src/lenis.ts
330 | var Lenis = class {
331 | _isScrolling = false;
332 | // true when scroll is animating
333 | _isStopped = false;
334 | // true if user should not be able to scroll - enable/disable programmatically
335 | _isLocked = false;
336 | // same as isStopped but enabled/disabled when scroll reaches target
337 | _preventNextNativeScrollEvent = false;
338 | _resetVelocityTimeout = null;
339 | __rafID = null;
340 | /**
341 | * Whether or not the user is touching the screen
342 | */
343 | isTouching;
344 | /**
345 | * The time in ms since the lenis instance was created
346 | */
347 | time = 0;
348 | /**
349 | * User data that will be forwarded through the scroll event
350 | *
351 | * @example
352 | * lenis.scrollTo(100, {
353 | * userData: {
354 | * foo: 'bar'
355 | * }
356 | * })
357 | */
358 | userData = {};
359 | /**
360 | * The last velocity of the scroll
361 | */
362 | lastVelocity = 0;
363 | /**
364 | * The current velocity of the scroll
365 | */
366 | velocity = 0;
367 | /**
368 | * The direction of the scroll
369 | */
370 | direction = 0;
371 | /**
372 | * The options passed to the lenis instance
373 | */
374 | options;
375 | /**
376 | * The target scroll value
377 | */
378 | targetScroll;
379 | /**
380 | * The animated scroll value
381 | */
382 | animatedScroll;
383 | // These are instanciated here as they don't need information from the options
384 | animate = new Animate();
385 | emitter = new Emitter();
386 | // These are instanciated in the constructor as they need information from the options
387 | dimensions;
388 | // This is not private because it's used in the Snap class
389 | virtualScroll;
390 | constructor({
391 | wrapper = window,
392 | content = document.documentElement,
393 | eventsTarget = wrapper,
394 | smoothWheel = true,
395 | syncTouch = false,
396 | syncTouchLerp = 0.075,
397 | touchInertiaMultiplier = 35,
398 | duration,
399 | // in seconds
400 | easing = (t) => Math.min(1, 1.001 - Math.pow(2, -10 * t)),
401 | lerp: lerp2 = 0.1,
402 | infinite = false,
403 | orientation = "vertical",
404 | // vertical, horizontal
405 | gestureOrientation = "vertical",
406 | // vertical, horizontal, both
407 | touchMultiplier = 1,
408 | wheelMultiplier = 1,
409 | autoResize = true,
410 | prevent,
411 | virtualScroll,
412 | overscroll = true,
413 | autoRaf = false,
414 | anchors = false,
415 | autoToggle = false,
416 | // https://caniuse.com/?search=transition-behavior
417 | allowNestedScroll = false,
418 | __experimental__naiveDimensions = false
419 | } = {}) {
420 | window.lenisVersion = version;
421 | if (!wrapper || wrapper === document.documentElement) {
422 | wrapper = window;
423 | }
424 | this.options = {
425 | wrapper,
426 | content,
427 | eventsTarget,
428 | smoothWheel,
429 | syncTouch,
430 | syncTouchLerp,
431 | touchInertiaMultiplier,
432 | duration,
433 | easing,
434 | lerp: lerp2,
435 | infinite,
436 | gestureOrientation,
437 | orientation,
438 | touchMultiplier,
439 | wheelMultiplier,
440 | autoResize,
441 | prevent,
442 | virtualScroll,
443 | overscroll,
444 | autoRaf,
445 | anchors,
446 | autoToggle,
447 | allowNestedScroll,
448 | __experimental__naiveDimensions
449 | };
450 | this.dimensions = new Dimensions(wrapper, content, { autoResize });
451 | this.updateClassName();
452 | this.targetScroll = this.animatedScroll = this.actualScroll;
453 | this.options.wrapper.addEventListener("scroll", this.onNativeScroll, false);
454 | this.options.wrapper.addEventListener("scrollend", this.onScrollEnd, {
455 | capture: true
456 | });
457 | if (this.options.anchors && this.options.wrapper === window) {
458 | this.options.wrapper.addEventListener(
459 | "click",
460 | this.onClick,
461 | false
462 | );
463 | }
464 | this.options.wrapper.addEventListener(
465 | "pointerdown",
466 | this.onPointerDown,
467 | false
468 | );
469 | this.virtualScroll = new VirtualScroll(eventsTarget, {
470 | touchMultiplier,
471 | wheelMultiplier
472 | });
473 | this.virtualScroll.on("scroll", this.onVirtualScroll);
474 | if (this.options.autoToggle) {
475 | this.rootElement.addEventListener("transitionend", this.onTransitionEnd, {
476 | passive: true
477 | });
478 | }
479 | if (this.options.autoRaf) {
480 | this.__rafID = requestAnimationFrame(this.raf);
481 | }
482 | }
483 | /**
484 | * Destroy the lenis instance, remove all event listeners and clean up the class name
485 | */
486 | destroy() {
487 | this.emitter.destroy();
488 | this.options.wrapper.removeEventListener(
489 | "scroll",
490 | this.onNativeScroll,
491 | false
492 | );
493 | this.options.wrapper.removeEventListener("scrollend", this.onScrollEnd, {
494 | capture: true
495 | });
496 | this.options.wrapper.removeEventListener(
497 | "pointerdown",
498 | this.onPointerDown,
499 | false
500 | );
501 | if (this.options.anchors && this.options.wrapper === window) {
502 | this.options.wrapper.removeEventListener(
503 | "click",
504 | this.onClick,
505 | false
506 | );
507 | }
508 | this.virtualScroll.destroy();
509 | this.dimensions.destroy();
510 | this.cleanUpClassName();
511 | if (this.__rafID) {
512 | cancelAnimationFrame(this.__rafID);
513 | }
514 | }
515 | on(event, callback) {
516 | return this.emitter.on(event, callback);
517 | }
518 | off(event, callback) {
519 | return this.emitter.off(event, callback);
520 | }
521 | onScrollEnd = (e) => {
522 | if (!(e instanceof CustomEvent)) {
523 | if (this.isScrolling === "smooth" || this.isScrolling === false) {
524 | e.stopPropagation();
525 | }
526 | }
527 | };
528 | dispatchScrollendEvent = () => {
529 | this.options.wrapper.dispatchEvent(
530 | new CustomEvent("scrollend", {
531 | bubbles: this.options.wrapper === window,
532 | // cancelable: false,
533 | detail: {
534 | lenisScrollEnd: true
535 | }
536 | })
537 | );
538 | };
539 | onTransitionEnd = (event) => {
540 | if (event.propertyName.includes("overflow")) {
541 | const property = this.isHorizontal ? "overflow-x" : "overflow-y";
542 | const overflow = getComputedStyle(this.rootElement)[property];
543 | if (["hidden", "clip"].includes(overflow)) {
544 | this.stop();
545 | } else {
546 | this.start();
547 | }
548 | }
549 | };
550 | setScroll(scroll) {
551 | if (this.isHorizontal) {
552 | this.options.wrapper.scrollTo({ left: scroll, behavior: "instant" });
553 | } else {
554 | this.options.wrapper.scrollTo({ top: scroll, behavior: "instant" });
555 | }
556 | }
557 | onClick = (event) => {
558 | const path = event.composedPath();
559 | const anchor = path.find(
560 | (node) => node instanceof HTMLAnchorElement && (node.getAttribute("href")?.startsWith("#") || node.getAttribute("href")?.startsWith("/#") || node.getAttribute("href")?.startsWith("./#"))
561 | );
562 | if (anchor) {
563 | const id = anchor.getAttribute("href");
564 | if (id) {
565 | const options = typeof this.options.anchors === "object" && this.options.anchors ? this.options.anchors : void 0;
566 | let target = `#${id.split("#")[1]}`;
567 | if (["#", "/#", "./#", "#top", "/#top", "./#top"].includes(id)) {
568 | target = 0;
569 | }
570 | this.scrollTo(target, options);
571 | }
572 | }
573 | };
574 | onPointerDown = (event) => {
575 | if (event.button === 1) {
576 | this.reset();
577 | }
578 | };
579 | onVirtualScroll = (data) => {
580 | if (typeof this.options.virtualScroll === "function" && this.options.virtualScroll(data) === false)
581 | return;
582 | const { deltaX, deltaY, event } = data;
583 | this.emitter.emit("virtual-scroll", { deltaX, deltaY, event });
584 | if (event.ctrlKey) return;
585 | if (event.lenisStopPropagation) return;
586 | const isTouch = event.type.includes("touch");
587 | const isWheel = event.type.includes("wheel");
588 | this.isTouching = event.type === "touchstart" || event.type === "touchmove";
589 | const isClickOrTap = deltaX === 0 && deltaY === 0;
590 | const isTapToStop = this.options.syncTouch && isTouch && event.type === "touchstart" && isClickOrTap && !this.isStopped && !this.isLocked;
591 | if (isTapToStop) {
592 | this.reset();
593 | return;
594 | }
595 | const isUnknownGesture = this.options.gestureOrientation === "vertical" && deltaY === 0 || this.options.gestureOrientation === "horizontal" && deltaX === 0;
596 | if (isClickOrTap || isUnknownGesture) {
597 | return;
598 | }
599 | let composedPath = event.composedPath();
600 | composedPath = composedPath.slice(0, composedPath.indexOf(this.rootElement));
601 | const prevent = this.options.prevent;
602 | if (!!composedPath.find(
603 | (node) => node instanceof HTMLElement && (typeof prevent === "function" && prevent?.(node) || node.hasAttribute?.("data-lenis-prevent") || isTouch && node.hasAttribute?.("data-lenis-prevent-touch") || isWheel && node.hasAttribute?.("data-lenis-prevent-wheel") || this.options.allowNestedScroll && this.checkNestedScroll(node, { deltaX, deltaY }))
604 | ))
605 | return;
606 | if (this.isStopped || this.isLocked) {
607 | event.preventDefault();
608 | return;
609 | }
610 | const isSmooth = this.options.syncTouch && isTouch || this.options.smoothWheel && isWheel;
611 | if (!isSmooth) {
612 | this.isScrolling = "native";
613 | this.animate.stop();
614 | event.lenisStopPropagation = true;
615 | return;
616 | }
617 | let delta = deltaY;
618 | if (this.options.gestureOrientation === "both") {
619 | delta = Math.abs(deltaY) > Math.abs(deltaX) ? deltaY : deltaX;
620 | } else if (this.options.gestureOrientation === "horizontal") {
621 | delta = deltaX;
622 | }
623 | if (!this.options.overscroll || this.options.infinite || this.options.wrapper !== window && (this.animatedScroll > 0 && this.animatedScroll < this.limit || this.animatedScroll === 0 && deltaY > 0 || this.animatedScroll === this.limit && deltaY < 0)) {
624 | event.lenisStopPropagation = true;
625 | }
626 | event.preventDefault();
627 | const isSyncTouch = isTouch && this.options.syncTouch;
628 | const isTouchEnd = isTouch && event.type === "touchend";
629 | const hasTouchInertia = isTouchEnd && Math.abs(delta) > 5;
630 | if (hasTouchInertia) {
631 | delta = this.velocity * this.options.touchInertiaMultiplier;
632 | }
633 | this.scrollTo(this.targetScroll + delta, {
634 | programmatic: false,
635 | ...isSyncTouch ? {
636 | lerp: hasTouchInertia ? this.options.syncTouchLerp : 1
637 | // immediate: !hasTouchInertia,
638 | } : {
639 | lerp: this.options.lerp,
640 | duration: this.options.duration,
641 | easing: this.options.easing
642 | }
643 | });
644 | };
645 | /**
646 | * Force lenis to recalculate the dimensions
647 | */
648 | resize() {
649 | this.dimensions.resize();
650 | this.animatedScroll = this.targetScroll = this.actualScroll;
651 | this.emit();
652 | }
653 | emit() {
654 | this.emitter.emit("scroll", this);
655 | }
656 | onNativeScroll = () => {
657 | if (this._resetVelocityTimeout !== null) {
658 | clearTimeout(this._resetVelocityTimeout);
659 | this._resetVelocityTimeout = null;
660 | }
661 | if (this._preventNextNativeScrollEvent) {
662 | this._preventNextNativeScrollEvent = false;
663 | return;
664 | }
665 | if (this.isScrolling === false || this.isScrolling === "native") {
666 | const lastScroll = this.animatedScroll;
667 | this.animatedScroll = this.targetScroll = this.actualScroll;
668 | this.lastVelocity = this.velocity;
669 | this.velocity = this.animatedScroll - lastScroll;
670 | this.direction = Math.sign(
671 | this.animatedScroll - lastScroll
672 | );
673 | if (!this.isStopped) {
674 | this.isScrolling = "native";
675 | }
676 | this.emit();
677 | if (this.velocity !== 0) {
678 | this._resetVelocityTimeout = setTimeout(() => {
679 | this.lastVelocity = this.velocity;
680 | this.velocity = 0;
681 | this.isScrolling = false;
682 | this.emit();
683 | }, 400);
684 | }
685 | }
686 | };
687 | reset() {
688 | this.isLocked = false;
689 | this.isScrolling = false;
690 | this.animatedScroll = this.targetScroll = this.actualScroll;
691 | this.lastVelocity = this.velocity = 0;
692 | this.animate.stop();
693 | }
694 | /**
695 | * Start lenis scroll after it has been stopped
696 | */
697 | start() {
698 | if (!this.isStopped) return;
699 | this.reset();
700 | this.isStopped = false;
701 | }
702 | /**
703 | * Stop lenis scroll
704 | */
705 | stop() {
706 | if (this.isStopped) return;
707 | this.reset();
708 | this.isStopped = true;
709 | }
710 | /**
711 | * RequestAnimationFrame for lenis
712 | *
713 | * @param time The time in ms from an external clock like `requestAnimationFrame` or Tempus
714 | */
715 | raf = (time) => {
716 | const deltaTime = time - (this.time || time);
717 | this.time = time;
718 | this.animate.advance(deltaTime * 1e-3);
719 | if (this.options.autoRaf) {
720 | this.__rafID = requestAnimationFrame(this.raf);
721 | }
722 | };
723 | /**
724 | * Scroll to a target value
725 | *
726 | * @param target The target value to scroll to
727 | * @param options The options for the scroll
728 | *
729 | * @example
730 | * lenis.scrollTo(100, {
731 | * offset: 100,
732 | * duration: 1,
733 | * easing: (t) => 1 - Math.cos((t * Math.PI) / 2),
734 | * lerp: 0.1,
735 | * onStart: () => {
736 | * console.log('onStart')
737 | * },
738 | * onComplete: () => {
739 | * console.log('onComplete')
740 | * },
741 | * })
742 | */
743 | scrollTo(target, {
744 | offset = 0,
745 | immediate = false,
746 | lock = false,
747 | duration = this.options.duration,
748 | easing = this.options.easing,
749 | lerp: lerp2 = this.options.lerp,
750 | onStart,
751 | onComplete,
752 | force = false,
753 | // scroll even if stopped
754 | programmatic = true,
755 | // called from outside of the class
756 | userData
757 | } = {}) {
758 | if ((this.isStopped || this.isLocked) && !force) return;
759 | if (typeof target === "string" && ["top", "left", "start"].includes(target)) {
760 | target = 0;
761 | } else if (typeof target === "string" && ["bottom", "right", "end"].includes(target)) {
762 | target = this.limit;
763 | } else {
764 | let node;
765 | if (typeof target === "string") {
766 | node = document.querySelector(target);
767 | } else if (target instanceof HTMLElement && target?.nodeType) {
768 | node = target;
769 | }
770 | if (node) {
771 | if (this.options.wrapper !== window) {
772 | const wrapperRect = this.rootElement.getBoundingClientRect();
773 | offset -= this.isHorizontal ? wrapperRect.left : wrapperRect.top;
774 | }
775 | const rect = node.getBoundingClientRect();
776 | target = (this.isHorizontal ? rect.left : rect.top) + this.animatedScroll;
777 | }
778 | }
779 | if (typeof target !== "number") return;
780 | target += offset;
781 | target = Math.round(target);
782 | if (this.options.infinite) {
783 | if (programmatic) {
784 | this.targetScroll = this.animatedScroll = this.scroll;
785 | const distance = target - this.animatedScroll;
786 | if (distance > this.limit / 2) {
787 | target = target - this.limit;
788 | } else if (distance < -this.limit / 2) {
789 | target = target + this.limit;
790 | }
791 | }
792 | } else {
793 | target = clamp(0, target, this.limit);
794 | }
795 | if (target === this.targetScroll) {
796 | onStart?.(this);
797 | onComplete?.(this);
798 | return;
799 | }
800 | this.userData = userData ?? {};
801 | if (immediate) {
802 | this.animatedScroll = this.targetScroll = target;
803 | this.setScroll(this.scroll);
804 | this.reset();
805 | this.preventNextNativeScrollEvent();
806 | this.emit();
807 | onComplete?.(this);
808 | this.userData = {};
809 | requestAnimationFrame(() => {
810 | this.dispatchScrollendEvent();
811 | });
812 | return;
813 | }
814 | if (!programmatic) {
815 | this.targetScroll = target;
816 | }
817 | this.animate.fromTo(this.animatedScroll, target, {
818 | duration,
819 | easing,
820 | lerp: lerp2,
821 | onStart: () => {
822 | if (lock) this.isLocked = true;
823 | this.isScrolling = "smooth";
824 | onStart?.(this);
825 | },
826 | onUpdate: (value, completed) => {
827 | this.isScrolling = "smooth";
828 | this.lastVelocity = this.velocity;
829 | this.velocity = value - this.animatedScroll;
830 | this.direction = Math.sign(this.velocity);
831 | this.animatedScroll = value;
832 | this.setScroll(this.scroll);
833 | if (programmatic) {
834 | this.targetScroll = value;
835 | }
836 | if (!completed) this.emit();
837 | if (completed) {
838 | this.reset();
839 | this.emit();
840 | onComplete?.(this);
841 | this.userData = {};
842 | requestAnimationFrame(() => {
843 | this.dispatchScrollendEvent();
844 | });
845 | this.preventNextNativeScrollEvent();
846 | }
847 | }
848 | });
849 | }
850 | preventNextNativeScrollEvent() {
851 | this._preventNextNativeScrollEvent = true;
852 | requestAnimationFrame(() => {
853 | this._preventNextNativeScrollEvent = false;
854 | });
855 | }
856 | checkNestedScroll(node, { deltaX, deltaY }) {
857 | const time = Date.now();
858 | const cache = node._lenis ??= {};
859 | let hasOverflowX, hasOverflowY, isScrollableX, isScrollableY, scrollWidth, scrollHeight, clientWidth, clientHeight;
860 | const gestureOrientation = this.options.gestureOrientation;
861 | if (time - (cache.time ?? 0) > 2e3) {
862 | cache.time = Date.now();
863 | const computedStyle = window.getComputedStyle(node);
864 | cache.computedStyle = computedStyle;
865 | const overflowXString = computedStyle.overflowX;
866 | const overflowYString = computedStyle.overflowY;
867 | hasOverflowX = ["auto", "overlay", "scroll"].includes(overflowXString);
868 | hasOverflowY = ["auto", "overlay", "scroll"].includes(overflowYString);
869 | cache.hasOverflowX = hasOverflowX;
870 | cache.hasOverflowY = hasOverflowY;
871 | if (!hasOverflowX && !hasOverflowY) return false;
872 | if (gestureOrientation === "vertical" && !hasOverflowY) return false;
873 | if (gestureOrientation === "horizontal" && !hasOverflowX) return false;
874 | scrollWidth = node.scrollWidth;
875 | scrollHeight = node.scrollHeight;
876 | clientWidth = node.clientWidth;
877 | clientHeight = node.clientHeight;
878 | isScrollableX = scrollWidth > clientWidth;
879 | isScrollableY = scrollHeight > clientHeight;
880 | cache.isScrollableX = isScrollableX;
881 | cache.isScrollableY = isScrollableY;
882 | cache.scrollWidth = scrollWidth;
883 | cache.scrollHeight = scrollHeight;
884 | cache.clientWidth = clientWidth;
885 | cache.clientHeight = clientHeight;
886 | } else {
887 | isScrollableX = cache.isScrollableX;
888 | isScrollableY = cache.isScrollableY;
889 | hasOverflowX = cache.hasOverflowX;
890 | hasOverflowY = cache.hasOverflowY;
891 | scrollWidth = cache.scrollWidth;
892 | scrollHeight = cache.scrollHeight;
893 | clientWidth = cache.clientWidth;
894 | clientHeight = cache.clientHeight;
895 | }
896 | if (!hasOverflowX && !hasOverflowY || !isScrollableX && !isScrollableY) {
897 | return false;
898 | }
899 | if (gestureOrientation === "vertical" && (!hasOverflowY || !isScrollableY))
900 | return false;
901 | if (gestureOrientation === "horizontal" && (!hasOverflowX || !isScrollableX))
902 | return false;
903 | let orientation;
904 | if (gestureOrientation === "horizontal") {
905 | orientation = "x";
906 | } else if (gestureOrientation === "vertical") {
907 | orientation = "y";
908 | } else {
909 | const isScrollingX = deltaX !== 0;
910 | const isScrollingY = deltaY !== 0;
911 | if (isScrollingX && hasOverflowX && isScrollableX) {
912 | orientation = "x";
913 | }
914 | if (isScrollingY && hasOverflowY && isScrollableY) {
915 | orientation = "y";
916 | }
917 | }
918 | if (!orientation) return false;
919 | let scroll, maxScroll, delta, hasOverflow, isScrollable;
920 | if (orientation === "x") {
921 | scroll = node.scrollLeft;
922 | maxScroll = scrollWidth - clientWidth;
923 | delta = deltaX;
924 | hasOverflow = hasOverflowX;
925 | isScrollable = isScrollableX;
926 | } else if (orientation === "y") {
927 | scroll = node.scrollTop;
928 | maxScroll = scrollHeight - clientHeight;
929 | delta = deltaY;
930 | hasOverflow = hasOverflowY;
931 | isScrollable = isScrollableY;
932 | } else {
933 | return false;
934 | }
935 | const willScroll = delta > 0 ? scroll < maxScroll : scroll > 0;
936 | return willScroll && hasOverflow && isScrollable;
937 | }
938 | /**
939 | * The root element on which lenis is instanced
940 | */
941 | get rootElement() {
942 | return this.options.wrapper === window ? document.documentElement : this.options.wrapper;
943 | }
944 | /**
945 | * The limit which is the maximum scroll value
946 | */
947 | get limit() {
948 | if (this.options.__experimental__naiveDimensions) {
949 | if (this.isHorizontal) {
950 | return this.rootElement.scrollWidth - this.rootElement.clientWidth;
951 | } else {
952 | return this.rootElement.scrollHeight - this.rootElement.clientHeight;
953 | }
954 | } else {
955 | return this.dimensions.limit[this.isHorizontal ? "x" : "y"];
956 | }
957 | }
958 | /**
959 | * Whether or not the scroll is horizontal
960 | */
961 | get isHorizontal() {
962 | return this.options.orientation === "horizontal";
963 | }
964 | /**
965 | * The actual scroll value
966 | */
967 | get actualScroll() {
968 | const wrapper = this.options.wrapper;
969 | return this.isHorizontal ? wrapper.scrollX ?? wrapper.scrollLeft : wrapper.scrollY ?? wrapper.scrollTop;
970 | }
971 | /**
972 | * The current scroll value
973 | */
974 | get scroll() {
975 | return this.options.infinite ? modulo(this.animatedScroll, this.limit) : this.animatedScroll;
976 | }
977 | /**
978 | * The progress of the scroll relative to the limit
979 | */
980 | get progress() {
981 | return this.limit === 0 ? 1 : this.scroll / this.limit;
982 | }
983 | /**
984 | * Current scroll state
985 | */
986 | get isScrolling() {
987 | return this._isScrolling;
988 | }
989 | set isScrolling(value) {
990 | if (this._isScrolling !== value) {
991 | this._isScrolling = value;
992 | this.updateClassName();
993 | }
994 | }
995 | /**
996 | * Check if lenis is stopped
997 | */
998 | get isStopped() {
999 | return this._isStopped;
1000 | }
1001 | set isStopped(value) {
1002 | if (this._isStopped !== value) {
1003 | this._isStopped = value;
1004 | this.updateClassName();
1005 | }
1006 | }
1007 | /**
1008 | * Check if lenis is locked
1009 | */
1010 | get isLocked() {
1011 | return this._isLocked;
1012 | }
1013 | set isLocked(value) {
1014 | if (this._isLocked !== value) {
1015 | this._isLocked = value;
1016 | this.updateClassName();
1017 | }
1018 | }
1019 | /**
1020 | * Check if lenis is smooth scrolling
1021 | */
1022 | get isSmooth() {
1023 | return this.isScrolling === "smooth";
1024 | }
1025 | /**
1026 | * The class name applied to the wrapper element
1027 | */
1028 | get className() {
1029 | let className = "lenis";
1030 | if (this.options.autoToggle) className += " lenis-autoToggle";
1031 | if (this.isStopped) className += " lenis-stopped";
1032 | if (this.isLocked) className += " lenis-locked";
1033 | if (this.isScrolling) className += " lenis-scrolling";
1034 | if (this.isScrolling === "smooth") className += " lenis-smooth";
1035 | return className;
1036 | }
1037 | updateClassName() {
1038 | this.cleanUpClassName();
1039 | this.rootElement.className = `${this.rootElement.className} ${this.className}`.trim();
1040 | }
1041 | cleanUpClassName() {
1042 | this.rootElement.className = this.rootElement.className.replace(/lenis(-\w+)?/g, "").trim();
1043 | }
1044 | };
1045 |
1046 | class FeatherScroll {
1047 | // Stores all instances of FeatherScroll
1048 | static instances = [];
1049 | constructor(options = {}) {
1050 | this.wrapper = options.wrapper || document.documentElement;
1051 | this.content = options.content || document.body;
1052 | // Initialize Lenis with custom options or defaults
1053 | this.lenis = new Lenis({
1054 | wrapper: this.wrapper,
1055 | content: this.content,
1056 | smooth: options.smooth ?? true,
1057 | duration: options.duration ?? 1.2,
1058 | easing: options.easing ?? ((t) => 1 - Math.pow(1 - t, 3)),
1059 | direction: options.direction ?? 'vertical',
1060 | gestureDirection: options.gestureDirection ?? 'both',
1061 | wheelMultiplier: options.mouseSenstivity ?? 1,
1062 | touchMultiplier: options.touchSenstivity ?? 2,
1063 | infinite: options.infinite ?? false
1064 | });
1065 | // Scroll direction tracking
1066 | this.scrollDirection = 'down';
1067 | this.lastScroll = 0;
1068 | // Elements with sticky and parallax behavior
1069 | this.stickyElements = [...this.content.querySelectorAll('[data-scroll-sticky]')];
1070 | this.parallaxElements = [...this.content.querySelectorAll('[data-scroll-speed]')];
1071 | // Store initial positions for parallax elements
1072 | this.parallaxElements.forEach((el) => {
1073 | const rect = el.getBoundingClientRect();
1074 | el.dataset.initialTop = rect.top + window.scrollY;
1075 | el.dataset.initialLeft = rect.left + window.scrollX;
1076 | });
1077 | // Initialize features
1078 | this.initStickyElements();
1079 | this.trackScrollDirection();
1080 | this.startRAF(); // Start animation loop
1081 | FeatherScroll.instances.push(this); // Register instance
1082 | if (window.ScrollTrigger) {
1083 | this.setupScrollTrigger();
1084 | }
1085 | // Observe body overflow for automatic disabling
1086 | this.observeBodyOverflow();
1087 | }
1088 | // RAF loop for Lenis + sticky + parallax
1089 | startRAF() {
1090 | const raf = (time) => {
1091 | this.lenis.raf(time);
1092 | this.updateStickyElements();
1093 | this.updateParallax();
1094 | requestAnimationFrame(raf);
1095 | };
1096 | requestAnimationFrame(raf);
1097 | }
1098 | // Detect scroll direction: 'up' or 'down'
1099 | trackScrollDirection() {
1100 | this.lenis.on('scroll', ({ scroll }) => {
1101 | const newDirection = scroll > this.lastScroll ? 'down' : 'up';
1102 | if (newDirection !== this.scrollDirection) {
1103 | this.scrollDirection = newDirection;
1104 | }
1105 | this.lastScroll = scroll;
1106 | });
1107 | }
1108 | // Observe overflow-y on body, pause/resume Lenis
1109 | observeBodyOverflow() {
1110 | const observer = new MutationObserver(() => {
1111 | const overflowY = window.getComputedStyle(document.body).overflowY;
1112 | if (overflowY === 'hidden') {
1113 | this.lenis.stop();
1114 | } else {
1115 | this.lenis.start();
1116 | }
1117 | });
1118 | observer.observe(document.body, {
1119 | attributes: true,
1120 | attributeFilter: ['style']
1121 | });
1122 | // Initial check
1123 | const initialOverflowY = window.getComputedStyle(document.body).overflowY;
1124 | if (initialOverflowY === 'hidden') {
1125 | this.lenis.stop();
1126 | }
1127 | }
1128 | // Return current scroll direction
1129 | getScrollDirection() {
1130 | return this.scrollDirection || 'down';
1131 | }
1132 | // Set initial positions for sticky elements
1133 | initStickyElements() {
1134 | this.stickyElements.forEach((el) => {
1135 | const parent = el.parentElement;
1136 | const rect = el.getBoundingClientRect();
1137 | el.dataset.stickyStart = parent.offsetTop;
1138 | el.dataset.stickyEnd = parent.offsetTop + parent.offsetHeight;
1139 | el.dataset.originalWidth = `${rect.width}px`;
1140 | el.dataset.originalHeight = `${rect.height}px`;
1141 | });
1142 | }
1143 | // Update sticky element positions
1144 | updateStickyElements() {
1145 | const scrollY = this.lenis.scroll;
1146 | const viewportHeight = window.innerHeight;
1147 | this.stickyElements.forEach((el) => {
1148 | const parent = el.parentElement;
1149 | const nextSibling = parent.nextElementSibling;
1150 | if (!nextSibling) return;
1151 | const stickyStart = parseFloat(el.dataset.stickyStart);
1152 | const stickyEnd = parseFloat(el.dataset.stickyEnd);
1153 | const parentRect = parent.getBoundingClientRect();
1154 | const nextRect = nextSibling.getBoundingClientRect();
1155 | // If next section enters halfway viewport, stop sticking
1156 | const isNextEntering = nextRect.top < viewportHeight * 0.5;
1157 | if (scrollY >= stickyStart && scrollY < stickyEnd && !isNextEntering) {
1158 | el.style.position = 'fixed';
1159 | el.style.top = `${window.innerHeight / 2 - el.offsetHeight / 2}px`;
1160 | el.style.left = `${parentRect.left + parentRect.width / 2 - el.offsetWidth / 2}px`;
1161 | el.style.opacity = '1';
1162 | } else {
1163 | el.style.position = 'relative';
1164 | el.style.opacity = '0';
1165 | }
1166 | });
1167 | }
1168 | // Apply parallax effect based on data attributes
1169 | updateParallax() {
1170 | const scrollY = this.lenis.scroll;
1171 | this.parallaxElements.forEach((el) => {
1172 | const speed = parseFloat(el.getAttribute("data-scroll-speed")) || 1;
1173 | const direction = el.getAttribute("data-scroll-direction") || "vertical";
1174 | const initialTop = parseFloat(el.dataset.initialTop);
1175 | parseFloat(el.dataset.initialLeft);
1176 | let offsetX = 0, offsetY = 0;
1177 | if (direction === "horizontal") {
1178 | offsetX = (scrollY - initialTop) * speed * 0.1;
1179 | } else if (direction === "vertical") {
1180 | offsetY = (scrollY - initialTop) * speed * 0.1;
1181 | } else if (direction === "both") {
1182 | offsetX = (scrollY - initialTop) * speed * 0.1;
1183 | offsetY = (scrollY - initialTop) * speed * 0.1;
1184 | }
1185 | // If GSAP is present, respect GSAP transforms
1186 | let gsapX = 0, gsapY = 0;
1187 | if (window.gsap) {
1188 | gsapX = gsap.getProperty(el, "x") || 0;
1189 | gsapY = gsap.getProperty(el, "y") || 0;
1190 | }
1191 | el.style.transform = `translate3d(${offsetX + gsapX}px, ${offsetY + gsapY}px, 0)`;
1192 | });
1193 | }
1194 | // Integration with GSAP ScrollTrigger
1195 | setupScrollTrigger() {
1196 | this.lenis.on('scroll', () => {
1197 | ScrollTrigger.update();
1198 | });
1199 | }
1200 | // Public method: Scroll to a target
1201 | scrollTo(target, options = {}) {
1202 | this.lenis.scrollTo(target, options);
1203 | }
1204 | // Public method: Start scrolling
1205 | start() {
1206 | this.lenis.start();
1207 | }
1208 | // Public method: Stop scrolling
1209 | stop() {
1210 | this.lenis.stop();
1211 | }
1212 | // Public method: Destroy the instance
1213 | destroy() {
1214 | this.lenis.destroy();
1215 | FeatherScroll.instances = FeatherScroll.instances.filter((instance) => instance !== this);
1216 | }
1217 | // Public method: Get scroll position
1218 | getScrollPosition() {
1219 | return this.lenis.scroll;
1220 | }
1221 | // Update Lenis options dynamically
1222 | updateOptions(newOptions) {
1223 | Object.assign(this.lenis.options, newOptions);
1224 | }
1225 | }
1226 |
1227 | // Also attach to window for CDN users
1228 | if (typeof window !== 'undefined') {
1229 | window.FeatherScroll = FeatherScroll;
1230 | }
1231 |
1232 | export { FeatherScroll as default };
1233 | //# sourceMappingURL=featherScroll.esm.js.map
1234 |
--------------------------------------------------------------------------------
/dist/featherScroll.esm.js.map:
--------------------------------------------------------------------------------
1 | {"version":3,"file":"featherScroll.esm.js","sources":["../node_modules/lenis/dist/lenis.mjs","../src/featherScroll.js"],"sourcesContent":["// package.json\nvar version = \"1.3.1\";\n\n// packages/core/src/maths.ts\nfunction clamp(min, input, max) {\n return Math.max(min, Math.min(input, max));\n}\nfunction lerp(x, y, t) {\n return (1 - t) * x + t * y;\n}\nfunction damp(x, y, lambda, deltaTime) {\n return lerp(x, y, 1 - Math.exp(-lambda * deltaTime));\n}\nfunction modulo(n, d) {\n return (n % d + d) % d;\n}\n\n// packages/core/src/animate.ts\nvar Animate = class {\n isRunning = false;\n value = 0;\n from = 0;\n to = 0;\n currentTime = 0;\n // These are instanciated in the fromTo method\n lerp;\n duration;\n easing;\n onUpdate;\n /**\n * Advance the animation by the given delta time\n *\n * @param deltaTime - The time in seconds to advance the animation\n */\n advance(deltaTime) {\n if (!this.isRunning) return;\n let completed = false;\n if (this.duration && this.easing) {\n this.currentTime += deltaTime;\n const linearProgress = clamp(0, this.currentTime / this.duration, 1);\n completed = linearProgress >= 1;\n const easedProgress = completed ? 1 : this.easing(linearProgress);\n this.value = this.from + (this.to - this.from) * easedProgress;\n } else if (this.lerp) {\n this.value = damp(this.value, this.to, this.lerp * 60, deltaTime);\n if (Math.round(this.value) === this.to) {\n this.value = this.to;\n completed = true;\n }\n } else {\n this.value = this.to;\n completed = true;\n }\n if (completed) {\n this.stop();\n }\n this.onUpdate?.(this.value, completed);\n }\n /** Stop the animation */\n stop() {\n this.isRunning = false;\n }\n /**\n * Set up the animation from a starting value to an ending value\n * with optional parameters for lerping, duration, easing, and onUpdate callback\n *\n * @param from - The starting value\n * @param to - The ending value\n * @param options - Options for the animation\n */\n fromTo(from, to, { lerp: lerp2, duration, easing, onStart, onUpdate }) {\n this.from = this.value = from;\n this.to = to;\n this.lerp = lerp2;\n this.duration = duration;\n this.easing = easing;\n this.currentTime = 0;\n this.isRunning = true;\n onStart?.();\n this.onUpdate = onUpdate;\n }\n};\n\n// packages/core/src/debounce.ts\nfunction debounce(callback, delay) {\n let timer;\n return function(...args) {\n let context = this;\n clearTimeout(timer);\n timer = setTimeout(() => {\n timer = void 0;\n callback.apply(context, args);\n }, delay);\n };\n}\n\n// packages/core/src/dimensions.ts\nvar Dimensions = class {\n constructor(wrapper, content, { autoResize = true, debounce: debounceValue = 250 } = {}) {\n this.wrapper = wrapper;\n this.content = content;\n if (autoResize) {\n this.debouncedResize = debounce(this.resize, debounceValue);\n if (this.wrapper instanceof Window) {\n window.addEventListener(\"resize\", this.debouncedResize, false);\n } else {\n this.wrapperResizeObserver = new ResizeObserver(this.debouncedResize);\n this.wrapperResizeObserver.observe(this.wrapper);\n }\n this.contentResizeObserver = new ResizeObserver(this.debouncedResize);\n this.contentResizeObserver.observe(this.content);\n }\n this.resize();\n }\n width = 0;\n height = 0;\n scrollHeight = 0;\n scrollWidth = 0;\n // These are instanciated in the constructor as they need information from the options\n debouncedResize;\n wrapperResizeObserver;\n contentResizeObserver;\n destroy() {\n this.wrapperResizeObserver?.disconnect();\n this.contentResizeObserver?.disconnect();\n if (this.wrapper === window && this.debouncedResize) {\n window.removeEventListener(\"resize\", this.debouncedResize, false);\n }\n }\n resize = () => {\n this.onWrapperResize();\n this.onContentResize();\n };\n onWrapperResize = () => {\n if (this.wrapper instanceof Window) {\n this.width = window.innerWidth;\n this.height = window.innerHeight;\n } else {\n this.width = this.wrapper.clientWidth;\n this.height = this.wrapper.clientHeight;\n }\n };\n onContentResize = () => {\n if (this.wrapper instanceof Window) {\n this.scrollHeight = this.content.scrollHeight;\n this.scrollWidth = this.content.scrollWidth;\n } else {\n this.scrollHeight = this.wrapper.scrollHeight;\n this.scrollWidth = this.wrapper.scrollWidth;\n }\n };\n get limit() {\n return {\n x: this.scrollWidth - this.width,\n y: this.scrollHeight - this.height\n };\n }\n};\n\n// packages/core/src/emitter.ts\nvar Emitter = class {\n events = {};\n /**\n * Emit an event with the given data\n * @param event Event name\n * @param args Data to pass to the event handlers\n */\n emit(event, ...args) {\n let callbacks = this.events[event] || [];\n for (let i = 0, length = callbacks.length; i < length; i++) {\n callbacks[i]?.(...args);\n }\n }\n /**\n * Add a callback to the event\n * @param event Event name\n * @param cb Callback function\n * @returns Unsubscribe function\n */\n on(event, cb) {\n this.events[event]?.push(cb) || (this.events[event] = [cb]);\n return () => {\n this.events[event] = this.events[event]?.filter((i) => cb !== i);\n };\n }\n /**\n * Remove a callback from the event\n * @param event Event name\n * @param callback Callback function\n */\n off(event, callback) {\n this.events[event] = this.events[event]?.filter((i) => callback !== i);\n }\n /**\n * Remove all event listeners and clean up\n */\n destroy() {\n this.events = {};\n }\n};\n\n// packages/core/src/virtual-scroll.ts\nvar LINE_HEIGHT = 100 / 6;\nvar listenerOptions = { passive: false };\nvar VirtualScroll = class {\n constructor(element, options = { wheelMultiplier: 1, touchMultiplier: 1 }) {\n this.element = element;\n this.options = options;\n window.addEventListener(\"resize\", this.onWindowResize, false);\n this.onWindowResize();\n this.element.addEventListener(\"wheel\", this.onWheel, listenerOptions);\n this.element.addEventListener(\n \"touchstart\",\n this.onTouchStart,\n listenerOptions\n );\n this.element.addEventListener(\n \"touchmove\",\n this.onTouchMove,\n listenerOptions\n );\n this.element.addEventListener(\"touchend\", this.onTouchEnd, listenerOptions);\n }\n touchStart = {\n x: 0,\n y: 0\n };\n lastDelta = {\n x: 0,\n y: 0\n };\n window = {\n width: 0,\n height: 0\n };\n emitter = new Emitter();\n /**\n * Add an event listener for the given event and callback\n *\n * @param event Event name\n * @param callback Callback function\n */\n on(event, callback) {\n return this.emitter.on(event, callback);\n }\n /** Remove all event listeners and clean up */\n destroy() {\n this.emitter.destroy();\n window.removeEventListener(\"resize\", this.onWindowResize, false);\n this.element.removeEventListener(\"wheel\", this.onWheel, listenerOptions);\n this.element.removeEventListener(\n \"touchstart\",\n this.onTouchStart,\n listenerOptions\n );\n this.element.removeEventListener(\n \"touchmove\",\n this.onTouchMove,\n listenerOptions\n );\n this.element.removeEventListener(\n \"touchend\",\n this.onTouchEnd,\n listenerOptions\n );\n }\n /**\n * Event handler for 'touchstart' event\n *\n * @param event Touch event\n */\n onTouchStart = (event) => {\n const { clientX, clientY } = event.targetTouches ? event.targetTouches[0] : event;\n this.touchStart.x = clientX;\n this.touchStart.y = clientY;\n this.lastDelta = {\n x: 0,\n y: 0\n };\n this.emitter.emit(\"scroll\", {\n deltaX: 0,\n deltaY: 0,\n event\n });\n };\n /** Event handler for 'touchmove' event */\n onTouchMove = (event) => {\n const { clientX, clientY } = event.targetTouches ? event.targetTouches[0] : event;\n const deltaX = -(clientX - this.touchStart.x) * this.options.touchMultiplier;\n const deltaY = -(clientY - this.touchStart.y) * this.options.touchMultiplier;\n this.touchStart.x = clientX;\n this.touchStart.y = clientY;\n this.lastDelta = {\n x: deltaX,\n y: deltaY\n };\n this.emitter.emit(\"scroll\", {\n deltaX,\n deltaY,\n event\n });\n };\n onTouchEnd = (event) => {\n this.emitter.emit(\"scroll\", {\n deltaX: this.lastDelta.x,\n deltaY: this.lastDelta.y,\n event\n });\n };\n /** Event handler for 'wheel' event */\n onWheel = (event) => {\n let { deltaX, deltaY, deltaMode } = event;\n const multiplierX = deltaMode === 1 ? LINE_HEIGHT : deltaMode === 2 ? this.window.width : 1;\n const multiplierY = deltaMode === 1 ? LINE_HEIGHT : deltaMode === 2 ? this.window.height : 1;\n deltaX *= multiplierX;\n deltaY *= multiplierY;\n deltaX *= this.options.wheelMultiplier;\n deltaY *= this.options.wheelMultiplier;\n this.emitter.emit(\"scroll\", { deltaX, deltaY, event });\n };\n onWindowResize = () => {\n this.window = {\n width: window.innerWidth,\n height: window.innerHeight\n };\n };\n};\n\n// packages/core/src/lenis.ts\nvar Lenis = class {\n _isScrolling = false;\n // true when scroll is animating\n _isStopped = false;\n // true if user should not be able to scroll - enable/disable programmatically\n _isLocked = false;\n // same as isStopped but enabled/disabled when scroll reaches target\n _preventNextNativeScrollEvent = false;\n _resetVelocityTimeout = null;\n __rafID = null;\n /**\n * Whether or not the user is touching the screen\n */\n isTouching;\n /**\n * The time in ms since the lenis instance was created\n */\n time = 0;\n /**\n * User data that will be forwarded through the scroll event\n *\n * @example\n * lenis.scrollTo(100, {\n * userData: {\n * foo: 'bar'\n * }\n * })\n */\n userData = {};\n /**\n * The last velocity of the scroll\n */\n lastVelocity = 0;\n /**\n * The current velocity of the scroll\n */\n velocity = 0;\n /**\n * The direction of the scroll\n */\n direction = 0;\n /**\n * The options passed to the lenis instance\n */\n options;\n /**\n * The target scroll value\n */\n targetScroll;\n /**\n * The animated scroll value\n */\n animatedScroll;\n // These are instanciated here as they don't need information from the options\n animate = new Animate();\n emitter = new Emitter();\n // These are instanciated in the constructor as they need information from the options\n dimensions;\n // This is not private because it's used in the Snap class\n virtualScroll;\n constructor({\n wrapper = window,\n content = document.documentElement,\n eventsTarget = wrapper,\n smoothWheel = true,\n syncTouch = false,\n syncTouchLerp = 0.075,\n touchInertiaMultiplier = 35,\n duration,\n // in seconds\n easing = (t) => Math.min(1, 1.001 - Math.pow(2, -10 * t)),\n lerp: lerp2 = 0.1,\n infinite = false,\n orientation = \"vertical\",\n // vertical, horizontal\n gestureOrientation = \"vertical\",\n // vertical, horizontal, both\n touchMultiplier = 1,\n wheelMultiplier = 1,\n autoResize = true,\n prevent,\n virtualScroll,\n overscroll = true,\n autoRaf = false,\n anchors = false,\n autoToggle = false,\n // https://caniuse.com/?search=transition-behavior\n allowNestedScroll = false,\n __experimental__naiveDimensions = false\n } = {}) {\n window.lenisVersion = version;\n if (!wrapper || wrapper === document.documentElement) {\n wrapper = window;\n }\n this.options = {\n wrapper,\n content,\n eventsTarget,\n smoothWheel,\n syncTouch,\n syncTouchLerp,\n touchInertiaMultiplier,\n duration,\n easing,\n lerp: lerp2,\n infinite,\n gestureOrientation,\n orientation,\n touchMultiplier,\n wheelMultiplier,\n autoResize,\n prevent,\n virtualScroll,\n overscroll,\n autoRaf,\n anchors,\n autoToggle,\n allowNestedScroll,\n __experimental__naiveDimensions\n };\n this.dimensions = new Dimensions(wrapper, content, { autoResize });\n this.updateClassName();\n this.targetScroll = this.animatedScroll = this.actualScroll;\n this.options.wrapper.addEventListener(\"scroll\", this.onNativeScroll, false);\n this.options.wrapper.addEventListener(\"scrollend\", this.onScrollEnd, {\n capture: true\n });\n if (this.options.anchors && this.options.wrapper === window) {\n this.options.wrapper.addEventListener(\n \"click\",\n this.onClick,\n false\n );\n }\n this.options.wrapper.addEventListener(\n \"pointerdown\",\n this.onPointerDown,\n false\n );\n this.virtualScroll = new VirtualScroll(eventsTarget, {\n touchMultiplier,\n wheelMultiplier\n });\n this.virtualScroll.on(\"scroll\", this.onVirtualScroll);\n if (this.options.autoToggle) {\n this.rootElement.addEventListener(\"transitionend\", this.onTransitionEnd, {\n passive: true\n });\n }\n if (this.options.autoRaf) {\n this.__rafID = requestAnimationFrame(this.raf);\n }\n }\n /**\n * Destroy the lenis instance, remove all event listeners and clean up the class name\n */\n destroy() {\n this.emitter.destroy();\n this.options.wrapper.removeEventListener(\n \"scroll\",\n this.onNativeScroll,\n false\n );\n this.options.wrapper.removeEventListener(\"scrollend\", this.onScrollEnd, {\n capture: true\n });\n this.options.wrapper.removeEventListener(\n \"pointerdown\",\n this.onPointerDown,\n false\n );\n if (this.options.anchors && this.options.wrapper === window) {\n this.options.wrapper.removeEventListener(\n \"click\",\n this.onClick,\n false\n );\n }\n this.virtualScroll.destroy();\n this.dimensions.destroy();\n this.cleanUpClassName();\n if (this.__rafID) {\n cancelAnimationFrame(this.__rafID);\n }\n }\n on(event, callback) {\n return this.emitter.on(event, callback);\n }\n off(event, callback) {\n return this.emitter.off(event, callback);\n }\n onScrollEnd = (e) => {\n if (!(e instanceof CustomEvent)) {\n if (this.isScrolling === \"smooth\" || this.isScrolling === false) {\n e.stopPropagation();\n }\n }\n };\n dispatchScrollendEvent = () => {\n this.options.wrapper.dispatchEvent(\n new CustomEvent(\"scrollend\", {\n bubbles: this.options.wrapper === window,\n // cancelable: false,\n detail: {\n lenisScrollEnd: true\n }\n })\n );\n };\n onTransitionEnd = (event) => {\n if (event.propertyName.includes(\"overflow\")) {\n const property = this.isHorizontal ? \"overflow-x\" : \"overflow-y\";\n const overflow = getComputedStyle(this.rootElement)[property];\n if ([\"hidden\", \"clip\"].includes(overflow)) {\n this.stop();\n } else {\n this.start();\n }\n }\n };\n setScroll(scroll) {\n if (this.isHorizontal) {\n this.options.wrapper.scrollTo({ left: scroll, behavior: \"instant\" });\n } else {\n this.options.wrapper.scrollTo({ top: scroll, behavior: \"instant\" });\n }\n }\n onClick = (event) => {\n const path = event.composedPath();\n const anchor = path.find(\n (node) => node instanceof HTMLAnchorElement && (node.getAttribute(\"href\")?.startsWith(\"#\") || node.getAttribute(\"href\")?.startsWith(\"/#\") || node.getAttribute(\"href\")?.startsWith(\"./#\"))\n );\n if (anchor) {\n const id = anchor.getAttribute(\"href\");\n if (id) {\n const options = typeof this.options.anchors === \"object\" && this.options.anchors ? this.options.anchors : void 0;\n let target = `#${id.split(\"#\")[1]}`;\n if ([\"#\", \"/#\", \"./#\", \"#top\", \"/#top\", \"./#top\"].includes(id)) {\n target = 0;\n }\n this.scrollTo(target, options);\n }\n }\n };\n onPointerDown = (event) => {\n if (event.button === 1) {\n this.reset();\n }\n };\n onVirtualScroll = (data) => {\n if (typeof this.options.virtualScroll === \"function\" && this.options.virtualScroll(data) === false)\n return;\n const { deltaX, deltaY, event } = data;\n this.emitter.emit(\"virtual-scroll\", { deltaX, deltaY, event });\n if (event.ctrlKey) return;\n if (event.lenisStopPropagation) return;\n const isTouch = event.type.includes(\"touch\");\n const isWheel = event.type.includes(\"wheel\");\n this.isTouching = event.type === \"touchstart\" || event.type === \"touchmove\";\n const isClickOrTap = deltaX === 0 && deltaY === 0;\n const isTapToStop = this.options.syncTouch && isTouch && event.type === \"touchstart\" && isClickOrTap && !this.isStopped && !this.isLocked;\n if (isTapToStop) {\n this.reset();\n return;\n }\n const isUnknownGesture = this.options.gestureOrientation === \"vertical\" && deltaY === 0 || this.options.gestureOrientation === \"horizontal\" && deltaX === 0;\n if (isClickOrTap || isUnknownGesture) {\n return;\n }\n let composedPath = event.composedPath();\n composedPath = composedPath.slice(0, composedPath.indexOf(this.rootElement));\n const prevent = this.options.prevent;\n if (!!composedPath.find(\n (node) => node instanceof HTMLElement && (typeof prevent === \"function\" && prevent?.(node) || node.hasAttribute?.(\"data-lenis-prevent\") || isTouch && node.hasAttribute?.(\"data-lenis-prevent-touch\") || isWheel && node.hasAttribute?.(\"data-lenis-prevent-wheel\") || this.options.allowNestedScroll && this.checkNestedScroll(node, { deltaX, deltaY }))\n ))\n return;\n if (this.isStopped || this.isLocked) {\n event.preventDefault();\n return;\n }\n const isSmooth = this.options.syncTouch && isTouch || this.options.smoothWheel && isWheel;\n if (!isSmooth) {\n this.isScrolling = \"native\";\n this.animate.stop();\n event.lenisStopPropagation = true;\n return;\n }\n let delta = deltaY;\n if (this.options.gestureOrientation === \"both\") {\n delta = Math.abs(deltaY) > Math.abs(deltaX) ? deltaY : deltaX;\n } else if (this.options.gestureOrientation === \"horizontal\") {\n delta = deltaX;\n }\n if (!this.options.overscroll || this.options.infinite || this.options.wrapper !== window && (this.animatedScroll > 0 && this.animatedScroll < this.limit || this.animatedScroll === 0 && deltaY > 0 || this.animatedScroll === this.limit && deltaY < 0)) {\n event.lenisStopPropagation = true;\n }\n event.preventDefault();\n const isSyncTouch = isTouch && this.options.syncTouch;\n const isTouchEnd = isTouch && event.type === \"touchend\";\n const hasTouchInertia = isTouchEnd && Math.abs(delta) > 5;\n if (hasTouchInertia) {\n delta = this.velocity * this.options.touchInertiaMultiplier;\n }\n this.scrollTo(this.targetScroll + delta, {\n programmatic: false,\n ...isSyncTouch ? {\n lerp: hasTouchInertia ? this.options.syncTouchLerp : 1\n // immediate: !hasTouchInertia,\n } : {\n lerp: this.options.lerp,\n duration: this.options.duration,\n easing: this.options.easing\n }\n });\n };\n /**\n * Force lenis to recalculate the dimensions\n */\n resize() {\n this.dimensions.resize();\n this.animatedScroll = this.targetScroll = this.actualScroll;\n this.emit();\n }\n emit() {\n this.emitter.emit(\"scroll\", this);\n }\n onNativeScroll = () => {\n if (this._resetVelocityTimeout !== null) {\n clearTimeout(this._resetVelocityTimeout);\n this._resetVelocityTimeout = null;\n }\n if (this._preventNextNativeScrollEvent) {\n this._preventNextNativeScrollEvent = false;\n return;\n }\n if (this.isScrolling === false || this.isScrolling === \"native\") {\n const lastScroll = this.animatedScroll;\n this.animatedScroll = this.targetScroll = this.actualScroll;\n this.lastVelocity = this.velocity;\n this.velocity = this.animatedScroll - lastScroll;\n this.direction = Math.sign(\n this.animatedScroll - lastScroll\n );\n if (!this.isStopped) {\n this.isScrolling = \"native\";\n }\n this.emit();\n if (this.velocity !== 0) {\n this._resetVelocityTimeout = setTimeout(() => {\n this.lastVelocity = this.velocity;\n this.velocity = 0;\n this.isScrolling = false;\n this.emit();\n }, 400);\n }\n }\n };\n reset() {\n this.isLocked = false;\n this.isScrolling = false;\n this.animatedScroll = this.targetScroll = this.actualScroll;\n this.lastVelocity = this.velocity = 0;\n this.animate.stop();\n }\n /**\n * Start lenis scroll after it has been stopped\n */\n start() {\n if (!this.isStopped) return;\n this.reset();\n this.isStopped = false;\n }\n /**\n * Stop lenis scroll\n */\n stop() {\n if (this.isStopped) return;\n this.reset();\n this.isStopped = true;\n }\n /**\n * RequestAnimationFrame for lenis\n *\n * @param time The time in ms from an external clock like `requestAnimationFrame` or Tempus\n */\n raf = (time) => {\n const deltaTime = time - (this.time || time);\n this.time = time;\n this.animate.advance(deltaTime * 1e-3);\n if (this.options.autoRaf) {\n this.__rafID = requestAnimationFrame(this.raf);\n }\n };\n /**\n * Scroll to a target value\n *\n * @param target The target value to scroll to\n * @param options The options for the scroll\n *\n * @example\n * lenis.scrollTo(100, {\n * offset: 100,\n * duration: 1,\n * easing: (t) => 1 - Math.cos((t * Math.PI) / 2),\n * lerp: 0.1,\n * onStart: () => {\n * console.log('onStart')\n * },\n * onComplete: () => {\n * console.log('onComplete')\n * },\n * })\n */\n scrollTo(target, {\n offset = 0,\n immediate = false,\n lock = false,\n duration = this.options.duration,\n easing = this.options.easing,\n lerp: lerp2 = this.options.lerp,\n onStart,\n onComplete,\n force = false,\n // scroll even if stopped\n programmatic = true,\n // called from outside of the class\n userData\n } = {}) {\n if ((this.isStopped || this.isLocked) && !force) return;\n if (typeof target === \"string\" && [\"top\", \"left\", \"start\"].includes(target)) {\n target = 0;\n } else if (typeof target === \"string\" && [\"bottom\", \"right\", \"end\"].includes(target)) {\n target = this.limit;\n } else {\n let node;\n if (typeof target === \"string\") {\n node = document.querySelector(target);\n } else if (target instanceof HTMLElement && target?.nodeType) {\n node = target;\n }\n if (node) {\n if (this.options.wrapper !== window) {\n const wrapperRect = this.rootElement.getBoundingClientRect();\n offset -= this.isHorizontal ? wrapperRect.left : wrapperRect.top;\n }\n const rect = node.getBoundingClientRect();\n target = (this.isHorizontal ? rect.left : rect.top) + this.animatedScroll;\n }\n }\n if (typeof target !== \"number\") return;\n target += offset;\n target = Math.round(target);\n if (this.options.infinite) {\n if (programmatic) {\n this.targetScroll = this.animatedScroll = this.scroll;\n const distance = target - this.animatedScroll;\n if (distance > this.limit / 2) {\n target = target - this.limit;\n } else if (distance < -this.limit / 2) {\n target = target + this.limit;\n }\n }\n } else {\n target = clamp(0, target, this.limit);\n }\n if (target === this.targetScroll) {\n onStart?.(this);\n onComplete?.(this);\n return;\n }\n this.userData = userData ?? {};\n if (immediate) {\n this.animatedScroll = this.targetScroll = target;\n this.setScroll(this.scroll);\n this.reset();\n this.preventNextNativeScrollEvent();\n this.emit();\n onComplete?.(this);\n this.userData = {};\n requestAnimationFrame(() => {\n this.dispatchScrollendEvent();\n });\n return;\n }\n if (!programmatic) {\n this.targetScroll = target;\n }\n this.animate.fromTo(this.animatedScroll, target, {\n duration,\n easing,\n lerp: lerp2,\n onStart: () => {\n if (lock) this.isLocked = true;\n this.isScrolling = \"smooth\";\n onStart?.(this);\n },\n onUpdate: (value, completed) => {\n this.isScrolling = \"smooth\";\n this.lastVelocity = this.velocity;\n this.velocity = value - this.animatedScroll;\n this.direction = Math.sign(this.velocity);\n this.animatedScroll = value;\n this.setScroll(this.scroll);\n if (programmatic) {\n this.targetScroll = value;\n }\n if (!completed) this.emit();\n if (completed) {\n this.reset();\n this.emit();\n onComplete?.(this);\n this.userData = {};\n requestAnimationFrame(() => {\n this.dispatchScrollendEvent();\n });\n this.preventNextNativeScrollEvent();\n }\n }\n });\n }\n preventNextNativeScrollEvent() {\n this._preventNextNativeScrollEvent = true;\n requestAnimationFrame(() => {\n this._preventNextNativeScrollEvent = false;\n });\n }\n checkNestedScroll(node, { deltaX, deltaY }) {\n const time = Date.now();\n const cache = node._lenis ??= {};\n let hasOverflowX, hasOverflowY, isScrollableX, isScrollableY, scrollWidth, scrollHeight, clientWidth, clientHeight;\n const gestureOrientation = this.options.gestureOrientation;\n if (time - (cache.time ?? 0) > 2e3) {\n cache.time = Date.now();\n const computedStyle = window.getComputedStyle(node);\n cache.computedStyle = computedStyle;\n const overflowXString = computedStyle.overflowX;\n const overflowYString = computedStyle.overflowY;\n hasOverflowX = [\"auto\", \"overlay\", \"scroll\"].includes(overflowXString);\n hasOverflowY = [\"auto\", \"overlay\", \"scroll\"].includes(overflowYString);\n cache.hasOverflowX = hasOverflowX;\n cache.hasOverflowY = hasOverflowY;\n if (!hasOverflowX && !hasOverflowY) return false;\n if (gestureOrientation === \"vertical\" && !hasOverflowY) return false;\n if (gestureOrientation === \"horizontal\" && !hasOverflowX) return false;\n scrollWidth = node.scrollWidth;\n scrollHeight = node.scrollHeight;\n clientWidth = node.clientWidth;\n clientHeight = node.clientHeight;\n isScrollableX = scrollWidth > clientWidth;\n isScrollableY = scrollHeight > clientHeight;\n cache.isScrollableX = isScrollableX;\n cache.isScrollableY = isScrollableY;\n cache.scrollWidth = scrollWidth;\n cache.scrollHeight = scrollHeight;\n cache.clientWidth = clientWidth;\n cache.clientHeight = clientHeight;\n } else {\n isScrollableX = cache.isScrollableX;\n isScrollableY = cache.isScrollableY;\n hasOverflowX = cache.hasOverflowX;\n hasOverflowY = cache.hasOverflowY;\n scrollWidth = cache.scrollWidth;\n scrollHeight = cache.scrollHeight;\n clientWidth = cache.clientWidth;\n clientHeight = cache.clientHeight;\n }\n if (!hasOverflowX && !hasOverflowY || !isScrollableX && !isScrollableY) {\n return false;\n }\n if (gestureOrientation === \"vertical\" && (!hasOverflowY || !isScrollableY))\n return false;\n if (gestureOrientation === \"horizontal\" && (!hasOverflowX || !isScrollableX))\n return false;\n let orientation;\n if (gestureOrientation === \"horizontal\") {\n orientation = \"x\";\n } else if (gestureOrientation === \"vertical\") {\n orientation = \"y\";\n } else {\n const isScrollingX = deltaX !== 0;\n const isScrollingY = deltaY !== 0;\n if (isScrollingX && hasOverflowX && isScrollableX) {\n orientation = \"x\";\n }\n if (isScrollingY && hasOverflowY && isScrollableY) {\n orientation = \"y\";\n }\n }\n if (!orientation) return false;\n let scroll, maxScroll, delta, hasOverflow, isScrollable;\n if (orientation === \"x\") {\n scroll = node.scrollLeft;\n maxScroll = scrollWidth - clientWidth;\n delta = deltaX;\n hasOverflow = hasOverflowX;\n isScrollable = isScrollableX;\n } else if (orientation === \"y\") {\n scroll = node.scrollTop;\n maxScroll = scrollHeight - clientHeight;\n delta = deltaY;\n hasOverflow = hasOverflowY;\n isScrollable = isScrollableY;\n } else {\n return false;\n }\n const willScroll = delta > 0 ? scroll < maxScroll : scroll > 0;\n return willScroll && hasOverflow && isScrollable;\n }\n /**\n * The root element on which lenis is instanced\n */\n get rootElement() {\n return this.options.wrapper === window ? document.documentElement : this.options.wrapper;\n }\n /**\n * The limit which is the maximum scroll value\n */\n get limit() {\n if (this.options.__experimental__naiveDimensions) {\n if (this.isHorizontal) {\n return this.rootElement.scrollWidth - this.rootElement.clientWidth;\n } else {\n return this.rootElement.scrollHeight - this.rootElement.clientHeight;\n }\n } else {\n return this.dimensions.limit[this.isHorizontal ? \"x\" : \"y\"];\n }\n }\n /**\n * Whether or not the scroll is horizontal\n */\n get isHorizontal() {\n return this.options.orientation === \"horizontal\";\n }\n /**\n * The actual scroll value\n */\n get actualScroll() {\n const wrapper = this.options.wrapper;\n return this.isHorizontal ? wrapper.scrollX ?? wrapper.scrollLeft : wrapper.scrollY ?? wrapper.scrollTop;\n }\n /**\n * The current scroll value\n */\n get scroll() {\n return this.options.infinite ? modulo(this.animatedScroll, this.limit) : this.animatedScroll;\n }\n /**\n * The progress of the scroll relative to the limit\n */\n get progress() {\n return this.limit === 0 ? 1 : this.scroll / this.limit;\n }\n /**\n * Current scroll state\n */\n get isScrolling() {\n return this._isScrolling;\n }\n set isScrolling(value) {\n if (this._isScrolling !== value) {\n this._isScrolling = value;\n this.updateClassName();\n }\n }\n /**\n * Check if lenis is stopped\n */\n get isStopped() {\n return this._isStopped;\n }\n set isStopped(value) {\n if (this._isStopped !== value) {\n this._isStopped = value;\n this.updateClassName();\n }\n }\n /**\n * Check if lenis is locked\n */\n get isLocked() {\n return this._isLocked;\n }\n set isLocked(value) {\n if (this._isLocked !== value) {\n this._isLocked = value;\n this.updateClassName();\n }\n }\n /**\n * Check if lenis is smooth scrolling\n */\n get isSmooth() {\n return this.isScrolling === \"smooth\";\n }\n /**\n * The class name applied to the wrapper element\n */\n get className() {\n let className = \"lenis\";\n if (this.options.autoToggle) className += \" lenis-autoToggle\";\n if (this.isStopped) className += \" lenis-stopped\";\n if (this.isLocked) className += \" lenis-locked\";\n if (this.isScrolling) className += \" lenis-scrolling\";\n if (this.isScrolling === \"smooth\") className += \" lenis-smooth\";\n return className;\n }\n updateClassName() {\n this.cleanUpClassName();\n this.rootElement.className = `${this.rootElement.className} ${this.className}`.trim();\n }\n cleanUpClassName() {\n this.rootElement.className = this.rootElement.className.replace(/lenis(-\\w+)?/g, \"\").trim();\n }\n};\nexport {\n Lenis as default\n};\n//# sourceMappingURL=lenis.mjs.map","import Lenis from 'lenis'\r\nclass FeatherScroll {\r\n // Stores all instances of FeatherScroll\r\n static instances = [];\r\n constructor(options = {}) {\r\n this.wrapper = options.wrapper || document.documentElement;\r\n this.content = options.content || document.body;\r\n // Initialize Lenis with custom options or defaults\r\n this.lenis = new Lenis({\r\n wrapper: this.wrapper,\r\n content: this.content,\r\n smooth: options.smooth ?? true,\r\n duration: options.duration ?? 1.2,\r\n easing: options.easing ?? ((t) => 1 - Math.pow(1 - t, 3)),\r\n direction: options.direction ?? 'vertical',\r\n gestureDirection: options.gestureDirection ?? 'both',\r\n wheelMultiplier: options.mouseSenstivity ?? 1,\r\n touchMultiplier: options.touchSenstivity ?? 2,\r\n infinite: options.infinite ?? false\r\n });\r\n // Scroll direction tracking\r\n this.scrollDirection = 'down';\r\n this.lastScroll = 0;\r\n // Elements with sticky and parallax behavior\r\n this.stickyElements = [...this.content.querySelectorAll('[data-scroll-sticky]')];\r\n this.parallaxElements = [...this.content.querySelectorAll('[data-scroll-speed]')];\r\n // Store initial positions for parallax elements\r\n this.parallaxElements.forEach((el) => {\r\n const rect = el.getBoundingClientRect();\r\n el.dataset.initialTop = rect.top + window.scrollY;\r\n el.dataset.initialLeft = rect.left + window.scrollX;\r\n });\r\n // Initialize features\r\n this.initStickyElements();\r\n this.trackScrollDirection();\r\n this.startRAF(); // Start animation loop\r\n FeatherScroll.instances.push(this); // Register instance\r\n if (window.ScrollTrigger) {\r\n this.setupScrollTrigger();\r\n }\r\n // Observe body overflow for automatic disabling\r\n this.observeBodyOverflow();\r\n }\r\n // RAF loop for Lenis + sticky + parallax\r\n startRAF() {\r\n const raf = (time) => {\r\n this.lenis.raf(time);\r\n this.updateStickyElements();\r\n this.updateParallax();\r\n requestAnimationFrame(raf);\r\n };\r\n requestAnimationFrame(raf);\r\n }\r\n // Detect scroll direction: 'up' or 'down'\r\n trackScrollDirection() {\r\n this.lenis.on('scroll', ({ scroll }) => {\r\n const newDirection = scroll > this.lastScroll ? 'down' : 'up';\r\n if (newDirection !== this.scrollDirection) {\r\n this.scrollDirection = newDirection;\r\n }\r\n this.lastScroll = scroll;\r\n });\r\n }\r\n // Observe overflow-y on body, pause/resume Lenis\r\n observeBodyOverflow() {\r\n const observer = new MutationObserver(() => {\r\n const overflowY = window.getComputedStyle(document.body).overflowY;\r\n if (overflowY === 'hidden') {\r\n this.lenis.stop();\r\n } else {\r\n this.lenis.start();\r\n }\r\n });\r\n observer.observe(document.body, {\r\n attributes: true,\r\n attributeFilter: ['style']\r\n });\r\n // Initial check\r\n const initialOverflowY = window.getComputedStyle(document.body).overflowY;\r\n if (initialOverflowY === 'hidden') {\r\n this.lenis.stop();\r\n }\r\n }\r\n // Return current scroll direction\r\n getScrollDirection() {\r\n return this.scrollDirection || 'down';\r\n }\r\n // Set initial positions for sticky elements\r\n initStickyElements() {\r\n this.stickyElements.forEach((el) => {\r\n const parent = el.parentElement;\r\n const rect = el.getBoundingClientRect();\r\n el.dataset.stickyStart = parent.offsetTop;\r\n el.dataset.stickyEnd = parent.offsetTop + parent.offsetHeight;\r\n el.dataset.originalWidth = `${rect.width}px`;\r\n el.dataset.originalHeight = `${rect.height}px`;\r\n });\r\n }\r\n // Update sticky element positions\r\n updateStickyElements() {\r\n const scrollY = this.lenis.scroll;\r\n const viewportHeight = window.innerHeight;\r\n this.stickyElements.forEach((el) => {\r\n const parent = el.parentElement;\r\n const nextSibling = parent.nextElementSibling;\r\n if (!nextSibling) return;\r\n const stickyStart = parseFloat(el.dataset.stickyStart);\r\n const stickyEnd = parseFloat(el.dataset.stickyEnd);\r\n const parentRect = parent.getBoundingClientRect();\r\n const nextRect = nextSibling.getBoundingClientRect();\r\n // If next section enters halfway viewport, stop sticking\r\n const isNextEntering = nextRect.top < viewportHeight * 0.5;\r\n if (scrollY >= stickyStart && scrollY < stickyEnd && !isNextEntering) {\r\n el.style.position = 'fixed';\r\n el.style.top = `${window.innerHeight / 2 - el.offsetHeight / 2}px`;\r\n el.style.left = `${parentRect.left + parentRect.width / 2 - el.offsetWidth / 2}px`;\r\n el.style.opacity = '1';\r\n } else {\r\n el.style.position = 'relative';\r\n el.style.opacity = '0';\r\n }\r\n });\r\n }\r\n // Apply parallax effect based on data attributes\r\n updateParallax() {\r\n const scrollY = this.lenis.scroll;\r\n this.parallaxElements.forEach((el) => {\r\n const speed = parseFloat(el.getAttribute(\"data-scroll-speed\")) || 1;\r\n const direction = el.getAttribute(\"data-scroll-direction\") || \"vertical\";\r\n const initialTop = parseFloat(el.dataset.initialTop);\r\n const initialLeft = parseFloat(el.dataset.initialLeft);\r\n let offsetX = 0, offsetY = 0;\r\n if (direction === \"horizontal\") {\r\n offsetX = (scrollY - initialTop) * speed * 0.1;\r\n } else if (direction === \"vertical\") {\r\n offsetY = (scrollY - initialTop) * speed * 0.1;\r\n } else if (direction === \"both\") {\r\n offsetX = (scrollY - initialTop) * speed * 0.1;\r\n offsetY = (scrollY - initialTop) * speed * 0.1;\r\n }\r\n // If GSAP is present, respect GSAP transforms\r\n let gsapX = 0, gsapY = 0;\r\n if (window.gsap) {\r\n gsapX = gsap.getProperty(el, \"x\") || 0;\r\n gsapY = gsap.getProperty(el, \"y\") || 0;\r\n }\r\n el.style.transform = `translate3d(${offsetX + gsapX}px, ${offsetY + gsapY}px, 0)`;\r\n });\r\n }\r\n // Integration with GSAP ScrollTrigger\r\n setupScrollTrigger() {\r\n this.lenis.on('scroll', () => {\r\n ScrollTrigger.update();\r\n });\r\n }\r\n // Public method: Scroll to a target\r\n scrollTo(target, options = {}) {\r\n this.lenis.scrollTo(target, options);\r\n }\r\n // Public method: Start scrolling\r\n start() {\r\n this.lenis.start();\r\n }\r\n // Public method: Stop scrolling\r\n stop() {\r\n this.lenis.stop();\r\n }\r\n // Public method: Destroy the instance\r\n destroy() {\r\n this.lenis.destroy();\r\n FeatherScroll.instances = FeatherScroll.instances.filter((instance) => instance !== this);\r\n }\r\n // Public method: Get scroll position\r\n getScrollPosition() {\r\n return this.lenis.scroll;\r\n }\r\n // Update Lenis options dynamically\r\n updateOptions(newOptions) {\r\n Object.assign(this.lenis.options, newOptions);\r\n }\r\n }\r\nexport default FeatherScroll;\r\n\r\n// Also attach to window for CDN users\r\nif (typeof window !== 'undefined') {\r\n window.FeatherScroll = FeatherScroll;\r\n}"],"names":[],"mappings":"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","x_google_ignoreList":[0]}
--------------------------------------------------------------------------------
/dist/featherScroll.min.js:
--------------------------------------------------------------------------------
1 | var FeatherScroll=function(){"use strict";function t(t,e,i){return Math.max(t,Math.min(e,i))}var e=class{isRunning=!1;value=0;from=0;to=0;currentTime=0;lerp;duration;easing;onUpdate;advance(e){if(!this.isRunning)return;let i=!1;if(this.duration&&this.easing){this.currentTime+=e;const s=t(0,this.currentTime/this.duration,1);i=s>=1;const o=i?1:this.easing(s);this.value=this.from+(this.to-this.from)*o}else this.lerp?(this.value=function(t,e,i,s){return function(t,e,i){return(1-i)*t+i*e}(t,e,1-Math.exp(-i*s))}(this.value,this.to,60*this.lerp,e),Math.round(this.value)===this.to&&(this.value=this.to,i=!0)):(this.value=this.to,i=!0);i&&this.stop(),this.onUpdate?.(this.value,i)}stop(){this.isRunning=!1}fromTo(t,e,{lerp:i,duration:s,easing:o,onStart:n,onUpdate:r}){this.from=this.value=t,this.to=e,this.lerp=i,this.duration=s,this.easing=o,this.currentTime=0,this.isRunning=!0,n?.(),this.onUpdate=r}};var i=class{constructor(t,e,{autoResize:i=!0,debounce:s=250}={}){this.wrapper=t,this.content=e,i&&(this.debouncedResize=function(t,e){let i;return function(...s){let o=this;clearTimeout(i),i=setTimeout((()=>{i=void 0,t.apply(o,s)}),e)}}(this.resize,s),this.wrapper instanceof Window?window.addEventListener("resize",this.debouncedResize,!1):(this.wrapperResizeObserver=new ResizeObserver(this.debouncedResize),this.wrapperResizeObserver.observe(this.wrapper)),this.contentResizeObserver=new ResizeObserver(this.debouncedResize),this.contentResizeObserver.observe(this.content)),this.resize()}width=0;height=0;scrollHeight=0;scrollWidth=0;debouncedResize;wrapperResizeObserver;contentResizeObserver;destroy(){this.wrapperResizeObserver?.disconnect(),this.contentResizeObserver?.disconnect(),this.wrapper===window&&this.debouncedResize&&window.removeEventListener("resize",this.debouncedResize,!1)}resize=()=>{this.onWrapperResize(),this.onContentResize()};onWrapperResize=()=>{this.wrapper instanceof Window?(this.width=window.innerWidth,this.height=window.innerHeight):(this.width=this.wrapper.clientWidth,this.height=this.wrapper.clientHeight)};onContentResize=()=>{this.wrapper instanceof Window?(this.scrollHeight=this.content.scrollHeight,this.scrollWidth=this.content.scrollWidth):(this.scrollHeight=this.wrapper.scrollHeight,this.scrollWidth=this.wrapper.scrollWidth)};get limit(){return{x:this.scrollWidth-this.width,y:this.scrollHeight-this.height}}},s=class{events={};emit(t,...e){let i=this.events[t]||[];for(let t=0,s=i.length;t{this.events[t]=this.events[t]?.filter((t=>e!==t))}}off(t,e){this.events[t]=this.events[t]?.filter((t=>e!==t))}destroy(){this.events={}}},o=100/6,n={passive:!1},r=class{constructor(t,e={wheelMultiplier:1,touchMultiplier:1}){this.element=t,this.options=e,window.addEventListener("resize",this.onWindowResize,!1),this.onWindowResize(),this.element.addEventListener("wheel",this.onWheel,n),this.element.addEventListener("touchstart",this.onTouchStart,n),this.element.addEventListener("touchmove",this.onTouchMove,n),this.element.addEventListener("touchend",this.onTouchEnd,n)}touchStart={x:0,y:0};lastDelta={x:0,y:0};window={width:0,height:0};emitter=new s;on(t,e){return this.emitter.on(t,e)}destroy(){this.emitter.destroy(),window.removeEventListener("resize",this.onWindowResize,!1),this.element.removeEventListener("wheel",this.onWheel,n),this.element.removeEventListener("touchstart",this.onTouchStart,n),this.element.removeEventListener("touchmove",this.onTouchMove,n),this.element.removeEventListener("touchend",this.onTouchEnd,n)}onTouchStart=t=>{const{clientX:e,clientY:i}=t.targetTouches?t.targetTouches[0]:t;this.touchStart.x=e,this.touchStart.y=i,this.lastDelta={x:0,y:0},this.emitter.emit("scroll",{deltaX:0,deltaY:0,event:t})};onTouchMove=t=>{const{clientX:e,clientY:i}=t.targetTouches?t.targetTouches[0]:t,s=-(e-this.touchStart.x)*this.options.touchMultiplier,o=-(i-this.touchStart.y)*this.options.touchMultiplier;this.touchStart.x=e,this.touchStart.y=i,this.lastDelta={x:s,y:o},this.emitter.emit("scroll",{deltaX:s,deltaY:o,event:t})};onTouchEnd=t=>{this.emitter.emit("scroll",{deltaX:this.lastDelta.x,deltaY:this.lastDelta.y,event:t})};onWheel=t=>{let{deltaX:e,deltaY:i,deltaMode:s}=t;e*=1===s?o:2===s?this.window.width:1,i*=1===s?o:2===s?this.window.height:1,e*=this.options.wheelMultiplier,i*=this.options.wheelMultiplier,this.emitter.emit("scroll",{deltaX:e,deltaY:i,event:t})};onWindowResize=()=>{this.window={width:window.innerWidth,height:window.innerHeight}}},l=class{_isScrolling=!1;_isStopped=!1;_isLocked=!1;_preventNextNativeScrollEvent=!1;_resetVelocityTimeout=null;__rafID=null;isTouching;time=0;userData={};lastVelocity=0;velocity=0;direction=0;options;targetScroll;animatedScroll;animate=new e;emitter=new s;dimensions;virtualScroll;constructor({wrapper:t=window,content:e=document.documentElement,eventsTarget:s=t,smoothWheel:o=!0,syncTouch:n=!1,syncTouchLerp:l=.075,touchInertiaMultiplier:h=35,duration:a,easing:c=t=>Math.min(1,1.001-Math.pow(2,-10*t)),lerp:p=.1,infinite:d=!1,orientation:u="vertical",gestureOrientation:m="vertical",touchMultiplier:v=1,wheelMultiplier:g=1,autoResize:w=!0,prevent:S,virtualScroll:f,overscroll:y=!0,autoRaf:E=!1,anchors:T=!1,autoToggle:b=!1,allowNestedScroll:z=!1,__experimental__naiveDimensions:R=!1}={}){window.lenisVersion="1.3.1",t&&t!==document.documentElement||(t=window),this.options={wrapper:t,content:e,eventsTarget:s,smoothWheel:o,syncTouch:n,syncTouchLerp:l,touchInertiaMultiplier:h,duration:a,easing:c,lerp:p,infinite:d,gestureOrientation:m,orientation:u,touchMultiplier:v,wheelMultiplier:g,autoResize:w,prevent:S,virtualScroll:f,overscroll:y,autoRaf:E,anchors:T,autoToggle:b,allowNestedScroll:z,__experimental__naiveDimensions:R},this.dimensions=new i(t,e,{autoResize:w}),this.updateClassName(),this.targetScroll=this.animatedScroll=this.actualScroll,this.options.wrapper.addEventListener("scroll",this.onNativeScroll,!1),this.options.wrapper.addEventListener("scrollend",this.onScrollEnd,{capture:!0}),this.options.anchors&&this.options.wrapper===window&&this.options.wrapper.addEventListener("click",this.onClick,!1),this.options.wrapper.addEventListener("pointerdown",this.onPointerDown,!1),this.virtualScroll=new r(s,{touchMultiplier:v,wheelMultiplier:g}),this.virtualScroll.on("scroll",this.onVirtualScroll),this.options.autoToggle&&this.rootElement.addEventListener("transitionend",this.onTransitionEnd,{passive:!0}),this.options.autoRaf&&(this.__rafID=requestAnimationFrame(this.raf))}destroy(){this.emitter.destroy(),this.options.wrapper.removeEventListener("scroll",this.onNativeScroll,!1),this.options.wrapper.removeEventListener("scrollend",this.onScrollEnd,{capture:!0}),this.options.wrapper.removeEventListener("pointerdown",this.onPointerDown,!1),this.options.anchors&&this.options.wrapper===window&&this.options.wrapper.removeEventListener("click",this.onClick,!1),this.virtualScroll.destroy(),this.dimensions.destroy(),this.cleanUpClassName(),this.__rafID&&cancelAnimationFrame(this.__rafID)}on(t,e){return this.emitter.on(t,e)}off(t,e){return this.emitter.off(t,e)}onScrollEnd=t=>{t instanceof CustomEvent||"smooth"!==this.isScrolling&&!1!==this.isScrolling||t.stopPropagation()};dispatchScrollendEvent=()=>{this.options.wrapper.dispatchEvent(new CustomEvent("scrollend",{bubbles:this.options.wrapper===window,detail:{lenisScrollEnd:!0}}))};onTransitionEnd=t=>{if(t.propertyName.includes("overflow")){const t=this.isHorizontal?"overflow-x":"overflow-y",e=getComputedStyle(this.rootElement)[t];["hidden","clip"].includes(e)?this.stop():this.start()}};setScroll(t){this.isHorizontal?this.options.wrapper.scrollTo({left:t,behavior:"instant"}):this.options.wrapper.scrollTo({top:t,behavior:"instant"})}onClick=t=>{const e=t.composedPath().find((t=>t instanceof HTMLAnchorElement&&(t.getAttribute("href")?.startsWith("#")||t.getAttribute("href")?.startsWith("/#")||t.getAttribute("href")?.startsWith("./#"))));if(e){const t=e.getAttribute("href");if(t){const e="object"==typeof this.options.anchors&&this.options.anchors?this.options.anchors:void 0;let i=`#${t.split("#")[1]}`;["#","/#","./#","#top","/#top","./#top"].includes(t)&&(i=0),this.scrollTo(i,e)}}};onPointerDown=t=>{1===t.button&&this.reset()};onVirtualScroll=t=>{if("function"==typeof this.options.virtualScroll&&!1===this.options.virtualScroll(t))return;const{deltaX:e,deltaY:i,event:s}=t;if(this.emitter.emit("virtual-scroll",{deltaX:e,deltaY:i,event:s}),s.ctrlKey)return;if(s.lenisStopPropagation)return;const o=s.type.includes("touch"),n=s.type.includes("wheel");this.isTouching="touchstart"===s.type||"touchmove"===s.type;const r=0===e&&0===i;if(this.options.syncTouch&&o&&"touchstart"===s.type&&r&&!this.isStopped&&!this.isLocked)return void this.reset();const l="vertical"===this.options.gestureOrientation&&0===i||"horizontal"===this.options.gestureOrientation&&0===e;if(r||l)return;let h=s.composedPath();h=h.slice(0,h.indexOf(this.rootElement));const a=this.options.prevent;if(h.find((t=>t instanceof HTMLElement&&("function"==typeof a&&a?.(t)||t.hasAttribute?.("data-lenis-prevent")||o&&t.hasAttribute?.("data-lenis-prevent-touch")||n&&t.hasAttribute?.("data-lenis-prevent-wheel")||this.options.allowNestedScroll&&this.checkNestedScroll(t,{deltaX:e,deltaY:i})))))return;if(this.isStopped||this.isLocked)return void s.preventDefault();if(!(this.options.syncTouch&&o||this.options.smoothWheel&&n))return this.isScrolling="native",this.animate.stop(),void(s.lenisStopPropagation=!0);let c=i;"both"===this.options.gestureOrientation?c=Math.abs(i)>Math.abs(e)?i:e:"horizontal"===this.options.gestureOrientation&&(c=e),(!this.options.overscroll||this.options.infinite||this.options.wrapper!==window&&(this.animatedScroll>0&&this.animatedScroll0||this.animatedScroll===this.limit&&i<0))&&(s.lenisStopPropagation=!0),s.preventDefault();const p=o&&this.options.syncTouch,d=o&&"touchend"===s.type&&Math.abs(c)>5;d&&(c=this.velocity*this.options.touchInertiaMultiplier),this.scrollTo(this.targetScroll+c,{programmatic:!1,...p?{lerp:d?this.options.syncTouchLerp:1}:{lerp:this.options.lerp,duration:this.options.duration,easing:this.options.easing}})};resize(){this.dimensions.resize(),this.animatedScroll=this.targetScroll=this.actualScroll,this.emit()}emit(){this.emitter.emit("scroll",this)}onNativeScroll=()=>{if(null!==this._resetVelocityTimeout&&(clearTimeout(this._resetVelocityTimeout),this._resetVelocityTimeout=null),this._preventNextNativeScrollEvent)this._preventNextNativeScrollEvent=!1;else if(!1===this.isScrolling||"native"===this.isScrolling){const t=this.animatedScroll;this.animatedScroll=this.targetScroll=this.actualScroll,this.lastVelocity=this.velocity,this.velocity=this.animatedScroll-t,this.direction=Math.sign(this.animatedScroll-t),this.isStopped||(this.isScrolling="native"),this.emit(),0!==this.velocity&&(this._resetVelocityTimeout=setTimeout((()=>{this.lastVelocity=this.velocity,this.velocity=0,this.isScrolling=!1,this.emit()}),400))}};reset(){this.isLocked=!1,this.isScrolling=!1,this.animatedScroll=this.targetScroll=this.actualScroll,this.lastVelocity=this.velocity=0,this.animate.stop()}start(){this.isStopped&&(this.reset(),this.isStopped=!1)}stop(){this.isStopped||(this.reset(),this.isStopped=!0)}raf=t=>{const e=t-(this.time||t);this.time=t,this.animate.advance(.001*e),this.options.autoRaf&&(this.__rafID=requestAnimationFrame(this.raf))};scrollTo(e,{offset:i=0,immediate:s=!1,lock:o=!1,duration:n=this.options.duration,easing:r=this.options.easing,lerp:l=this.options.lerp,onStart:h,onComplete:a,force:c=!1,programmatic:p=!0,userData:d}={}){if(!this.isStopped&&!this.isLocked||c){if("string"==typeof e&&["top","left","start"].includes(e))e=0;else if("string"==typeof e&&["bottom","right","end"].includes(e))e=this.limit;else{let t;if("string"==typeof e?t=document.querySelector(e):e instanceof HTMLElement&&e?.nodeType&&(t=e),t){if(this.options.wrapper!==window){const t=this.rootElement.getBoundingClientRect();i-=this.isHorizontal?t.left:t.top}const s=t.getBoundingClientRect();e=(this.isHorizontal?s.left:s.top)+this.animatedScroll}}if("number"==typeof e){if(e+=i,e=Math.round(e),this.options.infinite){if(p){this.targetScroll=this.animatedScroll=this.scroll;const t=e-this.animatedScroll;t>this.limit/2?e-=this.limit:t<-this.limit/2&&(e+=this.limit)}}else e=t(0,e,this.limit);if(e===this.targetScroll)return h?.(this),void a?.(this);if(this.userData=d??{},s)return this.animatedScroll=this.targetScroll=e,this.setScroll(this.scroll),this.reset(),this.preventNextNativeScrollEvent(),this.emit(),a?.(this),this.userData={},void requestAnimationFrame((()=>{this.dispatchScrollendEvent()}));p||(this.targetScroll=e),this.animate.fromTo(this.animatedScroll,e,{duration:n,easing:r,lerp:l,onStart:()=>{o&&(this.isLocked=!0),this.isScrolling="smooth",h?.(this)},onUpdate:(t,e)=>{this.isScrolling="smooth",this.lastVelocity=this.velocity,this.velocity=t-this.animatedScroll,this.direction=Math.sign(this.velocity),this.animatedScroll=t,this.setScroll(this.scroll),p&&(this.targetScroll=t),e||this.emit(),e&&(this.reset(),this.emit(),a?.(this),this.userData={},requestAnimationFrame((()=>{this.dispatchScrollendEvent()})),this.preventNextNativeScrollEvent())}})}}}preventNextNativeScrollEvent(){this._preventNextNativeScrollEvent=!0,requestAnimationFrame((()=>{this._preventNextNativeScrollEvent=!1}))}checkNestedScroll(t,{deltaX:e,deltaY:i}){const s=Date.now(),o=t._lenis??={};let n,r,l,h,a,c,p,d;const u=this.options.gestureOrientation;if(s-(o.time??0)>2e3){o.time=Date.now();const e=window.getComputedStyle(t);o.computedStyle=e;const i=e.overflowX,s=e.overflowY;if(n=["auto","overlay","scroll"].includes(i),r=["auto","overlay","scroll"].includes(s),o.hasOverflowX=n,o.hasOverflowY=r,!n&&!r)return!1;if("vertical"===u&&!r)return!1;if("horizontal"===u&&!n)return!1;a=t.scrollWidth,c=t.scrollHeight,p=t.clientWidth,d=t.clientHeight,l=a>p,h=c>d,o.isScrollableX=l,o.isScrollableY=h,o.scrollWidth=a,o.scrollHeight=c,o.clientWidth=p,o.clientHeight=d}else l=o.isScrollableX,h=o.isScrollableY,n=o.hasOverflowX,r=o.hasOverflowY,a=o.scrollWidth,c=o.scrollHeight,p=o.clientWidth,d=o.clientHeight;if(!n&&!r||!l&&!h)return!1;if(!("vertical"!==u||r&&h))return!1;if(!("horizontal"!==u||n&&l))return!1;let m,v,g,w,S,f;if("horizontal"===u)m="x";else if("vertical"===u)m="y";else{0!==e&&n&&l&&(m="x"),0!==i&&r&&h&&(m="y")}if(!m)return!1;if("x"===m)v=t.scrollLeft,g=a-p,w=e,S=n,f=l;else{if("y"!==m)return!1;v=t.scrollTop,g=c-d,w=i,S=r,f=h}return(w>0?v0)&&S&&f}get rootElement(){return this.options.wrapper===window?document.documentElement:this.options.wrapper}get limit(){return this.options.__experimental__naiveDimensions?this.isHorizontal?this.rootElement.scrollWidth-this.rootElement.clientWidth:this.rootElement.scrollHeight-this.rootElement.clientHeight:this.dimensions.limit[this.isHorizontal?"x":"y"]}get isHorizontal(){return"horizontal"===this.options.orientation}get actualScroll(){const t=this.options.wrapper;return this.isHorizontal?t.scrollX??t.scrollLeft:t.scrollY??t.scrollTop}get scroll(){return this.options.infinite?(t=this.animatedScroll,e=this.limit,(t%e+e)%e):this.animatedScroll;var t,e}get progress(){return 0===this.limit?1:this.scroll/this.limit}get isScrolling(){return this._isScrolling}set isScrolling(t){this._isScrolling!==t&&(this._isScrolling=t,this.updateClassName())}get isStopped(){return this._isStopped}set isStopped(t){this._isStopped!==t&&(this._isStopped=t,this.updateClassName())}get isLocked(){return this._isLocked}set isLocked(t){this._isLocked!==t&&(this._isLocked=t,this.updateClassName())}get isSmooth(){return"smooth"===this.isScrolling}get className(){let t="lenis";return this.options.autoToggle&&(t+=" lenis-autoToggle"),this.isStopped&&(t+=" lenis-stopped"),this.isLocked&&(t+=" lenis-locked"),this.isScrolling&&(t+=" lenis-scrolling"),"smooth"===this.isScrolling&&(t+=" lenis-smooth"),t}updateClassName(){this.cleanUpClassName(),this.rootElement.className=`${this.rootElement.className} ${this.className}`.trim()}cleanUpClassName(){this.rootElement.className=this.rootElement.className.replace(/lenis(-\w+)?/g,"").trim()}};class h{static instances=[];constructor(t={}){this.wrapper=t.wrapper||document.documentElement,this.content=t.content||document.body,this.lenis=new l({wrapper:this.wrapper,content:this.content,smooth:t.smooth??!0,duration:t.duration??1.2,easing:t.easing??(t=>1-Math.pow(1-t,3)),direction:t.direction??"vertical",gestureDirection:t.gestureDirection??"both",wheelMultiplier:t.mouseSenstivity??1,touchMultiplier:t.touchSenstivity??2,infinite:t.infinite??!1}),this.scrollDirection="down",this.lastScroll=0,this.stickyElements=[...this.content.querySelectorAll("[data-scroll-sticky]")],this.parallaxElements=[...this.content.querySelectorAll("[data-scroll-speed]")],this.parallaxElements.forEach((t=>{const e=t.getBoundingClientRect();t.dataset.initialTop=e.top+window.scrollY,t.dataset.initialLeft=e.left+window.scrollX})),this.initStickyElements(),this.trackScrollDirection(),this.startRAF(),h.instances.push(this),window.ScrollTrigger&&this.setupScrollTrigger(),this.observeBodyOverflow()}startRAF(){const t=e=>{this.lenis.raf(e),this.updateStickyElements(),this.updateParallax(),requestAnimationFrame(t)};requestAnimationFrame(t)}trackScrollDirection(){this.lenis.on("scroll",(({scroll:t})=>{const e=t>this.lastScroll?"down":"up";e!==this.scrollDirection&&(this.scrollDirection=e),this.lastScroll=t}))}observeBodyOverflow(){new MutationObserver((()=>{"hidden"===window.getComputedStyle(document.body).overflowY?this.lenis.stop():this.lenis.start()})).observe(document.body,{attributes:!0,attributeFilter:["style"]});"hidden"===window.getComputedStyle(document.body).overflowY&&this.lenis.stop()}getScrollDirection(){return this.scrollDirection||"down"}initStickyElements(){this.stickyElements.forEach((t=>{const e=t.parentElement,i=t.getBoundingClientRect();t.dataset.stickyStart=e.offsetTop,t.dataset.stickyEnd=e.offsetTop+e.offsetHeight,t.dataset.originalWidth=`${i.width}px`,t.dataset.originalHeight=`${i.height}px`}))}updateStickyElements(){const t=this.lenis.scroll,e=window.innerHeight;this.stickyElements.forEach((i=>{const s=i.parentElement,o=s.nextElementSibling;if(!o)return;const n=parseFloat(i.dataset.stickyStart),r=parseFloat(i.dataset.stickyEnd),l=s.getBoundingClientRect(),h=o.getBoundingClientRect().top<.5*e;t>=n&&t{const i=parseFloat(e.getAttribute("data-scroll-speed"))||1,s=e.getAttribute("data-scroll-direction")||"vertical",o=parseFloat(e.dataset.initialTop);parseFloat(e.dataset.initialLeft);let n=0,r=0;"horizontal"===s?n=(t-o)*i*.1:"vertical"===s?r=(t-o)*i*.1:"both"===s&&(n=(t-o)*i*.1,r=(t-o)*i*.1);let l=0,h=0;window.gsap&&(l=gsap.getProperty(e,"x")||0,h=gsap.getProperty(e,"y")||0),e.style.transform=`translate3d(${n+l}px, ${r+h}px, 0)`}))}setupScrollTrigger(){this.lenis.on("scroll",(()=>{ScrollTrigger.update()}))}scrollTo(t,e={}){this.lenis.scrollTo(t,e)}start(){this.lenis.start()}stop(){this.lenis.stop()}destroy(){this.lenis.destroy(),h.instances=h.instances.filter((t=>t!==this))}getScrollPosition(){return this.lenis.scroll}updateOptions(t){Object.assign(this.lenis.options,t)}}return"undefined"!=typeof window&&(window.FeatherScroll=h),h}();
2 | //# sourceMappingURL=featherScroll.min.js.map
3 |
--------------------------------------------------------------------------------
/dist/featherScroll.min.js.map:
--------------------------------------------------------------------------------
1 | {"version":3,"file":"featherScroll.min.js","sources":["../node_modules/lenis/dist/lenis.mjs","../src/featherScroll.js"],"sourcesContent":["// package.json\nvar version = \"1.3.1\";\n\n// packages/core/src/maths.ts\nfunction clamp(min, input, max) {\n return Math.max(min, Math.min(input, max));\n}\nfunction lerp(x, y, t) {\n return (1 - t) * x + t * y;\n}\nfunction damp(x, y, lambda, deltaTime) {\n return lerp(x, y, 1 - Math.exp(-lambda * deltaTime));\n}\nfunction modulo(n, d) {\n return (n % d + d) % d;\n}\n\n// packages/core/src/animate.ts\nvar Animate = class {\n isRunning = false;\n value = 0;\n from = 0;\n to = 0;\n currentTime = 0;\n // These are instanciated in the fromTo method\n lerp;\n duration;\n easing;\n onUpdate;\n /**\n * Advance the animation by the given delta time\n *\n * @param deltaTime - The time in seconds to advance the animation\n */\n advance(deltaTime) {\n if (!this.isRunning) return;\n let completed = false;\n if (this.duration && this.easing) {\n this.currentTime += deltaTime;\n const linearProgress = clamp(0, this.currentTime / this.duration, 1);\n completed = linearProgress >= 1;\n const easedProgress = completed ? 1 : this.easing(linearProgress);\n this.value = this.from + (this.to - this.from) * easedProgress;\n } else if (this.lerp) {\n this.value = damp(this.value, this.to, this.lerp * 60, deltaTime);\n if (Math.round(this.value) === this.to) {\n this.value = this.to;\n completed = true;\n }\n } else {\n this.value = this.to;\n completed = true;\n }\n if (completed) {\n this.stop();\n }\n this.onUpdate?.(this.value, completed);\n }\n /** Stop the animation */\n stop() {\n this.isRunning = false;\n }\n /**\n * Set up the animation from a starting value to an ending value\n * with optional parameters for lerping, duration, easing, and onUpdate callback\n *\n * @param from - The starting value\n * @param to - The ending value\n * @param options - Options for the animation\n */\n fromTo(from, to, { lerp: lerp2, duration, easing, onStart, onUpdate }) {\n this.from = this.value = from;\n this.to = to;\n this.lerp = lerp2;\n this.duration = duration;\n this.easing = easing;\n this.currentTime = 0;\n this.isRunning = true;\n onStart?.();\n this.onUpdate = onUpdate;\n }\n};\n\n// packages/core/src/debounce.ts\nfunction debounce(callback, delay) {\n let timer;\n return function(...args) {\n let context = this;\n clearTimeout(timer);\n timer = setTimeout(() => {\n timer = void 0;\n callback.apply(context, args);\n }, delay);\n };\n}\n\n// packages/core/src/dimensions.ts\nvar Dimensions = class {\n constructor(wrapper, content, { autoResize = true, debounce: debounceValue = 250 } = {}) {\n this.wrapper = wrapper;\n this.content = content;\n if (autoResize) {\n this.debouncedResize = debounce(this.resize, debounceValue);\n if (this.wrapper instanceof Window) {\n window.addEventListener(\"resize\", this.debouncedResize, false);\n } else {\n this.wrapperResizeObserver = new ResizeObserver(this.debouncedResize);\n this.wrapperResizeObserver.observe(this.wrapper);\n }\n this.contentResizeObserver = new ResizeObserver(this.debouncedResize);\n this.contentResizeObserver.observe(this.content);\n }\n this.resize();\n }\n width = 0;\n height = 0;\n scrollHeight = 0;\n scrollWidth = 0;\n // These are instanciated in the constructor as they need information from the options\n debouncedResize;\n wrapperResizeObserver;\n contentResizeObserver;\n destroy() {\n this.wrapperResizeObserver?.disconnect();\n this.contentResizeObserver?.disconnect();\n if (this.wrapper === window && this.debouncedResize) {\n window.removeEventListener(\"resize\", this.debouncedResize, false);\n }\n }\n resize = () => {\n this.onWrapperResize();\n this.onContentResize();\n };\n onWrapperResize = () => {\n if (this.wrapper instanceof Window) {\n this.width = window.innerWidth;\n this.height = window.innerHeight;\n } else {\n this.width = this.wrapper.clientWidth;\n this.height = this.wrapper.clientHeight;\n }\n };\n onContentResize = () => {\n if (this.wrapper instanceof Window) {\n this.scrollHeight = this.content.scrollHeight;\n this.scrollWidth = this.content.scrollWidth;\n } else {\n this.scrollHeight = this.wrapper.scrollHeight;\n this.scrollWidth = this.wrapper.scrollWidth;\n }\n };\n get limit() {\n return {\n x: this.scrollWidth - this.width,\n y: this.scrollHeight - this.height\n };\n }\n};\n\n// packages/core/src/emitter.ts\nvar Emitter = class {\n events = {};\n /**\n * Emit an event with the given data\n * @param event Event name\n * @param args Data to pass to the event handlers\n */\n emit(event, ...args) {\n let callbacks = this.events[event] || [];\n for (let i = 0, length = callbacks.length; i < length; i++) {\n callbacks[i]?.(...args);\n }\n }\n /**\n * Add a callback to the event\n * @param event Event name\n * @param cb Callback function\n * @returns Unsubscribe function\n */\n on(event, cb) {\n this.events[event]?.push(cb) || (this.events[event] = [cb]);\n return () => {\n this.events[event] = this.events[event]?.filter((i) => cb !== i);\n };\n }\n /**\n * Remove a callback from the event\n * @param event Event name\n * @param callback Callback function\n */\n off(event, callback) {\n this.events[event] = this.events[event]?.filter((i) => callback !== i);\n }\n /**\n * Remove all event listeners and clean up\n */\n destroy() {\n this.events = {};\n }\n};\n\n// packages/core/src/virtual-scroll.ts\nvar LINE_HEIGHT = 100 / 6;\nvar listenerOptions = { passive: false };\nvar VirtualScroll = class {\n constructor(element, options = { wheelMultiplier: 1, touchMultiplier: 1 }) {\n this.element = element;\n this.options = options;\n window.addEventListener(\"resize\", this.onWindowResize, false);\n this.onWindowResize();\n this.element.addEventListener(\"wheel\", this.onWheel, listenerOptions);\n this.element.addEventListener(\n \"touchstart\",\n this.onTouchStart,\n listenerOptions\n );\n this.element.addEventListener(\n \"touchmove\",\n this.onTouchMove,\n listenerOptions\n );\n this.element.addEventListener(\"touchend\", this.onTouchEnd, listenerOptions);\n }\n touchStart = {\n x: 0,\n y: 0\n };\n lastDelta = {\n x: 0,\n y: 0\n };\n window = {\n width: 0,\n height: 0\n };\n emitter = new Emitter();\n /**\n * Add an event listener for the given event and callback\n *\n * @param event Event name\n * @param callback Callback function\n */\n on(event, callback) {\n return this.emitter.on(event, callback);\n }\n /** Remove all event listeners and clean up */\n destroy() {\n this.emitter.destroy();\n window.removeEventListener(\"resize\", this.onWindowResize, false);\n this.element.removeEventListener(\"wheel\", this.onWheel, listenerOptions);\n this.element.removeEventListener(\n \"touchstart\",\n this.onTouchStart,\n listenerOptions\n );\n this.element.removeEventListener(\n \"touchmove\",\n this.onTouchMove,\n listenerOptions\n );\n this.element.removeEventListener(\n \"touchend\",\n this.onTouchEnd,\n listenerOptions\n );\n }\n /**\n * Event handler for 'touchstart' event\n *\n * @param event Touch event\n */\n onTouchStart = (event) => {\n const { clientX, clientY } = event.targetTouches ? event.targetTouches[0] : event;\n this.touchStart.x = clientX;\n this.touchStart.y = clientY;\n this.lastDelta = {\n x: 0,\n y: 0\n };\n this.emitter.emit(\"scroll\", {\n deltaX: 0,\n deltaY: 0,\n event\n });\n };\n /** Event handler for 'touchmove' event */\n onTouchMove = (event) => {\n const { clientX, clientY } = event.targetTouches ? event.targetTouches[0] : event;\n const deltaX = -(clientX - this.touchStart.x) * this.options.touchMultiplier;\n const deltaY = -(clientY - this.touchStart.y) * this.options.touchMultiplier;\n this.touchStart.x = clientX;\n this.touchStart.y = clientY;\n this.lastDelta = {\n x: deltaX,\n y: deltaY\n };\n this.emitter.emit(\"scroll\", {\n deltaX,\n deltaY,\n event\n });\n };\n onTouchEnd = (event) => {\n this.emitter.emit(\"scroll\", {\n deltaX: this.lastDelta.x,\n deltaY: this.lastDelta.y,\n event\n });\n };\n /** Event handler for 'wheel' event */\n onWheel = (event) => {\n let { deltaX, deltaY, deltaMode } = event;\n const multiplierX = deltaMode === 1 ? LINE_HEIGHT : deltaMode === 2 ? this.window.width : 1;\n const multiplierY = deltaMode === 1 ? LINE_HEIGHT : deltaMode === 2 ? this.window.height : 1;\n deltaX *= multiplierX;\n deltaY *= multiplierY;\n deltaX *= this.options.wheelMultiplier;\n deltaY *= this.options.wheelMultiplier;\n this.emitter.emit(\"scroll\", { deltaX, deltaY, event });\n };\n onWindowResize = () => {\n this.window = {\n width: window.innerWidth,\n height: window.innerHeight\n };\n };\n};\n\n// packages/core/src/lenis.ts\nvar Lenis = class {\n _isScrolling = false;\n // true when scroll is animating\n _isStopped = false;\n // true if user should not be able to scroll - enable/disable programmatically\n _isLocked = false;\n // same as isStopped but enabled/disabled when scroll reaches target\n _preventNextNativeScrollEvent = false;\n _resetVelocityTimeout = null;\n __rafID = null;\n /**\n * Whether or not the user is touching the screen\n */\n isTouching;\n /**\n * The time in ms since the lenis instance was created\n */\n time = 0;\n /**\n * User data that will be forwarded through the scroll event\n *\n * @example\n * lenis.scrollTo(100, {\n * userData: {\n * foo: 'bar'\n * }\n * })\n */\n userData = {};\n /**\n * The last velocity of the scroll\n */\n lastVelocity = 0;\n /**\n * The current velocity of the scroll\n */\n velocity = 0;\n /**\n * The direction of the scroll\n */\n direction = 0;\n /**\n * The options passed to the lenis instance\n */\n options;\n /**\n * The target scroll value\n */\n targetScroll;\n /**\n * The animated scroll value\n */\n animatedScroll;\n // These are instanciated here as they don't need information from the options\n animate = new Animate();\n emitter = new Emitter();\n // These are instanciated in the constructor as they need information from the options\n dimensions;\n // This is not private because it's used in the Snap class\n virtualScroll;\n constructor({\n wrapper = window,\n content = document.documentElement,\n eventsTarget = wrapper,\n smoothWheel = true,\n syncTouch = false,\n syncTouchLerp = 0.075,\n touchInertiaMultiplier = 35,\n duration,\n // in seconds\n easing = (t) => Math.min(1, 1.001 - Math.pow(2, -10 * t)),\n lerp: lerp2 = 0.1,\n infinite = false,\n orientation = \"vertical\",\n // vertical, horizontal\n gestureOrientation = \"vertical\",\n // vertical, horizontal, both\n touchMultiplier = 1,\n wheelMultiplier = 1,\n autoResize = true,\n prevent,\n virtualScroll,\n overscroll = true,\n autoRaf = false,\n anchors = false,\n autoToggle = false,\n // https://caniuse.com/?search=transition-behavior\n allowNestedScroll = false,\n __experimental__naiveDimensions = false\n } = {}) {\n window.lenisVersion = version;\n if (!wrapper || wrapper === document.documentElement) {\n wrapper = window;\n }\n this.options = {\n wrapper,\n content,\n eventsTarget,\n smoothWheel,\n syncTouch,\n syncTouchLerp,\n touchInertiaMultiplier,\n duration,\n easing,\n lerp: lerp2,\n infinite,\n gestureOrientation,\n orientation,\n touchMultiplier,\n wheelMultiplier,\n autoResize,\n prevent,\n virtualScroll,\n overscroll,\n autoRaf,\n anchors,\n autoToggle,\n allowNestedScroll,\n __experimental__naiveDimensions\n };\n this.dimensions = new Dimensions(wrapper, content, { autoResize });\n this.updateClassName();\n this.targetScroll = this.animatedScroll = this.actualScroll;\n this.options.wrapper.addEventListener(\"scroll\", this.onNativeScroll, false);\n this.options.wrapper.addEventListener(\"scrollend\", this.onScrollEnd, {\n capture: true\n });\n if (this.options.anchors && this.options.wrapper === window) {\n this.options.wrapper.addEventListener(\n \"click\",\n this.onClick,\n false\n );\n }\n this.options.wrapper.addEventListener(\n \"pointerdown\",\n this.onPointerDown,\n false\n );\n this.virtualScroll = new VirtualScroll(eventsTarget, {\n touchMultiplier,\n wheelMultiplier\n });\n this.virtualScroll.on(\"scroll\", this.onVirtualScroll);\n if (this.options.autoToggle) {\n this.rootElement.addEventListener(\"transitionend\", this.onTransitionEnd, {\n passive: true\n });\n }\n if (this.options.autoRaf) {\n this.__rafID = requestAnimationFrame(this.raf);\n }\n }\n /**\n * Destroy the lenis instance, remove all event listeners and clean up the class name\n */\n destroy() {\n this.emitter.destroy();\n this.options.wrapper.removeEventListener(\n \"scroll\",\n this.onNativeScroll,\n false\n );\n this.options.wrapper.removeEventListener(\"scrollend\", this.onScrollEnd, {\n capture: true\n });\n this.options.wrapper.removeEventListener(\n \"pointerdown\",\n this.onPointerDown,\n false\n );\n if (this.options.anchors && this.options.wrapper === window) {\n this.options.wrapper.removeEventListener(\n \"click\",\n this.onClick,\n false\n );\n }\n this.virtualScroll.destroy();\n this.dimensions.destroy();\n this.cleanUpClassName();\n if (this.__rafID) {\n cancelAnimationFrame(this.__rafID);\n }\n }\n on(event, callback) {\n return this.emitter.on(event, callback);\n }\n off(event, callback) {\n return this.emitter.off(event, callback);\n }\n onScrollEnd = (e) => {\n if (!(e instanceof CustomEvent)) {\n if (this.isScrolling === \"smooth\" || this.isScrolling === false) {\n e.stopPropagation();\n }\n }\n };\n dispatchScrollendEvent = () => {\n this.options.wrapper.dispatchEvent(\n new CustomEvent(\"scrollend\", {\n bubbles: this.options.wrapper === window,\n // cancelable: false,\n detail: {\n lenisScrollEnd: true\n }\n })\n );\n };\n onTransitionEnd = (event) => {\n if (event.propertyName.includes(\"overflow\")) {\n const property = this.isHorizontal ? \"overflow-x\" : \"overflow-y\";\n const overflow = getComputedStyle(this.rootElement)[property];\n if ([\"hidden\", \"clip\"].includes(overflow)) {\n this.stop();\n } else {\n this.start();\n }\n }\n };\n setScroll(scroll) {\n if (this.isHorizontal) {\n this.options.wrapper.scrollTo({ left: scroll, behavior: \"instant\" });\n } else {\n this.options.wrapper.scrollTo({ top: scroll, behavior: \"instant\" });\n }\n }\n onClick = (event) => {\n const path = event.composedPath();\n const anchor = path.find(\n (node) => node instanceof HTMLAnchorElement && (node.getAttribute(\"href\")?.startsWith(\"#\") || node.getAttribute(\"href\")?.startsWith(\"/#\") || node.getAttribute(\"href\")?.startsWith(\"./#\"))\n );\n if (anchor) {\n const id = anchor.getAttribute(\"href\");\n if (id) {\n const options = typeof this.options.anchors === \"object\" && this.options.anchors ? this.options.anchors : void 0;\n let target = `#${id.split(\"#\")[1]}`;\n if ([\"#\", \"/#\", \"./#\", \"#top\", \"/#top\", \"./#top\"].includes(id)) {\n target = 0;\n }\n this.scrollTo(target, options);\n }\n }\n };\n onPointerDown = (event) => {\n if (event.button === 1) {\n this.reset();\n }\n };\n onVirtualScroll = (data) => {\n if (typeof this.options.virtualScroll === \"function\" && this.options.virtualScroll(data) === false)\n return;\n const { deltaX, deltaY, event } = data;\n this.emitter.emit(\"virtual-scroll\", { deltaX, deltaY, event });\n if (event.ctrlKey) return;\n if (event.lenisStopPropagation) return;\n const isTouch = event.type.includes(\"touch\");\n const isWheel = event.type.includes(\"wheel\");\n this.isTouching = event.type === \"touchstart\" || event.type === \"touchmove\";\n const isClickOrTap = deltaX === 0 && deltaY === 0;\n const isTapToStop = this.options.syncTouch && isTouch && event.type === \"touchstart\" && isClickOrTap && !this.isStopped && !this.isLocked;\n if (isTapToStop) {\n this.reset();\n return;\n }\n const isUnknownGesture = this.options.gestureOrientation === \"vertical\" && deltaY === 0 || this.options.gestureOrientation === \"horizontal\" && deltaX === 0;\n if (isClickOrTap || isUnknownGesture) {\n return;\n }\n let composedPath = event.composedPath();\n composedPath = composedPath.slice(0, composedPath.indexOf(this.rootElement));\n const prevent = this.options.prevent;\n if (!!composedPath.find(\n (node) => node instanceof HTMLElement && (typeof prevent === \"function\" && prevent?.(node) || node.hasAttribute?.(\"data-lenis-prevent\") || isTouch && node.hasAttribute?.(\"data-lenis-prevent-touch\") || isWheel && node.hasAttribute?.(\"data-lenis-prevent-wheel\") || this.options.allowNestedScroll && this.checkNestedScroll(node, { deltaX, deltaY }))\n ))\n return;\n if (this.isStopped || this.isLocked) {\n event.preventDefault();\n return;\n }\n const isSmooth = this.options.syncTouch && isTouch || this.options.smoothWheel && isWheel;\n if (!isSmooth) {\n this.isScrolling = \"native\";\n this.animate.stop();\n event.lenisStopPropagation = true;\n return;\n }\n let delta = deltaY;\n if (this.options.gestureOrientation === \"both\") {\n delta = Math.abs(deltaY) > Math.abs(deltaX) ? deltaY : deltaX;\n } else if (this.options.gestureOrientation === \"horizontal\") {\n delta = deltaX;\n }\n if (!this.options.overscroll || this.options.infinite || this.options.wrapper !== window && (this.animatedScroll > 0 && this.animatedScroll < this.limit || this.animatedScroll === 0 && deltaY > 0 || this.animatedScroll === this.limit && deltaY < 0)) {\n event.lenisStopPropagation = true;\n }\n event.preventDefault();\n const isSyncTouch = isTouch && this.options.syncTouch;\n const isTouchEnd = isTouch && event.type === \"touchend\";\n const hasTouchInertia = isTouchEnd && Math.abs(delta) > 5;\n if (hasTouchInertia) {\n delta = this.velocity * this.options.touchInertiaMultiplier;\n }\n this.scrollTo(this.targetScroll + delta, {\n programmatic: false,\n ...isSyncTouch ? {\n lerp: hasTouchInertia ? this.options.syncTouchLerp : 1\n // immediate: !hasTouchInertia,\n } : {\n lerp: this.options.lerp,\n duration: this.options.duration,\n easing: this.options.easing\n }\n });\n };\n /**\n * Force lenis to recalculate the dimensions\n */\n resize() {\n this.dimensions.resize();\n this.animatedScroll = this.targetScroll = this.actualScroll;\n this.emit();\n }\n emit() {\n this.emitter.emit(\"scroll\", this);\n }\n onNativeScroll = () => {\n if (this._resetVelocityTimeout !== null) {\n clearTimeout(this._resetVelocityTimeout);\n this._resetVelocityTimeout = null;\n }\n if (this._preventNextNativeScrollEvent) {\n this._preventNextNativeScrollEvent = false;\n return;\n }\n if (this.isScrolling === false || this.isScrolling === \"native\") {\n const lastScroll = this.animatedScroll;\n this.animatedScroll = this.targetScroll = this.actualScroll;\n this.lastVelocity = this.velocity;\n this.velocity = this.animatedScroll - lastScroll;\n this.direction = Math.sign(\n this.animatedScroll - lastScroll\n );\n if (!this.isStopped) {\n this.isScrolling = \"native\";\n }\n this.emit();\n if (this.velocity !== 0) {\n this._resetVelocityTimeout = setTimeout(() => {\n this.lastVelocity = this.velocity;\n this.velocity = 0;\n this.isScrolling = false;\n this.emit();\n }, 400);\n }\n }\n };\n reset() {\n this.isLocked = false;\n this.isScrolling = false;\n this.animatedScroll = this.targetScroll = this.actualScroll;\n this.lastVelocity = this.velocity = 0;\n this.animate.stop();\n }\n /**\n * Start lenis scroll after it has been stopped\n */\n start() {\n if (!this.isStopped) return;\n this.reset();\n this.isStopped = false;\n }\n /**\n * Stop lenis scroll\n */\n stop() {\n if (this.isStopped) return;\n this.reset();\n this.isStopped = true;\n }\n /**\n * RequestAnimationFrame for lenis\n *\n * @param time The time in ms from an external clock like `requestAnimationFrame` or Tempus\n */\n raf = (time) => {\n const deltaTime = time - (this.time || time);\n this.time = time;\n this.animate.advance(deltaTime * 1e-3);\n if (this.options.autoRaf) {\n this.__rafID = requestAnimationFrame(this.raf);\n }\n };\n /**\n * Scroll to a target value\n *\n * @param target The target value to scroll to\n * @param options The options for the scroll\n *\n * @example\n * lenis.scrollTo(100, {\n * offset: 100,\n * duration: 1,\n * easing: (t) => 1 - Math.cos((t * Math.PI) / 2),\n * lerp: 0.1,\n * onStart: () => {\n * console.log('onStart')\n * },\n * onComplete: () => {\n * console.log('onComplete')\n * },\n * })\n */\n scrollTo(target, {\n offset = 0,\n immediate = false,\n lock = false,\n duration = this.options.duration,\n easing = this.options.easing,\n lerp: lerp2 = this.options.lerp,\n onStart,\n onComplete,\n force = false,\n // scroll even if stopped\n programmatic = true,\n // called from outside of the class\n userData\n } = {}) {\n if ((this.isStopped || this.isLocked) && !force) return;\n if (typeof target === \"string\" && [\"top\", \"left\", \"start\"].includes(target)) {\n target = 0;\n } else if (typeof target === \"string\" && [\"bottom\", \"right\", \"end\"].includes(target)) {\n target = this.limit;\n } else {\n let node;\n if (typeof target === \"string\") {\n node = document.querySelector(target);\n } else if (target instanceof HTMLElement && target?.nodeType) {\n node = target;\n }\n if (node) {\n if (this.options.wrapper !== window) {\n const wrapperRect = this.rootElement.getBoundingClientRect();\n offset -= this.isHorizontal ? wrapperRect.left : wrapperRect.top;\n }\n const rect = node.getBoundingClientRect();\n target = (this.isHorizontal ? rect.left : rect.top) + this.animatedScroll;\n }\n }\n if (typeof target !== \"number\") return;\n target += offset;\n target = Math.round(target);\n if (this.options.infinite) {\n if (programmatic) {\n this.targetScroll = this.animatedScroll = this.scroll;\n const distance = target - this.animatedScroll;\n if (distance > this.limit / 2) {\n target = target - this.limit;\n } else if (distance < -this.limit / 2) {\n target = target + this.limit;\n }\n }\n } else {\n target = clamp(0, target, this.limit);\n }\n if (target === this.targetScroll) {\n onStart?.(this);\n onComplete?.(this);\n return;\n }\n this.userData = userData ?? {};\n if (immediate) {\n this.animatedScroll = this.targetScroll = target;\n this.setScroll(this.scroll);\n this.reset();\n this.preventNextNativeScrollEvent();\n this.emit();\n onComplete?.(this);\n this.userData = {};\n requestAnimationFrame(() => {\n this.dispatchScrollendEvent();\n });\n return;\n }\n if (!programmatic) {\n this.targetScroll = target;\n }\n this.animate.fromTo(this.animatedScroll, target, {\n duration,\n easing,\n lerp: lerp2,\n onStart: () => {\n if (lock) this.isLocked = true;\n this.isScrolling = \"smooth\";\n onStart?.(this);\n },\n onUpdate: (value, completed) => {\n this.isScrolling = \"smooth\";\n this.lastVelocity = this.velocity;\n this.velocity = value - this.animatedScroll;\n this.direction = Math.sign(this.velocity);\n this.animatedScroll = value;\n this.setScroll(this.scroll);\n if (programmatic) {\n this.targetScroll = value;\n }\n if (!completed) this.emit();\n if (completed) {\n this.reset();\n this.emit();\n onComplete?.(this);\n this.userData = {};\n requestAnimationFrame(() => {\n this.dispatchScrollendEvent();\n });\n this.preventNextNativeScrollEvent();\n }\n }\n });\n }\n preventNextNativeScrollEvent() {\n this._preventNextNativeScrollEvent = true;\n requestAnimationFrame(() => {\n this._preventNextNativeScrollEvent = false;\n });\n }\n checkNestedScroll(node, { deltaX, deltaY }) {\n const time = Date.now();\n const cache = node._lenis ??= {};\n let hasOverflowX, hasOverflowY, isScrollableX, isScrollableY, scrollWidth, scrollHeight, clientWidth, clientHeight;\n const gestureOrientation = this.options.gestureOrientation;\n if (time - (cache.time ?? 0) > 2e3) {\n cache.time = Date.now();\n const computedStyle = window.getComputedStyle(node);\n cache.computedStyle = computedStyle;\n const overflowXString = computedStyle.overflowX;\n const overflowYString = computedStyle.overflowY;\n hasOverflowX = [\"auto\", \"overlay\", \"scroll\"].includes(overflowXString);\n hasOverflowY = [\"auto\", \"overlay\", \"scroll\"].includes(overflowYString);\n cache.hasOverflowX = hasOverflowX;\n cache.hasOverflowY = hasOverflowY;\n if (!hasOverflowX && !hasOverflowY) return false;\n if (gestureOrientation === \"vertical\" && !hasOverflowY) return false;\n if (gestureOrientation === \"horizontal\" && !hasOverflowX) return false;\n scrollWidth = node.scrollWidth;\n scrollHeight = node.scrollHeight;\n clientWidth = node.clientWidth;\n clientHeight = node.clientHeight;\n isScrollableX = scrollWidth > clientWidth;\n isScrollableY = scrollHeight > clientHeight;\n cache.isScrollableX = isScrollableX;\n cache.isScrollableY = isScrollableY;\n cache.scrollWidth = scrollWidth;\n cache.scrollHeight = scrollHeight;\n cache.clientWidth = clientWidth;\n cache.clientHeight = clientHeight;\n } else {\n isScrollableX = cache.isScrollableX;\n isScrollableY = cache.isScrollableY;\n hasOverflowX = cache.hasOverflowX;\n hasOverflowY = cache.hasOverflowY;\n scrollWidth = cache.scrollWidth;\n scrollHeight = cache.scrollHeight;\n clientWidth = cache.clientWidth;\n clientHeight = cache.clientHeight;\n }\n if (!hasOverflowX && !hasOverflowY || !isScrollableX && !isScrollableY) {\n return false;\n }\n if (gestureOrientation === \"vertical\" && (!hasOverflowY || !isScrollableY))\n return false;\n if (gestureOrientation === \"horizontal\" && (!hasOverflowX || !isScrollableX))\n return false;\n let orientation;\n if (gestureOrientation === \"horizontal\") {\n orientation = \"x\";\n } else if (gestureOrientation === \"vertical\") {\n orientation = \"y\";\n } else {\n const isScrollingX = deltaX !== 0;\n const isScrollingY = deltaY !== 0;\n if (isScrollingX && hasOverflowX && isScrollableX) {\n orientation = \"x\";\n }\n if (isScrollingY && hasOverflowY && isScrollableY) {\n orientation = \"y\";\n }\n }\n if (!orientation) return false;\n let scroll, maxScroll, delta, hasOverflow, isScrollable;\n if (orientation === \"x\") {\n scroll = node.scrollLeft;\n maxScroll = scrollWidth - clientWidth;\n delta = deltaX;\n hasOverflow = hasOverflowX;\n isScrollable = isScrollableX;\n } else if (orientation === \"y\") {\n scroll = node.scrollTop;\n maxScroll = scrollHeight - clientHeight;\n delta = deltaY;\n hasOverflow = hasOverflowY;\n isScrollable = isScrollableY;\n } else {\n return false;\n }\n const willScroll = delta > 0 ? scroll < maxScroll : scroll > 0;\n return willScroll && hasOverflow && isScrollable;\n }\n /**\n * The root element on which lenis is instanced\n */\n get rootElement() {\n return this.options.wrapper === window ? document.documentElement : this.options.wrapper;\n }\n /**\n * The limit which is the maximum scroll value\n */\n get limit() {\n if (this.options.__experimental__naiveDimensions) {\n if (this.isHorizontal) {\n return this.rootElement.scrollWidth - this.rootElement.clientWidth;\n } else {\n return this.rootElement.scrollHeight - this.rootElement.clientHeight;\n }\n } else {\n return this.dimensions.limit[this.isHorizontal ? \"x\" : \"y\"];\n }\n }\n /**\n * Whether or not the scroll is horizontal\n */\n get isHorizontal() {\n return this.options.orientation === \"horizontal\";\n }\n /**\n * The actual scroll value\n */\n get actualScroll() {\n const wrapper = this.options.wrapper;\n return this.isHorizontal ? wrapper.scrollX ?? wrapper.scrollLeft : wrapper.scrollY ?? wrapper.scrollTop;\n }\n /**\n * The current scroll value\n */\n get scroll() {\n return this.options.infinite ? modulo(this.animatedScroll, this.limit) : this.animatedScroll;\n }\n /**\n * The progress of the scroll relative to the limit\n */\n get progress() {\n return this.limit === 0 ? 1 : this.scroll / this.limit;\n }\n /**\n * Current scroll state\n */\n get isScrolling() {\n return this._isScrolling;\n }\n set isScrolling(value) {\n if (this._isScrolling !== value) {\n this._isScrolling = value;\n this.updateClassName();\n }\n }\n /**\n * Check if lenis is stopped\n */\n get isStopped() {\n return this._isStopped;\n }\n set isStopped(value) {\n if (this._isStopped !== value) {\n this._isStopped = value;\n this.updateClassName();\n }\n }\n /**\n * Check if lenis is locked\n */\n get isLocked() {\n return this._isLocked;\n }\n set isLocked(value) {\n if (this._isLocked !== value) {\n this._isLocked = value;\n this.updateClassName();\n }\n }\n /**\n * Check if lenis is smooth scrolling\n */\n get isSmooth() {\n return this.isScrolling === \"smooth\";\n }\n /**\n * The class name applied to the wrapper element\n */\n get className() {\n let className = \"lenis\";\n if (this.options.autoToggle) className += \" lenis-autoToggle\";\n if (this.isStopped) className += \" lenis-stopped\";\n if (this.isLocked) className += \" lenis-locked\";\n if (this.isScrolling) className += \" lenis-scrolling\";\n if (this.isScrolling === \"smooth\") className += \" lenis-smooth\";\n return className;\n }\n updateClassName() {\n this.cleanUpClassName();\n this.rootElement.className = `${this.rootElement.className} ${this.className}`.trim();\n }\n cleanUpClassName() {\n this.rootElement.className = this.rootElement.className.replace(/lenis(-\\w+)?/g, \"\").trim();\n }\n};\nexport {\n Lenis as default\n};\n//# sourceMappingURL=lenis.mjs.map","import Lenis from 'lenis'\r\nclass FeatherScroll {\r\n // Stores all instances of FeatherScroll\r\n static instances = [];\r\n constructor(options = {}) {\r\n this.wrapper = options.wrapper || document.documentElement;\r\n this.content = options.content || document.body;\r\n // Initialize Lenis with custom options or defaults\r\n this.lenis = new Lenis({\r\n wrapper: this.wrapper,\r\n content: this.content,\r\n smooth: options.smooth ?? true,\r\n duration: options.duration ?? 1.2,\r\n easing: options.easing ?? ((t) => 1 - Math.pow(1 - t, 3)),\r\n direction: options.direction ?? 'vertical',\r\n gestureDirection: options.gestureDirection ?? 'both',\r\n wheelMultiplier: options.mouseSenstivity ?? 1,\r\n touchMultiplier: options.touchSenstivity ?? 2,\r\n infinite: options.infinite ?? false\r\n });\r\n // Scroll direction tracking\r\n this.scrollDirection = 'down';\r\n this.lastScroll = 0;\r\n // Elements with sticky and parallax behavior\r\n this.stickyElements = [...this.content.querySelectorAll('[data-scroll-sticky]')];\r\n this.parallaxElements = [...this.content.querySelectorAll('[data-scroll-speed]')];\r\n // Store initial positions for parallax elements\r\n this.parallaxElements.forEach((el) => {\r\n const rect = el.getBoundingClientRect();\r\n el.dataset.initialTop = rect.top + window.scrollY;\r\n el.dataset.initialLeft = rect.left + window.scrollX;\r\n });\r\n // Initialize features\r\n this.initStickyElements();\r\n this.trackScrollDirection();\r\n this.startRAF(); // Start animation loop\r\n FeatherScroll.instances.push(this); // Register instance\r\n if (window.ScrollTrigger) {\r\n this.setupScrollTrigger();\r\n }\r\n // Observe body overflow for automatic disabling\r\n this.observeBodyOverflow();\r\n }\r\n // RAF loop for Lenis + sticky + parallax\r\n startRAF() {\r\n const raf = (time) => {\r\n this.lenis.raf(time);\r\n this.updateStickyElements();\r\n this.updateParallax();\r\n requestAnimationFrame(raf);\r\n };\r\n requestAnimationFrame(raf);\r\n }\r\n // Detect scroll direction: 'up' or 'down'\r\n trackScrollDirection() {\r\n this.lenis.on('scroll', ({ scroll }) => {\r\n const newDirection = scroll > this.lastScroll ? 'down' : 'up';\r\n if (newDirection !== this.scrollDirection) {\r\n this.scrollDirection = newDirection;\r\n }\r\n this.lastScroll = scroll;\r\n });\r\n }\r\n // Observe overflow-y on body, pause/resume Lenis\r\n observeBodyOverflow() {\r\n const observer = new MutationObserver(() => {\r\n const overflowY = window.getComputedStyle(document.body).overflowY;\r\n if (overflowY === 'hidden') {\r\n this.lenis.stop();\r\n } else {\r\n this.lenis.start();\r\n }\r\n });\r\n observer.observe(document.body, {\r\n attributes: true,\r\n attributeFilter: ['style']\r\n });\r\n // Initial check\r\n const initialOverflowY = window.getComputedStyle(document.body).overflowY;\r\n if (initialOverflowY === 'hidden') {\r\n this.lenis.stop();\r\n }\r\n }\r\n // Return current scroll direction\r\n getScrollDirection() {\r\n return this.scrollDirection || 'down';\r\n }\r\n // Set initial positions for sticky elements\r\n initStickyElements() {\r\n this.stickyElements.forEach((el) => {\r\n const parent = el.parentElement;\r\n const rect = el.getBoundingClientRect();\r\n el.dataset.stickyStart = parent.offsetTop;\r\n el.dataset.stickyEnd = parent.offsetTop + parent.offsetHeight;\r\n el.dataset.originalWidth = `${rect.width}px`;\r\n el.dataset.originalHeight = `${rect.height}px`;\r\n });\r\n }\r\n // Update sticky element positions\r\n updateStickyElements() {\r\n const scrollY = this.lenis.scroll;\r\n const viewportHeight = window.innerHeight;\r\n this.stickyElements.forEach((el) => {\r\n const parent = el.parentElement;\r\n const nextSibling = parent.nextElementSibling;\r\n if (!nextSibling) return;\r\n const stickyStart = parseFloat(el.dataset.stickyStart);\r\n const stickyEnd = parseFloat(el.dataset.stickyEnd);\r\n const parentRect = parent.getBoundingClientRect();\r\n const nextRect = nextSibling.getBoundingClientRect();\r\n // If next section enters halfway viewport, stop sticking\r\n const isNextEntering = nextRect.top < viewportHeight * 0.5;\r\n if (scrollY >= stickyStart && scrollY < stickyEnd && !isNextEntering) {\r\n el.style.position = 'fixed';\r\n el.style.top = `${window.innerHeight / 2 - el.offsetHeight / 2}px`;\r\n el.style.left = `${parentRect.left + parentRect.width / 2 - el.offsetWidth / 2}px`;\r\n el.style.opacity = '1';\r\n } else {\r\n el.style.position = 'relative';\r\n el.style.opacity = '0';\r\n }\r\n });\r\n }\r\n // Apply parallax effect based on data attributes\r\n updateParallax() {\r\n const scrollY = this.lenis.scroll;\r\n this.parallaxElements.forEach((el) => {\r\n const speed = parseFloat(el.getAttribute(\"data-scroll-speed\")) || 1;\r\n const direction = el.getAttribute(\"data-scroll-direction\") || \"vertical\";\r\n const initialTop = parseFloat(el.dataset.initialTop);\r\n const initialLeft = parseFloat(el.dataset.initialLeft);\r\n let offsetX = 0, offsetY = 0;\r\n if (direction === \"horizontal\") {\r\n offsetX = (scrollY - initialTop) * speed * 0.1;\r\n } else if (direction === \"vertical\") {\r\n offsetY = (scrollY - initialTop) * speed * 0.1;\r\n } else if (direction === \"both\") {\r\n offsetX = (scrollY - initialTop) * speed * 0.1;\r\n offsetY = (scrollY - initialTop) * speed * 0.1;\r\n }\r\n // If GSAP is present, respect GSAP transforms\r\n let gsapX = 0, gsapY = 0;\r\n if (window.gsap) {\r\n gsapX = gsap.getProperty(el, \"x\") || 0;\r\n gsapY = gsap.getProperty(el, \"y\") || 0;\r\n }\r\n el.style.transform = `translate3d(${offsetX + gsapX}px, ${offsetY + gsapY}px, 0)`;\r\n });\r\n }\r\n // Integration with GSAP ScrollTrigger\r\n setupScrollTrigger() {\r\n this.lenis.on('scroll', () => {\r\n ScrollTrigger.update();\r\n });\r\n }\r\n // Public method: Scroll to a target\r\n scrollTo(target, options = {}) {\r\n this.lenis.scrollTo(target, options);\r\n }\r\n // Public method: Start scrolling\r\n start() {\r\n this.lenis.start();\r\n }\r\n // Public method: Stop scrolling\r\n stop() {\r\n this.lenis.stop();\r\n }\r\n // Public method: Destroy the instance\r\n destroy() {\r\n this.lenis.destroy();\r\n FeatherScroll.instances = FeatherScroll.instances.filter((instance) => instance !== this);\r\n }\r\n // Public method: Get scroll position\r\n getScrollPosition() {\r\n return this.lenis.scroll;\r\n }\r\n // Update Lenis options dynamically\r\n updateOptions(newOptions) {\r\n Object.assign(this.lenis.options, newOptions);\r\n }\r\n }\r\nexport default FeatherScroll;\r\n\r\n// Also attach to window for CDN users\r\nif (typeof window !== 'undefined') {\r\n window.FeatherScroll = FeatherScroll;\r\n}"],"names":["clamp","min","input","max","Math","Animate","isRunning","value","from","to","currentTime","lerp","duration","easing","onUpdate","advance","deltaTime","this","completed","linearProgress","easedProgress","x","y","lambda","t","exp","damp","round","stop","fromTo","lerp2","onStart","Dimensions","constructor","wrapper","content","autoResize","debounce","debounceValue","debouncedResize","callback","delay","timer","args","context","clearTimeout","setTimeout","apply","resize","Window","window","addEventListener","wrapperResizeObserver","ResizeObserver","observe","contentResizeObserver","width","height","scrollHeight","scrollWidth","destroy","disconnect","removeEventListener","onWrapperResize","onContentResize","innerWidth","innerHeight","clientWidth","clientHeight","limit","Emitter","events","emit","event","callbacks","i","length","on","cb","push","filter","off","LINE_HEIGHT","listenerOptions","passive","VirtualScroll","element","options","wheelMultiplier","touchMultiplier","onWindowResize","onWheel","onTouchStart","onTouchMove","onTouchEnd","touchStart","lastDelta","emitter","clientX","clientY","targetTouches","deltaX","deltaY","deltaMode","Lenis","_isScrolling","_isStopped","_isLocked","_preventNextNativeScrollEvent","_resetVelocityTimeout","__rafID","isTouching","time","userData","lastVelocity","velocity","direction","targetScroll","animatedScroll","animate","dimensions","virtualScroll","document","documentElement","eventsTarget","smoothWheel","syncTouch","syncTouchLerp","touchInertiaMultiplier","pow","infinite","orientation","gestureOrientation","prevent","overscroll","autoRaf","anchors","autoToggle","allowNestedScroll","__experimental__naiveDimensions","lenisVersion","updateClassName","actualScroll","onNativeScroll","onScrollEnd","capture","onClick","onPointerDown","onVirtualScroll","rootElement","onTransitionEnd","requestAnimationFrame","raf","cleanUpClassName","cancelAnimationFrame","e","CustomEvent","isScrolling","stopPropagation","dispatchScrollendEvent","dispatchEvent","bubbles","detail","lenisScrollEnd","propertyName","includes","property","isHorizontal","overflow","getComputedStyle","start","setScroll","scroll","scrollTo","left","behavior","top","anchor","composedPath","find","node","HTMLAnchorElement","getAttribute","startsWith","id","target","split","button","reset","data","ctrlKey","lenisStopPropagation","isTouch","type","isWheel","isClickOrTap","isStopped","isLocked","isUnknownGesture","slice","indexOf","HTMLElement","hasAttribute","checkNestedScroll","preventDefault","delta","abs","isSyncTouch","hasTouchInertia","programmatic","lastScroll","sign","offset","immediate","lock","onComplete","force","querySelector","nodeType","wrapperRect","getBoundingClientRect","rect","distance","preventNextNativeScrollEvent","Date","now","cache","_lenis","hasOverflowX","hasOverflowY","isScrollableX","isScrollableY","computedStyle","overflowXString","overflowX","overflowYString","overflowY","maxScroll","hasOverflow","isScrollable","scrollLeft","scrollTop","scrollX","scrollY","n","d","progress","isSmooth","className","trim","replace","FeatherScroll","static","body","lenis","smooth","gestureDirection","mouseSenstivity","touchSenstivity","scrollDirection","stickyElements","querySelectorAll","parallaxElements","forEach","el","dataset","initialTop","initialLeft","initStickyElements","trackScrollDirection","startRAF","instances","ScrollTrigger","setupScrollTrigger","observeBodyOverflow","updateStickyElements","updateParallax","newDirection","MutationObserver","attributes","attributeFilter","getScrollDirection","parent","parentElement","stickyStart","offsetTop","stickyEnd","offsetHeight","originalWidth","originalHeight","viewportHeight","nextSibling","nextElementSibling","parseFloat","parentRect","isNextEntering","style","position","offsetWidth","opacity","speed","offsetX","offsetY","gsapX","gsapY","gsap","getProperty","transform","update","instance","getScrollPosition","updateOptions","newOptions","Object","assign"],"mappings":"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","x_google_ignoreList":[0]}
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "dependencies": {
3 | "@rollup/plugin-commonjs": "^28.0.3",
4 | "@rollup/plugin-node-resolve": "^16.0.1",
5 | "@rollup/plugin-terser": "^0.4.4",
6 | "lenis": "^1.3.1",
7 | "rollup": "^4.40.1"
8 | },
9 | "name": "scrollfeather",
10 | "version": "1.2.9",
11 | "description": "A lightweight and smooth scrolling library. Works for both full-page and container-based scrolling also supports all devices.",
12 | "main": "dist/featherScroll.min.js",
13 | "module": "dist/featherScroll.esm.js",
14 | "unpkg": "dist/featherScroll.min.js",
15 | "scripts": {
16 | "test": "echo \"Error: no test specified\" && exit 1",
17 | "build": "rollup -c"
18 | },
19 | "repository": {
20 | "type": "git",
21 | "url": "git+https://github.com/ranvijay-raj/Feather-scroll-js.git"
22 | },
23 | "keywords": [
24 | "smooth-scroll",
25 | "lenis",
26 | "scroll-library",
27 | "animation",
28 | "featherscroll",
29 | "scrollfeather"
30 | ],
31 | "author": "Ranvijay raj",
32 | "license": "MIT",
33 | "bugs": {
34 | "url": "https://github.com/ranvijay-raj/Feather-scroll-js/issues"
35 | },
36 | "homepage": "https://github.com/ranvijay-raj/Feather-scroll-js#readme"
37 | }
38 |
--------------------------------------------------------------------------------
/src/featherScroll.js:
--------------------------------------------------------------------------------
1 | import Lenis from 'lenis'
2 | class FeatherScroll {
3 | // Stores all instances of FeatherScroll
4 | static instances = [];
5 | constructor(options = {}) {
6 | this.wrapper = options.wrapper || document.documentElement;
7 | this.content = options.content || document.body;
8 | // Initialize Lenis with custom options or defaults
9 | this.lenis = new Lenis({
10 | wrapper: this.wrapper,
11 | content: this.content,
12 | smooth: options.smooth ?? true,
13 | duration: options.duration ?? 1.2,
14 | easing: options.easing ?? ((t) => 1 - Math.pow(1 - t, 3)),
15 | direction: options.direction ?? 'vertical',
16 | gestureDirection: options.gestureDirection ?? 'both',
17 | wheelMultiplier: options.mouseSenstivity ?? 1,
18 | touchMultiplier: options.touchSenstivity ?? 2,
19 | infinite: options.infinite ?? false
20 | });
21 | // Scroll direction tracking
22 | this.scrollDirection = 'down';
23 | this.lastScroll = 0;
24 | // Elements with sticky and parallax behavior
25 | this.stickyElements = [...this.content.querySelectorAll('[data-scroll-sticky]')];
26 | this.parallaxElements = [...this.content.querySelectorAll('[data-scroll-speed]')];
27 | // Store initial positions for parallax elements
28 | this.parallaxElements.forEach((el) => {
29 | const rect = el.getBoundingClientRect();
30 | el.dataset.initialTop = rect.top + window.scrollY;
31 | el.dataset.initialLeft = rect.left + window.scrollX;
32 | });
33 | // Initialize features
34 | this.initStickyElements();
35 | this.trackScrollDirection();
36 | this.startRAF(); // Start animation loop
37 | FeatherScroll.instances.push(this); // Register instance
38 | if (window.ScrollTrigger) {
39 | this.setupScrollTrigger();
40 | }
41 | // Observe body overflow for automatic disabling
42 | this.observeBodyOverflow();
43 | }
44 | // RAF loop for Lenis + sticky + parallax
45 | startRAF() {
46 | const raf = (time) => {
47 | this.lenis.raf(time);
48 | this.updateStickyElements();
49 | this.updateParallax();
50 | requestAnimationFrame(raf);
51 | };
52 | requestAnimationFrame(raf);
53 | }
54 | // Detect scroll direction: 'up' or 'down'
55 | trackScrollDirection() {
56 | this.lenis.on('scroll', ({ scroll }) => {
57 | const newDirection = scroll > this.lastScroll ? 'down' : 'up';
58 | if (newDirection !== this.scrollDirection) {
59 | this.scrollDirection = newDirection;
60 | }
61 | this.lastScroll = scroll;
62 | });
63 | }
64 | // Observe overflow-y on body, pause/resume Lenis
65 | observeBodyOverflow() {
66 | const observer = new MutationObserver(() => {
67 | const overflowY = window.getComputedStyle(document.body).overflowY;
68 | if (overflowY === 'hidden') {
69 | this.lenis.stop();
70 | } else {
71 | this.lenis.start();
72 | }
73 | });
74 | observer.observe(document.body, {
75 | attributes: true,
76 | attributeFilter: ['style']
77 | });
78 | // Initial check
79 | const initialOverflowY = window.getComputedStyle(document.body).overflowY;
80 | if (initialOverflowY === 'hidden') {
81 | this.lenis.stop();
82 | }
83 | }
84 | // Return current scroll direction
85 | getScrollDirection() {
86 | return this.scrollDirection || 'down';
87 | }
88 | // Set initial positions for sticky elements
89 | initStickyElements() {
90 | this.stickyElements.forEach((el) => {
91 | const parent = el.parentElement;
92 | const rect = el.getBoundingClientRect();
93 | el.dataset.stickyStart = parent.offsetTop;
94 | el.dataset.stickyEnd = parent.offsetTop + parent.offsetHeight;
95 | el.dataset.originalWidth = `${rect.width}px`;
96 | el.dataset.originalHeight = `${rect.height}px`;
97 | });
98 | }
99 | // Update sticky element positions
100 | updateStickyElements() {
101 | const scrollY = this.lenis.scroll;
102 | const viewportHeight = window.innerHeight;
103 | this.stickyElements.forEach((el) => {
104 | const parent = el.parentElement;
105 | const nextSibling = parent.nextElementSibling;
106 | if (!nextSibling) return;
107 | const stickyStart = parseFloat(el.dataset.stickyStart);
108 | const stickyEnd = parseFloat(el.dataset.stickyEnd);
109 | const parentRect = parent.getBoundingClientRect();
110 | const nextRect = nextSibling.getBoundingClientRect();
111 | // If next section enters halfway viewport, stop sticking
112 | const isNextEntering = nextRect.top < viewportHeight * 0.5;
113 | if (scrollY >= stickyStart && scrollY < stickyEnd && !isNextEntering) {
114 | el.style.position = 'fixed';
115 | el.style.top = `${window.innerHeight / 2 - el.offsetHeight / 2}px`;
116 | el.style.left = `${parentRect.left + parentRect.width / 2 - el.offsetWidth / 2}px`;
117 | el.style.opacity = '1';
118 | } else {
119 | el.style.position = 'relative';
120 | el.style.opacity = '0';
121 | }
122 | });
123 | }
124 | // Apply parallax effect based on data attributes
125 | updateParallax() {
126 | const scrollY = this.lenis.scroll;
127 | this.parallaxElements.forEach((el) => {
128 | const speed = parseFloat(el.getAttribute("data-scroll-speed")) || 1;
129 | const direction = el.getAttribute("data-scroll-direction") || "vertical";
130 | const initialTop = parseFloat(el.dataset.initialTop);
131 | const initialLeft = parseFloat(el.dataset.initialLeft);
132 | let offsetX = 0, offsetY = 0;
133 | if (direction === "horizontal") {
134 | offsetX = (scrollY - initialTop) * speed * 0.1;
135 | } else if (direction === "vertical") {
136 | offsetY = (scrollY - initialTop) * speed * 0.1;
137 | } else if (direction === "both") {
138 | offsetX = (scrollY - initialTop) * speed * 0.1;
139 | offsetY = (scrollY - initialTop) * speed * 0.1;
140 | }
141 | // If GSAP is present, respect GSAP transforms
142 | let gsapX = 0, gsapY = 0;
143 | if (window.gsap) {
144 | gsapX = gsap.getProperty(el, "x") || 0;
145 | gsapY = gsap.getProperty(el, "y") || 0;
146 | }
147 | el.style.transform = `translate3d(${offsetX + gsapX}px, ${offsetY + gsapY}px, 0)`;
148 | });
149 | }
150 | // Integration with GSAP ScrollTrigger
151 | setupScrollTrigger() {
152 | this.lenis.on('scroll', () => {
153 | ScrollTrigger.update();
154 | });
155 | }
156 | // Public method: Scroll to a target
157 | scrollTo(target, options = {}) {
158 | this.lenis.scrollTo(target, options);
159 | }
160 | // Public method: Start scrolling
161 | start() {
162 | this.lenis.start();
163 | }
164 | // Public method: Stop scrolling
165 | stop() {
166 | this.lenis.stop();
167 | }
168 | // Public method: Destroy the instance
169 | destroy() {
170 | this.lenis.destroy();
171 | FeatherScroll.instances = FeatherScroll.instances.filter((instance) => instance !== this);
172 | }
173 | // Public method: Get scroll position
174 | getScrollPosition() {
175 | return this.lenis.scroll;
176 | }
177 | // Update Lenis options dynamically
178 | updateOptions(newOptions) {
179 | Object.assign(this.lenis.options, newOptions);
180 | }
181 | }
182 | export default FeatherScroll;
183 |
184 | // Also attach to window for CDN users
185 | if (typeof window !== 'undefined') {
186 | window.FeatherScroll = FeatherScroll;
187 | }
--------------------------------------------------------------------------------