@spectrum-web-components/overlay
Version:
An `<sp-overlay>` element is used to decorate content that you would like to present to your visitors as "overlaid" on the rest of the application. This includes dialogs (modal and not), pickers, tooltips, context menus, et al.
3 lines (2 loc) • 3.83 kB
JavaScript
"use strict";import{arrow as w,autoUpdate as v,computePosition as H,flip as y,offset as R,shift as A,size as M}from"@floating-ui/dom";function c(o){if(typeof o=="undefined")return 0;const t=window.devicePixelRatio||1;return Math.round(o*t)/t}const p=8,C=100,T=o=>{var e;return(e={left:["right","bottom","top"],"left-start":["right-start","bottom","top"],"left-end":["right-end","bottom","top"],right:["left","bottom","top"],"right-start":["left-start","bottom","top"],"right-end":["left-end","bottom","top"],top:["bottom","left","right"],"top-start":["bottom-start","left","right"],"top-end":["bottom-end","left","right"],bottom:["top","left","right"],"bottom-start":["top-start","left","right"],"bottom-end":["top-end","left","right"]}[o])!=null?e:[o]};export const placementUpdatedSymbol=Symbol("placement updated");export class PlacementController{constructor(t){this.originalPlacements=new WeakMap;this.allowPlacementUpdate=!1;this.closeForAncestorUpdate=()=>{!this.allowPlacementUpdate&&this.options.type!=="modal"&&this.cleanup&&this.target.dispatchEvent(new Event("close",{bubbles:!0})),this.allowPlacementUpdate=!1};this.updatePlacement=()=>{this.computePlacement()};this.resetOverlayPosition=()=>{!this.target||!this.options||(this.clearOverlayPosition(),this.host.offsetHeight,this.computePlacement())};this.host=t,this.host.addController(this)}async placeOverlay(t=this.target,e=this.options){if(this.target=t,this.options=e,!t||!e)return;const m=v(e.trigger,t,this.closeForAncestorUpdate,{ancestorResize:!1,elementResize:!1,layoutShift:!1}),h=v(e.trigger,t,this.updatePlacement,{ancestorScroll:!1});this.cleanup=()=>{var n;(n=this.host.elements)==null||n.forEach(a=>{a.addEventListener("sp-closed",()=>{const r=this.originalPlacements.get(a);r&&a.setAttribute("placement",r),this.originalPlacements.delete(a)},{once:!0})}),m(),h()}}async computePlacement(){var g,u;const{options:t,target:e}=this;await(document.fonts?document.fonts.ready:Promise.resolve());const m=t.trigger instanceof HTMLElement?y():y({padding:p,fallbackPlacements:T(t.placement)}),[h=0,n=0]=Array.isArray(t==null?void 0:t.offset)?t.offset:[t.offset,0],a=(g=this.host.elements.find(i=>i.tipElement))==null?void 0:g.tipElement,r=[R({mainAxis:h,crossAxis:n}),A({padding:p}),m,M({padding:p,apply:({availableWidth:i,availableHeight:d,rects:{floating:x}})=>{const b=Math.max(C,Math.floor(d)),l=x.height;this.initialHeight=this.isConstrained&&this.initialHeight||l,this.isConstrained=l<this.initialHeight||b<=l;const O=this.isConstrained?`${b}px`:"";Object.assign(e.style,{maxWidth:`${Math.floor(i)}px`,maxHeight:O})}}),...a?[w({element:a,padding:t.tipPadding||p})]:[]],{x:P,y:E,placement:s,middlewareData:f}=await H(t.trigger,e,{placement:t.placement,middleware:r,strategy:"fixed"});if(Object.assign(e.style,{top:"0px",left:"0px",translate:`${c(P)}px ${c(E)}px`}),e.setAttribute("actual-placement",s),(u=this.host.elements)==null||u.forEach(i=>{this.originalPlacements.has(i)||this.originalPlacements.set(i,i.getAttribute("placement")),i.setAttribute("placement",s)}),a&&f.arrow){const{x:i,y:d}=f.arrow;Object.assign(a.style,{top:s.startsWith("right")||s.startsWith("left")?"0px":"",left:s.startsWith("bottom")||s.startsWith("top")?"0px":"",translate:`${c(i)}px ${c(d)}px`})}}clearOverlayPosition(){this.target&&(this.target.style.removeProperty("max-height"),this.target.style.removeProperty("max-width"),this.initialHeight=void 0,this.isConstrained=!1)}hostConnected(){document.addEventListener("sp-update-overlays",this.resetOverlayPosition)}hostUpdated(){var t;this.host.open||((t=this.cleanup)==null||t.call(this),this.cleanup=void 0)}hostDisconnected(){var t;(t=this.cleanup)==null||t.call(this),this.cleanup=void 0,document.removeEventListener("sp-update-overlays",this.resetOverlayPosition)}}
//# sourceMappingURL=PlacementController.js.map