1/*** 2 Lenis is a lightweight, robust, and performant smooth scroll library. 3 It's designed by @darkroom.engineering to be simple to use and easy to integrate into your projects. 4 It's built with performance in mind and is optimized for modern browsers. 5 It's perfect for creating smooth scrolling experiences on your website such as webgl scroll synching, parallax effects and much more. 6 * Licensed under MIT (https://github.com/darkroomengineering/lenis?tab=MIT-1-ov-file#readme) 7 * Lenis v1.1.3 designed by darkroomengineering https://github.com/darkroomengineering/lenis 8 */ 9 10!(function (t, e) { 11 "object" == typeof exports && "undefined" != typeof module ? (module.exports = e()) : "function" == typeof define && define.amd ? define(e) : ((t = "undefined" != typeof globalThis ? globalThis : t || self).Lenis = e()); 12})(this, function () { 13 "use strict"; 14 function clamp(t, e, i) { 15 return Math.max(t, Math.min(e, i)); 16 } 17 class Animate { 18 advance(t) { 19 if (!this.isRunning) return; 20 let e = !1; 21 if (this.duration && this.easing) { 22 this.currentTime += t; 23 const i = clamp(0, this.currentTime / this.duration, 1); 24 e = i >= 1; 25 const s = e ? 1 : this.easing(i); 26 this.value = this.from + (this.to - this.from) * s; 27 } else 28 this.lerp 29 ? ((this.value = (function damp(t, e, i, s) { 30 return (function lerp(t, e, i) { 31 return (1 - i) * t + i * e; 32 })(t, e, 1 - Math.exp(-i * s)); 33 })(this.value, this.to, 60 * this.lerp, t)), 34 Math.round(this.value) === this.to && ((this.value = this.to), (e = !0))) 35 : ((this.value = this.to), (e = !0)); 36 e && this.stop(), this.onUpdate?.(this.value, e); 37 } 38 stop() { 39 this.isRunning = !1; 40 } 41 fromTo(t, e, { lerp: i, duration: s, easing: o, onStart: n, onUpdate: l }) { 42 (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 = l); 43 } 44 } 45 class Dimensions { 46 constructor({ wrapper: t, content: e, autoResize: i = !0, debounce: s = 250 } = {}) { 47 (this.wrapper = t), 48 (this.content = e), 49 i && 50 ((this.debouncedResize = (function debounce(t, e) { 51 let i; 52 return function () { 53 let s = arguments, 54 o = this; 55 clearTimeout(i), 56 (i = setTimeout(function () { 57 t.apply(o, s); 58 }, e)); 59 }; 60 })(this.resize, s)), 61 this.wrapper === window ? window.addEventListener("resize", this.debouncedResize, !1) : ((this.wrapperResizeObserver = new ResizeObserver(this.debouncedResize)), this.wrapperResizeObserver.observe(this.wrapper)), 62 (this.contentResizeObserver = new ResizeObserver(this.debouncedResize)), 63 this.contentResizeObserver.observe(this.content)), 64 this.resize(); 65 } 66 destroy() { 67 this.wrapperResizeObserver?.disconnect(), this.contentResizeObserver?.disconnect(), window.removeEventListener("resize", this.debouncedResize, !1); 68 } 69 resize = () => { 70 this.onWrapperResize(), this.onContentResize(); 71 }; 72 onWrapperResize = () => { 73 this.wrapper === window ? ((this.width = window.innerWidth), (this.height = window.innerHeight)) : ((this.width = this.wrapper.clientWidth), (this.height = this.wrapper.clientHeight)); 74 }; 75 onContentResize = () => { 76 this.wrapper === window ? ((this.scrollHeight = this.content.scrollHeight), (this.scrollWidth = this.content.scrollWidth)) : ((this.scrollHeight = this.wrapper.scrollHeight), (this.scrollWidth = this.wrapper.scrollWidth)); 77 }; 78 get limit() { 79 return { x: this.scrollWidth - this.width, y: this.scrollHeight - this.height }; 80 } 81 } 82 class Emitter { 83 constructor() { 84 this.events = {}; 85 } 86 emit(t, ...e) { 87 let i = this.events[t] || []; 88 for (let t = 0, s = i.length; t < s; t++) i[t](...e); 89 } 90 on(t, e) { 91 return ( 92 this.events[t]?.push(e) || (this.events[t] = [e]), 93 () => { 94 this.events[t] = this.events[t]?.filter((t) => e !== t); 95 } 96 ); 97 } 98 off(t, e) { 99 this.events[t] = this.events[t]?.filter((t) => e !== t); 100 } 101 destroy() { 102 this.events = {}; 103 } 104 } 105 const t = 100 / 6; 106 class VirtualScroll { 107 constructor(t, { wheelMultiplier: e = 1, touchMultiplier: i = 1 }) { 108 (this.element = t), 109 (this.wheelMultiplier = e), 110 (this.touchMultiplier = i), 111 (this.touchStart = { x: null, y: null }), 112 (this.emitter = new Emitter()), 113 window.addEventListener("resize", this.onWindowResize, !1), 114 this.onWindowResize(), 115 this.element.addEventListener("wheel", this.onWheel, { passive: !1 }), 116 this.element.addEventListener("touchstart", this.onTouchStart, { passive: !1 }), 117 this.element.addEventListener("touchmove", this.onTouchMove, { passive: !1 }), 118 this.element.addEventListener("touchend", this.onTouchEnd, { passive: !1 }); 119 } 120 on(t, e) { 121 return this.emitter.on(t, e); 122 } 123 destroy() { 124 this.emitter.destroy(), 125 window.removeEventListener("resize", this.onWindowResize, !1), 126 this.element.removeEventListener("wheel", this.onWheel, { passive: !1 }), 127 this.element.removeEventListener("touchstart", this.onTouchStart, { passive: !1 }), 128 this.element.removeEventListener("touchmove", this.onTouchMove, { passive: !1 }), 129 this.element.removeEventListener("touchend", this.onTouchEnd, { passive: !1 }); 130 } 131 onTouchStart = (t) => { 132 const { clientX: e, clientY: i } = t.targetTouches ? t.targetTouches[0] : t; 133 (this.touchStart.x = e), (this.touchStart.y = i), (this.lastDelta = { x: 0, y: 0 }), this.emitter.emit("scroll", { deltaX: 0, deltaY: 0, event: t }); 134 }; 135 onTouchMove = (t) => { 136 const { clientX: e, clientY: i } = t.targetTouches ? t.targetTouches[0] : t, 137 s = -(e - this.touchStart.x) * this.touchMultiplier, 138 o = -(i - this.touchStart.y) * this.touchMultiplier; 139 (this.touchStart.x = e), (this.touchStart.y = i), (this.lastDelta = { x: s, y: o }), this.emitter.emit("scroll", { deltaX: s, deltaY: o, event: t }); 140 }; 141 onTouchEnd = (t) => { 142 this.emitter.emit("scroll", { deltaX: this.lastDelta.x, deltaY: this.lastDelta.y, event: t }); 143 }; 144 onWheel = (e) => { 145 let { deltaX: i, deltaY: s, deltaMode: o } = e; 146 (i *= 1 === o ? t : 2 === o ? this.windowWidth : 1), 147 (s *= 1 === o ? t : 2 === o ? this.windowHeight : 1), 148 (i *= this.wheelMultiplier), 149 (s *= this.wheelMultiplier), 150 this.emitter.emit("scroll", { deltaX: i, deltaY: s, event: e }); 151 }; 152 onWindowResize = () => { 153 (this.windowWidth = window.innerWidth), (this.windowHeight = window.innerHeight); 154 }; 155 } 156 return class Lenis { 157 constructor({ 158 wrapper: t = window, 159 content: e = document.documentElement, 160 wheelEventsTarget: i = t, 161 eventsTarget: s = i, 162 smoothWheel: o = !0, 163 syncTouch: n = !1, 164 syncTouchLerp: l = 0.075, 165 touchInertiaMultiplier: r = 35, 166 duration: h, 167 easing: a = (t) => Math.min(1, 1.001 - Math.pow(2, -10 * t)), 168 lerp: c = 0.1, 169 infinite: u = !1, 170 orientation: d = "vertical", 171 gestureOrientation: p = "vertical", 172 touchMultiplier: m = 1, 173 wheelMultiplier: v = 1, 174 autoResize: g = !0, 175 prevent: S = !1, 176 __experimental__naiveDimensions: w = !1, 177 } = {}) { 178 (this.__isScrolling = !1), 179 (this.__isStopped = !1),
180 (this.__isLocked = !1), 181 (this.direction = 0), 182 (this.onVirtualScroll = ({ deltaX: t, deltaY: e, event: i }) => { 183 if (i.ctrlKey) return; 184 const s = i.type.includes("touch"), 185 o = i.type.includes("wheel"); 186 this.isTouching = "touchstart" === i.type || "touchmove" === i.type; 187 if (this.options.syncTouch && s && "touchstart" === i.type && !this.isStopped && !this.isLocked) return void this.reset(); 188 const n = 0 === t && 0 === e, 189 l = ("vertical" === this.options.gestureOrientation && 0 === e) || ("horizontal" === this.options.gestureOrientation && 0 === t); 190 if (n || l) return; 191 let r = i.composedPath(); 192 r = r.slice(0, r.indexOf(this.rootElement)); 193 const h = this.options.prevent; 194 if ( 195 r.find((t) => { 196 var e, i, n, l, r; 197 return ( 198 t instanceof Element && 199 (("function" == typeof h ? (null == h ? void 0 : h(t)) : h) || 200 (null === (e = t.hasAttribute) || void 0 === e ? void 0 : e.call(t, "data-lenis-prevent")) || 201 (s && (null === (i = t.hasAttribute) || void 0 === i ? void 0 : i.call(t, "data-lenis-prevent-touch"))) || 202 (o && (null === (n = t.hasAttribute) || void 0 === n ? void 0 : n.call(t, "data-lenis-prevent-wheel"))) || 203 ((null === (l = t.classList) || void 0 === l ? void 0 : l.contains("lenis")) && !(null === (r = t.classList) || void 0 === r ? void 0 : r.contains("lenis-stopped")))) 204 ); 205 }) 206 ) 207 return; 208 if (this.isStopped || this.isLocked) return void i.preventDefault(); 209 if (!((this.options.syncTouch && s) || (this.options.smoothWheel && o))) return (this.isScrolling = "native"), void this.animate.stop(); 210 i.preventDefault(); 211 let a = e; 212 "both" === this.options.gestureOrientation ? (a = Math.abs(e) > Math.abs(t) ? e : t) : "horizontal" === this.options.gestureOrientation && (a = t); 213 const c = s && this.options.syncTouch, 214 u = s && "touchend" === i.type && Math.abs(a) > 5; 215 u && (a = this.velocity * this.options.touchInertiaMultiplier), 216 this.scrollTo(this.targetScroll + a, Object.assign({ programmatic: !1 }, c ? { lerp: u ? this.options.syncTouchLerp : 1 } : { lerp: this.options.lerp, duration: this.options.duration, easing: this.options.easing })); 217 }), 218 (this.onNativeScroll = () => { 219 if ((clearTimeout(this.__resetVelocityTimeout), delete this.__resetVelocityTimeout, this.__preventNextNativeScrollEvent)) delete this.__preventNextNativeScrollEvent; 220 else if (!1 === this.isScrolling || "native" === this.isScrolling) { 221 const t = this.animatedScroll; 222 (this.animatedScroll = this.targetScroll = this.actualScroll), 223 (this.lastVelocity = this.velocity), 224 (this.velocity = this.animatedScroll - t), 225 (this.direction = Math.sign(this.animatedScroll - t)), 226 (this.isScrolling = "native"), 227 this.emit(), 228 0 !== this.velocity && 229 (this.__resetVelocityTimeout = setTimeout(() => { 230 (this.lastVelocity = this.velocity), (this.velocity = 0), (this.isScrolling = !1), this.emit(); 231 }, 400)); 232 } 233 }), 234 (window.lenisVersion = "1.1.3"), 235 (t && t !== document.documentElement && t !== document.body) || (t = window), 236 (this.options = { 237 wrapper: t, 238 content: e, 239 wheelEventsTarget: i, 240 eventsTarget: s, 241 smoothWheel: o, 242 syncTouch: n, 243 syncTouchLerp: l, 244 touchInertiaMultiplier: r, 245 duration: h, 246 easing: a, 247 lerp: c, 248 infinite: u, 249 gestureOrientation: p, 250 orientation: d, 251 touchMultiplier: m, 252 wheelMultiplier: v, 253 autoResize: g, 254 prevent: S, 255 __experimental__naiveDimensions: w, 256 }), 257 (this.animate = new Animate()), 258 (this.emitter = new Emitter()), 259 (this.dimensions = new Dimensions({ wrapper: t, content: e, autoResize: g })), 260 this.updateClassName(), 261 (this.userData = {}), 262 (this.time = 0), 263 (this.velocity = this.lastVelocity = 0),
264 (this.isLocked = !1), 265 (this.isStopped = !1), 266 (this.isScrolling = !1), 267 (this.targetScroll = this.animatedScroll = this.actualScroll), 268 this.options.wrapper.addEventListener("scroll", this.onNativeScroll, !1), 269 (this.virtualScroll = new VirtualScroll(s, { touchMultiplier: m, wheelMultiplier: v })), 270 this.virtualScroll.on("scroll", this.onVirtualScroll); 271 } 272 destroy() { 273 this.emitter.destroy(), this.options.wrapper.removeEventListener("scroll", this.onNativeScroll, !1), this.virtualScroll.destroy(), this.dimensions.destroy(), this.cleanUpClassName(); 274 } 275 on(t, e) { 276 return this.emitter.on(t, e); 277 } 278 off(t, e) { 279 return this.emitter.off(t, e); 280 } 281 setScroll(t) { 282 this.isHorizontal ? (this.rootElement.scrollLeft = t) : (this.rootElement.scrollTop = t); 283 } 284 resize() { 285 this.dimensions.resize(); 286 } 287 emit() { 288 this.emitter.emit("scroll", this); 289 } 290 reset() { 291 (this.isLocked = !1), (this.isScrolling = !1), (this.animatedScroll = this.targetScroll = this.actualScroll), (this.lastVelocity = this.velocity = 0), this.animate.stop(); 292 } 293 start() { 294 this.isStopped && ((this.isStopped = !1), this.reset()); 295 } 296 stop() { 297 this.isStopped || ((this.isStopped = !0), this.animate.stop(), this.reset()); 298 } 299 raf(t) { 300 const e = t - (this.time || t); 301 (this.time = t), this.animate.advance(0.001 * e); 302 } 303 scrollTo( 304 t, 305 { 306 offset: e = 0, 307 immediate: i = !1, 308 lock: s = !1, 309 duration: o = this.options.duration, 310 easing: n = this.options.easing, 311 lerp: l = this.options.lerp, 312 onStart: r, 313 onComplete: h, 314 force: a = !1, 315 programmatic: c = !0, 316 userData: u = {}, 317 } = {} 318 ) { 319 if ((!this.isStopped && !this.isLocked) || a) { 320 if ("string" == typeof t && ["top", "left", "start"].includes(t)) t = 0; 321 else if ("string" == typeof t && ["bottom", "right", "end"].includes(t)) t = this.limit; 322 else { 323 let i; 324 if (("string" == typeof t ? (i = document.querySelector(t)) : t instanceof HTMLElement && (null == t ? void 0 : t.nodeType) && (i = t), i)) { 325 if (this.options.wrapper !== window) { 326 const t = this.rootElement.getBoundingClientRect(); 327 e -= this.isHorizontal ? t.left : t.top; 328 } 329 const s = i.getBoundingClientRect(); 330 t = (this.isHorizontal ? s.left : s.top) + this.animatedScroll; 331 } 332 } 333 if ("number" == typeof t && ((t += e), (t = Math.round(t)), this.options.infinite ? c && (this.targetScroll = this.animatedScroll = this.scroll) : (t = clamp(0, t, this.limit)), t !== this.targetScroll)) { 334 if (((this.userData = u), i)) 335 return (this.animatedScroll = this.targetScroll = t), this.setScroll(this.scroll), this.reset(), this.preventNextNativeScrollEvent(), this.emit(), null == h || h(this), void (this.userData = {}); 336 c || (this.targetScroll = t), 337 this.animate.fromTo(this.animatedScroll, t, { 338 duration: o, 339 easing: n, 340 lerp: l, 341 onStart: () => { 342 s && (this.isLocked = !0), (this.isScrolling = "smooth"), null == r || r(this); 343 }, 344 onUpdate: (t, e) => { 345 (this.isScrolling = "smooth"), 346 (this.lastVelocity = this.velocity), 347 (this.velocity = t - this.animatedScroll), 348 (this.direction = Math.sign(this.velocity)), 349 (this.animatedScroll = t), 350 this.setScroll(this.scroll), 351 c && (this.targetScroll = t),
352 e || this.emit(), 353 e && (this.reset(), this.emit(), null == h || h(this), (this.userData = {}), this.preventNextNativeScrollEvent()); 354 }, 355 }); 356 } 357 } 358 } 359 preventNextNativeScrollEvent() { 360 (this.__preventNextNativeScrollEvent = !0), 361 requestAnimationFrame(() => { 362 delete this.__preventNextNativeScrollEvent; 363 }); 364 } 365 get rootElement() { 366 return this.options.wrapper === window ? document.documentElement : this.options.wrapper; 367 } 368 get limit() { 369 return this.options.__experimental__naiveDimensions 370 ? this.isHorizontal 371 ? this.rootElement.scrollWidth - this.rootElement.clientWidth 372 : this.rootElement.scrollHeight - this.rootElement.clientHeight 373 : this.dimensions.limit[this.isHorizontal ? "x" : "y"]; 374 } 375 get isHorizontal() { 376 return "horizontal" === this.options.orientation; 377 } 378 get actualScroll() { 379 return this.isHorizontal ? this.rootElement.scrollLeft : this.rootElement.scrollTop; 380 } 381 get scroll() { 382 return this.options.infinite 383 ? (function modulo(t, e) { 384 return ((t % e) + e) % e; 385 })(this.animatedScroll, this.limit) 386 : this.animatedScroll; 387 } 388 get progress() { 389 return 0 === this.limit ? 1 : this.scroll / this.limit; 390 } 391 get isScrolling() { 392 return this.__isScrolling; 393 } 394 set isScrolling(t) { 395 this.__isScrolling !== t && ((this.__isScrolling = t), this.updateClassName()); 396 } 397 get isStopped() { 398 return this.__isStopped; 399 } 400 set isStopped(t) { 401 this.__isStopped !== t && ((this.__isStopped = t), this.updateClassName()); 402 } 403 get isLocked() { 404 return this.__isLocked; 405 } 406 set isLocked(t) { 407 this.__isLocked !== t && ((this.__isLocked = t), this.updateClassName()); 408 } 409 get isSmooth() { 410 return "smooth" === this.isScrolling; 411 } 412 get className() { 413 let t = "lenis"; 414 return this.isStopped && (t += " lenis-stopped"), this.isLocked && (t += " lenis-locked"), this.isScrolling && (t += " lenis-scrolling"), "smooth" === this.isScrolling && (t += " lenis-smooth"), t; 415 } 416 updateClassName() { 417 this.cleanUpClassName(), (this.rootElement.className = `${this.rootElement.className} ${this.className}`.trim()); 418 } 419 cleanUpClassName() { 420 this.rootElement.className = this.rootElement.className.replace(/lenis(-\w+)?/g, "").trim(); 421 } 422 }; 423}); 424//# sourceMappingURL=lenis.min.js.map
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.