UNPKG

@kadconsulting/dry

Version:
100 lines 4.53 kB
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime"; import React, { useState, useEffect, forwardRef } from 'react'; import { Button, ProgressSteps } from '../index'; import useWindowSize from '../../hooks/useWindowSize'; import './Wizard.scss'; const Wizard = forwardRef(({ steps, currentStep: externalCurrentStep, onStepChange: externalOnStepChange, error: externalError, nextButtonLabel = 'Next', previousButtonLabel = 'Previous', loading: externalLoading, onStepChanging, hideProgressBar, }, ref) => { // ======================= // Hooks // ======================= const { width } = useWindowSize(); // ======================= // State // ======================= const [currentStepIndex, setCurrentStepIndex] = useState(0); const [stepStates, setStepStates] = useState(new Array(steps.length)); const [error, setError] = useState(externalError); const [isLoading, setIsLoading] = useState(false); // ======================= // Effects // ======================= useEffect(() => { if (externalCurrentStep !== undefined) { setCurrentStepIndex(externalCurrentStep); } }, [externalCurrentStep]); useEffect(() => { setError(externalError); }, [externalError]); useEffect(() => { setIsLoading(externalLoading || false); }, [externalLoading]); // ======================= // Handle Functions // ======================= const handleNext = async () => { const currentStep = steps[currentStepIndex]; if (currentStep.validate && !currentStep.validate()) { return; } setIsLoading(true); await currentStep.onNext?.(); setIsLoading(false); if (onStepChanging) { await onStepChanging(currentStepIndex + 1); } const newStep = currentStepIndex + 1; setCurrentStepIndex(newStep); externalOnStepChange?.(newStep); scrollToTop(); }; const handlePrevious = async () => { const currentStep = steps[currentStepIndex]; setIsLoading(true); await currentStep.onPrevious?.(); setIsLoading(false); if (onStepChanging) { await onStepChanging(currentStepIndex - 1); } const newStep = currentStepIndex - 1; setCurrentStepIndex(newStep); externalOnStepChange?.(newStep); scrollToTop(); }; const handleStepChange = (stepIndex, stepState) => { const newStepStates = [...stepStates]; newStepStates[stepIndex] = stepState; setStepStates(newStepStates); }; const scrollToTop = () => { if (typeof window !== 'undefined') { window.scrollTo({ top: 0, behavior: 'smooth' }); } }; // ======================= // Variables // ======================= const progressSteps = steps.map((step, index) => ({ id: step.id || index, title: step.title, text: step.text, })); const currentStep = steps[currentStepIndex]; // ======================= // Render // ======================= if (isLoading) { return _jsx("div", { "aria-label": 'Loading', children: "Loading..." }); } return (_jsxs("div", { className: 'wizard', ref: ref, children: [!hideProgressBar && (_jsx(ProgressSteps, { steps: progressSteps, activeColor: '#007bff', onStepClick: (step) => { setCurrentStepIndex(step); externalOnStepChange?.(step); }, typographyProps: { textAlign: 'center' }, step: currentStepIndex, isMobile: width < 768 })), error && _jsx("div", { className: 'wizard__error', children: error }), _jsx("div", { className: 'wizard__step', children: React.cloneElement(currentStep.component, { stepState: stepStates[currentStepIndex], onStepChange: (stepState) => handleStepChange(currentStepIndex, stepState), }) }), !currentStep.removeButtons && (_jsxs("div", { className: 'wizard__navigation', children: [_jsx(Button, { onClick: handlePrevious, disabled: currentStepIndex === 0 || isLoading, children: previousButtonLabel }), !currentStep.noNextButton && (_jsx(Button, { onClick: handleNext, disabled: currentStepIndex === steps.length - 1 || isLoading || (currentStep.validate && !currentStep.validate()), children: nextButtonLabel }))] }))] })); }); export default Wizard; //# sourceMappingURL=Wizard.js.map