ct-rich-text-editor 1.2.9 → 1.3.1

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.
Files changed (41) hide show
  1. package/dist/assets/style.css +440 -193
  2. package/dist/{babel-d155920e.js → babel-d3085146.js} +3565 -3292
  3. package/dist/babel-d3085146.js.map +1 -0
  4. package/dist/components/CodeActionMenuPlugin/utils.d.ts +1 -1
  5. package/dist/{estree-b1fff53b.js → estree-164983f6.js} +1763 -1778
  6. package/dist/estree-164983f6.js.map +1 -0
  7. package/dist/hooks/useDebounce.d.ts +1 -1
  8. package/dist/{html-f95ee5dc.js → html-5586dbf6.js} +701 -656
  9. package/dist/html-5586dbf6.js.map +1 -0
  10. package/dist/{html2pdf.bundle-583538f8.js → html2pdf.bundle-f23e1b00.js} +2 -2
  11. package/dist/html2pdf.bundle-f23e1b00.js.map +1 -0
  12. package/dist/{html2pdf.bundle.min-bc7d5952.js → html2pdf.bundle.min-daf952fb.js} +2 -2
  13. package/dist/html2pdf.bundle.min-daf952fb.js.map +1 -0
  14. package/dist/{index-91238d37.js → index-10f9d057.js} +7 -11
  15. package/dist/index-10f9d057.js.map +1 -0
  16. package/dist/{index-9d28aec6.js → index-8d147c36.js} +1243 -658
  17. package/dist/index-8d147c36.js.map +1 -0
  18. package/dist/index.js +1 -1
  19. package/dist/{markdown-1d9e6c3f.js → markdown-d513479b.js} +1836 -1789
  20. package/dist/markdown-d513479b.js.map +1 -0
  21. package/dist/plugins/CombinedAutocompletGrammarPlugin.d.ts +22 -0
  22. package/dist/{postcss-c2592f3f.js → postcss-f084f74d.js} +1378 -1357
  23. package/dist/postcss-f084f74d.js.map +1 -0
  24. package/dist/standalone-5a8c6b7e.js +2518 -0
  25. package/dist/standalone-5a8c6b7e.js.map +1 -0
  26. package/dist/typescript-b1005db4.js +13705 -0
  27. package/dist/typescript-b1005db4.js.map +1 -0
  28. package/package.json +1 -1
  29. package/dist/babel-d155920e.js.map +0 -1
  30. package/dist/estree-b1fff53b.js.map +0 -1
  31. package/dist/html-f95ee5dc.js.map +0 -1
  32. package/dist/html2pdf.bundle-583538f8.js.map +0 -1
  33. package/dist/html2pdf.bundle.min-bc7d5952.js.map +0 -1
  34. package/dist/index-91238d37.js.map +0 -1
  35. package/dist/index-9d28aec6.js.map +0 -1
  36. package/dist/markdown-1d9e6c3f.js.map +0 -1
  37. package/dist/postcss-c2592f3f.js.map +0 -1
  38. package/dist/standalone-bcc7f37a.js +0 -2649
  39. package/dist/standalone-bcc7f37a.js.map +0 -1
  40. package/dist/typescript-48c10f50.js +0 -13601
  41. package/dist/typescript-48c10f50.js.map +0 -1
@@ -21,17 +21,17 @@ import { ListPlugin } from "@lexical/react/LexicalListPlugin";
21
21
  import { OnChangePlugin } from "@lexical/react/LexicalOnChangePlugin";
22
22
  import { RichTextPlugin } from "@lexical/react/LexicalRichTextPlugin";
23
23
  import { TablePlugin } from "@lexical/react/LexicalTablePlugin";
24
- import { $findMatchingParent, $getNearestNodeOfType, mergeRegister, $getNearestBlockElementAncestorOrThrow, $insertNodeToNearestRoot, $wrapNodeInElement, $isEditorIsNestedEditor, calculateZoomLevel, CAN_USE_DOM } from "@lexical/utils";
24
+ import { $findMatchingParent, $getNearestNodeOfType, mergeRegister, $getNearestBlockElementAncestorOrThrow, $insertNodeToNearestRoot, $wrapNodeInElement, $isEditorIsNestedEditor, mediaFileReader, isMimeType, calculateZoomLevel, CAN_USE_DOM } from "@lexical/utils";
25
25
  import Stack from "@mui/material/Stack";
26
- import { createCommand, COMMAND_PRIORITY_LOW, $getSelection, $isRangeSelection, $insertNodes, $getNearestNodeFromDOMNode, $setSelection, isHTMLElement as isHTMLElement$1, TextNode, $applyNodeReplacement, $getRoot, $createTextNode, $getNodeByKey, DecoratorNode, createEditor, COMMAND_PRIORITY_EDITOR, $createParagraphNode, $isRootOrShadowRoot, $isParagraphNode, $isTextNode, FORMAT_TEXT_COMMAND, FORMAT_ELEMENT_COMMAND, CAN_UNDO_COMMAND, CAN_REDO_COMMAND, $isElementNode, SELECTION_CHANGE_COMMAND, COMMAND_PRIORITY_CRITICAL, UNDO_COMMAND, REDO_COMMAND, KEY_ARROW_DOWN_COMMAND, KEY_ARROW_UP_COMMAND, KEY_ESCAPE_COMMAND, KEY_TAB_COMMAND, KEY_ENTER_COMMAND, $createNodeSelection, $isNodeSelection, CLICK_COMMAND, getDOMSelection, COMMAND_PRIORITY_HIGH, $isLineBreakNode, isDOMNode } from "lexical";
26
+ import { createCommand, COMMAND_PRIORITY_LOW, $getSelection, $isRangeSelection, $insertNodes, $getNearestNodeFromDOMNode, $setSelection, isHTMLElement as isHTMLElement$1, TextNode, $applyNodeReplacement, $getRoot, $createTextNode, $getNodeByKey, DecoratorNode, createEditor, COMMAND_PRIORITY_EDITOR, $createParagraphNode, $isRootOrShadowRoot, $isParagraphNode, $isTextNode, FORMAT_TEXT_COMMAND, FORMAT_ELEMENT_COMMAND, CAN_UNDO_COMMAND, CAN_REDO_COMMAND, $isElementNode, SELECTION_CHANGE_COMMAND, COMMAND_PRIORITY_CRITICAL, UNDO_COMMAND, REDO_COMMAND, KEY_ARROW_DOWN_COMMAND, KEY_ARROW_UP_COMMAND, KEY_ESCAPE_COMMAND, KEY_TAB_COMMAND, KEY_ENTER_COMMAND, $createNodeSelection, $isNodeSelection, CLICK_COMMAND, getDOMSelection, COMMAND_PRIORITY_HIGH, $isLineBreakNode, PASTE_COMMAND, isDOMNode } from "lexical";
27
27
  import * as ReactDOM from "react-dom";
28
28
  import ReactDOM__default, { createPortal } from "react-dom";
29
29
  import { $isCodeNode, CodeNode, normalizeCodeLang, getLanguageFriendlyName, CodeHighlightNode, CODE_LANGUAGE_MAP, $createCodeNode, registerCodeHighlighting, $isCodeHighlightNode } from "@lexical/code";
30
30
  import { LinkNode, $isLinkNode, TOGGLE_LINK_COMMAND, $createLinkNode, $isAutoLinkNode } from "@lexical/link";
31
- import { ListNode, ListItemNode, $isListNode, INSERT_UNORDERED_LIST_COMMAND, REMOVE_LIST_COMMAND, INSERT_CHECK_LIST_COMMAND, INSERT_ORDERED_LIST_COMMAND } from "@lexical/list";
32
- import { HeadingNode, QuoteNode, $isHeadingNode, $createHeadingNode, $createQuoteNode } from "@lexical/rich-text";
31
+ import { ListNode, ListItemNode, $isListNode, INSERT_UNORDERED_LIST_COMMAND, REMOVE_LIST_COMMAND, INSERT_CHECK_LIST_COMMAND, INSERT_ORDERED_LIST_COMMAND, $createListNode, $createListItemNode } from "@lexical/list";
32
+ import { HeadingNode, QuoteNode, $isHeadingNode, $createHeadingNode, $createQuoteNode, DRAG_DROP_PASTE } from "@lexical/rich-text";
33
33
  import { $isAtNodeEnd, $selectAll, $patchStyleText, $setBlocksType, $isParentElementRTL, $getSelectionStyleValueForProperty } from "@lexical/selection";
34
- import { TableNode, TableCellNode, TableRowNode, $createTableNodeWithDimensions, TableCellHeaderStates, $isTableNode, $isTableSelection, $getTableCellNodeFromLexicalNode, $getTableNodeFromLexicalNodeOrThrow, getTableElement, getTableObserverFromTableElement, $isTableCellNode, $insertTableRow__EXPERIMENTAL, $insertTableColumn__EXPERIMENTAL, $deleteTableRow__EXPERIMENTAL, $deleteTableColumn__EXPERIMENTAL, $getTableRowIndexFromTableCellNode, $isTableRowNode, $getTableColumnIndexFromTableCellNode, $getNodeTriplet, $unmergeCell, $computeTableMapSkipCellCheck, getDOMCellFromTarget, $getTableAndElementByKey } from "@lexical/table";
34
+ import { TableNode, TableCellNode, TableRowNode, $createTableNodeWithDimensions, TableCellHeaderStates, $isTableNode, $isTableSelection, $getTableCellNodeFromLexicalNode, $getTableNodeFromLexicalNodeOrThrow, getTableElement, getTableObserverFromTableElement, $isTableCellNode, $insertTableRow__EXPERIMENTAL, $insertTableColumn__EXPERIMENTAL, $getNodeTriplet, $isTableRowNode, $deleteTableRow__EXPERIMENTAL, $deleteTableColumn__EXPERIMENTAL, $getTableRowIndexFromTableCellNode, $getTableColumnIndexFromTableCellNode, $unmergeCell, $computeTableMapSkipCellCheck, getDOMCellFromTarget, $getTableAndElementByKey } from "@lexical/table";
35
35
  import { HorizontalRuleNode } from "@lexical/react/LexicalHorizontalRuleNode";
36
36
  import DescriptionIcon from "@mui/icons-material/Description";
37
37
  import FolderZipIcon from "@mui/icons-material/FolderZip";
@@ -2699,6 +2699,17 @@ const Highlighter = createLucideIcon("Highlighter", [
2699
2699
  ["path", { d: "m9 11-6 6v3h9l3-3", key: "1a3l36" }],
2700
2700
  ["path", { d: "m22 12-4.6 4.6a2 2 0 0 1-2.8 0l-5.2-5.2a2 2 0 0 1 0-2.8L14 4", key: "14a9rk" }]
2701
2701
  ]);
