{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "dictation-card",
  "type": "registry:ui",
  "title": "Dictation Card",
  "description": "Waveform + live editable transcript + confirm/cancel — dictation as a review step in the composer well.",
  "dependencies": [
    "lucide-react"
  ],
  "registryDependencies": [
    "https://seamui.dev/r/utils.json",
    "https://seamui.dev/r/button.json",
    "https://seamui.dev/r/textarea.json",
    "https://seamui.dev/r/voice-visualizer.json"
  ],
  "files": [
    {
      "path": "registry/seam/ui/dictation-card.tsx",
      "content": "\"use client\"\n\nimport * as React from \"react\"\nimport { Check, X } from \"lucide-react\"\n\nimport { cn } from \"@/lib/utils\"\nimport { Button } from \"./button\"\nimport { Textarea } from \"./textarea\"\nimport { VoiceVisualizer } from \"./voice-visualizer\"\n\n// The Conductor dictation pattern: speech renders into a card *inside the\n// composer well* as live, editable text with explicit confirm/cancel — a\n// review step instead of auto-send on silence. The card is a raised key in\n// the entry well: a draft token sitting in the slot, not yet committed.\n// Transport-agnostic — no STT engine; transcript in, decisions out.\nfunction DictationCard({\n  value,\n  onValueChange,\n  onConfirm,\n  onCancel,\n  listening = true,\n  level,\n  track,\n  placeholder = \"Listening…\",\n  className,\n  ...props\n}: Omit<React.ComponentProps<\"div\">, \"onChange\"> & {\n  /** The transcript so far (controlled). */\n  value: string\n  onValueChange: (value: string) => void\n  onConfirm: (value: string) => void\n  onCancel: () => void\n  /** Whether speech is still being captured. */\n  listening?: boolean\n  placeholder?: string\n  /** Live input level 0–1 for the visualizer (or pass `track`). */\n  level?: number\n  track?: MediaStreamTrack | null\n}) {\n  const id = React.useId()\n\n  return (\n    <div\n      data-slot=\"dictation-card\"\n      role=\"group\"\n      aria-labelledby={`${id}-label`}\n      className={cn(\n        \"bg-secondary shadow-resting flex items-center gap-2 rounded-lg squircle border border-border/60 p-2\",\n        className\n      )}\n      {...props}\n    >\n      <span id={`${id}-label`} className=\"sr-only\">\n        Dictation\n      </span>\n      <VoiceVisualizer\n        state={listening ? \"listening\" : \"disconnected\"}\n        level={level}\n        track={track}\n        count={4}\n        size=\"sm\"\n        className=\"shrink-0 self-center pl-1\"\n      />\n      <Textarea\n        data-slot=\"dictation-card-transcript\"\n        aria-label=\"Dictated text (editable)\"\n        value={value}\n        onChange={(e) => onValueChange(e.target.value)}\n        placeholder={placeholder}\n        rows={1}\n        // Bare text inside the key — no nested well, no chrome. The card is\n        // the surface; the transcript is its content.\n        className=\"min-h-8 flex-1 resize-none border-0 bg-transparent p-1 shadow-none focus-visible:ring-0 focus-visible:border-transparent\"\n      />\n      <div className=\"flex shrink-0 gap-1\">\n        <Button\n          data-slot=\"dictation-card-cancel\"\n          variant=\"ghost\"\n          size=\"icon\"\n          className=\"text-muted-foreground size-8\"\n          aria-label=\"Discard dictation\"\n          onClick={onCancel}\n        >\n          <X className=\"size-4\" />\n        </Button>\n        <Button\n          data-slot=\"dictation-card-confirm\"\n          size=\"icon\"\n          className=\"size-8\"\n          aria-label=\"Use dictated text\"\n          disabled={value.trim().length === 0}\n          onClick={() => onConfirm(value)}\n        >\n          <Check className=\"size-4\" />\n        </Button>\n      </div>\n    </div>\n  )\n}\n\nexport { DictationCard }\n",
      "type": "registry:ui",
      "target": "components/ui/dictation-card.tsx"
    }
  ]
}