ct-rich-text-editor 1.3.0 → 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.
- package/dist/assets/style.css +372 -187
- package/dist/{babel-d155920e.js → babel-d3085146.js} +3565 -3292
- package/dist/babel-d3085146.js.map +1 -0
- package/dist/components/CodeActionMenuPlugin/utils.d.ts +1 -1
- package/dist/{estree-b1fff53b.js → estree-164983f6.js} +1763 -1778
- package/dist/estree-164983f6.js.map +1 -0
- package/dist/hooks/useDebounce.d.ts +1 -1
- package/dist/{html-f95ee5dc.js → html-5586dbf6.js} +701 -656
- package/dist/html-5586dbf6.js.map +1 -0
- package/dist/{html2pdf.bundle-0fecc54c.js → html2pdf.bundle-f23e1b00.js} +2 -2
- package/dist/html2pdf.bundle-f23e1b00.js.map +1 -0
- package/dist/{html2pdf.bundle.min-d9d93bc1.js → html2pdf.bundle.min-daf952fb.js} +2 -2
- package/dist/html2pdf.bundle.min-daf952fb.js.map +1 -0
- package/dist/{index-113e3eb2.js → index-10f9d057.js} +7 -11
- package/dist/index-10f9d057.js.map +1 -0
- package/dist/{index-7aab7b5a.js → index-8d147c36.js} +1041 -602
- package/dist/index-8d147c36.js.map +1 -0
- package/dist/index.js +1 -1
- package/dist/{markdown-1d9e6c3f.js → markdown-d513479b.js} +1836 -1789
- package/dist/markdown-d513479b.js.map +1 -0
- package/dist/plugins/CombinedAutocompletGrammarPlugin.d.ts +22 -0
- package/dist/{postcss-c2592f3f.js → postcss-f084f74d.js} +1378 -1357
- package/dist/postcss-f084f74d.js.map +1 -0
- package/dist/standalone-5a8c6b7e.js +2518 -0
- package/dist/standalone-5a8c6b7e.js.map +1 -0
- package/dist/typescript-b1005db4.js +13705 -0
- package/dist/typescript-b1005db4.js.map +1 -0
- package/package.json +1 -1
- package/dist/babel-d155920e.js.map +0 -1
- package/dist/estree-b1fff53b.js.map +0 -1
- package/dist/html-f95ee5dc.js.map +0 -1
- package/dist/html2pdf.bundle-0fecc54c.js.map +0 -1
- package/dist/html2pdf.bundle.min-d9d93bc1.js.map +0 -1
- package/dist/index-113e3eb2.js.map +0 -1
- package/dist/index-7aab7b5a.js.map +0 -1
- package/dist/markdown-1d9e6c3f.js.map +0 -1
- package/dist/postcss-c2592f3f.js.map +0 -1
- package/dist/standalone-bcc7f37a.js +0 -2649
- package/dist/standalone-bcc7f37a.js.map +0 -1
- package/dist/typescript-48c10f50.js +0 -13601
- 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, $
|
|
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";
|
|
@@ -7822,16 +7822,16 @@ function CopyButton({ editor, getCodeDOMNode }) {
|
|
|
7822
7822
|
}
|
|
7823
7823
|
const index$4 = "";
|
|
7824
7824
|
const PRETTIER_PARSER_MODULES = {
|
|
7825
|
-
css: [() => import("./postcss-
|
|
7826
|
-
html: [() => import("./html-
|
|
7825
|
+
css: [() => import("./postcss-f084f74d.js")],
|
|
7826
|
+
html: [() => import("./html-5586dbf6.js")],
|
|
7827
7827
|
js: [
|
|
7828
|
-
() => import("./babel-
|
|
7829
|
-
() => import("./estree-
|
|
7828
|
+
() => import("./babel-d3085146.js"),
|
|
7829
|
+
() => import("./estree-164983f6.js")
|
|
7830
7830
|
],
|
|
7831
|
-
markdown: [() => import("./markdown-
|
|
7831
|
+
markdown: [() => import("./markdown-d513479b.js")],
|
|
7832
7832
|
typescript: [
|
|
7833
|
-
() => import("./typescript-
|
|
7834
|
-
() => import("./estree-
|
|
7833
|
+
() => import("./typescript-b1005db4.js"),
|
|
7834
|
+
() => import("./estree-164983f6.js")
|
|
7835
7835
|
]
|
|
7836
7836
|
};
|
|
7837
7837
|
async function loadPrettierParserByLang(lang) {
|
|
@@ -7842,7 +7842,7 @@ async function loadPrettierParserByLang(lang) {
|
|
|
7842
7842
|
return modules;
|
|
7843
7843
|
}
|
|
7844
7844
|
async function loadPrettierFormat() {
|
|
7845
|
-
const { format } = await import("./standalone-
|
|
7845
|
+
const { format } = await import("./standalone-5a8c6b7e.js");
|
|
7846
7846
|
return format;
|
|
7847
7847
|
}
|
|
7848
7848
|
const PRETTIER_OPTIONS_BY_LANG = {
|
|
@@ -12717,10 +12717,10 @@ const PDF_CONFIG = {
|
|
|
12717
12717
|
};
|
|
12718
12718
|
const loadHtml2Pdf = async () => {
|
|
12719
12719
|
try {
|
|
12720
|
-
const mod = await import("./html2pdf.bundle.min-
|
|
12720
|
+
const mod = await import("./html2pdf.bundle.min-daf952fb.js").then((n) => n.h);
|
|
12721
12721
|
return (mod == null ? void 0 : mod.default) || mod;
|
|
12722
12722
|
} catch {
|
|
12723
|
-
const mod2 = await import("./html2pdf.bundle-
|
|
12723
|
+
const mod2 = await import("./html2pdf.bundle-f23e1b00.js").then((n) => n.h);
|
|
12724
12724
|
return (mod2 == null ? void 0 : mod2.default) || mod2;
|
|
12725
12725
|
}
|
|
12726
12726
|
};
|
|
@@ -13927,7 +13927,7 @@ const EmbedComponent = ({ url, displayType, alignment, nodeKey }) => {
|
|
|
13927
13927
|
}
|
|
13928
13928
|
);
|
|
13929
13929
|
};
|
|
13930
|
-
const ImageView = React__default.lazy(() => import("./index-
|
|
13930
|
+
const ImageView = React__default.lazy(() => import("./index-10f9d057.js"));
|
|
13931
13931
|
function isGoogleDocCheckboxImg(img) {
|
|
13932
13932
|
return img.parentElement != null && img.parentElement.tagName === "LI" && img.previousSibling === null && img.getAttribute("aria-roledescription") === "checkbox";
|
|
13933
13933
|
}
|
|
@@ -16457,6 +16457,7 @@ function TableOptionPlugin() {
|
|
|
16457
16457
|
htmlCell.style.setProperty("padding", "8px", "important");
|
|
16458
16458
|
htmlCell.style.setProperty("border", "1px solid #ddd", "important");
|
|
16459
16459
|
htmlCell.style.setProperty("font-weight", "bold", "important");
|
|
16460
|
+
htmlCell.style.setProperty("white-space", "nowrap", "important");
|
|
16460
16461
|
}
|
|
16461
16462
|
});
|
|
16462
16463
|
}
|
|
@@ -16504,6 +16505,7 @@ function TableOptionPlugin() {
|
|
|
16504
16505
|
for (let i2 = 0; i2 < cells.length; i2++) {
|
|
16505
16506
|
const headingText = (columnHeadings[i2] || "").trim();
|
|
16506
16507
|
const cellNode = cells[i2];
|
|
16508
|
+
cellNode.clear();
|
|
16507
16509
|
if (headingText) {
|
|
16508
16510
|
cellNode.append($createTextNode(headingText));
|
|
16509
16511
|
}
|
|
@@ -16536,6 +16538,7 @@ function TableOptionPlugin() {
|
|
|
16536
16538
|
htmlCell.style.setProperty("padding", "8px", "important");
|
|
16537
16539
|
htmlCell.style.setProperty("border", "1px solid #ddd", "important");
|
|
16538
16540
|
htmlCell.style.setProperty("font-weight", "bold", "important");
|
|
16541
|
+
htmlCell.style.setProperty("white-space", "nowrap", "important");
|
|
16539
16542
|
});
|
|
16540
16543
|
return true;
|
|
16541
16544
|
}
|
|
@@ -21276,6 +21279,7 @@ const InsertImageUploadedDialogBody = ({
|
|
|
21276
21279
|
const { uploadFileToS3, uploadedUrl, progress, uploading } = useS3Uploader(apiKey || void 0);
|
|
21277
21280
|
const [tempSrc, setTempSrc] = useState$1("");
|
|
21278
21281
|
const [fileToUpload, setFileToUpload] = useState$1(null);
|
|
21282
|
+
const [imageDimensions, setImageDimensions] = useState$1(null);
|
|
21279
21283
|
const onChangeImage = async (event) => {
|
|
21280
21284
|
const files = event.target.files;
|
|
21281
21285
|
if (!files || files.length === 0)
|
|
@@ -21286,6 +21290,11 @@ const InsertImageUploadedDialogBody = ({
|
|
|
21286
21290
|
reader.onload = () => {
|
|
21287
21291
|
if (typeof reader.result === "string") {
|
|
21288
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;
|
|
21289
21298
|
}
|
|
21290
21299
|
};
|
|
21291
21300
|
reader.readAsDataURL(file);
|
|
@@ -21295,9 +21304,19 @@ const InsertImageUploadedDialogBody = ({
|
|
|
21295
21304
|
return;
|
|
21296
21305
|
try {
|
|
21297
21306
|
const uploadedUrl2 = await uploadFileToS3(fileToUpload);
|
|
21298
|
-
|
|
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);
|
|
21299
21317
|
setTempSrc("");
|
|
21300
21318
|
setFileToUpload(null);
|
|
21319
|
+
setImageDimensions(null);
|
|
21301
21320
|
} catch (error) {
|
|
21302
21321
|
console.error("Upload failed:", error);
|
|
21303
21322
|
}
|
|
@@ -21379,6 +21398,7 @@ const InsertImageUrlDialogBody = ({
|
|
|
21379
21398
|
const [altText, setAltText] = useState$1("");
|
|
21380
21399
|
const [isValidUrl, setIsValidUrl] = useState$1(false);
|
|
21381
21400
|
const [previewError, setPreviewError] = useState$1(null);
|
|
21401
|
+
const [imageDimensions, setImageDimensions] = useState$1(null);
|
|
21382
21402
|
const validateUrl2 = (url) => {
|
|
21383
21403
|
if (!url.trim())
|
|
21384
21404
|
return false;
|
|
@@ -21414,6 +21434,7 @@ const InsertImageUrlDialogBody = ({
|
|
|
21414
21434
|
img.onload = () => {
|
|
21415
21435
|
setPreviewError(null);
|
|
21416
21436
|
setIsValidUrl(true);
|
|
21437
|
+
setImageDimensions({ width: img.naturalWidth, height: img.naturalHeight });
|
|
21417
21438
|
};
|
|
21418
21439
|
img.onerror = () => {
|
|
21419
21440
|
setPreviewError(
|
|
@@ -21426,7 +21447,12 @@ const InsertImageUrlDialogBody = ({
|
|
|
21426
21447
|
const handleConfirmUrl = () => {
|
|
21427
21448
|
if (!imageUrl || !isValidUrl)
|
|
21428
21449
|
return;
|
|
21429
|
-
onClick({
|
|
21450
|
+
onClick({
|
|
21451
|
+
altText,
|
|
21452
|
+
src: imageUrl,
|
|
21453
|
+
width: imageDimensions == null ? void 0 : imageDimensions.width,
|
|
21454
|
+
height: imageDimensions == null ? void 0 : imageDimensions.height
|
|
21455
|
+
});
|
|
21430
21456
|
};
|
|
21431
21457
|
return /* @__PURE__ */ jsxs("div", { className: "cteditor-space-y-4", children: [
|
|
21432
21458
|
imageUrl && isValidUrl && !previewError && /* @__PURE__ */ jsx("div", { className: "cteditor-mb-4", children: /* @__PURE__ */ jsx(
|
|
@@ -22706,8 +22732,8 @@ const NotePanelMenu = ({ className }) => {
|
|
|
22706
22732
|
] });
|
|
22707
22733
|
};
|
|
22708
22734
|
const useStyles$1 = () => ({
|
|
22709
|
-
root: "cteditor-p-2 cteditor-border-b cteditor-border-[#e0e0e0] cteditor-overflow-auto",
|
|
22710
|
-
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",
|
|
22711
22737
|
toolbarButton: "cteditor-p-1.5"
|
|
22712
22738
|
});
|
|
22713
22739
|
const useModal$1 = () => {
|
|
@@ -23220,14 +23246,17 @@ const Toolbar = ({
|
|
|
23220
23246
|
"div",
|
|
23221
23247
|
{
|
|
23222
23248
|
ref: contentRef,
|
|
23223
|
-
className: "cteditor-flex cteditor-items-center cteditor-gap-1.5 cteditor-flex-1 cteditor-overflow-x-auto cteditor-
|
|
23224
|
-
style: {
|
|
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
|
+
},
|
|
23225
23254
|
children: [
|
|
23226
23255
|
enableUndoRedo && /* @__PURE__ */ jsxs(
|
|
23227
23256
|
"div",
|
|
23228
23257
|
{
|
|
23229
23258
|
"data-toolbar-item": "undoRedo",
|
|
23230
|
-
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",
|
|
23231
23260
|
children: [
|
|
23232
23261
|
/* @__PURE__ */ jsx(TooltipProvider, { delayDuration: 200, children: /* @__PURE__ */ jsxs(Tooltip, { children: [
|
|
23233
23262
|
/* @__PURE__ */ jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx(
|
|
@@ -24122,9 +24151,8 @@ function Skeleton({
|
|
|
24122
24151
|
}
|
|
24123
24152
|
);
|
|
24124
24153
|
}
|
|
24125
|
-
|
|
24126
|
-
|
|
24127
|
-
);
|
|
24154
|
+
const GrammarCheckPlugin = "";
|
|
24155
|
+
createCommand("AUTOCOMPLETE_COMMAND");
|
|
24128
24156
|
const STATIC_SUGGESTIONS = [
|
|
24129
24157
|
"javascript",
|
|
24130
24158
|
"typescript",
|
|
@@ -24152,7 +24180,6 @@ class AIService {
|
|
|
24152
24180
|
__publicField(this, "apiEndpoint");
|
|
24153
24181
|
__publicField(this, "cache", /* @__PURE__ */ new Map());
|
|
24154
24182
|
__publicField(this, "requestTimeout", 1e4);
|
|
24155
|
-
// 10 seconds timeout for more reliable responses
|
|
24156
24183
|
__publicField(this, "pendingRequests", /* @__PURE__ */ new Map());
|
|
24157
24184
|
this.apiEndpoint = "https://api.cteditor.com/" + apiEndpoint;
|
|
24158
24185
|
}
|
|
@@ -24174,19 +24201,9 @@ class AIService {
|
|
|
24174
24201
|
}
|
|
24175
24202
|
}
|
|
24176
24203
|
async executeRequest(payload, cacheKey) {
|
|
24177
|
-
var _a;
|
|
24178
24204
|
try {
|
|
24179
24205
|
const controller = new AbortController();
|
|
24180
|
-
const timeoutId = setTimeout(
|
|
24181
|
-
() => controller.abort(),
|
|
24182
|
-
this.requestTimeout
|
|
24183
|
-
);
|
|
24184
|
-
console.log("🌐 AIService: Making request to:", this.apiEndpoint);
|
|
24185
|
-
console.log("📦 AIService: Payload:", {
|
|
24186
|
-
...payload,
|
|
24187
|
-
text: ((_a = payload.text) == null ? void 0 : _a.substring(0, 100)) + "..."
|
|
24188
|
-
// Log only first 100 chars
|
|
24189
|
-
});
|
|
24206
|
+
const timeoutId = setTimeout(() => controller.abort(), this.requestTimeout);
|
|
24190
24207
|
const response = await fetch(this.apiEndpoint, {
|
|
24191
24208
|
method: "POST",
|
|
24192
24209
|
headers: {
|
|
@@ -24196,14 +24213,11 @@ class AIService {
|
|
|
24196
24213
|
signal: controller.signal
|
|
24197
24214
|
});
|
|
24198
24215
|
clearTimeout(timeoutId);
|
|
24199
|
-
console.log("📡 AIService: Response status:", response.status);
|
|
24200
24216
|
if (!response.ok) {
|
|
24201
24217
|
const errorText = await response.text();
|
|
24202
|
-
console.error("❌ AIService: Error response:", errorText);
|
|
24203
24218
|
throw new Error(`AI service error: ${response.status} - ${errorText}`);
|
|
24204
24219
|
}
|
|
24205
24220
|
const result = await response.json();
|
|
24206
|
-
console.log("✅ AIService: Successful response received");
|
|
24207
24221
|
this.cache.set(cacheKey, result.data);
|
|
24208
24222
|
if (this.cache.size > 50) {
|
|
24209
24223
|
const firstKey = this.cache.keys().next().value;
|
|
@@ -24213,15 +24227,7 @@ class AIService {
|
|
|
24213
24227
|
}
|
|
24214
24228
|
return result.data;
|
|
24215
24229
|
} catch (error) {
|
|
24216
|
-
|
|
24217
|
-
console.warn(
|
|
24218
|
-
"⏰ AIService: Request timed out after",
|
|
24219
|
-
this.requestTimeout,
|
|
24220
|
-
"ms"
|
|
24221
|
-
);
|
|
24222
|
-
} else {
|
|
24223
|
-
console.error("❌ AIService: Request failed:", error);
|
|
24224
|
-
}
|
|
24230
|
+
console.error("❌ AIService: Request failed:", error);
|
|
24225
24231
|
return null;
|
|
24226
24232
|
}
|
|
24227
24233
|
}
|
|
@@ -24231,43 +24237,118 @@ class AIService {
|
|
|
24231
24237
|
}
|
|
24232
24238
|
const result = await this.makeRequest({
|
|
24233
24239
|
text: text.trim(),
|
|
24234
|
-
// Send the sentence/text for correction
|
|
24235
24240
|
currentWord: currentWord == null ? void 0 : currentWord.trim(),
|
|
24236
|
-
// Send current word being typed (optional)
|
|
24237
24241
|
maxSuggestions
|
|
24238
24242
|
});
|
|
24239
24243
|
return result;
|
|
24240
24244
|
}
|
|
24241
24245
|
}
|
|
24242
|
-
|
|
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({
|
|
24243
24323
|
onQueryChange,
|
|
24244
24324
|
onSelectOption,
|
|
24245
24325
|
minMatchLength = 2,
|
|
24246
24326
|
maxSuggestions = 10,
|
|
24247
|
-
// anchorClassName = "",
|
|
24248
|
-
// menuClassName = "",
|
|
24249
|
-
// itemClassName = "",
|
|
24250
|
-
// selectedItemClassName = "",
|
|
24251
24327
|
apiEndpoint = "api/ai/process",
|
|
24252
24328
|
enableAI = true,
|
|
24253
24329
|
debounceDelay = 200
|
|
24254
24330
|
}) {
|
|
24255
24331
|
const [editor] = useLexicalComposerContext();
|
|
24256
24332
|
const { updateToolbarState } = useToolbarState();
|
|
24333
|
+
const [activeTab, setActiveTab] = useState$1("autocomplete");
|
|
24257
24334
|
const [queryString, setQueryString] = useState$1(null);
|
|
24258
24335
|
const [suggestions, setSuggestions] = useState$1([]);
|
|
24259
24336
|
const [selectedIndex, setSelectedIndex] = useState$1(0);
|
|
24260
24337
|
const [isLoading, setIsLoading] = useState$1(false);
|
|
24261
24338
|
const menuRef = useRef(null);
|
|
24262
24339
|
const anchorElementRef = useRef(null);
|
|
24263
|
-
const [anchorElement, setAnchorElement] = useState$1(
|
|
24264
|
-
null
|
|
24265
|
-
);
|
|
24340
|
+
const [anchorElement, setAnchorElement] = useState$1(null);
|
|
24266
24341
|
const aiService = useRef(new AIService(apiEndpoint));
|
|
24267
24342
|
const debounceTimer = useRef(null);
|
|
24268
24343
|
const justSelectedOption = useRef(false);
|
|
24269
24344
|
const lastRequestTime = useRef(0);
|
|
24270
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([]);
|
|
24271
24352
|
const extractWordsFromEditor = useCallback(() => {
|
|
24272
24353
|
const words = /* @__PURE__ */ new Set();
|
|
24273
24354
|
STATIC_SUGGESTIONS.forEach((word) => words.add(word));
|
|
@@ -24292,17 +24373,12 @@ function AutocompletePlugin({
|
|
|
24292
24373
|
return [];
|
|
24293
24374
|
}
|
|
24294
24375
|
if (justSelectedOption.current) {
|
|
24295
|
-
console.log(
|
|
24296
|
-
"🚫 AutocompletePlugin: Skipping AI request - just selected option"
|
|
24297
|
-
);
|
|
24298
24376
|
return [];
|
|
24299
24377
|
}
|
|
24300
24378
|
const now2 = Date.now();
|
|
24301
24379
|
if (now2 - lastRequestTime.current < requestThrottle) {
|
|
24302
|
-
console.log("🚫 AutocompletePlugin: Throttling AI request");
|
|
24303
24380
|
return [];
|
|
24304
24381
|
}
|
|
24305
|
-
console.log("🤖 AutocompletePlugin: Getting AI suggestions for:", query);
|
|
24306
24382
|
setIsLoading(true);
|
|
24307
24383
|
lastRequestTime.current = now2;
|
|
24308
24384
|
let lastSentence = "";
|
|
@@ -24341,11 +24417,8 @@ function AutocompletePlugin({
|
|
|
24341
24417
|
try {
|
|
24342
24418
|
const result = await aiService.current.getIntelligentSuggestions(
|
|
24343
24419
|
query,
|
|
24344
|
-
// currentWord
|
|
24345
24420
|
lastSentence,
|
|
24346
|
-
// text (the sentence to correct)
|
|
24347
24421
|
maxSuggestions
|
|
24348
|
-
// maxSuggestions
|
|
24349
24422
|
);
|
|
24350
24423
|
const aiOptions = [];
|
|
24351
24424
|
if (result) {
|
|
@@ -24418,10 +24491,6 @@ function AutocompletePlugin({
|
|
|
24418
24491
|
});
|
|
24419
24492
|
}
|
|
24420
24493
|
}
|
|
24421
|
-
console.log(
|
|
24422
|
-
"✅ AutocompletePlugin: AI sentence corrections received:",
|
|
24423
|
-
aiOptions
|
|
24424
|
-
);
|
|
24425
24494
|
return aiOptions.slice(0, Math.floor(maxSuggestions * 0.8));
|
|
24426
24495
|
} catch (error) {
|
|
24427
24496
|
console.error("❌ AutocompletePlugin: AI suggestions failed:", error);
|
|
@@ -24430,7 +24499,7 @@ function AutocompletePlugin({
|
|
|
24430
24499
|
setIsLoading(false);
|
|
24431
24500
|
}
|
|
24432
24501
|
},
|
|
24433
|
-
[enableAI, minMatchLength, maxSuggestions]
|
|
24502
|
+
[enableAI, minMatchLength, maxSuggestions, editor]
|
|
24434
24503
|
);
|
|
24435
24504
|
const getTraditionalSuggestions = useCallback(
|
|
24436
24505
|
(query) => {
|
|
@@ -24487,7 +24556,6 @@ function AutocompletePlugin({
|
|
|
24487
24556
|
}, 100);
|
|
24488
24557
|
return;
|
|
24489
24558
|
}
|
|
24490
|
-
console.log("🎯 AutocompletePlugin: Checking for autocomplete trigger");
|
|
24491
24559
|
editor.update(() => {
|
|
24492
24560
|
const selection = $getSelection();
|
|
24493
24561
|
if (!$isRangeSelection(selection) || !selection.isCollapsed()) {
|
|
@@ -24520,18 +24588,10 @@ function AutocompletePlugin({
|
|
|
24520
24588
|
}
|
|
24521
24589
|
if (queryString && !justSelectedOption.current) {
|
|
24522
24590
|
debounceTimer.current = setTimeout(async () => {
|
|
24523
|
-
console.log(
|
|
24524
|
-
"🔄 AutocompletePlugin: Getting suggestions for:",
|
|
24525
|
-
queryString
|
|
24526
|
-
);
|
|
24527
24591
|
const newSuggestions = await getCombinedSuggestions(queryString);
|
|
24528
24592
|
setSuggestions(newSuggestions);
|
|
24529
24593
|
setSelectedIndex(0);
|
|
24530
24594
|
onQueryChange == null ? void 0 : onQueryChange(queryString);
|
|
24531
|
-
console.log(
|
|
24532
|
-
"🎯 AutocompletePlugin: Updated suggestions:",
|
|
24533
|
-
newSuggestions
|
|
24534
|
-
);
|
|
24535
24595
|
}, debounceDelay);
|
|
24536
24596
|
} else {
|
|
24537
24597
|
setSuggestions([]);
|
|
@@ -24546,7 +24606,6 @@ function AutocompletePlugin({
|
|
|
24546
24606
|
}, [queryString, getCombinedSuggestions, onQueryChange, debounceDelay]);
|
|
24547
24607
|
const selectOption = useCallback(
|
|
24548
24608
|
(option) => {
|
|
24549
|
-
console.log("✅ AutocompletePlugin: Selecting option:", option);
|
|
24550
24609
|
justSelectedOption.current = true;
|
|
24551
24610
|
editor.update(() => {
|
|
24552
24611
|
const selection = $getSelection();
|
|
@@ -24584,9 +24643,6 @@ function AutocompletePlugin({
|
|
|
24584
24643
|
const newOffset = sentenceStart + option.displayText.length;
|
|
24585
24644
|
selection.anchor.set(textNode.getKey(), newOffset, "text");
|
|
24586
24645
|
selection.focus.set(textNode.getKey(), newOffset, "text");
|
|
24587
|
-
console.log(
|
|
24588
|
-
"✅ AutocompletePlugin: Sentence replaced successfully"
|
|
24589
|
-
);
|
|
24590
24646
|
}
|
|
24591
24647
|
} else {
|
|
24592
24648
|
let wordStart = anchorOffset;
|
|
@@ -24600,7 +24656,6 @@ function AutocompletePlugin({
|
|
|
24600
24656
|
const newOffset = wordStart + option.displayText.length;
|
|
24601
24657
|
selection.anchor.set(textNode.getKey(), newOffset, "text");
|
|
24602
24658
|
selection.focus.set(textNode.getKey(), newOffset, "text");
|
|
24603
|
-
console.log("✅ AutocompletePlugin: Word replaced successfully");
|
|
24604
24659
|
}
|
|
24605
24660
|
}
|
|
24606
24661
|
});
|
|
@@ -24704,6 +24759,136 @@ function AutocompletePlugin({
|
|
|
24704
24759
|
inputListener();
|
|
24705
24760
|
};
|
|
24706
24761
|
}, [editor, checkForAutocompleteTrigger]);
|
|
24762
|
+
const checkGrammar = useCallback(async () => {
|
|
24763
|
+
const isSlashActive = editor.getEditorState().read(() => {
|
|
24764
|
+
const selection = $getSelection();
|
|
24765
|
+
if (!$isRangeSelection(selection))
|
|
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--;
|
|
24774
|
+
}
|
|
24775
|
+
return wordStart > 0 && textContent[wordStart - 1] === "/";
|
|
24776
|
+
});
|
|
24777
|
+
if (isSlashActive) {
|
|
24778
|
+
setErrors([]);
|
|
24779
|
+
return;
|
|
24780
|
+
}
|
|
24781
|
+
const text = editor.getEditorState().read(() => $getRoot().getTextContent());
|
|
24782
|
+
if (text === lastCheckedText.current) {
|
|
24783
|
+
return;
|
|
24784
|
+
}
|
|
24785
|
+
if (Math.abs(text.length - lastCheckedText.current.length) > 20) {
|
|
24786
|
+
setUserDismissed(false);
|
|
24787
|
+
}
|
|
24788
|
+
lastCheckedText.current = text;
|
|
24789
|
+
if (!text || text.trim().length < 3) {
|
|
24790
|
+
setErrors([]);
|
|
24791
|
+
return;
|
|
24792
|
+
}
|
|
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
|
+
}
|
|
24852
|
+
}
|
|
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
|
+
);
|
|
24707
24892
|
const calculateMenuPosition = useCallback(() => {
|
|
24708
24893
|
if (!anchorElement)
|
|
24709
24894
|
return { top: 0, left: 0 };
|
|
@@ -24736,10 +24921,7 @@ function AutocompletePlugin({
|
|
|
24736
24921
|
try {
|
|
24737
24922
|
document.body.removeChild(anchorElementRef.current);
|
|
24738
24923
|
} catch (error) {
|
|
24739
|
-
console.warn(
|
|
24740
|
-
"🚨 AutocompletePlugin: Error removing existing anchor:",
|
|
24741
|
-
error
|
|
24742
|
-
);
|
|
24924
|
+
console.warn("Error removing existing anchor:", error);
|
|
24743
24925
|
}
|
|
24744
24926
|
}
|
|
24745
24927
|
document.body.appendChild(anchor);
|
|
@@ -24750,7 +24932,7 @@ function AutocompletePlugin({
|
|
|
24750
24932
|
try {
|
|
24751
24933
|
document.body.removeChild(anchorElementRef.current);
|
|
24752
24934
|
} catch (error) {
|
|
24753
|
-
console.warn("
|
|
24935
|
+
console.warn("Error during cleanup:", error);
|
|
24754
24936
|
}
|
|
24755
24937
|
}
|
|
24756
24938
|
};
|
|
@@ -24779,76 +24961,171 @@ function AutocompletePlugin({
|
|
|
24779
24961
|
return "outline";
|
|
24780
24962
|
}
|
|
24781
24963
|
};
|
|
24782
|
-
|
|
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) {
|
|
24783
24976
|
return null;
|
|
24784
24977
|
}
|
|
24785
24978
|
return createPortal(
|
|
24786
|
-
/* @__PURE__ */
|
|
24979
|
+
/* @__PURE__ */ jsxs(
|
|
24787
24980
|
Card,
|
|
24788
24981
|
{
|
|
24789
24982
|
ref: menuRef,
|
|
24790
|
-
className: "cteditor-w-80 cteditor-max-h-64 cteditor-overflow-
|
|
24791
|
-
children:
|
|
24792
|
-
|
|
24793
|
-
/* @__PURE__ */
|
|
24794
|
-
|
|
24795
|
-
|
|
24796
|
-
|
|
24797
|
-
|
|
24798
|
-
|
|
24799
|
-
|
|
24800
|
-
"cteditor-flex cteditor-items-start cteditor-gap-3 cteditor-p-3 cteditor-rounded-md cteditor-cursor-pointer cteditor-transition-colors cteditor-text-sm",
|
|
24801
|
-
index2 === selectedIndex ? "cteditor-bg-foreground/5" : "hover:cteditor-bg-red"
|
|
24802
|
-
),
|
|
24803
|
-
onClick: () => selectOption(option),
|
|
24804
|
-
onMouseEnter: () => setSelectedIndex(index2),
|
|
24805
|
-
children: [
|
|
24806
|
-
/* @__PURE__ */ jsx(
|
|
24807
|
-
"div",
|
|
24808
|
-
{
|
|
24809
|
-
className: cn$1(
|
|
24810
|
-
"cteditor-mt-0.5",
|
|
24811
|
-
index2 === selectedIndex ? "cteditor-text-primary" : "cteditor-text-primary"
|
|
24812
|
-
),
|
|
24813
|
-
children: getSuggestionIcon(option.type)
|
|
24814
|
-
}
|
|
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"
|
|
24815
24993
|
),
|
|
24816
|
-
|
|
24817
|
-
/* @__PURE__ */
|
|
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: [
|
|
24818
25032
|
/* @__PURE__ */ jsx(
|
|
24819
|
-
|
|
25033
|
+
"div",
|
|
24820
25034
|
{
|
|
24821
|
-
|
|
24822
|
-
|
|
24823
|
-
|
|
25035
|
+
className: cn$1(
|
|
25036
|
+
"cteditor-mt-0.5",
|
|
25037
|
+
index2 === selectedIndex ? "cteditor-text-primary" : "cteditor-text-primary"
|
|
25038
|
+
),
|
|
25039
|
+
children: getSuggestionIcon(option.type)
|
|
24824
25040
|
}
|
|
24825
25041
|
),
|
|
24826
|
-
|
|
24827
|
-
|
|
24828
|
-
|
|
24829
|
-
|
|
24830
|
-
|
|
24831
|
-
|
|
24832
|
-
|
|
24833
|
-
|
|
24834
|
-
|
|
24835
|
-
|
|
24836
|
-
|
|
24837
|
-
|
|
24838
|
-
|
|
24839
|
-
|
|
24840
|
-
|
|
24841
|
-
|
|
24842
|
-
|
|
24843
|
-
|
|
24844
|
-
|
|
24845
|
-
|
|
24846
|
-
|
|
24847
|
-
|
|
24848
|
-
|
|
24849
|
-
|
|
24850
|
-
|
|
24851
|
-
|
|
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
|
+
]
|
|
24852
25129
|
}
|
|
24853
25130
|
),
|
|
24854
25131
|
anchorElement
|
|
@@ -25048,6 +25325,174 @@ const CommentBubblePlugin = () => {
|
|
|
25048
25325
|
}, [editor, getCommentById]);
|
|
25049
25326
|
return null;
|
|
25050
25327
|
};
|
|
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
|
+
}
|
|
25051
25496
|
const FloatingEmbedMenuPlugin$1 = "";
|
|
25052
25497
|
function FloatingEmbedMenu({
|
|
25053
25498
|
editor,
|
|
@@ -27007,6 +27452,203 @@ function NewMentionsPlugin({
|
|
|
27007
27452
|
}
|
|
27008
27453
|
);
|
|
27009
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
|
+
}
|
|
27010
27652
|
function useModal() {
|
|
27011
27653
|
const [modalContent, setModalContent] = useState$1(null);
|
|
27012
27654
|
const onClose = useCallback(() => {
|
|
@@ -27552,8 +28194,79 @@ function TableActionMenu({
|
|
|
27552
28194
|
for (let i2 = 0; i2 < selectionCounts.columns; i2++) {
|
|
27553
28195
|
$insertTableColumn__EXPERIMENTAL(shouldInsertAfter);
|
|
27554
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
|
+
}
|
|
27555
28228
|
onClose();
|
|
27556
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
|
+
});
|
|
27557
28270
|
},
|
|
27558
28271
|
[editor, onClose, selectionCounts.columns]
|
|
27559
28272
|
);
|
|
@@ -28550,21 +29263,84 @@ function TableHoverActionsContainer({
|
|
|
28550
29263
|
} else {
|
|
28551
29264
|
$insertTableColumn__EXPERIMENTAL();
|
|
28552
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
|
+
}
|
|
28553
29292
|
}
|
|
28554
29293
|
}
|
|
28555
29294
|
});
|
|
28556
|
-
|
|
28557
|
-
|
|
28558
|
-
|
|
28559
|
-
|
|
28560
|
-
|
|
28561
|
-
|
|
28562
|
-
|
|
28563
|
-
|
|
28564
|
-
|
|
28565
|
-
|
|
28566
|
-
|
|
28567
|
-
|
|
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
|
+
}
|
|
29332
|
+
};
|
|
29333
|
+
if (!isEditable) {
|
|
29334
|
+
return null;
|
|
29335
|
+
}
|
|
29336
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
29337
|
+
isShownRow && /* @__PURE__ */ jsx(
|
|
29338
|
+
"button",
|
|
29339
|
+
{
|
|
29340
|
+
className: "PlaygroundEditorTheme__tableAddRows ",
|
|
29341
|
+
style: { ...position },
|
|
29342
|
+
onClick: () => insertAction(true),
|
|
29343
|
+
children: /* @__PURE__ */ jsx(PlusIcon, {})
|
|
28568
29344
|
}
|
|
28569
29345
|
),
|
|
28570
29346
|
isShownColumn && /* @__PURE__ */ jsx(
|
|
@@ -28686,6 +29462,10 @@ function SlashMenuItem({
|
|
|
28686
29462
|
function SlashCommandPlugin() {
|
|
28687
29463
|
const [editor] = useLexicalComposerContext();
|
|
28688
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);
|
|
28689
29469
|
const triggerFn = useBasicTypeaheadTriggerMatch("/", { minLength: 0 });
|
|
28690
29470
|
const makeBlock = useCallback((cb) => {
|
|
28691
29471
|
editor.update(() => {
|
|
@@ -28772,9 +29552,55 @@ function SlashCommandPlugin() {
|
|
|
28772
29552
|
}
|
|
28773
29553
|
});
|
|
28774
29554
|
closeMenu();
|
|
29555
|
+
setIsMenuOpen(false);
|
|
28775
29556
|
},
|
|
28776
29557
|
[editor]
|
|
28777
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]);
|
|
28778
29604
|
return /* @__PURE__ */ jsx(
|
|
28779
29605
|
LexicalTypeaheadMenuPlugin,
|
|
28780
29606
|
{
|
|
@@ -28782,31 +29608,52 @@ function SlashCommandPlugin() {
|
|
|
28782
29608
|
onSelectOption,
|
|
28783
29609
|
triggerFn,
|
|
28784
29610
|
options,
|
|
28785
|
-
menuRenderFn: (anchorElementRef, { selectedIndex, selectOptionAndCleanUp, setHighlightedIndex }) =>
|
|
28786
|
-
|
|
28787
|
-
|
|
28788
|
-
|
|
28789
|
-
|
|
28790
|
-
|
|
28791
|
-
|
|
28792
|
-
|
|
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",
|
|
28793
29621
|
{
|
|
28794
|
-
|
|
28795
|
-
|
|
28796
|
-
|
|
28797
|
-
|
|
28798
|
-
|
|
28799
|
-
|
|
28800
|
-
|
|
28801
|
-
setHighlightedIndex(i2);
|
|
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
|
|
28802
29629
|
},
|
|
28803
|
-
|
|
28804
|
-
|
|
28805
|
-
|
|
28806
|
-
|
|
28807
|
-
|
|
28808
|
-
|
|
28809
|
-
|
|
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
|
+
}
|
|
28810
29657
|
}
|
|
28811
29658
|
);
|
|
28812
29659
|
}
|
|
@@ -28858,415 +29705,6 @@ const WordCountPlugin = () => {
|
|
|
28858
29705
|
}
|
|
28859
29706
|
);
|
|
28860
29707
|
};
|
|
28861
|
-
const GrammarCheckPlugin$1 = "";
|
|
28862
|
-
class GrammarCheckService {
|
|
28863
|
-
constructor() {
|
|
28864
|
-
__publicField(this, "cache", /* @__PURE__ */ new Map());
|
|
28865
|
-
__publicField(this, "apiEndpoint");
|
|
28866
|
-
__publicField(this, "pendingRequest", null);
|
|
28867
|
-
this.apiEndpoint = "https://api.cteditor.com/api/ai/process";
|
|
28868
|
-
}
|
|
28869
|
-
async check(text) {
|
|
28870
|
-
if (!text || text.trim().length < 3) {
|
|
28871
|
-
return [];
|
|
28872
|
-
}
|
|
28873
|
-
const cacheKey = text.trim();
|
|
28874
|
-
if (this.cache.has(cacheKey)) {
|
|
28875
|
-
return this.cache.get(cacheKey);
|
|
28876
|
-
}
|
|
28877
|
-
if (this.pendingRequest) {
|
|
28878
|
-
return this.pendingRequest;
|
|
28879
|
-
}
|
|
28880
|
-
this.pendingRequest = this.executeCheck(text);
|
|
28881
|
-
try {
|
|
28882
|
-
const result = await this.pendingRequest;
|
|
28883
|
-
return result;
|
|
28884
|
-
} finally {
|
|
28885
|
-
this.pendingRequest = null;
|
|
28886
|
-
}
|
|
28887
|
-
}
|
|
28888
|
-
async executeCheck(text) {
|
|
28889
|
-
var _a, _b, _c, _d, _e, _f;
|
|
28890
|
-
try {
|
|
28891
|
-
const response = await fetch(this.apiEndpoint, {
|
|
28892
|
-
method: "POST",
|
|
28893
|
-
headers: { "Content-Type": "application/json" },
|
|
28894
|
-
body: JSON.stringify({ text: text.trim(), maxSuggestions: 3 }),
|
|
28895
|
-
signal: AbortSignal.timeout(1e4)
|
|
28896
|
-
});
|
|
28897
|
-
if (!response.ok) {
|
|
28898
|
-
console.error("❌ GrammarCheck: API error:", response.status);
|
|
28899
|
-
return [];
|
|
28900
|
-
}
|
|
28901
|
-
const result = await response.json();
|
|
28902
|
-
const foundErrors = [];
|
|
28903
|
-
if ((_c = (_b = (_a = result.data) == null ? void 0 : _a.corrections) == null ? void 0 : _b.spelling) == null ? void 0 : _c.errors) {
|
|
28904
|
-
result.data.corrections.spelling.errors.forEach((err, idx) => {
|
|
28905
|
-
foundErrors.push({
|
|
28906
|
-
type: "spelling",
|
|
28907
|
-
original: err.original,
|
|
28908
|
-
suggestions: err.suggestions || [],
|
|
28909
|
-
index: idx
|
|
28910
|
-
});
|
|
28911
|
-
});
|
|
28912
|
-
}
|
|
28913
|
-
if ((_f = (_e = (_d = result.data) == null ? void 0 : _d.corrections) == null ? void 0 : _e.grammar) == null ? void 0 : _f.errors) {
|
|
28914
|
-
result.data.corrections.grammar.errors.forEach((err, idx) => {
|
|
28915
|
-
foundErrors.push({
|
|
28916
|
-
type: "grammar",
|
|
28917
|
-
original: err.original || text,
|
|
28918
|
-
suggestions: [err.suggestion],
|
|
28919
|
-
index: foundErrors.length + idx,
|
|
28920
|
-
issue: err.issue
|
|
28921
|
-
});
|
|
28922
|
-
});
|
|
28923
|
-
}
|
|
28924
|
-
this.cache.set(text.trim(), foundErrors);
|
|
28925
|
-
if (this.cache.size > 30) {
|
|
28926
|
-
const firstKey = this.cache.keys().next().value;
|
|
28927
|
-
if (firstKey) {
|
|
28928
|
-
this.cache.delete(firstKey);
|
|
28929
|
-
}
|
|
28930
|
-
}
|
|
28931
|
-
return foundErrors;
|
|
28932
|
-
} catch (error) {
|
|
28933
|
-
console.error("❌ GrammarCheck: Check failed:", error);
|
|
28934
|
-
return [];
|
|
28935
|
-
}
|
|
28936
|
-
}
|
|
28937
|
-
}
|
|
28938
|
-
function GrammarCheckPlugin() {
|
|
28939
|
-
const [editor] = useLexicalComposerContext();
|
|
28940
|
-
const { updateToolbarState } = useToolbarState();
|
|
28941
|
-
const [errors, setErrors] = useState$1([]);
|
|
28942
|
-
const [tooltip, setTooltip] = useState$1(null);
|
|
28943
|
-
const [userDismissed, setUserDismissed] = useState$1(false);
|
|
28944
|
-
const grammarService = useRef(new GrammarCheckService());
|
|
28945
|
-
const checkTimeout = useRef();
|
|
28946
|
-
const lastCheckedText = useRef("");
|
|
28947
|
-
const highlightElementsRef = useRef([]);
|
|
28948
|
-
const checkGrammar = useCallback(async () => {
|
|
28949
|
-
const isSlashActive = editor.getEditorState().read(() => {
|
|
28950
|
-
const selection = $getSelection();
|
|
28951
|
-
if (!$isRangeSelection(selection))
|
|
28952
|
-
return false;
|
|
28953
|
-
const anchor = selection.anchor;
|
|
28954
|
-
const anchorNode = anchor.getNode();
|
|
28955
|
-
const anchorOffset = anchor.offset;
|
|
28956
|
-
const textContent = anchorNode.getTextContent();
|
|
28957
|
-
let wordStart = anchorOffset;
|
|
28958
|
-
while (wordStart > 0 && /[a-zA-Z0-9_']/.test(textContent[wordStart - 1])) {
|
|
28959
|
-
wordStart--;
|
|
28960
|
-
}
|
|
28961
|
-
return wordStart > 0 && textContent[wordStart - 1] === "/";
|
|
28962
|
-
});
|
|
28963
|
-
if (isSlashActive) {
|
|
28964
|
-
setErrors([]);
|
|
28965
|
-
return;
|
|
28966
|
-
}
|
|
28967
|
-
const text = editor.getEditorState().read(() => $getRoot().getTextContent());
|
|
28968
|
-
if (text === lastCheckedText.current) {
|
|
28969
|
-
return;
|
|
28970
|
-
}
|
|
28971
|
-
if (Math.abs(text.length - lastCheckedText.current.length) > 20) {
|
|
28972
|
-
setUserDismissed(false);
|
|
28973
|
-
}
|
|
28974
|
-
lastCheckedText.current = text;
|
|
28975
|
-
if (!text || text.trim().length < 3) {
|
|
28976
|
-
setErrors([]);
|
|
28977
|
-
return;
|
|
28978
|
-
}
|
|
28979
|
-
const foundErrors = await grammarService.current.check(text);
|
|
28980
|
-
setErrors(foundErrors);
|
|
28981
|
-
}, [editor]);
|
|
28982
|
-
useEffect$1(() => {
|
|
28983
|
-
const unregister = editor.registerUpdateListener(() => {
|
|
28984
|
-
clearTimeout(checkTimeout.current);
|
|
28985
|
-
checkTimeout.current = window.setTimeout(checkGrammar, 2e3);
|
|
28986
|
-
});
|
|
28987
|
-
return () => {
|
|
28988
|
-
unregister();
|
|
28989
|
-
clearTimeout(checkTimeout.current);
|
|
28990
|
-
};
|
|
28991
|
-
}, [editor, checkGrammar]);
|
|
28992
|
-
useEffect$1(() => {
|
|
28993
|
-
highlightElementsRef.current.forEach((el) => {
|
|
28994
|
-
el.classList.remove("spelling-error", "grammar-error");
|
|
28995
|
-
});
|
|
28996
|
-
highlightElementsRef.current = [];
|
|
28997
|
-
if (errors.length === 0 || userDismissed)
|
|
28998
|
-
return;
|
|
28999
|
-
const timeoutId = setTimeout(() => {
|
|
29000
|
-
const editorElement = document.querySelector(".ContentEditable__root");
|
|
29001
|
-
if (!editorElement)
|
|
29002
|
-
return;
|
|
29003
|
-
const walker = document.createTreeWalker(
|
|
29004
|
-
editorElement,
|
|
29005
|
-
NodeFilter.SHOW_TEXT,
|
|
29006
|
-
null
|
|
29007
|
-
);
|
|
29008
|
-
const textNodes = [];
|
|
29009
|
-
let node;
|
|
29010
|
-
while (node = walker.nextNode()) {
|
|
29011
|
-
textNodes.push(node);
|
|
29012
|
-
}
|
|
29013
|
-
errors.forEach((error) => {
|
|
29014
|
-
textNodes.forEach((textNode) => {
|
|
29015
|
-
const nodeText = textNode.textContent || "";
|
|
29016
|
-
const errorIndex = nodeText.toLowerCase().indexOf(error.original.toLowerCase());
|
|
29017
|
-
if (errorIndex !== -1 && textNode.parentElement) {
|
|
29018
|
-
const className = error.type === "spelling" ? "spelling-error" : "grammar-error";
|
|
29019
|
-
if (textNode.parentElement.tagName === "SPAN") {
|
|
29020
|
-
textNode.parentElement.classList.add(className);
|
|
29021
|
-
highlightElementsRef.current.push(textNode.parentElement);
|
|
29022
|
-
} else if (textNode.parentElement) {
|
|
29023
|
-
const range = document.createRange();
|
|
29024
|
-
range.setStart(textNode, errorIndex);
|
|
29025
|
-
range.setEnd(textNode, Math.min(errorIndex + error.original.length, nodeText.length));
|
|
29026
|
-
const span = document.createElement("span");
|
|
29027
|
-
span.className = className;
|
|
29028
|
-
span.setAttribute("data-error-type", error.type);
|
|
29029
|
-
try {
|
|
29030
|
-
range.surroundContents(span);
|
|
29031
|
-
highlightElementsRef.current.push(span);
|
|
29032
|
-
} catch (e) {
|
|
29033
|
-
if (textNode.parentElement) {
|
|
29034
|
-
textNode.parentElement.classList.add(className);
|
|
29035
|
-
highlightElementsRef.current.push(textNode.parentElement);
|
|
29036
|
-
}
|
|
29037
|
-
}
|
|
29038
|
-
}
|
|
29039
|
-
}
|
|
29040
|
-
});
|
|
29041
|
-
});
|
|
29042
|
-
}, 100);
|
|
29043
|
-
return () => clearTimeout(timeoutId);
|
|
29044
|
-
}, [errors, userDismissed]);
|
|
29045
|
-
const getWordAtPoint = useCallback((x2, y2) => {
|
|
29046
|
-
try {
|
|
29047
|
-
let range = null;
|
|
29048
|
-
if (document.caretRangeFromPoint) {
|
|
29049
|
-
range = document.caretRangeFromPoint(x2, y2);
|
|
29050
|
-
} else if (document.caretPositionFromPoint) {
|
|
29051
|
-
const position = document.caretPositionFromPoint(x2, y2);
|
|
29052
|
-
if (position) {
|
|
29053
|
-
range = document.createRange();
|
|
29054
|
-
range.setStart(position.offsetNode, position.offset);
|
|
29055
|
-
}
|
|
29056
|
-
}
|
|
29057
|
-
if (!range)
|
|
29058
|
-
return null;
|
|
29059
|
-
const textNode = range.startContainer;
|
|
29060
|
-
if (textNode.nodeType !== Node.TEXT_NODE)
|
|
29061
|
-
return null;
|
|
29062
|
-
const text = textNode.textContent || "";
|
|
29063
|
-
let start = range.startOffset;
|
|
29064
|
-
let end = range.startOffset;
|
|
29065
|
-
while (start > 0 && /\w/.test(text[start - 1])) {
|
|
29066
|
-
start--;
|
|
29067
|
-
}
|
|
29068
|
-
while (end < text.length && /\w/.test(text[end])) {
|
|
29069
|
-
end++;
|
|
29070
|
-
}
|
|
29071
|
-
const word = text.substring(start, end).trim();
|
|
29072
|
-
return word || null;
|
|
29073
|
-
} catch (error) {
|
|
29074
|
-
console.error("Error getting word at point:", error);
|
|
29075
|
-
return null;
|
|
29076
|
-
}
|
|
29077
|
-
}, []);
|
|
29078
|
-
useEffect$1(() => {
|
|
29079
|
-
if (errors.length === 0)
|
|
29080
|
-
return;
|
|
29081
|
-
let hoverTimeout;
|
|
29082
|
-
const handleMouseMove = (e) => {
|
|
29083
|
-
clearTimeout(hoverTimeout);
|
|
29084
|
-
hoverTimeout = window.setTimeout(() => {
|
|
29085
|
-
const wordAtCursor = getWordAtPoint(e.clientX, e.clientY);
|
|
29086
|
-
if (wordAtCursor) {
|
|
29087
|
-
const matchedError = errors.find(
|
|
29088
|
-
(err) => wordAtCursor.toLowerCase() === err.original.toLowerCase()
|
|
29089
|
-
);
|
|
29090
|
-
if (matchedError) {
|
|
29091
|
-
setTooltip({
|
|
29092
|
-
error: matchedError,
|
|
29093
|
-
x: e.clientX,
|
|
29094
|
-
y: e.clientY
|
|
29095
|
-
});
|
|
29096
|
-
}
|
|
29097
|
-
}
|
|
29098
|
-
}, 50);
|
|
29099
|
-
};
|
|
29100
|
-
const handleClick = () => {
|
|
29101
|
-
setTooltip(null);
|
|
29102
|
-
};
|
|
29103
|
-
document.addEventListener("mousemove", handleMouseMove);
|
|
29104
|
-
document.addEventListener("click", handleClick);
|
|
29105
|
-
return () => {
|
|
29106
|
-
clearTimeout(hoverTimeout);
|
|
29107
|
-
document.removeEventListener("mousemove", handleMouseMove);
|
|
29108
|
-
document.removeEventListener("click", handleClick);
|
|
29109
|
-
};
|
|
29110
|
-
}, [errors, getWordAtPoint]);
|
|
29111
|
-
const applyCorrection = useCallback(
|
|
29112
|
-
(suggestion, original, errorType) => {
|
|
29113
|
-
editor.update(() => {
|
|
29114
|
-
const root2 = $getRoot();
|
|
29115
|
-
const currentText = root2.getTextContent();
|
|
29116
|
-
const isSpellingError = errorType === "spelling";
|
|
29117
|
-
let newText = currentText;
|
|
29118
|
-
if (isSpellingError) {
|
|
29119
|
-
const escapedOriginal = original.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
29120
|
-
const regex = new RegExp(`\\b${escapedOriginal}\\b`, "gi");
|
|
29121
|
-
newText = currentText.replace(regex, suggestion);
|
|
29122
|
-
} else {
|
|
29123
|
-
const escapedOriginal = original.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
29124
|
-
const regex = new RegExp(escapedOriginal, "gi");
|
|
29125
|
-
if (currentText.toLowerCase().includes(original.toLowerCase())) {
|
|
29126
|
-
newText = currentText.replace(regex, suggestion);
|
|
29127
|
-
} else {
|
|
29128
|
-
newText = suggestion;
|
|
29129
|
-
}
|
|
29130
|
-
}
|
|
29131
|
-
root2.clear();
|
|
29132
|
-
const paragraph = $createParagraphNode();
|
|
29133
|
-
const textNode = $createTextNode(newText);
|
|
29134
|
-
paragraph.append(textNode);
|
|
29135
|
-
root2.append(paragraph);
|
|
29136
|
-
});
|
|
29137
|
-
setTooltip(null);
|
|
29138
|
-
setTimeout(() => {
|
|
29139
|
-
lastCheckedText.current = "";
|
|
29140
|
-
checkGrammar();
|
|
29141
|
-
}, 100);
|
|
29142
|
-
},
|
|
29143
|
-
[editor, checkGrammar]
|
|
29144
|
-
);
|
|
29145
|
-
const showErrorTooltip = (error, event) => {
|
|
29146
|
-
setTooltip({
|
|
29147
|
-
error,
|
|
29148
|
-
x: event.clientX,
|
|
29149
|
-
y: event.clientY
|
|
29150
|
-
});
|
|
29151
|
-
};
|
|
29152
|
-
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
29153
|
-
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: [
|
|
29154
|
-
/* @__PURE__ */ jsx(AlertCircle, { className: "cteditor-h-4 cteditor-w-4 cteditor-text-amber-600 cteditor-flex-shrink-0" }),
|
|
29155
|
-
/* @__PURE__ */ jsxs("div", { className: "cteditor-flex cteditor-items-center cteditor-gap-2 cteditor-flex-1 cteditor-overflow-x-auto cteditor-max-w-2xl", children: [
|
|
29156
|
-
/* @__PURE__ */ jsxs("span", { className: "cteditor-text-xs cteditor-font-semibold cteditor-text-amber-800 cteditor-whitespace-nowrap", children: [
|
|
29157
|
-
errors.length,
|
|
29158
|
-
" ",
|
|
29159
|
-
errors.length === 1 ? "issue" : "issues",
|
|
29160
|
-
":"
|
|
29161
|
-
] }),
|
|
29162
|
-
/* @__PURE__ */ jsx("div", { className: "cteditor-flex cteditor-gap-2 cteditor-items-center", children: errors.map((error, idx) => /* @__PURE__ */ jsxs(
|
|
29163
|
-
"div",
|
|
29164
|
-
{
|
|
29165
|
-
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",
|
|
29166
|
-
onClick: (e) => showErrorTooltip(error, e),
|
|
29167
|
-
children: [
|
|
29168
|
-
/* @__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 }),
|
|
29169
|
-
/* @__PURE__ */ jsx("span", { className: "cteditor-text-xs cteditor-text-gray-400", children: "→" }),
|
|
29170
|
-
/* @__PURE__ */ jsx(
|
|
29171
|
-
"button",
|
|
29172
|
-
{
|
|
29173
|
-
onClick: (e) => {
|
|
29174
|
-
e.stopPropagation();
|
|
29175
|
-
applyCorrection(error.suggestions[0], error.original, error.type);
|
|
29176
|
-
},
|
|
29177
|
-
className: "cteditor-text-xs cteditor-text-green-600 hover:cteditor-text-green-700 cteditor-font-medium cteditor-max-w-24 cteditor-truncate",
|
|
29178
|
-
title: error.suggestions[0],
|
|
29179
|
-
children: error.suggestions[0]
|
|
29180
|
-
}
|
|
29181
|
-
)
|
|
29182
|
-
]
|
|
29183
|
-
},
|
|
29184
|
-
idx
|
|
29185
|
-
)) })
|
|
29186
|
-
] }),
|
|
29187
|
-
/* @__PURE__ */ jsxs("div", { className: "cteditor-flex cteditor-items-center cteditor-gap-1 cteditor-flex-shrink-0", children: [
|
|
29188
|
-
/* @__PURE__ */ jsx(
|
|
29189
|
-
Button,
|
|
29190
|
-
{
|
|
29191
|
-
variant: "link",
|
|
29192
|
-
size: "sm",
|
|
29193
|
-
onClick: () => {
|
|
29194
|
-
setUserDismissed(true);
|
|
29195
|
-
setErrors([]);
|
|
29196
|
-
updateToolbarState("isGrammarCheckEnabled", false);
|
|
29197
|
-
},
|
|
29198
|
-
className: "cteditor-h-7 cteditor-px-2 cteditor-text-xs !cteditor-text-amber-700 ",
|
|
29199
|
-
title: "Disable Grammar Check",
|
|
29200
|
-
children: "Disable"
|
|
29201
|
-
}
|
|
29202
|
-
),
|
|
29203
|
-
/* @__PURE__ */ jsx(
|
|
29204
|
-
"button",
|
|
29205
|
-
{
|
|
29206
|
-
onClick: () => setUserDismissed(true),
|
|
29207
|
-
className: "cteditor-p-1 hover:cteditor-bg-amber-100 cteditor-rounded cteditor-transition-colors",
|
|
29208
|
-
title: "Dismiss grammar suggestions",
|
|
29209
|
-
children: /* @__PURE__ */ jsx(X$1, { className: "cteditor-h-3.5 cteditor-w-3.5 cteditor-text-amber-600" })
|
|
29210
|
-
}
|
|
29211
|
-
)
|
|
29212
|
-
] })
|
|
29213
|
-
] }) }),
|
|
29214
|
-
tooltip && createPortal(
|
|
29215
|
-
/* @__PURE__ */ jsx(
|
|
29216
|
-
"div",
|
|
29217
|
-
{
|
|
29218
|
-
className: "grammar-tooltip ",
|
|
29219
|
-
style: {
|
|
29220
|
-
position: "fixed",
|
|
29221
|
-
left: tooltip.x,
|
|
29222
|
-
top: tooltip.y + 20,
|
|
29223
|
-
zIndex: 1e4
|
|
29224
|
-
},
|
|
29225
|
-
onMouseEnter: () => {
|
|
29226
|
-
},
|
|
29227
|
-
onMouseLeave: () => {
|
|
29228
|
-
setTooltip(null);
|
|
29229
|
-
},
|
|
29230
|
-
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: [
|
|
29231
|
-
/* @__PURE__ */ jsxs("div", { className: "cteditor-flex cteditor-items-center cteditor-gap-2 cteditor-mb-3", children: [
|
|
29232
|
-
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" }),
|
|
29233
|
-
/* @__PURE__ */ jsx(
|
|
29234
|
-
Badge,
|
|
29235
|
-
{
|
|
29236
|
-
variant: tooltip.error.type === "spelling" ? "destructive" : "default",
|
|
29237
|
-
className: "cteditor-text-xs",
|
|
29238
|
-
children: tooltip.error.type === "spelling" ? "Spelling Error" : "Grammar Issue"
|
|
29239
|
-
}
|
|
29240
|
-
)
|
|
29241
|
-
] }),
|
|
29242
|
-
tooltip.error.issue && /* @__PURE__ */ jsx("p", { className: "cteditor-text-xs cteditor-text-muted-foreground cteditor-mb-2 cteditor-italic", children: tooltip.error.issue }),
|
|
29243
|
-
/* @__PURE__ */ jsxs("div", { className: "cteditor-mb-2", children: [
|
|
29244
|
-
/* @__PURE__ */ jsx("p", { className: "cteditor-text-xs cteditor-font-semibold cteditor-text-muted-foreground", children: "Original:" }),
|
|
29245
|
-
/* @__PURE__ */ jsx("p", { className: "cteditor-text-sm cteditor-line-through cteditor-text-red-600", children: tooltip.error.original })
|
|
29246
|
-
] }),
|
|
29247
|
-
tooltip.error.suggestions.length > 0 && /* @__PURE__ */ jsxs("div", { children: [
|
|
29248
|
-
/* @__PURE__ */ jsx("p", { className: "cteditor-text-xs cteditor-font-semibold cteditor-text-muted-foreground cteditor-mb-1", children: "Suggestions:" }),
|
|
29249
|
-
/* @__PURE__ */ jsx("div", { className: "cteditor-space-y-1", children: tooltip.error.suggestions.map((suggestion, idx) => /* @__PURE__ */ jsxs(
|
|
29250
|
-
"button",
|
|
29251
|
-
{
|
|
29252
|
-
onClick: () => applyCorrection(suggestion, tooltip.error.original, tooltip.error.type),
|
|
29253
|
-
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",
|
|
29254
|
-
children: [
|
|
29255
|
-
"✓ ",
|
|
29256
|
-
suggestion
|
|
29257
|
-
]
|
|
29258
|
-
},
|
|
29259
|
-
idx
|
|
29260
|
-
)) })
|
|
29261
|
-
] }),
|
|
29262
|
-
tooltip.error.suggestions.length === 0 && /* @__PURE__ */ jsx("p", { className: "cteditor-text-xs cteditor-text-muted-foreground cteditor-italic", children: "No suggestions available" })
|
|
29263
|
-
] }) })
|
|
29264
|
-
}
|
|
29265
|
-
),
|
|
29266
|
-
document.body
|
|
29267
|
-
)
|
|
29268
|
-
] });
|
|
29269
|
-
}
|
|
29270
29708
|
const useStyles = () => ({
|
|
29271
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",
|
|
29272
29710
|
contentEditable: cn$1(
|
|
@@ -29360,12 +29798,12 @@ const ToolbarWithEditor = (props) => {
|
|
|
29360
29798
|
}
|
|
29361
29799
|
);
|
|
29362
29800
|
};
|
|
29363
|
-
const
|
|
29801
|
+
const CombinedPluginWrapper = () => {
|
|
29364
29802
|
const { toolbarState } = useToolbarState();
|
|
29365
|
-
if (!toolbarState.isAutocompleteEnabled) {
|
|
29803
|
+
if (!toolbarState.isAutocompleteEnabled && !toolbarState.isGrammarCheckEnabled) {
|
|
29366
29804
|
return null;
|
|
29367
29805
|
}
|
|
29368
|
-
return /* @__PURE__ */ jsx(
|
|
29806
|
+
return /* @__PURE__ */ jsx(CombinedAutocompleteGrammarPlugin, { minMatchLength: 2, maxSuggestions: 10, enableAI: true });
|
|
29369
29807
|
};
|
|
29370
29808
|
const OnChangeWrapper = ({ onChange }) => {
|
|
29371
29809
|
const [editor] = useLexicalComposerContext();
|
|
@@ -29492,14 +29930,15 @@ const ConfigurableEditor = ({
|
|
|
29492
29930
|
/* @__PURE__ */ jsx(HtmlSyncPlugin, {}),
|
|
29493
29931
|
/* @__PURE__ */ jsx(CodeHighlightPlugin, {}),
|
|
29494
29932
|
/* @__PURE__ */ jsx(SlashCommandPlugin, {}),
|
|
29495
|
-
/* @__PURE__ */ jsx(
|
|
29496
|
-
/* @__PURE__ */ jsx(GrammarCheckPlugin, {}),
|
|
29933
|
+
/* @__PURE__ */ jsx(CombinedPluginWrapper, {}),
|
|
29497
29934
|
/* @__PURE__ */ jsx(OnChangeWrapper, { onChange }),
|
|
29498
29935
|
/* @__PURE__ */ jsx(InitialContentPlugin, { initialContent }),
|
|
29499
29936
|
/* @__PURE__ */ jsx(HistoryPlugin, {}),
|
|
29500
29937
|
/* @__PURE__ */ jsx(LocalStoragePlugin$1, { namespace: initialConfig.namespace }),
|
|
29501
29938
|
/* @__PURE__ */ jsx(ListPlugin, {}),
|
|
29502
29939
|
/* @__PURE__ */ jsx(LinkPlugin, { hasLinkAttributes: false }),
|
|
29940
|
+
/* @__PURE__ */ jsx(DragDropPaste, {}),
|
|
29941
|
+
/* @__PURE__ */ jsx(RichTextPastePlugin, {}),
|
|
29503
29942
|
/* @__PURE__ */ jsx(FilePlugin, {}),
|
|
29504
29943
|
/* @__PURE__ */ jsx(HorizontalRulePlugin, {}),
|
|
29505
29944
|
/* @__PURE__ */ jsx(CustomHorizontalRulePlugin, {}),
|
|
@@ -29561,7 +30000,7 @@ const ScopedEditorWrapper = ({
|
|
|
29561
30000
|
className = "",
|
|
29562
30001
|
darkMode = false
|
|
29563
30002
|
}) => {
|
|
29564
|
-
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 }) });
|
|
29565
30004
|
};
|
|
29566
30005
|
const MessageContainer = styled.div`
|
|
29567
30006
|
display: flex;
|
|
@@ -29685,4 +30124,4 @@ export {
|
|
|
29685
30124
|
useHtmlView as u,
|
|
29686
30125
|
verifyApiKey as v
|
|
29687
30126
|
};
|
|
29688
|
-
//# sourceMappingURL=index-
|
|
30127
|
+
//# sourceMappingURL=index-8d147c36.js.map
|