lexical-medium-editor 1.2.5 → 1.2.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -39,6 +39,7 @@ Here is an example of how to use the editor in your project:
39
39
  import { useRef } from "react";
40
40
  import Editor from "lexical-medium-editor";
41
41
  import { initialConfig } from "lexical-medium-editor/config";
42
+ import "lexical-medium-editor/styles.css";
42
43
 
43
44
  export default function App() {
44
45
  const editorRef = useRef(null);
@@ -59,3 +60,6 @@ export default function App() {
59
60
  );
60
61
  }
61
62
  ```
63
+
64
+ > [!TIP]
65
+ > You can also copy the CSS from `node_modules/lexical-medium-editor/dist-lib/lexical-medium-editor.css` into your own project and modify it to customize the editor's appearance.
@@ -1 +1 @@
1
- {"version":3,"file":"index.es.js","sources":["../src/components/InlineToolbar/utils.js","../src/Plugins/TextFormatPlugin.jsx","../src/components/InlineToolbar/LinkToolbar.jsx","../src/components/InlineToolbar/InlineToolbar.jsx","../src/Plugins/InlineToolbarPlugin.jsx","../src/components/CodeHighlightMenu/CodeMenu.jsx","../src/Plugins/CodePlugin.jsx","../src/Plugins/HorizontalDividerPlugin.jsx","../src/Plugins/ImagePlugin.jsx","../src/components/BlockToolbar/BlockToolbar.jsx","../src/Plugins/BlockToolbarPlugin.jsx","../src/Plugins/MathPlugin.jsx","../src/Plugins/ListPluginExtended.jsx","../src/Plugins/TabInterceptorPlugin.jsx","../src/Plugins/EditorExposePlugin.jsx","../src/Editor.jsx"],"sourcesContent":["export const OFFSCREEN_POSITION = -1000;\n\nexport function computeInlineToolbarPosition(\n boundingRectCoords,\n toolbarRef,\n topOffset = 0\n) {\n // Ensure the popover reference is valid\n if (!toolbarRef || !toolbarRef.current) {\n console.error(\"Invalid popover reference\");\n return {\n x: OFFSCREEN_POSITION,\n y: OFFSCREEN_POSITION,\n };\n }\n\n const toolbarElement = toolbarRef.current;\n\n const { x, y } = boundingRectCoords;\n const { width, height } = toolbarElement.getBoundingClientRect();\n\n const centerX = x - width / 2;\n const topY = y - height - topOffset;\n\n return {\n x: centerX,\n y: topY,\n };\n}\n\nexport function getBoundingRectCoords(range) {\n // Ensure the range is valid\n if (!range || typeof range.getBoundingClientRect !== \"function\") {\n console.error(\"Invalid DOM range\");\n return null;\n }\n\n const rect = range.getBoundingClientRect();\n\n const centerX = rect.left + rect.width / 2;\n const topY = rect.top + window.scrollY;\n\n return {\n x: centerX,\n y: topY,\n };\n}\n\nexport function computeBlockToolbarPosition(\n boundingRectCoords,\n toolbarRef,\n offset = 0\n) {\n // Ensure the popover reference is valid\n if (!toolbarRef || !toolbarRef.current) {\n console.error(\"Invalid popover reference\");\n return {\n x: OFFSCREEN_POSITION,\n y: OFFSCREEN_POSITION,\n };\n }\n\n const { x, y } = boundingRectCoords;\n\n const toolbarElement = toolbarRef.current;\n const { width, height } = toolbarElement.getBoundingClientRect();\n\n const toolbarX = x - width - offset;\n const toolbarY = y - height / 2;\n\n return {\n x: toolbarX,\n y: toolbarY,\n };\n}\n\nexport function computeCodeMenuPosition(\n codeBlockCoords,\n codeMenuRef,\n HORIZONTAL_OFFSET = 16,\n VERTICAL_OFFSET = 12\n) {\n // Ensure the popover reference is valid\n if (!codeMenuRef || !codeMenuRef.current) {\n console.error(\"Invalid popover reference\");\n return {\n x: OFFSCREEN_POSITION,\n y: OFFSCREEN_POSITION,\n };\n }\n\n const codeMenuElement = codeMenuRef.current;\n\n const { x, y } = codeBlockCoords;\n const { width } = codeMenuElement.getBoundingClientRect();\n\n const X = x - width - HORIZONTAL_OFFSET;\n const Y = y + VERTICAL_OFFSET;\n\n return {\n x: X,\n y: Y,\n };\n}\n","/* Plugins for formatting text */\n\nimport {\n $isHeadingNode,\n $createHeadingNode,\n $isQuoteNode,\n $createQuoteNode,\n HeadingNode,\n} from \"@lexical/rich-text\";\nimport { useLexicalComposerContext } from \"@lexical/react/LexicalComposerContext\";\nimport {\n COMMAND_PRIORITY_HIGH,\n createCommand,\n $getSelection,\n $isRangeSelection,\n $createParagraphNode,\n CLICK_COMMAND,\n COMMAND_PRIORITY_LOW,\n $getRoot,\n TextNode,\n $isParagraphNode,\n} from \"lexical\";\nimport { $setBlocksType } from \"@lexical/selection\";\nimport { useEffect } from \"react\";\nimport { $findMatchingParent } from \"@lexical/utils\";\nimport { $toggleLink, $isLinkNode } from \"@lexical/link\";\nimport { $isListNode } from \"@lexical/list\";\nimport \"@lexical/utils\";\nimport { $isAtNodeEnd } from \"@lexical/selection\";\n\nexport const TOGGLE_HEADING_COMMAND = createCommand(\"TOGGLE_HEADING_COMMAND\");\nexport const TOGGLE_QUOTE_COMMAND = createCommand(\"TOGGLE_QUOTE_COMMAND\");\nexport const TOGGLE_LINK_COMMAND = createCommand(\"TOGGLE_LINK_COMMAND\");\n\nexport function getSelectedNode(selection) {\n const anchor = selection.anchor;\n const focus = selection.focus;\n const anchorNode = selection.anchor.getNode();\n const focusNode = selection.focus.getNode();\n if (anchorNode === focusNode) {\n return anchorNode;\n }\n const isBackward = selection.isBackward();\n if (isBackward) {\n return $isAtNodeEnd(focus) ? anchorNode : focusNode;\n } else {\n return $isAtNodeEnd(anchor) ? anchorNode : focusNode;\n }\n}\n\n// Helper function to fetch the tag of a node if it or its ancestor is a heading node.\nfunction fetchTagIfHeadingNode(node) {\n const headingNode = $findMatchingParent(node, $isHeadingNode);\n return headingNode ? headingNode.getTag() : null;\n}\n\nexport function updateToolbarHeadingState(selection) {\n const toolbarHeadingState = {\n isHeadingOne: false,\n isHeadingTwo: false,\n isHeadingThree: false,\n };\n\n const nodes = selection.getNodes();\n if (!nodes.length) return toolbarHeadingState;\n\n const headingTag = fetchTagIfHeadingNode(nodes[0]);\n if (!headingTag) return toolbarHeadingState;\n\n const allMatch = nodes.every(\n (node) => fetchTagIfHeadingNode(node) === headingTag\n );\n\n if (allMatch) {\n const stateKey = {\n h1: \"isHeadingOne\",\n h2: \"isHeadingTwo\",\n h3: \"isHeadingThree\",\n }[headingTag];\n\n if (stateKey) toolbarHeadingState[stateKey] = true;\n }\n\n return toolbarHeadingState;\n}\n\nfunction HeadingPlugin() {\n const [editor] = useLexicalComposerContext();\n\n useEffect(() => {\n const unregisterListener = editor.registerCommand(\n TOGGLE_HEADING_COMMAND,\n (toolbarState) => {\n const { isHeadingOne, isHeadingTwo, isHeadingThree } = toolbarState;\n const selection = $getSelection();\n\n if ($isRangeSelection(selection)) {\n let tag;\n\n // Apply the toggling logic based on current state in toolbar\n if (isHeadingOne) {\n // H1 --> H3\n tag = \"h3\";\n } else if (isHeadingTwo) {\n // H2 --> H3\n tag = \"h3\";\n } else if (isHeadingThree) {\n // H3 --> None (paragraph)\n tag = null;\n } else {\n // None --> H2\n tag = \"h2\";\n }\n\n // Apply the heading or paragraph node\n $setBlocksType(selection, () =>\n tag ? $createHeadingNode(tag) : $createParagraphNode()\n );\n }\n return true;\n },\n COMMAND_PRIORITY_HIGH\n );\n return unregisterListener;\n }, [editor]);\n\n return null;\n}\n\nfunction HeadingOneFirstPlugin() {\n const [editor] = useLexicalComposerContext();\n\n // Effect for NodeTransform: H2 at start -> H1\n useEffect(() => {\n const unregisterTransform = editor.registerNodeTransform(\n HeadingNode,\n (node) => {\n // Check if it's an H2 node\n if (node.getTag() !== \"h2\") {\n return;\n }\n\n // Get the root node and the first child\n const root = $getRoot();\n const firstChild = root.getFirstChild();\n\n // Check if this H2 node is the very first child of the root\n if (firstChild !== null && node.is(firstChild)) {\n const children = node.getChildren();\n const h1Node = $createHeadingNode(\"h1\");\n h1Node.append(...children);\n node.replace(h1Node);\n }\n }\n );\n\n return () => {\n unregisterTransform();\n };\n }, [editor]);\n\n return null;\n}\n\n// Helper function to check if a node or its ancestor is a quote node\nfunction isNodeOrAncestorQuote(node) {\n return $findMatchingParent(node, $isQuoteNode);\n}\n\nexport function updateToolbarQuoteState(selection) {\n const nodes = selection.getNodes();\n if (!nodes.length) return false;\n\n // Check if all nodes are within quote blocks\n return nodes.length > 0 && nodes.every((node) => isNodeOrAncestorQuote(node));\n}\n\nfunction QuotePlugin() {\n const [editor] = useLexicalComposerContext();\n\n useEffect(() => {\n const unregisterListener = editor.registerCommand(\n TOGGLE_QUOTE_COMMAND,\n (toolbarState) => {\n const selection = $getSelection();\n\n if ($isRangeSelection(selection)) {\n $setBlocksType(selection, () =>\n toolbarState.isQuote ? $createParagraphNode() : $createQuoteNode()\n );\n }\n return true;\n },\n COMMAND_PRIORITY_HIGH\n );\n return unregisterListener;\n }, [editor]);\n\n return null;\n}\n\nexport function getLinkAtSelection(selection) {\n if (!$isRangeSelection(selection)) {\n return null;\n }\n\n const node = getSelectedNode(selection);\n return $findMatchingParent(node, $isLinkNode);\n}\n\nfunction LinkPlugin() {\n const [editor] = useLexicalComposerContext();\n\n // If a link node is clicked while holding the ctrl key, open the link in a new tab\n useEffect(() => {\n const unregisterListener = editor.registerCommand(\n CLICK_COMMAND,\n (payload) => {\n const selection = $getSelection();\n const linkNode = getLinkAtSelection(selection);\n if (linkNode && (payload.metaKey || payload.ctrlKey)) {\n window.open(linkNode.getURL(), \"_blank\");\n return true;\n }\n return false;\n },\n COMMAND_PRIORITY_LOW\n );\n return unregisterListener;\n }, [editor]);\n\n useEffect(() => {\n const unregisterListener = editor.registerCommand(\n TOGGLE_LINK_COMMAND,\n (linkURL) => {\n $toggleLink(linkURL);\n return true;\n },\n COMMAND_PRIORITY_HIGH\n );\n return unregisterListener;\n }, [editor]);\n\n return null;\n}\n\n/* Adds a CSS class to ElementNodes (excluding HeadingNodes) that follow a HeadingNode. */\nfunction AdjacentHeadingPlugin() {\n const [editor] = useLexicalComposerContext();\n const HEADING_ABOVE_CLASS = \"heading-above\";\n\n useEffect(() => {\n const unregisterTransform = editor.registerNodeTransform(\n TextNode,\n (textNode) => {\n const parentNode =\n $findMatchingParent(textNode, $isParagraphNode) ||\n $findMatchingParent(textNode, $isListNode);\n\n if (!parentNode) {\n return;\n }\n\n if ($isHeadingNode(parentNode)) {\n return;\n }\n\n const node = parentNode;\n\n const element = editor.getElementByKey(node.getKey());\n if (!element) {\n return;\n }\n\n const prevSibling = node.getPreviousSibling();\n const shouldHaveClass = $isHeadingNode(prevSibling);\n\n // Check if the DOM element *currently* has the class.\n const alreadyHasClass = element.classList.contains(HEADING_ABOVE_CLASS);\n\n // Add or remove the class directly on the DOM element to achieve the desired state.\n if (shouldHaveClass && !alreadyHasClass) {\n element.classList.add(HEADING_ABOVE_CLASS);\n } else if (!shouldHaveClass && alreadyHasClass) {\n element.classList.remove(HEADING_ABOVE_CLASS);\n }\n }\n );\n\n return unregisterTransform;\n }, [editor]);\n\n return null;\n}\n\nexport function TextFormatPlugin({ isHeadingOneFirst }) {\n return (\n <>\n <HeadingPlugin />\n {isHeadingOneFirst && <HeadingOneFirstPlugin />}\n <QuotePlugin />\n <LinkPlugin />\n <AdjacentHeadingPlugin />\n </>\n );\n}\n","import {\n Button,\n Group,\n Toolbar,\n TextField,\n Input,\n} from \"react-aria-components\";\nimport { IconCheck, IconX } from \"@tabler/icons-react\";\nimport { ICON_SIZE } from \"./InlineToolbar\";\nimport { useState } from \"react\";\nimport { TOGGLE_LINK_COMMAND } from \"../../Plugins/TextFormatPlugin\";\nimport { useLexicalComposerContext } from \"@lexical/react/LexicalComposerContext\";\n\nimport \"./styles/LinkToolbar.css\";\n\nexport function LinkToolbar({ style, closeToolbar, existingLinkURL }) {\n const [editor] = useLexicalComposerContext();\n const [linkURL, setLinkURL] = useState(existingLinkURL);\n\n // TODO: The left and right arrow keys aren't working at all. Need to debug.\n\n return (\n <Toolbar style={style} aria-details=\"link toolbar\" id=\"link-toolbar\">\n <TextField\n aria-label=\"url\"\n autoFocus={true}\n defaultValue={linkURL}\n onChange={setLinkURL}\n >\n <Input placeholder=\"Enter Link\" />\n </TextField>\n <Group aria-label=\"edit link\">\n <Button\n aria-label=\"Update link\"\n onPress={() => {\n const url = linkURL === \"\" ? null : linkURL;\n editor.dispatchCommand(TOGGLE_LINK_COMMAND, url);\n closeToolbar();\n }}\n >\n <IconCheck size={ICON_SIZE} />\n </Button>\n <Button aria-label=\"Discard changes\" onPress={closeToolbar}>\n <IconX size={ICON_SIZE} />\n </Button>\n </Group>\n <div className=\"inline-toolbar-pointer\"></div>\n </Toolbar>\n );\n}\n","import {\r\n Button,\r\n Group,\r\n Separator,\r\n ToggleButton,\r\n Toolbar,\r\n} from \"react-aria-components\";\r\nimport {\r\n IconBold,\r\n IconItalic,\r\n IconCode,\r\n IconTextSize,\r\n IconBlockquote,\r\n IconLink,\r\n} from \"@tabler/icons-react\";\r\nimport { useEffect, useState, useRef, useLayoutEffect } from \"react\";\r\nimport {\r\n $getSelection,\r\n $isRangeSelection,\r\n $getCharacterOffsets,\r\n FORMAT_TEXT_COMMAND,\r\n} from \"lexical\";\r\nimport { createDOMRange } from \"@lexical/selection\";\r\nimport {\r\n computeInlineToolbarPosition,\r\n OFFSCREEN_POSITION,\r\n getBoundingRectCoords,\r\n} from \"./utils\";\r\nimport {\r\n TOGGLE_HEADING_COMMAND,\r\n TOGGLE_QUOTE_COMMAND,\r\n updateToolbarHeadingState,\r\n updateToolbarQuoteState,\r\n getLinkAtSelection,\r\n} from \"../../Plugins/TextFormatPlugin\";\r\nimport { LinkToolbar } from \"./LinkToolbar\";\r\n\r\nimport \"./styles/Toolbar.css\";\r\n\r\nexport const ICON_SIZE = 24;\r\nconst TOP_OFFSET = 16;\r\n\r\nexport default function InlineToolbar({ editor }) {\r\n // State for storing the bounding rectangle coordinates of the selection\r\n const [selectionRectCoords, setSelectionRectCoords] = useState(null);\r\n // State for storing the toolbar's position (x, y coordinates)\r\n const [toolbarPosition, setToolbarPosition] = useState({\r\n x: OFFSCREEN_POSITION,\r\n y: OFFSCREEN_POSITION,\r\n });\r\n const toolbarRef = useRef(null);\r\n const [toolbarState, setToolbarState] = useState({\r\n isBold: false,\r\n isItalic: false,\r\n isCode: false,\r\n isHeadingOne: false,\r\n isHeadingTwo: false,\r\n isHeadingThree: false,\r\n isQuote: false,\r\n });\r\n\r\n // Link toolbar state\r\n const [isLinkToolbarVisible, setLinkToolbarVisible] = useState(false);\r\n const [toolbarWidth, setToolbarWidth] = useState(0);\r\n const [existingLinkURL, setExistingLinkURL] = useState(\"\");\r\n\r\n // Logic for updating/setting toolbar state\r\n const updateToolbarFormatState = (selection) => {\r\n if ($isRangeSelection(selection)) {\r\n setToolbarState({\r\n isBold: selection.hasFormat(\"bold\"),\r\n isItalic: selection.hasFormat(\"italic\"),\r\n isCode: selection.hasFormat(\"code\"),\r\n isQuote: updateToolbarQuoteState(selection),\r\n });\r\n\r\n // update/set heading state\r\n const toolbarHeadingState = updateToolbarHeadingState(selection);\r\n setToolbarState((prev) => ({\r\n ...prev,\r\n ...toolbarHeadingState,\r\n }));\r\n\r\n // Set the link URL if the selection is at a link node\r\n const linkNode = getLinkAtSelection(selection);\r\n setExistingLinkURL(linkNode ? linkNode.getURL() : \"\");\r\n }\r\n };\r\n\r\n // Initialize toolbar state on component mount\r\n useEffect(() => {\r\n editor.read(() => {\r\n const selection = $getSelection();\r\n updateToolbarFormatState(selection);\r\n });\r\n }, [editor]);\r\n\r\n // Update toolbar state\r\n useEffect(() => {\r\n const unregisterListener = editor.registerUpdateListener(\r\n ({ editorState }) => {\r\n editorState.read(() => {\r\n const selection = $getSelection();\r\n updateToolbarFormatState(selection);\r\n });\r\n }\r\n );\r\n return unregisterListener;\r\n }, [editor]);\r\n\r\n // Update selection rectangle coordinates when toolbar state changes\r\n useEffect(() => {\r\n editor.read(() => {\r\n const selection = $getSelection();\r\n if ($isRangeSelection(selection)) {\r\n // Create a DOM range from the selection\r\n const [anchorPoint, focusPoint] = selection.getStartEndPoints();\r\n const [anchorNode, focusNode] = [\r\n anchorPoint.getNode(),\r\n focusPoint.getNode(),\r\n ];\r\n const [anchorOffset, focusOffset] = $getCharacterOffsets(selection);\r\n const selectionDOMRange = createDOMRange(\r\n editor,\r\n anchorNode,\r\n anchorOffset,\r\n focusNode,\r\n focusOffset\r\n );\r\n\r\n // Set bounding rect coords\r\n setSelectionRectCoords(getBoundingRectCoords(selectionDOMRange));\r\n }\r\n });\r\n }, [editor, toolbarState]);\r\n\r\n // Update toolbar position\r\n useEffect(() => {\r\n if (selectionRectCoords) {\r\n setToolbarPosition(\r\n computeInlineToolbarPosition(\r\n selectionRectCoords,\r\n toolbarRef,\r\n TOP_OFFSET\r\n )\r\n );\r\n setTimeout(() => {\r\n toolbarRef.current?.classList.add(\"visible\");\r\n }, 50);\r\n } else {\r\n toolbarRef.current?.classList.remove(\"visible\");\r\n }\r\n }, [selectionRectCoords]);\r\n\r\n // Capture the width of the inline toolbar after it has been rendered\r\n useLayoutEffect(() => {\r\n if (toolbarRef.current) {\r\n const computedStyle = window.getComputedStyle(toolbarRef.current);\r\n const width = parseFloat(computedStyle.width);\r\n setToolbarWidth(width);\r\n }\r\n }, [selectionRectCoords]);\r\n\r\n // TODO: LinkToolbar should not be a separate toolbar.\r\n // It should be a part of the InlineToolbar\r\n\r\n return (\r\n selectionRectCoords &&\r\n (isLinkToolbarVisible ? (\r\n <LinkToolbar\r\n style={{\r\n position: \"absolute\",\r\n top: toolbarPosition.y,\r\n left: toolbarPosition.x,\r\n width: toolbarWidth,\r\n }}\r\n closeToolbar={() => {\r\n setLinkToolbarVisible(false);\r\n setSelectionRectCoords(null);\r\n }}\r\n existingLinkURL={existingLinkURL}\r\n />\r\n ) : (\r\n <Toolbar\r\n style={{\r\n position: \"absolute\",\r\n top: toolbarPosition.y,\r\n left: toolbarPosition.x,\r\n }}\r\n aria-label=\"Text formatting\"\r\n id=\"inline-toolbar\"\r\n ref={toolbarRef}\r\n >\r\n <Group aria-label=\"Style\">\r\n <ToggleButton\r\n aria-label=\"Bold\"\r\n isSelected={toolbarState.isBold}\r\n isDisabled={\r\n toolbarState.isCode ||\r\n toolbarState.isHeadingOne ||\r\n toolbarState.isHeadingTwo ||\r\n toolbarState.isHeadingThree\r\n }\r\n onChange={() => editor.dispatchCommand(FORMAT_TEXT_COMMAND, \"bold\")}\r\n >\r\n <IconBold size={ICON_SIZE} />\r\n </ToggleButton>\r\n <ToggleButton\r\n aria-label=\"Italic\"\r\n isSelected={toolbarState.isItalic}\r\n isDisabled={toolbarState.isCode || toolbarState.isHeadingOne}\r\n onChange={() =>\r\n editor.dispatchCommand(FORMAT_TEXT_COMMAND, \"italic\")\r\n }\r\n >\r\n <IconItalic size={ICON_SIZE} />\r\n </ToggleButton>\r\n <ToggleButton\r\n aria-label=\"inline-code\"\r\n isDisabled={toolbarState.isHeadingOne}\r\n isSelected={toolbarState.isCode}\r\n onChange={() => editor.dispatchCommand(FORMAT_TEXT_COMMAND, \"code\")}\r\n >\r\n <IconCode size={ICON_SIZE} />\r\n </ToggleButton>\r\n </Group>\r\n <Separator orientation=\"vertical\" />\r\n <Group aria-label=\"Text Blocks\">\r\n <ToggleButton\r\n aria-label=\"Heading\"\r\n isSelected={\r\n toolbarState.isHeadingOne ||\r\n toolbarState.isHeadingTwo ||\r\n toolbarState.isHeadingThree\r\n }\r\n onChange={() =>\r\n editor.dispatchCommand(TOGGLE_HEADING_COMMAND, toolbarState)\r\n }\r\n >\r\n <IconTextSize size={ICON_SIZE} />\r\n </ToggleButton>\r\n <ToggleButton\r\n aria-label=\"Quote\"\r\n isSelected={toolbarState.isQuote}\r\n onChange={() =>\r\n editor.dispatchCommand(TOGGLE_QUOTE_COMMAND, toolbarState)\r\n }\r\n >\r\n <IconBlockquote size={ICON_SIZE} />\r\n </ToggleButton>\r\n </Group>\r\n <Separator orientation=\"vertical\" />\r\n <Group aria-label=\"Links\">\r\n <Button\r\n onPress={() => setLinkToolbarVisible(true)}\r\n isDisabled={toolbarState.isHeadingOne}\r\n >\r\n <IconLink size={ICON_SIZE} />\r\n </Button>\r\n </Group>\r\n <div className=\"inline-toolbar-pointer\"></div>\r\n </Toolbar>\r\n ))\r\n );\r\n}\r\n","import { useLexicalComposerContext } from \"@lexical/react/LexicalComposerContext\";\nimport {\n $getSelection,\n $isRangeSelection,\n SELECTION_CHANGE_COMMAND,\n COMMAND_PRIORITY_HIGH,\n} from \"lexical\";\nimport { useEffect, useState } from \"react\";\nimport { createPortal } from \"react-dom\";\nimport { $findMatchingParent } from \"@lexical/utils\";\n\nimport InlineToolbar from \"../components/InlineToolbar/InlineToolbar\";\nimport { $isMathNode } from \"../nodes/MathNode\";\nimport {\n $isMathHighlightNodeBlock,\n $isMathHighlightNodeInline,\n} from \"../nodes/MathHighlightNode\";\nimport { $isCodeNode } from \"@lexical/code\";\n\nconst DOM_ELEMENT = document.body;\n\nexport default function InlineToolbarPlugin() {\n const [shouldShow, setShouldShow] = useState(false);\n const [editor] = useLexicalComposerContext();\n\n // Listen for selection changes and show/hide the toolbar\n useEffect(() => {\n const unregisterListener = editor.registerCommand(\n SELECTION_CHANGE_COMMAND,\n () => {\n const selection = $getSelection();\n\n if (!$isRangeSelection(selection) || selection.isCollapsed()) {\n setShouldShow(false);\n return false;\n }\n\n // Get all selected nodes\n const nodes = selection.getNodes();\n\n // Don't show if any Math nodes are in the selection\n const hasMathNode = nodes.some((node) => $isMathNode(node));\n\n // Don't show if only one node is selected and it's a MathHighlightNode\n const isSingleMathHighlight =\n nodes.length === 1 &&\n ($isMathHighlightNodeInline(nodes[0]) ||\n $findMatchingParent(nodes[0], $isMathHighlightNodeBlock));\n\n const isCodeBlock = nodes.some((node) =>\n $findMatchingParent(node, $isCodeNode)\n );\n\n setShouldShow(!hasMathNode && !isSingleMathHighlight && !isCodeBlock);\n return false;\n },\n COMMAND_PRIORITY_HIGH\n );\n return unregisterListener;\n }, [editor]);\n\n return (\n shouldShow && createPortal(<InlineToolbar editor={editor} />, DOM_ELEMENT)\n );\n}\n","import {\n Button,\n ComboBox,\n Input,\n ListBox,\n ListBoxItem,\n Popover,\n} from \"react-aria-components\";\nimport { IconCaretDownFilled } from \"@tabler/icons-react\";\nimport { useState, useRef, useEffect } from \"react\";\nimport { OFFSCREEN_POSITION } from \"../InlineToolbar/utils\";\nimport { computeCodeMenuPosition } from \"../InlineToolbar/utils\";\nimport { getCodeLanguages, getLanguageFriendlyName } from \"@lexical/code\";\nimport \"./styles.css\";\nimport { useLexicalComposerContext } from \"@lexical/react/LexicalComposerContext\";\nimport { $getNodeByKey } from \"lexical\";\nimport { SET_CODE_LANGUAGE_COMMAND } from \"../../Plugins/CodePlugin\";\n\nexport function CodeMenu({ codeBlockCoords, codeNodeKey }) {\n const [editor] = useLexicalComposerContext();\n const [codeMenuPosition, setCodeMenuPosition] = useState({\n x: OFFSCREEN_POSITION,\n y: OFFSCREEN_POSITION,\n });\n const codeMenuRef = useRef(null);\n const [language, setLanguage] = useState(\"\");\n\n // Get the available code languages\n const codeLanguages = getCodeLanguages();\n\n // Create a unique set of friendly language names\n const friendlyLanguages = Array.from(\n new Set(codeLanguages.map((lang) => getLanguageFriendlyName(lang)))\n );\n\n // Create a reverse dictionary for friendly languages\n const friendlyToOriginal = {};\n codeLanguages.forEach((lang) => {\n const friendly = getLanguageFriendlyName(lang);\n if (!friendlyToOriginal[friendly]) {\n friendlyToOriginal[friendly] = lang;\n }\n });\n\n // Update toolbar position when selection changes\n useEffect(() => {\n setCodeMenuPosition(computeCodeMenuPosition(codeBlockCoords, codeMenuRef));\n }, [codeBlockCoords]);\n\n // Set the current language of the code block\n useEffect(() => {\n editor.read(() => {\n if (codeNodeKey) {\n const codeNode = $getNodeByKey(codeNodeKey);\n const currentLanguage = codeNode.getLanguage();\n setLanguage(getLanguageFriendlyName(currentLanguage));\n }\n });\n }, [editor, codeNodeKey]);\n\n return (\n <ComboBox\n ref={codeMenuRef}\n style={{\n position: \"absolute\",\n top: codeMenuPosition.y,\n left: codeMenuPosition.x,\n }}\n aria-label=\"Code menu\"\n inputValue={language}\n onInputChange={(friendlyValue) => {\n const originalValue = friendlyToOriginal[friendlyValue];\n editor.dispatchCommand(SET_CODE_LANGUAGE_COMMAND, [\n codeNodeKey,\n originalValue,\n ]);\n setLanguage(friendlyValue);\n }}\n >\n <div>\n <Input />\n <Button>\n <IconCaretDownFilled size={24} />\n </Button>\n </div>\n <Popover>\n <ListBox>\n {friendlyLanguages.map((friendly, index) => (\n <ListBoxItem key={index}>{friendly}</ListBoxItem>\n ))}\n </ListBox>\n </Popover>\n </ComboBox>\n );\n}\n","import {\n $createCodeNode,\n $isCodeNode,\n registerCodeHighlighting,\n} from \"@lexical/code\";\nimport { useLexicalComposerContext } from \"@lexical/react/LexicalComposerContext\";\nimport {\n $getPreviousSelection,\n $isRangeSelection,\n COMMAND_PRIORITY_HIGH,\n createCommand,\n $getSelection,\n SELECTION_CHANGE_COMMAND,\n $getNodeByKey,\n KEY_BACKSPACE_COMMAND,\n TextNode,\n $isLineBreakNode,\n $isParagraphNode,\n} from \"lexical\";\nimport { useEffect, useState } from \"react\";\nimport { createPortal } from \"react-dom\";\nimport { getSelectedNode } from \"./TextFormatPlugin\";\nimport { $findMatchingParent } from \"@lexical/utils\";\nimport { CodeMenu } from \"../components/CodeHighlightMenu/CodeMenu\";\n\nconst DOM_ELEMENT = document.body;\n\nexport const INSERT_CODE_BLOCK_COMMAND = createCommand(\n \"INSERT_CODE_BLOCK_COMMAND\"\n);\nexport const SET_CODE_LANGUAGE_COMMAND = createCommand(\n \"SET_CODE_LANGUAGE_COMMAND\"\n);\n\nfunction CodeHighlightMenuPlugin() {\n const [codeBlockCoords, setCodeBlockCoords] = useState(null);\n const [codeNodeKey, setCodeNodeKey] = useState(null);\n const [editor] = useLexicalComposerContext();\n\n useEffect(() => {\n const unregisterListener = editor.registerCommand(\n SELECTION_CHANGE_COMMAND,\n () => {\n const selection = $getSelection();\n\n if (!$isRangeSelection(selection)) {\n setCodeBlockCoords(null);\n return false;\n }\n\n const node = getSelectedNode(selection);\n const codeNode = $findMatchingParent(node, $isCodeNode);\n if (codeNode) {\n // update selection coordinates when selection changes and the condition is met\n const DOMElement = editor.getElementByKey(codeNode.getKey());\n const boundingRect = DOMElement.getBoundingClientRect();\n\n // Use top-right coordinates\n const X = boundingRect.right;\n const Y = boundingRect.top + window.scrollY;\n\n setCodeBlockCoords({ x: X, y: Y });\n setCodeNodeKey(codeNode.getKey());\n } else {\n setCodeBlockCoords(null);\n }\n\n return false;\n },\n COMMAND_PRIORITY_HIGH\n );\n return unregisterListener;\n }, [editor]);\n\n return (\n codeBlockCoords &&\n createPortal(\n <CodeMenu codeBlockCoords={codeBlockCoords} codeNodeKey={codeNodeKey} />,\n DOM_ELEMENT\n )\n );\n}\n\nfunction CodeBlockPlugin() {\n const [editor] = useLexicalComposerContext();\n\n useEffect(() => {\n return registerCodeHighlighting(editor);\n }, [editor]);\n\n useEffect(() => {\n const removeTransform = editor.registerNodeTransform(TextNode, (node) => {\n if (!node.isSimpleText()) {\n return;\n }\n\n const text = node.getTextContent();\n\n // Check for Code Block Trigger: \"``` \" at start of line/paragraph\n if (text.startsWith(\"``` \")) {\n const prevSibling = node.getPreviousSibling();\n const parentNode = $findMatchingParent(node, $isParagraphNode);\n const isStartOfParagraph =\n parentNode !== null && parentNode.getChildrenSize() === 1;\n const isAfterLineBreak = $isLineBreakNode(prevSibling);\n\n if (isStartOfParagraph || isAfterLineBreak) {\n // If there is more text after \"``` \", don't do anything\n if (text.length > 4) {\n return;\n }\n\n // Create the new code block\n const codeNode = $createCodeNode();\n\n // Replace \"``` \" with the code block\n node.replace(codeNode);\n\n // Select the code block\n codeNode.select();\n\n // Check if the next sibling is a LineBreakNode and remove it\n const nextSibling = codeNode.getNextSibling();\n if ($isLineBreakNode(nextSibling)) {\n nextSibling.remove();\n }\n\n return;\n }\n }\n });\n\n return removeTransform;\n }, [editor]);\n\n useEffect(() => {\n const unregisterCommand = editor.registerCommand(\n INSERT_CODE_BLOCK_COMMAND,\n () => {\n const prevSelection = $getPreviousSelection();\n if ($isRangeSelection(prevSelection)) {\n const codeBlockNode = $createCodeNode();\n prevSelection.insertNodes([codeBlockNode]);\n codeBlockNode.selectStart();\n\n // Bring the focus back to the editor\n setTimeout(() => {\n editor.focus();\n }, 0);\n\n return true;\n }\n\n return false;\n },\n COMMAND_PRIORITY_HIGH\n );\n\n return unregisterCommand;\n }, [editor]);\n\n useEffect(() => {\n const unregisterCommand = editor.registerCommand(\n SET_CODE_LANGUAGE_COMMAND,\n (payload) => {\n const [nodeKey, language] = payload;\n const codeNode = $getNodeByKey(nodeKey);\n if ($isCodeNode(codeNode)) {\n codeNode.setLanguage(language);\n return true;\n }\n\n return false;\n },\n COMMAND_PRIORITY_HIGH\n );\n\n return unregisterCommand;\n }, [editor]);\n\n useEffect(() => {\n const unregisterCommand = editor.registerCommand(\n KEY_BACKSPACE_COMMAND,\n (payload) => {\n const selection = $getSelection();\n if (!$isRangeSelection(selection) || !selection.isCollapsed()) {\n return false;\n }\n\n const node = selection.anchor.getNode();\n const codeNode = $findMatchingParent(node, $isCodeNode);\n\n if (codeNode) {\n // Check if we are at the beginning of the code block\n if (selection.anchor.offset === 0) {\n // Check if code block is empty (only has empty text node or line break)\n const textContent = codeNode.getTextContent();\n if (textContent === \"\") {\n codeNode.remove();\n return true;\n }\n }\n }\n\n return false;\n },\n COMMAND_PRIORITY_HIGH\n );\n\n return unregisterCommand;\n }, [editor]);\n\n return null;\n}\n\nexport function CodePlugin() {\n return (\n <>\n <CodeBlockPlugin />\n <CodeHighlightMenuPlugin />\n </>\n );\n}\n","import { useLexicalComposerContext } from \"@lexical/react/LexicalComposerContext\";\nimport {\n COMMAND_PRIORITY_HIGH,\n createCommand,\n $getPreviousSelection,\n $isRangeSelection,\n $createParagraphNode,\n} from \"lexical\";\nimport { useEffect } from \"react\";\nimport {\n $createHorizontalDividerNode,\n HorizontalDividerNode,\n} from \"../nodes/HorizontalDividerNode\";\n\nexport const INSERT_HORIZONTAL_DIVIDER_COMMAND = createCommand(\n \"INSERT_HORIZONTAL_DIVIDER_COMMAND\"\n);\n\nexport function HorizontalDividerPlugin() {\n const [editor] = useLexicalComposerContext();\n\n useEffect(() => {\n if (!editor.hasNodes([HorizontalDividerNode])) {\n throw new Error(\"HorizontalDividerNode not registered on editor\");\n }\n\n const unregisterCommand = editor.registerCommand(\n INSERT_HORIZONTAL_DIVIDER_COMMAND,\n () => {\n const prevSelection = $getPreviousSelection();\n\n if ($isRangeSelection(prevSelection)) {\n const horizontalDividerNode = $createHorizontalDividerNode();\n prevSelection.insertNodes([horizontalDividerNode]);\n\n // Move the selection to the next line after the divider\n let nextNode =\n horizontalDividerNode.getNextSibling() ||\n horizontalDividerNode.getParent().getNextSibling();\n\n if (!nextNode) {\n nextNode = $createParagraphNode();\n horizontalDividerNode.insertAfter(nextNode);\n }\n nextNode.selectStart();\n\n // Bring the focus back to the editor\n setTimeout(() => {\n editor.focus();\n }, 0);\n\n return true;\n }\n\n return false;\n },\n COMMAND_PRIORITY_HIGH\n );\n\n return unregisterCommand;\n }, [editor]);\n\n return null;\n}\n","import { useLexicalComposerContext } from \"@lexical/react/LexicalComposerContext\";\nimport {\n createCommand,\n COMMAND_PRIORITY_HIGH,\n $getPreviousSelection,\n $isRangeSelection,\n $createParagraphNode,\n SELECTION_CHANGE_COMMAND,\n $getSelection,\n $isNodeSelection,\n COMMAND_PRIORITY_LOW,\n $getNodeByKey,\n PASTE_COMMAND,\n} from \"lexical\";\nimport { useEffect, useRef } from \"react\";\nimport { $createImageNode, $isImageNode, ImageNode } from \"../nodes/ImageNode\";\nimport { NodeEventPlugin } from \"@lexical/react/LexicalNodeEventPlugin\";\n\nexport const INSERT_IMAGE_COMMAND = createCommand(\"INSERT_IMAGE_COMMAND\");\nconst SELECTED_CLASS_NAME = \"selected\";\n\n// Helper to check if a file is an image\nfunction isImageFile(file) {\n return file && file.type && file.type.startsWith(\"image/\");\n}\n\nexport function ImagePlugin() {\n const [editor] = useLexicalComposerContext();\n const selectedImgElemRef = useRef(null);\n\n useEffect(() => {\n if (!editor.hasNode(ImageNode)) {\n throw new Error(\"ImagePlugin: ImageNode not registered on editor\");\n }\n\n const unregisterCommand = editor.registerCommand(\n INSERT_IMAGE_COMMAND,\n (payload) => {\n const src = payload;\n const prevSelection = $getPreviousSelection();\n\n if ($isRangeSelection(prevSelection)) {\n const imageNode = $createImageNode(src);\n prevSelection.insertNodes([imageNode]);\n\n let nextNode =\n imageNode.getNextSibling() ||\n imageNode.getParent().getNextSibling();\n\n // insert a new paragraph node after the image node\n if (!nextNode) {\n nextNode = $createParagraphNode();\n imageNode.insertAfter(nextNode);\n }\n\n // select the image after inserting\n imageNode.select();\n\n return true;\n }\n\n return false;\n },\n COMMAND_PRIORITY_HIGH\n );\n\n return unregisterCommand;\n }, [editor]);\n\n // handle selection\n useEffect(() => {\n const unregisterCommand = editor.registerCommand(\n SELECTION_CHANGE_COMMAND,\n () => {\n // clear previous selection\n if (selectedImgElemRef.current) {\n selectedImgElemRef.current.classList.remove(SELECTED_CLASS_NAME);\n selectedImgElemRef.current = null;\n }\n\n const selection = $getSelection();\n if ($isNodeSelection(selection) && selection.getNodes().length === 1) {\n const node = selection.getNodes()[0];\n if ($isImageNode(node)) {\n const DOMElement = editor.getElementByKey(node.getKey());\n DOMElement.classList.add(SELECTED_CLASS_NAME);\n selectedImgElemRef.current = DOMElement;\n }\n }\n\n return false;\n },\n COMMAND_PRIORITY_LOW\n );\n\n return unregisterCommand;\n }, [editor]);\n\n // --- Handle PASTE_COMMAND ---\n useEffect(() => {\n const unregisterPasteCommand = editor.registerCommand(\n PASTE_COMMAND,\n (event) => {\n const clipboardData = event.clipboardData;\n if (!clipboardData) {\n return false;\n }\n\n const files = Array.from(clipboardData.files);\n const imageFiles = files.filter(isImageFile);\n\n if (imageFiles.length === 1) {\n event.preventDefault();\n\n const imageFile = imageFiles[0];\n const selection = $getSelection() || $getPreviousSelection();\n\n if (!$isRangeSelection(selection)) {\n return false;\n }\n\n // Create a blob URL for the single image\n const imageUrl = URL.createObjectURL(imageFile);\n const imageNode = $createImageNode(imageUrl);\n\n // Insert the image node\n selection.insertNodes([imageNode]);\n\n // Insert a paragraph node after the image node if the next node is empty\n let nextNode =\n imageNode.getNextSibling() ||\n imageNode.getParent().getNextSibling();\n\n if (!nextNode) {\n nextNode = $createParagraphNode();\n imageNode.insertAfter(nextNode);\n }\n\n imageNode.select();\n\n // URL.revokeObjectURL(imageUrl);\n\n return true;\n }\n\n return false;\n },\n COMMAND_PRIORITY_HIGH\n );\n\n return unregisterPasteCommand;\n }, [editor]);\n\n return (\n // Make the Image selectable\n <NodeEventPlugin\n nodeType={ImageNode}\n eventType={\"click\"}\n eventListener={(event, editor, key) => {\n const node = $getNodeByKey(key);\n node.select();\n }}\n />\n );\n}\n","import {\r\n Button,\r\n DialogTrigger,\r\n Popover,\r\n Toolbar,\r\n Group,\r\n FileTrigger,\r\n} from \"react-aria-components\";\r\nimport {\r\n IconPlus,\r\n IconCodePlus,\r\n IconPhoto,\r\n IconLineDashed,\r\n} from \"@tabler/icons-react\";\r\nimport { useState, useRef, useEffect } from \"react\";\r\nimport { OFFSCREEN_POSITION } from \"../InlineToolbar/utils\";\r\nimport { computeBlockToolbarPosition } from \"../InlineToolbar/utils\";\r\nimport \"./styles/Popover.css\";\r\n\r\nimport { INSERT_CODE_BLOCK_COMMAND } from \"../../Plugins/CodePlugin\";\r\nimport { INSERT_HORIZONTAL_DIVIDER_COMMAND } from \"../../Plugins/HorizontalDividerPlugin\";\r\nimport { INSERT_IMAGE_COMMAND } from \"../../Plugins/ImagePlugin\";\r\nimport { useLexicalComposerContext } from \"@lexical/react/LexicalComposerContext\";\r\n\r\nconst ICON_SIZE = 24;\r\n\r\nfunction BlockToolbar() {\r\n const [editor] = useLexicalComposerContext();\r\n\r\n const handleFileSelect = (fileList) => {\r\n if (!fileList || fileList.length === 0) {\r\n return; // No file selected or user cancelled\r\n }\r\n\r\n const file = fileList[0]; // Get the first selected file\r\n\r\n // Basic MIME type check\r\n if (!file.type.startsWith(\"image/\")) {\r\n alert(\"Please select an image file.\");\r\n return;\r\n }\r\n\r\n // Use FileReader to get Data URL\r\n const reader = new FileReader();\r\n\r\n reader.onload = (event) => {\r\n const imageDataUrl = event.target?.result;\r\n if (typeof imageDataUrl === \"string\") {\r\n editor.dispatchCommand(INSERT_IMAGE_COMMAND, imageDataUrl);\r\n } else {\r\n alert(\"Failed to read file as Data URL.\");\r\n }\r\n };\r\n\r\n reader.onerror = (error) => {\r\n console.error(\"Error reading file:\", error);\r\n alert(\"Error reading file.\");\r\n };\r\n\r\n // Start reading the file content as a Data URL\r\n reader.readAsDataURL(file);\r\n };\r\n\r\n return (\r\n <Toolbar aria-label=\"Block toolbar\" id=\"block-toolbar\">\r\n <Group aria-label=\"Media\">\r\n <FileTrigger\r\n acceptedFileTypes={[\"image/png\", \"image/jpeg\", \"image/gif\"]}\r\n onSelect={handleFileSelect}\r\n allowsMultiple={false}\r\n >\r\n <Button aria-label=\"image\">\r\n <IconPhoto size={ICON_SIZE} />\r\n </Button>\r\n </FileTrigger>\r\n <Button\r\n aria-label=\"code block\"\r\n onPress={() => {\r\n editor.dispatchCommand(INSERT_CODE_BLOCK_COMMAND, undefined);\r\n }}\r\n >\r\n <IconCodePlus size={ICON_SIZE} />\r\n </Button>\r\n <Button\r\n aria-label=\"horizontal divider\"\r\n onPress={() => {\r\n editor.dispatchCommand(\r\n INSERT_HORIZONTAL_DIVIDER_COMMAND,\r\n undefined\r\n );\r\n }}\r\n >\r\n <IconLineDashed size={ICON_SIZE} />\r\n </Button>\r\n </Group>\r\n </Toolbar>\r\n );\r\n}\r\n\r\nexport default function BlockToolbarPopover({\r\n selectionRectCoords,\r\n TOOLBAR_OFFSET,\r\n toolbarTriggerId,\r\n toolbarPopoverId,\r\n}) {\r\n const [toolbarPosition, setToolbarPosition] = useState({\r\n x: OFFSCREEN_POSITION,\r\n y: OFFSCREEN_POSITION,\r\n });\r\n const toolbarRef = useRef(null);\r\n\r\n // Update toolbar position when selection changes\r\n useEffect(() => {\r\n setToolbarPosition(\r\n computeBlockToolbarPosition(\r\n selectionRectCoords,\r\n toolbarRef,\r\n TOOLBAR_OFFSET\r\n )\r\n );\r\n }, [selectionRectCoords]);\r\n\r\n return (\r\n <DialogTrigger>\r\n <Button\r\n aria-label=\"Block toolbar trigger\"\r\n className=\"block-toolbar-trigger\"\r\n id={toolbarTriggerId}\r\n ref={toolbarRef}\r\n style={{\r\n position: \"absolute\",\r\n top: toolbarPosition.y,\r\n left: toolbarPosition.x,\r\n }}\r\n >\r\n <IconPlus size={ICON_SIZE} />\r\n </Button>\r\n <Popover\r\n className=\"block-toolbar-popover\"\r\n id={toolbarPopoverId}\r\n placement=\"end\"\r\n shouldFlip={false}\r\n offset={TOOLBAR_OFFSET}\r\n >\r\n <BlockToolbar />\r\n </Popover>\r\n </DialogTrigger>\r\n );\r\n}\r\n","import { useLexicalComposerContext } from \"@lexical/react/LexicalComposerContext\";\nimport {\n $getSelection,\n $isRangeSelection,\n SELECTION_CHANGE_COMMAND,\n COMMAND_PRIORITY_HIGH,\n $isParagraphNode,\n} from \"lexical\";\nimport { useEffect, useState, useRef } from \"react\";\nimport { createPortal } from \"react-dom\";\nimport { getSelectedNode } from \"./TextFormatPlugin\";\n\nimport BlockToolbarPopover from \"../components/BlockToolbar/BlockToolbar\";\n\nconst DOM_ELEMENT = document.body;\n\nexport default function BlockToolbarPlugin({ toolbarGap }) {\n const [selectionRectCoords, setSelectionRectCoords] = useState(null);\n const [editor] = useLexicalComposerContext();\n const [isEditorFocused, setIsEditorFocused] = useState(false);\n const [toolbarActive, setToolbarActive] = useState(false);\n\n // Generate unique IDs specific to this editor instance\n const randomStringRef = useRef(Math.random().toString(36).substring(2, 9));\n const toolbarTriggerId = `block-toolbar-trigger-${randomStringRef.current}`;\n const toolbarPopoverId = `block-toolbar-popover-${randomStringRef.current}`;\n\n const handleFocus = () => setIsEditorFocused(true);\n const handleBlur = (event) => {\n // Delay the blur event to give time for toolbar click to register\n setTimeout(() => {\n const toolbarTrigger = document.getElementById(toolbarTriggerId);\n if (\n toolbarTrigger &&\n (toolbarTrigger === document.activeElement ||\n toolbarTrigger.contains(document.activeElement) ||\n toolbarTrigger.contains(event.relatedTarget))\n ) {\n // Don't update focus state if we're clicking on the toolbar trigger\n return;\n }\n setIsEditorFocused(false);\n }, 10);\n };\n\n // Add observer to detect if toolbar is active\n useEffect(() => {\n const checkToolbarPresence = () => {\n const isPresent = !!document.getElementById(toolbarPopoverId);\n setToolbarActive(isPresent);\n };\n\n const observer = new MutationObserver(checkToolbarPresence);\n observer.observe(document.body, {\n childList: true,\n subtree: true,\n });\n\n // Initial check\n checkToolbarPresence();\n\n return () => observer.disconnect();\n }, []);\n\n useEffect(() => {\n const unregisterListener = editor.registerRootListener(\n (rootElement, prevRootElement) => {\n if (rootElement) {\n rootElement.addEventListener(\"focus\", handleFocus);\n rootElement.addEventListener(\"blur\", handleBlur);\n }\n\n if (prevRootElement) {\n prevRootElement.removeEventListener(\"focus\", handleFocus);\n prevRootElement.removeEventListener(\"blur\", handleBlur);\n }\n }\n );\n\n return unregisterListener;\n }, [editor]);\n\n useEffect(() => {\n const unregisterListener = editor.registerCommand(\n SELECTION_CHANGE_COMMAND,\n () => {\n // Check editor focus state during selection changes\n const rootElement = editor.getRootElement();\n if (rootElement) {\n const hasFocus =\n rootElement === document.activeElement ||\n rootElement.contains(document.activeElement);\n\n // Update focus state only if it changed to avoid re-renders\n if (hasFocus !== isEditorFocused) {\n setIsEditorFocused(hasFocus);\n }\n }\n\n const selection = $getSelection();\n\n if (!$isRangeSelection(selection) || !selection.isCollapsed()) {\n setSelectionRectCoords(null);\n return false;\n }\n\n const node = getSelectedNode(selection);\n if ($isParagraphNode(node) && node.getTextContent() === \"\") {\n // update selection coordinates when selection changes and the condition is met\n const DOMElement = editor.getElementByKey(node.getKey());\n const boundingRect = DOMElement.getBoundingClientRect();\n\n const X = boundingRect.left;\n const centerY =\n boundingRect.top + boundingRect.height / 2 + window.scrollY;\n\n setSelectionRectCoords({ x: X, y: centerY });\n } else {\n setSelectionRectCoords(null);\n }\n\n return false;\n },\n COMMAND_PRIORITY_HIGH\n );\n return unregisterListener;\n }, [editor]);\n\n return (\n selectionRectCoords &&\n (isEditorFocused || toolbarActive) &&\n createPortal(\n <BlockToolbarPopover\n selectionRectCoords={selectionRectCoords}\n TOOLBAR_OFFSET={toolbarGap}\n toolbarTriggerId={toolbarTriggerId}\n toolbarPopoverId={toolbarPopoverId}\n />,\n DOM_ELEMENT\n )\n );\n}\n","import { useLexicalComposerContext } from \"@lexical/react/LexicalComposerContext\";\nimport { useEffect } from \"react\";\nimport { $createMathNode, $isMathNode, MathNode } from \"../nodes/MathNode\";\nimport {\n $getNodeByKey,\n $getRoot,\n $getSelection,\n $isLineBreakNode,\n $isNodeSelection,\n $isRangeSelection,\n $isTextNode,\n $isParagraphNode,\n COMMAND_PRIORITY_HIGH,\n KEY_ENTER_COMMAND,\n KEY_ARROW_RIGHT_COMMAND,\n KEY_BACKSPACE_COMMAND,\n SELECTION_CHANGE_COMMAND,\n $createTextNode,\n TextNode,\n $getAdjacentNode,\n COMMAND_PRIORITY_NORMAL\n} from \"lexical\";\nimport {\n $createMathHighlightNodeBlock,\n $createMathHighlightNodeInline,\n $isMathHighlightNodeBlock,\n $isMathHighlightNodeInline,\n MathHighlightNodeBlock,\n MathHighlightNodeInline,\n} from \"../nodes/MathHighlightNode\";\nimport { NodeEventPlugin } from \"@lexical/react/LexicalNodeEventPlugin\";\nimport { $findMatchingParent } from \"@lexical/utils\";\n\nexport const INLINE_DELIMITERS = [\n [\"$\", \"$\"],\n [\"\\\\(\", \"\\\\)\"],\n];\n\nexport const DISPLAY_DELIMITERS = [\n [\"$$\", \"$$\"],\n [\"\\\\[\", \"\\\\]\"],\n];\n\nconst escapeRegex = (str) => str.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n\nconst getMatch = (text, delimiters) => {\n let earliest = null;\n\n for (const [opening, closing] of delimiters) {\n const regex = new RegExp(\n `(.*?)(${escapeRegex(opening)})(.*?)(${escapeRegex(closing)})`,\n \"g\"\n );\n const match = regex.exec(text);\n if (match) {\n const content = match[3];\n if (content && content.trim() !== \"\") {\n const start = match.index + match[1].length;\n const end = match.index + match[0].length;\n if (!earliest || start < earliest.start) {\n earliest = {\n start,\n end,\n content: opening + content + closing,\n };\n }\n }\n }\n }\n\n return earliest;\n};\n\nexport function MathInlinePlugin() {\n const [editor] = useLexicalComposerContext();\n\n useEffect(() => {\n if (!editor.hasNodes([MathNode, MathHighlightNodeInline])) {\n throw new Error(\n \"MathInlinePlugin: MathNode or MathHighlightNodeInline not registered on editor\"\n );\n }\n }, [editor]);\n\n // Convert simple text $...$ to MathNode Inline\n useEffect(() => {\n const removeTransform = editor.registerNodeTransform(TextNode, (node) => {\n if (!node.isSimpleText()) {\n return;\n }\n\n if (\n $isMathHighlightNodeInline(node) ||\n $findMatchingParent(node, $isMathHighlightNodeBlock)\n ) {\n return;\n }\n\n const text = node.getTextContent();\n const match = getMatch(text, INLINE_DELIMITERS);\n\n if (match) {\n const { start, end, content } = match;\n let targetNode;\n const mathNode = $createMathNode(content, true);\n\n if (start === 0) {\n [targetNode] = node.splitText(end);\n targetNode.insertBefore(mathNode);\n targetNode.remove();\n } else {\n [, targetNode] = node.splitText(start, end);\n targetNode.replace(mathNode);\n }\n return mathNode;\n }\n });\n return removeTransform;\n }, [editor]);\n\n // conversion: MathNode Inline <--> MathHighlightNodeInline upon selection change\n useEffect(() => {\n const unregisterListener = editor.registerCommand(\n SELECTION_CHANGE_COMMAND,\n () => {\n const selection = $getSelection();\n const nodesToExclude = new Set();\n\n if ($isNodeSelection(selection)) {\n const nodes = selection.getNodes();\n if (nodes.length === 1 && $isMathNode(nodes[0])) {\n const mathNode = nodes[0];\n if (mathNode.isInline()) {\n let equation = mathNode.getEquation();\n // Strip delimiters\n if (equation.startsWith(\"$\") && equation.endsWith(\"$\")) {\n equation = equation.slice(1, -1);\n } else if (equation.startsWith(\"\\\\(\") && equation.endsWith(\"\\\\)\")) {\n equation = equation.slice(2, -2);\n }\n\n const mathHighlightNode = $createMathHighlightNodeInline(equation);\n mathNode.replace(mathHighlightNode);\n mathHighlightNode.select();\n return true;\n }\n }\n } else if ($isRangeSelection(selection)) {\n selection.getNodes().forEach(node => nodesToExclude.add(node.getKey()));\n }\n\n // Convert unselected inline highlight nodes back to math nodes\n const root = $getRoot();\n const allTextNodes = root.getAllTextNodes();\n\n // convert unselected MathHighlightNodeInline to MathNode Inline\n allTextNodes.forEach((node) => {\n if (\n $isMathHighlightNodeInline(node) &&\n !nodesToExclude.has(node.getKey())\n ) {\n let equation = node.getTextContent();\n if (!equation) {\n node.remove();\n return;\n }\n\n let isBlock = false;\n if (equation.startsWith(\"$\") && equation.endsWith(\"$\") && equation.length >= 2) {\n equation = equation.slice(1, -1);\n isBlock = true;\n }\n\n const mathNode = isBlock\n ? $createMathNode(`$$${equation}$$`, false)\n : $createMathNode(`$${equation}$`, true);\n node.replace(mathNode);\n }\n });\n\n return false;\n },\n COMMAND_PRIORITY_HIGH\n );\n return unregisterListener;\n }, [editor]);\n\n // If a collapsed selection lands on a MathNode Inline from left,\n // convert it to MathHighlightNodeInline and select it at the start\n useEffect(() => {\n return editor.registerCommand(\n KEY_ARROW_RIGHT_COMMAND,\n (payload) => {\n const selection = $getSelection();\n if (!$isRangeSelection(selection) || !selection.isCollapsed()) {\n return false;\n }\n\n const adjacentNode = $getAdjacentNode(selection.anchor, false);\n\n if ($isMathNode(adjacentNode) && adjacentNode.isInline()) {\n const equation = adjacentNode.getEquation();\n let cleanEquation = equation;\n // Strip delimiters if present\n if (cleanEquation.startsWith(\"$\") && cleanEquation.endsWith(\"$\")) {\n cleanEquation = cleanEquation.slice(1, -1);\n } else if (cleanEquation.startsWith(\"\\\\(\") && cleanEquation.endsWith(\"\\\\)\")) {\n cleanEquation = cleanEquation.slice(2, -2);\n }\n\n const mathHighlightNode = $createMathHighlightNodeInline(cleanEquation);\n adjacentNode.replace(mathHighlightNode);\n mathHighlightNode.select(0, 0);\n return true;\n }\n\n return false;\n },\n COMMAND_PRIORITY_HIGH\n );\n }, [editor]);\n\n // If a collapsed selection lands on a MathNode Inline from right upon backspace,\n // convert it to MathHighlightNodeInline and select it at the end\n useEffect(() => {\n return editor.registerCommand(\n KEY_BACKSPACE_COMMAND,\n (payload) => {\n const selection = $getSelection();\n if (!$isRangeSelection(selection) || !selection.isCollapsed()) {\n return false;\n }\n\n const adjacentNode = $getAdjacentNode(selection.anchor, true);\n\n if ($isMathNode(adjacentNode) && adjacentNode.isInline()) {\n const equation = adjacentNode.getEquation();\n let cleanEquation = equation;\n // Strip delimiters if present\n if (cleanEquation.startsWith(\"$\") && cleanEquation.endsWith(\"$\")) {\n cleanEquation = cleanEquation.slice(1, -1);\n } else if (cleanEquation.startsWith(\"\\\\(\") && cleanEquation.endsWith(\"\\\\)\")) {\n cleanEquation = cleanEquation.slice(2, -2);\n }\n\n const mathHighlightNode = $createMathHighlightNodeInline(cleanEquation);\n adjacentNode.replace(mathHighlightNode);\n mathHighlightNode.select();\n return true;\n }\n\n return false;\n },\n COMMAND_PRIORITY_HIGH\n );\n }, [editor]);\n\n // If the selection is inside a MathHighlightNodeInline and there is no next sibling,\n // add a space after it to make it easier to escape\n useEffect(() => {\n return editor.registerCommand(\n SELECTION_CHANGE_COMMAND,\n () => {\n const selection = $getSelection();\n if (!$isRangeSelection(selection) || !selection.isCollapsed()) {\n return false;\n }\n\n const node = selection.anchor.getNode();\n\n if ($isMathHighlightNodeInline(node)) {\n const nextSibling = node.getNextSibling();\n if (!nextSibling) {\n node.insertAfter($createTextNode(\" \"));\n }\n }\n\n return false;\n },\n COMMAND_PRIORITY_NORMAL\n );\n }, [editor]);\n\n return (\n // Register click event for MathNode\n <NodeEventPlugin\n nodeType={MathNode}\n eventType={\"click\"}\n eventListener={(event, editor, key) => {\n const node = $getNodeByKey(key);\n if (node && node.isInline()) {\n node.select();\n }\n }}\n />\n );\n}\n\nexport function MathBlockPlugin() {\n const [editor] = useLexicalComposerContext();\n\n useEffect(() => {\n if (!editor.hasNodes([MathNode, MathHighlightNodeBlock])) {\n throw new Error(\n \"MathBlockPlugin: MathNode or MathHighlightNodeBlock not registered on editor\"\n );\n }\n }, [editor]);\n\n useEffect(() => {\n const removeTransform = editor.registerNodeTransform(TextNode, (node) => {\n if (!node.isSimpleText()) {\n return;\n }\n\n if ($findMatchingParent(node, $isMathHighlightNodeBlock)) {\n return;\n }\n\n const text = node.getTextContent();\n\n // Check for Block Creation Trigger: \"$$ \" at start of line/paragraph\n if (text.startsWith(\"$$ \")) {\n const prevSibling = node.getPreviousSibling();\n const parentNode = $findMatchingParent(node, $isParagraphNode);\n const isStartOfParagraph = parentNode !== null && parentNode.getChildrenSize() === 1;\n const isAfterLineBreak = $isLineBreakNode(prevSibling);\n\n if (isStartOfParagraph || isAfterLineBreak) {\n // If there is more text after \"$$ \", don't do anything\n if (text.length > 3) {\n return;\n }\n\n // Create the new math block\n const mathBlock = $createMathHighlightNodeBlock(\"\");\n\n // Replace \"$$ \" with the math block\n node.replace(mathBlock);\n\n // Select the math block\n mathBlock.select();\n\n // Check if the next sibling is a LineBreakNode and remove it\n const nextSibling = mathBlock.getNextSibling();\n if ($isLineBreakNode(nextSibling)) {\n nextSibling.remove();\n }\n\n return;\n }\n }\n\n const match = getMatch(text, DISPLAY_DELIMITERS);\n\n if (match) {\n const { start, end, content } = match;\n let targetNode;\n const mathNode = $createMathNode(content, false);\n\n if (start === 0) {\n [targetNode] = node.splitText(end);\n targetNode.insertBefore(mathNode);\n targetNode.remove();\n } else {\n [, targetNode] = node.splitText(start, end);\n targetNode.replace(mathNode);\n }\n return mathNode;\n }\n });\n return removeTransform;\n }, [editor]);\n\n useEffect(() => {\n const unregisterListener = editor.registerCommand(\n SELECTION_CHANGE_COMMAND,\n () => {\n const selection = $getSelection();\n const nodesToExclude = new Set();\n\n if ($isNodeSelection(selection)) {\n const nodes = selection.getNodes();\n if (nodes.length === 1 && $isMathNode(nodes[0])) {\n const mathNode = nodes[0];\n if (!mathNode.isInline()) {\n let equation = mathNode.getEquation();\n // Strip delimiters\n if (equation.startsWith(\"$$\") && equation.endsWith(\"$$\")) {\n equation = equation.slice(2, -2);\n } else if (equation.startsWith(\"\\\\[\") && equation.endsWith(\"\\\\]\")) {\n equation = equation.slice(2, -2);\n }\n\n const mathHighlightNode = $createMathHighlightNodeBlock(equation);\n mathNode.replace(mathHighlightNode);\n mathHighlightNode.select();\n return true;\n }\n }\n } else if ($isRangeSelection(selection)) {\n selection.getNodes().forEach(node => {\n nodesToExclude.add(node.getKey());\n const blockNode = $findMatchingParent(node, $isMathHighlightNodeBlock);\n if (blockNode) {\n nodesToExclude.add(blockNode.getKey());\n }\n });\n }\n\n // Convert unselected block highlight nodes back to math nodes\n const editorState = editor.getEditorState();\n const allNodes = editorState._nodeMap;\n for (const [, node] of allNodes) {\n if ($isMathHighlightNodeBlock(node) && node.isAttached() && !nodesToExclude.has(node.getKey())) {\n const equation = node.getTextContent();\n if (!equation) {\n node.remove();\n continue;\n }\n // Always convert back to block MathNode\n const mathNode = $createMathNode(`$$${equation}$$`, false);\n node.replace(mathNode);\n }\n }\n\n return false;\n },\n COMMAND_PRIORITY_HIGH\n );\n return unregisterListener;\n }, [editor]);\n\n useEffect(() => {\n const unregisterListener = editor.registerCommand(\n KEY_ENTER_COMMAND,\n () => {\n const selection = $getSelection();\n if (!$isRangeSelection(selection)) {\n return false;\n }\n\n const firstNode = selection.getNodes()[0];\n const mathHighlightBlock = $findMatchingParent(\n firstNode,\n $isMathHighlightNodeBlock\n );\n if (!mathHighlightBlock) {\n return false;\n }\n\n const lastChild = mathHighlightBlock.getLastChild();\n const isAtBlockEnd =\n selection.isCollapsed() &&\n ((selection.anchor.getNode().getKey() ===\n mathHighlightBlock.getKey() &&\n selection.anchor.offset === 0 &&\n mathHighlightBlock.getChildrenSize() === 0) ||\n (lastChild &&\n $isLineBreakNode(lastChild) &&\n selection.anchor.getNode().getKey() ===\n mathHighlightBlock.getKey() &&\n selection.anchor.offset ===\n mathHighlightBlock.getChildrenSize()) ||\n (lastChild &&\n $isTextNode(lastChild) &&\n selection.anchor.getNode().getKey() === lastChild.getKey() &&\n selection.anchor.offset === lastChild.getTextContent().length));\n\n if (isAtBlockEnd) {\n return false;\n }\n\n selection.insertLineBreak();\n return true;\n },\n COMMAND_PRIORITY_HIGH\n );\n return unregisterListener;\n }, [editor]);\n\n // If a collapsed selection lands on a MathNode Block from right upon backspace,\n // convert it to MathHighlightNodeBlock and select it at the end\n useEffect(() => {\n return editor.registerCommand(\n KEY_BACKSPACE_COMMAND,\n (payload) => {\n const selection = $getSelection();\n if (!$isRangeSelection(selection) || !selection.isCollapsed()) {\n return false;\n }\n\n const adjacentNode = $getAdjacentNode(selection.anchor, true);\n\n if ($isMathNode(adjacentNode) && !adjacentNode.isInline()) {\n const equation = adjacentNode.getEquation();\n let cleanEquation = equation;\n // Strip delimiters if present\n if (cleanEquation.startsWith(\"$$\") && cleanEquation.endsWith(\"$$\")) {\n cleanEquation = cleanEquation.slice(2, -2);\n } else if (cleanEquation.startsWith(\"\\\\[\") && cleanEquation.endsWith(\"\\\\]\")) {\n cleanEquation = cleanEquation.slice(2, -2);\n }\n\n const mathHighlightNode = $createMathHighlightNodeBlock(cleanEquation);\n adjacentNode.replace(mathHighlightNode);\n mathHighlightNode.select();\n return true;\n }\n\n return false;\n },\n COMMAND_PRIORITY_HIGH\n );\n }, [editor]);\n\n return (\n <NodeEventPlugin\n nodeType={MathNode}\n eventType={\"click\"}\n eventListener={(event, editor, key) => {\n const node = $getNodeByKey(key);\n if (node && !node.isInline()) {\n node.select();\n }\n }}\n />\n );\n}\n","import { $insertList, $isListItemNode } from \"@lexical/list\";\nimport { useLexicalComposerContext } from \"@lexical/react/LexicalComposerContext\";\nimport { useEffect } from \"react\";\nimport {\n $getSelection,\n $isParagraphNode,\n $isRangeSelection,\n COMMAND_PRIORITY_HIGH,\n KEY_TAB_COMMAND,\n TextNode,\n} from \"lexical\";\nimport { $findMatchingParent } from \"@lexical/utils\";\nimport { getSelectedNode } from \"./TextFormatPlugin\";\n\nconst MAX_INDENT_LEVEL = 3;\n\nexport function ListPluginExtended() {\n const [editor] = useLexicalComposerContext();\n\n // If a text node begins with '1. ' or '- ', convert it into a list\n useEffect(() => {\n const removeTransform = editor.registerNodeTransform(TextNode, (node) => {\n if (!$findMatchingParent(node, $isParagraphNode)) {\n return;\n }\n\n const parentNode = $findMatchingParent(node, $isParagraphNode);\n if (parentNode.getFirstDescendant() !== node) {\n return;\n }\n\n const selection = $getSelection();\n if ($isRangeSelection(selection) && selection.isCollapsed()) {\n const anchor = selection.anchor;\n const offset = anchor.offset;\n\n if (node.getTextContent() === \"1. \" && offset === 3) {\n $insertList(\"number\");\n node.setTextContent(\"\");\n } else if (node.getTextContent() === \"- \" && offset === 2) {\n $insertList(\"bullet\");\n node.setTextContent(\"\");\n }\n }\n });\n\n return removeTransform;\n }, [editor]);\n\n // Handle TAB Command\n useEffect(() => {\n const unregisterCommand = editor.registerCommand(\n KEY_TAB_COMMAND,\n (event) => {\n const selection = $getSelection();\n if (!$isRangeSelection(selection)) {\n return false;\n }\n\n const node = getSelectedNode(selection);\n const listItemNode = $findMatchingParent(node, $isListItemNode);\n if (!listItemNode) {\n return false;\n }\n\n const indent = listItemNode.getIndent();\n if (event.shiftKey) {\n if (indent <= 0) {\n return false;\n }\n listItemNode.setIndent(indent - 1);\n } else {\n if (indent > MAX_INDENT_LEVEL) {\n return false;\n }\n listItemNode.setIndent(indent + 1);\n }\n\n return true;\n },\n COMMAND_PRIORITY_HIGH\n );\n\n return unregisterCommand;\n }, [editor]);\n\n return null;\n}\n","import { useLexicalComposerContext } from \"@lexical/react/LexicalComposerContext\";\nimport { useEffect } from \"react\";\n\nexport function TabInterceptorPlugin() {\n const [editor] = useLexicalComposerContext();\n\n const interceptTab = (event) => {\n if (event.key === \"Tab\") {\n event.preventDefault();\n }\n };\n\n useEffect(() => {\n const unregisterListener = editor.registerRootListener(\n (rootElement, prevRootElement) => {\n if (rootElement) {\n rootElement.addEventListener(\"keydown\", interceptTab);\n }\n\n if (prevRootElement) {\n prevRootElement.removeEventListener(\"keydown\", interceptTab);\n }\n }\n );\n\n return unregisterListener;\n }, [editor]);\n\n return null;\n}\n","import { useLexicalComposerContext } from \"@lexical/react/LexicalComposerContext\";\nimport { useEffect } from \"react\";\n\n// Exposes the editor to the parent component\nexport function EditorExposePlugin({ editorRef }) {\n const [editor] = useLexicalComposerContext();\n\n useEffect(() => {\n if (editorRef) {\n editorRef.current = editor;\n\n // Clear the ref on component unmount\n return () => {\n if (editorRef) {\n editorRef.current = null;\n }\n };\n }\n }, [editor, editorRef]);\n\n return null;\n}\n","import { AutoFocusPlugin } from \"@lexical/react/LexicalAutoFocusPlugin\";\nimport { LexicalComposer } from \"@lexical/react/LexicalComposer\";\nimport { RichTextPlugin } from \"@lexical/react/LexicalRichTextPlugin\";\nimport { HistoryPlugin } from \"@lexical/react/LexicalHistoryPlugin\";\nimport { LexicalErrorBoundary } from \"@lexical/react/LexicalErrorBoundary\";\nimport InlineToolbarPlugin from \"./Plugins/InlineToolbarPlugin.jsx\";\nimport { TextFormatPlugin } from \"./Plugins/TextFormatPlugin.jsx\";\nimport BlockToolbarPlugin from \"./Plugins/BlockToolbarPlugin.jsx\";\nimport { MathInlinePlugin, MathBlockPlugin } from \"./Plugins/MathPlugin.jsx\";\nimport { CodePlugin } from \"./Plugins/CodePlugin.jsx\";\nimport { HorizontalDividerPlugin } from \"./Plugins/HorizontalDividerPlugin.jsx\";\nimport { ImagePlugin } from \"./Plugins/ImagePlugin.jsx\";\nimport { ListPlugin } from \"@lexical/react/LexicalListPlugin\";\nimport { ListPluginExtended } from \"./Plugins/ListPluginExtended.jsx\";\nimport { TabInterceptorPlugin } from \"./Plugins/TabInterceptorPlugin.jsx\";\nimport { OnChangePlugin } from \"@lexical/react/LexicalOnChangePlugin\";\nimport { EditorExposePlugin } from \"./Plugins/EditorExposePlugin.jsx\";\nimport { ContentEditable } from \"@lexical/react/LexicalContentEditable\";\nimport { ClearEditorPlugin } from \"@lexical/react/LexicalClearEditorPlugin\";\n\nexport default function Editor({\n initialConfig,\n onChange,\n editorRef,\n blockToolbarGap,\n spellCheck,\n isHeadingOneFirst,\n}) {\n return (\n <LexicalComposer initialConfig={initialConfig}>\n <RichTextPlugin\n contentEditable={\n <ContentEditable spellCheck={spellCheck} className=\"editor-input\" />\n }\n ErrorBoundary={LexicalErrorBoundary}\n />\n <TextFormatPlugin isHeadingOneFirst={isHeadingOneFirst} />\n <InlineToolbarPlugin />\n <BlockToolbarPlugin toolbarGap={blockToolbarGap} />\n <AutoFocusPlugin />\n <HistoryPlugin />\n <MathInlinePlugin />\n <MathBlockPlugin />\n <CodePlugin />\n <HorizontalDividerPlugin />\n <ImagePlugin />\n <ListPlugin />\n <ListPluginExtended />\n <TabInterceptorPlugin />\n <OnChangePlugin onChange={onChange} />\n <EditorExposePlugin editorRef={editorRef} />\n <ClearEditorPlugin />\n </LexicalComposer>\n );\n}\n"],"names":["OFFSCREEN_POSITION","computeInlineToolbarPosition","boundingRectCoords","toolbarRef","topOffset","toolbarElement","x","y","width","height","centerX","topY","getBoundingRectCoords","range","rect","computeBlockToolbarPosition","offset","toolbarX","toolbarY","computeCodeMenuPosition","codeBlockCoords","codeMenuRef","HORIZONTAL_OFFSET","VERTICAL_OFFSET","codeMenuElement","X","Y","TOGGLE_HEADING_COMMAND","createCommand","TOGGLE_QUOTE_COMMAND","TOGGLE_LINK_COMMAND","getSelectedNode","selection","anchor","focus","anchorNode","focusNode","$isAtNodeEnd","fetchTagIfHeadingNode","node","headingNode","$findMatchingParent","$isHeadingNode","updateToolbarHeadingState","toolbarHeadingState","nodes","headingTag","stateKey","HeadingPlugin","editor","useLexicalComposerContext","useEffect","toolbarState","isHeadingOne","isHeadingTwo","isHeadingThree","$getSelection","$isRangeSelection","tag","$setBlocksType","$createHeadingNode","$createParagraphNode","COMMAND_PRIORITY_HIGH","HeadingOneFirstPlugin","unregisterTransform","HeadingNode","firstChild","$getRoot","children","h1Node","isNodeOrAncestorQuote","$isQuoteNode","updateToolbarQuoteState","QuotePlugin","$createQuoteNode","getLinkAtSelection","$isLinkNode","LinkPlugin","CLICK_COMMAND","payload","linkNode","COMMAND_PRIORITY_LOW","linkURL","$toggleLink","AdjacentHeadingPlugin","HEADING_ABOVE_CLASS","TextNode","textNode","parentNode","$isParagraphNode","$isListNode","element","prevSibling","shouldHaveClass","alreadyHasClass","TextFormatPlugin","isHeadingOneFirst","jsxs","Fragment","jsx","LinkToolbar","style","closeToolbar","existingLinkURL","setLinkURL","useState","Toolbar","TextField","Input","Group","Button","url","IconCheck","ICON_SIZE","IconX","TOP_OFFSET","InlineToolbar","selectionRectCoords","setSelectionRectCoords","toolbarPosition","setToolbarPosition","useRef","setToolbarState","isLinkToolbarVisible","setLinkToolbarVisible","toolbarWidth","setToolbarWidth","setExistingLinkURL","updateToolbarFormatState","prev","editorState","anchorPoint","focusPoint","anchorOffset","focusOffset","$getCharacterOffsets","selectionDOMRange","createDOMRange","_a","useLayoutEffect","computedStyle","ToggleButton","FORMAT_TEXT_COMMAND","IconBold","IconItalic","IconCode","Separator","IconTextSize","IconBlockquote","IconLink","DOM_ELEMENT","InlineToolbarPlugin","shouldShow","setShouldShow","SELECTION_CHANGE_COMMAND","hasMathNode","$isMathNode","isSingleMathHighlight","$isMathHighlightNodeInline","$isMathHighlightNodeBlock","isCodeBlock","$isCodeNode","createPortal","CodeMenu","codeNodeKey","codeMenuPosition","setCodeMenuPosition","language","setLanguage","codeLanguages","getCodeLanguages","friendlyLanguages","lang","getLanguageFriendlyName","friendlyToOriginal","friendly","currentLanguage","$getNodeByKey","ComboBox","friendlyValue","originalValue","SET_CODE_LANGUAGE_COMMAND","IconCaretDownFilled","Popover","ListBox","index","ListBoxItem","INSERT_CODE_BLOCK_COMMAND","CodeHighlightMenuPlugin","setCodeBlockCoords","setCodeNodeKey","codeNode","boundingRect","CodeBlockPlugin","registerCodeHighlighting","text","isStartOfParagraph","isAfterLineBreak","$isLineBreakNode","$createCodeNode","nextSibling","prevSelection","$getPreviousSelection","codeBlockNode","nodeKey","KEY_BACKSPACE_COMMAND","CodePlugin","INSERT_HORIZONTAL_DIVIDER_COMMAND","HorizontalDividerPlugin","HorizontalDividerNode","horizontalDividerNode","$createHorizontalDividerNode","nextNode","INSERT_IMAGE_COMMAND","SELECTED_CLASS_NAME","isImageFile","file","ImagePlugin","selectedImgElemRef","ImageNode","src","imageNode","$createImageNode","$isNodeSelection","$isImageNode","DOMElement","PASTE_COMMAND","event","clipboardData","imageFiles","imageFile","imageUrl","NodeEventPlugin","key","BlockToolbar","FileTrigger","fileList","reader","imageDataUrl","error","IconPhoto","IconCodePlus","IconLineDashed","BlockToolbarPopover","TOOLBAR_OFFSET","toolbarTriggerId","toolbarPopoverId","DialogTrigger","IconPlus","BlockToolbarPlugin","toolbarGap","isEditorFocused","setIsEditorFocused","toolbarActive","setToolbarActive","randomStringRef","handleFocus","handleBlur","toolbarTrigger","checkToolbarPresence","isPresent","observer","rootElement","prevRootElement","hasFocus","centerY","INLINE_DELIMITERS","DISPLAY_DELIMITERS","escapeRegex","str","getMatch","delimiters","earliest","opening","closing","match","content","start","end","MathInlinePlugin","MathNode","MathHighlightNodeInline","targetNode","mathNode","$createMathNode","nodesToExclude","equation","mathHighlightNode","$createMathHighlightNodeInline","isBlock","KEY_ARROW_RIGHT_COMMAND","adjacentNode","$getAdjacentNode","cleanEquation","$createTextNode","COMMAND_PRIORITY_NORMAL","MathBlockPlugin","MathHighlightNodeBlock","mathBlock","$createMathHighlightNodeBlock","blockNode","allNodes","KEY_ENTER_COMMAND","firstNode","mathHighlightBlock","lastChild","$isTextNode","MAX_INDENT_LEVEL","ListPluginExtended","$insertList","KEY_TAB_COMMAND","listItemNode","$isListItemNode","indent","TabInterceptorPlugin","interceptTab","EditorExposePlugin","editorRef","Editor","initialConfig","onChange","blockToolbarGap","spellCheck","LexicalComposer","RichTextPlugin","ContentEditable","LexicalErrorBoundary","AutoFocusPlugin","HistoryPlugin","ListPlugin","OnChangePlugin","ClearEditorPlugin"],"mappings":"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"}
1
+ {"version":3,"file":"index.es.js","sources":["../src/components/InlineToolbar/utils.js","../src/Plugins/TextFormatPlugin.jsx","../src/components/InlineToolbar/LinkToolbar.jsx","../src/components/InlineToolbar/InlineToolbar.jsx","../src/Plugins/InlineToolbarPlugin.jsx","../src/components/CodeHighlightMenu/CodeMenu.jsx","../src/Plugins/CodePlugin.jsx","../src/Plugins/HorizontalDividerPlugin.jsx","../src/Plugins/ImagePlugin.jsx","../src/components/BlockToolbar/BlockToolbar.jsx","../src/Plugins/BlockToolbarPlugin.jsx","../src/Plugins/MathPlugin.jsx","../src/Plugins/ListPluginExtended.jsx","../src/Plugins/TabInterceptorPlugin.jsx","../src/Plugins/EditorExposePlugin.jsx","../src/Editor.jsx"],"sourcesContent":["export const OFFSCREEN_POSITION = -1000;\n\nexport function computeInlineToolbarPosition(\n boundingRectCoords,\n toolbarRef,\n topOffset = 0\n) {\n // Ensure the popover reference is valid\n if (!toolbarRef || !toolbarRef.current) {\n console.error(\"Invalid popover reference\");\n return {\n x: OFFSCREEN_POSITION,\n y: OFFSCREEN_POSITION,\n };\n }\n\n const toolbarElement = toolbarRef.current;\n\n const { x, y } = boundingRectCoords;\n const { width, height } = toolbarElement.getBoundingClientRect();\n\n const centerX = x - width / 2;\n const topY = y - height - topOffset;\n\n return {\n x: centerX,\n y: topY,\n };\n}\n\nexport function getBoundingRectCoords(range) {\n // Ensure the range is valid\n if (!range || typeof range.getBoundingClientRect !== \"function\") {\n console.error(\"Invalid DOM range\");\n return null;\n }\n\n const rect = range.getBoundingClientRect();\n\n const centerX = rect.left + rect.width / 2;\n const topY = rect.top + window.scrollY;\n\n return {\n x: centerX,\n y: topY,\n };\n}\n\nexport function computeBlockToolbarPosition(\n boundingRectCoords,\n toolbarRef,\n offset = 0\n) {\n // Ensure the popover reference is valid\n if (!toolbarRef || !toolbarRef.current) {\n console.error(\"Invalid popover reference\");\n return {\n x: OFFSCREEN_POSITION,\n y: OFFSCREEN_POSITION,\n };\n }\n\n const { x, y } = boundingRectCoords;\n\n const toolbarElement = toolbarRef.current;\n const { width, height } = toolbarElement.getBoundingClientRect();\n\n const toolbarX = x - width - offset;\n const toolbarY = y - height / 2;\n\n return {\n x: toolbarX,\n y: toolbarY,\n };\n}\n\nexport function computeCodeMenuPosition(\n codeBlockCoords,\n codeMenuRef,\n HORIZONTAL_OFFSET = 16,\n VERTICAL_OFFSET = 12\n) {\n // Ensure the popover reference is valid\n if (!codeMenuRef || !codeMenuRef.current) {\n console.error(\"Invalid popover reference\");\n return {\n x: OFFSCREEN_POSITION,\n y: OFFSCREEN_POSITION,\n };\n }\n\n const codeMenuElement = codeMenuRef.current;\n\n const { x, y } = codeBlockCoords;\n const { width } = codeMenuElement.getBoundingClientRect();\n\n const X = x - width - HORIZONTAL_OFFSET;\n const Y = y + VERTICAL_OFFSET;\n\n return {\n x: X,\n y: Y,\n };\n}\n","/* Plugins for formatting text */\n\nimport {\n $isHeadingNode,\n $createHeadingNode,\n $isQuoteNode,\n $createQuoteNode,\n HeadingNode,\n} from \"@lexical/rich-text\";\nimport { useLexicalComposerContext } from \"@lexical/react/LexicalComposerContext\";\nimport {\n COMMAND_PRIORITY_HIGH,\n createCommand,\n $getSelection,\n $isRangeSelection,\n $createParagraphNode,\n CLICK_COMMAND,\n COMMAND_PRIORITY_LOW,\n $getRoot,\n TextNode,\n $isParagraphNode,\n} from \"lexical\";\nimport { $setBlocksType } from \"@lexical/selection\";\nimport { useEffect } from \"react\";\nimport { $findMatchingParent } from \"@lexical/utils\";\nimport { $toggleLink, $isLinkNode } from \"@lexical/link\";\nimport { $isListNode } from \"@lexical/list\";\nimport \"@lexical/utils\";\nimport { $isAtNodeEnd } from \"@lexical/selection\";\n\nexport const TOGGLE_HEADING_COMMAND = createCommand(\"TOGGLE_HEADING_COMMAND\");\nexport const TOGGLE_QUOTE_COMMAND = createCommand(\"TOGGLE_QUOTE_COMMAND\");\nexport const TOGGLE_LINK_COMMAND = createCommand(\"TOGGLE_LINK_COMMAND\");\n\nexport function getSelectedNode(selection) {\n const anchor = selection.anchor;\n const focus = selection.focus;\n const anchorNode = selection.anchor.getNode();\n const focusNode = selection.focus.getNode();\n if (anchorNode === focusNode) {\n return anchorNode;\n }\n const isBackward = selection.isBackward();\n if (isBackward) {\n return $isAtNodeEnd(focus) ? anchorNode : focusNode;\n } else {\n return $isAtNodeEnd(anchor) ? anchorNode : focusNode;\n }\n}\n\n// Helper function to fetch the tag of a node if it or its ancestor is a heading node.\nfunction fetchTagIfHeadingNode(node) {\n const headingNode = $findMatchingParent(node, $isHeadingNode);\n return headingNode ? headingNode.getTag() : null;\n}\n\nexport function updateToolbarHeadingState(selection) {\n const toolbarHeadingState = {\n isHeadingOne: false,\n isHeadingTwo: false,\n isHeadingThree: false,\n };\n\n const nodes = selection.getNodes();\n if (!nodes.length) return toolbarHeadingState;\n\n const headingTag = fetchTagIfHeadingNode(nodes[0]);\n if (!headingTag) return toolbarHeadingState;\n\n const allMatch = nodes.every(\n (node) => fetchTagIfHeadingNode(node) === headingTag\n );\n\n if (allMatch) {\n const stateKey = {\n h1: \"isHeadingOne\",\n h2: \"isHeadingTwo\",\n h3: \"isHeadingThree\",\n }[headingTag];\n\n if (stateKey) toolbarHeadingState[stateKey] = true;\n }\n\n return toolbarHeadingState;\n}\n\nfunction HeadingPlugin() {\n const [editor] = useLexicalComposerContext();\n\n useEffect(() => {\n const unregisterListener = editor.registerCommand(\n TOGGLE_HEADING_COMMAND,\n (toolbarState) => {\n const { isHeadingOne, isHeadingTwo, isHeadingThree } = toolbarState;\n const selection = $getSelection();\n\n if ($isRangeSelection(selection)) {\n let tag;\n\n // Apply the toggling logic based on current state in toolbar\n if (isHeadingOne) {\n // H1 --> H3\n tag = \"h3\";\n } else if (isHeadingTwo) {\n // H2 --> H3\n tag = \"h3\";\n } else if (isHeadingThree) {\n // H3 --> None (paragraph)\n tag = null;\n } else {\n // None --> H2\n tag = \"h2\";\n }\n\n // Apply the heading or paragraph node\n $setBlocksType(selection, () =>\n tag ? $createHeadingNode(tag) : $createParagraphNode()\n );\n }\n return true;\n },\n COMMAND_PRIORITY_HIGH\n );\n return unregisterListener;\n }, [editor]);\n\n return null;\n}\n\nfunction HeadingOneFirstPlugin() {\n const [editor] = useLexicalComposerContext();\n\n // Effect for NodeTransform: H2 at start -> H1\n useEffect(() => {\n const unregisterTransform = editor.registerNodeTransform(\n HeadingNode,\n (node) => {\n // Check if it's an H2 node\n if (node.getTag() !== \"h2\") {\n return;\n }\n\n // Get the root node and the first child\n const root = $getRoot();\n const firstChild = root.getFirstChild();\n\n // Check if this H2 node is the very first child of the root\n if (firstChild !== null && node.is(firstChild)) {\n const children = node.getChildren();\n const h1Node = $createHeadingNode(\"h1\");\n h1Node.append(...children);\n node.replace(h1Node);\n }\n }\n );\n\n return () => {\n unregisterTransform();\n };\n }, [editor]);\n\n return null;\n}\n\n// Helper function to check if a node or its ancestor is a quote node\nfunction isNodeOrAncestorQuote(node) {\n return $findMatchingParent(node, $isQuoteNode);\n}\n\nexport function updateToolbarQuoteState(selection) {\n const nodes = selection.getNodes();\n if (!nodes.length) return false;\n\n // Check if all nodes are within quote blocks\n return nodes.length > 0 && nodes.every((node) => isNodeOrAncestorQuote(node));\n}\n\nfunction QuotePlugin() {\n const [editor] = useLexicalComposerContext();\n\n useEffect(() => {\n const unregisterListener = editor.registerCommand(\n TOGGLE_QUOTE_COMMAND,\n (toolbarState) => {\n const selection = $getSelection();\n\n if ($isRangeSelection(selection)) {\n $setBlocksType(selection, () =>\n toolbarState.isQuote ? $createParagraphNode() : $createQuoteNode()\n );\n }\n return true;\n },\n COMMAND_PRIORITY_HIGH\n );\n return unregisterListener;\n }, [editor]);\n\n return null;\n}\n\nexport function getLinkAtSelection(selection) {\n if (!$isRangeSelection(selection)) {\n return null;\n }\n\n const node = getSelectedNode(selection);\n return $findMatchingParent(node, $isLinkNode);\n}\n\nfunction LinkPlugin() {\n const [editor] = useLexicalComposerContext();\n\n // If a link node is clicked while holding the ctrl key, open the link in a new tab\n useEffect(() => {\n const unregisterListener = editor.registerCommand(\n CLICK_COMMAND,\n (payload) => {\n const selection = $getSelection();\n const linkNode = getLinkAtSelection(selection);\n if (linkNode && (payload.metaKey || payload.ctrlKey)) {\n window.open(linkNode.getURL(), \"_blank\");\n return true;\n }\n return false;\n },\n COMMAND_PRIORITY_LOW\n );\n return unregisterListener;\n }, [editor]);\n\n useEffect(() => {\n const unregisterListener = editor.registerCommand(\n TOGGLE_LINK_COMMAND,\n (linkURL) => {\n $toggleLink(linkURL);\n return true;\n },\n COMMAND_PRIORITY_HIGH\n );\n return unregisterListener;\n }, [editor]);\n\n return null;\n}\n\n/* Adds a CSS class to ElementNodes (excluding HeadingNodes) that follow a HeadingNode. */\nfunction AdjacentHeadingPlugin() {\n const [editor] = useLexicalComposerContext();\n const HEADING_ABOVE_CLASS = \"heading-above\";\n\n useEffect(() => {\n const unregisterTransform = editor.registerNodeTransform(\n TextNode,\n (textNode) => {\n const parentNode =\n $findMatchingParent(textNode, $isParagraphNode) ||\n $findMatchingParent(textNode, $isListNode);\n\n if (!parentNode) {\n return;\n }\n\n if ($isHeadingNode(parentNode)) {\n return;\n }\n\n const node = parentNode;\n\n const element = editor.getElementByKey(node.getKey());\n if (!element) {\n return;\n }\n\n const prevSibling = node.getPreviousSibling();\n const shouldHaveClass = $isHeadingNode(prevSibling);\n\n // Check if the DOM element *currently* has the class.\n const alreadyHasClass = element.classList.contains(HEADING_ABOVE_CLASS);\n\n // Add or remove the class directly on the DOM element to achieve the desired state.\n if (shouldHaveClass && !alreadyHasClass) {\n element.classList.add(HEADING_ABOVE_CLASS);\n } else if (!shouldHaveClass && alreadyHasClass) {\n element.classList.remove(HEADING_ABOVE_CLASS);\n }\n }\n );\n\n return unregisterTransform;\n }, [editor]);\n\n return null;\n}\n\nexport function TextFormatPlugin({ isHeadingOneFirst }) {\n return (\n <>\n <HeadingPlugin />\n {isHeadingOneFirst && <HeadingOneFirstPlugin />}\n <QuotePlugin />\n <LinkPlugin />\n <AdjacentHeadingPlugin />\n </>\n );\n}\n","import {\n Button,\n Group,\n Toolbar,\n TextField,\n Input,\n} from \"react-aria-components\";\nimport { IconCheck, IconX } from \"@tabler/icons-react\";\nimport { ICON_SIZE } from \"./InlineToolbar\";\nimport { useState } from \"react\";\nimport { TOGGLE_LINK_COMMAND } from \"../../Plugins/TextFormatPlugin\";\nimport { useLexicalComposerContext } from \"@lexical/react/LexicalComposerContext\";\n\nimport \"./styles/LinkToolbar.css\";\n\nexport function LinkToolbar({ style, closeToolbar, existingLinkURL }) {\n const [editor] = useLexicalComposerContext();\n const [linkURL, setLinkURL] = useState(existingLinkURL);\n\n // TODO: The left and right arrow keys aren't working at all. Need to debug.\n\n return (\n <Toolbar style={style} aria-details=\"link toolbar\" id=\"link-toolbar\">\n <TextField\n aria-label=\"url\"\n autoFocus={true}\n defaultValue={linkURL}\n onChange={setLinkURL}\n >\n <Input placeholder=\"Enter Link\" />\n </TextField>\n <Group aria-label=\"edit link\">\n <Button\n aria-label=\"Update link\"\n onPress={() => {\n const url = linkURL === \"\" ? null : linkURL;\n editor.dispatchCommand(TOGGLE_LINK_COMMAND, url);\n closeToolbar();\n }}\n >\n <IconCheck size={ICON_SIZE} />\n </Button>\n <Button aria-label=\"Discard changes\" onPress={closeToolbar}>\n <IconX size={ICON_SIZE} />\n </Button>\n </Group>\n <div className=\"inline-toolbar-pointer\"></div>\n </Toolbar>\n );\n}\n","import {\r\n Button,\r\n Group,\r\n Separator,\r\n ToggleButton,\r\n Toolbar,\r\n} from \"react-aria-components\";\r\nimport {\r\n IconBold,\r\n IconItalic,\r\n IconCode,\r\n IconTextSize,\r\n IconBlockquote,\r\n IconLink,\r\n} from \"@tabler/icons-react\";\r\nimport { useEffect, useState, useRef, useLayoutEffect } from \"react\";\r\nimport {\r\n $getSelection,\r\n $isRangeSelection,\r\n $getCharacterOffsets,\r\n FORMAT_TEXT_COMMAND,\r\n} from \"lexical\";\r\nimport { createDOMRange } from \"@lexical/selection\";\r\nimport {\r\n computeInlineToolbarPosition,\r\n OFFSCREEN_POSITION,\r\n getBoundingRectCoords,\r\n} from \"./utils\";\r\nimport {\r\n TOGGLE_HEADING_COMMAND,\r\n TOGGLE_QUOTE_COMMAND,\r\n updateToolbarHeadingState,\r\n updateToolbarQuoteState,\r\n getLinkAtSelection,\r\n} from \"../../Plugins/TextFormatPlugin\";\r\nimport { LinkToolbar } from \"./LinkToolbar\";\r\n\r\nimport \"./styles/Toolbar.css\";\r\n\r\nexport const ICON_SIZE = 24;\r\nconst TOP_OFFSET = 16;\r\n\r\nexport default function InlineToolbar({ editor }) {\r\n // State for storing the bounding rectangle coordinates of the selection\r\n const [selectionRectCoords, setSelectionRectCoords] = useState(null);\r\n // State for storing the toolbar's position (x, y coordinates)\r\n const [toolbarPosition, setToolbarPosition] = useState({\r\n x: OFFSCREEN_POSITION,\r\n y: OFFSCREEN_POSITION,\r\n });\r\n const toolbarRef = useRef(null);\r\n const [toolbarState, setToolbarState] = useState({\r\n isBold: false,\r\n isItalic: false,\r\n isCode: false,\r\n isHeadingOne: false,\r\n isHeadingTwo: false,\r\n isHeadingThree: false,\r\n isQuote: false,\r\n });\r\n\r\n // Link toolbar state\r\n const [isLinkToolbarVisible, setLinkToolbarVisible] = useState(false);\r\n const [toolbarWidth, setToolbarWidth] = useState(0);\r\n const [existingLinkURL, setExistingLinkURL] = useState(\"\");\r\n\r\n // Logic for updating/setting toolbar state\r\n const updateToolbarFormatState = (selection) => {\r\n if ($isRangeSelection(selection)) {\r\n setToolbarState({\r\n isBold: selection.hasFormat(\"bold\"),\r\n isItalic: selection.hasFormat(\"italic\"),\r\n isCode: selection.hasFormat(\"code\"),\r\n isQuote: updateToolbarQuoteState(selection),\r\n });\r\n\r\n // update/set heading state\r\n const toolbarHeadingState = updateToolbarHeadingState(selection);\r\n setToolbarState((prev) => ({\r\n ...prev,\r\n ...toolbarHeadingState,\r\n }));\r\n\r\n // Set the link URL if the selection is at a link node\r\n const linkNode = getLinkAtSelection(selection);\r\n setExistingLinkURL(linkNode ? linkNode.getURL() : \"\");\r\n }\r\n };\r\n\r\n // Initialize toolbar state on component mount\r\n useEffect(() => {\r\n editor.read(() => {\r\n const selection = $getSelection();\r\n updateToolbarFormatState(selection);\r\n });\r\n }, [editor]);\r\n\r\n // Update toolbar state\r\n useEffect(() => {\r\n const unregisterListener = editor.registerUpdateListener(\r\n ({ editorState }) => {\r\n editorState.read(() => {\r\n const selection = $getSelection();\r\n updateToolbarFormatState(selection);\r\n });\r\n }\r\n );\r\n return unregisterListener;\r\n }, [editor]);\r\n\r\n // Update selection rectangle coordinates when toolbar state changes\r\n useEffect(() => {\r\n editor.read(() => {\r\n const selection = $getSelection();\r\n if ($isRangeSelection(selection)) {\r\n // Create a DOM range from the selection\r\n const [anchorPoint, focusPoint] = selection.getStartEndPoints();\r\n const [anchorNode, focusNode] = [\r\n anchorPoint.getNode(),\r\n focusPoint.getNode(),\r\n ];\r\n const [anchorOffset, focusOffset] = $getCharacterOffsets(selection);\r\n const selectionDOMRange = createDOMRange(\r\n editor,\r\n anchorNode,\r\n anchorOffset,\r\n focusNode,\r\n focusOffset\r\n );\r\n\r\n // Set bounding rect coords\r\n setSelectionRectCoords(getBoundingRectCoords(selectionDOMRange));\r\n }\r\n });\r\n }, [editor, toolbarState]);\r\n\r\n // Update toolbar position\r\n useEffect(() => {\r\n if (selectionRectCoords) {\r\n setToolbarPosition(\r\n computeInlineToolbarPosition(\r\n selectionRectCoords,\r\n toolbarRef,\r\n TOP_OFFSET\r\n )\r\n );\r\n setTimeout(() => {\r\n toolbarRef.current?.classList.add(\"visible\");\r\n }, 50);\r\n } else {\r\n toolbarRef.current?.classList.remove(\"visible\");\r\n }\r\n }, [selectionRectCoords]);\r\n\r\n // Capture the width of the inline toolbar after it has been rendered\r\n useLayoutEffect(() => {\r\n if (toolbarRef.current) {\r\n const computedStyle = window.getComputedStyle(toolbarRef.current);\r\n const width = parseFloat(computedStyle.width);\r\n setToolbarWidth(width);\r\n }\r\n }, [selectionRectCoords]);\r\n\r\n // TODO: LinkToolbar should not be a separate toolbar.\r\n // It should be a part of the InlineToolbar\r\n\r\n return (\r\n selectionRectCoords &&\r\n (isLinkToolbarVisible ? (\r\n <LinkToolbar\r\n style={{\r\n position: \"absolute\",\r\n top: toolbarPosition.y,\r\n left: toolbarPosition.x,\r\n width: toolbarWidth,\r\n }}\r\n closeToolbar={() => {\r\n setLinkToolbarVisible(false);\r\n setSelectionRectCoords(null);\r\n }}\r\n existingLinkURL={existingLinkURL}\r\n />\r\n ) : (\r\n <Toolbar\r\n style={{\r\n position: \"absolute\",\r\n top: toolbarPosition.y,\r\n left: toolbarPosition.x,\r\n }}\r\n aria-label=\"Text formatting\"\r\n id=\"inline-toolbar\"\r\n ref={toolbarRef}\r\n >\r\n <Group aria-label=\"Style\">\r\n <ToggleButton\r\n aria-label=\"Bold\"\r\n isSelected={toolbarState.isBold}\r\n isDisabled={\r\n toolbarState.isCode ||\r\n toolbarState.isHeadingOne ||\r\n toolbarState.isHeadingTwo ||\r\n toolbarState.isHeadingThree\r\n }\r\n onChange={() => editor.dispatchCommand(FORMAT_TEXT_COMMAND, \"bold\")}\r\n >\r\n <IconBold size={ICON_SIZE} />\r\n </ToggleButton>\r\n <ToggleButton\r\n aria-label=\"Italic\"\r\n isSelected={toolbarState.isItalic}\r\n isDisabled={toolbarState.isCode || toolbarState.isHeadingOne}\r\n onChange={() =>\r\n editor.dispatchCommand(FORMAT_TEXT_COMMAND, \"italic\")\r\n }\r\n >\r\n <IconItalic size={ICON_SIZE} />\r\n </ToggleButton>\r\n <ToggleButton\r\n aria-label=\"inline-code\"\r\n isDisabled={toolbarState.isHeadingOne}\r\n isSelected={toolbarState.isCode}\r\n onChange={() => editor.dispatchCommand(FORMAT_TEXT_COMMAND, \"code\")}\r\n >\r\n <IconCode size={ICON_SIZE} />\r\n </ToggleButton>\r\n </Group>\r\n <Separator orientation=\"vertical\" />\r\n <Group aria-label=\"Text Blocks\">\r\n <ToggleButton\r\n aria-label=\"Heading\"\r\n isSelected={\r\n toolbarState.isHeadingOne ||\r\n toolbarState.isHeadingTwo ||\r\n toolbarState.isHeadingThree\r\n }\r\n onChange={() =>\r\n editor.dispatchCommand(TOGGLE_HEADING_COMMAND, toolbarState)\r\n }\r\n >\r\n <IconTextSize size={ICON_SIZE} />\r\n </ToggleButton>\r\n <ToggleButton\r\n aria-label=\"Quote\"\r\n isSelected={toolbarState.isQuote}\r\n onChange={() =>\r\n editor.dispatchCommand(TOGGLE_QUOTE_COMMAND, toolbarState)\r\n }\r\n >\r\n <IconBlockquote size={ICON_SIZE} />\r\n </ToggleButton>\r\n </Group>\r\n <Separator orientation=\"vertical\" />\r\n <Group aria-label=\"Links\">\r\n <Button\r\n onPress={() => setLinkToolbarVisible(true)}\r\n isDisabled={toolbarState.isHeadingOne}\r\n >\r\n <IconLink size={ICON_SIZE} />\r\n </Button>\r\n </Group>\r\n <div className=\"inline-toolbar-pointer\"></div>\r\n </Toolbar>\r\n ))\r\n );\r\n}\r\n","import { useLexicalComposerContext } from \"@lexical/react/LexicalComposerContext\";\nimport {\n $getSelection,\n $isRangeSelection,\n SELECTION_CHANGE_COMMAND,\n COMMAND_PRIORITY_HIGH,\n} from \"lexical\";\nimport { useEffect, useState } from \"react\";\nimport { createPortal } from \"react-dom\";\nimport { $findMatchingParent } from \"@lexical/utils\";\n\nimport InlineToolbar from \"../components/InlineToolbar/InlineToolbar\";\nimport { $isMathNode } from \"../nodes/MathNode\";\nimport {\n $isMathHighlightNodeBlock,\n $isMathHighlightNodeInline,\n} from \"../nodes/MathHighlightNode\";\nimport { $isCodeNode } from \"@lexical/code\";\n\nconst DOM_ELEMENT = document.body;\n\nexport default function InlineToolbarPlugin() {\n const [shouldShow, setShouldShow] = useState(false);\n const [editor] = useLexicalComposerContext();\n\n // Listen for selection changes and show/hide the toolbar\n useEffect(() => {\n const unregisterListener = editor.registerCommand(\n SELECTION_CHANGE_COMMAND,\n () => {\n const selection = $getSelection();\n\n if (!$isRangeSelection(selection) || selection.isCollapsed()) {\n setShouldShow(false);\n return false;\n }\n\n // Get all selected nodes\n const nodes = selection.getNodes();\n\n // Don't show if any Math nodes are in the selection\n const hasMathNode = nodes.some((node) => $isMathNode(node));\n\n // Don't show if only one node is selected and it's a MathHighlightNode\n const isSingleMathHighlight =\n nodes.length === 1 &&\n ($isMathHighlightNodeInline(nodes[0]) ||\n $findMatchingParent(nodes[0], $isMathHighlightNodeBlock));\n\n const isCodeBlock = nodes.some((node) =>\n $findMatchingParent(node, $isCodeNode)\n );\n\n setShouldShow(!hasMathNode && !isSingleMathHighlight && !isCodeBlock);\n return false;\n },\n COMMAND_PRIORITY_HIGH\n );\n return unregisterListener;\n }, [editor]);\n\n return (\n shouldShow && createPortal(<InlineToolbar editor={editor} />, DOM_ELEMENT)\n );\n}\n","import {\n Button,\n ComboBox,\n Input,\n ListBox,\n ListBoxItem,\n Popover,\n} from \"react-aria-components\";\nimport { IconCaretDownFilled } from \"@tabler/icons-react\";\nimport { useState, useRef, useEffect } from \"react\";\nimport { OFFSCREEN_POSITION } from \"../InlineToolbar/utils\";\nimport { computeCodeMenuPosition } from \"../InlineToolbar/utils\";\nimport { getCodeLanguages, getLanguageFriendlyName } from \"@lexical/code\";\nimport \"./styles.css\";\nimport { useLexicalComposerContext } from \"@lexical/react/LexicalComposerContext\";\nimport { $getNodeByKey } from \"lexical\";\nimport { SET_CODE_LANGUAGE_COMMAND } from \"../../Plugins/CodePlugin\";\n\nexport function CodeMenu({ codeBlockCoords, codeNodeKey }) {\n const [editor] = useLexicalComposerContext();\n const [codeMenuPosition, setCodeMenuPosition] = useState({\n x: OFFSCREEN_POSITION,\n y: OFFSCREEN_POSITION,\n });\n const codeMenuRef = useRef(null);\n const [language, setLanguage] = useState(\"\");\n\n // Get the available code languages\n const codeLanguages = getCodeLanguages();\n\n // Create a unique set of friendly language names\n const friendlyLanguages = Array.from(\n new Set(codeLanguages.map((lang) => getLanguageFriendlyName(lang)))\n );\n\n // Create a reverse dictionary for friendly languages\n const friendlyToOriginal = {};\n codeLanguages.forEach((lang) => {\n const friendly = getLanguageFriendlyName(lang);\n if (!friendlyToOriginal[friendly]) {\n friendlyToOriginal[friendly] = lang;\n }\n });\n\n // Update toolbar position when selection changes\n useEffect(() => {\n setCodeMenuPosition(computeCodeMenuPosition(codeBlockCoords, codeMenuRef));\n }, [codeBlockCoords]);\n\n // Set the current language of the code block\n useEffect(() => {\n editor.read(() => {\n if (codeNodeKey) {\n const codeNode = $getNodeByKey(codeNodeKey);\n const currentLanguage = codeNode.getLanguage();\n setLanguage(getLanguageFriendlyName(currentLanguage));\n }\n });\n }, [editor, codeNodeKey]);\n\n return (\n <ComboBox\n ref={codeMenuRef}\n style={{\n position: \"absolute\",\n top: codeMenuPosition.y,\n left: codeMenuPosition.x,\n }}\n aria-label=\"Code menu\"\n inputValue={language}\n onInputChange={(friendlyValue) => {\n const originalValue = friendlyToOriginal[friendlyValue];\n editor.dispatchCommand(SET_CODE_LANGUAGE_COMMAND, [\n codeNodeKey,\n originalValue,\n ]);\n setLanguage(friendlyValue);\n }}\n >\n <div>\n <Input />\n <Button>\n <IconCaretDownFilled size={24} />\n </Button>\n </div>\n <Popover>\n <ListBox>\n {friendlyLanguages.map((friendly, index) => (\n <ListBoxItem key={index}>{friendly}</ListBoxItem>\n ))}\n </ListBox>\n </Popover>\n </ComboBox>\n );\n}\n","import {\n $createCodeNode,\n $isCodeNode,\n registerCodeHighlighting,\n} from \"@lexical/code\";\nimport { useLexicalComposerContext } from \"@lexical/react/LexicalComposerContext\";\nimport {\n $getPreviousSelection,\n $isRangeSelection,\n COMMAND_PRIORITY_HIGH,\n createCommand,\n $getSelection,\n SELECTION_CHANGE_COMMAND,\n $getNodeByKey,\n KEY_BACKSPACE_COMMAND,\n TextNode,\n $isLineBreakNode,\n $isParagraphNode,\n} from \"lexical\";\nimport { useEffect, useState } from \"react\";\nimport { createPortal } from \"react-dom\";\nimport { getSelectedNode } from \"./TextFormatPlugin\";\nimport { $findMatchingParent } from \"@lexical/utils\";\nimport { CodeMenu } from \"../components/CodeHighlightMenu/CodeMenu\";\n\nconst DOM_ELEMENT = document.body;\n\nexport const INSERT_CODE_BLOCK_COMMAND = createCommand(\n \"INSERT_CODE_BLOCK_COMMAND\"\n);\nexport const SET_CODE_LANGUAGE_COMMAND = createCommand(\n \"SET_CODE_LANGUAGE_COMMAND\"\n);\n\nfunction CodeHighlightMenuPlugin() {\n const [codeBlockCoords, setCodeBlockCoords] = useState(null);\n const [codeNodeKey, setCodeNodeKey] = useState(null);\n const [editor] = useLexicalComposerContext();\n\n useEffect(() => {\n const unregisterListener = editor.registerCommand(\n SELECTION_CHANGE_COMMAND,\n () => {\n const selection = $getSelection();\n\n if (!$isRangeSelection(selection)) {\n setCodeBlockCoords(null);\n return false;\n }\n\n const node = getSelectedNode(selection);\n const codeNode = $findMatchingParent(node, $isCodeNode);\n if (codeNode) {\n // update selection coordinates when selection changes and the condition is met\n const DOMElement = editor.getElementByKey(codeNode.getKey());\n const boundingRect = DOMElement.getBoundingClientRect();\n\n // Use top-right coordinates\n const X = boundingRect.right;\n const Y = boundingRect.top + window.scrollY;\n\n setCodeBlockCoords({ x: X, y: Y });\n setCodeNodeKey(codeNode.getKey());\n } else {\n setCodeBlockCoords(null);\n }\n\n return false;\n },\n COMMAND_PRIORITY_HIGH\n );\n return unregisterListener;\n }, [editor]);\n\n return (\n codeBlockCoords &&\n createPortal(\n <CodeMenu codeBlockCoords={codeBlockCoords} codeNodeKey={codeNodeKey} />,\n DOM_ELEMENT\n )\n );\n}\n\nfunction CodeBlockPlugin() {\n const [editor] = useLexicalComposerContext();\n\n useEffect(() => {\n return registerCodeHighlighting(editor);\n }, [editor]);\n\n useEffect(() => {\n const removeTransform = editor.registerNodeTransform(TextNode, (node) => {\n if (!node.isSimpleText()) {\n return;\n }\n\n const text = node.getTextContent();\n\n // Check for Code Block Trigger: \"``` \" at start of line/paragraph\n if (text.startsWith(\"``` \")) {\n const prevSibling = node.getPreviousSibling();\n const parentNode = $findMatchingParent(node, $isParagraphNode);\n const isStartOfParagraph =\n parentNode !== null && parentNode.getChildrenSize() === 1;\n const isAfterLineBreak = $isLineBreakNode(prevSibling);\n\n if (isStartOfParagraph || isAfterLineBreak) {\n // If there is more text after \"``` \", don't do anything\n if (text.length > 4) {\n return;\n }\n\n // Create the new code block\n const codeNode = $createCodeNode();\n\n // Replace \"``` \" with the code block\n node.replace(codeNode);\n\n // Select the code block\n codeNode.select();\n\n // Check if the next sibling is a LineBreakNode and remove it\n const nextSibling = codeNode.getNextSibling();\n if ($isLineBreakNode(nextSibling)) {\n nextSibling.remove();\n }\n\n return;\n }\n }\n });\n\n return removeTransform;\n }, [editor]);\n\n useEffect(() => {\n const unregisterCommand = editor.registerCommand(\n INSERT_CODE_BLOCK_COMMAND,\n () => {\n const prevSelection = $getPreviousSelection();\n if ($isRangeSelection(prevSelection)) {\n const codeBlockNode = $createCodeNode();\n prevSelection.insertNodes([codeBlockNode]);\n codeBlockNode.selectStart();\n\n // Bring the focus back to the editor\n setTimeout(() => {\n editor.focus();\n }, 0);\n\n return true;\n }\n\n return false;\n },\n COMMAND_PRIORITY_HIGH\n );\n\n return unregisterCommand;\n }, [editor]);\n\n useEffect(() => {\n const unregisterCommand = editor.registerCommand(\n SET_CODE_LANGUAGE_COMMAND,\n (payload) => {\n const [nodeKey, language] = payload;\n const codeNode = $getNodeByKey(nodeKey);\n if ($isCodeNode(codeNode)) {\n codeNode.setLanguage(language);\n return true;\n }\n\n return false;\n },\n COMMAND_PRIORITY_HIGH\n );\n\n return unregisterCommand;\n }, [editor]);\n\n useEffect(() => {\n const unregisterCommand = editor.registerCommand(\n KEY_BACKSPACE_COMMAND,\n (payload) => {\n const selection = $getSelection();\n if (!$isRangeSelection(selection) || !selection.isCollapsed()) {\n return false;\n }\n\n const node = selection.anchor.getNode();\n const codeNode = $findMatchingParent(node, $isCodeNode);\n\n if (codeNode) {\n // Check if we are at the beginning of the code block\n if (selection.anchor.offset === 0) {\n // Check if code block is empty (only has empty text node or line break)\n const textContent = codeNode.getTextContent();\n if (textContent === \"\") {\n codeNode.remove();\n return true;\n }\n }\n }\n\n return false;\n },\n COMMAND_PRIORITY_HIGH\n );\n\n return unregisterCommand;\n }, [editor]);\n\n return null;\n}\n\nexport function CodePlugin() {\n return (\n <>\n <CodeBlockPlugin />\n <CodeHighlightMenuPlugin />\n </>\n );\n}\n","import { useLexicalComposerContext } from \"@lexical/react/LexicalComposerContext\";\nimport {\n COMMAND_PRIORITY_HIGH,\n createCommand,\n $getPreviousSelection,\n $isRangeSelection,\n $createParagraphNode,\n} from \"lexical\";\nimport { useEffect } from \"react\";\nimport {\n $createHorizontalDividerNode,\n HorizontalDividerNode,\n} from \"../nodes/HorizontalDividerNode\";\n\nexport const INSERT_HORIZONTAL_DIVIDER_COMMAND = createCommand(\n \"INSERT_HORIZONTAL_DIVIDER_COMMAND\"\n);\n\nexport function HorizontalDividerPlugin() {\n const [editor] = useLexicalComposerContext();\n\n useEffect(() => {\n if (!editor.hasNodes([HorizontalDividerNode])) {\n throw new Error(\"HorizontalDividerNode not registered on editor\");\n }\n\n const unregisterCommand = editor.registerCommand(\n INSERT_HORIZONTAL_DIVIDER_COMMAND,\n () => {\n const prevSelection = $getPreviousSelection();\n\n if ($isRangeSelection(prevSelection)) {\n const horizontalDividerNode = $createHorizontalDividerNode();\n prevSelection.insertNodes([horizontalDividerNode]);\n\n // Move the selection to the next line after the divider\n let nextNode =\n horizontalDividerNode.getNextSibling() ||\n horizontalDividerNode.getParent().getNextSibling();\n\n if (!nextNode) {\n nextNode = $createParagraphNode();\n horizontalDividerNode.insertAfter(nextNode);\n }\n nextNode.selectStart();\n\n // Bring the focus back to the editor\n setTimeout(() => {\n editor.focus();\n }, 0);\n\n return true;\n }\n\n return false;\n },\n COMMAND_PRIORITY_HIGH\n );\n\n return unregisterCommand;\n }, [editor]);\n\n return null;\n}\n","import { useLexicalComposerContext } from \"@lexical/react/LexicalComposerContext\";\nimport {\n createCommand,\n COMMAND_PRIORITY_HIGH,\n $getPreviousSelection,\n $isRangeSelection,\n $createParagraphNode,\n SELECTION_CHANGE_COMMAND,\n $getSelection,\n $isNodeSelection,\n COMMAND_PRIORITY_LOW,\n $getNodeByKey,\n PASTE_COMMAND,\n} from \"lexical\";\nimport { useEffect, useRef } from \"react\";\nimport { $createImageNode, $isImageNode, ImageNode } from \"../nodes/ImageNode\";\nimport { NodeEventPlugin } from \"@lexical/react/LexicalNodeEventPlugin\";\n\nexport const INSERT_IMAGE_COMMAND = createCommand(\"INSERT_IMAGE_COMMAND\");\nconst SELECTED_CLASS_NAME = \"selected\";\n\n// Helper to check if a file is an image\nfunction isImageFile(file) {\n return file && file.type && file.type.startsWith(\"image/\");\n}\n\nexport function ImagePlugin() {\n const [editor] = useLexicalComposerContext();\n const selectedImgElemRef = useRef(null);\n\n useEffect(() => {\n if (!editor.hasNode(ImageNode)) {\n throw new Error(\"ImagePlugin: ImageNode not registered on editor\");\n }\n\n const unregisterCommand = editor.registerCommand(\n INSERT_IMAGE_COMMAND,\n (payload) => {\n const src = payload;\n const prevSelection = $getPreviousSelection();\n\n if ($isRangeSelection(prevSelection)) {\n const imageNode = $createImageNode(src);\n prevSelection.insertNodes([imageNode]);\n\n let nextNode =\n imageNode.getNextSibling() ||\n imageNode.getParent().getNextSibling();\n\n // insert a new paragraph node after the image node\n if (!nextNode) {\n nextNode = $createParagraphNode();\n imageNode.insertAfter(nextNode);\n }\n\n // select the image after inserting\n imageNode.select();\n\n return true;\n }\n\n return false;\n },\n COMMAND_PRIORITY_HIGH\n );\n\n return unregisterCommand;\n }, [editor]);\n\n // handle selection\n useEffect(() => {\n const unregisterCommand = editor.registerCommand(\n SELECTION_CHANGE_COMMAND,\n () => {\n // clear previous selection\n if (selectedImgElemRef.current) {\n selectedImgElemRef.current.classList.remove(SELECTED_CLASS_NAME);\n selectedImgElemRef.current = null;\n }\n\n const selection = $getSelection();\n if ($isNodeSelection(selection) && selection.getNodes().length === 1) {\n const node = selection.getNodes()[0];\n if ($isImageNode(node)) {\n const DOMElement = editor.getElementByKey(node.getKey());\n DOMElement.classList.add(SELECTED_CLASS_NAME);\n selectedImgElemRef.current = DOMElement;\n }\n }\n\n return false;\n },\n COMMAND_PRIORITY_LOW\n );\n\n return unregisterCommand;\n }, [editor]);\n\n // --- Handle PASTE_COMMAND ---\n useEffect(() => {\n const unregisterPasteCommand = editor.registerCommand(\n PASTE_COMMAND,\n (event) => {\n const clipboardData = event.clipboardData;\n if (!clipboardData) {\n return false;\n }\n\n const files = Array.from(clipboardData.files);\n const imageFiles = files.filter(isImageFile);\n\n if (imageFiles.length === 1) {\n event.preventDefault();\n\n const imageFile = imageFiles[0];\n const selection = $getSelection() || $getPreviousSelection();\n\n if (!$isRangeSelection(selection)) {\n return false;\n }\n\n // Create a blob URL for the single image\n const imageUrl = URL.createObjectURL(imageFile);\n const imageNode = $createImageNode(imageUrl);\n\n // Insert the image node\n selection.insertNodes([imageNode]);\n\n // Insert a paragraph node after the image node if the next node is empty\n let nextNode =\n imageNode.getNextSibling() ||\n imageNode.getParent().getNextSibling();\n\n if (!nextNode) {\n nextNode = $createParagraphNode();\n imageNode.insertAfter(nextNode);\n }\n\n imageNode.select();\n\n // URL.revokeObjectURL(imageUrl);\n\n return true;\n }\n\n return false;\n },\n COMMAND_PRIORITY_HIGH\n );\n\n return unregisterPasteCommand;\n }, [editor]);\n\n return (\n // Make the Image selectable\n <NodeEventPlugin\n nodeType={ImageNode}\n eventType={\"click\"}\n eventListener={(event, editor, key) => {\n const node = $getNodeByKey(key);\n node.select();\n }}\n />\n );\n}\n","import {\r\n Button,\r\n DialogTrigger,\r\n Popover,\r\n Toolbar,\r\n Group,\r\n FileTrigger,\r\n} from \"react-aria-components\";\r\nimport {\r\n IconPlus,\r\n IconCodePlus,\r\n IconPhoto,\r\n IconLineDashed,\r\n} from \"@tabler/icons-react\";\r\nimport { useState, useRef, useEffect } from \"react\";\r\nimport { OFFSCREEN_POSITION } from \"../InlineToolbar/utils\";\r\nimport { computeBlockToolbarPosition } from \"../InlineToolbar/utils\";\r\nimport \"./styles/Popover.css\";\r\n\r\nimport { INSERT_CODE_BLOCK_COMMAND } from \"../../Plugins/CodePlugin\";\r\nimport { INSERT_HORIZONTAL_DIVIDER_COMMAND } from \"../../Plugins/HorizontalDividerPlugin\";\r\nimport { INSERT_IMAGE_COMMAND } from \"../../Plugins/ImagePlugin\";\r\nimport { useLexicalComposerContext } from \"@lexical/react/LexicalComposerContext\";\r\n\r\nconst ICON_SIZE = 24;\r\n\r\nfunction BlockToolbar() {\r\n const [editor] = useLexicalComposerContext();\r\n\r\n const handleFileSelect = (fileList) => {\r\n if (!fileList || fileList.length === 0) {\r\n return; // No file selected or user cancelled\r\n }\r\n\r\n const file = fileList[0]; // Get the first selected file\r\n\r\n // Basic MIME type check\r\n if (!file.type.startsWith(\"image/\")) {\r\n alert(\"Please select an image file.\");\r\n return;\r\n }\r\n\r\n // Use FileReader to get Data URL\r\n const reader = new FileReader();\r\n\r\n reader.onload = (event) => {\r\n const imageDataUrl = event.target?.result;\r\n if (typeof imageDataUrl === \"string\") {\r\n editor.dispatchCommand(INSERT_IMAGE_COMMAND, imageDataUrl);\r\n } else {\r\n alert(\"Failed to read file as Data URL.\");\r\n }\r\n };\r\n\r\n reader.onerror = (error) => {\r\n console.error(\"Error reading file:\", error);\r\n alert(\"Error reading file.\");\r\n };\r\n\r\n // Start reading the file content as a Data URL\r\n reader.readAsDataURL(file);\r\n };\r\n\r\n return (\r\n <Toolbar aria-label=\"Block toolbar\" id=\"block-toolbar\">\r\n <Group aria-label=\"Media\">\r\n <FileTrigger\r\n acceptedFileTypes={[\"image/png\", \"image/jpeg\", \"image/gif\"]}\r\n onSelect={handleFileSelect}\r\n allowsMultiple={false}\r\n >\r\n <Button aria-label=\"image\">\r\n <IconPhoto size={ICON_SIZE} />\r\n </Button>\r\n </FileTrigger>\r\n <Button\r\n aria-label=\"code block\"\r\n onPress={() => {\r\n editor.dispatchCommand(INSERT_CODE_BLOCK_COMMAND, undefined);\r\n }}\r\n >\r\n <IconCodePlus size={ICON_SIZE} />\r\n </Button>\r\n <Button\r\n aria-label=\"horizontal divider\"\r\n onPress={() => {\r\n editor.dispatchCommand(\r\n INSERT_HORIZONTAL_DIVIDER_COMMAND,\r\n undefined\r\n );\r\n }}\r\n >\r\n <IconLineDashed size={ICON_SIZE} />\r\n </Button>\r\n </Group>\r\n </Toolbar>\r\n );\r\n}\r\n\r\nexport default function BlockToolbarPopover({\r\n selectionRectCoords,\r\n TOOLBAR_OFFSET,\r\n toolbarTriggerId,\r\n toolbarPopoverId,\r\n}) {\r\n const [toolbarPosition, setToolbarPosition] = useState({\r\n x: OFFSCREEN_POSITION,\r\n y: OFFSCREEN_POSITION,\r\n });\r\n const toolbarRef = useRef(null);\r\n\r\n // Update toolbar position when selection changes\r\n useEffect(() => {\r\n setToolbarPosition(\r\n computeBlockToolbarPosition(\r\n selectionRectCoords,\r\n toolbarRef,\r\n TOOLBAR_OFFSET\r\n )\r\n );\r\n }, [selectionRectCoords]);\r\n\r\n return (\r\n <DialogTrigger>\r\n <Button\r\n aria-label=\"Block toolbar trigger\"\r\n className=\"block-toolbar-trigger\"\r\n id={toolbarTriggerId}\r\n ref={toolbarRef}\r\n style={{\r\n position: \"absolute\",\r\n top: toolbarPosition.y,\r\n left: toolbarPosition.x,\r\n }}\r\n >\r\n <IconPlus size={ICON_SIZE} />\r\n </Button>\r\n <Popover\r\n className=\"block-toolbar-popover\"\r\n id={toolbarPopoverId}\r\n placement=\"end\"\r\n shouldFlip={false}\r\n offset={TOOLBAR_OFFSET}\r\n >\r\n <BlockToolbar />\r\n </Popover>\r\n </DialogTrigger>\r\n );\r\n}\r\n","import { useLexicalComposerContext } from \"@lexical/react/LexicalComposerContext\";\nimport {\n $getSelection,\n $isRangeSelection,\n SELECTION_CHANGE_COMMAND,\n COMMAND_PRIORITY_HIGH,\n $isParagraphNode,\n} from \"lexical\";\nimport { useEffect, useState, useRef } from \"react\";\nimport { createPortal } from \"react-dom\";\nimport { getSelectedNode } from \"./TextFormatPlugin\";\n\nimport BlockToolbarPopover from \"../components/BlockToolbar/BlockToolbar\";\n\nconst DOM_ELEMENT = document.body;\n\nexport default function BlockToolbarPlugin({ toolbarGap }) {\n const [selectionRectCoords, setSelectionRectCoords] = useState(null);\n const [editor] = useLexicalComposerContext();\n const [isEditorFocused, setIsEditorFocused] = useState(false);\n const [toolbarActive, setToolbarActive] = useState(false);\n\n // Generate unique IDs specific to this editor instance\n const randomStringRef = useRef(Math.random().toString(36).substring(2, 9));\n const toolbarTriggerId = `block-toolbar-trigger-${randomStringRef.current}`;\n const toolbarPopoverId = `block-toolbar-popover-${randomStringRef.current}`;\n\n const handleFocus = () => setIsEditorFocused(true);\n const handleBlur = (event) => {\n // Delay the blur event to give time for toolbar click to register\n setTimeout(() => {\n const toolbarTrigger = document.getElementById(toolbarTriggerId);\n if (\n toolbarTrigger &&\n (toolbarTrigger === document.activeElement ||\n toolbarTrigger.contains(document.activeElement) ||\n toolbarTrigger.contains(event.relatedTarget))\n ) {\n // Don't update focus state if we're clicking on the toolbar trigger\n return;\n }\n setIsEditorFocused(false);\n }, 10);\n };\n\n // Add observer to detect if toolbar is active\n useEffect(() => {\n const checkToolbarPresence = () => {\n const isPresent = !!document.getElementById(toolbarPopoverId);\n setToolbarActive(isPresent);\n };\n\n const observer = new MutationObserver(checkToolbarPresence);\n observer.observe(document.body, {\n childList: true,\n subtree: true,\n });\n\n // Initial check\n checkToolbarPresence();\n\n return () => observer.disconnect();\n }, []);\n\n useEffect(() => {\n const unregisterListener = editor.registerRootListener(\n (rootElement, prevRootElement) => {\n if (rootElement) {\n rootElement.addEventListener(\"focus\", handleFocus);\n rootElement.addEventListener(\"blur\", handleBlur);\n }\n\n if (prevRootElement) {\n prevRootElement.removeEventListener(\"focus\", handleFocus);\n prevRootElement.removeEventListener(\"blur\", handleBlur);\n }\n }\n );\n\n return unregisterListener;\n }, [editor]);\n\n useEffect(() => {\n const unregisterListener = editor.registerCommand(\n SELECTION_CHANGE_COMMAND,\n () => {\n // Check editor focus state during selection changes\n const rootElement = editor.getRootElement();\n if (rootElement) {\n const hasFocus =\n rootElement === document.activeElement ||\n rootElement.contains(document.activeElement);\n\n // Update focus state only if it changed to avoid re-renders\n if (hasFocus !== isEditorFocused) {\n setIsEditorFocused(hasFocus);\n }\n }\n\n const selection = $getSelection();\n\n if (!$isRangeSelection(selection) || !selection.isCollapsed()) {\n setSelectionRectCoords(null);\n return false;\n }\n\n const node = getSelectedNode(selection);\n if ($isParagraphNode(node) && node.getTextContent() === \"\") {\n // update selection coordinates when selection changes and the condition is met\n const DOMElement = editor.getElementByKey(node.getKey());\n const boundingRect = DOMElement.getBoundingClientRect();\n\n const X = boundingRect.left;\n const centerY =\n boundingRect.top + boundingRect.height / 2 + window.scrollY;\n\n setSelectionRectCoords({ x: X, y: centerY });\n } else {\n setSelectionRectCoords(null);\n }\n\n return false;\n },\n COMMAND_PRIORITY_HIGH\n );\n return unregisterListener;\n }, [editor]);\n\n return (\n selectionRectCoords &&\n (isEditorFocused || toolbarActive) &&\n createPortal(\n <BlockToolbarPopover\n selectionRectCoords={selectionRectCoords}\n TOOLBAR_OFFSET={toolbarGap}\n toolbarTriggerId={toolbarTriggerId}\n toolbarPopoverId={toolbarPopoverId}\n />,\n DOM_ELEMENT\n )\n );\n}\n","import { useLexicalComposerContext } from \"@lexical/react/LexicalComposerContext\";\nimport { useEffect } from \"react\";\nimport { $createMathNode, $isMathNode, MathNode } from \"../nodes/MathNode\";\nimport {\n $getNodeByKey,\n $getRoot,\n $getSelection,\n $isLineBreakNode,\n $isNodeSelection,\n $isRangeSelection,\n $isTextNode,\n $isParagraphNode,\n COMMAND_PRIORITY_HIGH,\n KEY_ENTER_COMMAND,\n KEY_ARROW_RIGHT_COMMAND,\n KEY_BACKSPACE_COMMAND,\n SELECTION_CHANGE_COMMAND,\n $createTextNode,\n TextNode,\n $getAdjacentNode,\n COMMAND_PRIORITY_NORMAL\n} from \"lexical\";\nimport {\n $createMathHighlightNodeBlock,\n $createMathHighlightNodeInline,\n $isMathHighlightNodeBlock,\n $isMathHighlightNodeInline,\n MathHighlightNodeBlock,\n MathHighlightNodeInline,\n} from \"../nodes/MathHighlightNode\";\nimport { NodeEventPlugin } from \"@lexical/react/LexicalNodeEventPlugin\";\nimport { $findMatchingParent } from \"@lexical/utils\";\n\nexport const INLINE_DELIMITERS = [\n [\"$\", \"$\"],\n [\"\\\\(\", \"\\\\)\"],\n];\n\nexport const DISPLAY_DELIMITERS = [\n [\"$$\", \"$$\"],\n [\"\\\\[\", \"\\\\]\"],\n];\n\nconst escapeRegex = (str) => str.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n\nconst getMatch = (text, delimiters) => {\n let earliest = null;\n\n for (const [opening, closing] of delimiters) {\n const regex = new RegExp(\n `(.*?)(${escapeRegex(opening)})(.*?)(${escapeRegex(closing)})`,\n \"g\"\n );\n const match = regex.exec(text);\n if (match) {\n const content = match[3];\n if (content && content.trim() !== \"\") {\n const start = match.index + match[1].length;\n const end = match.index + match[0].length;\n if (!earliest || start < earliest.start) {\n earliest = {\n start,\n end,\n content: opening + content + closing,\n };\n }\n }\n }\n }\n\n return earliest;\n};\n\nexport function MathInlinePlugin() {\n const [editor] = useLexicalComposerContext();\n\n useEffect(() => {\n if (!editor.hasNodes([MathNode, MathHighlightNodeInline])) {\n throw new Error(\n \"MathInlinePlugin: MathNode or MathHighlightNodeInline not registered on editor\"\n );\n }\n }, [editor]);\n\n // Convert simple text $...$ to MathNode Inline\n useEffect(() => {\n const removeTransform = editor.registerNodeTransform(TextNode, (node) => {\n if (!node.isSimpleText()) {\n return;\n }\n\n if (\n $isMathHighlightNodeInline(node) ||\n $findMatchingParent(node, $isMathHighlightNodeBlock)\n ) {\n return;\n }\n\n const text = node.getTextContent();\n const match = getMatch(text, INLINE_DELIMITERS);\n\n if (match) {\n const { start, end, content } = match;\n let targetNode;\n const mathNode = $createMathNode(content, true);\n\n if (start === 0) {\n [targetNode] = node.splitText(end);\n targetNode.insertBefore(mathNode);\n targetNode.remove();\n } else {\n [, targetNode] = node.splitText(start, end);\n targetNode.replace(mathNode);\n }\n return mathNode;\n }\n });\n return removeTransform;\n }, [editor]);\n\n // conversion: MathNode Inline <--> MathHighlightNodeInline upon selection change\n useEffect(() => {\n const unregisterListener = editor.registerCommand(\n SELECTION_CHANGE_COMMAND,\n () => {\n const selection = $getSelection();\n const nodesToExclude = new Set();\n\n if ($isNodeSelection(selection)) {\n const nodes = selection.getNodes();\n if (nodes.length === 1 && $isMathNode(nodes[0])) {\n const mathNode = nodes[0];\n if (mathNode.isInline()) {\n let equation = mathNode.getEquation();\n // Strip delimiters\n if (equation.startsWith(\"$\") && equation.endsWith(\"$\")) {\n equation = equation.slice(1, -1);\n } else if (equation.startsWith(\"\\\\(\") && equation.endsWith(\"\\\\)\")) {\n equation = equation.slice(2, -2);\n }\n\n const mathHighlightNode = $createMathHighlightNodeInline(equation);\n mathNode.replace(mathHighlightNode);\n mathHighlightNode.select();\n return true;\n }\n }\n } else if ($isRangeSelection(selection)) {\n selection.getNodes().forEach(node => nodesToExclude.add(node.getKey()));\n }\n\n // Convert unselected inline highlight nodes back to math nodes\n const root = $getRoot();\n const allTextNodes = root.getAllTextNodes();\n\n // convert unselected MathHighlightNodeInline to MathNode Inline\n allTextNodes.forEach((node) => {\n if (\n $isMathHighlightNodeInline(node) &&\n !nodesToExclude.has(node.getKey())\n ) {\n let equation = node.getTextContent();\n if (!equation) {\n node.remove();\n return;\n }\n\n let isBlock = false;\n if (equation.startsWith(\"$\") && equation.endsWith(\"$\") && equation.length >= 2) {\n equation = equation.slice(1, -1);\n isBlock = true;\n }\n\n const mathNode = isBlock\n ? $createMathNode(`$$${equation}$$`, false)\n : $createMathNode(`$${equation}$`, true);\n node.replace(mathNode);\n }\n });\n\n return false;\n },\n COMMAND_PRIORITY_HIGH\n );\n return unregisterListener;\n }, [editor]);\n\n // If a collapsed selection lands on a MathNode Inline from left,\n // convert it to MathHighlightNodeInline and select it at the start\n useEffect(() => {\n return editor.registerCommand(\n KEY_ARROW_RIGHT_COMMAND,\n (payload) => {\n const selection = $getSelection();\n if (!$isRangeSelection(selection) || !selection.isCollapsed()) {\n return false;\n }\n\n const adjacentNode = $getAdjacentNode(selection.anchor, false);\n\n if ($isMathNode(adjacentNode) && adjacentNode.isInline()) {\n const equation = adjacentNode.getEquation();\n let cleanEquation = equation;\n // Strip delimiters if present\n if (cleanEquation.startsWith(\"$\") && cleanEquation.endsWith(\"$\")) {\n cleanEquation = cleanEquation.slice(1, -1);\n } else if (cleanEquation.startsWith(\"\\\\(\") && cleanEquation.endsWith(\"\\\\)\")) {\n cleanEquation = cleanEquation.slice(2, -2);\n }\n\n const mathHighlightNode = $createMathHighlightNodeInline(cleanEquation);\n adjacentNode.replace(mathHighlightNode);\n mathHighlightNode.select(0, 0);\n return true;\n }\n\n return false;\n },\n COMMAND_PRIORITY_HIGH\n );\n }, [editor]);\n\n // If a collapsed selection lands on a MathNode Inline from right upon backspace,\n // convert it to MathHighlightNodeInline and select it at the end\n useEffect(() => {\n return editor.registerCommand(\n KEY_BACKSPACE_COMMAND,\n (payload) => {\n const selection = $getSelection();\n if (!$isRangeSelection(selection) || !selection.isCollapsed()) {\n return false;\n }\n\n const adjacentNode = $getAdjacentNode(selection.anchor, true);\n\n if ($isMathNode(adjacentNode) && adjacentNode.isInline()) {\n const equation = adjacentNode.getEquation();\n let cleanEquation = equation;\n // Strip delimiters if present\n if (cleanEquation.startsWith(\"$\") && cleanEquation.endsWith(\"$\")) {\n cleanEquation = cleanEquation.slice(1, -1);\n } else if (cleanEquation.startsWith(\"\\\\(\") && cleanEquation.endsWith(\"\\\\)\")) {\n cleanEquation = cleanEquation.slice(2, -2);\n }\n\n const mathHighlightNode = $createMathHighlightNodeInline(cleanEquation);\n adjacentNode.replace(mathHighlightNode);\n mathHighlightNode.select();\n return true;\n }\n\n return false;\n },\n COMMAND_PRIORITY_HIGH\n );\n }, [editor]);\n\n // If the selection is inside a MathHighlightNodeInline and there is no next sibling,\n // add a space after it to make it easier to escape\n useEffect(() => {\n return editor.registerCommand(\n SELECTION_CHANGE_COMMAND,\n () => {\n const selection = $getSelection();\n if (!$isRangeSelection(selection) || !selection.isCollapsed()) {\n return false;\n }\n\n const node = selection.anchor.getNode();\n\n if ($isMathHighlightNodeInline(node)) {\n const nextSibling = node.getNextSibling();\n if (!nextSibling) {\n node.insertAfter($createTextNode(\" \"));\n }\n }\n\n return false;\n },\n COMMAND_PRIORITY_NORMAL\n );\n }, [editor]);\n\n return (\n // Register click event for MathNode\n <NodeEventPlugin\n nodeType={MathNode}\n eventType={\"click\"}\n eventListener={(event, editor, key) => {\n const node = $getNodeByKey(key);\n if (node && node.isInline()) {\n node.select();\n }\n }}\n />\n );\n}\n\nexport function MathBlockPlugin() {\n const [editor] = useLexicalComposerContext();\n\n useEffect(() => {\n if (!editor.hasNodes([MathNode, MathHighlightNodeBlock])) {\n throw new Error(\n \"MathBlockPlugin: MathNode or MathHighlightNodeBlock not registered on editor\"\n );\n }\n }, [editor]);\n\n useEffect(() => {\n const removeTransform = editor.registerNodeTransform(TextNode, (node) => {\n if (!node.isSimpleText()) {\n return;\n }\n\n if ($findMatchingParent(node, $isMathHighlightNodeBlock)) {\n return;\n }\n\n const text = node.getTextContent();\n\n // Check for Block Creation Trigger: \"$$ \" at start of line/paragraph\n if (text.startsWith(\"$$ \")) {\n const prevSibling = node.getPreviousSibling();\n const parentNode = $findMatchingParent(node, $isParagraphNode);\n const isStartOfParagraph = parentNode !== null && parentNode.getChildrenSize() === 1;\n const isAfterLineBreak = $isLineBreakNode(prevSibling);\n\n if (isStartOfParagraph || isAfterLineBreak) {\n // If there is more text after \"$$ \", don't do anything\n if (text.length > 3) {\n return;\n }\n\n // Create the new math block\n const mathBlock = $createMathHighlightNodeBlock(\"\");\n\n // Replace \"$$ \" with the math block\n node.replace(mathBlock);\n\n // Select the math block\n mathBlock.select();\n\n // Check if the next sibling is a LineBreakNode and remove it\n const nextSibling = mathBlock.getNextSibling();\n if ($isLineBreakNode(nextSibling)) {\n nextSibling.remove();\n }\n\n return;\n }\n }\n\n const match = getMatch(text, DISPLAY_DELIMITERS);\n\n if (match) {\n const { start, end, content } = match;\n let targetNode;\n const mathNode = $createMathNode(content, false);\n\n if (start === 0) {\n [targetNode] = node.splitText(end);\n targetNode.insertBefore(mathNode);\n targetNode.remove();\n } else {\n [, targetNode] = node.splitText(start, end);\n targetNode.replace(mathNode);\n }\n return mathNode;\n }\n });\n return removeTransform;\n }, [editor]);\n\n useEffect(() => {\n const unregisterListener = editor.registerCommand(\n SELECTION_CHANGE_COMMAND,\n () => {\n const selection = $getSelection();\n const nodesToExclude = new Set();\n\n if ($isNodeSelection(selection)) {\n const nodes = selection.getNodes();\n if (nodes.length === 1 && $isMathNode(nodes[0])) {\n const mathNode = nodes[0];\n if (!mathNode.isInline()) {\n let equation = mathNode.getEquation();\n // Strip delimiters\n if (equation.startsWith(\"$$\") && equation.endsWith(\"$$\")) {\n equation = equation.slice(2, -2);\n } else if (equation.startsWith(\"\\\\[\") && equation.endsWith(\"\\\\]\")) {\n equation = equation.slice(2, -2);\n }\n\n const mathHighlightNode = $createMathHighlightNodeBlock(equation);\n mathNode.replace(mathHighlightNode);\n mathHighlightNode.select();\n return true;\n }\n }\n } else if ($isRangeSelection(selection)) {\n selection.getNodes().forEach(node => {\n nodesToExclude.add(node.getKey());\n const blockNode = $findMatchingParent(node, $isMathHighlightNodeBlock);\n if (blockNode) {\n nodesToExclude.add(blockNode.getKey());\n }\n });\n }\n\n // Convert unselected block highlight nodes back to math nodes\n const editorState = editor.getEditorState();\n const allNodes = editorState._nodeMap;\n for (const [, node] of allNodes) {\n if ($isMathHighlightNodeBlock(node) && node.isAttached() && !nodesToExclude.has(node.getKey())) {\n const equation = node.getTextContent();\n if (!equation) {\n node.remove();\n continue;\n }\n // Always convert back to block MathNode\n const mathNode = $createMathNode(`$$${equation}$$`, false);\n node.replace(mathNode);\n }\n }\n\n return false;\n },\n COMMAND_PRIORITY_HIGH\n );\n return unregisterListener;\n }, [editor]);\n\n useEffect(() => {\n const unregisterListener = editor.registerCommand(\n KEY_ENTER_COMMAND,\n () => {\n const selection = $getSelection();\n if (!$isRangeSelection(selection)) {\n return false;\n }\n\n const firstNode = selection.getNodes()[0];\n const mathHighlightBlock = $findMatchingParent(\n firstNode,\n $isMathHighlightNodeBlock\n );\n if (!mathHighlightBlock) {\n return false;\n }\n\n const lastChild = mathHighlightBlock.getLastChild();\n const isAtBlockEnd =\n selection.isCollapsed() &&\n ((selection.anchor.getNode().getKey() ===\n mathHighlightBlock.getKey() &&\n selection.anchor.offset === 0 &&\n mathHighlightBlock.getChildrenSize() === 0) ||\n (lastChild &&\n $isLineBreakNode(lastChild) &&\n selection.anchor.getNode().getKey() ===\n mathHighlightBlock.getKey() &&\n selection.anchor.offset ===\n mathHighlightBlock.getChildrenSize()) ||\n (lastChild &&\n $isTextNode(lastChild) &&\n selection.anchor.getNode().getKey() === lastChild.getKey() &&\n selection.anchor.offset === lastChild.getTextContent().length));\n\n if (isAtBlockEnd) {\n return false;\n }\n\n selection.insertLineBreak();\n return true;\n },\n COMMAND_PRIORITY_HIGH\n );\n return unregisterListener;\n }, [editor]);\n\n // If a collapsed selection lands on a MathNode Block from right upon backspace,\n // convert it to MathHighlightNodeBlock and select it at the end\n useEffect(() => {\n return editor.registerCommand(\n KEY_BACKSPACE_COMMAND,\n (payload) => {\n const selection = $getSelection();\n if (!$isRangeSelection(selection) || !selection.isCollapsed()) {\n return false;\n }\n\n const adjacentNode = $getAdjacentNode(selection.anchor, true);\n\n if ($isMathNode(adjacentNode) && !adjacentNode.isInline()) {\n const equation = adjacentNode.getEquation();\n let cleanEquation = equation;\n // Strip delimiters if present\n if (cleanEquation.startsWith(\"$$\") && cleanEquation.endsWith(\"$$\")) {\n cleanEquation = cleanEquation.slice(2, -2);\n } else if (cleanEquation.startsWith(\"\\\\[\") && cleanEquation.endsWith(\"\\\\]\")) {\n cleanEquation = cleanEquation.slice(2, -2);\n }\n\n const mathHighlightNode = $createMathHighlightNodeBlock(cleanEquation);\n adjacentNode.replace(mathHighlightNode);\n mathHighlightNode.select();\n return true;\n }\n\n return false;\n },\n COMMAND_PRIORITY_HIGH\n );\n }, [editor]);\n\n return (\n <NodeEventPlugin\n nodeType={MathNode}\n eventType={\"click\"}\n eventListener={(event, editor, key) => {\n const node = $getNodeByKey(key);\n if (node && !node.isInline()) {\n node.select();\n }\n }}\n />\n );\n}\n","import { $insertList, $isListItemNode } from \"@lexical/list\";\nimport { useLexicalComposerContext } from \"@lexical/react/LexicalComposerContext\";\nimport { useEffect } from \"react\";\nimport {\n $getSelection,\n $isParagraphNode,\n $isRangeSelection,\n COMMAND_PRIORITY_HIGH,\n KEY_TAB_COMMAND,\n TextNode,\n} from \"lexical\";\nimport { $findMatchingParent } from \"@lexical/utils\";\nimport { getSelectedNode } from \"./TextFormatPlugin\";\n\nconst MAX_INDENT_LEVEL = 3;\n\nexport function ListPluginExtended() {\n const [editor] = useLexicalComposerContext();\n\n // If a text node begins with '1. ' or '- ', convert it into a list\n useEffect(() => {\n const removeTransform = editor.registerNodeTransform(TextNode, (node) => {\n if (!$findMatchingParent(node, $isParagraphNode)) {\n return;\n }\n\n const parentNode = $findMatchingParent(node, $isParagraphNode);\n if (parentNode.getFirstDescendant() !== node) {\n return;\n }\n\n const selection = $getSelection();\n if ($isRangeSelection(selection) && selection.isCollapsed()) {\n const anchor = selection.anchor;\n const offset = anchor.offset;\n\n if (node.getTextContent() === \"1. \" && offset === 3) {\n $insertList(\"number\");\n node.setTextContent(\"\");\n } else if (node.getTextContent() === \"- \" && offset === 2) {\n $insertList(\"bullet\");\n node.setTextContent(\"\");\n }\n }\n });\n\n return removeTransform;\n }, [editor]);\n\n // Handle TAB Command\n useEffect(() => {\n const unregisterCommand = editor.registerCommand(\n KEY_TAB_COMMAND,\n (event) => {\n const selection = $getSelection();\n if (!$isRangeSelection(selection)) {\n return false;\n }\n\n const node = getSelectedNode(selection);\n const listItemNode = $findMatchingParent(node, $isListItemNode);\n if (!listItemNode) {\n return false;\n }\n\n const indent = listItemNode.getIndent();\n if (event.shiftKey) {\n if (indent <= 0) {\n return false;\n }\n listItemNode.setIndent(indent - 1);\n } else {\n if (indent > MAX_INDENT_LEVEL) {\n return false;\n }\n listItemNode.setIndent(indent + 1);\n }\n\n return true;\n },\n COMMAND_PRIORITY_HIGH\n );\n\n return unregisterCommand;\n }, [editor]);\n\n return null;\n}\n","import { useLexicalComposerContext } from \"@lexical/react/LexicalComposerContext\";\nimport { useEffect } from \"react\";\n\nexport function TabInterceptorPlugin() {\n const [editor] = useLexicalComposerContext();\n\n const interceptTab = (event) => {\n if (event.key === \"Tab\") {\n event.preventDefault();\n }\n };\n\n useEffect(() => {\n const unregisterListener = editor.registerRootListener(\n (rootElement, prevRootElement) => {\n if (rootElement) {\n rootElement.addEventListener(\"keydown\", interceptTab);\n }\n\n if (prevRootElement) {\n prevRootElement.removeEventListener(\"keydown\", interceptTab);\n }\n }\n );\n\n return unregisterListener;\n }, [editor]);\n\n return null;\n}\n","import { useLexicalComposerContext } from \"@lexical/react/LexicalComposerContext\";\nimport { useEffect } from \"react\";\n\n// Exposes the editor to the parent component\nexport function EditorExposePlugin({ editorRef }) {\n const [editor] = useLexicalComposerContext();\n\n useEffect(() => {\n if (editorRef) {\n editorRef.current = editor;\n\n // Clear the ref on component unmount\n return () => {\n if (editorRef) {\n editorRef.current = null;\n }\n };\n }\n }, [editor, editorRef]);\n\n return null;\n}\n","import { AutoFocusPlugin } from \"@lexical/react/LexicalAutoFocusPlugin\";\nimport { LexicalComposer } from \"@lexical/react/LexicalComposer\";\nimport \"./editor-styles.css\";\nimport { RichTextPlugin } from \"@lexical/react/LexicalRichTextPlugin\";\nimport { HistoryPlugin } from \"@lexical/react/LexicalHistoryPlugin\";\nimport { LexicalErrorBoundary } from \"@lexical/react/LexicalErrorBoundary\";\nimport InlineToolbarPlugin from \"./Plugins/InlineToolbarPlugin.jsx\";\nimport { TextFormatPlugin } from \"./Plugins/TextFormatPlugin.jsx\";\nimport BlockToolbarPlugin from \"./Plugins/BlockToolbarPlugin.jsx\";\nimport { MathInlinePlugin, MathBlockPlugin } from \"./Plugins/MathPlugin.jsx\";\nimport { CodePlugin } from \"./Plugins/CodePlugin.jsx\";\nimport { HorizontalDividerPlugin } from \"./Plugins/HorizontalDividerPlugin.jsx\";\nimport { ImagePlugin } from \"./Plugins/ImagePlugin.jsx\";\nimport { ListPlugin } from \"@lexical/react/LexicalListPlugin\";\nimport { ListPluginExtended } from \"./Plugins/ListPluginExtended.jsx\";\nimport { TabInterceptorPlugin } from \"./Plugins/TabInterceptorPlugin.jsx\";\nimport { OnChangePlugin } from \"@lexical/react/LexicalOnChangePlugin\";\nimport { EditorExposePlugin } from \"./Plugins/EditorExposePlugin.jsx\";\nimport { ContentEditable } from \"@lexical/react/LexicalContentEditable\";\nimport { ClearEditorPlugin } from \"@lexical/react/LexicalClearEditorPlugin\";\n\nexport default function Editor({\n initialConfig,\n onChange,\n editorRef,\n blockToolbarGap,\n spellCheck,\n isHeadingOneFirst,\n}) {\n return (\n <LexicalComposer initialConfig={initialConfig}>\n <RichTextPlugin\n contentEditable={\n <ContentEditable spellCheck={spellCheck} className=\"editor-input\" />\n }\n ErrorBoundary={LexicalErrorBoundary}\n />\n <TextFormatPlugin isHeadingOneFirst={isHeadingOneFirst} />\n <InlineToolbarPlugin />\n <BlockToolbarPlugin toolbarGap={blockToolbarGap} />\n <AutoFocusPlugin />\n <HistoryPlugin />\n <MathInlinePlugin />\n <MathBlockPlugin />\n <CodePlugin />\n <HorizontalDividerPlugin />\n <ImagePlugin />\n <ListPlugin />\n <ListPluginExtended />\n <TabInterceptorPlugin />\n <OnChangePlugin onChange={onChange} />\n <EditorExposePlugin editorRef={editorRef} />\n <ClearEditorPlugin />\n </LexicalComposer>\n );\n}\n"],"names":["OFFSCREEN_POSITION","computeInlineToolbarPosition","boundingRectCoords","toolbarRef","topOffset","toolbarElement","x","y","width","height","centerX","topY","getBoundingRectCoords","range","rect","computeBlockToolbarPosition","offset","toolbarX","toolbarY","computeCodeMenuPosition","codeBlockCoords","codeMenuRef","HORIZONTAL_OFFSET","VERTICAL_OFFSET","codeMenuElement","X","Y","TOGGLE_HEADING_COMMAND","createCommand","TOGGLE_QUOTE_COMMAND","TOGGLE_LINK_COMMAND","getSelectedNode","selection","anchor","focus","anchorNode","focusNode","$isAtNodeEnd","fetchTagIfHeadingNode","node","headingNode","$findMatchingParent","$isHeadingNode","updateToolbarHeadingState","toolbarHeadingState","nodes","headingTag","stateKey","HeadingPlugin","editor","useLexicalComposerContext","useEffect","toolbarState","isHeadingOne","isHeadingTwo","isHeadingThree","$getSelection","$isRangeSelection","tag","$setBlocksType","$createHeadingNode","$createParagraphNode","COMMAND_PRIORITY_HIGH","HeadingOneFirstPlugin","unregisterTransform","HeadingNode","firstChild","$getRoot","children","h1Node","isNodeOrAncestorQuote","$isQuoteNode","updateToolbarQuoteState","QuotePlugin","$createQuoteNode","getLinkAtSelection","$isLinkNode","LinkPlugin","CLICK_COMMAND","payload","linkNode","COMMAND_PRIORITY_LOW","linkURL","$toggleLink","AdjacentHeadingPlugin","HEADING_ABOVE_CLASS","TextNode","textNode","parentNode","$isParagraphNode","$isListNode","element","prevSibling","shouldHaveClass","alreadyHasClass","TextFormatPlugin","isHeadingOneFirst","jsxs","Fragment","jsx","LinkToolbar","style","closeToolbar","existingLinkURL","setLinkURL","useState","Toolbar","TextField","Input","Group","Button","url","IconCheck","ICON_SIZE","IconX","TOP_OFFSET","InlineToolbar","selectionRectCoords","setSelectionRectCoords","toolbarPosition","setToolbarPosition","useRef","setToolbarState","isLinkToolbarVisible","setLinkToolbarVisible","toolbarWidth","setToolbarWidth","setExistingLinkURL","updateToolbarFormatState","prev","editorState","anchorPoint","focusPoint","anchorOffset","focusOffset","$getCharacterOffsets","selectionDOMRange","createDOMRange","_a","useLayoutEffect","computedStyle","ToggleButton","FORMAT_TEXT_COMMAND","IconBold","IconItalic","IconCode","Separator","IconTextSize","IconBlockquote","IconLink","DOM_ELEMENT","InlineToolbarPlugin","shouldShow","setShouldShow","SELECTION_CHANGE_COMMAND","hasMathNode","$isMathNode","isSingleMathHighlight","$isMathHighlightNodeInline","$isMathHighlightNodeBlock","isCodeBlock","$isCodeNode","createPortal","CodeMenu","codeNodeKey","codeMenuPosition","setCodeMenuPosition","language","setLanguage","codeLanguages","getCodeLanguages","friendlyLanguages","lang","getLanguageFriendlyName","friendlyToOriginal","friendly","currentLanguage","$getNodeByKey","ComboBox","friendlyValue","originalValue","SET_CODE_LANGUAGE_COMMAND","IconCaretDownFilled","Popover","ListBox","index","ListBoxItem","INSERT_CODE_BLOCK_COMMAND","CodeHighlightMenuPlugin","setCodeBlockCoords","setCodeNodeKey","codeNode","boundingRect","CodeBlockPlugin","registerCodeHighlighting","text","isStartOfParagraph","isAfterLineBreak","$isLineBreakNode","$createCodeNode","nextSibling","prevSelection","$getPreviousSelection","codeBlockNode","nodeKey","KEY_BACKSPACE_COMMAND","CodePlugin","INSERT_HORIZONTAL_DIVIDER_COMMAND","HorizontalDividerPlugin","HorizontalDividerNode","horizontalDividerNode","$createHorizontalDividerNode","nextNode","INSERT_IMAGE_COMMAND","SELECTED_CLASS_NAME","isImageFile","file","ImagePlugin","selectedImgElemRef","ImageNode","src","imageNode","$createImageNode","$isNodeSelection","$isImageNode","DOMElement","PASTE_COMMAND","event","clipboardData","imageFiles","imageFile","imageUrl","NodeEventPlugin","key","BlockToolbar","FileTrigger","fileList","reader","imageDataUrl","error","IconPhoto","IconCodePlus","IconLineDashed","BlockToolbarPopover","TOOLBAR_OFFSET","toolbarTriggerId","toolbarPopoverId","DialogTrigger","IconPlus","BlockToolbarPlugin","toolbarGap","isEditorFocused","setIsEditorFocused","toolbarActive","setToolbarActive","randomStringRef","handleFocus","handleBlur","toolbarTrigger","checkToolbarPresence","isPresent","observer","rootElement","prevRootElement","hasFocus","centerY","INLINE_DELIMITERS","DISPLAY_DELIMITERS","escapeRegex","str","getMatch","delimiters","earliest","opening","closing","match","content","start","end","MathInlinePlugin","MathNode","MathHighlightNodeInline","targetNode","mathNode","$createMathNode","nodesToExclude","equation","mathHighlightNode","$createMathHighlightNodeInline","isBlock","KEY_ARROW_RIGHT_COMMAND","adjacentNode","$getAdjacentNode","cleanEquation","$createTextNode","COMMAND_PRIORITY_NORMAL","MathBlockPlugin","MathHighlightNodeBlock","mathBlock","$createMathHighlightNodeBlock","blockNode","allNodes","KEY_ENTER_COMMAND","firstNode","mathHighlightBlock","lastChild","$isTextNode","MAX_INDENT_LEVEL","ListPluginExtended","$insertList","KEY_TAB_COMMAND","listItemNode","$isListItemNode","indent","TabInterceptorPlugin","interceptTab","EditorExposePlugin","editorRef","Editor","initialConfig","onChange","blockToolbarGap","spellCheck","LexicalComposer","RichTextPlugin","ContentEditable","LexicalErrorBoundary","AutoFocusPlugin","HistoryPlugin","ListPlugin","OnChangePlugin","ClearEditorPlugin"],"mappings":"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"}