flexlayout-react 0.7.15 → 0.8.1

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 (252) hide show
  1. package/ChangeLog.txt +28 -0
  2. package/README.md +157 -330
  3. package/Screenshot_light.png +0 -0
  4. package/Screenshot_rounded.png +0 -0
  5. package/declarations/Attribute.d.ts +1 -1
  6. package/declarations/AttributeDefinitions.d.ts +1 -1
  7. package/declarations/DockLocation.d.ts +12 -12
  8. package/declarations/DropInfo.d.ts +12 -12
  9. package/declarations/I18nLabel.d.ts +12 -14
  10. package/declarations/Orientation.d.ts +7 -7
  11. package/declarations/PopupMenu.d.ts +1 -1
  12. package/declarations/Rect.d.ts +41 -28
  13. package/declarations/Types.d.ts +95 -79
  14. package/declarations/examples/demo/Utils.d.ts +4 -0
  15. package/declarations/index.d.ts +21 -22
  16. package/declarations/model/Action.d.ts +5 -5
  17. package/declarations/model/Actions.d.ts +127 -110
  18. package/declarations/model/BorderNode.d.ts +30 -34
  19. package/declarations/model/BorderSet.d.ts +3 -4
  20. package/declarations/model/ICloseType.d.ts +5 -5
  21. package/declarations/model/IDraggable.d.ts +2 -2
  22. package/declarations/model/IDropTarget.d.ts +2 -2
  23. package/declarations/model/IJsonModel.d.ts +811 -149
  24. package/declarations/model/LayoutWindow.d.ts +28 -0
  25. package/declarations/model/Model.d.ts +91 -86
  26. package/declarations/model/Node.d.ts +17 -17
  27. package/declarations/model/RowNode.d.ts +10 -11
  28. package/declarations/model/TabNode.d.ts +44 -37
  29. package/declarations/model/TabSetNode.d.ts +44 -41
  30. package/declarations/model/Utils.d.ts +1 -1
  31. package/declarations/model/WindowLayout.d.ts +24 -0
  32. package/declarations/src/Attribute.d.ts +1 -0
  33. package/declarations/src/AttributeDefinitions.d.ts +1 -0
  34. package/declarations/src/DockLocation.d.ts +12 -0
  35. package/declarations/src/DropInfo.d.ts +12 -0
  36. package/declarations/src/I18nLabel.d.ts +10 -0
  37. package/declarations/src/Orientation.d.ts +7 -0
  38. package/declarations/src/PopupMenu.d.ts +1 -0
  39. package/declarations/src/Rect.d.ts +31 -0
  40. package/declarations/src/Types.d.ts +92 -0
  41. package/declarations/src/index.d.ts +20 -0
  42. package/declarations/src/model/Action.d.ts +5 -0
  43. package/declarations/src/model/Actions.d.ts +110 -0
  44. package/declarations/src/model/BorderNode.d.ts +28 -0
  45. package/declarations/src/model/BorderSet.d.ts +3 -0
  46. package/declarations/src/model/ICloseType.d.ts +5 -0
  47. package/declarations/src/model/IDraggable.d.ts +2 -0
  48. package/declarations/src/model/IDropTarget.d.ts +2 -0
  49. package/declarations/src/model/IJsonModel.d.ts +153 -0
  50. package/declarations/src/model/Model.d.ts +98 -0
  51. package/declarations/src/model/Node.d.ts +16 -0
  52. package/declarations/src/model/RowNode.d.ts +11 -0
  53. package/declarations/src/model/TabNode.d.ts +36 -0
  54. package/declarations/src/model/TabSetNode.d.ts +37 -0
  55. package/declarations/src/model/Utils.d.ts +1 -0
  56. package/declarations/src/view/BorderButton.d.ts +1 -0
  57. package/declarations/src/view/BorderTab.d.ts +2 -0
  58. package/declarations/src/view/BorderTabSet.d.ts +1 -0
  59. package/declarations/src/view/DragContainer.d.ts +1 -0
  60. package/declarations/src/view/ErrorBoundary.d.ts +1 -0
  61. package/declarations/src/view/FloatingWindow.d.ts +1 -0
  62. package/declarations/src/view/Icons.d.ts +7 -0
  63. package/declarations/src/view/Layout.d.ts +113 -0
  64. package/declarations/src/view/Overlay.d.ts +1 -0
  65. package/declarations/src/view/PopupMenu.d.ts +1 -0
  66. package/declarations/src/view/Row.d.ts +1 -0
  67. package/declarations/src/view/Splitter.d.ts +1 -0
  68. package/declarations/src/view/Tab.d.ts +1 -0
  69. package/declarations/src/view/TabButton.d.ts +1 -0
  70. package/declarations/src/view/TabButtonStamp.d.ts +1 -0
  71. package/declarations/src/view/TabOverflowHook.d.ts +1 -0
  72. package/declarations/src/view/TabSet.d.ts +1 -0
  73. package/declarations/src/view/Utils.d.ts +4 -0
  74. package/declarations/view/BorderButton.d.ts +1 -1
  75. package/declarations/view/BorderTab.d.ts +2 -0
  76. package/declarations/view/BorderTabSet.d.ts +1 -1
  77. package/declarations/view/DragContainer.d.ts +1 -0
  78. package/declarations/view/ErrorBoundary.d.ts +1 -1
  79. package/declarations/view/ExtendedResizeObserver.d.ts +23 -0
  80. package/declarations/view/FloatingWindow.d.ts +1 -1
  81. package/declarations/view/Icons.d.ts +8 -7
  82. package/declarations/view/Layout.d.ts +140 -161
  83. package/declarations/view/Overlay.d.ts +1 -0
  84. package/declarations/view/PopoutWindow.d.ts +1 -0
  85. package/declarations/view/PopupMenu.d.ts +1 -0
  86. package/declarations/view/Row.d.ts +1 -0
  87. package/declarations/view/SizeTracker.d.ts +10 -0
  88. package/declarations/view/Splitter.d.ts +1 -1
  89. package/declarations/view/Tab.d.ts +1 -1
  90. package/declarations/view/TabButton.d.ts +1 -1
  91. package/declarations/view/TabButtonStamp.d.ts +1 -1
  92. package/declarations/view/TabOverflowHook.d.ts +1 -1
  93. package/declarations/view/TabSet.d.ts +1 -1
  94. package/declarations/view/Utils.d.ts +11 -1
  95. package/dist/bundles/demo.js +232052 -0
  96. package/dist/bundles/demo.js.map +1 -0
  97. package/dist/flexlayout.js +122 -92
  98. package/dist/flexlayout_min.js +1 -1
  99. package/lib/Attribute.js +42 -31
  100. package/lib/Attribute.js.map +1 -1
  101. package/lib/AttributeDefinitions.js +131 -108
  102. package/lib/AttributeDefinitions.js.map +1 -1
  103. package/lib/DockLocation.js +120 -124
  104. package/lib/DockLocation.js.map +1 -1
  105. package/lib/DropInfo.js +9 -13
  106. package/lib/DropInfo.js.map +1 -1
  107. package/lib/I18nLabel.js +13 -18
  108. package/lib/I18nLabel.js.map +1 -1
  109. package/lib/Orientation.js +22 -26
  110. package/lib/Orientation.js.map +1 -1
  111. package/lib/Rect.js +104 -72
  112. package/lib/Rect.js.map +1 -1
  113. package/lib/Types.js +96 -83
  114. package/lib/Types.js.map +1 -1
  115. package/lib/index.js +21 -38
  116. package/lib/index.js.map +1 -1
  117. package/lib/model/Action.js +6 -10
  118. package/lib/model/Action.js.map +1 -1
  119. package/lib/model/Actions.js +169 -155
  120. package/lib/model/Actions.js.map +1 -1
  121. package/lib/model/BorderNode.js +385 -406
  122. package/lib/model/BorderNode.js.map +1 -1
  123. package/lib/model/BorderSet.js +66 -121
  124. package/lib/model/BorderSet.js.map +1 -1
  125. package/lib/model/ICloseType.js +6 -9
  126. package/lib/model/ICloseType.js.map +1 -1
  127. package/lib/model/IDraggable.js +1 -2
  128. package/lib/model/IDropTarget.js +1 -2
  129. package/lib/model/IJsonModel.js +1 -2
  130. package/lib/model/LayoutWindow.js +83 -0
  131. package/lib/model/LayoutWindow.js.map +1 -0
  132. package/lib/model/Model.js +614 -496
  133. package/lib/model/Model.js.map +1 -1
  134. package/lib/model/Node.js +217 -228
  135. package/lib/model/Node.js.map +1 -1
  136. package/lib/model/RowNode.js +491 -504
  137. package/lib/model/RowNode.js.map +1 -1
  138. package/lib/model/TabNode.js +289 -184
  139. package/lib/model/TabNode.js.map +1 -1
  140. package/lib/model/TabSetNode.js +459 -446
  141. package/lib/model/TabSetNode.js.map +1 -1
  142. package/lib/model/Utils.js +47 -82
  143. package/lib/model/Utils.js.map +1 -1
  144. package/lib/view/BorderButton.js +129 -138
  145. package/lib/view/BorderButton.js.map +1 -1
  146. package/lib/view/BorderTab.js +47 -0
  147. package/lib/view/BorderTab.js.map +1 -0
  148. package/lib/view/BorderTabSet.js +134 -128
  149. package/lib/view/BorderTabSet.js.map +1 -1
  150. package/lib/view/DragContainer.js +16 -0
  151. package/lib/view/DragContainer.js.map +1 -0
  152. package/lib/view/ErrorBoundary.js +23 -27
  153. package/lib/view/ErrorBoundary.js.map +1 -1
  154. package/lib/view/Icons.js +40 -45
  155. package/lib/view/Icons.js.map +1 -1
  156. package/lib/view/Layout.js +919 -907
  157. package/lib/view/Layout.js.map +1 -1
  158. package/lib/view/Overlay.js +9 -0
  159. package/lib/view/Overlay.js.map +1 -0
  160. package/lib/view/PopoutWindow.js +129 -0
  161. package/lib/view/PopoutWindow.js.map +1 -0
  162. package/lib/view/PopupMenu.js +71 -0
  163. package/lib/view/PopupMenu.js.map +1 -0
  164. package/lib/view/Row.js +45 -0
  165. package/lib/view/Row.js.map +1 -0
  166. package/lib/view/SizeTracker.js +11 -0
  167. package/lib/view/SizeTracker.js.map +1 -0
  168. package/lib/view/Splitter.js +191 -147
  169. package/lib/view/Splitter.js.map +1 -1
  170. package/lib/view/Tab.js +86 -60
  171. package/lib/view/Tab.js.map +1 -1
  172. package/lib/view/TabButton.js +127 -135
  173. package/lib/view/TabButton.js.map +1 -1
  174. package/lib/view/TabButtonStamp.js +16 -21
  175. package/lib/view/TabButtonStamp.js.map +1 -1
  176. package/lib/view/TabOverflowHook.js +150 -149
  177. package/lib/view/TabOverflowHook.js.map +1 -1
  178. package/lib/view/TabSet.js +272 -234
  179. package/lib/view/TabSet.js.map +1 -1
  180. package/lib/view/Utils.js +126 -68
  181. package/lib/view/Utils.js.map +1 -1
  182. package/package.json +36 -30
  183. package/src/Attribute.ts +23 -0
  184. package/src/AttributeDefinitions.ts +38 -15
  185. package/src/DockLocation.ts +13 -13
  186. package/src/I18nLabel.ts +7 -9
  187. package/src/Rect.ts +53 -1
  188. package/src/Types.ts +16 -0
  189. package/src/index.ts +1 -2
  190. package/src/model/Actions.ts +49 -29
  191. package/src/model/BorderNode.ts +208 -214
  192. package/src/model/BorderSet.ts +42 -91
  193. package/src/model/IJsonModel.ts +883 -103
  194. package/src/model/LayoutWindow.ts +121 -0
  195. package/src/model/Model.ts +488 -366
  196. package/src/model/Node.ts +98 -111
  197. package/src/model/RowNode.ts +323 -319
  198. package/src/model/TabNode.ts +294 -110
  199. package/src/model/TabSetNode.ts +303 -242
  200. package/src/model/Utils.ts +6 -32
  201. package/src/view/BorderButton.tsx +36 -52
  202. package/src/view/BorderTab.tsx +70 -0
  203. package/src/view/BorderTabSet.tsx +64 -52
  204. package/src/view/DragContainer.tsx +32 -0
  205. package/src/view/Icons.tsx +6 -0
  206. package/src/view/Layout.tsx +1053 -1046
  207. package/src/view/Overlay.tsx +22 -0
  208. package/src/view/PopoutWindow.tsx +152 -0
  209. package/src/{PopupMenu.tsx → view/PopupMenu.tsx} +36 -31
  210. package/src/view/Row.tsx +68 -0
  211. package/src/view/SizeTracker.tsx +20 -0
  212. package/src/view/Splitter.tsx +167 -112
  213. package/src/view/Tab.tsx +76 -42
  214. package/src/view/TabButton.tsx +39 -54
  215. package/src/view/TabButtonStamp.tsx +5 -9
  216. package/src/view/TabOverflowHook.tsx +14 -9
  217. package/src/view/TabSet.tsx +221 -176
  218. package/src/view/Utils.tsx +119 -39
  219. package/style/_base.scss +140 -34
  220. package/style/dark.css +140 -35
  221. package/style/dark.css.map +1 -1
  222. package/style/dark.scss +3 -1
  223. package/style/gray.css +139 -34
  224. package/style/gray.css.map +1 -1
  225. package/style/gray.scss +2 -0
  226. package/style/light.css +141 -36
  227. package/style/light.css.map +1 -1
  228. package/style/light.scss +4 -2
  229. package/style/rounded.css +697 -0
  230. package/style/rounded.css.map +1 -0
  231. package/style/rounded.scss +194 -0
  232. package/style/underline.css +139 -34
  233. package/style/underline.css.map +1 -1
  234. package/style/underline.scss +2 -0
  235. package/cypress.config.ts +0 -16
  236. package/lib/DragDrop.js +0 -316
  237. package/lib/DragDrop.js.map +0 -1
  238. package/lib/PopupMenu.js +0 -68
  239. package/lib/PopupMenu.js.map +0 -1
  240. package/lib/model/SplitterNode.js +0 -72
  241. package/lib/model/SplitterNode.js.map +0 -1
  242. package/lib/view/FloatingWindow.js +0 -123
  243. package/lib/view/FloatingWindow.js.map +0 -1
  244. package/lib/view/FloatingWindowTab.js +0 -19
  245. package/lib/view/FloatingWindowTab.js.map +0 -1
  246. package/lib/view/TabFloating.js +0 -66
  247. package/lib/view/TabFloating.js.map +0 -1
  248. package/src/DragDrop.ts +0 -392
  249. package/src/model/SplitterNode.ts +0 -78
  250. package/src/view/FloatingWindow.tsx +0 -140
  251. package/src/view/FloatingWindowTab.tsx +0 -29
  252. package/src/view/TabFloating.tsx +0 -101
