UNPKG

@antv/t8

Version:

T8 is a text visualization solution for unstructured data within the AntV technology stack, and it is a declarative JSON Schema syntax that can be used to describe the content of data interpretation reports.

220 lines (216 loc) 9.74 kB
'use strict'; var tslib = require('tslib'); var jsxRuntime = require('preact/jsx-runtime'); var preact = require('preact'); var hooks = require('preact/hooks'); var getPrefixCls = require('../../../utils/getPrefixCls.js'); require('clarinet'); var TOOLTIP_CONTAINER_ID = 'ntv-tooltip-container'; // Create portal container. var createContainer = function () { if (document.getElementById(TOOLTIP_CONTAINER_ID)) { return document.getElementById(TOOLTIP_CONTAINER_ID); } var container = document.createElement('div'); container.className = getPrefixCls.getPrefixCls('tooltip-container'); container.id = TOOLTIP_CONTAINER_ID; document.body.appendChild(container); return container; }; var tooltipContentStyle = { position: 'absolute', zIndex: 1000, padding: '6px 8px', backgroundColor: 'rgba(0, 0, 0, 0.75)', color: '#fff', borderRadius: '4px', fontSize: '12px', maxWidth: '300px', wordWrap: 'break-word', boxShadow: '0 3px 6px -4px rgba(0, 0, 0, 0.12), 0 6px 16px 0 rgba(0, 0, 0, 0.08)', fontFamily: 'PingFang SC, Microsoft YaHei, Arial, sans-serif', }; var arrowStyle = { position: 'absolute', width: '0', height: '0', borderStyle: 'solid', borderWidth: '4px', }; /** * Tooltip Component * * A simple, lightweight tooltip component that displays tips when users interact with elements * * @example * <Tooltip title="This is a tip"> * <button>Hover to see</button> * </Tooltip> */ var Tooltip = function (_a) { var title = _a.title, propsVisible = _a.visible, _b = _a.defaultVisible, defaultVisible = _b === void 0 ? false : _b, children = _a.children, _c = _a.placement, placement = _c === void 0 ? 'top' : _c, _d = _a.trigger, trigger = _d === void 0 ? 'hover' : _d, style = _a.style, className = _a.className, _e = _a.showArrow, showArrow = _e === void 0 ? true : _e, onVisibleChange = _a.onVisibleChange, _f = _a.offset, offset = _f === void 0 ? placement === 'top' || placement === 'bottom' ? 4 : 8 : _f, _g = _a.mouseEnterDelay, mouseEnterDelay = _g === void 0 ? 100 : _g, _h = _a.mouseLeaveDelay, mouseLeaveDelay = _h === void 0 ? 100 : _h; // Store element references. var triggerChildrenRef = hooks.useRef(null); var tooltipRef = hooks.useRef(null); var containerRef = hooks.useRef(null); var enterTimer = hooks.useRef(null); var leaveTimer = hooks.useRef(null); var tooltipInnerRef = hooks.useRef(null); // Control visibility. var _j = hooks.useState(defaultVisible), visible = _j[0], setVisible = _j[1]; // if visible is provided, use it as the final visible state. var finalVisible = propsVisible !== undefined ? propsVisible : visible; // Ensure container is created only once. hooks.useEffect(function () { if (!containerRef.current) { containerRef.current = createContainer(); } // clear container when unmount. return function () { if (containerRef.current && containerRef.current.parentElement === document.body) { document.body.removeChild(containerRef.current); containerRef.current = null; } // Clear potential timers if (enterTimer.current) window.clearTimeout(enterTimer.current); if (leaveTimer.current) window.clearTimeout(leaveTimer.current); }; }, []); hooks.useEffect(function () { // render tooltip when visible or title changes. renderTooltip(); // // render title to tooltip-inner // if (finalVisible) { // renderTitle(); // } }, [finalVisible, title]); // Calculate tooltip position hooks.useEffect(function () { if (finalVisible && triggerChildrenRef.current && tooltipRef.current) { var triggerRect = triggerChildrenRef.current.getBoundingClientRect(); var tooltipRect = tooltipRef.current.getBoundingClientRect(); var top_1 = 0; var left = 0; var arrowStyle_1 = {}; // Calculate coordinates based on placement switch (placement) { case 'top': top_1 = triggerRect.top - tooltipRect.height - offset; left = triggerRect.left + (triggerRect.width - tooltipRect.width) / 2; arrowStyle_1 = { bottom: '-8px', left: '50%', transform: 'translateX(-50%)', borderColor: 'rgba(0, 0, 0, 0.75) transparent transparent transparent', }; break; case 'bottom': top_1 = triggerRect.bottom + offset; left = triggerRect.left + (triggerRect.width - tooltipRect.width) / 2; arrowStyle_1 = { top: '-8px', left: '50%', transform: 'translateX(-50%)', borderColor: 'transparent transparent rgba(0, 0, 0, 0.75) transparent', }; break; case 'left': top_1 = triggerRect.top + (triggerRect.height - tooltipRect.height) / 2; left = triggerRect.left - tooltipRect.width - offset; arrowStyle_1 = { right: '-8px', top: '50%', transform: 'translateY(-50%)', borderColor: 'transparent transparent transparent rgba(0, 0, 0, 0.75)', }; break; case 'right': top_1 = triggerRect.top + (triggerRect.height - tooltipRect.height) / 2; left = triggerRect.right + offset; arrowStyle_1 = { left: '-8px', top: '50%', transform: 'translateY(-50%)', borderColor: 'transparent rgba(0, 0, 0, 0.75) transparent transparent', }; break; } // Apply calculated position tooltipRef.current.style.top = "".concat(top_1 + window.scrollY, "px"); tooltipRef.current.style.left = "".concat(left + window.scrollX, "px"); // If showing arrow, set arrow style if (showArrow && tooltipRef.current.firstChild) { var arrowElement = tooltipRef.current.firstChild; Object.assign(arrowElement.style, arrowStyle_1); } } }, [finalVisible, placement, offset, showArrow]); // Handle visibility change var handleVisibleChange = function (newVisible) { if (propsVisible === undefined) { setVisible(newVisible); } onVisibleChange === null || onVisibleChange === void 0 ? void 0 : onVisibleChange(newVisible); }; // Mouse enter handler var handleMouseEnter = function () { if (leaveTimer.current) { window.clearTimeout(leaveTimer.current); leaveTimer.current = null; } if (!finalVisible) { enterTimer.current = window.setTimeout(function () { handleVisibleChange(true); }, mouseEnterDelay); } }; // Mouse leave handler var handleMouseLeave = function () { if (enterTimer.current) { window.clearTimeout(enterTimer.current); enterTimer.current = null; } if (finalVisible) { leaveTimer.current = window.setTimeout(function () { handleVisibleChange(false); }, mouseLeaveDelay); } }; // Click handler var handleClick = function () { handleVisibleChange(!finalVisible); }; // Add event handlers based on trigger type var triggerProps = {}; if (trigger === 'hover') { triggerProps.onMouseEnter = handleMouseEnter; triggerProps.onMouseLeave = handleMouseLeave; } else if (trigger === 'click') { triggerProps.onClick = handleClick; } // Assign ref to the child element triggerProps.ref = triggerChildrenRef; triggerProps.className = getPrefixCls.getPrefixCls('tooltip-trigger'); // Render tooltip content var renderTooltip = function () { var container = containerRef.current; var tooltipContent = !finalVisible || !title ? null : (jsxRuntime.jsxs("div", { ref: tooltipRef, className: "".concat(getPrefixCls.getPrefixCls('tooltip'), " ").concat(className || ''), style: tslib.__assign(tslib.__assign({}, tooltipContentStyle), style), onMouseEnter: handleMouseEnter, onMouseLeave: handleMouseLeave, children: [showArrow && jsxRuntime.jsx("div", { className: getPrefixCls.getPrefixCls('tooltip-arrow'), style: arrowStyle }), jsxRuntime.jsx("div", { className: getPrefixCls.getPrefixCls('tooltip-inner'), id: "tooltip-inner", ref: tooltipInnerRef })] })); preact.render(tooltipContent, container); // apply real dom to tooltip-inner when visible. if (tooltipInnerRef.current && finalVisible) { if (typeof title === 'string' || typeof title === 'number') { tooltipInnerRef.current.appendChild(document.createTextNode(String(title))); } else if (title instanceof HTMLElement) { tooltipInnerRef.current.appendChild(title); } } }; // Return the modified child and tooltip return jsxRuntime.jsx("span", tslib.__assign({}, triggerProps, { children: children })); }; exports.Tooltip = Tooltip; //# sourceMappingURL=Tooltip.js.map