flexlayout-react 0.8.12 → 0.8.13

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 (307) hide show
  1. package/README.md +16 -5
  2. package/declarations/Attribute.d.ts +25 -1
  3. package/declarations/AttributeDefinitions.d.ts +18 -1
  4. package/declarations/DockLocation.d.ts +22 -0
  5. package/declarations/I18nLabel.d.ts +2 -1
  6. package/declarations/Orientation.d.ts +4 -0
  7. package/declarations/Rect.d.ts +3 -0
  8. package/declarations/index.d.ts +1 -0
  9. package/declarations/model/BorderNode.d.ts +53 -0
  10. package/declarations/model/BorderSet.d.ts +28 -0
  11. package/declarations/model/IDraggable.d.ts +4 -0
  12. package/declarations/model/IDropTarget.d.ts +10 -0
  13. package/declarations/model/LayoutWindow.d.ts +16 -0
  14. package/declarations/model/Model.d.ts +55 -0
  15. package/declarations/model/Node.d.ts +61 -0
  16. package/declarations/model/RowNode.d.ts +67 -0
  17. package/declarations/model/TabNode.d.ts +79 -0
  18. package/declarations/model/TabSetNode.d.ts +60 -0
  19. package/declarations/model/Utils.d.ts +8 -0
  20. package/declarations/view/BorderButton.d.ts +13 -1
  21. package/declarations/view/BorderTab.d.ts +8 -0
  22. package/declarations/view/BorderTabSet.d.ts +10 -1
  23. package/declarations/view/DragContainer.d.ts +9 -1
  24. package/declarations/view/ErrorBoundary.d.ts +22 -1
  25. package/declarations/view/Icons.d.ts +1 -0
  26. package/declarations/view/Layout.d.ts +143 -1
  27. package/declarations/view/Overlay.d.ts +8 -1
  28. package/declarations/view/PopoutWindow.d.ts +14 -1
  29. package/declarations/view/PopupMenu.d.ts +12 -1
  30. package/declarations/view/Row.d.ts +9 -1
  31. package/declarations/view/Splitter.d.ts +14 -1
  32. package/declarations/view/Tab.d.ts +11 -1
  33. package/declarations/view/TabButton.d.ts +11 -1
  34. package/declarations/view/TabButtonStamp.d.ts +9 -1
  35. package/declarations/view/TabOverflowHook.d.ts +16 -1
  36. package/declarations/view/TabSet.d.ts +9 -1
  37. package/declarations/view/Utils.d.ts +13 -0
  38. package/lib/index.js +6410 -22
  39. package/package.json +34 -26
  40. package/ChangeLog.txt +0 -372
  41. package/declarations/DragDrop.d.ts +0 -15
  42. package/declarations/PopupMenu.d.ts +0 -1
  43. package/declarations/model/SplitterNode.d.ts +0 -5
  44. package/declarations/model/WindowLayout.d.ts +0 -24
  45. package/declarations/src/Attribute.d.ts +0 -1
  46. package/declarations/src/AttributeDefinitions.d.ts +0 -1
  47. package/declarations/src/DockLocation.d.ts +0 -12
  48. package/declarations/src/DropInfo.d.ts +0 -12
  49. package/declarations/src/I18nLabel.d.ts +0 -10
  50. package/declarations/src/Orientation.d.ts +0 -7
  51. package/declarations/src/PopupMenu.d.ts +0 -1
  52. package/declarations/src/Rect.d.ts +0 -31
  53. package/declarations/src/Types.d.ts +0 -92
  54. package/declarations/src/index.d.ts +0 -20
  55. package/declarations/src/model/Action.d.ts +0 -5
  56. package/declarations/src/model/Actions.d.ts +0 -110
  57. package/declarations/src/model/BorderNode.d.ts +0 -28
  58. package/declarations/src/model/BorderSet.d.ts +0 -3
  59. package/declarations/src/model/ICloseType.d.ts +0 -5
  60. package/declarations/src/model/IDraggable.d.ts +0 -2
  61. package/declarations/src/model/IDropTarget.d.ts +0 -2
  62. package/declarations/src/model/IJsonModel.d.ts +0 -153
  63. package/declarations/src/model/Model.d.ts +0 -98
  64. package/declarations/src/model/Node.d.ts +0 -16
  65. package/declarations/src/model/RowNode.d.ts +0 -11
  66. package/declarations/src/model/TabNode.d.ts +0 -36
  67. package/declarations/src/model/TabSetNode.d.ts +0 -37
  68. package/declarations/src/model/Utils.d.ts +0 -1
  69. package/declarations/src/view/BorderButton.d.ts +0 -1
  70. package/declarations/src/view/BorderTab.d.ts +0 -2
  71. package/declarations/src/view/BorderTabSet.d.ts +0 -1
  72. package/declarations/src/view/DragContainer.d.ts +0 -1
  73. package/declarations/src/view/ErrorBoundary.d.ts +0 -1
  74. package/declarations/src/view/FloatingWindow.d.ts +0 -1
  75. package/declarations/src/view/Icons.d.ts +0 -7
  76. package/declarations/src/view/Layout.d.ts +0 -113
  77. package/declarations/src/view/Overlay.d.ts +0 -1
  78. package/declarations/src/view/PopupMenu.d.ts +0 -1
  79. package/declarations/src/view/Row.d.ts +0 -1
  80. package/declarations/src/view/Splitter.d.ts +0 -1
  81. package/declarations/src/view/Tab.d.ts +0 -1
  82. package/declarations/src/view/TabButton.d.ts +0 -1
  83. package/declarations/src/view/TabButtonStamp.d.ts +0 -1
  84. package/declarations/src/view/TabOverflowHook.d.ts +0 -1
  85. package/declarations/src/view/TabSet.d.ts +0 -1
  86. package/declarations/src/view/Utils.d.ts +0 -4
  87. package/declarations/view/ExtendedResizeObserver.d.ts +0 -23
  88. package/declarations/view/FloatingWindow.d.ts +0 -1
  89. package/declarations/view/FloatingWindowTab.d.ts +0 -1
  90. package/declarations/view/TabFloating.d.ts +0 -1
  91. package/dist/flexlayout.js +0 -610
  92. package/dist/flexlayout_min.js +0 -2
  93. package/dist/flexlayout_min.js.LICENSE.txt +0 -29
  94. package/dist/src/Attribute.js +0 -43
  95. package/dist/src/Attribute.js.map +0 -1
  96. package/dist/src/AttributeDefinitions.js +0 -132
  97. package/dist/src/AttributeDefinitions.js.map +0 -1
  98. package/dist/src/DockLocation.js +0 -121
  99. package/dist/src/DockLocation.js.map +0 -1
  100. package/dist/src/DropInfo.js +0 -10
  101. package/dist/src/DropInfo.js.map +0 -1
  102. package/dist/src/I18nLabel.js +0 -14
  103. package/dist/src/I18nLabel.js.map +0 -1
  104. package/dist/src/Orientation.js +0 -23
  105. package/dist/src/Orientation.js.map +0 -1
  106. package/dist/src/Rect.js +0 -111
  107. package/dist/src/Rect.js.map +0 -1
  108. package/dist/src/Types.js +0 -95
  109. package/dist/src/Types.js.map +0 -1
  110. package/dist/src/index.js +0 -22
  111. package/dist/src/index.js.map +0 -1
  112. package/dist/src/model/Action.js +0 -7
  113. package/dist/src/model/Action.js.map +0 -1
  114. package/dist/src/model/Actions.js +0 -170
  115. package/dist/src/model/Actions.js.map +0 -1
  116. package/dist/src/model/BorderNode.js +0 -390
  117. package/dist/src/model/BorderNode.js.map +0 -1
  118. package/dist/src/model/BorderSet.js +0 -67
  119. package/dist/src/model/BorderSet.js.map +0 -1
  120. package/dist/src/model/ICloseType.js +0 -7
  121. package/dist/src/model/ICloseType.js.map +0 -1
  122. package/dist/src/model/IDraggable.js +0 -2
  123. package/dist/src/model/IDraggable.js.map +0 -1
  124. package/dist/src/model/IDropTarget.js +0 -2
  125. package/dist/src/model/IDropTarget.js.map +0 -1
  126. package/dist/src/model/IJsonModel.js +0 -2
  127. package/dist/src/model/IJsonModel.js.map +0 -1
  128. package/dist/src/model/LayoutWindow.js +0 -81
  129. package/dist/src/model/LayoutWindow.js.map +0 -1
  130. package/dist/src/model/Model.js +0 -608
  131. package/dist/src/model/Model.js.map +0 -1
  132. package/dist/src/model/Node.js +0 -218
  133. package/dist/src/model/Node.js.map +0 -1
  134. package/dist/src/model/RowNode.js +0 -492
  135. package/dist/src/model/RowNode.js.map +0 -1
  136. package/dist/src/model/TabNode.js +0 -293
  137. package/dist/src/model/TabNode.js.map +0 -1
  138. package/dist/src/model/TabSetNode.js +0 -469
  139. package/dist/src/model/TabSetNode.js.map +0 -1
  140. package/dist/src/model/Utils.js +0 -48
  141. package/dist/src/model/Utils.js.map +0 -1
  142. package/dist/src/view/BorderButton.js +0 -126
  143. package/dist/src/view/BorderButton.js.map +0 -1
  144. package/dist/src/view/BorderTab.js +0 -44
  145. package/dist/src/view/BorderTab.js.map +0 -1
  146. package/dist/src/view/BorderTabSet.js +0 -138
  147. package/dist/src/view/BorderTabSet.js.map +0 -1
  148. package/dist/src/view/DragContainer.js +0 -16
  149. package/dist/src/view/DragContainer.js.map +0 -1
  150. package/dist/src/view/ErrorBoundary.js +0 -24
  151. package/dist/src/view/ErrorBoundary.js.map +0 -1
  152. package/dist/src/view/Icons.js +0 -29
  153. package/dist/src/view/Icons.js.map +0 -1
  154. package/dist/src/view/Layout.js +0 -881
  155. package/dist/src/view/Layout.js.map +0 -1
  156. package/dist/src/view/Overlay.js +0 -9
  157. package/dist/src/view/Overlay.js.map +0 -1
  158. package/dist/src/view/PopoutWindow.js +0 -129
  159. package/dist/src/view/PopoutWindow.js.map +0 -1
  160. package/dist/src/view/PopupMenu.js +0 -89
  161. package/dist/src/view/PopupMenu.js.map +0 -1
  162. package/dist/src/view/Row.js +0 -46
  163. package/dist/src/view/Row.js.map +0 -1
  164. package/dist/src/view/SizeTracker.js +0 -12
  165. package/dist/src/view/SizeTracker.js.map +0 -1
  166. package/dist/src/view/Splitter.js +0 -192
  167. package/dist/src/view/Splitter.js.map +0 -1
  168. package/dist/src/view/Tab.js +0 -91
  169. package/dist/src/view/Tab.js.map +0 -1
  170. package/dist/src/view/TabButton.js +0 -124
  171. package/dist/src/view/TabButton.js.map +0 -1
  172. package/dist/src/view/TabButtonStamp.js +0 -15
  173. package/dist/src/view/TabButtonStamp.js.map +0 -1
  174. package/dist/src/view/TabOverflowHook.js +0 -266
  175. package/dist/src/view/TabOverflowHook.js.map +0 -1
  176. package/dist/src/view/TabSet.js +0 -256
  177. package/dist/src/view/TabSet.js.map +0 -1
  178. package/dist/src/view/Utils.js +0 -110
  179. package/dist/src/view/Utils.js.map +0 -1
  180. package/lib/Attribute.js +0 -43
  181. package/lib/Attribute.js.map +0 -1
  182. package/lib/AttributeDefinitions.js +0 -132
  183. package/lib/AttributeDefinitions.js.map +0 -1
  184. package/lib/DockLocation.js +0 -121
  185. package/lib/DockLocation.js.map +0 -1
  186. package/lib/DropInfo.js +0 -10
  187. package/lib/DropInfo.js.map +0 -1
  188. package/lib/I18nLabel.js +0 -14
  189. package/lib/I18nLabel.js.map +0 -1
  190. package/lib/Orientation.js +0 -23
  191. package/lib/Orientation.js.map +0 -1
  192. package/lib/Rect.js +0 -111
  193. package/lib/Rect.js.map +0 -1
  194. package/lib/Types.js +0 -95
  195. package/lib/Types.js.map +0 -1
  196. package/lib/index.js.map +0 -1
  197. package/lib/model/Action.js +0 -7
  198. package/lib/model/Action.js.map +0 -1
  199. package/lib/model/Actions.js +0 -170
  200. package/lib/model/Actions.js.map +0 -1
  201. package/lib/model/BorderNode.js +0 -390
  202. package/lib/model/BorderNode.js.map +0 -1
  203. package/lib/model/BorderSet.js +0 -67
  204. package/lib/model/BorderSet.js.map +0 -1
  205. package/lib/model/ICloseType.js +0 -7
  206. package/lib/model/ICloseType.js.map +0 -1
  207. package/lib/model/IDraggable.js +0 -2
  208. package/lib/model/IDraggable.js.map +0 -1
  209. package/lib/model/IDropTarget.js +0 -2
  210. package/lib/model/IDropTarget.js.map +0 -1
  211. package/lib/model/IJsonModel.js +0 -2
  212. package/lib/model/IJsonModel.js.map +0 -1
  213. package/lib/model/LayoutWindow.js +0 -81
  214. package/lib/model/LayoutWindow.js.map +0 -1
  215. package/lib/model/Model.js +0 -608
  216. package/lib/model/Model.js.map +0 -1
  217. package/lib/model/Node.js +0 -218
  218. package/lib/model/Node.js.map +0 -1
  219. package/lib/model/RowNode.js +0 -492
  220. package/lib/model/RowNode.js.map +0 -1
  221. package/lib/model/TabNode.js +0 -293
  222. package/lib/model/TabNode.js.map +0 -1
  223. package/lib/model/TabSetNode.js +0 -469
  224. package/lib/model/TabSetNode.js.map +0 -1
  225. package/lib/model/Utils.js +0 -48
  226. package/lib/model/Utils.js.map +0 -1
  227. package/lib/view/BorderButton.js +0 -126
  228. package/lib/view/BorderButton.js.map +0 -1
  229. package/lib/view/BorderTab.js +0 -56
  230. package/lib/view/BorderTab.js.map +0 -1
  231. package/lib/view/BorderTabSet.js +0 -138
  232. package/lib/view/BorderTabSet.js.map +0 -1
  233. package/lib/view/DragContainer.js +0 -16
  234. package/lib/view/DragContainer.js.map +0 -1
  235. package/lib/view/ErrorBoundary.js +0 -24
  236. package/lib/view/ErrorBoundary.js.map +0 -1
  237. package/lib/view/Icons.js +0 -29
  238. package/lib/view/Icons.js.map +0 -1
  239. package/lib/view/Layout.js +0 -881
  240. package/lib/view/Layout.js.map +0 -1
  241. package/lib/view/Overlay.js +0 -9
  242. package/lib/view/Overlay.js.map +0 -1
  243. package/lib/view/PopoutWindow.js +0 -129
  244. package/lib/view/PopoutWindow.js.map +0 -1
  245. package/lib/view/PopupMenu.js +0 -89
  246. package/lib/view/PopupMenu.js.map +0 -1
  247. package/lib/view/Row.js +0 -46
  248. package/lib/view/Row.js.map +0 -1
  249. package/lib/view/SizeTracker.js +0 -12
  250. package/lib/view/SizeTracker.js.map +0 -1
  251. package/lib/view/Splitter.js +0 -197
  252. package/lib/view/Splitter.js.map +0 -1
  253. package/lib/view/Tab.js +0 -91
  254. package/lib/view/Tab.js.map +0 -1
  255. package/lib/view/TabButton.js +0 -124
  256. package/lib/view/TabButton.js.map +0 -1
  257. package/lib/view/TabButtonStamp.js +0 -15
  258. package/lib/view/TabButtonStamp.js.map +0 -1
  259. package/lib/view/TabOverflowHook.js +0 -266
  260. package/lib/view/TabOverflowHook.js.map +0 -1
  261. package/lib/view/TabSet.js +0 -269
  262. package/lib/view/TabSet.js.map +0 -1
  263. package/lib/view/Utils.js +0 -110
  264. package/lib/view/Utils.js.map +0 -1
  265. package/src/Attribute.ts +0 -64
  266. package/src/AttributeDefinitions.ts +0 -144
  267. package/src/DockLocation.ts +0 -133
  268. package/src/DropInfo.ts +0 -20
  269. package/src/I18nLabel.ts +0 -12
  270. package/src/Orientation.ts +0 -28
  271. package/src/Rect.ts +0 -147
  272. package/src/Types.ts +0 -112
  273. package/src/index.ts +0 -23
  274. package/src/model/Action.ts +0 -9
  275. package/src/model/Actions.ts +0 -188
  276. package/src/model/BorderNode.ts +0 -458
  277. package/src/model/BorderSet.ts +0 -87
  278. package/src/model/ICloseType.ts +0 -5
  279. package/src/model/IDraggable.ts +0 -7
  280. package/src/model/IDropTarget.ts +0 -14
  281. package/src/model/IJsonModel.ts +0 -967
  282. package/src/model/LayoutWindow.ts +0 -119
  283. package/src/model/Model.ts +0 -704
  284. package/src/model/Node.ts +0 -280
  285. package/src/model/RowNode.ts +0 -559
  286. package/src/model/TabNode.ts +0 -424
  287. package/src/model/TabSetNode.ts +0 -592
  288. package/src/model/Utils.ts +0 -52
  289. package/src/view/BorderButton.tsx +0 -201
  290. package/src/view/BorderTab.tsx +0 -81
  291. package/src/view/BorderTabSet.tsx +0 -259
  292. package/src/view/DragContainer.tsx +0 -32
  293. package/src/view/ErrorBoundary.tsx +0 -42
  294. package/src/view/Icons.tsx +0 -57
  295. package/src/view/Layout.tsx +0 -1334
  296. package/src/view/Overlay.tsx +0 -21
  297. package/src/view/PopoutWindow.tsx +0 -152
  298. package/src/view/PopupMenu.tsx +0 -156
  299. package/src/view/Row.tsx +0 -68
  300. package/src/view/SizeTracker.tsx +0 -20
  301. package/src/view/Splitter.tsx +0 -262
  302. package/src/view/Tab.tsx +0 -128
  303. package/src/view/TabButton.tsx +0 -200
  304. package/src/view/TabButtonStamp.tsx +0 -42
  305. package/src/view/TabOverflowHook.tsx +0 -305
  306. package/src/view/TabSet.tsx +0 -475
  307. package/src/view/Utils.tsx +0 -135
