flexlayout-react 0.6.8 → 0.7.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 (44) hide show
  1. package/.github/ISSUE_TEMPLATE/bug_report.yml +104 -0
  2. package/.github/ISSUE_TEMPLATE/config.yml +5 -0
  3. package/ChangeLog.txt +10 -0
  4. package/README.md +19 -8
  5. package/declarations/view/Icons.d.ts +0 -1
  6. package/declarations/view/Layout.d.ts +5 -3
  7. package/dist/flexlayout.js +9 -9
  8. package/dist/flexlayout.js.zip +0 -0
  9. package/dist/flexlayout_min.js +1 -1
  10. package/dist/flexlayout_min.js.zip +0 -0
  11. package/lib/PopupMenu.js.map +1 -1
  12. package/lib/index.js +5 -1
  13. package/lib/index.js.map +1 -1
  14. package/lib/model/Node.js +13 -8
  15. package/lib/model/Node.js.map +1 -1
  16. package/lib/model/TabSetNode.js +4 -1
  17. package/lib/model/TabSetNode.js.map +1 -1
  18. package/lib/view/BorderTabSet.js +1 -1
  19. package/lib/view/BorderTabSet.js.map +1 -1
  20. package/lib/view/ErrorBoundary.js.map +1 -1
  21. package/lib/view/Layout.js +7 -5
  22. package/lib/view/Layout.js.map +1 -1
  23. package/lib/view/TabOverflowHook.js +1 -1
  24. package/lib/view/TabOverflowHook.js.map +1 -1
  25. package/lib/view/TabSet.js +6 -1
  26. package/lib/view/TabSet.js.map +1 -1
  27. package/lib/view/Utils.js.map +1 -1
  28. package/package.json +18 -20
  29. package/src/PopupMenu.tsx +5 -5
  30. package/src/model/Node.ts +11 -7
  31. package/src/model/TabSetNode.ts +4 -1
  32. package/src/view/BorderButton.tsx +3 -3
  33. package/src/view/BorderTabSet.tsx +4 -4
  34. package/src/view/ErrorBoundary.tsx +1 -0
  35. package/src/view/Layout.tsx +12 -8
  36. package/src/view/TabButton.tsx +3 -3
  37. package/src/view/TabButtonStamp.tsx +3 -3
  38. package/src/view/TabOverflowHook.tsx +1 -1
  39. package/src/view/TabSet.tsx +8 -4
  40. package/src/view/Utils.tsx +3 -3
  41. package/style/dark.css +2 -2
  42. package/style/gray.css +2 -2
  43. package/style/light.css +2 -2
  44. package/style/underline.css +2 -2
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "flexlayout-react",
3
- "version": "0.6.8",
3
+ "version": "0.7.0",
4
4
  "description": "A multi-tab docking layout manager",
5
5
  "main": "lib/index.js",
6
6
  "types": "./declarations/index.d.ts",
@@ -36,35 +36,33 @@
36
36
  "repository": "https://github.com/caplin/FlexLayout",
37
37
  "license": "ISC",
38
38
  "peerDependencies": {
39
- "react": "^17.0.2",
40
- "react-dom": "^17.0.2"
39
+ "react": "^18.0.0",
40
+ "react-dom": "^18.0.0"
41
41
  },
42
42
  "eslintConfig": {
43
43
  "extends": "react-app"
44
44
  },
