Files
big-agi/components/Link.tsx
T
Enrico Ros d2a7082564 Add Application
NextJS, React, JoyUI (like MUI), application for self-hosted
Chat-like GPT use cases. Includes streaming of responses from
the Vercel edge runtimes.
2023-03-19 00:42:23 -07:00

110 lines
3.0 KiB
TypeScript

import * as React from 'react';
import { useRouter } from 'next/router';
import NextLink, { LinkProps as NextLinkProps } from 'next/link';
import clsx from 'clsx';
import { Link as MuiLink, LinkProps as MuiLinkProps, styled } from '@mui/joy';
// Add support for the sx prop for consistency with the other branches.
const Anchor = styled('a')({});
interface NextLinkComposedProps
extends Omit<React.AnchorHTMLAttributes<HTMLAnchorElement>, 'href'>,
Omit<NextLinkProps, 'href' | 'as' | 'passHref' | 'onMouseEnter' | 'onClick' | 'onTouchStart'> {
to: NextLinkProps['href'];
linkAs?: NextLinkProps['as'];
}
const NextLinkComposed = React.forwardRef<HTMLAnchorElement, NextLinkComposedProps>(
function NextLinkComposed(props, ref) {
const {
to,
linkAs,
replace,
scroll,
shallow,
prefetch,
legacyBehavior = true,
locale,
...other
} = props;
return (
<NextLink
href={to}
prefetch={prefetch}
as={linkAs}
replace={replace}
scroll={scroll}
shallow={shallow}
passHref
locale={locale}
legacyBehavior={legacyBehavior}
>
<Anchor ref={ref} {...other} />
</NextLink>
);
},
);
export type LinkProps = {
activeClassName?: string;
as?: NextLinkProps['as'];
href: NextLinkProps['href'];
linkAs?: NextLinkProps['as']; // Useful when the as prop is shallow by styled().
noLinkStyle?: boolean;
} & Omit<NextLinkComposedProps, 'to' | 'linkAs' | 'href'> &
Omit<MuiLinkProps, 'href'>;
// A styled version of the Next.js Link component:
// https://nextjs.org/docs/api-reference/next/link
export const Link = React.forwardRef<HTMLAnchorElement, LinkProps>(function Link(props, ref) {
const {
activeClassName = 'active',
as,
className: classNameProps,
href,
legacyBehavior,
linkAs: linkAsProp,
locale,
noLinkStyle,
prefetch,
replace,
role, // Link don't have roles.
scroll,
shallow,
...other
} = props;
const router = useRouter();
const pathname = typeof href === 'string' ? href : href.pathname;
const className = clsx(classNameProps, {
[activeClassName]: router.pathname === pathname && activeClassName,
});
// external links: MuiLink (default) or 'a'
const isExternal = typeof href === 'string' && (href.indexOf('http') === 0 || href.indexOf('mailto:') === 0);
if (isExternal)
return !noLinkStyle
? <MuiLink className={className} href={href} ref={ref} {...other} />
: <Anchor className={className} href={href} ref={ref} {...other} />;
const linkAs = linkAsProp || as;
const nextjsProps = {
to: href,
linkAs,
replace,
scroll,
shallow,
prefetch,
legacyBehavior,
locale,
};
// internal (routed) links: MuiLink (default, over NextLinkComposed) or NextLinkComposed
return !noLinkStyle
? <MuiLink component={NextLinkComposed} className={className} ref={ref} {...nextjsProps} {...other} />
: <NextLinkComposed className={className} ref={ref} {...nextjsProps} {...other} />;
});