You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
89 lines
2.4 KiB
89 lines
2.4 KiB
import type { CSSProperties, MouseEvent } from 'react'
|
|
import { useState } from 'react'
|
|
|
|
import isUndefined from 'lodash/isUndefined'
|
|
|
|
import { useToggle } from './useToggle'
|
|
|
|
type TooltipParams = {
|
|
anchorId?: string,
|
|
horizontalPosition?: 'left' | 'center' | 'right',
|
|
indent?: number,
|
|
tooltipText: string,
|
|
verticalPosition?: 'top' | 'bottom',
|
|
}
|
|
|
|
export const useTooltip = () => {
|
|
const [stateTooltipStyle, setTooltipStyle] = useState<CSSProperties>({})
|
|
const [stateAnchorId, setAnchorId] = useState<string | null>(null)
|
|
const [stateTooltipText, setTooltipText] = useState('')
|
|
|
|
const {
|
|
close: hideTooltip,
|
|
isOpen: isTooltipShown,
|
|
open: showTooltip,
|
|
} = useToggle()
|
|
|
|
const onMouseOver = ({
|
|
anchorId,
|
|
horizontalPosition = 'center',
|
|
indent = 10,
|
|
tooltipText,
|
|
verticalPosition = 'bottom',
|
|
}: TooltipParams) => (e: MouseEvent<HTMLElement>) => {
|
|
const target = e.target as HTMLElement
|
|
|
|
if (anchorId && target.id !== anchorId) return
|
|
|
|
const {
|
|
left,
|
|
right,
|
|
top,
|
|
} = target.getBoundingClientRect()
|
|
|
|
const coords: Partial<DOMRect> = {
|
|
top: verticalPosition === 'bottom'
|
|
? top + target.clientHeight + indent
|
|
: top - target.clientHeight - indent,
|
|
|
|
...(horizontalPosition === 'center' && { left: left + target.clientWidth / 2 }),
|
|
...(horizontalPosition === 'left' && { left }),
|
|
...(horizontalPosition === 'right' && { right }),
|
|
}
|
|
|
|
const tooltipStyle: CSSProperties = {
|
|
left: !isUndefined(coords.left) ? `${coords.left}px` : 'auto',
|
|
position: 'fixed',
|
|
right: !isUndefined(coords.right) ? `${window.innerWidth - coords.right}px` : 'auto',
|
|
top: `${coords.top}px`,
|
|
zIndex: 999,
|
|
|
|
...(horizontalPosition === 'center' && { transform: 'translateX: (-50%)' }),
|
|
...(verticalPosition === 'top' && { transform: 'translateY: (-50%)' }),
|
|
...(horizontalPosition === 'center' && verticalPosition === 'top' && { transform: 'translate: (-50%, -50%)' }),
|
|
}
|
|
|
|
if (anchorId) {
|
|
setAnchorId(anchorId)
|
|
}
|
|
|
|
setTooltipStyle(tooltipStyle)
|
|
showTooltip()
|
|
setTooltipText(tooltipText)
|
|
}
|
|
|
|
const onMouseLeave = () => {
|
|
hideTooltip()
|
|
setAnchorId(null)
|
|
setTooltipStyle({})
|
|
}
|
|
|
|
return {
|
|
anchorId: stateAnchorId,
|
|
isTooltipShown,
|
|
onMouseLeave,
|
|
onMouseOver,
|
|
tooltipStyle: stateTooltipStyle,
|
|
tooltipText: stateTooltipText,
|
|
}
|
|
}
|
|
|