react-dockable-desktop 4.0.0 → 4.1.1
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 +100 -14
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -134,6 +134,50 @@ export default function EditorPanel() {
|
|
|
134
134
|
}
|
|
135
135
|
```
|
|
136
136
|
|
|
137
|
+
### Lifecycle callbacks
|
|
138
|
+
|
|
139
|
+
`useFormContainer()` exposes a full push-based lifecycle API — no subscriptions to global state required:
|
|
140
|
+
|
|
141
|
+
```tsx
|
|
142
|
+
import { useFormContainer } from 'react-dockable-desktop';
|
|
143
|
+
import { useEffect } from 'react';
|
|
144
|
+
|
|
145
|
+
export default function MapPanel() {
|
|
146
|
+
const {
|
|
147
|
+
containerType, // current container type at mount: 'dockable-panel' | 'floating-window'
|
|
148
|
+
onActivate, // fires when this panel becomes the globally active panel
|
|
149
|
+
onDeactivate, // fires when this panel loses active status (or is destroyed)
|
|
150
|
+
onContainerTypeChange, // fires when the panel moves between docked and floating
|
|
151
|
+
onClose, // fires just before the panel is destroyed
|
|
152
|
+
requestMinimize, // imperatively minimize this panel to the taskbar
|
|
153
|
+
getDimensions, // synchronously read current {width, height} — null until first layout
|
|
154
|
+
} = useFormContainer();
|
|
155
|
+
|
|
156
|
+
useEffect(() => {
|
|
157
|
+
const unsub = [
|
|
158
|
+
onActivate?.(() => {
|
|
159
|
+
// e.g. resume animation, reload data
|
|
160
|
+
const dims = getDimensions?.();
|
|
161
|
+
console.log('active, size:', dims);
|
|
162
|
+
}),
|
|
163
|
+
onDeactivate?.(() => {
|
|
164
|
+
// e.g. pause background work
|
|
165
|
+
}),
|
|
166
|
+
onContainerTypeChange?.((type) => {
|
|
167
|
+
// type === 'floating-window' | 'dockable-panel'
|
|
168
|
+
// e.g. trigger map.resize() after layout change
|
|
169
|
+
}),
|
|
170
|
+
onClose?.(() => {
|
|
171
|
+
// final cleanup — unsubscribe from external stores
|
|
172
|
+
}),
|
|
173
|
+
];
|
|
174
|
+
return () => unsub.forEach(fn => fn?.());
|
|
175
|
+
}, []);
|
|
176
|
+
|
|
177
|
+
return <div>Map</div>;
|
|
178
|
+
}
|
|
179
|
+
```
|
|
180
|
+
|
|
137
181
|
---
|
|
138
182
|
|
|
139
183
|
## Hooks
|
|
@@ -146,7 +190,7 @@ Call these inside any component within the `DockableDesktopProvider` tree:
|
|
|
146
190
|
| `useWindowManagerState(selector?)` | `WindowState` or selected slice | Read layout, floating windows, active panel ID |
|
|
147
191
|
| `usePanelActions()` | `PanelActions` | Open modal overlays and left/right side drawers |
|
|
148
192
|
| `usePanelContext()` | `{ publish, subscribe }` | Inter-panel typed event bus |
|
|
149
|
-
| `useFormContainer()` | `FormContainerContract` | Dirty state, close guards, dynamic
|
|
193
|
+
| `useFormContainer()` | `FormContainerContract` | Dirty state, close guards, dynamic title/icon, lifecycle callbacks (activate, deactivate, container-type change), imperative minimize, sync dimensions |
|
|
150
194
|
| `usePanelId()` | `string` | The panel's own instance ID — no prop drilling needed |
|
|
151
195
|
| `useToolbar()` | `ToolbarContextValue` | Read/write Toolbar state (active tool, modifiers) from any panel |
|
|
152
196
|
| `useSidebar()` | `SidebarContextValue` | Open/close Sidebar tabs from any component in the Sidebar tree |
|
|
@@ -203,6 +247,47 @@ workspace.setDirection('ltr' | 'rtl')
|
|
|
203
247
|
|
|
204
248
|
---
|
|
205
249
|
|
|
250
|
+
## FormContainerContract Reference
|
|
251
|
+
|
|
252
|
+
`useFormContainer()` returns a `FormContainerContract` with these members:
|
|
253
|
+
|
|
254
|
+
| Member | Type | Description |
|
|
255
|
+
| :--- | :--- | :--- |
|
|
256
|
+
| `requestClose(options?)` | `(options?: CloseOptions) => void` | Request the container to close; respects dirty state and close guards |
|
|
257
|
+
| `setDirty(dirty, options?)` | `(dirty: boolean) => void` | Mark unsaved changes; triggers confirmation dialog on close |
|
|
258
|
+
| `onCloseRequested(handler)` | `(handler) => unsubscribe` | Register a close guard; return `false` to block the close |
|
|
259
|
+
| `setTitle(title)` | `(title) => void` | Change the tab/window title dynamically |
|
|
260
|
+
| `setIcon?(icon)` | `(icon: ReactNode) => void` | Change the tab/window icon dynamically |
|
|
261
|
+
| `containerType?` | `ContainerType` | Container type **at mount time** — see `onContainerTypeChange` for live updates |
|
|
262
|
+
| `instanceId` | `string` | The panel's instance ID |
|
|
263
|
+
| `onClose?(handler)` | `(handler) => unsubscribe` | Subscribe to panel destruction |
|
|
264
|
+
| `onMinimize?(handler)` | `(handler) => unsubscribe` | Subscribe to minimize events |
|
|
265
|
+
| `onRestore?(handler)` | `(handler) => unsubscribe` | Subscribe to restore-from-taskbar events |
|
|
266
|
+
| `onResize?(handler)` | `(handler) => unsubscribe` | Subscribe to resize events; handler receives `(width, height)` |
|
|
267
|
+
| `requestMinimize?()` | `() => void` | Imperatively minimize this panel to the taskbar |
|
|
268
|
+
| `getDimensions?()` | `() => {width, height} \| null` | Synchronously read the current rendered size; `null` until first layout |
|
|
269
|
+
| `onActivate?(handler)` | `(handler) => unsubscribe` | Subscribe to this panel becoming the globally active panel |
|
|
270
|
+
| `onDeactivate?(handler)` | `(handler) => unsubscribe` | Subscribe to this panel losing active status; also fires on destruction |
|
|
271
|
+
| `onContainerTypeChange?(handler)` | `(handler) => unsubscribe` | Subscribe to dock↔float transitions; handler receives the new `ContainerType` |
|
|
272
|
+
|
|
273
|
+
### ContainerType
|
|
274
|
+
|
|
275
|
+
```ts
|
|
276
|
+
type ContainerType =
|
|
277
|
+
| 'dockable-panel' // panel is docked in the grid
|
|
278
|
+
| 'floating-window' // panel is in a detached floating window
|
|
279
|
+
| 'left-panel' // rendered inside the left side drawer
|
|
280
|
+
| 'right-panel' // rendered inside the right side drawer
|
|
281
|
+
| 'modal' // rendered inside a modal overlay
|
|
282
|
+
| 'standalone'; // rendered outside the Window Manager (default / no context)
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
`containerType` on the contract reflects the state **at mount time**. Subscribe to `onContainerTypeChange` to get notified whenever the panel moves between `'dockable-panel'` and `'floating-window'`. Minimize/restore cycles do **not** fire `onContainerTypeChange`; use `onMinimize`/`onRestore` for those.
|
|
286
|
+
|
|
287
|
+
All `on*` subscribers return an unsubscribe function. Call it (or return it from `useEffect`) to avoid leaks.
|
|
288
|
+
|
|
289
|
+
---
|
|
290
|
+
|
|
206
291
|
## Layout Persistence
|
|
207
292
|
|
|
208
293
|
```ts
|
|
@@ -313,25 +398,26 @@ All built-in skins include dark and light variants. Create your own skin by over
|
|
|
313
398
|
|
|
314
399
|
## What's New
|
|
315
400
|
|
|
316
|
-
### v4.3.0
|
|
317
|
-
- **Workspace corner anchor zones** — drag any panel (floating or docked tab) to a workspace corner to pin it there. Four 80×80 px snap zones appear during drag; same visual style as the inner panel drop zones. Anchored windows stack with 8 px gaps, uncapped, and reposition automatically on viewport resize.
|
|
318
|
-
- **`anchor` option on `openPanel` and `floatPanel`** — spawn a new floating window pre-anchored: `openPanel('id', 'comp', { initialTarget: 'floating', anchor: 'top-right' })` or `floatPanel('id', undefined, 'bottom-left')`.
|
|
319
|
-
- **`defaultAnchor` in panel registry** — set `defaultAnchor: 'top-left'` in `PanelRegistryEntry.defaultOptions` so every instance of that component opens anchored.
|
|
320
|
-
- **Full RTL support** — floating window drop zones, edge triggers, and corner snap zones all mirror correctly when `dir="rtl"`.
|
|
321
|
-
- **Removed:** `openPanel` options `stickyRight` / `stickyBottom` (replaced by `anchor`). Saved layouts are automatically migrated.
|
|
322
|
-
|
|
323
|
-
### v4.2.0
|
|
324
|
-
- **Toast Notifications** — zero-dependency `toast.info/success/warning/error/promise()` singleton. `<ToastContainer>` renders via `createPortal`; supports configurable position, width, max-visible queue, pause-on-hover, opt-in progress bar, and auto-dismiss. `ToastAdapter` lets you delegate to Ant Design, MUI, Sonner, or any other notification library without changing call sites. All colors inherit the active skin automatically.
|
|
325
|
-
|
|
326
401
|
### v4.1.0
|
|
327
|
-
-
|
|
328
|
-
- **`
|
|
329
|
-
-
|
|
402
|
+
- **`onActivate` / `onDeactivate` on `FormContainerContract`** — push-based callbacks fired when a panel gains or loses globally active status; no need to subscribe to `useWindowManagerState` and diff `activePanelId` inside each panel.
|
|
403
|
+
- **`onContainerTypeChange` on `FormContainerContract`** — fires with the new `ContainerType` (`'dockable-panel'` | `'floating-window'`) whenever the panel transitions between docked and floating; does not fire during minimize/restore cycles.
|
|
404
|
+
- **`getDimensions()` on `FormContainerContract`** — synchronous getter returning the current `{width, height}` of the panel (or `null` before first layout); reads from the same `ResizeObserver` that drives `onResize`.
|
|
405
|
+
- **`requestMinimize()` on `FormContainerContract`** — imperative counterpart to `requestClose()`; minimizes the panel without needing `useWindowManagerActions`.
|
|
406
|
+
- **`'floating-window'` ContainerType value** — `containerType` now correctly reports `'dockable-panel'` for docked panels and `'floating-window'` for panels in detached floating windows.
|
|
330
407
|
|
|
331
408
|
### v4.0.0
|
|
332
409
|
- **Built-in `<ContextMenu>`** — zero-dependency context menu, portal-rendered and styled with design tokens. No extra package or CSS import needed.
|
|
333
410
|
- **`ContextMenuAdapter` interface** — swap the default menu for your own design-system implementation via `<WindowManager contextMenuAdapter={...} />`.
|
|
334
411
|
- **New exports** — `ContextMenu`, `DefaultContextMenuAdapter`, `ContextMenuHandle`, `ContextMenuAdapter`, `ShowContextMenuOptions`.
|
|
412
|
+
- **Panel Overlay system** — `PanelOverlayRoot`, `PanelToolbar`, `PanelFloatingWindow`, and `usePanelFloatingWindowManager` bring per-panel toolbars and dynamically-spawned corner-anchored floating info windows to any panel.
|
|
413
|
+
- **`usePanelFloatingWindowManager()`** — imperative hook for opening N named floating windows from data or event handlers; all windows share z-ordering, drag, and corner-docking infrastructure.
|
|
414
|
+
- **Toolbar primitives** — `ToolbarButton`, `ToolbarToggle`, `PanelToolbarSeparator`, `ToolbarSpacer`, `ToolbarCenter`, `ToolbarSearchInput` compose panel toolbar content.
|
|
415
|
+
- **Toast Notifications** — zero-dependency `toast.info/success/warning/error/promise()` singleton. `<ToastContainer>` renders via `createPortal`; supports configurable position, width, max-visible queue, pause-on-hover, opt-in progress bar, and auto-dismiss. `ToastAdapter` lets you delegate to Ant Design, MUI, Sonner, or any other notification library without changing call sites.
|
|
416
|
+
- **Workspace corner anchor zones** — drag any panel (floating or docked tab) to a workspace corner to pin it there. Four 80×80 px snap zones appear during drag; anchored windows stack with 8 px gaps and reposition automatically on viewport resize.
|
|
417
|
+
- **`anchor` option on `openPanel` and `floatPanel`** — spawn a new floating window pre-anchored: `openPanel('id', 'comp', { initialTarget: 'floating', anchor: 'top-right' })` or `floatPanel('id', undefined, 'bottom-left')`.
|
|
418
|
+
- **`defaultAnchor` in panel registry** — set `defaultAnchor: 'top-left'` in `PanelRegistryEntry.defaultOptions` so every instance of that component opens anchored.
|
|
419
|
+
- **Full RTL support** — floating window drop zones, edge triggers, and corner snap zones all mirror correctly when `dir="rtl"`.
|
|
420
|
+
- **Removed:** `openPanel` options `stickyRight` / `stickyBottom` (replaced by `anchor`). Saved layouts are automatically migrated.
|
|
335
421
|
|
|
336
422
|
### v3.2.0
|
|
337
423
|
- **Per-skin active state design language** — Sidebar tabs and Toolbar buttons now use a per-skin visual pattern (transparent bar, floating chip, pill, line, neon glow), driven by new CSS design tokens — fully overridable in custom skins. CSS-only, no API changes.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-dockable-desktop",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.1.1",
|
|
4
4
|
"description": "A premium, state-of-the-art window manager and dockable layout engine for React. Supports fluid grid splits, tabbed groups, floating resizable windows, zero-unmount state preservation, context menus, and internationalization.",
|
|
5
5
|
"main": "dist/index.cjs",
|
|
6
6
|
"module": "dist/index.js",
|