@@ -1,1334 +0,0 @@
1
- import * as React from "react";
2
- import { createPortal } from "react-dom";
3
- import { createRoot } from "react-dom/client";
4
- import { DockLocation } from "../DockLocation";
5
- import { DropInfo } from "../DropInfo";
6
- import { I18nLabel } from "../I18nLabel";
7
- import { Orientation } from "../Orientation";
8
- import { Rect } from "../Rect";
9
- import { CLASSES } from "../Types";
10
- import { Action } from "../model/Action";
11
- import { Actions } from "../model/Actions";
12
- import { BorderNode } from "../model/BorderNode";
13
- import { IDraggable } from "../model/IDraggable";
14
- import { IJsonTabNode } from "../model/IJsonModel";
15
- import { Model } from "../model/Model";
16
- import { Node } from "../model/Node";
17
- import { TabNode } from "../model/TabNode";
18
- import { TabSetNode } from "../model/TabSetNode";
19
- import { BorderTab } from "./BorderTab";
20
- import { BorderTabSet } from "./BorderTabSet";
21
- import { DragContainer } from "./DragContainer";
22
- import { ErrorBoundary } from "./ErrorBoundary";
23
- import { PopoutWindow } from "./PopoutWindow";
24
- import { AsterickIcon, CloseIcon, EdgeIcon, MaximizeIcon, OverflowIcon, PopoutIcon, RestoreIcon } from "./Icons";
25
- import { Overlay } from "./Overlay";
26
- import { Row } from "./Row";
27
- import { Tab } from "./Tab";
28
- import { copyInlineStyles, enablePointerOnIFrames, isDesktop, isSafari } from "./Utils";
29
- import { LayoutWindow } from "../model/LayoutWindow";
30
- import { TabButtonStamp } from "./TabButtonStamp";
31
- import { SizeTracker } from "./SizeTracker";
32
-
33
- export interface ILayoutProps {
34
- /** the model for this layout */
35
- model: Model;
36
- /** factory function for creating the tab components */
37
- factory: (node: TabNode) => React.ReactNode;
38
- /** sets a top level class name on popout windows */
39
- popoutClassName?: string;
40
- /** object mapping keys among close, maximize, restore, more, popout to React nodes to use in place of the default icons, can alternatively return functions for creating the React nodes */
41
- icons?: IIcons;
42
- /** function called whenever the layout generates an action to update the model (allows for intercepting actions before they are dispatched to the model, for example, asking the user to confirm a tab close.) Returning undefined from the function will halt the action, otherwise return the action to continue */
43
- onAction?: (action: Action) => Action | undefined;
44
- /** function called when rendering a tab, allows leading (icon), content section, buttons and name used in overflow menu to be customized */
45
- onRenderTab?: (
46
- node: TabNode,
47
- renderValues: ITabRenderValues, // change the values in this object as required
48
- ) => void;
49
- /** function called when rendering a tabset, allows header and buttons to be customized */
50
- onRenderTabSet?: (
51
- tabSetNode: TabSetNode | BorderNode,
52
- renderValues: ITabSetRenderValues, // change the values in this object as required
53
- ) => void;
54
- /** function called when model has changed */
55
- onModelChange?: (model: Model, action: Action) => void;
56
- /** function called when an external object (not a tab) gets dragged onto the layout, with a single dragenter argument. Should return either undefined to reject the drag/drop or an object with keys dragText, jsonDrop, to create a tab via drag (similar to a call to addTabToTabSet). Function onDropis passed the added tabNodeand thedrop DragEvent`, unless the drag was canceled. */
57
- onExternalDrag?: (event: React.DragEvent<HTMLElement>) => undefined | {
58
- json: any,
59
- onDrop?: (node?: Node, event?: React.DragEvent<HTMLElement>) => void
60
- };
61
- /** function called with default css class name, return value is class name that will be used. Mainly for use with css modules. */
62
- classNameMapper?: (defaultClassName: string) => string;
63
- /** function called for each I18nLabel to allow user translation, currently used for tab and tabset move messages, return undefined to use default values */
64
- i18nMapper?: (id: I18nLabel, param?: string) => string | undefined;
65
- /** if left undefined will do simple check based on userAgent */
66
- supportsPopout?: boolean | undefined;
67
- /** URL of popout window relative to origin, defaults to popout.html */
68
- popoutURL?: string | undefined;
69
- /** boolean value, defaults to false, resize tabs as splitters are dragged. Warning: this can cause resizing to become choppy when tabs are slow to draw */
70
- realtimeResize?: boolean | undefined;
71
- /** callback for rendering the drag rectangles */
72
- onRenderDragRect?: DragRectRenderCallback;
73
- /** callback for handling context actions on tabs and tabsets */
74
- onContextMenu?: NodeMouseEvent;
75
- /** callback for handling mouse clicks on tabs and tabsets with alt, meta, shift keys, also handles center mouse clicks */
76
- onAuxMouseClick?: NodeMouseEvent;
77
- /** callback for handling the display of the tab overflow menu */
78
- onShowOverflowMenu?: ShowOverflowMenuCallback;
79
- /** callback for rendering a placeholder when a tabset is empty */
80
- onTabSetPlaceHolder?: TabSetPlaceHolderCallback;
81
- /** Name given to popout windows, defaults to 'Popout Window' */
82
- popoutWindowName?: string;
83
- }
84
-
85
- /**
86
- * A React component that hosts a multi-tabbed layout
87
- */
88
- export class Layout extends React.Component<ILayoutProps> {
89
- /** @internal */
90
- private selfRef: React.RefObject<LayoutInternal | null>;
91
- /** @internal */
92
- private revision: number; // so LayoutInternal knows this is a parent render (used for optimization)
93
-
94
- /** @internal */
95
- constructor(props: ILayoutProps) {
96
- super(props);
97
- this.selfRef = React.createRef<LayoutInternal>();
98
- this.revision = 0;
99
- }
100
-
101
- /** re-render the layout */
102
- redraw() {
103
- this.selfRef.current!.redraw("parent " + this.revision);
104
- }
105
-
106
- /**
107
- * Adds a new tab to the given tabset
108
- * @param tabsetId the id of the tabset where the new tab will be added
109
- * @param json the json for the new tab node
110
- * @returns the added tab node or undefined
111
- */
112
- addTabToTabSet(tabsetId: string, json: IJsonTabNode): TabNode | undefined {
113
- return this.selfRef.current!.addTabToTabSet(tabsetId, json);
114
- }
115
-
116
- /**
117
- * Adds a new tab by dragging an item to the drop location, must be called from within an HTML
118
- * drag start handler. You can use the setDragComponent() method to set the drag image before calling this
119
- * method.
120
- * @param event the drag start event
121
- * @param json the json for the new tab node
122
- * @param onDrop a callback to call when the drag is complete
123
- */
124
- addTabWithDragAndDrop(event: DragEvent, json: IJsonTabNode, onDrop?: (node?: Node, event?: React.DragEvent<HTMLElement>) => void) {
125
- this.selfRef.current!.addTabWithDragAndDrop(event, json, onDrop);
126
- }
127
-
128
- /**
129
- * Move a tab/tabset using drag and drop, must be called from within an HTML
130
- * drag start handler
131
- * @param event the drag start event
132
- * @param node the tab or tabset to drag
133
- */
134
- moveTabWithDragAndDrop(event: DragEvent, node: (TabNode | TabSetNode)) {
135
- this.selfRef.current!.moveTabWithDragAndDrop(event, node);
136
- }
137
-
138
- /**
139
- * Adds a new tab to the active tabset (if there is one)
140
- * @param json the json for the new tab node
141
- * @returns the added tab node or undefined
142
- */
143
- addTabToActiveTabSet(json: IJsonTabNode): TabNode | undefined {
144
- return this.selfRef.current!.addTabToActiveTabSet(json);
145
- }
146
-
147
- /**
148
- * Sets the drag image from a react component for a drag event
149
- * @param event the drag event
150
- * @param component the react component to be used for the drag image
151
- * @param x the x position of the drag cursor on the image
152
- * @param y the x position of the drag cursor on the image
153
- */
154
- setDragComponent(event: DragEvent, component: React.ReactNode, x: number, y: number) {
155
- this.selfRef.current!.setDragComponent(event, component, x, y);
156
- }
157
-
158
- /** Get the root div element of the layout */
159
- getRootDiv() {
160
- return this.selfRef.current!.getRootDiv();
161
- }
162
-
163
- /** @internal */
164
- render() {
165
- return (<LayoutInternal ref={this.selfRef} {...this.props} renderRevision={this.revision++} />)
166
- }
167
- }
168
-
169
- /** @internal */
170
- interface ILayoutInternalProps extends ILayoutProps {
171
- renderRevision: number;
172
-
173
- // used only for popout windows:
174
- windowId?: string;
175
- mainLayout?: LayoutInternal;
176
- }
177
-
178
- /** @internal */
179
- interface ILayoutInternalState {
180
- rect: Rect;
181
- editingTab?: TabNode;
182
- portal?: React.ReactPortal;
183
- showEdges: boolean;
184
- showOverlay: boolean;
185
- calculatedBorderBarSize: number;
186
- layoutRevision: number;
187
- forceRevision: number;
188
- showHiddenBorder: DockLocation;
189
- }
190
-
191
- /** @internal */
192
- export class LayoutInternal extends React.Component<ILayoutInternalProps, ILayoutInternalState> {
193
- public static dragState: DragState | undefined = undefined;
194
-
195
- private selfRef: React.RefObject<HTMLDivElement | null>;
196
- private moveablesRef: React.RefObject<HTMLDivElement | null>;
197
- private findBorderBarSizeRef: React.RefObject<HTMLDivElement | null>;
198
- private mainRef: React.RefObject<HTMLDivElement | null>;
199
- private previousModel?: Model;
200
- private orderedTabIds: string[];
201
- private orderedTabMoveableIds: string[];
202
- private moveableElementMap = new Map<string, HTMLElement>();
203
- private dropInfo: DropInfo | undefined;
204
- private outlineDiv?: HTMLElement;
205
- private currentDocument?: Document;
206
- private currentWindow?: Window;
207
- private supportsPopout: boolean;
208
- private popoutURL: string;
209
- private icons: IIcons;
210
- private resizeObserver?: ResizeObserver;
211
-
212
- private dragEnterCount: number = 0;
213
- private dragging: boolean = false;
214
- private windowId: string;
215
- private layoutWindow: LayoutWindow;
216
- private mainLayout: LayoutInternal;
217
- private isMainWindow: boolean;
218
- private isDraggingOverWindow: boolean;
219
- private styleObserver: MutationObserver | undefined;
220
- private popoutWindowName: string;
221
- // private renderCount: any;
222
-
223
- constructor(props: ILayoutInternalProps) {
224
- super(props);
225
-
226
- this.orderedTabIds = [];
227
- this.orderedTabMoveableIds = [];
228
- this.selfRef = React.createRef<HTMLDivElement>();
229
- this.moveablesRef = React.createRef<HTMLDivElement>();
230
- this.mainRef = React.createRef<HTMLDivElement>();
231
- this.findBorderBarSizeRef = React.createRef<HTMLDivElement>();
232
-
233
- this.supportsPopout = props.supportsPopout !== undefined ? props.supportsPopout : defaultSupportsPopout;
234
- this.popoutURL = props.popoutURL ? props.popoutURL : "popout.html";
235
- this.icons = { ...defaultIcons, ...props.icons };
236
- this.windowId = props.windowId ? props.windowId : Model.MAIN_WINDOW_ID;
237
- this.mainLayout = this.props.mainLayout ? this.props.mainLayout : this;
238
- this.isDraggingOverWindow = false;
239
- this.layoutWindow = this.props.model.getwindowsMap().get(this.windowId)!;
240
- this.layoutWindow.layout = this;
241
- this.popoutWindowName = this.props.popoutWindowName || "Popout Window";
242
- // this.renderCount = 0;
243
-
244
- this.state = {
245
- rect: Rect.empty(),
246
- editingTab: undefined,
247
- showEdges: false,
248
- showOverlay: false,
249
- calculatedBorderBarSize: 29,
250
- layoutRevision: 0,
251
- forceRevision: 0,
252
- showHiddenBorder: DockLocation.CENTER
253
- };
254
-
255
- this.isMainWindow = this.windowId === Model.MAIN_WINDOW_ID;
256
- }
257
-
258
- componentDidMount() {
259
- this.updateRect();
260
-
261
- this.currentDocument = (this.selfRef.current as HTMLElement).ownerDocument;
262
- this.currentWindow = this.currentDocument.defaultView!;
263
-
264
- this.layoutWindow.window = this.currentWindow;
265
- this.layoutWindow.toScreenRectFunction = (r) => this.getScreenRect(r);
266
-
267
- this.resizeObserver = new ResizeObserver(entries => {
268
- requestAnimationFrame(() => {
269
- this.updateRect();
270
- });
271
- });
272
- if (this.selfRef.current) {
273
- this.resizeObserver.observe(this.selfRef.current);
274
- }
275
-
276
- if (this.isMainWindow) {
277
- this.props.model.addChangeListener(this.onModelChange);
278
- this.updateLayoutMetrics();
279
- } else {
280
- // since resizeObserver doesn't always work as expected when observing element in another document
281
- this.currentWindow.addEventListener("resize", () => {
282
- this.updateRect();
283
- });
284
-
285
- const sourceElement = this.props.mainLayout!.getRootDiv()!;
286
- const targetElement = this.selfRef.current!;
287
-
288
- copyInlineStyles(sourceElement, targetElement);
289
-
290
- this.styleObserver = new MutationObserver(() => {
291
- const changed = copyInlineStyles(sourceElement, targetElement);
292
- if (changed) {
293
- this.redraw("mutation observer");
294
- }
295
- });
296
-
297
- // Observe changes to the source element's style attribute
298
- this.styleObserver.observe(sourceElement, { attributeFilter: ['style'] });
299
- }
300
-
301
- // allow tabs to overlay when hidden
302
- document.addEventListener('visibilitychange', () => {
303
- for (const [_, layoutWindow] of this.props.model.getwindowsMap()) {
304
- const layout = layoutWindow.layout;
305
- if (layout) {
306
- this.redraw("visibility change");
307
- }
308
- }
309
- });
310
- }
311
-
312
- componentDidUpdate() {
313
- this.currentDocument = (this.selfRef.current as HTMLElement).ownerDocument;
314
- this.currentWindow = this.currentDocument.defaultView!;
315
- if (this.isMainWindow) {
316
- if (this.props.model !== this.previousModel) {
317
- if (this.previousModel !== undefined) {
318
- this.previousModel.removeChangeListener(this.onModelChange); // stop listening to old model
319
- }
320
- this.props.model.getwindowsMap().get(this.windowId)!.layout = this;
321
- this.props.model.addChangeListener(this.onModelChange);
322
- this.layoutWindow = this.props.model.getwindowsMap().get(this.windowId)!;
323
- this.layoutWindow.layout = this;
324
- this.layoutWindow.toScreenRectFunction = (r) => this.getScreenRect(r);
325
- this.previousModel = this.props.model;
326
- this.tidyMoveablesMap();
327
- }
328
-
329
- this.updateLayoutMetrics();
330
- }
331
- }
332
-
333
- componentWillUnmount() {
334
- if (this.selfRef.current) {
335
- this.resizeObserver?.unobserve(this.selfRef.current);
336
- }
337
- this.styleObserver?.disconnect();
338
- }
339
-
340
- render() {
341
- // console.log("render", this.windowId, this.state.revision, this.renderCount++);
342
- // first render will be used to find the size (via selfRef)
343
- if (!this.selfRef.current) {
344
- return (
345
- <div ref={this.selfRef} className={this.getClassName(CLASSES.FLEXLAYOUT__LAYOUT)}>
346
- <div ref={this.moveablesRef} key="__moveables__" className={this.getClassName(CLASSES.FLEXLAYOUT__LAYOUT_MOVEABLES)}></div>
347
- {this.renderMetricsElements()}
348
- </div>
349
- );
350
- }
351
-
352
- const model = this.props.model;
353
- model.getRoot(this.windowId).calcMinMaxSize();
354
- model.getRoot(this.windowId).setPaths("");
355
- model.getBorderSet().setPaths();
356
-
357
- const inner = this.renderLayout();
358
- const outer = this.renderBorders(inner);
359
-
360
- const tabs = this.renderTabs();
361
- const reorderedTabs = this.reorderComponents(tabs, this.orderedTabIds);
362
-
363
- let floatingWindows = null;
364
- let reorderedTabMoveables = null;
365
- let tabStamps = null;
366
- let metricElements = null;
367
-
368
- if (this.isMainWindow) {
369
- floatingWindows = this.renderWindows();
370
- metricElements = this.renderMetricsElements();
371
- const tabMoveables = this.renderTabMoveables();
372
- reorderedTabMoveables = this.reorderComponents(tabMoveables, this.orderedTabMoveableIds);
373
- tabStamps = <div key="__tabStamps__" className={this.getClassName(CLASSES.FLEXLAYOUT__LAYOUT_TAB_STAMPS)}>
374
- {this.renderTabStamps()}
375
- </div>;
376
- }
377
-
378
- return (
379
- <div
380
- ref={this.selfRef}
381
- className={this.getClassName(CLASSES.FLEXLAYOUT__LAYOUT)}
382
- onDragEnter={this.onDragEnterRaw}
383
- onDragLeave={this.onDragLeaveRaw}
384
- onDragOver={this.onDragOver}
385
- onDrop={this.onDrop}
386
- >
387
- <div ref={this.moveablesRef} key="__moveables__" className={this.getClassName(CLASSES.FLEXLAYOUT__LAYOUT_MOVEABLES)}></div>
388
- {metricElements}
389
- <Overlay key="__overlay__" layout={this} show={this.state.showOverlay} />
390
- {outer}
391
- {reorderedTabs}
392
- {reorderedTabMoveables}
393
- {tabStamps}
394
- {this.state.portal}
395
- {floatingWindows}
396
- </div>
397
- );
398
- }
399
-
400
- renderBorders(
401
- inner: React.ReactNode
402
- ) {
403
- const classMain = this.getClassName(CLASSES.FLEXLAYOUT__LAYOUT_MAIN);
404
- const borders = this.props.model.getBorderSet().getBorderMap()
405
- if (this.isMainWindow && borders.size > 0) {
406
- inner = (
407
- <div className={classMain} ref={this.mainRef}>
408
- {inner}
409
- </div>);
410
- const borderSetComponents = new Map<DockLocation, React.ReactNode>();
411
- const borderSetContentComponents = new Map<DockLocation, React.ReactNode>();
412
- for (const [_, location] of DockLocation.values) {
413
- const border = borders.get(location);
414
- const showBorder = border && border.isShowing() && (
415
- !border.isAutoHide() ||
416
- (border.isAutoHide() && (border.getChildren().length > 0 || this.state.showHiddenBorder === location)));
417
- if (showBorder) {
418
- borderSetComponents.set(location, <BorderTabSet layout={this} border={border} size={this.state.calculatedBorderBarSize} />);
419
- borderSetContentComponents.set(location, <BorderTab layout={this} border={border} show={border.getSelected() !== -1} />);
420
- }
421
- }
422
-
423
- const classBorderOuter = this.getClassName(CLASSES.FLEXLAYOUT__LAYOUT_BORDER_CONTAINER);
424
- const classBorderInner = this.getClassName(CLASSES.FLEXLAYOUT__LAYOUT_BORDER_CONTAINER_INNER);
425
-
426
- if (this.props.model.getBorderSet().getLayoutHorizontal()) {
427
- const innerWithBorderTabs = (
428
- <div className={classBorderInner} style={{ flexDirection: "column" }}>
429
- {borderSetContentComponents.get(DockLocation.TOP)}
430
- <div className={classBorderInner} style={{ flexDirection: "row" }}>
431
- {borderSetContentComponents.get(DockLocation.LEFT)}
432
- {inner}
433
- {borderSetContentComponents.get(DockLocation.RIGHT)}
434
- </div>
435
- {borderSetContentComponents.get(DockLocation.BOTTOM)}
436
- </div>
437
- );
438
- return (
439
- <div className={classBorderOuter} style={{ flexDirection: "column" }}>
440
- {borderSetComponents.get(DockLocation.TOP)}
441
- <div className={classBorderInner} style={{ flexDirection: "row" }}>
442
- {borderSetComponents.get(DockLocation.LEFT)}
443
- {innerWithBorderTabs}
444
- {borderSetComponents.get(DockLocation.RIGHT)}
445
- </div>
446
- {borderSetComponents.get(DockLocation.BOTTOM)}
447
- </div>
448
- );
449
- } else {
450
- const innerWithBorderTabs = (
451
- <div className={classBorderInner} style={{ flexDirection: "row" }}>
452
- {borderSetContentComponents.get(DockLocation.LEFT)}
453
- <div className={classBorderInner} style={{ flexDirection: "column" }}>
454
- {borderSetContentComponents.get(DockLocation.TOP)}
455
- {inner}
456
- {borderSetContentComponents.get(DockLocation.BOTTOM)}
457
- </div>
458
- {borderSetContentComponents.get(DockLocation.RIGHT)}
459
- </div>
460
- );
461
-
462
- return (
463
- <div className={classBorderOuter} style={{ flexDirection: "row" }}>
464
- {borderSetComponents.get(DockLocation.LEFT)}
465
- <div className={classBorderInner} style={{ flexDirection: "column" }}>
466
- {borderSetComponents.get(DockLocation.TOP)}
467
- {innerWithBorderTabs}
468
- {borderSetComponents.get(DockLocation.BOTTOM)}
469
- </div>
470
- {borderSetComponents.get(DockLocation.RIGHT)}
471
- </div>
472
- );
473
- }
474
-
475
- } else { // no borders
476
- return (
477
- <div className={classMain} ref={this.mainRef} style={{ position: "absolute", top: 0, left: 0, bottom: 0, right: 0, display: "flex" }}>
478
- {inner}
479
- </div>
480
- );
481
- }
482
- }
483
-
484
- renderLayout() {
485
- return (
486
- <>
487
- <Row key="__row__" layout={this} node={this.props.model.getRoot(this.windowId)} />
488
- {this.renderEdgeIndicators()}
489
- </>
490
- );
491
- }
492
-
493
- renderEdgeIndicators() {
494
- const edges: React.ReactNode[] = [];
495
- const arrowIcon = this.icons.edgeArrow;
496
- if (this.state.showEdges) {
497
- const r = this.props.model.getRoot(this.windowId).getRect();
498
- const length = edgeRectLength;
499
- const width = edgeRectWidth;
500
- const offset = edgeRectLength / 2;
501
- const className = this.getClassName(CLASSES.FLEXLAYOUT__EDGE_RECT);
502
- const radius = 50;
503
- edges.push(<div key="North" style={{ top: 0, left: r.width / 2 - offset, width: length, height: width, borderBottomLeftRadius: radius, borderBottomRightRadius: radius }} className={className + " " + this.getClassName(CLASSES.FLEXLAYOUT__EDGE_RECT_TOP)}>
504
- <div style={{ transform: "rotate(180deg)" }}>
505
- {arrowIcon}
506
- </div>
507
- </div>);
508
- edges.push(<div key="West" style={{ top: r.height / 2 - offset, left: 0, width: width, height: length, borderTopRightRadius: radius, borderBottomRightRadius: radius }} className={className + " " + this.getClassName(CLASSES.FLEXLAYOUT__EDGE_RECT_LEFT)}>
509
- <div style={{ transform: "rotate(90deg)" }}>
510
- {arrowIcon}
511
- </div>
512
- </div>);
513
- edges.push(<div key="South" style={{ top: r.height - width, left: r.width / 2 - offset, width: length, height: width, borderTopLeftRadius: radius, borderTopRightRadius: radius }} className={className + " " + this.getClassName(CLASSES.FLEXLAYOUT__EDGE_RECT_BOTTOM)}>
514
- <div>
515
- {arrowIcon}
516
- </div>
517
- </div>);
518
- edges.push(<div key="East" style={{ top: r.height / 2 - offset, left: r.width - width, width: width, height: length, borderTopLeftRadius: radius, borderBottomLeftRadius: radius }} className={className + " " + this.getClassName(CLASSES.FLEXLAYOUT__EDGE_RECT_RIGHT)}>
519
- <div style={{ transform: "rotate(-90deg)" }}>
520
- {arrowIcon}
521
- </div>
522
- </div>);
523
- }
524
-
525
- return edges;
526
- }
527
-
528
- renderWindows() {
529
- const floatingWindows: React.ReactNode[] = [];
530
- if (this.supportsPopout) {
531
- const windows = this.props.model.getwindowsMap();
532
- let i = 1;
533
- for (const [windowId, layoutWindow] of windows) {
534
-
535
- if (windowId !== Model.MAIN_WINDOW_ID) {
536
- floatingWindows.push(
537
- <PopoutWindow
538
- key={windowId}
539
- layout={this}
540
- title={this.popoutWindowName + " " + i}
541
- layoutWindow={layoutWindow}
542
- url={this.popoutURL + "?id=" + windowId}
543
- onSetWindow={this.onSetWindow}
544
- onCloseWindow={this.onCloseWindow}
545
- >
546
- <div className={this.props.popoutClassName}>
547
- <LayoutInternal {...this.props} windowId={windowId} mainLayout={this} />
548
- </div>
549
- </PopoutWindow>
550
- );
551
- i++;
552
- }
553
- }
554
- }
555
- return floatingWindows;
556
- }
557
-
558
- renderTabMoveables() {
559
- // const tabMoveables: React.ReactNode[] = [];
560
- const tabMoveables = new Map<string, React.ReactNode>();
561
-
562
- this.props.model.visitNodes((node) => {
563
- if (node instanceof TabNode) {
564
- const child = node as TabNode;
565
- const element = this.getMoveableElement(child.getId());
566
- child.setMoveableElement(element);
567
- const selected = child.isSelected();
568
- const rect = (child.getParent() as BorderNode | TabSetNode).getContentRect();
569
-
570
- // only render first time if size >0
571
- const renderTab = child.isRendered() ||
572
- ((selected || !child.isEnableRenderOnDemand()) && (rect.width > 0 && rect.height > 0));
573
-
574
- if (renderTab) {
575
- // console.log("rendertab", child.getName(), this.props.renderRevision);
576
- const key = child.getId() + (child.isEnableWindowReMount() ? child.getWindowId() : "");
577
- tabMoveables.set(node.getId(), createPortal(
578
- <SizeTracker rect={rect} selected={child.isSelected()} forceRevision={this.state.forceRevision} tabsRevision={this.props.renderRevision} key={key}>
579
- <ErrorBoundary message={this.i18nName(I18nLabel.Error_rendering_component)}>
580
- {this.props.factory(child)}
581
- </ErrorBoundary>
582
- </SizeTracker>
583
- , element, key));
584
-
585
- child.setRendered(renderTab);
586
- }
587
- }
588
- });
589
-
590
- return tabMoveables;
591
- }
592
-
593
- renderTabStamps() {
594
- const tabStamps: React.ReactNode[] = [];
595
-
596
- this.props.model.visitNodes((node) => {
597
- if (node instanceof TabNode) {
598
- const child = node as TabNode;
599
-
600
- // what the tab should look like when dragged (since images need to have been loaded before drag image can be taken)
601
- tabStamps.push(<DragContainer key={child.getId()} layout={this} node={child} />)
602
- }
603
- });
604
-
605
- return tabStamps;
606
- }
607
-
608
- renderTabs() {
609
- const tabs = new Map<string, React.ReactNode>();
610
- this.props.model.visitWindowNodes(this.windowId, (node) => {
611
- if (node instanceof TabNode) {
612
- const child = node as TabNode;
613
- const selected = child.isSelected();
614
- const path = child.getPath();
615
-
616
- const renderTab = child.isRendered() || selected || !child.isEnableRenderOnDemand();
617
-
618
- if (renderTab) {
619
- // const rect = (child.getParent() as BorderNode | TabSetNode).getContentRect();
620
- // const key = child.getId();
621
-
622
- tabs.set(child.getId(), (
623
- // <SizeTracker rect={rect} forceRevision={this.state.forceRevision} key={key}>
624
- <Tab
625
- key={child.getId()}
626
- layout={this}
627
- path={path}
628
- node={child}
629
- selected={selected} />
630
- // </SizeTracker>
631
- ));
632
- }
633
- }
634
- });
635
- return tabs;
636
- }
637
-
638
- renderMetricsElements() {
639
- return (
640
- <div key="findBorderBarSize" ref={this.findBorderBarSizeRef} className={this.getClassName(CLASSES.FLEXLAYOUT__BORDER_SIZER)}>
641
- FindBorderBarSize
642
- </div>
643
- );
644
- }
645
-
646
- checkForBorderToShow(x: number, y: number) {
647
- const r = this.getBoundingClientRect(this.mainRef.current!);
648
- const c = r.getCenter();
649
- const margin = edgeRectWidth;
650
- const offset = edgeRectLength / 2;
651
-
652
- let overEdge = false;
653
- if (this.props.model.isEnableEdgeDock() && this.state.showHiddenBorder === DockLocation.CENTER) {
654
- if ((y > c.y - offset && y < c.y + offset) ||
655
- (x > c.x - offset && x < c.x + offset)) {
656
- overEdge = true;
657
- }
658
- }
659
-
660
- let location = DockLocation.CENTER;
661
- if (!overEdge) {
662
- if (x <= r.x + margin) {
663
- location = DockLocation.LEFT;
664
- } else if (x >= r.getRight() - margin) {
665
- location = DockLocation.RIGHT;
666
- } else if (y <= r.y + margin) {
667
- location = DockLocation.TOP;
668
- } else if (y >= r.getBottom() - margin) {
669
- location = DockLocation.BOTTOM;
670
- }
671
- }
672
-
673
- if (location !== this.state.showHiddenBorder) {
674
- this.setState({ showHiddenBorder: location });
675
- }
676
- }
677
-
678
- updateLayoutMetrics = () => {
679
- if (this.findBorderBarSizeRef.current) {
680
- const borderBarSize = this.findBorderBarSizeRef.current.getBoundingClientRect().height;
681
- if (borderBarSize !== this.state.calculatedBorderBarSize) {
682
- this.setState({ calculatedBorderBarSize: borderBarSize });
683
- }
684
- }
685
- };
686
-
687
- tidyMoveablesMap() {
688
- // console.log("tidyMoveablesMap");
689
- const tabs = new Map<string, TabNode>();
690
- this.props.model.visitNodes((node, _) => {
691
- if (node instanceof TabNode) {
692
- tabs.set(node.getId(), node);
693
- }
694
- });
695
-
696
- for (const [nodeId, element] of this.moveableElementMap) {
697
- if (!tabs.has(nodeId)) {
698
- // console.log("delete", nodeId);
699
- element.remove(); // remove from dom
700
- this.moveableElementMap.delete(nodeId); // remove map entry
701
- }
702
- }
703
- }
704
-
705
- reorderComponents(components: Map<string, React.ReactNode>, ids: string[]) {
706
- const nextIds: string[] = [];
707
- const nextIdsSet = new Set<string>();
708
-
709
- let reordered: React.ReactNode[] = [];
710
- // Keep any previous tabs in the same DOM order as before, removing any that have been deleted
711
- for (const id of ids) {
712
- if (components.get(id)) {
713
- nextIds.push(id);
714
- nextIdsSet.add(id);
715
- }
716
- }
717
- ids.splice(0, ids.length, ...nextIds);
718
-
719
- // Add tabs that have been added to the DOM
720
- for (const [id, _] of components) {
721
- if (!nextIdsSet.has(id)) {
722
- ids.push(id);
723
- }
724
- }
725
-
726
- reordered = ids.map((id) => {
727
- return components.get(id);
728
- });
729
-
730
- return reordered;
731
- }
732
-
733
- onModelChange = (action: Action) => {
734
- this.redrawInternal("model change");
735
- if (this.props.onModelChange) {
736
- this.props.onModelChange(this.props.model, action);
737
- }
738
- };
739
-
740
- redraw(type?: string) {
741
- // console.log("redraw", this.windowId, type);
742
- this.mainLayout.setState((state, props) => { return { forceRevision: state.forceRevision + 1 } });
743
- }
744
-
745
- redrawInternal(type: string) {
746
- // console.log("redrawInternal", this.windowId, type);
747
- this.mainLayout.setState((state, props) => { return { layoutRevision: state.layoutRevision + 1 } });
748
- }
749
-
750
- doAction(action: Action): Node | undefined {
751
- if (this.props.onAction !== undefined) {
752
- const outcome = this.props.onAction(action);
753
- if (outcome !== undefined) {
754
- return this.props.model.doAction(outcome);
755
- }
756
- return undefined;
757
- } else {
758
- return this.props.model.doAction(action);
759
- }
760
- }
761
-
762
- updateRect = () => {
763
- const rect = this.getDomRect()
764
- if (!rect.equals(this.state.rect) && rect.width !== 0 && rect.height !== 0) {
765
- // console.log("updateRect", rect.floor());
766
- this.setState({ rect });
767
- if (this.windowId !== Model.MAIN_WINDOW_ID) {
768
- this.redrawInternal("rect updated");
769
- }
770
- }
771
- };
772
-
773
- getBoundingClientRect(div: HTMLElement): Rect {
774
- const layoutRect = this.getDomRect();
775
- if (layoutRect) {
776
- return Rect.getBoundingClientRect(div).relativeTo(layoutRect);
777
- }
778
- return Rect.empty();
779
- }
780
-
781
- getMoveableContainer() {
782
- return this.moveablesRef.current;
783
- }
784
-
785
- getMoveableElement(id: string) {
786
- let moveableElement = this.moveableElementMap.get(id);
787
- if (moveableElement === undefined) {
788
- moveableElement = document.createElement("div");
789
- this.moveablesRef.current!.appendChild(moveableElement);
790
- moveableElement.className = CLASSES.FLEXLAYOUT__TAB_MOVEABLE;
791
- this.moveableElementMap.set(id, moveableElement);
792
- }
793
- return moveableElement;
794
- }
795
-
796
- getMainLayout() {
797
- return this.mainLayout;
798
- }
799
-
800
- getClassName = (defaultClassName: string) => {
801
- if (this.props.classNameMapper === undefined) {
802
- return defaultClassName;
803
- } else {
804
- return this.props.classNameMapper(defaultClassName);
805
- }
806
- };
807
-
808
- getCurrentDocument() {
809
- return this.currentDocument;
810
- }
811
-
812
- getDomRect() {
813
- if (this.selfRef.current) {
814
- return Rect.fromDomRect(this.selfRef.current.getBoundingClientRect());
815
- } else {
816
- return Rect.empty();
817
- }
818
- }
819
-
820
- getWindowId() {
821
- return this.windowId;
822
- }
823
-
824
- getRootDiv() {
825
- return this.selfRef.current;
826
- }
827
-
828
- getMainElement() {
829
- return this.mainRef.current;
830
- }
831
-
832
- getFactory() {
833
- return this.props.factory;
834
- }
835
-
836
- isSupportsPopout() {
837
- return this.supportsPopout;
838
- }
839
-
840
- isRealtimeResize() {
841
- return this.props.realtimeResize ?? false;
842
- }
843
-
844
- getPopoutURL() {
845
- return this.popoutURL;
846
- }
847
-
848
- setEditingTab(tabNode?: TabNode) {
849
- this.setState({ editingTab: tabNode });
850
- }
851
-
852
- getEditingTab() {
853
- return this.state.editingTab;
854
- }
855
-
856
- getModel() {
857
- return this.props.model;
858
- }
859
-
860
- onCloseWindow = (windowLayout: LayoutWindow) => {
861
- this.doAction(Actions.closeWindow(windowLayout.windowId));
862
- };
863
-
864
- onSetWindow = (windowLayout: LayoutWindow, window: Window) => {
865
- };
866
-
867
- getScreenRect(inRect: Rect) {
868
- const rect = inRect.clone();
869
- const layoutRect = this.getDomRect();
870
- // Note: outerHeight can be less than innerHeight when window is zoomed, so cannot use
871
- // const navHeight = Math.min(65, this.currentWindow!.outerHeight - this.currentWindow!.innerHeight);
872
- // const navWidth = Math.min(65, this.currentWindow!.outerWidth - this.currentWindow!.innerWidth);
873
- const navHeight = 60;
874
- const navWidth = 2;
875
- // console.log(rect.y, this.currentWindow!.screenX,layoutRect.y);
876
- rect.x = this.currentWindow!.screenX + this.currentWindow!.scrollX + navWidth / 2 + layoutRect.x + rect.x;
877
- rect.y = this.currentWindow!.screenY + this.currentWindow!.scrollY + (navHeight - navWidth / 2) + layoutRect.y + rect.y;
878
- rect.height += navHeight;
879
- rect.width += navWidth;
880
- return rect;
881
- }
882
-
883
- addTabToTabSet(tabsetId: string, json: IJsonTabNode): TabNode | undefined {
884
- const tabsetNode = this.props.model.getNodeById(tabsetId);
885
- if (tabsetNode !== undefined) {
886
- const node = this.doAction(Actions.addNode(json, tabsetId, DockLocation.CENTER, -1));
887
- return node as TabNode;
888
- }
889
- return undefined;
890
- }
891
-
892
- addTabToActiveTabSet(json: IJsonTabNode): TabNode | undefined {
893
- const tabsetNode = this.props.model.getActiveTabset(this.windowId);
894
- if (tabsetNode !== undefined) {
895
- const node = this.doAction(Actions.addNode(json, tabsetNode.getId(), DockLocation.CENTER, -1));
896
- return node as TabNode;
897
- }
898
- return undefined;
899
- }
900
-
901
- showControlInPortal = (control: React.ReactNode, element: HTMLElement) => {
902
- const portal = createPortal(control, element) as React.ReactPortal;
903
- this.setState({ portal });
904
- };
905
-
906
- hideControlInPortal = () => {
907
- this.setState({ portal: undefined });
908
- };
909
-
910
- getIcons = () => {
911
- return this.icons;
912
- };
913
-
914
- maximize(tabsetNode: TabSetNode) {
915
- this.doAction(Actions.maximizeToggle(tabsetNode.getId(), this.getWindowId()));
916
- }
917
-
918
- customizeTab(
919
- tabNode: TabNode,
920
- renderValues: ITabRenderValues,
921
- ) {
922
- if (this.props.onRenderTab) {
923
- this.props.onRenderTab(tabNode, renderValues);
924
- }
925
- }
926
-
927
- customizeTabSet(
928
- tabSetNode: TabSetNode | BorderNode,
929
- renderValues: ITabSetRenderValues,
930
- ) {
931
- if (this.props.onRenderTabSet) {
932
- this.props.onRenderTabSet(tabSetNode, renderValues);
933
- }
934
- }
935
-
936
- i18nName(id: I18nLabel, param?: string) {
937
- let message;
938
- if (this.props.i18nMapper) {
939
- message = this.props.i18nMapper(id, param);
940
- }
941
- if (message === undefined) {
942
- message = id + (param === undefined ? "" : param);
943
- }
944
- return message;
945
- }
946
-
947
- getShowOverflowMenu() {
948
- return this.props.onShowOverflowMenu;
949
- }
950
-
951
- getTabSetPlaceHolderCallback() {
952
- return this.props.onTabSetPlaceHolder;
953
- }
954
-
955
- showContextMenu(node: TabNode | TabSetNode | BorderNode, event: React.MouseEvent<HTMLElement, MouseEvent>) {
956
- if (this.props.onContextMenu) {
957
- this.props.onContextMenu(node, event);
958
- }
959
- }
960
-
961
- auxMouseClick(node: TabNode | TabSetNode | BorderNode, event: React.MouseEvent<HTMLElement, MouseEvent>) {
962
- if (this.props.onAuxMouseClick) {
963
- this.props.onAuxMouseClick(node, event);
964
- }
965
- }
966
-
967
- public showOverlay(show: boolean) {
968
- this.setState({ showOverlay: show });
969
- enablePointerOnIFrames(!show, this.currentDocument!);
970
- }
971
-
972
-
973
-
974
- // *************************** Start Drag Drop *************************************
975
-
976
- addTabWithDragAndDrop(event: DragEvent, json: IJsonTabNode, onDrop?: (node?: Node, event?: React.DragEvent<HTMLElement>) => void) {
977
- const tempNode = TabNode.fromJson(json, this.props.model, false);
978
- LayoutInternal.dragState = new DragState(this.mainLayout, DragSource.Add, tempNode, json, onDrop);
979
- }
980
-
981
- moveTabWithDragAndDrop(event: DragEvent, node: (TabNode | TabSetNode)) {
982
- this.setDragNode(event, node);
983
- }
984
-
985
- public setDragNode = (event: DragEvent, node: Node & IDraggable) => {
986
- LayoutInternal.dragState = new DragState(this.mainLayout, DragSource.Internal, node, undefined, undefined);
987
- // Note: can only set (very) limited types on android! so cannot set json
988
- // Note: must set text/plain for android to allow drag,
989
- // so just set a simple message indicating its a flexlayout drag (this is not used anywhere else)
990
- event.dataTransfer!.setData('text/plain', "--flexlayout--");
991
- event.dataTransfer!.effectAllowed = "copyMove";
992
- event.dataTransfer!.dropEffect = "move";
993
-
994
- this.dragEnterCount = 0;
995
-
996
- if (node instanceof TabSetNode) {
997
- let rendered = false;
998
- let content = this.i18nName(I18nLabel.Move_Tabset);
999
- if (node.getChildren().length > 0) {
1000
- content = this.i18nName(I18nLabel.Move_Tabs).replace("?", String(node.getChildren().length));
1001
- }
1002
- if (this.props.onRenderDragRect) {
1003
- const dragComponent = this.props.onRenderDragRect(content, node, undefined);
1004
- if (dragComponent) {
1005
- this.setDragComponent(event, dragComponent, 10, 10);
1006
- rendered = true;
1007
- }
1008
- }
1009
- if (!rendered) {
1010
- this.setDragComponent(event, content, 10, 10);
1011
- }
1012
- } else {
1013
- const element = event.target as HTMLElement;
1014
- const rect = element.getBoundingClientRect();
1015
- const offsetX = event.clientX - rect.left;
1016
- const offsetY = event.clientY - rect.top;
1017
- const parentNode = node?.getParent();
1018
- const isInVerticalBorder = parentNode instanceof BorderNode && (parentNode as BorderNode).getOrientation() === Orientation.HORZ;
1019
- const x = isInVerticalBorder ? 10 : offsetX;
1020
- const y = isInVerticalBorder ? 10 : offsetY;
1021
-
1022
- let rendered = false;
1023
- if (this.props.onRenderDragRect) {
1024
- const content = <TabButtonStamp key={node.getId()} layout={this} node={node as TabNode} />;
1025
- const dragComponent = this.props.onRenderDragRect(content, node, undefined);
1026
- if (dragComponent) {
1027
- this.setDragComponent(event, dragComponent, x, y);
1028
- rendered = true;
1029
- }
1030
- }
1031
- if (!rendered) {
1032
- if (isSafari()) { // safari doesnt render the offscreen tabstamps
1033
- this.setDragComponent(event, <TabButtonStamp node={node as TabNode} layout={this} />, x, y);
1034
- } else {
1035
- event.dataTransfer!.setDragImage((node as TabNode).getTabStamp()!, x, y);
1036
- }
1037
- }
1038
- }
1039
- };
1040
-
1041
-
1042
-
1043
- public setDragComponent(event: DragEvent, component: React.ReactNode, x: number, y: number) {
1044
- let dragElement = (
1045
- <div style={{ position: "unset" }}
1046
- className={this.getClassName(CLASSES.FLEXLAYOUT__LAYOUT) + " " + this.getClassName(CLASSES.FLEXLAYOUT__DRAG_RECT)}>
1047
- {component}
1048
- </div>
1049
- );
1050
-
1051
- const tempDiv = this.currentDocument!.createElement('div');
1052
- tempDiv.setAttribute("data-layout-path", "/drag-rectangle");
1053
- tempDiv.style.position = "absolute";
1054
- tempDiv.style.left = "-10000px";
1055
- tempDiv.style.top = "-10000px";
1056
- this.currentDocument!.body.appendChild(tempDiv);
1057
- createRoot(tempDiv).render(dragElement);
1058
-
1059
- event.dataTransfer!.setDragImage(tempDiv, x, y);
1060
- setTimeout(() => {
1061
- this.currentDocument!.body.removeChild(tempDiv!);
1062
- }, 0);
1063
- }
1064
-
1065
- setDraggingOverWindow(overWindow: boolean) {
1066
- // console.log("setDraggingOverWindow", overWindow);
1067
- if (this.isDraggingOverWindow !== overWindow) {
1068
- if (this.outlineDiv) {
1069
- this.outlineDiv!.style.visibility = overWindow ? "hidden" : "visible";
1070
- }
1071
-
1072
- if (overWindow) {
1073
- this.setState({ showEdges: false });
1074
- } else {
1075
- // add edge indicators
1076
- if (this.props.model.getMaximizedTabset(this.windowId) === undefined) {
1077
- this.setState({ showEdges: this.props.model.isEnableEdgeDock() });
1078
- }
1079
- }
1080
-
1081
- this.isDraggingOverWindow = overWindow;
1082
- }
1083
- }
1084
-
1085
- onDragEnterRaw = (event: React.DragEvent<HTMLElement>) => {
1086
- this.dragEnterCount++;
1087
- if (this.dragEnterCount === 1) {
1088
- this.onDragEnter(event);
1089
- }
1090
- }
1091
-
1092
- onDragLeaveRaw = (event: React.DragEvent<HTMLElement>) => {
1093
- this.dragEnterCount--;
1094
- if (this.dragEnterCount === 0) {
1095
- this.onDragLeave(event);
1096
- }
1097
- }
1098
-
1099
- clearDragMain() {
1100
- // console.log("clear drag main");
1101
- LayoutInternal.dragState = undefined;
1102
- if (this.windowId === Model.MAIN_WINDOW_ID) {
1103
- this.isDraggingOverWindow = false;
1104
- }
1105
- for (const [, layoutWindow] of this.props.model.getwindowsMap()) {
1106
- // console.log(layoutWindow);
1107
- layoutWindow.layout!.clearDragLocal();
1108
- }
1109
- }
1110
-
1111
- clearDragLocal() {
1112
- // console.log("clear drag local", this.windowId);
1113
- this.setState({ showEdges: false });
1114
- this.showOverlay(false);
1115
- this.dragEnterCount = 0;
1116
- this.dragging = false;
1117
- if (this.outlineDiv) {
1118
- this.selfRef.current!.removeChild(this.outlineDiv);
1119
- this.outlineDiv = undefined;
1120
- }
1121
- }
1122
-
1123
- onDragEnter = (event: React.DragEvent<HTMLElement>) => {
1124
- // console.log("onDragEnter", this.windowId, this.dragEnterCount);
1125
-
1126
- if (!LayoutInternal.dragState && this.props.onExternalDrag) { // not internal dragging
1127
- const externalDrag = this.props.onExternalDrag!(event);
1128
- if (externalDrag) {
1129
- const tempNode = TabNode.fromJson(externalDrag.json, this.props.model, false);
1130
- LayoutInternal.dragState = new DragState(this.mainLayout, DragSource.External, tempNode, externalDrag.json, externalDrag.onDrop);
1131
- }
1132
- }
1133
-
1134
- if (LayoutInternal.dragState) {
1135
- if (this.windowId !== Model.MAIN_WINDOW_ID && LayoutInternal.dragState.mainLayout === this.mainLayout) {
1136
- LayoutInternal.dragState.mainLayout.setDraggingOverWindow(true);
1137
- }
1138
-
1139
- if (LayoutInternal.dragState.mainLayout !== this.mainLayout) {
1140
- return; // drag not by this layout or its popouts
1141
- }
1142
-
1143
- event.preventDefault();
1144
-
1145
- this.dropInfo = undefined;
1146
- const rootdiv = this.selfRef.current;
1147
- this.outlineDiv = this.currentDocument!.createElement("div");
1148
- this.outlineDiv.className = this.getClassName(CLASSES.FLEXLAYOUT__OUTLINE_RECT);
1149
- this.outlineDiv.style.visibility = "hidden";
1150
- const speed = this.props.model.getAttribute("tabDragSpeed") as number;
1151
- this.outlineDiv.style.transition = `top ${speed}s, left ${speed}s, width ${speed}s, height ${speed}s`;
1152
-
1153
- rootdiv!.appendChild(this.outlineDiv);
1154
-
1155
- this.dragging = true;
1156
- this.showOverlay(true);
1157
- // add edge indicators
1158
- if (!this.isDraggingOverWindow && this.props.model.getMaximizedTabset(this.windowId) === undefined) {
1159
- this.setState({ showEdges: this.props.model.isEnableEdgeDock() });
1160
- }
1161
-
1162
- const clientRect = this.selfRef.current?.getBoundingClientRect()!;
1163
- const r = new Rect(
1164
- event.clientX - (clientRect.left),
1165
- event.clientY - (clientRect.top),
1166
- 1, 1
1167
- );
1168
- r.positionElement(this.outlineDiv);
1169
- }
1170
- }
1171
-
1172
- onDragOver = (event: React.DragEvent<HTMLElement>) => {
1173
- if (this.dragging && !this.isDraggingOverWindow) {
1174
- // console.log("onDragOver");
1175
-
1176
- event.preventDefault();
1177
- const clientRect = this.selfRef.current?.getBoundingClientRect();
1178
- const pos = {
1179
- x: event.clientX - (clientRect?.left ?? 0),
1180
- y: event.clientY - (clientRect?.top ?? 0),
1181
- };
1182
-
1183
- this.checkForBorderToShow(pos.x, pos.y);
1184
-
1185
- let dropInfo = this.props.model.findDropTargetNode(this.windowId, LayoutInternal.dragState!.dragNode!, pos.x, pos.y);
1186
- if (dropInfo) {
1187
- this.dropInfo = dropInfo;
1188
- if (this.outlineDiv) {
1189
- this.outlineDiv.className = this.getClassName(dropInfo.className);
1190
- dropInfo.rect.positionElement(this.outlineDiv);
1191
- this.outlineDiv.style.visibility = "visible";
1192
- }
1193
- }
1194
- }
1195
- }
1196
-
1197
- onDragLeave = (event: React.DragEvent<HTMLElement>) => {
1198
- // console.log("onDragLeave", this.windowId, this.dragging);
1199
- if (this.dragging) {
1200
- if (this.windowId !== Model.MAIN_WINDOW_ID) {
1201
- LayoutInternal.dragState!.mainLayout.setDraggingOverWindow(false);
1202
- }
1203
-
1204
- this.clearDragLocal();
1205
- }
1206
- }
1207
-
1208
- onDrop = (event: React.DragEvent<HTMLElement>) => {
1209
- // console.log("ondrop", this.windowId, this.dragging, Layout.dragState);
1210
-
1211
- if (this.dragging) {
1212
- event.preventDefault();
1213
-
1214
- const dragState = LayoutInternal.dragState!;
1215
- if (this.dropInfo) {
1216
- if (dragState.dragJson !== undefined) {
1217
- const newNode = this.doAction(Actions.addNode(dragState.dragJson, this.dropInfo.node.getId(), this.dropInfo.location, this.dropInfo.index));
1218
-
1219
- if (dragState.fnNewNodeDropped !== undefined) {
1220
- dragState.fnNewNodeDropped(newNode, event);
1221
- }
1222
- } else if (dragState.dragNode !== undefined) {
1223
- this.doAction(Actions.moveNode(dragState.dragNode.getId(), this.dropInfo.node.getId(), this.dropInfo.location, this.dropInfo.index));
1224
- }
1225
- }
1226
-
1227
- this.mainLayout.clearDragMain();
1228
- }
1229
- this.dragEnterCount = 0; // must set to zero here ref sublayouts
1230
- }
1231
-
1232
- // *************************** End Drag Drop *************************************
1233
- }
1234
-
1235
- export const FlexLayoutVersion = "0.8.12";
1236
-
1237
- export type DragRectRenderCallback = (
1238
- content: React.ReactNode | undefined,
1239
- node?: Node,
1240
- json?: IJsonTabNode
1241
- ) => React.ReactNode | undefined;
1242
-
1243
- export type NodeMouseEvent = (
1244
- node: TabNode | TabSetNode | BorderNode,
1245
- event: React.MouseEvent<HTMLElement, MouseEvent>
1246
- ) => void;
1247
-
1248
- export type ShowOverflowMenuCallback = (
1249
- node: TabSetNode | BorderNode,
1250
- mouseEvent: React.MouseEvent<HTMLElement, MouseEvent>,
1251
- items: { index: number; node: TabNode }[],
1252
- onSelect: (item: { index: number; node: TabNode }) => void,
1253
- ) => void;
1254
-
1255
- export type TabSetPlaceHolderCallback = (node: TabSetNode) => React.ReactNode;
1256
-
1257
- export interface ITabSetRenderValues {
1258
- /** components that will be added after the tabs */
1259
- stickyButtons: React.ReactNode[];
1260
- /** components that will be added at the end of the tabset */
1261
- buttons: React.ReactNode[];
1262
- /** position to insert overflow button within [...stickyButtons, ...buttons]
1263
- * if left undefined position will be after the sticky buttons (if any)
1264
- */
1265
- overflowPosition: number | undefined;
1266
- }
1267
-
1268
- export interface ITabRenderValues {
1269
- /** the icon or other leading component */
1270
- leading: React.ReactNode;
1271
- /** the main tab text/component */
1272
- content: React.ReactNode;
1273
- /** a set of react components to add to the tab after the content */
1274
- buttons: React.ReactNode[];
1275
- }
1276
-
1277
- export interface IIcons {
1278
- close?: (React.ReactNode | ((tabNode: TabNode) => React.ReactNode));
1279
- closeTabset?: (React.ReactNode | ((tabSetNode: TabSetNode) => React.ReactNode));
1280
- popout?: (React.ReactNode | ((tabNode: TabNode) => React.ReactNode));
1281
- maximize?: (React.ReactNode | ((tabSetNode: TabSetNode) => React.ReactNode));
1282
- restore?: (React.ReactNode | ((tabSetNode: TabSetNode) => React.ReactNode));
1283
- more?: (React.ReactNode | ((tabSetNode: (TabSetNode | BorderNode), hiddenTabs: { node: TabNode; index: number }[]) => React.ReactNode));
1284
- edgeArrow?: React.ReactNode;
1285
- activeTabset?: (React.ReactNode | ((tabSetNode: TabSetNode) => React.ReactNode));
1286
- }
1287
-
1288
- const defaultIcons = {
1289
- close: <CloseIcon />,
1290
- closeTabset: <CloseIcon />,
1291
- popout: <PopoutIcon />,
1292
- maximize: <MaximizeIcon />,
1293
- restore: <RestoreIcon />,
1294
- more: <OverflowIcon />,
1295
- edgeArrow: <EdgeIcon />,
1296
- activeTabset: <AsterickIcon />
1297
- };
1298
-
1299
- enum DragSource {
1300
- Internal = "internal",
1301
- External = "external",
1302
- Add = "add"
1303
- }
1304
-
1305
- /** @internal */
1306
- const defaultSupportsPopout: boolean = isDesktop();
1307
-
1308
- /** @internal */
1309
- const edgeRectLength = 100;
1310
- /** @internal */
1311
- const edgeRectWidth = 10;
1312
-
1313
- // global layout drag state
1314
- class DragState {
1315
- public readonly mainLayout: LayoutInternal;
1316
- public readonly dragSource: DragSource;
1317
- public readonly dragNode: Node & IDraggable | undefined;
1318
- public readonly dragJson: IJsonTabNode | undefined;
1319
- public readonly fnNewNodeDropped: ((node?: Node, event?: React.DragEvent<HTMLElement>) => void) | undefined;
1320
-
1321
- public constructor(
1322
- mainLayout: LayoutInternal,
1323
- dragSource: DragSource,
1324
- dragNode: Node & IDraggable | undefined,
1325
- dragJson: IJsonTabNode | undefined,
1326
- fnNewNodeDropped: ((node?: Node, event?: React.DragEvent<HTMLElement>) => void) | undefined
1327
- ) {
1328
- this.mainLayout = mainLayout;
1329
- this.dragSource = dragSource;
1330
- this.dragNode = dragNode;
1331
- this.dragJson = dragJson;
1332
- this.fnNewNodeDropped = fnNewNodeDropped;
1333
- }
1334
- }