{"version":3,"file":"FormField.cjs","names":[],"sources":["../../src/forms/FormField.tsx"],"sourcesContent":["/**\n * @tempest-limits props-count — FormFieldChildProps is not a component's props — it\n * is the contract handed to whatever control the field wraps, and it is exactly what\n * react-hook-form's register returns (name, value, onChange, onBlur, ref) plus what\n * the field adds around it (error, label, helperText, required, id). Trimming it\n * breaks the wiring it exists to describe.\n */\nimport { cloneElement, isValidElement } from \"react\";\nimport type { ReactElement, ReactNode } from \"react\";\nimport {\n    Controller,\n    useFormContext,\n    type Control,\n    type ControllerRenderProps,\n    type FieldPath,\n    type FieldValues,\n} from \"react-hook-form\";\n\nimport { DUPLICATE_COPY_REMEDY } from \"../utils/duplicate-instance\";\n\nexport interface FormFieldChildProps {\n    name: string;\n    value: unknown;\n    onChange: (...args: unknown[]) => void;\n    onBlur: () => void;\n    ref: ControllerRenderProps[\"ref\"];\n    error?: string;\n    \"aria-invalid\"?: boolean;\n    \"aria-describedby\"?: string;\n    label?: ReactNode;\n    helperText?: ReactNode;\n    required?: boolean;\n    id?: string;\n}\n\nexport interface FormFieldProps<\n    TValues extends FieldValues = FieldValues,\n    TName extends FieldPath<TValues> = FieldPath<TValues>,\n> {\n    /** Field name (dot path supported, e.g. `\"address.city\"`). */\n    name: TName;\n    /** Field label rendered by the wrapped control. */\n    label?: ReactNode;\n    /** Helper text rendered by the wrapped control when there is no error. */\n    helperText?: ReactNode;\n    /** When `true`, marks the control as required (visual hint + native attribute). */\n    required?: boolean;\n    /**\n     * Explicit `control` from `useForm()` / `useZodForm()`. Optional when a\n     * `FormProvider` is in the tree.\n     */\n    control?: Control<TValues>;\n    /**\n     * The control to render. Receives `{ value, onChange, onBlur, ref, error, ... }`\n     * via `cloneElement`. Pass `<Input />`, `<Select />`, masked inputs, etc.\n     */\n    children: ReactElement;\n}\n\n/**\n * Glue between `react-hook-form` `Controller` and the SDK's controlled\n * components. Wraps any control that accepts `{ value, onChange, label,\n * error }` and routes RHF state into it — eliminating the per-field\n * `<Controller render={...} />` boilerplate.\n *\n * @example\n * const form = useZodForm(schema);\n * <FormProvider {...form}>\n *     <Form>\n *         <FormField name=\"email\" label=\"Email\" required>\n *             <Input type=\"email\" />\n *         </FormField>\n *         <FormField name=\"cep\" label=\"CEP\">\n *             <CEPInput />\n *         </FormField>\n *     </Form>\n * </FormProvider>;\n */\n/**\n * What is thrown when no `control` can be resolved.\n *\n * It names **two** causes, because the throw cannot tell them apart and the\n * second one is the expensive one. The obvious reading — no provider, no prop —\n * is usually right. But the identical throw happens with a `<FormProvider>`\n * mounted directly above, when the app and the SDK resolve two different copies\n * of `react-hook-form`: the provider publishes on the app copy's context and\n * `useFormContext` here reads the SDK copy's, which is empty. Someone looking at\n * a provider they can see, being told it is missing, does not go looking at\n * `node_modules` — so the message has to send them there.\n */\nconst NO_CONTROL_MESSAGE =\n    \"FormField found no form to bind to. Either pass a `control` prop, or mount a \" +\n    \"<FormProvider> above it. If a <FormProvider> IS mounted above it, the app and the \" +\n    \"SDK are resolving two copies of react-hook-form: the provider publishes on one \" +\n    \"copy's context and this field reads the other's. \" +\n    DUPLICATE_COPY_REMEDY;\n\nexport function FormField<\n    TValues extends FieldValues = FieldValues,\n    TName extends FieldPath<TValues> = FieldPath<TValues>,\n>({ name, label, helperText, required, control, children }: FormFieldProps<TValues, TName>) {\n    const context = useFormContext<TValues>();\n    const resolvedControl = control ?? context?.control;\n    if (!resolvedControl) {\n        throw new Error(NO_CONTROL_MESSAGE);\n    }\n\n    return (\n        <Controller\n            name={name}\n            control={resolvedControl}\n            render={({ field, fieldState }) => {\n                if (!isValidElement(children)) return children;\n                const errorMessage = fieldState.error?.message;\n                return cloneElement(children as ReactElement<FormFieldChildProps>, {\n                    name: field.name,\n                    value: field.value,\n                    onChange: field.onChange,\n                    onBlur: field.onBlur,\n                    ref: field.ref,\n                    label,\n                    helperText: errorMessage ? undefined : helperText,\n                    error: errorMessage,\n                    required,\n                    \"aria-invalid\": !!errorMessage,\n                });\n            }}\n        />\n    );\n}\n"],"mappings":"sIA0FA,IAAM,EACF,kSAIA,EAAA,sBAEJ,SAAgB,EAGd,CAAE,OAAM,QAAO,aAAY,WAAU,UAAS,YAA4C,CACxF,IAAM,GAAA,EAAU,EAAA,eAAA,CAAwB,EAClC,EAAkB,GAAW,GAAS,QAC5C,GAAI,CAAC,EACD,MAAU,MAAM,CAAkB,EAGtC,OACI,EAAA,EAAA,IAAA,CAAC,EAAA,WAAD,CACU,OACN,QAAS,EACT,QAAS,CAAE,QAAO,gBAAiB,CAC/B,GAAI,EAAA,EAAC,EAAA,eAAA,CAAe,CAAQ,EAAG,OAAO,EACtC,IAAM,EAAe,EAAW,OAAO,QACvC,OAAA,EAAO,EAAA,aAAA,CAAa,EAA+C,CAC/D,KAAM,EAAM,KACZ,MAAO,EAAM,MACb,SAAU,EAAM,SAChB,OAAQ,EAAM,OACd,IAAK,EAAM,IACX,QACA,WAAY,EAAe,IAAA,GAAY,EACvC,MAAO,EACP,WACA,eAAgB,CAAC,CAAC,CACtB,CAAC,CACL,CACH,CAAA,CAET"}