mirror of
https://github.com/EnixCoda/Gitako.git
synced 2026-03-11 08:54:44 +00:00
76 lines
2.3 KiB
TypeScript
76 lines
2.3 KiB
TypeScript
import iconURL from 'assets/icons/Gitako.png'
|
|
import { useConfigs } from 'containers/ConfigsContext'
|
|
import * as React from 'react'
|
|
import { useDebounce, useWindowSize } from 'react-use'
|
|
import { cx } from 'utils/cx'
|
|
import { Icon } from './Icon'
|
|
import { useResizeHandler } from './ResizeHandler'
|
|
|
|
type Props = {
|
|
error?: string | null
|
|
className?: React.HTMLAttributes<HTMLButtonElement>['className']
|
|
onHover?: React.HTMLAttributes<HTMLButtonElement>['onMouseEnter']
|
|
onClick?: (e: PointerEvent) => void
|
|
}
|
|
|
|
const buttonHeight = 42
|
|
|
|
function getSafeDistance(y: number, height: number) {
|
|
return Math.max(0, Math.min(y, height - buttonHeight))
|
|
}
|
|
|
|
export function ToggleShowButton({ error, className, onClick, onHover }: Props) {
|
|
const ref = React.useRef<HTMLDivElement>(null)
|
|
const config = useConfigs()
|
|
const [distance, setDistance] = React.useState(config.value.toggleButtonVerticalDistance)
|
|
const { height } = useWindowSize()
|
|
React.useEffect(() => {
|
|
// make sure it is inside viewport
|
|
const safeDistance = getSafeDistance(distance, height)
|
|
if (safeDistance !== distance) setDistance(safeDistance)
|
|
}, [height, distance])
|
|
|
|
// updating context
|
|
useDebounce(
|
|
() => config.onChange({ toggleButtonVerticalDistance: distance }), // too slow
|
|
100,
|
|
[distance],
|
|
)
|
|
|
|
React.useEffect(() => {
|
|
if (ref.current) {
|
|
ref.current.style.top = distance + 'px'
|
|
}
|
|
}, [])
|
|
const { onPointerDown } = useResizeHandler(
|
|
[distance, distance],
|
|
([, y]) => {
|
|
const distance = getSafeDistance(y, height)
|
|
setDistance(distance)
|
|
if (ref.current) {
|
|
ref.current.style.top = distance + 'px'
|
|
}
|
|
},
|
|
{ onClick },
|
|
)
|
|
|
|
return (
|
|
<div ref={ref} className={cx('gitako-toggle-show-button-wrapper', className)}>
|
|
<button
|
|
className={cx('gitako-toggle-show-button', {
|
|
error,
|
|
})}
|
|
onPointerEnter={onHover}
|
|
onPointerDown={onPointerDown}
|
|
title={'Gitako (draggable)'}
|
|
>
|
|
{config.value.toggleButtonContent === 'octoface' ? (
|
|
<Icon className={'octoface-icon'} type={'octoface'} />
|
|
) : (
|
|
<img className={'tentacle'} draggable={false} src={iconURL} />
|
|
)}
|
|
</button>
|
|
{error && <span className={'error-message'}>{error}</span>}
|
|
</div>
|
|
)
|
|
}
|