flexlayout-react 0.5.18 → 0.6.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/ChangeLog.txt +27 -0
- package/README.md +126 -108
- package/declarations/Types.d.ts +8 -1
- package/declarations/model/IJsonModel.d.ts +3 -0
- package/declarations/model/Model.d.ts +2 -0
- package/declarations/view/Icons.d.ts +6 -0
- package/declarations/view/Layout.d.ts +8 -4
- package/declarations/view/MenuTabButton.d.ts +1 -0
- package/declarations/view/TabButtonStamp.d.ts +1 -0
- package/declarations/view/Utils.d.ts +1 -0
- package/dist/flexlayout.js +53 -17
- package/dist/flexlayout_min.js +1 -1
- package/lib/PopupMenu.js +22 -12
- package/lib/PopupMenu.js.map +1 -1
- package/lib/Types.js +7 -0
- package/lib/Types.js.map +1 -1
- package/lib/model/BorderNode.js +8 -7
- package/lib/model/BorderNode.js.map +1 -1
- package/lib/model/Model.js +15 -3
- package/lib/model/Model.js.map +1 -1
- package/lib/model/RowNode.js +19 -5
- package/lib/model/RowNode.js.map +1 -1
- package/lib/model/TabNode.js +6 -1
- package/lib/model/TabNode.js.map +1 -1
- package/lib/model/TabSetNode.js +8 -4
- package/lib/model/TabSetNode.js.map +1 -1
- package/lib/view/BorderButton.js +19 -38
- package/lib/view/BorderButton.js.map +1 -1
- package/lib/view/BorderTabSet.js +19 -8
- package/lib/view/BorderTabSet.js.map +1 -1
- package/lib/view/FloatingWindow.js +13 -5
- package/lib/view/FloatingWindow.js.map +1 -1
- package/lib/view/Icons.js +36 -0
- package/lib/view/Icons.js.map +1 -0
- package/lib/view/Layout.js +148 -71
- package/lib/view/Layout.js.map +1 -1
- package/lib/view/MenuTabButton.js +22 -0
- package/lib/view/MenuTabButton.js.map +1 -0
- package/lib/view/Splitter.js +3 -3
- package/lib/view/Splitter.js.map +1 -1
- package/lib/view/Tab.js +9 -6
- package/lib/view/Tab.js.map +1 -1
- package/lib/view/TabButton.js +20 -44
- package/lib/view/TabButton.js.map +1 -1
- package/lib/view/TabButtonStamp.js +22 -0
- package/lib/view/TabButtonStamp.js.map +1 -0
- package/lib/view/TabFloating.js +29 -15
- package/lib/view/TabFloating.js.map +1 -1
- package/lib/view/TabOverflowHook.js +1 -1
- package/lib/view/TabSet.js +40 -25
- package/lib/view/TabSet.js.map +1 -1
- package/lib/view/Utils.js +61 -0
- package/lib/view/Utils.js.map +1 -0
- package/package.json +11 -6
- package/src/I18nLabel.ts +1 -1
- package/src/PopupMenu.tsx +54 -15
- package/src/Types.ts +7 -0
- package/src/model/BorderNode.ts +8 -7
- package/src/model/IJsonModel.ts +3 -0
- package/src/model/Model.ts +19 -3
- package/src/model/RowNode.ts +8 -5
- package/src/model/TabNode.ts +6 -1
- package/src/model/TabSetNode.ts +8 -4
- package/src/view/BorderButton.tsx +38 -43
- package/src/view/BorderTabSet.tsx +34 -7
- package/src/view/FloatingWindow.tsx +14 -6
- package/src/view/Icons.tsx +36 -0
- package/src/view/Layout.tsx +179 -88
- package/src/view/Splitter.tsx +4 -1
- package/src/view/Tab.tsx +17 -6
- package/src/view/TabButton.tsx +42 -55
- package/src/view/TabButtonStamp.tsx +47 -0
- package/src/view/TabFloating.tsx +47 -23
- package/src/view/TabOverflowHook.tsx +1 -1
- package/src/view/TabSet.tsx +71 -22
- package/src/view/Utils.tsx +71 -0
- package/style/_base.scss +146 -92
- package/style/dark.css +157 -129
- package/style/dark.css.map +1 -1
- package/style/dark.scss +31 -21
- package/style/gray.css +157 -129
- package/style/gray.css.map +1 -1
- package/style/gray.scss +30 -23
- package/style/light.css +157 -129
- package/style/light.css.map +1 -1
- package/style/light.scss +30 -20
- package/images/close.png +0 -0
- package/images/maximize.png +0 -0
- package/images/more.png +0 -0
- package/images/more2.png +0 -0
- package/images/popout.png +0 -0
- package/images/restore.png +0 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "flexlayout-react",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
4
4
|
"description": "A multi-tab docking layout manager",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"types": "./declarations/index.d.ts",
|
|
@@ -20,14 +20,16 @@
|
|
|
20
20
|
],
|
|
21
21
|
"scripts": {
|
|
22
22
|
"start": "webpack serve",
|
|
23
|
-
"build": "npm run
|
|
23
|
+
"build": " npm run css && npm run test && npm run build:commonjs && npm run build:umd && npm run build:umd:min",
|
|
24
24
|
"build:commonjs": "tsc -p tsconfig2.json",
|
|
25
25
|
"build:umd": "webpack --mode=development --config webpack_build.config.js",
|
|
26
26
|
"build:umd:min": "webpack --mode=production --config webpack_build_min.config.js",
|
|
27
|
-
"test": "jasmine",
|
|
28
27
|
"lint:eslint": "eslint src/*",
|
|
29
28
|
"doc": "typedoc --out typedoc --exclude \"**/examples/**/*.tsx\" --excludeInternal --disableSources --excludePrivate --excludeProtected --readme none ./src",
|
|
30
|
-
"css": "sass style/gray.scss style/gray.css && sass style/light.scss style/light.css && sass style/dark.scss style/dark.css"
|
|
29
|
+
"css": "sass style/gray.scss style/gray.css && sass style/light.scss style/light.css && sass style/light.scss test/style/light.css && sass style/dark.scss style/dark.css",
|
|
30
|
+
"cypress": "cypress open-ct",
|
|
31
|
+
"cypress-firefox": "cypress open-ct --browser firefox",
|
|
32
|
+
"test": "cypress run-ct"
|
|
31
33
|
},
|
|
32
34
|
"author": "Caplin Systems Ltd",
|
|
33
35
|
"repository": "https://github.com/caplin/FlexLayout",
|
|
@@ -40,14 +42,17 @@
|
|
|
40
42
|
"extends": "react-app"
|
|
41
43
|
},
|
|
42
44
|
"devDependencies": {
|
|
43
|
-
"@
|
|
45
|
+
"@cypress/react": "^5.10.2",
|
|
46
|
+
"@cypress/webpack-dev-server": "^1.7.0",
|
|
44
47
|
"@types/node": "^15.0.2",
|
|
45
48
|
"@types/react": "^17.0.5",
|
|
46
49
|
"@types/react-dom": "^17.0.4",
|
|
47
50
|
"@types/uuid": "^8.3.1",
|
|
48
51
|
"awesome-typescript-loader": "^5.2.0",
|
|
49
|
-
"
|
|
52
|
+
"cypress": "^8.7.0",
|
|
50
53
|
"prettier": "^2.3.0",
|
|
54
|
+
"react": "^17.0.2",
|
|
55
|
+
"react-dom": "^17.0.2",
|
|
51
56
|
"react-scripts": "4.0.3",
|
|
52
57
|
"sass": "^1.32.12",
|
|
53
58
|
"source-map-loader": "^1.1.2",
|
package/src/I18nLabel.ts
CHANGED
package/src/PopupMenu.tsx
CHANGED
|
@@ -1,21 +1,28 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
2
|
import * as ReactDOM from "react-dom";
|
|
3
|
+
import { DragDrop } from ".";
|
|
3
4
|
import TabNode from "./model/TabNode";
|
|
5
|
+
import { CLASSES } from "./Types";
|
|
6
|
+
import { ILayoutCallbacks } from "./view/Layout";
|
|
7
|
+
import { TabButtonStamp } from "./view/TabButtonStamp";
|
|
4
8
|
|
|
5
9
|
/** @hidden @internal */
|
|
6
10
|
export function showPopup(
|
|
7
|
-
layoutDiv: HTMLDivElement,
|
|
8
11
|
triggerElement: Element,
|
|
9
12
|
items: { index: number; node: TabNode }[],
|
|
10
13
|
onSelect: (item: { index: number; node: TabNode }) => void,
|
|
11
|
-
|
|
14
|
+
layout: ILayoutCallbacks,
|
|
15
|
+
iconFactory?: (node: TabNode) => React.ReactNode | undefined,
|
|
16
|
+
titleFactory?: (node: TabNode) => React.ReactNode | undefined,
|
|
12
17
|
) {
|
|
18
|
+
const layoutDiv = layout.getRootDiv();
|
|
19
|
+
const classNameMapper = layout.getClassName;
|
|
13
20
|
const currentDocument = triggerElement.ownerDocument;
|
|
14
21
|
const triggerRect = triggerElement.getBoundingClientRect();
|
|
15
22
|
const layoutRect = layoutDiv.getBoundingClientRect();
|
|
16
23
|
|
|
17
24
|
const elm = currentDocument.createElement("div");
|
|
18
|
-
elm.className = classNameMapper(
|
|
25
|
+
elm.className = classNameMapper(CLASSES.FLEXLAYOUT__POPUP_MENU_CONTAINER);
|
|
19
26
|
if (triggerRect.left < layoutRect.left + layoutRect.width / 2) {
|
|
20
27
|
elm.style.left = triggerRect.left - layoutRect.left + "px";
|
|
21
28
|
} else {
|
|
@@ -27,27 +34,40 @@ export function showPopup(
|
|
|
27
34
|
} else {
|
|
28
35
|
elm.style.bottom = layoutRect.bottom - triggerRect.bottom + "px";
|
|
29
36
|
}
|
|
37
|
+
DragDrop.instance.addGlass(() => onHide());
|
|
38
|
+
DragDrop.instance.setGlassCursorOverride("default");
|
|
39
|
+
|
|
30
40
|
layoutDiv.appendChild(elm);
|
|
31
41
|
|
|
32
42
|
const onHide = () => {
|
|
43
|
+
DragDrop.instance.hideGlass();
|
|
33
44
|
layoutDiv.removeChild(elm);
|
|
34
45
|
ReactDOM.unmountComponentAtNode(elm);
|
|
35
|
-
elm.removeEventListener("
|
|
36
|
-
currentDocument.removeEventListener("
|
|
46
|
+
elm.removeEventListener("mousedown", onElementMouseDown);
|
|
47
|
+
currentDocument.removeEventListener("mousedown", onDocMouseDown);
|
|
37
48
|
};
|
|
38
49
|
|
|
39
|
-
const
|
|
50
|
+
const onElementMouseDown = (event: Event) => {
|
|
40
51
|
event.stopPropagation();
|
|
41
52
|
};
|
|
42
53
|
|
|
43
|
-
const
|
|
54
|
+
const onDocMouseDown = (event: Event) => {
|
|
44
55
|
onHide();
|
|
45
56
|
};
|
|
46
57
|
|
|
47
|
-
elm.addEventListener("
|
|
48
|
-
currentDocument.addEventListener("
|
|
58
|
+
elm.addEventListener("mousedown", onElementMouseDown);
|
|
59
|
+
currentDocument.addEventListener("mousedown", onDocMouseDown);
|
|
49
60
|
|
|
50
|
-
ReactDOM.render(<PopupMenu
|
|
61
|
+
ReactDOM.render(<PopupMenu
|
|
62
|
+
currentDocument={currentDocument}
|
|
63
|
+
onSelect={onSelect}
|
|
64
|
+
onHide={onHide}
|
|
65
|
+
items={items}
|
|
66
|
+
classNameMapper={classNameMapper}
|
|
67
|
+
layout={layout}
|
|
68
|
+
iconFactory={iconFactory}
|
|
69
|
+
titleFactory={titleFactory}
|
|
70
|
+
/>, elm);
|
|
51
71
|
}
|
|
52
72
|
|
|
53
73
|
/** @hidden @internal */
|
|
@@ -57,11 +77,14 @@ interface IPopupMenuProps {
|
|
|
57
77
|
onHide: () => void;
|
|
58
78
|
onSelect: (item: { index: number; node: TabNode }) => void;
|
|
59
79
|
classNameMapper: (defaultClassName: string) => string;
|
|
80
|
+
layout: ILayoutCallbacks;
|
|
81
|
+
iconFactory?: (node: TabNode) => React.ReactNode | undefined;
|
|
82
|
+
titleFactory?: (node: TabNode) => React.ReactNode | undefined;
|
|
60
83
|
}
|
|
61
84
|
|
|
62
85
|
/** @hidden @internal */
|
|
63
86
|
const PopupMenu = (props: IPopupMenuProps) => {
|
|
64
|
-
const { items, onHide, onSelect, classNameMapper } = props;
|
|
87
|
+
const { items, onHide, onSelect, classNameMapper, layout, iconFactory, titleFactory} = props;
|
|
65
88
|
|
|
66
89
|
const onItemClick = (item: { index: number; node: TabNode }, event: React.MouseEvent<HTMLDivElement, MouseEvent>) => {
|
|
67
90
|
onSelect(item);
|
|
@@ -69,11 +92,27 @@ const PopupMenu = (props: IPopupMenuProps) => {
|
|
|
69
92
|
event.stopPropagation();
|
|
70
93
|
};
|
|
71
94
|
|
|
72
|
-
const itemElements = items.map((item) => (
|
|
73
|
-
<div key={item.index}
|
|
74
|
-
{
|
|
95
|
+
const itemElements = items.map((item, i) => (
|
|
96
|
+
<div key={item.index}
|
|
97
|
+
className={classNameMapper(CLASSES.FLEXLAYOUT__POPUP_MENU_ITEM)}
|
|
98
|
+
data-layout-path={"/popup-menu/tb" + i}
|
|
99
|
+
onClick={(event) => onItemClick(item, event)}
|
|
100
|
+
title={item.node.getHelpText()} >
|
|
101
|
+
{item.node.getModel().isLegacyOverflowMenu() ?
|
|
102
|
+
item.node._getNameForOverflowMenu() :
|
|
103
|
+
<TabButtonStamp
|
|
104
|
+
node={item.node}
|
|
105
|
+
layout={layout}
|
|
106
|
+
iconFactory={iconFactory}
|
|
107
|
+
titleFactory={titleFactory}
|
|
108
|
+
/>}
|
|
75
109
|
</div>
|
|
76
110
|
));
|
|
77
111
|
|
|
78
|
-
return
|
|
112
|
+
return (
|
|
113
|
+
<div className={classNameMapper(CLASSES.FLEXLAYOUT__POPUP_MENU)}
|
|
114
|
+
data-layout-path="/popup-menu"
|
|
115
|
+
>
|
|
116
|
+
{itemElements}
|
|
117
|
+
</div>);
|
|
79
118
|
};
|
package/src/Types.ts
CHANGED
|
@@ -9,6 +9,8 @@ export enum CLASSES {
|
|
|
9
9
|
FLEXLAYOUT__BORDER_BUTTON_TRAILING = "flexlayout__border_button_trailing",
|
|
10
10
|
FLEXLAYOUT__BORDER_BUTTON__SELECTED = "flexlayout__border_button--selected",
|
|
11
11
|
FLEXLAYOUT__BORDER_BUTTON__UNSELECTED = "flexlayout__border_button--unselected",
|
|
12
|
+
FLEXLAYOUT__BORDER_TOOLBAR_BUTTON_OVERFLOW = "flexlayout__border_toolbar_button_overflow",
|
|
13
|
+
FLEXLAYOUT__BORDER_TOOLBAR_BUTTON_OVERFLOW_ = "flexlayout__border_toolbar_button_overflow_",
|
|
12
14
|
|
|
13
15
|
FLEXLAYOUT__BORDER_INNER = "flexlayout__border_inner",
|
|
14
16
|
FLEXLAYOUT__BORDER_INNER_ = "flexlayout__border_inner_",
|
|
@@ -34,6 +36,7 @@ export enum CLASSES {
|
|
|
34
36
|
FLEXLAYOUT__LAYOUT = "flexlayout__layout",
|
|
35
37
|
|
|
36
38
|
FLEXLAYOUT__OUTLINE_RECT = "flexlayout__outline_rect",
|
|
39
|
+
FLEXLAYOUT__OUTLINE_RECT_EDGE = "flexlayout__outline_rect_edge",
|
|
37
40
|
|
|
38
41
|
FLEXLAYOUT__SPLITTER = "flexlayout__splitter",
|
|
39
42
|
FLEXLAYOUT__SPLITTER_EXTRA = "flexlayout__splitter_extra",
|
|
@@ -67,6 +70,7 @@ export enum CLASSES {
|
|
|
67
70
|
FLEXLAYOUT__TAB_BUTTON_OVERFLOW = "flexlayout__tab_button_overflow",
|
|
68
71
|
FLEXLAYOUT__TAB_BUTTON_TEXTBOX = "flexlayout__tab_button_textbox",
|
|
69
72
|
FLEXLAYOUT__TAB_BUTTON_TRAILING = "flexlayout__tab_button_trailing",
|
|
73
|
+
FLEXLAYOUT__TAB_BUTTON_STAMP = "flexlayout__tab_button_stamp",
|
|
70
74
|
|
|
71
75
|
FLEXLAYOUT__TAB_FLOATING = "flexlayout__tab_floating",
|
|
72
76
|
FLEXLAYOUT__TAB_FLOATING_INNER = "flexlayout__tab_floating_inner",
|
|
@@ -78,4 +82,7 @@ export enum CLASSES {
|
|
|
78
82
|
FLEXLAYOUT__TAB_TOOLBAR_STICKY_BUTTONS_CONTAINER = "flexlayout__tab_toolbar_sticky_buttons_container",
|
|
79
83
|
FLEXLAYOUT__TAB_TOOLBAR_BUTTON_CLOSE = "flexlayout__tab_toolbar_button-close",
|
|
80
84
|
|
|
85
|
+
FLEXLAYOUT__POPUP_MENU_CONTAINER = "flexlayout__popup_menu_container",
|
|
86
|
+
FLEXLAYOUT__POPUP_MENU_ITEM = "flexlayout__popup_menu_item",
|
|
87
|
+
FLEXLAYOUT__POPUP_MENU = "flexlayout__popup_menu",
|
|
81
88
|
}
|
package/src/model/BorderNode.ts
CHANGED
|
@@ -4,6 +4,7 @@ import DockLocation from "../DockLocation";
|
|
|
4
4
|
import DropInfo from "../DropInfo";
|
|
5
5
|
import Orientation from "../Orientation";
|
|
6
6
|
import Rect from "../Rect";
|
|
7
|
+
import { CLASSES } from "../Types";
|
|
7
8
|
import IDraggable from "./IDraggable";
|
|
8
9
|
import IDropTarget from "./IDropTarget";
|
|
9
10
|
import { IJsonBorderNode } from "./IJsonModel";
|
|
@@ -309,18 +310,18 @@ class BorderNode extends Node implements IDropTarget {
|
|
|
309
310
|
childCenter = childRect.x + childRect.width / 2;
|
|
310
311
|
if (x >= pos && x < childCenter) {
|
|
311
312
|
const outlineRect = new Rect(childRect.x - 2, childY, 3, childHeight);
|
|
312
|
-
dropInfo = new DropInfo(this, outlineRect, dockLocation, i,
|
|
313
|
+
dropInfo = new DropInfo(this, outlineRect, dockLocation, i, CLASSES.FLEXLAYOUT__OUTLINE_RECT);
|
|
313
314
|
break;
|
|
314
315
|
}
|
|
315
316
|
pos = childCenter;
|
|
316
317
|
}
|
|
317
318
|
if (dropInfo == null) {
|
|
318
319
|
const outlineRect = new Rect(childRect.getRight() - 2, childY, 3, childHeight);
|
|
319
|
-
dropInfo = new DropInfo(this, outlineRect, dockLocation, this._children.length,
|
|
320
|
+
dropInfo = new DropInfo(this, outlineRect, dockLocation, this._children.length, CLASSES.FLEXLAYOUT__OUTLINE_RECT);
|
|
320
321
|
}
|
|
321
322
|
} else {
|
|
322
323
|
const outlineRect = new Rect(this._tabHeaderRect!.x + 1, this._tabHeaderRect!.y + 2, 3, 18);
|
|
323
|
-
dropInfo = new DropInfo(this, outlineRect, dockLocation, 0,
|
|
324
|
+
dropInfo = new DropInfo(this, outlineRect, dockLocation, 0, CLASSES.FLEXLAYOUT__OUTLINE_RECT);
|
|
324
325
|
}
|
|
325
326
|
} else {
|
|
326
327
|
if (this._children.length > 0) {
|
|
@@ -337,18 +338,18 @@ class BorderNode extends Node implements IDropTarget {
|
|
|
337
338
|
childCenter = childRect.y + childRect.height / 2;
|
|
338
339
|
if (y >= pos && y < childCenter) {
|
|
339
340
|
const outlineRect = new Rect(childX, childRect.y - 2, childWidth, 3);
|
|
340
|
-
dropInfo = new DropInfo(this, outlineRect, dockLocation, i,
|
|
341
|
+
dropInfo = new DropInfo(this, outlineRect, dockLocation, i, CLASSES.FLEXLAYOUT__OUTLINE_RECT);
|
|
341
342
|
break;
|
|
342
343
|
}
|
|
343
344
|
pos = childCenter;
|
|
344
345
|
}
|
|
345
346
|
if (dropInfo == null) {
|
|
346
347
|
const outlineRect = new Rect(childX, childRect.getBottom() - 2, childWidth, 3);
|
|
347
|
-
dropInfo = new DropInfo(this, outlineRect, dockLocation, this._children.length,
|
|
348
|
+
dropInfo = new DropInfo(this, outlineRect, dockLocation, this._children.length, CLASSES.FLEXLAYOUT__OUTLINE_RECT);
|
|
348
349
|
}
|
|
349
350
|
} else {
|
|
350
351
|
const outlineRect = new Rect(this._tabHeaderRect!.x + 2, this._tabHeaderRect!.y + 1, 18, 3);
|
|
351
|
-
dropInfo = new DropInfo(this, outlineRect, dockLocation, 0,
|
|
352
|
+
dropInfo = new DropInfo(this, outlineRect, dockLocation, 0, CLASSES.FLEXLAYOUT__OUTLINE_RECT);
|
|
352
353
|
}
|
|
353
354
|
}
|
|
354
355
|
if (!dragNode._canDockInto(dragNode, dropInfo)) {
|
|
@@ -356,7 +357,7 @@ class BorderNode extends Node implements IDropTarget {
|
|
|
356
357
|
}
|
|
357
358
|
} else if (this.getSelected() !== -1 && this._contentRect!.contains(x, y)) {
|
|
358
359
|
const outlineRect = this._contentRect;
|
|
359
|
-
dropInfo = new DropInfo(this, outlineRect!, dockLocation, -1,
|
|
360
|
+
dropInfo = new DropInfo(this, outlineRect!, dockLocation, -1, CLASSES.FLEXLAYOUT__OUTLINE_RECT);
|
|
360
361
|
if (!dragNode._canDockInto(dragNode, dropInfo)) {
|
|
361
362
|
return undefined;
|
|
362
363
|
}
|
package/src/model/IJsonModel.ts
CHANGED
|
@@ -40,6 +40,8 @@ export interface IGlobalAttributes {
|
|
|
40
40
|
borderMinSize?: number; // default: 0
|
|
41
41
|
borderSize?: number; // default: 200
|
|
42
42
|
enableEdgeDock?: boolean; // default: true
|
|
43
|
+
enableUseVisibility?: boolean; // default: false
|
|
44
|
+
legacyOverflowMenu?: boolean; // default: false
|
|
43
45
|
marginInsets?: IInsets; // default: {"top":0,"right":0,"bottom":0,"left":0}
|
|
44
46
|
rootOrientationVertical?: boolean; // default: false
|
|
45
47
|
splitterExtra?: number; // default: 0
|
|
@@ -108,6 +110,7 @@ export interface ITabSetAttributes {
|
|
|
108
110
|
width?: number;
|
|
109
111
|
}
|
|
110
112
|
export interface ITabAttributes {
|
|
113
|
+
altName?: string;
|
|
111
114
|
borderHeight?: number; // default: -1 - inherited from global tabBorderHeight
|
|
112
115
|
borderWidth?: number; // default: -1 - inherited from global tabBorderWidth
|
|
113
116
|
className?: string; // - inherited from global tabClassName
|
package/src/model/Model.ts
CHANGED
|
@@ -52,6 +52,9 @@ class Model {
|
|
|
52
52
|
/** @hidden @internal */
|
|
53
53
|
private static _createAttributeDefinitions(): AttributeDefinitions {
|
|
54
54
|
const attributeDefinitions = new AttributeDefinitions();
|
|
55
|
+
|
|
56
|
+
attributeDefinitions.add("legacyOverflowMenu", false).setType(Attribute.BOOLEAN);
|
|
57
|
+
|
|
55
58
|
// splitter
|
|
56
59
|
attributeDefinitions.add("splitterSize", -1).setType(Attribute.NUMBER);
|
|
57
60
|
attributeDefinitions.add("splitterExtra", 0).setType(Attribute.NUMBER);
|
|
@@ -59,6 +62,7 @@ class Model {
|
|
|
59
62
|
attributeDefinitions.add("rootOrientationVertical", false).setType(Attribute.BOOLEAN);
|
|
60
63
|
attributeDefinitions.add("marginInsets", { top: 0, right: 0, bottom: 0, left: 0 })
|
|
61
64
|
.setType("IInsets");
|
|
65
|
+
attributeDefinitions.add("enableUseVisibility", false).setType(Attribute.BOOLEAN);
|
|
62
66
|
|
|
63
67
|
// tab
|
|
64
68
|
attributeDefinitions.add("tabEnableClose", true).setType(Attribute.BOOLEAN);
|
|
@@ -201,6 +205,10 @@ class Model {
|
|
|
201
205
|
return this._attributes.rootOrientationVertical as boolean;
|
|
202
206
|
}
|
|
203
207
|
|
|
208
|
+
isUseVisibility() {
|
|
209
|
+
return this._attributes.enableUseVisibility as boolean;
|
|
210
|
+
}
|
|
211
|
+
|
|
204
212
|
/**
|
|
205
213
|
* Gets the
|
|
206
214
|
* @returns {BorderSet|*}
|
|
@@ -281,13 +289,17 @@ class Model {
|
|
|
281
289
|
const node = this._idMap[action.data.node];
|
|
282
290
|
|
|
283
291
|
if (node instanceof TabSetNode) {
|
|
284
|
-
// first delete all child tabs
|
|
292
|
+
// first delete all child tabs that are closeable
|
|
285
293
|
const children = [...node.getChildren()];
|
|
286
294
|
children.forEach((child, i) => {
|
|
287
|
-
(child as TabNode).
|
|
295
|
+
if ((child as TabNode).isEnableClose()) {
|
|
296
|
+
(child as TabNode)._delete();
|
|
297
|
+
}
|
|
288
298
|
});
|
|
289
299
|
|
|
290
|
-
node.
|
|
300
|
+
if (node.getChildren().length === 0) {
|
|
301
|
+
node._delete();
|
|
302
|
+
}
|
|
291
303
|
this._tidy();
|
|
292
304
|
}
|
|
293
305
|
break;
|
|
@@ -439,6 +451,10 @@ class Model {
|
|
|
439
451
|
return splitterSize;
|
|
440
452
|
}
|
|
441
453
|
|
|
454
|
+
isLegacyOverflowMenu() {
|
|
455
|
+
return this._attributes.legacyOverflowMenu as boolean;
|
|
456
|
+
}
|
|
457
|
+
|
|
442
458
|
getSplitterExtra() {
|
|
443
459
|
return this._attributes.splitterExtra as number;
|
|
444
460
|
}
|
package/src/model/RowNode.ts
CHANGED
|
@@ -5,6 +5,7 @@ import DockLocation from "../DockLocation";
|
|
|
5
5
|
import DropInfo from "../DropInfo";
|
|
6
6
|
import Orientation from "../Orientation";
|
|
7
7
|
import Rect from "../Rect";
|
|
8
|
+
import { CLASSES } from "../Types";
|
|
8
9
|
import BorderNode from "./BorderNode";
|
|
9
10
|
import IDraggable from "./IDraggable";
|
|
10
11
|
import IDropTarget from "./IDropTarget";
|
|
@@ -381,7 +382,9 @@ class RowNode extends Node implements IDropTarget {
|
|
|
381
382
|
// add tabset into empty root
|
|
382
383
|
if (this === this._model.getRoot() && this._children.length === 0) {
|
|
383
384
|
const callback = this._model._getOnCreateTabSet();
|
|
384
|
-
|
|
385
|
+
let attrs = callback ? callback() : {};
|
|
386
|
+
attrs = {...attrs, selected: -1};
|
|
387
|
+
const child = new TabSetNode(this._model, attrs);
|
|
385
388
|
this._model._setActiveTabset(child);
|
|
386
389
|
this._addChild(child);
|
|
387
390
|
}
|
|
@@ -404,24 +407,24 @@ class RowNode extends Node implements IDropTarget {
|
|
|
404
407
|
const dockLocation = DockLocation.LEFT;
|
|
405
408
|
const outlineRect = dockLocation.getDockRect(this._rect);
|
|
406
409
|
outlineRect.width = outlineRect.width / 2;
|
|
407
|
-
dropInfo = new DropInfo(this, outlineRect, dockLocation, -1,
|
|
410
|
+
dropInfo = new DropInfo(this, outlineRect, dockLocation, -1, CLASSES.FLEXLAYOUT__OUTLINE_RECT_EDGE);
|
|
408
411
|
} else if (x > this._rect.getRight() - margin && yy > h / 2 - half && yy < h / 2 + half) {
|
|
409
412
|
const dockLocation = DockLocation.RIGHT;
|
|
410
413
|
const outlineRect = dockLocation.getDockRect(this._rect);
|
|
411
414
|
outlineRect.width = outlineRect.width / 2;
|
|
412
415
|
outlineRect.x += outlineRect.width;
|
|
413
|
-
dropInfo = new DropInfo(this, outlineRect, dockLocation, -1,
|
|
416
|
+
dropInfo = new DropInfo(this, outlineRect, dockLocation, -1, CLASSES.FLEXLAYOUT__OUTLINE_RECT_EDGE);
|
|
414
417
|
} else if (y < this._rect.y + margin && xx > w / 2 - half && xx < w / 2 + half) {
|
|
415
418
|
const dockLocation = DockLocation.TOP;
|
|
416
419
|
const outlineRect = dockLocation.getDockRect(this._rect);
|
|
417
420
|
outlineRect.height = outlineRect.height / 2;
|
|
418
|
-
dropInfo = new DropInfo(this, outlineRect, dockLocation, -1,
|
|
421
|
+
dropInfo = new DropInfo(this, outlineRect, dockLocation, -1, CLASSES.FLEXLAYOUT__OUTLINE_RECT_EDGE);
|
|
419
422
|
} else if (y > this._rect.getBottom() - margin && xx > w / 2 - half && xx < w / 2 + half) {
|
|
420
423
|
const dockLocation = DockLocation.BOTTOM;
|
|
421
424
|
const outlineRect = dockLocation.getDockRect(this._rect);
|
|
422
425
|
outlineRect.height = outlineRect.height / 2;
|
|
423
426
|
outlineRect.y += outlineRect.height;
|
|
424
|
-
dropInfo = new DropInfo(this, outlineRect, dockLocation, -1,
|
|
427
|
+
dropInfo = new DropInfo(this, outlineRect, dockLocation, -1, CLASSES.FLEXLAYOUT__OUTLINE_RECT_EDGE);
|
|
425
428
|
}
|
|
426
429
|
|
|
427
430
|
if (dropInfo !== undefined) {
|
package/src/model/TabNode.ts
CHANGED
|
@@ -26,6 +26,7 @@ class TabNode extends Node implements IDraggable {
|
|
|
26
26
|
attributeDefinitions.add("id", undefined).setType(Attribute.STRING);
|
|
27
27
|
|
|
28
28
|
attributeDefinitions.add("name", "[Unnamed Tab]").setType(Attribute.STRING);
|
|
29
|
+
attributeDefinitions.add("altName", undefined).setType(Attribute.STRING);
|
|
29
30
|
attributeDefinitions.add("helpText", undefined).setType(Attribute.STRING);
|
|
30
31
|
attributeDefinitions.add("component", undefined).setType(Attribute.STRING);
|
|
31
32
|
attributeDefinitions.add("config", undefined).setType("any");
|
|
@@ -84,7 +85,11 @@ class TabNode extends Node implements IDraggable {
|
|
|
84
85
|
}
|
|
85
86
|
|
|
86
87
|
/** @hidden @internal */
|
|
87
|
-
|
|
88
|
+
_getNameForOverflowMenu() {
|
|
89
|
+
const altName = this._getAttr("altName") as string;
|
|
90
|
+
if (altName !== undefined) {
|
|
91
|
+
return altName;
|
|
92
|
+
}
|
|
88
93
|
return this._renderedName;
|
|
89
94
|
}
|
|
90
95
|
|
package/src/model/TabSetNode.ts
CHANGED
|
@@ -4,6 +4,7 @@ import DockLocation from "../DockLocation";
|
|
|
4
4
|
import DropInfo from "../DropInfo";
|
|
5
5
|
import Orientation from "../Orientation";
|
|
6
6
|
import Rect from "../Rect";
|
|
7
|
+
import { CLASSES } from "../Types";
|
|
7
8
|
import BorderNode from "./BorderNode";
|
|
8
9
|
import IDraggable from "./IDraggable";
|
|
9
10
|
import IDropTarget from "./IDropTarget";
|
|
@@ -27,6 +28,9 @@ class TabSetNode extends Node implements IDraggable, IDropTarget {
|
|
|
27
28
|
newLayoutNode._addChild(child);
|
|
28
29
|
});
|
|
29
30
|
}
|
|
31
|
+
if (newLayoutNode._children.length === 0) {
|
|
32
|
+
newLayoutNode._setSelected(-1);
|
|
33
|
+
}
|
|
30
34
|
|
|
31
35
|
if (json.maximized && json.maximized === true) {
|
|
32
36
|
model._setMaximizedTabset(newLayoutNode);
|
|
@@ -268,11 +272,11 @@ class TabSetNode extends Node implements IDraggable, IDropTarget {
|
|
|
268
272
|
if (dragNode === this) {
|
|
269
273
|
const dockLocation = DockLocation.CENTER;
|
|
270
274
|
const outlineRect = this._tabHeaderRect;
|
|
271
|
-
dropInfo = new DropInfo(this, outlineRect!, dockLocation, -1,
|
|
275
|
+
dropInfo = new DropInfo(this, outlineRect!, dockLocation, -1, CLASSES.FLEXLAYOUT__OUTLINE_RECT);
|
|
272
276
|
} else if (this._contentRect!.contains(x, y)) {
|
|
273
277
|
const dockLocation = DockLocation.getLocation(this._contentRect!, x, y);
|
|
274
278
|
const outlineRect = dockLocation.getDockRect(this._rect);
|
|
275
|
-
dropInfo = new DropInfo(this, outlineRect, dockLocation, -1,
|
|
279
|
+
dropInfo = new DropInfo(this, outlineRect, dockLocation, -1, CLASSES.FLEXLAYOUT__OUTLINE_RECT);
|
|
276
280
|
} else if (this._tabHeaderRect != null && this._tabHeaderRect.contains(x, y)) {
|
|
277
281
|
let r: Rect;
|
|
278
282
|
let yy: number;
|
|
@@ -296,7 +300,7 @@ class TabSetNode extends Node implements IDraggable, IDropTarget {
|
|
|
296
300
|
if (x >= p && x < childCenter) {
|
|
297
301
|
const dockLocation = DockLocation.CENTER;
|
|
298
302
|
const outlineRect = new Rect(r.x - 2, yy, 3, h);
|
|
299
|
-
dropInfo = new DropInfo(this, outlineRect, dockLocation, i,
|
|
303
|
+
dropInfo = new DropInfo(this, outlineRect, dockLocation, i, CLASSES.FLEXLAYOUT__OUTLINE_RECT);
|
|
300
304
|
break;
|
|
301
305
|
}
|
|
302
306
|
p = childCenter;
|
|
@@ -305,7 +309,7 @@ class TabSetNode extends Node implements IDraggable, IDropTarget {
|
|
|
305
309
|
if (dropInfo == null) {
|
|
306
310
|
const dockLocation = DockLocation.CENTER;
|
|
307
311
|
const outlineRect = new Rect(r.getRight() - 2, yy, 3, h);
|
|
308
|
-
dropInfo = new DropInfo(this, outlineRect, dockLocation, this._children.length,
|
|
312
|
+
dropInfo = new DropInfo(this, outlineRect, dockLocation, this._children.length, CLASSES.FLEXLAYOUT__OUTLINE_RECT);
|
|
309
313
|
}
|
|
310
314
|
}
|
|
311
315
|
|
|
@@ -3,9 +3,10 @@ import { I18nLabel } from "..";
|
|
|
3
3
|
import Actions from "../model/Actions";
|
|
4
4
|
import TabNode from "../model/TabNode";
|
|
5
5
|
import Rect from "../Rect";
|
|
6
|
-
import { IIcons, ILayoutCallbacks
|
|
6
|
+
import { IIcons, ILayoutCallbacks } from "./Layout";
|
|
7
7
|
import { ICloseType } from "../model/ICloseType";
|
|
8
8
|
import { CLASSES } from "../Types";
|
|
9
|
+
import { getRenderStateEx, isAuxMouseEvent } from "./Utils";
|
|
9
10
|
|
|
10
11
|
/** @hidden @internal */
|
|
11
12
|
export interface IBorderButtonProps {
|
|
@@ -16,16 +17,28 @@ export interface IBorderButtonProps {
|
|
|
16
17
|
iconFactory?: (node: TabNode) => React.ReactNode | undefined;
|
|
17
18
|
titleFactory?: (node: TabNode) => React.ReactNode | undefined;
|
|
18
19
|
icons?: IIcons;
|
|
20
|
+
path: string;
|
|
19
21
|
}
|
|
20
22
|
|
|
21
23
|
/** @hidden @internal */
|
|
22
24
|
export const BorderButton = (props: IBorderButtonProps) => {
|
|
23
|
-
const { layout, node, selected, border, iconFactory, titleFactory, icons } = props;
|
|
25
|
+
const { layout, node, selected, border, iconFactory, titleFactory, icons, path } = props;
|
|
24
26
|
const selfRef = React.useRef<HTMLDivElement | null>(null);
|
|
25
27
|
|
|
26
28
|
const onMouseDown = (event: React.MouseEvent<HTMLDivElement, MouseEvent> | React.TouchEvent<HTMLDivElement>) => {
|
|
27
|
-
|
|
28
|
-
|
|
29
|
+
if (!isAuxMouseEvent(event)) {
|
|
30
|
+
props.layout.dragStart(event, undefined, node, node.isEnableDrag(), onClick, (event2: Event) => undefined);
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
const onAuxMouseClick = (event: React.MouseEvent<HTMLDivElement, MouseEvent>) => {
|
|
35
|
+
if (isAuxMouseEvent(event)) {
|
|
36
|
+
layout.auxMouseClick(node, event);
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
const onContextMenu = (event: React.MouseEvent<HTMLDivElement, MouseEvent>) => {
|
|
41
|
+
layout.showContextMenu(node, event);
|
|
29
42
|
};
|
|
30
43
|
|
|
31
44
|
const onClick = () => {
|
|
@@ -82,57 +95,39 @@ export const BorderButton = (props: IBorderButtonProps) => {
|
|
|
82
95
|
classNames += " " + node.getClassName();
|
|
83
96
|
}
|
|
84
97
|
|
|
85
|
-
|
|
86
|
-
let titleContent: React.ReactNode = node.getName();
|
|
87
|
-
let name = node.getName();
|
|
88
|
-
|
|
89
|
-
function isTitleObject(obj: any): obj is ITitleObject {
|
|
90
|
-
return obj.titleContent !== undefined
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
if (titleFactory !== undefined) {
|
|
94
|
-
const titleObj = titleFactory(node);
|
|
95
|
-
if (titleObj !== undefined) {
|
|
96
|
-
if (typeof titleObj === "string") {
|
|
97
|
-
titleContent = titleObj as string;
|
|
98
|
-
name = titleObj as string;
|
|
99
|
-
} else if (isTitleObject(titleObj)) {
|
|
100
|
-
titleContent = titleObj.titleContent;
|
|
101
|
-
name = titleObj.name;
|
|
102
|
-
} else {
|
|
103
|
-
titleContent = titleObj;
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
if (typeof leadingContent === undefined && typeof node.getIcon() !== undefined) {
|
|
109
|
-
leadingContent = <img src={node.getIcon()} alt="leadingContent" />;
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
let buttons: any[] = [];
|
|
113
|
-
|
|
114
|
-
// allow customization of leading contents (icon) and contents
|
|
115
|
-
const renderState = { leading: leadingContent, content: titleContent, name, buttons };
|
|
116
|
-
layout.customizeTab(node, renderState);
|
|
117
|
-
node._setRenderedName(renderState.name);
|
|
98
|
+
const renderState = getRenderStateEx(layout, node, iconFactory, titleFactory);
|
|
118
99
|
|
|
119
|
-
const content = <div className={cm(CLASSES.FLEXLAYOUT__BORDER_BUTTON_CONTENT)}>{renderState.content}</div
|
|
120
|
-
const leading = <div className={cm(CLASSES.FLEXLAYOUT__BORDER_BUTTON_LEADING)}>{renderState.leading}</div
|
|
100
|
+
const content = renderState.content ? (<div className={cm(CLASSES.FLEXLAYOUT__BORDER_BUTTON_CONTENT)}>{renderState.content}</div>) : null;
|
|
101
|
+
const leading = renderState.leading ? (<div className={cm(CLASSES.FLEXLAYOUT__BORDER_BUTTON_LEADING)}>{renderState.leading}</div>) : null;
|
|
121
102
|
|
|
122
103
|
if (node.isEnableClose()) {
|
|
123
104
|
const closeTitle = layout.i18nName(I18nLabel.Close_Tab);
|
|
124
|
-
buttons.push(
|
|
125
|
-
<div
|
|
105
|
+
renderState.buttons.push(
|
|
106
|
+
<div
|
|
107
|
+
key="close"
|
|
108
|
+
data-layout-path={path + "/button/close"}
|
|
109
|
+
title={closeTitle}
|
|
110
|
+
className={cm(CLASSES.FLEXLAYOUT__BORDER_BUTTON_TRAILING)}
|
|
111
|
+
onMouseDown={onCloseMouseDown}
|
|
112
|
+
onClick={onClose}
|
|
113
|
+
onTouchStart={onCloseMouseDown}>
|
|
126
114
|
{icons?.close}
|
|
127
115
|
</div>
|
|
128
116
|
);
|
|
129
117
|
}
|
|
130
118
|
|
|
131
119
|
return (
|
|
132
|
-
<div ref={selfRef} style={{}} className={classNames}
|
|
120
|
+
<div ref={selfRef} style={{}} className={classNames}
|
|
121
|
+
data-layout-path={path}
|
|
122
|
+
onMouseDown={onMouseDown}
|
|
123
|
+
onClick={onAuxMouseClick}
|
|
124
|
+
onAuxClick={onAuxMouseClick}
|
|
125
|
+
onContextMenu={onContextMenu}
|
|
126
|
+
onTouchStart={onMouseDown}
|
|
127
|
+
title={node.getHelpText()}>
|
|
133
128
|
{leading}
|
|
134
129
|
{content}
|
|
135
|
-
{buttons}
|
|
130
|
+
{renderState.buttons}
|
|
136
131
|
</div>
|
|
137
132
|
);
|
|
138
133
|
};
|