UNPKG

5.2 kBJavaScriptView Raw
1import _extends from 'babel-runtime/helpers/extends';
2import _objectWithoutProperties from 'babel-runtime/helpers/objectWithoutProperties';
3import _Array$from from 'babel-runtime/core-js/array/from';
4import _classCallCheck from 'babel-runtime/helpers/classCallCheck';
5import _possibleConstructorReturn from 'babel-runtime/helpers/possibleConstructorReturn';
6import _inherits from 'babel-runtime/helpers/inherits';
7import classNames from 'classnames';
8import keycode from 'keycode';
9import React from 'react';
10import PropTypes from 'prop-types';
11import ReactDOM from 'react-dom';
12import RootCloseWrapper from 'react-overlays/lib/RootCloseWrapper';
13
14import { bsClass, getClassSet, prefix, splitBsPropsAndOmit } from './utils/bootstrapUtils';
15import createChainedFunction from './utils/createChainedFunction';
16import ValidComponentChildren from './utils/ValidComponentChildren';
17
18var propTypes = {
19 open: PropTypes.bool,
20 pullRight: PropTypes.bool,
21 onClose: PropTypes.func,
22 labelledBy: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
23 onSelect: PropTypes.func,
24 rootCloseEvent: PropTypes.oneOf(['click', 'mousedown'])
25};
26
27var defaultProps = {
28 bsRole: 'menu',
29 pullRight: false
30};
31
32var DropdownMenu = function (_React$Component) {
33 _inherits(DropdownMenu, _React$Component);
34
35 function DropdownMenu(props) {
36 _classCallCheck(this, DropdownMenu);
37
38 var _this = _possibleConstructorReturn(this, _React$Component.call(this, props));
39
40 _this.handleRootClose = _this.handleRootClose.bind(_this);
41 _this.handleKeyDown = _this.handleKeyDown.bind(_this);
42 return _this;
43 }
44
45 DropdownMenu.prototype.getFocusableMenuItems = function getFocusableMenuItems() {
46 var node = ReactDOM.findDOMNode(this);
47 if (!node) {
48 return [];
49 }
50
51 return _Array$from(node.querySelectorAll('[tabIndex="-1"]'));
52 };
53
54 DropdownMenu.prototype.getItemsAndActiveIndex = function getItemsAndActiveIndex() {
55 var items = this.getFocusableMenuItems();
56 var activeIndex = items.indexOf(document.activeElement);
57
58 return { items: items, activeIndex: activeIndex };
59 };
60
61 DropdownMenu.prototype.focusNext = function focusNext() {
62 var _getItemsAndActiveInd = this.getItemsAndActiveIndex(),
63 items = _getItemsAndActiveInd.items,
64 activeIndex = _getItemsAndActiveInd.activeIndex;
65
66 if (items.length === 0) {
67 return;
68 }
69
70 var nextIndex = activeIndex === items.length - 1 ? 0 : activeIndex + 1;
71 items[nextIndex].focus();
72 };
73
74 DropdownMenu.prototype.focusPrevious = function focusPrevious() {
75 var _getItemsAndActiveInd2 = this.getItemsAndActiveIndex(),
76 items = _getItemsAndActiveInd2.items,
77 activeIndex = _getItemsAndActiveInd2.activeIndex;
78
79 if (items.length === 0) {
80 return;
81 }
82
83 var prevIndex = activeIndex === 0 ? items.length - 1 : activeIndex - 1;
84 items[prevIndex].focus();
85 };
86
87 DropdownMenu.prototype.handleKeyDown = function handleKeyDown(event) {
88 switch (event.keyCode) {
89 case keycode.codes.down:
90 this.focusNext();
91 event.preventDefault();
92 break;
93 case keycode.codes.up:
94 this.focusPrevious();
95 event.preventDefault();
96 break;
97 case keycode.codes.esc:
98 case keycode.codes.tab:
99 this.props.onClose(event, { source: 'keydown' });
100 break;
101 default:
102 }
103 };
104
105 DropdownMenu.prototype.handleRootClose = function handleRootClose(event) {
106 this.props.onClose(event, { source: 'rootClose' });
107 };
108
109 DropdownMenu.prototype.render = function render() {
110 var _extends2,
111 _this2 = this;
112
113 var _props = this.props,
114 open = _props.open,
115 pullRight = _props.pullRight,
116 labelledBy = _props.labelledBy,
117 onSelect = _props.onSelect,
118 className = _props.className,
119 rootCloseEvent = _props.rootCloseEvent,
120 children = _props.children,
121 props = _objectWithoutProperties(_props, ['open', 'pullRight', 'labelledBy', 'onSelect', 'className', 'rootCloseEvent', 'children']);
122
123 var _splitBsPropsAndOmit = splitBsPropsAndOmit(props, ['onClose']),
124 bsProps = _splitBsPropsAndOmit[0],
125 elementProps = _splitBsPropsAndOmit[1];
126
127 var classes = _extends({}, getClassSet(bsProps), (_extends2 = {}, _extends2[prefix(bsProps, 'right')] = pullRight, _extends2));
128
129 return React.createElement(
130 RootCloseWrapper,
131 {
132 disabled: !open,
133 onRootClose: this.handleRootClose,
134 event: rootCloseEvent
135 },
136 React.createElement(
137 'ul',
138 _extends({}, elementProps, {
139 role: 'menu',
140 className: classNames(className, classes),
141 'aria-labelledby': labelledBy
142 }),
143 ValidComponentChildren.map(children, function (child) {
144 return React.cloneElement(child, {
145 onKeyDown: createChainedFunction(child.props.onKeyDown, _this2.handleKeyDown),
146 onSelect: createChainedFunction(child.props.onSelect, onSelect)
147 });
148 })
149 )
150 );
151 };
152
153 return DropdownMenu;
154}(React.Component);
155
156DropdownMenu.propTypes = propTypes;
157DropdownMenu.defaultProps = defaultProps;
158
159export default bsClass('dropdown-menu', DropdownMenu);
\No newline at end of file