{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "outreach-sequence",
  "title": "Outreach Sequence",
  "description": "A timeline of the emails in a follow-up sequence.",
  "dependencies": [
    "@xyflow/react",
    "cn"
  ],
  "registryDependencies": [],
  "files": [
    {
      "path": "registry/notra/outreach/components/outreach-sequence.tsx",
      "content": "import { cn } from \"cn\";\n\nimport { OUTREACH_STEP_STATUSES } from \"../constants/outreach\";\nimport type { OutreachSequenceProps } from \"../types/outreach\";\n\nexport const OutreachSequence = ({\n  className,\n  steps,\n  ...props\n}: OutreachSequenceProps) => (\n  <ol\n    className={cn(\"flex flex-col\", className)}\n    data-slot=\"outreach-sequence\"\n    {...props}\n  >\n    {steps.map((step, index) => (\n      <li\n        className=\"relative grid grid-cols-[0.75rem_minmax(0,1fr)_auto] gap-3 pb-4 last:pb-0\"\n        data-status={step.status}\n        key={step.id}\n      >\n        {index < steps.length - 1 && (\n          <span\n            aria-hidden=\"true\"\n            className=\"bg-border absolute top-4 bottom-0 left-[0.3125rem] w-px\"\n          />\n        )}\n        <span\n          aria-hidden=\"true\"\n          className={cn(\n            \"mt-1 size-2.5 rounded-full\",\n            OUTREACH_STEP_STATUSES[step.status].className\n          )}\n        />\n        <span className=\"flex min-w-0 flex-col\">\n          <span className=\"truncate text-[0.8125rem] font-medium\">\n            {step.subject}\n          </span>\n          <span className=\"text-muted-foreground text-xs\">\n            {`Day ${step.day} · ${OUTREACH_STEP_STATUSES[step.status].label}`}\n          </span>\n        </span>\n        <span className=\"text-muted-foreground text-xs tabular-nums\">\n          {step.at}\n        </span>\n      </li>\n    ))}\n  </ol>\n);\n",
      "type": "registry:component",
      "target": "components/outreach/components/outreach-sequence.tsx"
    },
    {
      "path": "registry/notra/outreach/constants/outreach.ts",
      "content": "import type {\n  OutreachDraft,\n  OutreachProspect,\n  OutreachStat,\n  OutreachStatus,\n  OutreachStatusConfig,\n  OutreachStepStatus,\n  OutreachVariable,\n} from \"../types/outreach\";\n\nexport const OUTREACH_STATUSES: Record<OutreachStatus, OutreachStatusConfig> = {\n  declined: { className: \"text-muted-foreground\", label: \"Declined\" },\n  drafted: {\n    className: \"text-violet-600 dark:text-violet-300\",\n    label: \"Drafted\",\n  },\n  found: { className: \"text-muted-foreground\", label: \"Found\" },\n  listed: {\n    className: \"text-emerald-600 dark:text-emerald-400\",\n    label: \"Listed\",\n  },\n  opened: { className: \"text-sky-600 dark:text-sky-400\", label: \"Opened\" },\n  replied: {\n    className: \"text-amber-600 dark:text-amber-400\",\n    label: \"Replied\",\n  },\n  sent: { className: \"text-blue-600 dark:text-blue-400\", label: \"Sent\" },\n};\n\nexport const OUTREACH_STEP_STATUSES: Record<\n  OutreachStepStatus,\n  OutreachStatusConfig\n> = {\n  cancelled: { className: \"bg-muted-foreground/40\", label: \"Cancelled\" },\n  opened: { className: \"bg-sky-500\", label: \"Opened\" },\n  replied: { className: \"bg-amber-500\", label: \"Replied\" },\n  scheduled: {\n    className: \"bg-background ring-1 ring-foreground/25\",\n    label: \"Scheduled\",\n  },\n  sent: { className: \"bg-blue-500\", label: \"Sent\" },\n};\n\nexport const OUTREACH_MODEL = \"gpt-5\";\n\nexport const OUTREACH_STATS: OutreachStat[] = [\n  {\n    hint: \"Cited by an AI answer this month\",\n    label: \"Listicles found\",\n    value: \"37\",\n  },\n  { hint: \"12 waiting for a follow-up\", label: \"Pitches sent\", value: \"21\" },\n  { hint: \"Industry average is 8%\", label: \"Reply rate\", value: \"28.6%\" },\n  { hint: \"+4 citations in ChatGPT since\", label: \"Now listed\", value: \"5\" },\n];\n\nexport const OUTREACH_PROSPECTS: OutreachProspect[] = [\n  {\n    citations: [\n      { engine: \"openai\", prompts: 9 },\n      { engine: \"perplexity\", prompts: 6 },\n      { engine: \"gemini\", prompts: 3 },\n    ],\n    competitors: [\n      { name: \"Beamer\", position: 1 },\n      { name: \"LaunchNotes\", position: 2 },\n      { name: \"Headway\", position: 4 },\n    ],\n    contact: {\n      email: \"maya@example.com\",\n      name: \"Maya Lindqvist\",\n      role: \"Editor\",\n      source: \"Author bio\",\n    },\n    domain: \"saasbase.dev\",\n    domainRating: 71,\n    id: \"saasbase\",\n    sequence: [\n      {\n        at: \"Oct 20\",\n        day: 0,\n        id: \"s1\",\n        status: \"opened\",\n        subject: \"Notra for your changelog roundup\",\n      },\n      {\n        at: \"Oct 23\",\n        day: 3,\n        id: \"s2\",\n        status: \"replied\",\n        subject: \"Re: Notra for your changelog roundup\",\n      },\n    ],\n    status: \"replied\",\n    title: \"The 12 best changelog tools in 2026\",\n    updatedAt: \"2h ago\",\n    url: \"https://saasbase.dev/best-changelog-tools\",\n  },\n  {\n    citations: [\n      { engine: \"perplexity\", prompts: 7 },\n      { engine: \"openai\", prompts: 2 },\n    ],\n    competitors: [\n      { name: \"LaunchNotes\", position: 1 },\n      { name: \"Beamer\", position: 3 },\n    ],\n    contact: {\n      email: \"jonas@example.com\",\n      name: \"Jonas Meyer\",\n      role: \"Founder\",\n      source: \"Contact page\",\n    },\n    domain: \"devtools.fm\",\n    domainRating: 64,\n    id: \"devtools\",\n    sequence: [\n      {\n        at: \"Oct 22\",\n        day: 0,\n        id: \"s1\",\n        status: \"opened\",\n        subject: \"A release-notes tool for your list\",\n      },\n      {\n        at: \"Oct 25\",\n        day: 3,\n        id: \"s2\",\n        status: \"scheduled\",\n        subject: \"Quick follow-up\",\n      },\n      {\n        at: \"Oct 29\",\n        day: 7,\n        id: \"s3\",\n        status: \"scheduled\",\n        subject: \"Last note from me\",\n      },\n    ],\n    status: \"opened\",\n    title: \"Top release notes apps for dev teams\",\n    updatedAt: \"Yesterday\",\n    url: \"https://devtools.fm/top-release-notes-apps\",\n  },\n  {\n    citations: [\n      { engine: \"gemini\", prompts: 5 },\n      { engine: \"grok\", prompts: 2 },\n    ],\n    competitors: [\n      { name: \"Headway\", position: 2 },\n      { name: \"Beamer\", position: 5 },\n    ],\n    contact: {\n      email: \"editor@example.com\",\n      name: \"Priya Raman\",\n      role: \"Managing editor\",\n      source: \"Masthead\",\n    },\n    domain: \"productledhq.com\",\n    domainRating: 58,\n    id: \"productled\",\n    sequence: [\n      {\n        at: \"Oct 24\",\n        day: 0,\n        id: \"s1\",\n        status: \"sent\",\n        subject: \"Changelog automation for your guide\",\n      },\n      {\n        at: \"Oct 27\",\n        day: 3,\n        id: \"s2\",\n        status: \"scheduled\",\n        subject: \"Quick follow-up\",\n      },\n    ],\n    status: \"sent\",\n    title: \"9 product update tools that save PMs time\",\n    updatedAt: \"Yesterday\",\n    url: \"https://productledhq.com/product-update-tools\",\n  },\n  {\n    citations: [{ engine: \"openai\", prompts: 4 }],\n    competitors: [{ name: \"LaunchNotes\", position: 3 }],\n    contact: {\n      email: \"sam@example.com\",\n      name: \"Sam Okafor\",\n      role: \"Writer\",\n      source: \"Author bio\",\n    },\n    domain: \"shipfaster.io\",\n    domainRating: 47,\n    id: \"shipfaster\",\n    sequence: [],\n    status: \"drafted\",\n    title: \"How to write release notes people read (+ 7 tools)\",\n    updatedAt: \"3h ago\",\n    url: \"https://shipfaster.io/release-notes-guide\",\n  },\n  {\n    citations: [\n      { engine: \"perplexity\", prompts: 3 },\n      { engine: \"claude\", prompts: 2 },\n    ],\n    competitors: [\n      { name: \"Beamer\", position: 1 },\n      { name: \"Headway\", position: 2 },\n    ],\n    contact: {\n      email: \"hello@example.com\",\n      name: \"Lea Fischer\",\n      role: \"Owner\",\n      source: \"WHOIS\",\n    },\n    domain: \"indiestack.co\",\n    domainRating: 39,\n    id: \"indiestack\",\n    sequence: [],\n    status: \"found\",\n    title: \"Best tools for indie SaaS founders: changelogs\",\n    updatedAt: \"Just now\",\n    url: \"https://indiestack.co/changelog-tools\",\n  },\n  {\n    citations: [{ engine: \"openai\", prompts: 6 }],\n    competitors: [\n      { name: \"Notra\", position: 3 },\n      { name: \"Beamer\", position: 1 },\n    ],\n    contact: {\n      email: \"tom@example.com\",\n      name: \"Tom Becker\",\n      role: \"Editor\",\n      source: \"Author bio\",\n    },\n    domain: \"growthnotes.com\",\n    domainRating: 66,\n    id: \"growthnotes\",\n    sequence: [\n      {\n        at: \"Oct 2\",\n        day: 0,\n        id: \"s1\",\n        status: \"replied\",\n        subject: \"Notra for your roundup\",\n      },\n    ],\n    status: \"listed\",\n    title: \"The changelog stack for growth teams\",\n    updatedAt: \"Oct 9\",\n    url: \"https://growthnotes.com/changelog-stack\",\n  },\n];\n\nexport const OUTREACH_VARIABLES: OutreachVariable[] = [\n  { key: \"first_name\", label: \"First name\", value: \"Maya\" },\n  {\n    key: \"listicle_title\",\n    label: \"Listicle\",\n    value: \"The 12 best changelog tools in 2026\",\n  },\n  { key: \"company\", label: \"Company\", value: \"Notra\" },\n  {\n    key: \"proof_point\",\n    label: \"Proof point\",\n    value: \"a weekly changelog takes minutes instead of an afternoon\",\n  },\n];\n\nexport const OUTREACH_DRAFTS: OutreachDraft[] = [\n  {\n    body: `Hi {{first_name}},\n\nI read \"{{listicle_title}}\" while researching how teams pick a changelog tool. It's one of the pages ChatGPT and Perplexity quote most for that question.\n\nI work on {{company}}. It turns merged pull requests into changelog posts and release notes, so {{proof_point}}.\n\nWould you consider adding it to the list? Happy to send a demo account, screenshots or anything else that makes it easy.\n\nThanks,\nAlex`,\n    subject: \"{{company}} for {{listicle_title}}\",\n    to: \"\",\n  },\n  {\n    body: `Hi {{first_name}},\n\nQuick one: your roundup \"{{listicle_title}}\" is cited in AI answers for \"best changelog tool\", and {{company}} is missing from it.\n\nWe're an AI changelog writer for dev teams; {{proof_point}}. If it's a fit, I can send everything you need for a write-up, no strings attached.\n\nBest,\nAlex`,\n    subject: \"A missing pick for {{listicle_title}}?\",\n    to: \"\",\n  },\n];\n\nexport const OUTREACH_MAX_COMPETITORS = 4;\n\nexport const OUTREACH_REWRITE_MS = 1200;\n\nexport const OUTREACH_SEND_MS = 900;\n\nexport const OUTREACH_PITCHABLE = new Set<OutreachStatus>([\n  \"declined\",\n  \"drafted\",\n  \"found\",\n]);\n",
      "type": "registry:lib",
      "target": "components/outreach/constants/outreach.ts"
    },
    {
      "path": "registry/notra/outreach/types/outreach.ts",
      "content": "import type { ComponentProps, ReactNode } from \"react\";\n\nimport type {\n  WorkflowLogoName,\n  WorkflowOverlayProps,\n} from \"../../workflow/types/workflow\";\n\nexport type OutreachStatus =\n  | \"found\"\n  | \"drafted\"\n  | \"sent\"\n  | \"opened\"\n  | \"replied\"\n  | \"listed\"\n  | \"declined\";\n\nexport type OutreachStepStatus =\n  | \"sent\"\n  | \"opened\"\n  | \"replied\"\n  | \"scheduled\"\n  | \"cancelled\";\n\nexport interface OutreachStatusConfig {\n  className: string;\n  label: string;\n}\n\nexport interface OutreachCitation {\n  engine: WorkflowLogoName;\n  prompts: number;\n}\n\nexport interface OutreachContact {\n  email: string;\n  name: string;\n  role: string;\n  source: string;\n}\n\nexport interface OutreachCompetitor {\n  name: string;\n  position: number;\n}\n\nexport interface OutreachSequenceStep {\n  id: string;\n  day: number;\n  subject: string;\n  status: OutreachStepStatus;\n  at: string;\n}\n\nexport interface OutreachProspect {\n  id: string;\n  title: string;\n  url: string;\n  domain: string;\n  domainRating: number;\n  status: OutreachStatus;\n  citations: OutreachCitation[];\n  competitors: OutreachCompetitor[];\n  contact: OutreachContact;\n  sequence: OutreachSequenceStep[];\n  updatedAt: string;\n}\n\nexport interface OutreachDraft {\n  body: string;\n  subject: string;\n  to: string;\n}\n\nexport interface OutreachVariable {\n  key: string;\n  label: string;\n  value: string;\n}\n\nexport interface OutreachStat {\n  hint: string;\n  label: string;\n  value: string;\n}\n\nexport type OutreachStatusBadgeProps = ComponentProps<\"span\"> & {\n  status: OutreachStatus;\n};\n\nexport type OutreachCitationsProps = ComponentProps<\"span\"> & {\n  citations: OutreachCitation[];\n};\n\nexport type OutreachProspectTableProps = ComponentProps<\"div\"> & {\n  prospects: OutreachProspect[];\n  emptyLabel?: ReactNode;\n  onOpen?: (prospect: OutreachProspect) => void;\n  onDraft?: (prospect: OutreachProspect) => void;\n};\n\nexport type OutreachEmailDialogProps = WorkflowOverlayProps & {\n  prospect?: OutreachProspect;\n  drafts: OutreachDraft[];\n  variables: OutreachVariable[];\n  model?: string;\n  onSend?: (prospect: OutreachProspect, draft: OutreachDraft) => void;\n};\n\nexport type OutreachProspectSheetProps = WorkflowOverlayProps & {\n  prospect?: OutreachProspect;\n  onDraft?: (prospect: OutreachProspect) => void;\n  onMarkListed?: (prospect: OutreachProspect) => void;\n};\n\nexport type OutreachSequenceProps = ComponentProps<\"ol\"> & {\n  steps: OutreachSequenceStep[];\n};\n\nexport type OutreachStatsProps = ComponentProps<\"div\"> & {\n  stats: OutreachStat[];\n};\n\nexport type OutreachEmailComposerProps = Required<\n  Pick<OutreachEmailDialogProps, \"drafts\" | \"variables\" | \"model\">\n> &\n  Pick<OutreachEmailDialogProps, \"onSend\"> & { prospect: OutreachProspect };\n\nexport interface OutreachFilter {\n  label: string;\n  statuses: OutreachStatus[];\n}\n",
      "type": "registry:lib",
      "target": "components/outreach/types/outreach.ts"
    },
    {
      "path": "registry/notra/workflow/types/workflow.ts",
      "content": "import type { Edge, Node, Position } from \"@xyflow/react\";\nimport type { ComponentProps, ComponentType, ReactNode, SVGProps } from \"react\";\n\nexport type WorkflowNodeKind =\n  | \"trigger\"\n  | \"task\"\n  | \"ai\"\n  | \"integration\"\n  | \"condition\"\n  | \"switch\"\n  | \"merge\"\n  | \"loop\"\n  | \"delay\"\n  | \"approval\"\n  | \"email\"\n  | \"output\";\n\nexport type WorkflowNodeStatus =\n  | \"idle\"\n  | \"queued\"\n  | \"running\"\n  | \"waiting\"\n  | \"success\"\n  | \"error\"\n  | \"skipped\";\n\nexport type WorkflowEdgeStatus = \"idle\" | \"active\" | \"done\" | \"skipped\";\n\nexport type WorkflowRunPhase = \"idle\" | \"running\" | \"done\";\n\nexport type WorkflowLogoName =\n  | \"openai\"\n  | \"anthropic\"\n  | \"claude\"\n  | \"gemini\"\n  | \"perplexity\"\n  | \"mistral\"\n  | \"deepseek\"\n  | \"grok\"\n  | \"browserbase\"\n  | \"context-dev\"\n  | \"firecrawl\"\n  | \"resend\"\n  | \"slack\"\n  | \"gmail\"\n  | \"notion\"\n  | \"google\"\n  | \"google-sheets\"\n  | \"webflow\"\n  | \"wordpress\"\n  | \"linear\"\n  | \"github\"\n  | \"ahrefs\"\n  | \"posthog\";\n\nexport type WorkflowLogLevel = \"info\" | \"success\" | \"error\" | \"skip\";\n\nexport type WorkflowIcon = ComponentType<SVGProps<SVGSVGElement>>;\n\nexport interface WorkflowPoint {\n  x: number;\n  y: number;\n}\n\nexport interface WorkflowAnchor extends WorkflowPoint {\n  position: Position;\n}\n\nexport interface WorkflowPort {\n  id: string;\n  label?: string;\n  hint?: string;\n  rate?: number;\n}\n\nexport interface WorkflowRule {\n  subject: string;\n  operator: string;\n  value: string;\n}\n\nexport interface WorkflowField {\n  label: string;\n  value: string;\n}\n\nexport interface WorkflowNodeData {\n  id: string;\n  kind: WorkflowNodeKind;\n  title: string;\n  description?: string;\n  position: WorkflowPoint;\n  inputs?: WorkflowPort[];\n  outputs?: WorkflowPort[];\n  logo?: WorkflowLogoName;\n  model?: string;\n  durationMs?: number;\n  branch?: string;\n  rule?: WorkflowRule;\n  fail?: boolean;\n  fields?: WorkflowField[];\n  output?: string;\n}\n\nexport interface WorkflowEdgeData {\n  id: string;\n  source: string;\n  sourcePort?: string;\n  target: string;\n  targetPort?: string;\n  label?: string;\n  animated?: boolean;\n}\n\nexport interface WorkflowEdgeLane {\n  id: string;\n  down: boolean;\n  from: WorkflowPoint;\n  to: WorkflowPoint;\n}\n\nexport interface WorkflowGraph {\n  edges: WorkflowEdgeData[];\n  nodes: WorkflowNodeData[];\n}\n\nexport interface WorkflowTemplate extends WorkflowGraph {\n  id: string;\n  title: string;\n  description: string;\n  category: string;\n}\n\nexport interface WorkflowKindConfig {\n  icon: WorkflowIcon;\n  label: string;\n  tileClassName: string;\n}\n\nexport interface WorkflowStatusConfig {\n  className: string;\n  label: string;\n  ledClassName: string;\n}\n\nexport interface WorkflowLogoConfig {\n  label: string;\n  logo: WorkflowIcon;\n  tile?: boolean;\n}\n\nexport interface WorkflowModel {\n  id: string;\n  label: string;\n  logo: WorkflowLogoName;\n  provider: string;\n}\n\nexport interface WorkflowBlock {\n  id: string;\n  title: string;\n  description: string;\n  group: string;\n  kind: WorkflowNodeKind;\n  logo?: WorkflowLogoName;\n  model?: string;\n  inputs?: WorkflowPort[];\n  outputs?: WorkflowPort[];\n  durationMs?: number;\n}\n\nexport interface WorkflowNodeRun {\n  start: number;\n  end: number;\n  status: \"success\" | \"error\" | \"skipped\";\n}\n\nexport interface WorkflowEdgeRun {\n  start: number;\n  end: number;\n  taken: boolean;\n}\n\nexport interface WorkflowSchedule {\n  edges: Record<string, WorkflowEdgeRun>;\n  nodes: Record<string, WorkflowNodeRun>;\n  order: string[];\n  totalMs: number;\n}\n\nexport interface WorkflowNodeState {\n  elapsedMs: number;\n  status: WorkflowNodeStatus;\n}\n\nexport interface WorkflowLogEntry {\n  at: number;\n  id: string;\n  level: WorkflowLogLevel;\n  message: string;\n  nodeId: string;\n  title: string;\n}\n\nexport interface WorkflowRunSummary {\n  id: string;\n  durationMs: number;\n  startedAt: string;\n  status: \"success\" | \"error\" | \"running\";\n  trigger: string;\n  steps: number;\n}\n\nexport interface WorkflowRun {\n  edgeState: (id: string) => WorkflowEdgeStatus;\n  elapsedMs: number;\n  nodeState: (id: string) => WorkflowNodeState;\n  phase: WorkflowRunPhase;\n  play: () => void;\n  schedule: WorkflowSchedule;\n  stop: () => void;\n  totalMs: number;\n}\n\nexport type WorkflowLogoProps = Omit<SVGProps<SVGSVGElement>, \"name\"> & {\n  name: WorkflowLogoName;\n};\n\nexport interface WorkflowFlowNodeData extends Record<string, unknown> {\n  node: WorkflowNodeData;\n  state?: WorkflowNodeState;\n}\n\nexport interface WorkflowFlowEdgeData extends Record<string, unknown> {\n  animated?: boolean;\n  reverse?: boolean;\n  label?: string;\n  status: WorkflowEdgeStatus;\n}\n\nexport type WorkflowFlowNode = Node<WorkflowFlowNodeData, \"workflow\">;\n\nexport type WorkflowFlowEdge = Edge<WorkflowFlowEdgeData, \"workflow\">;\n\nexport type WorkflowCanvasBackgroundVariant =\n  | \"dots\"\n  | \"lines\"\n  | \"cross\"\n  | \"grid\"\n  | \"none\";\n\nexport interface WorkflowCanvasBackgroundProps {\n  gap?: number;\n  variant?: WorkflowCanvasBackgroundVariant;\n}\n\nexport type WorkflowNodeSizes = Record<\n  string,\n  { height: number; width: number }\n>;\n\nexport interface WorkflowPortListProps {\n  ports: WorkflowPort[];\n  title: string;\n}\n\nexport interface WorkflowControlsProps {\n  toolbar?: ReactNode;\n}\n\nexport interface WorkflowBannerConfig {\n  className: string;\n  label: string;\n  message: string;\n}\n\nexport interface WorkflowStatusGlyphProps {\n  status: WorkflowNodeStatus;\n}\n\nexport interface WorkflowTemplatePreviewProps {\n  template: WorkflowTemplate;\n}\n\nexport interface WorkflowCanvasProps {\n  className?: string;\n  /** Follows new steps as they are added or move, like a workflow being written. */\n  autoFit?: boolean;\n  focusId?: string;\n  background?: WorkflowCanvasBackgroundVariant;\n  gap?: number;\n  nodes: WorkflowNodeData[];\n  edges: WorkflowEdgeData[];\n  nodeState?: (id: string) => WorkflowNodeState;\n  edgeState?: (id: string) => WorkflowEdgeStatus;\n  selectedId?: string;\n  controls?: boolean;\n  minimap?: boolean;\n  toolbar?: ReactNode;\n  minZoom?: number;\n  maxZoom?: number;\n  /** The smallest zoom that fits the whole graph; below it, the view shows the first or last steps instead. */\n  fitMinZoom?: number;\n  onSelectNode?: (id: string) => void;\n  onNodeMove?: (id: string, position: WorkflowPoint) => void;\n  onNodeRemove?: (id: string) => void;\n  onConnect?: (edge: Omit<WorkflowEdgeData, \"id\">) => void;\n  onDropBlock?: (blockId: string, position: WorkflowPoint) => void;\n}\n\nexport type WorkflowNodeCardProps = ComponentProps<\"div\"> & {\n  node: WorkflowNodeData;\n  state?: WorkflowNodeState;\n  selected?: boolean;\n  connectable?: boolean;\n  children?: ReactNode;\n};\n\nexport interface WorkflowHandleProps {\n  active?: boolean;\n  className?: string;\n  connectable?: boolean;\n  portId: string;\n  type: \"source\" | \"target\";\n}\n\nexport type WorkflowEdgeProps = ComponentProps<\"g\"> & {\n  path: string;\n  reverse?: boolean;\n  status?: WorkflowEdgeStatus;\n  animated?: boolean;\n};\n\nexport type WorkflowTimerProps = ComponentProps<\"span\"> & {\n  ms: number;\n  running?: boolean;\n};\n\nexport type WorkflowStatusIndicatorProps = ComponentProps<\"span\"> & {\n  status: WorkflowNodeStatus;\n};\n\nexport type WorkflowStatusBadgeProps = ComponentProps<\"span\"> & {\n  status: WorkflowNodeStatus;\n};\n\nexport type WorkflowStatusPillProps = ComponentProps<\"span\"> & {\n  status: WorkflowNodeStatus;\n};\n\nexport type WorkflowDeterminismBadgeProps = ComponentProps<\"span\"> & {\n  deterministic: boolean;\n};\n\nexport type WorkflowRunButtonProps = Omit<\n  ComponentProps<\"button\">,\n  \"children\"\n> & {\n  phase: WorkflowRunPhase;\n  progress?: number;\n  onPlay?: () => void;\n  onStop?: () => void;\n};\n\nexport type WorkflowNodePaletteProps = ComponentProps<\"div\"> & {\n  blocks: WorkflowBlock[];\n  onAdd?: (block: WorkflowBlock) => void;\n};\n\nexport interface WorkflowNodeBranchProps {\n  connectable?: boolean;\n  node: WorkflowNodeData;\n  port: WorkflowPort;\n  status: WorkflowNodeStatus;\n}\n\nexport interface WorkflowNodeBannerProps {\n  status: WorkflowNodeStatus;\n}\n\nexport interface WorkflowNodeSummaryProps {\n  children?: ReactNode;\n  node: WorkflowNodeData;\n}\n\nexport interface WorkflowNodeEngineProps {\n  node: WorkflowNodeData;\n}\n\nexport interface WorkflowNodeFooterProps {\n  node: WorkflowNodeData;\n  state?: WorkflowNodeState;\n}\n\nexport interface WorkflowBranchSelectProps {\n  node: WorkflowNodeData;\n  outputs: WorkflowPort[];\n  onBranchChange: (id: string, branch: string) => void;\n}\n\nexport type WorkflowNodeSettingsProps = Pick<\n  WorkflowNodeSheetProps,\n  \"onBranchChange\" | \"onModelChange\"\n> & {\n  node: WorkflowNodeData;\n};\n\nexport type WorkflowNodeSheetProps = WorkflowOverlayProps & {\n  node?: WorkflowNodeData;\n  state?: WorkflowNodeState;\n  log?: WorkflowLogEntry[];\n  onDelete?: (id: string) => void;\n  onModelChange?: (id: string, model: string) => void;\n  onBranchChange?: (id: string, branch: string) => void;\n};\n\nexport type WorkflowRunLogProps = ComponentProps<\"div\"> & {\n  entries: WorkflowLogEntry[];\n  emptyLabel?: string;\n};\n\nexport type WorkflowRunTimelineProps = ComponentProps<\"div\"> & {\n  nodes: WorkflowNodeData[];\n  schedule: WorkflowSchedule;\n  elapsedMs: number;\n  phase: WorkflowRunPhase;\n};\n\nexport type WorkflowRunHistoryProps = Omit<\n  ComponentProps<\"div\">,\n  \"onSelect\"\n> & {\n  runs: WorkflowRunSummary[];\n  selectedId?: string;\n  onSelect?: (id: string) => void;\n};\n\nexport interface WorkflowModelSelectProps {\n  className?: string;\n  defaultValue?: string;\n  disabled?: boolean;\n  id?: string;\n  models?: WorkflowModel[];\n  onValueChange?: (value: string) => void;\n  value?: string;\n}\n\nexport type WorkflowTemplateCardProps = ComponentProps<\"div\"> & {\n  template: WorkflowTemplate;\n  onUse?: (template: WorkflowTemplate) => void;\n};\n\nexport type WorkflowTemplateDialogProps = WorkflowOverlayProps & {\n  template?: WorkflowTemplate;\n  onUse?: (template: WorkflowTemplate) => void;\n};\n\nexport interface WorkflowBlockIconProps {\n  block: Pick<WorkflowBlock, \"kind\" | \"logo\" | \"model\">;\n  className?: string;\n}\n\nexport interface WorkflowOverlayProps {\n  defaultOpen?: boolean;\n  onOpenChange?: (open: boolean) => void;\n  open?: boolean;\n}\n\nexport interface WorkflowCanvasBackgroundOption {\n  label: string;\n  value: WorkflowCanvasBackgroundVariant;\n}\n\nexport interface WorkflowNodeDemo {\n  node: WorkflowNodeData;\n  state: WorkflowNodeState;\n}\n\nexport interface WorkflowEdgeDemo {\n  animated?: boolean;\n  label: string;\n  status: WorkflowEdgeStatus;\n}\n",
      "type": "registry:lib",
      "target": "components/workflow/types/workflow.ts"
    }
  ],
  "type": "registry:component"
}