lenis 1.1.1 → 1.1.3-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/README.md +5 -8
- package/dist/animate.d.ts +20 -0
- package/dist/debounce.d.ts +1 -0
- package/dist/dimensions.d.ts +25 -0
- package/dist/element.d.ts +36 -0
- package/dist/emitter.d.ts +7 -0
- package/dist/id.d.ts +1 -0
- package/dist/lenis-react.mjs.map +1 -1
- package/dist/lenis-snap.d.ts +67 -16
- package/dist/lenis-snap.js +239 -279
- package/dist/lenis-snap.js.map +1 -1
- package/dist/lenis-snap.min.js +1 -1
- package/dist/lenis-snap.min.js.map +1 -1
- package/dist/lenis-snap.mjs +1 -1
- package/dist/lenis-snap.mjs.map +1 -1
- package/dist/lenis.d.ts +29 -33
- package/dist/lenis.js +60 -114
- package/dist/lenis.js.map +1 -1
- package/dist/lenis.min.js +1 -1
- package/dist/lenis.min.js.map +1 -1
- package/dist/lenis.mjs +1 -1
- package/dist/lenis.mjs.map +1 -1
- package/dist/maths.d.ts +5 -0
- package/dist/slide.d.ts +24 -0
- package/dist/uid.d.ts +2 -0
- package/dist/virtual-scroll.d.ts +31 -0
- package/package.json +96 -97
package/dist/lenis-snap.js
CHANGED
|
@@ -1,287 +1,247 @@
|
|
|
1
1
|
(function (global, factory) {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
2
|
+
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
|
|
3
|
+
typeof define === 'function' && define.amd ? define(factory) :
|
|
4
|
+
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.Lenis = factory());
|
|
5
5
|
})(this, (function () { 'use strict';
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
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
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
if (this.ignoreSticky) removeParentSticky(this.element);
|
|
121
|
-
if (this.ignoreTransform) {
|
|
122
|
-
top = offsetTop(this.element);
|
|
123
|
-
left = offsetLeft(this.element);
|
|
124
|
-
} else {
|
|
125
|
-
const rect = this.element.getBoundingClientRect();
|
|
126
|
-
top = rect.top + scrollTop(this.element);
|
|
127
|
-
left = rect.left + scrollLeft(this.element);
|
|
128
|
-
}
|
|
129
|
-
if (this.ignoreSticky) addParentSticky(this.element);
|
|
130
|
-
|
|
131
|
-
this.setRect({ top, left });
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
onResize = ([entry]) => {
|
|
135
|
-
const width = entry.borderBoxSize[0].inlineSize;
|
|
136
|
-
const height = entry.borderBoxSize[0].blockSize;
|
|
137
|
-
|
|
138
|
-
this.setRect({ width, height });
|
|
139
|
-
}
|
|
140
|
-
}
|
|
7
|
+
function removeParentSticky(element) {
|
|
8
|
+
const position = getComputedStyle(element).position;
|
|
9
|
+
const isSticky = position === 'sticky';
|
|
10
|
+
if (isSticky) {
|
|
11
|
+
element.style.setProperty('position', 'static');
|
|
12
|
+
element.dataset.sticky = 'true';
|
|
13
|
+
}
|
|
14
|
+
if (element.offsetParent) {
|
|
15
|
+
removeParentSticky(element.offsetParent);
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
function addParentSticky(element) {
|
|
19
|
+
var _a;
|
|
20
|
+
if (((_a = element === null || element === void 0 ? void 0 : element.dataset) === null || _a === void 0 ? void 0 : _a.sticky) === 'true') {
|
|
21
|
+
element.style.removeProperty('position');
|
|
22
|
+
delete element.dataset.sticky;
|
|
23
|
+
}
|
|
24
|
+
if (element.offsetParent) {
|
|
25
|
+
addParentSticky(element.offsetParent);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
function offsetTop(element, accumulator = 0) {
|
|
29
|
+
const top = accumulator + element.offsetTop;
|
|
30
|
+
if (element.offsetParent) {
|
|
31
|
+
return offsetTop(element.offsetParent, top);
|
|
32
|
+
}
|
|
33
|
+
return top;
|
|
34
|
+
}
|
|
35
|
+
function offsetLeft(element, accumulator = 0) {
|
|
36
|
+
const left = accumulator + element.offsetLeft;
|
|
37
|
+
if (element.offsetParent) {
|
|
38
|
+
return offsetLeft(element.offsetParent, left);
|
|
39
|
+
}
|
|
40
|
+
return left;
|
|
41
|
+
}
|
|
42
|
+
function scrollTop(element, accumulator = 0) {
|
|
43
|
+
const top = accumulator + element.scrollTop;
|
|
44
|
+
if (element.offsetParent) {
|
|
45
|
+
return scrollTop(element.offsetParent, top);
|
|
46
|
+
}
|
|
47
|
+
return top + window.scrollY;
|
|
48
|
+
}
|
|
49
|
+
function scrollLeft(element, accumulator = 0) {
|
|
50
|
+
const left = accumulator + element.scrollLeft;
|
|
51
|
+
if (element.offsetParent) {
|
|
52
|
+
return scrollLeft(element.offsetParent, left);
|
|
53
|
+
}
|
|
54
|
+
return left + window.scrollX;
|
|
55
|
+
}
|
|
56
|
+
class SnapElement {
|
|
57
|
+
constructor(element, { align = ['start'], ignoreSticky = true, ignoreTransform = false, } = {}) {
|
|
58
|
+
this.rect = {};
|
|
59
|
+
this.onWrapperResize = () => {
|
|
60
|
+
let top, left;
|
|
61
|
+
if (this.options.ignoreSticky)
|
|
62
|
+
removeParentSticky(this.element);
|
|
63
|
+
if (this.options.ignoreTransform) {
|
|
64
|
+
top = offsetTop(this.element);
|
|
65
|
+
left = offsetLeft(this.element);
|
|
66
|
+
}
|
|
67
|
+
else {
|
|
68
|
+
const rect = this.element.getBoundingClientRect();
|
|
69
|
+
top = rect.top + scrollTop(this.element);
|
|
70
|
+
left = rect.left + scrollLeft(this.element);
|
|
71
|
+
}
|
|
72
|
+
if (this.options.ignoreSticky)
|
|
73
|
+
addParentSticky(this.element);
|
|
74
|
+
this.setRect({ top, left });
|
|
75
|
+
};
|
|
76
|
+
this.onResize = ([entry]) => {
|
|
77
|
+
const width = entry.borderBoxSize[0].inlineSize;
|
|
78
|
+
const height = entry.borderBoxSize[0].blockSize;
|
|
79
|
+
this.setRect({ width, height });
|
|
80
|
+
};
|
|
81
|
+
this.element = element;
|
|
82
|
+
this.options = { align, ignoreSticky, ignoreTransform };
|
|
83
|
+
this.align = [align].flat();
|
|
84
|
+
this.wrapperResizeObserver = new ResizeObserver(this.onWrapperResize);
|
|
85
|
+
this.wrapperResizeObserver.observe(document.body);
|
|
86
|
+
this.onWrapperResize();
|
|
87
|
+
this.resizeObserver = new ResizeObserver(this.onResize);
|
|
88
|
+
this.resizeObserver.observe(this.element);
|
|
89
|
+
this.setRect({
|
|
90
|
+
width: this.element.offsetWidth,
|
|
91
|
+
height: this.element.offsetHeight,
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
destroy() {
|
|
95
|
+
this.wrapperResizeObserver.disconnect();
|
|
96
|
+
this.resizeObserver.disconnect();
|
|
97
|
+
}
|
|
98
|
+
setRect({ top, left, width, height, element, } = {}) {
|
|
99
|
+
top = top !== null && top !== void 0 ? top : this.rect.top;
|
|
100
|
+
left = left !== null && left !== void 0 ? left : this.rect.left;
|
|
101
|
+
width = width !== null && width !== void 0 ? width : this.rect.width;
|
|
102
|
+
height = height !== null && height !== void 0 ? height : this.rect.height;
|
|
103
|
+
element = element !== null && element !== void 0 ? element : this.rect.element;
|
|
104
|
+
if (top === this.rect.top &&
|
|
105
|
+
left === this.rect.left &&
|
|
106
|
+
width === this.rect.width &&
|
|
107
|
+
height === this.rect.height &&
|
|
108
|
+
element === this.rect.element)
|
|
109
|
+
return;
|
|
110
|
+
this.rect.top = top;
|
|
111
|
+
this.rect.y = top;
|
|
112
|
+
this.rect.width = width;
|
|
113
|
+
this.rect.height = height;
|
|
114
|
+
this.rect.left = left;
|
|
115
|
+
this.rect.x = left;
|
|
116
|
+
this.rect.bottom = top + height;
|
|
117
|
+
this.rect.right = left + width;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
141
120
|
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
// - fix touch scroll, do not snap when not released
|
|
147
|
-
class Snap {
|
|
148
|
-
constructor(lenis, { type = 'mandatory', lerp, easing, duration, velocityThreshold = 1, onSnapStart, onSnapComplete, } = {}) {
|
|
149
|
-
this.onWindowResize = () => {
|
|
150
|
-
this.viewport.width = window.innerWidth;
|
|
151
|
-
this.viewport.height = window.innerHeight;
|
|
152
|
-
};
|
|
153
|
-
this.onScroll = ({ scroll, limit, lastVelocity, velocity, isScrolling, isTouching, userData, }) => {
|
|
154
|
-
if (this.isStopped)
|
|
155
|
-
return;
|
|
156
|
-
// console.log(scroll, velocity, type)
|
|
157
|
-
// return
|
|
158
|
-
const isDecelerating = Math.abs(lastVelocity) > Math.abs(velocity);
|
|
159
|
-
const isTurningBack = Math.sign(lastVelocity) !== Math.sign(velocity) && velocity !== 0;
|
|
160
|
-
// console.log({ lastVelocity, velocity, isTurningBack, isDecelerating })
|
|
161
|
-
// console.log('onScroll')
|
|
162
|
-
if (Math.abs(velocity) < this.velocityThreshold &&
|
|
163
|
-
// !isTouching &&
|
|
164
|
-
isDecelerating &&
|
|
165
|
-
!isTurningBack &&
|
|
166
|
-
(userData === null || userData === void 0 ? void 0 : userData.initiator) !== 'snap') {
|
|
167
|
-
scroll = Math.ceil(scroll);
|
|
168
|
-
let snaps = [0, ...this.snaps.values(), limit];
|
|
169
|
-
this.elements.forEach(({ rect, align }) => {
|
|
170
|
-
let snap;
|
|
171
|
-
align.forEach((align) => {
|
|
172
|
-
if (align === 'start') {
|
|
173
|
-
snap = rect.top;
|
|
174
|
-
}
|
|
175
|
-
else if (align === 'center') {
|
|
176
|
-
snap = rect.top + rect.height / 2 - this.viewport.height / 2;
|
|
177
|
-
}
|
|
178
|
-
else if (align === 'end') {
|
|
179
|
-
snap = rect.top + rect.height - this.viewport.height;
|
|
180
|
-
}
|
|
181
|
-
if (snap !== undefined) {
|
|
182
|
-
snaps.push(Math.ceil(snap));
|
|
183
|
-
}
|
|
184
|
-
});
|
|
185
|
-
});
|
|
186
|
-
snaps = snaps.sort((a, b) => Math.abs(a) - Math.abs(b));
|
|
187
|
-
let prevSnap = snaps.findLast((snap) => snap <= scroll);
|
|
188
|
-
if (prevSnap === undefined)
|
|
189
|
-
prevSnap = snaps[0];
|
|
190
|
-
const distanceToPrevSnap = Math.abs(scroll - prevSnap);
|
|
191
|
-
let nextSnap = snaps.find((snap) => snap >= scroll);
|
|
192
|
-
if (nextSnap === undefined)
|
|
193
|
-
nextSnap = snaps[snaps.length - 1];
|
|
194
|
-
const distanceToNextSnap = Math.abs(scroll - nextSnap);
|
|
195
|
-
const snap = distanceToPrevSnap < distanceToNextSnap ? prevSnap : nextSnap;
|
|
196
|
-
const distance = Math.abs(scroll - snap);
|
|
197
|
-
if (this.type === 'mandatory' ||
|
|
198
|
-
(this.type === 'proximity' && distance <= this.viewport.height)) {
|
|
199
|
-
// this.__isScrolling = true
|
|
200
|
-
// this.onSnapStart?.(snap)
|
|
201
|
-
// console.log('scroll to')
|
|
202
|
-
this.lenis.scrollTo(snap, {
|
|
203
|
-
lerp: this.options.lerp,
|
|
204
|
-
easing: this.options.easing,
|
|
205
|
-
duration: this.options.duration,
|
|
206
|
-
userData: { initiator: 'snap' },
|
|
207
|
-
onStart: () => {
|
|
208
|
-
var _a;
|
|
209
|
-
(_a = this.onSnapStart) === null || _a === void 0 ? void 0 : _a.call(this, snap);
|
|
210
|
-
},
|
|
211
|
-
onComplete: () => {
|
|
212
|
-
var _a;
|
|
213
|
-
(_a = this.onSnapComplete) === null || _a === void 0 ? void 0 : _a.call(this, snap);
|
|
214
|
-
},
|
|
215
|
-
});
|
|
216
|
-
}
|
|
217
|
-
// console.timeEnd('scroll')
|
|
218
|
-
}
|
|
219
|
-
};
|
|
220
|
-
this.lenis = lenis;
|
|
221
|
-
this.options = {
|
|
222
|
-
type,
|
|
223
|
-
lerp,
|
|
224
|
-
easing,
|
|
225
|
-
duration,
|
|
226
|
-
velocityThreshold,
|
|
227
|
-
};
|
|
228
|
-
this.type = type;
|
|
229
|
-
this.elements = new Map();
|
|
230
|
-
this.snaps = new Map();
|
|
231
|
-
this.velocityThreshold = velocityThreshold;
|
|
232
|
-
this.onSnapStart = onSnapStart;
|
|
233
|
-
this.onSnapComplete = onSnapComplete;
|
|
234
|
-
this.viewport = {
|
|
235
|
-
width: window.innerWidth,
|
|
236
|
-
height: window.innerHeight,
|
|
237
|
-
};
|
|
238
|
-
this.onWindowResize();
|
|
239
|
-
window.addEventListener('resize', this.onWindowResize);
|
|
240
|
-
this.lenis.on('scroll', this.onScroll);
|
|
241
|
-
}
|
|
242
|
-
// debug() {
|
|
243
|
-
// const element = document.createElement('div')
|
|
244
|
-
// element.style.cssText = `
|
|
245
|
-
// position: fixed;
|
|
246
|
-
// background: red;
|
|
247
|
-
// border-bottom: 1px solid red;
|
|
248
|
-
// left: 0;
|
|
249
|
-
// right: 0;
|
|
250
|
-
// top: 0;
|
|
251
|
-
// z-index: 9999;
|
|
252
|
-
// `
|
|
253
|
-
// document.body.appendChild(element)
|
|
254
|
-
// }
|
|
255
|
-
destroy() {
|
|
256
|
-
this.lenis.off('scroll', this.onScroll);
|
|
257
|
-
window.removeEventListener('resize', this.onWindowResize);
|
|
258
|
-
this.elements.forEach((slide) => slide.destroy());
|
|
259
|
-
}
|
|
260
|
-
start() {
|
|
261
|
-
this.isStopped = false;
|
|
262
|
-
}
|
|
263
|
-
stop() {
|
|
264
|
-
this.isStopped = true;
|
|
265
|
-
}
|
|
266
|
-
add(value) {
|
|
267
|
-
const id = crypto.randomUUID();
|
|
268
|
-
this.snaps.set(id, value);
|
|
269
|
-
return () => this.remove(id);
|
|
270
|
-
}
|
|
271
|
-
remove(id) {
|
|
272
|
-
this.snaps.delete(id);
|
|
273
|
-
}
|
|
274
|
-
addElement(element, options = {}) {
|
|
275
|
-
const id = crypto.randomUUID();
|
|
276
|
-
this.elements.set(id, new Slide(element, options));
|
|
277
|
-
return () => this.removeElement(id);
|
|
278
|
-
}
|
|
279
|
-
removeElement(id) {
|
|
280
|
-
this.elements.delete(id);
|
|
281
|
-
}
|
|
282
|
-
}
|
|
121
|
+
let index = 0;
|
|
122
|
+
function uid() {
|
|
123
|
+
return index++;
|
|
124
|
+
}
|
|
283
125
|
|
|
284
|
-
|
|
126
|
+
class Snap {
|
|
127
|
+
constructor(lenis, { type = 'mandatory', lerp, easing, duration, velocityThreshold = 1, onSnapStart, onSnapComplete, } = {}) {
|
|
128
|
+
this.isStopped = false;
|
|
129
|
+
this.onWindowResize = () => {
|
|
130
|
+
this.viewport.width = window.innerWidth;
|
|
131
|
+
this.viewport.height = window.innerHeight;
|
|
132
|
+
};
|
|
133
|
+
this.onScroll = ({ scroll, limit, lastVelocity, velocity, isScrolling, userData, isHorizontal, }) => {
|
|
134
|
+
if (this.isStopped)
|
|
135
|
+
return;
|
|
136
|
+
const isDecelerating = Math.abs(lastVelocity) > Math.abs(velocity);
|
|
137
|
+
const isTurningBack = Math.sign(lastVelocity) !== Math.sign(velocity) && velocity !== 0;
|
|
138
|
+
if (Math.abs(velocity) < this.options.velocityThreshold &&
|
|
139
|
+
isDecelerating &&
|
|
140
|
+
!isTurningBack &&
|
|
141
|
+
(userData === null || userData === void 0 ? void 0 : userData.initiator) !== 'snap') {
|
|
142
|
+
scroll = Math.ceil(scroll);
|
|
143
|
+
let snaps = [0, ...this.snaps.values(), limit];
|
|
144
|
+
this.elements.forEach(({ rect, align }) => {
|
|
145
|
+
let snap;
|
|
146
|
+
align.forEach((align) => {
|
|
147
|
+
if (align === 'start') {
|
|
148
|
+
snap = rect.top;
|
|
149
|
+
}
|
|
150
|
+
else if (align === 'center') {
|
|
151
|
+
snap = isHorizontal
|
|
152
|
+
? rect.left + rect.width / 2 - this.viewport.width / 2
|
|
153
|
+
: rect.top + rect.height / 2 - this.viewport.height / 2;
|
|
154
|
+
}
|
|
155
|
+
else if (align === 'end') {
|
|
156
|
+
snap = isHorizontal
|
|
157
|
+
? rect.left + rect.width - this.viewport.width
|
|
158
|
+
: rect.top + rect.height - this.viewport.height;
|
|
159
|
+
}
|
|
160
|
+
if (snap !== undefined) {
|
|
161
|
+
snaps.push(Math.ceil(snap));
|
|
162
|
+
}
|
|
163
|
+
});
|
|
164
|
+
});
|
|
165
|
+
snaps = snaps.sort((a, b) => Math.abs(a) - Math.abs(b));
|
|
166
|
+
let prevSnap = snaps.findLast((snap) => snap <= scroll);
|
|
167
|
+
if (prevSnap === undefined)
|
|
168
|
+
prevSnap = snaps[0];
|
|
169
|
+
const distanceToPrevSnap = Math.abs(scroll - prevSnap);
|
|
170
|
+
let nextSnap = snaps.find((snap) => snap >= scroll);
|
|
171
|
+
if (nextSnap === undefined)
|
|
172
|
+
nextSnap = snaps[snaps.length - 1];
|
|
173
|
+
const distanceToNextSnap = Math.abs(scroll - nextSnap);
|
|
174
|
+
const snap = distanceToPrevSnap < distanceToNextSnap ? prevSnap : nextSnap;
|
|
175
|
+
const distance = Math.abs(scroll - snap);
|
|
176
|
+
if (this.options.type === 'mandatory' ||
|
|
177
|
+
(this.options.type === 'proximity' && distance <= this.viewport.height)) {
|
|
178
|
+
this.lenis.scrollTo(snap, {
|
|
179
|
+
lerp: this.options.lerp,
|
|
180
|
+
easing: this.options.easing,
|
|
181
|
+
duration: this.options.duration,
|
|
182
|
+
userData: { initiator: 'snap' },
|
|
183
|
+
onStart: () => {
|
|
184
|
+
var _a, _b;
|
|
185
|
+
(_b = (_a = this.options).onSnapStart) === null || _b === void 0 ? void 0 : _b.call(_a, snap);
|
|
186
|
+
},
|
|
187
|
+
onComplete: () => {
|
|
188
|
+
var _a, _b;
|
|
189
|
+
(_b = (_a = this.options).onSnapComplete) === null || _b === void 0 ? void 0 : _b.call(_a, snap);
|
|
190
|
+
},
|
|
191
|
+
});
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
};
|
|
195
|
+
this.lenis = lenis;
|
|
196
|
+
this.options = {
|
|
197
|
+
type,
|
|
198
|
+
lerp,
|
|
199
|
+
easing,
|
|
200
|
+
duration,
|
|
201
|
+
velocityThreshold,
|
|
202
|
+
onSnapStart,
|
|
203
|
+
onSnapComplete,
|
|
204
|
+
};
|
|
205
|
+
this.elements = new Map();
|
|
206
|
+
this.snaps = new Map();
|
|
207
|
+
this.viewport = {
|
|
208
|
+
width: window.innerWidth,
|
|
209
|
+
height: window.innerHeight,
|
|
210
|
+
};
|
|
211
|
+
this.onWindowResize();
|
|
212
|
+
window.addEventListener('resize', this.onWindowResize);
|
|
213
|
+
this.lenis.on('scroll', this.onScroll);
|
|
214
|
+
}
|
|
215
|
+
destroy() {
|
|
216
|
+
this.lenis.off('scroll', this.onScroll);
|
|
217
|
+
window.removeEventListener('resize', this.onWindowResize);
|
|
218
|
+
this.elements.forEach((element) => element.destroy());
|
|
219
|
+
}
|
|
220
|
+
start() {
|
|
221
|
+
this.isStopped = false;
|
|
222
|
+
}
|
|
223
|
+
stop() {
|
|
224
|
+
this.isStopped = true;
|
|
225
|
+
}
|
|
226
|
+
add(value) {
|
|
227
|
+
const id = uid();
|
|
228
|
+
this.snaps.set(id, value);
|
|
229
|
+
return () => this.remove(id);
|
|
230
|
+
}
|
|
231
|
+
remove(id) {
|
|
232
|
+
this.snaps.delete(id);
|
|
233
|
+
}
|
|
234
|
+
addElement(element, options = {}) {
|
|
235
|
+
const id = uid();
|
|
236
|
+
this.elements.set(id, new SnapElement(element, options));
|
|
237
|
+
return () => this.removeElement(id);
|
|
238
|
+
}
|
|
239
|
+
removeElement(id) {
|
|
240
|
+
this.elements.delete(id);
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
return Snap;
|
|
285
245
|
|
|
286
246
|
}));
|
|
287
247
|
//# sourceMappingURL=lenis-snap.js.map
|
package/dist/lenis-snap.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lenis-snap.js","sources":["../src/slide.js","../src/index.ts"],"sourcesContent":["function removeParentSticky(element) {\r\n const position = getComputedStyle(element).position\r\n\r\n const isSticky = position === 'sticky'\r\n\r\n if (isSticky) {\r\n element.style.setProperty('position', 'static')\r\n element.dataset.sticky = 'true'\r\n }\r\n\r\n if (element.offsetParent) {\r\n removeParentSticky(element.offsetParent)\r\n }\r\n}\r\n\r\nfunction addParentSticky(element) {\r\n if (element?.dataset?.sticky === 'true') {\r\n element.style.removeProperty('position')\r\n delete element.dataset.sticky\r\n }\r\n\r\n if (element.offsetParent) {\r\n addParentSticky(element.offsetParent)\r\n }\r\n}\r\n\r\nfunction offsetTop(element, accumulator = 0) {\r\n const top = accumulator + element.offsetTop\r\n if (element.offsetParent) {\r\n return offsetTop(element.offsetParent, top)\r\n }\r\n return top\r\n}\r\n\r\nfunction offsetLeft(element, accumulator = 0) {\r\n const left = accumulator + element.offsetLeft\r\n if (element.offsetParent) {\r\n return offsetLeft(element.offsetParent, left)\r\n }\r\n return left\r\n}\r\n\r\nfunction scrollTop(element, accumulator = 0) {\r\n const top = accumulator + element.scrollTop\r\n if (element.offsetParent) {\r\n return scrollTop(element.offsetParent, top)\r\n }\r\n return top + window.scrollY\r\n}\r\n\r\nfunction scrollLeft(element, accumulator = 0) {\r\n const left = accumulator + element.scrollLeft\r\n if (element.offsetParent) {\r\n return scrollLeft(element.offsetParent, left)\r\n }\r\n return left + window.scrollX\r\n}\r\n\r\nexport default class Slide {\r\n constructor(\r\n element,\r\n { align = ['start'], ignoreSticky = true, ignoreTransform = false } = {}\r\n ) {\r\n this.element = element\r\n\r\n this.ignoreSticky = ignoreSticky\r\n this.ignoreTransform = ignoreTransform\r\n\r\n this.align = [align].flat()\r\n\r\n this.rect = {}\r\n\r\n this.wrapperResizeObserver = new ResizeObserver(this.onWrapperResize)\r\n this.wrapperResizeObserver.observe(document.body)\r\n\r\n this.resizeObserver = new ResizeObserver(this.onResize)\r\n this.resizeObserver.observe(this.element)\r\n }\r\n\r\n destroy() {\r\n this.wrapperResizeObserver.disconnect()\r\n this.resizeObserver.disconnect()\r\n }\r\n\r\n setRect({ top, left, width, height, element }) {\r\n top = top ?? this.rect.top\r\n left = left ?? this.rect.left\r\n width = width ?? this.rect.width\r\n height = height ?? this.rect.height\r\n element = element ?? this.rect.element\r\n\r\n if (\r\n top === this.rect.top &&\r\n left === this.rect.left &&\r\n width === this.rect.width &&\r\n height === this.rect.height &&\r\n element === this.rect.element\r\n )\r\n return\r\n\r\n this.rect.top = top\r\n this.rect.y = top\r\n this.rect.width = width\r\n this.rect.height = height\r\n this.rect.left = left\r\n this.rect.x = left\r\n this.rect.bottom = top + height\r\n this.rect.right = left + width\r\n }\r\n\r\n onWrapperResize = () => {\r\n let top, left\r\n\r\n if (this.ignoreSticky) removeParentSticky(this.element)\r\n if (this.ignoreTransform) {\r\n top = offsetTop(this.element)\r\n left = offsetLeft(this.element)\r\n } else {\r\n const rect = this.element.getBoundingClientRect()\r\n top = rect.top + scrollTop(this.element)\r\n left = rect.left + scrollLeft(this.element)\r\n }\r\n if (this.ignoreSticky) addParentSticky(this.element)\r\n\r\n this.setRect({ top, left })\r\n }\r\n\r\n onResize = ([entry]) => {\r\n const width = entry.borderBoxSize[0].inlineSize\r\n const height = entry.borderBoxSize[0].blockSize\r\n\r\n this.setRect({ width, height })\r\n }\r\n}\r\n","import Slide from './slide'\r\n\r\n// TODO:\r\n// - horizontal\r\n// - fix trackpad snapping too soon due to velocity (fuck Apple)\r\n// - fix wheel scrolling after limits (see console scroll to)\r\n// - fix touch scroll, do not snap when not released\r\n\r\nexport default class Snap {\r\n constructor(\r\n lenis,\r\n {\r\n type = 'mandatory',\r\n lerp,\r\n easing,\r\n duration,\r\n velocityThreshold = 1,\r\n onSnapStart,\r\n onSnapComplete,\r\n } = {}\r\n ) {\r\n this.lenis = lenis\r\n\r\n this.options = {\r\n type,\r\n lerp,\r\n easing,\r\n duration,\r\n velocityThreshold,\r\n }\r\n\r\n this.type = type\r\n this.elements = new Map()\r\n this.snaps = new Map()\r\n\r\n this.velocityThreshold = velocityThreshold\r\n this.onSnapStart = onSnapStart\r\n this.onSnapComplete = onSnapComplete\r\n\r\n this.viewport = {\r\n width: window.innerWidth,\r\n height: window.innerHeight,\r\n }\r\n this.onWindowResize()\r\n window.addEventListener('resize', this.onWindowResize)\r\n\r\n this.lenis.on('scroll', this.onScroll)\r\n }\r\n\r\n // debug() {\r\n // const element = document.createElement('div')\r\n // element.style.cssText = `\r\n // position: fixed;\r\n // background: red;\r\n // border-bottom: 1px solid red;\r\n // left: 0;\r\n // right: 0;\r\n // top: 0;\r\n // z-index: 9999;\r\n // `\r\n // document.body.appendChild(element)\r\n // }\r\n\r\n destroy() {\r\n this.lenis.off('scroll', this.onScroll)\r\n window.removeEventListener('resize', this.onWindowResize)\r\n this.elements.forEach((slide) => slide.destroy())\r\n }\r\n\r\n start() {\r\n this.isStopped = false\r\n }\r\n\r\n stop() {\r\n this.isStopped = true\r\n }\r\n\r\n add(value) {\r\n const id = crypto.randomUUID()\r\n\r\n this.snaps.set(id, value)\r\n\r\n return () => this.remove(id)\r\n }\r\n\r\n remove(id) {\r\n this.snaps.delete(id)\r\n }\r\n\r\n addElement(element, options = {}) {\r\n const id = crypto.randomUUID()\r\n\r\n this.elements.set(id, new Slide(element, options))\r\n\r\n return () => this.removeElement(id)\r\n }\r\n\r\n removeElement(id) {\r\n this.elements.delete(id)\r\n }\r\n\r\n onWindowResize = () => {\r\n this.viewport.width = window.innerWidth\r\n this.viewport.height = window.innerHeight\r\n }\r\n\r\n onScroll = ({\r\n scroll,\r\n limit,\r\n lastVelocity,\r\n velocity,\r\n isScrolling,\r\n isTouching,\r\n userData,\r\n }) => {\r\n if (this.isStopped) return\r\n // console.log(scroll, velocity, type)\r\n\r\n // return\r\n const isDecelerating = Math.abs(lastVelocity) > Math.abs(velocity)\r\n const isTurningBack =\r\n Math.sign(lastVelocity) !== Math.sign(velocity) && velocity !== 0\r\n\r\n // console.log({ lastVelocity, velocity, isTurningBack, isDecelerating })\r\n\r\n // console.log('onScroll')\r\n\r\n if (\r\n Math.abs(velocity) < this.velocityThreshold &&\r\n // !isTouching &&\r\n isDecelerating &&\r\n !isTurningBack &&\r\n userData?.initiator !== 'snap'\r\n ) {\r\n scroll = Math.ceil(scroll)\r\n\r\n let snaps = [0, ...this.snaps.values(), limit]\r\n\r\n this.elements.forEach(({ rect, align }) => {\r\n let snap\r\n\r\n align.forEach((align) => {\r\n if (align === 'start') {\r\n snap = rect.top\r\n } else if (align === 'center') {\r\n snap = rect.top + rect.height / 2 - this.viewport.height / 2\r\n } else if (align === 'end') {\r\n snap = rect.top + rect.height - this.viewport.height\r\n }\r\n\r\n if (snap !== undefined) {\r\n snaps.push(Math.ceil(snap))\r\n }\r\n })\r\n })\r\n\r\n snaps = snaps.sort((a, b) => Math.abs(a) - Math.abs(b))\r\n\r\n let prevSnap = snaps.findLast((snap) => snap <= scroll)\r\n if (prevSnap === undefined) prevSnap = snaps[0]\r\n const distanceToPrevSnap = Math.abs(scroll - prevSnap)\r\n\r\n let nextSnap = snaps.find((snap) => snap >= scroll)\r\n if (nextSnap === undefined) nextSnap = snaps[snaps.length - 1]\r\n const distanceToNextSnap = Math.abs(scroll - nextSnap)\r\n\r\n const snap = distanceToPrevSnap < distanceToNextSnap ? prevSnap : nextSnap\r\n\r\n const distance = Math.abs(scroll - snap)\r\n\r\n if (\r\n this.type === 'mandatory' ||\r\n (this.type === 'proximity' && distance <= this.viewport.height)\r\n ) {\r\n // this.__isScrolling = true\r\n // this.onSnapStart?.(snap)\r\n\r\n // console.log('scroll to')\r\n\r\n this.lenis.scrollTo(snap, {\r\n lerp: this.options.lerp,\r\n easing: this.options.easing,\r\n duration: this.options.duration,\r\n userData: { initiator: 'snap' },\r\n onStart: () => {\r\n this.onSnapStart?.(snap)\r\n },\r\n onComplete: () => {\r\n this.onSnapComplete?.(snap)\r\n },\r\n })\r\n }\r\n\r\n // console.timeEnd('scroll')\r\n }\r\n }\r\n}\r\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"lenis-snap.js","sources":["../src/element.ts","../src/uid.ts","../src/index.ts"],"sourcesContent":["function removeParentSticky(element: HTMLElement) {\r\n const position = getComputedStyle(element).position\r\n\r\n const isSticky = position === 'sticky'\r\n\r\n if (isSticky) {\r\n element.style.setProperty('position', 'static')\r\n element.dataset.sticky = 'true'\r\n }\r\n\r\n if (element.offsetParent) {\r\n removeParentSticky(element.offsetParent as HTMLElement)\r\n }\r\n}\r\n\r\nfunction addParentSticky(element: HTMLElement) {\r\n if (element?.dataset?.sticky === 'true') {\r\n element.style.removeProperty('position')\r\n delete element.dataset.sticky\r\n }\r\n\r\n if (element.offsetParent) {\r\n addParentSticky(element.offsetParent as HTMLElement)\r\n }\r\n}\r\n\r\nfunction offsetTop(element: HTMLElement, accumulator = 0) {\r\n const top = accumulator + element.offsetTop\r\n if (element.offsetParent) {\r\n return offsetTop(element.offsetParent as HTMLElement, top)\r\n }\r\n return top\r\n}\r\n\r\nfunction offsetLeft(element: HTMLElement, accumulator = 0) {\r\n const left = accumulator + element.offsetLeft\r\n if (element.offsetParent) {\r\n return offsetLeft(element.offsetParent as HTMLElement, left)\r\n }\r\n return left\r\n}\r\n\r\nfunction scrollTop(element: HTMLElement, accumulator = 0) {\r\n const top = accumulator + element.scrollTop\r\n if (element.offsetParent) {\r\n return scrollTop(element.offsetParent as HTMLElement, top)\r\n }\r\n return top + window.scrollY\r\n}\r\n\r\nfunction scrollLeft(element: HTMLElement, accumulator = 0) {\r\n const left = accumulator + element.scrollLeft\r\n if (element.offsetParent) {\r\n return scrollLeft(element.offsetParent as HTMLElement, left)\r\n }\r\n return left + window.scrollX\r\n}\r\n\r\nexport type SnapElementOptions = {\r\n align?: string[]\r\n ignoreSticky?: boolean\r\n ignoreTransform?: boolean\r\n}\r\n\r\ntype Rect = {\r\n top: number\r\n left: number\r\n width: number\r\n height: number\r\n x: number\r\n y: number\r\n bottom: number\r\n right: number\r\n element: HTMLElement\r\n}\r\n\r\nexport class SnapElement {\r\n element: HTMLElement\r\n options: SnapElementOptions\r\n align: string[]\r\n // @ts-ignore\r\n rect: Rect = {}\r\n wrapperResizeObserver: ResizeObserver\r\n resizeObserver: ResizeObserver\r\n\r\n constructor(\r\n element: HTMLElement,\r\n {\r\n align = ['start'],\r\n ignoreSticky = true,\r\n ignoreTransform = false,\r\n }: SnapElementOptions = {}\r\n ) {\r\n this.element = element\r\n\r\n this.options = { align, ignoreSticky, ignoreTransform }\r\n\r\n // this.ignoreSticky = ignoreSticky\r\n // this.ignoreTransform = ignoreTransform\r\n\r\n this.align = [align].flat()\r\n\r\n // TODO: assing rect immediately\r\n\r\n this.wrapperResizeObserver = new ResizeObserver(this.onWrapperResize)\r\n this.wrapperResizeObserver.observe(document.body)\r\n this.onWrapperResize()\r\n\r\n this.resizeObserver = new ResizeObserver(this.onResize)\r\n this.resizeObserver.observe(this.element)\r\n this.setRect({\r\n width: this.element.offsetWidth,\r\n height: this.element.offsetHeight,\r\n })\r\n }\r\n\r\n destroy() {\r\n this.wrapperResizeObserver.disconnect()\r\n this.resizeObserver.disconnect()\r\n }\r\n\r\n setRect({\r\n top,\r\n left,\r\n width,\r\n height,\r\n element,\r\n }: {\r\n top?: number\r\n left?: number\r\n width?: number\r\n height?: number\r\n element?: HTMLElement\r\n } = {}) {\r\n top = top ?? this.rect.top\r\n left = left ?? this.rect.left\r\n width = width ?? this.rect.width\r\n height = height ?? this.rect.height\r\n element = element ?? this.rect.element\r\n\r\n if (\r\n top === this.rect.top &&\r\n left === this.rect.left &&\r\n width === this.rect.width &&\r\n height === this.rect.height &&\r\n element === this.rect.element\r\n )\r\n return\r\n\r\n this.rect.top = top\r\n this.rect.y = top\r\n this.rect.width = width\r\n this.rect.height = height\r\n this.rect.left = left\r\n this.rect.x = left\r\n this.rect.bottom = top + height\r\n this.rect.right = left + width\r\n }\r\n\r\n onWrapperResize = () => {\r\n let top, left\r\n\r\n if (this.options.ignoreSticky) removeParentSticky(this.element)\r\n if (this.options.ignoreTransform) {\r\n top = offsetTop(this.element)\r\n left = offsetLeft(this.element)\r\n } else {\r\n const rect = this.element.getBoundingClientRect()\r\n top = rect.top + scrollTop(this.element)\r\n left = rect.left + scrollLeft(this.element)\r\n }\r\n if (this.options.ignoreSticky) addParentSticky(this.element)\r\n\r\n this.setRect({ top, left })\r\n }\r\n\r\n onResize = ([entry]: ResizeObserverEntry[]) => {\r\n const width = entry.borderBoxSize[0].inlineSize\r\n const height = entry.borderBoxSize[0].blockSize\r\n\r\n this.setRect({ width, height })\r\n }\r\n}\r\n","let index = 0\r\n\r\nexport type UID = number\r\n\r\nexport function uid(): UID {\r\n return index++\r\n}\r\n","import Lenis from 'lenis'\r\nimport { SnapElement, SnapElementOptions } from './element'\r\nimport { UID, uid } from './uid'\r\n\r\n// TODO:\r\n// - horizontal\r\n// - fix trackpad snapping too soon due to velocity (fuck Apple)\r\n// - fix wheel scrolling after limits (see console scroll to)\r\n// - fix touch scroll, do not snap when not released\r\n// - arrow, spacebar\r\n\r\ntype Viewport = {\r\n width: number\r\n height: number\r\n}\r\n\r\nexport type SnapOptions = {\r\n type?: 'mandatory' | 'proximity'\r\n lerp?: number\r\n easing?: (t: number) => number\r\n duration?: number\r\n velocityThreshold?: number\r\n onSnapStart?: (t: number) => number\r\n onSnapComplete?: (t: number) => number\r\n}\r\n\r\nexport default class Snap {\r\n lenis: Lenis\r\n options: SnapOptions\r\n elements: Map<UID, SnapElement>\r\n snaps: Map<UID, number>\r\n viewport: Viewport\r\n isStopped: Boolean = false\r\n\r\n constructor(\r\n lenis: Lenis,\r\n {\r\n type = 'mandatory',\r\n lerp,\r\n easing,\r\n duration,\r\n velocityThreshold = 1,\r\n onSnapStart,\r\n onSnapComplete,\r\n }: SnapOptions = {}\r\n ) {\r\n this.lenis = lenis\r\n\r\n this.options = {\r\n type,\r\n lerp,\r\n easing,\r\n duration,\r\n velocityThreshold,\r\n onSnapStart,\r\n onSnapComplete,\r\n }\r\n\r\n this.elements = new Map()\r\n this.snaps = new Map()\r\n\r\n this.viewport = {\r\n width: window.innerWidth,\r\n height: window.innerHeight,\r\n }\r\n this.onWindowResize()\r\n window.addEventListener('resize', this.onWindowResize)\r\n\r\n this.lenis.on('scroll', this.onScroll)\r\n }\r\n\r\n // debug() {\r\n // const element = document.createElement('div')\r\n // element.style.cssText = `\r\n // position: fixed;\r\n // background: red;\r\n // border-bottom: 1px solid red;\r\n // left: 0;\r\n // right: 0;\r\n // top: 0;\r\n // z-index: 9999;\r\n // `\r\n // document.body.appendChild(element)\r\n // }\r\n\r\n destroy() {\r\n this.lenis.off('scroll', this.onScroll)\r\n window.removeEventListener('resize', this.onWindowResize)\r\n this.elements.forEach((element) => element.destroy())\r\n }\r\n\r\n start() {\r\n this.isStopped = false\r\n }\r\n\r\n stop() {\r\n this.isStopped = true\r\n }\r\n\r\n add(value: number) {\r\n const id = uid()\r\n\r\n this.snaps.set(id, value)\r\n\r\n return () => this.remove(id)\r\n }\r\n\r\n remove(id: UID) {\r\n this.snaps.delete(id)\r\n }\r\n\r\n addElement(element: HTMLElement, options = {} as SnapElementOptions) {\r\n const id = uid()\r\n\r\n this.elements.set(id, new SnapElement(element, options))\r\n\r\n return () => this.removeElement(id)\r\n }\r\n\r\n removeElement(id: UID) {\r\n this.elements.delete(id)\r\n }\r\n\r\n onWindowResize = () => {\r\n this.viewport.width = window.innerWidth\r\n this.viewport.height = window.innerHeight\r\n }\r\n\r\n onScroll = ({\r\n scroll,\r\n limit,\r\n lastVelocity,\r\n velocity,\r\n isScrolling,\r\n userData,\r\n isHorizontal,\r\n }) => {\r\n if (this.isStopped) return\r\n // console.log(scroll, velocity, type)\r\n\r\n // return\r\n const isDecelerating = Math.abs(lastVelocity) > Math.abs(velocity)\r\n const isTurningBack =\r\n Math.sign(lastVelocity) !== Math.sign(velocity) && velocity !== 0\r\n\r\n // console.log({ lastVelocity, velocity, isTurningBack, isDecelerating })\r\n\r\n // console.log('onScroll')\r\n\r\n if (\r\n Math.abs(velocity) < this.options.velocityThreshold &&\r\n // !isTouching &&\r\n isDecelerating &&\r\n !isTurningBack &&\r\n userData?.initiator !== 'snap'\r\n ) {\r\n scroll = Math.ceil(scroll)\r\n\r\n let snaps = [0, ...this.snaps.values(), limit] as number[]\r\n\r\n this.elements.forEach(({ rect, align }) => {\r\n let snap: number | undefined\r\n\r\n align.forEach((align) => {\r\n if (align === 'start') {\r\n snap = rect.top\r\n } else if (align === 'center') {\r\n snap = isHorizontal\r\n ? rect.left + rect.width / 2 - this.viewport.width / 2\r\n : rect.top + rect.height / 2 - this.viewport.height / 2\r\n } else if (align === 'end') {\r\n snap = isHorizontal\r\n ? rect.left + rect.width - this.viewport.width\r\n : rect.top + rect.height - this.viewport.height\r\n }\r\n\r\n if (snap !== undefined) {\r\n snaps.push(Math.ceil(snap))\r\n }\r\n })\r\n })\r\n\r\n snaps = snaps.sort((a, b) => Math.abs(a) - Math.abs(b))\r\n\r\n let prevSnap = snaps.findLast((snap) => snap <= scroll)\r\n if (prevSnap === undefined) prevSnap = snaps[0]\r\n const distanceToPrevSnap = Math.abs(scroll - prevSnap)\r\n\r\n let nextSnap = snaps.find((snap) => snap >= scroll)\r\n if (nextSnap === undefined) nextSnap = snaps[snaps.length - 1]\r\n const distanceToNextSnap = Math.abs(scroll - nextSnap)\r\n\r\n const snap = distanceToPrevSnap < distanceToNextSnap ? prevSnap : nextSnap\r\n\r\n const distance = Math.abs(scroll - snap)\r\n\r\n if (\r\n this.options.type === 'mandatory' ||\r\n (this.options.type === 'proximity' && distance <= this.viewport.height)\r\n ) {\r\n // this.__isScrolling = true\r\n // this.onSnapStart?.(snap)\r\n\r\n // console.log('scroll to')\r\n\r\n this.lenis.scrollTo(snap, {\r\n lerp: this.options.lerp,\r\n easing: this.options.easing,\r\n duration: this.options.duration,\r\n userData: { initiator: 'snap' },\r\n onStart: () => {\r\n this.options.onSnapStart?.(snap)\r\n },\r\n onComplete: () => {\r\n this.options.onSnapComplete?.(snap)\r\n },\r\n })\r\n }\r\n\r\n // console.timeEnd('scroll')\r\n }\r\n }\r\n}\r\n"],"names":[],"mappings":"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"}
|