@dashfoo/react 0.2.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 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.4** — the framework-agnostic core (no React bindings) — for drag (the drag adapter is the only file that touches it; pointer-only).
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,24 +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 | 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. |
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. |
80
85
 
81
86
  You must pass either `model` or `defaultModel`. Passing neither throws.
82
87
 
@@ -175,19 +180,22 @@ with the right role and ARIA wiring, ready for you to style.
175
180
 
176
181
  ### Per-node enable flags
177
182
 
178
- The three top-level chrome props are global gates. Individual nodes can opt out
183
+ The top-level chrome props are layout-wide gates. Individual nodes can opt out
179
184
  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) |
185
+ explicitly `false`). A control shows only when the `editable` umbrella, the
186
+ chrome prop, the model global, and the node's flag all allow it (`maximizable`
187
+ ignores `editable` — maximize is view state, not a structural edit).
188
+
189
+ | Field | On node | Disables |
190
+ | ------------------- | ------- | ------------------------------------------------ |
191
+ | `enableClose` | tab | the close control for that tab |
192
+ | `enableClose` | tabset | closing for every tab in the tabset |
193
+ | `enableRename` | tab | double-click rename for that tab |
194
+ | `enableDrag` | tab | dragging that tab |
195
+ | `enableMaximize` | tabset | the maximize control for that tabset |
196
+ | `tabEnableDrag` | global | tree-wide default behind `tab.enableDrag` |
197
+ | `enableSplitDock` | global | splitting a tabset on drop (drops stack instead) |
198
+ | `enableSplitResize` | global | dragging the splitters (gutters keep their size) |
191
199
 
