{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "core-file-drag-card",
  "type": "registry:ui",
  "title": "Audio and MIDI File Drag Card",
  "description": "Audio and MIDI File Drag Card shared by module faces and application hosts.",
  "dependencies": [
    "lucide-react",
    "maru-icons@^0.0.1",
    "maruaudio@>=0.0.3 <0.1.0"
  ],
  "registryDependencies": [
    "https://pluginui.com/r/core-audio-clip-player.json",
    "https://pluginui.com/r/core-piano-roll.json"
  ],
  "files": [
    {
      "path": "components/ui/file-drag-card.tsx",
      "content": "/**\n * Source: https://maru.audio/ui-kit/file-drag-card\n * Copyright © [Maru](https://maru.audio)\n *\n * Maru UI Kit — https://maru.audio/ui-kit\n *\n * Installed from the Maru UI registry. This file is yours now: edit it\n * freely, it will not be overwritten unless you re-run the add command.\n *\n * Keep this item’s companion files and CSS imports together. Dependencies\n * declared by the registry are installed with the source.\n */\nimport { type HTMLAttributes, type ReactNode, type Ref } from \"react\"\nimport { FileIcon as File, FileMusicIcon as FileMusic } from \"maru-icons/react\"\nimport { FileAudio, GripVertical } from \"lucide-react\"\nimport { AudioClipWaveform } from \"@/components/ui/audio-clip-player\"\nimport type { AudioPreviewWaveform } from \"maruaudio/ui/shared/audio-clip-waveform\"\nimport {\n  PianoRollPreview,\n  type PianoRollPreviewProps,\n} from \"@/components/ui/piano-roll\"\n\nexport type FileDragPreview =\n  | {\n      kind: \"audio\"\n      waveform: AudioPreviewWaveform | null\n      durationMs?: number\n    }\n  | { kind: \"midi\"; notes: PianoRollPreviewProps[\"notes\"]; duration?: number }\n\nexport interface FileDragCardProps extends HTMLAttributes<HTMLDivElement> {\n  ref?: Ref<HTMLDivElement>\n  label: string\n  format?: string\n  detail?: ReactNode\n  icon?: ReactNode\n  preview?: FileDragPreview\n}\n\nconst STYLES = `\n:where([data-file-drag-card]){box-sizing:border-box;display:flex;flex-direction:column;gap:10px;min-width:0;width:252px;max-width:100%;padding:12px;border:1px solid var(--uikit-border,var(--border,#45454d));background:var(--uikit-surface,var(--background,#202026));color:var(--uikit-text,var(--foreground,#efeff4));font:500 12px/1.4 var(--uikit-font,system-ui,sans-serif);box-shadow:0 8px 24px #0003;border-radius:0;text-align:left;user-select:none}\n:where([data-file-drag-card] [data-drag-card-heading]){display:flex;align-items:center;gap:8px;min-width:0}\n:where([data-file-drag-card] [data-drag-card-label]){flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-weight:600}\n:where([data-file-drag-card] [data-drag-card-format]){flex:none;padding:2px 5px;border:1px solid var(--uikit-border,var(--border,#45454d));font:600 9px/1.3 var(--uikit-font-mono,monospace);letter-spacing:.06em}\n:where([data-file-drag-card] [data-drag-card-preview]){display:flex;align-items:center;width:100%;height:52px;overflow:hidden;color:var(--uikit-text-muted,#9696a8);--uikit-track:var(--uikit-text-muted,#9696a8)}\n:where([data-file-drag-card] [data-drag-card-footer]){display:flex;align-items:center;justify-content:space-between;gap:8px;color:var(--uikit-text-muted,var(--muted-foreground,#a4a4b2));font-size:10px}\n:where([data-file-drag-card] svg){flex-shrink:0}\n`\n\n/** Presentation only. Hosts supply real peaks/notes and prepared file actions;\n * this component never fetches, decodes, synthesizes or exports a file. */\nexport function FileDragCard({\n  ref,\n  label,\n  format,\n  detail,\n  icon,\n  preview,\n  children,\n  ...props\n}: FileDragCardProps) {\n  const kind = preview?.kind ?? \"file\"\n  return (\n    <div {...props} ref={ref} data-file-drag-card=\"\" data-kind={kind}>\n      <style>{STYLES}</style>\n      <div data-drag-card-heading=\"\">\n        {icon ??\n          (kind === \"audio\" ? (\n            <FileAudio size={16} />\n          ) : kind === \"midi\" ? (\n            <FileMusic size={16} />\n          ) : (\n            <File size={16} />\n          ))}\n        <span data-drag-card-label=\"\">{label}</span>\n        <span data-drag-card-format=\"\">\n          {format ??\n            (kind === \"midi\" ? \"MIDI\" : kind === \"audio\" ? \"AUDIO\" : \"FILE\")}\n        </span>\n      </div>\n      {preview && (\n        <div data-drag-card-preview=\"\">\n          {preview.kind === \"audio\" ? (\n            preview.waveform ? (\n              <AudioClipWaveform\n                variant={{\n                  label,\n                  waveform: preview.waveform,\n                  durationMs: preview.durationMs,\n                }}\n                progress={0}\n                waveformStyle=\"detailed\"\n                height={48}\n                onSeek={() => {}}\n                disabled\n                showPlayhead={false}\n              />\n            ) : (\n              <span>Waveform unavailable</span>\n            )\n          ) : preview.notes.length ? (\n            <PianoRollPreview\n              notes={preview.notes}\n              durationBeats={preview.duration}\n              style={{ height: 48, width: \"100%\" }}\n            />\n          ) : (\n            <span>No note preview</span>\n          )}\n        </div>\n      )}\n      <div data-drag-card-footer=\"\">\n        <span>{detail ?? \"Drag to your DAW\"}</span>\n        <GripVertical size={13} />\n      </div>\n      {children}\n    </div>\n  )\n}\n\n/** A painted, off-screen copy of the same card for setDragImage. */\nexport function FileDragGhost({ style, ...props }: FileDragCardProps) {\n  return (\n    <FileDragCard\n      {...props}\n      data-slot=\"file-drag-ghost\"\n      aria-hidden=\"true\"\n      style={{\n        position: \"fixed\",\n        top: -2000,\n        left: -2000,\n        pointerEvents: \"none\",\n        opacity: 0.88,\n        ...style,\n      }}\n    />\n  )\n}\nexport type FileDragGhostProps = FileDragCardProps\n",
      "type": "registry:component",
      "target": "@ui/file-drag-card.tsx"
    }
  ]
}
