{
  "schemaVersion": 1,
  "name": "field",
  "useFor": "Wrap Input, Textarea, TagsInput or SelectTrigger. Derive error from the current value and clear it when valid. Use required for required fields and htmlFor when the control has an explicit id.",
  "constraints": [
    "Labels inside the field as placeholders",
    "Bold or caps labels",
    "Errors shown only by color"
  ],
  "documentation": "`Field` connects its label and help/error message to `Input`, `Textarea`, `TagsInput`, and `SelectTrigger`. It also shares required and invalid state. Set `htmlFor` when you give the control an explicit `id`; otherwise the field generates an ID.\n\nValidation belongs to your form. Derive `error` from the current value and pass `undefined` when valid, as in the live example. A static error string stays visible until your form clears it. Set `required` on the `Select` root as well for native form validation. For a custom control, use `useFieldControl` to connect the same attributes.",
  "source": "opencommerce-agentcard-web src/components/monitoring.tsx (#merchant-filter); labels are an extension",
  "exports": [
    "Field",
    "useFieldControl"
  ],
  "client": true,
  "docsUrl": "https://opencommerce-ds.vercel.app/components/field",
  "markdownUrl": "https://opencommerce-ds.vercel.app/r/field.md",
  "examples": [
    {
      "path": "examples/field.tsx",
      "content": "\"use client\";\n\nimport { useState } from \"react\";\nimport { Field } from \"@/components/ui/field\";\nimport { Input } from \"@/components/ui/input\";\n\nfunction isWebAddress(value: string) {\n  const text = value.trim();\n  if (!text || /\\s/.test(text)) return false;\n  try {\n    const url = new URL(text.includes(\"://\") ? text : `https://${text}`);\n    return [\"http:\", \"https:\"].includes(url.protocol) && !url.username && !url.password &&\n      url.hostname.includes(\".\") && url.hostname.split(\".\").every((part) => /^[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$/i.test(part));\n  } catch { return false; }\n}\n\nexport function Site() {\n  const [website, setWebsite] = useState(\"acme\");\n  const valid = isWebAddress(website);\n  return (\n    <div className=\"grid max-w-170 gap-4\">\n      <Field label=\"Work email\" htmlFor=\"field-email\" required help=\"We reply within a day.\">\n        <Input id=\"field-email\" type=\"email\" autoComplete=\"email\" />\n      </Field>\n      <Field label=\"Website\" htmlFor=\"field-site\" error={valid ? undefined : \"Enter a web address, like acme.com.\"} help=\"Web address accepted.\">\n        <Input id=\"field-site\" value={website} onChange={(event) => setWebsite(event.target.value)} autoComplete=\"url\" inputMode=\"url\" />\n      </Field>\n    </div>\n  );\n}\n",
      "exports": [
        "Site"
      ],
      "requires": [
        "field",
        "input"
      ],
      "packages": [],
      "previews": [
        {
          "name": "Site",
          "url": "https://opencommerce-ds.vercel.app/preview/field/Site"
        }
      ]
    }
  ],
  "type": "ui",
  "title": "Field",
  "description": "Label, help text, error message and accessibility attributes for a form control.",
  "surface": "site",
  "kinds": [
    "input"
  ],
  "requires": [
    "theme",
    "label",
    "utils"
  ],
  "packages": [],
  "files": [
    {
      "path": "components/ui/field.tsx",
      "content": "\"use client\";\n\nimport * as React from \"react\";\nimport { Label } from \"@/components/ui/label\";\nimport { cn } from \"@/lib/utils\";\n\ntype FieldState = { id: string; description?: string; invalid: boolean; required: boolean };\nconst FieldContext = React.createContext<FieldState | undefined>(undefined);\n\n/** Connect a control to its Field without replacing its own IDs or accessibility descriptions. */\nfunction useFieldControl<T extends { id?: string; required?: boolean; \"aria-invalid\"?: React.AriaAttributes[\"aria-invalid\"]; \"aria-describedby\"?: string }>(props: T) {\n  const field = React.useContext(FieldContext);\n  return {\n    ...props,\n    id: props.id ?? field?.id,\n    required: props.required ?? field?.required,\n    \"aria-invalid\": props[\"aria-invalid\"] ?? (field?.invalid || undefined),\n    \"aria-describedby\": [props[\"aria-describedby\"], field?.description].filter(Boolean).join(\" \") || undefined,\n  };\n}\n\n// Validation belongs to the form; Field shares its current error, hint and required state with the control.\nfunction Field({ label, htmlFor, help, error, required = false, className, children }: {\n  label: React.ReactNode; htmlFor?: string; help?: React.ReactNode; error?: React.ReactNode;\n  required?: boolean; className?: string; children: React.ReactNode;\n}) {\n  const generatedId = React.useId();\n  const id = htmlFor ?? generatedId;\n  const message = error || help;\n  const description = message ? `${id}-description` : undefined;\n  return (\n    <FieldContext.Provider value={{ id, description, invalid: Boolean(error), required }}>\n      <div data-slot=\"field\" data-invalid={error ? true : undefined} className={cn(\"flex min-w-0 flex-col gap-1.5\", className)}>\n        <Label htmlFor={id} className=\"block font-sans text-caption leading-normal text-fg-muted\">\n          {label}\n          {required && <><span aria-hidden className=\"ml-0.5 text-danger\">*</span><span className=\"sr-only\"> (required)</span></>}\n        </Label>\n        {children}\n        <p id={`${id}-description`} aria-live=\"polite\" aria-atomic=\"true\" className={cn(\"text-body-sm leading-snug empty:hidden\", error ? \"text-danger\" : \"text-fg-muted\")}>{message}</p>\n      </div>\n    </FieldContext.Provider>\n  );\n}\n\nexport { Field, useFieldControl };\n"
    }
  ]
}
