Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@radix-ui/popper

Package Overview
Dependencies
Maintainers
6
Versions
17
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@radix-ui/popper - npm Package Compare versions

Comparing version 0.1.0 to 0.1.1-rc.1

342

dist/index.js

@@ -1,2 +0,342 @@

exports.SIDE_OPTIONS=["top","right","bottom","left"];function t(t,e,r){const o=t["x"===r?"left":"top"],n="x"===r?"width":"height",i=t[n],p=e[n];return{before:o-p,start:o,center:o+(i-p)/2,end:o+i-p,after:o+i}}function e(t){return{position:"absolute",top:0,left:0,minWidth:"max-content",willChange:"transform",transform:`translate3d(${Math.round(t.x+window.scrollX)}px, ${Math.round(t.y+window.scrollY)}px, 0)`}}function r(t,e,r,o,n){const i="top"===e||"bottom"===e,p=n?n.width:0,a=n?n.height:0,s=p/2+o;let c="",f="";return i?(c={start:`${s}px`,center:"center",end:t.width-s+"px"}[r],f="top"===e?`${t.height+a}px`:-a+"px"):(c="left"===e?`${t.width+a}px`:-a+"px",f={start:`${s}px`,center:"center",end:t.height-s+"px"}[r]),`${c} ${f}`}exports.ALIGN_OPTIONS=["start","center","end"],exports.getPlacementData=function({anchorRect:p,popperSize:c,arrowSize:f,arrowOffset:l=0,side:d,sideOffset:h=0,align:x,alignOffset:g=0,shouldAvoidCollisions:u=!0,collisionBoundariesRect:w,collisionTolerance:m=0}){if(!p||!c||!w)return{popperStyles:o,arrowStyles:n};const y=function(e,r,o=0,n=0,i){const p=i?i.height:0,a=t(r,e,"x"),s=t(r,e,"y"),c=s.before-o-p,f=s.after+o+p,l=a.before-o-p,d=a.after+o+p;return{top:{start:{x:a.start+n,y:c},center:{x:a.center,y:c},end:{x:a.end-n,y:c}},right:{start:{x:d,y:s.start+n},center:{x:d,y:s.center},end:{x:d,y:s.end-n}},bottom:{start:{x:a.start+n,y:f},center:{x:a.center,y:f},end:{x:a.end-n,y:f}},left:{start:{x:l,y:s.start+n},center:{x:l,y:s.center},end:{x:l,y:s.end-n}}}}(c,p,h,g,f),b=y[d][x];if(!1===u){const t=e(b);let o=n;f&&(o=i({popperSize:c,arrowSize:f,arrowOffset:l,side:d,align:x}));return{popperStyles:{...t,"--radix-popper-transform-origin":r(c,d,x,l,f)},arrowStyles:o,placedSide:d,placedAlign:x}}const S=DOMRect.fromRect({...c,...b}),$=(O=w,z=m,DOMRect.fromRect({width:O.width-2*z,height:O.height-2*z,x:O.left+z,y:O.top+z}));var O,z;const R=s(S,$),M=y[a(d)][x],D=function(t,e,r){const o=a(t);return e[t]&&!r[o]?o:t}(d,R,s(DOMRect.fromRect({...c,...M}),$)),A=function(t,e,r,o,n){const i="top"===r||"bottom"===r,p=i?"left":"top",a=i?"right":"bottom",s=i?"width":"height",c=e[s]>t[s];if(("start"===o||"center"===o)&&(n[p]&&c||n[a]&&!c))return"end";if(("end"===o||"center"===o)&&(n[a]&&c||n[p]&&!c))return"start";return o}(c,p,d,x,R),I=e(y[D][A]);let C=n;return f&&(C=i({popperSize:c,arrowSize:f,arrowOffset:l,side:D,align:A})),{popperStyles:{...I,"--radix-popper-transform-origin":r(c,D,A,l,f)},arrowStyles:C,placedSide:D,placedAlign:A}};const o={position:"fixed",top:0,left:0,opacity:0,transform:"translate3d(0, -200%, 0)"},n={position:"absolute",opacity:0};function i({popperSize:t,arrowSize:e,arrowOffset:r,side:o,align:n}){const i=(t.width-e.width)/2,a=(t.height-e.width)/2,s={top:0,right:90,bottom:180,left:-90}[o],c=Math.max(e.width,e.height),f={width:`${c}px`,height:`${c}px`,transform:`rotate(${s}deg)`,willChange:"transform",position:"absolute",[o]:"100%",direction:p(o,n)};return"top"!==o&&"bottom"!==o||("start"===n&&(f.left=`${r}px`),"center"===n&&(f.left=`${i}px`),"end"===n&&(f.right=`${r}px`)),"left"!==o&&"right"!==o||("start"===n&&(f.top=`${r}px`),"center"===n&&(f.top=`${a}px`),"end"===n&&(f.bottom=`${r}px`)),f}function p(t,e){return("top"!==t&&"right"!==t||"end"!==e)&&("bottom"!==t&&"left"!==t||"end"===e)?"ltr":"rtl"}function a(t){return{top:"bottom",right:"left",bottom:"top",left:"right"}[t]}function s(t,e){return{top:t.top<e.top,right:t.right>e.right,bottom:t.bottom>e.bottom,left:t.left<e.left}}
function $parcel$export(e, n, v, s) {
Object.defineProperty(e, n, {get: v, set: s, enumerable: true, configurable: true});
}
$parcel$export(module.exports, "getPlacementData", () => $25d1e7214bd08a9d$export$d3e7649885811a7d);
$parcel$export(module.exports, "SIDE_OPTIONS", () => $25d1e7214bd08a9d$export$36f0086da09c4b9f);
$parcel$export(module.exports, "ALIGN_OPTIONS", () => $25d1e7214bd08a9d$export$3671ffab7b302fc9);
const $25d1e7214bd08a9d$export$36f0086da09c4b9f = [
'top',
'right',
'bottom',
'left'
];
const $25d1e7214bd08a9d$export$3671ffab7b302fc9 = [
'start',
'center',
'end'
];
/**
* Given all the information necessary to compute it,
* this function calculates all the necessary placement data.
*
* It will return:
*
* - the styles to apply to the popper (including a custom property that is useful to set the transform origin in the right place)
* - the styles to apply to the arrow
* - the placed side (because it might have changed because of collisions)
* - the placed align (because it might have changed because of collisions)
*/ function $25d1e7214bd08a9d$export$d3e7649885811a7d({ anchorRect: anchorRect , popperSize: popperSize , arrowSize: arrowSize , arrowOffset: arrowOffset = 0 , side: side , sideOffset: sideOffset = 0 , align: align , alignOffset: alignOffset = 0 , shouldAvoidCollisions: shouldAvoidCollisions = true , collisionBoundariesRect: collisionBoundariesRect , collisionTolerance: collisionTolerance = 0 }) {
// if we're not ready to do all the measurements yet,
// we return some good default styles
if (!anchorRect || !popperSize || !collisionBoundariesRect) return {
popperStyles: $25d1e7214bd08a9d$var$UNMEASURED_POPPER_STYLES,
arrowStyles: $25d1e7214bd08a9d$var$UNMEASURED_ARROW_STYLES
};
// pre-compute points for all potential placements
const allPlacementPoints = $25d1e7214bd08a9d$var$getAllPlacementPoints(popperSize, anchorRect, sideOffset, alignOffset, arrowSize); // get point based on side / align
const popperPoint = allPlacementPoints[side][align]; // if we don't need to avoid collisions, we can stop here
if (shouldAvoidCollisions === false) {
const popperStyles = $25d1e7214bd08a9d$var$getPlacementStylesForPoint(popperPoint);
let arrowStyles = $25d1e7214bd08a9d$var$UNMEASURED_ARROW_STYLES;
if (arrowSize) arrowStyles = $25d1e7214bd08a9d$var$getPopperArrowStyles({
popperSize: popperSize,
arrowSize: arrowSize,
arrowOffset: arrowOffset,
side: side,
align: align
});
const transformOrigin = $25d1e7214bd08a9d$var$getTransformOrigin(popperSize, side, align, arrowOffset, arrowSize);
return {
popperStyles: {
...popperStyles,
['--radix-popper-transform-origin']: transformOrigin
},
arrowStyles: arrowStyles,
placedSide: side,
placedAlign: align
};
} // create a new rect as if element had been moved to new placement
const popperRect = DOMRect.fromRect({
...popperSize,
...popperPoint
}); // create a new rect representing the collision boundaries but taking into account any added tolerance
const collisionBoundariesRectWithTolerance = $25d1e7214bd08a9d$var$getContractedRect(collisionBoundariesRect, collisionTolerance); // check for any collisions in new placement
const popperCollisions = $25d1e7214bd08a9d$var$getCollisions(popperRect, collisionBoundariesRectWithTolerance); // do all the same calculations for the opposite side
// this is because we need to check for potential collisions if we were to swap side
const oppositeSide = $25d1e7214bd08a9d$var$getOppositeSide(side);
const oppositeSidePopperPoint = allPlacementPoints[oppositeSide][align];
const updatedOppositeSidePopperPoint = DOMRect.fromRect({
...popperSize,
...oppositeSidePopperPoint
});
const oppositeSidePopperCollisions = $25d1e7214bd08a9d$var$getCollisions(updatedOppositeSidePopperPoint, collisionBoundariesRectWithTolerance); // adjust side accounting for collisions / opposite side collisions
const placedSide = $25d1e7214bd08a9d$var$getSideAccountingForCollisions(side, popperCollisions, oppositeSidePopperCollisions); // adjust alignnment accounting for collisions
const placedAlign = $25d1e7214bd08a9d$var$getAlignAccountingForCollisions(popperSize, anchorRect, side, align, popperCollisions);
const placedPopperPoint = allPlacementPoints[placedSide][placedAlign]; // compute adjusted popper / arrow styles
const popperStyles = $25d1e7214bd08a9d$var$getPlacementStylesForPoint(placedPopperPoint);
let arrowStyles = $25d1e7214bd08a9d$var$UNMEASURED_ARROW_STYLES;
if (arrowSize) arrowStyles = $25d1e7214bd08a9d$var$getPopperArrowStyles({
popperSize: popperSize,
arrowSize: arrowSize,
arrowOffset: arrowOffset,
side: placedSide,
align: placedAlign
});
const transformOrigin = $25d1e7214bd08a9d$var$getTransformOrigin(popperSize, placedSide, placedAlign, arrowOffset, arrowSize);
return {
popperStyles: {
...popperStyles,
['--radix-popper-transform-origin']: transformOrigin
},
arrowStyles: arrowStyles,
placedSide: placedSide,
placedAlign: placedAlign
};
}
function $25d1e7214bd08a9d$var$getAllPlacementPoints(popperSize, anchorRect, sideOffset = 0, alignOffset = 0, arrowSize) {
const arrowBaseToTipLength = arrowSize ? arrowSize.height : 0;
const x = $25d1e7214bd08a9d$var$getPopperSlotsForAxis(anchorRect, popperSize, 'x');
const y = $25d1e7214bd08a9d$var$getPopperSlotsForAxis(anchorRect, popperSize, 'y');
const topY = y.before - sideOffset - arrowBaseToTipLength; // prettier-ignore
const bottomY = y.after + sideOffset + arrowBaseToTipLength; // prettier-ignore
const leftX = x.before - sideOffset - arrowBaseToTipLength; // prettier-ignore
const rightX = x.after + sideOffset + arrowBaseToTipLength; // prettier-ignore
// prettier-ignore
const map = {
top: {
start: {
x: x.start + alignOffset,
y: topY
},
center: {
x: x.center,
y: topY
},
end: {
x: x.end - alignOffset,
y: topY
}
},
right: {
start: {
x: rightX,
y: y.start + alignOffset
},
center: {
x: rightX,
y: y.center
},
end: {
x: rightX,
y: y.end - alignOffset
}
},
bottom: {
start: {
x: x.start + alignOffset,
y: bottomY
},
center: {
x: x.center,
y: bottomY
},
end: {
x: x.end - alignOffset,
y: bottomY
}
},
left: {
start: {
x: leftX,
y: y.start + alignOffset
},
center: {
x: leftX,
y: y.center
},
end: {
x: leftX,
y: y.end - alignOffset
}
}
};
return map;
}
function $25d1e7214bd08a9d$var$getPopperSlotsForAxis(anchorRect, popperSize, axis) {
const startSide = axis === 'x' ? 'left' : 'top';
const anchorStart = anchorRect[startSide];
const dimension = axis === 'x' ? 'width' : 'height';
const anchorDimension = anchorRect[dimension];
const popperDimension = popperSize[dimension]; // prettier-ignore
return {
before: anchorStart - popperDimension,
start: anchorStart,
center: anchorStart + (anchorDimension - popperDimension) / 2,
end: anchorStart + anchorDimension - popperDimension,
after: anchorStart + anchorDimension
};
}
/**
* Gets an adjusted side based on collision information
*/ function $25d1e7214bd08a9d$var$getSideAccountingForCollisions(/** The side we want to ideally position to */ side, /** The collisions for this given side */ collisions, /** The collisions for the opposite side (if we were to swap side) */ oppositeSideCollisions) {
const oppositeSide = $25d1e7214bd08a9d$var$getOppositeSide(side); // in order to prevent premature jumps
// we only swap side if there's enough space to fit on the opposite side
return collisions[side] && !oppositeSideCollisions[oppositeSide] ? oppositeSide : side;
}
/**
* Gets an adjusted alignment based on collision information
*/ function $25d1e7214bd08a9d$var$getAlignAccountingForCollisions(/** The size of the popper to place */ popperSize, /** The size of the anchor we are placing around */ anchorSize, /** The final side */ side, /** The desired align */ align, /** The collisions */ collisions) {
const isHorizontalSide = side === 'top' || side === 'bottom';
const startBound = isHorizontalSide ? 'left' : 'top';
const endBound = isHorizontalSide ? 'right' : 'bottom';
const dimension = isHorizontalSide ? 'width' : 'height';
const isAnchorBigger = anchorSize[dimension] > popperSize[dimension];
if (align === 'start' || align === 'center') {
if (collisions[startBound] && isAnchorBigger || collisions[endBound] && !isAnchorBigger) return 'end';
}
if (align === 'end' || align === 'center') {
if (collisions[endBound] && isAnchorBigger || collisions[startBound] && !isAnchorBigger) return 'start';
}
return align;
}
function $25d1e7214bd08a9d$var$getPlacementStylesForPoint(point) {
const x = Math.round(point.x + window.scrollX);
const y = Math.round(point.y + window.scrollY);
return {
position: 'absolute',
top: 0,
left: 0,
minWidth: 'max-content',
willChange: 'transform',
transform: `translate3d(${x}px, ${y}px, 0)`
};
}
function $25d1e7214bd08a9d$var$getTransformOrigin(popperSize, side, align, arrowOffset, arrowSize) {
const isHorizontalSide = side === 'top' || side === 'bottom';
const arrowBaseLength = arrowSize ? arrowSize.width : 0;
const arrowBaseToTipLength = arrowSize ? arrowSize.height : 0;
const sideOffset = arrowBaseToTipLength;
const alignOffset = arrowBaseLength / 2 + arrowOffset;
let x = '';
let y = '';
if (isHorizontalSide) {
x = ({
start: `${alignOffset}px`,
center: 'center',
end: `${popperSize.width - alignOffset}px`
})[align];
y = side === 'top' ? `${popperSize.height + sideOffset}px` : `${-sideOffset}px`;
} else {
x = side === 'left' ? `${popperSize.width + sideOffset}px` : `${-sideOffset}px`;
y = ({
start: `${alignOffset}px`,
center: 'center',
end: `${popperSize.height - alignOffset}px`
})[align];
}
return `${x} ${y}`;
}
const $25d1e7214bd08a9d$var$UNMEASURED_POPPER_STYLES = {
// position: 'fixed' here is important because it will take the popper
// out of the flow so it does not disturb the position of the anchor
position: 'fixed',
top: 0,
left: 0,
opacity: 0,
transform: 'translate3d(0, -200%, 0)'
};
const $25d1e7214bd08a9d$var$UNMEASURED_ARROW_STYLES = {
// given the arrow is nested inside the popper,
// make sure that it is out of the flow and doesn't hinder then popper's measurement
position: 'absolute',
opacity: 0
};
/**
* Computes the styles necessary to position, rotate and align the arrow correctly.
* It can adjust itself based on anchor/popper size, side/align and an optional offset.
*/ function $25d1e7214bd08a9d$var$getPopperArrowStyles({ popperSize: popperSize , arrowSize: arrowSize , arrowOffset: arrowOffset , side: side , align: align }) {
const popperCenterX = (popperSize.width - arrowSize.width) / 2;
const popperCenterY = (popperSize.height - arrowSize.width) / 2;
const rotationMap = {
top: 0,
right: 90,
bottom: 180,
left: -90
};
const rotation = rotationMap[side];
const arrowMaxDimension = Math.max(arrowSize.width, arrowSize.height);
const styles = {
// we make sure we put the arrow inside a 1:1 ratio container
// this is to make the rotation handling simpler
// as we do no need to worry about changing the transform-origin
width: `${arrowMaxDimension}px`,
height: `${arrowMaxDimension}px`,
// rotate the arrow appropriately
transform: `rotate(${rotation}deg)`,
willChange: 'transform',
// position the arrow appropriately
position: 'absolute',
[side]: '100%',
// Because the arrow gets rotated (see `transform above`)
// and we are putting it inside a 1:1 ratio container
// we need to adjust the CSS direction from `ltr` to `rtl`
// in some circumstances
direction: $25d1e7214bd08a9d$var$getArrowCssDirection(side, align)
};
if (side === 'top' || side === 'bottom') {
if (align === 'start') styles.left = `${arrowOffset}px`;
if (align === 'center') styles.left = `${popperCenterX}px`;
if (align === 'end') styles.right = `${arrowOffset}px`;
}
if (side === 'left' || side === 'right') {
if (align === 'start') styles.top = `${arrowOffset}px`;
if (align === 'center') styles.top = `${popperCenterY}px`;
if (align === 'end') styles.bottom = `${arrowOffset}px`;
}
return styles;
}
/**
* Adjusts the arrow's CSS direction (`ltr` / `rtl`)
*/ function $25d1e7214bd08a9d$var$getArrowCssDirection(side, align) {
if ((side === 'top' || side === 'right') && align === 'end') return 'rtl';
if ((side === 'bottom' || side === 'left') && align !== 'end') return 'rtl';
return 'ltr';
}
/**
* Gets the opposite side of a given side (ie. top => bottom, left => right, …)
*/ function $25d1e7214bd08a9d$var$getOppositeSide(side) {
const oppositeSides = {
top: 'bottom',
right: 'left',
bottom: 'top',
left: 'right'
};
return oppositeSides[side];
}
/**
* Creates a new rect (`ClientRect`) based on a given one but contracted by
* a given amout on each side.
*/ function $25d1e7214bd08a9d$var$getContractedRect(rect, amount) {
return DOMRect.fromRect({
width: rect.width - amount * 2,
height: rect.height - amount * 2,
x: rect.left + amount,
y: rect.top + amount
});
}
/**
* Gets collisions for each side of a rect (top, right, bottom, left)
*/ function $25d1e7214bd08a9d$var$getCollisions(/** The rect to test collisions against */ rect, /** The rect which represents the boundaries for collision checks */ collisionBoundariesRect) {
return {
top: rect.top < collisionBoundariesRect.top,
right: rect.right > collisionBoundariesRect.right,
bottom: rect.bottom > collisionBoundariesRect.bottom,
left: rect.left < collisionBoundariesRect.left
};
}
//# sourceMappingURL=index.js.map

