@dashfoo/react 0.7.0 → 0.8.2

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
@@ -66,7 +66,7 @@ a sized parent and add your CSS (see the [attribute reference](#data-dashfoo-att
66
66
  | `onModelChange` | `(model: Dashfoo, action?: Action) => void` | (none) | Called after every change with the next model and the action that caused it. |
67
67
  | `components` | `Record<string, ComponentType<{ node: TabNode }>>` | (none) | Registry mapping `tab.component` keys to components. |
68
68
  | `factory` | `(tab: TabNode) => ReactNode` | (none) | Render override. When provided, it resolves every tab and `components` is ignored. |
69
- | `persist` | `string \| { key; storage?; debounceMs? }` | (none) | Auto-save the model (uncontrolled mode only). A bare string is a localStorage key. |
69
+ | `persist` | `string \| { key; storage?; debounceMs? }` | (none) | Auto-save the model. The props type only accepts it alongside `defaultModel`. A bare string is a localStorage key. |
70
70
  | `onAction` | `(action: Action) => Action \| null` | (none) | Intercept each action before it commits: return it, a replacement, or `null` to veto. |
71
71
  | `onActiveTabsetChange` | `(id: string \| undefined) => void` | (none) | Fires when the active tabset changes. |
72
72
  | `onMaximizedTabsetChange` | `(id: string \| undefined) => void` | (none) | Fires when a tabset is maximized or restored. |
@@ -265,20 +265,16 @@ _restructure_ on small screens, give `DashfooLayout` a `responsive` prop:
265
265
  ```
266
266
 
267
267
  At or below `maxWidth` (measured on the layout's own container, not the viewport),
268
- the layout renders as a single stacked column and **locks every structural
269
- interaction** (tab/tabset drag, split resize), leaving tap-to-switch and
270
- maximize. This mirrors VS Code: docking is a desktop interaction, so narrow
271
- screens get a read-only, navigable view instead of unusable hit targets.
268
+ the layout renders as a single stacked column and **locks docking and split resizing** (tab/tabset drag, split resize), leaving tap-to-switch. Tabs remain selectable, closable and renamable; existing float controls remain available.
272
269
 
273
- The stacked view is a **derived projection**: the model in the store is never
274
- mutated, so the layout is never remounted and widening past `maxWidth` restores
270
+ The stacked view is a **derived projection**: the projection does not replace the model in the store, and the row hierarchy stays mounted and widening past `maxWidth` restores
275
271
  the desktop arrangement exactly. Undo history, persistence, selection, and
276
272
  mounted panels all survive the breakpoint cross. The theme grows tab hit targets
277
273
  to 44px under `@media (pointer: coarse)` so tap-to-switch stays usable.
278
274
 
279
- Hand-built layouts (the `Layout.*` primitives) get the same behavior with
275
+ Hand-built layouts (the `Layout.*` primitives) can compose a stacked view with
280
276
  `useContainerWidth` + `stackModel`; for _distinct_ per-breakpoint models, use
281
- `useResponsiveModel`. Both feed reactive props with no `key`/remount.
277
+ `useResponsiveModel`. Both feed reactive props; changing the tree hierarchy can remount nested panels.
282
278
 
283
279
  ## Floating panels
284
280
 
@@ -356,7 +352,7 @@ const Layout = () => {
356
352
  a custom store (sessionStorage, in-memory, your own). A pending save flushes on
357
353
  unmount and on page hide (reload, tab close, navigation, the page going to the
358
354
  background), so the last change is never lost, even inside the debounce window.
359
- It applies to uncontrolled mode only; in controlled mode, save the model yourself
355
+ The props type only accepts `persist` alongside `defaultModel`; in controlled mode, save the model yourself
360
356
  in `onModelChange`.
361
357
 
362
358
  The lower-level `usePersistence` load/save primitive (that `persist` is built on)
@@ -518,7 +514,7 @@ pattern as `Panel`:
518
514
 
519
515
  | Part | Element | Role |
520
516
  | ----------------------- | ---------------------------------------- | --------------------------------------------------------------------------------------------------------------------------- |
521
- | `Layout.Root` | `div[data-dashfoo="layout"]` | Creates the layout store. Takes `model`, `dispatch`, `renderTab`, and the chrome flags `DashfooLayout` accepts. |
517
+ | `Layout.Root` | `div[data-dashfoo="layout"]` | Creates the layout store. Takes `model`, `dispatch`, `renderers`, and the chrome flags `DashfooLayout` accepts. |
522
518
  | `Layout.DragLayer` | none (overlays) | Opts the tree into drag-dock. Omit it and everything else still works, just without dragging. |
523
519
  | `Layout.Rows` | rrp split tree | Renders a `RowNode` recursively. `renderTabset` swaps in a custom tabset composition at every leaf. |
524
520
  | `Layout.Tabset` | the stock `Tabset.*` composition | The stock tabset composition, for leaves that don't need custom chrome. |
@@ -530,7 +526,7 @@ pattern as `Panel`:
530
526
  | `Tabset.Trigger` | `button[data-dashfoo="tab"]` | The tab button: select on click, rename on double-click, draggable. Children override the label. |
531
527
  | `Tabset.RenameInput` | `input[data-dashfoo="tab-rename"]` | Inline rename editor; renders only while its tab is being renamed. |
532
528
  | `Tabset.CloseButton` | `button[data-dashfoo="tab-close"]` | Closes the tab with focus restore; hides when the tab isn't closable. |
533
- | `Tabset.Content` | `div[data-dashfoo="tabcontent"]` | The `role="tabpanel"` pane(s); honors `keepMounted`. Children render-prop overrides `renderTab`. |
529
+ | `Tabset.Content` | `div[data-dashfoo="tabcontent"]` | The `role="tabpanel"` pane(s); honors `keepMounted`. Children render-prop overrides `renderers.tab`. |
534
530
  | `Tabset.Toolbar` | `div[data-dashfoo="tabset-toolbar"]` | Trailing toolbar container. |
535
531
  | `Tabset.OverflowMenu` | menu button | Lists clipped tabs; hides when nothing overflows. |
536
532
  | `Tabset.Grip` | `button[data-dashfoo="tabset-grip"]` | Drag handle for the whole tabset; hides when tabset dragging is off. |
@@ -571,7 +567,7 @@ const MyTabset = ({ node }: { node: TabsetNode }) => (
571
567
  const MyLayout = () => {
572
568
  const store = useDashfooStore({ defaultModel });
573
569
  return (
574
- <Layout.Root dispatch={store.dispatch} model={store.model} renderTab={renderTab}>
570
+ <Layout.Root dispatch={store.dispatch} model={store.model} renderers={{ tab: renderTab }}>
575
571
  <Layout.DragLayer>
576
572
  <Layout.Rows node={store.model.layout} renderTabset={(node) => <MyTabset node={node} />} />
577
573
  </Layout.DragLayer>
@@ -613,6 +609,7 @@ type PanelTitleProps;
613
609
  // Layout primitives (build your own layout)
614
610
  Layout; // Layout.Root / Layout.DragLayer / Layout.Rows / Layout.Tabset
615
611
  type LayoutRootProps;
612
+ type LayoutRenderers;
616
613
  type LayoutDragLayerProps;
617
614
  type LayoutRowsProps;
618
615
  type LayoutTabsetProps;
@@ -664,3 +661,19 @@ from `@dashfoo/core`.
664
661
  ## License
665
662
 
666
663
  MIT
664
+
665
+ ### Closable tab semantics and refs
666
+
667
+ `data-dashfoo="tablist"` identifies the scrolling viewport. Inside it, a
668
+ semantic `role="tablist"` owns the tab triggers by id using `aria-owns`.
669
+ Close buttons and inline rename inputs are siblings in the accessibility tree,
670
+ so they remain independently accessible without becoming invalid tablist children.
671
+ Keep `Tabset.Trigger` inside `Tabset.Tab` and use the parts together; avoid
672
+ styling the internal semantic marker. Native compound parts forward refs on
673
+ React 18.3 and React 19. Docking itself remains pointer-only.
674
+
675
+ The built-in compact projection retains nested row identities so mounted widget state survives ordinary breakpoint changes. Entering compact mode from a maximized view, moving a tab between tabsets, or supplying a different tree can remount content; keep durable application state outside panel components. The lower-level `stackModel` helper flattens the tree, so hand-composed layouts using it can also remount nested panels.
676
+
677
+ `Tabset.Content` forwards its ref to the active panel, including when inactive panels are retained with `keepMounted`.
678
+
679
+ Existing floats remain overlays in compact mode. Their displayed bounds fit the viewport without changing saved geometry; float controls remain available to minimize or dock them back.
package/dist/index.d.ts CHANGED
@@ -52,10 +52,9 @@ type DashfooHandle = {
52
52
  selectTab: (tabsetId: string, index: number) => void;
53
53
  undo: () => void;
54
54
  };
55
- type DashfooLayoutProps = {
55
+ type DashfooLayoutCommonProps = {
56
56
  closableTabs?: boolean;
57
57
  components?: Record<string, TabComponent>;
58
- defaultModel?: Dashfoo;
59
58
  draggableTabs?: boolean;
60
59
  draggableTabsets?: boolean;
61
60
  editable?: boolean;
@@ -63,12 +62,10 @@ type DashfooLayoutProps = {
63
62
  floatable?: boolean;
64
63
  keepMounted?: boolean;
65
64
  maximizable?: boolean;
66
- model?: Dashfoo;
67
65
  onAction?: (action: Action) => Action | null;
68
66
  onActiveTabsetChange?: (tabsetId: string | undefined) => void;
69
67
  onMaximizedTabsetChange?: (tabsetId: string | undefined) => void;
70
68
  onModelChange?: (model: Dashfoo, action?: Action) => void;
71
- persist?: PersistInput;
72
69
  renamableTabs?: boolean;
73
70
  renderTabLabel?: (tab: TabNode) => ReactNode;
74
71
  renderTabsetToolbar?: (tabset: TabsetNode) => ReactNode;
@@ -79,9 +76,18 @@ type DashfooLayoutProps = {
79
76
  };
80
77
  snap?: SnapConfig;
81
78
  };
79
+ type DashfooLayoutProps = DashfooLayoutCommonProps & ({
80
+ defaultModel: Dashfoo;
81
+ model?: never;
82
+ persist?: PersistInput;
83
+ } | {
84
+ defaultModel?: never;
85
+ model: Dashfoo;
86
+ persist?: never;
87
+ });
82
88
  declare const DashfooLayout: import("react").ForwardRefExoticComponent<DashfooLayoutProps & import("react").RefAttributes<DashfooHandle>>;
83
89
  //#endregion
84
- //#region src/components/drag-root.d.ts
90
+ //#region src/components/dashfoo-drag-provider.d.ts
85
91
  declare const DashfooDragProvider: ({ children }: {
86
92
  children: ReactNode;
87
93
  }) => ReactNode;
@@ -96,33 +102,33 @@ declare const useExternalTabSource: ({ createTab, disabled, label }: ExternalTab
96
102
  ref: (element: Element | null) => void;
97
103
  };
98
104
  /**
99
- * Both drag readers are documented as working anywhere under the provider, which
100
- * includes a custom overlay mounted beside the layout rather than inside a drag
101
- * layer, so they read the root's actor. Outside a provider entirely there is no
102
- * actor to read and they report the empty state instead of throwing: a component
103
- * that renders both inside and outside a layout should not crash in one of them.
105
+ * Reads the root's actor, so it works from an overlay mounted beside the layout
106
+ * rather than inside a drag layer. Outside a provider it reports the empty state
107
+ * instead of throwing.
104
108
  */
105
109
  declare const useDragSubject: () => DragSubject | null;
106
110
  declare const useDropIntent: () => DropIntent | null;
107
111
  //#endregion
108
- //#region src/components/drag-adapter.d.ts
112
+ //#region src/components/drag-provider.d.ts
109
113
  type DragProviderProps = {
110
114
  children: ReactNode;
111
115
  onCommit?: (action: Action) => void;
112
116
  splitDock?: boolean;
113
117
  };
118
+ /**
119
+ * Mounts its own root when there is none above it. Decided on the first render:
120
+ * a root that disappears later means a torn-down tree, which `DragScope` reports.
121
+ */
122
+ declare const DragProvider: (props: DragProviderProps) => ReactNode;
114
123
  //#endregion
115
124
  //#region src/components/float-layer.d.ts
116
125
  type FloatLayerProps = {
117
126
  children: ReactNode;
118
127
  floats: Array<FloatNode>;
119
- /**
120
- * Accepted for backwards compatibility only. Floating panels now inherit
121
- * every global-derived capability from the layout store above them, so this
122
- * is no longer read; it disappears in the next major.
123
- */
128
+ /** Unread: floats inherit every global-derived capability from the layout store above them. */
124
129
  global?: GlobalAttributes;
125
130
  };
131
+ declare const FloatLayer: ({ children, floats }: FloatLayerProps) => ReactNode;
126
132
  //#endregion
127
133
  //#region src/hooks/layout-store.d.ts
128
134
  type LayoutState = {
@@ -161,67 +167,75 @@ type LayoutRootProps = Omit<ComponentProps<"div">, "children"> & {
161
167
  maximizable?: boolean;
162
168
  model: Dashfoo;
163
169
  renamableTabs?: boolean;
164
- renderTab: (tab: TabNode) => ReactNode;
165
- renderTabLabel?: (tab: TabNode) => ReactNode;
166
- renderTabsetToolbar?: (tabset: TabsetNode) => ReactNode;
170
+ renderers: LayoutRenderers;
167
171
  resizableSplits?: boolean;
168
172
  /** When false, the tree itself is frozen: no dragging, splitting or floating. Tabs stay closable and renamable. */
169
173
  restructurable?: boolean;
170
174
  rootRef?: Ref<HTMLDivElement>;
171
175
  snap?: SnapConfig;
172
176
  };
177
+ type LayoutRenderers = {
178
+ tab: (tab: TabNode) => ReactNode;
179
+ tabLabel?: (tab: TabNode) => ReactNode;
180
+ tabsetToolbar?: (tabset: TabsetNode) => ReactNode;
181
+ };
182
+ declare const LayoutRoot: ({ children, closableTabs, dispatch, draggableTabs, draggableTabsets, editable, floatable, keepMounted, maximizable, model, renamableTabs, renderers, resizableSplits, restructurable, rootRef, snap, style, ...props }: LayoutRootProps) => ReactNode;
173
183
  //#endregion
174
184
  //#region src/components/row-view.d.ts
175
185
  type RowViewProps = {
176
186
  node: RowNode;
177
187
  renderTabset?: (node: TabsetNode) => ReactNode;
178
188
  };
189
+ declare const RowView: ({ node, renderTabset }: RowViewProps) => ReactNode;
179
190
  //#endregion
180
191
  //#region src/components/tabset/tabset-view.d.ts
181
192
  type TabsetViewProps = {
182
193
  node: TabsetNode;
183
194
  };
195
+ declare const TabsetView: ({ node }: TabsetViewProps) => ReactNode;
184
196
  //#endregion
185
197
  //#region src/components/layout.d.ts
186
198
  declare const Layout: {
187
- readonly DragLayer: (props: DragProviderProps) => import("react").ReactNode;
188
- readonly FloatLayer: ({ children, floats }: FloatLayerProps) => import("react").ReactNode;
189
- readonly Root: ({ children, closableTabs, dispatch, draggableTabs, draggableTabsets, editable, floatable, keepMounted, maximizable, model, renamableTabs, renderTab, renderTabLabel, renderTabsetToolbar, resizableSplits, restructurable, rootRef, snap, style, ...props }: LayoutRootProps) => import("react").ReactNode;
190
- readonly Rows: ({ node, renderTabset }: RowViewProps) => import("react").ReactNode;
191
- readonly Tabset: ({ node }: TabsetViewProps) => import("react").ReactNode;
199
+ readonly DragLayer: typeof DragProvider;
200
+ readonly FloatLayer: typeof FloatLayer;
201
+ readonly Root: typeof LayoutRoot;
202
+ readonly Rows: typeof RowView;
203
+ readonly Tabset: typeof TabsetView;
192
204
  };
193
205
  //#endregion
194
- //#region src/components/panel.d.ts
195
- type PanelRootProps = ComponentProps<"div">;
196
- type PanelHeaderProps = ComponentProps<"div">;
206
+ //#region src/components/panel-badge.d.ts
207
+ type PanelBadgeProps = ComponentProps<"span">;
208
+ //#endregion
209
+ //#region src/components/panel-body.d.ts
197
210
  type PanelBodyProps = ComponentProps<"div">;
198
- type PanelTitleProps = ComponentProps<"span">;
211
+ //#endregion
212
+ //#region src/components/panel-header.d.ts
213
+ type PanelHeaderProps = ComponentProps<"div">;
214
+ //#endregion
215
+ //#region src/components/panel-icon.d.ts
199
216
  type PanelIconProps = ComponentProps<"span">;
200
- type PanelBadgeProps = ComponentProps<"span">;
217
+ //#endregion
218
+ //#region src/components/panel-root.d.ts
219
+ type PanelRootProps = ComponentProps<"div">;
220
+ //#endregion
221
+ //#region src/components/panel-title.d.ts
222
+ type PanelTitleProps = ComponentProps<"span">;
223
+ //#endregion
224
+ //#region src/components/panel.d.ts
201
225
  declare const Panel: {
202
- readonly Badge: (props: PanelBadgeProps) => ReactNode;
203
- readonly Body: (props: PanelBodyProps) => ReactNode;
204
- readonly Header: (props: PanelHeaderProps) => ReactNode;
205
- readonly Icon: (props: PanelIconProps) => ReactNode;
206
- readonly Root: (props: PanelRootProps) => ReactNode;
207
- readonly Title: (props: PanelTitleProps) => ReactNode;
226
+ readonly Badge: import("react").ForwardRefExoticComponent<Omit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLSpanElement>, HTMLSpanElement>, "ref"> & import("react").RefAttributes<HTMLSpanElement>>;
227
+ readonly Body: import("react").ForwardRefExoticComponent<Omit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref"> & import("react").RefAttributes<HTMLDivElement>>;
228
+ readonly Header: import("react").ForwardRefExoticComponent<Omit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref"> & import("react").RefAttributes<HTMLDivElement>>;
229
+ readonly Icon: import("react").ForwardRefExoticComponent<Omit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLSpanElement>, HTMLSpanElement>, "ref"> & import("react").RefAttributes<HTMLSpanElement>>;
230
+ readonly Root: import("react").ForwardRefExoticComponent<Omit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref"> & import("react").RefAttributes<HTMLDivElement>>;
231
+ readonly Title: import("react").ForwardRefExoticComponent<Omit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLSpanElement>, HTMLSpanElement>, "ref"> & import("react").RefAttributes<HTMLSpanElement>>;
208
232
  };
209
233
  //#endregion
210
- //#region src/components/tabset/tabset-tab-controls.d.ts
211
- type TabsetRenameInputProps = ComponentProps<"input">;
212
- type TabsetCloseButtonProps = ComponentProps<"button">;
213
- //#endregion
214
234
  //#region src/components/tabset/tabset-content.d.ts
215
235
  type TabsetContentProps = Omit<ComponentProps<"div">, "children"> & {
216
236
  children?: (tab: TabNode) => ReactNode;
217
237
  };
218
238
  //#endregion
219
- //#region src/components/tabset/tabset-toolbar.d.ts
220
- type TabsetToolbarProps = ComponentProps<"div">;
221
- type TabsetGripProps = ComponentProps<"button">;
222
- type TabsetMaximizeButtonProps = ComponentProps<"button">;
223
- type TabsetFloatButtonProps = ComponentProps<"button">;
224
- //#endregion
225
239
  //#region src/components/tabset/tabset-root.d.ts
226
240
  type TabsetRootProps = ComponentProps<"div"> & {
227
241
  node: TabsetNode;
@@ -233,28 +247,41 @@ type TabsetTabProps = ComponentProps<"span"> & {
233
247
  };
234
248
  type TabsetTriggerProps = ComponentProps<"button">;
235
249
  //#endregion
250
+ //#region src/components/tabset/tabset-overflow-menu.d.ts
251
+ declare const TabsetOverflowMenu: () => ReactNode;
252
+ //#endregion
253
+ //#region src/components/tabset/tabset-rename-input.d.ts
254
+ type TabsetRenameInputProps = ComponentProps<"input">;
255
+ type TabsetCloseButtonProps = ComponentProps<"button">;
256
+ //#endregion
236
257
  //#region src/components/tabset/tabset-tablist.d.ts
237
258
  type TabsetTabStripProps = ComponentProps<"div">;
238
259
  type TabsetTablistProps = ComponentProps<"div">;
239
260
  //#endregion
261
+ //#region src/components/tabset/tabset-toolbar.d.ts
262
+ type TabsetToolbarProps = ComponentProps<"div">;
263
+ type TabsetGripProps = ComponentProps<"button">;
264
+ type TabsetMaximizeButtonProps = ComponentProps<"button">;
265
+ type TabsetFloatButtonProps = ComponentProps<"button">;
266
+ //#endregion
240
267
  //#region src/components/tabset/tabset.d.ts
241
268
  declare const Tabset: {
242
- readonly CloseButton: ({ children, onClick, ...props }: TabsetCloseButtonProps) => import("react").ReactNode;
243
- readonly Content: ({ children, style, ...props }: TabsetContentProps) => import("react").ReactNode;
244
- readonly FloatButton: ({ children, onClick, ...props }: TabsetFloatButtonProps) => import("react").ReactNode;
245
- readonly Grip: ({ children, ref: userRef, ...props }: TabsetGripProps) => import("react").ReactNode;
246
- readonly MaximizeButton: ({ children, onClick, ...props }: TabsetMaximizeButtonProps) => import("react").ReactNode;
247
- readonly OverflowMenu: () => import("react").ReactNode;
248
- readonly RenameInput: (props: TabsetRenameInputProps) => import("react").ReactNode;
249
- readonly Root: ({ children, node, ref: userRef, style, ...props }: TabsetRootProps) => import("react").ReactNode;
250
- readonly Tab: ({ children, ref: userRef, tab, ...props }: TabsetTabProps) => import("react").ReactNode;
251
- readonly Tablist: ({ onKeyDown, ref: userRef, style, ...props }: TabsetTablistProps) => import("react").ReactNode;
252
- readonly TabStrip: ({ style, ...props }: TabsetTabStripProps) => import("react").ReactNode;
253
- readonly Toolbar: ({ style, ...props }: TabsetToolbarProps) => import("react").ReactNode;
254
- readonly Trigger: ({ children, onClick, onDoubleClick, ref: userRef, ...props }: TabsetTriggerProps) => import("react").ReactNode;
269
+ readonly CloseButton: import("react").ForwardRefExoticComponent<Omit<import("react").DetailedHTMLProps<import("react").ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>, "ref"> & import("react").RefAttributes<HTMLButtonElement>>;
270
+ readonly Content: import("react").ForwardRefExoticComponent<Omit<TabsetContentProps, "ref"> & import("react").RefAttributes<HTMLDivElement>>;
271
+ readonly FloatButton: import("react").ForwardRefExoticComponent<Omit<import("react").DetailedHTMLProps<import("react").ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>, "ref"> & import("react").RefAttributes<HTMLButtonElement>>;
272
+ readonly Grip: import("react").ForwardRefExoticComponent<Omit<import("react").DetailedHTMLProps<import("react").ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>, "ref"> & import("react").RefAttributes<HTMLButtonElement>>;
273
+ readonly MaximizeButton: import("react").ForwardRefExoticComponent<Omit<import("react").DetailedHTMLProps<import("react").ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>, "ref"> & import("react").RefAttributes<HTMLButtonElement>>;
274
+ readonly OverflowMenu: typeof TabsetOverflowMenu;
275
+ readonly RenameInput: import("react").ForwardRefExoticComponent<Omit<import("react").DetailedHTMLProps<import("react").InputHTMLAttributes<HTMLInputElement>, HTMLInputElement>, "ref"> & import("react").RefAttributes<HTMLInputElement>>;
276
+ readonly Root: import("react").ForwardRefExoticComponent<Omit<TabsetRootProps, "ref"> & import("react").RefAttributes<HTMLDivElement>>;
277
+ readonly Tab: import("react").ForwardRefExoticComponent<Omit<TabsetTabProps, "ref"> & import("react").RefAttributes<HTMLSpanElement>>;
278
+ readonly Tablist: import("react").ForwardRefExoticComponent<Omit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref"> & import("react").RefAttributes<HTMLDivElement>>;
279
+ readonly TabStrip: import("react").ForwardRefExoticComponent<Omit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref"> & import("react").RefAttributes<HTMLDivElement>>;
280
+ readonly Toolbar: import("react").ForwardRefExoticComponent<Omit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref"> & import("react").RefAttributes<HTMLDivElement>>;
281
+ readonly Trigger: import("react").ForwardRefExoticComponent<Omit<import("react").DetailedHTMLProps<import("react").ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>, "ref"> & import("react").RefAttributes<HTMLButtonElement>>;
255
282
  };
256
283
  //#endregion
257
- //#region src/components/tab-overflow.d.ts
284
+ //#region src/components/tab-overflow-menu.d.ts
258
285
  type OverflowItem = {
259
286
  id: string;
260
287
  name: string;
@@ -271,11 +298,12 @@ type TabsetState = {
271
298
  isMaximized: boolean;
272
299
  node: TabsetNode;
273
300
  overflowItems: Array<OverflowItem>;
301
+ /** The tab a `closeTab` is waiting on, so a vetoed close cannot restore focus. */
302
+ pendingCloseTabId: string | null;
274
303
  registerRenameInput: () => () => void;
275
304
  registerTablist: (element: HTMLDivElement | null) => void;
276
305
  renameInputCount: number;
277
306
  renameTab: (tabId: string, name: string) => void;
278
- restoreFocus: boolean;
279
307
  selectOverflowTab: (tabId: string) => void;
280
308
  selectTab: (index: number, options?: {
281
309
  focus?: boolean;
@@ -341,7 +369,9 @@ type UseDashfooStoreOptions = {
341
369
  onMaximizedTabsetChange?: (tabsetId: string | undefined) => void;
342
370
  onModelChange?: (model: Dashfoo, action?: Action) => void;
343
371
  };
372
+ /** The mode is latched on the first render; running both sources leaves the
373
+ * unread one describing a document nobody rendered. */
344
374
  declare const useDashfooStore: (options: UseDashfooStoreOptions) => DashfooStore;
345
375
  //#endregion
346
- export { type Breakpoint, DashfooDragProvider, type DashfooHandle, DashfooLayout, type DashfooLayoutProps, type DashfooStore, type ExternalTabSourceOptions, Layout, type DragProviderProps as LayoutDragLayerProps, type FloatLayerProps as LayoutFloatLayerProps, 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 TabsetFloatButtonProps, 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 };
376
+ export { type Breakpoint, DashfooDragProvider, type DashfooHandle, DashfooLayout, type DashfooLayoutCommonProps, type DashfooLayoutProps, type DashfooStore, type ExternalTabSourceOptions, Layout, type DragProviderProps as LayoutDragLayerProps, type FloatLayerProps as LayoutFloatLayerProps, type LayoutRenderers, 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 TabsetFloatButtonProps, 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 };
347
377
  //# 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/float-layer.tsx","../src/hooks/layout-store.ts","../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/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/dashfoo-drag-provider.tsx","../src/hooks/drag-hooks.tsx","../src/components/drag-provider.tsx","../src/components/float-layer.tsx","../src/hooks/layout-store.ts","../src/components/layout-root.tsx","../src/components/row-view.tsx","../src/components/tabset/tabset-view.tsx","../src/components/layout.tsx","../src/components/panel-badge.tsx","../src/components/panel-body.tsx","../src/components/panel-header.tsx","../src/components/panel-icon.tsx","../src/components/panel-root.tsx","../src/components/panel-title.tsx","../src/components/panel.tsx","../src/components/tabset/tabset-content.tsx","../src/components/tabset/tabset-root.tsx","../src/components/tabset/tabset-tab.tsx","../src/components/tabset/tabset-overflow-menu.tsx","../src/components/tabset/tabset-rename-input.tsx","../src/components/tabset/tabset-tablist.tsx","../src/components/tabset/tabset-toolbar.tsx","../src/components/tabset/tabset.ts","../src/components/tab-overflow-menu.tsx","../src/components/tabset/tabset-store.ts","../src/hooks/responsive.ts","../src/hooks/store.ts"],"mappings":"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"}