56 lines
1.6 KiB
JavaScript
56 lines
1.6 KiB
JavaScript
export const DEFAULT_SLASH_MENU_HEIGHT = 280
|
|
export const DEFAULT_SLASH_MENU_WIDTH = 288
|
|
export const DEFAULT_SLASH_MENU_GAP = 4
|
|
export const DEFAULT_SLASH_MENU_PADDING = 8
|
|
|
|
/**
|
|
* 슬래시 메뉴 좌표를 뷰포트 안으로 보정한다.
|
|
* @param {Object} options - 위치 계산 옵션
|
|
* @param {number} options.top - 후보 top(px)
|
|
* @param {number} options.left - 후보 left(px)
|
|
* @param {number} options.anchorTop - 기준 요소 top(px)
|
|
* @param {number} options.menuHeight - 메뉴 높이(px)
|
|
* @param {number} options.menuWidth - 메뉴 너비(px)
|
|
* @param {number} options.viewportHeight - 뷰포트 높이(px)
|
|
* @param {number} options.viewportWidth - 뷰포트 너비(px)
|
|
* @param {number} [options.gap] - 기준 요소와 메뉴 간격(px)
|
|
* @param {number} [options.padding] - 뷰포트 안쪽 여백(px)
|
|
* @returns {{ top: number, left: number }} 보정된 좌표
|
|
*/
|
|
export const calculateSlashMenuPosition = ({
|
|
top,
|
|
left,
|
|
anchorTop,
|
|
menuHeight,
|
|
menuWidth,
|
|
viewportHeight,
|
|
viewportWidth,
|
|
gap = DEFAULT_SLASH_MENU_GAP,
|
|
padding = DEFAULT_SLASH_MENU_PADDING
|
|
}) => {
|
|
const viewportBottom = viewportHeight - padding
|
|
const viewportRight = viewportWidth - padding
|
|
let nextTop = top
|
|
|
|
if (nextTop + menuHeight > viewportBottom) {
|
|
const aboveTop = anchorTop - menuHeight - gap
|
|
|
|
if (aboveTop >= padding) {
|
|
nextTop = aboveTop
|
|
} else {
|
|
nextTop = Math.max(padding, viewportBottom - menuHeight)
|
|
}
|
|
}
|
|
|
|
let nextLeft = left
|
|
|
|
if (nextLeft + menuWidth > viewportRight) {
|
|
nextLeft = viewportRight - menuWidth
|
|
}
|
|
|
|
return {
|
|
top: nextTop,
|
|
left: Math.max(padding, nextLeft)
|
|
}
|
|
}
|