@omicrxn/mercury
Version:
Mercury is a Svelte animation library powered by Motion. It simplifies complex animations with Svelte actions, provides layout and exit animations, and integrates seamlessly with Svelte features.
51 lines (50 loc) • 1.84 kB
JavaScript
const scopes = new WeakMap();
const MERCURY_CONTROLS = Symbol('mercury:controls');
/** Parent element used to coordinate enter/exit timing within a slot. */
export const getPresenceScope = (element) => element.parentElement ?? document.documentElement;
const getScopeState = (scope) => {
const state = scopes.get(scope) ?? { count: 0, listeners: new Set() };
scopes.set(scope, state);
return state;
};
/** Whether a wait-mode exit is still running in this scope. */
export const hasPendingWaitExit = (element) => (scopes.get(getPresenceScope(element))?.count ?? 0) > 0;
/** Register a wait-mode exit so subsequent enters in the same scope defer. */
export const registerWaitExit = (element) => {
getScopeState(getPresenceScope(element)).count += 1;
};
/** Call when a wait-mode exit animation finishes or is cancelled. */
export const completeWaitExit = (element) => {
const scope = getPresenceScope(element);
const state = scopes.get(scope);
if (!state)
return;
state.count -= 1;
if (state.count > 0)
return;
const listeners = [...state.listeners];
scopes.delete(scope);
for (const listener of listeners)
listener();
};
/**
* Run `fn` once any active wait-mode exit in this scope has finished.
* Waits one macrotask so out:presence can register in the same commit.
*/
export const runAfterPendingExit = (element, fn) => {
setTimeout(() => {
if (!hasPendingWaitExit(element)) {
fn();
return;
}
getScopeState(getPresenceScope(element)).listeners.add(fn);
}, 0);
};
export const registerMercuryControls = (element, controls) => {
element[MERCURY_CONTROLS] = controls;
};
export const stopMercury = (element) => {
const el = element;
el[MERCURY_CONTROLS]?.stop();
el[MERCURY_CONTROLS] = undefined;
};