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.
@@ -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
- const renderState = getRenderStateEx(layout, node, iconFactory, titleFactory);
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<HTMLDivElement, MouseEvent> | React.MouseEvent<HTMLButtonElement, MouseEvent> | React.TouchEvent<HTMLButtonElement>) => {
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
- const renderState = { headerContent: undefined, buttons, stickyButtons: [], headerButtons: [] };
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
- let toolbar;
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.push(
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>
@@ -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) {
@@ -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.push(
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}
@@ -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
- leadingContent = <img style={{ width: "1em", height: "1em" }} src={node.getIcon()} alt="leadingContent" />;
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[] = [];