/* Copyright 2026 Marimo. All rights reserved. */ import { AlertCircleIcon } from "lucide-react"; import { type Label as LabelPrimitive, Slot as SlotPrimitive } from "radix-ui"; import * as React from "react"; import { Controller, type ControllerProps, type FieldPath, type FieldValues, FormProvider, useFormContext, } from "react-hook-form"; import { Label } from "@/components/ui/label"; import { Tooltip } from "@/components/ui/tooltip"; import { cn } from "@/utils/cn"; const Form = FormProvider; export const FormErrorsBanner = () => { const ctx = useFormContext(); const errors = ctx.formState.errors; if (Object.keys(errors).length === 0) { return null; } return (
{Object.values(errors) .map((error) => error?.message) .filter(Boolean) .join(", ")}
); }; interface FormFieldContextValue< TFieldValues extends FieldValues = FieldValues, TName extends FieldPath = FieldPath, > { name: TName; } const FormFieldContext = React.createContext( {} as FormFieldContextValue, ); const FormField = < TFieldValues extends FieldValues = FieldValues, TName extends FieldPath = FieldPath, >({ ...props }: ControllerProps) => { return ( // Need key to prevent context value from being stale ); }; const useFormField = () => { const fieldContext = React.use(FormFieldContext); const itemContext = React.use(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, }; }; interface FormItemContextValue { id: string; } const FormItemContext = React.createContext( {} as FormItemContextValue, ); const FormItem = React.forwardRef< HTMLDivElement, React.HTMLAttributes >(({ className, ...props }, ref) => { const id = React.useId(); return (
); }); FormItem.displayName = "FormItem"; const FormLabel = React.forwardRef< React.ElementRef, React.ComponentPropsWithoutRef >(({ className, ...props }, ref) => { const { error, formItemId } = useFormField(); if (!props.children) { return; } return (