mirror of
https://github.com/MoonTechLab/LunaTV.git
synced 2026-02-23 19:52:09 +08:00
fix: refactor
This commit is contained in:
@@ -1,160 +0,0 @@
|
||||
import { LucideIcon } from 'lucide-react';
|
||||
import * as React from 'react';
|
||||
import { IconType } from 'react-icons';
|
||||
import { ImSpinner2 } from 'react-icons/im';
|
||||
|
||||
import { cn } from '@/lib/utils';
|
||||
|
||||
const ButtonVariant = ['primary', 'outline', 'ghost', 'light', 'dark'] as const;
|
||||
const ButtonSize = ['sm', 'base'] as const;
|
||||
|
||||
type ButtonProps = {
|
||||
isLoading?: boolean;
|
||||
isDarkBg?: boolean;
|
||||
variant?: (typeof ButtonVariant)[number];
|
||||
size?: (typeof ButtonSize)[number];
|
||||
leftIcon?: IconType | LucideIcon;
|
||||
rightIcon?: IconType | LucideIcon;
|
||||
classNames?: {
|
||||
leftIcon?: string;
|
||||
rightIcon?: string;
|
||||
};
|
||||
} & React.ComponentPropsWithRef<'button'>;
|
||||
|
||||
const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
|
||||
(
|
||||
{
|
||||
children,
|
||||
className,
|
||||
disabled: buttonDisabled,
|
||||
isLoading,
|
||||
variant = 'primary',
|
||||
size = 'base',
|
||||
isDarkBg = false,
|
||||
leftIcon: LeftIcon,
|
||||
rightIcon: RightIcon,
|
||||
classNames,
|
||||
...rest
|
||||
},
|
||||
ref
|
||||
) => {
|
||||
const disabled = isLoading || buttonDisabled;
|
||||
|
||||
return (
|
||||
<button
|
||||
ref={ref}
|
||||
type='button'
|
||||
disabled={disabled}
|
||||
className={cn(
|
||||
'inline-flex items-center rounded font-medium',
|
||||
'focus-visible:ring-primary-500 focus:outline-none focus-visible:ring',
|
||||
'shadow-sm',
|
||||
'transition-colors duration-75',
|
||||
//#region //*=========== Size ===========
|
||||
[
|
||||
size === 'base' && ['px-3 py-1.5', 'text-sm md:text-base'],
|
||||
size === 'sm' && ['px-2 py-1', 'text-xs md:text-sm'],
|
||||
],
|
||||
//#endregion //*======== Size ===========
|
||||
//#region //*=========== Variants ===========
|
||||
[
|
||||
variant === 'primary' && [
|
||||
'bg-primary-500 text-white',
|
||||
'border-primary-600 border',
|
||||
'hover:bg-primary-600 hover:text-white',
|
||||
'active:bg-primary-700',
|
||||
'disabled:bg-primary-700',
|
||||
],
|
||||
variant === 'outline' && [
|
||||
'text-primary-500',
|
||||
'border-primary-500 border',
|
||||
'hover:bg-primary-50 active:bg-primary-100 disabled:bg-primary-100',
|
||||
isDarkBg &&
|
||||
'hover:bg-gray-900 active:bg-gray-800 disabled:bg-gray-800',
|
||||
],
|
||||
variant === 'ghost' && [
|
||||
'text-primary-500',
|
||||
'shadow-none',
|
||||
'hover:bg-primary-50 active:bg-primary-100 disabled:bg-primary-100',
|
||||
isDarkBg &&
|
||||
'hover:bg-gray-900 active:bg-gray-800 disabled:bg-gray-800',
|
||||
],
|
||||
variant === 'light' && [
|
||||
'bg-white text-gray-700',
|
||||
'border border-gray-300',
|
||||
'hover:text-dark hover:bg-gray-100',
|
||||
'active:bg-white/80 disabled:bg-gray-200',
|
||||
],
|
||||
variant === 'dark' && [
|
||||
'bg-gray-900 text-white',
|
||||
'border border-gray-600',
|
||||
'hover:bg-gray-800 active:bg-gray-700 disabled:bg-gray-700',
|
||||
],
|
||||
],
|
||||
//#endregion //*======== Variants ===========
|
||||
'disabled:cursor-not-allowed',
|
||||
isLoading &&
|
||||
'relative text-transparent transition-none hover:text-transparent disabled:cursor-wait',
|
||||
className
|
||||
)}
|
||||
{...rest}
|
||||
>
|
||||
{isLoading && (
|
||||
<div
|
||||
className={cn(
|
||||
'absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2',
|
||||
{
|
||||
'text-white': ['primary', 'dark'].includes(variant),
|
||||
'text-black': ['light'].includes(variant),
|
||||
'text-primary-500': ['outline', 'ghost'].includes(variant),
|
||||
}
|
||||
)}
|
||||
>
|
||||
<ImSpinner2 className='animate-spin' />
|
||||
</div>
|
||||
)}
|
||||
{LeftIcon && (
|
||||
<div
|
||||
className={cn([
|
||||
size === 'base' && 'mr-1',
|
||||
size === 'sm' && 'mr-1.5',
|
||||
])}
|
||||
>
|
||||
<LeftIcon
|
||||
size='1em'
|
||||
className={cn(
|
||||
[
|
||||
size === 'base' && 'md:text-md text-md',
|
||||
size === 'sm' && 'md:text-md text-sm',
|
||||
],
|
||||
classNames?.leftIcon
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
{children}
|
||||
{RightIcon && (
|
||||
<div
|
||||
className={cn([
|
||||
size === 'base' && 'ml-1',
|
||||
size === 'sm' && 'ml-1.5',
|
||||
])}
|
||||
>
|
||||
<RightIcon
|
||||
size='1em'
|
||||
className={cn(
|
||||
[
|
||||
size === 'base' && 'text-md md:text-md',
|
||||
size === 'sm' && 'md:text-md text-sm',
|
||||
],
|
||||
classNames?.rightIcon
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</button>
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
export default Button;
|
||||
@@ -1,116 +0,0 @@
|
||||
import { LucideIcon } from 'lucide-react';
|
||||
import * as React from 'react';
|
||||
import { IconType } from 'react-icons';
|
||||
import { ImSpinner2 } from 'react-icons/im';
|
||||
|
||||
import { cn } from '@/lib/utils';
|
||||
|
||||
const IconButtonVariant = [
|
||||
'primary',
|
||||
'outline',
|
||||
'ghost',
|
||||
'light',
|
||||
'dark',
|
||||
] as const;
|
||||
|
||||
type IconButtonProps = {
|
||||
isLoading?: boolean;
|
||||
isDarkBg?: boolean;
|
||||
variant?: (typeof IconButtonVariant)[number];
|
||||
icon?: IconType | LucideIcon;
|
||||
classNames?: {
|
||||
icon?: string;
|
||||
};
|
||||
} & React.ComponentPropsWithRef<'button'>;
|
||||
|
||||
const IconButton = React.forwardRef<HTMLButtonElement, IconButtonProps>(
|
||||
(
|
||||
{
|
||||
className,
|
||||
disabled: buttonDisabled,
|
||||
isLoading,
|
||||
variant = 'primary',
|
||||
isDarkBg = false,
|
||||
icon: Icon,
|
||||
classNames,
|
||||
...rest
|
||||
},
|
||||
ref
|
||||
) => {
|
||||
const disabled = isLoading || buttonDisabled;
|
||||
|
||||
return (
|
||||
<button
|
||||
ref={ref}
|
||||
type='button'
|
||||
disabled={disabled}
|
||||
className={cn(
|
||||
'inline-flex items-center justify-center rounded font-medium',
|
||||
'focus-visible:ring-primary-500 focus:outline-none focus-visible:ring',
|
||||
'shadow-sm',
|
||||
'transition-colors duration-75',
|
||||
'min-h-[28px] min-w-[28px] p-1 md:min-h-[34px] md:min-w-[34px] md:p-2',
|
||||
//#region //*=========== Variants ===========
|
||||
[
|
||||
variant === 'primary' && [
|
||||
'bg-primary-500 text-white',
|
||||
'border-primary-600 border',
|
||||
'hover:bg-primary-600 hover:text-white',
|
||||
'active:bg-primary-700',
|
||||
'disabled:bg-primary-700',
|
||||
],
|
||||
variant === 'outline' && [
|
||||
'text-primary-500',
|
||||
'border-primary-500 border',
|
||||
'hover:bg-primary-50 active:bg-primary-100 disabled:bg-primary-100',
|
||||
isDarkBg &&
|
||||
'hover:bg-gray-900 active:bg-gray-800 disabled:bg-gray-800',
|
||||
],
|
||||
variant === 'ghost' && [
|
||||
'text-primary-500',
|
||||
'shadow-none',
|
||||
'hover:bg-primary-50 active:bg-primary-100 disabled:bg-primary-100',
|
||||
isDarkBg &&
|
||||
'hover:bg-gray-900 active:bg-gray-800 disabled:bg-gray-800',
|
||||
],
|
||||
variant === 'light' && [
|
||||
'bg-white text-gray-700',
|
||||
'border border-gray-300',
|
||||
'hover:text-dark hover:bg-gray-100',
|
||||
'active:bg-white/80 disabled:bg-gray-200',
|
||||
],
|
||||
variant === 'dark' && [
|
||||
'bg-gray-900 text-white',
|
||||
'border border-gray-600',
|
||||
'hover:bg-gray-800 active:bg-gray-700 disabled:bg-gray-700',
|
||||
],
|
||||
],
|
||||
//#endregion //*======== Variants ===========
|
||||
'disabled:cursor-not-allowed',
|
||||
isLoading &&
|
||||
'relative text-transparent transition-none hover:text-transparent disabled:cursor-wait',
|
||||
className
|
||||
)}
|
||||
{...rest}
|
||||
>
|
||||
{isLoading && (
|
||||
<div
|
||||
className={cn(
|
||||
'absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2',
|
||||
{
|
||||
'text-white': ['primary', 'dark'].includes(variant),
|
||||
'text-black': ['light'].includes(variant),
|
||||
'text-primary-500': ['outline', 'ghost'].includes(variant),
|
||||
}
|
||||
)}
|
||||
>
|
||||
<ImSpinner2 className='animate-spin' />
|
||||
</div>
|
||||
)}
|
||||
{Icon && <Icon size='1em' className={cn(classNames?.icon)} />}
|
||||
</button>
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
export default IconButton;
|
||||
@@ -1,52 +0,0 @@
|
||||
import * as React from 'react';
|
||||
|
||||
import { cn } from '@/lib/utils';
|
||||
|
||||
const TextButtonVariant = ['primary', 'basic'] as const;
|
||||
|
||||
type TextButtonProps = {
|
||||
variant?: (typeof TextButtonVariant)[number];
|
||||
} & React.ComponentPropsWithRef<'button'>;
|
||||
|
||||
const TextButton = React.forwardRef<HTMLButtonElement, TextButtonProps>(
|
||||
(
|
||||
{
|
||||
children,
|
||||
className,
|
||||
variant = 'primary',
|
||||
disabled: buttonDisabled,
|
||||
...rest
|
||||
},
|
||||
ref
|
||||
) => {
|
||||
return (
|
||||
<button
|
||||
ref={ref}
|
||||
type='button'
|
||||
disabled={buttonDisabled}
|
||||
className={cn(
|
||||
'button inline-flex items-center justify-center font-semibold',
|
||||
'focus-visible:ring-primary-500 focus:outline-none focus-visible:ring',
|
||||
'transition duration-100',
|
||||
//#region //*=========== Variant ===========
|
||||
variant === 'primary' && [
|
||||
'text-primary-500 hover:text-primary-600 active:text-primary-700',
|
||||
'disabled:text-primary-200',
|
||||
],
|
||||
variant === 'basic' && [
|
||||
'text-black hover:text-gray-600 active:text-gray-800',
|
||||
'disabled:text-gray-300',
|
||||
],
|
||||
//#endregion //*======== Variant ===========
|
||||
'disabled:cursor-not-allowed disabled:brightness-105 disabled:hover:underline',
|
||||
className
|
||||
)}
|
||||
{...rest}
|
||||
>
|
||||
{children}
|
||||
</button>
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
export default TextButton;
|
||||
@@ -1,64 +0,0 @@
|
||||
import * as React from 'react';
|
||||
|
||||
import { cn } from '@/lib/utils';
|
||||
|
||||
import UnderlineLink from '@/components/links/UnderlineLink';
|
||||
import { UnstyledLinkProps } from '@/components/links/UnstyledLink';
|
||||
|
||||
type ArrowLinkProps<C extends React.ElementType> = {
|
||||
as?: C;
|
||||
direction?: 'left' | 'right';
|
||||
} & UnstyledLinkProps &
|
||||
React.ComponentProps<C>;
|
||||
|
||||
export default function ArrowLink<C extends React.ElementType>({
|
||||
children,
|
||||
className,
|
||||
direction = 'right',
|
||||
as,
|
||||
...rest
|
||||
}: ArrowLinkProps<C>) {
|
||||
const Component = as || UnderlineLink;
|
||||
|
||||
return (
|
||||
<Component
|
||||
{...rest}
|
||||
className={cn(
|
||||
'group gap-[0.25em]',
|
||||
direction === 'left' && 'flex-row-reverse',
|
||||
className
|
||||
)}
|
||||
>
|
||||
<span>{children}</span>
|
||||
<svg
|
||||
viewBox='0 0 16 16'
|
||||
height='1em'
|
||||
width='1em'
|
||||
fill='none'
|
||||
xmlns='http://www.w3.org/2000/svg'
|
||||
className={cn(
|
||||
'relative',
|
||||
'transition-transform duration-200',
|
||||
direction === 'right' ? 'motion-safe:-translate-x-1' : 'rotate-180',
|
||||
'group-hover:translate-x-0'
|
||||
)}
|
||||
>
|
||||
<path
|
||||
fill='currentColor'
|
||||
d='M7.28033 3.21967C6.98744 2.92678 6.51256 2.92678 6.21967 3.21967C5.92678 3.51256 5.92678 3.98744 6.21967 4.28033L7.28033 3.21967ZM11 8L11.5303 8.53033C11.8232 8.23744 11.8232 7.76256 11.5303 7.46967L11 8ZM6.21967 11.7197C5.92678 12.0126 5.92678 12.4874 6.21967 12.7803C6.51256 13.0732 6.98744 13.0732 7.28033 12.7803L6.21967 11.7197ZM6.21967 4.28033L10.4697 8.53033L11.5303 7.46967L7.28033 3.21967L6.21967 4.28033ZM10.4697 7.46967L6.21967 11.7197L7.28033 12.7803L11.5303 8.53033L10.4697 7.46967Z'
|
||||
/>
|
||||
<path
|
||||
stroke='currentColor'
|
||||
d='M1.75 8H11'
|
||||
strokeWidth='1.5'
|
||||
strokeLinecap='round'
|
||||
className={cn(
|
||||
'origin-left transition-all duration-200',
|
||||
'opacity-0 motion-safe:-translate-x-1',
|
||||
'group-hover:translate-x-0 group-hover:opacity-100'
|
||||
)}
|
||||
/>
|
||||
</svg>
|
||||
</Component>
|
||||
);
|
||||
}
|
||||
@@ -1,146 +0,0 @@
|
||||
import { LucideIcon } from 'lucide-react';
|
||||
import * as React from 'react';
|
||||
import { IconType } from 'react-icons';
|
||||
|
||||
import { cn } from '@/lib/utils';
|
||||
|
||||
import UnstyledLink, {
|
||||
UnstyledLinkProps,
|
||||
} from '@/components/links/UnstyledLink';
|
||||
|
||||
const ButtonLinkVariant = [
|
||||
'primary',
|
||||
'outline',
|
||||
'ghost',
|
||||
'light',
|
||||
'dark',
|
||||
] as const;
|
||||
const ButtonLinkSize = ['sm', 'base'] as const;
|
||||
|
||||
type ButtonLinkProps = {
|
||||
isDarkBg?: boolean;
|
||||
variant?: (typeof ButtonLinkVariant)[number];
|
||||
size?: (typeof ButtonLinkSize)[number];
|
||||
leftIcon?: IconType | LucideIcon;
|
||||
rightIcon?: IconType | LucideIcon;
|
||||
classNames?: {
|
||||
leftIcon?: string;
|
||||
rightIcon?: string;
|
||||
};
|
||||
} & UnstyledLinkProps;
|
||||
|
||||
const ButtonLink = React.forwardRef<HTMLAnchorElement, ButtonLinkProps>(
|
||||
(
|
||||
{
|
||||
children,
|
||||
className,
|
||||
variant = 'primary',
|
||||
size = 'base',
|
||||
isDarkBg = false,
|
||||
leftIcon: LeftIcon,
|
||||
rightIcon: RightIcon,
|
||||
classNames,
|
||||
...rest
|
||||
},
|
||||
ref
|
||||
) => {
|
||||
return (
|
||||
<UnstyledLink
|
||||
ref={ref}
|
||||
{...rest}
|
||||
className={cn(
|
||||
'inline-flex items-center rounded font-medium',
|
||||
'focus-visible:ring-primary-500 focus:outline-none focus-visible:ring',
|
||||
'shadow-sm',
|
||||
'transition-colors duration-75',
|
||||
//#region //*=========== Size ===========
|
||||
[
|
||||
size === 'base' && ['px-3 py-1.5', 'text-sm md:text-base'],
|
||||
size === 'sm' && ['px-2 py-1', 'text-xs md:text-sm'],
|
||||
],
|
||||
//#endregion //*======== Size ===========
|
||||
//#region //*=========== Variants ===========
|
||||
[
|
||||
variant === 'primary' && [
|
||||
'bg-primary-500 text-white',
|
||||
'border-primary-600 border',
|
||||
'hover:bg-primary-600 hover:text-white',
|
||||
'active:bg-primary-700',
|
||||
'disabled:bg-primary-700',
|
||||
],
|
||||
variant === 'outline' && [
|
||||
'text-primary-500',
|
||||
'border-primary-500 border',
|
||||
'hover:bg-primary-50 active:bg-primary-100 disabled:bg-primary-100',
|
||||
isDarkBg &&
|
||||
'hover:bg-gray-900 active:bg-gray-800 disabled:bg-gray-800',
|
||||
],
|
||||
variant === 'ghost' && [
|
||||
'text-primary-500',
|
||||
'shadow-none',
|
||||
'hover:bg-primary-50 active:bg-primary-100 disabled:bg-primary-100',
|
||||
isDarkBg &&
|
||||
'hover:bg-gray-900 active:bg-gray-800 disabled:bg-gray-800',
|
||||
],
|
||||
variant === 'light' && [
|
||||
'bg-white text-gray-700',
|
||||
'border border-gray-300',
|
||||
'hover:text-dark hover:bg-gray-100',
|
||||
'active:bg-white/80 disabled:bg-gray-200',
|
||||
],
|
||||
variant === 'dark' && [
|
||||
'bg-gray-900 text-white',
|
||||
'border border-gray-600',
|
||||
'hover:bg-gray-800 active:bg-gray-700 disabled:bg-gray-700',
|
||||
],
|
||||
],
|
||||
//#endregion //*======== Variants ===========
|
||||
'disabled:cursor-not-allowed',
|
||||
className
|
||||
)}
|
||||
>
|
||||
{LeftIcon && (
|
||||
<div
|
||||
className={cn([
|
||||
size === 'base' && 'mr-1',
|
||||
size === 'sm' && 'mr-1.5',
|
||||
])}
|
||||
>
|
||||
<LeftIcon
|
||||
size='1em'
|
||||
className={cn(
|
||||
[
|
||||
size === 'base' && 'md:text-md text-md',
|
||||
size === 'sm' && 'md:text-md text-sm',
|
||||
],
|
||||
classNames?.leftIcon
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
{children}
|
||||
{RightIcon && (
|
||||
<div
|
||||
className={cn([
|
||||
size === 'base' && 'ml-1',
|
||||
size === 'sm' && 'ml-1.5',
|
||||
])}
|
||||
>
|
||||
<RightIcon
|
||||
size='1em'
|
||||
className={cn(
|
||||
[
|
||||
size === 'base' && 'text-md md:text-md',
|
||||
size === 'sm' && 'md:text-md text-sm',
|
||||
],
|
||||
classNames?.rightIcon
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</UnstyledLink>
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
export default ButtonLink;
|
||||
@@ -1,97 +0,0 @@
|
||||
import { LucideIcon } from 'lucide-react';
|
||||
import * as React from 'react';
|
||||
import { IconType } from 'react-icons';
|
||||
|
||||
import { cn } from '@/lib/utils';
|
||||
|
||||
import UnstyledLink, {
|
||||
UnstyledLinkProps,
|
||||
} from '@/components/links/UnstyledLink';
|
||||
|
||||
const IconLinkVariant = [
|
||||
'primary',
|
||||
'outline',
|
||||
'ghost',
|
||||
'light',
|
||||
'dark',
|
||||
] as const;
|
||||
|
||||
type IconLinkProps = {
|
||||
isDarkBg?: boolean;
|
||||
variant?: (typeof IconLinkVariant)[number];
|
||||
icon?: IconType | LucideIcon;
|
||||
classNames?: {
|
||||
icon?: string;
|
||||
};
|
||||
} & Omit<UnstyledLinkProps, 'children'>;
|
||||
|
||||
const IconLink = React.forwardRef<HTMLAnchorElement, IconLinkProps>(
|
||||
(
|
||||
{
|
||||
className,
|
||||
icon: Icon,
|
||||
variant = 'outline',
|
||||
isDarkBg = false,
|
||||
classNames,
|
||||
...rest
|
||||
},
|
||||
ref
|
||||
) => {
|
||||
return (
|
||||
<UnstyledLink
|
||||
ref={ref}
|
||||
type='button'
|
||||
className={cn(
|
||||
'inline-flex items-center justify-center rounded font-medium',
|
||||
'focus-visible:ring-primary-500 focus:outline-none focus-visible:ring',
|
||||
'shadow-sm',
|
||||
'transition-colors duration-75',
|
||||
'min-h-[28px] min-w-[28px] p-1 md:min-h-[34px] md:min-w-[34px] md:p-2',
|
||||
//#region //*=========== Variants ===========
|
||||
[
|
||||
variant === 'primary' && [
|
||||
'bg-primary-500 text-white',
|
||||
'border-primary-600 border',
|
||||
'hover:bg-primary-600 hover:text-white',
|
||||
'active:bg-primary-700',
|
||||
'disabled:bg-primary-700',
|
||||
],
|
||||
variant === 'outline' && [
|
||||
'text-primary-500',
|
||||
'border-primary-500 border',
|
||||
'hover:bg-primary-50 active:bg-primary-100 disabled:bg-primary-100',
|
||||
isDarkBg &&
|
||||
'hover:bg-gray-900 active:bg-gray-800 disabled:bg-gray-800',
|
||||
],
|
||||
variant === 'ghost' && [
|
||||
'text-primary-500',
|
||||
'shadow-none',
|
||||
'hover:bg-primary-50 active:bg-primary-100 disabled:bg-primary-100',
|
||||
isDarkBg &&
|
||||
'hover:bg-gray-900 active:bg-gray-800 disabled:bg-gray-800',
|
||||
],
|
||||
variant === 'light' && [
|
||||
'bg-white text-gray-700',
|
||||
'border border-gray-300',
|
||||
'hover:text-dark hover:bg-gray-100',
|
||||
'active:bg-white/80 disabled:bg-gray-200',
|
||||
],
|
||||
variant === 'dark' && [
|
||||
'bg-gray-900 text-white',
|
||||
'border border-gray-600',
|
||||
'hover:bg-gray-800 active:bg-gray-700 disabled:bg-gray-700',
|
||||
],
|
||||
],
|
||||
//#endregion //*======== Variants ===========
|
||||
'disabled:cursor-not-allowed',
|
||||
className
|
||||
)}
|
||||
{...rest}
|
||||
>
|
||||
{Icon && <Icon size='1em' className={cn(classNames?.icon)} />}
|
||||
</UnstyledLink>
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
export default IconLink;
|
||||
@@ -1,43 +0,0 @@
|
||||
import * as React from 'react';
|
||||
|
||||
import { cn } from '@/lib/utils';
|
||||
|
||||
import UnstyledLink, {
|
||||
UnstyledLinkProps,
|
||||
} from '@/components/links/UnstyledLink';
|
||||
|
||||
const PrimaryLinkVariant = ['primary', 'basic'] as const;
|
||||
type PrimaryLinkProps = {
|
||||
variant?: (typeof PrimaryLinkVariant)[number];
|
||||
} & UnstyledLinkProps;
|
||||
|
||||
const PrimaryLink = React.forwardRef<HTMLAnchorElement, PrimaryLinkProps>(
|
||||
({ className, children, variant = 'primary', ...rest }, ref) => {
|
||||
return (
|
||||
<UnstyledLink
|
||||
ref={ref}
|
||||
{...rest}
|
||||
className={cn(
|
||||
'inline-flex items-center',
|
||||
'focus-visible:ring-primary-500 focus:outline-none focus-visible:rounded focus-visible:ring focus-visible:ring-offset-2',
|
||||
'font-medium',
|
||||
//#region //*=========== Variant ===========
|
||||
variant === 'primary' && [
|
||||
'text-primary-500 hover:text-primary-600 active:text-primary-700',
|
||||
'disabled:text-primary-200',
|
||||
],
|
||||
variant === 'basic' && [
|
||||
'text-black hover:text-gray-600 active:text-gray-800',
|
||||
'disabled:text-gray-300',
|
||||
],
|
||||
//#endregion //*======== Variant ===========
|
||||
className
|
||||
)}
|
||||
>
|
||||
{children}
|
||||
</UnstyledLink>
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
export default PrimaryLink;
|
||||
@@ -1,28 +0,0 @@
|
||||
import * as React from 'react';
|
||||
|
||||
import { cn } from '@/lib/utils';
|
||||
|
||||
import UnstyledLink, {
|
||||
UnstyledLinkProps,
|
||||
} from '@/components/links/UnstyledLink';
|
||||
|
||||
const UnderlineLink = React.forwardRef<HTMLAnchorElement, UnstyledLinkProps>(
|
||||
({ children, className, ...rest }, ref) => {
|
||||
return (
|
||||
<UnstyledLink
|
||||
ref={ref}
|
||||
{...rest}
|
||||
className={cn(
|
||||
'animated-underline custom-link inline-flex items-center font-medium',
|
||||
'focus-visible:ring-primary-500 focus:outline-none focus-visible:rounded focus-visible:ring focus-visible:ring-offset-2',
|
||||
'border-dark border-b border-dotted hover:border-black/0',
|
||||
className
|
||||
)}
|
||||
>
|
||||
{children}
|
||||
</UnstyledLink>
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
export default UnderlineLink;
|
||||
@@ -1,50 +0,0 @@
|
||||
import Link, { LinkProps } from 'next/link';
|
||||
import * as React from 'react';
|
||||
|
||||
import { cn } from '@/lib/utils';
|
||||
|
||||
export type UnstyledLinkProps = {
|
||||
href: string;
|
||||
children: React.ReactNode;
|
||||
openNewTab?: boolean;
|
||||
className?: string;
|
||||
nextLinkProps?: Omit<LinkProps, 'href'>;
|
||||
} & React.ComponentPropsWithRef<'a'>;
|
||||
|
||||
const UnstyledLink = React.forwardRef<HTMLAnchorElement, UnstyledLinkProps>(
|
||||
({ children, href, openNewTab, className, nextLinkProps, ...rest }, ref) => {
|
||||
const isNewTab =
|
||||
openNewTab !== undefined
|
||||
? openNewTab
|
||||
: href && !href.startsWith('/') && !href.startsWith('#');
|
||||
|
||||
if (!isNewTab) {
|
||||
return (
|
||||
<Link
|
||||
href={href}
|
||||
ref={ref}
|
||||
className={className}
|
||||
{...rest}
|
||||
{...nextLinkProps}
|
||||
>
|
||||
{children}
|
||||
</Link>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<a
|
||||
ref={ref}
|
||||
target='_blank'
|
||||
rel='noopener noreferrer'
|
||||
href={href}
|
||||
{...rest}
|
||||
className={cn('cursor-newtab', className)}
|
||||
>
|
||||
{children}
|
||||
</a>
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
export default UnstyledLink;
|
||||
Reference in New Issue
Block a user