@nex-ui/react
Version:
🎉 A beautiful, modern, and reliable React component library.
98 lines (95 loc) • 2.95 kB
JavaScript
import { isPlainObject } from '@nex-ui/utils';
import { getElementRects } from './getElementRects.mjs';
import { computeCoordinatesByPlacement } from './computeCoordinatesByPlacement.mjs';
import { flip } from './middleware/flip.mjs';
import { shift } from './middleware/shift.mjs';
import { arrow } from './middleware/arrow.mjs';
import { offset } from './middleware/offset.mjs';
function computePosition(reference, popper, options) {
const { placement = 'bottom', shift: shiftOption, offset: offsetOption, flip: flipOption, arrow: arrowOption = false } = options ?? {};
const middlewareOptions = [
[
flipOption,
flip
],
[
shiftOption,
shift
],
[
arrowOption,
arrow
],
[
offsetOption,
offset
]
];
const middlewareList = middlewareOptions.filter(([option])=>option !== false).map(([option, fn])=>fn(option));
const rects = getElementRects(reference, popper);
const coordinates = computeCoordinatesByPlacement(rects, placement);
let middlewareData = {};
let state = {
rects: {
popper: {
...rects.popper,
x: coordinates.x,
y: coordinates.y
},
reference: {
...rects.reference
}
},
elements: {
reference,
popper
},
placement,
middlewareData,
initialPlacement: placement
};
for(let i = 0; i < middlewareList.length; i++){
const middleware = middlewareList[i];
let nextX, nextY;
const { x, y, overrides, data } = middleware.fn(state);
nextX = x;
nextY = y;
if (data) {
middlewareData = {
...middlewareData,
[middleware.name]: {
...middlewareData[middleware.name],
...data
}
};
}
let placementOverride;
if (isPlainObject(overrides)) {
if (overrides?.placement) {
placementOverride = overrides?.placement;
({ x: nextX, y: nextY } = computeCoordinatesByPlacement(rects, placementOverride));
}
i--;
}
state = {
...state,
rects: {
...state.rects,
popper: {
...state.rects.popper,
x: nextX ?? state.rects.popper.x,
y: nextY ?? state.rects.popper.y
}
},
middlewareData,
placement: placementOverride ?? state.placement
};
}
return {
x: state.rects.popper.x,
y: state.rects.popper.y,
placement: state.placement,
middlewareData: state.middlewareData
};
}
export { computePosition };