22 lines
8.0 KiB
JSON
22 lines
8.0 KiB
JSON
{
|
|
"name": "StepperForm",
|
|
"type": "registry:example",
|
|
"dependencies": [],
|
|
"registryDependencies": [
|
|
"button",
|
|
"form",
|
|
"input",
|
|
"select",
|
|
"stepper",
|
|
"toast"
|
|
],
|
|
"files": [
|
|
{
|
|
"path": "example/StepperForm.vue",
|
|
"content": "<script setup lang=\"ts\">\nimport { Button } from '@/registry/default/ui/button'\nimport { Form, FormControl, FormField, FormItem, FormLabel, FormMessage } from '@/registry/default/ui/form'\nimport { Input } from '@/registry/default/ui/input'\nimport {\n Select,\n SelectContent,\n SelectGroup,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from '@/registry/default/ui/select'\nimport { Stepper, StepperDescription, StepperItem, StepperSeparator, StepperTitle, StepperTrigger } from '@/registry/default/ui/stepper'\nimport { toast } from '@/registry/default/ui/toast'\nimport { toTypedSchema } from '@vee-validate/zod'\nimport { Check, Circle, Dot } from 'lucide-vue-next'\nimport { h, ref } from 'vue'\nimport * as z from 'zod'\n\nconst formSchema = [\n z.object({\n fullName: z.string(),\n email: z.string().email(),\n }),\n z.object({\n password: z.string().min(2).max(50),\n confirmPassword: z.string(),\n }).refine(\n (values) => {\n return values.password === values.confirmPassword\n },\n {\n message: 'Passwords must match!',\n path: ['confirmPassword'],\n },\n ),\n z.object({\n favoriteDrink: z.union([z.literal('coffee'), z.literal('tea'), z.literal('soda')]),\n }),\n]\n\nconst stepIndex = ref(1)\nconst steps = [\n {\n step: 1,\n title: 'Your details',\n description: 'Provide your name and email',\n },\n {\n step: 2,\n title: 'Your password',\n description: 'Choose a password',\n },\n {\n step: 3,\n title: 'Your Favorite Drink',\n description: 'Choose a drink',\n },\n]\n\nfunction onSubmit(values: any) {\n toast({\n title: 'You submitted the following values:',\n description: h('pre', { class: 'mt-2 w-[340px] rounded-md bg-slate-950 p-4' }, h('code', { class: 'text-white' }, JSON.stringify(values, null, 2))),\n })\n}\n</script>\n\n<template>\n <Form\n v-slot=\"{ meta, values, validate }\"\n as=\"\" keep-values :validation-schema=\"toTypedSchema(formSchema[stepIndex - 1])\"\n >\n <Stepper v-slot=\"{ isNextDisabled, isPrevDisabled, nextStep, prevStep }\" v-model=\"stepIndex\" class=\"block w-full\">\n <form\n @submit=\"(e) => {\n e.preventDefault()\n validate()\n\n if (stepIndex === steps.length && meta.valid) {\n onSubmit(values)\n }\n }\"\n >\n <div class=\"flex w-full flex-start gap-2\">\n <StepperItem\n v-for=\"step in steps\"\n :key=\"step.step\"\n v-slot=\"{ state }\"\n class=\"relative flex w-full flex-col items-center justify-center\"\n :step=\"step.step\"\n >\n <StepperSeparator\n v-if=\"step.step !== steps[steps.length - 1].step\"\n class=\"absolute left-[calc(50%+20px)] right-[calc(-50%+10px)] top-5 block h-0.5 shrink-0 rounded-full bg-muted group-data-[state=completed]:bg-primary\"\n />\n\n <StepperTrigger as-child>\n <Button\n :variant=\"state === 'completed' || state === 'active' ? 'default' : 'outline'\"\n size=\"icon\"\n class=\"z-10 rounded-full shrink-0\"\n :class=\"[state === 'active' && 'ring-2 ring-ring ring-offset-2 ring-offset-background']\"\n :disabled=\"state !== 'completed' && !meta.valid\"\n >\n <Check v-if=\"state === 'completed'\" class=\"size-5\" />\n <Circle v-if=\"state === 'active'\" />\n <Dot v-if=\"state === 'inactive'\" />\n </Button>\n </StepperTrigger>\n\n <div class=\"mt-5 flex flex-col items-center text-center\">\n <StepperTitle\n :class=\"[state === 'active' && 'text-primary']\"\n class=\"text-sm font-semibold transition lg:text-base\"\n >\n {{ step.title }}\n </StepperTitle>\n <StepperDescription\n :class=\"[state === 'active' && 'text-primary']\"\n class=\"sr-only text-xs text-muted-foreground transition md:not-sr-only lg:text-sm\"\n >\n {{ step.description }}\n </StepperDescription>\n </div>\n </StepperItem>\n </div>\n\n <div class=\"flex flex-col gap-4 mt-4\">\n <template v-if=\"stepIndex === 1\">\n <FormField v-slot=\"{ componentField }\" name=\"fullName\">\n <FormItem>\n <FormLabel>Full Name</FormLabel>\n <FormControl>\n <Input type=\"text\" v-bind=\"componentField\" />\n </FormControl>\n <FormMessage />\n </FormItem>\n </FormField>\n\n <FormField v-slot=\"{ componentField }\" name=\"email\">\n <FormItem>\n <FormLabel>Email</FormLabel>\n <FormControl>\n <Input type=\"email \" v-bind=\"componentField\" />\n </FormControl>\n <FormMessage />\n </FormItem>\n </FormField>\n </template>\n\n <template v-if=\"stepIndex === 2\">\n <FormField v-slot=\"{ componentField }\" name=\"password\">\n <FormItem>\n <FormLabel>Password</FormLabel>\n <FormControl>\n <Input type=\"password\" v-bind=\"componentField\" />\n </FormControl>\n <FormMessage />\n </FormItem>\n </FormField>\n\n <FormField v-slot=\"{ componentField }\" name=\"confirmPassword\">\n <FormItem>\n <FormLabel>Confirm Password</FormLabel>\n <FormControl>\n <Input type=\"password\" v-bind=\"componentField\" />\n </FormControl>\n <FormMessage />\n </FormItem>\n </FormField>\n </template>\n\n <template v-if=\"stepIndex === 3\">\n <FormField v-slot=\"{ componentField }\" name=\"favoriteDrink\">\n <FormItem>\n <FormLabel>Drink</FormLabel>\n\n <Select v-bind=\"componentField\">\n <FormControl>\n <SelectTrigger>\n <SelectValue placeholder=\"Select a drink\" />\n </SelectTrigger>\n </FormControl>\n <SelectContent>\n <SelectGroup>\n <SelectItem value=\"coffee\">\n Coffe\n </SelectItem>\n <SelectItem value=\"tea\">\n Tea\n </SelectItem>\n <SelectItem value=\"soda\">\n Soda\n </SelectItem>\n </SelectGroup>\n </SelectContent>\n </Select>\n <FormMessage />\n </FormItem>\n </FormField>\n </template>\n </div>\n\n <div class=\"flex items-center justify-between mt-4\">\n <Button :disabled=\"isPrevDisabled\" variant=\"outline\" size=\"sm\" @click=\"prevStep()\">\n Back\n </Button>\n <div class=\"flex items-center gap-3\">\n <Button v-if=\"stepIndex !== 3\" :type=\"meta.valid ? 'button' : 'submit'\" :disabled=\"isNextDisabled\" size=\"sm\" @click=\"meta.valid && nextStep()\">\n Next\n </Button>\n <Button\n v-if=\"stepIndex === 3\" size=\"sm\" type=\"submit\"\n >\n Submit\n </Button>\n </div>\n </div>\n </form>\n </Stepper>\n </Form>\n</template>\n",
|
|
"type": "registry:example",
|
|
"target": ""
|
|
}
|
|
]
|
|
}
|