@kadconsulting/dry
Version:
KAD Reusable Component Library
100 lines • 4.53 kB
JavaScript
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