lenis 1.1.4 → 1.1.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -45,7 +45,7 @@ import Lenis from 'lenis'
45
45
  using scripts:
46
46
 
47
47
  ```html
48
- <script src="https://unpkg.com/lenis@1.1.4/dist/lenis.min.js"></script>
48
+ <script src="https://unpkg.com/lenis@1.1.5/dist/lenis.min.js"></script>
49
49
  ```
50
50
 
51
51
 
@@ -140,7 +140,7 @@
140
140
  !isTurningBack &&
141
141
  (userData === null || userData === void 0 ? void 0 : userData.initiator) !== 'snap') {
142
142
  scroll = Math.ceil(scroll);
143
- let snaps = [0, ...this.snaps.values(), limit];
143
+ let snaps = [...this.snaps.values()];
144
144
  this.elements.forEach(({ rect, align }) => {
145
145
  let snap;
146
146
  align.forEach((align) => {
@@ -1 +1 @@
1
- {"version":3,"file":"lenis-snap.js","sources":["../src/element.ts","../src/uid.ts","../src/index.ts"],"sourcesContent":["function removeParentSticky(element: HTMLElement) {\r\n const position = getComputedStyle(element).position\r\n\r\n const isSticky = position === 'sticky'\r\n\r\n if (isSticky) {\r\n element.style.setProperty('position', 'static')\r\n element.dataset.sticky = 'true'\r\n }\r\n\r\n if (element.offsetParent) {\r\n removeParentSticky(element.offsetParent as HTMLElement)\r\n }\r\n}\r\n\r\nfunction addParentSticky(element: HTMLElement) {\r\n if (element?.dataset?.sticky === 'true') {\r\n element.style.removeProperty('position')\r\n delete element.dataset.sticky\r\n }\r\n\r\n if (element.offsetParent) {\r\n addParentSticky(element.offsetParent as HTMLElement)\r\n }\r\n}\r\n\r\nfunction offsetTop(element: HTMLElement, accumulator = 0) {\r\n const top = accumulator + element.offsetTop\r\n if (element.offsetParent) {\r\n return offsetTop(element.offsetParent as HTMLElement, top)\r\n }\r\n return top\r\n}\r\n\r\nfunction offsetLeft(element: HTMLElement, accumulator = 0) {\r\n const left = accumulator + element.offsetLeft\r\n if (element.offsetParent) {\r\n return offsetLeft(element.offsetParent as HTMLElement, left)\r\n }\r\n return left\r\n}\r\n\r\nfunction scrollTop(element: HTMLElement, accumulator = 0) {\r\n const top = accumulator + element.scrollTop\r\n if (element.offsetParent) {\r\n return scrollTop(element.offsetParent as HTMLElement, top)\r\n }\r\n return top + window.scrollY\r\n}\r\n\r\nfunction scrollLeft(element: HTMLElement, accumulator = 0) {\r\n const left = accumulator + element.scrollLeft\r\n if (element.offsetParent) {\r\n return scrollLeft(element.offsetParent as HTMLElement, left)\r\n }\r\n return left + window.scrollX\r\n}\r\n\r\nexport type SnapElementOptions = {\r\n align?: string[]\r\n ignoreSticky?: boolean\r\n ignoreTransform?: boolean\r\n}\r\n\r\ntype Rect = {\r\n top: number\r\n left: number\r\n width: number\r\n height: number\r\n x: number\r\n y: number\r\n bottom: number\r\n right: number\r\n element: HTMLElement\r\n}\r\n\r\nexport class SnapElement {\r\n element: HTMLElement\r\n options: SnapElementOptions\r\n align: string[]\r\n // @ts-ignore\r\n rect: Rect = {}\r\n wrapperResizeObserver: ResizeObserver\r\n resizeObserver: ResizeObserver\r\n\r\n constructor(\r\n element: HTMLElement,\r\n {\r\n align = ['start'],\r\n ignoreSticky = true,\r\n ignoreTransform = false,\r\n }: SnapElementOptions = {}\r\n ) {\r\n this.element = element\r\n\r\n this.options = { align, ignoreSticky, ignoreTransform }\r\n\r\n // this.ignoreSticky = ignoreSticky\r\n // this.ignoreTransform = ignoreTransform\r\n\r\n this.align = [align].flat()\r\n\r\n // TODO: assing rect immediately\r\n\r\n this.wrapperResizeObserver = new ResizeObserver(this.onWrapperResize)\r\n this.wrapperResizeObserver.observe(document.body)\r\n this.onWrapperResize()\r\n\r\n this.resizeObserver = new ResizeObserver(this.onResize)\r\n this.resizeObserver.observe(this.element)\r\n this.setRect({\r\n width: this.element.offsetWidth,\r\n height: this.element.offsetHeight,\r\n })\r\n }\r\n\r\n destroy() {\r\n this.wrapperResizeObserver.disconnect()\r\n this.resizeObserver.disconnect()\r\n }\r\n\r\n setRect({\r\n top,\r\n left,\r\n width,\r\n height,\r\n element,\r\n }: {\r\n top?: number\r\n left?: number\r\n width?: number\r\n height?: number\r\n element?: HTMLElement\r\n } = {}) {\r\n top = top ?? this.rect.top\r\n left = left ?? this.rect.left\r\n width = width ?? this.rect.width\r\n height = height ?? this.rect.height\r\n element = element ?? this.rect.element\r\n\r\n if (\r\n top === this.rect.top &&\r\n left === this.rect.left &&\r\n width === this.rect.width &&\r\n height === this.rect.height &&\r\n element === this.rect.element\r\n )\r\n return\r\n\r\n this.rect.top = top\r\n this.rect.y = top\r\n this.rect.width = width\r\n this.rect.height = height\r\n this.rect.left = left\r\n this.rect.x = left\r\n this.rect.bottom = top + height\r\n this.rect.right = left + width\r\n }\r\n\r\n onWrapperResize = () => {\r\n let top, left\r\n\r\n if (this.options.ignoreSticky) removeParentSticky(this.element)\r\n if (this.options.ignoreTransform) {\r\n top = offsetTop(this.element)\r\n left = offsetLeft(this.element)\r\n } else {\r\n const rect = this.element.getBoundingClientRect()\r\n top = rect.top + scrollTop(this.element)\r\n left = rect.left + scrollLeft(this.element)\r\n }\r\n if (this.options.ignoreSticky) addParentSticky(this.element)\r\n\r\n this.setRect({ top, left })\r\n }\r\n\r\n onResize = ([entry]: ResizeObserverEntry[]) => {\r\n const width = entry.borderBoxSize[0].inlineSize\r\n const height = entry.borderBoxSize[0].blockSize\r\n\r\n this.setRect({ width, height })\r\n }\r\n}\r\n","let index = 0\r\n\r\nexport type UID = number\r\n\r\nexport function uid(): UID {\r\n return index++\r\n}\r\n","import Lenis from 'lenis'\r\nimport { SnapElement, SnapElementOptions } from './element'\r\nimport { UID, uid } from './uid'\r\n\r\n// TODO:\r\n// - horizontal\r\n// - fix trackpad snapping too soon due to velocity (fuck Apple)\r\n// - fix wheel scrolling after limits (see console scroll to)\r\n// - fix touch scroll, do not snap when not released\r\n// - arrow, spacebar\r\n\r\ntype Viewport = {\r\n width: number\r\n height: number\r\n}\r\n\r\nexport type SnapOptions = {\r\n type?: 'mandatory' | 'proximity'\r\n lerp?: number\r\n easing?: (t: number) => number\r\n duration?: number\r\n velocityThreshold?: number\r\n onSnapStart?: (t: number) => number\r\n onSnapComplete?: (t: number) => number\r\n}\r\n\r\nexport default class Snap {\r\n lenis: Lenis\r\n options: SnapOptions\r\n elements: Map<UID, SnapElement>\r\n snaps: Map<UID, number>\r\n viewport: Viewport\r\n isStopped: Boolean = false\r\n\r\n constructor(\r\n lenis: Lenis,\r\n {\r\n type = 'mandatory',\r\n lerp,\r\n easing,\r\n duration,\r\n velocityThreshold = 1,\r\n onSnapStart,\r\n onSnapComplete,\r\n }: SnapOptions = {}\r\n ) {\r\n this.lenis = lenis\r\n\r\n this.options = {\r\n type,\r\n lerp,\r\n easing,\r\n duration,\r\n velocityThreshold,\r\n onSnapStart,\r\n onSnapComplete,\r\n }\r\n\r\n this.elements = new Map()\r\n this.snaps = new Map()\r\n\r\n this.viewport = {\r\n width: window.innerWidth,\r\n height: window.innerHeight,\r\n }\r\n this.onWindowResize()\r\n window.addEventListener('resize', this.onWindowResize)\r\n\r\n this.lenis.on('scroll', this.onScroll)\r\n }\r\n\r\n // debug() {\r\n // const element = document.createElement('div')\r\n // element.style.cssText = `\r\n // position: fixed;\r\n // background: red;\r\n // border-bottom: 1px solid red;\r\n // left: 0;\r\n // right: 0;\r\n // top: 0;\r\n // z-index: 9999;\r\n // `\r\n // document.body.appendChild(element)\r\n // }\r\n\r\n destroy() {\r\n this.lenis.off('scroll', this.onScroll)\r\n window.removeEventListener('resize', this.onWindowResize)\r\n this.elements.forEach((element) => element.destroy())\r\n }\r\n\r\n start() {\r\n this.isStopped = false\r\n }\r\n\r\n stop() {\r\n this.isStopped = true\r\n }\r\n\r\n add(value: number) {\r\n const id = uid()\r\n\r\n this.snaps.set(id, value)\r\n\r\n return () => this.remove(id)\r\n }\r\n\r\n remove(id: UID) {\r\n this.snaps.delete(id)\r\n }\r\n\r\n addElement(element: HTMLElement, options = {} as SnapElementOptions) {\r\n const id = uid()\r\n\r\n this.elements.set(id, new SnapElement(element, options))\r\n\r\n return () => this.removeElement(id)\r\n }\r\n\r\n removeElement(id: UID) {\r\n this.elements.delete(id)\r\n }\r\n\r\n onWindowResize = () => {\r\n this.viewport.width = window.innerWidth\r\n this.viewport.height = window.innerHeight\r\n }\r\n\r\n onScroll = ({\r\n scroll,\r\n limit,\r\n lastVelocity,\r\n velocity,\r\n isScrolling,\r\n userData,\r\n isHorizontal,\r\n }) => {\r\n if (this.isStopped) return\r\n // console.log(scroll, velocity, type)\r\n\r\n // return\r\n const isDecelerating = Math.abs(lastVelocity) > Math.abs(velocity)\r\n const isTurningBack =\r\n Math.sign(lastVelocity) !== Math.sign(velocity) && velocity !== 0\r\n\r\n // console.log({ lastVelocity, velocity, isTurningBack, isDecelerating })\r\n\r\n // console.log('onScroll')\r\n\r\n if (\r\n Math.abs(velocity) < this.options.velocityThreshold &&\r\n // !isTouching &&\r\n isDecelerating &&\r\n !isTurningBack &&\r\n userData?.initiator !== 'snap'\r\n ) {\r\n scroll = Math.ceil(scroll)\r\n\r\n let snaps = [0, ...this.snaps.values(), limit] as number[]\r\n\r\n this.elements.forEach(({ rect, align }) => {\r\n let snap: number | undefined\r\n\r\n align.forEach((align) => {\r\n if (align === 'start') {\r\n snap = rect.top\r\n } else if (align === 'center') {\r\n snap = isHorizontal\r\n ? rect.left + rect.width / 2 - this.viewport.width / 2\r\n : rect.top + rect.height / 2 - this.viewport.height / 2\r\n } else if (align === 'end') {\r\n snap = isHorizontal\r\n ? rect.left + rect.width - this.viewport.width\r\n : rect.top + rect.height - this.viewport.height\r\n }\r\n\r\n if (snap !== undefined) {\r\n snaps.push(Math.ceil(snap))\r\n }\r\n })\r\n })\r\n\r\n snaps = snaps.sort((a, b) => Math.abs(a) - Math.abs(b))\r\n\r\n let prevSnap = snaps.findLast((snap) => snap <= scroll)\r\n if (prevSnap === undefined) prevSnap = snaps[0]\r\n const distanceToPrevSnap = Math.abs(scroll - prevSnap)\r\n\r\n let nextSnap = snaps.find((snap) => snap >= scroll)\r\n if (nextSnap === undefined) nextSnap = snaps[snaps.length - 1]\r\n const distanceToNextSnap = Math.abs(scroll - nextSnap)\r\n\r\n const snap = distanceToPrevSnap < distanceToNextSnap ? prevSnap : nextSnap\r\n\r\n const distance = Math.abs(scroll - snap)\r\n\r\n if (\r\n this.options.type === 'mandatory' ||\r\n (this.options.type === 'proximity' && distance <= this.viewport.height)\r\n ) {\r\n // this.__isScrolling = true\r\n // this.onSnapStart?.(snap)\r\n\r\n // console.log('scroll to')\r\n\r\n this.lenis.scrollTo(snap, {\r\n lerp: this.options.lerp,\r\n easing: this.options.easing,\r\n duration: this.options.duration,\r\n userData: { initiator: 'snap' },\r\n onStart: () => {\r\n this.options.onSnapStart?.(snap)\r\n },\r\n onComplete: () => {\r\n this.options.onSnapComplete?.(snap)\r\n },\r\n })\r\n }\r\n\r\n // console.timeEnd('scroll')\r\n }\r\n }\r\n}\r\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"lenis-snap.js","sources":["../src/element.ts","../src/uid.ts","../src/index.ts"],"sourcesContent":["function removeParentSticky(element: HTMLElement) {\r\n const position = getComputedStyle(element).position\r\n\r\n const isSticky = position === 'sticky'\r\n\r\n if (isSticky) {\r\n element.style.setProperty('position', 'static')\r\n element.dataset.sticky = 'true'\r\n }\r\n\r\n if (element.offsetParent) {\r\n removeParentSticky(element.offsetParent as HTMLElement)\r\n }\r\n}\r\n\r\nfunction addParentSticky(element: HTMLElement) {\r\n if (element?.dataset?.sticky === 'true') {\r\n element.style.removeProperty('position')\r\n delete element.dataset.sticky\r\n }\r\n\r\n if (element.offsetParent) {\r\n addParentSticky(element.offsetParent as HTMLElement)\r\n }\r\n}\r\n\r\nfunction offsetTop(element: HTMLElement, accumulator = 0) {\r\n const top = accumulator + element.offsetTop\r\n if (element.offsetParent) {\r\n return offsetTop(element.offsetParent as HTMLElement, top)\r\n }\r\n return top\r\n}\r\n\r\nfunction offsetLeft(element: HTMLElement, accumulator = 0) {\r\n const left = accumulator + element.offsetLeft\r\n if (element.offsetParent) {\r\n return offsetLeft(element.offsetParent as HTMLElement, left)\r\n }\r\n return left\r\n}\r\n\r\nfunction scrollTop(element: HTMLElement, accumulator = 0) {\r\n const top = accumulator + element.scrollTop\r\n if (element.offsetParent) {\r\n return scrollTop(element.offsetParent as HTMLElement, top)\r\n }\r\n return top + window.scrollY\r\n}\r\n\r\nfunction scrollLeft(element: HTMLElement, accumulator = 0) {\r\n const left = accumulator + element.scrollLeft\r\n if (element.offsetParent) {\r\n return scrollLeft(element.offsetParent as HTMLElement, left)\r\n }\r\n return left + window.scrollX\r\n}\r\n\r\nexport type SnapElementOptions = {\r\n align?: string[]\r\n ignoreSticky?: boolean\r\n ignoreTransform?: boolean\r\n}\r\n\r\ntype Rect = {\r\n top: number\r\n left: number\r\n width: number\r\n height: number\r\n x: number\r\n y: number\r\n bottom: number\r\n right: number\r\n element: HTMLElement\r\n}\r\n\r\nexport class SnapElement {\r\n element: HTMLElement\r\n options: SnapElementOptions\r\n align: string[]\r\n // @ts-ignore\r\n rect: Rect = {}\r\n wrapperResizeObserver: ResizeObserver\r\n resizeObserver: ResizeObserver\r\n\r\n constructor(\r\n element: HTMLElement,\r\n {\r\n align = ['start'],\r\n ignoreSticky = true,\r\n ignoreTransform = false,\r\n }: SnapElementOptions = {}\r\n ) {\r\n this.element = element\r\n\r\n this.options = { align, ignoreSticky, ignoreTransform }\r\n\r\n // this.ignoreSticky = ignoreSticky\r\n // this.ignoreTransform = ignoreTransform\r\n\r\n this.align = [align].flat()\r\n\r\n // TODO: assing rect immediately\r\n\r\n this.wrapperResizeObserver = new ResizeObserver(this.onWrapperResize)\r\n this.wrapperResizeObserver.observe(document.body)\r\n this.onWrapperResize()\r\n\r\n this.resizeObserver = new ResizeObserver(this.onResize)\r\n this.resizeObserver.observe(this.element)\r\n this.setRect({\r\n width: this.element.offsetWidth,\r\n height: this.element.offsetHeight,\r\n })\r\n }\r\n\r\n destroy() {\r\n this.wrapperResizeObserver.disconnect()\r\n this.resizeObserver.disconnect()\r\n }\r\n\r\n setRect({\r\n top,\r\n left,\r\n width,\r\n height,\r\n element,\r\n }: {\r\n top?: number\r\n left?: number\r\n width?: number\r\n height?: number\r\n element?: HTMLElement\r\n } = {}) {\r\n top = top ?? this.rect.top\r\n left = left ?? this.rect.left\r\n width = width ?? this.rect.width\r\n height = height ?? this.rect.height\r\n element = element ?? this.rect.element\r\n\r\n if (\r\n top === this.rect.top &&\r\n left === this.rect.left &&\r\n width === this.rect.width &&\r\n height === this.rect.height &&\r\n element === this.rect.element\r\n )\r\n return\r\n\r\n this.rect.top = top\r\n this.rect.y = top\r\n this.rect.width = width\r\n this.rect.height = height\r\n this.rect.left = left\r\n this.rect.x = left\r\n this.rect.bottom = top + height\r\n this.rect.right = left + width\r\n }\r\n\r\n onWrapperResize = () => {\r\n let top, left\r\n\r\n if (this.options.ignoreSticky) removeParentSticky(this.element)\r\n if (this.options.ignoreTransform) {\r\n top = offsetTop(this.element)\r\n left = offsetLeft(this.element)\r\n } else {\r\n const rect = this.element.getBoundingClientRect()\r\n top = rect.top + scrollTop(this.element)\r\n left = rect.left + scrollLeft(this.element)\r\n }\r\n if (this.options.ignoreSticky) addParentSticky(this.element)\r\n\r\n this.setRect({ top, left })\r\n }\r\n\r\n onResize = ([entry]: ResizeObserverEntry[]) => {\r\n const width = entry.borderBoxSize[0].inlineSize\r\n const height = entry.borderBoxSize[0].blockSize\r\n\r\n this.setRect({ width, height })\r\n }\r\n}\r\n","let index = 0\r\n\r\nexport type UID = number\r\n\r\nexport function uid(): UID {\r\n return index++\r\n}\r\n","import Lenis from 'lenis'\r\nimport { SnapElement, SnapElementOptions } from './element'\r\nimport { UID, uid } from './uid'\r\n\r\n// TODO:\r\n// - horizontal\r\n// - fix trackpad snapping too soon due to velocity (fuck Apple)\r\n// - fix wheel scrolling after limits (see console scroll to)\r\n// - fix touch scroll, do not snap when not released\r\n// - arrow, spacebar\r\n\r\ntype Viewport = {\r\n width: number\r\n height: number\r\n}\r\n\r\nexport type SnapOptions = {\r\n type?: 'mandatory' | 'proximity'\r\n lerp?: number\r\n easing?: (t: number) => number\r\n duration?: number\r\n velocityThreshold?: number\r\n onSnapStart?: (t: number) => number\r\n onSnapComplete?: (t: number) => number\r\n}\r\n\r\nexport default class Snap {\r\n lenis: Lenis\r\n options: SnapOptions\r\n elements: Map<UID, SnapElement>\r\n snaps: Map<UID, number>\r\n viewport: Viewport\r\n isStopped: Boolean = false\r\n\r\n constructor(\r\n lenis: Lenis,\r\n {\r\n type = 'mandatory',\r\n lerp,\r\n easing,\r\n duration,\r\n velocityThreshold = 1,\r\n onSnapStart,\r\n onSnapComplete,\r\n }: SnapOptions = {}\r\n ) {\r\n this.lenis = lenis\r\n\r\n this.options = {\r\n type,\r\n lerp,\r\n easing,\r\n duration,\r\n velocityThreshold,\r\n onSnapStart,\r\n onSnapComplete,\r\n }\r\n\r\n this.elements = new Map()\r\n this.snaps = new Map()\r\n\r\n this.viewport = {\r\n width: window.innerWidth,\r\n height: window.innerHeight,\r\n }\r\n this.onWindowResize()\r\n window.addEventListener('resize', this.onWindowResize)\r\n\r\n this.lenis.on('scroll', this.onScroll)\r\n }\r\n\r\n // debug() {\r\n // const element = document.createElement('div')\r\n // element.style.cssText = `\r\n // position: fixed;\r\n // background: red;\r\n // border-bottom: 1px solid red;\r\n // left: 0;\r\n // right: 0;\r\n // top: 0;\r\n // z-index: 9999;\r\n // `\r\n // document.body.appendChild(element)\r\n // }\r\n\r\n destroy() {\r\n this.lenis.off('scroll', this.onScroll)\r\n window.removeEventListener('resize', this.onWindowResize)\r\n this.elements.forEach((element) => element.destroy())\r\n }\r\n\r\n start() {\r\n this.isStopped = false\r\n }\r\n\r\n stop() {\r\n this.isStopped = true\r\n }\r\n\r\n add(value: number) {\r\n const id = uid()\r\n\r\n this.snaps.set(id, value)\r\n\r\n return () => this.remove(id)\r\n }\r\n\r\n remove(id: UID) {\r\n this.snaps.delete(id)\r\n }\r\n\r\n addElement(element: HTMLElement, options = {} as SnapElementOptions) {\r\n const id = uid()\r\n\r\n this.elements.set(id, new SnapElement(element, options))\r\n\r\n return () => this.removeElement(id)\r\n }\r\n\r\n removeElement(id: UID) {\r\n this.elements.delete(id)\r\n }\r\n\r\n onWindowResize = () => {\r\n this.viewport.width = window.innerWidth\r\n this.viewport.height = window.innerHeight\r\n }\r\n\r\n onScroll = ({\r\n scroll,\r\n limit,\r\n lastVelocity,\r\n velocity,\r\n isScrolling,\r\n userData,\r\n isHorizontal,\r\n }) => {\r\n if (this.isStopped) return\r\n // console.log(scroll, velocity, type)\r\n\r\n // return\r\n const isDecelerating = Math.abs(lastVelocity) > Math.abs(velocity)\r\n const isTurningBack =\r\n Math.sign(lastVelocity) !== Math.sign(velocity) && velocity !== 0\r\n\r\n // console.log({ lastVelocity, velocity, isTurningBack, isDecelerating })\r\n\r\n // console.log('onScroll')\r\n\r\n if (\r\n Math.abs(velocity) < this.options.velocityThreshold &&\r\n // !isTouching &&\r\n isDecelerating &&\r\n !isTurningBack &&\r\n userData?.initiator !== 'snap'\r\n ) {\r\n scroll = Math.ceil(scroll)\r\n\r\n let snaps = [...this.snaps.values()] as number[]\r\n\r\n this.elements.forEach(({ rect, align }) => {\r\n let snap: number | undefined\r\n\r\n align.forEach((align) => {\r\n if (align === 'start') {\r\n snap = rect.top\r\n } else if (align === 'center') {\r\n snap = isHorizontal\r\n ? rect.left + rect.width / 2 - this.viewport.width / 2\r\n : rect.top + rect.height / 2 - this.viewport.height / 2\r\n } else if (align === 'end') {\r\n snap = isHorizontal\r\n ? rect.left + rect.width - this.viewport.width\r\n : rect.top + rect.height - this.viewport.height\r\n }\r\n\r\n if (snap !== undefined) {\r\n snaps.push(Math.ceil(snap))\r\n }\r\n })\r\n })\r\n\r\n snaps = snaps.sort((a, b) => Math.abs(a) - Math.abs(b))\r\n\r\n let prevSnap = snaps.findLast((snap) => snap <= scroll)\r\n if (prevSnap === undefined) prevSnap = snaps[0]\r\n const distanceToPrevSnap = Math.abs(scroll - prevSnap)\r\n\r\n let nextSnap = snaps.find((snap) => snap >= scroll)\r\n if (nextSnap === undefined) nextSnap = snaps[snaps.length - 1]\r\n const distanceToNextSnap = Math.abs(scroll - nextSnap)\r\n\r\n const snap = distanceToPrevSnap < distanceToNextSnap ? prevSnap : nextSnap\r\n\r\n const distance = Math.abs(scroll - snap)\r\n\r\n if (\r\n this.options.type === 'mandatory' ||\r\n (this.options.type === 'proximity' && distance <= this.viewport.height)\r\n ) {\r\n // this.__isScrolling = true\r\n // this.onSnapStart?.(snap)\r\n\r\n // console.log('scroll to')\r\n\r\n this.lenis.scrollTo(snap, {\r\n lerp: this.options.lerp,\r\n easing: this.options.easing,\r\n duration: this.options.duration,\r\n userData: { initiator: 'snap' },\r\n onStart: () => {\r\n this.options.onSnapStart?.(snap)\r\n },\r\n onComplete: () => {\r\n this.options.onSnapComplete?.(snap)\r\n },\r\n })\r\n }\r\n\r\n // console.timeEnd('scroll')\r\n }\r\n }\r\n}\r\n"],"names":[],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- !function(t,e){"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()}(this,(function(){"use strict";function removeParentSticky(t){"sticky"===getComputedStyle(t).position&&(t.style.setProperty("position","static"),t.dataset.sticky="true"),t.offsetParent&&removeParentSticky(t.offsetParent)}function addParentSticky(t){var e;"true"===(null===(e=null==t?void 0:t.dataset)||void 0===e?void 0:e.sticky)&&(t.style.removeProperty("position"),delete t.dataset.sticky),t.offsetParent&&addParentSticky(t.offsetParent)}function offsetTop(t,e=0){const i=e+t.offsetTop;return t.offsetParent?offsetTop(t.offsetParent,i):i}function offsetLeft(t,e=0){const i=e+t.offsetLeft;return t.offsetParent?offsetLeft(t.offsetParent,i):i}function scrollTop(t,e=0){const i=e+t.scrollTop;return t.offsetParent?scrollTop(t.offsetParent,i):i+window.scrollY}function scrollLeft(t,e=0){const i=e+t.scrollLeft;return t.offsetParent?scrollLeft(t.offsetParent,i):i+window.scrollX}class SnapElement{constructor(t,{align:e=["start"],ignoreSticky:i=!0,ignoreTransform:s=!1}={}){this.rect={},this.onWrapperResize=()=>{let t,e;if(this.options.ignoreSticky&&removeParentSticky(this.element),this.options.ignoreTransform)t=offsetTop(this.element),e=offsetLeft(this.element);else{const i=this.element.getBoundingClientRect();t=i.top+scrollTop(this.element),e=i.left+scrollLeft(this.element)}this.options.ignoreSticky&&addParentSticky(this.element),this.setRect({top:t,left:e})},this.onResize=([t])=>{const e=t.borderBoxSize[0].inlineSize,i=t.borderBoxSize[0].blockSize;this.setRect({width:e,height:i})},this.element=t,this.options={align:e,ignoreSticky:i,ignoreTransform:s},this.align=[e].flat(),this.wrapperResizeObserver=new ResizeObserver(this.onWrapperResize),this.wrapperResizeObserver.observe(document.body),this.onWrapperResize(),this.resizeObserver=new ResizeObserver(this.onResize),this.resizeObserver.observe(this.element),this.setRect({width:this.element.offsetWidth,height:this.element.offsetHeight})}destroy(){this.wrapperResizeObserver.disconnect(),this.resizeObserver.disconnect()}setRect({top:t,left:e,width:i,height:s,element:o}={}){t=null!=t?t:this.rect.top,e=null!=e?e:this.rect.left,i=null!=i?i:this.rect.width,s=null!=s?s:this.rect.height,o=null!=o?o:this.rect.element,t===this.rect.top&&e===this.rect.left&&i===this.rect.width&&s===this.rect.height&&o===this.rect.element||(this.rect.top=t,this.rect.y=t,this.rect.width=i,this.rect.height=s,this.rect.left=e,this.rect.x=e,this.rect.bottom=t+s,this.rect.right=e+i)}}let t=0;function uid(){return t++}return class Snap{constructor(t,{type:e="mandatory",lerp:i,easing:s,duration:o,velocityThreshold:n=1,onSnapStart:r,onSnapComplete:h}={}){this.isStopped=!1,this.onWindowResize=()=>{this.viewport.width=window.innerWidth,this.viewport.height=window.innerHeight},this.onScroll=({scroll:t,limit:e,lastVelocity:i,velocity:s,isScrolling:o,userData:n,isHorizontal:r})=>{if(this.isStopped)return;const h=Math.abs(i)>Math.abs(s),l=Math.sign(i)!==Math.sign(s)&&0!==s;if(Math.abs(s)<this.options.velocityThreshold&&h&&!l&&"snap"!==(null==n?void 0:n.initiator)){t=Math.ceil(t);let i=[0,...this.snaps.values(),e];this.elements.forEach((({rect:t,align:e})=>{let s;e.forEach((e=>{"start"===e?s=t.top:"center"===e?s=r?t.left+t.width/2-this.viewport.width/2:t.top+t.height/2-this.viewport.height/2:"end"===e&&(s=r?t.left+t.width-this.viewport.width:t.top+t.height-this.viewport.height),void 0!==s&&i.push(Math.ceil(s))}))})),i=i.sort(((t,e)=>Math.abs(t)-Math.abs(e)));let s=i.findLast((e=>e<=t));void 0===s&&(s=i[0]);const o=Math.abs(t-s);let n=i.find((e=>e>=t));void 0===n&&(n=i[i.length-1]);const h=o<Math.abs(t-n)?s:n,l=Math.abs(t-h);("mandatory"===this.options.type||"proximity"===this.options.type&&l<=this.viewport.height)&&this.lenis.scrollTo(h,{lerp:this.options.lerp,easing:this.options.easing,duration:this.options.duration,userData:{initiator:"snap"},onStart:()=>{var t,e;null===(e=(t=this.options).onSnapStart)||void 0===e||e.call(t,h)},onComplete:()=>{var t,e;null===(e=(t=this.options).onSnapComplete)||void 0===e||e.call(t,h)}})}},this.lenis=t,this.options={type:e,lerp:i,easing:s,duration:o,velocityThreshold:n,onSnapStart:r,onSnapComplete:h},this.elements=new Map,this.snaps=new Map,this.viewport={width:window.innerWidth,height:window.innerHeight},this.onWindowResize(),window.addEventListener("resize",this.onWindowResize),this.lenis.on("scroll",this.onScroll)}destroy(){this.lenis.off("scroll",this.onScroll),window.removeEventListener("resize",this.onWindowResize),this.elements.forEach((t=>t.destroy()))}start(){this.isStopped=!1}stop(){this.isStopped=!0}add(t){const e=uid();return this.snaps.set(e,t),()=>this.remove(e)}remove(t){this.snaps.delete(t)}addElement(t,e={}){const i=uid();return this.elements.set(i,new SnapElement(t,e)),()=>this.removeElement(i)}removeElement(t){this.elements.delete(t)}}}));
1
+ !function(t,e){"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()}(this,(function(){"use strict";function removeParentSticky(t){"sticky"===getComputedStyle(t).position&&(t.style.setProperty("position","static"),t.dataset.sticky="true"),t.offsetParent&&removeParentSticky(t.offsetParent)}function addParentSticky(t){var e;"true"===(null===(e=null==t?void 0:t.dataset)||void 0===e?void 0:e.sticky)&&(t.style.removeProperty("position"),delete t.dataset.sticky),t.offsetParent&&addParentSticky(t.offsetParent)}function offsetTop(t,e=0){const i=e+t.offsetTop;return t.offsetParent?offsetTop(t.offsetParent,i):i}function offsetLeft(t,e=0){const i=e+t.offsetLeft;return t.offsetParent?offsetLeft(t.offsetParent,i):i}function scrollTop(t,e=0){const i=e+t.scrollTop;return t.offsetParent?scrollTop(t.offsetParent,i):i+window.scrollY}function scrollLeft(t,e=0){const i=e+t.scrollLeft;return t.offsetParent?scrollLeft(t.offsetParent,i):i+window.scrollX}class SnapElement{constructor(t,{align:e=["start"],ignoreSticky:i=!0,ignoreTransform:s=!1}={}){this.rect={},this.onWrapperResize=()=>{let t,e;if(this.options.ignoreSticky&&removeParentSticky(this.element),this.options.ignoreTransform)t=offsetTop(this.element),e=offsetLeft(this.element);else{const i=this.element.getBoundingClientRect();t=i.top+scrollTop(this.element),e=i.left+scrollLeft(this.element)}this.options.ignoreSticky&&addParentSticky(this.element),this.setRect({top:t,left:e})},this.onResize=([t])=>{const e=t.borderBoxSize[0].inlineSize,i=t.borderBoxSize[0].blockSize;this.setRect({width:e,height:i})},this.element=t,this.options={align:e,ignoreSticky:i,ignoreTransform:s},this.align=[e].flat(),this.wrapperResizeObserver=new ResizeObserver(this.onWrapperResize),this.wrapperResizeObserver.observe(document.body),this.onWrapperResize(),this.resizeObserver=new ResizeObserver(this.onResize),this.resizeObserver.observe(this.element),this.setRect({width:this.element.offsetWidth,height:this.element.offsetHeight})}destroy(){this.wrapperResizeObserver.disconnect(),this.resizeObserver.disconnect()}setRect({top:t,left:e,width:i,height:s,element:o}={}){t=null!=t?t:this.rect.top,e=null!=e?e:this.rect.left,i=null!=i?i:this.rect.width,s=null!=s?s:this.rect.height,o=null!=o?o:this.rect.element,t===this.rect.top&&e===this.rect.left&&i===this.rect.width&&s===this.rect.height&&o===this.rect.element||(this.rect.top=t,this.rect.y=t,this.rect.width=i,this.rect.height=s,this.rect.left=e,this.rect.x=e,this.rect.bottom=t+s,this.rect.right=e+i)}}let t=0;function uid(){return t++}return class Snap{constructor(t,{type:e="mandatory",lerp:i,easing:s,duration:o,velocityThreshold:n=1,onSnapStart:r,onSnapComplete:h}={}){this.isStopped=!1,this.onWindowResize=()=>{this.viewport.width=window.innerWidth,this.viewport.height=window.innerHeight},this.onScroll=({scroll:t,limit:e,lastVelocity:i,velocity:s,isScrolling:o,userData:n,isHorizontal:r})=>{if(this.isStopped)return;const h=Math.abs(i)>Math.abs(s),l=Math.sign(i)!==Math.sign(s)&&0!==s;if(Math.abs(s)<this.options.velocityThreshold&&h&&!l&&"snap"!==(null==n?void 0:n.initiator)){t=Math.ceil(t);let e=[...this.snaps.values()];this.elements.forEach((({rect:t,align:i})=>{let s;i.forEach((i=>{"start"===i?s=t.top:"center"===i?s=r?t.left+t.width/2-this.viewport.width/2:t.top+t.height/2-this.viewport.height/2:"end"===i&&(s=r?t.left+t.width-this.viewport.width:t.top+t.height-this.viewport.height),void 0!==s&&e.push(Math.ceil(s))}))})),e=e.sort(((t,e)=>Math.abs(t)-Math.abs(e)));let i=e.findLast((e=>e<=t));void 0===i&&(i=e[0]);const s=Math.abs(t-i);let o=e.find((e=>e>=t));void 0===o&&(o=e[e.length-1]);const n=s<Math.abs(t-o)?i:o,h=Math.abs(t-n);("mandatory"===this.options.type||"proximity"===this.options.type&&h<=this.viewport.height)&&this.lenis.scrollTo(n,{lerp:this.options.lerp,easing:this.options.easing,duration:this.options.duration,userData:{initiator:"snap"},onStart:()=>{var t,e;null===(e=(t=this.options).onSnapStart)||void 0===e||e.call(t,n)},onComplete:()=>{var t,e;null===(e=(t=this.options).onSnapComplete)||void 0===e||e.call(t,n)}})}},this.lenis=t,this.options={type:e,lerp:i,easing:s,duration:o,velocityThreshold:n,onSnapStart:r,onSnapComplete:h},this.elements=new Map,this.snaps=new Map,this.viewport={width:window.innerWidth,height:window.innerHeight},this.onWindowResize(),window.addEventListener("resize",this.onWindowResize),this.lenis.on("scroll",this.onScroll)}destroy(){this.lenis.off("scroll",this.onScroll),window.removeEventListener("resize",this.onWindowResize),this.elements.forEach((t=>t.destroy()))}start(){this.isStopped=!1}stop(){this.isStopped=!0}add(t){const e=uid();return this.snaps.set(e,t),()=>this.remove(e)}remove(t){this.snaps.delete(t)}addElement(t,e={}){const i=uid();return this.elements.set(i,new SnapElement(t,e)),()=>this.removeElement(i)}removeElement(t){this.elements.delete(t)}}}));
2
2
  //# sourceMappingURL=lenis-snap.min.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"lenis-snap.min.js","sources":["../src/element.ts","../src/uid.ts","../src/index.ts"],"sourcesContent":["function removeParentSticky(element: HTMLElement) {\r\n const position = getComputedStyle(element).position\r\n\r\n const isSticky = position === 'sticky'\r\n\r\n if (isSticky) {\r\n element.style.setProperty('position', 'static')\r\n element.dataset.sticky = 'true'\r\n }\r\n\r\n if (element.offsetParent) {\r\n removeParentSticky(element.offsetParent as HTMLElement)\r\n }\r\n}\r\n\r\nfunction addParentSticky(element: HTMLElement) {\r\n if (element?.dataset?.sticky === 'true') {\r\n element.style.removeProperty('position')\r\n delete element.dataset.sticky\r\n }\r\n\r\n if (element.offsetParent) {\r\n addParentSticky(element.offsetParent as HTMLElement)\r\n }\r\n}\r\n\r\nfunction offsetTop(element: HTMLElement, accumulator = 0) {\r\n const top = accumulator + element.offsetTop\r\n if (element.offsetParent) {\r\n return offsetTop(element.offsetParent as HTMLElement, top)\r\n }\r\n return top\r\n}\r\n\r\nfunction offsetLeft(element: HTMLElement, accumulator = 0) {\r\n const left = accumulator + element.offsetLeft\r\n if (element.offsetParent) {\r\n return offsetLeft(element.offsetParent as HTMLElement, left)\r\n }\r\n return left\r\n}\r\n\r\nfunction scrollTop(element: HTMLElement, accumulator = 0) {\r\n const top = accumulator + element.scrollTop\r\n if (element.offsetParent) {\r\n return scrollTop(element.offsetParent as HTMLElement, top)\r\n }\r\n return top + window.scrollY\r\n}\r\n\r\nfunction scrollLeft(element: HTMLElement, accumulator = 0) {\r\n const left = accumulator + element.scrollLeft\r\n if (element.offsetParent) {\r\n return scrollLeft(element.offsetParent as HTMLElement, left)\r\n }\r\n return left + window.scrollX\r\n}\r\n\r\nexport type SnapElementOptions = {\r\n align?: string[]\r\n ignoreSticky?: boolean\r\n ignoreTransform?: boolean\r\n}\r\n\r\ntype Rect = {\r\n top: number\r\n left: number\r\n width: number\r\n height: number\r\n x: number\r\n y: number\r\n bottom: number\r\n right: number\r\n element: HTMLElement\r\n}\r\n\r\nexport class SnapElement {\r\n element: HTMLElement\r\n options: SnapElementOptions\r\n align: string[]\r\n // @ts-ignore\r\n rect: Rect = {}\r\n wrapperResizeObserver: ResizeObserver\r\n resizeObserver: ResizeObserver\r\n\r\n constructor(\r\n element: HTMLElement,\r\n {\r\n align = ['start'],\r\n ignoreSticky = true,\r\n ignoreTransform = false,\r\n }: SnapElementOptions = {}\r\n ) {\r\n this.element = element\r\n\r\n this.options = { align, ignoreSticky, ignoreTransform }\r\n\r\n // this.ignoreSticky = ignoreSticky\r\n // this.ignoreTransform = ignoreTransform\r\n\r\n this.align = [align].flat()\r\n\r\n // TODO: assing rect immediately\r\n\r\n this.wrapperResizeObserver = new ResizeObserver(this.onWrapperResize)\r\n this.wrapperResizeObserver.observe(document.body)\r\n this.onWrapperResize()\r\n\r\n this.resizeObserver = new ResizeObserver(this.onResize)\r\n this.resizeObserver.observe(this.element)\r\n this.setRect({\r\n width: this.element.offsetWidth,\r\n height: this.element.offsetHeight,\r\n })\r\n }\r\n\r\n destroy() {\r\n this.wrapperResizeObserver.disconnect()\r\n this.resizeObserver.disconnect()\r\n }\r\n\r\n setRect({\r\n top,\r\n left,\r\n width,\r\n height,\r\n element,\r\n }: {\r\n top?: number\r\n left?: number\r\n width?: number\r\n height?: number\r\n element?: HTMLElement\r\n } = {}) {\r\n top = top ?? this.rect.top\r\n left = left ?? this.rect.left\r\n width = width ?? this.rect.width\r\n height = height ?? this.rect.height\r\n element = element ?? this.rect.element\r\n\r\n if (\r\n top === this.rect.top &&\r\n left === this.rect.left &&\r\n width === this.rect.width &&\r\n height === this.rect.height &&\r\n element === this.rect.element\r\n )\r\n return\r\n\r\n this.rect.top = top\r\n this.rect.y = top\r\n this.rect.width = width\r\n this.rect.height = height\r\n this.rect.left = left\r\n this.rect.x = left\r\n this.rect.bottom = top + height\r\n this.rect.right = left + width\r\n }\r\n\r\n onWrapperResize = () => {\r\n let top, left\r\n\r\n if (this.options.ignoreSticky) removeParentSticky(this.element)\r\n if (this.options.ignoreTransform) {\r\n top = offsetTop(this.element)\r\n left = offsetLeft(this.element)\r\n } else {\r\n const rect = this.element.getBoundingClientRect()\r\n top = rect.top + scrollTop(this.element)\r\n left = rect.left + scrollLeft(this.element)\r\n }\r\n if (this.options.ignoreSticky) addParentSticky(this.element)\r\n\r\n this.setRect({ top, left })\r\n }\r\n\r\n onResize = ([entry]: ResizeObserverEntry[]) => {\r\n const width = entry.borderBoxSize[0].inlineSize\r\n const height = entry.borderBoxSize[0].blockSize\r\n\r\n this.setRect({ width, height })\r\n }\r\n}\r\n","let index = 0\r\n\r\nexport type UID = number\r\n\r\nexport function uid(): UID {\r\n return index++\r\n}\r\n","import Lenis from 'lenis'\r\nimport { SnapElement, SnapElementOptions } from './element'\r\nimport { UID, uid } from './uid'\r\n\r\n// TODO:\r\n// - horizontal\r\n// - fix trackpad snapping too soon due to velocity (fuck Apple)\r\n// - fix wheel scrolling after limits (see console scroll to)\r\n// - fix touch scroll, do not snap when not released\r\n// - arrow, spacebar\r\n\r\ntype Viewport = {\r\n width: number\r\n height: number\r\n}\r\n\r\nexport type SnapOptions = {\r\n type?: 'mandatory' | 'proximity'\r\n lerp?: number\r\n easing?: (t: number) => number\r\n duration?: number\r\n velocityThreshold?: number\r\n onSnapStart?: (t: number) => number\r\n onSnapComplete?: (t: number) => number\r\n}\r\n\r\nexport default class Snap {\r\n lenis: Lenis\r\n options: SnapOptions\r\n elements: Map<UID, SnapElement>\r\n snaps: Map<UID, number>\r\n viewport: Viewport\r\n isStopped: Boolean = false\r\n\r\n constructor(\r\n lenis: Lenis,\r\n {\r\n type = 'mandatory',\r\n lerp,\r\n easing,\r\n duration,\r\n velocityThreshold = 1,\r\n onSnapStart,\r\n onSnapComplete,\r\n }: SnapOptions = {}\r\n ) {\r\n this.lenis = lenis\r\n\r\n this.options = {\r\n type,\r\n lerp,\r\n easing,\r\n duration,\r\n velocityThreshold,\r\n onSnapStart,\r\n onSnapComplete,\r\n }\r\n\r\n this.elements = new Map()\r\n this.snaps = new Map()\r\n\r\n this.viewport = {\r\n width: window.innerWidth,\r\n height: window.innerHeight,\r\n }\r\n this.onWindowResize()\r\n window.addEventListener('resize', this.onWindowResize)\r\n\r\n this.lenis.on('scroll', this.onScroll)\r\n }\r\n\r\n // debug() {\r\n // const element = document.createElement('div')\r\n // element.style.cssText = `\r\n // position: fixed;\r\n // background: red;\r\n // border-bottom: 1px solid red;\r\n // left: 0;\r\n // right: 0;\r\n // top: 0;\r\n // z-index: 9999;\r\n // `\r\n // document.body.appendChild(element)\r\n // }\r\n\r\n destroy() {\r\n this.lenis.off('scroll', this.onScroll)\r\n window.removeEventListener('resize', this.onWindowResize)\r\n this.elements.forEach((element) => element.destroy())\r\n }\r\n\r\n start() {\r\n this.isStopped = false\r\n }\r\n\r\n stop() {\r\n this.isStopped = true\r\n }\r\n\r\n add(value: number) {\r\n const id = uid()\r\n\r\n this.snaps.set(id, value)\r\n\r\n return () => this.remove(id)\r\n }\r\n\r\n remove(id: UID) {\r\n this.snaps.delete(id)\r\n }\r\n\r\n addElement(element: HTMLElement, options = {} as SnapElementOptions) {\r\n const id = uid()\r\n\r\n this.elements.set(id, new SnapElement(element, options))\r\n\r\n return () => this.removeElement(id)\r\n }\r\n\r\n removeElement(id: UID) {\r\n this.elements.delete(id)\r\n }\r\n\r\n onWindowResize = () => {\r\n this.viewport.width = window.innerWidth\r\n this.viewport.height = window.innerHeight\r\n }\r\n\r\n onScroll = ({\r\n scroll,\r\n limit,\r\n lastVelocity,\r\n velocity,\r\n isScrolling,\r\n userData,\r\n isHorizontal,\r\n }) => {\r\n if (this.isStopped) return\r\n // console.log(scroll, velocity, type)\r\n\r\n // return\r\n const isDecelerating = Math.abs(lastVelocity) > Math.abs(velocity)\r\n const isTurningBack =\r\n Math.sign(lastVelocity) !== Math.sign(velocity) && velocity !== 0\r\n\r\n // console.log({ lastVelocity, velocity, isTurningBack, isDecelerating })\r\n\r\n // console.log('onScroll')\r\n\r\n if (\r\n Math.abs(velocity) < this.options.velocityThreshold &&\r\n // !isTouching &&\r\n isDecelerating &&\r\n !isTurningBack &&\r\n userData?.initiator !== 'snap'\r\n ) {\r\n scroll = Math.ceil(scroll)\r\n\r\n let snaps = [0, ...this.snaps.values(), limit] as number[]\r\n\r\n this.elements.forEach(({ rect, align }) => {\r\n let snap: number | undefined\r\n\r\n align.forEach((align) => {\r\n if (align === 'start') {\r\n snap = rect.top\r\n } else if (align === 'center') {\r\n snap = isHorizontal\r\n ? rect.left + rect.width / 2 - this.viewport.width / 2\r\n : rect.top + rect.height / 2 - this.viewport.height / 2\r\n } else if (align === 'end') {\r\n snap = isHorizontal\r\n ? rect.left + rect.width - this.viewport.width\r\n : rect.top + rect.height - this.viewport.height\r\n }\r\n\r\n if (snap !== undefined) {\r\n snaps.push(Math.ceil(snap))\r\n }\r\n })\r\n })\r\n\r\n snaps = snaps.sort((a, b) => Math.abs(a) - Math.abs(b))\r\n\r\n let prevSnap = snaps.findLast((snap) => snap <= scroll)\r\n if (prevSnap === undefined) prevSnap = snaps[0]\r\n const distanceToPrevSnap = Math.abs(scroll - prevSnap)\r\n\r\n let nextSnap = snaps.find((snap) => snap >= scroll)\r\n if (nextSnap === undefined) nextSnap = snaps[snaps.length - 1]\r\n const distanceToNextSnap = Math.abs(scroll - nextSnap)\r\n\r\n const snap = distanceToPrevSnap < distanceToNextSnap ? prevSnap : nextSnap\r\n\r\n const distance = Math.abs(scroll - snap)\r\n\r\n if (\r\n this.options.type === 'mandatory' ||\r\n (this.options.type === 'proximity' && distance <= this.viewport.height)\r\n ) {\r\n // this.__isScrolling = true\r\n // this.onSnapStart?.(snap)\r\n\r\n // console.log('scroll to')\r\n\r\n this.lenis.scrollTo(snap, {\r\n lerp: this.options.lerp,\r\n easing: this.options.easing,\r\n duration: this.options.duration,\r\n userData: { initiator: 'snap' },\r\n onStart: () => {\r\n this.options.onSnapStart?.(snap)\r\n },\r\n onComplete: () => {\r\n this.options.onSnapComplete?.(snap)\r\n },\r\n })\r\n }\r\n\r\n // console.timeEnd('scroll')\r\n }\r\n }\r\n}\r\n"],"names":["removeParentSticky","element","getComputedStyle","position","style","setProperty","dataset","sticky","offsetParent","addParentSticky","_a","removeProperty","offsetTop","accumulator","top","offsetLeft","left","scrollTop","window","scrollY","scrollLeft","scrollX","SnapElement","constructor","align","ignoreSticky","ignoreTransform","this","rect","onWrapperResize","options","getBoundingClientRect","setRect","onResize","entry","width","borderBoxSize","inlineSize","height","blockSize","flat","wrapperResizeObserver","ResizeObserver","observe","document","body","resizeObserver","offsetWidth","offsetHeight","destroy","disconnect","y","x","bottom","right","index","uid","Snap","lenis","type","lerp","easing","duration","velocityThreshold","onSnapStart","onSnapComplete","isStopped","onWindowResize","viewport","innerWidth","innerHeight","onScroll","scroll","limit","lastVelocity","velocity","isScrolling","userData","isHorizontal","isDecelerating","Math","abs","isTurningBack","sign","initiator","ceil","snaps","values","elements","forEach","snap","undefined","push","sort","a","b","prevSnap","findLast","distanceToPrevSnap","nextSnap","find","length","distance","scrollTo","onStart","_b","call","onComplete","Map","addEventListener","on","off","removeEventListener","start","stop","add","value","id","set","remove","delete","addElement","removeElement"],"mappings":"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"}
1
+ {"version":3,"file":"lenis-snap.min.js","sources":["../src/element.ts","../src/uid.ts","../src/index.ts"],"sourcesContent":["function removeParentSticky(element: HTMLElement) {\r\n const position = getComputedStyle(element).position\r\n\r\n const isSticky = position === 'sticky'\r\n\r\n if (isSticky) {\r\n element.style.setProperty('position', 'static')\r\n element.dataset.sticky = 'true'\r\n }\r\n\r\n if (element.offsetParent) {\r\n removeParentSticky(element.offsetParent as HTMLElement)\r\n }\r\n}\r\n\r\nfunction addParentSticky(element: HTMLElement) {\r\n if (element?.dataset?.sticky === 'true') {\r\n element.style.removeProperty('position')\r\n delete element.dataset.sticky\r\n }\r\n\r\n if (element.offsetParent) {\r\n addParentSticky(element.offsetParent as HTMLElement)\r\n }\r\n}\r\n\r\nfunction offsetTop(element: HTMLElement, accumulator = 0) {\r\n const top = accumulator + element.offsetTop\r\n if (element.offsetParent) {\r\n return offsetTop(element.offsetParent as HTMLElement, top)\r\n }\r\n return top\r\n}\r\n\r\nfunction offsetLeft(element: HTMLElement, accumulator = 0) {\r\n const left = accumulator + element.offsetLeft\r\n if (element.offsetParent) {\r\n return offsetLeft(element.offsetParent as HTMLElement, left)\r\n }\r\n return left\r\n}\r\n\r\nfunction scrollTop(element: HTMLElement, accumulator = 0) {\r\n const top = accumulator + element.scrollTop\r\n if (element.offsetParent) {\r\n return scrollTop(element.offsetParent as HTMLElement, top)\r\n }\r\n return top + window.scrollY\r\n}\r\n\r\nfunction scrollLeft(element: HTMLElement, accumulator = 0) {\r\n const left = accumulator + element.scrollLeft\r\n if (element.offsetParent) {\r\n return scrollLeft(element.offsetParent as HTMLElement, left)\r\n }\r\n return left + window.scrollX\r\n}\r\n\r\nexport type SnapElementOptions = {\r\n align?: string[]\r\n ignoreSticky?: boolean\r\n ignoreTransform?: boolean\r\n}\r\n\r\ntype Rect = {\r\n top: number\r\n left: number\r\n width: number\r\n height: number\r\n x: number\r\n y: number\r\n bottom: number\r\n right: number\r\n element: HTMLElement\r\n}\r\n\r\nexport class SnapElement {\r\n element: HTMLElement\r\n options: SnapElementOptions\r\n align: string[]\r\n // @ts-ignore\r\n rect: Rect = {}\r\n wrapperResizeObserver: ResizeObserver\r\n resizeObserver: ResizeObserver\r\n\r\n constructor(\r\n element: HTMLElement,\r\n {\r\n align = ['start'],\r\n ignoreSticky = true,\r\n ignoreTransform = false,\r\n }: SnapElementOptions = {}\r\n ) {\r\n this.element = element\r\n\r\n this.options = { align, ignoreSticky, ignoreTransform }\r\n\r\n // this.ignoreSticky = ignoreSticky\r\n // this.ignoreTransform = ignoreTransform\r\n\r\n this.align = [align].flat()\r\n\r\n // TODO: assing rect immediately\r\n\r\n this.wrapperResizeObserver = new ResizeObserver(this.onWrapperResize)\r\n this.wrapperResizeObserver.observe(document.body)\r\n this.onWrapperResize()\r\n\r\n this.resizeObserver = new ResizeObserver(this.onResize)\r\n this.resizeObserver.observe(this.element)\r\n this.setRect({\r\n width: this.element.offsetWidth,\r\n height: this.element.offsetHeight,\r\n })\r\n }\r\n\r\n destroy() {\r\n this.wrapperResizeObserver.disconnect()\r\n this.resizeObserver.disconnect()\r\n }\r\n\r\n setRect({\r\n top,\r\n left,\r\n width,\r\n height,\r\n element,\r\n }: {\r\n top?: number\r\n left?: number\r\n width?: number\r\n height?: number\r\n element?: HTMLElement\r\n } = {}) {\r\n top = top ?? this.rect.top\r\n left = left ?? this.rect.left\r\n width = width ?? this.rect.width\r\n height = height ?? this.rect.height\r\n element = element ?? this.rect.element\r\n\r\n if (\r\n top === this.rect.top &&\r\n left === this.rect.left &&\r\n width === this.rect.width &&\r\n height === this.rect.height &&\r\n element === this.rect.element\r\n )\r\n return\r\n\r\n this.rect.top = top\r\n this.rect.y = top\r\n this.rect.width = width\r\n this.rect.height = height\r\n this.rect.left = left\r\n this.rect.x = left\r\n this.rect.bottom = top + height\r\n this.rect.right = left + width\r\n }\r\n\r\n onWrapperResize = () => {\r\n let top, left\r\n\r\n if (this.options.ignoreSticky) removeParentSticky(this.element)\r\n if (this.options.ignoreTransform) {\r\n top = offsetTop(this.element)\r\n left = offsetLeft(this.element)\r\n } else {\r\n const rect = this.element.getBoundingClientRect()\r\n top = rect.top + scrollTop(this.element)\r\n left = rect.left + scrollLeft(this.element)\r\n }\r\n if (this.options.ignoreSticky) addParentSticky(this.element)\r\n\r\n this.setRect({ top, left })\r\n }\r\n\r\n onResize = ([entry]: ResizeObserverEntry[]) => {\r\n const width = entry.borderBoxSize[0].inlineSize\r\n const height = entry.borderBoxSize[0].blockSize\r\n\r\n this.setRect({ width, height })\r\n }\r\n}\r\n","let index = 0\r\n\r\nexport type UID = number\r\n\r\nexport function uid(): UID {\r\n return index++\r\n}\r\n","import Lenis from 'lenis'\r\nimport { SnapElement, SnapElementOptions } from './element'\r\nimport { UID, uid } from './uid'\r\n\r\n// TODO:\r\n// - horizontal\r\n// - fix trackpad snapping too soon due to velocity (fuck Apple)\r\n// - fix wheel scrolling after limits (see console scroll to)\r\n// - fix touch scroll, do not snap when not released\r\n// - arrow, spacebar\r\n\r\ntype Viewport = {\r\n width: number\r\n height: number\r\n}\r\n\r\nexport type SnapOptions = {\r\n type?: 'mandatory' | 'proximity'\r\n lerp?: number\r\n easing?: (t: number) => number\r\n duration?: number\r\n velocityThreshold?: number\r\n onSnapStart?: (t: number) => number\r\n onSnapComplete?: (t: number) => number\r\n}\r\n\r\nexport default class Snap {\r\n lenis: Lenis\r\n options: SnapOptions\r\n elements: Map<UID, SnapElement>\r\n snaps: Map<UID, number>\r\n viewport: Viewport\r\n isStopped: Boolean = false\r\n\r\n constructor(\r\n lenis: Lenis,\r\n {\r\n type = 'mandatory',\r\n lerp,\r\n easing,\r\n duration,\r\n velocityThreshold = 1,\r\n onSnapStart,\r\n onSnapComplete,\r\n }: SnapOptions = {}\r\n ) {\r\n this.lenis = lenis\r\n\r\n this.options = {\r\n type,\r\n lerp,\r\n easing,\r\n duration,\r\n velocityThreshold,\r\n onSnapStart,\r\n onSnapComplete,\r\n }\r\n\r\n this.elements = new Map()\r\n this.snaps = new Map()\r\n\r\n this.viewport = {\r\n width: window.innerWidth,\r\n height: window.innerHeight,\r\n }\r\n this.onWindowResize()\r\n window.addEventListener('resize', this.onWindowResize)\r\n\r\n this.lenis.on('scroll', this.onScroll)\r\n }\r\n\r\n // debug() {\r\n // const element = document.createElement('div')\r\n // element.style.cssText = `\r\n // position: fixed;\r\n // background: red;\r\n // border-bottom: 1px solid red;\r\n // left: 0;\r\n // right: 0;\r\n // top: 0;\r\n // z-index: 9999;\r\n // `\r\n // document.body.appendChild(element)\r\n // }\r\n\r\n destroy() {\r\n this.lenis.off('scroll', this.onScroll)\r\n window.removeEventListener('resize', this.onWindowResize)\r\n this.elements.forEach((element) => element.destroy())\r\n }\r\n\r\n start() {\r\n this.isStopped = false\r\n }\r\n\r\n stop() {\r\n this.isStopped = true\r\n }\r\n\r\n add(value: number) {\r\n const id = uid()\r\n\r\n this.snaps.set(id, value)\r\n\r\n return () => this.remove(id)\r\n }\r\n\r\n remove(id: UID) {\r\n this.snaps.delete(id)\r\n }\r\n\r\n addElement(element: HTMLElement, options = {} as SnapElementOptions) {\r\n const id = uid()\r\n\r\n this.elements.set(id, new SnapElement(element, options))\r\n\r\n return () => this.removeElement(id)\r\n }\r\n\r\n removeElement(id: UID) {\r\n this.elements.delete(id)\r\n }\r\n\r\n onWindowResize = () => {\r\n this.viewport.width = window.innerWidth\r\n this.viewport.height = window.innerHeight\r\n }\r\n\r\n onScroll = ({\r\n scroll,\r\n limit,\r\n lastVelocity,\r\n velocity,\r\n isScrolling,\r\n userData,\r\n isHorizontal,\r\n }) => {\r\n if (this.isStopped) return\r\n // console.log(scroll, velocity, type)\r\n\r\n // return\r\n const isDecelerating = Math.abs(lastVelocity) > Math.abs(velocity)\r\n const isTurningBack =\r\n Math.sign(lastVelocity) !== Math.sign(velocity) && velocity !== 0\r\n\r\n // console.log({ lastVelocity, velocity, isTurningBack, isDecelerating })\r\n\r\n // console.log('onScroll')\r\n\r\n if (\r\n Math.abs(velocity) < this.options.velocityThreshold &&\r\n // !isTouching &&\r\n isDecelerating &&\r\n !isTurningBack &&\r\n userData?.initiator !== 'snap'\r\n ) {\r\n scroll = Math.ceil(scroll)\r\n\r\n let snaps = [...this.snaps.values()] as number[]\r\n\r\n this.elements.forEach(({ rect, align }) => {\r\n let snap: number | undefined\r\n\r\n align.forEach((align) => {\r\n if (align === 'start') {\r\n snap = rect.top\r\n } else if (align === 'center') {\r\n snap = isHorizontal\r\n ? rect.left + rect.width / 2 - this.viewport.width / 2\r\n : rect.top + rect.height / 2 - this.viewport.height / 2\r\n } else if (align === 'end') {\r\n snap = isHorizontal\r\n ? rect.left + rect.width - this.viewport.width\r\n : rect.top + rect.height - this.viewport.height\r\n }\r\n\r\n if (snap !== undefined) {\r\n snaps.push(Math.ceil(snap))\r\n }\r\n })\r\n })\r\n\r\n snaps = snaps.sort((a, b) => Math.abs(a) - Math.abs(b))\r\n\r\n let prevSnap = snaps.findLast((snap) => snap <= scroll)\r\n if (prevSnap === undefined) prevSnap = snaps[0]\r\n const distanceToPrevSnap = Math.abs(scroll - prevSnap)\r\n\r\n let nextSnap = snaps.find((snap) => snap >= scroll)\r\n if (nextSnap === undefined) nextSnap = snaps[snaps.length - 1]\r\n const distanceToNextSnap = Math.abs(scroll - nextSnap)\r\n\r\n const snap = distanceToPrevSnap < distanceToNextSnap ? prevSnap : nextSnap\r\n\r\n const distance = Math.abs(scroll - snap)\r\n\r\n if (\r\n this.options.type === 'mandatory' ||\r\n (this.options.type === 'proximity' && distance <= this.viewport.height)\r\n ) {\r\n // this.__isScrolling = true\r\n // this.onSnapStart?.(snap)\r\n\r\n // console.log('scroll to')\r\n\r\n this.lenis.scrollTo(snap, {\r\n lerp: this.options.lerp,\r\n easing: this.options.easing,\r\n duration: this.options.duration,\r\n userData: { initiator: 'snap' },\r\n onStart: () => {\r\n this.options.onSnapStart?.(snap)\r\n },\r\n onComplete: () => {\r\n this.options.onSnapComplete?.(snap)\r\n },\r\n })\r\n }\r\n\r\n // console.timeEnd('scroll')\r\n }\r\n }\r\n}\r\n"],"names":["removeParentSticky","element","getComputedStyle","position","style","setProperty","dataset","sticky","offsetParent","addParentSticky","_a","removeProperty","offsetTop","accumulator","top","offsetLeft","left","scrollTop","window","scrollY","scrollLeft","scrollX","SnapElement","constructor","align","ignoreSticky","ignoreTransform","this","rect","onWrapperResize","options","getBoundingClientRect","setRect","onResize","entry","width","borderBoxSize","inlineSize","height","blockSize","flat","wrapperResizeObserver","ResizeObserver","observe","document","body","resizeObserver","offsetWidth","offsetHeight","destroy","disconnect","y","x","bottom","right","index","uid","Snap","lenis","type","lerp","easing","duration","velocityThreshold","onSnapStart","onSnapComplete","isStopped","onWindowResize","viewport","innerWidth","innerHeight","onScroll","scroll","limit","lastVelocity","velocity","isScrolling","userData","isHorizontal","isDecelerating","Math","abs","isTurningBack","sign","initiator","ceil","snaps","values","elements","forEach","snap","undefined","push","sort","a","b","prevSnap","findLast","distanceToPrevSnap","nextSnap","find","length","distance","scrollTo","onStart","_b","call","onComplete","Map","addEventListener","on","off","removeEventListener","start","stop","add","value","id","set","remove","delete","addElement","removeElement"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- function removeParentSticky(t){"sticky"===getComputedStyle(t).position&&(t.style.setProperty("position","static"),t.dataset.sticky="true"),t.offsetParent&&removeParentSticky(t.offsetParent)}function addParentSticky(t){var e;"true"===(null===(e=null==t?void 0:t.dataset)||void 0===e?void 0:e.sticky)&&(t.style.removeProperty("position"),delete t.dataset.sticky),t.offsetParent&&addParentSticky(t.offsetParent)}function offsetTop(t,e=0){const i=e+t.offsetTop;return t.offsetParent?offsetTop(t.offsetParent,i):i}function offsetLeft(t,e=0){const i=e+t.offsetLeft;return t.offsetParent?offsetLeft(t.offsetParent,i):i}function scrollTop(t,e=0){const i=e+t.scrollTop;return t.offsetParent?scrollTop(t.offsetParent,i):i+window.scrollY}function scrollLeft(t,e=0){const i=e+t.scrollLeft;return t.offsetParent?scrollLeft(t.offsetParent,i):i+window.scrollX}class SnapElement{constructor(t,{align:e=["start"],ignoreSticky:i=!0,ignoreTransform:s=!1}={}){this.rect={},this.onWrapperResize=()=>{let t,e;if(this.options.ignoreSticky&&removeParentSticky(this.element),this.options.ignoreTransform)t=offsetTop(this.element),e=offsetLeft(this.element);else{const i=this.element.getBoundingClientRect();t=i.top+scrollTop(this.element),e=i.left+scrollLeft(this.element)}this.options.ignoreSticky&&addParentSticky(this.element),this.setRect({top:t,left:e})},this.onResize=([t])=>{const e=t.borderBoxSize[0].inlineSize,i=t.borderBoxSize[0].blockSize;this.setRect({width:e,height:i})},this.element=t,this.options={align:e,ignoreSticky:i,ignoreTransform:s},this.align=[e].flat(),this.wrapperResizeObserver=new ResizeObserver(this.onWrapperResize),this.wrapperResizeObserver.observe(document.body),this.onWrapperResize(),this.resizeObserver=new ResizeObserver(this.onResize),this.resizeObserver.observe(this.element),this.setRect({width:this.element.offsetWidth,height:this.element.offsetHeight})}destroy(){this.wrapperResizeObserver.disconnect(),this.resizeObserver.disconnect()}setRect({top:t,left:e,width:i,height:s,element:o}={}){t=null!=t?t:this.rect.top,e=null!=e?e:this.rect.left,i=null!=i?i:this.rect.width,s=null!=s?s:this.rect.height,o=null!=o?o:this.rect.element,t===this.rect.top&&e===this.rect.left&&i===this.rect.width&&s===this.rect.height&&o===this.rect.element||(this.rect.top=t,this.rect.y=t,this.rect.width=i,this.rect.height=s,this.rect.left=e,this.rect.x=e,this.rect.bottom=t+s,this.rect.right=e+i)}}let t=0;function uid(){return t++}class Snap{constructor(t,{type:e="mandatory",lerp:i,easing:s,duration:o,velocityThreshold:n=1,onSnapStart:r,onSnapComplete:h}={}){this.isStopped=!1,this.onWindowResize=()=>{this.viewport.width=window.innerWidth,this.viewport.height=window.innerHeight},this.onScroll=({scroll:t,limit:e,lastVelocity:i,velocity:s,isScrolling:o,userData:n,isHorizontal:r})=>{if(this.isStopped)return;const h=Math.abs(i)>Math.abs(s),l=Math.sign(i)!==Math.sign(s)&&0!==s;if(Math.abs(s)<this.options.velocityThreshold&&h&&!l&&"snap"!==(null==n?void 0:n.initiator)){t=Math.ceil(t);let i=[0,...this.snaps.values(),e];this.elements.forEach((({rect:t,align:e})=>{let s;e.forEach((e=>{"start"===e?s=t.top:"center"===e?s=r?t.left+t.width/2-this.viewport.width/2:t.top+t.height/2-this.viewport.height/2:"end"===e&&(s=r?t.left+t.width-this.viewport.width:t.top+t.height-this.viewport.height),void 0!==s&&i.push(Math.ceil(s))}))})),i=i.sort(((t,e)=>Math.abs(t)-Math.abs(e)));let s=i.findLast((e=>e<=t));void 0===s&&(s=i[0]);const o=Math.abs(t-s);let n=i.find((e=>e>=t));void 0===n&&(n=i[i.length-1]);const h=o<Math.abs(t-n)?s:n,l=Math.abs(t-h);("mandatory"===this.options.type||"proximity"===this.options.type&&l<=this.viewport.height)&&this.lenis.scrollTo(h,{lerp:this.options.lerp,easing:this.options.easing,duration:this.options.duration,userData:{initiator:"snap"},onStart:()=>{var t,e;null===(e=(t=this.options).onSnapStart)||void 0===e||e.call(t,h)},onComplete:()=>{var t,e;null===(e=(t=this.options).onSnapComplete)||void 0===e||e.call(t,h)}})}},this.lenis=t,this.options={type:e,lerp:i,easing:s,duration:o,velocityThreshold:n,onSnapStart:r,onSnapComplete:h},this.elements=new Map,this.snaps=new Map,this.viewport={width:window.innerWidth,height:window.innerHeight},this.onWindowResize(),window.addEventListener("resize",this.onWindowResize),this.lenis.on("scroll",this.onScroll)}destroy(){this.lenis.off("scroll",this.onScroll),window.removeEventListener("resize",this.onWindowResize),this.elements.forEach((t=>t.destroy()))}start(){this.isStopped=!1}stop(){this.isStopped=!0}add(t){const e=uid();return this.snaps.set(e,t),()=>this.remove(e)}remove(t){this.snaps.delete(t)}addElement(t,e={}){const i=uid();return this.elements.set(i,new SnapElement(t,e)),()=>this.removeElement(i)}removeElement(t){this.elements.delete(t)}}export{Snap as default};
1
+ function removeParentSticky(t){"sticky"===getComputedStyle(t).position&&(t.style.setProperty("position","static"),t.dataset.sticky="true"),t.offsetParent&&removeParentSticky(t.offsetParent)}function addParentSticky(t){var e;"true"===(null===(e=null==t?void 0:t.dataset)||void 0===e?void 0:e.sticky)&&(t.style.removeProperty("position"),delete t.dataset.sticky),t.offsetParent&&addParentSticky(t.offsetParent)}function offsetTop(t,e=0){const i=e+t.offsetTop;return t.offsetParent?offsetTop(t.offsetParent,i):i}function offsetLeft(t,e=0){const i=e+t.offsetLeft;return t.offsetParent?offsetLeft(t.offsetParent,i):i}function scrollTop(t,e=0){const i=e+t.scrollTop;return t.offsetParent?scrollTop(t.offsetParent,i):i+window.scrollY}function scrollLeft(t,e=0){const i=e+t.scrollLeft;return t.offsetParent?scrollLeft(t.offsetParent,i):i+window.scrollX}class SnapElement{constructor(t,{align:e=["start"],ignoreSticky:i=!0,ignoreTransform:s=!1}={}){this.rect={},this.onWrapperResize=()=>{let t,e;if(this.options.ignoreSticky&&removeParentSticky(this.element),this.options.ignoreTransform)t=offsetTop(this.element),e=offsetLeft(this.element);else{const i=this.element.getBoundingClientRect();t=i.top+scrollTop(this.element),e=i.left+scrollLeft(this.element)}this.options.ignoreSticky&&addParentSticky(this.element),this.setRect({top:t,left:e})},this.onResize=([t])=>{const e=t.borderBoxSize[0].inlineSize,i=t.borderBoxSize[0].blockSize;this.setRect({width:e,height:i})},this.element=t,this.options={align:e,ignoreSticky:i,ignoreTransform:s},this.align=[e].flat(),this.wrapperResizeObserver=new ResizeObserver(this.onWrapperResize),this.wrapperResizeObserver.observe(document.body),this.onWrapperResize(),this.resizeObserver=new ResizeObserver(this.onResize),this.resizeObserver.observe(this.element),this.setRect({width:this.element.offsetWidth,height:this.element.offsetHeight})}destroy(){this.wrapperResizeObserver.disconnect(),this.resizeObserver.disconnect()}setRect({top:t,left:e,width:i,height:s,element:o}={}){t=null!=t?t:this.rect.top,e=null!=e?e:this.rect.left,i=null!=i?i:this.rect.width,s=null!=s?s:this.rect.height,o=null!=o?o:this.rect.element,t===this.rect.top&&e===this.rect.left&&i===this.rect.width&&s===this.rect.height&&o===this.rect.element||(this.rect.top=t,this.rect.y=t,this.rect.width=i,this.rect.height=s,this.rect.left=e,this.rect.x=e,this.rect.bottom=t+s,this.rect.right=e+i)}}let t=0;function uid(){return t++}class Snap{constructor(t,{type:e="mandatory",lerp:i,easing:s,duration:o,velocityThreshold:n=1,onSnapStart:r,onSnapComplete:h}={}){this.isStopped=!1,this.onWindowResize=()=>{this.viewport.width=window.innerWidth,this.viewport.height=window.innerHeight},this.onScroll=({scroll:t,limit:e,lastVelocity:i,velocity:s,isScrolling:o,userData:n,isHorizontal:r})=>{if(this.isStopped)return;const h=Math.abs(i)>Math.abs(s),l=Math.sign(i)!==Math.sign(s)&&0!==s;if(Math.abs(s)<this.options.velocityThreshold&&h&&!l&&"snap"!==(null==n?void 0:n.initiator)){t=Math.ceil(t);let e=[...this.snaps.values()];this.elements.forEach((({rect:t,align:i})=>{let s;i.forEach((i=>{"start"===i?s=t.top:"center"===i?s=r?t.left+t.width/2-this.viewport.width/2:t.top+t.height/2-this.viewport.height/2:"end"===i&&(s=r?t.left+t.width-this.viewport.width:t.top+t.height-this.viewport.height),void 0!==s&&e.push(Math.ceil(s))}))})),e=e.sort(((t,e)=>Math.abs(t)-Math.abs(e)));let i=e.findLast((e=>e<=t));void 0===i&&(i=e[0]);const s=Math.abs(t-i);let o=e.find((e=>e>=t));void 0===o&&(o=e[e.length-1]);const n=s<Math.abs(t-o)?i:o,h=Math.abs(t-n);("mandatory"===this.options.type||"proximity"===this.options.type&&h<=this.viewport.height)&&this.lenis.scrollTo(n,{lerp:this.options.lerp,easing:this.options.easing,duration:this.options.duration,userData:{initiator:"snap"},onStart:()=>{var t,e;null===(e=(t=this.options).onSnapStart)||void 0===e||e.call(t,n)},onComplete:()=>{var t,e;null===(e=(t=this.options).onSnapComplete)||void 0===e||e.call(t,n)}})}},this.lenis=t,this.options={type:e,lerp:i,easing:s,duration:o,velocityThreshold:n,onSnapStart:r,onSnapComplete:h},this.elements=new Map,this.snaps=new Map,this.viewport={width:window.innerWidth,height:window.innerHeight},this.onWindowResize(),window.addEventListener("resize",this.onWindowResize),this.lenis.on("scroll",this.onScroll)}destroy(){this.lenis.off("scroll",this.onScroll),window.removeEventListener("resize",this.onWindowResize),this.elements.forEach((t=>t.destroy()))}start(){this.isStopped=!1}stop(){this.isStopped=!0}add(t){const e=uid();return this.snaps.set(e,t),()=>this.remove(e)}remove(t){this.snaps.delete(t)}addElement(t,e={}){const i=uid();return this.elements.set(i,new SnapElement(t,e)),()=>this.removeElement(i)}removeElement(t){this.elements.delete(t)}}export{Snap as default};
2
2
  //# sourceMappingURL=lenis-snap.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"lenis-snap.mjs","sources":["../src/element.ts","../src/uid.ts","../src/index.ts"],"sourcesContent":["function removeParentSticky(element: HTMLElement) {\r\n const position = getComputedStyle(element).position\r\n\r\n const isSticky = position === 'sticky'\r\n\r\n if (isSticky) {\r\n element.style.setProperty('position', 'static')\r\n element.dataset.sticky = 'true'\r\n }\r\n\r\n if (element.offsetParent) {\r\n removeParentSticky(element.offsetParent as HTMLElement)\r\n }\r\n}\r\n\r\nfunction addParentSticky(element: HTMLElement) {\r\n if (element?.dataset?.sticky === 'true') {\r\n element.style.removeProperty('position')\r\n delete element.dataset.sticky\r\n }\r\n\r\n if (element.offsetParent) {\r\n addParentSticky(element.offsetParent as HTMLElement)\r\n }\r\n}\r\n\r\nfunction offsetTop(element: HTMLElement, accumulator = 0) {\r\n const top = accumulator + element.offsetTop\r\n if (element.offsetParent) {\r\n return offsetTop(element.offsetParent as HTMLElement, top)\r\n }\r\n return top\r\n}\r\n\r\nfunction offsetLeft(element: HTMLElement, accumulator = 0) {\r\n const left = accumulator + element.offsetLeft\r\n if (element.offsetParent) {\r\n return offsetLeft(element.offsetParent as HTMLElement, left)\r\n }\r\n return left\r\n}\r\n\r\nfunction scrollTop(element: HTMLElement, accumulator = 0) {\r\n const top = accumulator + element.scrollTop\r\n if (element.offsetParent) {\r\n return scrollTop(element.offsetParent as HTMLElement, top)\r\n }\r\n return top + window.scrollY\r\n}\r\n\r\nfunction scrollLeft(element: HTMLElement, accumulator = 0) {\r\n const left = accumulator + element.scrollLeft\r\n if (element.offsetParent) {\r\n return scrollLeft(element.offsetParent as HTMLElement, left)\r\n }\r\n return left + window.scrollX\r\n}\r\n\r\nexport type SnapElementOptions = {\r\n align?: string[]\r\n ignoreSticky?: boolean\r\n ignoreTransform?: boolean\r\n}\r\n\r\ntype Rect = {\r\n top: number\r\n left: number\r\n width: number\r\n height: number\r\n x: number\r\n y: number\r\n bottom: number\r\n right: number\r\n element: HTMLElement\r\n}\r\n\r\nexport class SnapElement {\r\n element: HTMLElement\r\n options: SnapElementOptions\r\n align: string[]\r\n // @ts-ignore\r\n rect: Rect = {}\r\n wrapperResizeObserver: ResizeObserver\r\n resizeObserver: ResizeObserver\r\n\r\n constructor(\r\n element: HTMLElement,\r\n {\r\n align = ['start'],\r\n ignoreSticky = true,\r\n ignoreTransform = false,\r\n }: SnapElementOptions = {}\r\n ) {\r\n this.element = element\r\n\r\n this.options = { align, ignoreSticky, ignoreTransform }\r\n\r\n // this.ignoreSticky = ignoreSticky\r\n // this.ignoreTransform = ignoreTransform\r\n\r\n this.align = [align].flat()\r\n\r\n // TODO: assing rect immediately\r\n\r\n this.wrapperResizeObserver = new ResizeObserver(this.onWrapperResize)\r\n this.wrapperResizeObserver.observe(document.body)\r\n this.onWrapperResize()\r\n\r\n this.resizeObserver = new ResizeObserver(this.onResize)\r\n this.resizeObserver.observe(this.element)\r\n this.setRect({\r\n width: this.element.offsetWidth,\r\n height: this.element.offsetHeight,\r\n })\r\n }\r\n\r\n destroy() {\r\n this.wrapperResizeObserver.disconnect()\r\n this.resizeObserver.disconnect()\r\n }\r\n\r\n setRect({\r\n top,\r\n left,\r\n width,\r\n height,\r\n element,\r\n }: {\r\n top?: number\r\n left?: number\r\n width?: number\r\n height?: number\r\n element?: HTMLElement\r\n } = {}) {\r\n top = top ?? this.rect.top\r\n left = left ?? this.rect.left\r\n width = width ?? this.rect.width\r\n height = height ?? this.rect.height\r\n element = element ?? this.rect.element\r\n\r\n if (\r\n top === this.rect.top &&\r\n left === this.rect.left &&\r\n width === this.rect.width &&\r\n height === this.rect.height &&\r\n element === this.rect.element\r\n )\r\n return\r\n\r\n this.rect.top = top\r\n this.rect.y = top\r\n this.rect.width = width\r\n this.rect.height = height\r\n this.rect.left = left\r\n this.rect.x = left\r\n this.rect.bottom = top + height\r\n this.rect.right = left + width\r\n }\r\n\r\n onWrapperResize = () => {\r\n let top, left\r\n\r\n if (this.options.ignoreSticky) removeParentSticky(this.element)\r\n if (this.options.ignoreTransform) {\r\n top = offsetTop(this.element)\r\n left = offsetLeft(this.element)\r\n } else {\r\n const rect = this.element.getBoundingClientRect()\r\n top = rect.top + scrollTop(this.element)\r\n left = rect.left + scrollLeft(this.element)\r\n }\r\n if (this.options.ignoreSticky) addParentSticky(this.element)\r\n\r\n this.setRect({ top, left })\r\n }\r\n\r\n onResize = ([entry]: ResizeObserverEntry[]) => {\r\n const width = entry.borderBoxSize[0].inlineSize\r\n const height = entry.borderBoxSize[0].blockSize\r\n\r\n this.setRect({ width, height })\r\n }\r\n}\r\n","let index = 0\r\n\r\nexport type UID = number\r\n\r\nexport function uid(): UID {\r\n return index++\r\n}\r\n","import Lenis from 'lenis'\r\nimport { SnapElement, SnapElementOptions } from './element'\r\nimport { UID, uid } from './uid'\r\n\r\n// TODO:\r\n// - horizontal\r\n// - fix trackpad snapping too soon due to velocity (fuck Apple)\r\n// - fix wheel scrolling after limits (see console scroll to)\r\n// - fix touch scroll, do not snap when not released\r\n// - arrow, spacebar\r\n\r\ntype Viewport = {\r\n width: number\r\n height: number\r\n}\r\n\r\nexport type SnapOptions = {\r\n type?: 'mandatory' | 'proximity'\r\n lerp?: number\r\n easing?: (t: number) => number\r\n duration?: number\r\n velocityThreshold?: number\r\n onSnapStart?: (t: number) => number\r\n onSnapComplete?: (t: number) => number\r\n}\r\n\r\nexport default class Snap {\r\n lenis: Lenis\r\n options: SnapOptions\r\n elements: Map<UID, SnapElement>\r\n snaps: Map<UID, number>\r\n viewport: Viewport\r\n isStopped: Boolean = false\r\n\r\n constructor(\r\n lenis: Lenis,\r\n {\r\n type = 'mandatory',\r\n lerp,\r\n easing,\r\n duration,\r\n velocityThreshold = 1,\r\n onSnapStart,\r\n onSnapComplete,\r\n }: SnapOptions = {}\r\n ) {\r\n this.lenis = lenis\r\n\r\n this.options = {\r\n type,\r\n lerp,\r\n easing,\r\n duration,\r\n velocityThreshold,\r\n onSnapStart,\r\n onSnapComplete,\r\n }\r\n\r\n this.elements = new Map()\r\n this.snaps = new Map()\r\n\r\n this.viewport = {\r\n width: window.innerWidth,\r\n height: window.innerHeight,\r\n }\r\n this.onWindowResize()\r\n window.addEventListener('resize', this.onWindowResize)\r\n\r\n this.lenis.on('scroll', this.onScroll)\r\n }\r\n\r\n // debug() {\r\n // const element = document.createElement('div')\r\n // element.style.cssText = `\r\n // position: fixed;\r\n // background: red;\r\n // border-bottom: 1px solid red;\r\n // left: 0;\r\n // right: 0;\r\n // top: 0;\r\n // z-index: 9999;\r\n // `\r\n // document.body.appendChild(element)\r\n // }\r\n\r\n destroy() {\r\n this.lenis.off('scroll', this.onScroll)\r\n window.removeEventListener('resize', this.onWindowResize)\r\n this.elements.forEach((element) => element.destroy())\r\n }\r\n\r\n start() {\r\n this.isStopped = false\r\n }\r\n\r\n stop() {\r\n this.isStopped = true\r\n }\r\n\r\n add(value: number) {\r\n const id = uid()\r\n\r\n this.snaps.set(id, value)\r\n\r\n return () => this.remove(id)\r\n }\r\n\r\n remove(id: UID) {\r\n this.snaps.delete(id)\r\n }\r\n\r\n addElement(element: HTMLElement, options = {} as SnapElementOptions) {\r\n const id = uid()\r\n\r\n this.elements.set(id, new SnapElement(element, options))\r\n\r\n return () => this.removeElement(id)\r\n }\r\n\r\n removeElement(id: UID) {\r\n this.elements.delete(id)\r\n }\r\n\r\n onWindowResize = () => {\r\n this.viewport.width = window.innerWidth\r\n this.viewport.height = window.innerHeight\r\n }\r\n\r\n onScroll = ({\r\n scroll,\r\n limit,\r\n lastVelocity,\r\n velocity,\r\n isScrolling,\r\n userData,\r\n isHorizontal,\r\n }) => {\r\n if (this.isStopped) return\r\n // console.log(scroll, velocity, type)\r\n\r\n // return\r\n const isDecelerating = Math.abs(lastVelocity) > Math.abs(velocity)\r\n const isTurningBack =\r\n Math.sign(lastVelocity) !== Math.sign(velocity) && velocity !== 0\r\n\r\n // console.log({ lastVelocity, velocity, isTurningBack, isDecelerating })\r\n\r\n // console.log('onScroll')\r\n\r\n if (\r\n Math.abs(velocity) < this.options.velocityThreshold &&\r\n // !isTouching &&\r\n isDecelerating &&\r\n !isTurningBack &&\r\n userData?.initiator !== 'snap'\r\n ) {\r\n scroll = Math.ceil(scroll)\r\n\r\n let snaps = [0, ...this.snaps.values(), limit] as number[]\r\n\r\n this.elements.forEach(({ rect, align }) => {\r\n let snap: number | undefined\r\n\r\n align.forEach((align) => {\r\n if (align === 'start') {\r\n snap = rect.top\r\n } else if (align === 'center') {\r\n snap = isHorizontal\r\n ? rect.left + rect.width / 2 - this.viewport.width / 2\r\n : rect.top + rect.height / 2 - this.viewport.height / 2\r\n } else if (align === 'end') {\r\n snap = isHorizontal\r\n ? rect.left + rect.width - this.viewport.width\r\n : rect.top + rect.height - this.viewport.height\r\n }\r\n\r\n if (snap !== undefined) {\r\n snaps.push(Math.ceil(snap))\r\n }\r\n })\r\n })\r\n\r\n snaps = snaps.sort((a, b) => Math.abs(a) - Math.abs(b))\r\n\r\n let prevSnap = snaps.findLast((snap) => snap <= scroll)\r\n if (prevSnap === undefined) prevSnap = snaps[0]\r\n const distanceToPrevSnap = Math.abs(scroll - prevSnap)\r\n\r\n let nextSnap = snaps.find((snap) => snap >= scroll)\r\n if (nextSnap === undefined) nextSnap = snaps[snaps.length - 1]\r\n const distanceToNextSnap = Math.abs(scroll - nextSnap)\r\n\r\n const snap = distanceToPrevSnap < distanceToNextSnap ? prevSnap : nextSnap\r\n\r\n const distance = Math.abs(scroll - snap)\r\n\r\n if (\r\n this.options.type === 'mandatory' ||\r\n (this.options.type === 'proximity' && distance <= this.viewport.height)\r\n ) {\r\n // this.__isScrolling = true\r\n // this.onSnapStart?.(snap)\r\n\r\n // console.log('scroll to')\r\n\r\n this.lenis.scrollTo(snap, {\r\n lerp: this.options.lerp,\r\n easing: this.options.easing,\r\n duration: this.options.duration,\r\n userData: { initiator: 'snap' },\r\n onStart: () => {\r\n this.options.onSnapStart?.(snap)\r\n },\r\n onComplete: () => {\r\n this.options.onSnapComplete?.(snap)\r\n },\r\n })\r\n }\r\n\r\n // console.timeEnd('scroll')\r\n }\r\n }\r\n}\r\n"],"names":["removeParentSticky","element","getComputedStyle","position","style","setProperty","dataset","sticky","offsetParent","addParentSticky","_a","removeProperty","offsetTop","accumulator","top","offsetLeft","left","scrollTop","window","scrollY","scrollLeft","scrollX","SnapElement","constructor","align","ignoreSticky","ignoreTransform","this","rect","onWrapperResize","options","getBoundingClientRect","setRect","onResize","entry","width","borderBoxSize","inlineSize","height","blockSize","flat","wrapperResizeObserver","ResizeObserver","observe","document","body","resizeObserver","offsetWidth","offsetHeight","destroy","disconnect","y","x","bottom","right","index","uid","Snap","lenis","type","lerp","easing","duration","velocityThreshold","onSnapStart","onSnapComplete","isStopped","onWindowResize","viewport","innerWidth","innerHeight","onScroll","scroll","limit","lastVelocity","velocity","isScrolling","userData","isHorizontal","isDecelerating","Math","abs","isTurningBack","sign","initiator","ceil","snaps","values","elements","forEach","snap","undefined","push","sort","a","b","prevSnap","findLast","distanceToPrevSnap","nextSnap","find","length","distance","scrollTo","onStart","_b","call","onComplete","Map","addEventListener","on","off","removeEventListener","start","stop","add","value","id","set","remove","delete","addElement","removeElement"],"mappings":"AAAA,SAASA,mBAAmBC,GAGI,WAFbC,iBAAiBD,GAASE,WAKzCF,EAAQG,MAAMC,YAAY,WAAY,UACtCJ,EAAQK,QAAQC,OAAS,QAGvBN,EAAQO,cACVR,mBAAmBC,EAAQO,aAE/B,CAEA,SAASC,gBAAgBR,SACU,UAAX,QAAlBS,EAAAT,aAAA,EAAAA,EAASK,eAAS,IAAAI,OAAA,EAAAA,EAAAH,UACpBN,EAAQG,MAAMO,eAAe,mBACtBV,EAAQK,QAAQC,QAGrBN,EAAQO,cACVC,gBAAgBR,EAAQO,aAE5B,CAEA,SAASI,UAAUX,EAAsBY,EAAc,GACrD,MAAMC,EAAMD,EAAcZ,EAAQW,UAClC,OAAIX,EAAQO,aACHI,UAAUX,EAAQO,aAA6BM,GAEjDA,CACT,CAEA,SAASC,WAAWd,EAAsBY,EAAc,GACtD,MAAMG,EAAOH,EAAcZ,EAAQc,WACnC,OAAId,EAAQO,aACHO,WAAWd,EAAQO,aAA6BQ,GAElDA,CACT,CAEA,SAASC,UAAUhB,EAAsBY,EAAc,GACrD,MAAMC,EAAMD,EAAcZ,EAAQgB,UAClC,OAAIhB,EAAQO,aACHS,UAAUhB,EAAQO,aAA6BM,GAEjDA,EAAMI,OAAOC,OACtB,CAEA,SAASC,WAAWnB,EAAsBY,EAAc,GACtD,MAAMG,EAAOH,EAAcZ,EAAQmB,WACnC,OAAInB,EAAQO,aACHY,WAAWnB,EAAQO,aAA6BQ,GAElDA,EAAOE,OAAOG,OACvB,OAoBaC,YASX,WAAAC,CACEtB,GACAuB,MACEA,EAAQ,CAAC,SAAQC,aACjBA,GAAe,EAAIC,gBACnBA,GAAkB,GACI,CAAA,GAV1BC,KAAIC,KAAS,GA8EbD,KAAeE,gBAAG,KAChB,IAAIf,EAAKE,EAGT,GADIW,KAAKG,QAAQL,cAAczB,mBAAmB2B,KAAK1B,SACnD0B,KAAKG,QAAQJ,gBACfZ,EAAMF,UAAUe,KAAK1B,SACrBe,EAAOD,WAAWY,KAAK1B,aAClB,CACL,MAAM2B,EAAOD,KAAK1B,QAAQ8B,wBAC1BjB,EAAMc,EAAKd,IAAMG,UAAUU,KAAK1B,SAChCe,EAAOY,EAAKZ,KAAOI,WAAWO,KAAK1B,QACpC,CACG0B,KAAKG,QAAQL,cAAchB,gBAAgBkB,KAAK1B,SAEpD0B,KAAKK,QAAQ,CAAElB,MAAKE,QAAO,EAG7BW,KAAAM,SAAW,EAAEC,MACX,MAAMC,EAAQD,EAAME,cAAc,GAAGC,WAC/BC,EAASJ,EAAME,cAAc,GAAGG,UAEtCZ,KAAKK,QAAQ,CAAEG,QAAOG,UAAS,EAvF/BX,KAAK1B,QAAUA,EAEf0B,KAAKG,QAAU,CAAEN,QAAOC,eAAcC,mBAKtCC,KAAKH,MAAQ,CAACA,GAAOgB,OAIrBb,KAAKc,sBAAwB,IAAIC,eAAef,KAAKE,iBACrDF,KAAKc,sBAAsBE,QAAQC,SAASC,MAC5ClB,KAAKE,kBAELF,KAAKmB,eAAiB,IAAIJ,eAAef,KAAKM,UAC9CN,KAAKmB,eAAeH,QAAQhB,KAAK1B,SACjC0B,KAAKK,QAAQ,CACXG,MAAOR,KAAK1B,QAAQ8C,YACpBT,OAAQX,KAAK1B,QAAQ+C,cAExB,CAED,OAAAC,GACEtB,KAAKc,sBAAsBS,aAC3BvB,KAAKmB,eAAeI,YACrB,CAED,OAAAlB,EAAQlB,IACNA,EAAGE,KACHA,EAAImB,MACJA,EAAKG,OACLA,EAAMrC,QACNA,GAOE,IACFa,EAAMA,QAAAA,EAAOa,KAAKC,KAAKd,IACvBE,EAAOA,QAAAA,EAAQW,KAAKC,KAAKZ,KACzBmB,EAAQA,QAAAA,EAASR,KAAKC,KAAKO,MAC3BG,EAASA,QAAAA,EAAUX,KAAKC,KAAKU,OAC7BrC,EAAUA,QAAAA,EAAW0B,KAAKC,KAAK3B,QAG7Ba,IAAQa,KAAKC,KAAKd,KAClBE,IAASW,KAAKC,KAAKZ,MACnBmB,IAAUR,KAAKC,KAAKO,OACpBG,IAAWX,KAAKC,KAAKU,QACrBrC,IAAY0B,KAAKC,KAAK3B,UAIxB0B,KAAKC,KAAKd,IAAMA,EAChBa,KAAKC,KAAKuB,EAAIrC,EACda,KAAKC,KAAKO,MAAQA,EAClBR,KAAKC,KAAKU,OAASA,EACnBX,KAAKC,KAAKZ,KAAOA,EACjBW,KAAKC,KAAKwB,EAAIpC,EACdW,KAAKC,KAAKyB,OAASvC,EAAMwB,EACzBX,KAAKC,KAAK0B,MAAQtC,EAAOmB,EAC1B,EC7JH,IAAIoB,EAAQ,WAIIC,MACd,OAAOD,GACT,CCoBc,MAAOE,KAQnB,WAAAlC,CACEmC,GACAC,KACEA,EAAO,YAAWC,KAClBA,EAAIC,OACJA,EAAMC,SACNA,EAAQC,kBACRA,EAAoB,EAACC,YACrBA,EAAWC,eACXA,GACe,CAAA,GAZnBtC,KAASuC,WAAY,EA2FrBvC,KAAcwC,eAAG,KACfxC,KAAKyC,SAASjC,MAAQjB,OAAOmD,WAC7B1C,KAAKyC,SAAS9B,OAASpB,OAAOoD,WAAW,EAG3C3C,KAAA4C,SAAW,EACTC,SACAC,QACAC,eACAC,WACAC,cACAC,WACAC,mBAEA,GAAInD,KAAKuC,UAAW,OAIpB,MAAMa,EAAiBC,KAAKC,IAAIP,GAAgBM,KAAKC,IAAIN,GACnDO,EACJF,KAAKG,KAAKT,KAAkBM,KAAKG,KAAKR,IAA0B,IAAbA,EAMrD,GACEK,KAAKC,IAAIN,GAAYhD,KAAKG,QAAQiC,mBAElCgB,IACCG,GACuB,UAAxBL,aAAA,EAAAA,EAAUO,WACV,CACAZ,EAASQ,KAAKK,KAAKb,GAEnB,IAAIc,EAAQ,CAAC,KAAM3D,KAAK2D,MAAMC,SAAUd,GAExC9C,KAAK6D,SAASC,SAAQ,EAAG7D,OAAMJ,YAC7B,IAAIkE,EAEJlE,EAAMiE,SAASjE,IACC,UAAVA,EACFkE,EAAO9D,EAAKd,IACO,WAAVU,EACTkE,EAAOZ,EACHlD,EAAKZ,KAAOY,EAAKO,MAAQ,EAAIR,KAAKyC,SAASjC,MAAQ,EACnDP,EAAKd,IAAMc,EAAKU,OAAS,EAAIX,KAAKyC,SAAS9B,OAAS,EACrC,QAAVd,IACTkE,EAAOZ,EACHlD,EAAKZ,KAAOY,EAAKO,MAAQR,KAAKyC,SAASjC,MACvCP,EAAKd,IAAMc,EAAKU,OAASX,KAAKyC,SAAS9B,aAGhCqD,IAATD,GACFJ,EAAMM,KAAKZ,KAAKK,KAAKK,GACtB,GACD,IAGJJ,EAAQA,EAAMO,MAAK,CAACC,EAAGC,IAAMf,KAAKC,IAAIa,GAAKd,KAAKC,IAAIc,KAEpD,IAAIC,EAAWV,EAAMW,UAAUP,GAASA,GAAQlB,SAC/BmB,IAAbK,IAAwBA,EAAWV,EAAM,IAC7C,MAAMY,EAAqBlB,KAAKC,IAAIT,EAASwB,GAE7C,IAAIG,EAAWb,EAAMc,MAAMV,GAASA,GAAQlB,SAC3BmB,IAAbQ,IAAwBA,EAAWb,EAAMA,EAAMe,OAAS,IAC5D,MAEMX,EAAOQ,EAFclB,KAAKC,IAAIT,EAAS2B,GAEUH,EAAWG,EAE5DG,EAAWtB,KAAKC,IAAIT,EAASkB,IAGX,cAAtB/D,KAAKG,QAAQ6B,MACU,cAAtBhC,KAAKG,QAAQ6B,MAAwB2C,GAAY3E,KAAKyC,SAAS9B,SAOhEX,KAAK+B,MAAM6C,SAASb,EAAM,CACxB9B,KAAMjC,KAAKG,QAAQ8B,KACnBC,OAAQlC,KAAKG,QAAQ+B,OACrBC,SAAUnC,KAAKG,QAAQgC,SACvBe,SAAU,CAAEO,UAAW,QACvBoB,QAAS,aACiB,QAAxBC,GAAA/F,EAAAiB,KAAKG,SAAQkC,mBAAW,IAAAyC,GAAAA,EAAAC,KAAAhG,EAAGgF,EAAK,EAElCiB,WAAY,aACiB,QAA3BF,GAAA/F,EAAAiB,KAAKG,SAAQmC,sBAAc,IAAAwC,GAAAA,EAAAC,KAAAhG,EAAGgF,EAAK,GAM1C,GA9KD/D,KAAK+B,MAAQA,EAEb/B,KAAKG,QAAU,CACb6B,OACAC,OACAC,SACAC,WACAC,oBACAC,cACAC,kBAGFtC,KAAK6D,SAAW,IAAIoB,IACpBjF,KAAK2D,MAAQ,IAAIsB,IAEjBjF,KAAKyC,SAAW,CACdjC,MAAOjB,OAAOmD,WACd/B,OAAQpB,OAAOoD,aAEjB3C,KAAKwC,iBACLjD,OAAO2F,iBAAiB,SAAUlF,KAAKwC,gBAEvCxC,KAAK+B,MAAMoD,GAAG,SAAUnF,KAAK4C,SAC9B,CAgBD,OAAAtB,GACEtB,KAAK+B,MAAMqD,IAAI,SAAUpF,KAAK4C,UAC9BrD,OAAO8F,oBAAoB,SAAUrF,KAAKwC,gBAC1CxC,KAAK6D,SAASC,SAASxF,GAAYA,EAAQgD,WAC5C,CAED,KAAAgE,GACEtF,KAAKuC,WAAY,CAClB,CAED,IAAAgD,GACEvF,KAAKuC,WAAY,CAClB,CAED,GAAAiD,CAAIC,GACF,MAAMC,EAAK7D,MAIX,OAFA7B,KAAK2D,MAAMgC,IAAID,EAAID,GAEZ,IAAMzF,KAAK4F,OAAOF,EAC1B,CAED,MAAAE,CAAOF,GACL1F,KAAK2D,MAAMkC,OAAOH,EACnB,CAED,UAAAI,CAAWxH,EAAsB6B,EAAU,IACzC,MAAMuF,EAAK7D,MAIX,OAFA7B,KAAK6D,SAAS8B,IAAID,EAAI,IAAI/F,YAAYrB,EAAS6B,IAExC,IAAMH,KAAK+F,cAAcL,EACjC,CAED,aAAAK,CAAcL,GACZ1F,KAAK6D,SAASgC,OAAOH,EACtB"}
1
+ {"version":3,"file":"lenis-snap.mjs","sources":["../src/element.ts","../src/uid.ts","../src/index.ts"],"sourcesContent":["function removeParentSticky(element: HTMLElement) {\r\n const position = getComputedStyle(element).position\r\n\r\n const isSticky = position === 'sticky'\r\n\r\n if (isSticky) {\r\n element.style.setProperty('position', 'static')\r\n element.dataset.sticky = 'true'\r\n }\r\n\r\n if (element.offsetParent) {\r\n removeParentSticky(element.offsetParent as HTMLElement)\r\n }\r\n}\r\n\r\nfunction addParentSticky(element: HTMLElement) {\r\n if (element?.dataset?.sticky === 'true') {\r\n element.style.removeProperty('position')\r\n delete element.dataset.sticky\r\n }\r\n\r\n if (element.offsetParent) {\r\n addParentSticky(element.offsetParent as HTMLElement)\r\n }\r\n}\r\n\r\nfunction offsetTop(element: HTMLElement, accumulator = 0) {\r\n const top = accumulator + element.offsetTop\r\n if (element.offsetParent) {\r\n return offsetTop(element.offsetParent as HTMLElement, top)\r\n }\r\n return top\r\n}\r\n\r\nfunction offsetLeft(element: HTMLElement, accumulator = 0) {\r\n const left = accumulator + element.offsetLeft\r\n if (element.offsetParent) {\r\n return offsetLeft(element.offsetParent as HTMLElement, left)\r\n }\r\n return left\r\n}\r\n\r\nfunction scrollTop(element: HTMLElement, accumulator = 0) {\r\n const top = accumulator + element.scrollTop\r\n if (element.offsetParent) {\r\n return scrollTop(element.offsetParent as HTMLElement, top)\r\n }\r\n return top + window.scrollY\r\n}\r\n\r\nfunction scrollLeft(element: HTMLElement, accumulator = 0) {\r\n const left = accumulator + element.scrollLeft\r\n if (element.offsetParent) {\r\n return scrollLeft(element.offsetParent as HTMLElement, left)\r\n }\r\n return left + window.scrollX\r\n}\r\n\r\nexport type SnapElementOptions = {\r\n align?: string[]\r\n ignoreSticky?: boolean\r\n ignoreTransform?: boolean\r\n}\r\n\r\ntype Rect = {\r\n top: number\r\n left: number\r\n width: number\r\n height: number\r\n x: number\r\n y: number\r\n bottom: number\r\n right: number\r\n element: HTMLElement\r\n}\r\n\r\nexport class SnapElement {\r\n element: HTMLElement\r\n options: SnapElementOptions\r\n align: string[]\r\n // @ts-ignore\r\n rect: Rect = {}\r\n wrapperResizeObserver: ResizeObserver\r\n resizeObserver: ResizeObserver\r\n\r\n constructor(\r\n element: HTMLElement,\r\n {\r\n align = ['start'],\r\n ignoreSticky = true,\r\n ignoreTransform = false,\r\n }: SnapElementOptions = {}\r\n ) {\r\n this.element = element\r\n\r\n this.options = { align, ignoreSticky, ignoreTransform }\r\n\r\n // this.ignoreSticky = ignoreSticky\r\n // this.ignoreTransform = ignoreTransform\r\n\r\n this.align = [align].flat()\r\n\r\n // TODO: assing rect immediately\r\n\r\n this.wrapperResizeObserver = new ResizeObserver(this.onWrapperResize)\r\n this.wrapperResizeObserver.observe(document.body)\r\n this.onWrapperResize()\r\n\r\n this.resizeObserver = new ResizeObserver(this.onResize)\r\n this.resizeObserver.observe(this.element)\r\n this.setRect({\r\n width: this.element.offsetWidth,\r\n height: this.element.offsetHeight,\r\n })\r\n }\r\n\r\n destroy() {\r\n this.wrapperResizeObserver.disconnect()\r\n this.resizeObserver.disconnect()\r\n }\r\n\r\n setRect({\r\n top,\r\n left,\r\n width,\r\n height,\r\n element,\r\n }: {\r\n top?: number\r\n left?: number\r\n width?: number\r\n height?: number\r\n element?: HTMLElement\r\n } = {}) {\r\n top = top ?? this.rect.top\r\n left = left ?? this.rect.left\r\n width = width ?? this.rect.width\r\n height = height ?? this.rect.height\r\n element = element ?? this.rect.element\r\n\r\n if (\r\n top === this.rect.top &&\r\n left === this.rect.left &&\r\n width === this.rect.width &&\r\n height === this.rect.height &&\r\n element === this.rect.element\r\n )\r\n return\r\n\r\n this.rect.top = top\r\n this.rect.y = top\r\n this.rect.width = width\r\n this.rect.height = height\r\n this.rect.left = left\r\n this.rect.x = left\r\n this.rect.bottom = top + height\r\n this.rect.right = left + width\r\n }\r\n\r\n onWrapperResize = () => {\r\n let top, left\r\n\r\n if (this.options.ignoreSticky) removeParentSticky(this.element)\r\n if (this.options.ignoreTransform) {\r\n top = offsetTop(this.element)\r\n left = offsetLeft(this.element)\r\n } else {\r\n const rect = this.element.getBoundingClientRect()\r\n top = rect.top + scrollTop(this.element)\r\n left = rect.left + scrollLeft(this.element)\r\n }\r\n if (this.options.ignoreSticky) addParentSticky(this.element)\r\n\r\n this.setRect({ top, left })\r\n }\r\n\r\n onResize = ([entry]: ResizeObserverEntry[]) => {\r\n const width = entry.borderBoxSize[0].inlineSize\r\n const height = entry.borderBoxSize[0].blockSize\r\n\r\n this.setRect({ width, height })\r\n }\r\n}\r\n","let index = 0\r\n\r\nexport type UID = number\r\n\r\nexport function uid(): UID {\r\n return index++\r\n}\r\n","import Lenis from 'lenis'\r\nimport { SnapElement, SnapElementOptions } from './element'\r\nimport { UID, uid } from './uid'\r\n\r\n// TODO:\r\n// - horizontal\r\n// - fix trackpad snapping too soon due to velocity (fuck Apple)\r\n// - fix wheel scrolling after limits (see console scroll to)\r\n// - fix touch scroll, do not snap when not released\r\n// - arrow, spacebar\r\n\r\ntype Viewport = {\r\n width: number\r\n height: number\r\n}\r\n\r\nexport type SnapOptions = {\r\n type?: 'mandatory' | 'proximity'\r\n lerp?: number\r\n easing?: (t: number) => number\r\n duration?: number\r\n velocityThreshold?: number\r\n onSnapStart?: (t: number) => number\r\n onSnapComplete?: (t: number) => number\r\n}\r\n\r\nexport default class Snap {\r\n lenis: Lenis\r\n options: SnapOptions\r\n elements: Map<UID, SnapElement>\r\n snaps: Map<UID, number>\r\n viewport: Viewport\r\n isStopped: Boolean = false\r\n\r\n constructor(\r\n lenis: Lenis,\r\n {\r\n type = 'mandatory',\r\n lerp,\r\n easing,\r\n duration,\r\n velocityThreshold = 1,\r\n onSnapStart,\r\n onSnapComplete,\r\n }: SnapOptions = {}\r\n ) {\r\n this.lenis = lenis\r\n\r\n this.options = {\r\n type,\r\n lerp,\r\n easing,\r\n duration,\r\n velocityThreshold,\r\n onSnapStart,\r\n onSnapComplete,\r\n }\r\n\r\n this.elements = new Map()\r\n this.snaps = new Map()\r\n\r\n this.viewport = {\r\n width: window.innerWidth,\r\n height: window.innerHeight,\r\n }\r\n this.onWindowResize()\r\n window.addEventListener('resize', this.onWindowResize)\r\n\r\n this.lenis.on('scroll', this.onScroll)\r\n }\r\n\r\n // debug() {\r\n // const element = document.createElement('div')\r\n // element.style.cssText = `\r\n // position: fixed;\r\n // background: red;\r\n // border-bottom: 1px solid red;\r\n // left: 0;\r\n // right: 0;\r\n // top: 0;\r\n // z-index: 9999;\r\n // `\r\n // document.body.appendChild(element)\r\n // }\r\n\r\n destroy() {\r\n this.lenis.off('scroll', this.onScroll)\r\n window.removeEventListener('resize', this.onWindowResize)\r\n this.elements.forEach((element) => element.destroy())\r\n }\r\n\r\n start() {\r\n this.isStopped = false\r\n }\r\n\r\n stop() {\r\n this.isStopped = true\r\n }\r\n\r\n add(value: number) {\r\n const id = uid()\r\n\r\n this.snaps.set(id, value)\r\n\r\n return () => this.remove(id)\r\n }\r\n\r\n remove(id: UID) {\r\n this.snaps.delete(id)\r\n }\r\n\r\n addElement(element: HTMLElement, options = {} as SnapElementOptions) {\r\n const id = uid()\r\n\r\n this.elements.set(id, new SnapElement(element, options))\r\n\r\n return () => this.removeElement(id)\r\n }\r\n\r\n removeElement(id: UID) {\r\n this.elements.delete(id)\r\n }\r\n\r\n onWindowResize = () => {\r\n this.viewport.width = window.innerWidth\r\n this.viewport.height = window.innerHeight\r\n }\r\n\r\n onScroll = ({\r\n scroll,\r\n limit,\r\n lastVelocity,\r\n velocity,\r\n isScrolling,\r\n userData,\r\n isHorizontal,\r\n }) => {\r\n if (this.isStopped) return\r\n // console.log(scroll, velocity, type)\r\n\r\n // return\r\n const isDecelerating = Math.abs(lastVelocity) > Math.abs(velocity)\r\n const isTurningBack =\r\n Math.sign(lastVelocity) !== Math.sign(velocity) && velocity !== 0\r\n\r\n // console.log({ lastVelocity, velocity, isTurningBack, isDecelerating })\r\n\r\n // console.log('onScroll')\r\n\r\n if (\r\n Math.abs(velocity) < this.options.velocityThreshold &&\r\n // !isTouching &&\r\n isDecelerating &&\r\n !isTurningBack &&\r\n userData?.initiator !== 'snap'\r\n ) {\r\n scroll = Math.ceil(scroll)\r\n\r\n let snaps = [...this.snaps.values()] as number[]\r\n\r\n this.elements.forEach(({ rect, align }) => {\r\n let snap: number | undefined\r\n\r\n align.forEach((align) => {\r\n if (align === 'start') {\r\n snap = rect.top\r\n } else if (align === 'center') {\r\n snap = isHorizontal\r\n ? rect.left + rect.width / 2 - this.viewport.width / 2\r\n : rect.top + rect.height / 2 - this.viewport.height / 2\r\n } else if (align === 'end') {\r\n snap = isHorizontal\r\n ? rect.left + rect.width - this.viewport.width\r\n : rect.top + rect.height - this.viewport.height\r\n }\r\n\r\n if (snap !== undefined) {\r\n snaps.push(Math.ceil(snap))\r\n }\r\n })\r\n })\r\n\r\n snaps = snaps.sort((a, b) => Math.abs(a) - Math.abs(b))\r\n\r\n let prevSnap = snaps.findLast((snap) => snap <= scroll)\r\n if (prevSnap === undefined) prevSnap = snaps[0]\r\n const distanceToPrevSnap = Math.abs(scroll - prevSnap)\r\n\r\n let nextSnap = snaps.find((snap) => snap >= scroll)\r\n if (nextSnap === undefined) nextSnap = snaps[snaps.length - 1]\r\n const distanceToNextSnap = Math.abs(scroll - nextSnap)\r\n\r\n const snap = distanceToPrevSnap < distanceToNextSnap ? prevSnap : nextSnap\r\n\r\n const distance = Math.abs(scroll - snap)\r\n\r\n if (\r\n this.options.type === 'mandatory' ||\r\n (this.options.type === 'proximity' && distance <= this.viewport.height)\r\n ) {\r\n // this.__isScrolling = true\r\n // this.onSnapStart?.(snap)\r\n\r\n // console.log('scroll to')\r\n\r\n this.lenis.scrollTo(snap, {\r\n lerp: this.options.lerp,\r\n easing: this.options.easing,\r\n duration: this.options.duration,\r\n userData: { initiator: 'snap' },\r\n onStart: () => {\r\n this.options.onSnapStart?.(snap)\r\n },\r\n onComplete: () => {\r\n this.options.onSnapComplete?.(snap)\r\n },\r\n })\r\n }\r\n\r\n // console.timeEnd('scroll')\r\n }\r\n }\r\n}\r\n"],"names":["removeParentSticky","element","getComputedStyle","position","style","setProperty","dataset","sticky","offsetParent","addParentSticky","_a","removeProperty","offsetTop","accumulator","top","offsetLeft","left","scrollTop","window","scrollY","scrollLeft","scrollX","SnapElement","constructor","align","ignoreSticky","ignoreTransform","this","rect","onWrapperResize","options","getBoundingClientRect","setRect","onResize","entry","width","borderBoxSize","inlineSize","height","blockSize","flat","wrapperResizeObserver","ResizeObserver","observe","document","body","resizeObserver","offsetWidth","offsetHeight","destroy","disconnect","y","x","bottom","right","index","uid","Snap","lenis","type","lerp","easing","duration","velocityThreshold","onSnapStart","onSnapComplete","isStopped","onWindowResize","viewport","innerWidth","innerHeight","onScroll","scroll","limit","lastVelocity","velocity","isScrolling","userData","isHorizontal","isDecelerating","Math","abs","isTurningBack","sign","initiator","ceil","snaps","values","elements","forEach","snap","undefined","push","sort","a","b","prevSnap","findLast","distanceToPrevSnap","nextSnap","find","length","distance","scrollTo","onStart","_b","call","onComplete","Map","addEventListener","on","off","removeEventListener","start","stop","add","value","id","set","remove","delete","addElement","removeElement"],"mappings":"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"}
package/dist/lenis.js CHANGED
@@ -4,7 +4,7 @@
4
4
  (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.Lenis = factory());
5
5
  })(this, (function () { 'use strict';
6
6
 
7
- var version = "1.1.4";
7
+ var version = "1.1.5";
8
8
 
9
9
  // Clamp a value between a minimum and maximum value
10
10
  function clamp(min, input, max) {
package/dist/lenis.min.js CHANGED
@@ -1,2 +1,2 @@
1
- !function(t,e){"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()}(this,(function(){"use strict";function clamp(t,e,i){return Math.max(t,Math.min(e,i))}class Animate{advance(t){if(!this.isRunning)return;let e=!1;if(this.duration&&this.easing){this.currentTime+=t;const i=clamp(0,this.currentTime/this.duration,1);e=i>=1;const s=e?1:this.easing(i);this.value=this.from+(this.to-this.from)*s}else this.lerp?(this.value=function damp(t,e,i,s){return function lerp(t,e,i){return(1-i)*t+i*e}(t,e,1-Math.exp(-i*s))}(this.value,this.to,60*this.lerp,t),Math.round(this.value)===this.to&&(this.value=this.to,e=!0)):(this.value=this.to,e=!0);e&&this.stop(),this.onUpdate?.(this.value,e)}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}}class Dimensions{constructor({wrapper:t,content:e,autoResize:i=!0,debounce:s=250}={}){this.wrapper=t,this.content=e,i&&(this.debouncedResize=function debounce(t,e){let i;return function(){let s=arguments,o=this;clearTimeout(i),i=setTimeout((function(){t.apply(o,s)}),e)}}(this.resize,s),this.wrapper===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()}destroy(){this.wrapperResizeObserver?.disconnect(),this.contentResizeObserver?.disconnect(),window.removeEventListener("resize",this.debouncedResize,!1)}resize=()=>{this.onWrapperResize(),this.onContentResize()};onWrapperResize=()=>{this.wrapper===window?(this.width=window.innerWidth,this.height=window.innerHeight):(this.width=this.wrapper.clientWidth,this.height=this.wrapper.clientHeight)};onContentResize=()=>{this.wrapper===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}}}class Emitter{constructor(){this.events={}}emit(t,...e){let i=this.events[t]||[];for(let t=0,s=i.length;t<s;t++)i[t](...e)}on(t,e){return this.events[t]?.push(e)||(this.events[t]=[e]),()=>{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={}}}const t=100/6;class VirtualScroll{constructor(t,{wheelMultiplier:e=1,touchMultiplier:i=1}){this.element=t,this.wheelMultiplier=e,this.touchMultiplier=i,this.touchStart={x:null,y:null},this.emitter=new Emitter,window.addEventListener("resize",this.onWindowResize,!1),this.onWindowResize(),this.element.addEventListener("wheel",this.onWheel,{passive:!1}),this.element.addEventListener("touchstart",this.onTouchStart,{passive:!1}),this.element.addEventListener("touchmove",this.onTouchMove,{passive:!1}),this.element.addEventListener("touchend",this.onTouchEnd,{passive:!1})}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,{passive:!1}),this.element.removeEventListener("touchstart",this.onTouchStart,{passive:!1}),this.element.removeEventListener("touchmove",this.onTouchMove,{passive:!1}),this.element.removeEventListener("touchend",this.onTouchEnd,{passive:!1})}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.touchMultiplier,o=-(i-this.touchStart.y)*this.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=e=>{let{deltaX:i,deltaY:s,deltaMode:o}=e;i*=1===o?t:2===o?this.windowWidth:1,s*=1===o?t:2===o?this.windowHeight:1,i*=this.wheelMultiplier,s*=this.wheelMultiplier,this.emitter.emit("scroll",{deltaX:i,deltaY:s,event:e})};onWindowResize=()=>{this.windowWidth=window.innerWidth,this.windowHeight=window.innerHeight}}return class Lenis{constructor({wrapper:t=window,content:e=document.documentElement,wheelEventsTarget:i=t,eventsTarget:s=i,smoothWheel:o=!0,syncTouch:n=!1,syncTouchLerp:r=.075,touchInertiaMultiplier:l=35,duration:h,easing:a=(t=>Math.min(1,1.001-Math.pow(2,-10*t))),lerp:c=.1,infinite:d=!1,orientation:p="vertical",gestureOrientation:u="vertical",touchMultiplier:m=1,wheelMultiplier:v=1,autoResize:g=!0,prevent:w=!1,__experimental__naiveDimensions:S=!1}={}){this.__isScrolling=!1,this.__isStopped=!1,this.__isLocked=!1,this.direction=0,this.onPointerDown=t=>{1===t.button&&this.reset()},this.onVirtualScroll=({deltaX:t,deltaY:e,event:i})=>{if(i.ctrlKey)return;const s=i.type.includes("touch"),o=i.type.includes("wheel");this.isTouching="touchstart"===i.type||"touchmove"===i.type;if(this.options.syncTouch&&s&&"touchstart"===i.type&&!this.isStopped&&!this.isLocked)return void this.reset();const n=0===t&&0===e,r="vertical"===this.options.gestureOrientation&&0===e||"horizontal"===this.options.gestureOrientation&&0===t;if(n||r)return;let l=i.composedPath();l=l.slice(0,l.indexOf(this.rootElement));const h=this.options.prevent;if(l.find((t=>{var e,i,n,r,l;return t instanceof Element&&(("function"==typeof h?null==h?void 0:h(t):h)||(null===(e=t.hasAttribute)||void 0===e?void 0:e.call(t,"data-lenis-prevent"))||s&&(null===(i=t.hasAttribute)||void 0===i?void 0:i.call(t,"data-lenis-prevent-touch"))||o&&(null===(n=t.hasAttribute)||void 0===n?void 0:n.call(t,"data-lenis-prevent-wheel"))||(null===(r=t.classList)||void 0===r?void 0:r.contains("lenis"))&&!(null===(l=t.classList)||void 0===l?void 0:l.contains("lenis-stopped")))})))return;if(this.isStopped||this.isLocked)return void i.preventDefault();if(!(this.options.syncTouch&&s||this.options.smoothWheel&&o))return this.isScrolling="native",void this.animate.stop();i.preventDefault();let a=e;"both"===this.options.gestureOrientation?a=Math.abs(e)>Math.abs(t)?e:t:"horizontal"===this.options.gestureOrientation&&(a=t);const c=s&&this.options.syncTouch,d=s&&"touchend"===i.type&&Math.abs(a)>5;d&&(a=this.velocity*this.options.touchInertiaMultiplier),this.scrollTo(this.targetScroll+a,Object.assign({programmatic:!1},c?{lerp:d?this.options.syncTouchLerp:1}:{lerp:this.options.lerp,duration:this.options.duration,easing:this.options.easing}))},this.onNativeScroll=()=>{if(clearTimeout(this.__resetVelocityTimeout),delete this.__resetVelocityTimeout,this.__preventNextNativeScrollEvent)delete this.__preventNextNativeScrollEvent;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.isScrolling="native",this.emit(),0!==this.velocity&&(this.__resetVelocityTimeout=setTimeout((()=>{this.lastVelocity=this.velocity,this.velocity=0,this.isScrolling=!1,this.emit()}),400))}},window.lenisVersion="1.1.4",t&&t!==document.documentElement&&t!==document.body||(t=window),this.options={wrapper:t,content:e,wheelEventsTarget:i,eventsTarget:s,smoothWheel:o,syncTouch:n,syncTouchLerp:r,touchInertiaMultiplier:l,duration:h,easing:a,lerp:c,infinite:d,gestureOrientation:u,orientation:p,touchMultiplier:m,wheelMultiplier:v,autoResize:g,prevent:w,__experimental__naiveDimensions:S},this.animate=new Animate,this.emitter=new Emitter,this.dimensions=new Dimensions({wrapper:t,content:e,autoResize:g}),this.updateClassName(),this.userData={},this.time=0,this.velocity=this.lastVelocity=0,this.isLocked=!1,this.isStopped=!1,this.isScrolling=!1,this.targetScroll=this.animatedScroll=this.actualScroll,this.options.wrapper.addEventListener("scroll",this.onNativeScroll,!1),this.options.wrapper.addEventListener("pointerdown",this.onPointerDown,!1),this.virtualScroll=new VirtualScroll(s,{touchMultiplier:m,wheelMultiplier:v}),this.virtualScroll.on("scroll",this.onVirtualScroll)}destroy(){this.emitter.destroy(),this.options.wrapper.removeEventListener("scroll",this.onNativeScroll,!1),this.options.wrapper.removeEventListener("pointerdown",this.onPointerDown,!1),this.virtualScroll.destroy(),this.dimensions.destroy(),this.cleanUpClassName()}on(t,e){return this.emitter.on(t,e)}off(t,e){return this.emitter.off(t,e)}setScroll(t){this.isHorizontal?this.rootElement.scrollLeft=t:this.rootElement.scrollTop=t}resize(){this.dimensions.resize()}emit(){this.emitter.emit("scroll",this)}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.isStopped=!1,this.reset())}stop(){this.isStopped||(this.isStopped=!0,this.animate.stop(),this.reset())}raf(t){const e=t-(this.time||t);this.time=t,this.animate.advance(.001*e)}scrollTo(t,{offset:e=0,immediate:i=!1,lock:s=!1,duration:o=this.options.duration,easing:n=this.options.easing,lerp:r=this.options.lerp,onStart:l,onComplete:h,force:a=!1,programmatic:c=!0,userData:d={}}={}){if(!this.isStopped&&!this.isLocked||a){if("string"==typeof t&&["top","left","start"].includes(t))t=0;else if("string"==typeof t&&["bottom","right","end"].includes(t))t=this.limit;else{let i;if("string"==typeof t?i=document.querySelector(t):t instanceof HTMLElement&&(null==t?void 0:t.nodeType)&&(i=t),i){if(this.options.wrapper!==window){const t=this.rootElement.getBoundingClientRect();e-=this.isHorizontal?t.left:t.top}const s=i.getBoundingClientRect();t=(this.isHorizontal?s.left:s.top)+this.animatedScroll}}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)){if(this.userData=d,i)return this.animatedScroll=this.targetScroll=t,this.setScroll(this.scroll),this.reset(),this.preventNextNativeScrollEvent(),this.emit(),null==h||h(this),void(this.userData={});c||(this.targetScroll=t),this.animate.fromTo(this.animatedScroll,t,{duration:o,easing:n,lerp:r,onStart:()=>{s&&(this.isLocked=!0),this.isScrolling="smooth",null==l||l(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),c&&(this.targetScroll=t),e||this.emit(),e&&(this.reset(),this.emit(),null==h||h(this),this.userData={},this.preventNextNativeScrollEvent())}})}}}preventNextNativeScrollEvent(){this.__preventNextNativeScrollEvent=!0,requestAnimationFrame((()=>{delete this.__preventNextNativeScrollEvent}))}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(){return this.isHorizontal?this.rootElement.scrollLeft:this.rootElement.scrollTop}get scroll(){return this.options.infinite?function modulo(t,e){return(t%e+e)%e}(this.animatedScroll,this.limit):this.animatedScroll}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.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()}}}));
1
+ !function(t,e){"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()}(this,(function(){"use strict";function clamp(t,e,i){return Math.max(t,Math.min(e,i))}class Animate{advance(t){if(!this.isRunning)return;let e=!1;if(this.duration&&this.easing){this.currentTime+=t;const i=clamp(0,this.currentTime/this.duration,1);e=i>=1;const s=e?1:this.easing(i);this.value=this.from+(this.to-this.from)*s}else this.lerp?(this.value=function damp(t,e,i,s){return function lerp(t,e,i){return(1-i)*t+i*e}(t,e,1-Math.exp(-i*s))}(this.value,this.to,60*this.lerp,t),Math.round(this.value)===this.to&&(this.value=this.to,e=!0)):(this.value=this.to,e=!0);e&&this.stop(),this.onUpdate?.(this.value,e)}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}}class Dimensions{constructor({wrapper:t,content:e,autoResize:i=!0,debounce:s=250}={}){this.wrapper=t,this.content=e,i&&(this.debouncedResize=function debounce(t,e){let i;return function(){let s=arguments,o=this;clearTimeout(i),i=setTimeout((function(){t.apply(o,s)}),e)}}(this.resize,s),this.wrapper===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()}destroy(){this.wrapperResizeObserver?.disconnect(),this.contentResizeObserver?.disconnect(),window.removeEventListener("resize",this.debouncedResize,!1)}resize=()=>{this.onWrapperResize(),this.onContentResize()};onWrapperResize=()=>{this.wrapper===window?(this.width=window.innerWidth,this.height=window.innerHeight):(this.width=this.wrapper.clientWidth,this.height=this.wrapper.clientHeight)};onContentResize=()=>{this.wrapper===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}}}class Emitter{constructor(){this.events={}}emit(t,...e){let i=this.events[t]||[];for(let t=0,s=i.length;t<s;t++)i[t](...e)}on(t,e){return this.events[t]?.push(e)||(this.events[t]=[e]),()=>{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={}}}const t=100/6;class VirtualScroll{constructor(t,{wheelMultiplier:e=1,touchMultiplier:i=1}){this.element=t,this.wheelMultiplier=e,this.touchMultiplier=i,this.touchStart={x:null,y:null},this.emitter=new Emitter,window.addEventListener("resize",this.onWindowResize,!1),this.onWindowResize(),this.element.addEventListener("wheel",this.onWheel,{passive:!1}),this.element.addEventListener("touchstart",this.onTouchStart,{passive:!1}),this.element.addEventListener("touchmove",this.onTouchMove,{passive:!1}),this.element.addEventListener("touchend",this.onTouchEnd,{passive:!1})}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,{passive:!1}),this.element.removeEventListener("touchstart",this.onTouchStart,{passive:!1}),this.element.removeEventListener("touchmove",this.onTouchMove,{passive:!1}),this.element.removeEventListener("touchend",this.onTouchEnd,{passive:!1})}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.touchMultiplier,o=-(i-this.touchStart.y)*this.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=e=>{let{deltaX:i,deltaY:s,deltaMode:o}=e;i*=1===o?t:2===o?this.windowWidth:1,s*=1===o?t:2===o?this.windowHeight:1,i*=this.wheelMultiplier,s*=this.wheelMultiplier,this.emitter.emit("scroll",{deltaX:i,deltaY:s,event:e})};onWindowResize=()=>{this.windowWidth=window.innerWidth,this.windowHeight=window.innerHeight}}return class Lenis{constructor({wrapper:t=window,content:e=document.documentElement,wheelEventsTarget:i=t,eventsTarget:s=i,smoothWheel:o=!0,syncTouch:n=!1,syncTouchLerp:r=.075,touchInertiaMultiplier:l=35,duration:h,easing:a=(t=>Math.min(1,1.001-Math.pow(2,-10*t))),lerp:c=.1,infinite:d=!1,orientation:p="vertical",gestureOrientation:u="vertical",touchMultiplier:m=1,wheelMultiplier:v=1,autoResize:g=!0,prevent:w=!1,__experimental__naiveDimensions:S=!1}={}){this.__isScrolling=!1,this.__isStopped=!1,this.__isLocked=!1,this.direction=0,this.onPointerDown=t=>{1===t.button&&this.reset()},this.onVirtualScroll=({deltaX:t,deltaY:e,event:i})=>{if(i.ctrlKey)return;const s=i.type.includes("touch"),o=i.type.includes("wheel");this.isTouching="touchstart"===i.type||"touchmove"===i.type;if(this.options.syncTouch&&s&&"touchstart"===i.type&&!this.isStopped&&!this.isLocked)return void this.reset();const n=0===t&&0===e,r="vertical"===this.options.gestureOrientation&&0===e||"horizontal"===this.options.gestureOrientation&&0===t;if(n||r)return;let l=i.composedPath();l=l.slice(0,l.indexOf(this.rootElement));const h=this.options.prevent;if(l.find((t=>{var e,i,n,r,l;return t instanceof Element&&(("function"==typeof h?null==h?void 0:h(t):h)||(null===(e=t.hasAttribute)||void 0===e?void 0:e.call(t,"data-lenis-prevent"))||s&&(null===(i=t.hasAttribute)||void 0===i?void 0:i.call(t,"data-lenis-prevent-touch"))||o&&(null===(n=t.hasAttribute)||void 0===n?void 0:n.call(t,"data-lenis-prevent-wheel"))||(null===(r=t.classList)||void 0===r?void 0:r.contains("lenis"))&&!(null===(l=t.classList)||void 0===l?void 0:l.contains("lenis-stopped")))})))return;if(this.isStopped||this.isLocked)return void i.preventDefault();if(!(this.options.syncTouch&&s||this.options.smoothWheel&&o))return this.isScrolling="native",void this.animate.stop();i.preventDefault();let a=e;"both"===this.options.gestureOrientation?a=Math.abs(e)>Math.abs(t)?e:t:"horizontal"===this.options.gestureOrientation&&(a=t);const c=s&&this.options.syncTouch,d=s&&"touchend"===i.type&&Math.abs(a)>5;d&&(a=this.velocity*this.options.touchInertiaMultiplier),this.scrollTo(this.targetScroll+a,Object.assign({programmatic:!1},c?{lerp:d?this.options.syncTouchLerp:1}:{lerp:this.options.lerp,duration:this.options.duration,easing:this.options.easing}))},this.onNativeScroll=()=>{if(clearTimeout(this.__resetVelocityTimeout),delete this.__resetVelocityTimeout,this.__preventNextNativeScrollEvent)delete this.__preventNextNativeScrollEvent;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.isScrolling="native",this.emit(),0!==this.velocity&&(this.__resetVelocityTimeout=setTimeout((()=>{this.lastVelocity=this.velocity,this.velocity=0,this.isScrolling=!1,this.emit()}),400))}},window.lenisVersion="1.1.5",t&&t!==document.documentElement&&t!==document.body||(t=window),this.options={wrapper:t,content:e,wheelEventsTarget:i,eventsTarget:s,smoothWheel:o,syncTouch:n,syncTouchLerp:r,touchInertiaMultiplier:l,duration:h,easing:a,lerp:c,infinite:d,gestureOrientation:u,orientation:p,touchMultiplier:m,wheelMultiplier:v,autoResize:g,prevent:w,__experimental__naiveDimensions:S},this.animate=new Animate,this.emitter=new Emitter,this.dimensions=new Dimensions({wrapper:t,content:e,autoResize:g}),this.updateClassName(),this.userData={},this.time=0,this.velocity=this.lastVelocity=0,this.isLocked=!1,this.isStopped=!1,this.isScrolling=!1,this.targetScroll=this.animatedScroll=this.actualScroll,this.options.wrapper.addEventListener("scroll",this.onNativeScroll,!1),this.options.wrapper.addEventListener("pointerdown",this.onPointerDown,!1),this.virtualScroll=new VirtualScroll(s,{touchMultiplier:m,wheelMultiplier:v}),this.virtualScroll.on("scroll",this.onVirtualScroll)}destroy(){this.emitter.destroy(),this.options.wrapper.removeEventListener("scroll",this.onNativeScroll,!1),this.options.wrapper.removeEventListener("pointerdown",this.onPointerDown,!1),this.virtualScroll.destroy(),this.dimensions.destroy(),this.cleanUpClassName()}on(t,e){return this.emitter.on(t,e)}off(t,e){return this.emitter.off(t,e)}setScroll(t){this.isHorizontal?this.rootElement.scrollLeft=t:this.rootElement.scrollTop=t}resize(){this.dimensions.resize()}emit(){this.emitter.emit("scroll",this)}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.isStopped=!1,this.reset())}stop(){this.isStopped||(this.isStopped=!0,this.animate.stop(),this.reset())}raf(t){const e=t-(this.time||t);this.time=t,this.animate.advance(.001*e)}scrollTo(t,{offset:e=0,immediate:i=!1,lock:s=!1,duration:o=this.options.duration,easing:n=this.options.easing,lerp:r=this.options.lerp,onStart:l,onComplete:h,force:a=!1,programmatic:c=!0,userData:d={}}={}){if(!this.isStopped&&!this.isLocked||a){if("string"==typeof t&&["top","left","start"].includes(t))t=0;else if("string"==typeof t&&["bottom","right","end"].includes(t))t=this.limit;else{let i;if("string"==typeof t?i=document.querySelector(t):t instanceof HTMLElement&&(null==t?void 0:t.nodeType)&&(i=t),i){if(this.options.wrapper!==window){const t=this.rootElement.getBoundingClientRect();e-=this.isHorizontal?t.left:t.top}const s=i.getBoundingClientRect();t=(this.isHorizontal?s.left:s.top)+this.animatedScroll}}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)){if(this.userData=d,i)return this.animatedScroll=this.targetScroll=t,this.setScroll(this.scroll),this.reset(),this.preventNextNativeScrollEvent(),this.emit(),null==h||h(this),void(this.userData={});c||(this.targetScroll=t),this.animate.fromTo(this.animatedScroll,t,{duration:o,easing:n,lerp:r,onStart:()=>{s&&(this.isLocked=!0),this.isScrolling="smooth",null==l||l(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),c&&(this.targetScroll=t),e||this.emit(),e&&(this.reset(),this.emit(),null==h||h(this),this.userData={},this.preventNextNativeScrollEvent())}})}}}preventNextNativeScrollEvent(){this.__preventNextNativeScrollEvent=!0,requestAnimationFrame((()=>{delete this.__preventNextNativeScrollEvent}))}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(){return this.isHorizontal?this.rootElement.scrollLeft:this.rootElement.scrollTop}get scroll(){return this.options.infinite?function modulo(t,e){return(t%e+e)%e}(this.animatedScroll,this.limit):this.animatedScroll}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.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()}}}));
2
2
  //# sourceMappingURL=lenis.min.js.map
package/dist/lenis.mjs CHANGED
@@ -1,2 +1,2 @@
1
- function clamp(t,e,i){return Math.max(t,Math.min(e,i))}class Animate{advance(t){if(!this.isRunning)return;let e=!1;if(this.duration&&this.easing){this.currentTime+=t;const i=clamp(0,this.currentTime/this.duration,1);e=i>=1;const s=e?1:this.easing(i);this.value=this.from+(this.to-this.from)*s}else this.lerp?(this.value=function damp(t,e,i,s){return function lerp(t,e,i){return(1-i)*t+i*e}(t,e,1-Math.exp(-i*s))}(this.value,this.to,60*this.lerp,t),Math.round(this.value)===this.to&&(this.value=this.to,e=!0)):(this.value=this.to,e=!0);e&&this.stop(),this.onUpdate?.(this.value,e)}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}}class Dimensions{constructor({wrapper:t,content:e,autoResize:i=!0,debounce:s=250}={}){this.wrapper=t,this.content=e,i&&(this.debouncedResize=function debounce(t,e){let i;return function(){let s=arguments,o=this;clearTimeout(i),i=setTimeout((function(){t.apply(o,s)}),e)}}(this.resize,s),this.wrapper===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()}destroy(){this.wrapperResizeObserver?.disconnect(),this.contentResizeObserver?.disconnect(),window.removeEventListener("resize",this.debouncedResize,!1)}resize=()=>{this.onWrapperResize(),this.onContentResize()};onWrapperResize=()=>{this.wrapper===window?(this.width=window.innerWidth,this.height=window.innerHeight):(this.width=this.wrapper.clientWidth,this.height=this.wrapper.clientHeight)};onContentResize=()=>{this.wrapper===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}}}class Emitter{constructor(){this.events={}}emit(t,...e){let i=this.events[t]||[];for(let t=0,s=i.length;t<s;t++)i[t](...e)}on(t,e){return this.events[t]?.push(e)||(this.events[t]=[e]),()=>{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={}}}const t=100/6;class VirtualScroll{constructor(t,{wheelMultiplier:e=1,touchMultiplier:i=1}){this.element=t,this.wheelMultiplier=e,this.touchMultiplier=i,this.touchStart={x:null,y:null},this.emitter=new Emitter,window.addEventListener("resize",this.onWindowResize,!1),this.onWindowResize(),this.element.addEventListener("wheel",this.onWheel,{passive:!1}),this.element.addEventListener("touchstart",this.onTouchStart,{passive:!1}),this.element.addEventListener("touchmove",this.onTouchMove,{passive:!1}),this.element.addEventListener("touchend",this.onTouchEnd,{passive:!1})}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,{passive:!1}),this.element.removeEventListener("touchstart",this.onTouchStart,{passive:!1}),this.element.removeEventListener("touchmove",this.onTouchMove,{passive:!1}),this.element.removeEventListener("touchend",this.onTouchEnd,{passive:!1})}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.touchMultiplier,o=-(i-this.touchStart.y)*this.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=e=>{let{deltaX:i,deltaY:s,deltaMode:o}=e;i*=1===o?t:2===o?this.windowWidth:1,s*=1===o?t:2===o?this.windowHeight:1,i*=this.wheelMultiplier,s*=this.wheelMultiplier,this.emitter.emit("scroll",{deltaX:i,deltaY:s,event:e})};onWindowResize=()=>{this.windowWidth=window.innerWidth,this.windowHeight=window.innerHeight}}class Lenis{constructor({wrapper:t=window,content:e=document.documentElement,wheelEventsTarget:i=t,eventsTarget:s=i,smoothWheel:o=!0,syncTouch:n=!1,syncTouchLerp:r=.075,touchInertiaMultiplier:l=35,duration:h,easing:a=(t=>Math.min(1,1.001-Math.pow(2,-10*t))),lerp:c=.1,infinite:p=!1,orientation:d="vertical",gestureOrientation:u="vertical",touchMultiplier:m=1,wheelMultiplier:v=1,autoResize:g=!0,prevent:w=!1,__experimental__naiveDimensions:S=!1}={}){this.__isScrolling=!1,this.__isStopped=!1,this.__isLocked=!1,this.direction=0,this.onPointerDown=t=>{1===t.button&&this.reset()},this.onVirtualScroll=({deltaX:t,deltaY:e,event:i})=>{if(i.ctrlKey)return;const s=i.type.includes("touch"),o=i.type.includes("wheel");this.isTouching="touchstart"===i.type||"touchmove"===i.type;if(this.options.syncTouch&&s&&"touchstart"===i.type&&!this.isStopped&&!this.isLocked)return void this.reset();const n=0===t&&0===e,r="vertical"===this.options.gestureOrientation&&0===e||"horizontal"===this.options.gestureOrientation&&0===t;if(n||r)return;let l=i.composedPath();l=l.slice(0,l.indexOf(this.rootElement));const h=this.options.prevent;if(l.find((t=>{var e,i,n,r,l;return t instanceof Element&&(("function"==typeof h?null==h?void 0:h(t):h)||(null===(e=t.hasAttribute)||void 0===e?void 0:e.call(t,"data-lenis-prevent"))||s&&(null===(i=t.hasAttribute)||void 0===i?void 0:i.call(t,"data-lenis-prevent-touch"))||o&&(null===(n=t.hasAttribute)||void 0===n?void 0:n.call(t,"data-lenis-prevent-wheel"))||(null===(r=t.classList)||void 0===r?void 0:r.contains("lenis"))&&!(null===(l=t.classList)||void 0===l?void 0:l.contains("lenis-stopped")))})))return;if(this.isStopped||this.isLocked)return void i.preventDefault();if(!(this.options.syncTouch&&s||this.options.smoothWheel&&o))return this.isScrolling="native",void this.animate.stop();i.preventDefault();let a=e;"both"===this.options.gestureOrientation?a=Math.abs(e)>Math.abs(t)?e:t:"horizontal"===this.options.gestureOrientation&&(a=t);const c=s&&this.options.syncTouch,p=s&&"touchend"===i.type&&Math.abs(a)>5;p&&(a=this.velocity*this.options.touchInertiaMultiplier),this.scrollTo(this.targetScroll+a,Object.assign({programmatic:!1},c?{lerp:p?this.options.syncTouchLerp:1}:{lerp:this.options.lerp,duration:this.options.duration,easing:this.options.easing}))},this.onNativeScroll=()=>{if(clearTimeout(this.__resetVelocityTimeout),delete this.__resetVelocityTimeout,this.__preventNextNativeScrollEvent)delete this.__preventNextNativeScrollEvent;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.isScrolling="native",this.emit(),0!==this.velocity&&(this.__resetVelocityTimeout=setTimeout((()=>{this.lastVelocity=this.velocity,this.velocity=0,this.isScrolling=!1,this.emit()}),400))}},window.lenisVersion="1.1.4",t&&t!==document.documentElement&&t!==document.body||(t=window),this.options={wrapper:t,content:e,wheelEventsTarget:i,eventsTarget:s,smoothWheel:o,syncTouch:n,syncTouchLerp:r,touchInertiaMultiplier:l,duration:h,easing:a,lerp:c,infinite:p,gestureOrientation:u,orientation:d,touchMultiplier:m,wheelMultiplier:v,autoResize:g,prevent:w,__experimental__naiveDimensions:S},this.animate=new Animate,this.emitter=new Emitter,this.dimensions=new Dimensions({wrapper:t,content:e,autoResize:g}),this.updateClassName(),this.userData={},this.time=0,this.velocity=this.lastVelocity=0,this.isLocked=!1,this.isStopped=!1,this.isScrolling=!1,this.targetScroll=this.animatedScroll=this.actualScroll,this.options.wrapper.addEventListener("scroll",this.onNativeScroll,!1),this.options.wrapper.addEventListener("pointerdown",this.onPointerDown,!1),this.virtualScroll=new VirtualScroll(s,{touchMultiplier:m,wheelMultiplier:v}),this.virtualScroll.on("scroll",this.onVirtualScroll)}destroy(){this.emitter.destroy(),this.options.wrapper.removeEventListener("scroll",this.onNativeScroll,!1),this.options.wrapper.removeEventListener("pointerdown",this.onPointerDown,!1),this.virtualScroll.destroy(),this.dimensions.destroy(),this.cleanUpClassName()}on(t,e){return this.emitter.on(t,e)}off(t,e){return this.emitter.off(t,e)}setScroll(t){this.isHorizontal?this.rootElement.scrollLeft=t:this.rootElement.scrollTop=t}resize(){this.dimensions.resize()}emit(){this.emitter.emit("scroll",this)}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.isStopped=!1,this.reset())}stop(){this.isStopped||(this.isStopped=!0,this.animate.stop(),this.reset())}raf(t){const e=t-(this.time||t);this.time=t,this.animate.advance(.001*e)}scrollTo(t,{offset:e=0,immediate:i=!1,lock:s=!1,duration:o=this.options.duration,easing:n=this.options.easing,lerp:r=this.options.lerp,onStart:l,onComplete:h,force:a=!1,programmatic:c=!0,userData:p={}}={}){if(!this.isStopped&&!this.isLocked||a){if("string"==typeof t&&["top","left","start"].includes(t))t=0;else if("string"==typeof t&&["bottom","right","end"].includes(t))t=this.limit;else{let i;if("string"==typeof t?i=document.querySelector(t):t instanceof HTMLElement&&(null==t?void 0:t.nodeType)&&(i=t),i){if(this.options.wrapper!==window){const t=this.rootElement.getBoundingClientRect();e-=this.isHorizontal?t.left:t.top}const s=i.getBoundingClientRect();t=(this.isHorizontal?s.left:s.top)+this.animatedScroll}}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)){if(this.userData=p,i)return this.animatedScroll=this.targetScroll=t,this.setScroll(this.scroll),this.reset(),this.preventNextNativeScrollEvent(),this.emit(),null==h||h(this),void(this.userData={});c||(this.targetScroll=t),this.animate.fromTo(this.animatedScroll,t,{duration:o,easing:n,lerp:r,onStart:()=>{s&&(this.isLocked=!0),this.isScrolling="smooth",null==l||l(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),c&&(this.targetScroll=t),e||this.emit(),e&&(this.reset(),this.emit(),null==h||h(this),this.userData={},this.preventNextNativeScrollEvent())}})}}}preventNextNativeScrollEvent(){this.__preventNextNativeScrollEvent=!0,requestAnimationFrame((()=>{delete this.__preventNextNativeScrollEvent}))}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(){return this.isHorizontal?this.rootElement.scrollLeft:this.rootElement.scrollTop}get scroll(){return this.options.infinite?function modulo(t,e){return(t%e+e)%e}(this.animatedScroll,this.limit):this.animatedScroll}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.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()}}export{Lenis as default};
1
+ function clamp(t,e,i){return Math.max(t,Math.min(e,i))}class Animate{advance(t){if(!this.isRunning)return;let e=!1;if(this.duration&&this.easing){this.currentTime+=t;const i=clamp(0,this.currentTime/this.duration,1);e=i>=1;const s=e?1:this.easing(i);this.value=this.from+(this.to-this.from)*s}else this.lerp?(this.value=function damp(t,e,i,s){return function lerp(t,e,i){return(1-i)*t+i*e}(t,e,1-Math.exp(-i*s))}(this.value,this.to,60*this.lerp,t),Math.round(this.value)===this.to&&(this.value=this.to,e=!0)):(this.value=this.to,e=!0);e&&this.stop(),this.onUpdate?.(this.value,e)}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}}class Dimensions{constructor({wrapper:t,content:e,autoResize:i=!0,debounce:s=250}={}){this.wrapper=t,this.content=e,i&&(this.debouncedResize=function debounce(t,e){let i;return function(){let s=arguments,o=this;clearTimeout(i),i=setTimeout((function(){t.apply(o,s)}),e)}}(this.resize,s),this.wrapper===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()}destroy(){this.wrapperResizeObserver?.disconnect(),this.contentResizeObserver?.disconnect(),window.removeEventListener("resize",this.debouncedResize,!1)}resize=()=>{this.onWrapperResize(),this.onContentResize()};onWrapperResize=()=>{this.wrapper===window?(this.width=window.innerWidth,this.height=window.innerHeight):(this.width=this.wrapper.clientWidth,this.height=this.wrapper.clientHeight)};onContentResize=()=>{this.wrapper===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}}}class Emitter{constructor(){this.events={}}emit(t,...e){let i=this.events[t]||[];for(let t=0,s=i.length;t<s;t++)i[t](...e)}on(t,e){return this.events[t]?.push(e)||(this.events[t]=[e]),()=>{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={}}}const t=100/6;class VirtualScroll{constructor(t,{wheelMultiplier:e=1,touchMultiplier:i=1}){this.element=t,this.wheelMultiplier=e,this.touchMultiplier=i,this.touchStart={x:null,y:null},this.emitter=new Emitter,window.addEventListener("resize",this.onWindowResize,!1),this.onWindowResize(),this.element.addEventListener("wheel",this.onWheel,{passive:!1}),this.element.addEventListener("touchstart",this.onTouchStart,{passive:!1}),this.element.addEventListener("touchmove",this.onTouchMove,{passive:!1}),this.element.addEventListener("touchend",this.onTouchEnd,{passive:!1})}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,{passive:!1}),this.element.removeEventListener("touchstart",this.onTouchStart,{passive:!1}),this.element.removeEventListener("touchmove",this.onTouchMove,{passive:!1}),this.element.removeEventListener("touchend",this.onTouchEnd,{passive:!1})}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.touchMultiplier,o=-(i-this.touchStart.y)*this.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=e=>{let{deltaX:i,deltaY:s,deltaMode:o}=e;i*=1===o?t:2===o?this.windowWidth:1,s*=1===o?t:2===o?this.windowHeight:1,i*=this.wheelMultiplier,s*=this.wheelMultiplier,this.emitter.emit("scroll",{deltaX:i,deltaY:s,event:e})};onWindowResize=()=>{this.windowWidth=window.innerWidth,this.windowHeight=window.innerHeight}}class Lenis{constructor({wrapper:t=window,content:e=document.documentElement,wheelEventsTarget:i=t,eventsTarget:s=i,smoothWheel:o=!0,syncTouch:n=!1,syncTouchLerp:r=.075,touchInertiaMultiplier:l=35,duration:h,easing:a=(t=>Math.min(1,1.001-Math.pow(2,-10*t))),lerp:c=.1,infinite:p=!1,orientation:d="vertical",gestureOrientation:u="vertical",touchMultiplier:m=1,wheelMultiplier:v=1,autoResize:g=!0,prevent:w=!1,__experimental__naiveDimensions:S=!1}={}){this.__isScrolling=!1,this.__isStopped=!1,this.__isLocked=!1,this.direction=0,this.onPointerDown=t=>{1===t.button&&this.reset()},this.onVirtualScroll=({deltaX:t,deltaY:e,event:i})=>{if(i.ctrlKey)return;const s=i.type.includes("touch"),o=i.type.includes("wheel");this.isTouching="touchstart"===i.type||"touchmove"===i.type;if(this.options.syncTouch&&s&&"touchstart"===i.type&&!this.isStopped&&!this.isLocked)return void this.reset();const n=0===t&&0===e,r="vertical"===this.options.gestureOrientation&&0===e||"horizontal"===this.options.gestureOrientation&&0===t;if(n||r)return;let l=i.composedPath();l=l.slice(0,l.indexOf(this.rootElement));const h=this.options.prevent;if(l.find((t=>{var e,i,n,r,l;return t instanceof Element&&(("function"==typeof h?null==h?void 0:h(t):h)||(null===(e=t.hasAttribute)||void 0===e?void 0:e.call(t,"data-lenis-prevent"))||s&&(null===(i=t.hasAttribute)||void 0===i?void 0:i.call(t,"data-lenis-prevent-touch"))||o&&(null===(n=t.hasAttribute)||void 0===n?void 0:n.call(t,"data-lenis-prevent-wheel"))||(null===(r=t.classList)||void 0===r?void 0:r.contains("lenis"))&&!(null===(l=t.classList)||void 0===l?void 0:l.contains("lenis-stopped")))})))return;if(this.isStopped||this.isLocked)return void i.preventDefault();if(!(this.options.syncTouch&&s||this.options.smoothWheel&&o))return this.isScrolling="native",void this.animate.stop();i.preventDefault();let a=e;"both"===this.options.gestureOrientation?a=Math.abs(e)>Math.abs(t)?e:t:"horizontal"===this.options.gestureOrientation&&(a=t);const c=s&&this.options.syncTouch,p=s&&"touchend"===i.type&&Math.abs(a)>5;p&&(a=this.velocity*this.options.touchInertiaMultiplier),this.scrollTo(this.targetScroll+a,Object.assign({programmatic:!1},c?{lerp:p?this.options.syncTouchLerp:1}:{lerp:this.options.lerp,duration:this.options.duration,easing:this.options.easing}))},this.onNativeScroll=()=>{if(clearTimeout(this.__resetVelocityTimeout),delete this.__resetVelocityTimeout,this.__preventNextNativeScrollEvent)delete this.__preventNextNativeScrollEvent;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.isScrolling="native",this.emit(),0!==this.velocity&&(this.__resetVelocityTimeout=setTimeout((()=>{this.lastVelocity=this.velocity,this.velocity=0,this.isScrolling=!1,this.emit()}),400))}},window.lenisVersion="1.1.5",t&&t!==document.documentElement&&t!==document.body||(t=window),this.options={wrapper:t,content:e,wheelEventsTarget:i,eventsTarget:s,smoothWheel:o,syncTouch:n,syncTouchLerp:r,touchInertiaMultiplier:l,duration:h,easing:a,lerp:c,infinite:p,gestureOrientation:u,orientation:d,touchMultiplier:m,wheelMultiplier:v,autoResize:g,prevent:w,__experimental__naiveDimensions:S},this.animate=new Animate,this.emitter=new Emitter,this.dimensions=new Dimensions({wrapper:t,content:e,autoResize:g}),this.updateClassName(),this.userData={},this.time=0,this.velocity=this.lastVelocity=0,this.isLocked=!1,this.isStopped=!1,this.isScrolling=!1,this.targetScroll=this.animatedScroll=this.actualScroll,this.options.wrapper.addEventListener("scroll",this.onNativeScroll,!1),this.options.wrapper.addEventListener("pointerdown",this.onPointerDown,!1),this.virtualScroll=new VirtualScroll(s,{touchMultiplier:m,wheelMultiplier:v}),this.virtualScroll.on("scroll",this.onVirtualScroll)}destroy(){this.emitter.destroy(),this.options.wrapper.removeEventListener("scroll",this.onNativeScroll,!1),this.options.wrapper.removeEventListener("pointerdown",this.onPointerDown,!1),this.virtualScroll.destroy(),this.dimensions.destroy(),this.cleanUpClassName()}on(t,e){return this.emitter.on(t,e)}off(t,e){return this.emitter.off(t,e)}setScroll(t){this.isHorizontal?this.rootElement.scrollLeft=t:this.rootElement.scrollTop=t}resize(){this.dimensions.resize()}emit(){this.emitter.emit("scroll",this)}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.isStopped=!1,this.reset())}stop(){this.isStopped||(this.isStopped=!0,this.animate.stop(),this.reset())}raf(t){const e=t-(this.time||t);this.time=t,this.animate.advance(.001*e)}scrollTo(t,{offset:e=0,immediate:i=!1,lock:s=!1,duration:o=this.options.duration,easing:n=this.options.easing,lerp:r=this.options.lerp,onStart:l,onComplete:h,force:a=!1,programmatic:c=!0,userData:p={}}={}){if(!this.isStopped&&!this.isLocked||a){if("string"==typeof t&&["top","left","start"].includes(t))t=0;else if("string"==typeof t&&["bottom","right","end"].includes(t))t=this.limit;else{let i;if("string"==typeof t?i=document.querySelector(t):t instanceof HTMLElement&&(null==t?void 0:t.nodeType)&&(i=t),i){if(this.options.wrapper!==window){const t=this.rootElement.getBoundingClientRect();e-=this.isHorizontal?t.left:t.top}const s=i.getBoundingClientRect();t=(this.isHorizontal?s.left:s.top)+this.animatedScroll}}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)){if(this.userData=p,i)return this.animatedScroll=this.targetScroll=t,this.setScroll(this.scroll),this.reset(),this.preventNextNativeScrollEvent(),this.emit(),null==h||h(this),void(this.userData={});c||(this.targetScroll=t),this.animate.fromTo(this.animatedScroll,t,{duration:o,easing:n,lerp:r,onStart:()=>{s&&(this.isLocked=!0),this.isScrolling="smooth",null==l||l(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),c&&(this.targetScroll=t),e||this.emit(),e&&(this.reset(),this.emit(),null==h||h(this),this.userData={},this.preventNextNativeScrollEvent())}})}}}preventNextNativeScrollEvent(){this.__preventNextNativeScrollEvent=!0,requestAnimationFrame((()=>{delete this.__preventNextNativeScrollEvent}))}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(){return this.isHorizontal?this.rootElement.scrollLeft:this.rootElement.scrollTop}get scroll(){return this.options.infinite?function modulo(t,e){return(t%e+e)%e}(this.animatedScroll,this.limit):this.animatedScroll}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.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()}}export{Lenis as default};
2
2
  //# sourceMappingURL=lenis.mjs.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lenis",
3
- "version": "1.1.4",
3
+ "version": "1.1.5",
4
4
  "author": "darkroom.engineering",
5
5
  "license": "MIT",
6
6
  "repository": {