ct-rich-text-editor 1.3.21 → 1.3.22
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/dist/assets/style.css +30 -4
- package/dist/{html2pdf.bundle-0b180070.js → html2pdf.bundle-3699b235.js} +2 -2
- package/dist/{html2pdf.bundle-0b180070.js.map → html2pdf.bundle-3699b235.js.map} +1 -1
- package/dist/{html2pdf.bundle.min-08b31c1f.js → html2pdf.bundle.min-83517dc2.js} +2 -2
- package/dist/{html2pdf.bundle.min-08b31c1f.js.map → html2pdf.bundle.min-83517dc2.js.map} +1 -1
- package/dist/{index-8bcb5b47.js → index-84187412.js} +2 -2
- package/dist/{index-8bcb5b47.js.map → index-84187412.js.map} +1 -1
- package/dist/{index-6360d552.js → index-9a8a49b6.js} +44 -18
- package/dist/index-9a8a49b6.js.map +1 -0
- package/dist/{index-68135c09.js → index-bf836d7a.js} +2 -2
- package/dist/{index-68135c09.js.map → index-bf836d7a.js.map} +1 -1
- package/dist/index.js +1 -1
- package/package.json +1 -1
- package/dist/index-6360d552.js.map +0 -1
|
@@ -15,7 +15,7 @@ import { useLexicalNodeSelection } from "@lexical/react/useLexicalNodeSelection"
|
|
|
15
15
|
import { calculateZoomLevel, mergeRegister } from "@lexical/utils";
|
|
16
16
|
import { RootNode, TextNode, LineBreakNode, ParagraphNode, $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, createCommand, $getNodeByKey } from "lexical";
|
|
17
17
|
import { useRef, useState, useCallback, useEffect, Suspense } from "react";
|
|
18
|
-
import { L as LocalStoragePlugin, i as initialConfig, b as Dialog, d as DialogContent, e as DialogHeader, f as DialogTitle, h as DialogDescription, j as DialogFooter, B as Button, k as $isImageNode, S as Sparkles, E as ExternalLink, T as Trash2, t as toast, A as AiJsonResponse } from "./index-
|
|
18
|
+
import { L as LocalStoragePlugin, i as initialConfig, b as Dialog, d as DialogContent, e as DialogHeader, f as DialogTitle, h as DialogDescription, j as DialogFooter, B as Button, k as $isImageNode, S as Sparkles, E as ExternalLink, T as Trash2, t as toast, A as AiJsonResponse } from "./index-9a8a49b6.js";
|
|
19
19
|
import "axios";
|
|
20
20
|
import "@emotion/styled";
|
|
21
21
|
import "@lexical/html";
|
|
@@ -1040,4 +1040,4 @@ export {
|
|
|
1040
1040
|
RIGHT_CLICK_IMAGE_COMMAND,
|
|
1041
1041
|
ImageComponent as default
|
|
1042
1042
|
};
|
|
1043
|
-
//# sourceMappingURL=index-
|
|
1043
|
+
//# sourceMappingURL=index-84187412.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index-8bcb5b47.js","sources":["../src/components/SignatureCaption/index.tsx","../src/components/ImageView/ImageResizer.tsx","../src/components/ImageComparisonDialog/index.tsx","../src/components/ImageView/index.tsx"],"sourcesContent":["/**\n * SignatureCaption Component\n * A premium styled caption component specifically for signatures\n */\n\nimport \"./signature-caption.css\";\n\nimport { CodeNode } from \"@lexical/code\";\nimport { LinkNode } from \"@lexical/link\";\nimport { ContentEditable } from \"@lexical/react/LexicalContentEditable\";\nimport { LexicalErrorBoundary } from \"@lexical/react/LexicalErrorBoundary\";\nimport { HistoryPlugin } from \"@lexical/react/LexicalHistoryPlugin\";\nimport { LexicalNestedComposer } from \"@lexical/react/LexicalNestedComposer\";\nimport { OnChangePlugin } from \"@lexical/react/LexicalOnChangePlugin\";\nimport { RichTextPlugin } from \"@lexical/react/LexicalRichTextPlugin\";\nimport type { LexicalEditor } from \"lexical\";\nimport { LineBreakNode, ParagraphNode, RootNode, TextNode } from \"lexical\";\nimport { initialConfig } from \"src/constants\";\nimport LocalStoragePlugin from \"src/plugins/LocalStoragePlugin\";\n\ninterface SignatureCaptionProps {\n caption: LexicalEditor;\n}\n\nexport default function SignatureCaption({\n caption,\n}: SignatureCaptionProps): JSX.Element {\n return (\n <div className=\"signature-caption-container\">\n <LexicalNestedComposer\n initialEditor={caption}\n initialNodes={[\n RootNode,\n TextNode,\n LineBreakNode,\n ParagraphNode,\n LinkNode,\n CodeNode,\n ]}\n >\n <RichTextPlugin\n contentEditable={\n <ContentEditable\n aria-placeholder=\"Enter signature name...\"\n placeholder={\n <div style={{\n position: 'absolute',\n top: '4px',\n left: '8px',\n right: '8px',\n textAlign: 'center',\n pointerEvents: 'none',\n color: 'hsla(var(--cteditorf47ac10b-foreground) / 0.4)',\n fontStyle: 'italic'\n }}>\n Enter signature name...\n </div>\n }\n className=\"signature-caption-editable\"\n />\n }\n ErrorBoundary={LexicalErrorBoundary}\n />\n\n <OnChangePlugin onChange={() => {\n // Placeholder for future change handling\n }} />\n <HistoryPlugin />\n <LocalStoragePlugin namespace={initialConfig.namespace} />\n </LexicalNestedComposer>\n </div>\n );\n}\n","/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n */\n\nimport \"./image-caption-styles.css\";\n\nimport { calculateZoomLevel } from \"@lexical/utils\";\nimport type { LexicalEditor } from \"lexical\";\nimport * as React from \"react\";\nimport { useRef } from \"react\";\n\nfunction clamp(value: number, min: number, max: number) {\n return Math.min(Math.max(value, min), max);\n}\n\nconst Direction = {\n east: 1 << 0,\n north: 1 << 3,\n south: 1 << 1,\n west: 1 << 2,\n};\n\nexport default function ImageResizer({\n onResizeStart,\n onResizeEnd,\n buttonRef,\n imageRef,\n maxWidth,\n editor,\n showCaption,\n setShowCaption,\n captionsEnabled,\n}: {\n editor: LexicalEditor;\n buttonRef: { current: null | HTMLButtonElement };\n imageRef: { current: null | HTMLElement };\n maxWidth?: number;\n onResizeEnd: (width: \"inherit\" | number, height: \"inherit\" | number) => void;\n onResizeStart: () => void;\n setShowCaption: (show: boolean) => void;\n showCaption: boolean;\n captionsEnabled: boolean;\n}): JSX.Element {\n const controlWrapperRef = useRef<HTMLDivElement>(null);\n const userSelect = useRef({\n priority: \"\",\n value: \"default\",\n });\n const positioningRef = useRef<{\n currentHeight: \"inherit\" | number;\n currentWidth: \"inherit\" | number;\n direction: number;\n isResizing: boolean;\n ratio: number;\n startHeight: number;\n startWidth: number;\n startX: number;\n startY: number;\n }>({\n currentHeight: 0,\n currentWidth: 0,\n direction: 0,\n isResizing: false,\n ratio: 0,\n startHeight: 0,\n startWidth: 0,\n startX: 0,\n startY: 0,\n });\n const editorRootElement = editor.getRootElement();\n\n // Allow enlarging up to the editor container width (ignore any fixed maxWidth cap)\n const maxWidthContainer =\n editorRootElement !== null\n ? editorRootElement.getBoundingClientRect().width - 20\n : 100;\n const maxHeightContainer =\n editorRootElement !== null\n ? editorRootElement.getBoundingClientRect().height - 20\n : 100;\n\n const minWidth = 100;\n const minHeight = 100;\n\n /**\n * Sets the cursor style to indicate the resizing direction.\n * This function updates the cursor for the editor and document body\n * based on the resizing direction.\n */\n const setStartCursor = (direction: number) => {\n // Determine if the resizing is happening horizontally (east or west)\n const ew = direction === Direction.east || direction === Direction.west;\n // Determine if the resizing is happening vertically (north or south)\n const ns = direction === Direction.north || direction === Direction.south;\n // Determine if the resizing is diagonal (north-west, south-east, etc.)\n const nwse =\n (direction & Direction.north && direction & Direction.west) ||\n (direction & Direction.south && direction & Direction.east);\n\n // Set the appropriate cursor style based on the detected direction\n const cursorDir = ew ? \"ew\" : ns ? \"ns\" : nwse ? \"nwse\" : \"nesw\";\n\n // Apply the cursor style to the editor root element if it exists\n if (editorRootElement !== null) {\n editorRootElement.style.setProperty(\n \"cursor\",\n `${cursorDir}-resize`,\n \"important\"\n );\n }\n\n // Apply the cursor style to the document body\n if (document.body !== null) {\n document.body.style.setProperty(\n \"cursor\",\n `${cursorDir}-resize`,\n \"important\"\n );\n\n // Store the current user selection settings before modifying them\n userSelect.current.value = document.body.style.getPropertyValue(\n \"-webkit-user-select\"\n );\n userSelect.current.priority = document.body.style.getPropertyPriority(\n \"-webkit-user-select\"\n );\n\n // Disable text selection during resizing to prevent unwanted text selection\n document.body.style.setProperty(\n \"-webkit-user-select\",\n `none`,\n \"important\"\n );\n }\n };\n\n /**\n * Resets the cursor style when resizing ends.\n */\n\n const setEndCursor = () => {\n if (editorRootElement !== null) {\n editorRootElement.style.setProperty(\"cursor\", \"text\");\n }\n if (document.body !== null) {\n document.body.style.setProperty(\"cursor\", \"default\");\n document.body.style.setProperty(\n \"-webkit-user-select\",\n userSelect.current.value,\n userSelect.current.priority\n );\n }\n };\n\n /**\n * Handles pointer down event when resizing starts.\n */\n const handlePointerDown = (\n event: React.PointerEvent<HTMLDivElement>,\n direction: number\n ) => {\n if (!editor.isEditable()) {\n return;\n }\n const image = imageRef.current;\n const controlWrapper = controlWrapperRef.current;\n\n // Ensure both the image and control wrapper exist before proceeding\n if (image !== null && controlWrapper !== null) {\n event.preventDefault();\n\n // Get the image's current width and height from its bounding rectangle\n const { width, height } = image.getBoundingClientRect();\n // Calculate the zoom level to adjust calculations accordingly\n const zoom = calculateZoomLevel(image);\n // Retrieve the positioning reference object to store resize state\n const positioning = positioningRef.current;\n\n // Store the initial dimensions of the image\n positioning.startWidth = width;\n positioning.startHeight = height;\n // Store the aspect ratio to maintain proportions when resizing\n positioning.ratio = width / height;\n // Set the current width and height values for tracking changes\n positioning.currentWidth = width;\n positioning.currentHeight = height;\n // Store the initial pointer position, adjusted for zoom level\n positioning.startX = event.clientX / zoom;\n positioning.startY = event.clientY / zoom;\n // Mark the resizing state as active\n positioning.isResizing = true;\n // Store the resize direction (north, south, east, west, or combinations)\n positioning.direction = direction;\n\n // Set the cursor style to indicate resizing in the correct direction\n setStartCursor(direction);\n onResizeStart();\n\n controlWrapper.classList.add(\"image-control-wrapper--resizing\");\n image.style.height = `${height}px`;\n image.style.width = `${width}px`;\n document.addEventListener(\"pointermove\", handlePointerMove);\n document.addEventListener(\"pointerup\", handlePointerUp);\n }\n };\n\n /**\n * Handles pointer move event when resizing the image dynamically.\n */\n const handlePointerMove = (event: PointerEvent) => {\n const image = imageRef.current;\n const positioning = positioningRef.current;\n\n // Check if the resize direction includes horizontal movement (east or west)\n const isHorizontal =\n positioning.direction & (Direction.east | Direction.west);\n // Check if the resize direction includes vertical movement (north or south)\n const isVertical =\n positioning.direction & (Direction.south | Direction.north);\n\n if (image !== null && positioning.isResizing) {\n // Get the zoom level of the image to ensure accurate calculations\n const zoom = calculateZoomLevel(image);\n\n if (isHorizontal && isVertical) {\n // Calculate the difference in X position relative to the starting point\n let diff = Math.floor(positioning.startX - event.clientX / zoom);\n // Reverse the difference if resizing from the east to ensure correct calculations\n diff = positioning.direction & Direction.east ? -diff : diff;\n\n // Calculate the new width, ensuring it stays within allowed min and max limits\n const width = clamp(\n positioning.startWidth + diff,\n minWidth,\n maxWidthContainer\n );\n // Maintain the aspect ratio by adjusting height proportionally\n const height = width / positioning.ratio;\n // Apply the new width and height to the image\n image.style.width = `${width}px`;\n image.style.height = `${height}px`;\n // Update stored dimensions for ongoing tracking\n positioning.currentHeight = height;\n positioning.currentWidth = width;\n } else if (isVertical) {\n // Calculate the difference in Y position relative to the starting point\n let diff = Math.floor(positioning.startY - event.clientY / zoom);\n // Reverse the difference if resizing from the south to maintain correct direction\n diff = positioning.direction & Direction.south ? -diff : diff;\n\n // Calculate the new height, ensuring it stays within allowed min and max limits\n const height = clamp(\n positioning.startHeight + diff,\n minHeight,\n maxHeightContainer\n );\n\n // Apply the new height to the image\n image.style.height = `${height}px`;\n // Update stored height for ongoing tracking\n positioning.currentHeight = height;\n } else {\n // Calculate the difference in X position relative to the starting point\n let diff = Math.floor(positioning.startX - event.clientX / zoom);\n // Reverse the difference if resizing from the east to maintain correct direction\n diff = positioning.direction & Direction.east ? -diff : diff;\n\n // Calculate the new width, ensuring it stays within allowed min and max limits\n const width = clamp(\n positioning.startWidth + diff,\n minWidth,\n maxWidthContainer\n );\n\n // Apply the new width to the image\n image.style.width = `${width}px`;\n // Update stored width for ongoing tracking\n positioning.currentWidth = width;\n }\n }\n };\n\n /**\n * Handles the pointer up event when resizing ends.\n */\n const handlePointerUp = () => {\n const image = imageRef.current;\n const positioning = positioningRef.current;\n const controlWrapper = controlWrapperRef.current;\n\n // Ensure the image, control wrapper exist, and resizing is active before proceeding\n if (image !== null && controlWrapper !== null && positioning.isResizing) {\n // Capture the final width and height of the resized image\n const width = positioning.currentWidth;\n const height = positioning.currentHeight;\n\n // Reset positioning values after resizing is complete\n positioning.startWidth = 0;\n positioning.startHeight = 0;\n positioning.ratio = 0;\n positioning.startX = 0;\n positioning.startY = 0;\n positioning.currentWidth = 0;\n positioning.currentHeight = 0;\n positioning.isResizing = false; // Mark resizing as finished\n\n // Remove the resizing class from the control wrapper\n controlWrapper.classList.remove(\"image-control-wrapper--resizing\");\n\n // Restore default cursor appearance\n setEndCursor();\n // Trigger the resize end callback with the final dimensions\n onResizeEnd(width, height);\n\n // Remove event listeners for pointer movement and release to stop tracking\n document.removeEventListener(\"pointermove\", handlePointerMove);\n document.removeEventListener(\"pointerup\", handlePointerUp);\n }\n };\n\n return (\n <div ref={controlWrapperRef}>\n {!showCaption && captionsEnabled && (\n <button\n className=\"image-caption-button\"\n ref={buttonRef}\n onClick={() => {\n setShowCaption(!showCaption);\n }}\n >\n Add Caption\n </button>\n )}\n <div\n className=\"image-resizer image-resizer-n\"\n onPointerDown={(event) => {\n handlePointerDown(event, Direction.north);\n }}\n />\n <div\n className=\"image-resizer image-resizer-ne\"\n onPointerDown={(event) => {\n handlePointerDown(event, Direction.north | Direction.east);\n }}\n />\n <div\n className=\"image-resizer image-resizer-e\"\n onPointerDown={(event) => {\n handlePointerDown(event, Direction.east);\n }}\n />\n <div\n className=\"image-resizer image-resizer-se\"\n onPointerDown={(event) => {\n handlePointerDown(event, Direction.south | Direction.east);\n }}\n />\n <div\n className=\"image-resizer image-resizer-s\"\n onPointerDown={(event) => {\n handlePointerDown(event, Direction.south);\n }}\n />\n <div\n className=\"image-resizer image-resizer-sw\"\n onPointerDown={(event) => {\n handlePointerDown(event, Direction.south | Direction.west);\n }}\n />\n <div\n className=\"image-resizer image-resizer-w\"\n onPointerDown={(event) => {\n handlePointerDown(event, Direction.west);\n }}\n />\n <div\n className=\"image-resizer image-resizer-nw\"\n onPointerDown={(event) => {\n handlePointerDown(event, Direction.north | Direction.west);\n }}\n />\n </div>\n );\n}\n","import React from \"react\";\nimport { Button } from \"../ui/button\";\nimport {\n Dialog,\n DialogContent,\n DialogDescription,\n DialogFooter,\n DialogHeader,\n DialogTitle,\n} from \"../ui/dialog\";\n\ninterface ImageComparisonDialogProps {\n open: boolean;\n onOpenChange: (open: boolean) => void;\n oldImageUrl: string;\n newImageUrl: string;\n onReplace: () => void;\n onCancel: () => void;\n}\n\nexport const ImageComparisonDialog: React.FC<ImageComparisonDialogProps> = ({\n open,\n onOpenChange,\n oldImageUrl,\n newImageUrl,\n onReplace,\n onCancel,\n}) => {\n return (\n <Dialog open={open} onOpenChange={onOpenChange}>\n <DialogContent className=\"sm:max-w-[800px] max-h-[90vh] overflow-y-auto\">\n <DialogHeader>\n <DialogTitle className=\"flex items-center gap-2 text-xl\">\n <span className=\"text-2xl\">🔄</span>\n Compare Images\n </DialogTitle>\n <DialogDescription className=\"text-sm pt-1\">\n Choose whether to replace the original image with the refined version.\n </DialogDescription>\n </DialogHeader>\n\n <div className=\"space-y-4 py-4\">\n <div className=\"grid grid-cols-2 gap-4\">\n\n {/* New Image */}\n <div className=\"space-y-2\">\n <div className=\"flex items-center justify-between\">\n <span className=\"text-sm font-semibold text-gray-700 dark:text-gray-300\">\n Refined Image\n </span>\n <span className=\"text-xs px-2 py-1 rounded-full bg-blue-100 dark:bg-blue-950/30 text-blue-600 dark:text-blue-400\">\n New\n </span>\n </div>\n <div className=\"relative aspect-square rounded-lg overflow-hidden bg-gray-100 dark:bg-gray-800 border-2 border-blue-500 dark:border-blue-600\">\n <img\n src={newImageUrl}\n alt=\"Refined\"\n className=\"w-full h-full object-contain\"\n />\n </div>\n </div>\n </div>\n\n {/* Info */}\n <div className=\"p-3 rounded-lg bg-blue-50 dark:bg-blue-950/20 border border-blue-200 dark:border-blue-800\">\n <p className=\"text-sm text-blue-800 dark:text-blue-200\">\n <span className=\"font-semibold\">Note:</span> Clicking \"Replace\" will update the image in your document.\n This action cannot be undone.\n </p>\n </div>\n </div>\n\n <DialogFooter className=\"gap-2\">\n <Button\n variant=\"outline\"\n onClick={onCancel}\n >\n Keep Original\n </Button>\n <Button\n onClick={onReplace}\n className=\"bg-blue-500 hover:bg-blue-600 text-white\"\n >\n <span className=\"mr-2\">✓</span>\n Replace Image\n </Button>\n </DialogFooter>\n </DialogContent>\n </Dialog>\n );\n};\n\n","/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n */\n\nimport \"./image-caption-styles.css\";\n\nimport { CodeNode } from \"@lexical/code\";\nimport { LinkNode } from \"@lexical/link\";\nimport { AutoFocusPlugin } from \"@lexical/react/LexicalAutoFocusPlugin\";\nimport { useCollaborationContext } from \"@lexical/react/LexicalCollaborationContext\";\nimport { useLexicalComposerContext } from \"@lexical/react/LexicalComposerContext\";\nimport { ContentEditable } from \"@lexical/react/LexicalContentEditable\";\nimport { LexicalErrorBoundary } from \"@lexical/react/LexicalErrorBoundary\";\nimport { HistoryPlugin } from \"@lexical/react/LexicalHistoryPlugin\";\nimport { LexicalNestedComposer } from \"@lexical/react/LexicalNestedComposer\";\nimport { OnChangePlugin } from \"@lexical/react/LexicalOnChangePlugin\";\n// import './ImageNode.css';\nimport { RichTextPlugin } from \"@lexical/react/LexicalRichTextPlugin\";\nimport { useLexicalEditable } from \"@lexical/react/useLexicalEditable\";\nimport { useLexicalNodeSelection } from \"@lexical/react/useLexicalNodeSelection\";\nimport { mergeRegister } from \"@lexical/utils\";\nimport type {\n BaseSelection,\n LexicalCommand,\n LexicalEditor,\n NodeKey,\n} from \"lexical\";\nimport {\n $getNodeByKey,\n $getSelection,\n $isNodeSelection,\n $isRangeSelection,\n $setSelection,\n CLICK_COMMAND,\n COMMAND_PRIORITY_LOW,\n createCommand,\n DRAGSTART_COMMAND,\n KEY_BACKSPACE_COMMAND,\n KEY_DELETE_COMMAND,\n KEY_ENTER_COMMAND,\n KEY_ESCAPE_COMMAND,\n LineBreakNode,\n ParagraphNode,\n RootNode,\n SELECTION_CHANGE_COMMAND,\n TextNode,\n} from \"lexical\";\nimport { ExternalLink, Trash2, Sparkles } from \"lucide-react\";\nimport * as React from \"react\";\nimport { Suspense, useCallback, useEffect, useRef, useState } from \"react\";\n// import brokenImage from '../images/image-broken.svg';\nimport { toast } from \"sonner\";\nimport { initialConfig } from \"src/constants\";\nimport { $isImageNode, ImagePosition } from \"src/nodes/ImageNode\";\nimport LocalStoragePlugin from \"src/plugins/LocalStoragePlugin\";\n\nimport SignatureCaption from \"../SignatureCaption\";\nimport ImageResizer from \"./ImageResizer\";\nimport { AiJsonResponse } from \"../../api/ai\";\nimport { ImageComparisonDialog } from \"../ImageComparisonDialog\";\n\nconst imageCache = new Set();\n\nexport const RIGHT_CLICK_IMAGE_COMMAND: LexicalCommand<MouseEvent> =\n createCommand(\"RIGHT_CLICK_IMAGE_COMMAND\");\n\nfunction useSuspenseImage(src: string) {\n if (!imageCache.has(src)) {\n throw new Promise((resolve) => {\n const img = new Image();\n img.src = src;\n img.onload = () => {\n imageCache.add(src);\n resolve(null);\n };\n img.onerror = () => {\n imageCache.add(src);\n };\n });\n }\n}\n\nfunction LazyImage({\n altText,\n className,\n imageRef,\n src,\n width,\n height,\n maxWidth,\n onError,\n}: {\n altText: string;\n className: string | null;\n height: \"inherit\" | number;\n imageRef: { current: null | HTMLImageElement };\n maxWidth: number;\n src: string;\n width: \"inherit\" | number;\n onError: () => void;\n}): JSX.Element {\n useSuspenseImage(src);\n const hasExplicitSize = typeof width === 'number' && typeof height === 'number';\n const computedWidth = typeof width === 'number' ? width : 'auto';\n const computedHeight = typeof height === 'number' ? height : 'auto';\n\n return (\n <img\n className={className || undefined}\n src={src}\n alt={altText}\n ref={imageRef}\n style={\n hasExplicitSize\n ? {\n // User has set a numeric size or original dimensions are provided\n width: computedWidth,\n height: computedHeight,\n maxWidth: '100%',\n }\n : {\n // No dimensions specified - use original image size\n maxWidth: '100%',\n height: 'auto',\n }\n }\n onError={onError}\n draggable=\"false\"\n />\n );\n}\n\n// if the image is broken ; we are showing this component\nfunction BrokenImage(): JSX.Element {\n return (\n <img\n src={\"\"} //TODO: NEED TO ADD BROKEN IMAGE\n style={{\n height: 200,\n opacity: 0.2,\n width: 200,\n }}\n draggable=\"false\"\n />\n );\n}\n\nexport default function ImageComponent({\n src,\n altText,\n nodeKey,\n width,\n height,\n maxWidth,\n resizable,\n showCaption,\n caption,\n captionsEnabled,\n originalPrompt,\n position = \"none\",\n}: {\n altText: string;\n caption: LexicalEditor;\n height: \"inherit\" | number;\n maxWidth: number;\n nodeKey: NodeKey;\n resizable: boolean;\n showCaption: boolean;\n src: string;\n width: \"inherit\" | number;\n captionsEnabled: boolean;\n originalPrompt?: string;\n position?: ImagePosition;\n}): JSX.Element {\n const imageRef = useRef<null | HTMLImageElement>(null);\n const buttonRef = useRef<HTMLButtonElement | null>(null);\n const [isSelected, setSelected, clearSelection] =\n useLexicalNodeSelection(nodeKey);\n const [isResizing, setIsResizing] = useState<boolean>(false);\n const { isCollabActive } = useCollaborationContext();\n const [editor] = useLexicalComposerContext();\n const [selection, setSelection] = useState<BaseSelection | null>(null);\n const activeEditorRef = useRef<LexicalEditor | null>(null);\n const [isLoadError, setIsLoadError] = useState<boolean>(false);\n const isEditable = useLexicalEditable();\n const [showRefineInput, setShowRefineInput] = useState<boolean>(false);\n const [refinementPrompt, setRefinementPrompt] = useState<string>(\"\");\n const [isRefining, setIsRefining] = useState<boolean>(false);\n const [showComparisonDialog, setShowComparisonDialog] = useState<boolean>(false);\n const [newImageUrl, setNewImageUrl] = useState<string>(\"\");\n const [newCombinedPrompt, setNewCombinedPrompt] = useState<string>(\"\");\n\n /**\n * Deletes the image node when the delete key is pressed.\n */\n const $onDelete = useCallback(\n (payload: KeyboardEvent) => {\n const deleteSelection = $getSelection();\n if (isSelected && $isNodeSelection(deleteSelection)) {\n const event: KeyboardEvent = payload;\n event.preventDefault();\n editor.update(() => {\n deleteSelection.getNodes().forEach((node) => {\n if ($isImageNode(node)) {\n node.remove();\n }\n });\n });\n }\n return false;\n },\n [editor, isSelected]\n );\n\n /**\n * Handles enter key to move focus into the caption editor.\n */\n const $onEnter = useCallback(\n (event: KeyboardEvent) => {\n const latestSelection = $getSelection();\n const buttonElem = buttonRef.current;\n if (\n isSelected &&\n $isNodeSelection(latestSelection) &&\n latestSelection.getNodes().length === 1\n ) {\n if (showCaption) {\n // Move focus into nested editor\n $setSelection(null);\n event.preventDefault();\n caption.focus();\n return true;\n } else if (\n buttonElem !== null &&\n buttonElem !== document.activeElement\n ) {\n event.preventDefault();\n buttonElem.focus();\n return true;\n }\n }\n return false;\n },\n [caption, isSelected, showCaption]\n );\n\n /**\n * Handles escape key to reset selection.\n */\n const $onEscape = useCallback(\n (event: KeyboardEvent) => {\n if (\n activeEditorRef.current === caption ||\n buttonRef.current === event.target\n ) {\n $setSelection(null);\n editor.update(() => {\n setSelected(true);\n const parentRootElement = editor.getRootElement();\n if (parentRootElement !== null) {\n parentRootElement.focus();\n }\n });\n return true;\n }\n return false;\n },\n [caption, editor, setSelected]\n );\n\n const onClick = useCallback(\n (payload: MouseEvent) => {\n const event = payload;\n\n if (isResizing) {\n return true;\n }\n if (event.target === imageRef.current) {\n if (event.shiftKey) {\n setSelected(!isSelected);\n } else {\n clearSelection();\n setSelected(true);\n }\n return true;\n }\n\n return false;\n },\n [isResizing, isSelected, setSelected, clearSelection]\n );\n\n const onRightClick = useCallback(\n (event: MouseEvent): void => {\n editor.getEditorState().read(() => {\n const latestSelection = $getSelection();\n const domElement = event.target as HTMLElement;\n if (\n domElement.tagName === \"IMG\" &&\n $isRangeSelection(latestSelection) &&\n latestSelection.getNodes().length === 1\n ) {\n editor.dispatchCommand(\n RIGHT_CLICK_IMAGE_COMMAND,\n event as MouseEvent\n );\n }\n });\n },\n [editor]\n );\n\n useEffect(() => {\n let isMounted = true;\n const rootElement = editor.getRootElement();\n const unregister = mergeRegister(\n editor.registerUpdateListener(({ editorState }) => {\n if (isMounted) {\n setSelection(editorState.read(() => $getSelection()));\n }\n }),\n editor.registerCommand(\n SELECTION_CHANGE_COMMAND,\n (_, activeEditor) => {\n activeEditorRef.current = activeEditor;\n return false;\n },\n COMMAND_PRIORITY_LOW\n ),\n editor.registerCommand<MouseEvent>(\n CLICK_COMMAND,\n onClick,\n COMMAND_PRIORITY_LOW\n ),\n editor.registerCommand<MouseEvent>(\n RIGHT_CLICK_IMAGE_COMMAND,\n onClick,\n COMMAND_PRIORITY_LOW\n ),\n editor.registerCommand(\n DRAGSTART_COMMAND,\n (event) => {\n if (event.target === imageRef.current) {\n // Temporary workaround for FF to behave like other browsers.\n // Ideally, this handles drag & drop too (and all browsers).\n event.preventDefault();\n return true;\n }\n return false;\n },\n COMMAND_PRIORITY_LOW\n ),\n editor.registerCommand(\n KEY_DELETE_COMMAND,\n $onDelete,\n COMMAND_PRIORITY_LOW\n ),\n editor.registerCommand(\n KEY_BACKSPACE_COMMAND,\n $onDelete,\n COMMAND_PRIORITY_LOW\n ),\n editor.registerCommand(KEY_ENTER_COMMAND, $onEnter, COMMAND_PRIORITY_LOW),\n editor.registerCommand(\n KEY_ESCAPE_COMMAND,\n $onEscape,\n COMMAND_PRIORITY_LOW\n )\n );\n\n rootElement?.addEventListener(\"contextmenu\", onRightClick);\n\n return () => {\n isMounted = false;\n unregister();\n rootElement?.removeEventListener(\"contextmenu\", onRightClick);\n };\n }, [\n clearSelection,\n editor,\n isResizing,\n isSelected,\n nodeKey,\n $onDelete,\n $onEnter,\n $onEscape,\n onClick,\n onRightClick,\n setSelected,\n ]);\n\n const setShowCaption = () => {\n editor.update(() => {\n const node = $getNodeByKey(nodeKey);\n if ($isImageNode(node)) {\n node.setShowCaption(true);\n }\n });\n };\n\n const onResizeEnd = (\n nextWidth: \"inherit\" | number,\n nextHeight: \"inherit\" | number\n ) => {\n // Delay hiding the resize bars for click case\n setTimeout(() => {\n setIsResizing(false);\n }, 200);\n\n editor.update(() => {\n const node = $getNodeByKey(nodeKey);\n if ($isImageNode(node)) {\n node.setWidthAndHeight(nextWidth, nextHeight);\n }\n });\n };\n\n const onResizeStart = () => {\n setIsResizing(true);\n };\n\n const handleOpenInNewTab = (e: React.MouseEvent) => {\n e.preventDefault();\n e.stopPropagation();\n\n // Check if it's a data URL (base64)\n if (src.startsWith('data:')) {\n // For data URLs, we need to open them in a new tab with the image displayed\n const newWindow = window.open('', '_blank');\n if (newWindow) {\n newWindow.document.write(`\n <!DOCTYPE html>\n <html>\n <head>\n <title>${altText || 'Image'}</title>\n <style>\n body {\n margin: 0;\n display: flex;\n justify-content: center;\n align-items: center;\n min-height: 100vh;\n background-color: #1a1a1a;\n }\n img {\n max-width: 100%;\n max-height: 100vh;\n object-fit: contain;\n }\n </style>\n </head>\n <body>\n <img src=\"${src}\" alt=\"${altText || 'Image'}\" />\n </body>\n </html>\n `);\n newWindow.document.close();\n }\n } else {\n // For regular URLs, just open them directly\n window.open(src, '_blank');\n }\n };\n\n const handleDeleteImage = (e: React.MouseEvent) => {\n e.preventDefault();\n e.stopPropagation();\n\n editor.update(() => {\n const node = $getNodeByKey(nodeKey);\n if ($isImageNode(node)) {\n node.remove();\n }\n });\n };\n\n const handleRefineClick = (e: React.MouseEvent) => {\n e.preventDefault();\n e.stopPropagation();\n setShowRefineInput(!showRefineInput);\n };\n\n const handleRefineImage = async () => {\n if (!refinementPrompt.trim() || isRefining) return;\n\n setIsRefining(true);\n \n // Show loading toast\n const loadingToast = toast.loading(\"Refining image...\", {\n description: \"This may take 10-30 seconds. Please wait.\",\n });\n \n try {\n // Intelligently combine original prompt with refinement\n let combinedPrompt = refinementPrompt.trim();\n \n // Check if we have an original prompt\n if (originalPrompt && originalPrompt.trim()) {\n const original = originalPrompt.trim();\n const refinement = refinementPrompt.trim();\n \n // Remove common \"add\" prefixes from refinement\n const cleanedRefinement = refinement\n .replace(/^(add|also add|include|with|and)\\s+(some|a|an)\\s+/gi, '')\n .replace(/^(add|also add|include|with|and)\\s+/gi, '')\n .trim();\n \n // Simple and clear combination - just list both elements\n // This is the most reliable format for DALL-E\n combinedPrompt = `${original} with ${cleanedRefinement}`;\n } else {\n // No original prompt (image was created before this feature)\n // Try to use altText or just use the refinement as-is\n if (altText && altText !== \"Generated image\" && altText.trim()) {\n // Use altText as the original description\n const cleanedRefinement = refinementPrompt.trim()\n .replace(/^(add|also add|include|with|and)\\s+(some|a|an)\\s+/gi, '')\n .replace(/^(add|also add|include|with|and)\\s+/gi, '')\n .trim();\n combinedPrompt = `${altText} with ${cleanedRefinement}`;\n }\n // else: Just use the refinement prompt as-is\n }\n\n // Generate refined image with combined prompt\n const response = await AiJsonResponse({ content: `Generate Image: ${combinedPrompt}` });\n const htmlString = response?.data;\n\n if (!htmlString) {\n throw new Error(\"Failed to generate image - empty response\");\n }\n\n // Extract image URL from HTML response\n const parser = new DOMParser();\n const dom = parser.parseFromString(htmlString, \"text/html\");\n const imgElement = dom.querySelector(\"img\");\n\n if (!imgElement || !imgElement.src) {\n throw new Error(`No image found in response`);\n }\n\n const generatedImageUrl = imgElement.src;\n\n // Dismiss loading toast and show success\n toast.dismiss(loadingToast);\n toast.success(\"Image refined successfully!\", {\n description: \"Compare the images and choose which to keep.\",\n });\n\n // Store new image URL, combined prompt, and show comparison dialog\n setNewImageUrl(generatedImageUrl);\n setNewCombinedPrompt(combinedPrompt);\n setShowComparisonDialog(true);\n\n // Clear refinement input and close it\n setRefinementPrompt(\"\");\n setShowRefineInput(false);\n } catch (error) {\n // Dismiss loading toast and show error\n toast.dismiss(loadingToast);\n toast.error(\"Failed to refine image\", {\n description: error instanceof Error ? error.message : 'Unknown error. Please try again.',\n });\n } finally {\n setIsRefining(false);\n }\n };\n\n const handleReplaceImage = () => {\n // Update the image node with new URL and updated prompt\n editor.update(() => {\n const node = $getNodeByKey(nodeKey);\n if ($isImageNode(node)) {\n // Use setter methods which properly call getWritable()\n node.setSrc(newImageUrl);\n node.setOriginalPrompt(newCombinedPrompt);\n \n // Force Lexical to re-render the DecoratorNode by triggering selection change\n const currentSelection = $getSelection();\n if (currentSelection) {\n $setSelection(currentSelection.clone());\n }\n }\n });\n\n // Close dialog and reset\n setShowComparisonDialog(false);\n setNewImageUrl(\"\");\n setNewCombinedPrompt(\"\");\n \n // Show success toast\n toast.success(\"Image replaced successfully!\", {\n description: \"The image has been updated with the refined version.\",\n });\n };\n\n const handleCancelReplace = () => {\n // Just close dialog and reset\n setShowComparisonDialog(false);\n setNewImageUrl(\"\");\n setNewCombinedPrompt(\"\");\n };\n\n const draggable = isSelected && $isNodeSelection(selection) && !isResizing;\n const isFocused = (isSelected || isResizing) && isEditable;\n\n // Get position-based styles for float layouts\n // Note: Float styles are now applied at the ImageNode.createDOM level for proper text wrapping\n // This component only needs basic positioning\n const getPositionStyles = (): React.CSSProperties => {\n // For floated images, use simpler styles since float is on parent span\n if (position === \"left\" || position === \"right\") {\n return {\n position: 'relative',\n display: 'block',\n width: '100%', // Fill the floated container\n };\n }\n if (position === \"full\") {\n return {\n position: 'relative',\n display: 'block',\n width: '100%',\n };\n }\n // Default: inline-block for regular images\n return {\n position: 'relative',\n display: 'inline-block',\n };\n };\n\n return (\n <Suspense fallback={null}>\n <>\n <div draggable={draggable} style={getPositionStyles()}>\n {isLoadError ? (\n <BrokenImage />\n ) : (\n <LazyImage\n className={\n isFocused\n ? `focused ${$isNodeSelection(selection) ? \"draggable\" : \"\"}`\n : null\n }\n src={src}\n altText={altText}\n imageRef={imageRef}\n width={width}\n height={height}\n maxWidth={maxWidth}\n onError={() => setIsLoadError(true)}\n />\n )}\n {/* Action Buttons - Refine, Open in New Tab and Delete */}\n {isSelected && $isNodeSelection(selection) && !isLoadError && (\n <div className=\"cteditor-absolute cteditor-top-2 cteditor-right-2 cteditor-flex cteditor-gap-2\" style={{ zIndex: 10 }}>\n <button\n onClick={(e) => {\n e.stopPropagation();\n handleRefineClick(e);\n }}\n className=\"cteditor-p-2 cteditor-rounded-md cteditor-bg-background/80 hover:cteditor-bg-accent cteditor-transition-colors cteditor-shadow-md cteditor-border cteditor-border-border\"\n aria-label=\"Refine image\"\n title=\"Refine image\"\n >\n <Sparkles className=\"cteditor-w-4 cteditor-h-4 cteditor-text-foreground\" />\n </button>\n <button\n onClick={(e) => {\n e.stopPropagation();\n handleOpenInNewTab(e);\n }}\n className=\"cteditor-p-2 cteditor-rounded-md cteditor-bg-background/80 hover:cteditor-bg-accent cteditor-transition-colors cteditor-shadow-md cteditor-border cteditor-border-border\"\n aria-label=\"Open image in new tab\"\n title=\"Open in new tab\"\n >\n <ExternalLink className=\"cteditor-w-4 cteditor-h-4 cteditor-text-foreground\" />\n </button>\n <button\n onClick={(e) => {\n e.stopPropagation();\n handleDeleteImage(e);\n }}\n className=\"cteditor-p-2 cteditor-rounded-md cteditor-bg-background/80 hover:cteditor-bg-destructive hover:cteditor-text-destructive-foreground cteditor-transition-colors cteditor-shadow-md cteditor-border cteditor-border-border\"\n aria-label=\"Delete image\"\n title=\"Delete image\"\n >\n <Trash2 className=\"cteditor-w-4 cteditor-h-4 cteditor-text-foreground\" />\n </button>\n </div>\n )}\n {/* Refine Input */}\n {showRefineInput && isSelected && !isLoadError && (\n <div \n className=\"cteditor-absolute cteditor-bottom-2 cteditor-left-2 cteditor-right-2 cteditor-bg-background cteditor-rounded-lg cteditor-shadow-xl cteditor-border cteditor-border-border cteditor-p-3\" \n style={{ zIndex: 10 }}\n onClick={(e) => e.stopPropagation()}\n onKeyDown={(e) => e.stopPropagation()}\n onKeyUp={(e) => e.stopPropagation()}\n >\n <div className=\"cteditor-flex cteditor-flex-col cteditor-gap-2\">\n <label className=\"cteditor-text-xs cteditor-font-medium cteditor-text-foreground\">\n What else do you want in this scene?\n </label>\n <input\n type=\"text\"\n value={refinementPrompt}\n onChange={(e) => setRefinementPrompt(e.target.value)}\n onKeyDown={(e) => {\n // Stop propagation to prevent editor commands from firing\n e.stopPropagation();\n \n if (e.key === 'Enter' && refinementPrompt.trim() && !isRefining) {\n handleRefineImage();\n }\n if (e.key === 'Escape') {\n setShowRefineInput(false);\n setRefinementPrompt(\"\");\n }\n }}\n onKeyUp={(e) => {\n // Also stop propagation on keyup\n e.stopPropagation();\n }}\n onClick={(e) => {\n // Prevent click from bubbling to image selection\n e.stopPropagation();\n }}\n placeholder=\"e.g., flying birds, golden sunset, stormy clouds...\"\n className=\"cteditor-w-full cteditor-px-3 cteditor-py-2 cteditor-text-sm cteditor-border cteditor-border-border cteditor-rounded-md cteditor-bg-background cteditor-text-foreground focus:cteditor-outline-none focus:cteditor-ring-2 focus:cteditor-ring-blue-500\"\n disabled={isRefining}\n autoFocus\n />\n <div className=\"cteditor-flex cteditor-gap-2\">\n <button\n onClick={(e) => {\n e.stopPropagation();\n handleRefineImage();\n }}\n disabled={isRefining || !refinementPrompt.trim()}\n className=\"cteditor-flex-1 cteditor-px-3 cteditor-py-2 cteditor-text-sm cteditor-rounded-md cteditor-bg-blue-500 cteditor-text-white hover:cteditor-bg-blue-600 disabled:cteditor-opacity-50 disabled:cteditor-cursor-not-allowed cteditor-transition-colors\"\n >\n {isRefining ? (\n <span className=\"cteditor-flex cteditor-items-center cteditor-justify-center cteditor-gap-2\">\n <span className=\"cteditor-inline-block cteditor-w-4 cteditor-h-4 cteditor-border-2 cteditor-border-white cteditor-border-t-transparent cteditor-rounded-full cteditor-animate-spin\"></span>\n Refining...\n </span>\n ) : (\n \"Refine Image\"\n )}\n </button>\n <button\n onClick={(e) => {\n e.stopPropagation();\n setShowRefineInput(false);\n setRefinementPrompt(\"\");\n }}\n disabled={isRefining}\n className=\"cteditor-px-3 cteditor-py-2 cteditor-text-sm cteditor-rounded-md cteditor-bg-background cteditor-border cteditor-border-border cteditor-text-foreground hover:cteditor-bg-accent disabled:cteditor-opacity-50 disabled:cteditor-cursor-not-allowed cteditor-transition-colors\"\n >\n Cancel\n </button>\n </div>\n </div>\n </div>\n )}\n </div>\n\n {showCaption && (\n altText.startsWith(\"Signature by\") ? (\n <SignatureCaption caption={caption} />\n ) : (\n <div className=\"image-caption-container\">\n <LexicalNestedComposer\n initialEditor={caption}\n initialNodes={[\n RootNode,\n TextNode,\n LineBreakNode,\n ParagraphNode,\n LinkNode,\n CodeNode,\n ]}\n >\n <AutoFocusPlugin />\n\n <RichTextPlugin\n contentEditable={\n <ContentEditable\n aria-placeholder=\"Enter a caption...\"\n placeholder={() => <span className=\"cteditor-text-xs\">Enter a caption...</span>}\n className=\"ImageNode__contentEditable\"\n />\n }\n ErrorBoundary={LexicalErrorBoundary}\n />\n\n <OnChangePlugin onChange={() => {}} />\n <HistoryPlugin />\n <LocalStoragePlugin namespace={initialConfig.namespace} />\n </LexicalNestedComposer>\n </div>\n )\n )}\n {resizable && $isNodeSelection(selection) && isFocused && (\n <ImageResizer\n showCaption={showCaption}\n setShowCaption={setShowCaption}\n editor={editor}\n buttonRef={buttonRef}\n imageRef={imageRef}\n maxWidth={maxWidth}\n onResizeStart={onResizeStart}\n onResizeEnd={onResizeEnd}\n captionsEnabled={!isLoadError && captionsEnabled}\n />\n )}\n\n {/* Image Comparison Dialog */}\n <ImageComparisonDialog\n open={showComparisonDialog}\n onOpenChange={setShowComparisonDialog}\n oldImageUrl={src}\n newImageUrl={newImageUrl}\n onReplace={handleReplaceImage}\n onCancel={handleCancelReplace}\n />\n </>\n </Suspense>\n );\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index-84187412.js","sources":["../src/components/SignatureCaption/index.tsx","../src/components/ImageView/ImageResizer.tsx","../src/components/ImageComparisonDialog/index.tsx","../src/components/ImageView/index.tsx"],"sourcesContent":["/**\n * SignatureCaption Component\n * A premium styled caption component specifically for signatures\n */\n\nimport \"./signature-caption.css\";\n\nimport { CodeNode } from \"@lexical/code\";\nimport { LinkNode } from \"@lexical/link\";\nimport { ContentEditable } from \"@lexical/react/LexicalContentEditable\";\nimport { LexicalErrorBoundary } from \"@lexical/react/LexicalErrorBoundary\";\nimport { HistoryPlugin } from \"@lexical/react/LexicalHistoryPlugin\";\nimport { LexicalNestedComposer } from \"@lexical/react/LexicalNestedComposer\";\nimport { OnChangePlugin } from \"@lexical/react/LexicalOnChangePlugin\";\nimport { RichTextPlugin } from \"@lexical/react/LexicalRichTextPlugin\";\nimport type { LexicalEditor } from \"lexical\";\nimport { LineBreakNode, ParagraphNode, RootNode, TextNode } from \"lexical\";\nimport { initialConfig } from \"src/constants\";\nimport LocalStoragePlugin from \"src/plugins/LocalStoragePlugin\";\n\ninterface SignatureCaptionProps {\n caption: LexicalEditor;\n}\n\nexport default function SignatureCaption({\n caption,\n}: SignatureCaptionProps): JSX.Element {\n return (\n <div className=\"signature-caption-container\">\n <LexicalNestedComposer\n initialEditor={caption}\n initialNodes={[\n RootNode,\n TextNode,\n LineBreakNode,\n ParagraphNode,\n LinkNode,\n CodeNode,\n ]}\n >\n <RichTextPlugin\n contentEditable={\n <ContentEditable\n aria-placeholder=\"Enter signature name...\"\n placeholder={\n <div style={{\n position: 'absolute',\n top: '4px',\n left: '8px',\n right: '8px',\n textAlign: 'center',\n pointerEvents: 'none',\n color: 'hsla(var(--cteditorf47ac10b-foreground) / 0.4)',\n fontStyle: 'italic'\n }}>\n Enter signature name...\n </div>\n }\n className=\"signature-caption-editable\"\n />\n }\n ErrorBoundary={LexicalErrorBoundary}\n />\n\n <OnChangePlugin onChange={() => {\n // Placeholder for future change handling\n }} />\n <HistoryPlugin />\n <LocalStoragePlugin namespace={initialConfig.namespace} />\n </LexicalNestedComposer>\n </div>\n );\n}\n","/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n */\n\nimport \"./image-caption-styles.css\";\n\nimport { calculateZoomLevel } from \"@lexical/utils\";\nimport type { LexicalEditor } from \"lexical\";\nimport * as React from \"react\";\nimport { useRef } from \"react\";\n\nfunction clamp(value: number, min: number, max: number) {\n return Math.min(Math.max(value, min), max);\n}\n\nconst Direction = {\n east: 1 << 0,\n north: 1 << 3,\n south: 1 << 1,\n west: 1 << 2,\n};\n\nexport default function ImageResizer({\n onResizeStart,\n onResizeEnd,\n buttonRef,\n imageRef,\n maxWidth,\n editor,\n showCaption,\n setShowCaption,\n captionsEnabled,\n}: {\n editor: LexicalEditor;\n buttonRef: { current: null | HTMLButtonElement };\n imageRef: { current: null | HTMLElement };\n maxWidth?: number;\n onResizeEnd: (width: \"inherit\" | number, height: \"inherit\" | number) => void;\n onResizeStart: () => void;\n setShowCaption: (show: boolean) => void;\n showCaption: boolean;\n captionsEnabled: boolean;\n}): JSX.Element {\n const controlWrapperRef = useRef<HTMLDivElement>(null);\n const userSelect = useRef({\n priority: \"\",\n value: \"default\",\n });\n const positioningRef = useRef<{\n currentHeight: \"inherit\" | number;\n currentWidth: \"inherit\" | number;\n direction: number;\n isResizing: boolean;\n ratio: number;\n startHeight: number;\n startWidth: number;\n startX: number;\n startY: number;\n }>({\n currentHeight: 0,\n currentWidth: 0,\n direction: 0,\n isResizing: false,\n ratio: 0,\n startHeight: 0,\n startWidth: 0,\n startX: 0,\n startY: 0,\n });\n const editorRootElement = editor.getRootElement();\n\n // Allow enlarging up to the editor container width (ignore any fixed maxWidth cap)\n const maxWidthContainer =\n editorRootElement !== null\n ? editorRootElement.getBoundingClientRect().width - 20\n : 100;\n const maxHeightContainer =\n editorRootElement !== null\n ? editorRootElement.getBoundingClientRect().height - 20\n : 100;\n\n const minWidth = 100;\n const minHeight = 100;\n\n /**\n * Sets the cursor style to indicate the resizing direction.\n * This function updates the cursor for the editor and document body\n * based on the resizing direction.\n */\n const setStartCursor = (direction: number) => {\n // Determine if the resizing is happening horizontally (east or west)\n const ew = direction === Direction.east || direction === Direction.west;\n // Determine if the resizing is happening vertically (north or south)\n const ns = direction === Direction.north || direction === Direction.south;\n // Determine if the resizing is diagonal (north-west, south-east, etc.)\n const nwse =\n (direction & Direction.north && direction & Direction.west) ||\n (direction & Direction.south && direction & Direction.east);\n\n // Set the appropriate cursor style based on the detected direction\n const cursorDir = ew ? \"ew\" : ns ? \"ns\" : nwse ? \"nwse\" : \"nesw\";\n\n // Apply the cursor style to the editor root element if it exists\n if (editorRootElement !== null) {\n editorRootElement.style.setProperty(\n \"cursor\",\n `${cursorDir}-resize`,\n \"important\"\n );\n }\n\n // Apply the cursor style to the document body\n if (document.body !== null) {\n document.body.style.setProperty(\n \"cursor\",\n `${cursorDir}-resize`,\n \"important\"\n );\n\n // Store the current user selection settings before modifying them\n userSelect.current.value = document.body.style.getPropertyValue(\n \"-webkit-user-select\"\n );\n userSelect.current.priority = document.body.style.getPropertyPriority(\n \"-webkit-user-select\"\n );\n\n // Disable text selection during resizing to prevent unwanted text selection\n document.body.style.setProperty(\n \"-webkit-user-select\",\n `none`,\n \"important\"\n );\n }\n };\n\n /**\n * Resets the cursor style when resizing ends.\n */\n\n const setEndCursor = () => {\n if (editorRootElement !== null) {\n editorRootElement.style.setProperty(\"cursor\", \"text\");\n }\n if (document.body !== null) {\n document.body.style.setProperty(\"cursor\", \"default\");\n document.body.style.setProperty(\n \"-webkit-user-select\",\n userSelect.current.value,\n userSelect.current.priority\n );\n }\n };\n\n /**\n * Handles pointer down event when resizing starts.\n */\n const handlePointerDown = (\n event: React.PointerEvent<HTMLDivElement>,\n direction: number\n ) => {\n if (!editor.isEditable()) {\n return;\n }\n const image = imageRef.current;\n const controlWrapper = controlWrapperRef.current;\n\n // Ensure both the image and control wrapper exist before proceeding\n if (image !== null && controlWrapper !== null) {\n event.preventDefault();\n\n // Get the image's current width and height from its bounding rectangle\n const { width, height } = image.getBoundingClientRect();\n // Calculate the zoom level to adjust calculations accordingly\n const zoom = calculateZoomLevel(image);\n // Retrieve the positioning reference object to store resize state\n const positioning = positioningRef.current;\n\n // Store the initial dimensions of the image\n positioning.startWidth = width;\n positioning.startHeight = height;\n // Store the aspect ratio to maintain proportions when resizing\n positioning.ratio = width / height;\n // Set the current width and height values for tracking changes\n positioning.currentWidth = width;\n positioning.currentHeight = height;\n // Store the initial pointer position, adjusted for zoom level\n positioning.startX = event.clientX / zoom;\n positioning.startY = event.clientY / zoom;\n // Mark the resizing state as active\n positioning.isResizing = true;\n // Store the resize direction (north, south, east, west, or combinations)\n positioning.direction = direction;\n\n // Set the cursor style to indicate resizing in the correct direction\n setStartCursor(direction);\n onResizeStart();\n\n controlWrapper.classList.add(\"image-control-wrapper--resizing\");\n image.style.height = `${height}px`;\n image.style.width = `${width}px`;\n document.addEventListener(\"pointermove\", handlePointerMove);\n document.addEventListener(\"pointerup\", handlePointerUp);\n }\n };\n\n /**\n * Handles pointer move event when resizing the image dynamically.\n */\n const handlePointerMove = (event: PointerEvent) => {\n const image = imageRef.current;\n const positioning = positioningRef.current;\n\n // Check if the resize direction includes horizontal movement (east or west)\n const isHorizontal =\n positioning.direction & (Direction.east | Direction.west);\n // Check if the resize direction includes vertical movement (north or south)\n const isVertical =\n positioning.direction & (Direction.south | Direction.north);\n\n if (image !== null && positioning.isResizing) {\n // Get the zoom level of the image to ensure accurate calculations\n const zoom = calculateZoomLevel(image);\n\n if (isHorizontal && isVertical) {\n // Calculate the difference in X position relative to the starting point\n let diff = Math.floor(positioning.startX - event.clientX / zoom);\n // Reverse the difference if resizing from the east to ensure correct calculations\n diff = positioning.direction & Direction.east ? -diff : diff;\n\n // Calculate the new width, ensuring it stays within allowed min and max limits\n const width = clamp(\n positioning.startWidth + diff,\n minWidth,\n maxWidthContainer\n );\n // Maintain the aspect ratio by adjusting height proportionally\n const height = width / positioning.ratio;\n // Apply the new width and height to the image\n image.style.width = `${width}px`;\n image.style.height = `${height}px`;\n // Update stored dimensions for ongoing tracking\n positioning.currentHeight = height;\n positioning.currentWidth = width;\n } else if (isVertical) {\n // Calculate the difference in Y position relative to the starting point\n let diff = Math.floor(positioning.startY - event.clientY / zoom);\n // Reverse the difference if resizing from the south to maintain correct direction\n diff = positioning.direction & Direction.south ? -diff : diff;\n\n // Calculate the new height, ensuring it stays within allowed min and max limits\n const height = clamp(\n positioning.startHeight + diff,\n minHeight,\n maxHeightContainer\n );\n\n // Apply the new height to the image\n image.style.height = `${height}px`;\n // Update stored height for ongoing tracking\n positioning.currentHeight = height;\n } else {\n // Calculate the difference in X position relative to the starting point\n let diff = Math.floor(positioning.startX - event.clientX / zoom);\n // Reverse the difference if resizing from the east to maintain correct direction\n diff = positioning.direction & Direction.east ? -diff : diff;\n\n // Calculate the new width, ensuring it stays within allowed min and max limits\n const width = clamp(\n positioning.startWidth + diff,\n minWidth,\n maxWidthContainer\n );\n\n // Apply the new width to the image\n image.style.width = `${width}px`;\n // Update stored width for ongoing tracking\n positioning.currentWidth = width;\n }\n }\n };\n\n /**\n * Handles the pointer up event when resizing ends.\n */\n const handlePointerUp = () => {\n const image = imageRef.current;\n const positioning = positioningRef.current;\n const controlWrapper = controlWrapperRef.current;\n\n // Ensure the image, control wrapper exist, and resizing is active before proceeding\n if (image !== null && controlWrapper !== null && positioning.isResizing) {\n // Capture the final width and height of the resized image\n const width = positioning.currentWidth;\n const height = positioning.currentHeight;\n\n // Reset positioning values after resizing is complete\n positioning.startWidth = 0;\n positioning.startHeight = 0;\n positioning.ratio = 0;\n positioning.startX = 0;\n positioning.startY = 0;\n positioning.currentWidth = 0;\n positioning.currentHeight = 0;\n positioning.isResizing = false; // Mark resizing as finished\n\n // Remove the resizing class from the control wrapper\n controlWrapper.classList.remove(\"image-control-wrapper--resizing\");\n\n // Restore default cursor appearance\n setEndCursor();\n // Trigger the resize end callback with the final dimensions\n onResizeEnd(width, height);\n\n // Remove event listeners for pointer movement and release to stop tracking\n document.removeEventListener(\"pointermove\", handlePointerMove);\n document.removeEventListener(\"pointerup\", handlePointerUp);\n }\n };\n\n return (\n <div ref={controlWrapperRef}>\n {!showCaption && captionsEnabled && (\n <button\n className=\"image-caption-button\"\n ref={buttonRef}\n onClick={() => {\n setShowCaption(!showCaption);\n }}\n >\n Add Caption\n </button>\n )}\n <div\n className=\"image-resizer image-resizer-n\"\n onPointerDown={(event) => {\n handlePointerDown(event, Direction.north);\n }}\n />\n <div\n className=\"image-resizer image-resizer-ne\"\n onPointerDown={(event) => {\n handlePointerDown(event, Direction.north | Direction.east);\n }}\n />\n <div\n className=\"image-resizer image-resizer-e\"\n onPointerDown={(event) => {\n handlePointerDown(event, Direction.east);\n }}\n />\n <div\n className=\"image-resizer image-resizer-se\"\n onPointerDown={(event) => {\n handlePointerDown(event, Direction.south | Direction.east);\n }}\n />\n <div\n className=\"image-resizer image-resizer-s\"\n onPointerDown={(event) => {\n handlePointerDown(event, Direction.south);\n }}\n />\n <div\n className=\"image-resizer image-resizer-sw\"\n onPointerDown={(event) => {\n handlePointerDown(event, Direction.south | Direction.west);\n }}\n />\n <div\n className=\"image-resizer image-resizer-w\"\n onPointerDown={(event) => {\n handlePointerDown(event, Direction.west);\n }}\n />\n <div\n className=\"image-resizer image-resizer-nw\"\n onPointerDown={(event) => {\n handlePointerDown(event, Direction.north | Direction.west);\n }}\n />\n </div>\n );\n}\n","import React from \"react\";\nimport { Button } from \"../ui/button\";\nimport {\n Dialog,\n DialogContent,\n DialogDescription,\n DialogFooter,\n DialogHeader,\n DialogTitle,\n} from \"../ui/dialog\";\n\ninterface ImageComparisonDialogProps {\n open: boolean;\n onOpenChange: (open: boolean) => void;\n oldImageUrl: string;\n newImageUrl: string;\n onReplace: () => void;\n onCancel: () => void;\n}\n\nexport const ImageComparisonDialog: React.FC<ImageComparisonDialogProps> = ({\n open,\n onOpenChange,\n oldImageUrl,\n newImageUrl,\n onReplace,\n onCancel,\n}) => {\n return (\n <Dialog open={open} onOpenChange={onOpenChange}>\n <DialogContent className=\"sm:max-w-[800px] max-h-[90vh] overflow-y-auto\">\n <DialogHeader>\n <DialogTitle className=\"flex items-center gap-2 text-xl\">\n <span className=\"text-2xl\">🔄</span>\n Compare Images\n </DialogTitle>\n <DialogDescription className=\"text-sm pt-1\">\n Choose whether to replace the original image with the refined version.\n </DialogDescription>\n </DialogHeader>\n\n <div className=\"space-y-4 py-4\">\n <div className=\"grid grid-cols-2 gap-4\">\n\n {/* New Image */}\n <div className=\"space-y-2\">\n <div className=\"flex items-center justify-between\">\n <span className=\"text-sm font-semibold text-gray-700 dark:text-gray-300\">\n Refined Image\n </span>\n <span className=\"text-xs px-2 py-1 rounded-full bg-blue-100 dark:bg-blue-950/30 text-blue-600 dark:text-blue-400\">\n New\n </span>\n </div>\n <div className=\"relative aspect-square rounded-lg overflow-hidden bg-gray-100 dark:bg-gray-800 border-2 border-blue-500 dark:border-blue-600\">\n <img\n src={newImageUrl}\n alt=\"Refined\"\n className=\"w-full h-full object-contain\"\n />\n </div>\n </div>\n </div>\n\n {/* Info */}\n <div className=\"p-3 rounded-lg bg-blue-50 dark:bg-blue-950/20 border border-blue-200 dark:border-blue-800\">\n <p className=\"text-sm text-blue-800 dark:text-blue-200\">\n <span className=\"font-semibold\">Note:</span> Clicking \"Replace\" will update the image in your document.\n This action cannot be undone.\n </p>\n </div>\n </div>\n\n <DialogFooter className=\"gap-2\">\n <Button\n variant=\"outline\"\n onClick={onCancel}\n >\n Keep Original\n </Button>\n <Button\n onClick={onReplace}\n className=\"bg-blue-500 hover:bg-blue-600 text-white\"\n >\n <span className=\"mr-2\">✓</span>\n Replace Image\n </Button>\n </DialogFooter>\n </DialogContent>\n </Dialog>\n );\n};\n\n","/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n */\n\nimport \"./image-caption-styles.css\";\n\nimport { CodeNode } from \"@lexical/code\";\nimport { LinkNode } from \"@lexical/link\";\nimport { AutoFocusPlugin } from \"@lexical/react/LexicalAutoFocusPlugin\";\nimport { useCollaborationContext } from \"@lexical/react/LexicalCollaborationContext\";\nimport { useLexicalComposerContext } from \"@lexical/react/LexicalComposerContext\";\nimport { ContentEditable } from \"@lexical/react/LexicalContentEditable\";\nimport { LexicalErrorBoundary } from \"@lexical/react/LexicalErrorBoundary\";\nimport { HistoryPlugin } from \"@lexical/react/LexicalHistoryPlugin\";\nimport { LexicalNestedComposer } from \"@lexical/react/LexicalNestedComposer\";\nimport { OnChangePlugin } from \"@lexical/react/LexicalOnChangePlugin\";\n// import './ImageNode.css';\nimport { RichTextPlugin } from \"@lexical/react/LexicalRichTextPlugin\";\nimport { useLexicalEditable } from \"@lexical/react/useLexicalEditable\";\nimport { useLexicalNodeSelection } from \"@lexical/react/useLexicalNodeSelection\";\nimport { mergeRegister } from \"@lexical/utils\";\nimport type {\n BaseSelection,\n LexicalCommand,\n LexicalEditor,\n NodeKey,\n} from \"lexical\";\nimport {\n $getNodeByKey,\n $getSelection,\n $isNodeSelection,\n $isRangeSelection,\n $setSelection,\n CLICK_COMMAND,\n COMMAND_PRIORITY_LOW,\n createCommand,\n DRAGSTART_COMMAND,\n KEY_BACKSPACE_COMMAND,\n KEY_DELETE_COMMAND,\n KEY_ENTER_COMMAND,\n KEY_ESCAPE_COMMAND,\n LineBreakNode,\n ParagraphNode,\n RootNode,\n SELECTION_CHANGE_COMMAND,\n TextNode,\n} from \"lexical\";\nimport { ExternalLink, Trash2, Sparkles } from \"lucide-react\";\nimport * as React from \"react\";\nimport { Suspense, useCallback, useEffect, useRef, useState } from \"react\";\n// import brokenImage from '../images/image-broken.svg';\nimport { toast } from \"sonner\";\nimport { initialConfig } from \"src/constants\";\nimport { $isImageNode, ImagePosition } from \"src/nodes/ImageNode\";\nimport LocalStoragePlugin from \"src/plugins/LocalStoragePlugin\";\n\nimport SignatureCaption from \"../SignatureCaption\";\nimport ImageResizer from \"./ImageResizer\";\nimport { AiJsonResponse } from \"../../api/ai\";\nimport { ImageComparisonDialog } from \"../ImageComparisonDialog\";\n\nconst imageCache = new Set();\n\nexport const RIGHT_CLICK_IMAGE_COMMAND: LexicalCommand<MouseEvent> =\n createCommand(\"RIGHT_CLICK_IMAGE_COMMAND\");\n\nfunction useSuspenseImage(src: string) {\n if (!imageCache.has(src)) {\n throw new Promise((resolve) => {\n const img = new Image();\n img.src = src;\n img.onload = () => {\n imageCache.add(src);\n resolve(null);\n };\n img.onerror = () => {\n imageCache.add(src);\n };\n });\n }\n}\n\nfunction LazyImage({\n altText,\n className,\n imageRef,\n src,\n width,\n height,\n maxWidth,\n onError,\n}: {\n altText: string;\n className: string | null;\n height: \"inherit\" | number;\n imageRef: { current: null | HTMLImageElement };\n maxWidth: number;\n src: string;\n width: \"inherit\" | number;\n onError: () => void;\n}): JSX.Element {\n useSuspenseImage(src);\n const hasExplicitSize = typeof width === 'number' && typeof height === 'number';\n const computedWidth = typeof width === 'number' ? width : 'auto';\n const computedHeight = typeof height === 'number' ? height : 'auto';\n\n return (\n <img\n className={className || undefined}\n src={src}\n alt={altText}\n ref={imageRef}\n style={\n hasExplicitSize\n ? {\n // User has set a numeric size or original dimensions are provided\n width: computedWidth,\n height: computedHeight,\n maxWidth: '100%',\n }\n : {\n // No dimensions specified - use original image size\n maxWidth: '100%',\n height: 'auto',\n }\n }\n onError={onError}\n draggable=\"false\"\n />\n );\n}\n\n// if the image is broken ; we are showing this component\nfunction BrokenImage(): JSX.Element {\n return (\n <img\n src={\"\"} //TODO: NEED TO ADD BROKEN IMAGE\n style={{\n height: 200,\n opacity: 0.2,\n width: 200,\n }}\n draggable=\"false\"\n />\n );\n}\n\nexport default function ImageComponent({\n src,\n altText,\n nodeKey,\n width,\n height,\n maxWidth,\n resizable,\n showCaption,\n caption,\n captionsEnabled,\n originalPrompt,\n position = \"none\",\n}: {\n altText: string;\n caption: LexicalEditor;\n height: \"inherit\" | number;\n maxWidth: number;\n nodeKey: NodeKey;\n resizable: boolean;\n showCaption: boolean;\n src: string;\n width: \"inherit\" | number;\n captionsEnabled: boolean;\n originalPrompt?: string;\n position?: ImagePosition;\n}): JSX.Element {\n const imageRef = useRef<null | HTMLImageElement>(null);\n const buttonRef = useRef<HTMLButtonElement | null>(null);\n const [isSelected, setSelected, clearSelection] =\n useLexicalNodeSelection(nodeKey);\n const [isResizing, setIsResizing] = useState<boolean>(false);\n const { isCollabActive } = useCollaborationContext();\n const [editor] = useLexicalComposerContext();\n const [selection, setSelection] = useState<BaseSelection | null>(null);\n const activeEditorRef = useRef<LexicalEditor | null>(null);\n const [isLoadError, setIsLoadError] = useState<boolean>(false);\n const isEditable = useLexicalEditable();\n const [showRefineInput, setShowRefineInput] = useState<boolean>(false);\n const [refinementPrompt, setRefinementPrompt] = useState<string>(\"\");\n const [isRefining, setIsRefining] = useState<boolean>(false);\n const [showComparisonDialog, setShowComparisonDialog] = useState<boolean>(false);\n const [newImageUrl, setNewImageUrl] = useState<string>(\"\");\n const [newCombinedPrompt, setNewCombinedPrompt] = useState<string>(\"\");\n\n /**\n * Deletes the image node when the delete key is pressed.\n */\n const $onDelete = useCallback(\n (payload: KeyboardEvent) => {\n const deleteSelection = $getSelection();\n if (isSelected && $isNodeSelection(deleteSelection)) {\n const event: KeyboardEvent = payload;\n event.preventDefault();\n editor.update(() => {\n deleteSelection.getNodes().forEach((node) => {\n if ($isImageNode(node)) {\n node.remove();\n }\n });\n });\n }\n return false;\n },\n [editor, isSelected]\n );\n\n /**\n * Handles enter key to move focus into the caption editor.\n */\n const $onEnter = useCallback(\n (event: KeyboardEvent) => {\n const latestSelection = $getSelection();\n const buttonElem = buttonRef.current;\n if (\n isSelected &&\n $isNodeSelection(latestSelection) &&\n latestSelection.getNodes().length === 1\n ) {\n if (showCaption) {\n // Move focus into nested editor\n $setSelection(null);\n event.preventDefault();\n caption.focus();\n return true;\n } else if (\n buttonElem !== null &&\n buttonElem !== document.activeElement\n ) {\n event.preventDefault();\n buttonElem.focus();\n return true;\n }\n }\n return false;\n },\n [caption, isSelected, showCaption]\n );\n\n /**\n * Handles escape key to reset selection.\n */\n const $onEscape = useCallback(\n (event: KeyboardEvent) => {\n if (\n activeEditorRef.current === caption ||\n buttonRef.current === event.target\n ) {\n $setSelection(null);\n editor.update(() => {\n setSelected(true);\n const parentRootElement = editor.getRootElement();\n if (parentRootElement !== null) {\n parentRootElement.focus();\n }\n });\n return true;\n }\n return false;\n },\n [caption, editor, setSelected]\n );\n\n const onClick = useCallback(\n (payload: MouseEvent) => {\n const event = payload;\n\n if (isResizing) {\n return true;\n }\n if (event.target === imageRef.current) {\n if (event.shiftKey) {\n setSelected(!isSelected);\n } else {\n clearSelection();\n setSelected(true);\n }\n return true;\n }\n\n return false;\n },\n [isResizing, isSelected, setSelected, clearSelection]\n );\n\n const onRightClick = useCallback(\n (event: MouseEvent): void => {\n editor.getEditorState().read(() => {\n const latestSelection = $getSelection();\n const domElement = event.target as HTMLElement;\n if (\n domElement.tagName === \"IMG\" &&\n $isRangeSelection(latestSelection) &&\n latestSelection.getNodes().length === 1\n ) {\n editor.dispatchCommand(\n RIGHT_CLICK_IMAGE_COMMAND,\n event as MouseEvent\n );\n }\n });\n },\n [editor]\n );\n\n useEffect(() => {\n let isMounted = true;\n const rootElement = editor.getRootElement();\n const unregister = mergeRegister(\n editor.registerUpdateListener(({ editorState }) => {\n if (isMounted) {\n setSelection(editorState.read(() => $getSelection()));\n }\n }),\n editor.registerCommand(\n SELECTION_CHANGE_COMMAND,\n (_, activeEditor) => {\n activeEditorRef.current = activeEditor;\n return false;\n },\n COMMAND_PRIORITY_LOW\n ),\n editor.registerCommand<MouseEvent>(\n CLICK_COMMAND,\n onClick,\n COMMAND_PRIORITY_LOW\n ),\n editor.registerCommand<MouseEvent>(\n RIGHT_CLICK_IMAGE_COMMAND,\n onClick,\n COMMAND_PRIORITY_LOW\n ),\n editor.registerCommand(\n DRAGSTART_COMMAND,\n (event) => {\n if (event.target === imageRef.current) {\n // Temporary workaround for FF to behave like other browsers.\n // Ideally, this handles drag & drop too (and all browsers).\n event.preventDefault();\n return true;\n }\n return false;\n },\n COMMAND_PRIORITY_LOW\n ),\n editor.registerCommand(\n KEY_DELETE_COMMAND,\n $onDelete,\n COMMAND_PRIORITY_LOW\n ),\n editor.registerCommand(\n KEY_BACKSPACE_COMMAND,\n $onDelete,\n COMMAND_PRIORITY_LOW\n ),\n editor.registerCommand(KEY_ENTER_COMMAND, $onEnter, COMMAND_PRIORITY_LOW),\n editor.registerCommand(\n KEY_ESCAPE_COMMAND,\n $onEscape,\n COMMAND_PRIORITY_LOW\n )\n );\n\n rootElement?.addEventListener(\"contextmenu\", onRightClick);\n\n return () => {\n isMounted = false;\n unregister();\n rootElement?.removeEventListener(\"contextmenu\", onRightClick);\n };\n }, [\n clearSelection,\n editor,\n isResizing,\n isSelected,\n nodeKey,\n $onDelete,\n $onEnter,\n $onEscape,\n onClick,\n onRightClick,\n setSelected,\n ]);\n\n const setShowCaption = () => {\n editor.update(() => {\n const node = $getNodeByKey(nodeKey);\n if ($isImageNode(node)) {\n node.setShowCaption(true);\n }\n });\n };\n\n const onResizeEnd = (\n nextWidth: \"inherit\" | number,\n nextHeight: \"inherit\" | number\n ) => {\n // Delay hiding the resize bars for click case\n setTimeout(() => {\n setIsResizing(false);\n }, 200);\n\n editor.update(() => {\n const node = $getNodeByKey(nodeKey);\n if ($isImageNode(node)) {\n node.setWidthAndHeight(nextWidth, nextHeight);\n }\n });\n };\n\n const onResizeStart = () => {\n setIsResizing(true);\n };\n\n const handleOpenInNewTab = (e: React.MouseEvent) => {\n e.preventDefault();\n e.stopPropagation();\n\n // Check if it's a data URL (base64)\n if (src.startsWith('data:')) {\n // For data URLs, we need to open them in a new tab with the image displayed\n const newWindow = window.open('', '_blank');\n if (newWindow) {\n newWindow.document.write(`\n <!DOCTYPE html>\n <html>\n <head>\n <title>${altText || 'Image'}</title>\n <style>\n body {\n margin: 0;\n display: flex;\n justify-content: center;\n align-items: center;\n min-height: 100vh;\n background-color: #1a1a1a;\n }\n img {\n max-width: 100%;\n max-height: 100vh;\n object-fit: contain;\n }\n </style>\n </head>\n <body>\n <img src=\"${src}\" alt=\"${altText || 'Image'}\" />\n </body>\n </html>\n `);\n newWindow.document.close();\n }\n } else {\n // For regular URLs, just open them directly\n window.open(src, '_blank');\n }\n };\n\n const handleDeleteImage = (e: React.MouseEvent) => {\n e.preventDefault();\n e.stopPropagation();\n\n editor.update(() => {\n const node = $getNodeByKey(nodeKey);\n if ($isImageNode(node)) {\n node.remove();\n }\n });\n };\n\n const handleRefineClick = (e: React.MouseEvent) => {\n e.preventDefault();\n e.stopPropagation();\n setShowRefineInput(!showRefineInput);\n };\n\n const handleRefineImage = async () => {\n if (!refinementPrompt.trim() || isRefining) return;\n\n setIsRefining(true);\n \n // Show loading toast\n const loadingToast = toast.loading(\"Refining image...\", {\n description: \"This may take 10-30 seconds. Please wait.\",\n });\n \n try {\n // Intelligently combine original prompt with refinement\n let combinedPrompt = refinementPrompt.trim();\n \n // Check if we have an original prompt\n if (originalPrompt && originalPrompt.trim()) {\n const original = originalPrompt.trim();\n const refinement = refinementPrompt.trim();\n \n // Remove common \"add\" prefixes from refinement\n const cleanedRefinement = refinement\n .replace(/^(add|also add|include|with|and)\\s+(some|a|an)\\s+/gi, '')\n .replace(/^(add|also add|include|with|and)\\s+/gi, '')\n .trim();\n \n // Simple and clear combination - just list both elements\n // This is the most reliable format for DALL-E\n combinedPrompt = `${original} with ${cleanedRefinement}`;\n } else {\n // No original prompt (image was created before this feature)\n // Try to use altText or just use the refinement as-is\n if (altText && altText !== \"Generated image\" && altText.trim()) {\n // Use altText as the original description\n const cleanedRefinement = refinementPrompt.trim()\n .replace(/^(add|also add|include|with|and)\\s+(some|a|an)\\s+/gi, '')\n .replace(/^(add|also add|include|with|and)\\s+/gi, '')\n .trim();\n combinedPrompt = `${altText} with ${cleanedRefinement}`;\n }\n // else: Just use the refinement prompt as-is\n }\n\n // Generate refined image with combined prompt\n const response = await AiJsonResponse({ content: `Generate Image: ${combinedPrompt}` });\n const htmlString = response?.data;\n\n if (!htmlString) {\n throw new Error(\"Failed to generate image - empty response\");\n }\n\n // Extract image URL from HTML response\n const parser = new DOMParser();\n const dom = parser.parseFromString(htmlString, \"text/html\");\n const imgElement = dom.querySelector(\"img\");\n\n if (!imgElement || !imgElement.src) {\n throw new Error(`No image found in response`);\n }\n\n const generatedImageUrl = imgElement.src;\n\n // Dismiss loading toast and show success\n toast.dismiss(loadingToast);\n toast.success(\"Image refined successfully!\", {\n description: \"Compare the images and choose which to keep.\",\n });\n\n // Store new image URL, combined prompt, and show comparison dialog\n setNewImageUrl(generatedImageUrl);\n setNewCombinedPrompt(combinedPrompt);\n setShowComparisonDialog(true);\n\n // Clear refinement input and close it\n setRefinementPrompt(\"\");\n setShowRefineInput(false);\n } catch (error) {\n // Dismiss loading toast and show error\n toast.dismiss(loadingToast);\n toast.error(\"Failed to refine image\", {\n description: error instanceof Error ? error.message : 'Unknown error. Please try again.',\n });\n } finally {\n setIsRefining(false);\n }\n };\n\n const handleReplaceImage = () => {\n // Update the image node with new URL and updated prompt\n editor.update(() => {\n const node = $getNodeByKey(nodeKey);\n if ($isImageNode(node)) {\n // Use setter methods which properly call getWritable()\n node.setSrc(newImageUrl);\n node.setOriginalPrompt(newCombinedPrompt);\n \n // Force Lexical to re-render the DecoratorNode by triggering selection change\n const currentSelection = $getSelection();\n if (currentSelection) {\n $setSelection(currentSelection.clone());\n }\n }\n });\n\n // Close dialog and reset\n setShowComparisonDialog(false);\n setNewImageUrl(\"\");\n setNewCombinedPrompt(\"\");\n \n // Show success toast\n toast.success(\"Image replaced successfully!\", {\n description: \"The image has been updated with the refined version.\",\n });\n };\n\n const handleCancelReplace = () => {\n // Just close dialog and reset\n setShowComparisonDialog(false);\n setNewImageUrl(\"\");\n setNewCombinedPrompt(\"\");\n };\n\n const draggable = isSelected && $isNodeSelection(selection) && !isResizing;\n const isFocused = (isSelected || isResizing) && isEditable;\n\n // Get position-based styles for float layouts\n // Note: Float styles are now applied at the ImageNode.createDOM level for proper text wrapping\n // This component only needs basic positioning\n const getPositionStyles = (): React.CSSProperties => {\n // For floated images, use simpler styles since float is on parent span\n if (position === \"left\" || position === \"right\") {\n return {\n position: 'relative',\n display: 'block',\n width: '100%', // Fill the floated container\n };\n }\n if (position === \"full\") {\n return {\n position: 'relative',\n display: 'block',\n width: '100%',\n };\n }\n // Default: inline-block for regular images\n return {\n position: 'relative',\n display: 'inline-block',\n };\n };\n\n return (\n <Suspense fallback={null}>\n <>\n <div draggable={draggable} style={getPositionStyles()}>\n {isLoadError ? (\n <BrokenImage />\n ) : (\n <LazyImage\n className={\n isFocused\n ? `focused ${$isNodeSelection(selection) ? \"draggable\" : \"\"}`\n : null\n }\n src={src}\n altText={altText}\n imageRef={imageRef}\n width={width}\n height={height}\n maxWidth={maxWidth}\n onError={() => setIsLoadError(true)}\n />\n )}\n {/* Action Buttons - Refine, Open in New Tab and Delete */}\n {isSelected && $isNodeSelection(selection) && !isLoadError && (\n <div className=\"cteditor-absolute cteditor-top-2 cteditor-right-2 cteditor-flex cteditor-gap-2\" style={{ zIndex: 10 }}>\n <button\n onClick={(e) => {\n e.stopPropagation();\n handleRefineClick(e);\n }}\n className=\"cteditor-p-2 cteditor-rounded-md cteditor-bg-background/80 hover:cteditor-bg-accent cteditor-transition-colors cteditor-shadow-md cteditor-border cteditor-border-border\"\n aria-label=\"Refine image\"\n title=\"Refine image\"\n >\n <Sparkles className=\"cteditor-w-4 cteditor-h-4 cteditor-text-foreground\" />\n </button>\n <button\n onClick={(e) => {\n e.stopPropagation();\n handleOpenInNewTab(e);\n }}\n className=\"cteditor-p-2 cteditor-rounded-md cteditor-bg-background/80 hover:cteditor-bg-accent cteditor-transition-colors cteditor-shadow-md cteditor-border cteditor-border-border\"\n aria-label=\"Open image in new tab\"\n title=\"Open in new tab\"\n >\n <ExternalLink className=\"cteditor-w-4 cteditor-h-4 cteditor-text-foreground\" />\n </button>\n <button\n onClick={(e) => {\n e.stopPropagation();\n handleDeleteImage(e);\n }}\n className=\"cteditor-p-2 cteditor-rounded-md cteditor-bg-background/80 hover:cteditor-bg-destructive hover:cteditor-text-destructive-foreground cteditor-transition-colors cteditor-shadow-md cteditor-border cteditor-border-border\"\n aria-label=\"Delete image\"\n title=\"Delete image\"\n >\n <Trash2 className=\"cteditor-w-4 cteditor-h-4 cteditor-text-foreground\" />\n </button>\n </div>\n )}\n {/* Refine Input */}\n {showRefineInput && isSelected && !isLoadError && (\n <div \n className=\"cteditor-absolute cteditor-bottom-2 cteditor-left-2 cteditor-right-2 cteditor-bg-background cteditor-rounded-lg cteditor-shadow-xl cteditor-border cteditor-border-border cteditor-p-3\" \n style={{ zIndex: 10 }}\n onClick={(e) => e.stopPropagation()}\n onKeyDown={(e) => e.stopPropagation()}\n onKeyUp={(e) => e.stopPropagation()}\n >\n <div className=\"cteditor-flex cteditor-flex-col cteditor-gap-2\">\n <label className=\"cteditor-text-xs cteditor-font-medium cteditor-text-foreground\">\n What else do you want in this scene?\n </label>\n <input\n type=\"text\"\n value={refinementPrompt}\n onChange={(e) => setRefinementPrompt(e.target.value)}\n onKeyDown={(e) => {\n // Stop propagation to prevent editor commands from firing\n e.stopPropagation();\n \n if (e.key === 'Enter' && refinementPrompt.trim() && !isRefining) {\n handleRefineImage();\n }\n if (e.key === 'Escape') {\n setShowRefineInput(false);\n setRefinementPrompt(\"\");\n }\n }}\n onKeyUp={(e) => {\n // Also stop propagation on keyup\n e.stopPropagation();\n }}\n onClick={(e) => {\n // Prevent click from bubbling to image selection\n e.stopPropagation();\n }}\n placeholder=\"e.g., flying birds, golden sunset, stormy clouds...\"\n className=\"cteditor-w-full cteditor-px-3 cteditor-py-2 cteditor-text-sm cteditor-border cteditor-border-border cteditor-rounded-md cteditor-bg-background cteditor-text-foreground focus:cteditor-outline-none focus:cteditor-ring-2 focus:cteditor-ring-blue-500\"\n disabled={isRefining}\n autoFocus\n />\n <div className=\"cteditor-flex cteditor-gap-2\">\n <button\n onClick={(e) => {\n e.stopPropagation();\n handleRefineImage();\n }}\n disabled={isRefining || !refinementPrompt.trim()}\n className=\"cteditor-flex-1 cteditor-px-3 cteditor-py-2 cteditor-text-sm cteditor-rounded-md cteditor-bg-blue-500 cteditor-text-white hover:cteditor-bg-blue-600 disabled:cteditor-opacity-50 disabled:cteditor-cursor-not-allowed cteditor-transition-colors\"\n >\n {isRefining ? (\n <span className=\"cteditor-flex cteditor-items-center cteditor-justify-center cteditor-gap-2\">\n <span className=\"cteditor-inline-block cteditor-w-4 cteditor-h-4 cteditor-border-2 cteditor-border-white cteditor-border-t-transparent cteditor-rounded-full cteditor-animate-spin\"></span>\n Refining...\n </span>\n ) : (\n \"Refine Image\"\n )}\n </button>\n <button\n onClick={(e) => {\n e.stopPropagation();\n setShowRefineInput(false);\n setRefinementPrompt(\"\");\n }}\n disabled={isRefining}\n className=\"cteditor-px-3 cteditor-py-2 cteditor-text-sm cteditor-rounded-md cteditor-bg-background cteditor-border cteditor-border-border cteditor-text-foreground hover:cteditor-bg-accent disabled:cteditor-opacity-50 disabled:cteditor-cursor-not-allowed cteditor-transition-colors\"\n >\n Cancel\n </button>\n </div>\n </div>\n </div>\n )}\n </div>\n\n {showCaption && (\n altText.startsWith(\"Signature by\") ? (\n <SignatureCaption caption={caption} />\n ) : (\n <div className=\"image-caption-container\">\n <LexicalNestedComposer\n initialEditor={caption}\n initialNodes={[\n RootNode,\n TextNode,\n LineBreakNode,\n ParagraphNode,\n LinkNode,\n CodeNode,\n ]}\n >\n <AutoFocusPlugin />\n\n <RichTextPlugin\n contentEditable={\n <ContentEditable\n aria-placeholder=\"Enter a caption...\"\n placeholder={() => <span className=\"cteditor-text-xs\">Enter a caption...</span>}\n className=\"ImageNode__contentEditable\"\n />\n }\n ErrorBoundary={LexicalErrorBoundary}\n />\n\n <OnChangePlugin onChange={() => {}} />\n <HistoryPlugin />\n <LocalStoragePlugin namespace={initialConfig.namespace} />\n </LexicalNestedComposer>\n </div>\n )\n )}\n {resizable && $isNodeSelection(selection) && isFocused && (\n <ImageResizer\n showCaption={showCaption}\n setShowCaption={setShowCaption}\n editor={editor}\n buttonRef={buttonRef}\n imageRef={imageRef}\n maxWidth={maxWidth}\n onResizeStart={onResizeStart}\n onResizeEnd={onResizeEnd}\n captionsEnabled={!isLoadError && captionsEnabled}\n />\n )}\n\n {/* Image Comparison Dialog */}\n <ImageComparisonDialog\n open={showComparisonDialog}\n onOpenChange={setShowComparisonDialog}\n oldImageUrl={src}\n newImageUrl={newImageUrl}\n onReplace={handleReplaceImage}\n onCancel={handleCancelReplace}\n />\n </>\n </Suspense>\n );\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -24,7 +24,7 @@ import { TablePlugin } from "@lexical/react/LexicalTablePlugin";
|
|
|
24
24
|
import { TableNode, TableCellNode, TableRowNode, $createTableNodeWithDimensions, $isTableRowNode, $isTableCellNode, TableCellHeaderStates, $isTableNode, $isTableSelection, $getTableCellNodeFromLexicalNode, $getTableNodeFromLexicalNodeOrThrow, getTableElement, getTableObserverFromTableElement, $getTableRowIndexFromTableCellNode, $getNodeTriplet, $insertTableRow__EXPERIMENTAL, $getTableColumnIndexFromTableCellNode, $insertTableColumn__EXPERIMENTAL, $deleteTableRow__EXPERIMENTAL, $deleteTableColumn__EXPERIMENTAL, $unmergeCell, $computeTableMapSkipCellCheck, getDOMCellFromTarget, $getTableAndElementByKey } from "@lexical/table";
|
|
25
25
|
import { mergeRegister, $wrapNodeInElement, $findMatchingParent, $getNearestNodeOfType, $getNearestBlockElementAncestorOrThrow, $insertNodeToNearestRoot, $isEditorIsNestedEditor, mediaFileReader, isMimeType, calculateZoomLevel, CAN_USE_DOM } from "@lexical/utils";
|
|
26
26
|
import Stack from "@mui/material/Stack";
|
|
27
|
-
import { createCommand, DecoratorNode, createEditor, $applyNodeReplacement, $insertNodes, $isRootOrShadowRoot, $createParagraphNode, COMMAND_PRIORITY_EDITOR, COMMAND_PRIORITY_LOW, $getSelection, $isRangeSelection, $getNearestNodeFromDOMNode,
|
|
27
|
+
import { createCommand, DecoratorNode, createEditor, $applyNodeReplacement, $insertNodes, $isRootOrShadowRoot, $createParagraphNode, COMMAND_PRIORITY_EDITOR, COMMAND_PRIORITY_LOW, $getSelection, $isRangeSelection, $getNearestNodeFromDOMNode, isHTMLElement as isHTMLElement$1, TextNode, $getRoot, $createTextNode, $getNodeByKey, $isParagraphNode, $isTextNode, FORMAT_TEXT_COMMAND, FORMAT_ELEMENT_COMMAND, KEY_DOWN_COMMAND, COMMAND_PRIORITY_CRITICAL, CAN_UNDO_COMMAND, CAN_REDO_COMMAND, $isElementNode, SELECTION_CHANGE_COMMAND, UNDO_COMMAND, REDO_COMMAND, KEY_SPACE_COMMAND, $isLineBreakNode, $createRangeSelection, $setSelection, COMMAND_PRIORITY_HIGH, KEY_ARROW_DOWN_COMMAND, KEY_ARROW_UP_COMMAND, KEY_ESCAPE_COMMAND, KEY_TAB_COMMAND, KEY_ENTER_COMMAND, $createNodeSelection, $isNodeSelection, getDOMSelection, CLICK_COMMAND, PASTE_COMMAND, ParagraphNode, $createLineBreakNode, isDOMNode } from "lexical";
|
|
28
28
|
import * as ReactDOM from "react-dom";
|
|
29
29
|
import ReactDOM__default, { createPortal } from "react-dom";
|
|
30
30
|
import { $isCodeNode, CodeNode, normalizeCodeLang, getLanguageFriendlyName, CodeHighlightNode, CODE_LANGUAGE_MAP, $createCodeNode, registerCodeHighlighting, $isCodeHighlightNode } from "@lexical/code";
|
|
@@ -1471,7 +1471,7 @@ const AiTextTransform = async ({ content, apiKey }) => {
|
|
|
1471
1471
|
const AI_ACTION_COMMAND = createCommand(
|
|
1472
1472
|
"AI_ACTION_COMMAND"
|
|
1473
1473
|
);
|
|
1474
|
-
const ImageView = React__default.lazy(() => import("./index-
|
|
1474
|
+
const ImageView = React__default.lazy(() => import("./index-84187412.js"));
|
|
1475
1475
|
function isGoogleDocCheckboxImg(img) {
|
|
1476
1476
|
return img.parentElement != null && img.parentElement.tagName === "LI" && img.previousSibling === null && img.getAttribute("aria-roledescription") === "checkbox";
|
|
1477
1477
|
}
|
|
@@ -9178,19 +9178,19 @@ function CopyButton({ editor, getCodeDOMNode }) {
|
|
|
9178
9178
|
const removeSuccessIcon = useDebounce$1(() => {
|
|
9179
9179
|
setCopyCompleted(false);
|
|
9180
9180
|
}, 1e3);
|
|
9181
|
-
async function handleClick() {
|
|
9181
|
+
async function handleClick(e) {
|
|
9182
|
+
e.preventDefault();
|
|
9183
|
+
e.stopPropagation();
|
|
9182
9184
|
const codeDOMNode = getCodeDOMNode();
|
|
9183
9185
|
if (!codeDOMNode) {
|
|
9184
9186
|
return;
|
|
9185
9187
|
}
|
|
9186
9188
|
let content = "";
|
|
9187
|
-
editor.
|
|
9189
|
+
editor.read(() => {
|
|
9188
9190
|
const codeNode = $getNearestNodeFromDOMNode(codeDOMNode);
|
|
9189
9191
|
if ($isCodeNode(codeNode)) {
|
|
9190
9192
|
content = codeNode.getTextContent();
|
|
9191
9193
|
}
|
|
9192
|
-
const selection = $getSelection();
|
|
9193
|
-
$setSelection(selection);
|
|
9194
9194
|
});
|
|
9195
9195
|
try {
|
|
9196
9196
|
await navigator.clipboard.writeText(content);
|
|
@@ -9200,7 +9200,16 @@ function CopyButton({ editor, getCodeDOMNode }) {
|
|
|
9200
9200
|
console.error("Failed to copy: ", err);
|
|
9201
9201
|
}
|
|
9202
9202
|
}
|
|
9203
|
-
return /* @__PURE__ */ jsx(
|
|
9203
|
+
return /* @__PURE__ */ jsx(
|
|
9204
|
+
"button",
|
|
9205
|
+
{
|
|
9206
|
+
className: "menu-item",
|
|
9207
|
+
onClick: handleClick,
|
|
9208
|
+
onMouseDown: (e) => e.preventDefault(),
|
|
9209
|
+
"aria-label": "copy",
|
|
9210
|
+
children: isCopyCompleted ? /* @__PURE__ */ jsx("i", { className: "format success" }) : /* @__PURE__ */ jsx("i", { className: "format copy" })
|
|
9211
|
+
}
|
|
9212
|
+
);
|
|
9204
9213
|
}
|
|
9205
9214
|
const index$7 = "";
|
|
9206
9215
|
const PRETTIER_PARSER_MODULES = {
|
|
@@ -9250,13 +9259,15 @@ function getPrettierOptions(lang) {
|
|
|
9250
9259
|
function PrettierButton({ lang, editor, getCodeDOMNode }) {
|
|
9251
9260
|
const [syntaxError, setSyntaxError] = useState$1("");
|
|
9252
9261
|
const [tipsVisible, setTipsVisible] = useState$1(false);
|
|
9253
|
-
async function handleClick() {
|
|
9262
|
+
async function handleClick(e) {
|
|
9263
|
+
e.preventDefault();
|
|
9264
|
+
e.stopPropagation();
|
|
9254
9265
|
const codeDOMNode = getCodeDOMNode();
|
|
9255
9266
|
if (!codeDOMNode) {
|
|
9256
9267
|
return;
|
|
9257
9268
|
}
|
|
9258
9269
|
let content = "";
|
|
9259
|
-
editor.
|
|
9270
|
+
editor.read(() => {
|
|
9260
9271
|
const codeNode = $getNearestNodeFromDOMNode(codeDOMNode);
|
|
9261
9272
|
if ($isCodeNode(codeNode)) {
|
|
9262
9273
|
content = codeNode.getTextContent();
|
|
@@ -9267,12 +9278,26 @@ function PrettierButton({ lang, editor, getCodeDOMNode }) {
|
|
|
9267
9278
|
}
|
|
9268
9279
|
try {
|
|
9269
9280
|
const format = await loadPrettierFormat();
|
|
9270
|
-
|
|
9271
|
-
|
|
9281
|
+
let options = getPrettierOptions(lang);
|
|
9282
|
+
let prettierParsers = await loadPrettierParserByLang(lang);
|
|
9272
9283
|
options.plugins = prettierParsers.map(
|
|
9273
9284
|
(parser) => parser.default || parser
|
|
9274
9285
|
);
|
|
9275
|
-
|
|
9286
|
+
let formattedCode;
|
|
9287
|
+
try {
|
|
9288
|
+
formattedCode = await format(content, options);
|
|
9289
|
+
} catch (firstError) {
|
|
9290
|
+
if (lang === "js" && firstError instanceof Error && (firstError.message.includes("Unexpected token") || firstError.message.includes("expected"))) {
|
|
9291
|
+
options = getPrettierOptions("typescript");
|
|
9292
|
+
prettierParsers = await loadPrettierParserByLang("typescript");
|
|
9293
|
+
options.plugins = prettierParsers.map(
|
|
9294
|
+
(parser) => parser.default || parser
|
|
9295
|
+
);
|
|
9296
|
+
formattedCode = await format(content, options);
|
|
9297
|
+
} else {
|
|
9298
|
+
throw firstError;
|
|
9299
|
+
}
|
|
9300
|
+
}
|
|
9276
9301
|
editor.update(() => {
|
|
9277
9302
|
const codeNode = $getNearestNodeFromDOMNode(codeDOMNode);
|
|
9278
9303
|
if ($isCodeNode(codeNode)) {
|
|
@@ -9281,7 +9306,7 @@ function PrettierButton({ lang, editor, getCodeDOMNode }) {
|
|
|
9281
9306
|
setSyntaxError("");
|
|
9282
9307
|
setTipsVisible(false);
|
|
9283
9308
|
}
|
|
9284
|
-
});
|
|
9309
|
+
}, { discrete: true, tag: "prettier-format" });
|
|
9285
9310
|
} catch (error) {
|
|
9286
9311
|
setError(error);
|
|
9287
9312
|
}
|
|
@@ -9310,6 +9335,7 @@ function PrettierButton({ lang, editor, getCodeDOMNode }) {
|
|
|
9310
9335
|
{
|
|
9311
9336
|
className: "menu-item",
|
|
9312
9337
|
onClick: handleClick,
|
|
9338
|
+
onMouseDown: (e) => e.preventDefault(),
|
|
9313
9339
|
onMouseEnter: handleMouseEnter,
|
|
9314
9340
|
onMouseLeave: handleMouseLeave,
|
|
9315
9341
|
"aria-label": "prettier",
|
|
@@ -15337,7 +15363,7 @@ const EmbedComponent = ({ url, displayType, alignment, nodeKey }) => {
|
|
|
15337
15363
|
}
|
|
15338
15364
|
);
|
|
15339
15365
|
};
|
|
15340
|
-
const FileComponent = React$1.lazy(() => import("./index-
|
|
15366
|
+
const FileComponent = React$1.lazy(() => import("./index-bf836d7a.js"));
|
|
15341
15367
|
function convertFileElement(domNode) {
|
|
15342
15368
|
if (domNode instanceof HTMLDivElement) {
|
|
15343
15369
|
const dataUrl = domNode.getAttribute("data-lexical-file-src");
|
|
@@ -20360,10 +20386,10 @@ const PDF_CONFIG = {
|
|
|
20360
20386
|
};
|
|
20361
20387
|
const loadHtml2Pdf = async () => {
|
|
20362
20388
|
try {
|
|
20363
|
-
const mod = await import("./html2pdf.bundle.min-
|
|
20389
|
+
const mod = await import("./html2pdf.bundle.min-83517dc2.js").then((n) => n.h);
|
|
20364
20390
|
return (mod == null ? void 0 : mod.default) || mod;
|
|
20365
20391
|
} catch {
|
|
20366
|
-
const mod2 = await import("./html2pdf.bundle-
|
|
20392
|
+
const mod2 = await import("./html2pdf.bundle-3699b235.js").then((n) => n.h);
|
|
20367
20393
|
return (mod2 == null ? void 0 : mod2.default) || mod2;
|
|
20368
20394
|
}
|
|
20369
20395
|
};
|
|
@@ -37232,7 +37258,7 @@ function applyGenericSafeStyles(container, codeBlockStyles) {
|
|
|
37232
37258
|
addStyle(allSelectors, "line-height: 1.5;");
|
|
37233
37259
|
addStyleIfNotSetOnElementOrChildren(blockSelectors, "font-family", defaultFontFamily);
|
|
37234
37260
|
addStyleIfNotSet("table, p, li, td, th, div", "font-size", "16px");
|
|
37235
|
-
addStyle("p", "margin: 0
|
|
37261
|
+
addStyle("p", "margin: 0;");
|
|
37236
37262
|
addStyle("th p, td p", "margin: 0; padding: 0;");
|
|
37237
37263
|
addStyle(
|
|
37238
37264
|
"table",
|
|
@@ -38545,4 +38571,4 @@ export {
|
|
|
38545
38571
|
useHtmlView as u,
|
|
38546
38572
|
verifyApiKey as v
|
|
38547
38573
|
};
|
|
38548
|
-
//# sourceMappingURL=index-
|
|
38574
|
+
//# sourceMappingURL=index-9a8a49b6.js.map
|