ELNOR REPO READER TEXT MIRROR Original path: Design Mockups/Archived Mockups/DOC20 Mockups and Design/DOC20 Archived Mockups/Q_UNIFIED_WORKSPACE_V6old.jsx Source repo: /Users/OpenClaw1/Elnor/Elnor Specs Git branch: main Git commit: dbaa25962edc11ab30e8d4ca1715f9ae5bf77331 Generated: 2026-06-09T01:23:58.539Z --- import { useState, useRef, useEffect, useMemo, useCallback } from "react"; const font={sans:"'Söhne','Helvetica Neue',-apple-system,BlinkMacSystemFont,sans-serif"}; const R={sm:"6px",md:"10px",full:"9999px"}; const c={bgApp:"#F8F8F6",bgPanel:"#FFFFFF",bgPanelAlt:"#F9FAFB",bgCard:"#FFFFFF",bgInput:"#EFF1F3",bgSidebar:"#131820",textPri:"#1A1D21",textSec:"#5E6570",textTer:"#8B919A",accentBtn:"#31588c",warn:"#D97706",error:"#B04040",border:"#E0E2E5",borderLight:"#ECEEF0",green:"#2E8B57",neutral:"#6B7280",agentAv:"#a1a7aa",borderDark:"#263040",purple:"#7C3AED"}; const Ic=({d,size=18,color,sw=1.75})=>; const I={Search:p=>,Plus:p=>,ChevR:p=>,ChevD:p=>,Pin:p=>,Folder:p=>,File:p=>,X:p=>,Check:p=>,Save:p=>,Trash:p=>,Copy:p=>,Link:p=>,Maximize:p=>,Spark:p=>,MsgCircle:p=>,Undo:p=>,Redo:p=>,Eye:p=>,Edit:p=>,FileText:p=>,ExtLink:p=>,Printer:p=>,Clock:p=>,ArrowL:p=>,ArrowR:p=>,Refresh:p=>,Star:p=>,Lock:p=>,Book:p=>,Scissors:p=>,Globe:p=>,Settings:p=>,Grid:p=>,Download:p=>,List:p=>,Bell:p=>,Zap:p=>,Sun:p=>,Mail:p=>,Calendar:p=>,Mask:p=>,Grip:p=>,Sidebar:p=>,Paperclip:p=>,Compass:p=>,Users:p=>,Database:p=>,Layers:p=>,User:p=>}; const Dot=({color,size=8})=>; const Toast=({msg,onDone})=>{useEffect(()=>{const t=setTimeout(onDone,2200);return()=>clearTimeout(t)},[onDone]);return
{msg}
}; const TBtn=({icon,title,active,onClick,label,dropdown})=>; const Sep=()=>
; const Btn=({children,primary,ghost,small,onClick,disabled,style:s})=>; const Av=({letter,color,size=20})=>
{letter}
; const DItem=({children,onClick,active,disabled})=>; const Radio=({selected,label,desc,onClick,disabled})=>; // ═══ DATA ═══ const agentName="Elnor"; const agents=[{name:"Elnor",color:c.agentAv,letter:"E"},{name:"Scout",color:"#5B5F97",letter:"S"}]; const tabColors={note:"#31588c",doc:"#2E8B57",web:"#D97706",clips:"#7C3AED",chat:"#2E8B57",room:"#6366F1",task:"#D97706",utility:c.neutral}; const groupColors=["#EF4444","#F97316","#22C55E","#3B82F6","#8B5CF6","#6B7280"]; const scopeFams=["Collection","Project","Bucket","Places","Folders","Saved Views","Notes"]; const typeChips=["Document","Chat","Preset","Skill","Task","Agent","Overlay","Note","Artifact","Prompt","Template","Chain","Memory","Room","Bookmark"]; const projects=[{id:1,name:"Paramount v. City of LA",color:"#31588c"},{id:2,name:"White v. Brooge Energy",color:"#2E8B57"},{id:3,name:"Internal Ops",color:"#8B7355"}]; const collections=[{name:"Priority",color:"#B04040"},{name:"Research",color:"#2E8B57"},{name:"Draft",color:"#D97706"},{name:"Archive",color:"#6B7280"},{name:"Reference",color:"#5B5F97"}]; const allItems=[{type:"Note",title:"Today — April 4, 2026",time:"2h",pin:true,proj:1},{type:"Doc",title:"Sanli Expert Report.pdf",time:"10m",proj:1},{type:"Artifact",title:"Motion in Limine No. 3",time:"1d",proj:1},{type:"Chat",title:"Paramount damages",time:"1h",proj:1},{type:"Task",title:"Review Sanli depo",time:"2h",proj:1,st:"running"},{type:"Note",title:"Brooge Loss Causation",time:"1d",proj:2},{type:"Doc",title:"Christensen_CV.pdf",time:"1d",proj:1},{type:"Preset",title:"Legal Brief Review",time:"1w",proj:null}]; const timeVal=t=>{if(t.includes("m"))return parseInt(t);if(t.includes("h"))return parseInt(t)*60;if(t.includes("d"))return parseInt(t)*1440;if(t.includes("w"))return parseInt(t)*10080;return 99999}; const recentConvos=[{id:"cv1",name:"Paramount damages strategy",color:c.accentBtn,time:"1h",starred:true},{id:"cv2",name:"Brooge loss causation",color:c.green,time:"3h",starred:true},{id:"cv3",name:"Expert depo prep",color:c.warn,time:"1d"},{id:"cv4",name:"Trial brief §III draft",color:c.accentBtn,time:"1d"},{id:"cv5",name:"Signage rights research",color:"#5B5F97",time:"2d"},{id:"cv6",name:"Patent landscape scan",color:c.green,time:"3d"}]; const navPages=[{id:"tasks",icon:,label:"Tasks"},{id:"projects",icon:,label:"Projects"},{id:"knowledge",icon:,label:"Knowledge Manager"},{id:"forums",icon:,label:"Forums & Panels"},{id:"agents",icon:,label:"Agents"},{id:"skills",icon:,label:"Skills & Connectors"},{id:"overlays",icon:,label:"Overlays & Prompts"},{id:"buckets",icon:,label:"Context Buckets"},{id:"settings",icon:,label:"Settings"}]; const initTabs=[ {id:"t1",type:"note",icon:"📝",title:"Today — April 4, 2026",color:tabColors.note,group:"g1"}, {id:"t2",type:"doc",icon:"📄",title:"Sanli Expert Report.pdf",color:tabColors.doc}, {id:"t3",type:"web",icon:"🌐",title:"Paramount MIL — PACER",color:tabColors.web,group:"g1"}, {id:"t4",type:"clips",icon:"✂️",title:"Clips: 4.4-1",color:tabColors.clips}, {id:"t5",type:"chat",icon:"💬",title:"Paramount damages",color:tabColors.chat}, ]; const initGroups=[{id:"g1",label:"Paramount Research",color:"#22C55E",collapsed:false}]; const initComments=[{id:"c1",author:"You",color:c.accentBtn,body:"Verify Sanli's 18% discount rate.",time:"10m ago",status:"open",anchor:"discount rate of 18%",replies:[{id:"r1",author:agentName,color:c.agentAv,body:"Found 3 comparables: avg 8-12%. Sanli's 18% unsupported.",time:"5m ago"}]},{id:"c2",author:"You",color:c.accentBtn,body:"Cross-ref Christensen methodology.",time:"8m ago",status:"open",anchor:"willing buyer-willing seller",replies:[]},{id:"c3",author:agentName,color:c.agentAv,body:"Sargon gatekeeper in §II.",time:"6m ago",status:"resolved",anchor:"Legal Standard",replies:[]}]; // ═══ MAIN ═══ export default function UnifiedWorkspaceV6(){ const [tabs,setTabs]=useState(initTabs);const [tabGroups,setTabGroups]=useState(initGroups); const [activeTabId,setActiveTabId]=useState("t1");const [selectedTabs,setSelectedTabs]=useState(new Set()); const [tabContextMenu,setTabContextMenu]=useState(null);const [newTabDrop,setNewTabDrop]=useState(false); const [dragTabId,setDragTabId]=useState(null);const [groupCtx,setGroupCtx]=useState(null); const [browserOpen,setBrowserOpen]=useState(true);const [browserWidth,setBrowserWidth]=useState(280); const [browserMode,setBrowserMode]=useState("nav"); // nav|browser|notes|web const [activeScope,setActiveScope]=useState(null);const [activeProjIdx,setActiveProjIdx]=useState(0); const [activeTypes,setActiveTypes]=useState(new Set());const [selectedCollections,setSelectedCollections]=useState(new Set()); const [sortKey,setSortKey]=useState("Modified");const [sortDrop,setSortDrop]=useState(false); const [selectedIdx,setSelectedIdx]=useState(null); const [noteSearch,setNoteSearch]=useState(""); const [noteExpandedFolders,setNoteExpandedFolders]=useState(new Set(["nf1"])); const [selectedNote,setSelectedNote]=useState("n1"); const [rightOpen,setRightOpen]=useState(false);const [rightTab,setRightTab]=useState("comments");const [rightWidth,setRightWidth]=useState(290); const [chatColumnOpen,setChatColumnOpen]=useState(false); // Separate right chat column const [comments,setComments]=useState(initComments);const [activeComment,setActiveComment]=useState(null); const [replyingTo,setReplyingTo]=useState(null);const [replyText,setReplyText]=useState(""); const [newCm,setNewCm]=useState(null);const [newCmText,setNewCmText]=useState(""); const [agentIdx,setAgentIdx]=useState(0);const [agentDrop,setAgentDrop]=useState(false); const [instruction,setInstruction]=useState(""); const [agentResponse,setAgentResponse]=useState(null); // Inline response in Ask panel const [showMarkup,setShowMarkup]=useState(true);const [findBar,setFindBar]=useState(false); const [pinned,setPinned]=useState(false);const [bookmarked,setBookmarked]=useState(false);const [readerMode,setReaderMode]=useState(false); const [openDrop,setOpenDrop]=useState(null);const [bubbleMenu,setBubbleMenu]=useState(null); const [showDownloads,setShowDownloads]=useState(false); const [sessionMinutes,setSessionMinutes]=useState(47);const [clipsCount,setClipsCount]=useState(2); const [toast,setToast]=useState(null); const editorRef=useRef(null);const cmRef=useRef(null); const flash=msg=>setToast(msg);const agent=agents[agentIdx]; const activeTab=tabs.find(t=>t.id===activeTabId)||tabs[0]; const openC=comments.filter(x=>x.status==="open");const resolvedC=comments.filter(x=>x.status==="resolved"); const isNoteType=activeTab.type==="note"||activeTab.type==="clips"; useEffect(()=>{const iv=setInterval(()=>setSessionMinutes(m=>m+1),60000);return()=>clearInterval(iv)},[]); useEffect(()=>{if(activeTab.type==="note"||activeTab.type==="clips")setBrowserMode("notes");else if(activeTab.type==="web")setBrowserMode("web");else if(activeTab.type==="chat"||activeTab.type==="utility")setBrowserMode("nav");else setBrowserMode("browser")},[activeTabId]); useEffect(()=>{setActiveComment(null);setReplyingTo(null);setNewCm(null);setAgentResponse(null)},[activeTabId]); const toggleType=t=>{const s=new Set(activeTypes);s.has(t)?s.delete(t):s.add(t);setActiveTypes(s)}; const toggleCollection=n=>{const s=new Set(selectedCollections);s.has(n)?s.delete(n):s.add(n);setSelectedCollections(s)}; const filtered=useMemo(()=>{let items=[...allItems];if(activeScope==="Project")items=items.filter(it=>it.proj===projects[activeProjIdx].id);if(selectedCollections.size>0)items=items.filter(it=>it.cols?.some(col=>selectedCollections.has(col)));if(activeTypes.size>0)items=items.filter(it=>activeTypes.has(it.type));if(sortKey==="Alphabetical")items.sort((a,b)=>a.title.localeCompare(b.title));else items.sort((a,b)=>timeVal(a.time)-timeVal(b.time));return [...items.filter(x=>x.pin),...items.filter(x=>!x.pin)]},[activeScope,activeProjIdx,selectedCollections,activeTypes,sortKey]); const addReply=cmId=>{if(!replyText.trim())return;setComments(p=>p.map(cm=>cm.id===cmId?{...cm,replies:[...cm.replies,{id:"r"+Date.now(),author:"You",color:c.accentBtn,body:replyText.trim(),time:"just now"}]}:cm));setReplyingTo(null);setReplyText("")}; const resolveComment=id=>setComments(p=>p.map(cm=>cm.id===id?{...cm,status:"resolved"}:cm)); const reopenComment=id=>setComments(p=>p.map(cm=>cm.id===id?{...cm,status:"open"}:cm)); const addComment=()=>{if(!newCmText.trim())return;setComments(p=>[...p,{id:"c"+Date.now(),author:"You",color:c.accentBtn,body:newCmText.trim(),time:"just now",status:"open",anchor:newCm?.text||null,replies:[]}]);setNewCm(null);setNewCmText("")}; // Tab management const closeTab=id=>{if(tabs.length<=1)return;const idx=tabs.findIndex(t=>t.id===id);setTabs(p=>p.filter(t=>t.id!==id));if(activeTabId===id){const next=tabs[idx===0?1:idx-1];if(next)setActiveTabId(next.id)}}; const openTab=(type,title,icon,extra={})=>{ // Duplicate prevention const existing=tabs.find(t=>t.title===title&&t.type===type); if(existing){setActiveTabId(existing.id);flash("Already open — switched to tab");return} // Close existing transient utility tab if(type==="utility"){const old=tabs.find(t=>t.type==="utility"&&!t.pinned);if(old)setTabs(p=>p.filter(t=>t.id!==old.id))} const id="t"+Date.now();setTabs(p=>[...p,{id,type,icon,title,color:tabColors[type]||c.neutral,...extra}]);setActiveTabId(id);setNewTabDrop(false)}; // Auto-close transient tab when switching away useEffect(()=>{const prev=tabs.find(t=>t.type==="utility"&&!t.pinned&&t.id!==activeTabId);if(prev&&activeTab.type!=="utility")setTabs(p=>p.filter(t=>t.id!==prev.id))},[activeTabId]); const handleTabDrop=targetId=>{if(!dragTabId||dragTabId===targetId)return;setTabs(prev=>{const d=prev.find(t=>t.id===dragTabId);const r=prev.filter(t=>t.id!==dragTabId);const ti=r.findIndex(t=>t.id===targetId);return [...r.slice(0,ti),d,...r.slice(ti)]});setDragTabId(null)}; const handleMouseUp=useCallback(e=>{if(e.target.closest("[data-bubble]"))return;const sel=window.getSelection();if(!sel||sel.isCollapsed||!sel.toString().trim()){setBubbleMenu(null);return}const text=sel.toString().trim();if(text.length<3)return;const rect=sel.getRangeAt(0).getBoundingClientRect();const er=editorRef.current?.getBoundingClientRect();if(!er)return;setBubbleMenu({x:rect.left-er.left+rect.width/2,y:rect.top-er.top-8,text})},[]); const dismissBubble=()=>{setBubbleMenu(null);window.getSelection()?.removeAllRanges()}; const sendToAgent=()=>{if(!instruction.trim())return;setAgentResponse({text:`Based on my analysis of "${activeTab.title}", the key points are: The discount rate of 18% used by Dr. Sanli has no support in comparable transaction data. Three comparable signage transactions show average rates of 8-12%. This significantly weakens the defense's damages calculation.`,time:"just now"});setInstruction("")}; // CmCard const CmCard=({cm,resolved})=>{const isAct=activeComment===cm.id;return
setActiveComment(isAct?null:cm.id)}>
{cm.anchor&&
"{cm.anchor.slice(0,55)}"
}
{cm.author}{cm.time}
{cm.body}
e.stopPropagation()}> {!resolved&&{setReplyingTo(replyingTo===cm.id?null:cm.id);setReplyText("")}}>Reply} {!resolved&&resolveComment(cm.id)}>Resolve} {resolved&&reopenComment(cm.id)}>Reopen} {cm.author==="You"&&Edit} {cm.author==="You"&&Delete} flash(`Sent to ${agent.name}`)} style={{cursor:"pointer",display:"flex",alignItems:"center",gap:2,color:c.textSec,fontWeight:600,fontSize:10}} onMouseEnter={e=>e.currentTarget.style.color=c.accentBtn} onMouseLeave={e=>e.currentTarget.style.color=c.textSec}>Send
{cm.replies.map(r=>
{r.author}{r.time}
{r.body}
)} {replyingTo===cm.id&&
e.stopPropagation()}>