192
200
  ```ts
193
201
  { id: "logs", type: "tab", name: "Logs", component: "logs", enableClose: false }
@@ -244,6 +252,31 @@ keyboard access.
244
252
  | `label` | `string` | `""` | The drag preview chip text. |
245
253
  | `disabled` | `boolean` | `false` | Unregisters the source while true. |
246
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
+
247
280
  ## Persistence
248
281
 
249
282
  The `persist` prop saves an uncontrolled layout and restores it on load. It loads
@@ -279,7 +312,7 @@ in `onModelChange`.
279
312
 
280
313
  The lower-level `usePersistence` load/save primitive (that `persist` is built on)
281
314
  is also exported, for hosts that drive the store directly. See the
282
- [persistence guide](https://docs.dashfoo.dev/persistence) for the storage seam,
315
+ [persistence guide](https://docs.dashfoo.com/persistence) for the storage seam,
283
316
  validation pipeline, and SSR notes.
284
317
 
285
318
  ### Options
@@ -345,7 +378,7 @@ you.
345
378
  | `tabset-grip` | `button` | Drags the whole tabset. `aria-label="Move tabset"`; shown when `draggableTabsets` is on and the tabset is not maximized. |
346
379
  | `tabset-maximize` | `button` | Maximize/restore toggle. `aria-pressed` reflects state. |
347
380
  | `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`. |
381
+ | `dock-indicator` | `div` | The drag preview overlay (insertion line or zone pane). `pointer-events: none`. |
349
382
  | `drag-preview` | `div` | The chip that follows the pointer during a drag, showing the dragged label. |
350
383
  | `separator` | rrp `Separator` | rrp emits `data-separator` with `aria-orientation`; style splitters here. |
351
384
 
@@ -366,7 +399,7 @@ to theme the drag preview without touching layout.
366
399
  | `--dashfoo-dock-border` | indicator border color | `oklch(0.708 0 0 / 0.75)` |
367
400
  | `--dashfoo-dock-border-width` | indicator border width | `1px` |
368
401
  | `--dashfoo-dock-radius` | indicator corner radius | `6px` |
369
- | `--dashfoo-dock-tab-radius` | insertion-ghost radius | `var(--dashfoo-dock-radius, 6px)` |
402
+ | `--dashfoo-dock-line-radius` | insertion-line radius | `2px` |
370
403
  | `--dashfoo-dock-transition` | indicator move animation | `left 60ms, top 60ms, width 60ms, height 60ms` |
371
404
 
372
405
  Set `--dashfoo-dock-transition: none` to disable the indicator animation.
@@ -405,6 +438,16 @@ const { index, tab } = useTab(); // which tab a part belongs to; throws outside
405
438
  tabset being dragged) or `null` — including outside a drag layer — for
406
439
  drag-aware styling in custom parts.
407
440
 
441
+ `useDropIntent()` returns the live drop intent (`{ targetId, location, index? }`
442
+ — where the drag would land if dropped right now) or `null` when nothing is
443
+ dragging or the pointer is over no valid target (empty space, a non-editable
444
+ layout, or a no-op drop the library suppresses). Together with
445
+ `dockZonePolygons` from `@dashfoo/core` it supports consumer-rendered drop
446
+ indicators and drop-zone visualizations alongside the built-in indicator. Both
447
+ hooks work anywhere under a layout; under a `DashfooDragProvider` they work
448
+ anywhere under the provider (the provider hosts the drag store, so widget lists
449
+ and overlays outside the layout observe the same drag).
450
+
408
451
  ## Build your own layout
409
452
 
410
453
  `DashfooLayout` is a thin assembly of exported primitives — you can compose the
@@ -525,9 +568,10 @@ type TabsetState;
525
568
  useTab; // { tab, index } identity (throws outside Tabset.Tab)
526
569
  type TabContextValue;
527
570
  useDragSubject; // the live drag subject, or null
571
+ useDropIntent; // where the drag would land if dropped right now, or null
528
572
 
529
573
  // External drag sources
530
- DashfooDragProvider; // shares one drag manager between a layout and outside sources
574
+ DashfooDragProvider; // shares one drag manager + drag store between a layout and outside sources
531
575
  useExternalTabSource;
532
576
  type ExternalTabSourceOptions;
533
577
 
@@ -540,7 +584,8 @@ type Persistence;
540
584
  type PersistConfig;
541
585
 
542
586
  // Responsive
543
- useResponsiveModel;
587
+ useContainerWidth; // [ref, width] via ResizeObserver — the hand-built building block
588
+ useResponsiveModel; // per-breakpoint model + lock flags (no remount)
544
589
  matchBreakpoint; // does a breakpoint apply at a given width
545
590
  activeBreakpoint; // first matching breakpoint, else the last (the catch-all)
546
591
  type Breakpoint;
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { Action, Dashfoo, DockLocation, DragSubject, 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 = {
@@ -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,12 @@ type DashfooLayoutProps = {
65
67
  renamableTabs?: boolean;
66
68
  renderTabLabel?: (tab: TabNode) => ReactNode;
67
69
  renderTabsetToolbar?: (tabset: TabsetNode) => ReactNode;
70
+ resizableSplits?: boolean;
71
+ responsive?: {
72
+ maxWidth: number;
73
+ orientation?: Orientation;
74
+ };
75
+ snap?: SnapConfig;
68
76
  };
69
77
  declare const DashfooLayout: import("react").ForwardRefExoticComponent<DashfooLayoutProps & import("react").RefAttributes<DashfooHandle>>;
70
78
  //#endregion
@@ -89,6 +97,7 @@ declare const useExternalTabSource: ({
89
97
  ref: (element: Element | null) => void;
90
98
  };
91
99
  declare const useDragSubject: () => DragSubject | null;
100
+ declare const useDropIntent: () => DropIntent | null;
92
101
  //#endregion
93
102
  //#region src/components/drag-adapter.d.ts
94
103
  type DragProviderProps = {
@@ -102,7 +111,9 @@ type LayoutRootProps = Omit<ComponentProps<"div">, "children"> & {
102
111
  children: ReactNode;
103
112
  closableTabs?: boolean;
104
113
  dispatch: (action: Action) => void;
114
+ draggableTabs?: boolean;
105
115
  draggableTabsets?: boolean;
116
+ editable?: boolean;
106
117
  keepMounted?: boolean;
107
118
  maximizable?: boolean;
108
119
  model: Dashfoo;
@@ -110,6 +121,9 @@ type LayoutRootProps = Omit<ComponentProps<"div">, "children"> & {
110
121
  renderTab: (tab: TabNode) => ReactNode;
111
122
  renderTabLabel?: (tab: TabNode) => ReactNode;
112
123
  renderTabsetToolbar?: (tabset: TabsetNode) => ReactNode;
124
+ resizableSplits?: boolean;
125
+ rootRef?: Ref<HTMLDivElement>;
126
+ snap?: SnapConfig;
113
127
  };
114
128
  //#endregion
115
129
  //#region src/components/row-view.d.ts
@@ -134,7 +148,9 @@ declare const Layout: {
134
148
  children,
135
149
  closableTabs,
136
150
  dispatch,
151
+ draggableTabs,
137
152
  draggableTabsets,
153
+ editable,
138
154
  keepMounted,
139
155
  maximizable,
140
156
  model,
@@ -142,6 +158,9 @@ declare const Layout: {
142
158
  renderTab,
143
159
  renderTabLabel,
144
160
  renderTabsetToolbar,
161
+ resizableSplits,
162
+ rootRef,
163
+ snap,
145
164
  style,
146
165
  ...props
147
166
  }: LayoutRootProps) => import("react").ReactNode;
@@ -304,7 +323,9 @@ declare const useTab: () => TabContextValue;
304
323
  type LayoutState = {
305
324
  closableTabs: boolean;
306
325
  dispatch: (action: Action) => void;
326
+ draggableTabs: boolean;
307
327
  draggableTabsets: boolean;
328
+ editable: boolean;
308
329
  keepMounted: boolean;
309
330
  maximizable: boolean;
310
331
  maximizedTabsetId: string | undefined;
@@ -312,6 +333,8 @@ type LayoutState = {
312
333
  renderTab: (tab: TabNode) => ReactNode;
313
334
  renderTabLabel: ((tab: TabNode) => ReactNode) | undefined;
314
335
  renderTabsetToolbar: ((tabset: TabsetNode) => ReactNode) | undefined;
336
+ resizableSplits: boolean;
337
+ snap: SnapConfig | null;
315
338
  splitDock: boolean;
316
339
  tabLocation: "bottom" | "top";
317
340
  tabsetMinSize: number;
@@ -321,6 +344,7 @@ declare const useLayout: <T>(selector: (state: LayoutState) => T) => T;
321
344
  //#endregion
322
345
  //#region src/hooks/responsive.d.ts
323
346
  type Breakpoint = {
347
+ compact?: boolean;
324
348
  id: string;
325
349
  model: Dashfoo;
326
350
  query?: {
@@ -335,11 +359,15 @@ type UseResponsiveModelOptions = {
335
359
  type ResponsiveModel = {
336
360
  breakpoint: string;
337
361
  containerRef: (element: HTMLElement | null) => void;
338
- defaultModel: Dashfoo;
339
- key: string;
362
+ draggableTabs: boolean;
363
+ draggableTabsets: boolean;
364
+ isCompact: boolean;
365
+ model: Dashfoo;
366
+ resizableSplits: boolean;
340
367
  };
341
368
  declare const matchBreakpoint: (breakpoint: Breakpoint, width: number) => boolean;
342
369
  declare const activeBreakpoint: (breakpoints: Array<Breakpoint>, width: number) => Breakpoint;
370
+ declare const useContainerWidth: () => [(element: HTMLElement | null) => void, number];
343
371
  declare const useResponsiveModel: ({
344
372
  breakpoints
345
373
  }: UseResponsiveModelOptions) => ResponsiveModel;
@@ -364,5 +392,5 @@ type UseDashfooStoreOptions = {
364
392
  };
365
393
  declare const useDashfooStore: (options: UseDashfooStoreOptions) => DashfooStore;
366
394
  //#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 };
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 };
368
396
  //# 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":"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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,tabNodeSchema as l,toJSON as u,zoneRect as d}from"@dashfoo/core";import{Fragment as f,createContext as p,createElement as m,forwardRef as h,useCallback as g,useContext as _,useEffect as v,useId as y,useImperativeHandle as b,useInsertionEffect as x,useLayoutEffect as S,useMemo as C,useRef as w,useState as T}from"react";import{useActorRef as E,useSelector as D}from"@xstate/react";import{Accessibility as O,DragDropManager as k,Draggable as A,Feedback as ee,PointerSensor as te}from"@dnd-kit/dom";import{createStore as j,useStore as M}from"zustand";import{Fragment as ne,jsx as N,jsxs as P}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)}}},F={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=w(e);v(()=>{n.current=e});let[r]=T(()=>{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}});v(()=>{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=w(e?.key);v(()=>{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=w(null),s=w(null),c=g(()=>{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=g(e=>{let t=n.current;t!==null&&(s.current={key:t.key,storage:t.storage,value:u(e)},o.current!==null&&clearTimeout(o.current),o.current=setTimeout(c,t.debounceMs))},[c]);return v(()=>{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]),{clear:g(()=>{o.current!==null&&(clearTimeout(o.current),o.current=null),s.current=null;let e=n.current;e!==null&&e.storage.removeItem(e.key)},[]),initialModel:r,save:l}},ce=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=E(n,{input:{model:o(f)}}),m=D(p,e=>e.context.history);v(()=>{a!==void 0&&p.send({model:o(a),type:`SET_MODEL`})},[p,a]);let h=a??m.present,_=g((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=g(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)}})();_(n.before,n.after,t)},[p,a,_,c]),b=g(()=>{if(a!==void 0)return;let e=p.getSnapshot().context.history.present;p.send({type:`UNDO`});let t=p.getSnapshot().context.history.present;_(e,t)},[p,a,_]);return{canRedo:()=>e(p.getSnapshot().context.history),canUndo:()=>t(p.getSnapshot().context.history),dispatch:y,model:h,redo:g(()=>{if(a!==void 0)return;let e=p.getSnapshot().context.history.present;p.send({type:`REDO`});let t=p.getSnapshot().context.history.present;_(e,t)},[p,a,_]),setModel:g(e=>{p.send({model:o(e),type:`SET_MODEL`})},[p]),undo:b}},le=(e,t)=>{let{target:n}=e;if(!(n instanceof Element))return!1;let r=n.closest(`
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),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},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