diff --git a/src/App.js b/src/App.js index cc8efb466c..09ecfe76d9 100644 --- a/src/App.js +++ b/src/App.js @@ -218,12 +218,12 @@ class AppMenu extends Component { ● Upload - this.openMenu(event, 6)} className={classNames({ 'active-menuitem': this.state.activeMenu === 6 })} style={{ display: 'none' }}> + this.openMenu(event, 6)} className={classNames({ 'active-menuitem': this.state.activeMenu === 6 })}> button Menu -
- +
+ ● Menu
this.openMenu(event, 7)} className={classNames({ 'active-menuitem': this.state.activeMenu === 7 })}> diff --git a/src/components/menu/Menu.css b/src/components/menu/Menu.css new file mode 100644 index 0000000000..955a45e540 --- /dev/null +++ b/src/components/menu/Menu.css @@ -0,0 +1,328 @@ +.ui-menu { + width: 12.5em; + padding: .25em; + position:relative; +} + +.ui-menu-separator { + border-width: 1px 0 0 0; +} + +.ui-menu.ui-menu-dynamic { + position: absolute; + display: none; + z-index: 100000; +} + +.ui-menu-list { + position: static; +} + +.ui-menu .ui-menu-list .ui-menuitem { + border: none; +} + +.ui-menu .ui-menu-list .ui-widget-header { + clear:both; + float:left; + width: 100%; + margin: .125em 0; + padding: .25em .5em; +} + +.ui-menu .ui-menuitem-parent, +.ui-menu .ui-menuitem { + width: 100%; + clear: both; + margin: .125em 0; + padding: 0; +} + +.ui-menu .ui-menuitem-link { + display: block; + width: 100%; + text-decoration: none; + font-weight: normal; + border: 1px solid transparent; + line-height: 1em; + padding: .25em; + cursor: pointer; +} + +.ui-menu .ui-menuitem-link .ui-menuitem-icon { + display: inline-block; + vertical-align: middle; +} + +.ui-menu .ui-menuitem-text { + vertical-align: middle; +} + +.ui-menu .ui-widget-header h1, +.ui-menu .ui-widget-header h2, +.ui-menu .ui-widget-header h3, +.ui-menu .ui-widget-header h4, +.ui-menu .ui-widget-header h5, +.ui-menu .ui-widget-header h6 { + font-size: 1em; + margin: 0 auto; +} + +/* Tiered Menu */ +.ui-menu .ui-menu-parent .ui-menu-child { + display: none; + width: 12.5em; + padding: .25em; + position:absolute; + margin: 0; + text-decoration:none; + list-style:none; +} + +.ui-menu .ui-menu-parent { + position: relative; +} + +.ui-menu .ui-menu-parent .ui-submenu-icon { + float: right; + margin-right: -.25em; +} + +/** MenuButton **/ +.ui-menubutton { + padding: 0; +} + +.ui-menubutton .ui-button { + margin: 0; +} + +/** Menubar **/ +.ui-menu.ui-menubar .ui-menubar-root-list > li > a > .ui-submenu-icon { + float: none; +} + +.ui-menubar { + width:auto; +} + +.ui-menubar .ui-menubar-root-list { + list-style: none; + padding: 0; + margin: 0; +} + +.ui-menubar .ui-menubar-root-list > .ui-menuitem { + display: inline-block; + width: auto; +} + +.ui-menubar:not(.ui-megamenu-vertical) .ui-menubar-root-list > .ui-menu-separator { + display: inline-block; + border-width: 0 0 0 1px; + width: 1px; + text-indent: -9999999px; +} + +.ui-menubar:not(.ui-megamenu-vertical) .ui-menubar-root-list > .ui-menu-separator:before { + content: 'ui-menu-separator'; +} + +.ui-menubar .ui-menu-child .ui-menuitem { + width: 100%; +} + +.ui-menubar .ui-menuitem.ui-menuitem-custom { + float: right; + margin-top: 0.25em; +} + +.ui-menubar .ui-menubar-options { + float: right; +} + +/** SlideMenu **/ +.ui-slidemenu .ui-slidemenu-wrapper { + position: relative; +} + +.ui-slidemenu .ui-slidemenu-content { + overflow-x: hidden; + overflow-y: auto; + position: relative; +} + +.ui-slidemenu .ui-menu-list { + position: absolute; + top: 0; +} + +.ui-slidemenu .ui-menu-parent { + position: static; +} + +.ui-slidemenu .ui-menu-child { + box-shadow : none; + border: 0 none; + background: none repeat scroll 0 0 transparent; +} + +.ui-slidemenu-backward { + position: absolute; + bottom: 0; + width: 100%; + padding: 0.2em; + cursor: pointer; + display: none; +} + +.ui-slidemenu-backward .fa { + vertical-align: middle; +} + +.ui-slidemenu-backward span { + vertical-align: middle; +} + +.ui-slidemenu .ui-slidemenuitem-active > .ui-submenu > ul { + display: block !important; +} + +/** MegaMenu **/ +.ui-megamenu .ui-g { + flex-wrap: nowrap; +} + +.ui-megamenu .ui-megamenu-panel.ui-menu-child { + width: auto; +} + +.ui-megamenu .ui-megamenu-panel .ui-menu-list { + width: 12.5em; +} + +.ui-megamenu-vertical { + width: 12.5em; +} + +.ui-megamenu-vertical .ui-menuitem-link, +.ui-megamenu-vertical .ui-menu-list .ui-menuitem { + width: 100%; + box-sizing: border-box; +} + +.ui-megamenu-vertical > .ui-menubar-root-list > .ui-menuitem > .ui-menuitem-link > .ui-submenu-icon { + float: right; +} + +/** PanelMenu **/ +.ui-panelmenu { + width: auto; +} + +.ui-panelmenu .ui-panelmenu-panel { + padding: 0; + margin: 0; +} + +.ui-panelmenu .ui-panelmenu-header { + cursor: pointer; + position: relative; + margin: -1px 0 0 0; + zoom: 1; +} + +.ui-panelmenu .ui-panelmenu-header a { + display: block; + padding: .25em .5em; +} + +.ui-panelmenu span { + vertical-align: middle; +} + +.ui-panelmenu .fa { + width: 1em; + text-align: center; + vertical-align: middle; + margin-right: .25em; +} + +.ui-panelmenu .ui-menuitem-text { + margin-left: .125em; +} + +.ui-panelmenu span { + vertical-align: middle; +} + +.ui-panelmenu .ui-panelmenu-content { + padding: 0.2em 0; + border-top: 0; + overflow: auto; + zoom: 1; + outline: none; + margin-bottom: 1px; +} + +.ui-panelmenu .ui-panelmenu-content .ui-menu-parent { + overflow: hidden; +} + +.ui-panelmenu .ui-panelmenu-content-wrapper { + box-sizing: border-box; +} + +.ui-panelmenu .ui-panelmenu-content-wrapper-overflown { + overflow: hidden; +} + +.ui-panelmenu .ui-panelmenu-header.ui-state-disabled, +.ui-panelmenu .ui-panelmenu-header.ui-state-disabled a { + cursor: default; +} + +.ui-panelmenu .ui-menu-list { + position: static; +} + +.ui-panelmenu .ui-menuitem { + margin: 1px 0; + padding: 0; +} + +.ui-panelmenu .ui-menu-separator { + width: 95%; + margin: 0 auto; +} + +.ui-panelmenu .ui-menuitem-link { + display: block; + text-decoration: none; + font-weight: normal; + border: 1px solid transparent; + line-height: 1em; + cursor: pointer; + position: relative; + padding: .25em .5em; +} + +.ui-panelmenu .ui-menu-parent .ui-menu-list { + margin-left: 1.5em; +} + +/** MegaMenu and TieredMenus **/ +.ui-menuitem-active > .ui-submenu > ul, +.ui-menuitem-active > .ui-megamenu-panel { + display: block !important; +} + +.ui-menuitem-outline { + outline: 1px dotted; + z-index: 1; +} + +/** Fluid **/ +.ui-fluid .ui-menu { + width: 100%; +} \ No newline at end of file diff --git a/src/components/menu/Menu.js b/src/components/menu/Menu.js new file mode 100644 index 0000000000..d46f95cae8 --- /dev/null +++ b/src/components/menu/Menu.js @@ -0,0 +1,189 @@ +import React, {Component} from 'react'; +import PropTypes from 'prop-types'; +import DomHandler from '../utils/DomHandler'; +import classNames from 'classnames'; + +export class MenuItem extends Component{ + static defaultProps = { + index:null, + items:null, + menu:null, + }; + + static propTypes = { + index:PropTypes.number, + items:PropTypes.any, + menu:PropTypes.any + }; + + constructor(props) { + super(props); + this.state = {}; + this.item=this.props.items; + this.menu=this.props.menu + } + + render() { + var styleClass=classNames('ui-menuitem-link ui-corner-all',{'ui-state-disabled':this.item.disabled}) + var iconClass=classNames('ui-menuitem-icon fa fa-fw',this.item.icon?this.item.icon:null) + if(this.item.url){ + return ( + this.menu.itemClick(event,this.item)}> + {this.item.icon?:null} + {this.item.label} + + ); + } + else{ + return ( + this.menu.itemClick(event,this.item)}> + {this.item.icon?:null} + {this.item.label} + + ); + } + } +} + +export class Menu extends Component { + + static defaultProps = { + model:null, + popup:false, + style:null, + styleClass:null, + onShow:null, + onHide:null + }; + + static propTypes = { + model:PropTypes.array, + popup:PropTypes.bool, + style:PropTypes.object, + styleClass:PropTypes.string, + onShow:PropTypes.func, + onHide:PropTypes.func + }; + + constructor() { + super(); + this.state = {}; + } + componentDidMount(){ + if(this.props.popup){ + document.body.appendChild(this.container); + this.documentClickListener=document.addEventListener('click',(event)=>{ + if(!this.preventDocumentDefault) { + this.hide(event); + } + this.preventDocumentDefault = false; + }) + } + window.addEventListener('resize',()=>{ + if(this.onResizeTarget && this.container.offsetParent) { + DomHandler.absolutePosition(this.container, this.onResizeTarget); + } + }) + } + hasSubMenu(){ + if(this.props.model){ + for(var items of this.props.model){ + if(items.items) + return true; + } + } + return false; + } + itemClick(event,item){ + if(item.disabled) { + event.preventDefault(); + return; + } + + if(!item.url) { + event.preventDefault(); + } + + if(item.command) { + item.command({ + originalEvent: event, + item: item + }); + } + + if(this.props.popup) { + this.hide(event); + } + } + toggle(event){ + if(this.container.offsetParent) + this.hide(event); + else + this.show(event); + + this.preventDocumentDefault = true; + } + + show(event) { + let target = event.currentTarget; + this.onResizeTarget = event.currentTarget; + this.container.style.display = 'block'; + DomHandler.absolutePosition(this.container, target); + DomHandler.fadeIn(this.container, 250); + this.preventDocumentDefault = true; + if(this.props.onShow){ + this.props.onShow({ + originalEvent:event + }) + } + } + hide(event) { + if(this.container) + this.container.style.display = 'none'; + if(this.props.onHide){ + this.props.onHide({ + originalEvent:event + }) + } + } + + render() { + var styleClass=classNames('ui-menu ui-widget ui-widget-content ui-corner-all ui-helper-clearfix',this.props.styleClass, + {'ui-menu-dynamic ui-shadow':this.props.popup}) + var itemSubMenu,itemMenu; + + if(this.hasSubMenu()){ + itemSubMenu=this.props.model && this.props.model.map((submenu,indexSub)=>{ + var subMenu=
+
  • +

    {submenu.label}

    +
  • + {submenu.items && submenu.items.map((item,indexItem)=>{ + var menu=
  • + +
  • + return menu; + })}
    + return subMenu}) + } + else{ + itemMenu=this.props.model && this.props.model.map((item,index)=>{ + var menu=
  • + +
  • + return menu + }) + } + + return ( +
    this.container=el} onClick={()=>this.preventDocumentDefault=true}> + +
    + ); + } +} \ No newline at end of file diff --git a/src/index.js b/src/index.js index 30ad33a13d..e4e54940ea 100644 --- a/src/index.js +++ b/src/index.js @@ -57,6 +57,7 @@ import {DataScrollerDemo} from './showcase/datascroller/DataScrollerDemo'; import {DataScrollerInlineDemo} from './showcase/datascroller/DataScrollerInlineDemo'; import {DataScrollerLoaderDemo} from './showcase/datascroller/DataScrollerLoaderDemo'; import {DataScrollerInfiniteDemo} from './showcase/datascroller/DataScrollerInfiniteDemo'; +import {MenuDemo} from './showcase/menu/MenuDemo'; import {Router,Route,hashHistory} from 'react-router'; ReactDOM.render( @@ -117,6 +118,7 @@ ReactDOM.render( + , diff --git a/src/showcase/menu/MenuDemo.js b/src/showcase/menu/MenuDemo.js new file mode 100644 index 0000000000..e5580b1fdd --- /dev/null +++ b/src/showcase/menu/MenuDemo.js @@ -0,0 +1,356 @@ +import React, {Component} from 'react'; +import {Link} from 'react-router'; +import {Menu} from '../../components/menu/Menu'; +import {TabView,TabPanel} from '../../components/tabview/TabView'; +import {CodeHighlight} from '../../components/codehighlight/CodeHighlight'; +import {Button} from "../../components/button/Button"; + +export class MenuDemo extends Component { + + constructor() { + super(); + this.state = {}; + } + + render() { + var items=[ { + label: 'File', + items: [{label: 'New', icon: 'fa-plus',command:()=>{ window.location.hash="/fileupload"; }}, + {label: 'Open', icon: 'fa-download', url: 'http://primetek.com.tr'}] + }, { + label: 'Edit', + items: [{label: 'Undo', icon: 'fa-refresh',command:()=>{ window.location.hash="/"; }}, + {label: 'Redo', icon: 'fa-repeat'} ] + }]; + return ( +
    +
    +
    +

    Menu

    +

    Menu is a navigation/command component that supports dynamic and static positioning.

    +
    +
    + +
    +

    Basic

    + + +

    Popup

    + this.menu=el}/> +
    + + + +
    + ) + } +} + +class MenuDoc extends Component { + + render() { + return ( +
    + + +

    Import

    + + {` +import {Menu} from 'primereact/components/menu/Menu'; + +`} + + +

    Getting Started

    +

    Menu requires a collection of menuitems as its model.Core of the api is MenuItem class that defines various options such as the label, icon and children of an item in a menu.MenuItem provides the following properties. Note that not all of them may be utilized by the menu component.

    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    NameTypeDefaultDescription
    labelstringnullText of the item.
    iconstringnullIcon of the item.
    commandfunctionnullCallback to execute when item is clicked.
    urlstringnullExternal link to navigate when item is clicked.
    itemsarraynullAn array of children menuitems.
    disabledbooleanfalseWhen set as true, disables the menuitem.
    targetstringnullSpecifies where to open the linked document.
    separatorbooleanfalseDefines the item as a separator.
    styleobjectnullInline style of the menuitem.
    styleClassstringnullStyle class of the menuitem.
    +
    + +

    Navigation

    +

    Navigation is specified using url property for external links and command function to invoke when an item is clicked is defined using the command property.

    + + {` +render() { + var items=[ { + label: 'File', + items: [{label: 'New', icon: 'fa-plus',command:()=>{ window.location.hash="/fileupload"; }}, + {label: 'Open', icon: 'fa-download', url: 'http://primetek.com.tr'}] + }, { + label: 'Edit', + items: [{label: 'Undo', icon: 'fa-refresh',command:()=>{ window.location.hash="/"; }}, + {label: 'Redo', icon: 'fa-repeat'} ] + }]; +} + +`} + + +

    Popup Mode

    +

    Menu is inline by default, popup mode is also supported by enabling popup property and calling toggle method by passing the event from the anchor element.

    + + {` +this.menu=el} /> +
    + + + +
    + ) + } +} +`} + + + + + ) + } +} \ No newline at end of file