UNPKG

@nex-ui/react

Version:

🎉 A beautiful, modern, and reliable React component library.

98 lines (95 loc) • 2.95 kB
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 };