flexlayout-react 0.5.16 → 0.5.20

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 (81) hide show
  1. package/ChangeLog.txt +24 -0
  2. package/README.md +128 -97
  3. package/declarations/DragDrop.d.ts +1 -0
  4. package/declarations/Rect.d.ts +4 -0
  5. package/declarations/Types.d.ts +8 -1
  6. package/declarations/model/BorderNode.d.ts +2 -1
  7. package/declarations/model/IJsonModel.d.ts +8 -0
  8. package/declarations/model/Model.d.ts +1 -0
  9. package/declarations/view/Layout.d.ts +19 -6
  10. package/dist/flexlayout.js +19 -19
  11. package/dist/flexlayout_min.js +1 -1
  12. package/lib/DockLocation.js +25 -11
  13. package/lib/DockLocation.js.map +1 -1
  14. package/lib/DragDrop.js +19 -3
  15. package/lib/DragDrop.js.map +1 -1
  16. package/lib/PopupMenu.js +14 -9
  17. package/lib/PopupMenu.js.map +1 -1
  18. package/lib/Rect.js +3 -0
  19. package/lib/Rect.js.map +1 -1
  20. package/lib/Types.js +7 -0
  21. package/lib/Types.js.map +1 -1
  22. package/lib/model/BorderNode.js +61 -14
  23. package/lib/model/BorderNode.js.map +1 -1
  24. package/lib/model/BorderSet.js +33 -19
  25. package/lib/model/BorderSet.js.map +1 -1
  26. package/lib/model/Model.js +23 -3
  27. package/lib/model/Model.js.map +1 -1
  28. package/lib/model/RowNode.js +19 -5
  29. package/lib/model/RowNode.js.map +1 -1
  30. package/lib/model/TabNode.js +10 -0
  31. package/lib/model/TabNode.js.map +1 -1
  32. package/lib/model/TabSetNode.js +34 -19
  33. package/lib/model/TabSetNode.js.map +1 -1
  34. package/lib/view/BorderButton.js +17 -6
  35. package/lib/view/BorderButton.js.map +1 -1
  36. package/lib/view/BorderTabSet.js +17 -6
  37. package/lib/view/BorderTabSet.js.map +1 -1
  38. package/lib/view/Layout.js +232 -57
  39. package/lib/view/Layout.js.map +1 -1
  40. package/lib/view/Splitter.js +35 -4
  41. package/lib/view/Splitter.js.map +1 -1
  42. package/lib/view/Tab.js +2 -2
  43. package/lib/view/Tab.js.map +1 -1
  44. package/lib/view/TabButton.js +16 -7
  45. package/lib/view/TabButton.js.map +1 -1
  46. package/lib/view/TabFloating.js +24 -12
  47. package/lib/view/TabFloating.js.map +1 -1
  48. package/lib/view/TabSet.js +49 -24
  49. package/lib/view/TabSet.js.map +1 -1
  50. package/package.json +11 -6
  51. package/src/DockLocation.ts +30 -9
  52. package/src/DragDrop.ts +26 -3
  53. package/src/PopupMenu.tsx +32 -11
  54. package/src/Rect.ts +6 -2
  55. package/src/Types.ts +7 -0
  56. package/src/model/BorderNode.ts +57 -15
  57. package/src/model/BorderSet.ts +32 -19
  58. package/src/model/IJsonModel.ts +8 -0
  59. package/src/model/Model.ts +30 -3
  60. package/src/model/RowNode.ts +8 -5
  61. package/src/model/TabNode.ts +11 -0
  62. package/src/model/TabSetNode.ts +33 -19
  63. package/src/view/BorderButton.tsx +34 -6
  64. package/src/view/BorderTabSet.tsx +25 -5
  65. package/src/view/Layout.tsx +299 -82
  66. package/src/view/Splitter.tsx +53 -4
  67. package/src/view/Tab.tsx +8 -2
  68. package/src/view/TabButton.tsx +31 -7
  69. package/src/view/TabFloating.tsx +42 -20
  70. package/src/view/TabSet.tsx +70 -18
  71. package/style/_base.scss +78 -51
  72. package/style/dark.css +94 -68
  73. package/style/dark.css.map +1 -1
  74. package/style/dark.scss +20 -20
  75. package/style/gray.css +94 -68
  76. package/style/gray.css.map +1 -1
  77. package/style/gray.scss +20 -20
  78. package/style/light.css +94 -68
  79. package/style/light.css.map +1 -1
  80. package/style/light.scss +18 -18
  81. package/yarn-error.log +0 -11828
