@dynamix-layout/solid 0.0.1

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 ADDED
@@ -0,0 +1,14 @@
1
+ # @dynamix-layout/solid
2
+
3
+ ## 0.0.1
4
+
5
+ ### Patch Changes
6
+
7
+ - [#52](https://github.com/akash-aman/dynamix-layout/pull/52) [`b6568bc`](https://github.com/akash-aman/dynamix-layout/commit/b6568bc6dac744ca18e066541b0306439b51738f) Thanks [@akash-aman](https://github.com/akash-aman)! - @dynamix-layout/solid
8
+ • Introduced SolidJS wrapper for @dynamix-layout/core.
9
+ • Added SolidJS and SolidStart usage examples.
10
+ • Enhanced default CSS styles.
11
+ • Added support for export & save layout as JSON via callback.
12
+ • Fixed TypeScript type definitions.
13
+ - Updated dependencies [[`b6568bc`](https://github.com/akash-aman/dynamix-layout/commit/b6568bc6dac744ca18e066541b0306439b51738f)]:
14
+ - @dynamix-layout/core@0.0.8
package/README.md ADDED
@@ -0,0 +1,204 @@
1
+ <div align="center">
2
+
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
+
8
+ </div>
9
+
10
+ ## 🚀 @dynamix-layout/solid
11
+
12
+ ### The official SolidJS wrapper for `@dynamix-layout/core`
13
+
14
+ ## Overview
15
+
16
+ **@dynamix-layout/solid** brings the power of the `@dynamix-layout/core` engine to **SolidJS** applications. It provides a flexible `<DynamixLayout />` component and an advanced `useDynamixLayout` hook to create fully dynamic, resizable, and draggable tab-based layouts with ease. Build complex UIs like VS Code or JSFiddle in minutes. 🔨
17
+
18
+ -----
19
+
20
+ ### Made with ❤️ by [Akash Aman](https://linktr.ee/akash_aman)
21
+
22
+ -----
23
+
24
+ ## 📦 Installation
25
+
26
+ ```bash
27
+ npm install @dynamix-layout/solid @dynamix-layout/core
28
+ ```
29
+
30
+ -----
31
+
32
+ ## 🏁 Getting Started
33
+
34
+ The easiest way to get started is by using the `<DynamixLayout />` component. Provide it with an array of `[id, component]` tuples.
35
+
36
+ ```jsx
37
+ import { DynamixLayout } from '@dynamix-layout/solid';
38
+ import '@dynamix-layout/solid/style.css'; // Don't forget to import the default style
39
+ import type { Component } from 'solid-js';
40
+
41
+ const App: Component = () => {
42
+ // 1. Define your tabs as an array of [id, component] tuples
43
+ const myTabs = [
44
+ ['editor', <div>This is my editor!</div>],
45
+ ['terminal', <div>This is the terminal.</div>],
46
+ ['preview', <div>Live preview here.</div>],
47
+ ];
48
+
49
+ return (
50
+ <div
51
+ style={{
52
+ width: '100vw',
53
+ height: '100vh',
54
+ }}
55
+ >
56
+ {/* 2. Render the DynamixLayout component with your tabs */}
57
+ <DynamixLayout tabs={myTabs} />
58
+ </div>
59
+ );
60
+ };
61
+
62
+ export default App;
63
+ ```
64
+
65
+ -----
66
+
67
+ ## 🧩 `<DynamixLayout />` Component API
68
+
69
+ The `<DynamixLayout />` component is the primary way to use this package. It's highly configurable through its props.
70
+
71
+ ### Core Functionality
72
+
73
+ | Prop | Type | Description | Default |
74
+ | :--- | :--- | :--- | :--- |
75
+ | **`tabs`** (required) | `[string, JSX.Element][]` | An array of `[id, component]` tuples for your tabs. | |
76
+ | `layoutTree` | `LayoutTree` | A serialized layout object from a previous session to restore a saved layout. | `null` |
77
+ | `tabNames` | `Map<string, string>` | An optional map to provide friendly display names for your tabs. | `new Map()` |
78
+ | `enableTabbar` | `boolean` | If `true`, renders the draggable tab bar on top of each tab panel. | `true` |
79
+ | `tabHeadHeight` | `number` | The height of the tab bar in pixels. | `40` |
80
+ | `pad` | `{ t, b, l, r }` | Padding for the root layout container in pixels. | `{ t: 0, b: 0, l: 0, r: 0 }` |
81
+ | `minTabWidth` | `number` | Minimum width of a tab panel in pixels. | `40` |
82
+ | `minTabHeight` | `number` | Minimum height of a tab panel in pixels. | `40` |
83
+ | `bondWidth` | `number` | The width/height of the draggable slider between panels in pixels. | `10` |
84
+ | `rootId` | `string` | The HTML `id` for the root `<div>` element of the layout. | `"dynamix-layout-root"` |
85
+ | `disableResizeTimeout` | `boolean` | Disables debounce on window resize for faster updates. Can impact performance. | `true` |
86
+ | `disableSliderTimeout` | `boolean` | Disables debounce when dragging a slider. | `true` |
87
+ | `windowResizeTimeout` | `number` | Debounce timeout in milliseconds for window resize events. | `2` |
88
+ | `sliderUpdateTimeout` | `number` | Debounce timeout in milliseconds for slider drag events. | `2` |
89
+ | `...props` | `JSX.HTMLAttributes` | Standard HTML attributes like `style` and `class` are passed to the root `<div>`. | |
90
+
91
+ ### 🎨 Customization with Wrapper Components
92
+
93
+ You can completely change the look and feel of the layout by providing your own **SolidJS components** for rendering different parts of the UI.
94
+
95
+ | Prop | Description |
96
+ | :--- | :--- |
97
+ | `WrapTabPanel` | A component to wrap the entire tab panel (tab bar + tab content area). |
98
+ | `WrapTabHead` | A component to wrap the tab bar that contains the tab labels. |
99
+ | `WrapTabLabel` | A component for an individual, clickable tab label in the tab bar. |
100
+ | `WrapTabBody` | A component to wrap the content of a single tab. |
101
+ | `SliderElement` | A component for the draggable slider used to resize panels. |
102
+ | `HoverElement` | A component that displays the visual drop zone indicator when dragging a tab. |
103
+
104
+ **Example: Custom Slider**
105
+
106
+ ```jsx
107
+ import { DynamixLayout } from '@dynamix-layout/solid';
108
+ import type { Component, JSX } from 'solid-js';
109
+ immport { MyCustomSlider } from "./compoments";
110
+
111
+ function App() {
112
+ // ... (myTabs definition from "Getting Started")
113
+ return <DynamixLayout tabs={myTabs} SliderElement={MyCustomSlider} />;
114
+ }
115
+ ```
116
+
117
+ ### Styling Props
118
+
119
+ For finer-grained control, you can pass `style` objects or `class` strings to the default wrapper components without replacing them entirely.
120
+
121
+ | Prop | Type | Target Element |
122
+ | :--- | :--- | :--- |
123
+ | `tabPanelElementStyles` | `JSX.CSSProperties` | `WrapTabPanel` |
124
+ | `tabPanelElementClass` | `string` | `WrapTabPanel` |
125
+ | `tabHeadElementStyles` | `JSX.CSSProperties` | `WrapTabHead` |
126
+ | `tabHeadElementClass` | `string` | `WrapTabHead` |
127
+ | `tabLabelElementStyles` | `JSX.CSSProperties` | `WrapTabLabel` |
128
+ | `tabLabelElementClass` | `string` | `WrapTabLabel` |
129
+ | `tabBodyElementStyles` | `JSX.CSSProperties` | `WrapTabBody` |
130
+ | `tabBodyElementClass` | `string` | `WrapTabBody` |
131
+ | `sliderElementStyles` | `JSX.CSSProperties` | `SliderElement` |
132
+ | `sliderElementClass` | `string` | `SliderElement` |
133
+ | `hoverElementStyles` | `JSX.CSSProperties` | `HoverElement` |
134
+ | `hoverElementClass` | `string` | `HoverElement` |
135
+ | `RootSplitterHoverElStyles` | `JSX.CSSProperties` | Root edge drop zones |
136
+ | `RootSplitterHoverElClass` | `string` | Root edge drop zones |
137
+
138
+ -----
139
+
140
+ ## ⚙️ Advanced Usage: The `useDynamixLayout` Hook
141
+
142
+ For ultimate control, you can use the `useDynamixLayout` hook to build your own layout renderer from scratch. It contains all the state, refs, and event handlers needed to power the layout, fully integrated with Solid's reactive system.
143
+
144
+ ### Options
145
+
146
+ The hook accepts an object with the same props as the `<DynamixLayout />` component, with two key differences:
147
+
148
+ 1. It requires a `tabOutput` prop, generated from your `tabs` array using the exported `getTabOutput` helper.
149
+ 2. It requires a `dimensions` prop, which is a **signal or function** that returns the layout container's size and position.
150
+
151
+ ### Return Value
152
+
153
+ The hook returns an object with everything you need to build your UI, including:
154
+
155
+ - **Reactive State**: `tabsets` and `sliders` (Maps containing the layout data, wrapped in SolidJS signals).
156
+ - **Refs**: `tabsetsRef`, `slidersRef`, `hoverElementRef`, etc., which are Maps for you to populate with element references using Solid's `ref` directive.
157
+ - **Event Handlers**: `onDragStart`, `onDragEnd`, `onDragOver`, `onPointerDown`, `updateActiveTab`, etc.
158
+ - **Instance**: `layoutInstance` (A signal containing the raw instance of `@dynamix-layout/core` for advanced actions like saving state).
159
+
160
+
161
+ -----
162
+
163
+ ### Example: Saving a Layout
164
+
165
+ - `updateJSON`: A callback function that receives the complete layout state object (LayoutTree) every time a change occurs (like dragging a tab or resizing a panel). You can use this to save the state to localStorage, a database, or anywhere else.
166
+
167
+ ```jsx
168
+ import { tabs } from './comp'
169
+ import { DynamixLayout } from '@dynamix-layout/solid'
170
+ import type { LayoutTree } from '@dynamix-layout/core'
171
+ import '@dynamix-layout/solid/style.css'
172
+
173
+ function App() {
174
+
175
+ const UpdateJSON = (layoutTree: LayoutTree) => {
176
+ console.log(layoutTree);
177
+ };
178
+
179
+ return (
180
+ <>
181
+ <DynamixLayout
182
+ updateJSON={UpdateJSON}
183
+ tabs={tabs}
184
+ />
185
+ </>
186
+ )
187
+ }
188
+
189
+ export default App
190
+
191
+ ```
192
+
193
+ ----
194
+
195
+ <div align="center">
196
+
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)
200
+
201
+
202
+ ### Made with ❤️ by [Akash Aman](https://linktr.ee/akash_aman)
203
+
204
+ </div>
package/dist/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Akash Aman <sir.akashaman@gmail.com> (https://akash.cx)
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1 @@
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const a=require("solid-js/web"),m=require("@dynamix-layout/core"),T=require("solid-js");var M=a.template("<div>"),ze=a.template("<div><div>"),We=a.template('<svg xmlns=http://www.w3.org/2000/svg width=24 height=24 viewBox="0 0 24 24"fill=none stroke=currentColor stroke-width=2 stroke-linecap=round stroke-linejoin=round class="lucide lucide-grip-vertical size-2.5"><circle cx=9 cy=12 r=1></circle><circle cx=9 cy=5 r=1></circle><circle cx=9 cy=19 r=1></circle><circle cx=15 cy=12 r=1></circle><circle cx=15 cy=5 r=1></circle><circle cx=15 cy=19 r=1>'),Ie=a.template('<svg xmlns=http://www.w3.org/2000/svg width=24 height=24 viewBox="0 0 24 24"fill=none stroke=currentColor stroke-width=2 stroke-linecap=round stroke-linejoin=round><circle cx=9 cy=12 r=1></circle><circle cx=9 cy=5 r=1></circle><circle cx=9 cy=19 r=1></circle><circle cx=15 cy=12 r=1></circle><circle cx=15 cy=5 r=1></circle><circle cx=15 cy=19 r=1>');const fe=r=>(()=>{var i=M();return a.spread(i,a.mergeProps(r,{get class(){return`DefaultWrapTabLabel ${r.class||""}`},get"data-state"(){return r.active?"active":"inactive"},get style(){return{"align-self":"center",padding:"4px 6px","box-sizing":"border-box","font-size":"14px","border-radius":"4px",...r.style}}}),!1,!0),a.insert(i,()=>r.children),i})(),he=r=>(()=>{var i=M();return a.spread(i,a.mergeProps(r,{get class(){return`DefaultWrapTabBody hide-scrollbar ${r.class||""}`},get style(){return{"box-sizing":"border-box",height:"100%",width:"100%",display:"grid",overflow:"auto","scrollbar-width":"none","-ms-overflow-style":"none",...r.style}}}),!1,!0),a.insert(i,()=>r.children),i})(),me=r=>(()=>{var i=M();return a.spread(i,a.mergeProps(r,{get class(){return`DefaultWrapTabHead hide-scrollbar ${r.class||""}`},get style(){return{display:"grid","grid-auto-flow":"column","justify-content":"start","align-items":"center",gap:"6px","padding-left":"8px",width:"100%","box-sizing":"border-box",height:"100%","place-items":"self-start",overflow:"auto","background-color":"#dfdfdf","scrollbar-width":"none","-ms-overflow-style":"none",...r.style}}}),!1,!0),a.insert(i,()=>r.children),i})(),ye=r=>(()=>{var i=M();return a.spread(i,a.mergeProps(r,{get class(){return`DefaultWrapTabPanel ${r.class||""}`},get style(){return{display:"grid","align-items":"center","place-items":"self-start","box-sizing":"border-box",position:"absolute","border-radius":"8px",...r.style}}}),!1,!0),a.insert(i,()=>r.children),i})(),pe=r=>(()=>{var i=M();return a.spread(i,a.mergeProps(r,{get class(){return`DefaultHoverElement ${r.class||""}`},get style(){return{display:"flex","justify-content":"center","align-items":"center",opacity:.7,position:"absolute","box-sizing":"border-box","font-weight":"bold","pointer-events":"none","background-color":"rgba(0, 175, 249, 0.5)","border-radius":"10px",transition:"all 0.2s ease",border:"2px dashed rgb(0, 196, 42)",...r.style}}}),!1,!0),a.insert(i,()=>r.children),i})(),be=r=>(()=>{var i=ze(),p=i.firstChild;return a.spread(i,a.mergeProps(r,{get class(){return`DefaultSliderElement ${r.class||""}`},get style(){return{width:"100%",height:"100%",position:"absolute","box-sizing":"border-box","background-color":"white","z-index":9,cursor:"grab",...r.style}}}),!1,!0),p.style.setProperty("display","flex"),p.style.setProperty("align-items","center"),p.style.setProperty("gap","4px"),p.style.setProperty("height","100%"),a.insert(p,(()=>{var b=a.memo(()=>!r.direction);return()=>b()?We():(()=>{var c=Ie();return c.style.setProperty("transform","rotate(90deg)"),c})()})()),a.insert(i,()=>r.children,null),a.effect(b=>(b=r.direction?"column":"row")!=null?p.style.setProperty("flex-direction",b):p.style.removeProperty("flex-direction")),i})(),xe=r=>{const[i,p]=T.splitProps(r,["area","size","gap","class","style","children"]),b=T.createMemo(()=>{const c=i.size||{h:"20%",w:"6px"},C=i.gap||"0px",y={};return i.area==="left"?(Object.assign(y,{"border-top-right-radius":"16px","border-bottom-right-radius":"16px",height:c.h,left:C,width:c.w}),y.top=`calc(50% - ${c.h} / 2)`):i.area==="top"?(Object.assign(y,{"border-bottom-left-radius":"16px","border-bottom-right-radius":"16px",width:c.h,top:C,height:c.w}),y.left=`calc(50% - ${c.h} / 2)`):i.area==="right"?(Object.assign(y,{"border-top-left-radius":"16px","border-bottom-left-radius":"16px",height:c.h,right:C,width:c.w}),y.top=`calc(50% - ${c.h} / 2)`):i.area==="bottom"&&(Object.assign(y,{"border-top-left-radius":"16px","border-top-right-radius":"16px",width:c.h,bottom:C,height:c.w}),y.left=`calc(50% - ${c.h} / 2)`),y});return(()=>{var c=M();return a.spread(c,a.mergeProps(p,{get class(){return`RootSplitterHoverEl ${i.class||""}`},get style(){return{position:"absolute","z-index":-1,display:"none","box-sizing":"border-box","background-color":"#0081f9",cursor:"grab",...i.style,...b()}}}),!1,!0),a.insert(c,()=>i.children),c})()},ve=({tabOutput:r,rootId:i,layoutTree:p,updateJSON:b,dimensions:c,tabHeadHeight:C,enableTabbar:y,bondWidth:te,minTabHeight:re,minTabWidth:k,sliderUpdateTimeout:ne,windowResizeTimeout:K,disableSliderTimeout:j,disableResizeTimeout:F})=>{const B=new Map,U=new Map,A=new Map,G=new Map,R={current:void 0},q=[],[V,ae]=T.createSignal(p),[Q,I]=T.createSignal(new Map),[oe,Z]=T.createSignal(new Map),[ie,H]=T.createSignal(!1);let L=null;const[se,E]=T.createSignal(!1),s={src:void 0,des:void 0,area:void 0,drag:!1},o={sliderId:void 0,isSliding:!1},u=new m.DynamixLayoutCore({tabs:r.keys,tree:V(),minW:k,minH:re,bond:te,uqid:i,tabsIds:r.name}),x=n=>{const e=new Map(n);I(e)},de=n=>{const e=new Map(n);Z(e)},X=()=>{m.Node.cache.tabOpts.get().forEach((e,l)=>{const t=G.get(l);t&&(t.style.width=`${e.nodDims.w}px`,t.style.height=y?`${e.nodDims.h-C}px`:`${e.nodDims.h}px`,t.style.left=`${e.nodDims.x}px`,t.style.top=y?`${e.nodDims.y+C}px`:`${e.nodDims.y}px`,t.style.display=e.nodOpen?"block":"none")})},De=()=>{m.Node.cache.bndOpts.get().forEach((e,l)=>{const t=U.get(l);t&&(t.style.width=`${e.nodDims.w}px`,t.style.height=`${e.nodDims.h}px`,t.style.left=`${e.nodDims.x}px`,t.style.top=`${e.nodDims.y}px`)})};m.Node.cache.nodOpts.onChange(n=>{n.forEach((e,l)=>{const t=A.get(l);t&&(t.style.width=`${e.nodDims.w}px`,t.style.height=`${e.nodDims.h}px`,t.style.left=`${e.nodDims.x}px`,t.style.top=`${e.nodDims.y}px`);const d=B.get(l);d&&y&&(d.style.width=`${e.nodDims.w}px`,d.style.height=y?`${C}px`:"0px",d.style.left=`${e.nodDims.x}px`,d.style.top=`${e.nodDims.y}px`)})}),m.Node.cache.bndOpts.onChange(n=>{n.forEach((e,l)=>{const t=U.get(l);t&&(t.style.width=`${e.nodDims.w}px`,t.style.height=`${e.nodDims.h}px`,t.style.left=`${e.nodDims.x}px`,t.style.top=`${e.nodDims.y}px`)})});const ce=n=>{o.isSliding&&(u.updateSlider(o.sliderId,{x:n.clientX,y:n.clientY},j,ne),De(),X())},ee=n=>{if(!o.isSliding)return;const e=n.currentTarget;o.isSliding=!1,o.sliderId=void 0,b&&b(m.DynamixLayoutCore._root.toJSON()),e.releasePointerCapture(n.pointerId),e.removeEventListener("pointermove",ce),e.removeEventListener("pointerup",ee),e.removeEventListener("pointercancel",ee)},Te=n=>{n.preventDefault();const e=n.currentTarget;o.isSliding=!0,o.sliderId=e.id,e.setPointerCapture(n.pointerId),e.addEventListener("pointermove",ce),e.addEventListener("pointerup",ee),e.addEventListener("pointercancel",ee)},h={},Ee=(n,e,l)=>{if(!R.current||!s||!l)return null;s.des=l;const t=l.getBoundingClientRect();if(!t)return null;const d=t.width,g=t.height,f=n-t.left,w=e-t.top;let v,$,N,D,P;f<d/3?(v="left",$=t.left,N=t.top,D=d/2,P=g):f>2*d/3?(v="right",$=t.left+d/2,N=t.top,D=d/2,P=g):w<g/3?(v="top",$=t.left,N=t.top,D=d,P=g/2):w>2*g/3?(v="bottom",$=t.left,N=t.top+g/2,D=d,P=g/2):(v="contain",$=t.left+d*.1,N=t.top+g*.1,D=d*.8,P=g*.8),(h.area!==v||h.left!==$||h.top!==N||h.width!==D||h.height!==P)&&(Y($,N,D,P,v),h.area=v,h.left=$,h.top=N,h.width=D,h.height=P),s.area=v},$e=n=>{n.preventDefault(),n.stopPropagation(),n.dataTransfer&&(n.dataTransfer.dropEffect="move");const e=n.currentTarget,l=Array.from(e.childNodes),t=n.clientX,d=n.clientY;if(!R.current||!s||l.length===0)return;const g=l[0].parentElement;if(!g)return;const f=g.getBoundingClientRect(),w=l[0],v=l[l.length-1],$=w.getBoundingClientRect(),N=v.getBoundingClientRect();let D=6;if(d<f.top||d>f.bottom)return;if(t>N.right){const S=N.right+1,O=N.top,z=D-2,W=N.height,_="right";Y(S,O,z,W,_),s.des=v,s.area=_;return}if(t<$.left){const S=$.left-D+1,O=$.top,z=D-2,W=$.height,_="left";Y(S,O,z,W,_),s.des=w,s.area=_;return}let P=null,ue=1/0,J=!1,le=0;for(let S=0;S<l.length;S++){const O=l[S].getBoundingClientRect(),z=O.left+O.width/2,W=Math.abs(t-z);W<ue&&(ue=W,P=l[S],J=t<z,le=S)}if(l.length>1&&(J&&le>0||!J&&le<l.length-1)&&(D=l[1].getBoundingClientRect().left-$.right),P){const S=P.getBoundingClientRect(),O=J?S.left-D+1:S.right+1,z=S.top,W=D-2,_=S.height,ge=J?"left":"right";Y(O,z,W,_,ge),s.des=P,s.area=ge}},Se=n=>{n.preventDefault(),n.stopPropagation(),n.dataTransfer&&(n.dataTransfer.dropEffect="move");const e=n.currentTarget.dataset.area,l=n.currentTarget.dataset.uid;if(!e||!l||!R.current||!s)return;s.des=n.currentTarget,s.area=e;const t=c();let d=t.x,g=t.y,f=t.w,w=t.h;e==="left"?(d=t.x,g=t.y,f=t.w/2,w=t.h):e==="right"?(d=t.x+t.w/2,g=t.y,f=t.w/2,w=t.h):e==="top"?(d=t.x,g=t.y,f=t.w,w=t.h/2):e==="bottom"&&(d=t.x,g=t.y+t.h/2,f=t.w,w=t.h/2),Y(d,g,f,w,e)},Y=(n,e,l,t,d)=>{if(h.area!==d||h.left!==n||h.top!==e||h.width!==l||h.height!==t){const g=R.current;if(g){const f={};for(let w=0;w<g.style.length;w++){const v=g.style[w];v&&(f[v]=g.style.getPropertyValue(v))}Object.assign(g.style,f,{left:`${n}px`,top:`${e}px`,width:`${l}px`,height:`${t}px`,display:"block","z-index":"100"}),h.area=d,h.left=n,h.top=e,h.width=l,h.height=t}}},Ce=n=>{if(n.stopPropagation(),H(!0),document.body.style.cursor="move",n.currentTarget){if(n.dataTransfer){n.dataTransfer.effectAllowed="move";const e=document.createElement("div");e.style.width="1px",e.style.height="1px",e.style.backgroundColor="transparent",e.style.position="absolute",e.style.top="-1000px",document.body.appendChild(e),n.dataTransfer.setDragImage(e,0,0),setTimeout(()=>{e.parentNode&&e.parentNode.removeChild(e)},0)}q.forEach(e=>{e&&(e.style.display="block",e.style.zIndex="99")}),A.forEach(e=>{e&&(e.style.display="block",e.style.zIndex="95")}),s.src=n.currentTarget,s.drag=!0}},Ne=n=>{if(n.preventDefault(),n.stopPropagation(),document.body.style.cursor="move",n.dataTransfer&&(n.dataTransfer.dropEffect="move"),!s?.src)return;const e=n.currentTarget,l=n.clientX,t=n.clientY;L&&cancelAnimationFrame(L),L=requestAnimationFrame(()=>{Ee(l,t,e)})},Pe=n=>{if(document.body.style.cursor="default",q.forEach(e=>{e&&(e.style.display="none",e.style.zIndex="-1")}),L&&(cancelAnimationFrame(L),L=null),R.current&&(R.current.style.display="none",R.current.style.zIndex="-1"),Object.assign(h,{}),s.drag=!1,!s?.src||!s?.des){s.area=void 0,s.src=void 0,s.des=void 0,H(!1);return}if(s.src===s.des){s.area=void 0,s.src=void 0,s.des=void 0,H(!1);return}if(s.src&&s.des){if(!s.area){console.warn("No area specified for drag and drop"),H(!1);return}if(!u.updateTree(s.src.dataset.uid,s.des.dataset.uid,s.area||"contain")){console.warn("Failed to update layout tree"),H(!1);return}requestAnimationFrame(()=>{x(m.Node.cache.nodOpts.get()),de(m.Node.cache.bndOpts.get()),X(),b&&b(m.DynamixLayoutCore._root.toJSON())})}s.area=void 0,s.src=void 0,s.des=void 0,H(!1)},Re=n=>{n.preventDefault(),n.stopPropagation(),n.dataTransfer&&(n.dataTransfer.dropEffect="move")},Le=n=>{n.preventDefault(),n.stopPropagation()},He=n=>{n.preventDefault(),n.stopPropagation(),n.dataTransfer&&n.dataTransfer.getData("text/plain")},Oe=n=>{const e=n.currentTarget,l=e.dataset.uid;if(!l)return;const t=m.Node.cache.mapElem.get(l);if(!(t instanceof m.Node)){console.warn(`Element with uid ${l} is not a Node instance`);return}if(!t||!t.host||!t.host.unId){console.warn(`Node with uid ${l} not found in mapNode`);return}if(t.host.open==t.name){console.warn(`Node ${t.name} is already open`);return}const d=m.Node.cache.nodOpts.get().get(t.host.unId);if(!d||d.nodOpen&&t?.open)return;t.host.open=t.name,d.nodOpen=t.name,d.nodKids?.forEach(f=>{f.nodOpen=f.nodName===t.name}),e?.parentElement?.childNodes?.forEach(f=>{f instanceof HTMLDivElement&&f.dataset.uid!==l?f.dataset.state="inactive":f.dataset.state="active"}),X()};return T.onMount(()=>{const n=l=>{u.updateDimension(c(),l,K),X()};n(!0);const e=()=>n(F??!1);window.addEventListener("resize",e),x(m.Node.cache.nodOpts.get()),de(m.Node.cache.bndOpts.get()),X(),b&&b(m.DynamixLayoutCore._root.toJSON()),T.onCleanup(()=>{window.removeEventListener("resize",e),L&&cancelAnimationFrame(L)})}),{tabsets:Q,sliders:oe,tabsetsRef:B,panelsRef:A,tabsRef:G,slidersRef:U,layoutJSON:V,layoutInstance:u,hoverElementRef:R,rootSplitHoverEl:q,dragging:ie,isUpdating:se,setIsUpdating:E,setDragging:H,setTabsets:I,setSliders:Z,setLayoutJSON:ae,onDragStart:Ce,onDragOver:Ne,onDragEnd:Pe,onDragEnter:Re,onDragLeave:Le,onDrop:He,onPointerDown:Te,updateActiveTab:Oe,handleRootSplit:Se,handleNavbarDragOver:$e}};var _e=a.template("<div>"),ke=a.template('<div class="flex items-center justify-center h-full"><span class=text-gray-500>No content');const we=r=>{const i=[],p=new Map,b=new Map;for(const[c,C]of r){const y=crypto.randomUUID();i.push(c),p.set(c,{uqid:y,name:c,node:C}),b.set(c,y)}return{keys:i,maps:p,name:b}},Be=r=>{const i=T.createMemo(()=>we(r.tabs));let p;const b=()=>{const E=p;if(!E)return{w:0,h:0,x:0,y:0};const s=E.getBoundingClientRect(),o=r.pad||{t:0,b:0,l:0,r:0};return{w:s.width-(o.l+o.r),h:s.height-(o.t+o.b),x:s.left+o.l,y:s.top+o.t}},{tabsetsRef:c,slidersRef:C,sliders:y,tabsets:te,hoverElementRef:re,onDragEnd:k,onDragOver:ne,onDragStart:K,onDragEnter:j,onDragLeave:F,onDrop:B,dragging:U,panelsRef:A,onPointerDown:G,handleNavbarDragOver:R,updateActiveTab:q,rootSplitHoverEl:V,handleRootSplit:ae,tabsRef:Q,isUpdating:I}=ve({tabOutput:i(),rootId:r.rootId||"dynamix-layout-root",updateJSON:r.updateJSON,enableTabbar:r.enableTabbar===void 0?!0:r.enableTabbar,layoutTree:r.layoutTree,tabHeadHeight:r.tabHeadHeight||m.DynamixLayoutCore._minH,dimensions:b,sliderUpdateTimeout:r.sliderUpdateTimeout||2,windowResizeTimeout:r.windowResizeTimeout||2,bondWidth:r.bondWidth||m.DynamixLayoutCore._bond,minTabHeight:r.minTabHeight||m.DynamixLayoutCore._minH,minTabWidth:r.minTabWidth||m.DynamixLayoutCore._minW,disableSliderTimeout:r.disableSliderTimeout===void 0?!0:r.disableSliderTimeout,disableResizeTimeout:r.disableResizeTimeout===void 0?!0:r.disableResizeTimeout,hoverElementStyles:r.hoverElementStyles}),oe=r.WrapTabPanel||ye,Z=r.WrapTabHead||me,ie=r.WrapTabLabel||fe,H=r.WrapTabBody||he,L=r.SliderElement||be,se=r.HoverElement||pe;return(()=>{var E=_e(),s=p;return typeof s=="function"?a.use(s,E):p=E,a.spread(E,a.mergeProps({get id(){return r.rootId||"dynamix-layout-root"}},r,{get"data-testid"(){return r.rootId||"dynamix-layout-root"},get class(){return U()?"is-dragging":""},get style(){return{position:"relative",width:"100%",height:"100%",overflow:"hidden",...r.style}}}),!1,!0),a.insert(E,a.createComponent(T.For,{get each(){return Array.from(te().values())},children:o=>[a.createComponent(oe,{ref:u=>{const x=o.uidNode;u?A.set(x,u):A.delete(x)},onDragEnd:k,onDragOver:ne,onDragEnter:j,onDragLeave:F,onDrop:B,get"data-uid"(){return o.uidNode},get"data-type"(){return o.typNode},get class(){return"hide-scrollbar DefaultWrapTabPanel "+(r.tabPanelElementClass||"")},get style(){return{position:"absolute",...r.tabPanelElementStyles,width:`${o.nodDims.w}px`,height:`${o.nodDims.h}px`,left:`${o.nodDims.x}px`,top:`${o.nodDims.y}px`,"background-color":"transparent"}}}),a.createComponent(Z,{get draggable(){return!I()},get"data-uid"(){return o.uidNode},"data-type":"tabset",onDragOver:R,onDragStart:K,onDragEnd:k,onDragEnter:j,onDragLeave:F,onDrop:B,ref:u=>{const x=o.uidNode;u?c.set(x,u):c.delete(x)},get class(){return"hide-scrollbar "+(r.tabHeadElementClass||"")},get style(){return{...r.tabHeadElementStyles,position:"absolute","z-index":99,width:`${o.nodDims.w}px`,height:`${r.tabHeadHeight||m.DynamixLayoutCore._minH}px`,left:`${o.nodDims.x}px`,top:`${o.nodDims.y}px`,cursor:I()?"wait":"pointer"}},get children(){return a.createComponent(T.For,{get each(){return o.nodKids},children:u=>a.createComponent(ie,{get"data-uid"(){return u.uidNode},"data-type":"tab",onDragStart:K,onDragEnd:k,get draggable(){return!I()},get active(){return!!u.nodOpen},get class(){return"hide-scrollbar "+(r.tabLabelElementClass||"")},get style(){return{cursor:I()?"wait":"pointer",...r.tabLabelElementStyles}},onClick:q,get children(){return a.memo(()=>!!r.tabNames)()&&r.tabNames.get(u.nodName)||u.nodName}})})}})]}),null),a.insert(E,a.createComponent(T.For,{get each(){return i().keys},children:o=>{const u=i().maps.get(o)?.uqid;return a.createComponent(H,{id:u,draggable:!1,"data-uid":u,get class(){return"hide-scrollbar "+(r.tabBodyElementClass||"")},get style(){return{position:"absolute","z-index":90,"overscroll-behavior":"contain",...r.tabBodyElementStyles}},ref:x=>{u&&(x?Q.set(u,x):Q.delete(u))},get children(){return i().maps.get(o)?.node||ke()}})}}),null),a.insert(E,a.createComponent(T.For,{get each(){return Array.from(y().values())},children:o=>a.createComponent(L,{get id(){return o.uidNode},get"data-uid"(){return o.uidNode},get direction(){return o.nodeDir},onPointerDown:G,get class(){return"hide-scrollbar "+(r.sliderElementClass||"")},ref:u=>{const x=o.uidNode;u?C.set(x,u):C.delete(x)},get style(){return{width:`${o.nodDims.w}px`,height:`${o.nodDims.h}px`,left:`${o.nodDims.x}px`,top:`${o.nodDims.y}px`,cursor:o.nodeDir?"ns-resize":"ew-resize",...r.sliderElementStyles}}})}),null),a.insert(E,a.createComponent(se,{get class(){return"hide-scrollbar "+(r.hoverElementClass||"")},get style(){return{...r.hoverElementStyles}},ref:o=>re.current=o}),null),a.insert(E,a.createComponent(T.For,{each:["left","right","top","bottom"],children:(o,u)=>a.createComponent(xe,{onDragOver:ae,onDragEnd:k,onDragEnter:j,onDragLeave:F,onDrop:B,get"data-uid"(){return r.rootId||"dynamix-layout-root"},"data-area":o,get class(){return"hide-scrollbar "+(r.RootSplitterHoverElClass||"")},ref:x=>{x&&(V[u()]=x)},get style(){return{...r.RootSplitterHoverElStyles}},area:o,size:{h:"25%",w:"8px"}})}),null),E})()};exports.DefaultHoverElement=pe;exports.DefaultSliderElement=be;exports.DefaultWrapTabBody=he;exports.DefaultWrapTabHead=me;exports.DefaultWrapTabLabel=fe;exports.DefaultWrapTabPanel=ye;exports.DynamixLayout=Be;exports.RootSplitterHoverEl=xe;exports.getTabOutput=we;exports.useDynamixLayout=ve;
package/dist/index.css ADDED
@@ -0,0 +1 @@
1
+ @import"https://fonts.googleapis.com/css2?family=Poppins:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800;1,900&display=swap";.DefaultWrapTabLabel[data-state=active]{background-color:#fff;font-family:Poppins,sans-serif}.DefaultWrapTabLabel[data-state=inactive]{background-color:#dfdfdf;font-family:Poppins,sans-serif}.hide-scrollbar::-webkit-scrollbar{display:none}.is-dragging .DefaultWrapTabBody>*{pointer-events:none}
@@ -0,0 +1,786 @@
1
+ import { template as F, spread as _, mergeProps as k, insert as R, memo as xe, effect as Pe, createComponent as N, use as We } from "solid-js/web";
2
+ import { DynamixLayoutCore as P, Node as C } from "@dynamix-layout/core";
3
+ import { splitProps as Ie, createMemo as ve, createSignal as Z, onMount as Le, onCleanup as _e, For as ee } from "solid-js";
4
+ var X = F("<div>"), ke = F("<div><div>"), Ae = F('<svg xmlns=http://www.w3.org/2000/svg width=24 height=24 viewBox="0 0 24 24"fill=none stroke=currentColor stroke-width=2 stroke-linecap=round stroke-linejoin=round class="lucide lucide-grip-vertical size-2.5"><circle cx=9 cy=12 r=1></circle><circle cx=9 cy=5 r=1></circle><circle cx=9 cy=19 r=1></circle><circle cx=15 cy=12 r=1></circle><circle cx=15 cy=5 r=1></circle><circle cx=15 cy=19 r=1>'), Be = F('<svg xmlns=http://www.w3.org/2000/svg width=24 height=24 viewBox="0 0 24 24"fill=none stroke=currentColor stroke-width=2 stroke-linecap=round stroke-linejoin=round><circle cx=9 cy=12 r=1></circle><circle cx=9 cy=5 r=1></circle><circle cx=9 cy=19 r=1></circle><circle cx=15 cy=12 r=1></circle><circle cx=15 cy=5 r=1></circle><circle cx=15 cy=19 r=1>');
5
+ const Me = (n) => (() => {
6
+ var o = X();
7
+ return _(o, k(n, {
8
+ get class() {
9
+ return `DefaultWrapTabLabel ${n.class || ""}`;
10
+ },
11
+ get "data-state"() {
12
+ return n.active ? "active" : "inactive";
13
+ },
14
+ get style() {
15
+ return {
16
+ "align-self": "center",
17
+ padding: "4px 6px",
18
+ "box-sizing": "border-box",
19
+ "font-size": "14px",
20
+ "border-radius": "4px",
21
+ ...n.style
22
+ };
23
+ }
24
+ }), !1, !0), R(o, () => n.children), o;
25
+ })(), je = (n) => (() => {
26
+ var o = X();
27
+ return _(o, k(n, {
28
+ get class() {
29
+ return `DefaultWrapTabBody hide-scrollbar ${n.class || ""}`;
30
+ },
31
+ get style() {
32
+ return {
33
+ "box-sizing": "border-box",
34
+ height: "100%",
35
+ width: "100%",
36
+ display: "grid",
37
+ overflow: "auto",
38
+ "scrollbar-width": "none",
39
+ "-ms-overflow-style": "none",
40
+ ...n.style
41
+ };
42
+ }
43
+ }), !1, !0), R(o, () => n.children), o;
44
+ })(), Ue = (n) => (() => {
45
+ var o = X();
46
+ return _(o, k(n, {
47
+ get class() {
48
+ return `DefaultWrapTabHead hide-scrollbar ${n.class || ""}`;
49
+ },
50
+ get style() {
51
+ return {
52
+ display: "grid",
53
+ "grid-auto-flow": "column",
54
+ "justify-content": "start",
55
+ "align-items": "center",
56
+ gap: "6px",
57
+ "padding-left": "8px",
58
+ width: "100%",
59
+ "box-sizing": "border-box",
60
+ height: "100%",
61
+ "place-items": "self-start",
62
+ overflow: "auto",
63
+ "background-color": "#dfdfdf",
64
+ "scrollbar-width": "none",
65
+ "-ms-overflow-style": "none",
66
+ ...n.style
67
+ };
68
+ }
69
+ }), !1, !0), R(o, () => n.children), o;
70
+ })(), Fe = (n) => (() => {
71
+ var o = X();
72
+ return _(o, k(n, {
73
+ get class() {
74
+ return `DefaultWrapTabPanel ${n.class || ""}`;
75
+ },
76
+ get style() {
77
+ return {
78
+ display: "grid",
79
+ "align-items": "center",
80
+ "place-items": "self-start",
81
+ "box-sizing": "border-box",
82
+ position: "absolute",
83
+ "border-radius": "8px",
84
+ ...n.style
85
+ };
86
+ }
87
+ }), !1, !0), R(o, () => n.children), o;
88
+ })(), Xe = (n) => (() => {
89
+ var o = X();
90
+ return _(o, k(n, {
91
+ get class() {
92
+ return `DefaultHoverElement ${n.class || ""}`;
93
+ },
94
+ get style() {
95
+ return {
96
+ display: "flex",
97
+ "justify-content": "center",
98
+ "align-items": "center",
99
+ opacity: 0.7,
100
+ position: "absolute",
101
+ "box-sizing": "border-box",
102
+ "font-weight": "bold",
103
+ "pointer-events": "none",
104
+ "background-color": "rgba(0, 175, 249, 0.5)",
105
+ "border-radius": "10px",
106
+ transition: "all 0.2s ease",
107
+ border: "2px dashed rgb(0, 196, 42)",
108
+ ...n.style
109
+ };
110
+ }
111
+ }), !1, !0), R(o, () => n.children), o;
112
+ })(), qe = (n) => (() => {
113
+ var o = ke(), m = o.firstChild;
114
+ return _(o, k(n, {
115
+ get class() {
116
+ return `DefaultSliderElement ${n.class || ""}`;
117
+ },
118
+ get style() {
119
+ return {
120
+ width: "100%",
121
+ height: "100%",
122
+ position: "absolute",
123
+ "box-sizing": "border-box",
124
+ "background-color": "white",
125
+ "z-index": 9,
126
+ cursor: "grab",
127
+ ...n.style
128
+ };
129
+ }
130
+ }), !1, !0), m.style.setProperty("display", "flex"), m.style.setProperty("align-items", "center"), m.style.setProperty("gap", "4px"), m.style.setProperty("height", "100%"), R(m, (() => {
131
+ var y = xe(() => !n.direction);
132
+ return () => y() ? Ae() : (() => {
133
+ var d = Be();
134
+ return d.style.setProperty("transform", "rotate(90deg)"), d;
135
+ })();
136
+ })()), R(o, () => n.children, null), Pe((y) => (y = n.direction ? "column" : "row") != null ? m.style.setProperty("flex-direction", y) : m.style.removeProperty("flex-direction")), o;
137
+ })(), Ye = (n) => {
138
+ const [o, m] = Ie(n, ["area", "size", "gap", "class", "style", "children"]), y = ve(() => {
139
+ const d = o.size || {
140
+ h: "20%",
141
+ w: "6px"
142
+ }, E = o.gap || "0px", h = {};
143
+ return o.area === "left" ? (Object.assign(h, {
144
+ "border-top-right-radius": "16px",
145
+ "border-bottom-right-radius": "16px",
146
+ height: d.h,
147
+ left: E,
148
+ width: d.w
149
+ }), h.top = `calc(50% - ${d.h} / 2)`) : o.area === "top" ? (Object.assign(h, {
150
+ "border-bottom-left-radius": "16px",
151
+ "border-bottom-right-radius": "16px",
152
+ width: d.h,
153
+ top: E,
154
+ height: d.w
155
+ }), h.left = `calc(50% - ${d.h} / 2)`) : o.area === "right" ? (Object.assign(h, {
156
+ "border-top-left-radius": "16px",
157
+ "border-bottom-left-radius": "16px",
158
+ height: d.h,
159
+ right: E,
160
+ width: d.w
161
+ }), h.top = `calc(50% - ${d.h} / 2)`) : o.area === "bottom" && (Object.assign(h, {
162
+ "border-top-left-radius": "16px",
163
+ "border-top-right-radius": "16px",
164
+ width: d.h,
165
+ bottom: E,
166
+ height: d.w
167
+ }), h.left = `calc(50% - ${d.h} / 2)`), h;
168
+ });
169
+ return (() => {
170
+ var d = X();
171
+ return _(d, k(m, {
172
+ get class() {
173
+ return `RootSplitterHoverEl ${o.class || ""}`;
174
+ },
175
+ get style() {
176
+ return {
177
+ position: "absolute",
178
+ "z-index": -1,
179
+ display: "none",
180
+ "box-sizing": "border-box",
181
+ "background-color": "#0081f9",
182
+ cursor: "grab",
183
+ ...o.style,
184
+ ...y()
185
+ };
186
+ }
187
+ }), !1, !0), R(d, () => o.children), d;
188
+ })();
189
+ }, Je = ({
190
+ tabOutput: n,
191
+ rootId: o,
192
+ layoutTree: m,
193
+ updateJSON: y,
194
+ dimensions: d,
195
+ tabHeadHeight: E,
196
+ enableTabbar: h,
197
+ bondWidth: se,
198
+ minTabHeight: le,
199
+ minTabWidth: M,
200
+ sliderUpdateTimeout: de,
201
+ windowResizeTimeout: te,
202
+ disableSliderTimeout: q,
203
+ disableResizeTimeout: Y
204
+ }) => {
205
+ const j = /* @__PURE__ */ new Map(), J = /* @__PURE__ */ new Map(), U = /* @__PURE__ */ new Map(), ne = /* @__PURE__ */ new Map(), z = { current: void 0 }, K = [], [re, ce] = Z(
206
+ m
207
+ ), [ae, A] = Z(
208
+ /* @__PURE__ */ new Map()
209
+ ), [ue, oe] = Z(
210
+ /* @__PURE__ */ new Map()
211
+ ), [ge, H] = Z(!1);
212
+ let O = null;
213
+ const [fe, w] = Z(!1), i = {
214
+ src: void 0,
215
+ des: void 0,
216
+ area: void 0,
217
+ drag: !1
218
+ }, a = {
219
+ sliderId: void 0,
220
+ isSliding: !1
221
+ }, c = new P({
222
+ tabs: n.keys,
223
+ tree: re(),
224
+ minW: M,
225
+ minH: le,
226
+ bond: se,
227
+ uqid: o,
228
+ tabsIds: n.name
229
+ }), p = (r) => {
230
+ const e = new Map(r);
231
+ A(e);
232
+ }, me = (r) => {
233
+ const e = new Map(r);
234
+ oe(e);
235
+ }, G = () => {
236
+ C.cache.tabOpts.get().forEach((e, s) => {
237
+ const t = ne.get(s);
238
+ t && (t.style.width = `${e.nodDims.w}px`, t.style.height = h ? `${e.nodDims.h - E}px` : `${e.nodDims.h}px`, t.style.left = `${e.nodDims.x}px`, t.style.top = h ? `${e.nodDims.y + E}px` : `${e.nodDims.y}px`, t.style.display = e.nodOpen ? "block" : "none");
239
+ });
240
+ }, we = () => {
241
+ C.cache.bndOpts.get().forEach((e, s) => {
242
+ const t = J.get(s);
243
+ t && (t.style.width = `${e.nodDims.w}px`, t.style.height = `${e.nodDims.h}px`, t.style.left = `${e.nodDims.x}px`, t.style.top = `${e.nodDims.y}px`);
244
+ });
245
+ };
246
+ C.cache.nodOpts.onChange((r) => {
247
+ r.forEach((e, s) => {
248
+ const t = U.get(s);
249
+ t && (t.style.width = `${e.nodDims.w}px`, t.style.height = `${e.nodDims.h}px`, t.style.left = `${e.nodDims.x}px`, t.style.top = `${e.nodDims.y}px`);
250
+ const l = j.get(s);
251
+ l && h && (l.style.width = `${e.nodDims.w}px`, l.style.height = h ? `${E}px` : "0px", l.style.left = `${e.nodDims.x}px`, l.style.top = `${e.nodDims.y}px`);
252
+ });
253
+ }), C.cache.bndOpts.onChange((r) => {
254
+ r.forEach((e, s) => {
255
+ const t = J.get(s);
256
+ t && (t.style.width = `${e.nodDims.w}px`, t.style.height = `${e.nodDims.h}px`, t.style.left = `${e.nodDims.x}px`, t.style.top = `${e.nodDims.y}px`);
257
+ });
258
+ });
259
+ const ye = (r) => {
260
+ a.isSliding && (c.updateSlider(
261
+ a.sliderId,
262
+ {
263
+ x: r.clientX,
264
+ y: r.clientY
265
+ },
266
+ q,
267
+ de
268
+ ), we(), G());
269
+ }, ie = (r) => {
270
+ if (!a.isSliding) return;
271
+ const e = r.currentTarget;
272
+ a.isSliding = !1, a.sliderId = void 0, y && y(P._root.toJSON()), e.releasePointerCapture(r.pointerId), e.removeEventListener("pointermove", ye), e.removeEventListener("pointerup", ie), e.removeEventListener("pointercancel", ie);
273
+ }, De = (r) => {
274
+ r.preventDefault();
275
+ const e = r.currentTarget;
276
+ a.isSliding = !0, a.sliderId = e.id, e.setPointerCapture(r.pointerId), e.addEventListener("pointermove", ye), e.addEventListener("pointerup", ie), e.addEventListener("pointercancel", ie);
277
+ }, f = {}, Te = (r, e, s) => {
278
+ if (!z.current || !i || !s)
279
+ return null;
280
+ i.des = s;
281
+ const t = s.getBoundingClientRect();
282
+ if (!t) return null;
283
+ const l = t.width, u = t.height, g = r - t.left, x = e - t.top;
284
+ let b, D, $, v, S;
285
+ g < l / 3 ? (b = "left", D = t.left, $ = t.top, v = l / 2, S = u) : g > 2 * l / 3 ? (b = "right", D = t.left + l / 2, $ = t.top, v = l / 2, S = u) : x < u / 3 ? (b = "top", D = t.left, $ = t.top, v = l, S = u / 2) : x > 2 * u / 3 ? (b = "bottom", D = t.left, $ = t.top + u / 2, v = l, S = u / 2) : (b = "contain", D = t.left + l * 0.1, $ = t.top + u * 0.1, v = l * 0.8, S = u * 0.8), (f.area !== b || f.left !== D || f.top !== $ || f.width !== v || f.height !== S) && (V(D, $, v, S, b), f.area = b, f.left = D, f.top = $, f.width = v, f.height = S), i.area = b;
286
+ }, Ee = (r) => {
287
+ r.preventDefault(), r.stopPropagation(), r.dataTransfer && (r.dataTransfer.dropEffect = "move");
288
+ const e = r.currentTarget, s = Array.from(
289
+ e.childNodes
290
+ ), t = r.clientX, l = r.clientY;
291
+ if (!z.current || !i || s.length === 0)
292
+ return;
293
+ const u = s[0].parentElement;
294
+ if (!u) return;
295
+ const g = u.getBoundingClientRect(), x = s[0], b = s[s.length - 1], D = x.getBoundingClientRect(), $ = b.getBoundingClientRect();
296
+ let v = 6;
297
+ if (l < g.top || l > g.bottom) return;
298
+ if (t > $.right) {
299
+ const T = $.right + 1, W = $.top, I = v - 2, L = $.height, B = "right";
300
+ V(T, W, I, L, B), i.des = b, i.area = B;
301
+ return;
302
+ }
303
+ if (t < D.left) {
304
+ const T = D.left - v + 1, W = D.top, I = v - 2, L = D.height, B = "left";
305
+ V(T, W, I, L, B), i.des = x, i.area = B;
306
+ return;
307
+ }
308
+ let S = null, pe = 1 / 0, Q = !1, he = 0;
309
+ for (let T = 0; T < s.length; T++) {
310
+ const W = s[T].getBoundingClientRect(), I = W.left + W.width / 2, L = Math.abs(t - I);
311
+ L < pe && (pe = L, S = s[T], Q = t < I, he = T);
312
+ }
313
+ if (s.length > 1 && (Q && he > 0 || !Q && he < s.length - 1) && (v = s[1].getBoundingClientRect().left - D.right), S) {
314
+ const T = S.getBoundingClientRect(), W = Q ? T.left - v + 1 : T.right + 1, I = T.top, L = v - 2, B = T.height, be = Q ? "left" : "right";
315
+ V(W, I, L, B, be), i.des = S, i.area = be;
316
+ }
317
+ }, $e = (r) => {
318
+ r.preventDefault(), r.stopPropagation(), r.dataTransfer && (r.dataTransfer.dropEffect = "move");
319
+ const e = r.currentTarget.dataset.area, s = r.currentTarget.dataset.uid;
320
+ if (!e || !s || !z.current || !i)
321
+ return;
322
+ i.des = r.currentTarget, i.area = e;
323
+ const t = d();
324
+ let l = t.x, u = t.y, g = t.w, x = t.h;
325
+ e === "left" ? (l = t.x, u = t.y, g = t.w / 2, x = t.h) : e === "right" ? (l = t.x + t.w / 2, u = t.y, g = t.w / 2, x = t.h) : e === "top" ? (l = t.x, u = t.y, g = t.w, x = t.h / 2) : e === "bottom" && (l = t.x, u = t.y + t.h / 2, g = t.w, x = t.h / 2), V(l, u, g, x, e);
326
+ }, V = (r, e, s, t, l) => {
327
+ if (f.area !== l || f.left !== r || f.top !== e || f.width !== s || f.height !== t) {
328
+ const u = z.current;
329
+ if (u) {
330
+ const g = {};
331
+ for (let x = 0; x < u.style.length; x++) {
332
+ const b = u.style[x];
333
+ b && (g[b] = u.style.getPropertyValue(b));
334
+ }
335
+ Object.assign(u.style, g, {
336
+ left: `${r}px`,
337
+ top: `${e}px`,
338
+ width: `${s}px`,
339
+ height: `${t}px`,
340
+ display: "block",
341
+ "z-index": "100"
342
+ }), f.area = l, f.left = r, f.top = e, f.width = s, f.height = t;
343
+ }
344
+ }
345
+ }, Se = (r) => {
346
+ if (r.stopPropagation(), H(!0), document.body.style.cursor = "move", r.currentTarget) {
347
+ if (r.dataTransfer) {
348
+ r.dataTransfer.effectAllowed = "move";
349
+ const e = document.createElement("div");
350
+ e.style.width = "1px", e.style.height = "1px", e.style.backgroundColor = "transparent", e.style.position = "absolute", e.style.top = "-1000px", document.body.appendChild(e), r.dataTransfer.setDragImage(e, 0, 0), setTimeout(() => {
351
+ e.parentNode && e.parentNode.removeChild(e);
352
+ }, 0);
353
+ }
354
+ K.forEach((e) => {
355
+ e && (e.style.display = "block", e.style.zIndex = "99");
356
+ }), U.forEach((e) => {
357
+ e && (e.style.display = "block", e.style.zIndex = "95");
358
+ }), i.src = r.currentTarget, i.drag = !0;
359
+ }
360
+ }, Re = (r) => {
361
+ if (r.preventDefault(), r.stopPropagation(), document.body.style.cursor = "move", r.dataTransfer && (r.dataTransfer.dropEffect = "move"), !i?.src)
362
+ return;
363
+ const e = r.currentTarget, s = r.clientX, t = r.clientY;
364
+ O && cancelAnimationFrame(O), O = requestAnimationFrame(() => {
365
+ Te(s, t, e);
366
+ });
367
+ }, Ne = (r) => {
368
+ if (document.body.style.cursor = "default", K.forEach((e) => {
369
+ e && (e.style.display = "none", e.style.zIndex = "-1");
370
+ }), O && (cancelAnimationFrame(O), O = null), z.current && (z.current.style.display = "none", z.current.style.zIndex = "-1"), Object.assign(f, {}), i.drag = !1, !i?.src || !i?.des) {
371
+ i.area = void 0, i.src = void 0, i.des = void 0, H(!1);
372
+ return;
373
+ }
374
+ if (i.src === i.des) {
375
+ i.area = void 0, i.src = void 0, i.des = void 0, H(!1);
376
+ return;
377
+ }
378
+ if (i.src && i.des) {
379
+ if (!i.area) {
380
+ console.warn("No area specified for drag and drop"), H(!1);
381
+ return;
382
+ }
383
+ if (!c.updateTree(
384
+ i.src.dataset.uid,
385
+ i.des.dataset.uid,
386
+ i.area || "contain"
387
+ )) {
388
+ console.warn("Failed to update layout tree"), H(!1);
389
+ return;
390
+ }
391
+ requestAnimationFrame(() => {
392
+ p(C.cache.nodOpts.get()), me(C.cache.bndOpts.get()), G(), y && y(P._root.toJSON());
393
+ });
394
+ }
395
+ i.area = void 0, i.src = void 0, i.des = void 0, H(!1);
396
+ }, Ce = (r) => {
397
+ r.preventDefault(), r.stopPropagation(), r.dataTransfer && (r.dataTransfer.dropEffect = "move");
398
+ }, ze = (r) => {
399
+ r.preventDefault(), r.stopPropagation();
400
+ }, Oe = (r) => {
401
+ r.preventDefault(), r.stopPropagation(), r.dataTransfer && r.dataTransfer.getData("text/plain");
402
+ }, He = (r) => {
403
+ const e = r.currentTarget, s = e.dataset.uid;
404
+ if (!s) return;
405
+ const t = C.cache.mapElem.get(s);
406
+ if (!(t instanceof C)) {
407
+ console.warn(`Element with uid ${s} is not a Node instance`);
408
+ return;
409
+ }
410
+ if (!t || !t.host || !t.host.unId) {
411
+ console.warn(`Node with uid ${s} not found in mapNode`);
412
+ return;
413
+ }
414
+ if (t.host.open == t.name) {
415
+ console.warn(`Node ${t.name} is already open`);
416
+ return;
417
+ }
418
+ const l = C.cache.nodOpts.get().get(t.host.unId);
419
+ if (!l || l.nodOpen && t?.open)
420
+ return;
421
+ t.host.open = t.name, l.nodOpen = t.name, l.nodKids?.forEach((g) => {
422
+ g.nodOpen = g.nodName === t.name;
423
+ }), e?.parentElement?.childNodes?.forEach((g) => {
424
+ g instanceof HTMLDivElement && g.dataset.uid !== s ? g.dataset.state = "inactive" : g.dataset.state = "active";
425
+ }), G();
426
+ };
427
+ return Le(() => {
428
+ const r = (s) => {
429
+ c.updateDimension(
430
+ d(),
431
+ s,
432
+ te
433
+ ), G();
434
+ };
435
+ r(!0);
436
+ const e = () => r(Y ?? !1);
437
+ window.addEventListener("resize", e), p(C.cache.nodOpts.get()), me(C.cache.bndOpts.get()), G(), y && y(P._root.toJSON()), _e(() => {
438
+ window.removeEventListener("resize", e), O && cancelAnimationFrame(O);
439
+ });
440
+ }), {
441
+ tabsets: ae,
442
+ sliders: ue,
443
+ tabsetsRef: j,
444
+ panelsRef: U,
445
+ tabsRef: ne,
446
+ slidersRef: J,
447
+ layoutJSON: re,
448
+ layoutInstance: c,
449
+ hoverElementRef: z,
450
+ rootSplitHoverEl: K,
451
+ dragging: ge,
452
+ isUpdating: fe,
453
+ setIsUpdating: w,
454
+ setDragging: H,
455
+ setTabsets: A,
456
+ setSliders: oe,
457
+ setLayoutJSON: ce,
458
+ onDragStart: Se,
459
+ onDragOver: Re,
460
+ onDragEnd: Ne,
461
+ onDragEnter: Ce,
462
+ onDragLeave: ze,
463
+ onDrop: Oe,
464
+ onPointerDown: De,
465
+ updateActiveTab: He,
466
+ handleRootSplit: $e,
467
+ handleNavbarDragOver: Ee
468
+ };
469
+ };
470
+ var Ke = F("<div>"), Ge = F('<div class="flex items-center justify-center h-full"><span class=text-gray-500>No content');
471
+ const Ve = (n) => {
472
+ const o = [], m = /* @__PURE__ */ new Map(), y = /* @__PURE__ */ new Map();
473
+ for (const [d, E] of n) {
474
+ const h = crypto.randomUUID();
475
+ o.push(d), m.set(d, {
476
+ uqid: h,
477
+ name: d,
478
+ node: E
479
+ }), y.set(d, h);
480
+ }
481
+ return {
482
+ keys: o,
483
+ maps: m,
484
+ name: y
485
+ };
486
+ }, tt = (n) => {
487
+ const o = ve(() => Ve(n.tabs));
488
+ let m;
489
+ const y = () => {
490
+ const w = m;
491
+ if (!w) return {
492
+ w: 0,
493
+ h: 0,
494
+ x: 0,
495
+ y: 0
496
+ };
497
+ const i = w.getBoundingClientRect(), a = n.pad || {
498
+ t: 0,
499
+ b: 0,
500
+ l: 0,
501
+ r: 0
502
+ };
503
+ return {
504
+ w: i.width - (a.l + a.r),
505
+ h: i.height - (a.t + a.b),
506
+ x: i.left + a.l,
507
+ y: i.top + a.t
508
+ };
509
+ }, {
510
+ tabsetsRef: d,
511
+ slidersRef: E,
512
+ sliders: h,
513
+ tabsets: se,
514
+ hoverElementRef: le,
515
+ onDragEnd: M,
516
+ onDragOver: de,
517
+ onDragStart: te,
518
+ onDragEnter: q,
519
+ onDragLeave: Y,
520
+ onDrop: j,
521
+ dragging: J,
522
+ panelsRef: U,
523
+ onPointerDown: ne,
524
+ handleNavbarDragOver: z,
525
+ updateActiveTab: K,
526
+ rootSplitHoverEl: re,
527
+ handleRootSplit: ce,
528
+ tabsRef: ae,
529
+ isUpdating: A
530
+ } = Je({
531
+ tabOutput: o(),
532
+ rootId: n.rootId || "dynamix-layout-root",
533
+ updateJSON: n.updateJSON,
534
+ enableTabbar: n.enableTabbar === void 0 ? !0 : n.enableTabbar,
535
+ layoutTree: n.layoutTree,
536
+ tabHeadHeight: n.tabHeadHeight || P._minH,
537
+ dimensions: y,
538
+ sliderUpdateTimeout: n.sliderUpdateTimeout || 2,
539
+ windowResizeTimeout: n.windowResizeTimeout || 2,
540
+ bondWidth: n.bondWidth || P._bond,
541
+ minTabHeight: n.minTabHeight || P._minH,
542
+ minTabWidth: n.minTabWidth || P._minW,
543
+ disableSliderTimeout: n.disableSliderTimeout === void 0 ? !0 : n.disableSliderTimeout,
544
+ disableResizeTimeout: n.disableResizeTimeout === void 0 ? !0 : n.disableResizeTimeout,
545
+ hoverElementStyles: n.hoverElementStyles
546
+ }), ue = n.WrapTabPanel || Fe, oe = n.WrapTabHead || Ue, ge = n.WrapTabLabel || Me, H = n.WrapTabBody || je, O = n.SliderElement || qe, fe = n.HoverElement || Xe;
547
+ return (() => {
548
+ var w = Ke(), i = m;
549
+ return typeof i == "function" ? We(i, w) : m = w, _(w, k({
550
+ get id() {
551
+ return n.rootId || "dynamix-layout-root";
552
+ }
553
+ }, n, {
554
+ get "data-testid"() {
555
+ return n.rootId || "dynamix-layout-root";
556
+ },
557
+ get class() {
558
+ return J() ? "is-dragging" : "";
559
+ },
560
+ get style() {
561
+ return {
562
+ position: "relative",
563
+ width: "100%",
564
+ height: "100%",
565
+ overflow: "hidden",
566
+ ...n.style
567
+ };
568
+ }
569
+ }), !1, !0), R(w, N(ee, {
570
+ get each() {
571
+ return Array.from(se().values());
572
+ },
573
+ children: (a) => [N(ue, {
574
+ ref: (c) => {
575
+ const p = a.uidNode;
576
+ c ? U.set(p, c) : U.delete(p);
577
+ },
578
+ onDragEnd: M,
579
+ onDragOver: de,
580
+ onDragEnter: q,
581
+ onDragLeave: Y,
582
+ onDrop: j,
583
+ get "data-uid"() {
584
+ return a.uidNode;
585
+ },
586
+ get "data-type"() {
587
+ return a.typNode;
588
+ },
589
+ get class() {
590
+ return "hide-scrollbar DefaultWrapTabPanel " + (n.tabPanelElementClass || "");
591
+ },
592
+ get style() {
593
+ return {
594
+ position: "absolute",
595
+ ...n.tabPanelElementStyles,
596
+ width: `${a.nodDims.w}px`,
597
+ height: `${a.nodDims.h}px`,
598
+ left: `${a.nodDims.x}px`,
599
+ top: `${a.nodDims.y}px`,
600
+ "background-color": "transparent"
601
+ };
602
+ }
603
+ }), N(oe, {
604
+ get draggable() {
605
+ return !A();
606
+ },
607
+ get "data-uid"() {
608
+ return a.uidNode;
609
+ },
610
+ "data-type": "tabset",
611
+ onDragOver: z,
612
+ onDragStart: te,
613
+ onDragEnd: M,
614
+ onDragEnter: q,
615
+ onDragLeave: Y,
616
+ onDrop: j,
617
+ ref: (c) => {
618
+ const p = a.uidNode;
619
+ c ? d.set(p, c) : d.delete(p);
620
+ },
621
+ get class() {
622
+ return "hide-scrollbar " + (n.tabHeadElementClass || "");
623
+ },
624
+ get style() {
625
+ return {
626
+ ...n.tabHeadElementStyles,
627
+ position: "absolute",
628
+ "z-index": 99,
629
+ width: `${a.nodDims.w}px`,
630
+ height: `${n.tabHeadHeight || P._minH}px`,
631
+ left: `${a.nodDims.x}px`,
632
+ top: `${a.nodDims.y}px`,
633
+ cursor: A() ? "wait" : "pointer"
634
+ };
635
+ },
636
+ get children() {
637
+ return N(ee, {
638
+ get each() {
639
+ return a.nodKids;
640
+ },
641
+ children: (c) => N(ge, {
642
+ get "data-uid"() {
643
+ return c.uidNode;
644
+ },
645
+ "data-type": "tab",
646
+ onDragStart: te,
647
+ onDragEnd: M,
648
+ get draggable() {
649
+ return !A();
650
+ },
651
+ get active() {
652
+ return !!c.nodOpen;
653
+ },
654
+ get class() {
655
+ return "hide-scrollbar " + (n.tabLabelElementClass || "");
656
+ },
657
+ get style() {
658
+ return {
659
+ cursor: A() ? "wait" : "pointer",
660
+ ...n.tabLabelElementStyles
661
+ };
662
+ },
663
+ onClick: K,
664
+ get children() {
665
+ return xe(() => !!n.tabNames)() && n.tabNames.get(c.nodName) || c.nodName;
666
+ }
667
+ })
668
+ });
669
+ }
670
+ })]
671
+ }), null), R(w, N(ee, {
672
+ get each() {
673
+ return o().keys;
674
+ },
675
+ children: (a) => {
676
+ const c = o().maps.get(a)?.uqid;
677
+ return N(H, {
678
+ id: c,
679
+ draggable: !1,
680
+ "data-uid": c,
681
+ get class() {
682
+ return "hide-scrollbar " + (n.tabBodyElementClass || "");
683
+ },
684
+ get style() {
685
+ return {
686
+ position: "absolute",
687
+ "z-index": 90,
688
+ "overscroll-behavior": "contain",
689
+ ...n.tabBodyElementStyles
690
+ };
691
+ },
692
+ ref: (p) => {
693
+ c && (p ? ae.set(c, p) : ae.delete(c));
694
+ },
695
+ get children() {
696
+ return o().maps.get(a)?.node || Ge();
697
+ }
698
+ });
699
+ }
700
+ }), null), R(w, N(ee, {
701
+ get each() {
702
+ return Array.from(h().values());
703
+ },
704
+ children: (a) => N(O, {
705
+ get id() {
706
+ return a.uidNode;
707
+ },
708
+ get "data-uid"() {
709
+ return a.uidNode;
710
+ },
711
+ get direction() {
712
+ return a.nodeDir;
713
+ },
714
+ onPointerDown: ne,
715
+ get class() {
716
+ return "hide-scrollbar " + (n.sliderElementClass || "");
717
+ },
718
+ ref: (c) => {
719
+ const p = a.uidNode;
720
+ c ? E.set(p, c) : E.delete(p);
721
+ },
722
+ get style() {
723
+ return {
724
+ width: `${a.nodDims.w}px`,
725
+ height: `${a.nodDims.h}px`,
726
+ left: `${a.nodDims.x}px`,
727
+ top: `${a.nodDims.y}px`,
728
+ cursor: a.nodeDir ? "ns-resize" : "ew-resize",
729
+ ...n.sliderElementStyles
730
+ };
731
+ }
732
+ })
733
+ }), null), R(w, N(fe, {
734
+ get class() {
735
+ return "hide-scrollbar " + (n.hoverElementClass || "");
736
+ },
737
+ get style() {
738
+ return {
739
+ ...n.hoverElementStyles
740
+ };
741
+ },
742
+ ref: (a) => le.current = a
743
+ }), null), R(w, N(ee, {
744
+ each: ["left", "right", "top", "bottom"],
745
+ children: (a, c) => N(Ye, {
746
+ onDragOver: ce,
747
+ onDragEnd: M,
748
+ onDragEnter: q,
749
+ onDragLeave: Y,
750
+ onDrop: j,
751
+ get "data-uid"() {
752
+ return n.rootId || "dynamix-layout-root";
753
+ },
754
+ "data-area": a,
755
+ get class() {
756
+ return "hide-scrollbar " + (n.RootSplitterHoverElClass || "");
757
+ },
758
+ ref: (p) => {
759
+ p && (re[c()] = p);
760
+ },
761
+ get style() {
762
+ return {
763
+ ...n.RootSplitterHoverElStyles
764
+ };
765
+ },
766
+ area: a,
767
+ size: {
768
+ h: "25%",
769
+ w: "8px"
770
+ }
771
+ })
772
+ }), null), w;
773
+ })();
774
+ };
775
+ export {
776
+ Xe as DefaultHoverElement,
777
+ qe as DefaultSliderElement,
778
+ je as DefaultWrapTabBody,
779
+ Ue as DefaultWrapTabHead,
780
+ Me as DefaultWrapTabLabel,
781
+ Fe as DefaultWrapTabPanel,
782
+ tt as DynamixLayout,
783
+ Ye as RootSplitterHoverEl,
784
+ Ve as getTabOutput,
785
+ Je as useDynamixLayout
786
+ };
@@ -0,0 +1,23 @@
1
+ import { JSX } from 'solid-js';
2
+ type DivProps = {
3
+ children?: JSX.Element;
4
+ active?: boolean;
5
+ } & JSX.HTMLAttributes<HTMLDivElement>;
6
+ export declare const DefaultWrapTabLabel: (props: DivProps) => JSX.Element;
7
+ export declare const DefaultWrapTabBody: (props: DivProps) => JSX.Element;
8
+ export declare const DefaultWrapTabHead: (props: DivProps) => JSX.Element;
9
+ export declare const DefaultWrapTabPanel: (props: DivProps) => JSX.Element;
10
+ export declare const DefaultHoverElement: (props: DivProps) => JSX.Element;
11
+ export declare const DefaultSliderElement: (props: {
12
+ direction?: boolean;
13
+ children?: JSX.Element;
14
+ } & DivProps) => JSX.Element;
15
+ export declare const RootSplitterHoverEl: (props: {
16
+ area: "left" | "right" | "top" | "bottom";
17
+ size?: {
18
+ w: string;
19
+ h: string;
20
+ };
21
+ gap?: string;
22
+ } & DivProps) => JSX.Element;
23
+ export {};
@@ -0,0 +1,4 @@
1
+ import { ParentComponent } from 'solid-js';
2
+ import { LayoutProps, TabInput, TabOutput } from '../types';
3
+ export declare const getTabOutput: (input: TabInput) => TabOutput;
4
+ export declare const DynamixLayout: ParentComponent<LayoutProps>;
@@ -0,0 +1,34 @@
1
+ import { LayoutTree, DynamixLayoutCore, NodeOptions } from '../../../core/src';
2
+ import { useDynamixLayoutOptions } from '../types';
3
+ import { Accessor, Setter } from 'solid-js';
4
+ export declare const useDynamixLayout: ({ tabOutput, rootId, layoutTree, updateJSON, dimensions, tabHeadHeight, enableTabbar, bondWidth, minTabHeight, minTabWidth, sliderUpdateTimeout, windowResizeTimeout, disableSliderTimeout, disableResizeTimeout, }: useDynamixLayoutOptions) => {
5
+ tabsets: Accessor<Map<string, NodeOptions>>;
6
+ sliders: Accessor<Map<string, NodeOptions>>;
7
+ tabsetsRef: Map<string, HTMLDivElement>;
8
+ panelsRef: Map<string, HTMLDivElement>;
9
+ tabsRef: Map<string, HTMLDivElement>;
10
+ slidersRef: Map<string, HTMLDivElement>;
11
+ layoutJSON: Accessor<LayoutTree | undefined>;
12
+ layoutInstance: DynamixLayoutCore;
13
+ hoverElementRef: {
14
+ current: HTMLDivElement | undefined;
15
+ };
16
+ rootSplitHoverEl: HTMLDivElement[];
17
+ dragging: Accessor<boolean>;
18
+ isUpdating: Accessor<boolean>;
19
+ setIsUpdating: Setter<boolean>;
20
+ setDragging: Setter<boolean>;
21
+ setTabsets: Setter<Map<string, NodeOptions>>;
22
+ setSliders: Setter<Map<string, NodeOptions>>;
23
+ setLayoutJSON: Setter<LayoutTree | undefined>;
24
+ onDragStart: (e: DragEvent) => void;
25
+ onDragOver: (e: DragEvent) => void;
26
+ onDragEnd: (e: DragEvent) => void;
27
+ onDragEnter: (e: DragEvent) => void;
28
+ onDragLeave: (e: DragEvent) => void;
29
+ onDrop: (e: DragEvent) => void;
30
+ onPointerDown: (e: PointerEvent) => void;
31
+ updateActiveTab: (e: MouseEvent) => void;
32
+ handleRootSplit: (e: DragEvent) => void;
33
+ handleNavbarDragOver: (e: DragEvent) => void;
34
+ };
@@ -0,0 +1,4 @@
1
+ export * from './components/Layout';
2
+ export * from './hooks/useLayout';
3
+ export * from './components/Default';
4
+ export * from './types';
@@ -0,0 +1,100 @@
1
+ import { LayoutTree, Dimension } from '../../../core/src';
2
+ import { JSX } from 'solid-js';
3
+ export interface DynamixLayoutProps {
4
+ children?: JSX.Element;
5
+ layoutTree?: LayoutTree;
6
+ tabs?: string[];
7
+ class?: string;
8
+ style?: JSX.CSSProperties;
9
+ }
10
+ export interface UseDynamixLayoutOptions {
11
+ initialLayoutTree?: LayoutTree;
12
+ tabs?: string[];
13
+ }
14
+ export interface UseDynamixLayoutResult {
15
+ layoutTree: LayoutTree | undefined;
16
+ tabs: string[];
17
+ setTabs: (tabs: string[]) => void;
18
+ setLayoutTree: (layoutTree: LayoutTree) => void;
19
+ }
20
+ export type DivFC = (props: {
21
+ children?: JSX.Element;
22
+ } & JSX.HTMLAttributes<HTMLDivElement>) => JSX.Element;
23
+ export type TabEntry = {
24
+ uqid: string;
25
+ name: string;
26
+ node: JSX.Element;
27
+ };
28
+ export type TabInput = [string, JSX.Element][];
29
+ export type TabOutput = {
30
+ keys: string[];
31
+ maps: Map<string, TabEntry>;
32
+ name: Map<string, string>;
33
+ };
34
+ export interface LayoutProps {
35
+ tabs: [string, JSX.Element][];
36
+ enableTabbar?: boolean;
37
+ WrapTabPanel?: DivFC;
38
+ WrapTabLabel?: (props: {
39
+ children?: JSX.Element;
40
+ active?: boolean;
41
+ } & JSX.HTMLAttributes<HTMLDivElement>) => JSX.Element;
42
+ WrapTabHead?: DivFC;
43
+ WrapTabBody?: DivFC;
44
+ HoverElement?: DivFC;
45
+ SliderElement?: (props: {
46
+ children?: JSX.Element;
47
+ direction?: boolean;
48
+ } & JSX.HTMLAttributes<HTMLDivElement>) => JSX.Element;
49
+ tabHeadHeight?: number;
50
+ layoutTree?: LayoutTree;
51
+ pad?: {
52
+ t: number;
53
+ b: number;
54
+ l: number;
55
+ r: number;
56
+ };
57
+ class?: string;
58
+ style?: JSX.CSSProperties;
59
+ bondWidth?: number;
60
+ updateJSON?: (layoutTree: LayoutTree) => void;
61
+ minTabHeight?: number;
62
+ minTabWidth?: number;
63
+ sliderUpdateTimeout?: number;
64
+ windowResizeTimeout?: number;
65
+ disableSliderTimeout?: boolean;
66
+ disableResizeTimeout?: boolean;
67
+ hoverElementStyles?: JSX.CSSProperties;
68
+ sliderElementStyles?: JSX.CSSProperties;
69
+ tabPanelElementStyles?: JSX.CSSProperties;
70
+ tabBodyElementStyles?: JSX.CSSProperties;
71
+ tabHeadElementStyles?: JSX.CSSProperties;
72
+ tabLabelElementStyles?: JSX.CSSProperties;
73
+ RootSplitterHoverElStyles?: JSX.CSSProperties;
74
+ hoverElementClass?: string;
75
+ sliderElementClass?: string;
76
+ tabPanelElementClass?: string;
77
+ tabBodyElementClass?: string;
78
+ tabHeadElementClass?: string;
79
+ tabLabelElementClass?: string;
80
+ RootSplitterHoverElClass?: string;
81
+ rootId?: string;
82
+ tabNames?: Map<string, string | JSX.Element>;
83
+ }
84
+ export interface useDynamixLayoutOptions {
85
+ tabOutput: TabOutput;
86
+ rootId: string;
87
+ layoutTree?: LayoutTree;
88
+ updateJSON?: (layoutTree: LayoutTree) => void;
89
+ enableTabbar: boolean;
90
+ dimensions: () => Dimension;
91
+ sliderUpdateTimeout: number;
92
+ windowResizeTimeout: number;
93
+ disableSliderTimeout: boolean;
94
+ disableResizeTimeout: boolean;
95
+ hoverElementStyles?: JSX.CSSProperties;
96
+ bondWidth: number;
97
+ minTabHeight: number;
98
+ minTabWidth: number;
99
+ tabHeadHeight: number;
100
+ }
package/package.json ADDED
@@ -0,0 +1,93 @@
1
+ {
2
+ "name": "@dynamix-layout/solid",
3
+ "version": "0.0.1",
4
+ "description": "A powerful SolidJS component for creating dynamic, resizable, and draggable layouts.",
5
+ "keywords": [
6
+ "solid",
7
+ "layout",
8
+ "resizable",
9
+ "draggable",
10
+ "split-layout",
11
+ "tabs",
12
+ "dynamic-layout",
13
+ "solid-layout",
14
+ "solid-component"
15
+ ],
16
+ "author": "Akash Aman <sir.akashaman@gmail.com> (https://akash.cx)",
17
+ "funding": [
18
+ {
19
+ "type": "patreon",
20
+ "url": "https://www.patreon.com/akashaman"
21
+ },
22
+ {
23
+ "type": "buymeacoffee",
24
+ "url": "https://www.buymeacoffee.com/akashaman"
25
+ }
26
+ ],
27
+ "repository": {
28
+ "type": "git",
29
+ "url": "https://github.com/akashaman/dynamix-layout",
30
+ "directory": "packages/solid"
31
+ },
32
+ "bugs": {
33
+ "url": "https://github.com/akashaman/dynamix-layout/issues"
34
+ },
35
+ "homepage": "https://github.com/akashaman/dynamix-layout#readme",
36
+ "main": "./dist/index.cjs.js",
37
+ "module": "./dist/index.es.js",
38
+ "types": "./dist/types/index.d.ts",
39
+ "typings": "./dist/types/index.d.ts",
40
+ "style": "./dist/index.css",
41
+ "exports": {
42
+ ".": {
43
+ "types": "./dist/types/index.d.ts",
44
+ "import": "./dist/index.es.js",
45
+ "require": "./dist/index.cjs.js"
46
+ },
47
+ "./style.css": "./dist/index.css"
48
+ },
49
+ "files": [
50
+ "dist",
51
+ "LICENSE",
52
+ "CHANGELOG.md",
53
+ "README.md",
54
+ "!**/*.map"
55
+ ],
56
+ "sideEffects": [
57
+ "./dist/index.css"
58
+ ],
59
+ "publishConfig": {
60
+ "access": "public"
61
+ },
62
+ "type": "module",
63
+ "engines": {
64
+ "node": ">=22.16.0",
65
+ "pnpm": ">=10.13.1"
66
+ },
67
+ "license": "MIT",
68
+ "devDependencies": {
69
+ "@solidjs/testing-library": "^0.8.10",
70
+ "@testing-library/jest-dom": "^6.6.3",
71
+ "jsdom": "^26.1.0",
72
+ "typescript": "^5.8.3",
73
+ "vite": "^7.0.5",
74
+ "vite-plugin-solid": "2.11.7",
75
+ "vitest": "^3.2.4",
76
+ "@repo/eslint-config": "0.0.0",
77
+ "@repo/typescript-config": "0.0.0"
78
+ },
79
+ "dependencies": {
80
+ "solid-js": "^1.9.7",
81
+ "@dynamix-layout/core": "0.0.8"
82
+ },
83
+ "scripts": {
84
+ "dev": "vite build --watch",
85
+ "debug": "vite --debug",
86
+ "clean": "rm -rf dist",
87
+ "build": "pnpm run clean && vite build && cp ../../LICENSE dist/LICENSE",
88
+ "dev:local": "vite",
89
+ "preview": "vite preview",
90
+ "lint": "eslint . --ext ts,tsx",
91
+ "test": "vitest"
92
+ }
93
+ }