@dynamix-layout/solid 1.1.0 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,31 @@
1
1
  # @dynamix-layout/solid
2
2
 
3
+ ## 2.0.0
4
+
5
+ ### Major Changes
6
+
7
+ - [#87](https://github.com/xcode-studio/dynamix-layout/pull/87) [`a31dc4c`](https://github.com/xcode-studio/dynamix-layout/commit/a31dc4c2aef4facb8b80f94b9e3d97c36e148ccc) Thanks [@akash-aman](https://github.com/akash-aman)! - **Runs on the v2 core.** `<DynamixLayout>` keeps its props, default components and drag-and-drop, but each component now has its own engine instance. Two Solid layouts on a page no longer share state, and a layout away from the viewport's top-left is placed correctly.
8
+
9
+ - **Installs on Node 18 and later** (1.x required Node 22).
10
+
11
+ **New:**
12
+ - `tabs` is reactive: add an entry to open a tab, remove it to close one. Existing tabs keep their content mounted.
13
+ - Closable tabs: a third tuple element `{ title, closable }` and an `onTabClose` prop.
14
+ - `onReady(layout)` gives the engine for actions from code (`maximize`, `fold`, `selectTab`, `moveTab`, `reset`, `toJSON`, …).
15
+ - `updateJSON(layout, reason)` also says why it was called: `'move'`, `'resize'`, `'select'`, `'fold'`, `'maximize'`, `'tabs'`, `'reset'`, or `'mount'` for the first call (type `LayoutUpdateReason`).
16
+
17
+ **Breaking:**
18
+ - `layoutTree` accepts v2 JSON (v1 trees are migrated automatically), and `updateJSON` receives v2 `LayoutJSON`.
19
+ - `getTabOutput` and the `TabEntry`/`TabInput`/`TabOutput` types are removed, and tab ids are the tab labels.
20
+ - `useDynamixLayout` returns a new shape.
21
+ - The slider timeout options no longer apply; splitters update once per frame.
22
+ - `solid-js` is a peer dependency.
23
+
24
+ ### Patch Changes
25
+
26
+ - Updated dependencies [[`a31dc4c`](https://github.com/xcode-studio/dynamix-layout/commit/a31dc4c2aef4facb8b80f94b9e3d97c36e148ccc)]:
27
+ - @dynamix-layout/core@2.0.0
28
+
3
29
  ## 1.1.0
4
30
 
5
31
  ### Minor Changes
package/README.md CHANGED
@@ -72,9 +72,11 @@ The `<DynamixLayout />` component is the primary way to use this package. It's h
72
72
 
73
73
  | Prop | Type | Description | Default |
74
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()` |
75
+ | **`tabs`** (required) | `TabItem[]` | `[id, component, options?]` tuples. `options` is `{ title?, closable? }`. The array is reactive: add or remove entries and only those tabs mount or unmount. | |
76
+ | `onTabClose` | `(tabId: string) => void` | Called by the × button of a `closable` tab. Remove the tab from `tabs` to close it. | `undefined` |
77
+ | `onReady` | `(layout: Layout) => void` | Receives the core engine once mounted, for `toggleMaximize`, `toggleFold`, `selectTab`, `moveTab`, `reset` and the rest of the [core API](../../docs/api/create-layout.md). | `undefined` |
78
+ | `layoutTree` | `LayoutJSON \| LayoutTreeV1` | A saved layout to restore. Layouts saved by v1 are migrated automatically. | `undefined` |
79
+ | `tabNames` | `Map<string, string \| JSX.Element>` | Display names for your tabs, keyed by tab id. | `undefined` |
78
80
  | `enableTabbar` | `boolean` | If `true`, renders the draggable tab bar on top of each tab panel. | `true` |
79
81
  | `tabHeadHeight` | `number` | The height of the tab bar in pixels. | `40` |
80
82
  | `pad` | `{ t, b, l, r }` | Padding for the root layout container in pixels. | `{ t: 0, b: 0, l: 0, r: 0 }` |
@@ -83,9 +85,9 @@ The `<DynamixLayout />` component is the primary way to use this package. It's h
83
85
  | `bondWidth` | `number` | The width/height of the draggable slider between panels in pixels. | `10` |
84
86
  | `rootId` | `string` | The HTML `id` for the root `<div>` element of the layout. | `"dynamix-layout-root"` |
85
87
  | `disableResizeTimeout` | `boolean` | Disables debounce on window resize for faster updates. Can impact performance. | `true` |
86
- | `disableSliderTimeout` | `boolean` | Disables debounce when dragging a slider. | `true` |
88
+ | `disableSliderTimeout` | `boolean` | No effect since 2.0: splitters update once per animation frame. | `true` |
87
89
  | `windowResizeTimeout` | `number` | Debounce timeout in milliseconds for window resize events. | `2` |
88
- | `sliderUpdateTimeout` | `number` | Debounce timeout in milliseconds for slider drag events. | `2` |
90
+ | `sliderUpdateTimeout` | `number` | No effect since 2.0. | `2` |
89
91
  | `...props` | `JSX.HTMLAttributes` | Standard HTML attributes like `style` and `class` are passed to the root `<div>`. | |
90
92
 
91
93
  ### 🎨 Customization with Wrapper Components
@@ -106,7 +108,7 @@ You can completely change the look and feel of the layout by providing your own
106
108
  ```jsx
107
109
  import { DynamixLayout } from '@dynamix-layout/solid';
108
110
  import type { Component, JSX } from 'solid-js';
109
- immport { MyCustomSlider } from "./compoments";
111
+ import { MyCustomSlider } from './components';
110
112
 
111
113
  function App() {
112
114
  // ... (myTabs definition from "Getting Started")
@@ -137,43 +139,26 @@ For finer-grained control, you can pass `style` objects or `class` strings to th
137
139
 
138
140
  -----
139
141
 
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).
142
+ ## ⚙️ The `useDynamixLayout` hook
159
143
 
144
+ The Solid `useDynamixLayout` binds a `@dynamix-layout/core` instance to Solid signals for `<DynamixLayout>`. Its shape changed in 2.0 and it is mainly an implementation detail of the component. For a custom renderer, build on [`createLayout`](https://github.com/xcode-studio/dynamix-layout/blob/main/docs/guides/core-without-react.md) directly. A headless Solid API, matching the React hooks, is planned.
160
145
 
161
146
  -----
162
147
 
163
148
  ### Example: Saving a Layout
164
149
 
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.
150
+ - `updateJSON` receives the layout as [`LayoutJSON`](https://github.com/xcode-studio/dynamix-layout/blob/main/docs/api/layout-json.md) (`version: 2`) once on mount and after every change (a drop, a splitter release, selecting a tab, maximize or fold). Its second argument says why: `'mount'` for the first call, then `'move'`, `'resize'`, `'select'`, `'fold'`, `'maximize'`, `'tabs'` or `'reset'`. Save it to localStorage, a database, or anywhere else, and pass it back as `layoutTree`.
166
151
 
167
152
  ```jsx
168
153
  import { tabs } from './comp'
169
154
  import { DynamixLayout } from '@dynamix-layout/solid'
170
- import type { LayoutTree } from '@dynamix-layout/core'
155
+ import type { LayoutJSON } from '@dynamix-layout/solid'
171
156
  import '@dynamix-layout/solid/style.css'
172
157
 
173
158
  function App() {
174
159
 
175
- const UpdateJSON = (layoutTree: LayoutTree) => {
176
- console.log(layoutTree);
160
+ const UpdateJSON = (layout: LayoutJSON) => {
161
+ localStorage.setItem('layout', JSON.stringify(layout));
177
162
  };
178
163
 
179
164
  return (
package/dist/index.cjs CHANGED
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const n=require("solid-js/web"),d=require("@dynamix-layout/core"),x=require("solid-js");var O=n.template("<div>"),He=n.template("<div><div style=display:flex;align-items:center;gap:4px;height:100%>"),Oe=n.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=n.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 style=transform:rotate(90deg)><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>'),_e=n.template('<svg xmlns=http://www.w3.org/2000/svg width=14 height=14 viewBox="0 0 24 24"fill=none stroke=currentColor stroke-width=2 stroke-linecap=round stroke-linejoin=round aria-hidden=true><path>'),We=n.template("<div class=DefaultTabsetToolbar>"),ue=n.template("<button type=button class=DefaultTabsetToolbarButton>");const me=e=>(()=>{var o=O();return n.spread(o,n.mergeProps(e,{get class(){return`DefaultWrapTabLabel ${e.class||""}`},get"data-state"(){return e.active?"active":"inactive"},get style(){return{"align-self":"center",padding:"4px 6px","box-sizing":"border-box","font-size":"14px","border-radius":"4px",...e.style}}}),!1,!0),n.insert(o,()=>e.children),o})(),fe=e=>(()=>{var o=O();return n.spread(o,n.mergeProps(e,{get class(){return`DefaultWrapTabBody hide-scrollbar ${e.class||""}`},get style(){return{"box-sizing":"border-box",height:"100%",width:"100%",display:"grid",overflow:"auto","scrollbar-width":"none","-ms-overflow-style":"none",...e.style}}}),!1,!0),n.insert(o,()=>e.children),o})(),be=e=>(()=>{var o=O();return n.spread(o,n.mergeProps(e,{get class(){return`DefaultWrapTabHead hide-scrollbar ${e.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",...e.style}}}),!1,!0),n.insert(o,()=>e.children),o})(),he=e=>(()=>{var o=O();return n.spread(o,n.mergeProps(e,{get class(){return`DefaultWrapTabPanel ${e.class||""}`},get style(){return{display:"grid","align-items":"center","place-items":"self-start","box-sizing":"border-box",position:"absolute","border-radius":"8px",...e.style}}}),!1,!0),n.insert(o,()=>e.children),o})(),ve=e=>(()=>{var o=O();return n.spread(o,n.mergeProps(e,{get class(){return`DefaultHoverElement ${e.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)",...e.style}}}),!1,!0),n.insert(o,()=>e.children),o})(),ye=e=>(()=>{var o=He(),v=o.firstChild;return n.spread(o,n.mergeProps(e,{get class(){return`DefaultSliderElement ${e.class||""}`},get style(){return{width:"100%",height:"100%",position:"absolute","box-sizing":"border-box","background-color":"white","z-index":9,cursor:"grab",...e.style}}}),!1,!0),n.insert(v,(()=>{var u=n.memo(()=>!e.direction);return()=>u()?Oe():Ie()})()),n.insert(o,()=>e.children,null),n.effect(u=>n.setStyleProperty(v,"flex-direction",e.direction?"column":"row")),o})(),pe=e=>{const[o,v]=x.splitProps(e,["area","size","gap","class","style","children"]),u=x.createMemo(()=>{const i=o.size||{h:"20%",w:"6px"},m=o.gap||"0px",g={};return o.area==="left"?(Object.assign(g,{"border-top-right-radius":"16px","border-bottom-right-radius":"16px",height:i.h,left:m,width:i.w}),g.top=`calc(50% - ${i.h} / 2)`):o.area==="top"?(Object.assign(g,{"border-bottom-left-radius":"16px","border-bottom-right-radius":"16px",width:i.h,top:m,height:i.w}),g.left=`calc(50% - ${i.h} / 2)`):o.area==="right"?(Object.assign(g,{"border-top-left-radius":"16px","border-bottom-left-radius":"16px",height:i.h,right:m,width:i.w}),g.top=`calc(50% - ${i.h} / 2)`):o.area==="bottom"&&(Object.assign(g,{"border-top-left-radius":"16px","border-top-right-radius":"16px",width:i.h,bottom:m,height:i.w}),g.left=`calc(50% - ${i.h} / 2)`),g});return(()=>{var i=O();return n.spread(i,n.mergeProps(v,{get class(){return`RootSplitterHoverEl ${o.class||""}`},get style(){return{position:"absolute","z-index":-1,display:"none","box-sizing":"border-box","background-color":"#0081f9",cursor:"grab",...o.style,...u()}}}),!1,!0),n.insert(i,()=>o.children),i})()},ge=e=>(()=>{var o=_e(),v=o.firstChild;return n.effect(u=>{var i=e.rotate?{transform:`rotate(${e.rotate}deg)`}:{},m=e.path;return u.e=n.style(o,i,u.e),m!==u.t&&n.setAttribute(v,"d",u.t=m),u},{e:void 0,t:void 0}),o})(),Ae="M8 3H5a2 2 0 0 0-2 2v3M21 8V5a2 2 0 0 0-2-2h-3M3 16v3a2 2 0 0 0 2 2h3M16 21h3a2 2 0 0 0 2-2v-3",Fe="M8 3v3a2 2 0 0 1-2 2H3M21 8h-3a2 2 0 0 1-2-2V3M3 16h3a2 2 0 0 1 2 2v3M16 21v-3a2 2 0 0 1 2-2h3",Be="m15 18-6-6 6-6",xe=e=>{const o=()=>(e.rowIsHorizontal?0:90)+(e.folded?180:0),v=()=>e.rotated?-90:0;let u;return x.onMount(()=>{const i=u?.parentElement;if(!u||!i)return;const m=()=>{u.style.transform=`translateX(${i.scrollLeft}px)`};m(),i.addEventListener("scroll",m,{passive:!0}),x.onCleanup(()=>i.removeEventListener("scroll",m))}),(()=>{var i=We();i.$$dblclick=g=>g.stopPropagation();var m=u;return typeof m=="function"?n.use(m,i):u=i,n.insert(i,(()=>{var g=n.memo(()=>!!e.showMaximize);return()=>g()&&(()=>{var p=ue();return p.$$click=()=>e.onToggleMaximize(),n.insert(p,n.createComponent(ge,{get path(){return e.maximized?Fe:Ae},get rotate(){return v()}})),n.effect(b=>{var T=e.maximized?"Restore":"Maximize",N=e.maximized,S=e.maximized?"Restore (⌥ +)":"Maximize (⌥ +)";return T!==b.e&&n.setAttribute(p,"aria-label",b.e=T),N!==b.t&&n.setAttribute(p,"aria-pressed",b.t=N),S!==b.a&&n.setAttribute(p,"title",b.a=S),b},{e:void 0,t:void 0,a:void 0}),p})()})(),null),n.insert(i,(()=>{var g=n.memo(()=>!!e.showFold);return()=>g()&&(()=>{var p=ue();return p.$$click=()=>e.onToggleFold(),n.insert(p,n.createComponent(ge,{path:Be,get rotate(){return o()+v()}})),n.effect(b=>{var T=e.folded?"Unfold":"Fold",N=!e.folded,S=e.folded?"Unfold (⌥ -)":"Fold (⌥ -)";return T!==b.e&&n.setAttribute(p,"aria-label",b.e=T),N!==b.t&&n.setAttribute(p,"aria-expanded",b.t=N),S!==b.a&&n.setAttribute(p,"title",b.a=S),b},{e:void 0,t:void 0,a:void 0}),p})()})(),null),i})()};n.delegateEvents(["dblclick","click"]);const we=({tabOutput:e,rootId:o,layoutTree:v,updateJSON:u,dimensions:i,tabHeadHeight:m,enableTabbar:g,bondWidth:p,minTabHeight:b,minTabWidth:T,sliderUpdateTimeout:N,windowResizeTimeout:S,disableSliderTimeout:I,disableResizeTimeout:_,keyboardShortcuts:W=!0,enableDoubleClickMaximize:Q=!0})=>{const A=new Map,X=new Map,F=new Map,V=new Map,E={current:void 0},B=[],[j,H]=x.createSignal(v),[ee,Y]=x.createSignal(new Map),[te,J]=x.createSignal(new Map),[re,C]=x.createSignal(!1);let $=null;const[ne,ae]=x.createSignal(!1),l={src:void 0,des:void 0,area:void 0,drag:!1},M={sliderId:void 0,isSliding:!1},Z=g?Math.max(b,m):b,z=new d.DynamixLayoutCore({tabs:e.keys,tree:j(),minW:T,minH:Z,bond:p,uqid:o,tabsIds:e.name,collapsedSize:g?m:Z}),q=t=>{const r=new Map(t);Y(r)},U=t=>{const r=new Map(t);J(r)},y=()=>{const t=g?m:0;d.Node.cache.tabOpts.get().forEach((r,c)=>{const s=V.get(c);if(!s)return;const f=d.getTabBodyRect(r.nodDims,t);d.setElementRect(s,f);const ce=r.nodOpen&&!r.nodFold&&!r.nodHidden&&f.h>0;s.style.display=ce?"block":"none"})},R=d.Node.cache.nodOpts.onChange(t=>{t.forEach((r,c)=>{const s=F.get(c);s&&d.setElementRect(s,r.nodDims);const f=A.get(c);f&&g&&(f.toggleAttribute("data-dx-hidden",!!r.nodHidden),d.placeTabbar(f,d.getTabbarPlacement(r,m)))})}),a=d.Node.cache.tabOpts.onChange(()=>y()),h=d.Node.cache.bndOpts.onChange(t=>{t.forEach((r,c)=>{const s=X.get(c);s&&(d.setElementRect(s,r.nodDims),s.toggleAttribute("data-dx-hidden",!!r.nodHidden),s.style.pointerEvents=r.nodLocked?"none":"")})}),w=d.createFrameScheduler(({id:t,point:r})=>z.updateSlider(t,r,I,N)),K=t=>{const r=M.sliderId;!M.isSliding||!r||w.schedule({id:r,point:{x:t.clientX,y:t.clientY}})},P=t=>{if(!M.isSliding)return;w.flush();const r=t.currentTarget;M.isSliding=!1,M.sliderId=void 0,C(!1),u&&u(d.DynamixLayoutCore._root.toJSON()),r.releasePointerCapture(t.pointerId),r.removeEventListener("pointermove",K),r.removeEventListener("pointerup",P),r.removeEventListener("pointercancel",P)},D=t=>{t.preventDefault();const r=t.currentTarget;M.isSliding=!0,M.sliderId=r.id,C(!0),r.setPointerCapture(t.pointerId),r.addEventListener("pointermove",K),r.addEventListener("pointerup",P),r.addEventListener("pointercancel",P)};let L={};const De=(t,r,c)=>{if(!E.current||!l||!c)return null;const s=d.getTabsetDropPreview(c.getBoundingClientRect(),t,r);G(s),l.des=c,l.area=s.area},Ee=t=>{t.preventDefault(),t.stopPropagation(),t.dataTransfer&&(t.dataTransfer.dropEffect="move");const r=t.currentTarget;if(r.hasAttribute("data-rotated")){if(!E.current||!l)return;const f=r.getBoundingClientRect();G({area:"contain",left:f.left,top:f.top,width:f.width,height:f.height}),l.des=r,l.area="contain";return}const c=Array.from(r.querySelectorAll(':scope > [data-type="tab"]'));if(!E.current||!l)return;const s=d.getNavbarDropPreview(r.getBoundingClientRect(),c.map(f=>f.getBoundingClientRect()),t.clientX,t.clientY);s&&(G(s),l.des=c[s.index],l.area=s.area)},Ce=t=>{t.preventDefault(),t.stopPropagation(),t.dataTransfer&&(t.dataTransfer.dropEffect="move");const r=t.currentTarget,{area:c,uid:s}=r.dataset;if(!c||!s||!E.current||!l)return;const f=c;l.des=r,l.area=f,G(d.getRootSplitPreview(i(),f))},G=t=>{const r=E.current;!r||d.isSameDropPreview(L,t)||(Object.assign(r.style,{left:`${t.left}px`,top:`${t.top}px`,width:`${t.width}px`,height:`${t.height}px`,display:"block",zIndex:"100"}),L=t)};let oe=null;const ie=()=>{q(d.Node.cache.nodOpts.get()),U(d.Node.cache.bndOpts.get()),y(),u&&u(d.DynamixLayoutCore._root.toJSON())},le=t=>{z.toggleMaximize(t)&&ie()},se=t=>{z.toggleCollapse(t)&&ie()},Se=t=>{const r=t.target.closest("[data-uid]"),c=r?.dataset.uid?d.Node.cache.mapElem.get(r.dataset.uid):void 0;c instanceof d.Node&&(c.type==="tabset"?oe=c.unId:c.type==="tab"&&c.host&&(oe=c.host.unId))},$e=t=>{const r=t.currentTarget.dataset.uid;Q&&r&&le(r)},de=t=>{if(!W||!t.altKey||t.ctrlKey||t.metaKey)return;const r=oe??z.maximizedId;r&&(t.code==="Equal"||t.code==="NumpadAdd"?(t.preventDefault(),le(r)):(t.code==="Minus"||t.code==="NumpadSubtract")&&(t.preventDefault(),se(r)))},ze=t=>{if(t.stopPropagation(),z.restore()&&ie(),C(!0),document.body.style.cursor="move",t.currentTarget){if(t.dataTransfer){t.dataTransfer.effectAllowed="move";const r=document.createElement("div");r.style.width="1px",r.style.height="1px",r.style.backgroundColor="transparent",r.style.position="absolute",r.style.top="-1000px",document.body.appendChild(r),t.dataTransfer.setDragImage(r,0,0),setTimeout(()=>{r.parentNode&&r.parentNode.removeChild(r)},0)}B.forEach(r=>{r&&(r.style.display="block",r.style.zIndex="99")}),F.forEach(r=>{r&&(r.style.display="block",r.style.zIndex="95")}),l.src=t.currentTarget,l.drag=!0}},Ne=t=>{if(t.preventDefault(),t.stopPropagation(),document.body.style.cursor="move",t.dataTransfer&&(t.dataTransfer.dropEffect="move"),!l?.src)return;const r=t.currentTarget,c=t.clientX,s=t.clientY;$&&cancelAnimationFrame($),$=requestAnimationFrame(()=>{De(c,s,r)})},Me=()=>{if(document.body.style.cursor="default",B.forEach(t=>{t&&(t.style.display="none",t.style.zIndex="-1")}),$&&(cancelAnimationFrame($),$=null),E.current&&(E.current.style.display="none",E.current.style.zIndex="-1"),L={},l.drag=!1,!l?.src||!l?.des){l.area=void 0,l.src=void 0,l.des=void 0,C(!1);return}if(l.src===l.des){l.area=void 0,l.src=void 0,l.des=void 0,C(!1);return}if(l.src&&l.des){if(!l.area){console.warn("No area specified for drag and drop"),C(!1);return}if(!z.updateTree(l.src.dataset.uid,l.des.dataset.uid,l.area||"contain")){console.warn("Failed to update layout tree"),C(!1);return}requestAnimationFrame(()=>{q(d.Node.cache.nodOpts.get()),U(d.Node.cache.bndOpts.get()),y(),u&&u(d.DynamixLayoutCore._root.toJSON())})}l.area=void 0,l.src=void 0,l.des=void 0,C(!1)},Re=t=>{t.preventDefault(),t.stopPropagation(),t.dataTransfer&&(t.dataTransfer.dropEffect="move")},Le=t=>{t.preventDefault(),t.stopPropagation()},Pe=t=>{t.preventDefault(),t.stopPropagation(),t.dataTransfer&&t.dataTransfer.getData("text/plain")},ke=t=>{const r=t.currentTarget,c=r.dataset.uid;if(!c)return;const s=d.Node.cache.mapElem.get(c);if(!(s instanceof d.Node)){console.warn(`Element with uid ${c} is not a Node instance`);return}if(!s||!s.host||!s.host.unId){console.warn(`Node with uid ${c} not found in mapNode`);return}if(s.host.open==s.name){console.warn(`Node ${s.name} is already open`);return}const f=d.Node.cache.nodOpts.get().get(s.host.unId);if(!f||f.nodOpen&&s?.open)return;s.host.open=s.name,f.nodOpen=s.name,f.nodKids?.forEach(k=>{k.nodOpen=k.nodName===s.name}),r?.parentElement?.childNodes?.forEach(k=>{k instanceof HTMLDivElement&&k.dataset.uid!==c?k.dataset.state="inactive":k.dataset.state="active"}),y()};return x.onMount(()=>{const t=c=>{z.updateDimension(i(),c,S)};t(!0);const r=()=>t(_??!1);window.addEventListener("resize",r),window.addEventListener("keydown",de),q(d.Node.cache.nodOpts.get()),U(d.Node.cache.bndOpts.get()),y(),u&&u(d.DynamixLayoutCore._root.toJSON()),x.onCleanup(()=>{window.removeEventListener("resize",r),window.removeEventListener("keydown",de),R(),h(),a(),w.cancel(),$&&cancelAnimationFrame($)})}),{tabsets:ee,sliders:te,tabsetsRef:A,panelsRef:F,tabsRef:V,slidersRef:X,layoutJSON:j,layoutInstance:z,hoverElementRef:E,rootSplitHoverEl:B,dragging:re,isUpdating:ne,setIsUpdating:ae,setDragging:C,setTabsets:Y,setSliders:J,setLayoutJSON:H,onDragStart:ze,onDragOver:Ne,onDragEnd:Me,onDragEnter:Re,onDragLeave:Le,onDrop:Pe,onPointerDown:D,updateActiveTab:ke,handleRootSplit:Ce,handleNavbarDragOver:Ee,toggleMaximize:le,toggleCollapse:se,onRootPointerDown:Se,onTabbarDoubleClick:$e}};var je=n.template("<div>"),qe=n.template('<div class="flex items-center justify-center h-full"><span class=text-gray-500>No content');const Te=e=>{const o=[],v=new Map,u=new Map;for(const[i,m]of e){const g=crypto.randomUUID();o.push(i),v.set(i,{uqid:g,name:i,node:m}),u.set(i,g)}return{keys:o,maps:v,name:u}},Ue=e=>{const o=x.createMemo(()=>Te(e.tabs));let v;const u=()=>{const y=v;if(!y)return{w:0,h:0,x:0,y:0};const R=y.getBoundingClientRect(),a=e.pad||{t:0,b:0,l:0,r:0};return{w:R.width-(a.l+a.r),h:R.height-(a.t+a.b),x:R.left+a.l,y:R.top+a.t}},{tabsetsRef:i,slidersRef:m,sliders:g,tabsets:p,hoverElementRef:b,onDragEnd:T,onDragOver:N,onDragStart:S,onDragEnter:I,onDragLeave:_,onDrop:W,dragging:Q,panelsRef:A,onPointerDown:X,handleNavbarDragOver:F,updateActiveTab:V,rootSplitHoverEl:E,handleRootSplit:B,tabsRef:j,isUpdating:H,toggleMaximize:ee,toggleCollapse:Y,onRootPointerDown:te,onTabbarDoubleClick:J}=we({tabOutput:o(),rootId:e.rootId||"dynamix-layout-root",updateJSON:e.updateJSON,enableTabbar:e.enableTabbar===void 0?!0:e.enableTabbar,layoutTree:e.layoutTree,tabHeadHeight:e.tabHeadHeight||d.DynamixLayoutCore._minH,dimensions:u,sliderUpdateTimeout:e.sliderUpdateTimeout||2,windowResizeTimeout:e.windowResizeTimeout||2,bondWidth:e.bondWidth||d.DynamixLayoutCore._bond,minTabHeight:e.minTabHeight||d.DynamixLayoutCore._minH,minTabWidth:e.minTabWidth||d.DynamixLayoutCore._minW,disableSliderTimeout:e.disableSliderTimeout===void 0?!0:e.disableSliderTimeout,disableResizeTimeout:e.disableResizeTimeout===void 0?!0:e.disableResizeTimeout,hoverElementStyles:e.hoverElementStyles,keyboardShortcuts:e.keyboardShortcuts??!0,enableDoubleClickMaximize:e.enableDoubleClickMaximize??!0}),re=e.WrapTabPanel||he,C=e.WrapTabHead||be,$=e.WrapTabLabel||me,ne=e.WrapTabBody||fe,ae=e.SliderElement||ye,l=e.HoverElement||ve,M=e.TabsetToolbar||xe,Z=e.tabHeadHeight||d.DynamixLayoutCore._minH,z=e.enableTabbar??!0,q=e.enableMaximize??!0,U=(e.enableCollapse??!0)&&z;return(()=>{var y=je(),R=v;return typeof R=="function"?n.use(R,y):v=y,n.spread(y,n.mergeProps({get id(){return e.rootId||"dynamix-layout-root"}},e,{get"data-testid"(){return e.rootId||"dynamix-layout-root"},get class(){return Q()?"is-dragging":""},onPointerDown:te,get style(){return{position:"relative",width:"100%",height:"100%",overflow:"hidden",...e.style}}}),!1,!0),n.insert(y,n.createComponent(x.For,{get each(){return Array.from(p().values())},children:a=>{const h=d.getTabbarPlacement(a,Z),w=q&&!!a.nodMaximizable,K=U&&!!a.nodFoldable&&!a.nodMaxd,P=w||K;return[n.createComponent(re,{ref:D=>{const L=a.uidNode;D?A.set(L,D):A.delete(L)},onDragEnd:T,onDragOver:N,onDragEnter:I,onDragLeave:_,onDrop:W,get"data-uid"(){return a.uidNode},get"data-type"(){return a.typNode},get class(){return"hide-scrollbar DefaultWrapTabPanel "+(e.tabPanelElementClass||"")},get style(){return{position:"absolute",...e.tabPanelElementStyles,width:`${a.nodDims.w}px`,height:`${a.nodDims.h}px`,left:`${a.nodDims.x}px`,top:`${a.nodDims.y}px`,"background-color":"transparent"}}}),n.createComponent(C,{get draggable(){return!H()},get"data-uid"(){return a.uidNode},"data-type":"tabset","data-tabbar":"",get"data-folded"(){return a.nodFold?"":void 0},get"data-maximized"(){return a.nodMaxd?"":void 0},get"data-dx-hidden"(){return a.nodHidden?"":void 0},get"data-rotated"(){return h.rotated?"":void 0},onDblClick:J,onDragOver:F,onDragStart:S,onDragEnd:T,onDragEnter:I,onDragLeave:_,onDrop:W,ref:D=>{const L=a.uidNode;D?i.set(L,D):i.delete(L)},get class(){return"hide-scrollbar "+(e.tabHeadElementClass||"")},get style(){return{...e.tabHeadElementStyles,position:"absolute","z-index":99,width:`${h.rect.w}px`,height:`${h.rect.h}px`,left:`${h.rect.x}px`,top:`${h.rect.y}px`,"transform-origin":"0 0",...h.rotated?{transform:"rotate(90deg)"}:{},...P?{"padding-right":"64px"}:{},cursor:H()?"wait":"pointer"}},get children(){return[n.createComponent(x.For,{get each(){return a.nodKids},children:D=>n.createComponent($,{get"data-uid"(){return D.uidNode},"data-type":"tab",onDragStart:S,onDragEnd:T,get draggable(){return!H()},get active(){return!!D.nodOpen},get class(){return"hide-scrollbar "+(e.tabLabelElementClass||"")},get style(){return{cursor:H()?"wait":"pointer",...e.tabLabelElementStyles}},onClick:V,get children(){return n.memo(()=>!!e.tabNames)()&&e.tabNames.get(D.nodName)||D.nodName}})}),n.memo(()=>P&&n.createComponent(M,{get maximized(){return!!a.nodMaxd},get folded(){return!!a.nodFold},get rotated(){return h.rotated},get rowIsHorizontal(){return a.nodeDir===!1},showMaximize:w,showFold:K,onToggleMaximize:()=>ee(a.uidNode),onToggleFold:()=>Y(a.uidNode)}))]}})]}}),null),n.insert(y,n.createComponent(x.For,{get each(){return o().keys},children:a=>{const h=o().maps.get(a)?.uqid;return n.createComponent(ne,{id:h,draggable:!1,"data-uid":h,get class(){return"hide-scrollbar "+(e.tabBodyElementClass||"")},get style(){return{position:"absolute","z-index":90,"overscroll-behavior":"contain",...e.tabBodyElementStyles}},ref:w=>{h&&(w?j.set(h,w):j.delete(h))},get children(){return o().maps.get(a)?.node||qe()}})}}),null),n.insert(y,n.createComponent(x.For,{get each(){return Array.from(g().values())},children:a=>n.createComponent(ae,{get id(){return a.uidNode},get"data-uid"(){return a.uidNode},get"data-dx-hidden"(){return a.nodHidden?"":void 0},get direction(){return a.nodeDir},onPointerDown:X,get class(){return"hide-scrollbar "+(e.sliderElementClass||"")},ref:h=>{const w=a.uidNode;h?m.set(w,h):m.delete(w)},get style(){return{width:`${a.nodDims.w}px`,height:`${a.nodDims.h}px`,left:`${a.nodDims.x}px`,top:`${a.nodDims.y}px`,cursor:a.nodeDir?"ns-resize":"ew-resize",...a.nodLocked?{"pointer-events":"none"}:{},...e.sliderElementStyles}}})}),null),n.insert(y,n.createComponent(l,{get class(){return"hide-scrollbar "+(e.hoverElementClass||"")},get style(){return{...e.hoverElementStyles}},ref:a=>b.current=a}),null),n.insert(y,n.createComponent(x.For,{each:["left","right","top","bottom"],children:(a,h)=>n.createComponent(pe,{onDragOver:B,onDragEnd:T,onDragEnter:I,onDragLeave:_,onDrop:W,get"data-uid"(){return e.rootId||"dynamix-layout-root"},"data-area":a,get class(){return"hide-scrollbar "+(e.RootSplitterHoverElClass||"")},ref:w=>{w&&(E[h()]=w)},get style(){return{...e.RootSplitterHoverElStyles}},area:a,size:{h:"25%",w:"8px"}})}),null),y})()};exports.DefaultHoverElement=ve;exports.DefaultSliderElement=ye;exports.DefaultTabsetToolbar=xe;exports.DefaultWrapTabBody=fe;exports.DefaultWrapTabHead=be;exports.DefaultWrapTabLabel=me;exports.DefaultWrapTabPanel=he;exports.DynamixLayout=Ue;exports.RootSplitterHoverEl=pe;exports.getTabOutput=Te;exports.useDynamixLayout=we;
1
+ /*! @dynamix-layout/solid | MIT License */ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const r=require("solid-js/web"),p=require("@dynamix-layout/core"),g=require("solid-js");var E=r.template("<div>"),Q=r.template("<div><div style=display:flex;align-items:center;gap:4px;height:100%>"),ee=r.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>'),te=r.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 style=transform:rotate(90deg)><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>'),re=r.template('<svg xmlns=http://www.w3.org/2000/svg width=14 height=14 viewBox="0 0 24 24"fill=none stroke=currentColor stroke-width=2 stroke-linecap=round stroke-linejoin=round aria-hidden=true><path>'),ae=r.template("<div class=DefaultTabsetToolbar>"),B=r.template("<button type=button class=DefaultTabsetToolbarButton>");const V=e=>(()=>{var a=E();return r.spread(a,r.mergeProps(e,{get class(){return`DefaultWrapTabLabel ${e.class||""}`},get"data-state"(){return e.active?"active":"inactive"},get style(){return{"align-self":"center",padding:"4px 6px","box-sizing":"border-box","font-size":"14px","border-radius":"4px",...e.style}}}),!1,!0),r.insert(a,()=>e.children),a})(),J=e=>(()=>{var a=E();return r.spread(a,r.mergeProps(e,{get class(){return`DefaultWrapTabBody hide-scrollbar ${e.class||""}`},get style(){return{"box-sizing":"border-box",height:"100%",width:"100%",display:"grid",overflow:"auto","scrollbar-width":"none","-ms-overflow-style":"none",...e.style}}}),!1,!0),r.insert(a,()=>e.children),a})(),K=e=>(()=>{var a=E();return r.spread(a,r.mergeProps(e,{get class(){return`DefaultWrapTabHead hide-scrollbar ${e.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",...e.style}}}),!1,!0),r.insert(a,()=>e.children),a})(),U=e=>(()=>{var a=E();return r.spread(a,r.mergeProps(e,{get class(){return`DefaultWrapTabPanel ${e.class||""}`},get style(){return{display:"grid","align-items":"center","place-items":"self-start","box-sizing":"border-box",position:"absolute","border-radius":"8px",...e.style}}}),!1,!0),r.insert(a,()=>e.children),a})(),I=e=>(()=>{var a=E();return r.spread(a,r.mergeProps(e,{get class(){return`DefaultHoverElement ${e.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)",...e.style}}}),!1,!0),r.insert(a,()=>e.children),a})(),X=e=>(()=>{var a=Q(),l=a.firstChild;return r.spread(a,r.mergeProps(e,{get class(){return`DefaultSliderElement ${e.class||""}`},get style(){return{width:"100%",height:"100%",position:"absolute","box-sizing":"border-box","background-color":"white","z-index":9,cursor:"grab",...e.style}}}),!1,!0),r.insert(l,(()=>{var d=r.memo(()=>!e.direction);return()=>d()?ee():te()})()),r.insert(a,()=>e.children,null),r.effect(d=>r.setStyleProperty(l,"flex-direction",e.direction?"column":"row")),a})(),Z=e=>{const[a,l]=g.splitProps(e,["area","size","gap","class","style","children"]),d=g.createMemo(()=>{const o=a.size||{h:"20%",w:"6px"},m=a.gap||"0px",u={};return a.area==="left"?(Object.assign(u,{"border-top-right-radius":"16px","border-bottom-right-radius":"16px",height:o.h,left:m,width:o.w}),u.top=`calc(50% - ${o.h} / 2)`):a.area==="top"?(Object.assign(u,{"border-bottom-left-radius":"16px","border-bottom-right-radius":"16px",width:o.h,top:m,height:o.w}),u.left=`calc(50% - ${o.h} / 2)`):a.area==="right"?(Object.assign(u,{"border-top-left-radius":"16px","border-bottom-left-radius":"16px",height:o.h,right:m,width:o.w}),u.top=`calc(50% - ${o.h} / 2)`):a.area==="bottom"&&(Object.assign(u,{"border-top-left-radius":"16px","border-top-right-radius":"16px",width:o.h,bottom:m,height:o.w}),u.left=`calc(50% - ${o.h} / 2)`),u});return(()=>{var o=E();return r.spread(o,r.mergeProps(l,{get class(){return`RootSplitterHoverEl ${a.class||""}`},get style(){return{position:"absolute","z-index":-1,display:"none","box-sizing":"border-box","background-color":"#0081f9",cursor:"grab",...a.style,...d()}}}),!1,!0),r.insert(o,()=>a.children),o})()},j=e=>(()=>{var a=re(),l=a.firstChild;return r.effect(d=>{var o=e.rotate?{transform:`rotate(${e.rotate}deg)`}:{},m=e.path;return d.e=r.style(a,o,d.e),m!==d.t&&r.setAttribute(l,"d",d.t=m),d},{e:void 0,t:void 0}),a})(),ne="M8 3H5a2 2 0 0 0-2 2v3M21 8V5a2 2 0 0 0-2-2h-3M3 16v3a2 2 0 0 0 2 2h3M16 21h3a2 2 0 0 0 2-2v-3",oe="M8 3v3a2 2 0 0 1-2 2H3M21 8h-3a2 2 0 0 1-2-2V3M3 16h3a2 2 0 0 1 2 2v3M16 21v-3a2 2 0 0 1 2-2h3",ie="m15 18-6-6 6-6",Y=e=>{const a=()=>(e.rowIsHorizontal?0:90)+(e.folded?180:0),l=()=>e.rotated?-90:0;let d;return g.onMount(()=>{const o=d?.parentElement;if(!d||!o)return;const m=()=>{d.style.transform=`translateX(${o.scrollLeft}px)`};m(),o.addEventListener("scroll",m,{passive:!0}),g.onCleanup(()=>o.removeEventListener("scroll",m))}),(()=>{var o=ae();o.$$dblclick=u=>u.stopPropagation();var m=d;return typeof m=="function"?r.use(m,o):d=o,r.insert(o,(()=>{var u=r.memo(()=>!!e.showMaximize);return()=>u()&&(()=>{var b=B();return b.$$click=()=>e.onToggleMaximize(),r.insert(b,r.createComponent(j,{get path(){return e.maximized?oe:ne},get rotate(){return l()}})),r.effect(i=>{var D=e.maximized?"Restore":"Maximize",x=e.maximized,w=e.maximized?"Restore (⌥ +)":"Maximize (⌥ +)";return D!==i.e&&r.setAttribute(b,"aria-label",i.e=D),x!==i.t&&r.setAttribute(b,"aria-pressed",i.t=x),w!==i.a&&r.setAttribute(b,"title",i.a=w),i},{e:void 0,t:void 0,a:void 0}),b})()})(),null),r.insert(o,(()=>{var u=r.memo(()=>!!e.showFold);return()=>u()&&(()=>{var b=B();return b.$$click=()=>e.onToggleFold(),r.insert(b,r.createComponent(j,{path:ie,get rotate(){return a()+l()}})),r.effect(i=>{var D=e.folded?"Unfold":"Fold",x=!e.folded,w=e.folded?"Unfold (⌥ -)":"Fold (⌥ -)";return D!==i.e&&r.setAttribute(b,"aria-label",i.e=D),x!==i.t&&r.setAttribute(b,"aria-expanded",i.t=x),w!==i.a&&r.setAttribute(b,"title",i.a=w),i},{e:void 0,t:void 0,a:void 0}),b})()})(),null),o})()};r.delegateEvents(["dblclick","click"]);const N=(e,a)=>({x:e.left-a.x,y:e.top-a.y,width:e.width,height:e.height}),G=e=>{const a=e.enableTabbar?Math.max(e.minTabHeight,e.tabHeadHeight):e.minTabHeight,l=p.createLayout({tabs:e.tabIds.map(t=>({id:t})),initialLayout:e.layoutTree??null,minPanelSize:{width:e.minTabWidth,height:a},splitterSize:e.bondWidth,foldedSize:e.enableTabbar?e.tabHeadHeight:a,onLayoutChange:(t,c)=>e.updateJSON?.(t,c)}),[d,o]=g.createSignal(l.getSnapshot(),{equals:!1}),[m,u]=g.createSignal(!1),b=l.subscribe(o),i=(t,c)=>{const n=e.getRoot();if(!n)return{x:t,y:c};const s=n.getBoundingClientRect();return{x:t-s.left-n.clientLeft,y:c-s.top-n.clientTop}},D=()=>{const t=new Map,c=e.getRoot();if(!c)return{tabBars:t};const n=c.getBoundingClientRect(),s={x:n.left+c.clientLeft,y:n.top+c.clientTop};return c.querySelectorAll("[data-tabbar]").forEach(h=>{const y=h.dataset.uid;y&&t.set(y,{rect:N(h.getBoundingClientRect(),s),isRotated:h.hasAttribute("data-rotated"),tabs:Array.from(h.querySelectorAll(':scope > [data-type="tab"]')).map(z=>({id:z.dataset.uid??"",rect:N(z.getBoundingClientRect(),s)}))})}),{tabBars:t}};let x;const w=p.createFrameScheduler(t=>l.updateDrag(t,x)),L=(t,c)=>{if(t.stopPropagation(),x=D(),!!l.startDrag(c)&&(u(!0),t.dataTransfer)){t.dataTransfer.effectAllowed="move";const n=document.createElement("div");n.style.cssText="width:1px;height:1px;position:absolute;top:-1000px",document.body.appendChild(n),t.dataTransfer.setDragImage(n,0,0),setTimeout(()=>n.remove(),0)}},R=t=>{d().drag&&(t.preventDefault(),t.dataTransfer&&(t.dataTransfer.dropEffect="move"),w.schedule(i(t.clientX,t.clientY)))},P=()=>{w.flush(),l.endDrag(),x=void 0,u(!1)},F=t=>t.preventDefault(),f=p.createFrameScheduler(t=>l.updateDrag(t)),C=(t,c)=>{if(t.preventDefault(),!l.startDrag({type:"splitter",splitterId:c}))return;const n=t.currentTarget;n.setPointerCapture?.(t.pointerId),u(!0);const s=y=>f.schedule(i(y.clientX,y.clientY)),h=()=>{f.flush(),l.endDrag(),u(!1),n.removeEventListener("pointermove",s),n.removeEventListener("pointerup",h),n.removeEventListener("pointercancel",h)};n.addEventListener("pointermove",s),n.addEventListener("pointerup",h),n.addEventListener("pointercancel",h)};let S=null;const W=t=>{const n=t.target.closest("[data-uid]")?.dataset.uid;if(!n)return;const s=d();s.tabsets.has(n)?S=n:s.tabs.has(n)&&(S=s.tabs.get(n).tabsetId)},k=t=>{e.enableDoubleClickMaximize&&l.toggleMaximize(t)},H=t=>{if(!e.keyboardShortcuts||!t.altKey||t.ctrlKey||t.metaKey)return;const c=S??d().maximizedTabsetId;c&&(t.code==="Equal"||t.code==="NumpadAdd"?(t.preventDefault(),l.toggleMaximize(c)):(t.code==="Minus"||t.code==="NumpadSubtract")&&(t.preventDefault(),l.toggleFold(c)))};return g.onMount(()=>{let t;const c=()=>l.setContainerRect(e.container()),n=()=>{if(e.disableResizeTimeout)return c();clearTimeout(t),t=setTimeout(c,e.windowResizeTimeout)};c(),window.addEventListener("resize",n),window.addEventListener("keydown",H),e.updateJSON?.(l.toJSON(),"mount"),g.onCleanup(()=>{clearTimeout(t),window.removeEventListener("resize",n),window.removeEventListener("keydown",H),w.cancel(),f.cancel(),b(),l.destroy()})}),{engine:l,snapshot:d,dragging:m,onDragStart:L,onDragOver:R,onDragEnd:P,onDrop:F,onSliderPointerDown:C,onRootPointerDown:W,onTabbarDoubleClick:k,selectTab:t=>{l.selectTab(t)},toggleMaximize:t=>{l.toggleMaximize(t)},toggleFold:t=>{l.toggleFold(t)}}};var le=r.template("<div>"),se=r.template("<button type=button class=DefaultTabClose>×");const O=40,ce=10,de=["left","right","top","bottom"],M=e=>e?{left:`${e.x}px`,top:`${e.y}px`,width:`${e.width}px`,height:`${e.height}px`}:{},q=(e,a)=>e.length===a.length&&e.every((l,d)=>l===a[d]),ue=e=>{let a;const l=e.tabs,d=e.tabHeadHeight??O,o=e.enableTabbar??!0,m=e.enableMaximize??!0,u=(e.enableCollapse??!0)&&o,b=e.rootId??"dynamix-layout-root",i=G({tabIds:l.map(([t])=>t),layoutTree:e.layoutTree,updateJSON:e.updateJSON,enableTabbar:o,tabHeadHeight:d,bondWidth:e.bondWidth??ce,minTabHeight:e.minTabHeight??O,minTabWidth:e.minTabWidth??O,windowResizeTimeout:e.windowResizeTimeout??2,disableResizeTimeout:e.disableResizeTimeout??!0,keyboardShortcuts:e.keyboardShortcuts??!0,enableDoubleClickMaximize:e.enableDoubleClickMaximize??!0,getRoot:()=>a,container:()=>{const t=e.pad??{t:0,b:0,l:0,r:0};return a?{x:t.l,y:t.t,width:Math.max(0,a.clientWidth-t.l-t.r),height:Math.max(0,a.clientHeight-t.t-t.b)}:{x:t.l,y:t.t,width:0,height:0}}}),D=e.WrapTabPanel??U,x=e.WrapTabHead??K,w=e.WrapTabLabel??V,L=e.WrapTabBody??J,R=e.SliderElement??X,P=e.HoverElement??I,F=e.TabsetToolbar??Y,{snapshot:f,dragging:C}=i,S=g.createMemo(()=>[...f().tabsets.keys()],[],{equals:q}),W=g.createMemo(()=>[...f().splitters.keys()],[],{equals:q}),k=t=>e.tabs.find(([c])=>c===t),H=t=>k(t)?.[2]?.title??e.tabNames?.get(t)??t;return g.createEffect(g.on(()=>e.tabs.map(([t])=>t).join("\0"),()=>i.engine.setTabs(e.tabs.map(([t])=>({id:t}))),{defer:!0})),g.onMount(()=>e.onReady?.(i.engine)),(()=>{var t=le(),c=a;return typeof c=="function"?r.use(c,t):a=t,r.setAttribute(t,"id",b),r.spread(t,r.mergeProps(e,{"data-testid":b,get class(){return C()?"is-dragging":""},onPointerDown:n=>i.onRootPointerDown(n),onDragOver:n=>i.onDragOver(n),onDrop:n=>i.onDrop(n),get style(){return{position:"relative",width:"100%",height:"100%",overflow:"hidden",...e.style}}}),!1,!0),r.insert(t,r.createComponent(g.For,{get each(){return S()},children:n=>{const s=()=>f().tabsets.get(n),h=()=>f().rects.tabsets.get(n),y=()=>{const v=s(),T=h();return v&&T?p.getTabBarPlacement(T,v,d):void 0},z=()=>m&&!!s()?.canMaximize,$=()=>u&&!!s()?.canFold&&!s()?.isMaximized,A=()=>z()||$();return[r.createComponent(D,{"data-uid":n,"data-type":"tabset",get class(){return"hide-scrollbar DefaultWrapTabPanel "+(e.tabPanelElementClass||"")},get style(){return{position:"absolute",...e.tabPanelElementStyles,...M(h()),"background-color":"transparent","z-index":C()?95:0,display:C()?"block":"none"}}}),r.createComponent(g.Show,{when:o,get children(){return r.createComponent(x,{draggable:!0,"data-uid":n,"data-type":"tabset","data-tabbar":"",get"data-folded"(){return s()?.isFolded?"":void 0},get"data-maximized"(){return s()?.isMaximized?"":void 0},get"data-dx-hidden"(){return s()?.isHidden?"":void 0},get"data-rotated"(){return y()?.isRotated?"":void 0},onDblClick:()=>i.onTabbarDoubleClick(n),onDragStart:v=>i.onDragStart(v,{type:"tabset",tabsetId:n}),onDragEnd:()=>i.onDragEnd(),get class(){return"hide-scrollbar "+(e.tabHeadElementClass||"")},get style(){return{...e.tabHeadElementStyles,position:"absolute","z-index":99,...M(y()?.rect),"transform-origin":"0 0",...y()?.isRotated?{transform:"rotate(90deg)"}:{},...A()?{"padding-right":"64px"}:{},cursor:"pointer"}},get children(){return[r.createComponent(g.For,{get each(){return s()?.tabIds??[]},children:v=>r.createComponent(w,{"data-uid":v,"data-type":"tab",draggable:!0,onDragStart:T=>i.onDragStart(T,{type:"tab",tabId:v}),onDragEnd:()=>i.onDragEnd(),get active(){return f().tabs.get(v)?.isActive??!1},get class(){return"hide-scrollbar "+(e.tabLabelElementClass||"")},get style(){return{cursor:"pointer",...e.tabLabelElementStyles}},onClick:()=>i.selectTab(v),get children(){return[r.memo(()=>H(v)),r.createComponent(g.Show,{get when(){return k(v)?.[2]?.closable},get children(){var T=se();return T.$$click=_=>{_.stopPropagation(),e.onTabClose?.(v)},T.$$mousedown=_=>_.stopPropagation(),r.setAttribute(T,"aria-label",`Close ${v}`),r.setAttribute(T,"draggable",!1),T}})]}})}),r.createComponent(g.Show,{get when(){return A()},get children(){return r.createComponent(F,{get maximized(){return!!s()?.isMaximized},get folded(){return!!s()?.isFolded},get rotated(){return!!y()?.isRotated},get rowIsHorizontal(){return s()?.parentDirection==="horizontal"},get showMaximize(){return z()},get showFold(){return $()},onToggleMaximize:()=>i.toggleMaximize(n),onToggleFold:()=>i.toggleFold(n)})}})]}})}})]}}),null),r.insert(t,r.createComponent(g.For,{get each(){return e.tabs},children:([n,s])=>{const h=()=>f().tabs.get(n),y=()=>{const $=h()&&f().rects.tabsets.get(h().tabsetId);return $&&p.getTabContentRect($,o?d:0)},z=()=>!!h()?.isVisible&&(y()?.height??0)>0;return r.createComponent(L,{"data-uid":n,draggable:!1,get"data-dx-hidden"(){return z()?void 0:""},get class(){return"hide-scrollbar "+(e.tabBodyElementClass||"")},get style(){return{position:"absolute","z-index":90,"overscroll-behavior":"contain",...e.tabBodyElementStyles,...M(y())}},children:s})}}),null),r.insert(t,r.createComponent(g.For,{get each(){return W()},children:n=>{const s=()=>f().splitters.get(n);return r.createComponent(R,{"data-uid":n,get"data-dx-hidden"(){return s()?.isHidden?"":void 0},get direction(){return s()?.direction==="vertical"},onPointerDown:h=>i.onSliderPointerDown(h,n),get class(){return"hide-scrollbar "+(e.sliderElementClass||"")},get style(){return{...M(f().rects.splitters.get(n)),cursor:s()?.direction==="vertical"?"ns-resize":"ew-resize",...s()?.isLocked?{"pointer-events":"none"}:{},...e.sliderElementStyles}}})}}),null),r.insert(t,r.createComponent(P,{get class(){return"hide-scrollbar "+(e.hoverElementClass||"")},get style(){return{...e.hoverElementStyles,...M(f().drag?.indicator??void 0),display:f().drag?.indicator?"block":"none","z-index":100}}}),null),r.insert(t,r.createComponent(g.For,{each:de,children:n=>r.createComponent(Z,{"data-uid":b,"data-area":n,get class(){return"hide-scrollbar "+(e.RootSplitterHoverElClass||"")},get style(){return{...e.RootSplitterHoverElStyles,...f().drag&&f().drag.source.type!=="splitter"?{display:"block","z-index":99}:{}}},area:n,size:{h:"25%",w:"8px"}})}),null),t})()};r.delegateEvents(["mousedown","click"]);Object.defineProperty(exports,"isLayoutV1",{enumerable:!0,get:()=>p.isLayoutV1});Object.defineProperty(exports,"migrateLayoutFromV1",{enumerable:!0,get:()=>p.migrateLayoutFromV1});exports.DefaultHoverElement=I;exports.DefaultSliderElement=X;exports.DefaultTabsetToolbar=Y;exports.DefaultWrapTabBody=J;exports.DefaultWrapTabHead=K;exports.DefaultWrapTabLabel=V;exports.DefaultWrapTabPanel=U;exports.DynamixLayout=ue;exports.RootSplitterHoverEl=Z;exports.useDynamixLayout=G;
@@ -0,0 +1,208 @@
1
+ import { Accessor } from 'solid-js';
2
+ import { DragSource } from '@dynamix-layout/core';
3
+ import { isLayoutV1 } from '@dynamix-layout/core';
4
+ import { JSX } from 'solid-js';
5
+ import { Layout } from '@dynamix-layout/core';
6
+ import { LayoutChangeReason } from '@dynamix-layout/core';
7
+ import { LayoutJSON } from '@dynamix-layout/core';
8
+ import { LayoutSnapshot } from '@dynamix-layout/core';
9
+ import { LayoutTreeV1 } from '@dynamix-layout/core';
10
+ import { migrateLayoutFromV1 } from '@dynamix-layout/core';
11
+ import { ParentComponent } from 'solid-js';
12
+ import { Rect } from '@dynamix-layout/core';
13
+
14
+ export declare const DefaultHoverElement: (props: DivProps) => JSX.Element;
15
+
16
+ export declare const DefaultSliderElement: (props: {
17
+ direction?: boolean;
18
+ children?: JSX.Element;
19
+ } & DivProps) => JSX.Element;
20
+
21
+ export declare const DefaultTabsetToolbar: (props: TabsetToolbarProps) => JSX.Element;
22
+
23
+ export declare const DefaultWrapTabBody: (props: DivProps) => JSX.Element;
24
+
25
+ export declare const DefaultWrapTabHead: (props: DivProps) => JSX.Element;
26
+
27
+ export declare const DefaultWrapTabLabel: (props: DivProps) => JSX.Element;
28
+
29
+ export declare const DefaultWrapTabPanel: (props: DivProps) => JSX.Element;
30
+
31
+ export declare type DivFC = (props: {
32
+ children?: JSX.Element;
33
+ } & JSX.HTMLAttributes<HTMLDivElement>) => JSX.Element;
34
+
35
+ declare type DivProps = {
36
+ children?: JSX.Element;
37
+ active?: boolean;
38
+ } & JSX.HTMLAttributes<HTMLDivElement>;
39
+
40
+ export declare const DynamixLayout: ParentComponent<LayoutProps>;
41
+
42
+ /** What `useDynamixLayout` returns to the Solid `<DynamixLayout>`. */
43
+ export declare interface DynamixLayoutState {
44
+ engine: Layout;
45
+ /** The current snapshot; Solid updates only what reads the parts that changed. */
46
+ snapshot: Accessor<LayoutSnapshot>;
47
+ /** A tab or tabset is being dragged (HTML5) or a splitter is moving. */
48
+ dragging: Accessor<boolean>;
49
+ onDragStart: (event: DragEvent, source: DragSource) => void;
50
+ onDragOver: (event: DragEvent) => void;
51
+ onDragEnd: () => void;
52
+ onDrop: (event: DragEvent) => void;
53
+ onSliderPointerDown: (event: PointerEvent, splitterId: string) => void;
54
+ onRootPointerDown: (event: PointerEvent) => void;
55
+ onTabbarDoubleClick: (tabsetId: string) => void;
56
+ selectTab: (tabId: string) => void;
57
+ toggleMaximize: (tabsetId: string) => void;
58
+ toggleFold: (tabsetId: string) => void;
59
+ }
60
+
61
+ export { isLayoutV1 }
62
+
63
+ export { LayoutJSON }
64
+
65
+ export declare interface LayoutProps {
66
+ /**
67
+ * The open tabs. Reactive: add an entry to open a tab, remove it to close
68
+ * one; existing tabs keep their content mounted.
69
+ */
70
+ tabs: TabItem[];
71
+ /** Called when a closable tab's close button is clicked; remove it from `tabs` to close it. */
72
+ onTabClose?: (tabId: string) => void;
73
+ /**
74
+ * Receives the layout engine once mounted, for actions from code:
75
+ * `maximize`, `restore`, `fold`, `unfold`, `selectTab`, `moveTab`, `reset`, `toJSON`, …
76
+ */
77
+ onReady?: (layout: Layout) => void;
78
+ enableTabbar?: boolean;
79
+ WrapTabPanel?: DivFC;
80
+ WrapTabLabel?: (props: {
81
+ children?: JSX.Element;
82
+ active?: boolean;
83
+ } & JSX.HTMLAttributes<HTMLDivElement>) => JSX.Element;
84
+ WrapTabHead?: DivFC;
85
+ WrapTabBody?: DivFC;
86
+ HoverElement?: DivFC;
87
+ SliderElement?: (props: {
88
+ children?: JSX.Element;
89
+ direction?: boolean;
90
+ } & JSX.HTMLAttributes<HTMLDivElement>) => JSX.Element;
91
+ tabHeadHeight?: number;
92
+ /** A saved layout: v2 JSON, or a v1 tree (migrated automatically). */
93
+ layoutTree?: LayoutJSON | LayoutTreeV1;
94
+ pad?: {
95
+ t: number;
96
+ b: number;
97
+ l: number;
98
+ r: number;
99
+ };
100
+ class?: string;
101
+ style?: JSX.CSSProperties;
102
+ bondWidth?: number;
103
+ /**
104
+ * Called with the v2 layout after every change, and once on mount.
105
+ * `reason` says why: the core's `LayoutChangeReason`, or `'mount'`.
106
+ */
107
+ updateJSON?: (layout: LayoutJSON, reason: LayoutUpdateReason) => void;
108
+ minTabHeight?: number;
109
+ minTabWidth?: number;
110
+ sliderUpdateTimeout?: number;
111
+ windowResizeTimeout?: number;
112
+ disableSliderTimeout?: boolean;
113
+ disableResizeTimeout?: boolean;
114
+ hoverElementStyles?: JSX.CSSProperties;
115
+ sliderElementStyles?: JSX.CSSProperties;
116
+ tabPanelElementStyles?: JSX.CSSProperties;
117
+ tabBodyElementStyles?: JSX.CSSProperties;
118
+ tabHeadElementStyles?: JSX.CSSProperties;
119
+ tabLabelElementStyles?: JSX.CSSProperties;
120
+ RootSplitterHoverElStyles?: JSX.CSSProperties;
121
+ hoverElementClass?: string;
122
+ sliderElementClass?: string;
123
+ tabPanelElementClass?: string;
124
+ tabBodyElementClass?: string;
125
+ tabHeadElementClass?: string;
126
+ tabLabelElementClass?: string;
127
+ RootSplitterHoverElClass?: string;
128
+ rootId?: string;
129
+ tabNames?: Map<string, string | JSX.Element>;
130
+ /** Show the maximize button on tab bars (default true). */
131
+ enableMaximize?: boolean;
132
+ /** Show the fold button on tab bars (default true; needs the tab bar). */
133
+ enableCollapse?: boolean;
134
+ /** Double-click a tab bar to maximize or restore it (default true). */
135
+ enableDoubleClickMaximize?: boolean;
136
+ /** Alt/Option + "+" maximizes, Alt/Option + "-" folds the active tabset (default true). */
137
+ keyboardShortcuts?: boolean;
138
+ TabsetToolbar?: (props: TabsetToolbarProps) => JSX.Element;
139
+ }
140
+
141
+ export { LayoutTreeV1 }
142
+
143
+ /** Why `updateJSON` was called. */
144
+ export declare type LayoutUpdateReason = LayoutChangeReason | 'mount';
145
+
146
+ export { migrateLayoutFromV1 }
147
+
148
+ export declare const RootSplitterHoverEl: (props: {
149
+ area: "left" | "right" | "top" | "bottom";
150
+ size?: {
151
+ w: string;
152
+ h: string;
153
+ };
154
+ gap?: string;
155
+ } & DivProps) => JSX.Element;
156
+
157
+ /** One tab: `[id, content]` or `[id, content, options]`. */
158
+ export declare type TabItem = [id: string, content: JSX.Element, options?: TabOptions];
159
+
160
+ /** Per-tab options: the third element of a `tabs` entry. */
161
+ export declare interface TabOptions {
162
+ /** Tab label. @default `tabNames.get(id)`, else the id */
163
+ title?: JSX.Element;
164
+ /** Show a close button; clicking it calls `onTabClose`. @default false */
165
+ closable?: boolean;
166
+ }
167
+
168
+ export declare interface TabsetToolbarProps {
169
+ maximized: boolean;
170
+ folded: boolean;
171
+ /** The tab bar is drawn as a rotated vertical strip (folded, side-by-side row). */
172
+ rotated: boolean;
173
+ /** The tabset's row lays its children out side by side. */
174
+ rowIsHorizontal: boolean;
175
+ showMaximize: boolean;
176
+ showFold: boolean;
177
+ onToggleMaximize: () => void;
178
+ onToggleFold: () => void;
179
+ }
180
+
181
+ /**
182
+ * The Solid adapter's engine binding: one `createLayout` instance per
183
+ * component, a snapshot signal, HTML5 drag-and-drop for tabs (drop targets
184
+ * come from the core), pointer drags for splitters, and window-resize
185
+ * tracking.
186
+ */
187
+ export declare const useDynamixLayout: (options: useDynamixLayoutOptions) => DynamixLayoutState;
188
+
189
+ /** Options of the Solid `useDynamixLayout` (resolved by `<DynamixLayout>`). */
190
+ export declare interface useDynamixLayoutOptions {
191
+ tabIds: string[];
192
+ layoutTree?: LayoutJSON | LayoutTreeV1;
193
+ updateJSON?: (layout: LayoutJSON, reason: LayoutUpdateReason) => void;
194
+ enableTabbar: boolean;
195
+ /** The area to fill, relative to the root element. */
196
+ container: () => Rect;
197
+ getRoot: () => HTMLElement | undefined;
198
+ windowResizeTimeout: number;
199
+ disableResizeTimeout: boolean;
200
+ bondWidth: number;
201
+ minTabHeight: number;
202
+ minTabWidth: number;
203
+ tabHeadHeight: number;
204
+ keyboardShortcuts?: boolean;
205
+ enableDoubleClickMaximize?: boolean;
206
+ }
207
+
208
+ export { }
@@ -0,0 +1,208 @@
1
+ import { Accessor } from 'solid-js';
2
+ import { DragSource } from '@dynamix-layout/core';
3
+ import { isLayoutV1 } from '@dynamix-layout/core';
4
+ import { JSX } from 'solid-js';
5
+ import { Layout } from '@dynamix-layout/core';
6
+ import { LayoutChangeReason } from '@dynamix-layout/core';
7
+ import { LayoutJSON } from '@dynamix-layout/core';
8
+ import { LayoutSnapshot } from '@dynamix-layout/core';
9
+ import { LayoutTreeV1 } from '@dynamix-layout/core';
10
+ import { migrateLayoutFromV1 } from '@dynamix-layout/core';
11
+ import { ParentComponent } from 'solid-js';
12
+ import { Rect } from '@dynamix-layout/core';
13
+
14
+ export declare const DefaultHoverElement: (props: DivProps) => JSX.Element;
15
+
16
+ export declare const DefaultSliderElement: (props: {
17
+ direction?: boolean;
18
+ children?: JSX.Element;
19
+ } & DivProps) => JSX.Element;
20
+
21
+ export declare const DefaultTabsetToolbar: (props: TabsetToolbarProps) => JSX.Element;
22
+
23
+ export declare const DefaultWrapTabBody: (props: DivProps) => JSX.Element;
24
+
25
+ export declare const DefaultWrapTabHead: (props: DivProps) => JSX.Element;
26
+
27
+ export declare const DefaultWrapTabLabel: (props: DivProps) => JSX.Element;
28
+
29
+ export declare const DefaultWrapTabPanel: (props: DivProps) => JSX.Element;
30
+
31
+ export declare type DivFC = (props: {
32
+ children?: JSX.Element;
33
+ } & JSX.HTMLAttributes<HTMLDivElement>) => JSX.Element;
34
+
35
+ declare type DivProps = {
36
+ children?: JSX.Element;
37
+ active?: boolean;
38
+ } & JSX.HTMLAttributes<HTMLDivElement>;
39
+
40
+ export declare const DynamixLayout: ParentComponent<LayoutProps>;
41
+
42
+ /** What `useDynamixLayout` returns to the Solid `<DynamixLayout>`. */
43
+ export declare interface DynamixLayoutState {
44
+ engine: Layout;
45
+ /** The current snapshot; Solid updates only what reads the parts that changed. */
46
+ snapshot: Accessor<LayoutSnapshot>;
47
+ /** A tab or tabset is being dragged (HTML5) or a splitter is moving. */
48
+ dragging: Accessor<boolean>;
49
+ onDragStart: (event: DragEvent, source: DragSource) => void;
50
+ onDragOver: (event: DragEvent) => void;
51
+ onDragEnd: () => void;
52
+ onDrop: (event: DragEvent) => void;
53
+ onSliderPointerDown: (event: PointerEvent, splitterId: string) => void;
54
+ onRootPointerDown: (event: PointerEvent) => void;
55
+ onTabbarDoubleClick: (tabsetId: string) => void;
56
+ selectTab: (tabId: string) => void;
57
+ toggleMaximize: (tabsetId: string) => void;
58
+ toggleFold: (tabsetId: string) => void;
59
+ }
60
+
61
+ export { isLayoutV1 }
62
+
63
+ export { LayoutJSON }
64
+
65
+ export declare interface LayoutProps {
66
+ /**
67
+ * The open tabs. Reactive: add an entry to open a tab, remove it to close
68
+ * one; existing tabs keep their content mounted.
69
+ */
70
+ tabs: TabItem[];
71
+ /** Called when a closable tab's close button is clicked; remove it from `tabs` to close it. */
72
+ onTabClose?: (tabId: string) => void;
73
+ /**
74
+ * Receives the layout engine once mounted, for actions from code:
75
+ * `maximize`, `restore`, `fold`, `unfold`, `selectTab`, `moveTab`, `reset`, `toJSON`, …
76
+ */
77
+ onReady?: (layout: Layout) => void;
78
+ enableTabbar?: boolean;
79
+ WrapTabPanel?: DivFC;
80
+ WrapTabLabel?: (props: {
81
+ children?: JSX.Element;
82
+ active?: boolean;
83
+ } & JSX.HTMLAttributes<HTMLDivElement>) => JSX.Element;
84
+ WrapTabHead?: DivFC;
85
+ WrapTabBody?: DivFC;
86
+ HoverElement?: DivFC;
87
+ SliderElement?: (props: {
88
+ children?: JSX.Element;
89
+ direction?: boolean;
90
+ } & JSX.HTMLAttributes<HTMLDivElement>) => JSX.Element;
91
+ tabHeadHeight?: number;
92
+ /** A saved layout: v2 JSON, or a v1 tree (migrated automatically). */
93
+ layoutTree?: LayoutJSON | LayoutTreeV1;
94
+ pad?: {
95
+ t: number;
96
+ b: number;
97
+ l: number;
98
+ r: number;
99
+ };
100
+ class?: string;
101
+ style?: JSX.CSSProperties;
102
+ bondWidth?: number;
103
+ /**
104
+ * Called with the v2 layout after every change, and once on mount.
105
+ * `reason` says why: the core's `LayoutChangeReason`, or `'mount'`.
106
+ */
107
+ updateJSON?: (layout: LayoutJSON, reason: LayoutUpdateReason) => void;
108
+ minTabHeight?: number;
109
+ minTabWidth?: number;
110
+ sliderUpdateTimeout?: number;
111
+ windowResizeTimeout?: number;
112
+ disableSliderTimeout?: boolean;
113
+ disableResizeTimeout?: boolean;
114
+ hoverElementStyles?: JSX.CSSProperties;
115
+ sliderElementStyles?: JSX.CSSProperties;
116
+ tabPanelElementStyles?: JSX.CSSProperties;
117
+ tabBodyElementStyles?: JSX.CSSProperties;
118
+ tabHeadElementStyles?: JSX.CSSProperties;
119
+ tabLabelElementStyles?: JSX.CSSProperties;
120
+ RootSplitterHoverElStyles?: JSX.CSSProperties;
121
+ hoverElementClass?: string;
122
+ sliderElementClass?: string;
123
+ tabPanelElementClass?: string;
124
+ tabBodyElementClass?: string;
125
+ tabHeadElementClass?: string;
126
+ tabLabelElementClass?: string;
127
+ RootSplitterHoverElClass?: string;
128
+ rootId?: string;
129
+ tabNames?: Map<string, string | JSX.Element>;
130
+ /** Show the maximize button on tab bars (default true). */
131
+ enableMaximize?: boolean;
132
+ /** Show the fold button on tab bars (default true; needs the tab bar). */
133
+ enableCollapse?: boolean;
134
+ /** Double-click a tab bar to maximize or restore it (default true). */
135
+ enableDoubleClickMaximize?: boolean;
136
+ /** Alt/Option + "+" maximizes, Alt/Option + "-" folds the active tabset (default true). */
137
+ keyboardShortcuts?: boolean;
138
+ TabsetToolbar?: (props: TabsetToolbarProps) => JSX.Element;
139
+ }
140
+
141
+ export { LayoutTreeV1 }
142
+
143
+ /** Why `updateJSON` was called. */
144
+ export declare type LayoutUpdateReason = LayoutChangeReason | 'mount';
145
+
146
+ export { migrateLayoutFromV1 }
147
+
148
+ export declare const RootSplitterHoverEl: (props: {
149
+ area: "left" | "right" | "top" | "bottom";
150
+ size?: {
151
+ w: string;
152
+ h: string;
153
+ };
154
+ gap?: string;
155
+ } & DivProps) => JSX.Element;
156
+
157
+ /** One tab: `[id, content]` or `[id, content, options]`. */
158
+ export declare type TabItem = [id: string, content: JSX.Element, options?: TabOptions];
159
+
160
+ /** Per-tab options: the third element of a `tabs` entry. */
161
+ export declare interface TabOptions {
162
+ /** Tab label. @default `tabNames.get(id)`, else the id */
163
+ title?: JSX.Element;
164
+ /** Show a close button; clicking it calls `onTabClose`. @default false */
165
+ closable?: boolean;
166
+ }
167
+
168
+ export declare interface TabsetToolbarProps {
169
+ maximized: boolean;
170
+ folded: boolean;
171
+ /** The tab bar is drawn as a rotated vertical strip (folded, side-by-side row). */
172
+ rotated: boolean;
173
+ /** The tabset's row lays its children out side by side. */
174
+ rowIsHorizontal: boolean;
175
+ showMaximize: boolean;
176
+ showFold: boolean;
177
+ onToggleMaximize: () => void;
178
+ onToggleFold: () => void;
179
+ }
180
+
181
+ /**
182
+ * The Solid adapter's engine binding: one `createLayout` instance per
183
+ * component, a snapshot signal, HTML5 drag-and-drop for tabs (drop targets
184
+ * come from the core), pointer drags for splitters, and window-resize
185
+ * tracking.
186
+ */
187
+ export declare const useDynamixLayout: (options: useDynamixLayoutOptions) => DynamixLayoutState;
188
+
189
+ /** Options of the Solid `useDynamixLayout` (resolved by `<DynamixLayout>`). */
190
+ export declare interface useDynamixLayoutOptions {
191
+ tabIds: string[];
192
+ layoutTree?: LayoutJSON | LayoutTreeV1;
193
+ updateJSON?: (layout: LayoutJSON, reason: LayoutUpdateReason) => void;
194
+ enableTabbar: boolean;
195
+ /** The area to fill, relative to the root element. */
196
+ container: () => Rect;
197
+ getRoot: () => HTMLElement | undefined;
198
+ windowResizeTimeout: number;
199
+ disableResizeTimeout: boolean;
200
+ bondWidth: number;
201
+ minTabHeight: number;
202
+ minTabWidth: number;
203
+ tabHeadHeight: number;
204
+ keyboardShortcuts?: boolean;
205
+ enableDoubleClickMaximize?: boolean;
206
+ }
207
+
208
+ export { }