45
45
  "devDependencies": {
46
- "@cypress/react": "^5.10.3",
47
- "@cypress/webpack-dev-server": "^1.7.0",
48
- "@types/node": "^16.11.12",
49
- "@types/react": "^17.0.37",
50
- "@types/react-dom": "^17.0.11",
46
+ "@types/react": "^18.0.5",
47
+ "@types/react-dom": "^18.0.1",
48
+ "@cypress/react": "^5.12.4",
49
+ "@cypress/webpack-dev-server": "^1.8.4",
50
+ "@types/node": "^17.0.24",
51
51
  "@types/uuid": "^8.3.3",
52
- "css-loader": "^6.5.1",
53
- "cypress": "^9.1.1",
52
+ "css-loader": "^6.7.1",
53
+ "cypress": "^9.5.4",
54
54
  "html-webpack-plugin": "^5.5.0",
55
- "prettier": "^2.5.1",
56
- "react": "^17.0.2",
57
- "react-dom": "^17.0.2",
58
- "react-scripts": "5.0.0",
59
- "sass": "^1.45.0",
55
+ "prettier": "^2.6.2",
56
+ "react-scripts": "5.0.1",
57
+ "sass": "^1.50.0",
60
58
  "source-map-loader": "^3.0.0",
61
59
  "style-loader": "^3.3.1",
62
- "ts-loader": "~9.2.6",
63
- "typedoc": "^0.22.10",
64
- "typescript": "^4.5.4",
65
- "webpack": "^5.65.0",
60
+ "ts-loader": "~9.2.8",
61
+ "typedoc": "^0.22.15",
62
+ "typescript": "^4.6.3",
63
+ "webpack": "^5.72.0",
66
64
  "webpack-cli": "^4.9.1",
67
- "webpack-dev-server": "^4.6.0"
65
+ "webpack-dev-server": "^4.8.1"
68
66
  },
