react-zeugma 6.2.2 → 6.3.0

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.
@@ -16,7 +16,14 @@ interface PaneNode {
16
16
  locked?: boolean;
17
17
  tabsMetadata?: Record<string, Record<string, unknown>>;
18
18
  }
19
- type TreeNode = SplitNode | PaneNode;
19
+ interface WidgetNode {
20
+ type: 'widget';
21
+ id: string;
22
+ locked?: boolean;
23
+ metadata?: Record<string, unknown>;
24
+ }
25
+ type LeafNode = PaneNode | WidgetNode;
26
+ type TreeNode = SplitNode | LeafNode;
20
27
  interface TabDetails {
21
28
  id: string;
22
29
  paneId: string;
@@ -113,14 +120,14 @@ interface ZeugmaController {
113
120
  onResize?: (currentNode: SplitNode, percentage: number) => void;
114
121
  onResizeEnd?: (currentNode: SplitNode, percentage: number) => void;
115
122
  onDismissIntentChange?: (paneId: string | null) => void;
116
- /** Removes the specified pane from the layout tree and collapses its parent split. */
123
+ /** Removes the specified pane or widget from the layout tree and collapses its parent split. */
117
124
  removePane: (paneId: string) => void;
118
- /** Appends/inserts a pane at the bottom-rightmost leaf of the layout tree. */
119
- addPane: (paneId: string, metadata?: Record<string, unknown>) => void;
120
- /** Appends a tab into a target pane node. */
121
- addTab: (paneId: string, tabId: string, metadata?: Record<string, unknown>) => void;
122
- /** Stable callback to update metadata for a specific tab. */
123
- updateTabMetadata: (tabId: string, updater: (current: Record<string, unknown> | undefined) => Record<string, unknown> | undefined) => void;
125
+ /** Appends/inserts a widget at the bottom-rightmost leaf of the layout tree. */
126
+ addWidget: (widgetId: string, metadata?: Record<string, unknown>) => void;
127
+ /** Appends a tab into a target pane node, or splits/creates a new pane if no target pane ID is provided. */
128
+ addTab: (tabId: string, targetPaneId?: string, metadata?: Record<string, unknown>) => void;
129
+ /** Stable callback to update metadata for a specific tab or widget. */
130
+ updateMetadata: (id: string, updater: (current: Record<string, unknown> | undefined) => Record<string, unknown> | undefined) => void;
124
131
  /** Stable callback to update the locked status of a specific pane in the layout tree. */
125
132
  updatePaneLock: (paneId: string, locked: boolean) => void;
126
133
  /** Stable callback to activate a tab within a pane. */
@@ -135,8 +142,8 @@ interface ZeugmaController {
135
142
  updateSplitPercentage: (currentNode: SplitNode, percentage: number) => void;
136
143
  /** Moves/reorders a tab relative to another target tab. */
137
144
  moveTab: (draggedTabId: string, targetTabId: string, position?: 'before' | 'after') => void;
138
- /** Find a PaneNode by its ID in the layout tree. */
139
- findPaneById: (paneId: string) => PaneNode | null;
145
+ /** Find a PaneNode or WidgetNode by its ID in the layout tree. */
146
+ findPaneById: (paneId: string) => LeafNode | null;
140
147
  /** Find the PaneNode containing the given tab ID in the layout tree. */
141
148
  findPaneContainingTab: (tabId: string) => PaneNode | null;
142
149
  /** Find the details of a tab by its ID in the layout tree. */
@@ -201,8 +208,8 @@ interface ZeugmaStateValue {
201
208
  locked: boolean;
202
209
  /** Programmatically updates the global locked status. */
203
210
  setLocked: Dispatch<SetStateAction<boolean>>;
204
- /** Find a PaneNode by its ID in the layout tree. */
205
- findPaneById: (paneId: string) => PaneNode | null;
211
+ /** Find a PaneNode or WidgetNode by its ID in the layout tree. */
212
+ findPaneById: (paneId: string) => LeafNode | null;
206
213
  /** Find the PaneNode containing the given tab ID in the layout tree. */
207
214
  findPaneContainingTab: (tabId: string) => PaneNode | null;
208
215
  /** Find the details of a tab by its ID in the layout tree. */
@@ -234,14 +241,14 @@ interface ZeugmaDragStateValue {
234
241
  * Consumers of only this context will never re-render from layout/drag state changes.
235
242
  */
236
243
  interface ZeugmaActionsValue {
237
- /** Removes the specified pane from the layout tree and collapses its parent split. */
244
+ /** Removes the specified pane or widget from the layout tree and collapses its parent split. */
238
245
  removePane: (paneId: string) => void;
239
- /** Appends/inserts a pane at the bottom-rightmost leaf of the layout tree. */
240
- addPane: (paneId: string, metadata?: Record<string, unknown>) => void;
241
- /** Appends a tab into a target pane node. */
242
- addTab: (paneId: string, tabId: string, metadata?: Record<string, unknown>) => void;
243
- /** Stable callback to update metadata for a specific tab. */
244
- updateTabMetadata: (tabId: string, updater: (current: Record<string, unknown> | undefined) => Record<string, unknown> | undefined) => void;
246
+ /** Appends/inserts a widget at the bottom-rightmost leaf of the layout tree. */
247
+ addWidget: (widgetId: string, metadata?: Record<string, unknown>) => void;
248
+ /** Appends a tab into a target pane node, or splits/creates a new pane if no target pane ID is provided. */
249
+ addTab: (tabId: string, targetPaneId?: string, metadata?: Record<string, unknown>) => void;
250
+ /** Stable callback to update metadata for a specific tab or widget. */
251
+ updateMetadata: (id: string, updater: (current: Record<string, unknown> | undefined) => Record<string, unknown> | undefined) => void;
245
252
  /** Stable callback to update the locked status of a specific pane in the layout tree. */
246
253
  updatePaneLock: (paneId: string, locked: boolean) => void;
247
254
  /** Stable callback to activate a tab within a pane. */
@@ -267,4 +274,4 @@ interface PortalRegistryValue {
267
274
  registerPortalTarget: (tabId: string, el: HTMLDivElement | null) => void;
268
275
  }
269
276
 
270
- export type { PortalRegistryValue as P, SplitDirection as S, TreeNode as T, UseZeugmaOptions as U, ZeugmaActionsValue as Z, ZeugmaDragStateValue as a, ZeugmaStateValue as b, ZeugmaController as c, ZeugmaContextValue as d, ZeugmaProps as e, SplitNode as f, PaneNode as g, TabDetails as h, ZeugmaClassNames as i };
277
+ export type { LeafNode as L, PortalRegistryValue as P, SplitDirection as S, TreeNode as T, UseZeugmaOptions as U, WidgetNode as W, ZeugmaActionsValue as Z, ZeugmaDragStateValue as a, ZeugmaStateValue as b, ZeugmaController as c, ZeugmaContextValue as d, ZeugmaProps as e, SplitNode as f, PaneNode as g, TabDetails as h, ZeugmaClassNames as i };
@@ -16,7 +16,14 @@ interface PaneNode {
16
16
  locked?: boolean;
17
17
  tabsMetadata?: Record<string, Record<string, unknown>>;
18
18
  }
19
- type TreeNode = SplitNode | PaneNode;
19
+ interface WidgetNode {
20
+ type: 'widget';
21
+ id: string;
22
+ locked?: boolean;
23
+ metadata?: Record<string, unknown>;
24
+ }
25
+ type LeafNode = PaneNode | WidgetNode;
26
+ type TreeNode = SplitNode | LeafNode;
20
27
  interface TabDetails {
21
28
  id: string;
22
29
  paneId: string;
@@ -113,14 +120,14 @@ interface ZeugmaController {
113
120
  onResize?: (currentNode: SplitNode, percentage: number) => void;
114
121
  onResizeEnd?: (currentNode: SplitNode, percentage: number) => void;
115
122
  onDismissIntentChange?: (paneId: string | null) => void;
116
- /** Removes the specified pane from the layout tree and collapses its parent split. */
123
+ /** Removes the specified pane or widget from the layout tree and collapses its parent split. */
117
124
  removePane: (paneId: string) => void;
118
- /** Appends/inserts a pane at the bottom-rightmost leaf of the layout tree. */
119
- addPane: (paneId: string, metadata?: Record<string, unknown>) => void;
120
- /** Appends a tab into a target pane node. */
121
- addTab: (paneId: string, tabId: string, metadata?: Record<string, unknown>) => void;
122
- /** Stable callback to update metadata for a specific tab. */
123
- updateTabMetadata: (tabId: string, updater: (current: Record<string, unknown> | undefined) => Record<string, unknown> | undefined) => void;
125
+ /** Appends/inserts a widget at the bottom-rightmost leaf of the layout tree. */
126
+ addWidget: (widgetId: string, metadata?: Record<string, unknown>) => void;
127
+ /** Appends a tab into a target pane node, or splits/creates a new pane if no target pane ID is provided. */
128
+ addTab: (tabId: string, targetPaneId?: string, metadata?: Record<string, unknown>) => void;
129
+ /** Stable callback to update metadata for a specific tab or widget. */
130
+ updateMetadata: (id: string, updater: (current: Record<string, unknown> | undefined) => Record<string, unknown> | undefined) => void;
124
131
  /** Stable callback to update the locked status of a specific pane in the layout tree. */
125
132
  updatePaneLock: (paneId: string, locked: boolean) => void;
126
133
  /** Stable callback to activate a tab within a pane. */
@@ -135,8 +142,8 @@ interface ZeugmaController {
135
142
  updateSplitPercentage: (currentNode: SplitNode, percentage: number) => void;
136
143
  /** Moves/reorders a tab relative to another target tab. */
137
144
  moveTab: (draggedTabId: string, targetTabId: string, position?: 'before' | 'after') => void;
138
- /** Find a PaneNode by its ID in the layout tree. */
139
- findPaneById: (paneId: string) => PaneNode | null;
145
+ /** Find a PaneNode or WidgetNode by its ID in the layout tree. */
146
+ findPaneById: (paneId: string) => LeafNode | null;
140
147
  /** Find the PaneNode containing the given tab ID in the layout tree. */
141
148
  findPaneContainingTab: (tabId: string) => PaneNode | null;
142
149
  /** Find the details of a tab by its ID in the layout tree. */
@@ -201,8 +208,8 @@ interface ZeugmaStateValue {
201
208
  locked: boolean;
202
209
  /** Programmatically updates the global locked status. */
203
210
  setLocked: Dispatch<SetStateAction<boolean>>;
204
- /** Find a PaneNode by its ID in the layout tree. */
205
- findPaneById: (paneId: string) => PaneNode | null;
211
+ /** Find a PaneNode or WidgetNode by its ID in the layout tree. */
212
+ findPaneById: (paneId: string) => LeafNode | null;
206
213
  /** Find the PaneNode containing the given tab ID in the layout tree. */
207
214
  findPaneContainingTab: (tabId: string) => PaneNode | null;
208
215
  /** Find the details of a tab by its ID in the layout tree. */
@@ -234,14 +241,14 @@ interface ZeugmaDragStateValue {
234
241
  * Consumers of only this context will never re-render from layout/drag state changes.
235
242
  */
236
243
  interface ZeugmaActionsValue {
237
- /** Removes the specified pane from the layout tree and collapses its parent split. */
244
+ /** Removes the specified pane or widget from the layout tree and collapses its parent split. */
238
245
  removePane: (paneId: string) => void;
239
- /** Appends/inserts a pane at the bottom-rightmost leaf of the layout tree. */
240
- addPane: (paneId: string, metadata?: Record<string, unknown>) => void;
241
- /** Appends a tab into a target pane node. */
242
- addTab: (paneId: string, tabId: string, metadata?: Record<string, unknown>) => void;
243
- /** Stable callback to update metadata for a specific tab. */
244
- updateTabMetadata: (tabId: string, updater: (current: Record<string, unknown> | undefined) => Record<string, unknown> | undefined) => void;
246
+ /** Appends/inserts a widget at the bottom-rightmost leaf of the layout tree. */
247
+ addWidget: (widgetId: string, metadata?: Record<string, unknown>) => void;
248
+ /** Appends a tab into a target pane node, or splits/creates a new pane if no target pane ID is provided. */
249
+ addTab: (tabId: string, targetPaneId?: string, metadata?: Record<string, unknown>) => void;
250
+ /** Stable callback to update metadata for a specific tab or widget. */
251
+ updateMetadata: (id: string, updater: (current: Record<string, unknown> | undefined) => Record<string, unknown> | undefined) => void;
245
252
  /** Stable callback to update the locked status of a specific pane in the layout tree. */
246
253
  updatePaneLock: (paneId: string, locked: boolean) => void;
247
254
  /** Stable callback to activate a tab within a pane. */
@@ -267,4 +274,4 @@ interface PortalRegistryValue {
267
274
  registerPortalTarget: (tabId: string, el: HTMLDivElement | null) => void;
268
275
  }
269
276
 
270
- export type { PortalRegistryValue as P, SplitDirection as S, TreeNode as T, UseZeugmaOptions as U, ZeugmaActionsValue as Z, ZeugmaDragStateValue as a, ZeugmaStateValue as b, ZeugmaController as c, ZeugmaContextValue as d, ZeugmaProps as e, SplitNode as f, PaneNode as g, TabDetails as h, ZeugmaClassNames as i };
277
+ export type { LeafNode as L, PortalRegistryValue as P, SplitDirection as S, TreeNode as T, UseZeugmaOptions as U, WidgetNode as W, ZeugmaActionsValue as Z, ZeugmaDragStateValue as a, ZeugmaStateValue as b, ZeugmaController as c, ZeugmaContextValue as d, ZeugmaProps as e, SplitNode as f, PaneNode as g, TabDetails as h, ZeugmaClassNames as i };
package/dist/utils.cjs CHANGED
@@ -1,2 +1,2 @@
1
- 'use strict';function p(){return "pane-"+Math.random().toString(36).substring(2,11)}function M(n,t){if(n===null)return null;if(n.type==="pane")return n.id===t?null:n;let e=M(n.first,t),s=M(n.second,t);return e===null?s:s===null?e:{...n,first:e,second:s}}function m(n,t){if(n===null)return null;if(n.type==="pane"){if(n.tabs.includes(t)){let i=n.tabs.filter(l=>l!==t);if(i.length===0)return null;let u=n.activeTabId;n.activeTabId===t&&(u=i[0]);let r={...n.tabsMetadata};return delete r[t],{...n,tabs:i,activeTabId:u,tabsMetadata:Object.keys(r).length>0?r:void 0}}return n}let e=m(n.first,t),s=m(n.second,t);return e===null?s:s===null?e:{...n,first:e,second:s}}function P(n,t,e,s,i){if(n===null)return typeof i=="string"?{type:"pane",id:p(),tabs:[i],activeTabId:i}:i;if(n.type==="pane"){if(n.id===t){let u=typeof i=="string"?{type:"pane",id:p(),tabs:[i],activeTabId:i}:i,r=s==="left"||s==="top";return {type:"split",direction:e,first:r?u:n,second:r?n:u,splitPercentage:50}}return n}return {...n,first:P(n.first,t,e,s,i)||n.first,second:P(n.second,t,e,s,i)||n.second}}function D(n,t,e){if(n===null)return {type:"pane",id:p(),tabs:[t],activeTabId:t,tabsMetadata:e?{[t]:e}:void 0};function s(i,u){return i.type==="pane"?{type:"split",direction:u==="row"?"column":"row",splitPercentage:50,first:i,second:{type:"pane",id:p(),tabs:[t],activeTabId:t,tabsMetadata:e?{[t]:e}:void 0}}:{...i,second:s(i.second,i.direction)}}return s(n,null)}function x(n,t,e){return n===null?null:n===t?{...n,splitPercentage:e}:n.type==="split"?{...n,first:x(n.first,t,e)||n.first,second:x(n.second,t,e)||n.second}:n}function v(n,t){return n===null?null:n.type==="pane"?n.id===t?n:null:v(n.first,t)??v(n.second,t)}function T(n,t){return n===null?null:n.type==="pane"?n.tabs.includes(t)?n:null:T(n.first,t)??T(n.second,t)}function g(n,t){let e=T(n,t);if(!e)return null;let s=e.tabs.indexOf(t);return {id:t,paneId:e.id,isActive:e.activeTabId===t,index:s,metadata:e.tabsMetadata?.[t]}}function S(n,t,e){if(n===null)return null;if(n.type==="pane"){if(n.tabs.includes(t)){let s=n.tabsMetadata||{},i=s[t],u=e(i),r={...s};return u===void 0?delete r[t]:r[t]=u,{...n,tabsMetadata:Object.keys(r).length>0?r:void 0}}return n}return {...n,first:S(n.first,t,e)??n.first,second:S(n.second,t,e)??n.second}}function w(n,t,e){if(n===null)return null;if(n.type==="pane"){if(n.id===t){if(e===false){let{locked:s,...i}=n;return i}return {...n,locked:e}}return n}return {...n,first:w(n.first,t,e)??n.first,second:w(n.second,t,e)??n.second}}function C(n,t,e){return n===null?null:n.type==="pane"?n.id===t?n.activeTabId===e?n:{...n,activeTabId:e}:n:{...n,first:C(n.first,t,e)??n.first,second:C(n.second,t,e)??n.second}}function L(n,t,e){if(n===null)return null;let i=T(n,t)?.tabsMetadata?.[t],u=m(n,t);if(u===null)return {type:"pane",id:p(),tabs:[t],activeTabId:t,tabsMetadata:i?{[t]:i}:void 0};function r(l){if(l.type==="pane"){if(l.id===e){let o=[...l.tabs];o.includes(t)||o.push(t);let c={...l.tabsMetadata};return i&&(c[t]=i),{...l,tabs:o,activeTabId:t,tabsMetadata:Object.keys(c).length>0?c:void 0}}return l}return {...l,first:r(l.first),second:r(l.second)}}return r(u)}function k(n,t,e,s="before"){if(n===null)return null;let u=T(n,t)?.tabsMetadata?.[t],r=m(n,t);if(r===null)return {type:"pane",id:p(),tabs:[t],activeTabId:t,tabsMetadata:u?{[t]:u}:void 0};function l(o){if(o.type==="pane"){if(o.tabs.includes(e)){let y=[...o.tabs].filter(b=>b!==t),d=y.indexOf(e);d<0&&(d=0),s==="after"&&(d+=1),y.splice(d,0,t);let a={...o.tabsMetadata};return u&&(a[t]=u),{...o,tabs:y,activeTabId:t,tabsMetadata:Object.keys(a).length>0?a:void 0}}return o}return {...o,first:l(o.first),second:l(o.second)}}return l(r)}function N(n,t=0,e=0,s=100,i=100,u="root"){if(n===null)return {panes:[],splitters:[]};if(n.type==="pane")return {panes:[{paneId:n.id,left:t,top:e,width:s,height:i,node:n}],splitters:[]};let{direction:r,splitPercentage:l,first:o,second:c}=n,d={id:`splitter-${u}-${r}`,currentNode:n,direction:r,left:r==="row"?t+s*(l/100):t,top:r==="column"?e+i*(l/100):e,width:r==="row"?0:s,height:r==="column"?0:i,parentLeft:t,parentTop:e,parentWidth:s,parentHeight:i},a={panes:[],splitters:[]},b={panes:[],splitters:[]};if(r==="row"){let f=s*(l/100);a=N(o,t,e,f,i,`${u}-L`),b=N(c,t+f,e,s-f,i,`${u}-R`);}else {let f=i*(l/100);a=N(o,t,e,s,f,`${u}-T`),b=N(c,t,e+f,s,i-f,`${u}-B`);}return {panes:[...a.panes,...b.panes],splitters:[d,...a.splitters,...b.splitters]}}function O(n,t,e,s){if(!(t==="tab"&&e&&n.includes(e))||!s)return -1;let r=n.indexOf(e);return s==="before"?r:r+1}exports.addPane=D;exports.calculateTabDropIndex=O;exports.computeLayout=N;exports.findPaneById=v;exports.findPaneContainingTab=T;exports.findTabById=g;exports.generateUniqueId=p;exports.mergeTab=L;exports.moveTab=k;exports.removePane=M;exports.removeTab=m;exports.selectTab=C;exports.splitPane=P;exports.updatePaneLock=w;exports.updateSplitPercentage=x;exports.updateTabMetadata=S;//# sourceMappingURL=utils.cjs.map
1
+ 'use strict';function d(){return "pane-"+Math.random().toString(36).substring(2,11)}function M(n,t){if(n===null)return null;if(n.type==="pane"||n.type==="widget")return n.id===t?null:n;let e=M(n.first,t),i=M(n.second,t);return e===null?i:i===null?e:{...n,first:e,second:i}}function m(n,t){if(n===null)return null;if(n.type==="widget")return n;if(n.type==="pane"){if(n.tabs.includes(t)){let r=n.tabs.filter(l=>l!==t);if(r.length===0)return null;let a=n.activeTabId;n.activeTabId===t&&(a=r[0]);let u={...n.tabsMetadata};return delete u[t],{...n,tabs:r,activeTabId:a,tabsMetadata:Object.keys(u).length>0?u:void 0}}return n}let e=m(n.first,t),i=m(n.second,t);return e===null?i:i===null?e:{...n,first:e,second:i}}function x(n,t,e,i,r){if(n===null)return typeof r=="string"?{type:"pane",id:d(),tabs:[r],activeTabId:r}:r;if(n.type==="pane"||n.type==="widget"){if(n.id===t){let a=typeof r=="string"?{type:"pane",id:d(),tabs:[r],activeTabId:r}:r,u=i==="left"||i==="top";return {type:"split",direction:e,first:u?a:n,second:u?n:a,splitPercentage:50}}return n}return {...n,first:x(n.first,t,e,i,r)||n.first,second:x(n.second,t,e,i,r)||n.second}}function L(n,t){if(n===null)return t;function e(i,r){return i.type==="pane"||i.type==="widget"?{type:"split",direction:r==="row"?"column":"row",splitPercentage:50,first:i,second:t}:{...i,second:e(i.second,i.direction)}}return e(n,null)}function C(n,t,e){return L(n,{type:"widget",id:t,metadata:e})}function D(n,t,e,i){if(n===null)return {type:"pane",id:d(),tabs:[e],activeTabId:e,tabsMetadata:i?{[e]:i}:void 0};let r=t?w(n,t):null;if(r&&r.type==="pane"){let l=function(s){if(s.type==="pane"&&s.id===t){let o=[...s.tabs];o.includes(e)||o.push(e);let c=s.tabsMetadata;return i&&(c={...s.tabsMetadata,[e]:i}),{...s,tabs:o,activeTabId:e,tabsMetadata:c}}return s.type==="split"?{...s,first:l(s.first),second:l(s.second)}:s};return l(n)}let a={type:"pane",id:d(),tabs:[e],activeTabId:e,tabsMetadata:i?{[e]:i}:void 0};return L(n,a)}function P(n,t,e){return n===null?null:n===t?{...n,splitPercentage:e}:n.type==="split"?{...n,first:P(n.first,t,e)||n.first,second:P(n.second,t,e)||n.second}:n}function w(n,t){return n===null?null:n.type==="pane"||n.type==="widget"?n.id===t?n:null:n.type==="split"?w(n.first,t)??w(n.second,t):null}function y(n,t){return n===null?null:n.type==="pane"?n.tabs.includes(t)?n:null:n.type==="split"?y(n.first,t)??y(n.second,t):null}function k(n,t){let e=y(n,t);if(!e)return null;let i=e.tabs.indexOf(t);return {id:t,paneId:e.id,isActive:e.activeTabId===t,index:i,metadata:e.tabsMetadata?.[t]}}function g(n,t,e){if(n===null)return null;if(n.type==="pane"){if(n.tabs.includes(t)){let i=n.tabsMetadata||{},r=i[t],a=e(r),u={...i};return a===void 0?delete u[t]:u[t]=a,{...n,tabsMetadata:Object.keys(u).length>0?u:void 0}}return n}return n.type==="widget"?n.id===t?{...n,metadata:e(n.metadata)}:n:n.type==="split"?{...n,first:g(n.first,t,e)??n.first,second:g(n.second,t,e)??n.second}:n}function v(n,t,e){if(n===null)return null;if(n.type==="pane"||n.type==="widget"){if(n.id===t){if(e===false){let{locked:i,...r}=n;return r}return {...n,locked:e}}return n}return n.type==="split"?{...n,first:v(n.first,t,e)??n.first,second:v(n.second,t,e)??n.second}:n}function S(n,t,e){return n===null?null:n.type==="pane"?n.id===t?n.activeTabId===e?n:{...n,activeTabId:e}:n:n.type==="split"?{...n,first:S(n.first,t,e)??n.first,second:S(n.second,t,e)??n.second}:n}function O(n,t,e){if(n===null)return null;let r=y(n,t)?.tabsMetadata?.[t],a=m(n,t);if(a===null)return {type:"pane",id:d(),tabs:[t],activeTabId:t,tabsMetadata:r?{[t]:r}:void 0};function u(l){if(l.type==="pane"){if(l.id===e){let s=[...l.tabs];s.includes(t)||s.push(t);let o={...l.tabsMetadata};return r&&(o[t]=r),{...l,tabs:s,activeTabId:t,tabsMetadata:Object.keys(o).length>0?o:void 0}}return l}return l.type==="widget"?l:l.type==="split"?{...l,first:u(l.first),second:u(l.second)}:l}return u(a)}function $(n,t,e,i="before"){if(n===null)return null;let a=y(n,t)?.tabsMetadata?.[t],u=m(n,t);if(u===null)return {type:"pane",id:d(),tabs:[t],activeTabId:t,tabsMetadata:a?{[t]:a}:void 0};function l(s){if(s.type==="pane"){if(s.tabs.includes(e)){let c=[...s.tabs].filter(T=>T!==t),b=c.indexOf(e);b<0&&(b=0),i==="after"&&(b+=1),c.splice(b,0,t);let f={...s.tabsMetadata};return a&&(f[t]=a),{...s,tabs:c,activeTabId:t,tabsMetadata:Object.keys(f).length>0?f:void 0}}return s}return s.type==="widget"?s:s.type==="split"?{...s,first:l(s.first),second:l(s.second)}:s}return l(u)}function N(n,t=0,e=0,i=100,r=100,a="root"){if(n===null)return {panes:[],splitters:[]};if(n.type==="pane"||n.type==="widget")return {panes:[{paneId:n.id,left:t,top:e,width:i,height:r,node:n}],splitters:[]};let{direction:u,splitPercentage:l,first:s,second:o}=n,b={id:`splitter-${a}-${u}`,currentNode:n,direction:u,left:u==="row"?t+i*(l/100):t,top:u==="column"?e+r*(l/100):e,width:u==="row"?0:i,height:u==="column"?0:r,parentLeft:t,parentTop:e,parentWidth:i,parentHeight:r},f={panes:[],splitters:[]},T={panes:[],splitters:[]};if(u==="row"){let p=i*(l/100);f=N(s,t,e,p,r,`${a}-L`),T=N(o,t+p,e,i-p,r,`${a}-R`);}else {let p=r*(l/100);f=N(s,t,e,i,p,`${a}-T`),T=N(o,t,e+p,i,r-p,`${a}-B`);}return {panes:[...f.panes,...T.panes],splitters:[b,...f.splitters,...T.splitters]}}function B(n,t,e,i){if(!(t==="tab"&&e&&n.includes(e))||!i)return -1;let u=n.indexOf(e);return i==="before"?u:u+1}exports.addTab=D;exports.addWidget=C;exports.calculateTabDropIndex=B;exports.computeLayout=N;exports.findPaneById=w;exports.findPaneContainingTab=y;exports.findTabById=k;exports.generateUniqueId=d;exports.insertLeaf=L;exports.mergeTab=O;exports.moveTab=$;exports.removePane=M;exports.removeTab=m;exports.selectTab=S;exports.splitPane=x;exports.updateMetadata=g;exports.updatePaneLock=v;exports.updateSplitPercentage=P;//# sourceMappingURL=utils.cjs.map
2
2
  //# sourceMappingURL=utils.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/shared/lib/tree/tree-helpers.ts"],"names":["generateUniqueId","removePane","tree","paneId","newFirst","newSecond","removeTab","tabId","newTabs","t","newActive","newTabsMetadata","splitPane","targetId","direction","splitType","paneToAdd","addedNode","isFirst","addPane","metadata","insert","node","parentDirection","updateSplitPercentage","target","newPercentage","findPaneById","findPaneContainingTab","findTabById","pane","index","updateTabMetadata","updater","currentTabsMetadata","currentTabMeta","newTabMeta","updatePaneLock","locked","_","rest","selectTab","mergeTab","draggedTabId","targetPaneId","sourceMetadata","cleanTree","moveTab","targetTabId","position","filteredTabs","insertIndex","computeLayout","left","top","width","height","path","splitPercentage","first","second","currentSplitter","firstLayout","secondLayout","firstWidth","firstHeight","calculateTabDropIndex","tabs","activeType","overTabId","overTabPosition"],"mappings":"aAEO,SAASA,GAA2B,CACzC,OAAO,OAAA,CAAU,IAAA,CAAK,QAAO,CAAE,QAAA,CAAS,EAAE,CAAA,CAAE,UAAU,CAAA,CAAG,EAAE,CAC7D,CAKO,SAASC,CAAAA,CAAWC,CAAAA,CAAuBC,CAAAA,CAAiC,CACjF,GAAID,CAAAA,GAAS,IAAA,CAAM,OAAO,IAAA,CAC1B,GAAIA,CAAAA,CAAK,IAAA,GAAS,MAAA,CAChB,OAAIA,EAAK,EAAA,GAAOC,CAAAA,CAAe,IAAA,CACxBD,CAAAA,CAET,IAAME,CAAAA,CAAWH,CAAAA,CAAWC,CAAAA,CAAK,KAAA,CAAOC,CAAM,CAAA,CACxCE,CAAAA,CAAYJ,CAAAA,CAAWC,CAAAA,CAAK,OAAQC,CAAM,CAAA,CAChD,OAAIC,CAAAA,GAAa,KAAaC,CAAAA,CAC1BA,CAAAA,GAAc,IAAA,CAAaD,CAAAA,CACxB,CAAE,GAAGF,CAAAA,CAAM,KAAA,CAAOE,CAAAA,CAAU,OAAQC,CAAU,CACvD,CAKO,SAASC,EAAUJ,CAAAA,CAAuBK,CAAAA,CAAgC,CAC/E,GAAIL,IAAS,IAAA,CAAM,OAAO,IAAA,CAC1B,GAAIA,EAAK,IAAA,GAAS,MAAA,CAAQ,CACxB,GAAIA,EAAK,IAAA,CAAK,QAAA,CAASK,CAAK,CAAA,CAAG,CAC7B,IAAMC,CAAAA,CAAUN,CAAAA,CAAK,IAAA,CAAK,OAAQO,CAAAA,EAAMA,CAAAA,GAAMF,CAAK,CAAA,CACnD,GAAIC,CAAAA,CAAQ,MAAA,GAAW,CAAA,CAAG,OAAO,KACjC,IAAIE,CAAAA,CAAYR,CAAAA,CAAK,WAAA,CACjBA,EAAK,WAAA,GAAgBK,CAAAA,GACvBG,CAAAA,CAAYF,CAAAA,CAAQ,CAAC,CAAA,CAAA,CAEvB,IAAMG,CAAAA,CAAkB,CAAE,GAAGT,CAAAA,CAAK,YAAa,CAAA,CAC/C,OAAA,OAAOS,EAAgBJ,CAAK,CAAA,CACrB,CACL,GAAGL,EACH,IAAA,CAAMM,CAAAA,CACN,WAAA,CAAaE,CAAAA,CACb,aAAc,MAAA,CAAO,IAAA,CAAKC,CAAe,CAAA,CAAE,OAAS,CAAA,CAAIA,CAAAA,CAAkB,MAC5E,CACF,CACA,OAAOT,CACT,CACA,IAAME,EAAWE,CAAAA,CAAUJ,CAAAA,CAAK,KAAA,CAAOK,CAAK,EACtCF,CAAAA,CAAYC,CAAAA,CAAUJ,CAAAA,CAAK,MAAA,CAAQK,CAAK,CAAA,CAC9C,OAAIH,CAAAA,GAAa,IAAA,CAAaC,EAC1BA,CAAAA,GAAc,IAAA,CAAaD,CAAAA,CACxB,CAAE,GAAGF,CAAAA,CAAM,KAAA,CAAOE,CAAAA,CAAU,MAAA,CAAQC,CAAU,CACvD,CAKO,SAASO,CAAAA,CACdV,EACAW,CAAAA,CACAC,CAAAA,CACAC,CAAAA,CACAC,CAAAA,CACiB,CACjB,GAAId,CAAAA,GAAS,IAAA,CACX,OAAI,OAAOc,CAAAA,EAAc,QAAA,CAChB,CAAE,IAAA,CAAM,OAAQ,EAAA,CAAIhB,CAAAA,EAAiB,CAAG,IAAA,CAAM,CAACgB,CAAS,CAAA,CAAG,WAAA,CAAaA,CAAU,EAEpFA,CAAAA,CAET,GAAId,CAAAA,CAAK,IAAA,GAAS,OAAQ,CACxB,GAAIA,CAAAA,CAAK,EAAA,GAAOW,EAAU,CACxB,IAAMI,CAAAA,CACJ,OAAOD,GAAc,QAAA,CACjB,CAAE,IAAA,CAAM,MAAA,CAAQ,GAAIhB,CAAAA,EAAiB,CAAG,IAAA,CAAM,CAACgB,CAAS,CAAA,CAAG,WAAA,CAAaA,CAAU,CAAA,CAClFA,EACAE,CAAAA,CAAUH,CAAAA,GAAc,MAAA,EAAUA,CAAAA,GAAc,MACtD,OAAO,CACL,IAAA,CAAM,OAAA,CACN,UAAAD,CAAAA,CACA,KAAA,CAAOI,CAAAA,CAAUD,CAAAA,CAAYf,EAC7B,MAAA,CAAQgB,CAAAA,CAAUhB,CAAAA,CAAOe,CAAAA,CACzB,gBAAiB,EACnB,CACF,CACA,OAAOf,CACT,CACA,OAAO,CACL,GAAGA,EACH,KAAA,CAAOU,CAAAA,CAAUV,CAAAA,CAAK,KAAA,CAAOW,EAAUC,CAAAA,CAAWC,CAAAA,CAAWC,CAAS,CAAA,EAAKd,EAAK,KAAA,CAChF,MAAA,CAAQU,CAAAA,CAAUV,CAAAA,CAAK,OAAQW,CAAAA,CAAUC,CAAAA,CAAWC,CAAAA,CAAWC,CAAS,GAAKd,CAAAA,CAAK,MACpF,CACF,CAKO,SAASiB,CAAAA,CACdjB,CAAAA,CACAc,CAAAA,CACAI,CAAAA,CACU,CACV,GAAIlB,CAAAA,GAAS,IAAA,CACX,OAAO,CACL,IAAA,CAAM,MAAA,CACN,EAAA,CAAIF,CAAAA,GACJ,IAAA,CAAM,CAACgB,CAAS,CAAA,CAChB,YAAaA,CAAAA,CACb,YAAA,CAAcI,CAAAA,CAAW,CAAE,CAACJ,CAAS,EAAGI,CAAS,CAAA,CAAI,MACvD,EAGF,SAASC,CAAAA,CAAOC,CAAAA,CAAgBC,CAAAA,CAAkD,CAChF,OAAID,CAAAA,CAAK,IAAA,GAAS,MAAA,CAET,CACL,IAAA,CAAM,OAAA,CACN,SAAA,CAHgCC,CAAAA,GAAoB,MAAQ,QAAA,CAAW,KAAA,CAIvE,eAAA,CAAiB,EAAA,CACjB,MAAOD,CAAAA,CACP,MAAA,CAAQ,CACN,IAAA,CAAM,OACN,EAAA,CAAItB,CAAAA,EAAiB,CACrB,IAAA,CAAM,CAACgB,CAAS,CAAA,CAChB,WAAA,CAAaA,CAAAA,CACb,aAAcI,CAAAA,CAAW,CAAE,CAACJ,CAAS,EAAGI,CAAS,CAAA,CAAI,MACvD,CACF,EAGK,CACL,GAAGE,CAAAA,CACH,MAAA,CAAQD,EAAOC,CAAAA,CAAK,MAAA,CAAQA,CAAAA,CAAK,SAAS,CAC5C,CACF,CAEA,OAAOD,CAAAA,CAAOnB,EAAM,IAAI,CAC1B,CAKO,SAASsB,EACdtB,CAAAA,CACAuB,CAAAA,CACAC,CAAAA,CACiB,CACjB,OAAIxB,CAAAA,GAAS,IAAA,CAAa,IAAA,CACtBA,CAAAA,GAASuB,EACJ,CAAE,GAAGvB,CAAAA,CAAM,eAAA,CAAiBwB,CAAc,CAAA,CAE/CxB,CAAAA,CAAK,IAAA,GAAS,OAAA,CACT,CACL,GAAGA,CAAAA,CACH,KAAA,CAAOsB,CAAAA,CAAsBtB,EAAK,KAAA,CAAOuB,CAAAA,CAAQC,CAAa,CAAA,EAAKxB,EAAK,KAAA,CACxE,MAAA,CAAQsB,CAAAA,CAAsBtB,CAAAA,CAAK,OAAQuB,CAAAA,CAAQC,CAAa,CAAA,EAAKxB,CAAAA,CAAK,MAC5E,CAAA,CAEKA,CACT,CAKO,SAASyB,EAAazB,CAAAA,CAAuBC,CAAAA,CAAiC,CACnF,OAAID,IAAS,IAAA,CAAa,IAAA,CACtBA,CAAAA,CAAK,IAAA,GAAS,OACTA,CAAAA,CAAK,EAAA,GAAOC,CAAAA,CAASD,CAAAA,CAAO,KAE9ByB,CAAAA,CAAazB,CAAAA,CAAK,KAAA,CAAOC,CAAM,GAAKwB,CAAAA,CAAazB,CAAAA,CAAK,MAAA,CAAQC,CAAM,CAC7E,CAKO,SAASyB,CAAAA,CAAsB1B,CAAAA,CAAuBK,EAAgC,CAC3F,OAAIL,CAAAA,GAAS,IAAA,CAAa,KACtBA,CAAAA,CAAK,IAAA,GAAS,MAAA,CACTA,CAAAA,CAAK,KAAK,QAAA,CAASK,CAAK,CAAA,CAAIL,CAAAA,CAAO,KAErC0B,CAAAA,CAAsB1B,CAAAA,CAAK,KAAA,CAAOK,CAAK,GAAKqB,CAAAA,CAAsB1B,CAAAA,CAAK,MAAA,CAAQK,CAAK,CAC7F,CAKO,SAASsB,CAAAA,CAAY3B,CAAAA,CAAuBK,EAAkC,CACnF,IAAMuB,CAAAA,CAAOF,CAAAA,CAAsB1B,EAAMK,CAAK,CAAA,CAC9C,GAAI,CAACuB,EAAM,OAAO,IAAA,CAClB,IAAMC,CAAAA,CAAQD,EAAK,IAAA,CAAK,OAAA,CAAQvB,CAAK,CAAA,CACrC,OAAO,CACL,EAAA,CAAIA,CAAAA,CACJ,MAAA,CAAQuB,EAAK,EAAA,CACb,QAAA,CAAUA,CAAAA,CAAK,WAAA,GAAgBvB,EAC/B,KAAA,CAAAwB,CAAAA,CACA,QAAA,CAAUD,CAAAA,CAAK,eAAevB,CAAK,CACrC,CACF,CAKO,SAASyB,CAAAA,CACd9B,CAAAA,CACAK,CAAAA,CACA0B,CAAAA,CACiB,CACjB,GAAI/B,CAAAA,GAAS,IAAA,CAAM,OAAO,KAC1B,GAAIA,CAAAA,CAAK,IAAA,GAAS,MAAA,CAAQ,CACxB,GAAIA,CAAAA,CAAK,IAAA,CAAK,QAAA,CAASK,CAAK,CAAA,CAAG,CAC7B,IAAM2B,CAAAA,CAAsBhC,EAAK,YAAA,EAAgB,EAAC,CAC5CiC,CAAAA,CAAiBD,EAAoB3B,CAAK,CAAA,CAC1C6B,CAAAA,CAAaH,CAAAA,CAAQE,CAAc,CAAA,CAEnCxB,CAAAA,CAAkB,CAAE,GAAGuB,CAAoB,CAAA,CACjD,OAAIE,CAAAA,GAAe,MAAA,CACjB,OAAOzB,CAAAA,CAAgBJ,CAAK,CAAA,CAE5BI,CAAAA,CAAgBJ,CAAK,CAAA,CAAI6B,CAAAA,CAGpB,CACL,GAAGlC,EACH,YAAA,CAAc,MAAA,CAAO,IAAA,CAAKS,CAAe,EAAE,MAAA,CAAS,CAAA,CAAIA,CAAAA,CAAkB,MAC5E,CACF,CACA,OAAOT,CACT,CACA,OAAO,CACL,GAAGA,CAAAA,CACH,KAAA,CAAO8B,EAAkB9B,CAAAA,CAAK,KAAA,CAAOK,CAAAA,CAAO0B,CAAO,GAAK/B,CAAAA,CAAK,KAAA,CAC7D,MAAA,CAAQ8B,CAAAA,CAAkB9B,EAAK,MAAA,CAAQK,CAAAA,CAAO0B,CAAO,CAAA,EAAK/B,EAAK,MACjE,CACF,CA4CO,SAASmC,EACdnC,CAAAA,CACAC,CAAAA,CACAmC,CAAAA,CACiB,CACjB,GAAIpC,CAAAA,GAAS,IAAA,CAAM,OAAO,IAAA,CAC1B,GAAIA,CAAAA,CAAK,IAAA,GAAS,OAAQ,CACxB,GAAIA,EAAK,EAAA,GAAOC,CAAAA,CAAQ,CACtB,GAAImC,IAAW,KAAA,CAAO,CACpB,GAAM,CAAE,OAAQC,CAAAA,CAAG,GAAGC,CAAK,CAAA,CAAItC,EAC/B,OAAOsC,CACT,CACA,OAAO,CAAE,GAAGtC,CAAAA,CAAM,MAAA,CAAAoC,CAAO,CAC3B,CACA,OAAOpC,CACT,CACA,OAAO,CACL,GAAGA,CAAAA,CACH,KAAA,CAAOmC,EAAenC,CAAAA,CAAK,KAAA,CAAOC,CAAAA,CAAQmC,CAAM,GAAKpC,CAAAA,CAAK,KAAA,CAC1D,MAAA,CAAQmC,CAAAA,CAAenC,EAAK,MAAA,CAAQC,CAAAA,CAAQmC,CAAM,CAAA,EAAKpC,EAAK,MAC9D,CACF,CAKO,SAASuC,EAAUvC,CAAAA,CAAuBC,CAAAA,CAAgBI,CAAAA,CAAgC,CAC/F,OAAIL,CAAAA,GAAS,IAAA,CAAa,IAAA,CACtBA,CAAAA,CAAK,OAAS,MAAA,CACZA,CAAAA,CAAK,EAAA,GAAOC,CAAAA,CACVD,EAAK,WAAA,GAAgBK,CAAAA,CAAcL,CAAAA,CAChC,CAAE,GAAGA,CAAAA,CAAM,WAAA,CAAaK,CAAM,CAAA,CAEhCL,EAEF,CACL,GAAGA,CAAAA,CACH,KAAA,CAAOuC,EAAUvC,CAAAA,CAAK,KAAA,CAAOC,CAAAA,CAAQI,CAAK,GAAKL,CAAAA,CAAK,KAAA,CACpD,MAAA,CAAQuC,CAAAA,CAAUvC,EAAK,MAAA,CAAQC,CAAAA,CAAQI,CAAK,CAAA,EAAKL,EAAK,MACxD,CACF,CAKO,SAASwC,EACdxC,CAAAA,CACAyC,CAAAA,CACAC,CAAAA,CACiB,CACjB,GAAI1C,CAAAA,GAAS,IAAA,CAAM,OAAO,IAAA,CAG1B,IAAM2C,CAAAA,CADajB,CAAAA,CAAsB1B,CAAAA,CAAMyC,CAAY,GACxB,YAAA,GAAeA,CAAY,CAAA,CAExDG,CAAAA,CAAYxC,EAAUJ,CAAAA,CAAMyC,CAAY,CAAA,CAC9C,GAAIG,IAAc,IAAA,CAChB,OAAO,CACL,IAAA,CAAM,OACN,EAAA,CAAI9C,CAAAA,EAAiB,CACrB,IAAA,CAAM,CAAC2C,CAAY,CAAA,CACnB,WAAA,CAAaA,CAAAA,CACb,aAAcE,CAAAA,CAAiB,CAAE,CAACF,CAAY,EAAGE,CAAe,CAAA,CAAI,MACtE,CAAA,CAGF,SAASxB,CAAAA,CAAOC,CAAAA,CAA0B,CACxC,GAAIA,EAAK,IAAA,GAAS,MAAA,CAAQ,CACxB,GAAIA,EAAK,EAAA,GAAOsB,CAAAA,CAAc,CAC5B,IAAMpC,EAAU,CAAC,GAAGc,CAAAA,CAAK,IAAI,EACxBd,CAAAA,CAAQ,QAAA,CAASmC,CAAY,CAAA,EAChCnC,EAAQ,IAAA,CAAKmC,CAAY,CAAA,CAE3B,IAAMhC,EAAkB,CAAE,GAAGW,CAAAA,CAAK,YAAa,EAC/C,OAAIuB,CAAAA,GACFlC,CAAAA,CAAgBgC,CAAY,EAAIE,CAAAA,CAAAA,CAE3B,CACL,GAAGvB,CAAAA,CACH,KAAMd,CAAAA,CACN,WAAA,CAAamC,CAAAA,CACb,YAAA,CAAc,OAAO,IAAA,CAAKhC,CAAe,CAAA,CAAE,MAAA,CAAS,EAAIA,CAAAA,CAAkB,MAC5E,CACF,CACA,OAAOW,CACT,CACA,OAAO,CACL,GAAGA,CAAAA,CACH,KAAA,CAAOD,CAAAA,CAAOC,CAAAA,CAAK,KAAK,CAAA,CACxB,MAAA,CAAQD,CAAAA,CAAOC,CAAAA,CAAK,MAAM,CAC5B,CACF,CAEA,OAAOD,EAAOyB,CAAS,CACzB,CAKO,SAASC,EACd7C,CAAAA,CACAyC,CAAAA,CACAK,CAAAA,CACAC,CAAAA,CAA+B,SACd,CACjB,GAAI/C,CAAAA,GAAS,IAAA,CAAM,OAAO,IAAA,CAG1B,IAAM2C,CAAAA,CADajB,CAAAA,CAAsB1B,EAAMyC,CAAY,CAAA,EACxB,YAAA,GAAeA,CAAY,EAExDG,CAAAA,CAAYxC,CAAAA,CAAUJ,CAAAA,CAAMyC,CAAY,EAC9C,GAAIG,CAAAA,GAAc,IAAA,CAChB,OAAO,CACL,IAAA,CAAM,MAAA,CACN,EAAA,CAAI9C,CAAAA,GACJ,IAAA,CAAM,CAAC2C,CAAY,CAAA,CACnB,YAAaA,CAAAA,CACb,YAAA,CAAcE,CAAAA,CAAiB,CAAE,CAACF,CAAY,EAAGE,CAAe,CAAA,CAAI,MACtE,CAAA,CAGF,SAASxB,CAAAA,CAAOC,CAAAA,CAA0B,CACxC,GAAIA,CAAAA,CAAK,IAAA,GAAS,MAAA,CAAQ,CACxB,GAAIA,CAAAA,CAAK,IAAA,CAAK,QAAA,CAAS0B,CAAW,CAAA,CAAG,CAEnC,IAAME,CAAAA,CADU,CAAC,GAAG5B,CAAAA,CAAK,IAAI,CAAA,CACA,OAAQb,CAAAA,EAAMA,CAAAA,GAAMkC,CAAY,CAAA,CACzDQ,CAAAA,CAAcD,EAAa,OAAA,CAAQF,CAAW,CAAA,CAC9CG,CAAAA,CAAc,IAChBA,CAAAA,CAAc,CAAA,CAAA,CAEZF,CAAAA,GAAa,OAAA,GACfE,GAAe,CAAA,CAAA,CAEjBD,CAAAA,CAAa,MAAA,CAAOC,CAAAA,CAAa,EAAGR,CAAY,CAAA,CAEhD,IAAMhC,CAAAA,CAAkB,CAAE,GAAGW,CAAAA,CAAK,YAAa,CAAA,CAC/C,OAAIuB,CAAAA,GACFlC,CAAAA,CAAgBgC,CAAY,CAAA,CAAIE,GAE3B,CACL,GAAGvB,CAAAA,CACH,IAAA,CAAM4B,EACN,WAAA,CAAaP,CAAAA,CACb,YAAA,CAAc,MAAA,CAAO,KAAKhC,CAAe,CAAA,CAAE,MAAA,CAAS,CAAA,CAAIA,EAAkB,MAC5E,CACF,CACA,OAAOW,CACT,CACA,OAAO,CACL,GAAGA,EACH,KAAA,CAAOD,CAAAA,CAAOC,CAAAA,CAAK,KAAK,EACxB,MAAA,CAAQD,CAAAA,CAAOC,CAAAA,CAAK,MAAM,CAC5B,CACF,CAEA,OAAOD,CAAAA,CAAOyB,CAAS,CACzB,CAyBO,SAASM,CAAAA,CACd9B,EACA+B,CAAAA,CAAO,CAAA,CACPC,CAAAA,CAAM,CAAA,CACNC,EAAQ,GAAA,CACRC,CAAAA,CAAS,GAAA,CACTC,CAAAA,CAAO,OACmD,CAC1D,GAAInC,CAAAA,GAAS,IAAA,CAAM,OAAO,CAAE,KAAA,CAAO,EAAC,CAAG,UAAW,EAAG,CAAA,CACrD,GAAIA,EAAK,IAAA,GAAS,MAAA,CAChB,OAAO,CACL,MAAO,CAAC,CAAE,MAAA,CAAQA,CAAAA,CAAK,GAAI,IAAA,CAAA+B,CAAAA,CAAM,GAAA,CAAAC,CAAAA,CAAK,MAAAC,CAAAA,CAAO,MAAA,CAAAC,CAAAA,CAAQ,IAAA,CAAAlC,CAAK,CAAC,CAAA,CAC3D,SAAA,CAAW,EACb,CAAA,CAGF,GAAM,CAAE,SAAA,CAAAR,EAAW,eAAA,CAAA4C,CAAAA,CAAiB,KAAA,CAAAC,CAAAA,CAAO,OAAAC,CAAO,CAAA,CAAItC,CAAAA,CAGhDuC,CAAAA,CAAoC,CACxC,EAAA,CAHiB,CAAA,SAAA,EAAYJ,CAAI,CAAA,CAAA,EAAI3C,CAAS,CAAA,CAAA,CAI9C,WAAA,CAAaQ,CAAAA,CACb,SAAA,CAAAR,EACA,IAAA,CAAMA,CAAAA,GAAc,KAAA,CAAQuC,CAAAA,CAAOE,GAASG,CAAAA,CAAkB,GAAA,CAAA,CAAOL,EACrE,GAAA,CAAKvC,CAAAA,GAAc,SAAWwC,CAAAA,CAAME,CAAAA,EAAUE,CAAAA,CAAkB,GAAA,CAAA,CAAOJ,EACvE,KAAA,CAAOxC,CAAAA,GAAc,KAAA,CAAQ,CAAA,CAAIyC,EACjC,MAAA,CAAQzC,CAAAA,GAAc,QAAA,CAAW,CAAA,CAAI0C,EACrC,UAAA,CAAYH,CAAAA,CACZ,SAAA,CAAWC,CAAAA,CACX,YAAaC,CAAAA,CACb,YAAA,CAAcC,CAChB,CAAA,CAEIM,EAAc,CAAE,KAAA,CAAO,EAAC,CAAqB,UAAW,EAAyB,CAAA,CACjFC,CAAAA,CAAe,CAAE,KAAA,CAAO,EAAC,CAAqB,SAAA,CAAW,EAAyB,CAAA,CAEtF,GAAIjD,CAAAA,GAAc,MAAO,CACvB,IAAMkD,CAAAA,CAAaT,CAAAA,EAASG,EAAkB,GAAA,CAAA,CAC9CI,CAAAA,CAAcV,CAAAA,CAAcO,CAAAA,CAAON,EAAMC,CAAAA,CAAKU,CAAAA,CAAYR,CAAAA,CAAQ,CAAA,EAAGC,CAAI,CAAA,EAAA,CAAI,CAAA,CAC7EM,CAAAA,CAAeX,CAAAA,CACbQ,EACAP,CAAAA,CAAOW,CAAAA,CACPV,CAAAA,CACAC,CAAAA,CAAQS,EACRR,CAAAA,CACA,CAAA,EAAGC,CAAI,CAAA,EAAA,CACT,EACF,CAAA,KAAO,CACL,IAAMQ,CAAAA,CAAcT,GAAUE,CAAAA,CAAkB,GAAA,CAAA,CAChDI,CAAAA,CAAcV,CAAAA,CAAcO,EAAON,CAAAA,CAAMC,CAAAA,CAAKC,CAAAA,CAAOU,CAAAA,CAAa,GAAGR,CAAI,CAAA,EAAA,CAAI,CAAA,CAC7EM,CAAAA,CAAeX,EACbQ,CAAAA,CACAP,CAAAA,CACAC,CAAAA,CAAMW,CAAAA,CACNV,EACAC,CAAAA,CAASS,CAAAA,CACT,CAAA,EAAGR,CAAI,IACT,EACF,CAEA,OAAO,CACL,MAAO,CAAC,GAAGK,CAAAA,CAAY,KAAA,CAAO,GAAGC,CAAAA,CAAa,KAAK,CAAA,CACnD,SAAA,CAAW,CAACF,CAAAA,CAAiB,GAAGC,CAAAA,CAAY,SAAA,CAAW,GAAGC,CAAAA,CAAa,SAAS,CAClF,CACF,CAMO,SAASG,CAAAA,CACdC,CAAAA,CACAC,CAAAA,CACAC,EACAC,CAAAA,CACQ,CAGR,GAAI,EAFkBF,IAAe,KAAA,EACWC,CAAAA,EAAaF,CAAAA,CAAK,QAAA,CAASE,CAAS,CAAA,CAAA,EACrD,CAACC,CAAAA,CAC9B,OAAO,IAET,IAAMvC,CAAAA,CAAQoC,CAAAA,CAAK,OAAA,CAAQE,CAAS,CAAA,CACpC,OAAOC,IAAoB,QAAA,CAAWvC,CAAAA,CAAQA,EAAQ,CACxD","file":"utils.cjs","sourcesContent":["import { TreeNode, SplitNode, SplitDirection, PaneNode, TabDetails } from '../../model'\n\nexport function generateUniqueId(): string {\n return 'pane-' + Math.random().toString(36).substring(2, 11)\n}\n\n/**\n * Tree Helper: Remove a pane container and consolidate the tree structure.\n */\nexport function removePane(tree: TreeNode | null, paneId: string): TreeNode | null {\n if (tree === null) return null\n if (tree.type === 'pane') {\n if (tree.id === paneId) return null\n return tree\n }\n const newFirst = removePane(tree.first, paneId)\n const newSecond = removePane(tree.second, paneId)\n if (newFirst === null) return newSecond\n if (newSecond === null) return newFirst\n return { ...tree, first: newFirst, second: newSecond }\n}\n\n/**\n * Tree Helper: Remove a tab from a pane and consolidate the tree structure if no tabs remain.\n */\nexport function removeTab(tree: TreeNode | null, tabId: string): TreeNode | null {\n if (tree === null) return null\n if (tree.type === 'pane') {\n if (tree.tabs.includes(tabId)) {\n const newTabs = tree.tabs.filter((t) => t !== tabId)\n if (newTabs.length === 0) return null\n let newActive = tree.activeTabId\n if (tree.activeTabId === tabId) {\n newActive = newTabs[0]\n }\n const newTabsMetadata = { ...tree.tabsMetadata }\n delete newTabsMetadata[tabId]\n return {\n ...tree,\n tabs: newTabs,\n activeTabId: newActive,\n tabsMetadata: Object.keys(newTabsMetadata).length > 0 ? newTabsMetadata : undefined,\n }\n }\n return tree\n }\n const newFirst = removeTab(tree.first, tabId)\n const newSecond = removeTab(tree.second, tabId)\n if (newFirst === null) return newSecond\n if (newSecond === null) return newFirst\n return { ...tree, first: newFirst, second: newSecond }\n}\n\n/**\n * Tree Helper: Insert a pane by splitting an existing target node.\n */\nexport function splitPane(\n tree: TreeNode | null,\n targetId: string,\n direction: SplitDirection,\n splitType: 'left' | 'right' | 'top' | 'bottom',\n paneToAdd: string | PaneNode,\n): TreeNode | null {\n if (tree === null) {\n if (typeof paneToAdd === 'string') {\n return { type: 'pane', id: generateUniqueId(), tabs: [paneToAdd], activeTabId: paneToAdd }\n }\n return paneToAdd\n }\n if (tree.type === 'pane') {\n if (tree.id === targetId) {\n const addedNode: PaneNode =\n typeof paneToAdd === 'string'\n ? { type: 'pane', id: generateUniqueId(), tabs: [paneToAdd], activeTabId: paneToAdd }\n : paneToAdd\n const isFirst = splitType === 'left' || splitType === 'top'\n return {\n type: 'split',\n direction,\n first: isFirst ? addedNode : tree,\n second: isFirst ? tree : addedNode,\n splitPercentage: 50,\n }\n }\n return tree\n }\n return {\n ...tree,\n first: splitPane(tree.first, targetId, direction, splitType, paneToAdd) || tree.first,\n second: splitPane(tree.second, targetId, direction, splitType, paneToAdd) || tree.second,\n }\n}\n\n/**\n * Tree Helper: Add a pane by recursively splitting the rightmost/bottommost pane in the tree.\n */\nexport function addPane(\n tree: TreeNode | null,\n paneToAdd: string,\n metadata?: Record<string, unknown>,\n): TreeNode {\n if (tree === null) {\n return {\n type: 'pane',\n id: generateUniqueId(),\n tabs: [paneToAdd],\n activeTabId: paneToAdd,\n tabsMetadata: metadata ? { [paneToAdd]: metadata } : undefined,\n }\n }\n\n function insert(node: TreeNode, parentDirection: SplitDirection | null): TreeNode {\n if (node.type === 'pane') {\n const direction: SplitDirection = parentDirection === 'row' ? 'column' : 'row'\n return {\n type: 'split',\n direction,\n splitPercentage: 50,\n first: node,\n second: {\n type: 'pane',\n id: generateUniqueId(),\n tabs: [paneToAdd],\n activeTabId: paneToAdd,\n tabsMetadata: metadata ? { [paneToAdd]: metadata } : undefined,\n },\n }\n }\n\n return {\n ...node,\n second: insert(node.second, node.direction),\n }\n }\n\n return insert(tree, null)\n}\n\n/**\n * Tree Helper: Update split percentage recursively.\n */\nexport function updateSplitPercentage(\n tree: TreeNode | null,\n target: SplitNode,\n newPercentage: number,\n): TreeNode | null {\n if (tree === null) return null\n if (tree === target) {\n return { ...tree, splitPercentage: newPercentage } as SplitNode\n }\n if (tree.type === 'split') {\n return {\n ...tree,\n first: updateSplitPercentage(tree.first, target, newPercentage) || tree.first,\n second: updateSplitPercentage(tree.second, target, newPercentage) || tree.second,\n }\n }\n return tree\n}\n\n/**\n * Find a PaneNode by its ID.\n */\nexport function findPaneById(tree: TreeNode | null, paneId: string): PaneNode | null {\n if (tree === null) return null\n if (tree.type === 'pane') {\n return tree.id === paneId ? tree : null\n }\n return findPaneById(tree.first, paneId) ?? findPaneById(tree.second, paneId)\n}\n\n/**\n * Find a PaneNode containing the given tab ID.\n */\nexport function findPaneContainingTab(tree: TreeNode | null, tabId: string): PaneNode | null {\n if (tree === null) return null\n if (tree.type === 'pane') {\n return tree.tabs.includes(tabId) ? tree : null\n }\n return findPaneContainingTab(tree.first, tabId) ?? findPaneContainingTab(tree.second, tabId)\n}\n\n/**\n * Find the details of a tab by its ID.\n */\nexport function findTabById(tree: TreeNode | null, tabId: string): TabDetails | null {\n const pane = findPaneContainingTab(tree, tabId)\n if (!pane) return null\n const index = pane.tabs.indexOf(tabId)\n return {\n id: tabId,\n paneId: pane.id,\n isActive: pane.activeTabId === tabId,\n index,\n metadata: pane.tabsMetadata?.[tabId],\n }\n}\n\n/**\n * Update metadata on a specific tab node using an updater function.\n */\nexport function updateTabMetadata(\n tree: TreeNode | null,\n tabId: string,\n updater: (current: Record<string, unknown> | undefined) => Record<string, unknown> | undefined,\n): TreeNode | null {\n if (tree === null) return null\n if (tree.type === 'pane') {\n if (tree.tabs.includes(tabId)) {\n const currentTabsMetadata = tree.tabsMetadata || {}\n const currentTabMeta = currentTabsMetadata[tabId]\n const newTabMeta = updater(currentTabMeta)\n\n const newTabsMetadata = { ...currentTabsMetadata }\n if (newTabMeta === undefined) {\n delete newTabsMetadata[tabId]\n } else {\n newTabsMetadata[tabId] = newTabMeta\n }\n\n return {\n ...tree,\n tabsMetadata: Object.keys(newTabsMetadata).length > 0 ? newTabsMetadata : undefined,\n }\n }\n return tree\n }\n return {\n ...tree,\n first: updateTabMetadata(tree.first, tabId, updater) ?? tree.first,\n second: updateTabMetadata(tree.second, tabId, updater) ?? tree.second,\n }\n}\n\n/**\n * Tree Helper: Add a tab directly to a specific target pane node.\n */\nexport function addTab(\n tree: TreeNode | null,\n targetPaneId: string,\n tabId: string,\n metadata?: Record<string, unknown>,\n): TreeNode | null {\n if (tree === null) return null\n if (tree.type === 'pane') {\n if (tree.id === targetPaneId) {\n const newTabs = [...tree.tabs]\n if (!newTabs.includes(tabId)) {\n newTabs.push(tabId)\n }\n let newTabsMetadata = tree.tabsMetadata\n if (metadata) {\n newTabsMetadata = {\n ...tree.tabsMetadata,\n [tabId]: metadata,\n }\n }\n return {\n ...tree,\n tabs: newTabs,\n activeTabId: tabId,\n tabsMetadata: newTabsMetadata,\n }\n }\n return tree\n }\n return {\n ...tree,\n first: addTab(tree.first, targetPaneId, tabId, metadata) || tree.first,\n second: addTab(tree.second, targetPaneId, tabId, metadata) || tree.second,\n }\n}\n\n/**\n * Update the locked status on a specific pane node in the layout tree.\n */\nexport function updatePaneLock(\n tree: TreeNode | null,\n paneId: string,\n locked: boolean,\n): TreeNode | null {\n if (tree === null) return null\n if (tree.type === 'pane') {\n if (tree.id === paneId) {\n if (locked === false) {\n const { locked: _, ...rest } = tree\n return rest as PaneNode\n }\n return { ...tree, locked }\n }\n return tree\n }\n return {\n ...tree,\n first: updatePaneLock(tree.first, paneId, locked) ?? tree.first,\n second: updatePaneLock(tree.second, paneId, locked) ?? tree.second,\n }\n}\n\n/**\n * Tree Helper: Activate a tab within a pane.\n */\nexport function selectTab(tree: TreeNode | null, paneId: string, tabId: string): TreeNode | null {\n if (tree === null) return null\n if (tree.type === 'pane') {\n if (tree.id === paneId) {\n if (tree.activeTabId === tabId) return tree\n return { ...tree, activeTabId: tabId }\n }\n return tree\n }\n return {\n ...tree,\n first: selectTab(tree.first, paneId, tabId) ?? tree.first,\n second: selectTab(tree.second, paneId, tabId) ?? tree.second,\n }\n}\n\n/**\n * Tree Helper: Merge a tab into a target pane node.\n */\nexport function mergeTab(\n tree: TreeNode | null,\n draggedTabId: string,\n targetPaneId: string,\n): TreeNode | null {\n if (tree === null) return null\n\n const sourcePane = findPaneContainingTab(tree, draggedTabId)\n const sourceMetadata = sourcePane?.tabsMetadata?.[draggedTabId]\n\n const cleanTree = removeTab(tree, draggedTabId)\n if (cleanTree === null) {\n return {\n type: 'pane',\n id: generateUniqueId(),\n tabs: [draggedTabId],\n activeTabId: draggedTabId,\n tabsMetadata: sourceMetadata ? { [draggedTabId]: sourceMetadata } : undefined,\n }\n }\n\n function insert(node: TreeNode): TreeNode {\n if (node.type === 'pane') {\n if (node.id === targetPaneId) {\n const newTabs = [...node.tabs]\n if (!newTabs.includes(draggedTabId)) {\n newTabs.push(draggedTabId)\n }\n const newTabsMetadata = { ...node.tabsMetadata }\n if (sourceMetadata) {\n newTabsMetadata[draggedTabId] = sourceMetadata\n }\n return {\n ...node,\n tabs: newTabs,\n activeTabId: draggedTabId,\n tabsMetadata: Object.keys(newTabsMetadata).length > 0 ? newTabsMetadata : undefined,\n }\n }\n return node\n }\n return {\n ...node,\n first: insert(node.first),\n second: insert(node.second),\n }\n }\n\n return insert(cleanTree)\n}\n\n/**\n * Tree Helper: Move/reorder a tab inside or to a target pane next to a target tab.\n */\nexport function moveTab(\n tree: TreeNode | null,\n draggedTabId: string,\n targetTabId: string,\n position: 'before' | 'after' = 'before',\n): TreeNode | null {\n if (tree === null) return null\n\n const sourcePane = findPaneContainingTab(tree, draggedTabId)\n const sourceMetadata = sourcePane?.tabsMetadata?.[draggedTabId]\n\n const cleanTree = removeTab(tree, draggedTabId)\n if (cleanTree === null) {\n return {\n type: 'pane',\n id: generateUniqueId(),\n tabs: [draggedTabId],\n activeTabId: draggedTabId,\n tabsMetadata: sourceMetadata ? { [draggedTabId]: sourceMetadata } : undefined,\n }\n }\n\n function insert(node: TreeNode): TreeNode {\n if (node.type === 'pane') {\n if (node.tabs.includes(targetTabId)) {\n const newTabs = [...node.tabs]\n const filteredTabs = newTabs.filter((t) => t !== draggedTabId)\n let insertIndex = filteredTabs.indexOf(targetTabId)\n if (insertIndex < 0) {\n insertIndex = 0\n }\n if (position === 'after') {\n insertIndex += 1\n }\n filteredTabs.splice(insertIndex, 0, draggedTabId)\n\n const newTabsMetadata = { ...node.tabsMetadata }\n if (sourceMetadata) {\n newTabsMetadata[draggedTabId] = sourceMetadata\n }\n return {\n ...node,\n tabs: filteredTabs,\n activeTabId: draggedTabId,\n tabsMetadata: Object.keys(newTabsMetadata).length > 0 ? newTabsMetadata : undefined,\n }\n }\n return node\n }\n return {\n ...node,\n first: insert(node.first),\n second: insert(node.second),\n }\n }\n\n return insert(cleanTree)\n}\n\nexport interface ComputedPane {\n paneId: string\n left: number\n top: number\n width: number\n height: number\n node: PaneNode\n}\n\nexport interface ComputedSplitter {\n id: string\n currentNode: SplitNode\n direction: SplitDirection\n left: number\n top: number\n width: number\n height: number\n parentLeft: number\n parentTop: number\n parentWidth: number\n parentHeight: number\n}\n\nexport function computeLayout(\n node: TreeNode | null,\n left = 0,\n top = 0,\n width = 100,\n height = 100,\n path = 'root',\n): { panes: ComputedPane[]; splitters: ComputedSplitter[] } {\n if (node === null) return { panes: [], splitters: [] }\n if (node.type === 'pane') {\n return {\n panes: [{ paneId: node.id, left, top, width, height, node }],\n splitters: [],\n }\n }\n\n const { direction, splitPercentage, first, second } = node\n const splitterId = `splitter-${path}-${direction}`\n\n const currentSplitter: ComputedSplitter = {\n id: splitterId,\n currentNode: node,\n direction,\n left: direction === 'row' ? left + width * (splitPercentage / 100) : left,\n top: direction === 'column' ? top + height * (splitPercentage / 100) : top,\n width: direction === 'row' ? 0 : width,\n height: direction === 'column' ? 0 : height,\n parentLeft: left,\n parentTop: top,\n parentWidth: width,\n parentHeight: height,\n }\n\n let firstLayout = { panes: [] as ComputedPane[], splitters: [] as ComputedSplitter[] }\n let secondLayout = { panes: [] as ComputedPane[], splitters: [] as ComputedSplitter[] }\n\n if (direction === 'row') {\n const firstWidth = width * (splitPercentage / 100)\n firstLayout = computeLayout(first, left, top, firstWidth, height, `${path}-L`)\n secondLayout = computeLayout(\n second,\n left + firstWidth,\n top,\n width - firstWidth,\n height,\n `${path}-R`,\n )\n } else {\n const firstHeight = height * (splitPercentage / 100)\n firstLayout = computeLayout(first, left, top, width, firstHeight, `${path}-T`)\n secondLayout = computeLayout(\n second,\n left,\n top + firstHeight,\n width,\n height - firstHeight,\n `${path}-B`,\n )\n }\n\n return {\n panes: [...firstLayout.panes, ...secondLayout.panes],\n splitters: [currentSplitter, ...firstLayout.splitters, ...secondLayout.splitters],\n }\n}\n\n/**\n * Calculates the target drop insertion index in a list of tabs during a drag.\n * Returns -1 if the drop target is not in the list.\n */\nexport function calculateTabDropIndex(\n tabs: string[],\n activeType: string | null,\n overTabId: string | null,\n overTabPosition: 'before' | 'after' | null,\n): number {\n const isDraggingTab = activeType === 'tab'\n const isHoveredTabInThisPane = isDraggingTab && overTabId && tabs.includes(overTabId)\n if (!isHoveredTabInThisPane || !overTabPosition) {\n return -1\n }\n const index = tabs.indexOf(overTabId)\n return overTabPosition === 'before' ? index : index + 1\n}\n"]}
1
+ {"version":3,"sources":["../src/shared/lib/tree/tree-helpers.ts"],"names":["generateUniqueId","removePane","tree","paneId","newFirst","newSecond","removeTab","tabId","newTabs","t","newActive","newTabsMetadata","splitPane","targetId","direction","splitType","paneToAdd","addedNode","isFirst","insertLeaf","leafNode","insert","node","parentDirection","addWidget","widgetId","metadata","addTab","targetPaneId","targetPane","findPaneById","appendTabToTarget","newPane","updateSplitPercentage","target","newPercentage","findPaneContainingTab","findTabById","pane","index","updateMetadata","id","updater","currentTabsMetadata","currentTabMeta","newTabMeta","updatePaneLock","locked","_","rest","selectTab","mergeTab","draggedTabId","sourceMetadata","cleanTree","moveTab","targetTabId","position","filteredTabs","insertIndex","computeLayout","left","top","width","height","path","splitPercentage","first","second","currentSplitter","firstLayout","secondLayout","firstWidth","firstHeight","calculateTabDropIndex","tabs","activeType","overTabId","overTabPosition"],"mappings":"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","file":"utils.cjs","sourcesContent":["import { TreeNode, SplitNode, SplitDirection, PaneNode, TabDetails, LeafNode } from '../../model'\n\nexport function generateUniqueId(): string {\n return 'pane-' + Math.random().toString(36).substring(2, 11)\n}\n\n/**\n * Tree Helper: Remove a pane container and consolidate the tree structure.\n */\nexport function removePane(tree: TreeNode | null, paneId: string): TreeNode | null {\n if (tree === null) return null\n if (tree.type === 'pane' || tree.type === 'widget') {\n if (tree.id === paneId) return null\n return tree\n }\n const newFirst = removePane(tree.first, paneId)\n const newSecond = removePane(tree.second, paneId)\n if (newFirst === null) return newSecond\n if (newSecond === null) return newFirst\n return { ...tree, first: newFirst, second: newSecond }\n}\n\n/**\n * Tree Helper: Remove a tab from a pane and consolidate the tree structure if no tabs remain.\n */\nexport function removeTab(tree: TreeNode | null, tabId: string): TreeNode | null {\n if (tree === null) return null\n if (tree.type === 'widget') {\n return tree\n }\n if (tree.type === 'pane') {\n if (tree.tabs.includes(tabId)) {\n const newTabs = tree.tabs.filter((t) => t !== tabId)\n if (newTabs.length === 0) return null\n let newActive = tree.activeTabId\n if (tree.activeTabId === tabId) {\n newActive = newTabs[0]\n }\n const newTabsMetadata = { ...tree.tabsMetadata }\n delete newTabsMetadata[tabId]\n return {\n ...tree,\n tabs: newTabs,\n activeTabId: newActive,\n tabsMetadata: Object.keys(newTabsMetadata).length > 0 ? newTabsMetadata : undefined,\n }\n }\n return tree\n }\n const newFirst = removeTab(tree.first, tabId)\n const newSecond = removeTab(tree.second, tabId)\n if (newFirst === null) return newSecond\n if (newSecond === null) return newFirst\n return { ...tree, first: newFirst, second: newSecond }\n}\n\n/**\n * Tree Helper: Insert a pane or widget by splitting an existing target node.\n */\nexport function splitPane(\n tree: TreeNode | null,\n targetId: string,\n direction: SplitDirection,\n splitType: 'left' | 'right' | 'top' | 'bottom',\n paneToAdd: string | LeafNode,\n): TreeNode | null {\n if (tree === null) {\n if (typeof paneToAdd === 'string') {\n return { type: 'pane', id: generateUniqueId(), tabs: [paneToAdd], activeTabId: paneToAdd }\n }\n return paneToAdd\n }\n if (tree.type === 'pane' || tree.type === 'widget') {\n if (tree.id === targetId) {\n const addedNode: LeafNode =\n typeof paneToAdd === 'string'\n ? { type: 'pane', id: generateUniqueId(), tabs: [paneToAdd], activeTabId: paneToAdd }\n : paneToAdd\n const isFirst = splitType === 'left' || splitType === 'top'\n return {\n type: 'split',\n direction,\n first: isFirst ? addedNode : tree,\n second: isFirst ? tree : addedNode,\n splitPercentage: 50,\n }\n }\n return tree\n }\n return {\n ...tree,\n first: splitPane(tree.first, targetId, direction, splitType, paneToAdd) || tree.first,\n second: splitPane(tree.second, targetId, direction, splitType, paneToAdd) || tree.second,\n }\n}\n\n/**\n * Helper to insert a leaf node (PaneNode or WidgetNode) into the layout tree.\n */\nexport function insertLeaf(tree: TreeNode | null, leafNode: LeafNode): TreeNode {\n if (tree === null) {\n return leafNode\n }\n\n function insert(node: TreeNode, parentDirection: SplitDirection | null): TreeNode {\n if (node.type === 'pane' || node.type === 'widget') {\n const direction: SplitDirection = parentDirection === 'row' ? 'column' : 'row'\n return {\n type: 'split',\n direction,\n splitPercentage: 50,\n first: node,\n second: leafNode,\n }\n }\n\n return {\n ...node,\n second: insert(node.second, node.direction),\n }\n }\n\n return insert(tree, null)\n}\n\n/**\n * Tree Helper: Add a widget by splitting the rightmost/bottommost pane/widget.\n */\nexport function addWidget(\n tree: TreeNode | null,\n widgetId: string,\n metadata?: Record<string, unknown>,\n): TreeNode {\n return insertLeaf(tree, {\n type: 'widget',\n id: widgetId,\n metadata,\n })\n}\n\n/**\n * Tree Helper: Add a tab into a target pane node, or splits/creates a new pane if no target pane ID is provided.\n */\nexport function addTab(\n tree: TreeNode | null,\n targetPaneId: string | undefined | null,\n tabId: string,\n metadata?: Record<string, unknown>,\n): TreeNode | null {\n if (tree === null) {\n return {\n type: 'pane',\n id: generateUniqueId(),\n tabs: [tabId],\n activeTabId: tabId,\n tabsMetadata: metadata ? { [tabId]: metadata } : undefined,\n }\n }\n\n const targetPane = targetPaneId ? findPaneById(tree, targetPaneId) : null\n if (targetPane && targetPane.type === 'pane') {\n function appendTabToTarget(node: TreeNode): TreeNode {\n if (node.type === 'pane' && node.id === targetPaneId) {\n const newTabs = [...node.tabs]\n if (!newTabs.includes(tabId)) {\n newTabs.push(tabId)\n }\n let newTabsMetadata = node.tabsMetadata\n if (metadata) {\n newTabsMetadata = {\n ...node.tabsMetadata,\n [tabId]: metadata,\n }\n }\n return {\n ...node,\n tabs: newTabs,\n activeTabId: tabId,\n tabsMetadata: newTabsMetadata,\n }\n }\n if (node.type === 'split') {\n return {\n ...node,\n first: appendTabToTarget(node.first),\n second: appendTabToTarget(node.second),\n }\n }\n return node\n }\n return appendTabToTarget(tree)\n }\n\n const newPane: PaneNode = {\n type: 'pane',\n id: generateUniqueId(),\n tabs: [tabId],\n activeTabId: tabId,\n tabsMetadata: metadata ? { [tabId]: metadata } : undefined,\n }\n return insertLeaf(tree, newPane)\n}\n\n/**\n * Tree Helper: Update split percentage recursively.\n */\nexport function updateSplitPercentage(\n tree: TreeNode | null,\n target: SplitNode,\n newPercentage: number,\n): TreeNode | null {\n if (tree === null) return null\n if (tree === target) {\n return { ...tree, splitPercentage: newPercentage }\n }\n if (tree.type === 'split') {\n return {\n ...tree,\n first: updateSplitPercentage(tree.first, target, newPercentage) || tree.first,\n second: updateSplitPercentage(tree.second, target, newPercentage) || tree.second,\n }\n }\n return tree\n}\n\n/**\n * Find a PaneNode or WidgetNode by its ID.\n */\nexport function findPaneById(tree: TreeNode | null, paneId: string): LeafNode | null {\n if (tree === null) return null\n if (tree.type === 'pane' || tree.type === 'widget') {\n return tree.id === paneId ? tree : null\n }\n if (tree.type === 'split') {\n return findPaneById(tree.first, paneId) ?? findPaneById(tree.second, paneId)\n }\n return null\n}\n\n/**\n * Find a PaneNode containing the given tab ID.\n */\nexport function findPaneContainingTab(tree: TreeNode | null, tabId: string): PaneNode | null {\n if (tree === null) return null\n if (tree.type === 'pane') {\n return tree.tabs.includes(tabId) ? tree : null\n }\n if (tree.type === 'split') {\n return findPaneContainingTab(tree.first, tabId) ?? findPaneContainingTab(tree.second, tabId)\n }\n return null\n}\n\n/**\n * Find the details of a tab by its ID.\n */\nexport function findTabById(tree: TreeNode | null, tabId: string): TabDetails | null {\n const pane = findPaneContainingTab(tree, tabId)\n if (!pane) return null\n const index = pane.tabs.indexOf(tabId)\n return {\n id: tabId,\n paneId: pane.id,\n isActive: pane.activeTabId === tabId,\n index,\n metadata: pane.tabsMetadata?.[tabId],\n }\n}\n\n/**\n * Update metadata on a specific tab or widget node using an updater function.\n */\nexport function updateMetadata(\n tree: TreeNode | null,\n id: string,\n updater: (current: Record<string, unknown> | undefined) => Record<string, unknown> | undefined,\n): TreeNode | null {\n if (tree === null) return null\n if (tree.type === 'pane') {\n if (tree.tabs.includes(id)) {\n const currentTabsMetadata = tree.tabsMetadata || {}\n const currentTabMeta = currentTabsMetadata[id]\n const newTabMeta = updater(currentTabMeta)\n\n const newTabsMetadata = { ...currentTabsMetadata }\n if (newTabMeta === undefined) {\n delete newTabsMetadata[id]\n } else {\n newTabsMetadata[id] = newTabMeta\n }\n\n return {\n ...tree,\n tabsMetadata: Object.keys(newTabsMetadata).length > 0 ? newTabsMetadata : undefined,\n }\n }\n return tree\n }\n if (tree.type === 'widget') {\n if (tree.id === id) {\n return {\n ...tree,\n metadata: updater(tree.metadata),\n }\n }\n return tree\n }\n if (tree.type === 'split') {\n return {\n ...tree,\n first: updateMetadata(tree.first, id, updater) ?? tree.first,\n second: updateMetadata(tree.second, id, updater) ?? tree.second,\n }\n }\n return tree\n}\n\n/**\n * Update the locked status on a specific pane or widget node in the layout tree.\n */\nexport function updatePaneLock(\n tree: TreeNode | null,\n paneId: string,\n locked: boolean,\n): TreeNode | null {\n if (tree === null) return null\n if (tree.type === 'pane' || tree.type === 'widget') {\n if (tree.id === paneId) {\n if (locked === false) {\n const { locked: _, ...rest } = tree\n return rest as LeafNode\n }\n return { ...tree, locked }\n }\n return tree\n }\n if (tree.type === 'split') {\n return {\n ...tree,\n first: updatePaneLock(tree.first, paneId, locked) ?? tree.first,\n second: updatePaneLock(tree.second, paneId, locked) ?? tree.second,\n }\n }\n return tree\n}\n\n/**\n * Tree Helper: Activate a tab within a pane.\n */\nexport function selectTab(tree: TreeNode | null, paneId: string, tabId: string): TreeNode | null {\n if (tree === null) return null\n if (tree.type === 'pane') {\n if (tree.id === paneId) {\n if (tree.activeTabId === tabId) return tree\n return { ...tree, activeTabId: tabId }\n }\n return tree\n }\n if (tree.type === 'split') {\n return {\n ...tree,\n first: selectTab(tree.first, paneId, tabId) ?? tree.first,\n second: selectTab(tree.second, paneId, tabId) ?? tree.second,\n }\n }\n return tree\n}\n\n/**\n * Tree Helper: Merge a tab into a target pane node.\n */\nexport function mergeTab(\n tree: TreeNode | null,\n draggedTabId: string,\n targetPaneId: string,\n): TreeNode | null {\n if (tree === null) return null\n\n const sourcePane = findPaneContainingTab(tree, draggedTabId)\n const sourceMetadata = sourcePane?.tabsMetadata?.[draggedTabId]\n\n const cleanTree = removeTab(tree, draggedTabId)\n if (cleanTree === null) {\n return {\n type: 'pane',\n id: generateUniqueId(),\n tabs: [draggedTabId],\n activeTabId: draggedTabId,\n tabsMetadata: sourceMetadata ? { [draggedTabId]: sourceMetadata } : undefined,\n }\n }\n\n function insert(node: TreeNode): TreeNode {\n if (node.type === 'pane') {\n if (node.id === targetPaneId) {\n const newTabs = [...node.tabs]\n if (!newTabs.includes(draggedTabId)) {\n newTabs.push(draggedTabId)\n }\n const newTabsMetadata = { ...node.tabsMetadata }\n if (sourceMetadata) {\n newTabsMetadata[draggedTabId] = sourceMetadata\n }\n return {\n ...node,\n tabs: newTabs,\n activeTabId: draggedTabId,\n tabsMetadata: Object.keys(newTabsMetadata).length > 0 ? newTabsMetadata : undefined,\n }\n }\n return node\n }\n if (node.type === 'widget') {\n return node\n }\n if (node.type === 'split') {\n return {\n ...node,\n first: insert(node.first),\n second: insert(node.second),\n }\n }\n return node\n }\n\n return insert(cleanTree)\n}\n\n/**\n * Tree Helper: Move/reorder a tab inside or to a target pane next to a target tab.\n */\nexport function moveTab(\n tree: TreeNode | null,\n draggedTabId: string,\n targetTabId: string,\n position: 'before' | 'after' = 'before',\n): TreeNode | null {\n if (tree === null) return null\n\n const sourcePane = findPaneContainingTab(tree, draggedTabId)\n const sourceMetadata = sourcePane?.tabsMetadata?.[draggedTabId]\n\n const cleanTree = removeTab(tree, draggedTabId)\n if (cleanTree === null) {\n return {\n type: 'pane',\n id: generateUniqueId(),\n tabs: [draggedTabId],\n activeTabId: draggedTabId,\n tabsMetadata: sourceMetadata ? { [draggedTabId]: sourceMetadata } : undefined,\n }\n }\n\n function insert(node: TreeNode): TreeNode {\n if (node.type === 'pane') {\n if (node.tabs.includes(targetTabId)) {\n const newTabs = [...node.tabs]\n const filteredTabs = newTabs.filter((t) => t !== draggedTabId)\n let insertIndex = filteredTabs.indexOf(targetTabId)\n if (insertIndex < 0) {\n insertIndex = 0\n }\n if (position === 'after') {\n insertIndex += 1\n }\n filteredTabs.splice(insertIndex, 0, draggedTabId)\n\n const newTabsMetadata = { ...node.tabsMetadata }\n if (sourceMetadata) {\n newTabsMetadata[draggedTabId] = sourceMetadata\n }\n return {\n ...node,\n tabs: filteredTabs,\n activeTabId: draggedTabId,\n tabsMetadata: Object.keys(newTabsMetadata).length > 0 ? newTabsMetadata : undefined,\n }\n }\n return node\n }\n if (node.type === 'widget') {\n return node\n }\n if (node.type === 'split') {\n return {\n ...node,\n first: insert(node.first),\n second: insert(node.second),\n }\n }\n return node\n }\n\n return insert(cleanTree)\n}\n\nexport interface ComputedPane {\n paneId: string\n left: number\n top: number\n width: number\n height: number\n node: LeafNode\n}\n\nexport interface ComputedSplitter {\n id: string\n currentNode: SplitNode\n direction: SplitDirection\n left: number\n top: number\n width: number\n height: number\n parentLeft: number\n parentTop: number\n parentWidth: number\n parentHeight: number\n}\n\nexport function computeLayout(\n node: TreeNode | null,\n left = 0,\n top = 0,\n width = 100,\n height = 100,\n path = 'root',\n): { panes: ComputedPane[]; splitters: ComputedSplitter[] } {\n if (node === null) return { panes: [], splitters: [] }\n if (node.type === 'pane' || node.type === 'widget') {\n return {\n panes: [{ paneId: node.id, left, top, width, height, node }],\n splitters: [],\n }\n }\n\n const { direction, splitPercentage, first, second } = node\n const splitterId = `splitter-${path}-${direction}`\n\n const currentSplitter: ComputedSplitter = {\n id: splitterId,\n currentNode: node,\n direction,\n left: direction === 'row' ? left + width * (splitPercentage / 100) : left,\n top: direction === 'column' ? top + height * (splitPercentage / 100) : top,\n width: direction === 'row' ? 0 : width,\n height: direction === 'column' ? 0 : height,\n parentLeft: left,\n parentTop: top,\n parentWidth: width,\n parentHeight: height,\n }\n\n let firstLayout = { panes: [] as ComputedPane[], splitters: [] as ComputedSplitter[] }\n let secondLayout = { panes: [] as ComputedPane[], splitters: [] as ComputedSplitter[] }\n\n if (direction === 'row') {\n const firstWidth = width * (splitPercentage / 100)\n firstLayout = computeLayout(first, left, top, firstWidth, height, `${path}-L`)\n secondLayout = computeLayout(\n second,\n left + firstWidth,\n top,\n width - firstWidth,\n height,\n `${path}-R`,\n )\n } else {\n const firstHeight = height * (splitPercentage / 100)\n firstLayout = computeLayout(first, left, top, width, firstHeight, `${path}-T`)\n secondLayout = computeLayout(\n second,\n left,\n top + firstHeight,\n width,\n height - firstHeight,\n `${path}-B`,\n )\n }\n\n return {\n panes: [...firstLayout.panes, ...secondLayout.panes],\n splitters: [currentSplitter, ...firstLayout.splitters, ...secondLayout.splitters],\n }\n}\n\n/**\n * Calculates the target drop insertion index in a list of tabs during a drag.\n * Returns -1 if the drop target is not in the list.\n */\nexport function calculateTabDropIndex(\n tabs: string[],\n activeType: string | null,\n overTabId: string | null,\n overTabPosition: 'before' | 'after' | null,\n): number {\n const isDraggingTab = activeType === 'tab'\n const isHoveredTabInThisPane = isDraggingTab && overTabId && tabs.includes(overTabId)\n if (!isHoveredTabInThisPane || !overTabPosition) {\n return -1\n }\n const index = tabs.indexOf(overTabId)\n return overTabPosition === 'before' ? index : index + 1\n}\n"]}
package/dist/utils.d.cts CHANGED
@@ -1,4 +1,4 @@
1
- import { g as PaneNode, f as SplitNode, S as SplitDirection, T as TreeNode, h as TabDetails } from './types-Yvj0Isvy.cjs';
1
+ import { L as LeafNode, f as SplitNode, S as SplitDirection, T as TreeNode, g as PaneNode, h as TabDetails } from './types-Diujkc-H.cjs';
2
2
  import 'react';
3
3
 
4
4
  declare function generateUniqueId(): string;
@@ -11,21 +11,29 @@ declare function removePane(tree: TreeNode | null, paneId: string): TreeNode | n
11
11
  */
12
12
  declare function removeTab(tree: TreeNode | null, tabId: string): TreeNode | null;
13
13
  /**
14
- * Tree Helper: Insert a pane by splitting an existing target node.
14
+ * Tree Helper: Insert a pane or widget by splitting an existing target node.
15
15
  */
16
- declare function splitPane(tree: TreeNode | null, targetId: string, direction: SplitDirection, splitType: 'left' | 'right' | 'top' | 'bottom', paneToAdd: string | PaneNode): TreeNode | null;
16
+ declare function splitPane(tree: TreeNode | null, targetId: string, direction: SplitDirection, splitType: 'left' | 'right' | 'top' | 'bottom', paneToAdd: string | LeafNode): TreeNode | null;
17
17
  /**
18
- * Tree Helper: Add a pane by recursively splitting the rightmost/bottommost pane in the tree.
18
+ * Helper to insert a leaf node (PaneNode or WidgetNode) into the layout tree.
19
19
  */
20
- declare function addPane(tree: TreeNode | null, paneToAdd: string, metadata?: Record<string, unknown>): TreeNode;
20
+ declare function insertLeaf(tree: TreeNode | null, leafNode: LeafNode): TreeNode;
21
+ /**
22
+ * Tree Helper: Add a widget by splitting the rightmost/bottommost pane/widget.
23
+ */
24
+ declare function addWidget(tree: TreeNode | null, widgetId: string, metadata?: Record<string, unknown>): TreeNode;
25
+ /**
26
+ * Tree Helper: Add a tab into a target pane node, or splits/creates a new pane if no target pane ID is provided.
27
+ */
28
+ declare function addTab(tree: TreeNode | null, targetPaneId: string | undefined | null, tabId: string, metadata?: Record<string, unknown>): TreeNode | null;
21
29
  /**
22
30
  * Tree Helper: Update split percentage recursively.
23
31
  */
24
32
  declare function updateSplitPercentage(tree: TreeNode | null, target: SplitNode, newPercentage: number): TreeNode | null;
25
33
  /**
26
- * Find a PaneNode by its ID.
34
+ * Find a PaneNode or WidgetNode by its ID.
27
35
  */
28
- declare function findPaneById(tree: TreeNode | null, paneId: string): PaneNode | null;
36
+ declare function findPaneById(tree: TreeNode | null, paneId: string): LeafNode | null;
29
37
  /**
30
38
  * Find a PaneNode containing the given tab ID.
31
39
  */
@@ -35,11 +43,11 @@ declare function findPaneContainingTab(tree: TreeNode | null, tabId: string): Pa
35
43
  */
36
44
  declare function findTabById(tree: TreeNode | null, tabId: string): TabDetails | null;
37
45
  /**
38
- * Update metadata on a specific tab node using an updater function.
46
+ * Update metadata on a specific tab or widget node using an updater function.
39
47
  */
40
- declare function updateTabMetadata(tree: TreeNode | null, tabId: string, updater: (current: Record<string, unknown> | undefined) => Record<string, unknown> | undefined): TreeNode | null;
48
+ declare function updateMetadata(tree: TreeNode | null, id: string, updater: (current: Record<string, unknown> | undefined) => Record<string, unknown> | undefined): TreeNode | null;
41
49
  /**
42
- * Update the locked status on a specific pane node in the layout tree.
50
+ * Update the locked status on a specific pane or widget node in the layout tree.
43
51
  */
44
52
  declare function updatePaneLock(tree: TreeNode | null, paneId: string, locked: boolean): TreeNode | null;
45
53
  /**
@@ -60,7 +68,7 @@ interface ComputedPane {
60
68
  top: number;
61
69
  width: number;
62
70
  height: number;
63
- node: PaneNode;
71
+ node: LeafNode;
64
72
  }
65
73
  interface ComputedSplitter {
66
74
  id: string;
@@ -85,4 +93,4 @@ declare function computeLayout(node: TreeNode | null, left?: number, top?: numbe
85
93
  */
86
94
  declare function calculateTabDropIndex(tabs: string[], activeType: string | null, overTabId: string | null, overTabPosition: 'before' | 'after' | null): number;
87
95
 
88
- export { type ComputedPane, type ComputedSplitter, addPane, calculateTabDropIndex, computeLayout, findPaneById, findPaneContainingTab, findTabById, generateUniqueId, mergeTab, moveTab, removePane, removeTab, selectTab, splitPane, updatePaneLock, updateSplitPercentage, updateTabMetadata };
96
+ export { type ComputedPane, type ComputedSplitter, addTab, addWidget, calculateTabDropIndex, computeLayout, findPaneById, findPaneContainingTab, findTabById, generateUniqueId, insertLeaf, mergeTab, moveTab, removePane, removeTab, selectTab, splitPane, updateMetadata, updatePaneLock, updateSplitPercentage };
package/dist/utils.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { g as PaneNode, f as SplitNode, S as SplitDirection, T as TreeNode, h as TabDetails } from './types-Yvj0Isvy.js';
1
+ import { L as LeafNode, f as SplitNode, S as SplitDirection, T as TreeNode, g as PaneNode, h as TabDetails } from './types-Diujkc-H.js';
2
2
  import 'react';
3
3
 
4
4
  declare function generateUniqueId(): string;
@@ -11,21 +11,29 @@ declare function removePane(tree: TreeNode | null, paneId: string): TreeNode | n
11
11
  */
12
12
  declare function removeTab(tree: TreeNode | null, tabId: string): TreeNode | null;
13
13
  /**
14
- * Tree Helper: Insert a pane by splitting an existing target node.
14
+ * Tree Helper: Insert a pane or widget by splitting an existing target node.
15
15
  */
16
- declare function splitPane(tree: TreeNode | null, targetId: string, direction: SplitDirection, splitType: 'left' | 'right' | 'top' | 'bottom', paneToAdd: string | PaneNode): TreeNode | null;
16
+ declare function splitPane(tree: TreeNode | null, targetId: string, direction: SplitDirection, splitType: 'left' | 'right' | 'top' | 'bottom', paneToAdd: string | LeafNode): TreeNode | null;
17
17
  /**
18
- * Tree Helper: Add a pane by recursively splitting the rightmost/bottommost pane in the tree.
18
+ * Helper to insert a leaf node (PaneNode or WidgetNode) into the layout tree.
19
19
  */
20
- declare function addPane(tree: TreeNode | null, paneToAdd: string, metadata?: Record<string, unknown>): TreeNode;
20
+ declare function insertLeaf(tree: TreeNode | null, leafNode: LeafNode): TreeNode;
21
+ /**
22
+ * Tree Helper: Add a widget by splitting the rightmost/bottommost pane/widget.
23
+ */
24
+ declare function addWidget(tree: TreeNode | null, widgetId: string, metadata?: Record<string, unknown>): TreeNode;
25
+ /**
26
+ * Tree Helper: Add a tab into a target pane node, or splits/creates a new pane if no target pane ID is provided.
27
+ */
28
+ declare function addTab(tree: TreeNode | null, targetPaneId: string | undefined | null, tabId: string, metadata?: Record<string, unknown>): TreeNode | null;
21
29
  /**
22
30
  * Tree Helper: Update split percentage recursively.
23
31
  */
24
32
  declare function updateSplitPercentage(tree: TreeNode | null, target: SplitNode, newPercentage: number): TreeNode | null;
25
33
  /**
26
- * Find a PaneNode by its ID.
34
+ * Find a PaneNode or WidgetNode by its ID.
27
35
  */
28
- declare function findPaneById(tree: TreeNode | null, paneId: string): PaneNode | null;
36
+ declare function findPaneById(tree: TreeNode | null, paneId: string): LeafNode | null;
29
37
  /**
30
38
  * Find a PaneNode containing the given tab ID.
31
39
  */
@@ -35,11 +43,11 @@ declare function findPaneContainingTab(tree: TreeNode | null, tabId: string): Pa
35
43
  */
36
44
  declare function findTabById(tree: TreeNode | null, tabId: string): TabDetails | null;
37
45
  /**
38
- * Update metadata on a specific tab node using an updater function.
46
+ * Update metadata on a specific tab or widget node using an updater function.
39
47
  */
40
- declare function updateTabMetadata(tree: TreeNode | null, tabId: string, updater: (current: Record<string, unknown> | undefined) => Record<string, unknown> | undefined): TreeNode | null;
48
+ declare function updateMetadata(tree: TreeNode | null, id: string, updater: (current: Record<string, unknown> | undefined) => Record<string, unknown> | undefined): TreeNode | null;
41
49
  /**
42
- * Update the locked status on a specific pane node in the layout tree.
50
+ * Update the locked status on a specific pane or widget node in the layout tree.
43
51
  */
44
52
  declare function updatePaneLock(tree: TreeNode | null, paneId: string, locked: boolean): TreeNode | null;
45
53
  /**
@@ -60,7 +68,7 @@ interface ComputedPane {
60
68
  top: number;
61
69
  width: number;
62
70
  height: number;
63
- node: PaneNode;
71
+ node: LeafNode;
64
72
  }
65
73
  interface ComputedSplitter {
66
74
  id: string;
@@ -85,4 +93,4 @@ declare function computeLayout(node: TreeNode | null, left?: number, top?: numbe
85
93
  */
86
94
  declare function calculateTabDropIndex(tabs: string[], activeType: string | null, overTabId: string | null, overTabPosition: 'before' | 'after' | null): number;
87
95
 
88
- export { type ComputedPane, type ComputedSplitter, addPane, calculateTabDropIndex, computeLayout, findPaneById, findPaneContainingTab, findTabById, generateUniqueId, mergeTab, moveTab, removePane, removeTab, selectTab, splitPane, updatePaneLock, updateSplitPercentage, updateTabMetadata };
96
+ export { type ComputedPane, type ComputedSplitter, addTab, addWidget, calculateTabDropIndex, computeLayout, findPaneById, findPaneContainingTab, findTabById, generateUniqueId, insertLeaf, mergeTab, moveTab, removePane, removeTab, selectTab, splitPane, updateMetadata, updatePaneLock, updateSplitPercentage };
package/dist/utils.js CHANGED
@@ -1,2 +1,2 @@
1
- function p(){return "pane-"+Math.random().toString(36).substring(2,11)}function M(n,t){if(n===null)return null;if(n.type==="pane")return n.id===t?null:n;let e=M(n.first,t),s=M(n.second,t);return e===null?s:s===null?e:{...n,first:e,second:s}}function m(n,t){if(n===null)return null;if(n.type==="pane"){if(n.tabs.includes(t)){let i=n.tabs.filter(l=>l!==t);if(i.length===0)return null;let u=n.activeTabId;n.activeTabId===t&&(u=i[0]);let r={...n.tabsMetadata};return delete r[t],{...n,tabs:i,activeTabId:u,tabsMetadata:Object.keys(r).length>0?r:void 0}}return n}let e=m(n.first,t),s=m(n.second,t);return e===null?s:s===null?e:{...n,first:e,second:s}}function P(n,t,e,s,i){if(n===null)return typeof i=="string"?{type:"pane",id:p(),tabs:[i],activeTabId:i}:i;if(n.type==="pane"){if(n.id===t){let u=typeof i=="string"?{type:"pane",id:p(),tabs:[i],activeTabId:i}:i,r=s==="left"||s==="top";return {type:"split",direction:e,first:r?u:n,second:r?n:u,splitPercentage:50}}return n}return {...n,first:P(n.first,t,e,s,i)||n.first,second:P(n.second,t,e,s,i)||n.second}}function D(n,t,e){if(n===null)return {type:"pane",id:p(),tabs:[t],activeTabId:t,tabsMetadata:e?{[t]:e}:void 0};function s(i,u){return i.type==="pane"?{type:"split",direction:u==="row"?"column":"row",splitPercentage:50,first:i,second:{type:"pane",id:p(),tabs:[t],activeTabId:t,tabsMetadata:e?{[t]:e}:void 0}}:{...i,second:s(i.second,i.direction)}}return s(n,null)}function x(n,t,e){return n===null?null:n===t?{...n,splitPercentage:e}:n.type==="split"?{...n,first:x(n.first,t,e)||n.first,second:x(n.second,t,e)||n.second}:n}function v(n,t){return n===null?null:n.type==="pane"?n.id===t?n:null:v(n.first,t)??v(n.second,t)}function T(n,t){return n===null?null:n.type==="pane"?n.tabs.includes(t)?n:null:T(n.first,t)??T(n.second,t)}function g(n,t){let e=T(n,t);if(!e)return null;let s=e.tabs.indexOf(t);return {id:t,paneId:e.id,isActive:e.activeTabId===t,index:s,metadata:e.tabsMetadata?.[t]}}function S(n,t,e){if(n===null)return null;if(n.type==="pane"){if(n.tabs.includes(t)){let s=n.tabsMetadata||{},i=s[t],u=e(i),r={...s};return u===void 0?delete r[t]:r[t]=u,{...n,tabsMetadata:Object.keys(r).length>0?r:void 0}}return n}return {...n,first:S(n.first,t,e)??n.first,second:S(n.second,t,e)??n.second}}function w(n,t,e){if(n===null)return null;if(n.type==="pane"){if(n.id===t){if(e===false){let{locked:s,...i}=n;return i}return {...n,locked:e}}return n}return {...n,first:w(n.first,t,e)??n.first,second:w(n.second,t,e)??n.second}}function C(n,t,e){return n===null?null:n.type==="pane"?n.id===t?n.activeTabId===e?n:{...n,activeTabId:e}:n:{...n,first:C(n.first,t,e)??n.first,second:C(n.second,t,e)??n.second}}function L(n,t,e){if(n===null)return null;let i=T(n,t)?.tabsMetadata?.[t],u=m(n,t);if(u===null)return {type:"pane",id:p(),tabs:[t],activeTabId:t,tabsMetadata:i?{[t]:i}:void 0};function r(l){if(l.type==="pane"){if(l.id===e){let o=[...l.tabs];o.includes(t)||o.push(t);let c={...l.tabsMetadata};return i&&(c[t]=i),{...l,tabs:o,activeTabId:t,tabsMetadata:Object.keys(c).length>0?c:void 0}}return l}return {...l,first:r(l.first),second:r(l.second)}}return r(u)}function k(n,t,e,s="before"){if(n===null)return null;let u=T(n,t)?.tabsMetadata?.[t],r=m(n,t);if(r===null)return {type:"pane",id:p(),tabs:[t],activeTabId:t,tabsMetadata:u?{[t]:u}:void 0};function l(o){if(o.type==="pane"){if(o.tabs.includes(e)){let y=[...o.tabs].filter(b=>b!==t),d=y.indexOf(e);d<0&&(d=0),s==="after"&&(d+=1),y.splice(d,0,t);let a={...o.tabsMetadata};return u&&(a[t]=u),{...o,tabs:y,activeTabId:t,tabsMetadata:Object.keys(a).length>0?a:void 0}}return o}return {...o,first:l(o.first),second:l(o.second)}}return l(r)}function N(n,t=0,e=0,s=100,i=100,u="root"){if(n===null)return {panes:[],splitters:[]};if(n.type==="pane")return {panes:[{paneId:n.id,left:t,top:e,width:s,height:i,node:n}],splitters:[]};let{direction:r,splitPercentage:l,first:o,second:c}=n,d={id:`splitter-${u}-${r}`,currentNode:n,direction:r,left:r==="row"?t+s*(l/100):t,top:r==="column"?e+i*(l/100):e,width:r==="row"?0:s,height:r==="column"?0:i,parentLeft:t,parentTop:e,parentWidth:s,parentHeight:i},a={panes:[],splitters:[]},b={panes:[],splitters:[]};if(r==="row"){let f=s*(l/100);a=N(o,t,e,f,i,`${u}-L`),b=N(c,t+f,e,s-f,i,`${u}-R`);}else {let f=i*(l/100);a=N(o,t,e,s,f,`${u}-T`),b=N(c,t,e+f,s,i-f,`${u}-B`);}return {panes:[...a.panes,...b.panes],splitters:[d,...a.splitters,...b.splitters]}}function O(n,t,e,s){if(!(t==="tab"&&e&&n.includes(e))||!s)return -1;let r=n.indexOf(e);return s==="before"?r:r+1}export{D as addPane,O as calculateTabDropIndex,N as computeLayout,v as findPaneById,T as findPaneContainingTab,g as findTabById,p as generateUniqueId,L as mergeTab,k as moveTab,M as removePane,m as removeTab,C as selectTab,P as splitPane,w as updatePaneLock,x as updateSplitPercentage,S as updateTabMetadata};//# sourceMappingURL=utils.js.map
1
+ function d(){return "pane-"+Math.random().toString(36).substring(2,11)}function M(n,t){if(n===null)return null;if(n.type==="pane"||n.type==="widget")return n.id===t?null:n;let e=M(n.first,t),i=M(n.second,t);return e===null?i:i===null?e:{...n,first:e,second:i}}function m(n,t){if(n===null)return null;if(n.type==="widget")return n;if(n.type==="pane"){if(n.tabs.includes(t)){let r=n.tabs.filter(l=>l!==t);if(r.length===0)return null;let a=n.activeTabId;n.activeTabId===t&&(a=r[0]);let u={...n.tabsMetadata};return delete u[t],{...n,tabs:r,activeTabId:a,tabsMetadata:Object.keys(u).length>0?u:void 0}}return n}let e=m(n.first,t),i=m(n.second,t);return e===null?i:i===null?e:{...n,first:e,second:i}}function x(n,t,e,i,r){if(n===null)return typeof r=="string"?{type:"pane",id:d(),tabs:[r],activeTabId:r}:r;if(n.type==="pane"||n.type==="widget"){if(n.id===t){let a=typeof r=="string"?{type:"pane",id:d(),tabs:[r],activeTabId:r}:r,u=i==="left"||i==="top";return {type:"split",direction:e,first:u?a:n,second:u?n:a,splitPercentage:50}}return n}return {...n,first:x(n.first,t,e,i,r)||n.first,second:x(n.second,t,e,i,r)||n.second}}function L(n,t){if(n===null)return t;function e(i,r){return i.type==="pane"||i.type==="widget"?{type:"split",direction:r==="row"?"column":"row",splitPercentage:50,first:i,second:t}:{...i,second:e(i.second,i.direction)}}return e(n,null)}function C(n,t,e){return L(n,{type:"widget",id:t,metadata:e})}function D(n,t,e,i){if(n===null)return {type:"pane",id:d(),tabs:[e],activeTabId:e,tabsMetadata:i?{[e]:i}:void 0};let r=t?w(n,t):null;if(r&&r.type==="pane"){let l=function(s){if(s.type==="pane"&&s.id===t){let o=[...s.tabs];o.includes(e)||o.push(e);let c=s.tabsMetadata;return i&&(c={...s.tabsMetadata,[e]:i}),{...s,tabs:o,activeTabId:e,tabsMetadata:c}}return s.type==="split"?{...s,first:l(s.first),second:l(s.second)}:s};return l(n)}let a={type:"pane",id:d(),tabs:[e],activeTabId:e,tabsMetadata:i?{[e]:i}:void 0};return L(n,a)}function P(n,t,e){return n===null?null:n===t?{...n,splitPercentage:e}:n.type==="split"?{...n,first:P(n.first,t,e)||n.first,second:P(n.second,t,e)||n.second}:n}function w(n,t){return n===null?null:n.type==="pane"||n.type==="widget"?n.id===t?n:null:n.type==="split"?w(n.first,t)??w(n.second,t):null}function y(n,t){return n===null?null:n.type==="pane"?n.tabs.includes(t)?n:null:n.type==="split"?y(n.first,t)??y(n.second,t):null}function k(n,t){let e=y(n,t);if(!e)return null;let i=e.tabs.indexOf(t);return {id:t,paneId:e.id,isActive:e.activeTabId===t,index:i,metadata:e.tabsMetadata?.[t]}}function g(n,t,e){if(n===null)return null;if(n.type==="pane"){if(n.tabs.includes(t)){let i=n.tabsMetadata||{},r=i[t],a=e(r),u={...i};return a===void 0?delete u[t]:u[t]=a,{...n,tabsMetadata:Object.keys(u).length>0?u:void 0}}return n}return n.type==="widget"?n.id===t?{...n,metadata:e(n.metadata)}:n:n.type==="split"?{...n,first:g(n.first,t,e)??n.first,second:g(n.second,t,e)??n.second}:n}function v(n,t,e){if(n===null)return null;if(n.type==="pane"||n.type==="widget"){if(n.id===t){if(e===false){let{locked:i,...r}=n;return r}return {...n,locked:e}}return n}return n.type==="split"?{...n,first:v(n.first,t,e)??n.first,second:v(n.second,t,e)??n.second}:n}function S(n,t,e){return n===null?null:n.type==="pane"?n.id===t?n.activeTabId===e?n:{...n,activeTabId:e}:n:n.type==="split"?{...n,first:S(n.first,t,e)??n.first,second:S(n.second,t,e)??n.second}:n}function O(n,t,e){if(n===null)return null;let r=y(n,t)?.tabsMetadata?.[t],a=m(n,t);if(a===null)return {type:"pane",id:d(),tabs:[t],activeTabId:t,tabsMetadata:r?{[t]:r}:void 0};function u(l){if(l.type==="pane"){if(l.id===e){let s=[...l.tabs];s.includes(t)||s.push(t);let o={...l.tabsMetadata};return r&&(o[t]=r),{...l,tabs:s,activeTabId:t,tabsMetadata:Object.keys(o).length>0?o:void 0}}return l}return l.type==="widget"?l:l.type==="split"?{...l,first:u(l.first),second:u(l.second)}:l}return u(a)}function $(n,t,e,i="before"){if(n===null)return null;let a=y(n,t)?.tabsMetadata?.[t],u=m(n,t);if(u===null)return {type:"pane",id:d(),tabs:[t],activeTabId:t,tabsMetadata:a?{[t]:a}:void 0};function l(s){if(s.type==="pane"){if(s.tabs.includes(e)){let c=[...s.tabs].filter(T=>T!==t),b=c.indexOf(e);b<0&&(b=0),i==="after"&&(b+=1),c.splice(b,0,t);let f={...s.tabsMetadata};return a&&(f[t]=a),{...s,tabs:c,activeTabId:t,tabsMetadata:Object.keys(f).length>0?f:void 0}}return s}return s.type==="widget"?s:s.type==="split"?{...s,first:l(s.first),second:l(s.second)}:s}return l(u)}function N(n,t=0,e=0,i=100,r=100,a="root"){if(n===null)return {panes:[],splitters:[]};if(n.type==="pane"||n.type==="widget")return {panes:[{paneId:n.id,left:t,top:e,width:i,height:r,node:n}],splitters:[]};let{direction:u,splitPercentage:l,first:s,second:o}=n,b={id:`splitter-${a}-${u}`,currentNode:n,direction:u,left:u==="row"?t+i*(l/100):t,top:u==="column"?e+r*(l/100):e,width:u==="row"?0:i,height:u==="column"?0:r,parentLeft:t,parentTop:e,parentWidth:i,parentHeight:r},f={panes:[],splitters:[]},T={panes:[],splitters:[]};if(u==="row"){let p=i*(l/100);f=N(s,t,e,p,r,`${a}-L`),T=N(o,t+p,e,i-p,r,`${a}-R`);}else {let p=r*(l/100);f=N(s,t,e,i,p,`${a}-T`),T=N(o,t,e+p,i,r-p,`${a}-B`);}return {panes:[...f.panes,...T.panes],splitters:[b,...f.splitters,...T.splitters]}}function B(n,t,e,i){if(!(t==="tab"&&e&&n.includes(e))||!i)return -1;let u=n.indexOf(e);return i==="before"?u:u+1}export{D as addTab,C as addWidget,B as calculateTabDropIndex,N as computeLayout,w as findPaneById,y as findPaneContainingTab,k as findTabById,d as generateUniqueId,L as insertLeaf,O as mergeTab,$ as moveTab,M as removePane,m as removeTab,S as selectTab,x as splitPane,g as updateMetadata,v as updatePaneLock,P as updateSplitPercentage};//# sourceMappingURL=utils.js.map
2
2
  //# sourceMappingURL=utils.js.map