@mochabug/adapt-web 1.0.1-rc.14 → 1.0.1-rc.16
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/cap-adapter.js +1 -1
- package/dist/esm/css-panel.js +11 -10
- package/dist/esm/panel-manager.js +1 -1
- package/dist/styles.css +11 -10
- package/dist/types/css-panel.d.ts +1 -1
- package/dist/types/panel-manager.d.ts +2 -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 +21 -11
- package/dist/umd/adapt-web.core.js.br +0 -0
- package/dist/umd/adapt-web.core.min.js +14 -13
- package/dist/umd/adapt-web.core.min.js.br +0 -0
- package/dist/umd/adapt-web.js +22 -12
- package/dist/umd/adapt-web.js.br +0 -0
- package/dist/umd/adapt-web.min.js +17 -16
- package/dist/umd/adapt-web.min.js.br +0 -0
- package/dist/umd/styles.css +11 -10
- package/dist/umd/styles.css.br +0 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -436,6 +436,16 @@ All three approaches compose — use `theme` for colors, CSS variables for fine-
|
|
|
436
436
|
| `--mb-adapt-cap-spinner-thickness` | `3px` | |
|
|
437
437
|
| `--mb-adapt-cap-font` | `inherit` | |
|
|
438
438
|
|
|
439
|
+
### Z-index / stacking
|
|
440
|
+
|
|
441
|
+
| Variable | Default | Description |
|
|
442
|
+
|---|---|---|
|
|
443
|
+
| `--mb-adapt-z-base` | `0` | Base z-index offset — added to all internal z-index values |
|
|
444
|
+
|
|
445
|
+
Set `--mb-adapt-z-base` to shift all internal z-index values. Useful when embedding inside modals or drawers that have their own stacking context. Example: `--mb-adapt-z-base: 10000` lifts all layers by 10000.
|
|
446
|
+
|
|
447
|
+
Internal stacking order from low to high: separators (1), resize handles (10), minimized tabs (100), floating panels (100000+), status/cap (200000), confirm dialog (300000), drop targets (999998), drag ghost (999999). All values are offset by `--mb-adapt-z-base`.
|
|
448
|
+
|
|
439
449
|
</details>
|
|
440
450
|
|
|
441
451
|
---
|
package/dist/README.md
CHANGED
|
@@ -6,7 +6,7 @@ Embed Adapt automations in any website.
|
|
|
6
6
|
npm install @mochabug/adapt-web
|
|
7
7
|
```
|
|
8
8
|
|
|
9
|
-
**CDN base:** `https://cdn.mochabug.com/adapt/web/1.0.1-rc.
|
|
9
|
+
**CDN base:** `https://cdn.mochabug.com/adapt/web/1.0.1-rc.16/`
|
|
10
10
|
|
|
11
11
|
| Bundle | File | Includes |
|
|
12
12
|
|--------|------|----------|
|
|
@@ -20,8 +20,8 @@ npm install @mochabug/adapt-web
|
|
|
20
20
|
Bundles merge into a single `MbAdapt` global, so you can combine them. For example, headless + Cap for automations that need proof-of-work but no UI:
|
|
21
21
|
|
|
22
22
|
```html
|
|
23
|
-
<script src="https://cdn.mochabug.com/adapt/web/1.0.1-rc.
|
|
24
|
-
<script src="https://cdn.mochabug.com/adapt/web/1.0.1-rc.
|
|
23
|
+
<script src="https://cdn.mochabug.com/adapt/web/1.0.1-rc.16/adapt-core.min.js"></script>
|
|
24
|
+
<script src="https://cdn.mochabug.com/adapt/web/1.0.1-rc.16/adapt-web.cap.min.js"></script>
|
|
25
25
|
<script>
|
|
26
26
|
// MbAdapt has exports from both scripts
|
|
27
27
|
var client = MbAdapt.createAdaptClient(
|
|
@@ -43,12 +43,12 @@ Preload the script and load the stylesheet in `<head>` to eliminate flash of uns
|
|
|
43
43
|
|
|
44
44
|
```html
|
|
45
45
|
<head>
|
|
46
|
-
<link rel="preload" href="https://cdn.mochabug.com/adapt/web/1.0.1-rc.
|
|
47
|
-
<link rel="stylesheet" href="https://cdn.mochabug.com/adapt/web/1.0.1-rc.
|
|
46
|
+
<link rel="preload" href="https://cdn.mochabug.com/adapt/web/1.0.1-rc.16/adapt-web.min.js" as="script">
|
|
47
|
+
<link rel="stylesheet" href="https://cdn.mochabug.com/adapt/web/1.0.1-rc.16/styles.css">
|
|
48
48
|
</head>
|
|
49
49
|
<body>
|
|
50
50
|
<adapt-automation automation-id="YOUR_ID" requires-challenge style="height: 600px"></adapt-automation>
|
|
51
|
-
<script src="https://cdn.mochabug.com/adapt/web/1.0.1-rc.
|
|
51
|
+
<script src="https://cdn.mochabug.com/adapt/web/1.0.1-rc.16/adapt-web.min.js"></script>
|
|
52
52
|
</body>
|
|
53
53
|
```
|
|
54
54
|
|
|
@@ -56,12 +56,12 @@ No challenges? Use the core bundle and drop `requires-challenge`:
|
|
|
56
56
|
|
|
57
57
|
```html
|
|
58
58
|
<head>
|
|
59
|
-
<link rel="preload" href="https://cdn.mochabug.com/adapt/web/1.0.1-rc.
|
|
60
|
-
<link rel="stylesheet" href="https://cdn.mochabug.com/adapt/web/1.0.1-rc.
|
|
59
|
+
<link rel="preload" href="https://cdn.mochabug.com/adapt/web/1.0.1-rc.16/adapt-web.core.min.js" as="script">
|
|
60
|
+
<link rel="stylesheet" href="https://cdn.mochabug.com/adapt/web/1.0.1-rc.16/styles.css">
|
|
61
61
|
</head>
|
|
62
62
|
<body>
|
|
63
63
|
<adapt-automation automation-id="YOUR_ID" style="height: 600px"></adapt-automation>
|
|
64
|
-
<script src="https://cdn.mochabug.com/adapt/web/1.0.1-rc.
|
|
64
|
+
<script src="https://cdn.mochabug.com/adapt/web/1.0.1-rc.16/adapt-web.core.min.js"></script>
|
|
65
65
|
</body>
|
|
66
66
|
```
|
|
67
67
|
|
|
@@ -71,14 +71,14 @@ Just the element and script. CSS is auto-injected at runtime.
|
|
|
71
71
|
|
|
72
72
|
```html
|
|
73
73
|
<adapt-automation automation-id="YOUR_ID" requires-challenge style="height: 600px"></adapt-automation>
|
|
74
|
-
<script src="https://cdn.mochabug.com/adapt/web/1.0.1-rc.
|
|
74
|
+
<script src="https://cdn.mochabug.com/adapt/web/1.0.1-rc.16/adapt-web.min.js"></script>
|
|
75
75
|
```
|
|
76
76
|
|
|
77
77
|
Without challenges:
|
|
78
78
|
|
|
79
79
|
```html
|
|
80
80
|
<adapt-automation automation-id="YOUR_ID" style="height: 600px"></adapt-automation>
|
|
81
|
-
<script src="https://cdn.mochabug.com/adapt/web/1.0.1-rc.
|
|
81
|
+
<script src="https://cdn.mochabug.com/adapt/web/1.0.1-rc.16/adapt-web.core.min.js"></script>
|
|
82
82
|
```
|
|
83
83
|
|
|
84
84
|
### ESM
|
|
@@ -160,12 +160,12 @@ Requires a `client` JS property — set it after the element is in the DOM.
|
|
|
160
160
|
|
|
161
161
|
```html
|
|
162
162
|
<head>
|
|
163
|
-
<link rel="preload" href="https://cdn.mochabug.com/adapt/web/1.0.1-rc.
|
|
164
|
-
<link rel="stylesheet" href="https://cdn.mochabug.com/adapt/web/1.0.1-rc.
|
|
163
|
+
<link rel="preload" href="https://cdn.mochabug.com/adapt/web/1.0.1-rc.16/adapt-web.cap.min.js" as="script">
|
|
164
|
+
<link rel="stylesheet" href="https://cdn.mochabug.com/adapt/web/1.0.1-rc.16/styles.css">
|
|
165
165
|
</head>
|
|
166
166
|
<body>
|
|
167
167
|
<adapt-cap automation-id="YOUR_ID"></adapt-cap>
|
|
168
|
-
<script src="https://cdn.mochabug.com/adapt/web/1.0.1-rc.
|
|
168
|
+
<script src="https://cdn.mochabug.com/adapt/web/1.0.1-rc.16/adapt-web.cap.min.js"></script>
|
|
169
169
|
<script>
|
|
170
170
|
var el = document.querySelector('adapt-cap');
|
|
171
171
|
el.client = MbAdapt.createConnectClient({ id: 'YOUR_ID' });
|
|
@@ -180,7 +180,7 @@ Requires a `client` JS property — set it after the element is in the DOM.
|
|
|
180
180
|
|
|
181
181
|
```html
|
|
182
182
|
<adapt-cap automation-id="YOUR_ID"></adapt-cap>
|
|
183
|
-
<script src="https://cdn.mochabug.com/adapt/web/1.0.1-rc.
|
|
183
|
+
<script src="https://cdn.mochabug.com/adapt/web/1.0.1-rc.16/adapt-web.cap.min.js"></script>
|
|
184
184
|
<script>
|
|
185
185
|
var el = document.querySelector('adapt-cap');
|
|
186
186
|
el.client = MbAdapt.createConnectClient({ id: 'YOUR_ID' });
|
|
@@ -436,6 +436,16 @@ All three approaches compose — use `theme` for colors, CSS variables for fine-
|
|
|
436
436
|
| `--mb-adapt-cap-spinner-thickness` | `3px` | |
|
|
437
437
|
| `--mb-adapt-cap-font` | `inherit` | |
|
|
438
438
|
|
|
439
|
+
### Z-index / stacking
|
|
440
|
+
|
|
441
|
+
| Variable | Default | Description |
|
|
442
|
+
|---|---|---|
|
|
443
|
+
| `--mb-adapt-z-base` | `0` | Base z-index offset — added to all internal z-index values |
|
|
444
|
+
|
|
445
|
+
Set `--mb-adapt-z-base` to shift all internal z-index values. Useful when embedding inside modals or drawers that have their own stacking context. Example: `--mb-adapt-z-base: 10000` lifts all layers by 10000.
|
|
446
|
+
|
|
447
|
+
Internal stacking order from low to high: separators (1), resize handles (10), minimized tabs (100), floating panels (100000+), status/cap (200000), confirm dialog (300000), drop targets (999998), drag ghost (999999). All values are offset by `--mb-adapt-z-base`.
|
|
448
|
+
|
|
439
449
|
</details>
|
|
440
450
|
|
|
441
451
|
---
|
package/dist/esm/cap-adapter.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
typeof window<"u"&&!window.CAP_CUSTOM_WASM_URL&&(window.CAP_CUSTOM_WASM_URL=new URL("https://cdn.mochabug.com/adapt/web/1.0.1-rc.
|
|
1
|
+
typeof window<"u"&&!window.CAP_CUSTOM_WASM_URL&&(window.CAP_CUSTOM_WASM_URL=new URL("https://cdn.mochabug.com/adapt/web/1.0.1-rc.16/cap_wasm.js",window.location.href).href);import{timestampDate}from"@bufbuild/protobuf/wkt";let currentClient=null,currentAutomationId=null;const verificationTokens=new Map;async function createChallenge(client,id){const response=await client.createChallenge({id});return{count:response.count,size:response.size,difficulty:response.difficulty,expires:response.expires?timestampDate(response.expires):new Date,token:response.token,verificationToken:response.verificationToken}}async function redeemChallenge(client,id,verificationToken,solutions){const response=await client.redeemChallenge({id,verificationToken,solutions});return{token:response.token,expires:response.expires?timestampDate(response.expires):new Date}}typeof window<"u"&&(window.CAP_CUSTOM_FETCH=async(url,options)=>{const urlStr=url.toString();if(urlStr.endsWith("/challenge")){if(!currentClient||!currentAutomationId)return new Response(JSON.stringify({error:"Cap adapter not initialized"}),{status:500,headers:{"Content-Type":"application/json"}});try{const challengeInfo=await createChallenge(currentClient,currentAutomationId);return verificationTokens.set(currentAutomationId,challengeInfo.verificationToken),new Response(JSON.stringify({challenge:{c:challengeInfo.count,s:challengeInfo.size,d:challengeInfo.difficulty},token:challengeInfo.token,expires:challengeInfo.expires.toISOString()}),{status:200,headers:{"Content-Type":"application/json"}})}catch(error){return new Response(JSON.stringify({error:String(error)}),{status:500,headers:{"Content-Type":"application/json"}})}}if(urlStr.endsWith("/redeem")){if(!currentClient||!currentAutomationId)return new Response(JSON.stringify({error:"Cap adapter not initialized"}),{status:500,headers:{"Content-Type":"application/json"}});const verificationToken=verificationTokens.get(currentAutomationId);if(!verificationToken)return new Response(JSON.stringify({error:"No verification token found - challenge must be created first"}),{status:400,headers:{"Content-Type":"application/json"}});try{const solutions=((options?.body?JSON.parse(options.body):{}).solutions||[]).map(s=>BigInt(s)),redeemed=await redeemChallenge(currentClient,currentAutomationId,verificationToken,solutions);return verificationTokens.delete(currentAutomationId),new Response(JSON.stringify({success:!0,token:redeemed.token,expires:redeemed.expires.toISOString()}),{status:200,headers:{"Content-Type":"application/json"}})}catch(error){return new Response(JSON.stringify({error:String(error)}),{status:500,headers:{"Content-Type":"application/json"}})}}return fetch(url,options)});function setupCapAdapter(client,automationId){currentClient=client,currentAutomationId=automationId}function cleanupCapAdapter(){currentAutomationId&&verificationTokens.delete(currentAutomationId),currentClient=null,currentAutomationId=null}export{cleanupCapAdapter,createChallenge,redeemChallenge,setupCapAdapter};
|
package/dist/esm/css-panel.js
CHANGED
|
@@ -31,6 +31,7 @@ const PANEL_MANAGER_CSS=`/* ====================================================
|
|
|
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 @@ const PANEL_MANAGER_CSS=`/* ====================================================
|
|
|
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
|
|
|
@@ -203,7 +204,7 @@ const PANEL_MANAGER_CSS=`/* ====================================================
|
|
|
203
204
|
|
|
204
205
|
.mb-group-tabs {
|
|
205
206
|
display: flex;
|
|
206
|
-
align-items:
|
|
207
|
+
align-items: stretch;
|
|
207
208
|
overflow-x: auto;
|
|
208
209
|
overflow-y: hidden;
|
|
209
210
|
flex: 0 1 auto;
|
|
@@ -349,7 +350,7 @@ const PANEL_MANAGER_CSS=`/* ====================================================
|
|
|
349
350
|
/* \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 */
|
|
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 @@ const PANEL_MANAGER_CSS=`/* ====================================================
|
|
|
400
401
|
/* \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 */
|
|
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 @@ const PANEL_MANAGER_CSS=`/* ====================================================
|
|
|
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 @@ const PANEL_MANAGER_CSS=`/* ====================================================
|
|
|
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 @@ const PANEL_MANAGER_CSS=`/* ====================================================
|
|
|
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 +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
|
|
|
@@ -203,7 +204,7 @@
|
|
|
203
204
|
|
|
204
205
|
.mb-group-tabs {
|
|
205
206
|
display: flex;
|
|
206
|
-
align-items:
|
|
207
|
+
align-items: stretch;
|
|
207
208
|
overflow-x: auto;
|
|
208
209
|
overflow-y: hidden;
|
|
209
210
|
flex: 0 1 auto;
|
|
@@ -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;
|