svelte-motion
Version:
Svelte animation library based on the React library framer-motion.
94 lines (90 loc) • 3.29 kB
JavaScript
/**
based on framer-motion@4.0.3,
Copyright (c) 2018 Framer B.V.
*/
import { __spreadArray, __read } from 'tslib';
//import { invariant } from 'hey-listen';
import { stopAnimation, animateVisualElement } from '../render/utils/animation.js';
import { setValues } from '../render/utils/setters.js';
/**
* @public
*/
function animationControls(startStopNotifier) {
/**
* Track whether the host component has mounted.
*/
var hasMounted = false;
/**
* Pending animations that are started before a component is mounted.
* TODO: Remove this as animations should only run in effects
*/
var pendingAnimations = [];
/**
* A collection of linked component animation controls.
*/
var subscribers = new Set();
var stopNotification;
var controls = {
subscribe: function (visualElement) {
if (subscribers.size === 0){
stopNotification = startStopNotifier?.();
}
subscribers.add(visualElement);
return function () {
subscribers.delete(visualElement);
if (subscribers.size===0){
stopNotification?.()
}
};
},
start: function (definition, transitionOverride) {
/**
* TODO: We only perform this hasMounted check because in Framer we used to
* encourage the ability to start an animation within the render phase. This
* isn't behaviour concurrent-safe so when we make Framer concurrent-safe
* we can ditch this.
*/
if (hasMounted) {
var animations_1 = [];
subscribers.forEach(function (visualElement) {
animations_1.push(animateVisualElement(visualElement, definition, {
transitionOverride: transitionOverride,
}));
});
return Promise.all(animations_1);
}
else {
return new Promise(function (resolve) {
pendingAnimations.push({
animation: [definition, transitionOverride],
resolve: resolve,
});
});
}
},
set: function (definition) {
//invariant(hasMounted, "controls.set() should only be called after a component has mounted. Consider calling within a useEffect hook.");
return subscribers.forEach(function (visualElement) {
setValues(visualElement, definition);
});
},
stop: function () {
subscribers.forEach(function (visualElement) {
stopAnimation(visualElement);
});
},
mount: function () {
hasMounted = true;
pendingAnimations.forEach(function (_a) {
var animation = _a.animation, resolve = _a.resolve;
controls.start.apply(controls, __spreadArray([], __read(animation))).then(resolve);
});
return function () {
hasMounted = false;
controls.stop();
};
},
};
return controls;
}
export { animationControls };