mirror of
https://github.com/Wei-Shaw/sub2api.git
synced 2026-10-31 08:25:35 +00:00
57 lines
1.9 KiB
TypeScript
57 lines
1.9 KiB
TypeScript
export interface FloatingPanelPosition {
|
|
top: number | null
|
|
bottom: number | null
|
|
left: number
|
|
width: number
|
|
maxHeight: number
|
|
}
|
|
|
|
export interface FloatingPanelOptions {
|
|
viewportPadding?: number
|
|
gap?: number
|
|
maxWidth?: number
|
|
maxHeightRatio?: number
|
|
mobileBreakpoint?: number
|
|
minComfortableHeight?: number
|
|
}
|
|
|
|
/**
|
|
* 计算挂载到 body 的浮层位置,避免触发按钮靠近视口边缘时浮层被挤到屏幕外。
|
|
*/
|
|
export const getFloatingPanelPosition = (
|
|
triggerRect: Pick<DOMRect, 'top' | 'right' | 'bottom'>,
|
|
viewportWidth: number,
|
|
viewportHeight: number,
|
|
options: FloatingPanelOptions = {}
|
|
): FloatingPanelPosition => {
|
|
const viewportPadding = options.viewportPadding ?? 16
|
|
const gap = options.gap ?? 8
|
|
const maxWidth = options.maxWidth ?? 320
|
|
const maxHeightRatio = options.maxHeightRatio ?? 0.7
|
|
const mobileBreakpoint = options.mobileBreakpoint ?? 768
|
|
const minComfortableHeight = options.minComfortableHeight ?? 240
|
|
|
|
const availableWidth = Math.max(0, viewportWidth - viewportPadding * 2)
|
|
const width = Math.min(maxWidth, availableWidth)
|
|
const left = viewportWidth < mobileBreakpoint
|
|
? viewportPadding
|
|
: Math.max(
|
|
viewportPadding,
|
|
Math.min(triggerRect.right - width, viewportWidth - width - viewportPadding)
|
|
)
|
|
|
|
const preferredMaxHeight = Math.max(0, Math.floor(viewportHeight * maxHeightRatio))
|
|
const spaceBelow = Math.max(0, viewportHeight - triggerRect.bottom - gap - viewportPadding)
|
|
const spaceAbove = Math.max(0, triggerRect.top - gap - viewportPadding)
|
|
const openAbove = spaceBelow < Math.min(minComfortableHeight, preferredMaxHeight) && spaceAbove > spaceBelow
|
|
const maxHeight = Math.min(preferredMaxHeight, openAbove ? spaceAbove : spaceBelow)
|
|
|
|
return {
|
|
top: openAbove ? null : triggerRect.bottom + gap,
|
|
bottom: openAbove ? viewportHeight - triggerRect.top + gap : null,
|
|
left,
|
|
width,
|
|
maxHeight
|
|
}
|
|
}
|