react-dockable-desktop 1.3.0 β 2.1.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 +73 -301
- package/dist/index.cjs +3 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +293 -67
- package/dist/index.d.ts +293 -67
- package/dist/index.js +3 -1
- package/dist/index.js.map +1 -1
- package/package.json +9 -2
package/README.md
CHANGED
|
@@ -1,103 +1,75 @@
|
|
|
1
1
|
# React Dockable Desktop
|
|
2
2
|
|
|
3
|
-
[](#)
|
|
5
|
-
[](https://felipecarrillo100.github.io/react-dockable-desktop/)
|
|
3
|
+
[](https://www.npmjs.com/package/react-dockable-desktop)
|
|
4
|
+
[](#license)
|
|
5
|
+
[](https://felipecarrillo100.github.io/react-dockable-desktop/demo/)
|
|
6
|
+
[](https://felipecarrillo100.github.io/react-dockable-desktop/)
|
|
6
7
|
|
|
7
|
-
A
|
|
8
|
+
A premium React window manager and dockable layout engine. Fluid split-docking grids, resizable floating windows, dynamic taskbars, and tabbed panels with **zero-unmount DOM persistence** and **built-in i18n/RTL support**.
|
|
8
9
|
|
|
9
|
-
[
|
|
10
|
+
**[Full Documentation](https://felipecarrillo100.github.io/react-dockable-desktop/)** |
|
|
11
|
+
**[Live Demo](https://felipecarrillo100.github.io/react-dockable-desktop/demo/)** |
|
|
12
|
+
**[API Reference](https://felipecarrillo100.github.io/react-dockable-desktop/api/)**
|
|
10
13
|
|
|
11
14
|
---
|
|
12
15
|
|
|
13
|
-
##
|
|
16
|
+
## Key Features
|
|
14
17
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
* **π Initial Letter Hover Miniatures**: Miniature preview popovers automatically display the uppercase first character of the panel title inside a theme-responsive grayish layout fallback for panels with disabled live previews.
|
|
24
|
-
* **π Glassmorphic & Modern Styling**: Sleek dark mode aesthetics, interactive micro-animations, and fluid transitions.
|
|
25
|
-
* **π Inter-Panel Pub/Sub Event Bus**: A robust messaging system for lightweight, decoupled communication between active panels.
|
|
18
|
+
- **Dockable Splits & Tab Grid** β drag panels to split screens or group them into tabbed containers
|
|
19
|
+
- **Workspace Edge Docking** β drag to outer edges to dock as full-width/height columns or rows
|
|
20
|
+
- **Floating Windows** β pop panels into resizable floating windows with maximize and minimize
|
|
21
|
+
- **Zero-Unmount DOM Persistence** β WebGL, maps, terminals, and stateful forms keep their DOM node and state when moved
|
|
22
|
+
- **i18n & RTL** β full Right-to-Left layout support with automatic `dir="rtl"` detection
|
|
23
|
+
- **Inter-Panel Pub/Sub** β decoupled lightweight messaging between active panels
|
|
24
|
+
- **Imperative API** β `WorkspaceClient` lets you open, close, focus, and serialize panels from anywhere outside React
|
|
25
|
+
- **Layout Serialization** β save/restore the full workspace layout as a JSON string
|
|
26
26
|
|
|
27
27
|
---
|
|
28
28
|
|
|
29
|
-
##
|
|
29
|
+
## Installation
|
|
30
30
|
|
|
31
31
|
```bash
|
|
32
32
|
npm install react-dockable-desktop replace-react-contexify
|
|
33
33
|
```
|
|
34
34
|
|
|
35
|
-
|
|
35
|
+
Import styles in your entry file:
|
|
36
36
|
|
|
37
|
-
```
|
|
37
|
+
```ts
|
|
38
38
|
import 'replace-react-contexify/styles.css';
|
|
39
39
|
import 'react-dockable-desktop/styles.css';
|
|
40
40
|
```
|
|
41
41
|
|
|
42
42
|
---
|
|
43
43
|
|
|
44
|
-
##
|
|
45
|
-
|
|
46
|
-
The project includes two built-in demo setups to explore and test the window manager layout features:
|
|
47
|
-
|
|
48
|
-
### 1. Leaflet & Monaco Open Source Demo (Default)
|
|
49
|
-
A clean, lightweight dashboard demo suitable for public deployment. It showcases Leaflet 2D/3D map integration (with dynamic CARTO Light/Dark tile styles mapping to dashboard theme switches) and Monaco Editor panels.
|
|
50
|
-
```bash
|
|
51
|
-
npm run dev
|
|
52
|
-
```
|
|
53
|
-
|
|
54
|
-
### 2. LuciadRIA Earth 3D Demo (Isolated)
|
|
55
|
-
An isolated sandbox dashboard demonstrating premium 3D Earth visualizations in the `EPSG:4978` reference reference frame using LuciadRIA. *Note: Requires a valid LuciadRIA developer license locally to run.*
|
|
56
|
-
```bash
|
|
57
|
-
npm run dev:ria
|
|
58
|
-
```
|
|
59
|
-
|
|
60
|
-
---
|
|
61
|
-
|
|
62
|
-
## π οΈ Getting Started
|
|
44
|
+
## Quick Start
|
|
63
45
|
|
|
64
46
|
### 1. Create a WorkspaceClient
|
|
65
47
|
|
|
66
|
-
```
|
|
48
|
+
```ts
|
|
67
49
|
import { WorkspaceClient } from 'react-dockable-desktop';
|
|
68
|
-
import
|
|
50
|
+
import MapPanel from './panels/MapPanel';
|
|
69
51
|
import EditorPanel from './panels/EditorPanel';
|
|
70
52
|
|
|
71
53
|
export const client = new WorkspaceClient({
|
|
72
54
|
panels: {
|
|
73
|
-
|
|
74
|
-
editor:
|
|
55
|
+
map: { component: MapPanel, defaultOptions: { title: 'Map View' } },
|
|
56
|
+
editor: { component: EditorPanel, defaultOptions: { title: 'Editor' } },
|
|
75
57
|
},
|
|
76
|
-
// Restore last layout, or null for an empty canvas
|
|
77
58
|
initialState: localStorage.getItem('workspace-layout'),
|
|
78
59
|
});
|
|
79
60
|
```
|
|
80
61
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
### 2. Set Up the Provider
|
|
62
|
+
### 2. Mount the Provider
|
|
84
63
|
|
|
85
|
-
```
|
|
86
|
-
import
|
|
87
|
-
import {
|
|
88
|
-
WindowManagerProvider,
|
|
89
|
-
WindowManager,
|
|
90
|
-
PanelProvider,
|
|
91
|
-
ModalStackRenderer,
|
|
92
|
-
SidePanelRenderer,
|
|
93
|
-
} from 'react-dockable-desktop';
|
|
64
|
+
```tsx
|
|
65
|
+
import { WindowManagerProvider, WindowManager, PanelProvider, ModalStackRenderer, SidePanelRenderer } from 'react-dockable-desktop';
|
|
94
66
|
import { client } from './workspaceClient';
|
|
95
67
|
|
|
96
68
|
function App() {
|
|
97
69
|
return (
|
|
98
70
|
<WindowManagerProvider client={client}>
|
|
99
71
|
<PanelProvider>
|
|
100
|
-
<div style={{ width: '100vw', height: '100vh'
|
|
72
|
+
<div style={{ width: '100vw', height: '100vh' }}>
|
|
101
73
|
<WindowManager />
|
|
102
74
|
</div>
|
|
103
75
|
<ModalStackRenderer />
|
|
@@ -106,280 +78,80 @@ function App() {
|
|
|
106
78
|
</WindowManagerProvider>
|
|
107
79
|
);
|
|
108
80
|
}
|
|
109
|
-
|
|
110
|
-
export default App;
|
|
111
81
|
```
|
|
112
82
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
---
|
|
116
|
-
|
|
117
|
-
## π Internationalization (i18n)
|
|
118
|
-
|
|
119
|
-
`react-dockable-desktop` is built with dynamic translation in mind. Titles and context menus can accept either raw `string` values or a structured descriptor object resembling `ContextMenuPredefinedMessage`.
|
|
83
|
+
### 3. Open Panels Imperatively
|
|
120
84
|
|
|
121
|
-
|
|
85
|
+
```ts
|
|
86
|
+
// From anywhere outside React:
|
|
87
|
+
client.openPanel('map-1', 'map', { title: 'Satellite View' });
|
|
88
|
+
client.focusPanel('map-1');
|
|
89
|
+
client.saveLayout();
|
|
122
90
|
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
defaultMessage?: string;
|
|
127
|
-
values?: Record<string, string | number>;
|
|
128
|
-
}
|
|
129
|
-
```
|
|
130
|
-
|
|
131
|
-
### Integrating custom formatters (e.g., `react-intl`)
|
|
132
|
-
|
|
133
|
-
To route messages through your application's translation engine, pass a `formatMessage` callback to `WorkspaceClient`:
|
|
134
|
-
|
|
135
|
-
```typescript
|
|
136
|
-
const client = new WorkspaceClient({
|
|
137
|
-
panels: { ... },
|
|
138
|
-
formatMessage: (msg) => intl.formatMessage({ id: msg.id, defaultMessage: msg.defaultMessage }, msg.values),
|
|
139
|
-
});
|
|
140
|
-
|
|
141
|
-
function App() {
|
|
142
|
-
return (
|
|
143
|
-
<WindowManagerProvider client={client}>
|
|
144
|
-
...
|
|
145
|
-
</WindowManagerProvider>
|
|
146
|
-
);
|
|
147
|
-
}
|
|
148
|
-
```
|
|
149
|
-
|
|
150
|
-
> **Backward compatibility:** Passing `formatMessage` directly as a prop to `WindowManagerProvider` is still supported for existing code.
|
|
151
|
-
|
|
152
|
-
*If no `formatMessage` function is provided, the engine defaults to a fallback formatting template parser resolving placeholders like `Hello {user}` using values.*
|
|
153
|
-
|
|
154
|
-
### Right-to-Left (RTL) Layout Support
|
|
155
|
-
|
|
156
|
-
The library features built-in, theme-resilient Right-to-Left (RTL) rendering. It automatically mirrors tab stacking flows, close icon alignments, custom header buttons, side drawers (which slide in from the opposite edge), titlebars, and taskbar icons.
|
|
157
|
-
|
|
158
|
-
#### 1. Automatic Detection (Zero Configuration)
|
|
159
|
-
Simply apply the HTML `dir="rtl"` attribute to the container enclosing your layout, or globally on the `<html>`/`<body>` nodes. The workspace will observe it using a `MutationObserver` and mirror dynamically:
|
|
160
|
-
```html
|
|
161
|
-
<div dir="rtl">
|
|
162
|
-
<Desktop />
|
|
163
|
-
</div>
|
|
164
|
-
```
|
|
165
|
-
|
|
166
|
-
#### 2. Explicit Programmatic Control
|
|
167
|
-
To force a specific direction regardless of the surrounding HTML structure, pass the `dir` option to `WorkspaceClient`:
|
|
168
|
-
```typescript
|
|
169
|
-
const client = new WorkspaceClient({ panels: { ... }, dir: 'rtl' });
|
|
170
|
-
<WindowManagerProvider client={client}>
|
|
171
|
-
<Desktop />
|
|
172
|
-
</WindowManagerProvider>
|
|
91
|
+
// Query state:
|
|
92
|
+
client.isOpen('map-1'); // boolean
|
|
93
|
+
client.getOpenPanelIds(); // string[]
|
|
173
94
|
```
|
|
174
95
|
|
|
175
96
|
---
|
|
176
97
|
|
|
177
|
-
##
|
|
178
|
-
|
|
179
|
-
Consume actions from the layout context anywhere inside or outside your panel components using the provided hooks.
|
|
180
|
-
|
|
181
|
-
```typescript
|
|
182
|
-
import { useWindowManagerActions, useWindowManagerState } from 'react-dockable-desktop';
|
|
98
|
+
## Hooks
|
|
183
99
|
|
|
184
|
-
|
|
185
|
-
const { openPanel, closePanel, saveLayout, loadLayout } = useWindowManagerActions();
|
|
186
|
-
const state = useWindowManagerState();
|
|
100
|
+
Use these inside any component within the provider tree:
|
|
187
101
|
|
|
188
|
-
|
|
189
|
-
openPanel('debug-console', 'terminal', {
|
|
190
|
-
title: { id: 'app.console', defaultMessage: 'System Console Log' },
|
|
191
|
-
initialTarget: 'floating' // Options: 'docked' | 'floating' | 'tabbed'
|
|
192
|
-
});
|
|
193
|
-
};
|
|
194
|
-
|
|
195
|
-
return (
|
|
196
|
-
<div>
|
|
197
|
-
<button onClick={handleOpenConsole}>Spawn Console</button>
|
|
198
|
-
<button onClick={() => alert(saveLayout())}>Backup Layout</button>
|
|
199
|
-
</div>
|
|
200
|
-
);
|
|
201
|
-
};
|
|
202
|
-
```
|
|
203
|
-
|
|
204
|
-
### Hook Reference
|
|
205
|
-
|
|
206
|
-
| Hook Name | Return Type | Description |
|
|
207
|
-
| :--- | :--- | :--- |
|
|
208
|
-
| `useWindowManagerState()` | `WindowState` | Access grid layout trees, list of active floating windows, minimized windows list, and general dragging statuses. |
|
|
209
|
-
| `useWindowManagerActions()` | `WindowActions` | Spawns, minimizes, restores, docks, floats, maximizes, or closes panels. Also handles split sizing, custom locations, and layout serialization (`saveLayout` / `loadLayout`). |
|
|
210
|
-
| `useFormatMessage()` | `(msg: ContextMenuPredefinedMessage) => string` | Returns the translation message formatter hook matching the provider preset configuration. |
|
|
211
|
-
| `usePanelContext()` | `{ publish, subscribe }` | Dynamic decoupled event bus helper for active panels. |
|
|
212
|
-
| `useStyleClasses()` | `StyleClasses` | Returns the custom CSS class overrides configured on the provider (`windowClass`, `windowBodyClass`, etc.). |
|
|
213
|
-
| `useRegistry()` | `PanelRegistryClass` | Returns the scoped panel registry for the current provider. |
|
|
214
|
-
|
|
215
|
-
---
|
|
216
|
-
|
|
217
|
-
## New Exports (v1.2.0)
|
|
218
|
-
|
|
219
|
-
The following additional exports are available in v1.2.0:
|
|
220
|
-
|
|
221
|
-
- `WorkspaceClient` β class for creating a scoped workspace configuration outside React.
|
|
222
|
-
- `WorkspaceClientConfig` β TypeScript interface for the `WorkspaceClient` constructor options.
|
|
223
|
-
- `PanelDefinition` β TypeScript interface describing a single panel entry in the `panels` map.
|
|
224
|
-
- `PanelRegistryClass` β the class backing both the scoped (per-client) and global registries; useful for typing or extending the registry.
|
|
225
|
-
|
|
226
|
-
---
|
|
227
|
-
|
|
228
|
-
## π‘οΈ Form Container Context (Close Interception & Dirty States)
|
|
229
|
-
|
|
230
|
-
`react-dockable-desktop` provides a context-driven panel container contract to support dirty form tracking, dynamic title overrides, and close action guards. Child elements can access this container context using the `useFormContainer()` hook.
|
|
231
|
-
|
|
232
|
-
### Context Hook Functions
|
|
233
|
-
|
|
234
|
-
| Function / Property | Type | Description |
|
|
102
|
+
| Hook | Returns | Description |
|
|
235
103
|
| :--- | :--- | :--- |
|
|
236
|
-
| `
|
|
237
|
-
| `
|
|
238
|
-
| `
|
|
239
|
-
| `
|
|
240
|
-
| `
|
|
241
|
-
|
|
242
|
-
### Implementation Example
|
|
243
|
-
|
|
244
|
-
```typescript
|
|
245
|
-
import React, { useState, useEffect } from 'react';
|
|
246
|
-
import { useFormContainer } from 'react-dockable-desktop';
|
|
247
|
-
|
|
248
|
-
const EditFormPanel: React.FC = () => {
|
|
249
|
-
const container = useFormContainer();
|
|
250
|
-
const [text, setText] = useState('');
|
|
251
|
-
|
|
252
|
-
// 1. Mark dirty when typing
|
|
253
|
-
const handleChange = (e: React.ChangeEvent<HTMLTextAreaElement>) => {
|
|
254
|
-
setText(e.target.value);
|
|
255
|
-
container.setDirty(true); // Appends '*' to tab header and prompts warning on close
|
|
256
|
-
};
|
|
257
|
-
|
|
258
|
-
const handleSave = () => {
|
|
259
|
-
container.setDirty(false); // Resets dirty state
|
|
260
|
-
alert('Saved successfully!');
|
|
261
|
-
};
|
|
262
|
-
|
|
263
|
-
// 2. Intercept and block closing based on conditions
|
|
264
|
-
useEffect(() => {
|
|
265
|
-
const unregister = container.onCloseRequested(() => {
|
|
266
|
-
if (text.includes('BLOCK')) {
|
|
267
|
-
alert('Cannot close while the word "BLOCK" is present!');
|
|
268
|
-
return false; // Blocks closure
|
|
269
|
-
}
|
|
270
|
-
return true; // Allows closure
|
|
271
|
-
});
|
|
272
|
-
return unregister;
|
|
273
|
-
}, [container, text]);
|
|
274
|
-
|
|
275
|
-
return (
|
|
276
|
-
<div style={{ padding: '1rem', color: '#fff' }}>
|
|
277
|
-
<h5>Dynamic Form Editor</h5>
|
|
278
|
-
<textarea value={text} onChange={handleChange} />
|
|
279
|
-
<button onClick={handleSave}>Save</button>
|
|
280
|
-
<button onClick={() => container.requestClose()}>Cancel & Close</button>
|
|
281
|
-
</div>
|
|
282
|
-
);
|
|
283
|
-
};
|
|
284
|
-
```
|
|
104
|
+
| `useWindowManagerActions()` | `WindowActions` | Open, close, focus, dock, float, minimize, maximize, serialize panels |
|
|
105
|
+
| `useWindowManagerState()` | `WindowState` | Reactive access to grid layout, floating windows, minimized panels |
|
|
106
|
+
| `useRegistry()` | `PanelRegistryClass` | The scoped panel registry for the current provider |
|
|
107
|
+
| `usePanelContext()` | `{ publish, subscribe }` | Inter-panel pub/sub event bus |
|
|
108
|
+
| `useFormContainer()` | `FormContainerContract` | Dirty-state tracking, dynamic title overrides, close guards |
|
|
109
|
+
| `useFormatMessage()` | `(msg) => string` | Translation formatter matching the provider's i18n config |
|
|
285
110
|
|
|
286
111
|
---
|
|
287
112
|
|
|
288
|
-
##
|
|
113
|
+
## v2.0.0 β Breaking Changes
|
|
289
114
|
|
|
290
|
-
|
|
115
|
+
| Removed | Replacement |
|
|
116
|
+
| :--- | :--- |
|
|
117
|
+
| `bringToFront(id)` | `focusPanel(id)` β works for both floating and docked panels |
|
|
118
|
+
| `setActivePanel(id)` on `WindowActions` | `focusPanel(id)` |
|
|
291
119
|
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
120
|
+
**New in v2.0.0:**
|
|
121
|
+
- `focusPanel(id)` β unified "show this panel" method
|
|
122
|
+
- `isOpen(id): boolean` β synchronous panel state query
|
|
123
|
+
- `getOpenPanelIds(): string[]` β list all open panel IDs
|
|
124
|
+
- Pending-call queue: imperative calls before the provider mounts are automatically buffered and replayed
|
|
125
|
+
- DEV-mode warning if `client=` prop is missing on the provider
|
|
126
|
+
- DEV-mode warning if `replace-react-contexify` CSS is not detected
|
|
295
127
|
|
|
296
|
-
|
|
297
|
-
const ConsoleView: React.FC = () => {
|
|
298
|
-
const { subscribe } = usePanelContext();
|
|
299
|
-
|
|
300
|
-
useEffect(() => {
|
|
301
|
-
const unsubscribe = subscribe('CONSOLE_LOG', (payload) => {
|
|
302
|
-
console.log('Received log message: ', payload.message);
|
|
303
|
-
});
|
|
304
|
-
return () => unsubscribe();
|
|
305
|
-
}, [subscribe]);
|
|
306
|
-
|
|
307
|
-
return <div>Console Viewer</div>;
|
|
308
|
-
};
|
|
309
|
-
|
|
310
|
-
// Publisher Panel (e.g. Map View)
|
|
311
|
-
const MapView: React.FC = () => {
|
|
312
|
-
const { publish } = usePanelContext();
|
|
313
|
-
|
|
314
|
-
const handleInteract = () => {
|
|
315
|
-
publish('CONSOLE_LOG', { message: 'User zoomed map viewport.' });
|
|
316
|
-
};
|
|
317
|
-
|
|
318
|
-
return <button onClick={handleInteract}>Click Map</button>;
|
|
319
|
-
};
|
|
320
|
-
```
|
|
128
|
+
See the [Migration Guide](https://felipecarrillo100.github.io/react-dockable-desktop/guide/migration) for the full list of changes.
|
|
321
129
|
|
|
322
130
|
---
|
|
323
131
|
|
|
324
|
-
##
|
|
325
|
-
|
|
326
|
-
You can customize defaults, positioning attributes, and sizes using the `WorkspaceClient` panels configuration:
|
|
327
|
-
|
|
328
|
-
```typescript
|
|
329
|
-
const client = new WorkspaceClient({
|
|
330
|
-
panels: {
|
|
331
|
-
'unique-panel-key': {
|
|
332
|
-
component: PanelComponent,
|
|
333
|
-
defaultOptions: {
|
|
334
|
-
title: 'Default Title String', // fallback
|
|
335
|
-
canMinimize: true,
|
|
336
|
-
canDrag: true,
|
|
337
|
-
canClose: true,
|
|
338
|
-
initialTarget: 'docked', // or 'floating'
|
|
339
|
-
favoritePosition: {
|
|
340
|
-
x: 400,
|
|
341
|
-
y: 200,
|
|
342
|
-
width: 500,
|
|
343
|
-
height: 350,
|
|
344
|
-
},
|
|
345
|
-
},
|
|
346
|
-
},
|
|
347
|
-
},
|
|
348
|
-
});
|
|
349
|
-
```
|
|
350
|
-
|
|
351
|
-
> **Legacy / backward-compatible approach:** You can still use the global `PanelRegistry.register('unique-panel-key', PanelComponent, options)` at module scope. This singleton is fully supported for existing codebases.
|
|
132
|
+
## Demo Environments
|
|
352
133
|
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
:
|
|
356
|
-
--accent-color: #00f0ff;
|
|
357
|
-
--bg-dark-color: #12131a;
|
|
358
|
-
--glass-bg: rgba(18, 19, 26, 0.65);
|
|
359
|
-
--border-color: rgba(255, 255, 255, 0.08);
|
|
360
|
-
}
|
|
134
|
+
```bash
|
|
135
|
+
npm run dev # Leaflet + Monaco open-source demo
|
|
136
|
+
npm run dev:ria # LuciadRIA 3D Earth demo (requires license)
|
|
361
137
|
```
|
|
362
138
|
|
|
363
139
|
---
|
|
364
140
|
|
|
365
|
-
##
|
|
141
|
+
## Documentation
|
|
366
142
|
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
```typescript
|
|
370
|
-
document.documentElement.setAttribute('data-color-scheme', 'dark'); // or 'light'
|
|
371
|
-
```
|
|
372
|
-
|
|
373
|
-
If you are also using Bootstrap, you may set `data-bs-theme` alongside it for Bootstrap component compatibility.
|
|
374
|
-
|
|
375
|
-
---
|
|
143
|
+
Full narrative guides, API reference, and the interactive demo are published at:
|
|
376
144
|
|
|
377
|
-
|
|
145
|
+
**https://felipecarrillo100.github.io/react-dockable-desktop/**
|
|
378
146
|
|
|
379
|
-
|
|
147
|
+
- [Getting Started](https://felipecarrillo100.github.io/react-dockable-desktop/guide/)
|
|
148
|
+
- [WorkspaceClient Guide](https://felipecarrillo100.github.io/react-dockable-desktop/guide/workspace-client)
|
|
149
|
+
- [Layout System](https://felipecarrillo100.github.io/react-dockable-desktop/guide/layout)
|
|
150
|
+
- [API Reference](https://felipecarrillo100.github.io/react-dockable-desktop/api/)
|
|
151
|
+
- [Migration v1 β v2](https://felipecarrillo100.github.io/react-dockable-desktop/guide/migration)
|
|
380
152
|
|
|
381
153
|
---
|
|
382
154
|
|
|
383
|
-
##
|
|
155
|
+
## License
|
|
384
156
|
|
|
385
157
|
MIT. Free to use, adapt, and build upon.
|