UNPKG

@talend/react-bootstrap

Version:

Bootstrap 3 components built with React

128 lines 3.62 kB
import React from 'react'; import ReactDOM from 'react-dom'; import RootCloseWrapper from 'react-overlays/lib/RootCloseWrapper'; import classNames from 'classnames'; import PropTypes from 'prop-types'; import { bsClass, getClassSet, prefix, splitBsPropsAndOmit } from './utils/bootstrapUtils'; import createChainedFunction from './utils/createChainedFunction'; import ValidComponentChildren from './utils/ValidComponentChildren'; import { jsx as _jsx } from "react/jsx-runtime"; const propTypes = { open: PropTypes.bool, pullRight: PropTypes.bool, onClose: PropTypes.func, labelledBy: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), onSelect: PropTypes.func, rootCloseEvent: PropTypes.oneOf(['click', 'mousedown']) }; const defaultProps = { bsRole: 'menu', pullRight: false }; class DropdownMenu extends React.Component { constructor(props) { super(props); this.handleRootClose = this.handleRootClose.bind(this); this.handleKeyDown = this.handleKeyDown.bind(this); } getFocusableMenuItems() { const node = ReactDOM.findDOMNode(this); if (!node) { return []; } return Array.from(node.querySelectorAll('[tabIndex="-1"]')); } getItemsAndActiveIndex() { const items = this.getFocusableMenuItems(); const activeIndex = items.indexOf(document.activeElement); return { items, activeIndex }; } focusNext() { const { items, activeIndex } = this.getItemsAndActiveIndex(); if (items.length === 0) { return; } const nextIndex = activeIndex === items.length - 1 ? 0 : activeIndex + 1; items[nextIndex].focus(); } focusPrevious() { const { items, activeIndex } = this.getItemsAndActiveIndex(); if (items.length === 0) { return; } const prevIndex = activeIndex === 0 ? items.length - 1 : activeIndex - 1; items[prevIndex].focus(); } handleKeyDown(event) { switch (event.key) { case 'Down': case 'ArrowDown': this.focusNext(); event.preventDefault(); break; case 'Up': case 'ArrowUp': this.focusPrevious(); event.preventDefault(); break; case 'Esc': case 'Escape': case 'Tab': this.props.onClose(event, { source: 'keydown' }); break; default: } } handleRootClose(event) { this.props.onClose(event, { source: 'rootClose' }); } render() { const { open, pullRight, labelledBy, onSelect, className, rootCloseEvent, children, ...props } = this.props; const [bsProps, elementProps] = splitBsPropsAndOmit(props, ['onClose']); const classes = { ...getClassSet(bsProps), [prefix(bsProps, 'right')]: pullRight }; return /*#__PURE__*/_jsx(RootCloseWrapper, { disabled: !open, onRootClose: this.handleRootClose, event: rootCloseEvent, children: /*#__PURE__*/_jsx("ul", { ...elementProps, role: "menu", className: classNames(className, classes), "aria-labelledby": labelledBy, children: ValidComponentChildren.map(children, child => /*#__PURE__*/React.cloneElement(child, { onKeyDown: createChainedFunction(child.props.onKeyDown, this.handleKeyDown), onSelect: createChainedFunction(child.props.onSelect, onSelect) })) }) }); } } DropdownMenu.propTypes = propTypes; DropdownMenu.defaultProps = defaultProps; export default bsClass('dropdown-menu', DropdownMenu); //# sourceMappingURL=DropdownMenu.js.map