UNPKG

aura-glass

Version:

A comprehensive glassmorphism design system for React applications with 142+ production-ready components

244 lines (241 loc) 9.88 kB
'use client'; import { jsx, jsxs } from 'react/jsx-runtime'; import { cn } from '../../lib/utilsComprehensive.js'; import { Check, AlertCircle, Circle } from 'lucide-react'; import React from 'react'; import '../../primitives/GlassCore.js'; import '../../primitives/glass/GlassAdvanced.js'; import '../../primitives/OptimizedGlassCore.js'; import '../../primitives/glass/OptimizedGlassAdvanced.js'; import '../../primitives/MotionNative.js'; import { MotionFramer } from '../../primitives/motion/MotionFramer.js'; /** * GlassFormStepper component * A visual stepper component for multi-step forms with glassmorphism design */ const GlassFormStepper = ({ steps, currentStep = 0, onStepClick, orientation = "horizontal", size = "md", showNumbers = true, showDescriptions = false, allowClickCompleted = true, showProgressLine = true, className, ...props }) => { // Size configurations const sizeConfigs = { sm: { stepSize: "w-8 h-8", iconSize: "w-4 h-4", fontSize: "glass-text-sm", lineHeight: "h-px", spacing: "glass-gap-4" }, md: { stepSize: "w-10 h-10", iconSize: "w-5 h-5", fontSize: "glass-text-base", lineHeight: "h-0.5", spacing: "glass-gap-6" }, lg: { stepSize: "w-12 h-12", iconSize: "w-6 h-6", fontSize: "glass-text-lg", lineHeight: "h-1", spacing: "gap-8" } }; const config = sizeConfigs[size]; // Get step state const getStepState = (stepIndex, step) => { if (step.disabled) return "disabled"; if (step.error) return "error"; if (step.completed) return "completed"; if (stepIndex === currentStep) return "active"; if (stepIndex < currentStep) return "completed"; return "pending"; }; // Get step styles based on state const getStepStyles = state => { switch (state) { case "completed": return { circle: "bg-green-500 border-green-500 glass-text-primary", icon: "glass-text-primary", line: "bg-green-500", text: "glass-text-primary" }; case "active": return { circle: "bg-primary border-primary glass-text-primary", icon: "glass-text-primary", line: "bg-primary/50", text: "glass-text-primary" }; case "error": return { circle: "bg-red-500 border-red-500 glass-text-primary", icon: "glass-text-primary", line: "bg-red-500/50", text: "text-red-300" }; case "disabled": return { circle: "bg-white/10 border-white/30 glass-text-primary/50", icon: "glass-text-primary/50", line: "bg-white/30", text: "glass-text-primary/50" }; default: return { circle: "bg-white/10 border-white/30 glass-text-primary/60", icon: "glass-text-primary/60", line: "bg-white/30", text: "glass-text-primary/60" }; } }; // Handle step click const handleStepClick = (stepIndex, step) => { const state = getStepState(stepIndex, step); if (state === "disabled") return; if (state === "pending" && !allowClickCompleted) return; onStepClick?.(stepIndex); }; // Render horizontal stepper const renderHorizontalStepper = () => jsx("nav", { "aria-label": "Form steps", className: cn("flex items-center justify-center", config.spacing, className), children: steps.map((step, index) => { const state = getStepState(index, step); const styles = getStepStyles(state); const isLast = index === steps.length - 1; return jsxs(React.Fragment, { "data-glass-component": true, children: [jsx("div", { className: 'glass-flex glass-flex-col glass-items-center group', children: jsxs(MotionFramer, { preset: state === "active" ? "scaleIn" : "fadeIn", className: 'glass-flex glass-flex-col glass-items-center cursor-pointer', onClick: e => handleStepClick(index, step), role: "button", "aria-label": `Step ${index + 1}: ${step.title}${state === "completed" ? " (completed)" : state === "active" ? " (current)" : ""}`, "aria-current": state === "active" ? "step" : undefined, "aria-disabled": state === "disabled", tabIndex: state === "disabled" ? -1 : 0, onKeyDown: e => { if (e.key === "Enter" || e.key === " ") { e.preventDefault(); handleStepClick(index, step); } }, children: [jsxs("div", { className: cn("relative glass-radius-full border-2 flex items-center justify-center transition-all duration-200", "hover:scale-110 group-hover:shadow-lg", config.stepSize, styles.circle), children: [state === "completed" ? jsx(Check, { className: config.iconSize }) : state === "error" ? jsx(AlertCircle, { className: config.iconSize }) : step.icon ? jsx("span", { className: cn(config.iconSize, styles.icon), children: step.icon }) : showNumbers ? jsx("span", { className: cn("font-medium", config.fontSize.replace("text-", "text-"), styles.icon), children: index + 1 }) : jsx(Circle, { className: config.iconSize }), step.optional && jsx("div", { className: 'absolute glass-top-1 -right-1 w-2 h-2 glass-surface-yellow glass-radius-full' })] }), jsxs("div", { className: 'mt-3 text-center max-w-24', children: [jsx("h3", { className: cn("font-medium leading-tight", config.fontSize, styles.text), children: step.title }), showDescriptions && step.description && jsx("p", { className: cn("glass-text-xs glass-mt-1 leading-tight", state === "active" ? "glass-text-primary/80" : "glass-text-primary/50"), children: step.description })] })] }) }), !isLast && showProgressLine && jsx("div", { className: cn("flex-1 glass-mx-2 transition-all duration-300", config.lineHeight, index < currentStep ? styles.line : "bg-white/20") })] }, step.id); }) }); // Render vertical stepper const renderVerticalStepper = () => jsx("nav", { "aria-label": "Form steps", className: cn("flex flex-col", config.spacing, className), children: steps.map((step, index) => { const state = getStepState(index, step); const styles = getStepStyles(state); const isLast = index === steps.length - 1; return jsxs(React.Fragment, { children: [jsx("div", { className: 'glass-flex glass-items-start group', children: jsxs(MotionFramer, { preset: state === "active" ? "slideRight" : "fadeIn", className: 'glass-flex glass-items-start cursor-pointer', onClick: e => handleStepClick(index, step), role: "button", "aria-label": `Step ${index + 1}: ${step.title}${state === "completed" ? " (completed)" : state === "active" ? " (current)" : ""}`, "aria-current": state === "active" ? "step" : undefined, "aria-disabled": state === "disabled", tabIndex: state === "disabled" ? -1 : 0, onKeyDown: e => { if (e.key === "Enter" || e.key === " ") { e.preventDefault(); handleStepClick(index, step); } }, children: [jsxs("div", { className: cn("relative glass-radius-full border-2 flex items-center justify-center transition-all duration-200", "hover:scale-110 group-hover:shadow-lg glass-mr-4", config.stepSize, styles.circle), children: [state === "completed" ? jsx(Check, { className: config.iconSize }) : state === "error" ? jsx(AlertCircle, { className: config.iconSize }) : step.icon ? jsx("span", { className: cn(config.iconSize, styles.icon), children: step.icon }) : showNumbers ? jsx("span", { className: cn("font-medium", config.fontSize.replace("text-", "text-"), styles.icon), children: index + 1 }) : jsx(Circle, { className: config.iconSize }), step.optional && jsx("div", { className: 'absolute glass-top-1 -right-1 w-2 h-2 glass-surface-yellow glass-radius-full' })] }), jsxs("div", { className: 'glass-flex-1 pt-1', children: [jsx("h3", { className: cn("font-medium leading-tight", config.fontSize, styles.text), children: step.title }), showDescriptions && step.description && jsx("p", { className: cn("glass-text-sm glass-mt-1 leading-tight", state === "active" ? "glass-text-primary/80" : "glass-text-primary/50"), children: step.description })] })] }) }), !isLast && showProgressLine && jsx("div", { className: "glass-flex glass-justify-center glass-py-2", children: jsx("div", { className: cn("w-px h-8 transition-all duration-300", index < currentStep ? styles.line : "bg-white/20") }) })] }, step.id); }) }); return jsx(MotionFramer, { preset: "fadeIn", className: "glass-w-full", children: orientation === "horizontal" ? renderHorizontalStepper() : renderVerticalStepper() }); }; export { GlassFormStepper, GlassFormStepper as default }; //# sourceMappingURL=GlassFormStepper.js.map