@dnb/eufemia
Version:
DNB Eufemia Design System UI Library
123 lines (122 loc) • 3.76 kB
JavaScript
"use client";
import _extends from "@babel/runtime/helpers/esm/extends";
import React from 'react';
import ReactDOM from 'react-dom';
import { makeUniqueId, warn } from '../../shared/component-helper';
import TooltipContainer from './TooltipContainer';
import { useTheme } from '../../shared';
import { getThemeClasses } from '../../shared/Theme';
let tooltipPortal;
if (typeof globalThis !== 'undefined') {
globalThis.tooltipPortal = globalThis.tooltipPortal || {};
tooltipPortal = globalThis.tooltipPortal;
} else {
tooltipPortal = {};
}
function TooltipPortal(props) {
var _tooltipPortal$id3;
const {
active,
targetElement,
hideDelay,
keepInDOM,
noAnimation,
children
} = props;
const [isMounted, setIsMounted] = React.useState(false);
const [isActive, setIsActive] = React.useState(active);
const [id] = React.useState(() => makeUniqueId());
const isInDOM = React.useRef(false);
const theme = useTheme();
const makePortal = () => {
if (!tooltipPortal[id]) {
tooltipPortal[id] = {
count: 0,
node: createRootElement(theme)
};
}
};
const clearTimers = () => {
var _tooltipPortal$id, _tooltipPortal$id2;
clearTimeout((_tooltipPortal$id = tooltipPortal[id]) === null || _tooltipPortal$id === void 0 ? void 0 : _tooltipPortal$id.delayTimeout);
clearTimeout((_tooltipPortal$id2 = tooltipPortal[id]) === null || _tooltipPortal$id2 === void 0 ? void 0 : _tooltipPortal$id2.hiddenTimeout);
};
const removeFromDOM = hide => {
if (isActive && hide) {
return;
}
const ref = tooltipPortal[id];
if (ref !== null && ref !== void 0 && ref.node) {
ref.count--;
if (ref.count <= 0) {
delete tooltipPortal[id];
}
}
};
React.useEffect(() => {
setIsMounted(true);
clearTimers();
if (active) {
makePortal();
setIsActive(true);
isInDOM.current = true;
if (!isMounted) {
tooltipPortal[id].count++;
}
} else if (!active && isMounted) {
const delayRender = () => {
setIsActive(false);
};
const delayHidden = () => {
isInDOM.current = false;
removeFromDOM(true);
};
if (noAnimation || globalThis.IS_TEST) {
delayRender();
delayHidden();
} else if (tooltipPortal[id]) {
const delay = parseFloat(String(hideDelay));
tooltipPortal[id].delayTimeout = setTimeout(delayRender, delay);
tooltipPortal[id].hiddenTimeout = setTimeout(delayHidden, delay + 300);
}
}
return clearTimers;
}, [children, active, id, hideDelay, noAnimation]);
React.useEffect(() => {
if (keepInDOM) {
makePortal();
}
return removeFromDOM;
}, []);
const root = (_tooltipPortal$id3 = tooltipPortal[id]) === null || _tooltipPortal$id3 === void 0 ? void 0 : _tooltipPortal$id3.node;
if (root) {
return ReactDOM.createPortal(isInDOM.current || keepInDOM ? React.createElement(TooltipContainer, _extends({}, props, {
targetElement: targetElement,
active: isActive
}), children) : null, root);
}
return null;
}
export default TooltipPortal;
const createRootElement = (theme, className = null) => {
if (!className) {
className = 'dnb-tooltip__portal';
}
try {
const element = document.querySelector(`.${className}`);
if (element) {
return element;
}
const elem = document.createElement('div');
elem.classList.add(className);
elem.classList.add('dnb-core-style');
if (theme) {
elem.classList.add.call(elem.classList, ...getThemeClasses(theme).split(' '));
}
document.body.appendChild(elem);
return elem;
} catch (e) {
warn(e);
}
};
//# sourceMappingURL=TooltipPortal.js.map