import { memo } from "react"; import { Badge } from "~/components/ui/badge"; import { Card, CardContent, CardHeader, CardTitle } from "~/components/ui/card"; /** * Lightweight, dependency‑minimal placeholder for step preview rendering in the * experiment designer. This was added to satisfy references expecting the file * to exist (diagnostics previously reported it missing). * * Replace / extend this component when richer preview logic (block graphs, * parameter summaries, validation states, drift indicators) is implemented. * * Design Goals: * - Zero external (designer-internal) imports to avoid circular dependencies * - Strict typing without leaking un-finalized internal step model types * - Safe rendering even with partial or incomplete data * - Pure presentational; no side-effects or client hooks required */ export interface StepPreviewAction { id?: string; name: string; description?: string | null; type?: string | null; pluginId?: string | null; pluginVersion?: string | null; category?: string | null; } export interface StepPreviewProps { id?: string; name: string; description?: string | null; type?: string | null; orderIndex?: number; required?: boolean; durationEstimateSeconds?: number; actions?: StepPreviewAction[]; conditions?: unknown; validationIssues?: readonly string[]; integrityHashFragment?: string | null; /** * When true, shows a subtle placeholder treatment (e.g. while constructing * from a transient visual design mutation). */ transient?: boolean; } /** * Stateless pure component – safe to use in server or client trees. */ export const StepPreview = memo(function StepPreview({ name, description, type, orderIndex, required, durationEstimateSeconds, actions = [], conditions, validationIssues, integrityHashFragment, transient, }: StepPreviewProps) { const hasIssues = (validationIssues?.length ?? 0) > 0; return (
{orderIndex !== undefined && ( #{orderIndex + 1} )} {name || "(Untitled Step)"} {description && (

{description}

)}
{type && ( {type} )} {required && ( Required )} {hasIssues && ( {validationIssues?.length} Issue {validationIssues && validationIssues.length > 1 ? "s" : ""} )}
{durationEstimateSeconds !== undefined && ( ≈ {Math.max(1, Math.round(durationEstimateSeconds))}s )} {actions.length > 0 && ( {actions.length} action{actions.length > 1 ? "s" : ""} )} {conditions !== undefined && conditions !== null && ( Conditional )} {integrityHashFragment && ( hash:{integrityHashFragment.slice(0, 8)} )} {transient && transient}
{/* Action summary */} {actions.length > 0 && (
    {actions.slice(0, 5).map((a, idx) => (
  1. {a.name} {a.type && ( {a.type} )} {a.pluginId && ( {a.pluginId} {a.pluginVersion && ( @{a.pluginVersion} )} )}
  2. ))} {actions.length > 5 && (
  3. + {actions.length - 5} more…
  4. )}
)} {hasIssues && validationIssues && (
    {validationIssues.slice(0, 3).map((issue, i) => (
  • • {issue}
  • ))} {validationIssues.length > 3 && (
  • + {validationIssues.length - 3} more…
  • )}
)}
); }); export default StepPreview;