eddyter 1.3.43 → 1.3.44

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 { RootNode, TextNode, LineBreakNode, ParagraphNode, $getSelection, $isNodeSelection, $isParagraphNode, $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, useEffect, useCallback, Suspense } from "react";
18
- import { a as createLucideIcon, b as Dialog, d as DialogContent, e as DialogHeader, f as DialogTitle, h as DialogDescription, i as DialogFooter, B as Button, L as LocalStoragePlugin, j as initialConfig, k as $isImageNode, A as AlignLeftIcon, l as AlignCenterIcon, m as AlignRightIcon, n as Type, S as Sparkles, E as ExternalLink, T as Trash2, t as toast, o as AiJsonResponse, p as ApiKeyRequiredError, C as CreditError } from "./index-636eff7f.js";
18
+ import { d as createLucideIcon, e as Dialog, f as DialogContent, h as DialogHeader, i as DialogTitle, j as DialogDescription, k as DialogFooter, B as Button, L as LocalStoragePlugin, l as initialConfig, m as $isImageNode, W as WrapTextLeftIcon, n as WrapTextRightIcon, A as AlignLeftIcon, o as AlignCenterIcon, p as AlignRightIcon, q as Type, r as LinkIcon, S as Sparkles, E as ExternalLinkIcon, s as TrashIcon, t as toast, u as AiJsonResponse, v as ApiKeyRequiredError, C as CreditError } from "./index-6eb4d179.js";
19
19
  import "axios";
20
20
  import "react-dom";
21
21
  import "@emotion/styled";
@@ -30,11 +30,6 @@ import "@lexical/list";
30
30
  import "@lexical/rich-text";
31
31
  import "@lexical/selection";
32
32
  import "@lexical/react/LexicalHorizontalRuleNode";
33
- import "@mui/icons-material/Description";
34
- import "@mui/icons-material/FolderZip";
35
- import "@mui/icons-material/InsertChart";
36
- import "@mui/icons-material/InsertDriveFile";
37
- import "@mui/icons-material/PictureAsPdf";
38
33
  import "@lexical/react/LexicalDecoratorBlockNode";
39
34
  import "emoji-picker-react";
40
35
  import "@lexical/react/LexicalLinkPlugin";
@@ -50,18 +45,6 @@ const Link2 = createLucideIcon("Link2", [
50
45
  ["path", { d: "M15 7h2a5 5 0 1 1 0 10h-2", key: "1b9ql8" }],
51
46
  ["line", { x1: "8", x2: "16", y1: "12", y2: "12", key: "1jonct" }]
52
47
  ]);
53
- /**
54
- * @license lucide-react v0.344.0 - ISC
55
- *
56
- * This source code is licensed under the ISC license.
57
- * See the LICENSE file in the root directory of this source tree.
58
- */
59
- const WrapText = createLucideIcon("WrapText", [
60
- ["line", { x1: "3", x2: "21", y1: "6", y2: "6", key: "4m8b97" }],
61
- ["path", { d: "M3 12h15a3 3 0 1 1 0 6h-4", key: "1cl7v7" }],
62
- ["polyline", { points: "16 16 14 18 16 20", key: "1jznyi" }],
63
- ["line", { x1: "3", x2: "10", y1: "18", y2: "18", key: "1h33wv" }]
64
- ]);
65
48
  const imageCaptionStyles = "";
