Files
tuono/packages/tuono-router/src/components/Link.tsx
T

62 lines
1.3 KiB
TypeScript
Raw Normal View History

2024-12-23 11:43:04 +01:00
import type * as React from 'react'
2024-12-01 10:07:35 +01:00
import { useInView } from 'react-intersection-observer'
2024-07-11 21:43:38 +02:00
import { useRouter } from '../hooks/useRouter'
import useRoute from '../hooks/useRoute'
2024-12-23 11:43:04 +01:00
interface TuonoLinkProps extends React.AnchorHTMLAttributes<HTMLAnchorElement> {
/**
2024-12-23 11:43:04 +01:00
* If "true" the route gets loaded when the link enters the viewport.
* @default true
*/
preload?: boolean
2024-12-23 11:43:04 +01:00
/**
2024-12-23 11:43:04 +01:00
* If "false" the scroll offset will be kept across page navigation.
* @default true
*/
scroll?: boolean
}
2024-05-11 15:08:49 +02:00
export default function Link(
2024-12-23 11:43:04 +01:00
componentProps: TuonoLinkProps,
): React.JSX.Element {
2024-12-23 11:43:04 +01:00
const {
preload = true,
scroll = true,
children,
href,
onClick,
...rest
} = componentProps
2024-07-11 21:43:38 +02:00
const router = useRouter()
2024-12-23 11:43:04 +01:00
const route = useRoute(href)
const { ref } = useInView({
onChange(inView) {
if (inView && preload) route?.component.preload()
},
triggerOnce: true,
})
2024-07-11 21:43:38 +02:00
2024-12-23 11:43:04 +01:00
const handleTransition: React.MouseEventHandler<HTMLAnchorElement> = (
event,
) => {
event.preventDefault()
onClick?.(event)
2024-08-16 11:21:18 +02:00
2024-12-23 11:43:04 +01:00
if (href?.startsWith('#')) {
window.location.hash = href
2024-08-16 11:21:18 +02:00
return
}
2024-12-23 11:43:04 +01:00
router.push(href || '', { scroll })
2024-05-11 15:08:49 +02:00
}
2024-07-11 21:43:38 +02:00
2024-05-11 15:08:49 +02:00
return (
2024-12-23 11:43:04 +01:00
<a {...rest} href={href} ref={ref} onClick={handleTransition}>
{children}
2024-05-11 15:08:49 +02:00
</a>
)
}