gitscope
https://dev.kronoz.win/r/marzneshin.git
dashboard/src/common/components/ui/form.tsx · v0.7.4
Source
1 88bd1b0 Mrdn 2y ago import * as React from "react"
2 88bd1b0 Mrdn 2y ago import * as LabelPrimitive from "@radix-ui/react-label"
3 88bd1b0 Mrdn 2y ago import { Slot } from "@radix-ui/react-slot"
4 88bd1b0 Mrdn 2y ago import {
5 d636f3f Dawsh 2y ago Controller,
6 d636f3f Dawsh 2y ago ControllerProps,
7 d636f3f Dawsh 2y ago FieldPath,
8 d636f3f Dawsh 2y ago FieldValues,
9 d636f3f Dawsh 2y ago FormProvider,
10 d636f3f Dawsh 2y ago useFormContext,
11 88bd1b0 Mrdn 2y ago } from "react-hook-form"
12 88bd1b0 Mrdn 2y ago
13 d636f3f Dawsh 2y ago import { cn } from "@marzneshin/common/utils"
14 7389ad0 Mardin 2y ago import { Label } from "@marzneshin/common/components/ui/label"
15 88bd1b0 Mrdn 2y ago
16 88bd1b0 Mrdn 2y ago const Form = FormProvider
17 88bd1b0 Mrdn 2y ago
18 88bd1b0 Mrdn 2y ago type FormFieldContextValue<
19 d636f3f Dawsh 2y ago TFieldValues extends FieldValues = FieldValues,
20 d636f3f Dawsh 2y ago TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>
21 88bd1b0 Mrdn 2y ago > = {
22 d636f3f Dawsh 2y ago name: TName
23 88bd1b0 Mrdn 2y ago }
24 88bd1b0 Mrdn 2y ago
25 88bd1b0 Mrdn 2y ago const FormFieldContext = React.createContext<FormFieldContextValue>(
26 d636f3f Dawsh 2y ago {} as FormFieldContextValue
27 88bd1b0 Mrdn 2y ago )
28 88bd1b0 Mrdn 2y ago
29 88bd1b0 Mrdn 2y ago const FormField = <
30 d636f3f Dawsh 2y ago TFieldValues extends FieldValues = FieldValues,
31 d636f3f Dawsh 2y ago TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>
32 88bd1b0 Mrdn 2y ago >({
33 d636f3f Dawsh 2y ago ...props
34 88bd1b0 Mrdn 2y ago }: ControllerProps<TFieldValues, TName>) => {
35 d636f3f Dawsh 2y ago return (
36 d636f3f Dawsh 2y ago <FormFieldContext.Provider value={{ name: props.name }}>
37 d636f3f Dawsh 2y ago <Controller {...props} />
38 d636f3f Dawsh 2y ago </FormFieldContext.Provider>
39 d636f3f Dawsh 2y ago )
40 88bd1b0 Mrdn 2y ago }
41 88bd1b0 Mrdn 2y ago
42 88bd1b0 Mrdn 2y ago const useFormField = () => {
43 d636f3f Dawsh 2y ago const fieldContext = React.useContext(FormFieldContext)
44 d636f3f Dawsh 2y ago const itemContext = React.useContext(FormItemContext)
45 d636f3f Dawsh 2y ago const { getFieldState, formState } = useFormContext()
46 d636f3f Dawsh 2y ago
47 d636f3f Dawsh 2y ago const fieldState = getFieldState(fieldContext.name, formState)
48 d636f3f Dawsh 2y ago
49 d636f3f Dawsh 2y ago if (!fieldContext) {
50 d636f3f Dawsh 2y ago throw new Error("useFormField should be used within <FormField>")
51 d636f3f Dawsh 2y ago }
52 d636f3f Dawsh 2y ago
53 d636f3f Dawsh 2y ago const { id } = itemContext
54 d636f3f Dawsh 2y ago
55 d636f3f Dawsh 2y ago return {
56 d636f3f Dawsh 2y ago id,
57 d636f3f Dawsh 2y ago name: fieldContext.name,
58 d636f3f Dawsh 2y ago formItemId: `${id}-form-item`,
59 d636f3f Dawsh 2y ago formDescriptionId: `${id}-form-item-description`,
60 d636f3f Dawsh 2y ago formMessageId: `${id}-form-item-message`,
61 d636f3f Dawsh 2y ago ...fieldState,
62 d636f3f Dawsh 2y ago }
63 88bd1b0 Mrdn 2y ago }
64 88bd1b0 Mrdn 2y ago
65 88bd1b0 Mrdn 2y ago type FormItemContextValue = {
66 d636f3f Dawsh 2y ago id: string
67 88bd1b0 Mrdn 2y ago }
68 88bd1b0 Mrdn 2y ago
69 88bd1b0 Mrdn 2y ago const FormItemContext = React.createContext<FormItemContextValue>(
70 d636f3f Dawsh 2y ago {} as FormItemContextValue
71 88bd1b0 Mrdn 2y ago )
72 88bd1b0 Mrdn 2y ago
73 88bd1b0 Mrdn 2y ago const FormItem = React.forwardRef<
74 d636f3f Dawsh 2y ago HTMLDivElement,
75 d636f3f Dawsh 2y ago React.HTMLAttributes<HTMLDivElement>
76 88bd1b0 Mrdn 2y ago >(({ className, ...props }, ref) => {
77 d636f3f Dawsh 2y ago const id = React.useId()
78 88bd1b0 Mrdn 2y ago
79 d636f3f Dawsh 2y ago return (
80 d636f3f Dawsh 2y ago <FormItemContext.Provider value={{ id }}>
81 d636f3f Dawsh 2y ago <div ref={ref} className={cn("space-y-2", className)} {...props} />
82 d636f3f Dawsh 2y ago </FormItemContext.Provider>
83 d636f3f Dawsh 2y ago )
84 88bd1b0 Mrdn 2y ago })
85 88bd1b0 Mrdn 2y ago FormItem.displayName = "FormItem"
86 88bd1b0 Mrdn 2y ago
87 88bd1b0 Mrdn 2y ago const FormLabel = React.forwardRef<
88 d636f3f Dawsh 2y ago React.ElementRef<typeof LabelPrimitive.Root>,
89 d636f3f Dawsh 2y ago React.ComponentPropsWithoutRef<typeof LabelPrimitive.Root>
90 88bd1b0 Mrdn 2y ago >(({ className, ...props }, ref) => {
91 d636f3f Dawsh 2y ago const { error, formItemId } = useFormField()
92 d636f3f Dawsh 2y ago
93 d636f3f Dawsh 2y ago return (
94 d636f3f Dawsh 2y ago <Label
95 d636f3f Dawsh 2y ago ref={ref}
96 d636f3f Dawsh 2y ago className={cn(error && "text-destructive", "font-semibold", className)}
97 d636f3f Dawsh 2y ago htmlFor={formItemId}
98 d636f3f Dawsh 2y ago {...props}
99 d636f3f Dawsh 2y ago />
100 d636f3f Dawsh 2y ago )
101 88bd1b0 Mrdn 2y ago })
102 88bd1b0 Mrdn 2y ago FormLabel.displayName = "FormLabel"
103 88bd1b0 Mrdn 2y ago
104 88bd1b0 Mrdn 2y ago const FormControl = React.forwardRef<
105 d636f3f Dawsh 2y ago React.ElementRef<typeof Slot>,
106 d636f3f Dawsh 2y ago React.ComponentPropsWithoutRef<typeof Slot>
107 88bd1b0 Mrdn 2y ago >(({ ...props }, ref) => {
108 d636f3f Dawsh 2y ago const { error, formItemId, formDescriptionId, formMessageId } = useFormField()
109 d636f3f Dawsh 2y ago
110 d636f3f Dawsh 2y ago return (
111 d636f3f Dawsh 2y ago <Slot
112 d636f3f Dawsh 2y ago ref={ref}
113 d636f3f Dawsh 2y ago id={formItemId}
114 d636f3f Dawsh 2y ago aria-describedby={
115 d636f3f Dawsh 2y ago !error
116 d636f3f Dawsh 2y ago ? `${formDescriptionId}`
117 d636f3f Dawsh 2y ago : `${formDescriptionId} ${formMessageId}`
118 d636f3f Dawsh 2y ago }
119 d636f3f Dawsh 2y ago aria-invalid={!!error}
120 d636f3f Dawsh 2y ago {...props}
121 d636f3f Dawsh 2y ago />
122 d636f3f Dawsh 2y ago )
123 88bd1b0 Mrdn 2y ago })
124 88bd1b0 Mrdn 2y ago FormControl.displayName = "FormControl"
125 88bd1b0 Mrdn 2y ago
126 88bd1b0 Mrdn 2y ago const FormDescription = React.forwardRef<
127 d636f3f Dawsh 2y ago HTMLParagraphElement,
128 d636f3f Dawsh 2y ago React.HTMLAttributes<HTMLParagraphElement>
129 88bd1b0 Mrdn 2y ago >(({ className, ...props }, ref) => {
130 d636f3f Dawsh 2y ago const { formDescriptionId } = useFormField()
131 d636f3f Dawsh 2y ago
132 d636f3f Dawsh 2y ago return (
133 d636f3f Dawsh 2y ago <p
134 d636f3f Dawsh 2y ago ref={ref}
135 d636f3f Dawsh 2y ago id={formDescriptionId}
136 d636f3f Dawsh 2y ago className={cn("text-sm text-muted-foreground", className)}
137 d636f3f Dawsh 2y ago {...props}
138 d636f3f Dawsh 2y ago />
139 d636f3f Dawsh 2y ago )
140 88bd1b0 Mrdn 2y ago })
141 88bd1b0 Mrdn 2y ago FormDescription.displayName = "FormDescription"
142 88bd1b0 Mrdn 2y ago
143 88bd1b0 Mrdn 2y ago const FormMessage = React.forwardRef<
144 d636f3f Dawsh 2y ago HTMLParagraphElement,
145 d636f3f Dawsh 2y ago React.HTMLAttributes<HTMLParagraphElement>
146 88bd1b0 Mrdn 2y ago >(({ className, children, ...props }, ref) => {
147 d636f3f Dawsh 2y ago const { error, formMessageId } = useFormField()
148 d636f3f Dawsh 2y ago const body = error ? String(error?.message) : children
149 d636f3f Dawsh 2y ago
150 d636f3f Dawsh 2y ago if (!body) {
151 d636f3f Dawsh 2y ago return null
152 d636f3f Dawsh 2y ago }
153 d636f3f Dawsh 2y ago
154 d636f3f Dawsh 2y ago return (
155 d636f3f Dawsh 2y ago <p
156 d636f3f Dawsh 2y ago ref={ref}
157 d636f3f Dawsh 2y ago id={formMessageId}
158 d636f3f Dawsh 2y ago className={cn("text-sm font-medium text-destructive", className)}
159 d636f3f Dawsh 2y ago {...props}
160 d636f3f Dawsh 2y ago >
161 d636f3f Dawsh 2y ago {body}
162 d636f3f Dawsh 2y ago </p>
163 d636f3f Dawsh 2y ago )
164 88bd1b0 Mrdn 2y ago })
165 88bd1b0 Mrdn 2y ago FormMessage.displayName = "FormMessage"
166 88bd1b0 Mrdn 2y ago
167 88bd1b0 Mrdn 2y ago export {
168 d636f3f Dawsh 2y ago useFormField,
169 d636f3f Dawsh 2y ago Form,
170 d636f3f Dawsh 2y ago FormItem,
171 d636f3f Dawsh 2y ago FormLabel,
172 d636f3f Dawsh 2y ago FormControl,
173 d636f3f Dawsh 2y ago FormDescription,
174 d636f3f Dawsh 2y ago FormMessage,
175 d636f3f Dawsh 2y ago FormField,
176 88bd1b0 Mrdn 2y ago }