};
export default function WorkspaceV5(){
const idC=useRef(500);const nid=()=>"x"+(++idC.current);
const [browserOpen,setBrowserOpen]=useState(false);
const [commentsOpen,setCommentsOpen]=useState(false);
const [rightTab,setRightTab]=useState("comments");
const [showMarkup,setShowMarkup]=useState(true);
const [findBar,setFindBar]=useState(false);
const [fullScreen,setFullScreen]=useState(false);
const [openDrop,setOpenDrop]=useState(null);
const [toast,setToast]=useState(null);
const [blocks,setBlocks]=useState(initBlocks);
const [expandedTask,setExpandedTask]=useState(null);
const [threadReplyId,setThreadReplyId]=useState(null);
const [threadReplyText,setThreadReplyText]=useState("");
const [newTaskText,setNewTaskText]=useState("");
const [newSubText,setNewSubText]=useState({});
const [collapsedFeeds,setCollapsedFeeds]=useState(new Set());
const [editingTitle,setEditingTitle]=useState(null);
// Module picker state
const [insertionPoint,setInsertionPoint]=useState(null);
const [pickerOpen,setPickerOpen]=useState(false);
const [pickerStep,setPickerStep]=useState("choose"); // "choose" | "feed_presets" | "feed_custom"
const [pickerTab,setPickerTab]=useState("system");
const [customName,setCustomName]=useState("");
const [customInstruction,setCustomInstruction]=useState("");
const editorRef=useRef(null);const agent=agents[0];const flash=msg=>setToast(msg);
const toggleBlock=(id)=>setBlocks(p=>p.map(b=>b.id===id?{...b,collapsed:!b.collapsed}:b));
const toggleTask=(bid,tid)=>setBlocks(p=>p.map(b=>b.id===bid?{...b,tasks:b.tasks.map(t=>t.id===tid?{...t,done:!t.done}:t)}:b));
const toggleSub=(bid,tid,sid)=>setBlocks(p=>p.map(b=>b.id===bid?{...b,tasks:b.tasks.map(t=>t.id===tid?{...t,sub:t.sub.map(s=>s.id===sid?{...s,done:!s.done}:s)}:t)}:b));
const deleteBlock=id=>setBlocks(p=>p.filter(b=>b.id!==id));
const toggleFeedSection=key=>{const s=new Set(collapsedFeeds);s.has(key)?s.delete(key):s.add(key);setCollapsedFeeds(s)};
const addTask=(bid,text)=>{if(!text.trim())return;setBlocks(p=>p.map(b=>b.id===bid?{...b,tasks:[...b.tasks,{id:nid(),text:text.trim(),done:false,sub:[]}]}:b));setNewTaskText("")};
const addSubtask=(bid,tid,text)=>{if(!text.trim())return;setBlocks(p=>p.map(b=>b.id===bid?{...b,tasks:b.tasks.map(t=>t.id===tid?{...t,sub:[...t.sub,{id:nid(),text:text.trim(),done:false}]}:t)}:b));setNewSubText(p=>({...p,[tid]:""}))};
const addThreadReply=(bid)=>{if(!threadReplyText.trim())return;setBlocks(p=>p.map(b=>b.id===bid?{...b,messages:[...b.messages,{id:nid(),author:"You",color:c.accentBtn,body:threadReplyText.trim(),time:"now"}]}:b));setThreadReplyId(null);setThreadReplyText("")};
// Insert block at end (toolbar button inserts at cursor position in real impl)
const insertBlock=(type,preset)=>{
const newId=nid();let block;
if(type==="tasks")block={id:newId,type:"tasks",title:"New Task List",collapsed:false,tasks:[]};
else if(type==="feed"){
const p=preset||{name:"Custom Feed",sections:[]};
block={id:newId,type:"feed",title:p.name,collapsed:false,preset:p.id,sections:
p.id==="fp1"?[{key:"activity",icon:"spark",label:"Activity",items:[{text:"Waiting for events…",time:"now"}]}]:
p.id==="fp2"?[{key:"notices",icon:"bell",label:"Notices",items:[{text:"No active notices",time:"now"}]}]:
p.id==="fp5"?[{key:"morning",icon:"sun",label:"Summary",items:[{text:"Generating morning brief…",time:"now"}]}]:
[{key:"custom",icon:"spark",label:p.name,items:[{text:"Configure this feed via the gear icon or @Elnor",time:"now"}]}]
};
}
else if(type==="thread")block={id:newId,type:"thread",collapsed:false,contextQuote:"",messages:[{id:nid(),author:"You",color:c.accentBtn,body:"@Elnor ",time:"now"}]};
else if(type==="bar")block={id:newId,type:"bar",title:"New notice — click Elnor to configure",accent:c.warn};
else return;
setBlocks(p=>{let pos=p.length;if(insertionPoint){const idx=p.findIndex(b=>b.id===insertionPoint);if(idx>=0)pos=idx+1}else{const lastTextIdx=p.map((b,i)=>b.type==="text"?i:-1).filter(i=>i>=0).pop();if(lastTextIdx!==undefined)pos=lastTextIdx}return [...p.slice(0,pos),block,...p.slice(pos)]});
setPickerOpen(false);setPickerStep("choose");
flash(`${type==="feed"?(preset?.name||"Feed"):type} block added`);
};
const DragHandle=()=>e.currentTarget.style.opacity=0.55} onMouseLeave={e=>e.currentTarget.style.opacity=0.18}>
;
const renderBlock=(block)=>{
// BAR
if(block.type==="bar") return
{block.title}
{block.time&&{block.time} }
flash(`Opening chat with ref to block:${block.id}`)} title="Ask Elnor" style={{padding:"2px 7px",borderRadius:R.sm,border:`1px solid ${c.agentAv}40`,backgroundColor:c.agentAv+"10",cursor:"pointer",display:"flex",alignItems:"center",gap:3,fontSize:10,fontFamily:font.sans,color:c.agentAv,fontWeight:600}}>Elnor
deleteBlock(block.id)} style={{border:"none",background:"none",cursor:"pointer",padding:1,display:"flex",color:c.textTer}} onMouseEnter={e=>e.currentTarget.style.color=c.error} onMouseLeave={e=>e.currentTarget.style.color=c.textTer}>
;
// TEXT
if(block.type==="text") return setInsertionPoint(block.id)} style={{display:"flex",alignItems:"flex-start",margin:"4px 0",position:"relative",borderLeft:insertionPoint===block.id?`2px solid ${c.accentBtn}`:"2px solid transparent",paddingLeft:insertionPoint===block.id?4:0,transition:"all 0.1s"}} onMouseEnter={e=>{const d=e.currentTarget.querySelector("[data-del]");if(d)d.style.opacity=0.4}} onMouseLeave={e=>{const d=e.currentTarget.querySelector("[data-del]");if(d)d.style.opacity=0}}>
{block.content||"Type here… @Elnor to ask, /todo /feed /ask for modules"}
deleteBlock(block.id)} style={{opacity:0,border:"none",background:"none",cursor:"pointer",padding:2,display:"flex",color:c.textTer,flexShrink:0,marginTop:6,transition:"opacity 0.1s"}}>
;
// TASKS
if(block.type==="tasks"){
const active=block.tasks.filter(t=>!t.done);const done=block.tasks.filter(t=>t.done);
if(block.collapsed) return toggleBlock(block.id)} style={{display:"flex",alignItems:"center",gap:6,padding:"6px 10px",borderRadius:R.sm,border:`1px solid ${c.borderLight}`,backgroundColor:c.bgPanelAlt,cursor:"pointer"}}>{block.title} {active.length} open {e.stopPropagation();deleteBlock(block.id)}} style={{border:"none",background:"none",cursor:"pointer",padding:1,display:"flex",color:c.textTer}} onMouseEnter={e=>e.currentTarget.style.color=c.error} onMouseLeave={e=>e.currentTarget.style.color=c.textTer}>
;
return
toggleBlock(block.id)} style={{display:"flex",alignItems:"center",gap:6,padding:"7px 10px",backgroundColor:c.bgPanelAlt,cursor:"pointer",borderBottom:`1px solid ${c.borderLight}`}}>
{editingTitle===block.id? {setBlocks(p=>p.map(b=>b.id===block.id?{...b,title:e.target.value||block.title}:b));setEditingTitle(null)}} onKeyDown={e=>{if(e.key==="Enter"){setBlocks(p=>p.map(b=>b.id===block.id?{...b,title:e.target.value||block.title}:b));setEditingTitle(null)}if(e.key==="Escape")setEditingTitle(null)}} onClick={e=>e.stopPropagation()} style={{flex:1,fontSize:12.5,fontWeight:700,border:`1px solid ${c.accentBtn}40`,borderRadius:3,padding:"1px 6px",outline:"none",fontFamily:font.sans,backgroundColor:c.bgCard}}/>
:{e.stopPropagation();setEditingTitle(block.id)}}>{block.title} }
{active.length} open
{e.stopPropagation();flash("Configure…")}} style={{border:"none",background:"none",cursor:"pointer",padding:1,display:"flex",color:c.textTer}}>
{e.stopPropagation();deleteBlock(block.id)}} style={{border:"none",background:"none",cursor:"pointer",padding:1,display:"flex",color:c.textTer}} onMouseEnter={e=>e.currentTarget.style.color=c.error} onMouseLeave={e=>e.currentTarget.style.color=c.textTer}>
{active.map(task=>
setExpandedTask(expandedTask===task.id?null:task.id)}>
toggleTask(block.id,task.id)} onClick={e=>e.stopPropagation()} style={{width:15,height:15,accentColor:c.accentBtn,flexShrink:0}}/>
{task.text}
{task.due&&
{task.due} }
{task.link&&
{e.stopPropagation();flash(`Open "${task.link}"`)}}>Note }
{task.sub?.length>0&&
{task.sub.filter(s=>s.done).length}/{task.sub.length} }
{expandedTask===task.id&&
{task.sub?.map(s=>
toggleSub(block.id,task.id,s.id)} style={{width:13,height:13,accentColor:c.accentBtn}}/>
{s.text}
)}
setNewSubText(p=>({...p,[task.id]:e.target.value}))} placeholder="Add subtask…" onKeyDown={e=>{if(e.key==="Enter")addSubtask(block.id,task.id,newSubText[task.id]||"")}} style={{flex:1,border:"none",borderBottom:`1px solid ${c.borderLight}`,outline:"none",fontSize:12,fontFamily:font.sans,color:c.textPri,backgroundColor:"transparent",padding:"2px 0"}}/>
flash("@Elnor…")}>@Elnor
flash(task.link?`Open "${task.link}"`:"Link note…")}>{task.link?"Open Note":"Link Note"}
}
)}
setNewTaskText(e.target.value)} placeholder="Add task…" onKeyDown={e=>{if(e.key==="Enter")addTask(block.id,newTaskText)}} style={{flex:1,border:"none",borderBottom:`1px solid ${c.borderLight}`,outline:"none",fontSize:14.5,fontFamily:font.sans,color:c.textPri,backgroundColor:"transparent",padding:"2px 0"}}/>
{done.length>0&&
Done ({done.length})
{done.map(t=> toggleTask(block.id,t.id)} style={{width:14,height:14,accentColor:c.accentBtn}}/>{t.text}
)}
}
;
}
// FEED
if(block.type==="feed"){
const totalItems=block.sections.reduce((a,s)=>a+s.items.length,0);
if(block.collapsed) return toggleBlock(block.id)} style={{display:"flex",alignItems:"center",gap:6,padding:"6px 10px",borderRadius:R.sm,border:`1px solid ${c.borderLight}`,backgroundColor:c.bgPanelAlt,cursor:"pointer"}}>{block.title} ● live {totalItems} {e.stopPropagation();deleteBlock(block.id)}} style={{border:"none",background:"none",cursor:"pointer",padding:1,display:"flex",color:c.textTer}} onMouseEnter={e=>e.currentTarget.style.color=c.error} onMouseLeave={e=>e.currentTarget.style.color=c.textTer}>
;
return
toggleBlock(block.id)} style={{display:"flex",alignItems:"center",gap:6,padding:"7px 10px",backgroundColor:c.bgPanelAlt,cursor:"pointer",borderBottom:`1px solid ${c.borderLight}`}}>
{editingTitle===block.id? {setBlocks(p=>p.map(b=>b.id===block.id?{...b,title:e.target.value||block.title}:b));setEditingTitle(null)}} onKeyDown={e=>{if(e.key==="Enter"){setBlocks(p=>p.map(b=>b.id===block.id?{...b,title:e.target.value||block.title}:b));setEditingTitle(null)}if(e.key==="Escape")setEditingTitle(null)}} onClick={e=>e.stopPropagation()} style={{flex:1,fontSize:12.5,fontWeight:700,border:`1px solid ${c.accentBtn}40`,borderRadius:3,padding:"1px 6px",outline:"none",fontFamily:font.sans,backgroundColor:c.bgCard}}/>
:{e.stopPropagation();setEditingTitle(block.id)}}>{block.title} }
● auto-updating
{totalItems}
{e.stopPropagation();flash("Configure…")}} style={{border:"none",background:"none",cursor:"pointer",padding:1,display:"flex",color:c.textTer}}>
{e.stopPropagation();deleteBlock(block.id)}} style={{border:"none",background:"none",cursor:"pointer",padding:1,display:"flex",color:c.textTer}} onMouseEnter={e=>e.currentTarget.style.color=c.error} onMouseLeave={e=>e.currentTarget.style.color=c.textTer}>
{block.sections.map(sec=>
toggleFeedSection(sec.key)} style={{display:"flex",alignItems:"center",gap:5,padding:"3px 4px",cursor:"pointer"}}>
{feedIcons[sec.icon]||
}{sec.label} ({sec.items.length})
{!collapsedFeeds.has(sec.key)&&sec.items.map((item,i)=>
▹
{item.accent&&}
{item.text}
{item.time}
)}
)}
;
}
// THREAD
if(block.type==="thread"){
if(block.collapsed) return toggleBlock(block.id)} style={{display:"flex",alignItems:"center",gap:6,padding:"6px 10px",borderRadius:R.sm,border:`1px solid ${c.borderLight}`,backgroundColor:c.bgPanelAlt,cursor:"pointer"}}>
Elnor · {block.messages.length} messages{block.messages[block.messages.length-1]?.time} {e.stopPropagation();deleteBlock(block.id)}} style={{border:"none",background:"none",cursor:"pointer",padding:1,display:"flex",color:c.textTer}} onMouseEnter={e=>e.currentTarget.style.color=c.error} onMouseLeave={e=>e.currentTarget.style.color=c.textTer}> ;
return
toggleBlock(block.id)} style={{padding:"5px 12px",display:"flex",alignItems:"center",gap:6,cursor:"pointer",backgroundColor:c.accentBtn+"06",borderBottom:`1px solid ${c.accentBtn}15`}}>
Thread · {block.messages.length}
{block.contextQuote&&re: "{block.contextQuote}" }
{e.stopPropagation();deleteBlock(block.id)}} style={{border:"none",background:"none",cursor:"pointer",padding:1,display:"flex",color:c.textTer}} onMouseEnter={e=>e.currentTarget.style.color=c.error} onMouseLeave={e=>e.currentTarget.style.color=c.textTer}>
{block.messages.map((msg,i)=>
{msg.author} {msg.time} {msg.author==="You"&&<>edit delete >}
{msg.body}
)}
{threadReplyId===block.id?
:
{setThreadReplyId(block.id);setThreadReplyText("")}} style={{display:"flex",alignItems:"center",gap:5,padding:"4px 8px",borderRadius:R.sm,border:`1px solid ${c.border}`,backgroundColor:c.bgCard,cursor:"text"}}>Reply… @Elnor
}
;
}
return null;
};
return (
{setOpenDrop(null);if(pickerOpen&&pickerStep==="choose")setPickerOpen(false)}}>
{toast&&
setToast(null)}/>}
{/* SIDEBAR RAIL */}
Q
setBrowserOpen(!browserOpen)} title="Browser (⌘B)" style={{width:28,height:28,borderRadius:R.sm,border:"none",cursor:"pointer",backgroundColor:browserOpen?"#ffffff18":"transparent",color:browserOpen?"#fff":"#777",display:"flex",alignItems:"center",justifyContent:"center"}}>
setCommentsOpen(!commentsOpen)} title="Comments" style={{width:28,height:28,borderRadius:R.sm,border:"none",cursor:"pointer",backgroundColor:commentsOpen?"#ffffff18":"transparent",color:commentsOpen?"#fff":"#777",display:"flex",alignItems:"center",justifyContent:"center"}}>
{/* BROWSER placeholder */}
{browserOpen&&Browser setBrowserOpen(false)} style={{border:"none",background:"none",cursor:"pointer",display:"flex",color:c.textTer}}>
Browser with Notes scope from V4.5
}
{/* MAIN */}
{/* TOOLBAR */}
Paragraph H1 H2
B}/>I}/>U}/>
}/>}/>
} title="Copy" onClick={()=>flash("Copied")}/>
} label="Save As…" dropdown onClick={e=>{e.stopPropagation();setOpenDrop(openDrop==="save"?null:"save")}}/>
{openDrop==="save"&&e.stopPropagation()} style={{position:"absolute",top:28,left:0,backgroundColor:c.bgCard,border:`1px solid ${c.border}`,borderRadius:R.sm,boxShadow:"0 8px 24px rgba(0,0,0,0.12)",zIndex:999,minWidth:180,padding:4}}>
{flash("Export MD");setOpenDrop(null)}}>Export as Markdown
{flash("Export DOCX");setOpenDrop(null)}}>Export as DOCX
{flash("Export PDF");setOpenDrop(null)}}>Export as PDF
{flash("Save as Prompt");setOpenDrop(null)}}>Save as Prompt
}
} label="Ref" onClick={()=>flash("Ref copied")}/>
{/* ═══ ADD MODULE BUTTON ═══ */}
} label="+Module" dropdown active={pickerOpen} onClick={e=>{e.stopPropagation();setPickerOpen(!pickerOpen);setPickerStep("choose")}}/>
{pickerOpen&&e.stopPropagation()} style={{position:"absolute",top:30,left:0,backgroundColor:c.bgCard,border:`1px solid ${c.border}`,borderRadius:R.sm,boxShadow:"0 8px 28px rgba(0,0,0,0.15)",zIndex:999,width:pickerStep==="choose"?220:380,padding:0,overflow:"hidden"}}>
{/* STEP 1: Choose block type */}
{pickerStep==="choose"&&
Insert Module
{insertBlock("tasks");}}>Task List
Checkboxes, subtasks, due dates
{setPickerStep("feed_presets");setPickerTab("system")}}>Activity Feed
Live updates, agent summaries
insertBlock("thread")}>@Elnor Thread
Inline conversation
insertBlock("bar")}>Notice Bar
Alert, reminder, status
}
{/* STEP 2: Feed preset picker */}
{pickerStep==="feed_presets"&&
setPickerStep("choose")} style={{border:"none",background:"none",cursor:"pointer",display:"flex",color:c.textTer,padding:0}}>
Choose Feed Preset
{/* Tabs */}
{[{id:"system",label:"System"},{id:"agent",label:"Agent"},{id:"custom",label:"My Presets"}].map(tab=>(
setPickerTab(tab.id)} style={{flex:1,padding:"8px 4px",border:"none",cursor:"pointer",fontFamily:font.sans,fontSize:10.5,fontWeight:pickerTab===tab.id?650:400,color:pickerTab===tab.id?c.accentBtn:c.textTer,backgroundColor:"transparent",borderBottom:pickerTab===tab.id?`2px solid ${c.accentBtn}`:"2px solid transparent",display:"flex",alignItems:"center",justifyContent:"center"}}>{tab.label}
))}
{/* Preset cards */}
{feedPresets.filter(p=>pickerTab==="custom"?p.category==="custom":p.category===pickerTab).map(preset=>(
insertBlock("feed",preset)} style={{display:"flex",alignItems:"center",gap:10,padding:"8px 10px",borderRadius:R.sm,cursor:"pointer",marginBottom:2}} onMouseEnter={e=>e.currentTarget.style.backgroundColor=c.bgInput} onMouseLeave={e=>e.currentTarget.style.backgroundColor="transparent"}>
{feedIcons[preset.icon]||}
{preset.name}
{preset.desc}
))}
{pickerTab==="custom"&&
No custom presets yet. Configure a feed and click "Save as Preset"
}
{/* Create custom */}
setPickerStep("feed_custom")}>Create Custom Feed…
}
{/* STEP 3: Custom feed configuration */}
{pickerStep==="feed_custom"&&
setPickerStep("feed_presets")} style={{border:"none",background:"none",cursor:"pointer",display:"flex",color:c.textTer,padding:0}}>
Create Custom Feed
Source type
System Events
Real-time event subscriptions
Agent Instruction
Runs on a schedule
Mode
Refresh on view
Updates when you open the note
Background monitor
Runs even when note is closed
{insertBlock("feed",{id:nid(),name:customName||"Custom Feed"});setCustomName("");setCustomInstruction("")}} style={{flex:1,justifyContent:"center"}}>Create
{setPickerStep("feed_presets")}}>Cancel
}
}
} active={findBar} onClick={()=>setFindBar(!findBar)}/>
} active={fullScreen} onClick={()=>setFullScreen(!fullScreen)}/>
} label="2" active={commentsOpen&&rightTab==="comments"} onClick={()=>{if(commentsOpen&&rightTab==="comments")setCommentsOpen(false);else{setCommentsOpen(true);setRightTab("comments")}}}/>
} label={showMarkup?"Markup":"Clean"} active={showMarkup} onClick={()=>setShowMarkup(!showMarkup)}/>
} label="0 ▾"/>
Saved just now
{if(commentsOpen&&rightTab==="send")setCommentsOpen(false);else{setCommentsOpen(true);setRightTab("send")}}} style={{padding:"3px 10px",borderRadius:R.sm,border:`1px solid ${c.accentBtn}40`,backgroundColor:(commentsOpen&&rightTab==="send")?c.accentBtn:c.accentBtn+"08",cursor:"pointer",display:"flex",alignItems:"center",gap:4,color:(commentsOpen&&rightTab==="send")?"#fff":c.accentBtn,fontFamily:font.sans,fontSize:10.5,fontWeight:600,height:26}}>Send to Agent
{findBar&&0/0 setFindBar(false)} style={{padding:2,border:"none",cursor:"pointer",backgroundColor:"transparent",display:"flex",color:c.textTer}}>
}
{/* CONTENT */}
{/* Title */}
Today — Wednesday, March 19
Pinned · Auto-updating · Configurable modules
flash("Configure workspace template…")} style={{border:`1px solid ${c.borderLight}`,borderRadius:3,backgroundColor:"transparent",cursor:"pointer",padding:"1px 6px",fontSize:9,color:c.textTer,fontFamily:font.sans,display:"flex",alignItems:"center",gap:2,marginLeft:4}}>Configure
{/* Blocks with natural spacing */}
{blocks.map(block=>renderBlock(block))}
{/* Slash command hint */}
Use +Module in toolbar · Type /todo /feed /ask anywhere · Type @Elnor on any line
{/* COMMENTS placeholder */}
{commentsOpen&&!fullScreen&&
setRightTab("comments")} style={{flex:1,padding:"7px 0",border:"none",cursor:"pointer",backgroundColor:rightTab==="comments"?c.bgPanelAlt:c.bgInput,color:rightTab==="comments"?c.accentBtn:c.textTer,fontSize:10.5,fontWeight:rightTab==="comments"?650:450,fontFamily:font.sans,borderBottom:rightTab==="comments"?`2px solid ${c.accentBtn}`:"2px solid transparent",display:"flex",alignItems:"center",justifyContent:"center",gap:3}}>Comments
setRightTab("send")} style={{flex:1,padding:"7px 0",border:"none",cursor:"pointer",backgroundColor:rightTab==="send"?c.bgPanel:c.bgInput,color:rightTab==="send"?c.accentBtn:c.textTer,fontSize:10.5,fontWeight:rightTab==="send"?650:450,fontFamily:font.sans,borderBottom:rightTab==="send"?`2px solid ${c.accentBtn}`:"2px solid transparent",display:"flex",alignItems:"center",justifyContent:"center",gap:3}}>Send to Agent
setCommentsOpen(false)} style={{width:26,border:"none",cursor:"pointer",backgroundColor:"transparent",display:"flex",alignItems:"center",justifyContent:"center",color:c.textTer}}>
Comments + Send to Agent from Q_NOTES_FULL.jsx
}
{/* CHAT INDICATOR */}
);
}