mirror of
https://github.com/hanzonet/explore.git
synced 2026-10-30 18:16:57 +00:00
* add more form fields and fix link props * extend select component to render custom item and add lg size to switch * fix build * fix button border radius * fix ts
116 lines
3.2 KiB
TypeScript
116 lines
3.2 KiB
TypeScript
import type { LinkProps as ChakraLinkProps } from '@chakra-ui/react';
|
|
import { Link as ChakraLink, LinkBox as ChakraLinkBox, LinkOverlay as ChakraLinkOverlay, Icon } from '@chakra-ui/react';
|
|
import NextLink from 'next/link';
|
|
import type { LinkProps as NextLinkProps } from 'next/link';
|
|
import React from 'react';
|
|
|
|
import ArrowIcon from 'icons/link_external.svg';
|
|
|
|
import { Skeleton } from './skeleton';
|
|
|
|
export const LinkExternalIcon = ({ color }: { color?: ChakraLinkProps['color'] }) => (
|
|
<Icon
|
|
boxSize={ 3 }
|
|
verticalAlign="middle"
|
|
color={ color ?? 'icon.externalLink' }
|
|
_groupHover={{
|
|
color: 'inherit',
|
|
}}
|
|
flexShrink={ 0 }
|
|
>
|
|
<ArrowIcon/>
|
|
</Icon>
|
|
);
|
|
|
|
interface LinkPropsChakra extends ChakraLinkProps {
|
|
loading?: boolean;
|
|
external?: boolean;
|
|
iconColor?: ChakraLinkProps['color'];
|
|
noIcon?: boolean;
|
|
disabled?: boolean;
|
|
}
|
|
|
|
interface LinkPropsNext extends Partial<Pick<NextLinkProps, 'shallow' | 'prefetch' | 'scroll'>> {}
|
|
|
|
export interface LinkProps extends LinkPropsChakra, LinkPropsNext {}
|
|
|
|
const splitProps = (props: LinkProps): { chakra: LinkPropsChakra; next: NextLinkProps } => {
|
|
const { scroll = true, shallow = false, prefetch = false, ...rest } = props;
|
|
|
|
return {
|
|
chakra: rest,
|
|
next: {
|
|
href: rest.href as NextLinkProps['href'],
|
|
scroll,
|
|
shallow,
|
|
prefetch,
|
|
},
|
|
};
|
|
};
|
|
|
|
export const Link = React.forwardRef<HTMLAnchorElement, LinkProps>(
|
|
function Link(props, ref) {
|
|
const { chakra, next } = splitProps(props);
|
|
const { external, loading, href, children, disabled, noIcon, iconColor, ...rest } = chakra;
|
|
|
|
if (external) {
|
|
return (
|
|
<Skeleton loading={ loading } ref={ ref as React.ForwardedRef<HTMLDivElement> } asChild>
|
|
<ChakraLink
|
|
href={ href }
|
|
className="group"
|
|
target="_blank"
|
|
rel="noopener noreferrer"
|
|
{ ...(disabled ? { 'data-disabled': true } : {}) }
|
|
{ ...rest }
|
|
>
|
|
{ children }
|
|
{ !noIcon && <LinkExternalIcon color={ iconColor }/> }
|
|
</ChakraLink>
|
|
</Skeleton>
|
|
);
|
|
}
|
|
|
|
return (
|
|
<Skeleton loading={ loading } ref={ ref as React.ForwardedRef<HTMLDivElement> } asChild>
|
|
<ChakraLink
|
|
asChild
|
|
{ ...(disabled ? { 'data-disabled': true } : {}) }
|
|
{ ...rest }
|
|
>
|
|
{ next.href ? (
|
|
<NextLink { ...next }>
|
|
{ children }
|
|
</NextLink>
|
|
) :
|
|
<span>{ children }</span>
|
|
}
|
|
</ChakraLink>
|
|
</Skeleton>
|
|
);
|
|
},
|
|
);
|
|
|
|
export const LinkBox = ChakraLinkBox;
|
|
|
|
export const LinkOverlay = React.forwardRef<HTMLAnchorElement, LinkProps>(
|
|
function LinkOverlay(props, ref) {
|
|
const { chakra, next } = splitProps(props);
|
|
const { children, external, ...rest } = chakra;
|
|
|
|
if (external) {
|
|
return (
|
|
<ChakraLinkOverlay ref={ ref } target="_blank" rel="noopener noreferrer" { ...rest }>
|
|
{ children }
|
|
</ChakraLinkOverlay>
|
|
);
|
|
}
|
|
|
|
return (
|
|
<ChakraLinkOverlay ref={ ref } asChild={ Boolean(next.href) } { ...rest }>
|
|
{ next.href ? <NextLink { ...next }>{ children }</NextLink> : children }
|
|
</ChakraLinkOverlay>
|
|
);
|
|
},
|
|
);
|