import { assignIn } from 'lodash'; import * as React from 'react'; import { Nav, Navbar, NavDropdown } from 'react-bootstrap'; import { generateId } from '../../../lib/helpers/idMethods'; export interface ToolbarProps { toolbar: IToolbar; generateData(): D; position?: 'top' | 'bottom', sticky?: boolean; bg?: 'light' | 'dark', brand?: ILink } /** * Definition of a Toolbar. * * @export * @interface IToolbar * @template D */ export interface IToolbar { /** * Items of the toolbar. * * @type {(Array | IMenu | ILink>)} * @memberof IToolbar */ items: Array | IMenu | ILink> } export interface IAction { type: 'action'; /** * Action which should be performed if the element * has been clicked. * * @param {D} data * @memberof IAction */ onClick(data: D): void; /** * Label of the Menu. * * @type {string} * @memberof IAction */ label: string, } /** * A Menu of the Toolbar * * @export * @interface IMenu * @template D */ export interface IMenu { type: 'menu', /** * The Menu ID. * * @type {string} * @memberof IMenu */ id: string; /** * Label of the Menu * * @type {string} * @memberof IMenu */ label: string, /** * Items of the Menu. * * @type {(Array | ILink | IDivider>)} * @memberof IMenu */ items: Array | IMenu | ILink | IDivider>; } /** * A Classical Link. * * @export * @interface ILink */ export interface ILink { /** * Type of the Element. * * @type {'link'} * @memberof ILink */ type: 'link'; /** * Label * * @type {string} * @memberof ILink */ label: string; /** * Referene, where the client should be navigated on click * * @type {string} * @memberof ILink */ ref: string; } /** * A Divider in a Menu. * * @export * @interface IDivider */ export interface IDivider { /** * Type Element * * @type {'divider'} * @memberof IDivider */ type: 'divider' } export interface ToolbarState { } class Toolbar extends React.Component, ToolbarState> { _renderMenuEntry(item: IAction | IMenu | ILink) { const _this = this; switch (item.type) { case 'action': return ( { item.onClick(this.props.generateData()); }}>{item.label} ); case 'menu': return this._renderDropdown(item); case 'link': return ( {item.label} ); } } _renderDropdown(item: IMenu) { return ( {/* Iterate over the deteced Modules. */} {item.items.map(entry => { switch (entry.type) { case 'action': return ( { entry.onClick(this.props.generateData()); }}>{entry.label} ); case 'divider': return ( ); case 'link': return ( {entry.label} ); case 'menu': return this._renderDropdown(entry); } })} ); } /** * Main Function to Render the Layout */ render() { const defaultOptions: Partial> = { bg: 'dark', position: 'top', sticky: true } const opts: ToolbarProps = assignIn(defaultOptions, this.props); return ( <> {opts.sticky ? // Render a collapsable Navbar containing the defined Menu structure. {opts.brand ? <> {opts.brand.label} : } {opts.toolbar.items.map(item => this._renderMenuEntry(item))} : {opts.brand ? <> {opts.brand.label} : } {opts.toolbar.items.map(item => this._renderMenuEntry(item))} } ); } } export default Toolbar;