65 lines
2.1 KiB
TypeScript
65 lines
2.1 KiB
TypeScript
import { MAX_MENU_SIZE_MULTIPLIER, MENU_MARGIN_FROM_APP_BORDER } from '@/Constants'
|
|
|
|
export type SubmenuStyle = {
|
|
top?: number | 'auto'
|
|
right?: number | 'auto'
|
|
bottom: number | 'auto'
|
|
left?: number | 'auto'
|
|
visibility?: 'hidden' | 'visible'
|
|
maxHeight: number | 'auto'
|
|
}
|
|
|
|
export const calculateSubmenuStyle = (
|
|
button: HTMLButtonElement | null,
|
|
menu?: HTMLDivElement | HTMLMenuElement | null,
|
|
): SubmenuStyle | undefined => {
|
|
const defaultFontSize = window.getComputedStyle(document.documentElement).fontSize
|
|
const maxChangeEditorMenuSize = parseFloat(defaultFontSize) * MAX_MENU_SIZE_MULTIPLIER
|
|
const { clientWidth, clientHeight } = document.documentElement
|
|
const buttonRect = button?.getBoundingClientRect()
|
|
const buttonParentRect = button?.parentElement?.getBoundingClientRect()
|
|
const menuBoundingRect = menu?.getBoundingClientRect()
|
|
const footerElementRect = document.getElementById('footer-bar')?.getBoundingClientRect()
|
|
const footerHeightInPx = footerElementRect?.height ?? 0
|
|
|
|
let position: SubmenuStyle = {
|
|
bottom: 'auto',
|
|
maxHeight: 'auto',
|
|
}
|
|
|
|
if (buttonRect && buttonParentRect) {
|
|
let positionBottom = clientHeight - buttonRect.bottom - buttonRect.height / 2
|
|
|
|
if (positionBottom < footerHeightInPx) {
|
|
positionBottom = footerHeightInPx + MENU_MARGIN_FROM_APP_BORDER
|
|
}
|
|
|
|
position = {
|
|
bottom: positionBottom,
|
|
visibility: 'hidden',
|
|
maxHeight: 'auto',
|
|
}
|
|
|
|
if (buttonRect.right + maxChangeEditorMenuSize > clientWidth) {
|
|
position.right = clientWidth - buttonRect.left
|
|
} else {
|
|
position.left = buttonRect.right
|
|
}
|
|
}
|
|
|
|
if (menuBoundingRect?.height && buttonRect && position.bottom !== 'auto') {
|
|
position.visibility = 'visible'
|
|
|
|
if (menuBoundingRect.y < MENU_MARGIN_FROM_APP_BORDER) {
|
|
position.bottom = position.bottom + menuBoundingRect.y - MENU_MARGIN_FROM_APP_BORDER * 2
|
|
}
|
|
|
|
if (footerElementRect && menuBoundingRect.height > footerElementRect.y) {
|
|
position.bottom = footerElementRect.height + MENU_MARGIN_FROM_APP_BORDER
|
|
position.maxHeight = clientHeight - footerElementRect.height - MENU_MARGIN_FROM_APP_BORDER * 2
|
|
}
|
|
}
|
|
|
|
return position
|
|
}
|