Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
const setFragmentData = (
dataTransfer: DataTransfer,
editor: ReactEditor
): void => {
const { selection } = editor
if (!selection) {
return
}
const [start, end] = Range.edges(selection)
const startVoid = Editor.void(editor, { at: start.path })
const endVoid = Editor.void(editor, { at: end.path })
if (Range.isCollapsed(selection) && !startVoid) {
return
}
// Create a fake selection so that we can add a Base64-encoded copy of the
// fragment to the HTML, to decode on future pastes.
const domRange = ReactEditor.toDOMRange(editor, selection)
let contents = domRange.cloneContents()
let attach = contents.childNodes[0] as HTMLElement
// Make sure attach is non-empty, since empty nodes will not get copied.
contents.childNodes.forEach(node => {
if (node.textContent && node.textContent.trim() !== '') {
attach = node as HTMLElement
}
})
useEffect(() => {
const el = ref.current
const { selection } = editor
if (!el) {
return
}
if (
!selection ||
!ReactEditor.isFocused(editor) ||
Range.isCollapsed(selection) ||
Editor.string(editor, selection) === ''
) {
el.removeAttribute('style')
return
}
const domSelection = window.getSelection()
const domRange = domSelection.getRangeAt(0)
const rect = domRange.getBoundingClientRect()
el.style.opacity = '1'
el.style.top = `${rect.top + window.pageYOffset - el.offsetHeight}px`
el.style.left = `${rect.left +
window.pageXOffset -
el.offsetWidth / 2 +
rect.width / 2}px`
})
editor.deleteBackward = (...args) => {
const { selection } = editor
if (selection && Range.isCollapsed(selection)) {
const [match] = Editor.nodes(editor, {
match: n => n.type === 'check-list-item',
})
if (match) {
const [, path] = match
const start = Editor.start(editor, path)
if (Point.equals(selection.anchor, start)) {
Transforms.setNodes(
editor,
{ type: 'paragraph' },
{ match: n => n.type === 'check-list-item' }
)
return
}
React.useEffect(() => {
if (!menu.current || !triangle.current) return
const { selection } = editor
if (
!selection ||
!ReactEditor.isFocused(editor) ||
Range.isCollapsed(selection) ||
SlateEditor.string(editor, selection) === ''
) {
menu.current.style.top = ''
menu.current.style.left = ''
return
}
const domSelection = window.getSelection()
if (!domSelection || domSelection.rangeCount === 0) return
const domRange = domSelection.getRangeAt(0)
const rect = domRange.getBoundingClientRect()
if (!rect || rect.height === 0) return
if (!menu.current.offsetParent) return
export function isCollapsed(editor: Editor) {
return editor.selection && Range.isCollapsed(editor.selection)
}
toDOMRange(editor: ReactEditor, range: Range): DOMRange {
const { anchor, focus } = range
const domAnchor = ReactEditor.toDOMPoint(editor, anchor)
const domFocus = Range.isCollapsed(range)
? domAnchor
: ReactEditor.toDOMPoint(editor, focus)
const domRange = window.document.createRange()
const start = Range.isBackward(range) ? domFocus : domAnchor
const end = Range.isBackward(range) ? domAnchor : domFocus
domRange.setStart(start[0], start[1])
domRange.setEnd(end[0], end[1])
return domRange
},
onChange={value => {
setValue(value)
const { selection } = editor
if (selection && Range.isCollapsed(selection)) {
const [start] = Range.edges(selection)
const wordBefore = Editor.before(editor, start, { unit: 'word' })
const before = wordBefore && Editor.before(editor, wordBefore)
const beforeRange = before && Editor.range(editor, before, start)
const beforeText = beforeRange && Editor.string(editor, beforeRange)
const beforeMatch = beforeText && beforeText.match(/^@(\w+)$/)
const after = Editor.after(editor, start)
const afterRange = Editor.range(editor, start, after)
const afterText = Editor.string(editor, afterRange)
const afterMatch = afterText.match(/^(\s|$)/)
if (beforeMatch && afterMatch) {
setTarget(beforeRange)
setSearch(beforeMatch[1])
setIndex(0)
return
wrapLink(editor, url) {
if (Controller.isBlockActive(editor, "link")) {
Controller.unwrapLink(editor);
}
const { selection } = editor
const isCollapsed = selection && Range.isCollapsed(selection);
const link = {
type: 'link',
url,
children: isCollapsed ? [{ text: url }] : [],
}
if (isCollapsed) {
Transforms.insertNodes(editor, link);
} else {
Transforms.wrapNodes(editor, link, { split: true });
Transforms.collapse(editor, { edge: 'end' });
}
}
}
const wrapLink = (editor, url) => {
if (isLinkActive(editor)) {
unwrapLink(editor)
}
const { selection } = editor
const isCollapsed = selection && Range.isCollapsed(selection)
const link = {
type: 'link',
url,
children: isCollapsed ? [{ text: url }] : [],
}
if (isCollapsed) {
Transforms.insertNodes(editor, link)
} else {
Transforms.wrapNodes(editor, link, { split: true })
Transforms.collapse(editor, { edge: 'end' })
}
}