'use client' import { Slot } from '@radix-ui/react-slot' import * as React from 'react' import { cn } from '../../utils' export type LinkRenderProps = React.AnchorHTMLAttributes & { href: string children: React.ReactNode } type RenderLinkFn = (props: LinkRenderProps) => React.ReactNode type BaseLinkProps = Omit< React.AnchorHTMLAttributes, 'href' > & { /** The URL the link points to. Required. */ href: string /** * Adds `rel="noopener noreferrer"` for security. * Use for all links pointing to external sites. */ external?: boolean /** * Opens the link in a new browser tab (`target="_blank"`). */ newTab?: boolean } type LinkWithAsChild = BaseLinkProps & { /** * Merges Link props onto a child element via Radix Slot. * Use to compose with framework-specific link components (e.g. Next.js Link). * Mutually exclusive with `renderLink`. */ asChild: true renderLink?: never } type LinkWithRenderLink = BaseLinkProps & { asChild?: never /** * Render function for framework-specific links. * Used internally by blocks components for framework-agnostic navigation. * Mutually exclusive with `asChild`. */ renderLink: RenderLinkFn } type LinkDefault = BaseLinkProps & { asChild?: false renderLink?: never } export type LinkProps = LinkWithAsChild | LinkWithRenderLink | LinkDefault /** * Unstyled base component for navigation links. Renders an `` element and * accepts all native anchor attributes. Use `asChild` to compose with * framework-specific link components (e.g. Next.js Link). For styled inline * text links, use TextLink instead. */ export const Link = React.forwardRef( ( { href, asChild, renderLink, external = false, newTab = false, className, children, rel, target, ...props }, ref, ) => { // Compute rel attribute const computedRel = external ? cn(rel, 'noopener noreferrer') : rel // Compute target attribute const computedTarget = newTab ? '_blank' : target const linkProps = { href, rel: computedRel || undefined, target: computedTarget, className, ...props, } // Priority 1: asChild - use Slot to merge props onto child if (asChild) { return ( {children} ) } // Priority 2: renderLink - call function to create element if (renderLink) { return <>{renderLink({ ...linkProps, children })} } // Default: plain anchor return ( {children} ) }, ) Link.displayName = 'Link'