From 5a215bcb411c6b67b4439a6fc9dc1370c74f68a7 Mon Sep 17 00:00:00 2001 From: cchaos Date: Mon, 11 Mar 2019 17:59:31 -0400 Subject: [PATCH] Simplify flyout children logic by adding `EuiNavDrawerGroup` --- src-docs/src/views/nav_drawer/nav_drawer.js | 10 +- src/components/index.js | 1 + src/components/nav_drawer/index.js | 4 + src/components/nav_drawer/nav_drawer.js | 95 ++----------------- src/components/nav_drawer/nav_drawer_group.js | 48 ++++++++++ 5 files changed, 66 insertions(+), 92 deletions(-) create mode 100644 src/components/nav_drawer/nav_drawer_group.js diff --git a/src-docs/src/views/nav_drawer/nav_drawer.js b/src-docs/src/views/nav_drawer/nav_drawer.js index 354e9fad1d2..06ffe5f4ce3 100644 --- a/src-docs/src/views/nav_drawer/nav_drawer.js +++ b/src-docs/src/views/nav_drawer/nav_drawer.js @@ -17,8 +17,8 @@ import { EuiHeaderLogo, EuiIcon, EuiTitle, + EuiNavDrawerGroup, EuiNavDrawer, - EuiListGroup, EuiHorizontalRule, EuiShowFor, EuiFocusTrap, @@ -493,13 +493,13 @@ export default class extends Component { - + - + - + - + diff --git a/src/components/index.js b/src/components/index.js index 314566a5035..3f718c299bd 100644 --- a/src/components/index.js +++ b/src/components/index.js @@ -235,6 +235,7 @@ export { export { EuiNavDrawer, + EuiNavDrawerGroup, EuiNavDrawerFlyout, } from './nav_drawer'; diff --git a/src/components/nav_drawer/index.js b/src/components/nav_drawer/index.js index 485c43ca01f..26722e4880f 100644 --- a/src/components/nav_drawer/index.js +++ b/src/components/nav_drawer/index.js @@ -2,6 +2,10 @@ export { EuiNavDrawer, } from './nav_drawer'; +export { + EuiNavDrawerGroup, +} from './nav_drawer_group'; + export { EuiNavDrawerFlyout, } from './nav_drawer_flyout'; diff --git a/src/components/nav_drawer/nav_drawer.js b/src/components/nav_drawer/nav_drawer.js index 372f39f2767..41ce1558a79 100644 --- a/src/components/nav_drawer/nav_drawer.js +++ b/src/components/nav_drawer/nav_drawer.js @@ -180,93 +180,14 @@ export class EuiNavDrawer extends Component { let modifiedChildren = children; // 1. Loop through the EuiNavDrawer children (EuiListGroup, EuiHorizontalRules, etc) - modifiedChildren = React.Children.map(this.props.children, (child, childIndex) => { - - // 2a. Check if child is an EuiListGroup (i.e. not an EuiHorizontalRule) - if (child.type.name === 'EuiListGroup') { - - // 3a. Loop through list items passed as an array on EuiListGroup - if (typeof child.props.listItems !== 'undefined') { - const listItemArray = child.props.listItems; - const modifiedListItems = listItemArray.map((item) => { - // 4. If there is a flyoutMenu prop, then add an onClick prop - if (item.flyoutMenu) { - const { flyoutMenu, ...itemProps } = item; - return { - onClick: () => this.expandFlyout(flyoutMenu.listItems, flyoutMenu.title), - ...itemProps - }; - } - return item; - }); - child = ({ ...child, ...{ - props: ({ ...child.props, ...{ listItems: modifiedListItems } }) - } }); - } - - // 3b. Loop through list itmes passed as separate EuiListGroupItem components - if (typeof child.props.children !== 'undefined') { - const listGroupItems = child.props.children; - - // 4. If there is a flyoutMenu prop, then add an onClick prop - // If only one child, then there is no index; props is top level - if (listGroupItems.props) { - const item = React.cloneElement(listGroupItems, { - onClick: listGroupItems.props.flyoutMenu ? - () => this.expandFlyout( - listGroupItems.props.flyoutMenu.listItems, - listGroupItems.props.flyoutMenu.title - ) - : null, - }); - - // Remove `flyoutMenu` so it doesn't get passed to the DOM - const { - flyoutMenu, // eslint-disable-line no-unused-vars - ...itemProps - } = item.props; - - child = React.cloneElement(child, { - key: childIndex, - children: ({ ...item, ...{ props: { ...itemProps } } }) - }); - // If more than one child, then there is an index - } else { - child = React.cloneElement(child, { - key: childIndex, - children: Object.keys(listGroupItems).map((key, itemIndex) => { - const item = React.cloneElement(listGroupItems[key], { - key: itemIndex, - onClick: listGroupItems[itemIndex].props.flyoutMenu ? - () => this.expandFlyout( - listGroupItems[itemIndex].props.flyoutMenu.listItems, - listGroupItems[itemIndex].props.flyoutMenu.title - ) - : null, - }); - - // Remove `flyoutMenu` so it doesn't get passed to the DOM - const { - flyoutMenu, // eslint-disable-line no-unused-vars - ...itemProps - } = item.props; - - return ({ ...item, ...{ props: { ...itemProps } } }); - }) - }); - } - } - - // 5. If showToolTips passed and currently enabled, add showToolTips prop to EuiListGroup - if (this.state.toolTipsEnabled && showToolTips) { - return React.cloneElement(child, { - showToolTips: true - }); - } else { - return child; - } - - // 2b. Child is not an EuiListGroup, so just return it as-is + modifiedChildren = React.Children.map(this.props.children, child => { + // 2. Check if child is an EuiNavDrawerGroup and if it does have a flyout, add the expand function + if (child.type.name === 'EuiNavDrawerGroup') { + const item = React.cloneElement(child, { + flyoutMenuButtonClick: this.expandFlyout, + showToolTips: this.state.toolTipsEnabled && showToolTips, + }); + return item; } else { return child; } diff --git a/src/components/nav_drawer/nav_drawer_group.js b/src/components/nav_drawer/nav_drawer_group.js new file mode 100644 index 00000000000..d36e18bb72f --- /dev/null +++ b/src/components/nav_drawer/nav_drawer_group.js @@ -0,0 +1,48 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import classNames from 'classnames'; + +import { EuiListGroup } from '../list_group/list_group'; + +export const EuiNavDrawerGroup = ({ className, listItems, flyoutMenuButtonClick, ...rest }) => { + const classes = classNames( + 'euiNavDrawerGroup', + className + ); + + // Create handlers if flyoutMenu exists + const newListItems = listItems.map((item) => { + // If the flyout menu exists, pass back the list of times and the title with the onClick handler of the item + if (item.flyoutMenu && flyoutMenuButtonClick) { + const items = [...item.flyoutMenu.listItems]; + const title = `${item.flyoutMenu.title}`; + item.onClick = () => flyoutMenuButtonClick(items, title); + } + + // Then remove the flyoutMenu key + delete item.flyoutMenu; + + // And return the item + return item; + }); + + + return ( + + ); +}; + +EuiNavDrawerGroup.propTypes = { + listItems: PropTypes.arrayOf(PropTypes.shape({ + ...EuiListGroup.propTypes.listItems[0], + flyoutMenu: PropTypes.shape({ + title: PropTypes.string.isRequired, + listItems: EuiListGroup.propTypes.listItems.isRequired, + }), + })).isRequired, + /** + * While not normally required, it is required to pass a function for handling + * of the flyout menu button click + */ + flyoutMenuButtonClick: PropTypes.func, +};