@rufous/ui 0.2.66 → 0.2.67

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/main.cjs CHANGED
@@ -8356,9 +8356,9 @@ var PhoneField = (0, import_react48.forwardRef)(function PhoneField2(props, ref)
8356
8356
  PhoneField.displayName = "PhoneField";
8357
8357
 
8358
8358
  // lib/RufousTextEditor/RufousTextEditor.tsx
8359
- var import_react58 = __toESM(require("react"), 1);
8360
- var import_react_dom13 = require("react-dom");
8361
- var import_react59 = require("@tiptap/react");
8359
+ var import_react59 = __toESM(require("react"), 1);
8360
+ var import_react_dom14 = require("react-dom");
8361
+ var import_react60 = require("@tiptap/react");
8362
8362
  var import_starter_kit = __toESM(require("@tiptap/starter-kit"), 1);
8363
8363
  var import_extension_placeholder = __toESM(require("@tiptap/extension-placeholder"), 1);
8364
8364
  var import_extension_link = __toESM(require("@tiptap/extension-link"), 1);
@@ -8483,7 +8483,7 @@ var import_react_dom10 = require("react-dom");
8483
8483
 
8484
8484
  // lib/RufousTextEditor/TextToSpeech.tsx
8485
8485
  var import_react51 = __toESM(require("react"), 1);
8486
- var TextToSpeech = ({ editor, onTextToSpeech }) => {
8486
+ var TextToSpeech = (0, import_react51.forwardRef)(({ editor, onTextToSpeech }, ref) => {
8487
8487
  const [speaking, setSpeaking] = (0, import_react51.useState)(false);
8488
8488
  const [paused, setPaused] = (0, import_react51.useState)(false);
8489
8489
  const [voices, setVoices] = (0, import_react51.useState)([]);
@@ -8586,6 +8586,7 @@ var TextToSpeech = ({ editor, onTextToSpeech }) => {
8586
8586
  setSpeaking(false);
8587
8587
  setPaused(false);
8588
8588
  }, []);
8589
+ (0, import_react51.useImperativeHandle)(ref, () => ({ stop: handleStop }), [handleStop]);
8589
8590
  return /* @__PURE__ */ import_react51.default.createElement("div", { className: "tts-wrapper", ref: panelRef }, /* @__PURE__ */ import_react51.default.createElement(
8590
8591
  "button",
8591
8592
  {
@@ -8623,12 +8624,12 @@ var TextToSpeech = ({ editor, onTextToSpeech }) => {
8623
8624
  handleSpeak();
8624
8625
  setShowPanel(false);
8625
8626
  } }, "\u25B6 Speak")), speaking && /* @__PURE__ */ import_react51.default.createElement("div", { className: "tts-controls" }, paused ? /* @__PURE__ */ import_react51.default.createElement("button", { className: "toolbar-btn", onClick: handleResume, title: "Resume" }, "\u25B6") : /* @__PURE__ */ import_react51.default.createElement("button", { className: "toolbar-btn", onClick: handlePause, title: "Pause" }, "\u275A\u275A"), /* @__PURE__ */ import_react51.default.createElement("button", { className: "toolbar-btn", onClick: handleStop, title: "Stop" }, "\u25A0")));
8626
- };
8627
+ });
8627
8628
  var TextToSpeech_default = TextToSpeech;
8628
8629
 
8629
8630
  // lib/RufousTextEditor/SpeechToText.tsx
8630
8631
  var import_react52 = __toESM(require("react"), 1);
8631
- var SpeechToText = ({ editor, onSpeechToText }) => {
8632
+ var SpeechToText = (0, import_react52.forwardRef)(({ editor, onSpeechToText }, ref) => {
8632
8633
  const [listening, setListening] = (0, import_react52.useState)(false);
8633
8634
  const [showPanel, setShowPanel] = (0, import_react52.useState)(false);
8634
8635
  const [language, setLanguage] = (0, import_react52.useState)("en-US");
@@ -8739,6 +8740,7 @@ var SpeechToText = ({ editor, onSpeechToText }) => {
8739
8740
  setListening(false);
8740
8741
  setInterim("");
8741
8742
  }, []);
8743
+ (0, import_react52.useImperativeHandle)(ref, () => ({ stop: stopListening }), [stopListening]);
8742
8744
  if (!supported) {
8743
8745
  return /* @__PURE__ */ import_react52.default.createElement("button", { className: "toolbar-btn", disabled: true, title: "Speech recognition not supported in this browser" }, "\u{1F3A4}");
8744
8746
  }
@@ -8785,7 +8787,7 @@ var SpeechToText = ({ editor, onSpeechToText }) => {
8785
8787
  },
8786
8788
  LANGUAGES2.map((l) => /* @__PURE__ */ import_react52.default.createElement("option", { key: l.code, value: l.code }, l.label))
8787
8789
  ), /* @__PURE__ */ import_react52.default.createElement("div", { className: "stt-info" }, "Speak into your microphone and the text will be typed into the editor."), /* @__PURE__ */ import_react52.default.createElement("button", { className: "stt-start-btn", onClick: startListening }, "\u{1F3A4} Start Listening")), listening && interim && /* @__PURE__ */ import_react52.default.createElement("div", { className: "stt-interim" }, interim));
8788
- };
8790
+ });
8789
8791
  var SpeechToText_default = SpeechToText;
8790
8792
 
8791
8793
  // lib/RufousTextEditor/AICommands.tsx
@@ -10356,10 +10358,11 @@ var ColorPickerPanel = ({ editor, onClose }) => {
10356
10358
  }
10357
10359
  ))), /* @__PURE__ */ import_react55.default.createElement("div", { className: "color-picker-footer" }, /* @__PURE__ */ import_react55.default.createElement("div", { className: "color-picker-preview", style: { background: activeColor || "#000" } }), /* @__PURE__ */ import_react55.default.createElement("button", { className: "color-picker-remove", onClick: removeColor, title: "Remove color" }, "\u2713")));
10358
10360
  };
