import type { ReactNode } from 'react' import { cn } from '@/lib/utils' import { CollapsibleCard } from '../basic/collapsible-card' import { Button } from '../basic/button' import { IconButton } from '../basic/icon-button' import { FileList2Line, CheckLine, DownloadLine } from '../basic/icons-inline' const ICON_CLASS = 'w-[var(--font-size-sm)] h-[var(--font-size-sm)] shrink-0' export interface PlanPartProps { title?: string description?: string content: string viewText?: string buildText?: string builtText?: string isBuilt?: boolean isGenerating?: boolean onView?: () => void onBuild?: () => void onDownload?: () => void defaultExpanded?: boolean contentMaxHeight?: number collapsible?: boolean className?: string headerIcon?: ReactNode downloadIcon?: ReactNode builtIcon?: ReactNode } const defaultHeaderIcon = const defaultDownloadIcon = const defaultBuiltIcon = export function PlanPart({ title = 'Plan', description, content, viewText = 'View', buildText = 'Build ⌘⏎', builtText = 'Built', isBuilt = false, isGenerating = false, onView, onBuild, onDownload, defaultExpanded = true, contentMaxHeight, collapsible = false, className, headerIcon, downloadIcon, builtIcon, }: PlanPartProps) { const lines = content.split('\n') const hasTitle = lines.length > 1 && lines[1].trim() === '' const contentTitle = hasTitle ? lines[0] : null const contentBody = hasTitle ? lines.slice(2).join('\n') : content return ( {isGenerating ? ( Planning... ) : ( <> {title} {description != null && ( {description} )} )} } titleShimmer={isGenerating} headerRight={ !isGenerating && onDownload ? ( { e.stopPropagation(); onDownload?.() }} title="Download as Markdown" aria-label="Download" className="!min-h-0 !min-w-0 h-[var(--font-size-sm)] w-[var(--font-size-sm)] text-text-secondary hover:text-text [&_svg]:w-[var(--font-size-sm)] [&_svg]:h-[var(--font-size-sm)]" /> ) : undefined } contentPadding="var(--spacing-1\.5) var(--spacing-2)" defaultExpanded={defaultExpanded} contentMaxHeight={contentMaxHeight} collapsible={collapsible} footer={ !isGenerating ? ( <>
{isBuilt ? (
{builtText} {builtIcon ?? defaultBuiltIcon}
) : ( )} ) : undefined } className={className} > {isGenerating ? (
{/* 点阵背景层 - 基础灰色点(与 QodeChatPanel PlanPart 一致) */}
{/* 逐行点亮的点阵层 - 高亮带的竖向移动动画(与 QodeChatPanel 一致) */}
) : (
{contentTitle != null && (
{contentTitle}
)} {contentBody != null && contentBody !== '' && ( {contentBody} )}
)} ) } PlanPart.displayName = 'PlanPart' export const AgentPlanCard = PlanPart export type AgentPlanCardProps = PlanPartProps