flexlayout-react 0.8.19 → 0.9.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.
Files changed (77) hide show
  1. package/README.md +144 -206
  2. package/dist/index.js +6463 -6395
  3. package/package.json +21 -24
  4. package/style/_base.scss +108 -33
  5. package/style/_themes.scss +720 -49
  6. package/style/alpha_dark.css +862 -0
  7. package/style/alpha_dark.css.map +1 -0
  8. package/style/alpha_dark.scss +6 -0
  9. package/style/alpha_light.css +856 -0
  10. package/style/alpha_light.css.map +1 -0
  11. package/style/alpha_light.scss +6 -0
  12. package/style/alpha_rounded.css +811 -0
  13. package/style/alpha_rounded.css.map +1 -0
  14. package/style/alpha_rounded.scss +6 -0
  15. package/style/combined.css +568 -44
  16. package/style/combined.css.map +1 -1
  17. package/style/combined.scss +25 -1
  18. package/style/dark.css +94 -22
  19. package/style/dark.css.map +1 -1
  20. package/style/gray.css +95 -23
  21. package/style/gray.css.map +1 -1
  22. package/style/light.css +95 -20
  23. package/style/light.css.map +1 -1
  24. package/style/rounded.css +106 -25
  25. package/style/rounded.css.map +1 -1
  26. package/style/underline.css +98 -22
  27. package/style/underline.css.map +1 -1
  28. package/types/index.d.ts +14 -14
  29. package/types/model/Actions.d.ts +62 -31
  30. package/types/model/Attributes.d.ts +42 -0
  31. package/types/model/BorderNode.d.ts +11 -11
  32. package/types/model/BorderSet.d.ts +2 -2
  33. package/types/{DropInfo.d.ts → model/DropInfo.d.ts} +2 -2
  34. package/types/model/IDropTarget.d.ts +2 -2
  35. package/types/model/IJsonModel.d.ts +70 -48
  36. package/types/model/Layout.d.ts +41 -0
  37. package/types/model/Model.d.ts +30 -25
  38. package/types/model/Node.d.ts +18 -10
  39. package/types/{Rect.d.ts → model/Rect.d.ts} +6 -4
  40. package/types/model/RowNode.d.ts +15 -14
  41. package/types/model/TabNode.d.ts +15 -21
  42. package/types/model/TabSetNode.d.ts +15 -21
  43. package/types/view/BorderButton.d.ts +4 -3
  44. package/types/view/BorderTab.d.ts +3 -3
  45. package/types/view/BorderTabSet.d.ts +3 -3
  46. package/types/{Types.d.ts → view/CSSClassNames.d.ts} +9 -2
  47. package/types/view/DragContainer.d.ts +6 -4
  48. package/types/view/FloatWindow.d.ts +11 -0
  49. package/types/{I18nLabel.d.ts → view/I18nLabel.d.ts} +1 -0
  50. package/types/view/Icons.d.ts +1 -0
  51. package/types/view/Layout.d.ts +34 -212
  52. package/types/view/Overlay.d.ts +2 -2
  53. package/types/view/PopoutWindow.d.ts +6 -6
  54. package/types/view/PopupMenu.d.ts +2 -2
  55. package/types/view/Row.d.ts +3 -3
  56. package/types/view/Splitter.d.ts +2 -4
  57. package/types/view/Tab.d.ts +3 -4
  58. package/types/view/TabButton.d.ts +3 -3
  59. package/types/view/TabButtonStamp.d.ts +3 -3
  60. package/types/view/TabContentRenderer.d.ts +14 -0
  61. package/types/view/TabLayout.d.ts +12 -0
  62. package/types/view/TabOverflowHook.d.ts +3 -3
  63. package/types/view/TabSet.d.ts +3 -3
  64. package/types/view/Utils.d.ts +7 -4
  65. package/types/view/layout/BorderContainer.d.ts +7 -0
  66. package/types/view/layout/DragDropManager.d.ts +48 -0
  67. package/types/view/layout/EdgeIndicators.d.ts +5 -0
  68. package/types/view/layout/FloatingWindowContainer.d.ts +5 -0
  69. package/types/view/layout/LayoutInternal.d.ts +151 -0
  70. package/types/view/layout/LayoutTypes.d.ts +51 -0
  71. package/types/Attribute.d.ts +0 -25
  72. package/types/AttributeDefinitions.d.ts +0 -18
  73. package/types/model/Action.d.ts +0 -5
  74. package/types/model/LayoutWindow.d.ts +0 -44
  75. package/types/view/SizeTracker.d.ts +0 -13
  76. /package/types/{DockLocation.d.ts → model/DockLocation.d.ts} +0 -0
  77. /package/types/{Orientation.d.ts → model/Orientation.d.ts} +0 -0
