{ "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "field", "title": "Field", "description": "A full form field system with labels, descriptions, and errors.", "registryDependencies": [ "https://ds.formance.com/r/label.json", "https://ds.formance.com/r/separator.json" ], "files": [ { "path": "registry/default/ui/field.tsx", "content": "'use client';\n\nimport { cva, type VariantProps } from 'class-variance-authority';\nimport { useMemo } from 'react';\n\nimport { cn } from '@/lib/utils';\nimport { Label } from '@/registry/default/ui/label';\nimport { Separator } from '@/registry/default/ui/separator';\n\nfunction FieldSet({\n className,\n ...props\n}: React.ComponentPropsWithoutRef<'fieldset'>) {\n return (\n [data-slot=checkbox-group]]:gap-3 has-[>[data-slot=radio-group]]:gap-3',\n className\n )}\n {...props}\n />\n );\n}\n\nfunction FieldLegend({\n className,\n variant = 'legend',\n ...props\n}: React.ComponentPropsWithoutRef<'legend'> & {\n variant?: 'legend' | 'label';\n}) {\n return (\n \n );\n}\n\nfunction FieldGroup({\n className,\n ...props\n}: React.ComponentPropsWithoutRef<'div'>) {\n return (\n [data-slot=field-group]]:gap-4',\n className\n )}\n {...props}\n />\n );\n}\n\nconst fieldVariants = cva(\n 'group/field flex w-full gap-3 data-[invalid=true]:text-destructive-foreground text-sm',\n {\n variants: {\n orientation: {\n vertical: ['flex-col [&>*]:w-full [&>.sr-only]:w-auto'],\n horizontal: [\n 'flex-row items-center',\n '[&>[data-slot=field-label]]:flex-1 [&>[data-slot=field-label]]:min-w-0 [&>[data-slot=field-label]]:flex-col [&>[data-slot=field-label]]:items-start [&>[data-slot=field-label]]:gap-0.5',\n '[&>[data-slot=field-content]]:shrink-0 [&>[data-slot=field-content]]:grow-0 [&>[data-slot=field-content]]:md:basis-1/2',\n 'has-[>[data-slot=field-content]]:items-start has-[>[data-slot=field-content]]:[&>[role=checkbox],[role=radio]]:mt-px',\n ],\n responsive: [\n 'flex-col [&>*]:w-full [&>.sr-only]:w-auto @md/field-group:flex-row @md/field-group:items-center @md/field-group:[&>*]:w-auto',\n '@md/field-group:[&>[data-slot=field-label]]:flex-1 @md/field-group:[&>[data-slot=field-label]]:min-w-0 @md/field-group:[&>[data-slot=field-label]]:flex-col @md/field-group:[&>[data-slot=field-label]]:items-start @md/field-group:[&>[data-slot=field-label]]:gap-0.5',\n '@md/field-group:[&>[data-slot=field-content]]:shrink-0 @md/field-group:[&>[data-slot=field-content]]:grow-0 @md/field-group:[&>[data-slot=field-content]]:md:basis-1/2',\n '@md/field-group:has-[>[data-slot=field-content]]:items-start @md/field-group:has-[>[data-slot=field-content]]:[&>[role=checkbox],[role=radio]]:mt-px',\n ],\n },\n },\n defaultVariants: {\n orientation: 'vertical',\n },\n }\n);\n\nfunction Field({\n className,\n orientation = 'vertical',\n ...props\n}: React.ComponentPropsWithoutRef<'div'> & VariantProps) {\n return (\n \n );\n}\n\nfunction FieldContent({\n className,\n ...props\n}: React.ComponentPropsWithoutRef<'div'>) {\n return (\n \n );\n}\n\nfunction FieldLabel({\n className,\n ...props\n}: React.ComponentPropsWithoutRef) {\n return (\n [data-slot=field]]:w-full has-[>[data-slot=field]]:flex-col has-[>[data-slot=field]]:rounded-md has-[>[data-slot=field]]:border [&>*]:data-[slot=field]:p-4',\n 'has-data-[state=checked]:bg-primary/5 has-data-[state=checked]:border-primary dark:has-data-[state=checked]:bg-primary/10',\n className\n )}\n {...props}\n />\n );\n}\n\nfunction FieldTitle({\n className,\n ...props\n}: React.ComponentPropsWithoutRef<'div'>) {\n return (\n \n );\n}\n\nfunction FieldDescription({\n className,\n ...props\n}: React.ComponentPropsWithoutRef<'p'>) {\n return (\n a:hover]:text-primary [&>a]:underline [&>a]:underline-offset-4',\n className\n )}\n {...props}\n />\n );\n}\n\nfunction FieldSeparator({\n children,\n className,\n ...props\n}: React.ComponentPropsWithoutRef<'div'> & {\n children?: React.ReactNode;\n}) {\n return (\n \n \n {children && (\n \n {children}\n \n )}\n \n );\n}\n\nfunction FieldError({\n className,\n children,\n errors,\n ...props\n}: React.ComponentPropsWithoutRef<'div'> & {\n errors?: Array<{ message?: string } | undefined>;\n}) {\n const content = useMemo(() => {\n if (children) {\n return children;\n }\n\n if (!errors?.length) {\n return null;\n }\n\n if (errors?.length == 1) {\n return errors[0]?.message;\n }\n\n return (\n
    \n {errors.flatMap((error, index) =>\n error?.message\n ? [
  • {error.message}
  • ]\n : []\n )}\n
\n );\n }, [children, errors]);\n\n if (!content) {\n return null;\n }\n\n return (\n \n {content}\n \n );\n}\n\nexport {\n Field,\n FieldContent,\n FieldDescription,\n FieldError,\n FieldGroup,\n FieldLabel,\n FieldLegend,\n FieldSeparator,\n FieldSet,\n FieldTitle,\n};\n", "type": "registry:ui" } ], "type": "registry:ui" }