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
74 lines (62 loc) • 2.03 kB
text/typescript
import {type Path} from '@sanity/types'
import {isHotkey} from 'is-hotkey-esm'
import {useEffect} from 'react'
import {useEffectEvent} from 'use-effect-event'
import {isFileTargetElement} from '../form/inputs/common/fileTarget/fileTarget'
import {type FormDocumentValue} from '../form/types/formDocumentValue'
import {useCopyPaste} from '../studio/copyPaste'
import {hasSelection, isEmptyFocusPath, isNativeEditableElement} from '../studio/copyPaste/utils'
/** @internal */
export interface GlobalCopyPasteElementHandler {
value: FormDocumentValue | undefined
element: HTMLElement | null
focusPath?: Path
}
const isCopyHotKey = isHotkey(`mod+c`)
const isPasteHotKey = isHotkey(`mod+v`)
/** @internal */
export function useGlobalCopyPasteElementHandler({
value,
element,
focusPath,
}: GlobalCopyPasteElementHandler): void {
const {onCopy, onPaste} = useCopyPaste()
const handleKeydown = useEffectEvent((event: KeyboardEvent) => {
const targetElement = event.target
if (isCopyHotKey(event)) {
// We will skip handling this event if you have focus on an native editable element
if (
isNativeEditableElement(targetElement as HTMLElement) ||
hasSelection() ||
isEmptyFocusPath(focusPath!)
) {
return
}
event.preventDefault()
event.stopPropagation()
onCopy(focusPath!, value, {
context: {source: 'keyboardShortcut'},
})
}
if (isPasteHotKey(event)) {
if (
isNativeEditableElement(targetElement as HTMLElement) ||
isEmptyFocusPath(focusPath!) ||
isFileTargetElement(targetElement as HTMLElement)
) {
return
}
event.stopPropagation()
event.preventDefault()
onPaste(focusPath!, value, {
context: {source: 'keyboardShortcut'},
})
}
})
useEffect(() => {
element?.addEventListener('keydown', handleKeydown)
return () => {
element?.removeEventListener('keydown', handleKeydown)
}
}, [element, onPaste])
}