UNPKG

react-ctxmenu-trigger

Version:

base abstract ctx menu trigger component for react

272 lines (226 loc) 8.95 kB
var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } 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; } 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; } import React from 'react'; import PropTypes from 'prop-types'; import { findDOMNode } from 'react-dom'; import Portal from 'rc-util/es/Portal'; import { getAlignFromPlacement, getAlignPopupClassName } from './utils'; import Popup from './Popup'; function noop() {} function returnEmptyString() { return ''; } function returnDocument() { return window.document; } var contextTypes = { rcTrigger: PropTypes.shape({ onPopupMouseDown: PropTypes.func }) }; var CtxMenuTrigger = function (_React$Component) { _inherits(CtxMenuTrigger, _React$Component); // todo: slim props function CtxMenuTrigger(props) { _classCallCheck(this, CtxMenuTrigger); var _this = _possibleConstructorReturn(this, _React$Component.call(this, props)); _initialiseProps.call(_this); var popupVisible = void 0; if ('popupVisible' in props) { popupVisible = !!props.popupVisible; } else { popupVisible = !!props.defaultPopupVisible; } _this.state = { prevPopupVisible: popupVisible, popupVisible: popupVisible }; return _this; } CtxMenuTrigger.prototype.getChildContext = function getChildContext() { return { rcTrigger: { onPopupMouseDown: this.onPopupMouseDown } }; }; CtxMenuTrigger.prototype.componentWillUnmount = function componentWillUnmount() { clearTimeout(this.mouseDownTimeout); }; CtxMenuTrigger.getDerivedStateFromProps = function getDerivedStateFromProps(_ref, prevState) { var popupVisible = _ref.popupVisible; var newState = {}; if (popupVisible !== undefined && prevState.popupVisible !== popupVisible) { newState.popupVisible = popupVisible; newState.prevPopupVisible = prevState.popupVisible; } return newState; }; CtxMenuTrigger.prototype.getPopupAlign = function getPopupAlign() { var props = this.props; var popupPlacement = props.popupPlacement, popupAlign = props.popupAlign, builtinPlacements = props.builtinPlacements; if (popupPlacement && builtinPlacements) { return getAlignFromPlacement(builtinPlacements, popupPlacement, popupAlign); } return popupAlign; }; CtxMenuTrigger.prototype.render = function render() { var popupVisible = this.state.popupVisible; var forceRender = this.props.forceRender; // prevent unmounting after it's rendered if (popupVisible || this._component || forceRender) { return React.createElement( Portal, { getContainer: this.getContainer }, this.getComponent() ); } return null; }; return CtxMenuTrigger; }(React.Component); CtxMenuTrigger.propTypes = { getPopupClassNameFromAlign: PropTypes.any, popup: PropTypes.oneOfType([PropTypes.node, PropTypes.func]).isRequired, popupStyle: PropTypes.object, prefixCls: PropTypes.string, popupClassName: PropTypes.string, popupPlacement: PropTypes.string, builtinPlacements: PropTypes.object, popupTransitionName: PropTypes.oneOfType([PropTypes.string, PropTypes.object]), popupAnimation: PropTypes.any, zIndex: PropTypes.number, getPopupContainer: PropTypes.func, getDocument: PropTypes.func, forceRender: PropTypes.bool, destroyPopupOnHide: PropTypes.bool, mask: PropTypes.bool, onPopupAlign: PropTypes.func, popupAlign: PropTypes.object, popupVisible: PropTypes.bool, defaultPopupVisible: PropTypes.bool, maskTransitionName: PropTypes.oneOfType([PropTypes.string, PropTypes.object]), maskAnimation: PropTypes.string, stretch: PropTypes.string, alignPoint: PropTypes.bool, // Maybe we can support user pass position in the future point: PropTypes.object }; CtxMenuTrigger.contextTypes = contextTypes; CtxMenuTrigger.childContextTypes = contextTypes; CtxMenuTrigger.defaultProps = { prefixCls: 'rc-trigger-popup', getPopupClassNameFromAlign: returnEmptyString, getDocument: returnDocument, onPopupAlign: noop, popupClassName: '', popupStyle: {}, destroyPopupOnHide: false, popupAlign: {}, defaultPopupVisible: false, mask: false }; var _initialiseProps = function _initialiseProps() { var _this2 = this; this.onPopupMouseDown = function () { var _context$rcTrigger = _this2.context.rcTrigger, rcTrigger = _context$rcTrigger === undefined ? {} : _context$rcTrigger; _this2.hasPopupMouseDown = true; clearTimeout(_this2.mouseDownTimeout); _this2.mouseDownTimeout = setTimeout(function () { _this2.hasPopupMouseDown = false; }, 0); if (rcTrigger.onPopupMouseDown) { rcTrigger.onPopupMouseDown.apply(rcTrigger, arguments); } }; this.getRootDomNode = function () { return findDOMNode(_this2); }; this.getPopupClassNameFromAlign = function (align) { var className = []; var _props = _this2.props, popupPlacement = _props.popupPlacement, builtinPlacements = _props.builtinPlacements, prefixCls = _props.prefixCls, alignPoint = _props.alignPoint, getPopupClassNameFromAlign = _props.getPopupClassNameFromAlign; if (popupPlacement && builtinPlacements) { className.push(getAlignPopupClassName(builtinPlacements, prefixCls, align, alignPoint)); } if (getPopupClassNameFromAlign) { className.push(getPopupClassNameFromAlign(align)); } return className.join(' '); }; this.getComponent = function () { var _props2 = _this2.props, prefixCls = _props2.prefixCls, destroyPopupOnHide = _props2.destroyPopupOnHide, popupClassName = _props2.popupClassName, onPopupAlign = _props2.onPopupAlign, popupAnimation = _props2.popupAnimation, popupTransitionName = _props2.popupTransitionName, popupStyle = _props2.popupStyle, mask = _props2.mask, maskAnimation = _props2.maskAnimation, maskTransitionName = _props2.maskTransitionName, zIndex = _props2.zIndex, popup = _props2.popup, stretch = _props2.stretch, alignPoint = _props2.alignPoint, point = _props2.point; var popupVisible = _this2.state.popupVisible; var align = _this2.getPopupAlign(); var mouseProps = {}; mouseProps.onMouseDown = _this2.onPopupMouseDown; return React.createElement( Popup, _extends({ prefixCls: prefixCls, destroyPopupOnHide: destroyPopupOnHide, visible: popupVisible, point: alignPoint && point, className: popupClassName, action: ['contextMenu'], align: align, onAlign: onPopupAlign, animation: popupAnimation, getClassNameFromAlign: _this2.getPopupClassNameFromAlign }, mouseProps, { stretch: stretch, getRootDomNode: _this2.getRootDomNode, style: popupStyle, mask: mask, zIndex: zIndex, transitionName: popupTransitionName, maskAnimation: maskAnimation, maskTransitionName: maskTransitionName, ref: _this2.savePopup }), typeof popup === 'function' ? popup() : popup ); }; this.getContainer = function () { var props = _this2.props; var popupContainer = document.createElement('div'); // Make sure default popup container will never cause scrollbar appearing // https://github.com/react-component/trigger/issues/41 popupContainer.style.position = 'absolute'; popupContainer.style.top = '0'; popupContainer.style.left = '0'; popupContainer.style.width = '100%'; var mountNode = props.getPopupContainer ? props.getPopupContainer(findDOMNode(_this2)) : props.getDocument().body; mountNode.appendChild(popupContainer); return popupContainer; }; this.savePopup = function (node) { _this2._component = node; }; }; export default CtxMenuTrigger;