ct-rich-text-editor 1.3.19 → 1.3.20

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, $setSelection, isHTMLElement as isHTMLElement$1, TextNode, $getRoot, $createTextNode, $getNodeByKey, $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, $createRangeSelection, KEY_ARROW_DOWN_COMMAND, KEY_ARROW_UP_COMMAND, KEY_ESCAPE_COMMAND, KEY_TAB_COMMAND, KEY_ENTER_COMMAND, $createNodeSelection, $isNodeSelection, getDOMSelection, CLICK_COMMAND, COMMAND_PRIORITY_HIGH, $isLineBreakNode, PASTE_COMMAND, ParagraphNode, $createLineBreakNode, isDOMNode } from "lexical";
27
+ import { createCommand, DecoratorNode, createEditor, $applyNodeReplacement, $insertNodes, $isRootOrShadowRoot, $createParagraphNode, COMMAND_PRIORITY_EDITOR, COMMAND_PRIORITY_LOW, $getSelection, $isRangeSelection, $getNearestNodeFromDOMNode, $setSelection, 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, $createRangeSelection, KEY_ARROW_DOWN_COMMAND, KEY_ARROW_UP_COMMAND, KEY_ESCAPE_COMMAND, KEY_TAB_COMMAND, KEY_ENTER_COMMAND, $createNodeSelection, $isNodeSelection, getDOMSelection, CLICK_COMMAND, COMMAND_PRIORITY_HIGH, $isLineBreakNode, 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";
@@ -40,15 +40,7 @@ import InsertDriveFileIcon from "@mui/icons-material/InsertDriveFile";
40
40
  import PictureAsPdfIcon from "@mui/icons-material/PictureAsPdf";
41
41
  import { $isDecoratorBlockNode } from "@lexical/react/LexicalDecoratorBlockNode";
42
42
  import EmojiPicker from "emoji-picker-react";
43
- import CodeIcon$1 from "@mui/icons-material/Code";
44
- import ContentCopyIcon from "@mui/icons-material/ContentCopy";
45
- import CropOriginalIcon from "@mui/icons-material/CropOriginal";
46
- import DeleteIcon from "@mui/icons-material/Delete";
47
- import FormatAlignCenterIcon from "@mui/icons-material/FormatAlignCenter";
48
- import FormatAlignLeftIcon from "@mui/icons-material/FormatAlignLeft";
49
- import FormatAlignRightIcon from "@mui/icons-material/FormatAlignRight";
50
- import LinkIcon$1 from "@mui/icons-material/Link";
51
- import OpenInNewIcon from "@mui/icons-material/OpenInNew";
43
+ import { Link as Link$1, CropOriginal, Code as Code$1, FormatAlignLeft, FormatAlignCenter, FormatAlignRight, OpenInNew, Delete, ContentCopy } from "@mui/icons-material";
52
44
  import { LinkPlugin as LinkPlugin$1 } from "@lexical/react/LexicalLinkPlugin";
53
45
  import { useBasicTypeaheadTriggerMatch, LexicalTypeaheadMenuPlugin, MenuOption } from "@lexical/react/LexicalTypeaheadMenuPlugin";
54
46
  import { useLexicalEditable } from "@lexical/react/useLexicalEditable";
@@ -1479,7 +1471,7 @@ const AiTextTransform = async ({ content, apiKey }) => {
1479
1471
  const AI_ACTION_COMMAND = createCommand(
1480
1472
  "AI_ACTION_COMMAND"
1481
1473
  );
1482
- const ImageView = React__default.lazy(() => import("./index-913b3634.js"));
1474
+ const ImageView = React__default.lazy(() => import("./index-d1931d92.js"));
1483
1475
  function isGoogleDocCheckboxImg(img) {
1484
1476
  return img.parentElement != null && img.parentElement.tagName === "LI" && img.previousSibling === null && img.getAttribute("aria-roledescription") === "checkbox";
1485
1477
  }
@@ -15345,7 +15337,7 @@ const EmbedComponent = ({ url, displayType, alignment, nodeKey }) => {
15345
15337
  }
15346
15338
  );
15347
15339
  };
