Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add vee-validate #85

Merged
merged 20 commits into from
Oct 6, 2023
Merged
Show file tree
Hide file tree
Changes from 14 commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
d4bb455
feat: add `vee-validate`
sadeghbarati Sep 25, 2023
55cf147
chore: update
sadeghbarati Sep 25, 2023
5ee0a46
chore: update `AccountForm` example
sadeghbarati Sep 25, 2023
72382e9
refactor: use radix-vue `Slot` component
sadeghbarati Sep 26, 2023
8c61c94
chore: refresh lockfile
sadeghbarati Sep 26, 2023
72ef22d
Merge branch 'dev' into feat/vee-validate
sadeghbarati Sep 27, 2023
6be33b1
chore: update `ProfileForm.vue` and `AccountForm`
sadeghbarati Sep 27, 2023
1dcb74f
chore: update `AppearanceForm.vue`
sadeghbarati Sep 27, 2023
76be3fb
Merge branch 'dev' of https://github.com/radix-vue/shadcn-vue into fe…
sadeghbarati Sep 28, 2023
23a3d2a
refactor: update
sadeghbarati Sep 28, 2023
03be864
fix: class-name -> class
sadeghbarati Sep 29, 2023
9881d9d
Merge branch 'dev' of https://github.com/radix-vue/shadcn-vue into fe…
sadeghbarati Oct 1, 2023
157b1f0
refactor: simplify validation for `Command` component
sadeghbarati Oct 1, 2023
ec7382b
fix: v-bind="field" -> v-bind="componentField"
sadeghbarati Oct 1, 2023
68337c5
fix: useAttrs to prevent class duplication
sadeghbarati Oct 2, 2023
854cb8f
docs: add `form.md`
sadeghbarati Oct 2, 2023
5868374
docs: add form example for `checkbox` `input` and `datepicker`
sadeghbarati Oct 2, 2023
fd0087b
docs: add `combobox`, `datepicker`, `radio-group`, `select`, `switch`…
sadeghbarati Oct 2, 2023
fec53d3
Merge branch 'dev' of https://github.com/radix-vue/shadcn-vue into fe…
sadeghbarati Oct 2, 2023
2cca677
chore: typo, update `zod`, `vite`, and `@vitejs/plugin-vue`
sadeghbarati Oct 5, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .eslintrc.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,6 @@ module.exports = {
'no-console': 'warn',
'no-tabs': 'off',
'no-invalid-character': 'off',
'import/first': 'off',
},
}
14 changes: 8 additions & 6 deletions apps/www/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,18 @@
"dependencies": {
"@morev/vue-transitions": "^2.3.6",
"@radix-icons/vue": "^1.0.0",
"@tanstack/vue-table": "^8.9.9",
"@tanstack/vue-table": "^8.10.3",
"@unovis/ts": "^1.2.1",
"@unovis/vue": "1.3.0-alpha.3",
"@vee-validate/zod": "^4.11.7",
"@vueuse/core": "^10.4.1",
"class-variance-authority": "^0.7.0",
"clsx": "^2.0.0",
"date-fns": "^2.30.0",
"lucide-vue-next": "^0.276.0",
"tailwindcss-animate": "^1.0.7",
"v-calendar": "^3.0.3",
"v-calendar": "^3.1.0",
"vee-validate": "4.11.7",
"vue": "^3.3.4",
"vue-wrap-balancer": "^1.1.3",
"zod": "^3.22.2"
Expand All @@ -39,17 +41,17 @@
"@vitejs/plugin-vue-jsx": "^3.0.2",
"@vue/compiler-core": "^3.3.4",
"@vue/compiler-dom": "^3.3.4",
"autoprefixer": "^10.4.15",
"autoprefixer": "^10.4.16",
"lodash.template": "^4.5.0",
"radix-vue": "^0.4.1",
"rimraf": "^5.0.1",
"tailwind-merge": "^1.14.0",
"tailwindcss": "^3.3.3",
"tsx": "^3.12.10",
"tsx": "^3.13.0",
"typescript": "^5.2.2",
"unplugin-icons": "^0.17.0",
"vite": "^4.4.9",
"vitepress": "^1.0.0-rc.13",
"vue-tsc": "^1.8.11"
"vitepress": "^1.0.0-rc.20",
"vue-tsc": "^1.8.15"
}
}
203 changes: 112 additions & 91 deletions apps/www/src/examples/forms/components/AccountForm.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,23 @@
import { ref } from 'vue'
import * as z from 'zod'
import { format } from 'date-fns'
import { toTypedSchema } from '@vee-validate/zod'
import { configure } from 'vee-validate'
import { Check, ChevronsUpDown } from 'lucide-vue-next'
import { cn } from '@/lib/utils'

