sanity
Version:
Sanity is a real-time content infrastructure with a scalable, hosted backend featuring a Graph Oriented Query Language (GROQ), asset pipelines and fast edge caches
92 lines (75 loc) • 2.03 kB
text/typescript
import {useCallback} from 'react'
import {useRouter} from './useRouter'
function isLeftClickEvent(event: React.MouseEvent) {
return event.button === 0
}
function isModifiedEvent(event: React.MouseEvent) {
return !!(event.metaKey || event.altKey || event.ctrlKey || event.shiftKey)
}
/**
* @public
*/
export interface UseLinkOptions {
/**
* The URL that the link should navigate to.
*/
href?: string
/**
* The event handler function that should be called when the link is clicked.
*/
onClick?: React.MouseEventHandler<HTMLElement>
/**
* Whether the link should replace the current URL in the browser history.
*/
replace?: boolean
/**
* The target window or frame that the linked document will open in.
*/
target?: string
}
/**
* Returns an object with an `onClick` function that can be used as a click handler for a link.
*
* @public
*
* @param options - An object containing the properties for the link.
* See {@link UseLinkOptions}
*
* @returns An object with an `onClick` function.
*
* @example
* ```tsx
* const linkProps = useLink({
* href: 'https://www.sanity.io',
* target: '_blank'
* })
*
* <a {...linkProps}>Link</a>
* ```
*/
export function useLink(options: UseLinkOptions): {onClick: React.MouseEventHandler<HTMLElement>} {
const {onClick: onClickProp, href, target, replace = false} = options
const {navigateUrl} = useRouter()
const onClick = useCallback(
(event: React.MouseEvent<HTMLElement>): void => {
if (event.isDefaultPrevented()) {
return
}
if (!href) return
if (onClickProp) {
onClickProp(event)
}
if (isModifiedEvent(event) || !isLeftClickEvent(event)) {
return
}
// If target prop is set (e.g. to "_blank") let browser handle link.
if (target) {
return
}
event.preventDefault()
navigateUrl({path: href, replace})
},
[href, navigateUrl, onClickProp, replace, target],
)
return {onClick: onClick}
}