ct-rich-text-editor 1.3.22 → 1.3.24

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.
@@ -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, $ as $isFileNode } from "./index-9a8a49b6.js";
4
+ import { a as createLucideIcon, D as Download, T as Trash2, $ as $isFileNode } from "./index-daaf2abc.js";
5
5
  import "react";
6
6
  import "axios";
7
7
  import "@emotion/styled";
@@ -202,4 +202,4 @@ const FileView = ({ src, fileName, fileSize, nodeKey }) => {
202
202
  export {
203
203
  FileView as default
204
204
  };
205
- //# sourceMappingURL=index-bf836d7a.js.map
205
+ //# sourceMappingURL=index-b535466a.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index-bf836d7a.js","sources":["../../../node_modules/lucide-react/dist/esm/icons/file-archive.js","../../../node_modules/lucide-react/dist/esm/icons/file-text.js","../../../node_modules/lucide-react/dist/esm/icons/file.js","../src/components/FileView/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 FileArchive = createLucideIcon(\"FileArchive\", [\n [\"path\", { d: \"M16 22h2a2 2 0 0 0 2-2V7l-5-5H6a2 2 0 0 0-2 2v18\", key: \"1oywqq\" }],\n [\"path\", { d: \"M14 2v4a2 2 0 0 0 2 2h4\", key: \"tnqrlb\" }],\n [\"circle\", { cx: \"10\", cy: \"20\", r: \"2\", key: \"1xzdoj\" }],\n [\"path\", { d: \"M10 7V6\", key: \"dljcrl\" }],\n [\"path\", { d: \"M10 12v-1\", key: \"v7bkov\" }],\n [\"path\", { d: \"M10 18v-2\", key: \"1cjy8d\" }]\n]);\n\nexport { FileArchive as default };\n//# sourceMappingURL=file-archive.js.map\n","/**\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 FileText = createLucideIcon(\"FileText\", [\n [\"path\", { d: \"M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z\", key: \"1rqfz7\" }],\n [\"path\", { d: \"M14 2v4a2 2 0 0 0 2 2h4\", key: \"tnqrlb\" }],\n [\"path\", { d: \"M10 9H8\", key: \"b1mrlr\" }],\n [\"path\", { d: \"M16 13H8\", key: \"t4e002\" }],\n [\"path\", { d: \"M16 17H8\", key: \"z1uh3a\" }]\n]);\n\nexport { FileText as default };\n//# sourceMappingURL=file-text.js.map\n","/**\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 File = createLucideIcon(\"File\", [\n [\"path\", { d: \"M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z\", key: \"1rqfz7\" }],\n [\"path\", { d: \"M14 2v4a2 2 0 0 0 2 2h4\", key: \"tnqrlb\" }]\n]);\n\nexport { File as default };\n//# sourceMappingURL=file.js.map\n","import { useLexicalComposerContext } from \"@lexical/react/LexicalComposerContext\";\nimport { $getNodeByKey } from \"lexical\";\nimport { Download, File as FileIcon, FileArchive, FileText, Trash2 } from \"lucide-react\";\nimport React from \"react\";\nimport { $isFileNode } from \"src/nodes/FileNode\";\n\ninterface FileViewProps {\n src: string;\n fileName: string;\n fileSize?: number;\n nodeKey: string;\n}\n\n// Helper to format file size\nconst formatFileSize = (bytes?: number): string => {\n if (!bytes) return \"\";\n if (bytes < 1024) return `${bytes} B`;\n if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;\n if (bytes < 1024 * 1024 * 1024) return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;\n return `${(bytes / (1024 * 1024 * 1024)).toFixed(1)} GB`;\n};\n\n// Helper to get file extension\nconst getFileExtension = (fileName: string): string => {\n const parts = fileName.split(\".\");\n return parts.length > 1 ? parts[parts.length - 1].toLowerCase() : \"\";\n};\n\n// Helper to get icon based on file type\nconst getFileIcon = (fileName: string) => {\n const ext = getFileExtension(fileName);\n\n if ([\"pdf\", \"doc\", \"docx\", \"txt\", \"odt\"].includes(ext)) {\n return <FileText className=\"cteditor-w-8 cteditor-h-8 cteditor-text-blue-500\" />;\n }\n if ([\"zip\", \"rar\", \"7z\", \"tar\", \"gz\"].includes(ext)) {\n return <FileArchive className=\"cteditor-w-8 cteditor-h-8 cteditor-text-orange-500\" />;\n }\n return <FileIcon className=\"cteditor-w-8 cteditor-h-8 cteditor-text-gray-500\" />;\n};\n\nconst FileView: React.FC<FileViewProps> = ({ src, fileName, fileSize, nodeKey }) => {\n const [editor] = useLexicalComposerContext();\n\n // Validate props to prevent errors\n if (!src || !fileName) {\n console.error('FileView: Missing required props', { src, fileName, fileSize, nodeKey });\n return (\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\">\n <div className=\"cteditor-text-sm cteditor-text-destructive\">\n Error loading file\n </div>\n </div>\n );\n }\n\n const handleDownload = (e: React.MouseEvent) => {\n e.preventDefault();\n e.stopPropagation();\n\n try {\n // Check if it's a data URL (base64)\n if (src.startsWith('data:')) {\n // Convert data URL to blob for proper download\n const arr = src.split(',');\n const mimeMatch = arr[0].match(/:(.*?);/);\n const mime = mimeMatch ? mimeMatch[1] : 'application/octet-stream';\n const bstr = atob(arr[1]);\n let n = bstr.length;\n const u8arr = new Uint8Array(n);\n\n while (n--) {\n u8arr[n] = bstr.charCodeAt(n);\n }\n\n const blob = new Blob([u8arr], { type: mime });\n const blobUrl = URL.createObjectURL(blob);\n\n const link = document.createElement(\"a\");\n link.href = blobUrl;\n link.download = fileName;\n link.style.display = \"none\";\n document.body.appendChild(link);\n link.click();\n document.body.removeChild(link);\n\n // Clean up the blob URL after a delay\n setTimeout(() => URL.revokeObjectURL(blobUrl), 100);\n } else {\n // Regular URL - just download directly\n const link = document.createElement(\"a\");\n link.href = src;\n link.download = fileName;\n link.style.display = \"none\";\n link.target = \"_blank\";\n document.body.appendChild(link);\n link.click();\n document.body.removeChild(link);\n }\n } catch (error) {\n console.error(\"Error downloading file:\", error);\n // Fallback: try to open in new tab\n window.open(src, '_blank');\n }\n };\n\n const handleDeleteFile = (e: React.MouseEvent) => {\n e.preventDefault();\n e.stopPropagation();\n\n editor.update(() => {\n const node = $getNodeByKey(nodeKey);\n if ($isFileNode(node)) {\n node.remove();\n }\n });\n };\n\n return (\n <div\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\"\n onClick={handleDownload}\n role=\"button\"\n tabIndex={0}\n onKeyDown={(e) => {\n if (e.key === \"Enter\" || e.key === \" \") {\n e.preventDefault();\n handleDownload(e as any);\n }\n }}\n >\n {/* File Icon */}\n <div className=\"cteditor-flex-shrink-0 *:cteditor-size-5\">\n {getFileIcon(fileName)}\n </div>\n\n {/* File Info */}\n <div className=\"cteditor-flex-1 cteditor-min-w-0\">\n <div className=\"cteditor-font-medium cteditor-text-xs cteditor-text-foreground cteditor-truncate\">\n {fileName}\n </div>\n {fileSize && (\n <div className=\"cteditor-text-xs cteditor-text-muted-foreground\">\n {formatFileSize(fileSize)}\n </div>\n )}\n </div>\n\n {/* Action Buttons - Download and Delete */}\n <div className=\"cteditor-flex cteditor-gap-1 cteditor-flex-shrink-0\">\n <button\n onClick={handleDownload}\n className=\"cteditor-p-1 cteditor-rounded-md hover:cteditor-bg-accent cteditor-transition-colors\"\n aria-label=\"Download file\"\n title=\"Download file\"\n >\n <Download className=\"cteditor-w-4 cteditor-h-4 cteditor-text-muted-foreground\" />\n </button>\n <button\n onClick={handleDeleteFile}\n className=\"cteditor-p-1 cteditor-rounded-md hover:cteditor-bg-destructive hover:cteditor-text-destructive-foreground cteditor-transition-colors\"\n aria-label=\"Delete file\"\n title=\"Delete file\"\n >\n <Trash2 className=\"cteditor-w-4 cteditor-h-4 cteditor-text-muted-foreground\" />\n </button>\n </div>\n </div>\n );\n};\n\nexport default FileView;\n"],"names":["FileIcon"],"mappings":"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","x_google_ignoreList":[0,1,2]}
1
+ {"version":3,"file":"index-b535466a.js","sources":["../../../node_modules/lucide-react/dist/esm/icons/file-archive.js","../../../node_modules/lucide-react/dist/esm/icons/file-text.js","../../../node_modules/lucide-react/dist/esm/icons/file.js","../src/components/FileView/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 FileArchive = createLucideIcon(\"FileArchive\", [\n [\"path\", { d: \"M16 22h2a2 2 0 0 0 2-2V7l-5-5H6a2 2 0 0 0-2 2v18\", key: \"1oywqq\" }],\n [\"path\", { d: \"M14 2v4a2 2 0 0 0 2 2h4\", key: \"tnqrlb\" }],\n [\"circle\", { cx: \"10\", cy: \"20\", r: \"2\", key: \"1xzdoj\" }],\n [\"path\", { d: \"M10 7V6\", key: \"dljcrl\" }],\n [\"path\", { d: \"M10 12v-1\", key: \"v7bkov\" }],\n [\"path\", { d: \"M10 18v-2\", key: \"1cjy8d\" }]\n]);\n\nexport { FileArchive as default };\n//# sourceMappingURL=file-archive.js.map\n","/**\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 FileText = createLucideIcon(\"FileText\", [\n [\"path\", { d: \"M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z\", key: \"1rqfz7\" }],\n [\"path\", { d: \"M14 2v4a2 2 0 0 0 2 2h4\", key: \"tnqrlb\" }],\n [\"path\", { d: \"M10 9H8\", key: \"b1mrlr\" }],\n [\"path\", { d: \"M16 13H8\", key: \"t4e002\" }],\n [\"path\", { d: \"M16 17H8\", key: \"z1uh3a\" }]\n]);\n\nexport { FileText as default };\n//# sourceMappingURL=file-text.js.map\n","/**\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 File = createLucideIcon(\"File\", [\n [\"path\", { d: \"M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z\", key: \"1rqfz7\" }],\n [\"path\", { d: \"M14 2v4a2 2 0 0 0 2 2h4\", key: \"tnqrlb\" }]\n]);\n\nexport { File as default };\n//# sourceMappingURL=file.js.map\n","import { useLexicalComposerContext } from \"@lexical/react/LexicalComposerContext\";\nimport { $getNodeByKey } from \"lexical\";\nimport { Download, File as FileIcon, FileArchive, FileText, Trash2 } from \"lucide-react\";\nimport React from \"react\";\nimport { $isFileNode } from \"src/nodes/FileNode\";\n\ninterface FileViewProps {\n src: string;\n fileName: string;\n fileSize?: number;\n nodeKey: string;\n}\n\n// Helper to format file size\nconst formatFileSize = (bytes?: number): string => {\n if (!bytes) return \"\";\n if (bytes < 1024) return `${bytes} B`;\n if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;\n if (bytes < 1024 * 1024 * 1024) return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;\n return `${(bytes / (1024 * 1024 * 1024)).toFixed(1)} GB`;\n};\n\n// Helper to get file extension\nconst getFileExtension = (fileName: string): string => {\n const parts = fileName.split(\".\");\n return parts.length > 1 ? parts[parts.length - 1].toLowerCase() : \"\";\n};\n\n// Helper to get icon based on file type\nconst getFileIcon = (fileName: string) => {\n const ext = getFileExtension(fileName);\n\n if ([\"pdf\", \"doc\", \"docx\", \"txt\", \"odt\"].includes(ext)) {\n return <FileText className=\"cteditor-w-8 cteditor-h-8 cteditor-text-blue-500\" />;\n }\n if ([\"zip\", \"rar\", \"7z\", \"tar\", \"gz\"].includes(ext)) {\n return <FileArchive className=\"cteditor-w-8 cteditor-h-8 cteditor-text-orange-500\" />;\n }\n return <FileIcon className=\"cteditor-w-8 cteditor-h-8 cteditor-text-gray-500\" />;\n};\n\nconst FileView: React.FC<FileViewProps> = ({ src, fileName, fileSize, nodeKey }) => {\n const [editor] = useLexicalComposerContext();\n\n // Validate props to prevent errors\n if (!src || !fileName) {\n console.error('FileView: Missing required props', { src, fileName, fileSize, nodeKey });\n return (\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\">\n <div className=\"cteditor-text-sm cteditor-text-destructive\">\n Error loading file\n </div>\n </div>\n );\n }\n\n const handleDownload = (e: React.MouseEvent) => {\n e.preventDefault();\n e.stopPropagation();\n\n try {\n // Check if it's a data URL (base64)\n if (src.startsWith('data:')) {\n // Convert data URL to blob for proper download\n const arr = src.split(',');\n const mimeMatch = arr[0].match(/:(.*?);/);\n const mime = mimeMatch ? mimeMatch[1] : 'application/octet-stream';\n const bstr = atob(arr[1]);\n let n = bstr.length;\n const u8arr = new Uint8Array(n);\n\n while (n--) {\n u8arr[n] = bstr.charCodeAt(n);\n }\n\n const blob = new Blob([u8arr], { type: mime });\n const blobUrl = URL.createObjectURL(blob);\n\n const link = document.createElement(\"a\");\n link.href = blobUrl;\n link.download = fileName;\n link.style.display = \"none\";\n document.body.appendChild(link);\n link.click();\n document.body.removeChild(link);\n\n // Clean up the blob URL after a delay\n setTimeout(() => URL.revokeObjectURL(blobUrl), 100);\n } else {\n // Regular URL - just download directly\n const link = document.createElement(\"a\");\n link.href = src;\n link.download = fileName;\n link.style.display = \"none\";\n link.target = \"_blank\";\n document.body.appendChild(link);\n link.click();\n document.body.removeChild(link);\n }\n } catch (error) {\n console.error(\"Error downloading file:\", error);\n // Fallback: try to open in new tab\n window.open(src, '_blank');\n }\n };\n\n const handleDeleteFile = (e: React.MouseEvent) => {\n e.preventDefault();\n e.stopPropagation();\n\n editor.update(() => {\n const node = $getNodeByKey(nodeKey);\n if ($isFileNode(node)) {\n node.remove();\n }\n });\n };\n\n return (\n <div\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\"\n onClick={handleDownload}\n role=\"button\"\n tabIndex={0}\n onKeyDown={(e) => {\n if (e.key === \"Enter\" || e.key === \" \") {\n e.preventDefault();\n handleDownload(e as any);\n }\n }}\n >\n {/* File Icon */}\n <div className=\"cteditor-flex-shrink-0 *:cteditor-size-5\">\n {getFileIcon(fileName)}\n </div>\n\n {/* File Info */}\n <div className=\"cteditor-flex-1 cteditor-min-w-0\">\n <div className=\"cteditor-font-medium cteditor-text-xs cteditor-text-foreground cteditor-truncate\">\n {fileName}\n </div>\n {fileSize && (\n <div className=\"cteditor-text-xs cteditor-text-muted-foreground\">\n {formatFileSize(fileSize)}\n </div>\n )}\n </div>\n\n {/* Action Buttons - Download and Delete */}\n <div className=\"cteditor-flex cteditor-gap-1 cteditor-flex-shrink-0\">\n <button\n onClick={handleDownload}\n className=\"cteditor-p-1 cteditor-rounded-md hover:cteditor-bg-accent cteditor-transition-colors\"\n aria-label=\"Download file\"\n title=\"Download file\"\n >\n <Download className=\"cteditor-w-4 cteditor-h-4 cteditor-text-muted-foreground\" />\n </button>\n <button\n onClick={handleDeleteFile}\n className=\"cteditor-p-1 cteditor-rounded-md hover:cteditor-bg-destructive hover:cteditor-text-destructive-foreground cteditor-transition-colors\"\n aria-label=\"Delete file\"\n title=\"Delete file\"\n >\n <Trash2 className=\"cteditor-w-4 cteditor-h-4 cteditor-text-muted-foreground\" />\n </button>\n </div>\n </div>\n );\n};\n\nexport default FileView;\n"],"names":["FileIcon"],"mappings":"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","x_google_ignoreList":[0,1,2]}
@@ -83,6 +83,7 @@ const getApiEndpoint = () => {
83
83
  return DEFAULT_API_ENDPOINT;
84
84
  };
85
85
  const verifyApiKey = async (apiKey) => {
86
+ var _a;
86
87
  try {
87
88
  const endpoint = getApiEndpoint();
88
89
  const response = await axios.post(
@@ -96,6 +97,12 @@ const verifyApiKey = async (apiKey) => {
96
97
  );
97
98
  return response.data;
98
99
  } catch (error) {
100
+ if ((_a = error.response) == null ? void 0 : _a.data) {
101
+ const customError = new Error(error.response.data.message || "Failed to verify API key");
102
+ customError.response = error.response;
103
+ customError.code = error.response.data.code;
104
+ throw customError;
105
+ }
99
106
  throw new Error("Failed to verify API key");
100
107
  }
101
108
  };
@@ -1471,7 +1478,7 @@ const AiTextTransform = async ({ content, apiKey }) => {
1471
1478
  const AI_ACTION_COMMAND = createCommand(
1472
1479
  "AI_ACTION_COMMAND"
1473
1480
  );
1474
- const ImageView = React__default.lazy(() => import("./index-84187412.js"));
1481
+ const ImageView = React__default.lazy(() => import("./index-fbad5b49.js"));
1475
1482
  function isGoogleDocCheckboxImg(img) {
1476
1483
  return img.parentElement != null && img.parentElement.tagName === "LI" && img.previousSibling === null && img.getAttribute("aria-roledescription") === "checkbox";
1477
1484
  }
@@ -15363,7 +15370,7 @@ const EmbedComponent = ({ url, displayType, alignment, nodeKey }) => {
15363
15370
  }
15364
15371
  );
15365
15372
  };
15366
- const FileComponent = React$1.lazy(() => import("./index-bf836d7a.js"));
15373
+ const FileComponent = React$1.lazy(() => import("./index-b535466a.js"));
15367
15374
  function convertFileElement(domNode) {
15368
15375
  if (domNode instanceof HTMLDivElement) {
15369
15376
  const dataUrl = domNode.getAttribute("data-lexical-file-src");
@@ -19158,6 +19165,7 @@ function AIChatDialog({
19158
19165
  const [provider, setProvider] = useState$1("chatgpt");
19159
19166
  const [costPerPrompt, setCostPerPrompt] = useState$1(1);
19160
19167
  const [remainingCredits, setRemainingCredits] = useState$1(0);
19168
+ const [purchasedCredits, setPurchasedCredits] = useState$1(0);
19161
19169
  useEffect$1(() => {
19162
19170
  if (open && initialText) {
19163
19171
  setInputValue(initialText);
@@ -19190,11 +19198,13 @@ function AIChatDialog({
19190
19198
  if (isMounted && info) {
19191
19199
  setCostPerPrompt(Number(info.costPerPrompt ?? 1));
19192
19200
  setRemainingCredits(Number(info.remainingCredits ?? 0));
19201
+ setPurchasedCredits(Number(info.purchasedCredits ?? 0));
19193
19202
  }
19194
19203
  } catch (_) {
19195
19204
  if (isMounted) {
19196
19205
  setCostPerPrompt(1);
19197
19206
  setRemainingCredits(0);
19207
+ setPurchasedCredits(0);
19198
19208
  }
19199
19209
  }
19200
19210
  };
@@ -19203,24 +19213,58 @@ function AIChatDialog({
19203
19213
  isMounted = false;
19204
19214
  };
19205
19215
  }, [apiKey]);
19216
+ const isImageGenerationRequest = (prompt) => {
19217
+ const lowerPrompt = prompt.toLowerCase();
19218
+ const imageKeywords = [
19219
+ "generate image",
19220
+ "generate an image",
19221
+ "create image",
19222
+ "create an image",
19223
+ "make image",
19224
+ "make an image",
19225
+ "draw",
19226
+ "illustration",
19227
+ "picture of",
19228
+ "image of",
19229
+ "photo of",
19230
+ "generate picture",
19231
+ "create picture",
19232
+ "visualize",
19233
+ "render image",
19234
+ "design image",
19235
+ "produce image"
19236
+ ];
19237
+ return imageKeywords.some((keyword) => lowerPrompt.includes(keyword));
19238
+ };
19206
19239
  const handleSubmit = async () => {
19207
19240
  var _a, _b;
19208
19241
  if (!inputValue.trim() || isLoading)
19209
19242
  return;
19210
19243
  setIsLoading(true);
19211
19244
  setErrorMessage(null);
19245
+ const isImageRequest = isImageGenerationRequest(inputValue);
19212
19246
  try {
19213
19247
  const response = await AiEditorAction({ content: inputValue, provider, apiKey });
19214
19248
  const htmlString = response.data;
19215
- editor.update(() => {
19216
- const parser = new DOMParser();
19217
- const dom = parser.parseFromString(htmlString.trim(), "text/html");
19218
- const nodes = $generateNodesFromDOM(editor, dom);
19219
- const currentSelection = $getSelection();
19220
- if (currentSelection) {
19221
- $insertNodes(nodes);
19222
- }
19223
- });
19249
+ const parser = new DOMParser();
19250
+ const dom = parser.parseFromString(htmlString.trim(), "text/html");
19251
+ const imgElement = dom.querySelector("img");
19252
+ if (isImageRequest && imgElement && imgElement.src) {
19253
+ editor.dispatchCommand(INSERT_IMAGE_COMMAND, {
19254
+ src: imgElement.src,
19255
+ altText: imgElement.alt || "AI generated image",
19256
+ originalPrompt: inputValue
19257
+ // Store the prompt for refinement
19258
+ });
19259
+ } else {
19260
+ editor.update(() => {
19261
+ const nodes = $generateNodesFromDOM(editor, dom);
19262
+ const currentSelection = $getSelection();
19263
+ if (currentSelection) {
19264
+ $insertNodes(nodes);
19265
+ }
19266
+ });
19267
+ }
19224
19268
  handleClose();
19225
19269
  setIsLoading(false);
19226
19270
  } catch (error) {
@@ -19279,8 +19323,12 @@ function AIChatDialog({
19279
19323
  ] })
19280
19324
  ] }),
19281
19325
  /* @__PURE__ */ jsxs("span", { className: "cteditor-inline-flex cteditor-items-center cteditor-gap-1 cteditor-rounded-md cteditor-bg-accent cteditor-px-2 cteditor-py-0.5", children: [
19282
- /* @__PURE__ */ jsx("span", { className: "cteditor-opacity-70", children: "Remaining" }),
19283
- /* @__PURE__ */ jsx("span", { className: "cteditor-font-medium", children: remainingCredits })
19326
+ /* @__PURE__ */ jsx("span", { className: "cteditor-opacity-70", children: "Total" }),
19327
+ /* @__PURE__ */ jsx("span", { className: "cteditor-font-medium", children: remainingCredits + purchasedCredits })
19328
+ ] }),
19329
+ purchasedCredits > 0 && /* @__PURE__ */ jsxs("span", { className: "cteditor-inline-flex cteditor-items-center cteditor-gap-1 cteditor-rounded-md cteditor-bg-green-500/10 cteditor-px-2 cteditor-py-0.5", children: [
19330
+ /* @__PURE__ */ jsx("span", { className: "cteditor-opacity-70", children: "Purchased" }),
19331
+ /* @__PURE__ */ jsx("span", { className: "cteditor-font-medium cteditor-text-green-600", children: purchasedCredits })
19284
19332
  ] })
19285
19333
  ] })
19286
19334
  ] }),