import RadixIconsCalendar from '~icons/radix-icons/calendar'

import { Form, FormControl, FormDescription, FormField, FormItem, FormLabel, FormMessage } from '@/lib/registry/default/ui/form'
import { Input } from '@/lib/registry/new-york/ui/input'
import { Label } from '@/lib/registry/new-york/ui/label'
import { Separator } from '@/lib/registry/new-york/ui/separator'
import {
Select,
SelectContent,
SelectGroup,
SelectItem,
SelectTrigger,
SelectValue,
} from '@/lib/registry/new-york/ui/select'
Command,
CommandEmpty,
CommandGroup,
CommandInput,
CommandItem,
} from '@/lib/registry/default/ui/command'
import { Button } from '@/lib/registry/new-york/ui/button'
import {
Popover,
Expand All @@ -25,11 +27,7 @@ import {
} from '@/lib/registry/default/ui/popover'
import { Calendar } from '@/lib/registry/new-york/ui/calendar'

const accountForm = ref({
name: '',
dob: null,
language: '',
})
const open = ref(false)

const languages = [
{ label: 'English', value: 'en' },
Expand All @@ -43,7 +41,7 @@ const languages = [
{ label: 'Chinese', value: 'zh' },
] as const

const accountFormSchema = z.object({
const accountFormSchema = toTypedSchema(z.object({
name: z
.string()
.min(2, {
Expand All @@ -58,20 +56,14 @@ const accountFormSchema = z.object({
language: z.string().nonempty({
message: 'Please select a language.',
}),
})
}))

type AccountFormValues = z.infer<typeof accountFormSchema>
const errors = ref<z.ZodFormattedError<AccountFormValues> | null>(null)
const filterFunction = (list: typeof languages, search: string) => list.filter(i => i.value.toLowerCase().includes(search.toLowerCase()))

async function handleSubmit() {
const result = accountFormSchema.safeParse(accountForm.value)
if (!result.success) {
errors.value = result.error.format()
console.log(errors.value)
return
}

console.log('Form submitted!', accountForm.value)
// https://github.com/logaretm/vee-validate/issues/3521
// https://github.com/logaretm/vee-validate/discussions/3571
async function onSubmit(values: any) {
console.log('Form submitted!', values)
}
</script>

Expand All @@ -85,74 +77,103 @@ async function handleSubmit() {
</p>
</div>
<Separator />
<form class="space-y-8" @submit.prevent="handleSubmit">
<div class="grid gap-2">
<Label for="name" :class="cn('text-sm', errors?.name && 'text-destructive')">
Name
</Label>
<Input id="name" v-model="accountForm.name" placeholder="Your name" />
<span class="text-muted-foreground text-sm">
This is the name that will be displayed on your profile and in emails.
</span>
<div v-if="errors?.name" class="text-sm text-destructive">
<span v-for="error in errors.name._errors" :key="error">{{ error }}</span>
</div>
</div>
<div class="grid gap-2">
<Label for="dob" :class="cn('text-sm', errors?.dob && 'text-destructive')">
Date of Birth
</Label>
<Popover>
<PopoverTrigger as-child>
<Button
variant="outline"
:class="cn(
'w-[280px] pl-3 text-left font-normal',
!accountForm.dob && 'text-muted-foreground',
)"
>
<span>{{ accountForm.dob ? format(accountForm.dob, "PPP") : "Pick a date" }}</span>
<RadixIconsCalendar class="ml-auto h-4 w-4 opacity-50" />
</Button>
</PopoverTrigger>
<PopoverContent class="p-0">
<Calendar v-model="accountForm.dob" />
</PopoverContent>
</Popover>
<span class="text-muted-foreground text-sm">
Your date of birth is used to calculate your age.
</span>
<div v-if="errors?.dob" class="text-sm text-destructive">
<span v-for="error in errors.dob._errors" :key="error">{{ error }}</span>
</div>
</div>
<div class="grid gap-2">
<Label for="language" :class="cn('text-sm', errors?.language && 'text-destructive')">
Language
</Label>
<Select id="language" v-model="accountForm.language">
<SelectTrigger class="w-[200px]">
<SelectValue placeholder="Select a language" />
</SelectTrigger>
<SelectContent>
<SelectGroup>
<SelectItem v-for="language in languages" :key="language.value" :value="language.value">
{{ language.label }}
</SelectItem>
</SelectGroup>
</SelectContent>
</Select>
<span class="text-muted-foreground text-sm">
This is the language that will be used in the dashboard.
</span>
<div v-if="errors?.language" class="text-sm text-destructive">
<span v-for="error in errors.language._errors" :key="error">{{ error }}</span>
</div>
</div>
<Form :validation-schema="accountFormSchema" class="space-y-8" @submit="onSubmit">
<FormField v-slot="{ componentField }" name="name">
<FormItem>
<FormLabel>Name</FormLabel>
<FormControl>
<Input type="text" placeholder="Your name" v-bind="componentField" />
</FormControl>
<FormDescription>
This is the name that will be displayed on your profile and in emails.
</FormDescription>
<FormMessage />
</FormItem>
</FormField>

<FormField v-slot="{ componentField, value }" name="dob">
<FormItem>
<FormLabel>Date of birth</FormLabel>
<Popover>
<PopoverTrigger as-child>
<FormControl>
<Button
variant="outline" :class="cn(
'w-[280px] pl-3 text-left font-normal',
!value && 'text-muted-foreground',
)"
>
<span>{{ value ? format(value, "PPP") : "Pick a date" }}</span>
<RadixIconsCalendar class="ml-auto h-4 w-4 opacity-50" />
</Button>
</FormControl>
</PopoverTrigger>
<PopoverContent class="p-0">
<Calendar v-bind="componentField" />
</PopoverContent>
</Popover>
<FormDescription>
Your date of birth is used to calculate your age.
</FormDescription>
<FormMessage />
</FormItem>
</FormField>

<FormField v-slot="{ value, componentField }" name="language">
<FormItem>
<FormLabel>Language</FormLabel>

<Popover v-model:open="open">
<PopoverTrigger as-child>
<FormControl>
<Button
variant="outline" role="combobox" :aria-expanded="open" :class="cn(
'w-[200px] justify-between',
!value && 'text-muted-foreground',
)"
>
{{ value ? languages.find(
(language) => language.value === value,
)?.label : 'Select language...' }}

<ChevronsUpDown class="ml-2 h-4 w-4 shrink-0 opacity-50" />
</Button>
</FormControl>
</PopoverTrigger>
<PopoverContent class="w-[200px] p-0">
<Command v-bind="componentField">
<CommandInput placeholder="Search language..." />
<CommandEmpty>No framework found.</CommandEmpty>
<CommandGroup>
<CommandItem
v-for="language in languages" :key="language.value" :value="language.value" @select="() => {
open = false
}"
>
<Check
:class="cn(
'mr-2 h-4 w-4',
value === language.label ? 'opacity-100' : 'opacity-0',
)"
/>
{{ language.label }}
</CommandItem>
</CommandGroup>
</Command>
</PopoverContent>
</Popover>

<FormDescription>
This is the language that will be used in the dashboard.
</FormDescription>
<FormMessage />
</FormItem>
</FormField>

<div class="flex justify-start">
<Button type="submit">
Update account
</Button>
</div>
</form>
</Form>
</template>
Loading
Loading