UNPKG

zarm-web

Version:
547 lines (450 loc) 20.7 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = void 0; var _react = _interopRequireDefault(require("react")); var _reactDom = require("react-dom"); var _classnames2 = _interopRequireDefault(require("classnames")); var _events = _interopRequireDefault(require("../utils/events")); var _throttle = _interopRequireDefault(require("../utils/throttle")); var _dom = _interopRequireDefault(require("../utils/dom")); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); } function _extends() { _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; }; return _extends.apply(this, arguments); } function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; } function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(source, true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(source).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; } 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; } function _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; } function _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; 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 (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } return _assertThisInitialized(self); } function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; } function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); } 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); } } function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; } function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); } function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); } function getOffsetElem(elem) { var parentElem = elem.parentNode; while (parentElem) { if (parentElem instanceof HTMLElement) { if (parentElem.style.position === 'fixed' || window.getComputedStyle(parentElem).position === 'fixed' || parentElem === document.body) { return parentElem; } parentElem = parentElem.parentNode; } else { break; } } return document.body; } // 获取元素坐标 function getElemPosition(elem) { var relativeElem = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : document.body; var parentElem = elem.offsetParent; var position = { top: elem.offsetTop, left: elem.offsetLeft }; while (relativeElem.contains(parentElem)) { if (parentElem instanceof HTMLElement) { if (relativeElem === parentElem) { return position; } position.top += parentElem.offsetTop; position.left += parentElem.offsetLeft; parentElem = parentElem.offsetParent; } } return position; } // todo [首次不创建] var placementMap = { bottomLeft: 5, bottomCenter: 9, bottomRight: 17, topLeft: 6, topCenter: 10, topRight: 18 }; var defaultProps = { visible: false, isRadius: false, hideOnClick: true, prefixCls: 'ui-dropdown', placement: 'bottomLeft', trigger: 'click', disabled: false, zIndex: 2018 }; var mountedInstance = new Set(); var Dropdown = /*#__PURE__*/ function (_React$Component) { _inherits(Dropdown, _React$Component); _createClass(Dropdown, null, [{ key: "hide", // 隐藏全部的Dropdown value: function hide() { mountedInstance.forEach(function (instance) { instance.props.onVisibleChange(false); }); } // 显示全部的Dropdown 除了disable }, { key: "show", value: function show() { mountedInstance.forEach(function (instance) { instance.props.onVisibleChange(true); }); } // 重新计算Dropdown定位 }, { key: "reposition", value: function reposition() { mountedInstance.forEach(function (instance) { instance.reposition(); }); } // 用于存储已生成的全部实例的Set // private static mountedInstance: Set<Dropdown> = new Set(); // 根据定位点计算定位信息 }, { key: "calcPosition", value: function calcPosition() { var placement = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 'bottomLeft'; var width = arguments.length > 1 ? arguments[1] : undefined; var height = arguments.length > 2 ? arguments[2] : undefined; var dropWidth = arguments.length > 3 ? arguments[3] : undefined; var dropHeight = arguments.length > 4 ? arguments[4] : undefined; var top = 0; var left = 0; var placementCode = placementMap[placement]; if (placementCode & 1) { top = height; } else if (placementCode & 2) { top = -dropHeight; } if (placementCode & 8) { left = (width - dropWidth) / 2; } else if (placementCode & 16) { left = width - dropWidth; } return { top: top, left: left }; } }, { key: "createDivBox", value: function createDivBox() { var div = document.createElement('div'); div.style.setProperty('position', 'absolute'); div.style.setProperty('left', '0'); div.style.setProperty('top', '0'); div.style.setProperty('width', 'auto'); return div; } }]); function Dropdown(props) { var _this; _classCallCheck(this, Dropdown); _this = _possibleConstructorReturn(this, _getPrototypeOf(Dropdown).call(this, props)); _this.state = { visible: _this.props.visible, positionInfo: { left: 0, top: 0 }, animationState: null, // eslint-disable-next-line react/no-unused-state animationProps: null }; _this.DropdownContentEvent = {}; _this.triggerEvent = {}; _this.onWindowResize = void 0; _this.onParentScroll = void 0; _this.div = Dropdown.createDivBox(); _this.triggerBox = void 0; _this.DropdownContent = void 0; _this.popContainer = void 0; _this.scrollParent = void 0; _this.isHoverOnDropContent = false; _this.hiddenTimer = void 0; _this.triggerBoxOffsetHeight = void 0; _this.setEventObject = function (triggerType) { if (triggerType === 'hover') { _this.DropdownContentEvent.onMouseLeave = _this.onDropdownContentMouseLeave; _this.DropdownContentEvent.onMouseEnter = _this.onDropdownContentMouseEnter; _this.triggerEvent.onMouseEnter = _this.onTrigger; _this.triggerEvent.onMouseLeave = _this.onTrigger; } else if (triggerType === 'click') { _this.triggerEvent.onClick = _this.onTrigger; } else if (triggerType === 'contextMenu') { _this.triggerEvent.onContextMenu = _this.onTrigger; } }; _this.onTrigger = function (e) { // 禁用状态不做任何处理 if (_this.props.disabled === true) { return; } var type = e.type; if (type === 'click') { _this.props.onVisibleChange(!_this.props.visible); } else if (type === 'contextmenu') { e.preventDefault(); _this.props.onVisibleChange(!_this.props.visible); } else if (type === 'mouseenter') { if (_this.props.visible === false) { _this.props.onVisibleChange(true); } else if (_this.hiddenTimer) { clearTimeout(_this.hiddenTimer); } } else if (type === 'mouseleave') { // 缓冲一点一时间给间隙 _this.hiddenTimer = setTimeout(function () { // 若当前鼠标在弹出层上 则不消失 if (_this.isHoverOnDropContent === false) { _this.props.onVisibleChange(false); } }, 300); } }; _this.onDropdownContentMouseEnter = function () { // 重新放置时候取消隐藏 if (_this.hiddenTimer) { clearTimeout(_this.hiddenTimer); } if (_this.isHoverOnDropContent === false) { _this.isHoverOnDropContent = true; } }; _this.onDropdownContentMouseLeave = function () { _this.isHoverOnDropContent = false; // 给消失一点缓冲时间 _this.hiddenTimer = setTimeout(function () { _this.props.onVisibleChange(false); }, 300); }; _this.onDocumentClick = function (e) { var _this$props = _this.props, hideOnClick = _this$props.hideOnClick, onVisibleChange = _this$props.onVisibleChange; if (_this.props.disabled === true || _this.state.visible === false) { return; } var target = e.target; // eslint-disable-next-line no-empty if (_this.div.contains(target) || _this.triggerBox.contains(target)) {} else { // eslint-disable-next-line no-lonely-if if (hideOnClick) { onVisibleChange(false); } } }; _this.reposition = function () { if (!_this.state.visible || _this.props.disabled) { return; } var _this$getDropdownPosi = _this.getDropdownPosition(_this.props.placement), left = _this$getDropdownPosi.left, top = _this$getDropdownPosi.top; if (left === _this.state.positionInfo.left && top === _this.state.positionInfo.top) { return; } _this.setState({ positionInfo: { left: left, top: top } }); }; _this.onAniEnd = function (e) { if (e.type.toLowerCase().endsWith('animationend')) { _this.setState({ visible: _this.props.visible, animationState: null }); } }; _this.setEventObject(props.trigger); _this.onWindowResize = (0, _throttle.default)(_this.reposition, 300); _this.onParentScroll = _this.reposition; return _this; } _createClass(Dropdown, [{ key: "componentDidMount", value: function componentDidMount() { var _this$props2 = this.props, getPopupContainer = _this$props2.getPopupContainer, visible = _this$props2.visible, placement = _this$props2.placement; if (typeof getPopupContainer === 'function') { this.popContainer = getPopupContainer(); this.popContainer.style.position = 'relative'; } else { this.popContainer = getOffsetElem(this.triggerBox); } this.popContainer.appendChild(this.div); if (visible) { var _this$getDropdownPosi2 = this.getDropdownPosition(placement), left = _this$getDropdownPosi2.left, top = _this$getDropdownPosi2.top; this.setState({ positionInfo: { left: left, top: top } }); } this.scrollParent = _dom.default.getScrollParent(this.triggerBox); _events.default.on(document, 'click', this.onDocumentClick); _events.default.on(window, 'resize', this.onWindowResize); _events.default.on(this.scrollParent, 'scroll', this.onParentScroll); // 存储当前实例,方便静态方法统一处理 mountedInstance.add(this); this.triggerBoxOffsetHeight = this.triggerBox.offsetHeight; } }, { key: "componentWillReceiveProps", value: function componentWillReceiveProps(nextProps) { var _this2 = this; var _this$props3 = this.props, visible = _this$props3.visible, trigger = _this$props3.trigger; if (nextProps.visible === visible) { return; } if (nextProps.trigger !== trigger) { this.setEventObject(nextProps.trigger); } if (nextProps.visible) { this.enter(function () { if (nextProps.visible) { _this2.setState({ positionInfo: _this2.getDropdownPosition(nextProps.placement) }); } }); } else { this.leave(); } } }, { key: "componentDidUpdate", value: function componentDidUpdate() { var height = this.triggerBox.offsetHeight; if (height !== this.triggerBoxOffsetHeight) { this.reposition(); this.triggerBoxOffsetHeight = height; } } }, { key: "componentWillUnmount", value: function componentWillUnmount() { var _this3 = this; _events.default.off(document, 'click', this.onDocumentClick); _events.default.off(window, 'click', this.onWindowResize); _events.default.off(this.scrollParent, 'scroll', this.onParentScroll); mountedInstance.delete(this); setTimeout(function () { _this3.popContainer.removeChild(_this3.div); }); } // 根据trigger方式不同绑定事件 }, { key: "getDropdownPosition", // 获取元素的定位信息 value: function getDropdownPosition() { var placement = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 'bottomLeft'; var rectInfo = getElemPosition(this.triggerBox, this.popContainer); var _this$DropdownContent = this.DropdownContent, offsetWidth = _this$DropdownContent.offsetWidth, offsetHeight = _this$DropdownContent.offsetHeight; var computerStyle = window.getComputedStyle(this.DropdownContent); var marginTop = parseFloat(this.DropdownContent.style.marginTop || computerStyle.marginTop || '0'); var marginLeft = parseFloat(this.DropdownContent.style.marginLeft || computerStyle.marginLeft || '0'); var _Dropdown$calcPositio = Dropdown.calcPosition(placement, this.triggerBox.offsetWidth, this.triggerBox.offsetHeight, offsetWidth, offsetHeight), top = _Dropdown$calcPositio.top, left = _Dropdown$calcPositio.left; var offset = placement.startsWith('bottom') ? 5 : -5; var scrollLeft = 0; var scrollTop = 0; if (this.scrollParent !== this.popContainer && this.popContainer.contains(this.scrollParent)) { scrollLeft = _dom.default.getScrollLeftValue(this.scrollParent); scrollTop = _dom.default.getScrollTopValue(this.scrollParent); } return { left: rectInfo.left + left - marginLeft - scrollLeft, top: rectInfo.top + top - marginTop + offset - scrollTop }; } }, { key: "enter", value: function enter(callback) { this.setState({ visible: true, animationState: 'enter' }, callback); } }, { key: "leave", value: function leave() { this.setState({ visible: true, animationState: 'leave' }); } }, { key: "render", value: function render() { var _classnames, _this4 = this; var _this$props4 = this.props, disabled = _this$props4.disabled, children = _this$props4.children, overlay = _this$props4.overlay, className = _this$props4.className, trigger = _this$props4.trigger, prefixCls = _this$props4.prefixCls, style = _this$props4.style, isRadius = _this$props4.isRadius, _this$props4$placemen = _this$props4.placement, placement = _this$props4$placemen === void 0 ? 'bottomLeft' : _this$props4$placemen, zIndex = _this$props4.zIndex, notRenderInDisabledMode = _this$props4.notRenderInDisabledMode, visible = _this$props4.visible, hideOnClick = _this$props4.hideOnClick, onVisibleChange = _this$props4.onVisibleChange, getPopupContainer = _this$props4.getPopupContainer, triggerBoxStyle = _this$props4.triggerBoxStyle, others = _objectWithoutProperties(_this$props4, ["disabled", "children", "overlay", "className", "trigger", "prefixCls", "style", "isRadius", "placement", "zIndex", "notRenderInDisabledMode", "visible", "hideOnClick", "onVisibleChange", "getPopupContainer", "triggerBoxStyle"]); var _this$state = this.state, positionInfo = _this$state.positionInfo, animationState = _this$state.animationState, stateVisible = _this$state.visible; // 根据placement判断向上动画还是向下动画 var animationProps = placementMap[placement] & 1 ? 'scaleDown' : 'scaleUp'; var cls = (0, _classnames2.default)((_classnames = {}, _defineProperty(_classnames, prefixCls, true), _defineProperty(_classnames, "radius", 'radius' in this.props || isRadius), _defineProperty(_classnames, className, !!className), _defineProperty(_classnames, "".concat(animationProps, "-").concat(animationState), !!animationState), _classnames)); var dropdownBoxStyle = _objectSpread({ minWidth: this.triggerBox && this.triggerBox.offsetWidth || 0 }, style, {}, positionInfo, { position: 'absolute', animationDuration: '300ms', // eslint-disable-next-line no-nested-ternary display: disabled ? 'none' : stateVisible ? 'block' : 'none', overflow: 'hidden', zIndex: zIndex }); return _react.default.createElement(_react.default.Fragment, null, _react.default.createElement("div", _extends({ className: "".concat(prefixCls, "-trigger-box"), style: triggerBoxStyle, ref: function ref(e) { _this4.triggerBox = e; } }, this.triggerEvent), children), (0, _reactDom.createPortal)(_react.default.createElement("div", _extends({ onAnimationEnd: this.onAniEnd, className: cls, ref: function ref(e) { _this4.DropdownContent = e; }, style: dropdownBoxStyle }, others, this.DropdownContentEvent), notRenderInDisabledMode && disabled ? null : overlay), this.div)); } }]); return Dropdown; }(_react.default.Component); exports.default = Dropdown; Dropdown.defaultProps = defaultProps;