index.tsx (3133B)
1 import { Link as MuiLink } from '@mui/material'; 2 import { styled } from '@mui/material/styles'; 3 import { clsx } from 'clsx'; 4 import NextLink from 'next/link'; 5 import { useRouter } from 'next/router'; 6 import * as React from 'react'; 7 8 import type { LinkProps as MuiLinkProps } from '@mui/material/Link'; 9 import type { LinkProps as NextLinkProps } from 'next/link'; 10 11 // Add support for the sx prop for consistency with the other branches. 12 const Anchor = styled('a')({}); 13 14 interface NextLinkComposedProps 15 extends Omit<React.AnchorHTMLAttributes<HTMLAnchorElement>, 'href'>, 16 Omit< 17 NextLinkProps, 18 'href' | 'as' | 'onClick' | 'onMouseEnter' | 'onTouchStart' 19 > { 20 to: NextLinkProps['href']; 21 linkAs?: NextLinkProps['as']; 22 } 23 24 export const NextLinkComposed = React.forwardRef< 25 HTMLAnchorElement, 26 NextLinkComposedProps 27 >(function NextLinkComposed(props, ref) { 28 const { 29 to, 30 linkAs, 31 replace, 32 scroll, 33 shallow, 34 prefetch, 35 legacyBehavior = true, 36 locale, 37 ...other 38 } = props; 39 40 return ( 41 <NextLink 42 href={to} 43 prefetch={prefetch} 44 as={linkAs} 45 replace={replace} 46 scroll={scroll} 47 shallow={shallow} 48 passHref 49 locale={locale} 50 legacyBehavior={legacyBehavior} 51 > 52 <Anchor ref={ref} {...other} /> 53 </NextLink> 54 ); 55 }); 56 57 export type LinkProps = { 58 activeClassName?: string; 59 as?: NextLinkProps['as']; 60 href: NextLinkProps['href']; 61 linkAs?: NextLinkProps['as']; // Useful when the as prop is shallow by styled(). 62 noLinkStyle?: boolean; 63 } & Omit<NextLinkComposedProps, 'to' | 'linkAs' | 'href'> & 64 Omit<MuiLinkProps, 'href'>; 65 66 // A styled version of the Next.js Link component: 67 // https://nextjs.org/docs/api-reference/next/link 68 const Link = React.forwardRef<HTMLAnchorElement, LinkProps>( 69 function Link(props, ref) { 70 const { 71 activeClassName = 'active', 72 as, 73 className: classNameProps, 74 href, 75 legacyBehavior, 76 linkAs: linkAsProp, 77 locale, 78 noLinkStyle, 79 prefetch, 80 replace, 81 // eslint-disable-next-line @typescript-eslint/no-unused-vars 82 role, // Link don't have roles. 83 scroll, 84 shallow, 85 ...other 86 } = props; 87 88 const router = useRouter(); 89 const pathname = typeof href === 'string' ? href : href.pathname; 90 const className = clsx(classNameProps, { 91 [activeClassName]: router.pathname === pathname && activeClassName, 92 }); 93 94 const isExternal = 95 typeof href === 'string' && 96 (href.indexOf('http') === 0 || href.indexOf('mailto:') === 0); 97 98 if (isExternal) { 99 if (noLinkStyle) { 100 return ( 101 <Anchor className={className} href={href} ref={ref} {...other} /> 102 ); 103 } 104 105 return <MuiLink className={className} href={href} ref={ref} {...other} />; 106 } 107 108 const linkAs = linkAsProp || as; 109 const nextjsProps = { 110 to: href, 111 linkAs, 112 replace, 113 scroll, 114 shallow, 115 prefetch, 116 legacyBehavior, 117 locale, 118 }; 119 120 if (noLinkStyle) { 121 return ( 122 <NextLinkComposed 123 className={className} 124 ref={ref} 125 {...nextjsProps} 126 {...other} 127 /> 128 ); 129 } 130 131 return ( 132 <MuiLink 133 component={NextLinkComposed} 134 className={className} 135 ref={ref} 136 {...nextjsProps} 137 {...other} 138 /> 139 ); 140 }, 141 ); 142 143 export default Link;