UNPKG

choerodon-ui

Version:

An enterprise-class UI design language and React-based implementation

832 lines (721 loc) 27.2 kB
import _slicedToArray from "@babel/runtime/helpers/slicedToArray"; import _extends from "@babel/runtime/helpers/extends"; import _classCallCheck from "@babel/runtime/helpers/classCallCheck"; import _createClass from "@babel/runtime/helpers/createClass"; import _inherits from "@babel/runtime/helpers/inherits"; import _possibleConstructorReturn from "@babel/runtime/helpers/possibleConstructorReturn"; import _getPrototypeOf from "@babel/runtime/helpers/getPrototypeOf"; import _objectSpread from "@babel/runtime/helpers/objectSpread2"; function _createSuper(Derived) { function isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Date.prototype.toString.call(Reflect.construct(Date, [], function () {})); return true; } catch (e) { return false; } } return function () { var Super = _getPrototypeOf(Derived), result; if (isNativeReflectConstruct()) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; } import { __decorate } from "tslib"; import React, { Children, Component, isValidElement } from 'react'; import PropTypes from 'prop-types'; import { findDOMNode } from 'react-dom'; import { isFragment } from 'react-is'; import classNames from 'classnames'; import raf from 'raf'; import { action as mobxAction, observable, runInAction } from 'mobx'; import { observer, PropTypes as MobxPropTypes } from 'mobx-react'; import noop from 'lodash/noop'; import isEqual from 'lodash/isEqual'; import autobind from '../../pro/es/_util/autobind'; import focusable, { findFocusableParent } from '../../pro/es/_util/focusable'; import { getIf } from '../../pro/es/data-set/utils'; import isIE from '../../pro/es/_util/isIE'; import KeyCode from '../_util/KeyCode'; import TaskRunner from '../_util/TaskRunner'; import Popup from './Popup'; import EventManager from '../_util/EventManager'; import { Action, HideAction, ShowAction } from './enum'; import TriggerChild from './TriggerChild'; function isPointsEq(a1, a2) { return a1[0] === a2[0] && a1[1] === a2[1]; } function _getPopupClassNameFromAlign(builtinPlacements, prefixCls, align) { var points = align.points; var found = Object.keys(builtinPlacements).find(function (placement) { return {}.hasOwnProperty.call(builtinPlacements, placement) && isPointsEq(builtinPlacements[placement].points, points); }); return found ? "".concat(prefixCls, "-popup-placement-").concat(found) : ''; } function getAlignFromPlacement(builtinPlacements, placementStr, align) { var baseAlign = builtinPlacements[placementStr] || {}; return _objectSpread({}, baseAlign, {}, align); } function getPopupAlign(props) { var popupPlacement = props.popupPlacement, popupAlign = props.popupAlign, builtinPlacements = props.builtinPlacements; if (popupPlacement && builtinPlacements) { return getAlignFromPlacement(builtinPlacements, popupPlacement, popupAlign); } return popupAlign; } function contains(root, n) { if (root) { var node = n; while (node) { if (node === root || root.contains && root.contains(node)) { return true; } node = node.parentNode; } } return false; } function isChildrenFunction(fn) { return typeof fn === 'function'; } var Trigger = /*#__PURE__*/ function (_Component) { _inherits(Trigger, _Component); var _super = _createSuper(Trigger); function Trigger(props, context) { var _this; _classCallCheck(this, Trigger); _this = _super.call(this, props, context); _this.focusTime = 0; _this.preClickTime = 0; _this.animateFrameId = 0; runInAction(function () { _this.popupHidden = 'popupHidden' in props ? props.popupHidden : props.defaultPopupHidden; _this.align = getPopupAlign(props); }); return _this; } _createClass(Trigger, [{ key: "saveRef", value: function saveRef(node) { this.popup = node; } }, { key: "getFocusableElements", value: function getFocusableElements(elements) { this.focusElements = elements; var target = this.target, targetEvent = this.targetEvent; if (target && targetEvent && (!elements || !elements.includes(targetEvent.el))) { targetEvent.clear(); delete this.targetEvent; target.focus(); } } }, { key: "renderTriggerChild", value: function renderTriggerChild(child) { var _this2 = this; if (child) { if (isFragment(child)) { var children = child.props.children; return Children.map(children, function (fragmentChild) { return _this2.renderTriggerChild(fragmentChild); }); } if (isValidElement(child)) { var newChildProps = { key: child.key }; if (this.isContextMenuToShow()) { newChildProps.onContextMenu = this.handleEvent; } if (this.isClickToHide() || this.isClickToShow()) { newChildProps.onClick = this.handleEvent; newChildProps.onMouseDown = this.handleEvent; } if (this.isMouseEnterToShow()) { newChildProps.onMouseEnter = this.handleEvent; var mouseEnterDelay = this.props.mouseEnterDelay; if (mouseEnterDelay && !this.isMouseLeaveToHide()) { newChildProps.onMouseLeave = this.cancelPopupTask; } } if (this.isMouseLeaveToHide()) { newChildProps.onMouseLeave = this.handleEvent; var mouseLeaveDelay = this.props.mouseLeaveDelay; if (mouseLeaveDelay && !this.isMouseEnterToShow()) { newChildProps.onMouseEnter = this.cancelPopupTask; } } if (this.isFocusToShow() || this.isBlurToHide()) { newChildProps.onFocus = this.handleEvent; newChildProps.onBlur = this.handleEvent; } newChildProps.onKeyDown = this.handleEvent; newChildProps.popupHidden = this.popupHidden; return React.createElement(TriggerChild, _extends({}, newChildProps), child); } } return child; } }, { key: "render", value: function render() { var _this3 = this; var _this$props = this.props, children = _this$props.children, childrenProps = _this$props.childrenProps; var popup = this.getPopup(); var newChildren = isChildrenFunction(children) ? children(this.renderTriggerChild, childrenProps) : Children.map(children, function (child) { return _this3.renderTriggerChild(child); }); return [newChildren, popup]; } }, { key: "componentWillReceiveProps", value: function componentWillReceiveProps(nextProps) { var popupHidden = nextProps.popupHidden; if (popupHidden !== this.popupHidden && popupHidden !== undefined) { this.popupHidden = popupHidden; } var newAlign = getPopupAlign(nextProps); if (!isEqual(this.align, newAlign)) { this.align = newAlign; } } }, { key: "componentDidMount", value: function componentDidMount() { this.mounted = true; } }, { key: "componentDidUpdate", value: function componentDidUpdate() { var popupHidden = this.popupHidden; if (this.documentEvent) { this.documentEvent.clear(); } if (!popupHidden) { var documentEvent = getIf(this, 'documentEvent', function () { return new EventManager(typeof window === 'undefined' ? undefined : document); }); documentEvent.addEventListener('scroll', this.handleDocumentScroll, true); if ((this.isClickToHide() || this.isContextMenuToShow()) && !this.isBlurToHide()) { documentEvent.addEventListener('mousedown', this.handleDocumentMouseDown); } } } }, { key: "componentWillUnmount", value: function componentWillUnmount() { this.cancelPopupTask(); if (this.documentEvent) { this.documentEvent.clear(); } if (this.targetEvent) { this.targetEvent.clear(); } } }, { key: "cancelPopupTask", value: function cancelPopupTask() { if (this.popupTask) { this.popupTask.cancel(); } } }, { key: "handlePopupKeyDown", value: function handlePopupKeyDown(e) { var focusTarget = this.focusTarget, activeElement = this.activeElement; if (activeElement && focusTarget && e.keyCode === KeyCode.TAB) { var focusElements = this.focusElements; var shiftKey = e.shiftKey; if (focusElements && focusElements.indexOf(activeElement) === (shiftKey ? 0 : focusElements.length - 1)) { if (shiftKey) { e.preventDefault(); } focusTarget.focus(); } } } }, { key: "handleTargetBlur", value: function handleTargetBlur(e, child) { var popup = this.popup, focusTarget = this.focusTarget; var relatedTarget = isIE() ? document.activeElement : e.relatedTarget; if (popup && popup.element.contains(relatedTarget)) { e.stopPropagation(); this.activeElement = relatedTarget; this.currentTriggerChild = child; if (!focusTarget) { this.focusTarget = e.target; } return false; } if (focusTarget) { this.focusTarget = null; this.activeElement = null; this.currentTriggerChild = null; if (focusTarget !== relatedTarget) { this.handleTriggerEvent('Blur', child, e); } } return true; } }, { key: "handleTriggerEvent", value: function handleTriggerEvent(eventName, child, e) { var handle = this.props["on".concat(eventName)]; var childHandle = child.props["on".concat(eventName)]; if (childHandle) { childHandle(e); } if (!e.isDefaultPrevented()) { if (handle) { handle(e); } if (!e.isDefaultPrevented()) { this["handle".concat(eventName)].call(this, e); } } } }, { key: "handleEvent", value: function handleEvent(eventName, child, e) { if (this.isBlurToHide() && eventName === 'Blur' && !this.handleTargetBlur(e, child)) { if (!this.target) { this.target = e.target; } } else { this.handleTriggerEvent(eventName, child, e); } } }, { key: "handlePopupMouseDown", value: function handlePopupMouseDown(e) { var fix = false; if (!e.isDefaultPrevented()) { var target = e.target; var popup = this.popup; var element = focusable(target) ? target : findFocusableParent(target, popup && popup.element); if (element) { e.stopPropagation(); } else { fix = true; } } else { fix = true; } if (fix && this.isBlurToHide()) { e.preventDefault(); } } }, { key: "handlePopupBlur", value: function handlePopupBlur(e) { if (this.isBlurToHide()) { var activeElement = this.activeElement, currentTriggerChild = this.currentTriggerChild; if (activeElement && currentTriggerChild) { this.handleTargetBlur(e, currentTriggerChild); } } } }, { key: "handleContextMenu", value: function handleContextMenu(e) { e.preventDefault(); this.setPopupHidden(false); } }, { key: "handleKeyDown", value: function handleKeyDown(e) { var tabIntoPopupContent = this.props.tabIntoPopupContent; if (!this.popupHidden && tabIntoPopupContent && this.focusElements && e.keyCode === KeyCode.TAB && !e.shiftKey) { var _this$focusElements = _slicedToArray(this.focusElements, 1), firstFocusElement = _this$focusElements[0]; if (firstFocusElement) { e.preventDefault(); firstFocusElement.focus(); } } } }, { key: "handleFocus", value: function handleFocus() { if (this.isFocusToShow()) { var focusDelay = this.props.focusDelay; this.focusTime = Date.now(); this.delaySetPopupHidden(false, focusDelay); } } }, { key: "handleBlur", value: function handleBlur() { if (this.isBlurToHide()) { var blurDelay = this.props.blurDelay; this.delaySetPopupHidden(true, blurDelay); } } }, { key: "handleDocumentMouseDown", value: function handleDocumentMouseDown(e) { if (this.popup) { var target = e.target; if (!contains(findDOMNode(this), target) && !contains(findDOMNode(this.popup), target)) { this.setPopupHidden(true); } } } }, { key: "handleDocumentScroll", value: function handleDocumentScroll(_ref) { var target = _ref.target; if (this.popup && target !== document && !contains(findDOMNode(this.popup), target)) { if (this.animateFrameId) { raf.cancel(this.animateFrameId); } this.animateFrameId = raf(this.forcePopupAlign); } } }, { key: "handleMouseDown", value: function handleMouseDown() { this.preClickTime = Date.now(); } }, { key: "handleClick", value: function handleClick(e) { var popupHidden = this.popupHidden; if (this.focusTime) { if (Math.abs(this.preClickTime - this.focusTime) < 20) { return; } this.focusTime = 0; } this.preClickTime = 0; if (this.isClickToHide() && !popupHidden || popupHidden && this.isClickToShow()) { e.preventDefault(); this.setPopupHidden(!popupHidden); } } }, { key: "handleMouseEnter", value: function handleMouseEnter() { var mouseEnterDelay = this.props.mouseEnterDelay; this.delaySetPopupHidden(false, mouseEnterDelay); } }, { key: "handleMouseLeave", value: function handleMouseLeave() { var mouseLeaveDelay = this.props.mouseLeaveDelay; this.delaySetPopupHidden(true, mouseLeaveDelay); } }, { key: "handlePopupMouseEnter", value: function handlePopupMouseEnter(e) { this.cancelPopupTask(); var onPopupMouseEnter = this.props.onPopupMouseEnter; if (onPopupMouseEnter) { onPopupMouseEnter(e); } } }, { key: "handlePopupMouseLeave", value: function handlePopupMouseLeave(e) { var _this$props2 = this.props, mouseLeaveDelay = _this$props2.mouseLeaveDelay, onPopupMouseLeave = _this$props2.onPopupMouseLeave; this.delaySetPopupHidden(true, mouseLeaveDelay); if (onPopupMouseLeave) { onPopupMouseLeave(e); } } }, { key: "getPopup", value: function getPopup() { var _this$props3 = this.props, prefixCls = _this$props3.prefixCls, popupCls = _this$props3.popupCls, popupStyle = _this$props3.popupStyle, popupClassName = _this$props3.popupClassName, onPopupAnimateAppear = _this$props3.onPopupAnimateAppear, onPopupAnimateEnter = _this$props3.onPopupAnimateEnter, onPopupAnimateLeave = _this$props3.onPopupAnimateLeave, onPopupAnimateEnd = _this$props3.onPopupAnimateEnd, onPopupAlign = _this$props3.onPopupAlign, onPopupMouseEnter = _this$props3.onPopupMouseEnter, onPopupMouseLeave = _this$props3.onPopupMouseLeave, getPopupStyleFromAlign = _this$props3.getPopupStyleFromAlign, _this$props3$getRootD = _this$props3.getRootDomNode, getRootDomNode = _this$props3$getRootD === void 0 ? this.getRootDomNode : _this$props3$getRootD, transitionName = _this$props3.transitionName, getPopupContainer = _this$props3.getPopupContainer, forceRender = _this$props3.forceRender; if (this.mounted || !getPopupContainer) { var hidden = this.popupHidden; if (!hidden || this.popup || forceRender) { var mouseProps = { onMouseEnter: this.isMouseEnterToShow() ? this.handlePopupMouseEnter : onPopupMouseEnter, onMouseLeave: this.isMouseLeaveToHide() ? this.handlePopupMouseLeave : onPopupMouseLeave }; return React.createElement(Popup, _extends({ key: "popup", ref: this.saveRef, transitionName: transitionName, className: classNames("".concat(prefixCls, "-popup"), popupCls, popupClassName), style: popupStyle, hidden: hidden, align: this.align, onAlign: onPopupAlign, onMouseDown: this.handlePopupMouseDown, onKeyDown: this.handlePopupKeyDown, onBlur: this.handlePopupBlur, getFocusableElements: this.getFocusableElements, getRootDomNode: getRootDomNode, onAnimateAppear: onPopupAnimateAppear, onAnimateEnter: onPopupAnimateEnter, onAnimateLeave: onPopupAnimateLeave, onAnimateEnd: onPopupAnimateEnd, getStyleFromAlign: getPopupStyleFromAlign, getClassNameFromAlign: this.getPopupClassNameFromAlign, getPopupContainer: getPopupContainer }, mouseProps), this.getPopupContent()); } } } }, { key: "getRootDomNode", value: function getRootDomNode() { return findDOMNode(this); } }, { key: "getPopupClassNameFromAlign", value: function getPopupClassNameFromAlign(align) { var className = []; var _this$props4 = this.props, popupPlacement = _this$props4.popupPlacement, builtinPlacements = _this$props4.builtinPlacements, prefixCls = _this$props4.prefixCls, getCls = _this$props4.getPopupClassNameFromAlign; if (popupPlacement && builtinPlacements) { className.push(_getPopupClassNameFromAlign(builtinPlacements, prefixCls, align)); } if (getCls) { var cls = getCls(align); if (cls) { className.push(cls); } } return className.join(' '); } }, { key: "forcePopupAlign", value: function forcePopupAlign() { if (!this.popupHidden && this.popup) { this.popup.forceAlign(); } } }, { key: "getPopupContent", value: function getPopupContent() { var _this$props5 = this.props, popupContent = _this$props5.popupContent, children = _this$props5.children; return typeof popupContent === 'function' ? popupContent({ trigger: children }) : popupContent; } }, { key: "popupHiddenBeforeChange", value: function popupHiddenBeforeChange(hidden) { var _this$props$onPopupHi = this.props.onPopupHiddenBeforeChange, onPopupHiddenBeforeChange = _this$props$onPopupHi === void 0 ? noop : _this$props$onPopupHi; if (onPopupHiddenBeforeChange(hidden) === false) { return false; } // if (hidden === false) { // return !isEmpty(this.getPopupContent()); // } return true; } }, { key: "setPopupHidden", value: function setPopupHidden(hidden) { this.cancelPopupTask(); if (this.popupHidden !== hidden) { var _this$props6 = this.props, popupHidden = _this$props6.popupHidden, _this$props6$onPopupH = _this$props6.onPopupHiddenChange, onPopupHiddenChange = _this$props6$onPopupH === void 0 ? noop : _this$props6$onPopupH; if (this.popupHiddenBeforeChange(hidden) !== false) { if (popupHidden === undefined) { this.popupHidden = hidden; } onPopupHiddenChange(hidden); } } } }, { key: "delaySetPopupHidden", value: function delaySetPopupHidden(popupHidden, delay) { var _this4 = this; this.cancelPopupTask(); if (delay) { getIf(this, 'popupTask', function () { return new TaskRunner(); }).delay(delay, function () { _this4.setPopupHidden(popupHidden); }); } else { this.setPopupHidden(popupHidden); } } }, { key: "isClickToShow", value: function isClickToShow() { var _this$props7 = this.props, _this$props7$action = _this$props7.action, action = _this$props7$action === void 0 ? [] : _this$props7$action, _this$props7$showActi = _this$props7.showAction, showAction = _this$props7$showActi === void 0 ? [] : _this$props7$showActi; return action.indexOf(Action.click) !== -1 || showAction.indexOf(ShowAction.click) !== -1; } }, { key: "isContextMenuToShow", value: function isContextMenuToShow() { var _this$props8 = this.props, _this$props8$action = _this$props8.action, action = _this$props8$action === void 0 ? [] : _this$props8$action, _this$props8$showActi = _this$props8.showAction, showAction = _this$props8$showActi === void 0 ? [] : _this$props8$showActi; return action.indexOf(Action.contextMenu) !== -1 || showAction.indexOf(ShowAction.contextMenu) !== -1; } }, { key: "isClickToHide", value: function isClickToHide() { var _this$props9 = this.props, _this$props9$action = _this$props9.action, action = _this$props9$action === void 0 ? [] : _this$props9$action, _this$props9$hideActi = _this$props9.hideAction, hideAction = _this$props9$hideActi === void 0 ? [] : _this$props9$hideActi; return action.indexOf(Action.click) !== -1 || hideAction.indexOf(HideAction.click) !== -1; } }, { key: "isMouseEnterToShow", value: function isMouseEnterToShow() { var _this$props10 = this.props, _this$props10$action = _this$props10.action, action = _this$props10$action === void 0 ? [] : _this$props10$action, _this$props10$showAct = _this$props10.showAction, showAction = _this$props10$showAct === void 0 ? [] : _this$props10$showAct; return action.indexOf(Action.hover) !== -1 || showAction.indexOf(ShowAction.mouseEnter) !== -1; } }, { key: "isMouseLeaveToHide", value: function isMouseLeaveToHide() { var _this$props11 = this.props, _this$props11$action = _this$props11.action, action = _this$props11$action === void 0 ? [] : _this$props11$action, _this$props11$hideAct = _this$props11.hideAction, hideAction = _this$props11$hideAct === void 0 ? [] : _this$props11$hideAct; return action.indexOf(Action.hover) !== -1 || hideAction.indexOf(HideAction.mouseLeave) !== -1; } }, { key: "isFocusToShow", value: function isFocusToShow() { var _this$props12 = this.props, _this$props12$action = _this$props12.action, action = _this$props12$action === void 0 ? [] : _this$props12$action, _this$props12$showAct = _this$props12.showAction, showAction = _this$props12$showAct === void 0 ? [] : _this$props12$showAct; return action.indexOf(Action.focus) !== -1 || showAction.indexOf(ShowAction.focus) !== -1; } }, { key: "isBlurToHide", value: function isBlurToHide() { var _this$props13 = this.props, _this$props13$action = _this$props13.action, action = _this$props13$action === void 0 ? [] : _this$props13$action, _this$props13$hideAct = _this$props13.hideAction, hideAction = _this$props13$hideAct === void 0 ? [] : _this$props13$hideAct; return action.indexOf(Action.focus) !== -1 || hideAction.indexOf(HideAction.blur) !== -1; } }]); return Trigger; }(Component); Trigger.displayName = 'Trigger'; Trigger.propTypes = { action: MobxPropTypes.arrayOrObservableArrayOf(PropTypes.oneOf([Action.hover, Action.contextMenu, Action.focus, Action.click])), showAction: MobxPropTypes.arrayOrObservableArrayOf(PropTypes.oneOf([ShowAction.mouseEnter, ShowAction.contextMenu, ShowAction.focus, ShowAction.click])), hideAction: MobxPropTypes.arrayOrObservableArrayOf(PropTypes.oneOf([HideAction.blur, HideAction.mouseLeave, HideAction.click])), popupContent: PropTypes.oneOfType([PropTypes.node, PropTypes.func]), popupCls: PropTypes.string, popupStyle: PropTypes.object, popupHidden: PropTypes.bool, popupPlacement: PropTypes.string, popupAlign: PropTypes.object, builtinPlacements: PropTypes.any, onPopupAnimateAppear: PropTypes.func, onPopupAnimateEnter: PropTypes.func, onPopupAnimateLeave: PropTypes.func, onPopupAnimateEnd: PropTypes.func, onPopupAlign: PropTypes.func, onPopupHiddenChange: PropTypes.func, getPopupStyleFromAlign: PropTypes.func, getPopupContainer: PropTypes.func, focusDelay: PropTypes.number, blurDelay: PropTypes.number, mouseEnterDelay: PropTypes.number, mouseLeaveDelay: PropTypes.number, transitionName: PropTypes.string, defaultPopupHidden: PropTypes.bool, popupClassName: PropTypes.string, tabIntoPopupContent: PropTypes.bool }; Trigger.defaultProps = { focusDelay: 150, blurDelay: 0, mouseEnterDelay: 100, mouseLeaveDelay: 100, transitionName: 'slide-up', defaultPopupHidden: true }; __decorate([observable], Trigger.prototype, "popupHidden", void 0); __decorate([observable], Trigger.prototype, "mounted", void 0); __decorate([autobind], Trigger.prototype, "saveRef", null); __decorate([autobind], Trigger.prototype, "getFocusableElements", null); __decorate([autobind], Trigger.prototype, "renderTriggerChild", null); __decorate([mobxAction], Trigger.prototype, "componentWillReceiveProps", null); __decorate([mobxAction], Trigger.prototype, "componentDidMount", null); __decorate([autobind], Trigger.prototype, "cancelPopupTask", null); __decorate([autobind], Trigger.prototype, "handlePopupKeyDown", null); __decorate([autobind], Trigger.prototype, "handleTargetBlur", null); __decorate([autobind], Trigger.prototype, "handleEvent", null); __decorate([autobind], Trigger.prototype, "handlePopupMouseDown", null); __decorate([autobind], Trigger.prototype, "handlePopupBlur", null); __decorate([autobind], Trigger.prototype, "handleDocumentMouseDown", null); __decorate([autobind], Trigger.prototype, "handleDocumentScroll", null); __decorate([autobind], Trigger.prototype, "handlePopupMouseEnter", null); __decorate([autobind], Trigger.prototype, "handlePopupMouseLeave", null); __decorate([autobind], Trigger.prototype, "getRootDomNode", null); __decorate([autobind], Trigger.prototype, "getPopupClassNameFromAlign", null); __decorate([autobind], Trigger.prototype, "forcePopupAlign", null); __decorate([mobxAction], Trigger.prototype, "setPopupHidden", null); Trigger = __decorate([observer], Trigger); export default Trigger; //# sourceMappingURL=Trigger.js.map