import React from 'react'; import { useState } from "react"; // Color palette — each chunk gets a rotating color const CHUNK_COLORS = [ { bg: "bg-blue-100", border: "border-blue-400", text: "text-blue-800", ring: "ring-blue-300" }, { bg: "bg-purple-100",border: "border-purple-400", text: "text-purple-800",ring: "ring-purple-300"}, { bg: "bg-green-100", border: "border-green-400", text: "text-green-800", ring: "ring-green-300" }, { bg: "bg-pink-100", border: "border-pink-400", text: "text-pink-800", ring: "ring-pink-300" }, { bg: "bg-yellow-100",border: "border-yellow-400", text: "text-yellow-800",ring: "ring-yellow-300"}, ]; export default function ChunkVisualizer({ chunks = [], loading, error }) { const [selectedId, setSelectedId] = useState(null); // handle different response shapes from backend const chunkList = Array.isArray(chunks) ? chunks : chunks?.chunks || chunks?.data || []; const selected = chunkList.find((c) => c.id === selectedId); if (loading) { return (

Generating chunks…

); } if (error) { return (

⚠️ Error loading chunks

{error}

); } if (!chunkList.length) { return (

Upload a document and configure chunking to see the preview.

); } return (
{/* ── Left panel: chunk blocks ──────────────────────────── */}

{chunks.length} chunks — click to inspect

{chunks.map((chunk, i) => { const color = CHUNK_COLORS[i % CHUNK_COLORS.length]; const isSelected = chunk.id === selectedId; const hasOverlapPrev = !!chunk.overlap_prev; const hasOverlapNext = !!chunk.overlap_next; return (
setSelectedId(isSelected ? null : chunk.id)}> {/* Overlap indicator — top */} {hasOverlapPrev && (
⟵ {chunk.overlap_prev}ch overlap with previous
)} {/* Chunk block */}
#{chunk.sequence_num + 1} · {chunk.id.slice(0, 6)} {chunk.start_char}–{chunk.end_char}

{chunk.text}

{/* Overlap indicator — bottom */} {hasOverlapNext && (
{chunk.overlap_next}ch overlap with next ⟶
)}
); })}
{/* ── Right panel: selected chunk detail ───────────────── */}
{selected ? ( ) : (
👈

Select a chunk to see details

)}
); } function ChunkDetail({ chunk, index, color }) { const charCount = chunk.end_char - chunk.start_char; const approxTokens = Math.round(charCount / 4); // rough approximation return (

Chunk #{index + 1}

{/* Metadata grid */}
{[ { label: "Chunk ID", value: chunk.id }, { label: "Position", value: `${chunk.start_char} → ${chunk.end_char}` }, { label: "Characters", value: charCount }, { label: "Approx Tokens", value: `~${approxTokens}` }, chunk.overlap_prev && { label: "Overlap Prev", value: `${chunk.overlap_prev}ch` }, chunk.overlap_next && { label: "Overlap Next", value: `${chunk.overlap_next}ch` }, ].filter(Boolean).map(({ label, value }) => (

{label}

{value}

))}
{/* Full text */}

Full Text

{chunk.text}

); }