Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

3 лет назад
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  1. 'use strict';
  2. Object.defineProperty(exports, "__esModule", {
  3. value: true
  4. });
  5. var _react = require('react');
  6. var _react2 = _interopRequireDefault(_react);
  7. var _propTypes = require('prop-types');
  8. var _propTypes2 = _interopRequireDefault(_propTypes);
  9. var _MenuItem = require('./MenuItem');
  10. var _MenuItem2 = _interopRequireDefault(_MenuItem);
  11. function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
  12. function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
  13. function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
  14. function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
  15. var AbstractMenu = function (_Component) {
  16. _inherits(AbstractMenu, _Component);
  17. function AbstractMenu(props) {
  18. _classCallCheck(this, AbstractMenu);
  19. var _this = _possibleConstructorReturn(this, (AbstractMenu.__proto__ || Object.getPrototypeOf(AbstractMenu)).call(this, props));
  20. _initialiseProps.call(_this);
  21. _this.seletedItemRef = null;
  22. _this.state = {
  23. selectedItem: null,
  24. forceSubMenuOpen: false
  25. };
  26. return _this;
  27. }
  28. return AbstractMenu;
  29. }(_react.Component);
  30. AbstractMenu.propTypes = {
  31. children: _propTypes2.default.node.isRequired
  32. };
  33. var _initialiseProps = function _initialiseProps() {
  34. var _this2 = this;
  35. this.handleKeyNavigation = function (e) {
  36. // check for isVisible strictly here as it might be undefined when this code executes in the context of SubMenu
  37. // but we only need to check when it runs in the ContextMenu context
  38. if (_this2.state.isVisible === false) {
  39. return;
  40. }
  41. switch (e.keyCode) {
  42. case 37: // left arrow
  43. case 27:
  44. // escape
  45. e.preventDefault();
  46. _this2.hideMenu(e);
  47. break;
  48. case 38:
  49. // up arrow
  50. e.preventDefault();
  51. _this2.selectChildren(true);
  52. break;
  53. case 40:
  54. // down arrow
  55. e.preventDefault();
  56. _this2.selectChildren(false);
  57. break;
  58. case 39:
  59. // right arrow
  60. _this2.tryToOpenSubMenu(e);
  61. break;
  62. case 13:
  63. // enter
  64. e.preventDefault();
  65. _this2.tryToOpenSubMenu(e);
  66. {
  67. // determine the selected item is disabled or not
  68. var disabled = _this2.seletedItemRef && _this2.seletedItemRef.props && _this2.seletedItemRef.props.disabled;
  69. if (_this2.seletedItemRef && _this2.seletedItemRef.ref instanceof HTMLElement && !disabled) {
  70. _this2.seletedItemRef.ref.click();
  71. } else {
  72. _this2.hideMenu(e);
  73. }
  74. }
  75. break;
  76. default:
  77. // do nothing
  78. }
  79. };
  80. this.handleForceClose = function () {
  81. _this2.setState({ forceSubMenuOpen: false });
  82. };
  83. this.tryToOpenSubMenu = function (e) {
  84. if (_this2.state.selectedItem && _this2.state.selectedItem.type === _this2.getSubMenuType()) {
  85. e.preventDefault();
  86. _this2.setState({ forceSubMenuOpen: true });
  87. }
  88. };
  89. this.selectChildren = function (forward) {
  90. var selectedItem = _this2.state.selectedItem;
  91. var children = [];
  92. var disabledChildrenCount = 0;
  93. var disabledChildIndexes = {};
  94. var childCollector = function childCollector(child, index) {
  95. // child can be empty in case you do conditional rendering of components, in which
  96. // case it should not be accounted for as a real child
  97. if (!child) {
  98. return;
  99. }
  100. if ([_MenuItem2.default, _this2.getSubMenuType()].indexOf(child.type) < 0) {
  101. // Maybe the MenuItem or SubMenu is capsuled in a wrapper div or something else
  102. _react2.default.Children.forEach(child.props.children, childCollector);
  103. } else if (!child.props.divider) {
  104. if (child.props.disabled) {
  105. ++disabledChildrenCount;
  106. disabledChildIndexes[index] = true;
  107. }
  108. children.push(child);
  109. }
  110. };
  111. _react2.default.Children.forEach(_this2.props.children, childCollector);
  112. if (disabledChildrenCount === children.length) {
  113. // All menu items are disabled, so none can be selected, don't do anything
  114. return;
  115. }
  116. function findNextEnabledChildIndex(currentIndex) {
  117. var i = currentIndex;
  118. var incrementCounter = function incrementCounter() {
  119. if (forward) {
  120. --i;
  121. } else {
  122. ++i;
  123. }
  124. if (i < 0) {
  125. i = children.length - 1;
  126. } else if (i >= children.length) {
  127. i = 0;
  128. }
  129. };
  130. do {
  131. incrementCounter();
  132. } while (i !== currentIndex && disabledChildIndexes[i]);
  133. return i === currentIndex ? null : i;
  134. }
  135. var currentIndex = children.indexOf(selectedItem);
  136. var nextEnabledChildIndex = findNextEnabledChildIndex(currentIndex);
  137. if (nextEnabledChildIndex !== null) {
  138. _this2.setState({
  139. selectedItem: children[nextEnabledChildIndex],
  140. forceSubMenuOpen: false
  141. });
  142. }
  143. };
  144. this.onChildMouseMove = function (child) {
  145. if (_this2.state.selectedItem !== child) {
  146. _this2.setState({ selectedItem: child, forceSubMenuOpen: false });
  147. }
  148. };
  149. this.onChildMouseLeave = function () {
  150. _this2.setState({ selectedItem: null, forceSubMenuOpen: false });
  151. };
  152. this.renderChildren = function (children) {
  153. return _react2.default.Children.map(children, function (child) {
  154. var props = {};
  155. if (!_react2.default.isValidElement(child)) return child;
  156. if ([_MenuItem2.default, _this2.getSubMenuType()].indexOf(child.type) < 0) {
  157. // Maybe the MenuItem or SubMenu is capsuled in a wrapper div or something else
  158. props.children = _this2.renderChildren(child.props.children);
  159. return _react2.default.cloneElement(child, props);
  160. }
  161. props.onMouseLeave = _this2.onChildMouseLeave.bind(_this2);
  162. if (child.type === _this2.getSubMenuType()) {
  163. // special props for SubMenu only
  164. props.forceOpen = _this2.state.forceSubMenuOpen && _this2.state.selectedItem === child;
  165. props.forceClose = _this2.handleForceClose;
  166. props.parentKeyNavigationHandler = _this2.handleKeyNavigation;
  167. }
  168. if (!child.props.divider && _this2.state.selectedItem === child) {
  169. // special props for selected item only
  170. props.selected = true;
  171. props.ref = function (ref) {
  172. _this2.seletedItemRef = ref;
  173. };
  174. return _react2.default.cloneElement(child, props);
  175. }
  176. // onMouseMove is only needed for non selected items
  177. props.onMouseMove = function () {
  178. return _this2.onChildMouseMove(child);
  179. };
  180. return _react2.default.cloneElement(child, props);
  181. });
  182. };
  183. };
  184. exports.default = AbstractMenu;