framer-motion 12.4.13 → 12.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/client.js +1 -1
- package/dist/cjs/{create-DkTZDHiS.js → create-BErQMR-o.js} +4234 -4792
- package/dist/cjs/debug.js +5 -281
- package/dist/cjs/dom-mini.js +9 -7
- package/dist/cjs/dom.js +81 -639
- package/dist/cjs/index.js +1555 -1553
- package/dist/cjs/m.js +11 -179
- package/dist/cjs/mini.js +8 -0
- package/dist/debug.d.ts +2 -35
- package/dist/dom-mini.d.ts +1 -181
- package/dist/dom-mini.js +1 -1
- package/dist/dom.d.ts +3 -242
- package/dist/dom.js +1 -1
- package/dist/es/animation/animate/single-value.mjs +1 -1
- package/dist/es/animation/animators/BaseAnimation.mjs +1 -1
- package/dist/es/animation/animators/MainThreadAnimation.mjs +1 -2
- package/dist/es/animation/animators/drivers/driver-frameloop.mjs +1 -2
- package/dist/es/animation/animators/waapi/index.mjs +1 -3
- package/dist/es/animation/generators/utils/velocity.mjs +1 -1
- package/dist/es/animation/interfaces/motion-value.mjs +2 -4
- package/dist/es/animation/interfaces/visual-element-target.mjs +1 -2
- package/dist/es/animation/optimized-appear/start.mjs +3 -3
- package/dist/es/animation/sequence/utils/edit.mjs +1 -1
- package/dist/es/components/AnimatePresence/index.mjs +1 -1
- package/dist/es/components/Reorder/utils/check-reorder.mjs +1 -1
- package/dist/es/debug.mjs +1 -1
- package/dist/es/dom.mjs +1 -5
- package/dist/es/gestures/drag/VisualElementDragControls.mjs +1 -2
- package/dist/es/gestures/hover.mjs +1 -2
- package/dist/es/gestures/pan/PanSession.mjs +1 -2
- package/dist/es/gestures/pan/index.mjs +1 -1
- package/dist/es/gestures/press.mjs +1 -2
- package/dist/es/index.mjs +14 -19
- package/dist/es/motion/features/layout/MeasureLayout.mjs +1 -2
- package/dist/es/motion/utils/use-visual-element.mjs +6 -6
- package/dist/es/projection/node/create-projection-node.mjs +2 -8
- package/dist/es/projection/shared/stack.mjs +1 -1
- package/dist/es/projection.mjs +1 -3
- package/dist/es/render/VisualElement.mjs +2 -5
- package/dist/es/render/components/create-proxy.mjs +1 -1
- package/dist/es/render/dom/DOMVisualElement.mjs +1 -1
- package/dist/es/render/dom/scroll/info.mjs +1 -2
- package/dist/es/render/dom/scroll/observe.mjs +1 -1
- package/dist/es/render/dom/scroll/on-scroll-handler.mjs +1 -1
- package/dist/es/render/dom/scroll/track.mjs +1 -1
- package/dist/es/render/svg/SVGVisualElement.mjs +1 -1
- package/dist/es/render/svg/config-motion.mjs +1 -1
- package/dist/es/render/utils/KeyframesResolver.mjs +1 -1
- package/dist/es/render/utils/flat-tree.mjs +1 -1
- package/dist/es/render/utils/motion-values.mjs +3 -3
- package/dist/es/render/utils/setters.mjs +1 -1
- package/dist/es/utils/delay.mjs +1 -2
- package/dist/es/utils/reduced-motion/use-reduced-motion.mjs +1 -1
- package/dist/es/utils/use-animation-frame.mjs +1 -1
- package/dist/es/utils/use-force-update.mjs +1 -1
- package/dist/es/utils/use-instant-transition.mjs +1 -1
- package/dist/es/value/scroll/use-element-scroll.mjs +1 -1
- package/dist/es/value/scroll/use-viewport-scroll.mjs +1 -1
- package/dist/es/value/use-combine-values.mjs +2 -2
- package/dist/es/value/use-computed.mjs +1 -1
- package/dist/es/value/use-inverted-scale.mjs +3 -3
- package/dist/es/value/use-motion-value.mjs +1 -1
- package/dist/es/value/use-scroll.mjs +4 -4
- package/dist/es/value/use-spring.mjs +1 -1
- package/dist/es/value/use-transform.mjs +1 -1
- package/dist/es/value/use-velocity.mjs +1 -1
- package/dist/es/value/use-will-change/WillChangeMotionValue.mjs +2 -2
- package/dist/framer-motion.dev.js +8227 -8251
- package/dist/framer-motion.js +1 -1
- package/dist/m.d.ts +49 -241
- package/dist/size-rollup-animate.js +1 -1
- package/dist/size-rollup-dom-animation-assets.js +1 -1
- package/dist/size-rollup-dom-animation.js +1 -1
- package/dist/size-rollup-dom-max-assets.js +1 -1
- package/dist/size-rollup-dom-max.js +1 -1
- package/dist/size-rollup-m.js +1 -1
- package/dist/size-rollup-motion.js +1 -1
- package/dist/size-rollup-scroll.js +1 -1
- package/dist/types/client.d.ts +2 -2
- package/dist/types/index.d.ts +43 -79
- package/dist/{types.d-6pKw1mTI.d.ts → types.d-B50aGbjN.d.ts} +81 -289
- package/package.json +4 -6
- package/dist/es/frameloop/batcher.mjs +0 -69
- package/dist/es/frameloop/frame.mjs +0 -6
- package/dist/es/frameloop/index-legacy.mjs +0 -20
- package/dist/es/frameloop/microtask.mjs +0 -5
- package/dist/es/frameloop/order.mjs +0 -10
- package/dist/es/frameloop/render-step.mjs +0 -92
- package/dist/es/frameloop/sync-time.mjs +0 -31
- package/dist/es/stats/animation-count.mjs +0 -7
- package/dist/es/stats/buffer.mjs +0 -6
- package/dist/es/stats/index.mjs +0 -113
- package/dist/es/utils/GlobalConfig.mjs +0 -6
- package/dist/es/utils/array.mjs +0 -21
- package/dist/es/utils/subscription-manager.mjs +0 -40
- package/dist/es/utils/velocity-per-second.mjs +0 -11
- package/dist/es/utils/warn-once.mjs +0 -11
- package/dist/es/value/index.mjs +0 -319
- package/dist/three.d.ts +0 -2833
package/dist/cjs/index.js
CHANGED
|
@@ -4,9 +4,9 @@ Object.defineProperty(exports, '__esModule', { value: true });
|
|
|
4
4
|
|
|
5
5
|
var jsxRuntime = require('react/jsx-runtime');
|
|
6
6
|
var React = require('react');
|
|
7
|
-
var create = require('./create-
|
|
8
|
-
var motionUtils = require('motion-utils');
|
|
7
|
+
var create = require('./create-BErQMR-o.js');
|
|
9
8
|
var motionDom = require('motion-dom');
|
|
9
|
+
var motionUtils = require('motion-utils');
|
|
10
10
|
|
|
11
11
|
function _interopNamespaceDefault(e) {
|
|
12
12
|
var n = Object.create(null);
|
|
@@ -27,35 +27,6 @@ function _interopNamespaceDefault(e) {
|
|
|
27
27
|
|
|
28
28
|
var React__namespace = /*#__PURE__*/_interopNamespaceDefault(React);
|
|
29
29
|
|
|
30
|
-
function useUnmountEffect(callback) {
|
|
31
|
-
return React.useEffect(() => () => callback(), []);
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
function useIsMounted() {
|
|
35
|
-
const isMounted = React.useRef(false);
|
|
36
|
-
create.useIsomorphicLayoutEffect(() => {
|
|
37
|
-
isMounted.current = true;
|
|
38
|
-
return () => {
|
|
39
|
-
isMounted.current = false;
|
|
40
|
-
};
|
|
41
|
-
}, []);
|
|
42
|
-
return isMounted;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
function useForceUpdate() {
|
|
46
|
-
const isMounted = useIsMounted();
|
|
47
|
-
const [forcedRenderCount, setForcedRenderCount] = React.useState(0);
|
|
48
|
-
const forceRender = React.useCallback(() => {
|
|
49
|
-
isMounted.current && setForcedRenderCount(forcedRenderCount + 1);
|
|
50
|
-
}, [forcedRenderCount]);
|
|
51
|
-
/**
|
|
52
|
-
* Defer this to the end of the next animation frame in case there are multiple
|
|
53
|
-
* synchronous calls.
|
|
54
|
-
*/
|
|
55
|
-
const deferredForceRender = React.useCallback(() => create.frame.postRender(forceRender), [forceRender]);
|
|
56
|
-
return [deferredForceRender, forcedRenderCount];
|
|
57
|
-
}
|
|
58
|
-
|
|
59
30
|
/**
|
|
60
31
|
* Measurement functionality has to be within a separate component
|
|
61
32
|
* to leverage snapshot lifecycle.
|
|
@@ -379,1684 +350,1697 @@ function nodeGroup() {
|
|
|
379
350
|
};
|
|
380
351
|
}
|
|
381
352
|
|
|
382
|
-
|
|
383
|
-
const
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
353
|
+
function useIsMounted() {
|
|
354
|
+
const isMounted = React.useRef(false);
|
|
355
|
+
create.useIsomorphicLayoutEffect(() => {
|
|
356
|
+
isMounted.current = true;
|
|
357
|
+
return () => {
|
|
358
|
+
isMounted.current = false;
|
|
359
|
+
};
|
|
360
|
+
}, []);
|
|
361
|
+
return isMounted;
|
|
389
362
|
}
|
|
390
363
|
|
|
391
|
-
function
|
|
392
|
-
|
|
364
|
+
function useForceUpdate() {
|
|
365
|
+
const isMounted = useIsMounted();
|
|
366
|
+
const [forcedRenderCount, setForcedRenderCount] = React.useState(0);
|
|
367
|
+
const forceRender = React.useCallback(() => {
|
|
368
|
+
isMounted.current && setForcedRenderCount(forcedRenderCount + 1);
|
|
369
|
+
}, [forcedRenderCount]);
|
|
370
|
+
/**
|
|
371
|
+
* Defer this to the end of the next animation frame in case there are multiple
|
|
372
|
+
* synchronous calls.
|
|
373
|
+
*/
|
|
374
|
+
const deferredForceRender = React.useCallback(() => motionDom.frame.postRender(forceRender), [forceRender]);
|
|
375
|
+
return [deferredForceRender, forcedRenderCount];
|
|
393
376
|
}
|
|
394
377
|
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
378
|
+
const shouldInheritGroup = (inherit) => inherit === true;
|
|
379
|
+
const shouldInheritId = (inherit) => shouldInheritGroup(inherit === true) || inherit === "id";
|
|
380
|
+
const LayoutGroup = ({ children, id, inherit = true }) => {
|
|
381
|
+
const layoutGroupContext = React.useContext(create.LayoutGroupContext);
|
|
382
|
+
const deprecatedLayoutGroupContext = React.useContext(DeprecatedLayoutGroupContext);
|
|
383
|
+
const [forceRender, key] = useForceUpdate();
|
|
384
|
+
const context = React.useRef(null);
|
|
385
|
+
const upstreamId = layoutGroupContext.id || deprecatedLayoutGroupContext;
|
|
386
|
+
if (context.current === null) {
|
|
387
|
+
if (shouldInheritId(inherit) && upstreamId) {
|
|
388
|
+
id = id ? upstreamId + "-" + id : upstreamId;
|
|
389
|
+
}
|
|
390
|
+
context.current = {
|
|
391
|
+
id,
|
|
392
|
+
group: shouldInheritGroup(inherit)
|
|
393
|
+
? layoutGroupContext.group || nodeGroup()
|
|
394
|
+
: nodeGroup(),
|
|
395
|
+
};
|
|
407
396
|
}
|
|
408
|
-
}
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
return duration * (repeat + 1);
|
|
412
|
-
}
|
|
397
|
+
const memoizedContext = React.useMemo(() => ({ ...context.current, forceRender }), [key]);
|
|
398
|
+
return (jsxRuntime.jsx(create.LayoutGroupContext.Provider, { value: memoizedContext, children: children }));
|
|
399
|
+
};
|
|
413
400
|
|
|
414
401
|
/**
|
|
415
|
-
*
|
|
416
|
-
*
|
|
402
|
+
* Used in conjunction with the `m` component to reduce bundle size.
|
|
403
|
+
*
|
|
404
|
+
* `m` is a version of the `motion` component that only loads functionality
|
|
405
|
+
* critical for the initial render.
|
|
406
|
+
*
|
|
407
|
+
* `LazyMotion` can then be used to either synchronously or asynchronously
|
|
408
|
+
* load animation and gesture support.
|
|
409
|
+
*
|
|
410
|
+
* ```jsx
|
|
411
|
+
* // Synchronous loading
|
|
412
|
+
* import { LazyMotion, m, domAnimation } from "framer-motion"
|
|
413
|
+
*
|
|
414
|
+
* function App() {
|
|
415
|
+
* return (
|
|
416
|
+
* <LazyMotion features={domAnimation}>
|
|
417
|
+
* <m.div animate={{ scale: 2 }} />
|
|
418
|
+
* </LazyMotion>
|
|
419
|
+
* )
|
|
420
|
+
* }
|
|
421
|
+
*
|
|
422
|
+
* // Asynchronous loading
|
|
423
|
+
* import { LazyMotion, m } from "framer-motion"
|
|
424
|
+
*
|
|
425
|
+
* function App() {
|
|
426
|
+
* return (
|
|
427
|
+
* <LazyMotion features={() => import('./path/to/domAnimation')}>
|
|
428
|
+
* <m.div animate={{ scale: 2 }} />
|
|
429
|
+
* </LazyMotion>
|
|
430
|
+
* )
|
|
431
|
+
* }
|
|
432
|
+
* ```
|
|
433
|
+
*
|
|
434
|
+
* @public
|
|
417
435
|
*/
|
|
418
|
-
function
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
return next;
|
|
422
|
-
}
|
|
423
|
-
else if (next.startsWith("-") || next.startsWith("+")) {
|
|
424
|
-
return Math.max(0, current + parseFloat(next));
|
|
425
|
-
}
|
|
426
|
-
else if (next === "<") {
|
|
427
|
-
return prev;
|
|
428
|
-
}
|
|
429
|
-
else {
|
|
430
|
-
return (_a = labels.get(next)) !== null && _a !== void 0 ? _a : current;
|
|
431
|
-
}
|
|
432
|
-
}
|
|
433
|
-
|
|
434
|
-
function eraseKeyframes(sequence, startTime, endTime) {
|
|
435
|
-
for (let i = 0; i < sequence.length; i++) {
|
|
436
|
-
const keyframe = sequence[i];
|
|
437
|
-
if (keyframe.at > startTime && keyframe.at < endTime) {
|
|
438
|
-
create.removeItem(sequence, keyframe);
|
|
439
|
-
// If we remove this item we have to push the pointer back one
|
|
440
|
-
i--;
|
|
441
|
-
}
|
|
442
|
-
}
|
|
443
|
-
}
|
|
444
|
-
function addKeyframes(sequence, keyframes, easing, offset, startTime, endTime) {
|
|
436
|
+
function LazyMotion({ children, features, strict = false }) {
|
|
437
|
+
const [, setIsLoaded] = React.useState(!isLazyBundle(features));
|
|
438
|
+
const loadedRenderer = React.useRef(undefined);
|
|
445
439
|
/**
|
|
446
|
-
*
|
|
447
|
-
* this will essentially splice this timeline into any currently
|
|
448
|
-
* defined ones.
|
|
440
|
+
* If this is a synchronous load, load features immediately
|
|
449
441
|
*/
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
at: create.mixNumber(startTime, endTime, offset[i]),
|
|
455
|
-
easing: getEasingForSegment(easing, i),
|
|
456
|
-
});
|
|
442
|
+
if (!isLazyBundle(features)) {
|
|
443
|
+
const { renderer, ...loadedFeatures } = features;
|
|
444
|
+
loadedRenderer.current = renderer;
|
|
445
|
+
create.loadFeatures(loadedFeatures);
|
|
457
446
|
}
|
|
447
|
+
React.useEffect(() => {
|
|
448
|
+
if (isLazyBundle(features)) {
|
|
449
|
+
features().then(({ renderer, ...loadedFeatures }) => {
|
|
450
|
+
create.loadFeatures(loadedFeatures);
|
|
451
|
+
loadedRenderer.current = renderer;
|
|
452
|
+
setIsLoaded(true);
|
|
453
|
+
});
|
|
454
|
+
}
|
|
455
|
+
}, []);
|
|
456
|
+
return (jsxRuntime.jsx(create.LazyContext.Provider, { value: { renderer: loadedRenderer.current, strict }, children: children }));
|
|
457
|
+
}
|
|
458
|
+
function isLazyBundle(features) {
|
|
459
|
+
return typeof features === "function";
|
|
458
460
|
}
|
|
459
461
|
|
|
460
462
|
/**
|
|
461
|
-
*
|
|
462
|
-
*
|
|
463
|
-
*
|
|
464
|
-
*
|
|
463
|
+
* `MotionConfig` is used to set configuration options for all children `motion` components.
|
|
464
|
+
*
|
|
465
|
+
* ```jsx
|
|
466
|
+
* import { motion, MotionConfig } from "framer-motion"
|
|
467
|
+
*
|
|
468
|
+
* export function App() {
|
|
469
|
+
* return (
|
|
470
|
+
* <MotionConfig transition={{ type: "spring" }}>
|
|
471
|
+
* <motion.div animate={{ x: 100 }} />
|
|
472
|
+
* </MotionConfig>
|
|
473
|
+
* )
|
|
474
|
+
* }
|
|
475
|
+
* ```
|
|
476
|
+
*
|
|
477
|
+
* @public
|
|
465
478
|
*/
|
|
466
|
-
function
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
479
|
+
function MotionConfig({ children, isValidProp, ...config }) {
|
|
480
|
+
isValidProp && create.loadExternalIsValidProp(isValidProp);
|
|
481
|
+
/**
|
|
482
|
+
* Inherit props from any parent MotionConfig components
|
|
483
|
+
*/
|
|
484
|
+
config = { ...React.useContext(create.MotionConfigContext), ...config };
|
|
485
|
+
/**
|
|
486
|
+
* Don't allow isStatic to change between renders as it affects how many hooks
|
|
487
|
+
* motion components fire.
|
|
488
|
+
*/
|
|
489
|
+
config.isStatic = create.useConstant(() => config.isStatic);
|
|
490
|
+
/**
|
|
491
|
+
* Creating a new config context object will re-render every `motion` component
|
|
492
|
+
* every time it renders. So we only want to create a new one sparingly.
|
|
493
|
+
*/
|
|
494
|
+
const context = React.useMemo(() => config, [
|
|
495
|
+
JSON.stringify(config.transition),
|
|
496
|
+
config.transformPagePoint,
|
|
497
|
+
config.reducedMotion,
|
|
498
|
+
]);
|
|
499
|
+
return (jsxRuntime.jsx(create.MotionConfigContext.Provider, { value: context, children: children }));
|
|
470
500
|
}
|
|
471
501
|
|
|
472
|
-
|
|
473
|
-
if (a.at === b.at) {
|
|
474
|
-
if (a.value === null)
|
|
475
|
-
return 1;
|
|
476
|
-
if (b.value === null)
|
|
477
|
-
return -1;
|
|
478
|
-
return 0;
|
|
479
|
-
}
|
|
480
|
-
else {
|
|
481
|
-
return a.at - b.at;
|
|
482
|
-
}
|
|
483
|
-
}
|
|
502
|
+
const ReorderContext = React.createContext(null);
|
|
484
503
|
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
const animationDefinitions = new Map();
|
|
490
|
-
const sequences = new Map();
|
|
491
|
-
const elementCache = {};
|
|
492
|
-
const timeLabels = new Map();
|
|
493
|
-
let prevTime = 0;
|
|
494
|
-
let currentTime = 0;
|
|
495
|
-
let totalDuration = 0;
|
|
504
|
+
function createDOMMotionComponentProxy(componentFactory) {
|
|
505
|
+
if (typeof Proxy === "undefined") {
|
|
506
|
+
return componentFactory;
|
|
507
|
+
}
|
|
496
508
|
/**
|
|
497
|
-
*
|
|
498
|
-
*
|
|
499
|
-
* These will later get converted into relative offsets in a second pass.
|
|
509
|
+
* A cache of generated `motion` components, e.g `motion.div`, `motion.input` etc.
|
|
510
|
+
* Rather than generating them anew every render.
|
|
500
511
|
*/
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
*/
|
|
506
|
-
if (typeof segment === "string") {
|
|
507
|
-
timeLabels.set(segment, currentTime);
|
|
508
|
-
continue;
|
|
509
|
-
}
|
|
510
|
-
else if (!Array.isArray(segment)) {
|
|
511
|
-
timeLabels.set(segment.name, calcNextTime(currentTime, segment.at, prevTime, timeLabels));
|
|
512
|
-
continue;
|
|
513
|
-
}
|
|
514
|
-
let [subject, keyframes, transition = {}] = segment;
|
|
515
|
-
/**
|
|
516
|
-
* If a relative or absolute time value has been specified we need to resolve
|
|
517
|
-
* it in relation to the currentTime.
|
|
518
|
-
*/
|
|
519
|
-
if (transition.at !== undefined) {
|
|
520
|
-
currentTime = calcNextTime(currentTime, transition.at, prevTime, timeLabels);
|
|
512
|
+
const componentCache = new Map();
|
|
513
|
+
const deprecatedFactoryFunction = (...args) => {
|
|
514
|
+
if (process.env.NODE_ENV !== "production") {
|
|
515
|
+
motionUtils.warnOnce(false, "motion() is deprecated. Use motion.create() instead.");
|
|
521
516
|
}
|
|
517
|
+
return componentFactory(...args);
|
|
518
|
+
};
|
|
519
|
+
return new Proxy(deprecatedFactoryFunction, {
|
|
522
520
|
/**
|
|
523
|
-
*
|
|
524
|
-
*
|
|
521
|
+
* Called when `motion` is referenced with a prop: `motion.div`, `motion.input` etc.
|
|
522
|
+
* The prop name is passed through as `key` and we can use that to generate a `motion`
|
|
523
|
+
* DOM component with that name.
|
|
525
524
|
*/
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
const { delay = 0, times = create.defaultOffset(valueKeyframesAsList), type = "keyframes", repeat, repeatType, repeatDelay = 0, ...remainingTransition } = valueTransition;
|
|
530
|
-
let { ease = defaultTransition.ease || "easeOut", duration } = valueTransition;
|
|
531
|
-
/**
|
|
532
|
-
* Resolve stagger() if defined.
|
|
533
|
-
*/
|
|
534
|
-
const calculatedDelay = typeof delay === "function"
|
|
535
|
-
? delay(elementIndex, numSubjects)
|
|
536
|
-
: delay;
|
|
525
|
+
get: (_target, key) => {
|
|
526
|
+
if (key === "create")
|
|
527
|
+
return componentFactory;
|
|
537
528
|
/**
|
|
538
|
-
* If this
|
|
529
|
+
* If this element doesn't exist in the component cache, create it and cache.
|
|
539
530
|
*/
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
? type
|
|
543
|
-
: generators === null || generators === void 0 ? void 0 : generators[type];
|
|
544
|
-
if (numKeyframes <= 2 && createGenerator) {
|
|
545
|
-
/**
|
|
546
|
-
* As we're creating an easing function from a spring,
|
|
547
|
-
* ideally we want to generate it using the real distance
|
|
548
|
-
* between the two keyframes. However this isn't always
|
|
549
|
-
* possible - in these situations we use 0-100.
|
|
550
|
-
*/
|
|
551
|
-
let absoluteDelta = 100;
|
|
552
|
-
if (numKeyframes === 2 &&
|
|
553
|
-
isNumberKeyframesArray(valueKeyframesAsList)) {
|
|
554
|
-
const delta = valueKeyframesAsList[1] - valueKeyframesAsList[0];
|
|
555
|
-
absoluteDelta = Math.abs(delta);
|
|
556
|
-
}
|
|
557
|
-
const springTransition = { ...remainingTransition };
|
|
558
|
-
if (duration !== undefined) {
|
|
559
|
-
springTransition.duration = motionUtils.secondsToMilliseconds(duration);
|
|
560
|
-
}
|
|
561
|
-
const springEasing = motionDom.createGeneratorEasing(springTransition, absoluteDelta, createGenerator);
|
|
562
|
-
ease = springEasing.ease;
|
|
563
|
-
duration = springEasing.duration;
|
|
531
|
+
if (!componentCache.has(key)) {
|
|
532
|
+
componentCache.set(key, componentFactory(key));
|
|
564
533
|
}
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
534
|
+
return componentCache.get(key);
|
|
535
|
+
},
|
|
536
|
+
});
|
|
537
|
+
}
|
|
538
|
+
|
|
539
|
+
const motion = /*@__PURE__*/ createDOMMotionComponentProxy(create.createMotionComponent);
|
|
540
|
+
|
|
541
|
+
function checkReorder(order, value, offset, velocity) {
|
|
542
|
+
if (!velocity)
|
|
543
|
+
return order;
|
|
544
|
+
const index = order.findIndex((item) => item.value === value);
|
|
545
|
+
if (index === -1)
|
|
546
|
+
return order;
|
|
547
|
+
const nextOffset = velocity > 0 ? 1 : -1;
|
|
548
|
+
const nextItem = order[index + nextOffset];
|
|
549
|
+
if (!nextItem)
|
|
550
|
+
return order;
|
|
551
|
+
const item = order[index];
|
|
552
|
+
const nextLayout = nextItem.layout;
|
|
553
|
+
const nextItemCenter = create.mixNumber(nextLayout.min, nextLayout.max, 0.5);
|
|
554
|
+
if ((nextOffset === 1 && item.layout.max + offset > nextItemCenter) ||
|
|
555
|
+
(nextOffset === -1 && item.layout.min + offset < nextItemCenter)) {
|
|
556
|
+
return motionUtils.moveItem(order, index, index + nextOffset);
|
|
557
|
+
}
|
|
558
|
+
return order;
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
function ReorderGroupComponent({ children, as = "ul", axis = "y", onReorder, values, ...props }, externalRef) {
|
|
562
|
+
const Component = create.useConstant(() => motion[as]);
|
|
563
|
+
const order = [];
|
|
564
|
+
const isReordering = React.useRef(false);
|
|
565
|
+
motionUtils.invariant(Boolean(values), "Reorder.Group must be provided a values prop");
|
|
566
|
+
const context = {
|
|
567
|
+
axis,
|
|
568
|
+
registerItem: (value, layout) => {
|
|
569
|
+
// If the entry was already added, update it rather than adding it again
|
|
570
|
+
const idx = order.findIndex((entry) => value === entry.value);
|
|
571
|
+
if (idx !== -1) {
|
|
572
|
+
order[idx].layout = layout[axis];
|
|
572
573
|
}
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
*/
|
|
576
|
-
const remainder = times.length - valueKeyframesAsList.length;
|
|
577
|
-
remainder > 0 && create.fillOffset(times, remainder);
|
|
578
|
-
/**
|
|
579
|
-
* If only one value has been set, ie [1], push a null to the start of
|
|
580
|
-
* the keyframe array. This will let us mark a keyframe at this point
|
|
581
|
-
* that will later be hydrated with the previous value.
|
|
582
|
-
*/
|
|
583
|
-
valueKeyframesAsList.length === 1 &&
|
|
584
|
-
valueKeyframesAsList.unshift(null);
|
|
585
|
-
/**
|
|
586
|
-
* Handle repeat options
|
|
587
|
-
*/
|
|
588
|
-
if (repeat) {
|
|
589
|
-
motionUtils.invariant(repeat < MAX_REPEAT, "Repeat count too high, must be less than 20");
|
|
590
|
-
duration = calculateRepeatDuration(duration, repeat);
|
|
591
|
-
const originalKeyframes = [...valueKeyframesAsList];
|
|
592
|
-
const originalTimes = [...times];
|
|
593
|
-
ease = Array.isArray(ease) ? [...ease] : [ease];
|
|
594
|
-
const originalEase = [...ease];
|
|
595
|
-
for (let repeatIndex = 0; repeatIndex < repeat; repeatIndex++) {
|
|
596
|
-
valueKeyframesAsList.push(...originalKeyframes);
|
|
597
|
-
for (let keyframeIndex = 0; keyframeIndex < originalKeyframes.length; keyframeIndex++) {
|
|
598
|
-
times.push(originalTimes[keyframeIndex] + (repeatIndex + 1));
|
|
599
|
-
ease.push(keyframeIndex === 0
|
|
600
|
-
? "linear"
|
|
601
|
-
: getEasingForSegment(originalEase, keyframeIndex - 1));
|
|
602
|
-
}
|
|
603
|
-
}
|
|
604
|
-
normalizeTimes(times, repeat);
|
|
574
|
+
else {
|
|
575
|
+
order.push({ value: value, layout: layout[axis] });
|
|
605
576
|
}
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
}
|
|
618
|
-
else {
|
|
619
|
-
const subjects = resolveSubjects(subject, keyframes, scope, elementCache);
|
|
620
|
-
const numSubjects = subjects.length;
|
|
621
|
-
/**
|
|
622
|
-
* For every element in this segment, process the defined values.
|
|
623
|
-
*/
|
|
624
|
-
for (let subjectIndex = 0; subjectIndex < numSubjects; subjectIndex++) {
|
|
625
|
-
/**
|
|
626
|
-
* Cast necessary, but we know these are of this type
|
|
627
|
-
*/
|
|
628
|
-
keyframes = keyframes;
|
|
629
|
-
transition = transition;
|
|
630
|
-
const thisSubject = subjects[subjectIndex];
|
|
631
|
-
const subjectSequence = getSubjectSequence(thisSubject, sequences);
|
|
632
|
-
for (const key in keyframes) {
|
|
633
|
-
resolveValueSequence(keyframes[key], getValueTransition(transition, key), getValueSequence(key, subjectSequence), subjectIndex, numSubjects);
|
|
634
|
-
}
|
|
577
|
+
order.sort(compareMin);
|
|
578
|
+
},
|
|
579
|
+
updateOrder: (item, offset, velocity) => {
|
|
580
|
+
if (isReordering.current)
|
|
581
|
+
return;
|
|
582
|
+
const newOrder = checkReorder(order, item, offset, velocity);
|
|
583
|
+
if (order !== newOrder) {
|
|
584
|
+
isReordering.current = true;
|
|
585
|
+
onReorder(newOrder
|
|
586
|
+
.map(getValue)
|
|
587
|
+
.filter((value) => values.indexOf(value) !== -1));
|
|
635
588
|
}
|
|
636
|
-
}
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
589
|
+
},
|
|
590
|
+
};
|
|
591
|
+
React.useEffect(() => {
|
|
592
|
+
isReordering.current = false;
|
|
593
|
+
});
|
|
594
|
+
return (jsxRuntime.jsx(Component, { ...props, ref: externalRef, ignoreStrict: true, children: jsxRuntime.jsx(ReorderContext.Provider, { value: context, children: children }) }));
|
|
595
|
+
}
|
|
596
|
+
const ReorderGroup = /*@__PURE__*/ React.forwardRef(ReorderGroupComponent);
|
|
597
|
+
function getValue(item) {
|
|
598
|
+
return item.value;
|
|
599
|
+
}
|
|
600
|
+
function compareMin(a, b) {
|
|
601
|
+
return a.layout.min - b.layout.min;
|
|
602
|
+
}
|
|
603
|
+
|
|
604
|
+
/**
|
|
605
|
+
* Creates a `MotionValue` to track the state and velocity of a value.
|
|
606
|
+
*
|
|
607
|
+
* Usually, these are created automatically. For advanced use-cases, like use with `useTransform`, you can create `MotionValue`s externally and pass them into the animated component via the `style` prop.
|
|
608
|
+
*
|
|
609
|
+
* ```jsx
|
|
610
|
+
* export const MyComponent = () => {
|
|
611
|
+
* const scale = useMotionValue(1)
|
|
612
|
+
*
|
|
613
|
+
* return <motion.div style={{ scale }} />
|
|
614
|
+
* }
|
|
615
|
+
* ```
|
|
616
|
+
*
|
|
617
|
+
* @param initial - The initial state.
|
|
618
|
+
*
|
|
619
|
+
* @public
|
|
620
|
+
*/
|
|
621
|
+
function useMotionValue(initial) {
|
|
622
|
+
const value = create.useConstant(() => motionDom.motionValue(initial));
|
|
640
623
|
/**
|
|
641
|
-
*
|
|
624
|
+
* If this motion value is being used in static mode, like on
|
|
625
|
+
* the Framer canvas, force components to rerender when the motion
|
|
626
|
+
* value is updated.
|
|
642
627
|
*/
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
* provide one by duplicating the initial keyframe. This ensures
|
|
666
|
-
* it snaps to the first keyframe when the animation starts.
|
|
667
|
-
*/
|
|
668
|
-
if (valueOffset[0] !== 0) {
|
|
669
|
-
valueOffset.unshift(0);
|
|
670
|
-
keyframes.unshift(keyframes[0]);
|
|
671
|
-
valueEasing.unshift(defaultSegmentEasing);
|
|
672
|
-
}
|
|
673
|
-
/**
|
|
674
|
-
* If the last keyframe doesn't land on offset: 1
|
|
675
|
-
* provide one with a null wildcard value. This will ensure it
|
|
676
|
-
* stays static until the end of the animation.
|
|
677
|
-
*/
|
|
678
|
-
if (valueOffset[valueOffset.length - 1] !== 1) {
|
|
679
|
-
valueOffset.push(1);
|
|
680
|
-
keyframes.push(null);
|
|
681
|
-
}
|
|
682
|
-
if (!animationDefinitions.has(element)) {
|
|
683
|
-
animationDefinitions.set(element, {
|
|
684
|
-
keyframes: {},
|
|
685
|
-
transition: {},
|
|
686
|
-
});
|
|
687
|
-
}
|
|
688
|
-
const definition = animationDefinitions.get(element);
|
|
689
|
-
definition.keyframes[key] = keyframes;
|
|
690
|
-
definition.transition[key] = {
|
|
691
|
-
...defaultTransition,
|
|
692
|
-
duration: totalDuration,
|
|
693
|
-
ease: valueEasing,
|
|
694
|
-
times: valueOffset,
|
|
695
|
-
...sequenceTransition,
|
|
696
|
-
};
|
|
697
|
-
}
|
|
628
|
+
const { isStatic } = React.useContext(create.MotionConfigContext);
|
|
629
|
+
if (isStatic) {
|
|
630
|
+
const [, setLatest] = React.useState(initial);
|
|
631
|
+
React.useEffect(() => value.on("change", setLatest), []);
|
|
632
|
+
}
|
|
633
|
+
return value;
|
|
634
|
+
}
|
|
635
|
+
|
|
636
|
+
const isCustomValueType = (v) => {
|
|
637
|
+
return v && typeof v === "object" && v.mix;
|
|
638
|
+
};
|
|
639
|
+
const getMixer = (v) => (isCustomValueType(v) ? v.mix : undefined);
|
|
640
|
+
function transform(...args) {
|
|
641
|
+
const useImmediate = !Array.isArray(args[0]);
|
|
642
|
+
const argOffset = useImmediate ? 0 : -1;
|
|
643
|
+
const inputValue = args[0 + argOffset];
|
|
644
|
+
const inputRange = args[1 + argOffset];
|
|
645
|
+
const outputRange = args[2 + argOffset];
|
|
646
|
+
const options = args[3 + argOffset];
|
|
647
|
+
const interpolator = create.interpolate(inputRange, outputRange, {
|
|
648
|
+
mixer: getMixer(outputRange[0]),
|
|
649
|
+
...options,
|
|
698
650
|
});
|
|
699
|
-
return
|
|
651
|
+
return useImmediate ? interpolator(inputValue) : interpolator;
|
|
700
652
|
}
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
653
|
+
|
|
654
|
+
function useCombineMotionValues(values, combineValues) {
|
|
655
|
+
/**
|
|
656
|
+
* Initialise the returned motion value. This remains the same between renders.
|
|
657
|
+
*/
|
|
658
|
+
const value = useMotionValue(combineValues());
|
|
659
|
+
/**
|
|
660
|
+
* Create a function that will update the template motion value with the latest values.
|
|
661
|
+
* This is pre-bound so whenever a motion value updates it can schedule its
|
|
662
|
+
* execution in Framesync. If it's already been scheduled it won't be fired twice
|
|
663
|
+
* in a single frame.
|
|
664
|
+
*/
|
|
665
|
+
const updateValue = () => value.set(combineValues());
|
|
666
|
+
/**
|
|
667
|
+
* Synchronously update the motion value with the latest values during the render.
|
|
668
|
+
* This ensures that within a React render, the styles applied to the DOM are up-to-date.
|
|
669
|
+
*/
|
|
670
|
+
updateValue();
|
|
671
|
+
/**
|
|
672
|
+
* Subscribe to all motion values found within the template. Whenever any of them change,
|
|
673
|
+
* schedule an update.
|
|
674
|
+
*/
|
|
675
|
+
create.useIsomorphicLayoutEffect(() => {
|
|
676
|
+
const scheduleUpdate = () => motionDom.frame.preRender(updateValue, false, true);
|
|
677
|
+
const subscriptions = values.map((v) => v.on("change", scheduleUpdate));
|
|
678
|
+
return () => {
|
|
679
|
+
subscriptions.forEach((unsubscribe) => unsubscribe());
|
|
680
|
+
motionDom.cancelFrame(updateValue);
|
|
681
|
+
};
|
|
682
|
+
});
|
|
683
|
+
return value;
|
|
704
684
|
}
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
685
|
+
|
|
686
|
+
function useComputed(compute) {
|
|
687
|
+
/**
|
|
688
|
+
* Open session of collectMotionValues. Any MotionValue that calls get()
|
|
689
|
+
* will be saved into this array.
|
|
690
|
+
*/
|
|
691
|
+
motionDom.collectMotionValues.current = [];
|
|
692
|
+
compute();
|
|
693
|
+
const value = useCombineMotionValues(motionDom.collectMotionValues.current, compute);
|
|
694
|
+
/**
|
|
695
|
+
* Synchronously close session of collectMotionValues.
|
|
696
|
+
*/
|
|
697
|
+
motionDom.collectMotionValues.current = undefined;
|
|
698
|
+
return value;
|
|
709
699
|
}
|
|
710
|
-
|
|
711
|
-
|
|
700
|
+
|
|
701
|
+
function useTransform(input, inputRangeOrTransformer, outputRange, options) {
|
|
702
|
+
if (typeof input === "function") {
|
|
703
|
+
return useComputed(input);
|
|
704
|
+
}
|
|
705
|
+
const transformer = typeof inputRangeOrTransformer === "function"
|
|
706
|
+
? inputRangeOrTransformer
|
|
707
|
+
: transform(inputRangeOrTransformer, outputRange, options);
|
|
708
|
+
return Array.isArray(input)
|
|
709
|
+
? useListTransform(input, transformer)
|
|
710
|
+
: useListTransform([input], ([latest]) => transformer(latest));
|
|
712
711
|
}
|
|
713
|
-
function
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
712
|
+
function useListTransform(values, transformer) {
|
|
713
|
+
const latest = create.useConstant(() => []);
|
|
714
|
+
return useCombineMotionValues(values, () => {
|
|
715
|
+
latest.length = 0;
|
|
716
|
+
const numValues = values.length;
|
|
717
|
+
for (let i = 0; i < numValues; i++) {
|
|
718
|
+
latest[i] = values[i].get();
|
|
718
719
|
}
|
|
719
|
-
|
|
720
|
+
return transformer(latest);
|
|
721
|
+
});
|
|
720
722
|
}
|
|
721
|
-
const isNumber = (keyframe) => typeof keyframe === "number";
|
|
722
|
-
const isNumberKeyframesArray = (keyframes) => keyframes.every(isNumber);
|
|
723
723
|
|
|
724
|
-
function
|
|
725
|
-
return
|
|
724
|
+
function useDefaultMotionValue(value, defaultValue = 0) {
|
|
725
|
+
return create.isMotionValue(value) ? value : useMotionValue(defaultValue);
|
|
726
726
|
}
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
727
|
+
function ReorderItemComponent({ children, style = {}, value, as = "li", onDrag, layout = true, ...props }, externalRef) {
|
|
728
|
+
const Component = create.useConstant(() => motion[as]);
|
|
729
|
+
const context = React.useContext(ReorderContext);
|
|
730
|
+
const point = {
|
|
731
|
+
x: useDefaultMotionValue(style.x),
|
|
732
|
+
y: useDefaultMotionValue(style.y),
|
|
733
|
+
};
|
|
734
|
+
const zIndex = useTransform([point.x, point.y], ([latestX, latestY]) => latestX || latestY ? 1 : "unset");
|
|
735
|
+
motionUtils.invariant(Boolean(context), "Reorder.Item must be a child of Reorder.Group");
|
|
736
|
+
const { axis, registerItem, updateOrder } = context;
|
|
737
|
+
return (jsxRuntime.jsx(Component, { drag: axis, ...props, dragSnapToOrigin: true, style: { ...style, x: point.x, y: point.y, zIndex }, layout: layout, onDrag: (event, gesturePoint) => {
|
|
738
|
+
const { velocity } = gesturePoint;
|
|
739
|
+
velocity[axis] &&
|
|
740
|
+
updateOrder(value, point[axis].get(), velocity[axis]);
|
|
741
|
+
onDrag && onDrag(event, gesturePoint);
|
|
742
|
+
}, onLayoutMeasure: (measured) => registerItem(value, measured), ref: externalRef, ignoreStrict: true, children: children }));
|
|
743
|
+
}
|
|
744
|
+
const ReorderItem = /*@__PURE__*/ React.forwardRef(ReorderItemComponent);
|
|
745
|
+
|
|
746
|
+
var namespace = /*#__PURE__*/Object.freeze({
|
|
747
|
+
__proto__: null,
|
|
748
|
+
Group: ReorderGroup,
|
|
749
|
+
Item: ReorderItem
|
|
750
|
+
});
|
|
751
|
+
|
|
752
|
+
const wrap = (min, max, v) => {
|
|
753
|
+
const rangeSize = max - min;
|
|
754
|
+
return ((((v - min) % rangeSize) + rangeSize) % rangeSize) + min;
|
|
755
|
+
};
|
|
756
|
+
|
|
757
|
+
function getEasingForSegment(easing, i) {
|
|
758
|
+
return create.isEasingArray(easing) ? easing[wrap(0, easing.length, i)] : easing;
|
|
759
|
+
}
|
|
760
|
+
|
|
761
|
+
function isDOMKeyframes(keyframes) {
|
|
762
|
+
return typeof keyframes === "object" && !Array.isArray(keyframes);
|
|
763
|
+
}
|
|
764
|
+
|
|
765
|
+
function resolveSubjects(subject, keyframes, scope, selectorCache) {
|
|
766
|
+
if (typeof subject === "string" && isDOMKeyframes(keyframes)) {
|
|
767
|
+
return motionDom.resolveElements(subject, scope, selectorCache);
|
|
731
768
|
}
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
const value = instance[key];
|
|
735
|
-
if (typeof value === "string" || typeof value === "number") {
|
|
736
|
-
return value;
|
|
737
|
-
}
|
|
738
|
-
}
|
|
739
|
-
return undefined;
|
|
769
|
+
else if (subject instanceof NodeList) {
|
|
770
|
+
return Array.from(subject);
|
|
740
771
|
}
|
|
741
|
-
|
|
742
|
-
return
|
|
772
|
+
else if (Array.isArray(subject)) {
|
|
773
|
+
return subject;
|
|
743
774
|
}
|
|
744
|
-
|
|
745
|
-
|
|
775
|
+
else {
|
|
776
|
+
return [subject];
|
|
746
777
|
}
|
|
747
|
-
|
|
748
|
-
|
|
778
|
+
}
|
|
779
|
+
|
|
780
|
+
function calculateRepeatDuration(duration, repeat, _repeatDelay) {
|
|
781
|
+
return duration * (repeat + 1);
|
|
782
|
+
}
|
|
783
|
+
|
|
784
|
+
/**
|
|
785
|
+
* Given a absolute or relative time definition and current/prev time state of the sequence,
|
|
786
|
+
* calculate an absolute time for the next keyframes.
|
|
787
|
+
*/
|
|
788
|
+
function calcNextTime(current, next, prev, labels) {
|
|
789
|
+
var _a;
|
|
790
|
+
if (typeof next === "number") {
|
|
791
|
+
return next;
|
|
749
792
|
}
|
|
750
|
-
|
|
751
|
-
|
|
793
|
+
else if (next.startsWith("-") || next.startsWith("+")) {
|
|
794
|
+
return Math.max(0, current + parseFloat(next));
|
|
752
795
|
}
|
|
753
|
-
|
|
754
|
-
|
|
796
|
+
else if (next === "<") {
|
|
797
|
+
return prev;
|
|
755
798
|
}
|
|
756
|
-
|
|
757
|
-
return 0;
|
|
799
|
+
else {
|
|
800
|
+
return (_a = labels.get(next)) !== null && _a !== void 0 ? _a : current;
|
|
758
801
|
}
|
|
759
802
|
}
|
|
760
803
|
|
|
761
|
-
function
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
transformOrigin: {},
|
|
769
|
-
style: {},
|
|
770
|
-
vars: {},
|
|
771
|
-
attrs: {},
|
|
772
|
-
},
|
|
773
|
-
latestValues: {},
|
|
774
|
-
},
|
|
775
|
-
};
|
|
776
|
-
const node = create.isSVGElement(element)
|
|
777
|
-
? new create.SVGVisualElement(options)
|
|
778
|
-
: new create.HTMLVisualElement(options);
|
|
779
|
-
node.mount(element);
|
|
780
|
-
create.visualElementStore.set(element, node);
|
|
781
|
-
}
|
|
782
|
-
function createObjectVisualElement(subject) {
|
|
783
|
-
const options = {
|
|
784
|
-
presenceContext: null,
|
|
785
|
-
props: {},
|
|
786
|
-
visualState: {
|
|
787
|
-
renderState: {
|
|
788
|
-
output: {},
|
|
789
|
-
},
|
|
790
|
-
latestValues: {},
|
|
791
|
-
},
|
|
792
|
-
};
|
|
793
|
-
const node = new ObjectVisualElement(options);
|
|
794
|
-
node.mount(subject);
|
|
795
|
-
create.visualElementStore.set(subject, node);
|
|
796
|
-
}
|
|
797
|
-
|
|
798
|
-
function isSingleValue(subject, keyframes) {
|
|
799
|
-
return (create.isMotionValue(subject) ||
|
|
800
|
-
typeof subject === "number" ||
|
|
801
|
-
(typeof subject === "string" && !isDOMKeyframes(keyframes)));
|
|
802
|
-
}
|
|
803
|
-
/**
|
|
804
|
-
* Implementation
|
|
805
|
-
*/
|
|
806
|
-
function animateSubject(subject, keyframes, options, scope) {
|
|
807
|
-
const animations = [];
|
|
808
|
-
if (isSingleValue(subject, keyframes)) {
|
|
809
|
-
animations.push(create.animateSingleValue(subject, isDOMKeyframes(keyframes)
|
|
810
|
-
? keyframes.default || keyframes
|
|
811
|
-
: keyframes, options ? options.default || options : options));
|
|
812
|
-
}
|
|
813
|
-
else {
|
|
814
|
-
const subjects = resolveSubjects(subject, keyframes, scope);
|
|
815
|
-
const numSubjects = subjects.length;
|
|
816
|
-
motionUtils.invariant(Boolean(numSubjects), "No valid elements provided.");
|
|
817
|
-
for (let i = 0; i < numSubjects; i++) {
|
|
818
|
-
const thisSubject = subjects[i];
|
|
819
|
-
const createVisualElement = thisSubject instanceof Element
|
|
820
|
-
? createDOMVisualElement
|
|
821
|
-
: createObjectVisualElement;
|
|
822
|
-
if (!create.visualElementStore.has(thisSubject)) {
|
|
823
|
-
createVisualElement(thisSubject);
|
|
824
|
-
}
|
|
825
|
-
const visualElement = create.visualElementStore.get(thisSubject);
|
|
826
|
-
const transition = { ...options };
|
|
827
|
-
/**
|
|
828
|
-
* Resolve stagger function if provided.
|
|
829
|
-
*/
|
|
830
|
-
if ("delay" in transition &&
|
|
831
|
-
typeof transition.delay === "function") {
|
|
832
|
-
transition.delay = transition.delay(i, numSubjects);
|
|
833
|
-
}
|
|
834
|
-
animations.push(...create.animateTarget(visualElement, { ...keyframes, transition }, {}));
|
|
804
|
+
function eraseKeyframes(sequence, startTime, endTime) {
|
|
805
|
+
for (let i = 0; i < sequence.length; i++) {
|
|
806
|
+
const keyframe = sequence[i];
|
|
807
|
+
if (keyframe.at > startTime && keyframe.at < endTime) {
|
|
808
|
+
motionUtils.removeItem(sequence, keyframe);
|
|
809
|
+
// If we remove this item we have to push the pointer back one
|
|
810
|
+
i--;
|
|
835
811
|
}
|
|
836
812
|
}
|
|
837
|
-
return animations;
|
|
838
|
-
}
|
|
839
|
-
|
|
840
|
-
function animateSequence(sequence, options, scope) {
|
|
841
|
-
const animations = [];
|
|
842
|
-
const animationDefinitions = createAnimationsFromSequence(sequence, options, scope, { spring: create.spring });
|
|
843
|
-
animationDefinitions.forEach(({ keyframes, transition }, subject) => {
|
|
844
|
-
animations.push(...animateSubject(subject, keyframes, transition));
|
|
845
|
-
});
|
|
846
|
-
return animations;
|
|
847
813
|
}
|
|
848
|
-
|
|
849
|
-
function isSequence(value) {
|
|
850
|
-
return Array.isArray(value) && value.some(Array.isArray);
|
|
851
|
-
}
|
|
852
|
-
/**
|
|
853
|
-
* Creates an animation function that is optionally scoped
|
|
854
|
-
* to a specific element.
|
|
855
|
-
*/
|
|
856
|
-
function createScopedAnimate(scope) {
|
|
814
|
+
function addKeyframes(sequence, keyframes, easing, offset, startTime, endTime) {
|
|
857
815
|
/**
|
|
858
|
-
*
|
|
816
|
+
* Erase every existing value between currentTime and targetTime,
|
|
817
|
+
* this will essentially splice this timeline into any currently
|
|
818
|
+
* defined ones.
|
|
859
819
|
*/
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
}
|
|
868
|
-
const animation = new motionDom.GroupPlaybackControls(animations);
|
|
869
|
-
if (scope) {
|
|
870
|
-
scope.animations.push(animation);
|
|
871
|
-
}
|
|
872
|
-
return animation;
|
|
820
|
+
eraseKeyframes(sequence, startTime, endTime);
|
|
821
|
+
for (let i = 0; i < keyframes.length; i++) {
|
|
822
|
+
sequence.push({
|
|
823
|
+
value: keyframes[i],
|
|
824
|
+
at: create.mixNumber(startTime, endTime, offset[i]),
|
|
825
|
+
easing: getEasingForSegment(easing, i),
|
|
826
|
+
});
|
|
873
827
|
}
|
|
874
|
-
return scopedAnimate;
|
|
875
|
-
}
|
|
876
|
-
const animate = createScopedAnimate();
|
|
877
|
-
|
|
878
|
-
function setCSSVar(element, name, value) {
|
|
879
|
-
element.style.setProperty(name, value);
|
|
880
|
-
}
|
|
881
|
-
function setStyle(element, name, value) {
|
|
882
|
-
element.style[name] = value;
|
|
883
828
|
}
|
|
884
829
|
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
830
|
+
/**
|
|
831
|
+
* Take an array of times that represent repeated keyframes. For instance
|
|
832
|
+
* if we have original times of [0, 0.5, 1] then our repeated times will
|
|
833
|
+
* be [0, 0.5, 1, 1, 1.5, 2]. Loop over the times and scale them back
|
|
834
|
+
* down to a 0-1 scale.
|
|
835
|
+
*/
|
|
836
|
+
function normalizeTimes(times, repeat) {
|
|
837
|
+
for (let i = 0; i < times.length; i++) {
|
|
838
|
+
times[i] = times[i] / (repeat + 1);
|
|
891
839
|
}
|
|
892
|
-
|
|
893
|
-
});
|
|
840
|
+
}
|
|
894
841
|
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
create.browserNumberValueTypes[valueName]) {
|
|
903
|
-
keyframes[i] = create.browserNumberValueTypes[valueName].transform(keyframes[i]);
|
|
904
|
-
}
|
|
842
|
+
function compareByTime(a, b) {
|
|
843
|
+
if (a.at === b.at) {
|
|
844
|
+
if (a.value === null)
|
|
845
|
+
return 1;
|
|
846
|
+
if (b.value === null)
|
|
847
|
+
return -1;
|
|
848
|
+
return 0;
|
|
905
849
|
}
|
|
906
|
-
|
|
907
|
-
|
|
850
|
+
else {
|
|
851
|
+
return a.at - b.at;
|
|
908
852
|
}
|
|
909
853
|
}
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
const readInitialKeyframe = () => {
|
|
923
|
-
return valueName.startsWith("--")
|
|
924
|
-
? element.style.getPropertyValue(valueName)
|
|
925
|
-
: window.getComputedStyle(element)[valueName];
|
|
926
|
-
};
|
|
927
|
-
if (!Array.isArray(valueKeyframes)) {
|
|
928
|
-
valueKeyframes = [valueKeyframes];
|
|
929
|
-
}
|
|
930
|
-
hydrateKeyframes(valueName, valueKeyframes, readInitialKeyframe);
|
|
931
|
-
// TODO: Replace this with toString()?
|
|
932
|
-
if (motionDom.isGenerator(options.type)) {
|
|
933
|
-
const generatorOptions = motionDom.createGeneratorEasing(options, 100, options.type);
|
|
934
|
-
options.ease = motionDom.supportsLinearEasing()
|
|
935
|
-
? generatorOptions.ease
|
|
936
|
-
: defaultEasing;
|
|
937
|
-
options.duration = motionUtils.secondsToMilliseconds(generatorOptions.duration);
|
|
938
|
-
options.type = "keyframes";
|
|
939
|
-
}
|
|
940
|
-
else {
|
|
941
|
-
options.ease = options.ease || defaultEasing;
|
|
942
|
-
}
|
|
943
|
-
const onFinish = () => {
|
|
944
|
-
this.setValue(element, valueName, create.getFinalKeyframe(valueKeyframes, options));
|
|
945
|
-
this.cancel();
|
|
946
|
-
this.resolveFinishedPromise();
|
|
947
|
-
};
|
|
948
|
-
const init = () => {
|
|
949
|
-
this.setValue = isCSSVar ? setCSSVar : setStyle;
|
|
950
|
-
this.options = options;
|
|
951
|
-
this.updateFinishedPromise();
|
|
952
|
-
this.removeAnimation = () => {
|
|
953
|
-
const elementState = state.get(element);
|
|
954
|
-
elementState && elementState.delete(valueName);
|
|
955
|
-
};
|
|
956
|
-
};
|
|
957
|
-
if (!create.supportsWaapi()) {
|
|
958
|
-
super();
|
|
959
|
-
init();
|
|
960
|
-
onFinish();
|
|
961
|
-
}
|
|
962
|
-
else {
|
|
963
|
-
super(create.startWaapiAnimation(element, valueName, valueKeyframes, options));
|
|
964
|
-
init();
|
|
965
|
-
if (options.autoplay === false) {
|
|
966
|
-
this.animation.pause();
|
|
967
|
-
}
|
|
968
|
-
this.animation.onfinish = onFinish;
|
|
969
|
-
getElementAnimationState(element).set(valueName, this);
|
|
970
|
-
}
|
|
971
|
-
}
|
|
854
|
+
|
|
855
|
+
const defaultSegmentEasing = "easeInOut";
|
|
856
|
+
const MAX_REPEAT = 20;
|
|
857
|
+
function createAnimationsFromSequence(sequence, { defaultTransition = {}, ...sequenceTransition } = {}, scope, generators) {
|
|
858
|
+
const defaultDuration = defaultTransition.duration || 0.3;
|
|
859
|
+
const animationDefinitions = new Map();
|
|
860
|
+
const sequences = new Map();
|
|
861
|
+
const elementCache = {};
|
|
862
|
+
const timeLabels = new Map();
|
|
863
|
+
let prevTime = 0;
|
|
864
|
+
let currentTime = 0;
|
|
865
|
+
let totalDuration = 0;
|
|
972
866
|
/**
|
|
973
|
-
*
|
|
974
|
-
*
|
|
975
|
-
*
|
|
867
|
+
* Build the timeline by mapping over the sequence array and converting
|
|
868
|
+
* the definitions into keyframes and offsets with absolute time values.
|
|
869
|
+
* These will later get converted into relative offsets in a second pass.
|
|
976
870
|
*/
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
play() {
|
|
986
|
-
if (this.state === "finished") {
|
|
987
|
-
this.updateFinishedPromise();
|
|
871
|
+
for (let i = 0; i < sequence.length; i++) {
|
|
872
|
+
const segment = sequence[i];
|
|
873
|
+
/**
|
|
874
|
+
* If this is a timeline label, mark it and skip the rest of this iteration.
|
|
875
|
+
*/
|
|
876
|
+
if (typeof segment === "string") {
|
|
877
|
+
timeLabels.set(segment, currentTime);
|
|
878
|
+
continue;
|
|
988
879
|
}
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
}
|
|
995
|
-
}
|
|
996
|
-
|
|
997
|
-
function animateElements(elementOrSelector, keyframes, options, scope) {
|
|
998
|
-
const elements = motionDom.resolveElements(elementOrSelector, scope);
|
|
999
|
-
const numElements = elements.length;
|
|
1000
|
-
motionUtils.invariant(Boolean(numElements), "No valid element provided.");
|
|
1001
|
-
const animations = [];
|
|
1002
|
-
for (let i = 0; i < numElements; i++) {
|
|
1003
|
-
const element = elements[i];
|
|
1004
|
-
const elementTransition = { ...options };
|
|
880
|
+
else if (!Array.isArray(segment)) {
|
|
881
|
+
timeLabels.set(segment.name, calcNextTime(currentTime, segment.at, prevTime, timeLabels));
|
|
882
|
+
continue;
|
|
883
|
+
}
|
|
884
|
+
let [subject, keyframes, transition = {}] = segment;
|
|
1005
885
|
/**
|
|
1006
|
-
*
|
|
886
|
+
* If a relative or absolute time value has been specified we need to resolve
|
|
887
|
+
* it in relation to the currentTime.
|
|
1007
888
|
*/
|
|
1008
|
-
if (
|
|
1009
|
-
|
|
1010
|
-
}
|
|
1011
|
-
for (const valueName in keyframes) {
|
|
1012
|
-
const valueKeyframes = keyframes[valueName];
|
|
1013
|
-
const valueOptions = {
|
|
1014
|
-
...motionDom.getValueTransition(elementTransition, valueName),
|
|
1015
|
-
};
|
|
1016
|
-
valueOptions.duration = valueOptions.duration
|
|
1017
|
-
? motionUtils.secondsToMilliseconds(valueOptions.duration)
|
|
1018
|
-
: valueOptions.duration;
|
|
1019
|
-
valueOptions.delay = motionUtils.secondsToMilliseconds(valueOptions.delay || 0);
|
|
1020
|
-
valueOptions.allowFlatten =
|
|
1021
|
-
!elementTransition.type && !elementTransition.ease;
|
|
1022
|
-
animations.push(new NativeAnimation(element, valueName, valueKeyframes, valueOptions));
|
|
1023
|
-
}
|
|
1024
|
-
}
|
|
1025
|
-
return animations;
|
|
1026
|
-
}
|
|
1027
|
-
|
|
1028
|
-
const createScopedWaapiAnimate = (scope) => {
|
|
1029
|
-
function scopedAnimate(elementOrSelector, keyframes, options) {
|
|
1030
|
-
return new motionDom.GroupPlaybackControls(animateElements(elementOrSelector, keyframes, options, scope));
|
|
1031
|
-
}
|
|
1032
|
-
return scopedAnimate;
|
|
1033
|
-
};
|
|
1034
|
-
const animateMini = /*@__PURE__*/ createScopedWaapiAnimate();
|
|
1035
|
-
|
|
1036
|
-
function observeTimeline(update, timeline) {
|
|
1037
|
-
let prevProgress;
|
|
1038
|
-
const onFrame = () => {
|
|
1039
|
-
const { currentTime } = timeline;
|
|
1040
|
-
const percentage = currentTime === null ? 0 : currentTime.value;
|
|
1041
|
-
const progress = percentage / 100;
|
|
1042
|
-
if (prevProgress !== progress) {
|
|
1043
|
-
update(progress);
|
|
1044
|
-
}
|
|
1045
|
-
prevProgress = progress;
|
|
1046
|
-
};
|
|
1047
|
-
create.frame.update(onFrame, true);
|
|
1048
|
-
return () => create.cancelFrame(onFrame);
|
|
1049
|
-
}
|
|
1050
|
-
|
|
1051
|
-
const resizeHandlers = new WeakMap();
|
|
1052
|
-
let observer;
|
|
1053
|
-
function getElementSize(target, borderBoxSize) {
|
|
1054
|
-
if (borderBoxSize) {
|
|
1055
|
-
const { inlineSize, blockSize } = borderBoxSize[0];
|
|
1056
|
-
return { width: inlineSize, height: blockSize };
|
|
1057
|
-
}
|
|
1058
|
-
else if (target instanceof SVGElement && "getBBox" in target) {
|
|
1059
|
-
return target.getBBox();
|
|
1060
|
-
}
|
|
1061
|
-
else {
|
|
1062
|
-
return {
|
|
1063
|
-
width: target.offsetWidth,
|
|
1064
|
-
height: target.offsetHeight,
|
|
1065
|
-
};
|
|
1066
|
-
}
|
|
1067
|
-
}
|
|
1068
|
-
function notifyTarget({ target, contentRect, borderBoxSize, }) {
|
|
1069
|
-
var _a;
|
|
1070
|
-
(_a = resizeHandlers.get(target)) === null || _a === void 0 ? void 0 : _a.forEach((handler) => {
|
|
1071
|
-
handler({
|
|
1072
|
-
target,
|
|
1073
|
-
contentSize: contentRect,
|
|
1074
|
-
get size() {
|
|
1075
|
-
return getElementSize(target, borderBoxSize);
|
|
1076
|
-
},
|
|
1077
|
-
});
|
|
1078
|
-
});
|
|
1079
|
-
}
|
|
1080
|
-
function notifyAll(entries) {
|
|
1081
|
-
entries.forEach(notifyTarget);
|
|
1082
|
-
}
|
|
1083
|
-
function createResizeObserver() {
|
|
1084
|
-
if (typeof ResizeObserver === "undefined")
|
|
1085
|
-
return;
|
|
1086
|
-
observer = new ResizeObserver(notifyAll);
|
|
1087
|
-
}
|
|
1088
|
-
function resizeElement(target, handler) {
|
|
1089
|
-
if (!observer)
|
|
1090
|
-
createResizeObserver();
|
|
1091
|
-
const elements = motionDom.resolveElements(target);
|
|
1092
|
-
elements.forEach((element) => {
|
|
1093
|
-
let elementHandlers = resizeHandlers.get(element);
|
|
1094
|
-
if (!elementHandlers) {
|
|
1095
|
-
elementHandlers = new Set();
|
|
1096
|
-
resizeHandlers.set(element, elementHandlers);
|
|
889
|
+
if (transition.at !== undefined) {
|
|
890
|
+
currentTime = calcNextTime(currentTime, transition.at, prevTime, timeLabels);
|
|
1097
891
|
}
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
892
|
+
/**
|
|
893
|
+
* Keep track of the maximum duration in this definition. This will be
|
|
894
|
+
* applied to currentTime once the definition has been parsed.
|
|
895
|
+
*/
|
|
896
|
+
let maxDuration = 0;
|
|
897
|
+
const resolveValueSequence = (valueKeyframes, valueTransition, valueSequence, elementIndex = 0, numSubjects = 0) => {
|
|
898
|
+
const valueKeyframesAsList = keyframesAsList(valueKeyframes);
|
|
899
|
+
const { delay = 0, times = create.defaultOffset(valueKeyframesAsList), type = "keyframes", repeat, repeatType, repeatDelay = 0, ...remainingTransition } = valueTransition;
|
|
900
|
+
let { ease = defaultTransition.ease || "easeOut", duration } = valueTransition;
|
|
901
|
+
/**
|
|
902
|
+
* Resolve stagger() if defined.
|
|
903
|
+
*/
|
|
904
|
+
const calculatedDelay = typeof delay === "function"
|
|
905
|
+
? delay(elementIndex, numSubjects)
|
|
906
|
+
: delay;
|
|
907
|
+
/**
|
|
908
|
+
* If this animation should and can use a spring, generate a spring easing function.
|
|
909
|
+
*/
|
|
910
|
+
const numKeyframes = valueKeyframesAsList.length;
|
|
911
|
+
const createGenerator = motionDom.isGenerator(type)
|
|
912
|
+
? type
|
|
913
|
+
: generators === null || generators === void 0 ? void 0 : generators[type];
|
|
914
|
+
if (numKeyframes <= 2 && createGenerator) {
|
|
915
|
+
/**
|
|
916
|
+
* As we're creating an easing function from a spring,
|
|
917
|
+
* ideally we want to generate it using the real distance
|
|
918
|
+
* between the two keyframes. However this isn't always
|
|
919
|
+
* possible - in these situations we use 0-100.
|
|
920
|
+
*/
|
|
921
|
+
let absoluteDelta = 100;
|
|
922
|
+
if (numKeyframes === 2 &&
|
|
923
|
+
isNumberKeyframesArray(valueKeyframesAsList)) {
|
|
924
|
+
const delta = valueKeyframesAsList[1] - valueKeyframesAsList[0];
|
|
925
|
+
absoluteDelta = Math.abs(delta);
|
|
926
|
+
}
|
|
927
|
+
const springTransition = { ...remainingTransition };
|
|
928
|
+
if (duration !== undefined) {
|
|
929
|
+
springTransition.duration = motionUtils.secondsToMilliseconds(duration);
|
|
930
|
+
}
|
|
931
|
+
const springEasing = motionDom.createGeneratorEasing(springTransition, absoluteDelta, createGenerator);
|
|
932
|
+
ease = springEasing.ease;
|
|
933
|
+
duration = springEasing.duration;
|
|
1107
934
|
}
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
}
|
|
1111
|
-
|
|
1112
|
-
const windowCallbacks = new Set();
|
|
1113
|
-
let windowResizeHandler;
|
|
1114
|
-
function createWindowResizeHandler() {
|
|
1115
|
-
windowResizeHandler = () => {
|
|
1116
|
-
const size = {
|
|
1117
|
-
width: window.innerWidth,
|
|
1118
|
-
height: window.innerHeight,
|
|
1119
|
-
};
|
|
1120
|
-
const info = {
|
|
1121
|
-
target: window,
|
|
1122
|
-
size,
|
|
1123
|
-
contentSize: size,
|
|
1124
|
-
};
|
|
1125
|
-
windowCallbacks.forEach((callback) => callback(info));
|
|
1126
|
-
};
|
|
1127
|
-
window.addEventListener("resize", windowResizeHandler);
|
|
1128
|
-
}
|
|
1129
|
-
function resizeWindow(callback) {
|
|
1130
|
-
windowCallbacks.add(callback);
|
|
1131
|
-
if (!windowResizeHandler)
|
|
1132
|
-
createWindowResizeHandler();
|
|
1133
|
-
return () => {
|
|
1134
|
-
windowCallbacks.delete(callback);
|
|
1135
|
-
if (!windowCallbacks.size && windowResizeHandler) {
|
|
1136
|
-
windowResizeHandler = undefined;
|
|
1137
|
-
}
|
|
1138
|
-
};
|
|
1139
|
-
}
|
|
1140
|
-
|
|
1141
|
-
function resize(a, b) {
|
|
1142
|
-
return typeof a === "function" ? resizeWindow(a) : resizeElement(a, b);
|
|
1143
|
-
}
|
|
1144
|
-
|
|
1145
|
-
/**
|
|
1146
|
-
* A time in milliseconds, beyond which we consider the scroll velocity to be 0.
|
|
1147
|
-
*/
|
|
1148
|
-
const maxElapsed = 50;
|
|
1149
|
-
const createAxisInfo = () => ({
|
|
1150
|
-
current: 0,
|
|
1151
|
-
offset: [],
|
|
1152
|
-
progress: 0,
|
|
1153
|
-
scrollLength: 0,
|
|
1154
|
-
targetOffset: 0,
|
|
1155
|
-
targetLength: 0,
|
|
1156
|
-
containerLength: 0,
|
|
1157
|
-
velocity: 0,
|
|
1158
|
-
});
|
|
1159
|
-
const createScrollInfo = () => ({
|
|
1160
|
-
time: 0,
|
|
1161
|
-
x: createAxisInfo(),
|
|
1162
|
-
y: createAxisInfo(),
|
|
1163
|
-
});
|
|
1164
|
-
const keys = {
|
|
1165
|
-
x: {
|
|
1166
|
-
length: "Width",
|
|
1167
|
-
position: "Left",
|
|
1168
|
-
},
|
|
1169
|
-
y: {
|
|
1170
|
-
length: "Height",
|
|
1171
|
-
position: "Top",
|
|
1172
|
-
},
|
|
1173
|
-
};
|
|
1174
|
-
function updateAxisInfo(element, axisName, info, time) {
|
|
1175
|
-
const axis = info[axisName];
|
|
1176
|
-
const { length, position } = keys[axisName];
|
|
1177
|
-
const prev = axis.current;
|
|
1178
|
-
const prevTime = info.time;
|
|
1179
|
-
axis.current = element[`scroll${position}`];
|
|
1180
|
-
axis.scrollLength = element[`scroll${length}`] - element[`client${length}`];
|
|
1181
|
-
axis.offset.length = 0;
|
|
1182
|
-
axis.offset[0] = 0;
|
|
1183
|
-
axis.offset[1] = axis.scrollLength;
|
|
1184
|
-
axis.progress = motionUtils.progress(0, axis.scrollLength, axis.current);
|
|
1185
|
-
const elapsed = time - prevTime;
|
|
1186
|
-
axis.velocity =
|
|
1187
|
-
elapsed > maxElapsed
|
|
1188
|
-
? 0
|
|
1189
|
-
: create.velocityPerSecond(axis.current - prev, elapsed);
|
|
1190
|
-
}
|
|
1191
|
-
function updateScrollInfo(element, info, time) {
|
|
1192
|
-
updateAxisInfo(element, "x", info, time);
|
|
1193
|
-
updateAxisInfo(element, "y", info, time);
|
|
1194
|
-
info.time = time;
|
|
1195
|
-
}
|
|
1196
|
-
|
|
1197
|
-
function calcInset(element, container) {
|
|
1198
|
-
const inset = { x: 0, y: 0 };
|
|
1199
|
-
let current = element;
|
|
1200
|
-
while (current && current !== container) {
|
|
1201
|
-
if (current instanceof HTMLElement) {
|
|
1202
|
-
inset.x += current.offsetLeft;
|
|
1203
|
-
inset.y += current.offsetTop;
|
|
1204
|
-
current = current.offsetParent;
|
|
1205
|
-
}
|
|
1206
|
-
else if (current.tagName === "svg") {
|
|
935
|
+
duration !== null && duration !== void 0 ? duration : (duration = defaultDuration);
|
|
936
|
+
const startTime = currentTime + calculatedDelay;
|
|
1207
937
|
/**
|
|
1208
|
-
*
|
|
1209
|
-
* It would be preferable, given they behave like HTMLElements in most ways
|
|
1210
|
-
* to use offsetLeft/Top. But these don't exist on <svg />. Likewise we
|
|
1211
|
-
* can't use .getBBox() like most SVG elements as these provide the offset
|
|
1212
|
-
* relative to the SVG itself, which for <svg /> is usually 0x0.
|
|
938
|
+
* If there's only one time offset of 0, fill in a second with length 1
|
|
1213
939
|
*/
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
940
|
+
if (times.length === 1 && times[0] === 0) {
|
|
941
|
+
times[1] = 1;
|
|
942
|
+
}
|
|
943
|
+
/**
|
|
944
|
+
* Fill out if offset if fewer offsets than keyframes
|
|
945
|
+
*/
|
|
946
|
+
const remainder = times.length - valueKeyframesAsList.length;
|
|
947
|
+
remainder > 0 && create.fillOffset(times, remainder);
|
|
948
|
+
/**
|
|
949
|
+
* If only one value has been set, ie [1], push a null to the start of
|
|
950
|
+
* the keyframe array. This will let us mark a keyframe at this point
|
|
951
|
+
* that will later be hydrated with the previous value.
|
|
952
|
+
*/
|
|
953
|
+
valueKeyframesAsList.length === 1 &&
|
|
954
|
+
valueKeyframesAsList.unshift(null);
|
|
955
|
+
/**
|
|
956
|
+
* Handle repeat options
|
|
957
|
+
*/
|
|
958
|
+
if (repeat) {
|
|
959
|
+
motionUtils.invariant(repeat < MAX_REPEAT, "Repeat count too high, must be less than 20");
|
|
960
|
+
duration = calculateRepeatDuration(duration, repeat);
|
|
961
|
+
const originalKeyframes = [...valueKeyframesAsList];
|
|
962
|
+
const originalTimes = [...times];
|
|
963
|
+
ease = Array.isArray(ease) ? [...ease] : [ease];
|
|
964
|
+
const originalEase = [...ease];
|
|
965
|
+
for (let repeatIndex = 0; repeatIndex < repeat; repeatIndex++) {
|
|
966
|
+
valueKeyframesAsList.push(...originalKeyframes);
|
|
967
|
+
for (let keyframeIndex = 0; keyframeIndex < originalKeyframes.length; keyframeIndex++) {
|
|
968
|
+
times.push(originalTimes[keyframeIndex] + (repeatIndex + 1));
|
|
969
|
+
ease.push(keyframeIndex === 0
|
|
970
|
+
? "linear"
|
|
971
|
+
: getEasingForSegment(originalEase, keyframeIndex - 1));
|
|
972
|
+
}
|
|
1229
973
|
}
|
|
1230
|
-
|
|
974
|
+
normalizeTimes(times, repeat);
|
|
1231
975
|
}
|
|
1232
|
-
|
|
976
|
+
const targetTime = startTime + duration;
|
|
977
|
+
/**
|
|
978
|
+
* Add keyframes, mapping offsets to absolute time.
|
|
979
|
+
*/
|
|
980
|
+
addKeyframes(valueSequence, valueKeyframesAsList, ease, times, startTime, targetTime);
|
|
981
|
+
maxDuration = Math.max(calculatedDelay + duration, maxDuration);
|
|
982
|
+
totalDuration = Math.max(targetTime, totalDuration);
|
|
983
|
+
};
|
|
984
|
+
if (create.isMotionValue(subject)) {
|
|
985
|
+
const subjectSequence = getSubjectSequence(subject, sequences);
|
|
986
|
+
resolveValueSequence(keyframes, transition, getValueSequence("default", subjectSequence));
|
|
1233
987
|
}
|
|
1234
988
|
else {
|
|
1235
|
-
|
|
989
|
+
const subjects = resolveSubjects(subject, keyframes, scope, elementCache);
|
|
990
|
+
const numSubjects = subjects.length;
|
|
991
|
+
/**
|
|
992
|
+
* For every element in this segment, process the defined values.
|
|
993
|
+
*/
|
|
994
|
+
for (let subjectIndex = 0; subjectIndex < numSubjects; subjectIndex++) {
|
|
995
|
+
/**
|
|
996
|
+
* Cast necessary, but we know these are of this type
|
|
997
|
+
*/
|
|
998
|
+
keyframes = keyframes;
|
|
999
|
+
transition = transition;
|
|
1000
|
+
const thisSubject = subjects[subjectIndex];
|
|
1001
|
+
const subjectSequence = getSubjectSequence(thisSubject, sequences);
|
|
1002
|
+
for (const key in keyframes) {
|
|
1003
|
+
resolveValueSequence(keyframes[key], getValueTransition(transition, key), getValueSequence(key, subjectSequence), subjectIndex, numSubjects);
|
|
1004
|
+
}
|
|
1005
|
+
}
|
|
1236
1006
|
}
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
}
|
|
1240
|
-
|
|
1241
|
-
const namedEdges = {
|
|
1242
|
-
start: 0,
|
|
1243
|
-
center: 0.5,
|
|
1244
|
-
end: 1,
|
|
1245
|
-
};
|
|
1246
|
-
function resolveEdge(edge, length, inset = 0) {
|
|
1247
|
-
let delta = 0;
|
|
1248
|
-
/**
|
|
1249
|
-
* If we have this edge defined as a preset, replace the definition
|
|
1250
|
-
* with the numerical value.
|
|
1251
|
-
*/
|
|
1252
|
-
if (edge in namedEdges) {
|
|
1253
|
-
edge = namedEdges[edge];
|
|
1007
|
+
prevTime = currentTime;
|
|
1008
|
+
currentTime += maxDuration;
|
|
1254
1009
|
}
|
|
1255
1010
|
/**
|
|
1256
|
-
*
|
|
1011
|
+
* For every element and value combination create a new animation.
|
|
1257
1012
|
*/
|
|
1258
|
-
|
|
1259
|
-
const
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1013
|
+
sequences.forEach((valueSequences, element) => {
|
|
1014
|
+
for (const key in valueSequences) {
|
|
1015
|
+
const valueSequence = valueSequences[key];
|
|
1016
|
+
/**
|
|
1017
|
+
* Arrange all the keyframes in ascending time order.
|
|
1018
|
+
*/
|
|
1019
|
+
valueSequence.sort(compareByTime);
|
|
1020
|
+
const keyframes = [];
|
|
1021
|
+
const valueOffset = [];
|
|
1022
|
+
const valueEasing = [];
|
|
1023
|
+
/**
|
|
1024
|
+
* For each keyframe, translate absolute times into
|
|
1025
|
+
* relative offsets based on the total duration of the timeline.
|
|
1026
|
+
*/
|
|
1027
|
+
for (let i = 0; i < valueSequence.length; i++) {
|
|
1028
|
+
const { at, value, easing } = valueSequence[i];
|
|
1029
|
+
keyframes.push(value);
|
|
1030
|
+
valueOffset.push(motionUtils.progress(0, totalDuration, at));
|
|
1031
|
+
valueEasing.push(easing || "easeOut");
|
|
1032
|
+
}
|
|
1033
|
+
/**
|
|
1034
|
+
* If the first keyframe doesn't land on offset: 0
|
|
1035
|
+
* provide one by duplicating the initial keyframe. This ensures
|
|
1036
|
+
* it snaps to the first keyframe when the animation starts.
|
|
1037
|
+
*/
|
|
1038
|
+
if (valueOffset[0] !== 0) {
|
|
1039
|
+
valueOffset.unshift(0);
|
|
1040
|
+
keyframes.unshift(keyframes[0]);
|
|
1041
|
+
valueEasing.unshift(defaultSegmentEasing);
|
|
1042
|
+
}
|
|
1043
|
+
/**
|
|
1044
|
+
* If the last keyframe doesn't land on offset: 1
|
|
1045
|
+
* provide one with a null wildcard value. This will ensure it
|
|
1046
|
+
* stays static until the end of the animation.
|
|
1047
|
+
*/
|
|
1048
|
+
if (valueOffset[valueOffset.length - 1] !== 1) {
|
|
1049
|
+
valueOffset.push(1);
|
|
1050
|
+
keyframes.push(null);
|
|
1051
|
+
}
|
|
1052
|
+
if (!animationDefinitions.has(element)) {
|
|
1053
|
+
animationDefinitions.set(element, {
|
|
1054
|
+
keyframes: {},
|
|
1055
|
+
transition: {},
|
|
1056
|
+
});
|
|
1057
|
+
}
|
|
1058
|
+
const definition = animationDefinitions.get(element);
|
|
1059
|
+
definition.keyframes[key] = keyframes;
|
|
1060
|
+
definition.transition[key] = {
|
|
1061
|
+
...defaultTransition,
|
|
1062
|
+
duration: totalDuration,
|
|
1063
|
+
ease: valueEasing,
|
|
1064
|
+
times: valueOffset,
|
|
1065
|
+
...sequenceTransition,
|
|
1066
|
+
};
|
|
1268
1067
|
}
|
|
1269
|
-
|
|
1270
|
-
|
|
1068
|
+
});
|
|
1069
|
+
return animationDefinitions;
|
|
1070
|
+
}
|
|
1071
|
+
function getSubjectSequence(subject, sequences) {
|
|
1072
|
+
!sequences.has(subject) && sequences.set(subject, {});
|
|
1073
|
+
return sequences.get(subject);
|
|
1074
|
+
}
|
|
1075
|
+
function getValueSequence(name, sequences) {
|
|
1076
|
+
if (!sequences[name])
|
|
1077
|
+
sequences[name] = [];
|
|
1078
|
+
return sequences[name];
|
|
1079
|
+
}
|
|
1080
|
+
function keyframesAsList(keyframes) {
|
|
1081
|
+
return Array.isArray(keyframes) ? keyframes : [keyframes];
|
|
1082
|
+
}
|
|
1083
|
+
function getValueTransition(transition, key) {
|
|
1084
|
+
return transition && transition[key]
|
|
1085
|
+
? {
|
|
1086
|
+
...transition,
|
|
1087
|
+
...transition[key],
|
|
1271
1088
|
}
|
|
1272
|
-
|
|
1273
|
-
|
|
1089
|
+
: { ...transition };
|
|
1090
|
+
}
|
|
1091
|
+
const isNumber = (keyframe) => typeof keyframe === "number";
|
|
1092
|
+
const isNumberKeyframesArray = (keyframes) => keyframes.every(isNumber);
|
|
1093
|
+
|
|
1094
|
+
function isObjectKey(key, object) {
|
|
1095
|
+
return key in object;
|
|
1096
|
+
}
|
|
1097
|
+
class ObjectVisualElement extends create.VisualElement {
|
|
1098
|
+
constructor() {
|
|
1099
|
+
super(...arguments);
|
|
1100
|
+
this.type = "object";
|
|
1101
|
+
}
|
|
1102
|
+
readValueFromInstance(instance, key) {
|
|
1103
|
+
if (isObjectKey(key, instance)) {
|
|
1104
|
+
const value = instance[key];
|
|
1105
|
+
if (typeof value === "string" || typeof value === "number") {
|
|
1106
|
+
return value;
|
|
1107
|
+
}
|
|
1274
1108
|
}
|
|
1109
|
+
return undefined;
|
|
1275
1110
|
}
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1111
|
+
getBaseTargetFromProps() {
|
|
1112
|
+
return undefined;
|
|
1113
|
+
}
|
|
1114
|
+
removeValueFromRenderState(key, renderState) {
|
|
1115
|
+
delete renderState.output[key];
|
|
1116
|
+
}
|
|
1117
|
+
measureInstanceViewportBox() {
|
|
1118
|
+
return create.createBox();
|
|
1119
|
+
}
|
|
1120
|
+
build(renderState, latestValues) {
|
|
1121
|
+
Object.assign(renderState.output, latestValues);
|
|
1122
|
+
}
|
|
1123
|
+
renderInstance(instance, { output }) {
|
|
1124
|
+
Object.assign(instance, output);
|
|
1125
|
+
}
|
|
1126
|
+
sortInstanceNodePosition() {
|
|
1127
|
+
return 0;
|
|
1281
1128
|
}
|
|
1282
|
-
return inset + delta;
|
|
1283
1129
|
}
|
|
1284
1130
|
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1131
|
+
function createDOMVisualElement(element) {
|
|
1132
|
+
const options = {
|
|
1133
|
+
presenceContext: null,
|
|
1134
|
+
props: {},
|
|
1135
|
+
visualState: {
|
|
1136
|
+
renderState: {
|
|
1137
|
+
transform: {},
|
|
1138
|
+
transformOrigin: {},
|
|
1139
|
+
style: {},
|
|
1140
|
+
vars: {},
|
|
1141
|
+
attrs: {},
|
|
1142
|
+
},
|
|
1143
|
+
latestValues: {},
|
|
1144
|
+
},
|
|
1145
|
+
};
|
|
1146
|
+
const node = create.isSVGElement(element)
|
|
1147
|
+
? new create.SVGVisualElement(options)
|
|
1148
|
+
: new create.HTMLVisualElement(options);
|
|
1149
|
+
node.mount(element);
|
|
1150
|
+
create.visualElementStore.set(element, node);
|
|
1151
|
+
}
|
|
1152
|
+
function createObjectVisualElement(subject) {
|
|
1153
|
+
const options = {
|
|
1154
|
+
presenceContext: null,
|
|
1155
|
+
props: {},
|
|
1156
|
+
visualState: {
|
|
1157
|
+
renderState: {
|
|
1158
|
+
output: {},
|
|
1159
|
+
},
|
|
1160
|
+
latestValues: {},
|
|
1161
|
+
},
|
|
1162
|
+
};
|
|
1163
|
+
const node = new ObjectVisualElement(options);
|
|
1164
|
+
node.mount(subject);
|
|
1165
|
+
create.visualElementStore.set(subject, node);
|
|
1166
|
+
}
|
|
1167
|
+
|
|
1168
|
+
function isSingleValue(subject, keyframes) {
|
|
1169
|
+
return (create.isMotionValue(subject) ||
|
|
1170
|
+
typeof subject === "number" ||
|
|
1171
|
+
(typeof subject === "string" && !isDOMKeyframes(keyframes)));
|
|
1172
|
+
}
|
|
1173
|
+
/**
|
|
1174
|
+
* Implementation
|
|
1175
|
+
*/
|
|
1176
|
+
function animateSubject(subject, keyframes, options, scope) {
|
|
1177
|
+
const animations = [];
|
|
1178
|
+
if (isSingleValue(subject, keyframes)) {
|
|
1179
|
+
animations.push(create.animateSingleValue(subject, isDOMKeyframes(keyframes)
|
|
1180
|
+
? keyframes.default || keyframes
|
|
1181
|
+
: keyframes, options ? options.default || options : options));
|
|
1297
1182
|
}
|
|
1298
|
-
else
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1183
|
+
else {
|
|
1184
|
+
const subjects = resolveSubjects(subject, keyframes, scope);
|
|
1185
|
+
const numSubjects = subjects.length;
|
|
1186
|
+
motionUtils.invariant(Boolean(numSubjects), "No valid elements provided.");
|
|
1187
|
+
for (let i = 0; i < numSubjects; i++) {
|
|
1188
|
+
const thisSubject = subjects[i];
|
|
1189
|
+
const createVisualElement = thisSubject instanceof Element
|
|
1190
|
+
? createDOMVisualElement
|
|
1191
|
+
: createObjectVisualElement;
|
|
1192
|
+
if (!create.visualElementStore.has(thisSubject)) {
|
|
1193
|
+
createVisualElement(thisSubject);
|
|
1194
|
+
}
|
|
1195
|
+
const visualElement = create.visualElementStore.get(thisSubject);
|
|
1196
|
+
const transition = { ...options };
|
|
1304
1197
|
/**
|
|
1305
|
-
*
|
|
1306
|
-
* that only to the top of the target point, leaving the container at 0.
|
|
1307
|
-
* Whereas a named offset like "end" should be applied to both.
|
|
1198
|
+
* Resolve stagger function if provided.
|
|
1308
1199
|
*/
|
|
1309
|
-
|
|
1200
|
+
if ("delay" in transition &&
|
|
1201
|
+
typeof transition.delay === "function") {
|
|
1202
|
+
transition.delay = transition.delay(i, numSubjects);
|
|
1203
|
+
}
|
|
1204
|
+
animations.push(...create.animateTarget(visualElement, { ...keyframes, transition }, {}));
|
|
1310
1205
|
}
|
|
1311
1206
|
}
|
|
1312
|
-
|
|
1313
|
-
containerPoint = resolveEdge(offsetDefinition[1], containerLength);
|
|
1314
|
-
return targetPoint - containerPoint;
|
|
1207
|
+
return animations;
|
|
1315
1208
|
}
|
|
1316
1209
|
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
],
|
|
1326
|
-
Any: [
|
|
1327
|
-
[1, 0],
|
|
1328
|
-
[0, 1],
|
|
1329
|
-
],
|
|
1330
|
-
All: [
|
|
1331
|
-
[0, 0],
|
|
1332
|
-
[1, 1],
|
|
1333
|
-
],
|
|
1334
|
-
};
|
|
1210
|
+
function animateSequence(sequence, options, scope) {
|
|
1211
|
+
const animations = [];
|
|
1212
|
+
const animationDefinitions = createAnimationsFromSequence(sequence, options, scope, { spring: create.spring });
|
|
1213
|
+
animationDefinitions.forEach(({ keyframes, transition }, subject) => {
|
|
1214
|
+
animations.push(...animateSubject(subject, keyframes, transition));
|
|
1215
|
+
});
|
|
1216
|
+
return animations;
|
|
1217
|
+
}
|
|
1335
1218
|
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
return "getBBox" in target && target.tagName !== "svg"
|
|
1339
|
-
? target.getBBox()
|
|
1340
|
-
: { width: target.clientWidth, height: target.clientHeight };
|
|
1219
|
+
function isSequence(value) {
|
|
1220
|
+
return Array.isArray(value) && value.some(Array.isArray);
|
|
1341
1221
|
}
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
/**
|
|
1348
|
-
* Measure the target and container. If they're the same thing then we
|
|
1349
|
-
* use the container's scrollWidth/Height as the target, from there
|
|
1350
|
-
* all other calculations can remain the same.
|
|
1351
|
-
*/
|
|
1352
|
-
const targetSize = target === container
|
|
1353
|
-
? { width: container.scrollWidth, height: container.scrollHeight }
|
|
1354
|
-
: getTargetSize(target);
|
|
1355
|
-
const containerSize = {
|
|
1356
|
-
width: container.clientWidth,
|
|
1357
|
-
height: container.clientHeight,
|
|
1358
|
-
};
|
|
1359
|
-
/**
|
|
1360
|
-
* Reset the length of the resolved offset array rather than creating a new one.
|
|
1361
|
-
* TODO: More reusable data structures for targetSize/containerSize would also be good.
|
|
1362
|
-
*/
|
|
1363
|
-
info[axis].offset.length = 0;
|
|
1222
|
+
/**
|
|
1223
|
+
* Creates an animation function that is optionally scoped
|
|
1224
|
+
* to a specific element.
|
|
1225
|
+
*/
|
|
1226
|
+
function createScopedAnimate(scope) {
|
|
1364
1227
|
/**
|
|
1365
|
-
*
|
|
1366
|
-
* a list of pixel scroll offets.
|
|
1228
|
+
* Implementation
|
|
1367
1229
|
*/
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
|
|
1372
|
-
if (!hasChanged && offset !== info[axis].interpolatorOffsets[i]) {
|
|
1373
|
-
hasChanged = true;
|
|
1230
|
+
function scopedAnimate(subjectOrSequence, optionsOrKeyframes, options) {
|
|
1231
|
+
let animations = [];
|
|
1232
|
+
if (isSequence(subjectOrSequence)) {
|
|
1233
|
+
animations = animateSequence(subjectOrSequence, optionsOrKeyframes, scope);
|
|
1374
1234
|
}
|
|
1375
|
-
|
|
1235
|
+
else {
|
|
1236
|
+
animations = animateSubject(subjectOrSequence, optionsOrKeyframes, options, scope);
|
|
1237
|
+
}
|
|
1238
|
+
const animation = new motionDom.GroupPlaybackControls(animations);
|
|
1239
|
+
if (scope) {
|
|
1240
|
+
scope.animations.push(animation);
|
|
1241
|
+
}
|
|
1242
|
+
return animation;
|
|
1376
1243
|
}
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1244
|
+
return scopedAnimate;
|
|
1245
|
+
}
|
|
1246
|
+
const animate = createScopedAnimate();
|
|
1247
|
+
|
|
1248
|
+
function setCSSVar(element, name, value) {
|
|
1249
|
+
element.style.setProperty(name, value);
|
|
1250
|
+
}
|
|
1251
|
+
function setStyle(element, name, value) {
|
|
1252
|
+
element.style[name] = value;
|
|
1253
|
+
}
|
|
1254
|
+
|
|
1255
|
+
const supportsPartialKeyframes = /*@__PURE__*/ motionUtils.memo(() => {
|
|
1256
|
+
try {
|
|
1257
|
+
document.createElement("div").animate({ opacity: [1] });
|
|
1384
1258
|
}
|
|
1385
|
-
|
|
1386
|
-
|
|
1259
|
+
catch (e) {
|
|
1260
|
+
return false;
|
|
1261
|
+
}
|
|
1262
|
+
return true;
|
|
1263
|
+
});
|
|
1387
1264
|
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
info.y.targetOffset = 0;
|
|
1394
|
-
if (target !== container) {
|
|
1395
|
-
let node = target;
|
|
1396
|
-
while (node && node !== container) {
|
|
1397
|
-
info.x.targetOffset += node.offsetLeft;
|
|
1398
|
-
info.y.targetOffset += node.offsetTop;
|
|
1399
|
-
node = node.offsetParent;
|
|
1265
|
+
const state = new WeakMap();
|
|
1266
|
+
function hydrateKeyframes(valueName, keyframes, read) {
|
|
1267
|
+
for (let i = 0; i < keyframes.length; i++) {
|
|
1268
|
+
if (keyframes[i] === null) {
|
|
1269
|
+
keyframes[i] = i === 0 ? read() : keyframes[i - 1];
|
|
1400
1270
|
}
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
info.y.targetLength =
|
|
1405
|
-
target === container ? target.scrollHeight : target.clientHeight;
|
|
1406
|
-
info.x.containerLength = container.clientWidth;
|
|
1407
|
-
info.y.containerLength = container.clientHeight;
|
|
1408
|
-
/**
|
|
1409
|
-
* In development mode ensure scroll containers aren't position: static as this makes
|
|
1410
|
-
* it difficult to measure their relative positions.
|
|
1411
|
-
*/
|
|
1412
|
-
if (process.env.NODE_ENV !== "production") {
|
|
1413
|
-
if (container && target && target !== container) {
|
|
1414
|
-
create.warnOnce(getComputedStyle(container).position !== "static", "Please ensure that the container has a non-static position, like 'relative', 'fixed', or 'absolute' to ensure scroll offset is calculated correctly.");
|
|
1271
|
+
if (typeof keyframes[i] === "number" &&
|
|
1272
|
+
create.browserNumberValueTypes[valueName]) {
|
|
1273
|
+
keyframes[i] = create.browserNumberValueTypes[valueName].transform(keyframes[i]);
|
|
1415
1274
|
}
|
|
1416
1275
|
}
|
|
1276
|
+
if (!supportsPartialKeyframes() && keyframes.length < 2) {
|
|
1277
|
+
keyframes.unshift(read());
|
|
1278
|
+
}
|
|
1417
1279
|
}
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
if (options.offset || options.target) {
|
|
1424
|
-
resolveOffsets(element, info, options);
|
|
1425
|
-
}
|
|
1426
|
-
},
|
|
1427
|
-
notify: () => onScroll(info),
|
|
1428
|
-
};
|
|
1280
|
+
const defaultEasing = "easeOut";
|
|
1281
|
+
function getElementAnimationState(element) {
|
|
1282
|
+
const animationState = state.get(element) || new Map();
|
|
1283
|
+
state.set(element, animationState);
|
|
1284
|
+
return state.get(element);
|
|
1429
1285
|
}
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
const
|
|
1433
|
-
|
|
1434
|
-
const
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
*/
|
|
1441
|
-
if (!containerHandlers) {
|
|
1442
|
-
containerHandlers = new Set();
|
|
1443
|
-
onScrollHandlers.set(container, containerHandlers);
|
|
1444
|
-
}
|
|
1445
|
-
/**
|
|
1446
|
-
* Create a new onScroll handler for the provided callback.
|
|
1447
|
-
*/
|
|
1448
|
-
const info = createScrollInfo();
|
|
1449
|
-
const containerHandler = createOnScrollHandler(container, onScroll, info, options);
|
|
1450
|
-
containerHandlers.add(containerHandler);
|
|
1451
|
-
/**
|
|
1452
|
-
* Check if there's a scroll event listener for this container.
|
|
1453
|
-
* If not, create one.
|
|
1454
|
-
*/
|
|
1455
|
-
if (!scrollListeners.has(container)) {
|
|
1456
|
-
const measureAll = () => {
|
|
1457
|
-
for (const handler of containerHandlers)
|
|
1458
|
-
handler.measure();
|
|
1459
|
-
};
|
|
1460
|
-
const updateAll = () => {
|
|
1461
|
-
for (const handler of containerHandlers) {
|
|
1462
|
-
handler.update(create.frameData.timestamp);
|
|
1463
|
-
}
|
|
1286
|
+
class NativeAnimation extends motionDom.NativeAnimationControls {
|
|
1287
|
+
constructor(element, valueName, valueKeyframes, options) {
|
|
1288
|
+
const isCSSVar = valueName.startsWith("--");
|
|
1289
|
+
motionUtils.invariant(typeof options.type !== "string", `animateMini doesn't support "type" as a string. Did you mean to import { spring } from "framer-motion"?`);
|
|
1290
|
+
const existingAnimation = getElementAnimationState(element).get(valueName);
|
|
1291
|
+
existingAnimation && existingAnimation.stop();
|
|
1292
|
+
const readInitialKeyframe = () => {
|
|
1293
|
+
return valueName.startsWith("--")
|
|
1294
|
+
? element.style.getPropertyValue(valueName)
|
|
1295
|
+
: window.getComputedStyle(element)[valueName];
|
|
1464
1296
|
};
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1297
|
+
if (!Array.isArray(valueKeyframes)) {
|
|
1298
|
+
valueKeyframes = [valueKeyframes];
|
|
1299
|
+
}
|
|
1300
|
+
hydrateKeyframes(valueName, valueKeyframes, readInitialKeyframe);
|
|
1301
|
+
// TODO: Replace this with toString()?
|
|
1302
|
+
if (motionDom.isGenerator(options.type)) {
|
|
1303
|
+
const generatorOptions = motionDom.createGeneratorEasing(options, 100, options.type);
|
|
1304
|
+
options.ease = motionDom.supportsLinearEasing()
|
|
1305
|
+
? generatorOptions.ease
|
|
1306
|
+
: defaultEasing;
|
|
1307
|
+
options.duration = motionUtils.secondsToMilliseconds(generatorOptions.duration);
|
|
1308
|
+
options.type = "keyframes";
|
|
1309
|
+
}
|
|
1310
|
+
else {
|
|
1311
|
+
options.ease = options.ease || defaultEasing;
|
|
1312
|
+
}
|
|
1313
|
+
const onFinish = () => {
|
|
1314
|
+
this.setValue(element, valueName, create.getFinalKeyframe(valueKeyframes, options));
|
|
1315
|
+
this.cancel();
|
|
1316
|
+
this.resolveFinishedPromise();
|
|
1468
1317
|
};
|
|
1469
|
-
const
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
|
|
1318
|
+
const init = () => {
|
|
1319
|
+
this.setValue = isCSSVar ? setCSSVar : setStyle;
|
|
1320
|
+
this.options = options;
|
|
1321
|
+
this.updateFinishedPromise();
|
|
1322
|
+
this.removeAnimation = () => {
|
|
1323
|
+
const elementState = state.get(element);
|
|
1324
|
+
elementState && elementState.delete(valueName);
|
|
1325
|
+
};
|
|
1473
1326
|
};
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
|
|
1327
|
+
if (!create.supportsWaapi()) {
|
|
1328
|
+
super();
|
|
1329
|
+
init();
|
|
1330
|
+
onFinish();
|
|
1331
|
+
}
|
|
1332
|
+
else {
|
|
1333
|
+
super(create.startWaapiAnimation(element, valueName, valueKeyframes, options));
|
|
1334
|
+
init();
|
|
1335
|
+
if (options.autoplay === false) {
|
|
1336
|
+
this.animation.pause();
|
|
1337
|
+
}
|
|
1338
|
+
this.animation.onfinish = onFinish;
|
|
1339
|
+
getElementAnimationState(element).set(valueName, this);
|
|
1479
1340
|
}
|
|
1480
|
-
target.addEventListener("scroll", listener, { passive: true });
|
|
1481
1341
|
}
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
|
|
1495
|
-
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
*/
|
|
1499
|
-
const scrollListener = scrollListeners.get(container);
|
|
1500
|
-
scrollListeners.delete(container);
|
|
1501
|
-
if (scrollListener) {
|
|
1502
|
-
getEventTarget(container).removeEventListener("scroll", scrollListener);
|
|
1503
|
-
(_a = resizeListeners.get(container)) === null || _a === void 0 ? void 0 : _a();
|
|
1504
|
-
window.removeEventListener("resize", scrollListener);
|
|
1342
|
+
/**
|
|
1343
|
+
* Allows the returned animation to be awaited or promise-chained. Currently
|
|
1344
|
+
* resolves when the animation finishes at all but in a future update could/should
|
|
1345
|
+
* reject if its cancels.
|
|
1346
|
+
*/
|
|
1347
|
+
then(resolve, reject) {
|
|
1348
|
+
return this.currentFinishedPromise.then(resolve, reject);
|
|
1349
|
+
}
|
|
1350
|
+
updateFinishedPromise() {
|
|
1351
|
+
this.currentFinishedPromise = new Promise((resolve) => {
|
|
1352
|
+
this.resolveFinishedPromise = resolve;
|
|
1353
|
+
});
|
|
1354
|
+
}
|
|
1355
|
+
play() {
|
|
1356
|
+
if (this.state === "finished") {
|
|
1357
|
+
this.updateFinishedPromise();
|
|
1505
1358
|
}
|
|
1506
|
-
|
|
1507
|
-
}
|
|
1508
|
-
|
|
1509
|
-
function scrollTimelineFallback({ source, container, axis = "y", }) {
|
|
1510
|
-
// Support legacy source argument. Deprecate later.
|
|
1511
|
-
if (source)
|
|
1512
|
-
container = source;
|
|
1513
|
-
// ScrollTimeline records progress as a percentage CSSUnitValue
|
|
1514
|
-
const currentTime = { value: 0 };
|
|
1515
|
-
const cancel = scrollInfo((info) => {
|
|
1516
|
-
currentTime.value = info[axis].progress * 100;
|
|
1517
|
-
}, { container, axis });
|
|
1518
|
-
return { currentTime, cancel };
|
|
1519
|
-
}
|
|
1520
|
-
const timelineCache = new Map();
|
|
1521
|
-
function getTimeline({ source, container = document.documentElement, axis = "y", } = {}) {
|
|
1522
|
-
// Support legacy source argument. Deprecate later.
|
|
1523
|
-
if (source)
|
|
1524
|
-
container = source;
|
|
1525
|
-
if (!timelineCache.has(container)) {
|
|
1526
|
-
timelineCache.set(container, {});
|
|
1359
|
+
super.play();
|
|
1527
1360
|
}
|
|
1528
|
-
|
|
1529
|
-
|
|
1530
|
-
|
|
1531
|
-
? new ScrollTimeline({ source: container, axis })
|
|
1532
|
-
: scrollTimelineFallback({ source: container, axis });
|
|
1361
|
+
cancel() {
|
|
1362
|
+
this.removeAnimation();
|
|
1363
|
+
super.cancel();
|
|
1533
1364
|
}
|
|
1534
|
-
return elementCache[axis];
|
|
1535
|
-
}
|
|
1536
|
-
/**
|
|
1537
|
-
* If the onScroll function has two arguments, it's expecting
|
|
1538
|
-
* more specific information about the scroll from scrollInfo.
|
|
1539
|
-
*/
|
|
1540
|
-
function isOnScrollWithInfo(onScroll) {
|
|
1541
|
-
return onScroll.length === 2;
|
|
1542
|
-
}
|
|
1543
|
-
/**
|
|
1544
|
-
* Currently, we only support element tracking with `scrollInfo`, though in
|
|
1545
|
-
* the future we can also offer ViewTimeline support.
|
|
1546
|
-
*/
|
|
1547
|
-
function needsElementTracking(options) {
|
|
1548
|
-
return options && (options.target || options.offset);
|
|
1549
1365
|
}
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
|
|
1366
|
+
|
|
1367
|
+
function animateElements(elementOrSelector, keyframes, options, scope) {
|
|
1368
|
+
const elements = motionDom.resolveElements(elementOrSelector, scope);
|
|
1369
|
+
const numElements = elements.length;
|
|
1370
|
+
motionUtils.invariant(Boolean(numElements), "No valid element provided.");
|
|
1371
|
+
const animations = [];
|
|
1372
|
+
for (let i = 0; i < numElements; i++) {
|
|
1373
|
+
const element = elements[i];
|
|
1374
|
+
const elementTransition = { ...options };
|
|
1375
|
+
/**
|
|
1376
|
+
* Resolve stagger function if provided.
|
|
1377
|
+
*/
|
|
1378
|
+
if (typeof elementTransition.delay === "function") {
|
|
1379
|
+
elementTransition.delay = elementTransition.delay(i, numElements);
|
|
1380
|
+
}
|
|
1381
|
+
for (const valueName in keyframes) {
|
|
1382
|
+
const valueKeyframes = keyframes[valueName];
|
|
1383
|
+
const valueOptions = {
|
|
1384
|
+
...motionDom.getValueTransition(elementTransition, valueName),
|
|
1385
|
+
};
|
|
1386
|
+
valueOptions.duration = valueOptions.duration
|
|
1387
|
+
? motionUtils.secondsToMilliseconds(valueOptions.duration)
|
|
1388
|
+
: valueOptions.duration;
|
|
1389
|
+
valueOptions.delay = motionUtils.secondsToMilliseconds(valueOptions.delay || 0);
|
|
1390
|
+
valueOptions.allowFlatten =
|
|
1391
|
+
!elementTransition.type && !elementTransition.ease;
|
|
1392
|
+
animations.push(new NativeAnimation(element, valueName, valueKeyframes, valueOptions));
|
|
1393
|
+
}
|
|
1555
1394
|
}
|
|
1556
|
-
|
|
1557
|
-
|
|
1395
|
+
return animations;
|
|
1396
|
+
}
|
|
1397
|
+
|
|
1398
|
+
const createScopedWaapiAnimate = (scope) => {
|
|
1399
|
+
function scopedAnimate(elementOrSelector, keyframes, options) {
|
|
1400
|
+
return new motionDom.GroupPlaybackControls(animateElements(elementOrSelector, keyframes, options, scope));
|
|
1558
1401
|
}
|
|
1402
|
+
return scopedAnimate;
|
|
1403
|
+
};
|
|
1404
|
+
const animateMini = /*@__PURE__*/ createScopedWaapiAnimate();
|
|
1405
|
+
|
|
1406
|
+
function observeTimeline(update, timeline) {
|
|
1407
|
+
let prevProgress;
|
|
1408
|
+
const onFrame = () => {
|
|
1409
|
+
const { currentTime } = timeline;
|
|
1410
|
+
const percentage = currentTime === null ? 0 : currentTime.value;
|
|
1411
|
+
const progress = percentage / 100;
|
|
1412
|
+
if (prevProgress !== progress) {
|
|
1413
|
+
update(progress);
|
|
1414
|
+
}
|
|
1415
|
+
prevProgress = progress;
|
|
1416
|
+
};
|
|
1417
|
+
motionDom.frame.update(onFrame, true);
|
|
1418
|
+
return () => motionDom.cancelFrame(onFrame);
|
|
1559
1419
|
}
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
|
|
1420
|
+
|
|
1421
|
+
const resizeHandlers = new WeakMap();
|
|
1422
|
+
let observer;
|
|
1423
|
+
function getElementSize(target, borderBoxSize) {
|
|
1424
|
+
if (borderBoxSize) {
|
|
1425
|
+
const { inlineSize, blockSize } = borderBoxSize[0];
|
|
1426
|
+
return { width: inlineSize, height: blockSize };
|
|
1427
|
+
}
|
|
1428
|
+
else if (target instanceof SVGElement && "getBBox" in target) {
|
|
1429
|
+
return target.getBBox();
|
|
1567
1430
|
}
|
|
1568
1431
|
else {
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
return observeTimeline((progress) => {
|
|
1574
|
-
valueAnimation.time = valueAnimation.duration * progress;
|
|
1575
|
-
}, timeline);
|
|
1576
|
-
});
|
|
1577
|
-
}
|
|
1578
|
-
else {
|
|
1579
|
-
return motionUtils.noop;
|
|
1580
|
-
}
|
|
1432
|
+
return {
|
|
1433
|
+
width: target.offsetWidth,
|
|
1434
|
+
height: target.offsetHeight,
|
|
1435
|
+
};
|
|
1581
1436
|
}
|
|
1582
1437
|
}
|
|
1583
|
-
function
|
|
1584
|
-
|
|
1585
|
-
|
|
1586
|
-
|
|
1587
|
-
|
|
1438
|
+
function notifyTarget({ target, contentRect, borderBoxSize, }) {
|
|
1439
|
+
var _a;
|
|
1440
|
+
(_a = resizeHandlers.get(target)) === null || _a === void 0 ? void 0 : _a.forEach((handler) => {
|
|
1441
|
+
handler({
|
|
1442
|
+
target,
|
|
1443
|
+
contentSize: contentRect,
|
|
1444
|
+
get size() {
|
|
1445
|
+
return getElementSize(target, borderBoxSize);
|
|
1446
|
+
},
|
|
1447
|
+
});
|
|
1448
|
+
});
|
|
1588
1449
|
}
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
|
|
1598
|
-
|
|
1599
|
-
|
|
1600
|
-
|
|
1601
|
-
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
|
|
1612
|
-
|
|
1613
|
-
|
|
1614
|
-
|
|
1615
|
-
|
|
1616
|
-
onEnd(entry);
|
|
1617
|
-
activeIntersections.delete(entry.target);
|
|
1450
|
+
function notifyAll(entries) {
|
|
1451
|
+
entries.forEach(notifyTarget);
|
|
1452
|
+
}
|
|
1453
|
+
function createResizeObserver() {
|
|
1454
|
+
if (typeof ResizeObserver === "undefined")
|
|
1455
|
+
return;
|
|
1456
|
+
observer = new ResizeObserver(notifyAll);
|
|
1457
|
+
}
|
|
1458
|
+
function resizeElement(target, handler) {
|
|
1459
|
+
if (!observer)
|
|
1460
|
+
createResizeObserver();
|
|
1461
|
+
const elements = motionDom.resolveElements(target);
|
|
1462
|
+
elements.forEach((element) => {
|
|
1463
|
+
let elementHandlers = resizeHandlers.get(element);
|
|
1464
|
+
if (!elementHandlers) {
|
|
1465
|
+
elementHandlers = new Set();
|
|
1466
|
+
resizeHandlers.set(element, elementHandlers);
|
|
1467
|
+
}
|
|
1468
|
+
elementHandlers.add(handler);
|
|
1469
|
+
observer === null || observer === void 0 ? void 0 : observer.observe(element);
|
|
1470
|
+
});
|
|
1471
|
+
return () => {
|
|
1472
|
+
elements.forEach((element) => {
|
|
1473
|
+
const elementHandlers = resizeHandlers.get(element);
|
|
1474
|
+
elementHandlers === null || elementHandlers === void 0 ? void 0 : elementHandlers.delete(handler);
|
|
1475
|
+
if (!(elementHandlers === null || elementHandlers === void 0 ? void 0 : elementHandlers.size)) {
|
|
1476
|
+
observer === null || observer === void 0 ? void 0 : observer.unobserve(element);
|
|
1618
1477
|
}
|
|
1619
1478
|
});
|
|
1620
1479
|
};
|
|
1621
|
-
const observer = new IntersectionObserver(onIntersectionChange, {
|
|
1622
|
-
root,
|
|
1623
|
-
rootMargin,
|
|
1624
|
-
threshold: typeof amount === "number" ? amount : thresholds[amount],
|
|
1625
|
-
});
|
|
1626
|
-
elements.forEach((element) => observer.observe(element));
|
|
1627
|
-
return () => observer.disconnect();
|
|
1628
1480
|
}
|
|
1629
1481
|
|
|
1630
|
-
|
|
1631
|
-
|
|
1632
|
-
|
|
1633
|
-
|
|
1634
|
-
|
|
1635
|
-
|
|
1636
|
-
|
|
1637
|
-
|
|
1638
|
-
|
|
1482
|
+
const windowCallbacks = new Set();
|
|
1483
|
+
let windowResizeHandler;
|
|
1484
|
+
function createWindowResizeHandler() {
|
|
1485
|
+
windowResizeHandler = () => {
|
|
1486
|
+
const size = {
|
|
1487
|
+
width: window.innerWidth,
|
|
1488
|
+
height: window.innerHeight,
|
|
1489
|
+
};
|
|
1490
|
+
const info = {
|
|
1491
|
+
target: window,
|
|
1492
|
+
size,
|
|
1493
|
+
contentSize: size,
|
|
1494
|
+
};
|
|
1495
|
+
windowCallbacks.forEach((callback) => callback(info));
|
|
1639
1496
|
};
|
|
1497
|
+
window.addEventListener("resize", windowResizeHandler);
|
|
1640
1498
|
}
|
|
1641
|
-
|
|
1642
|
-
|
|
1643
|
-
if (
|
|
1644
|
-
|
|
1645
|
-
|
|
1646
|
-
|
|
1647
|
-
|
|
1648
|
-
|
|
1649
|
-
}
|
|
1650
|
-
}
|
|
1651
|
-
function stagger(duration = 0.1, { startDelay = 0, from = 0, ease } = {}) {
|
|
1652
|
-
return (i, total) => {
|
|
1653
|
-
const fromIndex = typeof from === "number" ? from : getOriginIndex(from, total);
|
|
1654
|
-
const distance = Math.abs(fromIndex - i);
|
|
1655
|
-
let delay = duration * distance;
|
|
1656
|
-
if (ease) {
|
|
1657
|
-
const maxDelay = total * duration;
|
|
1658
|
-
const easingFunction = create.easingDefinitionToFunction(ease);
|
|
1659
|
-
delay = easingFunction(delay / maxDelay) * maxDelay;
|
|
1499
|
+
function resizeWindow(callback) {
|
|
1500
|
+
windowCallbacks.add(callback);
|
|
1501
|
+
if (!windowResizeHandler)
|
|
1502
|
+
createWindowResizeHandler();
|
|
1503
|
+
return () => {
|
|
1504
|
+
windowCallbacks.delete(callback);
|
|
1505
|
+
if (!windowCallbacks.size && windowResizeHandler) {
|
|
1506
|
+
windowResizeHandler = undefined;
|
|
1660
1507
|
}
|
|
1661
|
-
return startDelay + delay;
|
|
1662
1508
|
};
|
|
1663
1509
|
}
|
|
1664
1510
|
|
|
1665
|
-
|
|
1666
|
-
return
|
|
1511
|
+
function resize(a, b) {
|
|
1512
|
+
return typeof a === "function" ? resizeWindow(a) : resizeElement(a, b);
|
|
1513
|
+
}
|
|
1514
|
+
|
|
1515
|
+
/**
|
|
1516
|
+
* A time in milliseconds, beyond which we consider the scroll velocity to be 0.
|
|
1517
|
+
*/
|
|
1518
|
+
const maxElapsed = 50;
|
|
1519
|
+
const createAxisInfo = () => ({
|
|
1520
|
+
current: 0,
|
|
1521
|
+
offset: [],
|
|
1522
|
+
progress: 0,
|
|
1523
|
+
scrollLength: 0,
|
|
1524
|
+
targetOffset: 0,
|
|
1525
|
+
targetLength: 0,
|
|
1526
|
+
containerLength: 0,
|
|
1527
|
+
velocity: 0,
|
|
1528
|
+
});
|
|
1529
|
+
const createScrollInfo = () => ({
|
|
1530
|
+
time: 0,
|
|
1531
|
+
x: createAxisInfo(),
|
|
1532
|
+
y: createAxisInfo(),
|
|
1533
|
+
});
|
|
1534
|
+
const keys = {
|
|
1535
|
+
x: {
|
|
1536
|
+
length: "Width",
|
|
1537
|
+
position: "Left",
|
|
1538
|
+
},
|
|
1539
|
+
y: {
|
|
1540
|
+
length: "Height",
|
|
1541
|
+
position: "Top",
|
|
1542
|
+
},
|
|
1667
1543
|
};
|
|
1668
|
-
|
|
1669
|
-
|
|
1670
|
-
const
|
|
1671
|
-
const
|
|
1672
|
-
const
|
|
1673
|
-
|
|
1674
|
-
|
|
1675
|
-
|
|
1676
|
-
|
|
1677
|
-
|
|
1678
|
-
|
|
1679
|
-
|
|
1680
|
-
|
|
1544
|
+
function updateAxisInfo(element, axisName, info, time) {
|
|
1545
|
+
const axis = info[axisName];
|
|
1546
|
+
const { length, position } = keys[axisName];
|
|
1547
|
+
const prev = axis.current;
|
|
1548
|
+
const prevTime = info.time;
|
|
1549
|
+
axis.current = element[`scroll${position}`];
|
|
1550
|
+
axis.scrollLength = element[`scroll${length}`] - element[`client${length}`];
|
|
1551
|
+
axis.offset.length = 0;
|
|
1552
|
+
axis.offset[0] = 0;
|
|
1553
|
+
axis.offset[1] = axis.scrollLength;
|
|
1554
|
+
axis.progress = motionUtils.progress(0, axis.scrollLength, axis.current);
|
|
1555
|
+
const elapsed = time - prevTime;
|
|
1556
|
+
axis.velocity =
|
|
1557
|
+
elapsed > maxElapsed
|
|
1558
|
+
? 0
|
|
1559
|
+
: motionUtils.velocityPerSecond(axis.current - prev, elapsed);
|
|
1560
|
+
}
|
|
1561
|
+
function updateScrollInfo(element, info, time) {
|
|
1562
|
+
updateAxisInfo(element, "x", info, time);
|
|
1563
|
+
updateAxisInfo(element, "y", info, time);
|
|
1564
|
+
info.time = time;
|
|
1681
1565
|
}
|
|
1682
1566
|
|
|
1683
|
-
|
|
1684
|
-
|
|
1685
|
-
|
|
1686
|
-
|
|
1687
|
-
|
|
1688
|
-
|
|
1689
|
-
|
|
1690
|
-
|
|
1691
|
-
|
|
1692
|
-
|
|
1693
|
-
|
|
1694
|
-
|
|
1695
|
-
|
|
1696
|
-
|
|
1697
|
-
|
|
1698
|
-
|
|
1699
|
-
|
|
1700
|
-
const
|
|
1701
|
-
|
|
1702
|
-
|
|
1703
|
-
|
|
1704
|
-
|
|
1705
|
-
|
|
1706
|
-
|
|
1707
|
-
|
|
1708
|
-
|
|
1709
|
-
|
|
1567
|
+
function calcInset(element, container) {
|
|
1568
|
+
const inset = { x: 0, y: 0 };
|
|
1569
|
+
let current = element;
|
|
1570
|
+
while (current && current !== container) {
|
|
1571
|
+
if (current instanceof HTMLElement) {
|
|
1572
|
+
inset.x += current.offsetLeft;
|
|
1573
|
+
inset.y += current.offsetTop;
|
|
1574
|
+
current = current.offsetParent;
|
|
1575
|
+
}
|
|
1576
|
+
else if (current.tagName === "svg") {
|
|
1577
|
+
/**
|
|
1578
|
+
* This isn't an ideal approach to measuring the offset of <svg /> tags.
|
|
1579
|
+
* It would be preferable, given they behave like HTMLElements in most ways
|
|
1580
|
+
* to use offsetLeft/Top. But these don't exist on <svg />. Likewise we
|
|
1581
|
+
* can't use .getBBox() like most SVG elements as these provide the offset
|
|
1582
|
+
* relative to the SVG itself, which for <svg /> is usually 0x0.
|
|
1583
|
+
*/
|
|
1584
|
+
const svgBoundingBox = current.getBoundingClientRect();
|
|
1585
|
+
current = current.parentElement;
|
|
1586
|
+
const parentBoundingBox = current.getBoundingClientRect();
|
|
1587
|
+
inset.x += svgBoundingBox.left - parentBoundingBox.left;
|
|
1588
|
+
inset.y += svgBoundingBox.top - parentBoundingBox.top;
|
|
1589
|
+
}
|
|
1590
|
+
else if (current instanceof SVGGraphicsElement) {
|
|
1591
|
+
const { x, y } = current.getBBox();
|
|
1592
|
+
inset.x += x;
|
|
1593
|
+
inset.y += y;
|
|
1594
|
+
let svg = null;
|
|
1595
|
+
let parent = current.parentNode;
|
|
1596
|
+
while (!svg) {
|
|
1597
|
+
if (parent.tagName === "svg") {
|
|
1598
|
+
svg = parent;
|
|
1599
|
+
}
|
|
1600
|
+
parent = current.parentNode;
|
|
1601
|
+
}
|
|
1602
|
+
current = svg;
|
|
1603
|
+
}
|
|
1604
|
+
else {
|
|
1605
|
+
break;
|
|
1710
1606
|
}
|
|
1711
|
-
context.current = {
|
|
1712
|
-
id,
|
|
1713
|
-
group: shouldInheritGroup(inherit)
|
|
1714
|
-
? layoutGroupContext.group || nodeGroup()
|
|
1715
|
-
: nodeGroup(),
|
|
1716
|
-
};
|
|
1717
1607
|
}
|
|
1718
|
-
|
|
1719
|
-
|
|
1720
|
-
};
|
|
1608
|
+
return inset;
|
|
1609
|
+
}
|
|
1721
1610
|
|
|
1722
|
-
|
|
1723
|
-
|
|
1724
|
-
|
|
1725
|
-
|
|
1726
|
-
|
|
1727
|
-
|
|
1728
|
-
|
|
1729
|
-
* load animation and gesture support.
|
|
1730
|
-
*
|
|
1731
|
-
* ```jsx
|
|
1732
|
-
* // Synchronous loading
|
|
1733
|
-
* import { LazyMotion, m, domAnimation } from "framer-motion"
|
|
1734
|
-
*
|
|
1735
|
-
* function App() {
|
|
1736
|
-
* return (
|
|
1737
|
-
* <LazyMotion features={domAnimation}>
|
|
1738
|
-
* <m.div animate={{ scale: 2 }} />
|
|
1739
|
-
* </LazyMotion>
|
|
1740
|
-
* )
|
|
1741
|
-
* }
|
|
1742
|
-
*
|
|
1743
|
-
* // Asynchronous loading
|
|
1744
|
-
* import { LazyMotion, m } from "framer-motion"
|
|
1745
|
-
*
|
|
1746
|
-
* function App() {
|
|
1747
|
-
* return (
|
|
1748
|
-
* <LazyMotion features={() => import('./path/to/domAnimation')}>
|
|
1749
|
-
* <m.div animate={{ scale: 2 }} />
|
|
1750
|
-
* </LazyMotion>
|
|
1751
|
-
* )
|
|
1752
|
-
* }
|
|
1753
|
-
* ```
|
|
1754
|
-
*
|
|
1755
|
-
* @public
|
|
1756
|
-
*/
|
|
1757
|
-
function LazyMotion({ children, features, strict = false }) {
|
|
1758
|
-
const [, setIsLoaded] = React.useState(!isLazyBundle(features));
|
|
1759
|
-
const loadedRenderer = React.useRef(undefined);
|
|
1611
|
+
const namedEdges = {
|
|
1612
|
+
start: 0,
|
|
1613
|
+
center: 0.5,
|
|
1614
|
+
end: 1,
|
|
1615
|
+
};
|
|
1616
|
+
function resolveEdge(edge, length, inset = 0) {
|
|
1617
|
+
let delta = 0;
|
|
1760
1618
|
/**
|
|
1761
|
-
* If this
|
|
1619
|
+
* If we have this edge defined as a preset, replace the definition
|
|
1620
|
+
* with the numerical value.
|
|
1762
1621
|
*/
|
|
1763
|
-
if (
|
|
1764
|
-
|
|
1765
|
-
loadedRenderer.current = renderer;
|
|
1766
|
-
create.loadFeatures(loadedFeatures);
|
|
1622
|
+
if (edge in namedEdges) {
|
|
1623
|
+
edge = namedEdges[edge];
|
|
1767
1624
|
}
|
|
1768
|
-
|
|
1769
|
-
|
|
1770
|
-
|
|
1771
|
-
|
|
1772
|
-
|
|
1773
|
-
|
|
1774
|
-
|
|
1625
|
+
/**
|
|
1626
|
+
* Handle unit values
|
|
1627
|
+
*/
|
|
1628
|
+
if (typeof edge === "string") {
|
|
1629
|
+
const asNumber = parseFloat(edge);
|
|
1630
|
+
if (edge.endsWith("px")) {
|
|
1631
|
+
delta = asNumber;
|
|
1775
1632
|
}
|
|
1776
|
-
|
|
1777
|
-
|
|
1633
|
+
else if (edge.endsWith("%")) {
|
|
1634
|
+
edge = asNumber / 100;
|
|
1635
|
+
}
|
|
1636
|
+
else if (edge.endsWith("vw")) {
|
|
1637
|
+
delta = (asNumber / 100) * document.documentElement.clientWidth;
|
|
1638
|
+
}
|
|
1639
|
+
else if (edge.endsWith("vh")) {
|
|
1640
|
+
delta = (asNumber / 100) * document.documentElement.clientHeight;
|
|
1641
|
+
}
|
|
1642
|
+
else {
|
|
1643
|
+
edge = asNumber;
|
|
1644
|
+
}
|
|
1645
|
+
}
|
|
1646
|
+
/**
|
|
1647
|
+
* If the edge is defined as a number, handle as a progress value.
|
|
1648
|
+
*/
|
|
1649
|
+
if (typeof edge === "number") {
|
|
1650
|
+
delta = length * edge;
|
|
1651
|
+
}
|
|
1652
|
+
return inset + delta;
|
|
1778
1653
|
}
|
|
1779
|
-
|
|
1780
|
-
|
|
1654
|
+
|
|
1655
|
+
const defaultOffset = [0, 0];
|
|
1656
|
+
function resolveOffset(offset, containerLength, targetLength, targetInset) {
|
|
1657
|
+
let offsetDefinition = Array.isArray(offset) ? offset : defaultOffset;
|
|
1658
|
+
let targetPoint = 0;
|
|
1659
|
+
let containerPoint = 0;
|
|
1660
|
+
if (typeof offset === "number") {
|
|
1661
|
+
/**
|
|
1662
|
+
* If we're provided offset: [0, 0.5, 1] then each number x should become
|
|
1663
|
+
* [x, x], so we default to the behaviour of mapping 0 => 0 of both target
|
|
1664
|
+
* and container etc.
|
|
1665
|
+
*/
|
|
1666
|
+
offsetDefinition = [offset, offset];
|
|
1667
|
+
}
|
|
1668
|
+
else if (typeof offset === "string") {
|
|
1669
|
+
offset = offset.trim();
|
|
1670
|
+
if (offset.includes(" ")) {
|
|
1671
|
+
offsetDefinition = offset.split(" ");
|
|
1672
|
+
}
|
|
1673
|
+
else {
|
|
1674
|
+
/**
|
|
1675
|
+
* If we're provided a definition like "100px" then we want to apply
|
|
1676
|
+
* that only to the top of the target point, leaving the container at 0.
|
|
1677
|
+
* Whereas a named offset like "end" should be applied to both.
|
|
1678
|
+
*/
|
|
1679
|
+
offsetDefinition = [offset, namedEdges[offset] ? offset : `0`];
|
|
1680
|
+
}
|
|
1681
|
+
}
|
|
1682
|
+
targetPoint = resolveEdge(offsetDefinition[0], targetLength, targetInset);
|
|
1683
|
+
containerPoint = resolveEdge(offsetDefinition[1], containerLength);
|
|
1684
|
+
return targetPoint - containerPoint;
|
|
1781
1685
|
}
|
|
1782
1686
|
|
|
1783
|
-
|
|
1784
|
-
|
|
1785
|
-
|
|
1786
|
-
|
|
1787
|
-
|
|
1788
|
-
|
|
1789
|
-
|
|
1790
|
-
|
|
1791
|
-
|
|
1792
|
-
|
|
1793
|
-
|
|
1794
|
-
|
|
1795
|
-
|
|
1796
|
-
|
|
1797
|
-
|
|
1798
|
-
|
|
1799
|
-
|
|
1800
|
-
|
|
1801
|
-
|
|
1687
|
+
const ScrollOffset = {
|
|
1688
|
+
Enter: [
|
|
1689
|
+
[0, 1],
|
|
1690
|
+
[1, 1],
|
|
1691
|
+
],
|
|
1692
|
+
Exit: [
|
|
1693
|
+
[0, 0],
|
|
1694
|
+
[1, 0],
|
|
1695
|
+
],
|
|
1696
|
+
Any: [
|
|
1697
|
+
[1, 0],
|
|
1698
|
+
[0, 1],
|
|
1699
|
+
],
|
|
1700
|
+
All: [
|
|
1701
|
+
[0, 0],
|
|
1702
|
+
[1, 1],
|
|
1703
|
+
],
|
|
1704
|
+
};
|
|
1705
|
+
|
|
1706
|
+
const point = { x: 0, y: 0 };
|
|
1707
|
+
function getTargetSize(target) {
|
|
1708
|
+
return "getBBox" in target && target.tagName !== "svg"
|
|
1709
|
+
? target.getBBox()
|
|
1710
|
+
: { width: target.clientWidth, height: target.clientHeight };
|
|
1711
|
+
}
|
|
1712
|
+
function resolveOffsets(container, info, options) {
|
|
1713
|
+
const { offset: offsetDefinition = ScrollOffset.All } = options;
|
|
1714
|
+
const { target = container, axis = "y" } = options;
|
|
1715
|
+
const lengthLabel = axis === "y" ? "height" : "width";
|
|
1716
|
+
const inset = target !== container ? calcInset(target, container) : point;
|
|
1717
|
+
/**
|
|
1718
|
+
* Measure the target and container. If they're the same thing then we
|
|
1719
|
+
* use the container's scrollWidth/Height as the target, from there
|
|
1720
|
+
* all other calculations can remain the same.
|
|
1721
|
+
*/
|
|
1722
|
+
const targetSize = target === container
|
|
1723
|
+
? { width: container.scrollWidth, height: container.scrollHeight }
|
|
1724
|
+
: getTargetSize(target);
|
|
1725
|
+
const containerSize = {
|
|
1726
|
+
width: container.clientWidth,
|
|
1727
|
+
height: container.clientHeight,
|
|
1728
|
+
};
|
|
1802
1729
|
/**
|
|
1803
|
-
*
|
|
1730
|
+
* Reset the length of the resolved offset array rather than creating a new one.
|
|
1731
|
+
* TODO: More reusable data structures for targetSize/containerSize would also be good.
|
|
1804
1732
|
*/
|
|
1805
|
-
|
|
1733
|
+
info[axis].offset.length = 0;
|
|
1806
1734
|
/**
|
|
1807
|
-
*
|
|
1808
|
-
*
|
|
1735
|
+
* Populate the offset array by resolving the user's offset definition into
|
|
1736
|
+
* a list of pixel scroll offets.
|
|
1809
1737
|
*/
|
|
1810
|
-
|
|
1738
|
+
let hasChanged = !info[axis].interpolate;
|
|
1739
|
+
const numOffsets = offsetDefinition.length;
|
|
1740
|
+
for (let i = 0; i < numOffsets; i++) {
|
|
1741
|
+
const offset = resolveOffset(offsetDefinition[i], containerSize[lengthLabel], targetSize[lengthLabel], inset[axis]);
|
|
1742
|
+
if (!hasChanged && offset !== info[axis].interpolatorOffsets[i]) {
|
|
1743
|
+
hasChanged = true;
|
|
1744
|
+
}
|
|
1745
|
+
info[axis].offset[i] = offset;
|
|
1746
|
+
}
|
|
1811
1747
|
/**
|
|
1812
|
-
*
|
|
1813
|
-
*
|
|
1748
|
+
* If the pixel scroll offsets have changed, create a new interpolator function
|
|
1749
|
+
* to map scroll value into a progress.
|
|
1814
1750
|
*/
|
|
1815
|
-
|
|
1816
|
-
|
|
1817
|
-
|
|
1818
|
-
|
|
1819
|
-
]);
|
|
1820
|
-
return (jsxRuntime.jsx(create.MotionConfigContext.Provider, { value: context, children: children }));
|
|
1751
|
+
if (hasChanged) {
|
|
1752
|
+
info[axis].interpolate = create.interpolate(info[axis].offset, create.defaultOffset(offsetDefinition), { clamp: false });
|
|
1753
|
+
info[axis].interpolatorOffsets = [...info[axis].offset];
|
|
1754
|
+
}
|
|
1755
|
+
info[axis].progress = create.clamp(0, 1, info[axis].interpolate(info[axis].current));
|
|
1821
1756
|
}
|
|
1822
1757
|
|
|
1823
|
-
|
|
1824
|
-
|
|
1825
|
-
|
|
1826
|
-
|
|
1827
|
-
|
|
1758
|
+
function measure(container, target = container, info) {
|
|
1759
|
+
/**
|
|
1760
|
+
* Find inset of target within scrollable container
|
|
1761
|
+
*/
|
|
1762
|
+
info.x.targetOffset = 0;
|
|
1763
|
+
info.y.targetOffset = 0;
|
|
1764
|
+
if (target !== container) {
|
|
1765
|
+
let node = target;
|
|
1766
|
+
while (node && node !== container) {
|
|
1767
|
+
info.x.targetOffset += node.offsetLeft;
|
|
1768
|
+
info.y.targetOffset += node.offsetTop;
|
|
1769
|
+
node = node.offsetParent;
|
|
1770
|
+
}
|
|
1828
1771
|
}
|
|
1772
|
+
info.x.targetLength =
|
|
1773
|
+
target === container ? target.scrollWidth : target.clientWidth;
|
|
1774
|
+
info.y.targetLength =
|
|
1775
|
+
target === container ? target.scrollHeight : target.clientHeight;
|
|
1776
|
+
info.x.containerLength = container.clientWidth;
|
|
1777
|
+
info.y.containerLength = container.clientHeight;
|
|
1829
1778
|
/**
|
|
1830
|
-
*
|
|
1831
|
-
*
|
|
1779
|
+
* In development mode ensure scroll containers aren't position: static as this makes
|
|
1780
|
+
* it difficult to measure their relative positions.
|
|
1832
1781
|
*/
|
|
1833
|
-
|
|
1834
|
-
|
|
1835
|
-
|
|
1836
|
-
create.warnOnce(false, "motion() is deprecated. Use motion.create() instead.");
|
|
1782
|
+
if (process.env.NODE_ENV !== "production") {
|
|
1783
|
+
if (container && target && target !== container) {
|
|
1784
|
+
motionUtils.warnOnce(getComputedStyle(container).position !== "static", "Please ensure that the container has a non-static position, like 'relative', 'fixed', or 'absolute' to ensure scroll offset is calculated correctly.");
|
|
1837
1785
|
}
|
|
1838
|
-
|
|
1839
|
-
|
|
1840
|
-
|
|
1841
|
-
|
|
1842
|
-
|
|
1843
|
-
|
|
1844
|
-
|
|
1845
|
-
|
|
1846
|
-
|
|
1847
|
-
if (key === "create")
|
|
1848
|
-
return componentFactory;
|
|
1849
|
-
/**
|
|
1850
|
-
* If this element doesn't exist in the component cache, create it and cache.
|
|
1851
|
-
*/
|
|
1852
|
-
if (!componentCache.has(key)) {
|
|
1853
|
-
componentCache.set(key, componentFactory(key));
|
|
1786
|
+
}
|
|
1787
|
+
}
|
|
1788
|
+
function createOnScrollHandler(element, onScroll, info, options = {}) {
|
|
1789
|
+
return {
|
|
1790
|
+
measure: () => measure(element, options.target, info),
|
|
1791
|
+
update: (time) => {
|
|
1792
|
+
updateScrollInfo(element, info, time);
|
|
1793
|
+
if (options.offset || options.target) {
|
|
1794
|
+
resolveOffsets(element, info, options);
|
|
1854
1795
|
}
|
|
1855
|
-
return componentCache.get(key);
|
|
1856
1796
|
},
|
|
1857
|
-
|
|
1797
|
+
notify: () => onScroll(info),
|
|
1798
|
+
};
|
|
1858
1799
|
}
|
|
1859
1800
|
|
|
1860
|
-
const
|
|
1861
|
-
|
|
1862
|
-
|
|
1863
|
-
|
|
1864
|
-
|
|
1865
|
-
|
|
1866
|
-
|
|
1867
|
-
|
|
1868
|
-
|
|
1869
|
-
|
|
1870
|
-
if (!
|
|
1871
|
-
|
|
1872
|
-
|
|
1873
|
-
const nextLayout = nextItem.layout;
|
|
1874
|
-
const nextItemCenter = create.mixNumber(nextLayout.min, nextLayout.max, 0.5);
|
|
1875
|
-
if ((nextOffset === 1 && item.layout.max + offset > nextItemCenter) ||
|
|
1876
|
-
(nextOffset === -1 && item.layout.min + offset < nextItemCenter)) {
|
|
1877
|
-
return create.moveItem(order, index, index + nextOffset);
|
|
1801
|
+
const scrollListeners = new WeakMap();
|
|
1802
|
+
const resizeListeners = new WeakMap();
|
|
1803
|
+
const onScrollHandlers = new WeakMap();
|
|
1804
|
+
const getEventTarget = (element) => element === document.documentElement ? window : element;
|
|
1805
|
+
function scrollInfo(onScroll, { container = document.documentElement, ...options } = {}) {
|
|
1806
|
+
let containerHandlers = onScrollHandlers.get(container);
|
|
1807
|
+
/**
|
|
1808
|
+
* Get the onScroll handlers for this container.
|
|
1809
|
+
* If one isn't found, create a new one.
|
|
1810
|
+
*/
|
|
1811
|
+
if (!containerHandlers) {
|
|
1812
|
+
containerHandlers = new Set();
|
|
1813
|
+
onScrollHandlers.set(container, containerHandlers);
|
|
1878
1814
|
}
|
|
1879
|
-
|
|
1880
|
-
|
|
1881
|
-
|
|
1882
|
-
|
|
1883
|
-
const
|
|
1884
|
-
|
|
1885
|
-
|
|
1886
|
-
|
|
1887
|
-
|
|
1888
|
-
|
|
1889
|
-
|
|
1890
|
-
|
|
1891
|
-
|
|
1892
|
-
|
|
1893
|
-
|
|
1894
|
-
|
|
1895
|
-
|
|
1896
|
-
|
|
1897
|
-
}
|
|
1898
|
-
order.sort(compareMin);
|
|
1899
|
-
},
|
|
1900
|
-
updateOrder: (item, offset, velocity) => {
|
|
1901
|
-
if (isReordering.current)
|
|
1902
|
-
return;
|
|
1903
|
-
const newOrder = checkReorder(order, item, offset, velocity);
|
|
1904
|
-
if (order !== newOrder) {
|
|
1905
|
-
isReordering.current = true;
|
|
1906
|
-
onReorder(newOrder
|
|
1907
|
-
.map(getValue)
|
|
1908
|
-
.filter((value) => values.indexOf(value) !== -1));
|
|
1815
|
+
/**
|
|
1816
|
+
* Create a new onScroll handler for the provided callback.
|
|
1817
|
+
*/
|
|
1818
|
+
const info = createScrollInfo();
|
|
1819
|
+
const containerHandler = createOnScrollHandler(container, onScroll, info, options);
|
|
1820
|
+
containerHandlers.add(containerHandler);
|
|
1821
|
+
/**
|
|
1822
|
+
* Check if there's a scroll event listener for this container.
|
|
1823
|
+
* If not, create one.
|
|
1824
|
+
*/
|
|
1825
|
+
if (!scrollListeners.has(container)) {
|
|
1826
|
+
const measureAll = () => {
|
|
1827
|
+
for (const handler of containerHandlers)
|
|
1828
|
+
handler.measure();
|
|
1829
|
+
};
|
|
1830
|
+
const updateAll = () => {
|
|
1831
|
+
for (const handler of containerHandlers) {
|
|
1832
|
+
handler.update(motionDom.frameData.timestamp);
|
|
1909
1833
|
}
|
|
1910
|
-
}
|
|
1834
|
+
};
|
|
1835
|
+
const notifyAll = () => {
|
|
1836
|
+
for (const handler of containerHandlers)
|
|
1837
|
+
handler.notify();
|
|
1838
|
+
};
|
|
1839
|
+
const listener = () => {
|
|
1840
|
+
motionDom.frame.read(measureAll, false, true);
|
|
1841
|
+
motionDom.frame.read(updateAll, false, true);
|
|
1842
|
+
motionDom.frame.update(notifyAll, false, true);
|
|
1843
|
+
};
|
|
1844
|
+
scrollListeners.set(container, listener);
|
|
1845
|
+
const target = getEventTarget(container);
|
|
1846
|
+
window.addEventListener("resize", listener, { passive: true });
|
|
1847
|
+
if (container !== document.documentElement) {
|
|
1848
|
+
resizeListeners.set(container, resize(container, listener));
|
|
1849
|
+
}
|
|
1850
|
+
target.addEventListener("scroll", listener, { passive: true });
|
|
1851
|
+
}
|
|
1852
|
+
const listener = scrollListeners.get(container);
|
|
1853
|
+
motionDom.frame.read(listener, false, true);
|
|
1854
|
+
return () => {
|
|
1855
|
+
var _a;
|
|
1856
|
+
motionDom.cancelFrame(listener);
|
|
1857
|
+
/**
|
|
1858
|
+
* Check if we even have any handlers for this container.
|
|
1859
|
+
*/
|
|
1860
|
+
const currentHandlers = onScrollHandlers.get(container);
|
|
1861
|
+
if (!currentHandlers)
|
|
1862
|
+
return;
|
|
1863
|
+
currentHandlers.delete(containerHandler);
|
|
1864
|
+
if (currentHandlers.size)
|
|
1865
|
+
return;
|
|
1866
|
+
/**
|
|
1867
|
+
* If no more handlers, remove the scroll listener too.
|
|
1868
|
+
*/
|
|
1869
|
+
const scrollListener = scrollListeners.get(container);
|
|
1870
|
+
scrollListeners.delete(container);
|
|
1871
|
+
if (scrollListener) {
|
|
1872
|
+
getEventTarget(container).removeEventListener("scroll", scrollListener);
|
|
1873
|
+
(_a = resizeListeners.get(container)) === null || _a === void 0 ? void 0 : _a();
|
|
1874
|
+
window.removeEventListener("resize", scrollListener);
|
|
1875
|
+
}
|
|
1911
1876
|
};
|
|
1912
|
-
React.useEffect(() => {
|
|
1913
|
-
isReordering.current = false;
|
|
1914
|
-
});
|
|
1915
|
-
return (jsxRuntime.jsx(Component, { ...props, ref: externalRef, ignoreStrict: true, children: jsxRuntime.jsx(ReorderContext.Provider, { value: context, children: children }) }));
|
|
1916
1877
|
}
|
|
1917
|
-
|
|
1918
|
-
function
|
|
1919
|
-
|
|
1878
|
+
|
|
1879
|
+
function scrollTimelineFallback({ source, container, axis = "y", }) {
|
|
1880
|
+
// Support legacy source argument. Deprecate later.
|
|
1881
|
+
if (source)
|
|
1882
|
+
container = source;
|
|
1883
|
+
// ScrollTimeline records progress as a percentage CSSUnitValue
|
|
1884
|
+
const currentTime = { value: 0 };
|
|
1885
|
+
const cancel = scrollInfo((info) => {
|
|
1886
|
+
currentTime.value = info[axis].progress * 100;
|
|
1887
|
+
}, { container, axis });
|
|
1888
|
+
return { currentTime, cancel };
|
|
1920
1889
|
}
|
|
1921
|
-
|
|
1922
|
-
|
|
1890
|
+
const timelineCache = new Map();
|
|
1891
|
+
function getTimeline({ source, container = document.documentElement, axis = "y", } = {}) {
|
|
1892
|
+
// Support legacy source argument. Deprecate later.
|
|
1893
|
+
if (source)
|
|
1894
|
+
container = source;
|
|
1895
|
+
if (!timelineCache.has(container)) {
|
|
1896
|
+
timelineCache.set(container, {});
|
|
1897
|
+
}
|
|
1898
|
+
const elementCache = timelineCache.get(container);
|
|
1899
|
+
if (!elementCache[axis]) {
|
|
1900
|
+
elementCache[axis] = motionDom.supportsScrollTimeline()
|
|
1901
|
+
? new ScrollTimeline({ source: container, axis })
|
|
1902
|
+
: scrollTimelineFallback({ source: container, axis });
|
|
1903
|
+
}
|
|
1904
|
+
return elementCache[axis];
|
|
1905
|
+
}
|
|
1906
|
+
/**
|
|
1907
|
+
* If the onScroll function has two arguments, it's expecting
|
|
1908
|
+
* more specific information about the scroll from scrollInfo.
|
|
1909
|
+
*/
|
|
1910
|
+
function isOnScrollWithInfo(onScroll) {
|
|
1911
|
+
return onScroll.length === 2;
|
|
1923
1912
|
}
|
|
1924
|
-
|
|
1925
1913
|
/**
|
|
1926
|
-
*
|
|
1927
|
-
*
|
|
1928
|
-
* Usually, these are created automatically. For advanced use-cases, like use with `useTransform`, you can create `MotionValue`s externally and pass them into the animated component via the `style` prop.
|
|
1929
|
-
*
|
|
1930
|
-
* ```jsx
|
|
1931
|
-
* export const MyComponent = () => {
|
|
1932
|
-
* const scale = useMotionValue(1)
|
|
1933
|
-
*
|
|
1934
|
-
* return <motion.div style={{ scale }} />
|
|
1935
|
-
* }
|
|
1936
|
-
* ```
|
|
1937
|
-
*
|
|
1938
|
-
* @param initial - The initial state.
|
|
1939
|
-
*
|
|
1940
|
-
* @public
|
|
1914
|
+
* Currently, we only support element tracking with `scrollInfo`, though in
|
|
1915
|
+
* the future we can also offer ViewTimeline support.
|
|
1941
1916
|
*/
|
|
1942
|
-
function
|
|
1943
|
-
|
|
1944
|
-
|
|
1945
|
-
|
|
1946
|
-
|
|
1947
|
-
|
|
1948
|
-
|
|
1949
|
-
|
|
1950
|
-
if (isStatic) {
|
|
1951
|
-
const [, setLatest] = React.useState(initial);
|
|
1952
|
-
React.useEffect(() => value.on("change", setLatest), []);
|
|
1917
|
+
function needsElementTracking(options) {
|
|
1918
|
+
return options && (options.target || options.offset);
|
|
1919
|
+
}
|
|
1920
|
+
function scrollFunction(onScroll, options) {
|
|
1921
|
+
if (isOnScrollWithInfo(onScroll) || needsElementTracking(options)) {
|
|
1922
|
+
return scrollInfo((info) => {
|
|
1923
|
+
onScroll(info[options.axis].progress, info);
|
|
1924
|
+
}, options);
|
|
1953
1925
|
}
|
|
1954
|
-
|
|
1926
|
+
else {
|
|
1927
|
+
return observeTimeline(onScroll, getTimeline(options));
|
|
1928
|
+
}
|
|
1929
|
+
}
|
|
1930
|
+
function scrollAnimation(animation, options) {
|
|
1931
|
+
animation.flatten();
|
|
1932
|
+
if (needsElementTracking(options)) {
|
|
1933
|
+
animation.pause();
|
|
1934
|
+
return scrollInfo((info) => {
|
|
1935
|
+
animation.time = animation.duration * info[options.axis].progress;
|
|
1936
|
+
}, options);
|
|
1937
|
+
}
|
|
1938
|
+
else {
|
|
1939
|
+
const timeline = getTimeline(options);
|
|
1940
|
+
if (animation.attachTimeline) {
|
|
1941
|
+
return animation.attachTimeline(timeline, (valueAnimation) => {
|
|
1942
|
+
valueAnimation.pause();
|
|
1943
|
+
return observeTimeline((progress) => {
|
|
1944
|
+
valueAnimation.time = valueAnimation.duration * progress;
|
|
1945
|
+
}, timeline);
|
|
1946
|
+
});
|
|
1947
|
+
}
|
|
1948
|
+
else {
|
|
1949
|
+
return motionUtils.noop;
|
|
1950
|
+
}
|
|
1951
|
+
}
|
|
1952
|
+
}
|
|
1953
|
+
function scroll(onScroll, { axis = "y", ...options } = {}) {
|
|
1954
|
+
const optionsWithDefaults = { axis, ...options };
|
|
1955
|
+
return typeof onScroll === "function"
|
|
1956
|
+
? scrollFunction(onScroll, optionsWithDefaults)
|
|
1957
|
+
: scrollAnimation(onScroll, optionsWithDefaults);
|
|
1955
1958
|
}
|
|
1956
1959
|
|
|
1957
|
-
|
|
1958
|
-
|
|
1959
|
-
|
|
1960
|
-
|
|
1961
|
-
|
|
1962
|
-
|
|
1963
|
-
|
|
1964
|
-
|
|
1965
|
-
|
|
1966
|
-
|
|
1967
|
-
|
|
1968
|
-
|
|
1969
|
-
|
|
1970
|
-
|
|
1971
|
-
|
|
1972
|
-
|
|
1973
|
-
|
|
1974
|
-
|
|
1975
|
-
|
|
1976
|
-
|
|
1977
|
-
|
|
1978
|
-
|
|
1979
|
-
|
|
1980
|
-
|
|
1981
|
-
|
|
1982
|
-
|
|
1983
|
-
|
|
1984
|
-
|
|
1960
|
+
const thresholds = {
|
|
1961
|
+
some: 0,
|
|
1962
|
+
all: 1,
|
|
1963
|
+
};
|
|
1964
|
+
function inView(elementOrSelector, onStart, { root, margin: rootMargin, amount = "some" } = {}) {
|
|
1965
|
+
const elements = motionDom.resolveElements(elementOrSelector);
|
|
1966
|
+
const activeIntersections = new WeakMap();
|
|
1967
|
+
const onIntersectionChange = (entries) => {
|
|
1968
|
+
entries.forEach((entry) => {
|
|
1969
|
+
const onEnd = activeIntersections.get(entry.target);
|
|
1970
|
+
/**
|
|
1971
|
+
* If there's no change to the intersection, we don't need to
|
|
1972
|
+
* do anything here.
|
|
1973
|
+
*/
|
|
1974
|
+
if (entry.isIntersecting === Boolean(onEnd))
|
|
1975
|
+
return;
|
|
1976
|
+
if (entry.isIntersecting) {
|
|
1977
|
+
const newOnEnd = onStart(entry.target, entry);
|
|
1978
|
+
if (typeof newOnEnd === "function") {
|
|
1979
|
+
activeIntersections.set(entry.target, newOnEnd);
|
|
1980
|
+
}
|
|
1981
|
+
else {
|
|
1982
|
+
observer.unobserve(entry.target);
|
|
1983
|
+
}
|
|
1984
|
+
}
|
|
1985
|
+
else if (typeof onEnd === "function") {
|
|
1986
|
+
onEnd(entry);
|
|
1987
|
+
activeIntersections.delete(entry.target);
|
|
1988
|
+
}
|
|
1989
|
+
});
|
|
1990
|
+
};
|
|
1991
|
+
const observer = new IntersectionObserver(onIntersectionChange, {
|
|
1992
|
+
root,
|
|
1993
|
+
rootMargin,
|
|
1994
|
+
threshold: typeof amount === "number" ? amount : thresholds[amount],
|
|
1985
1995
|
});
|
|
1986
|
-
|
|
1996
|
+
elements.forEach((element) => observer.observe(element));
|
|
1997
|
+
return () => observer.disconnect();
|
|
1987
1998
|
}
|
|
1988
1999
|
|
|
1989
|
-
function
|
|
1990
|
-
|
|
1991
|
-
|
|
1992
|
-
|
|
1993
|
-
|
|
1994
|
-
|
|
1995
|
-
|
|
1996
|
-
|
|
1997
|
-
|
|
1998
|
-
|
|
1999
|
-
*/
|
|
2000
|
-
create.collectMotionValues.current = undefined;
|
|
2001
|
-
return value;
|
|
2000
|
+
function steps(numSteps, direction = "end") {
|
|
2001
|
+
return (progress) => {
|
|
2002
|
+
progress =
|
|
2003
|
+
direction === "end"
|
|
2004
|
+
? Math.min(progress, 0.999)
|
|
2005
|
+
: Math.max(progress, 0.001);
|
|
2006
|
+
const expanded = progress * numSteps;
|
|
2007
|
+
const rounded = direction === "end" ? Math.floor(expanded) : Math.ceil(expanded);
|
|
2008
|
+
return create.clamp(0, 1, rounded / numSteps);
|
|
2009
|
+
};
|
|
2002
2010
|
}
|
|
2003
2011
|
|
|
2004
|
-
function
|
|
2005
|
-
if (
|
|
2006
|
-
return
|
|
2012
|
+
function getOriginIndex(from, total) {
|
|
2013
|
+
if (from === "first") {
|
|
2014
|
+
return 0;
|
|
2015
|
+
}
|
|
2016
|
+
else {
|
|
2017
|
+
const lastIndex = total - 1;
|
|
2018
|
+
return from === "last" ? lastIndex : lastIndex / 2;
|
|
2007
2019
|
}
|
|
2008
|
-
const transformer = typeof inputRangeOrTransformer === "function"
|
|
2009
|
-
? inputRangeOrTransformer
|
|
2010
|
-
: transform(inputRangeOrTransformer, outputRange, options);
|
|
2011
|
-
return Array.isArray(input)
|
|
2012
|
-
? useListTransform(input, transformer)
|
|
2013
|
-
: useListTransform([input], ([latest]) => transformer(latest));
|
|
2014
2020
|
}
|
|
2015
|
-
function
|
|
2016
|
-
|
|
2017
|
-
|
|
2018
|
-
|
|
2019
|
-
|
|
2020
|
-
|
|
2021
|
-
|
|
2021
|
+
function stagger(duration = 0.1, { startDelay = 0, from = 0, ease } = {}) {
|
|
2022
|
+
return (i, total) => {
|
|
2023
|
+
const fromIndex = typeof from === "number" ? from : getOriginIndex(from, total);
|
|
2024
|
+
const distance = Math.abs(fromIndex - i);
|
|
2025
|
+
let delay = duration * distance;
|
|
2026
|
+
if (ease) {
|
|
2027
|
+
const maxDelay = total * duration;
|
|
2028
|
+
const easingFunction = create.easingDefinitionToFunction(ease);
|
|
2029
|
+
delay = easingFunction(delay / maxDelay) * maxDelay;
|
|
2022
2030
|
}
|
|
2023
|
-
return
|
|
2024
|
-
});
|
|
2025
|
-
}
|
|
2026
|
-
|
|
2027
|
-
function useDefaultMotionValue(value, defaultValue = 0) {
|
|
2028
|
-
return create.isMotionValue(value) ? value : useMotionValue(defaultValue);
|
|
2029
|
-
}
|
|
2030
|
-
function ReorderItemComponent({ children, style = {}, value, as = "li", onDrag, layout = true, ...props }, externalRef) {
|
|
2031
|
-
const Component = create.useConstant(() => motion[as]);
|
|
2032
|
-
const context = React.useContext(ReorderContext);
|
|
2033
|
-
const point = {
|
|
2034
|
-
x: useDefaultMotionValue(style.x),
|
|
2035
|
-
y: useDefaultMotionValue(style.y),
|
|
2031
|
+
return startDelay + delay;
|
|
2036
2032
|
};
|
|
2037
|
-
const zIndex = useTransform([point.x, point.y], ([latestX, latestY]) => latestX || latestY ? 1 : "unset");
|
|
2038
|
-
motionUtils.invariant(Boolean(context), "Reorder.Item must be a child of Reorder.Group");
|
|
2039
|
-
const { axis, registerItem, updateOrder } = context;
|
|
2040
|
-
return (jsxRuntime.jsx(Component, { drag: axis, ...props, dragSnapToOrigin: true, style: { ...style, x: point.x, y: point.y, zIndex }, layout: layout, onDrag: (event, gesturePoint) => {
|
|
2041
|
-
const { velocity } = gesturePoint;
|
|
2042
|
-
velocity[axis] &&
|
|
2043
|
-
updateOrder(value, point[axis].get(), velocity[axis]);
|
|
2044
|
-
onDrag && onDrag(event, gesturePoint);
|
|
2045
|
-
}, onLayoutMeasure: (measured) => registerItem(value, measured), ref: externalRef, ignoreStrict: true, children: children }));
|
|
2046
2033
|
}
|
|
2047
|
-
const ReorderItem = /*@__PURE__*/ React.forwardRef(ReorderItemComponent);
|
|
2048
|
-
|
|
2049
|
-
var namespace = /*#__PURE__*/Object.freeze({
|
|
2050
|
-
__proto__: null,
|
|
2051
|
-
Group: ReorderGroup,
|
|
2052
|
-
Item: ReorderItem
|
|
2053
|
-
});
|
|
2054
2034
|
|
|
2055
2035
|
const createMinimalMotionComponent =
|
|
2056
2036
|
/*@__PURE__*/ create.createMotionComponentFactory();
|
|
2057
2037
|
|
|
2058
2038
|
const m = /*@__PURE__*/ createDOMMotionComponentProxy(createMinimalMotionComponent);
|
|
2059
2039
|
|
|
2040
|
+
function useUnmountEffect(callback) {
|
|
2041
|
+
return React.useEffect(() => () => callback(), []);
|
|
2042
|
+
}
|
|
2043
|
+
|
|
2060
2044
|
/**
|
|
2061
2045
|
* @public
|
|
2062
2046
|
*/
|
|
@@ -2097,10 +2081,10 @@ function refWarning(name, ref) {
|
|
|
2097
2081
|
motionUtils.warning(Boolean(!ref || ref.current), `You have defined a ${name} options but the provided ref is not yet hydrated, probably because it's defined higher up the tree. Try calling useScroll() in the same component as the ref, or setting its \`layoutEffect: false\` option.`);
|
|
2098
2082
|
}
|
|
2099
2083
|
const createScrollMotionValues = () => ({
|
|
2100
|
-
scrollX:
|
|
2101
|
-
scrollY:
|
|
2102
|
-
scrollXProgress:
|
|
2103
|
-
scrollYProgress:
|
|
2084
|
+
scrollX: motionDom.motionValue(0),
|
|
2085
|
+
scrollY: motionDom.motionValue(0),
|
|
2086
|
+
scrollXProgress: motionDom.motionValue(0),
|
|
2087
|
+
scrollYProgress: motionDom.motionValue(0),
|
|
2104
2088
|
});
|
|
2105
2089
|
function useScroll({ container, target, layoutEffect = true, ...options } = {}) {
|
|
2106
2090
|
const values = create.useConstant(createScrollMotionValues);
|
|
@@ -2110,7 +2094,7 @@ function useScroll({ container, target, layoutEffect = true, ...options } = {})
|
|
|
2110
2094
|
useLifecycleEffect(() => {
|
|
2111
2095
|
refWarning("target", target);
|
|
2112
2096
|
refWarning("container", container);
|
|
2113
|
-
return scroll((_progress, { x, y }) => {
|
|
2097
|
+
return scroll((_progress, { x, y, }) => {
|
|
2114
2098
|
values.scrollX.set(x.current);
|
|
2115
2099
|
values.scrollXProgress.set(x.progress);
|
|
2116
2100
|
values.scrollY.set(y.current);
|
|
@@ -2129,7 +2113,7 @@ function useScroll({ container, target, layoutEffect = true, ...options } = {})
|
|
|
2129
2113
|
*/
|
|
2130
2114
|
function useElementScroll(ref) {
|
|
2131
2115
|
if (process.env.NODE_ENV === "development") {
|
|
2132
|
-
|
|
2116
|
+
motionUtils.warnOnce(false, "useElementScroll is deprecated. Convert to useScroll({ container: ref }).");
|
|
2133
2117
|
}
|
|
2134
2118
|
return useScroll({ container: ref });
|
|
2135
2119
|
}
|
|
@@ -2139,7 +2123,7 @@ function useElementScroll(ref) {
|
|
|
2139
2123
|
*/
|
|
2140
2124
|
function useViewportScroll() {
|
|
2141
2125
|
if (process.env.NODE_ENV !== "production") {
|
|
2142
|
-
|
|
2126
|
+
motionUtils.warnOnce(false, "useViewportScroll is deprecated. Convert to useScroll().");
|
|
2143
2127
|
}
|
|
2144
2128
|
return useScroll();
|
|
2145
2129
|
}
|
|
@@ -2218,7 +2202,7 @@ function useSpring(source, config = {}) {
|
|
|
2218
2202
|
return set(v);
|
|
2219
2203
|
latestValue.current = v;
|
|
2220
2204
|
latestSetter.current = (latest) => set(parseValue(latest, unit));
|
|
2221
|
-
|
|
2205
|
+
motionDom.frame.postRender(startAnimation);
|
|
2222
2206
|
return value.get();
|
|
2223
2207
|
}, stopAnimation);
|
|
2224
2208
|
}, [JSON.stringify(config)]);
|
|
@@ -2247,8 +2231,8 @@ function useAnimationFrame(callback) {
|
|
|
2247
2231
|
initialTimestamp.current = timestamp;
|
|
2248
2232
|
callback(timestamp - initialTimestamp.current, delta);
|
|
2249
2233
|
};
|
|
2250
|
-
|
|
2251
|
-
return () =>
|
|
2234
|
+
motionDom.frame.update(provideTimeSinceStart, true);
|
|
2235
|
+
return () => motionDom.cancelFrame(provideTimeSinceStart);
|
|
2252
2236
|
}, [callback]);
|
|
2253
2237
|
}
|
|
2254
2238
|
|
|
@@ -2279,11 +2263,11 @@ function useVelocity(value) {
|
|
|
2279
2263
|
* to keep checking until it is zero.
|
|
2280
2264
|
*/
|
|
2281
2265
|
if (latest)
|
|
2282
|
-
|
|
2266
|
+
motionDom.frame.update(updateVelocity);
|
|
2283
2267
|
};
|
|
2284
2268
|
useMotionValueEvent(value, "change", () => {
|
|
2285
2269
|
// Schedule an update to this value at the end of the current frame.
|
|
2286
|
-
|
|
2270
|
+
motionDom.frame.update(updateVelocity, false, true);
|
|
2287
2271
|
});
|
|
2288
2272
|
return velocity;
|
|
2289
2273
|
}
|
|
@@ -2297,7 +2281,7 @@ function getWillChangeName(name) {
|
|
|
2297
2281
|
}
|
|
2298
2282
|
}
|
|
2299
2283
|
|
|
2300
|
-
class WillChangeMotionValue extends
|
|
2284
|
+
class WillChangeMotionValue extends motionDom.MotionValue {
|
|
2301
2285
|
constructor() {
|
|
2302
2286
|
super(...arguments);
|
|
2303
2287
|
this.values = [];
|
|
@@ -2305,7 +2289,7 @@ class WillChangeMotionValue extends create.MotionValue {
|
|
|
2305
2289
|
add(name) {
|
|
2306
2290
|
const styleName = getWillChangeName(name);
|
|
2307
2291
|
if (styleName) {
|
|
2308
|
-
|
|
2292
|
+
motionUtils.addUniqueItem(this.values, styleName);
|
|
2309
2293
|
this.update();
|
|
2310
2294
|
}
|
|
2311
2295
|
}
|
|
@@ -2351,7 +2335,7 @@ function useReducedMotion() {
|
|
|
2351
2335
|
!create.hasReducedMotionListener.current && create.initPrefersReducedMotion();
|
|
2352
2336
|
const [shouldReduceMotion] = React.useState(create.prefersReducedMotion.current);
|
|
2353
2337
|
if (process.env.NODE_ENV !== "production") {
|
|
2354
|
-
|
|
2338
|
+
motionUtils.warnOnce(shouldReduceMotion !== true, "You have Reduced Motion enabled on your device. Animations may not appear as expected.");
|
|
2355
2339
|
}
|
|
2356
2340
|
/**
|
|
2357
2341
|
* TODO See if people miss automatically updating shouldReduceMotion setting
|
|
@@ -2741,7 +2725,7 @@ function useInstantTransition() {
|
|
|
2741
2725
|
/**
|
|
2742
2726
|
* Unblock after two animation frames, otherwise this will unblock too soon.
|
|
2743
2727
|
*/
|
|
2744
|
-
|
|
2728
|
+
motionDom.frame.postRender(() => motionDom.frame.postRender(() => {
|
|
2745
2729
|
/**
|
|
2746
2730
|
* If the callback has been called again after the effect
|
|
2747
2731
|
* triggered this 2 frame delay, don't unblock animations. This
|
|
@@ -2767,14 +2751,14 @@ function disableInstantTransitions() {
|
|
|
2767
2751
|
create.instantAnimationState.current = false;
|
|
2768
2752
|
}
|
|
2769
2753
|
|
|
2754
|
+
const appearAnimationStore = new Map();
|
|
2755
|
+
const appearComplete = new Map();
|
|
2756
|
+
|
|
2770
2757
|
const appearStoreId = (elementId, valueName) => {
|
|
2771
2758
|
const key = create.transformProps.has(valueName) ? "transform" : valueName;
|
|
2772
2759
|
return `${elementId}: ${key}`;
|
|
2773
2760
|
};
|
|
2774
2761
|
|
|
2775
|
-
const appearAnimationStore = new Map();
|
|
2776
|
-
const appearComplete = new Map();
|
|
2777
|
-
|
|
2778
2762
|
function handoffOptimizedAppearAnimation(elementId, valueName, frame) {
|
|
2779
2763
|
var _a;
|
|
2780
2764
|
const storeId = appearStoreId(elementId, valueName);
|
|
@@ -3089,8 +3073,6 @@ exports.FlatTree = create.FlatTree;
|
|
|
3089
3073
|
exports.LayoutGroupContext = create.LayoutGroupContext;
|
|
3090
3074
|
exports.MotionConfigContext = create.MotionConfigContext;
|
|
3091
3075
|
exports.MotionContext = create.MotionContext;
|
|
3092
|
-
exports.MotionGlobalConfig = create.MotionGlobalConfig;
|
|
3093
|
-
exports.MotionValue = create.MotionValue;
|
|
3094
3076
|
exports.PresenceContext = create.PresenceContext;
|
|
3095
3077
|
exports.SwitchLayoutGroupContext = create.SwitchLayoutGroupContext;
|
|
3096
3078
|
exports.VisualElement = create.VisualElement;
|
|
@@ -3106,7 +3088,6 @@ exports.backInOut = create.backInOut;
|
|
|
3106
3088
|
exports.backOut = create.backOut;
|
|
3107
3089
|
exports.buildTransform = create.buildTransform;
|
|
3108
3090
|
exports.calcLength = create.calcLength;
|
|
3109
|
-
exports.cancelFrame = create.cancelFrame;
|
|
3110
3091
|
exports.circIn = create.circIn;
|
|
3111
3092
|
exports.circInOut = create.circInOut;
|
|
3112
3093
|
exports.circOut = create.circOut;
|
|
@@ -3124,9 +3105,6 @@ exports.easeInOut = create.easeInOut;
|
|
|
3124
3105
|
exports.easeOut = create.easeOut;
|
|
3125
3106
|
exports.filterProps = create.filterProps;
|
|
3126
3107
|
exports.findSpring = create.findSpring;
|
|
3127
|
-
exports.frame = create.frame;
|
|
3128
|
-
exports.frameData = create.frameData;
|
|
3129
|
-
exports.frameSteps = create.frameSteps;
|
|
3130
3108
|
exports.inertia = create.inertia;
|
|
3131
3109
|
exports.interpolate = create.interpolate;
|
|
3132
3110
|
exports.isBrowser = create.isBrowser;
|
|
@@ -3136,29 +3114,31 @@ exports.keyframes = create.keyframes;
|
|
|
3136
3114
|
exports.makeUseVisualState = create.makeUseVisualState;
|
|
3137
3115
|
exports.mirrorEasing = create.mirrorEasing;
|
|
3138
3116
|
exports.mix = create.mix;
|
|
3139
|
-
exports.motionValue = create.motionValue;
|
|
3140
3117
|
exports.optimizedAppearDataAttribute = create.optimizedAppearDataAttribute;
|
|
3141
3118
|
exports.pipe = create.pipe;
|
|
3142
3119
|
exports.px = create.px;
|
|
3143
3120
|
exports.resolveMotionValue = create.resolveMotionValue;
|
|
3144
3121
|
exports.reverseEasing = create.reverseEasing;
|
|
3145
3122
|
exports.spring = create.spring;
|
|
3146
|
-
exports.time = create.time;
|
|
3147
3123
|
exports.useIsPresent = create.useIsPresent;
|
|
3148
3124
|
exports.useIsomorphicLayoutEffect = create.useIsomorphicLayoutEffect;
|
|
3149
3125
|
exports.usePresence = create.usePresence;
|
|
3150
3126
|
exports.visualElementStore = create.visualElementStore;
|
|
3151
|
-
Object.defineProperty(exports, "
|
|
3127
|
+
Object.defineProperty(exports, "MotionValue", {
|
|
3152
3128
|
enumerable: true,
|
|
3153
|
-
get: function () { return
|
|
3129
|
+
get: function () { return motionDom.MotionValue; }
|
|
3154
3130
|
});
|
|
3155
|
-
Object.defineProperty(exports, "
|
|
3131
|
+
Object.defineProperty(exports, "cancelFrame", {
|
|
3156
3132
|
enumerable: true,
|
|
3157
|
-
get: function () { return
|
|
3133
|
+
get: function () { return motionDom.cancelFrame; }
|
|
3158
3134
|
});
|
|
3159
|
-
Object.defineProperty(exports, "
|
|
3135
|
+
Object.defineProperty(exports, "frame", {
|
|
3160
3136
|
enumerable: true,
|
|
3161
|
-
get: function () { return
|
|
3137
|
+
get: function () { return motionDom.frame; }
|
|
3138
|
+
});
|
|
3139
|
+
Object.defineProperty(exports, "frameData", {
|
|
3140
|
+
enumerable: true,
|
|
3141
|
+
get: function () { return motionDom.frameData; }
|
|
3162
3142
|
});
|
|
3163
3143
|
Object.defineProperty(exports, "hover", {
|
|
3164
3144
|
enumerable: true,
|
|
@@ -3168,10 +3148,34 @@ Object.defineProperty(exports, "isDragActive", {
|
|
|
3168
3148
|
enumerable: true,
|
|
3169
3149
|
get: function () { return motionDom.isDragActive; }
|
|
3170
3150
|
});
|
|
3151
|
+
Object.defineProperty(exports, "motionValue", {
|
|
3152
|
+
enumerable: true,
|
|
3153
|
+
get: function () { return motionDom.motionValue; }
|
|
3154
|
+
});
|
|
3171
3155
|
Object.defineProperty(exports, "press", {
|
|
3172
3156
|
enumerable: true,
|
|
3173
3157
|
get: function () { return motionDom.press; }
|
|
3174
3158
|
});
|
|
3159
|
+
Object.defineProperty(exports, "time", {
|
|
3160
|
+
enumerable: true,
|
|
3161
|
+
get: function () { return motionDom.time; }
|
|
3162
|
+
});
|
|
3163
|
+
Object.defineProperty(exports, "MotionGlobalConfig", {
|
|
3164
|
+
enumerable: true,
|
|
3165
|
+
get: function () { return motionUtils.MotionGlobalConfig; }
|
|
3166
|
+
});
|
|
3167
|
+
Object.defineProperty(exports, "invariant", {
|
|
3168
|
+
enumerable: true,
|
|
3169
|
+
get: function () { return motionUtils.invariant; }
|
|
3170
|
+
});
|
|
3171
|
+
Object.defineProperty(exports, "noop", {
|
|
3172
|
+
enumerable: true,
|
|
3173
|
+
get: function () { return motionUtils.noop; }
|
|
3174
|
+
});
|
|
3175
|
+
Object.defineProperty(exports, "progress", {
|
|
3176
|
+
enumerable: true,
|
|
3177
|
+
get: function () { return motionUtils.progress; }
|
|
3178
|
+
});
|
|
3175
3179
|
exports.AnimatePresence = AnimatePresence;
|
|
3176
3180
|
exports.AnimateSharedLayout = AnimateSharedLayout;
|
|
3177
3181
|
exports.DeprecatedLayoutGroupContext = DeprecatedLayoutGroupContext;
|
|
@@ -3183,7 +3187,6 @@ exports.Reorder = namespace;
|
|
|
3183
3187
|
exports.animate = animate;
|
|
3184
3188
|
exports.animateMini = animateMini;
|
|
3185
3189
|
exports.animationControls = animationControls;
|
|
3186
|
-
exports.cancelSync = cancelSync;
|
|
3187
3190
|
exports.createScopedAnimate = createScopedAnimate;
|
|
3188
3191
|
exports.disableInstantTransitions = disableInstantTransitions;
|
|
3189
3192
|
exports.domAnimation = domAnimation;
|
|
@@ -3198,7 +3201,6 @@ exports.scrollInfo = scrollInfo;
|
|
|
3198
3201
|
exports.stagger = stagger;
|
|
3199
3202
|
exports.startOptimizedAppearAnimation = startOptimizedAppearAnimation;
|
|
3200
3203
|
exports.steps = steps;
|
|
3201
|
-
exports.sync = sync;
|
|
3202
3204
|
exports.transform = transform;
|
|
3203
3205
|
exports.unwrapMotionComponent = unwrapMotionComponent;
|
|
3204
3206
|
exports.useAnimate = useAnimate;
|