@moontra/moonui-pro 2.8.2 → 2.8.3
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.d.ts +1 -43
- package/dist/index.mjs +2179 -13827
- package/package.json +1 -1
- package/src/components/index.ts +0 -2
- package/src/components/multi-step-form/index.tsx +0 -223
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@moontra/moonui-pro",
|
|
3
|
-
"version": "2.8.
|
|
3
|
+
"version": "2.8.3",
|
|
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",
|
package/src/components/index.ts
CHANGED
|
@@ -1,223 +0,0 @@
|
|
|
1
|
-
"use client"
|
|
2
|
-
|
|
3
|
-
import React from "react"
|
|
4
|
-
import { useForm, FormProvider, UseFormReturn, FieldValues, DefaultValues } from "react-hook-form"
|
|
5
|
-
import { zodResolver } from "@hookform/resolvers/zod"
|
|
6
|
-
import { z } from "zod"
|
|
7
|
-
import { MoonUIFormWizardPro, FormWizardProps, WizardStep } from "../form-wizard"
|
|
8
|
-
import { Alert, AlertDescription } from "../ui/alert"
|
|
9
|
-
import { AlertCircle } from "lucide-react"
|
|
10
|
-
|
|
11
|
-
export interface MultiStepFormField {
|
|
12
|
-
name: string
|
|
13
|
-
label: string
|
|
14
|
-
type: 'text' | 'email' | 'password' | 'number' | 'tel' | 'url' | 'textarea' | 'select' | 'checkbox' | 'radio' | 'switch' | 'file' | 'date' | 'time' | 'datetime'
|
|
15
|
-
placeholder?: string
|
|
16
|
-
description?: string
|
|
17
|
-
required?: boolean
|
|
18
|
-
validation?: z.ZodSchema<any>
|
|
19
|
-
options?: Array<{ value: string; label: string }>
|
|
20
|
-
defaultValue?: any
|
|
21
|
-
disabled?: boolean
|
|
22
|
-
autoComplete?: string
|
|
23
|
-
min?: number | string
|
|
24
|
-
max?: number | string
|
|
25
|
-
step?: number | string
|
|
26
|
-
pattern?: string
|
|
27
|
-
multiple?: boolean
|
|
28
|
-
accept?: string
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
export interface MultiStepFormStep extends Omit<WizardStep, 'content' | 'validation'> {
|
|
32
|
-
fields: MultiStepFormField[]
|
|
33
|
-
schema?: z.ZodSchema<any>
|
|
34
|
-
submitLabel?: string
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
export interface MultiStepFormProps<TFormData extends FieldValues = FieldValues> extends Omit<FormWizardProps, 'steps'> {
|
|
38
|
-
steps: MultiStepFormStep[]
|
|
39
|
-
onSubmit: (data: TFormData) => void | Promise<void>
|
|
40
|
-
defaultValues?: DefaultValues<TFormData>
|
|
41
|
-
showErrorSummary?: boolean
|
|
42
|
-
fieldClassName?: string
|
|
43
|
-
labelClassName?: string
|
|
44
|
-
errorClassName?: string
|
|
45
|
-
descriptionClassName?: string
|
|
46
|
-
renderField?: (field: MultiStepFormField, form: UseFormReturn<TFormData>) => React.ReactNode
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
function createStepSchema(fields: MultiStepFormField[]): z.ZodSchema<any> {
|
|
50
|
-
const shape: Record<string, z.ZodSchema<any>> = {}
|
|
51
|
-
|
|
52
|
-
fields.forEach(field => {
|
|
53
|
-
if (field.validation) {
|
|
54
|
-
shape[field.name] = field.validation
|
|
55
|
-
} else {
|
|
56
|
-
let schema: z.ZodSchema<any> = z.any()
|
|
57
|
-
|
|
58
|
-
switch (field.type) {
|
|
59
|
-
case 'email':
|
|
60
|
-
schema = z.string().email('Invalid email address')
|
|
61
|
-
break
|
|
62
|
-
case 'number':
|
|
63
|
-
schema = z.number()
|
|
64
|
-
if (field.min !== undefined) schema = (schema as z.ZodNumber).min(Number(field.min))
|
|
65
|
-
if (field.max !== undefined) schema = (schema as z.ZodNumber).max(Number(field.max))
|
|
66
|
-
break
|
|
67
|
-
case 'url':
|
|
68
|
-
schema = z.string().url('Invalid URL')
|
|
69
|
-
break
|
|
70
|
-
case 'tel':
|
|
71
|
-
schema = z.string().regex(/^\+?[1-9]\d{1,14}$/, 'Invalid phone number')
|
|
72
|
-
break
|
|
73
|
-
case 'checkbox':
|
|
74
|
-
case 'switch':
|
|
75
|
-
schema = z.boolean()
|
|
76
|
-
break
|
|
77
|
-
default:
|
|
78
|
-
schema = z.string()
|
|
79
|
-
if (field.min !== undefined) schema = (schema as z.ZodString).min(Number(field.min))
|
|
80
|
-
if (field.max !== undefined) schema = (schema as z.ZodString).max(Number(field.max))
|
|
81
|
-
if (field.pattern) schema = (schema as z.ZodString).regex(new RegExp(field.pattern))
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
if (!field.required) {
|
|
85
|
-
schema = schema.optional()
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
shape[field.name] = schema
|
|
89
|
-
}
|
|
90
|
-
})
|
|
91
|
-
|
|
92
|
-
return z.object(shape)
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
export function MoonUIMultiStepFormPro<TFormData extends FieldValues = FieldValues>({
|
|
96
|
-
steps,
|
|
97
|
-
onSubmit,
|
|
98
|
-
defaultValues,
|
|
99
|
-
showErrorSummary = true,
|
|
100
|
-
fieldClassName,
|
|
101
|
-
labelClassName,
|
|
102
|
-
errorClassName,
|
|
103
|
-
descriptionClassName,
|
|
104
|
-
renderField,
|
|
105
|
-
...wizardProps
|
|
106
|
-
}: MultiStepFormProps<TFormData>) {
|
|
107
|
-
// Create combined schema from all steps
|
|
108
|
-
const combinedSchema = React.useMemo(() => {
|
|
109
|
-
const shape: Record<string, z.ZodSchema<any>> = {}
|
|
110
|
-
|
|
111
|
-
steps.forEach(step => {
|
|
112
|
-
const stepSchema = step.schema || createStepSchema(step.fields)
|
|
113
|
-
if (stepSchema instanceof z.ZodObject) {
|
|
114
|
-
Object.assign(shape, stepSchema.shape)
|
|
115
|
-
}
|
|
116
|
-
})
|
|
117
|
-
|
|
118
|
-
return z.object(shape)
|
|
119
|
-
}, [steps])
|
|
120
|
-
|
|
121
|
-
const form = useForm<TFormData>({
|
|
122
|
-
resolver: zodResolver(combinedSchema) as any,
|
|
123
|
-
defaultValues,
|
|
124
|
-
mode: 'onChange'
|
|
125
|
-
})
|
|
126
|
-
|
|
127
|
-
const wizardSteps: WizardStep[] = steps.map((step, stepIndex) => ({
|
|
128
|
-
...step,
|
|
129
|
-
validation: async () => {
|
|
130
|
-
// Validate only the fields in the current step
|
|
131
|
-
const currentStepFields = step.fields.map(f => f.name)
|
|
132
|
-
const result = await form.trigger(currentStepFields as any)
|
|
133
|
-
return result
|
|
134
|
-
},
|
|
135
|
-
content: ({ updateStepData }) => {
|
|
136
|
-
const errors = form.formState.errors
|
|
137
|
-
const stepErrors = step.fields
|
|
138
|
-
.map(field => errors[field.name])
|
|
139
|
-
.filter(Boolean)
|
|
140
|
-
|
|
141
|
-
return (
|
|
142
|
-
<FormProvider {...form}>
|
|
143
|
-
<form className="space-y-6">
|
|
144
|
-
{showErrorSummary && stepErrors.length > 0 && (
|
|
145
|
-
<Alert variant="error">
|
|
146
|
-
<AlertCircle className="h-4 w-4" />
|
|
147
|
-
<AlertDescription>
|
|
148
|
-
Please fix the errors below before proceeding.
|
|
149
|
-
</AlertDescription>
|
|
150
|
-
</Alert>
|
|
151
|
-
)}
|
|
152
|
-
|
|
153
|
-
{step.fields.map(field => {
|
|
154
|
-
if (renderField) {
|
|
155
|
-
return <div key={field.name}>{renderField(field, form)}</div>
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
// Default field rendering
|
|
159
|
-
return (
|
|
160
|
-
<div key={field.name} className={fieldClassName}>
|
|
161
|
-
<label
|
|
162
|
-
htmlFor={field.name}
|
|
163
|
-
className={cn(
|
|
164
|
-
"block text-sm font-medium",
|
|
165
|
-
labelClassName
|
|
166
|
-
)}
|
|
167
|
-
>
|
|
168
|
-
{field.label}
|
|
169
|
-
{field.required && <span className="text-destructive ml-1">*</span>}
|
|
170
|
-
</label>
|
|
171
|
-
|
|
172
|
-
{field.description && (
|
|
173
|
-
<p className={cn("text-sm text-muted-foreground mt-1", descriptionClassName)}>
|
|
174
|
-
{field.description}
|
|
175
|
-
</p>
|
|
176
|
-
)}
|
|
177
|
-
|
|
178
|
-
<div className="mt-2">
|
|
179
|
-
{/* Field rendering would go here - simplified for brevity */}
|
|
180
|
-
<input
|
|
181
|
-
{...form.register(field.name as any)}
|
|
182
|
-
id={field.name}
|
|
183
|
-
type={field.type}
|
|
184
|
-
placeholder={field.placeholder}
|
|
185
|
-
disabled={field.disabled}
|
|
186
|
-
className="w-full px-3 py-2 border rounded-md"
|
|
187
|
-
/>
|
|
188
|
-
</div>
|
|
189
|
-
|
|
190
|
-
{errors[field.name] && (
|
|
191
|
-
<p className={cn("text-sm text-destructive mt-1", errorClassName)}>
|
|
192
|
-
{errors[field.name]?.message as string}
|
|
193
|
-
</p>
|
|
194
|
-
)}
|
|
195
|
-
</div>
|
|
196
|
-
)
|
|
197
|
-
})}
|
|
198
|
-
</form>
|
|
199
|
-
</FormProvider>
|
|
200
|
-
)
|
|
201
|
-
}
|
|
202
|
-
}))
|
|
203
|
-
|
|
204
|
-
const handleComplete = async (stepData: Record<string, any>) => {
|
|
205
|
-
const isValid = await form.trigger()
|
|
206
|
-
if (isValid) {
|
|
207
|
-
await onSubmit(form.getValues())
|
|
208
|
-
}
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
return (
|
|
212
|
-
<MoonUIFormWizardPro
|
|
213
|
-
{...wizardProps}
|
|
214
|
-
steps={wizardSteps}
|
|
215
|
-
onComplete={handleComplete}
|
|
216
|
-
/>
|
|
217
|
-
)
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
// Utility function for better imports
|
|
221
|
-
function cn(...classes: (string | undefined | false)[]) {
|
|
222
|
-
return classes.filter(Boolean).join(' ')
|
|
223
|
-
}
|