diff --git a/src/App.js b/src/App.js index 6574bfd485..f01aca2c46 100644 --- a/src/App.js +++ b/src/App.js @@ -232,6 +232,7 @@ class AppMenu extends Component { ● TieredMenu ● Menubar ● ContextMenu + ● PanelMenu this.openMenu(event, 7)} className={classNames({ 'active-menuitem': this.state.activeMenu === 7 })}> diff --git a/src/components/contextmenu/ContextMenu.js b/src/components/contextmenu/ContextMenu.js index 7807b5a6e8..094b335a6a 100644 --- a/src/components/contextmenu/ContextMenu.js +++ b/src/components/contextmenu/ContextMenu.js @@ -1,6 +1,5 @@ import React, {Component} from 'react'; import PropTypes from 'prop-types'; -import ReactDOM from 'react-dom'; import DomHandler from '../utils/DomHandler'; import classNames from 'classnames'; import {NestedMenu} from "../nestedmenu/NestedMenu"; @@ -127,9 +126,9 @@ export class ContextMenu extends Component { var divClass=classNames('ui-contextmenu ui-menu ui-widget ui-widget-content ui-corner-all ui-helper-clearfix ui-menu-dynamic ui-shadow', this.props.styleClass); var ulClass=classNames('ui-menu-list ui-helper-reset'); - var styleClass={}; + var menuStyle=Object.assign({display:this.state.visible?'block':'none'},this.props.style) return ( -
this.container=el} > +
this.container=el} >
); diff --git a/src/components/panelmenu/PanelMenu.js b/src/components/panelmenu/PanelMenu.js new file mode 100644 index 0000000000..ebb1efbbfd --- /dev/null +++ b/src/components/panelmenu/PanelMenu.js @@ -0,0 +1,188 @@ +import React, {Component} from 'react'; +import PropTypes from 'prop-types'; +import classNames from 'classnames'; + +export class PanelMenu extends Component { + static defaultProps = { + model:null, + style: null, + styleClass: null + } + + static propsTypes = { + model:PropTypes.array, + style: PropTypes.any, + styleClass: PropTypes.string + } + + constructor(props) { + super(props); + this.state = {}; + } + render() { + var divClass=classNames('ui-panelmenu ui-widget',this.props.styleClass); + + return ( +
this.container=el} > + {this.props.model && this.props.model.map((item,index)=>{ + return })} +
+ ); + } +} + +export class PanelMenuItem extends Component{ + static defaultProps = { + item:null, + index:null, + length:null, + } + + static propsTypes = { + item:PropTypes.any, + index:PropTypes.any, + length:PropTypes.any + } + + constructor(props) { + super(props); + this.item=this.props.item; + this.state = {expanded:this.item.expanded}; + } + itemClick(event,item){ + if(item.disabled) { + event.preventDefault(); + return; + } + this.setState({expanded:!this.state.expanded}); + if(!item.url) { + event.preventDefault(); + } + + if(item.command) { + item.command({ + originalEvent: event, + item: item + }); + } + } + render(){ + + var subPanel=classNames('ui-panelmenu-content-wrapper',{'ui-panelmenu-content-wrapper-overflown': !this.state.expanded}) + var iconClass=classNames('ui-menuitem-icon fa fa-fw',this.item.icon?this.item.icon:null); + var panelIcon=classNames('ui-panelmenu-icon fa',{'fa-caret-right':!this.state.expanded},{' fa-caret-down':this.state.expanded}); + var itemClass=classNames('ui-widget ui-panelmenu-header ui-state-default', this.item.styleClass, {'ui-state-active':this.state.expanded}, + {'ui-state-disabled':this.item.disabled},{'ui-corner-top':this.props.index===0},{'ui-corner-bottom':this.props.index===this.props.length-1 &&!this.state.expanded}); + + return ( +
+
+ {this.item.url? + this.itemClick(event,this.item)}> + {this.item.items && } + {this.item.icon && } + {this.item.label} + : + this.itemClick(event,this.item)}> + {this.item.items && } + {this.item.icon && } + {this.item.label} + + } +
+ {this.item.items &&
+
+ +
+
} +
); + } +} +class SubItem extends Component{ + static defaultProps = { + item:null, + expanded:null, + } + + static propsTypes = { + item:PropTypes.any, + expanded:PropTypes.bool + } + + constructor(props) { + super(props); + this.item=this.props.item; + this.state = {}; + } + + render(){ + return( + + ); + } +} +class Item extends Component{ + static defaultProps = { + child:null, + tabIndex:null, + index:null + } + + static propsTypes = { + child:PropTypes.any, + tabIndex:PropTypes.bool, + index:PropTypes.any + } + + constructor(props) { + super(props); + this.child=this.props.child; + this.state = {expanded:this.child.expanded}; + } + itemClick(event,item){ + if(item.disabled) { + event.preventDefault(); + return; + } + this.setState({expanded:!this.state.expanded}) + if(!item.url) { + event.preventDefault(); + } + + if(item.command) { + item.command({ + originalEvent: event, + item: item + }); + } + } + + render(){ + var panelClass=classNames('ui-panelmenu-icon fa fa-fw',{'fa-caret-right':!this.state.expanded},{' fa-caret-down':this.state.expanded}) + var iconClass=classNames('ui-menuitem-icon fa fa-fw',this.child.icon?this.child.icon:null); + var aClass=classNames('ui-menuitem-link ui-corner-all',{'ui-menuitem-link-hasicon':this.child.icon&&this.child.items,'ui-state-disabled':this.child.disabled}) + var listClass=classNames('ui-menuitem ui-corner-all',{'ui-menu-parent':this.child.items},this.child.styleClass); + return( + this.child.separator? +
  • : +
  • + {this.child.url? + {this.itemClick(event,this.child);}}> + {this.child.items && } + {this.child.icon && } + {this.child.label} + : + {this.itemClick(event,this.child);}}> + {this.child.items && } + {this.child.icon && } + {this.child.label} + } + {this.child.items && } +
  • + ); + } +} \ No newline at end of file diff --git a/src/index.js b/src/index.js index c5e2c54d66..9b400622a3 100644 --- a/src/index.js +++ b/src/index.js @@ -74,6 +74,7 @@ import {BreadcrumbDemo} from './showcase/breadcrumb/BreadcrumbDemo'; import {TieredMenuDemo} from './showcase/tieredmenu/TieredMenuDemo'; import {MenubarDemo} from './showcase/menubar/MenubarDemo'; import {ContextMenuDemo} from './showcase/contextmenu/ContextMenuDemo'; +import {PanelMenuDemo} from './showcase/panelmenu/PanelMenuDemo'; import {OrganizationChartDemo} from './showcase/organizationchart/OrganizationChartDemo'; import {Router,Route,hashHistory} from 'react-router'; @@ -151,6 +152,7 @@ ReactDOM.render( + diff --git a/src/showcase/panelmenu/PanelMenuDemo.js b/src/showcase/panelmenu/PanelMenuDemo.js new file mode 100644 index 0000000000..9c17c30b78 --- /dev/null +++ b/src/showcase/panelmenu/PanelMenuDemo.js @@ -0,0 +1,409 @@ +import React, {Component} from 'react'; +import {Link} from 'react-router'; +import {PanelMenu} from '../../components/panelmenu/PanelMenu'; +import {TabView,TabPanel} from '../../components/tabview/TabView'; +import {CodeHighlight} from '../../components/codehighlight/CodeHighlight'; + +export class PanelMenuDemo extends Component { + + constructor() { + super(); + this.state = {}; + } + + render() { + var items=[ + { + label: 'File', + icon: 'fa-file-o', + items: [{ + label: 'New', + icon: 'fa-plus', + items: [ + {label: 'Project'}, + {label: 'Other'}, + ] + }, + {label: 'Open'}, + {separator: true}, + {label: 'Quit'} + ] + }, + { + label: 'Edit', + icon: 'fa-edit', + items: [ + {label: 'Undo', icon: 'fa-mail-forward'}, + {label: 'Redo', icon: 'fa-mail-reply'} + ] + }, + { + label: 'Help', + icon: 'fa-question', + items: [ + { + label: 'Contents' + }, + { + label: 'Search', + icon: 'fa-search', + items: [ + { + label: 'Text', + items: [ + { + label: 'Workspace' + } + ] + }, + { + label: 'File' + } + ]} + ] + }, + { + label: 'Actions', + icon: 'fa-gear', + items: [ + { + label: 'Edit', + icon: 'fa-refresh', + items: [ + {label: 'Save', icon: 'fa-save'}, + {label: 'Update', icon: 'fa-save'}, + ] + }, + { + label: 'Other', + icon: 'fa-phone', + items: [ + {label: 'Delete', icon: 'fa-minus'} + ] + } + ] + } + ]; + return ( +
    +
    +
    +

    PanelMenu

    +

    PanelMenu is a hybrid of accordion-tree components.

    +
    +
    +
    + +
    + + + +
    + ); + } +} + +class PanelMenuDoc extends Component { + render() { + return ( +
    + + +

    Import

    + + {` +import {PanelMenu} from 'primereact/components/panelmenu/PanelMenu'; + +`} +

    MenuItem API

    +

    PanelMenu uses the common menu item api to define its items, visit Menu for details.

    + +

    Getting Started

    +

    PanelMenu requires nested menuitems as its model.

    + + {` + + +`} + + + + {` +var items=[ + { + label: 'File', + icon: 'fa-file-o', + items: [{ + label: 'New', + icon: 'fa-plus', + items: [ + {label: 'Project'}, + {label: 'Other'}, + ] + }, + {label: 'Open'}, + {separator: true}, + {label: 'Quit'} + ] + }, + { + label: 'Edit', + icon: 'fa-edit', + items: [ + {label: 'Undo', icon: 'fa-mail-forward'}, + {label: 'Redo', icon: 'fa-mail-reply'} + ] + }, + { + label: 'Help', + icon: 'fa-question', + items: [ + { + label: 'Contents' + }, + { + label: 'Search', + icon: 'fa-search', + items: [ + { + label: 'Text', + items: [ + { + label: 'Workspace' + } + ] + }, + { + label: 'File' + } + ]} + ] + }, + { + label: 'Actions', + icon: 'fa-gear', + items: [ + { + label: 'Edit', + icon: 'fa-refresh', + items: [ + {label: 'Save', icon: 'fa-save'}, + {label: 'Update', icon: 'fa-save'}, + ] + }, + { + label: 'Other', + icon: 'fa-phone', + items: [ + {label: 'Delete', icon: 'fa-minus'} + ] + } + ] + } +]; + +`} + + +

    Initial State

    +

    MenuItem has an expanded property to control the visibility of a submenu, you may use this property to control the state from the menumodel.

    + +

    Attributes

    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    NameTypeDefaultDescription
    modelarraynullAn array of menuitems.
    stylestringnullInline style of the component.
    styleClassstringnullStyle class of the component.
    +
    + +

    Styling

    +

    Following is the list of structural style classes, for theming classes visit theming page.

    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    NameElement
    ui-panelmenuContainer element.
    ui-panelmenu-headerAccordion header of root submenu.
    ui-panelmenu-contentAccordion content of root submenu.
    ui-menu-listList element.
    ui-menuitemMenuitem element.
    ui-menuitem-textLabel of a menuitem.
    ui-menuitem-iconIcon of a menuitem.
    ui-panelmenu-iconArrow icon of an accordion header.
    +
    + +

    Dependencies

    +

    None.

    +
    + + + + + View on GitHub + + + {` +export class PanelMenuDemo extends Component { + + constructor() { + super(); + this.state = {}; + } + + render() { + var items=[ + { + label: 'File', + icon: 'fa-file-o', + items: [{ + label: 'New', + icon: 'fa-plus', + items: [ + {label: 'Project'}, + {label: 'Other'}, + ] + }, + {label: 'Open'}, + {separator: true}, + {label: 'Quit'} + ] + }, + { + label: 'Edit', + icon: 'fa-edit', + items: [ + {label: 'Undo', icon: 'fa-mail-forward'}, + {label: 'Redo', icon: 'fa-mail-reply'} + ] + }, + { + label: 'Help', + icon: 'fa-question', + items: [ + { + label: 'Contents' + }, + { + label: 'Search', + icon: 'fa-search', + items: [ + { + label: 'Text', + items: [ + { + label: 'Workspace' + } + ] + }, + { + label: 'File' + } + ]} + ] + }, + { + label: 'Actions', + icon: 'fa-gear', + items: [ + { + label: 'Edit', + icon: 'fa-refresh', + items: [ + {label: 'Save', icon: 'fa-save'}, + {label: 'Update', icon: 'fa-save'}, + ] + }, + { + label: 'Other', + icon: 'fa-phone', + items: [ + {label: 'Delete', icon: 'fa-minus'} + ] + } + ] + } + ]; + return ( +
    +
    +
    +

    PanelMenu

    +

    PanelMenu is a hybrid of accordion-tree components.

    +
    +
    +
    + +
    + + + +
    + ); + } +} + `} +
    +
    +
    +
    + ) + } + +} \ No newline at end of file