zero-tooltip 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ (function(N,B){typeof exports=="object"&&typeof module<"u"?module.exports=B():typeof define=="function"&&define.amd?define(B):(N=typeof globalThis<"u"?globalThis:N||self,N.ZeroTooltip=B())})(this,function(){"use strict";function N(){for(var e=0,n,i,t="";e<arguments.length;)(n=arguments[e++])&&(i=B(n))&&(t&&(t+=" "),t+=i);return t}function B(e){if(typeof e=="string")return e;for(var n,i="",t=0;t<e.length;t++)e[t]&&(n=B(e[t]))&&(i&&(i+=" "),i+=n);return i}var Y="-";function ce(e){var n=be(e),i=e.conflictingClassGroups,t=e.conflictingClassGroupModifiers,l=t===void 0?{}:t;function a(s){var m=s.split(Y);return m[0]===""&&m.length!==1&&m.shift(),oe(m,n)||fe(s)}function o(s,m){var f=i[s]||[];return m&&l[s]?[].concat(f,l[s]):f}return{getClassGroupId:a,getConflictingClassGroupIds:o}}function oe(e,n){var o;if(e.length===0)return n.classGroupId;var i=e[0],t=n.nextPart.get(i),l=t?oe(e.slice(1),t):void 0;if(l)return l;if(n.validators.length!==0){var a=e.join(Y);return(o=n.validators.find(function(s){var m=s.validator;return m(a)}))==null?void 0:o.classGroupId}}var ne=/^\[(.+)\]$/;function fe(e){if(ne.test(e)){var n=ne.exec(e)[1],i=n==null?void 0:n.substring(0,n.indexOf(":"));if(i)return"arbitrary.."+i}}function be(e){var n=e.theme,i=e.prefix,t={nextPart:new Map,validators:[]},l=me(Object.entries(e.classGroups),i);return l.forEach(function(a){var o=a[0],s=a[1];D(s,t,o,n)}),t}function D(e,n,i,t){e.forEach(function(l){if(typeof l=="string"){var a=l===""?n:ie(n,l);a.classGroupId=i;return}if(typeof l=="function"){if(he(l)){D(l(t),n,i,t);return}n.validators.push({validator:l,classGroupId:i});return}Object.entries(l).forEach(function(o){var s=o[0],m=o[1];D(m,ie(n,s),i,t)})})}function ie(e,n){var i=e;return n.split(Y).forEach(function(t){i.nextPart.has(t)||i.nextPart.set(t,{nextPart:new Map,validators:[]}),i=i.nextPart.get(t)}),i}function he(e){return e.isThemeGetter}function me(e,n){return n?e.map(function(i){var t=i[0],l=i[1],a=l.map(function(o){return typeof o=="string"?n+o:typeof o=="object"?Object.fromEntries(Object.entries(o).map(function(s){var m=s[0],f=s[1];return[n+m,f]})):o});return[t,a]}):e}function ge(e){if(e<1)return{get:function(){},set:function(){}};var n=0,i=new Map,t=new Map;function l(a,o){i.set(a,o),n++,n>e&&(n=0,t=i,i=new Map)}return{get:function(o){var s=i.get(o);if(s!==void 0)return s;if((s=t.get(o))!==void 0)return l(o,s),s},set:function(o,s){i.has(o)?i.set(o,s):l(o,s)}}}var se="!";function ve(e){var n=e.separator||":",i=n.length===1,t=n[0],l=n.length;return function(o){for(var s=[],m=0,f=0,p,w=0;w<o.length;w++){var y=o[w];if(m===0){if(y===t&&(i||o.slice(w,w+l)===n)){s.push(o.slice(f,w)),f=w+l;continue}if(y==="/"){p=w;continue}}y==="["?m++:y==="]"&&m--}var k=s.length===0?o:o.substring(f),A=k.startsWith(se),C=A?k.substring(1):k,S=p&&p>f?p-f:void 0;return{modifiers:s,hasImportantModifier:A,baseClassName:C,maybePostfixModifierPosition:S}}}function we(e){if(e.length<=1)return e;var n=[],i=[];return e.forEach(function(t){var l=t[0]==="[";l?(n.push.apply(n,i.sort().concat([t])),i=[]):i.push(t)}),n.push.apply(n,i.sort()),n}function xe(e){return{cache:ge(e.cacheSize),splitModifiers:ve(e),...ce(e)}}var ye=/\s+/;function Ce(e,n){var i=n.splitModifiers,t=n.getClassGroupId,l=n.getConflictingClassGroupIds,a=new Set;return e.trim().split(ye).map(function(o){var s=i(o),m=s.modifiers,f=s.hasImportantModifier,p=s.baseClassName,w=s.maybePostfixModifierPosition,y=t(w?p.substring(0,w):p),k=!!w;if(!y){if(!w)return{isTailwindClass:!1,originalClassName:o};if(y=t(p),!y)return{isTailwindClass:!1,originalClassName:o};k=!1}var A=we(m).join(":"),C=f?A+se:A;return{isTailwindClass:!0,modifierId:C,classGroupId:y,originalClassName:o,hasPostfixModifier:k}}).reverse().filter(function(o){if(!o.isTailwindClass)return!0;var s=o.modifierId,m=o.classGroupId,f=o.hasPostfixModifier,p=s+m;return a.has(p)?!1:(a.add(p),l(m,f).forEach(function(w){return a.add(s+w)}),!0)}).reverse().map(function(o){return o.originalClassName}).join(" ")}function Me(){for(var e=arguments.length,n=new Array(e),i=0;i<e;i++)n[i]=arguments[i];var t,l,a,o=s;function s(f){var p=n[0],w=n.slice(1),y=w.reduce(function(k,A){return A(k)},p());return t=xe(y),l=t.cache.get,a=t.cache.set,o=m,m(f)}function m(f){var p=l(f);if(p)return p;var w=Ce(f,t);return a(f,w),w}return function(){return o(N.apply(null,arguments))}}function x(e){var n=function(t){return t[e]||[]};return n.isThemeGetter=!0,n}var ae=/^\[(?:([a-z-]+):)?(.+)\]$/i,ke=/^\d+\/\d+$/,Ae=new Set(["px","full","screen"]),Se=/^(\d+(\.\d+)?)?(xs|sm|md|lg|xl)$/,Te=/\d+(%|px|r?em|[sdl]?v([hwib]|min|max)|pt|pc|in|cm|mm|cap|ch|ex|r?lh|cq(w|h|i|b|min|max))|\b(calc|min|max|clamp)\(.+\)|^0$/,We=/^-?((\d+)?\.?(\d+)[a-z]+|0)_-?((\d+)?\.?(\d+)[a-z]+|0)/;function W(e){return $(e)||Ae.has(e)||ke.test(e)||ee(e)}function ee(e){return P(e,"length",$e)}function ze(e){return P(e,"size",le)}function Ge(e){return P(e,"position",le)}function Ie(e){return P(e,"url",Pe)}function U(e){return P(e,"number",$)}function $(e){return!Number.isNaN(Number(e))}function Le(e){return e.endsWith("%")&&$(e.slice(0,-1))}function H(e){return de(e)||P(e,"number",de)}function c(e){return ae.test(e)}function q(){return!0}function L(e){return Se.test(e)}function Oe(e){return P(e,"",Be)}function P(e,n,i){var t=ae.exec(e);return t?t[1]?t[1]===n:i(t[2]):!1}function $e(e){return Te.test(e)}function le(){return!1}function Pe(e){return e.startsWith("url(")}function de(e){return Number.isInteger(Number(e))}function Be(e){return We.test(e)}function Fe(){var e=x("colors"),n=x("spacing"),i=x("blur"),t=x("brightness"),l=x("borderColor"),a=x("borderRadius"),o=x("borderSpacing"),s=x("borderWidth"),m=x("contrast"),f=x("grayscale"),p=x("hueRotate"),w=x("invert"),y=x("gap"),k=x("gradientColorStops"),A=x("gradientColorStopPositions"),C=x("inset"),S=x("margin"),z=x("opacity"),G=x("padding"),F=x("saturate"),g=x("scale"),Z=x("sepia"),E=x("skew"),J=x("space"),X=x("translate"),_=function(){return["auto","contain","none"]},j=function(){return["auto","hidden","clip","visible","scroll"]},V=function(){return["auto",c,n]},r=function(){return[c,n]},b=function(){return["",W]},d=function(){return["auto",$,c]},h=function(){return["bottom","center","left","left-bottom","left-top","right","right-bottom","right-top","top"]},u=function(){return["solid","dashed","dotted","double","none"]},v=function(){return["normal","multiply","screen","overlay","darken","lighten","color-dodge","color-burn","hard-light","soft-light","difference","exclusion","hue","saturation","color","luminosity","plus-lighter"]},M=function(){return["start","end","center","between","around","evenly","stretch"]},I=function(){return["","0",c]},K=function(){return["auto","avoid","all","avoid-page","page","left","right","column"]},O=function(){return[$,U]},Q=function(){return[$,c]};return{cacheSize:500,theme:{colors:[q],spacing:[W],blur:["none","",L,c],brightness:O(),borderColor:[e],borderRadius:["none","","full",L,c],borderSpacing:r(),borderWidth:b(),contrast:O(),grayscale:I(),hueRotate:Q(),invert:I(),gap:r(),gradientColorStops:[e],gradientColorStopPositions:[Le,ee],inset:V(),margin:V(),opacity:O(),padding:r(),saturate:O(),scale:O(),sepia:I(),skew:Q(),space:r(),translate:r()},classGroups:{aspect:[{aspect:["auto","square","video",c]}],container:["container"],columns:[{columns:[L]}],"break-after":[{"break-after":K()}],"break-before":[{"break-before":K()}],"break-inside":[{"break-inside":["auto","avoid","avoid-page","avoid-column"]}],"box-decoration":[{"box-decoration":["slice","clone"]}],box:[{box:["border","content"]}],display:["block","inline-block","inline","flex","inline-flex","table","inline-table","table-caption","table-cell","table-column","table-column-group","table-footer-group","table-header-group","table-row-group","table-row","flow-root","grid","inline-grid","contents","list-item","hidden"],float:[{float:["right","left","none"]}],clear:[{clear:["left","right","both","none"]}],isolation:["isolate","isolation-auto"],"object-fit":[{object:["contain","cover","fill","none","scale-down"]}],"object-position":[{object:[].concat(h(),[c])}],overflow:[{overflow:j()}],"overflow-x":[{"overflow-x":j()}],"overflow-y":[{"overflow-y":j()}],overscroll:[{overscroll:_()}],"overscroll-x":[{"overscroll-x":_()}],"overscroll-y":[{"overscroll-y":_()}],position:["static","fixed","absolute","relative","sticky"],inset:[{inset:[C]}],"inset-x":[{"inset-x":[C]}],"inset-y":[{"inset-y":[C]}],start:[{start:[C]}],end:[{end:[C]}],top:[{top:[C]}],right:[{right:[C]}],bottom:[{bottom:[C]}],left:[{left:[C]}],visibility:["visible","invisible","collapse"],z:[{z:["auto",H]}],basis:[{basis:V()}],"flex-direction":[{flex:["row","row-reverse","col","col-reverse"]}],"flex-wrap":[{flex:["wrap","wrap-reverse","nowrap"]}],flex:[{flex:["1","auto","initial","none",c]}],grow:[{grow:I()}],shrink:[{shrink:I()}],order:[{order:["first","last","none",H]}],"grid-cols":[{"grid-cols":[q]}],"col-start-end":[{col:["auto",{span:["full",H]},c]}],"col-start":[{"col-start":d()}],"col-end":[{"col-end":d()}],"grid-rows":[{"grid-rows":[q]}],"row-start-end":[{row:["auto",{span:[H]},c]}],"row-start":[{"row-start":d()}],"row-end":[{"row-end":d()}],"grid-flow":[{"grid-flow":["row","col","dense","row-dense","col-dense"]}],"auto-cols":[{"auto-cols":["auto","min","max","fr",c]}],"auto-rows":[{"auto-rows":["auto","min","max","fr",c]}],gap:[{gap:[y]}],"gap-x":[{"gap-x":[y]}],"gap-y":[{"gap-y":[y]}],"justify-content":[{justify:["normal"].concat(M())}],"justify-items":[{"justify-items":["start","end","center","stretch"]}],"justify-self":[{"justify-self":["auto","start","end","center","stretch"]}],"align-content":[{content:["normal"].concat(M(),["baseline"])}],"align-items":[{items:["start","end","center","baseline","stretch"]}],"align-self":[{self:["auto","start","end","center","stretch","baseline"]}],"place-content":[{"place-content":[].concat(M(),["baseline"])}],"place-items":[{"place-items":["start","end","center","baseline","stretch"]}],"place-self":[{"place-self":["auto","start","end","center","stretch"]}],p:[{p:[G]}],px:[{px:[G]}],py:[{py:[G]}],ps:[{ps:[G]}],pe:[{pe:[G]}],pt:[{pt:[G]}],pr:[{pr:[G]}],pb:[{pb:[G]}],pl:[{pl:[G]}],m:[{m:[S]}],mx:[{mx:[S]}],my:[{my:[S]}],ms:[{ms:[S]}],me:[{me:[S]}],mt:[{mt:[S]}],mr:[{mr:[S]}],mb:[{mb:[S]}],ml:[{ml:[S]}],"space-x":[{"space-x":[J]}],"space-x-reverse":["space-x-reverse"],"space-y":[{"space-y":[J]}],"space-y-reverse":["space-y-reverse"],w:[{w:["auto","min","max","fit",c,n]}],"min-w":[{"min-w":["min","max","fit",c,W]}],"max-w":[{"max-w":["0","none","full","min","max","fit","prose",{screen:[L]},L,c]}],h:[{h:[c,n,"auto","min","max","fit"]}],"min-h":[{"min-h":["min","max","fit",c,W]}],"max-h":[{"max-h":[c,n,"min","max","fit"]}],"font-size":[{text:["base",L,ee]}],"font-smoothing":["antialiased","subpixel-antialiased"],"font-style":["italic","not-italic"],"font-weight":[{font:["thin","extralight","light","normal","medium","semibold","bold","extrabold","black",U]}],"font-family":[{font:[q]}],"fvn-normal":["normal-nums"],"fvn-ordinal":["ordinal"],"fvn-slashed-zero":["slashed-zero"],"fvn-figure":["lining-nums","oldstyle-nums"],"fvn-spacing":["proportional-nums","tabular-nums"],"fvn-fraction":["diagonal-fractions","stacked-fractons"],tracking:[{tracking:["tighter","tight","normal","wide","wider","widest",c]}],"line-clamp":[{"line-clamp":["none",$,U]}],leading:[{leading:["none","tight","snug","normal","relaxed","loose",c,W]}],"list-image":[{"list-image":["none",c]}],"list-style-type":[{list:["none","disc","decimal",c]}],"list-style-position":[{list:["inside","outside"]}],"placeholder-color":[{placeholder:[e]}],"placeholder-opacity":[{"placeholder-opacity":[z]}],"text-alignment":[{text:["left","center","right","justify","start","end"]}],"text-color":[{text:[e]}],"text-opacity":[{"text-opacity":[z]}],"text-decoration":["underline","overline","line-through","no-underline"],"text-decoration-style":[{decoration:[].concat(u(),["wavy"])}],"text-decoration-thickness":[{decoration:["auto","from-font",W]}],"underline-offset":[{"underline-offset":["auto",c,W]}],"text-decoration-color":[{decoration:[e]}],"text-transform":["uppercase","lowercase","capitalize","normal-case"],"text-overflow":["truncate","text-ellipsis","text-clip"],indent:[{indent:r()}],"vertical-align":[{align:["baseline","top","middle","bottom","text-top","text-bottom","sub","super",c]}],whitespace:[{whitespace:["normal","nowrap","pre","pre-line","pre-wrap","break-spaces"]}],break:[{break:["normal","words","all","keep"]}],hyphens:[{hyphens:["none","manual","auto"]}],content:[{content:["none",c]}],"bg-attachment":[{bg:["fixed","local","scroll"]}],"bg-clip":[{"bg-clip":["border","padding","content","text"]}],"bg-opacity":[{"bg-opacity":[z]}],"bg-origin":[{"bg-origin":["border","padding","content"]}],"bg-position":[{bg:[].concat(h(),[Ge])}],"bg-repeat":[{bg:["no-repeat",{repeat:["","x","y","round","space"]}]}],"bg-size":[{bg:["auto","cover","contain",ze]}],"bg-image":[{bg:["none",{"gradient-to":["t","tr","r","br","b","bl","l","tl"]},Ie]}],"bg-color":[{bg:[e]}],"gradient-from-pos":[{from:[A]}],"gradient-via-pos":[{via:[A]}],"gradient-to-pos":[{to:[A]}],"gradient-from":[{from:[k]}],"gradient-via":[{via:[k]}],"gradient-to":[{to:[k]}],rounded:[{rounded:[a]}],"rounded-s":[{"rounded-s":[a]}],"rounded-e":[{"rounded-e":[a]}],"rounded-t":[{"rounded-t":[a]}],"rounded-r":[{"rounded-r":[a]}],"rounded-b":[{"rounded-b":[a]}],"rounded-l":[{"rounded-l":[a]}],"rounded-ss":[{"rounded-ss":[a]}],"rounded-se":[{"rounded-se":[a]}],"rounded-ee":[{"rounded-ee":[a]}],"rounded-es":[{"rounded-es":[a]}],"rounded-tl":[{"rounded-tl":[a]}],"rounded-tr":[{"rounded-tr":[a]}],"rounded-br":[{"rounded-br":[a]}],"rounded-bl":[{"rounded-bl":[a]}],"border-w":[{border:[s]}],"border-w-x":[{"border-x":[s]}],"border-w-y":[{"border-y":[s]}],"border-w-s":[{"border-s":[s]}],"border-w-e":[{"border-e":[s]}],"border-w-t":[{"border-t":[s]}],"border-w-r":[{"border-r":[s]}],"border-w-b":[{"border-b":[s]}],"border-w-l":[{"border-l":[s]}],"border-opacity":[{"border-opacity":[z]}],"border-style":[{border:[].concat(u(),["hidden"])}],"divide-x":[{"divide-x":[s]}],"divide-x-reverse":["divide-x-reverse"],"divide-y":[{"divide-y":[s]}],"divide-y-reverse":["divide-y-reverse"],"divide-opacity":[{"divide-opacity":[z]}],"divide-style":[{divide:u()}],"border-color":[{border:[l]}],"border-color-x":[{"border-x":[l]}],"border-color-y":[{"border-y":[l]}],"border-color-t":[{"border-t":[l]}],"border-color-r":[{"border-r":[l]}],"border-color-b":[{"border-b":[l]}],"border-color-l":[{"border-l":[l]}],"divide-color":[{divide:[l]}],"outline-style":[{outline:[""].concat(u())}],"outline-offset":[{"outline-offset":[c,W]}],"outline-w":[{outline:[W]}],"outline-color":[{outline:[e]}],"ring-w":[{ring:b()}],"ring-w-inset":["ring-inset"],"ring-color":[{ring:[e]}],"ring-opacity":[{"ring-opacity":[z]}],"ring-offset-w":[{"ring-offset":[W]}],"ring-offset-color":[{"ring-offset":[e]}],shadow:[{shadow:["","inner","none",L,Oe]}],"shadow-color":[{shadow:[q]}],opacity:[{opacity:[z]}],"mix-blend":[{"mix-blend":v()}],"bg-blend":[{"bg-blend":v()}],filter:[{filter:["","none"]}],blur:[{blur:[i]}],brightness:[{brightness:[t]}],contrast:[{contrast:[m]}],"drop-shadow":[{"drop-shadow":["","none",L,c]}],grayscale:[{grayscale:[f]}],"hue-rotate":[{"hue-rotate":[p]}],invert:[{invert:[w]}],saturate:[{saturate:[F]}],sepia:[{sepia:[Z]}],"backdrop-filter":[{"backdrop-filter":["","none"]}],"backdrop-blur":[{"backdrop-blur":[i]}],"backdrop-brightness":[{"backdrop-brightness":[t]}],"backdrop-contrast":[{"backdrop-contrast":[m]}],"backdrop-grayscale":[{"backdrop-grayscale":[f]}],"backdrop-hue-rotate":[{"backdrop-hue-rotate":[p]}],"backdrop-invert":[{"backdrop-invert":[w]}],"backdrop-opacity":[{"backdrop-opacity":[z]}],"backdrop-saturate":[{"backdrop-saturate":[F]}],"backdrop-sepia":[{"backdrop-sepia":[Z]}],"border-collapse":[{border:["collapse","separate"]}],"border-spacing":[{"border-spacing":[o]}],"border-spacing-x":[{"border-spacing-x":[o]}],"border-spacing-y":[{"border-spacing-y":[o]}],"table-layout":[{table:["auto","fixed"]}],caption:[{caption:["top","bottom"]}],transition:[{transition:["none","all","","colors","opacity","shadow","transform",c]}],duration:[{duration:Q()}],ease:[{ease:["linear","in","out","in-out",c]}],delay:[{delay:Q()}],animate:[{animate:["none","spin","ping","pulse","bounce",c]}],transform:[{transform:["","gpu","none"]}],scale:[{scale:[g]}],"scale-x":[{"scale-x":[g]}],"scale-y":[{"scale-y":[g]}],rotate:[{rotate:[H,c]}],"translate-x":[{"translate-x":[X]}],"translate-y":[{"translate-y":[X]}],"skew-x":[{"skew-x":[E]}],"skew-y":[{"skew-y":[E]}],"transform-origin":[{origin:["center","top","top-right","right","bottom-right","bottom","bottom-left","left","top-left",c]}],accent:[{accent:["auto",e]}],appearance:["appearance-none"],cursor:[{cursor:["auto","default","pointer","wait","text","move","help","not-allowed","none","context-menu","progress","cell","crosshair","vertical-text","alias","copy","no-drop","grab","grabbing","all-scroll","col-resize","row-resize","n-resize","e-resize","s-resize","w-resize","ne-resize","nw-resize","se-resize","sw-resize","ew-resize","ns-resize","nesw-resize","nwse-resize","zoom-in","zoom-out",c]}],"caret-color":[{caret:[e]}],"pointer-events":[{"pointer-events":["none","auto"]}],resize:[{resize:["none","y","x",""]}],"scroll-behavior":[{scroll:["auto","smooth"]}],"scroll-m":[{"scroll-m":r()}],"scroll-mx":[{"scroll-mx":r()}],"scroll-my":[{"scroll-my":r()}],"scroll-ms":[{"scroll-ms":r()}],"scroll-me":[{"scroll-me":r()}],"scroll-mt":[{"scroll-mt":r()}],"scroll-mr":[{"scroll-mr":r()}],"scroll-mb":[{"scroll-mb":r()}],"scroll-ml":[{"scroll-ml":r()}],"scroll-p":[{"scroll-p":r()}],"scroll-px":[{"scroll-px":r()}],"scroll-py":[{"scroll-py":r()}],"scroll-ps":[{"scroll-ps":r()}],"scroll-pe":[{"scroll-pe":r()}],"scroll-pt":[{"scroll-pt":r()}],"scroll-pr":[{"scroll-pr":r()}],"scroll-pb":[{"scroll-pb":r()}],"scroll-pl":[{"scroll-pl":r()}],"snap-align":[{snap:["start","end","center","align-none"]}],"snap-stop":[{snap:["normal","always"]}],"snap-type":[{snap:["none","x","y","both"]}],"snap-strictness":[{snap:["mandatory","proximity"]}],touch:[{touch:["auto","none","pinch-zoom","manipulation",{pan:["x","left","right","y","up","down"]}]}],select:[{select:["none","text","all","auto"]}],"will-change":[{"will-change":["auto","scroll","contents","transform",c]}],fill:[{fill:[e,"none"]}],"stroke-w":[{stroke:[W,U]}],stroke:[{stroke:[e,"none"]}],sr:["sr-only","not-sr-only"]},conflictingClassGroups:{overflow:["overflow-x","overflow-y"],overscroll:["overscroll-x","overscroll-y"],inset:["inset-x","inset-y","start","end","top","right","bottom","left"],"inset-x":["right","left"],"inset-y":["top","bottom"],flex:["basis","grow","shrink"],gap:["gap-x","gap-y"],p:["px","py","ps","pe","pt","pr","pb","pl"],px:["pr","pl"],py:["pt","pb"],m:["mx","my","ms","me","mt","mr","mb","ml"],mx:["mr","ml"],my:["mt","mb"],"font-size":["leading"],"fvn-normal":["fvn-ordinal","fvn-slashed-zero","fvn-figure","fvn-spacing","fvn-fraction"],"fvn-ordinal":["fvn-normal"],"fvn-slashed-zero":["fvn-normal"],"fvn-figure":["fvn-normal"],"fvn-spacing":["fvn-normal"],"fvn-fraction":["fvn-normal"],rounded:["rounded-s","rounded-e","rounded-t","rounded-r","rounded-b","rounded-l","rounded-ss","rounded-se","rounded-ee","rounded-es","rounded-tl","rounded-tr","rounded-br","rounded-bl"],"rounded-s":["rounded-ss","rounded-es"],"rounded-e":["rounded-se","rounded-ee"],"rounded-t":["rounded-tl","rounded-tr"],"rounded-r":["rounded-tr","rounded-br"],"rounded-b":["rounded-br","rounded-bl"],"rounded-l":["rounded-tl","rounded-bl"],"border-spacing":["border-spacing-x","border-spacing-y"],"border-w":["border-w-s","border-w-e","border-w-t","border-w-r","border-w-b","border-w-l"],"border-w-x":["border-w-r","border-w-l"],"border-w-y":["border-w-t","border-w-b"],"border-color":["border-color-t","border-color-r","border-color-b","border-color-l"],"border-color-x":["border-color-r","border-color-l"],"border-color-y":["border-color-t","border-color-b"],"scroll-m":["scroll-mx","scroll-my","scroll-ms","scroll-me","scroll-mt","scroll-mr","scroll-mb","scroll-ml"],"scroll-mx":["scroll-mr","scroll-ml"],"scroll-my":["scroll-mt","scroll-mb"],"scroll-p":["scroll-px","scroll-py","scroll-ps","scroll-pe","scroll-pt","scroll-pr","scroll-pb","scroll-pl"],"scroll-px":["scroll-pr","scroll-pl"],"scroll-py":["scroll-pt","scroll-pb"]},conflictingClassGroupModifiers:{"font-size":["leading"]}}}var te=Me(Fe);const re="simple-tooltip",ue="simple-tooltip__arrow",R={left:["left","right","top","bottom"],top:["top","bottom","right","left"],right:["right","left","top","bottom"],bottom:["bottom","top","right","left"]};let pe="top";const je=10,Ve=20,Ne=100,He=250,qe=0,_e="absolute opacity-0 inline-block w-fit py-1.5 px-2.5 rounded-md bg-[#495057] shadow-[0_2px_12px_0_rgba(0,0,0,0.1)] box-border",Ue="text-sm text-white whitespace-pre-wrap break-words",Re=5,Ze="absolute border-solid border-[#495057]",Ee=6,Je=e=>{var w,y,k,A;e!=null&&e.defaultPosition&&(pe=e.defaultPosition);const n={left:((w=e==null?void 0:e.positions)==null?void 0:w.left)??R.left,top:((y=e==null?void 0:e.positions)==null?void 0:y.top)??R.top,right:((k=e==null?void 0:e.positions)==null?void 0:k.right)??R.right,bottom:((A=e==null?void 0:e.positions)==null?void 0:A.bottom)??R.bottom},i=(e==null?void 0:e.offsetFromSource)??je,t=(e==null?void 0:e.offsetFromViewport)??Ve,l=(e==null?void 0:e.minWidth)??Ne,a=(e==null?void 0:e.maxWidth)??He,o=(e==null?void 0:e.tooltipBorderWidth)??qe,s=te(_e,(e==null?void 0:e.tooltipClasses)??""),m=te(Ue,(e==null?void 0:e.textClasses)??""),f=(e==null?void 0:e.arrowSize)??Re,p=(e==null?void 0:e.arrowMinOffsetFromTooltipCorner)??Ee;return{mounted:(C,S)=>{const z=S.arg??pe,G=S.value,F=document.createElement("p");F.classList.add(...m.split(" ")),F.innerText=G;const g=document.createElement("div");g.id=re,g.classList.add(...s.split(" ")),g.style.borderWidth=`${o}px`,g.appendChild(F);function Z(r){const b=Math.min(r.left-i-t,a),d=r.top>=t,h=window.innerHeight-r.bottom>=t;if(b<l||!d||!h)return!1;g.style.maxWidth=`${b}px`;const u=g.getBoundingClientRect();let v=r.top+r.height/2-u.height/2;v<t?v=t:v+u.height>window.innerHeight-t&&(v=window.innerHeight-t-u.height);const M=r.left-i-u.width;return r.bottom<v+p*2||r.top>v+u.height-p*2?!1:(g.style.top=`${v}px`,g.style.left=`${M}px`,!0)}function E(r){const b=Math.min(window.innerWidth-(r.right+i)-t,a),d=r.top>=t,h=window.innerHeight-r.bottom>=t;if(b<l||!d||!h)return!1;g.style.maxWidth=`${b}px`;const u=g.getBoundingClientRect();let v=r.top+r.height/2-u.height/2;v<t?v=t:v+u.height>window.innerHeight-t&&(v=window.innerHeight-t-u.height);const M=r.right+i;return r.bottom<v+p*2||r.top>v+u.height-p*2?!1:(g.style.top=`${v}px`,g.style.left=`${M}px`,!0)}function J(r){const b=Math.min(window.innerWidth-t*2,a);g.style.maxWidth=`${b}px`;const d=g.getBoundingClientRect();let h=r.top-i-d.height;if(h<t)return!1;let u=r.left+r.width/2-d.width/2;return u<t?u=t:u+d.width>window.innerWidth-t&&(u=window.innerWidth-t-d.width),r.left>u+d.width-p*2||r.right<u+p*2?!1:(g.style.top=`${h}px`,g.style.left=`${u}px`,!0)}function X(r){const b=Math.min(window.innerWidth-t*2,a);g.style.maxWidth=`${b}px`;const d=g.getBoundingClientRect();let h=r.bottom+i;if(h+d.height>window.innerHeight-t)return!1;let u=r.left+r.width/2-d.width/2;return u<t?u=t:u+d.width>window.innerWidth-t&&(u=window.innerWidth-t-d.width),r.left>u+d.width-p*2||r.right<u+p*2?!1:(g.style.top=`${h}px`,g.style.left=`${u}px`,!0)}function _(r,b){var O;const d=document.createElement("div"),h=g.getBoundingClientRect(),u=Math.sin(45*(180/Math.PI))*f;let v=0,M=0,I="";switch(b){case"left":I="border-y-transparent border-r-transparent",v=r.top-h.top+r.height/2-u-o,M=h.width-o;break;case"top":I="border-x-transparent border-b-transparent",v=h.height-o,M=r.left-h.left+r.width/2-u-o;break;case"right":I="border-y-transparent border-l-transparent",v=r.top-h.top+r.height/2-u-o,M=-f*2-o;break;case"bottom":I="border-x-transparent border-t-transparent",v=-f*2-o,M=r.left-h.left+r.width/2-u-o;break}b==="left"||b==="right"?j(b,h,v)||(v=V(b,h,v)):j(b,h,M)||(M=V(b,h,M));const K=te(Ze,(e==null?void 0:e.arrowClasses)??"",I);d.id=ue,d.classList.add(...K.split(" ")),d.style.top=`${v}px`,d.style.left=`${M}px`,d.style.borderWidth=`${f}px`,(O=document.querySelector(`#${re}`))==null||O.appendChild(d)}function j(r,b,d){switch(r){case"left":case"right":return d>p-o&&d<b.height+o-p-f*2;case"top":case"bottom":return d>p-o&&d<b.width+o-p-f*2}}function V(r,b,d){switch(r){case"left":case"right":return d<p-o?p-o:b.height-o-p-f*2;case"top":case"bottom":return d<p-o?p-o:b.width-o-p-f*2}}C.addEventListener("mouseenter",()=>{const r=C.getBoundingClientRect(),b=document.querySelector("body");b==null||b.appendChild(g);let d=!1,h=z;for(let u=0;u<4&&(h=n[z][u],h==="left"?d=Z(r):h==="top"?d=J(r):h==="right"?d=E(r):h==="bottom"&&(d=X(r)),!d);u++);d&&(_(r,h),g.style.opacity="1")}),C.addEventListener("mouseleave",()=>Xe())}}};function Xe(){var n;const e=document.querySelector(`#${re}`);(n=e==null?void 0:e.querySelector(`#${ue}`))==null||n.remove(),e==null||e.remove()}return Je});
package/package.json ADDED
@@ -0,0 +1,58 @@
1
+ {
2
+ "name": "zero-tooltip",
3
+ "description": "Tooltip component",
4
+ "main": "./dist/zero-tooltip.umd.cjs",
5
+ "module": "./dist/zero-tooltip.js",
6
+ "types": "./dist/index.d.ts",
7
+ "exports": {
8
+ ".": {
9
+ "import": "./dist/zero-tooltip.js",
10
+ "require": "./dist/zero-tooltip.umd.cjs"
11
+ }
12
+ },
13
+ "files": [
14
+ "dist",
15
+ "src"
16
+ ],
17
+ "version": "0.0.1",
18
+ "type": "module",
19
+ "scripts": {
20
+ "dev": "vite",
21
+ "build": "vue-tsc && vite build",
22
+ "preview": "vite preview"
23
+ },
24
+ "peerDependencies": {
25
+ "vue": "^3.3.4"
26
+ },
27
+ "dependencies": {
28
+ "tailwind-merge": "^1.14.0"
29
+ },
30
+ "devDependencies": {
31
+ "@types/node": "^20.6.2",
32
+ "@vitejs/plugin-vue": "^4.2.3",
33
+ "autoprefixer": "^10.4.15",
34
+ "postcss": "^8.4.29",
35
+ "tailwindcss": "^3.3.3",
36
+ "typescript": "^5.0.2",
37
+ "vite": "^4.4.5",
38
+ "vite-plugin-dts": "^3.5.3",
39
+ "vue": "^3.3.4",
40
+ "vue-tsc": "^1.8.5"
41
+ },
42
+ "repository": {
43
+ "type": "git",
44
+ "url": "git+https://github.com/TheAliter/zero-tooltip.git"
45
+ },
46
+ "keywords": [
47
+ "tooltip",
48
+ "vue3",
49
+ "tailwind",
50
+ "typescript"
51
+ ],
52
+ "author": "Andris Paškovskis",
53
+ "license": "MIT",
54
+ "bugs": {
55
+ "url": "https://github.com/TheAliter/zero-tooltip/issues"
56
+ },
57
+ "homepage": "https://github.com/TheAliter/zero-tooltip#readme"
58
+ }
package/src/index.ts ADDED
@@ -0,0 +1,7 @@
1
+ import ZeroTooltip from "./tooltip"
2
+ import TooltipConfig from "./types/config"
3
+ import TooltipPosition from "./types/tooltipPosition"
4
+ import TooltipPositions from "./types/tooltipPositions"
5
+
6
+ export default ZeroTooltip
7
+ export type { TooltipConfig as ZeroTooltipConfig, TooltipPosition as ZeroTooltipPosition, TooltipPositions as ZeroTooltipPositions }
package/src/style.css ADDED
@@ -0,0 +1,3 @@
1
+ @tailwind base;
2
+ @tailwind components;
3
+ @tailwind utilities;
package/src/tooltip.ts ADDED
@@ -0,0 +1,353 @@
1
+ import { Directive } from "vue"
2
+ import { twMerge } from 'tailwind-merge'
3
+ import TooltipConfig from "./types/config"
4
+ import TooltipPosition from "./types/tooltipPosition"
5
+ import TooltipPositions from "./types/tooltipPositions"
6
+
7
+ const tooltipElementId = 'simple-tooltip'
8
+ const arrowElementId = 'simple-tooltip__arrow'
9
+
10
+ // For each TooltipPosition define sequence of positions that will be checked when determining where to render Tooltip
11
+ // Meant as fallback positions in case Tooltip do not have enough space in originally set position
12
+ const defaultTooltipPositions: TooltipPositions = {
13
+ 'left': ['left', 'right', 'top', 'bottom'],
14
+ 'top': ['top', 'bottom', 'right', 'left'],
15
+ 'right': ['right', 'left', 'top', 'bottom'],
16
+ 'bottom': ['bottom', 'top', 'right', 'left'],
17
+ }
18
+
19
+ // TODO: set default styling
20
+ // TODO: publish to npmjs
21
+
22
+ let defaultTooltipPosition: TooltipPosition = 'top'
23
+ const defaultTooltipOffsetFromSource = 10
24
+ const defaultTooltipOffsetFromViewport = 20
25
+ const defaultTooltipMinWidth = 100
26
+ const defaultTooltipMaxWidth = 250
27
+ const defaultTooltipBorderWidth = 0
28
+ const defaultTooltipClasses = 'absolute opacity-0 inline-block w-fit py-1.5 px-2.5 rounded-md bg-[#495057] shadow-[0_2px_12px_0_rgba(0,0,0,0.1)] box-border'
29
+ const defaultTextClasses = 'text-sm text-white whitespace-pre-wrap break-words'
30
+ const defaultArrowSize = 5
31
+ const defaultArrowClasses = 'absolute border-solid border-[#495057]'
32
+ const defaultMinArrowOffsetFromTooltipCorner = 6
33
+
34
+ const ZeroTooltip = (config?: TooltipConfig): Directive => {
35
+ if (config?.defaultPosition) {
36
+ defaultTooltipPosition = config.defaultPosition
37
+ }
38
+
39
+ // Get Tooltip config
40
+ const tooltipPositions: TooltipPositions = {
41
+ 'left': config?.positions?.left ?? defaultTooltipPositions.left,
42
+ 'top': config?.positions?.top ?? defaultTooltipPositions.top,
43
+ 'right': config?.positions?.right ?? defaultTooltipPositions.right,
44
+ 'bottom': config?.positions?.bottom ?? defaultTooltipPositions.bottom,
45
+ }
46
+ const tooltipOffsetFromSource = config?.offsetFromSource ?? defaultTooltipOffsetFromSource
47
+ const tooltipOffsetFromViewport = config?.offsetFromViewport ?? defaultTooltipOffsetFromViewport
48
+ const tooltipMinWidth = config?.minWidth ?? defaultTooltipMinWidth
49
+ const tooltipMaxWidth = config?.maxWidth ?? defaultTooltipMaxWidth
50
+ const tooltipBorderWidth = config?.tooltipBorderWidth ?? defaultTooltipBorderWidth
51
+ const tooltipClasses = twMerge(defaultTooltipClasses, config?.tooltipClasses ?? '')
52
+ const textClasses = twMerge(defaultTextClasses, config?.textClasses ?? '')
53
+ const arrowSize = config?.arrowSize ?? defaultArrowSize
54
+ const arrowMinOffsetFromTooltipCorner = config?.arrowMinOffsetFromTooltipCorner ?? defaultMinArrowOffsetFromTooltipCorner
55
+
56
+ return {
57
+ mounted: (anchorElement: HTMLElement, binding) => {
58
+ // Get Tooltip position and text
59
+ const tooltipPosition: TooltipPosition = (binding.arg ?? defaultTooltipPosition) as TooltipPosition
60
+ const text: string = binding.value
61
+
62
+ // Create Text element
63
+ const textElement = document.createElement('p')
64
+ textElement.classList.add(...textClasses.split(' '))
65
+ textElement.innerText = text
66
+
67
+ // Create Tooltip element
68
+ const tooltipElement = document.createElement('div')
69
+ tooltipElement.id = tooltipElementId
70
+ tooltipElement.classList.add(...tooltipClasses.split(' '))
71
+ tooltipElement.style.borderWidth = `${tooltipBorderWidth}px`
72
+ tooltipElement.appendChild(textElement)
73
+
74
+ function tryMountTooltipOnLeft(anchorElementRect: DOMRect) {
75
+ // Check if Tooltip has enough available horizontal space, top and bottom offset from viewport
76
+ const tooltipAvailableMaxWidth = Math.min(anchorElementRect.left - tooltipOffsetFromSource - tooltipOffsetFromViewport, tooltipMaxWidth)
77
+ const isAnchorElementTopLowerThanOffsetFromViewport = anchorElementRect.top >= tooltipOffsetFromViewport
78
+ const isAnchorElementBottomHigherThanOffsetFromViewport = (window.innerHeight - anchorElementRect.bottom) >= tooltipOffsetFromViewport
79
+
80
+ if (tooltipAvailableMaxWidth < tooltipMinWidth || !isAnchorElementTopLowerThanOffsetFromViewport || !isAnchorElementBottomHigherThanOffsetFromViewport) return false
81
+
82
+ // Set Tooltip maxWidth
83
+ tooltipElement.style.maxWidth = `${tooltipAvailableMaxWidth}px`
84
+
85
+ // Calculate Tooltip position
86
+ const tooltipElementRect = tooltipElement.getBoundingClientRect()
87
+ let tooltipTop = anchorElementRect.top + (anchorElementRect.height / 2) - (tooltipElementRect.height / 2)
88
+
89
+ if (tooltipTop < tooltipOffsetFromViewport) {
90
+ tooltipTop = tooltipOffsetFromViewport
91
+ } else if (tooltipTop + tooltipElementRect.height > window.innerHeight - tooltipOffsetFromViewport) {
92
+ tooltipTop = window.innerHeight - tooltipOffsetFromViewport - tooltipElementRect.height
93
+ }
94
+
95
+ const tooltipLeft = anchorElementRect.left - tooltipOffsetFromSource - tooltipElementRect.width
96
+
97
+ // Check if anchor element is directly on right of Tooltip
98
+ if (anchorElementRect.bottom < tooltipTop + arrowMinOffsetFromTooltipCorner * 2
99
+ || anchorElementRect.top > tooltipTop + tooltipElementRect.height - arrowMinOffsetFromTooltipCorner * 2) return false
100
+
101
+ // Set Tooltip position
102
+ tooltipElement.style.top = `${tooltipTop}px`
103
+ tooltipElement.style.left = `${tooltipLeft}px`
104
+
105
+ return true
106
+ }
107
+
108
+ function tryMountTooltipOnRight(anchorElementRect: DOMRect) {
109
+ // Check if Tooltip has enough available horizontal space, top and bottom offset from viewport
110
+ const tooltipAvailableMaxWidth = Math.min(window.innerWidth - (anchorElementRect.right + tooltipOffsetFromSource) - tooltipOffsetFromViewport, tooltipMaxWidth)
111
+ const isAnchorElementTopLowerThanOffsetFromViewport = anchorElementRect.top >= tooltipOffsetFromViewport
112
+ const isAnchorElementBottomHigherThanOffsetFromViewport = (window.innerHeight - anchorElementRect.bottom) >= tooltipOffsetFromViewport
113
+
114
+ if (tooltipAvailableMaxWidth < tooltipMinWidth || !isAnchorElementTopLowerThanOffsetFromViewport || !isAnchorElementBottomHigherThanOffsetFromViewport) return false
115
+
116
+ // Set tooltip maxWidth
117
+ tooltipElement.style.maxWidth = `${tooltipAvailableMaxWidth}px`
118
+
119
+ // Calculate Tooltip position
120
+ const tooltipElementRect = tooltipElement.getBoundingClientRect()
121
+
122
+ let tooltipTop = anchorElementRect.top + (anchorElementRect.height / 2) - (tooltipElementRect.height / 2)
123
+
124
+ if (tooltipTop < tooltipOffsetFromViewport) {
125
+ tooltipTop = tooltipOffsetFromViewport
126
+ } else if (tooltipTop + tooltipElementRect.height > window.innerHeight - tooltipOffsetFromViewport) {
127
+ tooltipTop = window.innerHeight - tooltipOffsetFromViewport - tooltipElementRect.height
128
+ }
129
+
130
+ const tooltipLeft = anchorElementRect.right + tooltipOffsetFromSource
131
+
132
+ // Check if anchor element is directly on left of Tooltip
133
+ if (anchorElementRect.bottom < tooltipTop + arrowMinOffsetFromTooltipCorner * 2
134
+ || anchorElementRect.top > tooltipTop + tooltipElementRect.height - arrowMinOffsetFromTooltipCorner * 2) return false
135
+
136
+ // Set Tooltip position
137
+ tooltipElement.style.top = `${tooltipTop}px`
138
+ tooltipElement.style.left = `${tooltipLeft}px`
139
+
140
+ return true
141
+ }
142
+
143
+ function tryMountTooltipOnTop(anchorElementRect: DOMRect) {
144
+ // Calculate and set Tooltip width
145
+ const tooltipAvailableMaxWidth = Math.min(window.innerWidth - (tooltipOffsetFromViewport * 2), tooltipMaxWidth)
146
+ tooltipElement.style.maxWidth = `${tooltipAvailableMaxWidth}px`
147
+
148
+ // Calculate Tooltip top position
149
+ const tooltipElementRect = tooltipElement.getBoundingClientRect()
150
+ let tooltipTop = anchorElementRect.top - tooltipOffsetFromSource - tooltipElementRect.height
151
+
152
+ // Check if Tooltip has enough available on top
153
+ if (tooltipTop < tooltipOffsetFromViewport) return false
154
+
155
+ // Calculate Tooltip left position
156
+ let tooltipLeft = anchorElementRect.left + (anchorElementRect.width / 2) - (tooltipElementRect.width / 2)
157
+
158
+ if (tooltipLeft < tooltipOffsetFromViewport) {
159
+ tooltipLeft = tooltipOffsetFromViewport
160
+ } else if (tooltipLeft + tooltipElementRect.width > window.innerWidth - tooltipOffsetFromViewport) {
161
+ tooltipLeft = window.innerWidth - tooltipOffsetFromViewport - tooltipElementRect.width
162
+ }
163
+
164
+ // Check if anchor element is directly on below of Tooltip
165
+ if (anchorElementRect.left > tooltipLeft + tooltipElementRect.width - arrowMinOffsetFromTooltipCorner * 2
166
+ || anchorElementRect.right < tooltipLeft + arrowMinOffsetFromTooltipCorner * 2) return false
167
+
168
+ // Set Tooltip position
169
+ tooltipElement.style.top = `${tooltipTop}px`
170
+ tooltipElement.style.left = `${tooltipLeft}px`
171
+
172
+ return true
173
+ }
174
+
175
+ function tryMountTooltipOnBottom(anchorElementRect: DOMRect) {
176
+ // Calculate and set Tooltip width
177
+ const tooltipAvailableMaxWidth = Math.min(window.innerWidth - (tooltipOffsetFromViewport * 2), tooltipMaxWidth)
178
+ tooltipElement.style.maxWidth = `${tooltipAvailableMaxWidth}px`
179
+
180
+ // Calculate Tooltip top position
181
+ const tooltipElementRect = tooltipElement.getBoundingClientRect()
182
+ let tooltipTop = anchorElementRect.bottom + tooltipOffsetFromSource
183
+
184
+ // Check if Tooltip has enough available on bottom
185
+ if (tooltipTop + tooltipElementRect.height > window.innerHeight - tooltipOffsetFromViewport) return false
186
+
187
+ // Calculate Tooltip left position
188
+ let tooltipLeft = anchorElementRect.left + (anchorElementRect.width / 2) - (tooltipElementRect.width / 2)
189
+
190
+ if (tooltipLeft < tooltipOffsetFromViewport) {
191
+ tooltipLeft = tooltipOffsetFromViewport
192
+ } else if (tooltipLeft + tooltipElementRect.width > window.innerWidth - tooltipOffsetFromViewport) {
193
+ tooltipLeft = window.innerWidth - tooltipOffsetFromViewport - tooltipElementRect.width
194
+ }
195
+
196
+ // Check if anchor element is directly on top of Tooltip
197
+ if (anchorElementRect.left > tooltipLeft + tooltipElementRect.width - arrowMinOffsetFromTooltipCorner * 2
198
+ || anchorElementRect.right < tooltipLeft + arrowMinOffsetFromTooltipCorner * 2) return false
199
+
200
+ // Set Tooltip position
201
+ tooltipElement.style.top = `${tooltipTop}px`
202
+ tooltipElement.style.left = `${tooltipLeft}px`
203
+
204
+ return true
205
+ }
206
+
207
+ function drawArrow(anchorElementRect: DOMRect, currentTooltipPosition: TooltipPosition) {
208
+ // Create Arrow element
209
+ const arrowElement = document.createElement('div')
210
+
211
+ // Calculate Arrow element size, positions and style/angle classes
212
+ const tooltipElementRect = tooltipElement.getBoundingClientRect()
213
+ const arrowHalfLengthOfLongSide = Math.sin(45 * (180 / Math.PI)) * arrowSize
214
+
215
+ // Arrow top/left 0 is Tooltip top/left 0
216
+ let arrowTop = 0
217
+ let arrowLeft = 0
218
+
219
+ let arrowClassForCorrectAngle = ''
220
+
221
+ switch (currentTooltipPosition) {
222
+ case "left":
223
+ arrowClassForCorrectAngle = 'border-y-transparent border-r-transparent'
224
+ arrowTop = anchorElementRect.top - tooltipElementRect.top + (anchorElementRect.height / 2) - arrowHalfLengthOfLongSide - tooltipBorderWidth
225
+ arrowLeft = tooltipElementRect.width - tooltipBorderWidth
226
+ break;
227
+ case "top":
228
+ arrowClassForCorrectAngle = 'border-x-transparent border-b-transparent'
229
+ arrowTop = tooltipElementRect.height - tooltipBorderWidth
230
+ arrowLeft = anchorElementRect.left - tooltipElementRect.left + (anchorElementRect.width / 2) - arrowHalfLengthOfLongSide - tooltipBorderWidth
231
+ break;
232
+ case "right":
233
+ arrowClassForCorrectAngle = 'border-y-transparent border-l-transparent'
234
+ arrowTop = anchorElementRect.top - tooltipElementRect.top + (anchorElementRect.height / 2) - arrowHalfLengthOfLongSide - tooltipBorderWidth
235
+ arrowLeft = (-arrowSize * 2) - tooltipBorderWidth
236
+ break;
237
+ case "bottom":
238
+ arrowClassForCorrectAngle = 'border-x-transparent border-t-transparent'
239
+ arrowTop = (-arrowSize * 2) - tooltipBorderWidth
240
+ arrowLeft = anchorElementRect.left - tooltipElementRect.left + (anchorElementRect.width / 2) - arrowHalfLengthOfLongSide - tooltipBorderWidth
241
+ break;
242
+ }
243
+
244
+ if (currentTooltipPosition === 'left' || currentTooltipPosition === 'right') {
245
+ if (!isArrowPositionWithinLimits(currentTooltipPosition, tooltipElementRect, arrowTop)) {
246
+ arrowTop = getArrowPositionMinLimit(currentTooltipPosition, tooltipElementRect, arrowTop)
247
+ }
248
+ } else {
249
+ if (!isArrowPositionWithinLimits(currentTooltipPosition, tooltipElementRect, arrowLeft)) {
250
+ arrowLeft = getArrowPositionMinLimit(currentTooltipPosition, tooltipElementRect, arrowLeft)
251
+ }
252
+ }
253
+
254
+ // Set Arrow element id, styling/angle
255
+ const arrowClasses = twMerge(defaultArrowClasses, config?.arrowClasses ?? '', arrowClassForCorrectAngle)
256
+ arrowElement.id = arrowElementId
257
+ arrowElement.classList.add(...arrowClasses.split(' '))
258
+
259
+ // Set Arrow element size and position
260
+ arrowElement.style.top = `${arrowTop}px`
261
+ arrowElement.style.left = `${arrowLeft}px`
262
+ arrowElement.style.borderWidth = `${arrowSize}px`
263
+
264
+ // Mount Arrow element
265
+ document.querySelector(`#${tooltipElementId}`)?.appendChild(arrowElement)
266
+ }
267
+
268
+ function isArrowPositionWithinLimits(currentTooltipPosition: TooltipPosition, tooltipElementRect: DOMRect, arrowPosition: number) {
269
+ switch (currentTooltipPosition) {
270
+ case "left":
271
+ case "right":
272
+ return arrowPosition > arrowMinOffsetFromTooltipCorner - tooltipBorderWidth
273
+ && arrowPosition < tooltipElementRect.height + tooltipBorderWidth - arrowMinOffsetFromTooltipCorner - (arrowSize * 2)
274
+ case "top":
275
+ case "bottom":
276
+ return arrowPosition > arrowMinOffsetFromTooltipCorner - tooltipBorderWidth
277
+ && arrowPosition < tooltipElementRect.width + tooltipBorderWidth - arrowMinOffsetFromTooltipCorner - (arrowSize * 2)
278
+ }
279
+ }
280
+
281
+ function getArrowPositionMinLimit(currentTooltipPosition: TooltipPosition, tooltipElementRect: DOMRect, arrowPosition: number) {
282
+ switch (currentTooltipPosition) {
283
+ case "left":
284
+ case "right":
285
+ if (arrowPosition < arrowMinOffsetFromTooltipCorner - tooltipBorderWidth) {
286
+ // Arrow too close to viewport top
287
+ return arrowMinOffsetFromTooltipCorner - tooltipBorderWidth
288
+ } else {
289
+ // Arrow too close to viewport bottom
290
+ return tooltipElementRect.height - tooltipBorderWidth - arrowMinOffsetFromTooltipCorner - (arrowSize * 2)
291
+ }
292
+ case "top":
293
+ case "bottom":
294
+ if (arrowPosition < arrowMinOffsetFromTooltipCorner - tooltipBorderWidth) {
295
+ // Arrow too close to viewport left
296
+ return arrowMinOffsetFromTooltipCorner - tooltipBorderWidth
297
+ } else {
298
+ // Arrow too close to viewport right
299
+ return tooltipElementRect.width - tooltipBorderWidth - arrowMinOffsetFromTooltipCorner - (arrowSize * 2)
300
+ }
301
+ }
302
+ }
303
+
304
+ // Add listener for showing Tooltip element
305
+ anchorElement.addEventListener('mouseenter', () => {
306
+ const anchorElementRect = anchorElement.getBoundingClientRect()
307
+
308
+ // Mount Tooltip element to body
309
+ const body = document.querySelector('body')
310
+ body?.appendChild(tooltipElement)
311
+
312
+ // Find suitable Tooltip position
313
+ let hasNeededDisplaySpace = false
314
+ let currentTooltipPosition = tooltipPosition
315
+ for (let i = 0; i < 4; i++) {
316
+ currentTooltipPosition = tooltipPositions[tooltipPosition][i]
317
+
318
+ if (currentTooltipPosition === 'left') {
319
+ hasNeededDisplaySpace = tryMountTooltipOnLeft(anchorElementRect)
320
+ } else if (currentTooltipPosition === 'top') {
321
+ hasNeededDisplaySpace = tryMountTooltipOnTop(anchorElementRect)
322
+ } else if (currentTooltipPosition === 'right') {
323
+ hasNeededDisplaySpace = tryMountTooltipOnRight(anchorElementRect)
324
+ } else if (currentTooltipPosition === 'bottom') {
325
+ hasNeededDisplaySpace = tryMountTooltipOnBottom(anchorElementRect)
326
+ }
327
+
328
+ if (hasNeededDisplaySpace) break
329
+ }
330
+
331
+ if (hasNeededDisplaySpace) {
332
+ drawArrow(anchorElementRect, currentTooltipPosition)
333
+
334
+ tooltipElement.style.opacity = '1'
335
+ }
336
+ })
337
+
338
+ // Add listener for hiding Tooltip element
339
+ anchorElement.addEventListener('mouseleave', () => hideTooltip())
340
+ },
341
+ }
342
+ }
343
+
344
+ function hideTooltip() {
345
+ const tooltipElement = document.querySelector(`#${tooltipElementId}`)
346
+
347
+ // Remove Arrow element from Tooltip, because it needs to be rebuilt every time Tooltip is showed again
348
+ tooltipElement?.querySelector(`#${arrowElementId}`)?.remove()
349
+
350
+ tooltipElement?.remove()
351
+ }
352
+
353
+ export default ZeroTooltip
@@ -0,0 +1,19 @@
1
+ import TooltipPosition from "./tooltipPosition"
2
+ import TooltipPositions from "./tooltipPositions"
3
+
4
+ type TooltipConfig = {
5
+ 'defaultPosition'?: TooltipPosition,
6
+ 'positions'?: Partial<TooltipPositions>,
7
+ 'offsetFromSource'?: number,
8
+ 'offsetFromViewport'?: number,
9
+ 'minWidth'?: number,
10
+ 'maxWidth'?: number,
11
+ 'tooltipBorderWidth'?: number,
12
+ 'tooltipClasses'?: string,
13
+ 'textClasses'?: string,
14
+ 'arrowSize'?: number,
15
+ 'arrowClasses'?: string,
16
+ 'arrowMinOffsetFromTooltipCorner'?: number
17
+ }
18
+
19
+ export default TooltipConfig
@@ -0,0 +1,4 @@
1
+ type TooltipPosition = 'left' | 'top' | 'right' | 'bottom'
2
+
3
+ export default TooltipPosition
4
+
@@ -0,0 +1,10 @@
1
+ import TooltipPosition from "./tooltipPosition"
2
+
3
+ type TooltipPositions = {
4
+ 'left': [ TooltipPosition, TooltipPosition, TooltipPosition, TooltipPosition]
5
+ 'top': [ TooltipPosition, TooltipPosition, TooltipPosition, TooltipPosition]
6
+ 'right': [ TooltipPosition, TooltipPosition, TooltipPosition, TooltipPosition]
7
+ 'bottom': [ TooltipPosition, TooltipPosition, TooltipPosition, TooltipPosition]
8
+ }
9
+
10
+ export default TooltipPositions
@@ -0,0 +1 @@
1
+ /// <reference types="vite/client" />