import * as monaco from 'monaco-editor/esm/vs/editor/editor.api'; // Widths stay in effect while switching projects, tabs, and collapsed panels. export function installSidebarResize(editor: monaco.editor.IStandaloneCodeEditor) { const main = document.querySelector('main')!; const left = main.querySelector('aside')!; const right = document.getElementById('explanation-pane')!; const handles: { side: 'left' | 'right'; panel: HTMLElement; handle: HTMLDivElement }[] = []; function limits(side: 'left' | 'right') { const overlay = window.innerWidth <= 1100 || right.classList.contains('graph-expanded'); const other = side === 'left' ? (right.hidden || overlay ? 0 : right.getBoundingClientRect().width) : (overlay ? 0 : left.getBoundingClientRect().width); return { min: side === 'left' ? 180 : 300, max: Math.max(side === 'left' ? 180 : 300, Math.min(side === 'left' ? 650 : 1100, main.clientWidth - other - (overlay && side === 'right' ? 40 : 280))) }; } function widthProperty(side: 'left' | 'right') { return side === 'right' && right.classList.contains('graph-expanded') ? '--expanded-sidebar-width' : `--${side}-sidebar-width`; } function setWidth(side: 'left' | 'right', width: number) { const {min,max} = limits(side); document.documentElement.style.setProperty(widthProperty(side), `${Math.round(Math.max(min,Math.min(max,width)))}px`); editor.layout(); update(); } function update() { for (const {side,panel,handle} of handles) { const {min,max}=limits(side); handle.setAttribute('aria-valuemin',String(min));handle.setAttribute('aria-valuemax',String(Math.round(max))); handle.setAttribute('aria-valuenow',String(Math.round(panel.getBoundingClientRect().width))); } } for (const [side,panel] of [['left',left],['right',right]] as const) { const handle = document.createElement('div');handle.className=`sidebar-resizer ${side}-resizer`;handle.tabIndex=0; handle.setAttribute('role','separator');handle.setAttribute('aria-orientation','vertical'); handle.setAttribute('aria-label',`Resize ${side} sidebar`);handle.title='Drag to resize · arrow keys adjust · double-click to reset'; panel.append(handle);handles.push({side,panel,handle}); let drag: {x:number;width:number} | null=null; handle.onpointerdown=event=>{if(event.button)return;event.preventDefault();drag={x:event.clientX,width:panel.getBoundingClientRect().width};handle.setPointerCapture(event.pointerId);document.body.classList.add('resizing-sidebars');}; handle.onpointermove=event=>{if(drag)setWidth(side,drag.width+(event.clientX-drag.x)*(side==='left'?1:-1));}; const stop=()=>{drag=null;document.body.classList.remove('resizing-sidebars');}; handle.onpointerup=handle.onpointercancel=handle.onlostpointercapture=stop; handle.ondblclick=()=>{document.documentElement.style.removeProperty(widthProperty(side));editor.layout();update();}; handle.onkeydown=event=>{ if(event.key==='ArrowLeft'||event.key==='ArrowRight') {event.preventDefault();const direction=(event.key==='ArrowRight'?1:-1)*(side==='left'?1:-1);setWidth(side,panel.getBoundingClientRect().width+direction*(event.shiftKey?50:10));} else if(event.key==='Home'||event.key==='End') {event.preventDefault();const range=limits(side);setWidth(side,event.key==='Home'?range.min:range.max);} }; } const observer=new ResizeObserver(update);observer.observe(left);observer.observe(right); window.addEventListener('resize',()=>{for(const {side,panel} of handles) if(!panel.hidden && document.documentElement.style.getPropertyValue(widthProperty(side))) setWidth(side,panel.getBoundingClientRect().width);}); update(); }