69
67
  "dependencies": {
70
68
  "uuid": "^8.3.2"
package/src/PopupMenu.tsx CHANGED
@@ -2,7 +2,7 @@ import * as React from "react";
2
2
  import { DragDrop } from "./DragDrop";
3
3
  import { TabNode } from "./model/TabNode";
4
4
  import { CLASSES } from "./Types";
5
- import { ILayoutCallbacks } from "./view/Layout";
5
+ import { IconFactory, ILayoutCallbacks, TitleFactory } from "./view/Layout";
6
6
  import { TabButtonStamp } from "./view/TabButtonStamp";
7
7
 
8
8
  /** @internal */
@@ -11,8 +11,8 @@ export function showPopup(
11
11
  items: { index: number; node: TabNode }[],
12
12
  onSelect: (item: { index: number; node: TabNode }) => void,
13
13
  layout: ILayoutCallbacks,
14
- iconFactory?: (node: TabNode) => React.ReactNode | undefined,
15
- titleFactory?: (node: TabNode) => React.ReactNode | undefined,
14
+ iconFactory?: IconFactory,
15
+ titleFactory?: TitleFactory,
16
16
  ) {
17
17
  const layoutDiv = layout.getRootDiv();
18
18
  const classNameMapper = layout.getClassName;
@@ -77,8 +77,8 @@ interface IPopupMenuProps {
77
77
  onSelect: (item: { index: number; node: TabNode }) => void;
78
78
  classNameMapper: (defaultClassName: string) => string;
79
79
  layout: ILayoutCallbacks;
80
- iconFactory?: (node: TabNode) => React.ReactNode | undefined;
81
- titleFactory?: (node: TabNode) => React.ReactNode | undefined;
80
+ iconFactory?: IconFactory;
81
+ titleFactory?: TitleFactory;
82
82
  }
83
83
 
84
84
  /** @internal */
package/src/model/Node.ts CHANGED
@@ -179,13 +179,17 @@ export abstract class Node {
179
179
  _findDropTargetNode(dragNode: Node & IDraggable, x: number, y: number): DropInfo | undefined {
180
180
  let rtn: DropInfo | undefined;
181
181
  if (this._rect.contains(x, y)) {
182
- rtn = this.canDrop(dragNode, x, y);
183
- if (rtn === undefined) {
184
- if (this._children.length !== 0) {
185
- for (const child of this._children) {
186
- rtn = child._findDropTargetNode(dragNode, x, y);
187
- if (rtn !== undefined) {
188
- break;
182
+ if (this._model.getMaximizedTabset() !== undefined) {
183
+ rtn = this._model.getMaximizedTabset()!.canDrop(dragNode, x, y);
184
+ } else {
185
+ rtn = this.canDrop(dragNode, x, y);
186
+ if (rtn === undefined) {
187
+ if (this._children.length !== 0) {
188
+ for (const child of this._children) {
189
+ rtn = child._findDropTargetNode(dragNode, x, y);
190
+ if (rtn !== undefined) {
191
+ break;
192
+ }
189
193
  }
190
194
  }
191
195
  }
@@ -274,7 +274,10 @@ export class TabSetNode extends Node implements IDraggable, IDropTarget {
274
274
  const outlineRect = this._tabHeaderRect;
275
275
  dropInfo = new DropInfo(this, outlineRect!, dockLocation, -1, CLASSES.FLEXLAYOUT__OUTLINE_RECT);
276
276
  } else if (this._contentRect!.contains(x, y)) {
277
- const dockLocation = DockLocation.getLocation(this._contentRect!, x, y);
277
+ let dockLocation = DockLocation.CENTER;
278
+ if (this._model.getMaximizedTabset() === undefined) {
279
+ dockLocation = DockLocation.getLocation(this._contentRect!, x, y);
280
+ }
278
281
  const outlineRect = dockLocation.getDockRect(this._rect);
279
282
  dropInfo = new DropInfo(this, outlineRect, dockLocation, -1, CLASSES.FLEXLAYOUT__OUTLINE_RECT);
280
283
  } else if (this._tabHeaderRect != null && this._tabHeaderRect.contains(x, y)) {
@@ -3,7 +3,7 @@ import { I18nLabel } from "../I18nLabel";
3
3
  import { Actions } from "../model/Actions";
4
4
  import { TabNode } from "../model/TabNode";
5
5
  import { Rect } from "../Rect";
6
- import { IIcons, ILayoutCallbacks } from "./Layout";
6
+ import { IconFactory, IIcons, ILayoutCallbacks, TitleFactory } from "./Layout";
7
7
  import { ICloseType } from "../model/ICloseType";
8
8
  import { CLASSES } from "../Types";
9
9
  import { getRenderStateEx, isAuxMouseEvent } from "./Utils";
@@ -14,8 +14,8 @@ export interface IBorderButtonProps {
14
14
  node: TabNode;
15
15
  selected: boolean;
16
16
  border: string;
17
- iconFactory?: (node: TabNode) => React.ReactNode | undefined;
18
- titleFactory?: (node: TabNode) => React.ReactNode | undefined;
17
+ iconFactory?: IconFactory;
18
+ titleFactory?: TitleFactory;
19
19
  icons: IIcons;
20
20
  path: string;
21
21
  }
@@ -3,7 +3,7 @@ import { DockLocation } from "../DockLocation";
3
3
  import { BorderNode } from "../model/BorderNode";
4
4
  import { TabNode } from "../model/TabNode";
5
5
  import { BorderButton } from "./BorderButton";
6
- import { IIcons, ILayoutCallbacks } from "./Layout";
6
+ import { IIcons, ILayoutCallbacks, ITitleObject } from "./Layout";
7
7
  import { showPopup } from "../PopupMenu";
8
8
  import { Actions } from "../model/Actions";
9
9
  import { I18nLabel } from "../I18nLabel";
@@ -16,8 +16,8 @@ import { isAuxMouseEvent } from "./Utils";
16
16
  export interface IBorderTabSetProps {
17
17
  border: BorderNode;
18
18
  layout: ILayoutCallbacks;
19
- iconFactory?: (node: TabNode) => React.ReactNode | undefined;
20
- titleFactory?: (node: TabNode) => React.ReactNode | undefined;
19
+ iconFactory?: (node: TabNode) => (React.ReactNode | undefined);
20
+ titleFactory?: (node: TabNode) => (ITitleObject | React.ReactNode | undefined);
21
21
  icons: IIcons;
22
22
  path: string;
23
23
  }
@@ -114,7 +114,7 @@ export const BorderTabSet = (props: IBorderTabSetProps) => {
114
114
 
115
115
  // allow customization of tabset right/bottom buttons
116
116
  let buttons: any[] = [];
117
- const renderState = { headerContent: {}, buttons, stickyButtons: [], headerButtons: [] };
117
+ const renderState = { headerContent: undefined, buttons, stickyButtons: [], headerButtons: [] };
118
118
  layout.customizeTabSet(border, renderState);
119
119
  buttons = renderState.buttons;
120
120
 
@@ -5,6 +5,7 @@ import { CLASSES } from "../Types";
5
5
  /** @internal */
6
6
  export interface IErrorBoundaryProps {
7
7
  message: string;
8
+ children: React.ReactNode;
8
9
  }
9
10
  /** @internal */
10
11
  export interface IErrorBoundaryState {
@@ -1,5 +1,5 @@
1
1
  import * as React from "react";
2
- import * as ReactDOM from "react-dom";
2
+ import { createPortal } from "react-dom";
3
3
  import { DockLocation } from "../DockLocation";
4
4
  import { DragDrop } from "../DragDrop";
5
5
  import { DropInfo } from "../DropInfo";
@@ -40,14 +40,16 @@ export type ShowOverflowMenuCallback = (
40
40
  onSelect: (item: { index: number; node: TabNode }) => void,
41
41
  ) => void;
42
42
  export type TabSetPlaceHolderCallback = (node: TabSetNode) => React.ReactNode;
43
+ export type IconFactory = (node: TabNode) => React.ReactNode;
44
+ export type TitleFactory = (node: TabNode) => ITitleObject | React.ReactNode;
43
45
 
44
46
  export interface ILayoutProps {
45
47
  model: Model;
46
48
  factory: (node: TabNode) => React.ReactNode;
47
49
  font?: IFontValues;
48
50
  fontFamily?: string;
49
- iconFactory?: (node: TabNode) => React.ReactNode | undefined;
50
- titleFactory?: (node: TabNode) => ITitleObject | React.ReactNode | undefined;
51
+ iconFactory?: IconFactory;
52
+ titleFactory?: TitleFactory;
51
53
  icons?: IIcons;
52
54
  onAction?: (action: Action) => Action | undefined;
53
55
  onRenderTab?: (
@@ -120,7 +122,7 @@ export interface ILayoutState {
120
122
  calculatedBorderBarSize: number;
121
123
  editingTab?: TabNode;
122
124
  showHiddenBorder: DockLocation;
123
- portal?: React.ReactNode;
125
+ portal?: React.ReactPortal;
124
126
  }
125
127
 
126
128
  export interface IIcons {
@@ -742,7 +744,7 @@ export class Layout extends React.Component<ILayoutProps, ILayoutState> {
742
744
  this.dragDiv = this.currentDocument!.createElement("div");
743
745
  this.dragDiv.className = this.getClassName(CLASSES.FLEXLAYOUT__DRAG_RECT);
744
746
  this.dragDiv.addEventListener("mousedown", this.onDragDivMouseDown);
745
- this.dragDiv.addEventListener("touchstart", this.onDragDivMouseDown);
747
+ this.dragDiv.addEventListener("touchstart", this.onDragDivMouseDown, {passive: false});
746
748
 
747
749
  this.dragRectRender(this.dragDivText, undefined, this.newTabJson, () => {
748
750
  if (this.dragDiv) {
@@ -833,7 +835,7 @@ export class Layout extends React.Component<ILayoutProps, ILayoutState> {
833
835
  onClick?: (event: Event) => void,
834
836
  onDoubleClick?: (event: Event) => void
835
837
  ) => {
836
- if (this.props.model.getMaximizedTabset() !== undefined || !allowDrag) {
838
+ if (!allowDrag) {
837
839
  DragDrop.instance.startDrag(event, undefined, undefined, undefined, undefined, onClick, onDoubleClick, this.currentDocument, this.selfRef.current!);
838
840
  } else {
839
841
  this.dragNode = node;
@@ -883,7 +885,7 @@ export class Layout extends React.Component<ILayoutProps, ILayoutState> {
883
885
 
884
886
  /** @internal */
885
887
  showPortal = (control: React.ReactNode, element: HTMLElement) => {
886
- const portal = ReactDOM.createPortal(control, element);
888
+ const portal = createPortal(control, element) as React.ReactPortal;
887
889
  this.setState({ portal });
888
890
  };
889
891
 
@@ -911,7 +913,9 @@ export class Layout extends React.Component<ILayoutProps, ILayoutState> {
911
913
  rootdiv.appendChild(this.dragDiv);
912
914
  }
913
915
  // add edge indicators
914
- this.showEdges(rootdiv);
916
+ if (this.props.model.getMaximizedTabset() === undefined) {
917
+ this.showEdges(rootdiv);
918
+ }
915
919
 
916
920
  if (this.dragNode !== undefined && this.dragNode instanceof TabNode && this.dragNode.getTabRect() !== undefined) {
917
921
  this.dragNode.getTabRect()!.positionElement(this.outlineDiv);
@@ -4,7 +4,7 @@ import { Actions } from "../model/Actions";
4
4
  import { TabNode } from "../model/TabNode";
5
5
  import { TabSetNode } from "../model/TabSetNode";
6
6
  import { Rect } from "../Rect";
7
- import { IIcons, ILayoutCallbacks } from "./Layout";
7
+ import { IconFactory, IIcons, ILayoutCallbacks, TitleFactory } from "./Layout";
8
8
  import { ICloseType } from "../model/ICloseType";
9
9
  import { CLASSES } from "../Types";
10
10
  import { getRenderStateEx, isAuxMouseEvent } from "./Utils";
@@ -14,8 +14,8 @@ export interface ITabButtonProps {
14
14
  layout: ILayoutCallbacks;
15
15
  node: TabNode;
16
16
  selected: boolean;
17
- iconFactory?: (node: TabNode) => React.ReactNode | undefined;
18
- titleFactory?: (node: TabNode) => React.ReactNode | undefined;
17
+ iconFactory?: IconFactory;
18
+ titleFactory?: TitleFactory;
19
19
  icons: IIcons;
20
20
  path: string;
21
21
  }
@@ -1,6 +1,6 @@
1
1
  import * as React from "react";
2
2
  import { TabNode } from "../model/TabNode";
3
- import { ILayoutCallbacks } from "./Layout";
3
+ import { IconFactory, ILayoutCallbacks, TitleFactory } from "./Layout";
4
4
  import { CLASSES } from "../Types";
5
5
  import { getRenderStateEx } from "./Utils";
6
6
 
@@ -8,8 +8,8 @@ import { getRenderStateEx } from "./Utils";
8
8
  export interface ITabButtonStampProps {
9
9
  node: TabNode;
10
10
  layout: ILayoutCallbacks;
11
- iconFactory?: (node: TabNode) => React.ReactNode | undefined;
12
- titleFactory?: (node: TabNode) => React.ReactNode | undefined;
11
+ iconFactory?: IconFactory;
12
+ titleFactory?: TitleFactory;
13
13
  }
14
14
 
15
15
  /** @internal */
@@ -33,7 +33,7 @@ export const useTabOverflow = (
33
33
 
34
34
  React.useEffect(() => {
35
35
  const instance = selfRef.current!;
36
- instance.addEventListener('wheel', onWheel);
36
+ instance.addEventListener('wheel', onWheel, { passive: false });
37
37
  return () => {
38
38
  instance.removeEventListener('wheel', onWheel);
39
39
  }
@@ -4,7 +4,7 @@ import { Actions } from "../model/Actions";
4
4
  import { TabNode } from "../model/TabNode";
5
5
  import { TabSetNode } from "../model/TabSetNode";
6
6
  import { showPopup } from "../PopupMenu";
7
- import { IIcons, ILayoutCallbacks } from "./Layout";
7
+ import { IIcons, ILayoutCallbacks, ITitleObject } from "./Layout";
8
8
  import { TabButton } from "./TabButton";
9
9
  import { useTabOverflow } from "./TabOverflowHook";
10
10
  import { Orientation } from "../Orientation";
@@ -15,8 +15,8 @@ import { hideElement, isAuxMouseEvent } from "./Utils";
15
15
  export interface ITabSetProps {
16
16
  layout: ILayoutCallbacks;
17
17
  node: TabSetNode;
18
- iconFactory?: (node: TabNode) => React.ReactNode | undefined;
19
- titleFactory?: (node: TabNode) => React.ReactNode | undefined;
18
+ iconFactory?: (node: TabNode) => (React.ReactNode | undefined);
19
+ titleFactory?: (node: TabNode) => (ITitleObject | React.ReactNode | undefined);
20
20
  icons: IIcons;
21
21
  editingTab?: TabNode;
22
22
  path?: string;
@@ -67,7 +67,11 @@ export const TabSet = (props: ITabSetProps) => {
67
67
  layout.doAction(Actions.setActiveTabset(node.getId()));
68
68
  if (!layout.getEditingTab()) {
69
69
  const message = layout.i18nName(I18nLabel.Move_Tabset, name);
70
- layout.dragStart(event, message, node, node.isEnableDrag(), (event2: Event) => undefined, onDoubleClick);
70
+ if (node.getModel().getMaximizedTabset() !== undefined) {
71
+ layout.dragStart(event, message, node, false, (event2: Event) => undefined, onDoubleClick);
72
+ } else {
73
+ layout.dragStart(event, message, node, node.isEnableDrag(), (event2: Event) => undefined, onDoubleClick);
74
+ }
71
75
  }
72
76
  }
73
77
  };
@@ -1,13 +1,13 @@
1
1
  import * as React from "react";
2
2
  import { TabNode } from "../model/TabNode";
3
- import { ILayoutCallbacks, ITitleObject } from "./Layout";
3
+ import { IconFactory, ILayoutCallbacks, ITitleObject, TitleFactory } from "./Layout";
4
4
 
5
5
  /** @internal */
6
6
  export function getRenderStateEx(
7
7
  layout: ILayoutCallbacks,
8
8
  node: TabNode,
9
- iconFactory?: (node: TabNode) => React.ReactNode | undefined,
10
- titleFactory?: (node: TabNode) => React.ReactNode | undefined
9
+ iconFactory?: IconFactory,
10
+ titleFactory?: TitleFactory
11
11
  ) {
12
12
  let leadingContent = iconFactory ? iconFactory(node) : undefined;
13
13
  let titleContent: React.ReactNode = node.getName();
package/style/dark.css CHANGED
@@ -8,8 +8,8 @@
8
8
  --color-4: #333333;
9
9
  --color-5: #404040;
10
10
  --color-6: #4d4d4d;
11
- --color-drag1: #cfe8ff;
12
- --color-drag2: #b7d1b5;
11
+ --color-drag1: rgb(207, 232, 255);
12
+ --color-drag2: rgb(183, 209, 181);
13
13
  --color-drag1-background: rgba(128, 128, 128, 0.15);
14
14
  --color-drag2-background: rgba(128, 128, 128, 0.15);
15
15
  --font-size: medium;
package/style/gray.css CHANGED
@@ -8,8 +8,8 @@
8
8
  --color-4: #cccccc;
9
9
  --color-5: #bfbfbf;
10
10
  --color-6: #b3b3b3;
11
- --color-drag1: #5f86c4;
12
- --color-drag2: #77a677;
11
+ --color-drag1: rgb(95, 134, 196);
12
+ --color-drag2: rgb(119, 166, 119);
13
13
  --color-drag1-background: rgba(95, 134, 196, 0.1);
14
14
  --color-drag2-background: rgba(119, 166, 119, 0.075);
15
15
  --font-size: medium;
package/style/light.css CHANGED
@@ -8,8 +8,8 @@
8
8
  --color-4: #e2e2e2;
9
9
  --color-5: #dbdbdb;
10
10
  --color-6: #d4d4d4;
11
- --color-drag1: #5f86c4;
12
- --color-drag2: #77a677;
11
+ --color-drag1: rgb(95, 134, 196);
12
+ --color-drag2: rgb(119, 166, 119);
13
13
  --color-drag1-background: rgba(95, 134, 196, 0.1);
14
14
  --color-drag2-background: rgba(119, 166, 119, 0.075);
15
15
  --font-size: medium;
@@ -8,8 +8,8 @@
8
8
  --color-4: #e6e6e6;
9
9
  --color-5: #e0e0e0;
10
10
  --color-6: #d9d9d9;
11
- --color-drag1: #5f86c4;
12
- --color-drag2: #77a677;
11
+ --color-drag1: rgb(95, 134, 196);
12
+ --color-drag2: rgb(119, 166, 119);
13
13
  --color-drag1-background: rgba(95, 134, 196, 0.1);
14
14
  --color-drag2-background: rgba(119, 166, 119, 0.075);
15
15
  --font-size: medium;