lenis 1.1.13 → 1.1.14-dev.0

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.
@@ -1 +1 @@
1
- {"version":3,"file":"lenis-snap.mjs","sources":["../../src/element.ts","../../src/uid.ts","../../src/index.ts","../../src/debounce.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, { type UserData } from 'lenis'\r\nimport { debounce } from './debounce'\r\nimport { SnapElement, SnapElementOptions } from './element'\r\nimport type { SnapItem, SnapOptions } from './types'\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\n// Types\r\nexport * from './types'\r\n\r\ntype RequiredPick<T, F extends keyof T> = Omit<T, F> & Required<Pick<T, F>>\r\n\r\n/**\r\n * Snap class to handle the snap functionality\r\n *\r\n * @example\r\n * const snap = new Snap(lenis, {\r\n * type: 'mandatory', // 'mandatory', 'proximity'\r\n * lerp: 0.1,\r\n * duration: 1,\r\n * easing: (t) => t,\r\n * onSnapStart: (snap) => {\r\n * console.log('onSnapStart', snap)\r\n * },\r\n * onSnapComplete: (snap) => {\r\n * console.log('onSnapComplete', snap)\r\n * },\r\n * })\r\n *\r\n * snap.add(500) // snap at 500px\r\n *\r\n * const removeSnap = snap.add(500)\r\n *\r\n * if (someCondition) {\r\n * removeSnap()\r\n * }\r\n */\r\nexport default class Snap {\r\n options: RequiredPick<SnapOptions, 'type' | 'velocityThreshold' | 'debounce'>\r\n elements = new Map<UID, SnapElement>()\r\n snaps = new Map<UID, SnapItem>()\r\n viewport = {\r\n width: window.innerWidth,\r\n height: window.innerHeight,\r\n }\r\n isStopped = false\r\n onSnapDebounced: () => void\r\n\r\n constructor(\r\n private lenis: Lenis,\r\n {\r\n type = 'mandatory',\r\n lerp,\r\n easing,\r\n duration,\r\n velocityThreshold = 1,\r\n debounce: debounceDelay = 0,\r\n onSnapStart,\r\n onSnapComplete,\r\n }: SnapOptions = {}\r\n ) {\r\n this.options = {\r\n type,\r\n lerp,\r\n easing,\r\n duration,\r\n velocityThreshold,\r\n debounce: debounceDelay,\r\n onSnapStart,\r\n onSnapComplete,\r\n }\r\n\r\n this.onWindowResize()\r\n window.addEventListener('resize', this.onWindowResize, false)\r\n\r\n this.onSnapDebounced = debounce(this.onSnap, this.options.debounce)\r\n\r\n this.lenis.on('scroll', this.onScroll)\r\n }\r\n\r\n /**\r\n * Destroy the snap instance\r\n */\r\n destroy() {\r\n this.lenis.off('scroll', this.onScroll)\r\n window.removeEventListener('resize', this.onWindowResize, false)\r\n this.elements.forEach((element) => element.destroy())\r\n }\r\n\r\n /**\r\n * Start the snap after it has been stopped\r\n */\r\n start() {\r\n this.isStopped = false\r\n }\r\n\r\n /**\r\n * Stop the snap\r\n */\r\n stop() {\r\n this.isStopped = true\r\n }\r\n\r\n /**\r\n * Add a snap to the snap instance\r\n *\r\n * @param value The value to snap to\r\n * @param userData User data that will be forwarded through the snap event\r\n * @returns Unsubscribe function\r\n */\r\n add(value: number, userData: UserData = {}) {\r\n const id = uid()\r\n\r\n this.snaps.set(id, { value, userData })\r\n\r\n return () => this.remove(id)\r\n }\r\n\r\n /**\r\n * Remove a snap from the snap instance\r\n *\r\n * @param id The snap id of the snap to remove\r\n */\r\n remove(id: UID) {\r\n this.snaps.delete(id)\r\n }\r\n\r\n /**\r\n * Add an element to the snap instance\r\n *\r\n * @param element The element to add\r\n * @param options The options for the element\r\n * @returns Unsubscribe function\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 /**\r\n * Remove an element from the snap instance\r\n *\r\n * @param id The snap id of the snap element to remove\r\n */\r\n removeElement(id: UID) {\r\n this.elements.delete(id)\r\n }\r\n\r\n private onWindowResize = () => {\r\n this.viewport.width = window.innerWidth\r\n this.viewport.height = window.innerHeight\r\n }\r\n\r\n private onScroll = ({\r\n // scroll,\r\n // limit,\r\n lastVelocity,\r\n velocity,\r\n // isScrolling,\r\n userData,\r\n }: // isHorizontal,\r\n Lenis) => {\r\n if (this.isStopped) return\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 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 this.onSnapDebounced()\r\n }\r\n }\r\n\r\n private onSnap = () => {\r\n let { scroll, isHorizontal } = this.lenis\r\n scroll = Math.ceil(this.lenis.scroll)\r\n\r\n let snaps = [...this.snaps.values()] as SnapItem[]\r\n\r\n this.elements.forEach(({ rect, align }) => {\r\n let value: number | undefined\r\n\r\n align.forEach((align) => {\r\n if (align === 'start') {\r\n value = rect.top\r\n } else if (align === 'center') {\r\n value = 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 value = 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 (typeof value === 'number') {\r\n snaps.push({ value: Math.ceil(value), userData: {} })\r\n }\r\n })\r\n })\r\n\r\n snaps = snaps.sort((a, b) => Math.abs(a.value) - Math.abs(b.value))\r\n\r\n let prevSnap = snaps.findLast(({ value }) => value <= scroll)\r\n if (prevSnap === undefined) prevSnap = snaps[0]\r\n const distanceToPrevSnap = Math.abs(scroll - prevSnap.value)\r\n\r\n let nextSnap = snaps.find(({ value }) => value >= scroll)\r\n if (nextSnap === undefined) nextSnap = snaps[snaps.length - 1]\r\n const distanceToNextSnap = Math.abs(scroll - nextSnap.value)\r\n\r\n const snap = distanceToPrevSnap < distanceToNextSnap ? prevSnap : nextSnap\r\n\r\n const distance = Math.abs(scroll - snap.value)\r\n\r\n if (\r\n this.options.type === 'mandatory' ||\r\n (this.options.type === 'proximity' &&\r\n distance <=\r\n (isHorizontal\r\n ? this.lenis.dimensions.width\r\n : this.lenis.dimensions.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.value, {\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","export function debounce<CB extends (...args: any[]) => void>(\r\n callback: CB,\r\n delay: number\r\n) {\r\n let timer: number | undefined\r\n return function <T>(this: T, ...args: Parameters<typeof callback>) {\r\n let context = this\r\n clearTimeout(timer)\r\n timer = setTimeout(() => {\r\n timer = undefined\r\n callback.apply(context, args)\r\n }, delay)\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","debounce","debounceDelay","onSnapStart","onSnapComplete","elements","Map","snaps","viewport","innerWidth","innerHeight","isStopped","onWindowResize","onScroll","lastVelocity","velocity","userData","isDecelerating","Math","abs","isTurningBack","sign","initiator","onSnapDebounced","onSnap","scroll","isHorizontal","ceil","values","forEach","value","push","sort","a","b","prevSnap","findLast","undefined","distanceToPrevSnap","nextSnap","find","length","snap","distance","dimensions","scrollTo","onStart","_b","call","onComplete","addEventListener","callback","delay","timer","args","context","clearTimeout","setTimeout","apply","on","off","removeEventListener","start","stop","add","id","set","remove","delete","addElement","removeElement"],"mappings":"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"}
1
+ {"version":3,"sources":["../packages/snap/src/debounce.ts","../packages/snap/src/element.ts","../packages/snap/src/uid.ts","../packages/snap/src/snap.ts"],"sourcesContent":["export function debounce<CB extends (...args: any[]) => void>(\r\n callback: CB,\r\n delay: number\r\n) {\r\n let timer: number | undefined\r\n return function <T>(this: T, ...args: Parameters<typeof callback>) {\r\n let context = this\r\n clearTimeout(timer)\r\n timer = setTimeout(() => {\r\n timer = undefined\r\n callback.apply(context, args)\r\n }, delay)\r\n }\r\n}\r\n","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 if (!entry?.borderBoxSize[0]) return\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 type Lenis from 'lenis'\r\nimport type { UserData } from 'lenis'\r\nimport { debounce } from './debounce'\r\nimport type { SnapElementOptions } from './element'\r\nimport { SnapElement } from './element'\r\nimport type { SnapItem, SnapOptions } from './types'\r\nimport type { UID } from './uid'\r\nimport { 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 RequiredPick<T, F extends keyof T> = Omit<T, F> & Required<Pick<T, F>>\r\n\r\n/**\r\n * Snap class to handle the snap functionality\r\n *\r\n * @example\r\n * const snap = new Snap(lenis, {\r\n * type: 'mandatory', // 'mandatory', 'proximity'\r\n * lerp: 0.1,\r\n * duration: 1,\r\n * easing: (t) => t,\r\n * onSnapStart: (snap) => {\r\n * console.log('onSnapStart', snap)\r\n * },\r\n * onSnapComplete: (snap) => {\r\n * console.log('onSnapComplete', snap)\r\n * },\r\n * })\r\n *\r\n * snap.add(500) // snap at 500px\r\n *\r\n * const removeSnap = snap.add(500)\r\n *\r\n * if (someCondition) {\r\n * removeSnap()\r\n * }\r\n */\r\nexport class Snap {\r\n options: RequiredPick<SnapOptions, 'type' | 'velocityThreshold' | 'debounce'>\r\n elements = new Map<UID, SnapElement>()\r\n snaps = new Map<UID, SnapItem>()\r\n viewport = {\r\n width: window.innerWidth,\r\n height: window.innerHeight,\r\n }\r\n isStopped = false\r\n onSnapDebounced: () => void\r\n\r\n constructor(\r\n private lenis: Lenis,\r\n {\r\n type = 'mandatory',\r\n lerp,\r\n easing,\r\n duration,\r\n velocityThreshold = 1,\r\n debounce: debounceDelay = 0,\r\n onSnapStart,\r\n onSnapComplete,\r\n }: SnapOptions = {}\r\n ) {\r\n this.options = {\r\n type,\r\n lerp,\r\n easing,\r\n duration,\r\n velocityThreshold,\r\n debounce: debounceDelay,\r\n onSnapStart,\r\n onSnapComplete,\r\n }\r\n\r\n this.onWindowResize()\r\n window.addEventListener('resize', this.onWindowResize, false)\r\n\r\n this.onSnapDebounced = debounce(this.onSnap, this.options.debounce)\r\n\r\n this.lenis.on('scroll', this.onScroll)\r\n }\r\n\r\n /**\r\n * Destroy the snap instance\r\n */\r\n destroy() {\r\n this.lenis.off('scroll', this.onScroll)\r\n window.removeEventListener('resize', this.onWindowResize, false)\r\n this.elements.forEach((element) => element.destroy())\r\n }\r\n\r\n /**\r\n * Start the snap after it has been stopped\r\n */\r\n start() {\r\n this.isStopped = false\r\n }\r\n\r\n /**\r\n * Stop the snap\r\n */\r\n stop() {\r\n this.isStopped = true\r\n }\r\n\r\n /**\r\n * Add a snap to the snap instance\r\n *\r\n * @param value The value to snap to\r\n * @param userData User data that will be forwarded through the snap event\r\n * @returns Unsubscribe function\r\n */\r\n add(value: number, userData: UserData = {}) {\r\n const id = uid()\r\n\r\n this.snaps.set(id, { value, userData })\r\n\r\n return () => this.remove(id)\r\n }\r\n\r\n /**\r\n * Remove a snap from the snap instance\r\n *\r\n * @param id The snap id of the snap to remove\r\n */\r\n remove(id: UID) {\r\n this.snaps.delete(id)\r\n }\r\n\r\n /**\r\n * Add an element to the snap instance\r\n *\r\n * @param element The element to add\r\n * @param options The options for the element\r\n * @returns Unsubscribe function\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 /**\r\n * Remove an element from the snap instance\r\n *\r\n * @param id The snap id of the snap element to remove\r\n */\r\n removeElement(id: UID) {\r\n this.elements.delete(id)\r\n }\r\n\r\n private onWindowResize = () => {\r\n this.viewport.width = window.innerWidth\r\n this.viewport.height = window.innerHeight\r\n }\r\n\r\n private onScroll = ({\r\n // scroll,\r\n // limit,\r\n lastVelocity,\r\n velocity,\r\n // isScrolling,\r\n userData,\r\n }: // isHorizontal,\r\n Lenis) => {\r\n if (this.isStopped) return\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 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 this.onSnapDebounced()\r\n }\r\n }\r\n\r\n private onSnap = () => {\r\n let { scroll, isHorizontal } = this.lenis\r\n scroll = Math.ceil(this.lenis.scroll)\r\n\r\n let snaps = [...this.snaps.values()] as SnapItem[]\r\n\r\n this.elements.forEach(({ rect, align }) => {\r\n let value: number | undefined\r\n\r\n align.forEach((align) => {\r\n if (align === 'start') {\r\n value = rect.top\r\n } else if (align === 'center') {\r\n value = 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 value = 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 (typeof value === 'number') {\r\n snaps.push({ value: Math.ceil(value), userData: {} })\r\n }\r\n })\r\n })\r\n\r\n snaps = snaps.sort((a, b) => Math.abs(a.value) - Math.abs(b.value))\r\n\r\n let prevSnap = snaps.findLast(({ value }) => value <= scroll)\r\n if (prevSnap === undefined) prevSnap = snaps[0]!\r\n const distanceToPrevSnap = Math.abs(scroll - prevSnap.value)\r\n\r\n let nextSnap = snaps.find(({ value }) => value >= scroll)\r\n if (nextSnap === undefined) nextSnap = snaps[snaps.length - 1]!\r\n const distanceToNextSnap = Math.abs(scroll - nextSnap.value)\r\n\r\n const snap = distanceToPrevSnap < distanceToNextSnap ? prevSnap : nextSnap\r\n\r\n const distance = Math.abs(scroll - snap.value)\r\n\r\n if (\r\n this.options.type === 'mandatory' ||\r\n (this.options.type === 'proximity' &&\r\n distance <=\r\n (isHorizontal\r\n ? this.lenis.dimensions.width\r\n : this.lenis.dimensions.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.value, {\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"],"mappings":"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","names":["align"]}
@@ -0,0 +1,68 @@
1
+ import * as vue from 'vue';
2
+ import { PropType, HTMLAttributes, Plugin } from 'vue';
3
+ import * as lenis from 'lenis';
4
+ import { ScrollCallback } from 'lenis';
5
+
6
+ declare const VueLenis: vue.DefineComponent<{
7
+ root: {
8
+ type: PropType<boolean>;
9
+ default: boolean;
10
+ };
11
+ autoRaf: {
12
+ type: PropType<boolean>;
13
+ default: boolean;
14
+ };
15
+ rafPriority: {
16
+ type: PropType<number>;
17
+ default: number;
18
+ };
19
+ options: {
20
+ type: PropType<lenis.LenisOptions | undefined>;
21
+ default: () => {};
22
+ };
23
+ props: {
24
+ type: PropType<HTMLAttributes>;
25
+ default: () => {};
26
+ };
27
+ }, () => vue.VNode<vue.RendererNode, vue.RendererElement, {
28
+ [key: string]: any;
29
+ }> | vue.VNode<vue.RendererNode, vue.RendererElement, {
30
+ [key: string]: any;
31
+ }>[] | undefined, unknown, {}, {}, vue.ComponentOptionsMixin, vue.ComponentOptionsMixin, {}, string, vue.PublicProps, Readonly<vue.ExtractPropTypes<{
32
+ root: {
33
+ type: PropType<boolean>;
34
+ default: boolean;
35
+ };
36
+ autoRaf: {
37
+ type: PropType<boolean>;
38
+ default: boolean;
39
+ };
40
+ rafPriority: {
41
+ type: PropType<number>;
42
+ default: number;
43
+ };
44
+ options: {
45
+ type: PropType<lenis.LenisOptions | undefined>;
46
+ default: () => {};
47
+ };
48
+ props: {
49
+ type: PropType<HTMLAttributes>;
50
+ default: () => {};
51
+ };
52
+ }>>, {
53
+ props: HTMLAttributes;
54
+ root: boolean;
55
+ autoRaf: boolean;
56
+ rafPriority: number;
57
+ options: lenis.LenisOptions | undefined;
58
+ }, {}>;
59
+ declare const vueLenisPlugin: Plugin;
60
+ declare module '@vue/runtime-core' {
61
+ interface GlobalComponents {
62
+ 'vue-lenis': typeof VueLenis;
63
+ }
64
+ }
65
+
66
+ declare function useLenis(callback?: ScrollCallback, priority?: number): vue.ComputedRef<lenis.default | undefined>;
67
+
68
+ export { VueLenis as Lenis, VueLenis, vueLenisPlugin as default, useLenis };
@@ -0,0 +1,198 @@
1
+ // packages/vue/src/provider.ts
2
+ import Tempus from "@darkroom.engineering/tempus";
3
+ import Lenis from "lenis";
4
+ import {
5
+ defineComponent,
6
+ h,
7
+ onBeforeUnmount,
8
+ onMounted,
9
+ provide,
10
+ reactive,
11
+ ref,
12
+ shallowRef as shallowRef2,
13
+ watch
14
+ } from "vue";
15
+
16
+ // packages/vue/src/store.ts
17
+ import { shallowRef } from "vue";
18
+ var globalLenis = shallowRef();
19
+ var globalAddCallback = shallowRef();
20
+ var globalRemoveCallback = shallowRef();
21
+
22
+ // packages/vue/src/provider.ts
23
+ var LenisSymbol = Symbol("LenisContext");
24
+ var AddCallbackSymbol = Symbol("AddCallback");
25
+ var RemoveCallbackSymbol = Symbol("RemoveCallback");
26
+ var VueLenis = defineComponent({
27
+ name: "VueLenis",
28
+ props: {
29
+ root: {
30
+ type: Boolean,
31
+ default: false
32
+ },
33
+ autoRaf: {
34
+ type: Boolean,
35
+ default: true
36
+ },
37
+ rafPriority: {
38
+ type: Number,
39
+ default: 0
40
+ },
41
+ options: {
42
+ type: Object,
43
+ default: () => ({})
44
+ },
45
+ props: {
46
+ type: Object,
47
+ default: () => ({})
48
+ }
49
+ },
50
+ setup(props, { slots, expose }) {
51
+ const lenisRef = shallowRef2();
52
+ const tempusCleanupRef = shallowRef2();
53
+ const wrapper = ref();
54
+ const content = ref();
55
+ expose({
56
+ lenis: lenisRef,
57
+ wrapper,
58
+ content
59
+ });
60
+ onMounted(() => {
61
+ lenisRef.value = new Lenis({
62
+ ...props.options,
63
+ ...!props.root ? {
64
+ wrapper: wrapper.value,
65
+ content: content.value
66
+ } : {}
67
+ });
68
+ });
69
+ onBeforeUnmount(() => {
70
+ lenisRef.value?.destroy();
71
+ lenisRef.value = void 0;
72
+ });
73
+ watch(
74
+ () => props.options,
75
+ (options, oldOptions) => {
76
+ const optionsChanged = JSON.stringify(oldOptions) !== JSON.stringify(options);
77
+ if (optionsChanged) {
78
+ lenisRef.value?.destroy();
79
+ lenisRef.value = new Lenis({
80
+ ...props.options,
81
+ ...!props.root ? {
82
+ wrapper: wrapper.value,
83
+ content: content.value
84
+ } : {}
85
+ });
86
+ }
87
+ },
88
+ { deep: true }
89
+ );
90
+ watch(
91
+ [lenisRef, () => props.autoRaf, () => props.rafPriority],
92
+ ([lenis, autoRaf, rafPriority]) => {
93
+ if (!lenis || !autoRaf) {
94
+ return tempusCleanupRef.value?.();
95
+ }
96
+ tempusCleanupRef.value?.();
97
+ if (autoRaf) {
98
+ tempusCleanupRef.value = Tempus.add(
99
+ (time) => lenis?.raf(time),
100
+ rafPriority
101
+ );
102
+ }
103
+ }
104
+ );
105
+ const callbacks = reactive([]);
106
+ function addCallback(callback, priority) {
107
+ callbacks.push({ callback, priority });
108
+ callbacks.sort((a, b) => a.priority - b.priority);
109
+ }
110
+ function removeCallback(callback) {
111
+ callbacks.splice(
112
+ callbacks.findIndex((cb) => cb.callback === callback),
113
+ 1
114
+ );
115
+ }
116
+ const onScroll = (data) => {
117
+ for (let i = 0; i < callbacks.length; i++) {
118
+ callbacks[i]?.callback(data);
119
+ }
120
+ };
121
+ watch(lenisRef, (lenis) => {
122
+ lenis?.on("scroll", onScroll);
123
+ if (props.root) {
124
+ globalLenis.value = lenis;
125
+ globalAddCallback.value = addCallback;
126
+ globalRemoveCallback.value = removeCallback;
127
+ }
128
+ });
129
+ if (!props.root) {
130
+ provide(LenisSymbol, lenisRef);
131
+ provide(AddCallbackSymbol, addCallback);
132
+ provide(RemoveCallbackSymbol, removeCallback);
133
+ }
134
+ return () => {
135
+ if (props.root) {
136
+ return slots.default?.();
137
+ } else {
138
+ const combinedClassName = ["lenis", props.props?.class].filter(Boolean).join(" ");
139
+ delete props.props?.class;
140
+ return h("div", { class: combinedClassName, ref: wrapper, ...props }, [
141
+ h("div", { ref: content }, slots.default?.())
142
+ ]);
143
+ }
144
+ };
145
+ }
146
+ });
147
+ var vueLenisPlugin = (app) => {
148
+ app.component("vue-lenis", VueLenis);
149
+ app.provide(LenisSymbol, shallowRef2(void 0));
150
+ app.provide(AddCallbackSymbol, void 0);
151
+ app.provide(RemoveCallbackSymbol, void 0);
152
+ };
153
+
154
+ // packages/vue/src/use-lenis.ts
155
+ import { computed, inject, nextTick, onBeforeUnmount as onBeforeUnmount2, watch as watch2 } from "vue";
156
+ function useLenis(callback, priority = 0) {
157
+ const lenisInjection = inject(LenisSymbol);
158
+ const addCallbackInjection = inject(AddCallbackSymbol);
159
+ const removeCallbackInjection = inject(RemoveCallbackSymbol);
160
+ const addCallback = computed(
161
+ () => addCallbackInjection ? addCallbackInjection : globalAddCallback.value
162
+ );
163
+ const removeCallback = computed(
164
+ () => removeCallbackInjection ? removeCallbackInjection : globalRemoveCallback.value
165
+ );
166
+ const lenis = computed(
167
+ () => lenisInjection?.value ? lenisInjection.value : globalLenis.value
168
+ );
169
+ nextTick(() => {
170
+ nextTick(() => {
171
+ if (!lenis.value) {
172
+ throw new Error(
173
+ "No lenis instance found, either mount a root lenis instance or wrap your component in a lenis provider"
174
+ );
175
+ }
176
+ });
177
+ });
178
+ watch2(
179
+ [lenis, addCallback, removeCallback],
180
+ ([lenis2, addCallback2, removeCallback2]) => {
181
+ if (!lenis2 || !addCallback2 || !removeCallback2 || !callback) return;
182
+ addCallback2?.(callback, priority);
183
+ callback?.(lenis2);
184
+ }
185
+ );
186
+ onBeforeUnmount2(() => {
187
+ if (!removeCallback.value || !callback) return;
188
+ removeCallback.value?.(callback);
189
+ });
190
+ return lenis;
191
+ }
192
+ export {
193
+ VueLenis as Lenis,
194
+ VueLenis,
195
+ vueLenisPlugin as default,
196
+ useLenis
197
+ };
198
+ //# sourceMappingURL=lenis-vue.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../packages/vue/src/provider.ts","../packages/vue/src/store.ts","../packages/vue/src/use-lenis.ts"],"sourcesContent":["import Tempus from '@darkroom.engineering/tempus'\r\nimport Lenis, { type ScrollCallback } from 'lenis'\r\nimport type {\r\n HTMLAttributes,\r\n InjectionKey,\r\n Plugin,\r\n PropType,\r\n ShallowRef,\r\n} from 'vue'\r\nimport {\r\n defineComponent,\r\n h,\r\n onBeforeUnmount,\r\n onMounted,\r\n provide,\r\n reactive,\r\n ref,\r\n shallowRef,\r\n watch,\r\n} from 'vue'\r\nimport { globalAddCallback, globalLenis, globalRemoveCallback } from './store'\r\n\r\nexport const LenisSymbol: InjectionKey<ShallowRef<Lenis | undefined>> =\r\n Symbol('LenisContext')\r\nexport const AddCallbackSymbol: InjectionKey<\r\n (callback: any, priority: number) => void\r\n> = Symbol('AddCallback')\r\nexport const RemoveCallbackSymbol: InjectionKey<(callback: any) => void> =\r\n Symbol('RemoveCallback')\r\n\r\nexport const VueLenis = defineComponent({\r\n name: 'VueLenis',\r\n props: {\r\n root: {\r\n type: Boolean as PropType<boolean>,\r\n default: false,\r\n },\r\n autoRaf: {\r\n type: Boolean as PropType<boolean>,\r\n default: true,\r\n },\r\n rafPriority: {\r\n type: Number as PropType<number>,\r\n default: 0,\r\n },\r\n options: {\r\n type: Object as PropType<ConstructorParameters<typeof Lenis>[0]>,\r\n default: () => ({}),\r\n },\r\n props: {\r\n type: Object as PropType<HTMLAttributes>,\r\n default: () => ({}),\r\n },\r\n },\r\n setup(props, { slots, expose }) {\r\n const lenisRef = shallowRef<Lenis>()\r\n const tempusCleanupRef = shallowRef<() => void>()\r\n const wrapper = ref<HTMLDivElement>()\r\n const content = ref<HTMLDivElement>()\r\n\r\n // Setup exposed properties\r\n expose({\r\n lenis: lenisRef,\r\n wrapper,\r\n content,\r\n })\r\n\r\n // Setup the lenis instance when the component is mounted\r\n onMounted(() => {\r\n lenisRef.value = new Lenis({\r\n ...props.options,\r\n ...(!props.root\r\n ? {\r\n wrapper: wrapper.value,\r\n content: content.value,\r\n }\r\n : {}),\r\n })\r\n })\r\n\r\n // Destroy the lenis instance when the component is unmounted\r\n onBeforeUnmount(() => {\r\n lenisRef.value?.destroy()\r\n lenisRef.value = undefined\r\n })\r\n\r\n // Sync options\r\n watch(\r\n () => props.options,\r\n (options, oldOptions) => {\r\n const optionsChanged =\r\n JSON.stringify(oldOptions) !== JSON.stringify(options)\r\n\r\n // If any of the options changed, destroy the lenis instance and create a new one\r\n if (optionsChanged) {\r\n lenisRef.value?.destroy()\r\n lenisRef.value = new Lenis({\r\n ...props.options,\r\n ...(!props.root\r\n ? {\r\n wrapper: wrapper.value,\r\n content: content.value,\r\n }\r\n : {}),\r\n })\r\n }\r\n },\r\n { deep: true }\r\n )\r\n\r\n // Sync autoRaf\r\n watch(\r\n [lenisRef, () => props.autoRaf, () => props.rafPriority],\r\n ([lenis, autoRaf, rafPriority]) => {\r\n if (!lenis || !autoRaf) {\r\n // If lenis is not defined or autoRaf is false, stop the raf if there is one\r\n return tempusCleanupRef.value?.()\r\n }\r\n\r\n // If either lenis, autoRaf or rafPriority changed, stop the raf if there is one and start a new one\r\n tempusCleanupRef.value?.()\r\n if (autoRaf) {\r\n tempusCleanupRef.value = Tempus.add(\r\n (time: number) => lenis?.raf(time),\r\n rafPriority\r\n )\r\n }\r\n }\r\n )\r\n\r\n const callbacks = reactive<\r\n { callback: ScrollCallback; priority: number }[]\r\n >([])\r\n\r\n function addCallback(callback: ScrollCallback, priority: number) {\r\n callbacks.push({ callback, priority })\r\n callbacks.sort((a, b) => a.priority - b.priority)\r\n }\r\n\r\n function removeCallback(callback: ScrollCallback) {\r\n callbacks.splice(\r\n callbacks.findIndex((cb) => cb.callback === callback),\r\n 1\r\n )\r\n }\r\n\r\n const onScroll: ScrollCallback = (data) => {\r\n for (let i = 0; i < callbacks.length; i++) {\r\n callbacks[i]?.callback(data)\r\n }\r\n }\r\n\r\n watch(lenisRef, (lenis) => {\r\n lenis?.on('scroll', onScroll)\r\n\r\n if (props.root) {\r\n globalLenis.value = lenis\r\n globalAddCallback.value = addCallback\r\n globalRemoveCallback.value = removeCallback\r\n }\r\n })\r\n\r\n if (!props.root) {\r\n provide(LenisSymbol, lenisRef)\r\n provide(AddCallbackSymbol, addCallback)\r\n provide(RemoveCallbackSymbol, removeCallback)\r\n }\r\n\r\n return () => {\r\n if (props.root) {\r\n return slots.default?.()\r\n } else {\r\n const combinedClassName = ['lenis', props.props?.class]\r\n .filter(Boolean)\r\n .join(' ')\r\n delete props.props?.class\r\n\r\n return h('div', { class: combinedClassName, ref: wrapper, ...props }, [\r\n h('div', { ref: content }, slots.default?.()),\r\n ])\r\n }\r\n }\r\n },\r\n})\r\n\r\nexport const vueLenisPlugin: Plugin = (app) => {\r\n app.component('vue-lenis', VueLenis)\r\n // Setup a global provide to silence top level useLenis injection warning\r\n app.provide(LenisSymbol, shallowRef(undefined))\r\n app.provide(AddCallbackSymbol, undefined as any)\r\n app.provide(RemoveCallbackSymbol, undefined as any)\r\n}\r\n\r\n// @ts-ignore\r\ndeclare module '@vue/runtime-core' {\r\n export interface GlobalComponents {\r\n 'vue-lenis': typeof VueLenis\r\n }\r\n}\r\n","import type Lenis from 'lenis'\r\nimport type { ScrollCallback } from 'lenis'\r\nimport { shallowRef } from 'vue'\r\n\r\nexport const globalLenis = shallowRef<Lenis>()\r\nexport const globalAddCallback =\r\n shallowRef<(callback: ScrollCallback, priority: number) => void>()\r\nexport const globalRemoveCallback =\r\n shallowRef<(callback: ScrollCallback) => void>()\r\n","import type { ScrollCallback } from 'lenis'\r\nimport { computed, inject, nextTick, onBeforeUnmount, watch } from 'vue'\r\nimport {\r\n AddCallbackSymbol,\r\n LenisSymbol,\r\n RemoveCallbackSymbol,\r\n} from './provider'\r\nimport { globalAddCallback, globalLenis, globalRemoveCallback } from './store'\r\n\r\nexport function useLenis(callback?: ScrollCallback, priority = 0) {\r\n const lenisInjection = inject(LenisSymbol)\r\n const addCallbackInjection = inject(AddCallbackSymbol)\r\n const removeCallbackInjection = inject(RemoveCallbackSymbol)\r\n\r\n const addCallback = computed(() =>\r\n addCallbackInjection ? addCallbackInjection : globalAddCallback.value\r\n )\r\n const removeCallback = computed(() =>\r\n removeCallbackInjection\r\n ? removeCallbackInjection\r\n : globalRemoveCallback.value\r\n )\r\n\r\n const lenis = computed(() =>\r\n lenisInjection?.value ? lenisInjection.value : globalLenis.value\r\n )\r\n\r\n // Wait two ticks to make sure the lenis instance is mounted\r\n nextTick(() => {\r\n nextTick(() => {\r\n if (!lenis.value) {\r\n throw new Error(\r\n 'No lenis instance found, either mount a root lenis instance or wrap your component in a lenis provider'\r\n )\r\n }\r\n })\r\n })\r\n\r\n watch(\r\n [lenis, addCallback, removeCallback],\r\n ([lenis, addCallback, removeCallback]) => {\r\n if (!lenis || !addCallback || !removeCallback || !callback) return\r\n\r\n addCallback?.(callback, priority)\r\n callback?.(lenis as any)\r\n }\r\n )\r\n\r\n onBeforeUnmount(() => {\r\n if (!removeCallback.value || !callback) return\r\n removeCallback.value?.(callback)\r\n })\r\n\r\n return lenis\r\n}\r\n"],"mappings":"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","names":["shallowRef","shallowRef","onBeforeUnmount","watch","watch","lenis","addCallback","removeCallback","onBeforeUnmount"]}
package/dist/lenis.css CHANGED
@@ -1,20 +1 @@
1
- html.lenis,
2
- html.lenis body {
3
- height: auto;
4
- }
5
-
6
- .lenis.lenis-smooth {
7
- scroll-behavior: auto !important;
8
- }
9
-
10
- .lenis.lenis-smooth [data-lenis-prevent] {
11
- overscroll-behavior: contain;
12
- }
13
-
14
- .lenis.lenis-stopped {
15
- overflow: hidden;
16
- }
17
-
18
- .lenis.lenis-smooth iframe {
19
- pointer-events: none;
20
- }
1
+ html.lenis,html.lenis body{height:auto}.lenis.lenis-smooth{scroll-behavior:auto!important}.lenis.lenis-smooth [data-lenis-prevent]{overscroll-behavior:contain}.lenis.lenis-stopped{overflow:hidden}.lenis.lenis-smooth iframe{pointer-events:none}