ct-rich-text-editor 1.3.6 → 1.3.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (28) hide show
  1. package/dist/api/featureSuggestion.d.ts +21 -0
  2. package/dist/assets/style.css +294 -91
  3. package/dist/components/FeatureSuggestionDialog/index.d.ts +6 -0
  4. package/dist/components/ImageComparisonDialog/index.d.ts +11 -0
  5. package/dist/components/ImageGenerationDialog/ImageGenerationManager.d.ts +2 -1
  6. package/dist/components/ImageGenerationDialog/index.d.ts +2 -1
  7. package/dist/components/ImageView/index.d.ts +2 -1
  8. package/dist/editorConfig.d.ts +1 -1
  9. package/dist/{html2pdf.bundle-9236a762.js → html2pdf.bundle-6d32d085.js} +2 -2
  10. package/dist/{html2pdf.bundle-9236a762.js.map → html2pdf.bundle-6d32d085.js.map} +1 -1
  11. package/dist/{html2pdf.bundle.min-5e51c303.js → html2pdf.bundle.min-b3120e0c.js} +2 -2
  12. package/dist/{html2pdf.bundle.min-5e51c303.js.map → html2pdf.bundle.min-b3120e0c.js.map} +1 -1
  13. package/dist/{index-dbc626d0.js → index-158a9bd4.js} +2513 -1190
  14. package/dist/index-158a9bd4.js.map +1 -0
  15. package/dist/{index-4a68b444.js → index-42136c92.js} +255 -8
  16. package/dist/index-42136c92.js.map +1 -0
  17. package/dist/{index-984a0184.js → index-9548fdb4.js} +3 -3
  18. package/dist/{index-984a0184.js.map → index-9548fdb4.js.map} +1 -1
  19. package/dist/index.js +6 -6
  20. package/dist/nodes/ImageNode.d.ts +8 -2
  21. package/dist/plugins/LinkPreviewPlugin/index.d.ts +2 -0
  22. package/dist/plugins/TableActionMenuPlugin/index.d.ts +2 -2
  23. package/dist/plugins/TableHoverActionsPlugin/index.d.ts +2 -11
  24. package/dist/plugins/TableHoverActionsPlugin/index_old_backup.d.ts +17 -0
  25. package/dist/plugins/TablePlugin.d.ts +1 -1
  26. package/package.json +2 -1
  27. package/dist/index-4a68b444.js.map +0 -1
  28. package/dist/index-dbc626d0.js.map +0 -1
@@ -6,7 +6,7 @@ var __publicField = (obj, key, value) => {
6
6
  };
7
7
  import { jsx, Fragment, jsxs } from "react/jsx-runtime";
8
8
  import * as React$1 from "react";
9
- import React__default, { createContext, useContext, useState as useState$1, forwardRef, createElement, useImperativeHandle, useRef, useEffect as useEffect$1, useMemo, useCallback, useLayoutEffect as useLayoutEffect$1, Suspense, Component } from "react";
9
+ import React__default, { createContext, useContext, useState as useState$1, Suspense, useEffect as useEffect$1, forwardRef, createElement, useImperativeHandle, useRef, useMemo, useCallback, useLayoutEffect as useLayoutEffect$1, Component } from "react";
10
10
  import axios from "axios";
11
11
  import styled from "@emotion/styled";
12
12
  import { $generateNodesFromDOM, $generateHtmlFromNodes } from "@lexical/html";
@@ -21,9 +21,10 @@ 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, mediaFileReader, isMimeType, calculateZoomLevel, CAN_USE_DOM } from "@lexical/utils";
24
+ import { TableNode, TableCellNode, TableRowNode, $createTableNodeWithDimensions, $isTableRowNode, $isTableCellNode, TableCellHeaderStates, $isTableNode, $isTableSelection, $getTableCellNodeFromLexicalNode, $getTableNodeFromLexicalNodeOrThrow, getTableElement, getTableObserverFromTableElement, $getNodeTriplet, $getTableRowIndexFromTableCellNode, $insertTableRow__EXPERIMENTAL, $getTableColumnIndexFromTableCellNode, $insertTableColumn__EXPERIMENTAL, $deleteTableRow__EXPERIMENTAL, $deleteTableColumn__EXPERIMENTAL, $unmergeCell, $computeTableMapSkipCellCheck, getDOMCellFromTarget, $getTableAndElementByKey } from "@lexical/table";
25
+ import { mergeRegister, $wrapNodeInElement, $findMatchingParent, $getNearestNodeOfType, $getNearestBlockElementAncestorOrThrow, $insertNodeToNearestRoot, $isEditorIsNestedEditor, mediaFileReader, isMimeType, calculateZoomLevel, CAN_USE_DOM } from "@lexical/utils";
25
26
  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, getDOMSelection, CLICK_COMMAND, COMMAND_PRIORITY_HIGH, $isLineBreakNode, PASTE_COMMAND, 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, 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, getDOMSelection, CLICK_COMMAND, COMMAND_PRIORITY_HIGH, $isLineBreakNode, PASTE_COMMAND, isDOMNode } from "lexical";
27
28
  import * as ReactDOM from "react-dom";
28
29
  import ReactDOM__default, { createPortal } from "react-dom";
29
30
  import { $isCodeNode, CodeNode, normalizeCodeLang, getLanguageFriendlyName, CodeHighlightNode, CODE_LANGUAGE_MAP, $createCodeNode, registerCodeHighlighting, $isCodeHighlightNode } from "@lexical/code";
@@ -31,7 +32,6 @@ import { LinkNode, $isLinkNode, TOGGLE_LINK_COMMAND, $isAutoLinkNode, $createLin
31
32
  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
33
  import { HeadingNode, QuoteNode, $isHeadingNode, $createHeadingNode, $createQuoteNode, DRAG_DROP_PASTE } from "@lexical/rich-text";
33
34
  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, $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";
@@ -267,7 +267,7 @@ const editorConfig = {
267
267
  "Baskerville",
268
268
  "Gill Sans"
269
269
  ],
270
- mentionUserList: ["mukthar", "nimish", "Anoop", "Jewel", "Ankit", "Nitin"]
270
+ mentionUserList: []
271
271
  };
272
272
  const autocomplete = "";
