import { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext' import { useCallback, useEffect, useRef, useState } from 'react' import { SELECTION_CHANGE_COMMAND, FORMAT_TEXT_COMMAND, INDENT_CONTENT_COMMAND, OUTDENT_CONTENT_COMMAND, $getSelection, $isRangeSelection, $createParagraphNode } from 'lexical' import { $isLinkNode, TOGGLE_LINK_COMMAND } from '@lexical/link' import { $wrapNodes } from '@lexical/selection' import { $getNearestNodeOfType, mergeRegister } from '@lexical/utils' import { INSERT_ORDERED_LIST_COMMAND, INSERT_UNORDERED_LIST_COMMAND, REMOVE_LIST_COMMAND, $isListNode, ListNode } from '@lexical/list' import { $createHeadingNode, $createQuoteNode, $isHeadingNode } from '@lexical/rich-text' // import { // $createCodeNode // } from '@lexical/code' import BoldIcon from '../../svgs/bold.svg' import ItalicIcon from '../../svgs/italic.svg' // import StrikethroughIcon from '../../svgs/strikethrough.svg' import LinkIcon from '../../svgs/link.svg' import ListOrderedIcon from '../../svgs/list-ordered.svg' import ListUnorderedIcon from '../../svgs/list-unordered.svg' import IndentIcon from '../../svgs/indent-increase.svg' import OutdentIcon from '../../svgs/indent-decrease.svg' import ImageIcon from '../../svgs/image-line.svg' import FontSizeIcon from '../../svgs/font-size-2.svg' import QuoteIcon from '../../svgs/double-quotes-r.svg' // import CodeIcon from '../../svgs/code-line.svg' // import CodeBoxIcon from '../../svgs/code-box-line.svg' import ArrowDownIcon from '../../svgs/arrow-down-s-fill.svg' import CheckIcon from '../../svgs/check-line.svg' import styles from '../styles.module.css' import { Dropdown } from 'react-bootstrap' import { useLinkInsert } from './link-insert' import { getSelectedNode } from '../utils/selected-node' import { getLinkFromSelection } from '../utils/link-from-selection' import { ImageInsertModal } from './image-insert' import useModal from '../utils/modal' const LowPriority = 1 function Divider () { return
} function FontSizeDropdown ({ editor, blockType }) { const formatParagraph = () => { if (blockType !== 'paragraph') { editor.update(() => { const selection = $getSelection() if ($isRangeSelection(selection)) { $wrapNodes(selection, () => $createParagraphNode()) } setTimeout(() => editor.focus(), 100) }) } } const formatLargeHeading = () => { if (blockType !== 'h1') { editor.update(() => { const selection = $getSelection() if ($isRangeSelection(selection)) { $wrapNodes(selection, () => $createHeadingNode('h1')) } setTimeout(() => editor.focus(), 100) }) } } const formatSmallHeading = () => { if (blockType !== 'h2') { editor.update(() => { const selection = $getSelection() if ($isRangeSelection(selection)) { $wrapNodes(selection, () => $createHeadingNode('h2')) } setTimeout(() => editor.focus(), 100) }) } } return ( normal subheading heading ) } export default function ToolbarPlugin () { const [editor] = useLexicalComposerContext() const { setLink } = useLinkInsert() const toolbarRef = useRef(null) const [blockType, setBlockType] = useState('paragraph') const [isLink, setIsLink] = useState(false) const [isBold, setIsBold] = useState(false) const [isItalic, setIsItalic] = useState(false) // const [isStrikethrough, setIsStrikethrough] = useState(false) // const [isCode, setIsCode] = useState(false) const [modal, showModal] = useModal() const updateToolbar = useCallback(() => { const selection = $getSelection() if ($isRangeSelection(selection)) { const anchorNode = selection.anchor.getNode() const element = anchorNode.getKey() === 'root' ? anchorNode : anchorNode.getTopLevelElementOrThrow() const elementKey = element.getKey() const elementDOM = editor.getElementByKey(elementKey) if (elementDOM !== null) { if ($isListNode(element)) { const parentList = $getNearestNodeOfType(anchorNode, ListNode) const type = parentList ? parentList.getTag() : element.getTag() setBlockType(type) } else { const type = $isHeadingNode(element) ? element.getTag() : element.getType() setBlockType(type) } } // Update text format setIsBold(selection.hasFormat('bold')) setIsItalic(selection.hasFormat('italic')) // setIsStrikethrough(selection.hasFormat('strikethrough')) // setIsCode(selection.hasFormat('code')) // Update links const node = getSelectedNode(selection) const parent = node.getParent() if ($isLinkNode(parent) || $isLinkNode(node)) { setIsLink(true) } else { setIsLink(false) } } }, [editor]) useEffect(() => { return mergeRegister( editor.registerUpdateListener(({ editorState }) => { editorState.read(() => { updateToolbar() }) }), editor.registerCommand( SELECTION_CHANGE_COMMAND, (_payload, newEditor) => { updateToolbar() return false }, LowPriority ) ) }, [editor, updateToolbar]) const insertLink = useCallback(() => { if (isLink) { // unlink it editor.dispatchCommand(TOGGLE_LINK_COMMAND, null) } else { editor.update(() => { setLink(getLinkFromSelection()) }) } }, [editor, isLink]) const formatBulletList = () => { if (blockType !== 'ul') { editor.dispatchCommand(INSERT_UNORDERED_LIST_COMMAND) } else { editor.dispatchCommand(REMOVE_LIST_COMMAND) } } const formatNumberedList = () => { if (blockType !== 'ol') { editor.dispatchCommand(INSERT_ORDERED_LIST_COMMAND) } else { editor.dispatchCommand(REMOVE_LIST_COMMAND) } } const formatQuote = () => { if (blockType !== 'quote') { editor.update(() => { const selection = $getSelection() if ($isRangeSelection(selection)) { $wrapNodes(selection, () => $createQuoteNode()) } }) } else { editor.update(() => { const selection = $getSelection() if ($isRangeSelection(selection)) { $wrapNodes(selection, () => $createParagraphNode()) } }) } } // const formatCode = () => { // if (blockType !== 'code') { // editor.update(() => { // const selection = $getSelection() // if ($isRangeSelection(selection)) { // $wrapNodes(selection, () => { // const node = $createCodeNode() // node.setLanguage('plain') // return node // }) // } // }) // } // } return (
<> {/* */} {/* */} {/* */} {/* */} {modal}
) }