@@ -19460,6 +19508,7 @@ function InlineAIPrompt({
19460
19508
  const [provider, setProvider] = useState$1(initialProvider);
19461
19509
  const [inputValue, setInputValue] = useState$1("");
19462
19510
  const [isLoading, setIsLoading] = useState$1(false);
19511
+ const [status, setStatus] = useState$1("idle");
19463
19512
  const inputRef = useRef(null);
19464
19513
  const [selectedText, setSelectedText] = useState$1(initialSelectedText);
19465
19514
  useEffect$1(() => {
@@ -19470,6 +19519,7 @@ function InlineAIPrompt({
19470
19519
  const newSelectedText = selection.getTextContent();
19471
19520
  if (newSelectedText.trim() !== "") {
19472
19521
  setSelectedText(newSelectedText);
19522
+ setStatus("idle");
19473
19523
  }
19474
19524
  }
19475
19525
  });
@@ -19483,23 +19533,56 @@ function InlineAIPrompt({
19483
19533
  inputRef.current.focus();
19484
19534
  }
19485
19535
  }, []);
19536
+ const isImageGenerationRequest = (prompt) => {
19537
+ const lowerPrompt = prompt.toLowerCase();
19538
+ const imageKeywords = [
19539
+ "generate image",
19540
+ "generate an image",
19541
+ "create image",
19542
+ "create an image",
19543
+ "make image",
19544
+ "make an image",
19545
+ "draw",
19546
+ "illustration",
19547
+ "picture of",
19548
+ "image of",
19549
+ "photo of",
19550
+ "generate picture",
19551
+ "create picture",
19552
+ "visualize",
19553
+ "render image",
19554
+ "design image",
19555
+ "produce image"
19556
+ ];
19557
+ return imageKeywords.some((keyword) => lowerPrompt.includes(keyword));
19558
+ };
19486
19559
  const handleSubmit = async () => {
19487
19560
  var _a, _b;
19488
19561
  if (!inputValue.trim() || isLoading)
19489
19562
  return;
19490
- if (!selectedText || selectedText.trim() === "") {
19563
+ const isImageRequest = isImageGenerationRequest(inputValue) || selectedText && isImageGenerationRequest(selectedText);
19564
+ if (!isImageRequest && (!selectedText || selectedText.trim() === "")) {
19491
19565
  toast.error("Please select some text first");
19492
19566
  return;
19493
19567
  }
19494
19568
  setIsLoading(true);
19495
- const fullPrompt = `${inputValue}
19569
+ let finalPrompt;
19570
+ if (isImageRequest) {
19571
+ if (selectedText && selectedText.trim()) {
19572
+ finalPrompt = `${inputValue}: ${selectedText}`;
19573
+ } else {
19574
+ finalPrompt = inputValue;
19575
+ }
19576
+ } else {
19577
+ finalPrompt = `${inputValue}
19496
19578
 
19497
19579
  IMPORTANT: Return ONLY the modified/transformed text. Do NOT include any labels, prefixes, explanations, or formatting like "Simplified:", "Result:", "Here is", etc. Just return the pure result text.
19498
19580
 
19499
19581
  Text to transform:
19500
19582
  "${selectedText}"`;
19583
+ }
19501
19584
  try {
19502
- const response = await AiEditorAction({ content: fullPrompt, provider, apiKey });
19585
+ const response = await AiEditorAction({ content: finalPrompt, provider, apiKey });
19503
19586
  let htmlString = response.data;
19504
19587
  if (typeof htmlString === "string") {
19505
19588
  htmlString = htmlString.trim();
@@ -19507,22 +19590,34 @@ Text to transform:
19507
19590
  htmlString = htmlString.slice(1, -1);
19508
19591
  }
19509
19592
  }
19510
- editor.update(() => {
19511
- const parser = new DOMParser();
19512
- const dom = parser.parseFromString(htmlString.trim(), "text/html");
19513
- const nodes = $generateNodesFromDOM(editor, dom);
19514
- const currentSelection = $getSelection();
19515
- if (currentSelection) {
19516
- $insertNodes(nodes);
19517
- }
19518
- });
19593
+ const parser = new DOMParser();
19594
+ const dom = parser.parseFromString(htmlString.trim(), "text/html");
19595
+ const imgElement = dom.querySelector("img");
19596
+ if (isImageRequest && imgElement && imgElement.src) {
19597
+ editor.dispatchCommand(INSERT_IMAGE_COMMAND, {
19598
+ src: imgElement.src,
19599
+ altText: imgElement.alt || "AI generated image",
19600
+ originalPrompt: finalPrompt
19601
+ // Store the prompt for refinement
19602
+ });
19603
+ } else {
19604
+ editor.update(() => {
19605
+ const nodes = $generateNodesFromDOM(editor, dom);
19606
+ const currentSelection = $getSelection();
19607
+ if (currentSelection) {
19608
+ $insertNodes(nodes);
19609
+ }
19610
+ });
19611
+ }
19519
19612
  setInputValue("");
19520
19613
  setSelectedText("");
19614
+ setStatus("success");
19521
19615
  } catch (error) {
19522
19616
  console.error("Error processing AI action:", error);
19523
19617
  const apiMessage = ((_b = (_a = error == null ? void 0 : error.response) == null ? void 0 : _a.data) == null ? void 0 : _b.message) ?? (error instanceof Error ? error.message : null);
19524
19618
  const safeMessage = apiMessage && !/^Request failed with status code \d+/.test(apiMessage) ? apiMessage : "Error processing your request. Please try again.";
19525
19619
  toast.error(safeMessage);
19620
+ setStatus("error");
19526
19621
  } finally {
19527
19622
  setIsLoading(false);
19528
19623
  }
@@ -19537,6 +19632,7 @@ Text to transform:
19537
19632
  }
19538
19633
  };
19539
19634
  const hasSelectedText = selectedText && selectedText.trim() !== "";
19635
+ const isCurrentInputImageRequest = isImageGenerationRequest(inputValue);
19540
19636
  const displayText = hasSelectedText ? selectedText.length > 50 ? selectedText.substring(0, 50) + "..." : selectedText : "";
19541
19637
  return /* @__PURE__ */ jsxs(
19542
19638
  "div",
@@ -19566,20 +19662,20 @@ Text to transform:
19566
19662
  alignItems: "center",
19567
19663
  gap: "8px",
19568
19664
  padding: "6px 10px",
19569
- backgroundColor: hasSelectedText ? "#2a2a2a" : "#3a2a2a",
19665
+ backgroundColor: status === "success" ? "#1a2e1a" : status === "error" ? "#2e1a1a" : hasSelectedText ? "#2a2a2a" : isCurrentInputImageRequest ? "#2a3a2a" : "#3a2a2a",
19570
19666
  borderRadius: "6px",
19571
19667
  fontSize: "12px",
19572
19668
  color: "#999",
19573
- border: hasSelectedText ? "none" : "1px solid #5a3a3a"
19669
+ border: status === "success" ? "1px solid #3a5a3a" : status === "error" ? "1px solid #5a3a3a" : hasSelectedText ? "none" : isCurrentInputImageRequest ? "1px solid #3a5a3a" : "1px solid #5a3a3a"
19574
19670
  },
19575
- children: hasSelectedText ? /* @__PURE__ */ jsxs(Fragment, { children: [
19671
+ children: status === "success" ? /* @__PURE__ */ jsx("span", { style: { color: "#4ade80" }, children: "✓ Content inserted! Select new text or enter another prompt" }) : status === "error" ? /* @__PURE__ */ jsx("span", { style: { color: "#f87171" }, children: "✗ Request failed. Try again or select different text" }) : hasSelectedText ? /* @__PURE__ */ jsxs(Fragment, { children: [
19576
19672
  /* @__PURE__ */ jsx("span", { style: { color: "#666" }, children: "Selected:" }),
19577
19673
  /* @__PURE__ */ jsxs("span", { style: { color: "#ccc", fontStyle: "italic" }, children: [
19578
19674
  '"',
19579
19675
  displayText,
19580
19676
  '"'
19581
19677
  ] })
19582
- ] }) : /* @__PURE__ */ jsx("span", { style: { color: "#f87171" }, children: "⚠ Please select some text in the editor first" })
19678
+ ] }) : isCurrentInputImageRequest ? /* @__PURE__ */ jsx("span", { style: { color: "#4ade80" }, children: "🖼️ Image generation mode - no text selection required" }) : /* @__PURE__ */ jsx("span", { style: { color: "#f87171" }, children: "⚠ Please select some text or enter an image generation prompt" })
19583
19679
  }
19584
19680
  ),
19585
19681
  /* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", gap: "10px" }, children: [
@@ -19615,9 +19711,13 @@ Text to transform:
19615
19711
  ref: inputRef,
19616
19712
  type: "text",
19617
19713
  value: inputValue,
19618
- onChange: (e) => setInputValue(e.target.value),
19714
+ onChange: (e) => {
19715
+ setInputValue(e.target.value);
19716
+ if (status !== "idle")
19717
+ setStatus("idle");
19718
+ },
19619
19719
  onKeyDown: handleKeyDown,
19620
- placeholder: hasSelectedText ? "What do you want to do with this text?" : "Select text first...",
19720
+ placeholder: hasSelectedText ? "What do you want to do with this text?" : "Generate image of... or select text",
19621
19721
  disabled: isLoading,
19622
19722
  style: {
19623
19723
  width: "280px",
@@ -20386,10 +20486,10 @@ const PDF_CONFIG = {
20386
20486
  };
20387
20487
  const loadHtml2Pdf = async () => {
20388
20488
  try {
20389
- const mod = await import("./html2pdf.bundle.min-83517dc2.js").then((n) => n.h);
20489
+ const mod = await import("./html2pdf.bundle.min-f3fd0aa5.js").then((n) => n.h);
20390
20490
  return (mod == null ? void 0 : mod.default) || mod;
20391
20491
  } catch {
20392
- const mod2 = await import("./html2pdf.bundle-3699b235.js").then((n) => n.h);
20492
+ const mod2 = await import("./html2pdf.bundle-33b132a6.js").then((n) => n.h);
20393
20493
  return (mod2 == null ? void 0 : mod2.default) || mod2;
20394
20494
  }
20395
20495
  };
@@ -29091,49 +29191,15 @@ const fileToDataURL = (file) => {
29091
29191
  function DragDropPaste() {
29092
29192
  const [editor] = useLexicalComposerContext();
29093
29193
  const [isDragging, setIsDragging] = useState$1(false);
29194
+ const processedFilesRef = useRef(/* @__PURE__ */ new Set());
29094
29195
  const { apiKey } = useEditor();
29095
29196
  const { uploadFileToS3 } = useS3Uploader(apiKey || void 0);
29096
29197
  useEffect$1(() => {
29097
- const handlePaste = async (e) => {
29098
- const clipboardData = e.clipboardData;
29099
- if (!clipboardData)
29100
- return;
29101
- const files = clipboardData.files;
29102
- if (files && files.length > 0) {
29103
- const imageFiles = Array.from(files).filter(
29104
- (file) => ACCEPTABLE_IMAGE_TYPES.some((type) => file.type.startsWith(type.replace("/", "")) || file.type === type)
29105
- );
29106
- if (imageFiles.length > 0) {
29107
- e.preventDefault();
29108
- for (const file of imageFiles) {
29109
- let fileUrl;
29110
- try {
29111
- if (apiKey) {
29112
- fileUrl = await uploadFileToS3(file);
29113
- } else {
29114
- fileUrl = await fileToDataURL(file);
29115
- }
29116
- } catch (error) {
29117
- console.error("Upload failed for pasted image:", error);
29118
- fileUrl = await fileToDataURL(file);
29119
- }
29120
- editor.dispatchCommand(INSERT_IMAGE_COMMAND, {
29121
- altText: file.name || "Pasted image",
29122
- src: fileUrl
29123
- });
29124
- }
29125
- return;
29126
- }
29127
- }
29128
- };
29129
- const editorElement = editor.getRootElement();
29130
- if (editorElement) {
29131
- editorElement.addEventListener("paste", handlePaste);
29132
- return () => {
29133
- editorElement.removeEventListener("paste", handlePaste);
29134
- };
29135
- }
29136
- }, [editor, apiKey, uploadFileToS3]);
29198
+ const cleanup = setInterval(() => {
29199
+ processedFilesRef.current.clear();
29200
+ }, 1e3);
29201
+ return () => clearInterval(cleanup);
29202
+ }, []);
29137
29203
  useEffect$1(() => {
29138
29204
  const handleDragEnter = (e) => {
29139
29205
  var _a, _b;
@@ -29241,14 +29307,18 @@ function DragDropPaste() {
29241
29307
  ...ACCEPTABLE_APPLICATION_TYPES
29242
29308
  ]);
29243
29309
  for (const { file, result } of filesResult) {
29310
+ const fileKey = `${file.name}-${file.size}-${file.type}-${file.lastModified}`;
29311
+ if (processedFilesRef.current.has(fileKey)) {
29312
+ console.log("Skipping duplicate file:", file.name);
29313
+ continue;
29314
+ }
29315
+ processedFilesRef.current.add(fileKey);
29244
29316
  let fileUrl;
29245
29317
  try {
29246
29318
  if (apiKey) {
29247
29319
  fileUrl = await uploadFileToS3(file);
29248
- console.log("File uploaded to S3:", fileUrl);
29249
29320
  } else {
29250
29321
  fileUrl = await fileToDataURL(file);
29251
- console.log("Using local data URL (no S3 upload)");
29252
29322
  }
29253
29323
  } catch (error) {
29254
29324
  console.error("Upload failed, using local data URL:", error);
@@ -29256,7 +29326,7 @@ function DragDropPaste() {
29256
29326
  }
29257
29327
  if (isMimeType(file, ACCEPTABLE_IMAGE_TYPES)) {
29258
29328
  editor.dispatchCommand(INSERT_IMAGE_COMMAND, {
29259
- altText: file.name,
29329
+ altText: file.name || "Pasted image",
29260
29330
  src: fileUrl
29261
29331
  });
29262
29332
  } else if (isMimeType(file, ACCEPTABLE_APPLICATION_TYPES)) {
@@ -38517,10 +38587,7 @@ const ConfigurableEditorWithAuth = ({
38517
38587
  return /* @__PURE__ */ jsx(ScopedEditorWrapper, { children: /* @__PURE__ */ jsx(LoadingMessage, { children: /* @__PURE__ */ jsx("span", { children: "Loading editor..." }) }) });
38518
38588
  }
38519
38589
  if (error) {
38520
- return /* @__PURE__ */ jsx(ScopedEditorWrapper, { children: /* @__PURE__ */ jsx(ErrorMessage, { children: /* @__PURE__ */ jsxs("span", { children: [
38521
- "Error: ",
38522
- error
38523
- ] }) }) });
38590
+ return /* @__PURE__ */ jsx(ScopedEditorWrapper, { children: /* @__PURE__ */ jsx(ErrorMessage, { children: /* @__PURE__ */ jsx("span", { children: error }) }) });
38524
38591
  }
38525
38592
  if (!isAuthenticated || !editorConfig2) {
38526
38593
  return /* @__PURE__ */ jsx(ScopedEditorWrapper, { children: /* @__PURE__ */ jsx(AuthMessage, { children: /* @__PURE__ */ jsx("span", { children: "Please provide a valid API key to access the editor" }) }) });
@@ -38560,8 +38627,8 @@ export {
38560
38627
  DialogTitle as f,
38561
38628
  getDefaultExportFromCjs as g,
38562
38629
  DialogDescription as h,
38563
- initialConfig as i,
38564
- DialogFooter as j,
38630
+ DialogFooter as i,
38631
+ initialConfig as j,
38565
38632
  $isImageNode as k,
38566
38633
  EditorProvider as l,
38567
38634
  useEditor as m,
@@ -38571,4 +38638,4 @@ export {
38571
38638
  useHtmlView as u,
38572
38639
  verifyApiKey as v
38573
38640
  };
38574
- //# sourceMappingURL=index-9a8a49b6.js.map
38641
+ //# sourceMappingURL=index-daaf2abc.js.map