flexlayout-react 0.5.21 → 0.6.0
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 +11 -0
- package/README.md +7 -5
- package/declarations/Types.d.ts +1 -0
- package/declarations/model/IJsonModel.d.ts +2 -0
- package/declarations/model/Model.d.ts +1 -0
- package/declarations/view/Icons.d.ts +6 -0
- package/declarations/view/Layout.d.ts +3 -4
- package/declarations/view/MenuTabButton.d.ts +1 -0
- package/declarations/view/Tab.d.ts +1 -1
- package/declarations/view/TabButtonStamp.d.ts +1 -0
- package/declarations/view/Utils.d.ts +1 -0
- package/dist/flexlayout.js +48 -12
- package/dist/flexlayout_min.js +1 -1
- package/lib/PopupMenu.js +9 -4
- package/lib/PopupMenu.js.map +1 -1
- package/lib/Types.js +1 -0
- package/lib/Types.js.map +1 -1
- package/lib/model/Model.js +4 -0
- package/lib/model/Model.js.map +1 -1
- package/lib/model/TabNode.js +6 -1
- package/lib/model/TabNode.js.map +1 -1
- package/lib/view/BorderButton.js +9 -39
- package/lib/view/BorderButton.js.map +1 -1
- package/lib/view/BorderTabSet.js +4 -4
- package/lib/view/BorderTabSet.js.map +1 -1
- package/lib/view/Icons.js +36 -0
- package/lib/view/Icons.js.map +1 -0
- package/lib/view/Layout.js +41 -11
- package/lib/view/Layout.js.map +1 -1
- package/lib/view/MenuTabButton.js +22 -0
- package/lib/view/MenuTabButton.js.map +1 -0
- package/lib/view/Tab.js +4 -12
- package/lib/view/Tab.js.map +1 -1
- package/lib/view/TabButton.js +11 -42
- package/lib/view/TabButton.js.map +1 -1
- package/lib/view/TabButtonStamp.js +22 -0
- package/lib/view/TabButtonStamp.js.map +1 -0
- package/lib/view/TabFloating.js +2 -2
- package/lib/view/TabFloating.js.map +1 -1
- package/lib/view/TabOverflowHook.js +1 -1
- package/lib/view/TabSet.js +7 -18
- package/lib/view/TabSet.js.map +1 -1
- package/lib/view/Utils.js +61 -0
- package/lib/view/Utils.js.map +1 -0
- package/package.json +1 -1
- package/src/I18nLabel.ts +1 -1
- package/src/PopupMenu.tsx +23 -5
- package/src/Types.ts +1 -0
- package/src/model/IJsonModel.ts +2 -0
- package/src/model/Model.ts +7 -0
- package/src/model/TabNode.ts +6 -1
- package/src/view/BorderButton.tsx +8 -41
- package/src/view/BorderTabSet.tsx +10 -3
- package/src/view/Icons.tsx +36 -0
- package/src/view/Layout.tsx +42 -18
- package/src/view/Tab.tsx +2 -7
- package/src/view/TabButton.tsx +15 -48
- package/src/view/TabButtonStamp.tsx +47 -0
- package/src/view/TabFloating.tsx +1 -1
- package/src/view/TabOverflowHook.tsx +1 -1
- package/src/view/TabSet.tsx +10 -13
- package/src/view/Utils.tsx +71 -0
- package/style/_base.scss +75 -45
- package/style/dark.css +75 -69
- package/style/dark.css.map +1 -1
- package/style/dark.scss +15 -5
- package/style/gray.css +72 -66
- package/style/gray.css.map +1 -1
- package/style/gray.scss +10 -3
- package/style/light.css +76 -70
- package/style/light.css.map +1 -1
- package/style/light.scss +16 -6
- package/images/close.png +0 -0
- package/images/maximize.png +0 -0
- package/images/more.png +0 -0
- package/images/more2.png +0 -0
- package/images/popout.png +0 -0
- package/images/restore.png +0 -0
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.isAuxMouseEvent = exports.hideElement = exports.getRenderStateEx = void 0;
|
|
4
|
+
var React = require("react");
|
|
5
|
+
/** @hidden @internal */
|
|
6
|
+
function getRenderStateEx(layout, node, iconFactory, titleFactory) {
|
|
7
|
+
var leadingContent = iconFactory ? iconFactory(node) : undefined;
|
|
8
|
+
var titleContent = node.getName();
|
|
9
|
+
var name = node.getName();
|
|
10
|
+
function isTitleObject(obj) {
|
|
11
|
+
return obj.titleContent !== undefined;
|
|
12
|
+
}
|
|
13
|
+
if (titleFactory !== undefined) {
|
|
14
|
+
var titleObj = titleFactory(node);
|
|
15
|
+
if (titleObj !== undefined) {
|
|
16
|
+
if (typeof titleObj === "string") {
|
|
17
|
+
titleContent = titleObj;
|
|
18
|
+
name = titleObj;
|
|
19
|
+
}
|
|
20
|
+
else if (isTitleObject(titleObj)) {
|
|
21
|
+
titleContent = titleObj.titleContent;
|
|
22
|
+
name = titleObj.name;
|
|
23
|
+
}
|
|
24
|
+
else {
|
|
25
|
+
titleContent = titleObj;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
if (leadingContent === undefined && node.getIcon() !== undefined) {
|
|
30
|
+
leadingContent = React.createElement("img", { style: { width: "1em", height: "1em" }, src: node.getIcon(), alt: "leadingContent" });
|
|
31
|
+
}
|
|
32
|
+
var buttons = [];
|
|
33
|
+
// allow customization of leading contents (icon) and contents
|
|
34
|
+
var renderState = { leading: leadingContent, content: titleContent, name: name, buttons: buttons };
|
|
35
|
+
layout.customizeTab(node, renderState);
|
|
36
|
+
node._setRenderedName(renderState.name);
|
|
37
|
+
return renderState;
|
|
38
|
+
}
|
|
39
|
+
exports.getRenderStateEx = getRenderStateEx;
|
|
40
|
+
/** @hidden @internal */
|
|
41
|
+
function hideElement(style, useVisibility) {
|
|
42
|
+
if (useVisibility) {
|
|
43
|
+
style.visibility = "hidden";
|
|
44
|
+
}
|
|
45
|
+
else {
|
|
46
|
+
style.display = "none";
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
exports.hideElement = hideElement;
|
|
50
|
+
/** @hidden @internal */
|
|
51
|
+
function isAuxMouseEvent(event) {
|
|
52
|
+
var auxEvent = false;
|
|
53
|
+
if (event.nativeEvent instanceof MouseEvent) {
|
|
54
|
+
if (event.nativeEvent.button !== 0 || event.ctrlKey || event.altKey || event.metaKey || event.shiftKey) {
|
|
55
|
+
auxEvent = true;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
return auxEvent;
|
|
59
|
+
}
|
|
60
|
+
exports.isAuxMouseEvent = isAuxMouseEvent;
|
|
61
|
+
//# sourceMappingURL=Utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Utils.js","sourceRoot":"","sources":["../../src/view/Utils.tsx"],"names":[],"mappings":";;;AAAA,6BAA+B;AAI/B,wBAAwB;AACxB,SAAgB,gBAAgB,CAC5B,MAAwB,EACxB,IAAa,EACb,WAA4D,EAC5D,YAA6D;IAE7D,IAAI,cAAc,GAAG,WAAW,CAAC,CAAC,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IACjE,IAAI,YAAY,GAAoB,IAAI,CAAC,OAAO,EAAE,CAAC;IACnD,IAAI,IAAI,GAAG,IAAI,CAAC,OAAO,EAAE,CAAC;IAE1B,SAAS,aAAa,CAAC,GAAQ;QAC3B,OAAO,GAAG,CAAC,YAAY,KAAK,SAAS,CAAA;IACzC,CAAC;IAED,IAAI,YAAY,KAAK,SAAS,EAAE;QAC5B,IAAM,QAAQ,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC;QACpC,IAAI,QAAQ,KAAK,SAAS,EAAE;YACxB,IAAI,OAAO,QAAQ,KAAK,QAAQ,EAAE;gBAC9B,YAAY,GAAG,QAAkB,CAAC;gBAClC,IAAI,GAAG,QAAkB,CAAC;aAC7B;iBAAM,IAAI,aAAa,CAAC,QAAQ,CAAC,EAAE;gBAChC,YAAY,GAAG,QAAQ,CAAC,YAAY,CAAC;gBACrC,IAAI,GAAG,QAAQ,CAAC,IAAI,CAAC;aACxB;iBAAM;gBACH,YAAY,GAAG,QAAQ,CAAC;aAC3B;SACJ;KACJ;IAED,IAAI,cAAc,KAAK,SAAS,IAAI,IAAI,CAAC,OAAO,EAAE,KAAK,SAAS,EAAE;QAC9D,cAAc,GAAG,6BAAK,KAAK,EAAE,EAAC,KAAK,EAAC,KAAK,EAAE,MAAM,EAAC,KAAK,EAAC,EAAE,GAAG,EAAE,IAAI,CAAC,OAAO,EAAE,EAAE,GAAG,EAAC,gBAAgB,GAAG,CAAC;KAC1G;IAED,IAAI,OAAO,GAAU,EAAE,CAAC;IAExB,8DAA8D;IAC9D,IAAM,WAAW,GAAG,EAAE,OAAO,EAAE,cAAc,EAAE,OAAO,EAAE,YAAY,EAAE,IAAI,MAAA,EAAE,OAAO,SAAA,EAAE,CAAC;IACtF,MAAM,CAAC,YAAY,CAAC,IAAI,EAAE,WAAW,CAAC,CAAC;IAEvC,IAAI,CAAC,gBAAgB,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;IAExC,OAAO,WAAW,CAAC;AAEvB,CAAC;AA3CD,4CA2CC;AAED,wBAAwB;AACxB,SAAgB,WAAW,CAAC,KAA0B,EAAE,aAA+B;IACnF,IAAI,aAAa,EAAE;QACf,KAAK,CAAC,UAAU,GAAG,QAAQ,CAAC;KAC/B;SAAM;QACH,KAAK,CAAC,OAAO,GAAG,MAAM,CAAC;KAC1B;AACL,CAAC;AAND,kCAMC;AAGD,wBAAwB;AACxB,SAAgB,eAAe,CAAC,KAAsF;IAClH,IAAI,QAAQ,GAAG,KAAK,CAAC;IACrB,IAAI,KAAK,CAAC,WAAW,YAAY,UAAU,EAAE;QACzC,IAAI,KAAK,CAAC,WAAW,CAAC,MAAM,KAAK,CAAC,IAAI,KAAK,CAAC,OAAO,IAAI,KAAK,CAAC,MAAM,IAAI,KAAK,CAAC,OAAO,IAAI,KAAK,CAAC,QAAQ,EAAE;YACpG,QAAQ,GAAG,IAAI,CAAC;SACnB;KACJ;IACD,OAAO,QAAQ,CAAC;AACpB,CAAC;AARD,0CAQC"}
|
package/package.json
CHANGED
package/src/I18nLabel.ts
CHANGED
package/src/PopupMenu.tsx
CHANGED
|
@@ -3,15 +3,20 @@ import * as ReactDOM from "react-dom";
|
|
|
3
3
|
import { DragDrop } from ".";
|
|
4
4
|
import TabNode from "./model/TabNode";
|
|
5
5
|
import { CLASSES } from "./Types";
|
|
6
|
+
import { ILayoutCallbacks } from "./view/Layout";
|
|
7
|
+
import { TabButtonStamp } from "./view/TabButtonStamp";
|
|
6
8
|
|
|
7
9
|
/** @hidden @internal */
|
|
8
10
|
export function showPopup(
|
|
9
|
-
layoutDiv: HTMLDivElement,
|
|
10
11
|
triggerElement: Element,
|
|
11
12
|
items: { index: number; node: TabNode }[],
|
|
12
13
|
onSelect: (item: { index: number; node: TabNode }) => void,
|
|
13
|
-
|
|
14
|
+
layout: ILayoutCallbacks,
|
|
15
|
+
iconFactory?: (node: TabNode) => React.ReactNode | undefined,
|
|
16
|
+
titleFactory?: (node: TabNode) => React.ReactNode | undefined,
|
|
14
17
|
) {
|
|
18
|
+
const layoutDiv = layout.getRootDiv();
|
|
19
|
+
const classNameMapper = layout.getClassName;
|
|
15
20
|
const currentDocument = triggerElement.ownerDocument;
|
|
16
21
|
const triggerRect = triggerElement.getBoundingClientRect();
|
|
17
22
|
const layoutRect = layoutDiv.getBoundingClientRect();
|
|
@@ -59,6 +64,9 @@ export function showPopup(
|
|
|
59
64
|
onHide={onHide}
|
|
60
65
|
items={items}
|
|
61
66
|
classNameMapper={classNameMapper}
|
|
67
|
+
layout={layout}
|
|
68
|
+
iconFactory={iconFactory}
|
|
69
|
+
titleFactory={titleFactory}
|
|
62
70
|
/>, elm);
|
|
63
71
|
}
|
|
64
72
|
|
|
@@ -69,11 +77,14 @@ interface IPopupMenuProps {
|
|
|
69
77
|
onHide: () => void;
|
|
70
78
|
onSelect: (item: { index: number; node: TabNode }) => void;
|
|
71
79
|
classNameMapper: (defaultClassName: string) => string;
|
|
80
|
+
layout: ILayoutCallbacks;
|
|
81
|
+
iconFactory?: (node: TabNode) => React.ReactNode | undefined;
|
|
82
|
+
titleFactory?: (node: TabNode) => React.ReactNode | undefined;
|
|
72
83
|
}
|
|
73
84
|
|
|
74
85
|
/** @hidden @internal */
|
|
75
86
|
const PopupMenu = (props: IPopupMenuProps) => {
|
|
76
|
-
const { items, onHide, onSelect, classNameMapper } = props;
|
|
87
|
+
const { items, onHide, onSelect, classNameMapper, layout, iconFactory, titleFactory} = props;
|
|
77
88
|
|
|
78
89
|
const onItemClick = (item: { index: number; node: TabNode }, event: React.MouseEvent<HTMLDivElement, MouseEvent>) => {
|
|
79
90
|
onSelect(item);
|
|
@@ -86,8 +97,15 @@ const PopupMenu = (props: IPopupMenuProps) => {
|
|
|
86
97
|
className={classNameMapper(CLASSES.FLEXLAYOUT__POPUP_MENU_ITEM)}
|
|
87
98
|
data-layout-path={"/popup-menu/tb" + i}
|
|
88
99
|
onClick={(event) => onItemClick(item, event)}
|
|
89
|
-
title={item.node.getHelpText()}>
|
|
90
|
-
{item.node.
|
|
100
|
+
title={item.node.getHelpText()} >
|
|
101
|
+
{item.node.getModel().isLegacyOverflowMenu() ?
|
|
102
|
+
item.node._getNameForOverflowMenu() :
|
|
103
|
+
<TabButtonStamp
|
|
104
|
+
node={item.node}
|
|
105
|
+
layout={layout}
|
|
106
|
+
iconFactory={iconFactory}
|
|
107
|
+
titleFactory={titleFactory}
|
|
108
|
+
/>}
|
|
91
109
|
</div>
|
|
92
110
|
));
|
|
93
111
|
|
package/src/Types.ts
CHANGED
|
@@ -70,6 +70,7 @@ export enum CLASSES {
|
|
|
70
70
|
FLEXLAYOUT__TAB_BUTTON_OVERFLOW = "flexlayout__tab_button_overflow",
|
|
71
71
|
FLEXLAYOUT__TAB_BUTTON_TEXTBOX = "flexlayout__tab_button_textbox",
|
|
72
72
|
FLEXLAYOUT__TAB_BUTTON_TRAILING = "flexlayout__tab_button_trailing",
|
|
73
|
+
FLEXLAYOUT__TAB_BUTTON_STAMP = "flexlayout__tab_button_stamp",
|
|
73
74
|
|
|
74
75
|
FLEXLAYOUT__TAB_FLOATING = "flexlayout__tab_floating",
|
|
75
76
|
FLEXLAYOUT__TAB_FLOATING_INNER = "flexlayout__tab_floating_inner",
|
package/src/model/IJsonModel.ts
CHANGED
|
@@ -41,6 +41,7 @@ export interface IGlobalAttributes {
|
|
|
41
41
|
borderSize?: number; // default: 200
|
|
42
42
|
enableEdgeDock?: boolean; // default: true
|
|
43
43
|
enableUseVisibility?: boolean; // default: false
|
|
44
|
+
legacyOverflowMenu?: boolean; // default: false
|
|
44
45
|
marginInsets?: IInsets; // default: {"top":0,"right":0,"bottom":0,"left":0}
|
|
45
46
|
rootOrientationVertical?: boolean; // default: false
|
|
46
47
|
splitterExtra?: number; // default: 0
|
|
@@ -109,6 +110,7 @@ export interface ITabSetAttributes {
|
|
|
109
110
|
width?: number;
|
|
110
111
|
}
|
|
111
112
|
export interface ITabAttributes {
|
|
113
|
+
altName?: string;
|
|
112
114
|
borderHeight?: number; // default: -1 - inherited from global tabBorderHeight
|
|
113
115
|
borderWidth?: number; // default: -1 - inherited from global tabBorderWidth
|
|
114
116
|
className?: string; // - inherited from global tabClassName
|
package/src/model/Model.ts
CHANGED
|
@@ -52,6 +52,9 @@ class Model {
|
|
|
52
52
|
/** @hidden @internal */
|
|
53
53
|
private static _createAttributeDefinitions(): AttributeDefinitions {
|
|
54
54
|
const attributeDefinitions = new AttributeDefinitions();
|
|
55
|
+
|
|
56
|
+
attributeDefinitions.add("legacyOverflowMenu", false).setType(Attribute.BOOLEAN);
|
|
57
|
+
|
|
55
58
|
// splitter
|
|
56
59
|
attributeDefinitions.add("splitterSize", -1).setType(Attribute.NUMBER);
|
|
57
60
|
attributeDefinitions.add("splitterExtra", 0).setType(Attribute.NUMBER);
|
|
@@ -448,6 +451,10 @@ class Model {
|
|
|
448
451
|
return splitterSize;
|
|
449
452
|
}
|
|
450
453
|
|
|
454
|
+
isLegacyOverflowMenu() {
|
|
455
|
+
return this._attributes.legacyOverflowMenu as boolean;
|
|
456
|
+
}
|
|
457
|
+
|
|
451
458
|
getSplitterExtra() {
|
|
452
459
|
return this._attributes.splitterExtra as number;
|
|
453
460
|
}
|
package/src/model/TabNode.ts
CHANGED
|
@@ -26,6 +26,7 @@ class TabNode extends Node implements IDraggable {
|
|
|
26
26
|
attributeDefinitions.add("id", undefined).setType(Attribute.STRING);
|
|
27
27
|
|
|
28
28
|
attributeDefinitions.add("name", "[Unnamed Tab]").setType(Attribute.STRING);
|
|
29
|
+
attributeDefinitions.add("altName", undefined).setType(Attribute.STRING);
|
|
29
30
|
attributeDefinitions.add("helpText", undefined).setType(Attribute.STRING);
|
|
30
31
|
attributeDefinitions.add("component", undefined).setType(Attribute.STRING);
|
|
31
32
|
attributeDefinitions.add("config", undefined).setType("any");
|
|
@@ -84,7 +85,11 @@ class TabNode extends Node implements IDraggable {
|
|
|
84
85
|
}
|
|
85
86
|
|
|
86
87
|
/** @hidden @internal */
|
|
87
|
-
|
|
88
|
+
_getNameForOverflowMenu() {
|
|
89
|
+
const altName = this._getAttr("altName") as string;
|
|
90
|
+
if (altName !== undefined) {
|
|
91
|
+
return altName;
|
|
92
|
+
}
|
|
88
93
|
return this._renderedName;
|
|
89
94
|
}
|
|
90
95
|
|
|
@@ -3,10 +3,10 @@ import { I18nLabel } from "..";
|
|
|
3
3
|
import Actions from "../model/Actions";
|
|
4
4
|
import TabNode from "../model/TabNode";
|
|
5
5
|
import Rect from "../Rect";
|
|
6
|
-
import { IIcons, ILayoutCallbacks
|
|
6
|
+
import { IIcons, ILayoutCallbacks } from "./Layout";
|
|
7
7
|
import { ICloseType } from "../model/ICloseType";
|
|
8
8
|
import { CLASSES } from "../Types";
|
|
9
|
-
import { isAuxMouseEvent } from "./
|
|
9
|
+
import { getRenderStateEx, isAuxMouseEvent } from "./Utils";
|
|
10
10
|
|
|
11
11
|
/** @hidden @internal */
|
|
12
12
|
export interface IBorderButtonProps {
|
|
@@ -27,8 +27,7 @@ export const BorderButton = (props: IBorderButtonProps) => {
|
|
|
27
27
|
|
|
28
28
|
const onMouseDown = (event: React.MouseEvent<HTMLDivElement, MouseEvent> | React.TouchEvent<HTMLDivElement>) => {
|
|
29
29
|
if (!isAuxMouseEvent(event)) {
|
|
30
|
-
|
|
31
|
-
props.layout.dragStart(event, message, node, node.isEnableDrag(), onClick, (event2: Event) => undefined);
|
|
30
|
+
props.layout.dragStart(event, undefined, node, node.isEnableDrag(), onClick, (event2: Event) => undefined);
|
|
32
31
|
}
|
|
33
32
|
};
|
|
34
33
|
|
|
@@ -96,46 +95,14 @@ export const BorderButton = (props: IBorderButtonProps) => {
|
|
|
96
95
|
classNames += " " + node.getClassName();
|
|
97
96
|
}
|
|
98
97
|
|
|
99
|
-
|
|
100
|
-
let titleContent: React.ReactNode = node.getName();
|
|
101
|
-
let name = node.getName();
|
|
102
|
-
|
|
103
|
-
function isTitleObject(obj: any): obj is ITitleObject {
|
|
104
|
-
return obj.titleContent !== undefined
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
if (titleFactory !== undefined) {
|
|
108
|
-
const titleObj = titleFactory(node);
|
|
109
|
-
if (titleObj !== undefined) {
|
|
110
|
-
if (typeof titleObj === "string") {
|
|
111
|
-
titleContent = titleObj as string;
|
|
112
|
-
name = titleObj as string;
|
|
113
|
-
} else if (isTitleObject(titleObj)) {
|
|
114
|
-
titleContent = titleObj.titleContent;
|
|
115
|
-
name = titleObj.name;
|
|
116
|
-
} else {
|
|
117
|
-
titleContent = titleObj;
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
if (leadingContent === undefined && node.getIcon() !== undefined) {
|
|
123
|
-
leadingContent = <img src={node.getIcon()} alt="leadingContent" />;
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
let buttons: any[] = [];
|
|
127
|
-
|
|
128
|
-
// allow customization of leading contents (icon) and contents
|
|
129
|
-
const renderState = { leading: leadingContent, content: titleContent, name, buttons };
|
|
130
|
-
layout.customizeTab(node, renderState);
|
|
131
|
-
node._setRenderedName(renderState.name);
|
|
98
|
+
const renderState = getRenderStateEx(layout, node, iconFactory, titleFactory);
|
|
132
99
|
|
|
133
|
-
const content = <div className={cm(CLASSES.FLEXLAYOUT__BORDER_BUTTON_CONTENT)}>{renderState.content}</div
|
|
134
|
-
const leading = <div className={cm(CLASSES.FLEXLAYOUT__BORDER_BUTTON_LEADING)}>{renderState.leading}</div
|
|
100
|
+
const content = renderState.content ? (<div className={cm(CLASSES.FLEXLAYOUT__BORDER_BUTTON_CONTENT)}>{renderState.content}</div>) : null;
|
|
101
|
+
const leading = renderState.leading ? (<div className={cm(CLASSES.FLEXLAYOUT__BORDER_BUTTON_LEADING)}>{renderState.leading}</div>) : null;
|
|
135
102
|
|
|
136
103
|
if (node.isEnableClose()) {
|
|
137
104
|
const closeTitle = layout.i18nName(I18nLabel.Close_Tab);
|
|
138
|
-
buttons.push(
|
|
105
|
+
renderState.buttons.push(
|
|
139
106
|
<div
|
|
140
107
|
key="close"
|
|
141
108
|
data-layout-path={path + "/button/close"}
|
|
@@ -160,7 +127,7 @@ export const BorderButton = (props: IBorderButtonProps) => {
|
|
|
160
127
|
title={node.getHelpText()}>
|
|
161
128
|
{leading}
|
|
162
129
|
{content}
|
|
163
|
-
{buttons}
|
|
130
|
+
{renderState.buttons}
|
|
164
131
|
</div>
|
|
165
132
|
);
|
|
166
133
|
};
|
|
@@ -10,7 +10,7 @@ import { I18nLabel } from "../I18nLabel";
|
|
|
10
10
|
import { useTabOverflow } from "./TabOverflowHook";
|
|
11
11
|
import Orientation from "../Orientation";
|
|
12
12
|
import { CLASSES } from "../Types";
|
|
13
|
-
import { isAuxMouseEvent } from "./
|
|
13
|
+
import { isAuxMouseEvent } from "./Utils";
|
|
14
14
|
|
|
15
15
|
/** @hidden @internal */
|
|
16
16
|
export interface IBorderTabSetProps {
|
|
@@ -48,7 +48,12 @@ export const BorderTabSet = (props: IBorderTabSetProps) => {
|
|
|
48
48
|
|
|
49
49
|
const onOverflowClick = (event: React.MouseEvent<HTMLElement, MouseEvent>) => {
|
|
50
50
|
const element = overflowbuttonRef.current!;
|
|
51
|
-
showPopup(
|
|
51
|
+
showPopup( element,
|
|
52
|
+
hiddenTabs,
|
|
53
|
+
onOverflowItemSelect,
|
|
54
|
+
layout,
|
|
55
|
+
iconFactory,
|
|
56
|
+
titleFactory);
|
|
52
57
|
event.stopPropagation();
|
|
53
58
|
};
|
|
54
59
|
|
|
@@ -137,7 +142,9 @@ export const BorderTabSet = (props: IBorderTabSetProps) => {
|
|
|
137
142
|
onClick={onFloatTab}
|
|
138
143
|
onMouseDown={onInterceptMouseDown}
|
|
139
144
|
onTouchStart={onInterceptMouseDown}
|
|
140
|
-
|
|
145
|
+
>
|
|
146
|
+
{icons?.popout}
|
|
147
|
+
</button>
|
|
141
148
|
);
|
|
142
149
|
}
|
|
143
150
|
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
|
|
3
|
+
const style = {width:"1em", height:"1em", display: "flex", alignItems:"center"};
|
|
4
|
+
|
|
5
|
+
export const CloseIcon = () => {
|
|
6
|
+
return (
|
|
7
|
+
<svg xmlns="http://www.w3.org/2000/svg" style={style} viewBox="0 0 24 24" >
|
|
8
|
+
<path fill="none" d="M0 0h24v24H0z"/>
|
|
9
|
+
<path stroke="gray" fill="gray" d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z" />
|
|
10
|
+
</svg>
|
|
11
|
+
);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export const MaximizeIcon = () => {
|
|
15
|
+
return (
|
|
16
|
+
<svg xmlns="http://www.w3.org/2000/svg" style={style} viewBox="0 0 24 24" fill="gray"><path d="M0 0h24v24H0z" fill="none"/><path stroke="gray" d="M7 14H5v5h5v-2H7v-3zm-2-4h2V7h3V5H5v5zm12 7h-3v2h5v-5h-2v3zM14 5v2h3v3h2V5h-5z"/></svg>
|
|
17
|
+
);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export const OverflowIcon = () => {
|
|
21
|
+
return (
|
|
22
|
+
<svg xmlns="http://www.w3.org/2000/svg" style={style} viewBox="0 0 24 24" fill="gray"><path d="M0 0h24v24H0z" fill="none"/><path stroke="gray" d="M7 10l5 5 5-5z"/></svg>
|
|
23
|
+
);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export const PopoutIcon = () => {
|
|
27
|
+
return (
|
|
28
|
+
<svg xmlns="http://www.w3.org/2000/svg" style={style} viewBox="0 0 24 24" fill="gray"><path d="M0 0h24v24H0z" fill="none"/><path stroke="gray" d="M9 5v2h6.59L4 18.59 5.41 20 17 8.41V15h2V5z"/></svg>
|
|
29
|
+
);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export const RestoreIcon = () => {
|
|
33
|
+
return (
|
|
34
|
+
<svg xmlns="http://www.w3.org/2000/svg" style={style} viewBox="0 0 24 24" fill="gray"><path d="M0 0h24v24H0z" fill="none"/><path stroke="gray" d="M5 16h3v3h2v-5H5v2zm3-8H5v2h5V5H8v3zm6 11h2v-3h3v-2h-5v5zm2-11V5h-2v5h5V8h-3z"/></svg>
|
|
35
|
+
);
|
|
36
|
+
}
|
package/src/view/Layout.tsx
CHANGED
|
@@ -26,9 +26,11 @@ import { FloatingWindowTab } from "./FloatingWindowTab";
|
|
|
26
26
|
import { TabFloating } from "./TabFloating";
|
|
27
27
|
import { IJsonTabNode } from "../model/IJsonModel";
|
|
28
28
|
import { Orientation } from "..";
|
|
29
|
+
import { CloseIcon, MaximizeIcon, OverflowIcon, PopoutIcon, RestoreIcon } from "./Icons";
|
|
30
|
+
import { TabButtonStamp } from "./TabButtonStamp";
|
|
29
31
|
|
|
30
32
|
export type CustomDragCallback = (dragging: TabNode | IJsonTabNode, over: TabNode, x: number, y: number, location: DockLocation) => void;
|
|
31
|
-
export type DragRectRenderCallback = (
|
|
33
|
+
export type DragRectRenderCallback = (content: React.ReactElement | undefined, node?: Node, json?: IJsonTabNode) => React.ReactElement | undefined;
|
|
32
34
|
export type FloatingTabPlaceholderRenderCallback = (dockPopout: () => void, showPopout: () => void) => React.ReactElement | undefined;
|
|
33
35
|
export type NodeMouseEvent = (node: TabNode | TabSetNode | BorderNode, event: React.MouseEvent<HTMLElement, MouseEvent>) => void;
|
|
34
36
|
|
|
@@ -39,7 +41,6 @@ export interface ILayoutProps {
|
|
|
39
41
|
fontFamily?: string;
|
|
40
42
|
iconFactory?: (node: TabNode) => React.ReactNode | undefined;
|
|
41
43
|
titleFactory?: (node: TabNode) => ITitleObject | React.ReactNode | undefined;
|
|
42
|
-
closeIcon?: React.ReactNode;
|
|
43
44
|
icons?: IIcons;
|
|
44
45
|
onAction?: (action: Action) => Action | undefined;
|
|
45
46
|
onRenderTab?: (
|
|
@@ -120,6 +121,15 @@ export interface IIcons {
|
|
|
120
121
|
more?: React.ReactNode;
|
|
121
122
|
}
|
|
122
123
|
|
|
124
|
+
const defaultIcons = {
|
|
125
|
+
close: <CloseIcon/>,
|
|
126
|
+
closeTabset: <CloseIcon/>,
|
|
127
|
+
popout: <PopoutIcon/>,
|
|
128
|
+
maximize: <MaximizeIcon/>,
|
|
129
|
+
restore: <RestoreIcon/>,
|
|
130
|
+
more: <OverflowIcon/>,
|
|
131
|
+
};
|
|
132
|
+
|
|
123
133
|
export interface ICustomDropDestination {
|
|
124
134
|
rect: Rect;
|
|
125
135
|
callback: CustomDragCallback;
|
|
@@ -146,7 +156,7 @@ export interface ILayoutCallbacks {
|
|
|
146
156
|
getRootDiv(): HTMLDivElement;
|
|
147
157
|
dragStart(
|
|
148
158
|
event: Event | React.MouseEvent<HTMLDivElement, MouseEvent> | React.TouchEvent<HTMLDivElement> | React.DragEvent<HTMLDivElement> | undefined,
|
|
149
|
-
dragDivText: string,
|
|
159
|
+
dragDivText: string | undefined,
|
|
150
160
|
node: Node & IDraggable,
|
|
151
161
|
allowDrag: boolean,
|
|
152
162
|
onClick?: (event: Event) => void,
|
|
@@ -215,7 +225,7 @@ export class Layout extends React.Component<ILayoutProps, ILayoutState> {
|
|
|
215
225
|
/** @hidden @internal */
|
|
216
226
|
private dragRectRendered: boolean = true;
|
|
217
227
|
/** @hidden @internal */
|
|
218
|
-
private dragDivText: string =
|
|
228
|
+
private dragDivText: string | undefined = undefined;
|
|
219
229
|
/** @hidden @internal */
|
|
220
230
|
private dropInfo: DropInfo | undefined;
|
|
221
231
|
/** @hidden @internal */
|
|
@@ -264,8 +274,7 @@ export class Layout extends React.Component<ILayoutProps, ILayoutState> {
|
|
|
264
274
|
this.findBorderBarSizeRef = React.createRef<HTMLDivElement>();
|
|
265
275
|
this.supportsPopout = props.supportsPopout !== undefined ? props.supportsPopout : defaultSupportsPopout;
|
|
266
276
|
this.popoutURL = props.popoutURL ? props.popoutURL : "popout.html";
|
|
267
|
-
|
|
268
|
-
this.icons = props.closeIcon ? Object.assign({ close: props.closeIcon }, props.icons) : props.icons;
|
|
277
|
+
this.icons = {...defaultIcons, ...props.icons};
|
|
269
278
|
this.firstRender = true;
|
|
270
279
|
|
|
271
280
|
this.state = {
|
|
@@ -283,11 +292,13 @@ export class Layout extends React.Component<ILayoutProps, ILayoutState> {
|
|
|
283
292
|
/** @hidden @internal */
|
|
284
293
|
styleFont(style: Record<string, string>): Record<string, string> {
|
|
285
294
|
if (this.props.font) {
|
|
286
|
-
if (this.
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
295
|
+
if (this.selfRef.current) {
|
|
296
|
+
if (this.props.font.size) {
|
|
297
|
+
this.selfRef.current.style.setProperty("--font-size", this.props.font.size);
|
|
298
|
+
}
|
|
299
|
+
if (this.props.font.family) {
|
|
300
|
+
this.selfRef.current.style.setProperty("--font-family", this.props.font.family);
|
|
301
|
+
}
|
|
291
302
|
}
|
|
292
303
|
if (this.props.font.style) {
|
|
293
304
|
style.fontStyle = this.props.font.style;
|
|
@@ -459,7 +470,7 @@ export class Layout extends React.Component<ILayoutProps, ILayoutState> {
|
|
|
459
470
|
const metrics: ILayoutMetrics = {
|
|
460
471
|
headerBarSize: this.state.calculatedHeaderBarSize,
|
|
461
472
|
tabBarSize: this.state.calculatedTabBarSize,
|
|
462
|
-
borderBarSize: this.state.calculatedBorderBarSize
|
|
473
|
+
borderBarSize: this.state.calculatedBorderBarSize
|
|
463
474
|
};
|
|
464
475
|
this.props.model._setShowHiddenBorder(this.state.showHiddenBorder);
|
|
465
476
|
|
|
@@ -691,7 +702,7 @@ export class Layout extends React.Component<ILayoutProps, ILayoutState> {
|
|
|
691
702
|
* @param json the json for the new tab node
|
|
692
703
|
* @param onDrop a callback to call when the drag is complete (node and event will be undefined if the drag was cancelled)
|
|
693
704
|
*/
|
|
694
|
-
addTabWithDragAndDrop(dragText: string, json: IJsonTabNode, onDrop?: (node?: Node, event?: Event) => void) {
|
|
705
|
+
addTabWithDragAndDrop(dragText: string | undefined, json: IJsonTabNode, onDrop?: (node?: Node, event?: Event) => void) {
|
|
695
706
|
this.fnNewNodeDropped = onDrop;
|
|
696
707
|
this.newTabJson = json;
|
|
697
708
|
this.dragStart(undefined, dragText, TabNode._fromJson(json, this.props.model, false), true, undefined, undefined);
|
|
@@ -705,7 +716,7 @@ export class Layout extends React.Component<ILayoutProps, ILayoutState> {
|
|
|
705
716
|
* @param json the json for the new tab node
|
|
706
717
|
* @param onDrop a callback to call when the drag is complete (node and event will be undefined if the drag was cancelled)
|
|
707
718
|
*/
|
|
708
|
-
addTabWithDragAndDropIndirect(dragText: string, json: IJsonTabNode, onDrop?: (node?: Node, event?: Event) => void) {
|
|
719
|
+
addTabWithDragAndDropIndirect(dragText: string | undefined, json: IJsonTabNode, onDrop?: (node?: Node, event?: Event) => void) {
|
|
709
720
|
this.fnNewNodeDropped = onDrop;
|
|
710
721
|
this.newTabJson = json;
|
|
711
722
|
|
|
@@ -798,7 +809,7 @@ export class Layout extends React.Component<ILayoutProps, ILayoutState> {
|
|
|
798
809
|
/** @hidden @internal */
|
|
799
810
|
dragStart = (
|
|
800
811
|
event: Event | React.MouseEvent<HTMLDivElement, MouseEvent> | React.TouchEvent<HTMLDivElement> | React.DragEvent<HTMLDivElement> | undefined,
|
|
801
|
-
dragDivText: string,
|
|
812
|
+
dragDivText: string | undefined,
|
|
802
813
|
node: Node & IDraggable,
|
|
803
814
|
allowDrag: boolean,
|
|
804
815
|
onClick?: (event: Event) => void,
|
|
@@ -814,11 +825,24 @@ export class Layout extends React.Component<ILayoutProps, ILayoutState> {
|
|
|
814
825
|
};
|
|
815
826
|
|
|
816
827
|
/** @hidden @internal */
|
|
817
|
-
dragRectRender = (text: String, node?: Node, json?: IJsonTabNode, onRendered?: () => void) => {
|
|
818
|
-
let content: React.ReactElement | undefined
|
|
828
|
+
dragRectRender = (text: String | undefined, node?: Node, json?: IJsonTabNode, onRendered?: () => void) => {
|
|
829
|
+
let content: React.ReactElement | undefined;
|
|
830
|
+
|
|
831
|
+
if (text !== undefined) {
|
|
832
|
+
content = <div style={{ whiteSpace: "pre" }}>{text.replace("<br>", "\n")}</div>;
|
|
833
|
+
} else {
|
|
834
|
+
if (node && node instanceof TabNode) {
|
|
835
|
+
content = (<TabButtonStamp
|
|
836
|
+
node={node}
|
|
837
|
+
layout={this}
|
|
838
|
+
iconFactory={this.props.iconFactory}
|
|
839
|
+
titleFactory={this.props.titleFactory}
|
|
840
|
+
/>);
|
|
841
|
+
}
|
|
842
|
+
}
|
|
819
843
|
|
|
820
844
|
if (this.props.onRenderDragRect !== undefined) {
|
|
821
|
-
const customContent = this.props.onRenderDragRect(
|
|
845
|
+
const customContent = this.props.onRenderDragRect(content, node, json);
|
|
822
846
|
if (customContent !== undefined) {
|
|
823
847
|
content = customContent;
|
|
824
848
|
}
|
package/src/view/Tab.tsx
CHANGED
|
@@ -8,6 +8,7 @@ import { ILayoutCallbacks } from "./Layout";
|
|
|
8
8
|
import { ErrorBoundary } from "./ErrorBoundary";
|
|
9
9
|
import { I18nLabel } from "../I18nLabel";
|
|
10
10
|
import { BorderNode } from "..";
|
|
11
|
+
import { hideElement } from "./Utils";
|
|
11
12
|
|
|
12
13
|
/** @hidden @internal */
|
|
13
14
|
export interface ITabProps {
|
|
@@ -80,10 +81,4 @@ export const Tab = (props: ITabProps) => {
|
|
|
80
81
|
);
|
|
81
82
|
};
|
|
82
83
|
|
|
83
|
-
|
|
84
|
-
if (useVisibility) {
|
|
85
|
-
style.visibility = "hidden";
|
|
86
|
-
} else {
|
|
87
|
-
style.display = "none";
|
|
88
|
-
}
|
|
89
|
-
}
|
|
84
|
+
|
package/src/view/TabButton.tsx
CHANGED
|
@@ -4,10 +4,10 @@ import Actions from "../model/Actions";
|
|
|
4
4
|
import TabNode from "../model/TabNode";
|
|
5
5
|
import TabSetNode from "../model/TabSetNode";
|
|
6
6
|
import Rect from "../Rect";
|
|
7
|
-
import { IIcons, ILayoutCallbacks
|
|
7
|
+
import { IIcons, ILayoutCallbacks } from "./Layout";
|
|
8
8
|
import { ICloseType } from "../model/ICloseType";
|
|
9
9
|
import { CLASSES } from "../Types";
|
|
10
|
-
import { isAuxMouseEvent } from "./
|
|
10
|
+
import { getRenderStateEx, isAuxMouseEvent } from "./Utils";
|
|
11
11
|
|
|
12
12
|
/** @hidden @internal */
|
|
13
13
|
export interface ITabButtonProps {
|
|
@@ -31,8 +31,7 @@ export const TabButton = (props: ITabButtonProps) => {
|
|
|
31
31
|
const onMouseDown = (event: React.MouseEvent<HTMLDivElement, MouseEvent> | React.TouchEvent<HTMLDivElement>) => {
|
|
32
32
|
|
|
33
33
|
if (!isAuxMouseEvent(event) && !layout.getEditingTab()) {
|
|
34
|
-
|
|
35
|
-
layout.dragStart(event, message, node, node.isEnableDrag(), onClick, onDoubleClick);
|
|
34
|
+
layout.dragStart(event, undefined, node, node.isEnableDrag(), onClick, onDoubleClick);
|
|
36
35
|
}
|
|
37
36
|
};
|
|
38
37
|
|
|
@@ -110,7 +109,7 @@ export const TabButton = (props: ITabButtonProps) => {
|
|
|
110
109
|
const layoutRect = layout.getDomRect();
|
|
111
110
|
const r = selfRef.current!.getBoundingClientRect();
|
|
112
111
|
node._setTabRect(new Rect(r.left - layoutRect.left, r.top - layoutRect.top, r.width, r.height));
|
|
113
|
-
contentWidth.current =
|
|
112
|
+
contentWidth.current = selfRef.current!.getBoundingClientRect().width;
|
|
114
113
|
};
|
|
115
114
|
|
|
116
115
|
const onTextBoxMouseDown = (event: React.MouseEvent<HTMLInputElement> | React.TouchEvent<HTMLInputElement>) => {
|
|
@@ -147,53 +146,21 @@ export const TabButton = (props: ITabButtonProps) => {
|
|
|
147
146
|
classNames += " " + node.getClassName();
|
|
148
147
|
}
|
|
149
148
|
|
|
150
|
-
|
|
151
|
-
let titleContent: React.ReactNode = node.getName();
|
|
152
|
-
let name = node.getName();
|
|
149
|
+
const renderState = getRenderStateEx(layout, node, iconFactory, titleFactory);
|
|
153
150
|
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
if (titleFactory !== undefined) {
|
|
159
|
-
const titleObj = titleFactory(node);
|
|
160
|
-
if (titleObj !== undefined) {
|
|
161
|
-
if (typeof titleObj === "string") {
|
|
162
|
-
titleContent = titleObj as string;
|
|
163
|
-
name = titleObj as string;
|
|
164
|
-
} else if (isTitleObject(titleObj)) {
|
|
165
|
-
titleContent = titleObj.titleContent;
|
|
166
|
-
name = titleObj.name;
|
|
167
|
-
} else {
|
|
168
|
-
titleContent = titleObj;
|
|
169
|
-
}
|
|
170
|
-
}
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
if (leadingContent === undefined && node.getIcon() !== undefined) {
|
|
174
|
-
leadingContent = <img src={node.getIcon()} alt="leadingContent" />;
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
let buttons: any[] = [];
|
|
178
|
-
|
|
179
|
-
// allow customization of leading contents (icon) and contents
|
|
180
|
-
const renderState = { leading: leadingContent, content: titleContent, name, buttons };
|
|
181
|
-
layout.customizeTab(node, renderState);
|
|
182
|
-
|
|
183
|
-
node._setRenderedName(renderState.name);
|
|
184
|
-
|
|
185
|
-
let content = (
|
|
186
|
-
<div ref={contentRef} className={cm(CLASSES.FLEXLAYOUT__TAB_BUTTON_CONTENT)}>
|
|
151
|
+
let content = renderState.content ? (
|
|
152
|
+
<div className={cm(CLASSES.FLEXLAYOUT__TAB_BUTTON_CONTENT)}>
|
|
187
153
|
{renderState.content}
|
|
188
|
-
</div>
|
|
189
|
-
|
|
190
|
-
const leading =
|
|
154
|
+
</div>) : null;
|
|
155
|
+
|
|
156
|
+
const leading = renderState.leading ? (
|
|
157
|
+
<div className={cm(CLASSES.FLEXLAYOUT__TAB_BUTTON_LEADING)}>
|
|
158
|
+
{renderState.leading}
|
|
159
|
+
</div>) : null;
|
|
191
160
|
|
|
192
161
|
if (layout.getEditingTab() === node) {
|
|
193
|
-
const contentStyle = { width: contentWidth + "px" };
|
|
194
162
|
content = (
|
|
195
163
|
<input
|
|
196
|
-
style={contentStyle}
|
|
197
164
|
ref={contentRef}
|
|
198
165
|
className={cm(CLASSES.FLEXLAYOUT__TAB_BUTTON_TEXTBOX)}
|
|
199
166
|
data-layout-path={path + "/textbox"}
|
|
@@ -209,7 +176,7 @@ export const TabButton = (props: ITabButtonProps) => {
|
|
|
209
176
|
|
|
210
177
|
if (node.isEnableClose()) {
|
|
211
178
|
const closeTitle = layout.i18nName(I18nLabel.Close_Tab);
|
|
212
|
-
buttons.push(
|
|
179
|
+
renderState.buttons.push(
|
|
213
180
|
<div
|
|
214
181
|
key="close"
|
|
215
182
|
data-layout-path={path + "/button/close"}
|
|
@@ -236,7 +203,7 @@ export const TabButton = (props: ITabButtonProps) => {
|
|
|
236
203
|
>
|
|
237
204
|
{leading}
|
|
238
205
|
{content}
|
|
239
|
-
{buttons}
|
|
206
|
+
{renderState.buttons}
|
|
240
207
|
</div>
|
|
241
208
|
);
|
|
242
209
|
};
|