{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "field",
  "title": "Field",
  "description": "Form field layout with label, description and error that wire their ids to the control automatically, plus fieldset, legend, orientation and invalid/disabled state.",
  "dependencies": [
    "class-variance-authority"
  ],
  "files": [
    {
      "path": "registry/tealmac/field.tsx",
      "content": "// Adapted from Ballmac UI (https://github.com/vamsiy78/ballmac-ui), MIT License, Copyright (c) 2026 Ballmac.\n// Based on shadcn/ui Field (MIT, Copyright (c) 2023 shadcn), adding automatic id wiring (label, description, error) through useFieldControl and an invalid/disabled state that flows to the control.\n\"use client\"\n\nimport * as React from \"react\"\nimport { cva, type VariantProps } from \"class-variance-authority\"\n\nimport { cn } from \"@/lib/utils\"\n\ntype FieldContextValue = {\n  id: string\n  invalid: boolean\n  disabled: boolean\n}\nconst FieldContext = React.createContext<FieldContextValue | null>(null)\n\ntype FieldControlProps = {\n  id?: string\n  \"aria-invalid\"?: true\n  \"aria-describedby\"?: string\n  disabled?: true\n}\n\n/**\n * Props to spread on the control inside a `Field` (Input, Textarea, Select trigger, Combobox…).\n * It links the control to the label, description and error, and passes the invalid and disabled state.\n * Returns an empty object outside a `Field`.\n */\nfunction useFieldControl(): FieldControlProps {\n  const field = React.useContext(FieldContext)\n  if (!field) return {}\n  return {\n    id: field.id,\n    \"aria-invalid\": field.invalid || undefined,\n    \"aria-describedby\":\n      [`${field.id}-description`, field.invalid ? `${field.id}-error` : null]\n        .filter(Boolean)\n        .join(\" \") || undefined,\n    disabled: field.disabled || undefined,\n  }\n}\n\ntype FieldSetProps = React.ComponentProps<\"fieldset\">\nfunction FieldSet({ className, ...props }: FieldSetProps) {\n  return (\n    <fieldset\n      data-slot=\"field-set\"\n      className={cn(\"flex flex-col gap-5\", className)}\n      {...props}\n    />\n  )\n}\n\ntype FieldLegendProps = React.ComponentProps<\"legend\"> & {\n  /** `legend` for a section title, `label` for a smaller heading. */\n  variant?: \"legend\" | \"label\"\n}\nfunction FieldLegend({\n  className,\n  variant = \"legend\",\n  ...props\n}: FieldLegendProps) {\n  return (\n    <legend\n      data-slot=\"field-legend\"\n      data-variant={variant}\n      className={cn(\n        \"mb-3 font-semibold data-[variant=label]:text-sm data-[variant=legend]:text-base\",\n        className\n      )}\n      {...props}\n    />\n  )\n}\n\ntype FieldGroupProps = React.ComponentProps<\"div\">\nfunction FieldGroup({ className, ...props }: FieldGroupProps) {\n  return (\n    <div\n      data-slot=\"field-group\"\n      className={cn(\"group/field-group flex w-full flex-col gap-5\", className)}\n      {...props}\n    />\n  )\n}\n\nconst fieldVariants = cva(\n  \"group/field flex w-full gap-2 data-[invalid=true]:text-destructive\",\n  {\n    variants: {\n      orientation: {\n        vertical: \"flex-col\",\n        horizontal:\n          \"flex-row items-center [&>[data-slot=field-label]]:flex-auto\",\n        responsive:\n          \"flex-col @md/field-group:flex-row @md/field-group:items-center @md/field-group:[&>[data-slot=field-label]]:flex-auto\",\n      },\n    },\n    defaultVariants: { orientation: \"vertical\" },\n  }\n)\n\ntype FieldProps = React.ComponentProps<\"div\"> &\n  VariantProps<typeof fieldVariants> & {\n    /** Layout of label and control. `horizontal` suits checkboxes and switches. */\n    orientation?: \"vertical\" | \"horizontal\" | \"responsive\"\n    /** Marks the control invalid: the label turns destructive, the control gets `aria-invalid` and the error is announced. */\n    invalid?: boolean\n    /** Disables the control and dims the label. */\n    disabled?: boolean\n    /** Override the generated id shared by the label and control. */\n    controlId?: string\n  }\nfunction Field({\n  className,\n  orientation = \"vertical\",\n  invalid = false,\n  disabled = false,\n  controlId,\n  ...props\n}: FieldProps) {\n  const generated = React.useId()\n  const id = controlId ?? generated\n  const value = React.useMemo(\n    () => ({ id, invalid, disabled }),\n    [id, invalid, disabled]\n  )\n  return (\n    <FieldContext.Provider value={value}>\n      <div\n        role=\"group\"\n        data-slot=\"field\"\n        data-orientation={orientation}\n        data-invalid={invalid}\n        data-disabled={disabled}\n        className={cn(\n          fieldVariants({ orientation }),\n          \"data-[disabled=true]:opacity-60\",\n          className\n        )}\n        {...props}\n      />\n    </FieldContext.Provider>\n  )\n}\n\ntype FieldContentProps = React.ComponentProps<\"div\">\n/** Groups the label and description beside a horizontal control. */\nfunction FieldContent({ className, ...props }: FieldContentProps) {\n  return (\n    <div\n      data-slot=\"field-content\"\n      className={cn(\"flex flex-1 flex-col gap-1 leading-snug\", className)}\n      {...props}\n    />\n  )\n}\n\ntype FieldLabelProps = React.ComponentProps<\"label\"> & {\n  /** Show a required asterisk after the text. Add `required` to the control too. */\n  required?: boolean\n}\nfunction FieldLabel({\n  className,\n  required,\n  children,\n  htmlFor,\n  ...props\n}: FieldLabelProps) {\n  const field = React.useContext(FieldContext)\n  return (\n    <label\n      data-slot=\"field-label\"\n      htmlFor={htmlFor ?? field?.id}\n      className={cn(\n        \"flex w-fit items-center gap-2 text-sm leading-snug font-medium select-none group-data-[disabled=true]/field:cursor-not-allowed\",\n        className\n      )}\n      {...props}\n    >\n      {children}\n      {required && (\n        <span aria-hidden=\"true\" className=\"text-destructive\">\n          *\n        </span>\n      )}\n    </label>\n  )\n}\n\ntype FieldTitleProps = React.ComponentProps<\"div\">\n/** A label-styled title for cards that hold a control (radio cards, switch rows). */\nfunction FieldTitle({ className, ...props }: FieldTitleProps) {\n  return (\n    <div\n      data-slot=\"field-title\"\n      className={cn(\n        \"flex w-fit items-center gap-2 text-sm leading-snug font-medium\",\n        className\n      )}\n      {...props}\n    />\n  )\n}\n\ntype FieldDescriptionProps = React.ComponentProps<\"p\">\nfunction FieldDescription({ className, id, ...props }: FieldDescriptionProps) {\n  const field = React.useContext(FieldContext)\n  return (\n    <p\n      data-slot=\"field-description\"\n      id={id ?? (field ? `${field.id}-description` : undefined)}\n      className={cn(\n        \"text-muted-foreground text-sm leading-normal font-normal\",\n        className\n      )}\n      {...props}\n    />\n  )\n}\n\ntype FieldErrorProps = Omit<React.ComponentProps<\"div\">, \"children\"> & {\n  /** Messages to show. Duplicates are removed; one message renders as text, several as a list. */\n  errors?: Array<{ message?: string } | string | undefined>\n  /** Custom content instead of `errors`. */\n  children?: React.ReactNode\n}\n/** Announces validation messages (`role=\"alert\"`). Renders nothing when there are none. */\nfunction FieldError({\n  className,\n  errors,\n  children,\n  id,\n  ...props\n}: FieldErrorProps) {\n  const field = React.useContext(FieldContext)\n  const messages = React.useMemo(() => {\n    const list = (errors ?? [])\n      .map((e) => (typeof e === \"string\" ? e : e?.message))\n      .filter((m): m is string => Boolean(m))\n    return [...new Set(list)]\n  }, [errors])\n  const content =\n    children ??\n    (messages.length === 0 ? null : messages.length === 1 ? (\n      messages[0]\n    ) : (\n      <ul className=\"ms-4 flex list-disc flex-col gap-1\">\n        {messages.map((m) => (\n          <li key={m}>{m}</li>\n        ))}\n      </ul>\n    ))\n  if (!content) return null\n  return (\n    <div\n      role=\"alert\"\n      data-slot=\"field-error\"\n      id={id ?? (field ? `${field.id}-error` : undefined)}\n      className={cn(\"text-destructive text-sm font-normal\", className)}\n      {...props}\n    >\n      {content}\n    </div>\n  )\n}\n\ntype FieldSeparatorProps = React.ComponentProps<\"div\"> & {\n  /** Text in the middle of the rule, for example \"or\". */\n  children?: React.ReactNode\n}\nfunction FieldSeparator({\n  children,\n  className,\n  ...props\n}: FieldSeparatorProps) {\n  return (\n    <div\n      data-slot=\"field-separator\"\n      aria-hidden=\"true\"\n      className={cn(\"relative -my-1 flex h-5 items-center text-sm\", className)}\n      {...props}\n    >\n      <span className=\"bg-border absolute inset-x-0 h-px\" />\n      {children && (\n        <span className=\"bg-background text-muted-foreground relative mx-auto px-2\">\n          {children}\n        </span>\n      )}\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  useFieldControl,\n  fieldVariants,\n  type FieldControlProps,\n  type FieldProps,\n  type FieldLabelProps,\n  type FieldDescriptionProps,\n  type FieldErrorProps,\n  type FieldGroupProps,\n  type FieldLegendProps,\n  type FieldSeparatorProps,\n  type FieldSetProps,\n  type FieldContentProps,\n  type FieldTitleProps,\n}\n",
      "type": "registry:ui"
    }
  ],
  "type": "registry:ui"
}