@udixio/ui-react 2.5.2 → 2.6.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/CHANGELOG.md +17 -0
- package/dist/index.cjs +2 -2
- package/dist/index.js +1139 -1162
- package/dist/lib/components/Carousel.d.ts +0 -2
- package/dist/lib/components/Carousel.d.ts.map +1 -1
- package/dist/lib/effects/AnimateOnScroll.d.ts.map +1 -1
- package/package.json +3 -3
- package/src/lib/components/Carousel.tsx +68 -203
- package/src/lib/effects/AnimateOnScroll.ts +51 -18
|
@@ -6,8 +6,6 @@ import { ReactProps } from '../utils';
|
|
|
6
6
|
* @status beta
|
|
7
7
|
* @category Layout
|
|
8
8
|
* @limitations
|
|
9
|
-
* - At the end of the scroll, a residual gap/space may remain visible.
|
|
10
|
-
* - In/out behavior is inconsistent at range edges.
|
|
11
9
|
* - Responsive behavior on mobile is not supported.
|
|
12
10
|
* - Only the default (hero) variant is supported.
|
|
13
11
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Carousel.d.ts","sourceRoot":"","sources":["../../../src/lib/components/Carousel.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,iBAAiB,EAAyB,MAAM,eAAe,CAAC;AAIzE,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"Carousel.d.ts","sourceRoot":"","sources":["../../../src/lib/components/Carousel.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,iBAAiB,EAAyB,MAAM,eAAe,CAAC;AAIzE,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAOtC;;;;;;;;GAQG;AACH,eAAO,MAAM,QAAQ,GAAI,qKActB,UAAU,CAAC,iBAAiB,CAAC,4CA2f/B,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AnimateOnScroll.d.ts","sourceRoot":"","sources":["../../../src/lib/effects/AnimateOnScroll.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"AnimateOnScroll.d.ts","sourceRoot":"","sources":["../../../src/lib/effects/AnimateOnScroll.ts"],"names":[],"mappings":"AA2NA,MAAM,MAAM,sBAAsB,GAAG;IACnC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB,CAAC;AAEF,wBAAgB,mBAAmB,CACjC,OAAO,GAAE,sBAA2B,GACnC,MAAM,IAAI,CAgKZ;AAGD,eAAO,MAAM,mBAAmB,4BAAsB,CAAC;AACvD,eAAO,MAAM,eAAe,4BAAsB,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@udixio/ui-react",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.6.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"module": "./dist/index.js",
|
|
@@ -36,8 +36,8 @@
|
|
|
36
36
|
"devDependencies": {
|
|
37
37
|
"react": "^19.1.1",
|
|
38
38
|
"react-dom": "^19.1.1",
|
|
39
|
-
"@udixio/
|
|
40
|
-
"@udixio/
|
|
39
|
+
"@udixio/theme": "2.1.2",
|
|
40
|
+
"@udixio/tailwind": "2.3.7"
|
|
41
41
|
},
|
|
42
42
|
"repository": {
|
|
43
43
|
"type": "git",
|
|
@@ -7,14 +7,16 @@ import { CustomScroll } from '../effects';
|
|
|
7
7
|
import { ReactProps } from '../utils';
|
|
8
8
|
import { CarouselItem, normalize } from './CarouselItem';
|
|
9
9
|
|
|
10
|
+
function clamp(v: number, min: number, max: number) {
|
|
11
|
+
return Math.max(min, Math.min(max, v));
|
|
12
|
+
}
|
|
13
|
+
|
|
10
14
|
/**
|
|
11
15
|
* Carousels show a collection of items that can be scrolled on and off the screen
|
|
12
16
|
*
|
|
13
17
|
* @status beta
|
|
14
18
|
* @category Layout
|
|
15
19
|
* @limitations
|
|
16
|
-
* - At the end of the scroll, a residual gap/space may remain visible.
|
|
17
|
-
* - In/out behavior is inconsistent at range edges.
|
|
18
20
|
* - Responsive behavior on mobile is not supported.
|
|
19
21
|
* - Only the default (hero) variant is supported.
|
|
20
22
|
*/
|
|
@@ -49,6 +51,7 @@ export const Carousel = ({
|
|
|
49
51
|
onChange,
|
|
50
52
|
gap,
|
|
51
53
|
scrollSensitivity,
|
|
54
|
+
onMetricsChange,
|
|
52
55
|
});
|
|
53
56
|
|
|
54
57
|
const items = React.Children.toArray(children).filter(
|
|
@@ -79,7 +82,6 @@ export const Carousel = ({
|
|
|
79
82
|
|
|
80
83
|
const scrollVisible =
|
|
81
84
|
scroll?.scrollVisible ?? (ref.current as any)?.clientWidth ?? 0;
|
|
82
|
-
// const scrollProgress = scrollMV.get();
|
|
83
85
|
|
|
84
86
|
function assignRelativeIndexes(
|
|
85
87
|
values: number[],
|
|
@@ -90,13 +92,16 @@ export const Carousel = ({
|
|
|
90
92
|
index: number;
|
|
91
93
|
width: number;
|
|
92
94
|
}[] {
|
|
93
|
-
return values.map((value, index) =>
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
95
|
+
return values.map((value, index) => {
|
|
96
|
+
const relativeIndex =
|
|
97
|
+
(value - progressScroll) / Math.abs(values[1] - values[0]);
|
|
98
|
+
return {
|
|
99
|
+
itemScrollXCenter: value,
|
|
100
|
+
relativeIndex,
|
|
101
|
+
index: index,
|
|
102
|
+
width: 0,
|
|
103
|
+
};
|
|
104
|
+
});
|
|
100
105
|
}
|
|
101
106
|
|
|
102
107
|
const itemsScrollXCenter = items.map((_, index) => {
|
|
@@ -113,206 +118,85 @@ export const Carousel = ({
|
|
|
113
118
|
itemsScrollXCenter,
|
|
114
119
|
scroll?.scrollProgress ?? 0,
|
|
115
120
|
).sort((a, b) => a.index - b.index);
|
|
116
|
-
// const visible =
|
|
117
|
-
// ((ref.current?.clientWidth ?? scrollVisible) - (outputRange[0] + gap)) /
|
|
118
|
-
// (outputRange[1] + gap);
|
|
119
|
-
|
|
120
|
-
const visible =
|
|
121
|
-
((ref.current?.clientWidth ?? scrollVisible) + gap) /
|
|
122
|
-
(outputRange[1] + gap);
|
|
123
121
|
|
|
124
|
-
let
|
|
125
|
-
|
|
126
|
-
let selectedItem;
|
|
122
|
+
let widthLeft =
|
|
123
|
+
(ref.current?.clientWidth ?? scrollVisible) + gap + outputRange[0] + gap;
|
|
127
124
|
|
|
128
125
|
const visibleItemValues = itemValues
|
|
129
126
|
.sort((a, b) => Math.abs(a.relativeIndex) - Math.abs(b.relativeIndex))
|
|
130
127
|
.map((item, index) => {
|
|
131
|
-
if (
|
|
132
|
-
|
|
133
|
-
|
|
128
|
+
if (widthLeft <= 0) {
|
|
129
|
+
return undefined;
|
|
130
|
+
}
|
|
131
|
+
if (index == 0) {
|
|
134
132
|
setSelectedItem(item.index);
|
|
135
|
-
selectedItem = item;
|
|
136
133
|
}
|
|
137
134
|
|
|
138
|
-
|
|
139
|
-
|
|
135
|
+
item.width = normalize(
|
|
136
|
+
widthLeft - gap,
|
|
137
|
+
[outputRange[0], outputRange[1]],
|
|
138
|
+
[outputRange[0], outputRange[1]],
|
|
139
|
+
);
|
|
140
|
+
|
|
141
|
+
widthLeft -= item.width + gap;
|
|
140
142
|
|
|
141
|
-
if (
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
143
|
+
if (widthLeft != 0 && widthLeft < (outputRange[0] + gap) * 2) {
|
|
144
|
+
const newWidth =
|
|
145
|
+
item.width - ((outputRange[0] + gap) * 2 - widthLeft);
|
|
146
|
+
|
|
147
|
+
widthLeft += item.width;
|
|
148
|
+
item.width = newWidth;
|
|
149
|
+
widthLeft -= item.width;
|
|
150
|
+
} else if (widthLeft == 0 && item.width >= outputRange[0] * 2 + gap) {
|
|
151
|
+
const newWidth = item.width - (outputRange[0] + gap - widthLeft);
|
|
146
152
|
|
|
147
|
-
|
|
153
|
+
widthLeft += item.width;
|
|
154
|
+
item.width = newWidth;
|
|
155
|
+
widthLeft -= item.width;
|
|
156
|
+
}
|
|
148
157
|
return item;
|
|
149
158
|
})
|
|
150
|
-
.filter(Boolean)
|
|
151
|
-
.sort((a, b) => a.index - b.index) as {
|
|
159
|
+
.filter(Boolean) as unknown as {
|
|
152
160
|
itemScrollXCenter: number;
|
|
153
161
|
relativeIndex: number;
|
|
154
162
|
index: number;
|
|
155
163
|
width: number;
|
|
156
164
|
}[];
|
|
157
165
|
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
if (item.width == outputRange[1]) {
|
|
163
|
-
if (index === 0 || index === array.length - 1) {
|
|
164
|
-
isDynamic = true;
|
|
165
|
-
}
|
|
166
|
-
}
|
|
167
|
-
if (isDynamic) {
|
|
168
|
-
return true;
|
|
169
|
-
} else {
|
|
170
|
-
widthLeft -= item.width + gap;
|
|
171
|
-
return false;
|
|
172
|
-
}
|
|
173
|
-
});
|
|
166
|
+
const reverseItemsVisible = visibleItemValues.reverse();
|
|
167
|
+
const itemsVisibleByIndex = [...visibleItemValues].sort(
|
|
168
|
+
(a, b) => Math.abs(a.index) - Math.abs(b.index),
|
|
169
|
+
);
|
|
174
170
|
|
|
175
|
-
//
|
|
171
|
+
//dynamic items
|
|
176
172
|
|
|
177
|
-
|
|
173
|
+
reverseItemsVisible.forEach((item, index) => {
|
|
174
|
+
const nextItem = reverseItemsVisible[index + 1];
|
|
175
|
+
if (!nextItem) return;
|
|
178
176
|
|
|
179
|
-
|
|
180
|
-
|
|
177
|
+
const test =
|
|
178
|
+
1 - (Math.abs(item.relativeIndex) - Math.abs(nextItem?.relativeIndex));
|
|
181
179
|
|
|
182
|
-
const
|
|
183
|
-
|
|
184
|
-
[0,
|
|
185
|
-
[
|
|
180
|
+
const newWidth = normalize(
|
|
181
|
+
test,
|
|
182
|
+
[0, 2],
|
|
183
|
+
[item.width + widthLeft, nextItem.width],
|
|
186
184
|
);
|
|
187
|
-
item.width = result;
|
|
188
|
-
dynamicWidth += result;
|
|
189
|
-
});
|
|
190
|
-
|
|
191
|
-
// let widthLeft =
|
|
192
|
-
// (visible -
|
|
193
|
-
// visibleItemValues
|
|
194
|
-
// .slice(0, visibleItemValues.length - 2)
|
|
195
|
-
// .filter((item) => item.width === outputRange[1]).length) *
|
|
196
|
-
// outputRange[1];
|
|
197
|
-
|
|
198
|
-
// console.log(
|
|
199
|
-
// visible,
|
|
200
|
-
// widthLeft,
|
|
201
|
-
// visibleItemValues
|
|
202
|
-
// .slice(0, visibleItemValues.length - 2)
|
|
203
|
-
// .filter((item) => item.width === outputRange[1]).length,
|
|
204
|
-
// );
|
|
205
|
-
|
|
206
|
-
let translate = 0;
|
|
207
|
-
dynamicItems.forEach((item, index) => {
|
|
208
|
-
if (!item) return;
|
|
209
|
-
|
|
210
|
-
if (index == 0) {
|
|
211
|
-
const percent = normalize(
|
|
212
|
-
item?.relativeIndex,
|
|
213
|
-
[-2, item.index == 0 ? 0 : -1],
|
|
214
|
-
[0, 1],
|
|
215
|
-
);
|
|
216
|
-
|
|
217
|
-
if (item.index >= 1) {
|
|
218
|
-
itemValues.sort((a, b) => a.index - b.index);
|
|
219
185
|
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
translate = normalize(
|
|
225
|
-
1 - percent,
|
|
226
|
-
[0, 1],
|
|
227
|
-
[0, -(outputRange[0] + gap)],
|
|
228
|
-
);
|
|
229
|
-
}
|
|
230
|
-
widthLeft -= translate;
|
|
231
|
-
|
|
232
|
-
// let relative = selectedItem?.relativeIndex * 2;
|
|
233
|
-
// relative = relative > 0 ? (1 - relative) * -1 : 1 + relative;
|
|
234
|
-
|
|
235
|
-
item.width = normalize(
|
|
236
|
-
percent,
|
|
237
|
-
[0, 1],
|
|
238
|
-
[outputRange[0], outputRange[1]],
|
|
239
|
-
);
|
|
240
|
-
|
|
241
|
-
widthLeft -= item.width;
|
|
242
|
-
|
|
243
|
-
// console.log(widthLeft);
|
|
244
|
-
} else {
|
|
245
|
-
let dynamicIndex = item.index;
|
|
246
|
-
// console.log('n', dynamicIndex, widthLeft);
|
|
247
|
-
let isEnd = dynamicIndex == itemValues.length - 1;
|
|
248
|
-
const isNearEnd = dynamicIndex == itemValues.length - 2;
|
|
249
|
-
// console.log('start');
|
|
250
|
-
while (widthLeft > 0) {
|
|
251
|
-
// console.log('boucle', widthLeft);
|
|
252
|
-
const dynamicItem = itemValues.filter(
|
|
253
|
-
(item) => item.index === dynamicIndex,
|
|
254
|
-
)[0];
|
|
255
|
-
|
|
256
|
-
if (!dynamicItem) {
|
|
257
|
-
if (isEnd) {
|
|
258
|
-
throw new Error('dynamicItem not found');
|
|
259
|
-
}
|
|
260
|
-
// dynamicIndex = dynamicItems[0].index;
|
|
261
|
-
isEnd = true;
|
|
262
|
-
break;
|
|
263
|
-
}
|
|
264
|
-
|
|
265
|
-
if (!visibleItemValues.includes(dynamicItem)) {
|
|
266
|
-
visibleItemValues.push(dynamicItem);
|
|
267
|
-
}
|
|
268
|
-
|
|
269
|
-
dynamicItem.width = normalize(
|
|
270
|
-
widthLeft,
|
|
271
|
-
[outputRange[0], outputRange[1] + (gap + outputRange[0]) * 2],
|
|
272
|
-
[outputRange[0], outputRange[1]],
|
|
273
|
-
);
|
|
274
|
-
|
|
275
|
-
widthLeft -= dynamicItem.width + gap;
|
|
276
|
-
|
|
277
|
-
if (
|
|
278
|
-
(isNearEnd || isEnd) &&
|
|
279
|
-
dynamicItem.index == itemValues.length - 1
|
|
280
|
-
) {
|
|
281
|
-
let dynamicItemIndexStart = isEnd ? 1 : 1;
|
|
282
|
-
|
|
283
|
-
while (widthLeft > 0) {
|
|
284
|
-
const dynamicItemStart = visibleItemValues[dynamicItemIndexStart];
|
|
285
|
-
|
|
286
|
-
const width =
|
|
287
|
-
normalize(
|
|
288
|
-
dynamicItemStart.width + widthLeft,
|
|
289
|
-
[outputRange[0], outputRange[1]],
|
|
290
|
-
[outputRange[0], outputRange[1]],
|
|
291
|
-
) - dynamicItemStart.width;
|
|
292
|
-
|
|
293
|
-
dynamicItemStart.width += width;
|
|
294
|
-
widthLeft -= width;
|
|
295
|
-
|
|
296
|
-
dynamicItemIndexStart--;
|
|
297
|
-
// break;
|
|
298
|
-
}
|
|
299
|
-
|
|
300
|
-
break;
|
|
301
|
-
} else {
|
|
302
|
-
dynamicIndex++;
|
|
303
|
-
}
|
|
304
|
-
// }
|
|
305
|
-
}
|
|
306
|
-
}
|
|
186
|
+
widthLeft += item.width;
|
|
187
|
+
item.width = newWidth;
|
|
188
|
+
widthLeft -= item.width;
|
|
189
|
+
});
|
|
307
190
|
|
|
308
|
-
|
|
191
|
+
const percentMax = visibleItemValues.length / 2;
|
|
192
|
+
const percent = normalize(
|
|
193
|
+
Math.abs(itemsVisibleByIndex[0].relativeIndex),
|
|
194
|
+
[itemsVisibleByIndex[0].index == 0 ? 0 : percentMax - 1, percentMax],
|
|
195
|
+
[0, 1],
|
|
196
|
+
);
|
|
309
197
|
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
// [0, 1],
|
|
313
|
-
// [0, visible * outputRange[1]],
|
|
314
|
-
// );
|
|
315
|
-
});
|
|
198
|
+
const translate =
|
|
199
|
+
normalize(percent, [0, 1], [0, 1]) * -(outputRange[0] + gap);
|
|
316
200
|
|
|
317
201
|
setTranslateX(translate);
|
|
318
202
|
|
|
@@ -414,25 +298,6 @@ export const Carousel = ({
|
|
|
414
298
|
);
|
|
415
299
|
});
|
|
416
300
|
|
|
417
|
-
// persistent motion value for scroll progress, driven by user scroll and programmatic centering
|
|
418
|
-
// const scrollMVRef = useRef(motionValue(0));
|
|
419
|
-
// const scrollMV = scrollMVRef.current;
|
|
420
|
-
|
|
421
|
-
// const transform = useTransform(
|
|
422
|
-
// scrollMV,
|
|
423
|
-
// [0, 1],
|
|
424
|
-
// [
|
|
425
|
-
// 0,
|
|
426
|
-
// 1 -
|
|
427
|
-
// (ref.current?.clientWidth ?? 0) / (trackRef?.current?.clientWidth ?? 0),
|
|
428
|
-
// ],
|
|
429
|
-
// );
|
|
430
|
-
|
|
431
|
-
// const percentTransform = useTransform(
|
|
432
|
-
// transform,
|
|
433
|
-
// (value) => `${-value * 100}%`,
|
|
434
|
-
// );
|
|
435
|
-
|
|
436
301
|
const handleScroll = (args: {
|
|
437
302
|
scrollProgress: number;
|
|
438
303
|
scrollTotal: number;
|
|
@@ -152,10 +152,11 @@ function queryJsObserverCandidates(
|
|
|
152
152
|
}
|
|
153
153
|
|
|
154
154
|
// Utility: identify presence of in/out classes
|
|
155
|
-
function
|
|
156
|
-
return
|
|
155
|
+
function hasOutClass(cls: DOMTokenList, prefix: string): boolean {
|
|
156
|
+
return Array.from(cls).some(
|
|
157
|
+
(className) => className.startsWith(prefix) && className.includes('-out'),
|
|
158
|
+
);
|
|
157
159
|
}
|
|
158
|
-
|
|
159
160
|
// Utility: set run flags for a given direction ("in" or "out"), always ensuring generic run flag exists
|
|
160
161
|
function setRunFlag(el: HTMLElement, prefix: string, dir: 'in' | 'out'): void {
|
|
161
162
|
el.setAttribute(`data-${prefix}-run`, ``);
|
|
@@ -163,12 +164,20 @@ function setRunFlag(el: HTMLElement, prefix: string, dir: 'in' | 'out'): void {
|
|
|
163
164
|
}
|
|
164
165
|
|
|
165
166
|
// Utility: reset run flags and restart animation timeline without changing computed styles
|
|
166
|
-
function resetRunFlags(
|
|
167
|
+
function resetRunFlags(
|
|
168
|
+
el: HTMLElement,
|
|
169
|
+
prefix: string,
|
|
170
|
+
direction?: 'in' | 'out',
|
|
171
|
+
): void {
|
|
167
172
|
const currentAnimationName = el.style.animationName;
|
|
168
173
|
el.style.animationName = 'none';
|
|
169
174
|
el.removeAttribute(`data-${prefix}-run`);
|
|
170
|
-
|
|
171
|
-
|
|
175
|
+
if (!direction) {
|
|
176
|
+
el.removeAttribute(`data-${prefix}-in-run`);
|
|
177
|
+
el.removeAttribute(`data-${prefix}-out-run`);
|
|
178
|
+
} else {
|
|
179
|
+
el.removeAttribute(`data-${prefix}-${direction}-run`);
|
|
180
|
+
}
|
|
172
181
|
void (el as HTMLElement).offsetWidth; // reflow to restart animations
|
|
173
182
|
el.style.animationName = currentAnimationName;
|
|
174
183
|
}
|
|
@@ -198,11 +207,9 @@ function addAnimationLifecycle(el: HTMLElement, prefix: string): void {
|
|
|
198
207
|
|
|
199
208
|
const onEndOrCancel = (e: AnimationEvent) => {
|
|
200
209
|
if (e.target !== el) return;
|
|
210
|
+
// If an IN animation just finished, persist a completion flag so it won't replay on upward scroll
|
|
211
|
+
|
|
201
212
|
el.removeAttribute(`data-${prefix}-animating`);
|
|
202
|
-
// Clear directional run flags so a new trigger can happen after completion
|
|
203
|
-
el.removeAttribute(`data-${prefix}-in-run`);
|
|
204
|
-
el.removeAttribute(`data-${prefix}-out-run`);
|
|
205
|
-
// Note: keep generic data-{prefix}-run for style stability
|
|
206
213
|
};
|
|
207
214
|
|
|
208
215
|
el.addEventListener('animationstart', onStart as EventListener);
|
|
@@ -229,6 +236,21 @@ export function initAnimateOnScroll(
|
|
|
229
236
|
// Setup JS observers for non-scroll-driven animations
|
|
230
237
|
const observed = new WeakSet<Element>();
|
|
231
238
|
|
|
239
|
+
// Track scroll direction to prevent triggering IN when scrolling up
|
|
240
|
+
let lastScrollY =
|
|
241
|
+
typeof window !== 'undefined'
|
|
242
|
+
? window.pageYOffset || window.scrollY || 0
|
|
243
|
+
: 0;
|
|
244
|
+
let scrollingDown = true; // default allow initial IN
|
|
245
|
+
const onScrollDir = () => {
|
|
246
|
+
const y = window.pageYOffset || window.scrollY || 0;
|
|
247
|
+
scrollingDown = y >= lastScrollY;
|
|
248
|
+
lastScrollY = y;
|
|
249
|
+
};
|
|
250
|
+
if (typeof window !== 'undefined') {
|
|
251
|
+
window.addEventListener('scroll', onScrollDir, { passive: true });
|
|
252
|
+
}
|
|
253
|
+
|
|
232
254
|
const io = new IntersectionObserver(
|
|
233
255
|
(entries) => {
|
|
234
256
|
for (const entry of entries) {
|
|
@@ -239,17 +261,25 @@ export function initAnimateOnScroll(
|
|
|
239
261
|
// If an animation is in progress, avoid re-triggering or flipping direction
|
|
240
262
|
if (el.hasAttribute(`data-${prefix}-animating`)) continue;
|
|
241
263
|
|
|
242
|
-
const isOut = el.classList
|
|
264
|
+
const isOut = hasOutClass(el.classList, prefix);
|
|
243
265
|
|
|
244
|
-
if (
|
|
266
|
+
if (entry.isIntersecting) {
|
|
267
|
+
if (isOut) {
|
|
268
|
+
resetRunFlags(el, prefix, 'out');
|
|
269
|
+
}
|
|
245
270
|
setRunFlag(el, prefix, 'in');
|
|
271
|
+
|
|
246
272
|
if (once) io.unobserve(el);
|
|
247
|
-
} else
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
273
|
+
} else {
|
|
274
|
+
if (!once) {
|
|
275
|
+
if (!scrollingDown) {
|
|
276
|
+
resetRunFlags(el, prefix, 'in');
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
if (isOut) {
|
|
280
|
+
setRunFlag(el, prefix, 'out');
|
|
281
|
+
}
|
|
282
|
+
}
|
|
253
283
|
}
|
|
254
284
|
}
|
|
255
285
|
},
|
|
@@ -349,6 +379,9 @@ export function initAnimateOnScroll(
|
|
|
349
379
|
// Public cleanup
|
|
350
380
|
return () => {
|
|
351
381
|
if (cleanupScrollDriven) cleanupScrollDriven();
|
|
382
|
+
if (typeof window !== 'undefined') {
|
|
383
|
+
window.removeEventListener('scroll', onScrollDir as EventListener);
|
|
384
|
+
}
|
|
352
385
|
io.disconnect();
|
|
353
386
|
};
|
|
354
387
|
}
|