diff --git a/ChangeLog.txt b/ChangeLog.txt index 3e63f96b..b363f580 100644 --- a/ChangeLog.txt +++ b/ChangeLog.txt @@ -1,3 +1,7 @@ +0.7.12 +Action.setActiveTabset can now take undefined to unset the active tabset. +Added Tab attribute contentClassName to add a class to the tab content. + 0.7.11 Added ITabSetRenderValues.overflowPosition to allow overflow button position to be specified, if left undefined, position will be after sticky buttons as before. diff --git a/README.md b/README.md index 0aa5ba23..76b13859 100755 --- a/README.md +++ b/README.md @@ -42,20 +42,16 @@ Features: ## Installation -FlexLayout is in the npm repository. Simply install React and FlexLayout from npm: +FlexLayout is in the npm repository. install using: ``` -npm install react -npm install react-dom npm install flexlayout-react ``` -Import React and FlexLayout in your modules: +Import FlexLayout in your modules: ``` -import * as React from "react"; -import { createRoot } from "react-dom/client"; -import * as FlexLayout from "flexlayout-react"; +import {Layout, Model} from 'flexlayout-react'; ``` Include the light, underline, gray or dark theme by either: @@ -93,14 +89,6 @@ The factory is a function that takes a Node object and returns a React component The model can be created using the Model.fromJson(jsonObject) static method, and can be saved using the model.toJson() method. -```javascript -this.state = {model: FlexLayout.Model.fromJson(json)}; - -render() { - -} -``` - ## Example Configuration: ```javascript @@ -140,34 +128,25 @@ var json = { ## Example Code -``` -import * as React from "react"; -import { createRoot } from "react-dom/client"; -import * as FlexLayout from "flexlayout-react"; +```javascript +const model = Model.fromJson(json); -class Main extends React.Component { +function App() { - constructor(props) { - super(props); - this.state = {model: FlexLayout.Model.fromJson(json)}; - } + const factory = (node) => { + var component = node.getComponent(); - factory = (node) => { - var component = node.getComponent(); - if (component === "button") { - return ; - } + if (component === "button") { + return ; } + } - render() { - return ( - - ) - } + return ( + + ); } - -const root = createRoot(document.getElementById("container")); -root.render(
); ``` The above code would render two tabsets horizontally each containing a single tab that hosts a button component. The tabs could be moved and resized by dragging and dropping. Additional grids could be added to the layout by sending actions to the model. @@ -203,55 +182,6 @@ Weights on rows and tabsets specify the relative weight of these nodes within th NOTE: the easiest way to create your initial layout JSON is to use the [demo](https://rawgit.com/caplin/FlexLayout/demos/demos/v0.7/demo/index.html) app, modify one of the existing layouts by dragging/dropping and adding nodes then press the 'Show Layout JSON in console' button to print the JSON to the browser developer console. - -example borders section: -``` - borders: [ - { - type: "border", - location: "left", - children: [ - { - type: "tab", - enableClose: false, - name: "Navigation", - component: "grid", - } - ] - }, - { - type: "border", - location: "right", - children: [ - { - type: "tab", - enableClose: false, - name: "Options", - component: "grid", - } - ] - }, - { - type: "border", - location: "bottom", - children: [ - { - type: "tab", - enableClose: false, - name: "Activity Blotter", - component: "grid", - }, - { - type: "tab", - enableClose: false, - name: "Execution Blotter", - component: "grid", - } - ] - } - ] -``` - To control where nodes can be dropped you can add a callback function to the model: ``` @@ -259,7 +189,7 @@ model.setOnAllowDrop(this.allowDrop); ``` example: -``` +```javascript allowDrop(dragNode, dropInfo) { let dropNode = dropInfo.node; @@ -355,6 +285,7 @@ Attributes allowed in the 'global' element | tabEnableRename | true | allow user to rename all tabs by double clicking | | tabEnableFloat | false | enable popouts in all tabs (in popout capable browser) | | tabClassName | null | | +| tabContentClassName | null | | | tabIcon | null | | | tabEnableRenderOnDemand | true | whether to avoid rendering component until tab is visible | | tabDragSpeed | 0.3 | CSS transition speed of drag outlines (in seconds) | @@ -420,7 +351,8 @@ Inherited defaults will take their value from the associated global attributes ( | enableRename | *inherited* | allow user to rename tabs by double clicking | | enableFloat | *inherited* | enable popout (in popout capable browser) | | floating | false | | -| className | *inherited* | | +| className | *inherited* | class applied to tab button | +| contentClassName | *inherited* | class applied to tab content | | icon | *inherited* | | | enableRenderOnDemand | *inherited* | whether to avoid rendering component until tab is visible | | borderWidth | *inherited* | width when added to border, -1 will use border size | @@ -489,8 +421,7 @@ Inherited defaults will take their value from the associated global attributes ( | enableDrop | *inherited* | | | autoSelectTabWhenOpen | *inherited* | whether to select new/moved tabs in border when the border is already open | | autoSelectTabWhenClosed | *inherited* | whether to select new/moved tabs in border when the border is currently closed | -| className | *inherited* | | - +| className | *inherited* | class applied to tab button | ## Model Actions diff --git a/examples/simple/main.js b/examples/simple/main.js index 12068d81..ea069bf7 100755 --- a/examples/simple/main.js +++ b/examples/simple/main.js @@ -44,27 +44,22 @@ var json = { } }; -class Main extends React.Component { +const model = FlexLayout.Model.fromJson(json); - constructor(props) { - super(props); - this.state = {model: FlexLayout.Model.fromJson(json)}; - } +function Main(props) { - factory = (node) => { + const factory = (node) => { var component = node.getComponent(); if (component === "panel") { return
{node.getName()}
; } } - - render() { - return ( - - ); - } + + return ( + + ); } ReactDOM.createRoot(document.getElementById("container")).render(
); diff --git a/package.json b/package.json index b84007dd..d058c477 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "flexlayout-react", - "version": "0.7.11", + "version": "0.7.12", "description": "A multi-tab docking layout manager", "main": "lib/index.js", "types": "./declarations/index.d.ts", diff --git a/src/model/Actions.ts b/src/model/Actions.ts index e0be1c99..f5814ce1 100755 --- a/src/model/Actions.ts +++ b/src/model/Actions.ts @@ -100,7 +100,7 @@ export class Actions { * @param tabsetNodeId the id of the tabset node to set as active * @returns {Action} the action */ - static setActiveTabset(tabsetNodeId: string): Action { + static setActiveTabset(tabsetNodeId: string | undefined): Action { return new Action(Actions.SET_ACTIVE_TABSET, { tabsetNode: tabsetNodeId }); } diff --git a/src/model/IJsonModel.ts b/src/model/IJsonModel.ts index a32eed8c..a1cf7fdc 100755 --- a/src/model/IJsonModel.ts +++ b/src/model/IJsonModel.ts @@ -40,8 +40,8 @@ export interface IGlobalAttributes { borderMinSize?: number; // default: 0 borderSize?: number; // default: 200 enableEdgeDock?: boolean; // default: true - enableUseVisibility?: boolean; // default: false enableRotateBorderIcons?: boolean; // default: true + enableUseVisibility?: boolean; // default: false legacyOverflowMenu?: boolean; // default: false marginInsets?: IInsets; // default: {"top":0,"right":0,"bottom":0,"left":0} rootOrientationVertical?: boolean; // default: false @@ -51,6 +51,7 @@ export interface IGlobalAttributes { tabBorderWidth?: number; // default: -1 tabClassName?: string; tabCloseType?: ICloseType; // default: 1 + tabContentClassName?: string; tabDragSpeed?: number; // default: 0.3 tabEnableClose?: boolean; // default: true tabEnableDrag?: boolean; // default: true @@ -122,6 +123,7 @@ export interface ITabAttributes { closeType?: ICloseType; // default: 1 - inherited from global tabCloseType component?: string; config?: any; + contentClassName?: string; enableClose?: boolean; // default: true - inherited from global tabEnableClose enableDrag?: boolean; // default: true - inherited from global tabEnableDrag enableFloat?: boolean; // default: false - inherited from global tabEnableFloat diff --git a/src/model/Model.ts b/src/model/Model.ts index 032c9ba7..7baaf1c2 100755 --- a/src/model/Model.ts +++ b/src/model/Model.ts @@ -69,6 +69,7 @@ export class Model { attributeDefinitions.add("tabEnableFloat", false).setType(Attribute.BOOLEAN); attributeDefinitions.add("tabEnableDrag", true).setType(Attribute.BOOLEAN); attributeDefinitions.add("tabEnableRename", true).setType(Attribute.BOOLEAN); + attributeDefinitions.add("tabContentClassName", undefined).setType(Attribute.STRING); attributeDefinitions.add("tabClassName", undefined).setType(Attribute.STRING); attributeDefinitions.add("tabIcon", undefined).setType(Attribute.STRING); attributeDefinitions.add("tabEnableRenderOnDemand", true).setType(Attribute.BOOLEAN); @@ -371,9 +372,13 @@ export class Model { break; } case Actions.SET_ACTIVE_TABSET: { - const tabsetNode = this._idMap[action.data.tabsetNode]; - if (tabsetNode instanceof TabSetNode) { - this._activeTabSet = tabsetNode; + if (action.data.tabsetNode === undefined) { + this._activeTabSet = undefined; + } else { + const tabsetNode = this._idMap[action.data.tabsetNode]; + if (tabsetNode instanceof TabSetNode) { + this._activeTabSet = tabsetNode; + } } break; } diff --git a/src/model/TabNode.ts b/src/model/TabNode.ts index b6ef8374..f37585b7 100755 --- a/src/model/TabNode.ts +++ b/src/model/TabNode.ts @@ -37,6 +37,7 @@ export class TabNode extends Node implements IDraggable { attributeDefinitions.addInherited("enableDrag", "tabEnableDrag").setType(Attribute.BOOLEAN); attributeDefinitions.addInherited("enableRename", "tabEnableRename").setType(Attribute.BOOLEAN); attributeDefinitions.addInherited("className", "tabClassName").setType(Attribute.STRING); + attributeDefinitions.addInherited("contentClassName", "tabContentClassName").setType(Attribute.STRING); attributeDefinitions.addInherited("icon", "tabIcon").setType(Attribute.STRING); attributeDefinitions.addInherited("enableRenderOnDemand", "tabEnableRenderOnDemand").setType(Attribute.BOOLEAN); attributeDefinitions.addInherited("enableFloat", "tabEnableFloat").setType(Attribute.BOOLEAN); @@ -155,6 +156,10 @@ export class TabNode extends Node implements IDraggable { getClassName() { return this._getAttr("className") as string | undefined; } + + getContentClassName() { + return this._getAttr("contentClassName") as string | undefined; + } isEnableRenderOnDemand() { return this._getAttr("enableRenderOnDemand") as boolean; diff --git a/src/view/Tab.tsx b/src/view/Tab.tsx index 190fb75a..9e96b30a 100755 --- a/src/view/Tab.tsx +++ b/src/view/Tab.tsx @@ -66,6 +66,10 @@ export const Tab = (props: ITabProps) => { className += " " + cm(CLASSES.FLEXLAYOUT__TAB_BORDER); className += " " + cm(CLASSES.FLEXLAYOUT__TAB_BORDER_ + parentNode.getLocation().getName()); } + + if (node.getContentClassName() !== undefined) { + className += " " + node.getContentClassName(); + } return (