90 lines
1.9 KiB
TypeScript
90 lines
1.9 KiB
TypeScript
"use client"
|
|
import NextLink from "next/link"
|
|
import { usePathname, useRouter } from "next/navigation"
|
|
import { startTransition, useCallback } from "react"
|
|
|
|
import useRouterTransitionStore from "@/stores/router-transition"
|
|
import useTrackingStore from "@/stores/tracking"
|
|
|
|
import { trackClick, trackPageViewStart } from "@/utils/tracking"
|
|
|
|
import { linkVariants } from "./variants"
|
|
|
|
import type { LinkProps } from "./link"
|
|
|
|
export default function Link({
|
|
active,
|
|
className,
|
|
color,
|
|
href,
|
|
partialMatch = false,
|
|
textDecoration,
|
|
size,
|
|
scroll = true,
|
|
prefetch,
|
|
variant,
|
|
trackingId,
|
|
onClick,
|
|
...props
|
|
}: LinkProps) {
|
|
const currentPageSlug = usePathname()
|
|
const { setInitialPageLoadTime } = useTrackingStore()
|
|
let isActive = active || currentPageSlug === href
|
|
|
|
if (partialMatch && !isActive) {
|
|
isActive = currentPageSlug === href
|
|
}
|
|
|
|
const classNames = linkVariants({
|
|
active: isActive,
|
|
className,
|
|
textDecoration,
|
|
color,
|
|
size,
|
|
variant,
|
|
})
|
|
|
|
const router = useRouter()
|
|
|
|
const startRouterTransition = useRouterTransitionStore(
|
|
(state) => state.startRouterTransition
|
|
)
|
|
|
|
const trackClickById = useCallback(() => {
|
|
if (trackingId) {
|
|
trackClick(trackingId)
|
|
}
|
|
}, [trackingId])
|
|
|
|
return (
|
|
<NextLink
|
|
scroll={scroll}
|
|
prefetch={prefetch}
|
|
className={classNames}
|
|
onClick={(e) => {
|
|
if (onClick) {
|
|
onClick(e)
|
|
}
|
|
if (trackingId) {
|
|
trackClickById()
|
|
}
|
|
if (props.target === "_blank") {
|
|
// If link should open in new tab, we don't want to
|
|
// track navigation nor start a router transition.
|
|
return
|
|
}
|
|
e.preventDefault()
|
|
setInitialPageLoadTime(Date.now())
|
|
trackPageViewStart()
|
|
startTransition(() => {
|
|
startRouterTransition()
|
|
router.push(href, { scroll })
|
|
})
|
|
}}
|
|
href={href}
|
|
id={trackingId}
|
|
{...props}
|
|
/>
|
|
)
|
|
}
|