flexlayout-react 0.5.17 → 0.5.21
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 +20 -0
- package/README.md +123 -104
- package/declarations/Rect.d.ts +4 -0
- package/declarations/Types.d.ts +7 -1
- package/declarations/model/BorderNode.d.ts +1 -0
- package/declarations/model/IJsonModel.d.ts +3 -0
- package/declarations/model/Model.d.ts +1 -0
- package/declarations/view/Layout.d.ts +11 -3
- package/declarations/view/Tab.d.ts +1 -1
- package/dist/flexlayout.js +17 -17
- package/dist/flexlayout_min.js +1 -1
- package/lib/PopupMenu.js +14 -9
- package/lib/PopupMenu.js.map +1 -1
- package/lib/Rect.js +3 -0
- package/lib/Rect.js.map +1 -1
- package/lib/Types.js +6 -0
- package/lib/Types.js.map +1 -1
- package/lib/model/BorderNode.js +22 -8
- package/lib/model/BorderNode.js.map +1 -1
- package/lib/model/BorderSet.js +15 -17
- package/lib/model/BorderSet.js.map +1 -1
- package/lib/model/Model.js +21 -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/TabSetNode.js +8 -4
- package/lib/model/TabSetNode.js.map +1 -1
- package/lib/view/BorderButton.js +17 -6
- package/lib/view/BorderButton.js.map +1 -1
- package/lib/view/BorderTabSet.js +17 -6
- 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/Layout.js +205 -70
- package/lib/view/Layout.js.map +1 -1
- package/lib/view/Splitter.js +3 -3
- package/lib/view/Splitter.js.map +1 -1
- package/lib/view/Tab.js +18 -7
- package/lib/view/Tab.js.map +1 -1
- package/lib/view/TabButton.js +15 -8
- package/lib/view/TabButton.js.map +1 -1
- package/lib/view/TabFloating.js +29 -15
- package/lib/view/TabFloating.js.map +1 -1
- package/lib/view/TabSet.js +51 -25
- package/lib/view/TabSet.js.map +1 -1
- package/package.json +11 -6
- package/src/PopupMenu.tsx +32 -11
- package/src/Rect.ts +6 -2
- package/src/Types.ts +6 -0
- package/src/model/BorderNode.ts +22 -8
- package/src/model/BorderSet.ts +15 -17
- package/src/model/IJsonModel.ts +3 -0
- package/src/model/Model.ts +28 -3
- package/src/model/RowNode.ts +8 -5
- package/src/model/TabSetNode.ts +8 -4
- package/src/view/BorderButton.tsx +34 -6
- package/src/view/BorderTabSet.tsx +25 -5
- package/src/view/FloatingWindow.tsx +14 -6
- package/src/view/Layout.tsx +271 -92
- package/src/view/Splitter.tsx +4 -1
- package/src/view/Tab.tsx +22 -6
- package/src/view/TabButton.tsx +31 -11
- package/src/view/TabFloating.tsx +47 -23
- package/src/view/TabSet.tsx +72 -20
- package/style/_base.scss +72 -48
- package/style/dark.css +88 -66
- package/style/dark.css.map +1 -1
- package/style/dark.scss +20 -20
- package/style/gray.css +88 -66
- package/style/gray.css.map +1 -1
- package/style/gray.scss +20 -20
- package/style/light.css +88 -66
- package/style/light.css.map +1 -1
- package/style/light.scss +18 -18
package/src/view/Splitter.tsx
CHANGED
|
@@ -13,11 +13,12 @@ import { ILayoutCallbacks } from "./Layout";
|
|
|
13
13
|
export interface ISplitterProps {
|
|
14
14
|
layout: ILayoutCallbacks;
|
|
15
15
|
node: SplitterNode;
|
|
16
|
+
path: string;
|
|
16
17
|
}
|
|
17
18
|
|
|
18
19
|
/** @hidden @internal */
|
|
19
20
|
export const Splitter = (props: ISplitterProps) => {
|
|
20
|
-
const { layout, node } = props;
|
|
21
|
+
const { layout, node, path } = props;
|
|
21
22
|
|
|
22
23
|
const pBounds = React.useRef<number[]>([]);
|
|
23
24
|
const outlineDiv = React.useRef<HTMLDivElement | undefined>(undefined);
|
|
@@ -132,6 +133,7 @@ export const Splitter = (props: ISplitterProps) => {
|
|
|
132
133
|
if (extra === 0) {
|
|
133
134
|
return (<div
|
|
134
135
|
style={style}
|
|
136
|
+
data-layout-path={path}
|
|
135
137
|
className={className}
|
|
136
138
|
onTouchStart={onMouseDown}
|
|
137
139
|
onMouseDown={onMouseDown}>
|
|
@@ -156,6 +158,7 @@ export const Splitter = (props: ISplitterProps) => {
|
|
|
156
158
|
return (
|
|
157
159
|
<div
|
|
158
160
|
style={style}
|
|
161
|
+
data-layout-path={path}
|
|
159
162
|
className={className}>
|
|
160
163
|
<div
|
|
161
164
|
style={style2}
|
package/src/view/Tab.tsx
CHANGED
|
@@ -15,11 +15,12 @@ export interface ITabProps {
|
|
|
15
15
|
selected: boolean;
|
|
16
16
|
node: TabNode;
|
|
17
17
|
factory: (node: TabNode) => React.ReactNode;
|
|
18
|
+
path: string;
|
|
18
19
|
}
|
|
19
20
|
|
|
20
21
|
/** @hidden @internal */
|
|
21
22
|
export const Tab = (props: ITabProps) => {
|
|
22
|
-
const { layout, selected, node, factory } = props;
|
|
23
|
+
const { layout, selected, node, factory, path } = props;
|
|
23
24
|
const [renderComponent, setRenderComponent] = React.useState<boolean>(!props.node.isEnableRenderOnDemand() || props.selected);
|
|
24
25
|
|
|
25
26
|
React.useLayoutEffect(() => {
|
|
@@ -40,15 +41,17 @@ export const Tab = (props: ITabProps) => {
|
|
|
40
41
|
};
|
|
41
42
|
|
|
42
43
|
const cm = layout.getClassName;
|
|
44
|
+
const useVisibility = node.getModel().isUseVisibility();
|
|
43
45
|
|
|
44
46
|
const parentNode = node.getParent() as TabSetNode | BorderNode;
|
|
45
|
-
const style: Record<string, any> = node._styleWithPosition(
|
|
46
|
-
|
|
47
|
-
|
|
47
|
+
const style: Record<string, any> = node._styleWithPosition();
|
|
48
|
+
if (!selected) {
|
|
49
|
+
hideElement(style, useVisibility);
|
|
50
|
+
}
|
|
48
51
|
|
|
49
52
|
if (parentNode instanceof TabSetNode) {
|
|
50
53
|
if (node.getModel().getMaximizedTabset() !== undefined && !parentNode.isMaximized()) {
|
|
51
|
-
style
|
|
54
|
+
hideElement(style, useVisibility);
|
|
52
55
|
}
|
|
53
56
|
}
|
|
54
57
|
|
|
@@ -64,10 +67,23 @@ export const Tab = (props: ITabProps) => {
|
|
|
64
67
|
}
|
|
65
68
|
|
|
66
69
|
return (
|
|
67
|
-
<div
|
|
70
|
+
<div
|
|
71
|
+
className={className}
|
|
72
|
+
data-layout-path={path}
|
|
73
|
+
onMouseDown={onMouseDown}
|
|
74
|
+
onTouchStart={onMouseDown}
|
|
75
|
+
style={style}>
|
|
68
76
|
<ErrorBoundary message={props.layout.i18nName(I18nLabel.Error_rendering_component)}>
|
|
69
77
|
<Fragment>{child}</Fragment>
|
|
70
78
|
</ErrorBoundary>
|
|
71
79
|
</div>
|
|
72
80
|
);
|
|
73
81
|
};
|
|
82
|
+
|
|
83
|
+
export function hideElement(style: Record<string, any>, useVisibility: ConstrainBoolean ) {
|
|
84
|
+
if (useVisibility) {
|
|
85
|
+
style.visibility = "hidden";
|
|
86
|
+
} else {
|
|
87
|
+
style.display = "none";
|
|
88
|
+
}
|
|
89
|
+
}
|
package/src/view/TabButton.tsx
CHANGED
|
@@ -7,33 +7,45 @@ import Rect from "../Rect";
|
|
|
7
7
|
import { IIcons, ILayoutCallbacks, ITitleObject } from "./Layout";
|
|
8
8
|
import { ICloseType } from "../model/ICloseType";
|
|
9
9
|
import { CLASSES } from "../Types";
|
|
10
|
+
import { isAuxMouseEvent } from "./TabSet";
|
|
10
11
|
|
|
11
12
|
/** @hidden @internal */
|
|
12
13
|
export interface ITabButtonProps {
|
|
13
14
|
layout: ILayoutCallbacks;
|
|
14
15
|
node: TabNode;
|
|
15
|
-
show: boolean;
|
|
16
16
|
selected: boolean;
|
|
17
17
|
height: number;
|
|
18
18
|
iconFactory?: (node: TabNode) => React.ReactNode | undefined;
|
|
19
19
|
titleFactory?: (node: TabNode) => React.ReactNode | undefined;
|
|
20
20
|
icons?: IIcons;
|
|
21
|
+
path: string;
|
|
21
22
|
}
|
|
22
23
|
|
|
23
24
|
/** @hidden @internal */
|
|
24
25
|
export const TabButton = (props: ITabButtonProps) => {
|
|
25
|
-
const { layout, node,
|
|
26
|
+
const { layout, node, selected, iconFactory, titleFactory, icons, path } = props;
|
|
26
27
|
const selfRef = React.useRef<HTMLDivElement | null>(null);
|
|
27
28
|
const contentRef = React.useRef<HTMLInputElement | null>(null);
|
|
28
29
|
const contentWidth = React.useRef<number>(0);
|
|
29
30
|
|
|
30
31
|
const onMouseDown = (event: React.MouseEvent<HTMLDivElement, MouseEvent> | React.TouchEvent<HTMLDivElement>) => {
|
|
31
|
-
|
|
32
|
+
|
|
33
|
+
if (!isAuxMouseEvent(event) && !layout.getEditingTab()) {
|
|
32
34
|
const message = layout.i18nName(I18nLabel.Move_Tab, node.getName());
|
|
33
35
|
layout.dragStart(event, message, node, node.isEnableDrag(), onClick, onDoubleClick);
|
|
34
36
|
}
|
|
35
37
|
};
|
|
36
38
|
|
|
39
|
+
const onAuxMouseClick = (event: React.MouseEvent<HTMLDivElement, MouseEvent>) => {
|
|
40
|
+
if (isAuxMouseEvent(event)) {
|
|
41
|
+
layout.auxMouseClick(node, event);
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
const onContextMenu = (event: React.MouseEvent<HTMLDivElement, MouseEvent>) => {
|
|
46
|
+
layout.showContextMenu(node, event);
|
|
47
|
+
};
|
|
48
|
+
|
|
37
49
|
const onClick = () => {
|
|
38
50
|
layout.doAction(Actions.selectTab(node.getId()));
|
|
39
51
|
};
|
|
@@ -43,7 +55,7 @@ export const TabButton = (props: ITabButtonProps) => {
|
|
|
43
55
|
layout.setEditingTab(node);
|
|
44
56
|
layout.getCurrentDocument()!.body.addEventListener("mousedown", onEndEdit);
|
|
45
57
|
layout.getCurrentDocument()!.body.addEventListener("touchstart", onEndEdit);
|
|
46
|
-
}
|
|
58
|
+
}
|
|
47
59
|
// else {
|
|
48
60
|
// const parentNode = node.getParent() as TabSetNode;
|
|
49
61
|
// if (parentNode.canMaximize()) {
|
|
@@ -140,8 +152,8 @@ export const TabButton = (props: ITabButtonProps) => {
|
|
|
140
152
|
let name = node.getName();
|
|
141
153
|
|
|
142
154
|
function isTitleObject(obj: any): obj is ITitleObject {
|
|
143
|
-
return obj.titleContent !== undefined
|
|
144
|
-
|
|
155
|
+
return obj.titleContent !== undefined
|
|
156
|
+
}
|
|
145
157
|
|
|
146
158
|
if (titleFactory !== undefined) {
|
|
147
159
|
const titleObj = titleFactory(node);
|
|
@@ -158,7 +170,7 @@ export const TabButton = (props: ITabButtonProps) => {
|
|
|
158
170
|
}
|
|
159
171
|
}
|
|
160
172
|
|
|
161
|
-
if (
|
|
173
|
+
if (leadingContent === undefined && node.getIcon() !== undefined) {
|
|
162
174
|
leadingContent = <img src={node.getIcon()} alt="leadingContent" />;
|
|
163
175
|
}
|
|
164
176
|
|
|
@@ -184,6 +196,7 @@ export const TabButton = (props: ITabButtonProps) => {
|
|
|
184
196
|
style={contentStyle}
|
|
185
197
|
ref={contentRef}
|
|
186
198
|
className={cm(CLASSES.FLEXLAYOUT__TAB_BUTTON_TEXTBOX)}
|
|
199
|
+
data-layout-path={path + "/textbox"}
|
|
187
200
|
type="text"
|
|
188
201
|
autoFocus={true}
|
|
189
202
|
defaultValue={node.getName()}
|
|
@@ -197,7 +210,13 @@ export const TabButton = (props: ITabButtonProps) => {
|
|
|
197
210
|
if (node.isEnableClose()) {
|
|
198
211
|
const closeTitle = layout.i18nName(I18nLabel.Close_Tab);
|
|
199
212
|
buttons.push(
|
|
200
|
-
<div
|
|
213
|
+
<div
|
|
214
|
+
key="close"
|
|
215
|
+
data-layout-path={path + "/button/close"}
|
|
216
|
+
title={closeTitle}
|
|
217
|
+
className={cm(CLASSES.FLEXLAYOUT__TAB_BUTTON_TRAILING)}
|
|
218
|
+
onMouseDown={onCloseMouseDown} onClick={onClose}
|
|
219
|
+
onTouchStart={onCloseMouseDown}>
|
|
201
220
|
{icons?.close}
|
|
202
221
|
</div>
|
|
203
222
|
);
|
|
@@ -206,11 +225,12 @@ export const TabButton = (props: ITabButtonProps) => {
|
|
|
206
225
|
return (
|
|
207
226
|
<div
|
|
208
227
|
ref={selfRef}
|
|
209
|
-
|
|
210
|
-
visibility: show ? "visible" : "hidden",
|
|
211
|
-
}}
|
|
228
|
+
data-layout-path={path}
|
|
212
229
|
className={classNames}
|
|
213
230
|
onMouseDown={onMouseDown}
|
|
231
|
+
onClick={onAuxMouseClick}
|
|
232
|
+
onAuxClick={onAuxMouseClick}
|
|
233
|
+
onContextMenu={onContextMenu}
|
|
214
234
|
onTouchStart={onMouseDown}
|
|
215
235
|
title={node.getHelpText()}
|
|
216
236
|
>
|
package/src/view/TabFloating.tsx
CHANGED
|
@@ -5,17 +5,29 @@ import TabSetNode from "../model/TabSetNode";
|
|
|
5
5
|
import { CLASSES } from "../Types";
|
|
6
6
|
import { ILayoutCallbacks } from "./Layout";
|
|
7
7
|
import { I18nLabel } from "../I18nLabel";
|
|
8
|
+
import { hideElement } from "./Tab";
|
|
8
9
|
|
|
9
10
|
/** @hidden @internal */
|
|
10
11
|
export interface ITabFloatingProps {
|
|
11
12
|
layout: ILayoutCallbacks;
|
|
12
13
|
selected: boolean;
|
|
13
14
|
node: TabNode;
|
|
15
|
+
path: string;
|
|
14
16
|
}
|
|
15
17
|
|
|
16
18
|
/** @hidden @internal */
|
|
17
19
|
export const TabFloating = (props: ITabFloatingProps) => {
|
|
18
|
-
const { layout, selected, node } = props;
|
|
20
|
+
const { layout, selected, node, path } = props;
|
|
21
|
+
|
|
22
|
+
const showPopout = () => {
|
|
23
|
+
if (node.getWindow()) {
|
|
24
|
+
node.getWindow()!.focus();
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const dockPopout = () => {
|
|
29
|
+
layout.doAction(Actions.unFloatTab(node.getId()));
|
|
30
|
+
}
|
|
19
31
|
|
|
20
32
|
const onMouseDown = () => {
|
|
21
33
|
const parent = node.getParent() as TabSetNode;
|
|
@@ -28,41 +40,53 @@ export const TabFloating = (props: ITabFloatingProps) => {
|
|
|
28
40
|
|
|
29
41
|
const onClickFocus = (event: React.MouseEvent<HTMLAnchorElement, MouseEvent>) => {
|
|
30
42
|
event.preventDefault();
|
|
31
|
-
|
|
32
|
-
node.getWindow()!.focus();
|
|
33
|
-
}
|
|
43
|
+
showPopout();
|
|
34
44
|
};
|
|
35
45
|
|
|
36
46
|
const onClickDock = (event: React.MouseEvent<HTMLAnchorElement, MouseEvent>) => {
|
|
37
47
|
event.preventDefault();
|
|
38
|
-
|
|
48
|
+
dockPopout();
|
|
39
49
|
};
|
|
40
50
|
|
|
41
51
|
const cm = layout.getClassName;
|
|
42
52
|
|
|
43
|
-
const style: Record<string, any> = node._styleWithPosition(
|
|
44
|
-
|
|
45
|
-
|
|
53
|
+
const style: Record<string, any> = node._styleWithPosition();
|
|
54
|
+
if (!selected) {
|
|
55
|
+
hideElement(style, node.getModel().isUseVisibility());
|
|
56
|
+
}
|
|
46
57
|
|
|
47
58
|
const message = layout.i18nName(I18nLabel.Floating_Window_Message);
|
|
48
59
|
const showMessage = layout.i18nName(I18nLabel.Floating_Window_Show_Window);
|
|
49
60
|
const dockMessage = layout.i18nName(I18nLabel.Floating_Window_Dock_Window);
|
|
50
61
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
62
|
+
const customRenderCallback = layout.getOnRenderFloatingTabPlaceholder();
|
|
63
|
+
if (customRenderCallback) {
|
|
64
|
+
return (
|
|
65
|
+
<div className={cm(CLASSES.FLEXLAYOUT__TAB_FLOATING)} onMouseDown={onMouseDown} onTouchStart={onMouseDown} style={style}>
|
|
66
|
+
{customRenderCallback(dockPopout, showPopout)}
|
|
67
|
+
</div>
|
|
68
|
+
);
|
|
69
|
+
} else {
|
|
70
|
+
return (
|
|
71
|
+
<div className={cm(CLASSES.FLEXLAYOUT__TAB_FLOATING)}
|
|
72
|
+
data-layout-path={path}
|
|
73
|
+
onMouseDown={onMouseDown}
|
|
74
|
+
onTouchStart={onMouseDown}
|
|
75
|
+
style={style}>
|
|
76
|
+
<div className={cm(CLASSES.FLEXLAYOUT__TAB_FLOATING_INNER)}>
|
|
77
|
+
<div>{message}</div>
|
|
78
|
+
<div>
|
|
79
|
+
<a href="#" onClick={onClickFocus}>
|
|
80
|
+
{showMessage}
|
|
81
|
+
</a>
|
|
82
|
+
</div>
|
|
83
|
+
<div>
|
|
84
|
+
<a href="#" onClick={onClickDock}>
|
|
85
|
+
{dockMessage}
|
|
86
|
+
</a>
|
|
87
|
+
</div>
|
|
64
88
|
</div>
|
|
65
89
|
</div>
|
|
66
|
-
|
|
67
|
-
|
|
90
|
+
);
|
|
91
|
+
}
|
|
68
92
|
};
|
package/src/view/TabSet.tsx
CHANGED
|
@@ -9,6 +9,7 @@ import { TabButton } from "./TabButton";
|
|
|
9
9
|
import { useTabOverflow } from "./TabOverflowHook";
|
|
10
10
|
import Orientation from "../Orientation";
|
|
11
11
|
import { CLASSES } from "../Types";
|
|
12
|
+
import { hideElement } from "./Tab";
|
|
12
13
|
|
|
13
14
|
/** @hidden @internal */
|
|
14
15
|
export interface ITabSetProps {
|
|
@@ -17,12 +18,13 @@ export interface ITabSetProps {
|
|
|
17
18
|
iconFactory?: (node: TabNode) => React.ReactNode | undefined;
|
|
18
19
|
titleFactory?: (node: TabNode) => React.ReactNode | undefined;
|
|
19
20
|
icons?: IIcons;
|
|
20
|
-
editingTab?: TabNode;
|
|
21
|
+
editingTab?: TabNode;
|
|
22
|
+
path?: string;
|
|
21
23
|
}
|
|
22
24
|
|
|
23
25
|
/** @hidden @internal */
|
|
24
26
|
export const TabSet = (props: ITabSetProps) => {
|
|
25
|
-
const { node, layout, iconFactory, titleFactory, icons } = props;
|
|
27
|
+
const { node, layout, iconFactory, titleFactory, icons, path } = props;
|
|
26
28
|
|
|
27
29
|
const toolbarRef = React.useRef<HTMLDivElement | null>(null);
|
|
28
30
|
const overflowbuttonRef = React.useRef<HTMLButtonElement | null>(null);
|
|
@@ -31,9 +33,10 @@ export const TabSet = (props: ITabSetProps) => {
|
|
|
31
33
|
|
|
32
34
|
const { selfRef, position, userControlledLeft, hiddenTabs, onMouseWheel, tabsTruncated } = useTabOverflow(node, Orientation.HORZ, toolbarRef, stickyButtonsRef);
|
|
33
35
|
|
|
34
|
-
const onOverflowClick = () => {
|
|
36
|
+
const onOverflowClick = (event: React.MouseEvent<HTMLElement, MouseEvent>) => {
|
|
35
37
|
const element = overflowbuttonRef.current!;
|
|
36
38
|
showPopup(layout.getRootDiv(), element, hiddenTabs, onOverflowItemSelect, layout.getClassName);
|
|
39
|
+
event.stopPropagation();
|
|
37
40
|
};
|
|
38
41
|
|
|
39
42
|
const onOverflowItemSelect = (item: { node: TabNode; index: number }) => {
|
|
@@ -42,37 +45,52 @@ export const TabSet = (props: ITabSetProps) => {
|
|
|
42
45
|
};
|
|
43
46
|
|
|
44
47
|
const onMouseDown = (event: React.MouseEvent<HTMLDivElement, MouseEvent> | React.TouchEvent<HTMLDivElement>) => {
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
name
|
|
48
|
-
|
|
49
|
-
|
|
48
|
+
if (!isAuxMouseEvent(event)) {
|
|
49
|
+
let name = node.getName();
|
|
50
|
+
if (name === undefined) {
|
|
51
|
+
name = "";
|
|
52
|
+
} else {
|
|
53
|
+
name = ": " + name;
|
|
54
|
+
}
|
|
55
|
+
layout.doAction(Actions.setActiveTabset(node.getId()));
|
|
56
|
+
if (!layout.getEditingTab()) {
|
|
57
|
+
const message = layout.i18nName(I18nLabel.Move_Tabset, name);
|
|
58
|
+
layout.dragStart(event, message, node, node.isEnableDrag(), (event2: Event) => undefined, onDoubleClick);
|
|
59
|
+
}
|
|
50
60
|
}
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
const onAuxMouseClick = (event: React.MouseEvent<HTMLDivElement, MouseEvent>) => {
|
|
64
|
+
if (isAuxMouseEvent(event)) {
|
|
65
|
+
layout.auxMouseClick(node, event);
|
|
55
66
|
}
|
|
56
67
|
};
|
|
57
68
|
|
|
69
|
+
const onContextMenu = (event: React.MouseEvent<HTMLDivElement, MouseEvent>) => {
|
|
70
|
+
layout.showContextMenu(node, event);
|
|
71
|
+
};
|
|
72
|
+
|
|
58
73
|
const onInterceptMouseDown = (event: React.MouseEvent | React.TouchEvent) => {
|
|
59
74
|
event.stopPropagation();
|
|
60
75
|
};
|
|
61
76
|
|
|
62
|
-
const onMaximizeToggle = () => {
|
|
77
|
+
const onMaximizeToggle = (event: React.MouseEvent<HTMLElement, MouseEvent>) => {
|
|
63
78
|
if (node.canMaximize()) {
|
|
64
79
|
layout.maximize(node);
|
|
65
80
|
}
|
|
81
|
+
event.stopPropagation();
|
|
66
82
|
};
|
|
67
83
|
|
|
68
|
-
const onClose = () => {
|
|
84
|
+
const onClose = (event: React.MouseEvent<HTMLElement, MouseEvent>) => {
|
|
69
85
|
layout.doAction(Actions.deleteTabset(node.getId()));
|
|
86
|
+
event.stopPropagation();
|
|
70
87
|
};
|
|
71
88
|
|
|
72
|
-
const onFloatTab = () => {
|
|
89
|
+
const onFloatTab = (event: React.MouseEvent<HTMLElement, MouseEvent>) => {
|
|
73
90
|
if (selectedTabNode !== undefined) {
|
|
74
91
|
layout.doAction(Actions.floatTab(selectedTabNode.getId()));
|
|
75
92
|
}
|
|
93
|
+
event.stopPropagation();
|
|
76
94
|
};
|
|
77
95
|
|
|
78
96
|
const onDoubleClick = (event: Event) => {
|
|
@@ -93,7 +111,7 @@ export const TabSet = (props: ITabSetProps) => {
|
|
|
93
111
|
let style = node._styleWithPosition();
|
|
94
112
|
|
|
95
113
|
if (node.getModel().getMaximizedTabset() !== undefined && !node.isMaximized()) {
|
|
96
|
-
style.
|
|
114
|
+
hideElement(style, node.getModel().isUseVisibility())
|
|
97
115
|
}
|
|
98
116
|
|
|
99
117
|
const tabs = [];
|
|
@@ -105,9 +123,9 @@ export const TabSet = (props: ITabSetProps) => {
|
|
|
105
123
|
<TabButton
|
|
106
124
|
layout={layout}
|
|
107
125
|
node={child}
|
|
126
|
+
path={path + "/tb" + i}
|
|
108
127
|
key={child.getId()}
|
|
109
128
|
selected={isSelected}
|
|
110
|
-
show={true}
|
|
111
129
|
height={node.getTabStripHeight()}
|
|
112
130
|
iconFactory={iconFactory}
|
|
113
131
|
titleFactory={titleFactory}
|
|
@@ -153,6 +171,8 @@ export const TabSet = (props: ITabSetProps) => {
|
|
|
153
171
|
buttons.push(
|
|
154
172
|
<button
|
|
155
173
|
key="overflowbutton"
|
|
174
|
+
data-layout-path={path + "/button/overflow"}
|
|
175
|
+
|
|
156
176
|
ref={overflowbuttonRef}
|
|
157
177
|
className={cm(CLASSES.FLEXLAYOUT__TAB_BUTTON_OVERFLOW)}
|
|
158
178
|
title={overflowTitle}
|
|
@@ -171,6 +191,7 @@ export const TabSet = (props: ITabSetProps) => {
|
|
|
171
191
|
buttons.push(
|
|
172
192
|
<button
|
|
173
193
|
key="float"
|
|
194
|
+
data-layout-path={path + "/button/float"}
|
|
174
195
|
title={floatTitle}
|
|
175
196
|
className={cm(CLASSES.FLEXLAYOUT__TAB_TOOLBAR_BUTTON) + " " + cm(CLASSES.FLEXLAYOUT__TAB_TOOLBAR_BUTTON_FLOAT)}
|
|
176
197
|
onClick={onFloatTab}
|
|
@@ -188,6 +209,7 @@ export const TabSet = (props: ITabSetProps) => {
|
|
|
188
209
|
btns.push(
|
|
189
210
|
<button
|
|
190
211
|
key="max"
|
|
212
|
+
data-layout-path={path + "/button/max"}
|
|
191
213
|
title={node.isMaximized() ? minTitle : maxTitle}
|
|
192
214
|
className={cm(CLASSES.FLEXLAYOUT__TAB_TOOLBAR_BUTTON) + " " + cm(CLASSES.FLEXLAYOUT__TAB_TOOLBAR_BUTTON_ + (node.isMaximized() ? "max" : "min"))}
|
|
193
215
|
onClick={onMaximizeToggle}
|
|
@@ -205,6 +227,7 @@ export const TabSet = (props: ITabSetProps) => {
|
|
|
205
227
|
btns.push(
|
|
206
228
|
<button
|
|
207
229
|
key="close"
|
|
230
|
+
data-layout-path={path + "/button/close"}
|
|
208
231
|
title={title}
|
|
209
232
|
className={cm(CLASSES.FLEXLAYOUT__TAB_TOOLBAR_BUTTON) + " " + cm(CLASSES.FLEXLAYOUT__TAB_TOOLBAR_BUTTON_CLOSE)}
|
|
210
233
|
onClick={onClose}
|
|
@@ -269,7 +292,13 @@ export const TabSet = (props: ITabSetProps) => {
|
|
|
269
292
|
}
|
|
270
293
|
|
|
271
294
|
header = (
|
|
272
|
-
<div className={tabHeaderClasses} style={{ height: node.getHeaderHeight() + "px" }}
|
|
295
|
+
<div className={tabHeaderClasses} style={{ height: node.getHeaderHeight() + "px" }}
|
|
296
|
+
data-layout-path={path + "/header"}
|
|
297
|
+
onMouseDown={onMouseDown}
|
|
298
|
+
onContextMenu={onContextMenu}
|
|
299
|
+
onClick={onAuxMouseClick}
|
|
300
|
+
onAuxClick={onAuxMouseClick}
|
|
301
|
+
onTouchStart={onMouseDown}>
|
|
273
302
|
<div className={cm(CLASSES.FLEXLAYOUT__TABSET_HEADER_CONTENT)}>{headerContent}</div>
|
|
274
303
|
{headerToolbar}
|
|
275
304
|
</div>
|
|
@@ -284,7 +313,13 @@ export const TabSet = (props: ITabSetProps) => {
|
|
|
284
313
|
tabStripStyle["bottom"] = "0px";
|
|
285
314
|
}
|
|
286
315
|
tabStrip = (
|
|
287
|
-
<div className={tabStripClasses} style={tabStripStyle}
|
|
316
|
+
<div className={tabStripClasses} style={tabStripStyle}
|
|
317
|
+
data-layout-path={path + "/tabstrip"}
|
|
318
|
+
onMouseDown={onMouseDown}
|
|
319
|
+
onContextMenu={onContextMenu}
|
|
320
|
+
onClick={onAuxMouseClick}
|
|
321
|
+
onAuxClick={onAuxMouseClick}
|
|
322
|
+
onTouchStart={onMouseDown}>
|
|
288
323
|
<div ref={tabbarInnerRef} className={cm(CLASSES.FLEXLAYOUT__TABSET_TABBAR_INNER) + " " + cm(CLASSES.FLEXLAYOUT__TABSET_TABBAR_INNER_ + node.getTabLocation())}>
|
|
289
324
|
<div
|
|
290
325
|
style={{ left: position }}
|
|
@@ -300,9 +335,26 @@ export const TabSet = (props: ITabSetProps) => {
|
|
|
300
335
|
style = layout.styleFont(style);
|
|
301
336
|
|
|
302
337
|
return (
|
|
303
|
-
<div ref={selfRef}
|
|
338
|
+
<div ref={selfRef}
|
|
339
|
+
dir="ltr"
|
|
340
|
+
data-layout-path={path}
|
|
341
|
+
style={style}
|
|
342
|
+
className={cm(CLASSES.FLEXLAYOUT__TABSET)}
|
|
343
|
+
onWheel={onMouseWheel}>
|
|
304
344
|
{header}
|
|
305
345
|
{tabStrip}
|
|
306
346
|
</div>
|
|
307
347
|
);
|
|
308
348
|
};
|
|
349
|
+
|
|
350
|
+
/** @hidden @internal */
|
|
351
|
+
export function isAuxMouseEvent(event: React.MouseEvent<HTMLDivElement, MouseEvent> | React.TouchEvent<HTMLDivElement>) {
|
|
352
|
+
let auxEvent = false;
|
|
353
|
+
if (event.nativeEvent instanceof MouseEvent) {
|
|
354
|
+
if (event.nativeEvent.button !== 0 || event.ctrlKey || event.altKey || event.metaKey || event.shiftKey) {
|
|
355
|
+
auxEvent = true;
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
return auxEvent;
|
|
359
|
+
}
|
|
360
|
+
|