1import { Input, Select } from '@components/Form'
2import { FormProvider, useForm } from 'react-hook-form'
3import { zodResolver } from '@hookform/resolvers/zod';
4import { z } from 'zod'
5
6const LogPagesFormSchema = z.object({
7 languageCode: z.string(),
8 activity: z.number(),
9 amount: z.number().positive(),
10 unit: z.number(),
11 tags: z
12 .array(z.string())
13 .min(1, 'Must select at least one tag')
14 .max(3, 'Must select three or fewer'),
15 description: z.string().optional(),
16})
17
18const LogPagesForm = () => {
19 const methods = useForm({
20 resolver: zodResolver(LogPagesFormSchema),
21 })
22 const onSubmit = (data: any) => console.log(data, 'submitted')
23
24 const languages = [
25 { value: 'jpa', label: 'Japanese' },
26 { value: 'zho', label: 'Chinese' },
27 { value: 'kor', label: 'Korean' },
28 ]
29 const units = [
30 { value: '1', label: 'Pages' },
31 { value: '2', label: 'Comic pages' },
32 ]
33 const tags = ['Book', 'Ebook', 'Fiction', 'Non-fiction', 'Web page', 'Lyric']
34 const activities = [
35 { value: '1', label: 'Reading' },
36 { value: '2', label: 'Listening' },
37 { value: '3', label: 'Speaking' },
38 { value: '4', label: 'Writing' },
39 ]
40
41 return (
42 <FormProvider {...methods}>
43 <form
44 onSubmit={methods.handleSubmit(onSubmit)}
45 className="v-stack spaced"
46 >
47 <Select name="languageCode" label="Language" values={languages} />
48 <Select
49 name="activity"
50 label="Activity"
51 values={activities}
52 options={{ valueAsNumber: true }}
53 />
54 <div className="h-stack spaced">
55 <div className="flex-grow">
56 <Input
57 name="amount"
58 label="Amount"
59 type="number"
60 defaultValue={0}
61 options={{ valueAsNumber: true }}
62 min={0}
63 />
64 </div>
65 <div className="min-w-[150px]">
66 <Select
67 name="unit"
68 label="Unit"
69 values={units}
70 options={{ valueAsNumber: true }}
71 />
72 </div>
73 </div>
74 <AutocompleteMultiInput
75 name="tags"
76 label="Tags"
77 options={tags}
78 match={(option, query) =>
79 option
80 .toLowerCase()
81 .replace(/[^a-zA-Z0-9]/g, '')
82 .includes(query.toLowerCase())
83 }
84 getIdForOption={option => option}
85 format={option => option}
86 />
87 <Input
88 name="description"
89 label="Description"
90 type="text"
91 placeholder="e.g. One Piece volume 45"
92 />
93 <button
94 type="submit"
95 className="btn primary"
96 disabled={methods.formState.isSubmitting}
97 >
98 Save changes
99 </button>
100 </form>
101 </FormProvider>
102 )
103}
1import { AutocompleteInput, AutocompleteMultiInput } from '@components/Form'
2import { FormProvider, useForm } from 'react-hook-form'
3
4
5const AutocompleteForm = () => {
6 const methods = useForm()
7 const onSubmit = (data: any) => console.log(data, 'submitted')
8
9 const tags = ['Book', 'Ebook', 'Fiction', 'Non-fiction', 'Web page', 'Lyric']
10 const activities = [
11 { id: 1, name: 'Reading' },
12 { id: 2, name: 'Listening' },
13 { id: 3, name: 'Speaking' },
14 { id: 4, name: 'Writing' },
15 ]
16
17 return (
18 <FormProvider {...methods}>
19 <form
20 onSubmit={methods.handleSubmit(onSubmit)}
21 className="v-stack spaced"
22 >
23 <AutocompleteInput
24 name="tags"
25 label="Tags"
26 options={tags}
27 match={(option, query) =>
28 option
29 .toLowerCase()
30 .replace(/[^a-zA-Z0-9]/g, '')
31 .includes(query.toLowerCase())
32 }
33 format={option => option}
34 />
35 <AutocompleteMultiInput
36 name="activities"
37 label="Activities"
38 options={activities}
39 match={(option, query) =>
40 option.name
41 .toLowerCase()
42 .replace(/[^a-zA-Z0-9]/g, '')
43 .includes(query.toLowerCase())
44 }
45 getIdForOption={option => option.id}
46 format={option => option.name}
47 />
48 <button
49 type="submit"
50 className="btn primary"
51 disabled={methods.formState.isSubmitting}
52 >
53 Submit
54 </button>
55 </form>
56 </FormProvider>
57 )
58}
1import { Checkbox, Input, TextArea } from '@components/Form'
2import { FormProvider, useForm } from 'react-hook-form'
3
4const ComposeBlogPostForm = () => {
5 const methods = useForm()
6 const onSubmit = (data: any) => console.log(data, 'submitted')
7
8 return (
9 <FormProvider {...methods}>
10 <form
11 onSubmit={methods.handleSubmit(onSubmit)}
12 className="v-stack spaced"
13 >
14 <Input
15 name="title"
16 label="Title"
17 type="text"
18 options={{
19 required: true,
20 }}
21 />
22 <TextArea
23 name="content"
24 label="Content"
25 options={{
26 required: true,
27 }}
28 />
29 <Input
30 name="publishedAt"
31 label="Published at"
32 type="date"
33 options={{
34 required: true,
35 valueAsDate: true,
36 }}
37 />
38 <Checkbox name="isPublished" label="Published" />
39 <button
40 type="submit"
41 className="btn primary"
42 disabled={methods.formState.isSubmitting}
43 >
44 Save
45 </button>
46 </form>
47 </FormProvider>
48 )
49}
1import { RadioSelect } from '@components/Form'
2import { FormProvider, useForm } from 'react-hook-form'
3
4const MiscForm = () => {
5 const methods = useForm()
6 const onSubmit = (data: any) => console.log(data, 'submitted')
7
8 return (
9 <FormProvider {...methods}>
10 <form
11 onSubmit={methods.handleSubmit(onSubmit)}
12 className="v-stack spaced"
13 >
14 <RadioSelect
15 name="cardType"
16 label="Card type"
17 options={{
18 required: true,
19 valueAsNumber: true,
20 }}
21 values={[
22 { value: '1', label: 'Sentence card' },
23 { value: '2', label: 'Vocab card' },
24 ]}
25 />
26 <Input
27 name="datetime"
28 label="Datetime"
29 type="datetime-local"
30 options={{
31 required: true,
32 valueAsDate: true,
33 }}
34 />
35 <Input
36 name="time"
37 label="Time"
38 type="time"
39 options={{
40 required: true,
41 }}
42 />
43 <Input
44 name="week"
45 label="Week"
46 type="week"
47 options={{
48 required: true,
49 }}
50 />
51 <Input
52 name="month"
53 label="Month"
54 type="month"
55 options={{
56 required: true,
57 }}
58 />
59 <Input
60 name="color"
61 label="Color"
62 type="color"
63 options={{
64 required: true,
65 }}
66 />
67 <Input
68 name="email"
69 label="Email"
70 type="email"
71 options={{
72 required: true,
73 }}
74 />
75 <Input
76 name="file"
77 label="File"
78 type="file"
79 options={{
80 required: true,
81 }}
82 />
83 <Input
84 name="range"
85 label="Range"
86 type="range"
87 options={{
88 required: true,
89 }}
90 />
91 <Input
92 name="search"
93 label="Search"
94 type="search"
95 options={{
96 required: true,
97 }}
98 />
99 <Input
100 name="tel"
101 label="tel"
102 type="tel"
103 options={{
104 required: true,
105 }}
106 />
107 <Input
108 name="url"
109 label="url"
110 type="url"
111 options={{
112 required: true,
113 }}
114 />
115 <button
116 type="submit"
117 className="btn primary"
118 disabled={methods.formState.isSubmitting}
119 >
120 Submit
121 </button>
122 </form>
123 </FormProvider>
124 )
125}
1<form className="v-stack spaced">
2<label className="label">
3 <span className="label-text">First name</span>
4 <input className="input" type="text" placeholder="John Doe" />
5</label>
6<label className="label">
7 <span className="label-text">Message</span>
8 <textarea className="input" placeholder="Dolor sit amet..." />
9</label>
10<label className="label">
11 <span className="label-text">Choose a color</span>
12 <select className="input">
13 <option value="#ff0000">Red</option>
14 <option value="#00ff00">Green</option>
15 <option value="#0000ff">Blue</option>
16 </select>
17</label>
18<div>
19 <span className="label-text">Choose a color</span>
20 <div className="v-stack">
21 <label className="label-inline">
22 <input type="radio" name="color-radio" className="input" />
23 <span>Red</span>
24 </label>
25 <label className="label-inline">
26 <input type="radio" name="color-radio" />
27 <span>Green</span>
28 </label>
29 <label className="label-inline">
30 <input type="radio" name="color-radio" />
31 <span>Blue</span>
32 </label>
33 </div>
34</div>
35<label className="label error">
36 <span className="label-text">First name</span>
37 <input type="text" placeholder="John Doe" className="input" />
38 <span className="error">
39 Should be at least 1 character long
40 </span>
41</label>
42</form>