// Column 1 — Project Dataroom. Projects > Folders > Files. const dataroomStyles = { col: { borderRight:'1px solid var(--line)', background:'var(--paper)', display:'flex', flexDirection:'column', minHeight:0 }, head: { padding:'16px 20px 12px 20px', borderBottom:'1px solid var(--line)' }, eyebrow: { fontFamily:'var(--mono)', fontSize:10, letterSpacing:'.16em', color:'var(--ink-3)', textTransform:'uppercase' }, title: { fontFamily:'var(--serif)', fontSize:22, lineHeight:1.1, marginTop:4, color:'var(--ink)' }, sub: { fontSize:11.5, color:'var(--ink-3)', marginTop:4 }, searchWrap: { display:'flex', alignItems:'center', gap:8, height:30, padding:'0 10px', border:'1px solid var(--line-2)', borderRadius:6, background:'var(--paper-2)', marginTop:12, }, searchInput: { border:'none', outline:'none', background:'transparent', fontSize:12, color:'var(--ink)', flex:1, fontFamily:'var(--sans)' }, kbd: { fontFamily:'var(--mono)', fontSize:9.5, color:'var(--ink-4)', padding:'2px 5px', border:'1px solid var(--line-2)', borderRadius:3, background:'var(--paper)' }, scroll: { overflowY:'auto', flex:1, padding:'6px 0 80px 0' }, projHead: (active) => ({ display:'flex', alignItems:'center', gap:8, padding:'10px 16px 6px 16px', background: active ? 'var(--paper-2)' : 'transparent', borderLeft: active ? '2px solid var(--accent)' : '2px solid transparent', cursor:'pointer', }), projMeta: { flex:1, minWidth:0 }, projClient: { fontFamily:'var(--mono)', fontSize:10, letterSpacing:'.1em', color:'var(--ink-3)', textTransform:'uppercase' }, projName: { fontFamily:'var(--serif)', fontSize:15, color:'var(--ink)', marginTop:1, lineHeight:1.2 }, projStatus: (s) => ({ fontFamily:'var(--mono)', fontSize:9.5, letterSpacing:'.08em', textTransform:'uppercase', padding:'2px 6px', border:'1px solid var(--line-2)', borderRadius:999, color:'var(--ink-3)', whiteSpace:'nowrap', }), folder: (active) => ({ display:'flex', alignItems:'center', gap:8, padding:'7px 16px 7px 32px', cursor:'pointer', color:'var(--ink-2)', fontSize:12.5, background: active ? 'rgba(244,81,28,.06)' : 'transparent', }), folderName: { flex:1 }, fileCount: { fontFamily:'var(--mono)', fontSize:10, color:'var(--ink-4)' }, uploadBtn: { marginLeft:8, border:'1px solid var(--line-2)', background:'var(--paper)', borderRadius:4, padding:'1px 6px', fontSize:10, fontFamily:'var(--mono)', color:'var(--ink-3)', cursor:'pointer', letterSpacing:'.06em', }, file: (sel, focused) => ({ display:'grid', gridTemplateColumns:'auto 1fr auto auto', columnGap:10, rowGap:2, alignItems:'center', padding:'8px 16px 8px 48px', cursor:'pointer', background: sel ? 'var(--ink)' : (focused ? 'var(--paper-2)' : 'transparent'), color: sel ? 'var(--paper)' : 'var(--ink)', borderLeft: sel ? '2px solid var(--accent)' : '2px solid transparent', position:'relative', }), fileName: { fontSize:12.5, overflow:'hidden', textOverflow:'ellipsis', whiteSpace:'nowrap' }, fileMeta: { gridColumn:'2 / span 3', fontFamily:'var(--mono)', fontSize:10, color:'inherit', opacity:.6, display:'flex', gap:10 }, kindTag: (sel) => ({ fontFamily:'var(--mono)', fontSize:9, letterSpacing:'.08em', padding:'1.5px 5px', border: sel ? '1px solid rgba(255,255,255,.35)' : '1px solid var(--line-2)', borderRadius:3, color: sel ? 'var(--paper)' : 'var(--ink-3)', opacity: sel ? .8 : 1, }), statusDot: (s, sel) => ({ width:6, height:6, borderRadius:'50%', background: s==='analyzed' ? 'var(--accent-2)' : s==='analyzing' ? 'var(--accent-3)' : s==='queued' ? 'var(--ink-4)' : 'transparent', border: s==='idle' ? `1px solid ${sel ? 'var(--paper)' : 'var(--line-2)'}` : 'none', boxShadow: s==='analyzing' ? '0 0 0 3px rgba(244,81,28,.25)' : 'none', }), fileActions: { display:'flex', gap:4, marginLeft:'auto', opacity:.6 }, fileAct: (sel) => ({ border:'none', background:'transparent', cursor:'pointer', padding:'2px 4px', color: sel ? 'var(--paper)' : 'var(--ink-3)', fontSize:10, fontFamily:'var(--mono)', borderRadius:3, }), analyzeBar: { margin:'12px 16px 4px', padding:'12px', border:'1px dashed var(--line-2)', borderRadius:8, background:'var(--paper-2)', }, analyzeHead: { display:'flex', justifyContent:'space-between', alignItems:'center', marginBottom:6 }, runBtn: { width:'100%', height:34, borderRadius:6, border:'1px solid var(--ink)', background:'var(--ink)', color:'var(--paper)', fontSize:12, cursor:'pointer', marginTop:8, display:'inline-flex', alignItems:'center', justifyContent:'center', gap:6, fontFamily:'var(--sans)', }, newProjBtn: { margin:'14px 16px', height:34, borderRadius:6, border:'1px dashed var(--line-2)', background:'transparent', width:'calc(100% - 32px)', color:'var(--ink-3)', fontSize:12, cursor:'pointer', display:'inline-flex', alignItems:'center', justifyContent:'center', gap:6, }, }; function FolderUpload({ project_id, folder_id, onUpload }) { const ref = React.useRef(); return ( <> { const files = Array.from(e.target.files || []); for (const f of files) { try { await onUpload(folder_id, f); } catch(err) { console.error(err); } } if (ref.current) ref.current.value = ''; }}/> ); } function Dataroom({ projects, activeProjectId, setActiveProjectId, selectedFileId, setSelectedFileId, onNewProject, onUpload, onAnalyzeAll, onAnalyzeFile, onDeleteFile, analyzing, }) { const [openProj, setOpenProj] = React.useState({ [activeProjectId]: true }); const [openFolder, setOpenFolder] = React.useState({}); const [query, setQuery] = React.useState(''); const totalFiles = projects.flatMap(p => p.folders || []).flatMap(f => f.files || []).length; const activeProject = projects.find(p => p.id === activeProjectId); const todoCount = (activeProject?.folders || []).flatMap(f => f.files).filter(f => f.status !== 'analyzed').length; const matches = (file) => !query || file.name.toLowerCase().includes(query.toLowerCase()); return (
01 · Project Dataroom
Sources
RFPs, references, meeting notes, ideation — any format.
setQuery(e.target.value)}/> ⌘K
{projects.map(p => { const isActive = p.id === activeProjectId; const isOpen = openProj[p.id] ?? isActive; return (
{ setActiveProjectId(p.id); setOpenProj({...openProj, [p.id]: !isOpen}); }}>
{p.client}
{p.name}
{p.status || '—'}
{isOpen && (p.folders || []).map(f => { const fOpen = openFolder[f.id] ?? true; return (
setOpenFolder({...openFolder, [f.id]: !fOpen}) }> {fOpen ? : } {f.name} {f.files.length} {isActive && }
{fOpen && (f.files || []).filter(matches).map(file => { const sel = file.id === selectedFileId; const Kind = kindIcon(file.kind); const isAnalyzing = analyzing[file.id] || file.status === 'analyzing'; const displayStatus = isAnalyzing ? 'analyzing' : file.status || 'idle'; return (
{ setActiveProjectId(p.id); setSelectedFileId(file.id); }}> {file.name} {kindLabel(file.kind)}
{file.size}·{file.date} {file.duration && <>·{file.duration}} {file.pages && <>·{file.pages}p}
); })}
); })} {isActive && (
Batch {(p.folders || []).flatMap(f => f.files).length} files · {todoCount} queued
Agent A extracts summary & concept-ladder keywords per file.
)}
); })}
); } window.Dataroom = Dataroom;