2702
+ /**
2703
+ * @license lucide-react v0.344.0 - ISC
2704
+ *
2705
+ * This source code is licensed under the ISC license.
2706
+ * See the LICENSE file in the root directory of this source tree.
2707
+ */
2708
+ const Image$2 = createLucideIcon("Image", [
2709
+ ["rect", { width: "18", height: "18", x: "3", y: "3", rx: "2", ry: "2", key: "1m3agn" }],
2710
+ ["circle", { cx: "9", cy: "9", r: "2", key: "af1f0g" }],
2711
+ ["path", { d: "m21 15-3.086-3.086a2 2 0 0 0-2.828 0L6 21", key: "1xmnt7" }]
2712
+ ]);
2702
2713
  /**
2703
2714
  * @license lucide-react v0.344.0 - ISC
2704
2715
  *
@@ -2727,6 +2738,47 @@ const Lightbulb = createLucideIcon("Lightbulb", [
2727
2738
  ["path", { d: "M9 18h6", key: "x1upvd" }],
2728
2739
  ["path", { d: "M10 22h4", key: "ceow96" }]
2729
2740
  ]);
2741
+ /**
2742
+ * @license lucide-react v0.344.0 - ISC
2743
+ *
2744
+ * This source code is licensed under the ISC license.
2745
+ * See the LICENSE file in the root directory of this source tree.
2746
+ */
2747
+ const ListChecks = createLucideIcon("ListChecks", [
2748
+ ["path", { d: "m3 17 2 2 4-4", key: "1jhpwq" }],
2749
+ ["path", { d: "m3 7 2 2 4-4", key: "1obspn" }],
2750
+ ["path", { d: "M13 6h8", key: "15sg57" }],
2751
+ ["path", { d: "M13 12h8", key: "h98zly" }],
2752
+ ["path", { d: "M13 18h8", key: "oe0vm4" }]
2753
+ ]);
2754
+ /**
2755
+ * @license lucide-react v0.344.0 - ISC
2756
+ *
2757
+ * This source code is licensed under the ISC license.
2758
+ * See the LICENSE file in the root directory of this source tree.
2759
+ */
2760
+ const ListOrdered = createLucideIcon("ListOrdered", [
2761
+ ["line", { x1: "10", x2: "21", y1: "6", y2: "6", key: "76qw6h" }],
2762
+ ["line", { x1: "10", x2: "21", y1: "12", y2: "12", key: "16nom4" }],
2763
+ ["line", { x1: "10", x2: "21", y1: "18", y2: "18", key: "u3jurt" }],
2764
+ ["path", { d: "M4 6h1v4", key: "cnovpq" }],
2765
+ ["path", { d: "M4 10h2", key: "16xx2s" }],
2766
+ ["path", { d: "M6 18H4c0-1 2-2 2-3s-1-1.5-2-1", key: "m9a95d" }]
2767
+ ]);
2768
+ /**
2769
+ * @license lucide-react v0.344.0 - ISC
2770
+ *
2771
+ * This source code is licensed under the ISC license.
2772
+ * See the LICENSE file in the root directory of this source tree.
2773
+ */
2774
+ const List$1 = createLucideIcon("List", [
2775
+ ["line", { x1: "8", x2: "21", y1: "6", y2: "6", key: "7ey8pc" }],
2776
+ ["line", { x1: "8", x2: "21", y1: "12", y2: "12", key: "rjfblc" }],
2777
+ ["line", { x1: "8", x2: "21", y1: "18", y2: "18", key: "c3b1m8" }],
2778
+ ["line", { x1: "3", x2: "3.01", y1: "6", y2: "6", key: "1g7gq3" }],
2779
+ ["line", { x1: "3", x2: "3.01", y1: "12", y2: "12", key: "1pjlvk" }],
2780
+ ["line", { x1: "3", x2: "3.01", y1: "18", y2: "18", key: "28t2mc" }]
2781
+ ]);
2730
2782
  /**
2731
2783
  * @license lucide-react v0.344.0 - ISC
2732
2784
  *
@@ -2937,6 +2989,16 @@ const Type = createLucideIcon("Type", [
2937
2989
  ["line", { x1: "9", x2: "15", y1: "20", y2: "20", key: "swin9y" }],
2938
2990
  ["line", { x1: "12", x2: "12", y1: "4", y2: "20", key: "1tx1rr" }]
2939
2991
  ]);
2992
+ /**
2993
+ * @license lucide-react v0.344.0 - ISC
2994
+ *
2995
+ * This source code is licensed under the ISC license.
2996
+ * See the LICENSE file in the root directory of this source tree.
2997
+ */
2998
+ const Video = createLucideIcon("Video", [
2999
+ ["path", { d: "m22 8-6 4 6 4V8Z", key: "50v9me" }],
3000
+ ["rect", { width: "14", height: "12", x: "2", y: "6", rx: "2", ry: "2", key: "1rqjg6" }]
3001
+ ]);
2940
3002
  /**
2941
3003
  * @license lucide-react v0.344.0 - ISC
2942
3004
  *
@@ -7760,16 +7822,16 @@ function CopyButton({ editor, getCodeDOMNode }) {
7760
7822
  }
7761
7823
  const index$4 = "";
7762
7824
  const PRETTIER_PARSER_MODULES = {
7763
- css: [() => import("./postcss-c2592f3f.js")],
7764
- html: [() => import("./html-f95ee5dc.js")],
7825
+ css: [() => import("./postcss-f084f74d.js")],
7826
+ html: [() => import("./html-5586dbf6.js")],
7765
7827
  js: [
7766
- () => import("./babel-d155920e.js"),
7767
- () => import("./estree-b1fff53b.js")
7828
+ () => import("./babel-d3085146.js"),
7829
+ () => import("./estree-164983f6.js")
7768
7830
  ],
7769
- markdown: [() => import("./markdown-1d9e6c3f.js")],
7831
+ markdown: [() => import("./markdown-d513479b.js")],
7770
7832
  typescript: [
7771
- () => import("./typescript-48c10f50.js"),
7772
- () => import("./estree-b1fff53b.js")
7833
+ () => import("./typescript-b1005db4.js"),
7834
+ () => import("./estree-164983f6.js")
7773
7835
  ]
7774
7836
  };
7775
7837
  async function loadPrettierParserByLang(lang) {
@@ -7780,7 +7842,7 @@ async function loadPrettierParserByLang(lang) {
7780
7842
  return modules;
7781
7843
  }
7782
7844
  async function loadPrettierFormat() {
7783
- const { format } = await import("./standalone-bcc7f37a.js");
7845
+ const { format } = await import("./standalone-5a8c6b7e.js");
7784
7846
  return format;
7785
7847
  }
7786
7848
  const PRETTIER_OPTIONS_BY_LANG = {
@@ -12655,10 +12717,10 @@ const PDF_CONFIG = {
12655
12717
  };
12656
12718
  const loadHtml2Pdf = async () => {
12657
12719
  try {
12658
- const mod = await import("./html2pdf.bundle.min-bc7d5952.js").then((n) => n.h);
12720
+ const mod = await import("./html2pdf.bundle.min-daf952fb.js").then((n) => n.h);
12659
12721
  return (mod == null ? void 0 : mod.default) || mod;
12660
12722
  } catch {
12661
- const mod2 = await import("./html2pdf.bundle-583538f8.js").then((n) => n.h);
12723
+ const mod2 = await import("./html2pdf.bundle-f23e1b00.js").then((n) => n.h);
12662
12724
  return (mod2 == null ? void 0 : mod2.default) || mod2;
12663
12725
  }
12664
12726
  };
@@ -13865,7 +13927,7 @@ const EmbedComponent = ({ url, displayType, alignment, nodeKey }) => {
13865
13927
  }
13866
13928
  );
13867
13929
  };
13868
- const ImageView = React__default.lazy(() => import("./index-91238d37.js"));
13930
+ const ImageView = React__default.lazy(() => import("./index-10f9d057.js"));
13869
13931
  function isGoogleDocCheckboxImg(img) {
13870
13932
  return img.parentElement != null && img.parentElement.tagName === "LI" && img.previousSibling === null && img.getAttribute("aria-roledescription") === "checkbox";
13871
13933
  }
@@ -16395,6 +16457,7 @@ function TableOptionPlugin() {
16395
16457
  htmlCell.style.setProperty("padding", "8px", "important");
16396
16458
  htmlCell.style.setProperty("border", "1px solid #ddd", "important");
16397
16459
  htmlCell.style.setProperty("font-weight", "bold", "important");
16460
+ htmlCell.style.setProperty("white-space", "nowrap", "important");
16398
16461
  }
16399
16462
  });
16400
16463
  }
@@ -16442,6 +16505,7 @@ function TableOptionPlugin() {
16442
16505
  for (let i2 = 0; i2 < cells.length; i2++) {
16443
16506
  const headingText = (columnHeadings[i2] || "").trim();
16444
16507
  const cellNode = cells[i2];
16508
+ cellNode.clear();
16445
16509
  if (headingText) {
16446
16510
  cellNode.append($createTextNode(headingText));
16447
16511
  }
@@ -16474,6 +16538,7 @@ function TableOptionPlugin() {
16474
16538
  htmlCell.style.setProperty("padding", "8px", "important");
16475
16539
  htmlCell.style.setProperty("border", "1px solid #ddd", "important");
16476
16540
  htmlCell.style.setProperty("font-weight", "bold", "important");
16541
+ htmlCell.style.setProperty("white-space", "nowrap", "important");
16477
16542
  });
16478
16543
  return true;
16479
16544
  }
@@ -21214,6 +21279,7 @@ const InsertImageUploadedDialogBody = ({
21214
21279
  const { uploadFileToS3, uploadedUrl, progress, uploading } = useS3Uploader(apiKey || void 0);
21215
21280
  const [tempSrc, setTempSrc] = useState$1("");
21216
21281
  const [fileToUpload, setFileToUpload] = useState$1(null);
21282
+ const [imageDimensions, setImageDimensions] = useState$1(null);
21217
21283
  const onChangeImage = async (event) => {
21218
21284
  const files = event.target.files;
21219
21285
  if (!files || files.length === 0)
@@ -21224,6 +21290,11 @@ const InsertImageUploadedDialogBody = ({
21224
21290
  reader.onload = () => {
21225
21291
  if (typeof reader.result === "string") {
21226
21292
  setTempSrc(reader.result);
21293
+ const img = new Image();
21294
+ img.onload = () => {
21295
+ setImageDimensions({ width: img.naturalWidth, height: img.naturalHeight });
21296
+ };
21297
+ img.src = reader.result;
21227
21298
  }
21228
21299
  };
21229
21300
  reader.readAsDataURL(file);
@@ -21233,9 +21304,19 @@ const InsertImageUploadedDialogBody = ({
21233
21304
  return;
21234
21305
  try {
21235
21306
  const uploadedUrl2 = await uploadFileToS3(fileToUpload);
21236
- onClick({ altText, src: uploadedUrl2 });
21307
+ console.log("Upload successful! URL:", uploadedUrl2);
21308
+ console.log("Image dimensions:", imageDimensions);
21309
+ const payload = {
21310
+ altText,
21311
+ src: uploadedUrl2,
21312
+ width: imageDimensions == null ? void 0 : imageDimensions.width,
21313
+ height: imageDimensions == null ? void 0 : imageDimensions.height
21314
+ };
21315
+ console.log("Inserting image with payload:", payload);
21316
+ onClick(payload);
21237
21317
  setTempSrc("");
21238
21318
  setFileToUpload(null);
21319
+ setImageDimensions(null);
21239
21320
  } catch (error) {
21240
21321
  console.error("Upload failed:", error);
21241
21322
  }
@@ -21317,6 +21398,7 @@ const InsertImageUrlDialogBody = ({
21317
21398
  const [altText, setAltText] = useState$1("");
21318
21399
  const [isValidUrl, setIsValidUrl] = useState$1(false);
21319
21400
  const [previewError, setPreviewError] = useState$1(null);
21401
+ const [imageDimensions, setImageDimensions] = useState$1(null);
21320
21402
  const validateUrl2 = (url) => {
21321
21403
  if (!url.trim())
21322
21404
  return false;
@@ -21352,6 +21434,7 @@ const InsertImageUrlDialogBody = ({
21352
21434
  img.onload = () => {
21353
21435
  setPreviewError(null);
21354
21436
  setIsValidUrl(true);
21437
+ setImageDimensions({ width: img.naturalWidth, height: img.naturalHeight });
21355
21438
  };
21356
21439
  img.onerror = () => {
21357
21440
  setPreviewError(
@@ -21364,7 +21447,12 @@ const InsertImageUrlDialogBody = ({
21364
21447
  const handleConfirmUrl = () => {
21365
21448
  if (!imageUrl || !isValidUrl)
21366
21449
  return;
21367
- onClick({ altText, src: imageUrl });
21450
+ onClick({
21451
+ altText,
21452
+ src: imageUrl,
21453
+ width: imageDimensions == null ? void 0 : imageDimensions.width,
21454
+ height: imageDimensions == null ? void 0 : imageDimensions.height
21455
+ });
21368
21456
  };
21369
21457
  return /* @__PURE__ */ jsxs("div", { className: "cteditor-space-y-4", children: [
21370
21458
  imageUrl && isValidUrl && !previewError && /* @__PURE__ */ jsx("div", { className: "cteditor-mb-4", children: /* @__PURE__ */ jsx(
@@ -22644,8 +22732,8 @@ const NotePanelMenu = ({ className }) => {
22644
22732
  ] });
22645
22733
  };
22646
22734
  const useStyles$1 = () => ({
22647
- root: "cteditor-p-2 cteditor-border-b cteditor-border-[#e0e0e0] cteditor-overflow-auto",
22648
- toolbar: "cteditor-p-2 cteditor-overflow-auto",
22735
+ root: "cteditor-p-2 cteditor-border-b cteditor-border-[#e0e0e0] cteditor-max-w-full cteditor-overflow-x-auto",
22736
+ toolbar: "cteditor-p-2 cteditor-max-w-full cteditor-overflow-x-auto cteditor-flex cteditor-flex-nowrap cteditor-gap-1",
22649
22737
  toolbarButton: "cteditor-p-1.5"
22650
22738
  });
22651
22739
  const useModal$1 = () => {
@@ -22827,8 +22915,17 @@ const Toolbar = ({
22827
22915
  enableHtmlView
22828
22916
  ]);
22829
22917
  const handleClearEditorContent = () => {
22830
- if (confirm("Are you sure you want to clear out the editor's content?"))
22831
- clearEditorContent();
22918
+ toast.warning("Clear editor content?", {
22919
+ description: "This will remove all content.",
22920
+ action: {
22921
+ label: "OK",
22922
+ onClick: () => {
22923
+ clearEditorContent();
22924
+ toast.success("Editor cleared");
22925
+ }
22926
+ },
22927
+ duration: 8e3
22928
+ });
22832
22929
  };
22833
22930
  const { onFontColorSelect, onBgColorSelect, onHighlightColorSelect } = useColorPicker();
22834
22931
  const [isLinkActive, setIsLinkActive] = useState$1(false);
@@ -23149,14 +23246,17 @@ const Toolbar = ({
23149
23246
  "div",
23150
23247
  {
23151
23248
  ref: contentRef,
23152
- className: "cteditor-flex cteditor-items-center cteditor-gap-1.5 cteditor-flex-1 cteditor-overflow-x-auto cteditor-scrollbar-hide",
23153
- style: { scrollbarWidth: "none", msOverflowStyle: "none" },
23249
+ className: "cteditor-flex cteditor-items-center cteditor-gap-1.5 cteditor-flex-1 cteditor-overflow-x-auto cteditor-flex-nowrap",
23250
+ style: {
23251
+ scrollBehavior: "smooth",
23252
+ WebkitOverflowScrolling: "touch"
23253
+ },
23154
23254
  children: [
23155
23255
  enableUndoRedo && /* @__PURE__ */ jsxs(
23156
23256
  "div",
23157
23257
  {
23158
23258
  "data-toolbar-item": "undoRedo",
23159
- className: "cteditor-flex cteditor-items-center cteditor-gap-1.5",
23259
+ className: "cteditor-flex cteditor-items-center cteditor-gap-1.5 cteditor-flex-shrink-0",
23160
23260
  children: [
23161
23261
  /* @__PURE__ */ jsx(TooltipProvider, { delayDuration: 200, children: /* @__PURE__ */ jsxs(Tooltip, { children: [
23162
23262
  /* @__PURE__ */ jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx(
@@ -24051,9 +24151,8 @@ function Skeleton({
24051
24151
  }
24052
24152
  );
24053
24153
  }
24054
- createCommand(
24055
- "AUTOCOMPLETE_COMMAND"
24056
- );
24154
+ const GrammarCheckPlugin = "";
24155
+ createCommand("AUTOCOMPLETE_COMMAND");
24057
24156
  const STATIC_SUGGESTIONS = [
24058
24157
  "javascript",
24059
24158
  "typescript",
@@ -24081,7 +24180,6 @@ class AIService {
24081
24180
  __publicField(this, "apiEndpoint");
24082
24181
  __publicField(this, "cache", /* @__PURE__ */ new Map());
24083
24182
  __publicField(this, "requestTimeout", 1e4);
24084
- // 10 seconds timeout for more reliable responses
24085
24183
  __publicField(this, "pendingRequests", /* @__PURE__ */ new Map());
24086
24184
  this.apiEndpoint = "https://api.cteditor.com/" + apiEndpoint;
24087
24185
  }
@@ -24103,19 +24201,9 @@ class AIService {
24103
24201
  }
24104
24202
  }
24105
24203
  async executeRequest(payload, cacheKey) {
24106
- var _a;
24107
24204
  try {
24108
24205
  const controller = new AbortController();
24109
- const timeoutId = setTimeout(
24110
- () => controller.abort(),
24111
- this.requestTimeout
24112
- );
24113
- console.log("🌐 AIService: Making request to:", this.apiEndpoint);
24114
- console.log("📦 AIService: Payload:", {
24115
- ...payload,
24116
- text: ((_a = payload.text) == null ? void 0 : _a.substring(0, 100)) + "..."
24117
- // Log only first 100 chars
24118
- });
24206
+ const timeoutId = setTimeout(() => controller.abort(), this.requestTimeout);
24119
24207
  const response = await fetch(this.apiEndpoint, {
24120
24208
  method: "POST",
24121
24209
  headers: {
@@ -24125,14 +24213,11 @@ class AIService {
24125
24213
  signal: controller.signal
24126
24214
  });
24127
24215
  clearTimeout(timeoutId);
24128
- console.log("📡 AIService: Response status:", response.status);
24129
24216
  if (!response.ok) {
24130
24217
  const errorText = await response.text();
24131
- console.error("❌ AIService: Error response:", errorText);
24132
24218
  throw new Error(`AI service error: ${response.status} - ${errorText}`);
24133
24219
  }
24134
24220
  const result = await response.json();
24135
- console.log("✅ AIService: Successful response received");
24136
24221
  this.cache.set(cacheKey, result.data);
24137
24222
  if (this.cache.size > 50) {
24138
24223
  const firstKey = this.cache.keys().next().value;
@@ -24142,15 +24227,7 @@ class AIService {
24142
24227
  }
24143
24228
  return result.data;
24144
24229
  } catch (error) {
24145
- if (error instanceof Error && error.name === "AbortError") {
24146
- console.warn(
24147
- "⏰ AIService: Request timed out after",
24148
- this.requestTimeout,
24149
- "ms"
24150
- );
24151
- } else {
24152
- console.error("❌ AIService: Request failed:", error);
24153
- }
24230
+ console.error("❌ AIService: Request failed:", error);
24154
24231
  return null;
24155
24232
  }
24156
24233
  }
@@ -24160,43 +24237,118 @@ class AIService {
24160
24237
  }
24161
24238
  const result = await this.makeRequest({
24162
24239
  text: text.trim(),
24163
- // Send the sentence/text for correction
24164
24240
  currentWord: currentWord == null ? void 0 : currentWord.trim(),
24165
- // Send current word being typed (optional)
24166
24241
  maxSuggestions
24167
24242
  });
24168
24243
  return result;
24169
24244
  }
24170
24245
  }
24171
- function AutocompletePlugin({
24246
+ class GrammarCheckService {
24247
+ constructor() {
24248
+ __publicField(this, "cache", /* @__PURE__ */ new Map());
24249
+ __publicField(this, "apiEndpoint");
24250
+ __publicField(this, "pendingRequest", null);
24251
+ this.apiEndpoint = "https://api.cteditor.com/api/ai/process";
24252
+ }
24253
+ async check(text) {
24254
+ if (!text || text.trim().length < 3) {
24255
+ return [];
24256
+ }
24257
+ const cacheKey = text.trim();
24258
+ if (this.cache.has(cacheKey)) {
24259
+ return this.cache.get(cacheKey);
24260
+ }
24261
+ if (this.pendingRequest) {
24262
+ return this.pendingRequest;
24263
+ }
24264
+ this.pendingRequest = this.executeCheck(text);
24265
+ try {
24266
+ const result = await this.pendingRequest;
24267
+ return result;
24268
+ } finally {
24269
+ this.pendingRequest = null;
24270
+ }
24271
+ }
24272
+ async executeCheck(text) {
24273
+ var _a, _b, _c, _d, _e, _f;
24274
+ try {
24275
+ const response = await fetch(this.apiEndpoint, {
24276
+ method: "POST",
24277
+ headers: { "Content-Type": "application/json" },
24278
+ body: JSON.stringify({ text: text.trim(), maxSuggestions: 3 }),
24279
+ signal: AbortSignal.timeout(1e4)
24280
+ });
24281
+ if (!response.ok) {
24282
+ console.error("❌ GrammarCheck: API error:", response.status);
24283
+ return [];
24284
+ }
24285
+ const result = await response.json();
24286
+ const foundErrors = [];
24287
+ if ((_c = (_b = (_a = result.data) == null ? void 0 : _a.corrections) == null ? void 0 : _b.spelling) == null ? void 0 : _c.errors) {
24288
+ result.data.corrections.spelling.errors.forEach((err, idx) => {
24289
+ foundErrors.push({
24290
+ type: "spelling",
24291
+ original: err.original,
24292
+ suggestions: err.suggestions || [],
24293
+ index: idx
24294
+ });
24295
+ });
24296
+ }
24297
+ if ((_f = (_e = (_d = result.data) == null ? void 0 : _d.corrections) == null ? void 0 : _e.grammar) == null ? void 0 : _f.errors) {
24298
+ result.data.corrections.grammar.errors.forEach((err, idx) => {
24299
+ foundErrors.push({
24300
+ type: "grammar",
24301
+ original: err.original || text,
24302
+ suggestions: [err.suggestion],
24303
+ index: foundErrors.length + idx,
24304
+ issue: err.issue
24305
+ });
24306
+ });
24307
+ }
24308
+ this.cache.set(text.trim(), foundErrors);
24309
+ if (this.cache.size > 30) {
24310
+ const firstKey = this.cache.keys().next().value;
24311
+ if (firstKey) {
24312
+ this.cache.delete(firstKey);
24313
+ }
24314
+ }
24315
+ return foundErrors;
24316
+ } catch (error) {
24317
+ console.error("❌ GrammarCheck: Check failed:", error);
24318
+ return [];
24319
+ }
24320
+ }
24321
+ }
24322
+ function CombinedAutocompleteGrammarPlugin({
24172
24323
  onQueryChange,
24173
24324
  onSelectOption,
24174
24325
  minMatchLength = 2,
24175
24326
  maxSuggestions = 10,
24176
- // anchorClassName = "",
24177
- // menuClassName = "",
24178
- // itemClassName = "",
24179
- // selectedItemClassName = "",
24180
24327
  apiEndpoint = "api/ai/process",
24181
24328
  enableAI = true,
24182
24329
  debounceDelay = 200
24183
24330
  }) {
24184
24331
  const [editor] = useLexicalComposerContext();
24185
24332
  const { updateToolbarState } = useToolbarState();
24333
+ const [activeTab, setActiveTab] = useState$1("autocomplete");
24186
24334
  const [queryString, setQueryString] = useState$1(null);
24187
24335
  const [suggestions, setSuggestions] = useState$1([]);
24188
24336
  const [selectedIndex, setSelectedIndex] = useState$1(0);
24189
24337
  const [isLoading, setIsLoading] = useState$1(false);
24190
24338
  const menuRef = useRef(null);
24191
24339
  const anchorElementRef = useRef(null);
24192
- const [anchorElement, setAnchorElement] = useState$1(
24193
- null
24194
- );
24340
+ const [anchorElement, setAnchorElement] = useState$1(null);
24195
24341
  const aiService = useRef(new AIService(apiEndpoint));
24196
24342
  const debounceTimer = useRef(null);
24197
24343
  const justSelectedOption = useRef(false);
24198
24344
  const lastRequestTime = useRef(0);
24199
24345
  const requestThrottle = 100;
24346
+ const [errors, setErrors] = useState$1([]);
24347
+ const [userDismissed, setUserDismissed] = useState$1(false);
24348
+ const grammarService = useRef(new GrammarCheckService());
24349
+ const checkTimeout = useRef();
24350
+ const lastCheckedText = useRef("");
24351
+ const highlightElementsRef = useRef([]);
24200
24352
  const extractWordsFromEditor = useCallback(() => {
24201
24353
  const words = /* @__PURE__ */ new Set();
24202
24354
  STATIC_SUGGESTIONS.forEach((word) => words.add(word));
@@ -24221,17 +24373,12 @@ function AutocompletePlugin({
24221
24373
  return [];
24222
24374
  }
24223
24375
  if (justSelectedOption.current) {
24224
- console.log(
24225
- "🚫 AutocompletePlugin: Skipping AI request - just selected option"
24226
- );
24227
24376
  return [];
24228
24377
  }
24229
24378
  const now2 = Date.now();
24230
24379
  if (now2 - lastRequestTime.current < requestThrottle) {
24231
- console.log("🚫 AutocompletePlugin: Throttling AI request");
24232
24380
  return [];
24233
24381
  }
24234
- console.log("🤖 AutocompletePlugin: Getting AI suggestions for:", query);
24235
24382
  setIsLoading(true);
24236
24383
  lastRequestTime.current = now2;
24237
24384
  let lastSentence = "";
@@ -24270,11 +24417,8 @@ function AutocompletePlugin({
24270
24417
  try {
24271
24418
  const result = await aiService.current.getIntelligentSuggestions(
24272
24419
  query,
24273
- // currentWord
24274
24420
  lastSentence,
24275
- // text (the sentence to correct)
24276
24421
  maxSuggestions
24277
- // maxSuggestions
24278
24422
  );
24279
24423
  const aiOptions = [];
24280
24424
  if (result) {
@@ -24347,10 +24491,6 @@ function AutocompletePlugin({
24347
24491
  });
24348
24492
  }
24349
24493
  }
24350
- console.log(
24351
- "✅ AutocompletePlugin: AI sentence corrections received:",
24352
- aiOptions
24353
- );
24354
24494
  return aiOptions.slice(0, Math.floor(maxSuggestions * 0.8));
24355
24495
  } catch (error) {
24356
24496
  console.error("❌ AutocompletePlugin: AI suggestions failed:", error);
@@ -24359,7 +24499,7 @@ function AutocompletePlugin({
24359
24499
  setIsLoading(false);
24360
24500
  }
24361
24501
  },
24362
- [enableAI, minMatchLength, maxSuggestions]
24502
+ [enableAI, minMatchLength, maxSuggestions, editor]
24363
24503
  );
24364
24504
  const getTraditionalSuggestions = useCallback(
24365
24505
  (query) => {
@@ -24416,7 +24556,6 @@ function AutocompletePlugin({
24416
24556
  }, 100);
24417
24557
  return;
24418
24558
  }
24419
- console.log("🎯 AutocompletePlugin: Checking for autocomplete trigger");
24420
24559
  editor.update(() => {
24421
24560
  const selection = $getSelection();
24422
24561
  if (!$isRangeSelection(selection) || !selection.isCollapsed()) {
@@ -24431,6 +24570,10 @@ function AutocompletePlugin({
24431
24570
  while (wordStart > 0 && /[a-zA-Z0-9_']/.test(textContent[wordStart - 1])) {
24432
24571
  wordStart--;
24433
24572
  }
24573
+ if (wordStart > 0 && textContent[wordStart - 1] === "/") {
24574
+ setQueryString(null);
24575
+ return;
24576
+ }
24434
24577
  const currentWord = textContent.slice(wordStart, anchorOffset);
24435
24578
  if (currentWord.length >= minMatchLength) {
24436
24579
  setQueryString(currentWord);
@@ -24445,18 +24588,10 @@ function AutocompletePlugin({
24445
24588
  }
24446
24589
  if (queryString && !justSelectedOption.current) {
24447
24590
  debounceTimer.current = setTimeout(async () => {
24448
- console.log(
24449
- "🔄 AutocompletePlugin: Getting suggestions for:",
24450
- queryString
24451
- );
24452
24591
  const newSuggestions = await getCombinedSuggestions(queryString);
24453
24592
  setSuggestions(newSuggestions);
24454
24593
  setSelectedIndex(0);
24455
24594
  onQueryChange == null ? void 0 : onQueryChange(queryString);
24456
- console.log(
24457
- "🎯 AutocompletePlugin: Updated suggestions:",
24458
- newSuggestions
24459
- );
24460
24595
  }, debounceDelay);
24461
24596
  } else {
24462
24597
  setSuggestions([]);
@@ -24471,7 +24606,6 @@ function AutocompletePlugin({
24471
24606
  }, [queryString, getCombinedSuggestions, onQueryChange, debounceDelay]);
24472
24607
  const selectOption = useCallback(
24473
24608
  (option) => {
24474
- console.log("✅ AutocompletePlugin: Selecting option:", option);
24475
24609
  justSelectedOption.current = true;
24476
24610
  editor.update(() => {
24477
24611
  const selection = $getSelection();
@@ -24509,9 +24643,6 @@ function AutocompletePlugin({
24509
24643
  const newOffset = sentenceStart + option.displayText.length;
24510
24644
  selection.anchor.set(textNode.getKey(), newOffset, "text");
24511
24645
  selection.focus.set(textNode.getKey(), newOffset, "text");
24512
- console.log(
24513
- "✅ AutocompletePlugin: Sentence replaced successfully"
24514
- );
24515
24646
  }
24516
24647
  } else {
24517
24648
  let wordStart = anchorOffset;
@@ -24525,7 +24656,6 @@ function AutocompletePlugin({
24525
24656
  const newOffset = wordStart + option.displayText.length;
24526
24657
  selection.anchor.set(textNode.getKey(), newOffset, "text");
24527
24658
  selection.focus.set(textNode.getKey(), newOffset, "text");
24528
- console.log("✅ AutocompletePlugin: Word replaced successfully");
24529
24659
  }
24530
24660
  }
24531
24661
  });
@@ -24629,151 +24759,373 @@ function AutocompletePlugin({
24629
24759
  inputListener();
24630
24760
  };
24631
24761
  }, [editor, checkForAutocompleteTrigger]);
24632
- const calculateMenuPosition = useCallback(() => {
24633
- if (!anchorElement)
24634
- return { top: 0, left: 0 };
24635
- editor.update(() => {
24762
+ const checkGrammar = useCallback(async () => {
24763
+ const isSlashActive = editor.getEditorState().read(() => {
24636
24764
  const selection = $getSelection();
24637
24765
  if (!$isRangeSelection(selection))
24638
- return;
24639
- const domSelection = window.getSelection();
24640
- if (!domSelection || domSelection.rangeCount === 0)
24641
- return;
24642
- const range = domSelection.getRangeAt(0);
24643
- const rect = range.getBoundingClientRect();
24644
- if (anchorElementRef.current) {
24645
- const currentElement = anchorElementRef.current;
24646
- currentElement.style.top = `${rect.bottom + window.scrollY + 4}px`;
24647
- currentElement.style.left = `${rect.left + window.scrollX}px`;
24766
+ return false;
24767
+ const anchor = selection.anchor;
24768
+ const anchorNode = anchor.getNode();
24769
+ const anchorOffset = anchor.offset;
24770
+ const textContent = anchorNode.getTextContent();
24771
+ let wordStart = anchorOffset;
24772
+ while (wordStart > 0 && /[a-zA-Z0-9_']/.test(textContent[wordStart - 1])) {
24773
+ wordStart--;
24648
24774
  }
24775
+ return wordStart > 0 && textContent[wordStart - 1] === "/";
24649
24776
  });
24650
- }, [editor, anchorElement]);
24651
- useEffect$1(() => {
24652
- if (suggestions.length > 0) {
24653
- calculateMenuPosition();
24777
+ if (isSlashActive) {
24778
+ setErrors([]);
24779
+ return;
24654
24780
  }
24655
- }, [suggestions, calculateMenuPosition]);
24656
- useEffect$1(() => {
24657
- const anchor = document.createElement("div");
24658
- anchor.style.position = "absolute";
24659
- anchor.style.zIndex = "1000";
24660
- if (anchorElementRef.current && document.body.contains(anchorElementRef.current)) {
24661
- try {
24662
- document.body.removeChild(anchorElementRef.current);
24663
- } catch (error) {
24664
- console.warn(
24665
- "🚨 AutocompletePlugin: Error removing existing anchor:",
24666
- error
24667
- );
24668
- }
24781
+ const text = editor.getEditorState().read(() => $getRoot().getTextContent());
24782
+ if (text === lastCheckedText.current) {
24783
+ return;
24669
24784
  }
24670
- document.body.appendChild(anchor);
24671
- anchorElementRef.current = anchor;
24672
- setAnchorElement(anchor);
24673
- return () => {
24674
- if (anchorElementRef.current && document.body.contains(anchorElementRef.current)) {
24675
- try {
24676
- document.body.removeChild(anchorElementRef.current);
24677
- } catch (error) {
24678
- console.warn("🚨 AutocompletePlugin: Error during cleanup:", error);
24679
- }
24680
- }
24681
- };
24682
- }, []);
24683
- const getSuggestionIcon = (type) => {
24684
- switch (type) {
24685
- case "spelling":
24686
- return /* @__PURE__ */ jsx(CheckCircle, { className: "cteditor-size-4" });
24687
- case "correction":
24688
- return /* @__PURE__ */ jsx(Type, { className: "cteditor-size-4" });
24689
- case "enhancement":
24690
- return /* @__PURE__ */ jsx(Lightbulb, { className: "cteditor-size-4" });
24691
- default:
24692
- return /* @__PURE__ */ jsx(Sparkles, { className: "cteditor-size-4" });
24785
+ if (Math.abs(text.length - lastCheckedText.current.length) > 20) {
24786
+ setUserDismissed(false);
24693
24787
  }
24694
- };
24695
- const getSuggestionVariant = (type) => {
24696
- switch (type) {
24697
- case "spelling":
24698
- return "destructive";
24699
- case "correction":
24700
- return "default";
24701
- case "enhancement":
24702
- return "secondary";
24703
- default:
24704
- return "outline";
24788
+ lastCheckedText.current = text;
24789
+ if (!text || text.trim().length < 3) {
24790
+ setErrors([]);
24791
+ return;
24705
24792
  }
24706
- };
24707
- if (!anchorElement || !queryString || suggestions.length === 0 && !isLoading) {
24708
- return null;
24709
- }
24710
- return createPortal(
24711
- /* @__PURE__ */ jsx(
24712
- Card,
24713
- {
24714
- ref: menuRef,
24715
- className: "cteditor-w-80 cteditor-max-h-64 cteditor-overflow-y-auto cteditor-shadow-lg cteditor-border cteditor-bg-background cteditor-rounded-md",
24716
- children: /* @__PURE__ */ jsxs(CardContent, { className: "cteditor-p-2", children: [
24717
- isLoading && /* @__PURE__ */ jsxs("div", { className: "cteditor-flex cteditor-items-center cteditor-gap-2 cteditor-p-3 cteditor-text-sm cteditor-text-muted-foreground", children: [
24718
- /* @__PURE__ */ jsx(Skeleton, { className: "cteditor-h-4 cteditor-w-4 cteditor-rounded-full" }),
24719
- /* @__PURE__ */ jsx("span", { children: "Getting AI suggestions..." })
24720
- ] }),
24721
- /* @__PURE__ */ jsx("div", { className: "cteditor-space-y-1", children: suggestions.map((option, index2) => /* @__PURE__ */ jsxs(
24722
- "div",
24723
- {
24724
- className: cn$1(
24725
- "cteditor-flex cteditor-items-start cteditor-gap-3 cteditor-p-3 cteditor-rounded-md cteditor-cursor-pointer cteditor-transition-colors cteditor-text-sm",
24726
- index2 === selectedIndex ? "cteditor-bg-foreground/5" : "hover:cteditor-bg-red"
24727
- ),
24728
- onClick: () => selectOption(option),
24729
- onMouseEnter: () => setSelectedIndex(index2),
24730
- children: [
24731
- /* @__PURE__ */ jsx(
24732
- "div",
24733
- {
24734
- className: cn$1(
24735
- "cteditor-mt-0.5",
24736
- index2 === selectedIndex ? "cteditor-text-primary" : "cteditor-text-primary"
24737
- ),
24738
- children: getSuggestionIcon(option.type)
24739
- }
24740
- ),
24741
- /* @__PURE__ */ jsxs("div", { className: "cteditor-flex-1 cteditor-min-w-0", children: [
24742
- /* @__PURE__ */ jsxs("div", { className: "cteditor-flex cteditor-items-center cteditor-gap-2 cteditor-mb-2", children: [
24743
- /* @__PURE__ */ jsx(
24744
- Badge,
24745
- {
24746
- variant: index2 === selectedIndex ? "secondary" : getSuggestionVariant(option.type),
24747
- className: "cteditor-text-xs cteditor-border cteditor-border-foreground/20 cteditor-rounded-2xl !cteditor-font-normal ",
24748
- children: option.type
24749
- }
24750
- ),
24751
- option.confidence && /* @__PURE__ */ jsx("p", { className: "cteditor-text-xs cteditor-px-2 cteditor-py-0.5 cteditor-rounded-md cteditor-bg-muted/50 cteditor-text-foreground", children: option.confidence })
24752
- ] }),
24753
- /* @__PURE__ */ jsx("p", { className: "cteditor-leading-relaxed cteditor-break-words", children: option.displayText })
24754
- ] })
24755
- ]
24756
- },
24757
- option.key
24758
- )) }),
24759
- /* @__PURE__ */ jsx("div", { className: "cteditor-mt-1 cteditor-pt-1 cteditor-border-t cteditor-sticky cteditor-bottom-0 cteditor-bg-background", children: /* @__PURE__ */ jsxs(
24760
- Button,
24761
- {
24762
- variant: "ghost",
24763
- size: "sm",
24764
- className: "cteditor-w-full cteditor-justify-start cteditor-gap-2 cteditor-text-muted-foreground hover:cteditor-text-foreground",
24765
- onClick: () => {
24766
- setQueryString(null);
24767
- setSuggestions([]);
24768
- updateToolbarState("isAutocompleteEnabled", false);
24769
- },
24770
- children: [
24771
- /* @__PURE__ */ jsx(Ban, { className: "!cteditor-size-3" }),
24772
- "Disable Autocorrection"
24773
- ]
24793
+ const foundErrors = await grammarService.current.check(text);
24794
+ setErrors(foundErrors);
24795
+ }, [editor]);
24796
+ useEffect$1(() => {
24797
+ const unregister = editor.registerUpdateListener(() => {
24798
+ clearTimeout(checkTimeout.current);
24799
+ checkTimeout.current = window.setTimeout(checkGrammar, 2e3);
24800
+ });
24801
+ return () => {
24802
+ unregister();
24803
+ clearTimeout(checkTimeout.current);
24804
+ };
24805
+ }, [editor, checkGrammar]);
24806
+ useEffect$1(() => {
24807
+ highlightElementsRef.current.forEach((el) => {
24808
+ el.classList.remove("spelling-error", "grammar-error");
24809
+ });
24810
+ highlightElementsRef.current = [];
24811
+ if (errors.length === 0 || userDismissed)
24812
+ return;
24813
+ const timeoutId = setTimeout(() => {
24814
+ const editorElement = document.querySelector(".ContentEditable__root");
24815
+ if (!editorElement)
24816
+ return;
24817
+ const walker = document.createTreeWalker(
24818
+ editorElement,
24819
+ NodeFilter.SHOW_TEXT,
24820
+ null
24821
+ );
24822
+ const textNodes = [];
24823
+ let node;
24824
+ while (node = walker.nextNode()) {
24825
+ textNodes.push(node);
24826
+ }
24827
+ errors.forEach((error) => {
24828
+ textNodes.forEach((textNode) => {
24829
+ const nodeText = textNode.textContent || "";
24830
+ const errorIndex = nodeText.toLowerCase().indexOf(error.original.toLowerCase());
24831
+ if (errorIndex !== -1 && textNode.parentElement) {
24832
+ const className = error.type === "spelling" ? "spelling-error" : "grammar-error";
24833
+ if (textNode.parentElement.tagName === "SPAN") {
24834
+ textNode.parentElement.classList.add(className);
24835
+ highlightElementsRef.current.push(textNode.parentElement);
24836
+ } else if (textNode.parentElement) {
24837
+ const range = document.createRange();
24838
+ range.setStart(textNode, errorIndex);
24839
+ range.setEnd(textNode, Math.min(errorIndex + error.original.length, nodeText.length));
24840
+ const span = document.createElement("span");
24841
+ span.className = className;
24842
+ span.setAttribute("data-error-type", error.type);
24843
+ try {
24844
+ range.surroundContents(span);
24845
+ highlightElementsRef.current.push(span);
24846
+ } catch (e) {
24847
+ if (textNode.parentElement) {
24848
+ textNode.parentElement.classList.add(className);
24849
+ highlightElementsRef.current.push(textNode.parentElement);
24850
+ }
24851
+ }
24774
24852
  }
24775
- ) })
24776
- ] })
24853
+ }
24854
+ });
24855
+ });
24856
+ }, 100);
24857
+ return () => clearTimeout(timeoutId);
24858
+ }, [errors, userDismissed]);
24859
+ const applyCorrection = useCallback(
24860
+ (suggestion, original, errorType) => {
24861
+ editor.update(() => {
24862
+ const root2 = $getRoot();
24863
+ const currentText = root2.getTextContent();
24864
+ const isSpellingError = errorType === "spelling";
24865
+ let newText = currentText;
24866
+ if (isSpellingError) {
24867
+ const escapedOriginal = original.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
24868
+ const regex = new RegExp(`\\b${escapedOriginal}\\b`, "gi");
24869
+ newText = currentText.replace(regex, suggestion);
24870
+ } else {
24871
+ const escapedOriginal = original.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
24872
+ const regex = new RegExp(escapedOriginal, "gi");
24873
+ if (currentText.toLowerCase().includes(original.toLowerCase())) {
24874
+ newText = currentText.replace(regex, suggestion);
24875
+ } else {
24876
+ newText = suggestion;
24877
+ }
24878
+ }
24879
+ root2.clear();
24880
+ const paragraph = $createParagraphNode();
24881
+ const textNode = $createTextNode(newText);
24882
+ paragraph.append(textNode);
24883
+ root2.append(paragraph);
24884
+ });
24885
+ setTimeout(() => {
24886
+ lastCheckedText.current = "";
24887
+ checkGrammar();
24888
+ }, 100);
24889
+ },
24890
+ [editor, checkGrammar]
24891
+ );
24892
+ const calculateMenuPosition = useCallback(() => {
24893
+ if (!anchorElement)
24894
+ return { top: 0, left: 0 };
24895
+ editor.update(() => {
24896
+ const selection = $getSelection();
24897
+ if (!$isRangeSelection(selection))
24898
+ return;
24899
+ const domSelection = window.getSelection();
24900
+ if (!domSelection || domSelection.rangeCount === 0)
24901
+ return;
24902
+ const range = domSelection.getRangeAt(0);
24903
+ const rect = range.getBoundingClientRect();
24904
+ if (anchorElementRef.current) {
24905
+ const currentElement = anchorElementRef.current;
24906
+ currentElement.style.top = `${rect.bottom + window.scrollY + 4}px`;
24907
+ currentElement.style.left = `${rect.left + window.scrollX}px`;
24908
+ }
24909
+ });
24910
+ }, [editor, anchorElement]);
24911
+ useEffect$1(() => {
24912
+ if (suggestions.length > 0) {
24913
+ calculateMenuPosition();
24914
+ }
24915
+ }, [suggestions, calculateMenuPosition]);
24916
+ useEffect$1(() => {
24917
+ const anchor = document.createElement("div");
24918
+ anchor.style.position = "absolute";
24919
+ anchor.style.zIndex = "1000";
24920
+ if (anchorElementRef.current && document.body.contains(anchorElementRef.current)) {
24921
+ try {
24922
+ document.body.removeChild(anchorElementRef.current);
24923
+ } catch (error) {
24924
+ console.warn("Error removing existing anchor:", error);
24925
+ }
24926
+ }
24927
+ document.body.appendChild(anchor);
24928
+ anchorElementRef.current = anchor;
24929
+ setAnchorElement(anchor);
24930
+ return () => {
24931
+ if (anchorElementRef.current && document.body.contains(anchorElementRef.current)) {
24932
+ try {
24933
+ document.body.removeChild(anchorElementRef.current);
24934
+ } catch (error) {
24935
+ console.warn("Error during cleanup:", error);
24936
+ }
24937
+ }
24938
+ };
24939
+ }, []);
24940
+ const getSuggestionIcon = (type) => {
24941
+ switch (type) {
24942
+ case "spelling":
24943
+ return /* @__PURE__ */ jsx(CheckCircle, { className: "cteditor-size-4" });
24944
+ case "correction":
24945
+ return /* @__PURE__ */ jsx(Type, { className: "cteditor-size-4" });
24946
+ case "enhancement":
24947
+ return /* @__PURE__ */ jsx(Lightbulb, { className: "cteditor-size-4" });
24948
+ default:
24949
+ return /* @__PURE__ */ jsx(Sparkles, { className: "cteditor-size-4" });
24950
+ }
24951
+ };
24952
+ const getSuggestionVariant = (type) => {
24953
+ switch (type) {
24954
+ case "spelling":
24955
+ return "destructive";
24956
+ case "correction":
24957
+ return "default";
24958
+ case "enhancement":
24959
+ return "secondary";
24960
+ default:
24961
+ return "outline";
24962
+ }
24963
+ };
24964
+ useEffect$1(() => {
24965
+ const showAutocomplete2 = queryString && (suggestions.length > 0 || isLoading);
24966
+ const showGrammar2 = errors.length > 0 && !userDismissed;
24967
+ if (showAutocomplete2 && !showGrammar2) {
24968
+ setActiveTab("autocomplete");
24969
+ } else if (showGrammar2 && !showAutocomplete2) {
24970
+ setActiveTab("grammar");
24971
+ }
24972
+ }, [queryString, suggestions.length, isLoading, errors.length, userDismissed]);
24973
+ const showAutocomplete = queryString && (suggestions.length > 0 || isLoading);
24974
+ const showGrammar = errors.length > 0 && !userDismissed;
24975
+ if (!anchorElement || !showAutocomplete && !showGrammar) {
24976
+ return null;
24977
+ }
24978
+ return createPortal(
24979
+ /* @__PURE__ */ jsxs(
24980
+ Card,
24981
+ {
24982
+ ref: menuRef,
24983
+ className: "cteditor-w-80 cteditor-max-h-64 cteditor-overflow-hidden cteditor-shadow-lg cteditor-border cteditor-bg-background cteditor-rounded-md",
24984
+ children: [
24985
+ /* @__PURE__ */ jsxs("div", { className: "cteditor-flex cteditor-border-b cteditor-bg-muted/30", children: [
24986
+ /* @__PURE__ */ jsxs(
24987
+ "button",
24988
+ {
24989
+ onClick: () => setActiveTab("autocomplete"),
24990
+ className: cn$1(
24991
+ "cteditor-flex-1 cteditor-px-4 cteditor-py-2 cteditor-text-sm cteditor-font-medium cteditor-transition-colors",
24992
+ activeTab === "autocomplete" ? "cteditor-bg-background cteditor-text-foreground cteditor-border-b-2 cteditor-border-primary" : "cteditor-text-muted-foreground hover:cteditor-text-foreground"
24993
+ ),
24994
+ children: [
24995
+ /* @__PURE__ */ jsx(Sparkles, { className: "cteditor-inline cteditor-size-4 cteditor-mr-2" }),
24996
+ "Autocomplete"
24997
+ ]
24998
+ }
24999
+ ),
25000
+ /* @__PURE__ */ jsxs(
25001
+ "button",
25002
+ {
25003
+ onClick: () => setActiveTab("grammar"),
25004
+ className: cn$1(
25005
+ "cteditor-flex-1 cteditor-px-4 cteditor-py-2 cteditor-text-sm cteditor-font-medium cteditor-transition-colors",
25006
+ activeTab === "grammar" ? "cteditor-bg-background cteditor-text-foreground cteditor-border-b-2 cteditor-border-primary" : "cteditor-text-muted-foreground hover:cteditor-text-foreground"
25007
+ ),
25008
+ children: [
25009
+ /* @__PURE__ */ jsx(CheckCircle, { className: "cteditor-inline cteditor-size-4 cteditor-mr-2" }),
25010
+ "Grammar & Spelling",
25011
+ errors.length > 0 && /* @__PURE__ */ jsx(Badge, { variant: "destructive", className: "cteditor-ml-2 cteditor-text-xs", children: errors.length })
25012
+ ]
25013
+ }
25014
+ )
25015
+ ] }),
25016
+ /* @__PURE__ */ jsxs(CardContent, { className: "cteditor-p-2 cteditor-max-h-56 cteditor-overflow-y-auto", children: [
25017
+ activeTab === "autocomplete" && /* @__PURE__ */ jsxs(Fragment, { children: [
25018
+ isLoading && /* @__PURE__ */ jsxs("div", { className: "cteditor-flex cteditor-items-center cteditor-gap-2 cteditor-p-3 cteditor-text-sm cteditor-text-muted-foreground", children: [
25019
+ /* @__PURE__ */ jsx(Skeleton, { className: "cteditor-h-4 cteditor-w-4 cteditor-rounded-full" }),
25020
+ /* @__PURE__ */ jsx("span", { children: "Getting AI suggestions..." })
25021
+ ] }),
25022
+ /* @__PURE__ */ jsx("div", { className: "cteditor-space-y-1", children: suggestions.map((option, index2) => /* @__PURE__ */ jsxs(
25023
+ "div",
25024
+ {
25025
+ className: cn$1(
25026
+ "cteditor-flex cteditor-items-start cteditor-gap-3 cteditor-p-3 cteditor-rounded-md cteditor-cursor-pointer cteditor-transition-colors cteditor-text-sm",
25027
+ index2 === selectedIndex ? "cteditor-bg-foreground/5" : "hover:cteditor-bg-muted/50"
25028
+ ),
25029
+ onClick: () => selectOption(option),
25030
+ onMouseEnter: () => setSelectedIndex(index2),
25031
+ children: [
25032
+ /* @__PURE__ */ jsx(
25033
+ "div",
25034
+ {
25035
+ className: cn$1(
25036
+ "cteditor-mt-0.5",
25037
+ index2 === selectedIndex ? "cteditor-text-primary" : "cteditor-text-primary"
25038
+ ),
25039
+ children: getSuggestionIcon(option.type)
25040
+ }
25041
+ ),
25042
+ /* @__PURE__ */ jsxs("div", { className: "cteditor-flex-1 cteditor-min-w-0", children: [
25043
+ /* @__PURE__ */ jsxs("div", { className: "cteditor-flex cteditor-items-center cteditor-gap-2 cteditor-mb-2", children: [
25044
+ /* @__PURE__ */ jsx(
25045
+ Badge,
25046
+ {
25047
+ variant: index2 === selectedIndex ? "secondary" : getSuggestionVariant(option.type),
25048
+ className: "cteditor-text-xs cteditor-border cteditor-border-foreground/20 cteditor-rounded-2xl !cteditor-font-normal",
25049
+ children: option.type
25050
+ }
25051
+ ),
25052
+ option.confidence && /* @__PURE__ */ jsx("p", { className: "cteditor-text-xs cteditor-px-2 cteditor-py-0.5 cteditor-rounded-md cteditor-bg-muted/50 cteditor-text-foreground", children: option.confidence })
25053
+ ] }),
25054
+ /* @__PURE__ */ jsx("p", { className: "cteditor-leading-relaxed cteditor-break-words", children: option.displayText })
25055
+ ] })
25056
+ ]
25057
+ },
25058
+ option.key
25059
+ )) }),
25060
+ /* @__PURE__ */ jsx("div", { className: "cteditor-mt-1 cteditor-pt-1 cteditor-border-t cteditor-sticky cteditor-bottom-0 cteditor-bg-background", children: /* @__PURE__ */ jsxs(
25061
+ Button,
25062
+ {
25063
+ variant: "ghost",
25064
+ size: "sm",
25065
+ className: "cteditor-w-full cteditor-justify-start cteditor-gap-2 cteditor-text-muted-foreground hover:cteditor-text-foreground",
25066
+ onClick: () => {
25067
+ setQueryString(null);
25068
+ setSuggestions([]);
25069
+ updateToolbarState("isAutocompleteEnabled", false);
25070
+ },
25071
+ children: [
25072
+ /* @__PURE__ */ jsx(Ban, { className: "!cteditor-size-3" }),
25073
+ "Disable Autocomplete & Grammar Check"
25074
+ ]
25075
+ }
25076
+ ) })
25077
+ ] }),
25078
+ activeTab === "grammar" && /* @__PURE__ */ jsxs(Fragment, { children: [
25079
+ /* @__PURE__ */ jsx("div", { className: "cteditor-space-y-2 cteditor-p-2", children: errors.map((error, idx) => /* @__PURE__ */ jsx(
25080
+ "div",
25081
+ {
25082
+ className: "cteditor-flex cteditor-items-center cteditor-gap-2 cteditor-p-3 cteditor-rounded-md cteditor-bg-muted/50 cteditor-border",
25083
+ children: /* @__PURE__ */ jsxs("div", { className: "cteditor-flex-1", children: [
25084
+ /* @__PURE__ */ jsxs("div", { className: "cteditor-flex cteditor-items-center cteditor-gap-2 cteditor-mb-1", children: [
25085
+ /* @__PURE__ */ jsx(
25086
+ Badge,
25087
+ {
25088
+ variant: error.type === "spelling" ? "destructive" : "default",
25089
+ className: "cteditor-text-xs",
25090
+ children: error.type
25091
+ }
25092
+ ),
25093
+ error.confidence && /* @__PURE__ */ jsx("span", { className: "cteditor-text-xs cteditor-text-muted-foreground", children: error.confidence })
25094
+ ] }),
25095
+ /* @__PURE__ */ jsx("p", { className: "cteditor-text-sm cteditor-line-through cteditor-text-red-600 cteditor-mb-1", children: error.original }),
25096
+ error.suggestions.length > 0 && /* @__PURE__ */ jsx("div", { className: "cteditor-space-y-1", children: error.suggestions.slice(0, 2).map((suggestion, sIdx) => /* @__PURE__ */ jsx(
25097
+ "button",
25098
+ {
25099
+ onClick: () => applyCorrection(suggestion, error.original, error.type),
25100
+ className: "cteditor-block cteditor-w-full cteditor-text-left cteditor-text-sm cteditor-text-green-600 hover:cteditor-text-green-700 cteditor-px-2 cteditor-py-1 cteditor-rounded cteditor-bg-green-50 hover:cteditor-bg-green-100",
25101
+ children: suggestion
25102
+ },
25103
+ sIdx
25104
+ )) })
25105
+ ] })
25106
+ },
25107
+ idx
25108
+ )) }),
25109
+ /* @__PURE__ */ jsx("div", { className: "cteditor-mt-1 cteditor-pt-1 cteditor-border-t cteditor-sticky cteditor-bottom-0 cteditor-bg-background", children: /* @__PURE__ */ jsxs(
25110
+ Button,
25111
+ {
25112
+ variant: "ghost",
25113
+ size: "sm",
25114
+ className: "cteditor-w-full cteditor-justify-start cteditor-gap-2 cteditor-text-muted-foreground hover:cteditor-text-foreground",
25115
+ onClick: () => {
25116
+ setUserDismissed(true);
25117
+ setErrors([]);
25118
+ updateToolbarState("isGrammarCheckEnabled", false);
25119
+ },
25120
+ children: [
25121
+ /* @__PURE__ */ jsx(Ban, { className: "!cteditor-size-3" }),
25122
+ "Disable Autocomplete & Grammar Check"
25123
+ ]
25124
+ }
25125
+ ) })
25126
+ ] })
25127
+ ] })
25128
+ ]
24777
25129
  }
24778
25130
  ),
24779
25131
  anchorElement
@@ -24973,11 +25325,179 @@ const CommentBubblePlugin = () => {
24973
25325
  }, [editor, getCommentById]);
24974
25326
  return null;
24975
25327
  };
24976
- const FloatingEmbedMenuPlugin$1 = "";
24977
- function FloatingEmbedMenu({
24978
- editor,
24979
- anchorElem,
24980
- nodeKey,
25328
+ const ACCEPTABLE_IMAGE_TYPES = [
25329
+ "image/",
25330
+ "image/heic",
25331
+ "image/heif",
25332
+ "image/gif",
25333
+ "image/webp",
25334
+ "image/png",
25335
+ "image/jpg",
25336
+ "image/jpeg",
25337
+ "image/svg+xml"
25338
+ ];
25339
+ const ACCEPTABLE_APPLICATION_TYPES = [
25340
+ "application/pdf",
25341
+ "application/msword",
25342
+ "application/vnd.openxmlformats-officedocument.wordprocessingml.document"
25343
+ ];
25344
+ const fileToDataURL = (file) => {
25345
+ return new Promise((resolve, reject) => {
25346
+ const reader = new FileReader();
25347
+ reader.onload = () => resolve(reader.result);
25348
+ reader.onerror = reject;
25349
+ reader.readAsDataURL(file);
25350
+ });
25351
+ };
25352
+ function DragDropPaste() {
25353
+ const [editor] = useLexicalComposerContext();
25354
+ const [isDragging, setIsDragging] = useState$1(false);
25355
+ const apiKey = void 0;
25356
+ const { uploadFileToS3 } = useS3Uploader(apiKey);
25357
+ useEffect$1(() => {
25358
+ const handleDragEnter = (e) => {
25359
+ var _a, _b;
25360
+ e.preventDefault();
25361
+ e.stopPropagation();
25362
+ const hasFiles = (_a = e.dataTransfer) == null ? void 0 : _a.types.includes("Files");
25363
+ const hasImages = (_b = e.dataTransfer) == null ? void 0 : _b.types.some(
25364
+ (type) => type === "text/html" || type === "text/uri-list"
25365
+ );
25366
+ if (hasFiles || hasImages) {
25367
+ setIsDragging(true);
25368
+ const editorEl = editor.getRootElement();
25369
+ if (editorEl) {
25370
+ editorEl.style.backgroundColor = "rgba(59, 130, 246, 0.05)";
25371
+ editorEl.style.border = "2px dashed rgb(59, 130, 246)";
25372
+ editorEl.style.borderRadius = "8px";
25373
+ }
25374
+ }
25375
+ };
25376
+ const handleDragOver = (e) => {
25377
+ e.preventDefault();
25378
+ e.stopPropagation();
25379
+ if (e.dataTransfer) {
25380
+ e.dataTransfer.dropEffect = "copy";
25381
+ }
25382
+ };
25383
+ const handleDragLeave = (e) => {
25384
+ e.preventDefault();
25385
+ e.stopPropagation();
25386
+ const editorEl = editor.getRootElement();
25387
+ if (e.relatedTarget === null || editorEl && !editorEl.contains(e.relatedTarget)) {
25388
+ setIsDragging(false);
25389
+ if (editorEl) {
25390
+ editorEl.style.backgroundColor = "";
25391
+ editorEl.style.border = "";
25392
+ editorEl.style.borderRadius = "";
25393
+ }
25394
+ }
25395
+ };
25396
+ const handleDrop = (e) => {
25397
+ var _a, _b, _c;
25398
+ e.preventDefault();
25399
+ e.stopPropagation();
25400
+ setIsDragging(false);
25401
+ const editorEl = editor.getRootElement();
25402
+ if (editorEl) {
25403
+ editorEl.style.backgroundColor = "";
25404
+ editorEl.style.border = "";
25405
+ editorEl.style.borderRadius = "";
25406
+ }
25407
+ const files = (_a = e.dataTransfer) == null ? void 0 : _a.files;
25408
+ if (files && files.length > 0) {
25409
+ console.log("File drop detected, letting DRAG_DROP_PASTE command handle it");
25410
+ return;
25411
+ }
25412
+ const html = (_b = e.dataTransfer) == null ? void 0 : _b.getData("text/html");
25413
+ if (html) {
25414
+ const tempDiv = document.createElement("div");
25415
+ tempDiv.innerHTML = html;
25416
+ const img = tempDiv.querySelector("img");
25417
+ if (img && img.src) {
25418
+ editor.dispatchCommand(INSERT_IMAGE_COMMAND, {
25419
+ altText: img.alt || "Dragged image",
25420
+ src: img.src
25421
+ });
25422
+ console.log("Image from web browser inserted:", img.src);
25423
+ return;
25424
+ }
25425
+ }
25426
+ const uriList = (_c = e.dataTransfer) == null ? void 0 : _c.getData("text/uri-list");
25427
+ if (uriList) {
25428
+ const urls = uriList.split("\n").filter((url) => url.trim().length > 0);
25429
+ urls.forEach((url) => {
25430
+ if (/\.(jpg|jpeg|png|gif|webp|svg)$/i.test(url)) {
25431
+ editor.dispatchCommand(INSERT_IMAGE_COMMAND, {
25432
+ altText: "Dragged image",
25433
+ src: url.trim()
25434
+ });
25435
+ console.log("Image from URL inserted:", url);
25436
+ }
25437
+ });
25438
+ }
25439
+ };
25440
+ const editorElement = editor.getRootElement();
25441
+ if (editorElement) {
25442
+ editorElement.addEventListener("dragenter", handleDragEnter);
25443
+ editorElement.addEventListener("dragover", handleDragOver);
25444
+ editorElement.addEventListener("dragleave", handleDragLeave);
25445
+ editorElement.addEventListener("drop", handleDrop);
25446
+ return () => {
25447
+ editorElement.removeEventListener("dragenter", handleDragEnter);
25448
+ editorElement.removeEventListener("dragover", handleDragOver);
25449
+ editorElement.removeEventListener("dragleave", handleDragLeave);
25450
+ editorElement.removeEventListener("drop", handleDrop);
25451
+ };
25452
+ }
25453
+ }, [editor]);
25454
+ useEffect$1(() => {
25455
+ return editor.registerCommand(
25456
+ DRAG_DROP_PASTE,
25457
+ (files) => {
25458
+ (async () => {
25459
+ const filesResult = await mediaFileReader(files, [
25460
+ ...ACCEPTABLE_IMAGE_TYPES,
25461
+ ...ACCEPTABLE_APPLICATION_TYPES
25462
+ ]);
25463
+ for (const { file, result } of filesResult) {
25464
+ let fileUrl;
25465
+ try {
25466
+ if (apiKey)
25467
+ ;
25468
+ else {
25469
+ fileUrl = await fileToDataURL(file);
25470
+ console.log("Using local data URL (no S3 upload)");
25471
+ }
25472
+ } catch (error) {
25473
+ console.error("Upload failed, using local data URL:", error);
25474
+ fileUrl = await fileToDataURL(file);
25475
+ }
25476
+ if (isMimeType(file, ACCEPTABLE_IMAGE_TYPES)) {
25477
+ editor.dispatchCommand(INSERT_IMAGE_COMMAND, {
25478
+ altText: file.name,
25479
+ src: fileUrl
25480
+ });
25481
+ } else if (isMimeType(file, ACCEPTABLE_APPLICATION_TYPES)) {
25482
+ editor.dispatchCommand(INSERT_FILE_COMMAND, {
25483
+ linkText: file.name || "Download File",
25484
+ src: fileUrl
25485
+ });
25486
+ }
25487
+ }
25488
+ })();
25489
+ return true;
25490
+ },
25491
+ COMMAND_PRIORITY_LOW
25492
+ );
25493
+ }, [editor, apiKey, uploadFileToS3]);
25494
+ return null;
25495
+ }
25496
+ const FloatingEmbedMenuPlugin$1 = "";
25497
+ function FloatingEmbedMenu({
25498
+ editor,
25499
+ anchorElem,
25500
+ nodeKey,
24981
25501
  url,
24982
25502
  onClose
24983
25503
  }) {
@@ -26932,6 +27452,203 @@ function NewMentionsPlugin({
26932
27452
  }
26933
27453
  );
26934
27454
  }
27455
+ function RichTextPastePlugin() {
27456
+ const [editor] = useLexicalComposerContext();
27457
+ useEffect$1(() => {
27458
+ return editor.registerCommand(
27459
+ PASTE_COMMAND,
27460
+ (event) => {
27461
+ const clipboardData = event.clipboardData;
27462
+ if (!clipboardData)
27463
+ return false;
27464
+ const htmlContent = clipboardData.getData("text/html");
27465
+ const plainText = clipboardData.getData("text/plain");
27466
+ if (htmlContent) {
27467
+ event.preventDefault();
27468
+ handleHtmlPaste(htmlContent);
27469
+ return true;
27470
+ } else if (plainText) {
27471
+ event.preventDefault();
27472
+ handleMarkdownPaste(plainText);
27473
+ return true;
27474
+ }
27475
+ return false;
27476
+ },
27477
+ COMMAND_PRIORITY_LOW
27478
+ );
27479
+ }, [editor]);
27480
+ const handleHtmlPaste = (htmlContent) => {
27481
+ editor.update(() => {
27482
+ const selection = $getSelection();
27483
+ if ($isRangeSelection(selection)) {
27484
+ const tempDiv = document.createElement("div");
27485
+ tempDiv.innerHTML = htmlContent;
27486
+ const processNode = (node) => {
27487
+ if (node.nodeType === Node.TEXT_NODE) {
27488
+ const text = node.textContent || "";
27489
+ const textNode = $createTextNode(text);
27490
+ if (node.parentElement) {
27491
+ if (node.parentElement.tagName === "STRONG" || node.parentElement.tagName === "B") {
27492
+ textNode.setFormat("bold");
27493
+ }
27494
+ if (node.parentElement.tagName === "EM" || node.parentElement.tagName === "I") {
27495
+ textNode.setFormat("italic");
27496
+ }
27497
+ if (node.parentElement.tagName === "U") {
27498
+ textNode.setFormat("underline");
27499
+ }
27500
+ if (node.parentElement.tagName === "CODE") {
27501
+ textNode.setFormat("code");
27502
+ }
27503
+ if (node.parentElement.tagName === "STRIKE" || node.parentElement.tagName === "S") {
27504
+ textNode.setFormat("strikethrough");
27505
+ }
27506
+ if (node.parentElement.tagName === "SUB") {
27507
+ textNode.setFormat("subscript");
27508
+ }
27509
+ if (node.parentElement.tagName === "SUP") {
27510
+ textNode.setFormat("superscript");
27511
+ }
27512
+ }
27513
+ return textNode;
27514
+ }
27515
+ if (node.nodeType === Node.ELEMENT_NODE) {
27516
+ const element = node;
27517
+ if (element.tagName === "UL" || element.tagName === "OL") {
27518
+ const listNode = $createListNode(
27519
+ element.tagName === "UL" ? "bullet" : "number"
27520
+ );
27521
+ Array.from(element.childNodes).forEach((child) => {
27522
+ if (child.nodeType === Node.ELEMENT_NODE && child.tagName === "LI") {
27523
+ const listItemNode = $createListItemNode();
27524
+ Array.from(child.childNodes).forEach((grandChild) => {
27525
+ const processedNode = processNode(grandChild);
27526
+ if (processedNode) {
27527
+ if (Array.isArray(processedNode)) {
27528
+ processedNode.forEach(
27529
+ (node2) => listItemNode.append(node2)
27530
+ );
27531
+ } else {
27532
+ listItemNode.append(processedNode);
27533
+ }
27534
+ }
27535
+ });
27536
+ listNode.append(listItemNode);
27537
+ }
27538
+ });
27539
+ return listNode;
27540
+ }
27541
+ if (element.tagName.match(/^H[1-6]$/)) {
27542
+ const headingNode = $createHeadingNode(
27543
+ element.tagName.toLowerCase()
27544
+ );
27545
+ Array.from(element.childNodes).forEach((child) => {
27546
+ const processedNode = processNode(child);
27547
+ if (processedNode) {
27548
+ if (Array.isArray(processedNode)) {
27549
+ processedNode.forEach((node2) => headingNode.append(node2));
27550
+ } else {
27551
+ headingNode.append(processedNode);
27552
+ }
27553
+ }
27554
+ });
27555
+ return headingNode;
27556
+ }
27557
+ if (element.tagName === "P") {
27558
+ const paragraphNode = $createParagraphNode();
27559
+ Array.from(element.childNodes).forEach((child) => {
27560
+ const processedNode = processNode(child);
27561
+ if (processedNode) {
27562
+ if (Array.isArray(processedNode)) {
27563
+ processedNode.forEach((node2) => paragraphNode.append(node2));
27564
+ } else {
27565
+ paragraphNode.append(processedNode);
27566
+ }
27567
+ }
27568
+ });
27569
+ return paragraphNode;
27570
+ }
27571
+ const nodes = [];
27572
+ Array.from(element.childNodes).forEach((child) => {
27573
+ const processedNode = processNode(child);
27574
+ if (processedNode) {
27575
+ if (Array.isArray(processedNode)) {
27576
+ nodes.push(...processedNode);
27577
+ } else {
27578
+ nodes.push(processedNode);
27579
+ }
27580
+ }
27581
+ });
27582
+ return nodes;
27583
+ }
27584
+ return null;
27585
+ };
27586
+ const processedNodes = processNode(tempDiv);
27587
+ if (processedNodes) {
27588
+ if (Array.isArray(processedNodes)) {
27589
+ selection.insertNodes(processedNodes);
27590
+ } else {
27591
+ selection.insertNodes([processedNodes]);
27592
+ }
27593
+ }
27594
+ }
27595
+ });
27596
+ };
27597
+ const handleMarkdownPaste = (text) => {
27598
+ editor.update(() => {
27599
+ const selection = $getSelection();
27600
+ if ($isRangeSelection(selection)) {
27601
+ const lines = text.split("\n");
27602
+ const nodes = [];
27603
+ lines.forEach((line) => {
27604
+ const headingMatch = line.match(/^(#{1,6})\s+(.+)$/);
27605
+ if (headingMatch) {
27606
+ const level = headingMatch[1].length;
27607
+ const content = headingMatch[2];
27608
+ const headingNode = $createHeadingNode(
27609
+ `h${level}`
27610
+ );
27611
+ headingNode.append($createTextNode(content));
27612
+ nodes.push(headingNode);
27613
+ return;
27614
+ }
27615
+ const bulletMatch = line.match(/^-\s+(.+)$/);
27616
+ if (bulletMatch) {
27617
+ const listNode = $createListNode("bullet");
27618
+ const listItemNode = $createListItemNode();
27619
+ listItemNode.append($createTextNode(bulletMatch[1]));
27620
+ listNode.append(listItemNode);
27621
+ nodes.push(listNode);
27622
+ return;
27623
+ }
27624
+ const numberedMatch = line.match(/^\d+\.\s+(.+)$/);
27625
+ if (numberedMatch) {
27626
+ const listNode = $createListNode("number");
27627
+ const listItemNode = $createListItemNode();
27628
+ listItemNode.append($createTextNode(numberedMatch[1]));
27629
+ listNode.append(listItemNode);
27630
+ nodes.push(listNode);
27631
+ return;
27632
+ }
27633
+ const textNode = $createTextNode(line);
27634
+ if (line.includes("**") || line.includes("__")) {
27635
+ textNode.setFormat("bold");
27636
+ }
27637
+ if (line.includes("*") || line.includes("_")) {
27638
+ textNode.setFormat("italic");
27639
+ }
27640
+ if (line.includes("***") || line.includes("___")) {
27641
+ textNode.setFormat("bold");
27642
+ textNode.setFormat("italic");
27643
+ }
27644
+ nodes.push(textNode);
27645
+ });
27646
+ selection.insertNodes(nodes);
27647
+ }
27648
+ });
27649
+ };
27650
+ return null;
27651
+ }
26935
27652
  function useModal() {
26936
27653
  const [modalContent, setModalContent] = useState$1(null);
26937
27654
  const onClose = useCallback(() => {
@@ -27477,8 +28194,79 @@ function TableActionMenu({
27477
28194
  for (let i2 = 0; i2 < selectionCounts.columns; i2++) {
27478
28195
  $insertTableColumn__EXPERIMENTAL(shouldInsertAfter);
27479
28196
  }
28197
+ const selection = $getSelection();
28198
+ if ($isRangeSelection(selection) || $isTableSelection(selection)) {
28199
+ const [cell] = $getNodeTriplet(selection.anchor);
28200
+ if ($isTableCellNode(cell)) {
28201
+ const tableNode = $getTableNodeFromLexicalNodeOrThrow(cell);
28202
+ const rows = tableNode.getChildren();
28203
+ if (rows.length > 0 && $isTableRowNode(rows[0])) {
28204
+ const firstRow = rows[0];
28205
+ const firstRowCells = firstRow.getChildren();
28206
+ if (firstRowCells.length > 0 && $isTableCellNode(firstRowCells[0])) {
28207
+ const firstCell = firstRowCells[0];
28208
+ const hasColumnHeaders = (firstCell.getHeaderStyles() & TableCellHeaderStates.COLUMN) === TableCellHeaderStates.COLUMN;
28209
+ if (hasColumnHeaders) {
28210
+ const headerBackgroundColor = firstCell.getBackgroundColor();
28211
+ for (let i2 = 0; i2 < selectionCounts.columns; i2++) {
28212
+ const newHeaderCellIndex = firstRowCells.length - 1 - i2;
28213
+ if (newHeaderCellIndex >= 0) {
28214
+ const newHeaderCell = firstRowCells[newHeaderCellIndex];
28215
+ if ($isTableCellNode(newHeaderCell)) {
28216
+ newHeaderCell.setHeaderStyles(TableCellHeaderStates.COLUMN);
28217
+ if (headerBackgroundColor) {
28218
+ newHeaderCell.setBackgroundColor(headerBackgroundColor);
28219
+ }
28220
+ }
28221
+ }
28222
+ }
28223
+ }
28224
+ }
28225
+ }
28226
+ }
28227
+ }
27480
28228
  onClose();
27481
28229
  });
28230
+ requestAnimationFrame(() => {
28231
+ const applyHeaderStyles = () => {
28232
+ const rootElement = editor.getRootElement();
28233
+ if (!rootElement)
28234
+ return false;
28235
+ const tables = rootElement.querySelectorAll("table");
28236
+ tables.forEach((table) => {
28237
+ const rows = table.querySelectorAll("tr");
28238
+ if (rows.length > 0) {
28239
+ const firstRow = rows[0];
28240
+ const cells = firstRow.querySelectorAll("th, td");
28241
+ if (cells.length > 1) {
28242
+ const firstHeaderCell = cells[0];
28243
+ const headerColor = firstHeaderCell.getAttribute("data-header-color");
28244
+ const textColor = firstHeaderCell.getAttribute("data-text-color");
28245
+ if (headerColor && textColor) {
28246
+ for (let i2 = 0; i2 < selectionCounts.columns; i2++) {
28247
+ const cellIndex = cells.length - 1 - i2;
28248
+ if (cellIndex >= 0) {
28249
+ const newCell = cells[cellIndex];
28250
+ newCell.setAttribute("data-header-color", headerColor);
28251
+ newCell.setAttribute("data-text-color", textColor);
28252
+ newCell.style.setProperty("background-color", headerColor, "important");
28253
+ newCell.style.setProperty("color", textColor, "important");
28254
+ newCell.style.setProperty("padding", "8px", "important");
28255
+ newCell.style.setProperty("border", "1px solid #ddd", "important");
28256
+ newCell.style.setProperty("font-weight", "bold", "important");
28257
+ newCell.style.setProperty("white-space", "nowrap", "important");
28258
+ }
28259
+ }
28260
+ }
28261
+ }
28262
+ }
28263
+ });
28264
+ return true;
28265
+ };
28266
+ if (!applyHeaderStyles()) {
28267
+ setTimeout(applyHeaderStyles, 100);
28268
+ }
28269
+ });
27482
28270
  },
27483
28271
  [editor, onClose, selectionCounts.columns]
27484
28272
  );
@@ -28475,9 +29263,72 @@ function TableHoverActionsContainer({
28475
29263
  } else {
28476
29264
  $insertTableColumn__EXPERIMENTAL();
28477
29265
  setShownColumn(false);
29266
+ const tableCellNode = $getNearestNodeFromDOMNode(tableCellDOMNodeRef.current);
29267
+ if ($isTableCellNode(tableCellNode)) {
29268
+ const tableNode = $findMatchingParent(
29269
+ tableCellNode,
29270
+ (node) => $isTableNode(node)
29271
+ );
29272
+ if ($isTableNode(tableNode)) {
29273
+ const rows = tableNode.getChildren();
29274
+ if (rows.length > 0) {
29275
+ const firstRow = rows[0];
29276
+ const firstRowCells = firstRow.getChildren();
29277
+ if (firstRowCells.length > 0) {
29278
+ const firstCell = firstRowCells[0];
29279
+ const hasColumnHeaders = (firstCell.getHeaderStyles() & TableCellHeaderStates.COLUMN) === TableCellHeaderStates.COLUMN;
29280
+ if (hasColumnHeaders) {
29281
+ const newHeaderCell = firstRowCells[firstRowCells.length - 1];
29282
+ newHeaderCell.setHeaderStyles(TableCellHeaderStates.COLUMN);
29283
+ const headerBackgroundColor = firstCell.getBackgroundColor();
29284
+ if (headerBackgroundColor) {
29285
+ newHeaderCell.setBackgroundColor(headerBackgroundColor);
29286
+ }
29287
+ }
29288
+ }
29289
+ }
29290
+ }
29291
+ }
28478
29292
  }
28479
29293
  }
28480
29294
  });
29295
+ if (!insertRow) {
29296
+ requestAnimationFrame(() => {
29297
+ const applyHeaderStyles = () => {
29298
+ const rootElement = editor.getRootElement();
29299
+ if (!rootElement)
29300
+ return false;
29301
+ const tables = rootElement.querySelectorAll("table");
29302
+ tables.forEach((table) => {
29303
+ const rows = table.querySelectorAll("tr");
29304
+ if (rows.length > 0) {
29305
+ const firstRow = rows[0];
29306
+ const cells = firstRow.querySelectorAll("th, td");
29307
+ if (cells.length > 1) {
29308
+ const firstHeaderCell = cells[0];
29309
+ const headerColor = firstHeaderCell.getAttribute("data-header-color");
29310
+ const textColor = firstHeaderCell.getAttribute("data-text-color");
29311
+ if (headerColor && textColor) {
29312
+ const lastCell = cells[cells.length - 1];
29313
+ lastCell.setAttribute("data-header-color", headerColor);
29314
+ lastCell.setAttribute("data-text-color", textColor);
29315
+ lastCell.style.setProperty("background-color", headerColor, "important");
29316
+ lastCell.style.setProperty("color", textColor, "important");
29317
+ lastCell.style.setProperty("padding", "8px", "important");
29318
+ lastCell.style.setProperty("border", "1px solid #ddd", "important");
29319
+ lastCell.style.setProperty("font-weight", "bold", "important");
29320
+ lastCell.style.setProperty("white-space", "nowrap", "important");
29321
+ }
29322
+ }
29323
+ }
29324
+ });
29325
+ return true;
29326
+ };
29327
+ if (!applyHeaderStyles()) {
29328
+ setTimeout(applyHeaderStyles, 100);
29329
+ }
29330
+ });
29331
+ }
28481
29332
  };
28482
29333
  if (!isEditable) {
28483
29334
  return null;
@@ -28528,6 +29379,46 @@ function TableHoverActionsPlugin({
28528
29379
  anchorElem
28529
29380
  ) : null;
28530
29381
  }
29382
+ function getOptionMeta(label) {
29383
+ const lower = label.toLowerCase();
29384
+ if (lower.startsWith("paragraph")) {
29385
+ return { icon: /* @__PURE__ */ jsx(Type, { className: "cteditor-size-4" }), description: "Start a new paragraph", shortcut: "P" };
29386
+ }
29387
+ if (lower.includes("heading 1")) {
29388
+ return { icon: /* @__PURE__ */ jsx(Heading1, { className: "cteditor-size-4" }), description: "Large section title", shortcut: "H1" };
29389
+ }
29390
+ if (lower.includes("heading 2")) {
29391
+ return { icon: /* @__PURE__ */ jsx(Heading2, { className: "cteditor-size-4" }), description: "Section heading", shortcut: "H2" };
29392
+ }
29393
+ if (lower.includes("heading 3")) {
29394
+ return { icon: /* @__PURE__ */ jsx(Heading3, { className: "cteditor-size-4" }), description: "Subsection heading", shortcut: "H3" };
29395
+ }
29396
+ if (lower.includes("bullet")) {
29397
+ return { icon: /* @__PURE__ */ jsx(List$1, { className: "cteditor-size-4" }), description: "Create a bulleted list", shortcut: "•" };
29398
+ }
29399
+ if (lower.includes("numbered")) {
29400
+ return { icon: /* @__PURE__ */ jsx(ListOrdered, { className: "cteditor-size-4" }), description: "Create a numbered list", shortcut: "1." };
29401
+ }
29402
+ if (lower.includes("todo")) {
29403
+ return { icon: /* @__PURE__ */ jsx(ListChecks, { className: "cteditor-size-4" }), description: "Create a checklist", shortcut: "[ ]" };
29404
+ }
29405
+ if (lower.includes("image")) {
29406
+ return { icon: /* @__PURE__ */ jsx(Image$2, { className: "cteditor-size-4" }), description: "Insert an image", shortcut: "Img" };
29407
+ }
29408
+ if (lower.includes("video")) {
29409
+ return { icon: /* @__PURE__ */ jsx(Video, { className: "cteditor-size-4" }), description: "Embed a video", shortcut: "Vid" };
29410
+ }
29411
+ if (lower.includes("align left")) {
29412
+ return { icon: /* @__PURE__ */ jsx(AlignLeft, { className: "cteditor-size-4" }), description: "Align text left" };
29413
+ }
29414
+ if (lower.includes("align center")) {
29415
+ return { icon: /* @__PURE__ */ jsx(AlignCenter, { className: "cteditor-size-4" }), description: "Align text center" };
29416
+ }
29417
+ if (lower.includes("align right")) {
29418
+ return { icon: /* @__PURE__ */ jsx(AlignRight, { className: "cteditor-size-4" }), description: "Align text right" };
29419
+ }
29420
+ return { icon: /* @__PURE__ */ jsx(Type, { className: "cteditor-size-4" }) };
29421
+ }
28531
29422
  class SlashMenuOption extends MenuOption {
28532
29423
  constructor(label, onSelect) {
28533
29424
  super(label);
@@ -28544,22 +29435,26 @@ function SlashMenuItem({
28544
29435
  onMouseEnter,
28545
29436
  option
28546
29437
  }) {
28547
- let className = "item";
28548
- if (isSelected) {
28549
- className += " selected";
28550
- }
28551
- return /* @__PURE__ */ jsx(
29438
+ const meta = getOptionMeta(option.label);
29439
+ return /* @__PURE__ */ jsxs(
28552
29440
  "li",
28553
29441
  {
28554
29442
  tabIndex: -1,
28555
- className,
29443
+ className: (isSelected ? "cteditor-bg-primary/10 cteditor-border-primary/40 cteditor-shadow-md " : "hover:cteditor-bg-accent/50 hover:cteditor-border-primary/30 hover:cteditor-shadow ") + "cteditor-group cteditor-flex cteditor-items-center cteditor-gap-3 cteditor-px-3 cteditor-py-2 cteditor-rounded-xl cteditor-transition-all cteditor-duration-200 cteditor-cursor-pointer cteditor-border cteditor-border-border hover:cteditor-translate-x-[1px]",
28556
29444
  ref: option.setRefElement,
28557
29445
  role: "option",
28558
29446
  "aria-selected": isSelected,
28559
29447
  id: "typeahead-item-" + index2,
28560
29448
  onMouseEnter,
28561
29449
  onClick,
28562
- children: /* @__PURE__ */ jsx("div", { className: "slash-item", children: /* @__PURE__ */ jsx("span", { className: "text slash-item__label", children: option.label }) })
29450
+ children: [
29451
+ /* @__PURE__ */ jsx("div", { className: "cteditor-flex cteditor-items-center cteditor-justify-center cteditor-rounded-lg cteditor-h-8 cteditor-w-8 cteditor-text-primary cteditor-bg-gradient-to-br cteditor-from-primary/10 cteditor-to-accent/10 group-hover:cteditor-from-primary/20 group-hover:cteditor-to-accent/20", children: meta.icon }),
29452
+ /* @__PURE__ */ jsxs("div", { className: "cteditor-flex cteditor-flex-col cteditor-gap-0.5 cteditor-min-w-0", children: [
29453
+ /* @__PURE__ */ jsx("span", { className: "cteditor-text-sm cteditor-font-semibold cteditor-text-foreground cteditor-truncate", children: option.label }),
29454
+ meta.description && /* @__PURE__ */ jsx("span", { className: "cteditor-text-xs cteditor-text-muted-foreground cteditor-truncate", children: meta.description })
29455
+ ] }),
29456
+ meta.shortcut && /* @__PURE__ */ jsx("span", { className: "cteditor-ml-auto cteditor-text-[10px] cteditor-text-muted-foreground cteditor-border cteditor-border-border cteditor-rounded-md cteditor-px-1.5 cteditor-py-0.5 cteditor-bg-foreground/5", children: meta.shortcut })
29457
+ ]
28563
29458
  },
28564
29459
  option.key
28565
29460
  );
@@ -28567,6 +29462,10 @@ function SlashMenuItem({
28567
29462
  function SlashCommandPlugin() {
28568
29463
  const [editor] = useLexicalComposerContext();
28569
29464
  const [queryString, setQueryString] = useState$1(null);
29465
+ const menuRef = useRef(null);
29466
+ const [menuPosition, setMenuPosition] = useState$1({ left: 0 });
29467
+ const anchorRef = useRef(null);
29468
+ const [isMenuOpen, setIsMenuOpen] = useState$1(false);
28570
29469
  const triggerFn = useBasicTypeaheadTriggerMatch("/", { minLength: 0 });
28571
29470
  const makeBlock = useCallback((cb) => {
28572
29471
  editor.update(() => {
@@ -28653,9 +29552,55 @@ function SlashCommandPlugin() {
28653
29552
  }
28654
29553
  });
28655
29554
  closeMenu();
29555
+ setIsMenuOpen(false);
28656
29556
  },
28657
29557
  [editor]
28658
29558
  );
29559
+ useEffect$1(() => {
29560
+ if (!isMenuOpen) {
29561
+ return;
29562
+ }
29563
+ const menu = menuRef.current;
29564
+ const anchor = anchorRef.current;
29565
+ if (!menu || !anchor) {
29566
+ return;
29567
+ }
29568
+ const updatePosition = () => {
29569
+ const menuRect = menu.getBoundingClientRect();
29570
+ const viewportHeight = window.innerHeight;
29571
+ const viewportWidth = window.innerWidth;
29572
+ const anchorRect = anchor.getBoundingClientRect();
29573
+ const spaceBelow = viewportHeight - anchorRect.bottom;
29574
+ const spaceAbove = anchorRect.top;
29575
+ const menuHeight = menuRect.height || 240;
29576
+ const menuWidth = menuRect.width || 288;
29577
+ let newPosition = { left: anchorRect.left };
29578
+ if (spaceBelow >= menuHeight || spaceBelow >= spaceAbove) {
29579
+ newPosition.top = anchorRect.bottom + 4;
29580
+ } else {
29581
+ newPosition.bottom = viewportHeight - anchorRect.top + 4;
29582
+ }
29583
+ if (anchorRect.left + menuWidth > viewportWidth) {
29584
+ newPosition.left = Math.max(8, viewportWidth - menuWidth - 8);
29585
+ } else {
29586
+ newPosition.left = Math.max(8, anchorRect.left);
29587
+ }
29588
+ setMenuPosition((prev) => {
29589
+ if (prev.top === newPosition.top && prev.bottom === newPosition.bottom && prev.left === newPosition.left) {
29590
+ return prev;
29591
+ }
29592
+ return newPosition;
29593
+ });
29594
+ };
29595
+ const timeoutId = setTimeout(updatePosition, 0);
29596
+ window.addEventListener("scroll", updatePosition, true);
29597
+ window.addEventListener("resize", updatePosition);
29598
+ return () => {
29599
+ clearTimeout(timeoutId);
29600
+ window.removeEventListener("scroll", updatePosition, true);
29601
+ window.removeEventListener("resize", updatePosition);
29602
+ };
29603
+ }, [isMenuOpen]);
28659
29604
  return /* @__PURE__ */ jsx(
28660
29605
  LexicalTypeaheadMenuPlugin,
28661
29606
  {
@@ -28663,27 +29608,54 @@ function SlashCommandPlugin() {
28663
29608
  onSelectOption,
28664
29609
  triggerFn,
28665
29610
  options,
28666
- menuRenderFn: (anchorElementRef, { selectedIndex, selectOptionAndCleanUp, setHighlightedIndex }) => anchorElementRef.current ? ReactDOM.createPortal(
28667
- /* @__PURE__ */ jsx("div", { className: "typeahead-popover slash-menu", children: options.length > 0 ? /* @__PURE__ */ jsx("ul", { children: options.map((option, i2) => /* @__PURE__ */ jsx(
28668
- SlashMenuItem,
28669
- {
28670
- index: i2,
28671
- isSelected: selectedIndex === i2,
28672
- onClick: () => {
28673
- setHighlightedIndex(i2);
28674
- selectOptionAndCleanUp(option);
28675
- },
28676
- onMouseEnter: () => {
28677
- setHighlightedIndex(i2);
28678
- },
28679
- option
28680
- },
28681
- option.key
28682
- )) }) : /* @__PURE__ */ jsx("div", { className: "no-users-found", children: "No results" }) }),
28683
- anchorElementRef.current
28684
- ) : null
28685
- }
28686
- );
29611
+ menuRenderFn: (anchorElementRef, { selectedIndex, selectOptionAndCleanUp, setHighlightedIndex }) => {
29612
+ anchorRef.current = anchorElementRef.current;
29613
+ if (anchorElementRef.current && !isMenuOpen) {
29614
+ setIsMenuOpen(true);
29615
+ } else if (!anchorElementRef.current && isMenuOpen) {
29616
+ setIsMenuOpen(false);
29617
+ }
29618
+ return anchorElementRef.current ? ReactDOM.createPortal(
29619
+ /* @__PURE__ */ jsxs(
29620
+ "div",
29621
+ {
29622
+ ref: menuRef,
29623
+ className: "cteditor-w-72 cteditor-max-h-60 cteditor-overflow-y-auto no-scrollbar cteditor-backdrop-blur-md cteditor-shadow-xl cteditor-rounded-lg cteditor-border cteditor-border-border cteditor-p-1.5 cteditor-bg-background cteditor-z-50",
29624
+ style: {
29625
+ position: "fixed",
29626
+ top: menuPosition.top,
29627
+ bottom: menuPosition.bottom,
29628
+ left: menuPosition.left
29629
+ },
29630
+ children: [
29631
+ /* @__PURE__ */ jsxs("div", { className: "cteditor-flex cteditor-items-center cteditor-justify-between cteditor-px-2 cteditor-py-1 cteditor-text-[11px] cteditor-text-muted-foreground", children: [
29632
+ /* @__PURE__ */ jsx("span", { children: queryString ? "Search results" : "Quick actions" }),
29633
+ /* @__PURE__ */ jsx("span", { className: "cteditor-hidden sm:cteditor-inline", children: "Type to filter" })
29634
+ ] }),
29635
+ options.length > 0 ? /* @__PURE__ */ jsx("ul", { className: "cteditor-space-y-1", children: options.map((option, i2) => /* @__PURE__ */ jsx(
29636
+ SlashMenuItem,
29637
+ {
29638
+ index: i2,
29639
+ isSelected: selectedIndex === i2,
29640
+ onClick: () => {
29641
+ setHighlightedIndex(i2);
29642
+ selectOptionAndCleanUp(option);
29643
+ },
29644
+ onMouseEnter: () => {
29645
+ setHighlightedIndex(i2);
29646
+ },
29647
+ option
29648
+ },
29649
+ option.key
29650
+ )) }) : /* @__PURE__ */ jsx("div", { className: "cteditor-text-[11px] cteditor-text-muted-foreground cteditor-px-3 cteditor-py-2", children: "No results" })
29651
+ ]
29652
+ }
29653
+ ),
29654
+ anchorElementRef.current
29655
+ ) : null;
29656
+ }
29657
+ }
29658
+ );
28687
29659
  }
28688
29660
  const WordCountPlugin = () => {
28689
29661
  const [editor] = useLexicalComposerContext();
@@ -28733,402 +29705,14 @@ const WordCountPlugin = () => {
28733
29705
  }
28734
29706
  );
28735
29707
  };
28736
- const GrammarCheckPlugin$1 = "";
28737
- class GrammarCheckService {
28738
- constructor() {
28739
- __publicField(this, "cache", /* @__PURE__ */ new Map());
28740
- __publicField(this, "apiEndpoint");
28741
- __publicField(this, "pendingRequest", null);
28742
- this.apiEndpoint = "https://api.cteditor.com/api/ai/process";
28743
- }
28744
- async check(text) {
28745
- if (!text || text.trim().length < 3) {
28746
- return [];
28747
- }
28748
- const cacheKey = text.trim();
28749
- if (this.cache.has(cacheKey)) {
28750
- return this.cache.get(cacheKey);
28751
- }
28752
- if (this.pendingRequest) {
28753
- return this.pendingRequest;
28754
- }
28755
- this.pendingRequest = this.executeCheck(text);
28756
- try {
28757
- const result = await this.pendingRequest;
28758
- return result;
28759
- } finally {
28760
- this.pendingRequest = null;
28761
- }
28762
- }
28763
- async executeCheck(text) {
28764
- var _a, _b, _c, _d, _e, _f;
28765
- try {
28766
- const response = await fetch(this.apiEndpoint, {
28767
- method: "POST",
28768
- headers: { "Content-Type": "application/json" },
28769
- body: JSON.stringify({ text: text.trim(), maxSuggestions: 3 }),
28770
- signal: AbortSignal.timeout(1e4)
28771
- });
28772
- if (!response.ok) {
28773
- console.error("❌ GrammarCheck: API error:", response.status);
28774
- return [];
28775
- }
28776
- const result = await response.json();
28777
- const foundErrors = [];
28778
- if ((_c = (_b = (_a = result.data) == null ? void 0 : _a.corrections) == null ? void 0 : _b.spelling) == null ? void 0 : _c.errors) {
28779
- result.data.corrections.spelling.errors.forEach((err, idx) => {
28780
- foundErrors.push({
28781
- type: "spelling",
28782
- original: err.original,
28783
- suggestions: err.suggestions || [],
28784
- index: idx
28785
- });
28786
- });
28787
- }
28788
- if ((_f = (_e = (_d = result.data) == null ? void 0 : _d.corrections) == null ? void 0 : _e.grammar) == null ? void 0 : _f.errors) {
28789
- result.data.corrections.grammar.errors.forEach((err, idx) => {
28790
- foundErrors.push({
28791
- type: "grammar",
28792
- original: err.original || text,
28793
- suggestions: [err.suggestion],
28794
- index: foundErrors.length + idx,
28795
- issue: err.issue
28796
- });
28797
- });
28798
- }
28799
- this.cache.set(text.trim(), foundErrors);
28800
- if (this.cache.size > 30) {
28801
- const firstKey = this.cache.keys().next().value;
28802
- if (firstKey) {
28803
- this.cache.delete(firstKey);
28804
- }
28805
- }
28806
- return foundErrors;
28807
- } catch (error) {
28808
- console.error("❌ GrammarCheck: Check failed:", error);
28809
- return [];
28810
- }
28811
- }
28812
- }
28813
- function GrammarCheckPlugin() {
28814
- const [editor] = useLexicalComposerContext();
28815
- const { updateToolbarState } = useToolbarState();
28816
- const [errors, setErrors] = useState$1([]);
28817
- const [tooltip, setTooltip] = useState$1(null);
28818
- const [userDismissed, setUserDismissed] = useState$1(false);
28819
- const grammarService = useRef(new GrammarCheckService());
28820
- const checkTimeout = useRef();
28821
- const lastCheckedText = useRef("");
28822
- const highlightElementsRef = useRef([]);
28823
- const checkGrammar = useCallback(async () => {
28824
- const text = editor.getEditorState().read(() => $getRoot().getTextContent());
28825
- if (text === lastCheckedText.current) {
28826
- return;
28827
- }
28828
- if (Math.abs(text.length - lastCheckedText.current.length) > 20) {
28829
- setUserDismissed(false);
28830
- }
28831
- lastCheckedText.current = text;
28832
- if (!text || text.trim().length < 3) {
28833
- setErrors([]);
28834
- return;
28835
- }
28836
- const foundErrors = await grammarService.current.check(text);
28837
- setErrors(foundErrors);
28838
- }, [editor]);
28839
- useEffect$1(() => {
28840
- const unregister = editor.registerUpdateListener(() => {
28841
- clearTimeout(checkTimeout.current);
28842
- checkTimeout.current = window.setTimeout(checkGrammar, 2e3);
28843
- });
28844
- return () => {
28845
- unregister();
28846
- clearTimeout(checkTimeout.current);
28847
- };
28848
- }, [editor, checkGrammar]);
28849
- useEffect$1(() => {
28850
- highlightElementsRef.current.forEach((el) => {
28851
- el.classList.remove("spelling-error", "grammar-error");
28852
- });
28853
- highlightElementsRef.current = [];
28854
- if (errors.length === 0 || userDismissed)
28855
- return;
28856
- const timeoutId = setTimeout(() => {
28857
- const editorElement = document.querySelector(".ContentEditable__root");
28858
- if (!editorElement)
28859
- return;
28860
- const walker = document.createTreeWalker(
28861
- editorElement,
28862
- NodeFilter.SHOW_TEXT,
28863
- null
28864
- );
28865
- const textNodes = [];
28866
- let node;
28867
- while (node = walker.nextNode()) {
28868
- textNodes.push(node);
28869
- }
28870
- errors.forEach((error) => {
28871
- textNodes.forEach((textNode) => {
28872
- const nodeText = textNode.textContent || "";
28873
- const errorIndex = nodeText.toLowerCase().indexOf(error.original.toLowerCase());
28874
- if (errorIndex !== -1 && textNode.parentElement) {
28875
- const className = error.type === "spelling" ? "spelling-error" : "grammar-error";
28876
- if (textNode.parentElement.tagName === "SPAN") {
28877
- textNode.parentElement.classList.add(className);
28878
- highlightElementsRef.current.push(textNode.parentElement);
28879
- } else if (textNode.parentElement) {
28880
- const range = document.createRange();
28881
- range.setStart(textNode, errorIndex);
28882
- range.setEnd(textNode, Math.min(errorIndex + error.original.length, nodeText.length));
28883
- const span = document.createElement("span");
28884
- span.className = className;
28885
- span.setAttribute("data-error-type", error.type);
28886
- try {
28887
- range.surroundContents(span);
28888
- highlightElementsRef.current.push(span);
28889
- } catch (e) {
28890
- if (textNode.parentElement) {
28891
- textNode.parentElement.classList.add(className);
28892
- highlightElementsRef.current.push(textNode.parentElement);
28893
- }
28894
- }
28895
- }
28896
- }
28897
- });
28898
- });
28899
- }, 100);
28900
- return () => clearTimeout(timeoutId);
28901
- }, [errors, userDismissed]);
28902
- const getWordAtPoint = useCallback((x2, y2) => {
28903
- try {
28904
- let range = null;
28905
- if (document.caretRangeFromPoint) {
28906
- range = document.caretRangeFromPoint(x2, y2);
28907
- } else if (document.caretPositionFromPoint) {
28908
- const position = document.caretPositionFromPoint(x2, y2);
28909
- if (position) {
28910
- range = document.createRange();
28911
- range.setStart(position.offsetNode, position.offset);
28912
- }
28913
- }
28914
- if (!range)
28915
- return null;
28916
- const textNode = range.startContainer;
28917
- if (textNode.nodeType !== Node.TEXT_NODE)
28918
- return null;
28919
- const text = textNode.textContent || "";
28920
- let start = range.startOffset;
28921
- let end = range.startOffset;
28922
- while (start > 0 && /\w/.test(text[start - 1])) {
28923
- start--;
28924
- }
28925
- while (end < text.length && /\w/.test(text[end])) {
28926
- end++;
28927
- }
28928
- const word = text.substring(start, end).trim();
28929
- return word || null;
28930
- } catch (error) {
28931
- console.error("Error getting word at point:", error);
28932
- return null;
28933
- }
28934
- }, []);
28935
- useEffect$1(() => {
28936
- if (errors.length === 0)
28937
- return;
28938
- let hoverTimeout;
28939
- const handleMouseMove = (e) => {
28940
- clearTimeout(hoverTimeout);
28941
- hoverTimeout = window.setTimeout(() => {
28942
- const wordAtCursor = getWordAtPoint(e.clientX, e.clientY);
28943
- if (wordAtCursor) {
28944
- const matchedError = errors.find(
28945
- (err) => wordAtCursor.toLowerCase() === err.original.toLowerCase()
28946
- );
28947
- if (matchedError) {
28948
- setTooltip({
28949
- error: matchedError,
28950
- x: e.clientX,
28951
- y: e.clientY
28952
- });
28953
- }
28954
- }
28955
- }, 50);
28956
- };
28957
- const handleClick = () => {
28958
- setTooltip(null);
28959
- };
28960
- document.addEventListener("mousemove", handleMouseMove);
28961
- document.addEventListener("click", handleClick);
28962
- return () => {
28963
- clearTimeout(hoverTimeout);
28964
- document.removeEventListener("mousemove", handleMouseMove);
28965
- document.removeEventListener("click", handleClick);
28966
- };
28967
- }, [errors, getWordAtPoint]);
28968
- const applyCorrection = useCallback(
28969
- (suggestion, original, errorType) => {
28970
- editor.update(() => {
28971
- const root2 = $getRoot();
28972
- const currentText = root2.getTextContent();
28973
- const isSpellingError = errorType === "spelling";
28974
- let newText = currentText;
28975
- if (isSpellingError) {
28976
- const escapedOriginal = original.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
28977
- const regex = new RegExp(`\\b${escapedOriginal}\\b`, "gi");
28978
- newText = currentText.replace(regex, suggestion);
28979
- } else {
28980
- const escapedOriginal = original.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
28981
- const regex = new RegExp(escapedOriginal, "gi");
28982
- if (currentText.toLowerCase().includes(original.toLowerCase())) {
28983
- newText = currentText.replace(regex, suggestion);
28984
- } else {
28985
- newText = suggestion;
28986
- }
28987
- }
28988
- root2.clear();
28989
- const paragraph = $createParagraphNode();
28990
- const textNode = $createTextNode(newText);
28991
- paragraph.append(textNode);
28992
- root2.append(paragraph);
28993
- });
28994
- setTooltip(null);
28995
- setTimeout(() => {
28996
- lastCheckedText.current = "";
28997
- checkGrammar();
28998
- }, 100);
28999
- },
29000
- [editor, checkGrammar]
29001
- );
29002
- const showErrorTooltip = (error, event) => {
29003
- setTooltip({
29004
- error,
29005
- x: event.clientX,
29006
- y: event.clientY
29007
- });
29008
- };
29009
- return /* @__PURE__ */ jsxs(Fragment, { children: [
29010
- errors.length > 0 && !userDismissed && /* @__PURE__ */ jsx("div", { className: "grammar-error-panel", children: /* @__PURE__ */ jsxs("div", { className: "cteditor-flex cteditor-items-center cteditor-gap-2 cteditor-bg-amber-50 cteditor-border cteditor-border-amber-200 cteditor-rounded-lg cteditor-px-3 cteditor-py-2 cteditor-shadow-sm", children: [
29011
- /* @__PURE__ */ jsx(AlertCircle, { className: "cteditor-h-4 cteditor-w-4 cteditor-text-amber-600 cteditor-flex-shrink-0" }),
29012
- /* @__PURE__ */ jsxs("div", { className: "cteditor-flex cteditor-items-center cteditor-gap-2 cteditor-flex-1 cteditor-overflow-x-auto cteditor-max-w-2xl", children: [
29013
- /* @__PURE__ */ jsxs("span", { className: "cteditor-text-xs cteditor-font-semibold cteditor-text-amber-800 cteditor-whitespace-nowrap", children: [
29014
- errors.length,
29015
- " ",
29016
- errors.length === 1 ? "issue" : "issues",
29017
- ":"
29018
- ] }),
29019
- /* @__PURE__ */ jsx("div", { className: "cteditor-flex cteditor-gap-2 cteditor-items-center", children: errors.map((error, idx) => /* @__PURE__ */ jsxs(
29020
- "div",
29021
- {
29022
- className: "cteditor-flex cteditor-items-center cteditor-gap-1.5 cteditor-bg-white cteditor-border cteditor-border-gray-200 cteditor-rounded cteditor-px-2 cteditor-py-1 cteditor-whitespace-nowrap cteditor-cursor-pointer hover:cteditor-bg-gray-50 cteditor-transition-colors",
29023
- onClick: (e) => showErrorTooltip(error, e),
29024
- children: [
29025
- /* @__PURE__ */ jsx("span", { className: "cteditor-text-xs cteditor-line-through cteditor-text-red-600 cteditor-max-w-24 cteditor-truncate", title: error.original, children: error.original }),
29026
- /* @__PURE__ */ jsx("span", { className: "cteditor-text-xs cteditor-text-gray-400", children: "→" }),
29027
- /* @__PURE__ */ jsx(
29028
- "button",
29029
- {
29030
- onClick: (e) => {
29031
- e.stopPropagation();
29032
- applyCorrection(error.suggestions[0], error.original, error.type);
29033
- },
29034
- className: "cteditor-text-xs cteditor-text-green-600 hover:cteditor-text-green-700 cteditor-font-medium cteditor-max-w-24 cteditor-truncate",
29035
- title: error.suggestions[0],
29036
- children: error.suggestions[0]
29037
- }
29038
- )
29039
- ]
29040
- },
29041
- idx
29042
- )) })
29043
- ] }),
29044
- /* @__PURE__ */ jsxs("div", { className: "cteditor-flex cteditor-items-center cteditor-gap-1 cteditor-flex-shrink-0", children: [
29045
- /* @__PURE__ */ jsx(
29046
- Button,
29047
- {
29048
- variant: "link",
29049
- size: "sm",
29050
- onClick: () => {
29051
- setUserDismissed(true);
29052
- setErrors([]);
29053
- updateToolbarState("isGrammarCheckEnabled", false);
29054
- },
29055
- className: "cteditor-h-7 cteditor-px-2 cteditor-text-xs !cteditor-text-amber-700 ",
29056
- title: "Disable Grammar Check",
29057
- children: "Disable"
29058
- }
29059
- ),
29060
- /* @__PURE__ */ jsx(
29061
- "button",
29062
- {
29063
- onClick: () => setUserDismissed(true),
29064
- className: "cteditor-p-1 hover:cteditor-bg-amber-100 cteditor-rounded cteditor-transition-colors",
29065
- title: "Dismiss grammar suggestions",
29066
- children: /* @__PURE__ */ jsx(X$1, { className: "cteditor-h-3.5 cteditor-w-3.5 cteditor-text-amber-600" })
29067
- }
29068
- )
29069
- ] })
29070
- ] }) }),
29071
- tooltip && createPortal(
29072
- /* @__PURE__ */ jsx(
29073
- "div",
29074
- {
29075
- className: "grammar-tooltip ",
29076
- style: {
29077
- position: "fixed",
29078
- left: tooltip.x,
29079
- top: tooltip.y + 20,
29080
- zIndex: 1e4
29081
- },
29082
- onMouseEnter: () => {
29083
- },
29084
- onMouseLeave: () => {
29085
- setTooltip(null);
29086
- },
29087
- children: /* @__PURE__ */ jsx(Card, { className: "cteditor-w-72 cteditor-shadow-xl cteditor-border-2 cteditor-bg-background cteditor-rounded-xl", children: /* @__PURE__ */ jsxs(CardContent, { className: "cteditor-p-3", children: [
29088
- /* @__PURE__ */ jsxs("div", { className: "cteditor-flex cteditor-items-center cteditor-gap-2 cteditor-mb-3", children: [
29089
- tooltip.error.type === "spelling" ? /* @__PURE__ */ jsx(AlertCircle, { className: "cteditor-h-4 cteditor-w-4 cteditor-text-red-500" }) : /* @__PURE__ */ jsx(CheckCircle, { className: "cteditor-h-4 cteditor-w-4 cteditor-text-blue-500" }),
29090
- /* @__PURE__ */ jsx(
29091
- Badge,
29092
- {
29093
- variant: tooltip.error.type === "spelling" ? "destructive" : "default",
29094
- className: "cteditor-text-xs",
29095
- children: tooltip.error.type === "spelling" ? "Spelling Error" : "Grammar Issue"
29096
- }
29097
- )
29098
- ] }),
29099
- tooltip.error.issue && /* @__PURE__ */ jsx("p", { className: "cteditor-text-xs cteditor-text-muted-foreground cteditor-mb-2 cteditor-italic", children: tooltip.error.issue }),
29100
- /* @__PURE__ */ jsxs("div", { className: "cteditor-mb-2", children: [
29101
- /* @__PURE__ */ jsx("p", { className: "cteditor-text-xs cteditor-font-semibold cteditor-text-muted-foreground", children: "Original:" }),
29102
- /* @__PURE__ */ jsx("p", { className: "cteditor-text-sm cteditor-line-through cteditor-text-red-600", children: tooltip.error.original })
29103
- ] }),
29104
- tooltip.error.suggestions.length > 0 && /* @__PURE__ */ jsxs("div", { children: [
29105
- /* @__PURE__ */ jsx("p", { className: "cteditor-text-xs cteditor-font-semibold cteditor-text-muted-foreground cteditor-mb-1", children: "Suggestions:" }),
29106
- /* @__PURE__ */ jsx("div", { className: "cteditor-space-y-1", children: tooltip.error.suggestions.map((suggestion, idx) => /* @__PURE__ */ jsxs(
29107
- "button",
29108
- {
29109
- onClick: () => applyCorrection(suggestion, tooltip.error.original, tooltip.error.type),
29110
- className: "cteditor-w-full cteditor-text-left cteditor-p-2 cteditor-text-sm cteditor-rounded-md cteditor-bg-accent/50 hover:cteditor-bg-accent cteditor-transition-colors cteditor-border cteditor-border-transparent hover:cteditor-border-primary",
29111
- children: [
29112
- "✓ ",
29113
- suggestion
29114
- ]
29115
- },
29116
- idx
29117
- )) })
29118
- ] }),
29119
- tooltip.error.suggestions.length === 0 && /* @__PURE__ */ jsx("p", { className: "cteditor-text-xs cteditor-text-muted-foreground cteditor-italic", children: "No suggestions available" })
29120
- ] }) })
29121
- }
29122
- ),
29123
- document.body
29124
- )
29125
- ] });
29126
- }
29127
29708
  const useStyles = () => ({
29128
29709
  // container: "cteditor-relative cteditor-w-full cteditor-bg-white cteditor-text-black cteditor-font-normal cteditor-text-left cteditor-border cteditor-border-red-500",
29129
29710
  contentEditable: cn$1(
29130
- "cteditor-relative cteditor-min-h-[150px] !cteditor-h-auto cteditor-resize-none cteditor-outline-0 cteditor-text-background",
29131
- "cteditor-caret-[#757575] cteditor-p-0 cteditor-transition-all cteditor-duration-200",
29711
+ "cteditor-relative cteditor-min-h-[150px] !cteditor-h-auto cteditor-resize-none cteditor-outline-0",
29712
+ // Ensure strong contrast in both themes
29713
+ "cteditor-text-black dark:cteditor-text-white cteditor-bg-white dark:cteditor-bg-[#0b0b0b]",
29714
+ // Caret and spacing
29715
+ "cteditor-caret-[#3b82f6] cteditor-p-0 cteditor-transition-all cteditor-duration-200",
29132
29716
  "cteditor-w-full ",
29133
29717
  "[&>hr]:cteditor-border-none [&>hr]:cteditor-h-[2px]"
29134
29718
  ),
@@ -29214,12 +29798,12 @@ const ToolbarWithEditor = (props) => {
29214
29798
  }
29215
29799
  );
29216
29800
  };
29217
- const AutocompleteWrapper = () => {
29801
+ const CombinedPluginWrapper = () => {
29218
29802
  const { toolbarState } = useToolbarState();
29219
- if (!toolbarState.isAutocompleteEnabled) {
29803
+ if (!toolbarState.isAutocompleteEnabled && !toolbarState.isGrammarCheckEnabled) {
29220
29804
  return null;
29221
29805
  }
29222
- return /* @__PURE__ */ jsx(AutocompletePlugin, { minMatchLength: 2, maxSuggestions: 10 });
29806
+ return /* @__PURE__ */ jsx(CombinedAutocompleteGrammarPlugin, { minMatchLength: 2, maxSuggestions: 10, enableAI: true });
29223
29807
  };
29224
29808
  const OnChangeWrapper = ({ onChange }) => {
29225
29809
  const [editor] = useLexicalComposerContext();
@@ -29346,14 +29930,15 @@ const ConfigurableEditor = ({
29346
29930
  /* @__PURE__ */ jsx(HtmlSyncPlugin, {}),
29347
29931
  /* @__PURE__ */ jsx(CodeHighlightPlugin, {}),
29348
29932
  /* @__PURE__ */ jsx(SlashCommandPlugin, {}),
29349
- /* @__PURE__ */ jsx(AutocompleteWrapper, {}),
29350
- /* @__PURE__ */ jsx(GrammarCheckPlugin, {}),
29933
+ /* @__PURE__ */ jsx(CombinedPluginWrapper, {}),
29351
29934
  /* @__PURE__ */ jsx(OnChangeWrapper, { onChange }),
29352
29935
  /* @__PURE__ */ jsx(InitialContentPlugin, { initialContent }),
29353
29936
  /* @__PURE__ */ jsx(HistoryPlugin, {}),
29354
29937
  /* @__PURE__ */ jsx(LocalStoragePlugin$1, { namespace: initialConfig.namespace }),
29355
29938
  /* @__PURE__ */ jsx(ListPlugin, {}),
29356
29939
  /* @__PURE__ */ jsx(LinkPlugin, { hasLinkAttributes: false }),
29940
+ /* @__PURE__ */ jsx(DragDropPaste, {}),
29941
+ /* @__PURE__ */ jsx(RichTextPastePlugin, {}),
29357
29942
  /* @__PURE__ */ jsx(FilePlugin, {}),
29358
29943
  /* @__PURE__ */ jsx(HorizontalRulePlugin, {}),
29359
29944
  /* @__PURE__ */ jsx(CustomHorizontalRulePlugin, {}),
@@ -29415,7 +30000,7 @@ const ScopedEditorWrapper = ({
29415
30000
  className = "",
29416
30001
  darkMode = false
29417
30002
  }) => {
29418
- return /* @__PURE__ */ jsx("div", { id: "ct-editor-f47ac10b", children: /* @__PURE__ */ jsx("div", { className: "cteditor-p-2 ", children }) });
30003
+ return /* @__PURE__ */ jsx("div", { id: "ct-editor-f47ac10b", className: "cteditor-max-w-full cteditor-overflow-hidden", children: /* @__PURE__ */ jsx("div", { className: "cteditor-p-2 cteditor-w-full", children }) });
29419
30004
  };
29420
30005
  const MessageContainer = styled.div`
29421
30006
  display: flex;
@@ -29539,4 +30124,4 @@ export {
29539
30124
  useHtmlView as u,
29540
30125
  verifyApiKey as v
29541
30126
  };
29542
- //# sourceMappingURL=index-9d28aec6.js.map
30127
+ //# sourceMappingURL=index-8d147c36.js.map