import React, {ReactElement, useEffect, useRef, useState} from "react" import {Paper} from "@mui/material" import {whenElementHasBounds} from "~/utils" export interface MultiStepFormProps { steps: ReactElement[] index: number duration?: number easing?: string } function MultiStepForm({ steps, index, duration = 900, easing = "ease-in-out", }: MultiStepFormProps): ReactElement { const $currentElement = useRef(null) const $timeout = useRef() const [currentIndex, setCurrentIndex] = useState(index) const [currentSize, setCurrentSize] = useState(null) const [nextSize, setNextSize] = useState(null) const isTransitioning = currentIndex < index useEffect(() => { if (index > currentIndex) { $timeout.current = setTimeout(() => { setCurrentSize(null) setNextSize(null) setCurrentIndex(index) }, duration) } else if (index < currentIndex) { // "Going-back" animation is not supported setCurrentIndex(index) setCurrentSize(null) setNextSize(null) } return $timeout.current?.cancel! }, [index, currentIndex]) const hasSize = Boolean( (currentSize?.width || nextSize?.width) && (currentSize?.height || nextSize?.height), ) return (
{ if (ref === null) { return } // @ts-ignore $currentElement.current = ref const { width = 0, height = 0, x, y, } = ref.getBoundingClientRect() if ( width !== 0 && height !== 0 && width !== currentSize?.width && height !== currentSize?.height ) { setCurrentSize({ width: width, height: height, x: x, y: y, }) } }} style={{ position: "absolute", width: "max-content", height: "max-content", transition: easing, transitionDuration: isTransitioning ? `${duration}ms` : "", transform: isTransitioning ? "translateX(-100%)" : "", }} > {steps[currentIndex]}
{ if (nextSize === null) { setNextSize({ width: rect.width, height: rect.height, x: rect.x, y: rect.y, }) } })} style={{ position: "absolute", width: "max-content", height: "max-content", transition: easing, transitionDuration: isTransitioning ? `${duration}ms` : "", transform: isTransitioning ? "" : nextSize?.x ? "translateX(100%)" : "", }} > {currentIndex === steps.length - 1 ? null : steps[currentIndex + 1]}
) } export default MultiStepForm