import * as React from 'react';
import Button from '../../buttons/Button';
import Transition from '../Transition';
import DummyBox from './common/DummyBox';
import Stage from './common/Stage';
import {useIsomorphicLayoutEffect} from '../../utils/useIsomorphicLayoutEffect';
import {useTransformationState} from './common/useTransformationState';
const appearingEffect = {
initial: {
opacity: 0,
transform: {
scale: 0.9,
},
},
animate: {
opacity: 1,
duration: 'moderate1',
},
};
const removingEffect = {
animate: {
opacity: 0,
duration: 'quick2',
},
};
const initialItemIds = [0, 1, 2, 3];
/**
* It is greater than the ID of the last initial item to
* not animate the already added items at the beginning.
*/
let lastUniqueId = initialItemIds.length;
export const FluidList = () => {
const containerRef = React.useRef(null);
const [itemIds, setItemIds] = React.useState(initialItemIds);
const addItem = () => {
setItemIds(prev => [++lastUniqueId, ...prev]);
};
const removeItem = (id: number) => {
setItemIds(prev => prev.filter(n => n !== id));
};
return (
{itemIds.map((id, index) => (
removeItem(id)}
/>
))}
);
};
const FluidListItem = ({
index,
updateKey,
containerRef,
lastCreated,
siblingsAmount,
onRemove,
}: {
index: number;
updateKey: number;
containerRef: {
current: HTMLElement | null;
};
lastCreated: boolean;
siblingsAmount: number;
onRemove: () => void;
}) => {
const [removing, setRemoving] = React.useState(false);
const [movementEffect, setMovementEffect] = React.useState(null);
const elementRef = React.useRef(null);
const transformation = useTransformationState({
elementRef,
containerRef,
updateKey,
});
const getTransitionEffect = () => {
if (removing) {
return removingEffect;
}
if (lastCreated) {
return appearingEffect;
}
return movementEffect;
};
const getTransitionDelay = () => {
const appearingDelay = 180;
const delayOffset = 20;
if (removing || siblingsAmount === 0) {
return 0;
}
if (lastCreated) {
return appearingDelay;
}
/**
* To simulate weightlessness we can delay the
* transition of each item when it moves upward.
*/
if (transformation.diffTop < 0) {
return appearingDelay + delayOffset * index;
}
return 0;
};
useIsomorphicLayoutEffect(() => {
if (transformation.diffTop !== 0) {
/**
* https://css-tricks.com/animating-layouts-with-the-flip-technique/
*/
setMovementEffect({
// @ts-ignore TS2353
initial: {
transform: {
translateY: -transformation.diffTop,
},
},
animate: {
transform: {
translateY: 0,
duration: 'moderate1',
},
},
});
}
}, [transformation]);
return (
setRemoving(true)}
/>
);
};
FluidList.parameters = {
layout: 'centered',
};