15348
- const FileComponent = React$1.lazy(() => import("./index-afa4eda8.js"));
15340
+ const FileComponent = React$1.lazy(() => import("./index-9505418d.js"));
15349
15341
  function convertFileElement(domNode) {
15350
15342
  if (domNode instanceof HTMLDivElement) {
15351
15343
  const dataUrl = domNode.getAttribute("data-lexical-file-src");
@@ -20368,10 +20360,10 @@ const PDF_CONFIG = {
20368
20360
  };
20369
20361
  const loadHtml2Pdf = async () => {
20370
20362
  try {
20371
- const mod = await import("./html2pdf.bundle.min-f1b4a78e.js").then((n) => n.h);
20363
+ const mod = await import("./html2pdf.bundle.min-d830ece3.js").then((n) => n.h);
20372
20364
  return (mod == null ? void 0 : mod.default) || mod;
20373
20365
  } catch {
20374
- const mod2 = await import("./html2pdf.bundle-a30dde70.js").then((n) => n.h);
20366
+ const mod2 = await import("./html2pdf.bundle-dea9d834.js").then((n) => n.h);
20375
20367
  return (mod2 == null ? void 0 : mod2.default) || mod2;
20376
20368
  }
20377
20369
  };
@@ -23614,6 +23606,8 @@ const FontFamilyMenu = ({
23614
23606
  }) => {
23615
23607
  const [selectedFont, setSelectedFont] = useState$1("Arial");
23616
23608
  const [detectedFonts, setDetectedFonts] = useState$1(/* @__PURE__ */ new Set());
23609
+ const pendingFontRef = React__default.useRef(null);
23610
+ const userJustSetFontRef = React__default.useRef(false);
23617
23611
  const allFonts = useMemo(() => {
23618
23612
  const fontSet = new Set(fonts);
23619
23613
  detectedFonts.forEach((font) => fontSet.add(font));
@@ -23630,22 +23624,73 @@ const FontFamilyMenu = ({
23630
23624
  "Arial"
23631
23625
  );
23632
23626
  const cleanedFont = fontFamily.replace(/^["']|["']$/g, "").trim();
23633
- setSelectedFont(cleanedFont);
23634
- if (cleanedFont && cleanedFont !== "Arial" && !fonts.includes(cleanedFont)) {
23635
- setDetectedFonts((prev) => {
23636
- if (prev.has(cleanedFont))
23637
- return prev;
23638
- const newSet = new Set(prev);
23639
- newSet.add(cleanedFont);
23640
- return newSet;
23641
- });
23627
+ if (userJustSetFontRef.current) {
23628
+ userJustSetFontRef.current = false;
23629
+ return;
23630
+ }
23631
+ if (!selection.isCollapsed() && pendingFontRef.current !== null) {
23632
+ pendingFontRef.current = null;
23633
+ }
23634
+ if (pendingFontRef.current !== null && cleanedFont !== pendingFontRef.current && cleanedFont !== "Arial") {
23635
+ pendingFontRef.current = null;
23636
+ }
23637
+ if (pendingFontRef.current === null) {
23638
+ setSelectedFont(cleanedFont);
23639
+ if (cleanedFont && cleanedFont !== "Arial" && !fonts.includes(cleanedFont)) {
23640
+ setDetectedFonts((prev) => {
23641
+ if (prev.has(cleanedFont))
23642
+ return prev;
23643
+ const newSet = new Set(prev);
23644
+ newSet.add(cleanedFont);
23645
+ return newSet;
23646
+ });
23647
+ }
23642
23648
  }
23643
23649
  }
23644
23650
  });
23645
23651
  });
23646
23652
  }, [activeEditor, fonts]);
23653
+ useEffect$1(() => {
23654
+ return activeEditor.registerCommand(
23655
+ KEY_DOWN_COMMAND,
23656
+ (event) => {
23657
+ if (pendingFontRef.current !== null && event.key.length === 1 && !event.ctrlKey && !event.metaKey) {
23658
+ const pendingFont = pendingFontRef.current;
23659
+ const selection = $getSelection();
23660
+ if ($isRangeSelection(selection) && selection.isCollapsed()) {
23661
+ $patchStyleText(selection, { "font-family": pendingFont });
23662
+ }
23663
+ }
23664
+ return false;
23665
+ },
23666
+ COMMAND_PRIORITY_CRITICAL
23667
+ );
23668
+ }, [activeEditor]);
23669
+ useEffect$1(() => {
23670
+ const rootElement = activeEditor.getRootElement();
23671
+ if (!rootElement)
23672
+ return;
23673
+ const handleFocus = () => {
23674
+ if (pendingFontRef.current !== null) {
23675
+ const pendingFont = pendingFontRef.current;
23676
+ activeEditor.update(() => {
23677
+ const selection = $getSelection();
23678
+ if ($isRangeSelection(selection) && selection.isCollapsed()) {
23679
+ userJustSetFontRef.current = true;
23680
+ $patchStyleText(selection, { "font-family": pendingFont });
23681
+ }
23682
+ });
23683
+ }
23684
+ };
23685
+ rootElement.addEventListener("focus", handleFocus);
23686
+ return () => {
23687
+ rootElement.removeEventListener("focus", handleFocus);
23688
+ };
23689
+ }, [activeEditor]);
23647
23690
  const applyFontFamily = useCallback(
23648
23691
  (fontFamily) => {
23692
+ pendingFontRef.current = fontFamily;
23693
+ userJustSetFontRef.current = true;
23649
23694
  activeEditor.update(() => {
23650
23695
  const selection = $getSelection();
23651
23696
  if ($isRangeSelection(selection)) {
@@ -23659,10 +23704,20 @@ const FontFamilyMenu = ({
23659
23704
  setSelectedFont(value);
23660
23705
  applyFontFamily(value);
23661
23706
  };
23662
- return /* @__PURE__ */ jsx(Fragment, { children: /* @__PURE__ */ jsxs(Select, { value: selectedFont, onValueChange: handleFontChange, children: [
23663
- /* @__PURE__ */ jsx(SelectTrigger, { className: "!cteditor-h-7 md:!cteditor-bg-secondary !cteditor-bg-foreground/5 cteditor-text-foreground md:!cteditor-w-[120px] cteditor-text-xs max-md:cteditor-w-full", children: /* @__PURE__ */ jsx(SelectValue, { placeholder: "Select font" }) }),
23664
- /* @__PURE__ */ jsx(SelectContent, { children: allFonts.map((font) => /* @__PURE__ */ jsx(SelectItem, { value: font, style: { fontFamily: font }, children: font }, font)) })
23665
- ] }) });
23707
+ const handleMouseDown = (e) => {
23708
+ e.preventDefault();
23709
+ };
23710
+ return /* @__PURE__ */ jsxs(Select, { value: selectedFont, onValueChange: handleFontChange, children: [
23711
+ /* @__PURE__ */ jsx(
23712
+ SelectTrigger,
23713
+ {
23714
+ className: "!cteditor-h-7 md:!cteditor-bg-secondary !cteditor-bg-foreground/5 cteditor-text-foreground md:!cteditor-w-[120px] cteditor-text-xs max-md:cteditor-w-full",
23715
+ onMouseDown: handleMouseDown,
23716
+ children: /* @__PURE__ */ jsx(SelectValue, { placeholder: "Select font" })
23717
+ }
23718
+ ),
23719
+ /* @__PURE__ */ jsx(SelectContent, { onMouseDown: handleMouseDown, children: allFonts.map((font) => /* @__PURE__ */ jsx(SelectItem, { value: font, style: { fontFamily: font }, onMouseDown: handleMouseDown, children: font }, font)) })
23720
+ ] });
23666
23721
  };
23667
23722
  const MIN_FONT_SIZE = 8;
23668
23723
  const MAX_FONT_SIZE = 72;
@@ -23673,6 +23728,7 @@ const FontSizeControl = () => {
23673
23728
  const [fontSize, setFontSize] = useState$1(DEFAULT_FONT_SIZE);
23674
23729
  const [inputValue, setInputValue] = useState$1(DEFAULT_FONT_SIZE.toString());
23675
23730
  const pendingFontSizeRef = React__default.useRef(null);
23731
+ const userJustSetSizeRef = React__default.useRef(false);
23676
23732
  useEffect$1(() => {
23677
23733
  return editor.registerUpdateListener(({ editorState }) => {
23678
23734
  editorState.read(() => {
@@ -23684,7 +23740,14 @@ const FontSizeControl = () => {
23684
23740
  `${DEFAULT_FONT_SIZE}px`
23685
23741
  );
23686
23742
  const size2 = parseInt(fontSizeStr, 10) || DEFAULT_FONT_SIZE;
23687
- if (pendingFontSizeRef.current !== null && size2 === pendingFontSizeRef.current) {
23743
+ if (userJustSetSizeRef.current) {
23744
+ userJustSetSizeRef.current = false;
23745
+ return;
23746
+ }
23747
+ if (!selection.isCollapsed() && pendingFontSizeRef.current !== null) {
23748
+ pendingFontSizeRef.current = null;
23749
+ }
23750
+ if (pendingFontSizeRef.current !== null && size2 !== pendingFontSizeRef.current && size2 !== DEFAULT_FONT_SIZE) {
23688
23751
  pendingFontSizeRef.current = null;
23689
23752
  }
23690
23753
  if (pendingFontSizeRef.current === null) {
@@ -23695,6 +23758,22 @@ const FontSizeControl = () => {
23695
23758
  });
23696
23759
  });
23697
23760
  }, [editor]);
23761
+ useEffect$1(() => {
23762
+ return editor.registerCommand(
23763
+ KEY_DOWN_COMMAND,
23764
+ (event) => {
23765
+ if (pendingFontSizeRef.current !== null && event.key.length === 1 && !event.ctrlKey && !event.metaKey) {
23766
+ const pendingSize = pendingFontSizeRef.current;
23767
+ const selection = $getSelection();
23768
+ if ($isRangeSelection(selection) && selection.isCollapsed()) {
23769
+ $patchStyleText(selection, { "font-size": `${pendingSize}px` });
23770
+ }
23771
+ }
23772
+ return false;
23773
+ },
23774
+ COMMAND_PRIORITY_CRITICAL
23775
+ );
23776
+ }, [editor]);
23698
23777
  useEffect$1(() => {
23699
23778
  const rootElement = editor.getRootElement();
23700
23779
  if (!rootElement)
@@ -23704,7 +23783,8 @@ const FontSizeControl = () => {
23704
23783
  const pendingSize = pendingFontSizeRef.current;
23705
23784
  editor.update(() => {
23706
23785
  const selection = $getSelection();
23707
- if ($isRangeSelection(selection)) {
23786
+ if ($isRangeSelection(selection) && selection.isCollapsed()) {
23787
+ userJustSetSizeRef.current = true;
23708
23788
  $patchStyleText(selection, { "font-size": `${pendingSize}px` });
23709
23789
  }
23710
23790
  });
@@ -23718,6 +23798,7 @@ const FontSizeControl = () => {
23718
23798
  const applyFontSize = useCallback(
23719
23799
  (size2) => {
23720
23800
  pendingFontSizeRef.current = size2;
23801
+ userJustSetSizeRef.current = true;
23721
23802
  editor.update(() => {
23722
23803
  const selection = $getSelection();
23723
23804
  if ($isRangeSelection(selection)) {
@@ -23763,6 +23844,9 @@ const FontSizeControl = () => {
23763
23844
  setInputValue(newSize.toString());
23764
23845
  applyFontSize(newSize);
23765
23846
  };
23847
+ const handleMouseDown = (e) => {
23848
+ e.preventDefault();
23849
+ };
23766
23850
  return /* @__PURE__ */ jsxs("div", { className: "cteditor-flex cteditor-items-center cteditor-gap-1", children: [
23767
23851
  /* @__PURE__ */ jsx(TooltipProvider, { delayDuration: 200, children: /* @__PURE__ */ jsxs(Tooltip, { children: [
23768
23852
  /* @__PURE__ */ jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx(
@@ -23771,6 +23855,7 @@ const FontSizeControl = () => {
23771
23855
  variant: "ghost",
23772
23856
  size: "icon-sm",
23773
23857
  onClick: decreaseFontSize,
23858
+ onMouseDown: handleMouseDown,
23774
23859
  className: "cteditor-text-foreground/50",
23775
23860
  children: /* @__PURE__ */ jsx(Minus, { className: "!cteditor-size-[18px]" })
23776
23861
  }
@@ -23794,6 +23879,7 @@ const FontSizeControl = () => {
23794
23879
  variant: "ghost",
23795
23880
  size: "icon-sm",
23796
23881
  onClick: increaseFontSize,
23882
+ onMouseDown: handleMouseDown,
23797
23883
  className: "cteditor-text-foreground/50",
23798
23884
  children: /* @__PURE__ */ jsx(Plus, { className: "!cteditor-size-[18px]" })
23799
23885
  }
@@ -29172,7 +29258,7 @@ function FloatingEmbedMenu({
29172
29258
  handleDisplayTypeChange("url");
29173
29259
  },
29174
29260
  title: "URL",
29175
- children: /* @__PURE__ */ jsx(LinkIcon$1, { fontSize: "small" })
29261
+ children: /* @__PURE__ */ jsx(Link$1, { fontSize: "small" })
29176
29262
  }
29177
29263
  ),
29178
29264
  /* @__PURE__ */ jsx(
@@ -29184,7 +29270,7 @@ function FloatingEmbedMenu({
29184
29270
  handleDisplayTypeChange("card");
29185
29271
  },
29186
29272
  title: "Card",
29187
- children: /* @__PURE__ */ jsx(CropOriginalIcon, { fontSize: "small" })
29273
+ children: /* @__PURE__ */ jsx(CropOriginal, { fontSize: "small" })
29188
29274
  }
29189
29275
  ),
29190
29276
  /* @__PURE__ */ jsx(
@@ -29196,7 +29282,7 @@ function FloatingEmbedMenu({
29196
29282
  handleDisplayTypeChange("embed");
29197
29283
  },
29198
29284
  title: "Embedded",
29199
- children: /* @__PURE__ */ jsx(CodeIcon$1, { fontSize: "small" })
29285
+ children: /* @__PURE__ */ jsx(Code$1, { fontSize: "small" })
29200
29286
  }
29201
29287
  )
29202
29288
  ] }) }),
@@ -29211,7 +29297,7 @@ function FloatingEmbedMenu({
29211
29297
  handleAlignmentChange("left");
29212
29298
  },
29213
29299
  title: "Left",
29214
- children: /* @__PURE__ */ jsx(FormatAlignLeftIcon, { fontSize: "small" })
29300
+ children: /* @__PURE__ */ jsx(FormatAlignLeft, { fontSize: "small" })
29215
29301
  }
29216
29302
  ),
29217
29303
  /* @__PURE__ */ jsx(
@@ -29223,7 +29309,7 @@ function FloatingEmbedMenu({
29223
29309
  handleAlignmentChange("center");
29224
29310
  },
29225
29311
  title: "Center",
29226
- children: /* @__PURE__ */ jsx(FormatAlignCenterIcon, { fontSize: "small" })
29312
+ children: /* @__PURE__ */ jsx(FormatAlignCenter, { fontSize: "small" })
29227
29313
  }
29228
29314
  ),
29229
29315
  /* @__PURE__ */ jsx(
@@ -29235,7 +29321,7 @@ function FloatingEmbedMenu({
29235
29321
  handleAlignmentChange("right");
29236
29322
  },
29237
29323
  title: "Right",
29238
- children: /* @__PURE__ */ jsx(FormatAlignRightIcon, { fontSize: "small" })
29324
+ children: /* @__PURE__ */ jsx(FormatAlignRight, { fontSize: "small" })
29239
29325
  }
29240
29326
  )
29241
29327
  ] }) }),
@@ -29247,7 +29333,7 @@ function FloatingEmbedMenu({
29247
29333
  className: "embed-menu-button",
29248
29334
  onClick: handleOpenInNewTab,
29249
29335
  title: "Open in new tab",
29250
- children: /* @__PURE__ */ jsx(OpenInNewIcon, { fontSize: "small" })
29336
+ children: /* @__PURE__ */ jsx(OpenInNew, { fontSize: "small" })
29251
29337
  }
29252
29338
  ),
29253
29339
  /* @__PURE__ */ jsx(
@@ -29256,7 +29342,7 @@ function FloatingEmbedMenu({
29256
29342
  className: "embed-menu-button",
29257
29343
  onClick: handleRemoveEmbed,
29258
29344
  title: "Remove",
29259
- children: /* @__PURE__ */ jsx(DeleteIcon, { fontSize: "small" })
29345
+ children: /* @__PURE__ */ jsx(Delete, { fontSize: "small" })
29260
29346
  }
29261
29347
  ),
29262
29348
  /* @__PURE__ */ jsx(
@@ -29265,7 +29351,7 @@ function FloatingEmbedMenu({
29265
29351
  className: "embed-menu-button",
29266
29352
  onClick: handleCopyUrl,
29267
29353
  title: "Copy",
29268
- children: /* @__PURE__ */ jsx(ContentCopyIcon, { fontSize: "small" })
29354
+ children: /* @__PURE__ */ jsx(ContentCopy, { fontSize: "small" })
29269
29355
  }
29270
29356
  )
29271
29357
  ] }) })
@@ -31684,6 +31770,94 @@ const IS_CODE = 16;
31684
31770
  const IS_SUBSCRIPT = 32;
31685
31771
  const IS_SUPERSCRIPT = 64;
31686
31772
  const IS_HIGHLIGHT = 128;
31773
+ function parseColor(color) {
31774
+ if (!color)
31775
+ return null;
31776
+ color = color.trim().toLowerCase();
31777
+ if (color.startsWith("#")) {
31778
+ let hex = color.slice(1);
31779
+ if (hex.length === 3) {
31780
+ hex = hex[0] + hex[0] + hex[1] + hex[1] + hex[2] + hex[2];
31781
+ }
31782
+ if (hex.length === 6) {
31783
+ return {
31784
+ r: parseInt(hex.slice(0, 2), 16),
31785
+ g: parseInt(hex.slice(2, 4), 16),
31786
+ b: parseInt(hex.slice(4, 6), 16)
31787
+ };
31788
+ }
31789
+ }
31790
+ const rgbMatch = color.match(/rgba?\s*\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)/);
31791
+ if (rgbMatch) {
31792
+ return {
31793
+ r: parseInt(rgbMatch[1]),
31794
+ g: parseInt(rgbMatch[2]),
31795
+ b: parseInt(rgbMatch[3])
31796
+ };
31797
+ }
31798
+ const namedColors = {
31799
+ white: { r: 255, g: 255, b: 255 },
31800
+ black: { r: 0, g: 0, b: 0 },
31801
+ red: { r: 255, g: 0, b: 0 },
31802
+ green: { r: 0, g: 128, b: 0 },
31803
+ blue: { r: 0, g: 0, b: 255 },
31804
+ yellow: { r: 255, g: 255, b: 0 },
31805
+ transparent: { r: 0, g: 0, b: 0 }
31806
+ // Will be handled separately
31807
+ };
31808
+ return namedColors[color] || null;
31809
+ }
31810
+ function getLuminance(r2, g2, b2) {
31811
+ const sR = r2 / 255;
31812
+ const sG = g2 / 255;
31813
+ const sB = b2 / 255;
31814
+ const R = sR <= 0.03928 ? sR / 12.92 : Math.pow((sR + 0.055) / 1.055, 2.4);
31815
+ const G = sG <= 0.03928 ? sG / 12.92 : Math.pow((sG + 0.055) / 1.055, 2.4);
31816
+ const B = sB <= 0.03928 ? sB / 12.92 : Math.pow((sB + 0.055) / 1.055, 2.4);
31817
+ return 0.2126 * R + 0.7152 * G + 0.0722 * B;
31818
+ }
31819
+ function isLightColor(color) {
31820
+ const parsed = parseColor(color);
31821
+ if (!parsed)
31822
+ return null;
31823
+ return getLuminance(parsed.r, parsed.g, parsed.b) > 0.5;
31824
+ }
31825
+ function getEditorBackgroundColor(editor) {
31826
+ const rootElement = editor.getRootElement();
31827
+ if (!rootElement)
31828
+ return null;
31829
+ try {
31830
+ const computedStyle = window.getComputedStyle(rootElement);
31831
+ const bgColor = computedStyle.backgroundColor;
31832
+ if (bgColor === "transparent" || bgColor === "rgba(0, 0, 0, 0)") {
31833
+ let parent = rootElement.parentElement;
31834
+ while (parent) {
31835
+ const parentBg = window.getComputedStyle(parent).backgroundColor;
31836
+ if (parentBg && parentBg !== "transparent" && parentBg !== "rgba(0, 0, 0, 0)") {
31837
+ return parentBg;
31838
+ }
31839
+ parent = parent.parentElement;
31840
+ }
31841
+ return "rgb(255, 255, 255)";
31842
+ }
31843
+ return bgColor;
31844
+ } catch {
31845
+ return null;
31846
+ }
31847
+ }
31848
+ function isEditorDarkMode(editor) {
31849
+ const bgColor = getEditorBackgroundColor(editor);
31850
+ if (!bgColor)
31851
+ return false;
31852
+ const isLight = isLightColor(bgColor);
31853
+ return isLight === false;
31854
+ }
31855
+ function adjustColorsForTheme(styleInfo) {
31856
+ const adjusted = { ...styleInfo };
31857
+ adjusted.backgroundColor = "";
31858
+ adjusted.color = "";
31859
+ return adjusted;
31860
+ }
31687
31861
  function detectCKEditorSource(html) {
31688
31862
  return html.includes('class="image"') || // CKEditor's figure class for images
31689
31863
  html.includes('class="image ') || html.includes("image-style-") || // CKEditor's image alignment classes
@@ -31875,7 +32049,8 @@ function buildStyleString(info) {
31875
32049
  }
31876
32050
  function createStyledTextNode(text, parentElement) {
31877
32051
  const textNode = $createTextNode(text);
31878
- const styleInfo = getStyleInfoFromElement(parentElement);
32052
+ let styleInfo = getStyleInfoFromElement(parentElement);
32053
+ styleInfo = adjustColorsForTheme(styleInfo);
31879
32054
  if (styleInfo.format) {
31880
32055
  textNode.setFormat(styleInfo.format);
31881
32056
  }
@@ -32149,7 +32324,8 @@ function processChildrenWithStyle(element, parentNode, defaultStyles) {
32149
32324
  if (hasNonWhitespace || isSignificantWhitespace) {
32150
32325
  const normalizedText = text.replace(/\s+/g, " ");
32151
32326
  const textNode = $createTextNode(normalizedText);
32152
- const styleInfo = getStyleInfoFromElement(element);
32327
+ let styleInfo = getStyleInfoFromElement(element);
32328
+ styleInfo = adjustColorsForTheme(styleInfo);
32153
32329
  if (styleInfo.format) {
32154
32330
  textNode.setFormat(styleInfo.format);
32155
32331
  }
@@ -32263,6 +32439,11 @@ function convertHTMLToNodesWithStyles(html, editor) {
32263
32439
  currentPasteContext = {
32264
32440
  isCKEditor
32265
32441
  };
32442
+ const editorBgColor = getEditorBackgroundColor(editor);
32443
+ ({
32444
+ editorIsDark: isEditorDarkMode(editor),
32445
+ editorBgColor
32446
+ });
32266
32447
  const { container, cleanup } = createStyledDocument(html);
32267
32448
  try {
32268
32449
  const customNodes = processNode(container, null);
@@ -36479,10 +36660,38 @@ const WordCountPlugin = () => {
36479
36660
  }
36480
36661
  );
36481
36662
  };
36663
+ function getEditorColors(rootElement) {
36664
+ try {
36665
+ const computedStyle = window.getComputedStyle(rootElement);
36666
+ let bgColor = computedStyle.backgroundColor;
36667
+ let textColor = computedStyle.color;
36668
+ if (bgColor === "transparent" || bgColor === "rgba(0, 0, 0, 0)") {
36669
+ let parent = rootElement.parentElement;
36670
+ while (parent) {
36671
+ const parentBg = window.getComputedStyle(parent).backgroundColor;
36672
+ if (parentBg && parentBg !== "transparent" && parentBg !== "rgba(0, 0, 0, 0)") {
36673
+ bgColor = parentBg;
36674
+ break;
36675
+ }
36676
+ parent = parent.parentElement;
36677
+ }
36678
+ if (bgColor === "transparent" || bgColor === "rgba(0, 0, 0, 0)") {
36679
+ bgColor = "rgb(255, 255, 255)";
36680
+ }
36681
+ }
36682
+ if (!textColor || textColor === "rgba(0, 0, 0, 0)") {
36683
+ textColor = "rgb(0, 0, 0)";
36684
+ }
36685
+ return { bgColor, textColor };
36686
+ } catch {
36687
+ return { bgColor: "rgb(255, 255, 255)", textColor: "rgb(0, 0, 0)" };
36688
+ }
36689
+ }
36482
36690
  function exportEditorWithInlineStyle(editor) {
36483
36691
  const rootElement = editor.getRootElement();
36484
36692
  if (!rootElement)
36485
36693
  return "";
36694
+ const { bgColor, textColor } = getEditorColors(rootElement);
36486
36695
  const tableStyleMap = /* @__PURE__ */ new Map();
36487
36696
  const liveTables = rootElement.querySelectorAll("table");
36488
36697
  liveTables.forEach((table, index2) => {
@@ -36493,9 +36702,9 @@ function exportEditorWithInlineStyle(editor) {
36493
36702
  const headerBgColors = [];
36494
36703
  headerCells.forEach((th) => {
36495
36704
  const computed = window.getComputedStyle(th);
36496
- const bgColor = computed.backgroundColor;
36497
- if (bgColor && bgColor !== "rgba(0, 0, 0, 0)") {
36498
- headerBgColors.push(bgColor);
36705
+ const bgColor2 = computed.backgroundColor;
36706
+ if (bgColor2 && bgColor2 !== "rgba(0, 0, 0, 0)") {
36707
+ headerBgColors.push(bgColor2);
36499
36708
  } else {
36500
36709
  headerBgColors.push("");
36501
36710
  }
@@ -36530,7 +36739,7 @@ function exportEditorWithInlineStyle(editor) {
36530
36739
  editor.getEditorState().read(() => {
36531
36740
  htmlString = $generateHtmlFromNodes(editor, null);
36532
36741
  });
36533
- return processHtmlForExport(htmlString, tableStyleMap);
36742
+ return processHtmlForExport(htmlString, tableStyleMap, bgColor, textColor);
36534
36743
  }
36535
36744
  function normalizeColorForComparison(color) {
36536
36745
  if (!color)
@@ -36580,7 +36789,7 @@ function detectTableColorsFromVariables(table) {
36580
36789
  }
36581
36790
  return null;
36582
36791
  }
36583
- function processHtmlForExport(html, tableStyleMap) {
36792
+ function processHtmlForExport(html, tableStyleMap, bgColor, textColor) {
36584
36793
  const parser = new DOMParser();
36585
36794
  const doc = parser.parseFromString(html, "text/html");
36586
36795
  const tables = doc.querySelectorAll("table");
@@ -36590,14 +36799,14 @@ function processHtmlForExport(html, tableStyleMap) {
36590
36799
  return;
36591
36800
  const headerCells = table.querySelectorAll("th");
36592
36801
  headerCells.forEach((th, cellIndex) => {
36593
- const bgColor = styleInfo.headerBgColors[cellIndex];
36594
- if (bgColor) {
36802
+ const bgColor2 = styleInfo.headerBgColors[cellIndex];
36803
+ if (bgColor2) {
36595
36804
  const el = th;
36596
- el.style.setProperty("background-color", bgColor, "important");
36597
- const textColor = getContrastColor(bgColor);
36598
- el.style.color = textColor;
36805
+ el.style.setProperty("background-color", bgColor2, "important");
36806
+ const textColor2 = getContrastColor(bgColor2);
36807
+ el.style.color = textColor2;
36599
36808
  el.querySelectorAll("*").forEach((nested) => {
36600
- nested.style.color = textColor;
36809
+ nested.style.color = textColor2;
36601
36810
  });
36602
36811
  }
36603
36812
  });
@@ -36612,18 +36821,18 @@ function processHtmlForExport(html, tableStyleMap) {
36612
36821
  const el = cell;
36613
36822
  const explicitColor = styleInfo.explicitCellColors.get(`${rowIndex}-${cellIndex}`);
36614
36823
  if (explicitColor) {
36615
- const textColor = getContrastColor(explicitColor);
36824
+ const textColor2 = getContrastColor(explicitColor);
36616
36825
  el.style.setProperty("background-color", explicitColor, "important");
36617
- el.style.color = textColor;
36826
+ el.style.color = textColor2;
36618
36827
  el.querySelectorAll("*").forEach((nested) => {
36619
- nested.style.color = textColor;
36828
+ nested.style.color = textColor2;
36620
36829
  });
36621
36830
  } else if (stripingColor) {
36622
- const textColor = getContrastColor(stripingColor);
36831
+ const textColor2 = getContrastColor(stripingColor);
36623
36832
  el.style.setProperty("background-color", stripingColor, "important");
36624
- el.style.color = textColor;
36833
+ el.style.color = textColor2;
36625
36834
  el.querySelectorAll("*").forEach((nested) => {
36626
- nested.style.color = textColor;
36835
+ nested.style.color = textColor2;
36627
36836
  });
36628
36837
  }
36629
36838
  });
@@ -36632,7 +36841,15 @@ function processHtmlForExport(html, tableStyleMap) {
36632
36841
  cleanupHeaderCellStructure(doc.body);
36633
36842
  applyGenericSafeStyles(doc.body);
36634
36843
  cleanupClasses(doc.body);
36635
- return doc.body.innerHTML;
36844
+ const wrapper = doc.createElement("div");
36845
+ wrapper.style.backgroundColor = bgColor;
36846
+ wrapper.style.color = textColor;
36847
+ wrapper.style.padding = "1em";
36848
+ wrapper.style.minHeight = "100%";
36849
+ while (doc.body.firstChild) {
36850
+ wrapper.appendChild(doc.body.firstChild);
36851
+ }
36852
+ return wrapper.outerHTML;
36636
36853
  }
36637
36854
  function cleanupHeaderCellStructure(container) {
36638
36855
  const allHeaderCells = container.querySelectorAll("th");
@@ -36660,6 +36877,19 @@ function applyGenericSafeStyles(container) {
36660
36877
  el.style.cssText += "; " + styles;
36661
36878
  });
36662
36879
  };
36880
+ const addStyleIfNotSetOnElementOrChildren = (selector, property, value) => {
36881
+ container.querySelectorAll(selector).forEach((el) => {
36882
+ const currentValue = el.style.getPropertyValue(property);
36883
+ if (currentValue && currentValue !== "initial" && currentValue !== "inherit") {
36884
+ return;
36885
+ }
36886
+ const childrenWithProperty = el.querySelectorAll(`[style*="${property}"]`);
36887
+ if (childrenWithProperty.length > 0) {
36888
+ return;
36889
+ }
36890
+ el.style.setProperty(property, value);
36891
+ });
36892
+ };
36663
36893
  const addStyleIfNotSet = (selector, property, value) => {
36664
36894
  container.querySelectorAll(selector).forEach((el) => {
36665
36895
  const currentValue = el.style.getPropertyValue(property);
@@ -36669,10 +36899,11 @@ function applyGenericSafeStyles(container) {
36669
36899
  });
36670
36900
  };
36671
36901
  const defaultFontFamily = "Arial, sans-serif";
36672
- const selectors = "table, p, span, li, td, th, div, h1, h2, h3, h4, h5, h6";
36673
- addStyle(selectors, "line-height: 1.5;");
36674
- addStyleIfNotSet(selectors, "font-family", defaultFontFamily);
36675
- addStyleIfNotSet("table, p, span, li, td, th, div", "font-size", "16px");
36902
+ const blockSelectors = "table, p, li, td, th, div, h1, h2, h3, h4, h5, h6";
36903
+ const allSelectors = "table, p, span, li, td, th, div, h1, h2, h3, h4, h5, h6";
36904
+ addStyle(allSelectors, "line-height: 1.5;");
36905
+ addStyleIfNotSetOnElementOrChildren(blockSelectors, "font-family", defaultFontFamily);
36906
+ addStyleIfNotSet("table, p, li, td, th, div", "font-size", "16px");
36676
36907
  addStyle("p", "margin: 0 0 1em 0;");
36677
36908
  addStyle("th p, td p", "margin: 0; padding: 0;");
36678
36909
  addStyle(
@@ -36911,7 +37142,24 @@ function preprocessInitialContent(html) {
36911
37142
  return html;
36912
37143
  }
36913
37144
  const parser = new DOMParser();
36914
- const doc = parser.parseFromString(html, "text/html");
37145
+ let doc = parser.parseFromString(html, "text/html");
37146
+ let body = doc.body;
37147
+ if (body.children.length === 1) {
37148
+ const firstChild = body.children[0];
37149
+ if (firstChild.tagName === "DIV" && firstChild.style.backgroundColor && firstChild.style.color && firstChild.style.padding) {
37150
+ const innerHtml = firstChild.innerHTML;
37151
+ doc = parser.parseFromString(innerHtml, "text/html");
37152
+ body = doc.body;
37153
+ }
37154
+ }
37155
+ const emptyParagraphs = body.querySelectorAll("p");
37156
+ emptyParagraphs.forEach((p2) => {
37157
+ var _a, _b;
37158
+ const hasOnlyBrOrWhitespace = !((_a = p2.textContent) == null ? void 0 : _a.trim()) && (p2.innerHTML.trim() === "" || p2.innerHTML.trim() === "<br>" || p2.querySelector("br") !== null && !((_b = p2.textContent) == null ? void 0 : _b.trim()));
37159
+ if (hasOnlyBrOrWhitespace) {
37160
+ p2.remove();
37161
+ }
37162
+ });
36915
37163
  const tables = doc.querySelectorAll("table");
36916
37164
  tables.forEach((table) => {
36917
37165
  const styles = detectTableStylesFromInline(table);
@@ -37128,6 +37376,172 @@ const OnChangeWrapper = ({
37128
37376
  };
37129
37377
  return /* @__PURE__ */ jsx(OnChangePlugin, { onChange: handleChange });
37130
37378
  };
37379
+ function getStyleFromElement(element) {
37380
+ const styles = [];
37381
+ const style = element.style;
37382
+ if (style.fontFamily) {
37383
+ const fontFamily = style.fontFamily.replace(/["']/g, "").trim();
37384
+ if (fontFamily) {
37385
+ styles.push(`font-family: ${fontFamily}`);
37386
+ }
37387
+ }
37388
+ if (style.fontSize) {
37389
+ styles.push(`font-size: ${style.fontSize}`);
37390
+ }
37391
+ if (style.lineHeight) {
37392
+ styles.push(`line-height: ${style.lineHeight}`);
37393
+ }
37394
+ if (style.color && style.color !== "rgb(0, 0, 0)") {
37395
+ styles.push(`color: ${style.color}`);
37396
+ }
37397
+ if (style.backgroundColor && style.backgroundColor !== "rgba(0, 0, 0, 0)" && style.backgroundColor !== "transparent") {
37398
+ styles.push(`background-color: ${style.backgroundColor}`);
37399
+ }
37400
+ if (style.letterSpacing && style.letterSpacing !== "normal") {
37401
+ styles.push(`letter-spacing: ${style.letterSpacing}`);
37402
+ }
37403
+ if (style.wordSpacing && style.wordSpacing !== "normal") {
37404
+ styles.push(`word-spacing: ${style.wordSpacing}`);
37405
+ }
37406
+ return styles.join("; ");
37407
+ }
37408
+ function collectTextSegmentsFromElement(element) {
37409
+ const segments = [];
37410
+ function traverse(node, inheritedStyle) {
37411
+ if (node.nodeType === Node.TEXT_NODE) {
37412
+ const text = node.textContent || "";
37413
+ if (text) {
37414
+ segments.push({ text, style: inheritedStyle });
37415
+ }
37416
+ } else if (node.nodeType === Node.ELEMENT_NODE) {
37417
+ const el = node;
37418
+ const tagName = el.tagName.toLowerCase();
37419
+ if (["br", "img", "hr"].includes(tagName)) {
37420
+ return;
37421
+ }
37422
+ const elementStyle = getStyleFromElement(el);
37423
+ const currentStyle = elementStyle || inheritedStyle;
37424
+ const children = el.childNodes;
37425
+ for (let i2 = 0; i2 < children.length; i2++) {
37426
+ traverse(children[i2], currentStyle);
37427
+ }
37428
+ }
37429
+ }
37430
+ traverse(element, "");
37431
+ return segments;
37432
+ }
37433
+ function splitAndStyleTextNode(textNode, segments) {
37434
+ if (!$isTextNode(textNode) || segments.length === 0) {
37435
+ return;
37436
+ }
37437
+ const nodeText = textNode.getTextContent();
37438
+ const format = textNode.getFormat();
37439
+ const styledSegments = segments.filter((s2) => s2.style);
37440
+ if (styledSegments.length <= 1) {
37441
+ const styledSegment = styledSegments[0];
37442
+ if (styledSegment) {
37443
+ textNode.setStyle(styledSegment.style);
37444
+ }
37445
+ return;
37446
+ }
37447
+ const splitPoints = [];
37448
+ let runningOffset = 0;
37449
+ for (const segment of segments) {
37450
+ const segmentLength = segment.text.length;
37451
+ if (segment.style) {
37452
+ splitPoints.push({
37453
+ offset: runningOffset,
37454
+ style: segment.style
37455
+ });
37456
+ }
37457
+ runningOffset += segmentLength;
37458
+ }
37459
+ if (splitPoints.length === 0) {
37460
+ return;
37461
+ }
37462
+ const offsetsToSplit = [];
37463
+ runningOffset = 0;
37464
+ for (let i2 = 0; i2 < segments.length - 1; i2++) {
37465
+ runningOffset += segments[i2].text.length;
37466
+ if (runningOffset > 0 && runningOffset < nodeText.length) {
37467
+ offsetsToSplit.push(runningOffset);
37468
+ }
37469
+ }
37470
+ if (offsetsToSplit.length === 0) {
37471
+ if (splitPoints[0]) {
37472
+ textNode.setStyle(splitPoints[0].style);
37473
+ }
37474
+ return;
37475
+ }
37476
+ try {
37477
+ const splitNodes = textNode.splitText(...offsetsToSplit);
37478
+ let segmentIndex = 0;
37479
+ for (const splitNode of splitNodes) {
37480
+ if ($isTextNode(splitNode) && segmentIndex < segments.length) {
37481
+ const segment = segments[segmentIndex];
37482
+ if (segment.style) {
37483
+ splitNode.setStyle(segment.style);
37484
+ }
37485
+ splitNode.setFormat(format);
37486
+ segmentIndex++;
37487
+ }
37488
+ }
37489
+ } catch {
37490
+ if (splitPoints[0]) {
37491
+ textNode.setStyle(splitPoints[0].style);
37492
+ }
37493
+ }
37494
+ }
37495
+ const BLOCK_SELECTORS = "p, h1, h2, h3, h4, h5, h6, li, blockquote";
37496
+ function collectBlockStyleMap(container) {
37497
+ const map = /* @__PURE__ */ new Map();
37498
+ const blocks = container.querySelectorAll(BLOCK_SELECTORS);
37499
+ blocks.forEach((block) => {
37500
+ const segments = collectTextSegmentsFromElement(block);
37501
+ const fullText = segments.map((s2) => s2.text).join("").trim();
37502
+ if (fullText && segments.some((s2) => s2.style)) {
37503
+ const normalizedText = fullText.replace(/\s+/g, " ").toLowerCase();
37504
+ map.set(normalizedText, segments);
37505
+ }
37506
+ });
37507
+ return map;
37508
+ }
37509
+ function applyStylesToBlockNodes(lexicalNodes, blockStyleMap) {
37510
+ for (const node of lexicalNodes) {
37511
+ if ($isElementNode(node)) {
37512
+ const nodeType = node.getType();
37513
+ const isBlockElement = [
37514
+ "paragraph",
37515
+ "heading",
37516
+ "listitem",
37517
+ "quote"
37518
+ ].includes(nodeType);
37519
+ if (isBlockElement) {
37520
+ const nodeText = node.getTextContent().trim();
37521
+ if (nodeText) {
37522
+ const normalizedNodeText = nodeText.replace(/\s+/g, " ").toLowerCase();
37523
+ const segments = blockStyleMap.get(normalizedNodeText);
37524
+ if (segments && segments.length > 0) {
37525
+ const textChildren = node.getChildren().filter($isTextNode);
37526
+ if (textChildren.length === 1) {
37527
+ splitAndStyleTextNode(textChildren[0], segments);
37528
+ } else if (textChildren.length > 0) {
37529
+ for (let i2 = 0; i2 < textChildren.length && i2 < segments.length; i2++) {
37530
+ const textNode = textChildren[i2];
37531
+ const segment = segments[i2];
37532
+ if (segment.style) {
37533
+ textNode.setStyle(segment.style);
37534
+ }
37535
+ }
37536
+ }
37537
+ }
37538
+ }
37539
+ } else {
37540
+ applyStylesToBlockNodes(node.getChildren(), blockStyleMap);
37541
+ }
37542
+ }
37543
+ }
37544
+ }
37131
37545
  const InitialContentPlugin = ({
37132
37546
  initialContent
37133
37547
  }) => {
@@ -37141,7 +37555,9 @@ const InitialContentPlugin = ({
37141
37555
  editor.update(() => {
37142
37556
  const parser = new DOMParser();
37143
37557
  const dom = parser.parseFromString(processedHtml, "text/html");
37558
+ const blockStyleMap = collectBlockStyleMap(dom.body);
37144
37559
  const nodes = $generateNodesFromDOM(editor, dom);
37560
+ applyStylesToBlockNodes(nodes, blockStyleMap);
37145
37561
  const root2 = $getRoot();
37146
37562
  root2.clear();
37147
37563
  root2.append(...nodes);
@@ -37655,4 +38071,4 @@ export {
37655
38071
  useHtmlView as u,
37656
38072
  verifyApiKey as v
37657
38073
  };
37658
- //# sourceMappingURL=index-23abcbd9.js.map
38074
+ //# sourceMappingURL=index-c4b49ec3.js.map