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.
Files changed (2) hide show
  1. package/README.md +100 -14
  2. 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 panel title/icon |
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
- - **Panel Overlay system** `PanelOverlayRoot`, `PanelToolbar`, `PanelFloatingWindow`, and `usePanelFloatingWindowManager` bring per-panel toolbars and dynamically-spawned corner-anchored floating info windows to any panel.
328
- - **`usePanelFloatingWindowManager()`** — imperative hook for opening N named floating windows from data or event handlers; all windows share z-ordering, drag, and corner-docking infrastructure.
329
- - **Toolbar primitives**`ToolbarButton`, `ToolbarToggle`, `PanelToolbarSeparator`, `ToolbarSpacer`, `ToolbarCenter`, `ToolbarSearchInput` compose panel toolbar content.
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.0.0",
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",