chowa
Version:
UI component library based on React
184 lines (183 loc) • 5.99 kB
JavaScript
/**
* @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;