@coreui/react-pro
Version:
UI Components Library for React.js
202 lines (198 loc) • 10.7 kB
JavaScript
;
var tslib_es6 = require('../../node_modules/tslib/tslib.es6.js');
var React = require('react');
var PropTypes = require('prop-types');
var index = require('../../_virtual/index.js');
var CCollapse = require('../collapse/CCollapse.js');
var getNextActiveElement = require('../../utils/getNextActiveElement.js');
var CStepper = React.forwardRef(function (_a, ref) {
var controlledActiveStepIndex = _a.activeStepIndex, className = _a.className, _b = _a.defaultActiveStepIndex, defaultActiveStepIndex = _b === void 0 ? 0 : _b, _c = _a.layout, layout = _c === void 0 ? 'horizontal' : _c, _d = _a.linear, linear = _d === void 0 ? true : _d, onFinish = _a.onFinish, onReset = _a.onReset, onStepChange = _a.onStepChange, onStepValidationComplete = _a.onStepValidationComplete, _e = _a.steps, steps = _e === void 0 ? [] : _e, _f = _a.stepButtonLayout, stepButtonLayout = _f === void 0 ? 'horizontal' : _f, _g = _a.validation, validation = _g === void 0 ? true : _g, rest = tslib_es6.__rest(_a, ["activeStepIndex", "className", "defaultActiveStepIndex", "layout", "linear", "onFinish", "onReset", "onStepChange", "onStepValidationComplete", "steps", "stepButtonLayout", "validation"]);
var stepperRef = React.useRef(null);
var stepsRef = React.useRef(null);
var stepButtonRefs = React.useRef([]);
var uniqueId = React.useId();
var isControlled = controlledActiveStepIndex !== undefined;
var _h = React.useState(isControlled ? controlledActiveStepIndex : defaultActiveStepIndex), internalActiveStepIndex = _h[0], setInternalActiveStepIndex = _h[1];
var _j = React.useState(false), isFinished = _j[0], setIsFinished = _j[1];
var activeStepIndex = isControlled ? controlledActiveStepIndex : internalActiveStepIndex;
// Sync state if controlled prop changes
React.useEffect(function () {
if (isControlled) {
setInternalActiveStepIndex(controlledActiveStepIndex);
}
}, [controlledActiveStepIndex, isControlled]);
// Ensure stepButtonRefs array has the correct size
React.useEffect(function () {
stepButtonRefs.current = stepButtonRefs.current.slice(0, steps.length);
}, [steps.length]);
var isStepValid = React.useCallback(function (index) {
var _a;
if (!validation) {
return true;
}
var currentStepData = steps[index];
var form = (_a = currentStepData === null || currentStepData === void 0 ? void 0 : currentStepData.formRef) === null || _a === void 0 ? void 0 : _a.current;
if (form) {
var isValid = form.checkValidity();
onStepValidationComplete === null || onStepValidationComplete === void 0 ? void 0 : onStepValidationComplete({
stepNumber: index + 1,
isValid: isValid,
});
if (form && !isValid) {
form.reportValidity();
return false;
}
}
return true;
}, [steps, validation]);
var setActiveStep = React.useCallback(function (index, bypassValidation) {
if (bypassValidation === void 0) { bypassValidation = false; }
if (index < 0 || index >= steps.length || index === activeStepIndex) {
return;
}
// Validate current step before moving forward
if (!bypassValidation && index > activeStepIndex && !isStepValid(activeStepIndex)) {
return;
}
if (!isControlled) {
setInternalActiveStepIndex(index);
}
onStepChange === null || onStepChange === void 0 ? void 0 : onStepChange(index + 1);
}, [steps.length, activeStepIndex, isStepValid, isControlled, onStepChange]);
var handleStepClick = function (index) {
if (linear) {
setActiveStep(index, index <= activeStepIndex);
return;
}
setActiveStep(index, true);
};
var handleNext = function () {
if (activeStepIndex < steps.length - 1) {
setActiveStep(activeStepIndex + 1);
}
else {
handleFinish(); // Attempt finish if already on last step
}
};
var handlePrev = function () {
if (activeStepIndex > 0) {
setActiveStep(activeStepIndex - 1, true); // Bypass validation when going back
}
};
var handleFinish = function () {
if (activeStepIndex === steps.length - 1 && isStepValid(activeStepIndex)) {
setIsFinished(true);
onFinish === null || onFinish === void 0 ? void 0 : onFinish();
}
};
var handleReset = function () {
var _a;
if (validation) {
steps.forEach(function (step) { var _a, _b; return (_b = (_a = step.formRef) === null || _a === void 0 ? void 0 : _a.current) === null || _b === void 0 ? void 0 : _b.reset(); });
}
if (!isControlled) {
setInternalActiveStepIndex(defaultActiveStepIndex);
}
setIsFinished(false);
onStepChange === null || onStepChange === void 0 ? void 0 : onStepChange(defaultActiveStepIndex);
onReset === null || onReset === void 0 ? void 0 : onReset();
(_a = stepButtonRefs.current[defaultActiveStepIndex]) === null || _a === void 0 ? void 0 : _a.focus();
};
var handleKeyDown = function (event) {
var target = event.target;
var currentButton = target.closest('button.stepper-step-button');
if (!currentButton || !stepsRef.current) {
return;
}
var buttons = tslib_es6.__spreadArray([], stepsRef.current.querySelectorAll('button.stepper-step-button'), true);
var nextElement = null;
switch (event.key) {
case 'ArrowRight':
case 'ArrowDown': {
nextElement = getNextActiveElement.default(buttons, currentButton, true, false);
break;
}
case 'ArrowLeft':
case 'ArrowUp': {
nextElement = getNextActiveElement.default(buttons, currentButton, false, false);
break;
}
case 'Home': {
nextElement = buttons[0];
break;
}
case 'End': {
nextElement = buttons.at(-1);
break;
}
default: {
return;
}
}
if (nextElement) {
event.preventDefault();
nextElement.focus();
}
};
// Expose methods via ref
React.useImperativeHandle(ref, function () { return ({
next: handleNext,
prev: handlePrev,
finish: handleFinish,
reset: handleReset,
}); });
var isVertical = layout === 'vertical';
return (React.createElement("div", tslib_es6.__assign({ className: index.default('stepper', {
'stepper-vertical': isVertical,
}, className), ref: stepperRef }, rest),
React.createElement("ol", { className: "stepper-steps", "aria-orientation": isVertical ? 'vertical' : 'horizontal', ref: stepsRef, onKeyDown: handleKeyDown, role: "tablist" }, steps.map(function (step, index$1) {
var _a;
var isActive = !isFinished && index$1 === activeStepIndex;
var isComplete = isFinished || index$1 < activeStepIndex;
var isDisabled = isFinished || (linear && index$1 > activeStepIndex + 1);
var stepId = "stepper-".concat(rest.id || uniqueId, "-step-").concat(index$1);
var panelId = "stepper-".concat(rest.id || uniqueId, "-panel-").concat(index$1);
return (React.createElement("li", { key: index$1, className: index.default('stepper-step', stepButtonLayout), role: "presentation" },
React.createElement("button", tslib_es6.__assign({ type: "button", className: index.default('stepper-step-button', {
active: isActive,
complete: isComplete,
}), disabled: isDisabled, id: stepId, role: "tab", onClick: function () { return handleStepClick(index$1); }, ref: function (el) { return (stepButtonRefs.current[index$1] = el); }, "aria-selected": isActive }, (step.content && {
'aria-controls': panelId,
}), { tabIndex: isActive ? 0 : -1 }),
React.createElement("span", { className: "stepper-step-indicator" }, isComplete ? (React.createElement("span", { className: "stepper-step-indicator-icon" })) : (React.createElement("span", { className: "stepper-step-indicator-text" }, (_a = step.indicator) !== null && _a !== void 0 ? _a : index$1 + 1))),
React.createElement("span", { className: "stepper-step-label" }, step.label)),
index$1 < steps.length - 1 && React.createElement("div", { className: "stepper-step-connector" }),
step.content && isVertical && (React.createElement(CCollapse.CCollapse, { className: "stepper-step-content", id: panelId, role: "tabpanel", visible: isActive, "aria-hidden": !isActive, "aria-labelledby": stepId, "aria-live": "polite" }, step.content))));
})),
!isVertical &&
steps.some(function (step) { return step.content !== undefined && step.content !== null; }) && (React.createElement("div", { className: "stepper-content" }, steps.map(function (step, index$1) {
var isActive = !isFinished && index$1 === activeStepIndex;
var stepId = "stepper-".concat(rest.id || uniqueId, "-step-").concat(index$1);
var panelId = "stepper-".concat(rest.id || uniqueId, "-panel-").concat(index$1);
return (React.createElement("div", { key: index$1, className: index.default('stepper-pane', {
show: isActive,
active: isActive,
}), id: panelId, role: "tabpanel", "aria-hidden": !isActive, "aria-labelledby": stepId, "aria-live": "polite" }, step.content));
})))));
});
CStepper.displayName = 'CStepper';
CStepper.propTypes = {
activeStepIndex: PropTypes.number,
className: PropTypes.string,
defaultActiveStepIndex: PropTypes.number,
layout: PropTypes.oneOf(['horizontal', 'vertical']),
linear: PropTypes.bool,
onFinish: PropTypes.func,
onReset: PropTypes.func,
onStepChange: PropTypes.func,
onStepValidationComplete: PropTypes.func,
steps: PropTypes.arrayOf(PropTypes.shape({
label: PropTypes.node.isRequired,
content: PropTypes.node,
formRef: PropTypes.object, // Check for object shape might be better
}).isRequired).isRequired,
stepButtonLayout: PropTypes.oneOf(['horizontal', 'vertical']),
validation: PropTypes.bool,
};
exports.CStepper = CStepper;
//# sourceMappingURL=CStepper.js.map