flexlayout-react 0.8.19 → 0.9.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 +146 -208
- package/dist/index.js +6523 -6395
- package/package.json +25 -27
- package/style/_base.scss +115 -35
- package/style/_themes.scss +719 -49
- package/style/alpha_dark.css +865 -0
- package/style/alpha_dark.css.map +1 -0
- package/style/alpha_dark.scss +6 -0
- package/style/alpha_light.css +859 -0
- package/style/alpha_light.css.map +1 -0
- package/style/alpha_light.scss +6 -0
- package/style/alpha_rounded.css +813 -0
- package/style/alpha_rounded.css.map +1 -0
- package/style/alpha_rounded.scss +6 -0
- package/style/combined.css +573 -47
- package/style/combined.css.map +1 -1
- package/style/combined.scss +25 -1
- package/style/dark.css +100 -25
- package/style/dark.css.map +1 -1
- package/style/gray.css +101 -26
- package/style/gray.css.map +1 -1
- package/style/light.css +101 -23
- package/style/light.css.map +1 -1
- package/style/rounded.css +112 -28
- package/style/rounded.css.map +1 -1
- package/style/underline.css +104 -25
- package/style/underline.css.map +1 -1
- package/types/index.d.ts +14 -14
- package/types/model/Actions.d.ts +62 -31
- package/types/model/Attributes.d.ts +42 -0
- package/types/model/BorderNode.d.ts +11 -11
- package/types/model/BorderSet.d.ts +2 -2
- package/types/{DropInfo.d.ts → model/DropInfo.d.ts} +2 -2
- package/types/model/IDropTarget.d.ts +2 -2
- package/types/model/IJsonModel.d.ts +72 -50
- package/types/model/Layout.d.ts +41 -0
- package/types/model/Model.d.ts +30 -25
- package/types/model/Node.d.ts +18 -10
- package/types/{Rect.d.ts → model/Rect.d.ts} +6 -4
- package/types/model/RowNode.d.ts +15 -14
- package/types/model/TabNode.d.ts +17 -25
- package/types/model/TabSetNode.d.ts +15 -21
- package/types/view/BorderButton.d.ts +4 -3
- package/types/view/BorderTab.d.ts +3 -3
- package/types/view/BorderTabSet.d.ts +3 -3
- package/types/{Types.d.ts → view/CSSClassNames.d.ts} +11 -3
- package/types/view/DragTabButton.d.ts +11 -0
- package/types/view/FloatWindow.d.ts +12 -0
- package/types/{I18nLabel.d.ts → view/I18nLabel.d.ts} +2 -1
- package/types/view/Icons.d.ts +1 -0
- package/types/view/Layout.d.ts +21 -197
- package/types/view/Overlay.d.ts +2 -2
- package/types/view/PopoutWindow.d.ts +6 -6
- package/types/view/PopupMenu.d.ts +2 -2
- package/types/view/Row.d.ts +3 -3
- package/types/view/Splitter.d.ts +2 -4
- package/types/view/Tab.d.ts +3 -4
- package/types/view/TabButton.d.ts +3 -3
- package/types/view/TabButtonStamp.d.ts +3 -3
- package/types/view/TabContentRenderer.d.ts +14 -0
- package/types/view/TabLayout.d.ts +12 -0
- package/types/view/TabOverflowHook.d.ts +3 -3
- package/types/view/TabSet.d.ts +3 -3
- package/types/view/Utils.d.ts +15 -4
- package/types/view/layout/BorderContainer.d.ts +7 -0
- package/types/view/layout/DragDropManager.d.ts +48 -0
- package/types/view/layout/EdgeIndicators.d.ts +5 -0
- package/types/view/layout/FloatingWindowContainer.d.ts +5 -0
- package/types/view/layout/LayoutInternal.d.ts +147 -0
- package/types/view/layout/LayoutTypes.d.ts +51 -0
- package/types/Attribute.d.ts +0 -25
- package/types/AttributeDefinitions.d.ts +0 -18
- package/types/model/Action.d.ts +0 -5
- package/types/model/LayoutWindow.d.ts +0 -44
- package/types/view/DragContainer.d.ts +0 -9
- package/types/view/SizeTracker.d.ts +0 -13
- /package/types/{DockLocation.d.ts → model/DockLocation.d.ts} +0 -0
- /package/types/{Orientation.d.ts → model/Orientation.d.ts} +0 -0
package/README.md
CHANGED
|
@@ -4,93 +4,83 @@
|
|
|
4
4
|

