import { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext' import { $createTextNode, $getSelection, $insertNodes, $setSelection, COMMAND_PRIORITY_EDITOR, createCommand } from 'lexical' import { $wrapNodeInElement, mergeRegister } from '@lexical/utils' import { $createLinkNode, $isLinkNode } from '@lexical/link' import { Modal } from 'react-bootstrap' import React, { useState, useCallback, useContext, useRef, useEffect } from 'react' import { Form, Input, SubmitButton } from '../../components/form' import { ensureProtocol } from '../../lib/url' import { getSelectedNode } from '../utils/selected-node' import { namedUrlSchema } from '../../lib/validate' export const INSERT_LINK_COMMAND = createCommand('INSERT_LINK_COMMAND') export default function LinkInsertPlugin () { const [editor] = useLexicalComposerContext() useEffect(() => { return mergeRegister( editor.registerCommand( INSERT_LINK_COMMAND, (payload) => { const selection = $getSelection() const node = getSelectedNode(selection) const parent = node.getParent() if ($isLinkNode(parent)) { parent.remove() } else if ($isLinkNode(node)) { node.remove() } const textNode = $createTextNode(payload.text) $insertNodes([textNode]) const linkNode = $createLinkNode(payload.url) $wrapNodeInElement(textNode, () => linkNode) $setSelection(textNode.select()) return true }, COMMAND_PRIORITY_EDITOR ) ) }, [editor]) return null } export const LinkInsertContext = React.createContext({ link: null, setLink: () => {} }) export function LinkInsertProvider ({ children }) { const [link, setLink] = useState(null) const contextValue = { link, setLink: useCallback(link => setLink(link), []) } return ( {children} ) } export function useLinkInsert () { const { link, setLink } = useContext(LinkInsertContext) return { link, setLink } } export function LinkInsertModal () { const [editor] = useLexicalComposerContext() const { link, setLink } = useLinkInsert() const inputRef = useRef(null) useEffect(() => { if (link) { inputRef.current?.focus() } }, [link]) return ( { setLink(null) setTimeout(() => editor.focus(), 100) }} >
{ setLink(null) // I think bootstrap messes with the focus on close so we have to do this ourselves setTimeout(() => editor.focus(), 100) }} >X
{ editor.dispatchCommand(INSERT_LINK_COMMAND, { url: ensureProtocol(url), text }) await setLink(null) setTimeout(() => editor.focus(), 100) }} >
ok
) }