'use client' import * as LabelPrimitive from '@radix-ui/react-label' import { Slot } from '@radix-ui/react-slot' import { Controller, ControllerProps, FieldPath, FieldValues, FormProvider, useFormContext } from 'react-hook-form' import { createContext, forwardRef, useContext, useId } from 'react' import { cn } from '../lib/utils' import { Label } from './label' /** * Contexts */ type FormFieldContextValue< TFieldValues extends FieldValues = FieldValues, TName extends FieldPath = FieldPath, > = { name: TName } const FormFieldContext = createContext({} as FormFieldContextValue) type FormItemContextValue = { id: string } const FormItemContext = createContext({} as FormItemContextValue) /** * Hooks */ function useFormField() { const fieldContext = useContext(FormFieldContext) const itemContext = useContext(FormItemContext) const { getFieldState, formState } = useFormContext() const fieldState = getFieldState(fieldContext.name, formState) if (!fieldContext) { throw new Error('useFormField should be used within ') } const { id } = itemContext return { id, name: fieldContext.name, formItemId: `${id}-form-item`, formDescriptionId: `${id}-form-item-description`, formMessageId: `${id}-form-item-message`, ...fieldState, } } /** * Components */ const Form = FormProvider function FormFieldWithController< TFieldValues extends FieldValues = FieldValues, TName extends FieldPath = FieldPath, >(props: ControllerProps) { return ( ) } type FormFieldProps = { name: string children: React.ReactNode } function FormField({ name, children }: FormFieldProps) { return {children} } const FormItem = forwardRef>(({ className, ...props }, ref) => { const id = useId() return (
) }) FormItem.displayName = 'FormItem' const FormLabel = forwardRef< React.ElementRef, React.ComponentPropsWithoutRef >(({ className, ...props }, ref) => { const { error, formItemId } = useFormField() return