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

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.
Files changed (47) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/README.md +155 -61
  3. package/{LICENSE → dist/LICENSE} +1 -1
  4. package/dist/core.cjs.js +57 -0
  5. package/dist/core.cjs.js.br +0 -0
  6. package/dist/core.cjs.js.gz +0 -0
  7. package/dist/core.cjs.js.map +1 -0
  8. package/dist/core.es.js +1025 -0
  9. package/dist/core.es.js.br +0 -0
  10. package/dist/core.es.js.gz +0 -0
  11. package/dist/core.es.js.map +1 -0
  12. package/dist/core.iife.js +57 -1
  13. package/dist/core.iife.js.br +0 -0
  14. package/dist/core.iife.js.gz +0 -0
  15. package/dist/core.iife.js.map +1 -0
  16. package/dist/core.umd.js +57 -1
  17. package/dist/core.umd.js.br +0 -0
  18. package/dist/core.umd.js.gz +0 -0
  19. package/dist/core.umd.js.map +1 -0
  20. package/dist/types/app/comparator.d.ts +3 -0
  21. package/dist/types/app/dynamix.d.ts +97 -0
  22. package/dist/types/app/index.d.ts +4 -64
  23. package/dist/types/app/queue.d.ts +217 -0
  24. package/dist/types/app/reactive-state.d.ts +3 -0
  25. package/dist/types/index.d.ts +2 -2
  26. package/dist/types/type/index.d.ts +54 -0
  27. package/package.json +58 -29
  28. package/dist/core.js +0 -1
  29. package/dist/core.mjs +0 -244
  30. package/dist/types/lib/Constant.d.ts +0 -14
  31. package/dist/types/lib/Element.d.ts +0 -22
  32. package/dist/types/lib/Helper.d.ts +0 -21
  33. package/dist/types/lib/Method.d.ts +0 -1
  34. package/dist/types/lib/index.d.ts +0 -4
  35. package/dist/types/types/Element.d.ts +0 -103
  36. package/dist/types/types/Method.d.ts +0 -5
  37. package/dist/types/types/index.d.ts +0 -2
  38. package/src/app/index.ts +0 -291
  39. package/src/index.ts +0 -3
  40. package/src/lib/Constant.ts +0 -17
  41. package/src/lib/Element.ts +0 -66
  42. package/src/lib/Helper.ts +0 -259
  43. package/src/lib/Method.ts +0 -12
  44. package/src/lib/index.ts +0 -4
  45. package/src/types/Element.ts +0 -116
  46. package/src/types/Method.ts +0 -4
  47. package/src/types/index.ts +0 -2
package/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # @dynamix-layout/core
2
2
 
3
+ ## 0.0.5
4
+
5
+ ### Patch Changes
6
+
7
+ - Refactored layout core and added unit tests for reactive state and layout logic
8
+ - Replaced legacy `Layout` class with modular utilities: `Queue` and `createReactiveState`.
9
+ - Improved layout shifting algorithm (`shiftTree`) and bond-based slider behavior.
10
+ - Added comprehensive unit tests for layout validation, tree integrity, and reactive state handling.
11
+ - Simplified exports and cleaned up `index.ts`, `.gitignore`, and `package.json` structure.
12
+ - Refactored `vite.config.ts`, `tsconfig.json`, and `vitest.config.ts` for clarity and consistency.
13
+ - Added license metadata to Vite config and updated author name in LICENSE.
14
+
3
15
  ## 0.0.2-beta.0
4
16
 
5
17
  ### Patch Changes
package/README.md CHANGED
@@ -1,109 +1,203 @@
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
+ ## Core Classes
22
+
23
+ The package is built around three primary classes: `DynamixLayoutCore`, `Node`, and `Bond`.
8
24
 
9
- ## Options Object Parameters
25
+ 1. **`DynamixLayoutCore`**: The main controller class that you instantiate to create and manage the entire layout. It serves as the primary public API.
26
+ 2. **`Node`**: The fundamental building block of the layout tree. Each `Node` can be a `row`, a `tabset`, or a `tab`.
27
+ 3. **`Bond`**: A special object that represents the draggable separator between two nodes, allowing for resizing.
10
28
 
11
- When initializing the package, you can provide an options object with the following parameters:
29
+ ---
12
30
 
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`.
31
+ ## `DynamixLayoutCore` Class
14
32
 
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`.
33
+ The `DynamixLayoutCore` class is the central point of control for your entire layout configuration.
16
34
 
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]`.
35
+ ### Constructor
18
36
 
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]`.
37
+ When initializing the `DynamixLayoutCore` class, you provide a single **options object**.
20
38
 
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', ...]`.
39
+ `new DynamixLayoutCore(options)`
22
40
 
