import { useState } from 'react' import { ChevronDown, ChevronUp, Info, Table2, Image as ImageIcon } from 'lucide-react' import type { Source } from '../types' interface WhyDrawerProps { sources: Source[] query?: string focusChunkId?: number | null } function relevancePercent(distance: number): number { return Math.max(0, Math.round((1 - distance / 2) * 100)) } function highlightQuery(text: string, query?: string): React.ReactNode { if (!query) return text const words = query .split(/\s+/) .filter((w) => w.length > 2) .map((w) => w.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')) if (words.length === 0) return text const regex = new RegExp(`(${words.join('|')})`, 'gi') const parts = text.split(regex) return parts.map((part, i) => regex.test(part) ? ( {part} ) : ( part ) ) } function ChunkTypeIcon({ type }: { type: string }) { switch (type) { case 'table': return case 'figure': return default: return null } } function ChunkTypeBadge({ type }: { type: string }) { if (type === 'text') return null const label = type === 'table' ? 'Table' : 'Figure' return {label} } export function WhyDrawer({ sources, query, focusChunkId }: WhyDrawerProps) { const [isOpen, setIsOpen] = useState(false) if (sources.length === 0) return null const uniqueFiles = new Set(sources.map((s) => s.source_file)).size const tableCount = sources.filter((s) => s.chunk_type === 'table').length const figureCount = sources.filter((s) => s.chunk_type === 'figure').length return (
{isOpen && (

Used {sources.length} chunks from{' '} {uniqueFiles} document{uniqueFiles !== 1 ? 's' : ''} {tableCount > 0 && ( {tableCount} table{tableCount !== 1 ? 's' : ''} )} {figureCount > 0 && ( {figureCount} figure{figureCount !== 1 ? 's' : ''} )}

{sources.map((source) => (
Chunk #{source.chunk_id} {source.source_file} — {source.section || `Page ${source.page + 1}`} {relevancePercent(source.distance)}% relevant
{/* Render asset preview for tables and figures */} {source.asset_url && (source.chunk_type === 'table' || source.chunk_type === 'figure') && (
{source.section { (e.target as HTMLImageElement).style.display = 'none' }} />
)}

{highlightQuery(source.text_preview, query)}

))}
)}
) }