ct-rich-text-editor 1.2.9 → 1.3.0

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.
@@ -15,7 +15,7 @@ import { useLexicalNodeSelection } from "@lexical/react/useLexicalNodeSelection"
15
15
  import { calculateZoomLevel, mergeRegister } from "@lexical/utils";
16
16
  import { $getSelection, $isNodeSelection, $setSelection, $isRangeSelection, SELECTION_CHANGE_COMMAND, COMMAND_PRIORITY_LOW, CLICK_COMMAND, DRAGSTART_COMMAND, KEY_DELETE_COMMAND, KEY_BACKSPACE_COMMAND, KEY_ENTER_COMMAND, KEY_ESCAPE_COMMAND, RootNode, TextNode, LineBreakNode, ParagraphNode, createCommand, $getNodeByKey } from "lexical";
17
17
  import { useRef, useState, useCallback, useEffect, Suspense } from "react";
18
- import { $ as $isImageNode, L as LocalStoragePlugin, i as initialConfig } from "./index-9d28aec6.js";
18
+ import { $ as $isImageNode, L as LocalStoragePlugin, i as initialConfig } from "./index-7aab7b5a.js";
19
19
  import "axios";
20
20
  import "@emotion/styled";
21
21
  import "@lexical/html";
@@ -663,4 +663,4 @@ export {
663
663
  RIGHT_CLICK_IMAGE_COMMAND,
664
664
  ImageComponent as default
665
665
  };
