UNPKG

chowa

Version:

UI component library based on React

184 lines (183 loc) 5.99 kB
/** * @license chowa v1.1.3 * * Copyright (c) Chowa Techonlogies Co.,Ltd.(http://www.chowa.cn). * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const React = require("react"); const ReactDom = require("react-dom"); const resize_observer_polyfill_1 = require("resize-observer-polyfill"); const utils_1 = require("../utils"); class OverlayTrigger extends React.PureComponent { constructor(props) { super(props); this.state = { isDraging: false }; [ 'onClickHandler', 'onMouseEnterHandler', 'onMouseLeaveHandler', 'onFocusHandler', 'onBlurHandler', 'onContextMenuHandler', 'onMouseDownHandler', 'onDraging', 'onDragEnd', 'updateVisible', 'autoBindExternalListener' ].forEach((fn) => { this[fn] = this[fn].bind(this); }); } componentDidMount() { this.triggerElement = ReactDom.findDOMNode(this); this.props.setTriggerElement(this.triggerElement); this.resizeObserver = new resize_observer_polyfill_1.default(this.props.updateDropPosition); this.resizeObserver.observe(this.triggerElement); if (this.props.visible) { this.autoBindExternalListener(); } } autoBindExternalListener() { const { visible, action } = this.props; if (action !== 'click' && action !== 'contextMenu') { return; } if (visible) { utils_1.doms.on(document.body, 'mousedown', this.props.externalMouseDownListener); } else { utils_1.doms.off(document.body, 'mousedown', this.props.externalMouseDownListener); } } componentWillUnmount() { if (this.props.visible) { utils_1.doms.off(document.body, 'mousedown', this.props.externalMouseDownListener); } this.resizeObserver.unobserve(this.triggerElement); this.resizeObserver.disconnect(); } componentDidUpdate(preProps) { if (preProps.visible !== this.props.visible) { this.autoBindExternalListener(); } } updateVisible(v) { const { onVisibleChange } = this.props; const { isDraging } = this.state; if (isDraging && !v) { return; } onVisibleChange(v); } onDraging() { this.props.updateDropPosition(); } onDragEnd(e) { const targetNode = e.target; this.setState({ isDraging: false }, () => { if (targetNode !== this.triggerElement && !this.triggerElement.contains(targetNode)) { this.updateVisible(false); } utils_1.doms.off(document.body, 'mousemove', this.onDraging); utils_1.doms.off(document.body, 'mouseup', this.onDragEnd); }); } onMouseDownHandler(e) { const { children } = this.props; const { onMouseDown } = children.props; this.setState({ isDraging: true }, () => { utils_1.doms.on(document.body, 'mousemove', this.onDraging); utils_1.doms.on(document.body, 'mouseup', this.onDragEnd); }); if (onMouseDown) { onMouseDown(e); } } onClickHandler(e) { const { children, action, visible } = this.props; const { onClick } = children.props; if (onClick) { onClick(e); } if (action === 'click') { this.updateVisible(!visible); } } onContextMenuHandler(e) { const { children, action, visible } = this.props; const { onContextMenu } = children.props; if (onContextMenu) { onContextMenu(e); } if (action === 'contextMenu') { this.updateVisible(!visible); } e.preventDefault(); } onMouseEnterHandler(e) { const { children, action } = this.props; const { onMouseEnter } = children.props; if (onMouseEnter) { onMouseEnter(e); } if (action === 'hover') { this.updateVisible(true); } } onMouseLeaveHandler(e) { const { children, action } = this.props; const { onMouseLeave } = children.props; if (onMouseLeave) { onMouseLeave(e); } if (action === 'hover') { this.updateVisible(false); } } onFocusHandler(e) { const { children, action } = this.props; const { onFocus } = children.props; if (onFocus) { onFocus(e); } if (action === 'focus') { this.updateVisible(true); } } onBlurHandler(e) { const { children, action } = this.props; const { onBlur } = children.props; if (onBlur) { onBlur(e); } if (action === 'focus') { this.updateVisible(false); } } render() { const { children, disabled, action } = this.props; if (!utils_1.isReactElement(children)) { throw new Error('Overlay.Trigger elements must be wrapped in an enclosing tag'); } return React.cloneElement(children, { onClick: disabled ? null : this.onClickHandler, onMouseEnter: disabled ? null : this.onMouseEnterHandler, onMouseLeave: disabled ? null : this.onMouseLeaveHandler, onFocus: disabled ? null : this.onFocusHandler, onBlur: disabled ? null : this.onBlurHandler, onContextMenu: disabled ? null : this.onContextMenuHandler, onMouseDown: (disabled || action !== 'hover') ? null : this.onMouseDownHandler }); } } exports.default = OverlayTrigger;