Files
admin/apps/web/web-runtime/components/links.tsx
T

67 lines
1.5 KiB
TypeScript

import { cn } from '@crux-kit/utils';
import { toPublicHref } from '#i18n/content-href';
import { buttonVariants } from '#shared/ui/Button';
import type { NavigationLink } from '../types';
export function safeHref(link: NavigationLink): string | null {
const href = link.href || link.externalUrl;
if (!href) {
return null;
}
if (href.startsWith('/')) {
return toPublicHref(href);
}
if (href.startsWith('#')) {
return href;
}
try {
const url = new URL(href);
return ['http:', 'https:', 'mailto:', 'tel:'].includes(url.protocol) ? href : null;
} catch {
return null;
}
}
export function PageLink({ link, className = '' }: { link: NavigationLink; className?: string }) {
const href = safeHref(link);
const classes = cn(buttonVariants({ variant: link.variant }), className);
if (!href) {
return <span className={cn(classes, 'cursor-not-allowed opacity-45')}>{link.label}</span>;
}
return (
<a
href={href}
className={classes}
target={link.openInNewTab ? '_blank' : undefined}
rel={link.openInNewTab ? 'noreferrer noopener' : undefined}
>
{link.label}
</a>
);
}
export function LinkList({
links,
className = ''
}: {
links: NavigationLink[];
className?: string;
}) {
if (links.length === 0) {
return null;
}
return (
<div className={cn('flex flex-wrap items-center gap-3', className)}>
{links.map((link, index) => (
<PageLink key={`${link.label}-${index}`} link={link} />
))}
</div>
);
}