666
- //# sourceMappingURL=index-91238d37.js.map
666
+ //# sourceMappingURL=index-113e3eb2.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index-91238d37.js","sources":["../src/components/ImageView/ImageResizer.tsx","../src/components/ImageView/index.tsx"],"sourcesContent":["/**\r\n * Copyright (c) Meta Platforms, Inc. and affiliates.\r\n *\r\n * This source code is licensed under the MIT license found in the\r\n * LICENSE file in the root directory of this source tree.\r\n *\r\n */\r\n\r\nimport \"./image-caption-styles.css\";\r\n\r\nimport { calculateZoomLevel } from \"@lexical/utils\";\r\nimport type { LexicalEditor } from \"lexical\";\r\nimport * as React from \"react\";\r\nimport { useRef } from \"react\";\r\n\r\nfunction clamp(value: number, min: number, max: number) {\r\n return Math.min(Math.max(value, min), max);\r\n}\r\n\r\nconst Direction = {\r\n east: 1 << 0,\r\n north: 1 << 3,\r\n south: 1 << 1,\r\n west: 1 << 2,\r\n};\r\n\r\nexport default function ImageResizer({\r\n onResizeStart,\r\n onResizeEnd,\r\n buttonRef,\r\n imageRef,\r\n maxWidth,\r\n editor,\r\n showCaption,\r\n setShowCaption,\r\n captionsEnabled,\r\n}: {\r\n editor: LexicalEditor;\r\n buttonRef: { current: null | HTMLButtonElement };\r\n imageRef: { current: null | HTMLElement };\r\n maxWidth?: number;\r\n onResizeEnd: (width: \"inherit\" | number, height: \"inherit\" | number) => void;\r\n onResizeStart: () => void;\r\n setShowCaption: (show: boolean) => void;\r\n showCaption: boolean;\r\n captionsEnabled: boolean;\r\n}): JSX.Element {\r\n const controlWrapperRef = useRef<HTMLDivElement>(null);\r\n const userSelect = useRef({\r\n priority: \"\",\r\n value: \"default\",\r\n });\r\n const positioningRef = useRef<{\r\n currentHeight: \"inherit\" | number;\r\n currentWidth: \"inherit\" | number;\r\n direction: number;\r\n isResizing: boolean;\r\n ratio: number;\r\n startHeight: number;\r\n startWidth: number;\r\n startX: number;\r\n startY: number;\r\n }>({\r\n currentHeight: 0,\r\n currentWidth: 0,\r\n direction: 0,\r\n isResizing: false,\r\n ratio: 0,\r\n startHeight: 0,\r\n startWidth: 0,\r\n startX: 0,\r\n startY: 0,\r\n });\r\n const editorRootElement = editor.getRootElement();\r\n\r\n // Allow enlarging up to the editor container width (ignore any fixed maxWidth cap)\r\n const maxWidthContainer =\r\n editorRootElement !== null\r\n ? editorRootElement.getBoundingClientRect().width - 20\r\n : 100;\r\n const maxHeightContainer =\r\n editorRootElement !== null\r\n ? editorRootElement.getBoundingClientRect().height - 20\r\n : 100;\r\n\r\n const minWidth = 100;\r\n const minHeight = 100;\r\n\r\n /**\r\n * Sets the cursor style to indicate the resizing direction.\r\n * This function updates the cursor for the editor and document body\r\n * based on the resizing direction.\r\n */\r\n const setStartCursor = (direction: number) => {\r\n // Determine if the resizing is happening horizontally (east or west)\r\n const ew = direction === Direction.east || direction === Direction.west;\r\n // Determine if the resizing is happening vertically (north or south)\r\n const ns = direction === Direction.north || direction === Direction.south;\r\n // Determine if the resizing is diagonal (north-west, south-east, etc.)\r\n const nwse =\r\n (direction & Direction.north && direction & Direction.west) ||\r\n (direction & Direction.south && direction & Direction.east);\r\n\r\n // Set the appropriate cursor style based on the detected direction\r\n const cursorDir = ew ? \"ew\" : ns ? \"ns\" : nwse ? \"nwse\" : \"nesw\";\r\n\r\n // Apply the cursor style to the editor root element if it exists\r\n if (editorRootElement !== null) {\r\n editorRootElement.style.setProperty(\r\n \"cursor\",\r\n `${cursorDir}-resize`,\r\n \"important\"\r\n );\r\n }\r\n\r\n // Apply the cursor style to the document body\r\n if (document.body !== null) {\r\n document.body.style.setProperty(\r\n \"cursor\",\r\n `${cursorDir}-resize`,\r\n \"important\"\r\n );\r\n\r\n // Store the current user selection settings before modifying them\r\n userSelect.current.value = document.body.style.getPropertyValue(\r\n \"-webkit-user-select\"\r\n );\r\n userSelect.current.priority = document.body.style.getPropertyPriority(\r\n \"-webkit-user-select\"\r\n );\r\n\r\n // Disable text selection during resizing to prevent unwanted text selection\r\n document.body.style.setProperty(\r\n \"-webkit-user-select\",\r\n `none`,\r\n \"important\"\r\n );\r\n }\r\n };\r\n\r\n /**\r\n * Resets the cursor style when resizing ends.\r\n */\r\n\r\n const setEndCursor = () => {\r\n if (editorRootElement !== null) {\r\n editorRootElement.style.setProperty(\"cursor\", \"text\");\r\n }\r\n if (document.body !== null) {\r\n document.body.style.setProperty(\"cursor\", \"default\");\r\n document.body.style.setProperty(\r\n \"-webkit-user-select\",\r\n userSelect.current.value,\r\n userSelect.current.priority\r\n );\r\n }\r\n };\r\n\r\n /**\r\n * Handles pointer down event when resizing starts.\r\n */\r\n const handlePointerDown = (\r\n event: React.PointerEvent<HTMLDivElement>,\r\n direction: number\r\n ) => {\r\n if (!editor.isEditable()) {\r\n return;\r\n }\r\n const image = imageRef.current;\r\n const controlWrapper = controlWrapperRef.current;\r\n\r\n // Ensure both the image and control wrapper exist before proceeding\r\n if (image !== null && controlWrapper !== null) {\r\n event.preventDefault();\r\n\r\n // Get the image's current width and height from its bounding rectangle\r\n const { width, height } = image.getBoundingClientRect();\r\n // Calculate the zoom level to adjust calculations accordingly\r\n const zoom = calculateZoomLevel(image);\r\n // Retrieve the positioning reference object to store resize state\r\n const positioning = positioningRef.current;\r\n\r\n // Store the initial dimensions of the image\r\n positioning.startWidth = width;\r\n positioning.startHeight = height;\r\n // Store the aspect ratio to maintain proportions when resizing\r\n positioning.ratio = width / height;\r\n // Set the current width and height values for tracking changes\r\n positioning.currentWidth = width;\r\n positioning.currentHeight = height;\r\n // Store the initial pointer position, adjusted for zoom level\r\n positioning.startX = event.clientX / zoom;\r\n positioning.startY = event.clientY / zoom;\r\n // Mark the resizing state as active\r\n positioning.isResizing = true;\r\n // Store the resize direction (north, south, east, west, or combinations)\r\n positioning.direction = direction;\r\n\r\n // Set the cursor style to indicate resizing in the correct direction\r\n setStartCursor(direction);\r\n onResizeStart();\r\n\r\n controlWrapper.classList.add(\"image-control-wrapper--resizing\");\r\n image.style.height = `${height}px`;\r\n image.style.width = `${width}px`;\r\n document.addEventListener(\"pointermove\", handlePointerMove);\r\n document.addEventListener(\"pointerup\", handlePointerUp);\r\n }\r\n };\r\n\r\n /**\r\n * Handles pointer move event when resizing the image dynamically.\r\n */\r\n const handlePointerMove = (event: PointerEvent) => {\r\n const image = imageRef.current;\r\n const positioning = positioningRef.current;\r\n\r\n // Check if the resize direction includes horizontal movement (east or west)\r\n const isHorizontal =\r\n positioning.direction & (Direction.east | Direction.west);\r\n // Check if the resize direction includes vertical movement (north or south)\r\n const isVertical =\r\n positioning.direction & (Direction.south | Direction.north);\r\n\r\n if (image !== null && positioning.isResizing) {\r\n // Get the zoom level of the image to ensure accurate calculations\r\n const zoom = calculateZoomLevel(image);\r\n\r\n if (isHorizontal && isVertical) {\r\n // Calculate the difference in X position relative to the starting point\r\n let diff = Math.floor(positioning.startX - event.clientX / zoom);\r\n // Reverse the difference if resizing from the east to ensure correct calculations\r\n diff = positioning.direction & Direction.east ? -diff : diff;\r\n\r\n // Calculate the new width, ensuring it stays within allowed min and max limits\r\n const width = clamp(\r\n positioning.startWidth + diff,\r\n minWidth,\r\n maxWidthContainer\r\n );\r\n // Maintain the aspect ratio by adjusting height proportionally\r\n const height = width / positioning.ratio;\r\n // Apply the new width and height to the image\r\n image.style.width = `${width}px`;\r\n image.style.height = `${height}px`;\r\n // Update stored dimensions for ongoing tracking\r\n positioning.currentHeight = height;\r\n positioning.currentWidth = width;\r\n } else if (isVertical) {\r\n // Calculate the difference in Y position relative to the starting point\r\n let diff = Math.floor(positioning.startY - event.clientY / zoom);\r\n // Reverse the difference if resizing from the south to maintain correct direction\r\n diff = positioning.direction & Direction.south ? -diff : diff;\r\n\r\n // Calculate the new height, ensuring it stays within allowed min and max limits\r\n const height = clamp(\r\n positioning.startHeight + diff,\r\n minHeight,\r\n maxHeightContainer\r\n );\r\n\r\n // Apply the new height to the image\r\n image.style.height = `${height}px`;\r\n // Update stored height for ongoing tracking\r\n positioning.currentHeight = height;\r\n } else {\r\n // Calculate the difference in X position relative to the starting point\r\n let diff = Math.floor(positioning.startX - event.clientX / zoom);\r\n // Reverse the difference if resizing from the east to maintain correct direction\r\n diff = positioning.direction & Direction.east ? -diff : diff;\r\n\r\n // Calculate the new width, ensuring it stays within allowed min and max limits\r\n const width = clamp(\r\n positioning.startWidth + diff,\r\n minWidth,\r\n maxWidthContainer\r\n );\r\n\r\n // Apply the new width to the image\r\n image.style.width = `${width}px`;\r\n // Update stored width for ongoing tracking\r\n positioning.currentWidth = width;\r\n }\r\n }\r\n };\r\n\r\n /**\r\n * Handles the pointer up event when resizing ends.\r\n */\r\n const handlePointerUp = () => {\r\n const image = imageRef.current;\r\n const positioning = positioningRef.current;\r\n const controlWrapper = controlWrapperRef.current;\r\n\r\n // Ensure the image, control wrapper exist, and resizing is active before proceeding\r\n if (image !== null && controlWrapper !== null && positioning.isResizing) {\r\n // Capture the final width and height of the resized image\r\n const width = positioning.currentWidth;\r\n const height = positioning.currentHeight;\r\n\r\n // Reset positioning values after resizing is complete\r\n positioning.startWidth = 0;\r\n positioning.startHeight = 0;\r\n positioning.ratio = 0;\r\n positioning.startX = 0;\r\n positioning.startY = 0;\r\n positioning.currentWidth = 0;\r\n positioning.currentHeight = 0;\r\n positioning.isResizing = false; // Mark resizing as finished\r\n\r\n // Remove the resizing class from the control wrapper\r\n controlWrapper.classList.remove(\"image-control-wrapper--resizing\");\r\n\r\n // Restore default cursor appearance\r\n setEndCursor();\r\n // Trigger the resize end callback with the final dimensions\r\n onResizeEnd(width, height);\r\n\r\n // Remove event listeners for pointer movement and release to stop tracking\r\n document.removeEventListener(\"pointermove\", handlePointerMove);\r\n document.removeEventListener(\"pointerup\", handlePointerUp);\r\n }\r\n };\r\n\r\n return (\r\n <div ref={controlWrapperRef}>\r\n {!showCaption && captionsEnabled && (\r\n <button\r\n className=\"image-caption-button\"\r\n ref={buttonRef}\r\n onClick={() => {\r\n setShowCaption(!showCaption);\r\n }}\r\n >\r\n Add Caption\r\n </button>\r\n )}\r\n <div\r\n className=\"image-resizer image-resizer-n\"\r\n onPointerDown={(event) => {\r\n handlePointerDown(event, Direction.north);\r\n }}\r\n />\r\n <div\r\n className=\"image-resizer image-resizer-ne\"\r\n onPointerDown={(event) => {\r\n handlePointerDown(event, Direction.north | Direction.east);\r\n }}\r\n />\r\n <div\r\n className=\"image-resizer image-resizer-e\"\r\n onPointerDown={(event) => {\r\n handlePointerDown(event, Direction.east);\r\n }}\r\n />\r\n <div\r\n className=\"image-resizer image-resizer-se\"\r\n onPointerDown={(event) => {\r\n handlePointerDown(event, Direction.south | Direction.east);\r\n }}\r\n />\r\n <div\r\n className=\"image-resizer image-resizer-s\"\r\n onPointerDown={(event) => {\r\n handlePointerDown(event, Direction.south);\r\n }}\r\n />\r\n <div\r\n className=\"image-resizer image-resizer-sw\"\r\n onPointerDown={(event) => {\r\n handlePointerDown(event, Direction.south | Direction.west);\r\n }}\r\n />\r\n <div\r\n className=\"image-resizer image-resizer-w\"\r\n onPointerDown={(event) => {\r\n handlePointerDown(event, Direction.west);\r\n }}\r\n />\r\n <div\r\n className=\"image-resizer image-resizer-nw\"\r\n onPointerDown={(event) => {\r\n handlePointerDown(event, Direction.north | Direction.west);\r\n }}\r\n />\r\n </div>\r\n );\r\n}\r\n","/**\r\n * Copyright (c) Meta Platforms, Inc. and affiliates.\r\n *\r\n * This source code is licensed under the MIT license found in the\r\n * LICENSE file in the root directory of this source tree.\r\n *\r\n */\r\n\r\nimport \"./image-caption-styles.css\";\r\n\r\nimport { CodeNode } from \"@lexical/code\";\r\nimport { LinkNode } from \"@lexical/link\";\r\nimport { AutoFocusPlugin } from \"@lexical/react/LexicalAutoFocusPlugin\";\r\nimport { useCollaborationContext } from \"@lexical/react/LexicalCollaborationContext\";\r\nimport { useLexicalComposerContext } from \"@lexical/react/LexicalComposerContext\";\r\nimport { ContentEditable } from \"@lexical/react/LexicalContentEditable\";\r\nimport { LexicalErrorBoundary } from \"@lexical/react/LexicalErrorBoundary\";\r\nimport { HistoryPlugin } from \"@lexical/react/LexicalHistoryPlugin\";\r\nimport { LexicalNestedComposer } from \"@lexical/react/LexicalNestedComposer\";\r\nimport { OnChangePlugin } from \"@lexical/react/LexicalOnChangePlugin\";\r\n// import './ImageNode.css';\r\nimport { RichTextPlugin } from \"@lexical/react/LexicalRichTextPlugin\";\r\nimport { useLexicalEditable } from \"@lexical/react/useLexicalEditable\";\r\nimport { useLexicalNodeSelection } from \"@lexical/react/useLexicalNodeSelection\";\r\nimport { mergeRegister } from \"@lexical/utils\";\r\nimport type {\r\n BaseSelection,\r\n LexicalCommand,\r\n LexicalEditor,\r\n NodeKey,\r\n} from \"lexical\";\r\nimport {\r\n $getNodeByKey,\r\n $getSelection,\r\n $isNodeSelection,\r\n $isRangeSelection,\r\n $setSelection,\r\n CLICK_COMMAND,\r\n COMMAND_PRIORITY_LOW,\r\n createCommand,\r\n DRAGSTART_COMMAND,\r\n KEY_BACKSPACE_COMMAND,\r\n KEY_DELETE_COMMAND,\r\n KEY_ENTER_COMMAND,\r\n KEY_ESCAPE_COMMAND,\r\n LineBreakNode,\r\n ParagraphNode,\r\n RootNode,\r\n SELECTION_CHANGE_COMMAND,\r\n TextNode,\r\n} from \"lexical\";\r\nimport * as React from \"react\";\r\nimport { Suspense, useCallback, useEffect, useRef, useState } from \"react\";\r\n// import brokenImage from '../images/image-broken.svg';\r\nimport { initialConfig } from \"src/constants\";\r\nimport { $isImageNode } from \"src/nodes/ImageNode\";\r\nimport LocalStoragePlugin from \"src/plugins/LocalStoragePlugin\";\r\n\r\nimport ImageResizer from \"./ImageResizer\";\r\n\r\nconst imageCache = new Set();\r\n\r\nexport const RIGHT_CLICK_IMAGE_COMMAND: LexicalCommand<MouseEvent> =\r\n createCommand(\"RIGHT_CLICK_IMAGE_COMMAND\");\r\n\r\nfunction useSuspenseImage(src: string) {\r\n if (!imageCache.has(src)) {\r\n throw new Promise((resolve) => {\r\n const img = new Image();\r\n img.src = src;\r\n img.onload = () => {\r\n imageCache.add(src);\r\n resolve(null);\r\n };\r\n img.onerror = () => {\r\n imageCache.add(src);\r\n };\r\n });\r\n }\r\n}\r\n\r\nfunction LazyImage({\r\n altText,\r\n className,\r\n imageRef,\r\n src,\r\n width,\r\n height,\r\n maxWidth,\r\n onError,\r\n}: {\r\n altText: string;\r\n className: string | null;\r\n height: \"inherit\" | number;\r\n imageRef: { current: null | HTMLImageElement };\r\n maxWidth: number;\r\n src: string;\r\n width: \"inherit\" | number;\r\n onError: () => void;\r\n}): JSX.Element {\r\n useSuspenseImage(src);\r\n const hasExplicitSize = typeof width === 'number' || typeof height === 'number';\r\n const computedWidth = typeof width === 'number' ? width : 'auto';\r\n const computedHeight = typeof height === 'number' ? height : 'auto';\r\n const DEFAULT_PIXEL_WIDTH = 429; // px\r\n const DEFAULT_PIXEL_HEIGHT = 365.375; // px\r\n\r\n return (\r\n <img\r\n className={className || undefined}\r\n src={src}\r\n alt={altText}\r\n ref={imageRef}\r\n style={\r\n hasExplicitSize\r\n ? {\r\n // User/resizer has set a numeric size; respect it but don't exceed container\r\n width: computedWidth,\r\n height: computedHeight,\r\n maxWidth: '100%',\r\n }\r\n : {\r\n // Default rendering: requested smaller size\r\n width: `${DEFAULT_PIXEL_WIDTH}px`,\r\n height: `${DEFAULT_PIXEL_HEIGHT}px`,\r\n maxWidth: '100%',\r\n }\r\n }\r\n onError={onError}\r\n draggable=\"false\"\r\n />\r\n );\r\n}\r\n\r\n// if the image is broken ; we are showing this component\r\nfunction BrokenImage(): JSX.Element {\r\n return (\r\n <img\r\n src={\"\"} //TODO: NEED TO ADD BROKEN IMAGE\r\n style={{\r\n height: 200,\r\n opacity: 0.2,\r\n width: 200,\r\n }}\r\n draggable=\"false\"\r\n />\r\n );\r\n}\r\n\r\nexport default function ImageComponent({\r\n src,\r\n altText,\r\n nodeKey,\r\n width,\r\n height,\r\n maxWidth,\r\n resizable,\r\n showCaption,\r\n caption,\r\n captionsEnabled,\r\n}: {\r\n altText: string;\r\n caption: LexicalEditor;\r\n height: \"inherit\" | number;\r\n maxWidth: number;\r\n nodeKey: NodeKey;\r\n resizable: boolean;\r\n showCaption: boolean;\r\n src: string;\r\n width: \"inherit\" | number;\r\n captionsEnabled: boolean;\r\n}): JSX.Element {\r\n const imageRef = useRef<null | HTMLImageElement>(null);\r\n const buttonRef = useRef<HTMLButtonElement | null>(null);\r\n const [isSelected, setSelected, clearSelection] =\r\n useLexicalNodeSelection(nodeKey);\r\n const [isResizing, setIsResizing] = useState<boolean>(false);\r\n const { isCollabActive } = useCollaborationContext();\r\n const [editor] = useLexicalComposerContext();\r\n const [selection, setSelection] = useState<BaseSelection | null>(null);\r\n const activeEditorRef = useRef<LexicalEditor | null>(null);\r\n const [isLoadError, setIsLoadError] = useState<boolean>(false);\r\n const isEditable = useLexicalEditable();\r\n\r\n /**\r\n * Deletes the image node when the delete key is pressed.\r\n */\r\n const $onDelete = useCallback(\r\n (payload: KeyboardEvent) => {\r\n const deleteSelection = $getSelection();\r\n if (isSelected && $isNodeSelection(deleteSelection)) {\r\n const event: KeyboardEvent = payload;\r\n event.preventDefault();\r\n editor.update(() => {\r\n deleteSelection.getNodes().forEach((node) => {\r\n if ($isImageNode(node)) {\r\n node.remove();\r\n }\r\n });\r\n });\r\n }\r\n return false;\r\n },\r\n [editor, isSelected]\r\n );\r\n\r\n /**\r\n * Handles enter key to move focus into the caption editor.\r\n */\r\n const $onEnter = useCallback(\r\n (event: KeyboardEvent) => {\r\n const latestSelection = $getSelection();\r\n const buttonElem = buttonRef.current;\r\n if (\r\n isSelected &&\r\n $isNodeSelection(latestSelection) &&\r\n latestSelection.getNodes().length === 1\r\n ) {\r\n if (showCaption) {\r\n // Move focus into nested editor\r\n $setSelection(null);\r\n event.preventDefault();\r\n caption.focus();\r\n return true;\r\n } else if (\r\n buttonElem !== null &&\r\n buttonElem !== document.activeElement\r\n ) {\r\n event.preventDefault();\r\n buttonElem.focus();\r\n return true;\r\n }\r\n }\r\n return false;\r\n },\r\n [caption, isSelected, showCaption]\r\n );\r\n\r\n /**\r\n * Handles escape key to reset selection.\r\n */\r\n const $onEscape = useCallback(\r\n (event: KeyboardEvent) => {\r\n if (\r\n activeEditorRef.current === caption ||\r\n buttonRef.current === event.target\r\n ) {\r\n $setSelection(null);\r\n editor.update(() => {\r\n setSelected(true);\r\n const parentRootElement = editor.getRootElement();\r\n if (parentRootElement !== null) {\r\n parentRootElement.focus();\r\n }\r\n });\r\n return true;\r\n }\r\n return false;\r\n },\r\n [caption, editor, setSelected]\r\n );\r\n\r\n const onClick = useCallback(\r\n (payload: MouseEvent) => {\r\n const event = payload;\r\n\r\n if (isResizing) {\r\n return true;\r\n }\r\n if (event.target === imageRef.current) {\r\n if (event.shiftKey) {\r\n setSelected(!isSelected);\r\n } else {\r\n clearSelection();\r\n setSelected(true);\r\n }\r\n return true;\r\n }\r\n\r\n return false;\r\n },\r\n [isResizing, isSelected, setSelected, clearSelection]\r\n );\r\n\r\n const onRightClick = useCallback(\r\n (event: MouseEvent): void => {\r\n editor.getEditorState().read(() => {\r\n const latestSelection = $getSelection();\r\n const domElement = event.target as HTMLElement;\r\n if (\r\n domElement.tagName === \"IMG\" &&\r\n $isRangeSelection(latestSelection) &&\r\n latestSelection.getNodes().length === 1\r\n ) {\r\n editor.dispatchCommand(\r\n RIGHT_CLICK_IMAGE_COMMAND,\r\n event as MouseEvent\r\n );\r\n }\r\n });\r\n },\r\n [editor]\r\n );\r\n\r\n useEffect(() => {\r\n let isMounted = true;\r\n const rootElement = editor.getRootElement();\r\n const unregister = mergeRegister(\r\n editor.registerUpdateListener(({ editorState }) => {\r\n if (isMounted) {\r\n setSelection(editorState.read(() => $getSelection()));\r\n }\r\n }),\r\n editor.registerCommand(\r\n SELECTION_CHANGE_COMMAND,\r\n (_, activeEditor) => {\r\n activeEditorRef.current = activeEditor;\r\n return false;\r\n },\r\n COMMAND_PRIORITY_LOW\r\n ),\r\n editor.registerCommand<MouseEvent>(\r\n CLICK_COMMAND,\r\n onClick,\r\n COMMAND_PRIORITY_LOW\r\n ),\r\n editor.registerCommand<MouseEvent>(\r\n RIGHT_CLICK_IMAGE_COMMAND,\r\n onClick,\r\n COMMAND_PRIORITY_LOW\r\n ),\r\n editor.registerCommand(\r\n DRAGSTART_COMMAND,\r\n (event) => {\r\n if (event.target === imageRef.current) {\r\n alert(\"s\");\r\n // TODO This is just a temporary workaround for FF to behave like other browsers.\r\n // Ideally, this handles drag & drop too (and all browsers).\r\n event.preventDefault();\r\n return true;\r\n }\r\n return false;\r\n },\r\n COMMAND_PRIORITY_LOW\r\n ),\r\n editor.registerCommand(\r\n KEY_DELETE_COMMAND,\r\n $onDelete,\r\n COMMAND_PRIORITY_LOW\r\n ),\r\n editor.registerCommand(\r\n KEY_BACKSPACE_COMMAND,\r\n $onDelete,\r\n COMMAND_PRIORITY_LOW\r\n ),\r\n editor.registerCommand(KEY_ENTER_COMMAND, $onEnter, COMMAND_PRIORITY_LOW),\r\n editor.registerCommand(\r\n KEY_ESCAPE_COMMAND,\r\n $onEscape,\r\n COMMAND_PRIORITY_LOW\r\n )\r\n );\r\n\r\n rootElement?.addEventListener(\"contextmenu\", onRightClick);\r\n\r\n return () => {\r\n isMounted = false;\r\n unregister();\r\n rootElement?.removeEventListener(\"contextmenu\", onRightClick);\r\n };\r\n }, [\r\n clearSelection,\r\n editor,\r\n isResizing,\r\n isSelected,\r\n nodeKey,\r\n $onDelete,\r\n $onEnter,\r\n $onEscape,\r\n onClick,\r\n onRightClick,\r\n setSelected,\r\n ]);\r\n\r\n const setShowCaption = () => {\r\n editor.update(() => {\r\n const node = $getNodeByKey(nodeKey);\r\n if ($isImageNode(node)) {\r\n node.setShowCaption(true);\r\n }\r\n });\r\n };\r\n\r\n const onResizeEnd = (\r\n nextWidth: \"inherit\" | number,\r\n nextHeight: \"inherit\" | number\r\n ) => {\r\n // Delay hiding the resize bars for click case\r\n setTimeout(() => {\r\n setIsResizing(false);\r\n }, 200);\r\n\r\n editor.update(() => {\r\n const node = $getNodeByKey(nodeKey);\r\n if ($isImageNode(node)) {\r\n node.setWidthAndHeight(nextWidth, nextHeight);\r\n }\r\n });\r\n };\r\n\r\n const onResizeStart = () => {\r\n setIsResizing(true);\r\n };\r\n\r\n const draggable = isSelected && $isNodeSelection(selection) && !isResizing;\r\n const isFocused = (isSelected || isResizing) && isEditable;\r\n return (\r\n <Suspense fallback={null}>\r\n <>\r\n <div draggable={draggable}>\r\n {isLoadError ? (\r\n <BrokenImage />\r\n ) : (\r\n <LazyImage\r\n className={\r\n isFocused\r\n ? `focused ${$isNodeSelection(selection) ? \"draggable\" : \"\"}`\r\n : null\r\n }\r\n src={src}\r\n altText={altText}\r\n imageRef={imageRef}\r\n width={width}\r\n height={height}\r\n maxWidth={maxWidth}\r\n onError={() => setIsLoadError(true)}\r\n />\r\n )}\r\n </div>\r\n\r\n {showCaption && (\r\n <div className=\"image-caption-container\">\r\n <LexicalNestedComposer\r\n initialEditor={caption}\r\n initialNodes={[\r\n RootNode,\r\n TextNode,\r\n LineBreakNode,\r\n ParagraphNode,\r\n LinkNode,\r\n CodeNode,\r\n ]}\r\n >\r\n <AutoFocusPlugin />\r\n\r\n <RichTextPlugin\r\n contentEditable={\r\n <ContentEditable\r\n aria-placeholder=\"Enter a caption...\"\r\n placeholder={() => <span>Enter a caption...</span>}\r\n className=\"ImageNode__contentEditable\"\r\n />\r\n }\r\n ErrorBoundary={LexicalErrorBoundary}\r\n />\r\n\r\n <OnChangePlugin onChange={(e) => console.log(\"e\")} />\r\n <HistoryPlugin />\r\n <LocalStoragePlugin namespace={initialConfig.namespace} />\r\n </LexicalNestedComposer>\r\n </div>\r\n )}\r\n {resizable && $isNodeSelection(selection) && isFocused && (\r\n <ImageResizer\r\n showCaption={showCaption}\r\n setShowCaption={setShowCaption}\r\n editor={editor}\r\n buttonRef={buttonRef}\r\n imageRef={imageRef}\r\n maxWidth={maxWidth}\r\n onResizeStart={onResizeStart}\r\n onResizeEnd={onResizeEnd}\r\n captionsEnabled={!isLoadError && captionsEnabled}\r\n />\r\n )}\r\n </>\r\n </Suspense>\r\n );\r\n}\r\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAeA,SAAS,MAAM,OAAe,KAAa,KAAa;AACtD,SAAO,KAAK,IAAI,KAAK,IAAI,OAAO,GAAG,GAAG,GAAG;AAC3C;AAEA,MAAM,YAAY;AAAA,EAChB,MAAM,KAAK;AAAA,EACX,OAAO,KAAK;AAAA,EACZ,OAAO,KAAK;AAAA,EACZ,MAAM,KAAK;AACb;AAEA,SAAwB,aAAa;AAAA,EACnC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAUgB;AACR,QAAA,oBAAoB,OAAuB,IAAI;AACrD,QAAM,aAAa,OAAO;AAAA,IACxB,UAAU;AAAA,IACV,OAAO;AAAA,EAAA,CACR;AACD,QAAM,iBAAiB,OAUpB;AAAA,IACD,eAAe;AAAA,IACf,cAAc;AAAA,IACd,WAAW;AAAA,IACX,YAAY;AAAA,IACZ,OAAO;AAAA,IACP,aAAa;AAAA,IACb,YAAY;AAAA,IACZ,QAAQ;AAAA,IACR,QAAQ;AAAA,EAAA,CACT;AACK,QAAA,oBAAoB,OAAO;AAGjC,QAAM,oBACJ,sBAAsB,OAClB,kBAAkB,wBAAwB,QAAQ,KAClD;AACN,QAAM,qBACJ,sBAAsB,OAClB,kBAAkB,wBAAwB,SAAS,KACnD;AAEN,QAAM,WAAW;AACjB,QAAM,YAAY;AAOZ,QAAA,iBAAiB,CAAC,cAAsB;AAE5C,UAAM,KAAK,cAAc,UAAU,QAAQ,cAAc,UAAU;AAEnE,UAAM,KAAK,cAAc,UAAU,SAAS,cAAc,UAAU;AAE9D,UAAA,OACH,YAAY,UAAU,SAAS,YAAY,UAAU,QACrD,YAAY,UAAU,SAAS,YAAY,UAAU;AAGxD,UAAM,YAAY,KAAK,OAAO,KAAK,OAAO,OAAO,SAAS;AAG1D,QAAI,sBAAsB,MAAM;AAC9B,wBAAkB,MAAM;AAAA,QACtB;AAAA,QACA,GAAG,SAAS;AAAA,QACZ;AAAA,MAAA;AAAA,IAEJ;AAGI,QAAA,SAAS,SAAS,MAAM;AAC1B,eAAS,KAAK,MAAM;AAAA,QAClB;AAAA,QACA,GAAG,SAAS;AAAA,QACZ;AAAA,MAAA;AAIF,iBAAW,QAAQ,QAAQ,SAAS,KAAK,MAAM;AAAA,QAC7C;AAAA,MAAA;AAEF,iBAAW,QAAQ,WAAW,SAAS,KAAK,MAAM;AAAA,QAChD;AAAA,MAAA;AAIF,eAAS,KAAK,MAAM;AAAA,QAClB;AAAA,QACA;AAAA,QACA;AAAA,MAAA;AAAA,IAEJ;AAAA,EAAA;AAOF,QAAM,eAAe,MAAM;AACzB,QAAI,sBAAsB,MAAM;AACZ,wBAAA,MAAM,YAAY,UAAU,MAAM;AAAA,IACtD;AACI,QAAA,SAAS,SAAS,MAAM;AAC1B,eAAS,KAAK,MAAM,YAAY,UAAU,SAAS;AACnD,eAAS,KAAK,MAAM;AAAA,QAClB;AAAA,QACA,WAAW,QAAQ;AAAA,QACnB,WAAW,QAAQ;AAAA,MAAA;AAAA,IAEvB;AAAA,EAAA;AAMI,QAAA,oBAAoB,CACxB,OACA,cACG;AACC,QAAA,CAAC,OAAO,cAAc;AACxB;AAAA,IACF;AACA,UAAM,QAAQ,SAAS;AACvB,UAAM,iBAAiB,kBAAkB;AAGrC,QAAA,UAAU,QAAQ,mBAAmB,MAAM;AAC7C,YAAM,eAAe;AAGrB,YAAM,EAAE,OAAO,OAAO,IAAI,MAAM,sBAAsB;AAEhD,YAAA,OAAO,mBAAmB,KAAK;AAErC,YAAM,cAAc,eAAe;AAGnC,kBAAY,aAAa;AACzB,kBAAY,cAAc;AAE1B,kBAAY,QAAQ,QAAQ;AAE5B,kBAAY,eAAe;AAC3B,kBAAY,gBAAgB;AAEhB,kBAAA,SAAS,MAAM,UAAU;AACzB,kBAAA,SAAS,MAAM,UAAU;AAErC,kBAAY,aAAa;AAEzB,kBAAY,YAAY;AAGxB,qBAAe,SAAS;AACV;AAEC,qBAAA,UAAU,IAAI,iCAAiC;AACxD,YAAA,MAAM,SAAS,GAAG,MAAM;AACxB,YAAA,MAAM,QAAQ,GAAG,KAAK;AACnB,eAAA,iBAAiB,eAAe,iBAAiB;AACjD,eAAA,iBAAiB,aAAa,eAAe;AAAA,IACxD;AAAA,EAAA;AAMI,QAAA,oBAAoB,CAAC,UAAwB;AACjD,UAAM,QAAQ,SAAS;AACvB,UAAM,cAAc,eAAe;AAGnC,UAAM,eACJ,YAAY,aAAa,UAAU,OAAO,UAAU;AAEtD,UAAM,aACJ,YAAY,aAAa,UAAU,QAAQ,UAAU;AAEnD,QAAA,UAAU,QAAQ,YAAY,YAAY;AAEtC,YAAA,OAAO,mBAAmB,KAAK;AAErC,UAAI,gBAAgB,YAAY;AAE9B,YAAI,OAAO,KAAK,MAAM,YAAY,SAAS,MAAM,UAAU,IAAI;AAE/D,eAAO,YAAY,YAAY,UAAU,OAAO,CAAC,OAAO;AAGxD,cAAM,QAAQ;AAAA,UACZ,YAAY,aAAa;AAAA,UACzB;AAAA,UACA;AAAA,QAAA;AAGI,cAAA,SAAS,QAAQ,YAAY;AAE7B,cAAA,MAAM,QAAQ,GAAG,KAAK;AACtB,cAAA,MAAM,SAAS,GAAG,MAAM;AAE9B,oBAAY,gBAAgB;AAC5B,oBAAY,eAAe;AAAA,iBAClB,YAAY;AAErB,YAAI,OAAO,KAAK,MAAM,YAAY,SAAS,MAAM,UAAU,IAAI;AAE/D,eAAO,YAAY,YAAY,UAAU,QAAQ,CAAC,OAAO;AAGzD,cAAM,SAAS;AAAA,UACb,YAAY,cAAc;AAAA,UAC1B;AAAA,UACA;AAAA,QAAA;AAII,cAAA,MAAM,SAAS,GAAG,MAAM;AAE9B,oBAAY,gBAAgB;AAAA,MAAA,OACvB;AAEL,YAAI,OAAO,KAAK,MAAM,YAAY,SAAS,MAAM,UAAU,IAAI;AAE/D,eAAO,YAAY,YAAY,UAAU,OAAO,CAAC,OAAO;AAGxD,cAAM,QAAQ;AAAA,UACZ,YAAY,aAAa;AAAA,UACzB;AAAA,UACA;AAAA,QAAA;AAII,cAAA,MAAM,QAAQ,GAAG,KAAK;AAE5B,oBAAY,eAAe;AAAA,MAC7B;AAAA,IACF;AAAA,EAAA;AAMF,QAAM,kBAAkB,MAAM;AAC5B,UAAM,QAAQ,SAAS;AACvB,UAAM,cAAc,eAAe;AACnC,UAAM,iBAAiB,kBAAkB;AAGzC,QAAI,UAAU,QAAQ,mBAAmB,QAAQ,YAAY,YAAY;AAEvE,YAAM,QAAQ,YAAY;AAC1B,YAAM,SAAS,YAAY;AAG3B,kBAAY,aAAa;AACzB,kBAAY,cAAc;AAC1B,kBAAY,QAAQ;AACpB,kBAAY,SAAS;AACrB,kBAAY,SAAS;AACrB,kBAAY,eAAe;AAC3B,kBAAY,gBAAgB;AAC5B,kBAAY,aAAa;AAGV,qBAAA,UAAU,OAAO,iCAAiC;AAGpD;AAEb,kBAAY,OAAO,MAAM;AAGhB,eAAA,oBAAoB,eAAe,iBAAiB;AACpD,eAAA,oBAAoB,aAAa,eAAe;AAAA,IAC3D;AAAA,EAAA;AAIA,SAAA,qBAAC,OAAI,EAAA,KAAK,mBACP,UAAA;AAAA,IAAA,CAAC,eAAe,mBACf;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,WAAU;AAAA,QACV,KAAK;AAAA,QACL,SAAS,MAAM;AACb,yBAAe,CAAC,WAAW;AAAA,QAC7B;AAAA,QACD,UAAA;AAAA,MAAA;AAAA,IAED;AAAA,IAEF;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,WAAU;AAAA,QACV,eAAe,CAAC,UAAU;AACN,4BAAA,OAAO,UAAU,KAAK;AAAA,QAC1C;AAAA,MAAA;AAAA,IACF;AAAA,IACA;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,WAAU;AAAA,QACV,eAAe,CAAC,UAAU;AACxB,4BAAkB,OAAO,UAAU,QAAQ,UAAU,IAAI;AAAA,QAC3D;AAAA,MAAA;AAAA,IACF;AAAA,IACA;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,WAAU;AAAA,QACV,eAAe,CAAC,UAAU;AACN,4BAAA,OAAO,UAAU,IAAI;AAAA,QACzC;AAAA,MAAA;AAAA,IACF;AAAA,IACA;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,WAAU;AAAA,QACV,eAAe,CAAC,UAAU;AACxB,4BAAkB,OAAO,UAAU,QAAQ,UAAU,IAAI;AAAA,QAC3D;AAAA,MAAA;AAAA,IACF;AAAA,IACA;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,WAAU;AAAA,QACV,eAAe,CAAC,UAAU;AACN,4BAAA,OAAO,UAAU,KAAK;AAAA,QAC1C;AAAA,MAAA;AAAA,IACF;AAAA,IACA;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,WAAU;AAAA,QACV,eAAe,CAAC,UAAU;AACxB,4BAAkB,OAAO,UAAU,QAAQ,UAAU,IAAI;AAAA,QAC3D;AAAA,MAAA;AAAA,IACF;AAAA,IACA;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,WAAU;AAAA,QACV,eAAe,CAAC,UAAU;AACN,4BAAA,OAAO,UAAU,IAAI;AAAA,QACzC;AAAA,MAAA;AAAA,IACF;AAAA,IACA;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,WAAU;AAAA,QACV,eAAe,CAAC,UAAU;AACxB,4BAAkB,OAAO,UAAU,QAAQ,UAAU,IAAI;AAAA,QAC3D;AAAA,MAAA;AAAA,IACF;AAAA,EACF,EAAA,CAAA;AAEJ;ACvUA,MAAM,iCAAiB;AAEV,MAAA,4BACX,cAAc,2BAA2B;AAE3C,SAAS,iBAAiB,KAAa;AACrC,MAAI,CAAC,WAAW,IAAI,GAAG,GAAG;AAClB,UAAA,IAAI,QAAQ,CAAC,YAAY;AACvB,YAAA,MAAM,IAAI;AAChB,UAAI,MAAM;AACV,UAAI,SAAS,MAAM;AACjB,mBAAW,IAAI,GAAG;AAClB,gBAAQ,IAAI;AAAA,MAAA;AAEd,UAAI,UAAU,MAAM;AAClB,mBAAW,IAAI,GAAG;AAAA,MAAA;AAAA,IACpB,CACD;AAAA,EACH;AACF;AAEA,SAAS,UAAU;AAAA,EACjB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GASgB;AACd,mBAAiB,GAAG;AACpB,QAAM,kBAAkB,OAAO,UAAU,YAAY,OAAO,WAAW;AACvE,QAAM,gBAAgB,OAAO,UAAU,WAAW,QAAQ;AAC1D,QAAM,iBAAiB,OAAO,WAAW,WAAW,SAAS;AAC7D,QAAM,sBAAsB;AAC5B,QAAM,uBAAuB;AAG3B,SAAA;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,WAAW,aAAa;AAAA,MACxB;AAAA,MACA,KAAK;AAAA,MACL,KAAK;AAAA,MACL,OACE,kBACI;AAAA;AAAA,QAEE,OAAO;AAAA,QACP,QAAQ;AAAA,QACR,UAAU;AAAA,MAAA,IAEZ;AAAA;AAAA,QAEE,OAAO,GAAG,mBAAmB;AAAA,QAC7B,QAAQ,GAAG,oBAAoB;AAAA,QAC/B,UAAU;AAAA,MACZ;AAAA,MAEN;AAAA,MACA,WAAU;AAAA,IAAA;AAAA,EAAA;AAGhB;AAGA,SAAS,cAA2B;AAEhC,SAAA;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,KAAK;AAAA,MACL,OAAO;AAAA,QACL,QAAQ;AAAA,QACR,SAAS;AAAA,QACT,OAAO;AAAA,MACT;AAAA,MACA,WAAU;AAAA,IAAA;AAAA,EAAA;AAGhB;AAEA,SAAwB,eAAe;AAAA,EACrC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAWgB;AACR,QAAA,WAAW,OAAgC,IAAI;AAC/C,QAAA,YAAY,OAAiC,IAAI;AACvD,QAAM,CAAC,YAAY,aAAa,cAAc,IAC5C,wBAAwB,OAAO;AACjC,QAAM,CAAC,YAAY,aAAa,IAAI,SAAkB,KAAK;AAChC,0BAAwB;AAC7C,QAAA,CAAC,MAAM,IAAI;AACjB,QAAM,CAAC,WAAW,YAAY,IAAI,SAA+B,IAAI;AAC/D,QAAA,kBAAkB,OAA6B,IAAI;AACzD,QAAM,CAAC,aAAa,cAAc,IAAI,SAAkB,KAAK;AAC7D,QAAM,aAAa;AAKnB,QAAM,YAAY;AAAA,IAChB,CAAC,YAA2B;AAC1B,YAAM,kBAAkB;AACpB,UAAA,cAAc,iBAAiB,eAAe,GAAG;AACnD,cAAM,QAAuB;AAC7B,cAAM,eAAe;AACrB,eAAO,OAAO,MAAM;AAClB,0BAAgB,SAAS,EAAE,QAAQ,CAAC,SAAS;AACvC,gBAAA,aAAa,IAAI,GAAG;AACtB,mBAAK,OAAO;AAAA,YACd;AAAA,UAAA,CACD;AAAA,QAAA,CACF;AAAA,MACH;AACO,aAAA;AAAA,IACT;AAAA,IACA,CAAC,QAAQ,UAAU;AAAA,EAAA;AAMrB,QAAM,WAAW;AAAA,IACf,CAAC,UAAyB;AACxB,YAAM,kBAAkB;AACxB,YAAM,aAAa,UAAU;AAE3B,UAAA,cACA,iBAAiB,eAAe,KAChC,gBAAgB,SAAS,EAAE,WAAW,GACtC;AACA,YAAI,aAAa;AAEf,wBAAc,IAAI;AAClB,gBAAM,eAAe;AACrB,kBAAQ,MAAM;AACP,iBAAA;AAAA,QAEP,WAAA,eAAe,QACf,eAAe,SAAS,eACxB;AACA,gBAAM,eAAe;AACrB,qBAAW,MAAM;AACV,iBAAA;AAAA,QACT;AAAA,MACF;AACO,aAAA;AAAA,IACT;AAAA,IACA,CAAC,SAAS,YAAY,WAAW;AAAA,EAAA;AAMnC,QAAM,YAAY;AAAA,IAChB,CAAC,UAAyB;AACxB,UACE,gBAAgB,YAAY,WAC5B,UAAU,YAAY,MAAM,QAC5B;AACA,sBAAc,IAAI;AAClB,eAAO,OAAO,MAAM;AAClB,sBAAY,IAAI;AACV,gBAAA,oBAAoB,OAAO;AACjC,cAAI,sBAAsB,MAAM;AAC9B,8BAAkB,MAAM;AAAA,UAC1B;AAAA,QAAA,CACD;AACM,eAAA;AAAA,MACT;AACO,aAAA;AAAA,IACT;AAAA,IACA,CAAC,SAAS,QAAQ,WAAW;AAAA,EAAA;AAG/B,QAAM,UAAU;AAAA,IACd,CAAC,YAAwB;AACvB,YAAM,QAAQ;AAEd,UAAI,YAAY;AACP,eAAA;AAAA,MACT;AACI,UAAA,MAAM,WAAW,SAAS,SAAS;AACrC,YAAI,MAAM,UAAU;AAClB,sBAAY,CAAC,UAAU;AAAA,QAAA,OAClB;AACU;AACf,sBAAY,IAAI;AAAA,QAClB;AACO,eAAA;AAAA,MACT;AAEO,aAAA;AAAA,IACT;AAAA,IACA,CAAC,YAAY,YAAY,aAAa,cAAc;AAAA,EAAA;AAGtD,QAAM,eAAe;AAAA,IACnB,CAAC,UAA4B;AACpB,aAAA,iBAAiB,KAAK,MAAM;AACjC,cAAM,kBAAkB;AACxB,cAAM,aAAa,MAAM;AAEvB,YAAA,WAAW,YAAY,SACvB,kBAAkB,eAAe,KACjC,gBAAgB,SAAA,EAAW,WAAW,GACtC;AACO,iBAAA;AAAA,YACL;AAAA,YACA;AAAA,UAAA;AAAA,QAEJ;AAAA,MAAA,CACD;AAAA,IACH;AAAA,IACA,CAAC,MAAM;AAAA,EAAA;AAGT,YAAU,MAAM;AACd,QAAI,YAAY;AACV,UAAA,cAAc,OAAO;AAC3B,UAAM,aAAa;AAAA,MACjB,OAAO,uBAAuB,CAAC,EAAE,kBAAkB;AACjD,YAAI,WAAW;AACb,uBAAa,YAAY,KAAK,MAAM,cAAA,CAAe,CAAC;AAAA,QACtD;AAAA,MAAA,CACD;AAAA,MACD,OAAO;AAAA,QACL;AAAA,QACA,CAAC,GAAG,iBAAiB;AACnB,0BAAgB,UAAU;AACnB,iBAAA;AAAA,QACT;AAAA,QACA;AAAA,MACF;AAAA,MACA,OAAO;AAAA,QACL;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,MACA,OAAO;AAAA,QACL;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,MACA,OAAO;AAAA,QACL;AAAA,QACA,CAAC,UAAU;AACL,cAAA,MAAM,WAAW,SAAS,SAAS;AACrC,kBAAM,GAAG;AAGT,kBAAM,eAAe;AACd,mBAAA;AAAA,UACT;AACO,iBAAA;AAAA,QACT;AAAA,QACA;AAAA,MACF;AAAA,MACA,OAAO;AAAA,QACL;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,MACA,OAAO;AAAA,QACL;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,MACA,OAAO,gBAAgB,mBAAmB,UAAU,oBAAoB;AAAA,MACxE,OAAO;AAAA,QACL;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,IAAA;AAGW,+CAAA,iBAAiB,eAAe;AAE7C,WAAO,MAAM;AACC,kBAAA;AACD;AACE,iDAAA,oBAAoB,eAAe;AAAA,IAAY;AAAA,EAC9D,GACC;AAAA,IACD;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EAAA,CACD;AAED,QAAM,iBAAiB,MAAM;AAC3B,WAAO,OAAO,MAAM;AACZ,YAAA,OAAO,cAAc,OAAO;AAC9B,UAAA,aAAa,IAAI,GAAG;AACtB,aAAK,eAAe,IAAI;AAAA,MAC1B;AAAA,IAAA,CACD;AAAA,EAAA;AAGG,QAAA,cAAc,CAClB,WACA,eACG;AAEH,eAAW,MAAM;AACf,oBAAc,KAAK;AAAA,OAClB,GAAG;AAEN,WAAO,OAAO,MAAM;AACZ,YAAA,OAAO,cAAc,OAAO;AAC9B,UAAA,aAAa,IAAI,GAAG;AACjB,aAAA,kBAAkB,WAAW,UAAU;AAAA,MAC9C;AAAA,IAAA,CACD;AAAA,EAAA;AAGH,QAAM,gBAAgB,MAAM;AAC1B,kBAAc,IAAI;AAAA,EAAA;AAGpB,QAAM,YAAY,cAAc,iBAAiB,SAAS,KAAK,CAAC;AAC1D,QAAA,aAAa,cAAc,eAAe;AAChD,SACG,oBAAA,UAAA,EAAS,UAAU,MAClB,UACE,qBAAA,UAAA,EAAA,UAAA;AAAA,IAAA,oBAAC,OAAI,EAAA,WACF,UACC,cAAA,oBAAC,cAAY,CAAA,IAEb;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,WACE,YACI,WAAW,iBAAiB,SAAS,IAAI,cAAc,EAAE,KACzD;AAAA,QAEN;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA,SAAS,MAAM,eAAe,IAAI;AAAA,MAAA;AAAA,IAAA,GAGxC;AAAA,IAEC,eACC,oBAAC,OAAI,EAAA,WAAU,2BACb,UAAA;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,eAAe;AAAA,QACf,cAAc;AAAA,UACZ;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,QACF;AAAA,QAEA,UAAA;AAAA,UAAA,oBAAC,iBAAgB,EAAA;AAAA,UAEjB;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,iBACE;AAAA,gBAAC;AAAA,gBAAA;AAAA,kBACC,oBAAiB;AAAA,kBACjB,aAAa,MAAO,oBAAA,QAAA,EAAK,UAAkB,qBAAA,CAAA;AAAA,kBAC3C,WAAU;AAAA,gBAAA;AAAA,cACZ;AAAA,cAEF,eAAe;AAAA,YAAA;AAAA,UACjB;AAAA,UAEA,oBAAC,kBAAe,UAAU,CAAC,MAAM,QAAQ,IAAI,GAAG,GAAG;AAAA,8BAClD,eAAc,EAAA;AAAA,UACd,oBAAA,oBAAA,EAAmB,WAAW,cAAc,UAAW,CAAA;AAAA,QAAA;AAAA,MAAA;AAAA,IAAA,GAE5D;AAAA,IAED,aAAa,iBAAiB,SAAS,KAAK,aAC3C;AAAA,MAAC;AAAA,MAAA;AAAA,QACC;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA,iBAAiB,CAAC,eAAe;AAAA,MAAA;AAAA,IACnC;AAAA,EAAA,EAEJ,CAAA,EACF,CAAA;AAEJ;"}
1
+ {"version":3,"file":"index-113e3eb2.js","sources":["../src/components/ImageView/ImageResizer.tsx","../src/components/ImageView/index.tsx"],"sourcesContent":["/**\r\n * Copyright (c) Meta Platforms, Inc. and affiliates.\r\n *\r\n * This source code is licensed under the MIT license found in the\r\n * LICENSE file in the root directory of this source tree.\r\n *\r\n */\r\n\r\nimport \"./image-caption-styles.css\";\r\n\r\nimport { calculateZoomLevel } from \"@lexical/utils\";\r\nimport type { LexicalEditor } from \"lexical\";\r\nimport * as React from \"react\";\r\nimport { useRef } from \"react\";\r\n\r\nfunction clamp(value: number, min: number, max: number) {\r\n return Math.min(Math.max(value, min), max);\r\n}\r\n\r\nconst Direction = {\r\n east: 1 << 0,\r\n north: 1 << 3,\r\n south: 1 << 1,\r\n west: 1 << 2,\r\n};\r\n\r\nexport default function ImageResizer({\r\n onResizeStart,\r\n onResizeEnd,\r\n buttonRef,\r\n imageRef,\r\n maxWidth,\r\n editor,\r\n showCaption,\r\n setShowCaption,\r\n captionsEnabled,\r\n}: {\r\n editor: LexicalEditor;\r\n buttonRef: { current: null | HTMLButtonElement };\r\n imageRef: { current: null | HTMLElement };\r\n maxWidth?: number;\r\n onResizeEnd: (width: \"inherit\" | number, height: \"inherit\" | number) => void;\r\n onResizeStart: () => void;\r\n setShowCaption: (show: boolean) => void;\r\n showCaption: boolean;\r\n captionsEnabled: boolean;\r\n}): JSX.Element {\r\n const controlWrapperRef = useRef<HTMLDivElement>(null);\r\n const userSelect = useRef({\r\n priority: \"\",\r\n value: \"default\",\r\n });\r\n const positioningRef = useRef<{\r\n currentHeight: \"inherit\" | number;\r\n currentWidth: \"inherit\" | number;\r\n direction: number;\r\n isResizing: boolean;\r\n ratio: number;\r\n startHeight: number;\r\n startWidth: number;\r\n startX: number;\r\n startY: number;\r\n }>({\r\n currentHeight: 0,\r\n currentWidth: 0,\r\n direction: 0,\r\n isResizing: false,\r\n ratio: 0,\r\n startHeight: 0,\r\n startWidth: 0,\r\n startX: 0,\r\n startY: 0,\r\n });\r\n const editorRootElement = editor.getRootElement();\r\n\r\n // Allow enlarging up to the editor container width (ignore any fixed maxWidth cap)\r\n const maxWidthContainer =\r\n editorRootElement !== null\r\n ? editorRootElement.getBoundingClientRect().width - 20\r\n : 100;\r\n const maxHeightContainer =\r\n editorRootElement !== null\r\n ? editorRootElement.getBoundingClientRect().height - 20\r\n : 100;\r\n\r\n const minWidth = 100;\r\n const minHeight = 100;\r\n\r\n /**\r\n * Sets the cursor style to indicate the resizing direction.\r\n * This function updates the cursor for the editor and document body\r\n * based on the resizing direction.\r\n */\r\n const setStartCursor = (direction: number) => {\r\n // Determine if the resizing is happening horizontally (east or west)\r\n const ew = direction === Direction.east || direction === Direction.west;\r\n // Determine if the resizing is happening vertically (north or south)\r\n const ns = direction === Direction.north || direction === Direction.south;\r\n // Determine if the resizing is diagonal (north-west, south-east, etc.)\r\n const nwse =\r\n (direction & Direction.north && direction & Direction.west) ||\r\n (direction & Direction.south && direction & Direction.east);\r\n\r\n // Set the appropriate cursor style based on the detected direction\r\n const cursorDir = ew ? \"ew\" : ns ? \"ns\" : nwse ? \"nwse\" : \"nesw\";\r\n\r\n // Apply the cursor style to the editor root element if it exists\r\n if (editorRootElement !== null) {\r\n editorRootElement.style.setProperty(\r\n \"cursor\",\r\n `${cursorDir}-resize`,\r\n \"important\"\r\n );\r\n }\r\n\r\n // Apply the cursor style to the document body\r\n if (document.body !== null) {\r\n document.body.style.setProperty(\r\n \"cursor\",\r\n `${cursorDir}-resize`,\r\n \"important\"\r\n );\r\n\r\n // Store the current user selection settings before modifying them\r\n userSelect.current.value = document.body.style.getPropertyValue(\r\n \"-webkit-user-select\"\r\n );\r\n userSelect.current.priority = document.body.style.getPropertyPriority(\r\n \"-webkit-user-select\"\r\n );\r\n\r\n // Disable text selection during resizing to prevent unwanted text selection\r\n document.body.style.setProperty(\r\n \"-webkit-user-select\",\r\n `none`,\r\n \"important\"\r\n );\r\n }\r\n };\r\n\r\n /**\r\n * Resets the cursor style when resizing ends.\r\n */\r\n\r\n const setEndCursor = () => {\r\n if (editorRootElement !== null) {\r\n editorRootElement.style.setProperty(\"cursor\", \"text\");\r\n }\r\n if (document.body !== null) {\r\n document.body.style.setProperty(\"cursor\", \"default\");\r\n document.body.style.setProperty(\r\n \"-webkit-user-select\",\r\n userSelect.current.value,\r\n userSelect.current.priority\r\n );\r\n }\r\n };\r\n\r\n /**\r\n * Handles pointer down event when resizing starts.\r\n */\r\n const handlePointerDown = (\r\n event: React.PointerEvent<HTMLDivElement>,\r\n direction: number\r\n ) => {\r\n if (!editor.isEditable()) {\r\n return;\r\n }\r\n const image = imageRef.current;\r\n const controlWrapper = controlWrapperRef.current;\r\n\r\n // Ensure both the image and control wrapper exist before proceeding\r\n if (image !== null && controlWrapper !== null) {\r\n event.preventDefault();\r\n\r\n // Get the image's current width and height from its bounding rectangle\r\n const { width, height } = image.getBoundingClientRect();\r\n // Calculate the zoom level to adjust calculations accordingly\r\n const zoom = calculateZoomLevel(image);\r\n // Retrieve the positioning reference object to store resize state\r\n const positioning = positioningRef.current;\r\n\r\n // Store the initial dimensions of the image\r\n positioning.startWidth = width;\r\n positioning.startHeight = height;\r\n // Store the aspect ratio to maintain proportions when resizing\r\n positioning.ratio = width / height;\r\n // Set the current width and height values for tracking changes\r\n positioning.currentWidth = width;\r\n positioning.currentHeight = height;\r\n // Store the initial pointer position, adjusted for zoom level\r\n positioning.startX = event.clientX / zoom;\r\n positioning.startY = event.clientY / zoom;\r\n // Mark the resizing state as active\r\n positioning.isResizing = true;\r\n // Store the resize direction (north, south, east, west, or combinations)\r\n positioning.direction = direction;\r\n\r\n // Set the cursor style to indicate resizing in the correct direction\r\n setStartCursor(direction);\r\n onResizeStart();\r\n\r\n controlWrapper.classList.add(\"image-control-wrapper--resizing\");\r\n image.style.height = `${height}px`;\r\n image.style.width = `${width}px`;\r\n document.addEventListener(\"pointermove\", handlePointerMove);\r\n document.addEventListener(\"pointerup\", handlePointerUp);\r\n }\r\n };\r\n\r\n /**\r\n * Handles pointer move event when resizing the image dynamically.\r\n */\r\n const handlePointerMove = (event: PointerEvent) => {\r\n const image = imageRef.current;\r\n const positioning = positioningRef.current;\r\n\r\n // Check if the resize direction includes horizontal movement (east or west)\r\n const isHorizontal =\r\n positioning.direction & (Direction.east | Direction.west);\r\n // Check if the resize direction includes vertical movement (north or south)\r\n const isVertical =\r\n positioning.direction & (Direction.south | Direction.north);\r\n\r\n if (image !== null && positioning.isResizing) {\r\n // Get the zoom level of the image to ensure accurate calculations\r\n const zoom = calculateZoomLevel(image);\r\n\r\n if (isHorizontal && isVertical) {\r\n // Calculate the difference in X position relative to the starting point\r\n let diff = Math.floor(positioning.startX - event.clientX / zoom);\r\n // Reverse the difference if resizing from the east to ensure correct calculations\r\n diff = positioning.direction & Direction.east ? -diff : diff;\r\n\r\n // Calculate the new width, ensuring it stays within allowed min and max limits\r\n const width = clamp(\r\n positioning.startWidth + diff,\r\n minWidth,\r\n maxWidthContainer\r\n );\r\n // Maintain the aspect ratio by adjusting height proportionally\r\n const height = width / positioning.ratio;\r\n // Apply the new width and height to the image\r\n image.style.width = `${width}px`;\r\n image.style.height = `${height}px`;\r\n // Update stored dimensions for ongoing tracking\r\n positioning.currentHeight = height;\r\n positioning.currentWidth = width;\r\n } else if (isVertical) {\r\n // Calculate the difference in Y position relative to the starting point\r\n let diff = Math.floor(positioning.startY - event.clientY / zoom);\r\n // Reverse the difference if resizing from the south to maintain correct direction\r\n diff = positioning.direction & Direction.south ? -diff : diff;\r\n\r\n // Calculate the new height, ensuring it stays within allowed min and max limits\r\n const height = clamp(\r\n positioning.startHeight + diff,\r\n minHeight,\r\n maxHeightContainer\r\n );\r\n\r\n // Apply the new height to the image\r\n image.style.height = `${height}px`;\r\n // Update stored height for ongoing tracking\r\n positioning.currentHeight = height;\r\n } else {\r\n // Calculate the difference in X position relative to the starting point\r\n let diff = Math.floor(positioning.startX - event.clientX / zoom);\r\n // Reverse the difference if resizing from the east to maintain correct direction\r\n diff = positioning.direction & Direction.east ? -diff : diff;\r\n\r\n // Calculate the new width, ensuring it stays within allowed min and max limits\r\n const width = clamp(\r\n positioning.startWidth + diff,\r\n minWidth,\r\n maxWidthContainer\r\n );\r\n\r\n // Apply the new width to the image\r\n image.style.width = `${width}px`;\r\n // Update stored width for ongoing tracking\r\n positioning.currentWidth = width;\r\n }\r\n }\r\n };\r\n\r\n /**\r\n * Handles the pointer up event when resizing ends.\r\n */\r\n const handlePointerUp = () => {\r\n const image = imageRef.current;\r\n const positioning = positioningRef.current;\r\n const controlWrapper = controlWrapperRef.current;\r\n\r\n // Ensure the image, control wrapper exist, and resizing is active before proceeding\r\n if (image !== null && controlWrapper !== null && positioning.isResizing) {\r\n // Capture the final width and height of the resized image\r\n const width = positioning.currentWidth;\r\n const height = positioning.currentHeight;\r\n\r\n // Reset positioning values after resizing is complete\r\n positioning.startWidth = 0;\r\n positioning.startHeight = 0;\r\n positioning.ratio = 0;\r\n positioning.startX = 0;\r\n positioning.startY = 0;\r\n positioning.currentWidth = 0;\r\n positioning.currentHeight = 0;\r\n positioning.isResizing = false; // Mark resizing as finished\r\n\r\n // Remove the resizing class from the control wrapper\r\n controlWrapper.classList.remove(\"image-control-wrapper--resizing\");\r\n\r\n // Restore default cursor appearance\r\n setEndCursor();\r\n // Trigger the resize end callback with the final dimensions\r\n onResizeEnd(width, height);\r\n\r\n // Remove event listeners for pointer movement and release to stop tracking\r\n document.removeEventListener(\"pointermove\", handlePointerMove);\r\n document.removeEventListener(\"pointerup\", handlePointerUp);\r\n }\r\n };\r\n\r\n return (\r\n <div ref={controlWrapperRef}>\r\n {!showCaption && captionsEnabled && (\r\n <button\r\n className=\"image-caption-button\"\r\n ref={buttonRef}\r\n onClick={() => {\r\n setShowCaption(!showCaption);\r\n }}\r\n >\r\n Add Caption\r\n </button>\r\n )}\r\n <div\r\n className=\"image-resizer image-resizer-n\"\r\n onPointerDown={(event) => {\r\n handlePointerDown(event, Direction.north);\r\n }}\r\n />\r\n <div\r\n className=\"image-resizer image-resizer-ne\"\r\n onPointerDown={(event) => {\r\n handlePointerDown(event, Direction.north | Direction.east);\r\n }}\r\n />\r\n <div\r\n className=\"image-resizer image-resizer-e\"\r\n onPointerDown={(event) => {\r\n handlePointerDown(event, Direction.east);\r\n }}\r\n />\r\n <div\r\n className=\"image-resizer image-resizer-se\"\r\n onPointerDown={(event) => {\r\n handlePointerDown(event, Direction.south | Direction.east);\r\n }}\r\n />\r\n <div\r\n className=\"image-resizer image-resizer-s\"\r\n onPointerDown={(event) => {\r\n handlePointerDown(event, Direction.south);\r\n }}\r\n />\r\n <div\r\n className=\"image-resizer image-resizer-sw\"\r\n onPointerDown={(event) => {\r\n handlePointerDown(event, Direction.south | Direction.west);\r\n }}\r\n />\r\n <div\r\n className=\"image-resizer image-resizer-w\"\r\n onPointerDown={(event) => {\r\n handlePointerDown(event, Direction.west);\r\n }}\r\n />\r\n <div\r\n className=\"image-resizer image-resizer-nw\"\r\n onPointerDown={(event) => {\r\n handlePointerDown(event, Direction.north | Direction.west);\r\n }}\r\n />\r\n </div>\r\n );\r\n}\r\n","/**\r\n * Copyright (c) Meta Platforms, Inc. and affiliates.\r\n *\r\n * This source code is licensed under the MIT license found in the\r\n * LICENSE file in the root directory of this source tree.\r\n *\r\n */\r\n\r\nimport \"./image-caption-styles.css\";\r\n\r\nimport { CodeNode } from \"@lexical/code\";\r\nimport { LinkNode } from \"@lexical/link\";\r\nimport { AutoFocusPlugin } from \"@lexical/react/LexicalAutoFocusPlugin\";\r\nimport { useCollaborationContext } from \"@lexical/react/LexicalCollaborationContext\";\r\nimport { useLexicalComposerContext } from \"@lexical/react/LexicalComposerContext\";\r\nimport { ContentEditable } from \"@lexical/react/LexicalContentEditable\";\r\nimport { LexicalErrorBoundary } from \"@lexical/react/LexicalErrorBoundary\";\r\nimport { HistoryPlugin } from \"@lexical/react/LexicalHistoryPlugin\";\r\nimport { LexicalNestedComposer } from \"@lexical/react/LexicalNestedComposer\";\r\nimport { OnChangePlugin } from \"@lexical/react/LexicalOnChangePlugin\";\r\n// import './ImageNode.css';\r\nimport { RichTextPlugin } from \"@lexical/react/LexicalRichTextPlugin\";\r\nimport { useLexicalEditable } from \"@lexical/react/useLexicalEditable\";\r\nimport { useLexicalNodeSelection } from \"@lexical/react/useLexicalNodeSelection\";\r\nimport { mergeRegister } from \"@lexical/utils\";\r\nimport type {\r\n BaseSelection,\r\n LexicalCommand,\r\n LexicalEditor,\r\n NodeKey,\r\n} from \"lexical\";\r\nimport {\r\n $getNodeByKey,\r\n $getSelection,\r\n $isNodeSelection,\r\n $isRangeSelection,\r\n $setSelection,\r\n CLICK_COMMAND,\r\n COMMAND_PRIORITY_LOW,\r\n createCommand,\r\n DRAGSTART_COMMAND,\r\n KEY_BACKSPACE_COMMAND,\r\n KEY_DELETE_COMMAND,\r\n KEY_ENTER_COMMAND,\r\n KEY_ESCAPE_COMMAND,\r\n LineBreakNode,\r\n ParagraphNode,\r\n RootNode,\r\n SELECTION_CHANGE_COMMAND,\r\n TextNode,\r\n} from \"lexical\";\r\nimport * as React from \"react\";\r\nimport { Suspense, useCallback, useEffect, useRef, useState } from \"react\";\r\n// import brokenImage from '../images/image-broken.svg';\r\nimport { initialConfig } from \"src/constants\";\r\nimport { $isImageNode } from \"src/nodes/ImageNode\";\r\nimport LocalStoragePlugin from \"src/plugins/LocalStoragePlugin\";\r\n\r\nimport ImageResizer from \"./ImageResizer\";\r\n\r\nconst imageCache = new Set();\r\n\r\nexport const RIGHT_CLICK_IMAGE_COMMAND: LexicalCommand<MouseEvent> =\r\n createCommand(\"RIGHT_CLICK_IMAGE_COMMAND\");\r\n\r\nfunction useSuspenseImage(src: string) {\r\n if (!imageCache.has(src)) {\r\n throw new Promise((resolve) => {\r\n const img = new Image();\r\n img.src = src;\r\n img.onload = () => {\r\n imageCache.add(src);\r\n resolve(null);\r\n };\r\n img.onerror = () => {\r\n imageCache.add(src);\r\n };\r\n });\r\n }\r\n}\r\n\r\nfunction LazyImage({\r\n altText,\r\n className,\r\n imageRef,\r\n src,\r\n width,\r\n height,\r\n maxWidth,\r\n onError,\r\n}: {\r\n altText: string;\r\n className: string | null;\r\n height: \"inherit\" | number;\r\n imageRef: { current: null | HTMLImageElement };\r\n maxWidth: number;\r\n src: string;\r\n width: \"inherit\" | number;\r\n onError: () => void;\r\n}): JSX.Element {\r\n useSuspenseImage(src);\r\n const hasExplicitSize = typeof width === 'number' || typeof height === 'number';\r\n const computedWidth = typeof width === 'number' ? width : 'auto';\r\n const computedHeight = typeof height === 'number' ? height : 'auto';\r\n const DEFAULT_PIXEL_WIDTH = 429; // px\r\n const DEFAULT_PIXEL_HEIGHT = 365.375; // px\r\n\r\n return (\r\n <img\r\n className={className || undefined}\r\n src={src}\r\n alt={altText}\r\n ref={imageRef}\r\n style={\r\n hasExplicitSize\r\n ? {\r\n // User/resizer has set a numeric size; respect it but don't exceed container\r\n width: computedWidth,\r\n height: computedHeight,\r\n maxWidth: '100%',\r\n }\r\n : {\r\n // Default rendering: requested smaller size\r\n width: `${DEFAULT_PIXEL_WIDTH}px`,\r\n height: `${DEFAULT_PIXEL_HEIGHT}px`,\r\n maxWidth: '100%',\r\n }\r\n }\r\n onError={onError}\r\n draggable=\"false\"\r\n />\r\n );\r\n}\r\n\r\n// if the image is broken ; we are showing this component\r\nfunction BrokenImage(): JSX.Element {\r\n return (\r\n <img\r\n src={\"\"} //TODO: NEED TO ADD BROKEN IMAGE\r\n style={{\r\n height: 200,\r\n opacity: 0.2,\r\n width: 200,\r\n }}\r\n draggable=\"false\"\r\n />\r\n );\r\n}\r\n\r\nexport default function ImageComponent({\r\n src,\r\n altText,\r\n nodeKey,\r\n width,\r\n height,\r\n maxWidth,\r\n resizable,\r\n showCaption,\r\n caption,\r\n captionsEnabled,\r\n}: {\r\n altText: string;\r\n caption: LexicalEditor;\r\n height: \"inherit\" | number;\r\n maxWidth: number;\r\n nodeKey: NodeKey;\r\n resizable: boolean;\r\n showCaption: boolean;\r\n src: string;\r\n width: \"inherit\" | number;\r\n captionsEnabled: boolean;\r\n}): JSX.Element {\r\n const imageRef = useRef<null | HTMLImageElement>(null);\r\n const buttonRef = useRef<HTMLButtonElement | null>(null);\r\n const [isSelected, setSelected, clearSelection] =\r\n useLexicalNodeSelection(nodeKey);\r\n const [isResizing, setIsResizing] = useState<boolean>(false);\r\n const { isCollabActive } = useCollaborationContext();\r\n const [editor] = useLexicalComposerContext();\r\n const [selection, setSelection] = useState<BaseSelection | null>(null);\r\n const activeEditorRef = useRef<LexicalEditor | null>(null);\r\n const [isLoadError, setIsLoadError] = useState<boolean>(false);\r\n const isEditable = useLexicalEditable();\r\n\r\n /**\r\n * Deletes the image node when the delete key is pressed.\r\n */\r\n const $onDelete = useCallback(\r\n (payload: KeyboardEvent) => {\r\n const deleteSelection = $getSelection();\r\n if (isSelected && $isNodeSelection(deleteSelection)) {\r\n const event: KeyboardEvent = payload;\r\n event.preventDefault();\r\n editor.update(() => {\r\n deleteSelection.getNodes().forEach((node) => {\r\n if ($isImageNode(node)) {\r\n node.remove();\r\n }\r\n });\r\n });\r\n }\r\n return false;\r\n },\r\n [editor, isSelected]\r\n );\r\n\r\n /**\r\n * Handles enter key to move focus into the caption editor.\r\n */\r\n const $onEnter = useCallback(\r\n (event: KeyboardEvent) => {\r\n const latestSelection = $getSelection();\r\n const buttonElem = buttonRef.current;\r\n if (\r\n isSelected &&\r\n $isNodeSelection(latestSelection) &&\r\n latestSelection.getNodes().length === 1\r\n ) {\r\n if (showCaption) {\r\n // Move focus into nested editor\r\n $setSelection(null);\r\n event.preventDefault();\r\n caption.focus();\r\n return true;\r\n } else if (\r\n buttonElem !== null &&\r\n buttonElem !== document.activeElement\r\n ) {\r\n event.preventDefault();\r\n buttonElem.focus();\r\n return true;\r\n }\r\n }\r\n return false;\r\n },\r\n [caption, isSelected, showCaption]\r\n );\r\n\r\n /**\r\n * Handles escape key to reset selection.\r\n */\r\n const $onEscape = useCallback(\r\n (event: KeyboardEvent) => {\r\n if (\r\n activeEditorRef.current === caption ||\r\n buttonRef.current === event.target\r\n ) {\r\n $setSelection(null);\r\n editor.update(() => {\r\n setSelected(true);\r\n const parentRootElement = editor.getRootElement();\r\n if (parentRootElement !== null) {\r\n parentRootElement.focus();\r\n }\r\n });\r\n return true;\r\n }\r\n return false;\r\n },\r\n [caption, editor, setSelected]\r\n );\r\n\r\n const onClick = useCallback(\r\n (payload: MouseEvent) => {\r\n const event = payload;\r\n\r\n if (isResizing) {\r\n return true;\r\n }\r\n if (event.target === imageRef.current) {\r\n if (event.shiftKey) {\r\n setSelected(!isSelected);\r\n } else {\r\n clearSelection();\r\n setSelected(true);\r\n }\r\n return true;\r\n }\r\n\r\n return false;\r\n },\r\n [isResizing, isSelected, setSelected, clearSelection]\r\n );\r\n\r\n const onRightClick = useCallback(\r\n (event: MouseEvent): void => {\r\n editor.getEditorState().read(() => {\r\n const latestSelection = $getSelection();\r\n const domElement = event.target as HTMLElement;\r\n if (\r\n domElement.tagName === \"IMG\" &&\r\n $isRangeSelection(latestSelection) &&\r\n latestSelection.getNodes().length === 1\r\n ) {\r\n editor.dispatchCommand(\r\n RIGHT_CLICK_IMAGE_COMMAND,\r\n event as MouseEvent\r\n );\r\n }\r\n });\r\n },\r\n [editor]\r\n );\r\n\r\n useEffect(() => {\r\n let isMounted = true;\r\n const rootElement = editor.getRootElement();\r\n const unregister = mergeRegister(\r\n editor.registerUpdateListener(({ editorState }) => {\r\n if (isMounted) {\r\n setSelection(editorState.read(() => $getSelection()));\r\n }\r\n }),\r\n editor.registerCommand(\r\n SELECTION_CHANGE_COMMAND,\r\n (_, activeEditor) => {\r\n activeEditorRef.current = activeEditor;\r\n return false;\r\n },\r\n COMMAND_PRIORITY_LOW\r\n ),\r\n editor.registerCommand<MouseEvent>(\r\n CLICK_COMMAND,\r\n onClick,\r\n COMMAND_PRIORITY_LOW\r\n ),\r\n editor.registerCommand<MouseEvent>(\r\n RIGHT_CLICK_IMAGE_COMMAND,\r\n onClick,\r\n COMMAND_PRIORITY_LOW\r\n ),\r\n editor.registerCommand(\r\n DRAGSTART_COMMAND,\r\n (event) => {\r\n if (event.target === imageRef.current) {\r\n alert(\"s\");\r\n // TODO This is just a temporary workaround for FF to behave like other browsers.\r\n // Ideally, this handles drag & drop too (and all browsers).\r\n event.preventDefault();\r\n return true;\r\n }\r\n return false;\r\n },\r\n COMMAND_PRIORITY_LOW\r\n ),\r\n editor.registerCommand(\r\n KEY_DELETE_COMMAND,\r\n $onDelete,\r\n COMMAND_PRIORITY_LOW\r\n ),\r\n editor.registerCommand(\r\n KEY_BACKSPACE_COMMAND,\r\n $onDelete,\r\n COMMAND_PRIORITY_LOW\r\n ),\r\n editor.registerCommand(KEY_ENTER_COMMAND, $onEnter, COMMAND_PRIORITY_LOW),\r\n editor.registerCommand(\r\n KEY_ESCAPE_COMMAND,\r\n $onEscape,\r\n COMMAND_PRIORITY_LOW\r\n )\r\n );\r\n\r\n rootElement?.addEventListener(\"contextmenu\", onRightClick);\r\n\r\n return () => {\r\n isMounted = false;\r\n unregister();\r\n rootElement?.removeEventListener(\"contextmenu\", onRightClick);\r\n };\r\n }, [\r\n clearSelection,\r\n editor,\r\n isResizing,\r\n isSelected,\r\n nodeKey,\r\n $onDelete,\r\n $onEnter,\r\n $onEscape,\r\n onClick,\r\n onRightClick,\r\n setSelected,\r\n ]);\r\n\r\n const setShowCaption = () => {\r\n editor.update(() => {\r\n const node = $getNodeByKey(nodeKey);\r\n if ($isImageNode(node)) {\r\n node.setShowCaption(true);\r\n }\r\n });\r\n };\r\n\r\n const onResizeEnd = (\r\n nextWidth: \"inherit\" | number,\r\n nextHeight: \"inherit\" | number\r\n ) => {\r\n // Delay hiding the resize bars for click case\r\n setTimeout(() => {\r\n setIsResizing(false);\r\n }, 200);\r\n\r\n editor.update(() => {\r\n const node = $getNodeByKey(nodeKey);\r\n if ($isImageNode(node)) {\r\n node.setWidthAndHeight(nextWidth, nextHeight);\r\n }\r\n });\r\n };\r\n\r\n const onResizeStart = () => {\r\n setIsResizing(true);\r\n };\r\n\r\n const draggable = isSelected && $isNodeSelection(selection) && !isResizing;\r\n const isFocused = (isSelected || isResizing) && isEditable;\r\n return (\r\n <Suspense fallback={null}>\r\n <>\r\n <div draggable={draggable}>\r\n {isLoadError ? (\r\n <BrokenImage />\r\n ) : (\r\n <LazyImage\r\n className={\r\n isFocused\r\n ? `focused ${$isNodeSelection(selection) ? \"draggable\" : \"\"}`\r\n : null\r\n }\r\n src={src}\r\n altText={altText}\r\n imageRef={imageRef}\r\n width={width}\r\n height={height}\r\n maxWidth={maxWidth}\r\n onError={() => setIsLoadError(true)}\r\n />\r\n )}\r\n </div>\r\n\r\n {showCaption && (\r\n <div className=\"image-caption-container\">\r\n <LexicalNestedComposer\r\n initialEditor={caption}\r\n initialNodes={[\r\n RootNode,\r\n TextNode,\r\n LineBreakNode,\r\n ParagraphNode,\r\n LinkNode,\r\n CodeNode,\r\n ]}\r\n >\r\n <AutoFocusPlugin />\r\n\r\n <RichTextPlugin\r\n contentEditable={\r\n <ContentEditable\r\n aria-placeholder=\"Enter a caption...\"\r\n placeholder={() => <span>Enter a caption...</span>}\r\n className=\"ImageNode__contentEditable\"\r\n />\r\n }\r\n ErrorBoundary={LexicalErrorBoundary}\r\n />\r\n\r\n <OnChangePlugin onChange={(e) => console.log(\"e\")} />\r\n <HistoryPlugin />\r\n <LocalStoragePlugin namespace={initialConfig.namespace} />\r\n </LexicalNestedComposer>\r\n </div>\r\n )}\r\n {resizable && $isNodeSelection(selection) && isFocused && (\r\n <ImageResizer\r\n showCaption={showCaption}\r\n setShowCaption={setShowCaption}\r\n editor={editor}\r\n buttonRef={buttonRef}\r\n imageRef={imageRef}\r\n maxWidth={maxWidth}\r\n onResizeStart={onResizeStart}\r\n onResizeEnd={onResizeEnd}\r\n captionsEnabled={!isLoadError && captionsEnabled}\r\n />\r\n )}\r\n </>\r\n </Suspense>\r\n );\r\n}\r\n"],"names":[],"mappings":"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"}
@@ -2699,6 +2699,17 @@ const Highlighter = createLucideIcon("Highlighter", [
2699
2699
  ["path", { d: "m9 11-6 6v3h9l3-3", key: "1a3l36" }],
2700
2700
  ["path", { d: "m22 12-4.6 4.6a2 2 0 0 1-2.8 0l-5.2-5.2a2 2 0 0 1 0-2.8L14 4", key: "14a9rk" }]
2701
2701
  ]);
