UNPKG

monday-ui-react-core

Version:

Official monday.com UI resources for application development in React.js

143 lines (127 loc) 3.88 kB
/* eslint-disable react/jsx-props-no-spreading */ import React from "react"; import classnames from "classnames"; import isFunction from "lodash/isFunction"; import Dialog from "../Dialog/Dialog"; import "./Tooltip.scss"; // When last tooltip was shown in the last 1.5 second - the next tooltip will be shown immediately const IMMEDIATE_SHOW_THRESHOLD_MS = 1500; // Shared state accross multiple tooltip instances (i.e last tooltip shown time) const globalState = { lastTooltipHideTS: null, openTooltipsCount: 0 }; export default class Tooltip extends React.PureComponent { constructor(props) { super(props); this.renderTooltipContent = this.renderTooltipContent.bind(this); this.getShowDelay = this.getShowDelay.bind(this); this.onTooltipShow = this.onTooltipShow.bind(this); this.onTooltipHide = this.onTooltipHide.bind(this); this.wasShown = false; } getContainer() { return document.getElementById("tooltips-container") || document.querySelector("body"); } renderTooltipContent() { const { theme, content, paddingSize, className } = this.props; if (!content) { // don't render empty tooltip return null; } let contentValue; if (isFunction(content)) { contentValue = content(); } else if (React.isValidElement(content)) { contentValue = content; } else if (typeof content === "string" && content) { contentValue = content; } if (!contentValue) { return null; } return ( <div className={classnames( `monday-style-tooltip monday-style-tooltip-${theme} padding-size-${paddingSize}`, className )} > {contentValue} </div> ); } onTooltipShow() { if (!this.wasShown) { globalState.openTooltipsCount++; this.wasShown = true; } } onTooltipHide() { if (this.wasShown) { globalState.lastTooltipHideTS = Date.now(); globalState.openTooltipsCount--; this.wasShown = false; } } getTimeSinceLastTooltip() { if (globalState.openTooltipsCount > 0) { return 0; } return globalState.lastTooltipHideTS ? Date.now() - globalState.lastTooltipHideTS : Infinity; } getShowDelay() { const { showDelay, immediateShowDelay } = this.props; const timeSinceLastTooltip = this.getTimeSinceLastTooltip(); if ((immediateShowDelay === 0 || immediateShowDelay) && timeSinceLastTooltip < IMMEDIATE_SHOW_THRESHOLD_MS) { // showing the tooltip immediately (without animation) return { showDelay: immediateShowDelay, preventAnimation: true }; } return { showDelay, preventAnimation: false }; } render() { const { withoutDialog, moveBy, justify, children, getContainer, theme, paddingSize, tip } = this.props; if (!children) { return null; } if (withoutDialog) { return this.renderTooltipContent(); } const content = this.renderTooltipContent; const dialogProps = { ...this.props, startingEdge: justify, tooltip: tip, content, getContainer: getContainer || this.getContainer, moveBy, tooltipClassName: `monday-style-arrow monday-style-arrow-${theme} padding-size-${paddingSize}`, animationType: "expand", onDialogDidHide: this.onTooltipHide, onDialogDidShow: this.onTooltipShow, getDynamicShowDelay: this.getShowDelay }; return <Dialog {...dialogProps}>{children}</Dialog>; } } Tooltip.defaultProps = { arrowPosition: "center", // begin, center, end moveBy: { main: 4, secondary: 0 }, theme: "dark", position: "top", justify: "center", hideDelay: 0, showDelay: 300, disableDialogSlide: true, animationType: "expand", withoutDialog: false, containerSelector: "#tooltips-container", immediateShowDelay: null, tip: true };