@vielzeug/orbit 1.0.3
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.
- package/README.md +77 -0
- package/dist/_dev.cjs +2 -0
- package/dist/_dev.cjs.map +1 -0
- package/dist/_dev.d.ts +2 -0
- package/dist/_dev.d.ts.map +1 -0
- package/dist/_dev.js +2 -0
- package/dist/_dev.js.map +1 -0
- package/dist/auto-update.cjs +2 -0
- package/dist/auto-update.cjs.map +1 -0
- package/dist/auto-update.d.ts +53 -0
- package/dist/auto-update.d.ts.map +1 -0
- package/dist/auto-update.js +2 -0
- package/dist/auto-update.js.map +1 -0
- package/dist/compose.cjs +2 -0
- package/dist/compose.cjs.map +1 -0
- package/dist/compose.d.ts +25 -0
- package/dist/compose.d.ts.map +1 -0
- package/dist/compose.js +2 -0
- package/dist/compose.js.map +1 -0
- package/dist/core.cjs +2 -0
- package/dist/core.cjs.map +1 -0
- package/dist/core.d.ts +43 -0
- package/dist/core.d.ts.map +1 -0
- package/dist/core.js +2 -0
- package/dist/core.js.map +1 -0
- package/dist/devtools.cjs +2 -0
- package/dist/devtools.cjs.map +1 -0
- package/dist/devtools.d.ts +36 -0
- package/dist/devtools.d.ts.map +1 -0
- package/dist/devtools.js +2 -0
- package/dist/devtools.js.map +1 -0
- package/dist/errors.cjs +2 -0
- package/dist/errors.cjs.map +1 -0
- package/dist/errors.d.ts +9 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +2 -0
- package/dist/errors.js.map +1 -0
- package/dist/float.cjs +2 -0
- package/dist/float.cjs.map +1 -0
- package/dist/float.d.ts +73 -0
- package/dist/float.d.ts.map +1 -0
- package/dist/float.js +2 -0
- package/dist/float.js.map +1 -0
- package/dist/index.cjs +1 -0
- package/dist/index.d.ts +28 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +1 -0
- package/dist/inline.cjs +2 -0
- package/dist/inline.cjs.map +1 -0
- package/dist/inline.d.ts +35 -0
- package/dist/inline.d.ts.map +1 -0
- package/dist/inline.js +2 -0
- package/dist/inline.js.map +1 -0
- package/dist/middleware/arrow.cjs +2 -0
- package/dist/middleware/arrow.cjs.map +1 -0
- package/dist/middleware/arrow.d.ts +25 -0
- package/dist/middleware/arrow.d.ts.map +1 -0
- package/dist/middleware/arrow.js +2 -0
- package/dist/middleware/arrow.js.map +1 -0
- package/dist/middleware/auto-placement.cjs +2 -0
- package/dist/middleware/auto-placement.cjs.map +1 -0
- package/dist/middleware/auto-placement.d.ts +28 -0
- package/dist/middleware/auto-placement.d.ts.map +1 -0
- package/dist/middleware/auto-placement.js +2 -0
- package/dist/middleware/auto-placement.js.map +1 -0
- package/dist/middleware/flip.cjs +2 -0
- package/dist/middleware/flip.cjs.map +1 -0
- package/dist/middleware/flip.d.ts +14 -0
- package/dist/middleware/flip.d.ts.map +1 -0
- package/dist/middleware/flip.js +2 -0
- package/dist/middleware/flip.js.map +1 -0
- package/dist/middleware/hide.cjs +2 -0
- package/dist/middleware/hide.cjs.map +1 -0
- package/dist/middleware/hide.d.ts +17 -0
- package/dist/middleware/hide.d.ts.map +1 -0
- package/dist/middleware/hide.js +2 -0
- package/dist/middleware/hide.js.map +1 -0
- package/dist/middleware/offset.cjs +2 -0
- package/dist/middleware/offset.cjs.map +1 -0
- package/dist/middleware/offset.d.ts +16 -0
- package/dist/middleware/offset.d.ts.map +1 -0
- package/dist/middleware/offset.js +2 -0
- package/dist/middleware/offset.js.map +1 -0
- package/dist/middleware/shift.cjs +2 -0
- package/dist/middleware/shift.cjs.map +1 -0
- package/dist/middleware/shift.d.ts +69 -0
- package/dist/middleware/shift.d.ts.map +1 -0
- package/dist/middleware/shift.js +2 -0
- package/dist/middleware/shift.js.map +1 -0
- package/dist/middleware/size.cjs +2 -0
- package/dist/middleware/size.cjs.map +1 -0
- package/dist/middleware/size.d.ts +22 -0
- package/dist/middleware/size.d.ts.map +1 -0
- package/dist/middleware/size.js +2 -0
- package/dist/middleware/size.js.map +1 -0
- package/dist/orbit.cjs +2 -0
- package/dist/orbit.cjs.map +1 -0
- package/dist/orbit.iife.js +2 -0
- package/dist/orbit.iife.js.map +1 -0
- package/dist/orbit.js +2 -0
- package/dist/orbit.js.map +1 -0
- package/dist/overflow.cjs +2 -0
- package/dist/overflow.cjs.map +1 -0
- package/dist/overflow.d.ts +32 -0
- package/dist/overflow.d.ts.map +1 -0
- package/dist/overflow.js +2 -0
- package/dist/overflow.js.map +1 -0
- package/dist/presets.cjs +2 -0
- package/dist/presets.cjs.map +1 -0
- package/dist/presets.d.ts +65 -0
- package/dist/presets.d.ts.map +1 -0
- package/dist/presets.js +2 -0
- package/dist/presets.js.map +1 -0
- package/dist/reactive.cjs +2 -0
- package/dist/reactive.cjs.map +1 -0
- package/dist/reactive.d.ts +47 -0
- package/dist/reactive.d.ts.map +1 -0
- package/dist/reactive.js +2 -0
- package/dist/reactive.js.map +1 -0
- package/dist/ssr.cjs +2 -0
- package/dist/ssr.cjs.map +1 -0
- package/dist/ssr.d.ts +41 -0
- package/dist/ssr.d.ts.map +1 -0
- package/dist/ssr.js +2 -0
- package/dist/ssr.js.map +1 -0
- package/dist/types.d.ts +166 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/utils.cjs +2 -0
- package/dist/utils.cjs.map +1 -0
- package/dist/utils.d.ts +9 -0
- package/dist/utils.d.ts.map +1 -0
- package/dist/utils.js +2 -0
- package/dist/utils.js.map +1 -0
- package/package.json +67 -0
package/dist/orbit.js
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{clamp as e,throttle as t}from"@vielzeug/arsenal";var n=class e extends Error{constructor(e,t){super(e,t),this.name=new.target.name,Object.setPrototypeOf(this,new.target.prototype)}static is(t){return t instanceof e}},r=class extends n{},i=!globalThis.__ORBIT_PROD__;function a(e){i&&console.warn(`[@vielzeug/orbit] ${e}`)}function o(e){i&&e()}var s={bottom:`top`,left:`right`,right:`left`,top:`bottom`};function c(e){return e.split(`-`)[0]}function l(e){return e.split(`-`)[1]??null}function u(e,t){return t?`${e}-${t}`:e}function d({height:e,width:t,x:n,y:r}){return{height:e,width:t,x:n,y:r}}function f(e=0){return typeof e==`number`?{bottom:e,left:e,right:e,top:e}:{bottom:e.bottom??0,left:e.left??0,right:e.right??0,top:e.top??0}}function p(e){return typeof Element<`u`&&e instanceof Element}var m=[[`arrow`,`flip`],[`arrow`,`shift`],[`arrow`,`autoPlacement`],[`flip`,`inline`],[`shift`,`inline`],[`autoPlacement`,`inline`],[`size`,`flip`],[`size`,`autoPlacement`]];function h(e){for(let[t,n]of m){let i=e.indexOf(t),a=e.indexOf(n);if(i!==-1&&a!==-1&&i<a)throw new r(`"${t}" must come after "${n}" in the middleware pipeline. Recommended order: inline → offset → flip/autoPlacement → shift → size → arrow.`)}if(e.includes(`flip`)&&e.includes(`autoPlacement`))throw new r(`use either flip() or autoPlacement() in the middleware pipeline, not both.`)}var g=Symbol.for(`@vielzeug/orbit/name`);function _(e,t){return e[g]=t,e}function v(e,t,n,r){return e===`start`?t:e===`end`?t+n-r:t+(n-r)/2}function y(e,t,n){let r=c(e),i=l(e);switch(r){case`bottom`:return{x:v(i,t.x,t.width,n.width),y:t.y+t.height};case`left`:return{x:t.x-n.width,y:v(i,t.y,t.height,n.height)};case`right`:return{x:t.x+t.width,y:v(i,t.y,t.height,n.height)};case`top`:return{x:v(i,t.x,t.width,n.width),y:t.y-n.height}}}function b(e,t){return{floating:d(t.getBoundingClientRect()),reference:d(e.getBoundingClientRect())}}function x(e,t){return t?{...e,middlewareData:t.data?Object.assign(Object.create(null),e.middlewareData,t.data):e.middlewareData,placement:t.placement??e.placement,x:t.x??e.x,y:t.y??e.y}:e}var S=8;function ee(e,t,n){return Promise.resolve().then(()=>w(e,t,n))}function C(e,t,n){return new Promise((r,i)=>{requestAnimationFrame(()=>{try{r(w(e,t,n))}catch(e){i(e)}})})}function w(e,t,{boundary:n,containingBlock:i,middleware:s=[],padding:c,placement:l=`bottom`}={}){let u=s.filter(Boolean);e===t&&a(`computePosition: reference and floating are the same element.`),h(u.map(e=>{let t=e[g];return typeof t==`string`?t:null}));let d=l,f={},p=b(e,t);o(()=>{p.floating.width===0&&p.floating.height===0&&a(`computePosition: floating element has zero dimensions — is it hidden or detached from the DOM?`);let e=getComputedStyle(t).position;e!==`fixed`&&e!==`absolute`&&a(`computePosition: floating element has \`position: ${e}\`. Orbit computes viewport-relative coordinates and expects position: fixed (or absolute for scoped stacking contexts).`)});for(let r=0;r<S;r+=1){let r={...y(d,p.reference,p.floating),boundary:n,elements:{floating:t,reference:e},initialPlacement:l,middlewareData:f,padding:c,placement:d,rects:p},a;for(let e of u){let t=e(r);if(r=x(r,t),f=r.middlewareData,a=t?.reset,a)break}if(!a){let e={middlewareData:r.middlewareData,placement:r.placement,x:r.x,y:r.y};if(i){let t=i.getBoundingClientRect();return{...e,x:e.x-t.x,y:e.y-t.y}}return e}a.remeasure?p=b(e,t):a.rects!=null&&(p=a.rects),d=a.placement??r.placement}throw new r(`Middleware triggered too many resets in a single compute cycle.`)}function T(){let e=window.visualViewport;return e?{height:e.height,width:e.width,x:e.offsetLeft,y:e.offsetTop}:{height:window.innerHeight,width:window.innerWidth,x:0,y:0}}function E(e){if(!e)return T();if(e instanceof Element){let t=e.getBoundingClientRect();return{height:t.height,width:t.width,x:t.x,y:t.y}}return e}function D(e,t){return{boundary:E(e.boundary??t.boundary),padding:f(e.padding??t.padding)}}function O(e){return{...e.rects.floating,x:e.x,y:e.y}}function k(e,t,n){return{bottom:e.y+e.height-(t.y+t.height-n.bottom),left:t.x+n.left-e.x,right:e.x+e.width-(t.x+t.width-n.right),top:t.y+n.top-e.y}}function A(e){return Math.max(e.top,0)+Math.max(e.right,0)+Math.max(e.bottom,0)+Math.max(e.left,0)}function j(e){return e.top>0||e.right>0||e.bottom>0||e.left>0}function M(e,t){return t.top>=e.height||t.right>=e.width||t.bottom>=e.height||t.left>=e.width}function N(e,t,n,r){let i=e.rects.reference;switch(c(t)){case`bottom`:return n.y+n.height-r.bottom-(i.y+i.height);case`left`:return i.x-(n.x+r.left);case`right`:return n.x+n.width-r.right-(i.x+i.width);case`top`:return i.y-(n.y+r.top)}}function P(e,t,n={}){let{x:r,y:i}=y(t,e.rects.reference,e.rects.floating),{boundary:a,padding:o}=D(n,e);return k({...e.rects.floating,x:r,y:i},a,o)}function F(e,t={}){let{boundary:n,padding:r}=D(t,e);return k(O(e),n,r)}function I(e){let t=[],n=e.parentElement;for(;n;){let e=getComputedStyle(n),r=e.overflow+e.overflowX+e.overflowY;if(/auto|scroll|overlay/.test(r)&&t.push(n),n.parentElement)n=n.parentElement;else{let e=n.getRootNode();n=e instanceof ShadowRoot?e.host:null}}return t}function L(e,n,r,{animationFrame:i=!1,observeAncestors:a=!0,observeFloating:o=!0,observeVisualViewport:s=!0,pauseWhenHidden:c=!0,throttle:l=0}={}){let u=l>0?t(r,l,{leading:!0,trailing:!0}):null,d=u??r,f=!0,m=()=>{f&&d()};d();let h=[];if(c&&p(e)&&typeof IntersectionObserver<`u`){let t=new IntersectionObserver(e=>{f=e.at(-1)?.isIntersecting??!0,f&&d()});t.observe(e),h.push(()=>t.disconnect())}if(p(e)&&a){let t=I(e);for(let e of t)e.addEventListener(`scroll`,m,{passive:!0}),h.push(()=>e.removeEventListener(`scroll`,m));window.addEventListener(`scroll`,m,{passive:!0}),h.push(()=>window.removeEventListener(`scroll`,m))}else{let e=e=>{e.composedPath().includes(n)||m()};window.addEventListener(`scroll`,e,{capture:!0,passive:!0}),h.push(()=>window.removeEventListener(`scroll`,e,{capture:!0}))}window.addEventListener(`resize`,m,{passive:!0}),h.push(()=>window.removeEventListener(`resize`,m));let g=s?window.visualViewport:null;g&&(g.addEventListener(`resize`,m,{passive:!0}),g.addEventListener(`scroll`,m,{passive:!0}),h.push(()=>{g.removeEventListener(`resize`,m),g.removeEventListener(`scroll`,m)}));let _=new ResizeObserver(m);p(e)&&_.observe(e),o&&_.observe(n),h.push(()=>_.disconnect());let v=0;if(i){let e=()=>{m(),v=window.requestAnimationFrame(e)};v=window.requestAnimationFrame(e),h.push(()=>window.cancelAnimationFrame(v))}return()=>{u?.cancel();for(let e of h)e()}}function R(e,t,n){let r=new AbortController,i=!1;return{get disposalSignal(){return r.signal},dispose(){i||(i=!0,r.abort(),e())},get disposed(){return i},getPosition:t,[Symbol.dispose](){this.dispose()},update:n}}function z(){return typeof CSS<`u`&&CSS.supports(`anchor-name`,`--orbit`)}var B=0,V={bottom:`block-end center`,"bottom-end":`block-end span-inline-end`,"bottom-start":`block-end span-inline-start`,left:`inline-start center`,"left-end":`inline-start span-block-end`,"left-start":`inline-start span-block-start`,right:`inline-end center`,"right-end":`inline-end span-block-end`,"right-start":`inline-end span-block-start`,top:`block-start center`,"top-end":`block-start span-inline-end`,"top-start":`block-start span-inline-start`};function H(e,t){let n={};for(let r of Object.keys(t)){let i=e.style.getPropertyValue(r);n[r]=i===``?void 0:i,e.style.setProperty(r,t[r])}return()=>{for(let r of Object.keys(t)){let t=n[r];t===void 0?e.style.removeProperty(r):e.style.setProperty(r,t)}}}function U(e,t,n,r){let i=`--orbit-${++B}`,a=H(e,{"anchor-name":i}),o=H(t,{position:`fixed`,"position-anchor":i,"position-area":V[n],"position-try-fallbacks":r});return()=>{a(),o()}}function W(e,t,{fallbacks:n=`flip-block, flip-inline, flip-block flip-inline`,placement:r=`bottom`}={}){let i=U(e,t,r,n),a=R(()=>i(),()=>null,()=>{});return Object.assign(a,{cssAnchor:!0})}function G(e,t){t.style.left=`${e.x}px`,t.style.top=`${e.y}px`}function K(e,t,{apply:n,autoUpdate:r={},boundary:i,containingBlock:a,middleware:o,padding:s,placement:c=`bottom`}={}){let l=null,u=n??(e=>G(e,t));function d(){let n=w(e,t,{boundary:i,containingBlock:a,middleware:o,padding:s,placement:c});l=n,u(n)}if(r===!1)return d(),R(()=>{},()=>l,d);let f=L(e,t,d,r);return R(()=>f(),()=>l,d)}function q(...e){return e.filter(Boolean)}function J({element:t,padding:n=0}){function r(r){let i=c(r.placement),a=f(n),o=d(t.getBoundingClientRect());if(i===`top`||i===`bottom`){let t=r.rects.reference.x+r.rects.reference.width/2-r.x-o.width/2,n=a.left,i=e(t,n,Math.max(n,r.rects.floating.width-o.width-a.right));return{data:{arrow:{centerOffset:t-i,constrained:i!==t,x:i}}}}let s=r.rects.reference.y+r.rects.reference.height/2-r.y-o.height/2,l=a.top,u=e(s,l,Math.max(l,r.rects.floating.height-o.height-a.bottom));return{data:{arrow:{centerOffset:s-u,constrained:u!==s,y:u}}}}return _(r,`arrow`)}var Y=[`top`,`right`,`bottom`,`left`];function X(e){return e===void 0?Y:e===null?Y.flatMap(e=>[e,`${e}-start`,`${e}-end`]):Y.map(t=>`${t}-${e}`)}function Z(e={}){return _(function(t){let{boundary:n,padding:r}=D(e,t),i=e.allowedPlacements??X(e.alignment);i.length===0&&a(`autoPlacement: allowedPlacements is empty — no placement will be evaluated.`);let o=t.placement,s=1/0,c=-1/0;for(let a of i){let i=A(P(t,a,e)),l=N(t,a,n,r);(i<s||i===s&&l>c)&&(o=a,s=i,c=l)}if(o!==t.placement)return{reset:{placement:o}}},`autoPlacement`)}function Q(e={}){function t(t){let n=F(t,e);if(!j(n))return;let r=c(t.placement),i=l(t.placement),a=e.fallbackPlacements??[u(s[r],i)],o=[t.placement],d=t.placement,f=A(n);for(let n of a){let r=P(t,n,e),i=A(r);if(!j(r))return{data:{flip:{skippedPlacements:o}},reset:{placement:n}};o.push(n),i<f&&(d=n,f=i)}if(d!==t.placement)return{data:{flip:{skippedPlacements:o}},reset:{placement:d}}}return _(t,`flip`)}function te(e={}){let t=e.strategy??`both`;function n(n){let{boundary:r,padding:i}=D(e,n),a={};if(t===`escaped`||t===`both`){let e=O(n),t=k(e,r,i);a.escaped=M(e,t),a.escapedOffsets=t}if(t===`referenceHidden`||t===`both`){let e=k(n.rects.reference,r,i);a.referenceHidden=M(n.rects.reference,e),a.referenceHiddenOffsets=e}return{data:{hide:a}}}return _(n,`hide`)}function ne(e){return!(`getClientRects`in e)||typeof e.getClientRects!=`function`?[]:Array.from(e.getClientRects()).map(d).filter(e=>e.width>0||e.height>0)}function re(e,t,n,r){return t>=e.x-r.left&&t<=e.x+e.width+r.right&&n>=e.y-r.top&&n<=e.y+e.height+r.bottom}function ie(e,t){return e.x===t.x&&e.y===t.y&&e.width===t.width&&e.height===t.height}function $(e={}){function t(t){let n=ne(t.elements.reference);if(n.length<=1)return;let r=f(e.padding??2),i=c(t.placement),a=n[0];if(e.x!=null&&e.y!=null)a=n.find(t=>re(t,e.x,e.y,r))??a;else if(i===`top`||i===`bottom`){let e=t.x+t.rects.floating.width/2;a=n.reduce((t,n)=>{let r=Math.abs(t.x+t.width/2-e);return Math.abs(n.x+n.width/2-e)<r?n:t},a)}else{let e=t.y+t.rects.floating.height/2;a=n.reduce((t,n)=>{let r=Math.abs(t.y+t.height/2-e);return Math.abs(n.y+n.height/2-e)<r?n:t},a)}if(!ie(a,t.rects.reference))return{reset:{rects:{...t.rects,reference:a}}}}return _(t,`inline`)}function ae(e,t){let n=typeof e==`function`?e(t):e;return typeof n==`number`?{crossAxis:0,mainAxis:n}:{crossAxis:n.crossAxis??0,mainAxis:n.mainAxis??0}}function oe(e){return _(function(t){let n=c(t.placement),{crossAxis:r,mainAxis:i}=ae(e,t);switch(n){case`bottom`:return{x:t.x+r,y:t.y+i};case`left`:return{x:t.x-i,y:t.y+r};case`right`:return{x:t.x+i,y:t.y+r};case`top`:return{x:t.x+r,y:t.y-i}}},`offset`)}function se(t={}){return(n,r)=>{let{placement:i,rects:a,x:o,y:s}=n,l=c(i),u=l===`top`||l===`bottom`,d=typeof t.offset==`function`?t.offset(n):t.offset??0;if(u){let t=a.reference.x-d,n=a.reference.x+a.reference.width+d-a.floating.width,[i,s]=t<=n?[t,n]:[n,t],c=e(o+r.crossAxis,i,s);return{...r,crossAxis:c-o}}let f=a.reference.y-d,p=a.reference.y+a.reference.height+d-a.floating.height,[m,h]=f<=p?[f,p]:[p,f],g=e(s+r.crossAxis,m,h);return{...r,crossAxis:g-s}}}function ce(e={}){let{crossAxis:t=!0,limiter:n,mainAxis:r=!1}=e;function i(i){let a=F(i,e),o=c(i.placement),s=o===`top`||o===`bottom`,l=Math.max(a.left,0)-Math.max(a.right,0),u=Math.max(a.top,0)-Math.max(a.bottom,0),d=s?t:r,f=s?r:t,p=d?l:0,m=f?u:0;if(n){let e=n(i,{crossAxis:s?p:m,mainAxis:s?m:p});p=s?e.crossAxis:e.mainAxis,m=s?e.mainAxis:e.crossAxis}return{data:{shift:{x:p,y:m}},x:i.x+p,y:i.y+m}}return _(i,`shift`)}function le(e={}){function t(t){let{boundary:n,padding:r}=D(e,t),i=c(t.placement),a=n.y+r.top,o=n.x+n.width-r.right,s=n.y+n.height-r.bottom,l=n.x+r.left;return{data:{size:{availableHeight:i===`bottom`?Math.max(0,s-t.y):i===`top`?Math.max(0,t.rects.reference.y-a):Math.max(0,s-a),availableWidth:i===`right`?Math.max(0,o-t.x):i===`left`?Math.max(0,t.rects.reference.x-l):Math.max(0,o-l)}}}}return _(t,`size`)}export{r as OrbitConfigError,n as OrbitError,J as arrow,Z as autoPlacement,L as autoUpdate,q as compose,w as computePosition,ee as computePositionAsync,C as computePositionRaf,F as detectOverflow,Q as flip,K as float,W as floatWithAnchor,l as getAlignment,b as getRects,c as getSide,te as hide,$ as inline,z as isCssAnchorSupported,se as limitShift,oe as offset,ce as shift,le as size};
|
|
2
|
+
//# sourceMappingURL=orbit.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"orbit.js","names":[],"sources":["../src/errors.ts","../src/_dev.ts","../src/utils.ts","../src/core.ts","../src/overflow.ts","../src/auto-update.ts","../src/float.ts","../src/compose.ts","../src/middleware/arrow.ts","../src/middleware/auto-placement.ts","../src/middleware/flip.ts","../src/middleware/hide.ts","../src/inline.ts","../src/middleware/offset.ts","../src/middleware/shift.ts","../src/middleware/size.ts"],"sourcesContent":["/** Base class for all orbit errors. Use `instanceof OrbitError` to catch any orbit-originated error. */\nexport class OrbitError extends Error {\n constructor(message: string, opts?: ErrorOptions) {\n super(message, opts);\n this.name = new.target.name;\n Object.setPrototypeOf(this, new.target.prototype);\n }\n\n static is(err: unknown): err is OrbitError {\n return err instanceof OrbitError;\n }\n}\n\n/** Thrown when a middleware pipeline is configured incorrectly. */\nexport class OrbitConfigError extends OrbitError {}\n","const isDev = !(globalThis as { __ORBIT_PROD__?: boolean }).__ORBIT_PROD__;\n\n/** @internal @security Messages may include user-supplied element dimensions or computed styles. */\nexport function warn(msg: string): void {\n if (isDev) console.warn(`[@vielzeug/orbit] ${msg}`);\n}\n\n/** @internal — Run fn only in dev builds. Use when dev-only logic goes beyond a single warn() / error() call. */\nexport function devOnly(fn: () => void): void {\n if (isDev) fn();\n}\n","import { clamp } from '@vielzeug/arsenal';\n\nimport type { Alignment, Middleware, Padding, Placement, Rect, Side, SideObject, TypedMiddleware } from './types';\n\nimport { OrbitConfigError } from './errors';\n\nexport { clamp };\n\nexport const OPPOSITE: Record<Side, Side> = { bottom: 'top', left: 'right', right: 'left', top: 'bottom' };\n\n/** Returns the primary side of a placement (`'top' | 'bottom' | 'left' | 'right'`). */\nexport function getSide(p: Placement): Side {\n return p.split('-')[0] as Side;\n}\n\n/** Returns the alignment of a placement (`'start' | 'end'`), or `null` for center placements. */\nexport function getAlignment(p: Placement): Alignment | null {\n return (p.split('-')[1] as Alignment) ?? null;\n}\n\n/** @internal */\nexport function withPlacement(side: Side, align: Alignment | null): Placement {\n return (align ? `${side}-${align}` : side) as Placement;\n}\n\n/** @internal */\nexport function toRect({ height, width, x, y }: DOMRect | Rect): Rect {\n return { height, width, x, y };\n}\n\n/** @internal */\nexport function toSideObject(padding: Padding = 0): SideObject {\n if (typeof padding === 'number') {\n return { bottom: padding, left: padding, right: padding, top: padding };\n }\n\n return {\n bottom: padding.bottom ?? 0,\n left: padding.left ?? 0,\n right: padding.right ?? 0,\n top: padding.top ?? 0,\n };\n}\n\n/** @internal */\nexport function isElement(value: unknown): value is Element {\n return typeof Element !== 'undefined' && value instanceof Element;\n}\n\n// ── Middleware helpers ────────────────────────────────────────────────────────\n\n/**\n * Ordering rules for dev-mode middleware validation.\n * Each tuple is `[mustFollow, mustPrecede]` — `mustFollow` must appear **after** `mustPrecede`\n * in the pipeline. Validation throws if `mustFollow` is found at a lower index than `mustPrecede`.\n * @internal\n */\nexport const MIDDLEWARE_ORDER_RULES: Array<[mustFollow: string, mustPrecede: string]> = [\n ['arrow', 'flip'],\n ['arrow', 'shift'],\n ['arrow', 'autoPlacement'],\n ['flip', 'inline'],\n ['shift', 'inline'],\n ['autoPlacement', 'inline'],\n ['size', 'flip'],\n ['size', 'autoPlacement'],\n];\n\n/**\n * Validates a list of middleware names for known-bad orderings.\n * Throws a descriptive error in dev mode if an invalid ordering is detected.\n * @internal\n */\nexport function validateMiddlewareNames(names: Array<string | null>): void {\n for (const [mustFollow, mustPrecede] of MIDDLEWARE_ORDER_RULES) {\n const followIdx = names.indexOf(mustFollow);\n const precedeIdx = names.indexOf(mustPrecede);\n\n if (followIdx !== -1 && precedeIdx !== -1 && followIdx < precedeIdx) {\n throw new OrbitConfigError(\n `\"${mustFollow}\" must come after \"${mustPrecede}\" in the middleware pipeline. ` +\n `Recommended order: inline → offset → flip/autoPlacement → shift → size → arrow.`,\n );\n }\n }\n\n if (names.includes('flip') && names.includes('autoPlacement')) {\n throw new OrbitConfigError('use either flip() or autoPlacement() in the middleware pipeline, not both.');\n }\n}\n\n/**\n * Unique symbol used to tag middleware with a name for dev-mode ordering validation.\n * Using a Symbol avoids collisions with any `__name` property set by transpilers or wrappers.\n * @internal\n */\nexport const MIDDLEWARE_NAME = Symbol.for('@vielzeug/orbit/name');\n\n/**\n * Tags a middleware function with a name for dev-mode ordering validation and brands it\n * as a `TypedMiddleware<K, D>` for compile-time `middlewareData` inference.\n * @internal\n */\nexport function tagMiddleware<K extends string, D, F extends Middleware>(fn: F, name: K): F & TypedMiddleware<K, D> {\n (fn as Record<symbol, unknown>)[MIDDLEWARE_NAME] = name;\n\n return fn as F & TypedMiddleware<K, D>;\n}\n\n// ── Geometry ──────────────────────────────────────────────────────────────────\n\nfunction alignedOffset(align: Alignment | null, refStart: number, refSize: number, floatSize: number): number {\n if (align === 'start') return refStart;\n\n if (align === 'end') return refStart + refSize - floatSize;\n\n return refStart + (refSize - floatSize) / 2;\n}\n\n/**\n * Computes the base (un-shifted) x/y coordinates for a floating element\n * given the placement and the reference/floating rects.\n * @internal\n */\nexport function baseCoords(placement: Placement, ref: Rect, float: Rect): { x: number; y: number } {\n const side = getSide(placement);\n const align = getAlignment(placement);\n\n switch (side) {\n case 'bottom':\n return { x: alignedOffset(align, ref.x, ref.width, float.width), y: ref.y + ref.height };\n case 'left':\n return { x: ref.x - float.width, y: alignedOffset(align, ref.y, ref.height, float.height) };\n case 'right':\n return { x: ref.x + ref.width, y: alignedOffset(align, ref.y, ref.height, float.height) };\n case 'top':\n return { x: alignedOffset(align, ref.x, ref.width, float.width), y: ref.y - float.height };\n }\n}\n","import type {\n ComputePositionOptions,\n ComputePositionResult,\n Middleware,\n MiddlewareData,\n MiddlewareReset,\n MiddlewareResult,\n MiddlewareState,\n ReferenceElement,\n} from './types';\n\nimport { devOnly, warn } from './_dev';\nimport { OrbitConfigError } from './errors';\nimport { baseCoords, MIDDLEWARE_NAME, toRect, validateMiddlewareNames } from './utils';\n\n// ── DOM helpers ────────────────────────────────────────────────────────────────────────────────\n\n/** Reads the bounding rects of the reference and floating elements from the DOM. */\nexport function getRects(reference: ReferenceElement, floating: HTMLElement): MiddlewareState['rects'] {\n return {\n floating: toRect(floating.getBoundingClientRect()),\n reference: toRect(reference.getBoundingClientRect()),\n };\n}\n\n// ── Internal state helpers ───────────────────────────────────────────────────────────\n\nfunction mergeState(state: MiddlewareState, result: MiddlewareResult | void): MiddlewareState {\n if (!result) return state;\n\n return {\n ...state,\n middlewareData: result.data\n ? (Object.assign(Object.create(null), state.middlewareData, result.data) as MiddlewareData)\n : state.middlewareData,\n placement: result.placement ?? state.placement,\n x: result.x ?? state.x,\n y: result.y ?? state.y,\n };\n}\n\n// ── Constants ─────────────────────────────────────────────────────────────────────────────────\n\n/** Maximum number of pipeline restarts allowed per `computePosition` call before throwing. */\nconst MAX_RESETS = 8;\n\n// ── Public API ────────────────────────────────────────────────────────────────────────────────\n\n/**\n * Deferred position computation. Runs `computePosition` in the next **microtask** and\n * returns a `Promise<ComputePositionResult>`.\n *\n * Useful for async component lifecycles (e.g. `await nextTick()` in Vue/React) where the\n * synchronous `computePosition` would read stale DOM measurements because layout has not been\n * committed yet. Note: this defers to the microtask queue, not the next animation frame — if you\n * need post-layout measurements use `requestAnimationFrame` instead.\n *\n * @example\n * ```ts\n * const result = await computePositionAsync(reference, floating, { placement: 'top' });\n * floating.style.left = `${result.x}px`;\n * floating.style.top = `${result.y}px`;\n * ```\n */\nexport function computePositionAsync(\n reference: ReferenceElement,\n floating: HTMLElement,\n options?: ComputePositionOptions,\n): Promise<ComputePositionResult> {\n return Promise.resolve().then(() => computePosition(reference, floating, options));\n}\n\n/**\n * Deferred position computation. Runs `computePosition` in the next **animation frame** and\n * returns a `Promise<ComputePositionResult>`.\n *\n * Useful when the layout has not yet committed (e.g. immediately after DOM insertion). Unlike\n * `computePositionAsync` which defers to the microtask queue, this waits for the next\n * `requestAnimationFrame` tick — guaranteeing post-layout DOM measurements.\n *\n * @example\n * ```ts\n * const result = await computePositionRaf(reference, floating, { placement: 'top' });\n * floating.style.left = `${result.x}px`;\n * floating.style.top = `${result.y}px`;\n * ```\n */\nexport function computePositionRaf(\n reference: ReferenceElement,\n floating: HTMLElement,\n options?: ComputePositionOptions,\n): Promise<ComputePositionResult> {\n return new Promise((resolve, reject) => {\n requestAnimationFrame(() => {\n try {\n resolve(computePosition(reference, floating, options));\n } catch (err) {\n reject(err);\n }\n });\n });\n}\n\n/**\n * Runs the middleware pipeline and returns the final position.\n *\n * Position is computed in viewport-relative coordinates assuming `position: fixed`.\n */\nexport function computePosition(\n reference: ReferenceElement,\n floating: HTMLElement,\n { boundary, containingBlock, middleware = [], padding, placement = 'bottom' }: ComputePositionOptions = {},\n): ComputePositionResult {\n const mws = middleware.filter(Boolean) as Middleware[];\n\n if (reference === floating) {\n warn('computePosition: reference and floating are the same element.');\n }\n\n const names = mws.map((mw) => {\n const tag = (mw as unknown as Record<symbol, unknown>)[MIDDLEWARE_NAME];\n\n return typeof tag === 'string' ? tag : null;\n });\n\n validateMiddlewareNames(names);\n\n let currentPlacement = placement;\n let middlewareData: MiddlewareData = {};\n let rects = getRects(reference, floating);\n\n devOnly(() => {\n if (rects.floating.width === 0 && rects.floating.height === 0) {\n warn('computePosition: floating element has zero dimensions — is it hidden or detached from the DOM?');\n }\n\n const pos = getComputedStyle(floating).position;\n\n if (pos !== 'fixed' && pos !== 'absolute') {\n warn(\n `computePosition: floating element has \\`position: ${pos}\\`. ` +\n 'Orbit computes viewport-relative coordinates and expects position: fixed ' +\n '(or absolute for scoped stacking contexts).',\n );\n }\n });\n\n for (let resets = 0; resets < MAX_RESETS; resets += 1) {\n let state: MiddlewareState = {\n ...baseCoords(currentPlacement, rects.reference, rects.floating),\n boundary,\n elements: { floating, reference },\n initialPlacement: placement,\n middlewareData,\n padding,\n placement: currentPlacement,\n rects,\n };\n\n let reset: MiddlewareReset | undefined;\n\n for (const mw of mws) {\n const result = mw(state);\n\n state = mergeState(state, result);\n middlewareData = state.middlewareData;\n reset = result?.reset;\n\n if (reset) break;\n }\n\n if (!reset) {\n const result: ComputePositionResult = {\n middlewareData: state.middlewareData,\n placement: state.placement,\n x: state.x,\n y: state.y,\n };\n\n if (containingBlock) {\n const cb = containingBlock.getBoundingClientRect();\n\n return { ...result, x: result.x - cb.x, y: result.y - cb.y };\n }\n\n return result;\n }\n\n if (reset.remeasure) {\n rects = getRects(reference, floating);\n } else if (reset.rects != null) {\n rects = reset.rects;\n }\n\n currentPlacement = reset.placement ?? state.placement;\n }\n\n throw new OrbitConfigError('Middleware triggered too many resets in a single compute cycle.');\n}\n","/**\n * @vielzeug/orbit — overflow-detection helpers.\n *\n * Imported by both `core.ts` (for `detectOverflow`) and middleware modules.\n * Middleware should import from here instead of reaching into core internals.\n */\n\nimport type { DetectOverflowOptions, MiddlewareState, Placement, Rect, SideObject } from './types';\n\nimport { baseCoords, getSide, toSideObject } from './utils';\n\n// ── Boundary ──────────────────────────────────────────────────────────────────\n\nfunction getViewportRect(): Rect {\n const vv = window.visualViewport;\n\n if (vv) return { height: vv.height, width: vv.width, x: vv.offsetLeft, y: vv.offsetTop };\n\n return { height: window.innerHeight, width: window.innerWidth, x: 0, y: 0 };\n}\n\n/** Resolve a boundary option to a plain Rect. Defaults to the visual viewport. */\nexport function getBoundaryRect(boundary?: Element | Rect): Rect {\n if (!boundary) return getViewportRect();\n\n if (boundary instanceof Element) {\n const r = boundary.getBoundingClientRect();\n\n return { height: r.height, width: r.width, x: r.x, y: r.y };\n }\n\n return boundary as Rect;\n}\n\n/**\n * Resolves the effective boundary and padding for a middleware, falling back from\n * per-middleware `options` to the global `state.boundary` / `state.padding` defaults.\n * @internal\n */\nexport function resolveBoundary(\n options: DetectOverflowOptions,\n state: Pick<MiddlewareState, 'boundary' | 'padding'>,\n): { boundary: Rect; padding: SideObject } {\n return {\n boundary: getBoundaryRect(options.boundary ?? state.boundary),\n padding: toSideObject(options.padding ?? state.padding),\n };\n}\n\n// ── Floating rect at current position ────────────────────────────────────────\n\n/** The floating element's rect using the current computed x/y from state. */\nexport function getFloatingRect(state: MiddlewareState): Rect {\n return { ...state.rects.floating, x: state.x, y: state.y };\n}\n\n// ── Per-side overflow ─────────────────────────────────────────────────────────\n\n/** How many pixels each side of `rect` overflows `boundary` (adjusted by `padding`). Negative = no overflow. */\nexport function detectOverflowAtRect(rect: Rect, boundary: Rect, padding: SideObject): SideObject {\n return {\n bottom: rect.y + rect.height - (boundary.y + boundary.height - padding.bottom),\n left: boundary.x + padding.left - rect.x,\n right: rect.x + rect.width - (boundary.x + boundary.width - padding.right),\n top: boundary.y + padding.top - rect.y,\n };\n}\n\n/** Sum of positive overflows on all sides. */\nexport function totalOverflow(overflow: SideObject): number {\n return (\n Math.max(overflow.top, 0) + Math.max(overflow.right, 0) + Math.max(overflow.bottom, 0) + Math.max(overflow.left, 0)\n );\n}\n\n/** True if any side has positive overflow. */\nexport function hasOverflow(overflow: SideObject): boolean {\n return overflow.top > 0 || overflow.right > 0 || overflow.bottom > 0 || overflow.left > 0;\n}\n\n/**\n * True if the rect is fully clipped (hidden) by the overflow on any axis.\n * Used by `hide` middleware.\n */\nexport function isFullyClipped(rect: Rect, overflow: SideObject): boolean {\n return (\n overflow.top >= rect.height ||\n overflow.right >= rect.width ||\n overflow.bottom >= rect.height ||\n overflow.left >= rect.width\n );\n}\n\n// ── Placement-specific helpers ────────────────────────────────────────────────\n\n/** Available space in pixels between the reference and the boundary on the given placement's side. */\nexport function getAvailableSpace(\n state: MiddlewareState,\n placement: Placement,\n boundary: Rect,\n padding: SideObject,\n): number {\n const ref = state.rects.reference;\n const side = getSide(placement);\n\n switch (side) {\n case 'bottom':\n return boundary.y + boundary.height - padding.bottom - (ref.y + ref.height);\n case 'left':\n return ref.x - (boundary.x + padding.left);\n case 'right':\n return boundary.x + boundary.width - padding.right - (ref.x + ref.width);\n case 'top':\n return ref.y - (boundary.y + padding.top);\n }\n}\n\n/**\n * Overflow of the floating element if it were positioned at `placement`\n * using base (un-shifted) coordinates, before any middleware adjustments.\n */\nexport function getPlacementOverflow(\n state: MiddlewareState,\n placement: Placement,\n options: DetectOverflowOptions = {},\n): SideObject {\n const { x, y } = baseCoords(placement, state.rects.reference, state.rects.floating);\n const { boundary, padding } = resolveBoundary(options, state);\n const rect = { ...state.rects.floating, x, y };\n\n return detectOverflowAtRect(rect, boundary, padding);\n}\n\n/** Overflow of the floating element at its current position in the middleware pipeline. */\nexport function detectOverflow(state: MiddlewareState, options: DetectOverflowOptions = {}): SideObject {\n const { boundary, padding } = resolveBoundary(options, state);\n\n return detectOverflowAtRect(getFloatingRect(state), boundary, padding);\n}\n","import { throttle } from '@vielzeug/arsenal';\n\nimport type { ReferenceElement } from './types';\n\nimport { isElement } from './utils';\n\nexport interface AutoUpdateOptions {\n /** Watch the floating element for size changes. Default: `true`. */\n observeFloating?: boolean;\n /**\n * Listen to scroll events on ancestor scroll containers of the reference element\n * in addition to the window. More efficient in deeply nested DOMs.\n * Set to `false` to use only a capture-phase window listener.\n * Default: `true`.\n */\n observeAncestors?: boolean;\n /** Track visual viewport scroll and resize (useful for pinch-zoom). Default: `true`. */\n observeVisualViewport?: boolean;\n /** Re-position on every animation frame. Use only when the reference itself animates. Default: `false`. */\n animationFrame?: boolean;\n /**\n * Throttle update calls to at most once every `throttle` milliseconds.\n * Uses a leading + trailing strategy: fires immediately, then once more after the interval.\n * Default: `0` (no throttling).\n */\n throttle?: number;\n /**\n * Pause position updates while the reference element is scrolled out of the viewport.\n * Uses IntersectionObserver to detect visibility. When the reference becomes visible again,\n * one position update is fired immediately.\n * Default: `true`.\n */\n pauseWhenHidden?: boolean;\n}\n\n/**\n * Collects the ancestor scroll containers of an element (up to and including the\n * nearest scrollable ancestor). Used to scope scroll listeners to the minimal\n * set of elements rather than relying on a capture-phase window listener.\n */\nfunction getScrollAncestors(el: Element): Element[] {\n const ancestors: Element[] = [];\n let current: Element | null = el.parentElement;\n\n while (current) {\n const style = getComputedStyle(current);\n const overflow = style.overflow + style.overflowX + style.overflowY;\n\n if (/auto|scroll|overlay/.test(overflow)) {\n ancestors.push(current);\n }\n\n if (current.parentElement) {\n current = current.parentElement;\n } else {\n const root = current.getRootNode();\n\n current = root instanceof ShadowRoot ? root.host : null;\n }\n }\n\n return ancestors;\n}\n\n/**\n * Calls `update` immediately and re-calls it whenever the reference or floating element\n * could have changed position: scroll, resize, ResizeObserver, or animation frames.\n *\n * By default, scroll listeners are attached to both ancestor scroll containers of the reference\n * AND the window (for document scroll). The ancestor listeners fire for nested container scrolls;\n * the window listener fires for page-level scroll. Set `observeAncestors: false` to use only a\n * capture-phase window listener.\n *\n * Returns a cleanup function that removes all listeners.\n *\n * @example\n * ```ts\n * const cleanup = autoUpdate(reference, floating, () => {\n * const { x, y } = computePosition(reference, floating, options);\n * floating.style.left = `${x}px`;\n * floating.style.top = `${y}px`;\n * });\n * // later:\n * cleanup();\n * ```\n */\nexport function autoUpdate(\n reference: ReferenceElement,\n floating: HTMLElement,\n update: () => void,\n {\n animationFrame = false,\n observeAncestors = true,\n observeFloating = true,\n observeVisualViewport = true,\n pauseWhenHidden = true,\n throttle: throttleMs = 0,\n }: AutoUpdateOptions = {},\n): () => void {\n const throttled = throttleMs > 0 ? throttle(update, throttleMs, { leading: true, trailing: true }) : null;\n const notify = throttled ?? update;\n\n // ── Visibility guard ─────────────────────────────────────────────────────────\n let referenceVisible = true;\n const conditionalNotify = (): void => {\n if (referenceVisible) notify();\n };\n\n // Initial call always runs regardless of visibility state.\n notify();\n\n const cleanups: Array<() => void> = [];\n\n // IntersectionObserver: pause updates when reference is off-screen.\n if (pauseWhenHidden && isElement(reference) && typeof IntersectionObserver !== 'undefined') {\n const io = new IntersectionObserver((entries) => {\n referenceVisible = entries.at(-1)?.isIntersecting ?? true;\n\n if (referenceVisible) notify(); // Re-position immediately when becoming visible.\n });\n\n io.observe(reference);\n cleanups.push(() => io.disconnect());\n }\n\n // ── Scroll listeners ────────────────────────────────────────────────────────\n if (isElement(reference) && observeAncestors) {\n // Targeted ancestor listeners for nested container scroll.\n const ancestors = getScrollAncestors(reference);\n\n for (const ancestor of ancestors) {\n ancestor.addEventListener('scroll', conditionalNotify, { passive: true });\n cleanups.push(() => ancestor.removeEventListener('scroll', conditionalNotify));\n }\n\n // Always add window scroll for document-level scroll (non-capture, doesn't fire for nested containers).\n window.addEventListener('scroll', conditionalNotify, { passive: true });\n cleanups.push(() => window.removeEventListener('scroll', conditionalNotify));\n } else {\n // VirtualReference or observeAncestors: false — capture-phase window listener catches all scrolls.\n const scrollHandler = (e: Event): void => {\n if (e.composedPath().includes(floating)) return;\n\n conditionalNotify();\n };\n\n window.addEventListener('scroll', scrollHandler, { capture: true, passive: true });\n cleanups.push(() => window.removeEventListener('scroll', scrollHandler, { capture: true }));\n }\n\n window.addEventListener('resize', conditionalNotify, { passive: true });\n cleanups.push(() => window.removeEventListener('resize', conditionalNotify));\n\n const vv = observeVisualViewport ? window.visualViewport : null;\n\n if (vv) {\n vv.addEventListener('resize', conditionalNotify, { passive: true });\n vv.addEventListener('scroll', conditionalNotify, { passive: true });\n cleanups.push(() => {\n vv.removeEventListener('resize', conditionalNotify);\n vv.removeEventListener('scroll', conditionalNotify);\n });\n }\n\n const ro = new ResizeObserver(conditionalNotify);\n\n if (isElement(reference)) ro.observe(reference);\n\n if (observeFloating) ro.observe(floating);\n\n cleanups.push(() => ro.disconnect());\n\n let frameId = 0;\n\n if (animationFrame) {\n const frameLoop = (): void => {\n conditionalNotify();\n frameId = window.requestAnimationFrame(frameLoop);\n };\n\n frameId = window.requestAnimationFrame(frameLoop);\n cleanups.push(() => window.cancelAnimationFrame(frameId));\n }\n\n return (): void => {\n throttled?.cancel();\n\n for (const fn of cleanups) fn();\n };\n}\n","import type { ComputePositionOptions, ComputePositionResult, FloatHandle, Placement, ReferenceElement } from './types';\n\nimport { autoUpdate, type AutoUpdateOptions } from './auto-update';\nimport { computePosition } from './core';\n\n// ── makeHandle ────────────────────────────────────────────────────────────────\n\n/**\n * Constructs a {@link FloatHandle} with idempotent dispose, disposalSignal, and disposed getter.\n * @internal — exported for use by ssr.ts and devtools.ts only.\n */\nexport function makeHandle(\n rawDispose: () => void,\n getPosition: () => ComputePositionResult | null,\n update: () => void,\n): FloatHandle {\n const controller = new AbortController();\n let disposed = false;\n\n return {\n get disposalSignal() {\n return controller.signal;\n },\n dispose() {\n if (disposed) return;\n\n disposed = true;\n controller.abort();\n rawDispose();\n },\n get disposed() {\n return disposed;\n },\n getPosition,\n [Symbol.dispose](): void {\n this.dispose();\n },\n update,\n };\n}\n\n// ── CSS Anchor Positioning ────────────────────────────────────────────────────\n\nfunction isCssAnchorPositioningSupported(): boolean {\n return typeof CSS !== 'undefined' && CSS.supports('anchor-name', '--orbit');\n}\n\nlet anchorCounter = 0;\n\n/**\n * Maps a placement to the CSS `position-area` value.\n * https://drafts.csswg.org/css-anchor-position/#position-area\n */\nconst POSITION_AREA: Record<Placement, string> = {\n bottom: 'block-end center',\n 'bottom-end': 'block-end span-inline-end',\n 'bottom-start': 'block-end span-inline-start',\n left: 'inline-start center',\n 'left-end': 'inline-start span-block-end',\n 'left-start': 'inline-start span-block-start',\n right: 'inline-end center',\n 'right-end': 'inline-end span-block-end',\n 'right-start': 'inline-end span-block-start',\n top: 'block-start center',\n 'top-end': 'block-start span-inline-end',\n 'top-start': 'block-start span-inline-start',\n};\n\n/** Applies a set of CSS properties to an element and returns a cleanup that restores them. */\nfunction withStyles(el: HTMLElement, props: Record<string, string>): () => void {\n const saved: Record<string, string | undefined> = {};\n\n for (const prop of Object.keys(props)) {\n const prev = el.style.getPropertyValue(prop);\n\n saved[prop] = prev !== '' ? prev : undefined;\n el.style.setProperty(prop, props[prop]);\n }\n\n return () => {\n for (const prop of Object.keys(props)) {\n const prev = saved[prop];\n\n if (prev !== undefined) {\n el.style.setProperty(prop, prev);\n } else {\n el.style.removeProperty(prop);\n }\n }\n };\n}\n\nfunction setupCssAnchorPositioning(\n reference: HTMLElement,\n floating: HTMLElement,\n placement: Placement,\n fallbacks: string,\n): () => void {\n const name = `--orbit-${++anchorCounter}`;\n\n const cleanupRef = withStyles(reference, { 'anchor-name': name });\n const cleanupFloat = withStyles(floating, {\n position: 'fixed',\n 'position-anchor': name,\n 'position-area': POSITION_AREA[placement],\n 'position-try-fallbacks': fallbacks,\n });\n\n return () => {\n cleanupRef();\n cleanupFloat();\n };\n}\n\nexport interface CssAnchorHandle extends FloatHandle {\n /** Always `true` — position is managed natively by CSS Anchor Positioning. */\n readonly cssAnchor: true;\n}\n\n/**\n * Uses CSS Anchor Positioning to let the browser handle repositioning natively.\n * No JavaScript positioning loop — the browser manages placement via `position-try-fallbacks`.\n *\n * Requires both elements to be `HTMLElement`. Falls back to `float()` for complex cases\n * (e.g. middleware pipelines, custom apply callbacks).\n *\n * @experimental CSS Anchor Positioning support varies by browser. Check `isCssAnchorSupported()`\n * before using in production.\n *\n * @example\n * ```ts\n * import { floatWithAnchor } from '@vielzeug/orbit';\n *\n * const handle = floatWithAnchor(trigger, tooltip, { placement: 'top' });\n * // on hide:\n * handle.dispose();\n * ```\n */\nexport function floatWithAnchor(\n reference: HTMLElement,\n floating: HTMLElement,\n {\n fallbacks = 'flip-block, flip-inline, flip-block flip-inline',\n placement = 'bottom',\n }: { fallbacks?: string; placement?: Placement } = {},\n): CssAnchorHandle {\n const cleanupFn = setupCssAnchorPositioning(reference, floating, placement, fallbacks);\n const base = makeHandle(\n () => cleanupFn(),\n () => null,\n () => {},\n );\n\n return Object.assign(base, { cssAnchor: true as const });\n}\n\n/**\n * Returns `true` when the browser supports CSS Anchor Positioning.\n * Use to guard `floatWithAnchor()` calls in production.\n */\nexport { isCssAnchorPositioningSupported as isCssAnchorSupported };\n\n// ── float() ───────────────────────────────────────────────────────────────────\n\n/**\n * Options for `float()`. Extends `ComputePositionOptions` so all positioning\n * options (`placement`, `middleware`, `boundary`, `padding`, `containingBlock`)\n * are inherited directly.\n */\nexport interface FloatOptions extends ComputePositionOptions {\n /**\n * Custom callback to apply the computed position to the DOM.\n * Called once per position update with the full `ComputePositionResult`.\n * Defaults to writing `left` / `top` on the floating element (requires `position: fixed`).\n */\n apply?: (result: ComputePositionResult) => void;\n /**\n * Options for the auto-update loop. Omit to use defaults.\n * Pass `false` to disable auto-updating (position is computed once on call).\n */\n autoUpdate?: AutoUpdateOptions | false;\n}\n\nfunction applyDefault(result: ComputePositionResult, floating: HTMLElement): void {\n floating.style.left = `${result.x}px`;\n floating.style.top = `${result.y}px`;\n}\n\n/**\n * High-level API: positions the floating element and continuously keeps it updated.\n *\n * For CSS Anchor Positioning (browser-native, no JS loop), use {@link floatWithAnchor} instead.\n *\n * Returns a {@link FloatHandle} with `dispose()`, `update()`, and `getPosition()`.\n * Always call `dispose()` on teardown to remove listeners.\n *\n * @example\n * ```ts\n * const handle = float(trigger, tooltip, {\n * placement: 'top',\n * middleware: [offset(8), flip(), shift({ padding: 6 })],\n * });\n * // on hide:\n * handle.dispose();\n * ```\n */\nexport function float(\n reference: ReferenceElement,\n floating: HTMLElement,\n {\n apply,\n autoUpdate: autoUpdateOptions = {},\n boundary,\n containingBlock,\n middleware,\n padding,\n placement = 'bottom',\n }: FloatOptions = {},\n): FloatHandle {\n let lastPosition: ComputePositionResult | null = null;\n const applyFn = apply ?? ((result) => applyDefault(result, floating));\n\n function update(): void {\n const result = computePosition(reference, floating, { boundary, containingBlock, middleware, padding, placement });\n\n lastPosition = result;\n applyFn(result);\n }\n\n if (autoUpdateOptions === false) {\n update();\n\n return makeHandle(\n () => {},\n () => lastPosition,\n update,\n );\n }\n\n const cleanupFn = autoUpdate(reference, floating, update, autoUpdateOptions);\n\n return makeHandle(\n () => cleanupFn(),\n () => lastPosition,\n update,\n );\n}\n","import type { Middleware } from './types';\n\ntype Falsy = false | null | undefined;\n\n/**\n * Filters out falsy middleware entries (`null`, `undefined`, `false`) and returns a clean array.\n *\n * Middleware ordering validation runs automatically inside `computePosition()` in development —\n * you do not need `compose()` to get ordering warnings. Use it purely for its falsy-filter\n * ergonomics when conditionally including middleware.\n *\n * @example\n * ```ts\n * import { compose, offset, flip, shift, arrow } from '@vielzeug/orbit';\n *\n * const middleware = compose(\n * offset(8),\n * flip(),\n * shift({ padding: 6 }),\n * hasArrow && arrow({ element: arrowEl }),\n * );\n * float(trigger, tooltip, { middleware });\n * ```\n */\nexport function compose(...middleware: Array<Middleware | Falsy>): Middleware[] {\n return middleware.filter(Boolean) as Middleware[];\n}\n","import type { ArrowData, Middleware, Padding, TypedMiddleware } from '../types';\n\nimport { clamp, getSide, tagMiddleware, toRect, toSideObject } from '../utils';\n\nexport interface ArrowOptions {\n /** The arrow DOM element. Must be a child of the floating element. */\n element: HTMLElement;\n /** Padding to keep the arrow from the floating element's corners. */\n padding?: Padding;\n}\n\n/**\n * Positions an arrow element inside the floating element, pointed toward the reference.\n * Writes `{ x?, y?, centerOffset }` to `middlewareData.arrow`.\n *\n * Must come **after** flip(), shift(), and autoPlacement() in the middleware pipeline.\n *\n * @example\n * ```ts\n * const result = computePosition(ref, floating, {\n * middleware: [offset(8), flip(), shift(), arrow({ element: arrowEl })],\n * });\n * const { x, y } = result.middlewareData.arrow!;\n * arrowEl.style.left = x != null ? `${x}px` : '';\n * arrowEl.style.top = y != null ? `${y}px` : '';\n * ```\n */\nexport function arrow({ element, padding = 0 }: ArrowOptions): TypedMiddleware<'arrow', ArrowData> {\n function arrowMiddleware(state: Parameters<Middleware>[0]): ReturnType<Middleware> {\n const side = getSide(state.placement);\n const inset = toSideObject(padding);\n const arrowRect = toRect(element.getBoundingClientRect());\n\n if (side === 'top' || side === 'bottom') {\n const idealX = state.rects.reference.x + state.rects.reference.width / 2 - state.x - arrowRect.width / 2;\n const minX = inset.left;\n const maxX = Math.max(minX, state.rects.floating.width - arrowRect.width - inset.right);\n const x = clamp(idealX, minX, maxX);\n\n return { data: { arrow: { centerOffset: idealX - x, constrained: x !== idealX, x } } };\n }\n\n const idealY = state.rects.reference.y + state.rects.reference.height / 2 - state.y - arrowRect.height / 2;\n const minY = inset.top;\n const maxY = Math.max(minY, state.rects.floating.height - arrowRect.height - inset.bottom);\n const y = clamp(idealY, minY, maxY);\n\n return { data: { arrow: { centerOffset: idealY - y, constrained: y !== idealY, y } } };\n }\n\n return tagMiddleware<'arrow', ArrowData, typeof arrowMiddleware>(arrowMiddleware, 'arrow');\n}\n","import type { Alignment, DetectOverflowOptions, Middleware, Placement, Side } from '../types';\n\nimport { warn } from '../_dev';\nimport { getAvailableSpace, getPlacementOverflow, resolveBoundary, totalOverflow } from '../overflow';\nimport { tagMiddleware } from '../utils';\n\nexport interface AutoPlacementOptions extends DetectOverflowOptions {\n /**\n * Placements to evaluate. When provided, takes precedence over `alignment`.\n * Note: use either `flip` or `autoPlacement`, not both.\n */\n allowedPlacements?: Placement[];\n /**\n * Constrains auto-placement to variants with the given alignment.\n *\n * - `'start'` — evaluates only `top-start`, `right-start`, `bottom-start`, `left-start`.\n * - `'end'` — evaluates only `top-end`, `right-end`, `bottom-end`, `left-end`.\n * - `null` — evaluates all 12 variants (4 cardinal + 4 start + 4 end).\n * - omitted (default) — evaluates the 4 cardinal sides only.\n */\n alignment?: Alignment | null;\n}\n\nconst SIDES: Side[] = ['top', 'right', 'bottom', 'left'];\n\nfunction getDefaultPlacements(alignment?: Alignment | null): Placement[] {\n if (alignment === undefined) return SIDES;\n\n if (alignment === null) {\n return SIDES.flatMap((side) => [side, `${side}-start`, `${side}-end`] as Placement[]);\n }\n\n return SIDES.map((side) => `${side}-${alignment}` as Placement);\n}\n\n/**\n * Automatically selects the placement with the most available space and least overflow.\n * Evaluates all allowed placements and picks the optimal one.\n *\n * Use the `alignment` option to restrict evaluation to aligned variants (e.g. `'start'`)\n * when you want to preserve a consistent alignment across all candidate sides.\n *\n * @see {@link flip} for simple opposite-side flipping.\n */\nexport function autoPlacement(options: AutoPlacementOptions = {}): Middleware {\n return tagMiddleware(function autoPlacementMiddleware(state: Parameters<Middleware>[0]): ReturnType<Middleware> {\n const { boundary, padding } = resolveBoundary(options, state);\n const placements = options.allowedPlacements ?? getDefaultPlacements(options.alignment);\n\n if (placements.length === 0) {\n warn('autoPlacement: allowedPlacements is empty — no placement will be evaluated.');\n }\n\n let bestPlacement = state.placement;\n let bestOverflow = Number.POSITIVE_INFINITY;\n let bestSpace = Number.NEGATIVE_INFINITY;\n\n for (const candidate of placements) {\n const overflow = getPlacementOverflow(state, candidate, options);\n const overflowScore = totalOverflow(overflow);\n const availableSpace = getAvailableSpace(state, candidate, boundary, padding);\n\n if (overflowScore < bestOverflow || (overflowScore === bestOverflow && availableSpace > bestSpace)) {\n bestPlacement = candidate;\n bestOverflow = overflowScore;\n bestSpace = availableSpace;\n }\n }\n\n if (bestPlacement !== state.placement) {\n return { reset: { placement: bestPlacement } };\n }\n }, 'autoPlacement');\n}\n","import type { DetectOverflowOptions, FlipData, Middleware, Placement, TypedMiddleware } from '../types';\n\nimport { detectOverflow, getPlacementOverflow, hasOverflow, totalOverflow } from '../overflow';\nimport { getAlignment, getSide, OPPOSITE, tagMiddleware, withPlacement } from '../utils';\n\nexport interface FlipOptions extends DetectOverflowOptions {\n /**\n * Ordered list of candidate placements to try when the floating element overflows.\n * Defaults to the opposite side, preserving the current alignment.\n */\n fallbackPlacements?: Placement[];\n}\n\n/**\n * Flips the floating element to the opposite side when it overflows the boundary.\n * Falls back to the candidate with the least total overflow when no candidate fits.\n */\nexport function flip(options: FlipOptions = {}): TypedMiddleware<'flip', FlipData> {\n function flipMiddleware(state: Parameters<Middleware>[0]): ReturnType<Middleware> {\n const currentOverflow = detectOverflow(state, options);\n\n if (!hasOverflow(currentOverflow)) return;\n\n const side = getSide(state.placement);\n const align = getAlignment(state.placement);\n const fallbackPlacements = options.fallbackPlacements ?? [withPlacement(OPPOSITE[side], align)];\n const skipped: Placement[] = [state.placement];\n let bestPlacement = state.placement;\n let bestScore = totalOverflow(currentOverflow);\n\n for (const candidate of fallbackPlacements) {\n const candidateOverflow = getPlacementOverflow(state, candidate, options);\n const score = totalOverflow(candidateOverflow);\n\n if (!hasOverflow(candidateOverflow)) {\n return {\n data: { flip: { skippedPlacements: skipped } },\n reset: { placement: candidate },\n };\n }\n\n skipped.push(candidate);\n\n if (score < bestScore) {\n bestPlacement = candidate;\n bestScore = score;\n }\n }\n\n if (bestPlacement !== state.placement) {\n return {\n data: { flip: { skippedPlacements: skipped } },\n reset: { placement: bestPlacement },\n };\n }\n }\n\n return tagMiddleware<'flip', FlipData, typeof flipMiddleware>(flipMiddleware, 'flip');\n}\n","import type { DetectOverflowOptions, HideData, Middleware, TypedMiddleware } from '../types';\n\nimport { detectOverflowAtRect, getFloatingRect, isFullyClipped, resolveBoundary } from '../overflow';\nimport { tagMiddleware } from '../utils';\n\nexport interface HideOptions extends DetectOverflowOptions {\n /**\n * Which hidden states to compute.\n * - `'referenceHidden'` — whether the reference itself is off-screen.\n * - `'escaped'` — whether the floating element has fully exited the boundary.\n * - `'both'` (default) — both of the above.\n */\n strategy?: 'referenceHidden' | 'escaped' | 'both';\n}\n\n/**\n * Detects when the reference or floating element is hidden outside the boundary.\n * Writes `{ referenceHidden, referenceHiddenOffsets, escaped, escapedOffsets }` to\n * `middlewareData.hide`.\n */\nexport function hide(options: HideOptions = {}): TypedMiddleware<'hide', HideData> {\n const strategy = options.strategy ?? 'both';\n\n function hideMiddleware(state: Parameters<Middleware>[0]): ReturnType<Middleware> {\n const { boundary, padding } = resolveBoundary(options, state);\n const next: HideData = {};\n\n if (strategy === 'escaped' || strategy === 'both') {\n const floatingRect = getFloatingRect(state);\n const escapedOffsets = detectOverflowAtRect(floatingRect, boundary, padding);\n\n next.escaped = isFullyClipped(floatingRect, escapedOffsets);\n next.escapedOffsets = escapedOffsets;\n }\n\n if (strategy === 'referenceHidden' || strategy === 'both') {\n const referenceHiddenOffsets = detectOverflowAtRect(state.rects.reference, boundary, padding);\n\n next.referenceHidden = isFullyClipped(state.rects.reference, referenceHiddenOffsets);\n next.referenceHiddenOffsets = referenceHiddenOffsets;\n }\n\n return { data: { hide: next } };\n }\n\n return tagMiddleware<'hide', HideData, typeof hideMiddleware>(hideMiddleware, 'hide');\n}\n","import type { Middleware, Padding, Rect, ReferenceElement } from './types';\n\nimport { getSide, tagMiddleware, toRect, toSideObject } from './utils';\n\n// ── Private helpers (only used by inline) ────────────────────────────────────────────\n\nfunction getClientRects(reference: ReferenceElement): Rect[] {\n if (!('getClientRects' in reference) || typeof reference.getClientRects !== 'function') return [];\n\n return Array.from((reference.getClientRects as () => DOMRectList | DOMRect[])())\n .map(toRect)\n .filter((r) => r.width > 0 || r.height > 0);\n}\n\nfunction rectContainsPoint(rect: Rect, x: number, y: number, padding: ReturnType<typeof toSideObject>): boolean {\n return (\n x >= rect.x - padding.left &&\n x <= rect.x + rect.width + padding.right &&\n y >= rect.y - padding.top &&\n y <= rect.y + rect.height + padding.bottom\n );\n}\n\nfunction sameRect(a: Rect, b: Rect): boolean {\n return a.x === b.x && a.y === b.y && a.width === b.width && a.height === b.height;\n}\n\n// ── Inline middleware ─────────────────────────────────────────────────────────────────\n\nexport interface InlineOptions {\n /**\n * Cursor x-coordinate. When provided alongside `y`, the middleware picks the\n * client rect that contains the cursor instead of the closest rect to the floating element.\n */\n x?: number;\n /** Cursor y-coordinate. */\n y?: number;\n /**\n * Padding used when hit-testing cursor coordinates against client rects.\n * Prevents snapping when the cursor is just outside a rect edge. Default: `2`.\n *\n * @remarks Only applies when both `x` and `y` are provided.\n */\n padding?: Padding;\n}\n\n/**\n * Improves positioning accuracy for inline references that span multiple lines\n * (e.g. `<span>` wrapping across line breaks).\n *\n * Must be placed **before** `flip()` and other middleware in the pipeline.\n *\n * @example Tooltip on selected text:\n * ```ts\n * import { inline, float, flip, shift } from '@vielzeug/orbit';\n *\n * float(selectionRef, tooltip, {\n * placement: 'top',\n * middleware: [inline({ x: cursorX, y: cursorY }), flip(), shift({ padding: 6 })],\n * });\n * ```\n */\nexport function inline(options: InlineOptions = {}): Middleware {\n function inlineMiddleware(state: Parameters<Middleware>[0]): ReturnType<Middleware> {\n const rects = getClientRects(state.elements.reference);\n\n if (rects.length <= 1) return;\n\n const padding = toSideObject(options.padding ?? 2);\n const side = getSide(state.placement);\n let nextRect = rects[0]!;\n\n if (options.x != null && options.y != null) {\n nextRect = rects.find((rect) => rectContainsPoint(rect, options.x!, options.y!, padding)) ?? nextRect;\n } else if (side === 'top' || side === 'bottom') {\n const targetX = state.x + state.rects.floating.width / 2;\n\n nextRect = rects.reduce((best, rect) => {\n const bestDist = Math.abs(best.x + best.width / 2 - targetX);\n const rectDist = Math.abs(rect.x + rect.width / 2 - targetX);\n\n return rectDist < bestDist ? rect : best;\n }, nextRect);\n } else {\n const targetY = state.y + state.rects.floating.height / 2;\n\n nextRect = rects.reduce((best, rect) => {\n const bestDist = Math.abs(best.y + best.height / 2 - targetY);\n const rectDist = Math.abs(rect.y + rect.height / 2 - targetY);\n\n return rectDist < bestDist ? rect : best;\n }, nextRect);\n }\n\n if (sameRect(nextRect, state.rects.reference)) return;\n\n return { reset: { rects: { ...state.rects, reference: nextRect } } };\n }\n\n return tagMiddleware(inlineMiddleware, 'inline');\n}\n","import type { Middleware, MiddlewareState } from '../types';\n\nimport { getSide, tagMiddleware } from '../utils';\n\nexport type OffsetConfig = {\n /** Offset perpendicular to the main axis. */\n crossAxis?: number;\n /** Offset along the axis away from the reference. */\n mainAxis?: number;\n};\n\nexport type OffsetValue = number | OffsetConfig | ((state: MiddlewareState) => number | OffsetConfig);\n\nfunction resolveOffsetConfig(value: OffsetValue, state: MiddlewareState): Required<OffsetConfig> {\n const raw = typeof value === 'function' ? value(state) : value;\n\n if (typeof raw === 'number') return { crossAxis: 0, mainAxis: raw };\n\n return { crossAxis: raw.crossAxis ?? 0, mainAxis: raw.mainAxis ?? 0 };\n}\n\n/**\n * Shifts the floating element along the main axis (away from reference) and/or\n * the cross axis. Accepts a number, config object, or a function for dynamic values.\n *\n * Must be the **first** middleware in the pipeline.\n */\nexport function offset(value: OffsetValue): Middleware {\n return tagMiddleware(function offsetMiddleware(state: Parameters<Middleware>[0]): ReturnType<Middleware> {\n const side = getSide(state.placement);\n const { crossAxis, mainAxis } = resolveOffsetConfig(value, state);\n\n switch (side) {\n case 'bottom':\n return { x: state.x + crossAxis, y: state.y + mainAxis };\n case 'left':\n return { x: state.x - mainAxis, y: state.y + crossAxis };\n case 'right':\n return { x: state.x + mainAxis, y: state.y + crossAxis };\n case 'top':\n return { x: state.x + crossAxis, y: state.y - mainAxis };\n }\n }, 'offset');\n}\n","import type { DetectOverflowOptions, Middleware, MiddlewareState, ShiftData, TypedMiddleware } from '../types';\n\nimport { detectOverflow } from '../overflow';\nimport { clamp, getSide, tagMiddleware } from '../utils';\n\n/**\n * A limiter function passed to `shift()` that constrains the maximum allowed drift.\n * Receives the current middleware state and the proposed shift correction (as deltas),\n * and returns the clamped correction.\n */\nexport type ShiftLimiter = (\n state: MiddlewareState,\n correction: { crossAxis: number; mainAxis: number },\n) => { crossAxis: number; mainAxis: number };\n\nexport interface LimitShiftOptions {\n /**\n * Extra pixels of allowed drift past the reference's cross-axis extent before clamping kicks in.\n * Can be a static number or a function returning a number based on current state.\n * Default: `0`.\n */\n offset?: number | ((state: MiddlewareState) => number);\n}\n\n/**\n * Returns a {@link ShiftLimiter} that constrains `shift()` so the floating element\n * stays visually connected to the reference along the cross axis.\n *\n * Without a limiter, `shift()` will push the float as far as needed to fit in the boundary —\n * potentially sliding it far away from the reference. `limitShift` clamps the drift so the\n * float stays within the reference's cross-axis extent (± `offset` pixels).\n *\n * @example\n * ```ts\n * // Tooltip stays above the button even when viewport clips it.\n * shift({ padding: 6, limiter: limitShift() })\n *\n * // Allow up to 10px of drift beyond the reference's edges.\n * shift({ padding: 6, limiter: limitShift({ offset: 10 }) })\n * ```\n */\nexport function limitShift(options: LimitShiftOptions = {}): ShiftLimiter {\n return (state, correction) => {\n const { placement, rects, x, y } = state;\n const side = getSide(placement);\n const isVertical = side === 'top' || side === 'bottom';\n const extra = typeof options.offset === 'function' ? options.offset(state) : (options.offset ?? 0);\n\n if (isVertical) {\n // Cross axis is x. Clamp float.left to [ref.left-extra, ref.right+extra-float.width].\n const lo = rects.reference.x - extra;\n const hi = rects.reference.x + rects.reference.width + extra - rects.floating.width;\n const [min, max] = lo <= hi ? [lo, hi] : [hi, lo];\n const clamped = clamp(x + correction.crossAxis, min, max);\n\n return { ...correction, crossAxis: clamped - x };\n }\n\n // Cross axis is y. Clamp float.top to [ref.top-extra, ref.bottom+extra-float.height].\n const lo = rects.reference.y - extra;\n const hi = rects.reference.y + rects.reference.height + extra - rects.floating.height;\n const [min, max] = lo <= hi ? [lo, hi] : [hi, lo];\n const clamped = clamp(y + correction.crossAxis, min, max);\n\n return { ...correction, crossAxis: clamped - y };\n };\n}\n\nexport interface ShiftOptions extends DetectOverflowOptions {\n /**\n * Whether to shift along the main axis (the axis away from the reference).\n * Default: `false` — main-axis overflow is better handled by `flip`.\n */\n mainAxis?: boolean;\n /**\n * Whether to shift along the cross axis (perpendicular to the reference direction).\n * Default: `true`.\n */\n crossAxis?: boolean;\n /**\n * Constrains how far `shift()` can move the floating element along the cross axis.\n * Pass `limitShift()` to keep the float within the reference's extent.\n */\n limiter?: ShiftLimiter;\n}\n\n/**\n * Shifts the floating element along the cross axis to keep it inside the boundary.\n *\n * By default only the cross axis is corrected. Enable `mainAxis` to also shift\n * along the main axis (useful when `flip` is not in the pipeline).\n *\n * | Placement | Cross axis | Main axis |\n * |------------------|------------|-----------|\n * | `top` / `bottom` | horizontal | vertical |\n * | `left` / `right` | vertical | horizontal|\n */\nexport function shift(options: ShiftOptions = {}): TypedMiddleware<'shift', ShiftData> {\n const { crossAxis = true, limiter, mainAxis = false } = options;\n\n function shiftMiddleware(state: Parameters<Middleware>[0]): ReturnType<Middleware> {\n const overflow = detectOverflow(state, options);\n const side = getSide(state.placement);\n const isVertical = side === 'top' || side === 'bottom';\n\n const xCorrection = Math.max(overflow.left, 0) - Math.max(overflow.right, 0);\n const yCorrection = Math.max(overflow.top, 0) - Math.max(overflow.bottom, 0);\n const applyX = isVertical ? crossAxis : mainAxis;\n const applyY = isVertical ? mainAxis : crossAxis;\n\n let dx = applyX ? xCorrection : 0;\n let dy = applyY ? yCorrection : 0;\n\n if (limiter) {\n const limited = limiter(state, {\n crossAxis: isVertical ? dx : dy,\n mainAxis: isVertical ? dy : dx,\n });\n\n dx = isVertical ? limited.crossAxis : limited.mainAxis;\n dy = isVertical ? limited.mainAxis : limited.crossAxis;\n }\n\n return { data: { shift: { x: dx, y: dy } }, x: state.x + dx, y: state.y + dy };\n }\n\n return tagMiddleware<'shift', ShiftData, typeof shiftMiddleware>(shiftMiddleware, 'shift');\n}\n","import type { DetectOverflowOptions, Middleware, SizeData, TypedMiddleware } from '../types';\n\nimport { resolveBoundary } from '../overflow';\nimport { getSide, tagMiddleware } from '../utils';\n\nexport type SizeOptions = DetectOverflowOptions;\n\n/**\n * Reports the available space between the reference and boundary edges.\n *\n * Available dimensions are written to `middlewareData.size`.\n *\n * Read `result.middlewareData.size` in the `float()` `apply` option or after `computePosition()`\n * to constrain the floating element's dimensions.\n *\n * @example\n * ```ts\n * const cleanup = float(ref, el, {\n * middleware: [offset(8), flip(), shift(), size()],\n * apply(result) {\n * el.style.maxHeight = `${result.middlewareData.size!.availableHeight}px`;\n * },\n * });\n * ```\n */\nexport function size(options: SizeOptions = {}): TypedMiddleware<'size', SizeData> {\n function sizeMiddleware(state: Parameters<Middleware>[0]): ReturnType<Middleware> {\n const { boundary, padding } = resolveBoundary(options, state);\n const side = getSide(state.placement);\n const top = boundary.y + padding.top;\n const right = boundary.x + boundary.width - padding.right;\n const bottom = boundary.y + boundary.height - padding.bottom;\n const left = boundary.x + padding.left;\n\n const availableHeight =\n side === 'bottom'\n ? Math.max(0, bottom - state.y)\n : side === 'top'\n ? Math.max(0, state.rects.reference.y - top)\n : Math.max(0, bottom - top);\n\n const availableWidth =\n side === 'right'\n ? Math.max(0, right - state.x)\n : side === 'left'\n ? Math.max(0, state.rects.reference.x - left)\n : Math.max(0, right - left);\n\n const sizeData: SizeData = { availableHeight, availableWidth };\n\n return { data: { size: sizeData } };\n }\n\n return tagMiddleware<'size', SizeData, typeof sizeMiddleware>(sizeMiddleware, 'size');\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
const e=require("./utils.cjs");function t(){let e=window.visualViewport;return e?{height:e.height,width:e.width,x:e.offsetLeft,y:e.offsetTop}:{height:window.innerHeight,width:window.innerWidth,x:0,y:0}}function n(e){if(!e)return t();if(e instanceof Element){let t=e.getBoundingClientRect();return{height:t.height,width:t.width,x:t.x,y:t.y}}return e}function r(t,r){return{boundary:n(t.boundary??r.boundary),padding:e.toSideObject(t.padding??r.padding)}}function i(e){return{...e.rects.floating,x:e.x,y:e.y}}function a(e,t,n){return{bottom:e.y+e.height-(t.y+t.height-n.bottom),left:t.x+n.left-e.x,right:e.x+e.width-(t.x+t.width-n.right),top:t.y+n.top-e.y}}function o(e){return Math.max(e.top,0)+Math.max(e.right,0)+Math.max(e.bottom,0)+Math.max(e.left,0)}function s(e){return e.top>0||e.right>0||e.bottom>0||e.left>0}function c(e,t){return t.top>=e.height||t.right>=e.width||t.bottom>=e.height||t.left>=e.width}function l(t,n,r,i){let a=t.rects.reference;switch(e.getSide(n)){case`bottom`:return r.y+r.height-i.bottom-(a.y+a.height);case`left`:return a.x-(r.x+i.left);case`right`:return r.x+r.width-i.right-(a.x+a.width);case`top`:return a.y-(r.y+i.top)}}function u(t,n,i={}){let{x:o,y:s}=e.baseCoords(n,t.rects.reference,t.rects.floating),{boundary:c,padding:l}=r(i,t);return a({...t.rects.floating,x:o,y:s},c,l)}function d(e,t={}){let{boundary:n,padding:o}=r(t,e);return a(i(e),n,o)}exports.detectOverflow=d,exports.detectOverflowAtRect=a,exports.getAvailableSpace=l,exports.getBoundaryRect=n,exports.getFloatingRect=i,exports.getPlacementOverflow=u,exports.hasOverflow=s,exports.isFullyClipped=c,exports.resolveBoundary=r,exports.totalOverflow=o;
|
|
2
|
+
//# sourceMappingURL=overflow.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"overflow.cjs","names":[],"sources":["../src/overflow.ts"],"sourcesContent":["/**\n * @vielzeug/orbit — overflow-detection helpers.\n *\n * Imported by both `core.ts` (for `detectOverflow`) and middleware modules.\n * Middleware should import from here instead of reaching into core internals.\n */\n\nimport type { DetectOverflowOptions, MiddlewareState, Placement, Rect, SideObject } from './types';\n\nimport { baseCoords, getSide, toSideObject } from './utils';\n\n// ── Boundary ──────────────────────────────────────────────────────────────────\n\nfunction getViewportRect(): Rect {\n const vv = window.visualViewport;\n\n if (vv) return { height: vv.height, width: vv.width, x: vv.offsetLeft, y: vv.offsetTop };\n\n return { height: window.innerHeight, width: window.innerWidth, x: 0, y: 0 };\n}\n\n/** Resolve a boundary option to a plain Rect. Defaults to the visual viewport. */\nexport function getBoundaryRect(boundary?: Element | Rect): Rect {\n if (!boundary) return getViewportRect();\n\n if (boundary instanceof Element) {\n const r = boundary.getBoundingClientRect();\n\n return { height: r.height, width: r.width, x: r.x, y: r.y };\n }\n\n return boundary as Rect;\n}\n\n/**\n * Resolves the effective boundary and padding for a middleware, falling back from\n * per-middleware `options` to the global `state.boundary` / `state.padding` defaults.\n * @internal\n */\nexport function resolveBoundary(\n options: DetectOverflowOptions,\n state: Pick<MiddlewareState, 'boundary' | 'padding'>,\n): { boundary: Rect; padding: SideObject } {\n return {\n boundary: getBoundaryRect(options.boundary ?? state.boundary),\n padding: toSideObject(options.padding ?? state.padding),\n };\n}\n\n// ── Floating rect at current position ────────────────────────────────────────\n\n/** The floating element's rect using the current computed x/y from state. */\nexport function getFloatingRect(state: MiddlewareState): Rect {\n return { ...state.rects.floating, x: state.x, y: state.y };\n}\n\n// ── Per-side overflow ─────────────────────────────────────────────────────────\n\n/** How many pixels each side of `rect` overflows `boundary` (adjusted by `padding`). Negative = no overflow. */\nexport function detectOverflowAtRect(rect: Rect, boundary: Rect, padding: SideObject): SideObject {\n return {\n bottom: rect.y + rect.height - (boundary.y + boundary.height - padding.bottom),\n left: boundary.x + padding.left - rect.x,\n right: rect.x + rect.width - (boundary.x + boundary.width - padding.right),\n top: boundary.y + padding.top - rect.y,\n };\n}\n\n/** Sum of positive overflows on all sides. */\nexport function totalOverflow(overflow: SideObject): number {\n return (\n Math.max(overflow.top, 0) + Math.max(overflow.right, 0) + Math.max(overflow.bottom, 0) + Math.max(overflow.left, 0)\n );\n}\n\n/** True if any side has positive overflow. */\nexport function hasOverflow(overflow: SideObject): boolean {\n return overflow.top > 0 || overflow.right > 0 || overflow.bottom > 0 || overflow.left > 0;\n}\n\n/**\n * True if the rect is fully clipped (hidden) by the overflow on any axis.\n * Used by `hide` middleware.\n */\nexport function isFullyClipped(rect: Rect, overflow: SideObject): boolean {\n return (\n overflow.top >= rect.height ||\n overflow.right >= rect.width ||\n overflow.bottom >= rect.height ||\n overflow.left >= rect.width\n );\n}\n\n// ── Placement-specific helpers ────────────────────────────────────────────────\n\n/** Available space in pixels between the reference and the boundary on the given placement's side. */\nexport function getAvailableSpace(\n state: MiddlewareState,\n placement: Placement,\n boundary: Rect,\n padding: SideObject,\n): number {\n const ref = state.rects.reference;\n const side = getSide(placement);\n\n switch (side) {\n case 'bottom':\n return boundary.y + boundary.height - padding.bottom - (ref.y + ref.height);\n case 'left':\n return ref.x - (boundary.x + padding.left);\n case 'right':\n return boundary.x + boundary.width - padding.right - (ref.x + ref.width);\n case 'top':\n return ref.y - (boundary.y + padding.top);\n }\n}\n\n/**\n * Overflow of the floating element if it were positioned at `placement`\n * using base (un-shifted) coordinates, before any middleware adjustments.\n */\nexport function getPlacementOverflow(\n state: MiddlewareState,\n placement: Placement,\n options: DetectOverflowOptions = {},\n): SideObject {\n const { x, y } = baseCoords(placement, state.rects.reference, state.rects.floating);\n const { boundary, padding } = resolveBoundary(options, state);\n const rect = { ...state.rects.floating, x, y };\n\n return detectOverflowAtRect(rect, boundary, padding);\n}\n\n/** Overflow of the floating element at its current position in the middleware pipeline. */\nexport function detectOverflow(state: MiddlewareState, options: DetectOverflowOptions = {}): SideObject {\n const { boundary, padding } = resolveBoundary(options, state);\n\n return detectOverflowAtRect(getFloatingRect(state), boundary, padding);\n}\n"],"mappings":"+BAaA,SAAS,GAAwB,CAC/B,IAAM,EAAK,OAAO,eAIlB,OAFI,EAAW,CAAE,OAAQ,EAAG,OAAQ,MAAO,EAAG,MAAO,EAAG,EAAG,WAAY,EAAG,EAAG,SAAU,EAEhF,CAAE,OAAQ,OAAO,YAAa,MAAO,OAAO,WAAY,EAAG,EAAG,EAAG,CAAE,CAC5E,CAGA,SAAgB,EAAgB,EAAiC,CAC/D,GAAI,CAAC,EAAU,OAAO,EAAgB,EAEtC,GAAI,aAAoB,QAAS,CAC/B,IAAM,EAAI,EAAS,sBAAsB,EAEzC,MAAO,CAAE,OAAQ,EAAE,OAAQ,MAAO,EAAE,MAAO,EAAG,EAAE,EAAG,EAAG,EAAE,CAAE,CAC5D,CAEA,OAAO,CACT,CAOA,SAAgB,EACd,EACA,EACyC,CACzC,MAAO,CACL,SAAU,EAAgB,EAAQ,UAAY,EAAM,QAAQ,EAC5D,QAAS,EAAA,aAAa,EAAQ,SAAW,EAAM,OAAO,CACxD,CACF,CAKA,SAAgB,EAAgB,EAA8B,CAC5D,MAAO,CAAE,GAAG,EAAM,MAAM,SAAU,EAAG,EAAM,EAAG,EAAG,EAAM,CAAE,CAC3D,CAKA,SAAgB,EAAqB,EAAY,EAAgB,EAAiC,CAChG,MAAO,CACL,OAAQ,EAAK,EAAI,EAAK,QAAU,EAAS,EAAI,EAAS,OAAS,EAAQ,QACvE,KAAM,EAAS,EAAI,EAAQ,KAAO,EAAK,EACvC,MAAO,EAAK,EAAI,EAAK,OAAS,EAAS,EAAI,EAAS,MAAQ,EAAQ,OACpE,IAAK,EAAS,EAAI,EAAQ,IAAM,EAAK,CACvC,CACF,CAGA,SAAgB,EAAc,EAA8B,CAC1D,OACE,KAAK,IAAI,EAAS,IAAK,CAAC,EAAI,KAAK,IAAI,EAAS,MAAO,CAAC,EAAI,KAAK,IAAI,EAAS,OAAQ,CAAC,EAAI,KAAK,IAAI,EAAS,KAAM,CAAC,CAEtH,CAGA,SAAgB,EAAY,EAA+B,CACzD,OAAO,EAAS,IAAM,GAAK,EAAS,MAAQ,GAAK,EAAS,OAAS,GAAK,EAAS,KAAO,CAC1F,CAMA,SAAgB,EAAe,EAAY,EAA+B,CACxE,OACE,EAAS,KAAO,EAAK,QACrB,EAAS,OAAS,EAAK,OACvB,EAAS,QAAU,EAAK,QACxB,EAAS,MAAQ,EAAK,KAE1B,CAKA,SAAgB,EACd,EACA,EACA,EACA,EACQ,CACR,IAAM,EAAM,EAAM,MAAM,UAGxB,OAFa,EAAA,QAAQ,CAEb,EAAR,CACE,IAAK,SACH,OAAO,EAAS,EAAI,EAAS,OAAS,EAAQ,QAAU,EAAI,EAAI,EAAI,QACtE,IAAK,OACH,OAAO,EAAI,GAAK,EAAS,EAAI,EAAQ,MACvC,IAAK,QACH,OAAO,EAAS,EAAI,EAAS,MAAQ,EAAQ,OAAS,EAAI,EAAI,EAAI,OACpE,IAAK,MACH,OAAO,EAAI,GAAK,EAAS,EAAI,EAAQ,IACzC,CACF,CAMA,SAAgB,EACd,EACA,EACA,EAAiC,CAAC,EACtB,CACZ,GAAM,CAAE,IAAG,KAAM,EAAA,WAAW,EAAW,EAAM,MAAM,UAAW,EAAM,MAAM,QAAQ,EAC5E,CAAE,WAAU,WAAY,EAAgB,EAAS,CAAK,EAG5D,OAAO,EAAqB,CAFb,GAAG,EAAM,MAAM,SAAU,IAAG,GAEf,EAAM,EAAU,CAAO,CACrD,CAGA,SAAgB,EAAe,EAAwB,EAAiC,CAAC,EAAe,CACtG,GAAM,CAAE,WAAU,WAAY,EAAgB,EAAS,CAAK,EAE5D,OAAO,EAAqB,EAAgB,CAAK,EAAG,EAAU,CAAO,CACvE"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @vielzeug/orbit — overflow-detection helpers.
|
|
3
|
+
*
|
|
4
|
+
* Imported by both `core.ts` (for `detectOverflow`) and middleware modules.
|
|
5
|
+
* Middleware should import from here instead of reaching into core internals.
|
|
6
|
+
*/
|
|
7
|
+
import type { DetectOverflowOptions, MiddlewareState, Placement, Rect, SideObject } from './types';
|
|
8
|
+
/** Resolve a boundary option to a plain Rect. Defaults to the visual viewport. */
|
|
9
|
+
export declare function getBoundaryRect(boundary?: Element | Rect): Rect;
|
|
10
|
+
/** The floating element's rect using the current computed x/y from state. */
|
|
11
|
+
export declare function getFloatingRect(state: MiddlewareState): Rect;
|
|
12
|
+
/** How many pixels each side of `rect` overflows `boundary` (adjusted by `padding`). Negative = no overflow. */
|
|
13
|
+
export declare function detectOverflowAtRect(rect: Rect, boundary: Rect, padding: SideObject): SideObject;
|
|
14
|
+
/** Sum of positive overflows on all sides. */
|
|
15
|
+
export declare function totalOverflow(overflow: SideObject): number;
|
|
16
|
+
/** True if any side has positive overflow. */
|
|
17
|
+
export declare function hasOverflow(overflow: SideObject): boolean;
|
|
18
|
+
/**
|
|
19
|
+
* True if the rect is fully clipped (hidden) by the overflow on any axis.
|
|
20
|
+
* Used by `hide` middleware.
|
|
21
|
+
*/
|
|
22
|
+
export declare function isFullyClipped(rect: Rect, overflow: SideObject): boolean;
|
|
23
|
+
/** Available space in pixels between the reference and the boundary on the given placement's side. */
|
|
24
|
+
export declare function getAvailableSpace(state: MiddlewareState, placement: Placement, boundary: Rect, padding: SideObject): number;
|
|
25
|
+
/**
|
|
26
|
+
* Overflow of the floating element if it were positioned at `placement`
|
|
27
|
+
* using base (un-shifted) coordinates, before any middleware adjustments.
|
|
28
|
+
*/
|
|
29
|
+
export declare function getPlacementOverflow(state: MiddlewareState, placement: Placement, options?: DetectOverflowOptions): SideObject;
|
|
30
|
+
/** Overflow of the floating element at its current position in the middleware pipeline. */
|
|
31
|
+
export declare function detectOverflow(state: MiddlewareState, options?: DetectOverflowOptions): SideObject;
|
|
32
|
+
//# sourceMappingURL=overflow.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"overflow.d.ts","sourceRoot":"","sources":["../src/overflow.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,qBAAqB,EAAE,eAAe,EAAE,SAAS,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAcnG,kFAAkF;AAClF,wBAAgB,eAAe,CAAC,QAAQ,CAAC,EAAE,OAAO,GAAG,IAAI,GAAG,IAAI,CAU/D;AAmBD,6EAA6E;AAC7E,wBAAgB,eAAe,CAAC,KAAK,EAAE,eAAe,GAAG,IAAI,CAE5D;AAID,gHAAgH;AAChH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,OAAO,EAAE,UAAU,GAAG,UAAU,CAOhG;AAED,8CAA8C;AAC9C,wBAAgB,aAAa,CAAC,QAAQ,EAAE,UAAU,GAAG,MAAM,CAI1D;AAED,8CAA8C;AAC9C,wBAAgB,WAAW,CAAC,QAAQ,EAAE,UAAU,GAAG,OAAO,CAEzD;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,UAAU,GAAG,OAAO,CAOxE;AAID,sGAAsG;AACtG,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,eAAe,EACtB,SAAS,EAAE,SAAS,EACpB,QAAQ,EAAE,IAAI,EACd,OAAO,EAAE,UAAU,GAClB,MAAM,CAcR;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAClC,KAAK,EAAE,eAAe,EACtB,SAAS,EAAE,SAAS,EACpB,OAAO,GAAE,qBAA0B,GAClC,UAAU,CAMZ;AAED,2FAA2F;AAC3F,wBAAgB,cAAc,CAAC,KAAK,EAAE,eAAe,EAAE,OAAO,GAAE,qBAA0B,GAAG,UAAU,CAItG"}
|
package/dist/overflow.js
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{baseCoords as e,getSide as t,toSideObject as n}from"./utils.js";function r(){let e=window.visualViewport;return e?{height:e.height,width:e.width,x:e.offsetLeft,y:e.offsetTop}:{height:window.innerHeight,width:window.innerWidth,x:0,y:0}}function i(e){if(!e)return r();if(e instanceof Element){let t=e.getBoundingClientRect();return{height:t.height,width:t.width,x:t.x,y:t.y}}return e}function a(e,t){return{boundary:i(e.boundary??t.boundary),padding:n(e.padding??t.padding)}}function o(e){return{...e.rects.floating,x:e.x,y:e.y}}function s(e,t,n){return{bottom:e.y+e.height-(t.y+t.height-n.bottom),left:t.x+n.left-e.x,right:e.x+e.width-(t.x+t.width-n.right),top:t.y+n.top-e.y}}function c(e){return Math.max(e.top,0)+Math.max(e.right,0)+Math.max(e.bottom,0)+Math.max(e.left,0)}function l(e){return e.top>0||e.right>0||e.bottom>0||e.left>0}function u(e,t){return t.top>=e.height||t.right>=e.width||t.bottom>=e.height||t.left>=e.width}function d(e,n,r,i){let a=e.rects.reference;switch(t(n)){case`bottom`:return r.y+r.height-i.bottom-(a.y+a.height);case`left`:return a.x-(r.x+i.left);case`right`:return r.x+r.width-i.right-(a.x+a.width);case`top`:return a.y-(r.y+i.top)}}function f(t,n,r={}){let{x:i,y:o}=e(n,t.rects.reference,t.rects.floating),{boundary:c,padding:l}=a(r,t);return s({...t.rects.floating,x:i,y:o},c,l)}function p(e,t={}){let{boundary:n,padding:r}=a(t,e);return s(o(e),n,r)}export{p as detectOverflow,s as detectOverflowAtRect,d as getAvailableSpace,i as getBoundaryRect,o as getFloatingRect,f as getPlacementOverflow,l as hasOverflow,u as isFullyClipped,a as resolveBoundary,c as totalOverflow};
|
|
2
|
+
//# sourceMappingURL=overflow.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"overflow.js","names":[],"sources":["../src/overflow.ts"],"sourcesContent":["/**\n * @vielzeug/orbit — overflow-detection helpers.\n *\n * Imported by both `core.ts` (for `detectOverflow`) and middleware modules.\n * Middleware should import from here instead of reaching into core internals.\n */\n\nimport type { DetectOverflowOptions, MiddlewareState, Placement, Rect, SideObject } from './types';\n\nimport { baseCoords, getSide, toSideObject } from './utils';\n\n// ── Boundary ──────────────────────────────────────────────────────────────────\n\nfunction getViewportRect(): Rect {\n const vv = window.visualViewport;\n\n if (vv) return { height: vv.height, width: vv.width, x: vv.offsetLeft, y: vv.offsetTop };\n\n return { height: window.innerHeight, width: window.innerWidth, x: 0, y: 0 };\n}\n\n/** Resolve a boundary option to a plain Rect. Defaults to the visual viewport. */\nexport function getBoundaryRect(boundary?: Element | Rect): Rect {\n if (!boundary) return getViewportRect();\n\n if (boundary instanceof Element) {\n const r = boundary.getBoundingClientRect();\n\n return { height: r.height, width: r.width, x: r.x, y: r.y };\n }\n\n return boundary as Rect;\n}\n\n/**\n * Resolves the effective boundary and padding for a middleware, falling back from\n * per-middleware `options` to the global `state.boundary` / `state.padding` defaults.\n * @internal\n */\nexport function resolveBoundary(\n options: DetectOverflowOptions,\n state: Pick<MiddlewareState, 'boundary' | 'padding'>,\n): { boundary: Rect; padding: SideObject } {\n return {\n boundary: getBoundaryRect(options.boundary ?? state.boundary),\n padding: toSideObject(options.padding ?? state.padding),\n };\n}\n\n// ── Floating rect at current position ────────────────────────────────────────\n\n/** The floating element's rect using the current computed x/y from state. */\nexport function getFloatingRect(state: MiddlewareState): Rect {\n return { ...state.rects.floating, x: state.x, y: state.y };\n}\n\n// ── Per-side overflow ─────────────────────────────────────────────────────────\n\n/** How many pixels each side of `rect` overflows `boundary` (adjusted by `padding`). Negative = no overflow. */\nexport function detectOverflowAtRect(rect: Rect, boundary: Rect, padding: SideObject): SideObject {\n return {\n bottom: rect.y + rect.height - (boundary.y + boundary.height - padding.bottom),\n left: boundary.x + padding.left - rect.x,\n right: rect.x + rect.width - (boundary.x + boundary.width - padding.right),\n top: boundary.y + padding.top - rect.y,\n };\n}\n\n/** Sum of positive overflows on all sides. */\nexport function totalOverflow(overflow: SideObject): number {\n return (\n Math.max(overflow.top, 0) + Math.max(overflow.right, 0) + Math.max(overflow.bottom, 0) + Math.max(overflow.left, 0)\n );\n}\n\n/** True if any side has positive overflow. */\nexport function hasOverflow(overflow: SideObject): boolean {\n return overflow.top > 0 || overflow.right > 0 || overflow.bottom > 0 || overflow.left > 0;\n}\n\n/**\n * True if the rect is fully clipped (hidden) by the overflow on any axis.\n * Used by `hide` middleware.\n */\nexport function isFullyClipped(rect: Rect, overflow: SideObject): boolean {\n return (\n overflow.top >= rect.height ||\n overflow.right >= rect.width ||\n overflow.bottom >= rect.height ||\n overflow.left >= rect.width\n );\n}\n\n// ── Placement-specific helpers ────────────────────────────────────────────────\n\n/** Available space in pixels between the reference and the boundary on the given placement's side. */\nexport function getAvailableSpace(\n state: MiddlewareState,\n placement: Placement,\n boundary: Rect,\n padding: SideObject,\n): number {\n const ref = state.rects.reference;\n const side = getSide(placement);\n\n switch (side) {\n case 'bottom':\n return boundary.y + boundary.height - padding.bottom - (ref.y + ref.height);\n case 'left':\n return ref.x - (boundary.x + padding.left);\n case 'right':\n return boundary.x + boundary.width - padding.right - (ref.x + ref.width);\n case 'top':\n return ref.y - (boundary.y + padding.top);\n }\n}\n\n/**\n * Overflow of the floating element if it were positioned at `placement`\n * using base (un-shifted) coordinates, before any middleware adjustments.\n */\nexport function getPlacementOverflow(\n state: MiddlewareState,\n placement: Placement,\n options: DetectOverflowOptions = {},\n): SideObject {\n const { x, y } = baseCoords(placement, state.rects.reference, state.rects.floating);\n const { boundary, padding } = resolveBoundary(options, state);\n const rect = { ...state.rects.floating, x, y };\n\n return detectOverflowAtRect(rect, boundary, padding);\n}\n\n/** Overflow of the floating element at its current position in the middleware pipeline. */\nexport function detectOverflow(state: MiddlewareState, options: DetectOverflowOptions = {}): SideObject {\n const { boundary, padding } = resolveBoundary(options, state);\n\n return detectOverflowAtRect(getFloatingRect(state), boundary, padding);\n}\n"],"mappings":"uEAaA,SAAS,GAAwB,CAC/B,IAAM,EAAK,OAAO,eAIlB,OAFI,EAAW,CAAE,OAAQ,EAAG,OAAQ,MAAO,EAAG,MAAO,EAAG,EAAG,WAAY,EAAG,EAAG,SAAU,EAEhF,CAAE,OAAQ,OAAO,YAAa,MAAO,OAAO,WAAY,EAAG,EAAG,EAAG,CAAE,CAC5E,CAGA,SAAgB,EAAgB,EAAiC,CAC/D,GAAI,CAAC,EAAU,OAAO,EAAgB,EAEtC,GAAI,aAAoB,QAAS,CAC/B,IAAM,EAAI,EAAS,sBAAsB,EAEzC,MAAO,CAAE,OAAQ,EAAE,OAAQ,MAAO,EAAE,MAAO,EAAG,EAAE,EAAG,EAAG,EAAE,CAAE,CAC5D,CAEA,OAAO,CACT,CAOA,SAAgB,EACd,EACA,EACyC,CACzC,MAAO,CACL,SAAU,EAAgB,EAAQ,UAAY,EAAM,QAAQ,EAC5D,QAAS,EAAa,EAAQ,SAAW,EAAM,OAAO,CACxD,CACF,CAKA,SAAgB,EAAgB,EAA8B,CAC5D,MAAO,CAAE,GAAG,EAAM,MAAM,SAAU,EAAG,EAAM,EAAG,EAAG,EAAM,CAAE,CAC3D,CAKA,SAAgB,EAAqB,EAAY,EAAgB,EAAiC,CAChG,MAAO,CACL,OAAQ,EAAK,EAAI,EAAK,QAAU,EAAS,EAAI,EAAS,OAAS,EAAQ,QACvE,KAAM,EAAS,EAAI,EAAQ,KAAO,EAAK,EACvC,MAAO,EAAK,EAAI,EAAK,OAAS,EAAS,EAAI,EAAS,MAAQ,EAAQ,OACpE,IAAK,EAAS,EAAI,EAAQ,IAAM,EAAK,CACvC,CACF,CAGA,SAAgB,EAAc,EAA8B,CAC1D,OACE,KAAK,IAAI,EAAS,IAAK,CAAC,EAAI,KAAK,IAAI,EAAS,MAAO,CAAC,EAAI,KAAK,IAAI,EAAS,OAAQ,CAAC,EAAI,KAAK,IAAI,EAAS,KAAM,CAAC,CAEtH,CAGA,SAAgB,EAAY,EAA+B,CACzD,OAAO,EAAS,IAAM,GAAK,EAAS,MAAQ,GAAK,EAAS,OAAS,GAAK,EAAS,KAAO,CAC1F,CAMA,SAAgB,EAAe,EAAY,EAA+B,CACxE,OACE,EAAS,KAAO,EAAK,QACrB,EAAS,OAAS,EAAK,OACvB,EAAS,QAAU,EAAK,QACxB,EAAS,MAAQ,EAAK,KAE1B,CAKA,SAAgB,EACd,EACA,EACA,EACA,EACQ,CACR,IAAM,EAAM,EAAM,MAAM,UAGxB,OAFa,EAAQ,CAEb,EAAR,CACE,IAAK,SACH,OAAO,EAAS,EAAI,EAAS,OAAS,EAAQ,QAAU,EAAI,EAAI,EAAI,QACtE,IAAK,OACH,OAAO,EAAI,GAAK,EAAS,EAAI,EAAQ,MACvC,IAAK,QACH,OAAO,EAAS,EAAI,EAAS,MAAQ,EAAQ,OAAS,EAAI,EAAI,EAAI,OACpE,IAAK,MACH,OAAO,EAAI,GAAK,EAAS,EAAI,EAAQ,IACzC,CACF,CAMA,SAAgB,EACd,EACA,EACA,EAAiC,CAAC,EACtB,CACZ,GAAM,CAAE,IAAG,KAAM,EAAW,EAAW,EAAM,MAAM,UAAW,EAAM,MAAM,QAAQ,EAC5E,CAAE,WAAU,WAAY,EAAgB,EAAS,CAAK,EAG5D,OAAO,EAAqB,CAFb,GAAG,EAAM,MAAM,SAAU,IAAG,GAEf,EAAM,EAAU,CAAO,CACrD,CAGA,SAAgB,EAAe,EAAwB,EAAiC,CAAC,EAAe,CACtG,GAAM,CAAE,WAAU,WAAY,EAAgB,EAAS,CAAK,EAE5D,OAAO,EAAqB,EAAgB,CAAK,EAAG,EAAU,CAAO,CACvE"}
|
package/dist/presets.cjs
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./middleware/flip.cjs"),t=require("./middleware/offset.cjs"),n=require("./middleware/shift.cjs"),r=require("./middleware/size.cjs");function i(r={}){let i=r.padding??6;return{middleware:[t.offset(r.offset??8),e.flip({padding:i}),n.shift({padding:i})],placement:r.placement??`top`}}function a(i={}){let a=i.padding??6;return{middleware:[t.offset(i.offset??4),e.flip({padding:a}),n.shift({padding:a}),r.size({padding:a})],placement:i.placement??`bottom-start`}}function o(r={}){let i=r.padding??8;return{middleware:[t.offset(r.offset??12),e.flip({padding:i}),n.shift({padding:i})],placement:r.placement??`top`}}function s(r={}){let i=r.padding??8;return{middleware:[t.offset(r.offset??2),e.flip({padding:i}),n.shift({padding:i})],placement:r.placement??`bottom-start`}}exports.contextMenu=s,exports.dropdown=a,exports.popover=o,exports.tooltip=i;
|
|
2
|
+
//# sourceMappingURL=presets.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"presets.cjs","names":[],"sources":["../src/presets.ts"],"sourcesContent":["import type { Middleware, Placement } from './types';\n\nimport { flip } from './middleware/flip';\nimport { offset } from './middleware/offset';\nimport { shift } from './middleware/shift';\nimport { size } from './middleware/size';\n\n/**\n * A positioning preset — a pre-configured `placement` and `middleware` array\n * ready to spread into `float()` or `computePosition()` options.\n */\nexport interface PositioningPreset {\n placement: Placement;\n middleware: Middleware[];\n}\n\nexport interface PresetOptions {\n /** Gap between the reference and floating element in pixels. */\n offset?: number;\n /** Padding to keep the floating element away from the boundary edge. */\n padding?: number;\n /** Override the default placement. */\n placement?: Placement;\n}\n\n/**\n * Small informational tooltip.\n * Stack: `offset(8) → flip({ padding }) → shift({ padding })`\n *\n * @example\n * ```ts\n * import { tooltip } from '@vielzeug/orbit/presets';\n * const cleanup = float(trigger, tooltipEl, tooltip());\n * ```\n */\nexport function tooltip(options: PresetOptions = {}): PositioningPreset {\n const padding = options.padding ?? 6;\n\n return {\n middleware: [offset(options.offset ?? 8), flip({ padding }), shift({ padding })],\n placement: options.placement ?? 'top',\n };\n}\n\n/**\n * Dropdown panel (select, combobox, menu).\n * Stack: `offset(4) → flip({ padding }) → shift({ padding }) → size({ padding })`\n *\n * @example\n * ```ts\n * import { dropdown } from '@vielzeug/orbit/presets';\n * const cleanup = float(trigger, panel, dropdown());\n * ```\n */\nexport function dropdown(options: PresetOptions = {}): PositioningPreset {\n const padding = options.padding ?? 6;\n\n return {\n middleware: [offset(options.offset ?? 4), flip({ padding }), shift({ padding }), size({ padding })],\n placement: options.placement ?? 'bottom-start',\n };\n}\n\n/**\n * Rich popover or flyout panel (often with an arrow and close button).\n * Stack: `offset(12) → flip({ padding }) → shift({ padding })`\n *\n * @example\n * ```ts\n * import { popover } from '@vielzeug/orbit/presets';\n * const cleanup = float(trigger, panel, popover());\n * ```\n */\nexport function popover(options: PresetOptions = {}): PositioningPreset {\n const padding = options.padding ?? 8;\n\n return {\n middleware: [offset(options.offset ?? 12), flip({ padding }), shift({ padding })],\n placement: options.placement ?? 'top',\n };\n}\n\n/**\n * Right-click context menu anchored to cursor coordinates (virtual reference).\n * Stack: `offset(2) → flip({ padding }) → shift({ padding })`\n *\n * @example\n * ```ts\n * import { contextMenu } from '@vielzeug/orbit/presets';\n * document.addEventListener('contextmenu', (e) => {\n * const vref = { getBoundingClientRect: () => ({ x: e.clientX, y: e.clientY, width: 0, height: 0, ... }) };\n * float(vref, menu, contextMenu());\n * });\n * ```\n */\nexport function contextMenu(options: PresetOptions = {}): PositioningPreset {\n const padding = options.padding ?? 8;\n\n return {\n middleware: [offset(options.offset ?? 2), flip({ padding }), shift({ padding })],\n placement: options.placement ?? 'bottom-start',\n };\n}\n"],"mappings":"wNAmCA,SAAgB,EAAQ,EAAyB,CAAC,EAAsB,CACtE,IAAM,EAAU,EAAQ,SAAW,EAEnC,MAAO,CACL,WAAY,CAAC,EAAA,OAAO,EAAQ,QAAU,CAAC,EAAG,EAAA,KAAK,CAAE,SAAQ,CAAC,EAAG,EAAA,MAAM,CAAE,SAAQ,CAAC,CAAC,EAC/E,UAAW,EAAQ,WAAa,KAClC,CACF,CAYA,SAAgB,EAAS,EAAyB,CAAC,EAAsB,CACvE,IAAM,EAAU,EAAQ,SAAW,EAEnC,MAAO,CACL,WAAY,CAAC,EAAA,OAAO,EAAQ,QAAU,CAAC,EAAG,EAAA,KAAK,CAAE,SAAQ,CAAC,EAAG,EAAA,MAAM,CAAE,SAAQ,CAAC,EAAG,EAAA,KAAK,CAAE,SAAQ,CAAC,CAAC,EAClG,UAAW,EAAQ,WAAa,cAClC,CACF,CAYA,SAAgB,EAAQ,EAAyB,CAAC,EAAsB,CACtE,IAAM,EAAU,EAAQ,SAAW,EAEnC,MAAO,CACL,WAAY,CAAC,EAAA,OAAO,EAAQ,QAAU,EAAE,EAAG,EAAA,KAAK,CAAE,SAAQ,CAAC,EAAG,EAAA,MAAM,CAAE,SAAQ,CAAC,CAAC,EAChF,UAAW,EAAQ,WAAa,KAClC,CACF,CAeA,SAAgB,EAAY,EAAyB,CAAC,EAAsB,CAC1E,IAAM,EAAU,EAAQ,SAAW,EAEnC,MAAO,CACL,WAAY,CAAC,EAAA,OAAO,EAAQ,QAAU,CAAC,EAAG,EAAA,KAAK,CAAE,SAAQ,CAAC,EAAG,EAAA,MAAM,CAAE,SAAQ,CAAC,CAAC,EAC/E,UAAW,EAAQ,WAAa,cAClC,CACF"}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import type { Middleware, Placement } from './types';
|
|
2
|
+
/**
|
|
3
|
+
* A positioning preset — a pre-configured `placement` and `middleware` array
|
|
4
|
+
* ready to spread into `float()` or `computePosition()` options.
|
|
5
|
+
*/
|
|
6
|
+
export interface PositioningPreset {
|
|
7
|
+
placement: Placement;
|
|
8
|
+
middleware: Middleware[];
|
|
9
|
+
}
|
|
10
|
+
export interface PresetOptions {
|
|
11
|
+
/** Gap between the reference and floating element in pixels. */
|
|
12
|
+
offset?: number;
|
|
13
|
+
/** Padding to keep the floating element away from the boundary edge. */
|
|
14
|
+
padding?: number;
|
|
15
|
+
/** Override the default placement. */
|
|
16
|
+
placement?: Placement;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Small informational tooltip.
|
|
20
|
+
* Stack: `offset(8) → flip({ padding }) → shift({ padding })`
|
|
21
|
+
*
|
|
22
|
+
* @example
|
|
23
|
+
* ```ts
|
|
24
|
+
* import { tooltip } from '@vielzeug/orbit/presets';
|
|
25
|
+
* const cleanup = float(trigger, tooltipEl, tooltip());
|
|
26
|
+
* ```
|
|
27
|
+
*/
|
|
28
|
+
export declare function tooltip(options?: PresetOptions): PositioningPreset;
|
|
29
|
+
/**
|
|
30
|
+
* Dropdown panel (select, combobox, menu).
|
|
31
|
+
* Stack: `offset(4) → flip({ padding }) → shift({ padding }) → size({ padding })`
|
|
32
|
+
*
|
|
33
|
+
* @example
|
|
34
|
+
* ```ts
|
|
35
|
+
* import { dropdown } from '@vielzeug/orbit/presets';
|
|
36
|
+
* const cleanup = float(trigger, panel, dropdown());
|
|
37
|
+
* ```
|
|
38
|
+
*/
|
|
39
|
+
export declare function dropdown(options?: PresetOptions): PositioningPreset;
|
|
40
|
+
/**
|
|
41
|
+
* Rich popover or flyout panel (often with an arrow and close button).
|
|
42
|
+
* Stack: `offset(12) → flip({ padding }) → shift({ padding })`
|
|
43
|
+
*
|
|
44
|
+
* @example
|
|
45
|
+
* ```ts
|
|
46
|
+
* import { popover } from '@vielzeug/orbit/presets';
|
|
47
|
+
* const cleanup = float(trigger, panel, popover());
|
|
48
|
+
* ```
|
|
49
|
+
*/
|
|
50
|
+
export declare function popover(options?: PresetOptions): PositioningPreset;
|
|
51
|
+
/**
|
|
52
|
+
* Right-click context menu anchored to cursor coordinates (virtual reference).
|
|
53
|
+
* Stack: `offset(2) → flip({ padding }) → shift({ padding })`
|
|
54
|
+
*
|
|
55
|
+
* @example
|
|
56
|
+
* ```ts
|
|
57
|
+
* import { contextMenu } from '@vielzeug/orbit/presets';
|
|
58
|
+
* document.addEventListener('contextmenu', (e) => {
|
|
59
|
+
* const vref = { getBoundingClientRect: () => ({ x: e.clientX, y: e.clientY, width: 0, height: 0, ... }) };
|
|
60
|
+
* float(vref, menu, contextMenu());
|
|
61
|
+
* });
|
|
62
|
+
* ```
|
|
63
|
+
*/
|
|
64
|
+
export declare function contextMenu(options?: PresetOptions): PositioningPreset;
|
|
65
|
+
//# sourceMappingURL=presets.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"presets.d.ts","sourceRoot":"","sources":["../src/presets.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAOrD;;;GAGG;AACH,MAAM,WAAW,iBAAiB;IAChC,SAAS,EAAE,SAAS,CAAC;IACrB,UAAU,EAAE,UAAU,EAAE,CAAC;CAC1B;AAED,MAAM,WAAW,aAAa;IAC5B,gEAAgE;IAChE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,wEAAwE;IACxE,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,sCAAsC;IACtC,SAAS,CAAC,EAAE,SAAS,CAAC;CACvB;AAED;;;;;;;;;GASG;AACH,wBAAgB,OAAO,CAAC,OAAO,GAAE,aAAkB,GAAG,iBAAiB,CAOtE;AAED;;;;;;;;;GASG;AACH,wBAAgB,QAAQ,CAAC,OAAO,GAAE,aAAkB,GAAG,iBAAiB,CAOvE;AAED;;;;;;;;;GASG;AACH,wBAAgB,OAAO,CAAC,OAAO,GAAE,aAAkB,GAAG,iBAAiB,CAOtE;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,WAAW,CAAC,OAAO,GAAE,aAAkB,GAAG,iBAAiB,CAO1E"}
|
package/dist/presets.js
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{flip as e}from"./middleware/flip.js";import{offset as t}from"./middleware/offset.js";import{shift as n}from"./middleware/shift.js";import{size as r}from"./middleware/size.js";function i(r={}){let i=r.padding??6;return{middleware:[t(r.offset??8),e({padding:i}),n({padding:i})],placement:r.placement??`top`}}function a(i={}){let a=i.padding??6;return{middleware:[t(i.offset??4),e({padding:a}),n({padding:a}),r({padding:a})],placement:i.placement??`bottom-start`}}function o(r={}){let i=r.padding??8;return{middleware:[t(r.offset??12),e({padding:i}),n({padding:i})],placement:r.placement??`top`}}function s(r={}){let i=r.padding??8;return{middleware:[t(r.offset??2),e({padding:i}),n({padding:i})],placement:r.placement??`bottom-start`}}export{s as contextMenu,a as dropdown,o as popover,i as tooltip};
|
|
2
|
+
//# sourceMappingURL=presets.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"presets.js","names":[],"sources":["../src/presets.ts"],"sourcesContent":["import type { Middleware, Placement } from './types';\n\nimport { flip } from './middleware/flip';\nimport { offset } from './middleware/offset';\nimport { shift } from './middleware/shift';\nimport { size } from './middleware/size';\n\n/**\n * A positioning preset — a pre-configured `placement` and `middleware` array\n * ready to spread into `float()` or `computePosition()` options.\n */\nexport interface PositioningPreset {\n placement: Placement;\n middleware: Middleware[];\n}\n\nexport interface PresetOptions {\n /** Gap between the reference and floating element in pixels. */\n offset?: number;\n /** Padding to keep the floating element away from the boundary edge. */\n padding?: number;\n /** Override the default placement. */\n placement?: Placement;\n}\n\n/**\n * Small informational tooltip.\n * Stack: `offset(8) → flip({ padding }) → shift({ padding })`\n *\n * @example\n * ```ts\n * import { tooltip } from '@vielzeug/orbit/presets';\n * const cleanup = float(trigger, tooltipEl, tooltip());\n * ```\n */\nexport function tooltip(options: PresetOptions = {}): PositioningPreset {\n const padding = options.padding ?? 6;\n\n return {\n middleware: [offset(options.offset ?? 8), flip({ padding }), shift({ padding })],\n placement: options.placement ?? 'top',\n };\n}\n\n/**\n * Dropdown panel (select, combobox, menu).\n * Stack: `offset(4) → flip({ padding }) → shift({ padding }) → size({ padding })`\n *\n * @example\n * ```ts\n * import { dropdown } from '@vielzeug/orbit/presets';\n * const cleanup = float(trigger, panel, dropdown());\n * ```\n */\nexport function dropdown(options: PresetOptions = {}): PositioningPreset {\n const padding = options.padding ?? 6;\n\n return {\n middleware: [offset(options.offset ?? 4), flip({ padding }), shift({ padding }), size({ padding })],\n placement: options.placement ?? 'bottom-start',\n };\n}\n\n/**\n * Rich popover or flyout panel (often with an arrow and close button).\n * Stack: `offset(12) → flip({ padding }) → shift({ padding })`\n *\n * @example\n * ```ts\n * import { popover } from '@vielzeug/orbit/presets';\n * const cleanup = float(trigger, panel, popover());\n * ```\n */\nexport function popover(options: PresetOptions = {}): PositioningPreset {\n const padding = options.padding ?? 8;\n\n return {\n middleware: [offset(options.offset ?? 12), flip({ padding }), shift({ padding })],\n placement: options.placement ?? 'top',\n };\n}\n\n/**\n * Right-click context menu anchored to cursor coordinates (virtual reference).\n * Stack: `offset(2) → flip({ padding }) → shift({ padding })`\n *\n * @example\n * ```ts\n * import { contextMenu } from '@vielzeug/orbit/presets';\n * document.addEventListener('contextmenu', (e) => {\n * const vref = { getBoundingClientRect: () => ({ x: e.clientX, y: e.clientY, width: 0, height: 0, ... }) };\n * float(vref, menu, contextMenu());\n * });\n * ```\n */\nexport function contextMenu(options: PresetOptions = {}): PositioningPreset {\n const padding = options.padding ?? 8;\n\n return {\n middleware: [offset(options.offset ?? 2), flip({ padding }), shift({ padding })],\n placement: options.placement ?? 'bottom-start',\n };\n}\n"],"mappings":"sLAmCA,SAAgB,EAAQ,EAAyB,CAAC,EAAsB,CACtE,IAAM,EAAU,EAAQ,SAAW,EAEnC,MAAO,CACL,WAAY,CAAC,EAAO,EAAQ,QAAU,CAAC,EAAG,EAAK,CAAE,SAAQ,CAAC,EAAG,EAAM,CAAE,SAAQ,CAAC,CAAC,EAC/E,UAAW,EAAQ,WAAa,KAClC,CACF,CAYA,SAAgB,EAAS,EAAyB,CAAC,EAAsB,CACvE,IAAM,EAAU,EAAQ,SAAW,EAEnC,MAAO,CACL,WAAY,CAAC,EAAO,EAAQ,QAAU,CAAC,EAAG,EAAK,CAAE,SAAQ,CAAC,EAAG,EAAM,CAAE,SAAQ,CAAC,EAAG,EAAK,CAAE,SAAQ,CAAC,CAAC,EAClG,UAAW,EAAQ,WAAa,cAClC,CACF,CAYA,SAAgB,EAAQ,EAAyB,CAAC,EAAsB,CACtE,IAAM,EAAU,EAAQ,SAAW,EAEnC,MAAO,CACL,WAAY,CAAC,EAAO,EAAQ,QAAU,EAAE,EAAG,EAAK,CAAE,SAAQ,CAAC,EAAG,EAAM,CAAE,SAAQ,CAAC,CAAC,EAChF,UAAW,EAAQ,WAAa,KAClC,CACF,CAeA,SAAgB,EAAY,EAAyB,CAAC,EAAsB,CAC1E,IAAM,EAAU,EAAQ,SAAW,EAEnC,MAAO,CACL,WAAY,CAAC,EAAO,EAAQ,QAAU,CAAC,EAAG,EAAK,CAAE,SAAQ,CAAC,EAAG,EAAM,CAAE,SAAQ,CAAC,CAAC,EAC/E,UAAW,EAAQ,WAAa,cAClC,CACF"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./float.cjs");let t=require("@vielzeug/ripple");function n(n,r,i={}){let a=(0,t.signal)(null),o=e.float(n,r,{...i,apply:e=>{a.value=e}});return Object.assign(o,{position:a})}exports.createFloatState=n;
|
|
2
|
+
//# sourceMappingURL=reactive.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reactive.cjs","names":[],"sources":["../src/reactive.ts"],"sourcesContent":["/**\n * @vielzeug/orbit/reactive — reactive signal adapter for @vielzeug/ripple.\n *\n * Import from the dedicated sub-path so it is tree-shaken from production bundles\n * when ripple is not used:\n * ```ts\n * import { createFloatState } from '@vielzeug/orbit/reactive';\n * ```\n */\n\nimport type { Readable } from '@vielzeug/ripple';\n\nimport { signal } from '@vielzeug/ripple';\n\nimport type { FloatOptions } from './float';\nimport type { ComputePositionResult, FloatHandle, ReferenceElement } from './types';\n\nimport { float } from './float';\n\n/**\n * Reactive handle returned by `createFloatState`.\n * Extends {@link FloatHandle} with a `position` signal that updates on every reposition.\n */\nexport interface ReactiveFloatHandle extends FloatHandle {\n /** Reactive signal that holds the most recently computed position. Read-only. */\n readonly position: Readable<ComputePositionResult | null>;\n}\n\n/**\n * Like `float()` but exposes a reactive {@link Signal} that updates on every position change.\n *\n * DOM styles are **not** automatically applied — use a ripple `effect` to read `position` and apply:\n *\n * ```ts\n * import { createFloatState } from '@vielzeug/orbit/reactive';\n * import { effect } from '@vielzeug/ripple';\n *\n * const { position, dispose } = createFloatState(reference, tooltip, {\n * placement: 'top',\n * middleware: [offset(8), flip(), shift({ padding: 6 })],\n * });\n *\n * effect(() => {\n * const pos = position.value;\n * if (!pos) return;\n * tooltip.style.left = `${pos.x}px`;\n * tooltip.style.top = `${pos.y}px`;\n * });\n *\n * // on teardown:\n * dispose();\n * ```\n */\nexport function createFloatState(\n reference: ReferenceElement,\n floating: HTMLElement,\n options: Omit<FloatOptions, 'apply'> = {},\n): ReactiveFloatHandle {\n const position = signal<ComputePositionResult | null>(null);\n\n const handle = float(reference, floating, {\n ...options,\n apply: (result) => {\n position.value = result;\n },\n });\n\n return Object.assign(handle, {\n position: position as Readable<ComputePositionResult | null>,\n });\n}\n"],"mappings":"oIAqDA,SAAgB,EACd,EACA,EACA,EAAuC,CAAC,EACnB,CACrB,IAAM,GAAA,EAAA,EAAA,OAAA,CAAgD,IAAI,EAEpD,EAAS,EAAA,MAAM,EAAW,EAAU,CACxC,GAAG,EACH,MAAQ,GAAW,CACjB,EAAS,MAAQ,CACnB,CACF,CAAC,EAED,OAAO,OAAO,OAAO,EAAQ,CACjB,UACZ,CAAC,CACH"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @vielzeug/orbit/reactive — reactive signal adapter for @vielzeug/ripple.
|
|
3
|
+
*
|
|
4
|
+
* Import from the dedicated sub-path so it is tree-shaken from production bundles
|
|
5
|
+
* when ripple is not used:
|
|
6
|
+
* ```ts
|
|
7
|
+
* import { createFloatState } from '@vielzeug/orbit/reactive';
|
|
8
|
+
* ```
|
|
9
|
+
*/
|
|
10
|
+
import type { Readable } from '@vielzeug/ripple';
|
|
11
|
+
import type { FloatOptions } from './float';
|
|
12
|
+
import type { ComputePositionResult, FloatHandle, ReferenceElement } from './types';
|
|
13
|
+
/**
|
|
14
|
+
* Reactive handle returned by `createFloatState`.
|
|
15
|
+
* Extends {@link FloatHandle} with a `position` signal that updates on every reposition.
|
|
16
|
+
*/
|
|
17
|
+
export interface ReactiveFloatHandle extends FloatHandle {
|
|
18
|
+
/** Reactive signal that holds the most recently computed position. Read-only. */
|
|
19
|
+
readonly position: Readable<ComputePositionResult | null>;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Like `float()` but exposes a reactive {@link Signal} that updates on every position change.
|
|
23
|
+
*
|
|
24
|
+
* DOM styles are **not** automatically applied — use a ripple `effect` to read `position` and apply:
|
|
25
|
+
*
|
|
26
|
+
* ```ts
|
|
27
|
+
* import { createFloatState } from '@vielzeug/orbit/reactive';
|
|
28
|
+
* import { effect } from '@vielzeug/ripple';
|
|
29
|
+
*
|
|
30
|
+
* const { position, dispose } = createFloatState(reference, tooltip, {
|
|
31
|
+
* placement: 'top',
|
|
32
|
+
* middleware: [offset(8), flip(), shift({ padding: 6 })],
|
|
33
|
+
* });
|
|
34
|
+
*
|
|
35
|
+
* effect(() => {
|
|
36
|
+
* const pos = position.value;
|
|
37
|
+
* if (!pos) return;
|
|
38
|
+
* tooltip.style.left = `${pos.x}px`;
|
|
39
|
+
* tooltip.style.top = `${pos.y}px`;
|
|
40
|
+
* });
|
|
41
|
+
*
|
|
42
|
+
* // on teardown:
|
|
43
|
+
* dispose();
|
|
44
|
+
* ```
|
|
45
|
+
*/
|
|
46
|
+
export declare function createFloatState(reference: ReferenceElement, floating: HTMLElement, options?: Omit<FloatOptions, 'apply'>): ReactiveFloatHandle;
|
|
47
|
+
//# sourceMappingURL=reactive.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reactive.d.ts","sourceRoot":"","sources":["../src/reactive.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAIjD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAC5C,OAAO,KAAK,EAAE,qBAAqB,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAIpF;;;GAGG;AACH,MAAM,WAAW,mBAAoB,SAAQ,WAAW;IACtD,iFAAiF;IACjF,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC,qBAAqB,GAAG,IAAI,CAAC,CAAC;CAC3D;AAED;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAgB,gBAAgB,CAC9B,SAAS,EAAE,gBAAgB,EAC3B,QAAQ,EAAE,WAAW,EACrB,OAAO,GAAE,IAAI,CAAC,YAAY,EAAE,OAAO,CAAM,GACxC,mBAAmB,CAarB"}
|
package/dist/reactive.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reactive.js","names":[],"sources":["../src/reactive.ts"],"sourcesContent":["/**\n * @vielzeug/orbit/reactive — reactive signal adapter for @vielzeug/ripple.\n *\n * Import from the dedicated sub-path so it is tree-shaken from production bundles\n * when ripple is not used:\n * ```ts\n * import { createFloatState } from '@vielzeug/orbit/reactive';\n * ```\n */\n\nimport type { Readable } from '@vielzeug/ripple';\n\nimport { signal } from '@vielzeug/ripple';\n\nimport type { FloatOptions } from './float';\nimport type { ComputePositionResult, FloatHandle, ReferenceElement } from './types';\n\nimport { float } from './float';\n\n/**\n * Reactive handle returned by `createFloatState`.\n * Extends {@link FloatHandle} with a `position` signal that updates on every reposition.\n */\nexport interface ReactiveFloatHandle extends FloatHandle {\n /** Reactive signal that holds the most recently computed position. Read-only. */\n readonly position: Readable<ComputePositionResult | null>;\n}\n\n/**\n * Like `float()` but exposes a reactive {@link Signal} that updates on every position change.\n *\n * DOM styles are **not** automatically applied — use a ripple `effect` to read `position` and apply:\n *\n * ```ts\n * import { createFloatState } from '@vielzeug/orbit/reactive';\n * import { effect } from '@vielzeug/ripple';\n *\n * const { position, dispose } = createFloatState(reference, tooltip, {\n * placement: 'top',\n * middleware: [offset(8), flip(), shift({ padding: 6 })],\n * });\n *\n * effect(() => {\n * const pos = position.value;\n * if (!pos) return;\n * tooltip.style.left = `${pos.x}px`;\n * tooltip.style.top = `${pos.y}px`;\n * });\n *\n * // on teardown:\n * dispose();\n * ```\n */\nexport function createFloatState(\n reference: ReferenceElement,\n floating: HTMLElement,\n options: Omit<FloatOptions, 'apply'> = {},\n): ReactiveFloatHandle {\n const position = signal<ComputePositionResult | null>(null);\n\n const handle = float(reference, floating, {\n ...options,\n apply: (result) => {\n position.value = result;\n },\n });\n\n return Object.assign(handle, {\n position: position as Readable<ComputePositionResult | null>,\n });\n}\n"],"mappings":"6EAqDA,SAAgB,EACd,EACA,EACA,EAAuC,CAAC,EACnB,CACrB,IAAM,EAAW,EAAqC,IAAI,EAEpD,EAAS,EAAM,EAAW,EAAU,CACxC,GAAG,EACH,MAAQ,GAAW,CACjB,EAAS,MAAQ,CACnB,CACF,CAAC,EAED,OAAO,OAAO,OAAO,EAAQ,CACjB,UACZ,CAAC,CACH"}
|
package/dist/ssr.cjs
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./float.cjs");var t=()=>{},n=(e=`bottom`)=>({middlewareData:{},placement:e,x:0,y:0});function r(e,t,r={}){return Promise.resolve(n(r.placement))}function i(e,t,r={}){return Promise.resolve(n(r.placement))}function a(e,t,r={}){return n(r.placement)}function o(e,n,r,i){return t}function s(n,r,i){return e.makeHandle(t,()=>null,t)}exports.autoUpdate=o,exports.computePosition=a,exports.computePositionAsync=i,exports.computePositionRaf=r,exports.float=s;
|
|
2
|
+
//# sourceMappingURL=ssr.cjs.map
|
package/dist/ssr.cjs.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ssr.cjs","names":[],"sources":["../src/ssr.ts"],"sourcesContent":["/**\n * @vielzeug/orbit/ssr — no-op stubs for server-side rendering.\n *\n * Import this sub-path in SSR environments (Node.js, Deno, Bun) instead of the\n * main entry to avoid `getBoundingClientRect`, `window`, and `document` references\n * that are unavailable server-side.\n *\n * ```ts\n * // vite.config.ts (or equivalent)\n * resolve: {\n * alias: {\n * '@vielzeug/orbit': process.env.SSR ? '@vielzeug/orbit/ssr' : '@vielzeug/orbit',\n * },\n * }\n * ```\n */\n\nimport type { AutoUpdateOptions } from './auto-update';\nimport type { FloatOptions } from './float';\nimport type { ComputePositionOptions, ComputePositionResult, FloatHandle, ReferenceElement } from './types';\n\nimport { makeHandle } from './float';\n\nconst NOOP: () => void = () => {};\n\nconst NULL_RESULT = (placement: ComputePositionOptions['placement'] = 'bottom'): ComputePositionResult => ({\n middlewareData: {},\n placement,\n x: 0,\n y: 0,\n});\n\n/**\n * No-op stub. Resolves immediately with zero-coordinate result.\n */\nexport function computePositionRaf(\n _reference: ReferenceElement,\n _floating: HTMLElement,\n options: ComputePositionOptions = {},\n): Promise<ComputePositionResult> {\n return Promise.resolve(NULL_RESULT(options.placement));\n}\n\n/**\n * No-op stub. Resolves immediately with zero-coordinate result.\n */\nexport function computePositionAsync(\n _reference: ReferenceElement,\n _floating: HTMLElement,\n options: ComputePositionOptions = {},\n): Promise<ComputePositionResult> {\n return Promise.resolve(NULL_RESULT(options.placement));\n}\n\n/**\n * No-op stub. Returns zero-coordinate result with the requested placement.\n */\nexport function computePosition(\n _reference: ReferenceElement,\n _floating: HTMLElement,\n options: ComputePositionOptions = {},\n): ComputePositionResult {\n return NULL_RESULT(options.placement);\n}\n\n/**\n * No-op stub. Returns a no-op cleanup function.\n */\nexport function autoUpdate(\n _reference: ReferenceElement,\n _floating: HTMLElement,\n _update: () => void,\n _options?: AutoUpdateOptions,\n): () => void {\n return NOOP;\n}\n\n/**\n * No-op stub. Returns a FloatHandle with no-op methods. `getPosition()` always returns `null`\n * (position is never computed in an SSR environment).\n */\nexport function float(_reference: ReferenceElement, _floating: HTMLElement, _options?: FloatOptions): FloatHandle {\n return makeHandle(NOOP, () => null, NOOP);\n}\n"],"mappings":"kGAuBA,IAAM,MAAyB,CAAC,EAE1B,GAAe,EAAiD,YAAqC,CACzG,eAAgB,CAAC,EACjB,YACA,EAAG,EACH,EAAG,CACL,GAKA,SAAgB,EACd,EACA,EACA,EAAkC,CAAC,EACH,CAChC,OAAO,QAAQ,QAAQ,EAAY,EAAQ,SAAS,CAAC,CACvD,CAKA,SAAgB,EACd,EACA,EACA,EAAkC,CAAC,EACH,CAChC,OAAO,QAAQ,QAAQ,EAAY,EAAQ,SAAS,CAAC,CACvD,CAKA,SAAgB,EACd,EACA,EACA,EAAkC,CAAC,EACZ,CACvB,OAAO,EAAY,EAAQ,SAAS,CACtC,CAKA,SAAgB,EACd,EACA,EACA,EACA,EACY,CACZ,OAAO,CACT,CAMA,SAAgB,EAAM,EAA8B,EAAwB,EAAsC,CAChH,OAAO,EAAA,WAAW,MAAY,KAAM,CAAI,CAC1C"}
|
package/dist/ssr.d.ts
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @vielzeug/orbit/ssr — no-op stubs for server-side rendering.
|
|
3
|
+
*
|
|
4
|
+
* Import this sub-path in SSR environments (Node.js, Deno, Bun) instead of the
|
|
5
|
+
* main entry to avoid `getBoundingClientRect`, `window`, and `document` references
|
|
6
|
+
* that are unavailable server-side.
|
|
7
|
+
*
|
|
8
|
+
* ```ts
|
|
9
|
+
* // vite.config.ts (or equivalent)
|
|
10
|
+
* resolve: {
|
|
11
|
+
* alias: {
|
|
12
|
+
* '@vielzeug/orbit': process.env.SSR ? '@vielzeug/orbit/ssr' : '@vielzeug/orbit',
|
|
13
|
+
* },
|
|
14
|
+
* }
|
|
15
|
+
* ```
|
|
16
|
+
*/
|
|
17
|
+
import type { AutoUpdateOptions } from './auto-update';
|
|
18
|
+
import type { FloatOptions } from './float';
|
|
19
|
+
import type { ComputePositionOptions, ComputePositionResult, FloatHandle, ReferenceElement } from './types';
|
|
20
|
+
/**
|
|
21
|
+
* No-op stub. Resolves immediately with zero-coordinate result.
|
|
22
|
+
*/
|
|
23
|
+
export declare function computePositionRaf(_reference: ReferenceElement, _floating: HTMLElement, options?: ComputePositionOptions): Promise<ComputePositionResult>;
|
|
24
|
+
/**
|
|
25
|
+
* No-op stub. Resolves immediately with zero-coordinate result.
|
|
26
|
+
*/
|
|
27
|
+
export declare function computePositionAsync(_reference: ReferenceElement, _floating: HTMLElement, options?: ComputePositionOptions): Promise<ComputePositionResult>;
|
|
28
|
+
/**
|
|
29
|
+
* No-op stub. Returns zero-coordinate result with the requested placement.
|
|
30
|
+
*/
|
|
31
|
+
export declare function computePosition(_reference: ReferenceElement, _floating: HTMLElement, options?: ComputePositionOptions): ComputePositionResult;
|
|
32
|
+
/**
|
|
33
|
+
* No-op stub. Returns a no-op cleanup function.
|
|
34
|
+
*/
|
|
35
|
+
export declare function autoUpdate(_reference: ReferenceElement, _floating: HTMLElement, _update: () => void, _options?: AutoUpdateOptions): () => void;
|
|
36
|
+
/**
|
|
37
|
+
* No-op stub. Returns a FloatHandle with no-op methods. `getPosition()` always returns `null`
|
|
38
|
+
* (position is never computed in an SSR environment).
|
|
39
|
+
*/
|
|
40
|
+
export declare function float(_reference: ReferenceElement, _floating: HTMLElement, _options?: FloatOptions): FloatHandle;
|
|
41
|
+
//# sourceMappingURL=ssr.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ssr.d.ts","sourceRoot":"","sources":["../src/ssr.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AACvD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAC5C,OAAO,KAAK,EAAE,sBAAsB,EAAE,qBAAqB,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAa5G;;GAEG;AACH,wBAAgB,kBAAkB,CAChC,UAAU,EAAE,gBAAgB,EAC5B,SAAS,EAAE,WAAW,EACtB,OAAO,GAAE,sBAA2B,GACnC,OAAO,CAAC,qBAAqB,CAAC,CAEhC;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAClC,UAAU,EAAE,gBAAgB,EAC5B,SAAS,EAAE,WAAW,EACtB,OAAO,GAAE,sBAA2B,GACnC,OAAO,CAAC,qBAAqB,CAAC,CAEhC;AAED;;GAEG;AACH,wBAAgB,eAAe,CAC7B,UAAU,EAAE,gBAAgB,EAC5B,SAAS,EAAE,WAAW,EACtB,OAAO,GAAE,sBAA2B,GACnC,qBAAqB,CAEvB;AAED;;GAEG;AACH,wBAAgB,UAAU,CACxB,UAAU,EAAE,gBAAgB,EAC5B,SAAS,EAAE,WAAW,EACtB,OAAO,EAAE,MAAM,IAAI,EACnB,QAAQ,CAAC,EAAE,iBAAiB,GAC3B,MAAM,IAAI,CAEZ;AAED;;;GAGG;AACH,wBAAgB,KAAK,CAAC,UAAU,EAAE,gBAAgB,EAAE,SAAS,EAAE,WAAW,EAAE,QAAQ,CAAC,EAAE,YAAY,GAAG,WAAW,CAEhH"}
|
package/dist/ssr.js
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{makeHandle as e}from"./float.js";var t=()=>{},n=(e=`bottom`)=>({middlewareData:{},placement:e,x:0,y:0});function r(e,t,r={}){return Promise.resolve(n(r.placement))}function i(e,t,r={}){return Promise.resolve(n(r.placement))}function a(e,t,r={}){return n(r.placement)}function o(e,n,r,i){return t}function s(n,r,i){return e(t,()=>null,t)}export{o as autoUpdate,a as computePosition,i as computePositionAsync,r as computePositionRaf,s as float};
|
|
2
|
+
//# sourceMappingURL=ssr.js.map
|
package/dist/ssr.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ssr.js","names":[],"sources":["../src/ssr.ts"],"sourcesContent":["/**\n * @vielzeug/orbit/ssr — no-op stubs for server-side rendering.\n *\n * Import this sub-path in SSR environments (Node.js, Deno, Bun) instead of the\n * main entry to avoid `getBoundingClientRect`, `window`, and `document` references\n * that are unavailable server-side.\n *\n * ```ts\n * // vite.config.ts (or equivalent)\n * resolve: {\n * alias: {\n * '@vielzeug/orbit': process.env.SSR ? '@vielzeug/orbit/ssr' : '@vielzeug/orbit',\n * },\n * }\n * ```\n */\n\nimport type { AutoUpdateOptions } from './auto-update';\nimport type { FloatOptions } from './float';\nimport type { ComputePositionOptions, ComputePositionResult, FloatHandle, ReferenceElement } from './types';\n\nimport { makeHandle } from './float';\n\nconst NOOP: () => void = () => {};\n\nconst NULL_RESULT = (placement: ComputePositionOptions['placement'] = 'bottom'): ComputePositionResult => ({\n middlewareData: {},\n placement,\n x: 0,\n y: 0,\n});\n\n/**\n * No-op stub. Resolves immediately with zero-coordinate result.\n */\nexport function computePositionRaf(\n _reference: ReferenceElement,\n _floating: HTMLElement,\n options: ComputePositionOptions = {},\n): Promise<ComputePositionResult> {\n return Promise.resolve(NULL_RESULT(options.placement));\n}\n\n/**\n * No-op stub. Resolves immediately with zero-coordinate result.\n */\nexport function computePositionAsync(\n _reference: ReferenceElement,\n _floating: HTMLElement,\n options: ComputePositionOptions = {},\n): Promise<ComputePositionResult> {\n return Promise.resolve(NULL_RESULT(options.placement));\n}\n\n/**\n * No-op stub. Returns zero-coordinate result with the requested placement.\n */\nexport function computePosition(\n _reference: ReferenceElement,\n _floating: HTMLElement,\n options: ComputePositionOptions = {},\n): ComputePositionResult {\n return NULL_RESULT(options.placement);\n}\n\n/**\n * No-op stub. Returns a no-op cleanup function.\n */\nexport function autoUpdate(\n _reference: ReferenceElement,\n _floating: HTMLElement,\n _update: () => void,\n _options?: AutoUpdateOptions,\n): () => void {\n return NOOP;\n}\n\n/**\n * No-op stub. Returns a FloatHandle with no-op methods. `getPosition()` always returns `null`\n * (position is never computed in an SSR environment).\n */\nexport function float(_reference: ReferenceElement, _floating: HTMLElement, _options?: FloatOptions): FloatHandle {\n return makeHandle(NOOP, () => null, NOOP);\n}\n"],"mappings":"wCAuBA,IAAM,MAAyB,CAAC,EAE1B,GAAe,EAAiD,YAAqC,CACzG,eAAgB,CAAC,EACjB,YACA,EAAG,EACH,EAAG,CACL,GAKA,SAAgB,EACd,EACA,EACA,EAAkC,CAAC,EACH,CAChC,OAAO,QAAQ,QAAQ,EAAY,EAAQ,SAAS,CAAC,CACvD,CAKA,SAAgB,EACd,EACA,EACA,EAAkC,CAAC,EACH,CAChC,OAAO,QAAQ,QAAQ,EAAY,EAAQ,SAAS,CAAC,CACvD,CAKA,SAAgB,EACd,EACA,EACA,EAAkC,CAAC,EACZ,CACvB,OAAO,EAAY,EAAQ,SAAS,CACtC,CAKA,SAAgB,EACd,EACA,EACA,EACA,EACY,CACZ,OAAO,CACT,CAMA,SAAgB,EAAM,EAA8B,EAAwB,EAAsC,CAChH,OAAO,EAAW,MAAY,KAAM,CAAI,CAC1C"}
|