Files
standardnotes-app-web/packages/web/src/javascripts/Components/Popover/GetPositionedPopoverStyles.ts
2022-07-21 02:20:14 +05:30

55 lines
1.8 KiB
TypeScript

import { CSSProperties } from 'react'
import { PopoverAlignment, PopoverSide } from './Types'
import { OppositeSide, checkCollisions, getNonCollidingSide, getNonCollidingAlignment } from './Utils/Collisions'
import { getPositionedPopoverRect } from './Utils/Rect'
const getStylesFromRect = (rect: DOMRect): CSSProperties => {
return {
willChange: 'transform',
transform: `translate(${rect.x}px, ${rect.y}px)`,
}
}
type Options = {
align: PopoverAlignment
anchorRect?: DOMRect
documentRect: DOMRect
popoverRect?: DOMRect
side: PopoverSide
}
export const getPositionedPopoverStyles = ({
align,
anchorRect,
documentRect,
popoverRect,
side,
}: Options): [CSSProperties | null, PopoverSide, PopoverAlignment] => {
if (!popoverRect || !anchorRect) {
return [null, side, align]
}
const matchesMediumBreakpoint = matchMedia('(min-width: 768px)').matches
if (!matchesMediumBreakpoint) {
return [null, side, align]
}
const rectForPreferredSide = getPositionedPopoverRect(popoverRect, anchorRect, side, align)
const preferredSideRectCollisions = checkCollisions(rectForPreferredSide, documentRect)
const oppositeSide = OppositeSide[side]
const rectForOppositeSide = getPositionedPopoverRect(popoverRect, anchorRect, oppositeSide, align)
const oppositeSideRectCollisions = checkCollisions(rectForOppositeSide, documentRect)
const finalSide = getNonCollidingSide(side, preferredSideRectCollisions, oppositeSideRectCollisions)
const finalAlignment = getNonCollidingAlignment(finalSide, align, preferredSideRectCollisions, {
popoverRect,
buttonRect: anchorRect,
documentRect,
})
const finalPositionedRect = getPositionedPopoverRect(popoverRect, anchorRect, finalSide, finalAlignment)
return [getStylesFromRect(finalPositionedRect), finalSide, finalAlignment]
}