@@ -1,2 +0,336 @@

export const SIDE_OPTIONS=["top","right","bottom","left"];export const ALIGN_OPTIONS=["start","center","end"];export function getPlacementData({anchorRect:p,popperSize:c,arrowSize:f,arrowOffset:l=0,side:d,sideOffset:h=0,align:x,alignOffset:g=0,shouldAvoidCollisions:u=!0,collisionBoundariesRect:w,collisionTolerance:m=0}){if(!p||!c||!w)return{popperStyles:o,arrowStyles:n};const y=function(e,r,o=0,n=0,i){const p=i?i.height:0,a=t(r,e,"x"),s=t(r,e,"y"),c=s.before-o-p,f=s.after+o+p,l=a.before-o-p,d=a.after+o+p;return{top:{start:{x:a.start+n,y:c},center:{x:a.center,y:c},end:{x:a.end-n,y:c}},right:{start:{x:d,y:s.start+n},center:{x:d,y:s.center},end:{x:d,y:s.end-n}},bottom:{start:{x:a.start+n,y:f},center:{x:a.center,y:f},end:{x:a.end-n,y:f}},left:{start:{x:l,y:s.start+n},center:{x:l,y:s.center},end:{x:l,y:s.end-n}}}}(c,p,h,g,f),b=y[d][x];if(!1===u){const t=e(b);let o=n;f&&(o=i({popperSize:c,arrowSize:f,arrowOffset:l,side:d,align:x}));return{popperStyles:{...t,"--radix-popper-transform-origin":r(c,d,x,l,f)},arrowStyles:o,placedSide:d,placedAlign:x}}const S=DOMRect.fromRect({...c,...b}),$=(O=w,z=m,DOMRect.fromRect({width:O.width-2*z,height:O.height-2*z,x:O.left+z,y:O.top+z}));var O,z;const R=s(S,$),M=y[a(d)][x],D=function(t,e,r){const o=a(t);return e[t]&&!r[o]?o:t}(d,R,s(DOMRect.fromRect({...c,...M}),$)),A=function(t,e,r,o,n){const i="top"===r||"bottom"===r,p=i?"left":"top",a=i?"right":"bottom",s=i?"width":"height",c=e[s]>t[s];if(("start"===o||"center"===o)&&(n[p]&&c||n[a]&&!c))return"end";if(("end"===o||"center"===o)&&(n[a]&&c||n[p]&&!c))return"start";return o}(c,p,d,x,R),I=e(y[D][A]);let C=n;f&&(C=i({popperSize:c,arrowSize:f,arrowOffset:l,side:D,align:A}));return{popperStyles:{...I,"--radix-popper-transform-origin":r(c,D,A,l,f)},arrowStyles:C,placedSide:D,placedAlign:A}}function t(t,e,r){const o=t["x"===r?"left":"top"],n="x"===r?"width":"height",i=t[n],p=e[n];return{before:o-p,start:o,center:o+(i-p)/2,end:o+i-p,after:o+i}}function e(t){return{position:"absolute",top:0,left:0,minWidth:"max-content",willChange:"transform",transform:`translate3d(${Math.round(t.x+window.scrollX)}px, ${Math.round(t.y+window.scrollY)}px, 0)`}}function r(t,e,r,o,n){const i="top"===e||"bottom"===e,p=n?n.width:0,a=n?n.height:0,s=p/2+o;let c="",f="";return i?(c={start:`${s}px`,center:"center",end:t.width-s+"px"}[r],f="top"===e?`${t.height+a}px`:-a+"px"):(c="left"===e?`${t.width+a}px`:-a+"px",f={start:`${s}px`,center:"center",end:t.height-s+"px"}[r]),`${c} ${f}`}const o={position:"fixed",top:0,left:0,opacity:0,transform:"translate3d(0, -200%, 0)"},n={position:"absolute",opacity:0};function i({popperSize:t,arrowSize:e,arrowOffset:r,side:o,align:n}){const i=(t.width-e.width)/2,a=(t.height-e.width)/2,s={top:0,right:90,bottom:180,left:-90}[o],c=Math.max(e.width,e.height),f={width:`${c}px`,height:`${c}px`,transform:`rotate(${s}deg)`,willChange:"transform",position:"absolute",[o]:"100%",direction:p(o,n)};return"top"!==o&&"bottom"!==o||("start"===n&&(f.left=`${r}px`),"center"===n&&(f.left=`${i}px`),"end"===n&&(f.right=`${r}px`)),"left"!==o&&"right"!==o||("start"===n&&(f.top=`${r}px`),"center"===n&&(f.top=`${a}px`),"end"===n&&(f.bottom=`${r}px`)),f}function p(t,e){return("top"!==t&&"right"!==t||"end"!==e)&&("bottom"!==t&&"left"!==t||"end"===e)?"ltr":"rtl"}function a(t){return{top:"bottom",right:"left",bottom:"top",left:"right"}[t]}function s(t,e){return{top:t.top<e.top,right:t.right>e.right,bottom:t.bottom>e.bottom,left:t.left<e.left}}
const $dcd28e347ddb21ab$export$36f0086da09c4b9f = [
'top',
'right',
'bottom',
'left'
];
const $dcd28e347ddb21ab$export$3671ffab7b302fc9 = [
'start',
'center',
'end'
];
/**
* Given all the information necessary to compute it,
* this function calculates all the necessary placement data.
*
* It will return:
*
* - the styles to apply to the popper (including a custom property that is useful to set the transform origin in the right place)
* - the styles to apply to the arrow
* - the placed side (because it might have changed because of collisions)
* - the placed align (because it might have changed because of collisions)
*/ function $dcd28e347ddb21ab$export$d3e7649885811a7d({ anchorRect: anchorRect , popperSize: popperSize , arrowSize: arrowSize , arrowOffset: arrowOffset = 0 , side: side , sideOffset: sideOffset = 0 , align: align , alignOffset: alignOffset = 0 , shouldAvoidCollisions: shouldAvoidCollisions = true , collisionBoundariesRect: collisionBoundariesRect , collisionTolerance: collisionTolerance = 0 }) {
// if we're not ready to do all the measurements yet,
// we return some good default styles
if (!anchorRect || !popperSize || !collisionBoundariesRect) return {
popperStyles: $dcd28e347ddb21ab$var$UNMEASURED_POPPER_STYLES,
arrowStyles: $dcd28e347ddb21ab$var$UNMEASURED_ARROW_STYLES
};
// pre-compute points for all potential placements
const allPlacementPoints = $dcd28e347ddb21ab$var$getAllPlacementPoints(popperSize, anchorRect, sideOffset, alignOffset, arrowSize); // get point based on side / align
const popperPoint = allPlacementPoints[side][align]; // if we don't need to avoid collisions, we can stop here
if (shouldAvoidCollisions === false) {
const popperStyles = $dcd28e347ddb21ab$var$getPlacementStylesForPoint(popperPoint);
let arrowStyles = $dcd28e347ddb21ab$var$UNMEASURED_ARROW_STYLES;
if (arrowSize) arrowStyles = $dcd28e347ddb21ab$var$getPopperArrowStyles({
popperSize: popperSize,
arrowSize: arrowSize,
arrowOffset: arrowOffset,
side: side,
align: align
});
const transformOrigin = $dcd28e347ddb21ab$var$getTransformOrigin(popperSize, side, align, arrowOffset, arrowSize);
return {
popperStyles: {
...popperStyles,
['--radix-popper-transform-origin']: transformOrigin
},
arrowStyles: arrowStyles,
placedSide: side,
placedAlign: align
};
} // create a new rect as if element had been moved to new placement
const popperRect = DOMRect.fromRect({
...popperSize,
...popperPoint
}); // create a new rect representing the collision boundaries but taking into account any added tolerance
const collisionBoundariesRectWithTolerance = $dcd28e347ddb21ab$var$getContractedRect(collisionBoundariesRect, collisionTolerance); // check for any collisions in new placement
const popperCollisions = $dcd28e347ddb21ab$var$getCollisions(popperRect, collisionBoundariesRectWithTolerance); // do all the same calculations for the opposite side
// this is because we need to check for potential collisions if we were to swap side
const oppositeSide = $dcd28e347ddb21ab$var$getOppositeSide(side);
const oppositeSidePopperPoint = allPlacementPoints[oppositeSide][align];
const updatedOppositeSidePopperPoint = DOMRect.fromRect({
...popperSize,
...oppositeSidePopperPoint
});
const oppositeSidePopperCollisions = $dcd28e347ddb21ab$var$getCollisions(updatedOppositeSidePopperPoint, collisionBoundariesRectWithTolerance); // adjust side accounting for collisions / opposite side collisions
const placedSide = $dcd28e347ddb21ab$var$getSideAccountingForCollisions(side, popperCollisions, oppositeSidePopperCollisions); // adjust alignnment accounting for collisions
const placedAlign = $dcd28e347ddb21ab$var$getAlignAccountingForCollisions(popperSize, anchorRect, side, align, popperCollisions);
const placedPopperPoint = allPlacementPoints[placedSide][placedAlign]; // compute adjusted popper / arrow styles
const popperStyles = $dcd28e347ddb21ab$var$getPlacementStylesForPoint(placedPopperPoint);
let arrowStyles = $dcd28e347ddb21ab$var$UNMEASURED_ARROW_STYLES;
if (arrowSize) arrowStyles = $dcd28e347ddb21ab$var$getPopperArrowStyles({
popperSize: popperSize,
arrowSize: arrowSize,
arrowOffset: arrowOffset,
side: placedSide,
align: placedAlign
});
const transformOrigin = $dcd28e347ddb21ab$var$getTransformOrigin(popperSize, placedSide, placedAlign, arrowOffset, arrowSize);
return {
popperStyles: {
...popperStyles,
['--radix-popper-transform-origin']: transformOrigin
},
arrowStyles: arrowStyles,
placedSide: placedSide,
placedAlign: placedAlign
};
}
function $dcd28e347ddb21ab$var$getAllPlacementPoints(popperSize, anchorRect, sideOffset = 0, alignOffset = 0, arrowSize) {
const arrowBaseToTipLength = arrowSize ? arrowSize.height : 0;
const x = $dcd28e347ddb21ab$var$getPopperSlotsForAxis(anchorRect, popperSize, 'x');
const y = $dcd28e347ddb21ab$var$getPopperSlotsForAxis(anchorRect, popperSize, 'y');
const topY = y.before - sideOffset - arrowBaseToTipLength; // prettier-ignore
const bottomY = y.after + sideOffset + arrowBaseToTipLength; // prettier-ignore
const leftX = x.before - sideOffset - arrowBaseToTipLength; // prettier-ignore
const rightX = x.after + sideOffset + arrowBaseToTipLength; // prettier-ignore
// prettier-ignore
const map = {
top: {
start: {
x: x.start + alignOffset,
y: topY
},
center: {
x: x.center,
y: topY
},
end: {
x: x.end - alignOffset,
y: topY
}
},
right: {
start: {
x: rightX,
y: y.start + alignOffset
},
center: {
x: rightX,
y: y.center
},
end: {
x: rightX,
y: y.end - alignOffset
}
},
bottom: {
start: {
x: x.start + alignOffset,
y: bottomY
},
center: {
x: x.center,
y: bottomY
},
end: {
x: x.end - alignOffset,
y: bottomY
}
},
left: {
start: {
x: leftX,
y: y.start + alignOffset
},
center: {
x: leftX,
y: y.center
},
end: {
x: leftX,
y: y.end - alignOffset
}
}
};
return map;
}
function $dcd28e347ddb21ab$var$getPopperSlotsForAxis(anchorRect, popperSize, axis) {
const startSide = axis === 'x' ? 'left' : 'top';
const anchorStart = anchorRect[startSide];
const dimension = axis === 'x' ? 'width' : 'height';
const anchorDimension = anchorRect[dimension];
const popperDimension = popperSize[dimension]; // prettier-ignore
return {
before: anchorStart - popperDimension,
start: anchorStart,
center: anchorStart + (anchorDimension - popperDimension) / 2,
end: anchorStart + anchorDimension - popperDimension,
after: anchorStart + anchorDimension
};
}
/**
* Gets an adjusted side based on collision information
*/ function $dcd28e347ddb21ab$var$getSideAccountingForCollisions(/** The side we want to ideally position to */ side, /** The collisions for this given side */ collisions, /** The collisions for the opposite side (if we were to swap side) */ oppositeSideCollisions) {
const oppositeSide = $dcd28e347ddb21ab$var$getOppositeSide(side); // in order to prevent premature jumps
// we only swap side if there's enough space to fit on the opposite side
return collisions[side] && !oppositeSideCollisions[oppositeSide] ? oppositeSide : side;
}
/**
* Gets an adjusted alignment based on collision information
*/ function $dcd28e347ddb21ab$var$getAlignAccountingForCollisions(/** The size of the popper to place */ popperSize, /** The size of the anchor we are placing around */ anchorSize, /** The final side */ side, /** The desired align */ align, /** The collisions */ collisions) {
const isHorizontalSide = side === 'top' || side === 'bottom';
const startBound = isHorizontalSide ? 'left' : 'top';
const endBound = isHorizontalSide ? 'right' : 'bottom';
const dimension = isHorizontalSide ? 'width' : 'height';
const isAnchorBigger = anchorSize[dimension] > popperSize[dimension];
if (align === 'start' || align === 'center') {
if (collisions[startBound] && isAnchorBigger || collisions[endBound] && !isAnchorBigger) return 'end';
}
if (align === 'end' || align === 'center') {
if (collisions[endBound] && isAnchorBigger || collisions[startBound] && !isAnchorBigger) return 'start';
}
return align;
}
function $dcd28e347ddb21ab$var$getPlacementStylesForPoint(point) {
const x = Math.round(point.x + window.scrollX);
const y = Math.round(point.y + window.scrollY);
return {
position: 'absolute',
top: 0,
left: 0,
minWidth: 'max-content',
willChange: 'transform',
transform: `translate3d(${x}px, ${y}px, 0)`
};
}
function $dcd28e347ddb21ab$var$getTransformOrigin(popperSize, side, align, arrowOffset, arrowSize) {
const isHorizontalSide = side === 'top' || side === 'bottom';
const arrowBaseLength = arrowSize ? arrowSize.width : 0;
const arrowBaseToTipLength = arrowSize ? arrowSize.height : 0;
const sideOffset = arrowBaseToTipLength;
const alignOffset = arrowBaseLength / 2 + arrowOffset;
let x = '';
let y = '';
if (isHorizontalSide) {
x = ({
start: `${alignOffset}px`,
center: 'center',
end: `${popperSize.width - alignOffset}px`
})[align];
y = side === 'top' ? `${popperSize.height + sideOffset}px` : `${-sideOffset}px`;
} else {
x = side === 'left' ? `${popperSize.width + sideOffset}px` : `${-sideOffset}px`;
y = ({
start: `${alignOffset}px`,
center: 'center',
end: `${popperSize.height - alignOffset}px`
})[align];
}
return `${x} ${y}`;
}
const $dcd28e347ddb21ab$var$UNMEASURED_POPPER_STYLES = {
// position: 'fixed' here is important because it will take the popper
// out of the flow so it does not disturb the position of the anchor
position: 'fixed',
top: 0,
left: 0,
opacity: 0,
transform: 'translate3d(0, -200%, 0)'
};
const $dcd28e347ddb21ab$var$UNMEASURED_ARROW_STYLES = {
// given the arrow is nested inside the popper,
// make sure that it is out of the flow and doesn't hinder then popper's measurement
position: 'absolute',
opacity: 0
};
/**
* Computes the styles necessary to position, rotate and align the arrow correctly.
* It can adjust itself based on anchor/popper size, side/align and an optional offset.
*/ function $dcd28e347ddb21ab$var$getPopperArrowStyles({ popperSize: popperSize , arrowSize: arrowSize , arrowOffset: arrowOffset , side: side , align: align }) {
const popperCenterX = (popperSize.width - arrowSize.width) / 2;
const popperCenterY = (popperSize.height - arrowSize.width) / 2;
const rotationMap = {
top: 0,
right: 90,
bottom: 180,
left: -90
};
const rotation = rotationMap[side];
const arrowMaxDimension = Math.max(arrowSize.width, arrowSize.height);
const styles = {
// we make sure we put the arrow inside a 1:1 ratio container
// this is to make the rotation handling simpler
// as we do no need to worry about changing the transform-origin
width: `${arrowMaxDimension}px`,
height: `${arrowMaxDimension}px`,
// rotate the arrow appropriately
transform: `rotate(${rotation}deg)`,
willChange: 'transform',
// position the arrow appropriately
position: 'absolute',
[side]: '100%',
// Because the arrow gets rotated (see `transform above`)
// and we are putting it inside a 1:1 ratio container
// we need to adjust the CSS direction from `ltr` to `rtl`
// in some circumstances
direction: $dcd28e347ddb21ab$var$getArrowCssDirection(side, align)
};
if (side === 'top' || side === 'bottom') {
if (align === 'start') styles.left = `${arrowOffset}px`;
if (align === 'center') styles.left = `${popperCenterX}px`;
if (align === 'end') styles.right = `${arrowOffset}px`;
}
if (side === 'left' || side === 'right') {
if (align === 'start') styles.top = `${arrowOffset}px`;
if (align === 'center') styles.top = `${popperCenterY}px`;
if (align === 'end') styles.bottom = `${arrowOffset}px`;
}
return styles;
}
/**
* Adjusts the arrow's CSS direction (`ltr` / `rtl`)
*/ function $dcd28e347ddb21ab$var$getArrowCssDirection(side, align) {
if ((side === 'top' || side === 'right') && align === 'end') return 'rtl';
if ((side === 'bottom' || side === 'left') && align !== 'end') return 'rtl';
return 'ltr';
}
/**
* Gets the opposite side of a given side (ie. top => bottom, left => right, …)
*/ function $dcd28e347ddb21ab$var$getOppositeSide(side) {
const oppositeSides = {
top: 'bottom',
right: 'left',
bottom: 'top',
left: 'right'
};
return oppositeSides[side];
}
/**
* Creates a new rect (`ClientRect`) based on a given one but contracted by
* a given amout on each side.
*/ function $dcd28e347ddb21ab$var$getContractedRect(rect, amount) {
return DOMRect.fromRect({
width: rect.width - amount * 2,
height: rect.height - amount * 2,
x: rect.left + amount,
y: rect.top + amount
});
}
/**
* Gets collisions for each side of a rect (top, right, bottom, left)
*/ function $dcd28e347ddb21ab$var$getCollisions(/** The rect to test collisions against */ rect, /** The rect which represents the boundaries for collision checks */ collisionBoundariesRect) {
return {
top: rect.top < collisionBoundariesRect.top,
right: rect.right > collisionBoundariesRect.right,
bottom: rect.bottom > collisionBoundariesRect.bottom,
left: rect.left < collisionBoundariesRect.left
};
}
export {$dcd28e347ddb21ab$export$d3e7649885811a7d as getPlacementData, $dcd28e347ddb21ab$export$36f0086da09c4b9f as SIDE_OPTIONS, $dcd28e347ddb21ab$export$3671ffab7b302fc9 as ALIGN_OPTIONS};
//# sourceMappingURL=index.module.js.map

5

package.json
{
"name": "@radix-ui/popper",
"version": "0.1.0",
"version": "0.1.1-rc.1",
"license": "MIT",

@@ -29,3 +29,4 @@ "source": "src/index.ts",

"url": "https://github.com/radix-ui/primitives/issues"
}
},
"stableVersion": "0.1.0"
}

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc