import { ParsedUrlQueryInput, stringify } from "querystring" import { sanitizeUrl } from "@braintree/sanitize-url" import React, { ComponentPropsWithoutRef, forwardRef } from "react" import { disabledVariants, DisabledVariantProps, } from "../../styles/utils/disabled" import { LinkVariantProps, linkVariants } from "../../styles/utils/link" import { classNames } from "../../utils/classNames" export type Url = string | { pathname: string; query?: ParsedUrlQueryInput } export type LinkProps = Omit, "href"> & LinkVariantProps & DisabledVariantProps & { href?: Url } /** * A standard `a` tag with reasonable defaults. */ export const Link = forwardRef(function Link( { className, href, variant = "default", disabled, rel, target, ...rest }, ref, ) { if (href && isExternalLink(href)) { target = target ?? "_blank" rel = rel ?? "nofollow noopener" } return ( ) }) export const isExternalLink = (href: Url): boolean => { if (typeof href === "string") { return !href.startsWith("/") } return !href.pathname.startsWith("/") } export const formatHref = (href: Url): string => { if (typeof href === "string") { return href } const querystring = stringify(href.query) if (!querystring) { return href.pathname } return `${href.pathname}?${querystring}` } export const NonAnchorLink = forwardRef( function NonAnchorLink( { href, className, disabled, variant = "default", ...rest }, ref, ) { function navigate() { if (href) { if (isExternalLink(href)) { window.open(sanitizeUrl(formatHref(href)), "_blank") } else { window.location.href = sanitizeUrl(formatHref(href)) } } } return ( { rest.onClick?.( event as React.MouseEvent, ) event.preventDefault() navigate() }} onKeyDown={event => { rest.onKeyDown?.(event as React.KeyboardEvent) if (event.keyCode === 13) { navigate() } }} /> ) }, )