@@ -3,32 +3,6 @@ import { BorderNode } from "./BorderNode";
3
3
  import { RowNode } from "./RowNode";
4
4
  import { TabNode } from "./TabNode";
5
5
 
6
- /** @internal */
7
- export function adjustSelectedIndexAfterFloat(node: TabNode) {
8
- const parent = node.getParent();
9
- if (parent !== null) {
10
- if (parent instanceof TabSetNode) {
11
- let found = false;
12
- let newSelected = 0;
13
- const children = parent.getChildren();
14
- for (let i = 0; i < children.length; i++) {
15
- const child = children[i] as TabNode;
16
- if (child === node) {
17
- found = true;
18
- } else {
19
- if (!child.isFloating()) {
20
- newSelected = i;
21
- if (found) break;
22
- }
23
- }
24
- }
25
- parent._setSelected(newSelected);
26
- } else if (parent instanceof BorderNode) {
27
- parent._setSelected(-1);
28
- }
29
- }
30
- }
31
-
32
6
  /** @internal */
33
7
  export function adjustSelectedIndexAfterDock(node: TabNode) {
34
8
  const parent = node.getParent();
@@ -37,7 +11,7 @@ export function adjustSelectedIndexAfterDock(node: TabNode) {
37
11
  for (let i = 0; i < children.length; i++) {
38
12
  const child = children[i] as TabNode;
39
13
  if (child === node) {
40
- parent._setSelected(i);
14
+ parent.setSelected(i);
41
15
  return;
42
16
  }
43
17
  }
@@ -47,28 +21,28 @@ export function adjustSelectedIndexAfterDock(node: TabNode) {
47
21
  /** @internal */
48
22
  export function adjustSelectedIndex(parent: TabSetNode | BorderNode | RowNode, removedIndex: number) {
49
23
  // for the tabset/border being removed from set the selected index
50
- if (parent !== undefined && (parent.getType() === TabSetNode.TYPE || parent.getType() === BorderNode.TYPE)) {
24
+ if (parent !== undefined && (parent instanceof TabSetNode || parent instanceof BorderNode)) {
51
25
  const selectedIndex = (parent as TabSetNode | BorderNode).getSelected();
52
26
  if (selectedIndex !== -1) {
53
27
  if (removedIndex === selectedIndex && parent.getChildren().length > 0) {
54
28
  if (removedIndex >= parent.getChildren().length) {
55
29
  // removed last tab; select new last tab
56
- parent._setSelected(parent.getChildren().length - 1);
30
+ parent.setSelected(parent.getChildren().length - 1);
57
31
  } else {
58
32
  // leave selected index as is, selecting next tab after this one
59
33
  }
60
34
  } else if (removedIndex < selectedIndex) {
61
- parent._setSelected(selectedIndex - 1);
35
+ parent.setSelected(selectedIndex - 1);
62
36
  } else if (removedIndex > selectedIndex) {
63
37
  // leave selected index as is
64
38
  } else {
65
- parent._setSelected(-1);
39
+ parent.setSelected(-1);
66
40
  }
67
41
  }
68
42
  }
69
43
  }
70
44
 
71
- export function randomUUID() {
45
+ export function randomUUID(): string {
72
46
  // @ts-ignore
73
47
  return ([1e7]+-1e3+-4e3+-8e3+-1e11).replace(/[018]/g, c =>
74
48
  (c ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> c / 4).toString(16)
@@ -2,44 +2,48 @@ import * as React from "react";
2
2
  import { I18nLabel } from "../I18nLabel";
3
3
  import { Actions } from "../model/Actions";
4
4
  import { TabNode } from "../model/TabNode";
5
- import { Rect } from "../Rect";
6
- import { IconFactory, IIcons, ILayoutCallbacks, TitleFactory } from "./Layout";
5
+ import { IIcons, LayoutInternal } from "./Layout";
7
6
  import { ICloseType } from "../model/ICloseType";
8
7
  import { CLASSES } from "../Types";
9
8
  import { getRenderStateEx, isAuxMouseEvent } from "./Utils";
10
9
 
11
10
  /** @internal */
12
11
  export interface IBorderButtonProps {
13
- layout: ILayoutCallbacks;
12
+ layout: LayoutInternal;
14
13
  node: TabNode;
15
14
  selected: boolean;
16
15
  border: string;
17
- iconFactory?: IconFactory;
18
- titleFactory?: TitleFactory;
19
16
  icons: IIcons;
20
17
  path: string;
21
18
  }
22
19
 
23
20
  /** @internal */
24
21
  export const BorderButton = (props: IBorderButtonProps) => {
25
- const { layout, node, selected, border, iconFactory, titleFactory, icons, path } = props;
22
+ const { layout, node, selected, border, icons, path } = props;
26
23
  const selfRef = React.useRef<HTMLDivElement | null>(null);
27
24
  const contentRef = React.useRef<HTMLInputElement | null>(null);
28
25
 
29
- const onMouseDown = (event: React.MouseEvent<HTMLDivElement, MouseEvent> | React.TouchEvent<HTMLDivElement>) => {
30
-
31
- if (!isAuxMouseEvent(event) && !layout.getEditingTab()) {
32
- layout.dragStart(event, undefined, node, node.isEnableDrag(), onClick, onDoubleClick);
26
+ const onDragStart = (event: React.DragEvent<HTMLElement>) => {
27
+ if (node.isEnableDrag()) {
28
+ event.stopPropagation();
29
+ layout.setDragNode(event.nativeEvent, node as TabNode);
30
+ } else {
31
+ event.preventDefault();
33
32
  }
34
33
  };
35
34
 
36
- const onAuxMouseClick = (event: React.MouseEvent<HTMLDivElement, MouseEvent>) => {
35
+ const onDragEnd = (event: React.DragEvent<HTMLElement>) => {
36
+ event.stopPropagation();
37
+ layout.clearDragMain();
38
+ };
39
+
40
+ const onAuxMouseClick = (event: React.MouseEvent<HTMLElement, MouseEvent>) => {
37
41
  if (isAuxMouseEvent(event)) {
38
42
  layout.auxMouseClick(node, event);
39
- }
43
+ }
40
44
  };
41
45
 
42
- const onContextMenu = (event: React.MouseEvent<HTMLDivElement, MouseEvent>) => {
46
+ const onContextMenu = (event: React.MouseEvent<HTMLElement, MouseEvent>) => {
43
47
  layout.showContextMenu(node, event);
44
48
  };
45
49
 
@@ -47,22 +51,20 @@ export const BorderButton = (props: IBorderButtonProps) => {
47
51
  layout.doAction(Actions.selectTab(node.getId()));
48
52
  };
49
53
 
50
- const onDoubleClick = (event: Event) => {
51
- // if (node.isEnableRename()) {
52
- // onRename();
53
- // }
54
- };
54
+ // const onDoubleClick = (event: Event) => {
55
+ // // if (node.isEnableRename()) {
56
+ // // onRename();
57
+ // // }
58
+ // };
55
59
 
56
60
  // const onRename = () => {
57
61
  // layout.setEditingTab(node);
58
- // layout.getCurrentDocument()!.body.addEventListener("mousedown", onEndEdit);
59
- // layout.getCurrentDocument()!.body.addEventListener("touchstart", onEndEdit);
62
+ // layout.getCurrentDocument()!.body.addEventListener("pointerdown", onEndEdit);
60
63
  // };
61
64
 
62
65
  const onEndEdit = (event: Event) => {
63
66
  if (event.target !== contentRef.current!) {
64
- layout.getCurrentDocument()!.body.removeEventListener("mousedown", onEndEdit);
65
- layout.getCurrentDocument()!.body.removeEventListener("touchstart", onEndEdit);
67
+ layout.getCurrentDocument()!.body.removeEventListener("pointerdown", onEndEdit);
66
68
  layout.setEditingTab(undefined);
67
69
  }
68
70
  };
@@ -81,7 +83,7 @@ export const BorderButton = (props: IBorderButtonProps) => {
81
83
  return false;
82
84
  };
83
85
 
84
- const onClose = (event: React.MouseEvent<HTMLDivElement>) => {
86
+ const onClose = (event: React.MouseEvent<HTMLElement>) => {
85
87
  if (isClosable()) {
86
88
  layout.doAction(Actions.deleteTab(node.getId()));
87
89
  } else {
@@ -89,35 +91,18 @@ export const BorderButton = (props: IBorderButtonProps) => {
89
91
  }
90
92
  };
91
93
 
92
- const onCloseMouseDown = (event: React.MouseEvent<HTMLDivElement> | React.TouchEvent<HTMLDivElement>) => {
94
+ const onClosePointerDown = (event: React.PointerEvent<HTMLElement>) => {
93
95
  event.stopPropagation();
94
96
  };
95
97
 
96
98
  React.useLayoutEffect(() => {
97
- updateRect();
99
+ node.setTabRect(layout.getBoundingClientRect(selfRef.current!));
98
100
  if (layout.getEditingTab() === node) {
99
101
  (contentRef.current! as HTMLInputElement).select();
100
102
  }
101
103
  });
102
104
 
103
- const updateRect = () => {
104
- // record position of tab in node
105
- const layoutRect = layout.getDomRect();
106
- const r = selfRef.current?.getBoundingClientRect();
107
- if (r && layoutRect) {
108
- node._setTabRect(
109
- new Rect(
110
- r.left - layoutRect.left,
111
- r.top - layoutRect.top,
112
- r.width,
113
- r.height
114
- )
115
- );
116
- }
117
- };
118
-
119
- const onTextBoxMouseDown = (event: React.MouseEvent<HTMLInputElement> | React.TouchEvent<HTMLInputElement>) => {
120
- // console.log("onTextBoxMouseDown");
105
+ const onTextBoxPointerDown = (event: React.PointerEvent<HTMLInputElement>) => {
121
106
  event.stopPropagation();
122
107
  };
123
108
 
@@ -154,7 +139,7 @@ export const BorderButton = (props: IBorderButtonProps) => {
154
139
  }
155
140
  }
156
141
 
157
- const renderState = getRenderStateEx(layout, node, iconFactory, titleFactory, iconAngle);
142
+ const renderState = getRenderStateEx(layout, node, iconAngle);
158
143
 
159
144
  let content = renderState.content ? (
160
145
  <div className={cm(CLASSES.FLEXLAYOUT__BORDER_BUTTON_CONTENT)}>
@@ -176,8 +161,7 @@ export const BorderButton = (props: IBorderButtonProps) => {
176
161
  autoFocus={true}
177
162
  defaultValue={node.getName()}
178
163
  onKeyDown={onTextBoxKeyPress}
179
- onMouseDown={onTextBoxMouseDown}
180
- onTouchStart={onTextBoxMouseDown}
164
+ onPointerDown={onTextBoxPointerDown}
181
165
  />
182
166
  );
183
167
  }
@@ -190,9 +174,8 @@ export const BorderButton = (props: IBorderButtonProps) => {
190
174
  data-layout-path={path + "/button/close"}
191
175
  title={closeTitle}
192
176
  className={cm(CLASSES.FLEXLAYOUT__BORDER_BUTTON_TRAILING)}
193
- onMouseDown={onCloseMouseDown}
194
- onClick={onClose}
195
- onTouchStart={onCloseMouseDown}>
177
+ onPointerDown={onClosePointerDown}
178
+ onClick={onClose}>
196
179
  {(typeof icons.close === "function") ? icons.close(node) : icons.close}
197
180
  </div>
198
181
  );
@@ -203,12 +186,13 @@ export const BorderButton = (props: IBorderButtonProps) => {
203
186
  ref={selfRef}
204
187
  data-layout-path={path}
205
188
  className={classNames}
206
- onMouseDown={onMouseDown}
207
- onClick={onAuxMouseClick}
189
+ onClick={onClick}
208
190
  onAuxClick={onAuxMouseClick}
209
191
  onContextMenu={onContextMenu}
210
- onTouchStart={onMouseDown}
211
192
  title={node.getHelpText()}
193
+ draggable={true}
194
+ onDragStart={onDragStart}
195
+ onDragEnd={onDragEnd}
212
196
  >
213
197
  {leading}
214
198
  {content}
@@ -0,0 +1,70 @@
1
+ import * as React from "react";
2
+ import { Orientation } from "../Orientation";
3
+ import { LayoutInternal } from "./Layout";
4
+ import { BorderNode } from "../model/BorderNode";
5
+ import { Rect } from "../Rect";
6
+ import { Splitter } from "./Splitter";
7
+ import { DockLocation } from "../DockLocation";
8
+ import { CLASSES } from "../Types";
9
+
10
+ /** @internal */
11
+ export interface IBorderTabProps {
12
+ layout: LayoutInternal;
13
+ border: BorderNode;
14
+ show: boolean;
15
+ }
16
+
17
+ export function BorderTab(props: IBorderTabProps) {
18
+ const { layout, border, show } = props;
19
+ const selfRef = React.useRef<HTMLDivElement | null>(null);
20
+
21
+ React.useLayoutEffect(() => {
22
+ const outerRect = layout.getBoundingClientRect(selfRef.current!);
23
+ const contentRect = Rect.getContentRect(selfRef.current!).relativeTo(layout.getDomRect()!);
24
+ if (outerRect.width > 0) {
25
+ border.setOuterRect(outerRect);
26
+ if (!border.getContentRect().equals(contentRect)) {
27
+ border.setContentRect(contentRect);
28
+ layout.redrawInternal("border content rect");
29
+ }
30
+ }
31
+
32
+ });
33
+
34
+ let horizontal = true;
35
+ const style: Record<string, any> = {};
36
+
37
+ if (border.getOrientation() === Orientation.HORZ) {
38
+ style.width = border.getSize();
39
+ style.minWidth = border.getMinSize();
40
+ style.maxWidth = border.getMaxSize();
41
+ } else {
42
+ style.height = border.getSize();
43
+ style.minHeight = border.getMinSize();
44
+ style.maxHeight = border.getMaxSize();
45
+ horizontal = false;
46
+ }
47
+
48
+ style.display = show ? "flex":"none";
49
+
50
+ const className = layout.getClassName(CLASSES.FLEXLAYOUT__BORDER_TAB_CONTENTS);
51
+
52
+ if (border.getLocation() === DockLocation.LEFT || border.getLocation() === DockLocation.TOP) {
53
+ return (
54
+ <>
55
+ <div ref={selfRef} style={style} className={className}>
56
+ </div>
57
+ {show && <Splitter layout={layout} node={border} index={0} horizontal={horizontal} />}
58
+ </>
59
+ );
60
+ } else {
61
+ return (
62
+ <>
63
+ {show && <Splitter layout={layout} node={border} index={0} horizontal={horizontal} />}
64
+ <div ref={selfRef} style={style} className={className}>
65
+ </div>
66
+ </>
67
+ );
68
+
69
+ }
70
+ }
@@ -3,46 +3,51 @@ import { DockLocation } from "../DockLocation";
3
3
  import { BorderNode } from "../model/BorderNode";
4
4
  import { TabNode } from "../model/TabNode";
5
5
  import { BorderButton } from "./BorderButton";
6
- import { IIcons, ILayoutCallbacks, ITabSetRenderValues, ITitleObject } from "./Layout";
7
- import { showPopup } from "../PopupMenu";
6
+ import { LayoutInternal, ITabSetRenderValues } from "./Layout";
7
+ import { showPopup } from "./PopupMenu";
8
8
  import { Actions } from "../model/Actions";
9
9
  import { I18nLabel } from "../I18nLabel";
10
10
  import { useTabOverflow } from "./TabOverflowHook";
11
11
  import { Orientation } from "../Orientation";
12
12
  import { CLASSES } from "../Types";
13
13
  import { isAuxMouseEvent } from "./Utils";
14
+ import { Rect } from "../Rect";
14
15
 
15
16
  /** @internal */
16
17
  export interface IBorderTabSetProps {
17
18
  border: BorderNode;
18
- layout: ILayoutCallbacks;
19
- iconFactory?: (node: TabNode) => (React.ReactNode | undefined);
20
- titleFactory?: (node: TabNode) => (ITitleObject | React.ReactNode | undefined);
21
- icons: IIcons;
22
- path: string;
19
+ layout: LayoutInternal;
20
+ size: number;
23
21
  }
24
22
 
25
23
  /** @internal */
26
24
  export const BorderTabSet = (props: IBorderTabSetProps) => {
27
- const { border, layout, iconFactory, titleFactory, icons, path } = props;
25
+ const { border, layout, size } = props;
28
26
 
29
27
  const toolbarRef = React.useRef<HTMLDivElement | null>(null);
30
28
  const overflowbuttonRef = React.useRef<HTMLButtonElement | null>(null);
31
29
  const stickyButtonsRef = React.useRef<HTMLDivElement | null>(null);
32
30
 
33
- const { selfRef, position, userControlledLeft, hiddenTabs, onMouseWheel, tabsTruncated } = useTabOverflow(border, Orientation.flip(border.getOrientation()), toolbarRef, stickyButtonsRef);
31
+ const icons = layout.getIcons();
34
32
 
35
- const onAuxMouseClick = (event: React.MouseEvent<HTMLDivElement, MouseEvent>) => {
33
+ React.useLayoutEffect(() => {
34
+ border.setTabHeaderRect(Rect.getBoundingClientRect(selfRef.current!).relativeTo(layout.getDomRect()!));
35
+ });
36
+
37
+ const { selfRef, position, userControlledLeft, hiddenTabs, onMouseWheel, tabsTruncated }
38
+ = useTabOverflow(border, Orientation.flip(border.getOrientation()), toolbarRef, stickyButtonsRef);
39
+
40
+ const onAuxMouseClick = (event: React.MouseEvent<HTMLElement, MouseEvent>) => {
36
41
  if (isAuxMouseEvent(event)) {
37
42
  layout.auxMouseClick(border, event);
38
43
  }
39
44
  };
40
45
 
41
- const onContextMenu = (event: React.MouseEvent<HTMLDivElement, MouseEvent>) => {
46
+ const onContextMenu = (event: React.MouseEvent<HTMLElement, MouseEvent>) => {
42
47
  layout.showContextMenu(border, event);
43
48
  };
44
49
 
45
- const onInterceptMouseDown = (event: React.MouseEvent | React.TouchEvent) => {
50
+ const onInterceptPointerDown = (event: React.PointerEvent) => {
46
51
  event.stopPropagation();
47
52
  };
48
53
 
@@ -55,9 +60,7 @@ export const BorderTabSet = (props: IBorderTabSetProps) => {
55
60
  showPopup(element,
56
61
  hiddenTabs,
57
62
  onOverflowItemSelect,
58
- layout,
59
- iconFactory,
60
- titleFactory);
63
+ layout);
61
64
  }
62
65
  event.stopPropagation();
63
66
  };
@@ -67,42 +70,38 @@ export const BorderTabSet = (props: IBorderTabSetProps) => {
67
70
  userControlledLeft.current = false;
68
71
  };
69
72
 
70
- const onFloatTab = (event: React.MouseEvent<HTMLElement, MouseEvent>) => {
73
+ const onPopoutTab = (event: React.MouseEvent<HTMLElement, MouseEvent>) => {
71
74
  const selectedTabNode = border.getChildren()[border.getSelected()] as TabNode;
72
75
  if (selectedTabNode !== undefined) {
73
- layout.doAction(Actions.floatTab(selectedTabNode.getId()));
76
+ layout.doAction(Actions.popoutTab(selectedTabNode.getId()));
74
77
  }
75
78
  event.stopPropagation();
76
79
  };
77
80
 
78
81
  const cm = layout.getClassName;
79
82
 
80
- let style = border.getTabHeaderRect()!.styleWithPosition({});
81
- const tabs: any = [];
83
+ const tabButtons: any = [];
82
84
 
83
85
  const layoutTab = (i: number) => {
84
86
  let isSelected = border.getSelected() === i;
85
87
  let child = border.getChildren()[i] as TabNode;
86
88
 
87
- tabs.push(
89
+ tabButtons.push(
88
90
  <BorderButton
89
91
  layout={layout}
90
92
  border={border.getLocation().getName()}
91
93
  node={child}
92
- path={path + "/tb" + i}
94
+ path={border.getPath() + "/tb" + i}
93
95
  key={child.getId()}
94
96
  selected={isSelected}
95
- iconFactory={iconFactory}
96
- titleFactory={titleFactory}
97
97
  icons={icons}
98
98
  />
99
99
  );
100
- if (i < border.getChildren().length-1) {
101
- tabs.push(
100
+ if (i < border.getChildren().length - 1) {
101
+ tabButtons.push(
102
102
  <div key={"divider" + i} className={cm(CLASSES.FLEXLAYOUT__BORDER_TAB_DIVIDER)}></div>
103
103
  );
104
104
  }
105
-
106
105
  };
107
106
 
108
107
  for (let i = 0; i < border.getChildren().length; i++) {
@@ -117,10 +116,10 @@ export const BorderTabSet = (props: IBorderTabSetProps) => {
117
116
  // allow customization of tabset right/bottom buttons
118
117
  let buttons: any[] = [];
119
118
  let stickyButtons: any[] = [];
120
- const renderState : ITabSetRenderValues= { headerContent: undefined, buttons, stickyButtons: stickyButtons, headerButtons: [], overflowPosition: undefined };
119
+ const renderState: ITabSetRenderValues = { buttons, stickyButtons: stickyButtons, overflowPosition: undefined };
121
120
  layout.customizeTabSet(border, renderState);
122
121
  buttons = renderState.buttons;
123
-
122
+
124
123
  if (renderState.overflowPosition === undefined) {
125
124
  renderState.overflowPosition = stickyButtons.length;
126
125
  }
@@ -129,11 +128,10 @@ export const BorderTabSet = (props: IBorderTabSetProps) => {
129
128
  if (tabsTruncated) {
130
129
  buttons = [...stickyButtons, ...buttons];
131
130
  } else {
132
- tabs.push(<div
131
+ tabButtons.push(<div
133
132
  ref={stickyButtonsRef}
134
133
  key="sticky_buttons_container"
135
- onMouseDown={onInterceptMouseDown}
136
- onTouchStart={onInterceptMouseDown}
134
+ onPointerDown={onInterceptPointerDown}
137
135
  onDragStart={(e) => { e.preventDefault() }}
138
136
  className={cm(CLASSES.FLEXLAYOUT__TAB_TOOLBAR_STICKY_BUTTONS_CONTAINER)}
139
137
  >
@@ -160,8 +158,7 @@ export const BorderTabSet = (props: IBorderTabSetProps) => {
160
158
  className={cm(CLASSES.FLEXLAYOUT__BORDER_TOOLBAR_BUTTON) + " " + cm(CLASSES.FLEXLAYOUT__BORDER_TOOLBAR_BUTTON_OVERFLOW) + " " + cm(CLASSES.FLEXLAYOUT__BORDER_TOOLBAR_BUTTON_OVERFLOW_ + border.getLocation().getName())}
161
159
  title={overflowTitle}
162
160
  onClick={onOverflowClick}
163
- onMouseDown={onInterceptMouseDown}
164
- onTouchStart={onInterceptMouseDown}
161
+ onPointerDown={onInterceptPointerDown}
165
162
  >
166
163
  {overflowContent}
167
164
  </button>
@@ -171,16 +168,15 @@ export const BorderTabSet = (props: IBorderTabSetProps) => {
171
168
  const selectedIndex = border.getSelected();
172
169
  if (selectedIndex !== -1) {
173
170
  const selectedTabNode = border.getChildren()[selectedIndex] as TabNode;
174
- if (selectedTabNode !== undefined && layout.isSupportsPopout() && selectedTabNode.isEnableFloat() && !selectedTabNode.isFloating()) {
175
- const floatTitle = layout.i18nName(I18nLabel.Float_Tab);
171
+ if (selectedTabNode !== undefined && layout.isSupportsPopout() && selectedTabNode.isEnablePopout()) {
172
+ const popoutTitle = layout.i18nName(I18nLabel.Popout_Tab);
176
173
  buttons.push(
177
174
  <button
178
- key="float"
179
- title={floatTitle}
175
+ key="popout"
176
+ title={popoutTitle}
180
177
  className={cm(CLASSES.FLEXLAYOUT__BORDER_TOOLBAR_BUTTON) + " " + cm(CLASSES.FLEXLAYOUT__BORDER_TOOLBAR_BUTTON_FLOAT)}
181
- onClick={onFloatTab}
182
- onMouseDown={onInterceptMouseDown}
183
- onTouchStart={onInterceptMouseDown}
178
+ onClick={onPopoutTab}
179
+ onPointerDown={onInterceptPointerDown}
184
180
  >
185
181
  {(typeof icons.popout === "function") ? icons.popout(selectedTabNode) : icons.popout}
186
182
  </button>
@@ -193,31 +189,47 @@ export const BorderTabSet = (props: IBorderTabSetProps) => {
193
189
  </div>
194
190
  );
195
191
 
196
- style = layout.styleFont(style);
197
-
198
192
  let innerStyle = {};
199
- const borderHeight = border.getBorderBarSize() - 1;
193
+ let outerStyle = {};
194
+ const borderHeight = size - 1;
200
195
  if (border.getLocation() === DockLocation.LEFT) {
201
- innerStyle = { right: borderHeight, height: borderHeight, top: position };
196
+ innerStyle = { right: "100%", top: position };
197
+ outerStyle = { width: borderHeight };
202
198
  } else if (border.getLocation() === DockLocation.RIGHT) {
203
- innerStyle = { left: borderHeight, height: borderHeight, top: position };
199
+ innerStyle = { left: "100%" , top:position};
200
+ outerStyle = { width: borderHeight };
204
201
  } else {
205
- innerStyle = { height: borderHeight, left: position };
202
+ innerStyle = { left:position};
203
+ outerStyle = { height: borderHeight };
206
204
  }
207
205
 
208
206
  return (
209
- <div ref={selfRef} dir="ltr" style={style} className={borderClasses}
210
- data-layout-path={path}
207
+ <div
208
+ ref={selfRef}
209
+ style={{
210
+ display: "flex",
211
+ flexDirection: (border.getOrientation() === Orientation.VERT ? "row" : "column")
212
+ }}
213
+ className={borderClasses}
214
+ data-layout-path={border.getPath()}
211
215
  onClick={onAuxMouseClick}
212
216
  onAuxClick={onAuxMouseClick}
213
217
  onContextMenu={onContextMenu}
214
- onWheel={onMouseWheel}>
215
- <div style={{ height: borderHeight }} className={cm(CLASSES.FLEXLAYOUT__BORDER_INNER) + " " + cm(CLASSES.FLEXLAYOUT__BORDER_INNER_ + border.getLocation().getName())}>
216
- <div style={innerStyle} className={cm(CLASSES.FLEXLAYOUT__BORDER_INNER_TAB_CONTAINER) + " " + cm(CLASSES.FLEXLAYOUT__BORDER_INNER_TAB_CONTAINER_ + border.getLocation().getName())}>
217
- {tabs}
218
+ onWheel={onMouseWheel}
219
+ >
220
+ <div
221
+ style={outerStyle}
222
+ className={cm(CLASSES.FLEXLAYOUT__BORDER_INNER) + " " + cm(CLASSES.FLEXLAYOUT__BORDER_INNER_ + border.getLocation().getName())}
223
+ >
224
+ <div
225
+ style={innerStyle}
226
+ className={cm(CLASSES.FLEXLAYOUT__BORDER_INNER_TAB_CONTAINER) + " " + cm(CLASSES.FLEXLAYOUT__BORDER_INNER_TAB_CONTAINER_ + border.getLocation().getName())}
227
+ >
228
+ {tabButtons}
218
229
  </div>
219
230
  </div>
220
231
  {toolbar}
221
232
  </div>
222
233
  );
234
+
223
235
  };
@@ -0,0 +1,32 @@
1
+ import * as React from "react";
2
+ import { TabNode } from "../model/TabNode";
3
+ import { LayoutInternal } from "./Layout";
4
+ import { CLASSES } from "../Types";
5
+ import { TabButtonStamp } from "./TabButtonStamp";
6
+
7
+ /** @internal */
8
+ export interface IDragContainerProps {
9
+ node: TabNode;
10
+ layout: LayoutInternal;
11
+ }
12
+
13
+ /** @internal */
14
+ export const DragContainer = (props: IDragContainerProps) => {
15
+ const { layout, node} = props;
16
+ const selfRef = React.useRef<HTMLDivElement | null>(null);
17
+
18
+ React.useEffect(()=> {
19
+ node.setTabStamp(selfRef.current);
20
+ }, [node, selfRef.current]);
21
+
22
+ const cm = layout.getClassName;
23
+
24
+ let classNames = cm(CLASSES.FLEXLAYOUT__DRAG_RECT);
25
+
26
+ return (<div
27
+ ref={selfRef}
28
+ className={classNames}>
29
+ <TabButtonStamp key={node.getId()} layout={layout} node={node} />
30
+ </div>
31
+ );
32
+ };
@@ -51,3 +51,9 @@ export const RestoreIcon = () => {
51
51
  <svg xmlns="http://www.w3.org/2000/svg" style={style} viewBox="0 0 24 24" fill="var(--color-icon)"><path d="M0 0h24v24H0z" fill="none" /><path stroke="var(--color-icon)" d="M5 16h3v3h2v-5H5v2zm3-8H5v2h5V5H8v3zm6 11h2v-3h3v-2h-5v5zm2-11V5h-2v5h5V8h-3z" /></svg>
52
52
  );
53
53
  }
54
+
55
+ export const AsterickIcon = () => {
56
+ return (
57
+ <svg xmlns="http://www.w3.org/2000/svg" style={style} height="24px" viewBox="0 -960 960 960" width="24px" ><path fill="var(--color-icon)" stroke="var(--color-icon)" d="M440-120v-264L254-197l-57-57 187-186H120v-80h264L197-706l57-57 186 187v-264h80v264l186-187 57 57-187 186h264v80H576l187 186-57 57-186-187v264h-80Z"/></svg>
58
+ );
59
+ }