@dashfoo/react 0.2.0 → 0.3.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 CHANGED
@@ -59,24 +59,27 @@ 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 | 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
- | `closableTabs` | `boolean` | `true` | Show the per-tab close control. |
76
- | `renamableTabs` | `boolean` | `true` | Allow double-click inline rename. |
77
- | `maximizable` | `boolean` | `true` | Show the tabset maximize/restore control. |
78
- | `draggableTabsets` | `boolean` | `true` | Show the grip that drags a whole tabset. |
79
- | `keepMounted` | `boolean` | `false` | Keep inactive tab panels mounted (hidden) so their state survives a tab switch. |
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. |
80
83
 
81
84
  You must pass either `model` or `defaultModel`. Passing neither throws.
82
85
 
@@ -175,19 +178,22 @@ with the right role and ARIA wiring, ready for you to style.
175
178
 
176
179
  ### Per-node enable flags
177
180
 
178
- The three top-level chrome props are global gates. Individual nodes can opt out
181
+ The top-level chrome props are layout-wide gates. Individual nodes can opt out
179
182
  through optional boolean fields in the model (a flag defaults to enabled unless
180
- explicitly `false`). A control shows only when both the global prop and the
181
- node's flag allow it.
182
-
183
- | Field | On node | Disables |
184
- | ----------------- | ------- | ------------------------------------------------ |
185
- | `enableClose` | tab | the close control for that tab |
186
- | `enableClose` | tabset | closing for every tab in the tabset |
187
- | `enableRename` | tab | double-click rename for that tab |
188
- | `enableDrag` | tab | dragging that tab |
189
- | `enableMaximize` | tabset | the maximize control for that tabset |
190
- | `enableSplitDock` | global | splitting a tabset on drop (drops stack instead) |
183
+ explicitly `false`). A control shows only when the `editable` umbrella, the
184
+ chrome prop, the model global, and the node's flag all allow it (`maximizable`
185
+ ignores `editable` — maximize is view state, not a structural edit).
186
+
187
+ | Field | On node | Disables |
188
+ | ------------------- | ------- | ------------------------------------------------ |
189
+ | `enableClose` | tab | the close control for that tab |
190
+ | `enableClose` | tabset | closing for every tab in the tabset |
191
+ | `enableRename` | tab | double-click rename for that tab |
192
+ | `enableDrag` | tab | dragging that tab |
193
+ | `enableMaximize` | tabset | the maximize control for that tabset |
194
+ | `tabEnableDrag` | global | tree-wide default behind `tab.enableDrag` |
195
+ | `enableSplitDock` | global | splitting a tabset on drop (drops stack instead) |
196
+ | `enableSplitResize` | global | dragging the splitters (gutters keep their size) |
191
197
 
