@sociallane/elements 1.0.10 → 1.0.11

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.
@@ -0,0 +1,1099 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
3
+ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
4
+ var version = "1.3.17";
5
+ function clamp(min, input, max) {
6
+ return Math.max(min, Math.min(input, max));
7
+ }
8
+ function lerp(x, y, t) {
9
+ return (1 - t) * x + t * y;
10
+ }
11
+ function damp(x, y, lambda, deltaTime) {
12
+ return lerp(x, y, 1 - Math.exp(-lambda * deltaTime));
13
+ }
14
+ function modulo(n, d) {
15
+ return (n % d + d) % d;
16
+ }
17
+ var Animate = class {
18
+ constructor() {
19
+ __publicField(this, "isRunning", false);
20
+ __publicField(this, "value", 0);
21
+ __publicField(this, "from", 0);
22
+ __publicField(this, "to", 0);
23
+ __publicField(this, "currentTime", 0);
24
+ // These are instanciated in the fromTo method
25
+ __publicField(this, "lerp");
26
+ __publicField(this, "duration");
27
+ __publicField(this, "easing");
28
+ __publicField(this, "onUpdate");
29
+ }
30
+ /**
31
+ * Advance the animation by the given delta time
32
+ *
33
+ * @param deltaTime - The time in seconds to advance the animation
34
+ */
35
+ advance(deltaTime) {
36
+ if (!this.isRunning) return;
37
+ let completed = false;
38
+ if (this.duration && this.easing) {
39
+ this.currentTime += deltaTime;
40
+ const linearProgress = clamp(0, this.currentTime / this.duration, 1);
41
+ completed = linearProgress >= 1;
42
+ const easedProgress = completed ? 1 : this.easing(linearProgress);
43
+ this.value = this.from + (this.to - this.from) * easedProgress;
44
+ } else if (this.lerp) {
45
+ this.value = damp(this.value, this.to, this.lerp * 60, deltaTime);
46
+ if (Math.round(this.value) === this.to) {
47
+ this.value = this.to;
48
+ completed = true;
49
+ }
50
+ } else {
51
+ this.value = this.to;
52
+ completed = true;
53
+ }
54
+ if (completed) {
55
+ this.stop();
56
+ }
57
+ this.onUpdate?.(this.value, completed);
58
+ }
59
+ /** Stop the animation */
60
+ stop() {
61
+ this.isRunning = false;
62
+ }
63
+ /**
64
+ * Set up the animation from a starting value to an ending value
65
+ * with optional parameters for lerping, duration, easing, and onUpdate callback
66
+ *
67
+ * @param from - The starting value
68
+ * @param to - The ending value
69
+ * @param options - Options for the animation
70
+ */
71
+ fromTo(from, to, { lerp: lerp2, duration, easing, onStart, onUpdate }) {
72
+ this.from = this.value = from;
73
+ this.to = to;
74
+ this.lerp = lerp2;
75
+ this.duration = duration;
76
+ this.easing = easing;
77
+ this.currentTime = 0;
78
+ this.isRunning = true;
79
+ onStart?.();
80
+ this.onUpdate = onUpdate;
81
+ }
82
+ };
83
+ function debounce(callback, delay) {
84
+ let timer;
85
+ return function(...args) {
86
+ let context = this;
87
+ clearTimeout(timer);
88
+ timer = setTimeout(() => {
89
+ timer = void 0;
90
+ callback.apply(context, args);
91
+ }, delay);
92
+ };
93
+ }
94
+ var Dimensions = class {
95
+ constructor(wrapper, content, { autoResize = true, debounce: debounceValue = 250 } = {}) {
96
+ __publicField(this, "width", 0);
97
+ __publicField(this, "height", 0);
98
+ __publicField(this, "scrollHeight", 0);
99
+ __publicField(this, "scrollWidth", 0);
100
+ // These are instanciated in the constructor as they need information from the options
101
+ __publicField(this, "debouncedResize");
102
+ __publicField(this, "wrapperResizeObserver");
103
+ __publicField(this, "contentResizeObserver");
104
+ __publicField(this, "resize", () => {
105
+ this.onWrapperResize();
106
+ this.onContentResize();
107
+ });
108
+ __publicField(this, "onWrapperResize", () => {
109
+ if (this.wrapper instanceof Window) {
110
+ this.width = window.innerWidth;
111
+ this.height = window.innerHeight;
112
+ } else {
113
+ this.width = this.wrapper.clientWidth;
114
+ this.height = this.wrapper.clientHeight;
115
+ }
116
+ });
117
+ __publicField(this, "onContentResize", () => {
118
+ if (this.wrapper instanceof Window) {
119
+ this.scrollHeight = this.content.scrollHeight;
120
+ this.scrollWidth = this.content.scrollWidth;
121
+ } else {
122
+ this.scrollHeight = this.wrapper.scrollHeight;
123
+ this.scrollWidth = this.wrapper.scrollWidth;
124
+ }
125
+ });
126
+ this.wrapper = wrapper;
127
+ this.content = content;
128
+ if (autoResize) {
129
+ this.debouncedResize = debounce(this.resize, debounceValue);
130
+ if (this.wrapper instanceof Window) {
131
+ window.addEventListener("resize", this.debouncedResize, false);
132
+ } else {
133
+ this.wrapperResizeObserver = new ResizeObserver(this.debouncedResize);
134
+ this.wrapperResizeObserver.observe(this.wrapper);
135
+ }
136
+ this.contentResizeObserver = new ResizeObserver(this.debouncedResize);
137
+ this.contentResizeObserver.observe(this.content);
138
+ }
139
+ this.resize();
140
+ }
141
+ destroy() {
142
+ this.wrapperResizeObserver?.disconnect();
143
+ this.contentResizeObserver?.disconnect();
144
+ if (this.wrapper === window && this.debouncedResize) {
145
+ window.removeEventListener("resize", this.debouncedResize, false);
146
+ }
147
+ }
148
+ get limit() {
149
+ return {
150
+ x: this.scrollWidth - this.width,
151
+ y: this.scrollHeight - this.height
152
+ };
153
+ }
154
+ };
155
+ var Emitter = class {
156
+ constructor() {
157
+ __publicField(this, "events", {});
158
+ }
159
+ /**
160
+ * Emit an event with the given data
161
+ * @param event Event name
162
+ * @param args Data to pass to the event handlers
163
+ */
164
+ emit(event, ...args) {
165
+ let callbacks = this.events[event] || [];
166
+ for (let i = 0, length = callbacks.length; i < length; i++) {
167
+ callbacks[i]?.(...args);
168
+ }
169
+ }
170
+ /**
171
+ * Add a callback to the event
172
+ * @param event Event name
173
+ * @param cb Callback function
174
+ * @returns Unsubscribe function
175
+ */
176
+ on(event, cb) {
177
+ this.events[event]?.push(cb) || (this.events[event] = [cb]);
178
+ return () => {
179
+ this.events[event] = this.events[event]?.filter((i) => cb !== i);
180
+ };
181
+ }
182
+ /**
183
+ * Remove a callback from the event
184
+ * @param event Event name
185
+ * @param callback Callback function
186
+ */
187
+ off(event, callback) {
188
+ this.events[event] = this.events[event]?.filter((i) => callback !== i);
189
+ }
190
+ /**
191
+ * Remove all event listeners and clean up
192
+ */
193
+ destroy() {
194
+ this.events = {};
195
+ }
196
+ };
197
+ var LINE_HEIGHT = 100 / 6;
198
+ var listenerOptions = { passive: false };
199
+ var VirtualScroll = class {
200
+ constructor(element, options = { wheelMultiplier: 1, touchMultiplier: 1 }) {
201
+ __publicField(this, "touchStart", {
202
+ x: 0,
203
+ y: 0
204
+ });
205
+ __publicField(this, "lastDelta", {
206
+ x: 0,
207
+ y: 0
208
+ });
209
+ __publicField(this, "window", {
210
+ width: 0,
211
+ height: 0
212
+ });
213
+ __publicField(this, "emitter", new Emitter());
214
+ /**
215
+ * Event handler for 'touchstart' event
216
+ *
217
+ * @param event Touch event
218
+ */
219
+ __publicField(this, "onTouchStart", (event) => {
220
+ const { clientX, clientY } = event.targetTouches ? event.targetTouches[0] : event;
221
+ this.touchStart.x = clientX;
222
+ this.touchStart.y = clientY;
223
+ this.lastDelta = {
224
+ x: 0,
225
+ y: 0
226
+ };
227
+ this.emitter.emit("scroll", {
228
+ deltaX: 0,
229
+ deltaY: 0,
230
+ event
231
+ });
232
+ });
233
+ /** Event handler for 'touchmove' event */
234
+ __publicField(this, "onTouchMove", (event) => {
235
+ const { clientX, clientY } = event.targetTouches ? event.targetTouches[0] : event;
236
+ const deltaX = -(clientX - this.touchStart.x) * this.options.touchMultiplier;
237
+ const deltaY = -(clientY - this.touchStart.y) * this.options.touchMultiplier;
238
+ this.touchStart.x = clientX;
239
+ this.touchStart.y = clientY;
240
+ this.lastDelta = {
241
+ x: deltaX,
242
+ y: deltaY
243
+ };
244
+ this.emitter.emit("scroll", {
245
+ deltaX,
246
+ deltaY,
247
+ event
248
+ });
249
+ });
250
+ __publicField(this, "onTouchEnd", (event) => {
251
+ this.emitter.emit("scroll", {
252
+ deltaX: this.lastDelta.x,
253
+ deltaY: this.lastDelta.y,
254
+ event
255
+ });
256
+ });
257
+ /** Event handler for 'wheel' event */
258
+ __publicField(this, "onWheel", (event) => {
259
+ let { deltaX, deltaY, deltaMode } = event;
260
+ const multiplierX = deltaMode === 1 ? LINE_HEIGHT : deltaMode === 2 ? this.window.width : 1;
261
+ const multiplierY = deltaMode === 1 ? LINE_HEIGHT : deltaMode === 2 ? this.window.height : 1;
262
+ deltaX *= multiplierX;
263
+ deltaY *= multiplierY;
264
+ deltaX *= this.options.wheelMultiplier;
265
+ deltaY *= this.options.wheelMultiplier;
266
+ this.emitter.emit("scroll", { deltaX, deltaY, event });
267
+ });
268
+ __publicField(this, "onWindowResize", () => {
269
+ this.window = {
270
+ width: window.innerWidth,
271
+ height: window.innerHeight
272
+ };
273
+ });
274
+ this.element = element;
275
+ this.options = options;
276
+ window.addEventListener("resize", this.onWindowResize, false);
277
+ this.onWindowResize();
278
+ this.element.addEventListener("wheel", this.onWheel, listenerOptions);
279
+ this.element.addEventListener(
280
+ "touchstart",
281
+ this.onTouchStart,
282
+ listenerOptions
283
+ );
284
+ this.element.addEventListener(
285
+ "touchmove",
286
+ this.onTouchMove,
287
+ listenerOptions
288
+ );
289
+ this.element.addEventListener("touchend", this.onTouchEnd, listenerOptions);
290
+ }
291
+ /**
292
+ * Add an event listener for the given event and callback
293
+ *
294
+ * @param event Event name
295
+ * @param callback Callback function
296
+ */
297
+ on(event, callback) {
298
+ return this.emitter.on(event, callback);
299
+ }
300
+ /** Remove all event listeners and clean up */
301
+ destroy() {
302
+ this.emitter.destroy();
303
+ window.removeEventListener("resize", this.onWindowResize, false);
304
+ this.element.removeEventListener("wheel", this.onWheel, listenerOptions);
305
+ this.element.removeEventListener(
306
+ "touchstart",
307
+ this.onTouchStart,
308
+ listenerOptions
309
+ );
310
+ this.element.removeEventListener(
311
+ "touchmove",
312
+ this.onTouchMove,
313
+ listenerOptions
314
+ );
315
+ this.element.removeEventListener(
316
+ "touchend",
317
+ this.onTouchEnd,
318
+ listenerOptions
319
+ );
320
+ }
321
+ };
322
+ var defaultEasing = (t) => Math.min(1, 1.001 - Math.pow(2, -10 * t));
323
+ var Lenis = class {
324
+ constructor({
325
+ wrapper = window,
326
+ content = document.documentElement,
327
+ eventsTarget = wrapper,
328
+ smoothWheel = true,
329
+ syncTouch = false,
330
+ syncTouchLerp = 0.075,
331
+ touchInertiaExponent = 1.7,
332
+ duration,
333
+ // in seconds
334
+ easing,
335
+ lerp: lerp2 = 0.1,
336
+ infinite = false,
337
+ orientation = "vertical",
338
+ // vertical, horizontal
339
+ gestureOrientation = orientation === "horizontal" ? "both" : "vertical",
340
+ // vertical, horizontal, both
341
+ touchMultiplier = 1,
342
+ wheelMultiplier = 1,
343
+ autoResize = true,
344
+ prevent,
345
+ virtualScroll,
346
+ overscroll = true,
347
+ autoRaf = false,
348
+ anchors = false,
349
+ autoToggle = false,
350
+ // https://caniuse.com/?search=transition-behavior
351
+ allowNestedScroll = false,
352
+ // @ts-ignore: this will be deprecated in the future
353
+ __experimental__naiveDimensions = false,
354
+ naiveDimensions = __experimental__naiveDimensions,
355
+ stopInertiaOnNavigate = false
356
+ } = {}) {
357
+ __publicField(this, "_isScrolling", false);
358
+ // true when scroll is animating
359
+ __publicField(this, "_isStopped", false);
360
+ // true if user should not be able to scroll - enable/disable programmatically
361
+ __publicField(this, "_isLocked", false);
362
+ // same as isStopped but enabled/disabled when scroll reaches target
363
+ __publicField(this, "_preventNextNativeScrollEvent", false);
364
+ __publicField(this, "_resetVelocityTimeout", null);
365
+ __publicField(this, "_rafId", null);
366
+ /**
367
+ * Whether or not the user is touching the screen
368
+ */
369
+ __publicField(this, "isTouching");
370
+ /**
371
+ * The time in ms since the lenis instance was created
372
+ */
373
+ __publicField(this, "time", 0);
374
+ /**
375
+ * User data that will be forwarded through the scroll event
376
+ *
377
+ * @example
378
+ * lenis.scrollTo(100, {
379
+ * userData: {
380
+ * foo: 'bar'
381
+ * }
382
+ * })
383
+ */
384
+ __publicField(this, "userData", {});
385
+ /**
386
+ * The last velocity of the scroll
387
+ */
388
+ __publicField(this, "lastVelocity", 0);
389
+ /**
390
+ * The current velocity of the scroll
391
+ */
392
+ __publicField(this, "velocity", 0);
393
+ /**
394
+ * The direction of the scroll
395
+ */
396
+ __publicField(this, "direction", 0);
397
+ /**
398
+ * The options passed to the lenis instance
399
+ */
400
+ __publicField(this, "options");
401
+ /**
402
+ * The target scroll value
403
+ */
404
+ __publicField(this, "targetScroll");
405
+ /**
406
+ * The animated scroll value
407
+ */
408
+ __publicField(this, "animatedScroll");
409
+ // These are instanciated here as they don't need information from the options
410
+ __publicField(this, "animate", new Animate());
411
+ __publicField(this, "emitter", new Emitter());
412
+ // These are instanciated in the constructor as they need information from the options
413
+ __publicField(this, "dimensions");
414
+ // This is not private because it's used in the Snap class
415
+ __publicField(this, "virtualScroll");
416
+ __publicField(this, "onScrollEnd", (e) => {
417
+ if (!(e instanceof CustomEvent)) {
418
+ if (this.isScrolling === "smooth" || this.isScrolling === false) {
419
+ e.stopPropagation();
420
+ }
421
+ }
422
+ });
423
+ __publicField(this, "dispatchScrollendEvent", () => {
424
+ this.options.wrapper.dispatchEvent(
425
+ new CustomEvent("scrollend", {
426
+ bubbles: this.options.wrapper === window,
427
+ // cancelable: false,
428
+ detail: {
429
+ lenisScrollEnd: true
430
+ }
431
+ })
432
+ );
433
+ });
434
+ __publicField(this, "onTransitionEnd", (event) => {
435
+ if (event.propertyName.includes("overflow")) {
436
+ this.checkOverflow();
437
+ }
438
+ });
439
+ __publicField(this, "onClick", (event) => {
440
+ const path = event.composedPath();
441
+ const anchorElements = path.filter(
442
+ (node) => node instanceof HTMLAnchorElement && node.getAttribute("href")
443
+ );
444
+ if (this.options.anchors) {
445
+ const anchor = anchorElements.find(
446
+ (node) => node.getAttribute("href")?.includes("#")
447
+ );
448
+ if (anchor) {
449
+ const href = anchor.getAttribute("href");
450
+ if (href) {
451
+ const options = typeof this.options.anchors === "object" && this.options.anchors ? this.options.anchors : void 0;
452
+ const target = `#${href.split("#")[1]}`;
453
+ this.scrollTo(target, options);
454
+ }
455
+ }
456
+ }
457
+ if (this.options.stopInertiaOnNavigate) {
458
+ const internalLink = anchorElements.find(
459
+ (node) => node.host === window.location.host
460
+ );
461
+ if (internalLink) {
462
+ this.reset();
463
+ }
464
+ }
465
+ });
466
+ __publicField(this, "onPointerDown", (event) => {
467
+ if (event.button === 1) {
468
+ this.reset();
469
+ }
470
+ });
471
+ __publicField(this, "onVirtualScroll", (data) => {
472
+ if (typeof this.options.virtualScroll === "function" && this.options.virtualScroll(data) === false)
473
+ return;
474
+ const { deltaX, deltaY, event } = data;
475
+ this.emitter.emit("virtual-scroll", { deltaX, deltaY, event });
476
+ if (event.ctrlKey) return;
477
+ if (event.lenisStopPropagation) return;
478
+ const isTouch = event.type.includes("touch");
479
+ const isWheel = event.type.includes("wheel");
480
+ this.isTouching = event.type === "touchstart" || event.type === "touchmove";
481
+ const isClickOrTap = deltaX === 0 && deltaY === 0;
482
+ const isTapToStop = this.options.syncTouch && isTouch && event.type === "touchstart" && isClickOrTap && !this.isStopped && !this.isLocked;
483
+ if (isTapToStop) {
484
+ this.reset();
485
+ return;
486
+ }
487
+ const isUnknownGesture = this.options.gestureOrientation === "vertical" && deltaY === 0 || this.options.gestureOrientation === "horizontal" && deltaX === 0;
488
+ if (isClickOrTap || isUnknownGesture) {
489
+ return;
490
+ }
491
+ let composedPath = event.composedPath();
492
+ composedPath = composedPath.slice(0, composedPath.indexOf(this.rootElement));
493
+ const prevent = this.options.prevent;
494
+ if (!!composedPath.find(
495
+ (node) => node instanceof HTMLElement && (typeof prevent === "function" && prevent?.(node) || node.hasAttribute?.("data-lenis-prevent") || isTouch && node.hasAttribute?.("data-lenis-prevent-touch") || isWheel && node.hasAttribute?.("data-lenis-prevent-wheel") || this.options.allowNestedScroll && this.checkNestedScroll(node, { deltaX, deltaY }))
496
+ ))
497
+ return;
498
+ if (this.isStopped || this.isLocked) {
499
+ if (event.cancelable) {
500
+ event.preventDefault();
501
+ }
502
+ return;
503
+ }
504
+ const isSmooth = this.options.syncTouch && isTouch || this.options.smoothWheel && isWheel;
505
+ if (!isSmooth) {
506
+ this.isScrolling = "native";
507
+ this.animate.stop();
508
+ event.lenisStopPropagation = true;
509
+ return;
510
+ }
511
+ let delta = deltaY;
512
+ if (this.options.gestureOrientation === "both") {
513
+ delta = Math.abs(deltaY) > Math.abs(deltaX) ? deltaY : deltaX;
514
+ } else if (this.options.gestureOrientation === "horizontal") {
515
+ delta = deltaX;
516
+ }
517
+ if (!this.options.overscroll || this.options.infinite || this.options.wrapper !== window && this.limit > 0 && (this.animatedScroll > 0 && this.animatedScroll < this.limit || this.animatedScroll === 0 && deltaY > 0 || this.animatedScroll === this.limit && deltaY < 0)) {
518
+ event.lenisStopPropagation = true;
519
+ }
520
+ if (event.cancelable) {
521
+ event.preventDefault();
522
+ }
523
+ const isSyncTouch = isTouch && this.options.syncTouch;
524
+ const isTouchEnd = isTouch && event.type === "touchend";
525
+ const hasTouchInertia = isTouchEnd;
526
+ if (hasTouchInertia) {
527
+ delta = Math.sign(this.velocity) * Math.pow(Math.abs(this.velocity), this.options.touchInertiaExponent);
528
+ }
529
+ this.scrollTo(this.targetScroll + delta, {
530
+ programmatic: false,
531
+ ...isSyncTouch ? {
532
+ lerp: hasTouchInertia ? this.options.syncTouchLerp : 1
533
+ } : {
534
+ lerp: this.options.lerp,
535
+ duration: this.options.duration,
536
+ easing: this.options.easing
537
+ }
538
+ });
539
+ });
540
+ __publicField(this, "onNativeScroll", () => {
541
+ if (this._resetVelocityTimeout !== null) {
542
+ clearTimeout(this._resetVelocityTimeout);
543
+ this._resetVelocityTimeout = null;
544
+ }
545
+ if (this._preventNextNativeScrollEvent) {
546
+ this._preventNextNativeScrollEvent = false;
547
+ return;
548
+ }
549
+ if (this.isScrolling === false || this.isScrolling === "native") {
550
+ const lastScroll = this.animatedScroll;
551
+ this.animatedScroll = this.targetScroll = this.actualScroll;
552
+ this.lastVelocity = this.velocity;
553
+ this.velocity = this.animatedScroll - lastScroll;
554
+ this.direction = Math.sign(
555
+ this.animatedScroll - lastScroll
556
+ );
557
+ if (!this.isStopped) {
558
+ this.isScrolling = "native";
559
+ }
560
+ this.emit();
561
+ if (this.velocity !== 0) {
562
+ this._resetVelocityTimeout = setTimeout(() => {
563
+ this.lastVelocity = this.velocity;
564
+ this.velocity = 0;
565
+ this.isScrolling = false;
566
+ this.emit();
567
+ }, 400);
568
+ }
569
+ }
570
+ });
571
+ /**
572
+ * RequestAnimationFrame for lenis
573
+ *
574
+ * @param time The time in ms from an external clock like `requestAnimationFrame` or Tempus
575
+ */
576
+ __publicField(this, "raf", (time) => {
577
+ const deltaTime = time - (this.time || time);
578
+ this.time = time;
579
+ this.animate.advance(deltaTime * 1e-3);
580
+ if (this.options.autoRaf) {
581
+ this._rafId = requestAnimationFrame(this.raf);
582
+ }
583
+ });
584
+ window.lenisVersion = version;
585
+ if (!wrapper || wrapper === document.documentElement) {
586
+ wrapper = window;
587
+ }
588
+ if (typeof duration === "number" && typeof easing !== "function") {
589
+ easing = defaultEasing;
590
+ } else if (typeof easing === "function" && typeof duration !== "number") {
591
+ duration = 1;
592
+ }
593
+ this.options = {
594
+ wrapper,
595
+ content,
596
+ eventsTarget,
597
+ smoothWheel,
598
+ syncTouch,
599
+ syncTouchLerp,
600
+ touchInertiaExponent,
601
+ duration,
602
+ easing,
603
+ lerp: lerp2,
604
+ infinite,
605
+ gestureOrientation,
606
+ orientation,
607
+ touchMultiplier,
608
+ wheelMultiplier,
609
+ autoResize,
610
+ prevent,
611
+ virtualScroll,
612
+ overscroll,
613
+ autoRaf,
614
+ anchors,
615
+ autoToggle,
616
+ allowNestedScroll,
617
+ naiveDimensions,
618
+ stopInertiaOnNavigate
619
+ };
620
+ this.dimensions = new Dimensions(wrapper, content, { autoResize });
621
+ this.updateClassName();
622
+ this.targetScroll = this.animatedScroll = this.actualScroll;
623
+ this.options.wrapper.addEventListener("scroll", this.onNativeScroll, false);
624
+ this.options.wrapper.addEventListener("scrollend", this.onScrollEnd, {
625
+ capture: true
626
+ });
627
+ if (this.options.anchors || this.options.stopInertiaOnNavigate) {
628
+ this.options.wrapper.addEventListener(
629
+ "click",
630
+ this.onClick,
631
+ false
632
+ );
633
+ }
634
+ this.options.wrapper.addEventListener(
635
+ "pointerdown",
636
+ this.onPointerDown,
637
+ false
638
+ );
639
+ this.virtualScroll = new VirtualScroll(eventsTarget, {
640
+ touchMultiplier,
641
+ wheelMultiplier
642
+ });
643
+ this.virtualScroll.on("scroll", this.onVirtualScroll);
644
+ if (this.options.autoToggle) {
645
+ this.checkOverflow();
646
+ this.rootElement.addEventListener("transitionend", this.onTransitionEnd, {
647
+ passive: true
648
+ });
649
+ }
650
+ if (this.options.autoRaf) {
651
+ this._rafId = requestAnimationFrame(this.raf);
652
+ }
653
+ }
654
+ /**
655
+ * Destroy the lenis instance, remove all event listeners and clean up the class name
656
+ */
657
+ destroy() {
658
+ this.emitter.destroy();
659
+ this.options.wrapper.removeEventListener(
660
+ "scroll",
661
+ this.onNativeScroll,
662
+ false
663
+ );
664
+ this.options.wrapper.removeEventListener("scrollend", this.onScrollEnd, {
665
+ capture: true
666
+ });
667
+ this.options.wrapper.removeEventListener(
668
+ "pointerdown",
669
+ this.onPointerDown,
670
+ false
671
+ );
672
+ if (this.options.anchors || this.options.stopInertiaOnNavigate) {
673
+ this.options.wrapper.removeEventListener(
674
+ "click",
675
+ this.onClick,
676
+ false
677
+ );
678
+ }
679
+ this.virtualScroll.destroy();
680
+ this.dimensions.destroy();
681
+ this.cleanUpClassName();
682
+ if (this._rafId) {
683
+ cancelAnimationFrame(this._rafId);
684
+ }
685
+ }
686
+ on(event, callback) {
687
+ return this.emitter.on(event, callback);
688
+ }
689
+ off(event, callback) {
690
+ return this.emitter.off(event, callback);
691
+ }
692
+ get overflow() {
693
+ const property = this.isHorizontal ? "overflow-x" : "overflow-y";
694
+ return getComputedStyle(this.rootElement)[property];
695
+ }
696
+ checkOverflow() {
697
+ if (["hidden", "clip"].includes(this.overflow)) {
698
+ this.internalStop();
699
+ } else {
700
+ this.internalStart();
701
+ }
702
+ }
703
+ setScroll(scroll) {
704
+ if (this.isHorizontal) {
705
+ this.options.wrapper.scrollTo({ left: scroll, behavior: "instant" });
706
+ } else {
707
+ this.options.wrapper.scrollTo({ top: scroll, behavior: "instant" });
708
+ }
709
+ }
710
+ /**
711
+ * Force lenis to recalculate the dimensions
712
+ */
713
+ resize() {
714
+ this.dimensions.resize();
715
+ this.animatedScroll = this.targetScroll = this.actualScroll;
716
+ this.emit();
717
+ }
718
+ emit() {
719
+ this.emitter.emit("scroll", this);
720
+ }
721
+ reset() {
722
+ this.isLocked = false;
723
+ this.isScrolling = false;
724
+ this.animatedScroll = this.targetScroll = this.actualScroll;
725
+ this.lastVelocity = this.velocity = 0;
726
+ this.animate.stop();
727
+ }
728
+ /**
729
+ * Start lenis scroll after it has been stopped
730
+ */
731
+ start() {
732
+ if (!this.isStopped) return;
733
+ if (this.options.autoToggle) {
734
+ this.rootElement.style.removeProperty("overflow");
735
+ return;
736
+ }
737
+ this.internalStart();
738
+ }
739
+ internalStart() {
740
+ if (!this.isStopped) return;
741
+ this.reset();
742
+ this.isStopped = false;
743
+ this.emit();
744
+ }
745
+ /**
746
+ * Stop lenis scroll
747
+ */
748
+ stop() {
749
+ if (this.isStopped) return;
750
+ if (this.options.autoToggle) {
751
+ this.rootElement.style.setProperty("overflow", "clip");
752
+ return;
753
+ }
754
+ this.internalStop();
755
+ }
756
+ internalStop() {
757
+ if (this.isStopped) return;
758
+ this.reset();
759
+ this.isStopped = true;
760
+ this.emit();
761
+ }
762
+ /**
763
+ * Scroll to a target value
764
+ *
765
+ * @param target The target value to scroll to
766
+ * @param options The options for the scroll
767
+ *
768
+ * @example
769
+ * lenis.scrollTo(100, {
770
+ * offset: 100,
771
+ * duration: 1,
772
+ * easing: (t) => 1 - Math.cos((t * Math.PI) / 2),
773
+ * lerp: 0.1,
774
+ * onStart: () => {
775
+ * console.log('onStart')
776
+ * },
777
+ * onComplete: () => {
778
+ * console.log('onComplete')
779
+ * },
780
+ * })
781
+ */
782
+ scrollTo(target, {
783
+ offset = 0,
784
+ immediate = false,
785
+ lock = false,
786
+ programmatic = true,
787
+ // called from outside of the class
788
+ lerp: lerp2 = programmatic ? this.options.lerp : void 0,
789
+ duration = programmatic ? this.options.duration : void 0,
790
+ easing = programmatic ? this.options.easing : void 0,
791
+ onStart,
792
+ onComplete,
793
+ force = false,
794
+ // scroll even if stopped
795
+ userData
796
+ } = {}) {
797
+ if ((this.isStopped || this.isLocked) && !force) return;
798
+ if (typeof target === "string" && ["top", "left", "start", "#"].includes(target)) {
799
+ target = 0;
800
+ } else if (typeof target === "string" && ["bottom", "right", "end"].includes(target)) {
801
+ target = this.limit;
802
+ } else {
803
+ let node;
804
+ if (typeof target === "string") {
805
+ node = document.querySelector(target);
806
+ if (!node) {
807
+ if (target === "#top") {
808
+ target = 0;
809
+ } else {
810
+ console.warn("Lenis: Target not found", target);
811
+ }
812
+ }
813
+ } else if (target instanceof HTMLElement && target?.nodeType) {
814
+ node = target;
815
+ }
816
+ if (node) {
817
+ if (this.options.wrapper !== window) {
818
+ const wrapperRect = this.rootElement.getBoundingClientRect();
819
+ offset -= this.isHorizontal ? wrapperRect.left : wrapperRect.top;
820
+ }
821
+ const rect = node.getBoundingClientRect();
822
+ target = (this.isHorizontal ? rect.left : rect.top) + this.animatedScroll;
823
+ }
824
+ }
825
+ if (typeof target !== "number") return;
826
+ target += offset;
827
+ target = Math.round(target);
828
+ if (this.options.infinite) {
829
+ if (programmatic) {
830
+ this.targetScroll = this.animatedScroll = this.scroll;
831
+ const distance = target - this.animatedScroll;
832
+ if (distance > this.limit / 2) {
833
+ target = target - this.limit;
834
+ } else if (distance < -this.limit / 2) {
835
+ target = target + this.limit;
836
+ }
837
+ }
838
+ } else {
839
+ target = clamp(0, target, this.limit);
840
+ }
841
+ if (target === this.targetScroll) {
842
+ onStart?.(this);
843
+ onComplete?.(this);
844
+ return;
845
+ }
846
+ this.userData = userData ?? {};
847
+ if (immediate) {
848
+ this.animatedScroll = this.targetScroll = target;
849
+ this.setScroll(this.scroll);
850
+ this.reset();
851
+ this.preventNextNativeScrollEvent();
852
+ this.emit();
853
+ onComplete?.(this);
854
+ this.userData = {};
855
+ requestAnimationFrame(() => {
856
+ this.dispatchScrollendEvent();
857
+ });
858
+ return;
859
+ }
860
+ if (!programmatic) {
861
+ this.targetScroll = target;
862
+ }
863
+ if (typeof duration === "number" && typeof easing !== "function") {
864
+ easing = defaultEasing;
865
+ } else if (typeof easing === "function" && typeof duration !== "number") {
866
+ duration = 1;
867
+ }
868
+ this.animate.fromTo(this.animatedScroll, target, {
869
+ duration,
870
+ easing,
871
+ lerp: lerp2,
872
+ onStart: () => {
873
+ if (lock) this.isLocked = true;
874
+ this.isScrolling = "smooth";
875
+ onStart?.(this);
876
+ },
877
+ onUpdate: (value, completed) => {
878
+ this.isScrolling = "smooth";
879
+ this.lastVelocity = this.velocity;
880
+ this.velocity = value - this.animatedScroll;
881
+ this.direction = Math.sign(this.velocity);
882
+ this.animatedScroll = value;
883
+ this.setScroll(this.scroll);
884
+ if (programmatic) {
885
+ this.targetScroll = value;
886
+ }
887
+ if (!completed) this.emit();
888
+ if (completed) {
889
+ this.reset();
890
+ this.emit();
891
+ onComplete?.(this);
892
+ this.userData = {};
893
+ requestAnimationFrame(() => {
894
+ this.dispatchScrollendEvent();
895
+ });
896
+ this.preventNextNativeScrollEvent();
897
+ }
898
+ }
899
+ });
900
+ }
901
+ preventNextNativeScrollEvent() {
902
+ this._preventNextNativeScrollEvent = true;
903
+ requestAnimationFrame(() => {
904
+ this._preventNextNativeScrollEvent = false;
905
+ });
906
+ }
907
+ checkNestedScroll(node, { deltaX, deltaY }) {
908
+ const time = Date.now();
909
+ const cache = node._lenis ?? (node._lenis = {});
910
+ let hasOverflowX, hasOverflowY, isScrollableX, isScrollableY, scrollWidth, scrollHeight, clientWidth, clientHeight;
911
+ const gestureOrientation = this.options.gestureOrientation;
912
+ if (time - (cache.time ?? 0) > 2e3) {
913
+ cache.time = Date.now();
914
+ const computedStyle = window.getComputedStyle(node);
915
+ cache.computedStyle = computedStyle;
916
+ const overflowXString = computedStyle.overflowX;
917
+ const overflowYString = computedStyle.overflowY;
918
+ hasOverflowX = ["auto", "overlay", "scroll"].includes(overflowXString);
919
+ hasOverflowY = ["auto", "overlay", "scroll"].includes(overflowYString);
920
+ cache.hasOverflowX = hasOverflowX;
921
+ cache.hasOverflowY = hasOverflowY;
922
+ if (!hasOverflowX && !hasOverflowY) return false;
923
+ if (gestureOrientation === "vertical" && !hasOverflowY) return false;
924
+ if (gestureOrientation === "horizontal" && !hasOverflowX) return false;
925
+ scrollWidth = node.scrollWidth;
926
+ scrollHeight = node.scrollHeight;
927
+ clientWidth = node.clientWidth;
928
+ clientHeight = node.clientHeight;
929
+ isScrollableX = scrollWidth > clientWidth;
930
+ isScrollableY = scrollHeight > clientHeight;
931
+ cache.isScrollableX = isScrollableX;
932
+ cache.isScrollableY = isScrollableY;
933
+ cache.scrollWidth = scrollWidth;
934
+ cache.scrollHeight = scrollHeight;
935
+ cache.clientWidth = clientWidth;
936
+ cache.clientHeight = clientHeight;
937
+ } else {
938
+ isScrollableX = cache.isScrollableX;
939
+ isScrollableY = cache.isScrollableY;
940
+ hasOverflowX = cache.hasOverflowX;
941
+ hasOverflowY = cache.hasOverflowY;
942
+ scrollWidth = cache.scrollWidth;
943
+ scrollHeight = cache.scrollHeight;
944
+ clientWidth = cache.clientWidth;
945
+ clientHeight = cache.clientHeight;
946
+ }
947
+ if (!hasOverflowX && !hasOverflowY || !isScrollableX && !isScrollableY) {
948
+ return false;
949
+ }
950
+ if (gestureOrientation === "vertical" && (!hasOverflowY || !isScrollableY))
951
+ return false;
952
+ if (gestureOrientation === "horizontal" && (!hasOverflowX || !isScrollableX))
953
+ return false;
954
+ let orientation;
955
+ if (gestureOrientation === "horizontal") {
956
+ orientation = "x";
957
+ } else if (gestureOrientation === "vertical") {
958
+ orientation = "y";
959
+ } else {
960
+ const isScrollingX = deltaX !== 0;
961
+ const isScrollingY = deltaY !== 0;
962
+ if (isScrollingX && hasOverflowX && isScrollableX) {
963
+ orientation = "x";
964
+ }
965
+ if (isScrollingY && hasOverflowY && isScrollableY) {
966
+ orientation = "y";
967
+ }
968
+ }
969
+ if (!orientation) return false;
970
+ let scroll, maxScroll, delta, hasOverflow, isScrollable;
971
+ if (orientation === "x") {
972
+ scroll = node.scrollLeft;
973
+ maxScroll = scrollWidth - clientWidth;
974
+ delta = deltaX;
975
+ hasOverflow = hasOverflowX;
976
+ isScrollable = isScrollableX;
977
+ } else if (orientation === "y") {
978
+ scroll = node.scrollTop;
979
+ maxScroll = scrollHeight - clientHeight;
980
+ delta = deltaY;
981
+ hasOverflow = hasOverflowY;
982
+ isScrollable = isScrollableY;
983
+ } else {
984
+ return false;
985
+ }
986
+ const willScroll = delta > 0 ? scroll < maxScroll : scroll > 0;
987
+ return willScroll && hasOverflow && isScrollable;
988
+ }
989
+ /**
990
+ * The root element on which lenis is instanced
991
+ */
992
+ get rootElement() {
993
+ return this.options.wrapper === window ? document.documentElement : this.options.wrapper;
994
+ }
995
+ /**
996
+ * The limit which is the maximum scroll value
997
+ */
998
+ get limit() {
999
+ if (this.options.naiveDimensions) {
1000
+ if (this.isHorizontal) {
1001
+ return this.rootElement.scrollWidth - this.rootElement.clientWidth;
1002
+ } else {
1003
+ return this.rootElement.scrollHeight - this.rootElement.clientHeight;
1004
+ }
1005
+ } else {
1006
+ return this.dimensions.limit[this.isHorizontal ? "x" : "y"];
1007
+ }
1008
+ }
1009
+ /**
1010
+ * Whether or not the scroll is horizontal
1011
+ */
1012
+ get isHorizontal() {
1013
+ return this.options.orientation === "horizontal";
1014
+ }
1015
+ /**
1016
+ * The actual scroll value
1017
+ */
1018
+ get actualScroll() {
1019
+ const wrapper = this.options.wrapper;
1020
+ return this.isHorizontal ? wrapper.scrollX ?? wrapper.scrollLeft : wrapper.scrollY ?? wrapper.scrollTop;
1021
+ }
1022
+ /**
1023
+ * The current scroll value
1024
+ */
1025
+ get scroll() {
1026
+ return this.options.infinite ? modulo(this.animatedScroll, this.limit) : this.animatedScroll;
1027
+ }
1028
+ /**
1029
+ * The progress of the scroll relative to the limit
1030
+ */
1031
+ get progress() {
1032
+ return this.limit === 0 ? 1 : this.scroll / this.limit;
1033
+ }
1034
+ /**
1035
+ * Current scroll state
1036
+ */
1037
+ get isScrolling() {
1038
+ return this._isScrolling;
1039
+ }
1040
+ set isScrolling(value) {
1041
+ if (this._isScrolling !== value) {
1042
+ this._isScrolling = value;
1043
+ this.updateClassName();
1044
+ }
1045
+ }
1046
+ /**
1047
+ * Check if lenis is stopped
1048
+ */
1049
+ get isStopped() {
1050
+ return this._isStopped;
1051
+ }
1052
+ set isStopped(value) {
1053
+ if (this._isStopped !== value) {
1054
+ this._isStopped = value;
1055
+ this.updateClassName();
1056
+ }
1057
+ }
1058
+ /**
1059
+ * Check if lenis is locked
1060
+ */
1061
+ get isLocked() {
1062
+ return this._isLocked;
1063
+ }
1064
+ set isLocked(value) {
1065
+ if (this._isLocked !== value) {
1066
+ this._isLocked = value;
1067
+ this.updateClassName();
1068
+ }
1069
+ }
1070
+ /**
1071
+ * Check if lenis is smooth scrolling
1072
+ */
1073
+ get isSmooth() {
1074
+ return this.isScrolling === "smooth";
1075
+ }
1076
+ /**
1077
+ * The class name applied to the wrapper element
1078
+ */
1079
+ get className() {
1080
+ let className = "lenis";
1081
+ if (this.options.autoToggle) className += " lenis-autoToggle";
1082
+ if (this.isStopped) className += " lenis-stopped";
1083
+ if (this.isLocked) className += " lenis-locked";
1084
+ if (this.isScrolling) className += " lenis-scrolling";
1085
+ if (this.isScrolling === "smooth") className += " lenis-smooth";
1086
+ return className;
1087
+ }
1088
+ updateClassName() {
1089
+ this.cleanUpClassName();
1090
+ this.rootElement.className = `${this.rootElement.className} ${this.className}`.trim();
1091
+ }
1092
+ cleanUpClassName() {
1093
+ this.rootElement.className = this.rootElement.className.replace(/lenis(-\w+)?/g, "").trim();
1094
+ }
1095
+ };
1096
+ export {
1097
+ Lenis as L
1098
+ };
1099
+ //# sourceMappingURL=vendor-lenis-yRRXrftv.js.map