lenis 1.3.18-dev.1 → 1.3.18
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 +3 -4
- package/dist/lenis-snap.js +6 -2
- package/dist/lenis-snap.js.map +1 -1
- package/dist/lenis-snap.min.js +1 -1
- package/dist/lenis-snap.min.js.map +1 -1
- package/dist/lenis-snap.mjs +6 -2
- package/dist/lenis-snap.mjs.map +1 -1
- package/dist/lenis-vue.mjs.map +1 -1
- package/dist/lenis.d.ts +8 -3
- package/dist/lenis.js +20 -23
- package/dist/lenis.js.map +1 -1
- package/dist/lenis.min.js +1 -1
- package/dist/lenis.min.js.map +1 -1
- package/dist/lenis.mjs +20 -23
- package/dist/lenis.mjs.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -84,7 +84,7 @@ import Lenis from 'lenis'
|
|
|
84
84
|
Using scripts:
|
|
85
85
|
|
|
86
86
|
```html
|
|
87
|
-
<script src="https://unpkg.com/lenis@1.3.
|
|
87
|
+
<script src="https://unpkg.com/lenis@1.3.18/dist/lenis.min.js"></script>
|
|
88
88
|
```
|
|
89
89
|
|
|
90
90
|
|
|
@@ -131,7 +131,7 @@ import 'lenis/dist/lenis.css'
|
|
|
131
131
|
**Or link the CSS file:**
|
|
132
132
|
|
|
133
133
|
```html
|
|
134
|
-
<link rel="stylesheet" href="https://unpkg.com/lenis@1.3.
|
|
134
|
+
<link rel="stylesheet" href="https://unpkg.com/lenis@1.3.18/dist/lenis.css">
|
|
135
135
|
```
|
|
136
136
|
|
|
137
137
|
**Or add it manually:**
|
|
@@ -220,8 +220,7 @@ gsap.ticker.lagSmoothing(0);
|
|
|
220
220
|
| `animatedScroll` | `number` | Current scroll value |
|
|
221
221
|
| `dimensions` | `object` | Dimensions instance |
|
|
222
222
|
| `direction` | `number` | `1`: scrolling up, `-1`: scrolling down |
|
|
223
|
-
|
|
224
|
-
| `options` | `object` | Instance options |
|
|
223
|
+
`options` | `object` | Instance options |
|
|
225
224
|
| `targetScroll` | `number` | Target scroll value |
|
|
226
225
|
| `time` | `number` | Time elapsed since instance creation |
|
|
227
226
|
| `actualScroll` | `number` | Current scroll value registered by the browser |
|
package/dist/lenis-snap.js
CHANGED
|
@@ -157,6 +157,10 @@ var Snap = class {
|
|
|
157
157
|
onSnapComplete
|
|
158
158
|
} = {}) {
|
|
159
159
|
this.lenis = lenis;
|
|
160
|
+
if (!window.lenis) {
|
|
161
|
+
window.lenis = {};
|
|
162
|
+
}
|
|
163
|
+
window.lenis.snap = true;
|
|
160
164
|
this.options = {
|
|
161
165
|
type,
|
|
162
166
|
lerp,
|
|
@@ -168,7 +172,7 @@ var Snap = class {
|
|
|
168
172
|
onSnapComplete
|
|
169
173
|
};
|
|
170
174
|
this.onWindowResize();
|
|
171
|
-
window.addEventListener("resize", this.onWindowResize
|
|
175
|
+
window.addEventListener("resize", this.onWindowResize);
|
|
172
176
|
this.onSnapDebounced = debounce(
|
|
173
177
|
this.onSnap,
|
|
174
178
|
this.options.debounce
|
|
@@ -190,7 +194,7 @@ var Snap = class {
|
|
|
190
194
|
*/
|
|
191
195
|
destroy() {
|
|
192
196
|
this.lenis.off("virtual-scroll", this.onSnapDebounced);
|
|
193
|
-
window.removeEventListener("resize", this.onWindowResize
|
|
197
|
+
window.removeEventListener("resize", this.onWindowResize);
|
|
194
198
|
this.elements.forEach((element) => {
|
|
195
199
|
element.destroy();
|
|
196
200
|
});
|
package/dist/lenis-snap.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../packages/snap/src/debounce.ts","../packages/snap/src/element.ts","../packages/snap/src/uid.ts","../packages/snap/src/snap.ts","../packages/snap/browser.ts"],"sourcesContent":["export function debounce<CB extends (...args: unknown[]) => void>(\n callback: CB,\n delay: number\n) {\n let timer: ReturnType<typeof setTimeout> | undefined\n return function <T>(this: T, ...args: Parameters<typeof callback>): void {\n clearTimeout(timer)\n timer = setTimeout(() => {\n timer = undefined\n callback.apply(this, args)\n }, delay)\n }\n}\n","import { debounce } from './debounce'\n\nfunction removeParentSticky(element: HTMLElement) {\n const position = getComputedStyle(element).position\n\n const isSticky = position === 'sticky'\n\n if (isSticky) {\n element.style.setProperty('position', 'static')\n element.dataset.sticky = 'true'\n }\n\n if (element.offsetParent) {\n removeParentSticky(element.offsetParent as HTMLElement)\n }\n}\n\nfunction addParentSticky(element: HTMLElement) {\n if (element?.dataset?.sticky === 'true') {\n element.style.removeProperty('position')\n delete element.dataset.sticky\n }\n\n if (element.offsetParent) {\n addParentSticky(element.offsetParent as HTMLElement)\n }\n}\n\nfunction offsetTop(element: HTMLElement, accumulator = 0) {\n const top = accumulator + element.offsetTop\n if (element.offsetParent) {\n return offsetTop(element.offsetParent as HTMLElement, top)\n }\n return top\n}\n\nfunction offsetLeft(element: HTMLElement, accumulator = 0) {\n const left = accumulator + element.offsetLeft\n if (element.offsetParent) {\n return offsetLeft(element.offsetParent as HTMLElement, left)\n }\n return left\n}\n\nfunction scrollTop(element: HTMLElement, accumulator = 0) {\n const top = accumulator + element.scrollTop\n if (element.offsetParent) {\n return scrollTop(element.offsetParent as HTMLElement, top)\n }\n return top + window.scrollY\n}\n\nfunction scrollLeft(element: HTMLElement, accumulator = 0) {\n const left = accumulator + element.scrollLeft\n if (element.offsetParent) {\n return scrollLeft(element.offsetParent as HTMLElement, left)\n }\n return left + window.scrollX\n}\n\nexport type SnapElementOptions = {\n align?: string | string[]\n ignoreSticky?: boolean\n ignoreTransform?: boolean\n}\n\ntype Rect = {\n top: number\n left: number\n width: number\n height: number\n x: number\n y: number\n bottom: number\n right: number\n element: HTMLElement\n}\n\nexport class SnapElement {\n element: HTMLElement\n options: SnapElementOptions\n align: string[]\n // @ts-expect-error\n rect: Rect = {}\n wrapperResizeObserver: ResizeObserver\n resizeObserver: ResizeObserver\n debouncedWrapperResize: () => void\n\n constructor(\n element: HTMLElement,\n {\n align = ['start'],\n ignoreSticky = true,\n ignoreTransform = false,\n }: SnapElementOptions = {}\n ) {\n this.element = element\n\n this.options = { align, ignoreSticky, ignoreTransform }\n\n this.align = [align].flat()\n\n this.debouncedWrapperResize = debounce(this.onWrapperResize, 500)\n\n this.wrapperResizeObserver = new ResizeObserver(this.debouncedWrapperResize)\n this.wrapperResizeObserver.observe(document.body)\n this.onWrapperResize()\n\n this.resizeObserver = new ResizeObserver(this.onResize)\n this.resizeObserver.observe(this.element)\n this.setRect({\n width: this.element.offsetWidth,\n height: this.element.offsetHeight,\n })\n }\n\n destroy() {\n this.wrapperResizeObserver.disconnect()\n this.resizeObserver.disconnect()\n }\n\n setRect({\n top,\n left,\n width,\n height,\n element,\n }: {\n top?: number\n left?: number\n width?: number\n height?: number\n element?: HTMLElement\n } = {}) {\n top = top ?? this.rect.top\n left = left ?? this.rect.left\n width = width ?? this.rect.width\n height = height ?? this.rect.height\n element = element ?? this.rect.element\n\n if (\n top === this.rect.top &&\n left === this.rect.left &&\n width === this.rect.width &&\n height === this.rect.height &&\n element === this.rect.element\n )\n return\n\n this.rect.top = top\n this.rect.y = top\n this.rect.width = width\n this.rect.height = height\n this.rect.left = left\n this.rect.x = left\n this.rect.bottom = top + height\n this.rect.right = left + width\n }\n\n onWrapperResize = () => {\n let top: number | undefined\n let left: number | undefined\n\n if (this.options.ignoreSticky) removeParentSticky(this.element)\n if (this.options.ignoreTransform) {\n top = offsetTop(this.element)\n left = offsetLeft(this.element)\n } else {\n const rect = this.element.getBoundingClientRect()\n top = rect.top + scrollTop(this.element)\n left = rect.left + scrollLeft(this.element)\n }\n if (this.options.ignoreSticky) addParentSticky(this.element)\n\n this.setRect({ top, left })\n }\n\n onResize = ([entry]: ResizeObserverEntry[]) => {\n if (!entry?.borderBoxSize[0]) return\n const width = entry.borderBoxSize[0].inlineSize\n const height = entry.borderBoxSize[0].blockSize\n\n this.setRect({ width, height })\n }\n}\n","let index = 0\n\nexport type UID = number\n\nexport function uid(): UID {\n return index++\n}\n","import type Lenis from 'lenis'\nimport type { VirtualScrollData } from 'lenis'\nimport { debounce } from './debounce'\nimport type { SnapElementOptions } from './element'\nimport { SnapElement } from './element'\nimport type { SnapItem, SnapOptions } from './types'\nimport type { UID } from './uid'\nimport { uid } from './uid'\n\n// TODO:\n// - fix wheel scrolling after limits (see console scroll to)\n// - arrow, spacebar\n\ntype RequiredPick<T, F extends keyof T> = Omit<T, F> & Required<Pick<T, F>>\n\n/**\n * Snap class to handle the snap functionality\n *\n * @example\n * const snap = new Snap(lenis, {\n * type: 'mandatory', // 'mandatory', 'proximity' or 'lock'\n * onSnapStart: (snap) => {\n * console.log('onSnapStart', snap)\n * },\n * onSnapComplete: (snap) => {\n * console.log('onSnapComplete', snap)\n * },\n * })\n *\n * snap.add(500) // snap at 500px\n *\n * const removeSnap = snap.add(500)\n *\n * if (someCondition) {\n * removeSnap()\n * }\n */\nexport class Snap {\n options: RequiredPick<SnapOptions, 'type' | 'debounce'>\n elements = new Map<UID, SnapElement>()\n snaps = new Map<UID, SnapItem>()\n viewport: { width: number; height: number } = {\n width: window.innerWidth,\n height: window.innerHeight,\n }\n isStopped = false\n onSnapDebounced: (e: VirtualScrollData) => void\n currentSnapIndex?: number\n\n constructor(\n private lenis: Lenis,\n {\n type = 'proximity',\n lerp,\n easing,\n duration,\n distanceThreshold = '50%', // useless when type is \"mandatory\"\n debounce: debounceDelay = 500,\n onSnapStart,\n onSnapComplete,\n }: SnapOptions = {}\n ) {\n this.options = {\n type,\n lerp,\n easing,\n duration,\n distanceThreshold,\n debounce: debounceDelay,\n onSnapStart,\n onSnapComplete,\n }\n\n this.onWindowResize()\n window.addEventListener('resize', this.onWindowResize, false)\n\n this.onSnapDebounced = debounce(\n this.onSnap as (...args: unknown[]) => void,\n this.options.debounce\n )\n\n this.lenis.on('virtual-scroll', this.onSnapDebounced)\n }\n\n /**\n * Destroy the snap instance\n */\n destroy() {\n this.lenis.off('virtual-scroll', this.onSnapDebounced)\n window.removeEventListener('resize', this.onWindowResize, false)\n this.elements.forEach((element) => {\n element.destroy()\n })\n }\n\n /**\n * Start the snap after it has been stopped\n */\n start() {\n this.isStopped = false\n }\n\n /**\n * Stop the snap\n */\n stop() {\n this.isStopped = true\n }\n\n /**\n * Add a snap to the snap instance\n *\n * @param value The value to snap to\n * @param userData User data that will be forwarded through the snap event\n * @returns Unsubscribe function\n */\n add(value: number): () => void {\n const id = uid()\n\n this.snaps.set(id, { value })\n\n return () => this.snaps.delete(id)\n }\n\n /**\n * Add an element to the snap instance\n *\n * @param element The element to add\n * @param options The options for the element\n * @returns Unsubscribe function\n */\n addElement(\n element: HTMLElement,\n options: SnapElementOptions = {}\n ): () => void {\n const id = uid()\n\n this.elements.set(id, new SnapElement(element, options))\n\n return () => this.elements.delete(id)\n }\n\n addElements(\n elements: HTMLElement[],\n options: SnapElementOptions = {}\n ): () => void {\n const map = [...elements].map((element) =>\n this.addElement(element, options)\n )\n return () => {\n map.forEach((remove) => {\n remove()\n })\n }\n }\n\n private onWindowResize = () => {\n this.viewport.width = window.innerWidth\n this.viewport.height = window.innerHeight\n }\n\n private computeSnaps = () => {\n const { isHorizontal } = this.lenis\n\n let snaps = [...this.snaps.values()] as SnapItem[]\n\n this.elements.forEach(({ rect, align }) => {\n let value: number | undefined\n\n align.forEach((align) => {\n if (align === 'start') {\n value = rect.top\n } else if (align === 'center') {\n value = isHorizontal\n ? rect.left + rect.width / 2 - this.viewport.width / 2\n : rect.top + rect.height / 2 - this.viewport.height / 2\n } else if (align === 'end') {\n value = isHorizontal\n ? rect.left + rect.width - this.viewport.width\n : rect.top + rect.height - this.viewport.height\n }\n\n if (typeof value === 'number') {\n snaps.push({ value: Math.ceil(value) })\n }\n })\n })\n\n snaps = snaps.sort((a, b) => Math.abs(a.value) - Math.abs(b.value))\n\n return snaps\n }\n\n previous() {\n this.goTo((this.currentSnapIndex ?? 0) - 1)\n }\n\n next() {\n this.goTo((this.currentSnapIndex ?? 0) + 1)\n }\n\n goTo(index: number) {\n const snaps = this.computeSnaps()\n\n if (snaps.length === 0) return\n\n this.currentSnapIndex = Math.max(0, Math.min(index, snaps.length - 1))\n\n const currentSnap = snaps[this.currentSnapIndex]\n if (currentSnap === undefined) return\n\n this.lenis.scrollTo(currentSnap.value, {\n duration: this.options.duration,\n easing: this.options.easing,\n lerp: this.options.lerp,\n lock: this.options.type === 'lock',\n userData: { initiator: 'snap' },\n onStart: () => {\n this.options.onSnapStart?.({\n index: this.currentSnapIndex,\n ...currentSnap,\n })\n },\n onComplete: () => {\n this.options.onSnapComplete?.({\n index: this.currentSnapIndex,\n ...currentSnap,\n })\n },\n })\n }\n\n get distanceThreshold() {\n let distanceThreshold = Number.POSITIVE_INFINITY\n if (this.options.type === 'mandatory') return Number.POSITIVE_INFINITY\n\n const { isHorizontal } = this.lenis\n\n const axis = isHorizontal ? 'width' : 'height'\n\n if (\n typeof this.options.distanceThreshold === 'string' &&\n this.options.distanceThreshold.endsWith('%')\n ) {\n distanceThreshold =\n (Number(this.options.distanceThreshold.replace('%', '')) / 100) *\n this.viewport[axis]\n } else if (typeof this.options.distanceThreshold === 'number') {\n distanceThreshold = this.options.distanceThreshold\n } else {\n distanceThreshold = this.viewport[axis]\n }\n\n return distanceThreshold\n }\n\n private onSnap = (e: VirtualScrollData) => {\n if (this.isStopped) return\n\n if (e.event.type === 'touchmove') return\n\n if (\n this.options.type === 'lock' &&\n this.lenis.userData?.initiator === 'snap'\n )\n return\n\n let { scroll, isHorizontal } = this.lenis\n const delta = isHorizontal ? e.deltaX : e.deltaY\n scroll = Math.ceil(this.lenis.scroll + delta)\n\n const snaps = this.computeSnaps()\n\n if (snaps.length === 0) return\n\n let snapIndex: number | undefined\n\n const prevSnapIndex = snaps.findLastIndex(({ value }) => value < scroll)\n const nextSnapIndex = snaps.findIndex(({ value }) => value > scroll)\n\n if (this.options.type === 'lock') {\n if (delta > 0) {\n snapIndex = nextSnapIndex\n } else if (delta < 0) {\n snapIndex = prevSnapIndex\n }\n } else {\n const prevSnap = snaps[prevSnapIndex]!\n const distanceToPrevSnap = prevSnap\n ? Math.abs(scroll - prevSnap.value)\n : Number.POSITIVE_INFINITY\n\n const nextSnap = snaps[nextSnapIndex]!\n const distanceToNextSnap = nextSnap\n ? Math.abs(scroll - nextSnap.value)\n : Number.POSITIVE_INFINITY\n snapIndex =\n distanceToPrevSnap < distanceToNextSnap ? prevSnapIndex : nextSnapIndex\n }\n\n if (snapIndex === undefined) return\n if (snapIndex === -1) return\n\n snapIndex = Math.max(0, Math.min(snapIndex, snaps.length - 1))\n\n const snap = snaps[snapIndex]!\n\n const distance = Math.abs(scroll - snap.value)\n\n if (distance <= this.distanceThreshold) {\n this.goTo(snapIndex)\n }\n }\n\n resize() {\n this.elements.forEach((element) => {\n element.onWrapperResize()\n })\n }\n}\n","// This file serves as an entry point for the package\nimport { Snap } from './src/snap'\n\n// @ts-expect-error\nglobalThis.Snap = Snap\n"],"mappings":"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","names":["align","index"]}
|
|
1
|
+
{"version":3,"sources":["../packages/snap/src/debounce.ts","../packages/snap/src/element.ts","../packages/snap/src/uid.ts","../packages/snap/src/snap.ts","../packages/snap/browser.ts"],"sourcesContent":["export function debounce<CB extends (...args: unknown[]) => void>(\n callback: CB,\n delay: number\n) {\n let timer: ReturnType<typeof setTimeout> | undefined\n return function <T>(this: T, ...args: Parameters<typeof callback>): void {\n clearTimeout(timer)\n timer = setTimeout(() => {\n timer = undefined\n callback.apply(this, args)\n }, delay)\n }\n}\n","import { debounce } from './debounce'\n\nfunction removeParentSticky(element: HTMLElement) {\n const position = getComputedStyle(element).position\n\n const isSticky = position === 'sticky'\n\n if (isSticky) {\n element.style.setProperty('position', 'static')\n element.dataset.sticky = 'true'\n }\n\n if (element.offsetParent) {\n removeParentSticky(element.offsetParent as HTMLElement)\n }\n}\n\nfunction addParentSticky(element: HTMLElement) {\n if (element?.dataset?.sticky === 'true') {\n element.style.removeProperty('position')\n delete element.dataset.sticky\n }\n\n if (element.offsetParent) {\n addParentSticky(element.offsetParent as HTMLElement)\n }\n}\n\nfunction offsetTop(element: HTMLElement, accumulator = 0) {\n const top = accumulator + element.offsetTop\n if (element.offsetParent) {\n return offsetTop(element.offsetParent as HTMLElement, top)\n }\n return top\n}\n\nfunction offsetLeft(element: HTMLElement, accumulator = 0) {\n const left = accumulator + element.offsetLeft\n if (element.offsetParent) {\n return offsetLeft(element.offsetParent as HTMLElement, left)\n }\n return left\n}\n\nfunction scrollTop(element: HTMLElement, accumulator = 0) {\n const top = accumulator + element.scrollTop\n if (element.offsetParent) {\n return scrollTop(element.offsetParent as HTMLElement, top)\n }\n return top + window.scrollY\n}\n\nfunction scrollLeft(element: HTMLElement, accumulator = 0) {\n const left = accumulator + element.scrollLeft\n if (element.offsetParent) {\n return scrollLeft(element.offsetParent as HTMLElement, left)\n }\n return left + window.scrollX\n}\n\nexport type SnapElementOptions = {\n align?: string | string[]\n ignoreSticky?: boolean\n ignoreTransform?: boolean\n}\n\ntype Rect = {\n top: number\n left: number\n width: number\n height: number\n x: number\n y: number\n bottom: number\n right: number\n element: HTMLElement\n}\n\nexport class SnapElement {\n element: HTMLElement\n options: SnapElementOptions\n align: string[]\n // @ts-expect-error\n rect: Rect = {}\n wrapperResizeObserver: ResizeObserver\n resizeObserver: ResizeObserver\n debouncedWrapperResize: () => void\n\n constructor(\n element: HTMLElement,\n {\n align = ['start'],\n ignoreSticky = true,\n ignoreTransform = false,\n }: SnapElementOptions = {}\n ) {\n this.element = element\n\n this.options = { align, ignoreSticky, ignoreTransform }\n\n this.align = [align].flat()\n\n this.debouncedWrapperResize = debounce(this.onWrapperResize, 500)\n\n this.wrapperResizeObserver = new ResizeObserver(this.debouncedWrapperResize)\n this.wrapperResizeObserver.observe(document.body)\n this.onWrapperResize()\n\n this.resizeObserver = new ResizeObserver(this.onResize)\n this.resizeObserver.observe(this.element)\n this.setRect({\n width: this.element.offsetWidth,\n height: this.element.offsetHeight,\n })\n }\n\n destroy() {\n this.wrapperResizeObserver.disconnect()\n this.resizeObserver.disconnect()\n }\n\n setRect({\n top,\n left,\n width,\n height,\n element,\n }: {\n top?: number\n left?: number\n width?: number\n height?: number\n element?: HTMLElement\n } = {}) {\n top = top ?? this.rect.top\n left = left ?? this.rect.left\n width = width ?? this.rect.width\n height = height ?? this.rect.height\n element = element ?? this.rect.element\n\n if (\n top === this.rect.top &&\n left === this.rect.left &&\n width === this.rect.width &&\n height === this.rect.height &&\n element === this.rect.element\n )\n return\n\n this.rect.top = top\n this.rect.y = top\n this.rect.width = width\n this.rect.height = height\n this.rect.left = left\n this.rect.x = left\n this.rect.bottom = top + height\n this.rect.right = left + width\n }\n\n onWrapperResize = () => {\n let top: number | undefined\n let left: number | undefined\n\n if (this.options.ignoreSticky) removeParentSticky(this.element)\n if (this.options.ignoreTransform) {\n top = offsetTop(this.element)\n left = offsetLeft(this.element)\n } else {\n const rect = this.element.getBoundingClientRect()\n top = rect.top + scrollTop(this.element)\n left = rect.left + scrollLeft(this.element)\n }\n if (this.options.ignoreSticky) addParentSticky(this.element)\n\n this.setRect({ top, left })\n }\n\n onResize = ([entry]: ResizeObserverEntry[]) => {\n if (!entry?.borderBoxSize[0]) return\n const width = entry.borderBoxSize[0].inlineSize\n const height = entry.borderBoxSize[0].blockSize\n\n this.setRect({ width, height })\n }\n}\n","let index = 0\n\nexport type UID = number\n\nexport function uid(): UID {\n return index++\n}\n","import type Lenis from 'lenis'\nimport type { VirtualScrollData } from 'lenis'\nimport { debounce } from './debounce'\nimport type { SnapElementOptions } from './element'\nimport { SnapElement } from './element'\nimport type { SnapItem, SnapOptions } from './types'\nimport type { UID } from './uid'\nimport { uid } from './uid'\n\n// TODO:\n// - fix wheel scrolling after limits (see console scroll to)\n// - arrow, spacebar\n\ntype RequiredPick<T, F extends keyof T> = Omit<T, F> & Required<Pick<T, F>>\n\n/**\n * Snap class to handle the snap functionality\n *\n * @example\n * const snap = new Snap(lenis, {\n * type: 'mandatory', // 'mandatory', 'proximity' or 'lock'\n * onSnapStart: (snap) => {\n * console.log('onSnapStart', snap)\n * },\n * onSnapComplete: (snap) => {\n * console.log('onSnapComplete', snap)\n * },\n * })\n *\n * snap.add(500) // snap at 500px\n *\n * const removeSnap = snap.add(500)\n *\n * if (someCondition) {\n * removeSnap()\n * }\n */\nexport class Snap {\n options: RequiredPick<SnapOptions, 'type' | 'debounce'>\n elements = new Map<UID, SnapElement>()\n snaps = new Map<UID, SnapItem>()\n viewport: { width: number; height: number } = {\n width: window.innerWidth,\n height: window.innerHeight,\n }\n isStopped = false\n onSnapDebounced: (e: VirtualScrollData) => void\n currentSnapIndex?: number\n\n constructor(\n private lenis: Lenis,\n {\n type = 'proximity',\n lerp,\n easing,\n duration,\n distanceThreshold = '50%', // useless when type is \"mandatory\"\n debounce: debounceDelay = 500,\n onSnapStart,\n onSnapComplete,\n }: SnapOptions = {}\n ) {\n if (!window.lenis) {\n window.lenis = {}\n }\n\n window.lenis.snap = true\n\n this.options = {\n type,\n lerp,\n easing,\n duration,\n distanceThreshold,\n debounce: debounceDelay,\n onSnapStart,\n onSnapComplete,\n }\n\n this.onWindowResize()\n window.addEventListener('resize', this.onWindowResize)\n\n this.onSnapDebounced = debounce(\n this.onSnap as (...args: unknown[]) => void,\n this.options.debounce\n )\n\n this.lenis.on('virtual-scroll', this.onSnapDebounced)\n }\n\n /**\n * Destroy the snap instance\n */\n destroy() {\n this.lenis.off('virtual-scroll', this.onSnapDebounced)\n window.removeEventListener('resize', this.onWindowResize)\n this.elements.forEach((element) => {\n element.destroy()\n })\n }\n\n /**\n * Start the snap after it has been stopped\n */\n start() {\n this.isStopped = false\n }\n\n /**\n * Stop the snap\n */\n stop() {\n this.isStopped = true\n }\n\n /**\n * Add a snap to the snap instance\n *\n * @param value The value to snap to\n * @param userData User data that will be forwarded through the snap event\n * @returns Unsubscribe function\n */\n add(value: number): () => void {\n const id = uid()\n\n this.snaps.set(id, { value })\n\n return () => this.snaps.delete(id)\n }\n\n /**\n * Add an element to the snap instance\n *\n * @param element The element to add\n * @param options The options for the element\n * @returns Unsubscribe function\n */\n addElement(\n element: HTMLElement,\n options: SnapElementOptions = {}\n ): () => void {\n const id = uid()\n\n this.elements.set(id, new SnapElement(element, options))\n\n return () => this.elements.delete(id)\n }\n\n addElements(\n elements: HTMLElement[],\n options: SnapElementOptions = {}\n ): () => void {\n const map = [...elements].map((element) =>\n this.addElement(element, options)\n )\n return () => {\n map.forEach((remove) => {\n remove()\n })\n }\n }\n\n private onWindowResize = () => {\n this.viewport.width = window.innerWidth\n this.viewport.height = window.innerHeight\n }\n\n private computeSnaps = () => {\n const { isHorizontal } = this.lenis\n\n let snaps = [...this.snaps.values()] as SnapItem[]\n\n this.elements.forEach(({ rect, align }) => {\n let value: number | undefined\n\n align.forEach((align) => {\n if (align === 'start') {\n value = rect.top\n } else if (align === 'center') {\n value = isHorizontal\n ? rect.left + rect.width / 2 - this.viewport.width / 2\n : rect.top + rect.height / 2 - this.viewport.height / 2\n } else if (align === 'end') {\n value = isHorizontal\n ? rect.left + rect.width - this.viewport.width\n : rect.top + rect.height - this.viewport.height\n }\n\n if (typeof value === 'number') {\n snaps.push({ value: Math.ceil(value) })\n }\n })\n })\n\n snaps = snaps.sort((a, b) => Math.abs(a.value) - Math.abs(b.value))\n\n return snaps\n }\n\n previous() {\n this.goTo((this.currentSnapIndex ?? 0) - 1)\n }\n\n next() {\n this.goTo((this.currentSnapIndex ?? 0) + 1)\n }\n\n goTo(index: number) {\n const snaps = this.computeSnaps()\n\n if (snaps.length === 0) return\n\n this.currentSnapIndex = Math.max(0, Math.min(index, snaps.length - 1))\n\n const currentSnap = snaps[this.currentSnapIndex]\n if (currentSnap === undefined) return\n\n this.lenis.scrollTo(currentSnap.value, {\n duration: this.options.duration,\n easing: this.options.easing,\n lerp: this.options.lerp,\n lock: this.options.type === 'lock',\n userData: { initiator: 'snap' },\n onStart: () => {\n this.options.onSnapStart?.({\n index: this.currentSnapIndex,\n ...currentSnap,\n })\n },\n onComplete: () => {\n this.options.onSnapComplete?.({\n index: this.currentSnapIndex,\n ...currentSnap,\n })\n },\n })\n }\n\n get distanceThreshold() {\n let distanceThreshold = Number.POSITIVE_INFINITY\n if (this.options.type === 'mandatory') return Number.POSITIVE_INFINITY\n\n const { isHorizontal } = this.lenis\n\n const axis = isHorizontal ? 'width' : 'height'\n\n if (\n typeof this.options.distanceThreshold === 'string' &&\n this.options.distanceThreshold.endsWith('%')\n ) {\n distanceThreshold =\n (Number(this.options.distanceThreshold.replace('%', '')) / 100) *\n this.viewport[axis]\n } else if (typeof this.options.distanceThreshold === 'number') {\n distanceThreshold = this.options.distanceThreshold\n } else {\n distanceThreshold = this.viewport[axis]\n }\n\n return distanceThreshold\n }\n\n private onSnap = (e: VirtualScrollData) => {\n if (this.isStopped) return\n\n if (e.event.type === 'touchmove') return\n\n if (\n this.options.type === 'lock' &&\n this.lenis.userData?.initiator === 'snap'\n )\n return\n\n let { scroll, isHorizontal } = this.lenis\n const delta = isHorizontal ? e.deltaX : e.deltaY\n scroll = Math.ceil(this.lenis.scroll + delta)\n\n const snaps = this.computeSnaps()\n\n if (snaps.length === 0) return\n\n let snapIndex: number | undefined\n\n const prevSnapIndex = snaps.findLastIndex(({ value }) => value < scroll)\n const nextSnapIndex = snaps.findIndex(({ value }) => value > scroll)\n\n if (this.options.type === 'lock') {\n if (delta > 0) {\n snapIndex = nextSnapIndex\n } else if (delta < 0) {\n snapIndex = prevSnapIndex\n }\n } else {\n const prevSnap = snaps[prevSnapIndex]!\n const distanceToPrevSnap = prevSnap\n ? Math.abs(scroll - prevSnap.value)\n : Number.POSITIVE_INFINITY\n\n const nextSnap = snaps[nextSnapIndex]!\n const distanceToNextSnap = nextSnap\n ? Math.abs(scroll - nextSnap.value)\n : Number.POSITIVE_INFINITY\n snapIndex =\n distanceToPrevSnap < distanceToNextSnap ? prevSnapIndex : nextSnapIndex\n }\n\n if (snapIndex === undefined) return\n if (snapIndex === -1) return\n\n snapIndex = Math.max(0, Math.min(snapIndex, snaps.length - 1))\n\n const snap = snaps[snapIndex]!\n\n const distance = Math.abs(scroll - snap.value)\n\n if (distance <= this.distanceThreshold) {\n this.goTo(snapIndex)\n }\n }\n\n resize() {\n this.elements.forEach((element) => {\n element.onWrapperResize()\n })\n }\n}\n","// This file serves as an entry point for the package\nimport { Snap } from './src/snap'\n\n// @ts-expect-error\nglobalThis.Snap = Snap\n"],"mappings":"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","names":["align","index"]}
|
package/dist/lenis-snap.min.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
function e(e,t){let i;return function(...s){clearTimeout(i),i=setTimeout(()=>{i=void 0,e.apply(this,s)},t)}}function t(e){"sticky"===getComputedStyle(e).position&&(e.style.setProperty("position","static"),e.dataset.sticky="true"),e.offsetParent&&t(e.offsetParent)}function i(e){"true"===e?.dataset?.sticky&&(e.style.removeProperty("position"),delete e.dataset.sticky),e.offsetParent&&i(e.offsetParent)}function s(e,t=0){const i=t+e.offsetTop;return e.offsetParent?s(e.offsetParent,i):i}function n(e,t=0){const i=t+e.offsetLeft;return e.offsetParent?n(e.offsetParent,i):i}function o(e,t=0){const i=t+e.scrollTop;return e.offsetParent?o(e.offsetParent,i):i+window.scrollY}function r(e,t=0){const i=t+e.scrollLeft;return e.offsetParent?r(e.offsetParent,i):i+window.scrollX}var h=class{element;options;align;rect={};wrapperResizeObserver;resizeObserver;debouncedWrapperResize;constructor(t,{align:i=["start"],ignoreSticky:s=!0,ignoreTransform:n=!1}={}){this.element=t,this.options={align:i,ignoreSticky:s,ignoreTransform:n},this.align=[i].flat(),this.debouncedWrapperResize=e(this.onWrapperResize,500),this.wrapperResizeObserver=new ResizeObserver(this.debouncedWrapperResize),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:e,left:t,width:i,height:s,element:n}={}){e=e??this.rect.top,t=t??this.rect.left,i=i??this.rect.width,s=s??this.rect.height,n=n??this.rect.element,e===this.rect.top&&t===this.rect.left&&i===this.rect.width&&s===this.rect.height&&n===this.rect.element||(this.rect.top=e,this.rect.y=e,this.rect.width=i,this.rect.height=s,this.rect.left=t,this.rect.x=t,this.rect.bottom=e+s,this.rect.right=t+i)}onWrapperResize=()=>{let e,h;if(this.options.ignoreSticky&&t(this.element),this.options.ignoreTransform)e=s(this.element),h=n(this.element);else{const t=this.element.getBoundingClientRect();e=t.top+o(this.element),h=t.left+r(this.element)}this.options.ignoreSticky&&i(this.element),this.setRect({top:e,left:h})};onResize=([e])=>{if(!e?.borderBoxSize[0])return;const t=e.borderBoxSize[0].inlineSize,i=e.borderBoxSize[0].blockSize;this.setRect({width:t,height:i})}},a=0;function p(){return a++}globalThis.Snap=class{constructor(t,{type:i="proximity",lerp:s,easing:n,duration:o,distanceThreshold:r="50%",debounce:h=500,onSnapStart:a,onSnapComplete:p}={}){this.lenis=t,this.options={type:i,lerp:s,easing:n,duration:o,distanceThreshold:r,debounce:h,onSnapStart:a,onSnapComplete:p},this.onWindowResize(),window.addEventListener("resize",this.onWindowResize
|
|
1
|
+
function e(e,t){let i;return function(...s){clearTimeout(i),i=setTimeout(()=>{i=void 0,e.apply(this,s)},t)}}function t(e){"sticky"===getComputedStyle(e).position&&(e.style.setProperty("position","static"),e.dataset.sticky="true"),e.offsetParent&&t(e.offsetParent)}function i(e){"true"===e?.dataset?.sticky&&(e.style.removeProperty("position"),delete e.dataset.sticky),e.offsetParent&&i(e.offsetParent)}function s(e,t=0){const i=t+e.offsetTop;return e.offsetParent?s(e.offsetParent,i):i}function n(e,t=0){const i=t+e.offsetLeft;return e.offsetParent?n(e.offsetParent,i):i}function o(e,t=0){const i=t+e.scrollTop;return e.offsetParent?o(e.offsetParent,i):i+window.scrollY}function r(e,t=0){const i=t+e.scrollLeft;return e.offsetParent?r(e.offsetParent,i):i+window.scrollX}var h=class{element;options;align;rect={};wrapperResizeObserver;resizeObserver;debouncedWrapperResize;constructor(t,{align:i=["start"],ignoreSticky:s=!0,ignoreTransform:n=!1}={}){this.element=t,this.options={align:i,ignoreSticky:s,ignoreTransform:n},this.align=[i].flat(),this.debouncedWrapperResize=e(this.onWrapperResize,500),this.wrapperResizeObserver=new ResizeObserver(this.debouncedWrapperResize),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:e,left:t,width:i,height:s,element:n}={}){e=e??this.rect.top,t=t??this.rect.left,i=i??this.rect.width,s=s??this.rect.height,n=n??this.rect.element,e===this.rect.top&&t===this.rect.left&&i===this.rect.width&&s===this.rect.height&&n===this.rect.element||(this.rect.top=e,this.rect.y=e,this.rect.width=i,this.rect.height=s,this.rect.left=t,this.rect.x=t,this.rect.bottom=e+s,this.rect.right=t+i)}onWrapperResize=()=>{let e,h;if(this.options.ignoreSticky&&t(this.element),this.options.ignoreTransform)e=s(this.element),h=n(this.element);else{const t=this.element.getBoundingClientRect();e=t.top+o(this.element),h=t.left+r(this.element)}this.options.ignoreSticky&&i(this.element),this.setRect({top:e,left:h})};onResize=([e])=>{if(!e?.borderBoxSize[0])return;const t=e.borderBoxSize[0].inlineSize,i=e.borderBoxSize[0].blockSize;this.setRect({width:t,height:i})}},a=0;function p(){return a++}globalThis.Snap=class{constructor(t,{type:i="proximity",lerp:s,easing:n,duration:o,distanceThreshold:r="50%",debounce:h=500,onSnapStart:a,onSnapComplete:p}={}){this.lenis=t,window.lenis||(window.lenis={}),window.lenis.snap=!0,this.options={type:i,lerp:s,easing:n,duration:o,distanceThreshold:r,debounce:h,onSnapStart:a,onSnapComplete:p},this.onWindowResize(),window.addEventListener("resize",this.onWindowResize),this.onSnapDebounced=e(this.onSnap,this.options.debounce),this.lenis.on("virtual-scroll",this.onSnapDebounced)}options;elements=new Map;snaps=new Map;viewport={width:window.innerWidth,height:window.innerHeight};isStopped=!1;onSnapDebounced;currentSnapIndex;destroy(){this.lenis.off("virtual-scroll",this.onSnapDebounced),window.removeEventListener("resize",this.onWindowResize),this.elements.forEach(e=>{e.destroy()})}start(){this.isStopped=!1}stop(){this.isStopped=!0}add(e){const t=p();return this.snaps.set(t,{value:e}),()=>this.snaps.delete(t)}addElement(e,t={}){const i=p();return this.elements.set(i,new h(e,t)),()=>this.elements.delete(i)}addElements(e,t={}){const i=[...e].map(e=>this.addElement(e,t));return()=>{i.forEach(e=>{e()})}}onWindowResize=()=>{this.viewport.width=window.innerWidth,this.viewport.height=window.innerHeight};computeSnaps=()=>{const{isHorizontal:e}=this.lenis;let t=[...this.snaps.values()];return this.elements.forEach(({rect:i,align:s})=>{let n;s.forEach(s=>{"start"===s?n=i.top:"center"===s?n=e?i.left+i.width/2-this.viewport.width/2:i.top+i.height/2-this.viewport.height/2:"end"===s&&(n=e?i.left+i.width-this.viewport.width:i.top+i.height-this.viewport.height),"number"==typeof n&&t.push({value:Math.ceil(n)})})}),t=t.sort((e,t)=>Math.abs(e.value)-Math.abs(t.value)),t};previous(){this.goTo((this.currentSnapIndex??0)-1)}next(){this.goTo((this.currentSnapIndex??0)+1)}goTo(e){const t=this.computeSnaps();if(0===t.length)return;this.currentSnapIndex=Math.max(0,Math.min(e,t.length-1));const i=t[this.currentSnapIndex];void 0!==i&&this.lenis.scrollTo(i.value,{duration:this.options.duration,easing:this.options.easing,lerp:this.options.lerp,lock:"lock"===this.options.type,userData:{initiator:"snap"},onStart:()=>{this.options.onSnapStart?.({index:this.currentSnapIndex,...i})},onComplete:()=>{this.options.onSnapComplete?.({index:this.currentSnapIndex,...i})}})}get distanceThreshold(){let e=Number.POSITIVE_INFINITY;if("mandatory"===this.options.type)return Number.POSITIVE_INFINITY;const{isHorizontal:t}=this.lenis,i=t?"width":"height";return e="string"==typeof this.options.distanceThreshold&&this.options.distanceThreshold.endsWith("%")?Number(this.options.distanceThreshold.replace("%",""))/100*this.viewport[i]:"number"==typeof this.options.distanceThreshold?this.options.distanceThreshold:this.viewport[i],e}onSnap=e=>{if(this.isStopped)return;if("touchmove"===e.event.type)return;if("lock"===this.options.type&&"snap"===this.lenis.userData?.initiator)return;let{scroll:t,isHorizontal:i}=this.lenis;const s=i?e.deltaX:e.deltaY;t=Math.ceil(this.lenis.scroll+s);const n=this.computeSnaps();if(0===n.length)return;let o;const r=n.findLastIndex(({value:e})=>e<t),h=n.findIndex(({value:e})=>e>t);if("lock"===this.options.type)s>0?o=h:s<0&&(o=r);else{const e=n[r],i=e?Math.abs(t-e.value):Number.POSITIVE_INFINITY,s=n[h];o=i<(s?Math.abs(t-s.value):Number.POSITIVE_INFINITY)?r:h}if(void 0===o)return;if(-1===o)return;o=Math.max(0,Math.min(o,n.length-1));const a=n[o];Math.abs(t-a.value)<=this.distanceThreshold&&this.goTo(o)};resize(){this.elements.forEach(e=>{e.onWrapperResize()})}};//# sourceMappingURL=lenis-snap.min.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../packages/snap/src/debounce.ts","../packages/snap/src/element.ts","../packages/snap/src/uid.ts","../packages/snap/src/snap.ts","../packages/snap/browser.ts"],"sourcesContent":["export function debounce<CB extends (...args: unknown[]) => void>(\n callback: CB,\n delay: number\n) {\n let timer: ReturnType<typeof setTimeout> | undefined\n return function <T>(this: T, ...args: Parameters<typeof callback>): void {\n clearTimeout(timer)\n timer = setTimeout(() => {\n timer = undefined\n callback.apply(this, args)\n }, delay)\n }\n}\n","import { debounce } from './debounce'\n\nfunction removeParentSticky(element: HTMLElement) {\n const position = getComputedStyle(element).position\n\n const isSticky = position === 'sticky'\n\n if (isSticky) {\n element.style.setProperty('position', 'static')\n element.dataset.sticky = 'true'\n }\n\n if (element.offsetParent) {\n removeParentSticky(element.offsetParent as HTMLElement)\n }\n}\n\nfunction addParentSticky(element: HTMLElement) {\n if (element?.dataset?.sticky === 'true') {\n element.style.removeProperty('position')\n delete element.dataset.sticky\n }\n\n if (element.offsetParent) {\n addParentSticky(element.offsetParent as HTMLElement)\n }\n}\n\nfunction offsetTop(element: HTMLElement, accumulator = 0) {\n const top = accumulator + element.offsetTop\n if (element.offsetParent) {\n return offsetTop(element.offsetParent as HTMLElement, top)\n }\n return top\n}\n\nfunction offsetLeft(element: HTMLElement, accumulator = 0) {\n const left = accumulator + element.offsetLeft\n if (element.offsetParent) {\n return offsetLeft(element.offsetParent as HTMLElement, left)\n }\n return left\n}\n\nfunction scrollTop(element: HTMLElement, accumulator = 0) {\n const top = accumulator + element.scrollTop\n if (element.offsetParent) {\n return scrollTop(element.offsetParent as HTMLElement, top)\n }\n return top + window.scrollY\n}\n\nfunction scrollLeft(element: HTMLElement, accumulator = 0) {\n const left = accumulator + element.scrollLeft\n if (element.offsetParent) {\n return scrollLeft(element.offsetParent as HTMLElement, left)\n }\n return left + window.scrollX\n}\n\nexport type SnapElementOptions = {\n align?: string | string[]\n ignoreSticky?: boolean\n ignoreTransform?: boolean\n}\n\ntype Rect = {\n top: number\n left: number\n width: number\n height: number\n x: number\n y: number\n bottom: number\n right: number\n element: HTMLElement\n}\n\nexport class SnapElement {\n element: HTMLElement\n options: SnapElementOptions\n align: string[]\n // @ts-expect-error\n rect: Rect = {}\n wrapperResizeObserver: ResizeObserver\n resizeObserver: ResizeObserver\n debouncedWrapperResize: () => void\n\n constructor(\n element: HTMLElement,\n {\n align = ['start'],\n ignoreSticky = true,\n ignoreTransform = false,\n }: SnapElementOptions = {}\n ) {\n this.element = element\n\n this.options = { align, ignoreSticky, ignoreTransform }\n\n this.align = [align].flat()\n\n this.debouncedWrapperResize = debounce(this.onWrapperResize, 500)\n\n this.wrapperResizeObserver = new ResizeObserver(this.debouncedWrapperResize)\n this.wrapperResizeObserver.observe(document.body)\n this.onWrapperResize()\n\n this.resizeObserver = new ResizeObserver(this.onResize)\n this.resizeObserver.observe(this.element)\n this.setRect({\n width: this.element.offsetWidth,\n height: this.element.offsetHeight,\n })\n }\n\n destroy() {\n this.wrapperResizeObserver.disconnect()\n this.resizeObserver.disconnect()\n }\n\n setRect({\n top,\n left,\n width,\n height,\n element,\n }: {\n top?: number\n left?: number\n width?: number\n height?: number\n element?: HTMLElement\n } = {}) {\n top = top ?? this.rect.top\n left = left ?? this.rect.left\n width = width ?? this.rect.width\n height = height ?? this.rect.height\n element = element ?? this.rect.element\n\n if (\n top === this.rect.top &&\n left === this.rect.left &&\n width === this.rect.width &&\n height === this.rect.height &&\n element === this.rect.element\n )\n return\n\n this.rect.top = top\n this.rect.y = top\n this.rect.width = width\n this.rect.height = height\n this.rect.left = left\n this.rect.x = left\n this.rect.bottom = top + height\n this.rect.right = left + width\n }\n\n onWrapperResize = () => {\n let top: number | undefined\n let left: number | undefined\n\n if (this.options.ignoreSticky) removeParentSticky(this.element)\n if (this.options.ignoreTransform) {\n top = offsetTop(this.element)\n left = offsetLeft(this.element)\n } else {\n const rect = this.element.getBoundingClientRect()\n top = rect.top + scrollTop(this.element)\n left = rect.left + scrollLeft(this.element)\n }\n if (this.options.ignoreSticky) addParentSticky(this.element)\n\n this.setRect({ top, left })\n }\n\n onResize = ([entry]: ResizeObserverEntry[]) => {\n if (!entry?.borderBoxSize[0]) return\n const width = entry.borderBoxSize[0].inlineSize\n const height = entry.borderBoxSize[0].blockSize\n\n this.setRect({ width, height })\n }\n}\n","let index = 0\n\nexport type UID = number\n\nexport function uid(): UID {\n return index++\n}\n","import type Lenis from 'lenis'\nimport type { VirtualScrollData } from 'lenis'\nimport { debounce } from './debounce'\nimport type { SnapElementOptions } from './element'\nimport { SnapElement } from './element'\nimport type { SnapItem, SnapOptions } from './types'\nimport type { UID } from './uid'\nimport { uid } from './uid'\n\n// TODO:\n// - fix wheel scrolling after limits (see console scroll to)\n// - arrow, spacebar\n\ntype RequiredPick<T, F extends keyof T> = Omit<T, F> & Required<Pick<T, F>>\n\n/**\n * Snap class to handle the snap functionality\n *\n * @example\n * const snap = new Snap(lenis, {\n * type: 'mandatory', // 'mandatory', 'proximity' or 'lock'\n * onSnapStart: (snap) => {\n * console.log('onSnapStart', snap)\n * },\n * onSnapComplete: (snap) => {\n * console.log('onSnapComplete', snap)\n * },\n * })\n *\n * snap.add(500) // snap at 500px\n *\n * const removeSnap = snap.add(500)\n *\n * if (someCondition) {\n * removeSnap()\n * }\n */\nexport class Snap {\n options: RequiredPick<SnapOptions, 'type' | 'debounce'>\n elements = new Map<UID, SnapElement>()\n snaps = new Map<UID, SnapItem>()\n viewport: { width: number; height: number } = {\n width: window.innerWidth,\n height: window.innerHeight,\n }\n isStopped = false\n onSnapDebounced: (e: VirtualScrollData) => void\n currentSnapIndex?: number\n\n constructor(\n private lenis: Lenis,\n {\n type = 'proximity',\n lerp,\n easing,\n duration,\n distanceThreshold = '50%', // useless when type is \"mandatory\"\n debounce: debounceDelay = 500,\n onSnapStart,\n onSnapComplete,\n }: SnapOptions = {}\n ) {\n this.options = {\n type,\n lerp,\n easing,\n duration,\n distanceThreshold,\n debounce: debounceDelay,\n onSnapStart,\n onSnapComplete,\n }\n\n this.onWindowResize()\n window.addEventListener('resize', this.onWindowResize, false)\n\n this.onSnapDebounced = debounce(\n this.onSnap as (...args: unknown[]) => void,\n this.options.debounce\n )\n\n this.lenis.on('virtual-scroll', this.onSnapDebounced)\n }\n\n /**\n * Destroy the snap instance\n */\n destroy() {\n this.lenis.off('virtual-scroll', this.onSnapDebounced)\n window.removeEventListener('resize', this.onWindowResize, false)\n this.elements.forEach((element) => {\n element.destroy()\n })\n }\n\n /**\n * Start the snap after it has been stopped\n */\n start() {\n this.isStopped = false\n }\n\n /**\n * Stop the snap\n */\n stop() {\n this.isStopped = true\n }\n\n /**\n * Add a snap to the snap instance\n *\n * @param value The value to snap to\n * @param userData User data that will be forwarded through the snap event\n * @returns Unsubscribe function\n */\n add(value: number): () => void {\n const id = uid()\n\n this.snaps.set(id, { value })\n\n return () => this.snaps.delete(id)\n }\n\n /**\n * Add an element to the snap instance\n *\n * @param element The element to add\n * @param options The options for the element\n * @returns Unsubscribe function\n */\n addElement(\n element: HTMLElement,\n options: SnapElementOptions = {}\n ): () => void {\n const id = uid()\n\n this.elements.set(id, new SnapElement(element, options))\n\n return () => this.elements.delete(id)\n }\n\n addElements(\n elements: HTMLElement[],\n options: SnapElementOptions = {}\n ): () => void {\n const map = [...elements].map((element) =>\n this.addElement(element, options)\n )\n return () => {\n map.forEach((remove) => {\n remove()\n })\n }\n }\n\n private onWindowResize = () => {\n this.viewport.width = window.innerWidth\n this.viewport.height = window.innerHeight\n }\n\n private computeSnaps = () => {\n const { isHorizontal } = this.lenis\n\n let snaps = [...this.snaps.values()] as SnapItem[]\n\n this.elements.forEach(({ rect, align }) => {\n let value: number | undefined\n\n align.forEach((align) => {\n if (align === 'start') {\n value = rect.top\n } else if (align === 'center') {\n value = isHorizontal\n ? rect.left + rect.width / 2 - this.viewport.width / 2\n : rect.top + rect.height / 2 - this.viewport.height / 2\n } else if (align === 'end') {\n value = isHorizontal\n ? rect.left + rect.width - this.viewport.width\n : rect.top + rect.height - this.viewport.height\n }\n\n if (typeof value === 'number') {\n snaps.push({ value: Math.ceil(value) })\n }\n })\n })\n\n snaps = snaps.sort((a, b) => Math.abs(a.value) - Math.abs(b.value))\n\n return snaps\n }\n\n previous() {\n this.goTo((this.currentSnapIndex ?? 0) - 1)\n }\n\n next() {\n this.goTo((this.currentSnapIndex ?? 0) + 1)\n }\n\n goTo(index: number) {\n const snaps = this.computeSnaps()\n\n if (snaps.length === 0) return\n\n this.currentSnapIndex = Math.max(0, Math.min(index, snaps.length - 1))\n\n const currentSnap = snaps[this.currentSnapIndex]\n if (currentSnap === undefined) return\n\n this.lenis.scrollTo(currentSnap.value, {\n duration: this.options.duration,\n easing: this.options.easing,\n lerp: this.options.lerp,\n lock: this.options.type === 'lock',\n userData: { initiator: 'snap' },\n onStart: () => {\n this.options.onSnapStart?.({\n index: this.currentSnapIndex,\n ...currentSnap,\n })\n },\n onComplete: () => {\n this.options.onSnapComplete?.({\n index: this.currentSnapIndex,\n ...currentSnap,\n })\n },\n })\n }\n\n get distanceThreshold() {\n let distanceThreshold = Number.POSITIVE_INFINITY\n if (this.options.type === 'mandatory') return Number.POSITIVE_INFINITY\n\n const { isHorizontal } = this.lenis\n\n const axis = isHorizontal ? 'width' : 'height'\n\n if (\n typeof this.options.distanceThreshold === 'string' &&\n this.options.distanceThreshold.endsWith('%')\n ) {\n distanceThreshold =\n (Number(this.options.distanceThreshold.replace('%', '')) / 100) *\n this.viewport[axis]\n } else if (typeof this.options.distanceThreshold === 'number') {\n distanceThreshold = this.options.distanceThreshold\n } else {\n distanceThreshold = this.viewport[axis]\n }\n\n return distanceThreshold\n }\n\n private onSnap = (e: VirtualScrollData) => {\n if (this.isStopped) return\n\n if (e.event.type === 'touchmove') return\n\n if (\n this.options.type === 'lock' &&\n this.lenis.userData?.initiator === 'snap'\n )\n return\n\n let { scroll, isHorizontal } = this.lenis\n const delta = isHorizontal ? e.deltaX : e.deltaY\n scroll = Math.ceil(this.lenis.scroll + delta)\n\n const snaps = this.computeSnaps()\n\n if (snaps.length === 0) return\n\n let snapIndex: number | undefined\n\n const prevSnapIndex = snaps.findLastIndex(({ value }) => value < scroll)\n const nextSnapIndex = snaps.findIndex(({ value }) => value > scroll)\n\n if (this.options.type === 'lock') {\n if (delta > 0) {\n snapIndex = nextSnapIndex\n } else if (delta < 0) {\n snapIndex = prevSnapIndex\n }\n } else {\n const prevSnap = snaps[prevSnapIndex]!\n const distanceToPrevSnap = prevSnap\n ? Math.abs(scroll - prevSnap.value)\n : Number.POSITIVE_INFINITY\n\n const nextSnap = snaps[nextSnapIndex]!\n const distanceToNextSnap = nextSnap\n ? Math.abs(scroll - nextSnap.value)\n : Number.POSITIVE_INFINITY\n snapIndex =\n distanceToPrevSnap < distanceToNextSnap ? prevSnapIndex : nextSnapIndex\n }\n\n if (snapIndex === undefined) return\n if (snapIndex === -1) return\n\n snapIndex = Math.max(0, Math.min(snapIndex, snaps.length - 1))\n\n const snap = snaps[snapIndex]!\n\n const distance = Math.abs(scroll - snap.value)\n\n if (distance <= this.distanceThreshold) {\n this.goTo(snapIndex)\n }\n }\n\n resize() {\n this.elements.forEach((element) => {\n element.onWrapperResize()\n })\n }\n}\n","// This file serves as an entry point for the package\nimport { Snap } from './src/snap'\n\n// @ts-expect-error\nglobalThis.Snap = Snap\n"],"mappings":"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","names":["align","index"]}
|
|
1
|
+
{"version":3,"sources":["../packages/snap/src/debounce.ts","../packages/snap/src/element.ts","../packages/snap/src/uid.ts","../packages/snap/src/snap.ts","../packages/snap/browser.ts"],"sourcesContent":["export function debounce<CB extends (...args: unknown[]) => void>(\n callback: CB,\n delay: number\n) {\n let timer: ReturnType<typeof setTimeout> | undefined\n return function <T>(this: T, ...args: Parameters<typeof callback>): void {\n clearTimeout(timer)\n timer = setTimeout(() => {\n timer = undefined\n callback.apply(this, args)\n }, delay)\n }\n}\n","import { debounce } from './debounce'\n\nfunction removeParentSticky(element: HTMLElement) {\n const position = getComputedStyle(element).position\n\n const isSticky = position === 'sticky'\n\n if (isSticky) {\n element.style.setProperty('position', 'static')\n element.dataset.sticky = 'true'\n }\n\n if (element.offsetParent) {\n removeParentSticky(element.offsetParent as HTMLElement)\n }\n}\n\nfunction addParentSticky(element: HTMLElement) {\n if (element?.dataset?.sticky === 'true') {\n element.style.removeProperty('position')\n delete element.dataset.sticky\n }\n\n if (element.offsetParent) {\n addParentSticky(element.offsetParent as HTMLElement)\n }\n}\n\nfunction offsetTop(element: HTMLElement, accumulator = 0) {\n const top = accumulator + element.offsetTop\n if (element.offsetParent) {\n return offsetTop(element.offsetParent as HTMLElement, top)\n }\n return top\n}\n\nfunction offsetLeft(element: HTMLElement, accumulator = 0) {\n const left = accumulator + element.offsetLeft\n if (element.offsetParent) {\n return offsetLeft(element.offsetParent as HTMLElement, left)\n }\n return left\n}\n\nfunction scrollTop(element: HTMLElement, accumulator = 0) {\n const top = accumulator + element.scrollTop\n if (element.offsetParent) {\n return scrollTop(element.offsetParent as HTMLElement, top)\n }\n return top + window.scrollY\n}\n\nfunction scrollLeft(element: HTMLElement, accumulator = 0) {\n const left = accumulator + element.scrollLeft\n if (element.offsetParent) {\n return scrollLeft(element.offsetParent as HTMLElement, left)\n }\n return left + window.scrollX\n}\n\nexport type SnapElementOptions = {\n align?: string | string[]\n ignoreSticky?: boolean\n ignoreTransform?: boolean\n}\n\ntype Rect = {\n top: number\n left: number\n width: number\n height: number\n x: number\n y: number\n bottom: number\n right: number\n element: HTMLElement\n}\n\nexport class SnapElement {\n element: HTMLElement\n options: SnapElementOptions\n align: string[]\n // @ts-expect-error\n rect: Rect = {}\n wrapperResizeObserver: ResizeObserver\n resizeObserver: ResizeObserver\n debouncedWrapperResize: () => void\n\n constructor(\n element: HTMLElement,\n {\n align = ['start'],\n ignoreSticky = true,\n ignoreTransform = false,\n }: SnapElementOptions = {}\n ) {\n this.element = element\n\n this.options = { align, ignoreSticky, ignoreTransform }\n\n this.align = [align].flat()\n\n this.debouncedWrapperResize = debounce(this.onWrapperResize, 500)\n\n this.wrapperResizeObserver = new ResizeObserver(this.debouncedWrapperResize)\n this.wrapperResizeObserver.observe(document.body)\n this.onWrapperResize()\n\n this.resizeObserver = new ResizeObserver(this.onResize)\n this.resizeObserver.observe(this.element)\n this.setRect({\n width: this.element.offsetWidth,\n height: this.element.offsetHeight,\n })\n }\n\n destroy() {\n this.wrapperResizeObserver.disconnect()\n this.resizeObserver.disconnect()\n }\n\n setRect({\n top,\n left,\n width,\n height,\n element,\n }: {\n top?: number\n left?: number\n width?: number\n height?: number\n element?: HTMLElement\n } = {}) {\n top = top ?? this.rect.top\n left = left ?? this.rect.left\n width = width ?? this.rect.width\n height = height ?? this.rect.height\n element = element ?? this.rect.element\n\n if (\n top === this.rect.top &&\n left === this.rect.left &&\n width === this.rect.width &&\n height === this.rect.height &&\n element === this.rect.element\n )\n return\n\n this.rect.top = top\n this.rect.y = top\n this.rect.width = width\n this.rect.height = height\n this.rect.left = left\n this.rect.x = left\n this.rect.bottom = top + height\n this.rect.right = left + width\n }\n\n onWrapperResize = () => {\n let top: number | undefined\n let left: number | undefined\n\n if (this.options.ignoreSticky) removeParentSticky(this.element)\n if (this.options.ignoreTransform) {\n top = offsetTop(this.element)\n left = offsetLeft(this.element)\n } else {\n const rect = this.element.getBoundingClientRect()\n top = rect.top + scrollTop(this.element)\n left = rect.left + scrollLeft(this.element)\n }\n if (this.options.ignoreSticky) addParentSticky(this.element)\n\n this.setRect({ top, left })\n }\n\n onResize = ([entry]: ResizeObserverEntry[]) => {\n if (!entry?.borderBoxSize[0]) return\n const width = entry.borderBoxSize[0].inlineSize\n const height = entry.borderBoxSize[0].blockSize\n\n this.setRect({ width, height })\n }\n}\n","let index = 0\n\nexport type UID = number\n\nexport function uid(): UID {\n return index++\n}\n","import type Lenis from 'lenis'\nimport type { VirtualScrollData } from 'lenis'\nimport { debounce } from './debounce'\nimport type { SnapElementOptions } from './element'\nimport { SnapElement } from './element'\nimport type { SnapItem, SnapOptions } from './types'\nimport type { UID } from './uid'\nimport { uid } from './uid'\n\n// TODO:\n// - fix wheel scrolling after limits (see console scroll to)\n// - arrow, spacebar\n\ntype RequiredPick<T, F extends keyof T> = Omit<T, F> & Required<Pick<T, F>>\n\n/**\n * Snap class to handle the snap functionality\n *\n * @example\n * const snap = new Snap(lenis, {\n * type: 'mandatory', // 'mandatory', 'proximity' or 'lock'\n * onSnapStart: (snap) => {\n * console.log('onSnapStart', snap)\n * },\n * onSnapComplete: (snap) => {\n * console.log('onSnapComplete', snap)\n * },\n * })\n *\n * snap.add(500) // snap at 500px\n *\n * const removeSnap = snap.add(500)\n *\n * if (someCondition) {\n * removeSnap()\n * }\n */\nexport class Snap {\n options: RequiredPick<SnapOptions, 'type' | 'debounce'>\n elements = new Map<UID, SnapElement>()\n snaps = new Map<UID, SnapItem>()\n viewport: { width: number; height: number } = {\n width: window.innerWidth,\n height: window.innerHeight,\n }\n isStopped = false\n onSnapDebounced: (e: VirtualScrollData) => void\n currentSnapIndex?: number\n\n constructor(\n private lenis: Lenis,\n {\n type = 'proximity',\n lerp,\n easing,\n duration,\n distanceThreshold = '50%', // useless when type is \"mandatory\"\n debounce: debounceDelay = 500,\n onSnapStart,\n onSnapComplete,\n }: SnapOptions = {}\n ) {\n if (!window.lenis) {\n window.lenis = {}\n }\n\n window.lenis.snap = true\n\n this.options = {\n type,\n lerp,\n easing,\n duration,\n distanceThreshold,\n debounce: debounceDelay,\n onSnapStart,\n onSnapComplete,\n }\n\n this.onWindowResize()\n window.addEventListener('resize', this.onWindowResize)\n\n this.onSnapDebounced = debounce(\n this.onSnap as (...args: unknown[]) => void,\n this.options.debounce\n )\n\n this.lenis.on('virtual-scroll', this.onSnapDebounced)\n }\n\n /**\n * Destroy the snap instance\n */\n destroy() {\n this.lenis.off('virtual-scroll', this.onSnapDebounced)\n window.removeEventListener('resize', this.onWindowResize)\n this.elements.forEach((element) => {\n element.destroy()\n })\n }\n\n /**\n * Start the snap after it has been stopped\n */\n start() {\n this.isStopped = false\n }\n\n /**\n * Stop the snap\n */\n stop() {\n this.isStopped = true\n }\n\n /**\n * Add a snap to the snap instance\n *\n * @param value The value to snap to\n * @param userData User data that will be forwarded through the snap event\n * @returns Unsubscribe function\n */\n add(value: number): () => void {\n const id = uid()\n\n this.snaps.set(id, { value })\n\n return () => this.snaps.delete(id)\n }\n\n /**\n * Add an element to the snap instance\n *\n * @param element The element to add\n * @param options The options for the element\n * @returns Unsubscribe function\n */\n addElement(\n element: HTMLElement,\n options: SnapElementOptions = {}\n ): () => void {\n const id = uid()\n\n this.elements.set(id, new SnapElement(element, options))\n\n return () => this.elements.delete(id)\n }\n\n addElements(\n elements: HTMLElement[],\n options: SnapElementOptions = {}\n ): () => void {\n const map = [...elements].map((element) =>\n this.addElement(element, options)\n )\n return () => {\n map.forEach((remove) => {\n remove()\n })\n }\n }\n\n private onWindowResize = () => {\n this.viewport.width = window.innerWidth\n this.viewport.height = window.innerHeight\n }\n\n private computeSnaps = () => {\n const { isHorizontal } = this.lenis\n\n let snaps = [...this.snaps.values()] as SnapItem[]\n\n this.elements.forEach(({ rect, align }) => {\n let value: number | undefined\n\n align.forEach((align) => {\n if (align === 'start') {\n value = rect.top\n } else if (align === 'center') {\n value = isHorizontal\n ? rect.left + rect.width / 2 - this.viewport.width / 2\n : rect.top + rect.height / 2 - this.viewport.height / 2\n } else if (align === 'end') {\n value = isHorizontal\n ? rect.left + rect.width - this.viewport.width\n : rect.top + rect.height - this.viewport.height\n }\n\n if (typeof value === 'number') {\n snaps.push({ value: Math.ceil(value) })\n }\n })\n })\n\n snaps = snaps.sort((a, b) => Math.abs(a.value) - Math.abs(b.value))\n\n return snaps\n }\n\n previous() {\n this.goTo((this.currentSnapIndex ?? 0) - 1)\n }\n\n next() {\n this.goTo((this.currentSnapIndex ?? 0) + 1)\n }\n\n goTo(index: number) {\n const snaps = this.computeSnaps()\n\n if (snaps.length === 0) return\n\n this.currentSnapIndex = Math.max(0, Math.min(index, snaps.length - 1))\n\n const currentSnap = snaps[this.currentSnapIndex]\n if (currentSnap === undefined) return\n\n this.lenis.scrollTo(currentSnap.value, {\n duration: this.options.duration,\n easing: this.options.easing,\n lerp: this.options.lerp,\n lock: this.options.type === 'lock',\n userData: { initiator: 'snap' },\n onStart: () => {\n this.options.onSnapStart?.({\n index: this.currentSnapIndex,\n ...currentSnap,\n })\n },\n onComplete: () => {\n this.options.onSnapComplete?.({\n index: this.currentSnapIndex,\n ...currentSnap,\n })\n },\n })\n }\n\n get distanceThreshold() {\n let distanceThreshold = Number.POSITIVE_INFINITY\n if (this.options.type === 'mandatory') return Number.POSITIVE_INFINITY\n\n const { isHorizontal } = this.lenis\n\n const axis = isHorizontal ? 'width' : 'height'\n\n if (\n typeof this.options.distanceThreshold === 'string' &&\n this.options.distanceThreshold.endsWith('%')\n ) {\n distanceThreshold =\n (Number(this.options.distanceThreshold.replace('%', '')) / 100) *\n this.viewport[axis]\n } else if (typeof this.options.distanceThreshold === 'number') {\n distanceThreshold = this.options.distanceThreshold\n } else {\n distanceThreshold = this.viewport[axis]\n }\n\n return distanceThreshold\n }\n\n private onSnap = (e: VirtualScrollData) => {\n if (this.isStopped) return\n\n if (e.event.type === 'touchmove') return\n\n if (\n this.options.type === 'lock' &&\n this.lenis.userData?.initiator === 'snap'\n )\n return\n\n let { scroll, isHorizontal } = this.lenis\n const delta = isHorizontal ? e.deltaX : e.deltaY\n scroll = Math.ceil(this.lenis.scroll + delta)\n\n const snaps = this.computeSnaps()\n\n if (snaps.length === 0) return\n\n let snapIndex: number | undefined\n\n const prevSnapIndex = snaps.findLastIndex(({ value }) => value < scroll)\n const nextSnapIndex = snaps.findIndex(({ value }) => value > scroll)\n\n if (this.options.type === 'lock') {\n if (delta > 0) {\n snapIndex = nextSnapIndex\n } else if (delta < 0) {\n snapIndex = prevSnapIndex\n }\n } else {\n const prevSnap = snaps[prevSnapIndex]!\n const distanceToPrevSnap = prevSnap\n ? Math.abs(scroll - prevSnap.value)\n : Number.POSITIVE_INFINITY\n\n const nextSnap = snaps[nextSnapIndex]!\n const distanceToNextSnap = nextSnap\n ? Math.abs(scroll - nextSnap.value)\n : Number.POSITIVE_INFINITY\n snapIndex =\n distanceToPrevSnap < distanceToNextSnap ? prevSnapIndex : nextSnapIndex\n }\n\n if (snapIndex === undefined) return\n if (snapIndex === -1) return\n\n snapIndex = Math.max(0, Math.min(snapIndex, snaps.length - 1))\n\n const snap = snaps[snapIndex]!\n\n const distance = Math.abs(scroll - snap.value)\n\n if (distance <= this.distanceThreshold) {\n this.goTo(snapIndex)\n }\n }\n\n resize() {\n this.elements.forEach((element) => {\n element.onWrapperResize()\n })\n }\n}\n","// This file serves as an entry point for the package\nimport { Snap } from './src/snap'\n\n// @ts-expect-error\nglobalThis.Snap = Snap\n"],"mappings":"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","names":["align","index"]}
|
package/dist/lenis-snap.mjs
CHANGED
|
@@ -157,6 +157,10 @@ var Snap = class {
|
|
|
157
157
|
onSnapComplete
|
|
158
158
|
} = {}) {
|
|
159
159
|
this.lenis = lenis;
|
|
160
|
+
if (!window.lenis) {
|
|
161
|
+
window.lenis = {};
|
|
162
|
+
}
|
|
163
|
+
window.lenis.snap = true;
|
|
160
164
|
this.options = {
|
|
161
165
|
type,
|
|
162
166
|
lerp,
|
|
@@ -168,7 +172,7 @@ var Snap = class {
|
|
|
168
172
|
onSnapComplete
|
|
169
173
|
};
|
|
170
174
|
this.onWindowResize();
|
|
171
|
-
window.addEventListener("resize", this.onWindowResize
|
|
175
|
+
window.addEventListener("resize", this.onWindowResize);
|
|
172
176
|
this.onSnapDebounced = debounce(
|
|
173
177
|
this.onSnap,
|
|
174
178
|
this.options.debounce
|
|
@@ -190,7 +194,7 @@ var Snap = class {
|
|
|
190
194
|
*/
|
|
191
195
|
destroy() {
|
|
192
196
|
this.lenis.off("virtual-scroll", this.onSnapDebounced);
|
|
193
|
-
window.removeEventListener("resize", this.onWindowResize
|
|
197
|
+
window.removeEventListener("resize", this.onWindowResize);
|
|
194
198
|
this.elements.forEach((element) => {
|
|
195
199
|
element.destroy();
|
|
196
200
|
});
|
package/dist/lenis-snap.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
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: unknown[]) => void>(\n callback: CB,\n delay: number\n) {\n let timer: ReturnType<typeof setTimeout> | undefined\n return function <T>(this: T, ...args: Parameters<typeof callback>): void {\n clearTimeout(timer)\n timer = setTimeout(() => {\n timer = undefined\n callback.apply(this, args)\n }, delay)\n }\n}\n","import { debounce } from './debounce'\n\nfunction removeParentSticky(element: HTMLElement) {\n const position = getComputedStyle(element).position\n\n const isSticky = position === 'sticky'\n\n if (isSticky) {\n element.style.setProperty('position', 'static')\n element.dataset.sticky = 'true'\n }\n\n if (element.offsetParent) {\n removeParentSticky(element.offsetParent as HTMLElement)\n }\n}\n\nfunction addParentSticky(element: HTMLElement) {\n if (element?.dataset?.sticky === 'true') {\n element.style.removeProperty('position')\n delete element.dataset.sticky\n }\n\n if (element.offsetParent) {\n addParentSticky(element.offsetParent as HTMLElement)\n }\n}\n\nfunction offsetTop(element: HTMLElement, accumulator = 0) {\n const top = accumulator + element.offsetTop\n if (element.offsetParent) {\n return offsetTop(element.offsetParent as HTMLElement, top)\n }\n return top\n}\n\nfunction offsetLeft(element: HTMLElement, accumulator = 0) {\n const left = accumulator + element.offsetLeft\n if (element.offsetParent) {\n return offsetLeft(element.offsetParent as HTMLElement, left)\n }\n return left\n}\n\nfunction scrollTop(element: HTMLElement, accumulator = 0) {\n const top = accumulator + element.scrollTop\n if (element.offsetParent) {\n return scrollTop(element.offsetParent as HTMLElement, top)\n }\n return top + window.scrollY\n}\n\nfunction scrollLeft(element: HTMLElement, accumulator = 0) {\n const left = accumulator + element.scrollLeft\n if (element.offsetParent) {\n return scrollLeft(element.offsetParent as HTMLElement, left)\n }\n return left + window.scrollX\n}\n\nexport type SnapElementOptions = {\n align?: string | string[]\n ignoreSticky?: boolean\n ignoreTransform?: boolean\n}\n\ntype Rect = {\n top: number\n left: number\n width: number\n height: number\n x: number\n y: number\n bottom: number\n right: number\n element: HTMLElement\n}\n\nexport class SnapElement {\n element: HTMLElement\n options: SnapElementOptions\n align: string[]\n // @ts-expect-error\n rect: Rect = {}\n wrapperResizeObserver: ResizeObserver\n resizeObserver: ResizeObserver\n debouncedWrapperResize: () => void\n\n constructor(\n element: HTMLElement,\n {\n align = ['start'],\n ignoreSticky = true,\n ignoreTransform = false,\n }: SnapElementOptions = {}\n ) {\n this.element = element\n\n this.options = { align, ignoreSticky, ignoreTransform }\n\n this.align = [align].flat()\n\n this.debouncedWrapperResize = debounce(this.onWrapperResize, 500)\n\n this.wrapperResizeObserver = new ResizeObserver(this.debouncedWrapperResize)\n this.wrapperResizeObserver.observe(document.body)\n this.onWrapperResize()\n\n this.resizeObserver = new ResizeObserver(this.onResize)\n this.resizeObserver.observe(this.element)\n this.setRect({\n width: this.element.offsetWidth,\n height: this.element.offsetHeight,\n })\n }\n\n destroy() {\n this.wrapperResizeObserver.disconnect()\n this.resizeObserver.disconnect()\n }\n\n setRect({\n top,\n left,\n width,\n height,\n element,\n }: {\n top?: number\n left?: number\n width?: number\n height?: number\n element?: HTMLElement\n } = {}) {\n top = top ?? this.rect.top\n left = left ?? this.rect.left\n width = width ?? this.rect.width\n height = height ?? this.rect.height\n element = element ?? this.rect.element\n\n if (\n top === this.rect.top &&\n left === this.rect.left &&\n width === this.rect.width &&\n height === this.rect.height &&\n element === this.rect.element\n )\n return\n\n this.rect.top = top\n this.rect.y = top\n this.rect.width = width\n this.rect.height = height\n this.rect.left = left\n this.rect.x = left\n this.rect.bottom = top + height\n this.rect.right = left + width\n }\n\n onWrapperResize = () => {\n let top: number | undefined\n let left: number | undefined\n\n if (this.options.ignoreSticky) removeParentSticky(this.element)\n if (this.options.ignoreTransform) {\n top = offsetTop(this.element)\n left = offsetLeft(this.element)\n } else {\n const rect = this.element.getBoundingClientRect()\n top = rect.top + scrollTop(this.element)\n left = rect.left + scrollLeft(this.element)\n }\n if (this.options.ignoreSticky) addParentSticky(this.element)\n\n this.setRect({ top, left })\n }\n\n onResize = ([entry]: ResizeObserverEntry[]) => {\n if (!entry?.borderBoxSize[0]) return\n const width = entry.borderBoxSize[0].inlineSize\n const height = entry.borderBoxSize[0].blockSize\n\n this.setRect({ width, height })\n }\n}\n","let index = 0\n\nexport type UID = number\n\nexport function uid(): UID {\n return index++\n}\n","import type Lenis from 'lenis'\nimport type { VirtualScrollData } from 'lenis'\nimport { debounce } from './debounce'\nimport type { SnapElementOptions } from './element'\nimport { SnapElement } from './element'\nimport type { SnapItem, SnapOptions } from './types'\nimport type { UID } from './uid'\nimport { uid } from './uid'\n\n// TODO:\n// - fix wheel scrolling after limits (see console scroll to)\n// - arrow, spacebar\n\ntype RequiredPick<T, F extends keyof T> = Omit<T, F> & Required<Pick<T, F>>\n\n/**\n * Snap class to handle the snap functionality\n *\n * @example\n * const snap = new Snap(lenis, {\n * type: 'mandatory', // 'mandatory', 'proximity' or 'lock'\n * onSnapStart: (snap) => {\n * console.log('onSnapStart', snap)\n * },\n * onSnapComplete: (snap) => {\n * console.log('onSnapComplete', snap)\n * },\n * })\n *\n * snap.add(500) // snap at 500px\n *\n * const removeSnap = snap.add(500)\n *\n * if (someCondition) {\n * removeSnap()\n * }\n */\nexport class Snap {\n options: RequiredPick<SnapOptions, 'type' | 'debounce'>\n elements = new Map<UID, SnapElement>()\n snaps = new Map<UID, SnapItem>()\n viewport: { width: number; height: number } = {\n width: window.innerWidth,\n height: window.innerHeight,\n }\n isStopped = false\n onSnapDebounced: (e: VirtualScrollData) => void\n currentSnapIndex?: number\n\n constructor(\n private lenis: Lenis,\n {\n type = 'proximity',\n lerp,\n easing,\n duration,\n distanceThreshold = '50%', // useless when type is \"mandatory\"\n debounce: debounceDelay = 500,\n onSnapStart,\n onSnapComplete,\n }: SnapOptions = {}\n ) {\n this.options = {\n type,\n lerp,\n easing,\n duration,\n distanceThreshold,\n debounce: debounceDelay,\n onSnapStart,\n onSnapComplete,\n }\n\n this.onWindowResize()\n window.addEventListener('resize', this.onWindowResize, false)\n\n this.onSnapDebounced = debounce(\n this.onSnap as (...args: unknown[]) => void,\n this.options.debounce\n )\n\n this.lenis.on('virtual-scroll', this.onSnapDebounced)\n }\n\n /**\n * Destroy the snap instance\n */\n destroy() {\n this.lenis.off('virtual-scroll', this.onSnapDebounced)\n window.removeEventListener('resize', this.onWindowResize, false)\n this.elements.forEach((element) => {\n element.destroy()\n })\n }\n\n /**\n * Start the snap after it has been stopped\n */\n start() {\n this.isStopped = false\n }\n\n /**\n * Stop the snap\n */\n stop() {\n this.isStopped = true\n }\n\n /**\n * Add a snap to the snap instance\n *\n * @param value The value to snap to\n * @param userData User data that will be forwarded through the snap event\n * @returns Unsubscribe function\n */\n add(value: number): () => void {\n const id = uid()\n\n this.snaps.set(id, { value })\n\n return () => this.snaps.delete(id)\n }\n\n /**\n * Add an element to the snap instance\n *\n * @param element The element to add\n * @param options The options for the element\n * @returns Unsubscribe function\n */\n addElement(\n element: HTMLElement,\n options: SnapElementOptions = {}\n ): () => void {\n const id = uid()\n\n this.elements.set(id, new SnapElement(element, options))\n\n return () => this.elements.delete(id)\n }\n\n addElements(\n elements: HTMLElement[],\n options: SnapElementOptions = {}\n ): () => void {\n const map = [...elements].map((element) =>\n this.addElement(element, options)\n )\n return () => {\n map.forEach((remove) => {\n remove()\n })\n }\n }\n\n private onWindowResize = () => {\n this.viewport.width = window.innerWidth\n this.viewport.height = window.innerHeight\n }\n\n private computeSnaps = () => {\n const { isHorizontal } = this.lenis\n\n let snaps = [...this.snaps.values()] as SnapItem[]\n\n this.elements.forEach(({ rect, align }) => {\n let value: number | undefined\n\n align.forEach((align) => {\n if (align === 'start') {\n value = rect.top\n } else if (align === 'center') {\n value = isHorizontal\n ? rect.left + rect.width / 2 - this.viewport.width / 2\n : rect.top + rect.height / 2 - this.viewport.height / 2\n } else if (align === 'end') {\n value = isHorizontal\n ? rect.left + rect.width - this.viewport.width\n : rect.top + rect.height - this.viewport.height\n }\n\n if (typeof value === 'number') {\n snaps.push({ value: Math.ceil(value) })\n }\n })\n })\n\n snaps = snaps.sort((a, b) => Math.abs(a.value) - Math.abs(b.value))\n\n return snaps\n }\n\n previous() {\n this.goTo((this.currentSnapIndex ?? 0) - 1)\n }\n\n next() {\n this.goTo((this.currentSnapIndex ?? 0) + 1)\n }\n\n goTo(index: number) {\n const snaps = this.computeSnaps()\n\n if (snaps.length === 0) return\n\n this.currentSnapIndex = Math.max(0, Math.min(index, snaps.length - 1))\n\n const currentSnap = snaps[this.currentSnapIndex]\n if (currentSnap === undefined) return\n\n this.lenis.scrollTo(currentSnap.value, {\n duration: this.options.duration,\n easing: this.options.easing,\n lerp: this.options.lerp,\n lock: this.options.type === 'lock',\n userData: { initiator: 'snap' },\n onStart: () => {\n this.options.onSnapStart?.({\n index: this.currentSnapIndex,\n ...currentSnap,\n })\n },\n onComplete: () => {\n this.options.onSnapComplete?.({\n index: this.currentSnapIndex,\n ...currentSnap,\n })\n },\n })\n }\n\n get distanceThreshold() {\n let distanceThreshold = Number.POSITIVE_INFINITY\n if (this.options.type === 'mandatory') return Number.POSITIVE_INFINITY\n\n const { isHorizontal } = this.lenis\n\n const axis = isHorizontal ? 'width' : 'height'\n\n if (\n typeof this.options.distanceThreshold === 'string' &&\n this.options.distanceThreshold.endsWith('%')\n ) {\n distanceThreshold =\n (Number(this.options.distanceThreshold.replace('%', '')) / 100) *\n this.viewport[axis]\n } else if (typeof this.options.distanceThreshold === 'number') {\n distanceThreshold = this.options.distanceThreshold\n } else {\n distanceThreshold = this.viewport[axis]\n }\n\n return distanceThreshold\n }\n\n private onSnap = (e: VirtualScrollData) => {\n if (this.isStopped) return\n\n if (e.event.type === 'touchmove') return\n\n if (\n this.options.type === 'lock' &&\n this.lenis.userData?.initiator === 'snap'\n )\n return\n\n let { scroll, isHorizontal } = this.lenis\n const delta = isHorizontal ? e.deltaX : e.deltaY\n scroll = Math.ceil(this.lenis.scroll + delta)\n\n const snaps = this.computeSnaps()\n\n if (snaps.length === 0) return\n\n let snapIndex: number | undefined\n\n const prevSnapIndex = snaps.findLastIndex(({ value }) => value < scroll)\n const nextSnapIndex = snaps.findIndex(({ value }) => value > scroll)\n\n if (this.options.type === 'lock') {\n if (delta > 0) {\n snapIndex = nextSnapIndex\n } else if (delta < 0) {\n snapIndex = prevSnapIndex\n }\n } else {\n const prevSnap = snaps[prevSnapIndex]!\n const distanceToPrevSnap = prevSnap\n ? Math.abs(scroll - prevSnap.value)\n : Number.POSITIVE_INFINITY\n\n const nextSnap = snaps[nextSnapIndex]!\n const distanceToNextSnap = nextSnap\n ? Math.abs(scroll - nextSnap.value)\n : Number.POSITIVE_INFINITY\n snapIndex =\n distanceToPrevSnap < distanceToNextSnap ? prevSnapIndex : nextSnapIndex\n }\n\n if (snapIndex === undefined) return\n if (snapIndex === -1) return\n\n snapIndex = Math.max(0, Math.min(snapIndex, snaps.length - 1))\n\n const snap = snaps[snapIndex]!\n\n const distance = Math.abs(scroll - snap.value)\n\n if (distance <= this.distanceThreshold) {\n this.goTo(snapIndex)\n }\n }\n\n resize() {\n this.elements.forEach((element) => {\n element.onWrapperResize()\n })\n }\n}\n"],"mappings":"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","names":["align","index"]}
|
|
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: unknown[]) => void>(\n callback: CB,\n delay: number\n) {\n let timer: ReturnType<typeof setTimeout> | undefined\n return function <T>(this: T, ...args: Parameters<typeof callback>): void {\n clearTimeout(timer)\n timer = setTimeout(() => {\n timer = undefined\n callback.apply(this, args)\n }, delay)\n }\n}\n","import { debounce } from './debounce'\n\nfunction removeParentSticky(element: HTMLElement) {\n const position = getComputedStyle(element).position\n\n const isSticky = position === 'sticky'\n\n if (isSticky) {\n element.style.setProperty('position', 'static')\n element.dataset.sticky = 'true'\n }\n\n if (element.offsetParent) {\n removeParentSticky(element.offsetParent as HTMLElement)\n }\n}\n\nfunction addParentSticky(element: HTMLElement) {\n if (element?.dataset?.sticky === 'true') {\n element.style.removeProperty('position')\n delete element.dataset.sticky\n }\n\n if (element.offsetParent) {\n addParentSticky(element.offsetParent as HTMLElement)\n }\n}\n\nfunction offsetTop(element: HTMLElement, accumulator = 0) {\n const top = accumulator + element.offsetTop\n if (element.offsetParent) {\n return offsetTop(element.offsetParent as HTMLElement, top)\n }\n return top\n}\n\nfunction offsetLeft(element: HTMLElement, accumulator = 0) {\n const left = accumulator + element.offsetLeft\n if (element.offsetParent) {\n return offsetLeft(element.offsetParent as HTMLElement, left)\n }\n return left\n}\n\nfunction scrollTop(element: HTMLElement, accumulator = 0) {\n const top = accumulator + element.scrollTop\n if (element.offsetParent) {\n return scrollTop(element.offsetParent as HTMLElement, top)\n }\n return top + window.scrollY\n}\n\nfunction scrollLeft(element: HTMLElement, accumulator = 0) {\n const left = accumulator + element.scrollLeft\n if (element.offsetParent) {\n return scrollLeft(element.offsetParent as HTMLElement, left)\n }\n return left + window.scrollX\n}\n\nexport type SnapElementOptions = {\n align?: string | string[]\n ignoreSticky?: boolean\n ignoreTransform?: boolean\n}\n\ntype Rect = {\n top: number\n left: number\n width: number\n height: number\n x: number\n y: number\n bottom: number\n right: number\n element: HTMLElement\n}\n\nexport class SnapElement {\n element: HTMLElement\n options: SnapElementOptions\n align: string[]\n // @ts-expect-error\n rect: Rect = {}\n wrapperResizeObserver: ResizeObserver\n resizeObserver: ResizeObserver\n debouncedWrapperResize: () => void\n\n constructor(\n element: HTMLElement,\n {\n align = ['start'],\n ignoreSticky = true,\n ignoreTransform = false,\n }: SnapElementOptions = {}\n ) {\n this.element = element\n\n this.options = { align, ignoreSticky, ignoreTransform }\n\n this.align = [align].flat()\n\n this.debouncedWrapperResize = debounce(this.onWrapperResize, 500)\n\n this.wrapperResizeObserver = new ResizeObserver(this.debouncedWrapperResize)\n this.wrapperResizeObserver.observe(document.body)\n this.onWrapperResize()\n\n this.resizeObserver = new ResizeObserver(this.onResize)\n this.resizeObserver.observe(this.element)\n this.setRect({\n width: this.element.offsetWidth,\n height: this.element.offsetHeight,\n })\n }\n\n destroy() {\n this.wrapperResizeObserver.disconnect()\n this.resizeObserver.disconnect()\n }\n\n setRect({\n top,\n left,\n width,\n height,\n element,\n }: {\n top?: number\n left?: number\n width?: number\n height?: number\n element?: HTMLElement\n } = {}) {\n top = top ?? this.rect.top\n left = left ?? this.rect.left\n width = width ?? this.rect.width\n height = height ?? this.rect.height\n element = element ?? this.rect.element\n\n if (\n top === this.rect.top &&\n left === this.rect.left &&\n width === this.rect.width &&\n height === this.rect.height &&\n element === this.rect.element\n )\n return\n\n this.rect.top = top\n this.rect.y = top\n this.rect.width = width\n this.rect.height = height\n this.rect.left = left\n this.rect.x = left\n this.rect.bottom = top + height\n this.rect.right = left + width\n }\n\n onWrapperResize = () => {\n let top: number | undefined\n let left: number | undefined\n\n if (this.options.ignoreSticky) removeParentSticky(this.element)\n if (this.options.ignoreTransform) {\n top = offsetTop(this.element)\n left = offsetLeft(this.element)\n } else {\n const rect = this.element.getBoundingClientRect()\n top = rect.top + scrollTop(this.element)\n left = rect.left + scrollLeft(this.element)\n }\n if (this.options.ignoreSticky) addParentSticky(this.element)\n\n this.setRect({ top, left })\n }\n\n onResize = ([entry]: ResizeObserverEntry[]) => {\n if (!entry?.borderBoxSize[0]) return\n const width = entry.borderBoxSize[0].inlineSize\n const height = entry.borderBoxSize[0].blockSize\n\n this.setRect({ width, height })\n }\n}\n","let index = 0\n\nexport type UID = number\n\nexport function uid(): UID {\n return index++\n}\n","import type Lenis from 'lenis'\nimport type { VirtualScrollData } from 'lenis'\nimport { debounce } from './debounce'\nimport type { SnapElementOptions } from './element'\nimport { SnapElement } from './element'\nimport type { SnapItem, SnapOptions } from './types'\nimport type { UID } from './uid'\nimport { uid } from './uid'\n\n// TODO:\n// - fix wheel scrolling after limits (see console scroll to)\n// - arrow, spacebar\n\ntype RequiredPick<T, F extends keyof T> = Omit<T, F> & Required<Pick<T, F>>\n\n/**\n * Snap class to handle the snap functionality\n *\n * @example\n * const snap = new Snap(lenis, {\n * type: 'mandatory', // 'mandatory', 'proximity' or 'lock'\n * onSnapStart: (snap) => {\n * console.log('onSnapStart', snap)\n * },\n * onSnapComplete: (snap) => {\n * console.log('onSnapComplete', snap)\n * },\n * })\n *\n * snap.add(500) // snap at 500px\n *\n * const removeSnap = snap.add(500)\n *\n * if (someCondition) {\n * removeSnap()\n * }\n */\nexport class Snap {\n options: RequiredPick<SnapOptions, 'type' | 'debounce'>\n elements = new Map<UID, SnapElement>()\n snaps = new Map<UID, SnapItem>()\n viewport: { width: number; height: number } = {\n width: window.innerWidth,\n height: window.innerHeight,\n }\n isStopped = false\n onSnapDebounced: (e: VirtualScrollData) => void\n currentSnapIndex?: number\n\n constructor(\n private lenis: Lenis,\n {\n type = 'proximity',\n lerp,\n easing,\n duration,\n distanceThreshold = '50%', // useless when type is \"mandatory\"\n debounce: debounceDelay = 500,\n onSnapStart,\n onSnapComplete,\n }: SnapOptions = {}\n ) {\n if (!window.lenis) {\n window.lenis = {}\n }\n\n window.lenis.snap = true\n\n this.options = {\n type,\n lerp,\n easing,\n duration,\n distanceThreshold,\n debounce: debounceDelay,\n onSnapStart,\n onSnapComplete,\n }\n\n this.onWindowResize()\n window.addEventListener('resize', this.onWindowResize)\n\n this.onSnapDebounced = debounce(\n this.onSnap as (...args: unknown[]) => void,\n this.options.debounce\n )\n\n this.lenis.on('virtual-scroll', this.onSnapDebounced)\n }\n\n /**\n * Destroy the snap instance\n */\n destroy() {\n this.lenis.off('virtual-scroll', this.onSnapDebounced)\n window.removeEventListener('resize', this.onWindowResize)\n this.elements.forEach((element) => {\n element.destroy()\n })\n }\n\n /**\n * Start the snap after it has been stopped\n */\n start() {\n this.isStopped = false\n }\n\n /**\n * Stop the snap\n */\n stop() {\n this.isStopped = true\n }\n\n /**\n * Add a snap to the snap instance\n *\n * @param value The value to snap to\n * @param userData User data that will be forwarded through the snap event\n * @returns Unsubscribe function\n */\n add(value: number): () => void {\n const id = uid()\n\n this.snaps.set(id, { value })\n\n return () => this.snaps.delete(id)\n }\n\n /**\n * Add an element to the snap instance\n *\n * @param element The element to add\n * @param options The options for the element\n * @returns Unsubscribe function\n */\n addElement(\n element: HTMLElement,\n options: SnapElementOptions = {}\n ): () => void {\n const id = uid()\n\n this.elements.set(id, new SnapElement(element, options))\n\n return () => this.elements.delete(id)\n }\n\n addElements(\n elements: HTMLElement[],\n options: SnapElementOptions = {}\n ): () => void {\n const map = [...elements].map((element) =>\n this.addElement(element, options)\n )\n return () => {\n map.forEach((remove) => {\n remove()\n })\n }\n }\n\n private onWindowResize = () => {\n this.viewport.width = window.innerWidth\n this.viewport.height = window.innerHeight\n }\n\n private computeSnaps = () => {\n const { isHorizontal } = this.lenis\n\n let snaps = [...this.snaps.values()] as SnapItem[]\n\n this.elements.forEach(({ rect, align }) => {\n let value: number | undefined\n\n align.forEach((align) => {\n if (align === 'start') {\n value = rect.top\n } else if (align === 'center') {\n value = isHorizontal\n ? rect.left + rect.width / 2 - this.viewport.width / 2\n : rect.top + rect.height / 2 - this.viewport.height / 2\n } else if (align === 'end') {\n value = isHorizontal\n ? rect.left + rect.width - this.viewport.width\n : rect.top + rect.height - this.viewport.height\n }\n\n if (typeof value === 'number') {\n snaps.push({ value: Math.ceil(value) })\n }\n })\n })\n\n snaps = snaps.sort((a, b) => Math.abs(a.value) - Math.abs(b.value))\n\n return snaps\n }\n\n previous() {\n this.goTo((this.currentSnapIndex ?? 0) - 1)\n }\n\n next() {\n this.goTo((this.currentSnapIndex ?? 0) + 1)\n }\n\n goTo(index: number) {\n const snaps = this.computeSnaps()\n\n if (snaps.length === 0) return\n\n this.currentSnapIndex = Math.max(0, Math.min(index, snaps.length - 1))\n\n const currentSnap = snaps[this.currentSnapIndex]\n if (currentSnap === undefined) return\n\n this.lenis.scrollTo(currentSnap.value, {\n duration: this.options.duration,\n easing: this.options.easing,\n lerp: this.options.lerp,\n lock: this.options.type === 'lock',\n userData: { initiator: 'snap' },\n onStart: () => {\n this.options.onSnapStart?.({\n index: this.currentSnapIndex,\n ...currentSnap,\n })\n },\n onComplete: () => {\n this.options.onSnapComplete?.({\n index: this.currentSnapIndex,\n ...currentSnap,\n })\n },\n })\n }\n\n get distanceThreshold() {\n let distanceThreshold = Number.POSITIVE_INFINITY\n if (this.options.type === 'mandatory') return Number.POSITIVE_INFINITY\n\n const { isHorizontal } = this.lenis\n\n const axis = isHorizontal ? 'width' : 'height'\n\n if (\n typeof this.options.distanceThreshold === 'string' &&\n this.options.distanceThreshold.endsWith('%')\n ) {\n distanceThreshold =\n (Number(this.options.distanceThreshold.replace('%', '')) / 100) *\n this.viewport[axis]\n } else if (typeof this.options.distanceThreshold === 'number') {\n distanceThreshold = this.options.distanceThreshold\n } else {\n distanceThreshold = this.viewport[axis]\n }\n\n return distanceThreshold\n }\n\n private onSnap = (e: VirtualScrollData) => {\n if (this.isStopped) return\n\n if (e.event.type === 'touchmove') return\n\n if (\n this.options.type === 'lock' &&\n this.lenis.userData?.initiator === 'snap'\n )\n return\n\n let { scroll, isHorizontal } = this.lenis\n const delta = isHorizontal ? e.deltaX : e.deltaY\n scroll = Math.ceil(this.lenis.scroll + delta)\n\n const snaps = this.computeSnaps()\n\n if (snaps.length === 0) return\n\n let snapIndex: number | undefined\n\n const prevSnapIndex = snaps.findLastIndex(({ value }) => value < scroll)\n const nextSnapIndex = snaps.findIndex(({ value }) => value > scroll)\n\n if (this.options.type === 'lock') {\n if (delta > 0) {\n snapIndex = nextSnapIndex\n } else if (delta < 0) {\n snapIndex = prevSnapIndex\n }\n } else {\n const prevSnap = snaps[prevSnapIndex]!\n const distanceToPrevSnap = prevSnap\n ? Math.abs(scroll - prevSnap.value)\n : Number.POSITIVE_INFINITY\n\n const nextSnap = snaps[nextSnapIndex]!\n const distanceToNextSnap = nextSnap\n ? Math.abs(scroll - nextSnap.value)\n : Number.POSITIVE_INFINITY\n snapIndex =\n distanceToPrevSnap < distanceToNextSnap ? prevSnapIndex : nextSnapIndex\n }\n\n if (snapIndex === undefined) return\n if (snapIndex === -1) return\n\n snapIndex = Math.max(0, Math.min(snapIndex, snaps.length - 1))\n\n const snap = snaps[snapIndex]!\n\n const distance = Math.abs(scroll - snap.value)\n\n if (distance <= this.distanceThreshold) {\n this.goTo(snapIndex)\n }\n }\n\n resize() {\n this.elements.forEach((element) => {\n element.onWrapperResize()\n })\n }\n}\n"],"mappings":"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","names":["align","index"]}
|
package/dist/lenis-vue.mjs.map
CHANGED
|
@@ -1 +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'\nimport Lenis, { type ScrollCallback } from 'lenis'\nimport type {\n HTMLAttributes,\n InjectionKey,\n Plugin,\n PropType,\n ShallowRef,\n ToRefs,\n} from 'vue'\nimport {\n defineComponent,\n h,\n onWatcherCleanup,\n provide,\n reactive,\n ref,\n shallowRef,\n watch,\n} from 'vue'\nimport { globalAddCallback, globalLenis, globalRemoveCallback } from './store'\n\nexport const LenisSymbol: InjectionKey<ShallowRef<Lenis | undefined>> =\n Symbol('LenisContext')\nexport const AddCallbackSymbol: InjectionKey<\n ((callback: ScrollCallback, priority: number) => void) | undefined\n> = Symbol('AddCallback')\nexport const RemoveCallbackSymbol: InjectionKey<\n ((callback: ScrollCallback) => void) | undefined\n> = Symbol('RemoveCallback')\n\nexport type LenisExposed = {\n wrapper?: HTMLDivElement\n content?: HTMLDivElement\n lenis?: Lenis\n}\n\nconst VueLenisImpl = defineComponent({\n name: 'VueLenis',\n props: {\n root: {\n type: Boolean as PropType<boolean>,\n default: false,\n },\n autoRaf: {\n type: Boolean as PropType<boolean>,\n default: true,\n },\n options: {\n type: Object as PropType<ConstructorParameters<typeof Lenis>[0]>,\n default: () => ({}),\n },\n props: {\n type: Object as PropType<HTMLAttributes>,\n default: () => ({}),\n },\n },\n setup(props, { slots, expose }) {\n const lenisRef = shallowRef<Lenis>()\n // const tempusCleanupRef = shallowRef<() => void>()\n const wrapper = ref<HTMLDivElement>()\n const content = ref<HTMLDivElement>()\n // Setup exposed properties\n expose<ToRefs<LenisExposed>>({\n lenis: lenisRef,\n wrapper,\n content,\n })\n\n // Sync options\n watch(\n [() => props.options, wrapper, content],\n () => {\n const isClient = typeof window !== 'undefined'\n\n if (!isClient) return\n\n if (!(props.root || (wrapper.value && content.value))) return\n\n lenisRef.value = new Lenis({\n ...props.options,\n ...(!props.root\n ? {\n wrapper: wrapper.value,\n content: content.value,\n }\n : {}),\n autoRaf: props.options?.autoRaf ?? props.autoRaf,\n })\n\n onWatcherCleanup(() => {\n lenisRef.value?.destroy()\n lenisRef.value = undefined\n })\n },\n { deep: true, immediate: true }\n )\n\n const callbacks = reactive<\n { callback: ScrollCallback; priority: number }[]\n >([])\n\n function addCallback(callback: ScrollCallback, priority: number) {\n callbacks.push({ callback, priority })\n callbacks.sort((a, b) => a.priority - b.priority)\n }\n\n function removeCallback(callback: ScrollCallback) {\n callbacks.splice(\n callbacks.findIndex((cb) => cb.callback === callback),\n 1\n )\n }\n\n const onScroll: ScrollCallback = (data) => {\n for (const { callback } of callbacks) {\n callback(data)\n }\n }\n\n watch(\n [lenisRef, () => props.root],\n ([lenis, root]) => {\n lenis?.on('scroll', onScroll)\n\n if (root) {\n globalLenis.value = lenis\n globalAddCallback.value = addCallback\n globalRemoveCallback.value = removeCallback\n\n onWatcherCleanup(() => {\n globalLenis.value = undefined\n globalAddCallback.value = undefined\n globalRemoveCallback.value = undefined\n })\n }\n },\n { immediate: true }\n )\n\n if (!props.root) {\n provide(LenisSymbol, lenisRef)\n provide(AddCallbackSymbol, addCallback)\n provide(RemoveCallbackSymbol, removeCallback)\n }\n\n return () => {\n if (props.root) {\n return slots.default?.()\n }\n return h('div', { ref: wrapper, ...props?.props }, [\n h('div', { ref: content }, slots.default?.()),\n ])\n }\n },\n})\n\nexport const VueLenis = VueLenisImpl as typeof VueLenisImpl & {\n new (): LenisExposed\n}\n\nexport const vueLenisPlugin: Plugin = (app) => {\n app.component('vue-lenis', VueLenis)\n // Setup a global provide to silence top level useLenis injection warning\n app.provide(LenisSymbol, shallowRef(undefined))\n app.provide(AddCallbackSymbol, undefined)\n app.provide(RemoveCallbackSymbol, undefined)\n}\n\n// @ts-expect-error\ndeclare module '@vue/runtime-core' {\n export interface GlobalComponents {\n 'vue-lenis': typeof VueLenis\n }\n}\n","import type Lenis from 'lenis'\nimport type { ScrollCallback } from 'lenis'\nimport { shallowRef } from 'vue'\n\nexport const globalLenis = shallowRef<Lenis>()\nexport const globalAddCallback =\n shallowRef<(callback: ScrollCallback, priority: number) => void>()\nexport const globalRemoveCallback =\n shallowRef<(callback: ScrollCallback) => void>()\n","import type { ScrollCallback } from 'lenis'\nimport { computed, inject, nextTick, onWatcherCleanup, watch } from 'vue'\nimport {\n AddCallbackSymbol,\n LenisSymbol,\n RemoveCallbackSymbol,\n} from './provider'\nimport { globalAddCallback, globalLenis, globalRemoveCallback } from './store'\n\nexport function useLenis(callback?: ScrollCallback, priority = 0) {\n const lenisInjection = inject(LenisSymbol)\n const addCallbackInjection = inject(AddCallbackSymbol)\n const removeCallbackInjection = inject(RemoveCallbackSymbol)\n\n const addCallback = computed(() =>\n addCallbackInjection ? addCallbackInjection : globalAddCallback.value\n )\n const removeCallback = computed(() =>\n removeCallbackInjection\n ? removeCallbackInjection\n : globalRemoveCallback.value\n )\n\n const lenis = computed(() =>\n lenisInjection?.value ? lenisInjection.value : globalLenis.value\n )\n\n if (typeof window !== 'undefined') {\n // Wait two ticks to make sure the lenis instance is mounted\n nextTick(() => {\n nextTick(() => {\n // @ts-expect-error - import.meta.env is available in vite and nuxt\n if (!lenis.value && import.meta.env.DEV) {\n console.warn(\n 'No lenis instance found, either mount a root lenis instance or wrap your component in a lenis provider'\n )\n }\n })\n })\n }\n\n watch(\n [lenis, addCallback, removeCallback],\n ([lenis, addCallback, removeCallback]) => {\n if (!(lenis && addCallback && removeCallback && callback)) return\n\n addCallback?.(callback, priority)\n callback?.(lenis!)\n\n onWatcherCleanup(() => {\n removeCallback?.(callback)\n })\n },\n {\n immediate: true,\n }\n )\n return lenis\n}\n"],"mappings":"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","names":["shallowRef","shallowRef","onWatcherCleanup","watch","watch","lenis","addCallback","removeCallback","onWatcherCleanup"]}
|
|
1
|
+
{"version":3,"sources":["../packages/vue/src/provider.ts","../packages/vue/src/store.ts","../packages/vue/src/use-lenis.ts"],"sourcesContent":["import Lenis, { type ScrollCallback } from 'lenis'\nimport type {\n HTMLAttributes,\n InjectionKey,\n Plugin,\n PropType,\n ShallowRef,\n ToRefs,\n} from 'vue'\nimport {\n defineComponent,\n h,\n onWatcherCleanup,\n provide,\n reactive,\n ref,\n shallowRef,\n watch,\n} from 'vue'\nimport { globalAddCallback, globalLenis, globalRemoveCallback } from './store'\n\nexport const LenisSymbol: InjectionKey<ShallowRef<Lenis | undefined>> =\n Symbol('LenisContext')\nexport const AddCallbackSymbol: InjectionKey<\n ((callback: ScrollCallback, priority: number) => void) | undefined\n> = Symbol('AddCallback')\nexport const RemoveCallbackSymbol: InjectionKey<\n ((callback: ScrollCallback) => void) | undefined\n> = Symbol('RemoveCallback')\n\nexport type LenisExposed = {\n wrapper?: HTMLDivElement\n content?: HTMLDivElement\n lenis?: Lenis\n}\n\nconst VueLenisImpl = defineComponent({\n name: 'VueLenis',\n props: {\n root: {\n type: Boolean as PropType<boolean>,\n default: false,\n },\n autoRaf: {\n type: Boolean as PropType<boolean>,\n default: true,\n },\n options: {\n type: Object as PropType<ConstructorParameters<typeof Lenis>[0]>,\n default: () => ({}),\n },\n props: {\n type: Object as PropType<HTMLAttributes>,\n default: () => ({}),\n },\n },\n setup(props, { slots, expose }) {\n const lenisRef = shallowRef<Lenis>()\n const wrapper = ref<HTMLDivElement>()\n const content = ref<HTMLDivElement>()\n // Setup exposed properties\n expose<ToRefs<LenisExposed>>({\n lenis: lenisRef,\n wrapper,\n content,\n })\n\n // Sync options\n watch(\n [() => props.options, wrapper, content],\n () => {\n const isClient = typeof window !== 'undefined'\n\n if (!isClient) return\n\n if (!(props.root || (wrapper.value && content.value))) return\n\n lenisRef.value = new Lenis({\n ...props.options,\n ...(!props.root\n ? {\n wrapper: wrapper.value,\n content: content.value,\n }\n : {}),\n autoRaf: props.options?.autoRaf ?? props.autoRaf,\n })\n\n onWatcherCleanup(() => {\n lenisRef.value?.destroy()\n lenisRef.value = undefined\n })\n },\n { deep: true, immediate: true }\n )\n\n const callbacks = reactive<\n { callback: ScrollCallback; priority: number }[]\n >([])\n\n function addCallback(callback: ScrollCallback, priority: number) {\n callbacks.push({ callback, priority })\n callbacks.sort((a, b) => a.priority - b.priority)\n }\n\n function removeCallback(callback: ScrollCallback) {\n callbacks.splice(\n callbacks.findIndex((cb) => cb.callback === callback),\n 1\n )\n }\n\n const onScroll: ScrollCallback = (data) => {\n for (const { callback } of callbacks) {\n callback(data)\n }\n }\n\n watch(\n [lenisRef, () => props.root],\n ([lenis, root]) => {\n lenis?.on('scroll', onScroll)\n\n if (root) {\n globalLenis.value = lenis\n globalAddCallback.value = addCallback\n globalRemoveCallback.value = removeCallback\n\n onWatcherCleanup(() => {\n globalLenis.value = undefined\n globalAddCallback.value = undefined\n globalRemoveCallback.value = undefined\n })\n }\n },\n { immediate: true }\n )\n\n if (!props.root) {\n provide(LenisSymbol, lenisRef)\n provide(AddCallbackSymbol, addCallback)\n provide(RemoveCallbackSymbol, removeCallback)\n }\n\n return () => {\n if (props.root) {\n return slots.default?.()\n }\n return h('div', { ref: wrapper, ...props?.props }, [\n h('div', { ref: content }, slots.default?.()),\n ])\n }\n },\n})\n\nexport const VueLenis = VueLenisImpl as typeof VueLenisImpl & {\n new (): LenisExposed\n}\n\nexport const vueLenisPlugin: Plugin = (app) => {\n app.component('vue-lenis', VueLenis)\n // Setup a global provide to silence top level useLenis injection warning\n app.provide(LenisSymbol, shallowRef(undefined))\n app.provide(AddCallbackSymbol, undefined)\n app.provide(RemoveCallbackSymbol, undefined)\n}\n\n// @ts-expect-error\ndeclare module '@vue/runtime-core' {\n export interface GlobalComponents {\n 'vue-lenis': typeof VueLenis\n }\n}\n","import type Lenis from 'lenis'\nimport type { ScrollCallback } from 'lenis'\nimport { shallowRef } from 'vue'\n\nexport const globalLenis = shallowRef<Lenis>()\nexport const globalAddCallback =\n shallowRef<(callback: ScrollCallback, priority: number) => void>()\nexport const globalRemoveCallback =\n shallowRef<(callback: ScrollCallback) => void>()\n","import type { ScrollCallback } from 'lenis'\nimport { computed, inject, nextTick, onWatcherCleanup, watch } from 'vue'\nimport {\n AddCallbackSymbol,\n LenisSymbol,\n RemoveCallbackSymbol,\n} from './provider'\nimport { globalAddCallback, globalLenis, globalRemoveCallback } from './store'\n\nexport function useLenis(callback?: ScrollCallback, priority = 0) {\n const lenisInjection = inject(LenisSymbol)\n const addCallbackInjection = inject(AddCallbackSymbol)\n const removeCallbackInjection = inject(RemoveCallbackSymbol)\n\n const addCallback = computed(() =>\n addCallbackInjection ? addCallbackInjection : globalAddCallback.value\n )\n const removeCallback = computed(() =>\n removeCallbackInjection\n ? removeCallbackInjection\n : globalRemoveCallback.value\n )\n\n const lenis = computed(() =>\n lenisInjection?.value ? lenisInjection.value : globalLenis.value\n )\n\n if (typeof window !== 'undefined') {\n // Wait two ticks to make sure the lenis instance is mounted\n nextTick(() => {\n nextTick(() => {\n // @ts-expect-error - import.meta.env is available in vite and nuxt\n if (!lenis.value && import.meta.env.DEV) {\n console.warn(\n 'No lenis instance found, either mount a root lenis instance or wrap your component in a lenis provider'\n )\n }\n })\n })\n }\n\n watch(\n [lenis, addCallback, removeCallback],\n ([lenis, addCallback, removeCallback]) => {\n if (!(lenis && addCallback && removeCallback && callback)) return\n\n addCallback?.(callback, priority)\n callback?.(lenis!)\n\n onWatcherCleanup(() => {\n removeCallback?.(callback)\n })\n },\n {\n immediate: true,\n }\n )\n return lenis\n}\n"],"mappings":"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","names":["shallowRef","shallowRef","onWatcherCleanup","watch","watch","lenis","addCallback","removeCallback","onWatcherCleanup"]}
|
package/dist/lenis.d.ts
CHANGED
|
@@ -157,7 +157,7 @@ type LenisOptions = {
|
|
|
157
157
|
syncTouchLerp?: number;
|
|
158
158
|
/**
|
|
159
159
|
* Manage the the strength of `syncTouch` inertia
|
|
160
|
-
* @default
|
|
160
|
+
* @default 1.7
|
|
161
161
|
*/
|
|
162
162
|
touchInertiaExponent?: number;
|
|
163
163
|
/**
|
|
@@ -218,12 +218,12 @@ type LenisOptions = {
|
|
|
218
218
|
*/
|
|
219
219
|
overscroll?: boolean;
|
|
220
220
|
/**
|
|
221
|
-
* If `true`, Lenis will
|
|
221
|
+
* If `true`, Lenis will automatically run `requestAnimationFrame` loop
|
|
222
222
|
* @default false
|
|
223
223
|
*/
|
|
224
224
|
autoRaf?: boolean;
|
|
225
225
|
/**
|
|
226
|
-
* If `true`, Lenis will
|
|
226
|
+
* If `true`, Lenis will handle anchor links automatically
|
|
227
227
|
* @default false
|
|
228
228
|
*/
|
|
229
229
|
anchors?: boolean | ScrollToOptions;
|
|
@@ -255,6 +255,11 @@ type LenisOptions = {
|
|
|
255
255
|
declare global {
|
|
256
256
|
interface Window {
|
|
257
257
|
lenisVersion: string;
|
|
258
|
+
lenis: {
|
|
259
|
+
version?: string;
|
|
260
|
+
horizontal?: boolean;
|
|
261
|
+
snap?: boolean;
|
|
262
|
+
};
|
|
258
263
|
}
|
|
259
264
|
}
|
|
260
265
|
|