UNPKG

popover-lite

Version:

Tiny wrapper over the native Popover API + CSS Anchor Positioning

2 lines (1 loc) 2.43 kB
function g(r,t){r.style.setProperty("--placement",t),r.dataset.side=t}function M(r,t){typeof t=="number"?r.style.setProperty("--gap",`${t}px`):t&&(t.x!=null&&r.style.setProperty("--offset-x",`${t.x}px`),t.y!=null&&r.style.setProperty("--offset-y",`${t.y}px`))}function E(r){let t=[],n=r.parentElement;for(;n;){let e=getComputedStyle(n);/auto|scroll|overlay/.test(e.overflow+e.overflowX+e.overflowY)&&t.push(n),n=n.parentElement}return t.push(document.documentElement),t}function H(r,t,n={}){let e=r.getBoundingClientRect(),i=window.innerWidth,a=window.innerHeight,o={top:{placement:"top",space:e.top,overflow:Math.max(t.height-e.top,0),misalign:Math.abs(e.left+e.width/2-(e.left+t.width/2)),preference:n.top??0,score:0},bottom:{placement:"bottom",space:a-e.bottom,overflow:Math.max(t.height-(a-e.bottom),0),misalign:Math.abs(e.left+e.width/2-(e.left+t.width/2)),preference:n.bottom??0,score:0},left:{placement:"left",space:e.left,overflow:Math.max(t.width-e.left,0),misalign:Math.abs(e.top+e.height/2-(e.top+t.height/2)),preference:n.left??0,score:0},right:{placement:"right",space:i-e.right,overflow:Math.max(t.width-(i-e.right),0),misalign:Math.abs(e.top+e.height/2-(e.top+t.height/2)),preference:n.right??0,score:0}};for(let l of Object.values(o))l.score=l.space-l.overflow-l.misalign+l.preference;return Object.values(o).sort((l,c)=>c.score-l.score)}function T(r,t={}){let{placement:n="bottom",offset:e=8,preference:i={}}=t;r.id||(r.id=`anchor-${Math.random().toString(36).slice(2)}`);let a=r.id,o=document.createElement("div");o.setAttribute("popover","auto"),o.setAttribute("anchor",a),o.className="popover-lite",o.tabIndex=-1,M(o,e),g(o,Array.isArray(n)?n[0]:n),document.body.appendChild(o);function l(){let s=Array.isArray(n)?n:[n],w={width:o.offsetWidth,height:o.offsetHeight},u=H(r,w,i);for(let p=0;p<s.length;p++){let y=(s.length-p)*1e4,v=u.find(x=>x.placement===s[p]);v&&(v.score+=y)}return u[0].placement}function c(){g(o,l())}function m(){c(),o.showPopover?o.showPopover():o.togglePopover?.()}function h(){o.hidePopover?o.hidePopover():o.togglePopover?.()}function P(){o.matches(":popover-open")?h():m()}function b(){f.disconnect(),d.forEach(s=>s.removeEventListener("scroll",c)),o.remove()}let f=new ResizeObserver(()=>c());f.observe(r);let d=E(r);return d.forEach(s=>s.addEventListener("scroll",c,{passive:!0})),{element:o,show:m,hide:h,toggle:P,update:c,destroy:b}}export{H as computeScores,T as createPopover};