66
49
  const ImageComparisonDialog = ({
67
50
  open,
@@ -1040,20 +1023,20 @@ function ImageComponent({
1040
1023
  "button",
1041
1024
  {
1042
1025
  onClick: (e) => handlePositionChange(e, "left"),
1043
- className: `cteditor-p-1.5 cteditor-rounded hover:cteditor-bg-accent cteditor-transition-colors ${position === "left" ? "cteditor-bg-accent" : ""}`,
1026
+ className: ` cteditor-size-6 cteditor-flex cteditor-items-center cteditor-justify-center cteditor-rounded hover:cteditor-bg-accent cteditor-transition-colors ${position === "left" ? "cteditor-bg-accent" : ""}`,
1044
1027
  "aria-label": "Wrap text left",
1045
1028
  title: "Wrap text left",
1046
- children: /* @__PURE__ */ jsx(WrapText, { className: "cteditor-w-4 cteditor-h-4 cteditor-text-foreground", style: { transform: "scaleX(-1)" } })
1029
+ children: /* @__PURE__ */ jsx(WrapTextLeftIcon, {})
1047
1030
  }
1048
1031
  ),
1049
1032
  /* @__PURE__ */ jsx(
1050
1033
  "button",
1051
1034
  {
1052
1035
  onClick: (e) => handlePositionChange(e, "right"),
1053
- className: `cteditor-p-1.5 cteditor-rounded hover:cteditor-bg-accent cteditor-transition-colors ${position === "right" ? "cteditor-bg-accent" : ""}`,
1036
+ className: ` cteditor-size-6 cteditor-flex cteditor-items-center cteditor-justify-center cteditor-rounded hover:cteditor-bg-accent cteditor-transition-colors ${position === "right" ? "cteditor-bg-accent" : ""}`,
1054
1037
  "aria-label": "Wrap text right",
1055
1038
  title: "Wrap text right",
1056
- children: /* @__PURE__ */ jsx(WrapText, { className: "cteditor-w-4 cteditor-h-4 cteditor-text-foreground" })
1039
+ children: /* @__PURE__ */ jsx(WrapTextRightIcon, {})
1057
1040
  }
1058
1041
  ),
1059
1042
  /* @__PURE__ */ jsx("div", { className: "cteditor-w-px cteditor-h-5 cteditor-bg-border cteditor-mx-0.5" }),
@@ -1061,7 +1044,7 @@ function ImageComponent({
1061
1044
  "button",
1062
1045
  {
1063
1046
  onClick: (e) => handlePositionChange(e, "inline-left"),
1064
- className: `cteditor-p-1.5 cteditor-rounded hover:cteditor-bg-accent cteditor-transition-colors ${position === "inline-left" ? "cteditor-bg-accent" : ""}`,
1047
+ className: `cteditor-size-6 cteditor-flex cteditor-items-center cteditor-justify-center cteditor-rounded hover:cteditor-bg-accent cteditor-transition-colors ${position === "inline-left" ? "cteditor-bg-accent" : ""}`,
1065
1048
  "aria-label": "Align left",
1066
1049
  title: "Align left (no text wrap)",
1067
1050
  children: /* @__PURE__ */ jsx(AlignLeftIcon, {})
@@ -1071,7 +1054,7 @@ function ImageComponent({
1071
1054
  "button",
1072
1055
  {
1073
1056
  onClick: (e) => handlePositionChange(e, "inline-center"),
1074
- className: `cteditor-p-1.5 cteditor-rounded hover:cteditor-bg-accent cteditor-transition-colors ${position === "inline-center" || position === "full" ? "cteditor-bg-accent" : ""}`,
1057
+ className: `cteditor-size-6 cteditor-flex cteditor-items-center cteditor-justify-center cteditor-rounded hover:cteditor-bg-accent cteditor-transition-colors ${position === "inline-center" || position === "full" ? "cteditor-bg-accent" : ""}`,
1075
1058
  "aria-label": "Align center",
1076
1059
  title: "Align center (no text wrap)",
1077
1060
  children: /* @__PURE__ */ jsx(AlignCenterIcon, {})
@@ -1081,7 +1064,7 @@ function ImageComponent({
1081
1064
  "button",
1082
1065
  {
1083
1066
  onClick: (e) => handlePositionChange(e, "inline-right"),
1084
- className: `cteditor-p-1.5 cteditor-rounded hover:cteditor-bg-accent cteditor-transition-colors ${position === "inline-right" ? "cteditor-bg-accent" : ""}`,
1067
+ className: `cteditor-size-6 cteditor-flex cteditor-items-center cteditor-justify-center cteditor-rounded hover:cteditor-bg-accent cteditor-transition-colors ${position === "inline-right" ? "cteditor-bg-accent" : ""}`,
1085
1068
  "aria-label": "Align right",
1086
1069
  title: "Align right (no text wrap)",
1087
1070
  children: /* @__PURE__ */ jsx(AlignRightIcon, {})
@@ -1092,7 +1075,7 @@ function ImageComponent({
1092
1075
  "button",
1093
1076
  {
1094
1077
  onClick: (e) => handlePositionChange(e, "none"),
1095
- className: `cteditor-p-1.5 cteditor-rounded hover:cteditor-bg-accent cteditor-transition-colors ${position === "none" ? "cteditor-bg-accent" : ""}`,
1078
+ className: `cteditor-size-6 cteditor-flex cteditor-items-center cteditor-justify-center cteditor-rounded hover:cteditor-bg-accent cteditor-transition-colors ${position === "none" ? "cteditor-bg-accent" : ""}`,
1096
1079
  "aria-label": "Inline",
1097
1080
  title: "Inline with text",
1098
1081
  children: /* @__PURE__ */ jsx(Type, { className: "cteditor-w-4 cteditor-h-4 cteditor-text-foreground" })
@@ -1103,10 +1086,10 @@ function ImageComponent({
1103
1086
  "button",
1104
1087
  {
1105
1088
  onClick: handleLinkClick,
1106
- 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",
1089
+ className: " cteditor-size-6 cteditor-flex cteditor-items-center cteditor-justify-center cteditor-rounded-md cteditor-bg-background/80 hover:cteditor-bg-accent cteditor-transition-colors cteditor-shadow-md cteditor-border cteditor-border-border",
1107
1090
  "aria-label": "Visit link",
1108
1091
  title: `Visit: ${linkUrl}`,
1109
- children: /* @__PURE__ */ jsx(Link2, { className: "cteditor-w-4 cteditor-h-4 cteditor-text-foreground" })
1092
+ children: /* @__PURE__ */ jsx(LinkIcon, {})
1110
1093
  }
1111
1094
  ),
1112
1095
  originalPrompt && /* @__PURE__ */ jsx(
@@ -1116,7 +1099,7 @@ function ImageComponent({
1116
1099
  e.stopPropagation();
1117
1100
  handleRefineClick(e);
1118
1101
  },
1119
- 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",
1102
+ className: " cteditor-size-6 cteditor-flex cteditor-items-center cteditor-justify-center cteditor-rounded-md cteditor-bg-background/80 hover:cteditor-bg-accent cteditor-transition-colors cteditor-shadow-md cteditor-border cteditor-border-border",
1120
1103
  "aria-label": "Refine image",
1121
1104
  title: "Refine image",
1122
1105
  children: /* @__PURE__ */ jsx(Sparkles, { className: "cteditor-w-4 cteditor-h-4 cteditor-text-foreground" })
@@ -1129,10 +1112,10 @@ function ImageComponent({
1129
1112
  e.stopPropagation();
1130
1113
  handleOpenInNewTab(e);
1131
1114
  },
1132
- 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",
1115
+ className: " cteditor-size-8 cteditor-flex cteditor-items-center cteditor-justify-center cteditor-rounded-md cteditor-bg-background/80 hover:cteditor-bg-accent cteditor-transition-colors cteditor-shadow-md cteditor-border cteditor-border-border",
1133
1116
  "aria-label": "Open image in new tab",
1134
1117
  title: "Open in new tab",
1135
- children: /* @__PURE__ */ jsx(ExternalLink, { className: "cteditor-w-4 cteditor-h-4 cteditor-text-foreground" })
1118
+ children: /* @__PURE__ */ jsx(ExternalLinkIcon, {})
1136
1119
  }
1137
1120
  ),
1138
1121
  /* @__PURE__ */ jsx(
@@ -1142,10 +1125,10 @@ function ImageComponent({
1142
1125
  e.stopPropagation();
1143
1126
  handleDeleteImage(e);
1144
1127
  },
1145
- 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",
1128
+ className: " cteditor-size-8 cteditor-flex cteditor-items-center cteditor-justify-center 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",
1146
1129
  "aria-label": "Delete image",
1147
1130
  title: "Delete image",
1148
- children: /* @__PURE__ */ jsx(Trash2, { className: "cteditor-w-4 cteditor-h-4 cteditor-text-foreground" })
1131
+ children: /* @__PURE__ */ jsx(TrashIcon, {})
1149
1132
  }
1150
1133
  )
1151
1134
  ]
@@ -1296,4 +1279,4 @@ export {
1296
1279
  RIGHT_CLICK_IMAGE_COMMAND,
1297
1280
  ImageComponent as default
1298
1281
  };
1299
- //# sourceMappingURL=index-34ac313f.js.map
1282
+ //# sourceMappingURL=index-92744040.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index-92744040.js","sources":["../../../node_modules/.pnpm/lucide-react@0.344.0_react@18.3.1/node_modules/lucide-react/dist/esm/icons/link-2.js","../src/components/ImageComparisonDialog/index.tsx","../src/components/SignatureCaption/index.tsx","../src/components/ImageView/ImageResizer.tsx","../src/components/ImageView/index.tsx"],"sourcesContent":["/**\n * @license lucide-react v0.344.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Link2 = createLucideIcon(\"Link2\", [\n [\"path\", { d: \"M9 17H7A5 5 0 0 1 7 7h2\", key: \"8i5ue5\" }],\n [\"path\", { d: \"M15 7h2a5 5 0 1 1 0 10h-2\", key: \"1b9ql8\" }],\n [\"line\", { x1: \"8\", x2: \"16\", y1: \"12\", y2: \"12\", key: \"1jonct\" }]\n]);\n\nexport { Link2 as default };\n//# sourceMappingURL=link-2.js.map\n","import React from \"react\";\r\nimport { Button } from \"../ui/button\";\r\nimport {\r\n Dialog,\r\n DialogContent,\r\n DialogDescription,\r\n DialogFooter,\r\n DialogHeader,\r\n DialogTitle,\r\n} from \"../ui/dialog\";\r\n\r\ninterface ImageComparisonDialogProps {\r\n open: boolean;\r\n onOpenChange: (open: boolean) => void;\r\n oldImageUrl: string;\r\n newImageUrl: string;\r\n onReplace: () => void;\r\n onCancel: () => void;\r\n}\r\n\r\nexport const ImageComparisonDialog: React.FC<ImageComparisonDialogProps> = ({\r\n open,\r\n onOpenChange,\r\n oldImageUrl,\r\n newImageUrl,\r\n onReplace,\r\n onCancel,\r\n}) => {\r\n return (\r\n <Dialog open={open} onOpenChange={onOpenChange}>\r\n <DialogContent className=\"sm:max-w-[800px] max-h-[90vh] overflow-y-auto\">\r\n <DialogHeader>\r\n <DialogTitle className=\"flex items-center gap-2 text-xl\">\r\n <span className=\"text-2xl\">🔄</span>\r\n Compare Images\r\n </DialogTitle>\r\n <DialogDescription className=\"text-sm pt-1\">\r\n Choose whether to replace the original image with the refined version.\r\n </DialogDescription>\r\n </DialogHeader>\r\n\r\n <div className=\"space-y-4 py-4\">\r\n <div className=\"grid grid-cols-2 gap-4\">\r\n\r\n {/* New Image */}\r\n <div className=\"space-y-2\">\r\n <div className=\"flex items-center justify-between\">\r\n <span className=\"text-sm font-semibold text-gray-700 dark:text-gray-300\">\r\n Refined Image\r\n </span>\r\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\">\r\n New\r\n </span>\r\n </div>\r\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\">\r\n <img\r\n src={newImageUrl}\r\n alt=\"Refined\"\r\n className=\"w-full h-full object-contain\"\r\n />\r\n </div>\r\n </div>\r\n </div>\r\n\r\n {/* Info */}\r\n <div className=\"p-3 rounded-lg bg-blue-50 dark:bg-blue-950/20 border border-blue-200 dark:border-blue-800\">\r\n <p className=\"text-sm text-blue-800 dark:text-blue-200\">\r\n <span className=\"font-semibold\">Note:</span> Clicking \"Replace\" will update the image in your document.\r\n This action cannot be undone.\r\n </p>\r\n </div>\r\n </div>\r\n\r\n <DialogFooter className=\"gap-2\">\r\n <Button\r\n variant=\"outline\"\r\n onClick={onCancel}\r\n >\r\n Keep Original\r\n </Button>\r\n <Button\r\n onClick={onReplace}\r\n className=\"bg-blue-500 hover:bg-blue-600 text-white\"\r\n >\r\n <span className=\"mr-2\">✓</span>\r\n Replace Image\r\n </Button>\r\n </DialogFooter>\r\n </DialogContent>\r\n </Dialog>\r\n );\r\n};\r\n\r\n","/**\r\n * SignatureCaption Component\r\n * A premium styled caption component specifically for signatures\r\n */\r\n\r\nimport \"./signature-caption.css\";\r\n\r\nimport { CodeNode } from \"@lexical/code\";\r\nimport { LinkNode } from \"@lexical/link\";\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\nimport { RichTextPlugin } from \"@lexical/react/LexicalRichTextPlugin\";\r\nimport type { LexicalEditor } from \"lexical\";\r\nimport { LineBreakNode, ParagraphNode, RootNode, TextNode } from \"lexical\";\r\nimport { initialConfig } from \"src/constants\";\r\nimport LocalStoragePlugin from \"src/plugins/LocalStoragePlugin\";\r\n\r\ninterface SignatureCaptionProps {\r\n caption: LexicalEditor;\r\n}\r\n\r\nexport default function SignatureCaption({\r\n caption,\r\n}: SignatureCaptionProps): JSX.Element {\r\n return (\r\n <div className=\"signature-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 <RichTextPlugin\r\n contentEditable={\r\n <ContentEditable\r\n aria-placeholder=\"Enter signature name...\"\r\n placeholder={\r\n <div style={{\r\n position: 'absolute',\r\n top: '4px',\r\n left: '8px',\r\n right: '8px',\r\n textAlign: 'center',\r\n pointerEvents: 'none',\r\n color: 'hsla(var(--cteditorf47ac10b-foreground) / 0.4)',\r\n fontStyle: 'italic'\r\n }}>\r\n Enter signature name...\r\n </div>\r\n }\r\n className=\"signature-caption-editable\"\r\n />\r\n }\r\n ErrorBoundary={LexicalErrorBoundary}\r\n />\r\n\r\n <OnChangePlugin onChange={() => {\r\n // Placeholder for future change handling\r\n }} />\r\n <HistoryPlugin />\r\n <LocalStoragePlugin namespace={initialConfig.namespace} />\r\n </LexicalNestedComposer>\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 { 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 $isParagraphNode,\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 { ExternalLink, Link2, Sparkles, Trash2, Type, WrapText } from \"lucide-react\";\r\n\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 { toast } from \"sonner\";\r\nimport { initialConfig } from \"src/constants\";\r\nimport { $isImageNode, ImagePosition } from \"src/nodes/ImageNode\";\r\nimport LocalStoragePlugin from \"src/plugins/LocalStoragePlugin\";\r\n\r\nimport { AiJsonResponse, ApiKeyRequiredError, CreditError } from \"../../api/ai\";\r\nimport { ImageComparisonDialog } from \"../ImageComparisonDialog\";\r\nimport SignatureCaption from \"../SignatureCaption\";\r\nimport { AlignCenterIcon, AlignLeftIcon, AlignRightIcon, ExternalLinkIcon, LinkIcon, TrashIcon, WrapTextLeftIcon, WrapTextRightIcon } from \"src/ui/Icons\";\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 =\r\n 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\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 has set a numeric size or original dimensions are provided\r\n width: computedWidth,\r\n height: computedHeight,\r\n maxWidth: \"100%\",\r\n }\r\n : {\r\n // No dimensions specified - use original image size\r\n maxWidth: \"100%\",\r\n height: \"auto\",\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 originalPrompt,\r\n position = \"none\",\r\n linkUrl,\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 originalPrompt?: string;\r\n position?: ImagePosition;\r\n linkUrl?: string;\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 const [showRefineInput, setShowRefineInput] = useState<boolean>(false);\r\n const [refinementPrompt, setRefinementPrompt] = useState<string>(\"\");\r\n const [isRefining, setIsRefining] = useState<boolean>(false);\r\n const [showComparisonDialog, setShowComparisonDialog] =\r\n useState<boolean>(false);\r\n const [newImageUrl, setNewImageUrl] = useState<string>(\"\");\r\n const [newCombinedPrompt, setNewCombinedPrompt] = useState<string>(\"\");\r\n const [showLinkPreview, setShowLinkPreview] = useState<boolean>(false);\r\n const linkPreviewTimeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);\r\n const [imageWidth, setImageWidth] = useState<number>(0);\r\n\r\n // Position toolbar below image when it's small (under 350px)\r\n const shouldPositionBelow = imageWidth > 0 && imageWidth < 350;\r\n\r\n // Update image width when it changes\r\n useEffect(() => {\r\n if (imageRef.current) {\r\n const updateWidth = () => {\r\n if (imageRef.current) {\r\n setImageWidth(imageRef.current.offsetWidth);\r\n }\r\n };\r\n updateWidth();\r\n\r\n // Also observe for size changes\r\n const resizeObserver = new ResizeObserver(updateWidth);\r\n resizeObserver.observe(imageRef.current);\r\n\r\n return () => resizeObserver.disconnect();\r\n }\r\n }, [width, height, isSelected]);\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 // Get parent before removing to reset alignment if needed\r\n const parent = node.getParent();\r\n node.remove();\r\n // Reset paragraph alignment to left after removing centered image\r\n if (parent && $isParagraphNode(parent) && parent.getChildrenSize() === 0) {\r\n parent.setFormat(\"left\");\r\n }\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\r\n const target = event.target as HTMLElement;\r\n\r\n // Check if clicking directly on this image element\r\n const isClickOnImage = target === imageRef.current;\r\n\r\n // Also check if click coordinates are within the image bounds\r\n // This handles cases where inline images next to text might not receive direct clicks\r\n let isClickWithinImageBounds = false;\r\n if (!isClickOnImage && imageRef.current) {\r\n const imageRect = imageRef.current.getBoundingClientRect();\r\n isClickWithinImageBounds =\r\n event.clientX >= imageRect.left &&\r\n event.clientX <= imageRect.right &&\r\n event.clientY >= imageRect.top &&\r\n event.clientY <= imageRect.bottom;\r\n }\r\n\r\n if (isClickOnImage || isClickWithinImageBounds) {\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 // 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 handleOpenInNewTab = (e: React.MouseEvent) => {\r\n e.preventDefault();\r\n e.stopPropagation();\r\n\r\n // Check if it's a data URL (base64)\r\n if (src.startsWith(\"data:\")) {\r\n // For data URLs, we need to open them in a new tab with the image displayed\r\n const newWindow = window.open(\"\", \"_blank\");\r\n if (newWindow) {\r\n newWindow.document.write(`\r\n <!DOCTYPE html>\r\n <html>\r\n <head>\r\n <title>${altText || \"Image\"}</title>\r\n <style>\r\n body {\r\n margin: 0;\r\n display: flex;\r\n justify-content: center;\r\n align-items: center;\r\n min-height: 100vh;\r\n background-color: #1a1a1a;\r\n }\r\n img {\r\n max-width: 100%;\r\n max-height: 100vh;\r\n object-fit: contain;\r\n }\r\n </style>\r\n </head>\r\n <body>\r\n <img src=\"${src}\" alt=\"${altText || \"Image\"}\" />\r\n </body>\r\n </html>\r\n `);\r\n newWindow.document.close();\r\n }\r\n } else {\r\n // For regular URLs, just open them directly\r\n window.open(src, \"_blank\");\r\n }\r\n };\r\n\r\n const handleDeleteImage = (e: React.MouseEvent) => {\r\n e.preventDefault();\r\n e.stopPropagation();\r\n\r\n editor.update(() => {\r\n const node = $getNodeByKey(nodeKey);\r\n if ($isImageNode(node)) {\r\n // Get parent before removing to reset alignment if needed\r\n const parent = node.getParent();\r\n node.remove();\r\n // Reset paragraph alignment to left after removing centered image\r\n if (parent && $isParagraphNode(parent) && parent.getChildrenSize() === 0) {\r\n parent.setFormat(\"left\");\r\n }\r\n }\r\n });\r\n };\r\n\r\n const handlePositionChange = (e: React.MouseEvent, newPosition: ImagePosition) => {\r\n e.preventDefault();\r\n e.stopPropagation();\r\n\r\n editor.update(() => {\r\n const node = $getNodeByKey(nodeKey);\r\n if ($isImageNode(node)) {\r\n node.setPosition(newPosition);\r\n }\r\n });\r\n };\r\n\r\n const handleRefineClick = (e: React.MouseEvent) => {\r\n e.preventDefault();\r\n e.stopPropagation();\r\n setShowRefineInput(!showRefineInput);\r\n };\r\n\r\n // Link preview hover handlers\r\n const handleImageMouseEnter = useCallback(() => {\r\n if (linkUrl && !isSelected) {\r\n // Delay showing the link preview to avoid flickering on quick mouse movements\r\n linkPreviewTimeoutRef.current = setTimeout(() => {\r\n setShowLinkPreview(true);\r\n }, 300);\r\n }\r\n }, [linkUrl, isSelected]);\r\n\r\n const handleImageMouseLeave = useCallback(() => {\r\n // Clear the timeout if mouse leaves before preview shows\r\n if (linkPreviewTimeoutRef.current) {\r\n clearTimeout(linkPreviewTimeoutRef.current);\r\n linkPreviewTimeoutRef.current = null;\r\n }\r\n setShowLinkPreview(false);\r\n }, []);\r\n\r\n const handleLinkClick = useCallback((e: React.MouseEvent) => {\r\n e.preventDefault();\r\n e.stopPropagation();\r\n if (linkUrl) {\r\n window.open(linkUrl, \"_blank\", \"noopener,noreferrer\");\r\n }\r\n }, [linkUrl]);\r\n\r\n // Clean up timeout on unmount\r\n useEffect(() => {\r\n return () => {\r\n if (linkPreviewTimeoutRef.current) {\r\n clearTimeout(linkPreviewTimeoutRef.current);\r\n }\r\n };\r\n }, []);\r\n\r\n const handleRefineImage = async () => {\r\n if (!refinementPrompt.trim() || isRefining) return;\r\n\r\n setIsRefining(true);\r\n\r\n // Show loading toast\r\n const loadingToast = toast.loading(\"Refining image...\", {\r\n description: \"This may take 10-30 seconds. Please wait.\",\r\n });\r\n\r\n try {\r\n // Intelligently combine original prompt with refinement\r\n let combinedPrompt = refinementPrompt.trim();\r\n\r\n // Check if we have an original prompt\r\n if (originalPrompt && originalPrompt.trim()) {\r\n const original = originalPrompt.trim();\r\n const refinement = refinementPrompt.trim();\r\n\r\n // Remove common \"add\" prefixes from refinement\r\n const cleanedRefinement = refinement\r\n .replace(/^(add|also add|include|with|and)\\s+(some|a|an)\\s+/gi, \"\")\r\n .replace(/^(add|also add|include|with|and)\\s+/gi, \"\")\r\n .trim();\r\n\r\n // Simple and clear combination - just list both elements\r\n // This is the most reliable format for DALL-E\r\n combinedPrompt = `${original} with ${cleanedRefinement}`;\r\n } else {\r\n // No original prompt (image was created before this feature)\r\n // Try to use altText or just use the refinement as-is\r\n if (altText && altText !== \"Generated image\" && altText.trim()) {\r\n // Use altText as the original description\r\n const cleanedRefinement = refinementPrompt\r\n .trim()\r\n .replace(/^(add|also add|include|with|and)\\s+(some|a|an)\\s+/gi, \"\")\r\n .replace(/^(add|also add|include|with|and)\\s+/gi, \"\")\r\n .trim();\r\n combinedPrompt = `${altText} with ${cleanedRefinement}`;\r\n }\r\n // else: Just use the refinement prompt as-is\r\n }\r\n\r\n // Generate refined image with combined prompt\r\n const response = await AiJsonResponse({\r\n content: `Generate Image: ${combinedPrompt}`,\r\n });\r\n const htmlString = response?.data;\r\n\r\n if (!htmlString) {\r\n throw new Error(\"Failed to generate image - empty response\");\r\n }\r\n\r\n // Extract image URL from HTML response\r\n const parser = new DOMParser();\r\n const dom = parser.parseFromString(htmlString, \"text/html\");\r\n const imgElement = dom.querySelector(\"img\");\r\n\r\n if (!imgElement || !imgElement.src) {\r\n throw new Error(`No image found in response`);\r\n }\r\n\r\n const generatedImageUrl = imgElement.src;\r\n\r\n // Dismiss loading toast and show success\r\n toast.dismiss(loadingToast);\r\n toast.success(\"Image refined successfully!\", {\r\n description: \"Compare the images and choose which to keep.\",\r\n });\r\n\r\n // Store new image URL, combined prompt, and show comparison dialog\r\n setNewImageUrl(generatedImageUrl);\r\n setNewCombinedPrompt(combinedPrompt);\r\n setShowComparisonDialog(true);\r\n\r\n // Clear refinement input and close it\r\n setRefinementPrompt(\"\");\r\n setShowRefineInput(false);\r\n } catch (error) {\r\n // Dismiss loading toast and show error\r\n toast.dismiss(loadingToast);\r\n\r\n // Handle specific error types with appropriate messages\r\n if (error instanceof ApiKeyRequiredError) {\r\n // Use different title for disabled vs missing keys\r\n const title = error.code === 'API_KEYS_DISABLED' ? \"API Keys Disabled\" : \"API Key Required\";\r\n toast.error(title, {\r\n description: error.message,\r\n duration: 8000,\r\n });\r\n } else if (error instanceof CreditError) {\r\n toast.error(\"Credits Issue\", {\r\n description: error.message,\r\n duration: 8000,\r\n });\r\n } else {\r\n toast.error(\"Failed to refine image\", {\r\n description:\r\n error instanceof Error\r\n ? error.message\r\n : \"Unknown error. Please try again.\",\r\n });\r\n }\r\n } finally {\r\n setIsRefining(false);\r\n }\r\n };\r\n\r\n const handleReplaceImage = () => {\r\n // Update the image node with new URL and updated prompt\r\n editor.update(() => {\r\n const node = $getNodeByKey(nodeKey);\r\n if ($isImageNode(node)) {\r\n // Use setter methods which properly call getWritable()\r\n node.setSrc(newImageUrl);\r\n node.setOriginalPrompt(newCombinedPrompt);\r\n\r\n // Force Lexical to re-render the DecoratorNode by triggering selection change\r\n const currentSelection = $getSelection();\r\n if (currentSelection) {\r\n $setSelection(currentSelection.clone());\r\n }\r\n }\r\n });\r\n\r\n // Close dialog and reset\r\n setShowComparisonDialog(false);\r\n setNewImageUrl(\"\");\r\n setNewCombinedPrompt(\"\");\r\n\r\n // Show success toast\r\n toast.success(\"Image replaced successfully!\", {\r\n description: \"The image has been updated with the refined version.\",\r\n });\r\n };\r\n\r\n const handleCancelReplace = () => {\r\n // Just close dialog and reset\r\n setShowComparisonDialog(false);\r\n setNewImageUrl(\"\");\r\n setNewCombinedPrompt(\"\");\r\n };\r\n\r\n const draggable = isSelected && $isNodeSelection(selection) && !isResizing;\r\n const isFocused = (isSelected || isResizing) && isEditable;\r\n\r\n // Get position-based styles for float layouts\r\n // Note: Float styles are now applied at the ImageNode.createDOM level for proper text wrapping\r\n // This component only needs basic positioning\r\n const getPositionStyles = (): React.CSSProperties => {\r\n // For floated images, use simpler styles since float is on parent span\r\n if (position === \"left\" || position === \"right\") {\r\n return {\r\n position: \"relative\",\r\n display: \"block\",\r\n width: \"100%\", // Fill the floated container\r\n };\r\n }\r\n // For full width images, use inline-block so parent's text-align: center works\r\n if (position === \"full\") {\r\n return {\r\n position: \"relative\",\r\n display: \"inline-block\", // Use inline-block to respect text-align: center from parent\r\n };\r\n }\r\n // For inline alignment options (block-level with alignment)\r\n if (position === \"inline-left\" || position === \"inline-center\" || position === \"inline-right\") {\r\n return {\r\n position: \"relative\",\r\n display: \"inline-block\", // Use inline-block to respect text-align from parent\r\n };\r\n }\r\n // Default: inline-block for regular images (position \"none\")\r\n return {\r\n position: \"relative\",\r\n display: \"inline-block\",\r\n };\r\n };\r\n\r\n // Direct click handler as fallback for when Lexical CLICK_COMMAND doesn't fire\r\n // This happens in dialogs and other contexts where event propagation differs\r\n const handleDirectClick = useCallback(\r\n (e: React.MouseEvent) => {\r\n if (isResizing) {\r\n return;\r\n }\r\n\r\n // Don't handle if clicking on action buttons, toolbar, or other interactive elements\r\n if ((e.target as HTMLElement).closest(\"button\")) {\r\n return;\r\n }\r\n\r\n const target = e.target as HTMLElement;\r\n\r\n // Check if clicking directly on the image element\r\n const isClickOnImage = target === imageRef.current;\r\n\r\n // Also check if click coordinates are within the image bounds\r\n // This handles cases where inline images next to text might not receive direct clicks\r\n let isClickWithinImageBounds = false;\r\n if (!isClickOnImage && imageRef.current) {\r\n const imageRect = imageRef.current.getBoundingClientRect();\r\n isClickWithinImageBounds =\r\n e.clientX >= imageRect.left &&\r\n e.clientX <= imageRect.right &&\r\n e.clientY >= imageRect.top &&\r\n e.clientY <= imageRect.bottom;\r\n }\r\n\r\n if (!isClickOnImage && !isClickWithinImageBounds) {\r\n return;\r\n }\r\n\r\n // Stop propagation only for clicks on the actual image\r\n e.stopPropagation();\r\n\r\n if (e.shiftKey) {\r\n setSelected(!isSelected);\r\n } else {\r\n clearSelection();\r\n setSelected(true);\r\n }\r\n },\r\n [isResizing, isSelected, setSelected, clearSelection]\r\n );\r\n\r\n return (\r\n <Suspense fallback={null}>\r\n <>\r\n <div\r\n draggable={draggable}\r\n style={getPositionStyles()}\r\n onClick={handleDirectClick}\r\n onMouseEnter={handleImageMouseEnter}\r\n onMouseLeave={handleImageMouseLeave}\r\n >\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 : linkUrl ? \"cteditor-cursor-pointer\" : 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 {/* Link Preview Popup - shown on hover when image has a link */}\r\n {showLinkPreview && linkUrl && !isSelected && (\r\n <div\r\n className=\"cteditor-absolute cteditor-bottom-2 cteditor-left-2 cteditor-right-2 cteditor-bg-background cteditor-rounded-lg cteditor-shadow-lg cteditor-border cteditor-border-border cteditor-p-2 cteditor-flex cteditor-items-center cteditor-gap-2\"\r\n style={{ zIndex: 10 }}\r\n >\r\n <Link2 className=\"cteditor-w-4 cteditor-h-4 cteditor-text-muted-foreground cteditor-flex-shrink-0\" />\r\n <span className=\"cteditor-text-sm cteditor-text-foreground cteditor-truncate cteditor-flex-1\">\r\n {linkUrl}\r\n </span>\r\n <button\r\n onClick={handleLinkClick}\r\n className=\"cteditor-px-2 cteditor-py-1.5 cteditor-text-xs cteditor-rounded cteditor-bg-primary cteditor-text-primary-foreground hover:cteditor-bg-primary/90 cteditor-transition-colors cteditor-flex-shrink-0\"\r\n >\r\n Open\r\n </button>\r\n </div>\r\n )}\r\n {/* Action Buttons - Responsive toolbar that adapts to image size */}\r\n {isSelected && $isNodeSelection(selection) && !isLoadError && (\r\n <div\r\n className={`cteditor-absolute cteditor-flex cteditor-gap-1 z-10 ${\r\n shouldPositionBelow\r\n ? \"cteditor-left-1/2 cteditor--translate-x-1/2 cteditor-bottom-0 cteditor-translate-y-full cteditor-mt-1\"\r\n : \"cteditor-top-2 cteditor-right-2\"\r\n }`} \r\n >\r\n {/* Alignment buttons - always visible */}\r\n <div className=\"cteditor-flex cteditor-items-center cteditor-gap-0.5 cteditor-bg-background/80 cteditor-rounded-md cteditor-shadow-md cteditor-border cteditor-border-border cteditor-p-0.5\">\r\n {/* Text Wrap (Float) Options */}\r\n <button\r\n onClick={(e) => handlePositionChange(e, \"left\")}\r\n className={` cteditor-size-6 cteditor-flex cteditor-items-center cteditor-justify-center cteditor-rounded hover:cteditor-bg-accent cteditor-transition-colors ${position === \"left\" ? \"cteditor-bg-accent\" : \"\"}`}\r\n aria-label=\"Wrap text left\"\r\n title=\"Wrap text left\"\r\n >\r\n <WrapTextLeftIcon />\r\n </button>\r\n <button\r\n onClick={(e) => handlePositionChange(e, \"right\")}\r\n className={` cteditor-size-6 cteditor-flex cteditor-items-center cteditor-justify-center cteditor-rounded hover:cteditor-bg-accent cteditor-transition-colors ${position === \"right\" ? \"cteditor-bg-accent\" : \"\"}`}\r\n aria-label=\"Wrap text right\"\r\n title=\"Wrap text right\"\r\n >\r\n <WrapTextRightIcon />\r\n </button>\r\n\r\n {/* Separator */}\r\n <div className=\"cteditor-w-px cteditor-h-5 cteditor-bg-border cteditor-mx-0.5\" />\r\n\r\n {/* Block Alignment (Inline) Options */}\r\n <button\r\n onClick={(e) => handlePositionChange(e, \"inline-left\")}\r\n className={`cteditor-size-6 cteditor-flex cteditor-items-center cteditor-justify-center cteditor-rounded hover:cteditor-bg-accent cteditor-transition-colors ${position === \"inline-left\" ? \"cteditor-bg-accent\" : \"\"}`}\r\n aria-label=\"Align left\"\r\n title=\"Align left (no text wrap)\"\r\n >\r\n <AlignLeftIcon />\r\n </button>\r\n <button\r\n onClick={(e) => handlePositionChange(e, \"inline-center\")}\r\n className={`cteditor-size-6 cteditor-flex cteditor-items-center cteditor-justify-center cteditor-rounded hover:cteditor-bg-accent cteditor-transition-colors ${position === \"inline-center\" || position === \"full\" ? \"cteditor-bg-accent\" : \"\"}`}\r\n aria-label=\"Align center\"\r\n title=\"Align center (no text wrap)\"\r\n >\r\n <AlignCenterIcon />\r\n </button>\r\n <button\r\n onClick={(e) => handlePositionChange(e, \"inline-right\")}\r\n className={`cteditor-size-6 cteditor-flex cteditor-items-center cteditor-justify-center cteditor-rounded hover:cteditor-bg-accent cteditor-transition-colors ${position === \"inline-right\" ? \"cteditor-bg-accent\" : \"\"}`}\r\n aria-label=\"Align right\"\r\n title=\"Align right (no text wrap)\"\r\n >\r\n <AlignRightIcon />\r\n </button>\r\n\r\n {/* Separator */}\r\n <div className=\"cteditor-w-px cteditor-h-5 cteditor-bg-border cteditor-mx-0.5\" />\r\n\r\n {/* Inline (original behavior) */}\r\n <button\r\n onClick={(e) => handlePositionChange(e, \"none\")}\r\n className={`cteditor-size-6 cteditor-flex cteditor-items-center cteditor-justify-center cteditor-rounded hover:cteditor-bg-accent cteditor-transition-colors ${position === \"none\" ? \"cteditor-bg-accent\" : \"\"}`}\r\n aria-label=\"Inline\"\r\n title=\"Inline with text\"\r\n >\r\n <Type className=\"cteditor-w-4 cteditor-h-4 cteditor-text-foreground\" />\r\n </button>\r\n </div>\r\n\r\n {/* Link button - shown when image has an original link URL */}\r\n {linkUrl && (\r\n <button\r\n onClick={handleLinkClick}\r\n className=\" cteditor-size-6 cteditor-flex cteditor-items-center cteditor-justify-center cteditor-rounded-md cteditor-bg-background/80 hover:cteditor-bg-accent cteditor-transition-colors cteditor-shadow-md cteditor-border cteditor-border-border\"\r\n aria-label=\"Visit link\"\r\n title={`Visit: ${linkUrl}`}\r\n >\r\n <LinkIcon/>\r\n </button>\r\n )}\r\n\r\n {/* Only show Refine button for AI-generated images (those with originalPrompt) */}\r\n {originalPrompt && (\r\n <button\r\n onClick={(e) => {\r\n e.stopPropagation();\r\n handleRefineClick(e);\r\n }}\r\n className=\" cteditor-size-6 cteditor-flex cteditor-items-center cteditor-justify-center cteditor-rounded-md cteditor-bg-background/80 hover:cteditor-bg-accent cteditor-transition-colors cteditor-shadow-md cteditor-border cteditor-border-border\"\r\n aria-label=\"Refine image\"\r\n title=\"Refine image\"\r\n >\r\n <Sparkles className=\"cteditor-w-4 cteditor-h-4 cteditor-text-foreground\" />\r\n </button>\r\n )}\r\n <button\r\n onClick={(e) => {\r\n e.stopPropagation();\r\n handleOpenInNewTab(e);\r\n }}\r\n className=\" cteditor-size-8 cteditor-flex cteditor-items-center cteditor-justify-center cteditor-rounded-md cteditor-bg-background/80 hover:cteditor-bg-accent cteditor-transition-colors cteditor-shadow-md cteditor-border cteditor-border-border\"\r\n aria-label=\"Open image in new tab\"\r\n title=\"Open in new tab\"\r\n >\r\n <ExternalLinkIcon />\r\n </button>\r\n <button\r\n onClick={(e) => {\r\n e.stopPropagation();\r\n handleDeleteImage(e);\r\n }}\r\n className=\" cteditor-size-8 cteditor-flex cteditor-items-center cteditor-justify-center 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\"\r\n aria-label=\"Delete image\"\r\n title=\"Delete image\"\r\n >\r\n <TrashIcon />\r\n </button>\r\n </div>\r\n )}\r\n {/* Refine Input - Only for AI-generated images */}\r\n {showRefineInput && isSelected && !isLoadError && originalPrompt && (\r\n <div\r\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\"\r\n style={{ zIndex: 10 }}\r\n onClick={(e) => e.stopPropagation()}\r\n onKeyDown={(e) => e.stopPropagation()}\r\n onKeyUp={(e) => e.stopPropagation()}\r\n >\r\n <div className=\"cteditor-flex cteditor-flex-col cteditor-gap-2\">\r\n <label className=\"cteditor-text-xs cteditor-font-medium cteditor-text-foreground\">\r\n What else do you want in this scene?\r\n </label>\r\n <input\r\n type=\"text\"\r\n value={refinementPrompt}\r\n onChange={(e) => setRefinementPrompt(e.target.value)}\r\n onKeyDown={(e) => {\r\n // Stop propagation to prevent editor commands from firing\r\n e.stopPropagation();\r\n\r\n if (\r\n e.key === \"Enter\" &&\r\n refinementPrompt.trim() &&\r\n !isRefining\r\n ) {\r\n handleRefineImage();\r\n }\r\n if (e.key === \"Escape\") {\r\n setShowRefineInput(false);\r\n setRefinementPrompt(\"\");\r\n }\r\n }}\r\n onKeyUp={(e) => {\r\n // Also stop propagation on keyup\r\n e.stopPropagation();\r\n }}\r\n onClick={(e) => {\r\n // Prevent click from bubbling to image selection\r\n e.stopPropagation();\r\n }}\r\n placeholder=\"e.g., flying birds, golden sunset, stormy clouds...\"\r\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\"\r\n disabled={isRefining}\r\n autoFocus\r\n />\r\n <div className=\"cteditor-flex cteditor-gap-2\">\r\n <button\r\n onClick={(e) => {\r\n e.stopPropagation();\r\n handleRefineImage();\r\n }}\r\n disabled={isRefining || !refinementPrompt.trim()}\r\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\"\r\n >\r\n {isRefining ? (\r\n <span className=\"cteditor-flex cteditor-items-center cteditor-justify-center cteditor-gap-2\">\r\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>\r\n Refining...\r\n </span>\r\n ) : (\r\n \"Refine Image\"\r\n )}\r\n </button>\r\n <button\r\n onClick={(e) => {\r\n e.stopPropagation();\r\n setShowRefineInput(false);\r\n setRefinementPrompt(\"\");\r\n }}\r\n disabled={isRefining}\r\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\"\r\n >\r\n Cancel\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n )}\r\n {/* ImageResizer must be inside the position:relative container for proper absolute positioning */}\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 </div>\r\n\r\n {/* Caption container must be outside the draggable wrapper to prevent drag issues */}\r\n {showCaption &&\r\n (altText.startsWith(\"Signature by\") ? (\r\n <SignatureCaption caption={caption} />\r\n ) : (\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={() => (\r\n <span className=\"cteditor-text-xs\">\r\n Enter a caption...\r\n </span>\r\n )}\r\n className=\"ImageNode__contentEditable\"\r\n />\r\n }\r\n ErrorBoundary={LexicalErrorBoundary}\r\n />\r\n\r\n <OnChangePlugin\r\n onChange={() => {\r\n //no code\r\n }}\r\n />\r\n <HistoryPlugin />\r\n <LocalStoragePlugin namespace={initialConfig.namespace} />\r\n </LexicalNestedComposer>\r\n </div>\r\n ))}\r\n\r\n {/* Image Comparison Dialog */}\r\n <ImageComparisonDialog\r\n open={showComparisonDialog}\r\n onOpenChange={setShowComparisonDialog}\r\n oldImageUrl={src}\r\n newImageUrl={newImageUrl}\r\n onReplace={handleReplaceImage}\r\n onCancel={handleCancelReplace}\r\n />\r\n </>\r\n </Suspense>\r\n );\r\n}\r\n"],"names":[],"mappings":"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","x_google_ignoreList":[0]}
@@ -1,7 +1,7 @@
1
1
  import { jsx, jsxs } from "react/jsx-runtime";
2
2
  import { useLexicalComposerContext } from "@lexical/react/LexicalComposerContext";
3
3
  import { $getNodeByKey } from "lexical";
4
- import { a as createLucideIcon, D as Download, T as Trash2, F as FileText, $ as $isFileNode } from "./index-636eff7f.js";
4
+ import { D as Download, T as Trash2, F as FileText, a as FileArchive, b as File, $ as $isFileNode } from "./index-6eb4d179.js";
5
5
  import "react";
6
6
  import "axios";
7
7
  import "react-dom";
@@ -25,40 +25,11 @@ import "@lexical/list";
25
25
  import "@lexical/rich-text";
26
26
  import "@lexical/selection";
27
27
  import "@lexical/react/LexicalHorizontalRuleNode";
28
- import "@mui/icons-material/Description";
29
- import "@mui/icons-material/FolderZip";
30
- import "@mui/icons-material/InsertChart";
31
- import "@mui/icons-material/InsertDriveFile";
32
- import "@mui/icons-material/PictureAsPdf";
33
28
  import "@lexical/react/LexicalDecoratorBlockNode";
34
29
  import "emoji-picker-react";
35
30
  import "@lexical/react/LexicalLinkPlugin";
36
31
  import "@lexical/react/LexicalTypeaheadMenuPlugin";
37
32
  import "@lexical/react/useLexicalEditable";
38
- /**
39
- * @license lucide-react v0.344.0 - ISC
40
- *
41
- * This source code is licensed under the ISC license.
42
- * See the LICENSE file in the root directory of this source tree.
43
- */
44
- const FileArchive = createLucideIcon("FileArchive", [
45
- ["path", { d: "M16 22h2a2 2 0 0 0 2-2V7l-5-5H6a2 2 0 0 0-2 2v18", key: "1oywqq" }],
46
- ["path", { d: "M14 2v4a2 2 0 0 0 2 2h4", key: "tnqrlb" }],
47
- ["circle", { cx: "10", cy: "20", r: "2", key: "1xzdoj" }],
48
- ["path", { d: "M10 7V6", key: "dljcrl" }],
49
- ["path", { d: "M10 12v-1", key: "v7bkov" }],
50
- ["path", { d: "M10 18v-2", key: "1cjy8d" }]
51
- ]);
52
- /**
53
- * @license lucide-react v0.344.0 - ISC
54
- *
55
- * This source code is licensed under the ISC license.
56
- * See the LICENSE file in the root directory of this source tree.
57
- */
58
- const File = createLucideIcon("File", [
59
- ["path", { d: "M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z", key: "1rqfz7" }],
60
- ["path", { d: "M14 2v4a2 2 0 0 0 2 2h4", key: "tnqrlb" }]
61
- ]);
62
33
  const formatFileSize = (bytes) => {
63
34
  if (!bytes)
64
35
  return "";
@@ -187,4 +158,4 @@ const FileView = ({ src, fileName, fileSize, nodeKey }) => {
187
158
  export {
188
159
  FileView as default
189
160
  };
190
- //# sourceMappingURL=index-4ea49f5b.js.map
161
+ //# sourceMappingURL=index-bb293cb2.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index-bb293cb2.js","sources":["../src/components/FileView/index.tsx"],"sourcesContent":["import { useLexicalComposerContext } from \"@lexical/react/LexicalComposerContext\";\r\nimport { $getNodeByKey } from \"lexical\";\r\nimport { Download, File as FileIcon, FileArchive, FileText, Trash2 } from \"lucide-react\";\r\nimport React from \"react\";\r\nimport { $isFileNode } from \"src/nodes/FileNode\";\r\n\r\ninterface FileViewProps {\r\n src: string;\r\n fileName: string;\r\n fileSize?: number;\r\n nodeKey: string;\r\n}\r\n\r\n// Helper to format file size\r\nconst formatFileSize = (bytes?: number): string => {\r\n if (!bytes) return \"\";\r\n if (bytes < 1024) return `${bytes} B`;\r\n if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;\r\n if (bytes < 1024 * 1024 * 1024) return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;\r\n return `${(bytes / (1024 * 1024 * 1024)).toFixed(1)} GB`;\r\n};\r\n\r\n// Helper to get file extension\r\nconst getFileExtension = (fileName: string): string => {\r\n const parts = fileName.split(\".\");\r\n return parts.length > 1 ? parts[parts.length - 1].toLowerCase() : \"\";\r\n};\r\n\r\n// Helper to get icon based on file type\r\nconst getFileIcon = (fileName: string) => {\r\n const ext = getFileExtension(fileName);\r\n\r\n if ([\"pdf\", \"doc\", \"docx\", \"txt\", \"odt\"].includes(ext)) {\r\n return <FileText className=\"cteditor-w-8 cteditor-h-8 cteditor-text-blue-500\" />;\r\n }\r\n if ([\"zip\", \"rar\", \"7z\", \"tar\", \"gz\"].includes(ext)) {\r\n return <FileArchive className=\"cteditor-w-8 cteditor-h-8 cteditor-text-orange-500\" />;\r\n }\r\n return <FileIcon className=\"cteditor-w-8 cteditor-h-8 cteditor-text-gray-500\" />;\r\n};\r\n\r\nconst FileView: React.FC<FileViewProps> = ({ src, fileName, fileSize, nodeKey }) => {\r\n const [editor] = useLexicalComposerContext();\r\n\r\n // Validate props to prevent errors\r\n if (!src || !fileName) {\r\n console.error('FileView: Missing required props', { src, fileName, fileSize, nodeKey });\r\n return (\r\n <div className=\"cteditor-inline-flex cteditor-items-center cteditor-gap-3 cteditor-px-4 cteditor-py-3 cteditor-my-2 cteditor-border cteditor-border-destructive cteditor-rounded-lg cteditor-bg-destructive/10\">\r\n <div className=\"cteditor-text-sm cteditor-text-destructive\">\r\n Error loading file\r\n </div>\r\n </div>\r\n );\r\n }\r\n\r\n const handleDownload = (e: React.MouseEvent) => {\r\n e.preventDefault();\r\n e.stopPropagation();\r\n\r\n try {\r\n // Check if it's a data URL (base64)\r\n if (src.startsWith('data:')) {\r\n // Convert data URL to blob for proper download\r\n const arr = src.split(',');\r\n const mimeMatch = arr[0].match(/:(.*?);/);\r\n const mime = mimeMatch ? mimeMatch[1] : 'application/octet-stream';\r\n const bstr = atob(arr[1]);\r\n let n = bstr.length;\r\n const u8arr = new Uint8Array(n);\r\n\r\n while (n--) {\r\n u8arr[n] = bstr.charCodeAt(n);\r\n }\r\n\r\n const blob = new Blob([u8arr], { type: mime });\r\n const blobUrl = URL.createObjectURL(blob);\r\n\r\n const link = document.createElement(\"a\");\r\n link.href = blobUrl;\r\n link.download = fileName;\r\n link.style.display = \"none\";\r\n document.body.appendChild(link);\r\n link.click();\r\n document.body.removeChild(link);\r\n\r\n // Clean up the blob URL after a delay\r\n setTimeout(() => URL.revokeObjectURL(blobUrl), 100);\r\n } else {\r\n // Regular URL - just download directly\r\n const link = document.createElement(\"a\");\r\n link.href = src;\r\n link.download = fileName;\r\n link.style.display = \"none\";\r\n link.target = \"_blank\";\r\n document.body.appendChild(link);\r\n link.click();\r\n document.body.removeChild(link);\r\n }\r\n } catch (error) {\r\n console.error(\"Error downloading file:\", error);\r\n // Fallback: try to open in new tab\r\n window.open(src, '_blank');\r\n }\r\n };\r\n\r\n const handleDeleteFile = (e: React.MouseEvent) => {\r\n e.preventDefault();\r\n e.stopPropagation();\r\n\r\n editor.update(() => {\r\n const node = $getNodeByKey(nodeKey);\r\n if ($isFileNode(node)) {\r\n node.remove();\r\n }\r\n });\r\n };\r\n\r\n return (\r\n <div\r\n className=\"cteditor-inline-flex cteditor-items-center cteditor-gap-3 cteditor-py-1 cteditor-px-2 cteditor-my-2 cteditor-border cteditor-border-border cteditor-rounded-lg cteditor-bg-background hover:cteditor-bg-accent/50 cteditor-transition-colors cteditor-cursor-pointer cteditor-max-w-md\"\r\n onClick={handleDownload}\r\n role=\"button\"\r\n tabIndex={0}\r\n onKeyDown={(e) => {\r\n if (e.key === \"Enter\" || e.key === \" \") {\r\n e.preventDefault();\r\n handleDownload(e as any);\r\n }\r\n }}\r\n >\r\n {/* File Icon */}\r\n <div className=\"cteditor-flex-shrink-0 *:cteditor-size-5\">\r\n {getFileIcon(fileName)}\r\n </div>\r\n\r\n {/* File Info */}\r\n <div className=\"cteditor-flex-1 cteditor-min-w-0\">\r\n <div className=\"cteditor-font-medium cteditor-text-xs cteditor-text-foreground cteditor-truncate\">\r\n {fileName}\r\n </div>\r\n {fileSize && (\r\n <div className=\"cteditor-text-xs cteditor-text-muted-foreground\">\r\n {formatFileSize(fileSize)}\r\n </div>\r\n )}\r\n </div>\r\n\r\n {/* Action Buttons - Download and Delete */}\r\n <div className=\"cteditor-flex cteditor-gap-1 cteditor-flex-shrink-0\">\r\n <button\r\n onClick={handleDownload}\r\n className=\"cteditor-p-1 cteditor-rounded-md hover:cteditor-bg-accent cteditor-transition-colors\"\r\n aria-label=\"Download file\"\r\n title=\"Download file\"\r\n >\r\n <Download className=\"cteditor-w-4 cteditor-h-4 cteditor-text-muted-foreground\" />\r\n </button>\r\n <button\r\n onClick={handleDeleteFile}\r\n className=\"cteditor-p-1 cteditor-rounded-md hover:cteditor-bg-destructive hover:cteditor-text-destructive-foreground cteditor-transition-colors\"\r\n aria-label=\"Delete file\"\r\n title=\"Delete file\"\r\n >\r\n <Trash2 className=\"cteditor-w-4 cteditor-h-4 cteditor-text-muted-foreground\" />\r\n </button>\r\n </div>\r\n </div>\r\n );\r\n};\r\n\r\nexport default FileView;\r\n"],"names":["FileIcon"],"mappings":"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"}
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import { v, s, y, q, H, x, I, z, r, u, G, w } from "./index-636eff7f.js";
1
+ import { G, z, K, x, H, J, O, M, y, w, N, I } from "./index-6eb4d179.js";
2
2
  import "react/jsx-runtime";
3
3
  import "react";
4
4
  import "axios";
@@ -25,28 +25,23 @@ import "@lexical/list";
25
25
  import "@lexical/rich-text";
26
26
  import "@lexical/selection";
27
27
  import "@lexical/react/LexicalHorizontalRuleNode";
28
- import "@mui/icons-material/Description";
29
- import "@mui/icons-material/FolderZip";
30
- import "@mui/icons-material/InsertChart";
31
- import "@mui/icons-material/InsertDriveFile";
32
- import "@mui/icons-material/PictureAsPdf";
33
28
  import "@lexical/react/LexicalDecoratorBlockNode";
34
29
  import "emoji-picker-react";
35
30
  import "@lexical/react/LexicalLinkPlugin";
36
31
  import "@lexical/react/LexicalTypeaheadMenuPlugin";
37
32
  import "@lexical/react/useLexicalEditable";
38
33
  export {
39
- v as ConfigurableEditor,
40
- s as ConfigurableEditorWithAuth,
41
- y as ContentPreview,
42
- q as EditorProvider,
34
+ G as ConfigurableEditor,
35
+ z as ConfigurableEditorWithAuth,
36
+ K as ContentPreview,
37
+ x as EditorProvider,
43
38
  H as HtmlViewProvider,
44
- x as LinkPreviewHover,
45
- I as defaultEditorConfig,
46
- z as isReactNativeWebView,
47
- r as useEditor,
48
- u as useHtmlView,
49
- G as useReactNativeBridge,
50
- w as verifyApiKey
39
+ J as LinkPreviewHover,
40
+ O as defaultEditorConfig,
41
+ M as isReactNativeWebView,
42
+ y as useEditor,
43
+ w as useHtmlView,
44
+ N as useReactNativeBridge,
45
+ I as verifyApiKey
51
46
  };
52
47
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
package/dist/types.d.ts CHANGED
@@ -38,6 +38,24 @@ export interface ToolbarProps {
38
38
  enableHtmlViewToggle?: boolean;
39
39
  enableNotePanels?: boolean;
40
40
  enableAutocompleteToggle?: boolean;
41
+ enableHeadings?: boolean;
42
+ enableLists?: boolean;
43
+ enableBlockquote?: boolean;
44
+ enableImageUpload?: boolean;
45
+ enableWordCount?: boolean;
46
+ enableCharts?: boolean;
47
+ enableHighlight?: boolean;
48
+ enableAutoCorrection?: boolean;
49
+ enablePdfExport?: boolean;
50
+ enableSpeechToText?: boolean;
51
+ enableComments?: boolean;
52
+ enableMentions?: boolean;
53
+ enableHorizontalLine?: boolean;
54
+ enableFileAttachments?: boolean;
55
+ enableSignature?: boolean;
56
+ enableEmbeds?: boolean;
57
+ enableFormatPainter?: boolean;
58
+ enableFeatureSuggestion?: boolean;
41
59
  fonts?: string[];
42
60
  editor: LexicalEditor;
43
61
  activeEditor: LexicalEditor;
@@ -57,6 +75,15 @@ export interface ColorPickerProps {
57
75
  }
58
76
  export interface BlockFormatMenuProps {
59
77
  blockType: keyof typeof blockTypeToBlockName;
78
+ enableHeadings?: boolean;
79
+ enableLists?: boolean;
80
+ enableBlockquote?: boolean;
81
+ }
82
+ export interface InsertMenuProps {
83
+ enableHorizontalLine?: boolean;
84
+ enableFileAttachments?: boolean;
85
+ enableSignature?: boolean;
86
+ enableImageUpload?: boolean;
60
87
  }
61
88
  export interface PlaceholderProps {
62
89
  className?: string;
@@ -68,6 +95,9 @@ export interface IMenuButtonStyle {
68
95
  }
69
96
  export interface UseBlockFormatProps {
70
97
  blockType: keyof typeof blockTypeToBlockName;
98
+ enableHeadings?: boolean;
99
+ enableLists?: boolean;
100
+ enableBlockquote?: boolean;
71
101
  }
72
102
  export interface UseCustomCommandsReturn {
73
103
  clearEditorContent: () => void;
@@ -108,9 +138,30 @@ export interface EditorConfigTypes {
108
138
  enableHtmlViewToggle: boolean;
109
139
  enableNotePanels: boolean;
110
140
  enableAutocompleteToggle: boolean;
141
+ enableHeadings: boolean;
142
+ enableLists: boolean;
143
+ enableBlockquote: boolean;
144
+ enableImageUpload: boolean;
145
+ enableWordCount: boolean;
146
+ enableCharts: boolean;
147
+ enableHighlight: boolean;
148
+ enableAutoCorrection: boolean;
149
+ enablePdfExport: boolean;
150
+ enableSpeechToText: boolean;
151
+ enableComments: boolean;
152
+ enableMentions: boolean;
153
+ enableHorizontalLine: boolean;
154
+ enableFileAttachments: boolean;
155
+ enableSignature: boolean;
156
+ enableEmbeds: boolean;
157
+ enableFormatPainter: boolean;
158
+ enableFeatureSuggestion?: boolean;
111
159
  };
112
160
  enableFloatingMenu: boolean;
113
161
  htmlViewOption: boolean;
162
+ enableThemeToggle?: boolean;
163
+ enableShortcuts?: boolean;
164
+ enableFeatureSuggestion?: boolean;
114
165
  floatingMenuOptions: {
115
166
  bold: boolean;
116
167
  italic: boolean;
@@ -126,6 +177,7 @@ export interface EditorConfigTypes {
126
177
  aiChat: boolean;
127
178
  comment: boolean;
128
179
  improve: boolean;
180
+ highlight: boolean;
129
181
  };
130
182
  enableAutocomplete?: boolean;
131
183
  autocompleteOptions?: {