ct-rich-text-editor 1.3.26 → 1.3.27

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.
@@ -24,7 +24,7 @@ import { TablePlugin } from "@lexical/react/LexicalTablePlugin";
24
24
  import { TableNode, TableCellNode, TableRowNode, $createTableNodeWithDimensions, $isTableRowNode, $isTableCellNode, TableCellHeaderStates, $isTableNode, $isTableSelection, $getTableCellNodeFromLexicalNode, $getTableNodeFromLexicalNodeOrThrow, getTableElement, getTableObserverFromTableElement, $getTableRowIndexFromTableCellNode, $getNodeTriplet, $insertTableRow__EXPERIMENTAL, $getTableColumnIndexFromTableCellNode, $insertTableColumn__EXPERIMENTAL, $deleteTableRow__EXPERIMENTAL, $deleteTableColumn__EXPERIMENTAL, $unmergeCell, $computeTableMapSkipCellCheck, getDOMCellFromTarget, $getTableAndElementByKey } from "@lexical/table";
25
25
  import { mergeRegister, $wrapNodeInElement, $findMatchingParent, $getNearestNodeOfType, $getNearestBlockElementAncestorOrThrow, $insertNodeToNearestRoot, $isEditorIsNestedEditor, mediaFileReader, isMimeType, calculateZoomLevel, CAN_USE_DOM } from "@lexical/utils";
26
26
  import Stack from "@mui/material/Stack";
27
- import { createCommand, DecoratorNode, createEditor, $applyNodeReplacement, $insertNodes, $isRootOrShadowRoot, $createParagraphNode, COMMAND_PRIORITY_EDITOR, COMMAND_PRIORITY_LOW, $getSelection, $isRangeSelection, $getNearestNodeFromDOMNode, isHTMLElement as isHTMLElement$1, TextNode, $getRoot, $createTextNode, $getNodeByKey, $isParagraphNode, $isTextNode, FORMAT_TEXT_COMMAND, FORMAT_ELEMENT_COMMAND, KEY_DOWN_COMMAND, COMMAND_PRIORITY_CRITICAL, CAN_UNDO_COMMAND, CAN_REDO_COMMAND, $isElementNode, SELECTION_CHANGE_COMMAND, UNDO_COMMAND, REDO_COMMAND, KEY_SPACE_COMMAND, $isLineBreakNode, $createRangeSelection, $setSelection, COMMAND_PRIORITY_HIGH, KEY_ARROW_DOWN_COMMAND, KEY_ARROW_UP_COMMAND, KEY_ESCAPE_COMMAND, KEY_TAB_COMMAND, KEY_ENTER_COMMAND, $createNodeSelection, $isNodeSelection, getDOMSelection, CLICK_COMMAND, PASTE_COMMAND, ParagraphNode, $createLineBreakNode, isDOMNode } from "lexical";
27
+ import { createCommand, DecoratorNode, createEditor, $applyNodeReplacement, $getSelection, $isRangeSelection, ElementNode, $isRootOrShadowRoot, $createParagraphNode, COMMAND_PRIORITY_EDITOR, COMMAND_PRIORITY_LOW, $insertNodes, $getNearestNodeFromDOMNode, isHTMLElement as isHTMLElement$1, TextNode, $getRoot, $createTextNode, $getNodeByKey, $isParagraphNode, $isTextNode, FORMAT_TEXT_COMMAND, FORMAT_ELEMENT_COMMAND, KEY_DOWN_COMMAND, COMMAND_PRIORITY_CRITICAL, CAN_UNDO_COMMAND, CAN_REDO_COMMAND, $isElementNode, SELECTION_CHANGE_COMMAND, UNDO_COMMAND, REDO_COMMAND, KEY_SPACE_COMMAND, $isLineBreakNode, $createRangeSelection, $setSelection, COMMAND_PRIORITY_HIGH, KEY_ARROW_DOWN_COMMAND, KEY_ARROW_UP_COMMAND, KEY_ESCAPE_COMMAND, KEY_TAB_COMMAND, KEY_ENTER_COMMAND, $createNodeSelection, $isNodeSelection, getDOMSelection, CLICK_COMMAND, PASTE_COMMAND, ParagraphNode, $createLineBreakNode, isDOMNode } from "lexical";
28
28
  import * as ReactDOM from "react-dom";
29
29
  import ReactDOM__default, { createPortal } from "react-dom";
30
30
  import { $isCodeNode, CodeNode, normalizeCodeLang, getLanguageFriendlyName, CodeHighlightNode, CODE_LANGUAGE_MAP, $createCodeNode, registerCodeHighlighting, $isCodeHighlightNode } from "@lexical/code";
@@ -1395,6 +1395,9 @@ const apiEndpoints = {
1395
1395
  },
1396
1396
  transcript: {
1397
1397
  voiceTranscript: "/api/transcript/get-assemblyai-token"
1398
+ },
1399
+ linkPreview: {
1400
+ getPreview: "/api/link-preview"
1398
1401
  }
1399
1402
  };
