2023-02-04 01:01:54 +01:00
|
|
|
import { ReactNode, useRef } from "react";
|
|
|
|
import { CSSTransition } from "react-transition-group";
|
|
|
|
import { CSSTransitionClassNames } from "react-transition-group/CSSTransition";
|
|
|
|
|
2023-02-07 17:49:05 +01:00
|
|
|
type TransitionAnimations = "slide-down" | "slide-up" | "fade" | "fade-inverse";
|
2023-02-04 01:01:54 +01:00
|
|
|
|
|
|
|
interface Props {
|
|
|
|
show: boolean;
|
2023-02-07 17:49:05 +01:00
|
|
|
durationClass?: string;
|
2023-02-04 01:01:54 +01:00
|
|
|
animation: TransitionAnimations;
|
|
|
|
className?: string;
|
|
|
|
children?: ReactNode;
|
|
|
|
}
|
|
|
|
|
|
|
|
function getClasses(
|
|
|
|
animation: TransitionAnimations,
|
|
|
|
duration: number
|
|
|
|
): CSSTransitionClassNames {
|
|
|
|
if (animation === "slide-down") {
|
|
|
|
return {
|
|
|
|
exit: `transition-[transform,opacity] translate-y-0 duration-${duration} opacity-100`,
|
|
|
|
exitActive: "!-translate-y-4 !opacity-0",
|
|
|
|
exitDone: "hidden",
|
|
|
|
enter: `transition-[transform,opacity] -translate-y-4 duration-${duration} opacity-0`,
|
|
|
|
enterActive: "!translate-y-0 !opacity-100",
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
if (animation === "slide-up") {
|
|
|
|
return {
|
|
|
|
exit: `transition-[transform,opacity] translate-y-0 duration-${duration} opacity-100`,
|
|
|
|
exitActive: "!translate-y-4 !opacity-0",
|
|
|
|
exitDone: "hidden",
|
|
|
|
enter: `transition-[transform,opacity] translate-y-4 duration-${duration} opacity-0`,
|
|
|
|
enterActive: "!translate-y-0 !opacity-100",
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
if (animation === "fade") {
|
|
|
|
return {
|
|
|
|
exit: `transition-[transform,opacity] duration-${duration} opacity-100`,
|
|
|
|
exitActive: "!opacity-0",
|
|
|
|
exitDone: "hidden",
|
|
|
|
enter: `transition-[transform,opacity] duration-${duration} opacity-0`,
|
|
|
|
enterActive: "!opacity-100",
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2023-02-07 17:49:05 +01:00
|
|
|
if (animation === "fade-inverse") {
|
|
|
|
return {
|
|
|
|
enter: `transition-[transform,opacity] duration-${duration} opacity-100`,
|
|
|
|
enterActive: "!opacity-0",
|
|
|
|
exit: `transition-[transform,opacity] duration-${duration} opacity-0`,
|
|
|
|
exitActive: "!opacity-100",
|
|
|
|
enterDone: "hidden",
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2023-02-04 01:01:54 +01:00
|
|
|
return {};
|
|
|
|
}
|
|
|
|
|
|
|
|
export function Transition(props: Props) {
|
|
|
|
const ref = useRef<HTMLDivElement>(null);
|
2023-02-07 17:49:05 +01:00
|
|
|
const duration = props.durationClass
|
|
|
|
? parseInt(props.durationClass.split("-")[1], 10)
|
|
|
|
: 200;
|
|
|
|
const classes = getClasses(props.animation, duration);
|
2023-02-04 01:01:54 +01:00
|
|
|
|
|
|
|
return (
|
|
|
|
<CSSTransition
|
|
|
|
nodeRef={ref}
|
|
|
|
in={props.show}
|
2023-02-07 17:49:05 +01:00
|
|
|
timeout={duration}
|
|
|
|
classNames={classes}
|
2023-02-04 01:01:54 +01:00
|
|
|
>
|
2023-02-07 17:49:05 +01:00
|
|
|
<div
|
|
|
|
ref={ref}
|
|
|
|
className={[props.className ?? "", classes.enter ?? ""].join(" ")}
|
|
|
|
>
|
2023-02-04 01:01:54 +01:00
|
|
|
{props.children}
|
|
|
|
</div>
|
|
|
|
</CSSTransition>
|
|
|
|
);
|
|
|
|
}
|