{"$schema":"https://ui.shadcn.com/schema/registry-item.json","name":"ui-field","type":"registry:component","title":"Field","description":"Form field composition helpers for labels and controls.","version":"1.0.0","status":"ga","files":[{"path":"src/components/ui/field.tsx","type":"registry:component","content":"'use client'\n\nimport { useMemo } from 'react'\n\nimport { cva, type VariantProps } from 'class-variance-authority'\n\nimport { cn } from '@/lib/utils'\nimport { Label } from '@/components/ui/label'\nimport { Separator } from '@/components/ui/separator'\n\nfunction FieldSet({ className, ...props }: React.ComponentProps<'fieldset'>) {\n  return (\n    <fieldset\n      data-slot='field-set'\n      className={cn(\n        'flex flex-col gap-6',\n        'has-[>[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.ComponentProps<'legend'> & { variant?: 'legend' | 'label' }) {\n  return (\n    <legend\n      data-slot='field-legend'\n      data-variant={variant}\n      className={cn('mb-3 font-medium', 'data-[variant=legend]:text-base', 'data-[variant=label]:text-sm', className)}\n      {...props}\n    />\n  )\n}\n\nfunction FieldGroup({ className, ...props }: React.ComponentProps<'div'>) {\n  return (\n    <div\n      data-slot='field-group'\n      className={cn(\n        'group/field-group @container/field-group flex w-full flex-col gap-7 data-[slot=checkbox-group]:gap-3 [&>[data-slot=field-group]]:gap-4',\n        className\n      )}\n      {...props}\n    />\n  )\n}\n\nconst fieldVariants = cva('group/field data-[invalid=true]:text-destructive flex w-full gap-3', {\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-auto',\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 @md/field-group:flex-row @md/field-group:items-center [&>*]:w-full @md/field-group:[&>*]:w-auto [&>.sr-only]:w-auto',\n        '@md/field-group:[&>[data-slot=field-label]]:flex-auto',\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\nfunction Field({\n  className,\n  orientation = 'vertical',\n  ...props\n}: React.ComponentProps<'div'> & VariantProps<typeof fieldVariants>) {\n  return (\n    <div\n      role='group'\n      data-slot='field'\n      data-orientation={orientation}\n      className={cn(fieldVariants({ orientation }), className)}\n      {...props}\n    />\n  )\n}\n\nfunction FieldContent({ className, ...props }: React.ComponentProps<'div'>) {\n  return (\n    <div\n      data-slot='field-content'\n      className={cn('group/field-content flex flex-1 flex-col gap-1.5 leading-snug', className)}\n      {...props}\n    />\n  )\n}\n\nfunction FieldLabel({ className, ...props }: React.ComponentProps<typeof Label>) {\n  return (\n    <Label\n      data-slot='field-label'\n      className={cn(\n        'group/field-label peer/field-label flex w-fit gap-2 leading-snug group-data-[disabled=true]/field:opacity-50',\n        'has-[>[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({ className, ...props }: React.ComponentProps<'div'>) {\n  return (\n    <div\n      data-slot='field-label'\n      className={cn(\n        'flex w-fit items-center gap-2 text-sm leading-snug font-medium group-data-[disabled=true]/field:opacity-50',\n        className\n      )}\n      {...props}\n    />\n  )\n}\n\nfunction FieldDescription({ className, ...props }: React.ComponentProps<'p'>) {\n  return (\n    <p\n      data-slot='field-description'\n      className={cn(\n        'text-muted-foreground text-sm leading-normal font-normal group-has-[[data-orientation=horizontal]]/field:text-balance',\n        'last:mt-0 nth-last-2:-mt-1 [[data-variant=legend]+&]:-mt-1.5',\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.ComponentProps<'div'> & {\n  children?: React.ReactNode\n}) {\n  return (\n    <div\n      data-slot='field-separator'\n      data-content={!!children}\n      className={cn('relative -my-2 h-5 text-sm group-data-[variant=outline]/field-group:-mb-2', className)}\n      {...props}\n    >\n      <Separator className='absolute inset-0 top-1/2' />\n      {children && (\n        <span\n          className='bg-background text-muted-foreground relative mx-auto block w-fit px-2'\n          data-slot='field-separator-content'\n        >\n          {children}\n        </span>\n      )}\n    </div>\n  )\n}\n\nfunction FieldError({\n  className,\n  children,\n  errors,\n  ...props\n}: React.ComponentProps<'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    const uniqueErrors = [...new Map(errors.map(error => [error?.message, error])).values()]\n\n    if (uniqueErrors?.length == 1) {\n      return uniqueErrors[0]?.message\n    }\n\n    return (\n      <ul className='ml-4 flex list-disc flex-col gap-1'>\n        {uniqueErrors.map((error, index) => error?.message && <li key={index}>{error.message}</li>)}\n      </ul>\n    )\n  }, [children, errors])\n\n  if (!content) {\n    return null\n  }\n\n  return (\n    <div\n      role='alert'\n      data-slot='field-error'\n      className={cn('text-destructive text-sm font-normal', className)}\n      {...props}\n    >\n      {content}\n    </div>\n  )\n}\n\nexport {\n  Field,\n  FieldLabel,\n  FieldDescription,\n  FieldError,\n  FieldGroup,\n  FieldLegend,\n  FieldSeparator,\n  FieldSet,\n  FieldContent,\n  FieldTitle\n}\n"}]}