273
273
  function __insertCSS(code) {
@@ -1463,6 +1463,236 @@ const GetUserInfo = async ({ apiKey }) => {
1463
1463
  const AI_ACTION_COMMAND = createCommand(
1464
1464
  "AI_ACTION_COMMAND"
1465
1465
  );
1466
+ const ImageView = React__default.lazy(() => import("./index-42136c92.js"));
1467
+ function isGoogleDocCheckboxImg(img) {
1468
+ return img.parentElement != null && img.parentElement.tagName === "LI" && img.previousSibling === null && img.getAttribute("aria-roledescription") === "checkbox";
1469
+ }
1470
+ function $convertImageElement(domNode) {
1471
+ const img = domNode;
1472
+ if (img.src.startsWith("file:///") || isGoogleDocCheckboxImg(img)) {
1473
+ return null;
1474
+ }
1475
+ const { alt: altText, src, width, height } = img;
1476
+ const node = $createImageNode({ altText, height, src, width });
1477
+ return { node };
1478
+ }
1479
+ class ImageNode extends DecoratorNode {
1480
+ constructor(src, altText, maxWidth, width, height, showCaption, caption, captionsEnabled, originalPrompt, key) {
1481
+ super(key);
1482
+ __publicField(this, "__src");
1483
+ __publicField(this, "__altText");
1484
+ __publicField(this, "__width");
1485
+ __publicField(this, "__height");
1486
+ __publicField(this, "__maxWidth");
1487
+ __publicField(this, "__showCaption");
1488
+ __publicField(this, "__caption");
1489
+ // Captions cannot yet be used within editor cells
1490
+ __publicField(this, "__captionsEnabled");
1491
+ __publicField(this, "__originalPrompt");
1492
+ this.__src = src;
1493
+ this.__altText = altText;
1494
+ this.__maxWidth = maxWidth;
1495
+ this.__width = width || "inherit";
1496
+ this.__height = height || "inherit";
1497
+ this.__showCaption = showCaption || false;
1498
+ this.__caption = caption || createEditor({
1499
+ nodes: []
1500
+ });
1501
+ this.__captionsEnabled = captionsEnabled || captionsEnabled === void 0;
1502
+ this.__originalPrompt = originalPrompt || "";
1503
+ }
1504
+ // to identify the image node and must unique too
1505
+ static getType() {
1506
+ return "image";
1507
+ }
1508
+ // Clones the ImageNode when needed (during editor updates)
1509
+ static clone(node) {
1510
+ return new ImageNode(
1511
+ node.__src,
1512
+ node.__altText,
1513
+ node.__maxWidth,
1514
+ node.__width,
1515
+ node.__height,
1516
+ node.__showCaption,
1517
+ node.__caption,
1518
+ node.__captionsEnabled,
1519
+ node.__originalPrompt,
1520
+ node.__key
1521
+ );
1522
+ }
1523
+ // importing to json format
1524
+ static importJSON(serializedNode) {
1525
+ const { altText, height, width, maxWidth, caption, src, showCaption, originalPrompt } = serializedNode;
1526
+ const node = $createImageNode({
1527
+ altText,
1528
+ height,
1529
+ maxWidth,
1530
+ showCaption,
1531
+ src,
1532
+ width,
1533
+ originalPrompt: originalPrompt || ""
1534
+ // Default to empty string if undefined
1535
+ });
1536
+ const nestedEditor = node.__caption;
1537
+ const editorState = nestedEditor.parseEditorState(caption.editorState);
1538
+ if (!editorState.isEmpty()) {
1539
+ nestedEditor.setEditorState(editorState);
1540
+ }
1541
+ return node;
1542
+ }
1543
+ // Exports this node as an actual <img> tag in the DOM when needed
1544
+ exportDOM() {
1545
+ const element = document.createElement("img");
1546
+ element.setAttribute("src", this.__src);
1547
+ element.setAttribute("alt", this.__altText);
1548
+ element.setAttribute("width", this.__width.toString());
1549
+ element.setAttribute("height", this.__height.toString());
1550
+ return { element };
1551
+ }
1552
+ // convert img tag into image node in the editor using convertImageElement func
1553
+ static importDOM() {
1554
+ return {
1555
+ img: (node) => ({
1556
+ conversion: $convertImageElement,
1557
+ priority: 0
1558
+ })
1559
+ };
1560
+ }
1561
+ exportJSON() {
1562
+ return {
1563
+ altText: this.getAltText(),
1564
+ caption: this.__caption.toJSON(),
1565
+ height: this.__height === "inherit" ? 0 : this.__height,
1566
+ maxWidth: this.__maxWidth,
1567
+ showCaption: this.__showCaption,
1568
+ src: this.getSrc(),
1569
+ type: "image",
1570
+ version: 1,
1571
+ width: this.__width === "inherit" ? 0 : this.__width,
1572
+ originalPrompt: this.__originalPrompt
1573
+ };
1574
+ }
1575
+ // setting width and height when resizing
1576
+ setWidthAndHeight(width, height) {
1577
+ const writable = this.getWritable();
1578
+ writable.__width = width;
1579
+ writable.__height = height;
1580
+ }
1581
+ // state to update to show the caption
1582
+ setShowCaption(showCaption) {
1583
+ const writable = this.getWritable();
1584
+ writable.__showCaption = showCaption;
1585
+ }
1586
+ // To create a dom representation of image view
1587
+ createDOM(config) {
1588
+ const span = document.createElement("span");
1589
+ const theme2 = config.theme;
1590
+ const className = theme2.image;
1591
+ if (className !== void 0) {
1592
+ span.className = className;
1593
+ }
1594
+ return span;
1595
+ }
1596
+ updateDOM() {
1597
+ return false;
1598
+ }
1599
+ // to get the image src
1600
+ getSrc() {
1601
+ return this.__src;
1602
+ }
1603
+ // to set the image src (for image refinement)
1604
+ setSrc(src) {
1605
+ const writable = this.getWritable();
1606
+ writable.__src = src;
1607
+ }
1608
+ getAltText() {
1609
+ return this.__altText;
1610
+ }
1611
+ // to get the original prompt
1612
+ getOriginalPrompt() {
1613
+ return this.__originalPrompt;
1614
+ }
1615
+ // to set/update the original prompt (when refining)
1616
+ setOriginalPrompt(prompt) {
1617
+ const writable = this.getWritable();
1618
+ writable.__originalPrompt = prompt;
1619
+ }
1620
+ // to render the image tag
1621
+ decorate() {
1622
+ return /* @__PURE__ */ jsx(Suspense, { fallback: null, children: /* @__PURE__ */ jsx(
1623
+ ImageView,
1624
+ {
1625
+ src: this.__src,
1626
+ altText: this.__altText,
1627
+ width: this.__width,
1628
+ height: this.__height,
1629
+ maxWidth: this.__maxWidth,
1630
+ nodeKey: this.getKey(),
1631
+ showCaption: this.__showCaption,
1632
+ caption: this.__caption,
1633
+ captionsEnabled: this.__captionsEnabled,
1634
+ resizable: true,
1635
+ originalPrompt: this.__originalPrompt
1636
+ }
1637
+ ) });
1638
+ }
1639
+ }
1640
+ function $createImageNode({
1641
+ altText,
1642
+ height,
1643
+ maxWidth = 500,
1644
+ captionsEnabled,
1645
+ src,
1646
+ width,
1647
+ showCaption,
1648
+ caption,
1649
+ key,
1650
+ originalPrompt
1651
+ }) {
1652
+ return $applyNodeReplacement(
1653
+ new ImageNode(
1654
+ src,
1655
+ altText,
1656
+ maxWidth,
1657
+ width,
1658
+ height,
1659
+ showCaption,
1660
+ caption,
1661
+ captionsEnabled,
1662
+ originalPrompt,
1663
+ key
1664
+ )
1665
+ );
1666
+ }
1667
+ function $isImageNode(node) {
1668
+ return node instanceof ImageNode;
1669
+ }
1670
+ const INSERT_IMAGE_COMMAND = createCommand("INSERT_IMAGE_COMMAND");
1671
+ const ImagePlugin = ({
1672
+ captionsEnabled
1673
+ }) => {
1674
+ const [editor] = useLexicalComposerContext();
1675
+ useEffect$1(() => {
1676
+ if (!editor.hasNodes([ImageNode])) {
1677
+ throw new Error("ImagesPlugin: ImageNode not registered on editor");
1678
+ }
1679
+ return mergeRegister(
1680
+ editor.registerCommand(
1681
+ INSERT_IMAGE_COMMAND,
1682
+ (payload) => {
1683
+ const imageNode = $createImageNode(payload);
1684
+ $insertNodes([imageNode]);
1685
+ if ($isRootOrShadowRoot(imageNode.getParentOrThrow())) {
1686
+ $wrapNodeInElement(imageNode, $createParagraphNode).selectEnd();
1687
+ }
1688
+ return true;
1689
+ },
1690
+ COMMAND_PRIORITY_EDITOR
1691
+ )
1692
+ );
1693
+ }, [captionsEnabled, editor]);
1694
+ return null;
1695
+ };
1466
1696
  function setRef(ref, value) {
1467
1697
  if (typeof ref === "function") {
1468
1698
  return ref(value);
@@ -7769,6 +7999,7 @@ const ImageGenerationDialog = ({
7769
7999
  open,
7770
8000
  onOpenChange,
7771
8001
  onGenerate,
8002
+ onInsertImage,
7772
8003
  isGenerating,
7773
8004
  initialText
7774
8005
  }) => {
@@ -7778,11 +8009,29 @@ const ImageGenerationDialog = ({
7778
8009
  setPrompt(initialText);
7779
8010
  }
7780
8011
  }, [open, initialText]);
8012
+ React__default.useEffect(() => {
8013
+ if (!open) {
8014
+ setPrompt("");
8015
+ }
8016
+ }, [open]);
7781
8017
  const handleGenerate = async () => {
7782
8018
  if (!prompt.trim())
7783
8019
  return;
7784
- await onGenerate(prompt.trim());
7785
- setPrompt("");
8020
+ try {
8021
+ const trimmedPrompt = prompt.trim();
8022
+ const cleanPrompt = trimmedPrompt.replace(/^(generate|create|make|draw|paint)\s+(a|an|me|)\s*(image|picture|photo|drawing|illustration)\s+(of|with|showing|depicting)\s+/gi, "").replace(/^(generate|create|make|draw|paint)\s+(a|an|me|)\s*/gi, "").trim();
8023
+ const finalPrompt = cleanPrompt || trimmedPrompt;
8024
+ const imageUrl = await onGenerate(trimmedPrompt);
8025
+ if (!imageUrl || !imageUrl.includes("http")) {
8026
+ throw new Error("Invalid image URL received");
8027
+ }
8028
+ onInsertImage(imageUrl, finalPrompt);
8029
+ await new Promise((resolve) => setTimeout(resolve, 200));
8030
+ handleClose();
8031
+ } catch (error) {
8032
+ console.error("Error generating image:", error);
8033
+ throw error;
8034
+ }
7786
8035
  };
7787
8036
  const handleClose = () => {
7788
8037
  if (!isGenerating) {
@@ -7790,7 +8039,7 @@ const ImageGenerationDialog = ({
7790
8039
  onOpenChange(false);
7791
8040
  }
7792
8041
  };
7793
- return /* @__PURE__ */ jsx(Dialog, { open, onOpenChange: handleClose, children: /* @__PURE__ */ jsxs(DialogContent, { className: "sm:max-w-[500px]", children: [
8042
+ return /* @__PURE__ */ jsx(Dialog, { open, onOpenChange: handleClose, children: /* @__PURE__ */ jsxs(DialogContent, { className: "sm:max-w-[500px] max-h-[90vh] overflow-y-auto", children: [
7794
8043
  /* @__PURE__ */ jsxs(DialogHeader, { children: [
7795
8044
  /* @__PURE__ */ jsxs(DialogTitle, { className: "flex items-center gap-2 text-xl", children: [
7796
8045
  /* @__PURE__ */ jsx("span", { className: "text-2xl", children: "✨" }),
@@ -7800,12 +8049,12 @@ const ImageGenerationDialog = ({
7800
8049
  ] }),
7801
8050
  /* @__PURE__ */ jsxs("div", { className: "space-y-4 py-4", children: [
7802
8051
  /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
7803
- /* @__PURE__ */ jsx(Label$2, { htmlFor: "image-prompt", children: "Image Description" }),
8052
+ /* @__PURE__ */ jsx(Label$2, { htmlFor: "image-prompt", children: "What do you want to see?" }),
7804
8053
  /* @__PURE__ */ jsx(
7805
8054
  Input$1,
7806
8055
  {
7807
8056
  id: "image-prompt",
7808
- placeholder: "e.g., A beautiful sunset over mountains with a lake",
8057
+ placeholder: "Mountains and rivers with birds flying in the sky",
7809
8058
  value: prompt,
7810
8059
  onChange: (e) => setPrompt(e.target.value),
7811
8060
  disabled: isGenerating,
@@ -7817,7 +8066,7 @@ const ImageGenerationDialog = ({
7817
8066
  }
7818
8067
  }
7819
8068
  ),
7820
- /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: "Be specific and descriptive for best results" })
8069
+ /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: "💡 Just describe what you want - be specific and detailed for best results" })
7821
8070
  ] }),
7822
8071
  isGenerating && /* @__PURE__ */ jsx("div", { className: "p-4 rounded-lg bg-blue-50 dark:bg-blue-950/20 border border-blue-200 dark:border-blue-800", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3", children: [
7823
8072
  /* @__PURE__ */ jsx("div", { className: "h-5 w-5 animate-spin rounded-full border-2 border-blue-600 border-t-transparent" }),
@@ -7829,12 +8078,13 @@ const ImageGenerationDialog = ({
7829
8078
  !isGenerating && /* @__PURE__ */ jsx("div", { className: "p-3 rounded-lg bg-gray-50 dark:bg-gray-900 border border-gray-200 dark:border-gray-800", children: /* @__PURE__ */ jsxs("div", { className: "flex items-start gap-2", children: [
7830
8079
  /* @__PURE__ */ jsx("span", { className: "text-lg", children: "💡" }),
7831
8080
  /* @__PURE__ */ jsxs("div", { className: "text-xs text-gray-600 dark:text-gray-400", children: [
7832
- /* @__PURE__ */ jsx("p", { className: "font-medium mb-1", children: "Tips for better results:" }),
7833
- /* @__PURE__ */ jsxs("ul", { className: "list-disc list-inside space-y-0.5", children: [
7834
- /* @__PURE__ */ jsx("li", { children: "Be specific about style, colors, and mood" }),
7835
- /* @__PURE__ */ jsx("li", { children: "Mention key objects and their positions" }),
7836
- /* @__PURE__ */ jsx("li", { children: 'Add artistic style references (e.g., "oil painting")' })
7837
- ] })
8081
+ /* @__PURE__ */ jsx("p", { className: "font-medium mb-1.5", children: "Good examples:" }),
8082
+ /* @__PURE__ */ jsxs("ul", { className: "list-none space-y-1 ml-1", children: [
8083
+ /* @__PURE__ */ jsx("li", { children: '✅ "Mountains and rivers at sunset"' }),
8084
+ /* @__PURE__ */ jsx("li", { children: '✅ "A cat sitting on a windowsill"' }),
8085
+ /* @__PURE__ */ jsx("li", { children: ' "Modern city skyline at night"' })
8086
+ ] }),
8087
+ /* @__PURE__ */ jsx("p", { className: "mt-2 text-amber-600 dark:text-amber-400", children: `⚠️ Don't include "generate" or "create" - just describe!` })
7838
8088
  ] })
7839
8089
  ] }) })
7840
8090
  ] }),
@@ -7858,14 +8108,14 @@ const ImageGenerationDialog = ({
7858
8108
  "Generating..."
7859
8109
  ] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
7860
8110
  /* @__PURE__ */ jsx("span", { className: "mr-2", children: "✨" }),
7861
- "Generate Image"
8111
+ "Generate & Insert"
7862
8112
  ] })
7863
8113
  }
7864
8114
  )
7865
8115
  ] })
7866
8116
  ] }) });
7867
8117
  };
7868
- const ImageGenerationManager = forwardRef(({ onGenerate }, ref) => {
8118
+ const ImageGenerationManager = forwardRef(({ onGenerate, onInsertImage }, ref) => {
7869
8119
  const [open, setOpen] = useState$1(false);
7870
8120
  const [isGenerating, setIsGenerating] = useState$1(false);
7871
8121
  const [initialText, setInitialText] = useState$1(void 0);
@@ -7879,20 +8129,26 @@ const ImageGenerationManager = forwardRef(({ onGenerate }, ref) => {
7879
8129
  const handleGenerate = async (prompt) => {
7880
8130
  setIsGenerating(true);
7881
8131
  try {
7882
- await onGenerate(prompt);
7883
- setOpen(false);
8132
+ const imageUrl = await onGenerate(prompt);
8133
+ return imageUrl;
7884
8134
  } catch (error) {
7885
8135
  console.error("Error generating image:", error);
8136
+ throw error;
7886
8137
  } finally {
7887
8138
  setIsGenerating(false);
7888
8139
  }
7889
8140
  };
8141
+ const handleInsertImage = (imageUrl, prompt) => {
8142
+ onInsertImage(imageUrl, prompt);
8143
+ setOpen(false);
8144
+ };
7890
8145
  return /* @__PURE__ */ jsx(
7891
8146
  ImageGenerationDialog,
7892
8147
  {
7893
8148
  open,
7894
8149
  onOpenChange: setOpen,
7895
8150
  onGenerate: handleGenerate,
8151
+ onInsertImage: handleInsertImage,
7896
8152
  isGenerating,
7897
8153
  initialText
7898
8154
  }
@@ -8006,6 +8262,20 @@ const AIRephrasePlugin = () => {
8006
8262
  (_a = imageDialogRef.current) == null ? void 0 : _a.openDialog(selectedText);
8007
8263
  return true;
8008
8264
  };
8265
+ const extractImageUrlFromHtml = (htmlString) => {
8266
+ try {
8267
+ const parser = new DOMParser();
8268
+ const dom = parser.parseFromString(htmlString, "text/html");
8269
+ const imgElement = dom.querySelector("img");
8270
+ if (!imgElement || !imgElement.src) {
8271
+ throw new Error("No image element found in response");
8272
+ }
8273
+ return imgElement.src;
8274
+ } catch (error) {
8275
+ console.error("Error extracting image URL:", error);
8276
+ throw new Error("Failed to extract image URL from response");
8277
+ }
8278
+ };
8009
8279
  const generateImageFromPrompt = async (promptText) => {
8010
8280
  try {
8011
8281
  const response = await AiJsonResponse({ content: `Generate Image: ${promptText}` });
@@ -8014,21 +8284,26 @@ const AIRephrasePlugin = () => {
8014
8284
  console.warn("No HTML returned from agent for image generation");
8015
8285
  throw new Error("Failed to generate image via agent");
8016
8286
  }
8017
- editor.update(() => {
8018
- const currentSelection = $getSelection();
8019
- if (!currentSelection || !$isRangeSelection(currentSelection))
8020
- return;
8021
- const parser = new DOMParser();
8022
- const dom = parser.parseFromString(htmlString, "text/html");
8023
- const nodes = $generateNodesFromDOM(editor, dom);
8024
- currentSelection.insertText("");
8025
- $insertNodes(nodes);
8026
- });
8287
+ const imageUrl = extractImageUrlFromHtml(htmlString);
8288
+ return imageUrl;
8027
8289
  } catch (error) {
8028
8290
  console.error("Error generating image via agent:", error);
8029
8291
  throw error;
8030
8292
  }
8031
8293
  };
8294
+ const insertImageIntoEditor = (imageUrl, prompt) => {
8295
+ try {
8296
+ editor.dispatchCommand(INSERT_IMAGE_COMMAND, {
8297
+ src: imageUrl,
8298
+ altText: "Generated image",
8299
+ originalPrompt: prompt
8300
+ // Store the prompt for refinement
8301
+ });
8302
+ } catch (error) {
8303
+ console.error("Error inserting image into editor:", error);
8304
+ throw error;
8305
+ }
8306
+ };
8032
8307
  useEffect$1(() => {
8033
8308
  return editor.registerCommand(
8034
8309
  AI_ACTION_COMMAND,
@@ -8065,11 +8340,12 @@ const AIRephrasePlugin = () => {
8065
8340
  ImageGenerationManager,
8066
8341
  {
8067
8342
  ref: imageDialogRef,
8068
- onGenerate: generateImageFromPrompt
8343
+ onGenerate: generateImageFromPrompt,
8344
+ onInsertImage: insertImageIntoEditor
8069
8345
  }
8070
8346
  );
8071
8347
  };
8072
- const index$7 = "";
8348
+ const index$8 = "";
8073
8349
  var freeGlobal = typeof global == "object" && global && global.Object === Object && global;
8074
8350
  const freeGlobal$1 = freeGlobal;
8075
8351
  var freeSelf = typeof self == "object" && self && self.Object === Object && self;
@@ -8288,7 +8564,7 @@ function CopyButton({ editor, getCodeDOMNode }) {
8288
8564
  }
8289
8565
  return /* @__PURE__ */ jsx("button", { className: "menu-item", onClick: handleClick, "aria-label": "copy", children: isCopyCompleted ? /* @__PURE__ */ jsx("i", { className: "format success" }) : /* @__PURE__ */ jsx("i", { className: "format copy" }) });
8290
8566
  }
8291
- const index$6 = "";
8567
+ const index$7 = "";
8292
8568
  const PRETTIER_PARSER_MODULES = {
8293
8569
  css: [() => import("./postcss-f084f74d.js")],
8294
8570
  html: [() => import("./html-5586dbf6.js")],
@@ -12031,7 +12307,7 @@ const computePosition = (reference, floating, options) => {
12031
12307
  var isClient = typeof document !== "undefined";
12032
12308
  var noop = function noop2() {
12033
12309
  };
12034
- var index$5 = isClient ? useLayoutEffect$1 : noop;
12310
+ var index$6 = isClient ? useLayoutEffect$1 : noop;
12035
12311
  function deepEqual(a, b2) {
12036
12312
  if (a === b2) {
12037
12313
  return true;
@@ -12093,7 +12369,7 @@ function roundByDPR(element, value) {
12093
12369
  }
12094
12370
  function useLatestRef(value) {
12095
12371
  const ref = React$1.useRef(value);
12096
- index$5(() => {
12372
+ index$6(() => {
12097
12373
  ref.current = value;
12098
12374
  });
12099
12375
  return ref;
@@ -12179,7 +12455,7 @@ function useFloating(options) {
12179
12455
  }
12180
12456
  });
12181
12457
  }, [latestMiddleware, placement, strategy, platformRef, openRef]);
12182
- index$5(() => {
12458
+ index$6(() => {
12183
12459
  if (open === false && dataRef.current.isPositioned) {
12184
12460
  dataRef.current.isPositioned = false;
12185
12461
  setData((data2) => ({
@@ -12189,13 +12465,13 @@ function useFloating(options) {
12189
12465
  }
12190
12466
  }, [open]);
12191
12467
  const isMountedRef = React$1.useRef(false);
12192
- index$5(() => {
12468
+ index$6(() => {
12193
12469
  isMountedRef.current = true;
12194
12470
  return () => {
12195
12471
  isMountedRef.current = false;
12196
12472
  };
12197
12473
  }, []);
12198
- index$5(() => {
12474
+ index$6(() => {
12199
12475
  if (referenceEl)
12200
12476
  referenceRef.current = referenceEl;
12201
12477
  if (floatingEl)
@@ -14395,7 +14671,7 @@ const EmbedComponent = ({ url, displayType, alignment, nodeKey }) => {
14395
14671
  }
14396
14672
  );
14397
14673
  };
14398
- const FileComponent = React$1.lazy(() => import("./index-984a0184.js"));
14674
+ const FileComponent = React$1.lazy(() => import("./index-9548fdb4.js"));
14399
14675
  function convertFileElement(domNode) {
14400
14676
  if (domNode instanceof HTMLDivElement) {
14401
14677
  const dataUrl = domNode.getAttribute("data-lexical-file-src");
@@ -14503,187 +14779,6 @@ function $createFileNode({ src, fileName, fileSize, key }) {
14503
14779
  function $isFileNode(node) {
14504
14780
  return node instanceof FileNode;
14505
14781
  }
14506
- const ImageView = React__default.lazy(() => import("./index-4a68b444.js"));
14507
- function isGoogleDocCheckboxImg(img) {
14508
- return img.parentElement != null && img.parentElement.tagName === "LI" && img.previousSibling === null && img.getAttribute("aria-roledescription") === "checkbox";
14509
- }
14510
- function $convertImageElement(domNode) {
14511
- const img = domNode;
14512
- if (img.src.startsWith("file:///") || isGoogleDocCheckboxImg(img)) {
14513
- return null;
14514
- }
14515
- const { alt: altText, src, width, height } = img;
14516
- const node = $createImageNode({ altText, height, src, width });
14517
- return { node };
14518
- }
14519
- class ImageNode extends DecoratorNode {
14520
- constructor(src, altText, maxWidth, width, height, showCaption, caption, captionsEnabled, key) {
14521
- super(key);
14522
- __publicField(this, "__src");
14523
- __publicField(this, "__altText");
14524
- __publicField(this, "__width");
14525
- __publicField(this, "__height");
14526
- __publicField(this, "__maxWidth");
14527
- __publicField(this, "__showCaption");
14528
- __publicField(this, "__caption");
14529
- // Captions cannot yet be used within editor cells
14530
- __publicField(this, "__captionsEnabled");
14531
- this.__src = src;
14532
- this.__altText = altText;
14533
- this.__maxWidth = maxWidth;
14534
- this.__width = width || "inherit";
14535
- this.__height = height || "inherit";
14536
- this.__showCaption = showCaption || false;
14537
- this.__caption = caption || createEditor({
14538
- nodes: []
14539
- });
14540
- this.__captionsEnabled = captionsEnabled || captionsEnabled === void 0;
14541
- }
14542
- // to identify the image node and must unique too
14543
- static getType() {
14544
- return "image";
14545
- }
14546
- // Clones the ImageNode when needed (during editor updates)
14547
- static clone(node) {
14548
- return new ImageNode(
14549
- node.__src,
14550
- node.__altText,
14551
- node.__maxWidth,
14552
- node.__width,
14553
- node.__height,
14554
- node.__showCaption,
14555
- node.__caption,
14556
- node.__captionsEnabled,
14557
- node.__key
14558
- );
14559
- }
14560
- // importing to json format
14561
- static importJSON(serializedNode) {
14562
- const { altText, height, width, maxWidth, caption, src, showCaption } = serializedNode;
14563
- const node = $createImageNode({
14564
- altText,
14565
- height,
14566
- maxWidth,
14567
- showCaption,
14568
- src,
14569
- width
14570
- });
14571
- const nestedEditor = node.__caption;
14572
- const editorState = nestedEditor.parseEditorState(caption.editorState);
14573
- if (!editorState.isEmpty()) {
14574
- nestedEditor.setEditorState(editorState);
14575
- }
14576
- return node;
14577
- }
14578
- // Exports this node as an actual <img> tag in the DOM when needed
14579
- exportDOM() {
14580
- const element = document.createElement("img");
14581
- element.setAttribute("src", this.__src);
14582
- element.setAttribute("alt", this.__altText);
14583
- element.setAttribute("width", this.__width.toString());
14584
- element.setAttribute("height", this.__height.toString());
14585
- return { element };
14586
- }
14587
- // convert img tag into image node in the editor using convertImageElement func
14588
- static importDOM() {
14589
- return {
14590
- img: (node) => ({
14591
- conversion: $convertImageElement,
14592
- priority: 0
14593
- })
14594
- };
14595
- }
14596
- exportJSON() {
14597
- return {
14598
- altText: this.getAltText(),
14599
- caption: this.__caption.toJSON(),
14600
- height: this.__height === "inherit" ? 0 : this.__height,
14601
- maxWidth: this.__maxWidth,
14602
- showCaption: this.__showCaption,
14603
- src: this.getSrc(),
14604
- type: "image",
14605
- version: 1,
14606
- width: this.__width === "inherit" ? 0 : this.__width
14607
- };
14608
- }
14609
- // setting width and height when resizing
14610
- setWidthAndHeight(width, height) {
14611
- const writable = this.getWritable();
14612
- writable.__width = width;
14613
- writable.__height = height;
14614
- }
14615
- // state to update to show the caption
14616
- setShowCaption(showCaption) {
14617
- const writable = this.getWritable();
14618
- writable.__showCaption = showCaption;
14619
- }
14620
- // To create a dom representation of image view
14621
- createDOM(config) {
14622
- const span = document.createElement("span");
14623
- const theme2 = config.theme;
14624
- const className = theme2.image;
14625
- if (className !== void 0) {
14626
- span.className = className;
14627
- }
14628
- return span;
14629
- }
14630
- updateDOM() {
14631
- return false;
14632
- }
14633
- // to get the image src
14634
- getSrc() {
14635
- return this.__src;
14636
- }
14637
- getAltText() {
14638
- return this.__altText;
14639
- }
14640
- // to render the image tag
14641
- decorate() {
14642
- return /* @__PURE__ */ jsx(Suspense, { fallback: null, children: /* @__PURE__ */ jsx(
14643
- ImageView,
14644
- {
14645
- src: this.__src,
14646
- altText: this.__altText,
14647
- width: this.__width,
14648
- height: this.__height,
14649
- maxWidth: this.__maxWidth,
14650
- nodeKey: this.getKey(),
14651
- showCaption: this.__showCaption,
14652
- caption: this.__caption,
14653
- captionsEnabled: this.__captionsEnabled,
14654
- resizable: true
14655
- }
14656
- ) });
14657
- }
14658
- }
14659
- function $createImageNode({
14660
- altText,
14661
- height,
14662
- maxWidth = 500,
14663
- captionsEnabled,
14664
- src,
14665
- width,
14666
- showCaption,
14667
- caption,
14668
- key
14669
- }) {
14670
- return $applyNodeReplacement(
14671
- new ImageNode(
14672
- src,
14673
- altText,
14674
- maxWidth,
14675
- width,
14676
- height,
14677
- showCaption,
14678
- caption,
14679
- captionsEnabled,
14680
- key
14681
- )
14682
- );
14683
- }
14684
- function $isImageNode(node) {
14685
- return node instanceof ImageNode;
14686
- }
14687
14782
  function $convertMentionElement(domNode) {
14688
14783
  const textContent = domNode.textContent;
14689
14784
  const mentionName = domNode.getAttribute("data-lexical-mention-name");
@@ -15618,24 +15713,6 @@ const BoldIcon = () => /* @__PURE__ */ jsx(
15618
15713
  )
15619
15714
  }
15620
15715
  );
15621
- const PlusIcon = () => /* @__PURE__ */ jsxs(
15622
- "svg",
15623
- {
15624
- xmlns: "http://www.w3.org/2000/svg",
15625
- width: "24",
15626
- height: "24",
15627
- viewBox: "0 0 24 24",
15628
- fill: "none",
15629
- stroke: "currentColor",
15630
- strokeWidth: "2",
15631
- strokeLinecap: "round",
15632
- strokeLinejoin: "round",
15633
- children: [
15634
- /* @__PURE__ */ jsx("path", { d: "M5 12h14" }),
15635
- /* @__PURE__ */ jsx("path", { d: "M12 5v14" })
15636
- ]
15637
- }
15638
- );
15639
15716
  const ChevronDownIcon = () => /* @__PURE__ */ jsx(
15640
15717
  "svg",
15641
15718
  {
@@ -16038,7 +16115,6 @@ const RecordingIcon = () => /* @__PURE__ */ jsx(
16038
16115
  }
16039
16116
  );
16040
16117
  const AddCommentIcon = () => /* @__PURE__ */ jsx("svg", { xmlns: "http://www.w3.org/2000/svg", width: "24", height: "24", viewBox: "0 0 24 24", fill: "none", children: /* @__PURE__ */ jsx("path", { d: "M19 14.3333C19 14.7459 18.8361 15.1416 18.5444 15.4333C18.2527 15.725 17.857 15.8889 17.4444 15.8889H8.11111L5 19V6.55556C5 6.143 5.16389 5.74733 5.45561 5.45561C5.74733 5.16389 6.143 5 6.55556 5H17.4444C17.857 5 18.2527 5.16389 18.5444 5.45561C18.8361 5.74733 19 6.143 19 6.55556V14.3333Z", stroke: "currentColor", strokeWidth: "1.33333", strokeLinecap: "round", strokeLinejoin: "round" }) });
16041
- const CheckIcon = () => /* @__PURE__ */ jsx("svg", { xmlns: "http://www.w3.org/2000/svg", width: "24", height: "24", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx("path", { d: "M20 6 9 17l-5-5" }) });
16042
16118
  const QuoteIcon = () => /* @__PURE__ */ jsxs("svg", { xmlns: "http://www.w3.org/2000/svg", width: "24", height: "24", viewBox: "0 0 24 24", fill: "none", children: [
16043
16119
  /* @__PURE__ */ jsx("path", { d: "M4.75 19C7 19 10 18.2222 10 12.7779V6.55575C10 5.58354 9.433 4.98699 8.5 5.00022H5.5C4.5625 5.00022 4 5.58354 4 6.53397V11.2223C4 12.1945 4.5625 12.7779 5.5 12.7779C6.25 12.7779 6.25 12.7779 6.25 13.5556V14.3334C6.25 15.1112 5.5 15.8889 4.75 15.8889C4 15.8889 4 15.8952 4 16.6908V18.2222C4 19 4 19 4.75 19Z", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" }),
16044
16120
  /* @__PURE__ */ jsx("path", { d: "M14.75 19C17 19 20 18.2222 20 12.7779V6.55575C20 5.58354 19.4323 4.98699 18.5 5.00022H15.5C14.5625 5.00022 14 5.58354 14 6.53397V11.2223C14 12.1945 14.5625 12.7779 15.5 12.7779H16.0625C16.0625 14.5278 16.25 15.8889 14 15.8889V18.2222C14 19 14 19 14.75 19Z", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" })
@@ -16184,6 +16260,154 @@ const formatMenuItems = [
16184
16260
  }
16185
16261
  ];
16186
16262
  const LOWEST_PRIORITY = 1;
16263
+ class FeatureSuggestionAPI {
16264
+ static async createSuggestion(data, apiKey) {
16265
+ const response = await backendAPI.post(
16266
+ "/api/feature-suggestions",
16267
+ data,
16268
+ apiKey ? { headers: { "X-API-Key": apiKey } } : void 0
16269
+ );
16270
+ return response.data;
16271
+ }
16272
+ }
16273
+ function FeatureSuggestionDialog({
16274
+ open,
16275
+ onOpenChange
16276
+ }) {
16277
+ const { apiKey } = useEditor();
16278
+ const [title, setTitle] = useState$1("");
16279
+ const [description, setDescription] = useState$1("");
16280
+ const [isSubmitting, setIsSubmitting] = useState$1(false);
16281
+ const [errors, setErrors] = useState$1({});
16282
+ const validateForm = () => {
16283
+ const newErrors = {};
16284
+ if (!title.trim()) {
16285
+ newErrors.title = "Title is required";
16286
+ }
16287
+ if (!description.trim()) {
16288
+ newErrors.description = "Description is required";
16289
+ } else if (description.trim().length < 10) {
16290
+ newErrors.description = "Description must be at least 10 characters";
16291
+ }
16292
+ setErrors(newErrors);
16293
+ return Object.keys(newErrors).length === 0;
16294
+ };
16295
+ const handleSubmit = async (e) => {
16296
+ e.preventDefault();
16297
+ if (!validateForm()) {
16298
+ return;
16299
+ }
16300
+ setIsSubmitting(true);
16301
+ try {
16302
+ await FeatureSuggestionAPI.createSuggestion(
16303
+ {
16304
+ title: title.trim(),
16305
+ description: description.trim()
16306
+ },
16307
+ apiKey || void 0
16308
+ );
16309
+ toast.success("Success!", {
16310
+ description: "Your feature suggestion has been submitted successfully!"
16311
+ });
16312
+ setTitle("");
16313
+ setDescription("");
16314
+ setErrors({});
16315
+ onOpenChange(false);
16316
+ } catch (error) {
16317
+ console.error("Error submitting suggestion:", error);
16318
+ toast.error("Error", {
16319
+ description: "Failed to submit feature suggestion. Please try again."
16320
+ });
16321
+ } finally {
16322
+ setIsSubmitting(false);
16323
+ }
16324
+ };
16325
+ const handleCancel = () => {
16326
+ setTitle("");
16327
+ setDescription("");
16328
+ setErrors({});
16329
+ onOpenChange(false);
16330
+ };
16331
+ return /* @__PURE__ */ jsx(Dialog, { open, onOpenChange, children: /* @__PURE__ */ jsxs(DialogContent, { className: "sm:max-w-[500px]", children: [
16332
+ /* @__PURE__ */ jsxs(DialogHeader, { children: [
16333
+ /* @__PURE__ */ jsxs(DialogTitle, { className: "cteditor-flex cteditor-items-center cteditor-gap-2", children: [
16334
+ /* @__PURE__ */ jsx(Lightbulb, { className: "cteditor-h-5 cteditor-w-5 cteditor-text-primary" }),
16335
+ "Suggest a Feature"
16336
+ ] }),
16337
+ /* @__PURE__ */ jsx(DialogDescription, { children: "Help us improve by suggesting new features you'd like to see" })
16338
+ ] }),
16339
+ /* @__PURE__ */ jsxs("form", { onSubmit: handleSubmit, children: [
16340
+ /* @__PURE__ */ jsxs("div", { className: "cteditor-grid cteditor-gap-4 cteditor-py-4", children: [
16341
+ /* @__PURE__ */ jsxs("div", { className: "cteditor-grid cteditor-gap-2", children: [
16342
+ /* @__PURE__ */ jsx(Label$2, { htmlFor: "title", children: "Feature Name *" }),
16343
+ /* @__PURE__ */ jsx(
16344
+ Input$1,
16345
+ {
16346
+ id: "title",
16347
+ placeholder: "Enter a title for your feature suggestion",
16348
+ value: title,
16349
+ onChange: (e) => {
16350
+ setTitle(e.target.value);
16351
+ if (errors.title) {
16352
+ setErrors({ ...errors, title: void 0 });
16353
+ }
16354
+ },
16355
+ className: errors.title ? "cteditor-border-red-500 focus-visible:cteditor-ring-red-500" : ""
16356
+ }
16357
+ ),
16358
+ errors.title && /* @__PURE__ */ jsx("p", { className: "cteditor-text-sm cteditor-text-red-500", children: errors.title })
16359
+ ] }),
16360
+ /* @__PURE__ */ jsxs("div", { className: "cteditor-grid cteditor-gap-2", children: [
16361
+ /* @__PURE__ */ jsx(Label$2, { htmlFor: "description", children: "Description *" }),
16362
+ /* @__PURE__ */ jsx(
16363
+ "textarea",
16364
+ {
16365
+ id: "description",
16366
+ placeholder: "Describe your feature suggestion in detail. What problem would it solve? How would it work?",
16367
+ value: description,
16368
+ onChange: (e) => {
16369
+ setDescription(e.target.value);
16370
+ if (errors.description) {
16371
+ setErrors({ ...errors, description: void 0 });
16372
+ }
16373
+ },
16374
+ className: `cteditor-flex cteditor-min-h-[120px] cteditor-w-full cteditor-rounded-md cteditor-border cteditor-border-input cteditor-bg-transparent cteditor-px-3 cteditor-py-2 cteditor-text-base cteditor-shadow-sm placeholder:cteditor-text-muted-foreground focus-visible:cteditor-outline-none focus-visible:cteditor-ring-1 focus-visible:cteditor-ring-ring disabled:cteditor-cursor-not-allowed disabled:cteditor-opacity-50 ${errors.description ? "cteditor-border-red-500 focus-visible:cteditor-ring-red-500" : ""}`
16375
+ }
16376
+ ),
16377
+ errors.description && /* @__PURE__ */ jsx("p", { className: "cteditor-text-sm cteditor-text-red-500", children: errors.description })
16378
+ ] }),
16379
+ /* @__PURE__ */ jsxs("div", { className: "cteditor-p-3 cteditor-bg-muted/50 cteditor-rounded-lg", children: [
16380
+ /* @__PURE__ */ jsxs("div", { className: "cteditor-flex cteditor-items-center cteditor-gap-1 cteditor-mb-2", children: [
16381
+ /* @__PURE__ */ jsx(Lightbulb, { className: "cteditor-h-4 cteditor-w-4" }),
16382
+ /* @__PURE__ */ jsx("h3", { className: "cteditor-text-sm cteditor-font-medium", children: "Tips for a great suggestion:" })
16383
+ ] }),
16384
+ /* @__PURE__ */ jsxs("ul", { className: "cteditor-text-xs cteditor-text-muted-foreground cteditor-space-y-1", children: [
16385
+ /* @__PURE__ */ jsx("li", { children: "• Be specific about what you want and why it would be useful" }),
16386
+ /* @__PURE__ */ jsx("li", { children: "• Explain the problem your suggestion would solve" }),
16387
+ /* @__PURE__ */ jsx("li", { children: "• Consider how other users might benefit from this feature" }),
16388
+ /* @__PURE__ */ jsx("li", { children: "• Include any relevant examples or use cases" })
16389
+ ] })
16390
+ ] })
16391
+ ] }),
16392
+ /* @__PURE__ */ jsxs(DialogFooter, { children: [
16393
+ /* @__PURE__ */ jsx(
16394
+ Button,
16395
+ {
16396
+ type: "button",
16397
+ variant: "outline",
16398
+ onClick: handleCancel,
16399
+ disabled: isSubmitting,
16400
+ children: "Cancel"
16401
+ }
16402
+ ),
16403
+ /* @__PURE__ */ jsx(Button, { type: "submit", disabled: isSubmitting, children: isSubmitting ? /* @__PURE__ */ jsxs(Fragment, { children: [
16404
+ /* @__PURE__ */ jsx(Loader2, { className: "cteditor-h-4 cteditor-w-4 cteditor-animate-spin cteditor-mr-2" }),
16405
+ "Submitting..."
16406
+ ] }) : "Submit Suggestion" })
16407
+ ] })
16408
+ ] })
16409
+ ] }) });
16410
+ }
16187
16411
  const DEFAULT_FONT_SIZE = 15;
16188
16412
  const INITIAL_TOOLBAR_STATE = {
16189
16413
  bgColor: "#fff",
@@ -17013,342 +17237,80 @@ function AIChatPlugin({
17013
17237
  const [editor] = useLexicalComposerContext();
17014
17238
  return useAIChatToolbar(editor, apiKey);
17015
17239
  }
17016
- const OPEN_TABLE_MODAL_COMMAND = createCommand();
17017
- const getContrastColor = (hexColor) => {
17018
- const hex = hexColor.replace("#", "");
17019
- const r2 = parseInt(hex.substr(0, 2), 16);
17020
- const g2 = parseInt(hex.substr(2, 2), 16);
17021
- const b2 = parseInt(hex.substr(4, 2), 16);
17022
- const luminance = (0.299 * r2 + 0.587 * g2 + 0.114 * b2) / 255;
17023
- return luminance > 0.5 ? "#000000" : "#FFFFFF";
17024
- };
17240
+ const CREATE_TABLE_COMMAND = createCommand();
17025
17241
  function TableOptionPlugin() {
17026
- const [isOpen, setIsOpen] = useState$1(false);
17027
- const [rows, setRows] = useState$1("");
17028
- const [columns, setColumns] = useState$1("");
17029
- const [includeHeaders, setIncludeHeaders] = useState$1(false);
17030
- const [columnHeadings, setColumnHeadings] = useState$1([]);
17031
- const [headerColor, setHeaderColor] = useState$1("#4A90E2");
17032
17242
  const [editor] = useLexicalComposerContext();
17033
- const headerCellsMapRef = useRef(
17034
- /* @__PURE__ */ new Map()
17035
- );
17036
- useEffect$1(() => {
17037
- return editor.registerCommand(
17038
- OPEN_TABLE_MODAL_COMMAND,
17039
- () => {
17040
- setIsOpen(true);
17041
- return true;
17042
- },
17043
- COMMAND_PRIORITY_EDITOR
17044
- );
17045
- }, [editor]);
17046
- useEffect$1(() => {
17047
- const headerCellsMap = headerCellsMapRef.current;
17048
- const reapplyHeaderStyles = () => {
17049
- const rootElement2 = editor.getRootElement();
17050
- if (!rootElement2)
17051
- return;
17052
- const tables = rootElement2.querySelectorAll("table");
17053
- tables.forEach((table) => {
17054
- const rows2 = table.querySelectorAll("tr");
17055
- if (rows2.length > 0) {
17056
- const firstRow = rows2[0];
17057
- const cells = firstRow.querySelectorAll("th, td");
17058
- cells.forEach((cell, index2) => {
17059
- const htmlCell = cell;
17060
- let savedHeaderColor = htmlCell.getAttribute("data-header-color");
17061
- let savedTextColor = htmlCell.getAttribute("data-text-color");
17062
- const cellKey = `${Array.from(tables).indexOf(table)}-${index2}`;
17063
- if (!savedHeaderColor && headerCellsMap.has(cellKey)) {
17064
- const colors = headerCellsMap.get(cellKey);
17065
- savedHeaderColor = colors.bgColor;
17066
- savedTextColor = colors.textColor;
17067
- }
17068
- if (savedHeaderColor && savedTextColor) {
17069
- headerCellsMap.set(cellKey, {
17070
- bgColor: savedHeaderColor,
17071
- textColor: savedTextColor
17072
- });
17073
- htmlCell.setAttribute("data-header-color", savedHeaderColor);
17074
- htmlCell.setAttribute("data-text-color", savedTextColor);
17075
- htmlCell.style.setProperty(
17076
- "background-color",
17077
- savedHeaderColor,
17078
- "important"
17079
- );
17080
- htmlCell.style.setProperty("color", savedTextColor, "important");
17081
- htmlCell.style.setProperty("padding", "8px", "important");
17082
- htmlCell.style.setProperty(
17083
- "border",
17084
- "1px solid #ddd",
17085
- "important"
17086
- );
17087
- htmlCell.style.setProperty("font-weight", "bold", "important");
17088
- htmlCell.style.setProperty("white-space", "nowrap", "important");
17243
+ const createInstantTable = React__default.useCallback(() => {
17244
+ const rowCount = 3;
17245
+ const colCount = 3;
17246
+ const headerColor = "#565656ff";
17247
+ editor.update(() => {
17248
+ const selection = $getSelection();
17249
+ let shouldReplaceCurrentNode = false;
17250
+ if ($isRangeSelection(selection)) {
17251
+ const anchorNode = selection.anchor.getNode();
17252
+ const parent = anchorNode.getParent();
17253
+ if (parent) {
17254
+ try {
17255
+ const element = anchorNode.getTopLevelElementOrThrow();
17256
+ if ($isParagraphNode(element) && element.getTextContent().trim() === "") {
17257
+ shouldReplaceCurrentNode = true;
17089
17258
  }
17090
- });
17259
+ } catch (error) {
17260
+ shouldReplaceCurrentNode = false;
17261
+ }
17091
17262
  }
17092
- });
17093
- };
17094
- const removeUpdateListener = editor.registerUpdateListener(() => {
17095
- setTimeout(() => {
17096
- reapplyHeaderStyles();
17097
- }, 0);
17098
- });
17099
- const rootElement = editor.getRootElement();
17100
- let observer = null;
17101
- if (rootElement) {
17102
- observer = new MutationObserver(() => {
17103
- reapplyHeaderStyles();
17104
- });
17105
- observer.observe(rootElement, {
17106
- childList: true,
17107
- subtree: true,
17108
- attributes: true,
17109
- attributeFilter: ["style", "width"]
17110
- });
17111
- }
17112
- return () => {
17113
- removeUpdateListener();
17114
- observer == null ? void 0 : observer.disconnect();
17115
- };
17116
- }, [editor]);
17117
- const onAddTable = () => {
17118
- const rowCount = Number(rows);
17119
- const colCount = Number(columns);
17120
- if (!rowCount || !colCount)
17121
- return;
17122
- editor.update(() => {
17263
+ }
17123
17264
  const tableNode = $createTableNodeWithDimensions(
17124
17265
  rowCount,
17125
17266
  colCount,
17126
17267
  false
17268
+ // Don't use built-in headers, we'll set them manually
17127
17269
  );
17128
- if (includeHeaders) {
17129
- const rowsNodes = tableNode.getChildren();
17130
- const headerRow = rowsNodes[0];
17131
- if (headerRow) {
17132
- const cells = headerRow.getChildren();
17133
- for (let i2 = 0; i2 < cells.length; i2++) {
17134
- const headingText = (columnHeadings[i2] || "").trim();
17135
- const cellNode = cells[i2];
17136
- cellNode.clear();
17137
- if (headingText) {
17138
- cellNode.append($createTextNode(headingText));
17139
- }
17270
+ const rowsNodes = tableNode.getChildren();
17271
+ const headerRow = rowsNodes[0];
17272
+ if ($isTableRowNode(headerRow)) {
17273
+ const cells = headerRow.getChildren();
17274
+ for (let i2 = 0; i2 < cells.length; i2++) {
17275
+ const cellNode = cells[i2];
17276
+ if ($isTableCellNode(cellNode)) {
17140
17277
  cellNode.setHeaderStyles(TableCellHeaderStates.COLUMN);
17278
+ cellNode.setBackgroundColor(headerColor);
17279
+ const textNode = $createTextNode("​");
17280
+ cellNode.append(textNode);
17141
17281
  }
17142
17282
  }
17143
17283
  }
17144
- $insertNodeToNearestRoot(tableNode);
17145
- });
17146
- if (includeHeaders) {
17147
- requestAnimationFrame(() => {
17148
- const applyTextStyles = () => {
17149
- const rootElement = editor.getRootElement();
17150
- if (!rootElement)
17151
- return false;
17152
- const tables = rootElement.querySelectorAll("table");
17153
- if (tables.length > 0) {
17154
- const latestTable = tables[tables.length - 1];
17155
- const rows2 = latestTable.querySelectorAll("tr");
17156
- if (rows2.length > 0) {
17157
- const firstRow = rows2[0];
17158
- const cells = firstRow.querySelectorAll("th, td");
17159
- cells.forEach((cell) => {
17160
- const htmlCell = cell;
17161
- const textColor = getContrastColor(headerColor);
17162
- htmlCell.setAttribute("data-header-color", headerColor);
17163
- htmlCell.setAttribute("data-text-color", textColor);
17164
- htmlCell.style.setProperty(
17165
- "background-color",
17166
- headerColor,
17167
- "important"
17168
- );
17169
- htmlCell.style.setProperty("color", textColor, "important");
17170
- htmlCell.style.setProperty("padding", "8px", "important");
17171
- htmlCell.style.setProperty(
17172
- "border",
17173
- "1px solid #ddd",
17174
- "important"
17175
- );
17176
- htmlCell.style.setProperty("font-weight", "bold", "important");
17177
- htmlCell.style.setProperty(
17178
- "white-space",
17179
- "nowrap",
17180
- "important"
17181
- );
17182
- });
17183
- return true;
17184
- }
17185
- }
17186
- return false;
17187
- };
17188
- if (!applyTextStyles()) {
17189
- setTimeout(() => {
17190
- applyTextStyles();
17191
- }, 100);
17284
+ if (shouldReplaceCurrentNode && $isRangeSelection(selection)) {
17285
+ try {
17286
+ const anchorNode = selection.anchor.getNode();
17287
+ const element = anchorNode.getTopLevelElementOrThrow();
17288
+ element.replace(tableNode);
17289
+ } catch (error) {
17290
+ $insertNodeToNearestRoot(tableNode);
17192
17291
  }
17193
- });
17194
- }
17195
- setRows("");
17196
- setColumns("");
17197
- setIncludeHeaders(false);
17198
- setColumnHeadings([]);
17199
- setHeaderColor("#4A90E2");
17200
- setIsOpen(false);
17201
- };
17202
- return /* @__PURE__ */ jsxs(Fragment, { children: [
17203
- /* @__PURE__ */ jsx(Dialog, { open: isOpen, onOpenChange: setIsOpen, children: /* @__PURE__ */ jsxs(DialogContent, { children: [
17204
- /* @__PURE__ */ jsx(DialogHeader, { children: /* @__PURE__ */ jsx(DialogTitle, { children: "Add Table" }) }),
17205
- /* @__PURE__ */ jsxs("div", { className: "cteditor-grid cteditor-gap-4 cteditor-py-4", children: [
17206
- /* @__PURE__ */ jsxs("div", { className: "cteditor-grid cteditor-gap-2", children: [
17207
- /* @__PURE__ */ jsx(Label$2, { htmlFor: "rows", children: "Rows" }),
17208
- /* @__PURE__ */ jsx(
17209
- Input$1,
17210
- {
17211
- id: "rows",
17212
- type: "number",
17213
- value: rows,
17214
- onChange: (e) => setRows(e.target.value),
17215
- autoFocus: true
17216
- }
17217
- )
17218
- ] }),
17219
- /* @__PURE__ */ jsxs("div", { className: "cteditor-grid cteditor-gap-2", children: [
17220
- /* @__PURE__ */ jsx(Label$2, { htmlFor: "columns", children: "Columns" }),
17221
- /* @__PURE__ */ jsx(
17222
- Input$1,
17223
- {
17224
- id: "columns",
17225
- type: "number",
17226
- value: columns,
17227
- onChange: (e) => {
17228
- const value = e.target.value;
17229
- setColumns(value);
17230
- const count2 = Number(value);
17231
- if (!Number.isNaN(count2) && includeHeaders) {
17232
- setColumnHeadings((prev) => {
17233
- const next = [...prev];
17234
- next.length = Math.max(0, count2);
17235
- for (let i2 = 0; i2 < count2; i2++) {
17236
- if (typeof next[i2] !== "string")
17237
- next[i2] = "";
17238
- }
17239
- return next;
17240
- });
17241
- }
17242
- }
17243
- }
17244
- )
17245
- ] }),
17246
- /* @__PURE__ */ jsx("div", { className: "cteditor-flex cteditor-items-center cteditor-gap-2", children: /* @__PURE__ */ jsxs(
17247
- "label",
17248
- {
17249
- htmlFor: "include-headers",
17250
- className: "cteditor-flex cteditor-items-center cteditor-space-x-2 cteditor-cursor-pointer cteditor-select-none",
17251
- children: [
17252
- /* @__PURE__ */ jsxs("div", { className: "cteditor-relative cteditor-h-5", children: [
17253
- /* @__PURE__ */ jsx(
17254
- "input",
17255
- {
17256
- id: "include-headers",
17257
- type: "checkbox",
17258
- checked: includeHeaders,
17259
- onChange: (e) => {
17260
- const checked = e.target.checked;
17261
- setIncludeHeaders(checked);
17262
- const count2 = Number(columns);
17263
- if (checked && count2 > 0) {
17264
- setColumnHeadings((prev) => {
17265
- const next = [...prev];
17266
- next.length = count2;
17267
- for (let i2 = 0; i2 < count2; i2++) {
17268
- if (typeof next[i2] !== "string")
17269
- next[i2] = "";
17270
- }
17271
- return next;
17272
- });
17273
- }
17274
- if (!checked) {
17275
- setColumnHeadings([]);
17276
- }
17277
- },
17278
- className: "\n cteditor-peer\n cteditor-appearance-none\n cteditor-w-5 cteditor-h-5\n cteditor-border cteditor-border-gray-400 cteditor-rounded\n cteditor-transition-all cteditor-duration-200\n checked:cteditor-bg-blue-600 checked:cteditor-border-blue-600\n hover:cteditor-border-blue-500 [&>span]:checked:cteditor-opacity-100\n \n "
17279
- }
17280
- ),
17281
- /* @__PURE__ */ jsx("span", { className: "cteditor-absolute cteditor-top-1/2 cteditor-left-1/2 [&>svg]:cteditor-size-4 -cteditor-translate-x-1/2 -cteditor-translate-y-1/2 cteditor-opacity-0 peer-checked:cteditor-opacity-100", children: /* @__PURE__ */ jsx(CheckIcon, {}) })
17282
- ] }),
17283
- /* @__PURE__ */ jsx("span", { className: "cteditor-text-sm cteditor-font-medium ", children: "Add column headers" })
17284
- ]
17285
- }
17286
- ) }),
17287
- includeHeaders && Number(columns) > 0 && /* @__PURE__ */ jsxs(Fragment, { children: [
17288
- /* @__PURE__ */ jsxs("div", { className: "cteditor-grid cteditor-gap-2 cteditor-space-y-1", children: [
17289
- /* @__PURE__ */ jsx(Label$2, { children: "Header titles" }),
17290
- /* @__PURE__ */ jsx(
17291
- "div",
17292
- {
17293
- className: "cteditor-grid cteditor-gap-2",
17294
- style: { gridTemplateColumns: "repeat(2, minmax(0, 1fr))" },
17295
- children: Array.from({ length: Number(columns) }).map((_, i2) => /* @__PURE__ */ jsxs("div", { className: "cteditor-grid cteditor-gap-1", children: [
17296
- /* @__PURE__ */ jsxs(
17297
- Label$2,
17298
- {
17299
- className: "cteditor-font-normal",
17300
- htmlFor: `col-heading-${i2}`,
17301
- children: [
17302
- "Column ",
17303
- i2 + 1
17304
- ]
17305
- }
17306
- ),
17307
- /* @__PURE__ */ jsx(
17308
- Input$1,
17309
- {
17310
- id: `col-heading-${i2}`,
17311
- type: "text",
17312
- value: columnHeadings[i2] ?? "",
17313
- onChange: (e) => {
17314
- const value = e.target.value;
17315
- setColumnHeadings((prev) => {
17316
- const next = [...prev];
17317
- next[i2] = value;
17318
- return next;
17319
- });
17320
- }
17321
- }
17322
- )
17323
- ] }, i2))
17324
- }
17325
- )
17326
- ] }),
17327
- /* @__PURE__ */ jsxs("div", { className: "cteditor-grid cteditor-gap-2", children: [
17328
- /* @__PURE__ */ jsx(Label$2, { htmlFor: "header-color", children: "Header color" }),
17329
- /* @__PURE__ */ jsxs("div", { className: "cteditor-flex cteditor-items-center cteditor-gap-3", children: [
17330
- /* @__PURE__ */ jsx("div", { className: "cteditor-size-9 cteditor-rounded-md cteditor-relative cteditor-overflow-hidden", children: /* @__PURE__ */ jsx(
17331
- "input",
17332
- {
17333
- id: "header-color",
17334
- type: "color",
17335
- value: headerColor,
17336
- onChange: (e) => setHeaderColor(e.target.value),
17337
- className: "cteditor-w-12 cteditor-h-10 cteditor-border cteditor-border-gray-300 cteditor-rounded cteditor-cursor-pointer cteditor-scale-150"
17338
- }
17339
- ) }),
17340
- /* @__PURE__ */ jsx("div", { className: "cteditor-flex cteditor-items-center cteditor-gap-2", children: /* @__PURE__ */ jsx("span", { className: "cteditor-text-sm ", children: headerColor }) })
17341
- ] })
17342
- ] })
17343
- ] })
17344
- ] }),
17345
- /* @__PURE__ */ jsxs(DialogFooter, { children: [
17346
- /* @__PURE__ */ jsx(Button, { variant: "outline", onClick: () => setIsOpen(false), children: "Cancel" }),
17347
- /* @__PURE__ */ jsx(Button, { onClick: onAddTable, disabled: !rows || !columns, children: "Add" })
17348
- ] })
17349
- ] }) }),
17350
- /* @__PURE__ */ jsx(Button, { variant: "ghost", onClick: () => setIsOpen(true), size: "icon-sm", children: /* @__PURE__ */ jsx("span", { className: "[&_svg]:!cteditor-size-4", children: /* @__PURE__ */ jsx(PerspectiveIcon, {}) }) })
17351
- ] });
17292
+ } else {
17293
+ $insertNodeToNearestRoot(tableNode);
17294
+ }
17295
+ if ($isTableRowNode(headerRow)) {
17296
+ const cells = headerRow.getChildren();
17297
+ if (cells.length > 0 && $isTableCellNode(cells[0])) {
17298
+ cells[0].selectStart();
17299
+ }
17300
+ }
17301
+ });
17302
+ }, [editor]);
17303
+ useEffect$1(() => {
17304
+ return editor.registerCommand(
17305
+ CREATE_TABLE_COMMAND,
17306
+ () => {
17307
+ createInstantTable();
17308
+ return true;
17309
+ },
17310
+ COMMAND_PRIORITY_EDITOR
17311
+ );
17312
+ }, [editor, createInstantTable]);
17313
+ return /* @__PURE__ */ jsx(Button, { variant: "ghost", onClick: createInstantTable, size: "icon-sm", children: /* @__PURE__ */ jsx("span", { className: "[&_svg]:!cteditor-size-4", children: /* @__PURE__ */ jsx(PerspectiveIcon, {}) }) });
17352
17314
  }
17353
17315
  createCommand();
17354
17316
  const INSERT_TRANSCRIPT_COMMAND = createCommand();
@@ -17868,10 +17830,10 @@ const PDF_CONFIG = {
17868
17830
  };
17869
17831
  const loadHtml2Pdf = async () => {
17870
17832
  try {
17871
- const mod = await import("./html2pdf.bundle.min-5e51c303.js").then((n) => n.h);
17833
+ const mod = await import("./html2pdf.bundle.min-b3120e0c.js").then((n) => n.h);
17872
17834
  return (mod == null ? void 0 : mod.default) || mod;
17873
17835
  } catch {
17874
- const mod2 = await import("./html2pdf.bundle-9236a762.js").then((n) => n.h);
17836
+ const mod2 = await import("./html2pdf.bundle-6d32d085.js").then((n) => n.h);
17875
17837
  return (mod2 == null ? void 0 : mod2.default) || mod2;
17876
17838
  }
17877
17839
  };
@@ -22220,32 +22182,6 @@ const HighlightColorPicker = ({
22220
22182
  )
22221
22183
  ] });
22222
22184
  };
22223
- const INSERT_IMAGE_COMMAND = createCommand("INSERT_IMAGE_COMMAND");
22224
- const ImagePlugin = ({
22225
- captionsEnabled
22226
- }) => {
22227
- const [editor] = useLexicalComposerContext();
22228
- useEffect$1(() => {
22229
- if (!editor.hasNodes([ImageNode])) {
22230
- throw new Error("ImagesPlugin: ImageNode not registered on editor");
22231
- }
22232
- return mergeRegister(
22233
- editor.registerCommand(
22234
- INSERT_IMAGE_COMMAND,
22235
- (payload) => {
22236
- const imageNode = $createImageNode(payload);
22237
- $insertNodes([imageNode]);
22238
- if ($isRootOrShadowRoot(imageNode.getParentOrThrow())) {
22239
- $wrapNodeInElement(imageNode, $createParagraphNode).selectEnd();
22240
- }
22241
- return true;
22242
- },
22243
- COMMAND_PRIORITY_EDITOR
22244
- )
22245
- );
22246
- }, [captionsEnabled, editor]);
22247
- return null;
22248
- };
22249
22185
  const useS3Uploader = (apiKey) => {
22250
22186
  const [uploadState, setUploadState] = useState$1({
22251
22187
  progress: 0,
@@ -24064,6 +24000,7 @@ const Toolbar = ({
24064
24000
  const contentRef = useRef(null);
24065
24001
  const [hiddenItemIds, setHiddenItemIds] = useState$1(/* @__PURE__ */ new Set());
24066
24002
  const [isImageDialogOpen, setIsImageDialogOpen] = useState$1(false);
24003
+ const [isFeatureSuggestionDialogOpen, setIsFeatureSuggestionDialogOpen] = useState$1(false);
24067
24004
  const classes = useStyles$1();
24068
24005
  const { hasFormat, isEditorEmpty, blockType, clearFormatting } = useEditorToolbar();
24069
24006
  const { clearEditorContent } = useCustomCommands();
@@ -25354,7 +25291,24 @@ const Toolbar = ({
25354
25291
  ] }) })
25355
25292
  ]
25356
25293
  }
25357
- )
25294
+ ),
25295
+ /* @__PURE__ */ jsx(TooltipProvider, { delayDuration: 200, children: /* @__PURE__ */ jsxs(Tooltip, { children: [
25296
+ /* @__PURE__ */ jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxs(
25297
+ Button,
25298
+ {
25299
+ "data-toolbar-item": "suggestFeature",
25300
+ variant: "ghost",
25301
+ size: "sm",
25302
+ onClick: () => setIsFeatureSuggestionDialogOpen(true),
25303
+ className: "cteditor-relative",
25304
+ children: [
25305
+ /* @__PURE__ */ jsx(Lightbulb, { className: "!cteditor-size-4" }),
25306
+ /* @__PURE__ */ jsx("span", {})
25307
+ ]
25308
+ }
25309
+ ) }),
25310
+ /* @__PURE__ */ jsx(TooltipContent, { children: /* @__PURE__ */ jsx("p", { children: "Suggest a Feature" }) })
25311
+ ] }) })
25358
25312
  ]
25359
25313
  }
25360
25314
  ),
@@ -25364,6 +25318,13 @@ const Toolbar = ({
25364
25318
  activeEditor,
25365
25319
  onClose: closeImageDialog
25366
25320
  }
25321
+ ),
25322
+ /* @__PURE__ */ jsx(
25323
+ FeatureSuggestionDialog,
25324
+ {
25325
+ open: isFeatureSuggestionDialogOpen,
25326
+ onOpenChange: setIsFeatureSuggestionDialogOpen
25327
+ }
25367
25328
  )
25368
25329
  ] });
25369
25330
  };
@@ -27485,7 +27446,7 @@ const EmbedPreviewPlugin = ({
27485
27446
  }, [editor]);
27486
27447
  return /* @__PURE__ */ jsx(Fragment, { children: /* @__PURE__ */ jsx(FloatingEmbedMenuPlugin, { anchorElem: floatingAnchorElem }) });
27487
27448
  };
27488
- const index$4 = "";
27449
+ const index$5 = "";
27489
27450
  function getDOMRangeRect(nativeSelection, rootElement) {
27490
27451
  const domRange = nativeSelection.getRangeAt(0);
27491
27452
  let rect;
@@ -27923,7 +27884,7 @@ function FloatingEnhanceButtonPlugin({
27923
27884
  anchorElem
27924
27885
  );
27925
27886
  }
27926
- const index$3 = "";
27887
+ const index$4 = "";
27927
27888
  const VERTICAL_GAP$1 = 10;
27928
27889
  const HORIZONTAL_OFFSET$1 = 5;
27929
27890
  function setFloatingElemPositionForLinkEditor(targetRect, floatingElem, anchorElem, verticalGap = VERTICAL_GAP$1, horizontalOffset = HORIZONTAL_OFFSET$1) {
@@ -27996,7 +27957,7 @@ function FloatingLinkEditor({
27996
27957
  return;
27997
27958
  }
27998
27959
  const rootElement = editor.getRootElement();
27999
- const isCreatingNewLink = isLinkEditMode && linkUrl === "https://";
27960
+ const isInEditMode = isLinkEditMode;
28000
27961
  if (selection !== null && nativeSelection !== null && rootElement !== null && rootElement.contains(nativeSelection.anchorNode) && editor.isEditable()) {
28001
27962
  const domRect = (_b = (_a = nativeSelection.focusNode) == null ? void 0 : _a.parentElement) == null ? void 0 : _b.getBoundingClientRect();
28002
27963
  if (domRect) {
@@ -28005,7 +27966,7 @@ function FloatingLinkEditor({
28005
27966
  }
28006
27967
  setLastSelection(selection);
28007
27968
  } else if (!activeElement || activeElement.className !== "link-input") {
28008
- if (!isCreatingNewLink) {
27969
+ if (!isInEditMode) {
28009
27970
  if (rootElement !== null) {
28010
27971
  setFloatingElemPositionForLinkEditor(null, editorElem, anchorElem);
28011
27972
  }
@@ -28135,7 +28096,7 @@ function FloatingLinkEditor({
28135
28096
  "div",
28136
28097
  {
28137
28098
  ref: editorRef,
28138
- className: "link-editor cteditor-border cteditor-border-background/20 cteditor-rounded-md cteditor-shadow-2xl cteditor-overflow-hidden cteditor-backdrop-blur-sm",
28099
+ className: "link-editor cteditor-bg-white cteditor-border cteditor-border-gray-200 cteditor-rounded-md cteditor-shadow-2xl cteditor-overflow-hidden",
28139
28100
  children: shouldShowEditMode ? (
28140
28101
  // EDIT MODE - Input to edit URL
28141
28102
  /* @__PURE__ */ jsxs("div", { className: "cteditor-flex cteditor-items-center cteditor-gap-2 cteditor-p-1 cteditor-w-full", children: [
@@ -28143,7 +28104,7 @@ function FloatingLinkEditor({
28143
28104
  "input",
28144
28105
  {
28145
28106
  ref: inputRef,
28146
- className: "link-input cteditor-w-full cteditor-px-4 cteditor-py-2.5 cteditor-text-sm cteditor-border cteditor-border-background/20 cteditor-rounded-md cteditor-bg-transparent cteditor-transition-all cteditor-duration-200 cteditor-text-background placeholder:cteditor-text-background cteditor-font-medium cteditor-outline-background/30",
28107
+ className: "link-input cteditor-w-full cteditor-px-4 cteditor-py-2.5 cteditor-text-sm cteditor-border cteditor-border-gray-300 cteditor-rounded-md cteditor-bg-white cteditor-transition-all cteditor-duration-200 cteditor-text-gray-900 placeholder:cteditor-text-gray-500 cteditor-font-medium focus:cteditor-outline-none focus:cteditor-ring-2 focus:cteditor-ring-blue-500",
28147
28108
  value: editedLinkUrl,
28148
28109
  placeholder: "Enter URL (e.g., https://example.com)",
28149
28110
  onChange: (event) => setEditedLinkUrl(event.target.value),
@@ -28166,7 +28127,7 @@ function FloatingLinkEditor({
28166
28127
  /* @__PURE__ */ jsx(
28167
28128
  "button",
28168
28129
  {
28169
- className: "cteditor-p-2.5 cteditor-rounded-lg cteditor-bg-background hover:cteditor-bg-background/80 cteditor-text-foreground hover:cteditor-text-foreground cteditor-transition-all cteditor-duration-200 hover:cteditor-scale-105 active:cteditor-scale-95",
28130
+ className: "cteditor-p-2.5 cteditor-rounded-lg cteditor-bg-green-500 hover:cteditor-bg-green-600 cteditor-text-white cteditor-transition-all cteditor-duration-200 hover:cteditor-scale-105 active:cteditor-scale-95",
28170
28131
  onClick: handleLinkSubmission,
28171
28132
  title: "Save link",
28172
28133
  children: /* @__PURE__ */ jsx(Check, { className: "cteditor-size-4" })
@@ -28175,7 +28136,7 @@ function FloatingLinkEditor({
28175
28136
  /* @__PURE__ */ jsx(
28176
28137
  "button",
28177
28138
  {
28178
- className: "cteditor-p-2.5 cteditor-rounded-lg cteditor-bg-background hover:cteditor-bg-background/80 cteditor-text-foreground hover:cteditor-text-foreground cteditor-transition-all cteditor-duration-200 hover:cteditor-scale-105 active:cteditor-scale-95",
28139
+ className: "cteditor-p-2.5 cteditor-rounded-lg cteditor-bg-gray-200 hover:cteditor-bg-gray-300 cteditor-text-gray-700 cteditor-transition-all cteditor-duration-200 hover:cteditor-scale-105 active:cteditor-scale-95",
28179
28140
  onClick: () => {
28180
28141
  if (linkUrl === "https://") {
28181
28142
  editor.dispatchCommand(TOGGLE_LINK_COMMAND, null);
@@ -28192,15 +28153,15 @@ function FloatingLinkEditor({
28192
28153
  ) : showUrlView ? (
28193
28154
  // URL VIEW - Shows URL with edit and delete buttons
28194
28155
  /* @__PURE__ */ jsxs("div", { className: "cteditor-p-3 cteditor-space-y-2", children: [
28195
- /* @__PURE__ */ jsx("div", { className: "cteditor-flex cteditor-items-center cteditor-gap-2", children: /* @__PURE__ */ jsxs("div", { className: "cteditor-flex-1 cteditor-flex cteditor-items-center cteditor-gap-2 cteditor-px-3 cteditor-py-2 cteditor-bg-accent/30 cteditor-rounded-lg cteditor-border cteditor-border-border/30", children: [
28196
- /* @__PURE__ */ jsx(ExternalLink, { className: "cteditor-size-3.5 cteditor-text-primary cteditor-flex-shrink-0" }),
28156
+ /* @__PURE__ */ jsx("div", { className: "cteditor-flex cteditor-items-center cteditor-gap-2", children: /* @__PURE__ */ jsxs("div", { className: "cteditor-flex-1 cteditor-flex cteditor-items-center cteditor-gap-2 cteditor-px-3 cteditor-py-2 cteditor-bg-blue-50 cteditor-rounded-lg cteditor-border cteditor-border-blue-200", children: [
28157
+ /* @__PURE__ */ jsx(ExternalLink, { className: "cteditor-size-3.5 cteditor-text-blue-600 cteditor-flex-shrink-0" }),
28197
28158
  /* @__PURE__ */ jsx(
28198
28159
  "a",
28199
28160
  {
28200
28161
  href: sanitizeUrl(linkUrl),
28201
28162
  target: "_blank",
28202
28163
  rel: "noopener noreferrer",
28203
- className: "cteditor-flex-1 cteditor-text-xs cteditor-text-primary hover:cteditor-text-primary/80 cteditor-font-medium cteditor-truncate cteditor-transition-colors cteditor-no-underline",
28164
+ className: "cteditor-flex-1 cteditor-text-xs cteditor-text-blue-600 hover:cteditor-text-blue-800 cteditor-font-medium cteditor-truncate cteditor-transition-colors cteditor-no-underline",
28204
28165
  title: linkUrl,
28205
28166
  children: linkUrl
28206
28167
  }
@@ -28210,8 +28171,14 @@ function FloatingLinkEditor({
28210
28171
  /* @__PURE__ */ jsxs(
28211
28172
  "button",
28212
28173
  {
28213
- className: "cteditor-flex-1 cteditor-px-3 cteditor-py-2 cteditor-rounded-lg cteditor-bg-primary/10 hover:cteditor-bg-primary hover:cteditor-text-primary-foreground cteditor-text-primary cteditor-text-xs cteditor-font-medium cteditor-transition-all cteditor-duration-200 hover:cteditor-scale-[1.02] active:cteditor-scale-95 cteditor-flex cteditor-items-center cteditor-justify-center cteditor-gap-1.5",
28214
- onClick: () => {
28174
+ className: "cteditor-flex-1 cteditor-px-3 cteditor-py-2 cteditor-rounded-lg cteditor-bg-blue-100 hover:cteditor-bg-blue-600 hover:cteditor-text-white cteditor-text-blue-700 cteditor-text-xs cteditor-font-medium cteditor-transition-all cteditor-duration-200 hover:cteditor-scale-[1.02] active:cteditor-scale-95 cteditor-flex cteditor-items-center cteditor-justify-center cteditor-gap-1.5",
28175
+ onMouseDown: (e) => {
28176
+ e.preventDefault();
28177
+ e.stopPropagation();
28178
+ },
28179
+ onClick: (e) => {
28180
+ e.preventDefault();
28181
+ e.stopPropagation();
28215
28182
  setEditedLinkUrl(linkUrl);
28216
28183
  setIsLinkEditMode(true);
28217
28184
  setShowUrlView(false);
@@ -28226,8 +28193,14 @@ function FloatingLinkEditor({
28226
28193
  /* @__PURE__ */ jsxs(
28227
28194
  "button",
28228
28195
  {
28229
- className: "cteditor-flex-1 cteditor-px-3 cteditor-py-2 cteditor-rounded-lg cteditor-bg-destructive/10 hover:cteditor-bg-destructive hover:cteditor-text-destructive-foreground cteditor-text-destructive cteditor-text-xs cteditor-font-medium cteditor-transition-all cteditor-duration-200 hover:cteditor-scale-[1.02] active:cteditor-scale-95 cteditor-flex cteditor-items-center cteditor-justify-center cteditor-gap-1.5",
28230
- onClick: () => {
28196
+ className: "cteditor-flex-1 cteditor-px-3 cteditor-py-2 cteditor-rounded-lg cteditor-bg-red-100 hover:cteditor-bg-red-600 hover:cteditor-text-white cteditor-text-red-700 cteditor-text-xs cteditor-font-medium cteditor-transition-all cteditor-duration-200 hover:cteditor-scale-[1.02] active:cteditor-scale-95 cteditor-flex cteditor-items-center cteditor-justify-center cteditor-gap-1.5",
28197
+ onMouseDown: (e) => {
28198
+ e.preventDefault();
28199
+ e.stopPropagation();
28200
+ },
28201
+ onClick: (e) => {
28202
+ e.preventDefault();
28203
+ e.stopPropagation();
28231
28204
  editor.dispatchCommand(TOGGLE_LINK_COMMAND, null);
28232
28205
  setShowUrlView(false);
28233
28206
  },
@@ -28245,13 +28218,21 @@ function FloatingLinkEditor({
28245
28218
  /* @__PURE__ */ jsxs(
28246
28219
  "button",
28247
28220
  {
28248
- className: "cteditor-w-full cteditor-px-4 cteditor-py-2.5 cteditor-text-sm cteditor-text-foreground cteditor-font-medium cteditor-truncate cteditor-transition-all cteditor-duration-200 hover:cteditor-bg-accent/50 cteditor-text-left cteditor-flex cteditor-items-center cteditor-gap-2 cteditor-group",
28249
- onClick: () => setShowUrlView(true),
28221
+ className: "cteditor-w-full cteditor-px-4 cteditor-py-2.5 cteditor-text-sm cteditor-text-gray-900 cteditor-font-medium cteditor-truncate cteditor-transition-all cteditor-duration-200 hover:cteditor-bg-gray-100 cteditor-text-left cteditor-flex cteditor-items-center cteditor-gap-2 cteditor-group",
28222
+ onMouseDown: (e) => {
28223
+ e.preventDefault();
28224
+ e.stopPropagation();
28225
+ },
28226
+ onClick: (e) => {
28227
+ e.preventDefault();
28228
+ e.stopPropagation();
28229
+ setShowUrlView(true);
28230
+ },
28250
28231
  title: "Click to view URL and options",
28251
28232
  children: [
28252
- /* @__PURE__ */ jsx(ExternalLink, { className: "cteditor-size-3.5 cteditor-text-muted-foreground group-hover:cteditor-text-primary cteditor-transition-colors cteditor-flex-shrink-0" }),
28233
+ /* @__PURE__ */ jsx(ExternalLink, { className: "cteditor-size-3.5 cteditor-text-gray-500 group-hover:cteditor-text-blue-600 cteditor-transition-colors cteditor-flex-shrink-0" }),
28253
28234
  /* @__PURE__ */ jsx("span", { className: "cteditor-truncate", children: linkText || "Link" }),
28254
- /* @__PURE__ */ jsx("span", { className: "cteditor-ml-auto cteditor-text-xs cteditor-text-muted-foreground group-hover:cteditor-text-foreground cteditor-transition-colors", children: "Click to view" })
28235
+ /* @__PURE__ */ jsx("span", { className: "cteditor-ml-auto cteditor-text-xs cteditor-text-gray-500 group-hover:cteditor-text-gray-700 cteditor-transition-colors", children: "Click to view" })
28255
28236
  ]
28256
28237
  }
28257
28238
  )
@@ -28349,7 +28330,7 @@ function FloatingLinkEditorPlugin({
28349
28330
  setIsLinkEditMode
28350
28331
  );
28351
28332
  }
28352
- const index$2 = "";
28333
+ const index$3 = "";
28353
28334
  const VERTICAL_GAP = 10;
28354
28335
  const HORIZONTAL_OFFSET = 5;
28355
28336
  function setFloatingElemPosition(targetRect, floatingElem, anchorElem, isLink = false, verticalGap = VERTICAL_GAP, horizontalOffset = HORIZONTAL_OFFSET, isEmbed = false) {
@@ -28901,86 +28882,376 @@ function LinkPlugin({
28901
28882
  }
28902
28883
  );
28903
28884
  }
28904
- const debounce = (fn, delay) => {
28905
- let timeoutID;
28906
- return function(...args) {
28907
- clearTimeout(timeoutID);
28908
- timeoutID = window.setTimeout(() => fn.apply(this, args), delay);
28909
- };
28910
- };
28911
- const LocalStoragePlugin = ({ namespace }) => {
28885
+ function LinkPreviewPlugin() {
28912
28886
  const [editor] = useLexicalComposerContext();
28913
- const saveContent = useCallback(
28914
- (content) => {
28915
- localStorage.setItem(namespace, content);
28916
- },
28917
- [namespace]
28918
- );
28919
- const debouncedSaveContent = debounce(saveContent, 500);
28920
- useEffect$1(() => {
28921
- return editor.registerUpdateListener(
28922
- ({ editorState, dirtyElements, dirtyLeaves }) => {
28923
- if (dirtyElements.size === 0 && dirtyLeaves.size === 0)
28924
- return;
28925
- const serializedState = JSON.stringify(editorState);
28926
- debouncedSaveContent(serializedState);
28927
- }
28928
- );
28929
- }, [debouncedSaveContent, editor]);
28930
- return null;
28931
- };
28932
- const LocalStoragePlugin$1 = LocalStoragePlugin;
28933
- const PUNCTUATION = `\\.,\\+\\*\\?\\$\\@\\|#{}\\(\\)\\^\\-\\[\\]\\\\/!%'"~=<>_:;`;
28934
- const NAME = "\\b[A-Z][^\\s" + PUNCTUATION + "]";
28935
- const DocumentMentionsRegex = {
28936
- NAME,
28937
- PUNCTUATION
28938
- };
28939
- const PUNC = DocumentMentionsRegex.PUNCTUATION;
28940
- const TRIGGERS = ["@"].join("");
28941
- const VALID_CHARS = "[^" + TRIGGERS + PUNC + "\\s]";
28942
- const VALID_JOINS = "(?:\\.[ |$]| |[" + PUNC + "]|)";
28943
- const LENGTH_LIMIT = 75;
28944
- const AtSignMentionsRegex = new RegExp(
28945
- "(^|\\s|\\()([" + TRIGGERS + "]((?:" + VALID_CHARS + VALID_JOINS + "){0," + LENGTH_LIMIT + "}))$"
28946
- );
28947
- const SUGGESTION_LIST_LENGTH_LIMIT = 5;
28948
- const mentionsCache = /* @__PURE__ */ new Map();
28949
- const userLookupService = {
28950
- search(userList, string, callback) {
28951
- setTimeout(() => {
28952
- const results = userList.filter(
28953
- (mention) => mention.toLowerCase().includes(string.toLowerCase())
28954
- );
28955
- callback(results);
28956
- }, 500);
28957
- }
28958
- };
28959
- function useMentionLookupService(userList = [], mentionString) {
28960
- const [results, setResults] = useState$1([]);
28887
+ const [hoveredLink, setHoveredLink] = useState$1(null);
28961
28888
  useEffect$1(() => {
28962
- const cachedResults = mentionsCache.get(mentionString);
28963
- if (mentionString == null) {
28964
- setResults([]);
28965
- return;
28966
- }
28967
- if (cachedResults === null) {
28968
- return;
28969
- } else if (cachedResults !== void 0) {
28970
- setResults(cachedResults);
28889
+ const editorElement = editor.getRootElement();
28890
+ if (!editorElement)
28971
28891
  return;
28972
- }
28973
- mentionsCache.set(mentionString, null);
28974
- userLookupService.search(userList, mentionString, (newResults) => {
28975
- mentionsCache.set(mentionString, newResults);
28976
- setResults(newResults);
28977
- });
28978
- }, [mentionString]);
28979
- return results;
28980
- }
28981
- function checkForAtSignMentions(text, minMatchLength) {
28982
- const match = AtSignMentionsRegex.exec(text);
28983
- if (match !== null) {
28892
+ let showTimeout = null;
28893
+ let hideTimeout = null;
28894
+ let isOverPreview = false;
28895
+ const handleMouseOver = (event) => {
28896
+ const target = event.target;
28897
+ if (target.closest(".link-preview-card")) {
28898
+ isOverPreview = true;
28899
+ if (hideTimeout) {
28900
+ clearTimeout(hideTimeout);
28901
+ hideTimeout = null;
28902
+ }
28903
+ return;
28904
+ }
28905
+ const linkElement = target.closest("a");
28906
+ if (linkElement) {
28907
+ const href = linkElement.getAttribute("href");
28908
+ if (href && href !== "https://" && href !== "http://" && href !== "#") {
28909
+ if (showTimeout) {
28910
+ clearTimeout(showTimeout);
28911
+ }
28912
+ if (hideTimeout) {
28913
+ clearTimeout(hideTimeout);
28914
+ hideTimeout = null;
28915
+ }
28916
+ showTimeout = window.setTimeout(() => {
28917
+ const rect = linkElement.getBoundingClientRect();
28918
+ setHoveredLink({
28919
+ url: href,
28920
+ text: linkElement.textContent || "",
28921
+ rect
28922
+ });
28923
+ }, 500);
28924
+ }
28925
+ }
28926
+ };
28927
+ const handleMouseOut = (event) => {
28928
+ const target = event.target;
28929
+ const relatedTarget = event.relatedTarget;
28930
+ if (target.closest(".link-preview-card")) {
28931
+ isOverPreview = false;
28932
+ const movingToLink = relatedTarget == null ? void 0 : relatedTarget.closest("a");
28933
+ if (!movingToLink) {
28934
+ hideTimeout = window.setTimeout(() => {
28935
+ if (!isOverPreview) {
28936
+ setHoveredLink(null);
28937
+ }
28938
+ }, 300);
28939
+ }
28940
+ return;
28941
+ }
28942
+ const linkElement = target.closest("a");
28943
+ if (linkElement) {
28944
+ if (showTimeout) {
28945
+ clearTimeout(showTimeout);
28946
+ showTimeout = null;
28947
+ }
28948
+ const movingToPreview = relatedTarget == null ? void 0 : relatedTarget.closest(".link-preview-card");
28949
+ if (!movingToPreview) {
28950
+ hideTimeout = window.setTimeout(() => {
28951
+ if (!isOverPreview) {
28952
+ setHoveredLink(null);
28953
+ }
28954
+ }, 300);
28955
+ }
28956
+ }
28957
+ };
28958
+ editorElement.addEventListener("mouseover", handleMouseOver);
28959
+ editorElement.addEventListener("mouseout", handleMouseOut);
28960
+ document.body.addEventListener("mouseover", handleMouseOver);
28961
+ document.body.addEventListener("mouseout", handleMouseOut);
28962
+ return () => {
28963
+ if (showTimeout) {
28964
+ clearTimeout(showTimeout);
28965
+ }
28966
+ if (hideTimeout) {
28967
+ clearTimeout(hideTimeout);
28968
+ }
28969
+ editorElement.removeEventListener("mouseover", handleMouseOver);
28970
+ editorElement.removeEventListener("mouseout", handleMouseOut);
28971
+ document.body.removeEventListener("mouseover", handleMouseOver);
28972
+ document.body.removeEventListener("mouseout", handleMouseOut);
28973
+ };
28974
+ }, [editor]);
28975
+ if (!hoveredLink) {
28976
+ return null;
28977
+ }
28978
+ return createPortal(
28979
+ /* @__PURE__ */ jsx(
28980
+ LinkPreview,
28981
+ {
28982
+ url: hoveredLink.url,
28983
+ rect: hoveredLink.rect,
28984
+ onClose: () => setHoveredLink(null)
28985
+ }
28986
+ ),
28987
+ document.body
28988
+ );
28989
+ }
28990
+ function LinkPreview({ url, rect, onClose }) {
28991
+ const [position, setPosition] = useState$1({ top: 0, left: 0 });
28992
+ useEffect$1(() => {
28993
+ const previewWidth = 300;
28994
+ const previewHeight = 120;
28995
+ let top = rect.top + window.scrollY - previewHeight - 10;
28996
+ if (rect.top - previewHeight - 10 < 0) {
28997
+ top = rect.bottom + window.scrollY + 10;
28998
+ }
28999
+ let left = rect.left + window.scrollX + rect.width / 2 - previewWidth / 2;
29000
+ const viewportWidth = window.innerWidth;
29001
+ if (left < 10) {
29002
+ left = 10;
29003
+ } else if (left + previewWidth > viewportWidth - 10) {
29004
+ left = viewportWidth - previewWidth - 10;
29005
+ }
29006
+ setPosition({ top, left });
29007
+ }, [rect]);
29008
+ const getDomain = (urlString) => {
29009
+ try {
29010
+ const urlObj = new URL(urlString);
29011
+ return urlObj.hostname.replace("www.", "");
29012
+ } catch {
29013
+ return urlString;
29014
+ }
29015
+ };
29016
+ const domain = getDomain(url);
29017
+ const getProtocol = (urlString) => {
29018
+ try {
29019
+ const urlObj = new URL(urlString);
29020
+ return urlObj.protocol.replace(":", "").toUpperCase();
29021
+ } catch {
29022
+ return "HTTPS";
29023
+ }
29024
+ };
29025
+ const protocol = getProtocol(url);
29026
+ return /* @__PURE__ */ jsxs(
29027
+ "div",
29028
+ {
29029
+ className: "link-preview-card",
29030
+ style: {
29031
+ position: "absolute",
29032
+ top: `${position.top}px`,
29033
+ left: `${position.left}px`,
29034
+ zIndex: 1e4,
29035
+ pointerEvents: "auto",
29036
+ animation: "fadeIn 0.2s ease-out"
29037
+ },
29038
+ children: [
29039
+ /* @__PURE__ */ jsxs(
29040
+ "div",
29041
+ {
29042
+ style: {
29043
+ width: "250px",
29044
+ backgroundColor: "#2d2d2d",
29045
+ borderRadius: "12px",
29046
+ boxShadow: "0 10px 40px rgba(0, 0, 0, 0.3)",
29047
+ overflow: "hidden",
29048
+ position: "relative"
29049
+ },
29050
+ children: [
29051
+ /* @__PURE__ */ jsx(
29052
+ "button",
29053
+ {
29054
+ onClick: (e) => {
29055
+ e.preventDefault();
29056
+ e.stopPropagation();
29057
+ onClose();
29058
+ },
29059
+ style: {
29060
+ position: "absolute",
29061
+ top: "8px",
29062
+ right: "8px",
29063
+ width: "20px",
29064
+ height: "20px",
29065
+ borderRadius: "4px",
29066
+ backgroundColor: "#404040",
29067
+ border: "none",
29068
+ cursor: "pointer",
29069
+ display: "flex",
29070
+ alignItems: "center",
29071
+ justifyContent: "center",
29072
+ transition: "background-color 0.2s",
29073
+ zIndex: 1
29074
+ },
29075
+ onMouseEnter: (e) => {
29076
+ e.currentTarget.style.backgroundColor = "#525252";
29077
+ },
29078
+ onMouseLeave: (e) => {
29079
+ e.currentTarget.style.backgroundColor = "#404040";
29080
+ },
29081
+ title: "Close preview",
29082
+ children: /* @__PURE__ */ jsx(
29083
+ "svg",
29084
+ {
29085
+ style: { width: "12px", height: "12px", color: "#9ca3af" },
29086
+ fill: "none",
29087
+ stroke: "currentColor",
29088
+ viewBox: "0 0 24 24",
29089
+ children: /* @__PURE__ */ jsx(
29090
+ "path",
29091
+ {
29092
+ strokeLinecap: "round",
29093
+ strokeLinejoin: "round",
29094
+ strokeWidth: 2,
29095
+ d: "M6 18L18 6M6 6l12 12"
29096
+ }
29097
+ )
29098
+ }
29099
+ )
29100
+ }
29101
+ ),
29102
+ /* @__PURE__ */ jsxs("div", { style: { padding: "16px 16px 12px 16px" }, children: [
29103
+ /* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", gap: "8px", marginBottom: "4px" }, children: [
29104
+ /* @__PURE__ */ jsx(
29105
+ "svg",
29106
+ {
29107
+ style: { width: "16px", height: "16px", color: "#ffffff" },
29108
+ fill: "none",
29109
+ stroke: "currentColor",
29110
+ viewBox: "0 0 24 24",
29111
+ children: /* @__PURE__ */ jsx(
29112
+ "path",
29113
+ {
29114
+ strokeLinecap: "round",
29115
+ strokeLinejoin: "round",
29116
+ strokeWidth: 2,
29117
+ d: "M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14"
29118
+ }
29119
+ )
29120
+ }
29121
+ ),
29122
+ /* @__PURE__ */ jsx("span", { style: { fontSize: "14px", fontWeight: "600", color: "#ffffff" }, children: domain })
29123
+ ] }),
29124
+ /* @__PURE__ */ jsx("p", { style: { fontSize: "10px", color: "#9ca3af", marginLeft: "24px" }, children: protocol })
29125
+ ] }),
29126
+ /* @__PURE__ */ jsxs("div", { style: { padding: "0 16px 16px 16px" }, children: [
29127
+ /* @__PURE__ */ jsx("p", { style: { fontSize: "10px", fontWeight: "500", color: "#9ca3af", textTransform: "uppercase", marginBottom: "8px" }, children: "LINK URL" }),
29128
+ /* @__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 }) })
29129
+ ] }),
29130
+ /* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", justifyContent: "center", gap: "8px", padding: "12px", borderTop: "1px solid #404040" }, children: [
29131
+ /* @__PURE__ */ jsx(
29132
+ "div",
29133
+ {
29134
+ style: {
29135
+ width: "8px",
29136
+ height: "8px",
29137
+ borderRadius: "50%",
29138
+ backgroundColor: "#10b981",
29139
+ boxShadow: "0 0 8px rgba(16, 185, 129, 0.6)",
29140
+ animation: "pulse 2s ease-in-out infinite"
29141
+ }
29142
+ }
29143
+ ),
29144
+ /* @__PURE__ */ jsx("span", { style: { fontSize: "10px", fontWeight: "500", color: "#a1a1aa" }, children: "Link Preview" })
29145
+ ] })
29146
+ ]
29147
+ }
29148
+ ),
29149
+ /* @__PURE__ */ jsx("style", { children: `
29150
+ @keyframes fadeIn {
29151
+ from {
29152
+ opacity: 0;
29153
+ transform: translateY(5px);
29154
+ }
29155
+ to {
29156
+ opacity: 1;
29157
+ transform: translateY(0);
29158
+ }
29159
+ }
29160
+
29161
+ @keyframes pulse {
29162
+ 0%, 100% {
29163
+ opacity: 1;
29164
+ }
29165
+ 50% {
29166
+ opacity: 0.6;
29167
+ }
29168
+ }
29169
+ ` })
29170
+ ]
29171
+ }
29172
+ );
29173
+ }
29174
+ const debounce = (fn, delay) => {
29175
+ let timeoutID;
29176
+ return function(...args) {
29177
+ clearTimeout(timeoutID);
29178
+ timeoutID = window.setTimeout(() => fn.apply(this, args), delay);
29179
+ };
29180
+ };
29181
+ const LocalStoragePlugin = ({ namespace }) => {
29182
+ const [editor] = useLexicalComposerContext();
29183
+ const saveContent = useCallback(
29184
+ (content) => {
29185
+ localStorage.setItem(namespace, content);
29186
+ },
29187
+ [namespace]
29188
+ );
29189
+ const debouncedSaveContent = debounce(saveContent, 500);
29190
+ useEffect$1(() => {
29191
+ return editor.registerUpdateListener(
29192
+ ({ editorState, dirtyElements, dirtyLeaves }) => {
29193
+ if (dirtyElements.size === 0 && dirtyLeaves.size === 0)
29194
+ return;
29195
+ const serializedState = JSON.stringify(editorState);
29196
+ debouncedSaveContent(serializedState);
29197
+ }
29198
+ );
29199
+ }, [debouncedSaveContent, editor]);
29200
+ return null;
29201
+ };
29202
+ const LocalStoragePlugin$1 = LocalStoragePlugin;
29203
+ const index$2 = "";
29204
+ const PUNCTUATION = `\\.,\\+\\*\\?\\$\\@\\|#{}\\(\\)\\^\\-\\[\\]\\\\/!%'"~=<>_:;`;
29205
+ const NAME = "\\b[A-Z][^\\s" + PUNCTUATION + "]";
29206
+ const DocumentMentionsRegex = {
29207
+ NAME,
29208
+ PUNCTUATION
29209
+ };
29210
+ const PUNC = DocumentMentionsRegex.PUNCTUATION;
29211
+ const TRIGGERS = ["@"].join("");
29212
+ const VALID_CHARS = "[^" + TRIGGERS + PUNC + "\\s]";
29213
+ const VALID_JOINS = "(?:\\.[ |$]| |[" + PUNC + "]|)";
29214
+ const LENGTH_LIMIT = 75;
29215
+ const AtSignMentionsRegex = new RegExp(
29216
+ "(^|\\s|\\()([" + TRIGGERS + "]((?:" + VALID_CHARS + VALID_JOINS + "){0," + LENGTH_LIMIT + "}))$"
29217
+ );
29218
+ const SUGGESTION_LIST_LENGTH_LIMIT = 5;
29219
+ const mentionsCache = /* @__PURE__ */ new Map();
29220
+ const userLookupService = {
29221
+ search(userList, string, callback) {
29222
+ setTimeout(() => {
29223
+ const results = userList.filter(
29224
+ (mention) => mention.toLowerCase().includes(string.toLowerCase())
29225
+ );
29226
+ callback(results);
29227
+ }, 500);
29228
+ }
29229
+ };
29230
+ function useMentionLookupService(userList = [], mentionString) {
29231
+ const [results, setResults] = useState$1([]);
29232
+ useEffect$1(() => {
29233
+ const cachedResults = mentionsCache.get(mentionString);
29234
+ if (mentionString == null) {
29235
+ setResults([]);
29236
+ return;
29237
+ }
29238
+ if (cachedResults === null) {
29239
+ return;
29240
+ } else if (cachedResults !== void 0) {
29241
+ setResults(cachedResults);
29242
+ return;
29243
+ }
29244
+ mentionsCache.set(mentionString, null);
29245
+ userLookupService.search(userList, mentionString, (newResults) => {
29246
+ mentionsCache.set(mentionString, newResults);
29247
+ setResults(newResults);
29248
+ });
29249
+ }, [mentionString]);
29250
+ return results;
29251
+ }
29252
+ function checkForAtSignMentions(text, minMatchLength) {
29253
+ const match = AtSignMentionsRegex.exec(text);
29254
+ if (match !== null) {
28984
29255
  const maybeLeadingWhitespace = match[1];
28985
29256
  const matchingString = match[3];
28986
29257
  if (matchingString.length >= minMatchLength) {
@@ -29499,7 +29770,7 @@ function SlashCommandPlugin() {
29499
29770
  });
29500
29771
  }, [makeBlock]);
29501
29772
  const insertTable = useCallback(() => {
29502
- editor.dispatchCommand(OPEN_TABLE_MODAL_COMMAND, void 0);
29773
+ editor.dispatchCommand(CREATE_TABLE_COMMAND, void 0);
29503
29774
  }, [editor]);
29504
29775
  const formatBold = useCallback(() => {
29505
29776
  editor.dispatchCommand(FORMAT_TEXT_COMMAND, "bold");
@@ -29553,9 +29824,6 @@ function SlashCommandPlugin() {
29553
29824
  const openAIChat = useCallback(() => {
29554
29825
  editor.dispatchCommand(TOGGLE_AI_CHAT_COMMAND, void 0);
29555
29826
  }, [editor]);
29556
- const aiGenerateImage = useCallback(() => {
29557
- editor.dispatchCommand(AI_IMAGE_COMMAND, void 0);
29558
- }, [editor]);
29559
29827
  const baseOptions = useMemo(() => {
29560
29828
  return [
29561
29829
  // Block types
@@ -29609,8 +29877,8 @@ function SlashCommandPlugin() {
29609
29877
  // AI features
29610
29878
  new SlashMenuOption("__label__AI", () => {
29611
29879
  }),
29612
- new SlashMenuOption("AI Chat", openAIChat),
29613
- new SlashMenuOption("AI Generate image", aiGenerateImage)
29880
+ new SlashMenuOption("AI Chat", openAIChat)
29881
+ // new SlashMenuOption("AI Generate image", aiGenerateImage),
29614
29882
  ];
29615
29883
  }, [
29616
29884
  insertParagraph,
@@ -29636,8 +29904,7 @@ function SlashCommandPlugin() {
29636
29904
  handleClearFormatting,
29637
29905
  handleClearContent,
29638
29906
  addComment,
29639
- openAIChat,
29640
- aiGenerateImage
29907
+ openAIChat
29641
29908
  ]);
29642
29909
  const options = useMemo(() => {
29643
29910
  const query = searchQuery || queryString || "";
@@ -30179,8 +30446,12 @@ function $canUnmerge() {
30179
30446
  if ($isRangeSelection(selection) && !selection.isCollapsed() || $isTableSelection(selection) && !selection.anchor.is(selection.focus) || !$isRangeSelection(selection) && !$isTableSelection(selection)) {
30180
30447
  return false;
30181
30448
  }
30182
- const [cell] = $getNodeTriplet(selection.anchor);
30183
- return cell.__colSpan > 1 || cell.__rowSpan > 1;
30449
+ try {
30450
+ const [cell] = $getNodeTriplet(selection.anchor);
30451
+ return cell.__colSpan > 1 || cell.__rowSpan > 1;
30452
+ } catch (error) {
30453
+ return false;
30454
+ }
30184
30455
  }
30185
30456
  function $cellContainsEmptyParagraph(cell) {
30186
30457
  if (cell.getChildrenSize() !== 1) {
@@ -30236,12 +30507,12 @@ function TableActionMenu({
30236
30507
  columns: 1,
30237
30508
  rows: 1
30238
30509
  });
30510
+ const [selectionType, setSelectionType] = useState$1(null);
30239
30511
  const [canMergeCells, setCanMergeCells] = useState$1(false);
30240
30512
  const [canUnmergeCell, setCanUnmergeCell] = useState$1(false);
30241
- const [backgroundColor, setBackgroundColor] = useState$1(
30242
- () => currentCellBackgroundColor(editor) || ""
30243
- );
30244
- const [stripingColor, setStripingColor] = useState$1("#f0f0f0");
30513
+ const [backgroundColor, setBackgroundColor] = useState$1("");
30514
+ const [stripingColor, setStripingColor] = useState$1("");
30515
+ const [isHeaderCell, setIsHeaderCell] = useState$1(false);
30245
30516
  useEffect$1(() => {
30246
30517
  updateTableCellNode(_tableCellNode);
30247
30518
  }, [_tableCellNode]);
@@ -30269,10 +30540,43 @@ function TableActionMenu({
30269
30540
  setCanMergeCells(
30270
30541
  currentSelectionCounts.columns > 1 || currentSelectionCounts.rows > 1
30271
30542
  );
30543
+ const anchorNode = $getTableCellNodeFromLexicalNode(selection.anchor.getNode());
30544
+ if (anchorNode) {
30545
+ const tableNode = $getTableNodeFromLexicalNodeOrThrow(anchorNode);
30546
+ const tableRowCount = tableNode.getChildrenSize();
30547
+ const firstRow = tableNode.getFirstChild();
30548
+ const tableColumnCount = firstRow && $isTableRowNode(firstRow) ? firstRow.getChildrenSize() : 0;
30549
+ const nodes = selection.getNodes();
30550
+ const hasHeaderCell = nodes.some((node) => {
30551
+ if ($isTableCellNode(node)) {
30552
+ return node.getHeaderStyles() !== 0;
30553
+ }
30554
+ return false;
30555
+ });
30556
+ setIsHeaderCell(hasHeaderCell);
30557
+ if (currentSelectionCounts.rows === tableRowCount && currentSelectionCounts.columns < tableColumnCount) {
30558
+ setSelectionType("column");
30559
+ } else if (currentSelectionCounts.columns === tableColumnCount && currentSelectionCounts.rows < tableRowCount) {
30560
+ setSelectionType("row");
30561
+ } else {
30562
+ setSelectionType("cell");
30563
+ }
30564
+ } else {
30565
+ setSelectionType(null);
30566
+ setIsHeaderCell(false);
30567
+ }
30568
+ } else {
30569
+ setSelectionType(null);
30570
+ const node = $getTableCellNodeFromLexicalNode(tableCellNode);
30571
+ if (node && $isTableCellNode(node)) {
30572
+ setIsHeaderCell(node.getHeaderStyles() !== 0);
30573
+ } else {
30574
+ setIsHeaderCell(false);
30575
+ }
30272
30576
  }
30273
30577
  setCanUnmergeCell($canUnmerge());
30274
30578
  });
30275
- }, [editor]);
30579
+ }, [editor, tableCellNode]);
30276
30580
  useEffect$1(() => {
30277
30581
  const menuButtonElement = contextRef.current;
30278
30582
  const dropDownElement = dropDownRef.current;
@@ -30281,6 +30585,7 @@ function TableActionMenu({
30281
30585
  dropDownElement.style.opacity = "1";
30282
30586
  const dropDownElementRect = dropDownElement.getBoundingClientRect();
30283
30587
  const margin = 8;
30588
+ const viewportHeight = window.innerHeight;
30284
30589
  if (contextMenuPosition) {
30285
30590
  let leftPosition = contextMenuPosition.x + margin;
30286
30591
  let topPosition = contextMenuPosition.y + margin;
@@ -30296,6 +30601,12 @@ function TableActionMenu({
30296
30601
  if (topPosition < margin) {
30297
30602
  topPosition = margin;
30298
30603
  }
30604
+ const availableHeight = viewportHeight - topPosition - margin;
30605
+ if (availableHeight < dropDownElementRect.height) {
30606
+ dropDownElement.style.maxHeight = `${availableHeight}px`;
30607
+ } else {
30608
+ dropDownElement.style.maxHeight = "none";
30609
+ }
30299
30610
  dropDownElement.style.left = `${leftPosition}px`;
30300
30611
  dropDownElement.style.top = `${topPosition}px`;
30301
30612
  } else if (chevronPositionRef.current != null) {
@@ -30315,6 +30626,12 @@ function TableActionMenu({
30315
30626
  if (topPosition < margin) {
30316
30627
  topPosition = margin;
30317
30628
  }
30629
+ const availableHeight = viewportHeight - topPosition - margin;
30630
+ if (availableHeight < dropDownElementRect.height) {
30631
+ dropDownElement.style.maxHeight = `${availableHeight}px`;
30632
+ } else {
30633
+ dropDownElement.style.maxHeight = "none";
30634
+ }
30318
30635
  dropDownElement.style.top = `${topPosition}px`;
30319
30636
  } else if (menuButtonElement != null) {
30320
30637
  const menuButtonRect = menuButtonElement.getBoundingClientRect();
@@ -30333,6 +30650,12 @@ function TableActionMenu({
30333
30650
  if (topPosition < margin) {
30334
30651
  topPosition = margin;
30335
30652
  }
30653
+ const availableHeight = viewportHeight - topPosition - margin;
30654
+ if (availableHeight < dropDownElementRect.height) {
30655
+ dropDownElement.style.maxHeight = `${availableHeight}px`;
30656
+ } else {
30657
+ dropDownElement.style.maxHeight = "none";
30658
+ }
30336
30659
  dropDownElement.style.top = `${topPosition}px`;
30337
30660
  }
30338
30661
  }
@@ -30442,8 +30765,29 @@ function TableActionMenu({
30442
30765
  const insertTableRowAtSelection = useCallback(
30443
30766
  (shouldInsertAfter) => {
30444
30767
  editor.update(() => {
30768
+ const selection = $getSelection();
30769
+ if (!($isRangeSelection(selection) || $isTableSelection(selection))) {
30770
+ onClose();
30771
+ return;
30772
+ }
30773
+ const [cell] = $getNodeTriplet(selection.anchor);
30774
+ const tableNode = $getTableNodeFromLexicalNodeOrThrow(cell);
30775
+ const rowIndex = $getTableRowIndexFromTableCellNode(cell);
30445
30776
  for (let i2 = 0; i2 < selectionCounts.rows; i2++) {
30446
30777
  $insertTableRow__EXPERIMENTAL(shouldInsertAfter);
30778
+ const targetRowIndex = shouldInsertAfter ? rowIndex + i2 + 1 : rowIndex - i2;
30779
+ const rows = tableNode.getChildren();
30780
+ if (targetRowIndex >= 0 && targetRowIndex < rows.length) {
30781
+ const newRow = rows[targetRowIndex];
30782
+ if ($isTableRowNode(newRow)) {
30783
+ const cells = newRow.getChildren();
30784
+ cells.forEach((cellNode) => {
30785
+ if ($isTableCellNode(cellNode)) {
30786
+ cellNode.setHeaderStyles(TableCellHeaderStates.NO_STATUS);
30787
+ }
30788
+ });
30789
+ }
30790
+ }
30447
30791
  }
30448
30792
  onClose();
30449
30793
  });
@@ -30453,33 +30797,57 @@ function TableActionMenu({
30453
30797
  const insertTableColumnAtSelection = useCallback(
30454
30798
  (shouldInsertAfter) => {
30455
30799
  editor.update(() => {
30800
+ const selection = $getSelection();
30801
+ if (!($isRangeSelection(selection) || $isTableSelection(selection))) {
30802
+ onClose();
30803
+ return;
30804
+ }
30805
+ const [cell] = $getNodeTriplet(selection.anchor);
30806
+ if (!$isTableCellNode(cell)) {
30807
+ onClose();
30808
+ return;
30809
+ }
30810
+ const tableNode = $getTableNodeFromLexicalNodeOrThrow(cell);
30811
+ const rows = tableNode.getChildren();
30812
+ let hasColumnHeaders = false;
30813
+ let headerBackgroundColor = null;
30814
+ if (rows.length > 0 && $isTableRowNode(rows[0])) {
30815
+ const firstRow = rows[0];
30816
+ const cells = firstRow.getChildren();
30817
+ if (cells.length > 0 && $isTableCellNode(cells[0])) {
30818
+ const firstCell = cells[0];
30819
+ hasColumnHeaders = (firstCell.getHeaderStyles() & TableCellHeaderStates.COLUMN) === TableCellHeaderStates.COLUMN;
30820
+ headerBackgroundColor = firstCell.getBackgroundColor();
30821
+ }
30822
+ }
30823
+ const cellColumnIndex = $getTableColumnIndexFromTableCellNode(cell);
30456
30824
  for (let i2 = 0; i2 < selectionCounts.columns; i2++) {
30457
30825
  $insertTableColumn__EXPERIMENTAL(shouldInsertAfter);
30458
30826
  }
30459
- const selection = $getSelection();
30460
- if ($isRangeSelection(selection) || $isTableSelection(selection)) {
30461
- const [cell] = $getNodeTriplet(selection.anchor);
30462
- if ($isTableCellNode(cell)) {
30463
- const tableNode = $getTableNodeFromLexicalNodeOrThrow(cell);
30464
- const rows = tableNode.getChildren();
30465
- if (rows.length > 0 && $isTableRowNode(rows[0])) {
30466
- const firstRow = rows[0];
30467
- const firstRowCells = firstRow.getChildren();
30468
- if (firstRowCells.length > 0 && $isTableCellNode(firstRowCells[0])) {
30469
- const firstCell = firstRowCells[0];
30470
- const hasColumnHeaders = (firstCell.getHeaderStyles() & TableCellHeaderStates.COLUMN) === TableCellHeaderStates.COLUMN;
30471
- if (hasColumnHeaders) {
30472
- const headerBackgroundColor = firstCell.getBackgroundColor();
30473
- for (let i2 = 0; i2 < selectionCounts.columns; i2++) {
30474
- const newHeaderCellIndex = firstRowCells.length - 1 - i2;
30475
- if (newHeaderCellIndex >= 0) {
30476
- const newHeaderCell = firstRowCells[newHeaderCellIndex];
30477
- if ($isTableCellNode(newHeaderCell)) {
30478
- newHeaderCell.setHeaderStyles(TableCellHeaderStates.COLUMN);
30479
- if (headerBackgroundColor) {
30480
- newHeaderCell.setBackgroundColor(headerBackgroundColor);
30481
- }
30482
- }
30827
+ if (hasColumnHeaders) {
30828
+ const updatedFirstRow = tableNode.getChildren()[0];
30829
+ if ($isTableRowNode(updatedFirstRow)) {
30830
+ const updatedCells = updatedFirstRow.getChildren();
30831
+ const startIndex = shouldInsertAfter ? cellColumnIndex + 1 : cellColumnIndex;
30832
+ for (let i2 = 0; i2 < selectionCounts.columns; i2++) {
30833
+ const newColumnIndex = startIndex + i2;
30834
+ if (newColumnIndex >= 0 && newColumnIndex < updatedCells.length) {
30835
+ const newHeaderCell = updatedCells[newColumnIndex];
30836
+ if ($isTableCellNode(newHeaderCell)) {
30837
+ newHeaderCell.setHeaderStyles(TableCellHeaderStates.COLUMN);
30838
+ if (headerBackgroundColor) {
30839
+ newHeaderCell.setBackgroundColor(headerBackgroundColor);
30840
+ }
30841
+ if (newHeaderCell.getChildrenSize() === 0) {
30842
+ const paragraph = $createParagraphNode();
30843
+ const textNode = $createTextNode("​");
30844
+ paragraph.append(textNode);
30845
+ newHeaderCell.append(paragraph);
30846
+ } else {
30847
+ const firstChild = newHeaderCell.getFirstChild();
30848
+ if ($isParagraphNode(firstChild) && firstChild.getTextContentSize() === 0) {
30849
+ const textNode = $createTextNode("​");
30850
+ firstChild.append(textNode);
30483
30851
  }
30484
30852
  }
30485
30853
  }
@@ -30489,46 +30857,6 @@ function TableActionMenu({
30489
30857
  }
30490
30858
  onClose();
30491
30859
  });
30492
- requestAnimationFrame(() => {
30493
- const applyHeaderStyles = () => {
30494
- const rootElement = editor.getRootElement();
30495
- if (!rootElement)
30496
- return false;
30497
- const tables = rootElement.querySelectorAll("table");
30498
- tables.forEach((table) => {
30499
- const rows = table.querySelectorAll("tr");
30500
- if (rows.length > 0) {
30501
- const firstRow = rows[0];
30502
- const cells = firstRow.querySelectorAll("th, td");
30503
- if (cells.length > 1) {
30504
- const firstHeaderCell = cells[0];
30505
- const headerColor = firstHeaderCell.getAttribute("data-header-color");
30506
- const textColor = firstHeaderCell.getAttribute("data-text-color");
30507
- if (headerColor && textColor) {
30508
- for (let i2 = 0; i2 < selectionCounts.columns; i2++) {
30509
- const cellIndex = cells.length - 1 - i2;
30510
- if (cellIndex >= 0) {
30511
- const newCell = cells[cellIndex];
30512
- newCell.setAttribute("data-header-color", headerColor);
30513
- newCell.setAttribute("data-text-color", textColor);
30514
- newCell.style.setProperty("background-color", headerColor, "important");
30515
- newCell.style.setProperty("color", textColor, "important");
30516
- newCell.style.setProperty("padding", "8px", "important");
30517
- newCell.style.setProperty("border", "1px solid #ddd", "important");
30518
- newCell.style.setProperty("font-weight", "bold", "important");
30519
- newCell.style.setProperty("white-space", "nowrap", "important");
30520
- }
30521
- }
30522
- }
30523
- }
30524
- }
30525
- });
30526
- return true;
30527
- };
30528
- if (!applyHeaderStyles()) {
30529
- setTimeout(applyHeaderStyles, 100);
30530
- }
30531
- });
30532
30860
  },
30533
30861
  [editor, onClose, selectionCounts.columns]
30534
30862
  );
@@ -30569,6 +30897,7 @@ function TableActionMenu({
30569
30897
  });
30570
30898
  }, [editor, onClose]);
30571
30899
  const toggleTableRowIsHeader = useCallback(() => {
30900
+ const cellsToUpdate = [];
30572
30901
  editor.update(() => {
30573
30902
  const tableNode = $getTableNodeFromLexicalNodeOrThrow(tableCellNode);
30574
30903
  const tableRowIndex = $getTableRowIndexFromTableCellNode(tableCellNode);
@@ -30585,13 +30914,39 @@ function TableActionMenu({
30585
30914
  if (!$isTableCellNode(tableCell)) {
30586
30915
  throw new Error("Expected table cell");
30587
30916
  }
30917
+ const bgColor = tableCell.getBackgroundColor();
30588
30918
  tableCell.setHeaderStyles(newStyle, TableCellHeaderStates.ROW);
30919
+ cellsToUpdate.push({ key: tableCell.getKey(), bgColor });
30589
30920
  });
30590
30921
  $clearTableSelectionInline();
30591
30922
  onClose();
30592
30923
  });
30924
+ requestAnimationFrame(() => {
30925
+ cellsToUpdate.forEach(({ key, bgColor }) => {
30926
+ if (bgColor) {
30927
+ const cellElement = editor.getElementByKey(key);
30928
+ if (cellElement instanceof HTMLElement) {
30929
+ const hex = bgColor.replace("#", "");
30930
+ const r2 = parseInt(hex.substr(0, 2), 16);
30931
+ const g2 = parseInt(hex.substr(2, 2), 16);
30932
+ const b2 = parseInt(hex.substr(4, 2), 16);
30933
+ const luminance = (0.299 * r2 + 0.587 * g2 + 0.114 * b2) / 255;
30934
+ const textColor = luminance > 0.5 ? "#000000" : "#FFFFFF";
30935
+ cellElement.style.setProperty("color", textColor, "important");
30936
+ const nestedElements = cellElement.querySelectorAll("*");
30937
+ nestedElements.forEach((elem) => {
30938
+ if (elem instanceof HTMLElement) {
30939
+ elem.style.removeProperty("color");
30940
+ elem.style.setProperty("color", textColor, "important");
30941
+ }
30942
+ });
30943
+ }
30944
+ }
30945
+ });
30946
+ });
30593
30947
  }, [editor, tableCellNode, $clearTableSelectionInline, onClose]);
30594
30948
  const toggleTableColumnIsHeader = useCallback(() => {
30949
+ const cellsToUpdate = [];
30595
30950
  editor.update(() => {
30596
30951
  const tableNode = $getTableNodeFromLexicalNodeOrThrow(tableCellNode);
30597
30952
  const tableColumnIndex = $getTableColumnIndexFromTableCellNode(tableCellNode);
@@ -30616,11 +30971,37 @@ function TableActionMenu({
30616
30971
  if (!$isTableCellNode(tableCell)) {
30617
30972
  throw new Error("Expected table cell");
30618
30973
  }
30974
+ const bgColor = tableCell.getBackgroundColor();
30619
30975
  tableCell.setHeaderStyles(newStyle, TableCellHeaderStates.COLUMN);
30976
+ cellsToUpdate.push({ key: tableCell.getKey(), bgColor });
30977
+ cellsToUpdate.push({ key: tableCell.getKey(), bgColor });
30620
30978
  }
30621
30979
  $clearTableSelectionInline();
30622
30980
  onClose();
30623
30981
  });
30982
+ requestAnimationFrame(() => {
30983
+ cellsToUpdate.forEach(({ key, bgColor }) => {
30984
+ if (bgColor) {
30985
+ const cellElement = editor.getElementByKey(key);
30986
+ if (cellElement instanceof HTMLElement) {
30987
+ const hex = bgColor.replace("#", "");
30988
+ const r2 = parseInt(hex.substr(0, 2), 16);
30989
+ const g2 = parseInt(hex.substr(2, 2), 16);
30990
+ const b2 = parseInt(hex.substr(4, 2), 16);
30991
+ const luminance = (0.299 * r2 + 0.587 * g2 + 0.114 * b2) / 255;
30992
+ const textColor = luminance > 0.5 ? "#000000" : "#FFFFFF";
30993
+ cellElement.style.setProperty("color", textColor, "important");
30994
+ const nestedElements = cellElement.querySelectorAll("*");
30995
+ nestedElements.forEach((elem) => {
30996
+ if (elem instanceof HTMLElement) {
30997
+ elem.style.removeProperty("color");
30998
+ elem.style.setProperty("color", textColor, "important");
30999
+ }
31000
+ });
31001
+ }
31002
+ }
31003
+ });
31004
+ });
30624
31005
  }, [editor, tableCellNode, $clearTableSelectionInline, onClose]);
30625
31006
  const applyRowStriping = useCallback((color) => {
30626
31007
  editor.update(() => {
@@ -30640,7 +31021,7 @@ function TableActionMenu({
30640
31021
  }, [editor, tableCellNode, $clearTableSelectionInline]);
30641
31022
  const handleCellBackgroundColor = useCallback(
30642
31023
  (value) => {
30643
- const getContrastColor2 = (hexColor) => {
31024
+ const getContrastColor = (hexColor) => {
30644
31025
  const hex = hexColor.replace("#", "");
30645
31026
  const r2 = parseInt(hex.substr(0, 2), 16);
30646
31027
  const g2 = parseInt(hex.substr(2, 2), 16);
@@ -30648,15 +31029,12 @@ function TableActionMenu({
30648
31029
  const luminance = (0.299 * r2 + 0.587 * g2 + 0.114 * b2) / 255;
30649
31030
  return luminance > 0.5 ? "#000000" : "#FFFFFF";
30650
31031
  };
30651
- const textColor = getContrastColor2(value);
31032
+ const textColor = getContrastColor(value);
31033
+ const cellKeysToStyle = [];
30652
31034
  editor.update(() => {
30653
31035
  if (tableCellNode.isAttached()) {
30654
31036
  tableCellNode.setBackgroundColor(value);
30655
- const cellElement = editor.getElementByKey(tableCellNode.getKey());
30656
- if (cellElement instanceof HTMLElement) {
30657
- cellElement.style.setProperty("background-color", value, "important");
30658
- cellElement.style.setProperty("color", textColor, "important");
30659
- }
31037
+ cellKeysToStyle.push(tableCellNode.getKey());
30660
31038
  const selection = $getSelection();
30661
31039
  if ($isTableSelection(selection)) {
30662
31040
  const nodes = selection.getNodes();
@@ -30664,16 +31042,29 @@ function TableActionMenu({
30664
31042
  const node = nodes[i2];
30665
31043
  if ($isTableCellNode(node)) {
30666
31044
  node.setBackgroundColor(value);
30667
- const nodeElement = editor.getElementByKey(node.getKey());
30668
- if (nodeElement instanceof HTMLElement) {
30669
- nodeElement.style.setProperty("background-color", value, "important");
30670
- nodeElement.style.setProperty("color", textColor, "important");
30671
- }
31045
+ cellKeysToStyle.push(node.getKey());
30672
31046
  }
30673
31047
  }
30674
31048
  }
30675
31049
  }
30676
31050
  });
31051
+ requestAnimationFrame(() => {
31052
+ cellKeysToStyle.forEach((cellKey) => {
31053
+ const cellElement = editor.getElementByKey(cellKey);
31054
+ if (cellElement instanceof HTMLElement) {
31055
+ cellElement.style.setProperty("background-color", value, "important");
31056
+ cellElement.style.setProperty("color", textColor, "important");
31057
+ cellElement.style.setProperty("border-color", "#bbb", "important");
31058
+ const nestedElements = cellElement.querySelectorAll("*");
31059
+ nestedElements.forEach((elem) => {
31060
+ if (elem instanceof HTMLElement) {
31061
+ elem.style.removeProperty("color");
31062
+ elem.style.setProperty("color", textColor, "important");
31063
+ }
31064
+ });
31065
+ }
31066
+ });
31067
+ });
30677
31068
  },
30678
31069
  [editor, tableCellNode]
30679
31070
  );
@@ -30731,22 +31122,19 @@ function TableActionMenu({
30731
31122
  ColorPicker,
30732
31123
  {
30733
31124
  color: backgroundColor,
30734
- onChange: (value) => {
30735
- handleCellBackgroundColor(value);
30736
- },
30737
31125
  onApply: (value) => {
30738
31126
  handleCellBackgroundColor(value);
30739
31127
  closeModal();
30740
31128
  setIsMenuOpen(false);
30741
31129
  }
30742
31130
  }
30743
- ));
31131
+ ), true);
30744
31132
  },
30745
31133
  "data-test-id": "table-background-color",
30746
31134
  children: /* @__PURE__ */ jsx("span", { className: "text", children: "Background color" })
30747
31135
  }
30748
31136
  ),
30749
- /* @__PURE__ */ jsx(
31137
+ selectionType !== "column" && /* @__PURE__ */ jsx(
30750
31138
  "button",
30751
31139
  {
30752
31140
  type: "button",
@@ -30757,10 +31145,6 @@ function TableActionMenu({
30757
31145
  ColorPicker,
30758
31146
  {
30759
31147
  color: stripingColor,
30760
- onChange: (value) => {
30761
- setStripingColor(value);
30762
- applyRowStriping(value);
30763
- },
30764
31148
  onApply: (value) => {
30765
31149
  setStripingColor(value);
30766
31150
  applyRowStriping(value);
@@ -30768,14 +31152,14 @@ function TableActionMenu({
30768
31152
  setIsMenuOpen(false);
30769
31153
  }
30770
31154
  }
30771
- ));
31155
+ ), true);
30772
31156
  },
30773
31157
  "data-test-id": "table-row-striping",
30774
31158
  children: /* @__PURE__ */ jsx("span", { className: "text", children: "Row Striping Color" })
30775
31159
  }
30776
31160
  ),
30777
31161
  /* @__PURE__ */ jsx("div", { className: "cteditor-border-b cteditor-border-foreground/15 cteditor-my-1" }),
30778
- /* @__PURE__ */ jsx(
31162
+ !isHeaderCell && /* @__PURE__ */ jsx(
30779
31163
  "button",
30780
31164
  {
30781
31165
  type: "button",
@@ -30841,7 +31225,7 @@ function TableActionMenu({
30841
31225
  }
30842
31226
  ),
30843
31227
  /* @__PURE__ */ jsx("div", { className: "border-b border-foreground/15 my-1" }),
30844
- /* @__PURE__ */ jsx(
31228
+ selectionType !== "row" && /* @__PURE__ */ jsx(
30845
31229
  "button",
30846
31230
  {
30847
31231
  type: "button",
@@ -30851,7 +31235,7 @@ function TableActionMenu({
30851
31235
  children: /* @__PURE__ */ jsx("span", { className: "text", children: "Delete column" })
30852
31236
  }
30853
31237
  ),
30854
- /* @__PURE__ */ jsx(
31238
+ selectionType !== "column" && /* @__PURE__ */ jsx(
30855
31239
  "button",
30856
31240
  {
30857
31241
  type: "button",
@@ -30872,7 +31256,7 @@ function TableActionMenu({
30872
31256
  }
30873
31257
  ),
30874
31258
  /* @__PURE__ */ jsx("div", { className: "cteditor-border-b cteditor-border-foreground/15 cteditor-my-1" }),
30875
- /* @__PURE__ */ jsx(
31259
+ selectionType !== "column" && /* @__PURE__ */ jsx(
30876
31260
  "button",
30877
31261
  {
30878
31262
  type: "button",
@@ -30885,7 +31269,7 @@ function TableActionMenu({
30885
31269
  ] })
30886
31270
  }
30887
31271
  ),
30888
- /* @__PURE__ */ jsx(
31272
+ selectionType !== "row" && /* @__PURE__ */ jsx(
30889
31273
  "button",
30890
31274
  {
30891
31275
  type: "button",
@@ -30951,6 +31335,9 @@ function TableCellActionMenuContainer({
30951
31335
  if (tableCellParentNodeDOM == null || !tableCellNodeFromSelection.isAttached()) {
30952
31336
  return disable();
30953
31337
  }
31338
+ if (!rootElement.contains(nativeSelection.focusNode)) {
31339
+ return disable();
31340
+ }
30954
31341
  const cellHasContent = tableCellNodeFromSelection.getTextContentSize() > 0;
30955
31342
  if (cellHasContent && !isMenuOpen) {
30956
31343
  return disable();
@@ -31008,7 +31395,7 @@ function TableCellActionMenuContainer({
31008
31395
  menu.classList.add("table-cell-action-button-container--active");
31009
31396
  menu.classList.remove("table-cell-action-button-container--inactive");
31010
31397
  const margin = 4;
31011
- const btnWidth = 28;
31398
+ const btnWidth = 20;
31012
31399
  const top = cellRect.top - anchorRect.top + margin;
31013
31400
  const left = cellRect.right - anchorRect.left - btnWidth - margin;
31014
31401
  menu.style.top = `${top}px`;
@@ -31027,16 +31414,38 @@ function TableCellActionMenuContainer({
31027
31414
  }
31028
31415
  return false;
31029
31416
  };
31417
+ const handleScroll2 = () => {
31418
+ editor.getEditorState().read($moveMenu);
31419
+ };
31420
+ const editorElement = editor.getRootElement();
31421
+ const scrollableParent = editorElement == null ? void 0 : editorElement.closest(".cteditor-content");
31422
+ if (scrollableParent) {
31423
+ scrollableParent.addEventListener("scroll", handleScroll2, { capture: true, passive: true });
31424
+ }
31425
+ window.addEventListener("scroll", handleScroll2, { capture: true, passive: true });
31030
31426
  const handleContextMenu = (event) => {
31031
31427
  event.stopPropagation();
31032
31428
  const target = event.target;
31429
+ if (!target || target.classList.contains("TableNode__resizeHandle") || target.classList.contains("table-cell-action-button") || target.closest(".table-cell-action-button-container") || target.closest(".TableNode__resizeHandle")) {
31430
+ return;
31431
+ }
31033
31432
  const tableCell = target.closest("td, th");
31034
- if (tableCell) {
31035
- event.preventDefault();
31036
- event.stopPropagation();
31037
- let foundCellNode = null;
31038
- let isNodeAttached = false;
31039
- setTimeout(() => {
31433
+ if (!tableCell) {
31434
+ return;
31435
+ }
31436
+ const cellRect = tableCell.getBoundingClientRect();
31437
+ const clickX = event.clientX;
31438
+ const clickY = event.clientY;
31439
+ const borderThreshold = 3;
31440
+ if (clickX < cellRect.left + borderThreshold || clickX > cellRect.right - borderThreshold || clickY < cellRect.top + borderThreshold || clickY > cellRect.bottom - borderThreshold) {
31441
+ return;
31442
+ }
31443
+ event.preventDefault();
31444
+ event.stopPropagation();
31445
+ let foundCellNode = null;
31446
+ let isNodeAttached = false;
31447
+ setTimeout(() => {
31448
+ try {
31040
31449
  editor.getEditorState().read(() => {
31041
31450
  try {
31042
31451
  const allNodes = editor._editorState._nodeMap;
@@ -31060,8 +31469,10 @@ function TableCellActionMenuContainer({
31060
31469
  setContextMenuPosition({ x: event.clientX, y: event.clientY });
31061
31470
  setIsMenuOpen(true);
31062
31471
  }
31063
- }, 10);
31064
- }
31472
+ } catch (error) {
31473
+ console.warn("Error handling context menu:", error);
31474
+ }
31475
+ }, 10);
31065
31476
  };
31066
31477
  return mergeRegister(
31067
31478
  editor.registerUpdateListener(delayedCallback),
@@ -31081,7 +31492,15 @@ function TableCellActionMenuContainer({
31081
31492
  delayedCallback();
31082
31493
  }
31083
31494
  }),
31084
- () => clearTimeout(timeoutId)
31495
+ () => {
31496
+ clearTimeout(timeoutId);
31497
+ const editorElement2 = editor.getRootElement();
31498
+ const scrollableParent2 = editorElement2 == null ? void 0 : editorElement2.closest(".cteditor-content");
31499
+ if (scrollableParent2) {
31500
+ scrollableParent2.removeEventListener("scroll", handleScroll2);
31501
+ }
31502
+ window.removeEventListener("scroll", handleScroll2);
31503
+ }
31085
31504
  );
31086
31505
  });
31087
31506
  const prevTableCellDOM = useRef(tableCellNode);
@@ -31151,8 +31570,8 @@ function TableCellActionMenuContainer({
31151
31570
  }
31152
31571
  function TableActionMenuPlugin({
31153
31572
  anchorElem,
31154
- // Remove default value here
31155
- cellMerge = false
31573
+ cellMerge = false,
31574
+ isSmallWidthViewport = false
31156
31575
  }) {
31157
31576
  const isEditable = useLexicalEditable();
31158
31577
  if (!anchorElem)
@@ -31162,16 +31581,17 @@ function TableActionMenuPlugin({
31162
31581
  TableCellActionMenuContainer,
31163
31582
  {
31164
31583
  anchorElem,
31165
- cellMerge
31584
+ cellMerge,
31585
+ isSmallWidthViewport
31166
31586
  }
31167
31587
  ) : null,
31168
31588
  anchorElem
31169
- // Use the provided anchor element
31170
31589
  );
31171
31590
  }
31172
31591
  const index = "";
31173
31592
  const MIN_ROW_HEIGHT = 33;
31174
- const MIN_COLUMN_WIDTH = 92;
31593
+ const MIN_COLUMN_WIDTH = 50;
31594
+ const DEFAULT_COLUMN_WIDTH = 80;
31175
31595
  function TableCellResizer({ editor }) {
31176
31596
  const targetRef = useRef(null);
31177
31597
  const resizerRef = useRef(null);
@@ -31179,10 +31599,13 @@ function TableCellResizer({ editor }) {
31179
31599
  const mouseStartPosRef = useRef(null);
31180
31600
  const [mouseCurrentPos, updateMouseCurrentPos] = useState$1(null);
31181
31601
  const [activeCell, updateActiveCell] = useState$1(null);
31182
- const [isMouseDown, updateIsMouseDown] = useState$1(false);
31602
+ const [_isMouseDown, updateIsMouseDown] = useState$1(false);
31183
31603
  const [draggingDirection, updateDraggingDirection] = useState$1(null);
31184
31604
  const [currentDimension, setCurrentDimension] = useState$1(null);
31185
31605
  const [hoveredDirection, setHoveredDirection] = useState$1(null);
31606
+ const [initialDimension, setInitialDimension] = useState$1(null);
31607
+ const updateColumnWidthToValueRef = useRef(null);
31608
+ const updateRowHeightToValueRef = useRef(null);
31186
31609
  const resetState = useCallback(() => {
31187
31610
  updateActiveCell(null);
31188
31611
  targetRef.current = null;
@@ -31191,6 +31614,7 @@ function TableCellResizer({ editor }) {
31191
31614
  tableRectRef.current = null;
31192
31615
  setCurrentDimension(null);
31193
31616
  setHoveredDirection(null);
31617
+ setInitialDimension(null);
31194
31618
  }, []);
31195
31619
  const isMouseDownOnEvent = (event) => {
31196
31620
  return (event.buttons & 1) === 1;
@@ -31198,54 +31622,41 @@ function TableCellResizer({ editor }) {
31198
31622
  useEffect$1(() => {
31199
31623
  return editor.registerNodeTransform(TableNode, (tableNode) => {
31200
31624
  const existingWidths = tableNode.getColWidths();
31201
- const numColumns = tableNode.getColumnCount();
31202
- const tableElement = editor.getElementByKey(tableNode.getKey());
31203
- if (existingWidths && existingWidths.length > 0) {
31204
- if (tableElement) {
31205
- const totalWidth = existingWidths.reduce((sum, w2) => sum + w2, 0);
31206
- const currentWidth = tableElement.style.width;
31207
- if (!currentWidth || parseInt(currentWidth) !== totalWidth) {
31208
- tableElement.style.setProperty("width", `${totalWidth}px`, "important");
31209
- }
31210
- }
31625
+ if (existingWidths) {
31211
31626
  return tableNode;
31212
31627
  }
31213
- if (tableElement) {
31214
- const firstRow = tableElement.querySelector("tr");
31215
- if (firstRow) {
31216
- const cells = Array.from(firstRow.querySelectorAll("th, td"));
31217
- const actualWidths = cells.map((cell) => {
31218
- const width = cell.offsetWidth;
31219
- return Math.max(width || MIN_COLUMN_WIDTH, MIN_COLUMN_WIDTH);
31220
- });
31221
- if (actualWidths.length === numColumns) {
31222
- tableNode.setColWidths(actualWidths);
31223
- const totalWidth = actualWidths.reduce((sum, w2) => sum + w2, 0);
31224
- tableElement.style.setProperty("width", `${totalWidth}px`, "important");
31225
- return tableNode;
31226
- }
31227
- }
31228
- }
31229
- const fallbackWidths = Array(numColumns).fill(MIN_COLUMN_WIDTH);
31230
- tableNode.setColWidths(fallbackWidths);
31231
- if (tableElement) {
31232
- const totalWidth = fallbackWidths.reduce((sum, w2) => sum + w2, 0);
31233
- tableElement.style.setProperty("width", `${totalWidth}px`, "important");
31234
- }
31628
+ const numColumns = tableNode.getColumnCount();
31629
+ const initialWidths = Array(numColumns).fill(DEFAULT_COLUMN_WIDTH);
31630
+ tableNode.setColWidths(initialWidths);
31235
31631
  return tableNode;
31236
31632
  });
31237
31633
  }, [editor]);
31238
31634
  useEffect$1(() => {
31239
31635
  const onMouseMove = (event) => {
31636
+ var _a, _b;
31240
31637
  const target = event.target;
31241
31638
  if (!isHTMLElement$1(target)) {
31242
31639
  return;
31243
31640
  }
31244
- if (draggingDirection) {
31245
- updateMouseCurrentPos({
31641
+ if (draggingDirection && mouseStartPosRef.current && initialDimension !== null) {
31642
+ const newPos = {
31246
31643
  x: event.clientX,
31247
31644
  y: event.clientY
31248
- });
31645
+ };
31646
+ updateMouseCurrentPos(newPos);
31647
+ const zoom = calculateZoomLevel(event.target);
31648
+ const { x: x2, y: y2 } = mouseStartPosRef.current;
31649
+ if (isHeightChanging(draggingDirection)) {
31650
+ const heightChange = (newPos.y - y2) / zoom;
31651
+ const newHeight = Math.max(initialDimension + heightChange, MIN_ROW_HEIGHT);
31652
+ setCurrentDimension(newHeight);
31653
+ (_a = updateRowHeightToValueRef.current) == null ? void 0 : _a.call(updateRowHeightToValueRef, newHeight);
31654
+ } else {
31655
+ const widthChange = (newPos.x - x2) / zoom;
31656
+ const newWidth = Math.max(initialDimension + widthChange, MIN_COLUMN_WIDTH);
31657
+ setCurrentDimension(newWidth);
31658
+ (_b = updateColumnWidthToValueRef.current) == null ? void 0 : _b.call(updateColumnWidthToValueRef, newWidth);
31659
+ }
31249
31660
  return;
31250
31661
  }
31251
31662
  updateIsMouseDown(isMouseDownOnEvent(event));
@@ -31281,10 +31692,10 @@ function TableCellResizer({ editor }) {
31281
31692
  }
31282
31693
  }
31283
31694
  };
31284
- const onMouseDown = (event) => {
31695
+ const onMouseDown = (_event) => {
31285
31696
  updateIsMouseDown(true);
31286
31697
  };
31287
- const onMouseUp = (event) => {
31698
+ const onMouseUp = (_event) => {
31288
31699
  updateIsMouseDown(false);
31289
31700
  if (draggingDirection) {
31290
31701
  updateDraggingDirection(null);
@@ -31305,52 +31716,44 @@ function TableCellResizer({ editor }) {
31305
31716
  return () => {
31306
31717
  removeRootListener();
31307
31718
  };
31308
- }, [activeCell, draggingDirection, editor, resetState, setCurrentDimension]);
31719
+ }, [activeCell, draggingDirection, editor, resetState, initialDimension]);
31309
31720
  const isHeightChanging = (direction) => {
31310
31721
  if (direction === "bottom") {
31311
31722
  return true;
31312
31723
  }
31313
31724
  return false;
31314
31725
  };
31315
- const updateRowHeight = useCallback(
31316
- (heightChange) => {
31726
+ const updateRowHeightToValue = useCallback(
31727
+ (newHeight) => {
31317
31728
  if (!activeCell) {
31318
- throw new Error("TableCellResizer: Expected active cell.");
31729
+ return;
31319
31730
  }
31320
31731
  editor.update(
31321
31732
  () => {
31322
31733
  const tableCellNode = $getNearestNodeFromDOMNode(activeCell.elem);
31323
31734
  if (!$isTableCellNode(tableCellNode)) {
31324
- throw new Error("TableCellResizer: Table cell node not found.");
31735
+ return;
31325
31736
  }
31326
31737
  const tableNode = $getTableNodeFromLexicalNodeOrThrow(tableCellNode);
31327
31738
  const tableRowIndex = $getTableRowIndexFromTableCellNode(tableCellNode) + tableCellNode.getRowSpan() - 1;
31328
31739
  const tableRows = tableNode.getChildren();
31329
31740
  if (tableRowIndex >= tableRows.length || tableRowIndex < 0) {
31330
- throw new Error("Expected table cell to be inside of table row.");
31741
+ return;
31331
31742
  }
31332
31743
  const tableRow = tableRows[tableRowIndex];
31333
31744
  if (!$isTableRowNode(tableRow)) {
31334
- throw new Error("Expected table row");
31335
- }
31336
- let height = tableRow.getHeight();
31337
- if (height === void 0) {
31338
- const rowCells = tableRow.getChildren();
31339
- height = Math.min(
31340
- ...rowCells.map(
31341
- (cell) => getCellNodeHeight(cell, editor) ?? Infinity
31342
- )
31343
- );
31745
+ return;
31344
31746
  }
31345
- const newHeight = Math.max(height + heightChange, MIN_ROW_HEIGHT);
31346
- tableRow.setHeight(newHeight);
31347
- setCurrentDimension(newHeight);
31747
+ tableRow.setHeight(Math.max(newHeight, MIN_ROW_HEIGHT));
31348
31748
  },
31349
31749
  { tag: "skip-scroll-into-view" }
31350
31750
  );
31351
31751
  },
31352
31752
  [activeCell, editor]
31353
31753
  );
31754
+ useEffect$1(() => {
31755
+ updateRowHeightToValueRef.current = updateRowHeightToValue;
31756
+ }, [updateRowHeightToValue]);
31354
31757
  const autoFitRowHeight = useCallback(() => {
31355
31758
  if (!activeCell)
31356
31759
  return;
@@ -31386,16 +31789,16 @@ function TableCellResizer({ editor }) {
31386
31789
  }
31387
31790
  return void 0;
31388
31791
  };
31389
- const updateColumnWidth = useCallback(
31390
- (widthChange) => {
31792
+ const updateColumnWidthToValue = useCallback(
31793
+ (newWidth) => {
31391
31794
  if (!activeCell) {
31392
- throw new Error("TableCellResizer: Expected active cell.");
31795
+ return;
31393
31796
  }
31394
31797
  editor.update(
31395
31798
  () => {
31396
31799
  const tableCellNode = $getNearestNodeFromDOMNode(activeCell.elem);
31397
31800
  if (!$isTableCellNode(tableCellNode)) {
31398
- throw new Error("TableCellResizer: Table cell node not found.");
31801
+ return;
31399
31802
  }
31400
31803
  const tableNode = $getTableNodeFromLexicalNodeOrThrow(tableCellNode);
31401
31804
  const [tableMap] = $computeTableMapSkipCellCheck(
@@ -31403,64 +31806,65 @@ function TableCellResizer({ editor }) {
31403
31806
  null,
31404
31807
  null
31405
31808
  );
31406
- let startColumnIndex;
31407
- for (let row = 0; row < tableMap.length; row++) {
31408
- for (let column = 0; column < tableMap[row].length; column++) {
31409
- if (tableMap[row][column].cell === tableCellNode) {
31410
- startColumnIndex = column;
31411
- break;
31412
- }
31413
- }
31414
- if (startColumnIndex !== void 0)
31415
- break;
31416
- }
31417
- if (startColumnIndex === void 0) {
31418
- throw new Error("TableCellResizer: Table column not found.");
31809
+ const columnIndex = getCellColumnIndex(tableCellNode, tableMap);
31810
+ if (columnIndex === void 0) {
31811
+ return;
31419
31812
  }
31420
- const colSpan = tableCellNode.getColSpan() || 1;
31421
- const columnIndex = startColumnIndex + colSpan - 1;
31422
31813
  const colWidths = tableNode.getColWidths();
31423
- if (!colWidths || columnIndex >= colWidths.length) {
31814
+ if (!colWidths) {
31424
31815
  return;
31425
31816
  }
31426
- const width = colWidths[columnIndex];
31427
- if (width === void 0) {
31817
+ const tableElement = editor.getElementByKey(tableNode.getKey());
31818
+ if (!tableElement) {
31428
31819
  return;
31429
31820
  }
31430
- const newWidth = Math.max(width + widthChange, MIN_COLUMN_WIDTH);
31431
- const newColWidths = colWidths.map((w2, i2) => {
31432
- if (i2 === columnIndex) {
31433
- return newWidth;
31821
+ const currentCellRect = activeCell.elem.getBoundingClientRect();
31822
+ const constrainedNewWidth = Math.max(newWidth, MIN_COLUMN_WIDTH);
31823
+ const oldWidth = currentCellRect.width;
31824
+ const oldLexicalWidth = colWidths[columnIndex];
31825
+ const widthRatio = constrainedNewWidth / oldWidth;
31826
+ const newLexicalWidth = oldLexicalWidth * widthRatio;
31827
+ const newColWidths = [...colWidths];
31828
+ const lexicalWidthDelta = newLexicalWidth - oldLexicalWidth;
31829
+ newColWidths[columnIndex] = newLexicalWidth;
31830
+ let nextColumnIndex = columnIndex + 1;
31831
+ while (nextColumnIndex < colWidths.length) {
31832
+ const nextColWidth = colWidths[nextColumnIndex];
31833
+ if (nextColWidth !== void 0 && nextColWidth > 0) {
31834
+ const potentialNewWidth = nextColWidth - lexicalWidthDelta;
31835
+ let nextColumnCell = null;
31836
+ for (let row = 0; row < tableMap.length; row++) {
31837
+ const cellInfo = tableMap[row][nextColumnIndex];
31838
+ if (cellInfo && cellInfo.cell) {
31839
+ nextColumnCell = cellInfo.cell;
31840
+ break;
31841
+ }
31842
+ }
31843
+ if (nextColumnCell) {
31844
+ const nextCellElement = editor.getElementByKey(nextColumnCell.getKey());
31845
+ if (nextCellElement) {
31846
+ const nextCellRect = nextCellElement.getBoundingClientRect();
31847
+ const nextCellWidthRatio = potentialNewWidth / nextColWidth;
31848
+ const nextCellPotentialPixelWidth = nextCellRect.width * nextCellWidthRatio;
31849
+ if (nextCellPotentialPixelWidth >= MIN_COLUMN_WIDTH) {
31850
+ newColWidths[nextColumnIndex] = potentialNewWidth;
31851
+ break;
31852
+ }
31853
+ }
31854
+ }
31434
31855
  }
31435
- return w2;
31436
- });
31437
- tableNode.setColWidths(newColWidths);
31438
- setCurrentDimension(newWidth);
31439
- const totalWidth = newColWidths.reduce((sum, w2) => sum + w2, 0);
31440
- const tableElement = editor.getElementByKey(tableNode.getKey());
31441
- if (tableElement) {
31442
- tableElement.style.setProperty("width", `${totalWidth}px`, "important");
31856
+ nextColumnIndex++;
31443
31857
  }
31858
+ tableNode.setColWidths(newColWidths);
31444
31859
  },
31445
31860
  { tag: "skip-scroll-into-view" }
31446
31861
  );
31447
- setTimeout(() => {
31448
- editor.getEditorState().read(() => {
31449
- const tableCellNode = $getNearestNodeFromDOMNode(activeCell.elem);
31450
- if (!$isTableCellNode(tableCellNode))
31451
- return;
31452
- const tableNode = $getTableNodeFromLexicalNodeOrThrow(tableCellNode);
31453
- const tableElement = editor.getElementByKey(tableNode.getKey());
31454
- const colWidths = tableNode.getColWidths();
31455
- if (tableElement && colWidths) {
31456
- const totalWidth = colWidths.reduce((sum, w2) => sum + w2, 0);
31457
- tableElement.style.width = `${totalWidth}px`;
31458
- }
31459
- });
31460
- }, 0);
31461
31862
  },
31462
31863
  [activeCell, editor]
31463
31864
  );
31865
+ useEffect$1(() => {
31866
+ updateColumnWidthToValueRef.current = updateColumnWidthToValue;
31867
+ }, [updateColumnWidthToValue]);
31464
31868
  const autoFitColumnWidth = useCallback(() => {
31465
31869
  if (!activeCell)
31466
31870
  return;
@@ -31491,60 +31895,25 @@ function TableCellResizer({ editor }) {
31491
31895
  const newColWidths = [...colWidths];
31492
31896
  newColWidths[columnIndex] = Math.max(maxContentWidth, MIN_COLUMN_WIDTH);
31493
31897
  tableNode.setColWidths(newColWidths);
31494
- const totalWidth = newColWidths.reduce((sum, w2) => sum + w2, 0);
31495
- const tableElement = editor.getElementByKey(tableNode.getKey());
31496
- if (tableElement) {
31497
- tableElement.style.setProperty("width", `${totalWidth}px`, "important");
31498
- }
31499
31898
  },
31500
31899
  { tag: "skip-scroll-into-view" }
31501
31900
  );
31502
- setTimeout(() => {
31503
- editor.getEditorState().read(() => {
31504
- const tableCellNode = $getNearestNodeFromDOMNode(activeCell.elem);
31505
- if (!$isTableCellNode(tableCellNode))
31506
- return;
31507
- const tableNode = $getTableNodeFromLexicalNodeOrThrow(tableCellNode);
31508
- const tableElement = editor.getElementByKey(tableNode.getKey());
31509
- const colWidths = tableNode.getColWidths();
31510
- if (tableElement && colWidths) {
31511
- const totalWidth = colWidths.reduce((sum, w2) => sum + w2, 0);
31512
- tableElement.style.setProperty("width", `${totalWidth}px`, "important");
31513
- }
31514
- });
31515
- }, 0);
31516
31901
  }, [activeCell, editor]);
31517
31902
  const mouseUpHandler = useCallback(
31518
- (direction) => {
31903
+ (_direction) => {
31519
31904
  const handler = (event) => {
31520
31905
  event.preventDefault();
31521
31906
  event.stopPropagation();
31522
- if (!activeCell) {
31523
- throw new Error("TableCellResizer: Expected active cell.");
31524
- }
31525
- if (mouseStartPosRef.current) {
31526
- const { x: x2, y: y2 } = mouseStartPosRef.current;
31527
- if (activeCell === null) {
31528
- return;
31529
- }
31530
- const zoom = calculateZoomLevel(event.target);
31531
- if (isHeightChanging(direction)) {
31532
- const heightChange = (event.clientY - y2) / zoom;
31533
- updateRowHeight(heightChange);
31534
- } else {
31535
- const widthChange = (event.clientX - x2) / zoom;
31536
- updateColumnWidth(widthChange);
31537
- }
31538
- updateDraggingDirection(null);
31539
- updateMouseCurrentPos(null);
31540
- mouseStartPosRef.current = null;
31541
- setCurrentDimension(null);
31542
- document.removeEventListener("mouseup", handler);
31543
- }
31907
+ updateDraggingDirection(null);
31908
+ updateMouseCurrentPos(null);
31909
+ mouseStartPosRef.current = null;
31910
+ setCurrentDimension(null);
31911
+ setInitialDimension(null);
31912
+ document.removeEventListener("mouseup", handler);
31544
31913
  };
31545
31914
  return handler;
31546
31915
  },
31547
- [activeCell, updateColumnWidth, updateRowHeight]
31916
+ []
31548
31917
  );
31549
31918
  const toggleResize = useCallback(
31550
31919
  (direction) => (event) => {
@@ -31553,6 +31922,36 @@ function TableCellResizer({ editor }) {
31553
31922
  if (!activeCell) {
31554
31923
  throw new Error("TableCellResizer: Expected active cell.");
31555
31924
  }
31925
+ editor.read(() => {
31926
+ const tableCellNode = $getNearestNodeFromDOMNode(activeCell.elem);
31927
+ if (!$isTableCellNode(tableCellNode)) {
31928
+ return;
31929
+ }
31930
+ const tableNode = $getTableNodeFromLexicalNodeOrThrow(tableCellNode);
31931
+ if (isHeightChanging(direction)) {
31932
+ const tableRowIndex = $getTableRowIndexFromTableCellNode(tableCellNode) + tableCellNode.getRowSpan() - 1;
31933
+ const tableRows = tableNode.getChildren();
31934
+ if (tableRowIndex >= 0 && tableRowIndex < tableRows.length) {
31935
+ const tableRow = tableRows[tableRowIndex];
31936
+ if ($isTableRowNode(tableRow)) {
31937
+ let height = tableRow.getHeight();
31938
+ if (height === void 0) {
31939
+ const rowCells = tableRow.getChildren();
31940
+ height = Math.min(
31941
+ ...rowCells.map(
31942
+ (cell) => getCellNodeHeight(cell, editor) ?? Infinity
31943
+ )
31944
+ );
31945
+ }
31946
+ setInitialDimension(height || MIN_ROW_HEIGHT);
31947
+ }
31948
+ }
31949
+ } else {
31950
+ const cellRect = activeCell.elem.getBoundingClientRect();
31951
+ const actualWidth = cellRect.width;
31952
+ setInitialDimension(actualWidth);
31953
+ }
31954
+ });
31556
31955
  mouseStartPosRef.current = {
31557
31956
  x: event.clientX,
31558
31957
  y: event.clientY
@@ -31561,7 +31960,7 @@ function TableCellResizer({ editor }) {
31561
31960
  updateDraggingDirection(direction);
31562
31961
  document.addEventListener("mouseup", mouseUpHandler(direction));
31563
31962
  },
31564
- [activeCell, mouseUpHandler]
31963
+ [activeCell, editor, mouseUpHandler]
31565
31964
  );
31566
31965
  const handleDoubleClick = useCallback(
31567
31966
  (direction) => (event) => {
@@ -31601,15 +32000,16 @@ function TableCellResizer({ editor }) {
31601
32000
  }
31602
32001
  };
31603
32002
  const tableRect = tableRectRef.current;
31604
- if (draggingDirection && mouseCurrentPos && tableRect) {
32003
+ if (draggingDirection && mouseCurrentPos && tableRect && currentDimension !== null) {
31605
32004
  if (isHeightChanging(draggingDirection)) {
31606
32005
  styles[draggingDirection].left = `${window.pageXOffset + tableRect.left}px`;
31607
32006
  styles[draggingDirection].top = `${window.pageYOffset + mouseCurrentPos.y / zoom}px`;
31608
32007
  styles[draggingDirection].height = "3px";
31609
32008
  styles[draggingDirection].width = `${tableRect.width}px`;
31610
32009
  } else {
32010
+ const lineLeft = window.pageXOffset + left + currentDimension;
31611
32011
  styles[draggingDirection].top = `${window.pageYOffset + tableRect.top}px`;
31612
- styles[draggingDirection].left = `${window.pageXOffset + mouseCurrentPos.x / zoom}px`;
32012
+ styles[draggingDirection].left = `${lineLeft}px`;
31613
32013
  styles[draggingDirection].width = "3px";
31614
32014
  styles[draggingDirection].height = `${tableRect.height}px`;
31615
32015
  }
@@ -31624,7 +32024,7 @@ function TableCellResizer({ editor }) {
31624
32024
  right: null,
31625
32025
  top: null
31626
32026
  };
31627
- }, [activeCell, draggingDirection, mouseCurrentPos]);
32027
+ }, [activeCell, draggingDirection, mouseCurrentPos, currentDimension]);
31628
32028
  const resizerStyles = getResizers();
31629
32029
  return /* @__PURE__ */ jsxs("div", { ref: resizerRef, children: [
31630
32030
  activeCell != null && /* @__PURE__ */ jsxs(Fragment, { children: [
@@ -31699,131 +32099,699 @@ function useDebounce(fn, ms, maxWait) {
31699
32099
  [ms, maxWait]
31700
32100
  );
31701
32101
  }
31702
- const BUTTON_WIDTH_PX = 20;
32102
+ const DOT_SIZE = 8;
32103
+ const DOT_HOVER_SIZE = 16;
32104
+ const SELECTOR_BUTTON_SIZE = 12;
31703
32105
  function TableHoverActionsContainer({
31704
32106
  anchorElem
31705
32107
  }) {
31706
32108
  const [editor] = useLexicalComposerContext();
31707
32109
  const isEditable = useLexicalEditable();
31708
- const [isShownRow, setShownRow] = useState$1(false);
31709
- const [isShownColumn, setShownColumn] = useState$1(false);
31710
32110
  const [shouldListenMouseMove, setShouldListenMouseMove] = useState$1(false);
31711
- const [position, setPosition] = useState$1({});
32111
+ const [dots, setDots] = useState$1([]);
32112
+ const [selectorButtons, setSelectorButtons] = useState$1([]);
32113
+ const [hoveredDot, setHoveredDot] = useState$1(null);
32114
+ const [hoveredSelector, setHoveredSelector] = useState$1(null);
32115
+ const [hoveredRowColumn, setHoveredRowColumn] = useState$1({ row: null, column: null });
32116
+ const [activeTableDOM, setActiveTableDOM] = useState$1(null);
32117
+ const [dragState, setDragState] = useState$1(null);
32118
+ const [dragPreviewLine, setDragPreviewLine] = useState$1(null);
32119
+ const [highlightedRow, setHighlightedRow] = useState$1(null);
32120
+ const [highlightedColumn, setHighlightedColumn] = useState$1(null);
32121
+ const [targetHighlightedRow, setTargetHighlightedRow] = useState$1(null);
32122
+ const [targetHighlightedColumn, setTargetHighlightedColumn] = useState$1(null);
31712
32123
  const tableSetRef = useRef(/* @__PURE__ */ new Set());
31713
- const tableCellDOMNodeRef = useRef(null);
32124
+ const currentTableRef = useRef(null);
32125
+ const currentTableKeyRef = useRef(null);
32126
+ const calculateDotPositions = useCallback((tableDOMElement) => {
32127
+ const tableRect = tableDOMElement.getBoundingClientRect();
32128
+ const { left: editorLeft, top: editorTop } = anchorElem.getBoundingClientRect();
32129
+ const rows = tableDOMElement.querySelectorAll("tr");
32130
+ const newDots = [];
32131
+ const newSelectors = [];
32132
+ rows.forEach((row, index2) => {
32133
+ const rowRect = row.getBoundingClientRect();
32134
+ const dotTop = rowRect.bottom - editorTop - DOT_SIZE / 2;
32135
+ const dotLeft = tableRect.left - editorLeft - 20;
32136
+ newDots.push({
32137
+ left: dotLeft,
32138
+ top: dotTop,
32139
+ type: "row",
32140
+ index: index2 + 1,
32141
+ // This dot will insert at position index+1 (after current row)
32142
+ isHovered: false
32143
+ });
32144
+ });
32145
+ const lastRow = rows[rows.length - 1];
32146
+ if (lastRow) {
32147
+ const lastRowRect = lastRow.getBoundingClientRect();
32148
+ newDots.push({
32149
+ left: tableRect.left - editorLeft - 20,
32150
+ top: lastRowRect.bottom - editorTop - DOT_SIZE / 2,
32151
+ type: "row",
32152
+ index: rows.length,
32153
+ isHovered: false
32154
+ });
32155
+ }
32156
+ if (rows.length > 0) {
32157
+ const firstRow = rows[0];
32158
+ const cells = firstRow.querySelectorAll("td, th");
32159
+ cells.forEach((cell, index2) => {
32160
+ const cellRect = cell.getBoundingClientRect();
32161
+ const dotLeft = cellRect.right - editorLeft - DOT_SIZE / 2;
32162
+ const dotTop = tableRect.top - editorTop - 12;
32163
+ newDots.push({
32164
+ left: dotLeft,
32165
+ top: dotTop,
32166
+ type: "column",
32167
+ index: index2 + 1,
32168
+ // This dot will insert at position index+1 (after current column)
32169
+ isHovered: false
32170
+ });
32171
+ });
32172
+ const lastCell = cells[cells.length - 1];
32173
+ if (lastCell) {
32174
+ const lastCellRect = lastCell.getBoundingClientRect();
32175
+ newDots.push({
32176
+ left: lastCellRect.right - editorLeft - DOT_SIZE / 2,
32177
+ top: tableRect.top - editorTop - 12,
32178
+ type: "column",
32179
+ index: cells.length,
32180
+ isHovered: false
32181
+ });
32182
+ }
32183
+ }
32184
+ rows.forEach((row, index2) => {
32185
+ const rowRect = row.getBoundingClientRect();
32186
+ const buttonTop = rowRect.top - editorTop + (rowRect.height - SELECTOR_BUTTON_SIZE) / 2;
32187
+ const buttonLeft = tableRect.left - editorLeft - SELECTOR_BUTTON_SIZE / 2;
32188
+ newSelectors.push({
32189
+ left: buttonLeft,
32190
+ top: buttonTop,
32191
+ type: "row",
32192
+ index: index2,
32193
+ // The actual row index
32194
+ isHovered: false
32195
+ });
32196
+ });
32197
+ if (rows.length > 0) {
32198
+ const firstRow = rows[0];
32199
+ const cells = firstRow.querySelectorAll("td, th");
32200
+ cells.forEach((cell, index2) => {
32201
+ const cellRect = cell.getBoundingClientRect();
32202
+ const buttonLeft = cellRect.left - editorLeft + (cellRect.width - SELECTOR_BUTTON_SIZE) / 2;
32203
+ const buttonTop = tableRect.top - editorTop - SELECTOR_BUTTON_SIZE / 2;
32204
+ newSelectors.push({
32205
+ left: buttonLeft,
32206
+ top: buttonTop,
32207
+ type: "column",
32208
+ index: index2,
32209
+ // The actual column index
32210
+ isHovered: false
32211
+ });
32212
+ });
32213
+ }
32214
+ setDots(newDots);
32215
+ setSelectorButtons(newSelectors);
32216
+ }, [anchorElem]);
31714
32217
  const debouncedOnMouseMove = useDebounce(
31715
32218
  (event) => {
31716
- window.lastMouseX = event.clientX;
31717
- window.lastMouseY = event.clientY;
31718
32219
  const { isOutside, tableDOMNode } = getMouseInfo(event);
31719
- if (isOutside) {
31720
- setShownRow(false);
31721
- setShownColumn(false);
31722
- return;
31723
- }
31724
- if (!tableDOMNode) {
31725
- return;
31726
- }
31727
- tableCellDOMNodeRef.current = tableDOMNode;
31728
- let tableDOMElement = null;
31729
- editor.getEditorState().read(
31730
- () => {
31731
- const maybeTableCell = $getNearestNodeFromDOMNode(tableDOMNode);
31732
- if ($isTableCellNode(maybeTableCell)) {
31733
- const table = $findMatchingParent(
31734
- maybeTableCell,
31735
- (node) => $isTableNode(node)
31736
- );
31737
- if (!$isTableNode(table)) {
31738
- return;
31739
- }
31740
- tableDOMElement = getTableElement(
31741
- table,
31742
- editor.getElementByKey(table.getKey())
31743
- );
31744
- }
31745
- },
31746
- { editor }
31747
- );
31748
- if (tableDOMElement) {
31749
- const {
31750
- width: tableElemWidth,
31751
- y: tableElemY,
31752
- left: tableElemLeft,
31753
- bottom: tableElemBottom,
31754
- height: tableElemHeight
31755
- } = tableDOMElement.getBoundingClientRect();
31756
- const { y: editorElemY, left: editorElemLeft } = anchorElem.getBoundingClientRect();
31757
- setShownRow(true);
31758
- setShownColumn(true);
31759
- let actualTableWidth = tableElemWidth;
31760
- const firstRow = tableDOMElement.querySelector("tr");
31761
- if (firstRow) {
31762
- const cells = firstRow.querySelectorAll("td, th");
31763
- if (cells.length > 0) {
31764
- let sumWidth = 0;
31765
- cells.forEach((cell) => {
31766
- sumWidth += cell.offsetWidth;
31767
- });
31768
- if (sumWidth > 0 && sumWidth < tableElemWidth) {
31769
- actualTableWidth = sumWidth;
32220
+ if (isOutside || !tableDOMNode) {
32221
+ const hasFocusInTable = editor.getEditorState().read(() => {
32222
+ const selection = editor.getEditorState()._selection;
32223
+ if (!selection)
32224
+ return false;
32225
+ const nodes = selection.getNodes();
32226
+ for (const node of nodes) {
32227
+ const tableCell = $findMatchingParent(node, (n) => $isTableCellNode(n));
32228
+ if (tableCell && $isTableCellNode(tableCell)) {
32229
+ return true;
31770
32230
  }
31771
32231
  }
31772
- }
31773
- const tableRelativeLeft = tableElemLeft - editorElemLeft;
31774
- const tableRelativeRight = tableRelativeLeft + actualTableWidth;
31775
- setPosition({
31776
- row: {
31777
- height: BUTTON_WIDTH_PX,
31778
- left: tableRelativeLeft,
31779
- top: tableElemBottom - editorElemY + 5,
31780
- width: actualTableWidth
31781
- },
31782
- column: {
31783
- height: tableElemHeight,
31784
- left: tableRelativeRight + 5,
31785
- top: tableElemY - editorElemY,
31786
- width: BUTTON_WIDTH_PX
31787
- }
32232
+ return false;
31788
32233
  });
32234
+ if (!hasFocusInTable) {
32235
+ setDots([]);
32236
+ setSelectorButtons([]);
32237
+ setHoveredDot(null);
32238
+ setHoveredRowColumn({ row: null, column: null });
32239
+ currentTableRef.current = null;
32240
+ currentTableKeyRef.current = null;
32241
+ }
32242
+ return;
32243
+ }
32244
+ if (tableDOMNode && currentTableRef.current) {
32245
+ const tableElement = currentTableRef.current;
32246
+ const rows = tableElement.querySelectorAll("tr");
32247
+ const target = event.target;
32248
+ const cellElement = target.closest("td, th");
32249
+ if (cellElement) {
32250
+ const rowElement = cellElement.closest("tr");
32251
+ const rowIndex = Array.from(rows).indexOf(rowElement);
32252
+ const row = rowElement;
32253
+ const cells = row.querySelectorAll("td, th");
32254
+ const colIndex = Array.from(cells).indexOf(cellElement);
32255
+ setHoveredRowColumn({ row: rowIndex, column: colIndex });
32256
+ }
31789
32257
  }
31790
32258
  },
31791
32259
  50,
31792
32260
  250
31793
32261
  );
31794
- const tableResizeObserver = useMemo(() => {
31795
- return new ResizeObserver(() => {
31796
- const lastX = window.lastMouseX || 0;
31797
- const lastY = window.lastMouseY || 0;
31798
- const mouseEvent = new MouseEvent("mousemove", {
31799
- clientX: lastX,
31800
- clientY: lastY
32262
+ const handleDotClick = (type, index2) => {
32263
+ if (!currentTableKeyRef.current)
32264
+ return;
32265
+ editor.update(() => {
32266
+ const tableNode = editor.getEditorState().read(() => {
32267
+ const nodeKey = currentTableKeyRef.current;
32268
+ if (!nodeKey)
32269
+ return null;
32270
+ const node = editor.getEditorState()._nodeMap.get(nodeKey);
32271
+ return $isTableNode(node) ? node : null;
31801
32272
  });
31802
- const { isOutside } = getMouseInfo(mouseEvent);
31803
- if (isOutside) {
31804
- setShownRow(false);
31805
- setShownColumn(false);
32273
+ if (!tableNode)
32274
+ return;
32275
+ if (type === "row") {
32276
+ const rows = tableNode.getChildren();
32277
+ const targetRowIndex = index2 - 1;
32278
+ if (targetRowIndex >= 0 && targetRowIndex < rows.length) {
32279
+ const targetRow = rows[targetRowIndex];
32280
+ if (targetRow) {
32281
+ const cells = targetRow.getChildren();
32282
+ if (cells.length > 0) {
32283
+ cells[0].selectEnd();
32284
+ $insertTableRow__EXPERIMENTAL(true);
32285
+ const updatedRows = tableNode.getChildren();
32286
+ const newRowIndex = targetRowIndex + 1;
32287
+ if (newRowIndex < updatedRows.length) {
32288
+ const newRow = updatedRows[newRowIndex];
32289
+ const newCells = newRow.getChildren();
32290
+ newCells.forEach((cell) => {
32291
+ cell.setHeaderStyles(TableCellHeaderStates.NO_STATUS);
32292
+ if (cell.getChildrenSize() === 0) {
32293
+ const paragraph = $createParagraphNode();
32294
+ cell.append(paragraph);
32295
+ }
32296
+ });
32297
+ }
32298
+ }
32299
+ }
32300
+ }
32301
+ } else {
32302
+ const rows = tableNode.getChildren();
32303
+ if (rows.length > 0) {
32304
+ const firstRow = rows[0];
32305
+ const cells = firstRow.getChildren();
32306
+ const targetCellIndex = index2 - 1;
32307
+ if (targetCellIndex >= 0 && targetCellIndex < cells.length) {
32308
+ const targetCell = cells[targetCellIndex];
32309
+ if (targetCell) {
32310
+ targetCell.selectEnd();
32311
+ $insertTableColumn__EXPERIMENTAL(true);
32312
+ const hasColumnHeaders = (cells[0].getHeaderStyles() & TableCellHeaderStates.COLUMN) === TableCellHeaderStates.COLUMN;
32313
+ if (hasColumnHeaders) {
32314
+ const updatedFirstRow = tableNode.getChildren()[0];
32315
+ const updatedCells = updatedFirstRow.getChildren();
32316
+ const newHeaderCell = updatedCells[index2];
32317
+ if (newHeaderCell && $isTableCellNode(newHeaderCell)) {
32318
+ newHeaderCell.setHeaderStyles(TableCellHeaderStates.COLUMN);
32319
+ const headerBackgroundColor = cells[0].getBackgroundColor();
32320
+ if (headerBackgroundColor) {
32321
+ newHeaderCell.setBackgroundColor(headerBackgroundColor);
32322
+ }
32323
+ if (newHeaderCell.getChildrenSize() === 0) {
32324
+ const paragraph = $createParagraphNode();
32325
+ const textNode = $createTextNode("​");
32326
+ paragraph.append(textNode);
32327
+ newHeaderCell.append(paragraph);
32328
+ } else {
32329
+ const firstChild = newHeaderCell.getFirstChild();
32330
+ if ($isParagraphNode(firstChild) && firstChild.getTextContentSize() === 0) {
32331
+ const textNode = $createTextNode("​");
32332
+ firstChild.append(textNode);
32333
+ }
32334
+ }
32335
+ }
32336
+ }
32337
+ }
32338
+ }
32339
+ }
31806
32340
  }
31807
32341
  });
31808
- }, []);
31809
- useEffect$1(() => {
31810
- if (!shouldListenMouseMove) {
32342
+ setTimeout(() => {
32343
+ if (currentTableRef.current) {
32344
+ calculateDotPositions(currentTableRef.current);
32345
+ }
32346
+ }, 100);
32347
+ };
32348
+ const handleSelectorClick = (type, index2) => {
32349
+ if (!currentTableKeyRef.current)
31811
32350
  return;
31812
- }
31813
- document.addEventListener("mousemove", debouncedOnMouseMove);
31814
- return () => {
31815
- setShownRow(false);
31816
- setShownColumn(false);
31817
- debouncedOnMouseMove.cancel();
31818
- document.removeEventListener("mousemove", debouncedOnMouseMove);
31819
- };
31820
- }, [shouldListenMouseMove, debouncedOnMouseMove]);
31821
- useEffect$1(() => {
31822
- return mergeRegister(
31823
- editor.registerMutationListener(
31824
- TableNode,
31825
- (mutations) => {
31826
- editor.getEditorState().read(
32351
+ console.log(`[HoverPlugin] Selector clicked - Type: ${type}, Index: ${index2}`);
32352
+ editor.update(() => {
32353
+ const { tableNode } = $getTableAndElementByKey(currentTableKeyRef.current);
32354
+ if (!tableNode || !$isTableNode(tableNode)) {
32355
+ console.log("[HoverPlugin] Table node not found");
32356
+ return;
32357
+ }
32358
+ console.log("[HoverPlugin] Table node found, creating selection");
32359
+ if (type === "row") {
32360
+ const rows = tableNode.getChildren();
32361
+ if (index2 >= 0 && index2 < rows.length) {
32362
+ const targetRow = rows[index2];
32363
+ const cells = targetRow.getChildren();
32364
+ if (cells.length > 0) {
32365
+ const firstCell = cells[0];
32366
+ const lastCell = cells[cells.length - 1];
32367
+ console.log(`[HoverPlugin] Selecting row ${index2}, cells: ${cells.length}`);
32368
+ firstCell.selectEnd();
32369
+ const selection = firstCell.select();
32370
+ if (selection) {
32371
+ selection.focus.set(lastCell.getKey(), lastCell.getChildrenSize(), "element");
32372
+ console.log("[HoverPlugin] Row selection created");
32373
+ setTimeout(() => {
32374
+ const firstCellDOM = editor.getElementByKey(firstCell.getKey());
32375
+ if (firstCellDOM) {
32376
+ const event = new MouseEvent("contextmenu", {
32377
+ bubbles: true,
32378
+ cancelable: true,
32379
+ view: window,
32380
+ button: 2,
32381
+ clientX: firstCellDOM.getBoundingClientRect().left + 10,
32382
+ clientY: firstCellDOM.getBoundingClientRect().top + 10
32383
+ });
32384
+ firstCellDOM.dispatchEvent(event);
32385
+ console.log("[HoverPlugin] Context menu triggered");
32386
+ }
32387
+ }, 50);
32388
+ }
32389
+ }
32390
+ }
32391
+ } else {
32392
+ const rows = tableNode.getChildren();
32393
+ if (rows.length > 0) {
32394
+ const firstRow = rows[0];
32395
+ const firstRowCells = firstRow.getChildren();
32396
+ if (index2 >= 0 && index2 < firstRowCells.length) {
32397
+ const firstCell = firstRowCells[index2];
32398
+ const lastRow = rows[rows.length - 1];
32399
+ const lastRowCells = lastRow.getChildren();
32400
+ const lastCell = lastRowCells[index2];
32401
+ console.log(`[HoverPlugin] Selecting column ${index2}, rows: ${rows.length}`);
32402
+ if (firstCell && lastCell) {
32403
+ firstCell.selectEnd();
32404
+ const selection = firstCell.select();
32405
+ if (selection) {
32406
+ selection.focus.set(lastCell.getKey(), lastCell.getChildrenSize(), "element");
32407
+ console.log("[HoverPlugin] Column selection created");
32408
+ setTimeout(() => {
32409
+ const firstCellDOM = editor.getElementByKey(firstCell.getKey());
32410
+ if (firstCellDOM) {
32411
+ const event = new MouseEvent("contextmenu", {
32412
+ bubbles: true,
32413
+ cancelable: true,
32414
+ view: window,
32415
+ button: 2,
32416
+ clientX: firstCellDOM.getBoundingClientRect().left + 10,
32417
+ clientY: firstCellDOM.getBoundingClientRect().top + 10
32418
+ });
32419
+ firstCellDOM.dispatchEvent(event);
32420
+ console.log("[HoverPlugin] Context menu triggered");
32421
+ }
32422
+ }, 50);
32423
+ }
32424
+ }
32425
+ }
32426
+ }
32427
+ }
32428
+ });
32429
+ };
32430
+ const handleDragStart = (e, type, index2) => {
32431
+ e.stopPropagation();
32432
+ setTimeout(() => {
32433
+ setDragState({ type, sourceIndex: index2, targetIndex: null });
32434
+ }, 0);
32435
+ setTimeout(() => {
32436
+ if (type === "row") {
32437
+ setHighlightedRow(index2);
32438
+ } else {
32439
+ setHighlightedColumn(index2);
32440
+ }
32441
+ }, 0);
32442
+ e.dataTransfer.effectAllowed = "move";
32443
+ e.dataTransfer.dropEffect = "move";
32444
+ e.dataTransfer.setData("application/x-table-dnd", JSON.stringify({ type, index: index2 }));
32445
+ if (currentTableRef.current) {
32446
+ const dragPreview = document.createElement("div");
32447
+ dragPreview.style.position = "absolute";
32448
+ dragPreview.style.top = "-1000px";
32449
+ dragPreview.style.padding = "8px 16px";
32450
+ dragPreview.style.backgroundColor = "#3b82f6";
32451
+ dragPreview.style.color = "white";
32452
+ dragPreview.style.borderRadius = "6px";
32453
+ dragPreview.style.fontSize = "14px";
32454
+ dragPreview.style.fontWeight = "600";
32455
+ dragPreview.style.boxShadow = "0 4px 12px rgba(0,0,0,0.3)";
32456
+ dragPreview.style.pointerEvents = "none";
32457
+ dragPreview.textContent = `${type === "row" ? "↕" : "↔"} Moving ${type} ${index2 + 1}`;
32458
+ document.body.appendChild(dragPreview);
32459
+ e.dataTransfer.setDragImage(dragPreview, dragPreview.offsetWidth / 2, dragPreview.offsetHeight / 2);
32460
+ setTimeout(() => {
32461
+ if (document.body.contains(dragPreview)) {
32462
+ document.body.removeChild(dragPreview);
32463
+ }
32464
+ }, 0);
32465
+ }
32466
+ };
32467
+ const handleDragOver = (e, type, targetIndex) => {
32468
+ e.preventDefault();
32469
+ e.dataTransfer.dropEffect = "move";
32470
+ if (!dragState || dragState.type !== type) {
32471
+ return;
32472
+ }
32473
+ if (dragState.targetIndex !== targetIndex) {
32474
+ setDragState((prev) => prev ? { ...prev, targetIndex } : null);
32475
+ }
32476
+ if (type === "row") {
32477
+ setTargetHighlightedRow(targetIndex);
32478
+ setTargetHighlightedColumn(null);
32479
+ } else {
32480
+ setTargetHighlightedColumn(targetIndex);
32481
+ setTargetHighlightedRow(null);
32482
+ }
32483
+ if (currentTableRef.current) {
32484
+ const tableRect = currentTableRef.current.getBoundingClientRect();
32485
+ const { left: editorLeft, top: editorTop } = anchorElem.getBoundingClientRect();
32486
+ if (type === "row") {
32487
+ const rows = currentTableRef.current.querySelectorAll("tr");
32488
+ if (targetIndex >= 0 && targetIndex < rows.length) {
32489
+ const targetRow = rows[targetIndex];
32490
+ const rowRect = targetRow.getBoundingClientRect();
32491
+ const sourceIndex = dragState.sourceIndex;
32492
+ if (sourceIndex < targetIndex) {
32493
+ setDragPreviewLine({
32494
+ top: rowRect.bottom - editorTop,
32495
+ left: tableRect.left - editorLeft,
32496
+ width: tableRect.width,
32497
+ height: 3,
32498
+ isHorizontal: true
32499
+ });
32500
+ } else {
32501
+ setDragPreviewLine({
32502
+ top: rowRect.top - editorTop,
32503
+ left: tableRect.left - editorLeft,
32504
+ width: tableRect.width,
32505
+ height: 3,
32506
+ isHorizontal: true
32507
+ });
32508
+ }
32509
+ }
32510
+ } else {
32511
+ const rows = currentTableRef.current.querySelectorAll("tr");
32512
+ if (rows.length > 0) {
32513
+ const firstRow = rows[0];
32514
+ const cells = firstRow.querySelectorAll("td, th");
32515
+ if (targetIndex >= 0 && targetIndex < cells.length) {
32516
+ const targetCell = cells[targetIndex];
32517
+ const cellRect = targetCell.getBoundingClientRect();
32518
+ const sourceIndex = dragState.sourceIndex;
32519
+ if (sourceIndex < targetIndex) {
32520
+ setDragPreviewLine({
32521
+ top: tableRect.top - editorTop,
32522
+ left: cellRect.right - editorLeft,
32523
+ width: 3,
32524
+ height: tableRect.height,
32525
+ isHorizontal: false
32526
+ });
32527
+ } else {
32528
+ setDragPreviewLine({
32529
+ top: tableRect.top - editorTop,
32530
+ left: cellRect.left - editorLeft,
32531
+ width: 3,
32532
+ height: tableRect.height,
32533
+ isHorizontal: false
32534
+ });
32535
+ }
32536
+ }
32537
+ }
32538
+ }
32539
+ }
32540
+ };
32541
+ const handleDrop = (e) => {
32542
+ e.preventDefault();
32543
+ if (!dragState) {
32544
+ setDragPreviewLine(null);
32545
+ setHighlightedRow(null);
32546
+ setHighlightedColumn(null);
32547
+ setTargetHighlightedRow(null);
32548
+ setTargetHighlightedColumn(null);
32549
+ return;
32550
+ }
32551
+ const targetIndex = dragState.targetIndex;
32552
+ if (targetIndex === null) {
32553
+ setDragState(null);
32554
+ setDragPreviewLine(null);
32555
+ setHighlightedRow(null);
32556
+ setHighlightedColumn(null);
32557
+ setTargetHighlightedRow(null);
32558
+ setTargetHighlightedColumn(null);
32559
+ return;
32560
+ }
32561
+ if (dragState.sourceIndex === targetIndex) {
32562
+ setDragState(null);
32563
+ setDragPreviewLine(null);
32564
+ setHighlightedRow(null);
32565
+ setHighlightedColumn(null);
32566
+ setTargetHighlightedRow(null);
32567
+ setTargetHighlightedColumn(null);
32568
+ return;
32569
+ }
32570
+ const { type, sourceIndex } = dragState;
32571
+ let actualColWidths = [];
32572
+ let tableActualWidth = 0;
32573
+ if (currentTableRef.current) {
32574
+ tableActualWidth = currentTableRef.current.getBoundingClientRect().width;
32575
+ const firstRow = currentTableRef.current.querySelector("tr");
32576
+ if (firstRow) {
32577
+ const cells = firstRow.querySelectorAll("td, th");
32578
+ actualColWidths = Array.from(cells).map((cell) => {
32579
+ return cell.getBoundingClientRect().width;
32580
+ });
32581
+ }
32582
+ }
32583
+ console.log("[TABLE-DND] BEFORE DROP:");
32584
+ console.log(" - Table actual width:", tableActualWidth);
32585
+ console.log(" - Captured DOM column widths:", actualColWidths);
32586
+ console.log(" - Source index:", sourceIndex, "Target index:", targetIndex, "Type:", type);
32587
+ editor.update(() => {
32588
+ if (!currentTableKeyRef.current) {
32589
+ return;
32590
+ }
32591
+ try {
32592
+ const result = $getTableAndElementByKey(currentTableKeyRef.current);
32593
+ const tableNode = result.tableNode;
32594
+ if (!tableNode || !$isTableNode(tableNode)) {
32595
+ return;
32596
+ }
32597
+ const preservedColWidths = tableNode.getColWidths();
32598
+ console.log("[TABLE-DND] Lexical stored column widths:", preservedColWidths);
32599
+ if (type === "row") {
32600
+ const rows = tableNode.getChildren();
32601
+ if (sourceIndex >= 0 && sourceIndex < rows.length && targetIndex >= 0 && targetIndex < rows.length) {
32602
+ const sourceRow = rows[sourceIndex];
32603
+ sourceRow.remove();
32604
+ const updatedRows = tableNode.getChildren();
32605
+ let movedRow = null;
32606
+ if (sourceIndex < targetIndex) {
32607
+ const adjustedTargetIndex = targetIndex - 1;
32608
+ if (adjustedTargetIndex >= 0 && adjustedTargetIndex < updatedRows.length) {
32609
+ const adjustedTarget = updatedRows[adjustedTargetIndex];
32610
+ adjustedTarget.insertAfter(sourceRow);
32611
+ movedRow = adjustedTarget.getNextSibling();
32612
+ } else {
32613
+ tableNode.append(sourceRow);
32614
+ movedRow = tableNode.getLastChild();
32615
+ }
32616
+ } else {
32617
+ if (targetIndex < updatedRows.length) {
32618
+ const adjustedTarget = updatedRows[targetIndex];
32619
+ adjustedTarget.insertBefore(sourceRow);
32620
+ movedRow = adjustedTarget.getPreviousSibling();
32621
+ } else {
32622
+ tableNode.append(sourceRow);
32623
+ movedRow = tableNode.getLastChild();
32624
+ }
32625
+ }
32626
+ if (movedRow && movedRow.getChildrenSize() > 0) {
32627
+ const firstCell = movedRow.getFirstChild();
32628
+ if (firstCell && $isTableCellNode(firstCell)) {
32629
+ firstCell.select();
32630
+ }
32631
+ }
32632
+ }
32633
+ } else {
32634
+ const rows = tableNode.getChildren();
32635
+ rows.forEach((row) => {
32636
+ const cells = row.getChildren();
32637
+ if (sourceIndex >= 0 && sourceIndex < cells.length && targetIndex >= 0 && targetIndex < cells.length) {
32638
+ const sourceCell = cells[sourceIndex];
32639
+ sourceCell.remove();
32640
+ const updatedCells = row.getChildren();
32641
+ if (sourceIndex < targetIndex) {
32642
+ const adjustedTargetIndex = targetIndex - 1;
32643
+ if (adjustedTargetIndex >= 0 && adjustedTargetIndex < updatedCells.length) {
32644
+ const adjustedTarget = updatedCells[adjustedTargetIndex];
32645
+ adjustedTarget.insertAfter(sourceCell);
32646
+ } else {
32647
+ row.append(sourceCell);
32648
+ }
32649
+ } else {
32650
+ if (targetIndex < updatedCells.length) {
32651
+ const adjustedTarget = updatedCells[targetIndex];
32652
+ adjustedTarget.insertBefore(sourceCell);
32653
+ } else {
32654
+ row.append(sourceCell);
32655
+ }
32656
+ }
32657
+ }
32658
+ });
32659
+ }
32660
+ const widthsToRestore = actualColWidths.length > 0 ? actualColWidths : preservedColWidths;
32661
+ console.log("[TABLE-DND] Widths to restore:", widthsToRestore);
32662
+ if (widthsToRestore && widthsToRestore.length > 0) {
32663
+ tableNode.setColWidths(widthsToRestore);
32664
+ console.log("[TABLE-DND] Column widths restored");
32665
+ } else {
32666
+ console.log("[TABLE-DND] WARNING: No widths available to restore!");
32667
+ }
32668
+ } catch (error) {
32669
+ console.error(`[TABLE-DND] ERROR during swap:`, error);
32670
+ }
32671
+ });
32672
+ setTimeout(() => {
32673
+ if (currentTableRef.current) {
32674
+ const newTableWidth = currentTableRef.current.getBoundingClientRect().width;
32675
+ const firstRow = currentTableRef.current.querySelector("tr");
32676
+ let newColWidths = [];
32677
+ if (firstRow) {
32678
+ const cells = firstRow.querySelectorAll("td, th");
32679
+ newColWidths = Array.from(cells).map((cell) => {
32680
+ return cell.getBoundingClientRect().width;
32681
+ });
32682
+ }
32683
+ console.log("[TABLE-DND] AFTER DROP:");
32684
+ console.log(" - Table actual width:", newTableWidth);
32685
+ console.log(" - New DOM column widths:", newColWidths);
32686
+ console.log(" - Width changed:", tableActualWidth !== newTableWidth);
32687
+ }
32688
+ }, 100);
32689
+ setDragState(null);
32690
+ setDragPreviewLine(null);
32691
+ setHighlightedRow(null);
32692
+ setHighlightedColumn(null);
32693
+ setTargetHighlightedRow(null);
32694
+ setTargetHighlightedColumn(null);
32695
+ setTimeout(() => {
32696
+ if (currentTableRef.current) {
32697
+ calculateDotPositions(currentTableRef.current);
32698
+ }
32699
+ }, 50);
32700
+ };
32701
+ const handleDragEnd = (_e) => {
32702
+ setTimeout(() => {
32703
+ setDragState(null);
32704
+ setDragPreviewLine(null);
32705
+ setHighlightedRow(null);
32706
+ setHighlightedColumn(null);
32707
+ setTargetHighlightedRow(null);
32708
+ setTargetHighlightedColumn(null);
32709
+ }, 50);
32710
+ };
32711
+ const tableResizeObserver = useMemo(() => {
32712
+ return new ResizeObserver(() => {
32713
+ if (currentTableRef.current) {
32714
+ calculateDotPositions(currentTableRef.current);
32715
+ }
32716
+ });
32717
+ }, [calculateDotPositions]);
32718
+ useEffect$1(() => {
32719
+ if (!shouldListenMouseMove) {
32720
+ return;
32721
+ }
32722
+ document.addEventListener("mousemove", debouncedOnMouseMove);
32723
+ return () => {
32724
+ setDots([]);
32725
+ setSelectorButtons([]);
32726
+ setHoveredDot(null);
32727
+ debouncedOnMouseMove.cancel();
32728
+ document.removeEventListener("mousemove", debouncedOnMouseMove);
32729
+ };
32730
+ }, [shouldListenMouseMove, debouncedOnMouseMove]);
32731
+ useEffect$1(() => {
32732
+ if (!activeTableDOM)
32733
+ return;
32734
+ const handleScroll2 = () => {
32735
+ requestAnimationFrame(() => {
32736
+ calculateDotPositions(activeTableDOM);
32737
+ });
32738
+ };
32739
+ window.addEventListener("scroll", handleScroll2, { capture: true, passive: true });
32740
+ window.addEventListener("resize", handleScroll2);
32741
+ return () => {
32742
+ window.removeEventListener("scroll", handleScroll2, { capture: true });
32743
+ window.removeEventListener("resize", handleScroll2);
32744
+ };
32745
+ }, [activeTableDOM, calculateDotPositions]);
32746
+ useEffect$1(() => {
32747
+ return mergeRegister(
32748
+ editor.registerUpdateListener(({ editorState }) => {
32749
+ editorState.read(() => {
32750
+ const selection = editorState._selection;
32751
+ if (!selection) {
32752
+ setDots([]);
32753
+ setSelectorButtons([]);
32754
+ setHoveredDot(null);
32755
+ currentTableRef.current = null;
32756
+ currentTableKeyRef.current = null;
32757
+ return;
32758
+ }
32759
+ const nodes = selection.getNodes();
32760
+ let foundTable = false;
32761
+ for (const node of nodes) {
32762
+ const tableCell = $findMatchingParent(node, (n) => $isTableCellNode(n));
32763
+ if (tableCell && $isTableCellNode(tableCell)) {
32764
+ const table = $findMatchingParent(tableCell, (n) => $isTableNode(n));
32765
+ if (table && $isTableNode(table)) {
32766
+ const tableElement = getTableElement(
32767
+ table,
32768
+ editor.getElementByKey(table.getKey())
32769
+ );
32770
+ if (tableElement) {
32771
+ currentTableRef.current = tableElement;
32772
+ currentTableKeyRef.current = table.getKey();
32773
+ setActiveTableDOM(tableElement);
32774
+ calculateDotPositions(tableElement);
32775
+ foundTable = true;
32776
+ }
32777
+ return;
32778
+ }
32779
+ }
32780
+ }
32781
+ if (!foundTable) {
32782
+ setDots([]);
32783
+ setSelectorButtons([]);
32784
+ setHoveredDot(null);
32785
+ currentTableRef.current = null;
32786
+ currentTableKeyRef.current = null;
32787
+ setActiveTableDOM(null);
32788
+ }
32789
+ });
32790
+ }),
32791
+ editor.registerMutationListener(
32792
+ TableNode,
32793
+ (mutations) => {
32794
+ editor.getEditorState().read(
31827
32795
  () => {
31828
32796
  let resetObserver = false;
31829
32797
  for (const [key, type] of mutations) {
@@ -31855,109 +32823,404 @@ function TableHoverActionsContainer({
31855
32823
  { skipInitialization: false }
31856
32824
  )
31857
32825
  );
31858
- }, [editor, tableResizeObserver]);
31859
- const insertAction = (insertRow) => {
31860
- editor.update(() => {
31861
- if (tableCellDOMNodeRef.current) {
31862
- const maybeTableNode = $getNearestNodeFromDOMNode(
31863
- tableCellDOMNodeRef.current
31864
- );
31865
- maybeTableNode == null ? void 0 : maybeTableNode.selectEnd();
31866
- if (insertRow) {
31867
- $insertTableRow__EXPERIMENTAL();
31868
- setShownRow(false);
31869
- } else {
31870
- $insertTableColumn__EXPERIMENTAL();
31871
- setShownColumn(false);
31872
- const tableCellNode = $getNearestNodeFromDOMNode(tableCellDOMNodeRef.current);
31873
- if ($isTableCellNode(tableCellNode)) {
31874
- const tableNode = $findMatchingParent(
31875
- tableCellNode,
31876
- (node) => $isTableNode(node)
31877
- );
31878
- if ($isTableNode(tableNode)) {
31879
- const rows = tableNode.getChildren();
31880
- if (rows.length > 0) {
31881
- const firstRow = rows[0];
31882
- const firstRowCells = firstRow.getChildren();
31883
- if (firstRowCells.length > 0) {
31884
- const firstCell = firstRowCells[0];
31885
- const hasColumnHeaders = (firstCell.getHeaderStyles() & TableCellHeaderStates.COLUMN) === TableCellHeaderStates.COLUMN;
31886
- if (hasColumnHeaders) {
31887
- const newHeaderCell = firstRowCells[firstRowCells.length - 1];
31888
- newHeaderCell.setHeaderStyles(TableCellHeaderStates.COLUMN);
31889
- const headerBackgroundColor = firstCell.getBackgroundColor();
31890
- if (headerBackgroundColor) {
31891
- newHeaderCell.setBackgroundColor(headerBackgroundColor);
31892
- }
31893
- }
32826
+ }, [editor, tableResizeObserver, calculateDotPositions]);
32827
+ if (!isEditable) {
32828
+ return null;
32829
+ }
32830
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
32831
+ dots.map((dot, idx) => {
32832
+ const isHovered = (hoveredDot == null ? void 0 : hoveredDot.type) === dot.type && (hoveredDot == null ? void 0 : hoveredDot.index) === dot.index;
32833
+ const size2 = isHovered ? DOT_HOVER_SIZE : DOT_SIZE;
32834
+ return /* @__PURE__ */ jsx(
32835
+ "div",
32836
+ {
32837
+ style: {
32838
+ position: "absolute",
32839
+ left: `${dot.left - 12}px`,
32840
+ // Center hover zone on dot position
32841
+ top: `${dot.top - 12}px`,
32842
+ width: `${DOT_HOVER_SIZE + 16}px`,
32843
+ // Fixed larger hover zone
32844
+ height: `${DOT_HOVER_SIZE + 16}px`,
32845
+ display: "flex",
32846
+ alignItems: "center",
32847
+ justifyContent: "center",
32848
+ zIndex: 1e3
32849
+ },
32850
+ onMouseEnter: () => setHoveredDot({ type: dot.type, index: dot.index }),
32851
+ onMouseLeave: () => setHoveredDot(null),
32852
+ children: /* @__PURE__ */ jsx(
32853
+ "button",
32854
+ {
32855
+ className: `table-insert-dot ${isHovered ? "hovered" : ""}`,
32856
+ style: {
32857
+ width: `${size2}px`,
32858
+ height: `${size2}px`,
32859
+ borderRadius: "50%",
32860
+ backgroundColor: isHovered ? "white" : "transparent",
32861
+ border: `2px solid ${isHovered ? "#4b5563" : "#9ca3af"}`,
32862
+ cursor: "pointer",
32863
+ display: "flex",
32864
+ alignItems: "center",
32865
+ justifyContent: "center",
32866
+ transition: "all 0.2s ease",
32867
+ padding: 0,
32868
+ position: "relative",
32869
+ transform: isHovered ? "scale(1)" : "scale(1)"
32870
+ // Keep centered while scaling
32871
+ },
32872
+ onClick: () => handleDotClick(dot.type, dot.index),
32873
+ "aria-label": `Insert ${dot.type} ${dot.type === "row" ? "here" : "here"}`,
32874
+ role: "button",
32875
+ tabIndex: 0,
32876
+ children: isHovered && /* @__PURE__ */ jsxs(
32877
+ "svg",
32878
+ {
32879
+ width: "10",
32880
+ height: "10",
32881
+ viewBox: "0 0 10 10",
32882
+ style: {
32883
+ position: "absolute",
32884
+ top: "50%",
32885
+ left: "50%",
32886
+ transform: "translate(-50%, -50%)"
32887
+ },
32888
+ children: [
32889
+ /* @__PURE__ */ jsx("line", { x1: "5", y1: "1", x2: "5", y2: "9", stroke: "#4b5563", strokeWidth: "1.5", strokeLinecap: "round" }),
32890
+ /* @__PURE__ */ jsx("line", { x1: "1", y1: "5", x2: "9", y2: "5", stroke: "#4b5563", strokeWidth: "1.5", strokeLinecap: "round" })
32891
+ ]
31894
32892
  }
31895
- }
32893
+ )
32894
+ }
32895
+ )
32896
+ },
32897
+ `${dot.type}-${dot.index}-${idx}`
32898
+ );
32899
+ }),
32900
+ selectorButtons.map((selector, idx) => {
32901
+ const isDirectHover = (hoveredSelector == null ? void 0 : hoveredSelector.type) === selector.type && (hoveredSelector == null ? void 0 : hoveredSelector.index) === selector.index;
32902
+ const isRowColumnHovered = selector.type === "row" && hoveredRowColumn.row === selector.index || selector.type === "column" && hoveredRowColumn.column === selector.index;
32903
+ const shouldShow = isDirectHover || isRowColumnHovered;
32904
+ const isDragging = (dragState == null ? void 0 : dragState.type) === selector.type && (dragState == null ? void 0 : dragState.sourceIndex) === selector.index;
32905
+ const isDropTarget = (dragState == null ? void 0 : dragState.type) === selector.type && (dragState == null ? void 0 : dragState.targetIndex) === selector.index;
32906
+ return /* @__PURE__ */ jsx(
32907
+ "div",
32908
+ {
32909
+ style: {
32910
+ position: "absolute",
32911
+ left: `${selector.left - (isDirectHover ? 4 : 0)}px`,
32912
+ // Expand left when hovered
32913
+ top: `${selector.top - (isDirectHover ? 4 : 0)}px`,
32914
+ // Expand top when hovered
32915
+ width: `${isDirectHover ? SELECTOR_BUTTON_SIZE + 8 : SELECTOR_BUTTON_SIZE}px`,
32916
+ // Expand to ~20px when hovered
32917
+ height: `${isDirectHover ? SELECTOR_BUTTON_SIZE + 8 : SELECTOR_BUTTON_SIZE}px`,
32918
+ zIndex: 1e3,
32919
+ opacity: isDragging ? 0.5 : 1
32920
+ },
32921
+ onMouseEnter: () => {
32922
+ setHoveredSelector({ type: selector.type, index: selector.index });
32923
+ if (selector.type === "row") {
32924
+ setHighlightedRow(selector.index);
32925
+ } else {
32926
+ setHighlightedColumn(selector.index);
32927
+ }
32928
+ },
32929
+ onMouseLeave: () => {
32930
+ setHoveredSelector(null);
32931
+ if (!dragState) {
32932
+ setHighlightedRow(null);
32933
+ setHighlightedColumn(null);
32934
+ }
32935
+ },
32936
+ children: /* @__PURE__ */ jsx(
32937
+ "button",
32938
+ {
32939
+ className: "table-selector-button",
32940
+ draggable: shouldShow,
32941
+ onDragStart: (e) => {
32942
+ if (!shouldShow) {
32943
+ e.preventDefault();
32944
+ return;
32945
+ }
32946
+ handleDragStart(e, selector.type, selector.index);
32947
+ },
32948
+ onDragEnd: handleDragEnd,
32949
+ style: {
32950
+ width: "100%",
32951
+ height: "100%",
32952
+ borderRadius: "3px",
32953
+ backgroundColor: isDropTarget ? "#22c55e" : isDirectHover ? "#3b82f6" : isRowColumnHovered ? "#6b7280" : "transparent",
32954
+ border: "none",
32955
+ cursor: isDragging ? "grabbing" : isDirectHover ? "grab" : "pointer",
32956
+ display: "flex",
32957
+ alignItems: "center",
32958
+ justifyContent: "center",
32959
+ transition: "all 0.15s ease",
32960
+ padding: 0,
32961
+ opacity: shouldShow ? isDirectHover ? 1 : 0.6 : 0,
32962
+ boxShadow: isDirectHover ? "0 2px 4px rgba(0,0,0,0.2)" : "none"
32963
+ },
32964
+ onClick: () => {
32965
+ if (!dragState) {
32966
+ handleSelectorClick(selector.type, selector.index);
32967
+ }
32968
+ },
32969
+ "aria-label": `Drag to move or click to select ${selector.type} ${selector.index + 1}`,
32970
+ role: "button",
32971
+ tabIndex: 0,
32972
+ children: isDirectHover && /* @__PURE__ */ jsxs(
32973
+ "svg",
32974
+ {
32975
+ width: "16",
32976
+ height: "16",
32977
+ viewBox: "0 0 16 16",
32978
+ fill: "none",
32979
+ xmlns: "http://www.w3.org/2000/svg",
32980
+ style: { pointerEvents: "none" },
32981
+ children: [
32982
+ /* @__PURE__ */ jsx("circle", { cx: "5.5", cy: "3.5", r: "1.2", fill: "white" }),
32983
+ /* @__PURE__ */ jsx("circle", { cx: "10.5", cy: "3.5", r: "1.2", fill: "white" }),
32984
+ /* @__PURE__ */ jsx("circle", { cx: "5.5", cy: "8", r: "1.2", fill: "white" }),
32985
+ /* @__PURE__ */ jsx("circle", { cx: "10.5", cy: "8", r: "1.2", fill: "white" }),
32986
+ /* @__PURE__ */ jsx("circle", { cx: "5.5", cy: "12.5", r: "1.2", fill: "white" }),
32987
+ /* @__PURE__ */ jsx("circle", { cx: "10.5", cy: "12.5", r: "1.2", fill: "white" })
32988
+ ]
32989
+ }
32990
+ )
31896
32991
  }
32992
+ )
32993
+ },
32994
+ `selector-${selector.type}-${selector.index}-${idx}`
32995
+ );
32996
+ }),
32997
+ dragState && currentTableRef.current && /* @__PURE__ */ jsx(
32998
+ "div",
32999
+ {
33000
+ style: {
33001
+ position: "absolute",
33002
+ left: `${currentTableRef.current.getBoundingClientRect().left - anchorElem.getBoundingClientRect().left}px`,
33003
+ top: `${currentTableRef.current.getBoundingClientRect().top - anchorElem.getBoundingClientRect().top}px`,
33004
+ width: `${currentTableRef.current.getBoundingClientRect().width}px`,
33005
+ height: `${currentTableRef.current.getBoundingClientRect().height}px`,
33006
+ zIndex: 1e3,
33007
+ pointerEvents: "auto"
33008
+ },
33009
+ onDragOver: (e) => {
33010
+ e.preventDefault();
33011
+ e.stopPropagation();
33012
+ if (!dragState) {
33013
+ return;
31897
33014
  }
31898
- }
31899
- }
31900
- });
31901
- if (!insertRow) {
31902
- requestAnimationFrame(() => {
31903
- const applyHeaderStyles = () => {
31904
- const rootElement = editor.getRootElement();
31905
- if (!rootElement)
31906
- return false;
31907
- const tables = rootElement.querySelectorAll("table");
31908
- tables.forEach((table) => {
31909
- const rows = table.querySelectorAll("tr");
31910
- if (rows.length > 0) {
33015
+ e.dataTransfer.dropEffect = "move";
33016
+ if (!currentTableRef.current)
33017
+ return;
33018
+ if (dragState.type === "row") {
33019
+ const rows = currentTableRef.current.querySelectorAll("tr");
33020
+ const mouseY = e.clientY;
33021
+ let targetRowIndex = -1;
33022
+ for (let i2 = 0; i2 < rows.length; i2++) {
33023
+ const row = rows[i2];
33024
+ const rect = row.getBoundingClientRect();
33025
+ if (mouseY >= rect.top && mouseY <= rect.bottom) {
33026
+ targetRowIndex = i2;
33027
+ break;
33028
+ } else if (mouseY < rect.top && i2 === 0) {
33029
+ targetRowIndex = 0;
33030
+ break;
33031
+ } else if (i2 === rows.length - 1 && mouseY > rect.bottom) {
33032
+ targetRowIndex = rows.length - 1;
33033
+ break;
33034
+ }
33035
+ }
33036
+ if (targetRowIndex === 0) {
31911
33037
  const firstRow = rows[0];
31912
- const cells = firstRow.querySelectorAll("th, td");
31913
- if (cells.length > 1) {
31914
- const firstHeaderCell = cells[0];
31915
- const headerColor = firstHeaderCell.getAttribute("data-header-color");
31916
- const textColor = firstHeaderCell.getAttribute("data-text-color");
31917
- if (headerColor && textColor) {
31918
- const lastCell = cells[cells.length - 1];
31919
- lastCell.setAttribute("data-header-color", headerColor);
31920
- lastCell.setAttribute("data-text-color", textColor);
31921
- lastCell.style.setProperty("background-color", headerColor, "important");
31922
- lastCell.style.setProperty("color", textColor, "important");
31923
- lastCell.style.setProperty("padding", "8px", "important");
31924
- lastCell.style.setProperty("border", "1px solid #ddd", "important");
31925
- lastCell.style.setProperty("font-weight", "bold", "important");
31926
- lastCell.style.setProperty("white-space", "nowrap", "important");
33038
+ const firstCell = firstRow == null ? void 0 : firstRow.querySelector("th");
33039
+ if (firstCell) {
33040
+ e.dataTransfer.dropEffect = "none";
33041
+ setDragPreviewLine(null);
33042
+ setTargetHighlightedRow(null);
33043
+ return;
33044
+ }
33045
+ }
33046
+ if (targetRowIndex !== -1 && targetRowIndex !== dragState.sourceIndex) {
33047
+ handleDragOver(e, "row", targetRowIndex);
33048
+ } else if (targetRowIndex === dragState.sourceIndex) {
33049
+ setDragPreviewLine(null);
33050
+ setTargetHighlightedRow(dragState.sourceIndex);
33051
+ }
33052
+ } else {
33053
+ const rows = currentTableRef.current.querySelectorAll("tr");
33054
+ if (rows.length > 0) {
33055
+ const cells = rows[0].querySelectorAll("td, th");
33056
+ const mouseX = e.clientX;
33057
+ let targetColIndex = -1;
33058
+ for (let i2 = 0; i2 < cells.length; i2++) {
33059
+ const cell = cells[i2];
33060
+ const rect = cell.getBoundingClientRect();
33061
+ if (mouseX >= rect.left && mouseX <= rect.right) {
33062
+ targetColIndex = i2;
33063
+ break;
33064
+ } else if (mouseX < rect.left && i2 === 0) {
33065
+ targetColIndex = 0;
33066
+ break;
33067
+ } else if (i2 === cells.length - 1 && mouseX > rect.right) {
33068
+ targetColIndex = cells.length - 1;
33069
+ break;
31927
33070
  }
31928
33071
  }
33072
+ if (targetColIndex !== -1 && targetColIndex !== dragState.sourceIndex) {
33073
+ handleDragOver(e, "column", targetColIndex);
33074
+ } else if (targetColIndex === dragState.sourceIndex) {
33075
+ setDragPreviewLine(null);
33076
+ setTargetHighlightedColumn(dragState.sourceIndex);
33077
+ }
31929
33078
  }
31930
- });
31931
- return true;
31932
- };
31933
- if (!applyHeaderStyles()) {
31934
- setTimeout(applyHeaderStyles, 100);
33079
+ }
33080
+ },
33081
+ onDrop: (e) => {
33082
+ e.preventDefault();
33083
+ e.stopPropagation();
33084
+ handleDrop(e);
31935
33085
  }
31936
- });
31937
- }
31938
- };
31939
- if (!isEditable) {
31940
- return null;
31941
- }
31942
- return /* @__PURE__ */ jsxs(Fragment, { children: [
31943
- isShownRow && position.row && /* @__PURE__ */ jsx(
31944
- "button",
31945
- {
31946
- className: "PlaygroundEditorTheme__tableAddRows ",
31947
- style: { ...position.row },
31948
- onClick: () => insertAction(true),
31949
- children: /* @__PURE__ */ jsx(PlusIcon, {})
31950
33086
  }
31951
33087
  ),
31952
- isShownColumn && position.column && /* @__PURE__ */ jsx(
31953
- "button",
33088
+ dragPreviewLine && /* @__PURE__ */ jsx(
33089
+ "div",
31954
33090
  {
31955
- className: "PlaygroundEditorTheme__tableAddColumns",
31956
- style: { ...position.column },
31957
- onClick: () => insertAction(false),
31958
- children: /* @__PURE__ */ jsx(PlusIcon, {})
33091
+ style: {
33092
+ position: "absolute",
33093
+ left: `${dragPreviewLine.left}px`,
33094
+ top: `${dragPreviewLine.top}px`,
33095
+ width: dragPreviewLine.isHorizontal ? `${dragPreviewLine.width}px` : `${dragPreviewLine.width}px`,
33096
+ height: dragPreviewLine.isHorizontal ? `${dragPreviewLine.height}px` : `${dragPreviewLine.height}px`,
33097
+ backgroundColor: "#22c55e",
33098
+ zIndex: 1001,
33099
+ pointerEvents: "none",
33100
+ boxShadow: "0 0 8px rgba(34, 197, 94, 0.6)"
33101
+ }
31959
33102
  }
31960
- )
33103
+ ),
33104
+ highlightedRow !== null && currentTableRef.current && (() => {
33105
+ const tableRect = currentTableRef.current.getBoundingClientRect();
33106
+ const { left: editorLeft, top: editorTop } = anchorElem.getBoundingClientRect();
33107
+ const rows = currentTableRef.current.querySelectorAll("tr");
33108
+ if (highlightedRow >= 0 && highlightedRow < rows.length) {
33109
+ const row = rows[highlightedRow];
33110
+ const rowRect = row.getBoundingClientRect();
33111
+ return /* @__PURE__ */ jsx(
33112
+ "div",
33113
+ {
33114
+ style: {
33115
+ position: "absolute",
33116
+ left: `${tableRect.left - editorLeft}px`,
33117
+ top: `${rowRect.top - editorTop}px`,
33118
+ width: `${tableRect.width}px`,
33119
+ height: `${rowRect.height}px`,
33120
+ backgroundColor: dragState ? "rgba(59, 130, 246, 0.2)" : "rgba(59, 130, 246, 0.15)",
33121
+ zIndex: 999,
33122
+ pointerEvents: "none",
33123
+ border: "2px solid rgba(59, 130, 246, 0.5)",
33124
+ boxSizing: "border-box",
33125
+ transition: "all 0.15s ease"
33126
+ }
33127
+ }
33128
+ );
33129
+ }
33130
+ return null;
33131
+ })(),
33132
+ targetHighlightedRow !== null && dragState && currentTableRef.current && (() => {
33133
+ const tableRect = currentTableRef.current.getBoundingClientRect();
33134
+ const { left: editorLeft, top: editorTop } = anchorElem.getBoundingClientRect();
33135
+ const rows = currentTableRef.current.querySelectorAll("tr");
33136
+ if (targetHighlightedRow >= 0 && targetHighlightedRow < rows.length) {
33137
+ const row = rows[targetHighlightedRow];
33138
+ const rowRect = row.getBoundingClientRect();
33139
+ return /* @__PURE__ */ jsx(
33140
+ "div",
33141
+ {
33142
+ style: {
33143
+ position: "absolute",
33144
+ left: `${tableRect.left - editorLeft}px`,
33145
+ top: `${rowRect.top - editorTop}px`,
33146
+ width: `${tableRect.width}px`,
33147
+ height: `${rowRect.height}px`,
33148
+ backgroundColor: "rgba(34, 197, 94, 0.25)",
33149
+ zIndex: 1e3,
33150
+ pointerEvents: "none",
33151
+ border: "2px solid rgba(34, 197, 94, 0.6)",
33152
+ boxSizing: "border-box",
33153
+ transition: "all 0.15s ease"
33154
+ }
33155
+ }
33156
+ );
33157
+ }
33158
+ return null;
33159
+ })(),
33160
+ highlightedColumn !== null && currentTableRef.current && (() => {
33161
+ const tableRect = currentTableRef.current.getBoundingClientRect();
33162
+ const { left: editorLeft, top: editorTop } = anchorElem.getBoundingClientRect();
33163
+ const rows = currentTableRef.current.querySelectorAll("tr");
33164
+ if (rows.length > 0) {
33165
+ const firstRow = rows[0];
33166
+ const cells = firstRow.querySelectorAll("td, th");
33167
+ if (highlightedColumn >= 0 && highlightedColumn < cells.length) {
33168
+ const cell = cells[highlightedColumn];
33169
+ const cellRect = cell.getBoundingClientRect();
33170
+ return /* @__PURE__ */ jsx(
33171
+ "div",
33172
+ {
33173
+ style: {
33174
+ position: "absolute",
33175
+ left: `${cellRect.left - editorLeft}px`,
33176
+ top: `${tableRect.top - editorTop}px`,
33177
+ width: `${cellRect.width}px`,
33178
+ height: `${tableRect.height}px`,
33179
+ backgroundColor: dragState ? "rgba(59, 130, 246, 0.2)" : "rgba(59, 130, 246, 0.15)",
33180
+ zIndex: 999,
33181
+ pointerEvents: "none",
33182
+ border: "2px solid rgba(59, 130, 246, 0.5)",
33183
+ boxSizing: "border-box",
33184
+ transition: "all 0.15s ease"
33185
+ }
33186
+ }
33187
+ );
33188
+ }
33189
+ }
33190
+ return null;
33191
+ })(),
33192
+ targetHighlightedColumn !== null && dragState && currentTableRef.current && (() => {
33193
+ const tableRect = currentTableRef.current.getBoundingClientRect();
33194
+ const { left: editorLeft, top: editorTop } = anchorElem.getBoundingClientRect();
33195
+ const rows = currentTableRef.current.querySelectorAll("tr");
33196
+ if (rows.length > 0) {
33197
+ const firstRow = rows[0];
33198
+ const cells = firstRow.querySelectorAll("td, th");
33199
+ if (targetHighlightedColumn >= 0 && targetHighlightedColumn < cells.length) {
33200
+ const cell = cells[targetHighlightedColumn];
33201
+ const cellRect = cell.getBoundingClientRect();
33202
+ return /* @__PURE__ */ jsx(
33203
+ "div",
33204
+ {
33205
+ style: {
33206
+ position: "absolute",
33207
+ left: `${cellRect.left - editorLeft}px`,
33208
+ top: `${tableRect.top - editorTop}px`,
33209
+ width: `${cellRect.width}px`,
33210
+ height: `${tableRect.height}px`,
33211
+ backgroundColor: "rgba(34, 197, 94, 0.25)",
33212
+ zIndex: 1e3,
33213
+ pointerEvents: "none",
33214
+ border: "2px solid rgba(34, 197, 94, 0.6)",
33215
+ boxSizing: "border-box",
33216
+ transition: "all 0.15s ease"
33217
+ }
33218
+ }
33219
+ );
33220
+ }
33221
+ }
33222
+ return null;
33223
+ })()
31961
33224
  ] });
31962
33225
  }
31963
33226
  function getMouseInfo(event) {
@@ -31966,11 +33229,7 @@ function getMouseInfo(event) {
31966
33229
  const tableDOMNode = target.closest(
31967
33230
  "td.PlaygroundEditorTheme__tableCell, th.PlaygroundEditorTheme__tableCell"
31968
33231
  );
31969
- const isOutside = !(tableDOMNode || target.closest(
31970
- "button.PlaygroundEditorTheme__tableAddRows"
31971
- ) || target.closest(
31972
- "button.PlaygroundEditorTheme__tableAddColumns"
31973
- ) || target.closest("div.TableCellResizer__resizer"));
33232
+ const isOutside = !(tableDOMNode || target.closest("button.table-insert-dot") || target.closest("button.table-selector-button") || target.closest("div.TableCellResizer__resizer"));
31974
33233
  return { isOutside, tableDOMNode };
31975
33234
  } else {
31976
33235
  return { isOutside: true, tableDOMNode: null };
@@ -32121,7 +33380,6 @@ const ToolbarWithEditor = (props) => {
32121
33380
  editor,
32122
33381
  activeEditor: editor,
32123
33382
  setActiveEditor: (newEditor) => {
32124
- console.log("Editor change requested");
32125
33383
  }
32126
33384
  }
32127
33385
  );
@@ -32164,6 +33422,64 @@ const InitialContentPlugin = ({ initialContent }) => {
32164
33422
  }, [editor, initialContent]);
32165
33423
  return null;
32166
33424
  };
33425
+ const CellBackgroundPersistencePlugin = () => {
33426
+ const [editor] = useLexicalComposerContext();
33427
+ useEffect$1(() => {
33428
+ const applyCellStyles = () => {
33429
+ const rootElement = editor.getRootElement();
33430
+ if (!rootElement)
33431
+ return;
33432
+ editor.getEditorState().read(() => {
33433
+ const tables = rootElement.querySelectorAll("table");
33434
+ tables.forEach((tableElement) => {
33435
+ const cells = tableElement.querySelectorAll("td, th");
33436
+ cells.forEach((cell) => {
33437
+ const htmlCell = cell;
33438
+ const cellKey = Object.keys(htmlCell).find((key) => key.startsWith("__reactProps")) ? htmlCell["__lexicalKey"] : void 0;
33439
+ if (!cellKey)
33440
+ return;
33441
+ try {
33442
+ const cellNode = $getNodeByKey(cellKey);
33443
+ if ($isTableCellNode(cellNode)) {
33444
+ const bgColor = cellNode.getBackgroundColor();
33445
+ if (bgColor) {
33446
+ const hex = bgColor.replace("#", "");
33447
+ const r2 = parseInt(hex.substr(0, 2), 16);
33448
+ const g2 = parseInt(hex.substr(2, 2), 16);
33449
+ const b2 = parseInt(hex.substr(4, 2), 16);
33450
+ const luminance = (0.299 * r2 + 0.587 * g2 + 0.114 * b2) / 255;
33451
+ const textColor = luminance > 0.5 ? "#000000" : "#FFFFFF";
33452
+ htmlCell.style.setProperty("background-color", bgColor, "important");
33453
+ htmlCell.style.setProperty("color", textColor, "important");
33454
+ htmlCell.style.setProperty("border-color", "#bbb", "important");
33455
+ const nestedElements = htmlCell.querySelectorAll("*");
33456
+ nestedElements.forEach((elem) => {
33457
+ if (elem instanceof HTMLElement) {
33458
+ elem.style.setProperty("color", textColor, "important");
33459
+ }
33460
+ });
33461
+ const hasHeaderStyles = cellNode.getHeaderStyles();
33462
+ if (hasHeaderStyles) {
33463
+ htmlCell.style.setProperty("font-weight", "600", "important");
33464
+ }
33465
+ }
33466
+ }
33467
+ } catch (error) {
33468
+ }
33469
+ });
33470
+ });
33471
+ });
33472
+ };
33473
+ const removeUpdateListener = editor.registerUpdateListener(() => {
33474
+ requestAnimationFrame(applyCellStyles);
33475
+ });
33476
+ applyCellStyles();
33477
+ return () => {
33478
+ removeUpdateListener();
33479
+ };
33480
+ }, [editor]);
33481
+ return null;
33482
+ };
32167
33483
  const ConfigurableEditor = ({
32168
33484
  config,
32169
33485
  defaultFontFamilies,
@@ -32232,6 +33548,7 @@ const ConfigurableEditor = ({
32232
33548
  /* @__PURE__ */ jsx(NotePanelPlugin, {}),
32233
33549
  /* @__PURE__ */ jsx(CommentPlugin, {}),
32234
33550
  /* @__PURE__ */ jsx(CommentBubblePlugin, {}),
33551
+ /* @__PURE__ */ jsx(CellBackgroundPersistencePlugin, {}),
32235
33552
  /* @__PURE__ */ jsxs("div", { style: { position: "relative" }, children: [
32236
33553
  /* @__PURE__ */ jsx(
32237
33554
  RichTextPlugin,
@@ -32266,6 +33583,7 @@ const ConfigurableEditor = ({
32266
33583
  /* @__PURE__ */ jsx(LocalStoragePlugin$1, { namespace: initialConfig.namespace }),
32267
33584
  /* @__PURE__ */ jsx(ListPlugin, {}),
32268
33585
  /* @__PURE__ */ jsx(LinkPlugin, { hasLinkAttributes: false }),
33586
+ /* @__PURE__ */ jsx(LinkPreviewPlugin, {}),
32269
33587
  /* @__PURE__ */ jsx(DragDropPaste, {}),
32270
33588
  /* @__PURE__ */ jsx(RichTextPastePlugin, {}),
32271
33589
  /* @__PURE__ */ jsx(FilePlugin, {}),
@@ -32287,25 +33605,24 @@ const ConfigurableEditor = ({
32287
33605
  config.htmlViewOption && !config.toolbarOptions.enableHtmlViewToggle && /* @__PURE__ */ jsx(HtmlViewTogglePlugin, {})
32288
33606
  ] }),
32289
33607
  floatingAnchorElem && /* @__PURE__ */ jsxs(Fragment, { children: [
32290
- !isSmallWidthViewport && /* @__PURE__ */ jsxs(Fragment, { children: [
32291
- /* @__PURE__ */ jsx(
32292
- TableActionMenuPlugin,
32293
- {
32294
- anchorElem: floatingAnchorElem,
32295
- cellMerge: true
32296
- }
32297
- ),
32298
- /* @__PURE__ */ jsx(TableHoverActionsPlugin, { anchorElem: floatingAnchorElem }),
32299
- /* @__PURE__ */ jsx(CodeActionMenuPlugin, { anchorElem: floatingAnchorElem }),
32300
- /* @__PURE__ */ jsx(
32301
- FloatingLinkEditorPlugin,
32302
- {
32303
- anchorElem: floatingAnchorElem,
32304
- isLinkEditMode,
32305
- setIsLinkEditMode
32306
- }
32307
- )
32308
- ] }),
33608
+ /* @__PURE__ */ jsx(
33609
+ TableActionMenuPlugin,
33610
+ {
33611
+ anchorElem: floatingAnchorElem,
33612
+ cellMerge: true,
33613
+ isSmallWidthViewport
33614
+ }
33615
+ ),
33616
+ /* @__PURE__ */ jsx(TableHoverActionsPlugin, { anchorElem: floatingAnchorElem }),
33617
+ /* @__PURE__ */ jsx(CodeActionMenuPlugin, { anchorElem: floatingAnchorElem }),
33618
+ /* @__PURE__ */ jsx(
33619
+ FloatingLinkEditorPlugin,
33620
+ {
33621
+ anchorElem: floatingAnchorElem,
33622
+ isLinkEditMode,
33623
+ setIsLinkEditMode
33624
+ }
33625
+ ),
32309
33626
  config.enableFloatingMenu && /* @__PURE__ */ jsx(
32310
33627
  FloatingTextFormatToolbarPlugin,
32311
33628
  {
@@ -32371,7 +33688,6 @@ const ConfigurableEditorWithAuth = ({
32371
33688
  customVerifyKey
32372
33689
  }) => {
32373
33690
  const { isAuthenticated, isLoading, error, editorConfig: editorConfig2, verifyKey } = useEditor();
32374
- console.log(editorConfig2, "editorConfig");
32375
33691
  const successRef = useRef(onAuthSuccess);
32376
33692
  const errorRef = useRef(onAuthError);
32377
33693
  const hasAttemptedAuthRef = useRef(false);
@@ -32387,9 +33703,7 @@ const ConfigurableEditorWithAuth = ({
32387
33703
  var _a, _b, _c;
32388
33704
  try {
32389
33705
  if (customVerifyKey) {
32390
- console.log("Inside");
32391
33706
  const response = await customVerifyKey(apiKey);
32392
- console.log(response, "response");
32393
33707
  if (response.success) {
32394
33708
  (_a = successRef.current) == null ? void 0 : _a.call(successRef);
32395
33709
  } else {
@@ -32399,7 +33713,6 @@ const ConfigurableEditorWithAuth = ({
32399
33713
  await verifyKey(apiKey);
32400
33714
  }
32401
33715
  } catch (err) {
32402
- console.log(err, "error");
32403
33716
  (_c = errorRef.current) == null ? void 0 : _c.call(errorRef, err.message || "Failed to verify API key");
32404
33717
  }
32405
33718
  };
@@ -32443,22 +33756,32 @@ const ConfigurableEditorWithAuth = ({
32443
33756
  };
32444
33757
  export {
32445
33758
  $isFileNode as $,
33759
+ AiJsonResponse as A,
33760
+ Button as B,
32446
33761
  ConfigurableEditorWithAuth as C,
32447
33762
  Download as D,
32448
33763
  ExternalLink as E,
32449
33764
  HtmlViewProvider as H,
32450
33765
  LocalStoragePlugin$1 as L,
33766
+ Sparkles as S,
32451
33767
  Trash2 as T,
32452
33768
  createLucideIcon as a,
32453
- $isImageNode as b,
33769
+ Dialog as b,
32454
33770
  commonjsGlobal as c,
32455
- EditorProvider as d,
32456
- useEditor as e,
32457
- ConfigurableEditor as f,
33771
+ DialogContent as d,
33772
+ DialogHeader as e,
33773
+ DialogTitle as f,
32458
33774
  getDefaultExportFromCjs as g,
32459
- editorConfig as h,
33775
+ DialogDescription as h,
32460
33776
  initialConfig as i,
33777
+ DialogFooter as j,
33778
+ $isImageNode as k,
33779
+ EditorProvider as l,
33780
+ useEditor as m,
33781
+ ConfigurableEditor as n,
33782
+ editorConfig as o,
33783
+ toast as t,
32461
33784
  useHtmlView as u,
32462
33785
  verifyApiKey as v
32463
33786
  };
32464
- //# sourceMappingURL=index-dbc626d0.js.map
33787
+ //# sourceMappingURL=index-158a9bd4.js.map