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.
Files changed (74) hide show
  1. package/ChangeLog.txt +20 -0
  2. package/README.md +123 -104
  3. package/declarations/Rect.d.ts +4 -0
  4. package/declarations/Types.d.ts +7 -1
  5. package/declarations/model/BorderNode.d.ts +1 -0
  6. package/declarations/model/IJsonModel.d.ts +3 -0
  7. package/declarations/model/Model.d.ts +1 -0
  8. package/declarations/view/Layout.d.ts +11 -3
  9. package/declarations/view/Tab.d.ts +1 -1
  10. package/dist/flexlayout.js +17 -17
  11. package/dist/flexlayout_min.js +1 -1
  12. package/lib/PopupMenu.js +14 -9
  13. package/lib/PopupMenu.js.map +1 -1
  14. package/lib/Rect.js +3 -0
  15. package/lib/Rect.js.map +1 -1
  16. package/lib/Types.js +6 -0
  17. package/lib/Types.js.map +1 -1
  18. package/lib/model/BorderNode.js +22 -8
  19. package/lib/model/BorderNode.js.map +1 -1
  20. package/lib/model/BorderSet.js +15 -17
  21. package/lib/model/BorderSet.js.map +1 -1
  22. package/lib/model/Model.js +21 -3
  23. package/lib/model/Model.js.map +1 -1
  24. package/lib/model/RowNode.js +19 -5
  25. package/lib/model/RowNode.js.map +1 -1
  26. package/lib/model/TabSetNode.js +8 -4
  27. package/lib/model/TabSetNode.js.map +1 -1
  28. package/lib/view/BorderButton.js +17 -6
  29. package/lib/view/BorderButton.js.map +1 -1
  30. package/lib/view/BorderTabSet.js +17 -6
  31. package/lib/view/BorderTabSet.js.map +1 -1
  32. package/lib/view/FloatingWindow.js +13 -5
  33. package/lib/view/FloatingWindow.js.map +1 -1
  34. package/lib/view/Layout.js +205 -70
  35. package/lib/view/Layout.js.map +1 -1
  36. package/lib/view/Splitter.js +3 -3
  37. package/lib/view/Splitter.js.map +1 -1
  38. package/lib/view/Tab.js +18 -7
  39. package/lib/view/Tab.js.map +1 -1
  40. package/lib/view/TabButton.js +15 -8
  41. package/lib/view/TabButton.js.map +1 -1
  42. package/lib/view/TabFloating.js +29 -15
  43. package/lib/view/TabFloating.js.map +1 -1
  44. package/lib/view/TabSet.js +51 -25
  45. package/lib/view/TabSet.js.map +1 -1
  46. package/package.json +11 -6
  47. package/src/PopupMenu.tsx +32 -11
  48. package/src/Rect.ts +6 -2
  49. package/src/Types.ts +6 -0
  50. package/src/model/BorderNode.ts +22 -8
  51. package/src/model/BorderSet.ts +15 -17
  52. package/src/model/IJsonModel.ts +3 -0
  53. package/src/model/Model.ts +28 -3
  54. package/src/model/RowNode.ts +8 -5
  55. package/src/model/TabSetNode.ts +8 -4
  56. package/src/view/BorderButton.tsx +34 -6
  57. package/src/view/BorderTabSet.tsx +25 -5
  58. package/src/view/FloatingWindow.tsx +14 -6
  59. package/src/view/Layout.tsx +271 -92
  60. package/src/view/Splitter.tsx +4 -1
  61. package/src/view/Tab.tsx +22 -6
  62. package/src/view/TabButton.tsx +31 -11
  63. package/src/view/TabFloating.tsx +47 -23
  64. package/src/view/TabSet.tsx +72 -20
  65. package/style/_base.scss +72 -48
  66. package/style/dark.css +88 -66
  67. package/style/dark.css.map +1 -1
  68. package/style/dark.scss +20 -20
  69. package/style/gray.css +88 -66
  70. package/style/gray.css.map +1 -1
  71. package/style/gray.scss +20 -20
  72. package/style/light.css +88 -66
  73. package/style/light.css.map +1 -1
  74. package/style/light.scss +18 -18
@@ -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
- display: selected ? "block" : "none",
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.display = "none";
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 className={className} onMouseDown={onMouseDown} onTouchStart={onMouseDown} style={style}>
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
+ }
@@ -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, show, selected, iconFactory, titleFactory, icons } = props;
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
- if (!layout.getEditingTab()) {
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 (typeof leadingContent === undefined && typeof node.getIcon() !== undefined) {
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 key="close" title={closeTitle} className={cm(CLASSES.FLEXLAYOUT__TAB_BUTTON_TRAILING)} onMouseDown={onCloseMouseDown} onClick={onClose} onTouchStart={onCloseMouseDown}>
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
- style={{
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
  >
@@ -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
- if (node.getWindow()) {
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
- layout.doAction(Actions.unFloatTab(node.getId()));
48
+ dockPopout();
39
49
  };
40
50
 
41
51
  const cm = layout.getClassName;
42
52
 
43
- const style: Record<string, any> = node._styleWithPosition({
44
- display: selected ? "flex" : "none",
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
- return (
52
- <div className={cm(CLASSES.FLEXLAYOUT__TAB_FLOATING)} onMouseDown={onMouseDown} onTouchStart={onMouseDown} style={style}>
53
- <div className={cm(CLASSES.FLEXLAYOUT__TAB_FLOATING_INNER)}>
54
- <div>{message}</div>
55
- <div>
56
- <a href="#" onClick={onClickFocus}>
57
- {showMessage}
58
- </a>
59
- </div>
60
- <div>
61
- <a href="#" onClick={onClickDock}>
62
- {dockMessage}
63
- </a>
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
- </div>
67
- );
90
+ );
91
+ }
68
92
  };
@@ -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
- let name = node.getName();
46
- if (name === undefined) {
47
- name = "";
48
- } else {
49
- name = ": " + name;
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
- layout.doAction(Actions.setActiveTabset(node.getId()));
52
- if (!layout.getEditingTab()) {
53
- const message = layout.i18nName(I18nLabel.Move_Tabset, name);
54
- layout.dragStart(event, message, node, node.isEnableDrag(), (event2: Event) => undefined, onDoubleClick);
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.display = "none";
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" }} onMouseDown={onMouseDown} onTouchStart={onMouseDown}>
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} onMouseDown={onMouseDown} onTouchStart={onMouseDown}>
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} style={style} className={cm(CLASSES.FLEXLAYOUT__TABSET)} onWheel={onMouseWheel}>
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
+