@mochabug/adapt-web 1.0.1-rc.15 → 1.0.1-rc.17
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +10 -0
- package/dist/README.md +25 -15
- package/dist/esm/AdaptAutomationElement.js +1 -1
- package/dist/esm/cap-adapter.js +1 -1
- package/dist/esm/css-panel.js +10 -9
- package/dist/esm/index.js +1 -1
- package/dist/esm/panel-manager.js +1 -1
- package/dist/styles.css +10 -9
- package/dist/types/AdaptAutomationElement.d.ts +2 -1
- package/dist/types/core.d.ts +1 -1
- package/dist/types/css-panel.d.ts +1 -1
- package/dist/types/index.d.ts +2 -1
- package/dist/types/panel-manager.d.ts +2 -0
- package/dist/types/types.d.ts +24 -0
- package/dist/umd/adapt-web.cap.js +1 -1
- package/dist/umd/adapt-web.cap.js.br +0 -0
- package/dist/umd/adapt-web.cap.min.js +1 -1
- package/dist/umd/adapt-web.cap.min.js.br +0 -0
- package/dist/umd/adapt-web.core.js +61 -12
- package/dist/umd/adapt-web.core.js.br +0 -0
- package/dist/umd/adapt-web.core.min.js +13 -12
- package/dist/umd/adapt-web.core.min.js.br +0 -0
- package/dist/umd/adapt-web.js +62 -13
- package/dist/umd/adapt-web.js.br +0 -0
- package/dist/umd/adapt-web.min.js +16 -15
- package/dist/umd/adapt-web.min.js.br +0 -0
- package/dist/umd/styles.css +10 -9
- package/dist/umd/styles.css.br +0 -0
- package/package.json +2 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
import{SVG_POPOUT,SVG_WINDOW}from"./panel-setup.js";let iframeDragDepth=0;function disableIframePointEvents(){return iframeDragDepth++,document.documentElement.classList.add("mb-dragging"),{release(){--iframeDragDepth<=0&&(iframeDragDepth=0,document.documentElement.classList.remove("mb-dragging"))}}}class Panel{constructor(id,element,title){this.group=null;this.id=id,this.element=element,this.title=title||id,this.wrapper=document.createElement("div"),this.wrapper.className="mb-panel",this.wrapper.dataset.panelId=id,this.wrapper.dataset.active="false",this.wrapper.appendChild(element)}}let groupIdCounter=0;class PanelGroup{constructor(id){this._panels=[];this._activePanel=null;this._headerHidden=!1;this._locked=!1;this._onTabClose=null;this._onTabPointerDown=null;this._onTabPopOut=null;this._location="grid";this._onLocationChangedCb=null;this._isInFloatingSplit=!1;this._onSplitStateChangedCb=null;this._dragConstraint="any";this._dockingBlocked=!1;this._dialogDockingBlocked=!1;this._onPanelCountChangedCb=null;this._onActivePanelChangedCb=null;this.id=id||`group-${++groupIdCounter}`,this.element=document.createElement("div"),this.element.className="mb-group",this.element.dataset.groupId=this.id,this.headerElement=document.createElement("div"),this.headerElement.className="mb-group-header",this.headerPrefix=document.createElement("div"),this.headerPrefix.className="mb-group-header-prefix",this.tabsElement=document.createElement("div"),this.tabsElement.className="mb-group-tabs",this.headerVoid=document.createElement("div"),this.headerVoid.className="mb-group-header-void",this.headerActions=document.createElement("div"),this.headerActions.className="mb-group-header-actions",this.headerElement.appendChild(this.headerPrefix),this.headerElement.appendChild(this.tabsElement),this.headerElement.appendChild(this.headerVoid),this.headerElement.appendChild(this.headerActions),this.contentElement=document.createElement("div"),this.contentElement.className="mb-group-content",this.element.appendChild(this.headerElement),this.element.appendChild(this.contentElement)}get panels(){return this._panels}get activePanel(){return this._activePanel}get size(){return this._panels.length}get locked(){return this._locked}set locked(value){this._locked=value}setHeaderHidden(hidden){this._headerHidden=hidden,this.headerElement.style.display=hidden?"none":""}get headerHidden(){return this._headerHidden}setHeaderActions(element){this.headerActions.innerHTML="",this.headerActions.appendChild(element)}setHeaderPrefix(element){this.headerPrefix.innerHTML="",this.headerPrefix.appendChild(element)}onTabClose(cb){this._onTabClose=cb}onTabPointerDown(cb){this._onTabPointerDown=cb}get location(){return this._location}set location(value){this._location!==value&&(this._location=value,this._onLocationChangedCb?.(value))}onLocationChanged(cb){this._onLocationChangedCb=cb}fireLocationChanged(){this._onLocationChangedCb?.(this._location)}get isInFloatingSplit(){return this._isInFloatingSplit}set isInFloatingSplit(value){this._isInFloatingSplit!==value&&(this._isInFloatingSplit=value,this._onSplitStateChangedCb?.(value))}onSplitStateChanged(cb){this._onSplitStateChangedCb=cb}onTabPopOut(cb){this._onTabPopOut=cb}get dragConstraint(){return this._dragConstraint}set dragConstraint(v){this._dragConstraint=v}get dockingBlocked(){return this._dockingBlocked}set dockingBlocked(v){this._dockingBlocked=v}get dialogDockingBlocked(){return this._dialogDockingBlocked}set dialogDockingBlocked(v){this._dialogDockingBlocked=v}onPanelCountChanged(cb){this._onPanelCountChangedCb=cb}onActivePanelChanged(cb){this._onActivePanelChangedCb=cb}addPanel(panel){if(this._panels.some(p=>p.id===panel.id))return;panel.group=this,this._panels.push(panel),this.contentElement.appendChild(panel.wrapper);const tab=this.createTab(panel);this.tabsElement.appendChild(tab),this.activatePanel(panel.id),this.element.dataset.tabCount=String(this._panels.length),this._onPanelCountChangedCb?.(this._panels.length)}removePanel(panelId){const idx=this._panels.findIndex(p=>p.id===panelId);if(idx===-1)return null;const panel=this._panels[idx];if(this._panels.splice(idx,1),panel.wrapper.remove(),this.tabsElement.querySelector(`[data-tab-id="${panelId}"]`)?.remove(),panel.group=null,this._activePanel===panel&&(this._activePanel=null,this._panels.length>0)){const newActive=this._panels[Math.min(idx,this._panels.length-1)];newActive&&this.activatePanel(newActive.id)}return this.element.dataset.tabCount=String(this._panels.length),this._onPanelCountChangedCb?.(this._panels.length),panel}detachPanel(panelId){const idx=this._panels.findIndex(p=>p.id===panelId);if(idx===-1)return null;const panel=this._panels[idx];if(this._panels.splice(idx,1),this.tabsElement.querySelector(`[data-tab-id="${panelId}"]`)?.remove(),panel.group=null,this._activePanel===panel&&(this._activePanel=null,this._panels.length>0)){const newActive=this._panels[Math.min(idx,this._panels.length-1)];newActive&&this.activatePanel(newActive.id)}return this.element.dataset.tabCount=String(this._panels.length),this._onPanelCountChangedCb?.(this._panels.length),panel}activatePanel(panelId){const panel=this._panels.find(p=>p.id===panelId);if(!panel)return;this._activePanel=panel;for(const p of this._panels)p.wrapper.dataset.active=p===panel?"true":"false";const tabs=this.tabsElement.querySelectorAll(".mb-tab");for(const tab of tabs){const isActive=tab.dataset.tabId===panelId;tab.dataset.active=isActive?"true":"false"}this._onActivePanelChangedCb?.(panelId)}reorderPanel(panelId,dropX){const panelIdx=this._panels.findIndex(p=>p.id===panelId);if(panelIdx===-1)return;const panel=this._panels[panelIdx],tabs=Array.from(this.tabsElement.querySelectorAll(".mb-tab"));let targetIdx=this._panels.length;for(let i=0;i<tabs.length;i++){const rect=tabs[i].getBoundingClientRect();if(dropX<rect.left+rect.width/2){targetIdx=i;break}}if(targetIdx===panelIdx||targetIdx===panelIdx+1)return;this._panels.splice(panelIdx,1);const insertAt=panelIdx<targetIdx?targetIdx-1:targetIdx;this._panels.splice(insertAt,0,panel);const tabEl=this.tabsElement.querySelector(`[data-tab-id="${panelId}"]`);if(tabEl){const refTab=this.tabsElement.querySelectorAll(".mb-tab")[insertAt];refTab&&refTab!==tabEl?this.tabsElement.insertBefore(tabEl,refTab):this.tabsElement.appendChild(tabEl)}}createTab(panel){const tab=document.createElement("div");tab.className="mb-tab",tab.dataset.tabId=panel.id,tab.dataset.active="false";const label=document.createElement("span");label.className="mb-tab-label",label.innerHTML=SVG_WINDOW,label.title=panel.title,tab.appendChild(label);const actions=document.createElement("div");actions.className="mb-tab-actions";const popOutBtn=document.createElement("button");popOutBtn.className="mb-tab-popout",popOutBtn.title="Pop out",popOutBtn.innerHTML=SVG_POPOUT,popOutBtn.addEventListener("click",e=>{e.stopPropagation(),this._onTabPopOut?.(panel.id)}),actions.appendChild(popOutBtn);const closeBtn=document.createElement("button");return closeBtn.className="mb-tab-close",closeBtn.title="Close",closeBtn.innerHTML='<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"><line x1="4" y1="4" x2="12" y2="12"/><line x1="12" y1="4" x2="4" y2="12"/></svg>',closeBtn.addEventListener("click",e=>{e.stopPropagation(),this._onTabClose?.(panel.id)}),actions.appendChild(closeBtn),tab.appendChild(actions),tab.addEventListener("pointerdown",e=>{e.target.closest(".mb-tab-close")||e.target.closest(".mb-tab-popout")||e.button===0&&(e.preventDefault(),this._onTabPointerDown?.(panel.id,e))}),tab}dispose(){this._panels=[],this._activePanel=null,this.element.remove()}}let zIndexCounter=1e5;class FloatingOverlay{constructor(group,opts,parentElement,insertBefore){this.internalLayout=null;this.toolbarElement=null;this.savedBounds=null;this._isMaximized=!1;this._onDragEnd=null;this._onDragMove=null;this.group=group,this.bounds={...opts},this.element=document.createElement("div"),this.element.className="mb-floating-overlay",this.element.dataset.groupId=group.id,this.applyBounds();const directions=["n","s","e","w","ne","nw","se","sw"];for(const dir of directions){const handle=document.createElement("div");handle.className=`mb-resize-handle mb-resize-${dir}`,handle.addEventListener("pointerdown",e=>this.onResizeStart(e,dir)),this.element.appendChild(handle)}this.element.addEventListener("pointerdown",()=>this.bringToFront(),!0),group.headerVoid.addEventListener("pointerdown",e=>this.onDragStart(e)),group.headerVoid.style.cursor="grab";const parent=parentElement??document.body;insertBefore?parent.insertBefore(this.element,insertBefore):parent.appendChild(this.element),this.element.appendChild(group.element),this.bringToFront()}get isMaximized(){return this._isMaximized}set onDragEnd(cb){this._onDragEnd=cb}set onDragMove(cb){this._onDragMove=cb}bringToFront(){zIndexCounter+=2,this.element.style.zIndex=String(zIndexCounter)}maximize(){this._isMaximized||(this.savedBounds={...this.bounds},this._isMaximized=!0,this.element.style.inset="0",this.element.style.width="auto",this.element.style.height="auto",this.element.classList.add("mb-floating-maximized"))}restore(){!this._isMaximized||!this.savedBounds||(this._isMaximized=!1,this.bounds={...this.savedBounds},this.savedBounds=null,this.element.classList.remove("mb-floating-maximized"),this.element.style.inset="",this.applyBounds())}hide(){this.element.style.display="none"}show(){this.element.style.display=""}dispose(){this.internalLayout&&(this.internalLayout.dispose(),this.internalLayout=null),this.removeToolbar(),this.element.remove()}getBounds(){return{...this.bounds}}setBounds(partial){if(this._isMaximized)return;const pad=10;partial.width!==void 0&&(this.bounds.width=Math.min(partial.width,window.innerWidth-this.bounds.x-pad)),partial.height!==void 0&&(this.bounds.height=Math.min(partial.height,window.innerHeight-this.bounds.y-pad)),this.applyBounds()}setFullBounds(bounds){if(this._isMaximized)return;const vw=window.innerWidth,vh=window.innerHeight,pad=10,minVisible=100;this.bounds={width:Math.max(minVisible,Math.min(bounds.width,vw-pad)),height:Math.max(minVisible,Math.min(bounds.height,vh-pad)),x:Math.max(0,Math.min(bounds.x,vw-minVisible)),y:Math.max(0,Math.min(bounds.y,vh-minVisible))},this.applyBounds()}applyBounds(){this.element.style.position="fixed",this.element.style.left=`${this.bounds.x}px`,this.element.style.top=`${this.bounds.y}px`,this.element.style.width=`${this.bounds.width}px`,this.element.style.height=`${this.bounds.height}px`}setDragGroup(newGroup){newGroup.headerVoid.addEventListener("pointerdown",e=>this.onDragStart(e)),newGroup.headerVoid.style.cursor="grab"}setToolbar(el){this.removeToolbar(),this.toolbarElement=el,this.getToolbarHost().headerActions.appendChild(el)}removeToolbar(){this.toolbarElement&&(this.toolbarElement.remove(),this.toolbarElement=null)}repositionToolbar(){this.toolbarElement&&this.getToolbarHost().headerActions.appendChild(this.toolbarElement)}getToolbarHost(){if(!this.internalLayout)return this.group;const root=this.internalLayout.getRoot();return root?FloatingOverlay.topRightGroup(root):this.group}static topRightGroup(node){return node.kind==="leaf"?node.group:node.direction==="horizontal"?FloatingOverlay.topRightGroup(node.second):FloatingOverlay.topRightGroup(node.first)}get hasToolbar(){return this.toolbarElement!==null}getAllGroups(){return this.internalLayout?.allGroups()??[this.group]}updateTotalTabCount(){const groups=this.getAllGroups();let total=0;for(const g of groups)total+=g.size;this.element.dataset.totalTabCount=String(total)}onDragStart(e){if(this._isMaximized)return;e.preventDefault();const handle=e.currentTarget,startX=e.clientX,startY=e.clientY,origLeft=this.bounds.x,origTop=this.bounds.y,iframes=disableIframePointEvents();handle.style.cursor="grabbing",handle.setPointerCapture(e.pointerId);const onMove=ev=>{const dx=ev.clientX-startX,dy=ev.clientY-startY;this.bounds.x=Math.max(0,Math.min(origLeft+dx,window.innerWidth-this.bounds.width)),this.bounds.y=Math.max(0,Math.min(origTop+dy,window.innerHeight-this.bounds.height)),this.applyBounds(),this._onDragMove?.(this.bounds.x+this.bounds.width/2,this.bounds.y+this.bounds.height/2)},onUp=()=>{iframes.release(),handle.style.cursor="grab",handle.removeEventListener("pointermove",onMove),handle.removeEventListener("pointerup",onUp),handle.removeEventListener("pointercancel",onUp),this._onDragEnd?.(this.bounds.x+this.bounds.width/2,this.bounds.y+this.bounds.height/2)};handle.addEventListener("pointermove",onMove),handle.addEventListener("pointerup",onUp),handle.addEventListener("pointercancel",onUp)}onResizeStart(e,dir){if(this._isMaximized)return;e.preventDefault(),e.stopPropagation();const startX=e.clientX,startY=e.clientY,orig={...this.bounds},handle=e.currentTarget,minW=200,minH=100,iframes=disableIframePointEvents();handle.setPointerCapture(e.pointerId);const onMove=ev=>{const dx=ev.clientX-startX,dy=ev.clientY-startY;if(dir.includes("e")&&(this.bounds.width=Math.max(minW,orig.width+dx)),dir.includes("w")){const newW=Math.max(minW,orig.width-dx);this.bounds.x=orig.x+(orig.width-newW),this.bounds.width=newW}if(dir.includes("s")&&(this.bounds.height=Math.max(minH,orig.height+dy)),dir.includes("n")){const newH=Math.max(minH,orig.height-dy);this.bounds.y=orig.y+(orig.height-newH),this.bounds.height=newH}const pad=10;this.bounds.x=Math.max(0,this.bounds.x),this.bounds.y=Math.max(0,this.bounds.y),this.bounds.x+this.bounds.width>window.innerWidth-pad&&(this.bounds.width=window.innerWidth-this.bounds.x-pad),this.bounds.y+this.bounds.height>window.innerHeight-pad&&(this.bounds.height=window.innerHeight-this.bounds.y-pad),this.applyBounds()},onUp=()=>{iframes.release(),handle.removeEventListener("pointermove",onMove),handle.removeEventListener("pointerup",onUp),handle.removeEventListener("pointercancel",onUp)};handle.addEventListener("pointermove",onMove),handle.addEventListener("pointerup",onUp),handle.addEventListener("pointercancel",onUp)}}class SplitLayout{constructor(container){this.root=null;this.element=document.createElement("div"),this.element.className="mb-layout",container.appendChild(this.element)}getRoot(){return this.root}setMainGroup(group){const leaf=this.createLeaf(group);leaf.element.style.flex="1",this.root=leaf,this.element.appendChild(leaf.element)}splitGroup(targetGroup,newGroup,direction,newGroupSize){const splitDir=this.dockToSplitDirection(direction),leafNode=this.findGroupNode(targetGroup);if(!leafNode)return!1;const newLeafEl=document.createElement("div");newLeafEl.className="mb-split-leaf",newLeafEl.style.flex="1";const splitEl=document.createElement("div");splitEl.className=`mb-split-container ${splitDir==="horizontal"?"mb-split-horizontal":"mb-split-vertical"}`,splitEl.style.flex=leafNode.element.style.flex||"1",splitEl.style.minWidth="0",splitEl.style.minHeight="0";const separator=document.createElement("div"),isVerticalSplit=splitDir==="vertical";separator.className=`mb-layout-separator ${isVerticalSplit?"mb-layout-separator-h":"mb-layout-separator-v"}`;const existingFirst=direction==="right"||direction==="bottom";leafNode.element.parentElement.insertBefore(splitEl,leafNode.element),existingFirst?(splitEl.appendChild(leafNode.element),splitEl.appendChild(separator),splitEl.appendChild(newLeafEl)):(splitEl.appendChild(newLeafEl),splitEl.appendChild(separator),splitEl.appendChild(leafNode.element)),newLeafEl.appendChild(newGroup.element),newGroupSize!==void 0&&newGroupSize>0?existingFirst?(leafNode.element.style.flex="1",newLeafEl.style.flex=`0 0 ${newGroupSize}px`):(newLeafEl.style.flex=`0 0 ${newGroupSize}px`,leafNode.element.style.flex="1"):(leafNode.element.style.flex="1",newLeafEl.style.flex="1");const newLeaf={kind:"leaf",group:newGroup,element:newLeafEl},splitNode={kind:"split",direction:splitDir,first:existingFirst?leafNode:newLeaf,second:existingFirst?newLeaf:leafNode,element:splitEl,separator};return separator.addEventListener("pointerdown",e=>this.onSeparatorDrag(e,splitNode)),this.replaceNodeInTree(leafNode,splitNode),leafNode.element.style.display==="none"&&(separator.style.display="none",newLeafEl.dataset.savedFlex=newLeafEl.style.flex,newLeafEl.style.flex="1",leafNode.element.dataset.savedFlex=leafNode.element.style.flex),!0}removeGroup(group){const leafNode=this.findGroupNode(group);if(!leafNode)return;if(this.root===leafNode){leafNode.element.remove(),this.root=null;return}this.restoreMaximizedLeaf(group);const parentSplit=this.findParentSplit(leafNode);if(!parentSplit)return;const sibling=parentSplit.first===leafNode?parentSplit.second:parentSplit.first;this.restoreMaximizedSubtree(sibling),sibling.element.style.flex=parentSplit.element.style.flex||"1",parentSplit.element.parentElement.insertBefore(sibling.element,parentSplit.element),leafNode.element.remove(),parentSplit.separator.remove(),parentSplit.element.remove(),this.replaceNodeInTree(parentSplit,sibling)}findGroupNode(group){return this.findGroupNodeIn(this.root,group)}getGroupPosition(group){const leaf=this.findGroupNode(group);if(!leaf)return null;const parent=this.findParentSplit(leaf);if(!parent)return null;const isFirst=parent.first===leaf,siblingNode=isFirst?parent.second:parent.first,siblingGroup=this.firstGroupIn(siblingNode);if(!siblingGroup)return null;let direction;return parent.direction==="horizontal"?direction=isFirst?"left":"right":direction=isFirst?"top":"bottom",{siblingGroup,direction}}firstGroupIn(node){return node.kind==="leaf"?node.group:this.firstGroupIn(node.first)}collapseLeaf(group){const leaf=this.findGroupNode(group);if(!leaf)return;const parent=this.findParentSplit(leaf);if(parent){const sibling=parent.first===leaf?parent.second:parent.first;sibling.element.dataset.savedFlex=sibling.element.style.flex,sibling.element.style.flex="1",parent.separator.style.display="none"}leaf.element.dataset.savedFlex=leaf.element.style.flex,leaf.element.style.display="none"}expandLeaf(group){const leaf=this.findGroupNode(group);if(!leaf)return;leaf.element.style.display="",leaf.element.dataset.savedFlex!==void 0&&(leaf.element.style.flex=leaf.element.dataset.savedFlex,delete leaf.element.dataset.savedFlex);const parent=this.findParentSplit(leaf);if(parent){parent.separator.style.display="";const sibling=parent.first===leaf?parent.second:parent.first;sibling.element.dataset.savedFlex!==void 0&&(sibling.element.style.flex=sibling.element.dataset.savedFlex,delete sibling.element.dataset.savedFlex)}}maximizeLeaf(group){const leaf=this.findGroupNode(group);if(!leaf)return;let current=leaf,parent=this.findParentSplit(current);for(;parent;){const sibling=parent.first===current?parent.second:parent.first;sibling.element.dataset.maxSavedDisplay===void 0&&(sibling.element.dataset.maxSavedDisplay=sibling.element.style.display),sibling.element.style.display="none",parent.separator.dataset.maxSavedDisplay===void 0&&(parent.separator.dataset.maxSavedDisplay=parent.separator.style.display),parent.separator.style.display="none",current.element.dataset.maxSavedFlex===void 0&&(current.element.dataset.maxSavedFlex=current.element.style.flex),current.element.style.flex="1",current=parent,parent=this.findParentSplit(current)}}restoreMaximizedLeaf(group){const leaf=this.findGroupNode(group);if(!leaf)return;let current=leaf,parent=this.findParentSplit(current);for(;parent;){const sibling=parent.first===current?parent.second:parent.first;sibling.element.dataset.maxSavedDisplay!==void 0&&(sibling.element.style.display=sibling.element.dataset.maxSavedDisplay,delete sibling.element.dataset.maxSavedDisplay),parent.separator.dataset.maxSavedDisplay!==void 0&&(parent.separator.style.display=parent.separator.dataset.maxSavedDisplay,delete parent.separator.dataset.maxSavedDisplay),current.element.dataset.maxSavedFlex!==void 0&&(current.element.style.flex=current.element.dataset.maxSavedFlex,delete current.element.dataset.maxSavedFlex),current=parent,parent=this.findParentSplit(current)}}restoreMaximizedSubtree(node){node.element.dataset.maxSavedDisplay!==void 0&&(node.element.style.display=node.element.dataset.maxSavedDisplay,delete node.element.dataset.maxSavedDisplay),node.element.dataset.maxSavedFlex!==void 0&&(node.element.style.flex=node.element.dataset.maxSavedFlex,delete node.element.dataset.maxSavedFlex),node.kind==="split"&&(node.separator.dataset.maxSavedDisplay!==void 0&&(node.separator.style.display=node.separator.dataset.maxSavedDisplay,delete node.separator.dataset.maxSavedDisplay),this.restoreMaximizedSubtree(node.first),this.restoreMaximizedSubtree(node.second))}allGroups(){const result=[];return this.collectGroups(this.root,result),result}toJSON(){return this.serializeNode(this.root)}restoreFlexFromSerialized(serialized){if(!serialized||!this.root)return;const flexMap=new Map;this.collectFlexValues(serialized,flexMap),this.applyFlexValues(this.root,flexMap)}animateTransition(){const cls=node=>{node&&(node.kind==="leaf"?node.element.classList.add("mb-split-leaf--animating"):(node.element.classList.add("mb-split-container--animating"),node.separator&&node.separator.classList.add("mb-layout-separator--animating"),cls(node.first),cls(node.second)))};cls(this.root);const cleanup=()=>{this.element.querySelectorAll(".mb-split-leaf--animating, .mb-split-container--animating, .mb-layout-separator--animating").forEach(el=>{el.classList.remove("mb-split-leaf--animating","mb-split-container--animating","mb-layout-separator--animating")})},timer=setTimeout(cleanup,350);this.element.addEventListener("transitionend",()=>{clearTimeout(timer),cleanup()},{once:!0})}dispose(){this.element.remove(),this.root=null}createLeaf(group){const leafEl=document.createElement("div");return leafEl.className="mb-split-leaf",leafEl.style.flex="1",leafEl.appendChild(group.element),{kind:"leaf",group,element:leafEl}}dockToSplitDirection(pos){return pos==="left"||pos==="right"?"horizontal":"vertical"}findGroupNodeIn(node,group){return node?node.kind==="leaf"?node.group===group?node:null:this.findGroupNodeIn(node.first,group)??this.findGroupNodeIn(node.second,group):null}collectGroups(node,result){node&&(node.kind==="leaf"?result.push(node.group):(this.collectGroups(node.first,result),this.collectGroups(node.second,result)))}findParentSplit(target){return this.findParentSplitIn(this.root,target)}findParentSplitIn(node,target){return!node||node.kind==="leaf"?null:node.first===target||node.second===target?node:this.findParentSplitIn(node.first,target)??this.findParentSplitIn(node.second,target)}replaceNodeInTree(oldNode,newNode){if(this.root===oldNode){this.root=newNode;return}const parent=this.findParentSplit(oldNode);parent&&(parent.first===oldNode?parent.first=newNode:parent.second=newNode)}collectFlexValues(node,map){node.kind==="leaf"?map.set(node.groupId,node.flex):(this.collectFlexValues(node.first,map),this.collectFlexValues(node.second,map))}applyFlexValues(node,map){if(node.kind==="leaf"){const saved=map.get(node.group.id);saved&&this.isValidFlex(saved)&&(node.element.style.flex=saved)}else this.applyFlexValues(node.first,map),this.applyFlexValues(node.second,map)}isValidFlex(value){if(value.includes("px"))return!0;const n=Number(value);return Number.isFinite(n)&&n>=0}serializeNode(node){return node?node.kind==="leaf"?{kind:"leaf",groupId:node.group.id,flex:node.element.style.flex||"1"}:{kind:"split",direction:node.direction,first:this.serializeNode(node.first),second:this.serializeNode(node.second),flex:node.element.style.flex||"1"}:null}onSeparatorDrag(e,splitNode){if(e.preventDefault(),splitNode.first.element.style.display==="none"||splitNode.second.element.style.display==="none")return;const isHorizontal=splitNode.direction==="horizontal",startPos=isHorizontal?e.clientX:e.clientY,firstEl=splitNode.first.element,secondEl=splitNode.second.element;this.lockDescendantSizes(splitNode.first,isHorizontal),this.lockDescendantSizes(splitNode.second,isHorizontal);const origFirstSize=isHorizontal?firstEl.offsetWidth:firstEl.offsetHeight,origSecondSize=isHorizontal?secondEl.offsetWidth:secondEl.offsetHeight,totalSize=origFirstSize+origSecondSize;if(totalSize<=0)return;const minSize=150,iframes=disableIframePointEvents();splitNode.separator.setPointerCapture(e.pointerId),splitNode.separator.classList.add("mb-layout-separator--active");const onMove=ev=>{if(firstEl.style.display==="none"||secondEl.style.display==="none"){splitNode.separator.releasePointerCapture(ev.pointerId),onUp();return}const delta=(isHorizontal?ev.clientX:ev.clientY)-startPos;let newFirst=origFirstSize+delta,newSecond=origSecondSize-delta;newFirst<minSize&&(newFirst=minSize,newSecond=totalSize-minSize),newSecond<minSize&&(newSecond=minSize,newFirst=totalSize-minSize),firstEl.style.flex=String(newFirst/totalSize),secondEl.style.flex=String(newSecond/totalSize)},onUp=()=>{iframes.release(),splitNode.separator.classList.remove("mb-layout-separator--active"),splitNode.separator.removeEventListener("pointermove",onMove),splitNode.separator.removeEventListener("pointerup",onUp),splitNode.separator.removeEventListener("pointercancel",onUp),this.unlockDescendantSizes(splitNode.first,isHorizontal),this.unlockDescendantSizes(splitNode.second,isHorizontal)};splitNode.separator.addEventListener("pointermove",onMove),splitNode.separator.addEventListener("pointerup",onUp),splitNode.separator.addEventListener("pointercancel",onUp)}lockDescendantSizes(node,isHorizontal){if(node.kind!=="split"||node.direction==="horizontal"!==isHorizontal)return;const firstSize=isHorizontal?node.first.element.getBoundingClientRect().width:node.first.element.getBoundingClientRect().height;node.first.element.style.flex=`0 0 ${firstSize}px`,node.second.element.style.flex="1",this.lockDescendantSizes(node.first,isHorizontal),this.lockDescendantSizes(node.second,isHorizontal)}unlockDescendantSizes(node,isHorizontal){if(node.kind!=="split"||node.direction==="horizontal"!==isHorizontal)return;this.unlockDescendantSizes(node.first,isHorizontal),this.unlockDescendantSizes(node.second,isHorizontal);const firstSize=isHorizontal?node.first.element.getBoundingClientRect().width:node.first.element.getBoundingClientRect().height,secondSize=isHorizontal?node.second.element.getBoundingClientRect().width:node.second.element.getBoundingClientRect().height,total=firstSize+secondSize;total>0?(node.first.element.style.flex=String(firstSize/total),node.second.element.style.flex=String(secondSize/total)):(node.first.element.style.flex="0.5",node.second.element.style.flex="0.5")}}class PanelManager{constructor(opts){this.groups=new Map;this.panels=new Map;this.floatingOverlays=new Map;this.mainGroupId=null;this.onPanelRemovedCbs=[];this.onGroupCreatedByDragCb=null;this.disposed=!1;this.dragState=null;this.portals=new Map;this.portalRaf=0;this.mainGroupCollapsed=!1;this._beforeTabClose=null;this.container=opts.container,this.splitEdgeSize=opts.splitEdgeSize??100,this.layout=new SplitLayout(this.container),opts.onPanelRemoved&&this.onPanelRemovedCbs.push(opts.onPanelRemoved),this.onGroupCreatedByDragCb=opts.onGroupCreatedByDrag??null,this.dropOverlay=document.createElement("div"),this.dropOverlay.className="mb-drop-overlay",this.container.appendChild(this.dropOverlay),this.portalLayer=document.createElement("div"),this.portalLayer.className="mb-iframe-portal-layer",this.container.appendChild(this.portalLayer),this.syncPortals()}setBeforeTabClose(cb){this._beforeTabClose=cb}addPanel(opts){const panel=new Panel(opts.id,opts.element,opts.title);this.panels.set(opts.id,panel);const groupId=opts.groupId;if(groupId){const group=this.groups.get(groupId);group&&(group.addPanel(panel),this.registerPortal(panel.id,panel.element,panel.wrapper))}return panel}removePanel(panelId){const panel=this.panels.get(panelId);if(panel){if(this.unregisterPortal(panelId),panel.group){const group=panel.group;group.removePanel(panelId),group.size===0&&group.id!==this.mainGroupId&&this.removeGroup(group.id)}this.panels.delete(panelId);for(const cb of this.onPanelRemovedCbs)cb(panel)}}getPanel(panelId){return this.panels.get(panelId)}addGroup(opts){const group=new PanelGroup(opts?.id);if(this.groups.set(group.id,group),this.wireGroupCallbacks(group),opts?.floating)this.addFloatingGroup(group,opts.floating);else if(opts?.direction){const mainGroup=this.mainGroupId?this.groups.get(this.mainGroupId):void 0;mainGroup&&this.layout.splitGroup(mainGroup,group,opts.direction,opts.initialSize)}return group}removeGroup(groupId){const group=this.groups.get(groupId);if(!group)return;for(const panel of[...group.panels])this.unregisterPortal(panel.id);const overlay=this.floatingOverlays.get(groupId);if(overlay)if(overlay.internalLayout){overlay.internalLayout.removeGroup(group),this.floatingOverlays.delete(groupId);const remaining=this.cleanupOrphanedFloatingLeaf(overlay);remaining.length>0?this.floatingOverlays.set(remaining[0].id,overlay):overlay.dispose()}else overlay.dispose(),this.floatingOverlays.delete(groupId);if(!overlay){const parentOverlay=this.findOverlayForGroup(group);parentOverlay?.internalLayout&&(parentOverlay.internalLayout.removeGroup(group),this.cleanupOrphanedFloatingLeaf(parentOverlay))}this.layout.findGroupNode(group)&&this.layout.removeGroup(group),group.isInFloatingSplit=!1,group.dispose(),this.groups.delete(groupId)}getGroup(groupId){return this.groups.get(groupId)}getMainGroup(){if(this.mainGroupId)return this.groups.get(this.mainGroupId)}setMainGroup(group){this.mainGroupId=group.id,this.layout.setMainGroup(group)}collapseMainGroup(){const main=this.getMainGroup();!main||this.mainGroupCollapsed||(this.layout.collapseLeaf(main),this.mainGroupCollapsed=!0)}expandMainGroup(){const main=this.getMainGroup();!main||!this.mainGroupCollapsed||(this.layout.expandLeaf(main),this.mainGroupCollapsed=!1)}isMainGroupCollapsed(){return this.mainGroupCollapsed}getDockedGroups(){return this.layout.allGroups()}collapseDockedGroup(group){this.layout.collapseLeaf(group)}expandDockedGroup(group){this.layout.expandLeaf(group)}maximizeDockedGroup(group){this.layout.maximizeLeaf(group)}restoreMaximizedDockedGroup(group){this.layout.restoreMaximizedLeaf(group)}restoreLayoutFlex(serialized){this.layout.restoreFlexFromSerialized(serialized)}addFloatingGroup(group,opts){const existingOverlay=this.floatingOverlays.get(group.id);existingOverlay&&this.floatingOverlays.delete(group.id);const parentOverlay=existingOverlay?null:this.findOverlayForGroup(group),overlay=new FloatingOverlay(group,opts,this.container,this.portalLayer);if(this.floatingOverlays.set(group.id,overlay),this.layout.findGroupNode(group)&&this.layout.removeGroup(group),existingOverlay?.internalLayout){existingOverlay.internalLayout.removeGroup(group);const remaining=this.cleanupOrphanedFloatingLeaf(existingOverlay);remaining.length>0?this.floatingOverlays.set(remaining[0].id,existingOverlay):existingOverlay.dispose()}else existingOverlay?existingOverlay.dispose():parentOverlay?.internalLayout&&(parentOverlay.internalLayout.removeGroup(group),this.cleanupOrphanedFloatingLeaf(parentOverlay));return group.isInFloatingSplit=!1,group.location="floating",overlay.updateTotalTabCount(),overlay}dockGroup(groupId,position,initialSize){const group=this.groups.get(groupId);if(!group||groupId===this.mainGroupId)return;const mainGroup=this.mainGroupId?this.groups.get(this.mainGroupId):void 0;if(!mainGroup)return;const directOverlay=this.floatingOverlays.get(groupId),parentOverlay=directOverlay?null:this.findOverlayForGroup(group);if(this.layout.splitGroup(mainGroup,group,position,initialSize)){if(directOverlay)if(directOverlay.internalLayout){directOverlay.internalLayout.removeGroup(group),this.floatingOverlays.delete(groupId);const remaining=this.cleanupOrphanedFloatingLeaf(directOverlay);remaining.length>0?this.floatingOverlays.set(remaining[0].id,directOverlay):directOverlay.dispose()}else directOverlay.dispose(),this.floatingOverlays.delete(groupId);else parentOverlay?.internalLayout&&(parentOverlay.internalLayout.removeGroup(group),this.cleanupOrphanedFloatingLeaf(parentOverlay));group.location="grid",group.isInFloatingSplit=!1}}getFloatingOverlay(groupId){return this.floatingOverlays.get(groupId)}dockOverlay(groupId){const overlay=this.floatingOverlays.get(groupId);if(!overlay)return;const mainGroup=this.mainGroupId?this.groups.get(this.mainGroupId):void 0;if(!mainGroup)return;if(!overlay.internalLayout){this.dockGroup(groupId,"right");return}const allGroups=overlay.internalLayout.allGroups();if(allGroups.length===0)return;const first=allGroups[0];this.layout.splitGroup(mainGroup,first,"right"),first.location="grid",first.isInFloatingSplit=!1;for(let i=1;i<allGroups.length;i++){const g=allGroups[i];this.layout.splitGroup(first,g,"bottom"),g.location="grid",g.isInFloatingSplit=!1}overlay.internalLayout.dispose(),overlay.internalLayout=null,overlay.dispose(),this.floatingOverlays.delete(groupId)}findOverlayContaining(groupId){const group=this.groups.get(groupId);if(group)return this.findOverlayForGroup(group)??void 0}movePanel(panelId,targetGroupId){const panel=this.panels.get(panelId);if(!panel)return;const sourceGroup=panel.group;if(!sourceGroup||sourceGroup.id===targetGroupId)return;const targetGroup=this.groups.get(targetGroupId);targetGroup&&(sourceGroup.detachPanel(panelId),targetGroup.addPanel(panel),sourceGroup.size===0&&sourceGroup.id!==this.mainGroupId&&this.removeGroup(sourceGroup.id))}serializeLayout(){const floatingGroups=[];for(const[groupId,overlay]of this.floatingOverlays){const entry={groupId,bounds:overlay.getBounds(),internalLayout:overlay.internalLayout?.toJSON()??null};overlay.isMaximized&&(entry.isMaximized=!0),floatingGroups.push(entry)}const panelLocations={};for(const[panelId,panel]of this.panels)panel.group&&(panelLocations[panelId]=panel.group.id);return{mainLayout:this.layout.toJSON(),floatingGroups,panelLocations}}getFloatingOverlays(){return this.floatingOverlays}onDidRemovePanel(cb){return this.onPanelRemovedCbs.push(cb),{dispose:()=>{const idx=this.onPanelRemovedCbs.indexOf(cb);idx!==-1&&this.onPanelRemovedCbs.splice(idx,1)}}}dispose(){if(!this.disposed){this.disposed=!0,this.cancelTabDrag(),cancelAnimationFrame(this.portalRaf);for(const overlay of this.floatingOverlays.values())overlay.dispose();this.floatingOverlays.clear();for(const group of this.groups.values())group.dispose();this.groups.clear(),this.panels.clear(),this.onPanelRemovedCbs=[],this.dropOverlay.remove();for(const portal of this.portals.values())portal.entry.remove();this.portals.clear(),this.portalLayer.remove(),this.layout.dispose()}}wireGroupCallbacks(group){group.onTabClose(panelId=>{if(this._beforeTabClose){const result=this._beforeTabClose(panelId);result&&typeof result.then=="function"?result.then(allowed=>{allowed&&this.removePanel(panelId)}):result!==!1&&this.removePanel(panelId);return}this.removePanel(panelId)}),group.onTabPointerDown((panelId,e)=>{this.onTabPointerDown(panelId,group,e)}),group.onTabPopOut(panelId=>{this.detachPanelToFloating(panelId,window.innerWidth/2,window.innerHeight/2)})}onTabPointerDown(panelId,sourceGroup,e){if(this.dragState)return;this.dragState={panelId,sourceGroup,startX:e.clientX,startY:e.clientY,isDragging:!1,ghost:null,iframes:null,currentZone:null};const onMove=ev=>{if(!this.dragState)return;if(!this.dragState.isDragging){const dx=ev.clientX-this.dragState.startX,dy=ev.clientY-this.dragState.startY;if(dx*dx+dy*dy<25)return;this.dragState.isDragging=!0,this.dragState.iframes=disableIframePointEvents(),this.dragState.ghost=this.createDragGhost(panelId),this.container.appendChild(this.dragState.ghost)}this.dragState.ghost.style.left=`${ev.clientX+8}px`,this.dragState.ghost.style.top=`${ev.clientY+8}px`;let zone=this.hitTestDropZone(ev.clientX,ev.clientY);zone=this.applyDragConstraints(zone,this.dragState.sourceGroup),this.updateDropOverlay(zone)},onUp=ev=>{if(document.removeEventListener("pointermove",onMove),document.removeEventListener("pointerup",onUp),document.removeEventListener("pointercancel",onCancel),!this.dragState)return;if(!this.dragState.isDragging){sourceGroup.activatePanel(panelId),this.dragState=null;return}this.dragState.ghost?.remove(),this.dragState.iframes?.release(),this.updateDropOverlay(null);const zone=this.applyDragConstraints(this.hitTestDropZone(ev.clientX,ev.clientY),sourceGroup);if(zone)switch(zone.kind){case"header":case"content-center":zone.group.id===sourceGroup.id?sourceGroup.reorderPanel(panelId,ev.clientX):this.movePanel(panelId,zone.group.id);break;case"content-split":this.dockTabFromDrag(panelId,zone.direction,zone.group);break}this.dragState=null},onCancel=()=>{document.removeEventListener("pointermove",onMove),document.removeEventListener("pointerup",onUp),document.removeEventListener("pointercancel",onCancel),this.cancelTabDrag()};document.addEventListener("pointermove",onMove),document.addEventListener("pointerup",onUp),document.addEventListener("pointercancel",onCancel)}cancelTabDrag(){this.dragState&&(this.dragState.ghost?.remove(),this.dragState.iframes?.release(),this.updateDropOverlay(null),this.dragState=null)}createDragGhost(panelId){const panel=this.panels.get(panelId),ghost=document.createElement("div");return ghost.className="mb-drag-ghost",ghost.innerHTML=SVG_WINDOW,ghost.title=panel?.title||panelId,ghost}hitTestDropZone(x,y,skipGroupId){const floatingEntries=[...this.floatingOverlays.entries()].filter(([,overlay])=>overlay.element.style.display!=="none").sort((a,b)=>{const zA=parseInt(a[1].element.style.zIndex||"0");return parseInt(b[1].element.style.zIndex||"0")-zA});for(const[,overlay]of floatingEntries){const overlayGroups=overlay.internalLayout?overlay.internalLayout.allGroups():[overlay.group];for(const group of overlayGroups){if(group.id===skipGroupId||group.locked==="no-drop-target")continue;if(!group.headerHidden){const hr=group.headerElement.getBoundingClientRect();if(x>=hr.left&&x<=hr.right&&y>=hr.top&&y<=hr.bottom)return{kind:"header",group}}const cr=group.contentElement.getBoundingClientRect();if(x>=cr.left&&x<=cr.right&&y>=cr.top&&y<=cr.bottom)return this.classifyContentZone(x,y,cr,group)}}for(const group of this.groups.values()){if(this.floatingOverlays.has(group.id)||this.findOverlayForGroup(group)||group.id===skipGroupId)continue;if(!group.headerHidden){const hr=group.headerElement.getBoundingClientRect();if(x>=hr.left&&x<=hr.right&&y>=hr.top&&y<=hr.bottom&&group.locked!=="no-drop-target")return{kind:"header",group}}const cr=group.contentElement.getBoundingClientRect();if(x>=cr.left&&x<=cr.right&&y>=cr.top&&y<=cr.bottom)return this.classifyContentZone(x,y,cr,group)}return null}classifyContentZone(x,y,rect,group){if(group.locked==="no-drop-target"){const dT2=y-rect.top,dB2=rect.bottom-y,dL2=x-rect.left,dR2=rect.right-x;let direction;return dT2<=dB2&&dT2<=dL2&&dT2<=dR2?direction="top":dB2<=dT2&&dB2<=dL2&&dB2<=dR2?direction="bottom":dL2<=dR2?direction="left":direction="right",{kind:"content-split",group,direction}}const edgeSize=this.splitEdgeSize,dT=y-rect.top,dB=rect.bottom-y,dL=x-rect.left,dR=rect.right-x;if(Math.min(dT,dB,dL,dR)<edgeSize){let direction;return dT<=dB&&dT<=dL&&dT<=dR?direction="top":dB<=dT&&dB<=dL&&dB<=dR?direction="bottom":dL<=dR?direction="left":direction="right",{kind:"content-split",group,direction}}return{kind:"content-center",group}}applyDragConstraints(zone,sourceGroup){if(!zone)return null;if(!("group"in zone))return zone;const targetInOverlay=this.findOverlayForGroup(zone.group)!==null,targetIsLocked=!!zone.group.locked;return(zone.kind==="content-center"||zone.kind==="header")&&targetIsLocked||sourceGroup.dockingBlocked&&!targetInOverlay?null:zone.kind==="content-split"&&targetInOverlay&&sourceGroup.dialogDockingBlocked?{kind:"content-center",group:zone.group}:zone}updateDropOverlay(zone){const prev=this.dragState?.currentZone??null;if(prev&&prev.kind==="header"&&prev.group.headerElement.classList.remove("mb-group-header--drop-target"),this.dropOverlay.style.display="none",zone===null){this.dragState&&(this.dragState.currentZone=null);return}switch(zone.kind){case"header":zone.group.headerElement.classList.add("mb-group-header--drop-target");break;case"content-center":{const rect=zone.group.contentElement.getBoundingClientRect();this.positionDropOverlay(rect.left,rect.top,rect.width,rect.height),this.dropOverlay.dataset.zone="center";break}case"content-split":this.showSplitIndicator(zone.group,zone.direction);break}this.dragState&&(this.dragState.currentZone=zone)}showSplitIndicator(group,direction){const rect=group.contentElement.getBoundingClientRect();switch(direction){case"top":this.positionDropOverlay(rect.left,rect.top,rect.width,rect.height/2);break;case"bottom":this.positionDropOverlay(rect.left,rect.top+rect.height/2,rect.width,rect.height/2);break;case"left":this.positionDropOverlay(rect.left,rect.top,rect.width/2,rect.height);break;case"right":this.positionDropOverlay(rect.left+rect.width/2,rect.top,rect.width/2,rect.height);break}this.dropOverlay.dataset.zone=direction}positionDropOverlay(left,top,width,height){const el=this.dropOverlay;el.style.display="block",el.style.left=`${left}px`,el.style.top=`${top}px`,el.style.width=`${width}px`,el.style.height=`${height}px`}detachPanelToFloating(panelId,_x,_y){const panel=this.panels.get(panelId);if(!panel||!panel.group||panel.group.id===this.mainGroupId)return;const fw=Math.min(600,window.innerWidth*.8),fh=Math.min(450,window.innerHeight*.7),newGroup=this.addGroup({floating:{x:(window.innerWidth-fw)/2,y:(window.innerHeight-fh)/2,width:fw,height:fh}});this.movePanel(panelId,newGroup.id),this.onGroupCreatedByDragCb?.(newGroup)}dockTabFromDrag(panelId,direction,targetGroup){const layoutForGroup=this.getLayoutForGroup(targetGroup);if(!layoutForGroup)return;const newGroup=new PanelGroup;if(this.groups.set(newGroup.id,newGroup),this.wireGroupCallbacks(newGroup),!layoutForGroup.splitGroup(targetGroup,newGroup,direction)){this.groups.delete(newGroup.id),newGroup.dispose(),this.movePanel(panelId,targetGroup.id);return}const overlayForTarget=this.findOverlayForGroup(targetGroup);overlayForTarget?.internalLayout&&(overlayForTarget.setDragGroup(newGroup),newGroup.location="floating",this.updateFloatingSplitState(overlayForTarget)),this.movePanel(panelId,newGroup.id),overlayForTarget&&overlayForTarget.updateTotalTabCount(),this.onGroupCreatedByDragCb?.(newGroup)}getLayoutForGroup(group){if(this.layout.findGroupNode(group))return this.layout;const overlay=this.findOverlayForGroup(group);return overlay?(overlay.internalLayout||(overlay.internalLayout=new SplitLayout(overlay.element),overlay.internalLayout.setMainGroup(overlay.group)),overlay.internalLayout):null}escapeGroupFromSplit(groupId){const group=this.groups.get(groupId);if(!group||!group.isInFloatingSplit)return;const overlay=this.findOverlayForGroup(group);if(!overlay?.internalLayout)return;const rect=overlay.element.getBoundingClientRect(),wasOwner=this.floatingOverlays.get(groupId)===overlay,newOverlay=new FloatingOverlay(group,{x:Math.min(rect.left+30,window.innerWidth-320),y:Math.min(rect.top+30,window.innerHeight-220),width:Math.max(300,rect.width*.6),height:Math.max(200,rect.height*.8)},this.container,this.portalLayer);this.floatingOverlays.set(groupId,newOverlay),overlay.internalLayout.removeGroup(group);const remaining=this.cleanupOrphanedFloatingLeaf(overlay);wasOwner&&remaining.length>0?this.floatingOverlays.set(remaining[0].id,overlay):remaining.length===0&&overlay.dispose(),group.isInFloatingSplit=!1,group.location==="floating"?group.fireLocationChanged():group.location="floating"}updateFloatingSplitState(overlay){if(!overlay.internalLayout)return;const groups=overlay.internalLayout.allGroups(),isInSplit=groups.length>1;for(const g of groups)g.location="floating",g.isInFloatingSplit=isInSplit;overlay.repositionToolbar()}cleanupOrphanedFloatingLeaf(overlay){if(!overlay.internalLayout)return[];const remaining=overlay.internalLayout.allGroups();return remaining.length<=1?(remaining.length===1&&(overlay.element.appendChild(remaining[0].element),remaining[0].isInFloatingSplit=!1),overlay.internalLayout.dispose(),overlay.internalLayout=null,remaining.length===1&&(overlay.setDragGroup(remaining[0]),remaining[0].location="floating",overlay.repositionToolbar())):this.updateFloatingSplitState(overlay),overlay.updateTotalTabCount(),remaining}minimizeDocked(group){const pos=this.layout.getGroupPosition(group);return this.layout.findGroupNode(group)&&this.layout.removeGroup(group),pos?{siblingGroupId:pos.siblingGroup.id,direction:pos.direction}:null}restoreDocked(group,position,initialSize,siblingGroupId){if(siblingGroupId){const sibling=this.groups.get(siblingGroupId);if(sibling&&this.layout.findGroupNode(sibling)&&this.layout.splitGroup(sibling,group,position,initialSize))return}const mainGroup=this.mainGroupId?this.groups.get(this.mainGroupId):void 0;mainGroup&&this.layout.splitGroup(mainGroup,group,position,initialSize)}findOverlayForGroup(group){const direct=this.floatingOverlays.get(group.id);if(direct)return direct;for(const overlay of this.floatingOverlays.values())if(overlay.internalLayout?.findGroupNode(group))return overlay;return null}registerPortal(panelId,element,anchor){const entry=document.createElement("div");entry.className="mb-iframe-portal",entry.dataset.portalId=panelId,this.portalLayer.appendChild(entry),entry.appendChild(element),this.portals.set(panelId,{entry,anchor})}unregisterPortal(panelId){const portal=this.portals.get(panelId);portal&&(portal.entry.remove(),this.portals.delete(panelId))}syncPortals(){if(this.disposed)return;const updates=[];for(const[,portal]of this.portals){const{entry,anchor}=portal;if(anchor.offsetParent===null)updates.push({entry,rect:null,zIndex:"0"});else{const overlay=anchor.closest(".mb-floating-overlay"),overlayZ=overlay?.style.zIndex;updates.push({entry,rect:anchor.getBoundingClientRect(),zIndex:overlay?String(parseInt(overlayZ||"100000",10)+1):"50"})}}for(const{entry,rect,zIndex}of updates)rect?(entry.style.display="",entry.style.left=`${rect.left}px`,entry.style.top=`${rect.top}px`,entry.style.width=`${rect.width}px`,entry.style.height=`${rect.height}px`,entry.style.zIndex=zIndex):entry.style.display="none";this.portalRaf=requestAnimationFrame(()=>this.syncPortals())}}export{FloatingOverlay,Panel,PanelGroup,PanelManager,SplitLayout};
|
|
1
|
+
import{SVG_POPOUT,SVG_WINDOW}from"./panel-setup.js";let iframeDragDepth=0;function disableIframePointEvents(){return iframeDragDepth++,document.documentElement.classList.add("mb-dragging"),{release(){--iframeDragDepth<=0&&(iframeDragDepth=0,document.documentElement.classList.remove("mb-dragging"))}}}class Panel{constructor(id,element,title){this.group=null;this.id=id,this.element=element,this.title=title||id,this.wrapper=document.createElement("div"),this.wrapper.className="mb-panel",this.wrapper.dataset.panelId=id,this.wrapper.dataset.active="false",this.wrapper.appendChild(element)}}let groupIdCounter=0;class PanelGroup{constructor(id){this._panels=[];this._activePanel=null;this._headerHidden=!1;this._locked=!1;this._onTabClose=null;this._onTabPointerDown=null;this._onTabPopOut=null;this._location="grid";this._onLocationChangedCb=null;this._isInFloatingSplit=!1;this._onSplitStateChangedCb=null;this._dragConstraint="any";this._dockingBlocked=!1;this._dialogDockingBlocked=!1;this._onPanelCountChangedCb=null;this._onActivePanelChangedCb=null;this.id=id||`group-${++groupIdCounter}`,this.element=document.createElement("div"),this.element.className="mb-group",this.element.dataset.groupId=this.id,this.headerElement=document.createElement("div"),this.headerElement.className="mb-group-header",this.headerPrefix=document.createElement("div"),this.headerPrefix.className="mb-group-header-prefix",this.tabsElement=document.createElement("div"),this.tabsElement.className="mb-group-tabs",this.headerVoid=document.createElement("div"),this.headerVoid.className="mb-group-header-void",this.headerActions=document.createElement("div"),this.headerActions.className="mb-group-header-actions",this.headerElement.appendChild(this.headerPrefix),this.headerElement.appendChild(this.tabsElement),this.headerElement.appendChild(this.headerVoid),this.headerElement.appendChild(this.headerActions),this.contentElement=document.createElement("div"),this.contentElement.className="mb-group-content",this.element.appendChild(this.headerElement),this.element.appendChild(this.contentElement)}get panels(){return this._panels}get activePanel(){return this._activePanel}get size(){return this._panels.length}get locked(){return this._locked}set locked(value){this._locked=value}setHeaderHidden(hidden){this._headerHidden=hidden,this.headerElement.style.display=hidden?"none":""}get headerHidden(){return this._headerHidden}setHeaderActions(element){this.headerActions.innerHTML="",this.headerActions.appendChild(element)}setHeaderPrefix(element){this.headerPrefix.innerHTML="",this.headerPrefix.appendChild(element)}onTabClose(cb){this._onTabClose=cb}onTabPointerDown(cb){this._onTabPointerDown=cb}get location(){return this._location}set location(value){this._location!==value&&(this._location=value,this._onLocationChangedCb?.(value))}onLocationChanged(cb){this._onLocationChangedCb=cb}fireLocationChanged(){this._onLocationChangedCb?.(this._location)}get isInFloatingSplit(){return this._isInFloatingSplit}set isInFloatingSplit(value){this._isInFloatingSplit!==value&&(this._isInFloatingSplit=value,this._onSplitStateChangedCb?.(value))}onSplitStateChanged(cb){this._onSplitStateChangedCb=cb}onTabPopOut(cb){this._onTabPopOut=cb}get dragConstraint(){return this._dragConstraint}set dragConstraint(v){this._dragConstraint=v}get dockingBlocked(){return this._dockingBlocked}set dockingBlocked(v){this._dockingBlocked=v}get dialogDockingBlocked(){return this._dialogDockingBlocked}set dialogDockingBlocked(v){this._dialogDockingBlocked=v}onPanelCountChanged(cb){this._onPanelCountChangedCb=cb}onActivePanelChanged(cb){this._onActivePanelChangedCb=cb}addPanel(panel){if(this._panels.some(p=>p.id===panel.id))return;panel.group=this,this._panels.push(panel),this.contentElement.appendChild(panel.wrapper);const tab=this.createTab(panel);this.tabsElement.appendChild(tab),this.activatePanel(panel.id),this.element.dataset.tabCount=String(this._panels.length),this._onPanelCountChangedCb?.(this._panels.length)}removePanel(panelId){const idx=this._panels.findIndex(p=>p.id===panelId);if(idx===-1)return null;const panel=this._panels[idx];if(this._panels.splice(idx,1),panel.wrapper.remove(),this.tabsElement.querySelector(`[data-tab-id="${panelId}"]`)?.remove(),panel.group=null,this._activePanel===panel&&(this._activePanel=null,this._panels.length>0)){const newActive=this._panels[Math.min(idx,this._panels.length-1)];newActive&&this.activatePanel(newActive.id)}return this.element.dataset.tabCount=String(this._panels.length),this._onPanelCountChangedCb?.(this._panels.length),panel}detachPanel(panelId){const idx=this._panels.findIndex(p=>p.id===panelId);if(idx===-1)return null;const panel=this._panels[idx];if(this._panels.splice(idx,1),this.tabsElement.querySelector(`[data-tab-id="${panelId}"]`)?.remove(),panel.group=null,this._activePanel===panel&&(this._activePanel=null,this._panels.length>0)){const newActive=this._panels[Math.min(idx,this._panels.length-1)];newActive&&this.activatePanel(newActive.id)}return this.element.dataset.tabCount=String(this._panels.length),this._onPanelCountChangedCb?.(this._panels.length),panel}activatePanel(panelId){const panel=this._panels.find(p=>p.id===panelId);if(!panel)return;this._activePanel=panel;for(const p of this._panels)p.wrapper.dataset.active=p===panel?"true":"false";const tabs=this.tabsElement.querySelectorAll(".mb-tab");for(const tab of tabs){const isActive=tab.dataset.tabId===panelId;tab.dataset.active=isActive?"true":"false"}this._onActivePanelChangedCb?.(panelId)}reorderPanel(panelId,dropX){const panelIdx=this._panels.findIndex(p=>p.id===panelId);if(panelIdx===-1)return;const panel=this._panels[panelIdx],tabs=Array.from(this.tabsElement.querySelectorAll(".mb-tab"));let targetIdx=this._panels.length;for(let i=0;i<tabs.length;i++){const rect=tabs[i].getBoundingClientRect();if(dropX<rect.left+rect.width/2){targetIdx=i;break}}if(targetIdx===panelIdx||targetIdx===panelIdx+1)return;this._panels.splice(panelIdx,1);const insertAt=panelIdx<targetIdx?targetIdx-1:targetIdx;this._panels.splice(insertAt,0,panel);const tabEl=this.tabsElement.querySelector(`[data-tab-id="${panelId}"]`);if(tabEl){const refTab=this.tabsElement.querySelectorAll(".mb-tab")[insertAt];refTab&&refTab!==tabEl?this.tabsElement.insertBefore(tabEl,refTab):this.tabsElement.appendChild(tabEl)}}createTab(panel){const tab=document.createElement("div");tab.className="mb-tab",tab.dataset.tabId=panel.id,tab.dataset.active="false";const label=document.createElement("span");label.className="mb-tab-label",label.innerHTML=SVG_WINDOW,label.title=panel.title,tab.appendChild(label);const actions=document.createElement("div");actions.className="mb-tab-actions";const popOutBtn=document.createElement("button");popOutBtn.className="mb-tab-popout",popOutBtn.title="Pop out",popOutBtn.innerHTML=SVG_POPOUT,popOutBtn.addEventListener("click",e=>{e.stopPropagation(),this._onTabPopOut?.(panel.id)}),actions.appendChild(popOutBtn);const closeBtn=document.createElement("button");return closeBtn.className="mb-tab-close",closeBtn.title="Close",closeBtn.innerHTML='<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"><line x1="4" y1="4" x2="12" y2="12"/><line x1="12" y1="4" x2="4" y2="12"/></svg>',closeBtn.addEventListener("click",e=>{e.stopPropagation(),this._onTabClose?.(panel.id)}),actions.appendChild(closeBtn),tab.appendChild(actions),tab.addEventListener("pointerdown",e=>{e.target.closest(".mb-tab-close")||e.target.closest(".mb-tab-popout")||e.button===0&&(e.preventDefault(),this._onTabPointerDown?.(panel.id,e))}),tab}dispose(){this._panels=[],this._activePanel=null,this.element.remove()}}let zIndexCounter=1e5;class FloatingOverlay{constructor(group,opts,parentElement,insertBefore){this.internalLayout=null;this.toolbarElement=null;this.savedBounds=null;this._isMaximized=!1;this._onDragEnd=null;this._onDragMove=null;this.group=group,this.bounds={...opts},this.element=document.createElement("div"),this.element.className="mb-floating-overlay",this.element.dataset.groupId=group.id,this.applyBounds();const directions=["n","s","e","w","ne","nw","se","sw"];for(const dir of directions){const handle=document.createElement("div");handle.className=`mb-resize-handle mb-resize-${dir}`,handle.addEventListener("pointerdown",e=>this.onResizeStart(e,dir)),this.element.appendChild(handle)}this.element.addEventListener("pointerdown",()=>this.bringToFront(),!0),group.headerVoid.addEventListener("pointerdown",e=>this.onDragStart(e)),group.headerVoid.style.cursor="grab";const parent=parentElement??document.body;insertBefore?parent.insertBefore(this.element,insertBefore):parent.appendChild(this.element),this.element.appendChild(group.element),this.bringToFront()}get isMaximized(){return this._isMaximized}set onDragEnd(cb){this._onDragEnd=cb}set onDragMove(cb){this._onDragMove=cb}bringToFront(){zIndexCounter+=2,this.element.style.zIndex=String(zIndexCounter)}maximize(){this._isMaximized||(this.savedBounds={...this.bounds},this._isMaximized=!0,this.element.style.inset="0",this.element.style.width="auto",this.element.style.height="auto",this.element.classList.add("mb-floating-maximized"))}restore(){!this._isMaximized||!this.savedBounds||(this._isMaximized=!1,this.bounds={...this.savedBounds},this.savedBounds=null,this.element.classList.remove("mb-floating-maximized"),this.element.style.inset="",this.applyBounds())}hide(){this.element.style.display="none"}show(){this.element.style.display=""}dispose(){this.internalLayout&&(this.internalLayout.dispose(),this.internalLayout=null),this.removeToolbar(),this.element.remove()}getBounds(){return{...this.bounds}}setBounds(partial){if(this._isMaximized)return;const pad=10;partial.width!==void 0&&(this.bounds.width=Math.min(partial.width,window.innerWidth-this.bounds.x-pad)),partial.height!==void 0&&(this.bounds.height=Math.min(partial.height,window.innerHeight-this.bounds.y-pad)),this.applyBounds()}setFullBounds(bounds){if(this._isMaximized)return;const vw=window.innerWidth,vh=window.innerHeight,pad=10,minVisible=100;this.bounds={width:Math.max(minVisible,Math.min(bounds.width,vw-pad)),height:Math.max(minVisible,Math.min(bounds.height,vh-pad)),x:Math.max(0,Math.min(bounds.x,vw-minVisible)),y:Math.max(0,Math.min(bounds.y,vh-minVisible))},this.applyBounds()}applyBounds(){this.element.style.position="fixed",this.element.style.left=`${this.bounds.x}px`,this.element.style.top=`${this.bounds.y}px`,this.element.style.width=`${this.bounds.width}px`,this.element.style.height=`${this.bounds.height}px`}setDragGroup(newGroup){newGroup.headerVoid.addEventListener("pointerdown",e=>this.onDragStart(e)),newGroup.headerVoid.style.cursor="grab"}setToolbar(el){this.removeToolbar(),this.toolbarElement=el,this.getToolbarHost().headerActions.appendChild(el)}removeToolbar(){this.toolbarElement&&(this.toolbarElement.remove(),this.toolbarElement=null)}repositionToolbar(){this.toolbarElement&&this.getToolbarHost().headerActions.appendChild(this.toolbarElement)}getToolbarHost(){if(!this.internalLayout)return this.group;const root=this.internalLayout.getRoot();return root?FloatingOverlay.topRightGroup(root):this.group}static topRightGroup(node){return node.kind==="leaf"?node.group:node.direction==="horizontal"?FloatingOverlay.topRightGroup(node.second):FloatingOverlay.topRightGroup(node.first)}get hasToolbar(){return this.toolbarElement!==null}getAllGroups(){return this.internalLayout?.allGroups()??[this.group]}updateTotalTabCount(){const groups=this.getAllGroups();let total=0;for(const g of groups)total+=g.size;this.element.dataset.totalTabCount=String(total)}onDragStart(e){if(this._isMaximized)return;e.preventDefault();const handle=e.currentTarget,startX=e.clientX,startY=e.clientY,origLeft=this.bounds.x,origTop=this.bounds.y,iframes=disableIframePointEvents();handle.style.cursor="grabbing",handle.setPointerCapture(e.pointerId);const onMove=ev=>{const dx=ev.clientX-startX,dy=ev.clientY-startY;this.bounds.x=Math.max(0,Math.min(origLeft+dx,window.innerWidth-this.bounds.width)),this.bounds.y=Math.max(0,Math.min(origTop+dy,window.innerHeight-this.bounds.height)),this.applyBounds(),this._onDragMove?.(this.bounds.x+this.bounds.width/2,this.bounds.y+this.bounds.height/2)},onUp=()=>{iframes.release(),handle.style.cursor="grab",handle.removeEventListener("pointermove",onMove),handle.removeEventListener("pointerup",onUp),handle.removeEventListener("pointercancel",onUp),this._onDragEnd?.(this.bounds.x+this.bounds.width/2,this.bounds.y+this.bounds.height/2)};handle.addEventListener("pointermove",onMove),handle.addEventListener("pointerup",onUp),handle.addEventListener("pointercancel",onUp)}onResizeStart(e,dir){if(this._isMaximized)return;e.preventDefault(),e.stopPropagation();const startX=e.clientX,startY=e.clientY,orig={...this.bounds},handle=e.currentTarget,minW=200,minH=100,iframes=disableIframePointEvents();handle.setPointerCapture(e.pointerId);const onMove=ev=>{const dx=ev.clientX-startX,dy=ev.clientY-startY;if(dir.includes("e")&&(this.bounds.width=Math.max(minW,orig.width+dx)),dir.includes("w")){const newW=Math.max(minW,orig.width-dx);this.bounds.x=orig.x+(orig.width-newW),this.bounds.width=newW}if(dir.includes("s")&&(this.bounds.height=Math.max(minH,orig.height+dy)),dir.includes("n")){const newH=Math.max(minH,orig.height-dy);this.bounds.y=orig.y+(orig.height-newH),this.bounds.height=newH}const pad=10;this.bounds.x=Math.max(0,this.bounds.x),this.bounds.y=Math.max(0,this.bounds.y),this.bounds.x+this.bounds.width>window.innerWidth-pad&&(this.bounds.width=window.innerWidth-this.bounds.x-pad),this.bounds.y+this.bounds.height>window.innerHeight-pad&&(this.bounds.height=window.innerHeight-this.bounds.y-pad),this.applyBounds()},onUp=()=>{iframes.release(),handle.removeEventListener("pointermove",onMove),handle.removeEventListener("pointerup",onUp),handle.removeEventListener("pointercancel",onUp)};handle.addEventListener("pointermove",onMove),handle.addEventListener("pointerup",onUp),handle.addEventListener("pointercancel",onUp)}}class SplitLayout{constructor(container){this.root=null;this.element=document.createElement("div"),this.element.className="mb-layout",container.appendChild(this.element)}getRoot(){return this.root}setMainGroup(group){const leaf=this.createLeaf(group);leaf.element.style.flex="1",this.root=leaf,this.element.appendChild(leaf.element)}splitGroup(targetGroup,newGroup,direction,newGroupSize){const splitDir=this.dockToSplitDirection(direction),leafNode=this.findGroupNode(targetGroup);if(!leafNode)return!1;const newLeafEl=document.createElement("div");newLeafEl.className="mb-split-leaf",newLeafEl.style.flex="1";const splitEl=document.createElement("div");splitEl.className=`mb-split-container ${splitDir==="horizontal"?"mb-split-horizontal":"mb-split-vertical"}`,splitEl.style.flex=leafNode.element.style.flex||"1",splitEl.style.minWidth="0",splitEl.style.minHeight="0";const separator=document.createElement("div"),isVerticalSplit=splitDir==="vertical";separator.className=`mb-layout-separator ${isVerticalSplit?"mb-layout-separator-h":"mb-layout-separator-v"}`;const existingFirst=direction==="right"||direction==="bottom";leafNode.element.parentElement.insertBefore(splitEl,leafNode.element),existingFirst?(splitEl.appendChild(leafNode.element),splitEl.appendChild(separator),splitEl.appendChild(newLeafEl)):(splitEl.appendChild(newLeafEl),splitEl.appendChild(separator),splitEl.appendChild(leafNode.element)),newLeafEl.appendChild(newGroup.element),newGroupSize!==void 0&&newGroupSize>0?existingFirst?(leafNode.element.style.flex="1",newLeafEl.style.flex=`0 0 ${newGroupSize}px`):(newLeafEl.style.flex=`0 0 ${newGroupSize}px`,leafNode.element.style.flex="1"):(leafNode.element.style.flex="1",newLeafEl.style.flex="1");const newLeaf={kind:"leaf",group:newGroup,element:newLeafEl},splitNode={kind:"split",direction:splitDir,first:existingFirst?leafNode:newLeaf,second:existingFirst?newLeaf:leafNode,element:splitEl,separator};return separator.addEventListener("pointerdown",e=>this.onSeparatorDrag(e,splitNode)),this.replaceNodeInTree(leafNode,splitNode),leafNode.element.style.display==="none"&&(separator.style.display="none",newLeafEl.dataset.savedFlex=newLeafEl.style.flex,newLeafEl.style.flex="1",leafNode.element.dataset.savedFlex=leafNode.element.style.flex),!0}removeGroup(group){const leafNode=this.findGroupNode(group);if(!leafNode)return;if(this.root===leafNode){leafNode.element.remove(),this.root=null;return}this.restoreMaximizedLeaf(group);const parentSplit=this.findParentSplit(leafNode);if(!parentSplit)return;const sibling=parentSplit.first===leafNode?parentSplit.second:parentSplit.first;this.restoreMaximizedSubtree(sibling),sibling.element.style.flex=parentSplit.element.style.flex||"1",parentSplit.element.parentElement.insertBefore(sibling.element,parentSplit.element),leafNode.element.remove(),parentSplit.separator.remove(),parentSplit.element.remove(),this.replaceNodeInTree(parentSplit,sibling)}findGroupNode(group){return this.findGroupNodeIn(this.root,group)}getGroupPosition(group){const leaf=this.findGroupNode(group);if(!leaf)return null;const parent=this.findParentSplit(leaf);if(!parent)return null;const isFirst=parent.first===leaf,siblingNode=isFirst?parent.second:parent.first,siblingGroup=this.firstGroupIn(siblingNode);if(!siblingGroup)return null;let direction;return parent.direction==="horizontal"?direction=isFirst?"left":"right":direction=isFirst?"top":"bottom",{siblingGroup,direction}}firstGroupIn(node){return node.kind==="leaf"?node.group:this.firstGroupIn(node.first)}collapseLeaf(group){const leaf=this.findGroupNode(group);if(!leaf)return;const parent=this.findParentSplit(leaf);if(parent){const sibling=parent.first===leaf?parent.second:parent.first;sibling.element.dataset.savedFlex=sibling.element.style.flex,sibling.element.style.flex="1",parent.separator.style.display="none"}leaf.element.dataset.savedFlex=leaf.element.style.flex,leaf.element.style.display="none"}expandLeaf(group){const leaf=this.findGroupNode(group);if(!leaf)return;leaf.element.style.display="",leaf.element.dataset.savedFlex!==void 0&&(leaf.element.style.flex=leaf.element.dataset.savedFlex,delete leaf.element.dataset.savedFlex);const parent=this.findParentSplit(leaf);if(parent){parent.separator.style.display="";const sibling=parent.first===leaf?parent.second:parent.first;sibling.element.dataset.savedFlex!==void 0&&(sibling.element.style.flex=sibling.element.dataset.savedFlex,delete sibling.element.dataset.savedFlex)}}maximizeLeaf(group){const leaf=this.findGroupNode(group);if(!leaf)return;let current=leaf,parent=this.findParentSplit(current);for(;parent;){const sibling=parent.first===current?parent.second:parent.first;sibling.element.dataset.maxSavedDisplay===void 0&&(sibling.element.dataset.maxSavedDisplay=sibling.element.style.display),sibling.element.style.display="none",parent.separator.dataset.maxSavedDisplay===void 0&&(parent.separator.dataset.maxSavedDisplay=parent.separator.style.display),parent.separator.style.display="none",current.element.dataset.maxSavedFlex===void 0&&(current.element.dataset.maxSavedFlex=current.element.style.flex),current.element.style.flex="1",current=parent,parent=this.findParentSplit(current)}}restoreMaximizedLeaf(group){const leaf=this.findGroupNode(group);if(!leaf)return;let current=leaf,parent=this.findParentSplit(current);for(;parent;){const sibling=parent.first===current?parent.second:parent.first;sibling.element.dataset.maxSavedDisplay!==void 0&&(sibling.element.style.display=sibling.element.dataset.maxSavedDisplay,delete sibling.element.dataset.maxSavedDisplay),parent.separator.dataset.maxSavedDisplay!==void 0&&(parent.separator.style.display=parent.separator.dataset.maxSavedDisplay,delete parent.separator.dataset.maxSavedDisplay),current.element.dataset.maxSavedFlex!==void 0&&(current.element.style.flex=current.element.dataset.maxSavedFlex,delete current.element.dataset.maxSavedFlex),current=parent,parent=this.findParentSplit(current)}}restoreMaximizedSubtree(node){node.element.dataset.maxSavedDisplay!==void 0&&(node.element.style.display=node.element.dataset.maxSavedDisplay,delete node.element.dataset.maxSavedDisplay),node.element.dataset.maxSavedFlex!==void 0&&(node.element.style.flex=node.element.dataset.maxSavedFlex,delete node.element.dataset.maxSavedFlex),node.kind==="split"&&(node.separator.dataset.maxSavedDisplay!==void 0&&(node.separator.style.display=node.separator.dataset.maxSavedDisplay,delete node.separator.dataset.maxSavedDisplay),this.restoreMaximizedSubtree(node.first),this.restoreMaximizedSubtree(node.second))}allGroups(){const result=[];return this.collectGroups(this.root,result),result}toJSON(){return this.serializeNode(this.root)}restoreFlexFromSerialized(serialized){if(!serialized||!this.root)return;const flexMap=new Map;this.collectFlexValues(serialized,flexMap),this.applyFlexValues(this.root,flexMap)}animateTransition(){const cls=node=>{node&&(node.kind==="leaf"?node.element.classList.add("mb-split-leaf--animating"):(node.element.classList.add("mb-split-container--animating"),node.separator&&node.separator.classList.add("mb-layout-separator--animating"),cls(node.first),cls(node.second)))};cls(this.root);const cleanup=()=>{this.element.querySelectorAll(".mb-split-leaf--animating, .mb-split-container--animating, .mb-layout-separator--animating").forEach(el=>{el.classList.remove("mb-split-leaf--animating","mb-split-container--animating","mb-layout-separator--animating")})},timer=setTimeout(cleanup,350);this.element.addEventListener("transitionend",()=>{clearTimeout(timer),cleanup()},{once:!0})}dispose(){this.element.remove(),this.root=null}createLeaf(group){const leafEl=document.createElement("div");return leafEl.className="mb-split-leaf",leafEl.style.flex="1",leafEl.appendChild(group.element),{kind:"leaf",group,element:leafEl}}dockToSplitDirection(pos){return pos==="left"||pos==="right"?"horizontal":"vertical"}findGroupNodeIn(node,group){return node?node.kind==="leaf"?node.group===group?node:null:this.findGroupNodeIn(node.first,group)??this.findGroupNodeIn(node.second,group):null}collectGroups(node,result){node&&(node.kind==="leaf"?result.push(node.group):(this.collectGroups(node.first,result),this.collectGroups(node.second,result)))}findParentSplit(target){return this.findParentSplitIn(this.root,target)}findParentSplitIn(node,target){return!node||node.kind==="leaf"?null:node.first===target||node.second===target?node:this.findParentSplitIn(node.first,target)??this.findParentSplitIn(node.second,target)}replaceNodeInTree(oldNode,newNode){if(this.root===oldNode){this.root=newNode;return}const parent=this.findParentSplit(oldNode);parent&&(parent.first===oldNode?parent.first=newNode:parent.second=newNode)}collectFlexValues(node,map){node.kind==="leaf"?map.set(node.groupId,node.flex):(this.collectFlexValues(node.first,map),this.collectFlexValues(node.second,map))}applyFlexValues(node,map){if(node.kind==="leaf"){const saved=map.get(node.group.id);saved&&this.isValidFlex(saved)&&(node.element.style.flex=saved)}else this.applyFlexValues(node.first,map),this.applyFlexValues(node.second,map)}isValidFlex(value){if(value.includes("px"))return!0;const n=Number(value);return Number.isFinite(n)&&n>=0}serializeNode(node){return node?node.kind==="leaf"?{kind:"leaf",groupId:node.group.id,flex:node.element.style.flex||"1"}:{kind:"split",direction:node.direction,first:this.serializeNode(node.first),second:this.serializeNode(node.second),flex:node.element.style.flex||"1"}:null}onSeparatorDrag(e,splitNode){if(e.preventDefault(),splitNode.first.element.style.display==="none"||splitNode.second.element.style.display==="none")return;const isHorizontal=splitNode.direction==="horizontal",startPos=isHorizontal?e.clientX:e.clientY,firstEl=splitNode.first.element,secondEl=splitNode.second.element;this.lockDescendantSizes(splitNode.first,isHorizontal),this.lockDescendantSizes(splitNode.second,isHorizontal);const origFirstSize=isHorizontal?firstEl.offsetWidth:firstEl.offsetHeight,origSecondSize=isHorizontal?secondEl.offsetWidth:secondEl.offsetHeight,totalSize=origFirstSize+origSecondSize;if(totalSize<=0)return;const minSize=150,iframes=disableIframePointEvents();splitNode.separator.setPointerCapture(e.pointerId),splitNode.separator.classList.add("mb-layout-separator--active");const onMove=ev=>{if(firstEl.style.display==="none"||secondEl.style.display==="none"){splitNode.separator.releasePointerCapture(ev.pointerId),onUp();return}const delta=(isHorizontal?ev.clientX:ev.clientY)-startPos;let newFirst=origFirstSize+delta,newSecond=origSecondSize-delta;newFirst<minSize&&(newFirst=minSize,newSecond=totalSize-minSize),newSecond<minSize&&(newSecond=minSize,newFirst=totalSize-minSize),firstEl.style.flex=String(newFirst/totalSize),secondEl.style.flex=String(newSecond/totalSize)},onUp=()=>{iframes.release(),splitNode.separator.classList.remove("mb-layout-separator--active"),splitNode.separator.removeEventListener("pointermove",onMove),splitNode.separator.removeEventListener("pointerup",onUp),splitNode.separator.removeEventListener("pointercancel",onUp),this.unlockDescendantSizes(splitNode.first,isHorizontal),this.unlockDescendantSizes(splitNode.second,isHorizontal)};splitNode.separator.addEventListener("pointermove",onMove),splitNode.separator.addEventListener("pointerup",onUp),splitNode.separator.addEventListener("pointercancel",onUp)}lockDescendantSizes(node,isHorizontal){if(node.kind!=="split"||node.direction==="horizontal"!==isHorizontal)return;const firstSize=isHorizontal?node.first.element.getBoundingClientRect().width:node.first.element.getBoundingClientRect().height;node.first.element.style.flex=`0 0 ${firstSize}px`,node.second.element.style.flex="1",this.lockDescendantSizes(node.first,isHorizontal),this.lockDescendantSizes(node.second,isHorizontal)}unlockDescendantSizes(node,isHorizontal){if(node.kind!=="split"||node.direction==="horizontal"!==isHorizontal)return;this.unlockDescendantSizes(node.first,isHorizontal),this.unlockDescendantSizes(node.second,isHorizontal);const firstSize=isHorizontal?node.first.element.getBoundingClientRect().width:node.first.element.getBoundingClientRect().height,secondSize=isHorizontal?node.second.element.getBoundingClientRect().width:node.second.element.getBoundingClientRect().height,total=firstSize+secondSize;total>0?(node.first.element.style.flex=String(firstSize/total),node.second.element.style.flex=String(secondSize/total)):(node.first.element.style.flex="0.5",node.second.element.style.flex="0.5")}}class PanelManager{constructor(opts){this.groups=new Map;this.panels=new Map;this.floatingOverlays=new Map;this.mainGroupId=null;this.onPanelRemovedCbs=[];this.onGroupCreatedByDragCb=null;this.disposed=!1;this.dragState=null;this.portals=new Map;this.portalRaf=0;this.mainGroupCollapsed=!1;this._beforeTabClose=null;this.zBase=0;this.container=opts.container,this.splitEdgeSize=opts.splitEdgeSize??100,this.layout=new SplitLayout(this.container),opts.onPanelRemoved&&this.onPanelRemovedCbs.push(opts.onPanelRemoved),this.onGroupCreatedByDragCb=opts.onGroupCreatedByDrag??null,this.zBase=this.getZBase(),this.zBase!==0&&(zIndexCounter=1e5+this.zBase),this.dropOverlay=document.createElement("div"),this.dropOverlay.className="mb-drop-overlay",this.container.appendChild(this.dropOverlay),this.portalLayer=document.createElement("div"),this.portalLayer.className="mb-iframe-portal-layer",this.container.appendChild(this.portalLayer),this.syncPortals()}getZBase(){const v=getComputedStyle(this.container).getPropertyValue("--mb-adapt-z-base").trim();return parseInt(v,10)||0}setBeforeTabClose(cb){this._beforeTabClose=cb}addPanel(opts){const panel=new Panel(opts.id,opts.element,opts.title);this.panels.set(opts.id,panel);const groupId=opts.groupId;if(groupId){const group=this.groups.get(groupId);group&&(group.addPanel(panel),this.registerPortal(panel.id,panel.element,panel.wrapper))}return panel}removePanel(panelId){const panel=this.panels.get(panelId);if(panel){if(this.unregisterPortal(panelId),panel.group){const group=panel.group;group.removePanel(panelId),group.size===0&&group.id!==this.mainGroupId&&this.removeGroup(group.id)}this.panels.delete(panelId);for(const cb of this.onPanelRemovedCbs)cb(panel)}}getPanel(panelId){return this.panels.get(panelId)}addGroup(opts){const group=new PanelGroup(opts?.id);if(this.groups.set(group.id,group),this.wireGroupCallbacks(group),opts?.floating)this.addFloatingGroup(group,opts.floating);else if(opts?.direction){const mainGroup=this.mainGroupId?this.groups.get(this.mainGroupId):void 0;mainGroup&&this.layout.splitGroup(mainGroup,group,opts.direction,opts.initialSize)}return group}removeGroup(groupId){const group=this.groups.get(groupId);if(!group)return;for(const panel of[...group.panels])this.unregisterPortal(panel.id);const overlay=this.floatingOverlays.get(groupId);if(overlay)if(overlay.internalLayout){overlay.internalLayout.removeGroup(group),this.floatingOverlays.delete(groupId);const remaining=this.cleanupOrphanedFloatingLeaf(overlay);remaining.length>0?this.floatingOverlays.set(remaining[0].id,overlay):overlay.dispose()}else overlay.dispose(),this.floatingOverlays.delete(groupId);if(!overlay){const parentOverlay=this.findOverlayForGroup(group);parentOverlay?.internalLayout&&(parentOverlay.internalLayout.removeGroup(group),this.cleanupOrphanedFloatingLeaf(parentOverlay))}this.layout.findGroupNode(group)&&this.layout.removeGroup(group),group.isInFloatingSplit=!1,group.dispose(),this.groups.delete(groupId)}getGroup(groupId){return this.groups.get(groupId)}getMainGroup(){if(this.mainGroupId)return this.groups.get(this.mainGroupId)}setMainGroup(group){this.mainGroupId=group.id,this.layout.setMainGroup(group)}collapseMainGroup(){const main=this.getMainGroup();!main||this.mainGroupCollapsed||(this.layout.collapseLeaf(main),this.mainGroupCollapsed=!0)}expandMainGroup(){const main=this.getMainGroup();!main||!this.mainGroupCollapsed||(this.layout.expandLeaf(main),this.mainGroupCollapsed=!1)}isMainGroupCollapsed(){return this.mainGroupCollapsed}getDockedGroups(){return this.layout.allGroups()}collapseDockedGroup(group){this.layout.collapseLeaf(group)}expandDockedGroup(group){this.layout.expandLeaf(group)}maximizeDockedGroup(group){this.layout.maximizeLeaf(group)}restoreMaximizedDockedGroup(group){this.layout.restoreMaximizedLeaf(group)}restoreLayoutFlex(serialized){this.layout.restoreFlexFromSerialized(serialized)}addFloatingGroup(group,opts){const existingOverlay=this.floatingOverlays.get(group.id);existingOverlay&&this.floatingOverlays.delete(group.id);const parentOverlay=existingOverlay?null:this.findOverlayForGroup(group),overlay=new FloatingOverlay(group,opts,this.container,this.portalLayer);if(this.floatingOverlays.set(group.id,overlay),this.layout.findGroupNode(group)&&this.layout.removeGroup(group),existingOverlay?.internalLayout){existingOverlay.internalLayout.removeGroup(group);const remaining=this.cleanupOrphanedFloatingLeaf(existingOverlay);remaining.length>0?this.floatingOverlays.set(remaining[0].id,existingOverlay):existingOverlay.dispose()}else existingOverlay?existingOverlay.dispose():parentOverlay?.internalLayout&&(parentOverlay.internalLayout.removeGroup(group),this.cleanupOrphanedFloatingLeaf(parentOverlay));return group.isInFloatingSplit=!1,group.location="floating",overlay.updateTotalTabCount(),overlay}dockGroup(groupId,position,initialSize){const group=this.groups.get(groupId);if(!group||groupId===this.mainGroupId)return;const mainGroup=this.mainGroupId?this.groups.get(this.mainGroupId):void 0;if(!mainGroup)return;const directOverlay=this.floatingOverlays.get(groupId),parentOverlay=directOverlay?null:this.findOverlayForGroup(group);if(this.layout.splitGroup(mainGroup,group,position,initialSize)){if(directOverlay)if(directOverlay.internalLayout){directOverlay.internalLayout.removeGroup(group),this.floatingOverlays.delete(groupId);const remaining=this.cleanupOrphanedFloatingLeaf(directOverlay);remaining.length>0?this.floatingOverlays.set(remaining[0].id,directOverlay):directOverlay.dispose()}else directOverlay.dispose(),this.floatingOverlays.delete(groupId);else parentOverlay?.internalLayout&&(parentOverlay.internalLayout.removeGroup(group),this.cleanupOrphanedFloatingLeaf(parentOverlay));group.location="grid",group.isInFloatingSplit=!1}}getFloatingOverlay(groupId){return this.floatingOverlays.get(groupId)}dockOverlay(groupId){const overlay=this.floatingOverlays.get(groupId);if(!overlay)return;const mainGroup=this.mainGroupId?this.groups.get(this.mainGroupId):void 0;if(!mainGroup)return;if(!overlay.internalLayout){this.dockGroup(groupId,"right");return}const allGroups=overlay.internalLayout.allGroups();if(allGroups.length===0)return;const first=allGroups[0];this.layout.splitGroup(mainGroup,first,"right"),first.location="grid",first.isInFloatingSplit=!1;for(let i=1;i<allGroups.length;i++){const g=allGroups[i];this.layout.splitGroup(first,g,"bottom"),g.location="grid",g.isInFloatingSplit=!1}overlay.internalLayout.dispose(),overlay.internalLayout=null,overlay.dispose(),this.floatingOverlays.delete(groupId)}findOverlayContaining(groupId){const group=this.groups.get(groupId);if(group)return this.findOverlayForGroup(group)??void 0}movePanel(panelId,targetGroupId){const panel=this.panels.get(panelId);if(!panel)return;const sourceGroup=panel.group;if(!sourceGroup||sourceGroup.id===targetGroupId)return;const targetGroup=this.groups.get(targetGroupId);targetGroup&&(sourceGroup.detachPanel(panelId),targetGroup.addPanel(panel),sourceGroup.size===0&&sourceGroup.id!==this.mainGroupId&&this.removeGroup(sourceGroup.id))}serializeLayout(){const floatingGroups=[];for(const[groupId,overlay]of this.floatingOverlays){const entry={groupId,bounds:overlay.getBounds(),internalLayout:overlay.internalLayout?.toJSON()??null};overlay.isMaximized&&(entry.isMaximized=!0),floatingGroups.push(entry)}const panelLocations={};for(const[panelId,panel]of this.panels)panel.group&&(panelLocations[panelId]=panel.group.id);return{mainLayout:this.layout.toJSON(),floatingGroups,panelLocations}}getFloatingOverlays(){return this.floatingOverlays}onDidRemovePanel(cb){return this.onPanelRemovedCbs.push(cb),{dispose:()=>{const idx=this.onPanelRemovedCbs.indexOf(cb);idx!==-1&&this.onPanelRemovedCbs.splice(idx,1)}}}dispose(){if(!this.disposed){this.disposed=!0,this.cancelTabDrag(),cancelAnimationFrame(this.portalRaf);for(const overlay of this.floatingOverlays.values())overlay.dispose();this.floatingOverlays.clear();for(const group of this.groups.values())group.dispose();this.groups.clear(),this.panels.clear(),this.onPanelRemovedCbs=[],this.dropOverlay.remove();for(const portal of this.portals.values())portal.entry.remove();this.portals.clear(),this.portalLayer.remove(),this.layout.dispose()}}wireGroupCallbacks(group){group.onTabClose(panelId=>{if(this._beforeTabClose){const result=this._beforeTabClose(panelId);result&&typeof result.then=="function"?result.then(allowed=>{allowed&&this.removePanel(panelId)}):result!==!1&&this.removePanel(panelId);return}this.removePanel(panelId)}),group.onTabPointerDown((panelId,e)=>{this.onTabPointerDown(panelId,group,e)}),group.onTabPopOut(panelId=>{this.detachPanelToFloating(panelId,window.innerWidth/2,window.innerHeight/2)})}onTabPointerDown(panelId,sourceGroup,e){if(this.dragState)return;this.dragState={panelId,sourceGroup,startX:e.clientX,startY:e.clientY,isDragging:!1,ghost:null,iframes:null,currentZone:null};const onMove=ev=>{if(!this.dragState)return;if(!this.dragState.isDragging){const dx=ev.clientX-this.dragState.startX,dy=ev.clientY-this.dragState.startY;if(dx*dx+dy*dy<25)return;this.dragState.isDragging=!0,this.dragState.iframes=disableIframePointEvents(),this.dragState.ghost=this.createDragGhost(panelId),this.container.appendChild(this.dragState.ghost)}this.dragState.ghost.style.left=`${ev.clientX+8}px`,this.dragState.ghost.style.top=`${ev.clientY+8}px`;let zone=this.hitTestDropZone(ev.clientX,ev.clientY);zone=this.applyDragConstraints(zone,this.dragState.sourceGroup),this.updateDropOverlay(zone)},onUp=ev=>{if(document.removeEventListener("pointermove",onMove),document.removeEventListener("pointerup",onUp),document.removeEventListener("pointercancel",onCancel),!this.dragState)return;if(!this.dragState.isDragging){sourceGroup.activatePanel(panelId),this.dragState=null;return}this.dragState.ghost?.remove(),this.dragState.iframes?.release(),this.updateDropOverlay(null);const zone=this.applyDragConstraints(this.hitTestDropZone(ev.clientX,ev.clientY),sourceGroup);if(zone)switch(zone.kind){case"header":case"content-center":zone.group.id===sourceGroup.id?sourceGroup.reorderPanel(panelId,ev.clientX):this.movePanel(panelId,zone.group.id);break;case"content-split":this.dockTabFromDrag(panelId,zone.direction,zone.group);break}this.dragState=null},onCancel=()=>{document.removeEventListener("pointermove",onMove),document.removeEventListener("pointerup",onUp),document.removeEventListener("pointercancel",onCancel),this.cancelTabDrag()};document.addEventListener("pointermove",onMove),document.addEventListener("pointerup",onUp),document.addEventListener("pointercancel",onCancel)}cancelTabDrag(){this.dragState&&(this.dragState.ghost?.remove(),this.dragState.iframes?.release(),this.updateDropOverlay(null),this.dragState=null)}createDragGhost(panelId){const panel=this.panels.get(panelId),ghost=document.createElement("div");return ghost.className="mb-drag-ghost",ghost.innerHTML=SVG_WINDOW,ghost.title=panel?.title||panelId,ghost}hitTestDropZone(x,y,skipGroupId){const floatingEntries=[...this.floatingOverlays.entries()].filter(([,overlay])=>overlay.element.style.display!=="none").sort((a,b)=>{const zA=parseInt(a[1].element.style.zIndex||"0");return parseInt(b[1].element.style.zIndex||"0")-zA});for(const[,overlay]of floatingEntries){const overlayGroups=overlay.internalLayout?overlay.internalLayout.allGroups():[overlay.group];for(const group of overlayGroups){if(group.id===skipGroupId||group.locked==="no-drop-target")continue;if(!group.headerHidden){const hr=group.headerElement.getBoundingClientRect();if(x>=hr.left&&x<=hr.right&&y>=hr.top&&y<=hr.bottom)return{kind:"header",group}}const cr=group.contentElement.getBoundingClientRect();if(x>=cr.left&&x<=cr.right&&y>=cr.top&&y<=cr.bottom)return this.classifyContentZone(x,y,cr,group)}}for(const group of this.groups.values()){if(this.floatingOverlays.has(group.id)||this.findOverlayForGroup(group)||group.id===skipGroupId)continue;if(!group.headerHidden){const hr=group.headerElement.getBoundingClientRect();if(x>=hr.left&&x<=hr.right&&y>=hr.top&&y<=hr.bottom&&group.locked!=="no-drop-target")return{kind:"header",group}}const cr=group.contentElement.getBoundingClientRect();if(x>=cr.left&&x<=cr.right&&y>=cr.top&&y<=cr.bottom)return this.classifyContentZone(x,y,cr,group)}return null}classifyContentZone(x,y,rect,group){if(group.locked==="no-drop-target"){const dT2=y-rect.top,dB2=rect.bottom-y,dL2=x-rect.left,dR2=rect.right-x;let direction;return dT2<=dB2&&dT2<=dL2&&dT2<=dR2?direction="top":dB2<=dT2&&dB2<=dL2&&dB2<=dR2?direction="bottom":dL2<=dR2?direction="left":direction="right",{kind:"content-split",group,direction}}const edgeSize=this.splitEdgeSize,dT=y-rect.top,dB=rect.bottom-y,dL=x-rect.left,dR=rect.right-x;if(Math.min(dT,dB,dL,dR)<edgeSize){let direction;return dT<=dB&&dT<=dL&&dT<=dR?direction="top":dB<=dT&&dB<=dL&&dB<=dR?direction="bottom":dL<=dR?direction="left":direction="right",{kind:"content-split",group,direction}}return{kind:"content-center",group}}applyDragConstraints(zone,sourceGroup){if(!zone)return null;if(!("group"in zone))return zone;const targetInOverlay=this.findOverlayForGroup(zone.group)!==null,targetIsLocked=!!zone.group.locked;return(zone.kind==="content-center"||zone.kind==="header")&&targetIsLocked||sourceGroup.dockingBlocked&&!targetInOverlay?null:zone.kind==="content-split"&&targetInOverlay&&sourceGroup.dialogDockingBlocked?{kind:"content-center",group:zone.group}:zone}updateDropOverlay(zone){const prev=this.dragState?.currentZone??null;if(prev&&prev.kind==="header"&&prev.group.headerElement.classList.remove("mb-group-header--drop-target"),this.dropOverlay.style.display="none",zone===null){this.dragState&&(this.dragState.currentZone=null);return}switch(zone.kind){case"header":zone.group.headerElement.classList.add("mb-group-header--drop-target");break;case"content-center":{const rect=zone.group.contentElement.getBoundingClientRect();this.positionDropOverlay(rect.left,rect.top,rect.width,rect.height),this.dropOverlay.dataset.zone="center";break}case"content-split":this.showSplitIndicator(zone.group,zone.direction);break}this.dragState&&(this.dragState.currentZone=zone)}showSplitIndicator(group,direction){const rect=group.contentElement.getBoundingClientRect();switch(direction){case"top":this.positionDropOverlay(rect.left,rect.top,rect.width,rect.height/2);break;case"bottom":this.positionDropOverlay(rect.left,rect.top+rect.height/2,rect.width,rect.height/2);break;case"left":this.positionDropOverlay(rect.left,rect.top,rect.width/2,rect.height);break;case"right":this.positionDropOverlay(rect.left+rect.width/2,rect.top,rect.width/2,rect.height);break}this.dropOverlay.dataset.zone=direction}positionDropOverlay(left,top,width,height){const el=this.dropOverlay;el.style.display="block",el.style.left=`${left}px`,el.style.top=`${top}px`,el.style.width=`${width}px`,el.style.height=`${height}px`}detachPanelToFloating(panelId,_x,_y){const panel=this.panels.get(panelId);if(!panel||!panel.group||panel.group.id===this.mainGroupId)return;const fw=Math.min(600,window.innerWidth*.8),fh=Math.min(450,window.innerHeight*.7),newGroup=this.addGroup({floating:{x:(window.innerWidth-fw)/2,y:(window.innerHeight-fh)/2,width:fw,height:fh}});this.movePanel(panelId,newGroup.id),this.onGroupCreatedByDragCb?.(newGroup)}dockTabFromDrag(panelId,direction,targetGroup){const layoutForGroup=this.getLayoutForGroup(targetGroup);if(!layoutForGroup)return;const newGroup=new PanelGroup;if(this.groups.set(newGroup.id,newGroup),this.wireGroupCallbacks(newGroup),!layoutForGroup.splitGroup(targetGroup,newGroup,direction)){this.groups.delete(newGroup.id),newGroup.dispose(),this.movePanel(panelId,targetGroup.id);return}const overlayForTarget=this.findOverlayForGroup(targetGroup);overlayForTarget?.internalLayout&&(overlayForTarget.setDragGroup(newGroup),newGroup.location="floating",this.updateFloatingSplitState(overlayForTarget)),this.movePanel(panelId,newGroup.id),overlayForTarget&&overlayForTarget.updateTotalTabCount(),this.onGroupCreatedByDragCb?.(newGroup)}getLayoutForGroup(group){if(this.layout.findGroupNode(group))return this.layout;const overlay=this.findOverlayForGroup(group);return overlay?(overlay.internalLayout||(overlay.internalLayout=new SplitLayout(overlay.element),overlay.internalLayout.setMainGroup(overlay.group)),overlay.internalLayout):null}escapeGroupFromSplit(groupId){const group=this.groups.get(groupId);if(!group||!group.isInFloatingSplit)return;const overlay=this.findOverlayForGroup(group);if(!overlay?.internalLayout)return;const rect=overlay.element.getBoundingClientRect(),wasOwner=this.floatingOverlays.get(groupId)===overlay,newOverlay=new FloatingOverlay(group,{x:Math.min(rect.left+30,window.innerWidth-320),y:Math.min(rect.top+30,window.innerHeight-220),width:Math.max(300,rect.width*.6),height:Math.max(200,rect.height*.8)},this.container,this.portalLayer);this.floatingOverlays.set(groupId,newOverlay),overlay.internalLayout.removeGroup(group);const remaining=this.cleanupOrphanedFloatingLeaf(overlay);wasOwner&&remaining.length>0?this.floatingOverlays.set(remaining[0].id,overlay):remaining.length===0&&overlay.dispose(),group.isInFloatingSplit=!1,group.location==="floating"?group.fireLocationChanged():group.location="floating"}updateFloatingSplitState(overlay){if(!overlay.internalLayout)return;const groups=overlay.internalLayout.allGroups(),isInSplit=groups.length>1;for(const g of groups)g.location="floating",g.isInFloatingSplit=isInSplit;overlay.repositionToolbar()}cleanupOrphanedFloatingLeaf(overlay){if(!overlay.internalLayout)return[];const remaining=overlay.internalLayout.allGroups();return remaining.length<=1?(remaining.length===1&&(overlay.element.appendChild(remaining[0].element),remaining[0].isInFloatingSplit=!1),overlay.internalLayout.dispose(),overlay.internalLayout=null,remaining.length===1&&(overlay.setDragGroup(remaining[0]),remaining[0].location="floating",overlay.repositionToolbar())):this.updateFloatingSplitState(overlay),overlay.updateTotalTabCount(),remaining}minimizeDocked(group){const pos=this.layout.getGroupPosition(group);return this.layout.findGroupNode(group)&&this.layout.removeGroup(group),pos?{siblingGroupId:pos.siblingGroup.id,direction:pos.direction}:null}restoreDocked(group,position,initialSize,siblingGroupId){if(siblingGroupId){const sibling=this.groups.get(siblingGroupId);if(sibling&&this.layout.findGroupNode(sibling)&&this.layout.splitGroup(sibling,group,position,initialSize))return}const mainGroup=this.mainGroupId?this.groups.get(this.mainGroupId):void 0;mainGroup&&this.layout.splitGroup(mainGroup,group,position,initialSize)}findOverlayForGroup(group){const direct=this.floatingOverlays.get(group.id);if(direct)return direct;for(const overlay of this.floatingOverlays.values())if(overlay.internalLayout?.findGroupNode(group))return overlay;return null}registerPortal(panelId,element,anchor){const entry=document.createElement("div");entry.className="mb-iframe-portal",entry.dataset.portalId=panelId,this.portalLayer.appendChild(entry),entry.appendChild(element),this.portals.set(panelId,{entry,anchor})}unregisterPortal(panelId){const portal=this.portals.get(panelId);portal&&(portal.entry.remove(),this.portals.delete(panelId))}syncPortals(){if(this.disposed)return;const updates=[];for(const[,portal]of this.portals){const{entry,anchor}=portal;if(anchor.offsetParent===null)updates.push({entry,rect:null,zIndex:"0"});else{const overlay=anchor.closest(".mb-floating-overlay"),overlayZ=overlay?.style.zIndex;updates.push({entry,rect:anchor.getBoundingClientRect(),zIndex:String(overlay?parseInt(overlayZ||String(1e5+this.zBase),10)+1:50+this.zBase)})}}for(const{entry,rect,zIndex}of updates)rect?(entry.style.display="",entry.style.left=`${rect.left}px`,entry.style.top=`${rect.top}px`,entry.style.width=`${rect.width}px`,entry.style.height=`${rect.height}px`,entry.style.zIndex=zIndex):entry.style.display="none";this.portalRaf=requestAnimationFrame(()=>this.syncPortals())}}export{FloatingOverlay,Panel,PanelGroup,PanelManager,SplitLayout};
|
package/dist/styles.css
CHANGED
|
@@ -31,6 +31,7 @@
|
|
|
31
31
|
--_status-text: var(--mb-adapt-status-text, #374151);
|
|
32
32
|
--_drag-ghost-shadow: var(--mb-adapt-drag-ghost-shadow, 0 4px 12px rgba(0, 0, 0, 0.15));
|
|
33
33
|
--_border-radius: var(--mb-adapt-border-radius, 8px);
|
|
34
|
+
--_z-base: var(--mb-adapt-z-base, 0);
|
|
34
35
|
--mb-adapt-responsive-breakpoint: 768;
|
|
35
36
|
--mb-adapt-responsive-hysteresis: 40;
|
|
36
37
|
|
|
@@ -165,7 +166,7 @@
|
|
|
165
166
|
background: var(--_fork-separator);
|
|
166
167
|
transition: background 0.15s;
|
|
167
168
|
position: relative;
|
|
168
|
-
z-index: 1;
|
|
169
|
+
z-index: calc(1 + var(--_z-base));
|
|
169
170
|
touch-action: none;
|
|
170
171
|
}
|
|
171
172
|
|
|
@@ -349,7 +350,7 @@
|
|
|
349
350
|
/* ── Floating overlay ────────────────────────────────── */
|
|
350
351
|
.mb-floating-overlay {
|
|
351
352
|
position: fixed;
|
|
352
|
-
z-index: 100000;
|
|
353
|
+
z-index: calc(100000 + var(--_z-base));
|
|
353
354
|
box-shadow: var(--_floating-shadow);
|
|
354
355
|
border: var(--_floating-border);
|
|
355
356
|
backdrop-filter: var(--_floating-backdrop);
|
|
@@ -400,7 +401,7 @@
|
|
|
400
401
|
/* ── Resize handles ──────────────────────────────────── */
|
|
401
402
|
.mb-resize-handle {
|
|
402
403
|
position: absolute;
|
|
403
|
-
z-index: 10;
|
|
404
|
+
z-index: calc(10 + var(--_z-base));
|
|
404
405
|
touch-action: none;
|
|
405
406
|
}
|
|
406
407
|
|
|
@@ -442,7 +443,7 @@
|
|
|
442
443
|
display: flex;
|
|
443
444
|
align-items: center;
|
|
444
445
|
justify-content: center;
|
|
445
|
-
z-index: 200000;
|
|
446
|
+
z-index: calc(200000 + var(--_z-base));
|
|
446
447
|
background: transparent;
|
|
447
448
|
pointer-events: none;
|
|
448
449
|
}
|
|
@@ -515,7 +516,7 @@
|
|
|
515
516
|
flex-direction: row;
|
|
516
517
|
align-items: center;
|
|
517
518
|
justify-content: center;
|
|
518
|
-
z-index: 300000;
|
|
519
|
+
z-index: calc(300000 + var(--_z-base));
|
|
519
520
|
background: rgba(0, 0, 0, 0.4);
|
|
520
521
|
height: auto;
|
|
521
522
|
min-height: 0;
|
|
@@ -592,7 +593,7 @@
|
|
|
592
593
|
align-items: center;
|
|
593
594
|
justify-content: center;
|
|
594
595
|
pointer-events: none;
|
|
595
|
-
z-index: 200000;
|
|
596
|
+
z-index: calc(200000 + var(--_z-base));
|
|
596
597
|
}
|
|
597
598
|
|
|
598
599
|
.mb-adapt-cap > * {
|
|
@@ -664,7 +665,7 @@ cap-widget::part(attribution) {
|
|
|
664
665
|
display: none;
|
|
665
666
|
height: var(--_toolbar-height);
|
|
666
667
|
flex-shrink: 0;
|
|
667
|
-
z-index: 100;
|
|
668
|
+
z-index: calc(100 + var(--_z-base));
|
|
668
669
|
align-items: stretch;
|
|
669
670
|
background: var(--_fork-tab-bg);
|
|
670
671
|
border-bottom: 1px solid var(--_fork-separator);
|
|
@@ -737,7 +738,7 @@ cap-widget::part(attribution) {
|
|
|
737
738
|
.mb-drag-ghost {
|
|
738
739
|
position: fixed;
|
|
739
740
|
pointer-events: none;
|
|
740
|
-
z-index: 999999;
|
|
741
|
+
z-index: calc(999999 + var(--_z-base));
|
|
741
742
|
padding: 4px 10px;
|
|
742
743
|
background: var(--_fork-tab-bg);
|
|
743
744
|
color: var(--_fork-tab-color);
|
|
@@ -767,7 +768,7 @@ cap-widget::part(attribution) {
|
|
|
767
768
|
.mb-drop-overlay {
|
|
768
769
|
position: fixed;
|
|
769
770
|
pointer-events: none;
|
|
770
|
-
z-index: 999998;
|
|
771
|
+
z-index: calc(999998 + var(--_z-base));
|
|
771
772
|
display: none;
|
|
772
773
|
box-sizing: border-box;
|
|
773
774
|
border-radius: 6px;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { AdaptTheme } from "./theme.js";
|
|
2
|
-
import type { AdaptWebClientOptions, CapWidgetOptions, Output, PersistOptions, SignalValue, StatusJson, StatusText } from "./types.js";
|
|
2
|
+
import type { AdaptError, AdaptWebClientOptions, CapWidgetOptions, Output, PersistOptions, SignalValue, StatusJson, StatusText } from "./types.js";
|
|
3
3
|
/**
|
|
4
4
|
* `<adapt-automation>` custom element for embedding Adapt automations.
|
|
5
5
|
*
|
|
@@ -42,6 +42,7 @@ export declare class AdaptAutomationElement extends BaseElement {
|
|
|
42
42
|
onSessionCallback: ((status: StatusJson, fork?: string) => void) | undefined;
|
|
43
43
|
onOutputCallback: ((output: Output) => void) | undefined;
|
|
44
44
|
onForkActiveCallback: ((active: boolean) => void) | undefined;
|
|
45
|
+
onErrorCallback: ((error: AdaptError) => void) | undefined;
|
|
45
46
|
get automationId(): string | null;
|
|
46
47
|
set automationId(v: string | null);
|
|
47
48
|
get darkMode(): boolean;
|
package/dist/types/core.d.ts
CHANGED
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
* ```
|
|
11
11
|
*/
|
|
12
12
|
export { AdaptWebClient as WebClient } from "./index.js";
|
|
13
|
-
export type { AdaptTheme, AdaptWebClientOptions, CapWidgetI18n, CapWidgetOptions, ChallengeInfo, ForkDisplay, Output, PersistOptions, RedeemedChallenge, SignalValue, StatusJson, StatusText, } from "./types.js";
|
|
13
|
+
export type { AdaptError, AdaptErrorKind, AdaptTheme, AdaptWebClientOptions, CapWidgetI18n, CapWidgetOptions, ChallengeInfo, ForkDisplay, Output, PersistOptions, RedeemedChallenge, SignalValue, StatusJson, StatusText, } from "./types.js";
|
|
14
14
|
export { resolveTheme } from "./theme.js";
|
|
15
15
|
export type { SignalData } from "@mochabug/adapt-core";
|
|
16
16
|
export { createConnectClient } from "@mochabug/adapt-core/connect";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const PANEL_MANAGER_CSS = "/* ==========================================================================\n Mochabug Adapt Web \u2014 Combined Styles\n Panel Manager CSS + Cap Widget CSS\n ========================================================================== */\n\n:root { --mb-adapt-styles-loaded: 1; }\n\n/* \u2500\u2500 Root \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.mb-adapt {\n position: relative;\n width: 100%;\n height: 100%;\n min-height: inherit;\n display: flex;\n flex-direction: column;\n\n /* Two-layer CSS variables: --_X reads user-set --mb-adapt-X first, falls back to light default */\n --_bg: var(--mb-adapt-bg, transparent);\n --_font: var(--mb-adapt-font, system-ui, -apple-system, sans-serif);\n --_button-hover-bg: var(--mb-adapt-button-hover-bg, rgba(128, 128, 128, 0.2));\n --_separator-active: var(--mb-adapt-separator-active, rgba(59, 130, 246, 0.5));\n --_floating-shadow: var(--mb-adapt-floating-shadow, 0 25px 50px -12px rgba(0, 0, 0, 0.25), 0 12px 24px -8px rgba(0, 0, 0, 0.15));\n --_floating-border: var(--mb-adapt-floating-border, none);\n --_floating-backdrop: var(--mb-adapt-floating-backdrop, none);\n --_floating-radius: var(--mb-adapt-floating-radius, 8px);\n --_status-card-bg: var(--mb-adapt-status-card-bg, #ffffff);\n --_status-card-border: var(--mb-adapt-status-card-border, #e5e7eb);\n --_status-card-shadow: var(--mb-adapt-status-card-shadow, 0 4px 24px rgba(0, 0, 0, 0.08), 0 2px 8px rgba(0, 0, 0, 0.04));\n --_status-icon-bg: var(--mb-adapt-status-icon-bg, #fef2f2);\n --_status-icon-stopped-bg: var(--mb-adapt-status-icon-stopped-bg, var(--mb-adapt-status-icon-bg, #f3f4f6));\n --_status-text: var(--mb-adapt-status-text, #374151);\n --_drag-ghost-shadow: var(--mb-adapt-drag-ghost-shadow, 0 4px 12px rgba(0, 0, 0, 0.15));\n --_border-radius: var(--mb-adapt-border-radius, 8px);\n --mb-adapt-responsive-breakpoint: 768;\n --mb-adapt-responsive-hysteresis: 40;\n\n /* Cap.js widget variables */\n --_cap-background: var(--mb-adapt-cap-background, #ffffff);\n --_cap-border-color: var(--mb-adapt-cap-border-color, #e2e8f0);\n --_cap-border-radius: var(--mb-adapt-cap-border-radius, 16px);\n --_cap-height: var(--mb-adapt-cap-height, 72px);\n --_cap-width: var(--mb-adapt-cap-width, 380px);\n --_cap-padding: var(--mb-adapt-cap-padding, 20px 28px);\n --_cap-gap: var(--mb-adapt-cap-gap, 20px);\n --_cap-color: var(--mb-adapt-cap-color, #1e293b);\n --_cap-checkbox-size: var(--mb-adapt-cap-checkbox-size, 36px);\n --_cap-checkbox-border: var(--mb-adapt-cap-checkbox-border, 2px solid #cbd5e1);\n --_cap-checkbox-radius: var(--mb-adapt-cap-checkbox-radius, 10px);\n --_cap-checkbox-background: var(--mb-adapt-cap-checkbox-background, #f8fafc);\n --_cap-spinner-color: var(--mb-adapt-cap-spinner-color, #6366f1);\n --_cap-spinner-bg: var(--mb-adapt-cap-spinner-bg, #e2e8f0);\n --_cap-font: var(--mb-adapt-cap-font, inherit);\n --_cap-spinner-thickness: var(--mb-adapt-cap-spinner-thickness, 3px);\n --_cap-shadow: var(--mb-adapt-cap-shadow, 0 4px 20px rgba(0, 0, 0, 0.08), 0 2px 8px rgba(0, 0, 0, 0.04));\n --_cap-shadow-hover: var(--mb-adapt-cap-shadow-hover, 0 8px 30px rgba(0, 0, 0, 0.12), 0 4px 12px rgba(0, 0, 0, 0.06));\n\n /* Fork panel theming */\n --_fork-bg: var(--mb-adapt-fork-bg, #ffffff);\n --_fork-tab-bg: var(--mb-adapt-fork-tab-bg, #f3f3f3);\n --_fork-tab-active-bg: var(--mb-adapt-fork-tab-active-bg, #ffffff);\n --_fork-tab-color: var(--mb-adapt-fork-tab-color, rgb(51, 51, 51));\n --_fork-tab-inactive-color: var(--mb-adapt-fork-tab-inactive-color, rgba(51, 51, 51, 0.7));\n --_fork-separator: var(--mb-adapt-fork-separator, rgba(128, 128, 128, 0.35));\n\n /* Tab shape */\n --_tab-radius: var(--mb-adapt-tab-radius, 0);\n --_tab-shadow: var(--mb-adapt-tab-shadow, none);\n --_tab-active-shadow: var(--mb-adapt-tab-active-shadow, none);\n --_tab-gap: var(--mb-adapt-tab-gap, 0px);\n --_tab-padding: var(--mb-adapt-tab-padding, 0 14px);\n --_tab-font-size: var(--mb-adapt-tab-font-size, 13px);\n --_tab-min-width: var(--mb-adapt-tab-min-width, 100px);\n --_tab-spacing: var(--mb-adapt-tab-spacing, 6px);\n --_toolbar-height: var(--mb-adapt-toolbar-height, 40px);\n --_toolbar-padding: var(--mb-adapt-toolbar-padding, 0);\n\n /* Drop targets \u2014 light defaults */\n --_drop-header-bg: var(--mb-adapt-drop-header-bg, rgba(99, 102, 241, 0.18));\n --_drop-center-bg: var(--mb-adapt-drop-center-bg, rgba(99, 102, 241, 0.12));\n --_drop-split-bg: var(--mb-adapt-drop-split-bg, rgba(99, 102, 241, 0.14));\n --_drop-border: var(--mb-adapt-drop-border, rgba(99, 102, 241, 0.55));\n\n background: var(--_bg);\n}\n\n.mb-adapt--dark {\n /* Cap.js widget dark mode */\n --_cap-background: var(--mb-adapt-cap-background, #1e293b);\n --_cap-border-color: var(--mb-adapt-cap-border-color, #334155);\n --_cap-color: var(--mb-adapt-cap-color, #f1f5f9);\n --_cap-checkbox-border: var(--mb-adapt-cap-checkbox-border, 2px solid #475569);\n --_cap-checkbox-background: var(--mb-adapt-cap-checkbox-background, #0f172a);\n --_cap-spinner-color: var(--mb-adapt-cap-spinner-color, #818cf8);\n --_cap-spinner-bg: var(--mb-adapt-cap-spinner-bg, #334155);\n --_cap-shadow: var(--mb-adapt-cap-shadow, 0 4px 20px rgba(0, 0, 0, 0.25), 0 2px 8px rgba(0, 0, 0, 0.15));\n --_cap-shadow-hover: var(--mb-adapt-cap-shadow-hover, 0 8px 30px rgba(0, 0, 0, 0.35), 0 4px 12px rgba(0, 0, 0, 0.2));\n\n /* Status card dark mode */\n --_status-card-bg: var(--mb-adapt-status-card-bg, #1e293b);\n --_status-card-border: var(--mb-adapt-status-card-border, #334155);\n --_status-icon-bg: var(--mb-adapt-status-icon-bg, #351c1c);\n --_status-icon-stopped-bg: var(--mb-adapt-status-icon-stopped-bg, var(--mb-adapt-status-icon-bg, #1e293b));\n --_status-text: var(--mb-adapt-status-text, #e2e8f0);\n\n /* Panel dark mode overrides */\n --_button-hover-bg: var(--mb-adapt-button-hover-bg, rgba(128, 128, 128, 0.3));\n --_separator-active: var(--mb-adapt-separator-active, rgba(99, 130, 246, 0.6));\n --_floating-shadow: var(--mb-adapt-floating-shadow, 0 25px 50px -12px rgba(0, 0, 0, 0.5), 0 12px 24px -8px rgba(0, 0, 0, 0.3));\n --_floating-border: var(--mb-adapt-floating-border, 1px solid rgba(255, 255, 255, 0.06));\n --_status-card-shadow: var(--mb-adapt-status-card-shadow, 0 4px 24px rgba(0, 0, 0, 0.25), 0 2px 8px rgba(0, 0, 0, 0.15));\n --_drag-ghost-shadow: var(--mb-adapt-drag-ghost-shadow, 0 4px 12px rgba(0, 0, 0, 0.35));\n\n /* Fork panel dark mode */\n --_fork-bg: var(--mb-adapt-fork-bg, #1e1e1e);\n --_fork-tab-bg: var(--mb-adapt-fork-tab-bg, #252526);\n --_fork-tab-active-bg: var(--mb-adapt-fork-tab-active-bg, #1e1e1e);\n --_fork-tab-color: var(--mb-adapt-fork-tab-color, #ffffff);\n --_fork-tab-inactive-color: var(--mb-adapt-fork-tab-inactive-color, #969696);\n --_fork-separator: var(--mb-adapt-fork-separator, rgb(68, 68, 68));\n\n /* Drop target dark mode */\n --_drop-header-bg: var(--mb-adapt-drop-header-bg, rgba(129, 140, 248, 0.22));\n --_drop-center-bg: var(--mb-adapt-drop-center-bg, rgba(129, 140, 248, 0.15));\n --_drop-split-bg: var(--mb-adapt-drop-split-bg, rgba(129, 140, 248, 0.18));\n --_drop-border: var(--mb-adapt-drop-border, rgba(129, 140, 248, 0.6));\n}\n\n/* \u2500\u2500 Layout (recursive split tree) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.mb-layout {\n flex: 1;\n min-height: 0;\n position: relative;\n display: flex;\n}\n\n.mb-split-container {\n display: flex;\n min-width: 0;\n min-height: 0;\n}\n\n.mb-split-horizontal { flex-direction: row; }\n.mb-split-vertical { flex-direction: column; }\n\n.mb-split-leaf {\n min-width: 0;\n min-height: 0;\n overflow: hidden;\n}\n\n/* Animated flex transition \u2014 applied temporarily during dock/undock/maximize */\n.mb-split-leaf--animating {\n transition: flex 0.25s ease;\n}\n.mb-split-container--animating {\n transition: flex 0.25s ease;\n}\n.mb-layout-separator--animating {\n transition: opacity 0.25s ease;\n}\n\n/* Draggable separator between split panels */\n.mb-layout-separator {\n flex: 0 0 5px;\n background: var(--_fork-separator);\n transition: background 0.15s;\n position: relative;\n z-index: 1;\n touch-action: none;\n}\n\n.mb-layout-separator-v { cursor: col-resize; }\n.mb-layout-separator-h { cursor: row-resize; }\n\n.mb-layout-separator:hover,\n.mb-layout-separator--active {\n background: var(--_separator-active);\n}\n\n/* \u2500\u2500 Group \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.mb-group {\n display: flex;\n flex-direction: column;\n height: 100%;\n background: var(--_bg);\n}\n\n.mb-group-header {\n display: flex;\n align-items: stretch;\n height: var(--_toolbar-height);\n min-height: var(--_toolbar-height);\n padding: var(--_toolbar-padding);\n background: var(--_fork-tab-bg);\n border-bottom: 1px solid var(--_fork-separator);\n user-select: none;\n}\n\n.mb-group-header-prefix {\n display: flex;\n align-items: stretch;\n}\n\n.mb-group-tabs {\n display: flex;\n align-items: stretch;\n overflow-x: auto;\n overflow-y: hidden;\n flex: 0 1 auto;\n min-width: 0;\n}\n\n.mb-group-tabs::-webkit-scrollbar {\n height: 2px;\n}\n\n/* Drag handle \u2014 fills remaining header space so the user can grab it */\n.mb-group-header-void {\n flex: 1;\n min-width: 40px;\n touch-action: none;\n}\n\n.mb-group-header-actions {\n display: flex;\n align-items: center;\n}\n\n.mb-group-content {\n flex: 1;\n position: relative;\n overflow: hidden;\n background: var(--_fork-bg);\n}\n\n/* Main group overrides */\n.mb-group[data-main-group=\"true\"] {\n background: var(--_bg);\n}\n\n.mb-group[data-main-group=\"true\"] .mb-group-content {\n background: var(--_fork-bg);\n}\n\n\n/* \u2500\u2500 Tab \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.mb-tab {\n display: flex;\n align-items: center;\n gap: var(--_tab-spacing);\n padding: var(--_tab-padding);\n min-width: var(--_tab-min-width);\n font-size: var(--_tab-font-size);\n font-family: var(--_font);\n white-space: nowrap;\n cursor: pointer;\n touch-action: none;\n color: var(--_fork-tab-inactive-color);\n background: var(--_fork-tab-bg);\n border-right: 1px solid var(--_fork-separator);\n border-radius: var(--_tab-radius);\n box-shadow: var(--_tab-shadow);\n margin: var(--_tab-gap);\n transition: background 0.15s, box-shadow 0.15s;\n}\n\n.mb-tab[data-active=\"true\"] {\n color: var(--_fork-tab-color);\n background: var(--_fork-tab-active-bg);\n box-shadow: var(--_tab-active-shadow);\n}\n\n.mb-tab:hover {\n background: var(--_fork-tab-active-bg);\n}\n\n.mb-tab-label {\n display: flex;\n align-items: center;\n}\n\n.mb-tab-label svg {\n width: 14px;\n height: 14px;\n opacity: 0.7;\n flex-shrink: 0;\n}\n\n.mb-tab[data-active=\"true\"] .mb-tab-label svg {\n opacity: 1;\n}\n\n.mb-tab-actions {\n display: flex;\n align-items: center;\n gap: 2px;\n width: 40px;\n flex-shrink: 0;\n justify-content: flex-end;\n margin-left: auto;\n}\n\n.mb-tab-close {\n width: 18px;\n height: 18px;\n padding: 0;\n border: none;\n background: transparent;\n color: inherit;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n border-radius: 3px;\n opacity: 0;\n transition: opacity 0.15s, background 0.15s;\n}\n\n.mb-tab:hover .mb-tab-close {\n opacity: 0.7;\n}\n\n.mb-tab-close:hover {\n opacity: 1 !important;\n background: var(--_button-hover-bg);\n}\n\n.mb-tab-close svg {\n width: 12px;\n height: 12px;\n}\n\n/* \u2500\u2500 Panel visibility \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.mb-panel {\n width: 100%;\n height: 100%;\n position: absolute;\n inset: 0;\n}\n\n.mb-panel[data-active=\"false\"] {\n display: none;\n}\n\n.mb-panel[data-active=\"true\"] {\n display: block;\n}\n\n/* \u2500\u2500 Floating overlay \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.mb-floating-overlay {\n position: fixed;\n z-index: 100000;\n box-shadow: var(--_floating-shadow);\n border: var(--_floating-border);\n backdrop-filter: var(--_floating-backdrop);\n -webkit-backdrop-filter: var(--_floating-backdrop);\n border-radius: var(--_floating-radius);\n display: flex;\n flex-direction: column;\n /* No overflow:hidden here \u2014 resize handles use negative offsets (top:-3px etc.)\n and would be clipped. The inner .mb-group already has overflow:hidden for\n its own border-radius clipping. */\n}\n\n.mb-floating-overlay > .mb-group {\n flex: 1;\n border-radius: var(--_floating-radius);\n overflow: hidden;\n}\n\n/* Internal split layout inside a floating overlay */\n.mb-floating-overlay > .mb-layout {\n position: relative;\n inset: auto;\n height: auto;\n flex: 1;\n min-width: 0;\n min-height: 0;\n border-radius: var(--_floating-radius);\n overflow: hidden;\n}\n\n.mb-floating-maximized {\n border-radius: 0;\n box-shadow: none;\n}\n\n.mb-floating-maximized .mb-group {\n border-radius: 0;\n}\n\n.mb-floating-maximized .mb-resize-handle {\n display: none !important;\n}\n\n.mb-floating-maximized .mb-group-header-void {\n pointer-events: none;\n}\n\n/* \u2500\u2500 Resize handles \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.mb-resize-handle {\n position: absolute;\n z-index: 10;\n touch-action: none;\n}\n\n.mb-resize-n { top: -3px; left: 8px; right: 8px; height: 6px; cursor: n-resize; }\n.mb-resize-s { bottom: -3px; left: 8px; right: 8px; height: 6px; cursor: s-resize; }\n.mb-resize-e { right: -3px; top: 8px; bottom: 8px; width: 6px; cursor: e-resize; }\n.mb-resize-w { left: -3px; top: 8px; bottom: 8px; width: 6px; cursor: w-resize; }\n.mb-resize-ne { top: -3px; right: -3px; width: 12px; height: 12px; cursor: ne-resize; }\n.mb-resize-nw { top: -3px; left: -3px; width: 12px; height: 12px; cursor: nw-resize; }\n.mb-resize-se { bottom: -3px; right: -3px; width: 12px; height: 12px; cursor: se-resize; }\n.mb-resize-sw { bottom: -3px; left: -3px; width: 12px; height: 12px; cursor: sw-resize; }\n\n/* \u2500\u2500 Iframe styling \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.mb-adapt__iframe {\n width: 100%;\n height: 100%;\n min-height: 0;\n border: 0;\n display: block;\n background: transparent;\n border-radius: var(--_border-radius);\n pointer-events: auto;\n opacity: 0;\n transition: opacity 0.1s ease-out;\n}\n\n.mb-adapt__iframe--visible {\n opacity: 1;\n}\n\n.mb-adapt__iframe--hidden {\n display: none;\n}\n\n/* \u2500\u2500 Status message overlay \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.mb-adapt__status-message {\n position: absolute;\n inset: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: 200000;\n background: transparent;\n pointer-events: none;\n}\n\n.mb-adapt__status-card {\n pointer-events: auto;\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 16px;\n padding: 32px 40px;\n max-width: 380px;\n border-radius: 16px;\n background: var(--_status-card-bg);\n border: 1px solid var(--_status-card-border);\n box-shadow: var(--_status-card-shadow);\n font-family: var(--_font);\n text-align: center;\n}\n\n.mb-adapt__status-icon {\n width: 48px;\n height: 48px;\n border-radius: 12px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: var(--_status-icon-bg);\n}\n\n.mb-adapt__status-icon svg {\n width: 24px;\n height: 24px;\n}\n\n.mb-adapt__status-icon--stopped {\n background: var(--_status-icon-stopped-bg);\n}\n\n.mb-adapt__status-text {\n color: var(--_status-text);\n font-size: 15px;\n line-height: 1.5;\n margin: 0;\n}\n\n.mb-adapt__status-restart {\n padding: 8px 20px;\n border: 1px solid var(--_status-card-border);\n border-radius: 8px;\n background: transparent;\n color: var(--_status-text);\n font-size: 14px;\n font-weight: 500;\n font-family: var(--_font);\n cursor: pointer;\n transition: background 0.15s, border-color 0.15s;\n}\n\n.mb-adapt__status-restart:hover {\n background: var(--_status-card-border);\n}\n\n/* \u2500\u2500 Confirm-on-close dialog \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.mb-adapt__confirm-overlay {\n position: fixed;\n inset: 0;\n display: flex;\n flex-direction: row;\n align-items: center;\n justify-content: center;\n z-index: 300000;\n background: rgba(0, 0, 0, 0.4);\n height: auto;\n min-height: 0;\n}\n\n.mb-adapt--dark.mb-adapt__confirm-overlay {\n background: rgba(0, 0, 0, 0.55);\n}\n\n.mb-adapt__confirm-card {\n display: flex;\n flex-direction: column;\n align-items: stretch;\n gap: 16px;\n padding: 24px 28px;\n max-width: 360px;\n width: 100%;\n border-radius: var(--_floating-radius);\n background: var(--_fork-tab-active-bg);\n border: 1px solid var(--_fork-separator);\n box-shadow: var(--_floating-shadow);\n font-family: var(--_font);\n text-align: center;\n}\n\n.mb-adapt__confirm-text {\n font-size: 14px;\n line-height: 1.5;\n color: var(--_fork-tab-color);\n margin: 0;\n}\n\n.mb-adapt__confirm-buttons {\n display: flex;\n gap: 8px;\n justify-content: flex-end;\n}\n\n.mb-adapt__confirm-btn {\n padding: 8px 16px;\n border-radius: 6px;\n font-size: 13px;\n font-family: var(--_font);\n cursor: pointer;\n font-weight: 500;\n transition: background 0.15s, border-color 0.15s;\n}\n\n.mb-adapt__confirm-btn--cancel {\n background: transparent;\n border: 1px solid var(--_fork-separator);\n color: var(--_fork-tab-color);\n}\n\n.mb-adapt__confirm-btn--cancel:hover {\n background: var(--_button-hover-bg);\n}\n\n.mb-adapt__confirm-btn--confirm {\n background: var(--_fork-tab-color);\n color: var(--_fork-tab-active-bg);\n border: 1px solid transparent;\n}\n\n.mb-adapt__confirm-btn--confirm:hover {\n opacity: 0.85;\n}\n\n/* \u2500\u2500 Cap.js widget positioning \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.mb-adapt-cap {\n position: absolute;\n inset: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n pointer-events: none;\n z-index: 200000;\n}\n\n.mb-adapt-cap > * {\n pointer-events: auto;\n}\n\n/* Cap.js widget styling */\n.mb-adapt cap-widget {\n --cap-background: var(--_cap-background);\n --cap-border-color: var(--_cap-border-color);\n --cap-border-radius: var(--_cap-border-radius);\n --cap-widget-height: var(--_cap-height);\n --cap-widget-width: var(--_cap-width);\n --cap-widget-padding: var(--_cap-padding);\n --cap-gap: var(--_cap-gap);\n --cap-color: var(--_cap-color);\n --cap-checkbox-size: var(--_cap-checkbox-size);\n --cap-checkbox-border: var(--_cap-checkbox-border);\n --cap-checkbox-border-radius: var(--_cap-checkbox-radius);\n --cap-checkbox-background: var(--_cap-checkbox-background);\n --cap-checkbox-margin: 0;\n --cap-font: var(--_cap-font);\n --cap-spinner-color: var(--_cap-spinner-color);\n --cap-spinner-background-color: var(--_cap-spinner-bg);\n --cap-spinner-thickness: var(--_cap-spinner-thickness);\n}\n\n/* Hide Cap.js credits */\ncap-widget::part(attribution) {\n display: none;\n}\n\n/* \u2500\u2500 Fork group action buttons \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.mb-adapt-fork-actions {\n display: flex;\n align-items: center;\n gap: 2px;\n padding-right: 4px;\n}\n.mb-adapt-fork-actions button {\n width: 20px;\n height: 20px;\n padding: 0;\n border: none;\n background: transparent;\n color: var(--_fork-tab-color);\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n border-radius: 3px;\n opacity: 0.7;\n transition: opacity 0.15s, background 0.15s;\n}\n.mb-adapt-fork-actions button:hover {\n opacity: 1;\n background: var(--_button-hover-bg);\n}\n.mb-adapt-fork-actions button svg {\n width: 14px;\n height: 14px;\n}\n\n/* \u2500\u2500 Minimized-group tabs bar (at the top, NOT an overlay) \u2500\u2500\u2500 */\n/* Sits at the top of .mb-adapt as a normal flow element so the layout\n underneath shrinks to accommodate it. This prevents scrollbars when\n docked panels are minimized \u2014 the iframe gets the remaining height. */\n.mb-adapt-minimized-tabs {\n display: none;\n height: var(--_toolbar-height);\n flex-shrink: 0;\n z-index: 100;\n align-items: stretch;\n background: var(--_fork-tab-bg);\n border-bottom: 1px solid var(--_fork-separator);\n user-select: none;\n}\n.mb-adapt-minimized-tab {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 0 12px;\n flex: 1;\n background: var(--_fork-tab-bg);\n color: var(--_fork-tab-color);\n font-size: var(--_tab-font-size);\n font-family: var(--_font);\n white-space: nowrap;\n border-right: 1px solid var(--_fork-separator);\n cursor: default;\n}\n.mb-adapt-minimized-tab-label {\n flex: 1;\n display: flex;\n align-items: center;\n gap: 4px;\n}\n\n.mb-adapt-minimized-tab-label svg {\n width: 14px;\n height: 14px;\n opacity: 0.8;\n flex-shrink: 0;\n}\n.mb-adapt-minimized-tab-action {\n width: 22px;\n height: 22px;\n padding: 0;\n border: none;\n background: transparent;\n color: inherit;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n border-radius: 4px;\n opacity: 0.6;\n transition: opacity 0.15s, background 0.15s;\n}\n.mb-adapt-minimized-tab-action:hover {\n opacity: 1;\n background: var(--_button-hover-bg);\n}\n.mb-adapt-minimized-tab-action svg {\n width: 14px;\n height: 14px;\n}\n\n/* Minimized tab drag handle cursor */\n.mb-adapt-minimized-tab {\n cursor: grab;\n touch-action: none;\n}\n\n/* Drop target highlight for minimized tab merge */\n.mb-adapt-minimized-tab--drop-target {\n background: var(--_drop-header-bg) !important;\n box-shadow: inset 0 0 0 2px var(--_drop-border);\n}\n\n/* \u2500\u2500 Pointer-drag ghost element \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.mb-drag-ghost {\n position: fixed;\n pointer-events: none;\n z-index: 999999;\n padding: 4px 10px;\n background: var(--_fork-tab-bg);\n color: var(--_fork-tab-color);\n border: 1px solid var(--_fork-separator);\n border-radius: var(--_tab-radius, 4px);\n font-size: var(--_tab-font-size);\n font-family: var(--_font);\n white-space: nowrap;\n box-shadow: var(--_drag-ghost-shadow);\n opacity: 0.92;\n display: flex;\n align-items: center;\n}\n\n.mb-drag-ghost svg {\n width: 16px;\n height: 16px;\n}\n\n/* \u2500\u2500 Drop target highlight on group header \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.mb-group-header--drop-target {\n background: var(--_drop-header-bg) !important;\n box-shadow: inset 0 0 0 2px var(--_drop-border);\n}\n\n/* \u2500\u2500 Drop overlay (content-area and dock-strip indicators) */\n.mb-drop-overlay {\n position: fixed;\n pointer-events: none;\n z-index: 999998;\n display: none;\n box-sizing: border-box;\n border-radius: 6px;\n transition: opacity 0.1s ease-out;\n}\n\n.mb-drop-overlay[data-zone=\"center\"] {\n background: var(--_drop-center-bg);\n border: 2px solid var(--_drop-border);\n}\n\n.mb-drop-overlay[data-zone=\"top\"],\n.mb-drop-overlay[data-zone=\"bottom\"],\n.mb-drop-overlay[data-zone=\"left\"],\n.mb-drop-overlay[data-zone=\"right\"] {\n background: var(--_drop-split-bg);\n border: 2px solid var(--_drop-border);\n}\n\n/* \u2500\u2500 Iframe pointer-event guard during drag \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\nhtml.mb-dragging iframe,\nhtml.mb-dragging webview {\n pointer-events: none !important;\n}\n\n/* \u2500\u2500 Tab pop-out button \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.mb-tab-popout {\n width: 18px;\n height: 18px;\n padding: 0;\n border: none;\n background: transparent;\n color: inherit;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n border-radius: 3px;\n opacity: 0;\n transition: opacity 0.15s, background 0.15s;\n}\n\n.mb-tab:hover .mb-tab-popout {\n opacity: 0.7;\n}\n\n.mb-tab-popout:hover {\n opacity: 1 !important;\n background: var(--_button-hover-bg);\n}\n\n.mb-tab-popout svg {\n width: 12px;\n height: 12px;\n}\n\n/* Hide pop-out button on main group (never floats), when overlay\n has 0 or 1 total tabs (nothing to pop out), and when floating is disallowed. */\n.mb-group[data-main-group=\"true\"] .mb-tab-popout,\n.mb-floating-overlay[data-total-tab-count=\"0\"] .mb-tab-popout,\n.mb-floating-overlay[data-total-tab-count=\"1\"] .mb-tab-popout,\n.mb-group[data-allow-floating=\"false\"] .mb-tab-popout {\n display: none !important;\n}\n\n\n/* \u2500\u2500 Iframe portal layer \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n/* MUST NOT create a stacking context \u2014 portal entries' z-indexes\n must compete with floating overlays in the parent stacking context.\n position: absolute + no z-index achieves this. */\n.mb-iframe-portal-layer {\n position: absolute;\n width: 0;\n height: 0;\n overflow: visible;\n pointer-events: none;\n}\n.mb-iframe-portal {\n position: fixed;\n pointer-events: auto;\n overflow: hidden;\n}\n\n/* \u2500\u2500 Touch device adjustments \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n@media (hover: none) {\n .mb-tab-close {\n opacity: 0.5;\n }\n\n .mb-tab-popout {\n opacity: 0.5;\n }\n\n .mb-tab:hover .mb-tab-close,\n .mb-tab:hover .mb-tab-popout {\n opacity: 0.7;\n }\n}\n\n@media (pointer: coarse) {\n .mb-tab-close,\n .mb-tab-popout {\n width: 24px;\n height: 24px;\n }\n\n .mb-adapt-fork-actions button {\n width: 26px;\n height: 26px;\n }\n\n .mb-adapt-minimized-tab-action {\n width: 28px;\n height: 28px;\n }\n}";
|
|
1
|
+
export declare const PANEL_MANAGER_CSS = "/* ==========================================================================\n Mochabug Adapt Web \u2014 Combined Styles\n Panel Manager CSS + Cap Widget CSS\n ========================================================================== */\n\n:root { --mb-adapt-styles-loaded: 1; }\n\n/* \u2500\u2500 Root \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.mb-adapt {\n position: relative;\n width: 100%;\n height: 100%;\n min-height: inherit;\n display: flex;\n flex-direction: column;\n\n /* Two-layer CSS variables: --_X reads user-set --mb-adapt-X first, falls back to light default */\n --_bg: var(--mb-adapt-bg, transparent);\n --_font: var(--mb-adapt-font, system-ui, -apple-system, sans-serif);\n --_button-hover-bg: var(--mb-adapt-button-hover-bg, rgba(128, 128, 128, 0.2));\n --_separator-active: var(--mb-adapt-separator-active, rgba(59, 130, 246, 0.5));\n --_floating-shadow: var(--mb-adapt-floating-shadow, 0 25px 50px -12px rgba(0, 0, 0, 0.25), 0 12px 24px -8px rgba(0, 0, 0, 0.15));\n --_floating-border: var(--mb-adapt-floating-border, none);\n --_floating-backdrop: var(--mb-adapt-floating-backdrop, none);\n --_floating-radius: var(--mb-adapt-floating-radius, 8px);\n --_status-card-bg: var(--mb-adapt-status-card-bg, #ffffff);\n --_status-card-border: var(--mb-adapt-status-card-border, #e5e7eb);\n --_status-card-shadow: var(--mb-adapt-status-card-shadow, 0 4px 24px rgba(0, 0, 0, 0.08), 0 2px 8px rgba(0, 0, 0, 0.04));\n --_status-icon-bg: var(--mb-adapt-status-icon-bg, #fef2f2);\n --_status-icon-stopped-bg: var(--mb-adapt-status-icon-stopped-bg, var(--mb-adapt-status-icon-bg, #f3f4f6));\n --_status-text: var(--mb-adapt-status-text, #374151);\n --_drag-ghost-shadow: var(--mb-adapt-drag-ghost-shadow, 0 4px 12px rgba(0, 0, 0, 0.15));\n --_border-radius: var(--mb-adapt-border-radius, 8px);\n --_z-base: var(--mb-adapt-z-base, 0);\n --mb-adapt-responsive-breakpoint: 768;\n --mb-adapt-responsive-hysteresis: 40;\n\n /* Cap.js widget variables */\n --_cap-background: var(--mb-adapt-cap-background, #ffffff);\n --_cap-border-color: var(--mb-adapt-cap-border-color, #e2e8f0);\n --_cap-border-radius: var(--mb-adapt-cap-border-radius, 16px);\n --_cap-height: var(--mb-adapt-cap-height, 72px);\n --_cap-width: var(--mb-adapt-cap-width, 380px);\n --_cap-padding: var(--mb-adapt-cap-padding, 20px 28px);\n --_cap-gap: var(--mb-adapt-cap-gap, 20px);\n --_cap-color: var(--mb-adapt-cap-color, #1e293b);\n --_cap-checkbox-size: var(--mb-adapt-cap-checkbox-size, 36px);\n --_cap-checkbox-border: var(--mb-adapt-cap-checkbox-border, 2px solid #cbd5e1);\n --_cap-checkbox-radius: var(--mb-adapt-cap-checkbox-radius, 10px);\n --_cap-checkbox-background: var(--mb-adapt-cap-checkbox-background, #f8fafc);\n --_cap-spinner-color: var(--mb-adapt-cap-spinner-color, #6366f1);\n --_cap-spinner-bg: var(--mb-adapt-cap-spinner-bg, #e2e8f0);\n --_cap-font: var(--mb-adapt-cap-font, inherit);\n --_cap-spinner-thickness: var(--mb-adapt-cap-spinner-thickness, 3px);\n --_cap-shadow: var(--mb-adapt-cap-shadow, 0 4px 20px rgba(0, 0, 0, 0.08), 0 2px 8px rgba(0, 0, 0, 0.04));\n --_cap-shadow-hover: var(--mb-adapt-cap-shadow-hover, 0 8px 30px rgba(0, 0, 0, 0.12), 0 4px 12px rgba(0, 0, 0, 0.06));\n\n /* Fork panel theming */\n --_fork-bg: var(--mb-adapt-fork-bg, #ffffff);\n --_fork-tab-bg: var(--mb-adapt-fork-tab-bg, #f3f3f3);\n --_fork-tab-active-bg: var(--mb-adapt-fork-tab-active-bg, #ffffff);\n --_fork-tab-color: var(--mb-adapt-fork-tab-color, rgb(51, 51, 51));\n --_fork-tab-inactive-color: var(--mb-adapt-fork-tab-inactive-color, rgba(51, 51, 51, 0.7));\n --_fork-separator: var(--mb-adapt-fork-separator, rgba(128, 128, 128, 0.35));\n\n /* Tab shape */\n --_tab-radius: var(--mb-adapt-tab-radius, 0);\n --_tab-shadow: var(--mb-adapt-tab-shadow, none);\n --_tab-active-shadow: var(--mb-adapt-tab-active-shadow, none);\n --_tab-gap: var(--mb-adapt-tab-gap, 0px);\n --_tab-padding: var(--mb-adapt-tab-padding, 0 14px);\n --_tab-font-size: var(--mb-adapt-tab-font-size, 13px);\n --_tab-min-width: var(--mb-adapt-tab-min-width, 100px);\n --_tab-spacing: var(--mb-adapt-tab-spacing, 6px);\n --_toolbar-height: var(--mb-adapt-toolbar-height, 40px);\n --_toolbar-padding: var(--mb-adapt-toolbar-padding, 0);\n\n /* Drop targets \u2014 light defaults */\n --_drop-header-bg: var(--mb-adapt-drop-header-bg, rgba(99, 102, 241, 0.18));\n --_drop-center-bg: var(--mb-adapt-drop-center-bg, rgba(99, 102, 241, 0.12));\n --_drop-split-bg: var(--mb-adapt-drop-split-bg, rgba(99, 102, 241, 0.14));\n --_drop-border: var(--mb-adapt-drop-border, rgba(99, 102, 241, 0.55));\n\n background: var(--_bg);\n}\n\n.mb-adapt--dark {\n /* Cap.js widget dark mode */\n --_cap-background: var(--mb-adapt-cap-background, #1e293b);\n --_cap-border-color: var(--mb-adapt-cap-border-color, #334155);\n --_cap-color: var(--mb-adapt-cap-color, #f1f5f9);\n --_cap-checkbox-border: var(--mb-adapt-cap-checkbox-border, 2px solid #475569);\n --_cap-checkbox-background: var(--mb-adapt-cap-checkbox-background, #0f172a);\n --_cap-spinner-color: var(--mb-adapt-cap-spinner-color, #818cf8);\n --_cap-spinner-bg: var(--mb-adapt-cap-spinner-bg, #334155);\n --_cap-shadow: var(--mb-adapt-cap-shadow, 0 4px 20px rgba(0, 0, 0, 0.25), 0 2px 8px rgba(0, 0, 0, 0.15));\n --_cap-shadow-hover: var(--mb-adapt-cap-shadow-hover, 0 8px 30px rgba(0, 0, 0, 0.35), 0 4px 12px rgba(0, 0, 0, 0.2));\n\n /* Status card dark mode */\n --_status-card-bg: var(--mb-adapt-status-card-bg, #1e293b);\n --_status-card-border: var(--mb-adapt-status-card-border, #334155);\n --_status-icon-bg: var(--mb-adapt-status-icon-bg, #351c1c);\n --_status-icon-stopped-bg: var(--mb-adapt-status-icon-stopped-bg, var(--mb-adapt-status-icon-bg, #1e293b));\n --_status-text: var(--mb-adapt-status-text, #e2e8f0);\n\n /* Panel dark mode overrides */\n --_button-hover-bg: var(--mb-adapt-button-hover-bg, rgba(128, 128, 128, 0.3));\n --_separator-active: var(--mb-adapt-separator-active, rgba(99, 130, 246, 0.6));\n --_floating-shadow: var(--mb-adapt-floating-shadow, 0 25px 50px -12px rgba(0, 0, 0, 0.5), 0 12px 24px -8px rgba(0, 0, 0, 0.3));\n --_floating-border: var(--mb-adapt-floating-border, 1px solid rgba(255, 255, 255, 0.06));\n --_status-card-shadow: var(--mb-adapt-status-card-shadow, 0 4px 24px rgba(0, 0, 0, 0.25), 0 2px 8px rgba(0, 0, 0, 0.15));\n --_drag-ghost-shadow: var(--mb-adapt-drag-ghost-shadow, 0 4px 12px rgba(0, 0, 0, 0.35));\n\n /* Fork panel dark mode */\n --_fork-bg: var(--mb-adapt-fork-bg, #1e1e1e);\n --_fork-tab-bg: var(--mb-adapt-fork-tab-bg, #252526);\n --_fork-tab-active-bg: var(--mb-adapt-fork-tab-active-bg, #1e1e1e);\n --_fork-tab-color: var(--mb-adapt-fork-tab-color, #ffffff);\n --_fork-tab-inactive-color: var(--mb-adapt-fork-tab-inactive-color, #969696);\n --_fork-separator: var(--mb-adapt-fork-separator, rgb(68, 68, 68));\n\n /* Drop target dark mode */\n --_drop-header-bg: var(--mb-adapt-drop-header-bg, rgba(129, 140, 248, 0.22));\n --_drop-center-bg: var(--mb-adapt-drop-center-bg, rgba(129, 140, 248, 0.15));\n --_drop-split-bg: var(--mb-adapt-drop-split-bg, rgba(129, 140, 248, 0.18));\n --_drop-border: var(--mb-adapt-drop-border, rgba(129, 140, 248, 0.6));\n}\n\n/* \u2500\u2500 Layout (recursive split tree) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.mb-layout {\n flex: 1;\n min-height: 0;\n position: relative;\n display: flex;\n}\n\n.mb-split-container {\n display: flex;\n min-width: 0;\n min-height: 0;\n}\n\n.mb-split-horizontal { flex-direction: row; }\n.mb-split-vertical { flex-direction: column; }\n\n.mb-split-leaf {\n min-width: 0;\n min-height: 0;\n overflow: hidden;\n}\n\n/* Animated flex transition \u2014 applied temporarily during dock/undock/maximize */\n.mb-split-leaf--animating {\n transition: flex 0.25s ease;\n}\n.mb-split-container--animating {\n transition: flex 0.25s ease;\n}\n.mb-layout-separator--animating {\n transition: opacity 0.25s ease;\n}\n\n/* Draggable separator between split panels */\n.mb-layout-separator {\n flex: 0 0 5px;\n background: var(--_fork-separator);\n transition: background 0.15s;\n position: relative;\n z-index: calc(1 + var(--_z-base));\n touch-action: none;\n}\n\n.mb-layout-separator-v { cursor: col-resize; }\n.mb-layout-separator-h { cursor: row-resize; }\n\n.mb-layout-separator:hover,\n.mb-layout-separator--active {\n background: var(--_separator-active);\n}\n\n/* \u2500\u2500 Group \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.mb-group {\n display: flex;\n flex-direction: column;\n height: 100%;\n background: var(--_bg);\n}\n\n.mb-group-header {\n display: flex;\n align-items: stretch;\n height: var(--_toolbar-height);\n min-height: var(--_toolbar-height);\n padding: var(--_toolbar-padding);\n background: var(--_fork-tab-bg);\n border-bottom: 1px solid var(--_fork-separator);\n user-select: none;\n}\n\n.mb-group-header-prefix {\n display: flex;\n align-items: stretch;\n}\n\n.mb-group-tabs {\n display: flex;\n align-items: stretch;\n overflow-x: auto;\n overflow-y: hidden;\n flex: 0 1 auto;\n min-width: 0;\n}\n\n.mb-group-tabs::-webkit-scrollbar {\n height: 2px;\n}\n\n/* Drag handle \u2014 fills remaining header space so the user can grab it */\n.mb-group-header-void {\n flex: 1;\n min-width: 40px;\n touch-action: none;\n}\n\n.mb-group-header-actions {\n display: flex;\n align-items: center;\n}\n\n.mb-group-content {\n flex: 1;\n position: relative;\n overflow: hidden;\n background: var(--_fork-bg);\n}\n\n/* Main group overrides */\n.mb-group[data-main-group=\"true\"] {\n background: var(--_bg);\n}\n\n.mb-group[data-main-group=\"true\"] .mb-group-content {\n background: var(--_fork-bg);\n}\n\n\n/* \u2500\u2500 Tab \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.mb-tab {\n display: flex;\n align-items: center;\n gap: var(--_tab-spacing);\n padding: var(--_tab-padding);\n min-width: var(--_tab-min-width);\n font-size: var(--_tab-font-size);\n font-family: var(--_font);\n white-space: nowrap;\n cursor: pointer;\n touch-action: none;\n color: var(--_fork-tab-inactive-color);\n background: var(--_fork-tab-bg);\n border-right: 1px solid var(--_fork-separator);\n border-radius: var(--_tab-radius);\n box-shadow: var(--_tab-shadow);\n margin: var(--_tab-gap);\n transition: background 0.15s, box-shadow 0.15s;\n}\n\n.mb-tab[data-active=\"true\"] {\n color: var(--_fork-tab-color);\n background: var(--_fork-tab-active-bg);\n box-shadow: var(--_tab-active-shadow);\n}\n\n.mb-tab:hover {\n background: var(--_fork-tab-active-bg);\n}\n\n.mb-tab-label {\n display: flex;\n align-items: center;\n}\n\n.mb-tab-label svg {\n width: 14px;\n height: 14px;\n opacity: 0.7;\n flex-shrink: 0;\n}\n\n.mb-tab[data-active=\"true\"] .mb-tab-label svg {\n opacity: 1;\n}\n\n.mb-tab-actions {\n display: flex;\n align-items: center;\n gap: 2px;\n width: 40px;\n flex-shrink: 0;\n justify-content: flex-end;\n margin-left: auto;\n}\n\n.mb-tab-close {\n width: 18px;\n height: 18px;\n padding: 0;\n border: none;\n background: transparent;\n color: inherit;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n border-radius: 3px;\n opacity: 0;\n transition: opacity 0.15s, background 0.15s;\n}\n\n.mb-tab:hover .mb-tab-close {\n opacity: 0.7;\n}\n\n.mb-tab-close:hover {\n opacity: 1 !important;\n background: var(--_button-hover-bg);\n}\n\n.mb-tab-close svg {\n width: 12px;\n height: 12px;\n}\n\n/* \u2500\u2500 Panel visibility \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.mb-panel {\n width: 100%;\n height: 100%;\n position: absolute;\n inset: 0;\n}\n\n.mb-panel[data-active=\"false\"] {\n display: none;\n}\n\n.mb-panel[data-active=\"true\"] {\n display: block;\n}\n\n/* \u2500\u2500 Floating overlay \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.mb-floating-overlay {\n position: fixed;\n z-index: calc(100000 + var(--_z-base));\n box-shadow: var(--_floating-shadow);\n border: var(--_floating-border);\n backdrop-filter: var(--_floating-backdrop);\n -webkit-backdrop-filter: var(--_floating-backdrop);\n border-radius: var(--_floating-radius);\n display: flex;\n flex-direction: column;\n /* No overflow:hidden here \u2014 resize handles use negative offsets (top:-3px etc.)\n and would be clipped. The inner .mb-group already has overflow:hidden for\n its own border-radius clipping. */\n}\n\n.mb-floating-overlay > .mb-group {\n flex: 1;\n border-radius: var(--_floating-radius);\n overflow: hidden;\n}\n\n/* Internal split layout inside a floating overlay */\n.mb-floating-overlay > .mb-layout {\n position: relative;\n inset: auto;\n height: auto;\n flex: 1;\n min-width: 0;\n min-height: 0;\n border-radius: var(--_floating-radius);\n overflow: hidden;\n}\n\n.mb-floating-maximized {\n border-radius: 0;\n box-shadow: none;\n}\n\n.mb-floating-maximized .mb-group {\n border-radius: 0;\n}\n\n.mb-floating-maximized .mb-resize-handle {\n display: none !important;\n}\n\n.mb-floating-maximized .mb-group-header-void {\n pointer-events: none;\n}\n\n/* \u2500\u2500 Resize handles \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.mb-resize-handle {\n position: absolute;\n z-index: calc(10 + var(--_z-base));\n touch-action: none;\n}\n\n.mb-resize-n { top: -3px; left: 8px; right: 8px; height: 6px; cursor: n-resize; }\n.mb-resize-s { bottom: -3px; left: 8px; right: 8px; height: 6px; cursor: s-resize; }\n.mb-resize-e { right: -3px; top: 8px; bottom: 8px; width: 6px; cursor: e-resize; }\n.mb-resize-w { left: -3px; top: 8px; bottom: 8px; width: 6px; cursor: w-resize; }\n.mb-resize-ne { top: -3px; right: -3px; width: 12px; height: 12px; cursor: ne-resize; }\n.mb-resize-nw { top: -3px; left: -3px; width: 12px; height: 12px; cursor: nw-resize; }\n.mb-resize-se { bottom: -3px; right: -3px; width: 12px; height: 12px; cursor: se-resize; }\n.mb-resize-sw { bottom: -3px; left: -3px; width: 12px; height: 12px; cursor: sw-resize; }\n\n/* \u2500\u2500 Iframe styling \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.mb-adapt__iframe {\n width: 100%;\n height: 100%;\n min-height: 0;\n border: 0;\n display: block;\n background: transparent;\n border-radius: var(--_border-radius);\n pointer-events: auto;\n opacity: 0;\n transition: opacity 0.1s ease-out;\n}\n\n.mb-adapt__iframe--visible {\n opacity: 1;\n}\n\n.mb-adapt__iframe--hidden {\n display: none;\n}\n\n/* \u2500\u2500 Status message overlay \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.mb-adapt__status-message {\n position: absolute;\n inset: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: calc(200000 + var(--_z-base));\n background: transparent;\n pointer-events: none;\n}\n\n.mb-adapt__status-card {\n pointer-events: auto;\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 16px;\n padding: 32px 40px;\n max-width: 380px;\n border-radius: 16px;\n background: var(--_status-card-bg);\n border: 1px solid var(--_status-card-border);\n box-shadow: var(--_status-card-shadow);\n font-family: var(--_font);\n text-align: center;\n}\n\n.mb-adapt__status-icon {\n width: 48px;\n height: 48px;\n border-radius: 12px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: var(--_status-icon-bg);\n}\n\n.mb-adapt__status-icon svg {\n width: 24px;\n height: 24px;\n}\n\n.mb-adapt__status-icon--stopped {\n background: var(--_status-icon-stopped-bg);\n}\n\n.mb-adapt__status-text {\n color: var(--_status-text);\n font-size: 15px;\n line-height: 1.5;\n margin: 0;\n}\n\n.mb-adapt__status-restart {\n padding: 8px 20px;\n border: 1px solid var(--_status-card-border);\n border-radius: 8px;\n background: transparent;\n color: var(--_status-text);\n font-size: 14px;\n font-weight: 500;\n font-family: var(--_font);\n cursor: pointer;\n transition: background 0.15s, border-color 0.15s;\n}\n\n.mb-adapt__status-restart:hover {\n background: var(--_status-card-border);\n}\n\n/* \u2500\u2500 Confirm-on-close dialog \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.mb-adapt__confirm-overlay {\n position: fixed;\n inset: 0;\n display: flex;\n flex-direction: row;\n align-items: center;\n justify-content: center;\n z-index: calc(300000 + var(--_z-base));\n background: rgba(0, 0, 0, 0.4);\n height: auto;\n min-height: 0;\n}\n\n.mb-adapt--dark.mb-adapt__confirm-overlay {\n background: rgba(0, 0, 0, 0.55);\n}\n\n.mb-adapt__confirm-card {\n display: flex;\n flex-direction: column;\n align-items: stretch;\n gap: 16px;\n padding: 24px 28px;\n max-width: 360px;\n width: 100%;\n border-radius: var(--_floating-radius);\n background: var(--_fork-tab-active-bg);\n border: 1px solid var(--_fork-separator);\n box-shadow: var(--_floating-shadow);\n font-family: var(--_font);\n text-align: center;\n}\n\n.mb-adapt__confirm-text {\n font-size: 14px;\n line-height: 1.5;\n color: var(--_fork-tab-color);\n margin: 0;\n}\n\n.mb-adapt__confirm-buttons {\n display: flex;\n gap: 8px;\n justify-content: flex-end;\n}\n\n.mb-adapt__confirm-btn {\n padding: 8px 16px;\n border-radius: 6px;\n font-size: 13px;\n font-family: var(--_font);\n cursor: pointer;\n font-weight: 500;\n transition: background 0.15s, border-color 0.15s;\n}\n\n.mb-adapt__confirm-btn--cancel {\n background: transparent;\n border: 1px solid var(--_fork-separator);\n color: var(--_fork-tab-color);\n}\n\n.mb-adapt__confirm-btn--cancel:hover {\n background: var(--_button-hover-bg);\n}\n\n.mb-adapt__confirm-btn--confirm {\n background: var(--_fork-tab-color);\n color: var(--_fork-tab-active-bg);\n border: 1px solid transparent;\n}\n\n.mb-adapt__confirm-btn--confirm:hover {\n opacity: 0.85;\n}\n\n/* \u2500\u2500 Cap.js widget positioning \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.mb-adapt-cap {\n position: absolute;\n inset: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n pointer-events: none;\n z-index: calc(200000 + var(--_z-base));\n}\n\n.mb-adapt-cap > * {\n pointer-events: auto;\n}\n\n/* Cap.js widget styling */\n.mb-adapt cap-widget {\n --cap-background: var(--_cap-background);\n --cap-border-color: var(--_cap-border-color);\n --cap-border-radius: var(--_cap-border-radius);\n --cap-widget-height: var(--_cap-height);\n --cap-widget-width: var(--_cap-width);\n --cap-widget-padding: var(--_cap-padding);\n --cap-gap: var(--_cap-gap);\n --cap-color: var(--_cap-color);\n --cap-checkbox-size: var(--_cap-checkbox-size);\n --cap-checkbox-border: var(--_cap-checkbox-border);\n --cap-checkbox-border-radius: var(--_cap-checkbox-radius);\n --cap-checkbox-background: var(--_cap-checkbox-background);\n --cap-checkbox-margin: 0;\n --cap-font: var(--_cap-font);\n --cap-spinner-color: var(--_cap-spinner-color);\n --cap-spinner-background-color: var(--_cap-spinner-bg);\n --cap-spinner-thickness: var(--_cap-spinner-thickness);\n}\n\n/* Hide Cap.js credits */\ncap-widget::part(attribution) {\n display: none;\n}\n\n/* \u2500\u2500 Fork group action buttons \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.mb-adapt-fork-actions {\n display: flex;\n align-items: center;\n gap: 2px;\n padding-right: 4px;\n}\n.mb-adapt-fork-actions button {\n width: 20px;\n height: 20px;\n padding: 0;\n border: none;\n background: transparent;\n color: var(--_fork-tab-color);\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n border-radius: 3px;\n opacity: 0.7;\n transition: opacity 0.15s, background 0.15s;\n}\n.mb-adapt-fork-actions button:hover {\n opacity: 1;\n background: var(--_button-hover-bg);\n}\n.mb-adapt-fork-actions button svg {\n width: 14px;\n height: 14px;\n}\n\n/* \u2500\u2500 Minimized-group tabs bar (at the top, NOT an overlay) \u2500\u2500\u2500 */\n/* Sits at the top of .mb-adapt as a normal flow element so the layout\n underneath shrinks to accommodate it. This prevents scrollbars when\n docked panels are minimized \u2014 the iframe gets the remaining height. */\n.mb-adapt-minimized-tabs {\n display: none;\n height: var(--_toolbar-height);\n flex-shrink: 0;\n z-index: calc(100 + var(--_z-base));\n align-items: stretch;\n background: var(--_fork-tab-bg);\n border-bottom: 1px solid var(--_fork-separator);\n user-select: none;\n}\n.mb-adapt-minimized-tab {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 0 12px;\n flex: 1;\n background: var(--_fork-tab-bg);\n color: var(--_fork-tab-color);\n font-size: var(--_tab-font-size);\n font-family: var(--_font);\n white-space: nowrap;\n border-right: 1px solid var(--_fork-separator);\n cursor: default;\n}\n.mb-adapt-minimized-tab-label {\n flex: 1;\n display: flex;\n align-items: center;\n gap: 4px;\n}\n\n.mb-adapt-minimized-tab-label svg {\n width: 14px;\n height: 14px;\n opacity: 0.8;\n flex-shrink: 0;\n}\n.mb-adapt-minimized-tab-action {\n width: 22px;\n height: 22px;\n padding: 0;\n border: none;\n background: transparent;\n color: inherit;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n border-radius: 4px;\n opacity: 0.6;\n transition: opacity 0.15s, background 0.15s;\n}\n.mb-adapt-minimized-tab-action:hover {\n opacity: 1;\n background: var(--_button-hover-bg);\n}\n.mb-adapt-minimized-tab-action svg {\n width: 14px;\n height: 14px;\n}\n\n/* Minimized tab drag handle cursor */\n.mb-adapt-minimized-tab {\n cursor: grab;\n touch-action: none;\n}\n\n/* Drop target highlight for minimized tab merge */\n.mb-adapt-minimized-tab--drop-target {\n background: var(--_drop-header-bg) !important;\n box-shadow: inset 0 0 0 2px var(--_drop-border);\n}\n\n/* \u2500\u2500 Pointer-drag ghost element \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.mb-drag-ghost {\n position: fixed;\n pointer-events: none;\n z-index: calc(999999 + var(--_z-base));\n padding: 4px 10px;\n background: var(--_fork-tab-bg);\n color: var(--_fork-tab-color);\n border: 1px solid var(--_fork-separator);\n border-radius: var(--_tab-radius, 4px);\n font-size: var(--_tab-font-size);\n font-family: var(--_font);\n white-space: nowrap;\n box-shadow: var(--_drag-ghost-shadow);\n opacity: 0.92;\n display: flex;\n align-items: center;\n}\n\n.mb-drag-ghost svg {\n width: 16px;\n height: 16px;\n}\n\n/* \u2500\u2500 Drop target highlight on group header \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.mb-group-header--drop-target {\n background: var(--_drop-header-bg) !important;\n box-shadow: inset 0 0 0 2px var(--_drop-border);\n}\n\n/* \u2500\u2500 Drop overlay (content-area and dock-strip indicators) */\n.mb-drop-overlay {\n position: fixed;\n pointer-events: none;\n z-index: calc(999998 + var(--_z-base));\n display: none;\n box-sizing: border-box;\n border-radius: 6px;\n transition: opacity 0.1s ease-out;\n}\n\n.mb-drop-overlay[data-zone=\"center\"] {\n background: var(--_drop-center-bg);\n border: 2px solid var(--_drop-border);\n}\n\n.mb-drop-overlay[data-zone=\"top\"],\n.mb-drop-overlay[data-zone=\"bottom\"],\n.mb-drop-overlay[data-zone=\"left\"],\n.mb-drop-overlay[data-zone=\"right\"] {\n background: var(--_drop-split-bg);\n border: 2px solid var(--_drop-border);\n}\n\n/* \u2500\u2500 Iframe pointer-event guard during drag \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\nhtml.mb-dragging iframe,\nhtml.mb-dragging webview {\n pointer-events: none !important;\n}\n\n/* \u2500\u2500 Tab pop-out button \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.mb-tab-popout {\n width: 18px;\n height: 18px;\n padding: 0;\n border: none;\n background: transparent;\n color: inherit;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n border-radius: 3px;\n opacity: 0;\n transition: opacity 0.15s, background 0.15s;\n}\n\n.mb-tab:hover .mb-tab-popout {\n opacity: 0.7;\n}\n\n.mb-tab-popout:hover {\n opacity: 1 !important;\n background: var(--_button-hover-bg);\n}\n\n.mb-tab-popout svg {\n width: 12px;\n height: 12px;\n}\n\n/* Hide pop-out button on main group (never floats), when overlay\n has 0 or 1 total tabs (nothing to pop out), and when floating is disallowed. */\n.mb-group[data-main-group=\"true\"] .mb-tab-popout,\n.mb-floating-overlay[data-total-tab-count=\"0\"] .mb-tab-popout,\n.mb-floating-overlay[data-total-tab-count=\"1\"] .mb-tab-popout,\n.mb-group[data-allow-floating=\"false\"] .mb-tab-popout {\n display: none !important;\n}\n\n\n/* \u2500\u2500 Iframe portal layer \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n/* MUST NOT create a stacking context \u2014 portal entries' z-indexes\n must compete with floating overlays in the parent stacking context.\n position: absolute + no z-index achieves this. */\n.mb-iframe-portal-layer {\n position: absolute;\n width: 0;\n height: 0;\n overflow: visible;\n pointer-events: none;\n}\n.mb-iframe-portal {\n position: fixed;\n pointer-events: auto;\n overflow: hidden;\n}\n\n/* \u2500\u2500 Touch device adjustments \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n@media (hover: none) {\n .mb-tab-close {\n opacity: 0.5;\n }\n\n .mb-tab-popout {\n opacity: 0.5;\n }\n\n .mb-tab:hover .mb-tab-close,\n .mb-tab:hover .mb-tab-popout {\n opacity: 0.7;\n }\n}\n\n@media (pointer: coarse) {\n .mb-tab-close,\n .mb-tab-popout {\n width: 24px;\n height: 24px;\n }\n\n .mb-adapt-fork-actions button {\n width: 26px;\n height: 26px;\n }\n\n .mb-adapt-minimized-tab-action {\n width: 28px;\n height: 28px;\n }\n}";
|
package/dist/types/index.d.ts
CHANGED
|
@@ -3,7 +3,7 @@ import { createConnectClient } from "@mochabug/adapt-core/connect";
|
|
|
3
3
|
import { IframePanelComponent, type IframePanelHost } from "./panel-setup.js";
|
|
4
4
|
import { type AdaptTheme } from "./theme.js";
|
|
5
5
|
import type { AdaptWebClientOptions } from "./types.js";
|
|
6
|
-
export type { AdaptTheme, AdaptWebClientOptions, CapWidgetI18n, CapWidgetOptions, ChallengeInfo, ForkDisplay, Output, PersistOptions, RedeemedChallenge, SignalValue, StatusJson, StatusText, } from "./types.js";
|
|
6
|
+
export type { AdaptError, AdaptErrorKind, AdaptTheme, AdaptWebClientOptions, CapWidgetI18n, CapWidgetOptions, ChallengeInfo, ForkDisplay, Output, PersistOptions, RedeemedChallenge, SignalValue, StatusJson, StatusText, } from "./types.js";
|
|
7
7
|
export { resolveTheme } from "./theme.js";
|
|
8
8
|
export type { SignalData } from "@mochabug/adapt-core";
|
|
9
9
|
export { createConnectClient };
|
|
@@ -243,4 +243,5 @@ export declare class AdaptWebClient implements IframePanelHost {
|
|
|
243
243
|
private showErrorStatus;
|
|
244
244
|
private isExpiredTokenError;
|
|
245
245
|
private getErrorMessage;
|
|
246
|
+
private classifyError;
|
|
246
247
|
}
|
|
@@ -381,7 +381,9 @@ export declare class PanelManager {
|
|
|
381
381
|
private portalRaf;
|
|
382
382
|
private mainGroupCollapsed;
|
|
383
383
|
private _beforeTabClose;
|
|
384
|
+
private zBase;
|
|
384
385
|
constructor(opts: PanelManagerOptions);
|
|
386
|
+
private getZBase;
|
|
385
387
|
setBeforeTabClose(cb: ((panelId: string) => boolean | Promise<boolean>) | null): void;
|
|
386
388
|
addPanel(opts: PanelOptions): Panel;
|
|
387
389
|
removePanel(panelId: string): void;
|
package/dist/types/types.d.ts
CHANGED
|
@@ -402,6 +402,23 @@ export interface AdaptWebClientOptions {
|
|
|
402
402
|
* @param active - Whether a fork is visually active
|
|
403
403
|
*/
|
|
404
404
|
onForkActive?: (active: boolean) => void;
|
|
405
|
+
/**
|
|
406
|
+
* Callback invoked when the automation encounters an error.
|
|
407
|
+
* Receives a structured error with classification, message, and retriability.
|
|
408
|
+
* Fires for both init-phase errors (e.g. invalid inheritToken) and streaming errors.
|
|
409
|
+
*
|
|
410
|
+
* @example
|
|
411
|
+
* ```typescript
|
|
412
|
+
* onError: (error) => {
|
|
413
|
+
* if (error.retriable) {
|
|
414
|
+
* console.log('Retriable error:', error.kind, error.message);
|
|
415
|
+
* } else {
|
|
416
|
+
* console.error('Fatal error:', error.kind, error.message);
|
|
417
|
+
* }
|
|
418
|
+
* }
|
|
419
|
+
* ```
|
|
420
|
+
*/
|
|
421
|
+
onError?: (error: AdaptError) => void;
|
|
405
422
|
/**
|
|
406
423
|
* Custom CSS class names to override default styling.
|
|
407
424
|
* All properties are optional. Unspecified classes use defaults.
|
|
@@ -511,3 +528,10 @@ export interface StatusText {
|
|
|
511
528
|
/** Label for the restart/try-again button on status cards. Default: `"Try again"` */
|
|
512
529
|
restartButton?: string;
|
|
513
530
|
}
|
|
531
|
+
export type AdaptErrorKind = 'auth' | 'expired' | 'not_found' | 'session_not_found' | 'capacity' | 'error';
|
|
532
|
+
export interface AdaptError {
|
|
533
|
+
kind: AdaptErrorKind;
|
|
534
|
+
message: string;
|
|
535
|
+
retriable: boolean;
|
|
536
|
+
cause?: unknown;
|
|
537
|
+
}
|
|
@@ -4324,7 +4324,7 @@ var MbAdapt = (() => {
|
|
|
4324
4324
|
// src/cap-adapter.ts
|
|
4325
4325
|
if (typeof window !== "undefined" && true && !window.CAP_CUSTOM_WASM_URL) {
|
|
4326
4326
|
window.CAP_CUSTOM_WASM_URL = new URL(
|
|
4327
|
-
"https://cdn.mochabug.com/adapt/web/1.0.1-rc.
|
|
4327
|
+
"https://cdn.mochabug.com/adapt/web/1.0.1-rc.17/cap_wasm.js",
|
|
4328
4328
|
window.location.href
|
|
4329
4329
|
).href;
|
|
4330
4330
|
}
|
|
Binary file
|