react-tooltip
Version:
react tooltip component
9 lines (8 loc) • 16.4 kB
JavaScript
/*
* React Tooltip
* {@link https://github.com/ReactTooltip/react-tooltip}
* @copyright ReactTooltip Team
* @license MIT
*/
import e,{createContext as t,useState as r,useCallback as o,useMemo as n,useContext as l,useRef as c,useEffect as i,useLayoutEffect as s}from"react";import a from"classnames";import{arrow as u,computePosition as d,offset as p,flip as v,shift as m}from"@floating-ui/dom";const f="react-tooltip-core-styles",y="react-tooltip-base-styles";function h({css:e,id:t=y,type:r="base",ref:o}){var n,l;if("core"===r&&"undefined"!=typeof process&&(null===(n=null===process||void 0===process?void 0:process.env)||void 0===n?void 0:n.REACT_TOOLTIP_DISABLE_CORE_STYLES))return;if("core"!==r&&"undefined"!=typeof process&&(null===(l=null===process||void 0===process?void 0:process.env)||void 0===l?void 0:l.REACT_TOOLTIP_DISABLE_BASE_STYLES))return;"core"===r&&(t=f),o||(o={});const{insertAt:c}=o;if(!e||"undefined"==typeof document||document.getElementById(t))return;const i=document.head||document.getElementsByTagName("head")[0],s=document.createElement("style");s.id=t,s.type="text/css","top"===c&&i.firstChild?i.insertBefore(s,i.firstChild):i.appendChild(s),s.styleSheet?s.styleSheet.cssText=e:s.appendChild(document.createTextNode(e))}function w({type:e="base",id:t=y}={}){"core"===e&&(t=f);const r=document.getElementById(t);null==r||r.remove()}const b=(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))}},S="DEFAULT_TOOLTIP_ID",E={anchorRefs:new Set,activeAnchor:{current:null},attach:()=>{},detach:()=>{},setActiveAnchor:()=>{}},_=t({getTooltipData:()=>E}),g=({children:t})=>{const[l,c]=r({[S]:new Set}),[i,s]=r({[S]:{current:null}}),a=(e,...t)=>{c((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)}}))},u=(e,...t)=>{c((r=>{const o=r[e];return o?(t.forEach((e=>o.delete(e))),{...r}):r}))},d=o(((e=S)=>{var t,r;return{anchorRefs:null!==(t=l[e])&&void 0!==t?t:new Set,activeAnchor:null!==(r=i[e])&&void 0!==r?r:{current:null},attach:(...t)=>a(e,...t),detach:(...t)=>u(e,...t),setActiveAnchor:t=>((e,t)=>{s((r=>{var o;return(null===(o=r[e])||void 0===o?void 0:o.current)===t.current?r:{...r,[e]:t}}))})(e,t)}}),[l,i,a,u]),p=n((()=>({getTooltipData:d})),[d]);return e.createElement(_.Provider,{value:p},t)};function A(e=S){return l(_).getTooltipData(e)}const T=({tooltipId:t,children:r,className:o,place:n,content:l,html:s,variant:u,offset:d,wrapper:p,events:v,positionStrategy:m,delayShow:f,delayHide:y})=>{const{attach:h,detach:w}=A(t),b=c(null);return i((()=>(h(b),()=>{w(b)})),[]),e.createElement("span",{ref:b,className:a("react-tooltip-wrapper",o),"data-tooltip-place":n,"data-tooltip-content":l,"data-tooltip-html":s,"data-tooltip-variant":u,"data-tooltip-offset":d,"data-tooltip-wrapper":p,"data-tooltip-events":v,"data-tooltip-position-strategy":m,"data-tooltip-delay-show":f,"data-tooltip-delay-hide":y},r)},O="undefined"!=typeof window?s:i,L=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}))},R=e=>{if(!e)return null;let t=e.parentElement;for(;t;){if(L(t))return t;t=t.parentElement}return document.scrollingElement||document.documentElement},N=async({elementReference:e=null,tooltipReference:t=null,tooltipArrowReference:r=null,place:o="top",offset:n=10,strategy:l="absolute",middlewares:c=[p(Number(n)),v(),m({padding:5})],border:i})=>{if(!e)return{tooltipStyles:{},tooltipArrowStyles:{},place:o};if(null===t)return{tooltipStyles:{},tooltipArrowStyles:{},place:o};const s=c;return r?(s.push(u({element:r,padding:5})),d(e,t,{placement:o,strategy:l,middleware:s}).then((({x:e,y:t,placement:r,middlewareData:o})=>{var n,l;const c={left:`${e}px`,top:`${t}px`,border:i},{x:s,y:a}=null!==(n=o.arrow)&&void 0!==n?n:{x:0,y:0},u=null!==(l={top:"bottom",right:"left",bottom:"top",left:"right"}[r.split("-")[0]])&&void 0!==l?l:"bottom",d=i&&{top:{borderBottom:i,borderRight:i},right:{borderBottom:i,borderLeft:i},bottom:{borderTop:i,borderLeft:i},left:{borderTop:i,borderRight:i}}[r.split("-")[0]];let p=0;if(i){const e=`${i}`.match(/(\d+)px/);p=(null==e?void 0:e[1])?Number(e[1]):1}return{tooltipStyles:c,tooltipArrowStyles:{left:null!=s?`${s}px`:"",top:null!=a?`${a}px`:"",right:"",bottom:"",...d,[u]:`-${4+p}px`},place:r}}))):d(e,t,{placement:"bottom",strategy:l,middleware:s}).then((({x:e,y:t,placement:r})=>({tooltipStyles:{left:`${e}px`,top:`${t}px`},tooltipArrowStyles:{},place:r})))};var k="core-styles-module_tooltip__3vRRp",x="core-styles-module_fixed__pcSol",$="core-styles-module_arrow__cvMwQ",C="core-styles-module_noArrow__xock6",I="core-styles-module_clickable__ZuTTB",B="core-styles-module_show__Nt9eE",D={tooltip:"styles-module_tooltip__mnnfp",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 H=({id:t,className:o,classNameArrow:n,variant:l="dark",anchorId:s,anchorSelect:u,place:d="top",offset:p=10,events:v=["hover"],openOnClick:m=!1,positionStrategy:f="absolute",middlewares:y,wrapper:h,delayShow:w=0,delayHide:S=0,float:E=!1,hidden:_=!1,noArrow:g=!1,clickable:T=!1,closeOnEsc:L=!1,closeOnScroll:H=!1,closeOnResize:j=!1,style:q,position:z,afterShow:W,afterHide:M,content:P,contentWrapperRef:K,isOpen:U,setIsOpen:X,activeAnchor:Y,setActiveAnchor:F,border:V,opacity:Z})=>{const G=c(null),J=c(null),Q=c(null),ee=c(null),[te,re]=r(d),[oe,ne]=r({}),[le,ce]=r({}),[ie,se]=r(!1),[ae,ue]=r(!1),de=c(!1),pe=c(null),{anchorRefs:ve,setActiveAnchor:me}=A(t),fe=c(!1),[ye,he]=r([]),we=c(!1),be=m||v.includes("click");O((()=>(we.current=!0,()=>{we.current=!1})),[]),i((()=>{if(!ie){const e=setTimeout((()=>{ue(!1)}),150);return()=>{clearTimeout(e)}}return()=>null}),[ie]);const Se=e=>{we.current&&(e&&ue(!0),setTimeout((()=>{we.current&&(null==X||X(e),void 0===U&&se(e))}),10))};i((()=>{if(void 0===U)return()=>null;U&&ue(!0);const e=setTimeout((()=>{se(U)}),10);return()=>{clearTimeout(e)}}),[U]),i((()=>{ie!==de.current&&(de.current=ie,ie?null==W||W():null==M||M())}),[ie]);const Ee=(e=S)=>{ee.current&&clearTimeout(ee.current),ee.current=setTimeout((()=>{fe.current||Se(!1)}),e)},_e=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 F(null),void me({current:null});w?(Q.current&&clearTimeout(Q.current),Q.current=setTimeout((()=>{Se(!0)}),w)):Se(!0),F(r),me({current:r}),ee.current&&clearTimeout(ee.current)},ge=()=>{T?Ee(S||100):S?Ee():Se(!1),Q.current&&clearTimeout(Q.current)},Ae=({x:e,y:t})=>{N({place:d,offset:p,elementReference:{getBoundingClientRect:()=>({x:e,y:t,width:0,height:0,top:t,left:e,right:e,bottom:t})},tooltipReference:G.current,tooltipArrowReference:J.current,strategy:f,middlewares:y,border:V}).then((e=>{Object.keys(e.tooltipStyles).length&&ne(e.tooltipStyles),Object.keys(e.tooltipArrowStyles).length&&ce(e.tooltipArrowStyles),re(e.place)}))},Te=e=>{if(!e)return;const t=e,r={x:t.clientX,y:t.clientY};Ae(r),pe.current=r},Oe=e=>{_e(e),S&&Ee()},Le=e=>{var t;[document.querySelector(`[id='${s}']`),...ye].some((t=>null==t?void 0:t.contains(e.target)))||(null===(t=G.current)||void 0===t?void 0:t.contains(e.target))||(Se(!1),Q.current&&clearTimeout(Q.current))},Re=b(_e,50,!0),Ne=b(ge,50,!0);i((()=>{var e,t;const r=new Set(ve);ye.forEach((e=>{r.add({current:e})}));const o=document.querySelector(`[id='${s}']`);o&&r.add({current:o});const n=()=>{Se(!1)},l=R(Y),c=R(G.current);H&&(window.addEventListener("scroll",n),null==l||l.addEventListener("scroll",n),null==c||c.addEventListener("scroll",n)),j&&window.addEventListener("resize",n);const i=e=>{"Escape"===e.key&&Se(!1)};L&&window.addEventListener("keydown",i);const a=[];be?(window.addEventListener("click",Le),a.push({event:"click",listener:Oe})):(a.push({event:"mouseenter",listener:Re},{event:"mouseleave",listener:Ne},{event:"focus",listener:Re},{event:"blur",listener:Ne}),E&&a.push({event:"mousemove",listener:Te}));const u=()=>{fe.current=!0},d=()=>{fe.current=!1,ge()};return T&&!be&&(null===(e=G.current)||void 0===e||e.addEventListener("mouseenter",u),null===(t=G.current)||void 0===t||t.addEventListener("mouseleave",d)),a.forEach((({event:e,listener:t})=>{r.forEach((r=>{var o;null===(o=r.current)||void 0===o||o.addEventListener(e,t)}))})),()=>{var e,t;H&&(window.removeEventListener("scroll",n),null==l||l.removeEventListener("scroll",n),null==c||c.removeEventListener("scroll",n)),j&&window.removeEventListener("resize",n),be&&window.removeEventListener("click",Le),L&&window.removeEventListener("keydown",i),T&&!be&&(null===(e=G.current)||void 0===e||e.removeEventListener("mouseenter",u),null===(t=G.current)||void 0===t||t.removeEventListener("mouseleave",d)),a.forEach((({event:e,listener:t})=>{r.forEach((r=>{var o;null===(o=r.current)||void 0===o||o.removeEventListener(e,t)}))}))}}),[ae,ve,ye,L,v]),i((()=>{let e=null!=u?u:"";!e&&t&&(e=`[data-tooltip-id='${t}']`);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")===t&&o.push(r.target)}if("childList"===r.type&&(Y&&[...r.removedNodes].some((e=>{var t;return!!(null===(t=null==e?void 0:e.contains)||void 0===t?void 0:t.call(e,Y))&&(ue(!1),Se(!1),F(null),Q.current&&clearTimeout(Q.current),ee.current&&clearTimeout(ee.current),!0)})),e))try{const t=[...r.addedNodes].filter((e=>1===e.nodeType));o.push(...t.filter((t=>t.matches(e)))),o.push(...t.flatMap((t=>[...t.querySelectorAll(e)])))}catch(e){}})),o.length&&he((e=>[...e,...o]))}));return r.observe(document.body,{childList:!0,subtree:!0,attributes:!0,attributeFilter:["data-tooltip-id"]}),()=>{r.disconnect()}}),[t,u,Y]);const ke=()=>{z?Ae(z):E?pe.current&&Ae(pe.current):N({place:d,offset:p,elementReference:Y,tooltipReference:G.current,tooltipArrowReference:J.current,strategy:f,middlewares:y,border:V}).then((e=>{we.current&&(Object.keys(e.tooltipStyles).length&&ne(e.tooltipStyles),Object.keys(e.tooltipArrowStyles).length&&ce(e.tooltipArrowStyles),re(e.place))}))};i((()=>{ke()}),[ie,Y,P,q,d,p,f,z]),i((()=>{if(!(null==K?void 0:K.current))return()=>null;const e=new ResizeObserver((()=>{ke()}));return e.observe(K.current),()=>{e.disconnect()}}),[P,null==K?void 0:K.current]),i((()=>{var e;const t=document.querySelector(`[id='${s}']`),r=[...ye,t];Y&&r.includes(Y)||F(null!==(e=ye[0])&&void 0!==e?e:t)}),[s,ye,Y]),i((()=>()=>{Q.current&&clearTimeout(Q.current),ee.current&&clearTimeout(ee.current)}),[]),i((()=>{let e=u;if(!e&&t&&(e=`[data-tooltip-id='${t}']`),e)try{const t=Array.from(document.querySelectorAll(e));he(t)}catch(e){he([])}}),[t,u]);const xe=!_&&P&&ie&&Object.keys(oe).length>0;return ae?e.createElement(h,{id:t,role:"tooltip",className:a("react-tooltip",k,D.tooltip,D[l],o,`react-tooltip__place-${te}`,{[B]:xe,[x]:"fixed"===f,[I]:T}),style:{...q,...oe,opacity:void 0!==Z&&xe?Z:void 0},ref:G},P,e.createElement(h,{className:a("react-tooltip-arrow",$,D.arrow,n,{[C]:g}),style:le,ref:J})):null},j=({content:t})=>e.createElement("span",{dangerouslySetInnerHTML:{__html:t}}),q=({id:t,anchorId:o,anchorSelect:n,content:l,html:s,render:a,className:u,classNameArrow:d,variant:p="dark",place:v="top",offset:m=10,wrapper:f="div",children:y=null,events:h=["hover"],openOnClick:w=!1,positionStrategy:b="absolute",middlewares:S,delayShow:E=0,delayHide:_=0,float:g=!1,hidden:T=!1,noArrow:O=!1,clickable:L=!1,closeOnEsc:R=!1,closeOnScroll:N=!1,closeOnResize:k=!1,style:x,position:$,isOpen:C,border:I,opacity:B,setIsOpen:D,afterShow:q,afterHide:z})=>{const[W,M]=r(l),[P,K]=r(s),[U,X]=r(v),[Y,F]=r(p),[V,Z]=r(m),[G,J]=r(E),[Q,ee]=r(_),[te,re]=r(g),[oe,ne]=r(T),[le,ce]=r(f),[ie,se]=r(h),[ae,ue]=r(b),[de,pe]=r(null),{anchorRefs:ve,activeAnchor:me}=A(t),fe=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}),{}),ye=e=>{const t={place:e=>{var t;X(null!==(t=e)&&void 0!==t?t:v)},content:e=>{M(null!=e?e:l)},html:e=>{K(null!=e?e:s)},variant:e=>{var t;F(null!==(t=e)&&void 0!==t?t:p)},offset:e=>{Z(null===e?m:Number(e))},wrapper:e=>{var t;ce(null!==(t=e)&&void 0!==t?t:f)},events:e=>{const t=null==e?void 0:e.split(" ");se(null!=t?t:h)},"position-strategy":e=>{var t;ue(null!==(t=e)&&void 0!==t?t:b)},"delay-show":e=>{J(null===e?E:Number(e))},"delay-hide":e=>{ee(null===e?_:Number(e))},float:e=>{re(null===e?g:"true"===e)},hidden:e=>{ne(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)}))};i((()=>{M(l)}),[l]),i((()=>{K(s)}),[s]),i((()=>{X(v)}),[v]),i((()=>{F(p)}),[p]),i((()=>{Z(m)}),[m]),i((()=>{J(E)}),[E]),i((()=>{ee(_)}),[_]),i((()=>{re(g)}),[g]),i((()=>{ne(T)}),[T]),i((()=>{ue(b)}),[b]),i((()=>{var e;const r=new Set(ve);let l=n;if(!l&&t&&(l=`[data-tooltip-id='${t}']`),l)try{document.querySelectorAll(l).forEach((e=>{r.add({current:e})}))}catch(e){console.warn(`[react-tooltip] "${l}" is not a valid CSS selector`)}const c=document.querySelector(`[id='${o}']`);if(c&&r.add({current:c}),!r.size)return()=>null;const i=null!==(e=null!=de?de:c)&&void 0!==e?e:me.current,s=new MutationObserver((e=>{e.forEach((e=>{var t;if(!i||"attributes"!==e.type||!(null===(t=e.attributeName)||void 0===t?void 0:t.startsWith("data-tooltip-")))return;const r=fe(i);ye(r)}))})),a={attributes:!0,childList:!1,subtree:!1};if(i){const e=fe(i);ye(e),s.observe(i,a)}return()=>{s.disconnect()}}),[ve,me,de,o,n]),i((()=>{(null==x?void 0:x.border)&&console.warn("[react-tooltip] Do not set `style.border`. Use `border` prop instead."),I&&!CSS.supports("border",`${I}`)&&console.warn(`[react-tooltip] "${I}" is not a valid \`border\`.`),(null==x?void 0:x.opacity)&&console.warn("[react-tooltip] Do not set `style.opacity`. Use `opacity` prop instead."),B&&!CSS.supports("opacity",`${B}`)&&console.warn(`[react-tooltip] "${B}" is not a valid \`opacity\`.`)}),[]);let he=y;const we=c(null);if(a){const t=a({content:null!=W?W:null,activeAnchor:de});he=t?e.createElement("div",{ref:we,className:"react-tooltip-content-wrapper"},t):null}else W&&(he=W);P&&(he=e.createElement(j,{content:P}));const be={id:t,anchorId:o,anchorSelect:n,className:u,classNameArrow:d,content:he,contentWrapperRef:we,place:U,variant:Y,offset:V,wrapper:le,events:ie,openOnClick:w,positionStrategy:ae,middlewares:S,delayShow:G,delayHide:Q,float:te,hidden:oe,noArrow:O,clickable:L,closeOnEsc:R,closeOnScroll:N,closeOnResize:k,style:x,position:$,isOpen:C,border:I,opacity:B,setIsOpen:D,afterShow:q,afterHide:z,activeAnchor:de,setActiveAnchor:e=>pe(e)};return e.createElement(H,{...be})};h({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;position:absolute;top:0;left:0;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"}),h({css:`
.styles-module_tooltip__mnnfp{padding:8px 16px;border-radius:3px;font-size:90%;width:max-content}.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)}`});export{q as Tooltip,g as TooltipProvider,T as TooltipWrapper,w as removeStyle};