10359
- var Toolbar = ({ editor, setLink, onAICommand, onTranslate, onSpeechToText, onTextToSpeech, onClose, onImageUpload, visibleButtons }) => {
10361
+ var Toolbar = ({ editor, setLink, onAICommand, onTranslate, onSpeechToText, onTextToSpeech, onClose, onImageUpload, visibleButtons, isFullscreen, onToggleFullscreen }) => {
10360
10362
  const [, setEditorState] = (0, import_react55.useState)(0);
10361
- const [isFullscreen, setIsFullscreen] = (0, import_react55.useState)(false);
10362
10363
  const [todoEnabled, setTodoEnabled] = (0, import_react55.useState)(false);
10364
+ const ttsRef = (0, import_react55.useRef)(null);
10365
+ const sttRef = (0, import_react55.useRef)(null);
10363
10366
  const show = (id) => !visibleButtons || visibleButtons.has(id);
10364
10367
  (0, import_react55.useEffect)(() => {
10365
10368
  if (!editor) return;
@@ -10367,16 +10370,6 @@ var Toolbar = ({ editor, setLink, onAICommand, onTranslate, onSpeechToText, onTe
10367
10370
  editor.on("transaction", onTransaction);
10368
10371
  return () => editor.off("transaction", onTransaction);
10369
10372
  }, [editor]);
10370
- const toggleFullscreen = (0, import_react55.useCallback)(() => {
10371
- const wrapper = document.querySelector(".editor-wrapper");
10372
- if (!wrapper) return;
10373
- if (!isFullscreen) {
10374
- wrapper.classList.add("fullscreen");
10375
- } else {
10376
- wrapper.classList.remove("fullscreen");
10377
- }
10378
- setIsFullscreen(!isFullscreen);
10379
- }, [isFullscreen]);
10380
10373
  const insertSpecialChar = (0, import_react55.useCallback)((char) => {
10381
10374
  if (!editor) return;
10382
10375
  editor.chain().focus().insertContent(char).run();
@@ -10880,11 +10873,11 @@ var Toolbar = ({ editor, setLink, onAICommand, onTranslate, onSpeechToText, onTe
10880
10873
  "button",
10881
10874
  {
10882
10875
  className: `toolbar-btn ${isFullscreen ? "is-active" : ""}`,
10883
- onClick: toggleFullscreen,
10876
+ onClick: onToggleFullscreen,
10884
10877
  title: "Toggle Fullscreen"
10885
10878
  },
10886
10879
  /* @__PURE__ */ import_react55.default.createElement(IconFullscreen, null)
10887
- ), show("tts") && /* @__PURE__ */ import_react55.default.createElement(TextToSpeech_default, { editor, onTextToSpeech }), show("stt") && /* @__PURE__ */ import_react55.default.createElement(SpeechToText_default, { editor, onSpeechToText }), show("translate") && /* @__PURE__ */ import_react55.default.createElement("div", { className: "translate-split-btn" }, /* @__PURE__ */ import_react55.default.createElement(
10880
+ ), show("tts") && /* @__PURE__ */ import_react55.default.createElement(TextToSpeech_default, { ref: ttsRef, editor, onTextToSpeech }), show("stt") && /* @__PURE__ */ import_react55.default.createElement(SpeechToText_default, { ref: sttRef, editor, onSpeechToText }), show("translate") && /* @__PURE__ */ import_react55.default.createElement("div", { className: "translate-split-btn" }, /* @__PURE__ */ import_react55.default.createElement(
10888
10881
  "button",
10889
10882
  {
10890
10883
  className: "toolbar-btn",
@@ -10978,7 +10971,17 @@ var Toolbar = ({ editor, setLink, onAICommand, onTranslate, onSpeechToText, onTe
10978
10971
  "button",
10979
10972
  {
10980
10973
  className: "toolbar-btn btn-cross",
10981
- onClick: onClose,
10974
+ onClick: () => {
10975
+ try {
10976
+ ttsRef.current?.stop();
10977
+ } catch {
10978
+ }
10979
+ try {
10980
+ sttRef.current?.stop();
10981
+ } catch {
10982
+ }
10983
+ onClose();
10984
+ },
10982
10985
  title: "Close"
10983
10986
  },
10984
10987
  /* @__PURE__ */ import_react55.default.createElement(closeIcon_default, { color: "#a81c08" })
@@ -11520,6 +11523,175 @@ var VideoToolbar = ({ editor }) => {
11520
11523
  };
11521
11524
  var VideoToolbar_default = VideoToolbar;
11522
11525
 
11526
+ // lib/RufousTextEditor/TableToolbar.tsx
11527
+ var import_react58 = __toESM(require("react"), 1);
11528
+ var import_react_dom13 = require("react-dom");
11529
+ var IconAddRowBefore = () => /* @__PURE__ */ import_react58.default.createElement("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "currentColor" }, /* @__PURE__ */ import_react58.default.createElement("path", { d: "M20 3H4c-.55 0-1 .45-1 1v16c0 .55.45 1 1 1h16c.55 0 1-.45 1-1V4c0-.55-.45-1-1-1zm-1 8H5V5h14v6zm0 8H5v-6h14v6z" }), /* @__PURE__ */ import_react58.default.createElement("path", { d: "M9 6h2v1.5h1.5v2H11V11H9V9.5H7.5v-2H9z" }));
11530
+ var IconAddRowAfter = () => /* @__PURE__ */ import_react58.default.createElement("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "currentColor" }, /* @__PURE__ */ import_react58.default.createElement("path", { d: "M20 3H4c-.55 0-1 .45-1 1v16c0 .55.45 1 1 1h16c.55 0 1-.45 1-1V4c0-.55-.45-1-1-1zm-1 8H5V5h14v6zm0 8H5v-6h14v6z" }), /* @__PURE__ */ import_react58.default.createElement("path", { d: "M9 14h2v1.5h1.5v2H11V19H9v-1.5H7.5v-2H9z" }));
11531
+ var IconAddColBefore = () => /* @__PURE__ */ import_react58.default.createElement("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "currentColor" }, /* @__PURE__ */ import_react58.default.createElement("path", { d: "M20 3H4c-.55 0-1 .45-1 1v16c0 .55.45 1 1 1h16c.55 0 1-.45 1-1V4c0-.55-.45-1-1-1zm-9 16H5V5h6v14zm8 0h-6V5h6v14z" }), /* @__PURE__ */ import_react58.default.createElement("path", { d: "M6 10h1.5v2H6v1.5H4v-2h1.5V10H4V8h2z", transform: "translate(2,1)" }));
11532
+ var IconAddColAfter = () => /* @__PURE__ */ import_react58.default.createElement("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "currentColor" }, /* @__PURE__ */ import_react58.default.createElement("path", { d: "M20 3H4c-.55 0-1 .45-1 1v16c0 .55.45 1 1 1h16c.55 0 1-.45 1-1V4c0-.55-.45-1-1-1zm-9 16H5V5h6v14zm8 0h-6V5h6v14z" }), /* @__PURE__ */ import_react58.default.createElement("path", { d: "M15 9h2v1.5h1.5v2H17V14h-2v-1.5h-1.5v-2H15z" }));
11533
+ var IconDeleteRow = () => /* @__PURE__ */ import_react58.default.createElement("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "currentColor" }, /* @__PURE__ */ import_react58.default.createElement("path", { d: "M20 3H4c-.55 0-1 .45-1 1v16c0 .55.45 1 1 1h16c.55 0 1-.45 1-1V4c0-.55-.45-1-1-1zm-1 8H5V5h14v6zm0 8H5v-6h14v6z" }), /* @__PURE__ */ import_react58.default.createElement("path", { d: "M8 14.5h8v2H8z" }));
11534
+ var IconDeleteCol = () => /* @__PURE__ */ import_react58.default.createElement("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "currentColor" }, /* @__PURE__ */ import_react58.default.createElement("path", { d: "M20 3H4c-.55 0-1 .45-1 1v16c0 .55.45 1 1 1h16c.55 0 1-.45 1-1V4c0-.55-.45-1-1-1zm-9 16H5V5h6v14zm8 0h-6V5h6v14z" }), /* @__PURE__ */ import_react58.default.createElement("path", { d: "M14 9.5v6h2v-6z" }));
11535
+ var IconDeleteTable = () => /* @__PURE__ */ import_react58.default.createElement("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "currentColor" }, /* @__PURE__ */ import_react58.default.createElement("path", { d: "M20 3H4c-.55 0-1 .45-1 1v16c0 .55.45 1 1 1h16c.55 0 1-.45 1-1V4c0-.55-.45-1-1-1zm-1 16H5V5h14v14z" }), /* @__PURE__ */ import_react58.default.createElement("path", { d: "M9.17 10l-1.41 1.41L10.59 14l-2.83 2.83 1.41 1.41L12 15.41l2.83 2.83 1.41-1.41L13.41 14l2.83-2.83-1.41-1.41L12 12.59z" }));
11536
+ var IconMergeCells = () => /* @__PURE__ */ import_react58.default.createElement("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "currentColor" }, /* @__PURE__ */ import_react58.default.createElement("path", { d: "M3 3h18v18H3V3zm2 2v5h6V5H5zm8 0v5h6V5h-6zM5 13v6h14v-6H5z" }), /* @__PURE__ */ import_react58.default.createElement("path", { d: "M8 15h8v2H8z" }));
11537
+ var IconSplitCell = () => /* @__PURE__ */ import_react58.default.createElement("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "currentColor" }, /* @__PURE__ */ import_react58.default.createElement("path", { d: "M3 3h18v18H3V3zm2 2v5h6V5H5zm8 0v5h6V5h-6zM5 13v6h6v-6H5zm8 0v6h6v-6h-6z" }));
11538
+ var IconToggleHeader = () => /* @__PURE__ */ import_react58.default.createElement("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "currentColor" }, /* @__PURE__ */ import_react58.default.createElement("path", { d: "M3 3h18v18H3V3zm2 2v4h14V5H5zm0 6v8h14v-8H5z" }), /* @__PURE__ */ import_react58.default.createElement("rect", { x: "5", y: "5", width: "14", height: "4", opacity: "0.4" }));
11539
+ var TableToolbar = ({ editor }) => {
11540
+ const [pos, setPos] = (0, import_react58.useState)(null);
11541
+ const toolbarRef = (0, import_react58.useRef)(null);
11542
+ (0, import_react58.useEffect)(() => {
11543
+ if (!editor) return;
11544
+ const update = () => {
11545
+ if (!editor.isActive("table")) {
11546
+ setPos(null);
11547
+ return;
11548
+ }
11549
+ try {
11550
+ const { $from } = editor.state.selection;
11551
+ let depth = $from.depth;
11552
+ while (depth > 0) {
11553
+ const node = $from.node(depth);
11554
+ if (node.type.name === "table") {
11555
+ const domNode = editor.view.nodeDOM($from.before(depth));
11556
+ if (domNode) {
11557
+ const tableEl = domNode.tagName === "TABLE" ? domNode : domNode.querySelector?.("table") || domNode;
11558
+ const rect = tableEl.getBoundingClientRect();
11559
+ setPos({
11560
+ top: rect.top + window.scrollY - 40,
11561
+ left: rect.left + window.scrollX
11562
+ });
11563
+ }
11564
+ return;
11565
+ }
11566
+ depth--;
11567
+ }
11568
+ setPos(null);
11569
+ } catch {
11570
+ setPos(null);
11571
+ }
11572
+ };
11573
+ editor.on("selectionUpdate", update);
11574
+ editor.on("update", update);
11575
+ update();
11576
+ return () => {
11577
+ editor.off("selectionUpdate", update);
11578
+ editor.off("update", update);
11579
+ };
11580
+ }, [editor]);
11581
+ if (!editor || !pos || !editor.isActive("table")) return null;
11582
+ const canMerge = editor.can().mergeCells();
11583
+ const canSplit = editor.can().splitCell();
11584
+ const prevent = (e) => e.preventDefault();
11585
+ return (0, import_react_dom13.createPortal)(
11586
+ /* @__PURE__ */ import_react58.default.createElement(
11587
+ "div",
11588
+ {
11589
+ ref: toolbarRef,
11590
+ className: "rf-table-toolbar",
11591
+ style: { top: pos.top, left: pos.left },
11592
+ onMouseDown: prevent
11593
+ },
11594
+ /* @__PURE__ */ import_react58.default.createElement(
11595
+ "button",
11596
+ {
11597
+ className: "rf-table-toolbar-btn",
11598
+ onClick: () => editor.chain().focus().addRowBefore().run(),
11599
+ title: "Insert row above"
11600
+ },
11601
+ /* @__PURE__ */ import_react58.default.createElement(IconAddRowBefore, null)
11602
+ ),
11603
+ /* @__PURE__ */ import_react58.default.createElement(
11604
+ "button",
11605
+ {
11606
+ className: "rf-table-toolbar-btn",
11607
+ onClick: () => editor.chain().focus().addRowAfter().run(),
11608
+ title: "Insert row below"
11609
+ },
11610
+ /* @__PURE__ */ import_react58.default.createElement(IconAddRowAfter, null)
11611
+ ),
11612
+ /* @__PURE__ */ import_react58.default.createElement(
11613
+ "button",
11614
+ {
11615
+ className: "rf-table-toolbar-btn rf-table-toolbar-btn-danger",
11616
+ onClick: () => editor.chain().focus().deleteRow().run(),
11617
+ title: "Delete row"
11618
+ },
11619
+ /* @__PURE__ */ import_react58.default.createElement(IconDeleteRow, null)
11620
+ ),
11621
+ /* @__PURE__ */ import_react58.default.createElement("span", { className: "rf-table-toolbar-sep" }),
11622
+ /* @__PURE__ */ import_react58.default.createElement(
11623
+ "button",
11624
+ {
11625
+ className: "rf-table-toolbar-btn",
11626
+ onClick: () => editor.chain().focus().addColumnBefore().run(),
11627
+ title: "Insert column left"
11628
+ },
11629
+ /* @__PURE__ */ import_react58.default.createElement(IconAddColBefore, null)
11630
+ ),
11631
+ /* @__PURE__ */ import_react58.default.createElement(
11632
+ "button",
11633
+ {
11634
+ className: "rf-table-toolbar-btn",
11635
+ onClick: () => editor.chain().focus().addColumnAfter().run(),
11636
+ title: "Insert column right"
11637
+ },
11638
+ /* @__PURE__ */ import_react58.default.createElement(IconAddColAfter, null)
11639
+ ),
11640
+ /* @__PURE__ */ import_react58.default.createElement(
11641
+ "button",
11642
+ {
11643
+ className: "rf-table-toolbar-btn rf-table-toolbar-btn-danger",
11644
+ onClick: () => editor.chain().focus().deleteColumn().run(),
11645
+ title: "Delete column"
11646
+ },
11647
+ /* @__PURE__ */ import_react58.default.createElement(IconDeleteCol, null)
11648
+ ),
11649
+ /* @__PURE__ */ import_react58.default.createElement("span", { className: "rf-table-toolbar-sep" }),
11650
+ /* @__PURE__ */ import_react58.default.createElement(
11651
+ "button",
11652
+ {
11653
+ className: "rf-table-toolbar-btn",
11654
+ onClick: () => editor.chain().focus().mergeCells().run(),
11655
+ disabled: !canMerge,
11656
+ title: "Merge cells"
11657
+ },
11658
+ /* @__PURE__ */ import_react58.default.createElement(IconMergeCells, null)
11659
+ ),
11660
+ /* @__PURE__ */ import_react58.default.createElement(
11661
+ "button",
11662
+ {
11663
+ className: "rf-table-toolbar-btn",
11664
+ onClick: () => editor.chain().focus().splitCell().run(),
11665
+ disabled: !canSplit,
11666
+ title: "Split cell"
11667
+ },
11668
+ /* @__PURE__ */ import_react58.default.createElement(IconSplitCell, null)
11669
+ ),
11670
+ /* @__PURE__ */ import_react58.default.createElement("span", { className: "rf-table-toolbar-sep" }),
11671
+ /* @__PURE__ */ import_react58.default.createElement(
11672
+ "button",
11673
+ {
11674
+ className: `rf-table-toolbar-btn ${editor.isActive("tableHeader") ? "active" : ""}`,
11675
+ onClick: () => editor.chain().focus().toggleHeaderRow().run(),
11676
+ title: "Toggle header row"
11677
+ },
11678
+ /* @__PURE__ */ import_react58.default.createElement(IconToggleHeader, null)
11679
+ ),
11680
+ /* @__PURE__ */ import_react58.default.createElement(
11681
+ "button",
11682
+ {
11683
+ className: "rf-table-toolbar-btn rf-table-toolbar-btn-danger",
11684
+ onClick: () => editor.chain().focus().deleteTable().run(),
11685
+ title: "Delete table"
11686
+ },
11687
+ /* @__PURE__ */ import_react58.default.createElement(IconDeleteTable, null)
11688
+ )
11689
+ ),
11690
+ document.body
11691
+ );
11692
+ };
11693
+ var TableToolbar_default = TableToolbar;
11694
+
11523
11695
  // lib/RufousTextEditor/legacyTodoTransform.ts
11524
11696
  var IMAGE_TO_STATUS = {
11525
11697
  "todo-blank.svg": "todo",
@@ -11679,7 +11851,7 @@ var RufousTextEditor = ({
11679
11851
  sx
11680
11852
  }) => {
11681
11853
  const sxClass = useSx(sx);
11682
- const toolbarButtons = (0, import_react58.useMemo)(() => {
11854
+ const toolbarButtons = (0, import_react59.useMemo)(() => {
11683
11855
  const list = buttons || VARIANT_BUTTONS[variant] || VARIANT_BUTTONS.default;
11684
11856
  const visible = new Set(list.filter((b) => b !== "|"));
11685
11857
  if (hideButtons) {
@@ -11687,17 +11859,17 @@ var RufousTextEditor = ({
11687
11859
  }
11688
11860
  return visible;
11689
11861
  }, [buttons, variant, hideButtons]);
11690
- const mentionSuggestion = (0, import_react58.useMemo)(() => createMentionSuggestion(mentions), [mentions]);
11691
- const onChangeRef = (0, import_react58.useRef)(onChange);
11692
- const onBlurRef = (0, import_react58.useRef)(onBlur);
11693
- (0, import_react58.useEffect)(() => {
11862
+ const mentionSuggestion = (0, import_react59.useMemo)(() => createMentionSuggestion(mentions), [mentions]);
11863
+ const onChangeRef = (0, import_react59.useRef)(onChange);
11864
+ const onBlurRef = (0, import_react59.useRef)(onBlur);
11865
+ (0, import_react59.useEffect)(() => {
11694
11866
  onChangeRef.current = onChange;
11695
11867
  }, [onChange]);
11696
- (0, import_react58.useEffect)(() => {
11868
+ (0, import_react59.useEffect)(() => {
11697
11869
  onBlurRef.current = onBlur;
11698
11870
  }, [onBlur]);
11699
11871
  const isEditable = editable && !disabled;
11700
- const editor = (0, import_react59.useEditor)({
11872
+ const editor = (0, import_react60.useEditor)({
11701
11873
  editable: isEditable,
11702
11874
  extensions: [
11703
11875
  import_starter_kit.default,
@@ -11724,7 +11896,9 @@ var RufousTextEditor = ({
11724
11896
  multicolor: true
11725
11897
  }),
11726
11898
  import_extension_table.default.configure({
11727
- resizable: true
11899
+ resizable: true,
11900
+ cellMinWidth: 80,
11901
+ lastColumnResizable: true
11728
11902
  }),
11729
11903
  import_extension_table_row.default,
11730
11904
  import_extension_table_cell.default,
@@ -11792,8 +11966,8 @@ var RufousTextEditor = ({
11792
11966
  onChangeRef.current?.(e.getHTML(), e.getJSON());
11793
11967
  }
11794
11968
  });
11795
- const wrapperRef = (0, import_react58.useRef)(null);
11796
- (0, import_react58.useEffect)(() => {
11969
+ const wrapperRef = (0, import_react59.useRef)(null);
11970
+ (0, import_react59.useEffect)(() => {
11797
11971
  if (!editor) return;
11798
11972
  let blurTimer = null;
11799
11973
  const handler = ({ event }) => {
@@ -11811,15 +11985,15 @@ var RufousTextEditor = ({
11811
11985
  if (blurTimer) clearTimeout(blurTimer);
11812
11986
  };
11813
11987
  }, [editor]);
11814
- const setLinkRef = (0, import_react58.useRef)(null);
11815
- const [linkModalOpen, setLinkModalOpen] = (0, import_react58.useState)(false);
11816
- const [linkUrl, setLinkUrl] = (0, import_react58.useState)("");
11817
- const [linkText, setLinkText] = (0, import_react58.useState)("");
11818
- const [linkClassName, setLinkClassName] = (0, import_react58.useState)("");
11819
- const [linkNewTab, setLinkNewTab] = (0, import_react58.useState)(true);
11820
- const [linkNoFollow, setLinkNoFollow] = (0, import_react58.useState)(true);
11821
- const [linkSelection, setLinkSelection] = (0, import_react58.useState)(null);
11822
- const setLink = (0, import_react58.useCallback)(() => {
11988
+ const setLinkRef = (0, import_react59.useRef)(null);
11989
+ const [linkModalOpen, setLinkModalOpen] = (0, import_react59.useState)(false);
11990
+ const [linkUrl, setLinkUrl] = (0, import_react59.useState)("");
11991
+ const [linkText, setLinkText] = (0, import_react59.useState)("");
11992
+ const [linkClassName, setLinkClassName] = (0, import_react59.useState)("");
11993
+ const [linkNewTab, setLinkNewTab] = (0, import_react59.useState)(true);
11994
+ const [linkNoFollow, setLinkNoFollow] = (0, import_react59.useState)(true);
11995
+ const [linkSelection, setLinkSelection] = (0, import_react59.useState)(null);
11996
+ const setLink = (0, import_react59.useCallback)(() => {
11823
11997
  if (!editor) return;
11824
11998
  const attrs = editor.getAttributes("link");
11825
11999
  const previousUrl = attrs.href || "";
@@ -11856,10 +12030,10 @@ var RufousTextEditor = ({
11856
12030
  setLinkSelection({ from, to });
11857
12031
  setLinkModalOpen(true);
11858
12032
  }, [editor]);
11859
- (0, import_react58.useEffect)(() => {
12033
+ (0, import_react59.useEffect)(() => {
11860
12034
  setLinkRef.current = setLink;
11861
12035
  }, [setLink]);
11862
- (0, import_react58.useEffect)(() => {
12036
+ (0, import_react59.useEffect)(() => {
11863
12037
  if (!editor?.view) return;
11864
12038
  const handleKeyDown = (event) => {
11865
12039
  if ((event.ctrlKey || event.metaKey) && event.key === "k") {
@@ -11891,7 +12065,7 @@ var RufousTextEditor = ({
11891
12065
  editor.view.dom.removeEventListener("keydown", handleKeyDown);
11892
12066
  };
11893
12067
  }, [editor]);
11894
- const handleLinkSubmit = (0, import_react58.useCallback)(() => {
12068
+ const handleLinkSubmit = (0, import_react59.useCallback)(() => {
11895
12069
  if (!editor || !linkSelection) return;
11896
12070
  editor.chain().focus().setTextSelection(linkSelection).run();
11897
12071
  if (linkUrl === "") {
@@ -11927,7 +12101,7 @@ var RufousTextEditor = ({
11927
12101
  setLinkClassName("");
11928
12102
  setLinkSelection(null);
11929
12103
  }, [editor, linkUrl, linkText, linkClassName, linkNewTab, linkNoFollow, linkSelection]);
11930
- const handleLinkRemove = (0, import_react58.useCallback)(() => {
12104
+ const handleLinkRemove = (0, import_react59.useCallback)(() => {
11931
12105
  if (!editor || !linkSelection) return;
11932
12106
  editor.chain().focus().setTextSelection(linkSelection).extendMarkRange("link").unsetLink().run();
11933
12107
  setLinkModalOpen(false);
@@ -11936,7 +12110,7 @@ var RufousTextEditor = ({
11936
12110
  setLinkClassName("");
11937
12111
  setLinkSelection(null);
11938
12112
  }, [editor, linkSelection]);
11939
- const handleLinkCancel = (0, import_react58.useCallback)(() => {
12113
+ const handleLinkCancel = (0, import_react59.useCallback)(() => {
11940
12114
  setLinkModalOpen(false);
11941
12115
  setLinkUrl("");
11942
12116
  setLinkText("");
@@ -11944,30 +12118,32 @@ var RufousTextEditor = ({
11944
12118
  setLinkSelection(null);
11945
12119
  editor?.chain().focus().run();
11946
12120
  }, [editor]);
11947
- const [saveStatus, setSaveStatus] = (0, import_react58.useState)("");
11948
- const handleSave = (0, import_react58.useCallback)(() => {
12121
+ const [saveStatus, setSaveStatus] = (0, import_react59.useState)("");
12122
+ const handleSave = (0, import_react59.useCallback)(() => {
11949
12123
  if (!editor || !onSaveProp) return;
11950
12124
  onSaveProp(editor.getHTML(), editor.getJSON());
11951
12125
  setSaveStatus("Saved!");
11952
12126
  setTimeout(() => setSaveStatus(""), 2e3);
11953
12127
  }, [editor, onSaveProp]);
11954
- const handleExport = (0, import_react58.useCallback)(() => {
12128
+ const handleExport = (0, import_react59.useCallback)(() => {
11955
12129
  if (!editor || !onExportProp) return;
11956
12130
  onExportProp(editor.getHTML(), editor.getJSON());
11957
12131
  }, [editor, onExportProp]);
11958
- const providerValue = (0, import_react58.useMemo)(() => ({ editor }), [editor]);
11959
- return /* @__PURE__ */ import_react58.default.createElement(
12132
+ const providerValue = (0, import_react59.useMemo)(() => ({ editor }), [editor]);
12133
+ const [isFullscreen, setIsFullscreen] = (0, import_react59.useState)(false);
12134
+ const toggleFullscreen = (0, import_react59.useCallback)(() => setIsFullscreen((prev) => !prev), []);
12135
+ const wrapperJsx = /* @__PURE__ */ import_react59.default.createElement(
11960
12136
  "div",
11961
12137
  {
11962
12138
  ref: wrapperRef,
11963
- className: `rf-rte-wrapper editor-wrapper ${resizable ? "rf-rte-resizable" : ""} ${disabled ? "rf-rte-disabled" : ""} ${error ? "rf-rte-error" : ""} ${sxClass} ${className || ""}`,
11964
- style: {
12139
+ className: `rf-rte-wrapper editor-wrapper ${isFullscreen ? "fullscreen" : ""} ${resizable ? "rf-rte-resizable" : ""} ${disabled ? "rf-rte-disabled" : ""} ${error ? "rf-rte-error" : ""} ${sxClass} ${className || ""}`,
12140
+ style: isFullscreen ? void 0 : {
11965
12141
  ...style,
11966
12142
  ...width ? { width: typeof width === "number" ? `${width}px` : width } : {},
11967
12143
  ...height ? { height: typeof height === "number" ? `${height}px` : height } : {}
11968
12144
  }
11969
12145
  },
11970
- /* @__PURE__ */ import_react58.default.createElement(import_react59.EditorContext.Provider, { value: providerValue }, /* @__PURE__ */ import_react58.default.createElement(
12146
+ /* @__PURE__ */ import_react59.default.createElement(import_react60.EditorContext.Provider, { value: providerValue }, /* @__PURE__ */ import_react59.default.createElement(
11971
12147
  Toolbar_default,
11972
12148
  {
11973
12149
  editor,
@@ -11978,10 +12154,12 @@ var RufousTextEditor = ({
11978
12154
  onTextToSpeech,
11979
12155
  onImageUpload,
11980
12156
  onClose,
11981
- visibleButtons: toolbarButtons
12157
+ visibleButtons: toolbarButtons,
12158
+ isFullscreen,
12159
+ onToggleFullscreen: toggleFullscreen
11982
12160
  }
11983
- ), /* @__PURE__ */ import_react58.default.createElement(import_react59.EditorContent, { editor, className: "editor-content-wrapper" }), /* @__PURE__ */ import_react58.default.createElement(ImageToolbar_default, { editor }), /* @__PURE__ */ import_react58.default.createElement(VideoToolbar_default, { editor }), editor && /* @__PURE__ */ import_react58.default.createElement(
11984
- import_react59.BubbleMenu,
12161
+ ), /* @__PURE__ */ import_react59.default.createElement(import_react60.EditorContent, { editor, className: "editor-content-wrapper" }), /* @__PURE__ */ import_react59.default.createElement(ImageToolbar_default, { editor }), /* @__PURE__ */ import_react59.default.createElement(VideoToolbar_default, { editor }), /* @__PURE__ */ import_react59.default.createElement(TableToolbar_default, { editor }), editor && /* @__PURE__ */ import_react59.default.createElement(
12162
+ import_react60.BubbleMenu,
11985
12163
  {
11986
12164
  editor,
11987
12165
  className: "bubble-menu",
@@ -11998,31 +12176,31 @@ var RufousTextEditor = ({
11998
12176
  }
11999
12177
  }
12000
12178
  },
12001
- /* @__PURE__ */ import_react58.default.createElement(
12179
+ /* @__PURE__ */ import_react59.default.createElement(
12002
12180
  "button",
12003
12181
  {
12004
12182
  onClick: () => editor?.chain().focus().toggleBold().run(),
12005
12183
  className: editor?.isActive("bold") ? "is-active" : ""
12006
12184
  },
12007
- /* @__PURE__ */ import_react58.default.createElement("strong", null, "B")
12185
+ /* @__PURE__ */ import_react59.default.createElement("strong", null, "B")
12008
12186
  ),
12009
- /* @__PURE__ */ import_react58.default.createElement(
12187
+ /* @__PURE__ */ import_react59.default.createElement(
12010
12188
  "button",
12011
12189
  {
12012
12190
  onClick: () => editor?.chain().focus().toggleItalic().run(),
12013
12191
  className: editor?.isActive("italic") ? "is-active" : ""
12014
12192
  },
12015
- /* @__PURE__ */ import_react58.default.createElement("em", null, "I")
12193
+ /* @__PURE__ */ import_react59.default.createElement("em", null, "I")
12016
12194
  ),
12017
- /* @__PURE__ */ import_react58.default.createElement(
12195
+ /* @__PURE__ */ import_react59.default.createElement(
12018
12196
  "button",
12019
12197
  {
12020
12198
  onClick: () => editor?.chain().focus().toggleStrike().run(),
12021
12199
  className: editor?.isActive("strike") ? "is-active" : ""
12022
12200
  },
12023
- /* @__PURE__ */ import_react58.default.createElement("s", null, "S")
12201
+ /* @__PURE__ */ import_react59.default.createElement("s", null, "S")
12024
12202
  ),
12025
- /* @__PURE__ */ import_react58.default.createElement(
12203
+ /* @__PURE__ */ import_react59.default.createElement(
12026
12204
  "button",
12027
12205
  {
12028
12206
  onClick: () => editor?.chain().focus().toggleCode().run(),
@@ -12030,7 +12208,7 @@ var RufousTextEditor = ({
12030
12208
  },
12031
12209
  "</>"
12032
12210
  ),
12033
- /* @__PURE__ */ import_react58.default.createElement(
12211
+ /* @__PURE__ */ import_react59.default.createElement(
12034
12212
  "button",
12035
12213
  {
12036
12214
  onClick: setLink,
@@ -12038,8 +12216,8 @@ var RufousTextEditor = ({
12038
12216
  },
12039
12217
  "\u{1F517}"
12040
12218
  )
12041
- ), editor && /* @__PURE__ */ import_react58.default.createElement(
12042
- import_react59.FloatingMenu,
12219
+ ), editor && /* @__PURE__ */ import_react59.default.createElement(
12220
+ import_react60.FloatingMenu,
12043
12221
  {
12044
12222
  editor,
12045
12223
  className: "floating-menu",
@@ -12053,7 +12231,7 @@ var RufousTextEditor = ({
12053
12231
  }
12054
12232
  }
12055
12233
  },
12056
- /* @__PURE__ */ import_react58.default.createElement(
12234
+ /* @__PURE__ */ import_react59.default.createElement(
12057
12235
  "button",
12058
12236
  {
12059
12237
  onClick: () => editor?.chain().focus().toggleHeading({ level: 1 }).run(),
@@ -12061,7 +12239,7 @@ var RufousTextEditor = ({
12061
12239
  },
12062
12240
  "H1"
12063
12241
  ),
12064
- /* @__PURE__ */ import_react58.default.createElement(
12242
+ /* @__PURE__ */ import_react59.default.createElement(
12065
12243
  "button",
12066
12244
  {
12067
12245
  onClick: () => editor?.chain().focus().toggleHeading({ level: 2 }).run(),
@@ -12069,7 +12247,7 @@ var RufousTextEditor = ({
12069
12247
  },
12070
12248
  "H2"
12071
12249
  ),
12072
- /* @__PURE__ */ import_react58.default.createElement(
12250
+ /* @__PURE__ */ import_react59.default.createElement(
12073
12251
  "button",
12074
12252
  {
12075
12253
  onClick: () => editor?.chain().focus().toggleBulletList().run(),
@@ -12077,7 +12255,7 @@ var RufousTextEditor = ({
12077
12255
  },
12078
12256
  "\u2022 List"
12079
12257
  ),
12080
- /* @__PURE__ */ import_react58.default.createElement(
12258
+ /* @__PURE__ */ import_react59.default.createElement(
12081
12259
  "button",
12082
12260
  {
12083
12261
  onClick: () => editor?.chain().focus().toggleOrderedList().run(),
@@ -12085,7 +12263,7 @@ var RufousTextEditor = ({
12085
12263
  },
12086
12264
  "1. List"
12087
12265
  ),
12088
- /* @__PURE__ */ import_react58.default.createElement(
12266
+ /* @__PURE__ */ import_react59.default.createElement(
12089
12267
  "button",
12090
12268
  {
12091
12269
  onClick: () => editor?.chain().focus().toggleBlockquote().run(),
@@ -12093,8 +12271,8 @@ var RufousTextEditor = ({
12093
12271
  },
12094
12272
  "\u201C Quote"
12095
12273
  )
12096
- ), /* @__PURE__ */ import_react58.default.createElement("div", { className: "status-bar" }, /* @__PURE__ */ import_react58.default.createElement("div", { className: "status-bar-left" }, onSaveProp && /* @__PURE__ */ import_react58.default.createElement("button", { onClick: handleSave, className: "status-btn save-btn" }, "Save"), onExportProp && /* @__PURE__ */ import_react58.default.createElement("button", { onClick: handleExport, className: "status-btn export-btn" }, "Export")), /* @__PURE__ */ import_react58.default.createElement("div", { className: "status-bar-right" }, saveStatus && /* @__PURE__ */ import_react58.default.createElement("span", { className: "save-status" }, saveStatus), editor && /* @__PURE__ */ import_react58.default.createElement(import_react58.default.Fragment, null, /* @__PURE__ */ import_react58.default.createElement("span", { className: "word-count" }, "CHARS: ", editor.storage.characterCount?.characters?.() ?? editor.getText().length), /* @__PURE__ */ import_react58.default.createElement("span", { className: "word-count" }, "WORDS: ", editor.storage.characterCount?.words?.() ?? editor.getText().split(/\s+/).filter(Boolean).length)))), linkModalOpen && (0, import_react_dom13.createPortal)(
12097
- /* @__PURE__ */ import_react58.default.createElement("div", { className: "link-modal-overlay", onClick: handleLinkCancel }, /* @__PURE__ */ import_react58.default.createElement("div", { className: "link-modal", onClick: (e) => e.stopPropagation() }, /* @__PURE__ */ import_react58.default.createElement("div", { className: "link-modal-body" }, /* @__PURE__ */ import_react58.default.createElement("div", { className: "link-modal-field" }, /* @__PURE__ */ import_react58.default.createElement("label", { className: "link-modal-label" }, "URL"), /* @__PURE__ */ import_react58.default.createElement(
12274
+ ), /* @__PURE__ */ import_react59.default.createElement("div", { className: "status-bar" }, /* @__PURE__ */ import_react59.default.createElement("div", { className: "status-bar-left" }, onSaveProp && /* @__PURE__ */ import_react59.default.createElement("button", { onClick: handleSave, className: "status-btn save-btn" }, "Save"), onExportProp && /* @__PURE__ */ import_react59.default.createElement("button", { onClick: handleExport, className: "status-btn export-btn" }, "Export")), /* @__PURE__ */ import_react59.default.createElement("div", { className: "status-bar-right" }, saveStatus && /* @__PURE__ */ import_react59.default.createElement("span", { className: "save-status" }, saveStatus), editor && /* @__PURE__ */ import_react59.default.createElement(import_react59.default.Fragment, null, /* @__PURE__ */ import_react59.default.createElement("span", { className: "word-count" }, "CHARS: ", editor.storage.characterCount?.characters?.() ?? editor.getText().length), /* @__PURE__ */ import_react59.default.createElement("span", { className: "word-count" }, "WORDS: ", editor.storage.characterCount?.words?.() ?? editor.getText().split(/\s+/).filter(Boolean).length)))), linkModalOpen && (0, import_react_dom14.createPortal)(
12275
+ /* @__PURE__ */ import_react59.default.createElement("div", { className: "link-modal-overlay", onClick: handleLinkCancel }, /* @__PURE__ */ import_react59.default.createElement("div", { className: "link-modal", onClick: (e) => e.stopPropagation() }, /* @__PURE__ */ import_react59.default.createElement("div", { className: "link-modal-body" }, /* @__PURE__ */ import_react59.default.createElement("div", { className: "link-modal-field" }, /* @__PURE__ */ import_react59.default.createElement("label", { className: "link-modal-label" }, "URL"), /* @__PURE__ */ import_react59.default.createElement(
12098
12276
  "input",
12099
12277
  {
12100
12278
  type: "url",
@@ -12107,7 +12285,7 @@ var RufousTextEditor = ({
12107
12285
  placeholder: "https://example.com",
12108
12286
  autoFocus: true
12109
12287
  }
12110
- )), /* @__PURE__ */ import_react58.default.createElement("div", { className: "link-modal-field" }, /* @__PURE__ */ import_react58.default.createElement("label", { className: "link-modal-label" }, "Text"), /* @__PURE__ */ import_react58.default.createElement(
12288
+ )), /* @__PURE__ */ import_react59.default.createElement("div", { className: "link-modal-field" }, /* @__PURE__ */ import_react59.default.createElement("label", { className: "link-modal-label" }, "Text"), /* @__PURE__ */ import_react59.default.createElement(
12111
12289
  "input",
12112
12290
  {
12113
12291
  type: "text",
@@ -12119,30 +12297,31 @@ var RufousTextEditor = ({
12119
12297
  },
12120
12298
  placeholder: "Link text"
12121
12299
  }
12122
- )), /* @__PURE__ */ import_react58.default.createElement("div", { className: "link-modal-checkboxes" }, /* @__PURE__ */ import_react58.default.createElement("label", { className: "link-modal-checkbox" }, /* @__PURE__ */ import_react58.default.createElement(
12300
+ )), /* @__PURE__ */ import_react59.default.createElement("div", { className: "link-modal-checkboxes" }, /* @__PURE__ */ import_react59.default.createElement("label", { className: "link-modal-checkbox" }, /* @__PURE__ */ import_react59.default.createElement(
12123
12301
  "input",
12124
12302
  {
12125
12303
  type: "checkbox",
12126
12304
  checked: linkNewTab,
12127
12305
  onChange: (e) => setLinkNewTab(e.target.checked)
12128
12306
  }
12129
- ), "Open in new tab"), /* @__PURE__ */ import_react58.default.createElement("label", { className: "link-modal-checkbox" }, /* @__PURE__ */ import_react58.default.createElement(
12307
+ ), "Open in new tab"), /* @__PURE__ */ import_react59.default.createElement("label", { className: "link-modal-checkbox" }, /* @__PURE__ */ import_react59.default.createElement(
12130
12308
  "input",
12131
12309
  {
12132
12310
  type: "checkbox",
12133
12311
  checked: linkNoFollow,
12134
12312
  onChange: (e) => setLinkNoFollow(e.target.checked)
12135
12313
  }
12136
- ), "No follow"))), /* @__PURE__ */ import_react58.default.createElement("div", { className: "link-modal-footer" }, /* @__PURE__ */ import_react58.default.createElement("button", { className: "link-modal-btn-unlink", onClick: handleLinkRemove }, "Unlink"), /* @__PURE__ */ import_react58.default.createElement("button", { className: "link-modal-btn-apply", onClick: handleLinkSubmit }, "Update")))),
12314
+ ), "No follow"))), /* @__PURE__ */ import_react59.default.createElement("div", { className: "link-modal-footer" }, /* @__PURE__ */ import_react59.default.createElement("button", { className: "link-modal-btn-unlink", onClick: handleLinkRemove }, "Unlink"), /* @__PURE__ */ import_react59.default.createElement("button", { className: "link-modal-btn-apply", onClick: handleLinkSubmit }, "Update")))),
12137
12315
  document.body
12138
12316
  )),
12139
- helperText && /* @__PURE__ */ import_react58.default.createElement("div", { className: `rf-rte-helper-text ${error ? "rf-rte-helper-error" : ""}` }, helperText)
12317
+ helperText && /* @__PURE__ */ import_react59.default.createElement("div", { className: `rf-rte-helper-text ${error ? "rf-rte-helper-error" : ""}` }, helperText)
12140
12318
  );
12319
+ return isFullscreen ? (0, import_react_dom14.createPortal)(wrapperJsx, document.body) : wrapperJsx;
12141
12320
  };
12142
12321
  var RufousTextContent = ({ content, className, style, sx }) => {
12143
12322
  const sxClass = useSx(sx);
12144
- const transformedContent = (0, import_react58.useMemo)(() => transformLegacyTodos(content || ""), [content]);
12145
- return /* @__PURE__ */ import_react58.default.createElement(
12323
+ const transformedContent = (0, import_react59.useMemo)(() => transformLegacyTodos(content || ""), [content]);
12324
+ return /* @__PURE__ */ import_react59.default.createElement(
12146
12325
  "div",
12147
12326
  {
12148
12327
  className: `rf-rte-content ${sxClass} ${className || ""}`,