23
- ## Allowed Parameters
41
+ - **`options`** (`object`): An object containing configuration properties.
42
+ - **`tabs`** (`string[]`): An array of tab names to generate an initial binary tree layout. Defaults to `[]`.
43
+ - **`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`.
44
+ - **`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.
45
+ - **`minW`** (`number`): The minimum width for a `tabset`. Defaults to `40`.
46
+ - **`minH`** (`number`): The minimum height for a `tabset`. Defaults to `40`.
47
+ - **`bond`** (`number`): The width or height (in pixels) of the draggable separator (`Bond`) between nodes. Defaults to `10`.
24
48
 
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.
49
+ ### Reactive Properties
30
50
 
31
- ## Methods
51
+ The layout's state is exposed through static reactive properties on the `Node` class. You can subscribe to these to drive your UI.
32
52
 
33
- ### 1. shiftTree(srcId, destId)
53
+ - **`Node.cache.nodOpts`**: A reactive map of all `tabset` nodes and their options.
54
+ - **`Node.cache.bndOpts`**: A reactive map of all `bond` objects.
55
+ - **`Node.cache.tabOpts`**: A reactive map of all `tab` nodes within their respective tabsets.
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
+ ### Methods
58
+
59
+ #### 🌳 `updateTree(src, des, layout)`
60
+
61
+ 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`).
62
+
63
+ - **`src`** (`string`): The unique ID of the node to move (can be a `tab` or a `tabset`).
64
+ - **`des`** (`string`): The unique ID of the destination node.
65
+ - **`layout`** (`'top' | 'bottom' | 'left' | 'right' | 'contain'`): Specifies how the source should be placed relative to the destination.
66
+ - `top`, `bottom`, `left`, `right`: Places the source node by splitting the destination area.
67
+ - `contain`: Places a source `tab` into the destination `tabset`.
68
+
69
+ **Returns**: `boolean` - `true` if the update was successful, `false` otherwise.
36
70
 
37
- Example:
38
71
  ```javascript
39
- const sizes = dynamixLayout.shiftTree('tab-1', 'tab-2');
72
+ // Moves the node with 'sidebar-id' to be to the left of 'main-content-id'
73
+ layout.updateTree('sidebar-id', 'main-content-id', 'left')
40
74
  ```
41
75
 
42
- ### 2. updateTree()
76
+ ---
77
+
78
+ #### 📏 `updateDimension(dim, disableTimeout, timeout)`
79
+
80
+ Recalculates all node dimensions within the layout, typically after the main container has been resized.
81
+
82
+ - **`dim`** (`{ w, h, x, y }`): An object representing the new dimensions of the root container.
83
+ - **`disableTimeout`** (`boolean`): If `true`, the update runs instantly. Otherwise, it's debounced. Defaults to `false`.
84
+ - **`timeout`** (`number`): The debounce delay in milliseconds. Defaults to `2`.
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
+ <!-- end list -->
45
87
 
46
- Example:
47
88
  ```javascript
48
- dynamixLayout.updateTree();
89
+ // On window resize, update the layout dimensions
90
+ layout.updateDimension({
91
+ w: window.innerWidth,
92
+ h: window.innerHeight,
93
+ x: 0,
94
+ y: 0,
95
+ })
49
96
  ```
50
97
 
51
- ### 3. getElement()
98
+ ---
52
99
 
53
- The `getElement` method returns information about all the tabs and their sizes. It is useful for retrieving the current state of the layout.
100
+ #### ↔️ `updateSlider(id, dim, disableTimeout, timeout)`
101
+
102
+ Updates the layout in response to a user dragging a `Bond` (slider).
103
+
104
+ - **`id`** (`string`): The unique ID of the `Bond` being moved.
105
+ - **`dim`** (`{ x, y }`): An object with the new coordinates of the slider.
106
+ - **`disableTimeout`** (`boolean`): If `true`, the update runs instantly. Defaults to `false`.
107
+ - **`timeout`** (`number`): The debounce delay in milliseconds. Defaults to `2`.
108
+
109
+ <!-- end list -->
54
110
 
55
- Example:
56
111
  ```javascript
57
- const tabInfo = dynamixLayout.getElement();
112
+ // When a user drags a separator
113
+ layout.updateSlider('bond-123', { x: 450, y: 300 })
58
114
  ```