192
198
  ```ts
193
199
  { id: "logs", type: "tab", name: "Logs", component: "logs", enableClose: false }
@@ -345,7 +351,7 @@ you.
345
351
  | `tabset-grip` | `button` | Drags the whole tabset. `aria-label="Move tabset"`; shown when `draggableTabsets` is on and the tabset is not maximized. |
346
352
  | `tabset-maximize` | `button` | Maximize/restore toggle. `aria-pressed` reflects state. |
347
353
  | `tabcontent` | `div` | `role="tabpanel"`, the active tab's content (or empty when none). |
348
- | `dock-indicator` | `div` | The drag preview overlay (ghost tab or zone pane). `pointer-events: none`. |
354
+ | `dock-indicator` | `div` | The drag preview overlay (insertion line or zone pane). `pointer-events: none`. |
349
355
  | `drag-preview` | `div` | The chip that follows the pointer during a drag, showing the dragged label. |
350
356
  | `separator` | rrp `Separator` | rrp emits `data-separator` with `aria-orientation`; style splitters here. |
351
357
 
@@ -366,7 +372,7 @@ to theme the drag preview without touching layout.
366
372
  | `--dashfoo-dock-border` | indicator border color | `oklch(0.708 0 0 / 0.75)` |
367
373
  | `--dashfoo-dock-border-width` | indicator border width | `1px` |
368
374
  | `--dashfoo-dock-radius` | indicator corner radius | `6px` |
369
- | `--dashfoo-dock-tab-radius` | insertion-ghost radius | `var(--dashfoo-dock-radius, 6px)` |
375
+ | `--dashfoo-dock-line-radius` | insertion-line radius | `2px` |
370
376
  | `--dashfoo-dock-transition` | indicator move animation | `left 60ms, top 60ms, width 60ms, height 60ms` |
371
377
 
372
378
  Set `--dashfoo-dock-transition: none` to disable the indicator animation.
@@ -405,6 +411,16 @@ const { index, tab } = useTab(); // which tab a part belongs to; throws outside
405
411
  tabset being dragged) or `null` — including outside a drag layer — for
406
412
  drag-aware styling in custom parts.
407
413
 
414
+ `useDropIntent()` returns the live drop intent (`{ targetId, location, index? }`
415
+ — where the drag would land if dropped right now) or `null` when nothing is
416
+ dragging or the pointer is over no valid target (empty space, a non-editable
417
+ layout, or a no-op drop the library suppresses). Together with
418
+ `dockZonePolygons` from `@dashfoo/core` it supports consumer-rendered drop
419
+ indicators and drop-zone visualizations alongside the built-in indicator. Both
420
+ hooks work anywhere under a layout; under a `DashfooDragProvider` they work
421
+ anywhere under the provider (the provider hosts the drag store, so widget lists
422
+ and overlays outside the layout observe the same drag).
423
+
408
424
  ## Build your own layout
409
425
 
410
426
  `DashfooLayout` is a thin assembly of exported primitives — you can compose the
@@ -525,9 +541,10 @@ type TabsetState;
525
541
  useTab; // { tab, index } identity (throws outside Tabset.Tab)
526
542
  type TabContextValue;
527
543
  useDragSubject; // the live drag subject, or null
544
+ useDropIntent; // where the drag would land if dropped right now, or null
528
545
 
529
546
  // External drag sources
530
- DashfooDragProvider; // shares one drag manager between a layout and outside sources
547
+ DashfooDragProvider; // shares one drag manager + drag store between a layout and outside sources
531
548
  useExternalTabSource;
532
549
  type ExternalTabSourceOptions;
533
550
 
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { Action, Dashfoo, DockLocation, DragSubject, RowNode, TabNode, TabsetNode } from "@dashfoo/core";
1
+ import { Action, Dashfoo, DockLocation, DragSubject, DropIntent, RowNode, TabNode, TabsetNode } from "@dashfoo/core";
2
2
  import { ComponentProps, ComponentType, ReactNode } from "react";
3
3
  import { DragDropManager } from "@dnd-kit/dom";
4
4
  //#region src/hooks/persistence.d.ts
@@ -52,7 +52,9 @@ type DashfooLayoutProps = {
52
52
  closableTabs?: boolean;
53
53
  components?: Record<string, TabComponent>;
54
54
  defaultModel?: Dashfoo;
55
+ draggableTabs?: boolean;
55
56
  draggableTabsets?: boolean;
57
+ editable?: boolean;
56
58
  factory?: (tab: TabNode) => ReactNode;
57
59
  keepMounted?: boolean;
58
60
  maximizable?: boolean;
@@ -65,6 +67,7 @@ type DashfooLayoutProps = {
65
67
  renamableTabs?: boolean;
66
68
  renderTabLabel?: (tab: TabNode) => ReactNode;
67
69
  renderTabsetToolbar?: (tabset: TabsetNode) => ReactNode;
70
+ resizableSplits?: boolean;
68
71
  };
69
72
  declare const DashfooLayout: import("react").ForwardRefExoticComponent<DashfooLayoutProps & import("react").RefAttributes<DashfooHandle>>;
70
73
  //#endregion
@@ -89,6 +92,7 @@ declare const useExternalTabSource: ({
89
92
  ref: (element: Element | null) => void;
90
93
  };
91
94
  declare const useDragSubject: () => DragSubject | null;
95
+ declare const useDropIntent: () => DropIntent | null;
92
96
  //#endregion
93
97
  //#region src/components/drag-adapter.d.ts
94
98
  type DragProviderProps = {
@@ -102,7 +106,9 @@ type LayoutRootProps = Omit<ComponentProps<"div">, "children"> & {
102
106
  children: ReactNode;
103
107
  closableTabs?: boolean;
104
108
  dispatch: (action: Action) => void;
109
+ draggableTabs?: boolean;
105
110
  draggableTabsets?: boolean;
111
+ editable?: boolean;
106
112
  keepMounted?: boolean;
107
113
  maximizable?: boolean;
108
114
  model: Dashfoo;
@@ -110,6 +116,7 @@ type LayoutRootProps = Omit<ComponentProps<"div">, "children"> & {
110
116
  renderTab: (tab: TabNode) => ReactNode;
111
117
  renderTabLabel?: (tab: TabNode) => ReactNode;
112
118
  renderTabsetToolbar?: (tabset: TabsetNode) => ReactNode;
119
+ resizableSplits?: boolean;
113
120
  };
114
121
  //#endregion
115
122
  //#region src/components/row-view.d.ts
@@ -134,7 +141,9 @@ declare const Layout: {
134
141
  children,
135
142
  closableTabs,
136
143
  dispatch,
144
+ draggableTabs,
137
145
  draggableTabsets,
146
+ editable,
138
147
  keepMounted,
139
148
  maximizable,
140
149
  model,
@@ -142,6 +151,7 @@ declare const Layout: {
142
151
  renderTab,
143
152
  renderTabLabel,
144
153
  renderTabsetToolbar,
154
+ resizableSplits,
145
155
  style,
146
156
  ...props
147
157
  }: LayoutRootProps) => import("react").ReactNode;
@@ -304,7 +314,9 @@ declare const useTab: () => TabContextValue;
304
314
  type LayoutState = {
305
315
  closableTabs: boolean;
306
316
  dispatch: (action: Action) => void;
317
+ draggableTabs: boolean;
307
318
  draggableTabsets: boolean;
319
+ editable: boolean;
308
320
  keepMounted: boolean;
309
321
  maximizable: boolean;
310
322
  maximizedTabsetId: string | undefined;
@@ -312,6 +324,7 @@ type LayoutState = {
312
324
  renderTab: (tab: TabNode) => ReactNode;
313
325
  renderTabLabel: ((tab: TabNode) => ReactNode) | undefined;
314
326
  renderTabsetToolbar: ((tabset: TabsetNode) => ReactNode) | undefined;
327
+ resizableSplits: boolean;
315
328
  splitDock: boolean;
316
329
  tabLocation: "bottom" | "top";
317
330
  tabsetMinSize: number;
@@ -364,5 +377,5 @@ type UseDashfooStoreOptions = {
364
377
  };
365
378
  declare const useDashfooStore: (options: UseDashfooStoreOptions) => DashfooStore;
366
379
  //#endregion
367
- 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, useExternalTabSource, useLayout, usePersistence, useResponsiveModel, useTab, useTabset };
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 };
368
381
  //# sourceMappingURL=index.d.ts.map
@@ -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":"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"}
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;;;KCtEE,YAAA;EAA0B,UAAA;EAAqB,GAAA;EAAa,OAAA,GAAU,cAAc;AAAA;AAAA,KAmBpF,YAAA,GAAe,aAAa;EAAG,IAAA,EAAM,OAAA;AAAA;AAAA,KAOrC,aAAA;EACH,MAAA,GACE,GAAA,EAAK,OAAA,EACL,MAAA;IAAU,KAAA;IAAgB,QAAA,GAAW,YAAA;IAAc,QAAA;EAAA;EAErD,OAAA;EACA,OAAA;EACA,QAAA,GAAW,KAAA;EACX,QAAA,GAAW,MAAA,EAAQ,MAAA;EACnB,QAAA,QAAgB,OAAA;EAChB,cAAA,GAAiB,QAAA;EACjB,IAAA;EACA,SAAA,GAAY,KAAA,UAAe,IAAA;EAG3B,WAAA;EACA,SAAA,GAAY,QAAA,UAAkB,KAAA;EAC9B,IAAA;AAAA;AAAA,KAGG,kBAAA;EACH,YAAA;EACA,UAAA,GAAa,MAAA,SAAe,YAAA;EAC5B,YAAA,GAAe,OAAA;EACf,aAAA;EACA,gBAAA;EAGA,QAAA;EACA,OAAA,IAAW,GAAA,EAAK,OAAA,KAAY,SAAA;EAC5B,WAAA;EACA,WAAA;EACA,KAAA,GAAQ,OAAA;EACR,QAAA,IAAY,MAAA,EAAQ,MAAA,KAAW,MAAA;EAC/B,oBAAA,IAAwB,QAAA;EACxB,uBAAA,IAA2B,QAAA;EAC3B,aAAA,IAAiB,KAAA,EAAO,OAAA,EAAS,MAAA,GAAS,MAAA;EAC1C,OAAA,GAAU,YAAA;EACV,aAAA;EACA,cAAA,IAAkB,GAAA,EAAK,OAAA,KAAY,SAAA;EACnC,mBAAA,IAAuB,MAAA,EAAQ,UAAA,KAAe,SAAA;EAC9C,eAAA;AAAA;AAAA,cAOI,aAAA,kBAAa,yBAAA,CAAA,kBAAA,mBAAA,aAAA,CAAA,aAAA;;;cC5Eb,mBAAA;EAAuB;AAAA;EAAgB,QAAA,EAAU,SAAA;AAAA,MAAc,SAAA;;;KCmMhE,wBAAA;EAGH,SAAA,QAAiB,OAAO;EACxB,QAAA;EACA,KAAA;AAAA;AAAA,cAQI,oBAAA;EAAwB,SAAA;EAAA,QAAA;EAAA;AAAA,GAI3B,wBAAA;EAA6B,GAAA,GAAM,OAAA,EAAS,OAAA;AAAA;AAAA,cAczC,cAAA,QAAqB,WAAW;AAAA,cAShC,aAAA,QAAoB,UAAU;;;KCzH/B,iBAAA;EACH,QAAA,EAAU,SAAA;EAEV,QAAA,IAAY,MAAA,EAAQ,MAAM;EAE1B,SAAA;AAAA;;;KC1HG,eAAA,GAAkB,IAAA,CAAK,cAAA;EAC1B,QAAA,EAAU,SAAA;EACV,YAAA;EACA,QAAA,GAAW,MAAA,EAAQ,MAAA;EACnB,aAAA;EACA,gBAAA;EAIA,QAAA;EACA,WAAA;EACA,WAAA;EACA,KAAA,EAAO,OAAA;EACP,aAAA;EACA,SAAA,GAAY,GAAA,EAAK,OAAA,KAAY,SAAA;EAC7B,cAAA,IAAkB,GAAA,EAAK,OAAA,KAAY,SAAA;EACnC,mBAAA,IAAuB,MAAA,EAAQ,UAAA,KAAe,SAAA;EAC9C,eAAA;AAAA;;;KC8CG,YAAA;EACH,IAAA,EAAM,OAAA;EAGN,YAAA,IAAgB,IAAA,EAAM,UAAA,KAAe,SAAA;AAAA;;;KCLlC,eAAA;EAAoB,IAAA,EAAM,UAAU;AAAA;;;cChEnC,MAAA;EAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KCPD,cAAA,GAAiB,cAAc;AAAA,KAC/B,gBAAA,GAAmB,cAAc;AAAA,KACjC,cAAA,GAAiB,cAAc;AAAA,KAC/B,eAAA,GAAkB,cAAc;AAAA,KAChC,cAAA,GAAiB,cAAc;AAAA,KAC/B,eAAA,GAAkB,cAAc;AAAA,cAmB/B,KAAA;EAAA,wBAJqB,eAAA,KAAkB,SAAA;EAAA,uBATnB,cAAA,KAAiB,SAAA;EAAA,yBAHf,gBAAA,KAAmB,SAAA;EAAA,uBASrB,cAAA,KAAiB,SAAA;EAAA,uBAVjB,cAAA,KAAiB,SAAA;EAAA,wBAOhB,eAAA,KAAkB,SAAA;AAAA;;;KCTxC,sBAAA,GAAyB,cAAc;AAAA,KAgFvC,sBAAA,GAAyB,cAAc;;;KC9DvC,kBAAA,GAAqB,IAAA,CAAK,cAAA;EAE7B,QAAA,IAAY,GAAA,EAAK,OAAA,KAAY,SAAA;AAAA;;;KCV1B,kBAAA,GAAqB,cAAc;AAAA,KAMnC,eAAA,GAAkB,cAAc;AAAA,KA+BhC,yBAAA,GAA4B,cAAc;;;KC5B1C,eAAA,GAAkB,cAAA;EAA0B,IAAA,EAAM,UAAU;AAAA;;;KCd5D,cAAA,GAAiB,cAAA;EAA2B,GAAA,EAAK,OAAO;AAAA;AAAA,KA4DxD,kBAAA,GAAqB,cAAc;;;KCzDnC,mBAAA,GAAsB,cAAc;AAAA,KAMpC,kBAAA,GAAqB,cAAc;;;cCXlC,MAAA;EAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KCQD,YAAA;EAAiB,EAAA;EAAY,IAAI;AAAA;;;KCCjC,WAAA;EACH,SAAA,EAAW,OAAA;EACX,YAAA;EACA,QAAA,GAAW,KAAA;EACX,YAAA,GAAe,KAAA,UAAe,KAAA;EAC9B,QAAA,GAAW,MAAA,EAAQ,MAAA;EACnB,YAAA;EACA,WAAA;EACA,IAAA,EAAM,UAAA;EACN,aAAA,EAAe,KAAA,CAAM,YAAA;EACrB,mBAAA;EACA,eAAA,GAAkB,OAAA,EAAS,cAAA;EAC3B,gBAAA;EACA,SAAA,GAAY,KAAA,UAAe,IAAA;EAC3B,YAAA;EACA,iBAAA,GAAoB,KAAA;EACpB,SAAA,GAAY,KAAA,UAAe,OAAA;IAAY,KAAA;EAAA;EACvC,YAAA;EACA,YAAA,GAAe,KAAA;EACf,cAAA,EAAgB,cAAA;EAChB,YAAA;EACA,aAAA;EACA,cAAA;EACA,cAAA;AAAA;AAAA,cAgHI,SAAA,MAAgB,QAAA,GAAW,KAAA,EAAO,WAAA,KAAgB,CAAA,KAAI,CAAA;AAAA,KAUvD,eAAA;EAAoB,KAAA;EAAe,GAAA,EAAK,OAAO;AAAA;AAAA,cAI9C,MAAA,QAAa,eAMlB;;;KCpKI,WAAA;EACH,YAAA;EACA,QAAA,GAAW,MAAA,EAAQ,MAAA;EACnB,aAAA;EACA,gBAAA;EACA,QAAA;EACA,WAAA;EACA,WAAA;EACA,iBAAA;EACA,aAAA;EACA,SAAA,GAAY,GAAA,EAAK,OAAA,KAAY,SAAA;EAC7B,cAAA,IAAkB,GAAA,EAAK,OAAA,KAAY,SAAA;EACnC,mBAAA,IAAuB,MAAA,EAAQ,UAAA,KAAe,SAAA;EAC9C,eAAA;EACA,SAAA;EACA,WAAA;EACA,aAAA;EACA,eAAA;AAAA;AAAA,cAWI,SAAA,MAAgB,QAAA,GAAW,KAAA,EAAO,WAAA,KAAgB,CAAA,KAAI,CAAA;;;KCnCvD,UAAA;EACH,EAAA;EACA,KAAA,EAAO,OAAO;EACd,KAAA;IAAU,QAAA;EAAA;IAAuB,KAAA;EAAA;AAAA;AAAA,KAG9B,yBAAA;EAA8B,WAAA,EAAa,KAAK,CAAC,UAAA;AAAA;AAAA,KAEjD,eAAA;EACH,UAAA;EACA,YAAA,GAAe,OAAA,EAAS,WAAA;EACxB,YAAA,EAAc,OAAO;EACrB,GAAA;AAAA;AAAA,cAQI,eAAA,GAAmB,UAAA,EAAY,UAAU,EAAE,KAAA;AAAA,cAY3C,gBAAA,GAAoB,WAAA,EAAa,KAAA,CAAM,UAAA,GAAa,KAAA,aAAgB,UAAA;AAAA,cAWpE,kBAAA;EAAsB;AAAA,GAAiB,yBAAA,KAA4B,eAAA;;;KCzCpE,YAAA;EACH,OAAA;EACA,OAAA;EACA,QAAA,GAAW,MAAA,EAAQ,MAAA;EACnB,KAAA,EAAO,OAAA;EACP,IAAA;EACA,QAAA,GAAW,KAAA,EAAO,OAAA;EAClB,IAAA;AAAA;AAAA,KAGG,sBAAA;EACH,YAAA,GAAe,OAAA;EACf,KAAA,GAAQ,OAAA;EACR,QAAA,IAAY,MAAA,EAAQ,MAAA,KAAW,MAAA;EAC/B,oBAAA,IAAwB,QAAA;EACxB,uBAAA,IAA2B,QAAA;EAC3B,aAAA,IAAiB,KAAA,EAAO,OAAA,EAAS,MAAA,GAAS,MAAA;AAAA;AAAA,cAQtC,eAAA,GAAmB,OAAA,EAAS,sBAAA,KAAyB,YAmH1D"}
package/dist/index.js CHANGED
@@ -5,5 +5,5 @@
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),de=()=>j(()=>({subject:null})),fe=de(),pe=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)},[])}},R=(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=``)=>R({data:C(()=>({type:`tab`}),[]),id:e},t,n),ge=(e,t=!1,n=``)=>R({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}),R({data:C(()=>({createTab:()=>i.current(),type:`external`}),[]),id:`external-${r}`},t,n)},z=()=>M(_(pe)??fe,e=>e.subject),ye=e=>j(()=>e),B=p(null),V=e=>{let t=_(B);if(t===null)throw Error(`dashfoo components must be rendered inside <DashfooLayout> or <Layout.Root>.`);return M(t,e)},H=(e,t)=>e.x>=t.x&&e.x<=t.x+t.width&&e.y>=t.y&&e.y<=t.y+t.height,be=(e,t)=>{let n=e.findIndex(e=>t<e.x+e.width/2);return n===-1?e.length:n},xe=(e,t,n,r)=>{let i=t[n],a=t.at(-1),o=i??a,s=i?.x??(a?a.x+a.width:e.x),c=Math.min(r.width,e.width),l=o?.height??Math.min(r.height,e.height);return{height:l,width:c,x:Math.max(e.x,Math.min(s,e.x+e.width-c)),y:o?.y??e.y+e.height-l}},Se=(e,t,n)=>!(e===`grip-${t}`||n.length===1&&n[0]===e),Ce=new Set,U=(e,t)=>{Ce.has(e)||(Ce.add(e),console.warn(`[dashfoo] ${t}`))},we={boxSizing:`border-box`,pointerEvents:`none`,position:`fixed`,transition:`var(--dashfoo-dock-transition, left 60ms, top 60ms, width 60ms, height 60ms)`,zIndex:9999},Te=e=>({...we,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}),Ee=e=>({...Te(e),borderRadius:`var(--dashfoo-dock-tab-radius, var(--dashfoo-dock-radius, 6px))`}),De=(e,t)=>[...e.querySelectorAll(`[data-dashfoo="tab-item"]`)].flatMap(e=>e.querySelector(`[data-dashfoo="tab"]`)?.dataset.tabId===t?[]:[e.getBoundingClientRect()]),Oe={height:32,width:96},ke=(e,t)=>e||(t.length>0?{height:t.reduce((e,t)=>e+t.height,0)/t.length,width:t.reduce((e,t)=>e+t.width,0)/t.length}:Oe),Ae=({actorRef:e,getSourceSize:t,getTabsetElement:n})=>{let r=D(e,e=>e.context.intent),i=D(e,e=>e.context.subject?.id);if(!r)return null;let a=n(r.targetId);if(!a)return null;if(r.location===`center`){let e=a.querySelector(`[data-dashfoo="tabstrip"]`);if(e){let n=De(e,i);return N(`div`,{"data-dashfoo":`dock-indicator`,style:Ee(xe(e.getBoundingClientRect(),n,r.index??0,ke(t(),n)))})}}return N(`div`,{"data-dashfoo":`dock-indicator`,style:Te(d(a.getBoundingClientRect(),r.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&&H(n,i.getBoundingClientRect()))return{index:be(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}},W={x:12,y:8},Fe=e=>{let t=e?.data?.label;return typeof t==`string`?t:``},Ie=e=>typeof e==`function`,Le=e=>{if(!e)return;let t=(e.closest(`[data-dashfoo="tab-item"]`)??e).getBoundingClientRect();return t.width>0&&t.height>0?{height:t.height,width:t.width}:void 0},Re=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`}},ze=({children:e,onCommit:t,splitDock:n})=>{let i=E(r),a=_(B),o=w(new Map),s=w(null),c=w(void 0),[l,u]=T(null),d=_(L),[f]=T(()=>d?null:ue());x(()=>()=>f?.destroy(),[f]);let p=d??f;if(p===null)throw Error(`[dashfoo] DashfooDragProvider unmounted while its layout is still mounted; keep the provider above the layout or remount the layout`);let[m]=T(()=>de());v(()=>{let e=i.subscribe(e=>{let t=e.context.subject;m.getState().subject!==t&&m.setState({subject:t})});return()=>{e.unsubscribe()}},[i,m]),v(()=>{let e=i.on(`COMMIT`,e=>{let n=t??a?.getState().dispatch;if(!n){U(`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 h=g((e,t)=>{t?o.current.set(e,t):o.current.delete(e)},[]),y=g(e=>o.current.get(e),[]),b=g(()=>c.current,[]),S=g(e=>{for(let[t,n]of o.current)if(H(e,n.getBoundingClientRect()))return{element:n,id:t}},[]),D=g((e,t,r,i)=>{if(!Se(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]),O=g(e=>{let t=s.current;t&&(t.style.transform=`translate(${e.x+W.x}px, ${e.y+W.y}px)`)},[]),k=g(e=>{s.current=e},[]);v(()=>{let e=e=>{let t=e.operation.source;if(!t)return;let n=Re(t);if(!n)return;let r=e.operation.position.current;c.current=Le(t.element),u({label:Fe(t),x:r.x+W.x,y:r.y+W.y}),i.send({subject:n,type:`START`})},t=e=>{let t=e.operation,n=t.position.current;O(n);let r=t.source?String(t.source.id):void 0,a=S(n);i.send({intent:a?D(a.id,a.element,n,r):null,type:`OVER`})},n=e=>{if(u(null),c.current=void 0,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=S(n);a&&i.send({intent:D(a.id,a.element,n,r),type:`OVER`}),i.send({type:`DROP`})},r=p.monitor.addEventListener(`dragstart`,e),a=p.monitor.addEventListener(`dragmove`,t),o=p.monitor.addEventListener(`dragend`,n);return()=>{r(),a(),o()}},[i,p,O,D,S]);let A=C(()=>({manager:p,registerTabset:h}),[p,h]);return N(I.Provider,{value:A,children:P(pe.Provider,{value:m,children:[e,N(Ae,{actorRef:i,getSourceSize:b,getTabsetElement:y}),N(Me,{overlayRef:k,preview:l})]})})},Be={display:`flex`,height:`100%`,width:`100%`},Ve=({children:e,closableTabs:t=!0,dispatch:n,draggableTabsets:r=!0,keepMounted:i=!1,maximizable:a=!0,model:o,renamableTabs:s=!0,renderTab:c,renderTabLabel:l,renderTabsetToolbar:u,style:d,...f})=>{let p=o.global,m={closableTabs:t&&p.tabEnableClose!==!1,dispatch:n,draggableTabsets:r,keepMounted:i,maximizable:a&&p.tabSetEnableMaximize!==!1,maximizedTabsetId:o.maximizedTabsetId,renamableTabs:s&&p.tabEnableRename!==!1,renderTab:c,renderTabLabel:l,renderTabsetToolbar:u,splitDock:p.enableSplitDock!==!1,tabLocation:p.tabLocation??`top`,tabsetMinSize:p.tabSetMinSize??320,tabStripEnabled:p.tabSetEnableTabStrip!==!1},[h]=T(()=>ye(m));S(()=>{h.setState(m)});let g=p.splitterSize===void 0?{...Be,...d}:{...Be,"--dashfoo-splitter-size":`${p.splitterSize}px`,...d};return N(B.Provider,{value:h,children:N(`div`,{...f,"data-dashfoo":`layout`,style:g,children:e})})},G=(e,t)=>`dashfoo-tab-${e}-${t}`,K=e=>`dashfoo-panel-${e}`,He=(e,t,n)=>e?.querySelector(`#${CSS.escape(G(t,n))}`)??null,Ue=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&&U(`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`}),He(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&&He(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){U(`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`})}})),q=p(null),J=e=>{let t=_(q);if(t===null)throw Error(`dashfoo Tabset parts must be rendered inside <Tabset.Root>.`);return M(t,e)},We=p(null),Y=()=>{let e=_(We);if(e===null)throw Error(`dashfoo tab parts must be rendered inside <Tabset.Tab>.`);return e},Ge={flex:1,minHeight:0,overflow:`auto`},Ke=({render:e,tab:t})=>{let n=V(e=>e.renderTab);return e?e(t):n(t)},qe=({children:e,style:t,...n})=>{let r=J(e=>e.node),i=J(e=>e.visualSelected),a=V(e=>e.keepMounted),o={...Ge,...t};if(a&&r.children.length>0)return r.children.map((t,a)=>m(`div`,{...n,"aria-labelledby":G(r.id,t.id),"data-dashfoo":`tabcontent`,hidden:a!==i||void 0,id:a===i?K(r.id):void 0,key:t.id,role:a===i?`tabpanel`:void 0,style:o,tabIndex:a===i?0:void 0},N(Ke,{render:e,tab:t})));let s=r.children[i];return s?N(`div`,{...n,"aria-labelledby":G(r.id,s.id),"data-dashfoo":`tabcontent`,id:K(r.id),role:`tabpanel`,style:o,tabIndex:0,children:N(Ke,{render:e,tab:s})}):N(`div`,{...n,"data-dashfoo":`tabcontent`,style:o})},Je=()=>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`})]}),Ye={position:`absolute`,right:0,top:`100%`,zIndex:10},Xe=({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(Je,{})}),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:Ye,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]})},Ze=()=>{let e=J(e=>e.overflowItems),t=J(e=>e.selectOverflowTab);return e.length===0?null:N(Xe,{items:e,onSelect:t})},Qe=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]:[]})},$e=(e,t)=>{let[n,r]=T([]);return v(()=>{let t=()=>{r(t=>{let n=e?Qe(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},et=(e,t)=>t+1<e?t+1:t-1,tt={display:`flex`,flexDirection:`column`,height:`100%`,minHeight:0,minWidth:0,width:`100%`},nt=({children:e,node:t,ref:n,style:r,...i})=>{let a=V(e=>e.closableTabs),o=V(e=>e.dispatch),s=V(e=>e.maximizable),c=V(e=>e.maximizedTabsetId),l=V(e=>e.renamableTabs),u=V(e=>e.tabLocation),{ref:d}=_e(t.id),f=z(),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?et(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(()=>Ue(D));S(()=>{O.setState(D)});let k=$e(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(G(t.id,e))}`)?.focus():p.current?.focus()},[t.children,t.selected,t.id,O]),N(q.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:{...tt,...r},tabIndex:-1,children:e})})},rt=(e,t)=>{typeof e==`function`?e(t):e&&(e.current=t)},X=(...e)=>t=>{for(let n of e)rt(n,t)},it=({children:e,ref:t,tab:n,...r})=>{let i=_(q),a=J(e=>e.node),o=J(e=>e.editingTabId===n.id),s=z(),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&&U(`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(()=>X(l,t),[t]);return N(We.Provider,{value:f,children:N(`span`,{...r,"data-dashfoo":`tab-item`,"data-dragging":c||void 0,ref:p,children:e})})},at=({children:e,onClick:t,onDoubleClick:n,ref:r,...i})=>{let{index:a,tab:o}=Y(),s=J(e=>e.node),c=J(e=>e.editingTabId===o.id),l=J(e=>e.selectTab),u=J(e=>e.startEditing),d=J(e=>e.tabsRenamable),f=J(e=>e.visualSelected),p=V(e=>e.renderTabLabel),{ref:m}=he(o.id,o.enableDrag===!1,o.name),h=C(()=>X(m,r),[m,r]);if(c)return null;let g=a===f,_=d&&o.enableRename!==!1,v=e=>{t?.(e),l(a)},y=e=>{n?.(e),_&&u(o.id)};return N(`button`,{"aria-label":p?o.name:void 0,...i,"aria-controls":K(s.id),"aria-selected":g,"data-dashfoo":`tab`,"data-tab-id":o.id,id:G(s.id,o.id),onClick:v,onDoubleClick:y,ref:h,role:`tab`,tabIndex:g?0:-1,type:`button`,children:e??(p?p(o):o.name)})},ot={pointerEvents:`none`},Z=({children:e})=>N(`svg`,{"aria-hidden":`true`,fill:`none`,height:`12`,stroke:`currentColor`,strokeLinecap:`round`,strokeLinejoin:`round`,strokeWidth:`2`,style:ot,viewBox:`0 0 24 24`,width:`12`,children:e}),st=()=>P(Z,{children:[N(`path`,{d:`M18 6 6 18`}),N(`path`,{d:`m6 6 12 12`})]}),ct=()=>P(Z,{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`})]}),lt=({maximized:e})=>e?P(Z,{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(Z,{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`})]}),ut=({defaultValue:e,onBlur:t,onKeyDown:n,ref:r,...i})=>{let{tab:a}=Y(),o=J(e=>e.cancelRename),s=J(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`})},dt=e=>{let{tab:t}=Y(),n=J(e=>e.editingTabId===t.id),r=J(e=>e.registerRenameInput);return v(()=>r(),[r]),n?N(ut,{...e}):null},ft=({children:e,onClick:t,...n})=>{let{index:r,tab:i}=Y(),a=J(e=>e.closeTab),o=J(e=>e.editingTabId===i.id),s=J(e=>e.tabsClosable),c=J(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(st,{})})},pt={display:`flex`,flexShrink:0},mt={display:`flex`,minWidth:0,overflowX:`auto`},ht=({style:e,...t})=>N(`div`,{...t,"data-dashfoo":`tabstrip`,style:{...pt,...e}}),gt=({onKeyDown:e,ref:t,style:n,...r})=>{let i=J(e=>e.node),a=J(e=>e.registerTablist),o=J(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(()=>X(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:{...mt,...n},tabIndex:-1})},_t={alignItems:`center`,display:`flex`,flexShrink:0,marginInlineStart:`auto`},vt=({style:e,...t})=>N(`div`,{...t,"data-dashfoo":`tabset-toolbar`,style:{..._t,...e}}),yt=({children:e,ref:t,...n})=>{let r=J(e=>e.activeTab?.name??``),i=J(e=>e.isMaximized),a=J(e=>e.node),o=!V(e=>e.draggableTabsets)||i,{ref:s}=ge(a.id,o,r),c=C(()=>X(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(ct,{})})},Q=({children:e,onClick:t,...n})=>{let r=J(e=>e.isMaximized),i=J(e=>e.showMaximize),a=J(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(lt,{maximized:r})})},bt=()=>{let e=V(e=>e.draggableTabsets),t=V(e=>e.renderTabsetToolbar),n=V(e=>e.tabLocation),r=V(e=>e.tabStripEnabled),i=J(e=>e.isMaximized),a=J(e=>e.node),o=J(e=>e.overflowItems.length),s=J(e=>e.showMaximize)||t!==void 0||o>0||e&&!i,c=r?P(ht,{children:[N(gt,{children:a.children.map(e=>P(it,{tab:e,children:[N(at,{}),N(dt,{}),N(ft,{})]},e.id))}),s?P(vt,{children:[N(Ze,{}),N(yt,{}),t?.(a),N(Q,{})]}):null]}):null,l=N(qe,{});return n===`bottom`?P(ne,{children:[l,c]}):P(ne,{children:[c,l]})},xt=({node:e})=>N(nt,{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=V(e=>e.dispatch),r=V(e=>e.tabsetMinSize),i=e.orientation===`row`?`horizontal`:`vertical`,a=e.children.reduce((e,t)=>e+(t.weight??1),0),o=C(()=>Et(e.children,a),[e.children,a]),s=w(!1),c=w(null),l=w(!1);return S(()=>{let e=c.current;if(!e||Dt(e.getLayout(),o))return;l.current=!0,e.setLayout(o);let t=requestAnimationFrame(()=>{l.current=!1});return()=>{cancelAnimationFrame(t),l.current=!1}},[o]),N(re,{"data-dashfoo":`row`,groupRef:c,onLayoutChanged:t=>{if(!s.current){s.current=!0;return}if(l.current)return;let r=e.children.map(e=>t[e.id]??e.weight??1);r.some((t,n)=>Math.abs(t-(e.children[n]?.weight??1))>Tt)&&n({rowId:e.id,type:`adjustSplit`,weights:r})},orientation:i,style:wt,children:e.children.map((n,i)=>{let o=(n.weight??1)/a*100,s=n.min?St(n.min):void 0;if(s===void 0){let t=Ot(n,e.orientation,r);s=t===void 0?void 0:`${t}px`}let c=n.max?St(n.max):void 0;return P(f,{children:[i>0?N(ae,{"data-dashfoo":`splitter`}):null,N(ie,{defaultSize:`${o}%`,id:n.id,maxSize:c,minSize:s,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:ze,Root:Ve,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,draggableTabsets:o=!0,factory:s,keepMounted:c=!1,maximizable:l=!0,model:u,onAction:d,onActiveTabsetChange:f,onMaximizedTabsetChange:p,onModelChange:m,persist:h,renamableTabs:_=!0,renderTabLabel:v,renderTabsetToolbar:y}=e,x=se(C(()=>At(h,a!==void 0),[h,a]),a),S=g((e,t)=>{x.save(e),m?.(e,t)},[m,x]),w=ce({defaultModel:x.initialModel??a,model:u,onAction:d,onActiveTabsetChange:f,onMaximizedTabsetChange:p,onModelChange:S});b(t,()=>({addTab:(e,t)=>w.dispatch({index:t.index,location:t.location??`center`,tab:e,targetId:t.targetId,type:`addNode`}),canRedo:w.canRedo,canUndo:w.canUndo,closeTab:e=>w.dispatch({tabId:e,type:`deleteTab`}),dispatch:w.dispatch,getModel:()=>w.model,maximizeTabset:e=>w.dispatch({tabsetId:e,type:`setMaximizedTabset`}),redo:w.redo,renameTab:(e,t)=>w.dispatch({name:t,tabId:e,type:`renameTab`}),resetLayout:()=>{x.clear(),a!==void 0&&w.setModel(a)},selectTab:(e,t)=>w.dispatch({index:t,tabsetId:e,type:`selectTab`}),undo:w.undo}),[a,x,w]);let T=g(e=>{if(s)return s(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,s]),E=w.model.maximizedTabsetId?i(w.model,w.model.maximizedTabsetId):void 0;return N($.Root,{closableTabs:n,dispatch:w.dispatch,draggableTabsets:o,keepMounted:c,maximizable:l,model:w.model,renamableTabs:_,renderTab:T,renderTabLabel:v,renderTabsetToolbar:y,children:N($.DragLayer,{children:E?N($.Tabset,{node:E}):N($.Rows,{node:w.model.layout})})})});Mt.displayName=`DashfooLayout`;const Nt=({children:e})=>{let[t]=T(ue);return x(()=>()=>t.destroy(),[t]),N(L.Provider,{value:t,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:ft,Content:qe,Grip:yt,MaximizeButton:Q,OverflowMenu:Ze,RenameInput:dt,Root:nt,Tab:it,Tablist:gt,TabStrip:ht,Toolbar:vt,Trigger:at},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,z as useDragSubject,ve as useExternalTabSource,V as useLayout,se as usePersistence,zt as useResponsiveModel,Y as useTab,J as useTabset};
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};
9
9
  //# sourceMappingURL=index.js.map