lenis 1.1.4 → 1.1.6-dev.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/lenis.js CHANGED
@@ -4,7 +4,7 @@
4
4
  (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.Lenis = factory());
5
5
  })(this, (function () { 'use strict';
6
6
 
7
- var version = "1.1.4";
7
+ var version = "1.1.6-dev.0";
8
8
 
9
9
  // Clamp a value between a minimum and maximum value
10
10
  function clamp(min, input, max) {
@@ -27,60 +27,57 @@
27
27
  return ((n % d) + d) % d
28
28
  }
29
29
 
30
- // Animate class to handle value animations with lerping or easing
31
- class Animate {
32
- // Advance the animation by the given delta time
33
- advance(deltaTime) {
34
- if (!this.isRunning) return
35
-
36
- let completed = false;
37
-
38
- if (this.duration && this.easing) {
39
- this.currentTime += deltaTime;
40
- const linearProgress = clamp(0, this.currentTime / this.duration, 1);
41
-
42
- completed = linearProgress >= 1;
43
- const easedProgress = completed ? 1 : this.easing(linearProgress);
44
- this.value = this.from + (this.to - this.from) * easedProgress;
45
- } else if (this.lerp) {
46
- this.value = damp(this.value, this.to, this.lerp * 60, deltaTime);
47
- if (Math.round(this.value) === this.to) {
48
- this.value = this.to;
49
- completed = true;
50
- }
51
- } else {
52
- // If no easing or lerp, just jump to the end value
53
- this.value = this.to;
54
- completed = true;
55
- }
56
-
57
- if (completed) {
58
- this.stop();
59
- }
60
-
61
- // Call the onUpdate callback with the current value and completed status
62
- this.onUpdate?.(this.value, completed);
63
- }
64
-
65
- // Stop the animation
66
- stop() {
67
- this.isRunning = false;
68
- }
69
-
70
- // Set up the animation from a starting value to an ending value
71
- // with optional parameters for lerping, duration, easing, and onUpdate callback
72
- fromTo(from, to, { lerp, duration, easing, onStart, onUpdate }) {
73
- this.from = this.value = from;
74
- this.to = to;
75
- this.lerp = lerp;
76
- this.duration = duration;
77
- this.easing = easing;
78
- this.currentTime = 0;
79
- this.isRunning = true;
80
-
81
- onStart?.();
82
- this.onUpdate = onUpdate;
83
- }
30
+ class Animate {
31
+ constructor() {
32
+ this.isRunning = false;
33
+ this.value = 0;
34
+ this.from = 0;
35
+ this.to = 0;
36
+ this.duration = 0;
37
+ this.currentTime = 0;
38
+ }
39
+ advance(deltaTime) {
40
+ var _a;
41
+ if (!this.isRunning)
42
+ return;
43
+ let completed = false;
44
+ if (this.duration && this.easing) {
45
+ this.currentTime += deltaTime;
46
+ const linearProgress = clamp(0, this.currentTime / this.duration, 1);
47
+ completed = linearProgress >= 1;
48
+ const easedProgress = completed ? 1 : this.easing(linearProgress);
49
+ this.value = this.from + (this.to - this.from) * easedProgress;
50
+ }
51
+ else if (this.lerp) {
52
+ this.value = damp(this.value, this.to, this.lerp * 60, deltaTime);
53
+ if (Math.round(this.value) === this.to) {
54
+ this.value = this.to;
55
+ completed = true;
56
+ }
57
+ }
58
+ else {
59
+ this.value = this.to;
60
+ completed = true;
61
+ }
62
+ if (completed) {
63
+ this.stop();
64
+ }
65
+ (_a = this.onUpdate) === null || _a === void 0 ? void 0 : _a.call(this, this.value, completed);
66
+ }
67
+ stop() {
68
+ this.isRunning = false;
69
+ }
70
+ fromTo(from, to, { lerp, duration, easing, onStart, onUpdate, }) {
71
+ this.from = this.value = from;
72
+ this.to = to;
73
+ this.lerp = lerp;
74
+ this.duration = duration;
75
+ this.easing = easing;
76
+ this.currentTime = 0;
77
+ this.isRunning = true;
78
+ onStart === null || onStart === void 0 ? void 0 : onStart();
79
+ this.onUpdate = onUpdate;
80
+ }
84
81
  }
85
82
 
86
83
  function debounce(callback, delay) {
@@ -95,246 +92,214 @@
95
92
  }
96
93
  }
97
94
 
98
- class Dimensions {
99
- constructor({
100
- wrapper,
101
- content,
102
- autoResize = true,
103
- debounce: debounceValue = 250,
104
- } = {}) {
105
- this.wrapper = wrapper;
106
- this.content = content;
107
-
108
- if (autoResize) {
109
- this.debouncedResize = debounce(this.resize, debounceValue);
110
-
111
- if (this.wrapper === window) {
112
- window.addEventListener('resize', this.debouncedResize, false);
113
- } else {
114
- this.wrapperResizeObserver = new ResizeObserver(this.debouncedResize);
115
- this.wrapperResizeObserver.observe(this.wrapper);
116
- }
117
-
118
- this.contentResizeObserver = new ResizeObserver(this.debouncedResize);
119
- this.contentResizeObserver.observe(this.content);
120
- }
121
-
122
- this.resize();
123
- }
124
-
125
- destroy() {
126
- this.wrapperResizeObserver?.disconnect();
127
- this.contentResizeObserver?.disconnect();
128
- window.removeEventListener('resize', this.debouncedResize, false);
129
- }
130
-
131
- resize = () => {
132
- this.onWrapperResize();
133
- this.onContentResize();
134
- }
135
-
136
- onWrapperResize = () => {
137
- if (this.wrapper === window) {
138
- this.width = window.innerWidth;
139
- this.height = window.innerHeight;
140
- } else {
141
- this.width = this.wrapper.clientWidth;
142
- this.height = this.wrapper.clientHeight;
143
- }
144
- }
145
-
146
- onContentResize = () => {
147
- if (this.wrapper === window) {
148
- this.scrollHeight = this.content.scrollHeight;
149
- this.scrollWidth = this.content.scrollWidth;
150
- } else {
151
- this.scrollHeight = this.wrapper.scrollHeight;
152
- this.scrollWidth = this.wrapper.scrollWidth;
153
- }
154
- }
155
-
156
- get limit() {
157
- return {
158
- x: this.scrollWidth - this.width,
159
- y: this.scrollHeight - this.height,
160
- }
161
- }
95
+ class Dimensions {
96
+ constructor({ wrapper, content, autoResize = true, debounce: debounceValue = 250, } = {}) {
97
+ this.width = 0;
98
+ this.height = 0;
99
+ this.scrollWidth = 0;
100
+ this.scrollHeight = 0;
101
+ this.resize = () => {
102
+ this.onWrapperResize();
103
+ this.onContentResize();
104
+ };
105
+ this.onWrapperResize = () => {
106
+ if (this.wrapper === window) {
107
+ this.width = window.innerWidth;
108
+ this.height = window.innerHeight;
109
+ }
110
+ else if (this.wrapper instanceof HTMLElement) {
111
+ this.width = this.wrapper.clientWidth;
112
+ this.height = this.wrapper.clientHeight;
113
+ }
114
+ };
115
+ this.onContentResize = () => {
116
+ if (this.wrapper === window) {
117
+ this.scrollHeight = this.content.scrollHeight;
118
+ this.scrollWidth = this.content.scrollWidth;
119
+ }
120
+ else if (this.wrapper instanceof HTMLElement) {
121
+ this.scrollHeight = this.wrapper.scrollHeight;
122
+ this.scrollWidth = this.wrapper.scrollWidth;
123
+ }
124
+ };
125
+ this.wrapper = wrapper;
126
+ this.content = content;
127
+ if (autoResize) {
128
+ this.debouncedResize = debounce(this.resize, debounceValue);
129
+ if (this.wrapper === window) {
130
+ window.addEventListener('resize', this.debouncedResize, false);
131
+ }
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
+ var _a, _b;
143
+ (_a = this.wrapperResizeObserver) === null || _a === void 0 ? void 0 : _a.disconnect();
144
+ (_b = this.contentResizeObserver) === null || _b === void 0 ? void 0 : _b.disconnect();
145
+ window.removeEventListener('resize', this.debouncedResize, false);
146
+ }
147
+ get limit() {
148
+ return {
149
+ x: this.scrollWidth - this.width,
150
+ y: this.scrollHeight - this.height,
151
+ };
152
+ }
162
153
  }
163
154
 
164
- class Emitter {
165
- constructor() {
166
- this.events = {};
167
- }
168
-
169
- emit(event, ...args) {
170
- let callbacks = this.events[event] || [];
171
- for (let i = 0, length = callbacks.length; i < length; i++) {
172
- callbacks[i](...args);
173
- }
174
- }
175
-
176
- on(event, cb) {
177
- // Add the callback to the event's callback list, or create a new list with the callback
178
- this.events[event]?.push(cb) || (this.events[event] = [cb]);
179
-
180
- // Return an unsubscribe function
181
- return () => {
182
- this.events[event] = this.events[event]?.filter((i) => cb !== i);
183
- }
184
- }
185
-
186
- off(event, callback) {
187
- this.events[event] = this.events[event]?.filter((i) => callback !== i);
188
- }
189
-
190
- destroy() {
191
- this.events = {};
192
- }
155
+ class Emitter {
156
+ constructor() {
157
+ this.events = {};
158
+ }
159
+ emit(event, ...args) {
160
+ let callbacks = this.events[event] || [];
161
+ for (let i = 0, length = callbacks.length; i < length; i++) {
162
+ callbacks[i](...args);
163
+ }
164
+ }
165
+ on(event, callback) {
166
+ var _a;
167
+ ((_a = this.events[event]) === null || _a === void 0 ? void 0 : _a.push(callback)) || (this.events[event] = [callback]);
168
+ return () => {
169
+ var _a;
170
+ this.events[event] = (_a = this.events[event]) === null || _a === void 0 ? void 0 : _a.filter((i) => callback !== i);
171
+ };
172
+ }
173
+ off(event, callback) {
174
+ var _a;
175
+ this.events[event] = (_a = this.events[event]) === null || _a === void 0 ? void 0 : _a.filter((i) => callback !== i);
176
+ }
177
+ destroy() {
178
+ this.events = {};
179
+ }
193
180
  }
194
181
 
195
- const LINE_HEIGHT = 100 / 6;
196
-
197
- class VirtualScroll {
198
- constructor(element, { wheelMultiplier = 1, touchMultiplier = 1 }) {
199
- this.element = element;
200
- this.wheelMultiplier = wheelMultiplier;
201
- this.touchMultiplier = touchMultiplier;
202
-
203
- this.touchStart = {
204
- x: null,
205
- y: null,
206
- };
207
-
208
- this.emitter = new Emitter();
209
- window.addEventListener('resize', this.onWindowResize, false);
210
- this.onWindowResize();
211
-
212
- this.element.addEventListener('wheel', this.onWheel, { passive: false });
213
- this.element.addEventListener('touchstart', this.onTouchStart, {
214
- passive: false,
215
- });
216
- this.element.addEventListener('touchmove', this.onTouchMove, {
217
- passive: false,
218
- });
219
- this.element.addEventListener('touchend', this.onTouchEnd, {
220
- passive: false,
221
- });
222
- }
223
-
224
- // Add an event listener for the given event and callback
225
- on(event, callback) {
226
- return this.emitter.on(event, callback)
227
- }
228
-
229
- // Remove all event listeners and clean up
230
- destroy() {
231
- this.emitter.destroy();
232
-
233
- window.removeEventListener('resize', this.onWindowResize, false);
234
-
235
- this.element.removeEventListener('wheel', this.onWheel, {
236
- passive: false,
237
- });
238
- this.element.removeEventListener('touchstart', this.onTouchStart, {
239
- passive: false,
240
- });
241
- this.element.removeEventListener('touchmove', this.onTouchMove, {
242
- passive: false,
243
- });
244
- this.element.removeEventListener('touchend', this.onTouchEnd, {
245
- passive: false,
246
- });
247
- }
248
-
249
- // Event handler for 'touchstart' event
250
- onTouchStart = (event) => {
251
- const { clientX, clientY } = event.targetTouches
252
- ? event.targetTouches[0]
253
- : event;
254
-
255
- this.touchStart.x = clientX;
256
- this.touchStart.y = clientY;
257
-
258
- this.lastDelta = {
259
- x: 0,
260
- y: 0,
261
- };
262
-
263
- this.emitter.emit('scroll', {
264
- deltaX: 0,
265
- deltaY: 0,
266
- event,
267
- });
268
- }
269
-
270
- // Event handler for 'touchmove' event
271
- onTouchMove = (event) => {
272
- const { clientX, clientY } = event.targetTouches
273
- ? event.targetTouches[0]
274
- : event;
275
-
276
- const deltaX = -(clientX - this.touchStart.x) * this.touchMultiplier;
277
- const deltaY = -(clientY - this.touchStart.y) * this.touchMultiplier;
278
-
279
- this.touchStart.x = clientX;
280
- this.touchStart.y = clientY;
281
-
282
- this.lastDelta = {
283
- x: deltaX,
284
- y: deltaY,
285
- };
286
-
287
- this.emitter.emit('scroll', {
288
- deltaX,
289
- deltaY,
290
- event,
291
- });
292
- }
293
-
294
- onTouchEnd = (event) => {
295
- this.emitter.emit('scroll', {
296
- deltaX: this.lastDelta.x,
297
- deltaY: this.lastDelta.y,
298
- event,
299
- });
300
- }
301
-
302
- // Event handler for 'wheel' event
303
- onWheel = (event) => {
304
- let { deltaX, deltaY, deltaMode } = event;
305
-
306
- const multiplierX =
307
- deltaMode === 1 ? LINE_HEIGHT : deltaMode === 2 ? this.windowWidth : 1;
308
- const multiplierY =
309
- deltaMode === 1 ? LINE_HEIGHT : deltaMode === 2 ? this.windowHeight : 1;
310
-
311
- deltaX *= multiplierX;
312
- deltaY *= multiplierY;
313
-
314
- deltaX *= this.wheelMultiplier;
315
- deltaY *= this.wheelMultiplier;
316
-
317
- this.emitter.emit('scroll', { deltaX, deltaY, event });
318
- }
319
-
320
- onWindowResize = () => {
321
- this.windowWidth = window.innerWidth;
322
- this.windowHeight = window.innerHeight;
323
- }
182
+ const LINE_HEIGHT = 100 / 6;
183
+ class VirtualScroll {
184
+ constructor(element, { wheelMultiplier = 1, touchMultiplier = 1 }) {
185
+ this.lastDelta = {
186
+ x: 0,
187
+ y: 0,
188
+ };
189
+ this.windowWidth = 0;
190
+ this.windowHeight = 0;
191
+ this.onTouchStart = (event) => {
192
+ const { clientX, clientY } = event.targetTouches
193
+ ? event.targetTouches[0]
194
+ : event;
195
+ this.touchStart.x = clientX;
196
+ this.touchStart.y = clientY;
197
+ this.lastDelta = {
198
+ x: 0,
199
+ y: 0,
200
+ };
201
+ this.emitter.emit('scroll', {
202
+ deltaX: 0,
203
+ deltaY: 0,
204
+ event,
205
+ });
206
+ };
207
+ this.onTouchMove = (event) => {
208
+ var _a, _b, _c, _d;
209
+ const { clientX, clientY } = event.targetTouches
210
+ ? event.targetTouches[0]
211
+ : event;
212
+ const deltaX = -(clientX - ((_b = (_a = this.touchStart) === null || _a === void 0 ? void 0 : _a.x) !== null && _b !== void 0 ? _b : 0)) * this.touchMultiplier;
213
+ const deltaY = -(clientY - ((_d = (_c = this.touchStart) === null || _c === void 0 ? void 0 : _c.y) !== null && _d !== void 0 ? _d : 0)) * this.touchMultiplier;
214
+ this.touchStart.x = clientX;
215
+ this.touchStart.y = clientY;
216
+ this.lastDelta = {
217
+ x: deltaX,
218
+ y: deltaY,
219
+ };
220
+ this.emitter.emit('scroll', {
221
+ deltaX,
222
+ deltaY,
223
+ event,
224
+ });
225
+ };
226
+ this.onTouchEnd = (event) => {
227
+ this.emitter.emit('scroll', {
228
+ deltaX: this.lastDelta.x,
229
+ deltaY: this.lastDelta.y,
230
+ event,
231
+ });
232
+ };
233
+ this.onWheel = (event) => {
234
+ let { deltaX, deltaY, deltaMode } = event;
235
+ const multiplierX = deltaMode === 1 ? LINE_HEIGHT : deltaMode === 2 ? this.windowWidth : 1;
236
+ const multiplierY = deltaMode === 1 ? LINE_HEIGHT : deltaMode === 2 ? this.windowHeight : 1;
237
+ deltaX *= multiplierX;
238
+ deltaY *= multiplierY;
239
+ deltaX *= this.wheelMultiplier;
240
+ deltaY *= this.wheelMultiplier;
241
+ this.emitter.emit('scroll', { deltaX, deltaY, event });
242
+ };
243
+ this.onWindowResize = () => {
244
+ this.windowWidth = window.innerWidth;
245
+ this.windowHeight = window.innerHeight;
246
+ };
247
+ this.element = element;
248
+ this.wheelMultiplier = wheelMultiplier;
249
+ this.touchMultiplier = touchMultiplier;
250
+ this.touchStart = {
251
+ x: null,
252
+ y: null,
253
+ };
254
+ this.emitter = new Emitter();
255
+ window.addEventListener('resize', this.onWindowResize, false);
256
+ this.onWindowResize();
257
+ this.element.addEventListener('wheel', this.onWheel, {
258
+ passive: false,
259
+ });
260
+ this.element.addEventListener('touchstart', this.onTouchStart, {
261
+ passive: false,
262
+ });
263
+ this.element.addEventListener('touchmove', this.onTouchMove, {
264
+ passive: false,
265
+ });
266
+ this.element.addEventListener('touchend', this.onTouchEnd, {
267
+ passive: false,
268
+ });
269
+ }
270
+ on(event, callback) {
271
+ return this.emitter.on(event, callback);
272
+ }
273
+ destroy() {
274
+ this.emitter.destroy();
275
+ window.removeEventListener('resize', this.onWindowResize, false);
276
+ this.element.removeEventListener('wheel', this.onWheel);
277
+ this.element.removeEventListener('touchstart', this.onTouchStart);
278
+ this.element.removeEventListener('touchmove', this.onTouchMove);
279
+ this.element.removeEventListener('touchend', this.onTouchEnd);
280
+ }
324
281
  }
325
282
 
326
283
  class Lenis {
327
- constructor({ wrapper = window, content = document.documentElement, wheelEventsTarget = wrapper, eventsTarget = wheelEventsTarget, smoothWheel = true, syncTouch = false, syncTouchLerp = 0.075, touchInertiaMultiplier = 35, duration, easing = (t) => Math.min(1, 1.001 - Math.pow(2, -10 * t)), lerp = 0.1, infinite = false, orientation = 'vertical', gestureOrientation = 'vertical', touchMultiplier = 1, wheelMultiplier = 1, autoResize = true, prevent = false, __experimental__naiveDimensions = false, } = {}) {
284
+ constructor({ wrapper = window, content = document.documentElement, wheelEventsTarget = wrapper, eventsTarget = wheelEventsTarget, smoothWheel = true, syncTouch = false, syncTouchLerp = 0.075, touchInertiaMultiplier = 35, duration, easing = (t) => Math.min(1, 1.001 - Math.pow(2, -10 * t)), lerp = 0.1, infinite = false, orientation = 'vertical', gestureOrientation = 'vertical', touchMultiplier = 1, wheelMultiplier = 1, autoResize = true, prevent, virtualScroll, __experimental__naiveDimensions = false, } = {}) {
328
285
  this.__isScrolling = false;
329
286
  this.__isStopped = false;
330
287
  this.__isLocked = false;
288
+ this.userData = {};
289
+ this.lastVelocity = 0;
290
+ this.velocity = 0;
331
291
  this.direction = 0;
332
292
  this.onPointerDown = (event) => {
333
293
  if (event.button === 1) {
334
294
  this.reset();
335
295
  }
336
296
  };
337
- this.onVirtualScroll = ({ deltaX, deltaY, event, }) => {
297
+ this.onVirtualScroll = (data) => {
298
+ if (typeof this.options.virtualScroll === 'function' &&
299
+ this.options.virtualScroll(data) === false)
300
+ return;
301
+ const { deltaX, deltaY, event } = data;
302
+ this.emitter.emit('virtual-scroll', { deltaX, deltaY, event });
338
303
  if (event.ctrlKey)
339
304
  return;
340
305
  const isTouch = event.type.includes('touch');
@@ -361,7 +326,7 @@
361
326
  if (!!composedPath.find((node) => {
362
327
  var _a, _b, _c, _d, _e;
363
328
  return node instanceof Element &&
364
- ((typeof prevent === 'function' ? prevent === null || prevent === void 0 ? void 0 : prevent(node) : prevent) ||
329
+ ((typeof prevent === 'function' && (prevent === null || prevent === void 0 ? void 0 : prevent(node))) ||
365
330
  ((_a = node.hasAttribute) === null || _a === void 0 ? void 0 : _a.call(node, 'data-lenis-prevent')) ||
366
331
  (isTouch && ((_b = node.hasAttribute) === null || _b === void 0 ? void 0 : _b.call(node, 'data-lenis-prevent-touch'))) ||
367
332
  (isWheel && ((_c = node.hasAttribute) === null || _c === void 0 ? void 0 : _c.call(node, 'data-lenis-prevent-wheel'))) ||
@@ -454,6 +419,7 @@
454
419
  wheelMultiplier,
455
420
  autoResize,
456
421
  prevent,
422
+ virtualScroll,
457
423
  __experimental__naiveDimensions,
458
424
  };
459
425
  this.animate = new Animate();