1
0
mirror of https://github.com/Sonarr/Sonarr.git synced 2024-10-29 23:12:39 +01:00

Link polymorphic static typing

This commit is contained in:
Treycos 2024-08-26 02:21:50 +02:00 committed by GitHub
parent ae7b187e41
commit a2e06e9e65
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -1,96 +1,89 @@
import classNames from 'classnames'; import classNames from 'classnames';
import React, { import React, {
ComponentClass, ComponentPropsWithoutRef,
FunctionComponent, ElementType,
SyntheticEvent, SyntheticEvent,
useCallback, useCallback,
} from 'react'; } from 'react';
import { Link as RouterLink } from 'react-router-dom'; import { Link as RouterLink } from 'react-router-dom';
import styles from './Link.css'; import styles from './Link.css';
interface ReactRouterLinkProps { export type LinkProps<C extends ElementType = 'button'> =
to?: string; ComponentPropsWithoutRef<C> & {
} component?: C;
export interface LinkProps extends React.HTMLProps<HTMLAnchorElement> {
className?: string;
component?:
| string
| FunctionComponent<LinkProps>
| ComponentClass<LinkProps, unknown>;
to?: string; to?: string;
target?: string; target?: string;
isDisabled?: boolean; isDisabled?: LinkProps<C>['disabled'];
noRouter?: boolean; noRouter?: boolean;
onPress?(event: SyntheticEvent): void; onPress?(event: SyntheticEvent): void;
} };
function Link(props: LinkProps) {
const { export default function Link<C extends ElementType = 'button'>({
className, className,
component = 'button', component,
to, to,
target, target,
type, type,
isDisabled, isDisabled,
noRouter = false, noRouter,
onPress, onPress,
...otherProps ...otherProps
} = props; }: LinkProps<C>) {
const Component = component || 'button';
const onClick = useCallback( const onClick = useCallback(
(event: SyntheticEvent) => { (event: SyntheticEvent) => {
if (!isDisabled && onPress) { if (isDisabled) {
onPress(event); return;
} }
onPress?.(event);
}, },
[isDisabled, onPress] [isDisabled, onPress]
); );
const linkProps: React.HTMLProps<HTMLAnchorElement> & ReactRouterLinkProps = { const linkClass = classNames(
target,
};
let el = component;
if (to) {
if (/\w+?:\/\//.test(to)) {
el = 'a';
linkProps.href = to;
linkProps.target = target || '_blank';
linkProps.rel = 'noreferrer';
} else if (noRouter) {
el = 'a';
linkProps.href = to;
linkProps.target = target || '_self';
} else {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
el = RouterLink;
linkProps.to = `${window.Sonarr.urlBase}/${to.replace(/^\//, '')}`;
linkProps.target = target;
}
}
if (el === 'button' || el === 'input') {
linkProps.type = type || 'button';
linkProps.disabled = isDisabled;
}
linkProps.className = classNames(
className, className,
styles.link, styles.link,
to && styles.to, to && styles.to,
isDisabled && 'isDisabled' isDisabled && 'isDisabled'
); );
const elementProps = { if (to) {
...otherProps, const toLink = /\w+?:\/\//.test(to);
type,
...linkProps,
};
elementProps.onClick = onClick; if (toLink || noRouter) {
return (
return React.createElement(el, elementProps); <a
href={to}
target={target || (toLink ? '_blank' : '_self')}
rel={toLink ? 'noreferrer' : undefined}
className={linkClass}
onClick={onClick}
{...otherProps}
/>
);
} }
export default Link; return (
<RouterLink
to={`${window.Sonarr.urlBase}/${to.replace(/^\//, '')}`}
target={target}
className={linkClass}
onClick={onClick}
{...otherProps}
/>
);
}
return (
<Component
type={type || 'button'}
target={target}
className={linkClass}
disabled={isDisabled}
onClick={onClick}
{...otherProps}
/>
);
}