59
115
 
60
- ### 4. jsonify()
116
+ ---
117
+
118
+ #### 🗑️ `clearAllCache()`
61
119
 
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.
120
+ Clears all internal caches for nodes, bonds, dimensions, and other layout data. Use this when completely destroying or resetting the layout.
63
121
 
64
- Example:
65
122
  ```javascript
66
- const layoutJSON = dynamixLayout.jsonify();
123
+ layout.clearAllCache()
67
124
  ```
68
125
 
69
- ## Emojis
126
+ ---
127
+
128
+ ## `Node` Class
129
+
130
+ 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.
131
+
132
+ ### Constructor
70
133
 
71
- 🔀 - Used to shift the layout with the `shiftTree` method.
134
+ `new Node(options)`
72
135
 
73
- 🔄 - Triggered when updating the layout using the `updateTree` method.
136
+ - **`options`** (`object`): An object containing node properties like `type`, `host`, `name`, `part`, `dims`, `unId`, and `open`.
74
137
 
75
- 📜 - Represents the information retrieval with the `getElement` method.
138
+ ### Static Cache (`Node.cache`)
76
139
 
77
- 💾 - Indicates the ability to save and recreate layouts with the `jsonify` method.
140
+ 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.**
141
+
142
+ ### Methods
143
+
144
+ #### 💾 `toJSON()`
145
+
146
+ Serializes the node and its entire subtree into a JSON object (`LayoutTree`). This is used to save the current state of the layout.
147
+
148
+ ```javascript
149
+ const rootNode = DynamixLayoutCore._root // Access the static root node
150
+ const layoutJSON = rootNode.toJSON()
151
+ // localStorage.setItem('savedLayout', JSON.stringify(layoutJSON));
152
+ ```
78
153
 
79
154
  ## Example Usage
80
155
 
81
156
  ```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();
157
+ import { DynamixLayoutCore, Node } from '@dynamix-layout/core'
158
+
159
+ // 1. Initialize the Layout class
160
+ // Provide an options object to the constructor
161
+ const layout = new DynamixLayoutCore({
162
+ tabs: ['editor', 'terminal', 'preview'],
163
+ })
164
+
165
+ // ...or restore a layout from a saved JSON object
166
+ // const savedLayout = JSON.parse(localStorage.getItem('savedLayout'));
167
+ // const layout = new DynamixLayoutCore({ tree: savedLayout });
168
+
169
+ // 2. Set the initial dimensions of your container
170
+ layout.updateDimension({ w: 1200, h: 800, x: 0, y: 0 }, true)
171
+
172
+ // 3. Subscribe to reactive state to render your UI.
173
+ const unsubscribe = Node.cache.nodOpts.subscribe((nodeOptionsMap) => {
174
+ console.log('Layout updated!', nodeOptionsMap)
175
+ // Your UI rendering logic here...
176
+ })
177
+
178
+ // 4. Move a tab to a new location
179
+ // (In a real app, you'd get these IDs from the reactive state)
180
+ setTimeout(() => {
181
+ const terminalTabId = 'some-unique-id-for-terminal-tab'
182
+ const editorTabsetId = 'some-unique-id-for-editor-tabset'
183
+
184
+ // Move the terminal tab into the editor's tabset
185
+ layout.updateTree(terminalTabId, editorTabsetId, 'contain')
186
+ }, 2000)
187
+
188
+ // 5. Clean up when the component unmounts
189
+ // unsubscribe();
190
+ // layout.clearAllCache();
102
191
  ```
103
192
 
104
- Dynamix Layout/Core is a powerful tool for managing layouts and tabbed content, making it easier to build dynamic and responsive user interfaces.
193
+ ---
194
+
195
+ <div align="center">
105
196
 
106
- For more details and advanced usage, please refer to the official documentation.
197
+ [![Patreon](https://img.shields.io/badge/Patreon-Support-F96854?style=for-the-badge&logo=patreon)](https://www.patreon.com/akashaman)
198
+ [![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)
199
+ [![Hire Me](https://img.shields.io/badge/Hire%20Me-Email-blue?style=for-the-badge&logo=gmail)](mailto:sir.akashaman@gmail.com)
107
200
 
108
- **Thank you for choosing Dynamix Layout/Core!** 🚀
201
+ ### Made with ❤️ by [Akash Aman](https://linktr.ee/akash_aman)
109
202
 
203
+ </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;
Binary file
Binary file