motion 10.11.2 → 10.13.1
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 +26 -0
- package/dist/animate.cjs.js +6 -5
- package/dist/animate.es.js +7 -6
- package/dist/main.cjs.js +7 -25
- package/dist/main.es.js +2 -2
- package/dist/motion.min.js +1 -1
- package/dist/motion.umd.js +949 -94
- package/dist/size-index.js +1 -1
- package/lib/animate.js +7 -6
- package/lib/animate.js.map +1 -1
- package/lib/index.js +2 -2
- package/lib/index.js.map +1 -1
- package/package.json +8 -8
- package/types/animate.d.ts +2 -2
- package/types/animate.d.ts.map +1 -1
- package/types/index.d.ts +2 -3
- package/types/index.d.ts.map +1 -1
- package/dist/react.cjs.js +0 -14
- package/dist/react.es.js +0 -1
- package/react/package.json +0 -6
package/dist/motion.umd.js
CHANGED
|
@@ -56,12 +56,20 @@
|
|
|
56
56
|
};
|
|
57
57
|
|
|
58
58
|
const isNumber = (value) => typeof value === "number";
|
|
59
|
-
|
|
60
|
-
const isEasingGenerator = (easing) => typeof easing === "object" &&
|
|
61
|
-
Boolean(easing.createAnimation);
|
|
62
|
-
const isCubicBezier = (easing) => Array.isArray(easing) && isNumber(easing[0]);
|
|
59
|
+
|
|
63
60
|
const isEasingList = (easing) => Array.isArray(easing) && !isNumber(easing[0]);
|
|
64
61
|
|
|
62
|
+
const wrap = (min, max, v) => {
|
|
63
|
+
const rangeSize = max - min;
|
|
64
|
+
return ((((v - min) % rangeSize) + rangeSize) % rangeSize) + min;
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
function getEasingForSegment(easing, i) {
|
|
68
|
+
return isEasingList(easing)
|
|
69
|
+
? easing[wrap(0, easing.length, i)]
|
|
70
|
+
: easing;
|
|
71
|
+
}
|
|
72
|
+
|
|
65
73
|
const mix = (min, max, progress) => -progress * min + progress * max + min;
|
|
66
74
|
|
|
67
75
|
const noop = () => { };
|
|
@@ -76,12 +84,44 @@
|
|
|
76
84
|
offset.push(mix(min, 1, offsetProgress));
|
|
77
85
|
}
|
|
78
86
|
}
|
|
79
|
-
function defaultOffset(length) {
|
|
87
|
+
function defaultOffset$1(length) {
|
|
80
88
|
const offset = [0];
|
|
81
89
|
fillOffset(offset, length - 1);
|
|
82
90
|
return offset;
|
|
83
91
|
}
|
|
84
92
|
|
|
93
|
+
function interpolate(output, input = defaultOffset$1(output.length), easing = noopReturn) {
|
|
94
|
+
const length = output.length;
|
|
95
|
+
/**
|
|
96
|
+
* If the input length is lower than the output we
|
|
97
|
+
* fill the input to match. This currently assumes the input
|
|
98
|
+
* is an animation progress value so is a good candidate for
|
|
99
|
+
* moving outside the function.
|
|
100
|
+
*/
|
|
101
|
+
const remainder = length - input.length;
|
|
102
|
+
remainder > 0 && fillOffset(input, remainder);
|
|
103
|
+
return (t) => {
|
|
104
|
+
let i = 0;
|
|
105
|
+
for (; i < length - 2; i++) {
|
|
106
|
+
if (t < input[i + 1])
|
|
107
|
+
break;
|
|
108
|
+
}
|
|
109
|
+
let progressInRange = clamp(0, 1, progress(input[i], input[i + 1], t));
|
|
110
|
+
const segmentEasing = getEasingForSegment(easing, i);
|
|
111
|
+
progressInRange = segmentEasing(progressInRange);
|
|
112
|
+
return mix(output[i], output[i + 1], progressInRange);
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
const isCubicBezier = (easing) => Array.isArray(easing) && isNumber(easing[0]);
|
|
117
|
+
|
|
118
|
+
const isEasingGenerator = (easing) => typeof easing === "object" &&
|
|
119
|
+
Boolean(easing.createAnimation);
|
|
120
|
+
|
|
121
|
+
const isFunction = (value) => typeof value === "function";
|
|
122
|
+
|
|
123
|
+
const isString = (value) => typeof value === "string";
|
|
124
|
+
|
|
85
125
|
const time = {
|
|
86
126
|
ms: (seconds) => seconds * 1000,
|
|
87
127
|
s: (milliseconds) => milliseconds / 1000,
|
|
@@ -97,11 +137,6 @@
|
|
|
97
137
|
return frameDuration ? velocity * (1000 / frameDuration) : 0;
|
|
98
138
|
}
|
|
99
139
|
|
|
100
|
-
const wrap = (min, max, v) => {
|
|
101
|
-
const rangeSize = max - min;
|
|
102
|
-
return ((((v - min) % rangeSize) + rangeSize) % rangeSize) + min;
|
|
103
|
-
};
|
|
104
|
-
|
|
105
140
|
/**
|
|
106
141
|
* A list of all transformable axes. We'll use this list to generated a version
|
|
107
142
|
* of each axes for each transform.
|
|
@@ -264,7 +299,7 @@
|
|
|
264
299
|
const functionArgsRegex = /\((.*?)\)/;
|
|
265
300
|
function getEasingFunction(definition) {
|
|
266
301
|
// If already an easing function, return
|
|
267
|
-
if (
|
|
302
|
+
if (isFunction(definition))
|
|
268
303
|
return definition;
|
|
269
304
|
// If an easing curve definition, return bezier function
|
|
270
305
|
if (Array.isArray(definition))
|
|
@@ -282,67 +317,46 @@
|
|
|
282
317
|
}
|
|
283
318
|
return noopReturn;
|
|
284
319
|
}
|
|
285
|
-
function getEasingForSegment(easing, i) {
|
|
286
|
-
return isEasingList(easing)
|
|
287
|
-
? easing[wrap(0, easing.length, i)]
|
|
288
|
-
: easing;
|
|
289
|
-
}
|
|
290
|
-
|
|
291
|
-
const clampProgress = (p) => Math.min(1, Math.max(p, 0));
|
|
292
|
-
function interpolate(output, input = defaultOffset(output.length), easing = noopReturn) {
|
|
293
|
-
const length = output.length;
|
|
294
|
-
/**
|
|
295
|
-
* If the input length is lower than the output we
|
|
296
|
-
* fill the input to match. This currently assumes the input
|
|
297
|
-
* is an animation progress value so is a good candidate for
|
|
298
|
-
* moving outside the function.
|
|
299
|
-
*/
|
|
300
|
-
const remainder = length - input.length;
|
|
301
|
-
remainder > 0 && fillOffset(input, remainder);
|
|
302
|
-
return (t) => {
|
|
303
|
-
let i = 0;
|
|
304
|
-
for (; i < length - 2; i++) {
|
|
305
|
-
if (t < input[i + 1])
|
|
306
|
-
break;
|
|
307
|
-
}
|
|
308
|
-
let progressInRange = clampProgress(progress(input[i], input[i + 1], t));
|
|
309
|
-
const segmentEasing = getEasingForSegment(easing, i);
|
|
310
|
-
progressInRange = segmentEasing(progressInRange);
|
|
311
|
-
return mix(output[i], output[i + 1], progressInRange);
|
|
312
|
-
};
|
|
313
|
-
}
|
|
314
320
|
|
|
315
321
|
class Animation {
|
|
316
|
-
constructor(output, keyframes = [0, 1], { easing
|
|
322
|
+
constructor(output, keyframes = [0, 1], { easing, duration: initialDuration = defaults$1.duration, delay = defaults$1.delay, endDelay = defaults$1.endDelay, repeat = defaults$1.repeat, offset, direction = "normal", } = {}) {
|
|
317
323
|
this.startTime = null;
|
|
318
324
|
this.rate = 1;
|
|
319
325
|
this.t = 0;
|
|
320
326
|
this.cancelTimestamp = null;
|
|
327
|
+
this.easing = noopReturn;
|
|
328
|
+
this.duration = 0;
|
|
329
|
+
this.totalDuration = 0;
|
|
330
|
+
this.repeat = 0;
|
|
321
331
|
this.playState = "idle";
|
|
322
332
|
this.finished = new Promise((resolve, reject) => {
|
|
323
333
|
this.resolve = resolve;
|
|
324
334
|
this.reject = reject;
|
|
325
335
|
});
|
|
336
|
+
easing = easing || defaults$1.easing;
|
|
326
337
|
if (isEasingGenerator(easing)) {
|
|
327
338
|
const custom = easing.createAnimation(keyframes, () => "0", true);
|
|
328
339
|
easing = custom.easing;
|
|
329
340
|
if (custom.keyframes !== undefined)
|
|
330
341
|
keyframes = custom.keyframes;
|
|
331
342
|
if (custom.duration !== undefined)
|
|
332
|
-
|
|
343
|
+
initialDuration = custom.duration;
|
|
333
344
|
}
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
const totalDuration = duration * (repeat + 1);
|
|
345
|
+
this.repeat = repeat;
|
|
346
|
+
this.easing = isEasingList(easing) ? noopReturn : getEasingFunction(easing);
|
|
347
|
+
this.updateDuration(initialDuration);
|
|
338
348
|
const interpolate$1 = interpolate(keyframes, offset, isEasingList(easing) ? easing.map(getEasingFunction) : noopReturn);
|
|
339
349
|
this.tick = (timestamp) => {
|
|
340
350
|
var _a;
|
|
341
351
|
// TODO: Temporary fix for OptionsResolver typing
|
|
342
352
|
delay = delay;
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
353
|
+
let t = 0;
|
|
354
|
+
if (this.pauseTime !== undefined) {
|
|
355
|
+
t = this.pauseTime;
|
|
356
|
+
}
|
|
357
|
+
else {
|
|
358
|
+
t = (timestamp - this.startTime) * this.rate;
|
|
359
|
+
}
|
|
346
360
|
this.t = t;
|
|
347
361
|
// Convert to seconds
|
|
348
362
|
t /= 1000;
|
|
@@ -352,14 +366,15 @@
|
|
|
352
366
|
* If this animation has finished, set the current time
|
|
353
367
|
* to the total duration.
|
|
354
368
|
*/
|
|
355
|
-
if (this.playState === "finished")
|
|
356
|
-
t = totalDuration;
|
|
369
|
+
if (this.playState === "finished" && this.pauseTime === undefined) {
|
|
370
|
+
t = this.totalDuration;
|
|
371
|
+
}
|
|
357
372
|
/**
|
|
358
373
|
* Get the current progress (0-1) of the animation. If t is >
|
|
359
374
|
* than duration we'll get values like 2.5 (midway through the
|
|
360
375
|
* third iteration)
|
|
361
376
|
*/
|
|
362
|
-
const progress = t / duration;
|
|
377
|
+
const progress = t / this.duration;
|
|
363
378
|
// TODO progress += iterationStart
|
|
364
379
|
/**
|
|
365
380
|
* Get the current iteration (0 indexed). For instance the floor of
|
|
@@ -388,10 +403,11 @@
|
|
|
388
403
|
(direction === "alternate-reverse" && !iterationIsOdd)) {
|
|
389
404
|
iterationProgress = 1 - iterationProgress;
|
|
390
405
|
}
|
|
391
|
-
const p = t >= totalDuration ? 1 : Math.min(iterationProgress, 1);
|
|
392
|
-
const latest = interpolate$1(
|
|
406
|
+
const p = t >= this.totalDuration ? 1 : Math.min(iterationProgress, 1);
|
|
407
|
+
const latest = interpolate$1(this.easing(p));
|
|
393
408
|
output(latest);
|
|
394
|
-
const isAnimationFinished = this.
|
|
409
|
+
const isAnimationFinished = this.pauseTime === undefined &&
|
|
410
|
+
(this.playState === "finished" || t >= this.totalDuration + endDelay);
|
|
395
411
|
if (isAnimationFinished) {
|
|
396
412
|
this.playState = "finished";
|
|
397
413
|
(_a = this.resolve) === null || _a === void 0 ? void 0 : _a.call(this, latest);
|
|
@@ -403,22 +419,21 @@
|
|
|
403
419
|
this.play();
|
|
404
420
|
}
|
|
405
421
|
play() {
|
|
406
|
-
var _a;
|
|
407
422
|
const now = performance.now();
|
|
408
423
|
this.playState = "running";
|
|
409
|
-
if (this.pauseTime) {
|
|
410
|
-
this.startTime = now -
|
|
424
|
+
if (this.pauseTime !== undefined) {
|
|
425
|
+
this.startTime = now - this.pauseTime;
|
|
411
426
|
}
|
|
412
427
|
else if (!this.startTime) {
|
|
413
428
|
this.startTime = now;
|
|
414
429
|
}
|
|
415
430
|
this.cancelTimestamp = this.startTime;
|
|
416
431
|
this.pauseTime = undefined;
|
|
417
|
-
requestAnimationFrame(this.tick);
|
|
432
|
+
this.frameRequestId = requestAnimationFrame(this.tick);
|
|
418
433
|
}
|
|
419
434
|
pause() {
|
|
420
435
|
this.playState = "paused";
|
|
421
|
-
this.pauseTime =
|
|
436
|
+
this.pauseTime = this.t;
|
|
422
437
|
}
|
|
423
438
|
finish() {
|
|
424
439
|
this.playState = "finished";
|
|
@@ -440,11 +455,15 @@
|
|
|
440
455
|
this.rate *= -1;
|
|
441
456
|
}
|
|
442
457
|
commitStyles() { }
|
|
458
|
+
updateDuration(duration) {
|
|
459
|
+
this.duration = duration;
|
|
460
|
+
this.totalDuration = duration * (this.repeat + 1);
|
|
461
|
+
}
|
|
443
462
|
get currentTime() {
|
|
444
463
|
return this.t;
|
|
445
464
|
}
|
|
446
465
|
set currentTime(t) {
|
|
447
|
-
if (this.pauseTime || this.rate === 0) {
|
|
466
|
+
if (this.pauseTime !== undefined || this.rate === 0) {
|
|
448
467
|
this.pauseTime = t;
|
|
449
468
|
}
|
|
450
469
|
else {
|
|
@@ -459,10 +478,7 @@
|
|
|
459
478
|
}
|
|
460
479
|
}
|
|
461
480
|
|
|
462
|
-
const
|
|
463
|
-
const cubicBezierAsString = ([a, b, c, d]) => `cubic-bezier(${a}, ${b}, ${c}, ${d})`;
|
|
464
|
-
|
|
465
|
-
const testAnimation = (keyframes) => document.createElement("div").animate(keyframes, { duration: 0.001 });
|
|
481
|
+
const testAnimation = (keyframes, options) => document.createElement("div").animate(keyframes, options);
|
|
466
482
|
const featureTests = {
|
|
467
483
|
cssRegisterProperty: () => typeof CSS !== "undefined" &&
|
|
468
484
|
Object.hasOwnProperty.call(CSS, "registerProperty"),
|
|
@@ -476,7 +492,16 @@
|
|
|
476
492
|
}
|
|
477
493
|
return true;
|
|
478
494
|
},
|
|
479
|
-
finished: () => Boolean(testAnimation({ opacity: [0, 1] }).finished),
|
|
495
|
+
finished: () => Boolean(testAnimation({ opacity: [0, 1] }, { duration: 0.001 }).finished),
|
|
496
|
+
linearEasing: () => {
|
|
497
|
+
try {
|
|
498
|
+
testAnimation({ opacity: 0 }, { easing: "linear(0, 1)" });
|
|
499
|
+
}
|
|
500
|
+
catch (e) {
|
|
501
|
+
return false;
|
|
502
|
+
}
|
|
503
|
+
return true;
|
|
504
|
+
},
|
|
480
505
|
};
|
|
481
506
|
const results = {};
|
|
482
507
|
const supports = {};
|
|
@@ -488,6 +513,28 @@
|
|
|
488
513
|
};
|
|
489
514
|
}
|
|
490
515
|
|
|
516
|
+
// Create a linear easing point for every x second
|
|
517
|
+
const resolution = 0.015;
|
|
518
|
+
const generateLinearEasingPoints = (easing, duration) => {
|
|
519
|
+
let points = "";
|
|
520
|
+
const numPoints = Math.round(duration / resolution);
|
|
521
|
+
for (let i = 0; i < numPoints; i++) {
|
|
522
|
+
points += easing(progress(0, numPoints - 1, i)) + ", ";
|
|
523
|
+
}
|
|
524
|
+
return points.substring(0, points.length - 2);
|
|
525
|
+
};
|
|
526
|
+
const convertEasing = (easing, duration) => {
|
|
527
|
+
if (isFunction(easing)) {
|
|
528
|
+
return supports.linearEasing()
|
|
529
|
+
? `linear(${generateLinearEasingPoints(easing, duration)})`
|
|
530
|
+
: defaults$1.easing;
|
|
531
|
+
}
|
|
532
|
+
else {
|
|
533
|
+
return isCubicBezier(easing) ? cubicBezierAsString(easing) : easing;
|
|
534
|
+
}
|
|
535
|
+
};
|
|
536
|
+
const cubicBezierAsString = ([a, b, c, d]) => `cubic-bezier(${a}, ${b}, ${c}, ${d})`;
|
|
537
|
+
|
|
491
538
|
function hydrateKeyframes(keyframes, readInitialValue) {
|
|
492
539
|
for (let i = 0; i < keyframes.length; i++) {
|
|
493
540
|
if (keyframes[i] === null) {
|
|
@@ -553,8 +600,8 @@
|
|
|
553
600
|
let animation;
|
|
554
601
|
let { duration = defaults$1.duration, delay = defaults$1.delay, endDelay = defaults$1.endDelay, repeat = defaults$1.repeat, easing = defaults$1.easing, direction, offset, allowWebkitAcceleration = false, } = options;
|
|
555
602
|
const data = getAnimationData(element);
|
|
556
|
-
let canAnimateNatively = supports.waapi();
|
|
557
603
|
const valueIsTransform = isTransform(key);
|
|
604
|
+
let canAnimateNatively = supports.waapi();
|
|
558
605
|
/**
|
|
559
606
|
* If this is an individual transform, we need to map its
|
|
560
607
|
* key to a CSS variable and update the element's transform style
|
|
@@ -607,8 +654,18 @@
|
|
|
607
654
|
}
|
|
608
655
|
}
|
|
609
656
|
/**
|
|
610
|
-
* If we
|
|
611
|
-
*
|
|
657
|
+
* If we've been passed a custom easing function, and this browser
|
|
658
|
+
* does **not** support linear() easing, and the value is a transform
|
|
659
|
+
* (and thus a pure number) we can still support the custom easing
|
|
660
|
+
* by falling back to the animation polyfill.
|
|
661
|
+
*/
|
|
662
|
+
if (valueIsTransform &&
|
|
663
|
+
!supports.linearEasing() &&
|
|
664
|
+
(isFunction(easing) || (isEasingList(easing) && easing.some(isFunction)))) {
|
|
665
|
+
canAnimateNatively = false;
|
|
666
|
+
}
|
|
667
|
+
/**
|
|
668
|
+
* If we can animate this value with WAAPI, do so.
|
|
612
669
|
*/
|
|
613
670
|
if (canAnimateNatively) {
|
|
614
671
|
/**
|
|
@@ -630,7 +687,9 @@
|
|
|
630
687
|
delay: time.ms(delay),
|
|
631
688
|
duration: time.ms(duration),
|
|
632
689
|
endDelay: time.ms(endDelay),
|
|
633
|
-
easing: !isEasingList(easing)
|
|
690
|
+
easing: !isEasingList(easing)
|
|
691
|
+
? convertEasing(easing, duration)
|
|
692
|
+
: undefined,
|
|
634
693
|
direction,
|
|
635
694
|
iterations: repeat + 1,
|
|
636
695
|
fill: "both",
|
|
@@ -638,7 +697,9 @@
|
|
|
638
697
|
animation = element.animate({
|
|
639
698
|
[name]: keyframes,
|
|
640
699
|
offset,
|
|
641
|
-
easing: isEasingList(easing)
|
|
700
|
+
easing: isEasingList(easing)
|
|
701
|
+
? easing.map((thisEasing) => convertEasing(thisEasing, duration))
|
|
702
|
+
: undefined,
|
|
642
703
|
}, animationOptions);
|
|
643
704
|
/**
|
|
644
705
|
* Polyfill finished Promise in browsers that don't support it
|
|
@@ -744,10 +805,13 @@
|
|
|
744
805
|
}
|
|
745
806
|
|
|
746
807
|
const createAnimation = (factory) => factory();
|
|
747
|
-
const
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
808
|
+
const withControls = (animationFactory, options, duration = defaults$1.duration) => {
|
|
809
|
+
return new Proxy({
|
|
810
|
+
animations: animationFactory.map(createAnimation).filter(Boolean),
|
|
811
|
+
duration,
|
|
812
|
+
options,
|
|
813
|
+
}, controls);
|
|
814
|
+
};
|
|
751
815
|
/**
|
|
752
816
|
* TODO:
|
|
753
817
|
* Currently this returns the first animation, ideally it would return
|
|
@@ -761,8 +825,7 @@
|
|
|
761
825
|
case "duration":
|
|
762
826
|
return target.duration;
|
|
763
827
|
case "currentTime":
|
|
764
|
-
|
|
765
|
-
return time ? time / 1000 : 0;
|
|
828
|
+
return time.s((activeAnimation === null || activeAnimation === void 0 ? void 0 : activeAnimation[key]) || 0);
|
|
766
829
|
case "playbackRate":
|
|
767
830
|
case "playState":
|
|
768
831
|
return activeAnimation === null || activeAnimation === void 0 ? void 0 : activeAnimation[key];
|
|
@@ -772,7 +835,17 @@
|
|
|
772
835
|
}
|
|
773
836
|
return target.finished;
|
|
774
837
|
case "stop":
|
|
775
|
-
return () =>
|
|
838
|
+
return () => {
|
|
839
|
+
target.animations.forEach((animation) => stopAnimation(animation));
|
|
840
|
+
};
|
|
841
|
+
case "forEachNative":
|
|
842
|
+
/**
|
|
843
|
+
* This is for internal use only, fire a callback for each
|
|
844
|
+
* underlying animation.
|
|
845
|
+
*/
|
|
846
|
+
return (callback) => {
|
|
847
|
+
target.animations.forEach((animation) => callback(animation, target));
|
|
848
|
+
};
|
|
776
849
|
default:
|
|
777
850
|
return typeof (activeAnimation === null || activeAnimation === void 0 ? void 0 : activeAnimation[key]) === "undefined"
|
|
778
851
|
? undefined
|
|
@@ -818,9 +891,7 @@
|
|
|
818
891
|
}
|
|
819
892
|
}
|
|
820
893
|
function resolveOption(option, i, total) {
|
|
821
|
-
return
|
|
822
|
-
? option(i, total)
|
|
823
|
-
: option;
|
|
894
|
+
return isFunction(option) ? option(i, total) : option;
|
|
824
895
|
}
|
|
825
896
|
|
|
826
897
|
function animate$1(elements, keyframes, options = {}) {
|
|
@@ -839,7 +910,7 @@
|
|
|
839
910
|
animationFactories.push(animation);
|
|
840
911
|
}
|
|
841
912
|
}
|
|
842
|
-
return
|
|
913
|
+
return withControls(animationFactories, options,
|
|
843
914
|
/**
|
|
844
915
|
* TODO:
|
|
845
916
|
* If easing is set to spring or glide, duration will be dynamically
|
|
@@ -948,7 +1019,7 @@
|
|
|
948
1019
|
const animationFactories = animationDefinitions
|
|
949
1020
|
.map((definition) => animateStyle(...definition))
|
|
950
1021
|
.filter(Boolean);
|
|
951
|
-
return
|
|
1022
|
+
return withControls(animationFactories, options,
|
|
952
1023
|
// Get the duration from the first animation definition
|
|
953
1024
|
(_a = animationDefinitions[0]) === null || _a === void 0 ? void 0 : _a[3].duration);
|
|
954
1025
|
}
|
|
@@ -1025,7 +1096,7 @@
|
|
|
1025
1096
|
/**
|
|
1026
1097
|
*
|
|
1027
1098
|
*/
|
|
1028
|
-
let { offset = defaultOffset(valueKeyframes.length) } = valueOptions;
|
|
1099
|
+
let { offset = defaultOffset$1(valueKeyframes.length) } = valueOptions;
|
|
1029
1100
|
/**
|
|
1030
1101
|
* If there's only one offset of 0, fill in a second with length 1
|
|
1031
1102
|
*
|
|
@@ -1377,7 +1448,7 @@
|
|
|
1377
1448
|
any: 0,
|
|
1378
1449
|
all: 1,
|
|
1379
1450
|
};
|
|
1380
|
-
function inView(
|
|
1451
|
+
function inView$1(elementOrSelector, onStart, { root, margin: rootMargin, amount = "any" } = {}) {
|
|
1381
1452
|
/**
|
|
1382
1453
|
* If this browser doesn't support IntersectionObserver, return a dummy stop function.
|
|
1383
1454
|
* Default triggering of onStart is tricky - it could be used for starting/stopping
|
|
@@ -1387,7 +1458,7 @@
|
|
|
1387
1458
|
if (typeof IntersectionObserver === "undefined") {
|
|
1388
1459
|
return () => { };
|
|
1389
1460
|
}
|
|
1390
|
-
const
|
|
1461
|
+
const elements = resolveElements(elementOrSelector);
|
|
1391
1462
|
const activeIntersections = new WeakMap();
|
|
1392
1463
|
const onIntersectionChange = (entries) => {
|
|
1393
1464
|
entries.forEach((entry) => {
|
|
@@ -1400,7 +1471,7 @@
|
|
|
1400
1471
|
return;
|
|
1401
1472
|
if (entry.isIntersecting) {
|
|
1402
1473
|
const newOnEnd = onStart(entry);
|
|
1403
|
-
if (
|
|
1474
|
+
if (isFunction(newOnEnd)) {
|
|
1404
1475
|
activeIntersections.set(entry.target, newOnEnd);
|
|
1405
1476
|
}
|
|
1406
1477
|
else {
|
|
@@ -1418,32 +1489,816 @@
|
|
|
1418
1489
|
rootMargin,
|
|
1419
1490
|
threshold: typeof amount === "number" ? amount : thresholds[amount],
|
|
1420
1491
|
});
|
|
1421
|
-
|
|
1492
|
+
elements.forEach((element) => observer.observe(element));
|
|
1422
1493
|
return () => observer.disconnect();
|
|
1423
1494
|
}
|
|
1424
1495
|
|
|
1425
|
-
|
|
1426
|
-
|
|
1496
|
+
const resizeHandlers = new WeakMap();
|
|
1497
|
+
let observer;
|
|
1498
|
+
function getElementSize(target, borderBoxSize) {
|
|
1499
|
+
if (borderBoxSize) {
|
|
1500
|
+
const { inlineSize, blockSize } = borderBoxSize[0];
|
|
1501
|
+
return { width: inlineSize, height: blockSize };
|
|
1502
|
+
}
|
|
1503
|
+
else if (target instanceof SVGElement && "getBBox" in target) {
|
|
1504
|
+
return target.getBBox();
|
|
1505
|
+
}
|
|
1506
|
+
else {
|
|
1507
|
+
return {
|
|
1508
|
+
width: target.offsetWidth,
|
|
1509
|
+
height: target.offsetHeight,
|
|
1510
|
+
};
|
|
1511
|
+
}
|
|
1512
|
+
}
|
|
1513
|
+
function notifyTarget({ target, contentRect, borderBoxSize, }) {
|
|
1514
|
+
var _a;
|
|
1515
|
+
(_a = resizeHandlers.get(target)) === null || _a === void 0 ? void 0 : _a.forEach((handler) => {
|
|
1516
|
+
handler({
|
|
1517
|
+
target,
|
|
1518
|
+
contentSize: contentRect,
|
|
1519
|
+
get size() {
|
|
1520
|
+
return getElementSize(target, borderBoxSize);
|
|
1521
|
+
},
|
|
1522
|
+
});
|
|
1523
|
+
});
|
|
1524
|
+
}
|
|
1525
|
+
function notifyAll(entries) {
|
|
1526
|
+
entries.forEach(notifyTarget);
|
|
1527
|
+
}
|
|
1528
|
+
function createResizeObserver() {
|
|
1529
|
+
if (typeof ResizeObserver === "undefined")
|
|
1530
|
+
return;
|
|
1531
|
+
observer = new ResizeObserver(notifyAll);
|
|
1532
|
+
}
|
|
1533
|
+
function resizeElement(target, handler) {
|
|
1534
|
+
if (!observer)
|
|
1535
|
+
createResizeObserver();
|
|
1536
|
+
const elements = resolveElements(target);
|
|
1537
|
+
elements.forEach((element) => {
|
|
1538
|
+
let elementHandlers = resizeHandlers.get(element);
|
|
1539
|
+
if (!elementHandlers) {
|
|
1540
|
+
elementHandlers = new Set();
|
|
1541
|
+
resizeHandlers.set(element, elementHandlers);
|
|
1542
|
+
}
|
|
1543
|
+
elementHandlers.add(handler);
|
|
1544
|
+
observer === null || observer === void 0 ? void 0 : observer.observe(element);
|
|
1545
|
+
});
|
|
1546
|
+
return () => {
|
|
1547
|
+
elements.forEach((element) => {
|
|
1548
|
+
const elementHandlers = resizeHandlers.get(element);
|
|
1549
|
+
elementHandlers === null || elementHandlers === void 0 ? void 0 : elementHandlers.delete(handler);
|
|
1550
|
+
if (!(elementHandlers === null || elementHandlers === void 0 ? void 0 : elementHandlers.size)) {
|
|
1551
|
+
observer === null || observer === void 0 ? void 0 : observer.unobserve(element);
|
|
1552
|
+
}
|
|
1553
|
+
});
|
|
1554
|
+
};
|
|
1555
|
+
}
|
|
1556
|
+
|
|
1557
|
+
const windowCallbacks = new Set();
|
|
1558
|
+
let windowResizeHandler;
|
|
1559
|
+
function createWindowResizeHandler() {
|
|
1560
|
+
windowResizeHandler = () => {
|
|
1561
|
+
const size = {
|
|
1562
|
+
width: window.innerWidth,
|
|
1563
|
+
height: window.innerHeight,
|
|
1564
|
+
};
|
|
1565
|
+
const info = {
|
|
1566
|
+
target: window,
|
|
1567
|
+
size,
|
|
1568
|
+
contentSize: size,
|
|
1569
|
+
};
|
|
1570
|
+
windowCallbacks.forEach((callback) => callback(info));
|
|
1571
|
+
};
|
|
1572
|
+
window.addEventListener("resize", windowResizeHandler);
|
|
1573
|
+
}
|
|
1574
|
+
function resizeWindow(callback) {
|
|
1575
|
+
windowCallbacks.add(callback);
|
|
1576
|
+
if (!windowResizeHandler)
|
|
1577
|
+
createWindowResizeHandler();
|
|
1578
|
+
return () => {
|
|
1579
|
+
windowCallbacks.delete(callback);
|
|
1580
|
+
if (!windowCallbacks.size && windowResizeHandler) {
|
|
1581
|
+
windowResizeHandler = undefined;
|
|
1582
|
+
}
|
|
1583
|
+
};
|
|
1584
|
+
}
|
|
1585
|
+
|
|
1586
|
+
function resize(a, b) {
|
|
1587
|
+
return isFunction(a) ? resizeWindow(a) : resizeElement(a, b);
|
|
1588
|
+
}
|
|
1589
|
+
|
|
1590
|
+
/**
|
|
1591
|
+
* A time in milliseconds, beyond which we consider the scroll velocity to be 0.
|
|
1592
|
+
*/
|
|
1593
|
+
const maxElapsed = 50;
|
|
1594
|
+
const createAxisInfo = () => ({
|
|
1595
|
+
current: 0,
|
|
1596
|
+
offset: [],
|
|
1597
|
+
progress: 0,
|
|
1598
|
+
scrollLength: 0,
|
|
1599
|
+
targetOffset: 0,
|
|
1600
|
+
targetLength: 0,
|
|
1601
|
+
containerLength: 0,
|
|
1602
|
+
velocity: 0,
|
|
1603
|
+
});
|
|
1604
|
+
const createScrollInfo = () => ({
|
|
1605
|
+
time: 0,
|
|
1606
|
+
x: createAxisInfo(),
|
|
1607
|
+
y: createAxisInfo(),
|
|
1608
|
+
});
|
|
1609
|
+
const keys = {
|
|
1610
|
+
x: {
|
|
1611
|
+
length: "Width",
|
|
1612
|
+
position: "Left",
|
|
1613
|
+
},
|
|
1614
|
+
y: {
|
|
1615
|
+
length: "Height",
|
|
1616
|
+
position: "Top",
|
|
1617
|
+
},
|
|
1618
|
+
};
|
|
1619
|
+
function updateAxisInfo(element, axisName, info, time) {
|
|
1620
|
+
const axis = info[axisName];
|
|
1621
|
+
const { length, position } = keys[axisName];
|
|
1622
|
+
const prev = axis.current;
|
|
1623
|
+
const prevTime = info.time;
|
|
1624
|
+
axis.current = element["scroll" + position];
|
|
1625
|
+
axis.scrollLength = element["scroll" + length] - element["client" + length];
|
|
1626
|
+
axis.offset.length = 0;
|
|
1627
|
+
axis.offset[0] = 0;
|
|
1628
|
+
axis.offset[1] = axis.scrollLength;
|
|
1629
|
+
axis.progress = progress(0, axis.scrollLength, axis.current);
|
|
1630
|
+
const elapsed = time - prevTime;
|
|
1631
|
+
axis.velocity =
|
|
1632
|
+
elapsed > maxElapsed ? 0 : velocityPerSecond(axis.current - prev, elapsed);
|
|
1633
|
+
}
|
|
1634
|
+
function updateScrollInfo(element, info, time) {
|
|
1635
|
+
updateAxisInfo(element, "x", info, time);
|
|
1636
|
+
updateAxisInfo(element, "y", info, time);
|
|
1637
|
+
info.time = time;
|
|
1638
|
+
}
|
|
1639
|
+
|
|
1640
|
+
function calcInset(element, container) {
|
|
1641
|
+
let inset = { x: 0, y: 0 };
|
|
1642
|
+
let current = element;
|
|
1643
|
+
while (current && current !== container) {
|
|
1644
|
+
if (current instanceof HTMLElement) {
|
|
1645
|
+
inset.x += current.offsetLeft;
|
|
1646
|
+
inset.y += current.offsetTop;
|
|
1647
|
+
current = current.offsetParent;
|
|
1648
|
+
}
|
|
1649
|
+
else if (current instanceof SVGGraphicsElement && "getBBox" in current) {
|
|
1650
|
+
const { top, left } = current.getBBox();
|
|
1651
|
+
inset.x += left;
|
|
1652
|
+
inset.y += top;
|
|
1653
|
+
/**
|
|
1654
|
+
* Assign the next parent element as the <svg /> tag.
|
|
1655
|
+
*/
|
|
1656
|
+
while (current && current.tagName !== "svg") {
|
|
1657
|
+
current = current.parentNode;
|
|
1658
|
+
}
|
|
1659
|
+
}
|
|
1660
|
+
}
|
|
1661
|
+
return inset;
|
|
1662
|
+
}
|
|
1663
|
+
|
|
1664
|
+
const ScrollOffset = {
|
|
1665
|
+
Enter: [
|
|
1666
|
+
[0, 1],
|
|
1667
|
+
[1, 1],
|
|
1668
|
+
],
|
|
1669
|
+
Exit: [
|
|
1670
|
+
[0, 0],
|
|
1671
|
+
[1, 0],
|
|
1672
|
+
],
|
|
1673
|
+
Any: [
|
|
1674
|
+
[1, 0],
|
|
1675
|
+
[0, 1],
|
|
1676
|
+
],
|
|
1677
|
+
All: [
|
|
1678
|
+
[0, 0],
|
|
1679
|
+
[1, 1],
|
|
1680
|
+
],
|
|
1681
|
+
};
|
|
1682
|
+
|
|
1683
|
+
const namedEdges = {
|
|
1684
|
+
start: 0,
|
|
1685
|
+
center: 0.5,
|
|
1686
|
+
end: 1,
|
|
1687
|
+
};
|
|
1688
|
+
function resolveEdge(edge, length, inset = 0) {
|
|
1689
|
+
let delta = 0;
|
|
1690
|
+
/**
|
|
1691
|
+
* If we have this edge defined as a preset, replace the definition
|
|
1692
|
+
* with the numerical value.
|
|
1693
|
+
*/
|
|
1694
|
+
if (namedEdges[edge] !== undefined) {
|
|
1695
|
+
edge = namedEdges[edge];
|
|
1696
|
+
}
|
|
1697
|
+
/**
|
|
1698
|
+
* Handle unit values
|
|
1699
|
+
*/
|
|
1700
|
+
if (isString(edge)) {
|
|
1701
|
+
const asNumber = parseFloat(edge);
|
|
1702
|
+
if (edge.endsWith("px")) {
|
|
1703
|
+
delta = asNumber;
|
|
1704
|
+
}
|
|
1705
|
+
else if (edge.endsWith("%")) {
|
|
1706
|
+
edge = asNumber / 100;
|
|
1707
|
+
}
|
|
1708
|
+
else if (edge.endsWith("vw")) {
|
|
1709
|
+
delta = (asNumber / 100) * document.documentElement.clientWidth;
|
|
1710
|
+
}
|
|
1711
|
+
else if (edge.endsWith("vh")) {
|
|
1712
|
+
delta = (asNumber / 100) * document.documentElement.clientHeight;
|
|
1713
|
+
}
|
|
1714
|
+
else {
|
|
1715
|
+
edge = asNumber;
|
|
1716
|
+
}
|
|
1717
|
+
}
|
|
1718
|
+
/**
|
|
1719
|
+
* If the edge is defined as a number, handle as a progress value.
|
|
1720
|
+
*/
|
|
1721
|
+
if (isNumber(edge)) {
|
|
1722
|
+
delta = length * edge;
|
|
1723
|
+
}
|
|
1724
|
+
return inset + delta;
|
|
1725
|
+
}
|
|
1726
|
+
|
|
1727
|
+
const defaultOffset = [0, 0];
|
|
1728
|
+
function resolveOffset(offset, containerLength, targetLength, targetInset) {
|
|
1729
|
+
let offsetDefinition = Array.isArray(offset) ? offset : defaultOffset;
|
|
1730
|
+
let targetPoint = 0;
|
|
1731
|
+
let containerPoint = 0;
|
|
1732
|
+
if (isNumber(offset)) {
|
|
1733
|
+
/**
|
|
1734
|
+
* If we're provided offset: [0, 0.5, 1] then each number x should become
|
|
1735
|
+
* [x, x], so we default to the behaviour of mapping 0 => 0 of both target
|
|
1736
|
+
* and container etc.
|
|
1737
|
+
*/
|
|
1738
|
+
offsetDefinition = [offset, offset];
|
|
1739
|
+
}
|
|
1740
|
+
else if (isString(offset)) {
|
|
1741
|
+
offset = offset.trim();
|
|
1742
|
+
if (offset.includes(" ")) {
|
|
1743
|
+
offsetDefinition = offset.split(" ");
|
|
1744
|
+
}
|
|
1745
|
+
else {
|
|
1746
|
+
/**
|
|
1747
|
+
* If we're provided a definition like "100px" then we want to apply
|
|
1748
|
+
* that only to the top of the target point, leaving the container at 0.
|
|
1749
|
+
* Whereas a named offset like "end" should be applied to both.
|
|
1750
|
+
*/
|
|
1751
|
+
offsetDefinition = [offset, namedEdges[offset] ? offset : `0`];
|
|
1752
|
+
}
|
|
1753
|
+
}
|
|
1754
|
+
targetPoint = resolveEdge(offsetDefinition[0], targetLength, targetInset);
|
|
1755
|
+
containerPoint = resolveEdge(offsetDefinition[1], containerLength);
|
|
1756
|
+
return targetPoint - containerPoint;
|
|
1757
|
+
}
|
|
1758
|
+
|
|
1759
|
+
const point = { x: 0, y: 0 };
|
|
1760
|
+
function resolveOffsets(container, info, options) {
|
|
1761
|
+
let { offset: offsetDefinition = ScrollOffset.All } = options;
|
|
1762
|
+
const { target = container, axis = "y" } = options;
|
|
1763
|
+
const lengthLabel = axis === "y" ? "height" : "width";
|
|
1764
|
+
const inset = target !== container ? calcInset(target, container) : point;
|
|
1765
|
+
/**
|
|
1766
|
+
* Measure the target and container. If they're the same thing then we
|
|
1767
|
+
* use the container's scrollWidth/Height as the target, from there
|
|
1768
|
+
* all other calculations can remain the same.
|
|
1769
|
+
*/
|
|
1770
|
+
const targetSize = target === container
|
|
1771
|
+
? { width: container.scrollWidth, height: container.scrollHeight }
|
|
1772
|
+
: { width: target.clientWidth, height: target.clientHeight };
|
|
1773
|
+
const containerSize = {
|
|
1774
|
+
width: container.clientWidth,
|
|
1775
|
+
height: container.clientHeight,
|
|
1776
|
+
};
|
|
1777
|
+
/**
|
|
1778
|
+
* Reset the length of the resolved offset array rather than creating a new one.
|
|
1779
|
+
* TODO: More reusable data structures for targetSize/containerSize would also be good.
|
|
1780
|
+
*/
|
|
1781
|
+
info[axis].offset.length = 0;
|
|
1782
|
+
/**
|
|
1783
|
+
* Populate the offset array by resolving the user's offset definition into
|
|
1784
|
+
* a list of pixel scroll offets.
|
|
1785
|
+
*/
|
|
1786
|
+
let hasChanged = !info[axis].interpolate;
|
|
1787
|
+
const numOffsets = offsetDefinition.length;
|
|
1788
|
+
for (let i = 0; i < numOffsets; i++) {
|
|
1789
|
+
const offset = resolveOffset(offsetDefinition[i], containerSize[lengthLabel], targetSize[lengthLabel], inset[axis]);
|
|
1790
|
+
if (!hasChanged && offset !== info[axis].interpolatorOffsets[i]) {
|
|
1791
|
+
hasChanged = true;
|
|
1792
|
+
}
|
|
1793
|
+
info[axis].offset[i] = offset;
|
|
1794
|
+
}
|
|
1795
|
+
/**
|
|
1796
|
+
* If the pixel scroll offsets have changed, create a new interpolator function
|
|
1797
|
+
* to map scroll value into a progress.
|
|
1798
|
+
*/
|
|
1799
|
+
if (hasChanged) {
|
|
1800
|
+
info[axis].interpolate = interpolate(defaultOffset$1(numOffsets), info[axis].offset);
|
|
1801
|
+
info[axis].interpolatorOffsets = [...info[axis].offset];
|
|
1802
|
+
}
|
|
1803
|
+
info[axis].progress = info[axis].interpolate(info[axis].current);
|
|
1804
|
+
}
|
|
1805
|
+
|
|
1806
|
+
function measure(container, target = container, info) {
|
|
1807
|
+
/**
|
|
1808
|
+
* Find inset of target within scrollable container
|
|
1809
|
+
*/
|
|
1810
|
+
info.x.targetOffset = 0;
|
|
1811
|
+
info.y.targetOffset = 0;
|
|
1812
|
+
if (target !== container) {
|
|
1813
|
+
let node = target;
|
|
1814
|
+
while (node && node != container) {
|
|
1815
|
+
info.x.targetOffset += node.offsetLeft;
|
|
1816
|
+
info.y.targetOffset += node.offsetTop;
|
|
1817
|
+
node = node.offsetParent;
|
|
1818
|
+
}
|
|
1819
|
+
}
|
|
1820
|
+
info.x.targetLength =
|
|
1821
|
+
target === container ? target.scrollWidth : target.clientWidth;
|
|
1822
|
+
info.y.targetLength =
|
|
1823
|
+
target === container ? target.scrollHeight : target.clientHeight;
|
|
1824
|
+
info.x.containerLength = container.clientWidth;
|
|
1825
|
+
info.y.containerLength = container.clientHeight;
|
|
1826
|
+
}
|
|
1827
|
+
function createOnScrollHandler(element, onScroll, info, options = {}) {
|
|
1828
|
+
const axis = options.axis || "y";
|
|
1829
|
+
return {
|
|
1830
|
+
measure: () => measure(element, options.target, info),
|
|
1831
|
+
update: (time) => {
|
|
1832
|
+
updateScrollInfo(element, info, time);
|
|
1833
|
+
if (options.offset || options.target) {
|
|
1834
|
+
resolveOffsets(element, info, options);
|
|
1835
|
+
}
|
|
1836
|
+
},
|
|
1837
|
+
notify: isFunction(onScroll)
|
|
1838
|
+
? () => onScroll(info)
|
|
1839
|
+
: scrubAnimation(onScroll, info[axis]),
|
|
1840
|
+
};
|
|
1841
|
+
}
|
|
1842
|
+
function scrubAnimation(controls, axisInfo) {
|
|
1843
|
+
controls.pause();
|
|
1844
|
+
controls.forEachNative((animation, { easing }) => {
|
|
1845
|
+
var _a, _b;
|
|
1846
|
+
if (animation.updateDuration) {
|
|
1847
|
+
if (!easing)
|
|
1848
|
+
animation.easing = noopReturn;
|
|
1849
|
+
animation.updateDuration(1);
|
|
1850
|
+
}
|
|
1851
|
+
else {
|
|
1852
|
+
const timingOptions = { duration: 1000 };
|
|
1853
|
+
if (!easing)
|
|
1854
|
+
timingOptions.easing = "linear";
|
|
1855
|
+
(_b = (_a = animation.effect) === null || _a === void 0 ? void 0 : _a.updateTiming) === null || _b === void 0 ? void 0 : _b.call(_a, timingOptions);
|
|
1856
|
+
}
|
|
1857
|
+
});
|
|
1858
|
+
return () => {
|
|
1859
|
+
controls.currentTime = axisInfo.progress;
|
|
1860
|
+
};
|
|
1861
|
+
}
|
|
1862
|
+
|
|
1863
|
+
const scrollListeners = new WeakMap();
|
|
1864
|
+
const resizeListeners = new WeakMap();
|
|
1865
|
+
const onScrollHandlers = new WeakMap();
|
|
1866
|
+
const getEventTarget = (element) => element === document.documentElement ? window : element;
|
|
1867
|
+
function scroll(onScroll, _a = {}) {
|
|
1868
|
+
var { container = document.documentElement } = _a, options = __rest(_a, ["container"]);
|
|
1869
|
+
let containerHandlers = onScrollHandlers.get(container);
|
|
1870
|
+
/**
|
|
1871
|
+
* Get the onScroll handlers for this container.
|
|
1872
|
+
* If one isn't found, create a new one.
|
|
1873
|
+
*/
|
|
1874
|
+
if (!containerHandlers) {
|
|
1875
|
+
containerHandlers = new Set();
|
|
1876
|
+
onScrollHandlers.set(container, containerHandlers);
|
|
1877
|
+
}
|
|
1878
|
+
/**
|
|
1879
|
+
* Create a new onScroll handler for the provided callback.
|
|
1880
|
+
*/
|
|
1881
|
+
const info = createScrollInfo();
|
|
1882
|
+
const containerHandler = createOnScrollHandler(container, onScroll, info, options);
|
|
1883
|
+
containerHandlers.add(containerHandler);
|
|
1884
|
+
/**
|
|
1885
|
+
* Check if there's a scroll event listener for this container.
|
|
1886
|
+
* If not, create one.
|
|
1887
|
+
*/
|
|
1888
|
+
if (!scrollListeners.has(container)) {
|
|
1889
|
+
const listener = () => {
|
|
1890
|
+
const time = performance.now();
|
|
1891
|
+
for (const handler of containerHandlers)
|
|
1892
|
+
handler.measure();
|
|
1893
|
+
for (const handler of containerHandlers)
|
|
1894
|
+
handler.update(time);
|
|
1895
|
+
for (const handler of containerHandlers)
|
|
1896
|
+
handler.notify();
|
|
1897
|
+
};
|
|
1898
|
+
scrollListeners.set(container, listener);
|
|
1899
|
+
const target = getEventTarget(container);
|
|
1900
|
+
window.addEventListener("resize", listener, { passive: true });
|
|
1901
|
+
if (container !== document.documentElement) {
|
|
1902
|
+
resizeListeners.set(container, resize(container, listener));
|
|
1903
|
+
}
|
|
1904
|
+
target.addEventListener("scroll", listener, { passive: true });
|
|
1905
|
+
}
|
|
1906
|
+
const listener = scrollListeners.get(container);
|
|
1907
|
+
const onLoadProcesss = requestAnimationFrame(listener);
|
|
1908
|
+
return () => {
|
|
1909
|
+
var _a;
|
|
1910
|
+
if (typeof onScroll !== "function")
|
|
1911
|
+
onScroll.stop();
|
|
1912
|
+
cancelAnimationFrame(onLoadProcesss);
|
|
1913
|
+
/**
|
|
1914
|
+
* Check if we even have any handlers for this container.
|
|
1915
|
+
*/
|
|
1916
|
+
const containerHandlers = onScrollHandlers.get(container);
|
|
1917
|
+
if (!containerHandlers)
|
|
1918
|
+
return;
|
|
1919
|
+
containerHandlers.delete(containerHandler);
|
|
1920
|
+
if (containerHandlers.size)
|
|
1921
|
+
return;
|
|
1922
|
+
/**
|
|
1923
|
+
* If no more handlers, remove the scroll listener too.
|
|
1924
|
+
*/
|
|
1925
|
+
const listener = scrollListeners.get(container);
|
|
1926
|
+
scrollListeners.delete(container);
|
|
1927
|
+
if (listener) {
|
|
1928
|
+
getEventTarget(container).removeEventListener("scroll", listener);
|
|
1929
|
+
(_a = resizeListeners.get(container)) === null || _a === void 0 ? void 0 : _a();
|
|
1930
|
+
window.removeEventListener("resize", listener);
|
|
1931
|
+
}
|
|
1932
|
+
};
|
|
1933
|
+
}
|
|
1934
|
+
|
|
1935
|
+
function hasChanged(a, b) {
|
|
1936
|
+
if (typeof a !== typeof b)
|
|
1937
|
+
return true;
|
|
1938
|
+
if (Array.isArray(a) && Array.isArray(b))
|
|
1939
|
+
return !shallowCompare(a, b);
|
|
1940
|
+
return a !== b;
|
|
1941
|
+
}
|
|
1942
|
+
function shallowCompare(next, prev) {
|
|
1943
|
+
const prevLength = prev.length;
|
|
1944
|
+
if (prevLength !== next.length)
|
|
1945
|
+
return false;
|
|
1946
|
+
for (let i = 0; i < prevLength; i++) {
|
|
1947
|
+
if (prev[i] !== next[i])
|
|
1948
|
+
return false;
|
|
1949
|
+
}
|
|
1950
|
+
return true;
|
|
1951
|
+
}
|
|
1952
|
+
|
|
1953
|
+
function isVariant(definition) {
|
|
1954
|
+
return typeof definition === "object";
|
|
1955
|
+
}
|
|
1956
|
+
|
|
1957
|
+
function resolveVariant(definition, variants) {
|
|
1958
|
+
if (isVariant(definition)) {
|
|
1959
|
+
return definition;
|
|
1960
|
+
}
|
|
1961
|
+
else if (definition && variants) {
|
|
1962
|
+
return variants[definition];
|
|
1963
|
+
}
|
|
1964
|
+
}
|
|
1965
|
+
|
|
1966
|
+
let scheduled = undefined;
|
|
1967
|
+
function processScheduledAnimations() {
|
|
1968
|
+
if (!scheduled)
|
|
1969
|
+
return;
|
|
1970
|
+
const generators = scheduled.sort(compareByDepth).map(fireAnimateUpdates);
|
|
1971
|
+
generators.forEach(fireNext);
|
|
1972
|
+
generators.forEach(fireNext);
|
|
1973
|
+
scheduled = undefined;
|
|
1974
|
+
}
|
|
1975
|
+
function scheduleAnimation(state) {
|
|
1976
|
+
if (!scheduled) {
|
|
1977
|
+
scheduled = [state];
|
|
1978
|
+
requestAnimationFrame(processScheduledAnimations);
|
|
1979
|
+
}
|
|
1980
|
+
else {
|
|
1981
|
+
addUniqueItem(scheduled, state);
|
|
1982
|
+
}
|
|
1983
|
+
}
|
|
1984
|
+
function unscheduleAnimation(state) {
|
|
1985
|
+
scheduled && removeItem(scheduled, state);
|
|
1986
|
+
}
|
|
1987
|
+
const compareByDepth = (a, b) => a.getDepth() - b.getDepth();
|
|
1988
|
+
const fireAnimateUpdates = (state) => state.animateUpdates();
|
|
1989
|
+
const fireNext = (iterator) => iterator.next();
|
|
1990
|
+
|
|
1991
|
+
const motionEvent = (name, target) => new CustomEvent(name, { detail: { target } });
|
|
1992
|
+
function dispatchPointerEvent(element, name, event) {
|
|
1993
|
+
element.dispatchEvent(new CustomEvent(name, { detail: { originalEvent: event } }));
|
|
1994
|
+
}
|
|
1995
|
+
function dispatchViewEvent(element, name, entry) {
|
|
1996
|
+
element.dispatchEvent(new CustomEvent(name, { detail: { originalEntry: entry } }));
|
|
1997
|
+
}
|
|
1998
|
+
|
|
1999
|
+
const inView = {
|
|
2000
|
+
isActive: (options) => Boolean(options.inView),
|
|
2001
|
+
subscribe: (element, { enable, disable }, { inViewOptions = {} }) => {
|
|
2002
|
+
const { once } = inViewOptions, viewOptions = __rest(inViewOptions, ["once"]);
|
|
2003
|
+
return inView$1(element, (enterEntry) => {
|
|
2004
|
+
enable();
|
|
2005
|
+
dispatchViewEvent(element, "viewenter", enterEntry);
|
|
2006
|
+
if (!once) {
|
|
2007
|
+
return (leaveEntry) => {
|
|
2008
|
+
disable();
|
|
2009
|
+
dispatchViewEvent(element, "viewleave", leaveEntry);
|
|
2010
|
+
};
|
|
2011
|
+
}
|
|
2012
|
+
}, viewOptions);
|
|
2013
|
+
},
|
|
2014
|
+
};
|
|
2015
|
+
|
|
2016
|
+
const mouseEvent = (element, name, action) => (event) => {
|
|
2017
|
+
if (event.pointerType && event.pointerType !== "mouse")
|
|
2018
|
+
return;
|
|
2019
|
+
action();
|
|
2020
|
+
dispatchPointerEvent(element, name, event);
|
|
2021
|
+
};
|
|
2022
|
+
const hover = {
|
|
2023
|
+
isActive: (options) => Boolean(options.hover),
|
|
2024
|
+
subscribe: (element, { enable, disable }) => {
|
|
2025
|
+
const onEnter = mouseEvent(element, "hoverstart", enable);
|
|
2026
|
+
const onLeave = mouseEvent(element, "hoverend", disable);
|
|
2027
|
+
element.addEventListener("pointerenter", onEnter);
|
|
2028
|
+
element.addEventListener("pointerleave", onLeave);
|
|
2029
|
+
return () => {
|
|
2030
|
+
element.removeEventListener("pointerenter", onEnter);
|
|
2031
|
+
element.removeEventListener("pointerleave", onLeave);
|
|
2032
|
+
};
|
|
2033
|
+
},
|
|
2034
|
+
};
|
|
2035
|
+
|
|
2036
|
+
const press = {
|
|
2037
|
+
isActive: (options) => Boolean(options.press),
|
|
2038
|
+
subscribe: (element, { enable, disable }) => {
|
|
2039
|
+
const onPointerUp = (event) => {
|
|
2040
|
+
disable();
|
|
2041
|
+
dispatchPointerEvent(element, "pressend", event);
|
|
2042
|
+
window.removeEventListener("pointerup", onPointerUp);
|
|
2043
|
+
};
|
|
2044
|
+
const onPointerDown = (event) => {
|
|
2045
|
+
enable();
|
|
2046
|
+
dispatchPointerEvent(element, "pressstart", event);
|
|
2047
|
+
window.addEventListener("pointerup", onPointerUp);
|
|
2048
|
+
};
|
|
2049
|
+
element.addEventListener("pointerdown", onPointerDown);
|
|
2050
|
+
return () => {
|
|
2051
|
+
element.removeEventListener("pointerdown", onPointerDown);
|
|
2052
|
+
window.removeEventListener("pointerup", onPointerUp);
|
|
2053
|
+
};
|
|
2054
|
+
},
|
|
2055
|
+
};
|
|
2056
|
+
|
|
2057
|
+
const gestures = { inView, hover, press };
|
|
2058
|
+
/**
|
|
2059
|
+
* A list of state types, in priority order. If a value is defined in
|
|
2060
|
+
* a righter-most type, it will override any definition in a lefter-most.
|
|
2061
|
+
*/
|
|
2062
|
+
const stateTypes = ["initial", "animate", ...Object.keys(gestures), "exit"];
|
|
2063
|
+
/**
|
|
2064
|
+
* A global store of all generated motion states. This can be used to lookup
|
|
2065
|
+
* a motion state for a given Element.
|
|
2066
|
+
*/
|
|
2067
|
+
const mountedStates = new WeakMap();
|
|
2068
|
+
function createMotionState(options = {}, parent) {
|
|
2069
|
+
/**
|
|
2070
|
+
* The element represented by the motion state. This is an empty reference
|
|
2071
|
+
* when we create the state to support SSR and allow for later mounting
|
|
2072
|
+
* in view libraries.
|
|
2073
|
+
*
|
|
2074
|
+
* @ts-ignore
|
|
2075
|
+
*/
|
|
2076
|
+
let element;
|
|
2077
|
+
/**
|
|
2078
|
+
* Calculate a depth that we can use to order motion states by tree depth.
|
|
2079
|
+
*/
|
|
2080
|
+
let depth = parent ? parent.getDepth() + 1 : 0;
|
|
2081
|
+
/**
|
|
2082
|
+
* Track which states are currently active.
|
|
2083
|
+
*/
|
|
2084
|
+
const activeStates = { initial: true, animate: true };
|
|
2085
|
+
/**
|
|
2086
|
+
* A map of functions that, when called, will remove event listeners for
|
|
2087
|
+
* a given gesture.
|
|
2088
|
+
*/
|
|
2089
|
+
const gestureSubscriptions = {};
|
|
2090
|
+
/**
|
|
2091
|
+
* Initialise a context to share through motion states. This
|
|
2092
|
+
* will be populated by variant names (if any).
|
|
2093
|
+
*/
|
|
2094
|
+
const context = {};
|
|
2095
|
+
for (const name of stateTypes) {
|
|
2096
|
+
context[name] =
|
|
2097
|
+
typeof options[name] === "string"
|
|
2098
|
+
? options[name]
|
|
2099
|
+
: parent === null || parent === void 0 ? void 0 : parent.getContext()[name];
|
|
2100
|
+
}
|
|
2101
|
+
/**
|
|
2102
|
+
* If initial is set to false we use the animate prop as the initial
|
|
2103
|
+
* animation state.
|
|
2104
|
+
*/
|
|
2105
|
+
const initialVariantSource = options.initial === false ? "animate" : "initial";
|
|
2106
|
+
/**
|
|
2107
|
+
* Destructure an initial target out from the resolved initial variant.
|
|
2108
|
+
*/
|
|
2109
|
+
let _a = resolveVariant(options[initialVariantSource] || context[initialVariantSource], options.variants) || {}, target = __rest(_a, ["transition"]);
|
|
2110
|
+
/**
|
|
2111
|
+
* The base target is a cached map of values that we'll use to animate
|
|
2112
|
+
* back to if a value is removed from all active state types. This
|
|
2113
|
+
* is usually the initial value as read from the DOM, for instance if
|
|
2114
|
+
* it hasn't been defined in initial.
|
|
2115
|
+
*/
|
|
2116
|
+
const baseTarget = Object.assign({}, target);
|
|
2117
|
+
/**
|
|
2118
|
+
* A generator that will be processed by the global animation scheduler.
|
|
2119
|
+
* This yeilds when it switches from reading the DOM to writing to it
|
|
2120
|
+
* to prevent layout thrashing.
|
|
2121
|
+
*/
|
|
2122
|
+
function* animateUpdates() {
|
|
2123
|
+
var _a, _b;
|
|
2124
|
+
const prevTarget = target;
|
|
2125
|
+
target = {};
|
|
2126
|
+
const animationOptions = {};
|
|
2127
|
+
for (const name of stateTypes) {
|
|
2128
|
+
if (!activeStates[name])
|
|
2129
|
+
continue;
|
|
2130
|
+
const variant = resolveVariant(options[name]);
|
|
2131
|
+
if (!variant)
|
|
2132
|
+
continue;
|
|
2133
|
+
for (const key in variant) {
|
|
2134
|
+
if (key === "transition")
|
|
2135
|
+
continue;
|
|
2136
|
+
target[key] = variant[key];
|
|
2137
|
+
animationOptions[key] = getOptions((_b = (_a = variant.transition) !== null && _a !== void 0 ? _a : options.transition) !== null && _b !== void 0 ? _b : {}, key);
|
|
2138
|
+
}
|
|
2139
|
+
}
|
|
2140
|
+
const allTargetKeys = new Set([
|
|
2141
|
+
...Object.keys(target),
|
|
2142
|
+
...Object.keys(prevTarget),
|
|
2143
|
+
]);
|
|
2144
|
+
const animationFactories = [];
|
|
2145
|
+
allTargetKeys.forEach((key) => {
|
|
2146
|
+
var _a;
|
|
2147
|
+
if (target[key] === undefined) {
|
|
2148
|
+
target[key] = baseTarget[key];
|
|
2149
|
+
}
|
|
2150
|
+
if (hasChanged(prevTarget[key], target[key])) {
|
|
2151
|
+
(_a = baseTarget[key]) !== null && _a !== void 0 ? _a : (baseTarget[key] = style.get(element, key));
|
|
2152
|
+
animationFactories.push(animateStyle(element, key, target[key], animationOptions[key]));
|
|
2153
|
+
}
|
|
2154
|
+
});
|
|
2155
|
+
// Wait for all animation states to read from the DOM
|
|
2156
|
+
yield;
|
|
2157
|
+
const animations = animationFactories
|
|
2158
|
+
.map((factory) => factory())
|
|
2159
|
+
.filter(Boolean);
|
|
2160
|
+
if (!animations.length)
|
|
2161
|
+
return;
|
|
2162
|
+
const animationTarget = target;
|
|
2163
|
+
element.dispatchEvent(motionEvent("motionstart", animationTarget));
|
|
2164
|
+
Promise.all(animations.map((animation) => animation.finished))
|
|
2165
|
+
.then(() => {
|
|
2166
|
+
element.dispatchEvent(motionEvent("motioncomplete", animationTarget));
|
|
2167
|
+
})
|
|
2168
|
+
.catch(noop);
|
|
2169
|
+
}
|
|
2170
|
+
const setGesture = (name, isActive) => () => {
|
|
2171
|
+
activeStates[name] = isActive;
|
|
2172
|
+
scheduleAnimation(state);
|
|
2173
|
+
};
|
|
2174
|
+
const updateGestureSubscriptions = () => {
|
|
2175
|
+
for (const name in gestures) {
|
|
2176
|
+
const isGestureActive = gestures[name].isActive(options);
|
|
2177
|
+
const remove = gestureSubscriptions[name];
|
|
2178
|
+
if (isGestureActive && !remove) {
|
|
2179
|
+
gestureSubscriptions[name] = gestures[name].subscribe(element, {
|
|
2180
|
+
enable: setGesture(name, true),
|
|
2181
|
+
disable: setGesture(name, false),
|
|
2182
|
+
}, options);
|
|
2183
|
+
}
|
|
2184
|
+
else if (!isGestureActive && remove) {
|
|
2185
|
+
remove();
|
|
2186
|
+
delete gestureSubscriptions[name];
|
|
2187
|
+
}
|
|
2188
|
+
}
|
|
2189
|
+
};
|
|
2190
|
+
const state = {
|
|
2191
|
+
update: (newOptions) => {
|
|
2192
|
+
if (!element)
|
|
2193
|
+
return;
|
|
2194
|
+
options = newOptions;
|
|
2195
|
+
updateGestureSubscriptions();
|
|
2196
|
+
scheduleAnimation(state);
|
|
2197
|
+
},
|
|
2198
|
+
setActive: (name, isActive) => {
|
|
2199
|
+
if (!element)
|
|
2200
|
+
return;
|
|
2201
|
+
activeStates[name] = isActive;
|
|
2202
|
+
scheduleAnimation(state);
|
|
2203
|
+
},
|
|
2204
|
+
animateUpdates,
|
|
2205
|
+
getDepth: () => depth,
|
|
2206
|
+
getTarget: () => target,
|
|
2207
|
+
getOptions: () => options,
|
|
2208
|
+
getContext: () => context,
|
|
2209
|
+
mount: (newElement) => {
|
|
2210
|
+
invariant(Boolean(newElement), "Animation state must be mounted with valid Element");
|
|
2211
|
+
element = newElement;
|
|
2212
|
+
mountedStates.set(element, state);
|
|
2213
|
+
updateGestureSubscriptions();
|
|
2214
|
+
return () => {
|
|
2215
|
+
mountedStates.delete(element);
|
|
2216
|
+
unscheduleAnimation(state);
|
|
2217
|
+
for (const key in gestureSubscriptions) {
|
|
2218
|
+
gestureSubscriptions[key]();
|
|
2219
|
+
}
|
|
2220
|
+
};
|
|
2221
|
+
},
|
|
2222
|
+
isMounted: () => Boolean(element),
|
|
2223
|
+
};
|
|
2224
|
+
return state;
|
|
2225
|
+
}
|
|
2226
|
+
|
|
2227
|
+
function createStyles(keyframes) {
|
|
2228
|
+
const initialKeyframes = {};
|
|
2229
|
+
const transformKeys = [];
|
|
2230
|
+
for (let key in keyframes) {
|
|
2231
|
+
const value = keyframes[key];
|
|
2232
|
+
if (isTransform(key)) {
|
|
2233
|
+
if (transformAlias[key])
|
|
2234
|
+
key = transformAlias[key];
|
|
2235
|
+
transformKeys.push(key);
|
|
2236
|
+
key = asTransformCssVar(key);
|
|
2237
|
+
}
|
|
2238
|
+
let initialKeyframe = Array.isArray(value) ? value[0] : value;
|
|
2239
|
+
/**
|
|
2240
|
+
* If this is a number and we have a default value type, convert the number
|
|
2241
|
+
* to this type.
|
|
2242
|
+
*/
|
|
2243
|
+
const definition = transformDefinitions.get(key);
|
|
2244
|
+
if (definition) {
|
|
2245
|
+
initialKeyframe = isNumber(value)
|
|
2246
|
+
? definition.toDefaultUnit(value)
|
|
2247
|
+
: value;
|
|
2248
|
+
}
|
|
2249
|
+
initialKeyframes[key] = initialKeyframe;
|
|
2250
|
+
}
|
|
2251
|
+
if (transformKeys.length) {
|
|
2252
|
+
initialKeyframes.transform = buildTransformTemplate(transformKeys);
|
|
2253
|
+
}
|
|
2254
|
+
return initialKeyframes;
|
|
2255
|
+
}
|
|
2256
|
+
|
|
2257
|
+
const camelLetterToPipeLetter = (letter) => `-${letter.toLowerCase()}`;
|
|
2258
|
+
const camelToPipeCase = (str) => str.replace(/[A-Z]/g, camelLetterToPipeLetter);
|
|
2259
|
+
function createStyleString(target = {}) {
|
|
2260
|
+
const styles = createStyles(target);
|
|
2261
|
+
let style = "";
|
|
2262
|
+
for (const key in styles) {
|
|
2263
|
+
style += key.startsWith("--") ? key : camelToPipeCase(key);
|
|
2264
|
+
style += `: ${styles[key]}; `;
|
|
2265
|
+
}
|
|
2266
|
+
return style;
|
|
2267
|
+
}
|
|
2268
|
+
|
|
2269
|
+
function animateProgress(target, options = {}) {
|
|
2270
|
+
return withControls([
|
|
1427
2271
|
() => {
|
|
1428
2272
|
const animation = new Animation(target, [0, 1], options);
|
|
1429
2273
|
animation.finished.catch(() => { });
|
|
1430
2274
|
return animation;
|
|
1431
2275
|
},
|
|
1432
|
-
], options
|
|
2276
|
+
], options, options.duration);
|
|
1433
2277
|
}
|
|
1434
2278
|
function animate(target, keyframesOrOptions, options) {
|
|
1435
|
-
const
|
|
1436
|
-
return
|
|
2279
|
+
const factory = isFunction(target) ? animateProgress : animate$1;
|
|
2280
|
+
return factory(target, keyframesOrOptions, options);
|
|
1437
2281
|
}
|
|
1438
2282
|
|
|
1439
2283
|
exports.MotionValue = MotionValue;
|
|
2284
|
+
exports.ScrollOffset = ScrollOffset;
|
|
1440
2285
|
exports.animate = animate;
|
|
2286
|
+
exports.animateStyle = animateStyle;
|
|
2287
|
+
exports.createMotionState = createMotionState;
|
|
2288
|
+
exports.createStyleString = createStyleString;
|
|
2289
|
+
exports.createStyles = createStyles;
|
|
2290
|
+
exports.getAnimationData = getAnimationData;
|
|
2291
|
+
exports.getStyleName = getStyleName;
|
|
1441
2292
|
exports.glide = glide;
|
|
1442
|
-
exports.inView = inView;
|
|
2293
|
+
exports.inView = inView$1;
|
|
2294
|
+
exports.mountedStates = mountedStates;
|
|
2295
|
+
exports.resize = resize;
|
|
2296
|
+
exports.scroll = scroll;
|
|
1443
2297
|
exports.spring = spring;
|
|
1444
2298
|
exports.stagger = stagger;
|
|
1445
2299
|
exports.style = style;
|
|
1446
2300
|
exports.timeline = timeline;
|
|
2301
|
+
exports.withControls = withControls;
|
|
1447
2302
|
|
|
1448
2303
|
Object.defineProperty(exports, '__esModule', { value: true });
|
|
1449
2304
|
|