@@ -39,6 +39,8 @@ class TabNode extends Node implements IDraggable {
39
39
  attributeDefinitions.addInherited("icon", "tabIcon").setType(Attribute.STRING);
40
40
  attributeDefinitions.addInherited("enableRenderOnDemand", "tabEnableRenderOnDemand").setType(Attribute.BOOLEAN);
41
41
  attributeDefinitions.addInherited("enableFloat", "tabEnableFloat").setType(Attribute.BOOLEAN);
42
+ attributeDefinitions.addInherited("borderWidth", "tabBorderWidth").setType(Attribute.NUMBER);
43
+ attributeDefinitions.addInherited("borderHeight", "tabBorderHeight").setType(Attribute.NUMBER);
42
44
  return attributeDefinitions;
43
45
  }
44
46
 
@@ -200,7 +202,16 @@ class TabNode extends Node implements IDraggable {
200
202
  _setWindow(window: Window | undefined) {
201
203
  this._window = window;
202
204
  }
205
+
206
+ /** @hidden @internal */
207
+ _setBorderWidth(width: number) {
208
+ this._attributes.borderWidth = width;
209
+ }
203
210
 
211
+ /** @hidden @internal */
212
+ _setBorderHeight(height: number) {
213
+ this._attributes.borderHeight = height;
214
+ }
204
215
 
205
216
  /** @hidden @internal */
206
217
  static getAttributeDefinitions() {
@@ -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,34 +272,44 @@ 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, "flexlayout__outline_rect");
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, "flexlayout__outline_rect");
276
- } else if (this._children.length > 0 && this._tabHeaderRect != null && this._tabHeaderRect.contains(x, y)) {
277
- let child = this._children[0] as TabNode;
278
- let r = child.getTabRect()!;
279
- const yy = r.y;
280
- const h = r.height;
281
- let p = this._tabHeaderRect.x;
282
- let childCenter = 0;
283
- for (let i = 0; i < this._children.length; i++) {
284
- child = this._children[i] as TabNode;
279
+ dropInfo = new DropInfo(this, outlineRect, dockLocation, -1, CLASSES.FLEXLAYOUT__OUTLINE_RECT);
280
+ } else if (this._tabHeaderRect != null && this._tabHeaderRect.contains(x, y)) {
281
+ let r: Rect;
282
+ let yy: number;
283
+ let h: number;
284
+ if (this._children.length === 0) {
285
+ r = this._tabHeaderRect.clone();
286
+ yy = r.y + 3;
287
+ h = r.height - 4;
288
+ r.width = 2;
289
+ } else {
290
+ let child = this._children[0] as TabNode;
285
291
  r = child.getTabRect()!;
286
- childCenter = r.x + r.width / 2;
287
- if (x >= p && x < childCenter) {
288
- const dockLocation = DockLocation.CENTER;
289
- const outlineRect = new Rect(r.x - 2, yy, 3, h);
290
- dropInfo = new DropInfo(this, outlineRect, dockLocation, i, "flexlayout__outline_rect");
291
- break;
292
+ yy = r.y;
293
+ h = r.height;
294
+ let p = this._tabHeaderRect.x;
295
+ let childCenter = 0;
296
+ for (let i = 0; i < this._children.length; i++) {
297
+ child = this._children[i] as TabNode;
298
+ r = child.getTabRect()!;
299
+ childCenter = r.x + r.width / 2;
300
+ if (x >= p && x < childCenter) {
301
+ const dockLocation = DockLocation.CENTER;
302
+ const outlineRect = new Rect(r.x - 2, yy, 3, h);
303
+ dropInfo = new DropInfo(this, outlineRect, dockLocation, i, CLASSES.FLEXLAYOUT__OUTLINE_RECT);
304
+ break;
305
+ }
306
+ p = childCenter;
292
307
  }
293
- p = childCenter;
294
308
  }
295
309
  if (dropInfo == null) {
296
310
  const dockLocation = DockLocation.CENTER;
297
311
  const outlineRect = new Rect(r.getRight() - 2, yy, 3, h);
298
- dropInfo = new DropInfo(this, outlineRect, dockLocation, this._children.length, "flexlayout__outline_rect");
312
+ dropInfo = new DropInfo(this, outlineRect, dockLocation, this._children.length, CLASSES.FLEXLAYOUT__OUTLINE_RECT);
299
313
  }
300
314
  }
301
315
 
@@ -6,6 +6,7 @@ import Rect from "../Rect";
6
6
  import { IIcons, ILayoutCallbacks, ITitleObject } from "./Layout";
7
7
  import { ICloseType } from "../model/ICloseType";
8
8
  import { CLASSES } from "../Types";
9
+ import { isAuxMouseEvent } from "./TabSet";
9
10
 
10
11
  /** @hidden @internal */
11
12
  export interface IBorderButtonProps {
@@ -16,16 +17,29 @@ 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
- const message = layout.i18nName(I18nLabel.Move_Tab, node.getName());
28
- props.layout.dragStart(event, message, node, node.isEnableDrag(), onClick, (event2: Event) => undefined);
29
+ if (!isAuxMouseEvent(event)) {
30
+ const message = layout.i18nName(I18nLabel.Move_Tab, node.getName());
31
+ props.layout.dragStart(event, message, node, node.isEnableDrag(), onClick, (event2: Event) => undefined);
32
+ }
33
+ };
34
+
35
+ const onAuxMouseClick = (event: React.MouseEvent<HTMLDivElement, MouseEvent>) => {
36
+ if (isAuxMouseEvent(event)) {
37
+ layout.auxMouseClick(node, event);
38
+ }
39
+ };
40
+
41
+ const onContextMenu = (event: React.MouseEvent<HTMLDivElement, MouseEvent>) => {
42
+ layout.showContextMenu(node, event);
29
43
  };
30
44
 
31
45
  const onClick = () => {
@@ -105,7 +119,7 @@ export const BorderButton = (props: IBorderButtonProps) => {
105
119
  }
106
120
  }
107
121
 
108
- if (typeof leadingContent === undefined && typeof node.getIcon() !== undefined) {
122
+ if (leadingContent === undefined && node.getIcon() !== undefined) {
109
123
  leadingContent = <img src={node.getIcon()} alt="leadingContent" />;
110
124
  }
111
125
 
@@ -122,14 +136,28 @@ export const BorderButton = (props: IBorderButtonProps) => {
122
136
  if (node.isEnableClose()) {
123
137
  const closeTitle = layout.i18nName(I18nLabel.Close_Tab);
124
138
  buttons.push(
125
- <div key="close" title={closeTitle} className={cm(CLASSES.FLEXLAYOUT__BORDER_BUTTON_TRAILING)} onMouseDown={onCloseMouseDown} onClick={onClose} onTouchStart={onCloseMouseDown}>
139
+ <div
140
+ key="close"
141
+ data-layout-path={path + "/button/close"}
142
+ title={closeTitle}
143
+ className={cm(CLASSES.FLEXLAYOUT__BORDER_BUTTON_TRAILING)}
144
+ onMouseDown={onCloseMouseDown}
145
+ onClick={onClose}
146
+ onTouchStart={onCloseMouseDown}>
126
147
  {icons?.close}
127
148
  </div>
128
149
  );
129
150
  }
130
151
 
131
152
  return (
132
- <div ref={selfRef} style={{}} className={classNames} onMouseDown={onMouseDown} onTouchStart={onMouseDown} title={node.getHelpText()}>
153
+ <div ref={selfRef} style={{}} className={classNames}
154
+ data-layout-path={path}
155
+ onMouseDown={onMouseDown}
156
+ onClick={onAuxMouseClick}
157
+ onAuxClick={onAuxMouseClick}
158
+ onContextMenu={onContextMenu}
159
+ onTouchStart={onMouseDown}
160
+ title={node.getHelpText()}>
133
161
  {leading}
134
162
  {content}
135
163
  {buttons}
@@ -10,6 +10,7 @@ import { I18nLabel } from "../I18nLabel";
10
10
  import { useTabOverflow } from "./TabOverflowHook";
11
11
  import Orientation from "../Orientation";
12
12
  import { CLASSES } from "../Types";
13
+ import { isAuxMouseEvent } from "./TabSet";
13
14
 
14
15
  /** @hidden @internal */
15
16
  export interface IBorderTabSetProps {
@@ -18,11 +19,12 @@ export interface IBorderTabSetProps {
18
19
  iconFactory?: (node: TabNode) => React.ReactNode | undefined;
19
20
  titleFactory?: (node: TabNode) => React.ReactNode | undefined;
20
21
  icons?: IIcons;
22
+ path: string;
21
23
  }
22
24
 
23
25
  /** @hidden @internal */
24
26
  export const BorderTabSet = (props: IBorderTabSetProps) => {
25
- const { border, layout, iconFactory, titleFactory, icons } = props;
27
+ const { border, 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);
@@ -30,13 +32,24 @@ export const BorderTabSet = (props: IBorderTabSetProps) => {
30
32
 
31
33
  const { selfRef, position, userControlledLeft, hiddenTabs, onMouseWheel } = useTabOverflow(border, Orientation.flip(border.getOrientation()), toolbarRef, stickyButtonsRef);
32
34
 
35
+ const onAuxMouseClick = (event: React.MouseEvent<HTMLDivElement, MouseEvent>) => {
36
+ if (isAuxMouseEvent(event)) {
37
+ layout.auxMouseClick(border, event);
38
+ }
39
+ };
40
+
41
+ const onContextMenu = (event: React.MouseEvent<HTMLDivElement, MouseEvent>) => {
42
+ layout.showContextMenu(border, event);
43
+ };
44
+
33
45
  const onInterceptMouseDown = (event: React.MouseEvent<HTMLDivElement, MouseEvent> | React.MouseEvent<HTMLButtonElement, MouseEvent> | React.TouchEvent<HTMLButtonElement>) => {
34
46
  event.stopPropagation();
35
47
  };
36
48
 
37
- const onOverflowClick = () => {
49
+ const onOverflowClick = (event: React.MouseEvent<HTMLElement, MouseEvent>) => {
38
50
  const element = overflowbuttonRef.current!;
39
51
  showPopup(layout.getRootDiv(), element, hiddenTabs, onOverflowItemSelect, layout.getClassName);
52
+ event.stopPropagation();
40
53
  };
41
54
 
42
55
  const onOverflowItemSelect = (item: { node: TabNode; index: number }) => {
@@ -44,11 +57,12 @@ export const BorderTabSet = (props: IBorderTabSetProps) => {
44
57
  userControlledLeft.current = false;
45
58
  };
46
59
 
47
- const onFloatTab = () => {
60
+ const onFloatTab = (event: React.MouseEvent<HTMLElement, MouseEvent>) => {
48
61
  const selectedTabNode = border.getChildren()[border.getSelected()] as TabNode;
49
62
  if (selectedTabNode !== undefined) {
50
63
  layout.doAction(Actions.floatTab(selectedTabNode.getId()));
51
64
  }
65
+ event.stopPropagation();
52
66
  };
53
67
 
54
68
  const cm = layout.getClassName;
@@ -65,6 +79,7 @@ export const BorderTabSet = (props: IBorderTabSetProps) => {
65
79
  layout={layout}
66
80
  border={border.getLocation().getName()}
67
81
  node={child}
82
+ path={path + "/tb" + i}
68
83
  key={child.getId()}
69
84
  selected={isSelected}
70
85
  iconFactory={iconFactory}
@@ -97,7 +112,7 @@ export const BorderTabSet = (props: IBorderTabSetProps) => {
97
112
  <button
98
113
  key="overflowbutton"
99
114
  ref={overflowbuttonRef}
100
- className={cm("flexlayout__border_toolbar_button_overflow") + " " + cm("flexlayout__border_toolbar_button_overflow_" + border.getLocation().getName())}
115
+ className={cm(CLASSES.FLEXLAYOUT__BORDER_TOOLBAR_BUTTON_OVERFLOW) + " " + cm(CLASSES.FLEXLAYOUT__BORDER_TOOLBAR_BUTTON_OVERFLOW_ + border.getLocation().getName())}
101
116
  title={overflowTitle}
102
117
  onClick={onOverflowClick}
103
118
  onMouseDown={onInterceptMouseDown}
@@ -145,7 +160,12 @@ export const BorderTabSet = (props: IBorderTabSetProps) => {
145
160
  }
146
161
 
147
162
  return (
148
- <div ref={selfRef} style={style} className={borderClasses} onWheel={onMouseWheel}>
163
+ <div ref={selfRef} dir="ltr" style={style} className={borderClasses}
164
+ data-layout-path={path}
165
+ onClick={onAuxMouseClick}
166
+ onAuxClick={onAuxMouseClick}
167
+ onContextMenu={onContextMenu}
168
+ onWheel={onMouseWheel}>
149
169
  <div style={{ height: borderHeight }} className={cm(CLASSES.FLEXLAYOUT__BORDER_INNER) + " " + cm(CLASSES.FLEXLAYOUT__BORDER_INNER_ + border.getLocation().getName())}>
150
170
  <div style={innerStyle} className={cm(CLASSES.FLEXLAYOUT__BORDER_INNER_TAB_CONTAINER) + " " + cm(CLASSES.FLEXLAYOUT__BORDER_INNER_TAB_CONTAINER_ + border.getLocation().getName())}>
151
171
  {tabs}