import { useMemo, useState } from "react"; import { X, Table as TableIcon, FileText } from "lucide-react"; import type { EmbedDataFile } from "../editor/embeds/embed-data-store"; import { formatBytes } from "../utils/data-files"; interface DataFileViewerProps { file: EmbedDataFile; onClose: () => void; } const MAX_PREVIEW_ROWS = 100; function splitCsvLine(line: string, delim: string): string[] { const out: string[] = []; let cur = ""; let inQuotes = false; for (let i = 0; i < line.length; i++) { const c = line[i]; if (inQuotes) { if (c === '"') { if (line[i + 1] === '"') { cur += '"'; i++; } else { inQuotes = false; } } else { cur += c; } } else if (c === '"') { inQuotes = true; } else if (c === delim) { out.push(cur); cur = ""; } else { cur += c; } } out.push(cur); return out; } function parseTable(content: string, delim: string, maxRows: number): { columns: string[]; rows: string[][]; total: number; } { const lines = content.split(/\r\n|\n|\r/).filter((l) => l.length > 0); if (lines.length === 0) return { columns: [], rows: [], total: 0 }; const columns = splitCsvLine(lines[0], delim); const rows = lines .slice(1, 1 + maxRows) .map((l) => splitCsvLine(l, delim)); return { columns, rows, total: Math.max(0, lines.length - 1) }; } function prettyJson(content: string): string { try { return JSON.stringify(JSON.parse(content), null, 2); } catch { return content; } } export function DataFileViewer({ file, onClose }: DataFileViewerProps) { const { ext } = file.meta; const isTabular = ext === "csv" || ext === "tsv"; const [mode, setMode] = useState<"table" | "raw">(isTabular ? "table" : "raw"); const parsed = useMemo(() => { if (!isTabular) return null; return parseTable(file.content, ext === "tsv" ? "\t" : ",", MAX_PREVIEW_ROWS); }, [file.content, ext, isTabular]); const raw = useMemo(() => { if (ext === "json") return prettyJson(file.content); return file.content; }, [file.content, ext]); return (
{file.meta.name} {ext.toUpperCase()} - {formatBytes(file.meta.size)} {file.meta.rowCount !== undefined ? ` - ${file.meta.rowCount} rows` : ""}
{isTabular && (
)}
{isTabular && mode === "table" && parsed ? (
{parsed.columns.map((col, i) => ( ))} {parsed.rows.map((row, ri) => ( {parsed.columns.map((_, ci) => ( ))} ))}
{col}
{row[ci] ?? ""}
{parsed.total > parsed.rows.length && (
Showing first {parsed.rows.length} of {parsed.total} rows
)}
) : (
            {raw}
          
)}
); }