@moontra/moonui-pro 2.8.1 → 2.8.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs
CHANGED
|
@@ -60056,16 +60056,61 @@ var FormWizardProvider = ({
|
|
|
60056
60056
|
}, [stepData, currentStep, completedSteps, persistData, storageKey]);
|
|
60057
60057
|
const validateCurrentStep = useCallback(async () => {
|
|
60058
60058
|
const step = steps[currentStep];
|
|
60059
|
+
if (typeof window !== "undefined") {
|
|
60060
|
+
const stepElement = document.querySelector("[data-wizard-step-content]");
|
|
60061
|
+
if (stepElement) {
|
|
60062
|
+
const requiredInputs = stepElement.querySelectorAll("input[required], select[required], textarea[required]");
|
|
60063
|
+
const emptyFields = [];
|
|
60064
|
+
requiredInputs.forEach((input) => {
|
|
60065
|
+
const htmlInput = input;
|
|
60066
|
+
if (!htmlInput.value || htmlInput.value.trim() === "") {
|
|
60067
|
+
const label = document.querySelector(`label[for="${htmlInput.id}"]`);
|
|
60068
|
+
const fieldName = label ? label.textContent?.replace(" *", "") || "Field" : htmlInput.name || htmlInput.id || "Field";
|
|
60069
|
+
emptyFields.push(fieldName);
|
|
60070
|
+
}
|
|
60071
|
+
});
|
|
60072
|
+
const requiredCheckboxes = stepElement.querySelectorAll('input[type="checkbox"][required]');
|
|
60073
|
+
requiredCheckboxes.forEach((checkbox) => {
|
|
60074
|
+
const htmlCheckbox = checkbox;
|
|
60075
|
+
if (!htmlCheckbox.checked) {
|
|
60076
|
+
const label = document.querySelector(`label[for="${htmlCheckbox.id}"]`);
|
|
60077
|
+
const fieldName = label ? label.textContent?.replace(" *", "") || "Checkbox" : htmlCheckbox.name || htmlCheckbox.id || "Checkbox";
|
|
60078
|
+
emptyFields.push(fieldName);
|
|
60079
|
+
}
|
|
60080
|
+
});
|
|
60081
|
+
if (emptyFields.length > 0) {
|
|
60082
|
+
setError(`Please fill in the following required fields: ${emptyFields.join(", ")}`);
|
|
60083
|
+
return false;
|
|
60084
|
+
}
|
|
60085
|
+
}
|
|
60086
|
+
}
|
|
60059
60087
|
if (!step.validation)
|
|
60060
60088
|
return true;
|
|
60061
60089
|
setIsLoading(true);
|
|
60062
60090
|
setError(null);
|
|
60063
60091
|
try {
|
|
60064
|
-
const
|
|
60065
|
-
if (
|
|
60066
|
-
|
|
60092
|
+
const result = await step.validation();
|
|
60093
|
+
if (typeof result === "boolean") {
|
|
60094
|
+
if (!result) {
|
|
60095
|
+
setError("Please complete all required fields before proceeding");
|
|
60096
|
+
}
|
|
60097
|
+
return result;
|
|
60098
|
+
}
|
|
60099
|
+
if (typeof result === "object" && result !== null && "isValid" in result) {
|
|
60100
|
+
const validationResult = result;
|
|
60101
|
+
if (!validationResult.isValid) {
|
|
60102
|
+
if (validationResult.error) {
|
|
60103
|
+
setError(validationResult.error);
|
|
60104
|
+
} else if (validationResult.errors && Array.isArray(validationResult.errors)) {
|
|
60105
|
+
setError(validationResult.errors.join(", "));
|
|
60106
|
+
} else {
|
|
60107
|
+
setError("Please complete all required fields before proceeding");
|
|
60108
|
+
}
|
|
60109
|
+
}
|
|
60110
|
+
return validationResult.isValid;
|
|
60067
60111
|
}
|
|
60068
|
-
|
|
60112
|
+
setError("Invalid validation response");
|
|
60113
|
+
return false;
|
|
60069
60114
|
} catch (err) {
|
|
60070
60115
|
setError(err instanceof Error ? err.message : "Validation failed");
|
|
60071
60116
|
return false;
|
|
@@ -60196,47 +60241,46 @@ var FormWizardProgress = ({
|
|
|
60196
60241
|
"relative w-full",
|
|
60197
60242
|
orientation === "vertical" ? "flex flex-col space-y-8" : "",
|
|
60198
60243
|
className
|
|
60199
|
-
), children: orientation === "horizontal" ? /* @__PURE__ */
|
|
60200
|
-
|
|
60201
|
-
|
|
60202
|
-
|
|
60203
|
-
|
|
60204
|
-
|
|
60205
|
-
|
|
60206
|
-
|
|
60207
|
-
|
|
60208
|
-
|
|
60209
|
-
|
|
60210
|
-
|
|
60211
|
-
|
|
60212
|
-
|
|
60213
|
-
|
|
60214
|
-
|
|
60215
|
-
|
|
60216
|
-
|
|
60217
|
-
|
|
60218
|
-
|
|
60219
|
-
|
|
60220
|
-
|
|
60221
|
-
|
|
60222
|
-
|
|
60223
|
-
|
|
60224
|
-
|
|
60225
|
-
|
|
60226
|
-
|
|
60227
|
-
|
|
60228
|
-
|
|
60229
|
-
|
|
60230
|
-
|
|
60231
|
-
|
|
60232
|
-
|
|
60233
|
-
|
|
60234
|
-
|
|
60235
|
-
|
|
60236
|
-
|
|
60237
|
-
|
|
60238
|
-
|
|
60239
|
-
] }),
|
|
60244
|
+
), children: orientation === "horizontal" ? /* @__PURE__ */ jsx("div", { className: "relative w-full", children: /* @__PURE__ */ jsx("div", { className: "relative flex items-start justify-between w-full", children: steps.map((step, index2) => {
|
|
60245
|
+
const isActive2 = index2 === currentStep;
|
|
60246
|
+
const isCompleted = isStepCompleted(index2);
|
|
60247
|
+
const isAccessible = isStepAccessible(index2);
|
|
60248
|
+
const hasError = isActive2 && error42;
|
|
60249
|
+
const StepIcon = typeof step.icon === "function" ? step.icon({ isActive: isActive2, isCompleted }) : step.icon;
|
|
60250
|
+
return /* @__PURE__ */ jsxs("div", { className: "relative flex-1 flex flex-col items-center", children: [
|
|
60251
|
+
showStepTitles && /* @__PURE__ */ jsxs("div", { className: "text-center mb-3 min-h-[40px] px-2", children: [
|
|
60252
|
+
/* @__PURE__ */ jsx("p", { className: cn(
|
|
60253
|
+
"text-sm font-semibold transition-colors",
|
|
60254
|
+
isActive2 && "text-primary",
|
|
60255
|
+
isCompleted && !isActive2 && "text-primary",
|
|
60256
|
+
!isActive2 && !isCompleted && "text-muted-foreground"
|
|
60257
|
+
), children: step.title }),
|
|
60258
|
+
step.description && /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground mt-1", children: step.description })
|
|
60259
|
+
] }),
|
|
60260
|
+
/* @__PURE__ */ jsxs("div", { className: "relative flex items-center w-full", children: [
|
|
60261
|
+
index2 < steps.length - 1 && /* @__PURE__ */ jsxs(
|
|
60262
|
+
"div",
|
|
60263
|
+
{
|
|
60264
|
+
className: "absolute left-1/2 w-full h-[2px]",
|
|
60265
|
+
style: {
|
|
60266
|
+
width: "calc(100% + 24px)",
|
|
60267
|
+
marginLeft: "24px"
|
|
60268
|
+
},
|
|
60269
|
+
children: [
|
|
60270
|
+
/* @__PURE__ */ jsx("div", { className: "h-full bg-gray-200 dark:bg-gray-700" }),
|
|
60271
|
+
index2 < currentStep && /* @__PURE__ */ jsx(
|
|
60272
|
+
motion.div,
|
|
60273
|
+
{
|
|
60274
|
+
className: "absolute inset-0 bg-primary",
|
|
60275
|
+
initial: { scaleX: 0 },
|
|
60276
|
+
animate: { scaleX: 1 },
|
|
60277
|
+
transition: { duration: 0.5, delay: index2 * 0.1 },
|
|
60278
|
+
style: { transformOrigin: "left" }
|
|
60279
|
+
}
|
|
60280
|
+
)
|
|
60281
|
+
]
|
|
60282
|
+
}
|
|
60283
|
+
),
|
|
60240
60284
|
/* @__PURE__ */ jsx(
|
|
60241
60285
|
motion.div,
|
|
60242
60286
|
{
|
|
@@ -60244,7 +60288,7 @@ var FormWizardProgress = ({
|
|
|
60244
60288
|
animate: { scale: isActive2 ? 1.05 : 1 },
|
|
60245
60289
|
transition: { duration: 0.2 },
|
|
60246
60290
|
className: cn(
|
|
60247
|
-
"relative z-10 flex items-center justify-center rounded-full transition-all duration-300",
|
|
60291
|
+
"relative z-10 flex items-center justify-center rounded-full transition-all duration-300 mx-auto",
|
|
60248
60292
|
"w-12 h-12 border-2",
|
|
60249
60293
|
isActive2 && "border-primary bg-primary text-primary-foreground shadow-lg shadow-primary/20",
|
|
60250
60294
|
isCompleted && !isActive2 && "border-primary bg-primary text-primary-foreground",
|
|
@@ -60254,16 +60298,16 @@ var FormWizardProgress = ({
|
|
|
60254
60298
|
),
|
|
60255
60299
|
children: hasError ? errorStepIcon : isCompleted && !isActive2 ? completedStepIcon : isActive2 && activeStepIcon ? activeStepIcon : StepIcon ? /* @__PURE__ */ jsx("span", { className: "w-5 h-5 flex items-center justify-center", children: StepIcon }) : showStepNumbers ? /* @__PURE__ */ jsx("span", { className: "text-sm font-semibold", children: index2 + 1 }) : /* @__PURE__ */ jsx(Circle, { className: "w-4 h-4" })
|
|
60256
60300
|
}
|
|
60257
|
-
)
|
|
60258
|
-
|
|
60259
|
-
|
|
60260
|
-
|
|
60261
|
-
|
|
60262
|
-
|
|
60263
|
-
|
|
60264
|
-
] }
|
|
60265
|
-
}
|
|
60266
|
-
|
|
60301
|
+
)
|
|
60302
|
+
] }),
|
|
60303
|
+
/* @__PURE__ */ jsx("div", { className: "mt-3", children: /* @__PURE__ */ jsxs("p", { className: "text-xs text-muted-foreground font-medium", children: [
|
|
60304
|
+
"Step ",
|
|
60305
|
+
index2 + 1,
|
|
60306
|
+
" of ",
|
|
60307
|
+
steps.length
|
|
60308
|
+
] }) })
|
|
60309
|
+
] }, step.id);
|
|
60310
|
+
}) }) }) : (
|
|
60267
60311
|
// Vertical orientation
|
|
60268
60312
|
/* @__PURE__ */ jsxs("div", { className: "relative pl-12", children: [
|
|
60269
60313
|
steps.length > 1 && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
@@ -60420,7 +60464,7 @@ var FormWizardStep = ({
|
|
|
60420
60464
|
animationType = "slide",
|
|
60421
60465
|
animationDuration = 0.3
|
|
60422
60466
|
}) => {
|
|
60423
|
-
const { steps, currentStep, goToNext, goToPrevious, goToStep, updateStepData, stepData } = useFormWizard();
|
|
60467
|
+
const { steps, currentStep, goToNext, goToPrevious, goToStep, updateStepData, stepData, error: error42 } = useFormWizard();
|
|
60424
60468
|
const [direction, setDirection] = t__default.useState(0);
|
|
60425
60469
|
const previousStep = t__default.useRef(currentStep);
|
|
60426
60470
|
t__default.useEffect(() => {
|
|
@@ -60455,7 +60499,14 @@ var FormWizardStep = ({
|
|
|
60455
60499
|
ease: "easeInOut"
|
|
60456
60500
|
},
|
|
60457
60501
|
className: cn("w-full", className),
|
|
60458
|
-
|
|
60502
|
+
"data-wizard-step-content": true,
|
|
60503
|
+
children: /* @__PURE__ */ jsxs("div", { className: "space-y-4", children: [
|
|
60504
|
+
error42 && /* @__PURE__ */ jsxs(MoonUIAlertPro, { variant: "error", children: [
|
|
60505
|
+
/* @__PURE__ */ jsx(AlertCircle, { className: "h-4 w-4" }),
|
|
60506
|
+
/* @__PURE__ */ jsx(MoonUIAlertDescriptionPro, { children: error42 })
|
|
60507
|
+
] }),
|
|
60508
|
+
content
|
|
60509
|
+
] })
|
|
60459
60510
|
},
|
|
60460
60511
|
currentStep
|
|
60461
60512
|
) });
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@moontra/moonui-pro",
|
|
3
|
-
"version": "2.8.
|
|
3
|
+
"version": "2.8.2",
|
|
4
4
|
"description": "Premium React components for MoonUI - Advanced UI library with 50+ pro components including performance, interactive, and gesture components",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.mjs",
|
|
@@ -95,17 +95,76 @@ export const FormWizardProvider: React.FC<FormWizardProviderProps> = ({
|
|
|
95
95
|
|
|
96
96
|
const validateCurrentStep = useCallback(async (): Promise<boolean> => {
|
|
97
97
|
const step = steps[currentStep]
|
|
98
|
+
|
|
99
|
+
// First check HTML5 validation for required fields
|
|
100
|
+
if (typeof window !== 'undefined') {
|
|
101
|
+
const stepElement = document.querySelector('[data-wizard-step-content]')
|
|
102
|
+
if (stepElement) {
|
|
103
|
+
const requiredInputs = stepElement.querySelectorAll('input[required], select[required], textarea[required]')
|
|
104
|
+
const emptyFields: string[] = []
|
|
105
|
+
|
|
106
|
+
requiredInputs.forEach((input: Element) => {
|
|
107
|
+
const htmlInput = input as HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement
|
|
108
|
+
if (!htmlInput.value || htmlInput.value.trim() === '') {
|
|
109
|
+
const label = document.querySelector(`label[for="${htmlInput.id}"]`)
|
|
110
|
+
const fieldName = label ? (label.textContent?.replace(' *', '') || 'Field') : htmlInput.name || htmlInput.id || 'Field'
|
|
111
|
+
emptyFields.push(fieldName)
|
|
112
|
+
}
|
|
113
|
+
})
|
|
114
|
+
|
|
115
|
+
// Check for required checkboxes
|
|
116
|
+
const requiredCheckboxes = stepElement.querySelectorAll('input[type="checkbox"][required]')
|
|
117
|
+
requiredCheckboxes.forEach((checkbox: Element) => {
|
|
118
|
+
const htmlCheckbox = checkbox as HTMLInputElement
|
|
119
|
+
if (!htmlCheckbox.checked) {
|
|
120
|
+
const label = document.querySelector(`label[for="${htmlCheckbox.id}"]`)
|
|
121
|
+
const fieldName = label ? (label.textContent?.replace(' *', '') || 'Checkbox') : htmlCheckbox.name || htmlCheckbox.id || 'Checkbox'
|
|
122
|
+
emptyFields.push(fieldName)
|
|
123
|
+
}
|
|
124
|
+
})
|
|
125
|
+
|
|
126
|
+
if (emptyFields.length > 0) {
|
|
127
|
+
setError(`Please fill in the following required fields: ${emptyFields.join(', ')}`)
|
|
128
|
+
return false
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
// Then run custom validation if provided
|
|
98
134
|
if (!step.validation) return true
|
|
99
135
|
|
|
100
136
|
setIsLoading(true)
|
|
101
137
|
setError(null)
|
|
102
138
|
|
|
103
139
|
try {
|
|
104
|
-
const
|
|
105
|
-
|
|
106
|
-
|
|
140
|
+
const result = await step.validation()
|
|
141
|
+
|
|
142
|
+
// Handle boolean return
|
|
143
|
+
if (typeof result === 'boolean') {
|
|
144
|
+
if (!result) {
|
|
145
|
+
setError("Please complete all required fields before proceeding")
|
|
146
|
+
}
|
|
147
|
+
return result
|
|
107
148
|
}
|
|
108
|
-
|
|
149
|
+
|
|
150
|
+
// Handle object return {isValid: boolean, error?: string, errors?: string[]}
|
|
151
|
+
if (typeof result === 'object' && result !== null && 'isValid' in result) {
|
|
152
|
+
const validationResult = result as { isValid: boolean; error?: string; errors?: string[] }
|
|
153
|
+
if (!validationResult.isValid) {
|
|
154
|
+
if (validationResult.error) {
|
|
155
|
+
setError(validationResult.error)
|
|
156
|
+
} else if (validationResult.errors && Array.isArray(validationResult.errors)) {
|
|
157
|
+
setError(validationResult.errors.join(', '))
|
|
158
|
+
} else {
|
|
159
|
+
setError("Please complete all required fields before proceeding")
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
return validationResult.isValid
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
// Invalid return type
|
|
166
|
+
setError("Invalid validation response")
|
|
167
|
+
return false
|
|
109
168
|
} catch (err) {
|
|
110
169
|
setError(err instanceof Error ? err.message : "Validation failed")
|
|
111
170
|
return false
|
|
@@ -41,31 +41,7 @@ export const FormWizardProgress: React.FC<FormWizardProgressProps> = ({
|
|
|
41
41
|
)}>
|
|
42
42
|
{orientation === 'horizontal' ? (
|
|
43
43
|
<div className="relative w-full">
|
|
44
|
-
{/*
|
|
45
|
-
<div
|
|
46
|
-
className="absolute left-6 right-6 h-[2px] bg-gray-200 dark:bg-gray-700"
|
|
47
|
-
style={{
|
|
48
|
-
top: showStepTitles ? '80px' : '24px'
|
|
49
|
-
}}
|
|
50
|
-
/>
|
|
51
|
-
|
|
52
|
-
{/* Progress Line Fill */}
|
|
53
|
-
<motion.div
|
|
54
|
-
className="absolute left-6 h-[2px] bg-primary"
|
|
55
|
-
style={{
|
|
56
|
-
top: showStepTitles ? '80px' : '24px',
|
|
57
|
-
right: `${100 - ((currentStep / (steps.length - 1)) * 100)}%`
|
|
58
|
-
}}
|
|
59
|
-
initial={{ right: '100%' }}
|
|
60
|
-
animate={{
|
|
61
|
-
right: steps.length > 1
|
|
62
|
-
? `${100 - ((currentStep / (steps.length - 1)) * 100)}%`
|
|
63
|
-
: '100%'
|
|
64
|
-
}}
|
|
65
|
-
transition={{ duration: 0.5, ease: "easeInOut" }}
|
|
66
|
-
/>
|
|
67
|
-
|
|
68
|
-
{/* Steps Container */}
|
|
44
|
+
{/* Steps Container with connecting lines */}
|
|
69
45
|
<div className="relative flex items-start justify-between w-full">
|
|
70
46
|
{steps.map((step, index) => {
|
|
71
47
|
const isActive = index === currentStep
|
|
@@ -78,7 +54,7 @@ export const FormWizardProgress: React.FC<FormWizardProgressProps> = ({
|
|
|
78
54
|
: step.icon
|
|
79
55
|
|
|
80
56
|
return (
|
|
81
|
-
<div key={step.id} className="relative flex flex-col items-center">
|
|
57
|
+
<div key={step.id} className="relative flex-1 flex flex-col items-center">
|
|
82
58
|
{/* Step Title & Description - Above the circle */}
|
|
83
59
|
{showStepTitles && (
|
|
84
60
|
<div className="text-center mb-3 min-h-[40px] px-2">
|
|
@@ -98,35 +74,60 @@ export const FormWizardProgress: React.FC<FormWizardProgressProps> = ({
|
|
|
98
74
|
</div>
|
|
99
75
|
)}
|
|
100
76
|
|
|
101
|
-
{/* Step Circle */}
|
|
102
|
-
<
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
<span className="w-5 h-5 flex items-center justify-center">{StepIcon}</span>
|
|
124
|
-
) : showStepNumbers ? (
|
|
125
|
-
<span className="text-sm font-semibold">{index + 1}</span>
|
|
126
|
-
) : (
|
|
127
|
-
<Circle className="w-4 h-4" />
|
|
77
|
+
{/* Step Circle Container with line */}
|
|
78
|
+
<div className="relative flex items-center w-full">
|
|
79
|
+
{/* Connecting Line - Positioned after each circle except the last */}
|
|
80
|
+
{index < steps.length - 1 && (
|
|
81
|
+
<div
|
|
82
|
+
className="absolute left-1/2 w-full h-[2px]"
|
|
83
|
+
style={{
|
|
84
|
+
width: 'calc(100% + 24px)',
|
|
85
|
+
marginLeft: '24px'
|
|
86
|
+
}}
|
|
87
|
+
>
|
|
88
|
+
<div className="h-full bg-gray-200 dark:bg-gray-700" />
|
|
89
|
+
{index < currentStep && (
|
|
90
|
+
<motion.div
|
|
91
|
+
className="absolute inset-0 bg-primary"
|
|
92
|
+
initial={{ scaleX: 0 }}
|
|
93
|
+
animate={{ scaleX: 1 }}
|
|
94
|
+
transition={{ duration: 0.5, delay: index * 0.1 }}
|
|
95
|
+
style={{ transformOrigin: 'left' }}
|
|
96
|
+
/>
|
|
97
|
+
)}
|
|
98
|
+
</div>
|
|
128
99
|
)}
|
|
129
|
-
|
|
100
|
+
|
|
101
|
+
{/* Step Circle */}
|
|
102
|
+
<motion.div
|
|
103
|
+
initial={{ scale: 0.8 }}
|
|
104
|
+
animate={{ scale: isActive ? 1.05 : 1 }}
|
|
105
|
+
transition={{ duration: 0.2 }}
|
|
106
|
+
className={cn(
|
|
107
|
+
"relative z-10 flex items-center justify-center rounded-full transition-all duration-300 mx-auto",
|
|
108
|
+
"w-12 h-12 border-2",
|
|
109
|
+
isActive && "border-primary bg-primary text-primary-foreground shadow-lg shadow-primary/20",
|
|
110
|
+
isCompleted && !isActive && "border-primary bg-primary text-primary-foreground",
|
|
111
|
+
!isActive && !isCompleted && isAccessible && "border-gray-300 bg-background text-gray-500 hover:border-gray-400 dark:border-gray-600 dark:text-gray-400",
|
|
112
|
+
!isAccessible && "border-gray-200 bg-gray-50 text-gray-400 cursor-not-allowed dark:border-gray-700 dark:bg-gray-900 dark:text-gray-600",
|
|
113
|
+
hasError && "border-destructive bg-destructive text-destructive-foreground"
|
|
114
|
+
)}
|
|
115
|
+
>
|
|
116
|
+
{hasError ? (
|
|
117
|
+
errorStepIcon
|
|
118
|
+
) : isCompleted && !isActive ? (
|
|
119
|
+
completedStepIcon
|
|
120
|
+
) : isActive && activeStepIcon ? (
|
|
121
|
+
activeStepIcon
|
|
122
|
+
) : StepIcon ? (
|
|
123
|
+
<span className="w-5 h-5 flex items-center justify-center">{StepIcon}</span>
|
|
124
|
+
) : showStepNumbers ? (
|
|
125
|
+
<span className="text-sm font-semibold">{index + 1}</span>
|
|
126
|
+
) : (
|
|
127
|
+
<Circle className="w-4 h-4" />
|
|
128
|
+
)}
|
|
129
|
+
</motion.div>
|
|
130
|
+
</div>
|
|
130
131
|
|
|
131
132
|
{/* Step Label Below Circle */}
|
|
132
133
|
<div className="mt-3">
|
|
@@ -5,6 +5,8 @@ import { motion, AnimatePresence } from "framer-motion"
|
|
|
5
5
|
import { cn } from "../../lib/utils"
|
|
6
6
|
import { useFormWizard } from "./form-wizard-context"
|
|
7
7
|
import { FormWizardProps } from "./types"
|
|
8
|
+
import { Alert, AlertDescription } from "../ui/alert"
|
|
9
|
+
import { AlertCircle } from "lucide-react"
|
|
8
10
|
|
|
9
11
|
interface FormWizardStepProps {
|
|
10
12
|
className?: string
|
|
@@ -49,7 +51,7 @@ export const FormWizardStep: React.FC<FormWizardStepProps> = ({
|
|
|
49
51
|
animationType = 'slide',
|
|
50
52
|
animationDuration = 0.3
|
|
51
53
|
}) => {
|
|
52
|
-
const { steps, currentStep, goToNext, goToPrevious, goToStep, updateStepData, stepData } = useFormWizard()
|
|
54
|
+
const { steps, currentStep, goToNext, goToPrevious, goToStep, updateStepData, stepData, error } = useFormWizard()
|
|
53
55
|
const [direction, setDirection] = React.useState(0)
|
|
54
56
|
const previousStep = React.useRef(currentStep)
|
|
55
57
|
|
|
@@ -92,8 +94,17 @@ export const FormWizardStep: React.FC<FormWizardStepProps> = ({
|
|
|
92
94
|
ease: "easeInOut"
|
|
93
95
|
}}
|
|
94
96
|
className={cn("w-full", className)}
|
|
97
|
+
data-wizard-step-content
|
|
95
98
|
>
|
|
96
|
-
|
|
99
|
+
<div className="space-y-4">
|
|
100
|
+
{error && (
|
|
101
|
+
<Alert variant="error">
|
|
102
|
+
<AlertCircle className="h-4 w-4" />
|
|
103
|
+
<AlertDescription>{error}</AlertDescription>
|
|
104
|
+
</Alert>
|
|
105
|
+
)}
|
|
106
|
+
{content}
|
|
107
|
+
</div>
|
|
97
108
|
</motion.div>
|
|
98
109
|
</AnimatePresence>
|
|
99
110
|
)
|