Skip to content

Commit 2a1a3cd

Browse files
committed
v0.8.5
1 parent 7806833 commit 2a1a3cd

23 files changed

+536
-197
lines changed

ChangeLog.txt

+3
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
0.8.5
2+
Changed the mini scrollbar to only show when tabs are hovered over
3+
14
0.8.4
25
Added attribute 'enableTabScrollbar' to TabSet and Border nodes
36
Enabling this attribute will show a mini 'scrollbar' for the tabs to indicate the scroll position

examples/demo/layouts/complex.layout

+3-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
{
22
"global": {
3-
"tabEnableFloat": true
3+
"tabEnableFloat": true,
4+
"tabSetEnableTabScrollbar": true,
5+
"borderEnableTabScrollbar": true
46
},
57
"layout": {
68
"type": "row",

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "flexlayout-react",
3-
"version": "0.8.4",
3+
"version": "0.8.5",
44
"description": "A multi-tab docking layout manager",
55
"main": "lib/index.js",
66
"types": "./declarations/index.d.ts",

src/Types.ts

+3-2
Original file line numberDiff line numberDiff line change
@@ -75,10 +75,10 @@ export enum CLASSES {
7575
FLEXLAYOUT__TABSET_SELECTED = "flexlayout__tabset-selected",
7676
FLEXLAYOUT__TABSET_SIZER = "flexlayout__tabset_sizer",
7777
FLEXLAYOUT__TABSET_TAB_DIVIDER = "flexlayout__tabset_tab_divider",
78-
7978
FLEXLAYOUT__TABSET_CONTENT = "flexlayout__tabset_content",
8079
FLEXLAYOUT__TABSET_TABBAR_INNER = "flexlayout__tabset_tabbar_inner",
8180
FLEXLAYOUT__TABSET_TABBAR_INNER_ = "flexlayout__tabset_tabbar_inner_",
81+
8282
FLEXLAYOUT__TABSET_TABBAR_INNER_TAB_CONTAINER = "flexlayout__tabset_tabbar_inner_tab_container",
8383
FLEXLAYOUT__TABSET_TABBAR_INNER_TAB_CONTAINER_ = "flexlayout__tabset_tabbar_inner_tab_container_",
8484

@@ -110,8 +110,9 @@ export enum CLASSES {
110110

111111
FLEXLAYOUT__POPUP_MENU_CONTAINER = "flexlayout__popup_menu_container",
112112
FLEXLAYOUT__POPUP_MENU_ITEM = "flexlayout__popup_menu_item",
113+
FLEXLAYOUT__POPUP_MENU_ITEM__SELECTED = "flexlayout__popup_menu_item--selected",
113114
FLEXLAYOUT__POPUP_MENU = "flexlayout__popup_menu",
114115

115116
FLEXLAYOUT__MINI_SCROLLBAR = "flexlayout__mini_scrollbar",
116-
FLEXLAYOUT__MINI_SCROLLBAR_HIDDEN = "flexlayout__mini_scrollbar_hidden",
117+
FLEXLAYOUT__MINI_SCROLLBAR_CONTAINER = "flexlayout__mini_scrollbar_container",
117118
}

src/view/BorderTabSet.tsx

+38-24
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ export const BorderTabSet = (props: IBorderTabSetProps) => {
2525
const { border, layout, size } = props;
2626

2727
const toolbarRef = React.useRef<HTMLDivElement | null>(null);
28+
const miniScrollRef = React.useRef<HTMLDivElement | null>(null);
2829
const overflowbuttonRef = React.useRef<HTMLButtonElement | null>(null);
2930
const stickyButtonsRef = React.useRef<HTMLDivElement | null>(null);
3031
const tabStripInnerRef = React.useRef<HTMLDivElement | null>(null);
@@ -34,11 +35,11 @@ export const BorderTabSet = (props: IBorderTabSetProps) => {
3435
React.useLayoutEffect(() => {
3536
border.setTabHeaderRect(Rect.getBoundingClientRect(selfRef.current!).relativeTo(layout.getDomRect()!));
3637
});
37-
38-
const { selfRef, userControlledPositionRef, onScroll, hiddenTabs, onMouseWheel, isTabOverflow } =
39-
useTabOverflow(layout, border, Orientation.flip(border.getOrientation()), tabStripInnerRef,
38+
39+
const { selfRef, userControlledPositionRef, onScroll, onScrollPointerDown, hiddenTabs, onMouseWheel, isTabOverflow } =
40+
useTabOverflow(layout, border, Orientation.flip(border.getOrientation()), tabStripInnerRef, miniScrollRef,
4041
layout.getClassName(CLASSES.FLEXLAYOUT__BORDER_BUTTON)
41-
);
42+
);
4243

4344
const onAuxMouseClick = (event: React.MouseEvent<HTMLElement, MouseEvent>) => {
4445
if (isAuxMouseEvent(event)) {
@@ -56,13 +57,15 @@ export const BorderTabSet = (props: IBorderTabSetProps) => {
5657

5758
const onOverflowClick = (event: React.MouseEvent<HTMLElement, MouseEvent>) => {
5859
const callback = layout.getShowOverflowMenu();
59-
const items = hiddenTabs.map(h=> {return {index: h, node: (border.getChildren()[h] as TabNode)};});
60+
const items = hiddenTabs.map(h => { return { index: h, node: (border.getChildren()[h] as TabNode) }; });
6061
if (callback !== undefined) {
6162

6263
callback(border, event, items, onOverflowItemSelect);
6364
} else {
6465
const element = overflowbuttonRef.current!;
65-
showPopup(element,
66+
showPopup(
67+
element,
68+
border,
6669
items,
6770
onOverflowItemSelect,
6871
layout);
@@ -72,7 +75,7 @@ export const BorderTabSet = (props: IBorderTabSetProps) => {
7275

7376
const onOverflowItemSelect = (item: { node: TabNode; index: number }) => {
7477
layout.doAction(Actions.selectTab(item.node.getId()));
75-
userControlledPositionRef.current = false;
78+
userControlledPositionRef.current = false;
7679
};
7780

7881
const onPopoutTab = (event: React.MouseEvent<HTMLElement, MouseEvent>) => {
@@ -149,7 +152,7 @@ export const BorderTabSet = (props: IBorderTabSetProps) => {
149152
const overflowTitle = layout.i18nName(I18nLabel.Overflow_Menu_Tooltip);
150153
let overflowContent;
151154
if (typeof icons.more === "function") {
152-
const items = hiddenTabs.map(h=> {return {index: h, node: (border.getChildren()[h] as TabNode)};});
155+
const items = hiddenTabs.map(h => { return { index: h, node: (border.getChildren()[h] as TabNode) }; });
153156

154157
overflowContent = icons.more(border, items);
155158
} else {
@@ -200,17 +203,25 @@ export const BorderTabSet = (props: IBorderTabSetProps) => {
200203
let outerStyle = {};
201204
const borderHeight = size - 1;
202205
if (border.getLocation() === DockLocation.LEFT) {
203-
innerStyle = { right: "100%", top:0 };
204-
outerStyle = { width: borderHeight, overflowY: "auto"};
206+
innerStyle = { right: "100%", top: 0 };
207+
outerStyle = { width: borderHeight, overflowY: "auto" };
205208
} else if (border.getLocation() === DockLocation.RIGHT) {
206-
innerStyle = { left: "100%", top:0};
209+
innerStyle = { left: "100%", top: 0 };
207210
outerStyle = { width: borderHeight, overflowY: "auto" };
208211
} else {
209-
innerStyle = {left:0 };
212+
innerStyle = { left: 0 };
210213
outerStyle = { height: borderHeight, overflowX: "auto" };
211214
}
212-
const miniScrollbarClasses = cm(CLASSES.FLEXLAYOUT__MINI_SCROLLBAR) + (border.isEnableTabScrollbar()?"":" " + cm(CLASSES.FLEXLAYOUT__MINI_SCROLLBAR_HIDDEN));
213-
215+
216+
let miniScrollbar = undefined;
217+
if (border.isEnableTabScrollbar()) {
218+
miniScrollbar = (
219+
<div ref={miniScrollRef}
220+
className={cm(CLASSES.FLEXLAYOUT__MINI_SCROLLBAR)}
221+
onPointerDown={onScrollPointerDown}
222+
/>
223+
);
224+
}
214225

215226
return (
216227
<div
@@ -226,21 +237,24 @@ export const BorderTabSet = (props: IBorderTabSetProps) => {
226237
onContextMenu={onContextMenu}
227238
onWheel={onMouseWheel}
228239
>
229-
<div
230-
ref={tabStripInnerRef}
231-
className={cm(CLASSES.FLEXLAYOUT__BORDER_INNER) + " " + cm(CLASSES.FLEXLAYOUT__BORDER_INNER_ + border.getLocation().getName()) + " " + miniScrollbarClasses}
232-
style={outerStyle}
233-
onScroll={onScroll}
234-
>
240+
<div className={cm(CLASSES.FLEXLAYOUT__MINI_SCROLLBAR_CONTAINER)}>
235241
<div
236-
style={innerStyle}
237-
className={cm(CLASSES.FLEXLAYOUT__BORDER_INNER_TAB_CONTAINER) + " " + cm(CLASSES.FLEXLAYOUT__BORDER_INNER_TAB_CONTAINER_ + border.getLocation().getName())}
242+
ref={tabStripInnerRef}
243+
className={cm(CLASSES.FLEXLAYOUT__BORDER_INNER) + " " + cm(CLASSES.FLEXLAYOUT__BORDER_INNER_ + border.getLocation().getName())}
244+
style={outerStyle}
245+
onScroll={onScroll}
238246
>
239-
{tabButtons}
247+
<div
248+
style={innerStyle}
249+
className={cm(CLASSES.FLEXLAYOUT__BORDER_INNER_TAB_CONTAINER) + " " + cm(CLASSES.FLEXLAYOUT__BORDER_INNER_TAB_CONTAINER_ + border.getLocation().getName())}
250+
>
251+
{tabButtons}
252+
</div>
240253
</div>
254+
{miniScrollbar}
241255
</div>
242256
{toolbar}
243-
</div>
257+
</div >
244258
);
245259

246260
};

src/view/Layout.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -1224,7 +1224,7 @@ export class LayoutInternal extends React.Component<ILayoutInternalProps, ILayou
12241224
// *************************** End Drag Drop *************************************
12251225
}
12261226

1227-
export const FlexLayoutVersion = "0.8.4";
1227+
export const FlexLayoutVersion = "0.8.5";
12281228

12291229
export type DragRectRenderCallback = (
12301230
content: React.ReactNode | undefined,

src/view/PopupMenu.tsx

+31-19
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,13 @@ import { TabNode } from "../model/TabNode";
33
import { CLASSES } from "../Types";
44
import { LayoutInternal } from "./Layout";
55
import { TabButtonStamp } from "./TabButtonStamp";
6+
import { TabSetNode } from "../model/TabSetNode";
7+
import { BorderNode } from "../model/BorderNode";
68

79
/** @internal */
810
export function showPopup(
911
triggerElement: Element,
12+
parentNode: TabSetNode | BorderNode,
1013
items: { index: number; node: TabNode }[],
1114
onSelect: (item: { index: number; node: TabNode }) => void,
1215
layout: LayoutInternal,
@@ -60,6 +63,7 @@ export function showPopup(
6063

6164
layout.showControlInPortal(<PopupMenu
6265
currentDocument={currentDocument}
66+
parentNode={parentNode}
6367
onSelect={onSelect}
6468
onHide={onHide}
6569
items={items}
@@ -70,6 +74,7 @@ export function showPopup(
7074

7175
/** @internal */
7276
interface IPopupMenuProps {
77+
parentNode: TabSetNode | BorderNode;
7378
items: { index: number; node: TabNode }[];
7479
currentDocument: Document;
7580
onHide: () => void;
@@ -80,46 +85,53 @@ interface IPopupMenuProps {
8085

8186
/** @internal */
8287
const PopupMenu = (props: IPopupMenuProps) => {
83-
const { items, onHide, onSelect, classNameMapper, layout} = props;
88+
const { parentNode, items, onHide, onSelect, classNameMapper, layout } = props;
8489

8590
const onItemClick = (item: { index: number; node: TabNode }, event: React.MouseEvent<HTMLElement, MouseEvent>) => {
8691
onSelect(item);
8792
onHide();
8893
event.stopPropagation();
8994
};
9095

91-
const onDragStart = (event: React.DragEvent<HTMLElement>, node:TabNode) => {
96+
const onDragStart = (event: React.DragEvent<HTMLElement>, node: TabNode) => {
9297
event.stopPropagation(); // prevent starting a tabset drag as well
9398
layout.setDragNode(event.nativeEvent, node as TabNode);
9499
setTimeout(() => {
95100
onHide();
96101
}, 0);
97-
102+
98103
};
99104

100105
const onDragEnd = (event: React.DragEvent<HTMLElement>) => {
101106
layout.clearDragMain();
102107
};
103108

104-
const itemElements = items.map((item, i) => (
105-
<div key={item.index}
106-
className={classNameMapper(CLASSES.FLEXLAYOUT__POPUP_MENU_ITEM)}
107-
data-layout-path={"/popup-menu/tb" + i}
108-
onClick={(event) => onItemClick(item, event)}
109-
draggable={true}
110-
onDragStart={(e) => onDragStart(e, item.node)}
111-
onDragEnd={onDragEnd}
112-
title={item.node.getHelpText()} >
113-
<TabButtonStamp
114-
node={item.node}
115-
layout={layout}
116-
/>
117-
</div>
118-
));
109+
const itemElements = items.map((item, i) => {
110+
let classes = classNameMapper(CLASSES.FLEXLAYOUT__POPUP_MENU_ITEM);
111+
if (parentNode.getSelected() === item.index) {
112+
classes += " " + classNameMapper(CLASSES.FLEXLAYOUT__POPUP_MENU_ITEM__SELECTED);
113+
}
114+
return (
115+
<div key={item.index}
116+
className={classes}
117+
data-layout-path={"/popup-menu/tb" + i}
118+
onClick={(event) => onItemClick(item, event)}
119+
draggable={true}
120+
onDragStart={(e) => onDragStart(e, item.node)}
121+
onDragEnd={onDragEnd}
122+
title={item.node.getHelpText()} >
123+
<TabButtonStamp
124+
node={item.node}
125+
layout={layout}
126+
/>
127+
</div>
128+
)
129+
}
130+
);
119131

120132
return (
121133
<div className={classNameMapper(CLASSES.FLEXLAYOUT__POPUP_MENU)}
122-
data-layout-path="/popup-menu"
134+
data-layout-path="/popup-menu"
123135
>
124136
{itemElements}
125137
</div>);

0 commit comments

Comments
 (0)