@nomios/web-uikit
Version:
Nomios' living web UIKit
162 lines (137 loc) • 4.65 kB
JavaScript
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; }
import React, { Component, cloneElement } from 'react';
import { findDOMNode } from 'react-dom';
import PropTypes from 'prop-types';
import { Manager, Reference } from 'react-popper';
const DEFAULT_HOVER_DELAY = 200;
class TooltipTrigger extends Component {
constructor() {
super();
_defineProperty(this, "defaultEventProps", null);
_defineProperty(this, "state", {
open: false
});
_defineProperty(this, "renderReference", ({
ref
}) => {
this.setReferenceRef = ref;
const {
children: trigger
} = this.props;
const {
open
} = this.state;
if (typeof trigger === 'function') {
const element = trigger({
state: open,
open: this.handleOpen,
cancelOpen: this.handleCancelOpen,
close: this.handleClose,
toggle: this.handleToggle,
defaultEventProps: this.defaultEventProps
});
return cloneElement(element, {
ref: this.storeReferenceRef
});
}
return cloneElement(trigger, { ...this.defaultEventProps,
ref: this.storeReferenceRef
});
});
_defineProperty(this, "renderTooltip", () => {
const {
open
} = this.state;
const {
tooltip
} = this.props;
return cloneElement(tooltip, {
ref: this.storeTooltipRef,
open,
onRequestCancelClose: this.handleRequestCancelClose,
onRequestClose: this.handleRequestClose
});
});
_defineProperty(this, "storeReferenceRef", ref => {
this.reference = ref;
const referenceNode = findDOMNode(this.reference);
this.setReferenceRef && this.setReferenceRef(referenceNode);
this.tooltip && this.tooltip.setReferenceNode(referenceNode);
});
_defineProperty(this, "storeTooltipRef", ref => {
this.tooltip = ref;
this.tooltip && this.tooltip.setReferenceNode(findDOMNode(this.reference));
});
_defineProperty(this, "handleOpen", delay => {
clearTimeout(this.openCloseTimeoutId);
this.pendingClose = false;
this.openCloseTimeoutId = setTimeout(() => {
this.setState({
open: true
});
}, delay);
});
_defineProperty(this, "handleCancelOpen", () => {
clearTimeout(this.openCloseTimeoutId);
});
_defineProperty(this, "handleClose", delay => {
this.pendingClose = true;
clearTimeout(this.openCloseTimeoutId);
this.openCloseTimeoutId = setTimeout(() => {
this.pendingClose = false;
this.setState({
open: false
});
}, delay);
});
_defineProperty(this, "handleToggle", delay => {
if (this.state.open) {
this.handleClose(delay);
} else {
this.handleOpen(delay);
}
});
_defineProperty(this, "handleRequestCancelClose", () => {
clearTimeout(this.openCloseTimeoutId);
});
_defineProperty(this, "handleRequestClose", reason => {
const isMouseLeave = reason === 'mouseLeave'; // If the reason to close is `mouseLeave`, only close it if there's a pending close
// We only want to "override" de trigger for `escapePress` / `clickOutside`
if (isMouseLeave && !this.pendingClose) {
return;
}
this.pendingClose = false;
clearTimeout(this.openCloseTimeoutId);
this.openCloseTimeoutId = setTimeout(() => {
this.setState({
open: false
});
}, isMouseLeave ? DEFAULT_HOVER_DELAY : 0);
});
this.defaultEventProps = {
onClick: this.handleOpen,
onMouseEnter: () => this.handleOpen(DEFAULT_HOVER_DELAY),
onMouseLeave: () => this.handleClose(DEFAULT_HOVER_DELAY)
};
}
componentDidUpdate(prevProps, prevState) {
if (this.state.open !== prevState.open) {
this.props.onChange && this.props.onChange(this.state.open);
}
}
componentWillUnmount() {
clearTimeout(this.openCloseTimeoutId);
if (this.state.open) {
this.props.onChange && this.props.onChange(false);
}
}
render() {
return React.createElement(Manager, null, React.createElement(Reference, null, this.renderReference), this.renderTooltip());
}
}
TooltipTrigger.propTypes = {
tooltip: PropTypes.element.isRequired,
children: PropTypes.oneOfType([PropTypes.element, PropTypes.func]).isRequired,
onChange: PropTypes.func
};
export default TooltipTrigger;