2702
+ /**
2703
+ * @license lucide-react v0.344.0 - ISC
2704
+ *
2705
+ * This source code is licensed under the ISC license.
2706
+ * See the LICENSE file in the root directory of this source tree.
2707
+ */
2708
+ const Image$2 = createLucideIcon("Image", [
2709
+ ["rect", { width: "18", height: "18", x: "3", y: "3", rx: "2", ry: "2", key: "1m3agn" }],
2710
+ ["circle", { cx: "9", cy: "9", r: "2", key: "af1f0g" }],
2711
+ ["path", { d: "m21 15-3.086-3.086a2 2 0 0 0-2.828 0L6 21", key: "1xmnt7" }]
2712
+ ]);
2702
2713
  /**
2703
2714
  * @license lucide-react v0.344.0 - ISC
2704
2715
  *
@@ -2727,6 +2738,47 @@ const Lightbulb = createLucideIcon("Lightbulb", [
2727
2738
  ["path", { d: "M9 18h6", key: "x1upvd" }],
2728
2739
  ["path", { d: "M10 22h4", key: "ceow96" }]
2729
2740
  ]);
2741
+ /**
2742
+ * @license lucide-react v0.344.0 - ISC
2743
+ *
2744
+ * This source code is licensed under the ISC license.
2745
+ * See the LICENSE file in the root directory of this source tree.
2746
+ */
2747
+ const ListChecks = createLucideIcon("ListChecks", [
2748
+ ["path", { d: "m3 17 2 2 4-4", key: "1jhpwq" }],
2749
+ ["path", { d: "m3 7 2 2 4-4", key: "1obspn" }],
2750
+ ["path", { d: "M13 6h8", key: "15sg57" }],
2751
+ ["path", { d: "M13 12h8", key: "h98zly" }],
2752
+ ["path", { d: "M13 18h8", key: "oe0vm4" }]
2753
+ ]);
2754
+ /**
2755
+ * @license lucide-react v0.344.0 - ISC
2756
+ *
2757
+ * This source code is licensed under the ISC license.
2758
+ * See the LICENSE file in the root directory of this source tree.
2759
+ */
2760
+ const ListOrdered = createLucideIcon("ListOrdered", [
2761
+ ["line", { x1: "10", x2: "21", y1: "6", y2: "6", key: "76qw6h" }],
2762
+ ["line", { x1: "10", x2: "21", y1: "12", y2: "12", key: "16nom4" }],
2763
+ ["line", { x1: "10", x2: "21", y1: "18", y2: "18", key: "u3jurt" }],
2764
+ ["path", { d: "M4 6h1v4", key: "cnovpq" }],
2765
+ ["path", { d: "M4 10h2", key: "16xx2s" }],
2766
+ ["path", { d: "M6 18H4c0-1 2-2 2-3s-1-1.5-2-1", key: "m9a95d" }]
2767
+ ]);
2768
+ /**
2769
+ * @license lucide-react v0.344.0 - ISC
2770
+ *
2771
+ * This source code is licensed under the ISC license.
2772
+ * See the LICENSE file in the root directory of this source tree.
2773
+ */
2774
+ const List$1 = createLucideIcon("List", [
2775
+ ["line", { x1: "8", x2: "21", y1: "6", y2: "6", key: "7ey8pc" }],
2776
+ ["line", { x1: "8", x2: "21", y1: "12", y2: "12", key: "rjfblc" }],
2777
+ ["line", { x1: "8", x2: "21", y1: "18", y2: "18", key: "c3b1m8" }],
2778
+ ["line", { x1: "3", x2: "3.01", y1: "6", y2: "6", key: "1g7gq3" }],
2779
+ ["line", { x1: "3", x2: "3.01", y1: "12", y2: "12", key: "1pjlvk" }],
2780
+ ["line", { x1: "3", x2: "3.01", y1: "18", y2: "18", key: "28t2mc" }]
2781
+ ]);
2730
2782
  /**
2731
2783
  * @license lucide-react v0.344.0 - ISC
2732
2784
  *
@@ -2937,6 +2989,16 @@ const Type = createLucideIcon("Type", [
2937
2989
  ["line", { x1: "9", x2: "15", y1: "20", y2: "20", key: "swin9y" }],
2938
2990
  ["line", { x1: "12", x2: "12", y1: "4", y2: "20", key: "1tx1rr" }]
2939
2991
  ]);
2992
+ /**
2993
+ * @license lucide-react v0.344.0 - ISC
2994
+ *
2995
+ * This source code is licensed under the ISC license.
2996
+ * See the LICENSE file in the root directory of this source tree.
2997
+ */
2998
+ const Video = createLucideIcon("Video", [
2999
+ ["path", { d: "m22 8-6 4 6 4V8Z", key: "50v9me" }],
3000
+ ["rect", { width: "14", height: "12", x: "2", y: "6", rx: "2", ry: "2", key: "1rqjg6" }]
3001
+ ]);
2940
3002
  /**
2941
3003
  * @license lucide-react v0.344.0 - ISC
2942
3004
  *
@@ -12655,10 +12717,10 @@ const PDF_CONFIG = {
12655
12717
  };
12656
12718
  const loadHtml2Pdf = async () => {
12657
12719
  try {
12658
- const mod = await import("./html2pdf.bundle.min-bc7d5952.js").then((n) => n.h);
12720
+ const mod = await import("./html2pdf.bundle.min-d9d93bc1.js").then((n) => n.h);
12659
12721
  return (mod == null ? void 0 : mod.default) || mod;
12660
12722
  } catch {
12661
- const mod2 = await import("./html2pdf.bundle-583538f8.js").then((n) => n.h);
12723
+ const mod2 = await import("./html2pdf.bundle-0fecc54c.js").then((n) => n.h);
12662
12724
  return (mod2 == null ? void 0 : mod2.default) || mod2;
12663
12725
  }
12664
12726
  };
@@ -13865,7 +13927,7 @@ const EmbedComponent = ({ url, displayType, alignment, nodeKey }) => {
13865
13927
  }
13866
13928
  );
13867
13929
  };
13868
- const ImageView = React__default.lazy(() => import("./index-91238d37.js"));
13930
+ const ImageView = React__default.lazy(() => import("./index-113e3eb2.js"));
13869
13931
  function isGoogleDocCheckboxImg(img) {
13870
13932
  return img.parentElement != null && img.parentElement.tagName === "LI" && img.previousSibling === null && img.getAttribute("aria-roledescription") === "checkbox";
13871
13933
  }
@@ -22827,8 +22889,17 @@ const Toolbar = ({
22827
22889
  enableHtmlView
22828
22890
  ]);
22829
22891
  const handleClearEditorContent = () => {
22830
- if (confirm("Are you sure you want to clear out the editor's content?"))
22831
- clearEditorContent();
22892
+ toast.warning("Clear editor content?", {
22893
+ description: "This will remove all content.",
22894
+ action: {
22895
+ label: "OK",
22896
+ onClick: () => {
22897
+ clearEditorContent();
22898
+ toast.success("Editor cleared");
22899
+ }
22900
+ },
22901
+ duration: 8e3
22902
+ });
22832
22903
  };
22833
22904
  const { onFontColorSelect, onBgColorSelect, onHighlightColorSelect } = useColorPicker();
22834
22905
  const [isLinkActive, setIsLinkActive] = useState$1(false);
@@ -24431,6 +24502,10 @@ function AutocompletePlugin({
24431
24502
  while (wordStart > 0 && /[a-zA-Z0-9_']/.test(textContent[wordStart - 1])) {
24432
24503
  wordStart--;
24433
24504
  }
24505
+ if (wordStart > 0 && textContent[wordStart - 1] === "/") {
24506
+ setQueryString(null);
24507
+ return;
24508
+ }
24434
24509
  const currentWord = textContent.slice(wordStart, anchorOffset);
24435
24510
  if (currentWord.length >= minMatchLength) {
24436
24511
  setQueryString(currentWord);
@@ -28528,6 +28603,46 @@ function TableHoverActionsPlugin({
28528
28603
  anchorElem
28529
28604
  ) : null;
28530
28605
  }
28606
+ function getOptionMeta(label) {
28607
+ const lower = label.toLowerCase();
28608
+ if (lower.startsWith("paragraph")) {
28609
+ return { icon: /* @__PURE__ */ jsx(Type, { className: "cteditor-size-4" }), description: "Start a new paragraph", shortcut: "P" };
28610
+ }
28611
+ if (lower.includes("heading 1")) {
28612
+ return { icon: /* @__PURE__ */ jsx(Heading1, { className: "cteditor-size-4" }), description: "Large section title", shortcut: "H1" };
28613
+ }
28614
+ if (lower.includes("heading 2")) {
28615
+ return { icon: /* @__PURE__ */ jsx(Heading2, { className: "cteditor-size-4" }), description: "Section heading", shortcut: "H2" };
28616
+ }
28617
+ if (lower.includes("heading 3")) {
28618
+ return { icon: /* @__PURE__ */ jsx(Heading3, { className: "cteditor-size-4" }), description: "Subsection heading", shortcut: "H3" };
28619
+ }
28620
+ if (lower.includes("bullet")) {
28621
+ return { icon: /* @__PURE__ */ jsx(List$1, { className: "cteditor-size-4" }), description: "Create a bulleted list", shortcut: "•" };
28622
+ }
28623
+ if (lower.includes("numbered")) {
28624
+ return { icon: /* @__PURE__ */ jsx(ListOrdered, { className: "cteditor-size-4" }), description: "Create a numbered list", shortcut: "1." };
28625
+ }
28626
+ if (lower.includes("todo")) {
28627
+ return { icon: /* @__PURE__ */ jsx(ListChecks, { className: "cteditor-size-4" }), description: "Create a checklist", shortcut: "[ ]" };
28628
+ }
28629
+ if (lower.includes("image")) {
28630
+ return { icon: /* @__PURE__ */ jsx(Image$2, { className: "cteditor-size-4" }), description: "Insert an image", shortcut: "Img" };
28631
+ }
28632
+ if (lower.includes("video")) {
28633
+ return { icon: /* @__PURE__ */ jsx(Video, { className: "cteditor-size-4" }), description: "Embed a video", shortcut: "Vid" };
28634
+ }
28635
+ if (lower.includes("align left")) {
28636
+ return { icon: /* @__PURE__ */ jsx(AlignLeft, { className: "cteditor-size-4" }), description: "Align text left" };
28637
+ }
28638
+ if (lower.includes("align center")) {
28639
+ return { icon: /* @__PURE__ */ jsx(AlignCenter, { className: "cteditor-size-4" }), description: "Align text center" };
28640
+ }
28641
+ if (lower.includes("align right")) {
28642
+ return { icon: /* @__PURE__ */ jsx(AlignRight, { className: "cteditor-size-4" }), description: "Align text right" };
28643
+ }
28644
+ return { icon: /* @__PURE__ */ jsx(Type, { className: "cteditor-size-4" }) };
28645
+ }
28531
28646
  class SlashMenuOption extends MenuOption {
28532
28647
  constructor(label, onSelect) {
28533
28648
  super(label);
@@ -28544,22 +28659,26 @@ function SlashMenuItem({
28544
28659
  onMouseEnter,
28545
28660
  option
28546
28661
  }) {
28547
- let className = "item";
28548
- if (isSelected) {
28549
- className += " selected";
28550
- }
28551
- return /* @__PURE__ */ jsx(
28662
+ const meta = getOptionMeta(option.label);
28663
+ return /* @__PURE__ */ jsxs(
28552
28664
  "li",
28553
28665
  {
28554
28666
  tabIndex: -1,
28555
- className,
28667
+ className: (isSelected ? "cteditor-bg-primary/10 cteditor-border-primary/40 cteditor-shadow-md " : "hover:cteditor-bg-accent/50 hover:cteditor-border-primary/30 hover:cteditor-shadow ") + "cteditor-group cteditor-flex cteditor-items-center cteditor-gap-3 cteditor-px-3 cteditor-py-2 cteditor-rounded-xl cteditor-transition-all cteditor-duration-200 cteditor-cursor-pointer cteditor-border cteditor-border-border hover:cteditor-translate-x-[1px]",
28556
28668
  ref: option.setRefElement,
28557
28669
  role: "option",
28558
28670
  "aria-selected": isSelected,
28559
28671
  id: "typeahead-item-" + index2,
28560
28672
  onMouseEnter,
28561
28673
  onClick,
28562
- children: /* @__PURE__ */ jsx("div", { className: "slash-item", children: /* @__PURE__ */ jsx("span", { className: "text slash-item__label", children: option.label }) })
28674
+ children: [
28675
+ /* @__PURE__ */ jsx("div", { className: "cteditor-flex cteditor-items-center cteditor-justify-center cteditor-rounded-lg cteditor-h-8 cteditor-w-8 cteditor-text-primary cteditor-bg-gradient-to-br cteditor-from-primary/10 cteditor-to-accent/10 group-hover:cteditor-from-primary/20 group-hover:cteditor-to-accent/20", children: meta.icon }),
28676
+ /* @__PURE__ */ jsxs("div", { className: "cteditor-flex cteditor-flex-col cteditor-gap-0.5 cteditor-min-w-0", children: [
28677
+ /* @__PURE__ */ jsx("span", { className: "cteditor-text-sm cteditor-font-semibold cteditor-text-foreground cteditor-truncate", children: option.label }),
28678
+ meta.description && /* @__PURE__ */ jsx("span", { className: "cteditor-text-xs cteditor-text-muted-foreground cteditor-truncate", children: meta.description })
28679
+ ] }),
28680
+ meta.shortcut && /* @__PURE__ */ jsx("span", { className: "cteditor-ml-auto cteditor-text-[10px] cteditor-text-muted-foreground cteditor-border cteditor-border-border cteditor-rounded-md cteditor-px-1.5 cteditor-py-0.5 cteditor-bg-foreground/5", children: meta.shortcut })
28681
+ ]
28563
28682
  },
28564
28683
  option.key
28565
28684
  );
@@ -28664,22 +28783,28 @@ function SlashCommandPlugin() {
28664
28783
  triggerFn,
28665
28784
  options,
28666
28785
  menuRenderFn: (anchorElementRef, { selectedIndex, selectOptionAndCleanUp, setHighlightedIndex }) => anchorElementRef.current ? ReactDOM.createPortal(
28667
- /* @__PURE__ */ jsx("div", { className: "typeahead-popover slash-menu", children: options.length > 0 ? /* @__PURE__ */ jsx("ul", { children: options.map((option, i2) => /* @__PURE__ */ jsx(
28668
- SlashMenuItem,
28669
- {
28670
- index: i2,
28671
- isSelected: selectedIndex === i2,
28672
- onClick: () => {
28673
- setHighlightedIndex(i2);
28674
- selectOptionAndCleanUp(option);
28675
- },
28676
- onMouseEnter: () => {
28677
- setHighlightedIndex(i2);
28786
+ /* @__PURE__ */ jsxs("div", { className: "cteditor-w-72 cteditor-max-h-60 cteditor-overflow-y-auto no-scrollbar cteditor-backdrop-blur-md cteditor-shadow-xl cteditor-rounded-lg cteditor-border cteditor-border-border cteditor-p-1.5 cteditor-bg-background", style: { position: "absolute" }, children: [
28787
+ /* @__PURE__ */ jsxs("div", { className: "cteditor-flex cteditor-items-center cteditor-justify-between cteditor-px-2 cteditor-py-1 cteditor-text-[11px] cteditor-text-muted-foreground", children: [
28788
+ /* @__PURE__ */ jsx("span", { children: queryString ? "Search results" : "Quick actions" }),
28789
+ /* @__PURE__ */ jsx("span", { className: "cteditor-hidden sm:cteditor-inline", children: "Type to filter" })
28790
+ ] }),
28791
+ options.length > 0 ? /* @__PURE__ */ jsx("ul", { className: "cteditor-space-y-1", children: options.map((option, i2) => /* @__PURE__ */ jsx(
28792
+ SlashMenuItem,
28793
+ {
28794
+ index: i2,
28795
+ isSelected: selectedIndex === i2,
28796
+ onClick: () => {
28797
+ setHighlightedIndex(i2);
28798
+ selectOptionAndCleanUp(option);
28799
+ },
28800
+ onMouseEnter: () => {
28801
+ setHighlightedIndex(i2);
28802
+ },
28803
+ option
28678
28804
  },
28679
- option
28680
- },
28681
- option.key
28682
- )) }) : /* @__PURE__ */ jsx("div", { className: "no-users-found", children: "No results" }) }),
28805
+ option.key
28806
+ )) }) : /* @__PURE__ */ jsx("div", { className: "cteditor-text-[11px] cteditor-text-muted-foreground cteditor-px-3 cteditor-py-2", children: "No results" })
28807
+ ] }),
28683
28808
  anchorElementRef.current
28684
28809
  ) : null
28685
28810
  }
@@ -28821,6 +28946,24 @@ function GrammarCheckPlugin() {
28821
28946
  const lastCheckedText = useRef("");
28822
28947
  const highlightElementsRef = useRef([]);
28823
28948
  const checkGrammar = useCallback(async () => {
28949
+ const isSlashActive = editor.getEditorState().read(() => {
28950
+ const selection = $getSelection();
28951
+ if (!$isRangeSelection(selection))
28952
+ return false;
28953
+ const anchor = selection.anchor;
28954
+ const anchorNode = anchor.getNode();
28955
+ const anchorOffset = anchor.offset;
28956
+ const textContent = anchorNode.getTextContent();
28957
+ let wordStart = anchorOffset;
28958
+ while (wordStart > 0 && /[a-zA-Z0-9_']/.test(textContent[wordStart - 1])) {
28959
+ wordStart--;
28960
+ }
28961
+ return wordStart > 0 && textContent[wordStart - 1] === "/";
28962
+ });
28963
+ if (isSlashActive) {
28964
+ setErrors([]);
28965
+ return;
28966
+ }
28824
28967
  const text = editor.getEditorState().read(() => $getRoot().getTextContent());
28825
28968
  if (text === lastCheckedText.current) {
28826
28969
  return;
@@ -29127,8 +29270,11 @@ function GrammarCheckPlugin() {
29127
29270
  const useStyles = () => ({
29128
29271
  // container: "cteditor-relative cteditor-w-full cteditor-bg-white cteditor-text-black cteditor-font-normal cteditor-text-left cteditor-border cteditor-border-red-500",
29129
29272
  contentEditable: cn$1(
29130
- "cteditor-relative cteditor-min-h-[150px] !cteditor-h-auto cteditor-resize-none cteditor-outline-0 cteditor-text-background",
29131
- "cteditor-caret-[#757575] cteditor-p-0 cteditor-transition-all cteditor-duration-200",
29273
+ "cteditor-relative cteditor-min-h-[150px] !cteditor-h-auto cteditor-resize-none cteditor-outline-0",
29274
+ // Ensure strong contrast in both themes
29275
+ "cteditor-text-black dark:cteditor-text-white cteditor-bg-white dark:cteditor-bg-[#0b0b0b]",
29276
+ // Caret and spacing
29277
+ "cteditor-caret-[#3b82f6] cteditor-p-0 cteditor-transition-all cteditor-duration-200",
29132
29278
  "cteditor-w-full ",
29133
29279
  "[&>hr]:cteditor-border-none [&>hr]:cteditor-h-[2px]"
29134
29280
  ),
@@ -29539,4 +29685,4 @@ export {
29539
29685
  useHtmlView as u,
29540
29686
  verifyApiKey as v
29541
29687
  };
29542
- //# sourceMappingURL=index-9d28aec6.js.map
29688
+ //# sourceMappingURL=index-7aab7b5a.js.map