Files
sori.studio/lib/markdown-slash-menu-position.js

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)
}
}