1400
1403
  const AiJsonResponse = async ({ content }) => {
@@ -1478,7 +1481,7 @@ const AiTextTransform = async ({ content, apiKey }) => {
1478
1481
  const AI_ACTION_COMMAND = createCommand(
1479
1482
  "AI_ACTION_COMMAND"
1480
1483
  );
1481
- const ImageView = React__default.lazy(() => import("./index-01a6d110.js"));
1484
+ const ImageView = React__default.lazy(() => import("./index-aa2e3927.js"));
1482
1485
  function isGoogleDocCheckboxImg(img) {
1483
1486
  return img.parentElement != null && img.parentElement.tagName === "LI" && img.previousSibling === null && img.getAttribute("aria-roledescription") === "checkbox";
1484
1487
  }
@@ -1738,7 +1741,37 @@ const ImagePlugin = ({
1738
1741
  INSERT_IMAGE_COMMAND,
1739
1742
  (payload) => {
1740
1743
  const imageNode = $createImageNode(payload);
1741
- $insertNodes([imageNode]);
1744
+ const selection = $getSelection();
1745
+ if ($isRangeSelection(selection)) {
1746
+ const anchorNode = selection.anchor.getNode();
1747
+ const anchorParent = anchorNode.getParent();
1748
+ if (anchorParent instanceof ElementNode && !$isRootOrShadowRoot(anchorParent)) {
1749
+ const parentType = anchorParent.getType();
1750
+ if (parentType === "paragraph" || parentType === "listitem") {
1751
+ const hasContent = anchorParent.getTextContent().trim().length > 0;
1752
+ const isAtEnd = selection.anchor.offset === anchorNode.getTextContentSize();
1753
+ const isAtStart = selection.anchor.offset === 0;
1754
+ if (hasContent) {
1755
+ const imageParagraph = $createParagraphNode();
1756
+ imageParagraph.append(imageNode);
1757
+ if (isAtEnd) {
1758
+ anchorParent.insertAfter(imageParagraph);
1759
+ } else if (isAtStart) {
1760
+ anchorParent.insertBefore(imageParagraph);
1761
+ } else {
1762
+ anchorParent.insertAfter(imageParagraph);
1763
+ }
1764
+ const emptyParagraph = $createParagraphNode();
1765
+ imageParagraph.insertAfter(emptyParagraph);
1766
+ emptyParagraph.selectEnd();
1767
+ return true;
1768
+ }
1769
+ }
1770
+ }
1771
+ }
1772
+ if ($isRangeSelection(selection)) {
1773
+ selection.insertNodes([imageNode]);
1774
+ }
1742
1775
  if ($isRootOrShadowRoot(imageNode.getParentOrThrow())) {
1743
1776
  $wrapNodeInElement(imageNode, $createParagraphNode).selectEnd();
1744
1777
  }
@@ -2111,20 +2144,20 @@ const createLruCache = (maxCacheSize) => {
2111
2144
  };
2112
2145
  }
2113
2146
  let cacheSize = 0;
2114
- let cache = /* @__PURE__ */ Object.create(null);
2147
+ let cache2 = /* @__PURE__ */ Object.create(null);
2115
2148
  let previousCache = /* @__PURE__ */ Object.create(null);
2116
2149
  const update = (key, value) => {
2117
- cache[key] = value;
2150
+ cache2[key] = value;
2118
2151
  cacheSize++;
2119
2152
  if (cacheSize > maxCacheSize) {
2120
2153
  cacheSize = 0;
2121
- previousCache = cache;
2122
- cache = /* @__PURE__ */ Object.create(null);
2154
+ previousCache = cache2;
2155
+ cache2 = /* @__PURE__ */ Object.create(null);
2123
2156
  }
2124
2157
  };
2125
2158
  return {
2126
2159
  get(key) {
2127
- let value = cache[key];
2160
+ let value = cache2[key];
2128
2161
  if (value !== void 0) {
2129
2162
  return value;
2130
2163
  }
@@ -2134,8 +2167,8 @@ const createLruCache = (maxCacheSize) => {
2134
2167
  }
2135
2168
  },
2136
2169
  set(key, value) {
2137
- if (key in cache) {
2138
- cache[key] = value;
2170
+ if (key in cache2) {
2171
+ cache2[key] = value;
2139
2172
  } else {
2140
2173
  update(key, value);
2141
2174
  }
@@ -12665,8 +12698,8 @@ function hasFixedPositionAncestor(element, stopNode) {
12665
12698
  }
12666
12699
  return getComputedStyle$1(parentNode).position === "fixed" || hasFixedPositionAncestor(parentNode, stopNode);
12667
12700
  }
12668
- function getClippingElementAncestors(element, cache) {
12669
- const cachedResult = cache.get(element);
12701
+ function getClippingElementAncestors(element, cache2) {
12702
+ const cachedResult = cache2.get(element);
12670
12703
  if (cachedResult) {
12671
12704
  return cachedResult;
12672
12705
  }
@@ -12688,7 +12721,7 @@ function getClippingElementAncestors(element, cache) {
12688
12721
  }
12689
12722
  currentNode = getParentNode(currentNode);
12690
12723
  }
12691
- cache.set(element, result);
12724
+ cache2.set(element, result);
12692
12725
  return result;
12693
12726
  }
12694
12727
  function getClippingRect(_ref) {
@@ -12986,14 +13019,14 @@ const hide$1 = hide$2;
12986
13019
  const arrow$2 = arrow$3;
12987
13020
  const limitShift$1 = limitShift$2;
12988
13021
  const computePosition = (reference, floating, options) => {
12989
- const cache = /* @__PURE__ */ new Map();
13022
+ const cache2 = /* @__PURE__ */ new Map();
12990
13023
  const mergedOptions = {
12991
13024
  platform,
12992
13025
  ...options
12993
13026
  };
12994
13027
  const platformWithCache = {
12995
13028
  ...mergedOptions.platform,
12996
- _c: cache
13029
+ _c: cache2
12997
13030
  };
12998
13031
  return computePosition$1(reference, floating, {
12999
13032
  ...mergedOptions,
@@ -15370,7 +15403,7 @@ const EmbedComponent = ({ url, displayType, alignment, nodeKey }) => {
15370
15403
  }
15371
15404
  );
15372
15405
  };
15373
- const FileComponent = React$1.lazy(() => import("./index-9b519a99.js"));
15406
+ const FileComponent = React$1.lazy(() => import("./index-4edbb171.js"));
15374
15407
  function convertFileElement(domNode) {
15375
15408
  if (domNode instanceof HTMLDivElement) {
15376
15409
  const dataUrl = domNode.getAttribute("data-lexical-file-src");
@@ -19160,6 +19193,7 @@ function AIChatDialog({
19160
19193
  selectedTextForInline
19161
19194
  }) {
19162
19195
  const [inputValue, setInputValue] = useState$1("");
19196
+ const [selectedText, setSelectedText] = useState$1("");
19163
19197
  const [isLoading, setIsLoading] = useState$1(false);
19164
19198
  const [errorMessage, setErrorMessage] = useState$1(null);
19165
19199
  const [provider, setProvider] = useState$1("chatgpt");
@@ -19168,7 +19202,11 @@ function AIChatDialog({
19168
19202
  const [purchasedCredits, setPurchasedCredits] = useState$1(0);
19169
19203
  useEffect$1(() => {
19170
19204
  if (open && initialText) {
19171
- setInputValue(initialText);
19205
+ setSelectedText(initialText);
19206
+ setInputValue("");
19207
+ } else if (!open) {
19208
+ setSelectedText("");
19209
+ setInputValue("");
19172
19210
  }
19173
19211
  }, [open, initialText]);
19174
19212
  const {
@@ -19243,8 +19281,26 @@ function AIChatDialog({
19243
19281
  setIsLoading(true);
19244
19282
  setErrorMessage(null);
19245
19283
  const isImageRequest = isImageGenerationRequest(inputValue);
19284
+ let finalPrompt;
19285
+ const hasSelectedText = selectedText && selectedText.trim() !== "";
19286
+ if (isImageRequest) {
19287
+ if (hasSelectedText) {
19288
+ finalPrompt = `${inputValue}: ${selectedText}`;
19289
+ } else {
19290
+ finalPrompt = inputValue;
19291
+ }
19292
+ } else if (hasSelectedText) {
19293
+ finalPrompt = `${inputValue}
19294
+
19295
+ IMPORTANT: Return ONLY the modified/transformed text. Do NOT include any labels, prefixes, explanations, or formatting like "Simplified:", "Result:", "Here is", etc. Just return the pure result text.
19296
+
19297
+ Text to transform:
19298
+ "${selectedText}"`;
19299
+ } else {
19300
+ finalPrompt = inputValue;
19301
+ }
19246
19302
  try {
19247
- const response = await AiEditorAction({ content: inputValue, provider, apiKey });
19303
+ const response = await AiEditorAction({ content: finalPrompt, provider, apiKey });
19248
19304
  const htmlString = response.data;
19249
19305
  const parser = new DOMParser();
19250
19306
  const dom = parser.parseFromString(htmlString.trim(), "text/html");
@@ -19281,6 +19337,7 @@ function AIChatDialog({
19281
19337
  const handleClose = () => {
19282
19338
  if (!isLoading) {
19283
19339
  setInputValue("");
19340
+ setSelectedText("");
19284
19341
  setErrorMessage(null);
19285
19342
  onOpenChange(false);
19286
19343
  }
@@ -19345,9 +19402,26 @@ function AIChatDialog({
19345
19402
  ] })
19346
19403
  ] }) }),
19347
19404
  /* @__PURE__ */ jsxs("div", { className: "cteditor-space-y-4 ", children: [
19405
+ selectedText && selectedText.trim() !== "" && /* @__PURE__ */ jsxs("div", { className: "cteditor-space-y-2", children: [
19406
+ /* @__PURE__ */ jsxs("div", { className: "cteditor-flex cteditor-items-center cteditor-justify-between", children: [
19407
+ /* @__PURE__ */ jsx(Label$2, { className: "cteditor-text-sm cteditor-font-medium cteditor-text-muted-foreground", children: "Selected Text" }),
19408
+ /* @__PURE__ */ jsx(
19409
+ "button",
19410
+ {
19411
+ type: "button",
19412
+ onClick: () => setSelectedText(""),
19413
+ className: "cteditor-text-xs cteditor-text-muted-foreground hover:cteditor-text-foreground cteditor-transition-colors",
19414
+ title: "Clear selected text",
19415
+ children: /* @__PURE__ */ jsx(X$1, { size: 14 })
19416
+ }
19417
+ )
19418
+ ] }),
19419
+ /* @__PURE__ */ jsx("div", { className: "cteditor-p-3 cteditor-rounded-md cteditor-bg-accent/50 cteditor-border cteditor-border-foreground/10 cteditor-max-h-24 cteditor-overflow-y-auto", children: /* @__PURE__ */ jsx("p", { className: "cteditor-text-xs cteditor-text-foreground/80 cteditor-whitespace-pre-wrap cteditor-break-words", children: selectedText.length > 300 ? selectedText.substring(0, 300) + "..." : selectedText }) }),
19420
+ /* @__PURE__ */ jsx("p", { className: "cteditor-text-xs cteditor-text-muted-foreground", children: "Your prompt will be applied to this selected text" })
19421
+ ] }),
19348
19422
  /* @__PURE__ */ jsxs("div", { children: [
19349
19423
  /* @__PURE__ */ jsxs("div", { className: "cteditor-flex cteditor-justify-between cteditor-gap-1 cteditor-min-h-8 cteditor-items-center", children: [
19350
- /* @__PURE__ */ jsx(Label$2, { htmlFor: "ai-prompt", className: "cteditor-text-sm cteditor-font-medium cteditor-mb-0 cteditor-block", children: "Your Question" }),
19424
+ /* @__PURE__ */ jsx(Label$2, { htmlFor: "ai-prompt", className: "cteditor-text-sm cteditor-font-medium cteditor-mb-0 cteditor-block", children: selectedText && selectedText.trim() !== "" ? "Your Instruction" : "Your Question" }),
19351
19425
  !isRecording && /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx(
19352
19426
  "button",
19353
19427
  {
@@ -19368,7 +19442,7 @@ function AIChatDialog({
19368
19442
  {
19369
19443
  ref: textareaRef,
19370
19444
  id: "ai-prompt",
19371
- placeholder: isVoiceLoading ? "Initializing microphone..." : isRecording ? isPaused ? "Paused..." : "Listening..." : "e.g., Improve this text, translate to Spanish, or explain this concept",
19445
+ placeholder: isVoiceLoading ? "Initializing microphone..." : isRecording ? isPaused ? "Paused..." : "Listening..." : selectedText && selectedText.trim() !== "" ? "e.g., Improve this, translate to Spanish, summarize, fix grammar..." : "e.g., Write a paragraph about..., Generate an image of...",
19372
19446
  value: inputValue,
19373
19447
  onChange: (e) => setInputValue(e.target.value),
19374
19448
  disabled: isLoading || isRecording || isVoiceLoading,
@@ -19423,7 +19497,7 @@ function AIChatDialog({
19423
19497
  ] }),
19424
19498
  !isRecording && !voiceError && !isVoiceLoading && /* @__PURE__ */ jsxs("div", { className: "cteditor-flex cteditor-items-center cteditor-gap-2 cteditor-text-xs cteditor-text-muted-foreground", children: [
19425
19499
  /* @__PURE__ */ jsx("svg", { className: "cteditor-w-4 cteditor-h-4 cteditor-opacity-60", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" }) }),
19426
- /* @__PURE__ */ jsx("span", { children: "Type your question or click the microphone icon to use voice input" })
19500
+ /* @__PURE__ */ jsx("span", { children: selectedText && selectedText.trim() !== "" ? "Enter what you want to do with the selected text, or use voice input" : "Type your question or click the microphone icon to use voice input" })
19427
19501
  ] })
19428
19502
  ] }),
19429
19503
  isVoiceLoading && /* @__PURE__ */ jsx("div", { className: "cteditor-p-3 cteditor-rounded-lg cteditor-bg-gray-100 dark:cteditor-bg-gray-900/50 cteditor-border cteditor-border-gray-300 dark:cteditor-border-gray-700", children: /* @__PURE__ */ jsxs("div", { className: "cteditor-flex cteditor-items-center cteditor-gap-2", children: [
@@ -20486,10 +20560,10 @@ const PDF_CONFIG = {
20486
20560
  };
20487
20561
  const loadHtml2Pdf = async () => {
20488
20562
  try {
20489
- const mod = await import("./html2pdf.bundle.min-1f376935.js").then((n) => n.h);
20563
+ const mod = await import("./html2pdf.bundle.min-382f2ad4.js").then((n) => n.h);
20490
20564
  return (mod == null ? void 0 : mod.default) || mod;
20491
20565
  } catch {
20492
- const mod2 = await import("./html2pdf.bundle-41a72ab2.js").then((n) => n.h);
20566
+ const mod2 = await import("./html2pdf.bundle-08dfd2d4.js").then((n) => n.h);
20493
20567
  return (mod2 == null ? void 0 : mod2.default) || mod2;
20494
20568
  }
20495
20569
  };
@@ -27805,7 +27879,7 @@ const STATIC_SUGGESTIONS = [
27805
27879
  "programming"
27806
27880
  ];
27807
27881
  const CACHE_MAX_AGE = 5 * 60 * 1e3;
27808
- const MAX_CACHE_SIZE = 200;
27882
+ const MAX_CACHE_SIZE$1 = 200;
27809
27883
  const REQUEST_TIMEOUT = 3e4;
27810
27884
  const MENU_CONFIG = { width: 320, height: 200, padding: 8 };
27811
27885
  const TOOLTIP_CONFIG = {
@@ -27977,7 +28051,7 @@ class GrammarAIService {
27977
28051
  errors,
27978
28052
  checkedAt: Date.now()
27979
28053
  });
27980
- if (this.sentenceCache.size > MAX_CACHE_SIZE) {
28054
+ if (this.sentenceCache.size > MAX_CACHE_SIZE$1) {
27981
28055
  const oldestKey = this.sentenceCache.keys().next().value;
27982
28056
  if (oldestKey)
27983
28057
  this.sentenceCache.delete(oldestKey);
@@ -31361,7 +31435,51 @@ function LinkPlugin({
31361
31435
  }
31362
31436
  );
31363
31437
  }
31364
- function LinkPreviewPlugin() {
31438
+ const cache = /* @__PURE__ */ new Map();
31439
+ const CACHE_TTL = 30 * 60 * 1e3;
31440
+ const MAX_CACHE_SIZE = 100;
31441
+ function getCached(url) {
31442
+ const entry = cache.get(url);
31443
+ if (!entry)
31444
+ return null;
31445
+ if (Date.now() - entry.timestamp > CACHE_TTL) {
31446
+ cache.delete(url);
31447
+ return null;
31448
+ }
31449
+ return entry.data;
31450
+ }
31451
+ function setCache(url, data) {
31452
+ if (cache.size >= MAX_CACHE_SIZE) {
31453
+ const oldestKey = cache.keys().next().value;
31454
+ if (oldestKey)
31455
+ cache.delete(oldestKey);
31456
+ }
31457
+ cache.set(url, { data, timestamp: Date.now() });
31458
+ }
31459
+ async function fetchLinkPreview({
31460
+ url,
31461
+ apiKey
31462
+ }) {
31463
+ const cached = getCached(url);
31464
+ if (cached)
31465
+ return cached;
31466
+ try {
31467
+ const response = await backendAPI.post(
31468
+ apiEndpoints.linkPreview.getPreview,
31469
+ { url },
31470
+ apiKey ? { headers: { "X-API-Key": apiKey } } : void 0
31471
+ );
31472
+ if (response.data.success && response.data.data) {
31473
+ setCache(url, response.data.data);
31474
+ return response.data.data;
31475
+ }
31476
+ return null;
31477
+ } catch (error) {
31478
+ console.error("Error fetching link preview:", error);
31479
+ return null;
31480
+ }
31481
+ }
31482
+ function LinkPreviewPlugin({ apiKey }) {
31365
31483
  const [editor] = useLexicalComposerContext();
31366
31484
  const [hoveredLink, setHoveredLink] = useState$1(null);
31367
31485
  useEffect$1(() => {
@@ -31385,20 +31503,14 @@ function LinkPreviewPlugin() {
31385
31503
  if (linkElement && editorElement.contains(linkElement)) {
31386
31504
  const href = linkElement.getAttribute("href");
31387
31505
  if (href && href !== "https://" && href !== "http://" && href !== "#") {
31388
- if (showTimeout) {
31506
+ if (showTimeout)
31389
31507
  clearTimeout(showTimeout);
31390
- }
31391
31508
  if (hideTimeout) {
31392
31509
  clearTimeout(hideTimeout);
31393
31510
  hideTimeout = null;
31394
31511
  }
31395
31512
  showTimeout = window.setTimeout(() => {
31396
- const rect = linkElement.getBoundingClientRect();
31397
- setHoveredLink({
31398
- url: href,
31399
- text: linkElement.textContent || "",
31400
- rect
31401
- });
31513
+ setHoveredLink({ url: href, rect: linkElement.getBoundingClientRect() });
31402
31514
  }, 500);
31403
31515
  }
31404
31516
  }
@@ -31408,12 +31520,10 @@ function LinkPreviewPlugin() {
31408
31520
  const relatedTarget = event.relatedTarget;
31409
31521
  if (target.closest(".link-preview-card")) {
31410
31522
  isOverPreview = false;
31411
- const movingToLink = relatedTarget == null ? void 0 : relatedTarget.closest("a");
31412
- if (!movingToLink) {
31523
+ if (!(relatedTarget == null ? void 0 : relatedTarget.closest("a"))) {
31413
31524
  hideTimeout = window.setTimeout(() => {
31414
- if (!isOverPreview) {
31525
+ if (!isOverPreview)
31415
31526
  setHoveredLink(null);
31416
- }
31417
31527
  }, 300);
31418
31528
  }
31419
31529
  return;
@@ -31424,19 +31534,16 @@ function LinkPreviewPlugin() {
31424
31534
  clearTimeout(showTimeout);
31425
31535
  showTimeout = null;
31426
31536
  }
31427
- const movingToPreview = relatedTarget == null ? void 0 : relatedTarget.closest(".link-preview-card");
31428
- if (!movingToPreview) {
31537
+ if (!(relatedTarget == null ? void 0 : relatedTarget.closest(".link-preview-card"))) {
31429
31538
  hideTimeout = window.setTimeout(() => {
31430
- if (!isOverPreview) {
31539
+ if (!isOverPreview)
31431
31540
  setHoveredLink(null);
31432
- }
31433
31541
  }, 300);
31434
31542
  }
31435
31543
  }
31436
31544
  };
31437
31545
  const handlePreviewMouseOver = (event) => {
31438
- const target = event.target;
31439
- if (target.closest(".link-preview-card")) {
31546
+ if (event.target.closest(".link-preview-card")) {
31440
31547
  isOverPreview = true;
31441
31548
  if (hideTimeout) {
31442
31549
  clearTimeout(hideTimeout);
@@ -31449,12 +31556,10 @@ function LinkPreviewPlugin() {
31449
31556
  const relatedTarget = event.relatedTarget;
31450
31557
  if (target.closest(".link-preview-card")) {
31451
31558
  isOverPreview = false;
31452
- const movingToLink = relatedTarget == null ? void 0 : relatedTarget.closest("a");
31453
- if (!movingToLink || !editorElement.contains(movingToLink)) {
31559
+ if (!(relatedTarget == null ? void 0 : relatedTarget.closest("a")) || !editorElement.contains(relatedTarget)) {
31454
31560
  hideTimeout = window.setTimeout(() => {
31455
- if (!isOverPreview) {
31561
+ if (!isOverPreview)
31456
31562
  setHoveredLink(null);
31457
- }
31458
31563
  }, 300);
31459
31564
  }
31460
31565
  }
@@ -31464,216 +31569,241 @@ function LinkPreviewPlugin() {
31464
31569
  document.body.addEventListener("mouseover", handlePreviewMouseOver);
31465
31570
  document.body.addEventListener("mouseout", handlePreviewMouseOut);
31466
31571
  return () => {
31467
- if (showTimeout) {
31572
+ if (showTimeout)
31468
31573
  clearTimeout(showTimeout);
31469
- }
31470
- if (hideTimeout) {
31574
+ if (hideTimeout)
31471
31575
  clearTimeout(hideTimeout);
31472
- }
31473
31576
  editorElement.removeEventListener("mouseover", handleMouseOver);
31474
31577
  editorElement.removeEventListener("mouseout", handleMouseOut);
31475
31578
  document.body.removeEventListener("mouseover", handlePreviewMouseOver);
31476
31579
  document.body.removeEventListener("mouseout", handlePreviewMouseOut);
31477
31580
  };
31478
31581
  }, [editor]);
31479
- if (!hoveredLink) {
31582
+ if (!hoveredLink)
31480
31583
  return null;
31481
- }
31482
31584
  return createPortal(
31483
31585
  /* @__PURE__ */ jsx(
31484
31586
  LinkPreview,
31485
31587
  {
31486
31588
  url: hoveredLink.url,
31487
31589
  rect: hoveredLink.rect,
31590
+ apiKey,
31488
31591
  onClose: () => setHoveredLink(null)
31489
31592
  }
31490
31593
  ),
31491
31594
  document.body
31492
31595
  );
31493
31596
  }
31494
- function LinkPreview({ url, rect, onClose }) {
31597
+ const PREVIEW_WIDTH = 320;
31598
+ function LinkPreview({ url, rect, apiKey, onClose }) {
31495
31599
  const [position, setPosition] = useState$1({ top: 0, left: 0 });
31600
+ const [previewData, setPreviewData] = useState$1(null);
31601
+ const [isLoading, setIsLoading] = useState$1(true);
31602
+ const [hasError, setHasError] = useState$1(false);
31603
+ const fetchedRef = useRef(false);
31496
31604
  useEffect$1(() => {
31497
- const previewWidth = 300;
31498
- const previewHeight = 120;
31605
+ if (fetchedRef.current)
31606
+ return;
31607
+ fetchedRef.current = true;
31608
+ setIsLoading(true);
31609
+ setHasError(false);
31610
+ fetchLinkPreview({ url, apiKey }).then((data) => {
31611
+ if (data)
31612
+ setPreviewData(data);
31613
+ else
31614
+ setHasError(true);
31615
+ }).catch(() => setHasError(true)).finally(() => setIsLoading(false));
31616
+ }, [url, apiKey]);
31617
+ useEffect$1(() => {
31618
+ const previewHeight = (previewData == null ? void 0 : previewData.image) ? 280 : 160;
31499
31619
  let top = rect.top + window.scrollY - previewHeight - 10;
31500
31620
  if (rect.top - previewHeight - 10 < 0) {
31501
31621
  top = rect.bottom + window.scrollY + 10;
31502
31622
  }
31503
- let left = rect.left + window.scrollX + rect.width / 2 - previewWidth / 2;
31623
+ let left = rect.left + window.scrollX + rect.width / 2 - PREVIEW_WIDTH / 2;
31504
31624
  const viewportWidth = window.innerWidth;
31505
- if (left < 10) {
31625
+ if (left < 10)
31506
31626
  left = 10;
31507
- } else if (left + previewWidth > viewportWidth - 10) {
31508
- left = viewportWidth - previewWidth - 10;
31509
- }
31627
+ else if (left + PREVIEW_WIDTH > viewportWidth - 10)
31628
+ left = viewportWidth - PREVIEW_WIDTH - 10;
31510
31629
  setPosition({ top, left });
31511
- }, [rect]);
31630
+ }, [rect, previewData]);
31512
31631
  const getDomain = (urlString) => {
31513
31632
  try {
31514
- const urlObj = new URL(urlString);
31515
- return urlObj.hostname.replace("www.", "");
31633
+ return new URL(urlString).hostname.replace("www.", "");
31516
31634
  } catch {
31517
31635
  return urlString;
31518
31636
  }
31519
31637
  };
31520
31638
  const domain = getDomain(url);
31521
- const getProtocol = (urlString) => {
31522
- try {
31523
- const urlObj = new URL(urlString);
31524
- return urlObj.protocol.replace(":", "").toUpperCase();
31525
- } catch {
31526
- return "HTTPS";
31639
+ const TypeIcon = ({ type }) => {
31640
+ const iconProps = { style: { width: "14px", height: "14px" }, fill: "none", stroke: "currentColor", viewBox: "0 0 24 24" };
31641
+ const pathProps = { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2 };
31642
+ switch (type) {
31643
+ case "image":
31644
+ return /* @__PURE__ */ jsx("svg", { ...iconProps, children: /* @__PURE__ */ jsx("path", { ...pathProps, d: "M4 16l4.586-4.586a2 2 0 012.828 0L16 16m-2-2l1.586-1.586a2 2 0 012.828 0L20 14m-6-6h.01M6 20h12a2 2 0 002-2V6a2 2 0 00-2-2H6a2 2 0 00-2 2v12a2 2 0 002 2z" }) });
31645
+ case "video":
31646
+ return /* @__PURE__ */ jsxs("svg", { ...iconProps, children: [
31647
+ /* @__PURE__ */ jsx("path", { ...pathProps, d: "M14.752 11.168l-3.197-2.132A1 1 0 0010 9.87v4.263a1 1 0 001.555.832l3.197-2.132a1 1 0 000-1.664z" }),
31648
+ /* @__PURE__ */ jsx("path", { ...pathProps, d: "M21 12a9 9 0 11-18 0 9 9 0 0118 0z" })
31649
+ ] });
31650
+ case "pdf":
31651
+ return /* @__PURE__ */ jsx("svg", { ...iconProps, children: /* @__PURE__ */ jsx("path", { ...pathProps, d: "M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z" }) });
31652
+ default:
31653
+ return /* @__PURE__ */ jsx("svg", { ...iconProps, children: /* @__PURE__ */ jsx("path", { ...pathProps, d: "M21 12a9 9 0 01-9 9m9-9a9 9 0 00-9-9m9 9H3m9 9a9 9 0 01-9-9m9 9c1.657 0 3-4.03 3-9s-1.343-9-3-9m0 18c-1.657 0-3-4.03-3-9s1.343-9 3-9m-9 9a9 9 0 019-9" }) });
31527
31654
  }
31528
31655
  };
31529
- const protocol = getProtocol(url);
31530
- return /* @__PURE__ */ jsxs(
31531
- "div",
31532
- {
31533
- className: "link-preview-card",
31534
- style: {
31535
- position: "absolute",
31536
- top: `${position.top}px`,
31537
- left: `${position.left}px`,
31538
- zIndex: 1e4,
31539
- pointerEvents: "auto",
31540
- animation: "fadeIn 0.2s ease-out"
31541
- },
31542
- children: [
31543
- /* @__PURE__ */ jsxs(
31544
- "div",
31545
- {
31546
- style: {
31547
- width: "250px",
31548
- backgroundColor: "#2d2d2d",
31549
- borderRadius: "12px",
31550
- boxShadow: "0 10px 40px rgba(0, 0, 0, 0.3)",
31551
- overflow: "hidden",
31552
- position: "relative"
31553
- },
31554
- children: [
31555
- /* @__PURE__ */ jsx(
31556
- "button",
31557
- {
31558
- onClick: (e) => {
31559
- e.preventDefault();
31560
- e.stopPropagation();
31561
- onClose();
31562
- },
31563
- style: {
31564
- position: "absolute",
31565
- top: "8px",
31566
- right: "8px",
31567
- width: "20px",
31568
- height: "20px",
31569
- borderRadius: "4px",
31570
- backgroundColor: "#404040",
31571
- border: "none",
31572
- cursor: "pointer",
31573
- display: "flex",
31574
- alignItems: "center",
31575
- justifyContent: "center",
31576
- transition: "background-color 0.2s",
31577
- zIndex: 1
31578
- },
31579
- onMouseEnter: (e) => {
31580
- e.currentTarget.style.backgroundColor = "#525252";
31581
- },
31582
- onMouseLeave: (e) => {
31583
- e.currentTarget.style.backgroundColor = "#404040";
31584
- },
31585
- title: "Close preview",
31586
- children: /* @__PURE__ */ jsx(
31587
- "svg",
31588
- {
31589
- style: { width: "12px", height: "12px", color: "#9ca3af" },
31590
- fill: "none",
31591
- stroke: "currentColor",
31592
- viewBox: "0 0 24 24",
31593
- children: /* @__PURE__ */ jsx(
31594
- "path",
31595
- {
31596
- strokeLinecap: "round",
31597
- strokeLinejoin: "round",
31598
- strokeWidth: 2,
31599
- d: "M6 18L18 6M6 6l12 12"
31600
- }
31601
- )
31602
- }
31603
- )
31656
+ const cardStyle = {
31657
+ position: "absolute",
31658
+ top: `${position.top}px`,
31659
+ left: `${position.left}px`,
31660
+ zIndex: 1e4,
31661
+ pointerEvents: "auto",
31662
+ animation: "linkPreviewFadeIn 0.2s ease-out"
31663
+ };
31664
+ const containerStyle = {
31665
+ width: `${PREVIEW_WIDTH}px`,
31666
+ backgroundColor: "#1e1e1e",
31667
+ borderRadius: "12px",
31668
+ boxShadow: "0 10px 40px rgba(0, 0, 0, 0.4)",
31669
+ overflow: "hidden",
31670
+ position: "relative",
31671
+ border: "1px solid #333"
31672
+ };
31673
+ const closeButtonStyle = {
31674
+ position: "absolute",
31675
+ top: "8px",
31676
+ right: "8px",
31677
+ width: "24px",
31678
+ height: "24px",
31679
+ borderRadius: "6px",
31680
+ backgroundColor: "rgba(0,0,0,0.5)",
31681
+ border: "none",
31682
+ cursor: "pointer",
31683
+ display: "flex",
31684
+ alignItems: "center",
31685
+ justifyContent: "center",
31686
+ zIndex: 10
31687
+ };
31688
+ return /* @__PURE__ */ jsxs("div", { className: "link-preview-card", style: cardStyle, children: [
31689
+ /* @__PURE__ */ jsxs("div", { style: containerStyle, children: [
31690
+ /* @__PURE__ */ jsx(
31691
+ "button",
31692
+ {
31693
+ onClick: (e) => {
31694
+ e.preventDefault();
31695
+ e.stopPropagation();
31696
+ onClose();
31697
+ },
31698
+ style: closeButtonStyle,
31699
+ onMouseEnter: (e) => {
31700
+ e.currentTarget.style.backgroundColor = "rgba(0,0,0,0.7)";
31701
+ },
31702
+ onMouseLeave: (e) => {
31703
+ e.currentTarget.style.backgroundColor = "rgba(0,0,0,0.5)";
31704
+ },
31705
+ title: "Close preview",
31706
+ children: /* @__PURE__ */ jsx("svg", { style: { width: "14px", height: "14px", color: "#fff" }, fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M6 18L18 6M6 6l12 12" }) })
31707
+ }
31708
+ ),
31709
+ isLoading && /* @__PURE__ */ jsxs("div", { style: { padding: "40px", textAlign: "center" }, children: [
31710
+ /* @__PURE__ */ jsx("div", { style: {
31711
+ width: "24px",
31712
+ height: "24px",
31713
+ border: "2px solid #444",
31714
+ borderTopColor: "#fff",
31715
+ borderRadius: "50%",
31716
+ animation: "linkPreviewSpin 1s linear infinite",
31717
+ margin: "0 auto 12px"
31718
+ } }),
31719
+ /* @__PURE__ */ jsx("p", { style: { fontSize: "12px", color: "#888" }, children: "Loading preview..." })
31720
+ ] }),
31721
+ !isLoading && hasError && /* @__PURE__ */ jsxs("div", { style: { padding: "16px" }, children: [
31722
+ /* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", gap: "8px", marginBottom: "12px" }, children: [
31723
+ /* @__PURE__ */ jsx("svg", { style: { width: "16px", height: "16px", color: "#fff" }, fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14" }) }),
31724
+ /* @__PURE__ */ jsx("span", { style: { fontSize: "14px", fontWeight: "600", color: "#fff" }, children: domain })
31725
+ ] }),
31726
+ /* @__PURE__ */ jsx("div", { style: { backgroundColor: "#2a2a2a", padding: "10px", borderRadius: "6px" }, children: /* @__PURE__ */ jsx("p", { style: { fontSize: "12px", color: "#ccc", wordBreak: "break-all", lineHeight: "1.5" }, children: url }) })
31727
+ ] }),
31728
+ !isLoading && !hasError && previewData && /* @__PURE__ */ jsxs(Fragment, { children: [
31729
+ previewData.image && /* @__PURE__ */ jsx("div", { style: {
31730
+ width: "100%",
31731
+ height: "140px",
31732
+ backgroundColor: "#2a2a2a",
31733
+ backgroundImage: `url(${previewData.image})`,
31734
+ backgroundSize: "cover",
31735
+ backgroundPosition: "center"
31736
+ } }),
31737
+ /* @__PURE__ */ jsxs("div", { style: { padding: "14px" }, children: [
31738
+ /* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", gap: "8px", marginBottom: "10px" }, children: [
31739
+ previewData.favicon ? /* @__PURE__ */ jsx(
31740
+ "img",
31741
+ {
31742
+ src: previewData.favicon,
31743
+ alt: "",
31744
+ style: { width: "16px", height: "16px", borderRadius: "2px", objectFit: "contain" },
31745
+ onError: (e) => {
31746
+ e.currentTarget.style.display = "none";
31604
31747
  }
31605
- ),
31606
- /* @__PURE__ */ jsxs("div", { style: { padding: "16px 16px 12px 16px" }, children: [
31607
- /* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", gap: "8px", marginBottom: "4px" }, children: [
31608
- /* @__PURE__ */ jsx(
31609
- "svg",
31610
- {
31611
- style: { width: "16px", height: "16px", color: "#ffffff" },
31612
- fill: "none",
31613
- stroke: "currentColor",
31614
- viewBox: "0 0 24 24",
31615
- children: /* @__PURE__ */ jsx(
31616
- "path",
31617
- {
31618
- strokeLinecap: "round",
31619
- strokeLinejoin: "round",
31620
- strokeWidth: 2,
31621
- d: "M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14"
31622
- }
31623
- )
31624
- }
31625
- ),
31626
- /* @__PURE__ */ jsx("span", { style: { fontSize: "14px", fontWeight: "600", color: "#ffffff" }, children: domain })
31627
- ] }),
31628
- /* @__PURE__ */ jsx("p", { style: { fontSize: "10px", color: "#9ca3af", marginLeft: "24px" }, children: protocol })
31629
- ] }),
31630
- /* @__PURE__ */ jsxs("div", { style: { padding: "0 16px 16px 16px" }, children: [
31631
- /* @__PURE__ */ jsx("p", { style: { fontSize: "10px", fontWeight: "500", color: "#9ca3af", textTransform: "uppercase", marginBottom: "8px" }, children: "LINK URL" }),
31632
- /* @__PURE__ */ jsx("div", { style: { backgroundColor: "#1a1a1a", padding: "10px", borderRadius: "6px" }, children: /* @__PURE__ */ jsx("p", { style: { fontSize: "12px", color: "#ffffff", wordBreak: "break-all", lineHeight: "1.5" }, children: url }) })
31633
- ] }),
31634
- /* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", justifyContent: "center", gap: "8px", padding: "12px", borderTop: "1px solid #404040" }, children: [
31635
- /* @__PURE__ */ jsx(
31636
- "div",
31637
- {
31638
- style: {
31639
- width: "8px",
31640
- height: "8px",
31641
- borderRadius: "50%",
31642
- backgroundColor: "#10b981",
31643
- boxShadow: "0 0 8px rgba(16, 185, 129, 0.6)",
31644
- animation: "pulse 2s ease-in-out infinite"
31645
- }
31646
- }
31647
- ),
31648
- /* @__PURE__ */ jsx("span", { style: { fontSize: "10px", fontWeight: "500", color: "#a1a1aa" }, children: "Link Preview" })
31649
- ] })
31650
- ]
31651
- }
31652
- ),
31653
- /* @__PURE__ */ jsx("style", { children: `
31654
- @keyframes fadeIn {
31655
- from {
31656
- opacity: 0;
31657
- transform: translateY(5px);
31658
- }
31659
- to {
31660
- opacity: 1;
31661
- transform: translateY(0);
31662
- }
31748
+ }
31749
+ ) : /* @__PURE__ */ jsx("span", { style: { color: "#888" }, children: /* @__PURE__ */ jsx(TypeIcon, { type: previewData.type }) }),
31750
+ /* @__PURE__ */ jsx("span", { style: { fontSize: "12px", color: "#888", flex: 1, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }, children: previewData.siteName || domain }),
31751
+ /* @__PURE__ */ jsx("span", { style: {
31752
+ fontSize: "10px",
31753
+ color: "#666",
31754
+ padding: "2px 6px",
31755
+ backgroundColor: "#333",
31756
+ borderRadius: "4px",
31757
+ textTransform: "uppercase"
31758
+ }, children: previewData.type })
31759
+ ] }),
31760
+ previewData.title && /* @__PURE__ */ jsx("h4", { style: {
31761
+ fontSize: "14px",
31762
+ fontWeight: "600",
31763
+ color: "#fff",
31764
+ marginBottom: "6px",
31765
+ lineHeight: "1.4",
31766
+ display: "-webkit-box",
31767
+ WebkitLineClamp: 2,
31768
+ WebkitBoxOrient: "vertical",
31769
+ overflow: "hidden"
31770
+ }, children: previewData.title }),
31771
+ previewData.description && /* @__PURE__ */ jsx("p", { style: {
31772
+ fontSize: "12px",
31773
+ color: "#999",
31774
+ lineHeight: "1.5",
31775
+ display: "-webkit-box",
31776
+ WebkitLineClamp: 2,
31777
+ WebkitBoxOrient: "vertical",
31778
+ overflow: "hidden",
31779
+ marginBottom: "10px"
31780
+ }, children: previewData.description }),
31781
+ /* @__PURE__ */ jsxs("div", { style: {
31782
+ display: "flex",
31783
+ alignItems: "center",
31784
+ gap: "6px",
31785
+ padding: "8px 10px",
31786
+ backgroundColor: "#252525",
31787
+ borderRadius: "6px",
31788
+ marginTop: "8px"
31789
+ }, children: [
31790
+ /* @__PURE__ */ jsx("svg", { style: { width: "12px", height: "12px", color: "#666", flexShrink: 0 }, fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M13.828 10.172a4 4 0 00-5.656 0l-4 4a4 4 0 105.656 5.656l1.102-1.101m-.758-4.899a4 4 0 005.656 0l4-4a4 4 0 00-5.656-5.656l-1.1 1.1" }) }),
31791
+ /* @__PURE__ */ jsx("span", { style: { fontSize: "11px", color: "#888", overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }, children: url })
31792
+ ] })
31793
+ ] })
31794
+ ] })
31795
+ ] }),
31796
+ /* @__PURE__ */ jsx("style", { children: `
31797
+ @keyframes linkPreviewFadeIn {
31798
+ from { opacity: 0; transform: translateY(5px); }
31799
+ to { opacity: 1; transform: translateY(0); }
31663
31800
  }
31664
-
31665
- @keyframes pulse {
31666
- 0%, 100% {
31667
- opacity: 1;
31668
- }
31669
- 50% {
31670
- opacity: 0.6;
31671
- }
31801
+ @keyframes linkPreviewSpin {
31802
+ from { transform: rotate(0deg); }
31803
+ to { transform: rotate(360deg); }
31672
31804
  }
31673
31805
  ` })
31674
- ]
31675
- }
31676
- );
31806
+ ] });
31677
31807
  }
31678
31808
  const debounce = (fn, delay) => {
31679
31809
  let timeoutID;
@@ -32887,7 +33017,56 @@ function RichTextPastePlugin() {
32887
33017
  return true;
32888
33018
  });
32889
33019
  if (filteredNodes.length > 0) {
32890
- selection.insertNodes(filteredNodes);
33020
+ const anchorNode = selection.anchor.getNode();
33021
+ const anchorParent = anchorNode.getParent();
33022
+ const isInsideParagraphWithContent = anchorParent instanceof ElementNode && anchorParent.getType() === "paragraph" && anchorParent.getTextContent().trim().length > 0;
33023
+ if (isInsideParagraphWithContent) {
33024
+ for (const node of filteredNodes) {
33025
+ if ($isImageNode(node)) {
33026
+ const currentSelection = $getSelection();
33027
+ if ($isRangeSelection(currentSelection)) {
33028
+ const currentAnchor = currentSelection.anchor.getNode();
33029
+ const currentParent = currentAnchor.getParent();
33030
+ if (currentParent instanceof ElementNode && currentParent.getType() === "paragraph") {
33031
+ const imageParagraph = $createParagraphNode();
33032
+ imageParagraph.append(node);
33033
+ currentParent.insertAfter(imageParagraph);
33034
+ imageParagraph.selectEnd();
33035
+ } else {
33036
+ currentSelection.insertNodes([node]);
33037
+ }
33038
+ }
33039
+ } else if (node instanceof ParagraphNode) {
33040
+ const children = node.getChildren();
33041
+ const hasOnlyImage = children.length === 1 && $isImageNode(children[0]);
33042
+ if (hasOnlyImage) {
33043
+ const currentSelection = $getSelection();
33044
+ if ($isRangeSelection(currentSelection)) {
33045
+ const currentAnchor = currentSelection.anchor.getNode();
33046
+ const currentParent = currentAnchor.getParent();
33047
+ if (currentParent instanceof ElementNode && currentParent.getType() === "paragraph") {
33048
+ currentParent.insertAfter(node);
33049
+ node.selectEnd();
33050
+ } else {
33051
+ currentSelection.insertNodes([node]);
33052
+ }
33053
+ }
33054
+ } else {
33055
+ const currentSelection = $getSelection();
33056
+ if ($isRangeSelection(currentSelection)) {
33057
+ currentSelection.insertNodes([node]);
33058
+ }
33059
+ }
33060
+ } else {
33061
+ const currentSelection = $getSelection();
33062
+ if ($isRangeSelection(currentSelection)) {
33063
+ currentSelection.insertNodes([node]);
33064
+ }
33065
+ }
33066
+ }
33067
+ } else {
33068
+ selection.insertNodes(filteredNodes);
33069
+ }
32891
33070
  }
32892
33071
  }
32893
33072
  } catch (error) {
@@ -38608,4 +38787,4 @@ export {
38608
38787
  useHtmlView as u,
38609
38788
  verifyApiKey as v
38610
38789
  };
38611
- //# sourceMappingURL=index-a2107b7c.js.map
38790
+ //# sourceMappingURL=index-d1d21414.js.map