import React from 'react'; import { ChevronDown, Compass, FileSearch, Megaphone, ScrollText, Sparkles, Target, TrendingUp, UserCheck, Users, Zap, } from 'lucide-react'; import { useTheme } from '../../contexts/ThemeContext'; import type { ActorCard, BehaviorDriverCard, NarrativeCard, PurposeCard, } from './types'; interface CollapsibleProps { title: React.ReactNode; children: React.ReactNode; defaultOpen?: boolean; variant?: 'default' | 'subtle'; } export const InlineCollapsible: React.FC = ({ title, children, defaultOpen = true, variant = 'default' }) => { const { theme } = useTheme(); const isDark = theme === 'dark'; const [open, setOpen] = React.useState(defaultOpen); const wrapperClass = variant === 'subtle' ? `${isDark ? 'border-slate-700/50 bg-slate-900/30' : 'border-gray-100 bg-white/80'}` : `${isDark ? 'border-slate-700/60 bg-slate-800/40' : 'border-red-100 bg-white'}`; return (
{children}
); }; interface CardIndexBadgeProps { index: number; variant: 'purpose' | 'actor' | 'behavior' | 'narrative'; } const VARIANT_COLOR: Record = { purpose: { dark: 'bg-violet-500/20 text-violet-200 border-violet-400/30', light: 'bg-orange-50 text-orange-600 border-orange-200' }, actor: { dark: 'bg-cyan-500/20 text-cyan-200 border-cyan-400/30', light: 'bg-red-50 text-red-600 border-red-200' }, behavior: { dark: 'bg-emerald-500/20 text-emerald-200 border-emerald-400/30', light: 'bg-emerald-50 text-emerald-600 border-emerald-200' }, narrative: { dark: 'bg-amber-500/20 text-amber-200 border-amber-400/30', light: 'bg-amber-50 text-amber-600 border-amber-200' }, }; const CardIndexBadge: React.FC = ({ index, variant }) => { const { theme } = useTheme(); const isDark = theme === 'dark'; const cls = VARIANT_COLOR[variant][isDark ? 'dark' : 'light']; return ( {index.toString().padStart(2, '0')} ); }; export const PurposeCardItem: React.FC<{ card: PurposeCard }> = ({ card }) => { const { theme } = useTheme(); const isDark = theme === 'dark'; return (
{card.title}
理由 {card.reason}
); }; export const ActorCardItem: React.FC<{ card: ActorCard }> = ({ card }) => { const { theme } = useTheme(); const isDark = theme === 'dark'; return (
{card.title}
{card.content}
); }; export const BehaviorCardItem: React.FC<{ card: BehaviorDriverCard }> = ({ card }) => { const { theme } = useTheme(); const isDark = theme === 'dark'; return (
预期行为
{card.expectedBehavior}
驱动因素
{card.driver}
); }; export const NarrativeCardItem: React.FC<{ card: NarrativeCard }> = ({ card }) => { const { theme } = useTheme(); const isDark = theme === 'dark'; return (
{card.title}
理由 {card.reason}
); }; interface GroupHeaderProps { label: string; parentTitle: string; count: number; variant: 'actor' | 'behavior' | 'narrative'; } export const ParentGroupHeader: React.FC = ({ label, parentTitle, count, variant }) => { const { theme } = useTheme(); const isDark = theme === 'dark'; const Icon = variant === 'actor' ? Target : variant === 'behavior' ? Users : Zap; const accent = variant === 'actor' ? (isDark ? 'text-violet-200 bg-violet-500/15 border-violet-400/30' : 'text-orange-600 bg-orange-50 border-orange-200') : variant === 'behavior' ? (isDark ? 'text-cyan-200 bg-cyan-500/15 border-cyan-400/30' : 'text-red-600 bg-red-50 border-red-200') : (isDark ? 'text-emerald-200 bg-emerald-500/15 border-emerald-400/30' : 'text-emerald-600 bg-emerald-50 border-emerald-200'); return (
{label} {parentTitle} · {count} 张
); }; interface ThinkingBlockProps { text: string; loading?: boolean; empty?: string; } export const ThinkingBlock: React.FC = ({ text, loading, empty = '正在生成思考内容...' }) => { const { theme } = useTheme(); const isDark = theme === 'dark'; return (
思考过程 {loading && ( 生成中 )}
{text ? (
          {text}
        
) : (
{empty}
)}
); }; interface StageHeaderProps { title: string; desc?: string; count?: number; loading?: boolean; done?: boolean; icon: React.ComponentType<{ className?: string }>; accent: 'purpose' | 'actor' | 'behavior' | 'narrative'; } const ACCENT_BG: Record = { purpose: { dark: 'bg-violet-500/15 text-violet-200', light: 'bg-orange-50 text-orange-500' }, actor: { dark: 'bg-cyan-500/15 text-cyan-200', light: 'bg-red-50 text-red-500' }, behavior: { dark: 'bg-emerald-500/15 text-emerald-200', light: 'bg-emerald-50 text-emerald-600' }, narrative: { dark: 'bg-amber-500/15 text-amber-200', light: 'bg-amber-50 text-amber-600' }, }; export const StageHeader: React.FC = ({ title, desc, count, loading, done, icon: Icon, accent }) => { const { theme } = useTheme(); const isDark = theme === 'dark'; const cls = ACCENT_BG[accent][isDark ? 'dark' : 'light']; return (
{title} {typeof count === 'number' && ( {count} 张 )} {done && ( 已完成 )} {loading && ( 生成中 )}
{desc && (
{desc}
)}
); }; export const STAGE_ICONS = { purpose: Target, actor: Users, behavior: Zap, narrative: Megaphone, };