{
  "$schema": "https://blode.co/ui/schema/registry-item.json",
  "name": "field",
  "title": "Field",
  "author": "Matthew Blode",
  "description": "A form field wrapper that pairs a label, input, and helper text.",
  "registryDependencies": ["label", "separator"],
  "files": [
    {
      "path": "ui/field.tsx",
      "content": "\"use client\";\n\nimport { cva } from \"class-variance-authority\";\nimport type { VariantProps } from \"class-variance-authority\";\nimport { useMemo } from \"react\";\n\nimport { cn } from \"@/lib/utils\";\nimport { Label } from \"@/components/ui/label\";\nimport { Separator } from \"@/components/ui/separator\";\n\nconst FieldSet = ({ className, ...props }: React.ComponentProps<\"fieldset\">) => (\n  <fieldset\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    data-slot=\"field-set\"\n    {...props}\n  />\n);\n\nconst FieldLegend = ({\n  className,\n  variant = \"legend\",\n  ...props\n}: React.ComponentProps<\"legend\"> & { variant?: \"legend\" | \"label\" }) => (\n  <legend\n    className={cn(\n      \"mb-3 font-medium\",\n      \"data-[variant=legend]:text-base\",\n      \"data-[variant=label]:text-sm\",\n      className,\n    )}\n    data-slot=\"field-legend\"\n    data-variant={variant}\n    {...props}\n  />\n);\n\nconst FieldGroup = ({ className, ...props }: React.ComponentProps<\"div\">) => (\n  <div\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    data-slot=\"field-group\"\n    {...props}\n  />\n);\n\nconst fieldVariants = cva(\"group/field flex w-full gap-3 data-[invalid=true]:text-destructive\", {\n  defaultVariants: {\n    orientation: \"vertical\",\n  },\n  variants: {\n    orientation: {\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        \"@md/field-group:flex-row flex-col @md/field-group:items-center @md/field-group:[&>*]:w-auto [&>*]:w-full [&>.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      vertical: [\"flex-col [&>*]:w-full [&>.sr-only]:w-auto\"],\n    },\n  },\n});\n\nconst Field = ({\n  className,\n  orientation = \"vertical\",\n  ...props\n}: React.ComponentProps<\"fieldset\"> & VariantProps<typeof fieldVariants>) => (\n  <fieldset\n    className={cn(fieldVariants({ orientation }), className)}\n    data-orientation={orientation}\n    data-slot=\"field\"\n    {...props}\n  />\n);\n\nconst FieldContent = ({ className, ...props }: React.ComponentProps<\"div\">) => (\n  <div\n    className={cn(\"group/field-content flex flex-1 flex-col gap-1.5 leading-snug\", className)}\n    data-slot=\"field-content\"\n    {...props}\n  />\n);\n\nconst FieldLabel = ({ className, ...props }: React.ComponentProps<typeof Label>) => (\n  <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]:border-primary has-data-[state=checked]:bg-primary/5 dark:has-data-[state=checked]:bg-primary/10\",\n      className,\n    )}\n    data-slot=\"field-label\"\n    {...props}\n  />\n);\n\nconst FieldTitle = ({ className, ...props }: React.ComponentProps<\"div\">) => (\n  <div\n    className={cn(\n      \"flex w-fit items-center gap-2 font-medium text-sm leading-snug group-data-[disabled=true]/field:opacity-50\",\n      className,\n    )}\n    data-slot=\"field-title\"\n    {...props}\n  />\n);\n\nconst FieldDescription = ({ className, ...props }: React.ComponentProps<\"p\">) => (\n  <p\n    className={cn(\n      \"font-normal text-muted-foreground text-sm leading-normal group-has-[[data-orientation=horizontal]]/field:text-balance\",\n      \"nth-last-2:-mt-1 last:mt-0 [[data-variant=legend]+&]:-mt-1.5\",\n      \"[&>a:hover]:text-primary [&>a]:underline [&>a]:underline-offset-4\",\n      className,\n    )}\n    data-slot=\"field-description\"\n    {...props}\n  />\n);\n\nconst FieldSeparator = ({\n  children,\n  className,\n  ...props\n}: React.ComponentProps<\"div\"> & {\n  children?: React.ReactNode;\n}) => (\n  <div\n    className={cn(\n      \"relative -my-2 h-5 text-sm group-data-[variant=outline]/field-group:-mb-2\",\n      className,\n    )}\n    data-content={!!children}\n    data-slot=\"field-separator\"\n    {...props}\n  >\n    <Separator className=\"absolute inset-0 top-1/2\" />\n    {children && (\n      <span\n        className=\"relative mx-auto block w-fit bg-background px-2 text-muted-foreground\"\n        data-slot=\"field-separator-content\"\n      >\n        {children}\n      </span>\n    )}\n  </div>\n);\n\nconst FieldError = ({\n  className,\n  children,\n  errors,\n  ...props\n}: React.ComponentProps<\"div\"> & {\n  errors?: ({ 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      className={cn(\"font-normal text-destructive text-sm\", className)}\n      data-slot=\"field-error\"\n      role=\"alert\"\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",
      "type": "registry:ui",
      "target": ""
    }
  ],
  "type": "registry:ui"
}
