mirror of
https://github.com/supabase/supabase.git
synced 2026-10-10 20:05:06 +03:00
93 lines
2.7 KiB
TypeScript
93 lines
2.7 KiB
TypeScript
export type DockCorner = (typeof DOCK_CORNERS)[number]
|
|
|
|
export type DockPlacement = DockCorner | 'center'
|
|
|
|
export type DockArrowKey = (typeof DOCK_ARROW_KEYS)[number]
|
|
|
|
export interface Point {
|
|
x: number
|
|
y: number
|
|
}
|
|
|
|
interface CornerParts {
|
|
vertical: 'top' | 'bottom'
|
|
horizontal: 'left' | 'right'
|
|
}
|
|
|
|
export const DOCK_CORNERS = ['top-left', 'top-right', 'bottom-left', 'bottom-right'] as const
|
|
|
|
export const DEFAULT_DOCK_CORNER: DockCorner = 'bottom-right'
|
|
|
|
export const DOCK_ARROW_KEYS = ['ArrowLeft', 'ArrowRight', 'ArrowUp', 'ArrowDown'] as const
|
|
|
|
const CENTER_BAND_SHARE = 1 / 3
|
|
|
|
const CORNER_PARTS: Record<DockCorner, CornerParts> = {
|
|
'top-left': { vertical: 'top', horizontal: 'left' },
|
|
'top-right': { vertical: 'top', horizontal: 'right' },
|
|
'bottom-left': { vertical: 'bottom', horizontal: 'left' },
|
|
'bottom-right': { vertical: 'bottom', horizontal: 'right' },
|
|
}
|
|
|
|
export const getNearestPlacement = ({
|
|
point,
|
|
velocity,
|
|
viewport,
|
|
canCenter,
|
|
}: {
|
|
point: Point
|
|
velocity: Point
|
|
viewport: { width: number; height: number }
|
|
canCenter: boolean
|
|
}): DockPlacement => {
|
|
const x = point.x + project(velocity.x)
|
|
const y = point.y + project(velocity.y)
|
|
const isInCenterBand = Math.abs(x - viewport.width / 2) < (viewport.width * CENTER_BAND_SHARE) / 2
|
|
if (canCenter && isInCenterBand && y >= viewport.height / 2) return 'center'
|
|
|
|
return toCorner({
|
|
vertical: y < viewport.height / 2 ? 'top' : 'bottom',
|
|
horizontal: x < viewport.width / 2 ? 'left' : 'right',
|
|
})
|
|
}
|
|
|
|
export const parseStoredCorner = (value: unknown): DockCorner =>
|
|
DOCK_CORNERS.find((corner) => corner === value) ?? DEFAULT_DOCK_CORNER
|
|
|
|
export const getAdjacentPlacement = ({
|
|
placement,
|
|
key,
|
|
canCenter,
|
|
}: {
|
|
placement: DockPlacement
|
|
key: DockArrowKey
|
|
canCenter: boolean
|
|
}): DockPlacement => {
|
|
if (placement === 'center') {
|
|
if (key === 'ArrowLeft') return 'bottom-left'
|
|
if (key === 'ArrowRight') return 'bottom-right'
|
|
return placement
|
|
}
|
|
const isTowardCenter =
|
|
(placement === 'bottom-left' && key === 'ArrowRight') ||
|
|
(placement === 'bottom-right' && key === 'ArrowLeft')
|
|
if (canCenter && isTowardCenter) return 'center'
|
|
|
|
const { vertical, horizontal } = CORNER_PARTS[placement]
|
|
|
|
switch (key) {
|
|
case 'ArrowLeft':
|
|
return toCorner({ vertical, horizontal: 'left' })
|
|
case 'ArrowRight':
|
|
return toCorner({ vertical, horizontal: 'right' })
|
|
case 'ArrowUp':
|
|
return toCorner({ vertical: 'top', horizontal })
|
|
case 'ArrowDown':
|
|
return toCorner({ vertical: 'bottom', horizontal })
|
|
}
|
|
}
|
|
|
|
const project = (velocity: number, rate = 0.999) => ((velocity / 1000) * rate) / (1 - rate)
|
|
|
|
const toCorner = ({ vertical, horizontal }: CornerParts): DockCorner => `${vertical}-${horizontal}`
|