1 |
"use client"; |
2 |
|
3 |
import { useRouterContext } from "@/contexts/RouterContext"; |
4 |
import NextLink from "next/link"; |
5 |
import { usePathname } from "next/navigation"; |
6 |
import { ComponentProps, FC, KeyboardEvent, MouseEvent } from "react"; |
7 |
|
8 |
type LinkProps = Omit<ComponentProps<typeof NextLink>, "as"> & { |
9 |
nextLink?: boolean; |
10 |
as?: keyof JSX.IntrinsicElements | FC; |
11 |
}; |
12 |
|
13 |
export default function Link({ |
14 |
nextLink = true, |
15 |
as = NextLink as unknown as keyof JSX.IntrinsicElements, |
16 |
onClick, |
17 |
onKeyUp, |
18 |
href, |
19 |
children, |
20 |
...props |
21 |
}: LinkProps) { |
22 |
const { setIsChanging } = useRouterContext(); |
23 |
const pathname = usePathname(); |
24 |
const Component = ((nextLink ? NextLink : as) ?? "a") as "a"; |
25 |
const propsToPass = { |
26 |
...props, |
27 |
href, |
28 |
} as ComponentProps<typeof NextLink>; |
29 |
|
30 |
if (nextLink) { |
31 |
propsToPass.as = as as unknown as keyof JSX.IntrinsicElements; |
32 |
} |
33 |
|
34 |
const stringHref = href.toString(); |
35 |
|
36 |
const onNavigate = () => { |
37 |
const pos = stringHref.indexOf("?"); |
38 |
|
39 |
if ( |
40 |
!stringHref.startsWith("https://") && |
41 |
!stringHref.startsWith("http://") && |
42 |
pathname !== |
43 |
stringHref |
44 |
.substring(0, pos === -1 ? undefined : pos) |
45 |
.replace(/\/+/g, "/") |
46 |
.replace(/\/$/g, "") |
47 |
) { |
48 |
setIsChanging(true); |
49 |
} |
50 |
}; |
51 |
|
52 |
return ( |
53 |
<Component |
54 |
href={href as string} |
55 |
{...props} |
56 |
onClick={event => { |
57 |
event.stopPropagation(); |
58 |
onClick?.(event as MouseEvent<any, any>); |
59 |
onNavigate(); |
60 |
}} |
61 |
onKeyUp={event => { |
62 |
onKeyUp?.(event as KeyboardEvent<any>); |
63 |
|
64 |
if (event.key === "Enter") { |
65 |
onNavigate(); |
66 |
} |
67 |
}} |
68 |
> |
69 |
{children} |
70 |
</Component> |
71 |
); |
72 |
} |