flexlayout-react 0.7.9 → 0.7.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/ChangeLog.txt +13 -0
- package/README.md +14 -3
- package/declarations/Types.d.ts +4 -0
- package/declarations/model/IJsonModel.d.ts +3 -0
- package/declarations/model/Model.d.ts +7 -0
- package/declarations/view/Layout.d.ts +1 -0
- package/dist/flexlayout.js +7 -7
- package/dist/flexlayout_min.js +1 -1
- package/lib/Types.js +4 -0
- package/lib/Types.js.map +1 -1
- package/lib/model/Model.js +21 -3
- package/lib/model/Model.js.map +1 -1
- package/lib/view/BorderButton.js +10 -1
- package/lib/view/BorderButton.js.map +1 -1
- package/lib/view/BorderTabSet.js +16 -5
- package/lib/view/BorderTabSet.js.map +1 -1
- package/lib/view/Layout.js +4 -4
- package/lib/view/Layout.js.map +1 -1
- package/lib/view/TabSet.js +6 -4
- package/lib/view/TabSet.js.map +1 -1
- package/lib/view/Utils.js +10 -2
- package/lib/view/Utils.js.map +1 -1
- package/package.json +1 -1
- package/src/Types.ts +5 -0
- package/src/model/IJsonModel.ts +5 -0
- package/src/model/Model.ts +27 -4
- package/src/view/BorderButton.tsx +10 -1
- package/src/view/BorderTabSet.tsx +27 -7
- package/src/view/Layout.tsx +9 -6
- package/src/view/TabSet.tsx +9 -6
- package/src/view/Utils.tsx +10 -2
- package/style/light.css +544 -544
package/src/model/Model.ts
CHANGED
|
@@ -52,15 +52,16 @@ export class Model {
|
|
|
52
52
|
const attributeDefinitions = new AttributeDefinitions();
|
|
53
53
|
|
|
54
54
|
attributeDefinitions.add("legacyOverflowMenu", false).setType(Attribute.BOOLEAN);
|
|
55
|
-
|
|
56
|
-
// splitter
|
|
57
|
-
attributeDefinitions.add("splitterSize", -1).setType(Attribute.NUMBER);
|
|
58
|
-
attributeDefinitions.add("splitterExtra", 0).setType(Attribute.NUMBER);
|
|
59
55
|
attributeDefinitions.add("enableEdgeDock", true).setType(Attribute.BOOLEAN);
|
|
60
56
|
attributeDefinitions.add("rootOrientationVertical", false).setType(Attribute.BOOLEAN);
|
|
61
57
|
attributeDefinitions.add("marginInsets", { top: 0, right: 0, bottom: 0, left: 0 })
|
|
62
58
|
.setType("IInsets");
|
|
63
59
|
attributeDefinitions.add("enableUseVisibility", false).setType(Attribute.BOOLEAN);
|
|
60
|
+
attributeDefinitions.add("enableRotateBorderIcons", true).setType(Attribute.BOOLEAN);
|
|
61
|
+
|
|
62
|
+
// splitter
|
|
63
|
+
attributeDefinitions.add("splitterSize", -1).setType(Attribute.NUMBER);
|
|
64
|
+
attributeDefinitions.add("splitterExtra", 0).setType(Attribute.NUMBER);
|
|
64
65
|
|
|
65
66
|
// tab
|
|
66
67
|
attributeDefinitions.add("tabEnableClose", true).setType(Attribute.BOOLEAN);
|
|
@@ -207,6 +208,10 @@ export class Model {
|
|
|
207
208
|
return this._attributes.enableUseVisibility as boolean;
|
|
208
209
|
}
|
|
209
210
|
|
|
211
|
+
isEnableRotateBorderIcons() {
|
|
212
|
+
return this._attributes.enableRotateBorderIcons as boolean;
|
|
213
|
+
}
|
|
214
|
+
|
|
210
215
|
/**
|
|
211
216
|
* Gets the
|
|
212
217
|
* @returns {BorderSet|*}
|
|
@@ -247,6 +252,24 @@ export class Model {
|
|
|
247
252
|
return this._idMap[id];
|
|
248
253
|
}
|
|
249
254
|
|
|
255
|
+
/**
|
|
256
|
+
* Finds the first/top left tab set of the given node.
|
|
257
|
+
* @param node The top node you want to begin searching from, deafults to the root node
|
|
258
|
+
* @returns The first Tab Set
|
|
259
|
+
*/
|
|
260
|
+
getFirstTabSet(node = this._root as Node): Node
|
|
261
|
+
{
|
|
262
|
+
const child = node.getChildren()[0];
|
|
263
|
+
if (child instanceof TabSetNode)
|
|
264
|
+
{
|
|
265
|
+
return child;
|
|
266
|
+
}
|
|
267
|
+
else
|
|
268
|
+
{
|
|
269
|
+
return this.getFirstTabSet(child);
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
|
|
250
273
|
/**
|
|
251
274
|
* Update the node tree by performing the given action,
|
|
252
275
|
* Actions should be generated via static methods on the Actions class
|
|
@@ -137,7 +137,16 @@ export const BorderButton = (props: IBorderButtonProps) => {
|
|
|
137
137
|
classNames += " " + node.getClassName();
|
|
138
138
|
}
|
|
139
139
|
|
|
140
|
-
|
|
140
|
+
let iconAngle = 0;
|
|
141
|
+
if (node.getModel().isEnableRotateBorderIcons() === false) {
|
|
142
|
+
if (border === "left") {
|
|
143
|
+
iconAngle = 90;
|
|
144
|
+
} else if (border === "right") {
|
|
145
|
+
iconAngle = -90;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
const renderState = getRenderStateEx(layout, node, iconFactory, titleFactory, iconAngle);
|
|
141
150
|
|
|
142
151
|
let content = renderState.content ? (
|
|
143
152
|
<div className={cm(CLASSES.FLEXLAYOUT__BORDER_BUTTON_CONTENT)}>
|
|
@@ -3,7 +3,7 @@ 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, ITitleObject } from "./Layout";
|
|
6
|
+
import { IIcons, ILayoutCallbacks, ITabSetRenderValues, ITitleObject } from "./Layout";
|
|
7
7
|
import { showPopup } from "../PopupMenu";
|
|
8
8
|
import { Actions } from "../model/Actions";
|
|
9
9
|
import { I18nLabel } from "../I18nLabel";
|
|
@@ -30,7 +30,7 @@ export const BorderTabSet = (props: IBorderTabSetProps) => {
|
|
|
30
30
|
const overflowbuttonRef = React.useRef<HTMLButtonElement | null>(null);
|
|
31
31
|
const stickyButtonsRef = React.useRef<HTMLDivElement | null>(null);
|
|
32
32
|
|
|
33
|
-
const { selfRef, position, userControlledLeft, hiddenTabs, onMouseWheel } = useTabOverflow(border, Orientation.flip(border.getOrientation()), toolbarRef, stickyButtonsRef);
|
|
33
|
+
const { selfRef, position, userControlledLeft, hiddenTabs, onMouseWheel, tabsTruncated } = useTabOverflow(border, Orientation.flip(border.getOrientation()), toolbarRef, stickyButtonsRef);
|
|
34
34
|
|
|
35
35
|
const onAuxMouseClick = (event: React.MouseEvent<HTMLDivElement, MouseEvent>) => {
|
|
36
36
|
if (isAuxMouseEvent(event)) {
|
|
@@ -42,7 +42,7 @@ export const BorderTabSet = (props: IBorderTabSetProps) => {
|
|
|
42
42
|
layout.showContextMenu(border, event);
|
|
43
43
|
};
|
|
44
44
|
|
|
45
|
-
const onInterceptMouseDown = (event: React.MouseEvent
|
|
45
|
+
const onInterceptMouseDown = (event: React.MouseEvent | React.TouchEvent) => {
|
|
46
46
|
event.stopPropagation();
|
|
47
47
|
};
|
|
48
48
|
|
|
@@ -116,11 +116,31 @@ export const BorderTabSet = (props: IBorderTabSetProps) => {
|
|
|
116
116
|
|
|
117
117
|
// allow customization of tabset right/bottom buttons
|
|
118
118
|
let buttons: any[] = [];
|
|
119
|
-
|
|
119
|
+
let stickyButtons: any[] = [];
|
|
120
|
+
const renderState : ITabSetRenderValues= { headerContent: undefined, buttons, stickyButtons: stickyButtons, headerButtons: [], overflowPosition: undefined };
|
|
120
121
|
layout.customizeTabSet(border, renderState);
|
|
121
122
|
buttons = renderState.buttons;
|
|
123
|
+
|
|
124
|
+
if (renderState.overflowPosition === undefined) {
|
|
125
|
+
renderState.overflowPosition = stickyButtons.length;
|
|
126
|
+
}
|
|
122
127
|
|
|
123
|
-
|
|
128
|
+
if (stickyButtons.length > 0) {
|
|
129
|
+
if (tabsTruncated) {
|
|
130
|
+
buttons = [...stickyButtons, ...buttons];
|
|
131
|
+
} else {
|
|
132
|
+
tabs.push(<div
|
|
133
|
+
ref={stickyButtonsRef}
|
|
134
|
+
key="sticky_buttons_container"
|
|
135
|
+
onMouseDown={onInterceptMouseDown}
|
|
136
|
+
onTouchStart={onInterceptMouseDown}
|
|
137
|
+
onDragStart={(e) => { e.preventDefault() }}
|
|
138
|
+
className={cm(CLASSES.FLEXLAYOUT__TAB_TOOLBAR_STICKY_BUTTONS_CONTAINER)}
|
|
139
|
+
>
|
|
140
|
+
{stickyButtons}
|
|
141
|
+
</div>);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
124
144
|
|
|
125
145
|
if (hiddenTabs.length > 0) {
|
|
126
146
|
const overflowTitle = layout.i18nName(I18nLabel.Overflow_Menu_Tooltip);
|
|
@@ -133,7 +153,7 @@ export const BorderTabSet = (props: IBorderTabSetProps) => {
|
|
|
133
153
|
<div className={cm(CLASSES.FLEXLAYOUT__TAB_BUTTON_OVERFLOW_COUNT)}>{hiddenTabs.length}</div>
|
|
134
154
|
</>);
|
|
135
155
|
}
|
|
136
|
-
buttons.
|
|
156
|
+
buttons.splice(Math.min(renderState.overflowPosition, buttons.length), 0,
|
|
137
157
|
<button
|
|
138
158
|
key="overflowbutton"
|
|
139
159
|
ref={overflowbuttonRef}
|
|
@@ -167,7 +187,7 @@ export const BorderTabSet = (props: IBorderTabSetProps) => {
|
|
|
167
187
|
);
|
|
168
188
|
}
|
|
169
189
|
}
|
|
170
|
-
toolbar = (
|
|
190
|
+
const toolbar = (
|
|
171
191
|
<div key="toolbar" ref={toolbarRef} className={cm(CLASSES.FLEXLAYOUT__BORDER_TOOLBAR) + " " + cm(CLASSES.FLEXLAYOUT__BORDER_TOOLBAR_ + border.getLocation().getName())}>
|
|
172
192
|
{buttons}
|
|
173
193
|
</div>
|
package/src/view/Layout.tsx
CHANGED
|
@@ -101,6 +101,9 @@ export interface ITabSetRenderValues {
|
|
|
101
101
|
stickyButtons: React.ReactNode[];
|
|
102
102
|
buttons: React.ReactNode[];
|
|
103
103
|
headerButtons: React.ReactNode[];
|
|
104
|
+
// position to insert overflow button within [...stickyButtons, ...buttons]
|
|
105
|
+
// if left undefined position will be after the sticky buttons (if any)
|
|
106
|
+
overflowPosition: number | undefined;
|
|
104
107
|
}
|
|
105
108
|
|
|
106
109
|
export interface ITabRenderValues {
|
|
@@ -510,10 +513,10 @@ export class Layout extends React.Component<ILayoutProps, ILayoutState> {
|
|
|
510
513
|
const offset = this.edgeRectLength / 2;
|
|
511
514
|
const className = this.getClassName(CLASSES.FLEXLAYOUT__EDGE_RECT);
|
|
512
515
|
const radius = 50;
|
|
513
|
-
edges.push(<div key="North" style={{ top: r.y, left: r.x + r.width / 2 - offset, width: length, height: width, borderBottomLeftRadius: radius, borderBottomRightRadius: radius }} className={className}></div>)
|
|
514
|
-
edges.push(<div key="West" style={{ top: r.y + r.height / 2 - offset, left: r.x, width: width, height: length, borderTopRightRadius: radius, borderBottomRightRadius: radius }} className={className}></div>)
|
|
515
|
-
edges.push(<div key="South" style={{ top: r.y + r.height - width, left: r.x + r.width / 2 - offset, width: length, height: width, borderTopLeftRadius: radius, borderTopRightRadius: radius }} className={className}></div>)
|
|
516
|
-
edges.push(<div key="East" style={{ top: r.y + r.height / 2 - offset, left: r.x + r.width - width, width: width, height: length, borderTopLeftRadius: radius, borderBottomLeftRadius: radius }} className={className}></div>)
|
|
516
|
+
edges.push(<div key="North" style={{ top: r.y, left: r.x + r.width / 2 - offset, width: length, height: width, borderBottomLeftRadius: radius, borderBottomRightRadius: radius }} className={className + " " + this.getClassName(CLASSES.FLEXLAYOUT__EDGE_RECT_TOP)}></div>);
|
|
517
|
+
edges.push(<div key="West" style={{ top: r.y + r.height / 2 - offset, left: r.x, width: width, height: length, borderTopRightRadius: radius, borderBottomRightRadius: radius }} className={className + " " + this.getClassName(CLASSES.FLEXLAYOUT__EDGE_RECT_LEFT)}></div>);
|
|
518
|
+
edges.push(<div key="South" style={{ top: r.y + r.height - width, left: r.x + r.width / 2 - offset, width: length, height: width, borderTopLeftRadius: radius, borderTopRightRadius: radius }} className={className + " " + this.getClassName(CLASSES.FLEXLAYOUT__EDGE_RECT_BOTTOM)}></div>);
|
|
519
|
+
edges.push(<div key="East" style={{ top: r.y + r.height / 2 - offset, left: r.x + r.width - width, width: width, height: length, borderTopLeftRadius: radius, borderBottomLeftRadius: radius }} className={className + " " + this.getClassName(CLASSES.FLEXLAYOUT__EDGE_RECT_RIGHT)}></div>);
|
|
517
520
|
}
|
|
518
521
|
|
|
519
522
|
// this.layoutTime = (Date.now() - this.start);
|
|
@@ -596,8 +599,8 @@ export class Layout extends React.Component<ILayoutProps, ILayoutState> {
|
|
|
596
599
|
if (this.supportsPopout && child.isFloating()) {
|
|
597
600
|
const rect = this._getScreenRect(child);
|
|
598
601
|
|
|
599
|
-
const tabBorderWidth= child._getAttr("borderWidth");
|
|
600
|
-
const tabBorderHeight= child._getAttr("borderHeight");
|
|
602
|
+
const tabBorderWidth = child._getAttr("borderWidth");
|
|
603
|
+
const tabBorderHeight = child._getAttr("borderHeight");
|
|
601
604
|
if (tabBorderWidth !== -1 && border.getLocation().getOrientation() === Orientation.HORZ) {
|
|
602
605
|
rect.width = tabBorderWidth;
|
|
603
606
|
} else if (tabBorderHeight !== -1 && border.getLocation().getOrientation() === Orientation.VERT) {
|
package/src/view/TabSet.tsx
CHANGED
|
@@ -4,7 +4,7 @@ import { Actions } from "../model/Actions";
|
|
|
4
4
|
import { TabNode } from "../model/TabNode";
|
|
5
5
|
import { TabSetNode } from "../model/TabSetNode";
|
|
6
6
|
import { showPopup } from "../PopupMenu";
|
|
7
|
-
import { IIcons, ILayoutCallbacks, ITitleObject } from "./Layout";
|
|
7
|
+
import { IIcons, ILayoutCallbacks, ITabSetRenderValues, ITitleObject } from "./Layout";
|
|
8
8
|
import { TabButton } from "./TabButton";
|
|
9
9
|
import { useTabOverflow } from "./TabOverflowHook";
|
|
10
10
|
import { Orientation } from "../Orientation";
|
|
@@ -160,13 +160,17 @@ export const TabSet = (props: ITabSetProps) => {
|
|
|
160
160
|
let headerButtons: React.ReactNode[] = [];
|
|
161
161
|
|
|
162
162
|
// allow customization of header contents and buttons
|
|
163
|
-
const renderState = { headerContent: node.getName(), stickyButtons, buttons, headerButtons };
|
|
163
|
+
const renderState : ITabSetRenderValues = { headerContent: node.getName(), stickyButtons, buttons, headerButtons, overflowPosition: undefined };
|
|
164
164
|
layout.customizeTabSet(node, renderState);
|
|
165
165
|
const headerContent = renderState.headerContent;
|
|
166
166
|
stickyButtons = renderState.stickyButtons;
|
|
167
167
|
buttons = renderState.buttons;
|
|
168
168
|
headerButtons = renderState.headerButtons;
|
|
169
169
|
|
|
170
|
+
if (renderState.overflowPosition === undefined) {
|
|
171
|
+
renderState.overflowPosition = stickyButtons.length;
|
|
172
|
+
}
|
|
173
|
+
|
|
170
174
|
if (stickyButtons.length > 0) {
|
|
171
175
|
if (tabsTruncated) {
|
|
172
176
|
buttons = [...stickyButtons, ...buttons];
|
|
@@ -183,8 +187,7 @@ export const TabSet = (props: ITabSetProps) => {
|
|
|
183
187
|
</div>);
|
|
184
188
|
}
|
|
185
189
|
}
|
|
186
|
-
|
|
187
|
-
let toolbar;
|
|
190
|
+
|
|
188
191
|
if (hiddenTabs.length > 0) {
|
|
189
192
|
const overflowTitle = layout.i18nName(I18nLabel.Overflow_Menu_Tooltip);
|
|
190
193
|
let overflowContent;
|
|
@@ -196,7 +199,7 @@ export const TabSet = (props: ITabSetProps) => {
|
|
|
196
199
|
<div className={cm(CLASSES.FLEXLAYOUT__TAB_BUTTON_OVERFLOW_COUNT)}>{hiddenTabs.length}</div>
|
|
197
200
|
</>);
|
|
198
201
|
}
|
|
199
|
-
buttons.
|
|
202
|
+
buttons.splice(Math.min(renderState.overflowPosition, buttons.length), 0,
|
|
200
203
|
<button
|
|
201
204
|
key="overflowbutton"
|
|
202
205
|
data-layout-path={path + "/button/overflow"}
|
|
@@ -268,7 +271,7 @@ export const TabSet = (props: ITabSetProps) => {
|
|
|
268
271
|
);
|
|
269
272
|
}
|
|
270
273
|
|
|
271
|
-
toolbar = (
|
|
274
|
+
const toolbar = (
|
|
272
275
|
<div key="toolbar" ref={toolbarRef}
|
|
273
276
|
className={cm(CLASSES.FLEXLAYOUT__TAB_TOOLBAR)}
|
|
274
277
|
onMouseDown={onInterceptMouseDown}
|
package/src/view/Utils.tsx
CHANGED
|
@@ -7,11 +7,15 @@ export function getRenderStateEx(
|
|
|
7
7
|
layout: ILayoutCallbacks,
|
|
8
8
|
node: TabNode,
|
|
9
9
|
iconFactory?: IconFactory,
|
|
10
|
-
titleFactory?: TitleFactory
|
|
10
|
+
titleFactory?: TitleFactory,
|
|
11
|
+
iconAngle?: number
|
|
11
12
|
) {
|
|
12
13
|
let leadingContent = iconFactory ? iconFactory(node) : undefined;
|
|
13
14
|
let titleContent: React.ReactNode = node.getName();
|
|
14
15
|
let name = node.getName();
|
|
16
|
+
if (iconAngle === undefined) {
|
|
17
|
+
iconAngle = 0;
|
|
18
|
+
}
|
|
15
19
|
|
|
16
20
|
function isTitleObject(obj: any): obj is ITitleObject {
|
|
17
21
|
return obj.titleContent !== undefined
|
|
@@ -33,7 +37,11 @@ export function getRenderStateEx(
|
|
|
33
37
|
}
|
|
34
38
|
|
|
35
39
|
if (leadingContent === undefined && node.getIcon() !== undefined) {
|
|
36
|
-
|
|
40
|
+
if (iconAngle !== 0) {
|
|
41
|
+
leadingContent = <img style={{ width: "1em", height: "1em", transform: "rotate(" + iconAngle + "deg)" }} src={node.getIcon()} alt="leadingContent" />;
|
|
42
|
+
} else {
|
|
43
|
+
leadingContent = <img style={{ width: "1em", height: "1em" }} src={node.getIcon()} alt="leadingContent" />;
|
|
44
|
+
}
|
|
37
45
|
}
|
|
38
46
|
|
|
39
47
|
let buttons: any[] = [];
|