package/README.md CHANGED
@@ -4,93 +4,83 @@
4
4
  ![npm](https://img.shields.io/npm/dw/flexlayout-react)
5
5
  [![npm](https://img.shields.io/npm/v/flexlayout-react)](https://www.npmjs.com/package/flexlayout-react)
6
6
 
7
- FlexLayout is a layout manager that arranges React components in multiple tabsets, tabs can be resized and moved.
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
- ![FlexLayout Demo Screenshot](screenshots/Screenshot_light.png?raw=true "FlexLayout Demo Screenshot")
9
+ ![FlexLayout Demo Screenshot](screenshots/Screenshot_v0.9.png?raw=true "FlexLayout Demo Screenshot")
10
10
 
11
- [Run the Demo](https://caplin.github.io/FlexLayout/demos/v0.8/demo/index.html)
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.8/typedoc/index.html)
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
- * splitters
23
- * tabs (scrolling or wrapped)
24
- * tab dragging and ordering
25
- * tabset dragging (move all the tabs in a tabset in one operation)
26
- * dock to tabset or edge of frame
27
- * maximize tabset (double click tabset header or use icon)
28
- * tab overflow (show menu when tabs overflow, scroll tabs using mouse wheel)
29
- * border tabsets
30
- * popout tabs into new browser windows
31
- * submodels, allow layouts inside layouts
32
- * tab renaming (double click tab text to rename)
33
- * theming - light, dark, underline, gray, rounded and combined
34
- * works on mobile devices (iPad, Android)
35
- * add tabs using drag, add to active tabset, add to tabset by id
36
- * tab and tabset attributes: enableTabStrip, enableDock, enableDrop...
37
- * customizable tabs and tabset rendering
38
- * component state is preserved when tabs are moved
39
- * Playwright tests
40
- * typescript type declarations
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
+ ![FlexLayout Animation](screenshots/Animation.gif?raw=true "FlexLayout Animation")
41
42
 
42
43
  ## Installation
43
44
 
44
- FlexLayout is in the npm repository. install using:
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
- Adding an import in your js code:
59
-
60
- ```
61
- import 'flexlayout-react/style/light.css';
53
+ ```javascript
54
+ import { Layout, Model } from 'flexlayout-react';
62
55
  ```
63
56
 
64
- or by copying the relevant css from the node_modules/flexlayout-react/style directory to your
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
- <link rel="stylesheet" href="/style/light.css" />
59
+ ```css
60
+ import 'flexlayout-react/style/alpha_light.css';
69
61
  ```
70
62
 
71
- [How to change the theme dynamically in code](#dynamically-changing-the-theme)
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, it takes the following props:
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
- | Prop | Description |
83
- | --------------- | ----------------- |
84
- | model | the layout model |
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 that should be hosted by a tab in the layout.
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
- The model can be created using the Model.fromJson(jsonObject) static method, and can be saved using the model.toJson() method.
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 would render two tabsets horizontally each containing a single tab that hosts a div component (returned from the factory). The tabs could be moved and resized by dragging and dropping. Additional tabs could be added to the layout by sending actions to the model.
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 Typescript example can be found here:
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 json contains 4 top level elements:
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
- The layout element is built up using 3 types of 'node':
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
- * row - rows contains a list of tabsets and child rows, the top level 'row' will render horizontally (unless the global attribute rootOrientationVertical is set)
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
- * tabset - tabsets contain a list of tabs and the index of the selected tab
179
-
180
- * tab - tabs specify the name of the component that they should host (that will be loaded via the factory) and the text of the actual 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 show the layout structure by ticking the 'Show layout' checkbox, rows are shown in blue, tabsets in orange.
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
  ![FlexLayout Demo Showing Layout](screenshots/Screenshot_layout.png?raw=true "Demo showing layout")
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
- The tree structure for the JSON model is well defined as Typescript interfaces, see [JSON Model](#json-model-definition)
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
- Each type of node has a defined set of requires/optional attributes.
181
+ The JSON model tree structure is defined as TypeScript interfaces; see [JSON Model](#json-model-definition).
196
182
 
197
- Weights on rows and tabsets specify the relative weight of these nodes within the parent row, the actual values do not matter just their relative values (ie two tabsets of weights 30,70 would render the same if they had weights of 3,7).
183
+ Each node type has a defined set of required and optional attributes.
198
184
 
199
- NOTE: the easiest way to create your initial layout JSON is to use the [demo](https://caplin.github.io/FlexLayout/demos/v0.8/demo/index.html) app, modify one of the
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
- By changing global or node attributes you can change the layout appearance and functionality, for example:
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
- Setting tabSetEnableTabStrip:false in the global options would change the layout into a multi-splitter (without
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 'combined.css' theme contains all the other themes and can be used for theme switching.
197
+ The `combined.css` theme includes all other themes and supports dynamic theme switching.
214
198
 
215
- When using combined.css, add a className (of the form "flexlayout__theme_[theme name]") to the div containing the `<Layout>` to select the applied theme.
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="flexlayout__theme_light">
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 = "flexlayout__theme_dark"
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 the tab rendering:
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 : the red block
225
+ `renderValues.leading`: The area shown in red.
243
226
 
244
- renderValues.content : the green block
227
+ `renderValues.content`: The area shown in green.
245
228
 
246
- renderValues.buttons : the yellow block
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 the tabset rendering:
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 : the blue block
251
+ `renderValues.leading`: The area shown in blue.
270
252
 
271
- renderValues.stickyButtons : the red block
253
+ `renderValues.stickyButtons`: The area shown in red.
272
254
 
273
- renderValues.buttons : the green block
255
+ `renderValues.buttons`: The area shown in green.
274
256
 
275
257
 
276
258
  For example:
@@ -296,16 +278,17 @@ onRenderTabSet = (node: (TabSetNode | BorderNode), renderValues: ITabSetRenderVa
296
278
 
297
279
  ## Model Actions
298
280
 
299
- Once the model json has been loaded all changes to the model are applied through actions.
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
- You apply actions using the `Model.doAction()` method.
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, created by one of the action
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 doc](https://caplin.github.io/FlexLayout/demos/v0.8/typedoc/classes/Actions.html)
289
+ [Actions Documentation](https://caplin.github.io/FlexLayout/demos/v0.9/typedoc/classes/Actions.html)
307
290
 
308
- ### Examples
291
+ ### Example
309
292
 
310
293
  ```js
311
294
  model.doAction(FlexLayout.Actions.addNode(
@@ -313,178 +296,133 @@ model.doAction(FlexLayout.Actions.addNode(
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 id "1" and at the 0'th tab position (use value -1 to add to the end of the tabs).
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: you can get the id of a node (e.g., the node returned by the `addNode`
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 `addNode` 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
- There are many optional properties that can be applied to the layout:
307
+ Many optional properties can be applied to the layout:
338
308
 
339
- [Layout Properties doc](https://caplin.github.io/FlexLayout/demos/v0.8/typedoc/interfaces/ILayoutProps.html)
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 well defined as a set of TypeScript interfaces, see the doc for details of all the attributes allowed:
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
- ## Row Config Attributes
316
+ [Model Attributes Documentation](https://caplin.github.io/FlexLayout/demos/v0.9/typedoc/interfaces/IJsonModel.html)
355
317
 
356
- [Row Attributes doc](https://caplin.github.io/FlexLayout/demos/v0.8/typedoc/interfaces/IJsonRowNode.html)
318
+ [Global Attributes Documentation](https://caplin.github.io/FlexLayout/demos/v0.9/typedoc/interfaces/IGlobalAttributes.html)
357
319
 
358
- ## TabSet Config Attributes
320
+ [Row Attributes Documentation](https://caplin.github.io/FlexLayout/demos/v0.9/typedoc/interfaces/IJsonRowNode.html)
359
321
 
360
- [Tabset Attributes doc](https://caplin.github.io/FlexLayout/demos/v0.8/typedoc/interfaces/IJsonTabSetNode.html)
322
+ [Tabset Attributes Documentation](https://caplin.github.io/FlexLayout/demos/v0.9/typedoc/interfaces/IJsonTabSetNode.html)
361
323
 
362
- Note: tabsets will be dynamically created as tabs are moved, and deleted when all their tabs are removed (unless enableDeleteWhenEmpty is false).
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
- ## Tab Config attributes
326
+ [Tab Attributes Documentation](https://caplin.github.io/FlexLayout/demos/v0.9/typedoc/interfaces/IJsonTabNode.html)
365
327
 
366
- [Tab Attributes doc](https://caplin.github.io/FlexLayout/demos/v0.8/typedoc/interfaces/IJsonTabNode.html)
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
- layoutRef.current.addTabToTabSet("NAVIGATION", {type:"tab", component:"grid", name:"a grid"});
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 on nodes by adding a listener, this would typically be done
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
- function MyComponent({node}) {
399
-
400
- useEffect(() => {
401
- // save subject in flexlayout node tree
402
- node.setEventListener("save", () => {
403
- node.getConfig().subject = subject;
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 | parameters | Description |
411
- | ------------- |:-------------:| -----|
412
- | resize | {rect} | called when tab is resized during layout, called before it is rendered with the new size|
413
- | close | none | called when a tab is closed |
414
- | visibility | {visible} | called when the visibility of a tab changes |
415
- | save | none | called before a tabnode is serialized to json, use to save node config by adding data to the object returned by node.getConfig()|
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 use in multi-monitor setups)
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` attribute. When enabled, a popout icon appears in the tab header.
423
373
 
424
- For popouts to work there needs to be an additional html page 'popout.html' hosted
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 popouts are rendering into a different document to the main layout any code in the popped out
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
- const currentDocument = selfRef.current.ownerDocument;
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
- In the above code selfRef is a React ref to the toplevel element in the tab being rendered.
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
- Note: libraries may support popout windows by allowing you to specify the document to use,
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
- ### Limitations of Popouts
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
- * Your code must use the popout window/document in popout windows when adding event listeners (e.g popoutDocument.addEventListener(...)).
448
-
449
- * Timers throttle when main window is in the background
450
- you could implement a webworker timer replacement if needed (which will not throttle)
451
- * Many third party controls will use the global document for some event listeners,
452
- these will not work correctly without modification
453
- * Some third party controls will suspend when the global document is hidden
454
- you can use the tab overlay attribute to 'gray out' these tabs when the main window is hidden
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 Demo app:
409
+ Run the demo app:
472
410
 
473
411
  ```
474
412
  pnpm dev
475
413
  ```
476
414
 
477
- The 'pnpm dev' command will watch for changes to FlexLayout and the Demo, so you can make changes to the FlexLayout code and see the changes in your browser.
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 run the Playwright tests by running (in another terminal window)
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 'pnpm build'.
425
+ To build the npm distribution, run `pnpm build`.
488
426
 
489
427
  ## Alternative Layout Managers
490
428