@dashfoo/react 0.3.0 → 0.4.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/README.md +52 -24
- package/dist/index.d.ts +20 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/package.json +5 -5
package/README.md
CHANGED
|
@@ -15,7 +15,7 @@ paint.
|
|
|
15
15
|
It builds on three engines:
|
|
16
16
|
|
|
17
17
|
- **[react-resizable-panels](https://github.com/bvaughn/react-resizable-panels)** for splitter resize (the resize adapter is the only file that imports it).
|
|
18
|
-
- **[@dnd-kit/dom](https://github.com/clauderic/dnd-kit) 0.
|
|
18
|
+
- **[@dnd-kit/dom](https://github.com/clauderic/dnd-kit) 0.5** — the framework-agnostic core (no React bindings) — for drag (the drag adapter is the only file that touches it; pointer-only).
|
|
19
19
|
- **[@dashfoo/core](https://www.npmjs.com/package/@dashfoo/core)** for the document: a zod schema, a pure reducer, and the XState machines that drive state and the drag lifecycle.
|
|
20
20
|
|
|
21
21
|
## Install
|
|
@@ -59,27 +59,29 @@ a sized parent and add your CSS (see the [attribute reference](#data-dashfoo-att
|
|
|
59
59
|
|
|
60
60
|
## `DashfooLayout` props
|
|
61
61
|
|
|
62
|
-
| Prop | Type
|
|
63
|
-
| ------------------------- |
|
|
64
|
-
| `model` | `Dashfoo`
|
|
65
|
-
| `defaultModel` | `Dashfoo`
|
|
66
|
-
| `onModelChange` | `(model: Dashfoo, action?: Action) => void`
|
|
67
|
-
| `components` | `Record<string, ComponentType<{ node: TabNode }>>`
|
|
68
|
-
| `factory` | `(tab: TabNode) => ReactNode`
|
|
69
|
-
| `persist` | `string \| { key; storage?; debounceMs? }`
|
|
70
|
-
| `onAction` | `(action: Action) => Action \| null`
|
|
71
|
-
| `onActiveTabsetChange` | `(id: string \| undefined) => void`
|
|
72
|
-
| `onMaximizedTabsetChange` | `(id: string \| undefined) => void`
|
|
73
|
-
| `renderTabLabel` | `(tab: TabNode) => ReactNode`
|
|
74
|
-
| `renderTabsetToolbar` | `(tabset: TabsetNode) => ReactNode`
|
|
75
|
-
| `editable` | `boolean`
|
|
76
|
-
| `closableTabs` | `boolean`
|
|
77
|
-
| `renamableTabs` | `boolean`
|
|
78
|
-
| `maximizable` | `boolean`
|
|
79
|
-
| `draggableTabs` | `boolean`
|
|
80
|
-
| `draggableTabsets` | `boolean`
|
|
81
|
-
| `resizableSplits` | `boolean`
|
|
82
|
-
| `keepMounted` | `boolean`
|
|
62
|
+
| Prop | Type | Default | Description |
|
|
63
|
+
| ------------------------- | ----------------------------------------------------------------------- | ------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
64
|
+
| `model` | `Dashfoo` | — | Controlled document. When set, the prop is the source of truth. |
|
|
65
|
+
| `defaultModel` | `Dashfoo` | — | Uncontrolled initial document. The component owns it from there. |
|
|
66
|
+
| `onModelChange` | `(model: Dashfoo, action?: Action) => void` | — | Called after every change with the next model and the action that caused it. |
|
|
67
|
+
| `components` | `Record<string, ComponentType<{ node: TabNode }>>` | — | Registry mapping `tab.component` keys to components. |
|
|
68
|
+
| `factory` | `(tab: TabNode) => ReactNode` | — | Render override. When provided, it resolves every tab and `components` is ignored. |
|
|
69
|
+
| `persist` | `string \| { key; storage?; debounceMs? }` | — | Auto-save the model (uncontrolled mode only). A bare string is a localStorage key. |
|
|
70
|
+
| `onAction` | `(action: Action) => Action \| null` | — | Intercept each action before it commits — return it, a replacement, or `null` to veto. |
|
|
71
|
+
| `onActiveTabsetChange` | `(id: string \| undefined) => void` | — | Fires when the active tabset changes. |
|
|
72
|
+
| `onMaximizedTabsetChange` | `(id: string \| undefined) => void` | — | Fires when a tabset is maximized or restored. |
|
|
73
|
+
| `renderTabLabel` | `(tab: TabNode) => ReactNode` | — | Override the tab label (the accessible name stays `tab.name`). |
|
|
74
|
+
| `renderTabsetToolbar` | `(tabset: TabsetNode) => ReactNode` | — | Inject custom controls into a tabset's toolbar. |
|
|
75
|
+
| `editable` | `boolean` | `true` | `false` renders a static layout: no drag, close, rename, or splitter resize. Tab selection, maximize, and the ref API keep working. |
|
|
76
|
+
| `closableTabs` | `boolean` | `true` | Show the per-tab close control. |
|
|
77
|
+
| `renamableTabs` | `boolean` | `true` | Allow double-click inline rename. |
|
|
78
|
+
| `maximizable` | `boolean` | `true` | Show the tabset maximize/restore control. |
|
|
79
|
+
| `draggableTabs` | `boolean` | `true` | Allow individual tabs to be dragged between tabsets. |
|
|
80
|
+
| `draggableTabsets` | `boolean` | `true` | Show the grip that drags a whole tabset. |
|
|
81
|
+
| `resizableSplits` | `boolean` | `true` | Allow dragging the splitters; `false` disables them in place (gutters keep their size). |
|
|
82
|
+
| `keepMounted` | `boolean` | `false` | Keep inactive tab panels mounted (hidden) so their state survives a tab switch. |
|
|
83
|
+
| `responsive` | `{ maxWidth: number; orientation? }` | — | At/below `maxWidth` (the layout's own container width) render a stacked column and lock drag + resize. View-only projection — no remount, state preserved. See below. |
|
|
84
|
+
| `snap` | `{ step?: number; divisions?: number \| "panels"; threshold?: number }` | — | Magnetic splitter snapping onto a grid — the union of `step` (multiples of a fixed percent) and `divisions` (even splits: `100/d`, or `"panels"` to divide by the row's panel count, so a 3-panel row snaps to thirds). Within `threshold` percent (default `4`) it snaps and commits on release as one undo step. Off when omitted; replaces `global.snap`; a row overrides via its own `snap` (`{}` disables). Locked off in compact mode. |
|
|
83
85
|
|
|
84
86
|
You must pass either `model` or `defaultModel`. Passing neither throws.
|
|
85
87
|
|
|
@@ -250,6 +252,31 @@ keyboard access.
|
|
|
250
252
|
| `label` | `string` | `""` | The drag preview chip text. |
|
|
251
253
|
| `disabled` | `boolean` | `false` | Unregisters the source while true. |
|
|
252
254
|
|
|
255
|
+
## Responsive layouts
|
|
256
|
+
|
|
257
|
+
Panels are weight-based, so the tree already scales with its container. To
|
|
258
|
+
_restructure_ on small screens, give `DashfooLayout` a `responsive` prop:
|
|
259
|
+
|
|
260
|
+
```tsx
|
|
261
|
+
<DashfooLayout defaultModel={model} factory={renderPanel} responsive={{ maxWidth: 720 }} />
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
At or below `maxWidth` — measured on the layout's own container, not the viewport
|
|
265
|
+
— the layout renders as a single stacked column and **locks every structural
|
|
266
|
+
interaction** (tab/tabset drag, split resize), leaving tap-to-switch and
|
|
267
|
+
maximize. This mirrors VS Code: docking is a desktop interaction, so narrow
|
|
268
|
+
screens get a read-only, navigable view instead of unusable hit targets.
|
|
269
|
+
|
|
270
|
+
The stacked view is a **derived projection** — the model in the store is never
|
|
271
|
+
mutated, so the layout is never remounted and widening past `maxWidth` restores
|
|
272
|
+
the desktop arrangement exactly. Undo history, persistence, selection, and
|
|
273
|
+
mounted panels all survive the breakpoint cross. The theme grows tab hit targets
|
|
274
|
+
to 44px under `@media (pointer: coarse)` so tap-to-switch stays usable.
|
|
275
|
+
|
|
276
|
+
Hand-built layouts (the `Layout.*` primitives) get the same behavior with
|
|
277
|
+
`useContainerWidth` + `stackModel`; for _distinct_ per-breakpoint models, use
|
|
278
|
+
`useResponsiveModel`. Both feed reactive props with no `key`/remount.
|
|
279
|
+
|
|
253
280
|
## Persistence
|
|
254
281
|
|
|
255
282
|
The `persist` prop saves an uncontrolled layout and restores it on load. It loads
|
|
@@ -285,7 +312,7 @@ in `onModelChange`.
|
|
|
285
312
|
|
|
286
313
|
The lower-level `usePersistence` load/save primitive (that `persist` is built on)
|
|
287
314
|
is also exported, for hosts that drive the store directly. See the
|
|
288
|
-
[persistence guide](https://docs.dashfoo.
|
|
315
|
+
[persistence guide](https://docs.dashfoo.com/persistence) for the storage seam,
|
|
289
316
|
validation pipeline, and SSR notes.
|
|
290
317
|
|
|
291
318
|
### Options
|
|
@@ -557,7 +584,8 @@ type Persistence;
|
|
|
557
584
|
type PersistConfig;
|
|
558
585
|
|
|
559
586
|
// Responsive
|
|
560
|
-
|
|
587
|
+
useContainerWidth; // [ref, width] via ResizeObserver — the hand-built building block
|
|
588
|
+
useResponsiveModel; // per-breakpoint model + lock flags (no remount)
|
|
561
589
|
matchBreakpoint; // does a breakpoint apply at a given width
|
|
562
590
|
activeBreakpoint; // first matching breakpoint, else the last (the catch-all)
|
|
563
591
|
type Breakpoint;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { Action, Dashfoo, DockLocation, DragSubject, DropIntent, RowNode, TabNode, TabsetNode } from "@dashfoo/core";
|
|
2
|
-
import { ComponentProps, ComponentType, ReactNode } from "react";
|
|
1
|
+
import { Action, Dashfoo, DockLocation, DragSubject, DropIntent, Orientation, RowNode, SnapConfig, TabNode, TabsetNode } from "@dashfoo/core";
|
|
2
|
+
import { ComponentProps, ComponentType, ReactNode, Ref } from "react";
|
|
3
3
|
import { DragDropManager } from "@dnd-kit/dom";
|
|
4
4
|
//#region src/hooks/persistence.d.ts
|
|
5
5
|
type StorageAdapter = {
|
|
@@ -68,6 +68,11 @@ type DashfooLayoutProps = {
|
|
|
68
68
|
renderTabLabel?: (tab: TabNode) => ReactNode;
|
|
69
69
|
renderTabsetToolbar?: (tabset: TabsetNode) => ReactNode;
|
|
70
70
|
resizableSplits?: boolean;
|
|
71
|
+
responsive?: {
|
|
72
|
+
maxWidth: number;
|
|
73
|
+
orientation?: Orientation;
|
|
74
|
+
};
|
|
75
|
+
snap?: SnapConfig;
|
|
71
76
|
};
|
|
72
77
|
declare const DashfooLayout: import("react").ForwardRefExoticComponent<DashfooLayoutProps & import("react").RefAttributes<DashfooHandle>>;
|
|
73
78
|
//#endregion
|
|
@@ -117,6 +122,8 @@ type LayoutRootProps = Omit<ComponentProps<"div">, "children"> & {
|
|
|
117
122
|
renderTabLabel?: (tab: TabNode) => ReactNode;
|
|
118
123
|
renderTabsetToolbar?: (tabset: TabsetNode) => ReactNode;
|
|
119
124
|
resizableSplits?: boolean;
|
|
125
|
+
rootRef?: Ref<HTMLDivElement>;
|
|
126
|
+
snap?: SnapConfig;
|
|
120
127
|
};
|
|
121
128
|
//#endregion
|
|
122
129
|
//#region src/components/row-view.d.ts
|
|
@@ -152,6 +159,8 @@ declare const Layout: {
|
|
|
152
159
|
renderTabLabel,
|
|
153
160
|
renderTabsetToolbar,
|
|
154
161
|
resizableSplits,
|
|
162
|
+
rootRef,
|
|
163
|
+
snap,
|
|
155
164
|
style,
|
|
156
165
|
...props
|
|
157
166
|
}: LayoutRootProps) => import("react").ReactNode;
|
|
@@ -325,6 +334,7 @@ type LayoutState = {
|
|
|
325
334
|
renderTabLabel: ((tab: TabNode) => ReactNode) | undefined;
|
|
326
335
|
renderTabsetToolbar: ((tabset: TabsetNode) => ReactNode) | undefined;
|
|
327
336
|
resizableSplits: boolean;
|
|
337
|
+
snap: SnapConfig | null;
|
|
328
338
|
splitDock: boolean;
|
|
329
339
|
tabLocation: "bottom" | "top";
|
|
330
340
|
tabsetMinSize: number;
|
|
@@ -334,6 +344,7 @@ declare const useLayout: <T>(selector: (state: LayoutState) => T) => T;
|
|
|
334
344
|
//#endregion
|
|
335
345
|
//#region src/hooks/responsive.d.ts
|
|
336
346
|
type Breakpoint = {
|
|
347
|
+
compact?: boolean;
|
|
337
348
|
id: string;
|
|
338
349
|
model: Dashfoo;
|
|
339
350
|
query?: {
|
|
@@ -348,11 +359,15 @@ type UseResponsiveModelOptions = {
|
|
|
348
359
|
type ResponsiveModel = {
|
|
349
360
|
breakpoint: string;
|
|
350
361
|
containerRef: (element: HTMLElement | null) => void;
|
|
351
|
-
|
|
352
|
-
|
|
362
|
+
draggableTabs: boolean;
|
|
363
|
+
draggableTabsets: boolean;
|
|
364
|
+
isCompact: boolean;
|
|
365
|
+
model: Dashfoo;
|
|
366
|
+
resizableSplits: boolean;
|
|
353
367
|
};
|
|
354
368
|
declare const matchBreakpoint: (breakpoint: Breakpoint, width: number) => boolean;
|
|
355
369
|
declare const activeBreakpoint: (breakpoints: Array<Breakpoint>, width: number) => Breakpoint;
|
|
370
|
+
declare const useContainerWidth: () => [(element: HTMLElement | null) => void, number];
|
|
356
371
|
declare const useResponsiveModel: ({
|
|
357
372
|
breakpoints
|
|
358
373
|
}: UseResponsiveModelOptions) => ResponsiveModel;
|
|
@@ -377,5 +392,5 @@ type UseDashfooStoreOptions = {
|
|
|
377
392
|
};
|
|
378
393
|
declare const useDashfooStore: (options: UseDashfooStoreOptions) => DashfooStore;
|
|
379
394
|
//#endregion
|
|
380
|
-
export { type Breakpoint, DashfooDragProvider, type DashfooHandle, DashfooLayout, type DashfooLayoutProps, type DashfooStore, type ExternalTabSourceOptions, Layout, type DragProviderProps as LayoutDragLayerProps, type LayoutRootProps, type RowViewProps as LayoutRowsProps, type LayoutState, type TabsetViewProps as LayoutTabsetProps, Panel, type PanelBadgeProps, type PanelBodyProps, type PanelHeaderProps, type PanelIconProps, type PanelRootProps, type PanelTitleProps, type PersistConfig, type Persistence, type ResponsiveModel, type StorageAdapter, type TabComponent, type TabContextValue, Tabset, type TabsetCloseButtonProps, type TabsetContentProps, type TabsetGripProps, type TabsetMaximizeButtonProps, type TabsetRenameInputProps, type TabsetRootProps, type TabsetState, type TabsetTabProps, type TabsetTabStripProps, type TabsetTablistProps, type TabsetToolbarProps, type TabsetTriggerProps, type UseDashfooStoreOptions, type UseResponsiveModelOptions, activeBreakpoint, localStorageAdapter, matchBreakpoint, memoryStorageAdapter, useDashfooStore, useDragSubject, useDropIntent, useExternalTabSource, useLayout, usePersistence, useResponsiveModel, useTab, useTabset };
|
|
395
|
+
export { type Breakpoint, DashfooDragProvider, type DashfooHandle, DashfooLayout, type DashfooLayoutProps, type DashfooStore, type ExternalTabSourceOptions, Layout, type DragProviderProps as LayoutDragLayerProps, type LayoutRootProps, type RowViewProps as LayoutRowsProps, type LayoutState, type TabsetViewProps as LayoutTabsetProps, Panel, type PanelBadgeProps, type PanelBodyProps, type PanelHeaderProps, type PanelIconProps, type PanelRootProps, type PanelTitleProps, type PersistConfig, type Persistence, type ResponsiveModel, type StorageAdapter, type TabComponent, type TabContextValue, Tabset, type TabsetCloseButtonProps, type TabsetContentProps, type TabsetGripProps, type TabsetMaximizeButtonProps, type TabsetRenameInputProps, type TabsetRootProps, type TabsetState, type TabsetTabProps, type TabsetTabStripProps, type TabsetTablistProps, type TabsetToolbarProps, type TabsetTriggerProps, type UseDashfooStoreOptions, type UseResponsiveModelOptions, activeBreakpoint, localStorageAdapter, matchBreakpoint, memoryStorageAdapter, useContainerWidth, useDashfooStore, useDragSubject, useDropIntent, useExternalTabSource, useLayout, usePersistence, useResponsiveModel, useTab, useTabset };
|
|
381
396
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","names":[],"sources":["../src/hooks/persistence.ts","../src/components/dashfoo-layout.tsx","../src/components/drag-root.tsx","../src/hooks/drag-hooks.tsx","../src/components/drag-adapter.tsx","../src/components/layout-root.tsx","../src/components/row-view.tsx","../src/components/tabset/tabset-view.tsx","../src/components/layout.tsx","../src/components/panel.tsx","../src/components/tabset/tabset-tab-controls.tsx","../src/components/tabset/tabset-content.tsx","../src/components/tabset/tabset-toolbar.tsx","../src/components/tabset/tabset-root.tsx","../src/components/tabset/tabset-tab.tsx","../src/components/tabset/tabset-tablist.tsx","../src/components/tabset/tabset.ts","../src/components/tab-overflow.tsx","../src/components/tabset/tabset-store.ts","../src/hooks/layout-store.ts","../src/hooks/responsive.ts","../src/hooks/store.ts"],"mappings":";;;;KAQK,cAAA;EACH,OAAA,GAAU,GAAA;EACV,UAAA,GAAa,GAAA;EACb,OAAA,GAAU,GAAA,UAAa,KAAA;AAAA;AAAA,cAGnB,oBAAA,QAA2B,cAWhC;AAAA,cAIK,mBAAA,EAAqB,cAiC1B;AAAA,KAII,aAAA;EACH,UAAA;EACA,GAAA;EACA,OAAA,EAAS,cAAc;AAAA;AAAA,KAGpB,WAAA;EACH,KAAA;EAEA,YAAA,EAAc,OAAA;EACd,IAAA,GAAO,KAAA,EAAO,OAAO;AAAA;AAAA,cASjB,cAAA,GACJ,MAAA,EAAQ,aAAA,SACR,YAAA,EAAc,OAAA,iBACb,WAAA;;;
|
|
1
|
+
{"version":3,"file":"index.d.ts","names":[],"sources":["../src/hooks/persistence.ts","../src/components/dashfoo-layout.tsx","../src/components/drag-root.tsx","../src/hooks/drag-hooks.tsx","../src/components/drag-adapter.tsx","../src/components/layout-root.tsx","../src/components/row-view.tsx","../src/components/tabset/tabset-view.tsx","../src/components/layout.tsx","../src/components/panel.tsx","../src/components/tabset/tabset-tab-controls.tsx","../src/components/tabset/tabset-content.tsx","../src/components/tabset/tabset-toolbar.tsx","../src/components/tabset/tabset-root.tsx","../src/components/tabset/tabset-tab.tsx","../src/components/tabset/tabset-tablist.tsx","../src/components/tabset/tabset.ts","../src/components/tab-overflow.tsx","../src/components/tabset/tabset-store.ts","../src/hooks/layout-store.ts","../src/hooks/responsive.ts","../src/hooks/store.ts"],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
"use client";import{canRedo as e,canUndo as t,dashfooMachine as n,dragDockMachine as r,findTabset as i,fromJSON as a,normalize as o,reducer as s,resolveDockTarget as c,
|
|
1
|
+
"use client";import{canRedo as e,canUndo as t,dashfooMachine as n,dragDockMachine as r,findTabset as i,fromJSON as a,normalize as o,reducer as s,resolveDockTarget as c,snapEnabled as l,snapSizes as u,stackModel as d,tabNodeSchema as f,toJSON as p,zoneRect as m}from"@dashfoo/core";import{Fragment as h,createContext as g,createElement as _,forwardRef as v,useCallback as y,useContext as b,useEffect as x,useId as S,useImperativeHandle as C,useInsertionEffect as w,useLayoutEffect as T,useMemo as E,useRef as D,useState as O}from"react";import{useActorRef as k,useSelector as A}from"@xstate/react";import{Accessibility as j,DragDropManager as ee,Draggable as te,Feedback as ne,PointerSensor as M}from"@dnd-kit/dom";import{createStore as N,useStore as P}from"zustand";import{Fragment as F,jsx as I,jsxs as L}from"react/jsx-runtime";import{Group as re,Panel as ie,Separator as ae}from"react-resizable-panels";const oe=()=>{let e=new Map;return{getItem:t=>e.get(t)??null,removeItem:t=>{e.delete(t)},setItem:(t,n)=>{e.set(t,n)}}},R={getItem:e=>{if(typeof window>`u`)return null;try{return window.localStorage.getItem(e)}catch{return null}},removeItem:e=>{if(!(typeof window>`u`))try{window.localStorage.removeItem(e)}catch{}},setItem:(e,t)=>{if(!(typeof window>`u`))try{window.localStorage.setItem(e,t)}catch(e){console.warn(`[dashfoo] failed to persist layout`,e)}}},se=(e,t)=>{let n=D(e);x(()=>{n.current=e});let[r]=O(()=>{if(e===null||t===void 0)return t;let n=e.storage.getItem(e.key);if(n===null)return t;try{return a(n)}catch{return t}});x(()=>{let e=n.current;if(e===null)return;let t=e.storage.getItem(e.key);if(t!==null)try{a(t)}catch(t){console.warn(`[dashfoo] discarding unreadable persisted layout`,t),e.storage.removeItem(e.key)}},[]);let i=D(e?.key);x(()=>{e!==null&&e.key!==i.current&&(console.warn(`[dashfoo] persist key changed for a mounted layout; the displayed layout still reflects the previous key — remount (key={persistKey}) to load the new key`),i.current=e.key)},[e]);let o=D(null),s=D(null),c=y(()=>{o.current!==null&&(clearTimeout(o.current),o.current=null),s.current!==null&&(s.current.storage.setItem(s.current.key,s.current.value),s.current=null)},[]),l=y(e=>{let t=n.current;t!==null&&(s.current={key:t.key,storage:t.storage,value:p(e)},o.current!==null&&clearTimeout(o.current),o.current=setTimeout(c,t.debounceMs))},[c]);x(()=>{let e=()=>{c()},t=()=>{document.visibilityState===`hidden`&&c()};return window.addEventListener(`pagehide`,e),document.addEventListener(`visibilitychange`,t),()=>{window.removeEventListener(`pagehide`,e),document.removeEventListener(`visibilitychange`,t),c()}},[c]);let u=y(()=>{o.current!==null&&(clearTimeout(o.current),o.current=null),s.current=null;let e=n.current;e!==null&&e.storage.removeItem(e.key)},[]);return E(()=>({clear:u,initialModel:r,save:l}),[u,r,l])},ce=()=>typeof window<`u`&&typeof window.matchMedia==`function`,le=(e,t)=>{let{query:n}=e;return n?`maxWidth`in n?t<=n.maxWidth:ce()&&window.matchMedia(n.media).matches:!0},ue=(e,t)=>{let n=e.at(-1);if(!n)throw Error(`useResponsiveModel requires at least one breakpoint.`);return e.find(e=>le(e,t))??n},z=()=>{let[e,t]=O(1/0),n=D(null),r=y(e=>{if(n.current?.disconnect(),!e)return;let r=new ResizeObserver(e=>{let n=e[0];n&&t(n.contentRect.width)});r.observe(e),n.current=r},[]);return x(()=>()=>{n.current?.disconnect()},[]),[r,e]},de=({breakpoints:e})=>{let[t,n]=z(),[,r]=O(0);x(()=>{if(!ce())return;let t=e.flatMap(e=>e.query&&`media`in e.query?[window.matchMedia(e.query.media)]:[]);if(t.length===0)return;let n=()=>{r(e=>e+1)};for(let e of t)e.addEventListener(`change`,n);return()=>{for(let e of t)e.removeEventListener(`change`,n)}},[e]);let i=ue(e,n),a=i.compact===!0;return{breakpoint:i.id,containerRef:t,draggableTabs:!a,draggableTabsets:!a,isCompact:a,model:i.model,resizableSplits:!a}},fe=r=>{let{defaultModel:i,model:a,onAction:c,onActiveTabsetChange:l,onMaximizedTabsetChange:u,onModelChange:d}=r,f=a??i;if(f===void 0)throw Error("useDashfooStore requires either a `model` or a `defaultModel`.");let p=k(n,{input:{model:o(f)}}),m=A(p,e=>e.context.history);x(()=>{a!==void 0&&p.send({model:o(a),type:`SET_MODEL`})},[p,a]);let h=a??m.present,g=y((e,t,n)=>{Object.is(e,t)||(d?.(t,n),t.activeTabsetId!==e.activeTabsetId&&l?.(t.activeTabsetId),t.maximizedTabsetId!==e.maximizedTabsetId&&u?.(t.maximizedTabsetId))},[d,l,u]),_=y(e=>{let t=c?c(e):e;if(!t)return;let n=(()=>{if(a===void 0){let e=p.getSnapshot().context.history.present;return p.send({action:t,type:`DISPATCH`}),{after:p.getSnapshot().context.history.present,before:e}}return{after:s(a,t),before:o(a)}})();g(n.before,n.after,t)},[p,a,g,c]),v=y(()=>{if(a!==void 0)return;let e=p.getSnapshot().context.history.present;p.send({type:`UNDO`});let t=p.getSnapshot().context.history.present;g(e,t)},[p,a,g]),b=y(()=>{if(a!==void 0)return;let e=p.getSnapshot().context.history.present;p.send({type:`REDO`});let t=p.getSnapshot().context.history.present;g(e,t)},[p,a,g]),S=y(e=>{p.send({model:o(e),type:`SET_MODEL`})},[p]);return E(()=>({canRedo:()=>e(p.getSnapshot().context.history),canUndo:()=>t(p.getSnapshot().context.history),dispatch:_,model:h,redo:b,setModel:S,undo:v}),[p,_,h,b,S,v])},pe=(e,t)=>{let{target:n}=e;if(!(n instanceof Element))return!1;let r=n.closest(`
|
|
2
2
|
input:not([disabled]),
|
|
3
3
|
select:not([disabled]),
|
|
4
4
|
textarea:not([disabled]),
|
|
5
5
|
button:not([disabled]),
|
|
6
6
|
a[href],
|
|
7
7
|
[contenteditable]:not([contenteditable="false"])
|
|
8
|
-
`);return r!==null&&r!==t.element},ue=()=>new k({plugins:e=>e.filter(e=>e!==O&&e!==ee),sensors:()=>[te.configure({preventActivation:le})]}),I=p(null),L=p(null),R=()=>j(()=>({intent:null,intentOwner:null,subject:null})),de=(e,t)=>e===t||e!==null&&t!==null&&e.index===t.index&&e.location===t.location&&e.targetId===t.targetId,fe=(e,t)=>e===t||e!==null&&t!==null&&e.id===t.id&&e.kind===t.kind,pe=R(),z=p(null),me=()=>{let e=w(null),t=w(null);return{draggableRef:t,elementRef:e,ref:g(n=>{e.current=n,t.current&&(t.current.element=n??void 0)},[])}},B=(e,t,n)=>{let r=_(I),i=_(L),a=r?.manager??i,{draggableRef:o,elementRef:s,ref:c}=me(),{data:l,id:u}=e;return v(()=>{if(!a||t)return;let e=new A({data:{...l,label:``},id:u},a);return e.element=s.current??void 0,o.current=e,()=>{e.destroy(),o.current=null}},[l,t,o,s,u,a]),v(()=>{let e=o.current;e&&(e.data={...l,label:n})},[l,o,n]),{ref:c}},he=(e,t=!1,n=``)=>B({data:C(()=>({type:`tab`}),[]),id:e},t,n),ge=(e,t=!1,n=``)=>B({data:C(()=>({tabsetId:e,type:`tabset`}),[e]),id:`grip-${e}`},t,n),_e=e=>{let t=_(I);return{ref:g(n=>{t?.registerTabset(e,n)},[t,e])}},ve=({createTab:e,disabled:t=!1,label:n=``})=>{let r=y(),i=w(e);return v(()=>{i.current=e}),B({data:C(()=>({createTab:()=>i.current(),type:`external`}),[]),id:`external-${r}`},t,n)},V=()=>M(_(z)??pe,e=>e.subject),ye=()=>M(_(z)??pe,e=>e.intent),be=e=>j(()=>e),H=p(null),U=e=>{let t=_(H);if(t===null)throw Error(`dashfoo components must be rendered inside <DashfooLayout> or <Layout.Root>.`);return M(t,e)},xe=(e,t)=>e.x>=t.x&&e.x<=t.x+t.width&&e.y>=t.y&&e.y<=t.y+t.height,Se=(e,t)=>{let n=e.findIndex(e=>t<e.x+e.width/2);return n===-1?e.length:n},Ce=(e,t,n)=>{let r=t[n],i=t.at(-1),a=(r?.x??(i?i.x+i.width:e.x))-4/2;return{height:e.height,width:4,x:Math.max(e.x,Math.min(a,e.x+e.width-4)),y:e.y}},we=(e,t,n)=>!(e===`grip-${t}`||n.length===1&&n[0]===e),Te=new Set,W=(e,t)=>{Te.has(e)||(Te.add(e),console.warn(`[dashfoo] ${t}`))},Ee={boxSizing:`border-box`,pointerEvents:`none`,position:`fixed`,transition:`var(--dashfoo-dock-transition, left 60ms, top 60ms, width 60ms, height 60ms)`,zIndex:9999},De=e=>({...Ee,background:`var(--dashfoo-dock-fill, oklch(0.556 0 0 / 0.18))`,border:`var(--dashfoo-dock-border-width, 1px) solid var(--dashfoo-dock-border, oklch(0.708 0 0 / 0.75))`,borderRadius:`var(--dashfoo-dock-radius, 6px)`,height:e.height,left:e.x,top:e.y,width:e.width}),Oe=e=>({...De(e),borderRadius:`var(--dashfoo-dock-line-radius, 2px)`}),ke=(e,t)=>[...e.querySelectorAll(`[data-dashfoo="tab-item"]`)].flatMap(e=>e.querySelector(`[data-dashfoo="tab"]`)?.dataset.tabId===t?[]:[e.getBoundingClientRect()]),Ae=({actorRef:e,getTabsetElement:t})=>{let n=D(e,e=>e.context.intent),r=D(e,e=>e.context.subject?.id);if(!n)return null;let i=t(n.targetId);if(!i)return null;if(n.location===`center`){let e=i.querySelector(`[data-dashfoo="tabstrip"]`);if(e)return N(`div`,{"data-dashfoo":`dock-indicator`,style:Oe(Ce(e.getBoundingClientRect(),ke(e,r),n.index??0))})}return N(`div`,{"data-dashfoo":`dock-indicator`,style:De(d(i.getBoundingClientRect(),n.location))})},je={left:0,position:`fixed`,top:0,zIndex:9999},Me=({overlayRef:e,preview:t})=>t?N(`div`,{"data-dashfoo":`drag-preview`,ref:e,style:{...je,transform:`translate(${t.x}px, ${t.y}px)`},children:t.label}):null,Ne=(e,t)=>[...e.querySelectorAll(`[data-dashfoo="tab"]`)].flatMap(e=>e.dataset.tabId===t?[]:[e.getBoundingClientRect()]),Pe=(e,t,n,r)=>{let i=t.querySelector(`[data-dashfoo="tabstrip"]`);if(i&&xe(n,i.getBoundingClientRect()))return{index:Se(Ne(i,r),n.x),location:`center`,targetId:e};let a=c(n,t.getBoundingClientRect()),o=a.kind===`tab`?`center`:`split-${a.edge}`;return o===`center`&&i?{index:Ne(i,r).length,location:o,targetId:e}:{location:o,targetId:e}},G={x:12,y:8},Fe=e=>{let t=e?.data?.label;return typeof t==`string`?t:``},Ie=e=>typeof e==`function`,Le=e=>{let t=e.data;if(t?.type===`tabset`)return{id:String(t.tabsetId),kind:`tabset`};if(t?.type===`external`){if(!Ie(t.createTab))return console.warn(`[dashfoo] external drag source is missing its createTab function`),null;let n;try{n=t.createTab()}catch(e){return console.warn(`[dashfoo] external drag source createTab threw`,e),null}let r=l.safeParse(n);return r.success?{id:String(e.id),kind:`external`,tab:r.data}:(console.warn(`[dashfoo] external drag source returned an invalid tab`,r.error),null)}return{id:String(e.id),kind:`tab`}},Re=({children:e,onCommit:t,splitDock:n})=>{let i=E(r),a=_(H),o=w(new Map),s=w(null),[c,l]=T(null),u=_(L),[d]=T(()=>u?null:ue());x(()=>()=>d?.destroy(),[d]);let f=u??d;if(f===null)throw Error(`[dashfoo] DashfooDragProvider unmounted while its layout is still mounted; keep the provider above the layout or remount the layout`);let p=_(z),[m]=T(()=>p??R()),h=y();v(()=>{let e=i.subscribe(e=>{let{intent:t,subject:n}=e.context,r=m.getState();t===null?r.intent!==null&&r.intentOwner===h&&m.setState({intent:null,intentOwner:null}):(!de(r.intent,t)||r.intentOwner!==h)&&m.setState({intent:t,intentOwner:h}),fe(m.getState().subject,n)||m.setState({subject:n})});return()=>{e.unsubscribe()}},[i,h,m]),v(()=>{let e=i.on(`COMMIT`,e=>{if(a?.getState().editable===!1)return;let n=t??a?.getState().dispatch;if(!n){W(`drag-layer-no-commit`,`Layout.DragLayer has neither an onCommit prop nor a <Layout.Root> above it; drops are ignored`);return}n(e.action)});return()=>{e.unsubscribe()}},[i,a,t]);let b=g((e,t)=>{t?o.current.set(e,t):o.current.delete(e)},[]),S=g(e=>o.current.get(e),[]),D=g(e=>{for(let[t,n]of o.current)if(xe(e,n.getBoundingClientRect()))return{element:n,id:t}},[]),O=g((e,t,r,i)=>{if(a?.getState().editable===!1||!we(i,e,[...t.querySelectorAll(`[data-dashfoo="tab"]`)].map(e=>e.dataset.tabId??``)))return null;let o=Pe(e,t,r,i);return!(n??a?.getState().splitDock??!0)&&o.location.startsWith(`split-`)?{location:`center`,targetId:e}:o},[a,n]),k=g(e=>{let t=s.current;t&&(t.style.transform=`translate(${e.x+G.x}px, ${e.y+G.y}px)`)},[]),A=g(e=>{s.current=e},[]);v(()=>{let e=e=>{let t=e.operation.source;if(!t)return;let n=Le(t);if(!n)return;let r=e.operation.position.current;l({label:Fe(t),x:r.x+G.x,y:r.y+G.y}),i.send({subject:n,type:`START`})},t=e=>{let t=e.operation,n=t.position.current;k(n);let r=t.source?String(t.source.id):void 0,a=D(n);i.send({intent:a?O(a.id,a.element,n,r):null,type:`OVER`})},n=e=>{if(l(null),e.canceled){i.send({type:`CANCEL`});return}let t=e.operation,n=t.position.current,r=t.source?String(t.source.id):void 0,a=D(n);a&&i.send({intent:O(a.id,a.element,n,r),type:`OVER`}),i.send({type:`DROP`})},r=f.monitor.addEventListener(`dragstart`,e),a=f.monitor.addEventListener(`dragmove`,t),o=f.monitor.addEventListener(`dragend`,n);return()=>{r(),a(),o()}},[i,f,k,O,D]);let ee=C(()=>({manager:f,registerTabset:b}),[f,b]);return N(I.Provider,{value:ee,children:P(z.Provider,{value:m,children:[e,N(Ae,{actorRef:i,getTabsetElement:S}),N(Me,{overlayRef:A,preview:c})]})})},ze={display:`flex`,height:`100%`,width:`100%`},Be=({children:e,closableTabs:t=!0,dispatch:n,draggableTabs:r=!0,draggableTabsets:i=!0,editable:a=!0,keepMounted:o=!1,maximizable:s=!0,model:c,renamableTabs:l=!0,renderTab:u,renderTabLabel:d,renderTabsetToolbar:f,resizableSplits:p=!0,style:m,...h})=>{let g=c.global,_={closableTabs:a&&t&&g.tabEnableClose!==!1,dispatch:n,draggableTabs:a&&r&&g.tabEnableDrag!==!1,draggableTabsets:a&&i,editable:a,keepMounted:o,maximizable:s&&g.tabSetEnableMaximize!==!1,maximizedTabsetId:c.maximizedTabsetId,renamableTabs:a&&l&&g.tabEnableRename!==!1,renderTab:u,renderTabLabel:d,renderTabsetToolbar:f,resizableSplits:a&&p&&g.enableSplitResize!==!1,splitDock:g.enableSplitDock!==!1,tabLocation:g.tabLocation??`top`,tabsetMinSize:g.tabSetMinSize??320,tabStripEnabled:g.tabSetEnableTabStrip!==!1},[v]=T(()=>be(_));S(()=>{v.setState(_)});let y=g.splitterSize===void 0?{...ze,...m}:{...ze,"--dashfoo-splitter-size":`${g.splitterSize}px`,...m};return N(H.Provider,{value:v,children:N(`div`,{...h,"data-dashfoo":`layout`,style:y,children:e})})},K=(e,t)=>`dashfoo-tab-${e}-${t}`,q=e=>`dashfoo-panel-${e}`,Ve=(e,t,n)=>e?.querySelector(`#${CSS.escape(K(t,n))}`)??null,He=e=>j((t,n)=>({...e,cancelRename:()=>t({editingTabId:null}),closeTab:e=>{t({restoreFocus:!0}),n().dispatch({tabId:e,type:`deleteTab`})},commitRename:(e,r)=>{t({editingTabId:null});let{node:i,renameTab:a}=n(),o=r.trim(),s=i.children.find(t=>t.id===e)?.name;o&&o!==s&&a(e,o)},editingTabId:null,overflowItems:[],registerRenameInput:()=>(t(e=>({renameInputCount:e.renameInputCount+1})),()=>t(e=>({renameInputCount:e.renameInputCount-1}))),registerTablist:e=>{if(e){let r=n().tablistElement;r&&r!==e&&W(`duplicate-tablist-${n().node.id}`,`more than one <Tabset.Tablist> under the same <Tabset.Root>; the last one wins for keyboard focus and overflow`),t({tablistElement:e});return}t({tablistElement:null})},renameInputCount:0,renameTab:(e,t)=>n().dispatch({name:t,tabId:e,type:`renameTab`}),restoreFocus:!1,selectOverflowTab:e=>{let{dispatch:t,node:r,tablistElement:i}=n(),a=r.children.findIndex(t=>t.id===e);a!==-1&&(t({index:a,tabsetId:r.id,type:`selectTab`}),Ve(i,r.id,e)?.scrollIntoView({block:`nearest`,inline:`nearest`}))},selectTab:(e,t)=>{let{dispatch:r,node:i,tablistElement:a}=n();if(r({index:e,tabsetId:i.id,type:`selectTab`}),t?.focus){let t=i.children[e]?.id;t&&Ve(a,i.id,t)?.focus()}},startEditing:e=>{let{node:r,renameInputCount:i,tabsRenamable:a}=n(),o=r.children.find(t=>t.id===e);if(!(!a||o?.enableRename===!1)){if(i===0){W(`missing-rename-input-${r.id}`,`startEditing needs a <Tabset.RenameInput> in the composition; ignoring`);return}t({editingTabId:e})}},tablistElement:null,toggleMaximize:()=>{let{dispatch:e,isMaximized:t,node:r}=n();e({tabsetId:t?null:r.id,type:`setMaximizedTabset`})}})),J=p(null),Y=e=>{let t=_(J);if(t===null)throw Error(`dashfoo Tabset parts must be rendered inside <Tabset.Root>.`);return M(t,e)},Ue=p(null),X=()=>{let e=_(Ue);if(e===null)throw Error(`dashfoo tab parts must be rendered inside <Tabset.Tab>.`);return e},We={flex:1,minHeight:0,overflow:`auto`},Ge=({render:e,tab:t})=>{let n=U(e=>e.renderTab);return e?e(t):n(t)},Ke=({children:e,style:t,...n})=>{let r=Y(e=>e.node),i=Y(e=>e.visualSelected),a=U(e=>e.keepMounted),o={...We,...t};if(a&&r.children.length>0)return r.children.map((t,a)=>m(`div`,{...n,"aria-labelledby":K(r.id,t.id),"data-dashfoo":`tabcontent`,hidden:a!==i||void 0,id:a===i?q(r.id):void 0,key:t.id,role:a===i?`tabpanel`:void 0,style:o,tabIndex:a===i?0:void 0},N(Ge,{render:e,tab:t})));let s=r.children[i];return s?N(`div`,{...n,"aria-labelledby":K(r.id,s.id),"data-dashfoo":`tabcontent`,id:q(r.id),role:`tabpanel`,style:o,tabIndex:0,children:N(Ge,{render:e,tab:s})}):N(`div`,{...n,"data-dashfoo":`tabcontent`,style:o})},qe=()=>P(`svg`,{"aria-hidden":`true`,fill:`currentColor`,height:`10`,viewBox:`0 0 10 10`,width:`10`,children:[N(`circle`,{cx:`2`,cy:`5`,r:`1`}),N(`circle`,{cx:`5`,cy:`5`,r:`1`}),N(`circle`,{cx:`8`,cy:`5`,r:`1`})]}),Je={position:`absolute`,right:0,top:`100%`,zIndex:10},Ye=({items:e,onSelect:t})=>{let[n,r]=T(!1),[i,a]=T(0),o=w(null),s=w(null),c=w([]);v(()=>{if(!n)return;let e=e=>{e.target instanceof Node&&!o.current?.contains(e.target)&&r(!1)};return document.addEventListener(`pointerdown`,e),()=>{document.removeEventListener(`pointerdown`,e)}},[n]),v(()=>{n&&c.current[0]?.focus()},[n]);let l=()=>{r(!1),s.current?.focus()},u=e=>{a(e),c.current[e]?.focus()},d=()=>{a(0),r(e=>!e)},f=e=>{t(e),l()};return P(`div`,{"data-dashfoo":`tab-overflow-root`,ref:o,style:{position:`relative`},children:[N(`button`,{"aria-expanded":n,"aria-haspopup":`menu`,"aria-label":`More tabs`,"data-dashfoo":`tab-overflow`,onClick:d,ref:s,type:`button`,children:N(qe,{})}),n?N(`div`,{"data-dashfoo":`tab-overflow-menu`,onBlur:e=>{e.relatedTarget instanceof Node&&o.current?.contains(e.relatedTarget)||r(!1)},onKeyDown:t=>{let n=e.length-1;switch(t.key){case`ArrowDown`:t.preventDefault(),u(i>=n?0:i+1);break;case`ArrowUp`:t.preventDefault(),u(i<=0?n:i-1);break;case`Home`:t.preventDefault(),u(0);break;case`End`:t.preventDefault(),u(n);break;case`Escape`:t.preventDefault(),l();break;default:break}},role:`menu`,style:Je,tabIndex:-1,children:e.map((e,t)=>N(`button`,{"data-dashfoo":`tab-overflow-item`,onClick:()=>f(e.id),ref:e=>{c.current[t]=e},role:`menuitem`,tabIndex:t===i?0:-1,type:`button`,children:e.name},e.id))}):null]})},Xe=()=>{let e=Y(e=>e.overflowItems),t=Y(e=>e.selectOverflowTab);return e.length===0?null:N(Ye,{items:e,onSelect:t})},Ze=e=>{let t=e.getBoundingClientRect();return[...e.querySelectorAll(`[data-dashfoo="tab"]`)].flatMap(e=>{let n=e.getBoundingClientRect();return(n.right>t.right+1||n.left<t.left-1)&&e.dataset.tabId?[e.dataset.tabId]:[]})},Qe=(e,t)=>{let[n,r]=T([]);return v(()=>{let t=()=>{r(t=>{let n=e?Ze(e):[];return n.length===0&&t.length===0?t:n})};if(t(),!e)return;let n=new ResizeObserver(t);return n.observe(e),e.addEventListener(`scroll`,t,{passive:!0}),()=>{n.disconnect(),e.removeEventListener(`scroll`,t)}},[e,t]),n},$e=(e,t)=>t+1<e?t+1:t-1,et={display:`flex`,flexDirection:`column`,height:`100%`,minHeight:0,minWidth:0,width:`100%`},tt=({children:e,node:t,ref:n,style:r,...i})=>{let a=U(e=>e.closableTabs),o=U(e=>e.dispatch),s=U(e=>e.maximizable),c=U(e=>e.maximizedTabsetId),l=U(e=>e.renamableTabs),u=U(e=>e.tabLocation),{ref:d}=_e(t.id),f=V(),p=w(null),m=c===t.id,h=s&&t.enableMaximize!==!1,g=a&&t.enableClose!==!1,_=l,y=f?.kind===`tab`?t.children.findIndex(e=>e.id===f.id):-1,b=y!==-1&&y===t.selected?$e(t.children.length,y):t.selected,x=t.children[b],E=f?.kind===`tabset`&&f.id===t.id,D={activeTab:x,dispatch:o,isMaximized:m,node:t,showMaximize:h,tabsClosable:g,tabsRenamable:_,visualSelected:b},[O]=T(()=>He(D));S(()=>{O.setState(D)});let k=Qe(M(O,e=>e.tablistElement),t.children.map(e=>`${e.id}:${e.name}`).join(`|`)),A=C(()=>{let e=new Map(t.children.map(e=>[e.id,e.name]));return k.map(t=>({id:t,name:e.get(t)??t}))},[k,t.children]);return S(()=>{O.setState({overflowItems:A})},[A,O]),v(()=>{if(!O.getState().restoreFocus)return;O.setState({restoreFocus:!1});let e=t.children[t.selected]?.id;e?p.current?.querySelector(`#${CSS.escape(K(t.id,e))}`)?.focus():p.current?.focus()},[t.children,t.selected,t.id,O]),N(J.Provider,{value:O,children:N(`div`,{...i,"data-dashfoo":`tabset`,"data-dragging-source":E||void 0,"data-tab-location":u,ref:e=>{d(e),p.current=e,typeof n==`function`?n(e):n&&(n.current=e)},style:{...et,...r},tabIndex:-1,children:e})})},nt=(e,t)=>{typeof e==`function`?e(t):e&&(e.current=t)},Z=(...e)=>t=>{for(let n of e)nt(n,t)},rt=({children:e,ref:t,tab:n,...r})=>{let i=_(J),a=Y(e=>e.node),o=Y(e=>e.editingTabId===n.id),s=V(),c=s?.kind===`tab`&&s.id===n.id,l=w(null),u=w(!1),d=a.children.findIndex(e=>e.id===n.id);v(()=>{i?.getState().node.children.some(e=>e.id===n.id)===!1&&W(`orphan-tab-${n.id}`,`<Tabset.Tab> for "${n.id}" is not a child of its Tabset.Root's node; it renders but can never be selected`)},[d===-1,i,n.id]),v(()=>{u.current&&!o&&l.current?.querySelector(`[data-dashfoo="tab"]`)?.focus(),u.current=o},[o]);let f=C(()=>({index:d,tab:n}),[d,n]),p=C(()=>Z(l,t),[t]);return N(Ue.Provider,{value:f,children:N(`span`,{...r,"data-dashfoo":`tab-item`,"data-dragging":c||void 0,ref:p,children:e})})},it=({children:e,onClick:t,onDoubleClick:n,ref:r,...i})=>{let{index:a,tab:o}=X(),s=Y(e=>e.node),c=Y(e=>e.editingTabId===o.id),l=Y(e=>e.selectTab),u=Y(e=>e.startEditing),d=Y(e=>e.tabsRenamable),f=Y(e=>e.visualSelected),p=U(e=>e.draggableTabs),m=U(e=>e.renderTabLabel),{ref:h}=he(o.id,!p||o.enableDrag===!1,o.name),g=C(()=>Z(h,r),[h,r]);if(c)return null;let _=a===f,v=d&&o.enableRename!==!1,y=e=>{t?.(e),l(a)},b=e=>{n?.(e),v&&u(o.id)};return N(`button`,{"aria-label":m?o.name:void 0,...i,"aria-controls":q(s.id),"aria-selected":_,"data-dashfoo":`tab`,"data-tab-id":o.id,id:K(s.id,o.id),onClick:y,onDoubleClick:b,ref:g,role:`tab`,tabIndex:_?0:-1,type:`button`,children:e??(m?m(o):o.name)})},at={pointerEvents:`none`},Q=({children:e})=>N(`svg`,{"aria-hidden":`true`,fill:`none`,height:`12`,stroke:`currentColor`,strokeLinecap:`round`,strokeLinejoin:`round`,strokeWidth:`2`,style:at,viewBox:`0 0 24 24`,width:`12`,children:e}),ot=()=>P(Q,{children:[N(`path`,{d:`M18 6 6 18`}),N(`path`,{d:`m6 6 12 12`})]}),st=()=>P(Q,{children:[N(`circle`,{cx:`12`,cy:`5`,r:`1`}),N(`circle`,{cx:`19`,cy:`5`,r:`1`}),N(`circle`,{cx:`5`,cy:`5`,r:`1`}),N(`circle`,{cx:`12`,cy:`12`,r:`1`}),N(`circle`,{cx:`19`,cy:`12`,r:`1`}),N(`circle`,{cx:`5`,cy:`12`,r:`1`}),N(`circle`,{cx:`12`,cy:`19`,r:`1`}),N(`circle`,{cx:`19`,cy:`19`,r:`1`}),N(`circle`,{cx:`5`,cy:`19`,r:`1`})]}),ct=({maximized:e})=>e?P(Q,{children:[N(`path`,{d:`m14 10 7-7`}),N(`path`,{d:`M20 10h-6V4`}),N(`path`,{d:`m3 21 7-7`}),N(`path`,{d:`M4 14h6v6`})]}):P(Q,{children:[N(`path`,{d:`M15 3h6v6`}),N(`path`,{d:`m21 3-7 7`}),N(`path`,{d:`m3 21 7-7`}),N(`path`,{d:`M9 21H3v-6`})]}),lt=({defaultValue:e,onBlur:t,onKeyDown:n,ref:r,...i})=>{let{tab:a}=X(),o=Y(e=>e.cancelRename),s=Y(e=>e.commitRename),c=w(null),l=w(!1);v(()=>{c.current?.focus(),c.current?.select()},[]);let u=e=>{n?.(e),e.key===`Enter`?(l.current=!0,s(a.id,e.currentTarget.value)):e.key===`Escape`&&(l.current=!0,o())},d=e=>{t?.(e),!l.current&&(l.current=!0,s(a.id,e.currentTarget.value))};return N(`input`,{"aria-label":`Rename ${a.name}`,...i,"data-dashfoo":`tab-rename`,defaultValue:e??a.name,onBlur:d,onKeyDown:u,ref:e=>{c.current=e,typeof r==`function`?r(e):r&&(r.current=e)},type:`text`})},ut=e=>{let{tab:t}=X(),n=Y(e=>e.editingTabId===t.id),r=Y(e=>e.registerRenameInput);return v(()=>r(),[r]),n?N(lt,{...e}):null},dt=({children:e,onClick:t,...n})=>{let{index:r,tab:i}=X(),a=Y(e=>e.closeTab),o=Y(e=>e.editingTabId===i.id),s=Y(e=>e.tabsClosable),c=Y(e=>e.visualSelected);if(!(s&&i.enableClose!==!1)||o)return null;let l=e=>{t?.(e),e.stopPropagation(),a(i.id)};return N(`button`,{"aria-label":`Close ${i.name}`,...n,"data-dashfoo":`tab-close`,onClick:l,tabIndex:r===c?0:-1,type:`button`,children:e??N(ot,{})})},ft={display:`flex`,flexShrink:0},pt={display:`flex`,minWidth:0,overflowX:`auto`},mt=({style:e,...t})=>N(`div`,{...t,"data-dashfoo":`tabstrip`,style:{...ft,...e}}),ht=({onKeyDown:e,ref:t,style:n,...r})=>{let i=Y(e=>e.node),a=Y(e=>e.registerTablist),o=Y(e=>e.selectTab),s=t=>{if(e?.(t),t.defaultPrevented||!(t.target instanceof HTMLElement)||!t.target.closest(`[role="tab"]`))return;let n=i.children.length;if(n===0)return;let r={ArrowLeft:(i.selected-1+n)%n,ArrowRight:(i.selected+1)%n,End:n-1,Home:0}[t.key];r!==void 0&&(t.preventDefault(),o(r,{focus:!0}))},c=C(()=>Z(a,t),[a,t]);return N(`div`,{"aria-label":i.name??`Tabs`,...r,"aria-orientation":`horizontal`,"data-dashfoo":`tablist`,onKeyDown:s,ref:c,role:`tablist`,style:{...pt,...n},tabIndex:-1})},gt={alignItems:`center`,display:`flex`,flexShrink:0,marginInlineStart:`auto`},_t=({style:e,...t})=>N(`div`,{...t,"data-dashfoo":`tabset-toolbar`,style:{...gt,...e}}),vt=({children:e,ref:t,...n})=>{let r=Y(e=>e.activeTab?.name??``),i=Y(e=>e.isMaximized),a=Y(e=>e.node),o=!U(e=>e.draggableTabsets)||i,{ref:s}=ge(a.id,o,r),c=C(()=>Z(s,t),[s,t]);return o?null:N(`button`,{"aria-label":`Move tabset`,...n,"data-dashfoo":`tabset-grip`,ref:c,type:`button`,children:e??N(st,{})})},yt=({children:e,onClick:t,...n})=>{let r=Y(e=>e.isMaximized),i=Y(e=>e.showMaximize),a=Y(e=>e.toggleMaximize);if(!i)return null;let o=e=>{t?.(e),a()};return N(`button`,{"aria-label":r?`Restore`:`Maximize`,...n,"aria-pressed":r,"data-dashfoo":`tabset-maximize`,onClick:o,type:`button`,children:e??N(ct,{maximized:r})})},bt=()=>{let e=U(e=>e.draggableTabsets),t=U(e=>e.renderTabsetToolbar),n=U(e=>e.tabLocation),r=U(e=>e.tabStripEnabled),i=Y(e=>e.isMaximized),a=Y(e=>e.node),o=Y(e=>e.overflowItems.length),s=Y(e=>e.showMaximize)||t!==void 0||o>0||e&&!i,c=r?P(mt,{children:[N(ht,{children:a.children.map(e=>P(rt,{tab:e,children:[N(it,{}),N(ut,{}),N(dt,{})]},e.id))}),s?P(_t,{children:[N(Xe,{}),N(vt,{}),t?.(a),N(yt,{})]}):null]}):null,l=N(Ke,{});return n===`bottom`?P(ne,{children:[l,c]}):P(ne,{children:[c,l]})},xt=({node:e})=>N(tt,{node:e,children:N(bt,{})}),St=e=>`${e.value}${e.unit}`,Ct=e=>e?.unit===`px`?e.value:void 0,wt={display:`flex`,flex:1,minHeight:0,minWidth:0},Tt=.01,Et=(e,t)=>e.reduce((e,n)=>(e[n.id]=(n.weight??1)/t*100,e),{}),Dt=(e,t)=>{let n=Object.keys(e),r=Object.keys(t);return n.length===r.length?r.every(n=>Math.abs((e[n]??NaN)-t[n])<=Tt):!1},Ot=(e,t,n)=>{let r=Ct(e.min);if(r!==void 0)return r;if(e.min!==void 0)return;if(e.type===`tabset`)return n;let i=[];for(let r of e.children){let e=Ot(r,t,n);if(e===void 0)return;i.push(e)}if(i.length!==0)return e.orientation===t?i.reduce((e,t)=>e+t,0):Math.max(...i)},kt=({node:e,renderTabset:t})=>{let n=U(e=>e.dispatch),r=U(e=>e.resizableSplits),i=U(e=>e.tabsetMinSize),a=e.orientation===`row`?`horizontal`:`vertical`,o=e.children.reduce((e,t)=>e+(t.weight??1),0),s=C(()=>Et(e.children,o),[e.children,o]),c=w(!1),l=w(null),u=w(!1);return S(()=>{let e=l.current;if(!e||Dt(e.getLayout(),s))return;u.current=!0,e.setLayout(s);let t=requestAnimationFrame(()=>{u.current=!1});return()=>{cancelAnimationFrame(t),u.current=!1}},[s]),N(re,{"data-dashfoo":`row`,disabled:!r,groupRef:l,onLayoutChanged:t=>{if(!c.current){c.current=!0;return}if(u.current||!r)return;let i=e.children.map(e=>t[e.id]??e.weight??1);i.some((t,n)=>Math.abs(t-(e.children[n]?.weight??1))>Tt)&&n({rowId:e.id,type:`adjustSplit`,weights:i})},orientation:a,style:wt,children:e.children.map((n,a)=>{let s=(n.weight??1)/o*100,c=n.min?St(n.min):void 0;if(c===void 0){let t=Ot(n,e.orientation,i);c=t===void 0?void 0:`${t}px`}let l=n.max?St(n.max):void 0;return P(f,{children:[a>0?N(ae,{"data-dashfoo":`splitter`,disabled:!r}):null,N(ie,{defaultSize:`${s}%`,id:n.id,maxSize:l,minSize:c,children:n.type===`row`?N(kt,{node:n,renderTabset:t}):t?.(n)??N(xt,{node:n})})]},n.id)})},e.children.map(e=>e.id).join(`|`))},$={DragLayer:Re,Root:Be,Rows:kt,Tabset:xt},At=(e,t)=>e===void 0||!t?null:typeof e==`string`?{debounceMs:300,key:e,storage:F}:{debounceMs:e.debounceMs??300,key:e.key,storage:e.storage??F},jt=new Set,Mt=h((e,t)=>{let{closableTabs:n=!0,components:r,defaultModel:a,draggableTabs:o=!0,draggableTabsets:s=!0,editable:c=!0,factory:l,keepMounted:u=!1,maximizable:d=!0,model:f,onAction:p,onActiveTabsetChange:m,onMaximizedTabsetChange:h,onModelChange:_,persist:v,renamableTabs:y=!0,renderTabLabel:x,renderTabsetToolbar:S,resizableSplits:w=!0}=e,T=se(C(()=>At(v,a!==void 0),[v,a]),a),E=g((e,t)=>{T.save(e),_?.(e,t)},[_,T]),D=ce({defaultModel:T.initialModel??a,model:f,onAction:p,onActiveTabsetChange:m,onMaximizedTabsetChange:h,onModelChange:E});b(t,()=>({addTab:(e,t)=>D.dispatch({index:t.index,location:t.location??`center`,tab:e,targetId:t.targetId,type:`addNode`}),canRedo:D.canRedo,canUndo:D.canUndo,closeTab:e=>D.dispatch({tabId:e,type:`deleteTab`}),dispatch:D.dispatch,getModel:()=>D.model,maximizeTabset:e=>D.dispatch({tabsetId:e,type:`setMaximizedTabset`}),redo:D.redo,renameTab:(e,t)=>D.dispatch({name:t,tabId:e,type:`renameTab`}),resetLayout:()=>{T.clear(),a!==void 0&&D.setModel(a)},selectTab:(e,t)=>D.dispatch({index:t,tabsetId:e,type:`selectTab`}),undo:D.undo}),[a,T,D]);let O=g(e=>{if(l)return l(e);let t=r?.[e.component];return t?N(t,{node:e}):(r&&!jt.has(e.component)&&(jt.add(e.component),console.warn(`[dashfoo] no component registered for "${e.component}"`)),null)},[r,l]),k=D.model.maximizedTabsetId?i(D.model,D.model.maximizedTabsetId):void 0;return N($.Root,{closableTabs:n,dispatch:D.dispatch,draggableTabs:o,draggableTabsets:s,editable:c,keepMounted:u,maximizable:d,model:D.model,renamableTabs:y,renderTab:O,renderTabLabel:x,renderTabsetToolbar:S,resizableSplits:w,children:N($.DragLayer,{children:k?N($.Tabset,{node:k}):N($.Rows,{node:D.model.layout})})})});Mt.displayName=`DashfooLayout`;const Nt=({children:e})=>{let[t]=T(ue);x(()=>()=>t.destroy(),[t]);let[n]=T(R);return N(L.Provider,{value:t,children:N(z.Provider,{value:n,children:e})})},Pt={Badge:e=>N(`span`,{...e,"data-dashfoo":`panel-badge`}),Body:e=>N(`div`,{...e,"data-dashfoo":`panel-body`}),Header:e=>N(`div`,{...e,"data-dashfoo":`panel-header`}),Icon:e=>N(`span`,{...e,"data-dashfoo":`panel-icon`}),Root:e=>N(`div`,{...e,"data-dashfoo":`panel`}),Title:e=>N(`span`,{...e,"data-dashfoo":`panel-title`})},Ft={CloseButton:dt,Content:Ke,Grip:vt,MaximizeButton:yt,OverflowMenu:Xe,RenameInput:ut,Root:tt,Tab:rt,Tablist:ht,TabStrip:mt,Toolbar:_t,Trigger:it},It=()=>typeof window<`u`&&typeof window.matchMedia==`function`,Lt=(e,t)=>{let{query:n}=e;return n?`maxWidth`in n?t<=n.maxWidth:It()&&window.matchMedia(n.media).matches:!0},Rt=(e,t)=>{let n=e.at(-1);if(!n)throw Error(`useResponsiveModel requires at least one breakpoint.`);return e.find(e=>Lt(e,t))??n},zt=({breakpoints:e})=>{let[t,n]=T(1/0),[,r]=T(0),i=w(null),a=g(e=>{if(i.current?.disconnect(),!e)return;let t=new ResizeObserver(e=>{let t=e[0];t&&n(t.contentRect.width)});t.observe(e),i.current=t},[]);v(()=>()=>{i.current?.disconnect()},[]),v(()=>{if(!It())return;let t=e.flatMap(e=>e.query&&`media`in e.query?[window.matchMedia(e.query.media)]:[]);if(t.length===0)return;let n=()=>{r(e=>e+1)};for(let e of t)e.addEventListener(`change`,n);return()=>{for(let e of t)e.removeEventListener(`change`,n)}},[e]);let o=Rt(e,t);return{breakpoint:o.id,containerRef:a,defaultModel:o.model,key:o.id}};export{Nt as DashfooDragProvider,Mt as DashfooLayout,$ as Layout,Pt as Panel,Ft as Tabset,Rt as activeBreakpoint,F as localStorageAdapter,Lt as matchBreakpoint,oe as memoryStorageAdapter,ce as useDashfooStore,V as useDragSubject,ye as useDropIntent,ve as useExternalTabSource,U as useLayout,se as usePersistence,zt as useResponsiveModel,X as useTab,Y as useTabset};
|
|
8
|
+
`);return r!==null&&r!==t.element},me=()=>new ee({plugins:e=>e.filter(e=>e!==j&&e!==ne),sensors:()=>[M.configure({preventActivation:pe})]}),B=g(null),V=g(null),H=()=>N(()=>({intent:null,intentOwner:null,subject:null})),he=(e,t)=>e===t||e!==null&&t!==null&&e.index===t.index&&e.location===t.location&&e.targetId===t.targetId,ge=(e,t)=>e===t||e!==null&&t!==null&&e.id===t.id&&e.kind===t.kind,_e=H(),U=g(null),ve=()=>{let e=D(null),t=D(null);return{draggableRef:t,elementRef:e,ref:y(n=>{e.current=n,t.current&&(t.current.element=n??void 0)},[])}},W=(e,t,n)=>{let r=b(B),i=b(V),a=r?.manager??i,{draggableRef:o,elementRef:s,ref:c}=ve(),{data:l,id:u}=e;return x(()=>{if(!a||t)return;let e=new te({data:{...l,label:``},id:u},a);return e.element=s.current??void 0,o.current=e,()=>{e.destroy(),o.current=null}},[l,t,o,s,u,a]),x(()=>{let e=o.current;e&&(e.data={...l,label:n})},[l,o,n]),{ref:c}},ye=(e,t=!1,n=``)=>W({data:E(()=>({type:`tab`}),[]),id:e},t,n),be=(e,t=!1,n=``)=>W({data:E(()=>({tabsetId:e,type:`tabset`}),[e]),id:`grip-${e}`},t,n),xe=e=>{let t=b(B);return{ref:y(n=>{t?.registerTabset(e,n)},[t,e])}},Se=({createTab:e,disabled:t=!1,label:n=``})=>{let r=S(),i=D(e);return x(()=>{i.current=e}),W({data:E(()=>({createTab:()=>i.current(),type:`external`}),[]),id:`external-${r}`},t,n)},Ce=()=>P(b(U)??_e,e=>e.subject),we=()=>P(b(U)??_e,e=>e.intent),Te=e=>N(()=>e),Ee=g(null),G=e=>{let t=b(Ee);if(t===null)throw Error(`dashfoo components must be rendered inside <DashfooLayout> or <Layout.Root>.`);return P(t,e)},De=(e,t)=>e.x>=t.x&&e.x<=t.x+t.width&&e.y>=t.y&&e.y<=t.y+t.height,Oe=(e,t)=>{let n=e.findIndex(e=>t<e.x+e.width/2);return n===-1?e.length:n},ke=(e,t,n)=>{let r=t[n],i=t.at(-1),a=(r?.x??(i?i.x+i.width:e.x))-4/2;return{height:e.height,width:4,x:Math.max(e.x,Math.min(a,e.x+e.width-4)),y:e.y}},Ae=(e,t,n)=>!(e===`grip-${t}`||n.length===1&&n[0]===e),je=new Set,K=(e,t)=>{je.has(e)||(je.add(e),console.warn(`[dashfoo] ${t}`))},Me={boxSizing:`border-box`,pointerEvents:`none`,position:`fixed`,transition:`var(--dashfoo-dock-transition, left 60ms, top 60ms, width 60ms, height 60ms)`,zIndex:9999},Ne=e=>({...Me,background:`var(--dashfoo-dock-fill, oklch(0.556 0 0 / 0.18))`,border:`var(--dashfoo-dock-border-width, 1px) solid var(--dashfoo-dock-border, oklch(0.708 0 0 / 0.75))`,borderRadius:`var(--dashfoo-dock-radius, 6px)`,height:e.height,left:e.x,top:e.y,width:e.width}),Pe=e=>({...Ne(e),borderRadius:`var(--dashfoo-dock-line-radius, 2px)`}),Fe=(e,t)=>[...e.querySelectorAll(`[data-dashfoo="tab-item"]`)].flatMap(e=>e.querySelector(`[data-dashfoo="tab"]`)?.dataset.tabId===t?[]:[e.getBoundingClientRect()]),Ie=({actorRef:e,getTabsetElement:t})=>{let n=A(e,e=>e.context.intent),r=A(e,e=>e.context.subject?.id);if(!n)return null;let i=t(n.targetId);if(!i)return null;if(n.location===`center`){let e=i.querySelector(`[data-dashfoo="tabstrip"]`);if(e)return I(`div`,{"data-dashfoo":`dock-indicator`,style:Pe(ke(e.getBoundingClientRect(),Fe(e,r),n.index??0))})}return I(`div`,{"data-dashfoo":`dock-indicator`,style:Ne(m(i.getBoundingClientRect(),n.location))})},Le={left:0,position:`fixed`,top:0,zIndex:9999},Re=({overlayRef:e,preview:t})=>t?I(`div`,{"data-dashfoo":`drag-preview`,ref:e,style:{...Le,transform:`translate(${t.x}px, ${t.y}px)`},children:t.label}):null,ze=(e,t)=>[...e.querySelectorAll(`[data-dashfoo="tab"]`)].flatMap(e=>e.dataset.tabId===t?[]:[e.getBoundingClientRect()]),Be=(e,t,n,r)=>{let i=t.querySelector(`[data-dashfoo="tabstrip"]`);if(i&&De(n,i.getBoundingClientRect()))return{index:Oe(ze(i,r),n.x),location:`center`,targetId:e};let a=c(n,t.getBoundingClientRect()),o=a.kind===`tab`?`center`:`split-${a.edge}`;return o===`center`&&i?{index:ze(i,r).length,location:o,targetId:e}:{location:o,targetId:e}},q={x:12,y:8},Ve=e=>{let t=e?.data?.label;return typeof t==`string`?t:``},He=e=>typeof e==`function`,Ue=e=>{let t=e.data;if(t?.type===`tabset`)return{id:String(t.tabsetId),kind:`tabset`};if(t?.type===`external`){if(!He(t.createTab))return console.warn(`[dashfoo] external drag source is missing its createTab function`),null;let n;try{n=t.createTab()}catch(e){return console.warn(`[dashfoo] external drag source createTab threw`,e),null}let r=f.safeParse(n);return r.success?{id:String(e.id),kind:`external`,tab:r.data}:(console.warn(`[dashfoo] external drag source returned an invalid tab`,r.error),null)}return{id:String(e.id),kind:`tab`}},We=({children:e,onCommit:t,splitDock:n})=>{let i=k(r),a=b(Ee),[o]=O(()=>new Map),s=D(null),[c,l]=O(null),u=b(V),[d]=O(()=>u?null:me());w(()=>()=>d?.destroy(),[d]);let f=u??d;if(f===null)throw Error(`[dashfoo] DashfooDragProvider unmounted while its layout is still mounted; keep the provider above the layout or remount the layout`);let p=b(U),[m]=O(()=>p??H()),h=S();x(()=>{let e=i.subscribe(e=>{let{intent:t,subject:n}=e.context,r=m.getState();t===null?r.intent!==null&&r.intentOwner===h&&m.setState({intent:null,intentOwner:null}):(!he(r.intent,t)||r.intentOwner!==h)&&m.setState({intent:t,intentOwner:h}),ge(m.getState().subject,n)||m.setState({subject:n})});return()=>{e.unsubscribe()}},[i,h,m]);let g=D(t),_=D(n);x(()=>{g.current=t,_.current=n}),x(()=>{let e=i.on(`COMMIT`,e=>{if(a?.getState().editable===!1)return;let t=g.current??a?.getState().dispatch;if(!t){K(`drag-layer-no-commit`,`Layout.DragLayer has neither an onCommit prop nor a <Layout.Root> above it; drops are ignored`);return}t(e.action)});return()=>{e.unsubscribe()}},[i,a]);let v=y((e,t)=>{t?o.set(e,t):o.delete(e)},[o]),C=y(e=>o.get(e),[o]),T=y(e=>{s.current=e},[]);x(()=>{let e=e=>{for(let[t,n]of o)if(De(e,n.getBoundingClientRect()))return{element:n,id:t}},t=(e,t,n,r)=>{if(a?.getState().editable===!1||!Ae(r,e,[...t.querySelectorAll(`[data-dashfoo="tab"]`)].map(e=>e.dataset.tabId??``)))return null;let i=Be(e,t,n,r);return!(_.current??a?.getState().splitDock??!0)&&i.location.startsWith(`split-`)?{location:`center`,targetId:e}:i},n=e=>{let t=s.current;t&&(t.style.transform=`translate(${e.x+q.x}px, ${e.y+q.y}px)`)},r=e=>{let t=e.operation.source;if(!t)return;let n=Ue(t);if(!n)return;let r=e.operation.position.current;l({label:Ve(t),x:r.x+q.x,y:r.y+q.y}),i.send({subject:n,type:`START`})},c=r=>{let a=r.operation,o=a.position.current;n(o);let s=a.source?String(a.source.id):void 0,c=e(o);i.send({intent:c?t(c.id,c.element,o,s):null,type:`OVER`})},u=n=>{if(l(null),n.canceled){i.send({type:`CANCEL`});return}let r=n.operation,a=r.position.current,o=r.source?String(r.source.id):void 0,s=e(a);s&&i.send({intent:t(s.id,s.element,a,o),type:`OVER`}),i.send({type:`DROP`})},d=f.monitor.addEventListener(`dragstart`,r),p=f.monitor.addEventListener(`dragmove`,c),m=f.monitor.addEventListener(`dragend`,u);return()=>{d(),p(),m()}},[i,a,f,o]);let A=E(()=>({manager:f,registerTabset:v}),[f,v]);return I(B.Provider,{value:A,children:L(U.Provider,{value:m,children:[e,I(Ie,{actorRef:i,getTabsetElement:C}),I(Re,{overlayRef:T,preview:c})]})})},Ge={display:`flex`,height:`100%`,width:`100%`},Ke=({children:e,closableTabs:t=!0,dispatch:n,draggableTabs:r=!0,draggableTabsets:i=!0,editable:a=!0,keepMounted:o=!1,maximizable:s=!0,model:c,renamableTabs:l=!0,renderTab:u,renderTabLabel:d,renderTabsetToolbar:f,resizableSplits:p=!0,rootRef:m,snap:h,style:g,..._})=>{let v=c.global,y={closableTabs:a&&t&&v.tabEnableClose!==!1,dispatch:n,draggableTabs:a&&r&&v.tabEnableDrag!==!1,draggableTabsets:a&&i,editable:a,keepMounted:o,maximizable:s&&v.tabSetEnableMaximize!==!1,maximizedTabsetId:c.maximizedTabsetId,renamableTabs:a&&l&&v.tabEnableRename!==!1,renderTab:u,renderTabLabel:d,renderTabsetToolbar:f,resizableSplits:a&&p&&v.enableSplitResize!==!1,snap:h??v.snap??null,splitDock:v.enableSplitDock!==!1,tabLocation:v.tabLocation??`top`,tabsetMinSize:v.tabSetMinSize??320,tabStripEnabled:v.tabSetEnableTabStrip!==!1},[b]=O(()=>Te(y));T(()=>{b.setState(y)});let x=v.splitterSize===void 0?{...Ge,...g}:{...Ge,"--dashfoo-splitter-size":`${v.splitterSize}px`,...g};return I(Ee.Provider,{value:b,children:I(`div`,{..._,"data-dashfoo":`layout`,ref:m,style:x,children:e})})},J=(e,t)=>`dashfoo-tab-${e}-${t}`,qe=e=>`dashfoo-panel-${e}`,Je=(e,t,n)=>e?.querySelector(`#${CSS.escape(J(t,n))}`)??null,Ye=e=>N((t,n)=>({...e,cancelRename:()=>t({editingTabId:null}),closeTab:e=>{t({restoreFocus:!0}),n().dispatch({tabId:e,type:`deleteTab`})},commitRename:(e,r)=>{t({editingTabId:null});let{node:i,renameTab:a}=n(),o=r.trim(),s=i.children.find(t=>t.id===e)?.name;o&&o!==s&&a(e,o)},editingTabId:null,overflowItems:[],registerRenameInput:()=>(t(e=>({renameInputCount:e.renameInputCount+1})),()=>t(e=>({renameInputCount:e.renameInputCount-1}))),registerTablist:e=>{if(e){let r=n().tablistElement;r&&r!==e&&K(`duplicate-tablist-${n().node.id}`,`more than one <Tabset.Tablist> under the same <Tabset.Root>; the last one wins for keyboard focus and overflow`),t({tablistElement:e});return}t({tablistElement:null})},renameInputCount:0,renameTab:(e,t)=>n().dispatch({name:t,tabId:e,type:`renameTab`}),restoreFocus:!1,selectOverflowTab:e=>{let{dispatch:t,node:r,tablistElement:i}=n(),a=r.children.findIndex(t=>t.id===e);a!==-1&&(t({index:a,tabsetId:r.id,type:`selectTab`}),Je(i,r.id,e)?.scrollIntoView({block:`nearest`,inline:`nearest`}))},selectTab:(e,t)=>{let{dispatch:r,node:i,tablistElement:a}=n();if(r({index:e,tabsetId:i.id,type:`selectTab`}),t?.focus){let t=i.children[e]?.id;t&&Je(a,i.id,t)?.focus()}},startEditing:e=>{let{node:r,renameInputCount:i,tabsRenamable:a}=n(),o=r.children.find(t=>t.id===e);if(!(!a||o?.enableRename===!1)){if(i===0){K(`missing-rename-input-${r.id}`,`startEditing needs a <Tabset.RenameInput> in the composition; ignoring`);return}t({editingTabId:e})}},tablistElement:null,toggleMaximize:()=>{let{dispatch:e,isMaximized:t,node:r}=n();e({tabsetId:t?null:r.id,type:`setMaximizedTabset`})}})),Xe=g(null),Y=e=>{let t=b(Xe);if(t===null)throw Error(`dashfoo Tabset parts must be rendered inside <Tabset.Root>.`);return P(t,e)},Ze=g(null),X=()=>{let e=b(Ze);if(e===null)throw Error(`dashfoo tab parts must be rendered inside <Tabset.Tab>.`);return e},Qe={flex:1,minHeight:0,overflow:`auto`},$e=({render:e,tab:t})=>{let n=G(e=>e.renderTab);return e?e(t):n(t)},et=({children:e,style:t,...n})=>{let r=Y(e=>e.node),i=Y(e=>e.visualSelected),a=G(e=>e.keepMounted),o={...Qe,...t};if(a&&r.children.length>0)return r.children.map((t,a)=>_(`div`,{...n,"aria-labelledby":J(r.id,t.id),"data-dashfoo":`tabcontent`,hidden:a!==i||void 0,id:a===i?qe(r.id):void 0,key:t.id,role:a===i?`tabpanel`:void 0,style:o,tabIndex:a===i?0:void 0},I($e,{render:e,tab:t})));let s=r.children[i];return s?I(`div`,{...n,"aria-labelledby":J(r.id,s.id),"data-dashfoo":`tabcontent`,id:qe(r.id),role:`tabpanel`,style:o,tabIndex:0,children:I($e,{render:e,tab:s})}):I(`div`,{...n,"data-dashfoo":`tabcontent`,style:o})},tt=()=>L(`svg`,{"aria-hidden":`true`,fill:`currentColor`,height:`10`,viewBox:`0 0 10 10`,width:`10`,children:[I(`circle`,{cx:`2`,cy:`5`,r:`1`}),I(`circle`,{cx:`5`,cy:`5`,r:`1`}),I(`circle`,{cx:`8`,cy:`5`,r:`1`})]}),nt={position:`absolute`,right:0,top:`100%`,zIndex:10},rt=({items:e,onSelect:t})=>{let[n,r]=O(!1),[i,a]=O(0),o=D(null),s=D(null),c=D([]);x(()=>{if(!n)return;let e=e=>{e.target instanceof Node&&!o.current?.contains(e.target)&&r(!1)};return document.addEventListener(`pointerdown`,e),()=>{document.removeEventListener(`pointerdown`,e)}},[n]),x(()=>{n&&c.current[0]?.focus()},[n]);let l=()=>{r(!1),s.current?.focus()},u=e=>{a(e),c.current[e]?.focus()},d=()=>{a(0),r(e=>!e)},f=e=>{t(e),l()};return L(`div`,{"data-dashfoo":`tab-overflow-root`,ref:o,style:{position:`relative`},children:[I(`button`,{"aria-expanded":n,"aria-haspopup":`menu`,"aria-label":`More tabs`,"data-dashfoo":`tab-overflow`,onClick:d,ref:s,type:`button`,children:I(tt,{})}),n?I(`div`,{"data-dashfoo":`tab-overflow-menu`,onBlur:e=>{e.relatedTarget instanceof Node&&o.current?.contains(e.relatedTarget)||r(!1)},onKeyDown:t=>{let n=e.length-1;switch(t.key){case`ArrowDown`:t.preventDefault(),u(i>=n?0:i+1);break;case`ArrowUp`:t.preventDefault(),u(i<=0?n:i-1);break;case`Home`:t.preventDefault(),u(0);break;case`End`:t.preventDefault(),u(n);break;case`Escape`:t.preventDefault(),l();break;default:break}},role:`menu`,style:nt,tabIndex:-1,children:e.map((e,t)=>I(`button`,{"data-dashfoo":`tab-overflow-item`,onClick:()=>f(e.id),ref:e=>{c.current[t]=e},role:`menuitem`,tabIndex:t===i?0:-1,type:`button`,children:e.name},e.id))}):null]})},it=()=>{let e=Y(e=>e.overflowItems),t=Y(e=>e.selectOverflowTab);return e.length===0?null:I(rt,{items:e,onSelect:t})},at=e=>{let t=e.getBoundingClientRect();return[...e.querySelectorAll(`[data-dashfoo="tab"]`)].flatMap(e=>{let n=e.getBoundingClientRect();return(n.right>t.right+1||n.left<t.left-1)&&e.dataset.tabId?[e.dataset.tabId]:[]})},ot=(e,t)=>{let[n,r]=O([]);return x(()=>{let t=()=>{r(t=>{let n=e?at(e):[];return n.length===0&&t.length===0?t:n})};if(t(),!e)return;let n=new ResizeObserver(t);return n.observe(e),e.addEventListener(`scroll`,t,{passive:!0}),()=>{n.disconnect(),e.removeEventListener(`scroll`,t)}},[e,t]),n},st=(e,t)=>t+1<e?t+1:t-1,ct={display:`flex`,flexDirection:`column`,height:`100%`,minHeight:0,minWidth:0,width:`100%`},lt=({children:e,node:t,ref:n,style:r,...i})=>{let a=G(e=>e.closableTabs),o=G(e=>e.dispatch),s=G(e=>e.maximizable),c=G(e=>e.maximizedTabsetId),l=G(e=>e.renamableTabs),u=G(e=>e.tabLocation),{ref:d}=xe(t.id),f=Ce(),p=D(null),m=c===t.id,h=s&&t.enableMaximize!==!1,g=a&&t.enableClose!==!1,_=l,v=f?.kind===`tab`?t.children.findIndex(e=>e.id===f.id):-1,y=v!==-1&&v===t.selected?st(t.children.length,v):t.selected,b=t.children[y],S=f?.kind===`tabset`&&f.id===t.id,C={activeTab:b,dispatch:o,isMaximized:m,node:t,showMaximize:h,tabsClosable:g,tabsRenamable:_,visualSelected:y},[w]=O(()=>Ye(C));T(()=>{w.setState(C)});let k=ot(P(w,e=>e.tablistElement),t.children.map(e=>`${e.id}:${e.name}`).join(`|`)),A=E(()=>{let e=new Map(t.children.map(e=>[e.id,e.name]));return k.map(t=>({id:t,name:e.get(t)??t}))},[k,t.children]);return T(()=>{w.setState({overflowItems:A})},[A,w]),x(()=>{if(!w.getState().restoreFocus)return;w.setState({restoreFocus:!1});let e=t.children[t.selected]?.id;e?p.current?.querySelector(`#${CSS.escape(J(t.id,e))}`)?.focus():p.current?.focus()},[t.children,t.selected,t.id,w]),I(Xe.Provider,{value:w,children:I(`div`,{...i,"data-dashfoo":`tabset`,"data-dragging-source":S||void 0,"data-tab-location":u,ref:e=>{d(e),p.current=e,typeof n==`function`?n(e):n&&(n.current=e)},style:{...ct,...r},tabIndex:-1,children:e})})},ut=(e,t)=>{typeof e==`function`?e(t):e&&(e.current=t)},Z=(...e)=>t=>{for(let n of e)ut(n,t)},dt=({children:e,ref:t,tab:n,...r})=>{let i=b(Xe),a=Y(e=>e.node),o=Y(e=>e.editingTabId===n.id),s=Ce(),c=s?.kind===`tab`&&s.id===n.id,l=D(null),u=D(!1),d=a.children.findIndex(e=>e.id===n.id);x(()=>{i?.getState().node.children.some(e=>e.id===n.id)===!1&&K(`orphan-tab-${n.id}`,`<Tabset.Tab> for "${n.id}" is not a child of its Tabset.Root's node; it renders but can never be selected`)},[d===-1,i,n.id]),x(()=>{u.current&&!o&&l.current?.querySelector(`[data-dashfoo="tab"]`)?.focus(),u.current=o},[o]);let f=E(()=>({index:d,tab:n}),[d,n]),p=E(()=>Z(l,t),[t]);return I(Ze.Provider,{value:f,children:I(`span`,{...r,"data-dashfoo":`tab-item`,"data-dragging":c||void 0,ref:p,children:e})})},ft=({children:e,onClick:t,onDoubleClick:n,ref:r,...i})=>{let{index:a,tab:o}=X(),s=Y(e=>e.node),c=Y(e=>e.editingTabId===o.id),l=Y(e=>e.selectTab),u=Y(e=>e.startEditing),d=Y(e=>e.tabsRenamable),f=Y(e=>e.visualSelected),p=G(e=>e.draggableTabs),m=G(e=>e.renderTabLabel),{ref:h}=ye(o.id,!p||o.enableDrag===!1,o.name),g=E(()=>Z(h,r),[h,r]);if(c)return null;let _=a===f,v=d&&o.enableRename!==!1,y=e=>{t?.(e),l(a)},b=e=>{n?.(e),v&&u(o.id)};return I(`button`,{"aria-label":m?o.name:void 0,...i,"aria-controls":qe(s.id),"aria-selected":_,"data-dashfoo":`tab`,"data-tab-id":o.id,id:J(s.id,o.id),onClick:y,onDoubleClick:b,ref:g,role:`tab`,tabIndex:_?0:-1,type:`button`,children:e??(m?m(o):o.name)})},pt={pointerEvents:`none`},Q=({children:e})=>I(`svg`,{"aria-hidden":`true`,fill:`none`,height:`12`,stroke:`currentColor`,strokeLinecap:`round`,strokeLinejoin:`round`,strokeWidth:`2`,style:pt,viewBox:`0 0 24 24`,width:`12`,children:e}),mt=()=>L(Q,{children:[I(`path`,{d:`M18 6 6 18`}),I(`path`,{d:`m6 6 12 12`})]}),ht=()=>L(Q,{children:[I(`circle`,{cx:`12`,cy:`5`,r:`1`}),I(`circle`,{cx:`19`,cy:`5`,r:`1`}),I(`circle`,{cx:`5`,cy:`5`,r:`1`}),I(`circle`,{cx:`12`,cy:`12`,r:`1`}),I(`circle`,{cx:`19`,cy:`12`,r:`1`}),I(`circle`,{cx:`5`,cy:`12`,r:`1`}),I(`circle`,{cx:`12`,cy:`19`,r:`1`}),I(`circle`,{cx:`19`,cy:`19`,r:`1`}),I(`circle`,{cx:`5`,cy:`19`,r:`1`})]}),gt=({maximized:e})=>e?L(Q,{children:[I(`path`,{d:`m14 10 7-7`}),I(`path`,{d:`M20 10h-6V4`}),I(`path`,{d:`m3 21 7-7`}),I(`path`,{d:`M4 14h6v6`})]}):L(Q,{children:[I(`path`,{d:`M15 3h6v6`}),I(`path`,{d:`m21 3-7 7`}),I(`path`,{d:`m3 21 7-7`}),I(`path`,{d:`M9 21H3v-6`})]}),_t=({defaultValue:e,onBlur:t,onKeyDown:n,ref:r,...i})=>{let{tab:a}=X(),o=Y(e=>e.cancelRename),s=Y(e=>e.commitRename),c=D(null),l=D(!1),u=E(()=>Z(c,r),[r]);x(()=>{c.current?.focus(),c.current?.select()},[]);let d=e=>{n?.(e),e.key===`Enter`?(l.current=!0,s(a.id,e.currentTarget.value)):e.key===`Escape`&&(l.current=!0,o())},f=e=>{t?.(e),!l.current&&(l.current=!0,s(a.id,e.currentTarget.value))};return I(`input`,{"aria-label":`Rename ${a.name}`,...i,"data-dashfoo":`tab-rename`,defaultValue:e??a.name,onBlur:f,onKeyDown:d,ref:u,type:`text`})},vt=e=>{let{tab:t}=X(),n=Y(e=>e.editingTabId===t.id),r=Y(e=>e.registerRenameInput);return x(()=>r(),[r]),n?I(_t,{...e}):null},yt=({children:e,onClick:t,...n})=>{let{index:r,tab:i}=X(),a=Y(e=>e.closeTab),o=Y(e=>e.editingTabId===i.id),s=Y(e=>e.tabsClosable),c=Y(e=>e.visualSelected);if(!(s&&i.enableClose!==!1)||o)return null;let l=e=>{t?.(e),e.stopPropagation(),a(i.id)};return I(`button`,{"aria-label":`Close ${i.name}`,...n,"data-dashfoo":`tab-close`,onClick:l,tabIndex:r===c?0:-1,type:`button`,children:e??I(mt,{})})},bt={display:`flex`,flexShrink:0},xt={display:`flex`,minWidth:0,overflowX:`auto`},St=({style:e,...t})=>I(`div`,{...t,"data-dashfoo":`tabstrip`,style:{...bt,...e}}),Ct=({onKeyDown:e,ref:t,style:n,...r})=>{let i=Y(e=>e.node),a=Y(e=>e.registerTablist),o=Y(e=>e.selectTab),s=t=>{if(e?.(t),t.defaultPrevented||!(t.target instanceof HTMLElement)||!t.target.closest(`[role="tab"]`))return;let n=i.children.length;if(n===0)return;let r={ArrowLeft:(i.selected-1+n)%n,ArrowRight:(i.selected+1)%n,End:n-1,Home:0}[t.key];r!==void 0&&(t.preventDefault(),o(r,{focus:!0}))},c=E(()=>Z(a,t),[a,t]);return I(`div`,{"aria-label":i.name??`Tabs`,...r,"aria-orientation":`horizontal`,"data-dashfoo":`tablist`,onKeyDown:s,ref:c,role:`tablist`,style:{...xt,...n},tabIndex:-1})},wt={alignItems:`center`,display:`flex`,flexShrink:0,marginInlineStart:`auto`},Tt=({style:e,...t})=>I(`div`,{...t,"data-dashfoo":`tabset-toolbar`,style:{...wt,...e}}),Et=({children:e,ref:t,...n})=>{let r=Y(e=>e.activeTab?.name??``),i=Y(e=>e.isMaximized),a=Y(e=>e.node),o=!G(e=>e.draggableTabsets)||i,{ref:s}=be(a.id,o,r),c=E(()=>Z(s,t),[s,t]);return o?null:I(`button`,{"aria-label":`Move tabset`,...n,"data-dashfoo":`tabset-grip`,ref:c,type:`button`,children:e??I(ht,{})})},Dt=({children:e,onClick:t,...n})=>{let r=Y(e=>e.isMaximized),i=Y(e=>e.showMaximize),a=Y(e=>e.toggleMaximize);if(!i)return null;let o=e=>{t?.(e),a()};return I(`button`,{"aria-label":r?`Restore`:`Maximize`,...n,"aria-pressed":r,"data-dashfoo":`tabset-maximize`,onClick:o,type:`button`,children:e??I(gt,{maximized:r})})},Ot=I(et,{}),kt=()=>{let e=G(e=>e.draggableTabsets),t=G(e=>e.renderTabsetToolbar),n=G(e=>e.tabLocation),r=G(e=>e.tabStripEnabled),i=Y(e=>e.isMaximized),a=Y(e=>e.node),o=Y(e=>e.overflowItems.length),s=Y(e=>e.showMaximize)||t!==void 0||o>0||e&&!i,c=r?L(St,{children:[I(Ct,{children:a.children.map(e=>L(dt,{tab:e,children:[I(ft,{}),I(vt,{}),I(yt,{})]},e.id))}),s?L(Tt,{children:[I(it,{}),I(Et,{}),t?.(a),I(Dt,{})]}):null]}):null;return n===`bottom`?L(F,{children:[Ot,c]}):L(F,{children:[c,Ot]})},At=({node:e})=>I(lt,{node:e,children:I(kt,{})}),jt=e=>`${e.value}${e.unit}`,Mt=e=>e?.unit===`px`?e.value:void 0,Nt={display:`flex`,flex:1,minHeight:0,minWidth:0},Pt=.01,Ft=(e,t)=>e.reduce((e,n)=>(e[n.id]=(n.weight??1)/t*100,e),{}),It=(e,t)=>t.map(t=>e[t.id]??0),Lt=(e,t)=>t.reduce((t,n,r)=>(t[n.id]=e[r]??0,t),{}),Rt=(e,t)=>{let n=Object.keys(e),r=Object.keys(t);return n.length===r.length?r.every(n=>Math.abs((e[n]??NaN)-t[n])<=Pt):!1},zt=(e,t,n)=>{let r=Mt(e.min);if(r!==void 0)return r;if(e.min!==void 0)return;if(e.type===`tabset`)return n;let i=[];for(let r of e.children){let e=zt(r,t,n);if(e===void 0)return;i.push(e)}if(i.length!==0)return e.orientation===t?i.reduce((e,t)=>e+t,0):Math.max(...i)},Bt=({node:e,renderTabset:t})=>{let n=G(e=>e.dispatch),r=G(e=>e.resizableSplits),i=G(e=>e.tabsetMinSize),a=G(e=>e.snap),o=e.snap??a,s=l(o),c=e.orientation===`row`?`horizontal`:`vertical`,d=e.children.reduce((e,t)=>e+(t.weight??1),0),f=E(()=>Ft(e.children,d),[e.children,d]),p=D(!1),m=D(null),g=D(null),_=D(!1),v=D(null),y=D(!1),b=D(null),[x,S]=O(null),C=e=>{e!==b.current&&(b.current=e,S(e))},w=e=>{let t=g.current;t&&(e?t.dataset.dashfooSnapping=`true`:delete t.dataset.dashfooSnapping)};return T(()=>{let e=m.current;if(!e)return;let t=e.getLayout();if(!(Object.keys(t).length===Object.keys(f).length&&Object.keys(f).every(e=>e in t))||Rt(t,f))return;_.current=!0,e.setLayout(f);let n=requestAnimationFrame(()=>{_.current=!1});return()=>{cancelAnimationFrame(n),_.current=!1}},[f]),I(re,{"data-dashfoo":`row`,disabled:!r,elementRef:g,groupRef:m,onLayoutChange:s?t=>{if(y.current||_.current||!r||o===null||!s)return;let n=v.current;if(n===null)return;let{sizes:i,snapped:a}=u(It(t,e.children),n,o);if(C(a?n:null),!a){w(!1);return}w(!0);let c=m.current,l=Lt(i,e.children);!c||Rt(t,l)||(y.current=!0,c.setLayout(l),y.current=!1)}:void 0,onLayoutChanged:t=>{if(!p.current){p.current=!0;return}if(_.current)return;let i=v.current;if(v.current=null,C(null),w(!1),!r)return;let a=e.children.map(e=>t[e.id]??e.weight??1);i!==null&&o!==null&&s&&(a=u(a,i,o).sizes),a.some((t,n)=>Math.abs(t-(e.children[n]?.weight??1))>Pt)&&n({rowId:e.id,type:`adjustSplit`,weights:a})},orientation:c,style:Nt,children:e.children.map((n,a)=>{let o=(n.weight??1)/d*100,c=n.min?jt(n.min):void 0;if(c===void 0){let t=zt(n,e.orientation,i);c=t===void 0?void 0:`${t}px`}let l=n.max?jt(n.max):void 0;return L(h,{children:[a>0?I(ae,{"data-dashfoo":`splitter`,"data-dashfoo-snapped":x===a-1?`true`:void 0,disabled:!r,onPointerDown:s&&r?()=>{v.current=a-1}:void 0}):null,I(ie,{defaultSize:`${o}%`,id:n.id,maxSize:l,minSize:c,children:n.type===`row`?I(Bt,{node:n,renderTabset:t}):t?.(n)??I(At,{node:n})})]},n.id)})},e.id)},$={DragLayer:We,Root:Ke,Rows:Bt,Tabset:At},Vt=(e,t)=>e===void 0||!t?null:typeof e==`string`?{debounceMs:300,key:e,storage:R}:{debounceMs:e.debounceMs??300,key:e.key,storage:e.storage??R},Ht=new Set,Ut=v((e,t)=>{let{closableTabs:n=!0,components:r,defaultModel:a,draggableTabs:o=!0,draggableTabsets:s=!0,editable:c=!0,factory:l,keepMounted:u=!1,maximizable:f=!0,model:p,onAction:m,onActiveTabsetChange:h,onMaximizedTabsetChange:g,onModelChange:_,persist:v,renamableTabs:b=!0,renderTabLabel:x,renderTabsetToolbar:S,resizableSplits:w=!0,responsive:T,snap:O}=e,k=se(E(()=>Vt(v,a!==void 0),[v,a]),a),A=y((e,t)=>{k.save(e),_?.(e,t)},[_,k]),j=fe({defaultModel:k.initialModel??a,model:p,onAction:m,onActiveTabsetChange:h,onMaximizedTabsetChange:g,onModelChange:A});C(t,()=>({addTab:(e,t)=>j.dispatch({index:t.index,location:t.location??`center`,tab:e,targetId:t.targetId,type:`addNode`}),canRedo:j.canRedo,canUndo:j.canUndo,closeTab:e=>j.dispatch({tabId:e,type:`deleteTab`}),dispatch:j.dispatch,getModel:()=>j.model,maximizeTabset:e=>j.dispatch({tabsetId:e,type:`setMaximizedTabset`}),redo:j.redo,renameTab:(e,t)=>j.dispatch({name:t,tabId:e,type:`renameTab`}),resetLayout:()=>{k.clear(),a!==void 0&&j.setModel(a)},selectTab:(e,t)=>j.dispatch({index:t,tabsetId:e,type:`selectTab`}),undo:j.undo}),[a,k,j]);let ee=y(e=>{if(l)return l(e);let t=r?.[e.component];return t?I(t,{node:e}):(r&&!Ht.has(e.component)&&(Ht.add(e.component),console.warn(`[dashfoo] no component registered for "${e.component}"`)),null)},[r,l]),[te,ne]=z(),M=T!==void 0&&ne<=T.maxWidth,N=E(()=>M?d(j.model,T?.orientation):j.model,[M,T?.orientation,j.model]),P=D(M);P.current=M;let F=y(e=>{P.current&&e.type===`adjustSplit`||j.dispatch(e)},[j]),L=N.maximizedTabsetId?i(N,N.maximizedTabsetId):void 0;return I($.Root,{closableTabs:n,dispatch:F,draggableTabs:M?!1:o,draggableTabsets:M?!1:s,editable:c,keepMounted:u,maximizable:f,model:N,renamableTabs:b,renderTab:ee,renderTabLabel:x,renderTabsetToolbar:S,resizableSplits:M?!1:w,rootRef:te,snap:O,children:I($.DragLayer,{children:L?I($.Tabset,{node:L}):I($.Rows,{node:N.layout})})})});Ut.displayName=`DashfooLayout`;const Wt=({children:e})=>{let[t]=O(me);w(()=>()=>t.destroy(),[t]);let[n]=O(H);return I(V.Provider,{value:t,children:I(U.Provider,{value:n,children:e})})},Gt={Badge:e=>I(`span`,{...e,"data-dashfoo":`panel-badge`}),Body:e=>I(`div`,{...e,"data-dashfoo":`panel-body`}),Header:e=>I(`div`,{...e,"data-dashfoo":`panel-header`}),Icon:e=>I(`span`,{...e,"data-dashfoo":`panel-icon`}),Root:e=>I(`div`,{...e,"data-dashfoo":`panel`}),Title:e=>I(`span`,{...e,"data-dashfoo":`panel-title`})},Kt={CloseButton:yt,Content:et,Grip:Et,MaximizeButton:Dt,OverflowMenu:it,RenameInput:vt,Root:lt,Tab:dt,Tablist:Ct,TabStrip:St,Toolbar:Tt,Trigger:ft};export{Wt as DashfooDragProvider,Ut as DashfooLayout,$ as Layout,Gt as Panel,Kt as Tabset,ue as activeBreakpoint,R as localStorageAdapter,le as matchBreakpoint,oe as memoryStorageAdapter,z as useContainerWidth,fe as useDashfooStore,Ce as useDragSubject,we as useDropIntent,Se as useExternalTabSource,G as useLayout,se as usePersistence,de as useResponsiveModel,X as useTab,Y as useTabset};
|
|
9
9
|
//# sourceMappingURL=index.js.map
|