@wix/design-system
Version:
@wix/design-system
70 lines • 2.52 kB
JavaScript
import { useLayoutEffect, useReducer, useRef } from 'react';
export const useExitTransition = ({ elements, getNode, }) => {
const previous = useRef(new Map());
const exiting = useRef(new Map());
const watched = useRef(new Set());
const getNodeRef = useRef(getNode);
const [, rerender] = useReducer(count => count + 1, 0);
getNodeRef.current = getNode;
const current = new Map();
elements.forEach(element => current.set(String(element.key), element));
current.forEach((_, key) => exiting.current.delete(key));
previous.current.forEach((element, key) => {
if (!current.has(key) && !exiting.current.has(key)) {
exiting.current.set(key, element);
}
});
const insertions = new Map();
let displaced = [];
previous.current.forEach((_, key) => {
if (current.has(key)) {
if (displaced.length) {
insertions.set(key, displaced);
displaced = [];
}
}
else if (exiting.current.has(key)) {
displaced.push(key);
}
});
const orderedKeys = [];
current.forEach((_, key) => {
orderedKeys.push(...(insertions.get(key) ?? []), key);
});
orderedKeys.push(...displaced);
const entries = orderedKeys.map(key => ({
key,
element: (current.get(key) ??
exiting.current.get(key)),
exiting: !current.has(key),
}));
previous.current = new Map(entries.map(entry => [entry.key, entry.element]));
const exitingKeys = entries
.filter(entry => entry.exiting)
.map(entry => entry.key)
.join('|');
useLayoutEffect(() => {
const finish = (key) => {
watched.current.delete(key);
previous.current.delete(key);
if (exiting.current.delete(key)) {
rerender();
}
};
exiting.current.forEach((_, key) => {
if (watched.current.has(key)) {
return;
}
watched.current.add(key);
const node = getNodeRef.current(key);
const animations = typeof node?.getAnimations === 'function' ? node.getAnimations() : [];
if (!animations.length) {
finish(key);
return;
}
Promise.allSettled(animations.map(animation => animation.finished)).then(() => finish(key));
});
}, [exitingKeys]);
return entries;
};
//# sourceMappingURL=useExitTransition.js.map