lenis 1.3.12-dev.2 → 1.3.12-dev.3
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/dist/lenis-snap.d.ts +11 -12
- package/dist/lenis-snap.js +12 -26
- 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 +12 -26
- package/dist/lenis-snap.mjs.map +1 -1
- package/dist/lenis.js +1 -1
- 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 +1 -1
- package/dist/lenis.mjs.map +1 -1
- package/package.json +1 -1
package/dist/lenis-snap.d.ts
CHANGED
|
@@ -46,35 +46,37 @@ type OnSnapCallback = (item: SnapItem & {
|
|
|
46
46
|
type SnapOptions = {
|
|
47
47
|
/**
|
|
48
48
|
* Snap type
|
|
49
|
-
* @default
|
|
49
|
+
* @default 'proximity'
|
|
50
50
|
*/
|
|
51
51
|
type?: 'mandatory' | 'proximity' | 'lock';
|
|
52
52
|
/**
|
|
53
|
-
* Linear interpolation (lerp) intensity (between 0 and 1)
|
|
53
|
+
* @description Linear interpolation (lerp) intensity (between 0 and 1)
|
|
54
54
|
*/
|
|
55
55
|
lerp?: number;
|
|
56
56
|
/**
|
|
57
|
-
* The easing function to use for the snap animation
|
|
57
|
+
* @description The easing function to use for the snap animation
|
|
58
58
|
*/
|
|
59
59
|
easing?: EasingFunction;
|
|
60
60
|
/**
|
|
61
|
-
* The duration of the snap animation (in s)
|
|
61
|
+
* @description The duration of the snap animation (in s)
|
|
62
62
|
*/
|
|
63
63
|
duration?: number;
|
|
64
64
|
/**
|
|
65
|
-
*
|
|
65
|
+
* @default '50%'
|
|
66
|
+
* @description The distance threshold from the snap point to the scroll position. Ignored when `type` is `mandatory`. If a percentage, it is relative to the viewport size. If a number, it is absolute.
|
|
66
67
|
*/
|
|
67
68
|
distanceThreshold?: number | `${number}%`;
|
|
68
69
|
/**
|
|
69
|
-
*
|
|
70
|
+
* @default 500
|
|
71
|
+
* @description The debounce delay (in ms) to prevent snapping too often
|
|
70
72
|
*/
|
|
71
73
|
debounce?: number;
|
|
72
74
|
/**
|
|
73
|
-
* Called when the snap starts
|
|
75
|
+
* @description Called when the snap starts
|
|
74
76
|
*/
|
|
75
77
|
onSnapStart?: OnSnapCallback;
|
|
76
78
|
/**
|
|
77
|
-
* Called when the snap completes
|
|
79
|
+
* @description Called when the snap completes
|
|
78
80
|
*/
|
|
79
81
|
onSnapComplete?: OnSnapCallback;
|
|
80
82
|
};
|
|
@@ -85,10 +87,7 @@ type RequiredPick<T, F extends keyof T> = Omit<T, F> & Required<Pick<T, F>>;
|
|
|
85
87
|
*
|
|
86
88
|
* @example
|
|
87
89
|
* const snap = new Snap(lenis, {
|
|
88
|
-
* type: 'mandatory', // 'mandatory', 'proximity'
|
|
89
|
-
* lerp: 0.1,
|
|
90
|
-
* duration: 1,
|
|
91
|
-
* easing: (t) => t,
|
|
90
|
+
* type: 'mandatory', // 'mandatory', 'proximity' or 'lock'
|
|
92
91
|
* onSnapStart: (snap) => {
|
|
93
92
|
* console.log('onSnapStart', snap)
|
|
94
93
|
* },
|
package/dist/lenis-snap.js
CHANGED
|
@@ -169,11 +169,11 @@ var Snap = class {
|
|
|
169
169
|
};
|
|
170
170
|
this.onWindowResize();
|
|
171
171
|
window.addEventListener("resize", this.onWindowResize, false);
|
|
172
|
-
this.onSnapDebounced = debounce(
|
|
173
|
-
|
|
174
|
-
|
|
172
|
+
this.onSnapDebounced = debounce(this.onSnap, this.options.debounce);
|
|
173
|
+
this.lenis.on(
|
|
174
|
+
"virtual-scroll",
|
|
175
|
+
this.options.type === "lock" ? this.onSnap : this.onSnapDebounced
|
|
175
176
|
);
|
|
176
|
-
this.lenis.on("virtual-scroll", this.onSnapDebounced);
|
|
177
177
|
}
|
|
178
178
|
options;
|
|
179
179
|
elements = /* @__PURE__ */ new Map();
|
|
@@ -289,17 +289,6 @@ var Snap = class {
|
|
|
289
289
|
}
|
|
290
290
|
});
|
|
291
291
|
}
|
|
292
|
-
// private onSlide = (e: VirtualScrollData) => {
|
|
293
|
-
// if (this.isStopped) return
|
|
294
|
-
// const { userData, isHorizontal } = this.lenis
|
|
295
|
-
// if (userData?.initiator === 'snap') return
|
|
296
|
-
// const delta = isHorizontal ? e.deltaX : e.deltaY
|
|
297
|
-
// if (delta > 0) {
|
|
298
|
-
// this.next()
|
|
299
|
-
// } else if (delta < 0) {
|
|
300
|
-
// this.previous()
|
|
301
|
-
// }
|
|
302
|
-
// }
|
|
303
292
|
get distanceThreshold() {
|
|
304
293
|
let distanceThreshold = Infinity;
|
|
305
294
|
if (this.options.type === "mandatory") return Infinity;
|
|
@@ -316,31 +305,28 @@ var Snap = class {
|
|
|
316
305
|
}
|
|
317
306
|
onSnap = (e) => {
|
|
318
307
|
if (this.isStopped) return;
|
|
308
|
+
if (e.event.type === "touchmove") return;
|
|
319
309
|
if (this.options.type === "lock" && this.lenis.userData?.initiator === "snap")
|
|
320
310
|
return;
|
|
321
311
|
let { scroll, isHorizontal } = this.lenis;
|
|
322
312
|
const delta = isHorizontal ? e.deltaX : e.deltaY;
|
|
323
|
-
scroll = Math.ceil(this.lenis.scroll);
|
|
313
|
+
scroll = Math.ceil(this.lenis.scroll + delta);
|
|
324
314
|
const snaps = this.computeSnaps();
|
|
325
315
|
if (snaps.length === 0) return;
|
|
326
316
|
let snapIndex;
|
|
317
|
+
const prevSnapIndex = snaps.findLastIndex(({ value }) => value < scroll);
|
|
318
|
+
const nextSnapIndex = snaps.findIndex(({ value }) => value > scroll);
|
|
327
319
|
if (this.options.type === "lock") {
|
|
328
320
|
if (delta > 0) {
|
|
329
|
-
|
|
330
|
-
snapIndex = currentSnapIndex;
|
|
321
|
+
snapIndex = nextSnapIndex;
|
|
331
322
|
} else if (delta < 0) {
|
|
332
|
-
|
|
333
|
-
({ value }) => value < scroll
|
|
334
|
-
);
|
|
335
|
-
snapIndex = currentSnapIndex;
|
|
323
|
+
snapIndex = prevSnapIndex;
|
|
336
324
|
}
|
|
337
325
|
} else {
|
|
338
|
-
let prevSnapIndex = snaps.findLastIndex(({ value }) => value < scroll);
|
|
339
326
|
const prevSnap = snaps[prevSnapIndex];
|
|
340
|
-
const distanceToPrevSnap = Math.abs(scroll - prevSnap.value);
|
|
341
|
-
let nextSnapIndex = snaps.findIndex(({ value }) => value > scroll);
|
|
327
|
+
const distanceToPrevSnap = prevSnap ? Math.abs(scroll - prevSnap.value) : Infinity;
|
|
342
328
|
const nextSnap = snaps[nextSnapIndex];
|
|
343
|
-
const distanceToNextSnap = Math.abs(scroll - nextSnap.value);
|
|
329
|
+
const distanceToNextSnap = nextSnap ? Math.abs(scroll - nextSnap.value) : Infinity;
|
|
344
330
|
snapIndex = distanceToPrevSnap < distanceToNextSnap ? prevSnapIndex : nextSnapIndex;
|
|
345
331
|
}
|
|
346
332
|
if (snapIndex === void 0) return;
|
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: any[]) => void>(\r\n callback: CB,\r\n delay: number\r\n) {\r\n let timer: ReturnType<typeof setTimeout> | undefined\r\n return function <T>(this: T, ...args: Parameters<typeof callback>): void {\r\n let context = this\r\n clearTimeout(timer)\r\n timer = setTimeout(() => {\r\n timer = undefined\r\n callback.apply(context, args)\r\n }, delay)\r\n }\r\n}\r\n","import { debounce } from './debounce'\r\n\r\nfunction removeParentSticky(element: HTMLElement) {\r\n const position = getComputedStyle(element).position\r\n\r\n const isSticky = position === 'sticky'\r\n\r\n if (isSticky) {\r\n element.style.setProperty('position', 'static')\r\n element.dataset.sticky = 'true'\r\n }\r\n\r\n if (element.offsetParent) {\r\n removeParentSticky(element.offsetParent as HTMLElement)\r\n }\r\n}\r\n\r\nfunction addParentSticky(element: HTMLElement) {\r\n if (element?.dataset?.sticky === 'true') {\r\n element.style.removeProperty('position')\r\n delete element.dataset.sticky\r\n }\r\n\r\n if (element.offsetParent) {\r\n addParentSticky(element.offsetParent as HTMLElement)\r\n }\r\n}\r\n\r\nfunction offsetTop(element: HTMLElement, accumulator = 0) {\r\n const top = accumulator + element.offsetTop\r\n if (element.offsetParent) {\r\n return offsetTop(element.offsetParent as HTMLElement, top)\r\n }\r\n return top\r\n}\r\n\r\nfunction offsetLeft(element: HTMLElement, accumulator = 0) {\r\n const left = accumulator + element.offsetLeft\r\n if (element.offsetParent) {\r\n return offsetLeft(element.offsetParent as HTMLElement, left)\r\n }\r\n return left\r\n}\r\n\r\nfunction scrollTop(element: HTMLElement, accumulator = 0) {\r\n const top = accumulator + element.scrollTop\r\n if (element.offsetParent) {\r\n return scrollTop(element.offsetParent as HTMLElement, top)\r\n }\r\n return top + window.scrollY\r\n}\r\n\r\nfunction scrollLeft(element: HTMLElement, accumulator = 0) {\r\n const left = accumulator + element.scrollLeft\r\n if (element.offsetParent) {\r\n return scrollLeft(element.offsetParent as HTMLElement, left)\r\n }\r\n return left + window.scrollX\r\n}\r\n\r\nexport type SnapElementOptions = {\r\n align?: string | string[]\r\n ignoreSticky?: boolean\r\n ignoreTransform?: boolean\r\n}\r\n\r\ntype Rect = {\r\n top: number\r\n left: number\r\n width: number\r\n height: number\r\n x: number\r\n y: number\r\n bottom: number\r\n right: number\r\n element: HTMLElement\r\n}\r\n\r\nexport class SnapElement {\r\n element: HTMLElement\r\n options: SnapElementOptions\r\n align: string[]\r\n // @ts-ignore\r\n rect: Rect = {}\r\n wrapperResizeObserver: ResizeObserver\r\n resizeObserver: ResizeObserver\r\n debouncedWrapperResize: () => void\r\n\r\n constructor(\r\n element: HTMLElement,\r\n {\r\n align = ['start'],\r\n ignoreSticky = true,\r\n ignoreTransform = false,\r\n }: SnapElementOptions = {}\r\n ) {\r\n this.element = element\r\n\r\n this.options = { align, ignoreSticky, ignoreTransform }\r\n\r\n this.align = [align].flat()\r\n\r\n this.debouncedWrapperResize = debounce(this.onWrapperResize, 500)\r\n\r\n this.wrapperResizeObserver = new ResizeObserver(this.debouncedWrapperResize)\r\n this.wrapperResizeObserver.observe(document.body)\r\n this.onWrapperResize()\r\n\r\n this.resizeObserver = new ResizeObserver(this.onResize)\r\n this.resizeObserver.observe(this.element)\r\n this.setRect({\r\n width: this.element.offsetWidth,\r\n height: this.element.offsetHeight,\r\n })\r\n }\r\n\r\n destroy() {\r\n this.wrapperResizeObserver.disconnect()\r\n this.resizeObserver.disconnect()\r\n }\r\n\r\n setRect({\r\n top,\r\n left,\r\n width,\r\n height,\r\n element,\r\n }: {\r\n top?: number\r\n left?: number\r\n width?: number\r\n height?: number\r\n element?: HTMLElement\r\n } = {}) {\r\n top = top ?? this.rect.top\r\n left = left ?? this.rect.left\r\n width = width ?? this.rect.width\r\n height = height ?? this.rect.height\r\n element = element ?? this.rect.element\r\n\r\n if (\r\n top === this.rect.top &&\r\n left === this.rect.left &&\r\n width === this.rect.width &&\r\n height === this.rect.height &&\r\n element === this.rect.element\r\n )\r\n return\r\n\r\n this.rect.top = top\r\n this.rect.y = top\r\n this.rect.width = width\r\n this.rect.height = height\r\n this.rect.left = left\r\n this.rect.x = left\r\n this.rect.bottom = top + height\r\n this.rect.right = left + width\r\n }\r\n\r\n onWrapperResize = () => {\r\n let top, left\r\n\r\n if (this.options.ignoreSticky) removeParentSticky(this.element)\r\n if (this.options.ignoreTransform) {\r\n top = offsetTop(this.element)\r\n left = offsetLeft(this.element)\r\n } else {\r\n const rect = this.element.getBoundingClientRect()\r\n top = rect.top + scrollTop(this.element)\r\n left = rect.left + scrollLeft(this.element)\r\n }\r\n if (this.options.ignoreSticky) addParentSticky(this.element)\r\n\r\n this.setRect({ top, left })\r\n }\r\n\r\n onResize = ([entry]: ResizeObserverEntry[]) => {\r\n if (!entry?.borderBoxSize[0]) return\r\n const width = entry.borderBoxSize[0].inlineSize\r\n const height = entry.borderBoxSize[0].blockSize\r\n\r\n this.setRect({ width, height })\r\n }\r\n}\r\n","let index = 0\r\n\r\nexport type UID = number\r\n\r\nexport function uid(): UID {\r\n return index++\r\n}\r\n","import type Lenis from 'lenis'\r\nimport type { VirtualScrollData } from 'lenis'\r\nimport { debounce } from './debounce'\r\nimport type { SnapElementOptions } from './element'\r\nimport { SnapElement } from './element'\r\nimport type { SnapItem, SnapOptions } from './types'\r\nimport type { UID } from './uid'\r\nimport { uid } from './uid'\r\n\r\n// TODO:\r\n// - fix wheel scrolling after limits (see console scroll to)\r\n// - fix touch scroll, do not snap when not released\r\n// - arrow, spacebar\r\n\r\ntype RequiredPick<T, F extends keyof T> = Omit<T, F> & Required<Pick<T, F>>\r\n\r\n/**\r\n * Snap class to handle the snap functionality\r\n *\r\n * @example\r\n * const snap = new Snap(lenis, {\r\n * type: 'mandatory', // 'mandatory', 'proximity'\r\n * lerp: 0.1,\r\n * duration: 1,\r\n * easing: (t) => t,\r\n * onSnapStart: (snap) => {\r\n * console.log('onSnapStart', snap)\r\n * },\r\n * onSnapComplete: (snap) => {\r\n * console.log('onSnapComplete', snap)\r\n * },\r\n * })\r\n *\r\n * snap.add(500) // snap at 500px\r\n *\r\n * const removeSnap = snap.add(500)\r\n *\r\n * if (someCondition) {\r\n * removeSnap()\r\n * }\r\n */\r\nexport class Snap {\r\n options: RequiredPick<SnapOptions, 'type' | 'debounce'>\r\n elements = new Map<UID, SnapElement>()\r\n snaps = new Map<UID, SnapItem>()\r\n viewport: { width: number; height: number } = {\r\n width: window.innerWidth,\r\n height: window.innerHeight,\r\n }\r\n isStopped = false\r\n onSnapDebounced: (e: VirtualScrollData) => void\r\n currentSnapIndex?: number\r\n\r\n constructor(\r\n private lenis: Lenis,\r\n {\r\n type = 'proximity',\r\n lerp,\r\n easing,\r\n duration,\r\n distanceThreshold = '50%', // useless when type is \"mandatory\"\r\n debounce: debounceDelay = 500,\r\n onSnapStart,\r\n onSnapComplete,\r\n }: SnapOptions = {}\r\n ) {\r\n this.options = {\r\n type,\r\n lerp,\r\n easing,\r\n duration,\r\n distanceThreshold,\r\n debounce: debounceDelay,\r\n onSnapStart,\r\n onSnapComplete,\r\n }\r\n\r\n this.onWindowResize()\r\n window.addEventListener('resize', this.onWindowResize, false)\r\n\r\n this.onSnapDebounced = debounce(\r\n this.onSnap,\r\n this.options.type === 'lock' ? 0 : this.options.debounce\r\n )\r\n\r\n this.lenis.on('virtual-scroll', this.onSnapDebounced)\r\n }\r\n\r\n /**\r\n * Destroy the snap instance\r\n */\r\n destroy() {\r\n this.lenis.off('virtual-scroll', this.onSnapDebounced)\r\n window.removeEventListener('resize', this.onWindowResize, false)\r\n this.elements.forEach((element) => element.destroy())\r\n }\r\n\r\n /**\r\n * Start the snap after it has been stopped\r\n */\r\n start() {\r\n this.isStopped = false\r\n }\r\n\r\n /**\r\n * Stop the snap\r\n */\r\n stop() {\r\n this.isStopped = true\r\n }\r\n\r\n /**\r\n * Add a snap to the snap instance\r\n *\r\n * @param value The value to snap to\r\n * @param userData User data that will be forwarded through the snap event\r\n * @returns Unsubscribe function\r\n */\r\n add(value: number) {\r\n const id = uid()\r\n\r\n this.snaps.set(id, { value })\r\n\r\n return () => this.snaps.delete(id)\r\n }\r\n\r\n /**\r\n * Add an element to the snap instance\r\n *\r\n * @param element The element to add\r\n * @param options The options for the element\r\n * @returns Unsubscribe function\r\n */\r\n addElement(element: HTMLElement, options: SnapElementOptions = {}) {\r\n const id = uid()\r\n\r\n this.elements.set(id, new SnapElement(element, options))\r\n\r\n return () => this.elements.delete(id)\r\n }\r\n\r\n addElements(elements: HTMLElement[], options: SnapElementOptions = {}) {\r\n elements.forEach((element) => this.addElement(element, options))\r\n }\r\n\r\n private onWindowResize = () => {\r\n this.viewport.width = window.innerWidth\r\n this.viewport.height = window.innerHeight\r\n }\r\n\r\n private computeSnaps = () => {\r\n const { isHorizontal } = this.lenis\r\n\r\n let snaps = [...this.snaps.values()] as SnapItem[]\r\n\r\n this.elements.forEach(({ rect, align }) => {\r\n let value: number | undefined\r\n\r\n align.forEach((align) => {\r\n if (align === 'start') {\r\n value = rect.top\r\n } else if (align === 'center') {\r\n value = isHorizontal\r\n ? rect.left + rect.width / 2 - this.viewport.width / 2\r\n : rect.top + rect.height / 2 - this.viewport.height / 2\r\n } else if (align === 'end') {\r\n value = isHorizontal\r\n ? rect.left + rect.width - this.viewport.width\r\n : rect.top + rect.height - this.viewport.height\r\n }\r\n\r\n if (typeof value === 'number') {\r\n snaps.push({ value: Math.ceil(value) })\r\n }\r\n })\r\n })\r\n\r\n snaps = snaps.sort((a, b) => Math.abs(a.value) - Math.abs(b.value))\r\n\r\n return snaps\r\n }\r\n\r\n previous() {\r\n this.goTo((this.currentSnapIndex ?? 0) - 1)\r\n }\r\n\r\n next() {\r\n this.goTo((this.currentSnapIndex ?? 0) + 1)\r\n }\r\n\r\n goTo(index: number) {\r\n const snaps = this.computeSnaps()\r\n\r\n if (snaps.length === 0) return\r\n\r\n this.currentSnapIndex = Math.max(0, Math.min(index, snaps.length - 1))\r\n\r\n const currentSnap = snaps[this.currentSnapIndex]\r\n if (currentSnap === undefined) return\r\n\r\n this.lenis.scrollTo(currentSnap.value, {\r\n duration: this.options.duration,\r\n easing: this.options.easing,\r\n lerp: this.options.lerp,\r\n lock: this.options.type === 'lock',\r\n userData: { initiator: 'snap' },\r\n onStart: () => {\r\n this.options.onSnapStart?.({\r\n index: this.currentSnapIndex,\r\n ...currentSnap,\r\n })\r\n },\r\n onComplete: () => {\r\n this.options.onSnapComplete?.({\r\n index: this.currentSnapIndex,\r\n ...currentSnap,\r\n })\r\n },\r\n })\r\n }\r\n\r\n // private onSlide = (e: VirtualScrollData) => {\r\n // if (this.isStopped) return\r\n\r\n // const { userData, isHorizontal } = this.lenis\r\n\r\n // if (userData?.initiator === 'snap') return\r\n\r\n // const delta = isHorizontal ? e.deltaX : e.deltaY\r\n\r\n // if (delta > 0) {\r\n // this.next()\r\n // } else if (delta < 0) {\r\n // this.previous()\r\n // }\r\n // }\r\n\r\n get distanceThreshold() {\r\n let distanceThreshold = Infinity\r\n if (this.options.type === 'mandatory') return Infinity\r\n\r\n const { isHorizontal } = this.lenis\r\n\r\n const axis = isHorizontal ? 'width' : 'height'\r\n\r\n if (\r\n typeof this.options.distanceThreshold === 'string' &&\r\n this.options.distanceThreshold.endsWith('%')\r\n ) {\r\n distanceThreshold =\r\n (Number(this.options.distanceThreshold.replace('%', '')) / 100) *\r\n this.viewport[axis]\r\n } else if (typeof this.options.distanceThreshold === 'number') {\r\n distanceThreshold = this.options.distanceThreshold\r\n } else {\r\n distanceThreshold = this.viewport[axis]\r\n }\r\n\r\n return distanceThreshold\r\n }\r\n\r\n private onSnap = (e: VirtualScrollData) => {\r\n if (this.isStopped) return\r\n\r\n if (\r\n this.options.type === 'lock' &&\r\n this.lenis.userData?.initiator === 'snap'\r\n )\r\n return\r\n\r\n let { scroll, isHorizontal } = this.lenis\r\n const delta = isHorizontal ? e.deltaX : e.deltaY\r\n scroll = Math.ceil(this.lenis.scroll)\r\n\r\n const snaps = this.computeSnaps()\r\n\r\n if (snaps.length === 0) return\r\n\r\n let snapIndex\r\n\r\n if (this.options.type === 'lock') {\r\n if (delta > 0) {\r\n const currentSnapIndex = snaps.findIndex(({ value }) => value > scroll)\r\n snapIndex = currentSnapIndex\r\n } else if (delta < 0) {\r\n const currentSnapIndex = snaps.findLastIndex(\r\n ({ value }) => value < scroll\r\n )\r\n snapIndex = currentSnapIndex\r\n }\r\n } else {\r\n let prevSnapIndex = snaps.findLastIndex(({ value }) => value < scroll)\r\n // if (prevSnapIndex === -1) prevSnapIndex = 0\r\n const prevSnap = snaps[prevSnapIndex]!\r\n const distanceToPrevSnap = Math.abs(scroll - prevSnap.value)\r\n\r\n let nextSnapIndex = snaps.findIndex(({ value }) => value > scroll)\r\n // if (nextSnapIndex === -1) nextSnapIndex = snaps.length - 1\r\n const nextSnap = snaps[nextSnapIndex]!\r\n const distanceToNextSnap = Math.abs(scroll - nextSnap.value)\r\n snapIndex =\r\n distanceToPrevSnap < distanceToNextSnap ? prevSnapIndex : nextSnapIndex\r\n }\r\n\r\n if (snapIndex === undefined) return\r\n if (snapIndex === -1) return\r\n\r\n snapIndex = Math.max(0, Math.min(snapIndex, snaps.length - 1))\r\n\r\n const snap = snaps[snapIndex]!\r\n\r\n const distance = Math.abs(scroll - snap.value)\r\n\r\n if (distance <= this.distanceThreshold) {\r\n this.goTo(snapIndex)\r\n }\r\n }\r\n\r\n resize() {\r\n this.elements.forEach((element) => element.onWrapperResize())\r\n }\r\n}\r\n","// This file serves as an entry point for the package\r\nimport { Snap } from './src/snap'\r\nglobalThis.Snap = Snap\r\n"],"mappings":";AAAO,SAAS,SACd,UACA,OACA;AACA,MAAI;AACJ,SAAO,YAAyB,MAAyC;AACvE,QAAI,UAAU;AACd,iBAAa,KAAK;AAClB,YAAQ,WAAW,MAAM;AACvB,cAAQ;AACR,eAAS,MAAM,SAAS,IAAI;AAAA,IAC9B,GAAG,KAAK;AAAA,EACV;AACF;;;ACXA,SAAS,mBAAmB,SAAsB;AAChD,QAAM,WAAW,iBAAiB,OAAO,EAAE;AAE3C,QAAM,WAAW,aAAa;AAE9B,MAAI,UAAU;AACZ,YAAQ,MAAM,YAAY,YAAY,QAAQ;AAC9C,YAAQ,QAAQ,SAAS;AAAA,EAC3B;AAEA,MAAI,QAAQ,cAAc;AACxB,uBAAmB,QAAQ,YAA2B;AAAA,EACxD;AACF;AAEA,SAAS,gBAAgB,SAAsB;AAC7C,MAAI,SAAS,SAAS,WAAW,QAAQ;AACvC,YAAQ,MAAM,eAAe,UAAU;AACvC,WAAO,QAAQ,QAAQ;AAAA,EACzB;AAEA,MAAI,QAAQ,cAAc;AACxB,oBAAgB,QAAQ,YAA2B;AAAA,EACrD;AACF;AAEA,SAAS,UAAU,SAAsB,cAAc,GAAG;AACxD,QAAM,MAAM,cAAc,QAAQ;AAClC,MAAI,QAAQ,cAAc;AACxB,WAAO,UAAU,QAAQ,cAA6B,GAAG;AAAA,EAC3D;AACA,SAAO;AACT;AAEA,SAAS,WAAW,SAAsB,cAAc,GAAG;AACzD,QAAM,OAAO,cAAc,QAAQ;AACnC,MAAI,QAAQ,cAAc;AACxB,WAAO,WAAW,QAAQ,cAA6B,IAAI;AAAA,EAC7D;AACA,SAAO;AACT;AAEA,SAAS,UAAU,SAAsB,cAAc,GAAG;AACxD,QAAM,MAAM,cAAc,QAAQ;AAClC,MAAI,QAAQ,cAAc;AACxB,WAAO,UAAU,QAAQ,cAA6B,GAAG;AAAA,EAC3D;AACA,SAAO,MAAM,OAAO;AACtB;AAEA,SAAS,WAAW,SAAsB,cAAc,GAAG;AACzD,QAAM,OAAO,cAAc,QAAQ;AACnC,MAAI,QAAQ,cAAc;AACxB,WAAO,WAAW,QAAQ,cAA6B,IAAI;AAAA,EAC7D;AACA,SAAO,OAAO,OAAO;AACvB;AAoBO,IAAM,cAAN,MAAkB;AAAA,EACvB;AAAA,EACA;AAAA,EACA;AAAA;AAAA,EAEA,OAAa,CAAC;AAAA,EACd;AAAA,EACA;AAAA,EACA;AAAA,EAEA,YACE,SACA;AAAA,IACE,QAAQ,CAAC,OAAO;AAAA,IAChB,eAAe;AAAA,IACf,kBAAkB;AAAA,EACpB,IAAwB,CAAC,GACzB;AACA,SAAK,UAAU;AAEf,SAAK,UAAU,EAAE,OAAO,cAAc,gBAAgB;AAEtD,SAAK,QAAQ,CAAC,KAAK,EAAE,KAAK;AAE1B,SAAK,yBAAyB,SAAS,KAAK,iBAAiB,GAAG;AAEhE,SAAK,wBAAwB,IAAI,eAAe,KAAK,sBAAsB;AAC3E,SAAK,sBAAsB,QAAQ,SAAS,IAAI;AAChD,SAAK,gBAAgB;AAErB,SAAK,iBAAiB,IAAI,eAAe,KAAK,QAAQ;AACtD,SAAK,eAAe,QAAQ,KAAK,OAAO;AACxC,SAAK,QAAQ;AAAA,MACX,OAAO,KAAK,QAAQ;AAAA,MACpB,QAAQ,KAAK,QAAQ;AAAA,IACvB,CAAC;AAAA,EACH;AAAA,EAEA,UAAU;AACR,SAAK,sBAAsB,WAAW;AACtC,SAAK,eAAe,WAAW;AAAA,EACjC;AAAA,EAEA,QAAQ;AAAA,IACN;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,IAMI,CAAC,GAAG;AACN,UAAM,OAAO,KAAK,KAAK;AACvB,WAAO,QAAQ,KAAK,KAAK;AACzB,YAAQ,SAAS,KAAK,KAAK;AAC3B,aAAS,UAAU,KAAK,KAAK;AAC7B,cAAU,WAAW,KAAK,KAAK;AAE/B,QACE,QAAQ,KAAK,KAAK,OAClB,SAAS,KAAK,KAAK,QACnB,UAAU,KAAK,KAAK,SACpB,WAAW,KAAK,KAAK,UACrB,YAAY,KAAK,KAAK;AAEtB;AAEF,SAAK,KAAK,MAAM;AAChB,SAAK,KAAK,IAAI;AACd,SAAK,KAAK,QAAQ;AAClB,SAAK,KAAK,SAAS;AACnB,SAAK,KAAK,OAAO;AACjB,SAAK,KAAK,IAAI;AACd,SAAK,KAAK,SAAS,MAAM;AACzB,SAAK,KAAK,QAAQ,OAAO;AAAA,EAC3B;AAAA,EAEA,kBAAkB,MAAM;AACtB,QAAI,KAAK;AAET,QAAI,KAAK,QAAQ,aAAc,oBAAmB,KAAK,OAAO;AAC9D,QAAI,KAAK,QAAQ,iBAAiB;AAChC,YAAM,UAAU,KAAK,OAAO;AAC5B,aAAO,WAAW,KAAK,OAAO;AAAA,IAChC,OAAO;AACL,YAAM,OAAO,KAAK,QAAQ,sBAAsB;AAChD,YAAM,KAAK,MAAM,UAAU,KAAK,OAAO;AACvC,aAAO,KAAK,OAAO,WAAW,KAAK,OAAO;AAAA,IAC5C;AACA,QAAI,KAAK,QAAQ,aAAc,iBAAgB,KAAK,OAAO;AAE3D,SAAK,QAAQ,EAAE,KAAK,KAAK,CAAC;AAAA,EAC5B;AAAA,EAEA,WAAW,CAAC,CAAC,KAAK,MAA6B;AAC7C,QAAI,CAAC,OAAO,cAAc,CAAC,EAAG;AAC9B,UAAM,QAAQ,MAAM,cAAc,CAAC,EAAE;AACrC,UAAM,SAAS,MAAM,cAAc,CAAC,EAAE;AAEtC,SAAK,QAAQ,EAAE,OAAO,OAAO,CAAC;AAAA,EAChC;AACF;;;ACvLA,IAAI,QAAQ;AAIL,SAAS,MAAW;AACzB,SAAO;AACT;;;ACmCO,IAAM,OAAN,MAAW;AAAA,EAYhB,YACU,OACR;AAAA,IACE,OAAO;AAAA,IACP;AAAA,IACA;AAAA,IACA;AAAA,IACA,oBAAoB;AAAA;AAAA,IACpB,UAAU,gBAAgB;AAAA,IAC1B;AAAA,IACA;AAAA,EACF,IAAiB,CAAC,GAClB;AAXQ;AAYR,SAAK,UAAU;AAAA,MACb;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,UAAU;AAAA,MACV;AAAA,MACA;AAAA,IACF;AAEA,SAAK,eAAe;AACpB,WAAO,iBAAiB,UAAU,KAAK,gBAAgB,KAAK;AAE5D,SAAK,kBAAkB;AAAA,MACrB,KAAK;AAAA,MACL,KAAK,QAAQ,SAAS,SAAS,IAAI,KAAK,QAAQ;AAAA,IAClD;AAEA,SAAK,MAAM,GAAG,kBAAkB,KAAK,eAAe;AAAA,EACtD;AAAA,EA5CA;AAAA,EACA,WAAW,oBAAI,IAAsB;AAAA,EACrC,QAAQ,oBAAI,IAAmB;AAAA,EAC/B,WAA8C;AAAA,IAC5C,OAAO,OAAO;AAAA,IACd,QAAQ,OAAO;AAAA,EACjB;AAAA,EACA,YAAY;AAAA,EACZ;AAAA,EACA;AAAA;AAAA;AAAA;AAAA,EAwCA,UAAU;AACR,SAAK,MAAM,IAAI,kBAAkB,KAAK,eAAe;AACrD,WAAO,oBAAoB,UAAU,KAAK,gBAAgB,KAAK;AAC/D,SAAK,SAAS,QAAQ,CAAC,YAAY,QAAQ,QAAQ,CAAC;AAAA,EACtD;AAAA;AAAA;AAAA;AAAA,EAKA,QAAQ;AACN,SAAK,YAAY;AAAA,EACnB;AAAA;AAAA;AAAA;AAAA,EAKA,OAAO;AACL,SAAK,YAAY;AAAA,EACnB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,IAAI,OAAe;AACjB,UAAM,KAAK,IAAI;AAEf,SAAK,MAAM,IAAI,IAAI,EAAE,MAAM,CAAC;AAE5B,WAAO,MAAM,KAAK,MAAM,OAAO,EAAE;AAAA,EACnC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,WAAW,SAAsB,UAA8B,CAAC,GAAG;AACjE,UAAM,KAAK,IAAI;AAEf,SAAK,SAAS,IAAI,IAAI,IAAI,YAAY,SAAS,OAAO,CAAC;AAEvD,WAAO,MAAM,KAAK,SAAS,OAAO,EAAE;AAAA,EACtC;AAAA,EAEA,YAAY,UAAyB,UAA8B,CAAC,GAAG;AACrE,aAAS,QAAQ,CAAC,YAAY,KAAK,WAAW,SAAS,OAAO,CAAC;AAAA,EACjE;AAAA,EAEQ,iBAAiB,MAAM;AAC7B,SAAK,SAAS,QAAQ,OAAO;AAC7B,SAAK,SAAS,SAAS,OAAO;AAAA,EAChC;AAAA,EAEQ,eAAe,MAAM;AAC3B,UAAM,EAAE,aAAa,IAAI,KAAK;AAE9B,QAAI,QAAQ,CAAC,GAAG,KAAK,MAAM,OAAO,CAAC;AAEnC,SAAK,SAAS,QAAQ,CAAC,EAAE,MAAM,MAAM,MAAM;AACzC,UAAI;AAEJ,YAAM,QAAQ,CAACA,WAAU;AACvB,YAAIA,WAAU,SAAS;AACrB,kBAAQ,KAAK;AAAA,QACf,WAAWA,WAAU,UAAU;AAC7B,kBAAQ,eACJ,KAAK,OAAO,KAAK,QAAQ,IAAI,KAAK,SAAS,QAAQ,IACnD,KAAK,MAAM,KAAK,SAAS,IAAI,KAAK,SAAS,SAAS;AAAA,QAC1D,WAAWA,WAAU,OAAO;AAC1B,kBAAQ,eACJ,KAAK,OAAO,KAAK,QAAQ,KAAK,SAAS,QACvC,KAAK,MAAM,KAAK,SAAS,KAAK,SAAS;AAAA,QAC7C;AAEA,YAAI,OAAO,UAAU,UAAU;AAC7B,gBAAM,KAAK,EAAE,OAAO,KAAK,KAAK,KAAK,EAAE,CAAC;AAAA,QACxC;AAAA,MACF,CAAC;AAAA,IACH,CAAC;AAED,YAAQ,MAAM,KAAK,CAAC,GAAG,MAAM,KAAK,IAAI,EAAE,KAAK,IAAI,KAAK,IAAI,EAAE,KAAK,CAAC;AAElE,WAAO;AAAA,EACT;AAAA,EAEA,WAAW;AACT,SAAK,MAAM,KAAK,oBAAoB,KAAK,CAAC;AAAA,EAC5C;AAAA,EAEA,OAAO;AACL,SAAK,MAAM,KAAK,oBAAoB,KAAK,CAAC;AAAA,EAC5C;AAAA,EAEA,KAAKC,QAAe;AAClB,UAAM,QAAQ,KAAK,aAAa;AAEhC,QAAI,MAAM,WAAW,EAAG;AAExB,SAAK,mBAAmB,KAAK,IAAI,GAAG,KAAK,IAAIA,QAAO,MAAM,SAAS,CAAC,CAAC;AAErE,UAAM,cAAc,MAAM,KAAK,gBAAgB;AAC/C,QAAI,gBAAgB,OAAW;AAE/B,SAAK,MAAM,SAAS,YAAY,OAAO;AAAA,MACrC,UAAU,KAAK,QAAQ;AAAA,MACvB,QAAQ,KAAK,QAAQ;AAAA,MACrB,MAAM,KAAK,QAAQ;AAAA,MACnB,MAAM,KAAK,QAAQ,SAAS;AAAA,MAC5B,UAAU,EAAE,WAAW,OAAO;AAAA,MAC9B,SAAS,MAAM;AACb,aAAK,QAAQ,cAAc;AAAA,UACzB,OAAO,KAAK;AAAA,UACZ,GAAG;AAAA,QACL,CAAC;AAAA,MACH;AAAA,MACA,YAAY,MAAM;AAChB,aAAK,QAAQ,iBAAiB;AAAA,UAC5B,OAAO,KAAK;AAAA,UACZ,GAAG;AAAA,QACL,CAAC;AAAA,MACH;AAAA,IACF,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAkBA,IAAI,oBAAoB;AACtB,QAAI,oBAAoB;AACxB,QAAI,KAAK,QAAQ,SAAS,YAAa,QAAO;AAE9C,UAAM,EAAE,aAAa,IAAI,KAAK;AAE9B,UAAM,OAAO,eAAe,UAAU;AAEtC,QACE,OAAO,KAAK,QAAQ,sBAAsB,YAC1C,KAAK,QAAQ,kBAAkB,SAAS,GAAG,GAC3C;AACA,0BACG,OAAO,KAAK,QAAQ,kBAAkB,QAAQ,KAAK,EAAE,CAAC,IAAI,MAC3D,KAAK,SAAS,IAAI;AAAA,IACtB,WAAW,OAAO,KAAK,QAAQ,sBAAsB,UAAU;AAC7D,0BAAoB,KAAK,QAAQ;AAAA,IACnC,OAAO;AACL,0BAAoB,KAAK,SAAS,IAAI;AAAA,IACxC;AAEA,WAAO;AAAA,EACT;AAAA,EAEQ,SAAS,CAAC,MAAyB;AACzC,QAAI,KAAK,UAAW;AAEpB,QACE,KAAK,QAAQ,SAAS,UACtB,KAAK,MAAM,UAAU,cAAc;AAEnC;AAEF,QAAI,EAAE,QAAQ,aAAa,IAAI,KAAK;AACpC,UAAM,QAAQ,eAAe,EAAE,SAAS,EAAE;AAC1C,aAAS,KAAK,KAAK,KAAK,MAAM,MAAM;AAEpC,UAAM,QAAQ,KAAK,aAAa;AAEhC,QAAI,MAAM,WAAW,EAAG;AAExB,QAAI;AAEJ,QAAI,KAAK,QAAQ,SAAS,QAAQ;AAChC,UAAI,QAAQ,GAAG;AACb,cAAM,mBAAmB,MAAM,UAAU,CAAC,EAAE,MAAM,MAAM,QAAQ,MAAM;AACtE,oBAAY;AAAA,MACd,WAAW,QAAQ,GAAG;AACpB,cAAM,mBAAmB,MAAM;AAAA,UAC7B,CAAC,EAAE,MAAM,MAAM,QAAQ;AAAA,QACzB;AACA,oBAAY;AAAA,MACd;AAAA,IACF,OAAO;AACL,UAAI,gBAAgB,MAAM,cAAc,CAAC,EAAE,MAAM,MAAM,QAAQ,MAAM;AAErE,YAAM,WAAW,MAAM,aAAa;AACpC,YAAM,qBAAqB,KAAK,IAAI,SAAS,SAAS,KAAK;AAE3D,UAAI,gBAAgB,MAAM,UAAU,CAAC,EAAE,MAAM,MAAM,QAAQ,MAAM;AAEjE,YAAM,WAAW,MAAM,aAAa;AACpC,YAAM,qBAAqB,KAAK,IAAI,SAAS,SAAS,KAAK;AAC3D,kBACE,qBAAqB,qBAAqB,gBAAgB;AAAA,IAC9D;AAEA,QAAI,cAAc,OAAW;AAC7B,QAAI,cAAc,GAAI;AAEtB,gBAAY,KAAK,IAAI,GAAG,KAAK,IAAI,WAAW,MAAM,SAAS,CAAC,CAAC;AAE7D,UAAM,OAAO,MAAM,SAAS;AAE5B,UAAM,WAAW,KAAK,IAAI,SAAS,KAAK,KAAK;AAE7C,QAAI,YAAY,KAAK,mBAAmB;AACtC,WAAK,KAAK,SAAS;AAAA,IACrB;AAAA,EACF;AAAA,EAEA,SAAS;AACP,SAAK,SAAS,QAAQ,CAAC,YAAY,QAAQ,gBAAgB,CAAC;AAAA,EAC9D;AACF;;;AC/TA,WAAW,OAAO;","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: any[]) => void>(\r\n callback: CB,\r\n delay: number\r\n) {\r\n let timer: ReturnType<typeof setTimeout> | undefined\r\n return function <T>(this: T, ...args: Parameters<typeof callback>): void {\r\n let context = this\r\n clearTimeout(timer)\r\n timer = setTimeout(() => {\r\n timer = undefined\r\n callback.apply(context, args)\r\n }, delay)\r\n }\r\n}\r\n","import { debounce } from './debounce'\r\n\r\nfunction removeParentSticky(element: HTMLElement) {\r\n const position = getComputedStyle(element).position\r\n\r\n const isSticky = position === 'sticky'\r\n\r\n if (isSticky) {\r\n element.style.setProperty('position', 'static')\r\n element.dataset.sticky = 'true'\r\n }\r\n\r\n if (element.offsetParent) {\r\n removeParentSticky(element.offsetParent as HTMLElement)\r\n }\r\n}\r\n\r\nfunction addParentSticky(element: HTMLElement) {\r\n if (element?.dataset?.sticky === 'true') {\r\n element.style.removeProperty('position')\r\n delete element.dataset.sticky\r\n }\r\n\r\n if (element.offsetParent) {\r\n addParentSticky(element.offsetParent as HTMLElement)\r\n }\r\n}\r\n\r\nfunction offsetTop(element: HTMLElement, accumulator = 0) {\r\n const top = accumulator + element.offsetTop\r\n if (element.offsetParent) {\r\n return offsetTop(element.offsetParent as HTMLElement, top)\r\n }\r\n return top\r\n}\r\n\r\nfunction offsetLeft(element: HTMLElement, accumulator = 0) {\r\n const left = accumulator + element.offsetLeft\r\n if (element.offsetParent) {\r\n return offsetLeft(element.offsetParent as HTMLElement, left)\r\n }\r\n return left\r\n}\r\n\r\nfunction scrollTop(element: HTMLElement, accumulator = 0) {\r\n const top = accumulator + element.scrollTop\r\n if (element.offsetParent) {\r\n return scrollTop(element.offsetParent as HTMLElement, top)\r\n }\r\n return top + window.scrollY\r\n}\r\n\r\nfunction scrollLeft(element: HTMLElement, accumulator = 0) {\r\n const left = accumulator + element.scrollLeft\r\n if (element.offsetParent) {\r\n return scrollLeft(element.offsetParent as HTMLElement, left)\r\n }\r\n return left + window.scrollX\r\n}\r\n\r\nexport type SnapElementOptions = {\r\n align?: string | string[]\r\n ignoreSticky?: boolean\r\n ignoreTransform?: boolean\r\n}\r\n\r\ntype Rect = {\r\n top: number\r\n left: number\r\n width: number\r\n height: number\r\n x: number\r\n y: number\r\n bottom: number\r\n right: number\r\n element: HTMLElement\r\n}\r\n\r\nexport class SnapElement {\r\n element: HTMLElement\r\n options: SnapElementOptions\r\n align: string[]\r\n // @ts-ignore\r\n rect: Rect = {}\r\n wrapperResizeObserver: ResizeObserver\r\n resizeObserver: ResizeObserver\r\n debouncedWrapperResize: () => void\r\n\r\n constructor(\r\n element: HTMLElement,\r\n {\r\n align = ['start'],\r\n ignoreSticky = true,\r\n ignoreTransform = false,\r\n }: SnapElementOptions = {}\r\n ) {\r\n this.element = element\r\n\r\n this.options = { align, ignoreSticky, ignoreTransform }\r\n\r\n this.align = [align].flat()\r\n\r\n this.debouncedWrapperResize = debounce(this.onWrapperResize, 500)\r\n\r\n this.wrapperResizeObserver = new ResizeObserver(this.debouncedWrapperResize)\r\n this.wrapperResizeObserver.observe(document.body)\r\n this.onWrapperResize()\r\n\r\n this.resizeObserver = new ResizeObserver(this.onResize)\r\n this.resizeObserver.observe(this.element)\r\n this.setRect({\r\n width: this.element.offsetWidth,\r\n height: this.element.offsetHeight,\r\n })\r\n }\r\n\r\n destroy() {\r\n this.wrapperResizeObserver.disconnect()\r\n this.resizeObserver.disconnect()\r\n }\r\n\r\n setRect({\r\n top,\r\n left,\r\n width,\r\n height,\r\n element,\r\n }: {\r\n top?: number\r\n left?: number\r\n width?: number\r\n height?: number\r\n element?: HTMLElement\r\n } = {}) {\r\n top = top ?? this.rect.top\r\n left = left ?? this.rect.left\r\n width = width ?? this.rect.width\r\n height = height ?? this.rect.height\r\n element = element ?? this.rect.element\r\n\r\n if (\r\n top === this.rect.top &&\r\n left === this.rect.left &&\r\n width === this.rect.width &&\r\n height === this.rect.height &&\r\n element === this.rect.element\r\n )\r\n return\r\n\r\n this.rect.top = top\r\n this.rect.y = top\r\n this.rect.width = width\r\n this.rect.height = height\r\n this.rect.left = left\r\n this.rect.x = left\r\n this.rect.bottom = top + height\r\n this.rect.right = left + width\r\n }\r\n\r\n onWrapperResize = () => {\r\n let top, left\r\n\r\n if (this.options.ignoreSticky) removeParentSticky(this.element)\r\n if (this.options.ignoreTransform) {\r\n top = offsetTop(this.element)\r\n left = offsetLeft(this.element)\r\n } else {\r\n const rect = this.element.getBoundingClientRect()\r\n top = rect.top + scrollTop(this.element)\r\n left = rect.left + scrollLeft(this.element)\r\n }\r\n if (this.options.ignoreSticky) addParentSticky(this.element)\r\n\r\n this.setRect({ top, left })\r\n }\r\n\r\n onResize = ([entry]: ResizeObserverEntry[]) => {\r\n if (!entry?.borderBoxSize[0]) return\r\n const width = entry.borderBoxSize[0].inlineSize\r\n const height = entry.borderBoxSize[0].blockSize\r\n\r\n this.setRect({ width, height })\r\n }\r\n}\r\n","let index = 0\r\n\r\nexport type UID = number\r\n\r\nexport function uid(): UID {\r\n return index++\r\n}\r\n","import type Lenis from 'lenis'\r\nimport type { VirtualScrollData } from 'lenis'\r\nimport { debounce } from './debounce'\r\nimport type { SnapElementOptions } from './element'\r\nimport { SnapElement } from './element'\r\nimport type { SnapItem, SnapOptions } from './types'\r\nimport type { UID } from './uid'\r\nimport { uid } from './uid'\r\n\r\n// TODO:\r\n// - fix wheel scrolling after limits (see console scroll to)\r\n// - arrow, spacebar\r\n\r\ntype RequiredPick<T, F extends keyof T> = Omit<T, F> & Required<Pick<T, F>>\r\n\r\n/**\r\n * Snap class to handle the snap functionality\r\n *\r\n * @example\r\n * const snap = new Snap(lenis, {\r\n * type: 'mandatory', // 'mandatory', 'proximity' or 'lock'\r\n * onSnapStart: (snap) => {\r\n * console.log('onSnapStart', snap)\r\n * },\r\n * onSnapComplete: (snap) => {\r\n * console.log('onSnapComplete', snap)\r\n * },\r\n * })\r\n *\r\n * snap.add(500) // snap at 500px\r\n *\r\n * const removeSnap = snap.add(500)\r\n *\r\n * if (someCondition) {\r\n * removeSnap()\r\n * }\r\n */\r\nexport class Snap {\r\n options: RequiredPick<SnapOptions, 'type' | 'debounce'>\r\n elements = new Map<UID, SnapElement>()\r\n snaps = new Map<UID, SnapItem>()\r\n viewport: { width: number; height: number } = {\r\n width: window.innerWidth,\r\n height: window.innerHeight,\r\n }\r\n isStopped = false\r\n onSnapDebounced: (e: VirtualScrollData) => void\r\n currentSnapIndex?: number\r\n\r\n constructor(\r\n private lenis: Lenis,\r\n {\r\n type = 'proximity',\r\n lerp,\r\n easing,\r\n duration,\r\n distanceThreshold = '50%', // useless when type is \"mandatory\"\r\n debounce: debounceDelay = 500,\r\n onSnapStart,\r\n onSnapComplete,\r\n }: SnapOptions = {}\r\n ) {\r\n this.options = {\r\n type,\r\n lerp,\r\n easing,\r\n duration,\r\n distanceThreshold,\r\n debounce: debounceDelay,\r\n onSnapStart,\r\n onSnapComplete,\r\n }\r\n\r\n this.onWindowResize()\r\n window.addEventListener('resize', this.onWindowResize, false)\r\n\r\n this.onSnapDebounced = debounce(this.onSnap, this.options.debounce)\r\n\r\n this.lenis.on(\r\n 'virtual-scroll',\r\n this.options.type === 'lock' ? this.onSnap : this.onSnapDebounced\r\n )\r\n }\r\n\r\n /**\r\n * Destroy the snap instance\r\n */\r\n destroy() {\r\n this.lenis.off('virtual-scroll', this.onSnapDebounced)\r\n window.removeEventListener('resize', this.onWindowResize, false)\r\n this.elements.forEach((element) => element.destroy())\r\n }\r\n\r\n /**\r\n * Start the snap after it has been stopped\r\n */\r\n start() {\r\n this.isStopped = false\r\n }\r\n\r\n /**\r\n * Stop the snap\r\n */\r\n stop() {\r\n this.isStopped = true\r\n }\r\n\r\n /**\r\n * Add a snap to the snap instance\r\n *\r\n * @param value The value to snap to\r\n * @param userData User data that will be forwarded through the snap event\r\n * @returns Unsubscribe function\r\n */\r\n add(value: number) {\r\n const id = uid()\r\n\r\n this.snaps.set(id, { value })\r\n\r\n return () => this.snaps.delete(id)\r\n }\r\n\r\n /**\r\n * Add an element to the snap instance\r\n *\r\n * @param element The element to add\r\n * @param options The options for the element\r\n * @returns Unsubscribe function\r\n */\r\n addElement(element: HTMLElement, options: SnapElementOptions = {}) {\r\n const id = uid()\r\n\r\n this.elements.set(id, new SnapElement(element, options))\r\n\r\n return () => this.elements.delete(id)\r\n }\r\n\r\n addElements(elements: HTMLElement[], options: SnapElementOptions = {}) {\r\n elements.forEach((element) => this.addElement(element, options))\r\n }\r\n\r\n private onWindowResize = () => {\r\n this.viewport.width = window.innerWidth\r\n this.viewport.height = window.innerHeight\r\n }\r\n\r\n private computeSnaps = () => {\r\n const { isHorizontal } = this.lenis\r\n\r\n let snaps = [...this.snaps.values()] as SnapItem[]\r\n\r\n this.elements.forEach(({ rect, align }) => {\r\n let value: number | undefined\r\n\r\n align.forEach((align) => {\r\n if (align === 'start') {\r\n value = rect.top\r\n } else if (align === 'center') {\r\n value = isHorizontal\r\n ? rect.left + rect.width / 2 - this.viewport.width / 2\r\n : rect.top + rect.height / 2 - this.viewport.height / 2\r\n } else if (align === 'end') {\r\n value = isHorizontal\r\n ? rect.left + rect.width - this.viewport.width\r\n : rect.top + rect.height - this.viewport.height\r\n }\r\n\r\n if (typeof value === 'number') {\r\n snaps.push({ value: Math.ceil(value) })\r\n }\r\n })\r\n })\r\n\r\n snaps = snaps.sort((a, b) => Math.abs(a.value) - Math.abs(b.value))\r\n\r\n return snaps\r\n }\r\n\r\n previous() {\r\n this.goTo((this.currentSnapIndex ?? 0) - 1)\r\n }\r\n\r\n next() {\r\n this.goTo((this.currentSnapIndex ?? 0) + 1)\r\n }\r\n\r\n goTo(index: number) {\r\n const snaps = this.computeSnaps()\r\n\r\n if (snaps.length === 0) return\r\n\r\n this.currentSnapIndex = Math.max(0, Math.min(index, snaps.length - 1))\r\n\r\n const currentSnap = snaps[this.currentSnapIndex]\r\n if (currentSnap === undefined) return\r\n\r\n this.lenis.scrollTo(currentSnap.value, {\r\n duration: this.options.duration,\r\n easing: this.options.easing,\r\n lerp: this.options.lerp,\r\n lock: this.options.type === 'lock',\r\n userData: { initiator: 'snap' },\r\n onStart: () => {\r\n this.options.onSnapStart?.({\r\n index: this.currentSnapIndex,\r\n ...currentSnap,\r\n })\r\n },\r\n onComplete: () => {\r\n this.options.onSnapComplete?.({\r\n index: this.currentSnapIndex,\r\n ...currentSnap,\r\n })\r\n },\r\n })\r\n }\r\n\r\n get distanceThreshold() {\r\n let distanceThreshold = Infinity\r\n if (this.options.type === 'mandatory') return Infinity\r\n\r\n const { isHorizontal } = this.lenis\r\n\r\n const axis = isHorizontal ? 'width' : 'height'\r\n\r\n if (\r\n typeof this.options.distanceThreshold === 'string' &&\r\n this.options.distanceThreshold.endsWith('%')\r\n ) {\r\n distanceThreshold =\r\n (Number(this.options.distanceThreshold.replace('%', '')) / 100) *\r\n this.viewport[axis]\r\n } else if (typeof this.options.distanceThreshold === 'number') {\r\n distanceThreshold = this.options.distanceThreshold\r\n } else {\r\n distanceThreshold = this.viewport[axis]\r\n }\r\n\r\n return distanceThreshold\r\n }\r\n\r\n private onSnap = (e: VirtualScrollData) => {\r\n if (this.isStopped) return\r\n\r\n if (e.event.type === 'touchmove') return\r\n\r\n if (\r\n this.options.type === 'lock' &&\r\n this.lenis.userData?.initiator === 'snap'\r\n )\r\n return\r\n\r\n let { scroll, isHorizontal } = this.lenis\r\n const delta = isHorizontal ? e.deltaX : e.deltaY\r\n scroll = Math.ceil(this.lenis.scroll + delta)\r\n\r\n const snaps = this.computeSnaps()\r\n\r\n if (snaps.length === 0) return\r\n\r\n let snapIndex\r\n\r\n const prevSnapIndex = snaps.findLastIndex(({ value }) => value < scroll)\r\n const nextSnapIndex = snaps.findIndex(({ value }) => value > scroll)\r\n\r\n if (this.options.type === 'lock') {\r\n if (delta > 0) {\r\n snapIndex = nextSnapIndex\r\n } else if (delta < 0) {\r\n snapIndex = prevSnapIndex\r\n }\r\n } else {\r\n const prevSnap = snaps[prevSnapIndex]!\r\n const distanceToPrevSnap = prevSnap\r\n ? Math.abs(scroll - prevSnap.value)\r\n : Infinity\r\n\r\n const nextSnap = snaps[nextSnapIndex]!\r\n const distanceToNextSnap = nextSnap\r\n ? Math.abs(scroll - nextSnap.value)\r\n : Infinity\r\n snapIndex =\r\n distanceToPrevSnap < distanceToNextSnap ? prevSnapIndex : nextSnapIndex\r\n }\r\n\r\n if (snapIndex === undefined) return\r\n if (snapIndex === -1) return\r\n\r\n snapIndex = Math.max(0, Math.min(snapIndex, snaps.length - 1))\r\n\r\n const snap = snaps[snapIndex]!\r\n\r\n const distance = Math.abs(scroll - snap.value)\r\n\r\n if (distance <= this.distanceThreshold) {\r\n this.goTo(snapIndex)\r\n }\r\n }\r\n\r\n resize() {\r\n this.elements.forEach((element) => element.onWrapperResize())\r\n }\r\n}\r\n","// This file serves as an entry point for the package\r\nimport { Snap } from './src/snap'\r\nglobalThis.Snap = Snap\r\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){let n=this;clearTimeout(i),i=setTimeout((()=>{i=void 0,e.apply(n,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
|
|
1
|
+
function e(e,t){let i;return function(...s){let n=this;clearTimeout(i),i=setTimeout((()=>{i=void 0,e.apply(n,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),this.onSnapDebounced=e(this.onSnap,this.options.debounce),this.lenis.on("virtual-scroll","lock"===this.options.type?this.onSnap: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,!1),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={}){e.forEach((e=>this.addElement(e,t)))}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=1/0;if("mandatory"===this.options.type)return 1/0;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):1/0,s=n[h];o=i<(s?Math.abs(t-s.value):1/0)?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: any[]) => void>(\r\n callback: CB,\r\n delay: number\r\n) {\r\n let timer: ReturnType<typeof setTimeout> | undefined\r\n return function <T>(this: T, ...args: Parameters<typeof callback>): void {\r\n let context = this\r\n clearTimeout(timer)\r\n timer = setTimeout(() => {\r\n timer = undefined\r\n callback.apply(context, args)\r\n }, delay)\r\n }\r\n}\r\n","import { debounce } from './debounce'\r\n\r\nfunction removeParentSticky(element: HTMLElement) {\r\n const position = getComputedStyle(element).position\r\n\r\n const isSticky = position === 'sticky'\r\n\r\n if (isSticky) {\r\n element.style.setProperty('position', 'static')\r\n element.dataset.sticky = 'true'\r\n }\r\n\r\n if (element.offsetParent) {\r\n removeParentSticky(element.offsetParent as HTMLElement)\r\n }\r\n}\r\n\r\nfunction addParentSticky(element: HTMLElement) {\r\n if (element?.dataset?.sticky === 'true') {\r\n element.style.removeProperty('position')\r\n delete element.dataset.sticky\r\n }\r\n\r\n if (element.offsetParent) {\r\n addParentSticky(element.offsetParent as HTMLElement)\r\n }\r\n}\r\n\r\nfunction offsetTop(element: HTMLElement, accumulator = 0) {\r\n const top = accumulator + element.offsetTop\r\n if (element.offsetParent) {\r\n return offsetTop(element.offsetParent as HTMLElement, top)\r\n }\r\n return top\r\n}\r\n\r\nfunction offsetLeft(element: HTMLElement, accumulator = 0) {\r\n const left = accumulator + element.offsetLeft\r\n if (element.offsetParent) {\r\n return offsetLeft(element.offsetParent as HTMLElement, left)\r\n }\r\n return left\r\n}\r\n\r\nfunction scrollTop(element: HTMLElement, accumulator = 0) {\r\n const top = accumulator + element.scrollTop\r\n if (element.offsetParent) {\r\n return scrollTop(element.offsetParent as HTMLElement, top)\r\n }\r\n return top + window.scrollY\r\n}\r\n\r\nfunction scrollLeft(element: HTMLElement, accumulator = 0) {\r\n const left = accumulator + element.scrollLeft\r\n if (element.offsetParent) {\r\n return scrollLeft(element.offsetParent as HTMLElement, left)\r\n }\r\n return left + window.scrollX\r\n}\r\n\r\nexport type SnapElementOptions = {\r\n align?: string | string[]\r\n ignoreSticky?: boolean\r\n ignoreTransform?: boolean\r\n}\r\n\r\ntype Rect = {\r\n top: number\r\n left: number\r\n width: number\r\n height: number\r\n x: number\r\n y: number\r\n bottom: number\r\n right: number\r\n element: HTMLElement\r\n}\r\n\r\nexport class SnapElement {\r\n element: HTMLElement\r\n options: SnapElementOptions\r\n align: string[]\r\n // @ts-ignore\r\n rect: Rect = {}\r\n wrapperResizeObserver: ResizeObserver\r\n resizeObserver: ResizeObserver\r\n debouncedWrapperResize: () => void\r\n\r\n constructor(\r\n element: HTMLElement,\r\n {\r\n align = ['start'],\r\n ignoreSticky = true,\r\n ignoreTransform = false,\r\n }: SnapElementOptions = {}\r\n ) {\r\n this.element = element\r\n\r\n this.options = { align, ignoreSticky, ignoreTransform }\r\n\r\n this.align = [align].flat()\r\n\r\n this.debouncedWrapperResize = debounce(this.onWrapperResize, 500)\r\n\r\n this.wrapperResizeObserver = new ResizeObserver(this.debouncedWrapperResize)\r\n this.wrapperResizeObserver.observe(document.body)\r\n this.onWrapperResize()\r\n\r\n this.resizeObserver = new ResizeObserver(this.onResize)\r\n this.resizeObserver.observe(this.element)\r\n this.setRect({\r\n width: this.element.offsetWidth,\r\n height: this.element.offsetHeight,\r\n })\r\n }\r\n\r\n destroy() {\r\n this.wrapperResizeObserver.disconnect()\r\n this.resizeObserver.disconnect()\r\n }\r\n\r\n setRect({\r\n top,\r\n left,\r\n width,\r\n height,\r\n element,\r\n }: {\r\n top?: number\r\n left?: number\r\n width?: number\r\n height?: number\r\n element?: HTMLElement\r\n } = {}) {\r\n top = top ?? this.rect.top\r\n left = left ?? this.rect.left\r\n width = width ?? this.rect.width\r\n height = height ?? this.rect.height\r\n element = element ?? this.rect.element\r\n\r\n if (\r\n top === this.rect.top &&\r\n left === this.rect.left &&\r\n width === this.rect.width &&\r\n height === this.rect.height &&\r\n element === this.rect.element\r\n )\r\n return\r\n\r\n this.rect.top = top\r\n this.rect.y = top\r\n this.rect.width = width\r\n this.rect.height = height\r\n this.rect.left = left\r\n this.rect.x = left\r\n this.rect.bottom = top + height\r\n this.rect.right = left + width\r\n }\r\n\r\n onWrapperResize = () => {\r\n let top, left\r\n\r\n if (this.options.ignoreSticky) removeParentSticky(this.element)\r\n if (this.options.ignoreTransform) {\r\n top = offsetTop(this.element)\r\n left = offsetLeft(this.element)\r\n } else {\r\n const rect = this.element.getBoundingClientRect()\r\n top = rect.top + scrollTop(this.element)\r\n left = rect.left + scrollLeft(this.element)\r\n }\r\n if (this.options.ignoreSticky) addParentSticky(this.element)\r\n\r\n this.setRect({ top, left })\r\n }\r\n\r\n onResize = ([entry]: ResizeObserverEntry[]) => {\r\n if (!entry?.borderBoxSize[0]) return\r\n const width = entry.borderBoxSize[0].inlineSize\r\n const height = entry.borderBoxSize[0].blockSize\r\n\r\n this.setRect({ width, height })\r\n }\r\n}\r\n","let index = 0\r\n\r\nexport type UID = number\r\n\r\nexport function uid(): UID {\r\n return index++\r\n}\r\n","import type Lenis from 'lenis'\r\nimport type { VirtualScrollData } from 'lenis'\r\nimport { debounce } from './debounce'\r\nimport type { SnapElementOptions } from './element'\r\nimport { SnapElement } from './element'\r\nimport type { SnapItem, SnapOptions } from './types'\r\nimport type { UID } from './uid'\r\nimport { uid } from './uid'\r\n\r\n// TODO:\r\n// - fix wheel scrolling after limits (see console scroll to)\r\n// - fix touch scroll, do not snap when not released\r\n// - arrow, spacebar\r\n\r\ntype RequiredPick<T, F extends keyof T> = Omit<T, F> & Required<Pick<T, F>>\r\n\r\n/**\r\n * Snap class to handle the snap functionality\r\n *\r\n * @example\r\n * const snap = new Snap(lenis, {\r\n * type: 'mandatory', // 'mandatory', 'proximity'\r\n * lerp: 0.1,\r\n * duration: 1,\r\n * easing: (t) => t,\r\n * onSnapStart: (snap) => {\r\n * console.log('onSnapStart', snap)\r\n * },\r\n * onSnapComplete: (snap) => {\r\n * console.log('onSnapComplete', snap)\r\n * },\r\n * })\r\n *\r\n * snap.add(500) // snap at 500px\r\n *\r\n * const removeSnap = snap.add(500)\r\n *\r\n * if (someCondition) {\r\n * removeSnap()\r\n * }\r\n */\r\nexport class Snap {\r\n options: RequiredPick<SnapOptions, 'type' | 'debounce'>\r\n elements = new Map<UID, SnapElement>()\r\n snaps = new Map<UID, SnapItem>()\r\n viewport: { width: number; height: number } = {\r\n width: window.innerWidth,\r\n height: window.innerHeight,\r\n }\r\n isStopped = false\r\n onSnapDebounced: (e: VirtualScrollData) => void\r\n currentSnapIndex?: number\r\n\r\n constructor(\r\n private lenis: Lenis,\r\n {\r\n type = 'proximity',\r\n lerp,\r\n easing,\r\n duration,\r\n distanceThreshold = '50%', // useless when type is \"mandatory\"\r\n debounce: debounceDelay = 500,\r\n onSnapStart,\r\n onSnapComplete,\r\n }: SnapOptions = {}\r\n ) {\r\n this.options = {\r\n type,\r\n lerp,\r\n easing,\r\n duration,\r\n distanceThreshold,\r\n debounce: debounceDelay,\r\n onSnapStart,\r\n onSnapComplete,\r\n }\r\n\r\n this.onWindowResize()\r\n window.addEventListener('resize', this.onWindowResize, false)\r\n\r\n this.onSnapDebounced = debounce(\r\n this.onSnap,\r\n this.options.type === 'lock' ? 0 : this.options.debounce\r\n )\r\n\r\n this.lenis.on('virtual-scroll', this.onSnapDebounced)\r\n }\r\n\r\n /**\r\n * Destroy the snap instance\r\n */\r\n destroy() {\r\n this.lenis.off('virtual-scroll', this.onSnapDebounced)\r\n window.removeEventListener('resize', this.onWindowResize, false)\r\n this.elements.forEach((element) => element.destroy())\r\n }\r\n\r\n /**\r\n * Start the snap after it has been stopped\r\n */\r\n start() {\r\n this.isStopped = false\r\n }\r\n\r\n /**\r\n * Stop the snap\r\n */\r\n stop() {\r\n this.isStopped = true\r\n }\r\n\r\n /**\r\n * Add a snap to the snap instance\r\n *\r\n * @param value The value to snap to\r\n * @param userData User data that will be forwarded through the snap event\r\n * @returns Unsubscribe function\r\n */\r\n add(value: number) {\r\n const id = uid()\r\n\r\n this.snaps.set(id, { value })\r\n\r\n return () => this.snaps.delete(id)\r\n }\r\n\r\n /**\r\n * Add an element to the snap instance\r\n *\r\n * @param element The element to add\r\n * @param options The options for the element\r\n * @returns Unsubscribe function\r\n */\r\n addElement(element: HTMLElement, options: SnapElementOptions = {}) {\r\n const id = uid()\r\n\r\n this.elements.set(id, new SnapElement(element, options))\r\n\r\n return () => this.elements.delete(id)\r\n }\r\n\r\n addElements(elements: HTMLElement[], options: SnapElementOptions = {}) {\r\n elements.forEach((element) => this.addElement(element, options))\r\n }\r\n\r\n private onWindowResize = () => {\r\n this.viewport.width = window.innerWidth\r\n this.viewport.height = window.innerHeight\r\n }\r\n\r\n private computeSnaps = () => {\r\n const { isHorizontal } = this.lenis\r\n\r\n let snaps = [...this.snaps.values()] as SnapItem[]\r\n\r\n this.elements.forEach(({ rect, align }) => {\r\n let value: number | undefined\r\n\r\n align.forEach((align) => {\r\n if (align === 'start') {\r\n value = rect.top\r\n } else if (align === 'center') {\r\n value = isHorizontal\r\n ? rect.left + rect.width / 2 - this.viewport.width / 2\r\n : rect.top + rect.height / 2 - this.viewport.height / 2\r\n } else if (align === 'end') {\r\n value = isHorizontal\r\n ? rect.left + rect.width - this.viewport.width\r\n : rect.top + rect.height - this.viewport.height\r\n }\r\n\r\n if (typeof value === 'number') {\r\n snaps.push({ value: Math.ceil(value) })\r\n }\r\n })\r\n })\r\n\r\n snaps = snaps.sort((a, b) => Math.abs(a.value) - Math.abs(b.value))\r\n\r\n return snaps\r\n }\r\n\r\n previous() {\r\n this.goTo((this.currentSnapIndex ?? 0) - 1)\r\n }\r\n\r\n next() {\r\n this.goTo((this.currentSnapIndex ?? 0) + 1)\r\n }\r\n\r\n goTo(index: number) {\r\n const snaps = this.computeSnaps()\r\n\r\n if (snaps.length === 0) return\r\n\r\n this.currentSnapIndex = Math.max(0, Math.min(index, snaps.length - 1))\r\n\r\n const currentSnap = snaps[this.currentSnapIndex]\r\n if (currentSnap === undefined) return\r\n\r\n this.lenis.scrollTo(currentSnap.value, {\r\n duration: this.options.duration,\r\n easing: this.options.easing,\r\n lerp: this.options.lerp,\r\n lock: this.options.type === 'lock',\r\n userData: { initiator: 'snap' },\r\n onStart: () => {\r\n this.options.onSnapStart?.({\r\n index: this.currentSnapIndex,\r\n ...currentSnap,\r\n })\r\n },\r\n onComplete: () => {\r\n this.options.onSnapComplete?.({\r\n index: this.currentSnapIndex,\r\n ...currentSnap,\r\n })\r\n },\r\n })\r\n }\r\n\r\n // private onSlide = (e: VirtualScrollData) => {\r\n // if (this.isStopped) return\r\n\r\n // const { userData, isHorizontal } = this.lenis\r\n\r\n // if (userData?.initiator === 'snap') return\r\n\r\n // const delta = isHorizontal ? e.deltaX : e.deltaY\r\n\r\n // if (delta > 0) {\r\n // this.next()\r\n // } else if (delta < 0) {\r\n // this.previous()\r\n // }\r\n // }\r\n\r\n get distanceThreshold() {\r\n let distanceThreshold = Infinity\r\n if (this.options.type === 'mandatory') return Infinity\r\n\r\n const { isHorizontal } = this.lenis\r\n\r\n const axis = isHorizontal ? 'width' : 'height'\r\n\r\n if (\r\n typeof this.options.distanceThreshold === 'string' &&\r\n this.options.distanceThreshold.endsWith('%')\r\n ) {\r\n distanceThreshold =\r\n (Number(this.options.distanceThreshold.replace('%', '')) / 100) *\r\n this.viewport[axis]\r\n } else if (typeof this.options.distanceThreshold === 'number') {\r\n distanceThreshold = this.options.distanceThreshold\r\n } else {\r\n distanceThreshold = this.viewport[axis]\r\n }\r\n\r\n return distanceThreshold\r\n }\r\n\r\n private onSnap = (e: VirtualScrollData) => {\r\n if (this.isStopped) return\r\n\r\n if (\r\n this.options.type === 'lock' &&\r\n this.lenis.userData?.initiator === 'snap'\r\n )\r\n return\r\n\r\n let { scroll, isHorizontal } = this.lenis\r\n const delta = isHorizontal ? e.deltaX : e.deltaY\r\n scroll = Math.ceil(this.lenis.scroll)\r\n\r\n const snaps = this.computeSnaps()\r\n\r\n if (snaps.length === 0) return\r\n\r\n let snapIndex\r\n\r\n if (this.options.type === 'lock') {\r\n if (delta > 0) {\r\n const currentSnapIndex = snaps.findIndex(({ value }) => value > scroll)\r\n snapIndex = currentSnapIndex\r\n } else if (delta < 0) {\r\n const currentSnapIndex = snaps.findLastIndex(\r\n ({ value }) => value < scroll\r\n )\r\n snapIndex = currentSnapIndex\r\n }\r\n } else {\r\n let prevSnapIndex = snaps.findLastIndex(({ value }) => value < scroll)\r\n // if (prevSnapIndex === -1) prevSnapIndex = 0\r\n const prevSnap = snaps[prevSnapIndex]!\r\n const distanceToPrevSnap = Math.abs(scroll - prevSnap.value)\r\n\r\n let nextSnapIndex = snaps.findIndex(({ value }) => value > scroll)\r\n // if (nextSnapIndex === -1) nextSnapIndex = snaps.length - 1\r\n const nextSnap = snaps[nextSnapIndex]!\r\n const distanceToNextSnap = Math.abs(scroll - nextSnap.value)\r\n snapIndex =\r\n distanceToPrevSnap < distanceToNextSnap ? prevSnapIndex : nextSnapIndex\r\n }\r\n\r\n if (snapIndex === undefined) return\r\n if (snapIndex === -1) return\r\n\r\n snapIndex = Math.max(0, Math.min(snapIndex, snaps.length - 1))\r\n\r\n const snap = snaps[snapIndex]!\r\n\r\n const distance = Math.abs(scroll - snap.value)\r\n\r\n if (distance <= this.distanceThreshold) {\r\n this.goTo(snapIndex)\r\n }\r\n }\r\n\r\n resize() {\r\n this.elements.forEach((element) => element.onWrapperResize())\r\n }\r\n}\r\n","// This file serves as an entry point for the package\r\nimport { Snap } from './src/snap'\r\nglobalThis.Snap = Snap\r\n"],"mappings":";AAAO,SAAS,SACd,UACA,OACA;AACA,MAAI;AACJ,SAAO,YAAyB,MAAyC;AACvE,QAAI,UAAU;AACd,iBAAa,KAAK;AAClB,YAAQ,WAAW,MAAM;AACvB,cAAQ;AACR,eAAS,MAAM,SAAS,IAAI;AAAA,IAC9B,GAAG,KAAK;AAAA,EACV;AACF;;;ACXA,SAAS,mBAAmB,SAAsB;AAChD,QAAM,WAAW,iBAAiB,OAAO,EAAE;AAE3C,QAAM,WAAW,aAAa;AAE9B,MAAI,UAAU;AACZ,YAAQ,MAAM,YAAY,YAAY,QAAQ;AAC9C,YAAQ,QAAQ,SAAS;AAAA,EAC3B;AAEA,MAAI,QAAQ,cAAc;AACxB,uBAAmB,QAAQ,YAA2B;AAAA,EACxD;AACF;AAEA,SAAS,gBAAgB,SAAsB;AAC7C,MAAI,SAAS,SAAS,WAAW,QAAQ;AACvC,YAAQ,MAAM,eAAe,UAAU;AACvC,WAAO,QAAQ,QAAQ;AAAA,EACzB;AAEA,MAAI,QAAQ,cAAc;AACxB,oBAAgB,QAAQ,YAA2B;AAAA,EACrD;AACF;AAEA,SAAS,UAAU,SAAsB,cAAc,GAAG;AACxD,QAAM,MAAM,cAAc,QAAQ;AAClC,MAAI,QAAQ,cAAc;AACxB,WAAO,UAAU,QAAQ,cAA6B,GAAG;AAAA,EAC3D;AACA,SAAO;AACT;AAEA,SAAS,WAAW,SAAsB,cAAc,GAAG;AACzD,QAAM,OAAO,cAAc,QAAQ;AACnC,MAAI,QAAQ,cAAc;AACxB,WAAO,WAAW,QAAQ,cAA6B,IAAI;AAAA,EAC7D;AACA,SAAO;AACT;AAEA,SAAS,UAAU,SAAsB,cAAc,GAAG;AACxD,QAAM,MAAM,cAAc,QAAQ;AAClC,MAAI,QAAQ,cAAc;AACxB,WAAO,UAAU,QAAQ,cAA6B,GAAG;AAAA,EAC3D;AACA,SAAO,MAAM,OAAO;AACtB;AAEA,SAAS,WAAW,SAAsB,cAAc,GAAG;AACzD,QAAM,OAAO,cAAc,QAAQ;AACnC,MAAI,QAAQ,cAAc;AACxB,WAAO,WAAW,QAAQ,cAA6B,IAAI;AAAA,EAC7D;AACA,SAAO,OAAO,OAAO;AACvB;AAoBO,IAAM,cAAN,MAAkB;AAAA,EACvB;AAAA,EACA;AAAA,EACA;AAAA;AAAA,EAEA,OAAa,CAAC;AAAA,EACd;AAAA,EACA;AAAA,EACA;AAAA,EAEA,YACE,SACA;AAAA,IACE,QAAQ,CAAC,OAAO;AAAA,IAChB,eAAe;AAAA,IACf,kBAAkB;AAAA,EACpB,IAAwB,CAAC,GACzB;AACA,SAAK,UAAU;AAEf,SAAK,UAAU,EAAE,OAAO,cAAc,gBAAgB;AAEtD,SAAK,QAAQ,CAAC,KAAK,EAAE,KAAK;AAE1B,SAAK,yBAAyB,SAAS,KAAK,iBAAiB,GAAG;AAEhE,SAAK,wBAAwB,IAAI,eAAe,KAAK,sBAAsB;AAC3E,SAAK,sBAAsB,QAAQ,SAAS,IAAI;AAChD,SAAK,gBAAgB;AAErB,SAAK,iBAAiB,IAAI,eAAe,KAAK,QAAQ;AACtD,SAAK,eAAe,QAAQ,KAAK,OAAO;AACxC,SAAK,QAAQ;AAAA,MACX,OAAO,KAAK,QAAQ;AAAA,MACpB,QAAQ,KAAK,QAAQ;AAAA,IACvB,CAAC;AAAA,EACH;AAAA,EAEA,UAAU;AACR,SAAK,sBAAsB,WAAW;AACtC,SAAK,eAAe,WAAW;AAAA,EACjC;AAAA,EAEA,QAAQ;AAAA,IACN;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,IAMI,CAAC,GAAG;AACN,UAAM,OAAO,KAAK,KAAK;AACvB,WAAO,QAAQ,KAAK,KAAK;AACzB,YAAQ,SAAS,KAAK,KAAK;AAC3B,aAAS,UAAU,KAAK,KAAK;AAC7B,cAAU,WAAW,KAAK,KAAK;AAE/B,QACE,QAAQ,KAAK,KAAK,OAClB,SAAS,KAAK,KAAK,QACnB,UAAU,KAAK,KAAK,SACpB,WAAW,KAAK,KAAK,UACrB,YAAY,KAAK,KAAK;AAEtB;AAEF,SAAK,KAAK,MAAM;AAChB,SAAK,KAAK,IAAI;AACd,SAAK,KAAK,QAAQ;AAClB,SAAK,KAAK,SAAS;AACnB,SAAK,KAAK,OAAO;AACjB,SAAK,KAAK,IAAI;AACd,SAAK,KAAK,SAAS,MAAM;AACzB,SAAK,KAAK,QAAQ,OAAO;AAAA,EAC3B;AAAA,EAEA,kBAAkB,MAAM;AACtB,QAAI,KAAK;AAET,QAAI,KAAK,QAAQ,aAAc,oBAAmB,KAAK,OAAO;AAC9D,QAAI,KAAK,QAAQ,iBAAiB;AAChC,YAAM,UAAU,KAAK,OAAO;AAC5B,aAAO,WAAW,KAAK,OAAO;AAAA,IAChC,OAAO;AACL,YAAM,OAAO,KAAK,QAAQ,sBAAsB;AAChD,YAAM,KAAK,MAAM,UAAU,KAAK,OAAO;AACvC,aAAO,KAAK,OAAO,WAAW,KAAK,OAAO;AAAA,IAC5C;AACA,QAAI,KAAK,QAAQ,aAAc,iBAAgB,KAAK,OAAO;AAE3D,SAAK,QAAQ,EAAE,KAAK,KAAK,CAAC;AAAA,EAC5B;AAAA,EAEA,WAAW,CAAC,CAAC,KAAK,MAA6B;AAC7C,QAAI,CAAC,OAAO,cAAc,CAAC,EAAG;AAC9B,UAAM,QAAQ,MAAM,cAAc,CAAC,EAAE;AACrC,UAAM,SAAS,MAAM,cAAc,CAAC,EAAE;AAEtC,SAAK,QAAQ,EAAE,OAAO,OAAO,CAAC;AAAA,EAChC;AACF;;;ACvLA,IAAI,QAAQ;AAIL,SAAS,MAAW;AACzB,SAAO;AACT;;;ACmCO,IAAM,OAAN,MAAW;AAAA,EAYhB,YACU,OACR;AAAA,IACE,OAAO;AAAA,IACP;AAAA,IACA;AAAA,IACA;AAAA,IACA,oBAAoB;AAAA;AAAA,IACpB,UAAU,gBAAgB;AAAA,IAC1B;AAAA,IACA;AAAA,EACF,IAAiB,CAAC,GAClB;AAXQ;AAYR,SAAK,UAAU;AAAA,MACb;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,UAAU;AAAA,MACV;AAAA,MACA;AAAA,IACF;AAEA,SAAK,eAAe;AACpB,WAAO,iBAAiB,UAAU,KAAK,gBAAgB,KAAK;AAE5D,SAAK,kBAAkB;AAAA,MACrB,KAAK;AAAA,MACL,KAAK,QAAQ,SAAS,SAAS,IAAI,KAAK,QAAQ;AAAA,IAClD;AAEA,SAAK,MAAM,GAAG,kBAAkB,KAAK,eAAe;AAAA,EACtD;AAAA,EA5CA;AAAA,EACA,WAAW,oBAAI,IAAsB;AAAA,EACrC,QAAQ,oBAAI,IAAmB;AAAA,EAC/B,WAA8C;AAAA,IAC5C,OAAO,OAAO;AAAA,IACd,QAAQ,OAAO;AAAA,EACjB;AAAA,EACA,YAAY;AAAA,EACZ;AAAA,EACA;AAAA;AAAA;AAAA;AAAA,EAwCA,UAAU;AACR,SAAK,MAAM,IAAI,kBAAkB,KAAK,eAAe;AACrD,WAAO,oBAAoB,UAAU,KAAK,gBAAgB,KAAK;AAC/D,SAAK,SAAS,QAAQ,CAAC,YAAY,QAAQ,QAAQ,CAAC;AAAA,EACtD;AAAA;AAAA;AAAA;AAAA,EAKA,QAAQ;AACN,SAAK,YAAY;AAAA,EACnB;AAAA;AAAA;AAAA;AAAA,EAKA,OAAO;AACL,SAAK,YAAY;AAAA,EACnB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,IAAI,OAAe;AACjB,UAAM,KAAK,IAAI;AAEf,SAAK,MAAM,IAAI,IAAI,EAAE,MAAM,CAAC;AAE5B,WAAO,MAAM,KAAK,MAAM,OAAO,EAAE;AAAA,EACnC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,WAAW,SAAsB,UAA8B,CAAC,GAAG;AACjE,UAAM,KAAK,IAAI;AAEf,SAAK,SAAS,IAAI,IAAI,IAAI,YAAY,SAAS,OAAO,CAAC;AAEvD,WAAO,MAAM,KAAK,SAAS,OAAO,EAAE;AAAA,EACtC;AAAA,EAEA,YAAY,UAAyB,UAA8B,CAAC,GAAG;AACrE,aAAS,QAAQ,CAAC,YAAY,KAAK,WAAW,SAAS,OAAO,CAAC;AAAA,EACjE;AAAA,EAEQ,iBAAiB,MAAM;AAC7B,SAAK,SAAS,QAAQ,OAAO;AAC7B,SAAK,SAAS,SAAS,OAAO;AAAA,EAChC;AAAA,EAEQ,eAAe,MAAM;AAC3B,UAAM,EAAE,aAAa,IAAI,KAAK;AAE9B,QAAI,QAAQ,CAAC,GAAG,KAAK,MAAM,OAAO,CAAC;AAEnC,SAAK,SAAS,QAAQ,CAAC,EAAE,MAAM,MAAM,MAAM;AACzC,UAAI;AAEJ,YAAM,QAAQ,CAACA,WAAU;AACvB,YAAIA,WAAU,SAAS;AACrB,kBAAQ,KAAK;AAAA,QACf,WAAWA,WAAU,UAAU;AAC7B,kBAAQ,eACJ,KAAK,OAAO,KAAK,QAAQ,IAAI,KAAK,SAAS,QAAQ,IACnD,KAAK,MAAM,KAAK,SAAS,IAAI,KAAK,SAAS,SAAS;AAAA,QAC1D,WAAWA,WAAU,OAAO;AAC1B,kBAAQ,eACJ,KAAK,OAAO,KAAK,QAAQ,KAAK,SAAS,QACvC,KAAK,MAAM,KAAK,SAAS,KAAK,SAAS;AAAA,QAC7C;AAEA,YAAI,OAAO,UAAU,UAAU;AAC7B,gBAAM,KAAK,EAAE,OAAO,KAAK,KAAK,KAAK,EAAE,CAAC;AAAA,QACxC;AAAA,MACF,CAAC;AAAA,IACH,CAAC;AAED,YAAQ,MAAM,KAAK,CAAC,GAAG,MAAM,KAAK,IAAI,EAAE,KAAK,IAAI,KAAK,IAAI,EAAE,KAAK,CAAC;AAElE,WAAO;AAAA,EACT;AAAA,EAEA,WAAW;AACT,SAAK,MAAM,KAAK,oBAAoB,KAAK,CAAC;AAAA,EAC5C;AAAA,EAEA,OAAO;AACL,SAAK,MAAM,KAAK,oBAAoB,KAAK,CAAC;AAAA,EAC5C;AAAA,EAEA,KAAKC,QAAe;AAClB,UAAM,QAAQ,KAAK,aAAa;AAEhC,QAAI,MAAM,WAAW,EAAG;AAExB,SAAK,mBAAmB,KAAK,IAAI,GAAG,KAAK,IAAIA,QAAO,MAAM,SAAS,CAAC,CAAC;AAErE,UAAM,cAAc,MAAM,KAAK,gBAAgB;AAC/C,QAAI,gBAAgB,OAAW;AAE/B,SAAK,MAAM,SAAS,YAAY,OAAO;AAAA,MACrC,UAAU,KAAK,QAAQ;AAAA,MACvB,QAAQ,KAAK,QAAQ;AAAA,MACrB,MAAM,KAAK,QAAQ;AAAA,MACnB,MAAM,KAAK,QAAQ,SAAS;AAAA,MAC5B,UAAU,EAAE,WAAW,OAAO;AAAA,MAC9B,SAAS,MAAM;AACb,aAAK,QAAQ,cAAc;AAAA,UACzB,OAAO,KAAK;AAAA,UACZ,GAAG;AAAA,QACL,CAAC;AAAA,MACH;AAAA,MACA,YAAY,MAAM;AAChB,aAAK,QAAQ,iBAAiB;AAAA,UAC5B,OAAO,KAAK;AAAA,UACZ,GAAG;AAAA,QACL,CAAC;AAAA,MACH;AAAA,IACF,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAkBA,IAAI,oBAAoB;AACtB,QAAI,oBAAoB;AACxB,QAAI,KAAK,QAAQ,SAAS,YAAa,QAAO;AAE9C,UAAM,EAAE,aAAa,IAAI,KAAK;AAE9B,UAAM,OAAO,eAAe,UAAU;AAEtC,QACE,OAAO,KAAK,QAAQ,sBAAsB,YAC1C,KAAK,QAAQ,kBAAkB,SAAS,GAAG,GAC3C;AACA,0BACG,OAAO,KAAK,QAAQ,kBAAkB,QAAQ,KAAK,EAAE,CAAC,IAAI,MAC3D,KAAK,SAAS,IAAI;AAAA,IACtB,WAAW,OAAO,KAAK,QAAQ,sBAAsB,UAAU;AAC7D,0BAAoB,KAAK,QAAQ;AAAA,IACnC,OAAO;AACL,0BAAoB,KAAK,SAAS,IAAI;AAAA,IACxC;AAEA,WAAO;AAAA,EACT;AAAA,EAEQ,SAAS,CAAC,MAAyB;AACzC,QAAI,KAAK,UAAW;AAEpB,QACE,KAAK,QAAQ,SAAS,UACtB,KAAK,MAAM,UAAU,cAAc;AAEnC;AAEF,QAAI,EAAE,QAAQ,aAAa,IAAI,KAAK;AACpC,UAAM,QAAQ,eAAe,EAAE,SAAS,EAAE;AAC1C,aAAS,KAAK,KAAK,KAAK,MAAM,MAAM;AAEpC,UAAM,QAAQ,KAAK,aAAa;AAEhC,QAAI,MAAM,WAAW,EAAG;AAExB,QAAI;AAEJ,QAAI,KAAK,QAAQ,SAAS,QAAQ;AAChC,UAAI,QAAQ,GAAG;AACb,cAAM,mBAAmB,MAAM,UAAU,CAAC,EAAE,MAAM,MAAM,QAAQ,MAAM;AACtE,oBAAY;AAAA,MACd,WAAW,QAAQ,GAAG;AACpB,cAAM,mBAAmB,MAAM;AAAA,UAC7B,CAAC,EAAE,MAAM,MAAM,QAAQ;AAAA,QACzB;AACA,oBAAY;AAAA,MACd;AAAA,IACF,OAAO;AACL,UAAI,gBAAgB,MAAM,cAAc,CAAC,EAAE,MAAM,MAAM,QAAQ,MAAM;AAErE,YAAM,WAAW,MAAM,aAAa;AACpC,YAAM,qBAAqB,KAAK,IAAI,SAAS,SAAS,KAAK;AAE3D,UAAI,gBAAgB,MAAM,UAAU,CAAC,EAAE,MAAM,MAAM,QAAQ,MAAM;AAEjE,YAAM,WAAW,MAAM,aAAa;AACpC,YAAM,qBAAqB,KAAK,IAAI,SAAS,SAAS,KAAK;AAC3D,kBACE,qBAAqB,qBAAqB,gBAAgB;AAAA,IAC9D;AAEA,QAAI,cAAc,OAAW;AAC7B,QAAI,cAAc,GAAI;AAEtB,gBAAY,KAAK,IAAI,GAAG,KAAK,IAAI,WAAW,MAAM,SAAS,CAAC,CAAC;AAE7D,UAAM,OAAO,MAAM,SAAS;AAE5B,UAAM,WAAW,KAAK,IAAI,SAAS,KAAK,KAAK;AAE7C,QAAI,YAAY,KAAK,mBAAmB;AACtC,WAAK,KAAK,SAAS;AAAA,IACrB;AAAA,EACF;AAAA,EAEA,SAAS;AACP,SAAK,SAAS,QAAQ,CAAC,YAAY,QAAQ,gBAAgB,CAAC;AAAA,EAC9D;AACF;;;AC/TA,WAAW,OAAO;","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: any[]) => void>(\r\n callback: CB,\r\n delay: number\r\n) {\r\n let timer: ReturnType<typeof setTimeout> | undefined\r\n return function <T>(this: T, ...args: Parameters<typeof callback>): void {\r\n let context = this\r\n clearTimeout(timer)\r\n timer = setTimeout(() => {\r\n timer = undefined\r\n callback.apply(context, args)\r\n }, delay)\r\n }\r\n}\r\n","import { debounce } from './debounce'\r\n\r\nfunction removeParentSticky(element: HTMLElement) {\r\n const position = getComputedStyle(element).position\r\n\r\n const isSticky = position === 'sticky'\r\n\r\n if (isSticky) {\r\n element.style.setProperty('position', 'static')\r\n element.dataset.sticky = 'true'\r\n }\r\n\r\n if (element.offsetParent) {\r\n removeParentSticky(element.offsetParent as HTMLElement)\r\n }\r\n}\r\n\r\nfunction addParentSticky(element: HTMLElement) {\r\n if (element?.dataset?.sticky === 'true') {\r\n element.style.removeProperty('position')\r\n delete element.dataset.sticky\r\n }\r\n\r\n if (element.offsetParent) {\r\n addParentSticky(element.offsetParent as HTMLElement)\r\n }\r\n}\r\n\r\nfunction offsetTop(element: HTMLElement, accumulator = 0) {\r\n const top = accumulator + element.offsetTop\r\n if (element.offsetParent) {\r\n return offsetTop(element.offsetParent as HTMLElement, top)\r\n }\r\n return top\r\n}\r\n\r\nfunction offsetLeft(element: HTMLElement, accumulator = 0) {\r\n const left = accumulator + element.offsetLeft\r\n if (element.offsetParent) {\r\n return offsetLeft(element.offsetParent as HTMLElement, left)\r\n }\r\n return left\r\n}\r\n\r\nfunction scrollTop(element: HTMLElement, accumulator = 0) {\r\n const top = accumulator + element.scrollTop\r\n if (element.offsetParent) {\r\n return scrollTop(element.offsetParent as HTMLElement, top)\r\n }\r\n return top + window.scrollY\r\n}\r\n\r\nfunction scrollLeft(element: HTMLElement, accumulator = 0) {\r\n const left = accumulator + element.scrollLeft\r\n if (element.offsetParent) {\r\n return scrollLeft(element.offsetParent as HTMLElement, left)\r\n }\r\n return left + window.scrollX\r\n}\r\n\r\nexport type SnapElementOptions = {\r\n align?: string | string[]\r\n ignoreSticky?: boolean\r\n ignoreTransform?: boolean\r\n}\r\n\r\ntype Rect = {\r\n top: number\r\n left: number\r\n width: number\r\n height: number\r\n x: number\r\n y: number\r\n bottom: number\r\n right: number\r\n element: HTMLElement\r\n}\r\n\r\nexport class SnapElement {\r\n element: HTMLElement\r\n options: SnapElementOptions\r\n align: string[]\r\n // @ts-ignore\r\n rect: Rect = {}\r\n wrapperResizeObserver: ResizeObserver\r\n resizeObserver: ResizeObserver\r\n debouncedWrapperResize: () => void\r\n\r\n constructor(\r\n element: HTMLElement,\r\n {\r\n align = ['start'],\r\n ignoreSticky = true,\r\n ignoreTransform = false,\r\n }: SnapElementOptions = {}\r\n ) {\r\n this.element = element\r\n\r\n this.options = { align, ignoreSticky, ignoreTransform }\r\n\r\n this.align = [align].flat()\r\n\r\n this.debouncedWrapperResize = debounce(this.onWrapperResize, 500)\r\n\r\n this.wrapperResizeObserver = new ResizeObserver(this.debouncedWrapperResize)\r\n this.wrapperResizeObserver.observe(document.body)\r\n this.onWrapperResize()\r\n\r\n this.resizeObserver = new ResizeObserver(this.onResize)\r\n this.resizeObserver.observe(this.element)\r\n this.setRect({\r\n width: this.element.offsetWidth,\r\n height: this.element.offsetHeight,\r\n })\r\n }\r\n\r\n destroy() {\r\n this.wrapperResizeObserver.disconnect()\r\n this.resizeObserver.disconnect()\r\n }\r\n\r\n setRect({\r\n top,\r\n left,\r\n width,\r\n height,\r\n element,\r\n }: {\r\n top?: number\r\n left?: number\r\n width?: number\r\n height?: number\r\n element?: HTMLElement\r\n } = {}) {\r\n top = top ?? this.rect.top\r\n left = left ?? this.rect.left\r\n width = width ?? this.rect.width\r\n height = height ?? this.rect.height\r\n element = element ?? this.rect.element\r\n\r\n if (\r\n top === this.rect.top &&\r\n left === this.rect.left &&\r\n width === this.rect.width &&\r\n height === this.rect.height &&\r\n element === this.rect.element\r\n )\r\n return\r\n\r\n this.rect.top = top\r\n this.rect.y = top\r\n this.rect.width = width\r\n this.rect.height = height\r\n this.rect.left = left\r\n this.rect.x = left\r\n this.rect.bottom = top + height\r\n this.rect.right = left + width\r\n }\r\n\r\n onWrapperResize = () => {\r\n let top, left\r\n\r\n if (this.options.ignoreSticky) removeParentSticky(this.element)\r\n if (this.options.ignoreTransform) {\r\n top = offsetTop(this.element)\r\n left = offsetLeft(this.element)\r\n } else {\r\n const rect = this.element.getBoundingClientRect()\r\n top = rect.top + scrollTop(this.element)\r\n left = rect.left + scrollLeft(this.element)\r\n }\r\n if (this.options.ignoreSticky) addParentSticky(this.element)\r\n\r\n this.setRect({ top, left })\r\n }\r\n\r\n onResize = ([entry]: ResizeObserverEntry[]) => {\r\n if (!entry?.borderBoxSize[0]) return\r\n const width = entry.borderBoxSize[0].inlineSize\r\n const height = entry.borderBoxSize[0].blockSize\r\n\r\n this.setRect({ width, height })\r\n }\r\n}\r\n","let index = 0\r\n\r\nexport type UID = number\r\n\r\nexport function uid(): UID {\r\n return index++\r\n}\r\n","import type Lenis from 'lenis'\r\nimport type { VirtualScrollData } from 'lenis'\r\nimport { debounce } from './debounce'\r\nimport type { SnapElementOptions } from './element'\r\nimport { SnapElement } from './element'\r\nimport type { SnapItem, SnapOptions } from './types'\r\nimport type { UID } from './uid'\r\nimport { uid } from './uid'\r\n\r\n// TODO:\r\n// - fix wheel scrolling after limits (see console scroll to)\r\n// - arrow, spacebar\r\n\r\ntype RequiredPick<T, F extends keyof T> = Omit<T, F> & Required<Pick<T, F>>\r\n\r\n/**\r\n * Snap class to handle the snap functionality\r\n *\r\n * @example\r\n * const snap = new Snap(lenis, {\r\n * type: 'mandatory', // 'mandatory', 'proximity' or 'lock'\r\n * onSnapStart: (snap) => {\r\n * console.log('onSnapStart', snap)\r\n * },\r\n * onSnapComplete: (snap) => {\r\n * console.log('onSnapComplete', snap)\r\n * },\r\n * })\r\n *\r\n * snap.add(500) // snap at 500px\r\n *\r\n * const removeSnap = snap.add(500)\r\n *\r\n * if (someCondition) {\r\n * removeSnap()\r\n * }\r\n */\r\nexport class Snap {\r\n options: RequiredPick<SnapOptions, 'type' | 'debounce'>\r\n elements = new Map<UID, SnapElement>()\r\n snaps = new Map<UID, SnapItem>()\r\n viewport: { width: number; height: number } = {\r\n width: window.innerWidth,\r\n height: window.innerHeight,\r\n }\r\n isStopped = false\r\n onSnapDebounced: (e: VirtualScrollData) => void\r\n currentSnapIndex?: number\r\n\r\n constructor(\r\n private lenis: Lenis,\r\n {\r\n type = 'proximity',\r\n lerp,\r\n easing,\r\n duration,\r\n distanceThreshold = '50%', // useless when type is \"mandatory\"\r\n debounce: debounceDelay = 500,\r\n onSnapStart,\r\n onSnapComplete,\r\n }: SnapOptions = {}\r\n ) {\r\n this.options = {\r\n type,\r\n lerp,\r\n easing,\r\n duration,\r\n distanceThreshold,\r\n debounce: debounceDelay,\r\n onSnapStart,\r\n onSnapComplete,\r\n }\r\n\r\n this.onWindowResize()\r\n window.addEventListener('resize', this.onWindowResize, false)\r\n\r\n this.onSnapDebounced = debounce(this.onSnap, this.options.debounce)\r\n\r\n this.lenis.on(\r\n 'virtual-scroll',\r\n this.options.type === 'lock' ? this.onSnap : this.onSnapDebounced\r\n )\r\n }\r\n\r\n /**\r\n * Destroy the snap instance\r\n */\r\n destroy() {\r\n this.lenis.off('virtual-scroll', this.onSnapDebounced)\r\n window.removeEventListener('resize', this.onWindowResize, false)\r\n this.elements.forEach((element) => element.destroy())\r\n }\r\n\r\n /**\r\n * Start the snap after it has been stopped\r\n */\r\n start() {\r\n this.isStopped = false\r\n }\r\n\r\n /**\r\n * Stop the snap\r\n */\r\n stop() {\r\n this.isStopped = true\r\n }\r\n\r\n /**\r\n * Add a snap to the snap instance\r\n *\r\n * @param value The value to snap to\r\n * @param userData User data that will be forwarded through the snap event\r\n * @returns Unsubscribe function\r\n */\r\n add(value: number) {\r\n const id = uid()\r\n\r\n this.snaps.set(id, { value })\r\n\r\n return () => this.snaps.delete(id)\r\n }\r\n\r\n /**\r\n * Add an element to the snap instance\r\n *\r\n * @param element The element to add\r\n * @param options The options for the element\r\n * @returns Unsubscribe function\r\n */\r\n addElement(element: HTMLElement, options: SnapElementOptions = {}) {\r\n const id = uid()\r\n\r\n this.elements.set(id, new SnapElement(element, options))\r\n\r\n return () => this.elements.delete(id)\r\n }\r\n\r\n addElements(elements: HTMLElement[], options: SnapElementOptions = {}) {\r\n elements.forEach((element) => this.addElement(element, options))\r\n }\r\n\r\n private onWindowResize = () => {\r\n this.viewport.width = window.innerWidth\r\n this.viewport.height = window.innerHeight\r\n }\r\n\r\n private computeSnaps = () => {\r\n const { isHorizontal } = this.lenis\r\n\r\n let snaps = [...this.snaps.values()] as SnapItem[]\r\n\r\n this.elements.forEach(({ rect, align }) => {\r\n let value: number | undefined\r\n\r\n align.forEach((align) => {\r\n if (align === 'start') {\r\n value = rect.top\r\n } else if (align === 'center') {\r\n value = isHorizontal\r\n ? rect.left + rect.width / 2 - this.viewport.width / 2\r\n : rect.top + rect.height / 2 - this.viewport.height / 2\r\n } else if (align === 'end') {\r\n value = isHorizontal\r\n ? rect.left + rect.width - this.viewport.width\r\n : rect.top + rect.height - this.viewport.height\r\n }\r\n\r\n if (typeof value === 'number') {\r\n snaps.push({ value: Math.ceil(value) })\r\n }\r\n })\r\n })\r\n\r\n snaps = snaps.sort((a, b) => Math.abs(a.value) - Math.abs(b.value))\r\n\r\n return snaps\r\n }\r\n\r\n previous() {\r\n this.goTo((this.currentSnapIndex ?? 0) - 1)\r\n }\r\n\r\n next() {\r\n this.goTo((this.currentSnapIndex ?? 0) + 1)\r\n }\r\n\r\n goTo(index: number) {\r\n const snaps = this.computeSnaps()\r\n\r\n if (snaps.length === 0) return\r\n\r\n this.currentSnapIndex = Math.max(0, Math.min(index, snaps.length - 1))\r\n\r\n const currentSnap = snaps[this.currentSnapIndex]\r\n if (currentSnap === undefined) return\r\n\r\n this.lenis.scrollTo(currentSnap.value, {\r\n duration: this.options.duration,\r\n easing: this.options.easing,\r\n lerp: this.options.lerp,\r\n lock: this.options.type === 'lock',\r\n userData: { initiator: 'snap' },\r\n onStart: () => {\r\n this.options.onSnapStart?.({\r\n index: this.currentSnapIndex,\r\n ...currentSnap,\r\n })\r\n },\r\n onComplete: () => {\r\n this.options.onSnapComplete?.({\r\n index: this.currentSnapIndex,\r\n ...currentSnap,\r\n })\r\n },\r\n })\r\n }\r\n\r\n get distanceThreshold() {\r\n let distanceThreshold = Infinity\r\n if (this.options.type === 'mandatory') return Infinity\r\n\r\n const { isHorizontal } = this.lenis\r\n\r\n const axis = isHorizontal ? 'width' : 'height'\r\n\r\n if (\r\n typeof this.options.distanceThreshold === 'string' &&\r\n this.options.distanceThreshold.endsWith('%')\r\n ) {\r\n distanceThreshold =\r\n (Number(this.options.distanceThreshold.replace('%', '')) / 100) *\r\n this.viewport[axis]\r\n } else if (typeof this.options.distanceThreshold === 'number') {\r\n distanceThreshold = this.options.distanceThreshold\r\n } else {\r\n distanceThreshold = this.viewport[axis]\r\n }\r\n\r\n return distanceThreshold\r\n }\r\n\r\n private onSnap = (e: VirtualScrollData) => {\r\n if (this.isStopped) return\r\n\r\n if (e.event.type === 'touchmove') return\r\n\r\n if (\r\n this.options.type === 'lock' &&\r\n this.lenis.userData?.initiator === 'snap'\r\n )\r\n return\r\n\r\n let { scroll, isHorizontal } = this.lenis\r\n const delta = isHorizontal ? e.deltaX : e.deltaY\r\n scroll = Math.ceil(this.lenis.scroll + delta)\r\n\r\n const snaps = this.computeSnaps()\r\n\r\n if (snaps.length === 0) return\r\n\r\n let snapIndex\r\n\r\n const prevSnapIndex = snaps.findLastIndex(({ value }) => value < scroll)\r\n const nextSnapIndex = snaps.findIndex(({ value }) => value > scroll)\r\n\r\n if (this.options.type === 'lock') {\r\n if (delta > 0) {\r\n snapIndex = nextSnapIndex\r\n } else if (delta < 0) {\r\n snapIndex = prevSnapIndex\r\n }\r\n } else {\r\n const prevSnap = snaps[prevSnapIndex]!\r\n const distanceToPrevSnap = prevSnap\r\n ? Math.abs(scroll - prevSnap.value)\r\n : Infinity\r\n\r\n const nextSnap = snaps[nextSnapIndex]!\r\n const distanceToNextSnap = nextSnap\r\n ? Math.abs(scroll - nextSnap.value)\r\n : Infinity\r\n snapIndex =\r\n distanceToPrevSnap < distanceToNextSnap ? prevSnapIndex : nextSnapIndex\r\n }\r\n\r\n if (snapIndex === undefined) return\r\n if (snapIndex === -1) return\r\n\r\n snapIndex = Math.max(0, Math.min(snapIndex, snaps.length - 1))\r\n\r\n const snap = snaps[snapIndex]!\r\n\r\n const distance = Math.abs(scroll - snap.value)\r\n\r\n if (distance <= this.distanceThreshold) {\r\n this.goTo(snapIndex)\r\n }\r\n }\r\n\r\n resize() {\r\n this.elements.forEach((element) => element.onWrapperResize())\r\n }\r\n}\r\n","// This file serves as an entry point for the package\r\nimport { Snap } from './src/snap'\r\nglobalThis.Snap = Snap\r\n"],"mappings":"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","names":["align","index"]}
|
package/dist/lenis-snap.mjs
CHANGED
|
@@ -169,11 +169,11 @@ var Snap = class {
|
|
|
169
169
|
};
|
|
170
170
|
this.onWindowResize();
|
|
171
171
|
window.addEventListener("resize", this.onWindowResize, false);
|
|
172
|
-
this.onSnapDebounced = debounce(
|
|
173
|
-
|
|
174
|
-
|
|
172
|
+
this.onSnapDebounced = debounce(this.onSnap, this.options.debounce);
|
|
173
|
+
this.lenis.on(
|
|
174
|
+
"virtual-scroll",
|
|
175
|
+
this.options.type === "lock" ? this.onSnap : this.onSnapDebounced
|
|
175
176
|
);
|
|
176
|
-
this.lenis.on("virtual-scroll", this.onSnapDebounced);
|
|
177
177
|
}
|
|
178
178
|
options;
|
|
179
179
|
elements = /* @__PURE__ */ new Map();
|
|
@@ -289,17 +289,6 @@ var Snap = class {
|
|
|
289
289
|
}
|
|
290
290
|
});
|
|
291
291
|
}
|
|
292
|
-
// private onSlide = (e: VirtualScrollData) => {
|
|
293
|
-
// if (this.isStopped) return
|
|
294
|
-
// const { userData, isHorizontal } = this.lenis
|
|
295
|
-
// if (userData?.initiator === 'snap') return
|
|
296
|
-
// const delta = isHorizontal ? e.deltaX : e.deltaY
|
|
297
|
-
// if (delta > 0) {
|
|
298
|
-
// this.next()
|
|
299
|
-
// } else if (delta < 0) {
|
|
300
|
-
// this.previous()
|
|
301
|
-
// }
|
|
302
|
-
// }
|
|
303
292
|
get distanceThreshold() {
|
|
304
293
|
let distanceThreshold = Infinity;
|
|
305
294
|
if (this.options.type === "mandatory") return Infinity;
|
|
@@ -316,31 +305,28 @@ var Snap = class {
|
|
|
316
305
|
}
|
|
317
306
|
onSnap = (e) => {
|
|
318
307
|
if (this.isStopped) return;
|
|
308
|
+
if (e.event.type === "touchmove") return;
|
|
319
309
|
if (this.options.type === "lock" && this.lenis.userData?.initiator === "snap")
|
|
320
310
|
return;
|
|
321
311
|
let { scroll, isHorizontal } = this.lenis;
|
|
322
312
|
const delta = isHorizontal ? e.deltaX : e.deltaY;
|
|
323
|
-
scroll = Math.ceil(this.lenis.scroll);
|
|
313
|
+
scroll = Math.ceil(this.lenis.scroll + delta);
|
|
324
314
|
const snaps = this.computeSnaps();
|
|
325
315
|
if (snaps.length === 0) return;
|
|
326
316
|
let snapIndex;
|
|
317
|
+
const prevSnapIndex = snaps.findLastIndex(({ value }) => value < scroll);
|
|
318
|
+
const nextSnapIndex = snaps.findIndex(({ value }) => value > scroll);
|
|
327
319
|
if (this.options.type === "lock") {
|
|
328
320
|
if (delta > 0) {
|
|
329
|
-
|
|
330
|
-
snapIndex = currentSnapIndex;
|
|
321
|
+
snapIndex = nextSnapIndex;
|
|
331
322
|
} else if (delta < 0) {
|
|
332
|
-
|
|
333
|
-
({ value }) => value < scroll
|
|
334
|
-
);
|
|
335
|
-
snapIndex = currentSnapIndex;
|
|
323
|
+
snapIndex = prevSnapIndex;
|
|
336
324
|
}
|
|
337
325
|
} else {
|
|
338
|
-
let prevSnapIndex = snaps.findLastIndex(({ value }) => value < scroll);
|
|
339
326
|
const prevSnap = snaps[prevSnapIndex];
|
|
340
|
-
const distanceToPrevSnap = Math.abs(scroll - prevSnap.value);
|
|
341
|
-
let nextSnapIndex = snaps.findIndex(({ value }) => value > scroll);
|
|
327
|
+
const distanceToPrevSnap = prevSnap ? Math.abs(scroll - prevSnap.value) : Infinity;
|
|
342
328
|
const nextSnap = snaps[nextSnapIndex];
|
|
343
|
-
const distanceToNextSnap = Math.abs(scroll - nextSnap.value);
|
|
329
|
+
const distanceToNextSnap = nextSnap ? Math.abs(scroll - nextSnap.value) : Infinity;
|
|
344
330
|
snapIndex = distanceToPrevSnap < distanceToNextSnap ? prevSnapIndex : nextSnapIndex;
|
|
345
331
|
}
|
|
346
332
|
if (snapIndex === void 0) return;
|
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: any[]) => void>(\r\n callback: CB,\r\n delay: number\r\n) {\r\n let timer: ReturnType<typeof setTimeout> | undefined\r\n return function <T>(this: T, ...args: Parameters<typeof callback>): void {\r\n let context = this\r\n clearTimeout(timer)\r\n timer = setTimeout(() => {\r\n timer = undefined\r\n callback.apply(context, args)\r\n }, delay)\r\n }\r\n}\r\n","import { debounce } from './debounce'\r\n\r\nfunction removeParentSticky(element: HTMLElement) {\r\n const position = getComputedStyle(element).position\r\n\r\n const isSticky = position === 'sticky'\r\n\r\n if (isSticky) {\r\n element.style.setProperty('position', 'static')\r\n element.dataset.sticky = 'true'\r\n }\r\n\r\n if (element.offsetParent) {\r\n removeParentSticky(element.offsetParent as HTMLElement)\r\n }\r\n}\r\n\r\nfunction addParentSticky(element: HTMLElement) {\r\n if (element?.dataset?.sticky === 'true') {\r\n element.style.removeProperty('position')\r\n delete element.dataset.sticky\r\n }\r\n\r\n if (element.offsetParent) {\r\n addParentSticky(element.offsetParent as HTMLElement)\r\n }\r\n}\r\n\r\nfunction offsetTop(element: HTMLElement, accumulator = 0) {\r\n const top = accumulator + element.offsetTop\r\n if (element.offsetParent) {\r\n return offsetTop(element.offsetParent as HTMLElement, top)\r\n }\r\n return top\r\n}\r\n\r\nfunction offsetLeft(element: HTMLElement, accumulator = 0) {\r\n const left = accumulator + element.offsetLeft\r\n if (element.offsetParent) {\r\n return offsetLeft(element.offsetParent as HTMLElement, left)\r\n }\r\n return left\r\n}\r\n\r\nfunction scrollTop(element: HTMLElement, accumulator = 0) {\r\n const top = accumulator + element.scrollTop\r\n if (element.offsetParent) {\r\n return scrollTop(element.offsetParent as HTMLElement, top)\r\n }\r\n return top + window.scrollY\r\n}\r\n\r\nfunction scrollLeft(element: HTMLElement, accumulator = 0) {\r\n const left = accumulator + element.scrollLeft\r\n if (element.offsetParent) {\r\n return scrollLeft(element.offsetParent as HTMLElement, left)\r\n }\r\n return left + window.scrollX\r\n}\r\n\r\nexport type SnapElementOptions = {\r\n align?: string | string[]\r\n ignoreSticky?: boolean\r\n ignoreTransform?: boolean\r\n}\r\n\r\ntype Rect = {\r\n top: number\r\n left: number\r\n width: number\r\n height: number\r\n x: number\r\n y: number\r\n bottom: number\r\n right: number\r\n element: HTMLElement\r\n}\r\n\r\nexport class SnapElement {\r\n element: HTMLElement\r\n options: SnapElementOptions\r\n align: string[]\r\n // @ts-ignore\r\n rect: Rect = {}\r\n wrapperResizeObserver: ResizeObserver\r\n resizeObserver: ResizeObserver\r\n debouncedWrapperResize: () => void\r\n\r\n constructor(\r\n element: HTMLElement,\r\n {\r\n align = ['start'],\r\n ignoreSticky = true,\r\n ignoreTransform = false,\r\n }: SnapElementOptions = {}\r\n ) {\r\n this.element = element\r\n\r\n this.options = { align, ignoreSticky, ignoreTransform }\r\n\r\n this.align = [align].flat()\r\n\r\n this.debouncedWrapperResize = debounce(this.onWrapperResize, 500)\r\n\r\n this.wrapperResizeObserver = new ResizeObserver(this.debouncedWrapperResize)\r\n this.wrapperResizeObserver.observe(document.body)\r\n this.onWrapperResize()\r\n\r\n this.resizeObserver = new ResizeObserver(this.onResize)\r\n this.resizeObserver.observe(this.element)\r\n this.setRect({\r\n width: this.element.offsetWidth,\r\n height: this.element.offsetHeight,\r\n })\r\n }\r\n\r\n destroy() {\r\n this.wrapperResizeObserver.disconnect()\r\n this.resizeObserver.disconnect()\r\n }\r\n\r\n setRect({\r\n top,\r\n left,\r\n width,\r\n height,\r\n element,\r\n }: {\r\n top?: number\r\n left?: number\r\n width?: number\r\n height?: number\r\n element?: HTMLElement\r\n } = {}) {\r\n top = top ?? this.rect.top\r\n left = left ?? this.rect.left\r\n width = width ?? this.rect.width\r\n height = height ?? this.rect.height\r\n element = element ?? this.rect.element\r\n\r\n if (\r\n top === this.rect.top &&\r\n left === this.rect.left &&\r\n width === this.rect.width &&\r\n height === this.rect.height &&\r\n element === this.rect.element\r\n )\r\n return\r\n\r\n this.rect.top = top\r\n this.rect.y = top\r\n this.rect.width = width\r\n this.rect.height = height\r\n this.rect.left = left\r\n this.rect.x = left\r\n this.rect.bottom = top + height\r\n this.rect.right = left + width\r\n }\r\n\r\n onWrapperResize = () => {\r\n let top, left\r\n\r\n if (this.options.ignoreSticky) removeParentSticky(this.element)\r\n if (this.options.ignoreTransform) {\r\n top = offsetTop(this.element)\r\n left = offsetLeft(this.element)\r\n } else {\r\n const rect = this.element.getBoundingClientRect()\r\n top = rect.top + scrollTop(this.element)\r\n left = rect.left + scrollLeft(this.element)\r\n }\r\n if (this.options.ignoreSticky) addParentSticky(this.element)\r\n\r\n this.setRect({ top, left })\r\n }\r\n\r\n onResize = ([entry]: ResizeObserverEntry[]) => {\r\n if (!entry?.borderBoxSize[0]) return\r\n const width = entry.borderBoxSize[0].inlineSize\r\n const height = entry.borderBoxSize[0].blockSize\r\n\r\n this.setRect({ width, height })\r\n }\r\n}\r\n","let index = 0\r\n\r\nexport type UID = number\r\n\r\nexport function uid(): UID {\r\n return index++\r\n}\r\n","import type Lenis from 'lenis'\r\nimport type { VirtualScrollData } from 'lenis'\r\nimport { debounce } from './debounce'\r\nimport type { SnapElementOptions } from './element'\r\nimport { SnapElement } from './element'\r\nimport type { SnapItem, SnapOptions } from './types'\r\nimport type { UID } from './uid'\r\nimport { uid } from './uid'\r\n\r\n// TODO:\r\n// - fix wheel scrolling after limits (see console scroll to)\r\n// - fix touch scroll, do not snap when not released\r\n// - arrow, spacebar\r\n\r\ntype RequiredPick<T, F extends keyof T> = Omit<T, F> & Required<Pick<T, F>>\r\n\r\n/**\r\n * Snap class to handle the snap functionality\r\n *\r\n * @example\r\n * const snap = new Snap(lenis, {\r\n * type: 'mandatory', // 'mandatory', 'proximity'\r\n * lerp: 0.1,\r\n * duration: 1,\r\n * easing: (t) => t,\r\n * onSnapStart: (snap) => {\r\n * console.log('onSnapStart', snap)\r\n * },\r\n * onSnapComplete: (snap) => {\r\n * console.log('onSnapComplete', snap)\r\n * },\r\n * })\r\n *\r\n * snap.add(500) // snap at 500px\r\n *\r\n * const removeSnap = snap.add(500)\r\n *\r\n * if (someCondition) {\r\n * removeSnap()\r\n * }\r\n */\r\nexport class Snap {\r\n options: RequiredPick<SnapOptions, 'type' | 'debounce'>\r\n elements = new Map<UID, SnapElement>()\r\n snaps = new Map<UID, SnapItem>()\r\n viewport: { width: number; height: number } = {\r\n width: window.innerWidth,\r\n height: window.innerHeight,\r\n }\r\n isStopped = false\r\n onSnapDebounced: (e: VirtualScrollData) => void\r\n currentSnapIndex?: number\r\n\r\n constructor(\r\n private lenis: Lenis,\r\n {\r\n type = 'proximity',\r\n lerp,\r\n easing,\r\n duration,\r\n distanceThreshold = '50%', // useless when type is \"mandatory\"\r\n debounce: debounceDelay = 500,\r\n onSnapStart,\r\n onSnapComplete,\r\n }: SnapOptions = {}\r\n ) {\r\n this.options = {\r\n type,\r\n lerp,\r\n easing,\r\n duration,\r\n distanceThreshold,\r\n debounce: debounceDelay,\r\n onSnapStart,\r\n onSnapComplete,\r\n }\r\n\r\n this.onWindowResize()\r\n window.addEventListener('resize', this.onWindowResize, false)\r\n\r\n this.onSnapDebounced = debounce(\r\n this.onSnap,\r\n this.options.type === 'lock' ? 0 : this.options.debounce\r\n )\r\n\r\n this.lenis.on('virtual-scroll', this.onSnapDebounced)\r\n }\r\n\r\n /**\r\n * Destroy the snap instance\r\n */\r\n destroy() {\r\n this.lenis.off('virtual-scroll', this.onSnapDebounced)\r\n window.removeEventListener('resize', this.onWindowResize, false)\r\n this.elements.forEach((element) => element.destroy())\r\n }\r\n\r\n /**\r\n * Start the snap after it has been stopped\r\n */\r\n start() {\r\n this.isStopped = false\r\n }\r\n\r\n /**\r\n * Stop the snap\r\n */\r\n stop() {\r\n this.isStopped = true\r\n }\r\n\r\n /**\r\n * Add a snap to the snap instance\r\n *\r\n * @param value The value to snap to\r\n * @param userData User data that will be forwarded through the snap event\r\n * @returns Unsubscribe function\r\n */\r\n add(value: number) {\r\n const id = uid()\r\n\r\n this.snaps.set(id, { value })\r\n\r\n return () => this.snaps.delete(id)\r\n }\r\n\r\n /**\r\n * Add an element to the snap instance\r\n *\r\n * @param element The element to add\r\n * @param options The options for the element\r\n * @returns Unsubscribe function\r\n */\r\n addElement(element: HTMLElement, options: SnapElementOptions = {}) {\r\n const id = uid()\r\n\r\n this.elements.set(id, new SnapElement(element, options))\r\n\r\n return () => this.elements.delete(id)\r\n }\r\n\r\n addElements(elements: HTMLElement[], options: SnapElementOptions = {}) {\r\n elements.forEach((element) => this.addElement(element, options))\r\n }\r\n\r\n private onWindowResize = () => {\r\n this.viewport.width = window.innerWidth\r\n this.viewport.height = window.innerHeight\r\n }\r\n\r\n private computeSnaps = () => {\r\n const { isHorizontal } = this.lenis\r\n\r\n let snaps = [...this.snaps.values()] as SnapItem[]\r\n\r\n this.elements.forEach(({ rect, align }) => {\r\n let value: number | undefined\r\n\r\n align.forEach((align) => {\r\n if (align === 'start') {\r\n value = rect.top\r\n } else if (align === 'center') {\r\n value = isHorizontal\r\n ? rect.left + rect.width / 2 - this.viewport.width / 2\r\n : rect.top + rect.height / 2 - this.viewport.height / 2\r\n } else if (align === 'end') {\r\n value = isHorizontal\r\n ? rect.left + rect.width - this.viewport.width\r\n : rect.top + rect.height - this.viewport.height\r\n }\r\n\r\n if (typeof value === 'number') {\r\n snaps.push({ value: Math.ceil(value) })\r\n }\r\n })\r\n })\r\n\r\n snaps = snaps.sort((a, b) => Math.abs(a.value) - Math.abs(b.value))\r\n\r\n return snaps\r\n }\r\n\r\n previous() {\r\n this.goTo((this.currentSnapIndex ?? 0) - 1)\r\n }\r\n\r\n next() {\r\n this.goTo((this.currentSnapIndex ?? 0) + 1)\r\n }\r\n\r\n goTo(index: number) {\r\n const snaps = this.computeSnaps()\r\n\r\n if (snaps.length === 0) return\r\n\r\n this.currentSnapIndex = Math.max(0, Math.min(index, snaps.length - 1))\r\n\r\n const currentSnap = snaps[this.currentSnapIndex]\r\n if (currentSnap === undefined) return\r\n\r\n this.lenis.scrollTo(currentSnap.value, {\r\n duration: this.options.duration,\r\n easing: this.options.easing,\r\n lerp: this.options.lerp,\r\n lock: this.options.type === 'lock',\r\n userData: { initiator: 'snap' },\r\n onStart: () => {\r\n this.options.onSnapStart?.({\r\n index: this.currentSnapIndex,\r\n ...currentSnap,\r\n })\r\n },\r\n onComplete: () => {\r\n this.options.onSnapComplete?.({\r\n index: this.currentSnapIndex,\r\n ...currentSnap,\r\n })\r\n },\r\n })\r\n }\r\n\r\n // private onSlide = (e: VirtualScrollData) => {\r\n // if (this.isStopped) return\r\n\r\n // const { userData, isHorizontal } = this.lenis\r\n\r\n // if (userData?.initiator === 'snap') return\r\n\r\n // const delta = isHorizontal ? e.deltaX : e.deltaY\r\n\r\n // if (delta > 0) {\r\n // this.next()\r\n // } else if (delta < 0) {\r\n // this.previous()\r\n // }\r\n // }\r\n\r\n get distanceThreshold() {\r\n let distanceThreshold = Infinity\r\n if (this.options.type === 'mandatory') return Infinity\r\n\r\n const { isHorizontal } = this.lenis\r\n\r\n const axis = isHorizontal ? 'width' : 'height'\r\n\r\n if (\r\n typeof this.options.distanceThreshold === 'string' &&\r\n this.options.distanceThreshold.endsWith('%')\r\n ) {\r\n distanceThreshold =\r\n (Number(this.options.distanceThreshold.replace('%', '')) / 100) *\r\n this.viewport[axis]\r\n } else if (typeof this.options.distanceThreshold === 'number') {\r\n distanceThreshold = this.options.distanceThreshold\r\n } else {\r\n distanceThreshold = this.viewport[axis]\r\n }\r\n\r\n return distanceThreshold\r\n }\r\n\r\n private onSnap = (e: VirtualScrollData) => {\r\n if (this.isStopped) return\r\n\r\n if (\r\n this.options.type === 'lock' &&\r\n this.lenis.userData?.initiator === 'snap'\r\n )\r\n return\r\n\r\n let { scroll, isHorizontal } = this.lenis\r\n const delta = isHorizontal ? e.deltaX : e.deltaY\r\n scroll = Math.ceil(this.lenis.scroll)\r\n\r\n const snaps = this.computeSnaps()\r\n\r\n if (snaps.length === 0) return\r\n\r\n let snapIndex\r\n\r\n if (this.options.type === 'lock') {\r\n if (delta > 0) {\r\n const currentSnapIndex = snaps.findIndex(({ value }) => value > scroll)\r\n snapIndex = currentSnapIndex\r\n } else if (delta < 0) {\r\n const currentSnapIndex = snaps.findLastIndex(\r\n ({ value }) => value < scroll\r\n )\r\n snapIndex = currentSnapIndex\r\n }\r\n } else {\r\n let prevSnapIndex = snaps.findLastIndex(({ value }) => value < scroll)\r\n // if (prevSnapIndex === -1) prevSnapIndex = 0\r\n const prevSnap = snaps[prevSnapIndex]!\r\n const distanceToPrevSnap = Math.abs(scroll - prevSnap.value)\r\n\r\n let nextSnapIndex = snaps.findIndex(({ value }) => value > scroll)\r\n // if (nextSnapIndex === -1) nextSnapIndex = snaps.length - 1\r\n const nextSnap = snaps[nextSnapIndex]!\r\n const distanceToNextSnap = Math.abs(scroll - nextSnap.value)\r\n snapIndex =\r\n distanceToPrevSnap < distanceToNextSnap ? prevSnapIndex : nextSnapIndex\r\n }\r\n\r\n if (snapIndex === undefined) return\r\n if (snapIndex === -1) return\r\n\r\n snapIndex = Math.max(0, Math.min(snapIndex, snaps.length - 1))\r\n\r\n const snap = snaps[snapIndex]!\r\n\r\n const distance = Math.abs(scroll - snap.value)\r\n\r\n if (distance <= this.distanceThreshold) {\r\n this.goTo(snapIndex)\r\n }\r\n }\r\n\r\n resize() {\r\n this.elements.forEach((element) => element.onWrapperResize())\r\n }\r\n}\r\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: any[]) => void>(\r\n callback: CB,\r\n delay: number\r\n) {\r\n let timer: ReturnType<typeof setTimeout> | undefined\r\n return function <T>(this: T, ...args: Parameters<typeof callback>): void {\r\n let context = this\r\n clearTimeout(timer)\r\n timer = setTimeout(() => {\r\n timer = undefined\r\n callback.apply(context, args)\r\n }, delay)\r\n }\r\n}\r\n","import { debounce } from './debounce'\r\n\r\nfunction removeParentSticky(element: HTMLElement) {\r\n const position = getComputedStyle(element).position\r\n\r\n const isSticky = position === 'sticky'\r\n\r\n if (isSticky) {\r\n element.style.setProperty('position', 'static')\r\n element.dataset.sticky = 'true'\r\n }\r\n\r\n if (element.offsetParent) {\r\n removeParentSticky(element.offsetParent as HTMLElement)\r\n }\r\n}\r\n\r\nfunction addParentSticky(element: HTMLElement) {\r\n if (element?.dataset?.sticky === 'true') {\r\n element.style.removeProperty('position')\r\n delete element.dataset.sticky\r\n }\r\n\r\n if (element.offsetParent) {\r\n addParentSticky(element.offsetParent as HTMLElement)\r\n }\r\n}\r\n\r\nfunction offsetTop(element: HTMLElement, accumulator = 0) {\r\n const top = accumulator + element.offsetTop\r\n if (element.offsetParent) {\r\n return offsetTop(element.offsetParent as HTMLElement, top)\r\n }\r\n return top\r\n}\r\n\r\nfunction offsetLeft(element: HTMLElement, accumulator = 0) {\r\n const left = accumulator + element.offsetLeft\r\n if (element.offsetParent) {\r\n return offsetLeft(element.offsetParent as HTMLElement, left)\r\n }\r\n return left\r\n}\r\n\r\nfunction scrollTop(element: HTMLElement, accumulator = 0) {\r\n const top = accumulator + element.scrollTop\r\n if (element.offsetParent) {\r\n return scrollTop(element.offsetParent as HTMLElement, top)\r\n }\r\n return top + window.scrollY\r\n}\r\n\r\nfunction scrollLeft(element: HTMLElement, accumulator = 0) {\r\n const left = accumulator + element.scrollLeft\r\n if (element.offsetParent) {\r\n return scrollLeft(element.offsetParent as HTMLElement, left)\r\n }\r\n return left + window.scrollX\r\n}\r\n\r\nexport type SnapElementOptions = {\r\n align?: string | string[]\r\n ignoreSticky?: boolean\r\n ignoreTransform?: boolean\r\n}\r\n\r\ntype Rect = {\r\n top: number\r\n left: number\r\n width: number\r\n height: number\r\n x: number\r\n y: number\r\n bottom: number\r\n right: number\r\n element: HTMLElement\r\n}\r\n\r\nexport class SnapElement {\r\n element: HTMLElement\r\n options: SnapElementOptions\r\n align: string[]\r\n // @ts-ignore\r\n rect: Rect = {}\r\n wrapperResizeObserver: ResizeObserver\r\n resizeObserver: ResizeObserver\r\n debouncedWrapperResize: () => void\r\n\r\n constructor(\r\n element: HTMLElement,\r\n {\r\n align = ['start'],\r\n ignoreSticky = true,\r\n ignoreTransform = false,\r\n }: SnapElementOptions = {}\r\n ) {\r\n this.element = element\r\n\r\n this.options = { align, ignoreSticky, ignoreTransform }\r\n\r\n this.align = [align].flat()\r\n\r\n this.debouncedWrapperResize = debounce(this.onWrapperResize, 500)\r\n\r\n this.wrapperResizeObserver = new ResizeObserver(this.debouncedWrapperResize)\r\n this.wrapperResizeObserver.observe(document.body)\r\n this.onWrapperResize()\r\n\r\n this.resizeObserver = new ResizeObserver(this.onResize)\r\n this.resizeObserver.observe(this.element)\r\n this.setRect({\r\n width: this.element.offsetWidth,\r\n height: this.element.offsetHeight,\r\n })\r\n }\r\n\r\n destroy() {\r\n this.wrapperResizeObserver.disconnect()\r\n this.resizeObserver.disconnect()\r\n }\r\n\r\n setRect({\r\n top,\r\n left,\r\n width,\r\n height,\r\n element,\r\n }: {\r\n top?: number\r\n left?: number\r\n width?: number\r\n height?: number\r\n element?: HTMLElement\r\n } = {}) {\r\n top = top ?? this.rect.top\r\n left = left ?? this.rect.left\r\n width = width ?? this.rect.width\r\n height = height ?? this.rect.height\r\n element = element ?? this.rect.element\r\n\r\n if (\r\n top === this.rect.top &&\r\n left === this.rect.left &&\r\n width === this.rect.width &&\r\n height === this.rect.height &&\r\n element === this.rect.element\r\n )\r\n return\r\n\r\n this.rect.top = top\r\n this.rect.y = top\r\n this.rect.width = width\r\n this.rect.height = height\r\n this.rect.left = left\r\n this.rect.x = left\r\n this.rect.bottom = top + height\r\n this.rect.right = left + width\r\n }\r\n\r\n onWrapperResize = () => {\r\n let top, left\r\n\r\n if (this.options.ignoreSticky) removeParentSticky(this.element)\r\n if (this.options.ignoreTransform) {\r\n top = offsetTop(this.element)\r\n left = offsetLeft(this.element)\r\n } else {\r\n const rect = this.element.getBoundingClientRect()\r\n top = rect.top + scrollTop(this.element)\r\n left = rect.left + scrollLeft(this.element)\r\n }\r\n if (this.options.ignoreSticky) addParentSticky(this.element)\r\n\r\n this.setRect({ top, left })\r\n }\r\n\r\n onResize = ([entry]: ResizeObserverEntry[]) => {\r\n if (!entry?.borderBoxSize[0]) return\r\n const width = entry.borderBoxSize[0].inlineSize\r\n const height = entry.borderBoxSize[0].blockSize\r\n\r\n this.setRect({ width, height })\r\n }\r\n}\r\n","let index = 0\r\n\r\nexport type UID = number\r\n\r\nexport function uid(): UID {\r\n return index++\r\n}\r\n","import type Lenis from 'lenis'\r\nimport type { VirtualScrollData } from 'lenis'\r\nimport { debounce } from './debounce'\r\nimport type { SnapElementOptions } from './element'\r\nimport { SnapElement } from './element'\r\nimport type { SnapItem, SnapOptions } from './types'\r\nimport type { UID } from './uid'\r\nimport { uid } from './uid'\r\n\r\n// TODO:\r\n// - fix wheel scrolling after limits (see console scroll to)\r\n// - arrow, spacebar\r\n\r\ntype RequiredPick<T, F extends keyof T> = Omit<T, F> & Required<Pick<T, F>>\r\n\r\n/**\r\n * Snap class to handle the snap functionality\r\n *\r\n * @example\r\n * const snap = new Snap(lenis, {\r\n * type: 'mandatory', // 'mandatory', 'proximity' or 'lock'\r\n * onSnapStart: (snap) => {\r\n * console.log('onSnapStart', snap)\r\n * },\r\n * onSnapComplete: (snap) => {\r\n * console.log('onSnapComplete', snap)\r\n * },\r\n * })\r\n *\r\n * snap.add(500) // snap at 500px\r\n *\r\n * const removeSnap = snap.add(500)\r\n *\r\n * if (someCondition) {\r\n * removeSnap()\r\n * }\r\n */\r\nexport class Snap {\r\n options: RequiredPick<SnapOptions, 'type' | 'debounce'>\r\n elements = new Map<UID, SnapElement>()\r\n snaps = new Map<UID, SnapItem>()\r\n viewport: { width: number; height: number } = {\r\n width: window.innerWidth,\r\n height: window.innerHeight,\r\n }\r\n isStopped = false\r\n onSnapDebounced: (e: VirtualScrollData) => void\r\n currentSnapIndex?: number\r\n\r\n constructor(\r\n private lenis: Lenis,\r\n {\r\n type = 'proximity',\r\n lerp,\r\n easing,\r\n duration,\r\n distanceThreshold = '50%', // useless when type is \"mandatory\"\r\n debounce: debounceDelay = 500,\r\n onSnapStart,\r\n onSnapComplete,\r\n }: SnapOptions = {}\r\n ) {\r\n this.options = {\r\n type,\r\n lerp,\r\n easing,\r\n duration,\r\n distanceThreshold,\r\n debounce: debounceDelay,\r\n onSnapStart,\r\n onSnapComplete,\r\n }\r\n\r\n this.onWindowResize()\r\n window.addEventListener('resize', this.onWindowResize, false)\r\n\r\n this.onSnapDebounced = debounce(this.onSnap, this.options.debounce)\r\n\r\n this.lenis.on(\r\n 'virtual-scroll',\r\n this.options.type === 'lock' ? this.onSnap : this.onSnapDebounced\r\n )\r\n }\r\n\r\n /**\r\n * Destroy the snap instance\r\n */\r\n destroy() {\r\n this.lenis.off('virtual-scroll', this.onSnapDebounced)\r\n window.removeEventListener('resize', this.onWindowResize, false)\r\n this.elements.forEach((element) => element.destroy())\r\n }\r\n\r\n /**\r\n * Start the snap after it has been stopped\r\n */\r\n start() {\r\n this.isStopped = false\r\n }\r\n\r\n /**\r\n * Stop the snap\r\n */\r\n stop() {\r\n this.isStopped = true\r\n }\r\n\r\n /**\r\n * Add a snap to the snap instance\r\n *\r\n * @param value The value to snap to\r\n * @param userData User data that will be forwarded through the snap event\r\n * @returns Unsubscribe function\r\n */\r\n add(value: number) {\r\n const id = uid()\r\n\r\n this.snaps.set(id, { value })\r\n\r\n return () => this.snaps.delete(id)\r\n }\r\n\r\n /**\r\n * Add an element to the snap instance\r\n *\r\n * @param element The element to add\r\n * @param options The options for the element\r\n * @returns Unsubscribe function\r\n */\r\n addElement(element: HTMLElement, options: SnapElementOptions = {}) {\r\n const id = uid()\r\n\r\n this.elements.set(id, new SnapElement(element, options))\r\n\r\n return () => this.elements.delete(id)\r\n }\r\n\r\n addElements(elements: HTMLElement[], options: SnapElementOptions = {}) {\r\n elements.forEach((element) => this.addElement(element, options))\r\n }\r\n\r\n private onWindowResize = () => {\r\n this.viewport.width = window.innerWidth\r\n this.viewport.height = window.innerHeight\r\n }\r\n\r\n private computeSnaps = () => {\r\n const { isHorizontal } = this.lenis\r\n\r\n let snaps = [...this.snaps.values()] as SnapItem[]\r\n\r\n this.elements.forEach(({ rect, align }) => {\r\n let value: number | undefined\r\n\r\n align.forEach((align) => {\r\n if (align === 'start') {\r\n value = rect.top\r\n } else if (align === 'center') {\r\n value = isHorizontal\r\n ? rect.left + rect.width / 2 - this.viewport.width / 2\r\n : rect.top + rect.height / 2 - this.viewport.height / 2\r\n } else if (align === 'end') {\r\n value = isHorizontal\r\n ? rect.left + rect.width - this.viewport.width\r\n : rect.top + rect.height - this.viewport.height\r\n }\r\n\r\n if (typeof value === 'number') {\r\n snaps.push({ value: Math.ceil(value) })\r\n }\r\n })\r\n })\r\n\r\n snaps = snaps.sort((a, b) => Math.abs(a.value) - Math.abs(b.value))\r\n\r\n return snaps\r\n }\r\n\r\n previous() {\r\n this.goTo((this.currentSnapIndex ?? 0) - 1)\r\n }\r\n\r\n next() {\r\n this.goTo((this.currentSnapIndex ?? 0) + 1)\r\n }\r\n\r\n goTo(index: number) {\r\n const snaps = this.computeSnaps()\r\n\r\n if (snaps.length === 0) return\r\n\r\n this.currentSnapIndex = Math.max(0, Math.min(index, snaps.length - 1))\r\n\r\n const currentSnap = snaps[this.currentSnapIndex]\r\n if (currentSnap === undefined) return\r\n\r\n this.lenis.scrollTo(currentSnap.value, {\r\n duration: this.options.duration,\r\n easing: this.options.easing,\r\n lerp: this.options.lerp,\r\n lock: this.options.type === 'lock',\r\n userData: { initiator: 'snap' },\r\n onStart: () => {\r\n this.options.onSnapStart?.({\r\n index: this.currentSnapIndex,\r\n ...currentSnap,\r\n })\r\n },\r\n onComplete: () => {\r\n this.options.onSnapComplete?.({\r\n index: this.currentSnapIndex,\r\n ...currentSnap,\r\n })\r\n },\r\n })\r\n }\r\n\r\n get distanceThreshold() {\r\n let distanceThreshold = Infinity\r\n if (this.options.type === 'mandatory') return Infinity\r\n\r\n const { isHorizontal } = this.lenis\r\n\r\n const axis = isHorizontal ? 'width' : 'height'\r\n\r\n if (\r\n typeof this.options.distanceThreshold === 'string' &&\r\n this.options.distanceThreshold.endsWith('%')\r\n ) {\r\n distanceThreshold =\r\n (Number(this.options.distanceThreshold.replace('%', '')) / 100) *\r\n this.viewport[axis]\r\n } else if (typeof this.options.distanceThreshold === 'number') {\r\n distanceThreshold = this.options.distanceThreshold\r\n } else {\r\n distanceThreshold = this.viewport[axis]\r\n }\r\n\r\n return distanceThreshold\r\n }\r\n\r\n private onSnap = (e: VirtualScrollData) => {\r\n if (this.isStopped) return\r\n\r\n if (e.event.type === 'touchmove') return\r\n\r\n if (\r\n this.options.type === 'lock' &&\r\n this.lenis.userData?.initiator === 'snap'\r\n )\r\n return\r\n\r\n let { scroll, isHorizontal } = this.lenis\r\n const delta = isHorizontal ? e.deltaX : e.deltaY\r\n scroll = Math.ceil(this.lenis.scroll + delta)\r\n\r\n const snaps = this.computeSnaps()\r\n\r\n if (snaps.length === 0) return\r\n\r\n let snapIndex\r\n\r\n const prevSnapIndex = snaps.findLastIndex(({ value }) => value < scroll)\r\n const nextSnapIndex = snaps.findIndex(({ value }) => value > scroll)\r\n\r\n if (this.options.type === 'lock') {\r\n if (delta > 0) {\r\n snapIndex = nextSnapIndex\r\n } else if (delta < 0) {\r\n snapIndex = prevSnapIndex\r\n }\r\n } else {\r\n const prevSnap = snaps[prevSnapIndex]!\r\n const distanceToPrevSnap = prevSnap\r\n ? Math.abs(scroll - prevSnap.value)\r\n : Infinity\r\n\r\n const nextSnap = snaps[nextSnapIndex]!\r\n const distanceToNextSnap = nextSnap\r\n ? Math.abs(scroll - nextSnap.value)\r\n : Infinity\r\n snapIndex =\r\n distanceToPrevSnap < distanceToNextSnap ? prevSnapIndex : nextSnapIndex\r\n }\r\n\r\n if (snapIndex === undefined) return\r\n if (snapIndex === -1) return\r\n\r\n snapIndex = Math.max(0, Math.min(snapIndex, snaps.length - 1))\r\n\r\n const snap = snaps[snapIndex]!\r\n\r\n const distance = Math.abs(scroll - snap.value)\r\n\r\n if (distance <= this.distanceThreshold) {\r\n this.goTo(snapIndex)\r\n }\r\n }\r\n\r\n resize() {\r\n this.elements.forEach((element) => element.onWrapperResize())\r\n }\r\n}\r\n"],"mappings":"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","names":["align","index"]}
|
package/dist/lenis.js
CHANGED