|
|
5
5
|
[](https://www.npmjs.com/package/flexlayout-react)
|
|
6
6
|
|
|
7
|
-
FlexLayout is a layout manager that arranges
|
|
7
|
+
FlexLayout is a layout manager for React that arranges components in multiple tabsets. Tabs can be resized, moved, and organized into complex layouts.
|
|
8
8
|
|
|
9
|
-

|
|
10
10
|
|
|
11
|
-
[Run the Demo](https://caplin.github.io/FlexLayout/demos/v0.
|
|
11
|
+
[Run the Demo](https://caplin.github.io/FlexLayout/demos/v0.9/demo/index.html)
|
|
12
12
|
|
|
13
13
|
Try it now using [CodeSandbox](https://codesandbox.io/p/sandbox/yvjzqf)
|
|
14
14
|
|
|
15
|
-
[API Doc](https://caplin.github.io/FlexLayout/demos/v0.
|
|
16
|
-
|
|
17
|
-
[Screenshot of Caplin Liberator Explorer using FlexLayout](https://caplin.github.io/FlexLayout/demos/v0.20/images/LiberatorExplorerV3_3.PNG)
|
|
15
|
+
[API Doc](https://caplin.github.io/FlexLayout/demos/v0.9/typedoc/index.html)
|
|
18
16
|
|
|
19
17
|
FlexLayout's only dependency is React.
|
|
20
18
|
|
|
21
19
|
Features:
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
*
|
|
31
|
-
*
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
-
*
|
|
35
|
-
*
|
|
36
|
-
*
|
|
37
|
-
*
|
|
38
|
-
*
|
|
39
|
-
*
|
|
40
|
-
*
|
|
20
|
+
* Splitters for resizing
|
|
21
|
+
* Tabs (scrolling or wrapped)
|
|
22
|
+
* Tab dragging and ordering
|
|
23
|
+
* Tabset dragging (move all tabs in a tabset in one operation)
|
|
24
|
+
* Docking to tabsets or edges of the frame
|
|
25
|
+
* Maximizing tabsets (double-click tabset header or use icon)
|
|
26
|
+
* Tab overflow (menu for hidden tabs, mouse wheel scrolling)
|
|
27
|
+
* Border tabsets
|
|
28
|
+
* Popout tabs into floating panels or new browser windows
|
|
29
|
+
* Submodels (layouts inside layouts)
|
|
30
|
+
* Tab renaming (double-click tab text)
|
|
31
|
+
* Theming (light, dark, underline, etc., and combined)
|
|
32
|
+
* Mobile support (iPad, Android)
|
|
33
|
+
* Multiple ways to add tabs (drag, active tabset, by ID)
|
|
34
|
+
* Comprehensive tab and tabset attributes (`enableTabStrip`, `enableDock`, `enableDrop`, etc.)
|
|
35
|
+
* Customizable tab and tabset rendering
|
|
36
|
+
* Preservation of component state when tabs are moved
|
|
37
|
+
* Playwright tests
|
|
38
|
+
* TypeScript type declarations
|
|
39
|
+
|
|
40
|
+
## Example Interaction
|
|
41
|
+

|
|
41
42
|
|
|
42
43
|
## Installation
|
|
43
44
|
|
|
44
|
-
FlexLayout is
|
|
45
|
+
FlexLayout is available on npm. Install it using:
|
|
45
46
|
|
|
46
|
-
```
|
|
47
|
+
```bash
|
|
47
48
|
npm install flexlayout-react
|
|
48
49
|
```
|
|
49
50
|
|
|
50
|
-
Import FlexLayout in your modules:
|
|
51
|
-
|
|
52
|
-
```
|
|
53
|
-
import {Layout, Model} from 'flexlayout-react';
|
|
54
|
-
```
|
|
55
|
-
|
|
56
|
-
Include the light, dark, underline, gray, rounded or combined theme by either:
|
|
51
|
+
Import FlexLayout and its model in your modules:
|
|
57
52
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
```
|
|
61
|
-
import 'flexlayout-react/style/light.css';
|
|
53
|
+
```javascript
|
|
54
|
+
import { Layout, Model } from 'flexlayout-react';
|
|
62
55
|
```
|
|
63
56
|
|
|
64
|
-
|
|
65
|
-
public assets folder (e.g. public/style) and linking the css in your html:
|
|
57
|
+
Include a theme. Choose from `alpha_light`, `alpha_dark`, `alpha_rounded`, `light`, `dark`, `underline`, `gray`, `rounded`, or `combined` (see the demo for examples):
|
|
66
58
|
|
|
67
|
-
```
|
|
68
|
-
|
|
59
|
+
```css
|
|
60
|
+
import 'flexlayout-react/style/alpha_light.css';
|
|
69
61
|
```
|
|
70
62
|
|
|
71
|
-
[
|
|
63
|
+
[Learn how to change the theme dynamically in code](#dynamically-changing-the-theme)
|
|
72
64
|
|
|
73
65
|
|
|
74
66
|
## Usage
|
|
75
67
|
|
|
76
|
-
The `<Layout>` component renders the tabsets and splitters
|
|
77
|
-
|
|
68
|
+
The `<Layout>` component renders the tabsets and splitters. It takes the following props:
|
|
78
69
|
|
|
79
70
|
#### Required props:
|
|
80
71
|
|
|
81
|
-
|
|
82
|
-
|
|
|
83
|
-
|
|
|
84
|
-
|
|
|
85
|
-
| factory | a factory function for creating React components |
|
|
72
|
+
| Prop | Description |
|
|
73
|
+
| ------- | ------------------------------------------------ |
|
|
74
|
+
| `model` | The layout model |
|
|
75
|
+
| `factory` | A factory function for creating React components |
|
|
86
76
|
|
|
87
77
|
Additional [optional props](#optional-layout-props)
|
|
88
78
|
|
|
89
|
-
The model is tree of Node objects that define the structure of the layout.
|
|
79
|
+
The model is a tree of `Node` objects that define the structure of the layout.
|
|
90
80
|
|
|
91
|
-
The factory is a function that takes a Node object and returns a React component
|
|
81
|
+
The factory is a function that takes a `Node` object and returns a React component to be hosted within a tab.
|
|
92
82
|
|
|
93
|
-
|
|
83
|
+
Models can be created using the `Model.fromJson(jsonObject)` static method and saved using the `model.toJson()` method.
|
|
94
84
|
|
|
95
85
|
## Example Configuration:
|
|
96
86
|
|
|
@@ -152,57 +142,51 @@ function App() {
|
|
|
152
142
|
}
|
|
153
143
|
```
|
|
154
144
|
|
|
155
|
-
The above code
|
|
145
|
+
The above code renders two tabsets horizontally, each containing a single tab that hosts a `div` component (returned from the factory). Tabs can be moved and resized by dragging and dropping. Additional tabs can be added to the layout by sending actions to the model.
|
|
156
146
|
|
|
157
147
|
<img src="screenshots/Screenshot_two_tabs.png?raw=true" alt="Simple layout" title="Generated Layout"/>
|
|
158
148
|
|
|
149
|
+
Note: The `<Layout>` component must be hosted in a container element (with CSS `position: absolute` or `relative`). The layout will fill the containing element.
|
|
150
|
+
|
|
159
151
|
|
|
160
152
|
Try it now using [CodeSandbox](https://codesandbox.io/p/sandbox/yvjzqf)
|
|
161
153
|
|
|
162
|
-
A simple
|
|
154
|
+
A simple TypeScript example can be found here:
|
|
163
155
|
|
|
164
156
|
https://github.com/nealus/flexlayout-vite-example
|
|
165
157
|
|
|
166
|
-
The model
|
|
167
|
-
|
|
168
|
-
* global - (optional) where global options are defined
|
|
169
|
-
* layout - where the main row/tabset/tabs layout hierarchy is defined
|
|
170
|
-
* borders - (optional) where up to 4 borders are defined ("top", "bottom", "left", "right").
|
|
171
|
-
* popouts - (optional) where the popout windows are defined
|
|
158
|
+
The model JSON contains four top-level elements:
|
|
172
159
|
|
|
173
|
-
|
|
160
|
+
* `global` - (optional) Global options.
|
|
161
|
+
* `layout` - The main row/tabset/tabs layout hierarchy.
|
|
162
|
+
* `borders` - (optional) Up to four borders ("top", "bottom", "left", "right").
|
|
163
|
+
* `subLayouts` - (optional) Where sub layouts for popout windows, floating panels and tabs are defined.
|
|
174
164
|
|
|
175
|
-
|
|
176
|
-
, child 'rows' will render in the opposite orientation to their parent row.
|
|
165
|
+
The `layout` element is built using three types of nodes:
|
|
177
166
|
|
|
178
|
-
*
|
|
179
|
-
|
|
180
|
-
* tab -
|
|
167
|
+
* `row` - Rows contain a list of tabsets and child rows. The top-level `row` renders horizontally by default (unless the global attribute `rootOrientationVertical` is set). Child rows render in the opposite orientation to their parent row.
|
|
168
|
+
* `tabset` - Tabsets contain a list of tabs and the index of the selected tab.
|
|
169
|
+
* `tab` - Tabs specify the component to host (loaded via the factory) and the tab's display text.
|
|
181
170
|
|
|
182
171
|
The layout structure is defined with rows within rows that contain tabsets that themselves contain tabs.
|
|
183
172
|
|
|
184
|
-
Within the demo app you can
|
|
173
|
+
Within the demo app, you can view the layout structure by checking the 'Show layout' box. Rows are shown in blue, and tabsets in orange.
|
|
185
174
|
|
|
186
175
|

|
|
187
176
|
|
|
188
|
-
The optional borders element is made up of border nodes
|
|
189
|
-
|
|
190
|
-
* border - borders contain a list of tabs and the index of the selected tab, they can only be used in the borders
|
|
191
|
-
top level element.
|
|
177
|
+
The optional `borders` element is made up of border nodes:
|
|
192
178
|
|
|
193
|
-
|
|
179
|
+
* `border` - Borders contain a list of tabs and the index of the selected tab. They can only be used within the `borders` top-level element.
|
|
194
180
|
|
|
195
|
-
|
|
181
|
+
The JSON model tree structure is defined as TypeScript interfaces; see [JSON Model](#json-model-definition).
|
|
196
182
|
|
|
197
|
-
|
|
183
|
+
Each node type has a defined set of required and optional attributes.
|
|
198
184
|
|
|
199
|
-
|
|
200
|
-
existing layouts by dragging/dropping and adding nodes then press the 'Show Layout JSON in console' button to print the JSON to the browser developer console.
|
|
185
|
+
Weights on rows and tabsets specify their relative size within the parent row. The absolute values do not matter, only their proportions (e.g., two tabsets with weights 30 and 70 would render the same as if they had weights 3 and 7).
|
|
201
186
|
|
|
202
|
-
|
|
187
|
+
NOTE: The easiest way to create your initial layout JSON is to use the [demo](https://caplin.github.io/FlexLayout/demos/v0.9/demo/index.html) app. Modify an existing layout by dragging, dropping, and adding nodes, then press the 'print' button to print the JSON to the browser's developer console.
|
|
203
188
|
|
|
204
|
-
|
|
205
|
-
tabs or drag and drop).
|
|
189
|
+
By changing global or node attributes, you can modify the layout's appearance and functionality. For example, setting `tabSetEnableTabStrip: false` in the global options would change the layout into a multi-splitter (without tabs or drag-and-drop):
|
|
206
190
|
|
|
207
191
|
```
|
|
208
192
|
global: {tabSetEnableTabStrip:false},
|
|
@@ -210,13 +194,13 @@ tabs or drag and drop).
|
|
|
210
194
|
|
|
211
195
|
## Dynamically Changing the Theme
|
|
212
196
|
|
|
213
|
-
The
|
|
197
|
+
The `combined.css` theme includes all other themes and supports dynamic theme switching.
|
|
214
198
|
|
|
215
|
-
When using combined.css
|
|
199
|
+
When using `combined.css`, add a `className` (in the form `flexlayout__theme_[theme-name]`) to the `div` containing the `<Layout>` to select the desired theme.
|
|
216
200
|
|
|
217
201
|
For example:
|
|
218
202
|
```
|
|
219
|
-
<div ref={containerRef} className="
|
|
203
|
+
<div ref={containerRef} className="flexlayout__theme_alpha_light">
|
|
220
204
|
<Layout model={model} factory={factory} />
|
|
221
205
|
</div>
|
|
222
206
|
```
|
|
@@ -225,25 +209,24 @@ Change the theme in code by changing the className on the containing div.
|
|
|
225
209
|
|
|
226
210
|
For example:
|
|
227
211
|
```
|
|
228
|
-
containerRef.current!.className = "
|
|
212
|
+
containerRef.current!.className = "flexlayout__theme_alpha_dark"
|
|
229
213
|
```
|
|
230
214
|
|
|
231
215
|
## Customizing Tabs
|
|
232
216
|
|
|
233
|
-
You can use the `<Layout>` prop onRenderTab to customize
|
|
234
|
-
|
|
217
|
+
You can use the `<Layout>` prop `onRenderTab` to customize tab rendering:
|
|
235
218
|
|
|
236
219
|
<img src="screenshots/Screenshot_customize_tab.png?raw=true"
|
|
237
220
|
alt="FlexLayout Tab structure"
|
|
238
221
|
title="Tab structure"/>
|
|
239
222
|
|
|
240
|
-
Update the renderValues parameter as needed:
|
|
223
|
+
Update the `renderValues` parameter as needed:
|
|
241
224
|
|
|
242
|
-
renderValues.leading
|
|
225
|
+
`renderValues.leading`: The area shown in red.
|
|
243
226
|
|
|
244
|
-
renderValues.content
|
|
227
|
+
`renderValues.content`: The area shown in green.
|
|
245
228
|
|
|
246
|
-
renderValues.buttons
|
|
229
|
+
`renderValues.buttons`: The area shown in yellow.
|
|
247
230
|
|
|
248
231
|
For example:
|
|
249
232
|
|
|
@@ -257,20 +240,19 @@ onRenderTab = (node: TabNode, renderValues: ITabRenderValues) => {
|
|
|
257
240
|
|
|
258
241
|
## Customizing Tabsets
|
|
259
242
|
|
|
260
|
-
You can use the `<Layout>` prop onRenderTabSet to customize
|
|
261
|
-
|
|
243
|
+
You can use the `<Layout>` prop `onRenderTabSet` to customize tabset rendering:
|
|
262
244
|
|
|
263
245
|
<img src="screenshots/Screenshot_customize_tabset.png?raw=true"
|
|
264
246
|
alt="FlexLayout Tab structure"
|
|
265
247
|
title="Tabset structure" />
|
|
266
248
|
|
|
267
|
-
Update the renderValues parameter as needed:
|
|
249
|
+
Update the `renderValues` parameter as needed:
|
|
268
250
|
|
|
269
|
-
renderValues.leading
|
|
251
|
+
`renderValues.leading`: The area shown in blue.
|
|
270
252
|
|
|
271
|
-
renderValues.stickyButtons
|
|
253
|
+
`renderValues.stickyButtons`: The area shown in red.
|
|
272
254
|
|
|
273
|
-
renderValues.buttons
|
|
255
|
+
`renderValues.buttons`: The area shown in green.
|
|
274
256
|
|
|
275
257
|
|
|
276
258
|
For example:
|
|
@@ -283,7 +265,7 @@ onRenderTabSet = (node: (TabSetNode | BorderNode), renderValues: ITabSetRenderVa
|
|
|
283
265
|
title="Add"
|
|
284
266
|
className="flexlayout__tab_toolbar_button"
|
|
285
267
|
onClick={() => {
|
|
286
|
-
model.doAction(Actions.
|
|
268
|
+
model.doAction(Actions.addTab({
|
|
287
269
|
component: "placeholder",
|
|
288
270
|
name: "Added " + nextAddIndex.current++
|
|
289
271
|
}, node.getId(), DockLocation.CENTER, -1, true));
|
|
@@ -296,195 +278,151 @@ onRenderTabSet = (node: (TabSetNode | BorderNode), renderValues: ITabSetRenderVa
|
|
|
296
278
|
|
|
297
279
|
## Model Actions
|
|
298
280
|
|
|
299
|
-
Once the model
|
|
281
|
+
Once the model JSON has been loaded, all changes are applied through actions. In the Demo app, you can view these actions in the 'Action Log':
|
|
300
282
|
|
|
301
|
-
|
|
283
|
+
<img src="screenshots/Screenshot_action_log.png?raw=true"
|
|
284
|
+
alt="Action Log"
|
|
285
|
+
title="Action Log" />
|
|
302
286
|
|
|
303
|
-
This method takes a single argument
|
|
304
|
-
generators (accessed as `FlexLayout.Actions.<actionName>`):
|
|
287
|
+
Apply actions using the `model.doAction()` method. This method takes a single argument created by one of the action generators (accessible via `FlexLayout.Actions.<actionName>`):
|
|
305
288
|
|
|
306
|
-
[Actions
|
|
289
|
+
[Actions Documentation](https://caplin.github.io/FlexLayout/demos/v0.9/typedoc/classes/Actions.html)
|
|
307
290
|
|
|
308
|
-
###
|
|
291
|
+
### Example
|
|
309
292
|
|
|
310
293
|
```js
|
|
311
|
-
model.doAction(FlexLayout.Actions.
|
|
294
|
+
model.doAction(FlexLayout.Actions.addTab(
|
|
312
295
|
{type:"tab", component:"grid", name:"a grid", id:"5"},
|
|
313
296
|
"1", FlexLayout.DockLocation.CENTER, 0));
|
|
314
297
|
```
|
|
315
298
|
|
|
316
|
-
This example adds a new grid component to the center of tabset with
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
```js
|
|
320
|
-
model.doAction(FlexLayout.Actions.updateModelAttributes({
|
|
321
|
-
splitterSize:40
|
|
322
|
-
}));
|
|
323
|
-
```
|
|
324
|
-
|
|
325
|
-
The above example would increase the size of the splitters, this could be used to make
|
|
326
|
-
adjusting the layout easier on a small device.
|
|
299
|
+
This example adds a new grid component to the center of the tabset with ID "1" at the first position (0). Use `-1` to add to the end of the tabs.
|
|
327
300
|
|
|
328
|
-
Note:
|
|
329
|
-
action) using the method `node.getId()`.
|
|
330
|
-
If an id wasn't assigned when the node was created, then one will be created for you of the form `#<uuid>` (e.g. `#0c459064-8dee-444e-8636-eb9ab910fb27`).
|
|
301
|
+
Note: You can retrieve the ID of a node (e.g., the node returned by the `addTab` action) using `node.getId()`. If an ID wasn't assigned when the node was created, one will be generated for you in the form `#<uuid>` (e.g., `#0c459064-8dee-444e-8636-eb9ab910fb27`).
|
|
331
302
|
|
|
332
|
-
Note: You can intercept actions resulting from GUI changes before they are applied by
|
|
333
|
-
implementing the `onAction` callback property of the `Layout`.
|
|
303
|
+
Note: You can intercept actions resulting from GUI changes before they are applied by implementing the `onAction` callback property of the `Layout`.
|
|
334
304
|
|
|
335
305
|
## Optional Layout Props
|
|
336
306
|
|
|
337
|
-
|
|
307
|
+
Many optional properties can be applied to the layout:
|
|
338
308
|
|
|
339
|
-
[Layout Properties
|
|
309
|
+
[Layout Properties Documentation](https://caplin.github.io/FlexLayout/demos/v0.9/typedoc/interfaces/ILayoutProps.html)
|
|
340
310
|
|
|
341
311
|
|
|
342
312
|
## JSON Model Definition
|
|
343
313
|
|
|
344
|
-
The JSON model is
|
|
345
|
-
|
|
346
|
-
## Model Config Attributes
|
|
347
|
-
|
|
348
|
-
[Model Attributes doc](https://caplin.github.io/FlexLayout/demos/v0.8/typedoc/interfaces/IJsonModel.html)
|
|
349
|
-
|
|
350
|
-
## Global Config Attributes
|
|
351
|
-
|
|
352
|
-
[Global Attributes doc](https://caplin.github.io/FlexLayout/demos/v0.8/typedoc/interfaces/IGlobalAttributes.html)
|
|
314
|
+
The JSON model is defined as a set of TypeScript interfaces. See the documentation for details on allowed attributes:
|
|
353
315
|
|
|
354
|
-
|
|
316
|
+
[Model Attributes Documentation](https://caplin.github.io/FlexLayout/demos/v0.9/typedoc/interfaces/IJsonModel.html)
|
|
355
317
|
|
|
356
|
-
[
|
|
318
|
+
[Global Attributes Documentation](https://caplin.github.io/FlexLayout/demos/v0.9/typedoc/interfaces/IGlobalAttributes.html)
|
|
357
319
|
|
|
358
|
-
|
|
320
|
+
[Row Attributes Documentation](https://caplin.github.io/FlexLayout/demos/v0.9/typedoc/interfaces/IJsonRowNode.html)
|
|
359
321
|
|
|
360
|
-
[Tabset Attributes
|
|
322
|
+
[Tabset Attributes Documentation](https://caplin.github.io/FlexLayout/demos/v0.9/typedoc/interfaces/IJsonTabSetNode.html)
|
|
361
323
|
|
|
362
|
-
Note:
|
|
324
|
+
Note: Tabsets are dynamically created as tabs are moved and deleted when their last tab is removed (unless `enableDeleteWhenEmpty` is set to `false`).
|
|
363
325
|
|
|
364
|
-
|
|
326
|
+
[Tab Attributes Documentation](https://caplin.github.io/FlexLayout/demos/v0.9/typedoc/interfaces/ITabAttributes.html)
|
|
365
327
|
|
|
366
|
-
[
|
|
328
|
+
[Border Attributes Documentation](https://caplin.github.io/FlexLayout/demos/v0.9/typedoc/interfaces/IJsonBorderNode.html)
|
|
367
329
|
|
|
368
|
-
## Border Config attributes
|
|
369
330
|
|
|
370
|
-
[Border Attributes doc](https://caplin.github.io/FlexLayout/demos/v0.8/typedoc/interfaces/IJsonBorderNode.html)
|
|
371
331
|
|
|
372
332
|
|
|
333
|
+
## Layout API Methods to Create New Tabs
|
|
373
334
|
|
|
335
|
+
The Layout Ref provides methods for adding tabs:
|
|
374
336
|
|
|
375
|
-
|
|
376
|
-
## Layout Component Methods to Create New Tabs
|
|
377
|
-
|
|
378
|
-
There are methods on the Layout Component for adding tabs:
|
|
379
|
-
|
|
380
|
-
[Layout Methods doc](https://caplin.github.io/FlexLayout/demos/v0.8/typedoc/classes/Layout.html)
|
|
337
|
+
[Layout Methods Documentation](https://caplin.github.io/FlexLayout/demos/v0.9/typedoc/interfaces/ILayoutApi.html)
|
|
381
338
|
|
|
382
339
|
Example:
|
|
383
340
|
|
|
341
|
+
```javascript
|
|
342
|
+
layoutRef.current.addTabToTabSet("NAVIGATION", { type: "tab", component: "grid", name: "a grid" });
|
|
384
343
|
```
|
|
385
|
-
|
|
386
|
-
```
|
|
387
|
-
This would add a new grid component to the tabset with id "NAVIGATION" (where layoutRef is a ref to the Layout element, see https://reactjs.org/docs/refs-and-the-dom.html ).
|
|
388
|
-
|
|
344
|
+
This adds a new grid component to the tabset with ID "NAVIGATION". (where `layoutRef` is a React ref to the `Layout` element; see [React Refs](https://reactjs.org/docs/refs-and-the-dom.html)).
|
|
389
345
|
|
|
390
346
|
|
|
391
347
|
## Tab Node Events
|
|
392
348
|
|
|
393
|
-
You can handle events
|
|
394
|
-
when the component is mounted in a useEffect method:
|
|
349
|
+
You can handle node events by adding a listener, typically within a component's `useEffect` hook:
|
|
395
350
|
|
|
396
351
|
Example:
|
|
397
|
-
```
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
}
|
|
407
|
-
|
|
352
|
+
```javascript
|
|
353
|
+
function MyComponent({ node }) {
|
|
354
|
+
useEffect(() => {
|
|
355
|
+
const listenerId = node.setEventListener("save", () => {
|
|
356
|
+
node.getConfig().subject = subject;
|
|
357
|
+
});
|
|
358
|
+
return () => node.removeEventListener(listenerId);
|
|
359
|
+
}, [subject]);
|
|
360
|
+
}
|
|
408
361
|
```
|
|
409
362
|
|
|
410
|
-
| Event
|
|
411
|
-
|
|
|
412
|
-
| resize
|
|
413
|
-
| close |
|
|
414
|
-
| visibility |
|
|
415
|
-
| save |
|
|
363
|
+
| Event | Parameters | Description |
|
|
364
|
+
| ---------- | ---------- | ----------- |
|
|
365
|
+
| resize | `{rect}` | Called when the tab is resized during layout, before it is rendered with the new size. |
|
|
366
|
+
| close | None | Called when the tab is closed. |
|
|
367
|
+
| visibility | `{visible}`| Called when the tab's visibility changes. |
|
|
368
|
+
| save | None | Called before a `TabNode` is serialized to JSON. Use this to save node configuration by adding data to the object returned by `node.getConfig()`. |
|
|
416
369
|
|
|
417
370
|
## Popout Windows
|
|
418
371
|
|
|
419
|
-
Tabs can be rendered into external browser windows (for
|
|
420
|
-
by configuring them with the enablePopout attribute. When this attribute is present
|
|
421
|
-
an additional icon is shown in the tab header bar allowing the tab to be popped out
|
|
422
|
-
into an external window.
|
|
372
|
+
Tabs can be rendered into external browser windows (useful for multi-monitor setups) by using the `enablePopout` and `enablePopoutIcon` attributes. When enabled, a popout icon appears in the tab header.
|
|
423
373
|
|
|
424
|
-
|
|
425
|
-
at the same location as the main page (copy the one from the demo app). The popout.html is the host page for the
|
|
426
|
-
popped out tab, the styles from the main page will be copied into it at runtime.
|
|
374
|
+
Popout windows require an additional HTML page, `popout.html`, hosted at the same location as the main page (you can copy this from the demo app). The `popout.html` acts as the host for the popped-out tab, and the main page's styles are copied into it at runtime.
|
|
427
375
|
|
|
428
|
-
Because
|
|
429
|
-
tab that uses the global document or window objects for event listeners will not work correctly (for example custom popup menus where the code uses document.addEventListener(...)),
|
|
430
|
-
they need to instead use the document/window of the popout. To get the document/window of the popout use the
|
|
431
|
-
following method on one of the elements rendered in the popout (for example a ref or target in an event handler):
|
|
376
|
+
Because popout windows render into a different document, any code using global `document` or `window` objects (e.g., for event listeners) will not function correctly. Instead, you must use the `document` or `window` of the popout. To obtain these, use the following methods on an element rendered within the popout (such as a ref):
|
|
432
377
|
|
|
378
|
+
```javascript
|
|
379
|
+
const currentDocument = selfRef.current.ownerDocument;
|
|
380
|
+
const currentWindow = currentDocument.defaultView!;
|
|
433
381
|
```
|
|
434
|
-
|
|
435
|
-
const currentWindow = currentDocument.defaultView!;
|
|
436
|
-
```
|
|
382
|
+
In this example, `selfRef` is a React ref to the top-level element in the tab being rendered.
|
|
437
383
|
|
|
438
|
-
|
|
384
|
+
Note: Libraries may support popout windows by allowing you to specify the document to use; for example, see the `getDocument()` callback in ag-Grid at https://www.ag-grid.com/javascript-grid-callbacks/
|
|
439
385
|
|
|
440
|
-
|
|
441
|
-
for example see the getDocument() callback in agGrid at https://www.ag-grid.com/javascript-grid-callbacks/
|
|
386
|
+
### Limitations of Popout Windows
|
|
442
387
|
|
|
443
|
-
|
|
444
|
-
* FlexLayout uses React Portals to draw the popout window content,
|
|
445
|
-
this means all the code runs in the main Window's JS context, so effectively the popout windows are just extensions of the area on which the main window can render panels.
|
|
388
|
+
Note this section only applies to window based popouts, not floating panels.
|
|
446
389
|
|
|
447
|
-
*
|
|
448
|
-
|
|
449
|
-
* Timers throttle when main window is in the background
|
|
450
|
-
|
|
451
|
-
*
|
|
452
|
-
|
|
453
|
-
*
|
|
454
|
-
|
|
455
|
-
* Resize observers may be throttled (or stay attached to the main window), so you may need to use some other way to resize the component when in a popout.
|
|
456
|
-
* Popouts will not size and position correctly when the browser is zoomed (ie set to 50% zoom)
|
|
457
|
-
* Popouts cannot reload in maximized or minimized states
|
|
458
|
-
* by default flexlayout will maintain react state when moving tabs between windows, but you can use the
|
|
459
|
-
enableWindowReMount tab attribute to force the component to re-mount.
|
|
390
|
+
* **React Portals**: FlexLayout uses React Portals for popout content. Code runs in the main window's JS context, effectively extending the rendering area.
|
|
391
|
+
* **Event Listeners**: You must use the popout's window/document when adding listeners (e.g., `popoutDocument.addEventListener(...)`).
|
|
392
|
+
* **Timer Throttling**: Timers may throttle when the main window is in the background. Use web workers for high-precision timing if needed.
|
|
393
|
+
* **Third-Party Libraries**: Controls that rely on the global `document` for event listeners or visibility tracking may require modification.
|
|
394
|
+
* **Resize Observers**: May stay attached to the main window; alternative resize handling might be necessary.
|
|
395
|
+
* **Browser Zoom**: Popouts may not size or position correctly when the browser is zoomed (e.g., at 50% zoom).
|
|
396
|
+
* **States**: Popouts cannot reload in maximized or minimized states.
|
|
397
|
+
* **State Preservation**: While FlexLayout maintains React state when moving tabs between windows, you can use the `enableWindowReMount` attribute to force a component to re-mount.
|
|
460
398
|
|
|
461
399
|
See this article about using React portals in this way: https://dev.to/noriste/the-challenges-of-rendering-an-openlayers-map-in-a-popup-through-react-2elh
|
|
462
400
|
|
|
463
401
|
## Running the Demo and Building the Project
|
|
464
402
|
|
|
465
|
-
First install dependencies:
|
|
403
|
+
First, install the dependencies:
|
|
466
404
|
|
|
467
405
|
```
|
|
468
406
|
pnpm install
|
|
469
407
|
```
|
|
470
408
|
|
|
471
|
-
Run the
|
|
409
|
+
Run the demo app:
|
|
472
410
|
|
|
473
411
|
```
|
|
474
412
|
pnpm dev
|
|
475
413
|
```
|
|
476
414
|
|
|
477
|
-
The
|
|
415
|
+
The `pnpm dev` command watches for changes in both FlexLayout and the Demo app, allowing you to see updates in your browser immediately.
|
|
478
416
|
|
|
479
|
-
Once the demo is running you can
|
|
417
|
+
Once the demo is running, you can execute the Playwright tests in a separate terminal window:
|
|
480
418
|
|
|
481
|
-
```
|
|
419
|
+
```bash
|
|
482
420
|
pnpm playwright
|
|
483
421
|
```
|
|
484
422
|
|
|
485
423
|
<img src="screenshots/PlaywrightUI.png?raw=true" alt="PlaywrightUI" title="PlaywrightUI screenshot"/>
|
|
486
424
|
|
|
487
|
-
To build the npm distribution run
|
|
425
|
+
To build the npm distribution, run `pnpm build`.
|
|
488
426
|
|
|
489
427
|
## Alternative Layout Managers
|
|
490
428
|
|