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