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