* fix(BOOK-408): Updated logo aria label * fix(BOOK-408): Added title for links opening in new tab * fix(BOOK-408): Added translations handling for title Approved-by: Anton Gunnarsson Approved-by: Matilda Landström
132 lines
3.1 KiB
TypeScript
132 lines
3.1 KiB
TypeScript
'use client'
|
|
import NextLink from 'next/link'
|
|
import { usePathname, useSearchParams } from 'next/navigation'
|
|
import { useMemo } from 'react'
|
|
|
|
import { linkVariants } from './variants'
|
|
|
|
import type { LinkProps } from './link'
|
|
import { useIntl } from 'react-intl'
|
|
|
|
export { LinkProps }
|
|
|
|
/**
|
|
* @deprecated Use `@scandic-hotels/design-system/TextLink` instead.
|
|
*/
|
|
export default function Link({
|
|
active,
|
|
className,
|
|
color,
|
|
href,
|
|
partialMatch = false,
|
|
textDecoration,
|
|
size,
|
|
scroll = true,
|
|
prefetch,
|
|
variant,
|
|
weight,
|
|
onClick,
|
|
/**
|
|
* Decides if the link should include the current search params in the URL.
|
|
* If the given href also contains search params, they take precedence and
|
|
* override any current search params. If you need to merge them, handle that
|
|
* in your component that passes the href here.
|
|
*/
|
|
keepSearchParams,
|
|
...props
|
|
}: LinkProps) {
|
|
const currentPageSlug = usePathname()
|
|
const searchParams = useSearchParams()
|
|
const intl = useIntl()
|
|
let isActive = active || currentPageSlug === href
|
|
|
|
if (partialMatch && !isActive) {
|
|
isActive = currentPageSlug === href
|
|
}
|
|
|
|
const classNames = linkVariants({
|
|
active: isActive,
|
|
className,
|
|
textDecoration,
|
|
color,
|
|
size,
|
|
weight,
|
|
variant,
|
|
})
|
|
|
|
const fullUrl = useMemo(() => {
|
|
const newPath = href
|
|
|
|
if (keepSearchParams && searchParams.size) {
|
|
if (newPath.includes('?')) {
|
|
const newPathParts = newPath.split('?')
|
|
const newSearchParams = new URLSearchParams(newPathParts[1])
|
|
searchParams.forEach((v, k) => {
|
|
if (!newSearchParams.has(k)) {
|
|
newSearchParams.set(k, v)
|
|
}
|
|
})
|
|
return `${newPathParts[0]}?${newSearchParams}`
|
|
}
|
|
return `${newPath}?${searchParams}`
|
|
}
|
|
|
|
return newPath
|
|
}, [href, searchParams, keepSearchParams])
|
|
|
|
// TODO: Remove this check (and hook) and only return <Link /> when current web is deleted
|
|
const isExternal = useCheckIfExternalLink(href)
|
|
|
|
const linkProps = {
|
|
href: fullUrl,
|
|
className: classNames,
|
|
title:
|
|
props.target === '_blank'
|
|
? intl.formatMessage({
|
|
id: 'common.linkOpenInNewTab',
|
|
defaultMessage: 'Opens in a new tab/window',
|
|
})
|
|
: '',
|
|
}
|
|
|
|
return isExternal ? (
|
|
<a
|
|
{...linkProps}
|
|
{...props}
|
|
onClick={(e) => {
|
|
if (onClick) {
|
|
onClick(e)
|
|
}
|
|
}}
|
|
/>
|
|
) : (
|
|
<NextLink
|
|
scroll={scroll}
|
|
prefetch={prefetch}
|
|
onClick={onClick}
|
|
{...props}
|
|
{...linkProps}
|
|
/>
|
|
)
|
|
}
|
|
|
|
const useCheckIfExternalLink = (url: string) => {
|
|
return useMemo(() => {
|
|
if (typeof window !== 'undefined' && url?.length) {
|
|
try {
|
|
const hostName = window.location.hostname
|
|
const newURL = new URL(url)
|
|
|
|
const hostsMatch = hostName === newURL.hostname
|
|
const langRouteRegex = /^\/[a-zA-Z]{2}\//
|
|
|
|
return !hostsMatch || !langRouteRegex.test(newURL.pathname)
|
|
} catch {
|
|
// Don't care. Expecting internal url (#, /my-pages/overview, etc)
|
|
return false
|
|
}
|
|
}
|
|
return false
|
|
}, [url])
|
|
}
|