{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "workflow-status",
  "title": "Workflow Status",
  "description": "Status indicators and badges for steps, plus the deterministic and non-deterministic badges.",
  "dependencies": [
    "@xyflow/react",
    "cn",
    "lucide-react"
  ],
  "registryDependencies": [
    "badge"
  ],
  "files": [
    {
      "path": "registry/notra/workflow/components/workflow-status.tsx",
      "content": "import { cn } from \"cn\";\nimport {\n  CheckIcon,\n  CircleDashedIcon,\n  CircleIcon,\n  DicesIcon,\n  HourglassIcon,\n  LoaderCircleIcon,\n  MinusIcon,\n  RulerIcon,\n  XIcon,\n} from \"lucide-react\";\n\nimport { Badge } from \"@/components/ui/badge\";\n\nimport { WORKFLOW_STATUSES } from \"../constants/workflow\";\nimport {\n  WORKFLOW_LED_CLASS,\n  WORKFLOW_PILL_BOTTOM_CLASS,\n  WORKFLOW_PILL_CLASS,\n  WORKFLOW_PILL_TOP_CLASS,\n} from \"../constants/workflow-ui\";\nimport type {\n  WorkflowDeterminismBadgeProps,\n  WorkflowStatusBadgeProps,\n  WorkflowStatusGlyphProps,\n  WorkflowStatusIndicatorProps,\n  WorkflowStatusPillProps,\n} from \"../types/workflow\";\n\nconst StatusGlyph = ({ status }: WorkflowStatusGlyphProps) => {\n  switch (status) {\n    case \"running\": {\n      return <LoaderCircleIcon className=\"size-3.5 animate-spin\" />;\n    }\n    case \"waiting\": {\n      return <HourglassIcon className=\"size-3.5 motion-safe:animate-pulse\" />;\n    }\n    case \"success\": {\n      return <CheckIcon className=\"size-3.5\" strokeWidth={2.5} />;\n    }\n    case \"error\": {\n      return <XIcon className=\"size-3.5\" strokeWidth={2.5} />;\n    }\n    case \"skipped\": {\n      return <MinusIcon className=\"size-3.5\" />;\n    }\n    case \"queued\": {\n      return <CircleDashedIcon className=\"size-3.5\" />;\n    }\n    default: {\n      return <CircleIcon className=\"size-3.5\" />;\n    }\n  }\n};\n\nexport const WorkflowStatusIndicator = ({\n  className,\n  status,\n  ...props\n}: WorkflowStatusIndicatorProps) => (\n  <span\n    className={cn(\n      \"inline-flex size-4 shrink-0 items-center justify-center\",\n      WORKFLOW_STATUSES[status].className,\n      className\n    )}\n    data-slot=\"workflow-status-indicator\"\n    data-status={status}\n    {...props}\n  >\n    <StatusGlyph status={status} />\n    <span className=\"sr-only\">{WORKFLOW_STATUSES[status].label}</span>\n  </span>\n);\n\nexport const WorkflowStatusBadge = ({\n  className,\n  status,\n  ...props\n}: WorkflowStatusBadgeProps) => (\n  <Badge\n    className={cn(\"gap-1 pl-1\", WORKFLOW_STATUSES[status].className, className)}\n    data-slot=\"workflow-status-badge\"\n    data-status={status}\n    variant=\"outline\"\n    {...props}\n  >\n    <StatusGlyph status={status} />\n    {WORKFLOW_STATUSES[status].label}\n  </Badge>\n);\n\nexport const WorkflowDeterminismBadge = ({\n  className,\n  deterministic,\n  ...props\n}: WorkflowDeterminismBadgeProps) => (\n  <Badge\n    className={cn(\n      \"text-muted-foreground gap-1 font-normal\",\n      !deterministic &&\n        \"border-violet-500/30 text-violet-600 dark:text-violet-300\",\n      className\n    )}\n    data-slot=\"workflow-determinism-badge\"\n    title={\n      deterministic\n        ? \"Same input, same output\"\n        : \"Uses a language model, so the output can change between runs\"\n    }\n    variant=\"outline\"\n    {...props}\n  >\n    {deterministic ? <RulerIcon /> : <DicesIcon />}\n    {deterministic ? \"Deterministic\" : \"Non-deterministic\"}\n  </Badge>\n);\n\nexport const WorkflowStatusPill = ({\n  className,\n  status,\n  ...props\n}: WorkflowStatusPillProps) => (\n  <span\n    className={cn(WORKFLOW_PILL_CLASS, className)}\n    data-slot=\"workflow-status-pill\"\n    data-status={status}\n    title={WORKFLOW_STATUSES[status].label}\n    {...props}\n  >\n    <span className={WORKFLOW_PILL_TOP_CLASS}>\n      <span\n        className={cn(\n          WORKFLOW_LED_CLASS,\n          WORKFLOW_STATUSES[status].ledClassName\n        )}\n      />\n    </span>\n    {status !== \"idle\" && (\n      <span className={WORKFLOW_PILL_BOTTOM_CLASS}>\n        <StatusGlyph status={status} />\n      </span>\n    )}\n    <span className=\"sr-only\">{WORKFLOW_STATUSES[status].label}</span>\n  </span>\n);\n",
      "type": "registry:component",
      "target": "components/workflow/components/workflow-status.tsx"
    },
    {
      "path": "registry/notra/workflow/constants/workflow-ui.ts",
      "content": "import type {\n  WorkflowBannerConfig,\n  WorkflowEdgeStatus,\n  WorkflowRunPhase,\n} from \"../types/workflow\";\n\nexport const WORKFLOW_NODE_WIDTH = 256;\n\nexport const WORKFLOW_NODE_DROP_OFFSET_Y = 24;\n\nexport const WORKFLOW_COLUMN = 320;\n\nexport const WORKFLOW_FIT_PADDING = 0.12;\n\nexport const WORKFLOW_FIT_MIN_ZOOM = 0.6;\n\nexport const WORKFLOW_FIT_MAX_ZOOM = 1;\n\nexport const WORKFLOW_FIT_EDGE_PX = 32;\n\nexport const WORKFLOW_FIT_VIEW_OPTIONS = {\n  maxZoom: WORKFLOW_FIT_MAX_ZOOM,\n  padding: WORKFLOW_FIT_PADDING,\n};\n\nexport const WORKFLOW_ZOOM_DURATION_MS = 200;\n\nexport const WORKFLOW_FIT_DURATION_MS = 300;\n\nexport const WORKFLOW_MINIMAP_STYLE = { height: 96, width: 144 };\n\nexport const WORKFLOW_PATTERN_STRENGTH = {\n  cross: 22,\n  dots: 24,\n  gridMajor: 12,\n  gridMinor: 5,\n  lines: 7,\n};\n\nexport const WORKFLOW_PORT_ROW_CLASS =\n  \"text-muted-foreground border-table-card-border relative flex h-7.5 min-w-0 items-center border-t px-3 text-[0.6875rem] font-medium\";\n\nexport const WORKFLOW_CHIP_CLASS =\n  \"bg-foreground/[0.05] text-muted-foreground inline-flex h-5 min-w-0 items-center gap-1 rounded-full px-2 text-[0.6875rem] leading-none tabular-nums [&_svg]:size-3 [&_svg]:shrink-0\";\n\nexport const WORKFLOW_BANNERS: Record<\n  \"error\" | \"waiting\",\n  WorkflowBannerConfig\n> = {\n  error: {\n    className: \"text-red-600 dark:text-red-400\",\n    label: \"Failed\",\n    message: \"Check the run log\",\n  },\n  waiting: {\n    className: \"text-amber-600 dark:text-amber-400\",\n    label: \"Waiting\",\n    message: \"Needs approval\",\n  },\n};\n\nexport const WORKFLOW_PILL_CLASS =\n  \"bg-table-shell border-table-shell-border text-muted-foreground inline-flex h-9 w-7 shrink-0 flex-col overflow-hidden rounded-lg border [&_svg]:size-3\";\n\nexport const WORKFLOW_PILL_TOP_CLASS =\n  \"flex flex-1 items-center justify-center\";\n\nexport const WORKFLOW_PILL_BOTTOM_CLASS =\n  \"border-table-shell-border flex flex-1 items-center justify-center border-t\";\n\nexport const WORKFLOW_LED_CLASS =\n  \"ring-background/60 size-1.5 rounded-full ring-2 transition-colors duration-300\";\n\nexport const WORKFLOW_EDGE_COLOR: Record<WorkflowEdgeStatus, string> = {\n  active: \"text-primary\",\n  done: \"text-primary/70\",\n  idle: \"text-muted-foreground/70\",\n  skipped: \"text-muted-foreground/25\",\n};\n\nexport const WORKFLOW_EDGE_DASH = \"0 10\";\n\nexport const WORKFLOW_EDGE_STEP_OPTIONS = { borderRadius: 24, offset: 24 };\n\nexport const WORKFLOW_EDGE_RADIUS = 24;\n\nexport const WORKFLOW_EDGE_LANE_GAP = 16;\n\nexport const WORKFLOW_RUN_LABELS: Record<WorkflowRunPhase, string> = {\n  done: \"Run again\",\n  idle: \"Run workflow\",\n  running: \"Stop\",\n};\n\nexport const WORKFLOW_RUN_RING_RADIUS = 10;\n\nexport const WORKFLOW_RUN_RING_LENGTH = 2 * Math.PI * WORKFLOW_RUN_RING_RADIUS;\n\nexport const WORKFLOW_SECTION_TITLE_CLASS =\n  \"text-muted-foreground text-[0.6875rem] font-medium tracking-wide uppercase\";\n\nexport const WORKFLOW_EDGE_REVERSE_STYLE = { animationDirection: \"reverse\" };\n\nexport const WORKFLOW_SKIPPED_DIM_CLASS =\n  \"transition-opacity duration-300 group-data-[status=skipped]/node:opacity-45\";\n\nexport const WORKFLOW_BRANCH_RAIL_CLASS =\n  \"border-table-card-border bg-table-card/60 divide-table-card-border mt-0.5 divide-y rounded-[14px] border\";\n\nexport const WORKFLOW_BRANCH_ROW_CLASS =\n  \"relative flex h-10 min-w-0 items-center gap-2.5 px-3\";\n\nexport const WORKFLOW_BRANCH_LED_CLASS =\n  \"size-2 shrink-0 rounded-full ring-2 transition-[background-color,box-shadow,opacity] duration-300\";\n\nexport const WORKFLOW_RULE_TOKEN_CLASS =\n  \"bg-foreground/[0.05] text-foreground/80 inline-flex h-5 max-w-full min-w-0 items-center truncate rounded-md px-1.5 text-[0.6875rem] whitespace-nowrap\";\n",
      "type": "registry:lib",
      "target": "components/workflow/constants/workflow-ui.ts"
    },
    {
      "path": "registry/notra/workflow/constants/workflow.ts",
      "content": "import {\n  FlagIcon,\n  GitForkIcon,\n  HourglassIcon,\n  MailIcon,\n  MergeIcon,\n  PlugIcon,\n  RepeatIcon,\n  SparklesIcon,\n  SplitIcon,\n  SquareFunctionIcon,\n  UserCheckIcon,\n  ZapIcon,\n} from \"lucide-react\";\n\nimport type {\n  WorkflowKindConfig,\n  WorkflowModel,\n  WorkflowNodeKind,\n  WorkflowNodeStatus,\n  WorkflowPort,\n  WorkflowStatusConfig,\n} from \"../types/workflow\";\n\nexport const WORKFLOW_DEFAULT_DURATION_MS = 900;\n\nexport const WORKFLOW_EDGE_TRAVEL_MS = 450;\n\nexport const WORKFLOW_TICK_MS = 50;\n\nexport const WORKFLOW_BLOCK_MIME = \"application/x-workflow-block\";\n\nexport const WORKFLOW_IN_PORT: WorkflowPort = { id: \"in\" };\n\nexport const WORKFLOW_OUT_PORT: WorkflowPort = { id: \"out\" };\n\nexport const WORKFLOW_KINDS: Record<WorkflowNodeKind, WorkflowKindConfig> = {\n  ai: {\n    icon: SparklesIcon,\n    label: \"AI step\",\n    tileClassName:\n      \"bg-violet-500/10 text-violet-600 ring-violet-500/20 dark:text-violet-300\",\n  },\n  approval: {\n    icon: UserCheckIcon,\n    label: \"Human approval\",\n    tileClassName:\n      \"bg-pink-500/10 text-pink-600 ring-pink-500/20 dark:text-pink-300\",\n  },\n  condition: {\n    icon: SplitIcon,\n    label: \"If / else\",\n    tileClassName:\n      \"bg-orange-500/10 text-orange-600 ring-orange-500/20 dark:text-orange-300\",\n  },\n  delay: {\n    icon: HourglassIcon,\n    label: \"Wait\",\n    tileClassName:\n      \"bg-zinc-500/10 text-zinc-600 ring-zinc-500/20 dark:text-zinc-300\",\n  },\n  email: {\n    icon: MailIcon,\n    label: \"Email\",\n    tileClassName:\n      \"bg-emerald-500/10 text-emerald-600 ring-emerald-500/20 dark:text-emerald-300\",\n  },\n  integration: {\n    icon: PlugIcon,\n    label: \"Integration\",\n    tileClassName:\n      \"bg-sky-500/10 text-sky-600 ring-sky-500/20 dark:text-sky-300\",\n  },\n  loop: {\n    icon: RepeatIcon,\n    label: \"For each\",\n    tileClassName:\n      \"bg-indigo-500/10 text-indigo-600 ring-indigo-500/20 dark:text-indigo-300\",\n  },\n  merge: {\n    icon: MergeIcon,\n    label: \"Merge\",\n    tileClassName:\n      \"bg-teal-500/10 text-teal-600 ring-teal-500/20 dark:text-teal-300\",\n  },\n  output: {\n    icon: FlagIcon,\n    label: \"Output\",\n    tileClassName:\n      \"bg-zinc-500/10 text-zinc-600 ring-zinc-500/20 dark:text-zinc-300\",\n  },\n  switch: {\n    icon: GitForkIcon,\n    label: \"Decision\",\n    tileClassName:\n      \"bg-orange-500/10 text-orange-600 ring-orange-500/20 dark:text-orange-300\",\n  },\n  task: {\n    icon: SquareFunctionIcon,\n    label: \"Task\",\n    tileClassName:\n      \"bg-blue-500/10 text-blue-600 ring-blue-500/20 dark:text-blue-300\",\n  },\n  trigger: {\n    icon: ZapIcon,\n    label: \"Trigger\",\n    tileClassName:\n      \"bg-amber-500/10 text-amber-600 ring-amber-500/20 dark:text-amber-300\",\n  },\n};\n\nexport const WORKFLOW_NON_DETERMINISTIC_KINDS: WorkflowNodeKind[] = [\"ai\"];\n\nexport const WORKFLOW_STATUSES: Record<\n  WorkflowNodeStatus,\n  WorkflowStatusConfig\n> = {\n  error: {\n    className: \"text-red-600 dark:text-red-400\",\n    label: \"Failed\",\n    ledClassName: \"bg-red-500 shadow-[0_0_6px_var(--color-red-500)]\",\n  },\n  idle: {\n    className: \"text-muted-foreground\",\n    label: \"Idle\",\n    ledClassName: \"bg-muted-foreground/35\",\n  },\n  queued: {\n    className: \"text-muted-foreground\",\n    label: \"Queued\",\n    ledClassName: \"bg-muted-foreground/35\",\n  },\n  running: {\n    className: \"text-primary\",\n    label: \"Running\",\n    ledClassName:\n      \"bg-primary shadow-[0_0_6px_var(--color-primary,var(--primary))] motion-safe:animate-pulse\",\n  },\n  skipped: {\n    className: \"text-muted-foreground\",\n    label: \"Skipped\",\n    ledClassName: \"bg-muted-foreground/20\",\n  },\n  success: {\n    className: \"text-emerald-600 dark:text-emerald-400\",\n    label: \"Completed\",\n    ledClassName: \"bg-emerald-500 shadow-[0_0_6px_var(--color-emerald-500)]\",\n  },\n  waiting: {\n    className: \"text-amber-600 dark:text-amber-400\",\n    label: \"Waiting for approval\",\n    ledClassName:\n      \"bg-amber-500 shadow-[0_0_6px_var(--color-amber-500)] motion-safe:animate-pulse\",\n  },\n};\n\nexport const WORKFLOW_NODE_RING: Record<WorkflowNodeStatus, string> = {\n  error: \"border-red-500/60\",\n  idle: \"\",\n  queued: \"\",\n  running:\n    \"border-primary shadow-[0_0_0_0.3rem_color-mix(in_oklab,var(--color-primary,var(--primary))_14%,transparent)]\",\n  skipped: \"\",\n  success: \"border-emerald-500/50\",\n  waiting:\n    \"border-amber-500 shadow-[0_0_0_0.3rem_color-mix(in_oklab,var(--color-amber-500)_14%,transparent)]\",\n};\n\nexport const WORKFLOW_MODELS: WorkflowModel[] = [\n  {\n    id: \"claude-opus-5-5\",\n    label: \"Claude Opus 5.5\",\n    logo: \"claude\",\n    provider: \"Anthropic\",\n  },\n  {\n    id: \"claude-sonnet-5-5\",\n    label: \"Claude Sonnet 5.5\",\n    logo: \"claude\",\n    provider: \"Anthropic\",\n  },\n  {\n    id: \"claude-haiku-5-5\",\n    label: \"Claude Haiku 5.5\",\n    logo: \"claude\",\n    provider: \"Anthropic\",\n  },\n  { id: \"gpt-5\", label: \"GPT-5\", logo: \"openai\", provider: \"OpenAI\" },\n  { id: \"gpt-5-mini\", label: \"GPT-5 mini\", logo: \"openai\", provider: \"OpenAI\" },\n  {\n    id: \"gemini-2-5-pro\",\n    label: \"Gemini 2.5 Pro\",\n    logo: \"gemini\",\n    provider: \"Google\",\n  },\n  {\n    id: \"sonar-pro\",\n    label: \"Sonar Pro\",\n    logo: \"perplexity\",\n    provider: \"Perplexity\",\n  },\n  { id: \"grok-4\", label: \"Grok 4\", logo: \"grok\", provider: \"xAI\" },\n  {\n    id: \"mistral-large\",\n    label: \"Mistral Large\",\n    logo: \"mistral\",\n    provider: \"Mistral\",\n  },\n  {\n    id: \"deepseek-v3\",\n    label: \"DeepSeek V3\",\n    logo: \"deepseek\",\n    provider: \"DeepSeek\",\n  },\n];\n",
      "type": "registry:lib",
      "target": "components/workflow/constants/workflow.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"
    }
  ],
  "cssVars": {
    "theme": {
      "color-table-shell": "var(--table-shell)",
      "color-table-shell-border": "var(--table-shell-border)",
      "color-table-card": "var(--table-card)",
      "color-table-card-border": "var(--table-card-border)",
      "color-table-row-border": "var(--table-row-border)",
      "shadow-table-card": "var(--table-card-shadow)"
    },
    "light": {
      "table-shell": "#f3f3f2",
      "table-shell-border": "#e7e7e5",
      "table-card": "#ffffff",
      "table-card-border": "#e5e5e5",
      "table-row-border": "#efefee",
      "table-card-shadow": "0 1px 2px hsl(240 10% 10% / 0.06), 0 2px 8px -2px hsl(240 10% 10% / 0.06)"
    },
    "dark": {
      "table-shell": "#161616",
      "table-shell-border": "#232323",
      "table-card": "#1f1f1f",
      "table-card-border": "#333333",
      "table-row-border": "#292929",
      "table-card-shadow": "inset 0 1px 0 hsl(0 0% 100% / 0.05), inset 0 0 0 1px hsl(0 0% 100% / 0.015), inset 0 12px 18px -16px hsl(0 0% 100% / 0.035)"
    }
  },
  "type": "registry:component"
}