You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

пре 3 година
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323
  1. 'use strict';
  2. Object.defineProperty(exports, "__esModule", {
  3. value: true
  4. });
  5. var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
  6. var _react = require('react');
  7. var _react2 = _interopRequireDefault(_react);
  8. var _propTypes = require('prop-types');
  9. var _propTypes2 = _interopRequireDefault(_propTypes);
  10. var _classnames = require('classnames');
  11. var _classnames2 = _interopRequireDefault(_classnames);
  12. var _objectAssign = require('object-assign');
  13. var _objectAssign2 = _interopRequireDefault(_objectAssign);
  14. var _globalEventListener = require('./globalEventListener');
  15. var _globalEventListener2 = _interopRequireDefault(_globalEventListener);
  16. var _AbstractMenu2 = require('./AbstractMenu');
  17. var _AbstractMenu3 = _interopRequireDefault(_AbstractMenu2);
  18. var _SubMenu = require('./SubMenu');
  19. var _SubMenu2 = _interopRequireDefault(_SubMenu);
  20. var _actions = require('./actions');
  21. var _helpers = require('./helpers');
  22. function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
  23. function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
  24. function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
  25. 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; }
  26. 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; }
  27. var ContextMenu = function (_AbstractMenu) {
  28. _inherits(ContextMenu, _AbstractMenu);
  29. function ContextMenu(props) {
  30. _classCallCheck(this, ContextMenu);
  31. var _this = _possibleConstructorReturn(this, (ContextMenu.__proto__ || Object.getPrototypeOf(ContextMenu)).call(this, props));
  32. _this.registerHandlers = function () {
  33. document.addEventListener('mousedown', _this.handleOutsideClick);
  34. document.addEventListener('touchstart', _this.handleOutsideClick);
  35. if (!_this.props.preventHideOnScroll) document.addEventListener('scroll', _this.handleHide);
  36. if (!_this.props.preventHideOnContextMenu) document.addEventListener('contextmenu', _this.handleHide);
  37. document.addEventListener('keydown', _this.handleKeyNavigation);
  38. if (!_this.props.preventHideOnResize) window.addEventListener('resize', _this.handleHide);
  39. };
  40. _this.unregisterHandlers = function () {
  41. document.removeEventListener('mousedown', _this.handleOutsideClick);
  42. document.removeEventListener('touchstart', _this.handleOutsideClick);
  43. document.removeEventListener('scroll', _this.handleHide);
  44. document.removeEventListener('contextmenu', _this.handleHide);
  45. document.removeEventListener('keydown', _this.handleKeyNavigation);
  46. window.removeEventListener('resize', _this.handleHide);
  47. };
  48. _this.handleShow = function (e) {
  49. if (e.detail.id !== _this.props.id || _this.state.isVisible) return;
  50. var _e$detail$position = e.detail.position,
  51. x = _e$detail$position.x,
  52. y = _e$detail$position.y;
  53. _this.setState({ isVisible: true, x: x, y: y });
  54. _this.registerHandlers();
  55. (0, _helpers.callIfExists)(_this.props.onShow, e);
  56. };
  57. _this.handleHide = function (e) {
  58. if (_this.state.isVisible && (!e.detail || !e.detail.id || e.detail.id === _this.props.id)) {
  59. _this.unregisterHandlers();
  60. _this.setState({ isVisible: false, selectedItem: null, forceSubMenuOpen: false });
  61. (0, _helpers.callIfExists)(_this.props.onHide, e);
  62. }
  63. };
  64. _this.handleOutsideClick = function (e) {
  65. if (!_this.menu.contains(e.target)) (0, _actions.hideMenu)();
  66. };
  67. _this.handleMouseLeave = function (event) {
  68. event.preventDefault();
  69. (0, _helpers.callIfExists)(_this.props.onMouseLeave, event, (0, _objectAssign2.default)({}, _this.props.data, _helpers.store.data), _helpers.store.target);
  70. if (_this.props.hideOnLeave) (0, _actions.hideMenu)();
  71. };
  72. _this.handleContextMenu = function (e) {
  73. if (process.env.NODE_ENV === 'production') {
  74. e.preventDefault();
  75. }
  76. _this.handleHide(e);
  77. };
  78. _this.hideMenu = function (e) {
  79. if (e.keyCode === 27 || e.keyCode === 13) {
  80. // ECS or enter
  81. (0, _actions.hideMenu)();
  82. }
  83. };
  84. _this.getMenuPosition = function () {
  85. var x = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;
  86. var y = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
  87. var menuStyles = {
  88. top: y,
  89. left: x
  90. };
  91. if (!_this.menu) return menuStyles;
  92. var _window = window,
  93. innerWidth = _window.innerWidth,
  94. innerHeight = _window.innerHeight;
  95. var rect = _this.menu.getBoundingClientRect();
  96. if (y + rect.height > innerHeight) {
  97. menuStyles.top -= rect.height;
  98. }
  99. if (x + rect.width > innerWidth) {
  100. menuStyles.left -= rect.width;
  101. }
  102. if (menuStyles.top < 0) {
  103. menuStyles.top = rect.height < innerHeight ? (innerHeight - rect.height) / 2 : 0;
  104. }
  105. if (menuStyles.left < 0) {
  106. menuStyles.left = rect.width < innerWidth ? (innerWidth - rect.width) / 2 : 0;
  107. }
  108. return menuStyles;
  109. };
  110. _this.getRTLMenuPosition = function () {
  111. var x = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;
  112. var y = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
  113. var menuStyles = {
  114. top: y,
  115. left: x
  116. };
  117. if (!_this.menu) return menuStyles;
  118. var _window2 = window,
  119. innerWidth = _window2.innerWidth,
  120. innerHeight = _window2.innerHeight;
  121. var rect = _this.menu.getBoundingClientRect();
  122. // Try to position the menu on the left side of the cursor
  123. menuStyles.left = x - rect.width;
  124. if (y + rect.height > innerHeight) {
  125. menuStyles.top -= rect.height;
  126. }
  127. if (menuStyles.left < 0) {
  128. menuStyles.left += rect.width;
  129. }
  130. if (menuStyles.top < 0) {
  131. menuStyles.top = rect.height < innerHeight ? (innerHeight - rect.height) / 2 : 0;
  132. }
  133. if (menuStyles.left + rect.width > innerWidth) {
  134. menuStyles.left = rect.width < innerWidth ? (innerWidth - rect.width) / 2 : 0;
  135. }
  136. return menuStyles;
  137. };
  138. _this.menuRef = function (c) {
  139. _this.menu = c;
  140. };
  141. _this.state = (0, _objectAssign2.default)({}, _this.state, {
  142. x: 0,
  143. y: 0,
  144. isVisible: false
  145. });
  146. return _this;
  147. }
  148. _createClass(ContextMenu, [{
  149. key: 'getSubMenuType',
  150. value: function getSubMenuType() {
  151. // eslint-disable-line class-methods-use-this
  152. return _SubMenu2.default;
  153. }
  154. }, {
  155. key: 'componentDidMount',
  156. value: function componentDidMount() {
  157. this.listenId = _globalEventListener2.default.register(this.handleShow, this.handleHide);
  158. }
  159. }, {
  160. key: 'componentDidUpdate',
  161. value: function componentDidUpdate() {
  162. var _this2 = this;
  163. var wrapper = window.requestAnimationFrame || setTimeout;
  164. if (this.state.isVisible) {
  165. wrapper(function () {
  166. var _state = _this2.state,
  167. x = _state.x,
  168. y = _state.y;
  169. var _ref = _this2.props.rtl ? _this2.getRTLMenuPosition(x, y) : _this2.getMenuPosition(x, y),
  170. top = _ref.top,
  171. left = _ref.left;
  172. wrapper(function () {
  173. if (!_this2.menu) return;
  174. _this2.menu.style.top = top + 'px';
  175. _this2.menu.style.left = left + 'px';
  176. _this2.menu.style.opacity = 1;
  177. _this2.menu.style.pointerEvents = 'auto';
  178. });
  179. });
  180. } else {
  181. wrapper(function () {
  182. if (!_this2.menu) return;
  183. _this2.menu.style.opacity = 0;
  184. _this2.menu.style.pointerEvents = 'none';
  185. });
  186. }
  187. }
  188. }, {
  189. key: 'componentWillUnmount',
  190. value: function componentWillUnmount() {
  191. if (this.listenId) {
  192. _globalEventListener2.default.unregister(this.listenId);
  193. }
  194. this.unregisterHandlers();
  195. }
  196. }, {
  197. key: 'render',
  198. value: function render() {
  199. var _props = this.props,
  200. children = _props.children,
  201. className = _props.className,
  202. style = _props.style;
  203. var isVisible = this.state.isVisible;
  204. var inlineStyle = (0, _objectAssign2.default)({}, style, { position: 'fixed', opacity: 0, pointerEvents: 'none' });
  205. var menuClassnames = (0, _classnames2.default)(_helpers.cssClasses.menu, className, _defineProperty({}, _helpers.cssClasses.menuVisible, isVisible));
  206. return _react2.default.createElement(
  207. 'nav',
  208. {
  209. role: 'menu', tabIndex: '-1', ref: this.menuRef, style: inlineStyle, className: menuClassnames,
  210. onContextMenu: this.handleContextMenu, onMouseLeave: this.handleMouseLeave },
  211. this.renderChildren(children)
  212. );
  213. }
  214. }]);
  215. return ContextMenu;
  216. }(_AbstractMenu3.default);
  217. ContextMenu.propTypes = {
  218. id: _propTypes2.default.string.isRequired,
  219. children: _propTypes2.default.node.isRequired,
  220. data: _propTypes2.default.object,
  221. className: _propTypes2.default.string,
  222. hideOnLeave: _propTypes2.default.bool,
  223. rtl: _propTypes2.default.bool,
  224. onHide: _propTypes2.default.func,
  225. onMouseLeave: _propTypes2.default.func,
  226. onShow: _propTypes2.default.func,
  227. preventHideOnContextMenu: _propTypes2.default.bool,
  228. preventHideOnResize: _propTypes2.default.bool,
  229. preventHideOnScroll: _propTypes2.default.bool,
  230. style: _propTypes2.default.object
  231. };
  232. ContextMenu.defaultProps = {
  233. className: '',
  234. data: {},
  235. hideOnLeave: false,
  236. rtl: false,
  237. onHide: function onHide() {
  238. return null;
  239. },
  240. onMouseLeave: function onMouseLeave() {
  241. return null;
  242. },
  243. onShow: function onShow() {
  244. return null;
  245. },
  246. preventHideOnContextMenu: false,
  247. preventHideOnResize: false,
  248. preventHideOnScroll: false,
  249. style: {}
  250. };
  251. exports.default = ContextMenu;