@talend/react-bootstrap
Version:
Bootstrap 3 components built with React
128 lines • 3.62 kB
JavaScript
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