react-tooltip
Advanced tools
Comparing version 5.15.0 to 5.16.0-beta.10410.0
@@ -150,2 +150,7 @@ import React, { ElementType, ReactNode, CSSProperties, PropsWithChildren } from 'react'; | ||
export { ChildrenType, DataAttribute, EventsType, IPosition, ITooltipController as ITooltip, ITooltipWrapper, Middleware, PlacesType, PositionStrategy, TooltipController as Tooltip, TooltipProvider, TooltipWrapper, VariantType, WrapperType }; | ||
declare function removeStyle({ type, id, }: { | ||
type?: string; | ||
id?: string; | ||
}): void; | ||
export { ChildrenType, DataAttribute, EventsType, IPosition, ITooltipController as ITooltip, ITooltipWrapper, Middleware, PlacesType, PositionStrategy, TooltipController as Tooltip, TooltipProvider, TooltipWrapper, VariantType, WrapperType, removeStyle }; |
@@ -9,996 +9,1112 @@ | ||
(function (global, factory) { | ||
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('react'), require('classnames'), require('@floating-ui/dom')) : | ||
typeof define === 'function' && define.amd ? define(['exports', 'react', 'classnames', '@floating-ui/dom'], factory) : | ||
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.ReactTooltip = {}, global.React, global.classNames, global.FloatingUIDOM)); | ||
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('react'), require('classnames'), require('@floating-ui/dom')) : | ||
typeof define === 'function' && define.amd ? define(['exports', 'react', 'classnames', '@floating-ui/dom'], factory) : | ||
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.ReactTooltip = {}, global.React, global.classNames, global.FloatingUIDOM)); | ||
})(this, (function (exports, React, classNames, dom) { 'use strict'; | ||
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; } | ||
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; } | ||
var React__default = /*#__PURE__*/_interopDefaultLegacy(React); | ||
var classNames__default = /*#__PURE__*/_interopDefaultLegacy(classNames); | ||
var React__default = /*#__PURE__*/_interopDefaultLegacy(React); | ||
var classNames__default = /*#__PURE__*/_interopDefaultLegacy(classNames); | ||
function styleInject(css, ref) { | ||
if ( ref === void 0 ) ref = {}; | ||
var insertAt = ref.insertAt; | ||
// This is the ID for the core styles of ReactTooltip | ||
const REACT_TOOLTIP_CORE_STYLES_ID = 'react-tooltip-core-styles'; | ||
// This is the ID for the visual styles of ReactTooltip | ||
const REACT_TOOLTIP_BASE_STYLES_ID = 'react-tooltip-base-styles'; | ||
function injectStyle({ css, id = REACT_TOOLTIP_BASE_STYLES_ID, type = 'base', ref, }) { | ||
if (type === 'core' && process.env.REACT_TOOLTIP_DISABLE_CORE_STYLES) { | ||
return; | ||
} | ||
if (type !== 'core' && process.env.REACT_TOOLTIP_DISABLE_BASE_STYLES) { | ||
return; | ||
} | ||
if (type === 'core') { | ||
// eslint-disable-next-line no-param-reassign | ||
id = REACT_TOOLTIP_CORE_STYLES_ID; | ||
} | ||
if (!ref) { | ||
// eslint-disable-next-line no-param-reassign | ||
ref = {}; | ||
} | ||
const { insertAt } = ref; | ||
if (!css || typeof document === 'undefined' || document.getElementById(id)) { | ||
return; | ||
} | ||
const head = document.head || document.getElementsByTagName('head')[0]; | ||
// eslint-disable-next-line @typescript-eslint/no-explicit-any | ||
const style = document.createElement('style'); | ||
style.id = id; | ||
style.type = 'text/css'; | ||
if (insertAt === 'top') { | ||
if (head.firstChild) { | ||
head.insertBefore(style, head.firstChild); | ||
} | ||
else { | ||
head.appendChild(style); | ||
} | ||
} | ||
else { | ||
head.appendChild(style); | ||
} | ||
if (style.styleSheet) { | ||
style.styleSheet.cssText = css; | ||
} | ||
else { | ||
style.appendChild(document.createTextNode(css)); | ||
} | ||
} | ||
function removeStyle({ type = 'base', id = REACT_TOOLTIP_BASE_STYLES_ID, }) { | ||
if (type === 'core') { | ||
// eslint-disable-next-line no-param-reassign | ||
id = REACT_TOOLTIP_CORE_STYLES_ID; | ||
} | ||
const style = document.getElementById(id); | ||
style === null || style === void 0 ? void 0 : style.remove(); | ||
} | ||
if (!css || typeof document === 'undefined') { return; } | ||
/* eslint-disable @typescript-eslint/no-explicit-any */ | ||
/** | ||
* This function debounce the received function | ||
* @param { function } func Function to be debounced | ||
* @param { number } wait Time to wait before execut the function | ||
* @param { boolean } immediate Param to define if the function will be executed immediately | ||
*/ | ||
const debounce = (func, wait, immediate) => { | ||
let timeout = null; | ||
return function debounced(...args) { | ||
const later = () => { | ||
timeout = null; | ||
if (!immediate) { | ||
func.apply(this, args); | ||
} | ||
}; | ||
if (immediate && !timeout) { | ||
/** | ||
* there's not need to clear the timeout | ||
* since we expect it to resolve and set `timeout = null` | ||
*/ | ||
func.apply(this, args); | ||
timeout = setTimeout(later, wait); | ||
} | ||
if (!immediate) { | ||
if (timeout) { | ||
clearTimeout(timeout); | ||
} | ||
timeout = setTimeout(later, wait); | ||
} | ||
}; | ||
}; | ||
var head = document.head || document.getElementsByTagName('head')[0]; | ||
var style = document.createElement('style'); | ||
style.type = 'text/css'; | ||
if (insertAt === 'top') { | ||
if (head.firstChild) { | ||
head.insertBefore(style, head.firstChild); | ||
} else { | ||
head.appendChild(style); | ||
} | ||
} else { | ||
head.appendChild(style); | ||
const DEFAULT_TOOLTIP_ID = 'DEFAULT_TOOLTIP_ID'; | ||
const DEFAULT_CONTEXT_DATA = { | ||
anchorRefs: new Set(), | ||
activeAnchor: { current: null }, | ||
attach: () => { | ||
/* attach anchor element */ | ||
}, | ||
detach: () => { | ||
/* detach anchor element */ | ||
}, | ||
setActiveAnchor: () => { | ||
/* set active anchor */ | ||
}, | ||
}; | ||
const DEFAULT_CONTEXT_DATA_WRAPPER = { | ||
getTooltipData: () => DEFAULT_CONTEXT_DATA, | ||
}; | ||
const TooltipContext = React.createContext(DEFAULT_CONTEXT_DATA_WRAPPER); | ||
/** | ||
* @deprecated Use the `data-tooltip-id` attribute, or the `anchorSelect` prop instead. | ||
* See https://react-tooltip.com/docs/getting-started | ||
*/ | ||
const TooltipProvider = ({ children }) => { | ||
const [anchorRefMap, setAnchorRefMap] = React.useState({ | ||
[DEFAULT_TOOLTIP_ID]: new Set(), | ||
}); | ||
const [activeAnchorMap, setActiveAnchorMap] = React.useState({ | ||
[DEFAULT_TOOLTIP_ID]: { current: null }, | ||
}); | ||
const attach = (tooltipId, ...refs) => { | ||
setAnchorRefMap((oldMap) => { | ||
var _a; | ||
const tooltipRefs = (_a = oldMap[tooltipId]) !== null && _a !== void 0 ? _a : new Set(); | ||
refs.forEach((ref) => tooltipRefs.add(ref)); | ||
// create new object to trigger re-render | ||
return { ...oldMap, [tooltipId]: new Set(tooltipRefs) }; | ||
}); | ||
}; | ||
const detach = (tooltipId, ...refs) => { | ||
setAnchorRefMap((oldMap) => { | ||
const tooltipRefs = oldMap[tooltipId]; | ||
if (!tooltipRefs) { | ||
// tooltip not found | ||
// maybe thow error? | ||
return oldMap; | ||
} | ||
refs.forEach((ref) => tooltipRefs.delete(ref)); | ||
// create new object to trigger re-render | ||
return { ...oldMap }; | ||
}); | ||
}; | ||
const setActiveAnchor = (tooltipId, ref) => { | ||
setActiveAnchorMap((oldMap) => { | ||
var _a; | ||
if (((_a = oldMap[tooltipId]) === null || _a === void 0 ? void 0 : _a.current) === ref.current) { | ||
return oldMap; | ||
} | ||
// create new object to trigger re-render | ||
return { ...oldMap, [tooltipId]: ref }; | ||
}); | ||
}; | ||
const getTooltipData = React.useCallback((tooltipId = DEFAULT_TOOLTIP_ID) => { | ||
var _a, _b; | ||
return ({ | ||
anchorRefs: (_a = anchorRefMap[tooltipId]) !== null && _a !== void 0 ? _a : new Set(), | ||
activeAnchor: (_b = activeAnchorMap[tooltipId]) !== null && _b !== void 0 ? _b : { current: null }, | ||
attach: (...refs) => attach(tooltipId, ...refs), | ||
detach: (...refs) => detach(tooltipId, ...refs), | ||
setActiveAnchor: (ref) => setActiveAnchor(tooltipId, ref), | ||
}); | ||
}, [anchorRefMap, activeAnchorMap, attach, detach]); | ||
const context = React.useMemo(() => { | ||
return { | ||
getTooltipData, | ||
}; | ||
}, [getTooltipData]); | ||
return React__default["default"].createElement(TooltipContext.Provider, { value: context }, children); | ||
}; | ||
function useTooltip(tooltipId = DEFAULT_TOOLTIP_ID) { | ||
return React.useContext(TooltipContext).getTooltipData(tooltipId); | ||
} | ||
if (style.styleSheet) { | ||
style.styleSheet.cssText = css; | ||
} else { | ||
style.appendChild(document.createTextNode(css)); | ||
} | ||
} | ||
/** | ||
* @deprecated Use the `data-tooltip-id` attribute, or the `anchorSelect` prop instead. | ||
* See https://react-tooltip.com/docs/getting-started | ||
*/ | ||
const TooltipWrapper = ({ tooltipId, children, className, place, content, html, variant, offset, wrapper, events, positionStrategy, delayShow, delayHide, }) => { | ||
const { attach, detach } = useTooltip(tooltipId); | ||
const anchorRef = React.useRef(null); | ||
React.useEffect(() => { | ||
attach(anchorRef); | ||
return () => { | ||
detach(anchorRef); | ||
}; | ||
}, []); | ||
return (React__default["default"].createElement("span", { ref: anchorRef, className: classNames__default["default"]('react-tooltip-wrapper', className), "data-tooltip-place": place, "data-tooltip-content": content, "data-tooltip-html": html, "data-tooltip-variant": variant, "data-tooltip-offset": offset, "data-tooltip-wrapper": wrapper, "data-tooltip-events": events, "data-tooltip-position-strategy": positionStrategy, "data-tooltip-delay-show": delayShow, "data-tooltip-delay-hide": delayHide }, children)); | ||
}; | ||
var css_248z$1 = ":root {\n --rt-color-white: #fff;\n --rt-color-dark: #222;\n --rt-color-success: #8dc572;\n --rt-color-error: #be6464;\n --rt-color-warning: #f0ad4e;\n --rt-color-info: #337ab7;\n --rt-opacity: 0.9;\n}\n"; | ||
styleInject(css_248z$1); | ||
const useIsomorphicLayoutEffect = typeof window !== 'undefined' ? React.useLayoutEffect : React.useEffect; | ||
/* eslint-disable @typescript-eslint/no-explicit-any */ | ||
/** | ||
* This function debounce the received function | ||
* @param { function } func Function to be debounced | ||
* @param { number } wait Time to wait before execut the function | ||
* @param { boolean } immediate Param to define if the function will be executed immediately | ||
*/ | ||
const debounce = (func, wait, immediate) => { | ||
let timeout = null; | ||
return function debounced(...args) { | ||
const later = () => { | ||
timeout = null; | ||
if (!immediate) { | ||
func.apply(this, args); | ||
} | ||
}; | ||
if (immediate && !timeout) { | ||
/** | ||
* there's not need to clear the timeout | ||
* since we expect it to resolve and set `timeout = null` | ||
*/ | ||
func.apply(this, args); | ||
timeout = setTimeout(later, wait); | ||
} | ||
if (!immediate) { | ||
if (timeout) { | ||
clearTimeout(timeout); | ||
} | ||
timeout = setTimeout(later, wait); | ||
} | ||
}; | ||
}; | ||
const isScrollable = (node) => { | ||
if (!(node instanceof HTMLElement || node instanceof SVGElement)) { | ||
return false; | ||
} | ||
const style = getComputedStyle(node); | ||
return ['overflow', 'overflow-x', 'overflow-y'].some((propertyName) => { | ||
const value = style.getPropertyValue(propertyName); | ||
return value === 'auto' || value === 'scroll'; | ||
}); | ||
}; | ||
const getScrollParent = (node) => { | ||
if (!node) { | ||
return null; | ||
} | ||
let currentParent = node.parentElement; | ||
while (currentParent) { | ||
if (isScrollable(currentParent)) { | ||
return currentParent; | ||
} | ||
currentParent = currentParent.parentElement; | ||
} | ||
return document.scrollingElement || document.documentElement; | ||
}; | ||
const DEFAULT_TOOLTIP_ID = 'DEFAULT_TOOLTIP_ID'; | ||
const DEFAULT_CONTEXT_DATA = { | ||
anchorRefs: new Set(), | ||
activeAnchor: { current: null }, | ||
attach: () => { | ||
/* attach anchor element */ | ||
}, | ||
detach: () => { | ||
/* detach anchor element */ | ||
}, | ||
setActiveAnchor: () => { | ||
/* set active anchor */ | ||
}, | ||
}; | ||
const DEFAULT_CONTEXT_DATA_WRAPPER = { | ||
getTooltipData: () => DEFAULT_CONTEXT_DATA, | ||
}; | ||
const TooltipContext = React.createContext(DEFAULT_CONTEXT_DATA_WRAPPER); | ||
/** | ||
* @deprecated Use the `data-tooltip-id` attribute, or the `anchorSelect` prop instead. | ||
* See https://react-tooltip.com/docs/getting-started | ||
*/ | ||
const TooltipProvider = ({ children }) => { | ||
const [anchorRefMap, setAnchorRefMap] = React.useState({ | ||
[DEFAULT_TOOLTIP_ID]: new Set(), | ||
}); | ||
const [activeAnchorMap, setActiveAnchorMap] = React.useState({ | ||
[DEFAULT_TOOLTIP_ID]: { current: null }, | ||
}); | ||
const attach = (tooltipId, ...refs) => { | ||
setAnchorRefMap((oldMap) => { | ||
var _a; | ||
const tooltipRefs = (_a = oldMap[tooltipId]) !== null && _a !== void 0 ? _a : new Set(); | ||
refs.forEach((ref) => tooltipRefs.add(ref)); | ||
// create new object to trigger re-render | ||
return { ...oldMap, [tooltipId]: new Set(tooltipRefs) }; | ||
}); | ||
}; | ||
const detach = (tooltipId, ...refs) => { | ||
setAnchorRefMap((oldMap) => { | ||
const tooltipRefs = oldMap[tooltipId]; | ||
if (!tooltipRefs) { | ||
// tooltip not found | ||
// maybe thow error? | ||
return oldMap; | ||
} | ||
refs.forEach((ref) => tooltipRefs.delete(ref)); | ||
// create new object to trigger re-render | ||
return { ...oldMap }; | ||
}); | ||
}; | ||
const setActiveAnchor = (tooltipId, ref) => { | ||
setActiveAnchorMap((oldMap) => { | ||
var _a; | ||
if (((_a = oldMap[tooltipId]) === null || _a === void 0 ? void 0 : _a.current) === ref.current) { | ||
return oldMap; | ||
} | ||
// create new object to trigger re-render | ||
return { ...oldMap, [tooltipId]: ref }; | ||
}); | ||
}; | ||
const getTooltipData = React.useCallback((tooltipId = DEFAULT_TOOLTIP_ID) => { | ||
var _a, _b; | ||
return ({ | ||
anchorRefs: (_a = anchorRefMap[tooltipId]) !== null && _a !== void 0 ? _a : new Set(), | ||
activeAnchor: (_b = activeAnchorMap[tooltipId]) !== null && _b !== void 0 ? _b : { current: null }, | ||
attach: (...refs) => attach(tooltipId, ...refs), | ||
detach: (...refs) => detach(tooltipId, ...refs), | ||
setActiveAnchor: (ref) => setActiveAnchor(tooltipId, ref), | ||
}); | ||
}, [anchorRefMap, activeAnchorMap, attach, detach]); | ||
const context = React.useMemo(() => { | ||
return { | ||
getTooltipData, | ||
}; | ||
}, [getTooltipData]); | ||
return React__default["default"].createElement(TooltipContext.Provider, { value: context }, children); | ||
}; | ||
function useTooltip(tooltipId = DEFAULT_TOOLTIP_ID) { | ||
return React.useContext(TooltipContext).getTooltipData(tooltipId); | ||
} | ||
const computeTooltipPosition = async ({ elementReference = null, tooltipReference = null, tooltipArrowReference = null, place = 'top', offset: offsetValue = 10, strategy = 'absolute', middlewares = [dom.offset(Number(offsetValue)), dom.flip(), dom.shift({ padding: 5 })], }) => { | ||
if (!elementReference) { | ||
// elementReference can be null or undefined and we will not compute the position | ||
// eslint-disable-next-line no-console | ||
// console.error('The reference element for tooltip was not defined: ', elementReference) | ||
return { tooltipStyles: {}, tooltipArrowStyles: {}, place }; | ||
} | ||
if (tooltipReference === null) { | ||
return { tooltipStyles: {}, tooltipArrowStyles: {}, place }; | ||
} | ||
const middleware = middlewares; | ||
if (tooltipArrowReference) { | ||
middleware.push(dom.arrow({ element: tooltipArrowReference, padding: 5 })); | ||
return dom.computePosition(elementReference, tooltipReference, { | ||
placement: place, | ||
strategy, | ||
middleware, | ||
}).then(({ x, y, placement, middlewareData }) => { | ||
var _a, _b; | ||
const styles = { left: `${x}px`, top: `${y}px` }; | ||
const { x: arrowX, y: arrowY } = (_a = middlewareData.arrow) !== null && _a !== void 0 ? _a : { x: 0, y: 0 }; | ||
const staticSide = (_b = { | ||
top: 'bottom', | ||
right: 'left', | ||
bottom: 'top', | ||
left: 'right', | ||
}[placement.split('-')[0]]) !== null && _b !== void 0 ? _b : 'bottom'; | ||
const arrowStyle = { | ||
left: arrowX != null ? `${arrowX}px` : '', | ||
top: arrowY != null ? `${arrowY}px` : '', | ||
right: '', | ||
bottom: '', | ||
[staticSide]: '-4px', | ||
}; | ||
return { tooltipStyles: styles, tooltipArrowStyles: arrowStyle, place: placement }; | ||
}); | ||
} | ||
return dom.computePosition(elementReference, tooltipReference, { | ||
placement: 'bottom', | ||
strategy, | ||
middleware, | ||
}).then(({ x, y, placement }) => { | ||
const styles = { left: `${x}px`, top: `${y}px` }; | ||
return { tooltipStyles: styles, tooltipArrowStyles: {}, place: placement }; | ||
}); | ||
}; | ||
/** | ||
* @deprecated Use the `data-tooltip-id` attribute, or the `anchorSelect` prop instead. | ||
* See https://react-tooltip.com/docs/getting-started | ||
*/ | ||
const TooltipWrapper = ({ tooltipId, children, className, place, content, html, variant, offset, wrapper, events, positionStrategy, delayShow, delayHide, }) => { | ||
const { attach, detach } = useTooltip(tooltipId); | ||
const anchorRef = React.useRef(null); | ||
React.useEffect(() => { | ||
attach(anchorRef); | ||
return () => { | ||
detach(anchorRef); | ||
}; | ||
}, []); | ||
return (React__default["default"].createElement("span", { ref: anchorRef, className: classNames__default["default"]('react-tooltip-wrapper', className), "data-tooltip-place": place, "data-tooltip-content": content, "data-tooltip-html": html, "data-tooltip-variant": variant, "data-tooltip-offset": offset, "data-tooltip-wrapper": wrapper, "data-tooltip-events": events, "data-tooltip-position-strategy": positionStrategy, "data-tooltip-delay-show": delayShow, "data-tooltip-delay-hide": delayHide }, children)); | ||
}; | ||
var coreStyles = {"tooltip":"core-styles-module_tooltip__3vRRp","fixed":"core-styles-module_fixed__pcSol","arrow":"core-styles-module_arrow__cvMwQ","noArrow":"core-styles-module_noArrow__xock6","clickable":"core-styles-module_clickable__ZuTTB","show":"core-styles-module_show__Nt9eE"}; | ||
const useIsomorphicLayoutEffect = typeof window !== 'undefined' ? React.useLayoutEffect : React.useEffect; | ||
var styles = {"arrow":"styles-module_arrow__K0L3T","dark":"styles-module_dark__xNqje","light":"styles-module_light__Z6W-X","success":"styles-module_success__A2AKt","warning":"styles-module_warning__SCK0X","error":"styles-module_error__JvumD","info":"styles-module_info__BWdHW"}; | ||
const isScrollable = (node) => { | ||
if (!(node instanceof HTMLElement || node instanceof SVGElement)) { | ||
return false; | ||
} | ||
const style = getComputedStyle(node); | ||
return ['overflow', 'overflow-x', 'overflow-y'].some((propertyName) => { | ||
const value = style.getPropertyValue(propertyName); | ||
return value === 'auto' || value === 'scroll'; | ||
}); | ||
}; | ||
const getScrollParent = (node) => { | ||
if (!node) { | ||
return null; | ||
} | ||
let currentParent = node.parentElement; | ||
while (currentParent) { | ||
if (isScrollable(currentParent)) { | ||
return currentParent; | ||
} | ||
currentParent = currentParent.parentElement; | ||
} | ||
return document.scrollingElement || document.documentElement; | ||
}; | ||
const Tooltip = ({ | ||
// props | ||
id, className, classNameArrow, variant = 'dark', anchorId, anchorSelect, place = 'top', offset = 10, events = ['hover'], openOnClick = false, positionStrategy = 'absolute', middlewares, wrapper: WrapperElement, delayShow = 0, delayHide = 0, float = false, hidden = false, noArrow = false, clickable = false, closeOnEsc = false, closeOnScroll = false, closeOnResize = false, style: externalStyles, position, afterShow, afterHide, | ||
// props handled by controller | ||
content, contentWrapperRef, isOpen, setIsOpen, activeAnchor, setActiveAnchor, }) => { | ||
const tooltipRef = React.useRef(null); | ||
const tooltipArrowRef = React.useRef(null); | ||
const tooltipShowDelayTimerRef = React.useRef(null); | ||
const tooltipHideDelayTimerRef = React.useRef(null); | ||
const [actualPlacement, setActualPlacement] = React.useState(place); | ||
const [inlineStyles, setInlineStyles] = React.useState({}); | ||
const [inlineArrowStyles, setInlineArrowStyles] = React.useState({}); | ||
const [show, setShow] = React.useState(false); | ||
const [rendered, setRendered] = React.useState(false); | ||
const wasShowing = React.useRef(false); | ||
const lastFloatPosition = React.useRef(null); | ||
/** | ||
* @todo Remove this in a future version (provider/wrapper method is deprecated) | ||
*/ | ||
const { anchorRefs, setActiveAnchor: setProviderActiveAnchor } = useTooltip(id); | ||
const hoveringTooltip = React.useRef(false); | ||
const [anchorsBySelect, setAnchorsBySelect] = React.useState([]); | ||
const mounted = React.useRef(false); | ||
const shouldOpenOnClick = openOnClick || events.includes('click'); | ||
/** | ||
* useLayoutEffect runs before useEffect, | ||
* but should be used carefully because of caveats | ||
* https://beta.reactjs.org/reference/react/useLayoutEffect#caveats | ||
*/ | ||
useIsomorphicLayoutEffect(() => { | ||
mounted.current = true; | ||
return () => { | ||
mounted.current = false; | ||
}; | ||
}, []); | ||
React.useEffect(() => { | ||
if (!show) { | ||
/** | ||
* this fixes weird behavior when switching between two anchor elements very quickly | ||
* remove the timeout and switch quickly between two adjancent anchor elements to see it | ||
* | ||
* in practice, this means the tooltip is not immediately removed from the DOM on hide | ||
*/ | ||
const timeout = setTimeout(() => { | ||
setRendered(false); | ||
}, 150); | ||
return () => { | ||
clearTimeout(timeout); | ||
}; | ||
} | ||
return () => null; | ||
}, [show]); | ||
const handleShow = (value) => { | ||
if (!mounted.current) { | ||
return; | ||
} | ||
if (value) { | ||
setRendered(true); | ||
} | ||
/** | ||
* wait for the component to render and calculate position | ||
* before actually showing | ||
*/ | ||
setTimeout(() => { | ||
if (!mounted.current) { | ||
return; | ||
} | ||
setIsOpen === null || setIsOpen === void 0 ? void 0 : setIsOpen(value); | ||
if (isOpen === undefined) { | ||
setShow(value); | ||
} | ||
}, 10); | ||
}; | ||
/** | ||
* this replicates the effect from `handleShow()` | ||
* when `isOpen` is changed from outside | ||
*/ | ||
React.useEffect(() => { | ||
if (isOpen === undefined) { | ||
return () => null; | ||
} | ||
if (isOpen) { | ||
setRendered(true); | ||
} | ||
const timeout = setTimeout(() => { | ||
setShow(isOpen); | ||
}, 10); | ||
return () => { | ||
clearTimeout(timeout); | ||
}; | ||
}, [isOpen]); | ||
React.useEffect(() => { | ||
if (show === wasShowing.current) { | ||
return; | ||
} | ||
wasShowing.current = show; | ||
if (show) { | ||
afterShow === null || afterShow === void 0 ? void 0 : afterShow(); | ||
} | ||
else { | ||
afterHide === null || afterHide === void 0 ? void 0 : afterHide(); | ||
} | ||
}, [show]); | ||
const handleShowTooltipDelayed = () => { | ||
if (tooltipShowDelayTimerRef.current) { | ||
clearTimeout(tooltipShowDelayTimerRef.current); | ||
} | ||
tooltipShowDelayTimerRef.current = setTimeout(() => { | ||
handleShow(true); | ||
}, delayShow); | ||
}; | ||
const handleHideTooltipDelayed = (delay = delayHide) => { | ||
if (tooltipHideDelayTimerRef.current) { | ||
clearTimeout(tooltipHideDelayTimerRef.current); | ||
} | ||
tooltipHideDelayTimerRef.current = setTimeout(() => { | ||
if (hoveringTooltip.current) { | ||
return; | ||
} | ||
handleShow(false); | ||
}, delay); | ||
}; | ||
const handleShowTooltip = (event) => { | ||
var _a; | ||
if (!event) { | ||
return; | ||
} | ||
const target = ((_a = event.currentTarget) !== null && _a !== void 0 ? _a : event.target); | ||
if (!(target === null || target === void 0 ? void 0 : target.isConnected)) { | ||
/** | ||
* this happens when the target is removed from the DOM | ||
* at the same time the tooltip gets triggered | ||
*/ | ||
setActiveAnchor(null); | ||
setProviderActiveAnchor({ current: null }); | ||
return; | ||
} | ||
if (delayShow) { | ||
handleShowTooltipDelayed(); | ||
} | ||
else { | ||
handleShow(true); | ||
} | ||
setActiveAnchor(target); | ||
setProviderActiveAnchor({ current: target }); | ||
if (tooltipHideDelayTimerRef.current) { | ||
clearTimeout(tooltipHideDelayTimerRef.current); | ||
} | ||
}; | ||
const handleHideTooltip = () => { | ||
if (clickable) { | ||
// allow time for the mouse to reach the tooltip, in case there's a gap | ||
handleHideTooltipDelayed(delayHide || 100); | ||
} | ||
else if (delayHide) { | ||
handleHideTooltipDelayed(); | ||
} | ||
else { | ||
handleShow(false); | ||
} | ||
if (tooltipShowDelayTimerRef.current) { | ||
clearTimeout(tooltipShowDelayTimerRef.current); | ||
} | ||
}; | ||
const handleTooltipPosition = ({ x, y }) => { | ||
const virtualElement = { | ||
getBoundingClientRect() { | ||
return { | ||
x, | ||
y, | ||
width: 0, | ||
height: 0, | ||
top: y, | ||
left: x, | ||
right: x, | ||
bottom: y, | ||
}; | ||
}, | ||
}; | ||
computeTooltipPosition({ | ||
place, | ||
offset, | ||
elementReference: virtualElement, | ||
tooltipReference: tooltipRef.current, | ||
tooltipArrowReference: tooltipArrowRef.current, | ||
strategy: positionStrategy, | ||
middlewares, | ||
}).then((computedStylesData) => { | ||
if (Object.keys(computedStylesData.tooltipStyles).length) { | ||
setInlineStyles(computedStylesData.tooltipStyles); | ||
} | ||
if (Object.keys(computedStylesData.tooltipArrowStyles).length) { | ||
setInlineArrowStyles(computedStylesData.tooltipArrowStyles); | ||
} | ||
setActualPlacement(computedStylesData.place); | ||
}); | ||
}; | ||
const handleMouseMove = (event) => { | ||
if (!event) { | ||
return; | ||
} | ||
const mouseEvent = event; | ||
const mousePosition = { | ||
x: mouseEvent.clientX, | ||
y: mouseEvent.clientY, | ||
}; | ||
handleTooltipPosition(mousePosition); | ||
lastFloatPosition.current = mousePosition; | ||
}; | ||
const handleClickTooltipAnchor = (event) => { | ||
handleShowTooltip(event); | ||
if (delayHide) { | ||
handleHideTooltipDelayed(); | ||
} | ||
}; | ||
const handleClickOutsideAnchors = (event) => { | ||
var _a; | ||
const anchorById = document.querySelector(`[id='${anchorId}']`); | ||
const anchors = [anchorById, ...anchorsBySelect]; | ||
if (anchors.some((anchor) => anchor === null || anchor === void 0 ? void 0 : anchor.contains(event.target))) { | ||
return; | ||
} | ||
if ((_a = tooltipRef.current) === null || _a === void 0 ? void 0 : _a.contains(event.target)) { | ||
return; | ||
} | ||
handleShow(false); | ||
if (tooltipShowDelayTimerRef.current) { | ||
clearTimeout(tooltipShowDelayTimerRef.current); | ||
} | ||
}; | ||
// debounce handler to prevent call twice when | ||
// mouse enter and focus events being triggered toggether | ||
const debouncedHandleShowTooltip = debounce(handleShowTooltip, 50, true); | ||
const debouncedHandleHideTooltip = debounce(handleHideTooltip, 50, true); | ||
React.useEffect(() => { | ||
var _a, _b; | ||
const elementRefs = new Set(anchorRefs); | ||
anchorsBySelect.forEach((anchor) => { | ||
elementRefs.add({ current: anchor }); | ||
}); | ||
const anchorById = document.querySelector(`[id='${anchorId}']`); | ||
if (anchorById) { | ||
elementRefs.add({ current: anchorById }); | ||
} | ||
const handleScrollResize = () => { | ||
handleShow(false); | ||
}; | ||
const anchorScrollParent = getScrollParent(activeAnchor); | ||
const tooltipScrollParent = getScrollParent(tooltipRef.current); | ||
if (closeOnScroll) { | ||
window.addEventListener('scroll', handleScrollResize); | ||
anchorScrollParent === null || anchorScrollParent === void 0 ? void 0 : anchorScrollParent.addEventListener('scroll', handleScrollResize); | ||
tooltipScrollParent === null || tooltipScrollParent === void 0 ? void 0 : tooltipScrollParent.addEventListener('scroll', handleScrollResize); | ||
} | ||
if (closeOnResize) { | ||
window.addEventListener('resize', handleScrollResize); | ||
} | ||
const handleEsc = (event) => { | ||
if (event.key !== 'Escape') { | ||
return; | ||
} | ||
handleShow(false); | ||
}; | ||
if (closeOnEsc) { | ||
window.addEventListener('keydown', handleEsc); | ||
} | ||
const enabledEvents = []; | ||
if (shouldOpenOnClick) { | ||
window.addEventListener('click', handleClickOutsideAnchors); | ||
enabledEvents.push({ event: 'click', listener: handleClickTooltipAnchor }); | ||
} | ||
else { | ||
enabledEvents.push({ event: 'mouseenter', listener: debouncedHandleShowTooltip }, { event: 'mouseleave', listener: debouncedHandleHideTooltip }, { event: 'focus', listener: debouncedHandleShowTooltip }, { event: 'blur', listener: debouncedHandleHideTooltip }); | ||
if (float) { | ||
enabledEvents.push({ | ||
event: 'mousemove', | ||
listener: handleMouseMove, | ||
}); | ||
} | ||
} | ||
const handleMouseEnterTooltip = () => { | ||
hoveringTooltip.current = true; | ||
}; | ||
const handleMouseLeaveTooltip = () => { | ||
hoveringTooltip.current = false; | ||
handleHideTooltip(); | ||
}; | ||
if (clickable && !shouldOpenOnClick) { | ||
(_a = tooltipRef.current) === null || _a === void 0 ? void 0 : _a.addEventListener('mouseenter', handleMouseEnterTooltip); | ||
(_b = tooltipRef.current) === null || _b === void 0 ? void 0 : _b.addEventListener('mouseleave', handleMouseLeaveTooltip); | ||
} | ||
enabledEvents.forEach(({ event, listener }) => { | ||
elementRefs.forEach((ref) => { | ||
var _a; | ||
(_a = ref.current) === null || _a === void 0 ? void 0 : _a.addEventListener(event, listener); | ||
}); | ||
}); | ||
return () => { | ||
var _a, _b; | ||
if (closeOnScroll) { | ||
window.removeEventListener('scroll', handleScrollResize); | ||
anchorScrollParent === null || anchorScrollParent === void 0 ? void 0 : anchorScrollParent.removeEventListener('scroll', handleScrollResize); | ||
tooltipScrollParent === null || tooltipScrollParent === void 0 ? void 0 : tooltipScrollParent.removeEventListener('scroll', handleScrollResize); | ||
} | ||
if (closeOnResize) { | ||
window.removeEventListener('resize', handleScrollResize); | ||
} | ||
if (shouldOpenOnClick) { | ||
window.removeEventListener('click', handleClickOutsideAnchors); | ||
} | ||
if (closeOnEsc) { | ||
window.removeEventListener('keydown', handleEsc); | ||
} | ||
if (clickable && !shouldOpenOnClick) { | ||
(_a = tooltipRef.current) === null || _a === void 0 ? void 0 : _a.removeEventListener('mouseenter', handleMouseEnterTooltip); | ||
(_b = tooltipRef.current) === null || _b === void 0 ? void 0 : _b.removeEventListener('mouseleave', handleMouseLeaveTooltip); | ||
} | ||
enabledEvents.forEach(({ event, listener }) => { | ||
elementRefs.forEach((ref) => { | ||
var _a; | ||
(_a = ref.current) === null || _a === void 0 ? void 0 : _a.removeEventListener(event, listener); | ||
}); | ||
}); | ||
}; | ||
/** | ||
* rendered is also a dependency to ensure anchor observers are re-registered | ||
* since `tooltipRef` becomes stale after removing/adding the tooltip to the DOM | ||
*/ | ||
}, [rendered, anchorRefs, anchorsBySelect, closeOnEsc, events]); | ||
React.useEffect(() => { | ||
let selector = anchorSelect !== null && anchorSelect !== void 0 ? anchorSelect : ''; | ||
if (!selector && id) { | ||
selector = `[data-tooltip-id='${id}']`; | ||
} | ||
const documentObserverCallback = (mutationList) => { | ||
const newAnchors = []; | ||
mutationList.forEach((mutation) => { | ||
if (mutation.type === 'attributes' && mutation.attributeName === 'data-tooltip-id') { | ||
const newId = mutation.target.getAttribute('data-tooltip-id'); | ||
if (newId === id) { | ||
newAnchors.push(mutation.target); | ||
} | ||
} | ||
if (mutation.type !== 'childList') { | ||
return; | ||
} | ||
if (activeAnchor) { | ||
[...mutation.removedNodes].some((node) => { | ||
var _a; | ||
if ((_a = node === null || node === void 0 ? void 0 : node.contains) === null || _a === void 0 ? void 0 : _a.call(node, activeAnchor)) { | ||
setRendered(false); | ||
handleShow(false); | ||
setActiveAnchor(null); | ||
if (tooltipShowDelayTimerRef.current) { | ||
clearTimeout(tooltipShowDelayTimerRef.current); | ||
} | ||
if (tooltipHideDelayTimerRef.current) { | ||
clearTimeout(tooltipHideDelayTimerRef.current); | ||
} | ||
return true; | ||
} | ||
return false; | ||
}); | ||
} | ||
if (!selector) { | ||
return; | ||
} | ||
try { | ||
const elements = [...mutation.addedNodes].filter((node) => node.nodeType === 1); | ||
newAnchors.push( | ||
// the element itself is an anchor | ||
...elements.filter((element) => element.matches(selector))); | ||
newAnchors.push( | ||
// the element has children which are anchors | ||
...elements.flatMap((element) => [...element.querySelectorAll(selector)])); | ||
} | ||
catch (_a) { | ||
/** | ||
* invalid CSS selector. | ||
* already warned on tooltip controller | ||
*/ | ||
} | ||
}); | ||
if (newAnchors.length) { | ||
setAnchorsBySelect((anchors) => [...anchors, ...newAnchors]); | ||
} | ||
}; | ||
const documentObserver = new MutationObserver(documentObserverCallback); | ||
// watch for anchor being removed from the DOM | ||
documentObserver.observe(document.body, { | ||
childList: true, | ||
subtree: true, | ||
attributes: true, | ||
attributeFilter: ['data-tooltip-id'], | ||
}); | ||
return () => { | ||
documentObserver.disconnect(); | ||
}; | ||
}, [id, anchorSelect, activeAnchor]); | ||
const updateTooltipPosition = () => { | ||
if (position) { | ||
// if `position` is set, override regular and `float` positioning | ||
handleTooltipPosition(position); | ||
return; | ||
} | ||
if (float) { | ||
if (lastFloatPosition.current) { | ||
/* | ||
Without this, changes to `content`, `place`, `offset`, ..., will only | ||
trigger a position calculation after a `mousemove` event. | ||
To see why this matters, comment this line, run `yarn dev` and click the | ||
"Hover me!" anchor. | ||
*/ | ||
handleTooltipPosition(lastFloatPosition.current); | ||
} | ||
// if `float` is set, override regular positioning | ||
return; | ||
} | ||
computeTooltipPosition({ | ||
place, | ||
offset, | ||
elementReference: activeAnchor, | ||
tooltipReference: tooltipRef.current, | ||
tooltipArrowReference: tooltipArrowRef.current, | ||
strategy: positionStrategy, | ||
middlewares, | ||
}).then((computedStylesData) => { | ||
if (!mounted.current) { | ||
// invalidate computed positions after remount | ||
return; | ||
} | ||
if (Object.keys(computedStylesData.tooltipStyles).length) { | ||
setInlineStyles(computedStylesData.tooltipStyles); | ||
} | ||
if (Object.keys(computedStylesData.tooltipArrowStyles).length) { | ||
setInlineArrowStyles(computedStylesData.tooltipArrowStyles); | ||
} | ||
setActualPlacement(computedStylesData.place); | ||
}); | ||
}; | ||
React.useEffect(() => { | ||
updateTooltipPosition(); | ||
}, [show, activeAnchor, content, externalStyles, place, offset, positionStrategy, position]); | ||
React.useEffect(() => { | ||
if (!(contentWrapperRef === null || contentWrapperRef === void 0 ? void 0 : contentWrapperRef.current)) { | ||
return () => null; | ||
} | ||
const contentObserver = new ResizeObserver(() => { | ||
updateTooltipPosition(); | ||
}); | ||
contentObserver.observe(contentWrapperRef.current); | ||
return () => { | ||
contentObserver.disconnect(); | ||
}; | ||
}, [content, contentWrapperRef === null || contentWrapperRef === void 0 ? void 0 : contentWrapperRef.current]); | ||
React.useEffect(() => { | ||
var _a; | ||
const anchorById = document.querySelector(`[id='${anchorId}']`); | ||
const anchors = [...anchorsBySelect, anchorById]; | ||
if (!activeAnchor || !anchors.includes(activeAnchor)) { | ||
/** | ||
* if there is no active anchor, | ||
* or if the current active anchor is not amongst the allowed ones, | ||
* reset it | ||
*/ | ||
setActiveAnchor((_a = anchorsBySelect[0]) !== null && _a !== void 0 ? _a : anchorById); | ||
} | ||
}, [anchorId, anchorsBySelect, activeAnchor]); | ||
React.useEffect(() => { | ||
return () => { | ||
if (tooltipShowDelayTimerRef.current) { | ||
clearTimeout(tooltipShowDelayTimerRef.current); | ||
} | ||
if (tooltipHideDelayTimerRef.current) { | ||
clearTimeout(tooltipHideDelayTimerRef.current); | ||
} | ||
}; | ||
}, []); | ||
React.useEffect(() => { | ||
let selector = anchorSelect; | ||
if (!selector && id) { | ||
selector = `[data-tooltip-id='${id}']`; | ||
} | ||
if (!selector) { | ||
return; | ||
} | ||
try { | ||
const anchors = Array.from(document.querySelectorAll(selector)); | ||
setAnchorsBySelect(anchors); | ||
} | ||
catch (_a) { | ||
// warning was already issued in the controller | ||
setAnchorsBySelect([]); | ||
} | ||
}, [id, anchorSelect]); | ||
const canShow = !hidden && content && show && Object.keys(inlineStyles).length > 0; | ||
return rendered ? (React__default["default"].createElement(WrapperElement, { id: id, role: "tooltip", className: classNames__default["default"]('react-tooltip', coreStyles['tooltip'], styles[variant], className, `react-tooltip__place-${actualPlacement}`, { | ||
[coreStyles['show']]: canShow, | ||
[coreStyles['fixed']]: positionStrategy === 'fixed', | ||
[coreStyles['clickable']]: clickable, | ||
}), style: { ...externalStyles, ...inlineStyles }, ref: tooltipRef }, | ||
content, | ||
React__default["default"].createElement(WrapperElement, { className: classNames__default["default"]('react-tooltip-arrow', coreStyles['arrow'], styles['arrow'], classNameArrow, { | ||
/** | ||
* changed from dash `no-arrow` to camelcase because of: | ||
* https://github.com/indooorsman/esbuild-css-modules-plugin/issues/42 | ||
*/ | ||
[coreStyles['noArrow']]: noArrow, | ||
}), style: inlineArrowStyles, ref: tooltipArrowRef }))) : null; | ||
}; | ||
const computeTooltipPosition = async ({ elementReference = null, tooltipReference = null, tooltipArrowReference = null, place = 'top', offset: offsetValue = 10, strategy = 'absolute', middlewares = [dom.offset(Number(offsetValue)), dom.flip(), dom.shift({ padding: 5 })], }) => { | ||
if (!elementReference) { | ||
// elementReference can be null or undefined and we will not compute the position | ||
// eslint-disable-next-line no-console | ||
// console.error('The reference element for tooltip was not defined: ', elementReference) | ||
return { tooltipStyles: {}, tooltipArrowStyles: {}, place }; | ||
} | ||
if (tooltipReference === null) { | ||
return { tooltipStyles: {}, tooltipArrowStyles: {}, place }; | ||
} | ||
const middleware = middlewares; | ||
if (tooltipArrowReference) { | ||
middleware.push(dom.arrow({ element: tooltipArrowReference, padding: 5 })); | ||
return dom.computePosition(elementReference, tooltipReference, { | ||
placement: place, | ||
strategy, | ||
middleware, | ||
}).then(({ x, y, placement, middlewareData }) => { | ||
var _a, _b; | ||
const styles = { left: `${x}px`, top: `${y}px` }; | ||
const { x: arrowX, y: arrowY } = (_a = middlewareData.arrow) !== null && _a !== void 0 ? _a : { x: 0, y: 0 }; | ||
const staticSide = (_b = { | ||
top: 'bottom', | ||
right: 'left', | ||
bottom: 'top', | ||
left: 'right', | ||
}[placement.split('-')[0]]) !== null && _b !== void 0 ? _b : 'bottom'; | ||
const arrowStyle = { | ||
left: arrowX != null ? `${arrowX}px` : '', | ||
top: arrowY != null ? `${arrowY}px` : '', | ||
right: '', | ||
bottom: '', | ||
[staticSide]: '-4px', | ||
}; | ||
return { tooltipStyles: styles, tooltipArrowStyles: arrowStyle, place: placement }; | ||
}); | ||
} | ||
return dom.computePosition(elementReference, tooltipReference, { | ||
placement: 'bottom', | ||
strategy, | ||
middleware, | ||
}).then(({ x, y, placement }) => { | ||
const styles = { left: `${x}px`, top: `${y}px` }; | ||
return { tooltipStyles: styles, tooltipArrowStyles: {}, place: placement }; | ||
}); | ||
}; | ||
/* eslint-disable react/no-danger */ | ||
const TooltipContent = ({ content }) => { | ||
return React__default["default"].createElement("span", { dangerouslySetInnerHTML: { __html: content } }); | ||
}; | ||
var css_248z = ".styles-module_tooltip__mnnfp {\n visibility: hidden;\n width: max-content;\n position: absolute;\n top: 0;\n left: 0;\n padding: 8px 16px;\n border-radius: 3px;\n font-size: 90%;\n pointer-events: none;\n opacity: 0;\n transition: opacity 0.3s ease-out;\n will-change: opacity, visibility;\n}\n\n.styles-module_fixed__7ciUi {\n position: fixed;\n}\n\n.styles-module_arrow__K0L3T {\n position: absolute;\n background: inherit;\n width: 8px;\n height: 8px;\n transform: rotate(45deg);\n}\n\n.styles-module_noArrow__T8y2L {\n display: none;\n}\n\n.styles-module_clickable__Bv9o7 {\n pointer-events: auto;\n}\n\n.styles-module_show__2NboJ {\n visibility: visible;\n opacity: var(--rt-opacity);\n}\n\n/** Types variant **/\n.styles-module_dark__xNqje {\n background: var(--rt-color-dark);\n color: var(--rt-color-white);\n}\n\n.styles-module_light__Z6W-X {\n background-color: var(--rt-color-white);\n color: var(--rt-color-dark);\n}\n\n.styles-module_success__A2AKt {\n background-color: var(--rt-color-success);\n color: var(--rt-color-white);\n}\n\n.styles-module_warning__SCK0X {\n background-color: var(--rt-color-warning);\n color: var(--rt-color-white);\n}\n\n.styles-module_error__JvumD {\n background-color: var(--rt-color-error);\n color: var(--rt-color-white);\n}\n\n.styles-module_info__BWdHW {\n background-color: var(--rt-color-info);\n color: var(--rt-color-white);\n}\n"; | ||
var styles = {"tooltip":"styles-module_tooltip__mnnfp","fixed":"styles-module_fixed__7ciUi","arrow":"styles-module_arrow__K0L3T","noArrow":"styles-module_noArrow__T8y2L","clickable":"styles-module_clickable__Bv9o7","show":"styles-module_show__2NboJ","dark":"styles-module_dark__xNqje","light":"styles-module_light__Z6W-X","success":"styles-module_success__A2AKt","warning":"styles-module_warning__SCK0X","error":"styles-module_error__JvumD","info":"styles-module_info__BWdHW"}; | ||
styleInject(css_248z); | ||
const TooltipController = ({ id, anchorId, anchorSelect, content, html, render, className, classNameArrow, variant = 'dark', place = 'top', offset = 10, wrapper = 'div', children = null, events = ['hover'], openOnClick = false, positionStrategy = 'absolute', middlewares, delayShow = 0, delayHide = 0, float = false, hidden = false, noArrow = false, clickable = false, closeOnEsc = false, closeOnScroll = false, closeOnResize = false, style, position, isOpen, setIsOpen, afterShow, afterHide, }) => { | ||
const [tooltipContent, setTooltipContent] = React.useState(content); | ||
const [tooltipHtml, setTooltipHtml] = React.useState(html); | ||
const [tooltipPlace, setTooltipPlace] = React.useState(place); | ||
const [tooltipVariant, setTooltipVariant] = React.useState(variant); | ||
const [tooltipOffset, setTooltipOffset] = React.useState(offset); | ||
const [tooltipDelayShow, setTooltipDelayShow] = React.useState(delayShow); | ||
const [tooltipDelayHide, setTooltipDelayHide] = React.useState(delayHide); | ||
const [tooltipFloat, setTooltipFloat] = React.useState(float); | ||
const [tooltipHidden, setTooltipHidden] = React.useState(hidden); | ||
const [tooltipWrapper, setTooltipWrapper] = React.useState(wrapper); | ||
const [tooltipEvents, setTooltipEvents] = React.useState(events); | ||
const [tooltipPositionStrategy, setTooltipPositionStrategy] = React.useState(positionStrategy); | ||
const [activeAnchor, setActiveAnchor] = React.useState(null); | ||
/** | ||
* @todo Remove this in a future version (provider/wrapper method is deprecated) | ||
*/ | ||
const { anchorRefs, activeAnchor: providerActiveAnchor } = useTooltip(id); | ||
const getDataAttributesFromAnchorElement = (elementReference) => { | ||
const dataAttributes = elementReference === null || elementReference === void 0 ? void 0 : elementReference.getAttributeNames().reduce((acc, name) => { | ||
var _a; | ||
if (name.startsWith('data-tooltip-')) { | ||
const parsedAttribute = name.replace(/^data-tooltip-/, ''); | ||
acc[parsedAttribute] = (_a = elementReference === null || elementReference === void 0 ? void 0 : elementReference.getAttribute(name)) !== null && _a !== void 0 ? _a : null; | ||
} | ||
return acc; | ||
}, {}); | ||
return dataAttributes; | ||
}; | ||
const applyAllDataAttributesFromAnchorElement = (dataAttributes) => { | ||
const handleDataAttributes = { | ||
place: (value) => { | ||
var _a; | ||
setTooltipPlace((_a = value) !== null && _a !== void 0 ? _a : place); | ||
}, | ||
content: (value) => { | ||
setTooltipContent(value !== null && value !== void 0 ? value : content); | ||
}, | ||
html: (value) => { | ||
setTooltipHtml(value !== null && value !== void 0 ? value : html); | ||
}, | ||
variant: (value) => { | ||
var _a; | ||
setTooltipVariant((_a = value) !== null && _a !== void 0 ? _a : variant); | ||
}, | ||
offset: (value) => { | ||
setTooltipOffset(value === null ? offset : Number(value)); | ||
}, | ||
wrapper: (value) => { | ||
var _a; | ||
setTooltipWrapper((_a = value) !== null && _a !== void 0 ? _a : wrapper); | ||
}, | ||
events: (value) => { | ||
const parsed = value === null || value === void 0 ? void 0 : value.split(' '); | ||
setTooltipEvents(parsed !== null && parsed !== void 0 ? parsed : events); | ||
}, | ||
'position-strategy': (value) => { | ||
var _a; | ||
setTooltipPositionStrategy((_a = value) !== null && _a !== void 0 ? _a : positionStrategy); | ||
}, | ||
'delay-show': (value) => { | ||
setTooltipDelayShow(value === null ? delayShow : Number(value)); | ||
}, | ||
'delay-hide': (value) => { | ||
setTooltipDelayHide(value === null ? delayHide : Number(value)); | ||
}, | ||
float: (value) => { | ||
setTooltipFloat(value === null ? float : value === 'true'); | ||
}, | ||
hidden: (value) => { | ||
setTooltipHidden(value === null ? hidden : value === 'true'); | ||
}, | ||
}; | ||
// reset unset data attributes to default values | ||
// without this, data attributes from the last active anchor will still be used | ||
Object.values(handleDataAttributes).forEach((handler) => handler(null)); | ||
Object.entries(dataAttributes).forEach(([key, value]) => { | ||
var _a; | ||
(_a = handleDataAttributes[key]) === null || _a === void 0 ? void 0 : _a.call(handleDataAttributes, value); | ||
}); | ||
}; | ||
React.useEffect(() => { | ||
setTooltipContent(content); | ||
}, [content]); | ||
React.useEffect(() => { | ||
setTooltipHtml(html); | ||
}, [html]); | ||
React.useEffect(() => { | ||
setTooltipPlace(place); | ||
}, [place]); | ||
React.useEffect(() => { | ||
setTooltipVariant(variant); | ||
}, [variant]); | ||
React.useEffect(() => { | ||
setTooltipOffset(offset); | ||
}, [offset]); | ||
React.useEffect(() => { | ||
setTooltipDelayShow(delayShow); | ||
}, [delayShow]); | ||
React.useEffect(() => { | ||
setTooltipDelayHide(delayHide); | ||
}, [delayHide]); | ||
React.useEffect(() => { | ||
setTooltipFloat(float); | ||
}, [float]); | ||
React.useEffect(() => { | ||
setTooltipHidden(hidden); | ||
}, [hidden]); | ||
React.useEffect(() => { | ||
setTooltipPositionStrategy(positionStrategy); | ||
}, [positionStrategy]); | ||
React.useEffect(() => { | ||
var _a; | ||
const elementRefs = new Set(anchorRefs); | ||
let selector = anchorSelect; | ||
if (!selector && id) { | ||
selector = `[data-tooltip-id='${id}']`; | ||
} | ||
if (selector) { | ||
try { | ||
const anchorsBySelect = document.querySelectorAll(selector); | ||
anchorsBySelect.forEach((anchor) => { | ||
elementRefs.add({ current: anchor }); | ||
}); | ||
} | ||
catch (_b) { | ||
{ | ||
// eslint-disable-next-line no-console | ||
console.warn(`[react-tooltip] "${selector}" is not a valid CSS selector`); | ||
} | ||
} | ||
} | ||
const anchorById = document.querySelector(`[id='${anchorId}']`); | ||
if (anchorById) { | ||
elementRefs.add({ current: anchorById }); | ||
} | ||
if (!elementRefs.size) { | ||
return () => null; | ||
} | ||
const anchorElement = (_a = activeAnchor !== null && activeAnchor !== void 0 ? activeAnchor : anchorById) !== null && _a !== void 0 ? _a : providerActiveAnchor.current; | ||
const observerCallback = (mutationList) => { | ||
mutationList.forEach((mutation) => { | ||
var _a; | ||
if (!anchorElement || | ||
mutation.type !== 'attributes' || | ||
!((_a = mutation.attributeName) === null || _a === void 0 ? void 0 : _a.startsWith('data-tooltip-'))) { | ||
return; | ||
} | ||
// make sure to get all set attributes, since all unset attributes are reset | ||
const dataAttributes = getDataAttributesFromAnchorElement(anchorElement); | ||
applyAllDataAttributesFromAnchorElement(dataAttributes); | ||
}); | ||
}; | ||
// Create an observer instance linked to the callback function | ||
const observer = new MutationObserver(observerCallback); | ||
// do not check for subtree and childrens, we only want to know attribute changes | ||
// to stay watching `data-attributes-*` from anchor element | ||
const observerConfig = { attributes: true, childList: false, subtree: false }; | ||
if (anchorElement) { | ||
const dataAttributes = getDataAttributesFromAnchorElement(anchorElement); | ||
applyAllDataAttributesFromAnchorElement(dataAttributes); | ||
// Start observing the target node for configured mutations | ||
observer.observe(anchorElement, observerConfig); | ||
} | ||
return () => { | ||
// Remove the observer when the tooltip is destroyed | ||
observer.disconnect(); | ||
}; | ||
}, [anchorRefs, providerActiveAnchor, activeAnchor, anchorId, anchorSelect]); | ||
/** | ||
* content priority: children < render or content < html | ||
* children should be lower priority so that it can be used as the "default" content | ||
*/ | ||
let renderedContent = children; | ||
const contentWrapperRef = React.useRef(null); | ||
if (render) { | ||
const rendered = render({ content: tooltipContent !== null && tooltipContent !== void 0 ? tooltipContent : null, activeAnchor }); | ||
renderedContent = rendered ? (React__default["default"].createElement("div", { ref: contentWrapperRef, className: "react-tooltip-content-wrapper" }, rendered)) : null; | ||
} | ||
else if (tooltipContent) { | ||
renderedContent = tooltipContent; | ||
} | ||
if (tooltipHtml) { | ||
renderedContent = React__default["default"].createElement(TooltipContent, { content: tooltipHtml }); | ||
} | ||
const props = { | ||
id, | ||
anchorId, | ||
anchorSelect, | ||
className, | ||
classNameArrow, | ||
content: renderedContent, | ||
contentWrapperRef, | ||
place: tooltipPlace, | ||
variant: tooltipVariant, | ||
offset: tooltipOffset, | ||
wrapper: tooltipWrapper, | ||
events: tooltipEvents, | ||
openOnClick, | ||
positionStrategy: tooltipPositionStrategy, | ||
middlewares, | ||
delayShow: tooltipDelayShow, | ||
delayHide: tooltipDelayHide, | ||
float: tooltipFloat, | ||
hidden: tooltipHidden, | ||
noArrow, | ||
clickable, | ||
closeOnEsc, | ||
closeOnScroll, | ||
closeOnResize, | ||
style, | ||
position, | ||
isOpen, | ||
setIsOpen, | ||
afterShow, | ||
afterHide, | ||
activeAnchor, | ||
setActiveAnchor: (anchor) => setActiveAnchor(anchor), | ||
}; | ||
return React__default["default"].createElement(Tooltip, { ...props }); | ||
}; | ||
const Tooltip = ({ | ||
// props | ||
id, className, classNameArrow, variant = 'dark', anchorId, anchorSelect, place = 'top', offset = 10, events = ['hover'], openOnClick = false, positionStrategy = 'absolute', middlewares, wrapper: WrapperElement, delayShow = 0, delayHide = 0, float = false, hidden = false, noArrow = false, clickable = false, closeOnEsc = false, closeOnScroll = false, closeOnResize = false, style: externalStyles, position, afterShow, afterHide, | ||
// props handled by controller | ||
content, contentWrapperRef, isOpen, setIsOpen, activeAnchor, setActiveAnchor, }) => { | ||
const tooltipRef = React.useRef(null); | ||
const tooltipArrowRef = React.useRef(null); | ||
const tooltipShowDelayTimerRef = React.useRef(null); | ||
const tooltipHideDelayTimerRef = React.useRef(null); | ||
const [actualPlacement, setActualPlacement] = React.useState(place); | ||
const [inlineStyles, setInlineStyles] = React.useState({}); | ||
const [inlineArrowStyles, setInlineArrowStyles] = React.useState({}); | ||
const [show, setShow] = React.useState(false); | ||
const [rendered, setRendered] = React.useState(false); | ||
const wasShowing = React.useRef(false); | ||
const lastFloatPosition = React.useRef(null); | ||
/** | ||
* @todo Remove this in a future version (provider/wrapper method is deprecated) | ||
*/ | ||
const { anchorRefs, setActiveAnchor: setProviderActiveAnchor } = useTooltip(id); | ||
const hoveringTooltip = React.useRef(false); | ||
const [anchorsBySelect, setAnchorsBySelect] = React.useState([]); | ||
const mounted = React.useRef(false); | ||
const shouldOpenOnClick = openOnClick || events.includes('click'); | ||
/** | ||
* useLayoutEffect runs before useEffect, | ||
* but should be used carefully because of caveats | ||
* https://beta.reactjs.org/reference/react/useLayoutEffect#caveats | ||
*/ | ||
useIsomorphicLayoutEffect(() => { | ||
mounted.current = true; | ||
return () => { | ||
mounted.current = false; | ||
}; | ||
}, []); | ||
React.useEffect(() => { | ||
if (!show) { | ||
/** | ||
* this fixes weird behavior when switching between two anchor elements very quickly | ||
* remove the timeout and switch quickly between two adjancent anchor elements to see it | ||
* | ||
* in practice, this means the tooltip is not immediately removed from the DOM on hide | ||
*/ | ||
const timeout = setTimeout(() => { | ||
setRendered(false); | ||
}, 150); | ||
return () => { | ||
clearTimeout(timeout); | ||
}; | ||
} | ||
return () => null; | ||
}, [show]); | ||
const handleShow = (value) => { | ||
if (!mounted.current) { | ||
return; | ||
} | ||
if (value) { | ||
setRendered(true); | ||
} | ||
/** | ||
* wait for the component to render and calculate position | ||
* before actually showing | ||
*/ | ||
setTimeout(() => { | ||
if (!mounted.current) { | ||
return; | ||
} | ||
setIsOpen === null || setIsOpen === void 0 ? void 0 : setIsOpen(value); | ||
if (isOpen === undefined) { | ||
setShow(value); | ||
} | ||
}, 10); | ||
}; | ||
/** | ||
* this replicates the effect from `handleShow()` | ||
* when `isOpen` is changed from outside | ||
*/ | ||
React.useEffect(() => { | ||
if (isOpen === undefined) { | ||
return () => null; | ||
} | ||
if (isOpen) { | ||
setRendered(true); | ||
} | ||
const timeout = setTimeout(() => { | ||
setShow(isOpen); | ||
}, 10); | ||
return () => { | ||
clearTimeout(timeout); | ||
}; | ||
}, [isOpen]); | ||
React.useEffect(() => { | ||
if (show === wasShowing.current) { | ||
return; | ||
} | ||
wasShowing.current = show; | ||
if (show) { | ||
afterShow === null || afterShow === void 0 ? void 0 : afterShow(); | ||
} | ||
else { | ||
afterHide === null || afterHide === void 0 ? void 0 : afterHide(); | ||
} | ||
}, [show]); | ||
const handleShowTooltipDelayed = () => { | ||
if (tooltipShowDelayTimerRef.current) { | ||
clearTimeout(tooltipShowDelayTimerRef.current); | ||
} | ||
tooltipShowDelayTimerRef.current = setTimeout(() => { | ||
handleShow(true); | ||
}, delayShow); | ||
}; | ||
const handleHideTooltipDelayed = (delay = delayHide) => { | ||
if (tooltipHideDelayTimerRef.current) { | ||
clearTimeout(tooltipHideDelayTimerRef.current); | ||
} | ||
tooltipHideDelayTimerRef.current = setTimeout(() => { | ||
if (hoveringTooltip.current) { | ||
return; | ||
} | ||
handleShow(false); | ||
}, delay); | ||
}; | ||
const handleShowTooltip = (event) => { | ||
var _a; | ||
if (!event) { | ||
return; | ||
} | ||
const target = ((_a = event.currentTarget) !== null && _a !== void 0 ? _a : event.target); | ||
if (!(target === null || target === void 0 ? void 0 : target.isConnected)) { | ||
/** | ||
* this happens when the target is removed from the DOM | ||
* at the same time the tooltip gets triggered | ||
*/ | ||
setActiveAnchor(null); | ||
setProviderActiveAnchor({ current: null }); | ||
return; | ||
} | ||
if (delayShow) { | ||
handleShowTooltipDelayed(); | ||
} | ||
else { | ||
handleShow(true); | ||
} | ||
setActiveAnchor(target); | ||
setProviderActiveAnchor({ current: target }); | ||
if (tooltipHideDelayTimerRef.current) { | ||
clearTimeout(tooltipHideDelayTimerRef.current); | ||
} | ||
}; | ||
const handleHideTooltip = () => { | ||
if (clickable) { | ||
// allow time for the mouse to reach the tooltip, in case there's a gap | ||
handleHideTooltipDelayed(delayHide || 100); | ||
} | ||
else if (delayHide) { | ||
handleHideTooltipDelayed(); | ||
} | ||
else { | ||
handleShow(false); | ||
} | ||
if (tooltipShowDelayTimerRef.current) { | ||
clearTimeout(tooltipShowDelayTimerRef.current); | ||
} | ||
}; | ||
const handleTooltipPosition = ({ x, y }) => { | ||
const virtualElement = { | ||
getBoundingClientRect() { | ||
return { | ||
x, | ||
y, | ||
width: 0, | ||
height: 0, | ||
top: y, | ||
left: x, | ||
right: x, | ||
bottom: y, | ||
}; | ||
}, | ||
}; | ||
computeTooltipPosition({ | ||
place, | ||
offset, | ||
elementReference: virtualElement, | ||
tooltipReference: tooltipRef.current, | ||
tooltipArrowReference: tooltipArrowRef.current, | ||
strategy: positionStrategy, | ||
middlewares, | ||
}).then((computedStylesData) => { | ||
if (Object.keys(computedStylesData.tooltipStyles).length) { | ||
setInlineStyles(computedStylesData.tooltipStyles); | ||
} | ||
if (Object.keys(computedStylesData.tooltipArrowStyles).length) { | ||
setInlineArrowStyles(computedStylesData.tooltipArrowStyles); | ||
} | ||
setActualPlacement(computedStylesData.place); | ||
}); | ||
}; | ||
const handleMouseMove = (event) => { | ||
if (!event) { | ||
return; | ||
} | ||
const mouseEvent = event; | ||
const mousePosition = { | ||
x: mouseEvent.clientX, | ||
y: mouseEvent.clientY, | ||
}; | ||
handleTooltipPosition(mousePosition); | ||
lastFloatPosition.current = mousePosition; | ||
}; | ||
const handleClickTooltipAnchor = (event) => { | ||
handleShowTooltip(event); | ||
if (delayHide) { | ||
handleHideTooltipDelayed(); | ||
} | ||
}; | ||
const handleClickOutsideAnchors = (event) => { | ||
var _a; | ||
const anchorById = document.querySelector(`[id='${anchorId}']`); | ||
const anchors = [anchorById, ...anchorsBySelect]; | ||
if (anchors.some((anchor) => anchor === null || anchor === void 0 ? void 0 : anchor.contains(event.target))) { | ||
return; | ||
} | ||
if ((_a = tooltipRef.current) === null || _a === void 0 ? void 0 : _a.contains(event.target)) { | ||
return; | ||
} | ||
handleShow(false); | ||
if (tooltipShowDelayTimerRef.current) { | ||
clearTimeout(tooltipShowDelayTimerRef.current); | ||
} | ||
}; | ||
// debounce handler to prevent call twice when | ||
// mouse enter and focus events being triggered toggether | ||
const debouncedHandleShowTooltip = debounce(handleShowTooltip, 50, true); | ||
const debouncedHandleHideTooltip = debounce(handleHideTooltip, 50, true); | ||
React.useEffect(() => { | ||
var _a, _b; | ||
const elementRefs = new Set(anchorRefs); | ||
anchorsBySelect.forEach((anchor) => { | ||
elementRefs.add({ current: anchor }); | ||
}); | ||
const anchorById = document.querySelector(`[id='${anchorId}']`); | ||
if (anchorById) { | ||
elementRefs.add({ current: anchorById }); | ||
} | ||
const handleScrollResize = () => { | ||
handleShow(false); | ||
}; | ||
const anchorScrollParent = getScrollParent(activeAnchor); | ||
const tooltipScrollParent = getScrollParent(tooltipRef.current); | ||
if (closeOnScroll) { | ||
window.addEventListener('scroll', handleScrollResize); | ||
anchorScrollParent === null || anchorScrollParent === void 0 ? void 0 : anchorScrollParent.addEventListener('scroll', handleScrollResize); | ||
tooltipScrollParent === null || tooltipScrollParent === void 0 ? void 0 : tooltipScrollParent.addEventListener('scroll', handleScrollResize); | ||
} | ||
if (closeOnResize) { | ||
window.addEventListener('resize', handleScrollResize); | ||
} | ||
const handleEsc = (event) => { | ||
if (event.key !== 'Escape') { | ||
return; | ||
} | ||
handleShow(false); | ||
}; | ||
if (closeOnEsc) { | ||
window.addEventListener('keydown', handleEsc); | ||
} | ||
const enabledEvents = []; | ||
if (shouldOpenOnClick) { | ||
window.addEventListener('click', handleClickOutsideAnchors); | ||
enabledEvents.push({ event: 'click', listener: handleClickTooltipAnchor }); | ||
} | ||
else { | ||
enabledEvents.push({ event: 'mouseenter', listener: debouncedHandleShowTooltip }, { event: 'mouseleave', listener: debouncedHandleHideTooltip }, { event: 'focus', listener: debouncedHandleShowTooltip }, { event: 'blur', listener: debouncedHandleHideTooltip }); | ||
if (float) { | ||
enabledEvents.push({ | ||
event: 'mousemove', | ||
listener: handleMouseMove, | ||
}); | ||
} | ||
} | ||
const handleMouseEnterTooltip = () => { | ||
hoveringTooltip.current = true; | ||
}; | ||
const handleMouseLeaveTooltip = () => { | ||
hoveringTooltip.current = false; | ||
handleHideTooltip(); | ||
}; | ||
if (clickable && !shouldOpenOnClick) { | ||
(_a = tooltipRef.current) === null || _a === void 0 ? void 0 : _a.addEventListener('mouseenter', handleMouseEnterTooltip); | ||
(_b = tooltipRef.current) === null || _b === void 0 ? void 0 : _b.addEventListener('mouseleave', handleMouseLeaveTooltip); | ||
} | ||
enabledEvents.forEach(({ event, listener }) => { | ||
elementRefs.forEach((ref) => { | ||
var _a; | ||
(_a = ref.current) === null || _a === void 0 ? void 0 : _a.addEventListener(event, listener); | ||
}); | ||
}); | ||
return () => { | ||
var _a, _b; | ||
if (closeOnScroll) { | ||
window.removeEventListener('scroll', handleScrollResize); | ||
anchorScrollParent === null || anchorScrollParent === void 0 ? void 0 : anchorScrollParent.removeEventListener('scroll', handleScrollResize); | ||
tooltipScrollParent === null || tooltipScrollParent === void 0 ? void 0 : tooltipScrollParent.removeEventListener('scroll', handleScrollResize); | ||
} | ||
if (closeOnResize) { | ||
window.removeEventListener('resize', handleScrollResize); | ||
} | ||
if (shouldOpenOnClick) { | ||
window.removeEventListener('click', handleClickOutsideAnchors); | ||
} | ||
if (closeOnEsc) { | ||
window.removeEventListener('keydown', handleEsc); | ||
} | ||
if (clickable && !shouldOpenOnClick) { | ||
(_a = tooltipRef.current) === null || _a === void 0 ? void 0 : _a.removeEventListener('mouseenter', handleMouseEnterTooltip); | ||
(_b = tooltipRef.current) === null || _b === void 0 ? void 0 : _b.removeEventListener('mouseleave', handleMouseLeaveTooltip); | ||
} | ||
enabledEvents.forEach(({ event, listener }) => { | ||
elementRefs.forEach((ref) => { | ||
var _a; | ||
(_a = ref.current) === null || _a === void 0 ? void 0 : _a.removeEventListener(event, listener); | ||
}); | ||
}); | ||
}; | ||
/** | ||
* rendered is also a dependency to ensure anchor observers are re-registered | ||
* since `tooltipRef` becomes stale after removing/adding the tooltip to the DOM | ||
*/ | ||
}, [rendered, anchorRefs, anchorsBySelect, closeOnEsc, events]); | ||
React.useEffect(() => { | ||
let selector = anchorSelect !== null && anchorSelect !== void 0 ? anchorSelect : ''; | ||
if (!selector && id) { | ||
selector = `[data-tooltip-id='${id}']`; | ||
} | ||
const documentObserverCallback = (mutationList) => { | ||
const newAnchors = []; | ||
mutationList.forEach((mutation) => { | ||
if (mutation.type === 'attributes' && mutation.attributeName === 'data-tooltip-id') { | ||
const newId = mutation.target.getAttribute('data-tooltip-id'); | ||
if (newId === id) { | ||
newAnchors.push(mutation.target); | ||
} | ||
} | ||
if (mutation.type !== 'childList') { | ||
return; | ||
} | ||
if (activeAnchor) { | ||
[...mutation.removedNodes].some((node) => { | ||
var _a; | ||
if ((_a = node === null || node === void 0 ? void 0 : node.contains) === null || _a === void 0 ? void 0 : _a.call(node, activeAnchor)) { | ||
setRendered(false); | ||
handleShow(false); | ||
setActiveAnchor(null); | ||
if (tooltipShowDelayTimerRef.current) { | ||
clearTimeout(tooltipShowDelayTimerRef.current); | ||
} | ||
if (tooltipHideDelayTimerRef.current) { | ||
clearTimeout(tooltipHideDelayTimerRef.current); | ||
} | ||
return true; | ||
} | ||
return false; | ||
}); | ||
} | ||
if (!selector) { | ||
return; | ||
} | ||
try { | ||
const elements = [...mutation.addedNodes].filter((node) => node.nodeType === 1); | ||
newAnchors.push( | ||
// the element itself is an anchor | ||
...elements.filter((element) => element.matches(selector))); | ||
newAnchors.push( | ||
// the element has children which are anchors | ||
...elements.flatMap((element) => [...element.querySelectorAll(selector)])); | ||
} | ||
catch (_a) { | ||
/** | ||
* invalid CSS selector. | ||
* already warned on tooltip controller | ||
*/ | ||
} | ||
}); | ||
if (newAnchors.length) { | ||
setAnchorsBySelect((anchors) => [...anchors, ...newAnchors]); | ||
} | ||
}; | ||
const documentObserver = new MutationObserver(documentObserverCallback); | ||
// watch for anchor being removed from the DOM | ||
documentObserver.observe(document.body, { | ||
childList: true, | ||
subtree: true, | ||
attributes: true, | ||
attributeFilter: ['data-tooltip-id'], | ||
}); | ||
return () => { | ||
documentObserver.disconnect(); | ||
}; | ||
}, [id, anchorSelect, activeAnchor]); | ||
const updateTooltipPosition = () => { | ||
if (position) { | ||
// if `position` is set, override regular and `float` positioning | ||
handleTooltipPosition(position); | ||
return; | ||
} | ||
if (float) { | ||
if (lastFloatPosition.current) { | ||
/* | ||
Without this, changes to `content`, `place`, `offset`, ..., will only | ||
trigger a position calculation after a `mousemove` event. | ||
To see why this matters, comment this line, run `yarn dev` and click the | ||
"Hover me!" anchor. | ||
*/ | ||
handleTooltipPosition(lastFloatPosition.current); | ||
} | ||
// if `float` is set, override regular positioning | ||
return; | ||
} | ||
computeTooltipPosition({ | ||
place, | ||
offset, | ||
elementReference: activeAnchor, | ||
tooltipReference: tooltipRef.current, | ||
tooltipArrowReference: tooltipArrowRef.current, | ||
strategy: positionStrategy, | ||
middlewares, | ||
}).then((computedStylesData) => { | ||
if (!mounted.current) { | ||
// invalidate computed positions after remount | ||
return; | ||
} | ||
if (Object.keys(computedStylesData.tooltipStyles).length) { | ||
setInlineStyles(computedStylesData.tooltipStyles); | ||
} | ||
if (Object.keys(computedStylesData.tooltipArrowStyles).length) { | ||
setInlineArrowStyles(computedStylesData.tooltipArrowStyles); | ||
} | ||
setActualPlacement(computedStylesData.place); | ||
}); | ||
}; | ||
React.useEffect(() => { | ||
updateTooltipPosition(); | ||
}, [show, activeAnchor, content, externalStyles, place, offset, positionStrategy, position]); | ||
React.useEffect(() => { | ||
if (!(contentWrapperRef === null || contentWrapperRef === void 0 ? void 0 : contentWrapperRef.current)) { | ||
return () => null; | ||
} | ||
const contentObserver = new ResizeObserver(() => { | ||
updateTooltipPosition(); | ||
}); | ||
contentObserver.observe(contentWrapperRef.current); | ||
return () => { | ||
contentObserver.disconnect(); | ||
}; | ||
}, [content, contentWrapperRef === null || contentWrapperRef === void 0 ? void 0 : contentWrapperRef.current]); | ||
React.useEffect(() => { | ||
var _a; | ||
const anchorById = document.querySelector(`[id='${anchorId}']`); | ||
const anchors = [...anchorsBySelect, anchorById]; | ||
if (!activeAnchor || !anchors.includes(activeAnchor)) { | ||
/** | ||
* if there is no active anchor, | ||
* or if the current active anchor is not amongst the allowed ones, | ||
* reset it | ||
*/ | ||
setActiveAnchor((_a = anchorsBySelect[0]) !== null && _a !== void 0 ? _a : anchorById); | ||
} | ||
}, [anchorId, anchorsBySelect, activeAnchor]); | ||
React.useEffect(() => { | ||
return () => { | ||
if (tooltipShowDelayTimerRef.current) { | ||
clearTimeout(tooltipShowDelayTimerRef.current); | ||
} | ||
if (tooltipHideDelayTimerRef.current) { | ||
clearTimeout(tooltipHideDelayTimerRef.current); | ||
} | ||
}; | ||
}, []); | ||
React.useEffect(() => { | ||
let selector = anchorSelect; | ||
if (!selector && id) { | ||
selector = `[data-tooltip-id='${id}']`; | ||
} | ||
if (!selector) { | ||
return; | ||
} | ||
try { | ||
const anchors = Array.from(document.querySelectorAll(selector)); | ||
setAnchorsBySelect(anchors); | ||
} | ||
catch (_a) { | ||
// warning was already issued in the controller | ||
setAnchorsBySelect([]); | ||
} | ||
}, [id, anchorSelect]); | ||
const canShow = !hidden && content && show && Object.keys(inlineStyles).length > 0; | ||
return rendered ? (React__default["default"].createElement(WrapperElement, { id: id, role: "tooltip", className: classNames__default["default"]('react-tooltip', styles['tooltip'], styles[variant], className, `react-tooltip__place-${actualPlacement}`, { | ||
[styles['show']]: canShow, | ||
[styles['fixed']]: positionStrategy === 'fixed', | ||
[styles['clickable']]: clickable, | ||
}), style: { ...externalStyles, ...inlineStyles }, ref: tooltipRef }, | ||
content, | ||
React__default["default"].createElement(WrapperElement, { className: classNames__default["default"]('react-tooltip-arrow', styles['arrow'], classNameArrow, { | ||
/** | ||
* changed from dash `no-arrow` to camelcase because of: | ||
* https://github.com/indooorsman/esbuild-css-modules-plugin/issues/42 | ||
*/ | ||
[styles['noArrow']]: noArrow, | ||
}), style: inlineArrowStyles, ref: tooltipArrowRef }))) : null; | ||
}; | ||
// those content will be replaced in build time with the `react-tooltip.css` builded content | ||
const TooltipCoreStyles = `:root { | ||
--rt-color-white: #fff; | ||
--rt-color-dark: #222; | ||
--rt-color-success: #8dc572; | ||
--rt-color-error: #be6464; | ||
--rt-color-warning: #f0ad4e; | ||
--rt-color-info: #337ab7; | ||
--rt-opacity: 0.9; | ||
} | ||
/* eslint-disable react/no-danger */ | ||
const TooltipContent = ({ content }) => { | ||
return React__default["default"].createElement("span", { dangerouslySetInnerHTML: { __html: content } }); | ||
}; | ||
.core-styles-module_tooltip__3vRRp { | ||
visibility: hidden; | ||
width: max-content; | ||
position: absolute; | ||
top: 0; | ||
left: 0; | ||
padding: 8px 16px; | ||
border-radius: 3px; | ||
font-size: 90%; | ||
pointer-events: none; | ||
opacity: 0; | ||
transition: opacity 0.3s ease-out; | ||
will-change: opacity, visibility; | ||
} | ||
const TooltipController = ({ id, anchorId, anchorSelect, content, html, render, className, classNameArrow, variant = 'dark', place = 'top', offset = 10, wrapper = 'div', children = null, events = ['hover'], openOnClick = false, positionStrategy = 'absolute', middlewares, delayShow = 0, delayHide = 0, float = false, hidden = false, noArrow = false, clickable = false, closeOnEsc = false, closeOnScroll = false, closeOnResize = false, style, position, isOpen, setIsOpen, afterShow, afterHide, }) => { | ||
const [tooltipContent, setTooltipContent] = React.useState(content); | ||
const [tooltipHtml, setTooltipHtml] = React.useState(html); | ||
const [tooltipPlace, setTooltipPlace] = React.useState(place); | ||
const [tooltipVariant, setTooltipVariant] = React.useState(variant); | ||
const [tooltipOffset, setTooltipOffset] = React.useState(offset); | ||
const [tooltipDelayShow, setTooltipDelayShow] = React.useState(delayShow); | ||
const [tooltipDelayHide, setTooltipDelayHide] = React.useState(delayHide); | ||
const [tooltipFloat, setTooltipFloat] = React.useState(float); | ||
const [tooltipHidden, setTooltipHidden] = React.useState(hidden); | ||
const [tooltipWrapper, setTooltipWrapper] = React.useState(wrapper); | ||
const [tooltipEvents, setTooltipEvents] = React.useState(events); | ||
const [tooltipPositionStrategy, setTooltipPositionStrategy] = React.useState(positionStrategy); | ||
const [activeAnchor, setActiveAnchor] = React.useState(null); | ||
/** | ||
* @todo Remove this in a future version (provider/wrapper method is deprecated) | ||
*/ | ||
const { anchorRefs, activeAnchor: providerActiveAnchor } = useTooltip(id); | ||
const getDataAttributesFromAnchorElement = (elementReference) => { | ||
const dataAttributes = elementReference === null || elementReference === void 0 ? void 0 : elementReference.getAttributeNames().reduce((acc, name) => { | ||
var _a; | ||
if (name.startsWith('data-tooltip-')) { | ||
const parsedAttribute = name.replace(/^data-tooltip-/, ''); | ||
acc[parsedAttribute] = (_a = elementReference === null || elementReference === void 0 ? void 0 : elementReference.getAttribute(name)) !== null && _a !== void 0 ? _a : null; | ||
} | ||
return acc; | ||
}, {}); | ||
return dataAttributes; | ||
}; | ||
const applyAllDataAttributesFromAnchorElement = (dataAttributes) => { | ||
const handleDataAttributes = { | ||
place: (value) => { | ||
var _a; | ||
setTooltipPlace((_a = value) !== null && _a !== void 0 ? _a : place); | ||
}, | ||
content: (value) => { | ||
setTooltipContent(value !== null && value !== void 0 ? value : content); | ||
}, | ||
html: (value) => { | ||
setTooltipHtml(value !== null && value !== void 0 ? value : html); | ||
}, | ||
variant: (value) => { | ||
var _a; | ||
setTooltipVariant((_a = value) !== null && _a !== void 0 ? _a : variant); | ||
}, | ||
offset: (value) => { | ||
setTooltipOffset(value === null ? offset : Number(value)); | ||
}, | ||
wrapper: (value) => { | ||
var _a; | ||
setTooltipWrapper((_a = value) !== null && _a !== void 0 ? _a : wrapper); | ||
}, | ||
events: (value) => { | ||
const parsed = value === null || value === void 0 ? void 0 : value.split(' '); | ||
setTooltipEvents(parsed !== null && parsed !== void 0 ? parsed : events); | ||
}, | ||
'position-strategy': (value) => { | ||
var _a; | ||
setTooltipPositionStrategy((_a = value) !== null && _a !== void 0 ? _a : positionStrategy); | ||
}, | ||
'delay-show': (value) => { | ||
setTooltipDelayShow(value === null ? delayShow : Number(value)); | ||
}, | ||
'delay-hide': (value) => { | ||
setTooltipDelayHide(value === null ? delayHide : Number(value)); | ||
}, | ||
float: (value) => { | ||
setTooltipFloat(value === null ? float : value === 'true'); | ||
}, | ||
hidden: (value) => { | ||
setTooltipHidden(value === null ? hidden : value === 'true'); | ||
}, | ||
}; | ||
// reset unset data attributes to default values | ||
// without this, data attributes from the last active anchor will still be used | ||
Object.values(handleDataAttributes).forEach((handler) => handler(null)); | ||
Object.entries(dataAttributes).forEach(([key, value]) => { | ||
var _a; | ||
(_a = handleDataAttributes[key]) === null || _a === void 0 ? void 0 : _a.call(handleDataAttributes, value); | ||
}); | ||
}; | ||
React.useEffect(() => { | ||
setTooltipContent(content); | ||
}, [content]); | ||
React.useEffect(() => { | ||
setTooltipHtml(html); | ||
}, [html]); | ||
React.useEffect(() => { | ||
setTooltipPlace(place); | ||
}, [place]); | ||
React.useEffect(() => { | ||
setTooltipVariant(variant); | ||
}, [variant]); | ||
React.useEffect(() => { | ||
setTooltipOffset(offset); | ||
}, [offset]); | ||
React.useEffect(() => { | ||
setTooltipDelayShow(delayShow); | ||
}, [delayShow]); | ||
React.useEffect(() => { | ||
setTooltipDelayHide(delayHide); | ||
}, [delayHide]); | ||
React.useEffect(() => { | ||
setTooltipFloat(float); | ||
}, [float]); | ||
React.useEffect(() => { | ||
setTooltipHidden(hidden); | ||
}, [hidden]); | ||
React.useEffect(() => { | ||
setTooltipPositionStrategy(positionStrategy); | ||
}, [positionStrategy]); | ||
React.useEffect(() => { | ||
var _a; | ||
const elementRefs = new Set(anchorRefs); | ||
let selector = anchorSelect; | ||
if (!selector && id) { | ||
selector = `[data-tooltip-id='${id}']`; | ||
} | ||
if (selector) { | ||
try { | ||
const anchorsBySelect = document.querySelectorAll(selector); | ||
anchorsBySelect.forEach((anchor) => { | ||
elementRefs.add({ current: anchor }); | ||
}); | ||
} | ||
catch (_b) { | ||
{ | ||
// eslint-disable-next-line no-console | ||
console.warn(`[react-tooltip] "${selector}" is not a valid CSS selector`); | ||
} | ||
} | ||
} | ||
const anchorById = document.querySelector(`[id='${anchorId}']`); | ||
if (anchorById) { | ||
elementRefs.add({ current: anchorById }); | ||
} | ||
if (!elementRefs.size) { | ||
return () => null; | ||
} | ||
const anchorElement = (_a = activeAnchor !== null && activeAnchor !== void 0 ? activeAnchor : anchorById) !== null && _a !== void 0 ? _a : providerActiveAnchor.current; | ||
const observerCallback = (mutationList) => { | ||
mutationList.forEach((mutation) => { | ||
var _a; | ||
if (!anchorElement || | ||
mutation.type !== 'attributes' || | ||
!((_a = mutation.attributeName) === null || _a === void 0 ? void 0 : _a.startsWith('data-tooltip-'))) { | ||
return; | ||
} | ||
// make sure to get all set attributes, since all unset attributes are reset | ||
const dataAttributes = getDataAttributesFromAnchorElement(anchorElement); | ||
applyAllDataAttributesFromAnchorElement(dataAttributes); | ||
}); | ||
}; | ||
// Create an observer instance linked to the callback function | ||
const observer = new MutationObserver(observerCallback); | ||
// do not check for subtree and childrens, we only want to know attribute changes | ||
// to stay watching `data-attributes-*` from anchor element | ||
const observerConfig = { attributes: true, childList: false, subtree: false }; | ||
if (anchorElement) { | ||
const dataAttributes = getDataAttributesFromAnchorElement(anchorElement); | ||
applyAllDataAttributesFromAnchorElement(dataAttributes); | ||
// Start observing the target node for configured mutations | ||
observer.observe(anchorElement, observerConfig); | ||
} | ||
return () => { | ||
// Remove the observer when the tooltip is destroyed | ||
observer.disconnect(); | ||
}; | ||
}, [anchorRefs, providerActiveAnchor, activeAnchor, anchorId, anchorSelect]); | ||
/** | ||
* content priority: children < render or content < html | ||
* children should be lower priority so that it can be used as the "default" content | ||
*/ | ||
let renderedContent = children; | ||
const contentWrapperRef = React.useRef(null); | ||
if (render) { | ||
const rendered = render({ content: tooltipContent !== null && tooltipContent !== void 0 ? tooltipContent : null, activeAnchor }); | ||
renderedContent = rendered ? (React__default["default"].createElement("div", { ref: contentWrapperRef, className: "react-tooltip-content-wrapper" }, rendered)) : null; | ||
} | ||
else if (tooltipContent) { | ||
renderedContent = tooltipContent; | ||
} | ||
if (tooltipHtml) { | ||
renderedContent = React__default["default"].createElement(TooltipContent, { content: tooltipHtml }); | ||
} | ||
const props = { | ||
id, | ||
anchorId, | ||
anchorSelect, | ||
className, | ||
classNameArrow, | ||
content: renderedContent, | ||
contentWrapperRef, | ||
place: tooltipPlace, | ||
variant: tooltipVariant, | ||
offset: tooltipOffset, | ||
wrapper: tooltipWrapper, | ||
events: tooltipEvents, | ||
openOnClick, | ||
positionStrategy: tooltipPositionStrategy, | ||
middlewares, | ||
delayShow: tooltipDelayShow, | ||
delayHide: tooltipDelayHide, | ||
float: tooltipFloat, | ||
hidden: tooltipHidden, | ||
noArrow, | ||
clickable, | ||
closeOnEsc, | ||
closeOnScroll, | ||
closeOnResize, | ||
style, | ||
position, | ||
isOpen, | ||
setIsOpen, | ||
afterShow, | ||
afterHide, | ||
activeAnchor, | ||
setActiveAnchor: (anchor) => setActiveAnchor(anchor), | ||
}; | ||
return React__default["default"].createElement(Tooltip, { ...props }); | ||
}; | ||
.core-styles-module_fixed__pcSol { | ||
position: fixed; | ||
} | ||
exports.Tooltip = TooltipController; | ||
exports.TooltipProvider = TooltipProvider; | ||
exports.TooltipWrapper = TooltipWrapper; | ||
.core-styles-module_arrow__cvMwQ { | ||
position: absolute; | ||
background: inherit; | ||
} | ||
Object.defineProperty(exports, '__esModule', { value: true }); | ||
.core-styles-module_noArrow__xock6 { | ||
display: none; | ||
} | ||
.core-styles-module_clickable__ZuTTB { | ||
pointer-events: auto; | ||
} | ||
.core-styles-module_show__Nt9eE { | ||
visibility: visible; | ||
opacity: var(--rt-opacity); | ||
} | ||
`; | ||
const TooltipStyles = ` | ||
.styles-module_arrow__K0L3T { | ||
width: 8px; | ||
height: 8px; | ||
transform: rotate(45deg); | ||
} | ||
/** Types variant **/ | ||
.styles-module_dark__xNqje { | ||
background: var(--rt-color-dark); | ||
color: var(--rt-color-white); | ||
} | ||
.styles-module_light__Z6W-X { | ||
background-color: var(--rt-color-white); | ||
color: var(--rt-color-dark); | ||
} | ||
.styles-module_success__A2AKt { | ||
background-color: var(--rt-color-success); | ||
color: var(--rt-color-white); | ||
} | ||
.styles-module_warning__SCK0X { | ||
background-color: var(--rt-color-warning); | ||
color: var(--rt-color-white); | ||
} | ||
.styles-module_error__JvumD { | ||
background-color: var(--rt-color-error); | ||
color: var(--rt-color-white); | ||
} | ||
.styles-module_info__BWdHW { | ||
background-color: var(--rt-color-info); | ||
color: var(--rt-color-white); | ||
} | ||
`; | ||
injectStyle({ css: TooltipCoreStyles, type: 'core' }); | ||
injectStyle({ css: TooltipStyles }); | ||
exports.Tooltip = TooltipController; | ||
exports.TooltipProvider = TooltipProvider; | ||
exports.TooltipWrapper = TooltipWrapper; | ||
exports.removeStyle = removeStyle; | ||
Object.defineProperty(exports, '__esModule', { value: true }); | ||
})); | ||
//# sourceMappingURL=react-tooltip.umd.js.map |
@@ -7,3 +7,3 @@ /* | ||
*/ | ||
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports,require("react"),require("classnames"),require("@floating-ui/dom")):"function"==typeof define&&define.amd?define(["exports","react","classnames","@floating-ui/dom"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).ReactTooltip={},e.React,e.classNames,e.FloatingUIDOM)}(this,(function(e,t,r,o){"use strict";function l(e){return e&&"object"==typeof e&&"default"in e?e:{default:e}}var n=l(t),c=l(r);function s(e,t){void 0===t&&(t={});var r=t.insertAt;if(e&&"undefined"!=typeof document){var o=document.head||document.getElementsByTagName("head")[0],l=document.createElement("style");l.type="text/css","top"===r&&o.firstChild?o.insertBefore(l,o.firstChild):o.appendChild(l),l.styleSheet?l.styleSheet.cssText=e:l.appendChild(document.createTextNode(e))}}s(":root{--rt-color-white:#fff;--rt-color-dark:#222;--rt-color-success:#8dc572;--rt-color-error:#be6464;--rt-color-warning:#f0ad4e;--rt-color-info:#337ab7;--rt-opacity:0.9}");const a=(e,t,r)=>{let o=null;return function(...l){const n=()=>{o=null,r||e.apply(this,l)};r&&!o&&(e.apply(this,l),o=setTimeout(n,t)),r||(o&&clearTimeout(o),o=setTimeout(n,t))}},i="DEFAULT_TOOLTIP_ID",u={anchorRefs:new Set,activeAnchor:{current:null},attach:()=>{},detach:()=>{},setActiveAnchor:()=>{}},d={getTooltipData:()=>u},f=t.createContext(d);function p(e=i){return t.useContext(f).getTooltipData(e)}const v="undefined"!=typeof window?t.useLayoutEffect:t.useEffect,m=e=>{if(!(e instanceof HTMLElement||e instanceof SVGElement))return!1;const t=getComputedStyle(e);return["overflow","overflow-x","overflow-y"].some((e=>{const r=t.getPropertyValue(e);return"auto"===r||"scroll"===r}))},h=e=>{if(!e)return null;let t=e.parentElement;for(;t;){if(m(t))return t;t=t.parentElement}return document.scrollingElement||document.documentElement},y=async({elementReference:e=null,tooltipReference:t=null,tooltipArrowReference:r=null,place:l="top",offset:n=10,strategy:c="absolute",middlewares:s=[o.offset(Number(n)),o.flip(),o.shift({padding:5})]})=>{if(!e)return{tooltipStyles:{},tooltipArrowStyles:{},place:l};if(null===t)return{tooltipStyles:{},tooltipArrowStyles:{},place:l};const a=s;return r?(a.push(o.arrow({element:r,padding:5})),o.computePosition(e,t,{placement:l,strategy:c,middleware:a}).then((({x:e,y:t,placement:r,middlewareData:o})=>{var l,n;const c={left:`${e}px`,top:`${t}px`},{x:s,y:a}=null!==(l=o.arrow)&&void 0!==l?l:{x:0,y:0};return{tooltipStyles:c,tooltipArrowStyles:{left:null!=s?`${s}px`:"",top:null!=a?`${a}px`:"",right:"",bottom:"",[null!==(n={top:"bottom",right:"left",bottom:"top",left:"right"}[r.split("-")[0]])&&void 0!==n?n:"bottom"]:"-4px"},place:r}}))):o.computePosition(e,t,{placement:"bottom",strategy:c,middleware:a}).then((({x:e,y:t,placement:r})=>({tooltipStyles:{left:`${e}px`,top:`${t}px`},tooltipArrowStyles:{},place:r})))};var w={tooltip:"styles-module_tooltip__mnnfp",fixed:"styles-module_fixed__7ciUi",arrow:"styles-module_arrow__K0L3T",noArrow:"styles-module_noArrow__T8y2L",clickable:"styles-module_clickable__Bv9o7",show:"styles-module_show__2NboJ",dark:"styles-module_dark__xNqje",light:"styles-module_light__Z6W-X",success:"styles-module_success__A2AKt",warning:"styles-module_warning__SCK0X",error:"styles-module_error__JvumD",info:"styles-module_info__BWdHW"};s(".styles-module_tooltip__mnnfp{border-radius:3px;font-size:90%;left:0;opacity:0;padding:8px 16px;pointer-events:none;position:absolute;top:0;transition:opacity .3s ease-out;visibility:hidden;width:max-content;will-change:opacity,visibility}.styles-module_fixed__7ciUi{position:fixed}.styles-module_arrow__K0L3T{background:inherit;height:8px;position:absolute;transform:rotate(45deg);width:8px}.styles-module_noArrow__T8y2L{display:none}.styles-module_clickable__Bv9o7{pointer-events:auto}.styles-module_show__2NboJ{opacity:var(--rt-opacity);visibility:visible}.styles-module_dark__xNqje{background:var(--rt-color-dark);color:var(--rt-color-white)}.styles-module_light__Z6W-X{background-color:var(--rt-color-white);color:var(--rt-color-dark)}.styles-module_success__A2AKt{background-color:var(--rt-color-success);color:var(--rt-color-white)}.styles-module_warning__SCK0X{background-color:var(--rt-color-warning);color:var(--rt-color-white)}.styles-module_error__JvumD{background-color:var(--rt-color-error);color:var(--rt-color-white)}.styles-module_info__BWdHW{background-color:var(--rt-color-info);color:var(--rt-color-white)}");const _=({id:e,className:r,classNameArrow:o,variant:l="dark",anchorId:s,anchorSelect:i,place:u="top",offset:d=10,events:f=["hover"],openOnClick:m=!1,positionStrategy:_="absolute",middlewares:S,wrapper:E,delayShow:b=0,delayHide:g=0,float:A=!1,hidden:T=!1,noArrow:k=!1,clickable:x=!1,closeOnEsc:O=!1,closeOnScroll:R=!1,closeOnResize:L=!1,style:N,position:C,afterShow:$,afterHide:j,content:q,contentWrapperRef:H,isOpen:I,setIsOpen:W,activeAnchor:D,setActiveAnchor:z})=>{const M=t.useRef(null),B=t.useRef(null),P=t.useRef(null),K=t.useRef(null),[X,J]=t.useState(u),[U,F]=t.useState({}),[V,Z]=t.useState({}),[G,Y]=t.useState(!1),[Q,ee]=t.useState(!1),te=t.useRef(!1),re=t.useRef(null),{anchorRefs:oe,setActiveAnchor:le}=p(e),ne=t.useRef(!1),[ce,se]=t.useState([]),ae=t.useRef(!1),ie=m||f.includes("click");v((()=>(ae.current=!0,()=>{ae.current=!1})),[]),t.useEffect((()=>{if(!G){const e=setTimeout((()=>{ee(!1)}),150);return()=>{clearTimeout(e)}}return()=>null}),[G]);const ue=e=>{ae.current&&(e&&ee(!0),setTimeout((()=>{ae.current&&(null==W||W(e),void 0===I&&Y(e))}),10))};t.useEffect((()=>{if(void 0===I)return()=>null;I&&ee(!0);const e=setTimeout((()=>{Y(I)}),10);return()=>{clearTimeout(e)}}),[I]),t.useEffect((()=>{G!==te.current&&(te.current=G,G?null==$||$():null==j||j())}),[G]);const de=(e=g)=>{K.current&&clearTimeout(K.current),K.current=setTimeout((()=>{ne.current||ue(!1)}),e)},fe=e=>{var t;if(!e)return;const r=null!==(t=e.currentTarget)&&void 0!==t?t:e.target;if(!(null==r?void 0:r.isConnected))return z(null),void le({current:null});b?(P.current&&clearTimeout(P.current),P.current=setTimeout((()=>{ue(!0)}),b)):ue(!0),z(r),le({current:r}),K.current&&clearTimeout(K.current)},pe=()=>{x?de(g||100):g?de():ue(!1),P.current&&clearTimeout(P.current)},ve=({x:e,y:t})=>{y({place:u,offset:d,elementReference:{getBoundingClientRect:()=>({x:e,y:t,width:0,height:0,top:t,left:e,right:e,bottom:t})},tooltipReference:M.current,tooltipArrowReference:B.current,strategy:_,middlewares:S}).then((e=>{Object.keys(e.tooltipStyles).length&&F(e.tooltipStyles),Object.keys(e.tooltipArrowStyles).length&&Z(e.tooltipArrowStyles),J(e.place)}))},me=e=>{if(!e)return;const t=e,r={x:t.clientX,y:t.clientY};ve(r),re.current=r},he=e=>{fe(e),g&&de()},ye=e=>{var t;[document.querySelector(`[id='${s}']`),...ce].some((t=>null==t?void 0:t.contains(e.target)))||(null===(t=M.current)||void 0===t?void 0:t.contains(e.target))||(ue(!1),P.current&&clearTimeout(P.current))},we=a(fe,50,!0),_e=a(pe,50,!0);t.useEffect((()=>{var e,t;const r=new Set(oe);ce.forEach((e=>{r.add({current:e})}));const o=document.querySelector(`[id='${s}']`);o&&r.add({current:o});const l=()=>{ue(!1)},n=h(D),c=h(M.current);R&&(window.addEventListener("scroll",l),null==n||n.addEventListener("scroll",l),null==c||c.addEventListener("scroll",l)),L&&window.addEventListener("resize",l);const a=e=>{"Escape"===e.key&&ue(!1)};O&&window.addEventListener("keydown",a);const i=[];ie?(window.addEventListener("click",ye),i.push({event:"click",listener:he})):(i.push({event:"mouseenter",listener:we},{event:"mouseleave",listener:_e},{event:"focus",listener:we},{event:"blur",listener:_e}),A&&i.push({event:"mousemove",listener:me}));const u=()=>{ne.current=!0},d=()=>{ne.current=!1,pe()};return x&&!ie&&(null===(e=M.current)||void 0===e||e.addEventListener("mouseenter",u),null===(t=M.current)||void 0===t||t.addEventListener("mouseleave",d)),i.forEach((({event:e,listener:t})=>{r.forEach((r=>{var o;null===(o=r.current)||void 0===o||o.addEventListener(e,t)}))})),()=>{var e,t;R&&(window.removeEventListener("scroll",l),null==n||n.removeEventListener("scroll",l),null==c||c.removeEventListener("scroll",l)),L&&window.removeEventListener("resize",l),ie&&window.removeEventListener("click",ye),O&&window.removeEventListener("keydown",a),x&&!ie&&(null===(e=M.current)||void 0===e||e.removeEventListener("mouseenter",u),null===(t=M.current)||void 0===t||t.removeEventListener("mouseleave",d)),i.forEach((({event:e,listener:t})=>{r.forEach((r=>{var o;null===(o=r.current)||void 0===o||o.removeEventListener(e,t)}))}))}}),[Q,oe,ce,O,f]),t.useEffect((()=>{let t=null!=i?i:"";!t&&e&&(t=`[data-tooltip-id='${e}']`);const r=new MutationObserver((r=>{const o=[];r.forEach((r=>{if("attributes"===r.type&&"data-tooltip-id"===r.attributeName){r.target.getAttribute("data-tooltip-id")===e&&o.push(r.target)}if("childList"===r.type&&(D&&[...r.removedNodes].some((e=>{var t;return!!(null===(t=null==e?void 0:e.contains)||void 0===t?void 0:t.call(e,D))&&(ee(!1),ue(!1),z(null),P.current&&clearTimeout(P.current),K.current&&clearTimeout(K.current),!0)})),t))try{const e=[...r.addedNodes].filter((e=>1===e.nodeType));o.push(...e.filter((e=>e.matches(t)))),o.push(...e.flatMap((e=>[...e.querySelectorAll(t)])))}catch(e){}})),o.length&&se((e=>[...e,...o]))}));return r.observe(document.body,{childList:!0,subtree:!0,attributes:!0,attributeFilter:["data-tooltip-id"]}),()=>{r.disconnect()}}),[e,i,D]);const Se=()=>{C?ve(C):A?re.current&&ve(re.current):y({place:u,offset:d,elementReference:D,tooltipReference:M.current,tooltipArrowReference:B.current,strategy:_,middlewares:S}).then((e=>{ae.current&&(Object.keys(e.tooltipStyles).length&&F(e.tooltipStyles),Object.keys(e.tooltipArrowStyles).length&&Z(e.tooltipArrowStyles),J(e.place))}))};t.useEffect((()=>{Se()}),[G,D,q,N,u,d,_,C]),t.useEffect((()=>{if(!(null==H?void 0:H.current))return()=>null;const e=new ResizeObserver((()=>{Se()}));return e.observe(H.current),()=>{e.disconnect()}}),[q,null==H?void 0:H.current]),t.useEffect((()=>{var e;const t=document.querySelector(`[id='${s}']`),r=[...ce,t];D&&r.includes(D)||z(null!==(e=ce[0])&&void 0!==e?e:t)}),[s,ce,D]),t.useEffect((()=>()=>{P.current&&clearTimeout(P.current),K.current&&clearTimeout(K.current)}),[]),t.useEffect((()=>{let t=i;if(!t&&e&&(t=`[data-tooltip-id='${e}']`),t)try{const e=Array.from(document.querySelectorAll(t));se(e)}catch(e){se([])}}),[e,i]);const Ee=!T&&q&&G&&Object.keys(U).length>0;return Q?n.default.createElement(E,{id:e,role:"tooltip",className:c.default("react-tooltip",w.tooltip,w[l],r,`react-tooltip__place-${X}`,{[w.show]:Ee,[w.fixed]:"fixed"===_,[w.clickable]:x}),style:{...N,...U},ref:M},q,n.default.createElement(E,{className:c.default("react-tooltip-arrow",w.arrow,o,{[w.noArrow]:k}),style:V,ref:B})):null},S=({content:e})=>n.default.createElement("span",{dangerouslySetInnerHTML:{__html:e}});e.Tooltip=({id:e,anchorId:r,anchorSelect:o,content:l,html:c,render:s,className:a,classNameArrow:i,variant:u="dark",place:d="top",offset:f=10,wrapper:v="div",children:m=null,events:h=["hover"],openOnClick:y=!1,positionStrategy:w="absolute",middlewares:E,delayShow:b=0,delayHide:g=0,float:A=!1,hidden:T=!1,noArrow:k=!1,clickable:x=!1,closeOnEsc:O=!1,closeOnScroll:R=!1,closeOnResize:L=!1,style:N,position:C,isOpen:$,setIsOpen:j,afterShow:q,afterHide:H})=>{const[I,W]=t.useState(l),[D,z]=t.useState(c),[M,B]=t.useState(d),[P,K]=t.useState(u),[X,J]=t.useState(f),[U,F]=t.useState(b),[V,Z]=t.useState(g),[G,Y]=t.useState(A),[Q,ee]=t.useState(T),[te,re]=t.useState(v),[oe,le]=t.useState(h),[ne,ce]=t.useState(w),[se,ae]=t.useState(null),{anchorRefs:ie,activeAnchor:ue}=p(e),de=e=>null==e?void 0:e.getAttributeNames().reduce(((t,r)=>{var o;if(r.startsWith("data-tooltip-")){t[r.replace(/^data-tooltip-/,"")]=null!==(o=null==e?void 0:e.getAttribute(r))&&void 0!==o?o:null}return t}),{}),fe=e=>{const t={place:e=>{var t;B(null!==(t=e)&&void 0!==t?t:d)},content:e=>{W(null!=e?e:l)},html:e=>{z(null!=e?e:c)},variant:e=>{var t;K(null!==(t=e)&&void 0!==t?t:u)},offset:e=>{J(null===e?f:Number(e))},wrapper:e=>{var t;re(null!==(t=e)&&void 0!==t?t:v)},events:e=>{const t=null==e?void 0:e.split(" ");le(null!=t?t:h)},"position-strategy":e=>{var t;ce(null!==(t=e)&&void 0!==t?t:w)},"delay-show":e=>{F(null===e?b:Number(e))},"delay-hide":e=>{Z(null===e?g:Number(e))},float:e=>{Y(null===e?A:"true"===e)},hidden:e=>{ee(null===e?T:"true"===e)}};Object.values(t).forEach((e=>e(null))),Object.entries(e).forEach((([e,r])=>{var o;null===(o=t[e])||void 0===o||o.call(t,r)}))};t.useEffect((()=>{W(l)}),[l]),t.useEffect((()=>{z(c)}),[c]),t.useEffect((()=>{B(d)}),[d]),t.useEffect((()=>{K(u)}),[u]),t.useEffect((()=>{J(f)}),[f]),t.useEffect((()=>{F(b)}),[b]),t.useEffect((()=>{Z(g)}),[g]),t.useEffect((()=>{Y(A)}),[A]),t.useEffect((()=>{ee(T)}),[T]),t.useEffect((()=>{ce(w)}),[w]),t.useEffect((()=>{var t;const l=new Set(ie);let n=o;if(!n&&e&&(n=`[data-tooltip-id='${e}']`),n)try{document.querySelectorAll(n).forEach((e=>{l.add({current:e})}))}catch(e){console.warn(`[react-tooltip] "${n}" is not a valid CSS selector`)}const c=document.querySelector(`[id='${r}']`);if(c&&l.add({current:c}),!l.size)return()=>null;const s=null!==(t=null!=se?se:c)&&void 0!==t?t:ue.current,a=new MutationObserver((e=>{e.forEach((e=>{var t;if(!s||"attributes"!==e.type||!(null===(t=e.attributeName)||void 0===t?void 0:t.startsWith("data-tooltip-")))return;const r=de(s);fe(r)}))})),i={attributes:!0,childList:!1,subtree:!1};if(s){const e=de(s);fe(e),a.observe(s,i)}return()=>{a.disconnect()}}),[ie,ue,se,r,o]);let pe=m;const ve=t.useRef(null);if(s){const e=s({content:null!=I?I:null,activeAnchor:se});pe=e?n.default.createElement("div",{ref:ve,className:"react-tooltip-content-wrapper"},e):null}else I&&(pe=I);D&&(pe=n.default.createElement(S,{content:D}));const me={id:e,anchorId:r,anchorSelect:o,className:a,classNameArrow:i,content:pe,contentWrapperRef:ve,place:M,variant:P,offset:X,wrapper:te,events:oe,openOnClick:y,positionStrategy:ne,middlewares:E,delayShow:U,delayHide:V,float:G,hidden:Q,noArrow:k,clickable:x,closeOnEsc:O,closeOnScroll:R,closeOnResize:L,style:N,position:C,isOpen:$,setIsOpen:j,afterShow:q,afterHide:H,activeAnchor:se,setActiveAnchor:e=>ae(e)};return n.default.createElement(_,{...me})},e.TooltipProvider=({children:e})=>{const[r,o]=t.useState({[i]:new Set}),[l,c]=t.useState({[i]:{current:null}}),s=(e,...t)=>{o((r=>{var o;const l=null!==(o=r[e])&&void 0!==o?o:new Set;return t.forEach((e=>l.add(e))),{...r,[e]:new Set(l)}}))},a=(e,...t)=>{o((r=>{const o=r[e];return o?(t.forEach((e=>o.delete(e))),{...r}):r}))},u=t.useCallback(((e=i)=>{var t,o;return{anchorRefs:null!==(t=r[e])&&void 0!==t?t:new Set,activeAnchor:null!==(o=l[e])&&void 0!==o?o:{current:null},attach:(...t)=>s(e,...t),detach:(...t)=>a(e,...t),setActiveAnchor:t=>((e,t)=>{c((r=>{var o;return(null===(o=r[e])||void 0===o?void 0:o.current)===t.current?r:{...r,[e]:t}}))})(e,t)}}),[r,l,s,a]),d=t.useMemo((()=>({getTooltipData:u})),[u]);return n.default.createElement(f.Provider,{value:d},e)},e.TooltipWrapper=({tooltipId:e,children:r,className:o,place:l,content:s,html:a,variant:i,offset:u,wrapper:d,events:f,positionStrategy:v,delayShow:m,delayHide:h})=>{const{attach:y,detach:w}=p(e),_=t.useRef(null);return t.useEffect((()=>(y(_),()=>{w(_)})),[]),n.default.createElement("span",{ref:_,className:c.default("react-tooltip-wrapper",o),"data-tooltip-place":l,"data-tooltip-content":s,"data-tooltip-html":a,"data-tooltip-variant":i,"data-tooltip-offset":u,"data-tooltip-wrapper":d,"data-tooltip-events":f,"data-tooltip-position-strategy":v,"data-tooltip-delay-show":m,"data-tooltip-delay-hide":h},r)},Object.defineProperty(e,"__esModule",{value:!0})})); | ||
//# sourceMappingURL=react-tooltip.umd.min.js.map | ||
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports,require("react"),require("classnames"),require("@floating-ui/dom")):"function"==typeof define&&define.amd?define(["exports","react","classnames","@floating-ui/dom"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).ReactTooltip={},e.React,e.classNames,e.FloatingUIDOM)}(this,(function(e,t,r,o){"use strict";function n(e){return e&&"object"==typeof e&&"default"in e?e:{default:e}}var l=n(t),c=n(r);const s="react-tooltip-core-styles",a="react-tooltip-base-styles";function u({css:e,id:t=a,type:r="base",ref:o}){if("core"===r&&process.env.REACT_TOOLTIP_DISABLE_CORE_STYLES)return;if("core"!==r&&process.env.REACT_TOOLTIP_DISABLE_BASE_STYLES)return;"core"===r&&(t=s),o||(o={});const{insertAt:n}=o;if(!e||"undefined"==typeof document||document.getElementById(t))return;const l=document.head||document.getElementsByTagName("head")[0],c=document.createElement("style");c.id=t,c.type="text/css","top"===n&&l.firstChild?l.insertBefore(c,l.firstChild):l.appendChild(c),c.styleSheet?c.styleSheet.cssText=e:c.appendChild(document.createTextNode(e))}const i=(e,t,r)=>{let o=null;return function(...n){const l=()=>{o=null,r||e.apply(this,n)};r&&!o&&(e.apply(this,n),o=setTimeout(l,t)),r||(o&&clearTimeout(o),o=setTimeout(l,t))}},d="DEFAULT_TOOLTIP_ID",f={anchorRefs:new Set,activeAnchor:{current:null},attach:()=>{},detach:()=>{},setActiveAnchor:()=>{}},p={getTooltipData:()=>f},m=t.createContext(p);function v(e=d){return t.useContext(m).getTooltipData(e)}const y="undefined"!=typeof window?t.useLayoutEffect:t.useEffect,h=e=>{if(!(e instanceof HTMLElement||e instanceof SVGElement))return!1;const t=getComputedStyle(e);return["overflow","overflow-x","overflow-y"].some((e=>{const r=t.getPropertyValue(e);return"auto"===r||"scroll"===r}))},w=e=>{if(!e)return null;let t=e.parentElement;for(;t;){if(h(t))return t;t=t.parentElement}return document.scrollingElement||document.documentElement},E=async({elementReference:e=null,tooltipReference:t=null,tooltipArrowReference:r=null,place:n="top",offset:l=10,strategy:c="absolute",middlewares:s=[o.offset(Number(l)),o.flip(),o.shift({padding:5})]})=>{if(!e)return{tooltipStyles:{},tooltipArrowStyles:{},place:n};if(null===t)return{tooltipStyles:{},tooltipArrowStyles:{},place:n};const a=s;return r?(a.push(o.arrow({element:r,padding:5})),o.computePosition(e,t,{placement:n,strategy:c,middleware:a}).then((({x:e,y:t,placement:r,middlewareData:o})=>{var n,l;const c={left:`${e}px`,top:`${t}px`},{x:s,y:a}=null!==(n=o.arrow)&&void 0!==n?n:{x:0,y:0};return{tooltipStyles:c,tooltipArrowStyles:{left:null!=s?`${s}px`:"",top:null!=a?`${a}px`:"",right:"",bottom:"",[null!==(l={top:"bottom",right:"left",bottom:"top",left:"right"}[r.split("-")[0]])&&void 0!==l?l:"bottom"]:"-4px"},place:r}}))):o.computePosition(e,t,{placement:"bottom",strategy:c,middleware:a}).then((({x:e,y:t,placement:r})=>({tooltipStyles:{left:`${e}px`,top:`${t}px`},tooltipArrowStyles:{},place:r})))};var S="core-styles-module_tooltip__3vRRp",g="core-styles-module_fixed__pcSol",_="core-styles-module_arrow__cvMwQ",b="core-styles-module_noArrow__xock6",A="core-styles-module_clickable__ZuTTB",T="core-styles-module_show__Nt9eE",O={arrow:"styles-module_arrow__K0L3T",dark:"styles-module_dark__xNqje",light:"styles-module_light__Z6W-X",success:"styles-module_success__A2AKt",warning:"styles-module_warning__SCK0X",error:"styles-module_error__JvumD",info:"styles-module_info__BWdHW"};const R=({id:e,className:r,classNameArrow:o,variant:n="dark",anchorId:s,anchorSelect:a,place:u="top",offset:d=10,events:f=["hover"],openOnClick:p=!1,positionStrategy:m="absolute",middlewares:h,wrapper:R,delayShow:L=0,delayHide:x=0,float:k=!1,hidden:N=!1,noArrow:C=!1,clickable:I=!1,closeOnEsc:$=!1,closeOnScroll:j=!1,closeOnResize:q=!1,style:B,position:D,afterShow:H,afterHide:M,content:P,contentWrapperRef:W,isOpen:z,setIsOpen:F,activeAnchor:K,setActiveAnchor:X})=>{const Y=t.useRef(null),U=t.useRef(null),V=t.useRef(null),Z=t.useRef(null),[G,J]=t.useState(u),[Q,ee]=t.useState({}),[te,re]=t.useState({}),[oe,ne]=t.useState(!1),[le,ce]=t.useState(!1),se=t.useRef(!1),ae=t.useRef(null),{anchorRefs:ue,setActiveAnchor:ie}=v(e),de=t.useRef(!1),[fe,pe]=t.useState([]),me=t.useRef(!1),ve=p||f.includes("click");y((()=>(me.current=!0,()=>{me.current=!1})),[]),t.useEffect((()=>{if(!oe){const e=setTimeout((()=>{ce(!1)}),150);return()=>{clearTimeout(e)}}return()=>null}),[oe]);const ye=e=>{me.current&&(e&&ce(!0),setTimeout((()=>{me.current&&(null==F||F(e),void 0===z&&ne(e))}),10))};t.useEffect((()=>{if(void 0===z)return()=>null;z&&ce(!0);const e=setTimeout((()=>{ne(z)}),10);return()=>{clearTimeout(e)}}),[z]),t.useEffect((()=>{oe!==se.current&&(se.current=oe,oe?null==H||H():null==M||M())}),[oe]);const he=(e=x)=>{Z.current&&clearTimeout(Z.current),Z.current=setTimeout((()=>{de.current||ye(!1)}),e)},we=e=>{var t;if(!e)return;const r=null!==(t=e.currentTarget)&&void 0!==t?t:e.target;if(!(null==r?void 0:r.isConnected))return X(null),void ie({current:null});L?(V.current&&clearTimeout(V.current),V.current=setTimeout((()=>{ye(!0)}),L)):ye(!0),X(r),ie({current:r}),Z.current&&clearTimeout(Z.current)},Ee=()=>{I?he(x||100):x?he():ye(!1),V.current&&clearTimeout(V.current)},Se=({x:e,y:t})=>{E({place:u,offset:d,elementReference:{getBoundingClientRect:()=>({x:e,y:t,width:0,height:0,top:t,left:e,right:e,bottom:t})},tooltipReference:Y.current,tooltipArrowReference:U.current,strategy:m,middlewares:h}).then((e=>{Object.keys(e.tooltipStyles).length&&ee(e.tooltipStyles),Object.keys(e.tooltipArrowStyles).length&&re(e.tooltipArrowStyles),J(e.place)}))},ge=e=>{if(!e)return;const t=e,r={x:t.clientX,y:t.clientY};Se(r),ae.current=r},_e=e=>{we(e),x&&he()},be=e=>{var t;[document.querySelector(`[id='${s}']`),...fe].some((t=>null==t?void 0:t.contains(e.target)))||(null===(t=Y.current)||void 0===t?void 0:t.contains(e.target))||(ye(!1),V.current&&clearTimeout(V.current))},Ae=i(we,50,!0),Te=i(Ee,50,!0);t.useEffect((()=>{var e,t;const r=new Set(ue);fe.forEach((e=>{r.add({current:e})}));const o=document.querySelector(`[id='${s}']`);o&&r.add({current:o});const n=()=>{ye(!1)},l=w(K),c=w(Y.current);j&&(window.addEventListener("scroll",n),null==l||l.addEventListener("scroll",n),null==c||c.addEventListener("scroll",n)),q&&window.addEventListener("resize",n);const a=e=>{"Escape"===e.key&&ye(!1)};$&&window.addEventListener("keydown",a);const u=[];ve?(window.addEventListener("click",be),u.push({event:"click",listener:_e})):(u.push({event:"mouseenter",listener:Ae},{event:"mouseleave",listener:Te},{event:"focus",listener:Ae},{event:"blur",listener:Te}),k&&u.push({event:"mousemove",listener:ge}));const i=()=>{de.current=!0},d=()=>{de.current=!1,Ee()};return I&&!ve&&(null===(e=Y.current)||void 0===e||e.addEventListener("mouseenter",i),null===(t=Y.current)||void 0===t||t.addEventListener("mouseleave",d)),u.forEach((({event:e,listener:t})=>{r.forEach((r=>{var o;null===(o=r.current)||void 0===o||o.addEventListener(e,t)}))})),()=>{var e,t;j&&(window.removeEventListener("scroll",n),null==l||l.removeEventListener("scroll",n),null==c||c.removeEventListener("scroll",n)),q&&window.removeEventListener("resize",n),ve&&window.removeEventListener("click",be),$&&window.removeEventListener("keydown",a),I&&!ve&&(null===(e=Y.current)||void 0===e||e.removeEventListener("mouseenter",i),null===(t=Y.current)||void 0===t||t.removeEventListener("mouseleave",d)),u.forEach((({event:e,listener:t})=>{r.forEach((r=>{var o;null===(o=r.current)||void 0===o||o.removeEventListener(e,t)}))}))}}),[le,ue,fe,$,f]),t.useEffect((()=>{let t=null!=a?a:"";!t&&e&&(t=`[data-tooltip-id='${e}']`);const r=new MutationObserver((r=>{const o=[];r.forEach((r=>{if("attributes"===r.type&&"data-tooltip-id"===r.attributeName){r.target.getAttribute("data-tooltip-id")===e&&o.push(r.target)}if("childList"===r.type&&(K&&[...r.removedNodes].some((e=>{var t;return!!(null===(t=null==e?void 0:e.contains)||void 0===t?void 0:t.call(e,K))&&(ce(!1),ye(!1),X(null),V.current&&clearTimeout(V.current),Z.current&&clearTimeout(Z.current),!0)})),t))try{const e=[...r.addedNodes].filter((e=>1===e.nodeType));o.push(...e.filter((e=>e.matches(t)))),o.push(...e.flatMap((e=>[...e.querySelectorAll(t)])))}catch(e){}})),o.length&&pe((e=>[...e,...o]))}));return r.observe(document.body,{childList:!0,subtree:!0,attributes:!0,attributeFilter:["data-tooltip-id"]}),()=>{r.disconnect()}}),[e,a,K]);const Oe=()=>{D?Se(D):k?ae.current&&Se(ae.current):E({place:u,offset:d,elementReference:K,tooltipReference:Y.current,tooltipArrowReference:U.current,strategy:m,middlewares:h}).then((e=>{me.current&&(Object.keys(e.tooltipStyles).length&&ee(e.tooltipStyles),Object.keys(e.tooltipArrowStyles).length&&re(e.tooltipArrowStyles),J(e.place))}))};t.useEffect((()=>{Oe()}),[oe,K,P,B,u,d,m,D]),t.useEffect((()=>{if(!(null==W?void 0:W.current))return()=>null;const e=new ResizeObserver((()=>{Oe()}));return e.observe(W.current),()=>{e.disconnect()}}),[P,null==W?void 0:W.current]),t.useEffect((()=>{var e;const t=document.querySelector(`[id='${s}']`),r=[...fe,t];K&&r.includes(K)||X(null!==(e=fe[0])&&void 0!==e?e:t)}),[s,fe,K]),t.useEffect((()=>()=>{V.current&&clearTimeout(V.current),Z.current&&clearTimeout(Z.current)}),[]),t.useEffect((()=>{let t=a;if(!t&&e&&(t=`[data-tooltip-id='${e}']`),t)try{const e=Array.from(document.querySelectorAll(t));pe(e)}catch(e){pe([])}}),[e,a]);const Re=!N&&P&&oe&&Object.keys(Q).length>0;return le?l.default.createElement(R,{id:e,role:"tooltip",className:c.default("react-tooltip",S,O[n],r,`react-tooltip__place-${G}`,{[T]:Re,[g]:"fixed"===m,[A]:I}),style:{...B,...Q},ref:Y},P,l.default.createElement(R,{className:c.default("react-tooltip-arrow",_,O.arrow,o,{[b]:C}),style:te,ref:U})):null},L=({content:e})=>l.default.createElement("span",{dangerouslySetInnerHTML:{__html:e}});u({css:`:root{--rt-color-white:#fff;--rt-color-dark:#222;--rt-color-success:#8dc572;--rt-color-error:#be6464;--rt-color-warning:#f0ad4e;--rt-color-info:#337ab7;--rt-opacity:0.9}.core-styles-module_tooltip__3vRRp{visibility:hidden;width:max-content;position:absolute;top:0;left:0;padding:8px 16px;border-radius:3px;font-size:90%;pointer-events:none;opacity:0;transition:opacity 0.3s ease-out;will-change:opacity,visibility}.core-styles-module_fixed__pcSol{position:fixed}.core-styles-module_arrow__cvMwQ{position:absolute;background:inherit}.core-styles-module_noArrow__xock6{display:none}.core-styles-module_clickable__ZuTTB{pointer-events:auto}.core-styles-module_show__Nt9eE{visibility:visible;opacity:var(--rt-opacity)}`,type:"core"}),u({css:` | ||
.styles-module_arrow__K0L3T{width:8px;height:8px;transform:rotate(45deg)}.styles-module_dark__xNqje{background:var(--rt-color-dark);color:var(--rt-color-white)}.styles-module_light__Z6W-X{background-color:var(--rt-color-white);color:var(--rt-color-dark)}.styles-module_success__A2AKt{background-color:var(--rt-color-success);color:var(--rt-color-white)}.styles-module_warning__SCK0X{background-color:var(--rt-color-warning);color:var(--rt-color-white)}.styles-module_error__JvumD{background-color:var(--rt-color-error);color:var(--rt-color-white)}.styles-module_info__BWdHW{background-color:var(--rt-color-info);color:var(--rt-color-white)}`}),e.Tooltip=({id:e,anchorId:r,anchorSelect:o,content:n,html:c,render:s,className:a,classNameArrow:u,variant:i="dark",place:d="top",offset:f=10,wrapper:p="div",children:m=null,events:y=["hover"],openOnClick:h=!1,positionStrategy:w="absolute",middlewares:E,delayShow:S=0,delayHide:g=0,float:_=!1,hidden:b=!1,noArrow:A=!1,clickable:T=!1,closeOnEsc:O=!1,closeOnScroll:x=!1,closeOnResize:k=!1,style:N,position:C,isOpen:I,setIsOpen:$,afterShow:j,afterHide:q})=>{const[B,D]=t.useState(n),[H,M]=t.useState(c),[P,W]=t.useState(d),[z,F]=t.useState(i),[K,X]=t.useState(f),[Y,U]=t.useState(S),[V,Z]=t.useState(g),[G,J]=t.useState(_),[Q,ee]=t.useState(b),[te,re]=t.useState(p),[oe,ne]=t.useState(y),[le,ce]=t.useState(w),[se,ae]=t.useState(null),{anchorRefs:ue,activeAnchor:ie}=v(e),de=e=>null==e?void 0:e.getAttributeNames().reduce(((t,r)=>{var o;if(r.startsWith("data-tooltip-")){t[r.replace(/^data-tooltip-/,"")]=null!==(o=null==e?void 0:e.getAttribute(r))&&void 0!==o?o:null}return t}),{}),fe=e=>{const t={place:e=>{var t;W(null!==(t=e)&&void 0!==t?t:d)},content:e=>{D(null!=e?e:n)},html:e=>{M(null!=e?e:c)},variant:e=>{var t;F(null!==(t=e)&&void 0!==t?t:i)},offset:e=>{X(null===e?f:Number(e))},wrapper:e=>{var t;re(null!==(t=e)&&void 0!==t?t:p)},events:e=>{const t=null==e?void 0:e.split(" ");ne(null!=t?t:y)},"position-strategy":e=>{var t;ce(null!==(t=e)&&void 0!==t?t:w)},"delay-show":e=>{U(null===e?S:Number(e))},"delay-hide":e=>{Z(null===e?g:Number(e))},float:e=>{J(null===e?_:"true"===e)},hidden:e=>{ee(null===e?b:"true"===e)}};Object.values(t).forEach((e=>e(null))),Object.entries(e).forEach((([e,r])=>{var o;null===(o=t[e])||void 0===o||o.call(t,r)}))};t.useEffect((()=>{D(n)}),[n]),t.useEffect((()=>{M(c)}),[c]),t.useEffect((()=>{W(d)}),[d]),t.useEffect((()=>{F(i)}),[i]),t.useEffect((()=>{X(f)}),[f]),t.useEffect((()=>{U(S)}),[S]),t.useEffect((()=>{Z(g)}),[g]),t.useEffect((()=>{J(_)}),[_]),t.useEffect((()=>{ee(b)}),[b]),t.useEffect((()=>{ce(w)}),[w]),t.useEffect((()=>{var t;const n=new Set(ue);let l=o;if(!l&&e&&(l=`[data-tooltip-id='${e}']`),l)try{document.querySelectorAll(l).forEach((e=>{n.add({current:e})}))}catch(e){console.warn(`[react-tooltip] "${l}" is not a valid CSS selector`)}const c=document.querySelector(`[id='${r}']`);if(c&&n.add({current:c}),!n.size)return()=>null;const s=null!==(t=null!=se?se:c)&&void 0!==t?t:ie.current,a=new MutationObserver((e=>{e.forEach((e=>{var t;if(!s||"attributes"!==e.type||!(null===(t=e.attributeName)||void 0===t?void 0:t.startsWith("data-tooltip-")))return;const r=de(s);fe(r)}))})),u={attributes:!0,childList:!1,subtree:!1};if(s){const e=de(s);fe(e),a.observe(s,u)}return()=>{a.disconnect()}}),[ue,ie,se,r,o]);let pe=m;const me=t.useRef(null);if(s){const e=s({content:null!=B?B:null,activeAnchor:se});pe=e?l.default.createElement("div",{ref:me,className:"react-tooltip-content-wrapper"},e):null}else B&&(pe=B);H&&(pe=l.default.createElement(L,{content:H}));const ve={id:e,anchorId:r,anchorSelect:o,className:a,classNameArrow:u,content:pe,contentWrapperRef:me,place:P,variant:z,offset:K,wrapper:te,events:oe,openOnClick:h,positionStrategy:le,middlewares:E,delayShow:Y,delayHide:V,float:G,hidden:Q,noArrow:A,clickable:T,closeOnEsc:O,closeOnScroll:x,closeOnResize:k,style:N,position:C,isOpen:I,setIsOpen:$,afterShow:j,afterHide:q,activeAnchor:se,setActiveAnchor:e=>ae(e)};return l.default.createElement(R,{...ve})},e.TooltipProvider=({children:e})=>{const[r,o]=t.useState({[d]:new Set}),[n,c]=t.useState({[d]:{current:null}}),s=(e,...t)=>{o((r=>{var o;const n=null!==(o=r[e])&&void 0!==o?o:new Set;return t.forEach((e=>n.add(e))),{...r,[e]:new Set(n)}}))},a=(e,...t)=>{o((r=>{const o=r[e];return o?(t.forEach((e=>o.delete(e))),{...r}):r}))},u=t.useCallback(((e=d)=>{var t,o;return{anchorRefs:null!==(t=r[e])&&void 0!==t?t:new Set,activeAnchor:null!==(o=n[e])&&void 0!==o?o:{current:null},attach:(...t)=>s(e,...t),detach:(...t)=>a(e,...t),setActiveAnchor:t=>((e,t)=>{c((r=>{var o;return(null===(o=r[e])||void 0===o?void 0:o.current)===t.current?r:{...r,[e]:t}}))})(e,t)}}),[r,n,s,a]),i=t.useMemo((()=>({getTooltipData:u})),[u]);return l.default.createElement(m.Provider,{value:i},e)},e.TooltipWrapper=({tooltipId:e,children:r,className:o,place:n,content:s,html:a,variant:u,offset:i,wrapper:d,events:f,positionStrategy:p,delayShow:m,delayHide:y})=>{const{attach:h,detach:w}=v(e),E=t.useRef(null);return t.useEffect((()=>(h(E),()=>{w(E)})),[]),l.default.createElement("span",{ref:E,className:c.default("react-tooltip-wrapper",o),"data-tooltip-place":n,"data-tooltip-content":s,"data-tooltip-html":a,"data-tooltip-variant":u,"data-tooltip-offset":i,"data-tooltip-wrapper":d,"data-tooltip-events":f,"data-tooltip-position-strategy":p,"data-tooltip-delay-show":m,"data-tooltip-delay-hide":y},r)},e.removeStyle=function({type:e="base",id:t=a}){"core"===e&&(t=s);const r=document.getElementById(t);null==r||r.remove()},Object.defineProperty(e,"__esModule",{value:!0})})); |
{ | ||
"name": "react-tooltip", | ||
"version": "5.15.0", | ||
"version": "5.16.0-beta.10410.0", | ||
"description": "react tooltip component", | ||
@@ -5,0 +5,0 @@ "scripts": { |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 2 instances in 1 package
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 1 instance in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
634849
3928
27
3
13