UNPKG

choerodon-ui

Version:

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

739 lines (624 loc) 20.8 kB
import _extends from "@babel/runtime/helpers/extends"; import _toConsumableArray from "@babel/runtime/helpers/toConsumableArray"; import _objectSpread from "@babel/runtime/helpers/objectSpread2"; import _regeneratorRuntime from "@babel/runtime/regenerator"; import _asyncToGenerator from "@babel/runtime/helpers/asyncToGenerator"; 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"; 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, { Component } from 'react'; import { createPortal, render } from 'react-dom'; import { action, computed, observable, runInAction } from 'mobx'; import { observer } from 'mobx-react'; import findLast from 'lodash/findLast'; import noop from 'lodash/noop'; import EventManager from '../../../es/_util/EventManager'; import measureScrollbar from '../../../es/_util/measureScrollbar'; import { pxToRem } from '../../../es/_util/UnitConvertor'; import warning from '../../../es/_util/warning'; import { getConfig, getProPrefixCls } from '../../../es/configure'; import ModalManager from '../modal-manager'; import Modal from '../modal/Modal'; import Animate from '../animate'; import Mask from './Mask'; import { stopEvent } from '../_util/EventManager'; import { suffixCls } from '../modal/utils'; import { getDocument, getMousePosition } from '../_util/DocumentUtils'; var containerInstances = ModalManager.containerInstances; function getArrayIndex(array, index) { if (array.length > index) { return array[index]; } return 0; } function getRoot() { var root = ModalManager.root; if (typeof window !== 'undefined') { var doc = getDocument(window); if (root) { if (!root.parentNode) { doc.body.appendChild(root); } } else { root = doc.createElement('div'); root.className = "".concat(getProPrefixCls(suffixCls), "-container"); doc.body.appendChild(root); ModalManager.root = root; } } return root; } /** * 判断body是否有滚动条 * * @returns {boolean} */ function hasScrollBar(body) { var scrollHeight = body.scrollHeight, clientHeight = body.clientHeight; return scrollHeight > clientHeight; } function hideBodyScrollBar(body) { var style = body.style; if (!ModalManager.defaultBodyStyle) { ModalManager.defaultBodyStyle = { overflow: style.overflow, paddingRight: style.paddingRight }; style.overflow = 'hidden'; if (hasScrollBar(body)) { style.paddingRight = pxToRem(measureScrollbar()) || ''; } } } function showBodyScrollBar(body) { var style = body.style; if (ModalManager.defaultBodyStyle) { var _ModalManager$default = ModalManager.defaultBodyStyle, overflow = _ModalManager$default.overflow, paddingRight = _ModalManager$default.paddingRight; ModalManager.defaultBodyStyle = undefined; style.overflow = overflow; style.paddingRight = paddingRight; } } var ModalContainer = /*#__PURE__*/ function (_Component) { _inherits(ModalContainer, _Component); var _super = _createSuper(ModalContainer); function ModalContainer(props, context) { var _this; _classCallCheck(this, ModalContainer); _this = _super.call(this, props, context); _this.state = { modals: [] }; _this.saveMount = function (mount) { if (mount) { _this.setState({ mount: mount }); } }; _this.handleAnimationEnd = function (modalKey, isEnter) { if (!isEnter) { var modals = _this.state.modals; var index = _this.findIndex(modalKey); if (index !== -1) { var _props = modals[index]; modals.splice(index, 1); if (!_props.destroyOnClose) { modals.unshift(_props); } if (_props.afterClose) { _props.afterClose(); } _this.updateModals(modals); } } }; _this.handleMaskClick = /*#__PURE__*/ _asyncToGenerator( /*#__PURE__*/ _regeneratorRuntime.mark(function _callee() { var modals, modal, _modal$close, close, _modal$onCancel, onCancel, _modal$maskClosable, maskClosable, ret; return _regeneratorRuntime.wrap(function _callee$(_context) { while (1) { switch (_context.prev = _context.next) { case 0: modals = _this.state.modals; modal = findLast(modals, function (_ref2) { var hidden = _ref2.hidden; return !hidden; }); if (!modal) { _context.next = 9; break; } _modal$close = modal.close, close = _modal$close === void 0 ? noop : _modal$close, _modal$onCancel = modal.onCancel, onCancel = _modal$onCancel === void 0 ? noop : _modal$onCancel, _modal$maskClosable = modal.maskClosable, maskClosable = _modal$maskClosable === void 0 ? getConfig('modalMaskClosable') : _modal$maskClosable; if (!maskClosable) { _context.next = 9; break; } _context.next = 7; return onCancel(); case 7: ret = _context.sent; if (ret !== false) { close(); } case 9: case "end": return _context.stop(); } } }, _callee); })); runInAction(function () { _this.maskHidden = true; _this.drawerOffsets = { 'slide-up': [], 'slide-right': [], 'slide-down': [], 'slide-left': [] }; _this.top(); var doc = typeof window === 'undefined' ? undefined : document; if (doc && !ModalManager.mousePositionEventBound.has(doc)) { new EventManager(doc).addEventListener('click', function (e) { ModalManager.mousePosition = getMousePosition(e.clientX, e.clientY, window); // 100ms 内发生过点击事件,则从点击位置动画展示 // 否则直接 zoom 展示 // 这样可以兼容非点击方式展开 setTimeout(function () { return ModalManager.mousePosition = undefined; }, 100); }, true); ModalManager.mousePositionEventBound.add(doc); } }); return _this; } _createClass(ModalContainer, [{ key: "top", value: function top() { ModalManager.addInstance(this); return this; } }, { key: "componentDidUpdate", value: function componentDidUpdate(prevProps) { var location = prevProps.location; var currentLocation = this.props.location; if (location && currentLocation && location.pathname !== currentLocation.pathname) { ModalManager.clear(true); } } }, { key: "componentWillUnmount", value: function componentWillUnmount() { var modals = this.state.modals; ModalManager.removeInstance(this); var current = ModalManager.containerInstances[0]; if (current && modals.length) { current.mergeModals(modals.reduce(function (list, modal) { return modal.__deprecate__ && (!modal.hidden || !modal.destroyOnClose) ? list.concat(_objectSpread({}, modal, { transitionAppear: false })) : list; }, [])); } } }, { key: "updateModals", value: function updateModals(modals) { this.top(); var maskHidden = true; var drawerOffsets = { 'slide-up': [], 'slide-right': [], 'slide-down': [], 'slide-left': [] }; modals.slice().reverse().forEach(function (_ref3) { var hidden = _ref3.hidden, drawer = _ref3.drawer, drawerOffset = _ref3.drawerOffset, drawerTransitionName = _ref3.drawerTransitionName; if (!hidden) { maskHidden = false; if (drawer && drawerTransitionName) { var offsets = drawerOffsets[drawerTransitionName]; var offset = offsets[0] || 0; offsets.unshift(offset + (drawerOffset || 0)); } } }); this.drawerOffsets = drawerOffsets; this.maskHidden = maskHidden; // modals.every(({ hidden }) => hidden); this.setState({ modals: modals }); } }, { key: "mergeModals", value: function mergeModals(newModals) { var modals = this.state.modals; var map = new Map(); modals.forEach(function (modal) { if (modal.key) { map.set(modal.key, modal); } }); newModals.forEach(function (modal) { if (modal.key) { map.set(modal.key, modal); } }); this.updateModals(_toConsumableArray(map.values())); } }, { key: "findIndex", value: function findIndex(modalKey) { var modals = this.state.modals; return modals.findIndex(function (_ref4) { var key = _ref4.key; return key === modalKey; }); } }, { key: "open", value: function open(props) { var modals = this.state.modals; if (!props.key) { props.key = ModalManager.getKey(); warning(!!props.destroyOnClose, "The modal which opened has no key, please provide a key or set the `destroyOnClose` as true."); } else { var index = this.findIndex(props.key); if (index !== -1) { modals.splice(index, 1); } } modals.push(_objectSpread({}, props, { hidden: false })); this.updateModals(modals); } }, { key: "close", value: function close(props) { var modals = this.state.modals; var target = modals.find(function (_ref5) { var key = _ref5.key; return key === props.key; }); if (target) { _extends(target, props, { hidden: true }); this.updateModals(modals); } } }, { key: "update", value: function update(props) { var originModals = this.state.modals; var modals = _toConsumableArray(originModals); if (props.key) { var index = this.findIndex(props.key); if (index !== -1) { modals[index] = _objectSpread({}, modals[index], {}, props); this.updateModals(modals); } } } }, { key: "clear", value: function clear(closeByLocationChange) { var modals = this.state.modals; this.updateModals(modals.map(function (modal) { return closeByLocationChange && !modal.closeOnLocationChange ? modal : _objectSpread({}, modal, { destroyOnClose: true, hidden: true }); })); } }, { key: "getModalWidth", value: function getModalWidth(modal) { return modal && modal.style && modal.style.width || 520; } }, { key: "getComponent", value: function getComponent(mount) { var _this2 = this; var hidden = this.maskHidden, isTop = this.isTop, drawerOffsets = this.drawerOffsets, baseOffsets = this.baseOffsets; var modals = this.state.modals; var indexes = { 'slide-up': 1, 'slide-right': 1, 'slide-down': 1, 'slide-left': 1 }; var activeModal; var maskTransition = true; var items = modals.map(function (props, index) { var _props$drawerTransiti = props.drawerTransitionName, drawerTransitionName = _props$drawerTransiti === void 0 ? getConfig('drawerTransitionName') : _props$drawerTransiti, drawer = props.drawer, key = props.key, _props$transitionAppe = props.transitionAppear, transitionAppear = _props$transitionAppe === void 0 ? true : _props$transitionAppe; var style = _objectSpread({}, props.style); if (drawer && drawerTransitionName) { var i = indexes[drawerTransitionName]; indexes[drawerTransitionName] += 1; var offset = getArrayIndex(drawerOffsets[drawerTransitionName], i) + baseOffsets[drawerTransitionName]; if (offset) { switch (drawerTransitionName) { case 'slide-up': style.marginTop = offset; break; case 'slide-down': style.marginBottom = offset; break; case 'slide-left': style.marginLeft = offset; break; default: style.marginRight = offset; } } } var active = isTop && index === modals.length - 1; if (active) { activeModal = props; } if (transitionAppear === false) { maskTransition = false; } return React.createElement(Animate, { key: key, component: "div", // UED 用类名判断 className: props.drawer ? "".concat(getProPrefixCls(suffixCls), "-container-drawer") : "".concat(getProPrefixCls(suffixCls), "-container-pristine"), transitionAppear: transitionAppear, transitionName: drawer ? drawerTransitionName : 'zoom', hiddenProp: "hidden", onEnd: _this2.handleAnimationEnd }, React.createElement(Modal, _extends({ key: key, mousePosition: ModalManager.mousePosition }, props, { style: style, active: active }))); }); var animationProps = {}; if (mount && mount.ownerDocument) { var body = mount.ownerDocument.body; if (containerInstances.every(function (instance) { return instance.maskHidden; })) { animationProps.onEnd = function () { return showBodyScrollBar(body); }; } else { hideBodyScrollBar(body); } } var eventProps = {}; if (activeModal && activeModal.mask) { var _activeModal = activeModal, _activeModal$maskClos = _activeModal.maskClosable, maskClosable = _activeModal$maskClos === void 0 ? getConfig('modalMaskClosable') : _activeModal$maskClos; if (maskClosable === 'dblclick') { eventProps.onDoubleClick = this.handleMaskClick; } else { eventProps.onClick = this.handleMaskClick; } } return React.createElement(React.Fragment, null, React.createElement(Animate, _extends({ component: "", transitionAppear: true, transitionName: maskTransition ? 'fade' : undefined, hiddenProp: "hidden" }, animationProps), activeModal && activeModal.mask ? React.createElement(Mask, _extends({ style: activeModal.maskStyle, className: activeModal.maskClassName, hidden: hidden }, eventProps, { onMouseDown: stopEvent })) : React.createElement("div", { hidden: hidden })), items, !mount && React.createElement("span", { ref: this.saveMount })); } }, { key: "getContainer", value: function getContainer() { var getModalContainer = this.props.getContainer; if (typeof getModalContainer === 'function') { return getModalContainer(); } return getModalContainer; } }, { key: "render", value: function render() { var getModalContainer = this.props.getContainer; if (getModalContainer === false) { var _mount = this.state.mount; return this.getComponent(_mount); } var mount = this.getContainer(); if (mount) { return createPortal(this.getComponent(mount), mount); } return null; } }, { key: "baseOffsets", get: function get() { var _this3 = this; var offsets = { 'slide-up': 0, 'slide-right': 0, 'slide-down': 0, 'slide-left': 0 }; containerInstances.some(function (instance) { if (instance === _this3) { return true; } var drawerOffsets = instance.drawerOffsets, maskHidden = instance.maskHidden; if (!maskHidden) { offsets['slide-up'] += getArrayIndex(drawerOffsets['slide-up'], 0); offsets['slide-right'] += getArrayIndex(drawerOffsets['slide-right'], 0); offsets['slide-down'] += getArrayIndex(drawerOffsets['slide-down'], 0); offsets['slide-left'] += getArrayIndex(drawerOffsets['slide-left'], 0); } return false; }); return offsets; } }, { key: "isTop", get: function get() { var _this4 = this; var is = true; containerInstances.some(function (instance) { if (instance !== _this4 && !instance.maskHidden) { is = false; return true; } if (instance === _this4) { return true; } return false; }); return is; } }]); return ModalContainer; }(Component); ModalContainer.displayName = 'ModalContainer'; ModalContainer.defaultProps = { getContainer: getRoot }; __decorate([observable], ModalContainer.prototype, "maskHidden", void 0); __decorate([observable], ModalContainer.prototype, "drawerOffsets", void 0); __decorate([computed], ModalContainer.prototype, "baseOffsets", null); __decorate([computed], ModalContainer.prototype, "isTop", null); __decorate([action], ModalContainer.prototype, "top", null); __decorate([action], ModalContainer.prototype, "updateModals", null); ModalContainer = __decorate([observer], ModalContainer); export default ModalContainer; export function getContainer(loop) { var length = containerInstances.length; if (length) { return containerInstances[0]; } if (loop !== true) { var root = getRoot(); if (root) { render(React.createElement(ModalContainer, null), root); } return getContainer(true); } } export function open(props) { var container = getContainer(); function getCurrentContainer() { return containerInstances.includes(container) ? container : getContainer(); } function close(_x) { return _close.apply(this, arguments); } function _close() { _close = _asyncToGenerator( /*#__PURE__*/ _regeneratorRuntime.mark(function _callee2(destroy) { var _props2, _props2$onClose, onClose; return _regeneratorRuntime.wrap(function _callee2$(_context2) { while (1) { switch (_context2.prev = _context2.next) { case 0: _props2 = props, _props2$onClose = _props2.onClose, onClose = _props2$onClose === void 0 ? noop : _props2$onClose; _context2.next = 3; return onClose(); case 3: _context2.t0 = _context2.sent; if (!(_context2.t0 !== false)) { _context2.next = 6; break; } if (destroy) { getCurrentContainer().close(_objectSpread({}, props, { destroyOnClose: true })); } else { getCurrentContainer().close(props); } case 6: case "end": return _context2.stop(); } } }, _callee2); })); return _close.apply(this, arguments); } function update(newProps) { getCurrentContainer().update(_objectSpread({}, newProps, { key: props.key })); } props = _objectSpread({ __deprecate__: true, close: close, update: update }, Modal.defaultProps, {}, props); container.open(props); function show(newProps) { getCurrentContainer().open(_objectSpread({}, props, {}, newProps)); } return { close: close, open: show, update: update }; } //# sourceMappingURL=ModalContainer.js.map