@dynamix-layout/core 0.0.2-beta.0 → 0.0.6

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/CHANGELOG.md CHANGED
@@ -1,5 +1,36 @@
1
1
  # @dynamix-layout/core
2
2
 
3
+ ## 0.0.6
4
+
5
+ ### Patch Changes
6
+
7
+ - [#25](https://github.com/akash-aman/dynamix-layout/pull/25) [`8b7ab1a`](https://github.com/akash-aman/dynamix-layout/commit/8b7ab1a0317dae85400ed381c85a4e50c35db41e) Thanks [@akash-aman](https://github.com/akash-aman)! - feat(core): enhance demo with GIFs/MP4s and update README for better structure
8
+ - Updated `.hintrc` to enforce consistent casing for TypeScript.
9
+ - Added demo assets (GIFs, MP4) to showcase layout functionality.
10
+ - Cleaned up `.npmignore` to exclude `.map` files.
11
+ - Removed unused `vite-plugin-compression2` dependency.
12
+ - Improved README structure and visual assets for `core` package.
13
+ - Added TypeScript configuration files for clearer project setup.
14
+
15
+ feat(react): initial release of DynamixLayout React component
16
+ - Introduced `@dynamix-layout/react` package to provide a React wrapper around `@dynamix-layout/core`.
17
+ - Added `DynamixLayout` component with support for dynamic, draggable, and resizable layouts.
18
+ - Included usage examples and updated README for better developer onboarding.
19
+ - Integrated demo assets (GIFs, MP4s) to showcase layout behavior.
20
+ - Refactored tests to validate component behavior and ensure coverage.
21
+
22
+ ## 0.0.5
23
+
24
+ ### Patch Changes
25
+
26
+ - Refactored layout core and added unit tests for reactive state and layout logic
27
+ - Replaced legacy `Layout` class with modular utilities: `Queue` and `createReactiveState`.
28
+ - Improved layout shifting algorithm (`shiftTree`) and bond-based slider behavior.
29
+ - Added comprehensive unit tests for layout validation, tree integrity, and reactive state handling.
30
+ - Simplified exports and cleaned up `index.ts`, `.gitignore`, and `package.json` structure.
31
+ - Refactored `vite.config.ts`, `tsconfig.json`, and `vitest.config.ts` for clarity and consistency.
32
+ - Added license metadata to Vite config and updated author name in LICENSE.
33
+
3
34
  ## 0.0.2-beta.0
4
35
 
5
36
  ### Patch Changes
package/README.md CHANGED
@@ -1,109 +1,207 @@
1
- # Dynamix Layout/Core
1
+ <div align="center">
2
2
 
3
- ![Dynamix Layout Logo](https://raw.githubusercontent.com/akash-aman/dynamix-layout/main/packages/core/assets/view.gif)
3
+ [![Patreon](https://img.shields.io/badge/Patreon-Support-F96854?style=for-the-badge&logo=patreon)](https://www.patreon.com/akashaman)
4
+ [![Buy Me A Coffee](https://img.shields.io/badge/Buy%20Me%20A%20Coffee-Donate-FFDD00?style=for-the-badge&logo=buy-me-a-coffee)](https://www.buymeacoffee.com/akashaman)
5
+ [![Hire Me](https://img.shields.io/badge/Hire%20Me-Email-blue?style=for-the-badge&logo=gmail)](mailto:sir.akashaman@gmail.com)
6
+
7
+ </div>
8
+
9
+ # 🚀 @dynamix-layout/core
4
10
 
5
11
  ## Overview
6
12
 
7
- **Dynamix Layout/Core** is a versatile JavaScript package for creating dynamic layouts with ease. This package provides a set of options and methods to manage and manipulate layouts within a container. With Dynamix Layout/Core, you can efficiently handle layouts, dimensions, coordinates, tabs, and more.
13
+ **@dynamix-layout/core** is the **engine** that powers the **creation**, **management**, and **dynamic modification** of your layout structures. It handles the **internal logic** of the layout tree, including **node creation**, **dimension calculation**, and **state updates**. This package works with a **hierarchical tree structure** composed of `Node` objects and exposes a **reactive state** for seamless integration with modern UI frameworks.
14
+
15
+ ---
16
+
17
+ ### Made with ❤️ by [Akash Aman](https://linktr.ee/akash_aman)
18
+
19
+ ---
20
+
21
+ ![alt text](https://raw.githubusercontent.com/akash-aman/dynamix-layout/main/assets/demo.gif)
22
+
23
+ ---
24
+
25
+ ## Core Classes
8
26
 
9
- ## Options Object Parameters
27
+ The package is built around three primary classes: `DynamixLayoutCore`, `Node`, and `Bond`.
10
28
 
11
- When initializing the package, you can provide an options object with the following parameters:
29
+ 1. **`DynamixLayoutCore`**: The main controller class that you instantiate to create and manage the entire layout. It serves as the primary public API.
30
+ 2. **`Node`**: The fundamental building block of the layout tree. Each `Node` can be a `row`, a `tabset`, or a `tab`.
31
+ 3. **`Bond`**: A special object that represents the draggable separator between two nodes, allowing for resizing.
12
32
 
13
- 1. **layout** *(JSON)*: This parameter allows you to provide a serialized JSON representation of a layout. It can be used to recreate the same layout in the future. If not provided, it defaults to `null`.
33
+ ---
14
34
 
15
- 2. **range** *(Number)*: Use this parameter to specify the number of tabs you want to create and get their sizes on layout shift. If not provided, it defaults to `1`.
35
+ ## `DynamixLayoutCore` Class
16
36
 
17
- 3. **dimension** *(Array)*: This parameter is used to set the width and height of the main container in which child layouts exist. It should be an array of two numbers, e.g., `[width, height]`. The default value is `[0, 0]`.
37
+ The `DynamixLayoutCore` class is the central point of control for your entire layout configuration.
18
38
 
19
- 4. **coordinate** *(Array)*: Specify the x and y positions within the window of the container element using this parameter. It should be an array of two numbers, e.g., `[x, y]`. The default value is `[0, 0]`.
39
+ ### Constructor
20
40
 
21
- 5. **tabs** *(Array)*: This parameter allows you to provide an array of names for the tabs. These names are used as IDs and key names. The default value is an array created based on the `range` parameter, such as `['tab-1', 'tab-2', ...]`.
41
+ When initializing the `DynamixLayoutCore` class, you provide a single **options object**.
22
42
 
23
- ## Allowed Parameters
43
+ `new DynamixLayoutCore(options)`
24
44
 
25
- - **layout**: Represents a serialized JSON layout for recreating layouts.
26
- - **dimension**: Specifies the width and height of the main container.
27
- - **coordinate**: Sets the x and y positions within the container element's window.
28
- - **tabs**: An array of names for tabs, used as IDs and key names.
29
- - **range**: Number of tabs to create and get their sizes on layout shift.
45
+ - **`options`** (`object`): An object containing configuration properties.
46
+ - **`tabs`** (`string[]`): An array of tab names to generate an initial binary tree layout. Defaults to `[]`.
47
+ - **`tree`** (`LayoutTree | null`): A serialized JSON representation of a previously saved layout (`LayoutTree` object). If provided, it will recreate that specific layout. Defaults to `null`.
48
+ - **`tabsIds`** (`Map<string, string>`): A map where keys are tab names and values are their unique IDs. This is useful for persisting tab identities across sessions.
49
+ - **`minW`** (`number`): The minimum width for a `tabset`. Defaults to `40`.
50
+ - **`minH`** (`number`): The minimum height for a `tabset`. Defaults to `40`.
51
+ - **`bond`** (`number`): The width or height (in pixels) of the draggable separator (`Bond`) between nodes. Defaults to `10`.
30
52
 
31
- ## Methods
53
+ ### Reactive Properties
32
54
 
33
- ### 1. shiftTree(srcId, destId)
55
+ The layout's state is exposed through static reactive properties on the `Node` class. You can subscribe to these to drive your UI.
34
56
 
35
- The `shiftTree` method is used to shift the layout from a source element with the given `srcId` to a destination element with the `destId`. It returns the sizes of the elements involved in the shift.
57
+ - **`Node.cache.nodOpts`**: A reactive map of all `tabset` nodes and their options.
58
+ - **`Node.cache.bndOpts`**: A reactive map of all `bond` objects.
59
+ - **`Node.cache.tabOpts`**: A reactive map of all `tab` nodes within their respective tabsets.
60
+
61
+ ### Methods
62
+
63
+ #### 🌳 `updateTree(src, des, layout)`
64
+
65
+ This is the core method for rearranging the layout. It moves a source node (`src`) to a new position relative to a destination node (`des`).
66
+
67
+ - **`src`** (`string`): The unique ID of the node to move (can be a `tab` or a `tabset`).
68
+ - **`des`** (`string`): The unique ID of the destination node.
69
+ - **`layout`** (`'top' | 'bottom' | 'left' | 'right' | 'contain'`): Specifies how the source should be placed relative to the destination.
70
+ - `top`, `bottom`, `left`, `right`: Places the source node by splitting the destination area.
71
+ - `contain`: Places a source `tab` into the destination `tabset`.
72
+
73
+ **Returns**: `boolean` - `true` if the update was successful, `false` otherwise.
36
74
 
37
- Example:
38
75
  ```javascript
39
- const sizes = dynamixLayout.shiftTree('tab-1', 'tab-2');
76
+ // Moves the node with 'sidebar-id' to be to the left of 'main-content-id'
77
+ layout.updateTree('sidebar-id', 'main-content-id', 'left')
40
78
  ```
41
79
 
42
- ### 2. updateTree()
80
+ ---
81
+
82
+ #### 📏 `updateDimension(dim, disableTimeout, timeout)`
83
+
84
+ Recalculates all node dimensions within the layout, typically after the main container has been resized.
43
85
 
44
- The `updateTree` method is used to recalculate the sizes in case of a window resize. It ensures that the layout remains consistent after a container size change.
86
+ - **`dim`** (`{ w, h, x, y }`): An object representing the new dimensions of the root container.
87
+ - **`disableTimeout`** (`boolean`): If `true`, the update runs instantly. Otherwise, it's debounced. Defaults to `false`.
88
+ - **`timeout`** (`number`): The debounce delay in milliseconds. Defaults to `2`.
89
+
90
+ <!-- end list -->
45
91
 
46
- Example:
47
92
  ```javascript
48
- dynamixLayout.updateTree();
93
+ // On window resize, update the layout dimensions
94
+ layout.updateDimension({
95
+ w: window.innerWidth,
96
+ h: window.innerHeight,
97
+ x: 0,
98
+ y: 0,
99
+ })
49
100
  ```
50
101
 
51
- ### 3. getElement()
102
+ ---
103
+
104
+ #### ↔️ `updateSlider(id, dim, disableTimeout, timeout)`
105
+
106
+ Updates the layout in response to a user dragging a `Bond` (slider).
107
+
108
+ - **`id`** (`string`): The unique ID of the `Bond` being moved.
109
+ - **`dim`** (`{ x, y }`): An object with the new coordinates of the slider.
110
+ - **`disableTimeout`** (`boolean`): If `true`, the update runs instantly. Defaults to `false`.
111
+ - **`timeout`** (`number`): The debounce delay in milliseconds. Defaults to `2`.
52
112
 
53
- The `getElement` method returns information about all the tabs and their sizes. It is useful for retrieving the current state of the layout.
113
+ <!-- end list -->
54
114
 
55
- Example:
56
115
  ```javascript
57
- const tabInfo = dynamixLayout.getElement();
116
+ // When a user drags a separator
117
+ layout.updateSlider('bond-123', { x: 450, y: 300 })
58
118
  ```
59
119
 
60
- ### 4. jsonify()
120
+ ---
61
121
 
62
- The `jsonify` method is used to generate a JSON representation of the current layout. You can store this JSON in local storage and use it to recreate the same layout at a later time.
122
+ #### 🗑️ `clearAllCache()`
123
+
124
+ Clears all internal caches for nodes, bonds, dimensions, and other layout data. Use this when completely destroying or resetting the layout.
63
125
 
64
- Example:
65
126
  ```javascript
66
- const layoutJSON = dynamixLayout.jsonify();
127
+ layout.clearAllCache()
67
128
  ```
68
129
 
69
- ## Emojis
130
+ ---
131
+
132
+ ## `Node` Class
133
+
134
+ The `Node` represents a single element in the layout tree. You will typically interact with Node data through the reactive properties rather than manipulating `Node` objects directly.
135
+
136
+ ### Constructor
70
137
 
71
- 🔀 - Used to shift the layout with the `shiftTree` method.
138
+ `new Node(options)`
72
139
 
73
- 🔄 - Triggered when updating the layout using the `updateTree` method.
140
+ - **`options`** (`object`): An object containing node properties like `type`, `host`, `name`, `part`, `dims`, `unId`, and `open`.
74
141
 
75
- 📜 - Represents the information retrieval with the `getElement` method.
142
+ ### Static Cache (`Node.cache`)
76
143
 
77
- 💾 - Indicates the ability to save and recreate layouts with the `jsonify` method.
144
+ The `Node` class contains a static `cache` object. This centralized cache holds the state for the entire layout, including maps of all nodes, dimensions, and the **reactive options** that your UI will consume. **Direct manipulation of the cache is not recommended.**
145
+
146
+ ### Methods
147
+
148
+ #### 💾 `toJSON()`
149
+
150
+ Serializes the node and its entire subtree into a JSON object (`LayoutTree`). This is used to save the current state of the layout.
151
+
152
+ ```javascript
153
+ const rootNode = DynamixLayoutCore._root // Access the static root node
154
+ const layoutJSON = rootNode.toJSON()
155
+ // localStorage.setItem('savedLayout', JSON.stringify(layoutJSON));
156
+ ```
78
157
 
79
158
  ## Example Usage
80
159
 
81
160
  ```javascript
82
- // Initialize Dynamix Layout/Core
83
- const dynamixLayout = new DynamixLayoutCore({
84
- layout: { /* Your serialized layout JSON here */ },
85
- dimension: [800, 600],
86
- coordinate: [100, 100],
87
- tabs: ['tab-1', 'tab-2', 'tab-3'],
88
- range: 3,
89
- });
90
-
91
- // Perform layout shifts
92
- const sizes = dynamixLayout.shiftTree('tab-1', 'tab-2');
93
-
94
- // Handle window resize
95
- dynamixLayout.updateTree();
96
-
97
- // Retrieve tab information
98
- const tabInfo = dynamixLayout.getElement();
99
-
100
- // Generate JSON for storage and future use
101
- const layoutJSON = dynamixLayout.jsonify();
161
+ import { DynamixLayoutCore, Node } from '@dynamix-layout/core'
162
+
163
+ // 1. Initialize the Layout class
164
+ // Provide an options object to the constructor
165
+ const layout = new DynamixLayoutCore({
166
+ tabs: ['editor', 'terminal', 'preview'],
167
+ })
168
+
169
+ // ...or restore a layout from a saved JSON object
170
+ // const savedLayout = JSON.parse(localStorage.getItem('savedLayout'));
171
+ // const layout = new DynamixLayoutCore({ tree: savedLayout });
172
+
173
+ // 2. Set the initial dimensions of your container
174
+ layout.updateDimension({ w: 1200, h: 800, x: 0, y: 0 }, true)
175
+
176
+ // 3. Subscribe to reactive state to render your UI.
177
+ const unsubscribe = Node.cache.nodOpts.onChange((nodeOptionsMap) => {
178
+ console.log('Layout updated!', nodeOptionsMap)
179
+ // Your UI rendering logic here...
180
+ })
181
+
182
+ // 4. Move a tab to a new location
183
+ // (In a real app, you'd get these IDs from the reactive state)
184
+ setTimeout(() => {
185
+ const terminalTabId = 'some-unique-id-for-terminal-tab'
186
+ const editorTabsetId = 'some-unique-id-for-editor-tabset'
187
+
188
+ // Move the terminal tab into the editor's tabset
189
+ layout.updateTree(terminalTabId, editorTabsetId, 'contain')
190
+ }, 2000)
191
+
192
+ // 5. Clean up when the component unmounts
193
+ // unsubscribe();
194
+ // layout.clearAllCache();
102
195
  ```
103
196
 
104
- Dynamix Layout/Core is a powerful tool for managing layouts and tabbed content, making it easier to build dynamic and responsive user interfaces.
197
+ ---
198
+
199
+ <div align="center">
105
200
 
106
- For more details and advanced usage, please refer to the official documentation.
201
+ [![Patreon](https://img.shields.io/badge/Patreon-Support-F96854?style=for-the-badge&logo=patreon)](https://www.patreon.com/akashaman)
202
+ [![Buy Me A Coffee](https://img.shields.io/badge/Buy%20Me%20A%20Coffee-Donate-FFDD00?style=for-the-badge&logo=buy-me-a-coffee)](https://www.buymeacoffee.com/akashaman)
203
+ [![Hire Me](https://img.shields.io/badge/Hire%20Me-Email-blue?style=for-the-badge&logo=gmail)](mailto:sir.akashaman@gmail.com)
107
204
 
108
- **Thank you for choosing Dynamix Layout/Core!** 🚀
205
+ ### Made with ❤️ by [Akash Aman](https://linktr.ee/akash_aman)
109
206
 
207
+ </div>
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2023 Akash
3
+ Copyright (c) 2025 Akash Aman <sir.akashaman@gmail.com> (https://akash.cx)
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
@@ -0,0 +1,57 @@
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});class N{buffer;head=0;tail=0;count=0;capacity;constructor(t=16,e=[]){this.capacity=Math.max(t,e.length),this.buffer=new Array(this.capacity),e.forEach(i=>{this.enqueue(i)})}enqueue(t){this.count===this.capacity&&this.resize(),this.buffer[this.tail]=t,this.tail=(this.tail+1)%this.capacity,this.count++}enqueueFront(t){this.count===this.capacity&&this.resize(),this.head=(this.head-1+this.capacity)%this.capacity,this.buffer[this.head]=t,this.count++}insert(t,e){if(t<0||t>this.count)return!1;if(t===0)return this.enqueueFront(e),!0;if(t===this.count)return this.enqueue(e),!0;this.count===this.capacity&&this.resize();const i=t,n=this.count-t;return i<=n?this.shiftLeft(t,e):this.shiftRight(t,e),this.count++,!0}insertArray(t,e){if(t<0||t>this.count)return!1;if(e.length===0)return!0;if(t===0){for(let d=e.length-1;d>=0;d--)this.enqueueFront(e[d]);return!0}if(t===this.count)return e.forEach(d=>this.enqueue(d)),!0;for(;this.count+e.length>this.capacity;)this.resize();const i=t,n=this.count-t,s=e.length;return i<=n?this.shiftLeftArray(t,e):this.shiftRightArray(t,e),this.count+=s,!0}insertQueue(t,e){if(t<0||t>this.count)return!1;if(e.isEmpty())return!0;const i=e.size();if(t===0){const o=e.toArray();for(let h=o.length-1;h>=0;h--)this.enqueueFront(o[h]);return!0}if(t===this.count){for(const o of e)this.enqueue(o);return!0}for(;this.count+i>this.capacity;)this.resize();const n=e.toArray(),s=t,d=this.count-t;return s<=d?this.shiftLeftArray(t,n):this.shiftRightArray(t,n),this.count+=i,!0}push(t){this.enqueue(t)}unshift(t){this.enqueueFront(t)}dequeue(){if(this.count===0)return;const t=this.buffer[this.head];return this.head=(this.head+1)%this.capacity,this.count--,t}dequeueBack(){if(this.count===0)return;this.tail=(this.tail-1+this.capacity)%this.capacity;const t=this.buffer[this.tail];return this.count--,t}indexOf(t){for(let e=0;e<this.count;e++){const i=(this.head+e)%this.capacity;if(this.buffer[i]===t)return e}return-1}remove(t){const e=this.indexOf(t);return e===-1?!1:(this.removeAt(e),!0)}removeAt(t){if(t<0||t>=this.count)return;if(t===0)return this.dequeue();if(t===this.count-1)return this.dequeueBack();const e=(this.head+t)%this.capacity,i=this.buffer[e],n=t,s=this.count-t-1;return n<=s?this.shiftRightForRemoval(t):this.shiftLeftForRemoval(t),this.count--,i}shift(){return this.dequeue()}pop(){return this.dequeueBack()}fifoAdd(t){this.enqueue(t)}fifoRemove(){return this.dequeue()}filoAdd(t){this.enqueue(t)}filoRemove(){return this.dequeueBack()}lifoAdd(t){this.enqueueFront(t)}lifoRemove(){return this.dequeue()}liloAdd(t){this.enqueueFront(t)}liloRemove(){return this.dequeueBack()}get(t){if(t<0||t>=this.count)return;const e=(this.head+t)%this.capacity;return this.buffer[e]}set(t,e){if(t<0||t>=this.count)return!1;const i=(this.head+t)%this.capacity;return this.buffer[i]=e,!0}peek(){return this.count>0?this.buffer[this.head]:void 0}peekBack(){if(this.count===0)return;const t=(this.tail-1+this.capacity)%this.capacity;return this.buffer[t]}front(){return this.peek()}back(){return this.peekBack()}size(){return this.count}getCapacity(){return this.capacity}isEmpty(){return this.count===0}isFull(){return this.count===this.capacity}clear(){this.head=0,this.tail=0,this.count=0}toArray(){const t=[];for(let e=0;e<this.count;e++){const i=(this.head+e)%this.capacity;t.push(this.buffer[i])}return t}*[Symbol.iterator](){for(let t=0;t<this.count;t++){const e=(this.head+t)%this.capacity;yield this.buffer[e]}}*forward(){for(let t=0;t<this.count;t++){const e=(this.head+t)%this.capacity;yield this.buffer[e]}}*reverse(){for(let t=this.count-1;t>=0;t--){const e=(this.head+t)%this.capacity;yield this.buffer[e]}}*entries(){for(let t=0;t<this.count;t++){const e=(this.head+t)%this.capacity;yield[t,this.buffer[e]]}}*keys(){for(let t=0;t<this.count;t++)yield t}*values(){for(let t=0;t<this.count;t++){const e=(this.head+t)%this.capacity;yield this.buffer[e]}}toString(){return`Queue(${this.toArray().join(", ")})`}resize(){const t=this.capacity*2,e=new Array(t);for(let i=0;i<this.count;i++){const n=(this.head+i)%this.capacity;e[i]=this.buffer[n]}this.buffer=e,this.capacity=t,this.head=0,this.tail=this.count}shiftLeft(t,e){this.head=(this.head-1+this.capacity)%this.capacity;for(let n=0;n<t;n++){const s=(this.head+1+n)%this.capacity,d=(this.head+n)%this.capacity;this.buffer[d]=this.buffer[s]}const i=(this.head+t)%this.capacity;this.buffer[i]=e}shiftRight(t,e){for(let n=this.count-1;n>=t;n--){const s=(this.head+n)%this.capacity,d=(this.head+n+1)%this.capacity;this.buffer[d]=this.buffer[s]}const i=(this.head+t)%this.capacity;this.buffer[i]=e,this.tail=(this.tail+1)%this.capacity}shiftRightForRemoval(t){for(let e=t;e>0;e--){const i=(this.head+e-1)%this.capacity,n=(this.head+e)%this.capacity;this.buffer[n]=this.buffer[i]}this.head=(this.head+1)%this.capacity}shiftLeftForRemoval(t){for(let e=t;e<this.count-1;e++){const i=(this.head+e+1)%this.capacity,n=(this.head+e)%this.capacity;this.buffer[n]=this.buffer[i]}this.tail=(this.tail-1+this.capacity)%this.capacity}shiftLeftArray(t,e){const i=e.length;this.head=(this.head-i+this.capacity)%this.capacity;for(let n=0;n<t;n++){const s=(this.head+i+n)%this.capacity,d=(this.head+n)%this.capacity;this.buffer[d]=this.buffer[s]}for(let n=0;n<i;n++){const s=(this.head+t+n)%this.capacity;this.buffer[s]=e[n]}}shiftRightArray(t,e){const i=e.length;for(let n=this.count-1;n>=t;n--){const s=(this.head+n)%this.capacity,d=(this.head+n+i)%this.capacity;this.buffer[d]=this.buffer[s]}for(let n=0;n<i;n++){const s=(this.head+t+n)%this.capacity;this.buffer[s]=e[n]}this.tail=(this.tail+i)%this.capacity}}function g(I,t=(e,i)=>e===i){let e=I;const i=new Set;let n=[];const s=()=>e,d=(l,f=!1)=>{if(f){e=l;return}t(e,l)||(e=l,i.forEach(m=>m(e)),n.forEach(m=>m(e)),n=[])},o=()=>{i.forEach(l=>l(e)),n.forEach(l=>l(e)),n=[]},h=l=>(i.add(l),()=>i.delete(l)),r=()=>new Promise(l=>{n.push(l)});return{get:s,set:d,onChange:h,nextChange:r,triggerChange:o,onChangePromise:l=>{let f=!0;return(async()=>{for(;f;){const p=await r();if(!f)break;l(p)}})(),()=>{f=!1}}}}function E(I,t){if(I.size!==t.size)return!1;for(const[e,i]of I.entries()){const n=t.get(e);if(!n||!O(i,n))return!1}return!0}function O(I,t){if(I.typNode!==t.typNode||I.nodName!==t.nodName||I.uidNode!==t.uidNode||I.nodPart!==t.nodPart)return!1;const e=I.nodDims,i=t.nodDims;return e.x===i.x&&e.y===i.y&&e.w===i.w&&e.h===i.h}class a{static cache={dimMins:new Map,mapDirs:new Map,tabCnts:new Map,mapElem:new Map,tabOpts:g(new Map,E),nodOpts:g(new Map,E),bndOpts:g(new Map,E)};kids=new N;dims={w:0,h:0,x:0,y:0};unId;next=null;prev=null;type="row";name="";part=0;host=null;open="";constructor(t={}){const e={type:"row",host:null,name:"",part:100,dims:{w:0,h:0,x:0,y:0},unId:crypto.randomUUID(),open:""};this.type=t.type??e.type,this.host=t.host??e.host,this.name=t.name??e.name,this.part=t.part??e.part,this.dims=t.dims??e.dims,this.open=t.open??e.open,this.unId=t.unId||e.unId}addBond(t,e=null){if(!e)return;const i=new x(t,this,e);a.cache.mapElem.set(i.unId,i)}getReqDimension(){const t=a.cache.dimMins.get(this.unId),e=a.cache.tabCnts.get(this.unId),i=Math.max(t.minWidth,e.horizontal*c._minW+Math.max(0,e.horizontal-1)*c._bond),n=Math.max(t.minHeight,e.vertical*c._minH+Math.max(0,e.vertical-1)*c._bond);return{width:i,height:n}}calcDimensions(){const t=a.cache.mapDirs.get(this.unId);if(!this.kids)return;let e=0;const i=a.cache.dimMins.get(this.unId)||{minWidth:0,minHeight:0};let n=0;for(const o of this.kids)e+=o.part;if(e===0)return;let s;t?s=this.dims.w-i.minWidth:s=this.dims.h-i.minHeight;let d=s;for(const o of this.kids){const h=a.cache.dimMins.get(o.unId)||{minWidth:0,minHeight:0};if(this.dims.w<i.minWidth)t?(o.dims.w=h.minWidth,o.dims.h=this.dims.h,o.dims.x=this.dims.x+n,o.dims.y=this.dims.y,n+=o.dims.w+c._bond):(o.dims.h=h.minHeight,o.dims.w=this.dims.w,o.dims.y=this.dims.y+n,o.dims.x=this.dims.x,n+=o.dims.h+c._bond);else{const r=o.part/e,u=Math.floor(s*r);if(o===this.kids.peekBack()){t?(o.dims.w=h.minWidth+d,o.dims.h=this.dims.h,o.dims.x=this.dims.x+n,o.dims.y=this.dims.y,n+=o.dims.w+c._bond):(o.dims.h=h.minHeight+d,o.dims.w=this.dims.w,o.dims.y=this.dims.y+n,o.dims.x=this.dims.x,n+=o.dims.h+c._bond);break}t?(o.dims.w=h.minWidth+u,o.dims.h=this.dims.h,o.dims.x=this.dims.x+n,o.dims.y=this.dims.y,n+=o.dims.w+c._bond):(o.dims.h=h.minHeight+u,o.dims.w=this.dims.w,o.dims.y=this.dims.y+n,o.dims.x=this.dims.x,n+=o.dims.h+c._bond),d-=u}o.next&&(t?o.next.dims={w:c._bond,h:o.dims.h,x:o.dims.x+o.dims.w,y:o.dims.y}:o.next.dims={w:o.dims.w,h:c._bond,x:o.dims.x,y:o.dims.y+o.dims.h})}}toJSON(){const t=[];for(const i of this.kids)t.push(i.toJSON());const e={typNode:this.type,nodPart:this.part,nodName:this.name,uidNode:this.unId};return this.open&&(e.nodOpen=this.open),t.length>0&&(e.nodKids=t),e}}class c{static _root;static _tree;static _minW=40;static _minH=40;static _bond=10;static _inst=null;nodeOps;cntdown=null;tabsIds=new Map;constructor(t={}){const e={tabs:[],tree:null,minW:40,minH:40,bond:10,uqid:"dynamix-layout-root",tabsIds:new Map,...t};this.tabsIds=e.tabsIds,e.tree&&(c._tree=e.tree),c._root=new a({unId:e.uqid,name:e.uqid,type:"row"}),this.nodeOps=g(new Map,E),c._minW=e.minW,c._minH=e.minH,c._bond=e.bond;const i=new N(e.tabs.length,e.tabs);c._tree?this.createNodeLayout():this.createBinaryNodeTreeFromQueue(i),c._inst=this}*JSONLayoutIterator(t){const e=new N;for(e.enqueue(t);!e.isEmpty();){const i=e.dequeue();if(i&&(yield i,i.nodKids&&i.nodKids.length>0))for(const n of i.nodKids)e.enqueue(n)}}*NodeLayoutIterator(t){const e=new N;for(e.enqueue(t);!e.isEmpty();){const i=e.dequeue();if(i&&(a.cache.mapElem.set(i.unId,i),yield i,i.kids.size()>0))for(const n of i.kids)e.enqueue(n)}}*NodeLayoutRecursiveIterator(t){for(const e of t.kids)yield*this.NodeLayoutRecursiveIterator(e);yield t}updateChildDirections(t){const e=a.cache.mapDirs.get(t.unId);if(e===void 0){console.warn(`Cannot update child directions for node ${t.unId}; its own direction is not set.`);return}for(const i of t.kids)a.cache.mapDirs.set(i.unId,!e),i.kids.size()>0&&(i.host=t,this.updateChildDirections(i),i.next&&a.cache.mapDirs.set(i.next.unId,!e))}createNodeLayout(t=c._tree){const e=this.JSONLayoutIterator(t),i=this.NodeLayoutIterator(c._root);for(a.cache.mapDirs.set(c._root.unId,!0);;){const n=e.next(),s=i.next();if(n.done||s.done)break;const d=n.value,o=s.value;!d||!o||this.createNodeTreeFromJSONTree(d,o)}this.calcTabsetCountAndMinDim()}createNodeTreeFromJSONTree(t,e){const i=a.cache.mapDirs.get(e.unId);for(const n of t.nodKids||[]){const s=this.createNodeFromJSON(n),d=e.kids.peekBack();s.host=e,s.addBond(s.host,d),e.kids.enqueue(s),a.cache.mapDirs.set(s.unId,!i)}e.type==="tabset"&&a.cache.mapElem.set(e.unId,e),e.type==="tab"&&a.cache.mapElem.set(e.unId,e)}createBinaryNodeTreeFromQueue(t,e=c._root){const i=new N;for(i.enqueue(e),a.cache.mapDirs.set(c._root.unId,!0);!t.isEmpty();){const n=i.dequeue();if(!n)break;const s=a.cache.mapDirs.get(n.unId);if(t.size()==2){const u=t.dequeue(),l=t.dequeue(),f=new a({type:"tabset",host:n}),m=new a({type:"tabset",host:n}),p=new a({type:"tab",host:f,name:u,unId:this.tabsIds.get(u??"")??crypto.randomUUID()}),w=new a({type:"tab",host:m,name:l,unId:this.tabsIds.get(l??"")??crypto.randomUUID()});f.open=p.name,m.open=w.name,f.kids.enqueue(p),m.kids.enqueue(w),n.kids.enqueue(f),n.kids.enqueue(m),m.addBond(n,f),a.cache.mapDirs.set(f.unId,!s),a.cache.mapDirs.set(m.unId,!s),a.cache.mapElem.set(f.unId,f),a.cache.mapElem.set(m.unId,m),a.cache.mapDirs.set(p.unId,s),a.cache.mapDirs.set(w.unId,s),a.cache.mapElem.set(p.unId,p),a.cache.mapElem.set(w.unId,w),console.log(this.tabsIds);break}const d=t.dequeue(),o=new a({type:"tabset",host:n}),h=new a({type:"row",host:n}),r=new a({type:"tab",host:o,name:d,unId:this.tabsIds.get(d??"")??crypto.randomUUID()});o.open=r.name,o.kids.enqueue(r),n.kids.enqueue(o),n.kids.enqueue(h),h.addBond(n,o),a.cache.mapDirs.set(o.unId,!s),a.cache.mapDirs.set(h.unId,!s),a.cache.mapElem.set(o.unId,o),a.cache.mapDirs.set(r.unId,s),a.cache.mapElem.set(r.unId,r),i.enqueue(h)}this.calcTabsetCountAndMinDim()}createNodeFromJSON(t){const e=new a({type:t.typNode,name:t.nodName,unId:t.uidNode,part:t.nodPart,dims:{w:0,h:0,x:0,y:0},open:typeof t.nodOpen=="string"?t.nodOpen:""});return t.typNode==="tab"&&(e.unId=this.tabsIds.get(t.nodName)||t.uidNode),e}calcTabsetCountAndMinDim(t=c._root,e=!0){t===c._root&&e&&(a.cache.tabCnts.clear(),a.cache.dimMins.clear(),a.cache.mapElem.clear(),a.cache.mapElem.clear(),a.cache.mapElem.clear(),a.cache.mapElem.clear(),a.cache.nodOpts.get().clear(),a.cache.bndOpts.get().clear());for(const i of this.NodeLayoutRecursiveIterator(t)){const n=a.cache.tabCnts,s=a.cache.dimMins;a.cache.mapElem.set(i.unId,i);const d=n.set(i.unId,{horizontal:0,vertical:0}).get(i.unId),o=s.set(i.unId,{minWidth:0,minHeight:0}).get(i.unId),h=a.cache.mapDirs.get(i.unId);if(i.type==="tab"&&(a.cache.mapElem.set(i.unId,i),s.set(i.unId,{minWidth:0,minHeight:0})),i.next&&a.cache.mapElem.set(i.next.unId,i.next),i.type==="tabset"&&(a.cache.mapElem.set(i.unId,i),s.set(i.unId,{minWidth:c._minW,minHeight:c._minH}),h?n.set(i.unId,{horizontal:0,vertical:1}):n.set(i.unId,{horizontal:1,vertical:0})),i.type==="row"){for(const r of i.kids){const u=n.get(r.unId),l=s.get(r.unId);u&&(d.horizontal+=u.horizontal,d.vertical+=u.vertical,h?(o.minHeight=Math.max(o.minHeight,l.minHeight),o.minWidth+=l.minWidth):(o.minHeight+=l.minHeight,o.minWidth=Math.max(o.minWidth,l.minWidth)))}h?o.minWidth+=(i.kids.size()-1)*c._bond:o.minHeight+=(i.kids.size()-1)*c._bond}}}calculateRootAdjustment(){const t=c._root.getReqDimension();let e=!1,i=c._root.dims.w,n=c._root.dims.h;return c._root.dims.w<t.width&&(i=t.width,e=!0),c._root.dims.h<t.height&&(n=t.height,e=!0),e&&(c._root.dims.w=i,c._root.dims.h=n),{adjustedW:i,adjustedH:n,wasAdjusted:e}}calcDimensions(t=c._root,e=!1){const i=new Map,n=new Map,s=new Map;t===c._root&&this.calculateRootAdjustment();for(const d of this.NodeLayoutIterator(t)){d.calcDimensions();const o=a.cache.mapDirs.get(d.unId);if(d.type==="tabset"){const h={typNode:d.type,nodName:d.name,uidNode:d.unId,nodPart:d.part,nodOpen:d.open,nodeDir:o,nodKids:Array.from(d.kids).map(r=>{const u={typNode:r.type,nodName:r.name,uidNode:r.unId,nodPart:r.part,nodOpen:d.open===r.name,nodeDir:!o,nodDims:{...d.dims}};return s.set(r.unId,u),u}),nodDims:{...d.dims}};i.set(d.unId,h)}if(d.next&&d.type!=="tab"){const h={typNode:"bond",nodName:d.name,uidNode:d.next.unId,nodeDir:o,nodPart:0,nodDims:{...d.next.dims}};n.set(d.next.unId,h)}}a.cache.nodOpts.set(i,e),a.cache.bndOpts.set(n,e),a.cache.tabOpts.set(s,e)}updateDimension(t,e=!1,i=2){if(c._root.dims=t,e){this.calcDimensions(c._root);return}this.cntdown&&(clearTimeout(this.cntdown),this.cntdown=null),this.cntdown=setTimeout(()=>{this.cntdown=null,this.calcDimensions()},i)}updateSlider(t,e,i=!1,n=2){if(i){this.updateSliderDimension(t,e);return}this.cntdown&&(clearTimeout(this.cntdown),this.cntdown=null),this.cntdown=setTimeout(()=>{this.cntdown=null,this.updateSliderDimension(t,e)},n)}updateSliderDimension(t,e){const i=a.cache.mapElem.get(t);if(!i||!(i instanceof x)){console.warn(`Bond with id ${t} not found or is not a Bond instance`);return}const n=a.cache.mapDirs.get(i.host.unId),s=i.prev,d=i.next,o=i.host;if(!s||!d||!o){console.warn("Missing prev, next, or host node",s,d,o);return}const h=a.cache.dimMins.get(s.unId)||{minWidth:0,minHeight:0},r=a.cache.dimMins.get(d.unId)||{minWidth:0,minHeight:0},u=c._bond/2;if(n){const l=d.dims.x+d.dims.w,f=s.dims.x+h.minWidth+u,m=l-r.minWidth-u,p=Math.max(f,Math.min(m,e.x));i.dims.x=p-u,s.dims.w=i.dims.x-s.dims.x,d.dims.x=p+u,d.dims.w=l-d.dims.x;const w=Math.max(0,s.dims.w-h.minWidth),k=Math.max(0,d.dims.w-r.minWidth),b=w+k,y=s.part+d.part;b>0?(s.part=w/b*y,d.part=k/b*y):(s.part=y/2,d.part=y/2)}else{const l=d.dims.y+d.dims.h,f=s.dims.y+h.minHeight+u,m=l-r.minHeight-u,p=Math.max(f,Math.min(m,e.y));i.dims.y=p-u,s.dims.h=i.dims.y-s.dims.y,d.dims.y=p+u,d.dims.h=l-d.dims.y;const w=Math.max(0,s.dims.h-h.minHeight),k=Math.max(0,d.dims.h-r.minHeight),b=w+k,y=s.part+d.part;b>0?(s.part=w/b*y,d.part=k/b*y):(s.part=y/2,d.part=y/2)}this.calcDimensions(o)}updateTree(t,e,i){const n=a.cache.mapElem.get(t);let s=a.cache.mapElem.get(e);return!n||!(n instanceof a)||!s||!(s instanceof a)?(console.warn(`Source node ${t} not found or is not a Node instance`),!1):n?.type=="tab"&&n.host===s&&s.kids.size()<2?(console.warn("Cannot move to self as it has only one tab"),!1):n?.type=="tabset"&&s?.host===n?(console.warn("Cannot move tabset to self as it is already a child"),!1):!n||!s?(console.warn(`Source or destination node not found: ${t}, ${e}`),!1):n===s?(console.warn("Source and destination nodes are the same, no action taken."),!1):!n.host||!s.host&&s.type!=="row"?(console.warn(`Source node or destination node's host is null: ${n.unId}, ${s.unId}`),!1):s.type==="row"&&i==="contain"?(console.warn(`Cannot move to a row with 'contain' layout: ${s.unId}`),!1):n.type==="row"?!1:(s.type==="tabset"&&i==="contain"&&(s=s.kids.peekBack()||s),s.type==="tab"&&(i==="contain"||i==="left"||i==="right")?this.moveNodeAsTab(n,s,i):s.type==="row"&&i!=="contain"?this.moveRelativeToRoot(n,s,i):s.type==="tabset"&&i!=="contain"&&this.moveRelativeToTabset(n,s,i),this.calcTabsetCountAndMinDim(),this.calcDimensions(c._root,!0),!0)}moveNodeAsTab(t,e,i){if(!e||!e.host){console.warn(`Destination node ${e.unId} has no host, cannot move.`);return}this.removeNode(t);const n=e.host,s=n.kids.indexOf(e);if(s===void 0||s===-1)return;const d=i==="contain"||i==="left",o=d?s:s+1,h=n.kids.get(o+1),r=n.kids.get(o-1),u=e.next,l=e.prev;if(!d&&u?(a.cache.mapElem.delete(u.unId),a.cache.nodOpts.get().delete(u.unId)):d&&l&&(a.cache.mapElem.delete(l.unId),a.cache.nodOpts.get().delete(l.unId)),t.type=="tab")d?(r&&t.addBond(n,r),e.addBond(n,t)):(t.addBond(n,e),h&&h.addBond(n,t)),n.kids.insert(o,t),t.host=n,n.open=t.name;else if(t.type=="tabset"){const f=t.kids.peek(),m=t.kids.peekBack();d?(f&&r&&f.addBond(n,r),m&&e&&e.addBond(n,m)):(f&&e&&f.addBond(n,e),m&&h&&h.addBond(n,m)),n.kids.insertQueue(o,t.kids);for(const p of t.kids)p.host=n,p.next&&(p.next.host=n);n.open=m?m.name:""}this.updateChildDirections(n)}moveRelativeToRoot(t,e,i){this.removeNode(t);const n=a.cache.mapDirs.get(e.unId),s=i==="top"||i==="left";if(t.type==="tab"){const d=new a({type:"tabset",host:e.host});d.kids.enqueue(t),t.host=d,d.open=t.name,n==!1?i==="left"||i==="right"?this.insertNodeWithNewParent(d,e,s):this.insertNode(e,d,s):i==="top"||i==="bottom"?this.insertNodeWithNewParent(d,e,s):this.insertNode(e,d,s)}else t.type==="tabset"&&(n==!1?i==="left"||i==="right"?this.insertNodeWithNewParent(t,e,s):this.insertNode(e,t,s):i==="top"||i==="bottom"?this.insertNodeWithNewParent(t,e,s):this.insertNode(e,t,s))}moveRelativeToTabset(t,e,i){this.removeNode(t);const n=a.cache.mapDirs.get(e.unId),s=i==="top"||i==="left";if(t.type==="tab"){const d=new a({type:"tabset",host:e.host});d.kids.enqueue(t),t.host=d,d.open=t.name,n==!1?i==="top"||i==="bottom"?this.insertNodeWithNewParent(d,e,s):this.insertNode(e,d,s):i==="left"||i==="right"?this.insertNodeWithNewParent(d,e,s):this.insertNode(e,d,s)}else t.type==="tabset"&&(n==!1?i==="top"||i==="bottom"?this.insertNodeWithNewParent(t,e,s):this.insertNode(e,t,s):i==="left"||i==="right"?this.insertNodeWithNewParent(t,e,s):this.insertNode(e,t,s))}insertNode(t,e,i){const n=t.host;if(t==c._root){const l=c._root.kids.peek(),f=c._root.kids.peekBack();i?(c._root.kids.enqueueFront(e),l&&l.addBond(c._root,e)):(c._root.kids.enqueue(e),f&&e.addBond(c._root,f)),e.host=c._root,this.updateChildDirections(c._root);return}if(!n){console.warn(`Destination node ${t.unId} has no host, cannot insert.`);return}const s=n.kids.indexOf(t);if(s===-1){console.warn(`Destination node ${t.unId} not found in its host's kids.`);return}const d=a.cache.mapDirs.get(n.unId);d&&a.cache.mapDirs.set(e.unId,!d);const o=n.kids.get(s+1),h=n.kids.get(s-1),r=t.next,u=t.prev;e.host=n,i?(n.kids.insert(s,e),t.addBond(n,e),h&&e.addBond(n,h),u&&(a.cache.mapElem.delete(u.unId),a.cache.nodOpts.get().delete(u.unId))):(n.kids.insert(s+1,e),e.addBond(n,t),o&&o.addBond(n,e),r&&(a.cache.mapElem.delete(r.unId),a.cache.nodOpts.get().delete(r.unId))),this.updateChildDirections(n)}insertNodeWithNewParent(t,e,i){const n=new N,s=new a({type:"tabset",host:e.host});if(!e||!t){console.warn(`Destination node ${e.unId} has no host, cannot insert.`);return}if(e===c._root){const o=new a({type:"row",host:e});if(e.kids.size()==1&&e.kids.peek()?.type==="tabset"){const h=e.kids.dequeue();if(!h){console.warn(`No kid found in destination node ${e.unId}, cannot insert.`);return}i?(o.kids.enqueue(t),o.kids.enqueue(h),e.kids.enqueue(o),h.addBond(o,t)):(o.kids.enqueue(h),o.kids.enqueue(t),t.addBond(o,h),e.kids.enqueue(o)),t.host=o,h.host=o}else if(e.kids.size()==1&&e.kids.peek()?.type==="row"){const h=e.kids.peek(),r=h?.kids.peek(),u=h?.kids.peekBack();i&&h?(h.kids.enqueueFront(t),r&&r.addBond(h,t)):h&&(h.kids.enqueue(t),u&&t.addBond(h,u)),t.host=h}else if(e.kids.size()>1){const h=new a({type:"row",host:e}),r=new a({type:"row",host:h});for(const u of e.kids)r.kids.enqueue(u),u.host=r,u.next&&(u.next.host=r);t.host=h,e.kids.clear(),i?(h.kids.enqueueFront(t),h.kids.enqueue(r),r.addBond(h,t)):(h.kids.enqueue(r),h.kids.enqueue(t),t.addBond(h,r)),e.kids.enqueue(h)}this.updateChildDirections(e);return}t.host=e,s.host=e,s.kids=e.kids,s.open=e.open;const d=a.cache.mapDirs.get(e.unId);for(const o of s.kids)o.host=s,o.next&&(o.next.host=s),a.cache.mapDirs.set(o.unId,d);for(const o of t.kids)o.host=t,o.next&&(o.next.host=t),a.cache.mapDirs.set(o.unId,d);a.cache.mapDirs.set(s.unId,!d),a.cache.mapDirs.set(t.unId,!d),i?(n.enqueue(t),n.enqueue(s),e.kids=n,e.type="row",s.addBond(e,t)):(n.enqueue(s),n.enqueue(t),e.kids=n,e.type="row",t.addBond(e,s))}moveAdjacentNodeToGrandParent(t){if(!t.host||!t.host.host){console.warn(`Source node ${t.unId} has no host, cannot move.`);return}const e=t.host,i=t.host.host,n=i.kids.indexOf(e),s=i.kids.get(n-1),d=i.kids.get(n+1),o=t.kids.peek(),h=t.kids.peekBack();this.removeKid(e);let r=n;if(t.type=="row"&&e){s&&o&&o.addBond(i,s),d&&h&&d.addBond(i,h);for(const u of t.kids)u.host=i,u.next&&(u.next.host=i),i.kids.insert(r,u),a.cache.mapDirs.set(u.unId,!a.cache.mapDirs.get(i.unId)),a.cache.dimMins.delete(u.unId),r++}else if(t.type=="tabset"){s&&t.addBond(i,s),d&&d.addBond(i,t),i.kids.insert(r,t),t.host=i,a.cache.mapDirs.set(t.unId,!a.cache.mapDirs.get(i.unId));for(const u of t.kids)a.cache.mapDirs.set(u.unId,a.cache.mapDirs.get(i.unId)),a.cache.dimMins.delete(u.unId)}}removeRelation(t,e=!0){const i=t.host,n=t.prev,s=t.next;if(t.host=null,t.next=null,t.prev=null,n&&(n.next=null),s&&(s.prev=null),!e)return t;n&&s&&n.prev&&s.next?n.prev.addBond(i,s.next):n&&n.prev?n.prev.next=null:s&&s.next&&(s.next.prev=null)}removeNode(t){if(!t.host){console.warn("Kid node has no host, cannot remove.");return}const e=t?.host,i=e?.host;if(this.removeKid(t),t.type==="tabset"&&e.kids.size()===1){const n=e.kids.peek();n&&this.moveAdjacentNodeToGrandParent(n)}else if(t.type==="tab"&&e.kids.size()===0&&i.kids.size()===2){this.removeKid(e);const n=i?.kids.peek();n&&this.moveAdjacentNodeToGrandParent(n)}else if(t.type==="tab"&&e.kids.size()===0&&i.kids.size()>2)this.removeKid(e);else if(t.type==="tab"&&e.open===t.name&&e.kids.size()>0){const n=e.kids.peek();n&&(e.open=n.name)}}removeKid(t){if(!t.host){console.warn("Kid node has no host, cannot remove.");return}const e=t.host,i=e.kids.indexOf(t),n=e.kids.get(i+1),s=e.kids.get(i-1),d=t.next,o=t.prev;if(i===-1){console.warn("Kid node not found in its host's kids.");return}d&&(a.cache.mapElem.delete(d.unId),a.cache.nodOpts.get().delete(d.unId)),o&&(a.cache.mapElem.delete(o.unId),a.cache.nodOpts.get().delete(o.unId)),n&&s?n.addBond(e,s):n?n.prev=null:s&&(s.next=null),e.kids.removeAt(i),a.cache.mapElem.delete(t.unId),a.cache.dimMins.delete(t.unId),a.cache.mapDirs.delete(t.unId),a.cache.tabCnts.delete(t.unId),t.type==="tabset"&&a.cache.mapElem.delete(t.unId),t.type==="tab"&&a.cache.mapElem.delete(t.unId),t.host=null,t.next=null,t.prev=null}clearAllCache(){a.cache.dimMins.clear(),a.cache.mapDirs.clear(),a.cache.tabCnts.clear(),a.cache.mapElem.clear(),a.cache.nodOpts.get().clear(),a.cache.bndOpts.get().clear()}}class x{dims={w:0,h:0,x:0,y:0};unId=crypto.randomUUID();next=null;prev=null;host=null;constructor(t=null,e=null,i=null){this.host=t,this.next=e,this.prev=i,this.next&&(this.next.prev=this),this.prev&&(this.prev.next=this)}toJSON(){return{nodName:this.host?.name||"",typNode:"bond",uidNode:this.unId,nodPart:0,nodOpen:"",nodKids:[]}}}(()=>{if(typeof window>"u")return;const I="color: #03A9F4; font-weight: bold; line-height: 1.2;",t="color: #E0E0E0; font-size: 12px;",e="color: #42a5f5; font-size: 12px;",i="color: #9E9E9E; font-size: 10px;",n=`
2
+ ██████╗ ██╗ ██╗ ███╗ ██╗ █████╗ ███╗ ███╗ ██████╗ ██╗ ██╗
3
+ ██╔══██╗╚██╗ ██╔╝ ████╗ ██║ ██╔══██╗ ████╗ ████║ ╚═██╔═╝ ╚██╗██╔╝
4
+ ██║ ██║ ╚████╔╝ ██╔██╗ ██║ ███████║ ██╔████╔██║ ██║ ╚███╔╝
5
+ ██║ ██║ ╚██╔╝ ██║╚██╗██║ ██╔══██║ ██║╚██╔╝██║ ██║ ██╔██╗
6
+ ██████╔╝ ██║ ██║ ╚████║ ██║ ██║ ██║ ╚═╝ ██║ ██████╗ ██╔╝ ██╗
7
+ ╚═════╝ ╚═╝ ╚═╝ ╚═══╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝
8
+ ██╗ █████╗ ██╗ ██╗ ██████╗ ██╗ ██╗████████╗
9
+ ██║ ██╔══██╗ ╚██╗ ██╔╝ ██╔═══██╗ ██║ ██║╚══██╔══╝
10
+ ██║ ███████║ ╚████╔╝ ██║ ██║ ██║ ██║ ██║
11
+ ██║ ██╔══██║ ╚██╔╝ ██║ ██║ ██║ ██║ ██║
12
+ ███████╗ ██║ ██║ ██║ ╚██████╔╝ ╚█████╔╝ ██║
13
+ ╚══════╝ ╚═╝ ╚═╝ ╚═╝ ╚═════╝ ╚════╝ ╚═╝
14
+ `;console.groupCollapsed("%cDYNAMIX LAYOUT (click to expand)","color: #03A9F4; font-weight: bold; font-size: 14px;"),console.log(`%c${n}`,I),console.log("%c A powerful, dynamic layout system 🚀",t),console.log(`%c ⚡ For docs and more info,
15
+ ⚡ visit: https://github.com/akash-aman/dynamix-layout`,e),console.log(`%cMIT License
16
+
17
+ Copyright (c) 2025 Akash Aman <sir.akashaman@gmail.com> (https://akash.cx)
18
+
19
+ Permission is hereby granted, free of charge, to any person obtaining a copy
20
+ of this software and associated documentation files (the "Software"), to deal
21
+ in the Software without restriction, including without limitation the rights
22
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
23
+ copies of the Software, and to permit persons to whom the Software is
24
+ furnished to do so, subject to the following conditions:
25
+
26
+ The above copyright notice and this permission notice shall be included in all
27
+ copies or substantial portions of the Software.
28
+
29
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
30
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
31
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
32
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
33
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
34
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
35
+ SOFTWARE.
36
+ `,i),console.groupEnd(),typeof window<"u"&&(window.__DYNAMIX_LAYOUT__={__LICENSE__:`MIT License
37
+
38
+ Copyright (c) 2025 Akash Aman <sir.akashaman@gmail.com> (https://akash.cx)
39
+
40
+ Permission is hereby granted, free of charge, to any person obtaining a copy
41
+ of this software and associated documentation files (the "Software"), to deal
42
+ in the Software without restriction, including without limitation the rights
43
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
44
+ copies of the Software, and to permit persons to whom the Software is
45
+ furnished to do so, subject to the following conditions:
46
+
47
+ The above copyright notice and this permission notice shall be included in all
48
+ copies or substantial portions of the Software.
49
+
50
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
51
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
52
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
53
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
54
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
55
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
56
+ SOFTWARE.
57
+ `,__LAYOUT__:c})})();exports.Bond=x;exports.DynamixLayoutCore=c;exports.Node=a;exports.Queue=N;exports.areNodeOptionsEqual=O;exports.areNodeOptionsMapEqual=E;exports.createReactiveState=g;