@rufous/ui 0.2.65 → 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.js CHANGED
@@ -1987,6 +1987,7 @@ import React70, {
1987
1987
  useEffect as useEffect4,
1988
1988
  useCallback
1989
1989
  } from "react";
1990
+ import { createPortal } from "react-dom";
1990
1991
  var WEEKDAYS = ["SU", "MO", "TU", "WE", "TH", "FR", "SA"];
1991
1992
  var MONTHS = [
1992
1993
  "January",
@@ -2428,7 +2429,10 @@ var DateField = ({
2428
2429
  useEffect4(() => {
2429
2430
  if (!open) return;
2430
2431
  const handler = (e) => {
2431
- if (containerRef.current && !containerRef.current.contains(e.target)) setOpen(false);
2432
+ const target = e.target;
2433
+ if (containerRef.current?.contains(target)) return;
2434
+ if (pickerRef.current?.contains(target)) return;
2435
+ setOpen(false);
2432
2436
  };
2433
2437
  document.addEventListener("mousedown", handler);
2434
2438
  return () => document.removeEventListener("mousedown", handler);
@@ -2629,80 +2633,97 @@ var DateField = ({
2629
2633
  )),
2630
2634
  label && /* @__PURE__ */ React70.createElement("label", { htmlFor: inputId, className: "rf-text-field__label" }, label, " ", required && /* @__PURE__ */ React70.createElement("span", { className: "rf-text-field__asterisk" }, "*")),
2631
2635
  variant === "outlined" && /* @__PURE__ */ React70.createElement("fieldset", { className: "rf-text-field__notch" }, label && /* @__PURE__ */ React70.createElement("legend", { className: "rf-text-field__legend" }, /* @__PURE__ */ React70.createElement("span", null, label, required ? " *" : "")))
2632
- ), open && !disabled && /* @__PURE__ */ React70.createElement(
2633
- "div",
2634
- {
2635
- ref: pickerRef,
2636
- className: [
2637
- "rf-date-picker",
2638
- isSideVariant ? "rf-date-picker--side" : "",
2639
- dropUp ? "rf-date-picker--drop-up" : ""
2640
- ].filter(Boolean).join(" "),
2641
- onMouseDown: (e) => e.preventDefault()
2642
- },
2643
- /* @__PURE__ */ React70.createElement("div", { className: isSideVariant ? "rf-date-picker__cal-col" : void 0 }, /* @__PURE__ */ React70.createElement(
2644
- CalendarBody,
2645
- {
2646
- viewMonth,
2647
- viewYear,
2648
- selectedDate,
2649
- todayDate,
2650
- dayCells,
2651
- onDayClick: handleDayClick,
2652
- onPrev: prevMonth,
2653
- onNext: nextMonth,
2654
- onMonthSelect: setViewMonth,
2655
- onYearSelect: setViewYear
2656
- }
2657
- ), type === "datetime" && /* @__PURE__ */ React70.createElement("div", { className: "rf-date-picker__time-section" }, /* @__PURE__ */ React70.createElement("div", { className: "rf-date-picker__time-label" }, "Time"), /* @__PURE__ */ React70.createElement(
2658
- SpinnerPanel,
2659
- {
2660
- hour,
2661
- minute,
2662
- ampm,
2663
- onHourChange: handleHourChange,
2664
- onMinuteChange: handleMinuteChange,
2665
- onHourInput: handleHourInput,
2666
- onMinuteInput: handleMinuteInput,
2667
- onAmpmToggle: handleAmpmToggle
2668
- }
2669
- )), /* @__PURE__ */ React70.createElement("div", { className: "rf-date-picker__divider" }), /* @__PURE__ */ React70.createElement("div", { className: "rf-date-picker__footer" }, /* @__PURE__ */ React70.createElement("button", { type: "button", className: "rf-date-picker__footer-btn", onClick: handleToday }, "Today"), /* @__PURE__ */ React70.createElement("button", { type: "button", className: "rf-date-picker__footer-btn rf-date-picker__footer-btn--clear", onClick: handleClear }, "Clear"))),
2670
- type === "datetime-side" && /* @__PURE__ */ React70.createElement("div", { className: "rf-date-picker__side-panel" }, /* @__PURE__ */ React70.createElement("div", { className: "rf-date-picker__side-label" }, "Time"), /* @__PURE__ */ React70.createElement("div", { className: "rf-date-picker__side-spinner" }, /* @__PURE__ */ React70.createElement(
2671
- SpinnerPanel,
2672
- {
2673
- hour,
2674
- minute,
2675
- ampm,
2676
- onHourChange: handleHourChange,
2677
- onMinuteChange: handleMinuteChange,
2678
- onHourInput: handleHourInput,
2679
- onMinuteInput: handleMinuteInput,
2680
- onAmpmToggle: handleAmpmToggle
2681
- }
2682
- )), /* @__PURE__ */ React70.createElement("div", { className: "rf-date-picker__side-time-display" }, String(hour).padStart(2, "0"), ":", String(minute).padStart(2, "0"), " ", ampm)),
2683
- type === "datetime-scroll" && /* @__PURE__ */ React70.createElement("div", { className: "rf-date-picker__side-panel" }, /* @__PURE__ */ React70.createElement("div", { className: "rf-date-picker__side-label" }, "Time"), /* @__PURE__ */ React70.createElement("div", { className: "rf-timescroll" }, /* @__PURE__ */ React70.createElement(
2684
- ScrollColumn,
2685
- {
2686
- items: HOURS,
2687
- selected: hour - 1,
2688
- onSelect: handleScrollHour
2689
- }
2690
- ), /* @__PURE__ */ React70.createElement("div", { className: "rf-timescroll__colon" }, ":"), /* @__PURE__ */ React70.createElement(
2691
- ScrollColumn,
2692
- {
2693
- items: MINUTES,
2694
- selected: minute,
2695
- onSelect: handleScrollMinute
2696
- }
2697
- ), /* @__PURE__ */ React70.createElement(
2698
- ScrollColumn,
2636
+ ), open && !disabled && createPortal(
2637
+ /* @__PURE__ */ React70.createElement(
2638
+ "div",
2699
2639
  {
2700
- items: AMPMS,
2701
- selected: ampm === "AM" ? 0 : 1,
2702
- onSelect: handleScrollAmpm,
2703
- infinite: false
2704
- }
2705
- )), /* @__PURE__ */ React70.createElement("div", { className: "rf-date-picker__side-time-display" }, String(hour).padStart(2, "0"), ":", String(minute).padStart(2, "0"), " ", ampm))
2640
+ ref: pickerRef,
2641
+ className: [
2642
+ "rf-date-picker",
2643
+ "rf-date-picker--portaled",
2644
+ isSideVariant ? "rf-date-picker--side" : "",
2645
+ dropUp ? "rf-date-picker--drop-up" : ""
2646
+ ].filter(Boolean).join(" "),
2647
+ style: (() => {
2648
+ const rect = containerRef.current?.getBoundingClientRect();
2649
+ if (!rect) return {};
2650
+ const top = rect.bottom + 6;
2651
+ const spaceBelow = window.innerHeight - rect.bottom - 6;
2652
+ const useDropUp = spaceBelow < 350 && rect.top > spaceBelow;
2653
+ return {
2654
+ position: "fixed",
2655
+ left: rect.left,
2656
+ ...useDropUp ? { bottom: window.innerHeight - rect.top + 6 } : { top },
2657
+ zIndex: 99999
2658
+ };
2659
+ })(),
2660
+ onMouseDown: (e) => e.preventDefault()
2661
+ },
2662
+ /* @__PURE__ */ React70.createElement("div", { className: isSideVariant ? "rf-date-picker__cal-col" : void 0 }, /* @__PURE__ */ React70.createElement(
2663
+ CalendarBody,
2664
+ {
2665
+ viewMonth,
2666
+ viewYear,
2667
+ selectedDate,
2668
+ todayDate,
2669
+ dayCells,
2670
+ onDayClick: handleDayClick,
2671
+ onPrev: prevMonth,
2672
+ onNext: nextMonth,
2673
+ onMonthSelect: setViewMonth,
2674
+ onYearSelect: setViewYear
2675
+ }
2676
+ ), type === "datetime" && /* @__PURE__ */ React70.createElement("div", { className: "rf-date-picker__time-section" }, /* @__PURE__ */ React70.createElement("div", { className: "rf-date-picker__time-label" }, "Time"), /* @__PURE__ */ React70.createElement(
2677
+ SpinnerPanel,
2678
+ {
2679
+ hour,
2680
+ minute,
2681
+ ampm,
2682
+ onHourChange: handleHourChange,
2683
+ onMinuteChange: handleMinuteChange,
2684
+ onHourInput: handleHourInput,
2685
+ onMinuteInput: handleMinuteInput,
2686
+ onAmpmToggle: handleAmpmToggle
2687
+ }
2688
+ )), /* @__PURE__ */ React70.createElement("div", { className: "rf-date-picker__divider" }), /* @__PURE__ */ React70.createElement("div", { className: "rf-date-picker__footer" }, /* @__PURE__ */ React70.createElement("button", { type: "button", className: "rf-date-picker__footer-btn", onClick: handleToday }, "Today"), /* @__PURE__ */ React70.createElement("button", { type: "button", className: "rf-date-picker__footer-btn rf-date-picker__footer-btn--clear", onClick: handleClear }, "Clear"))),
2689
+ type === "datetime-side" && /* @__PURE__ */ React70.createElement("div", { className: "rf-date-picker__side-panel" }, /* @__PURE__ */ React70.createElement("div", { className: "rf-date-picker__side-label" }, "Time"), /* @__PURE__ */ React70.createElement("div", { className: "rf-date-picker__side-spinner" }, /* @__PURE__ */ React70.createElement(
2690
+ SpinnerPanel,
2691
+ {
2692
+ hour,
2693
+ minute,
2694
+ ampm,
2695
+ onHourChange: handleHourChange,
2696
+ onMinuteChange: handleMinuteChange,
2697
+ onHourInput: handleHourInput,
2698
+ onMinuteInput: handleMinuteInput,
2699
+ onAmpmToggle: handleAmpmToggle
2700
+ }
2701
+ )), /* @__PURE__ */ React70.createElement("div", { className: "rf-date-picker__side-time-display" }, String(hour).padStart(2, "0"), ":", String(minute).padStart(2, "0"), " ", ampm)),
2702
+ type === "datetime-scroll" && /* @__PURE__ */ React70.createElement("div", { className: "rf-date-picker__side-panel" }, /* @__PURE__ */ React70.createElement("div", { className: "rf-date-picker__side-label" }, "Time"), /* @__PURE__ */ React70.createElement("div", { className: "rf-timescroll" }, /* @__PURE__ */ React70.createElement(
2703
+ ScrollColumn,
2704
+ {
2705
+ items: HOURS,
2706
+ selected: hour - 1,
2707
+ onSelect: handleScrollHour
2708
+ }
2709
+ ), /* @__PURE__ */ React70.createElement("div", { className: "rf-timescroll__colon" }, ":"), /* @__PURE__ */ React70.createElement(
2710
+ ScrollColumn,
2711
+ {
2712
+ items: MINUTES,
2713
+ selected: minute,
2714
+ onSelect: handleScrollMinute
2715
+ }
2716
+ ), /* @__PURE__ */ React70.createElement(
2717
+ ScrollColumn,
2718
+ {
2719
+ items: AMPMS,
2720
+ selected: ampm === "AM" ? 0 : 1,
2721
+ onSelect: handleScrollAmpm,
2722
+ infinite: false
2723
+ }
2724
+ )), /* @__PURE__ */ React70.createElement("div", { className: "rf-date-picker__side-time-display" }, String(hour).padStart(2, "0"), ":", String(minute).padStart(2, "0"), " ", ampm))
2725
+ ),
2726
+ document.body
2706
2727
  )), helperText && /* @__PURE__ */ React70.createElement("div", { className: "rf-text-field__helper-text" }, helperText));
2707
2728
  };
2708
2729
  DateField.displayName = "DateField";
@@ -8269,8 +8290,8 @@ var PhoneField = forwardRef10(function PhoneField2(props, ref) {
8269
8290
  PhoneField.displayName = "PhoneField";
8270
8291
 
8271
8292
  // lib/RufousTextEditor/RufousTextEditor.tsx
8272
- import React115, { useMemo as useMemo4, useCallback as useCallback13, useState as useState33, useRef as useRef29, useEffect as useEffect26 } from "react";
8273
- import { createPortal as createPortal6 } from "react-dom";
8293
+ import React116, { useMemo as useMemo4, useCallback as useCallback13, useState as useState34, useRef as useRef30, useEffect as useEffect27 } from "react";
8294
+ import { createPortal as createPortal8 } from "react-dom";
8274
8295
  import { useEditor, EditorContent, EditorContext, FloatingMenu, BubbleMenu } from "@tiptap/react";
8275
8296
  import StarterKit from "@tiptap/starter-kit";
8276
8297
  import Placeholder from "@tiptap/extension-placeholder";
@@ -8392,11 +8413,11 @@ function createMentionSuggestion(users) {
8392
8413
 
8393
8414
  // lib/RufousTextEditor/Toolbar.tsx
8394
8415
  import React112, { useState as useState30, useRef as useRef26, useEffect as useEffect23, useCallback as useCallback12 } from "react";
8395
- import { createPortal as createPortal3 } from "react-dom";
8416
+ import { createPortal as createPortal4 } from "react-dom";
8396
8417
 
8397
8418
  // lib/RufousTextEditor/TextToSpeech.tsx
8398
- import React107, { useState as useState26, useEffect as useEffect20, useRef as useRef23, useCallback as useCallback9 } from "react";
8399
- var TextToSpeech = ({ editor, onTextToSpeech }) => {
8419
+ import React107, { useState as useState26, useEffect as useEffect20, useRef as useRef23, useCallback as useCallback9, forwardRef as forwardRef12, useImperativeHandle as useImperativeHandle2 } from "react";
8420
+ var TextToSpeech = forwardRef12(({ editor, onTextToSpeech }, ref) => {
8400
8421
  const [speaking, setSpeaking] = useState26(false);
8401
8422
  const [paused, setPaused] = useState26(false);
8402
8423
  const [voices, setVoices] = useState26([]);
@@ -8499,6 +8520,7 @@ var TextToSpeech = ({ editor, onTextToSpeech }) => {
8499
8520
  setSpeaking(false);
8500
8521
  setPaused(false);
8501
8522
  }, []);
8523
+ useImperativeHandle2(ref, () => ({ stop: handleStop }), [handleStop]);
8502
8524
  return /* @__PURE__ */ React107.createElement("div", { className: "tts-wrapper", ref: panelRef }, /* @__PURE__ */ React107.createElement(
8503
8525
  "button",
8504
8526
  {
@@ -8536,12 +8558,12 @@ var TextToSpeech = ({ editor, onTextToSpeech }) => {
8536
8558
  handleSpeak();
8537
8559
  setShowPanel(false);
8538
8560
  } }, "\u25B6 Speak")), speaking && /* @__PURE__ */ React107.createElement("div", { className: "tts-controls" }, paused ? /* @__PURE__ */ React107.createElement("button", { className: "toolbar-btn", onClick: handleResume, title: "Resume" }, "\u25B6") : /* @__PURE__ */ React107.createElement("button", { className: "toolbar-btn", onClick: handlePause, title: "Pause" }, "\u275A\u275A"), /* @__PURE__ */ React107.createElement("button", { className: "toolbar-btn", onClick: handleStop, title: "Stop" }, "\u25A0")));
8539
- };
8561
+ });
8540
8562
  var TextToSpeech_default = TextToSpeech;
8541
8563
 
8542
8564
  // lib/RufousTextEditor/SpeechToText.tsx
8543
- import React108, { useState as useState27, useRef as useRef24, useCallback as useCallback10, useEffect as useEffect21 } from "react";
8544
- var SpeechToText = ({ editor, onSpeechToText }) => {
8565
+ import React108, { useState as useState27, useRef as useRef24, useCallback as useCallback10, useEffect as useEffect21, forwardRef as forwardRef13, useImperativeHandle as useImperativeHandle3 } from "react";
8566
+ var SpeechToText = forwardRef13(({ editor, onSpeechToText }, ref) => {
8545
8567
  const [listening, setListening] = useState27(false);
8546
8568
  const [showPanel, setShowPanel] = useState27(false);
8547
8569
  const [language, setLanguage] = useState27("en-US");
@@ -8652,6 +8674,7 @@ var SpeechToText = ({ editor, onSpeechToText }) => {
8652
8674
  setListening(false);
8653
8675
  setInterim("");
8654
8676
  }, []);
8677
+ useImperativeHandle3(ref, () => ({ stop: stopListening }), [stopListening]);
8655
8678
  if (!supported) {
8656
8679
  return /* @__PURE__ */ React108.createElement("button", { className: "toolbar-btn", disabled: true, title: "Speech recognition not supported in this browser" }, "\u{1F3A4}");
8657
8680
  }
@@ -8698,12 +8721,12 @@ var SpeechToText = ({ editor, onSpeechToText }) => {
8698
8721
  },
8699
8722
  LANGUAGES2.map((l) => /* @__PURE__ */ React108.createElement("option", { key: l.code, value: l.code }, l.label))
8700
8723
  ), /* @__PURE__ */ React108.createElement("div", { className: "stt-info" }, "Speak into your microphone and the text will be typed into the editor."), /* @__PURE__ */ React108.createElement("button", { className: "stt-start-btn", onClick: startListening }, "\u{1F3A4} Start Listening")), listening && interim && /* @__PURE__ */ React108.createElement("div", { className: "stt-interim" }, interim));
8701
- };
8724
+ });
8702
8725
  var SpeechToText_default = SpeechToText;
8703
8726
 
8704
8727
  // lib/RufousTextEditor/AICommands.tsx
8705
8728
  import React109, { useState as useState28, useRef as useRef25, useEffect as useEffect22, useCallback as useCallback11 } from "react";
8706
- import { createPortal } from "react-dom";
8729
+ import { createPortal as createPortal2 } from "react-dom";
8707
8730
  var AI_COMMANDS = [
8708
8731
  { id: "improve", label: "Improve writing", prompt: "Improve the following text to make it clearer, more engaging, and well-structured. Return only the improved text, no explanations." },
8709
8732
  { id: "shorter", label: "Make shorter", prompt: "Make the following text shorter and more concise while keeping the key points. Return only the shortened text, no explanations." },
@@ -8860,7 +8883,7 @@ var AICommands = ({ editor, onAICommand }) => {
8860
8883
  onClick: () => handleCommandSelect(cmd)
8861
8884
  },
8862
8885
  cmd.label
8863
- ))), /* @__PURE__ */ React109.createElement("div", { className: "ai-commands-hint" }, editor.state.selection.empty ? "Will apply to all text" : "Will apply to selected text"))), showModal && createPortal(
8886
+ ))), /* @__PURE__ */ React109.createElement("div", { className: "ai-commands-hint" }, editor.state.selection.empty ? "Will apply to all text" : "Will apply to selected text"))), showModal && createPortal2(
8864
8887
  /* @__PURE__ */ React109.createElement("div", { className: "ai-modal-overlay", onMouseDown: handleCancel }, /* @__PURE__ */ React109.createElement("div", { className: "ai-modal", onMouseDown: (e) => e.stopPropagation() }, /* @__PURE__ */ React109.createElement("div", { className: "ai-modal-header" }, /* @__PURE__ */ React109.createElement("span", { className: "ai-modal-title" }, "AI Assistant"), /* @__PURE__ */ React109.createElement("button", { className: "ai-modal-close", onClick: handleCancel }, "\xD7")), /* @__PURE__ */ React109.createElement("div", { className: "ai-modal-prompt-section" }, /* @__PURE__ */ React109.createElement("label", { className: "ai-modal-label" }, "Prompt"), /* @__PURE__ */ React109.createElement("div", { className: "ai-modal-prompt-row" }, /* @__PURE__ */ React109.createElement(
8865
8888
  "textarea",
8866
8889
  {
@@ -8911,7 +8934,7 @@ var AICommands_default = AICommands;
8911
8934
 
8912
8935
  // lib/RufousTextEditor/TranslateModal.tsx
8913
8936
  import React110, { useState as useState29, useMemo as useMemo3 } from "react";
8914
- import { createPortal as createPortal2 } from "react-dom";
8937
+ import { createPortal as createPortal3 } from "react-dom";
8915
8938
  var LANGUAGES = [
8916
8939
  { code: "af", name: "Afrikaans" },
8917
8940
  { code: "sq", name: "Albanian" },
@@ -9102,7 +9125,7 @@ var TranslateModal = ({ editor, onClose, onTranslate, initialSource, initialTarg
9102
9125
  setTranslating(false);
9103
9126
  }
9104
9127
  };
9105
- return createPortal2(
9128
+ return createPortal3(
9106
9129
  /* @__PURE__ */ React110.createElement("div", { className: "modal-overlay", onClick: onClose }, /* @__PURE__ */ React110.createElement("div", { className: "modal-content translate-modal", onClick: (e) => e.stopPropagation() }, /* @__PURE__ */ React110.createElement("div", { className: "modal-header" }, /* @__PURE__ */ React110.createElement("h3", null, "Translate options"), /* @__PURE__ */ React110.createElement("button", { className: "modal-close", onClick: onClose }, "\xD7")), /* @__PURE__ */ React110.createElement("div", { className: "modal-body" }, /* @__PURE__ */ React110.createElement("div", { className: "translate-columns" }, /* @__PURE__ */ React110.createElement("div", { className: "translate-col" }, /* @__PURE__ */ React110.createElement("div", { className: "translate-filter" }, /* @__PURE__ */ React110.createElement(
9107
9130
  "input",
9108
9131
  {
@@ -10012,7 +10035,7 @@ var Dropdown = ({ trigger, children, className = "", keepOpen = false }) => {
10012
10035
  },
10013
10036
  trigger.label,
10014
10037
  /* @__PURE__ */ React112.createElement("span", { className: "dropdown-arrow" }, "\u25BE")
10015
- ), open && createPortal3(
10038
+ ), open && createPortal4(
10016
10039
  /* @__PURE__ */ React112.createElement("div", { className: "rf-rte-wrapper rf-rte-dropdown-portal" }, /* @__PURE__ */ React112.createElement("div", { ref: menuRef, className: "dropdown-menu dropdown-menu-fixed", onClick: keepOpen ? void 0 : () => setOpen(false) }, typeof children === "function" ? children(() => setOpen(false)) : children)),
10017
10040
  document.body
10018
10041
  ));
@@ -10269,10 +10292,11 @@ var ColorPickerPanel = ({ editor, onClose }) => {
10269
10292
  }
10270
10293
  ))), /* @__PURE__ */ React112.createElement("div", { className: "color-picker-footer" }, /* @__PURE__ */ React112.createElement("div", { className: "color-picker-preview", style: { background: activeColor || "#000" } }), /* @__PURE__ */ React112.createElement("button", { className: "color-picker-remove", onClick: removeColor, title: "Remove color" }, "\u2713")));
10271
10294
  };
10272
- var Toolbar = ({ editor, setLink, onAICommand, onTranslate, onSpeechToText, onTextToSpeech, onClose, onImageUpload, visibleButtons }) => {
10295
+ var Toolbar = ({ editor, setLink, onAICommand, onTranslate, onSpeechToText, onTextToSpeech, onClose, onImageUpload, visibleButtons, isFullscreen, onToggleFullscreen }) => {
10273
10296
  const [, setEditorState] = useState30(0);
10274
- const [isFullscreen, setIsFullscreen] = useState30(false);
10275
10297
  const [todoEnabled, setTodoEnabled] = useState30(false);
10298
+ const ttsRef = useRef26(null);
10299
+ const sttRef = useRef26(null);
10276
10300
  const show = (id) => !visibleButtons || visibleButtons.has(id);
10277
10301
  useEffect23(() => {
10278
10302
  if (!editor) return;
@@ -10280,16 +10304,6 @@ var Toolbar = ({ editor, setLink, onAICommand, onTranslate, onSpeechToText, onTe
10280
10304
  editor.on("transaction", onTransaction);
10281
10305
  return () => editor.off("transaction", onTransaction);
10282
10306
  }, [editor]);
10283
- const toggleFullscreen = useCallback12(() => {
10284
- const wrapper = document.querySelector(".editor-wrapper");
10285
- if (!wrapper) return;
10286
- if (!isFullscreen) {
10287
- wrapper.classList.add("fullscreen");
10288
- } else {
10289
- wrapper.classList.remove("fullscreen");
10290
- }
10291
- setIsFullscreen(!isFullscreen);
10292
- }, [isFullscreen]);
10293
10307
  const insertSpecialChar = useCallback12((char) => {
10294
10308
  if (!editor) return;
10295
10309
  editor.chain().focus().insertContent(char).run();
@@ -10793,11 +10807,11 @@ var Toolbar = ({ editor, setLink, onAICommand, onTranslate, onSpeechToText, onTe
10793
10807
  "button",
10794
10808
  {
10795
10809
  className: `toolbar-btn ${isFullscreen ? "is-active" : ""}`,
10796
- onClick: toggleFullscreen,
10810
+ onClick: onToggleFullscreen,
10797
10811
  title: "Toggle Fullscreen"
10798
10812
  },
10799
10813
  /* @__PURE__ */ React112.createElement(IconFullscreen, null)
10800
- ), show("tts") && /* @__PURE__ */ React112.createElement(TextToSpeech_default, { editor, onTextToSpeech }), show("stt") && /* @__PURE__ */ React112.createElement(SpeechToText_default, { editor, onSpeechToText }), show("translate") && /* @__PURE__ */ React112.createElement("div", { className: "translate-split-btn" }, /* @__PURE__ */ React112.createElement(
10814
+ ), show("tts") && /* @__PURE__ */ React112.createElement(TextToSpeech_default, { ref: ttsRef, editor, onTextToSpeech }), show("stt") && /* @__PURE__ */ React112.createElement(SpeechToText_default, { ref: sttRef, editor, onSpeechToText }), show("translate") && /* @__PURE__ */ React112.createElement("div", { className: "translate-split-btn" }, /* @__PURE__ */ React112.createElement(
10801
10815
  "button",
10802
10816
  {
10803
10817
  className: "toolbar-btn",
@@ -10891,7 +10905,17 @@ var Toolbar = ({ editor, setLink, onAICommand, onTranslate, onSpeechToText, onTe
10891
10905
  "button",
10892
10906
  {
10893
10907
  className: "toolbar-btn btn-cross",
10894
- onClick: onClose,
10908
+ onClick: () => {
10909
+ try {
10910
+ ttsRef.current?.stop();
10911
+ } catch {
10912
+ }
10913
+ try {
10914
+ sttRef.current?.stop();
10915
+ } catch {
10916
+ }
10917
+ onClose();
10918
+ },
10895
10919
  title: "Close"
10896
10920
  },
10897
10921
  /* @__PURE__ */ React112.createElement(closeIcon_default, { color: "#a81c08" })
@@ -10914,7 +10938,7 @@ var Toolbar_default = Toolbar;
10914
10938
 
10915
10939
  // lib/RufousTextEditor/ImageToolbar.tsx
10916
10940
  import React113, { useState as useState31, useEffect as useEffect24, useRef as useRef27 } from "react";
10917
- import { createPortal as createPortal4 } from "react-dom";
10941
+ import { createPortal as createPortal5 } from "react-dom";
10918
10942
  var ALIGNMENTS = [
10919
10943
  { value: "left", label: "Left", icon: "\u2630" },
10920
10944
  { value: "center", label: "Center", icon: "\u2261" },
@@ -11086,7 +11110,7 @@ var ImageToolbar = ({ editor }) => {
11086
11110
  }, [editor]);
11087
11111
  const node = editor?.state.selection.node;
11088
11112
  const isImage = node && node.type.name === "image";
11089
- if (!editor || !isImage || !pos) return showModal ? createPortal4(
11113
+ if (!editor || !isImage || !pos) return showModal ? createPortal5(
11090
11114
  /* @__PURE__ */ React113.createElement(ImagePropertiesModal, { editor, node, onClose: () => setShowModal(false) }),
11091
11115
  document.body
11092
11116
  ) : null;
@@ -11163,7 +11187,7 @@ var ImageToolbar = ({ editor }) => {
11163
11187
  );
11164
11188
  setShowVAlign(false);
11165
11189
  };
11166
- return createPortal4(
11190
+ return createPortal5(
11167
11191
  /* @__PURE__ */ React113.createElement(React113.Fragment, null, /* @__PURE__ */ React113.createElement(
11168
11192
  "div",
11169
11193
  {
@@ -11194,7 +11218,7 @@ var ImageToolbar_default = ImageToolbar;
11194
11218
 
11195
11219
  // lib/RufousTextEditor/VideoToolbar.tsx
11196
11220
  import React114, { useState as useState32, useEffect as useEffect25, useRef as useRef28 } from "react";
11197
- import { createPortal as createPortal5 } from "react-dom";
11221
+ import { createPortal as createPortal6 } from "react-dom";
11198
11222
  var ALIGNMENTS2 = [
11199
11223
  { value: "left", label: "Left", icon: "\u2630" },
11200
11224
  { value: "center", label: "Center", icon: "\u2261" },
@@ -11340,7 +11364,7 @@ var VideoToolbar = ({ editor }) => {
11340
11364
  const node = editor?.state.selection.node;
11341
11365
  const isVideo = node && VIDEO_TYPES.includes(node.type.name);
11342
11366
  const nodeType = node?.type.name;
11343
- if (!editor || !isVideo || !pos) return showModal ? createPortal5(
11367
+ if (!editor || !isVideo || !pos) return showModal ? createPortal6(
11344
11368
  /* @__PURE__ */ React114.createElement(VideoPropertiesModal, { editor, node, nodeType, onClose: () => setShowModal(false) }),
11345
11369
  document.body
11346
11370
  ) : null;
@@ -11387,7 +11411,7 @@ var VideoToolbar = ({ editor }) => {
11387
11411
  })
11388
11412
  );
11389
11413
  };
11390
- return createPortal5(
11414
+ return createPortal6(
11391
11415
  /* @__PURE__ */ React114.createElement(React114.Fragment, null, /* @__PURE__ */ React114.createElement(
11392
11416
  "div",
11393
11417
  {
@@ -11433,6 +11457,175 @@ var VideoToolbar = ({ editor }) => {
11433
11457
  };
11434
11458
  var VideoToolbar_default = VideoToolbar;
11435
11459
 
11460
+ // lib/RufousTextEditor/TableToolbar.tsx
11461
+ import React115, { useState as useState33, useEffect as useEffect26, useRef as useRef29 } from "react";
11462
+ import { createPortal as createPortal7 } from "react-dom";
11463
+ var IconAddRowBefore = () => /* @__PURE__ */ React115.createElement("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "currentColor" }, /* @__PURE__ */ React115.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__ */ React115.createElement("path", { d: "M9 6h2v1.5h1.5v2H11V11H9V9.5H7.5v-2H9z" }));
11464
+ var IconAddRowAfter = () => /* @__PURE__ */ React115.createElement("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "currentColor" }, /* @__PURE__ */ React115.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__ */ React115.createElement("path", { d: "M9 14h2v1.5h1.5v2H11V19H9v-1.5H7.5v-2H9z" }));
11465
+ var IconAddColBefore = () => /* @__PURE__ */ React115.createElement("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "currentColor" }, /* @__PURE__ */ React115.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__ */ React115.createElement("path", { d: "M6 10h1.5v2H6v1.5H4v-2h1.5V10H4V8h2z", transform: "translate(2,1)" }));
11466
+ var IconAddColAfter = () => /* @__PURE__ */ React115.createElement("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "currentColor" }, /* @__PURE__ */ React115.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__ */ React115.createElement("path", { d: "M15 9h2v1.5h1.5v2H17V14h-2v-1.5h-1.5v-2H15z" }));
11467
+ var IconDeleteRow = () => /* @__PURE__ */ React115.createElement("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "currentColor" }, /* @__PURE__ */ React115.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__ */ React115.createElement("path", { d: "M8 14.5h8v2H8z" }));
11468
+ var IconDeleteCol = () => /* @__PURE__ */ React115.createElement("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "currentColor" }, /* @__PURE__ */ React115.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__ */ React115.createElement("path", { d: "M14 9.5v6h2v-6z" }));
11469
+ var IconDeleteTable = () => /* @__PURE__ */ React115.createElement("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "currentColor" }, /* @__PURE__ */ React115.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__ */ React115.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" }));
11470
+ var IconMergeCells = () => /* @__PURE__ */ React115.createElement("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "currentColor" }, /* @__PURE__ */ React115.createElement("path", { d: "M3 3h18v18H3V3zm2 2v5h6V5H5zm8 0v5h6V5h-6zM5 13v6h14v-6H5z" }), /* @__PURE__ */ React115.createElement("path", { d: "M8 15h8v2H8z" }));
11471
+ var IconSplitCell = () => /* @__PURE__ */ React115.createElement("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "currentColor" }, /* @__PURE__ */ React115.createElement("path", { d: "M3 3h18v18H3V3zm2 2v5h6V5H5zm8 0v5h6V5h-6zM5 13v6h6v-6H5zm8 0v6h6v-6h-6z" }));
11472
+ var IconToggleHeader = () => /* @__PURE__ */ React115.createElement("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "currentColor" }, /* @__PURE__ */ React115.createElement("path", { d: "M3 3h18v18H3V3zm2 2v4h14V5H5zm0 6v8h14v-8H5z" }), /* @__PURE__ */ React115.createElement("rect", { x: "5", y: "5", width: "14", height: "4", opacity: "0.4" }));
11473
+ var TableToolbar = ({ editor }) => {
11474
+ const [pos, setPos] = useState33(null);
11475
+ const toolbarRef = useRef29(null);
11476
+ useEffect26(() => {
11477
+ if (!editor) return;
11478
+ const update = () => {
11479
+ if (!editor.isActive("table")) {
11480
+ setPos(null);
11481
+ return;
11482
+ }
11483
+ try {
11484
+ const { $from } = editor.state.selection;
11485
+ let depth = $from.depth;
11486
+ while (depth > 0) {
11487
+ const node = $from.node(depth);
11488
+ if (node.type.name === "table") {
11489
+ const domNode = editor.view.nodeDOM($from.before(depth));
11490
+ if (domNode) {
11491
+ const tableEl = domNode.tagName === "TABLE" ? domNode : domNode.querySelector?.("table") || domNode;
11492
+ const rect = tableEl.getBoundingClientRect();
11493
+ setPos({
11494
+ top: rect.top + window.scrollY - 40,
11495
+ left: rect.left + window.scrollX
11496
+ });
11497
+ }
11498
+ return;
11499
+ }
11500
+ depth--;
11501
+ }
11502
+ setPos(null);
11503
+ } catch {
11504
+ setPos(null);
11505
+ }
11506
+ };
11507
+ editor.on("selectionUpdate", update);
11508
+ editor.on("update", update);
11509
+ update();
11510
+ return () => {
11511
+ editor.off("selectionUpdate", update);
11512
+ editor.off("update", update);
11513
+ };
11514
+ }, [editor]);
11515
+ if (!editor || !pos || !editor.isActive("table")) return null;
11516
+ const canMerge = editor.can().mergeCells();
11517
+ const canSplit = editor.can().splitCell();
11518
+ const prevent = (e) => e.preventDefault();
11519
+ return createPortal7(
11520
+ /* @__PURE__ */ React115.createElement(
11521
+ "div",
11522
+ {
11523
+ ref: toolbarRef,
11524
+ className: "rf-table-toolbar",
11525
+ style: { top: pos.top, left: pos.left },
11526
+ onMouseDown: prevent
11527
+ },
11528
+ /* @__PURE__ */ React115.createElement(
11529
+ "button",
11530
+ {
11531
+ className: "rf-table-toolbar-btn",
11532
+ onClick: () => editor.chain().focus().addRowBefore().run(),
11533
+ title: "Insert row above"
11534
+ },
11535
+ /* @__PURE__ */ React115.createElement(IconAddRowBefore, null)
11536
+ ),
11537
+ /* @__PURE__ */ React115.createElement(
11538
+ "button",
11539
+ {
11540
+ className: "rf-table-toolbar-btn",
11541
+ onClick: () => editor.chain().focus().addRowAfter().run(),
11542
+ title: "Insert row below"
11543
+ },
11544
+ /* @__PURE__ */ React115.createElement(IconAddRowAfter, null)
11545
+ ),
11546
+ /* @__PURE__ */ React115.createElement(
11547
+ "button",
11548
+ {
11549
+ className: "rf-table-toolbar-btn rf-table-toolbar-btn-danger",
11550
+ onClick: () => editor.chain().focus().deleteRow().run(),
11551
+ title: "Delete row"
11552
+ },
11553
+ /* @__PURE__ */ React115.createElement(IconDeleteRow, null)
11554
+ ),
11555
+ /* @__PURE__ */ React115.createElement("span", { className: "rf-table-toolbar-sep" }),
11556
+ /* @__PURE__ */ React115.createElement(
11557
+ "button",
11558
+ {
11559
+ className: "rf-table-toolbar-btn",
11560
+ onClick: () => editor.chain().focus().addColumnBefore().run(),
11561
+ title: "Insert column left"
11562
+ },
11563
+ /* @__PURE__ */ React115.createElement(IconAddColBefore, null)
11564
+ ),
11565
+ /* @__PURE__ */ React115.createElement(
11566
+ "button",
11567
+ {
11568
+ className: "rf-table-toolbar-btn",
11569
+ onClick: () => editor.chain().focus().addColumnAfter().run(),
11570
+ title: "Insert column right"
11571
+ },
11572
+ /* @__PURE__ */ React115.createElement(IconAddColAfter, null)
11573
+ ),
11574
+ /* @__PURE__ */ React115.createElement(
11575
+ "button",
11576
+ {
11577
+ className: "rf-table-toolbar-btn rf-table-toolbar-btn-danger",
11578
+ onClick: () => editor.chain().focus().deleteColumn().run(),
11579
+ title: "Delete column"
11580
+ },
11581
+ /* @__PURE__ */ React115.createElement(IconDeleteCol, null)
11582
+ ),
11583
+ /* @__PURE__ */ React115.createElement("span", { className: "rf-table-toolbar-sep" }),
11584
+ /* @__PURE__ */ React115.createElement(
11585
+ "button",
11586
+ {
11587
+ className: "rf-table-toolbar-btn",
11588
+ onClick: () => editor.chain().focus().mergeCells().run(),
11589
+ disabled: !canMerge,
11590
+ title: "Merge cells"
11591
+ },
11592
+ /* @__PURE__ */ React115.createElement(IconMergeCells, null)
11593
+ ),
11594
+ /* @__PURE__ */ React115.createElement(
11595
+ "button",
11596
+ {
11597
+ className: "rf-table-toolbar-btn",
11598
+ onClick: () => editor.chain().focus().splitCell().run(),
11599
+ disabled: !canSplit,
11600
+ title: "Split cell"
11601
+ },
11602
+ /* @__PURE__ */ React115.createElement(IconSplitCell, null)
11603
+ ),
11604
+ /* @__PURE__ */ React115.createElement("span", { className: "rf-table-toolbar-sep" }),
11605
+ /* @__PURE__ */ React115.createElement(
11606
+ "button",
11607
+ {
11608
+ className: `rf-table-toolbar-btn ${editor.isActive("tableHeader") ? "active" : ""}`,
11609
+ onClick: () => editor.chain().focus().toggleHeaderRow().run(),
11610
+ title: "Toggle header row"
11611
+ },
11612
+ /* @__PURE__ */ React115.createElement(IconToggleHeader, null)
11613
+ ),
11614
+ /* @__PURE__ */ React115.createElement(
11615
+ "button",
11616
+ {
11617
+ className: "rf-table-toolbar-btn rf-table-toolbar-btn-danger",
11618
+ onClick: () => editor.chain().focus().deleteTable().run(),
11619
+ title: "Delete table"
11620
+ },
11621
+ /* @__PURE__ */ React115.createElement(IconDeleteTable, null)
11622
+ )
11623
+ ),
11624
+ document.body
11625
+ );
11626
+ };
11627
+ var TableToolbar_default = TableToolbar;
11628
+
11436
11629
  // lib/RufousTextEditor/legacyTodoTransform.ts
11437
11630
  var IMAGE_TO_STATUS = {
11438
11631
  "todo-blank.svg": "todo",
@@ -11601,12 +11794,12 @@ var RufousTextEditor = ({
11601
11794
  return visible;
11602
11795
  }, [buttons, variant, hideButtons]);
11603
11796
  const mentionSuggestion = useMemo4(() => createMentionSuggestion(mentions), [mentions]);
11604
- const onChangeRef = useRef29(onChange);
11605
- const onBlurRef = useRef29(onBlur);
11606
- useEffect26(() => {
11797
+ const onChangeRef = useRef30(onChange);
11798
+ const onBlurRef = useRef30(onBlur);
11799
+ useEffect27(() => {
11607
11800
  onChangeRef.current = onChange;
11608
11801
  }, [onChange]);
11609
- useEffect26(() => {
11802
+ useEffect27(() => {
11610
11803
  onBlurRef.current = onBlur;
11611
11804
  }, [onBlur]);
11612
11805
  const isEditable = editable && !disabled;
@@ -11637,7 +11830,9 @@ var RufousTextEditor = ({
11637
11830
  multicolor: true
11638
11831
  }),
11639
11832
  Table.configure({
11640
- resizable: true
11833
+ resizable: true,
11834
+ cellMinWidth: 80,
11835
+ lastColumnResizable: true
11641
11836
  }),
11642
11837
  TableRow,
11643
11838
  TableCell,
@@ -11705,8 +11900,8 @@ var RufousTextEditor = ({
11705
11900
  onChangeRef.current?.(e.getHTML(), e.getJSON());
11706
11901
  }
11707
11902
  });
11708
- const wrapperRef = useRef29(null);
11709
- useEffect26(() => {
11903
+ const wrapperRef = useRef30(null);
11904
+ useEffect27(() => {
11710
11905
  if (!editor) return;
11711
11906
  let blurTimer = null;
11712
11907
  const handler = ({ event }) => {
@@ -11724,14 +11919,14 @@ var RufousTextEditor = ({
11724
11919
  if (blurTimer) clearTimeout(blurTimer);
11725
11920
  };
11726
11921
  }, [editor]);
11727
- const setLinkRef = useRef29(null);
11728
- const [linkModalOpen, setLinkModalOpen] = useState33(false);
11729
- const [linkUrl, setLinkUrl] = useState33("");
11730
- const [linkText, setLinkText] = useState33("");
11731
- const [linkClassName, setLinkClassName] = useState33("");
11732
- const [linkNewTab, setLinkNewTab] = useState33(true);
11733
- const [linkNoFollow, setLinkNoFollow] = useState33(true);
11734
- const [linkSelection, setLinkSelection] = useState33(null);
11922
+ const setLinkRef = useRef30(null);
11923
+ const [linkModalOpen, setLinkModalOpen] = useState34(false);
11924
+ const [linkUrl, setLinkUrl] = useState34("");
11925
+ const [linkText, setLinkText] = useState34("");
11926
+ const [linkClassName, setLinkClassName] = useState34("");
11927
+ const [linkNewTab, setLinkNewTab] = useState34(true);
11928
+ const [linkNoFollow, setLinkNoFollow] = useState34(true);
11929
+ const [linkSelection, setLinkSelection] = useState34(null);
11735
11930
  const setLink = useCallback13(() => {
11736
11931
  if (!editor) return;
11737
11932
  const attrs = editor.getAttributes("link");
@@ -11769,10 +11964,10 @@ var RufousTextEditor = ({
11769
11964
  setLinkSelection({ from, to });
11770
11965
  setLinkModalOpen(true);
11771
11966
  }, [editor]);
11772
- useEffect26(() => {
11967
+ useEffect27(() => {
11773
11968
  setLinkRef.current = setLink;
11774
11969
  }, [setLink]);
11775
- useEffect26(() => {
11970
+ useEffect27(() => {
11776
11971
  if (!editor?.view) return;
11777
11972
  const handleKeyDown = (event) => {
11778
11973
  if ((event.ctrlKey || event.metaKey) && event.key === "k") {
@@ -11857,7 +12052,7 @@ var RufousTextEditor = ({
11857
12052
  setLinkSelection(null);
11858
12053
  editor?.chain().focus().run();
11859
12054
  }, [editor]);
11860
- const [saveStatus, setSaveStatus] = useState33("");
12055
+ const [saveStatus, setSaveStatus] = useState34("");
11861
12056
  const handleSave = useCallback13(() => {
11862
12057
  if (!editor || !onSaveProp) return;
11863
12058
  onSaveProp(editor.getHTML(), editor.getJSON());
@@ -11869,18 +12064,20 @@ var RufousTextEditor = ({
11869
12064
  onExportProp(editor.getHTML(), editor.getJSON());
11870
12065
  }, [editor, onExportProp]);
11871
12066
  const providerValue = useMemo4(() => ({ editor }), [editor]);
11872
- return /* @__PURE__ */ React115.createElement(
12067
+ const [isFullscreen, setIsFullscreen] = useState34(false);
12068
+ const toggleFullscreen = useCallback13(() => setIsFullscreen((prev) => !prev), []);
12069
+ const wrapperJsx = /* @__PURE__ */ React116.createElement(
11873
12070
  "div",
11874
12071
  {
11875
12072
  ref: wrapperRef,
11876
- className: `rf-rte-wrapper editor-wrapper ${resizable ? "rf-rte-resizable" : ""} ${disabled ? "rf-rte-disabled" : ""} ${error ? "rf-rte-error" : ""} ${sxClass} ${className || ""}`,
11877
- style: {
12073
+ className: `rf-rte-wrapper editor-wrapper ${isFullscreen ? "fullscreen" : ""} ${resizable ? "rf-rte-resizable" : ""} ${disabled ? "rf-rte-disabled" : ""} ${error ? "rf-rte-error" : ""} ${sxClass} ${className || ""}`,
12074
+ style: isFullscreen ? void 0 : {
11878
12075
  ...style,
11879
12076
  ...width ? { width: typeof width === "number" ? `${width}px` : width } : {},
11880
12077
  ...height ? { height: typeof height === "number" ? `${height}px` : height } : {}
11881
12078
  }
11882
12079
  },
11883
- /* @__PURE__ */ React115.createElement(EditorContext.Provider, { value: providerValue }, /* @__PURE__ */ React115.createElement(
12080
+ /* @__PURE__ */ React116.createElement(EditorContext.Provider, { value: providerValue }, /* @__PURE__ */ React116.createElement(
11884
12081
  Toolbar_default,
11885
12082
  {
11886
12083
  editor,
@@ -11891,9 +12088,11 @@ var RufousTextEditor = ({
11891
12088
  onTextToSpeech,
11892
12089
  onImageUpload,
11893
12090
  onClose,
11894
- visibleButtons: toolbarButtons
12091
+ visibleButtons: toolbarButtons,
12092
+ isFullscreen,
12093
+ onToggleFullscreen: toggleFullscreen
11895
12094
  }
11896
- ), /* @__PURE__ */ React115.createElement(EditorContent, { editor, className: "editor-content-wrapper" }), /* @__PURE__ */ React115.createElement(ImageToolbar_default, { editor }), /* @__PURE__ */ React115.createElement(VideoToolbar_default, { editor }), editor && /* @__PURE__ */ React115.createElement(
12095
+ ), /* @__PURE__ */ React116.createElement(EditorContent, { editor, className: "editor-content-wrapper" }), /* @__PURE__ */ React116.createElement(ImageToolbar_default, { editor }), /* @__PURE__ */ React116.createElement(VideoToolbar_default, { editor }), /* @__PURE__ */ React116.createElement(TableToolbar_default, { editor }), editor && /* @__PURE__ */ React116.createElement(
11897
12096
  BubbleMenu,
11898
12097
  {
11899
12098
  editor,
@@ -11911,31 +12110,31 @@ var RufousTextEditor = ({
11911
12110
  }
11912
12111
  }
11913
12112
  },
11914
- /* @__PURE__ */ React115.createElement(
12113
+ /* @__PURE__ */ React116.createElement(
11915
12114
  "button",
11916
12115
  {
11917
12116
  onClick: () => editor?.chain().focus().toggleBold().run(),
11918
12117
  className: editor?.isActive("bold") ? "is-active" : ""
11919
12118
  },
11920
- /* @__PURE__ */ React115.createElement("strong", null, "B")
12119
+ /* @__PURE__ */ React116.createElement("strong", null, "B")
11921
12120
  ),
11922
- /* @__PURE__ */ React115.createElement(
12121
+ /* @__PURE__ */ React116.createElement(
11923
12122
  "button",
11924
12123
  {
11925
12124
  onClick: () => editor?.chain().focus().toggleItalic().run(),
11926
12125
  className: editor?.isActive("italic") ? "is-active" : ""
11927
12126
  },
11928
- /* @__PURE__ */ React115.createElement("em", null, "I")
12127
+ /* @__PURE__ */ React116.createElement("em", null, "I")
11929
12128
  ),
11930
- /* @__PURE__ */ React115.createElement(
12129
+ /* @__PURE__ */ React116.createElement(
11931
12130
  "button",
11932
12131
  {
11933
12132
  onClick: () => editor?.chain().focus().toggleStrike().run(),
11934
12133
  className: editor?.isActive("strike") ? "is-active" : ""
11935
12134
  },
11936
- /* @__PURE__ */ React115.createElement("s", null, "S")
12135
+ /* @__PURE__ */ React116.createElement("s", null, "S")
11937
12136
  ),
11938
- /* @__PURE__ */ React115.createElement(
12137
+ /* @__PURE__ */ React116.createElement(
11939
12138
  "button",
11940
12139
  {
11941
12140
  onClick: () => editor?.chain().focus().toggleCode().run(),
@@ -11943,7 +12142,7 @@ var RufousTextEditor = ({
11943
12142
  },
11944
12143
  "</>"
11945
12144
  ),
11946
- /* @__PURE__ */ React115.createElement(
12145
+ /* @__PURE__ */ React116.createElement(
11947
12146
  "button",
11948
12147
  {
11949
12148
  onClick: setLink,
@@ -11951,7 +12150,7 @@ var RufousTextEditor = ({
11951
12150
  },
11952
12151
  "\u{1F517}"
11953
12152
  )
11954
- ), editor && /* @__PURE__ */ React115.createElement(
12153
+ ), editor && /* @__PURE__ */ React116.createElement(
11955
12154
  FloatingMenu,
11956
12155
  {
11957
12156
  editor,
@@ -11966,7 +12165,7 @@ var RufousTextEditor = ({
11966
12165
  }
11967
12166
  }
11968
12167
  },
11969
- /* @__PURE__ */ React115.createElement(
12168
+ /* @__PURE__ */ React116.createElement(
11970
12169
  "button",
11971
12170
  {
11972
12171
  onClick: () => editor?.chain().focus().toggleHeading({ level: 1 }).run(),
@@ -11974,7 +12173,7 @@ var RufousTextEditor = ({
11974
12173
  },
11975
12174
  "H1"
11976
12175
  ),
11977
- /* @__PURE__ */ React115.createElement(
12176
+ /* @__PURE__ */ React116.createElement(
11978
12177
  "button",
11979
12178
  {
11980
12179
  onClick: () => editor?.chain().focus().toggleHeading({ level: 2 }).run(),
@@ -11982,7 +12181,7 @@ var RufousTextEditor = ({
11982
12181
  },
11983
12182
  "H2"
11984
12183
  ),
11985
- /* @__PURE__ */ React115.createElement(
12184
+ /* @__PURE__ */ React116.createElement(
11986
12185
  "button",
11987
12186
  {
11988
12187
  onClick: () => editor?.chain().focus().toggleBulletList().run(),
@@ -11990,7 +12189,7 @@ var RufousTextEditor = ({
11990
12189
  },
11991
12190
  "\u2022 List"
11992
12191
  ),
11993
- /* @__PURE__ */ React115.createElement(
12192
+ /* @__PURE__ */ React116.createElement(
11994
12193
  "button",
11995
12194
  {
11996
12195
  onClick: () => editor?.chain().focus().toggleOrderedList().run(),
@@ -11998,7 +12197,7 @@ var RufousTextEditor = ({
11998
12197
  },
11999
12198
  "1. List"
12000
12199
  ),
12001
- /* @__PURE__ */ React115.createElement(
12200
+ /* @__PURE__ */ React116.createElement(
12002
12201
  "button",
12003
12202
  {
12004
12203
  onClick: () => editor?.chain().focus().toggleBlockquote().run(),
@@ -12006,8 +12205,8 @@ var RufousTextEditor = ({
12006
12205
  },
12007
12206
  "\u201C Quote"
12008
12207
  )
12009
- ), /* @__PURE__ */ React115.createElement("div", { className: "status-bar" }, /* @__PURE__ */ React115.createElement("div", { className: "status-bar-left" }, onSaveProp && /* @__PURE__ */ React115.createElement("button", { onClick: handleSave, className: "status-btn save-btn" }, "Save"), onExportProp && /* @__PURE__ */ React115.createElement("button", { onClick: handleExport, className: "status-btn export-btn" }, "Export")), /* @__PURE__ */ React115.createElement("div", { className: "status-bar-right" }, saveStatus && /* @__PURE__ */ React115.createElement("span", { className: "save-status" }, saveStatus), editor && /* @__PURE__ */ React115.createElement(React115.Fragment, null, /* @__PURE__ */ React115.createElement("span", { className: "word-count" }, "CHARS: ", editor.storage.characterCount?.characters?.() ?? editor.getText().length), /* @__PURE__ */ React115.createElement("span", { className: "word-count" }, "WORDS: ", editor.storage.characterCount?.words?.() ?? editor.getText().split(/\s+/).filter(Boolean).length)))), linkModalOpen && createPortal6(
12010
- /* @__PURE__ */ React115.createElement("div", { className: "link-modal-overlay", onClick: handleLinkCancel }, /* @__PURE__ */ React115.createElement("div", { className: "link-modal", onClick: (e) => e.stopPropagation() }, /* @__PURE__ */ React115.createElement("div", { className: "link-modal-body" }, /* @__PURE__ */ React115.createElement("div", { className: "link-modal-field" }, /* @__PURE__ */ React115.createElement("label", { className: "link-modal-label" }, "URL"), /* @__PURE__ */ React115.createElement(
12208
+ ), /* @__PURE__ */ React116.createElement("div", { className: "status-bar" }, /* @__PURE__ */ React116.createElement("div", { className: "status-bar-left" }, onSaveProp && /* @__PURE__ */ React116.createElement("button", { onClick: handleSave, className: "status-btn save-btn" }, "Save"), onExportProp && /* @__PURE__ */ React116.createElement("button", { onClick: handleExport, className: "status-btn export-btn" }, "Export")), /* @__PURE__ */ React116.createElement("div", { className: "status-bar-right" }, saveStatus && /* @__PURE__ */ React116.createElement("span", { className: "save-status" }, saveStatus), editor && /* @__PURE__ */ React116.createElement(React116.Fragment, null, /* @__PURE__ */ React116.createElement("span", { className: "word-count" }, "CHARS: ", editor.storage.characterCount?.characters?.() ?? editor.getText().length), /* @__PURE__ */ React116.createElement("span", { className: "word-count" }, "WORDS: ", editor.storage.characterCount?.words?.() ?? editor.getText().split(/\s+/).filter(Boolean).length)))), linkModalOpen && createPortal8(
12209
+ /* @__PURE__ */ React116.createElement("div", { className: "link-modal-overlay", onClick: handleLinkCancel }, /* @__PURE__ */ React116.createElement("div", { className: "link-modal", onClick: (e) => e.stopPropagation() }, /* @__PURE__ */ React116.createElement("div", { className: "link-modal-body" }, /* @__PURE__ */ React116.createElement("div", { className: "link-modal-field" }, /* @__PURE__ */ React116.createElement("label", { className: "link-modal-label" }, "URL"), /* @__PURE__ */ React116.createElement(
12011
12210
  "input",
12012
12211
  {
12013
12212
  type: "url",
@@ -12020,7 +12219,7 @@ var RufousTextEditor = ({
12020
12219
  placeholder: "https://example.com",
12021
12220
  autoFocus: true
12022
12221
  }
12023
- )), /* @__PURE__ */ React115.createElement("div", { className: "link-modal-field" }, /* @__PURE__ */ React115.createElement("label", { className: "link-modal-label" }, "Text"), /* @__PURE__ */ React115.createElement(
12222
+ )), /* @__PURE__ */ React116.createElement("div", { className: "link-modal-field" }, /* @__PURE__ */ React116.createElement("label", { className: "link-modal-label" }, "Text"), /* @__PURE__ */ React116.createElement(
12024
12223
  "input",
12025
12224
  {
12026
12225
  type: "text",
@@ -12032,30 +12231,31 @@ var RufousTextEditor = ({
12032
12231
  },
12033
12232
  placeholder: "Link text"
12034
12233
  }
12035
- )), /* @__PURE__ */ React115.createElement("div", { className: "link-modal-checkboxes" }, /* @__PURE__ */ React115.createElement("label", { className: "link-modal-checkbox" }, /* @__PURE__ */ React115.createElement(
12234
+ )), /* @__PURE__ */ React116.createElement("div", { className: "link-modal-checkboxes" }, /* @__PURE__ */ React116.createElement("label", { className: "link-modal-checkbox" }, /* @__PURE__ */ React116.createElement(
12036
12235
  "input",
12037
12236
  {
12038
12237
  type: "checkbox",
12039
12238
  checked: linkNewTab,
12040
12239
  onChange: (e) => setLinkNewTab(e.target.checked)
12041
12240
  }
12042
- ), "Open in new tab"), /* @__PURE__ */ React115.createElement("label", { className: "link-modal-checkbox" }, /* @__PURE__ */ React115.createElement(
12241
+ ), "Open in new tab"), /* @__PURE__ */ React116.createElement("label", { className: "link-modal-checkbox" }, /* @__PURE__ */ React116.createElement(
12043
12242
  "input",
12044
12243
  {
12045
12244
  type: "checkbox",
12046
12245
  checked: linkNoFollow,
12047
12246
  onChange: (e) => setLinkNoFollow(e.target.checked)
12048
12247
  }
12049
- ), "No follow"))), /* @__PURE__ */ React115.createElement("div", { className: "link-modal-footer" }, /* @__PURE__ */ React115.createElement("button", { className: "link-modal-btn-unlink", onClick: handleLinkRemove }, "Unlink"), /* @__PURE__ */ React115.createElement("button", { className: "link-modal-btn-apply", onClick: handleLinkSubmit }, "Update")))),
12248
+ ), "No follow"))), /* @__PURE__ */ React116.createElement("div", { className: "link-modal-footer" }, /* @__PURE__ */ React116.createElement("button", { className: "link-modal-btn-unlink", onClick: handleLinkRemove }, "Unlink"), /* @__PURE__ */ React116.createElement("button", { className: "link-modal-btn-apply", onClick: handleLinkSubmit }, "Update")))),
12050
12249
  document.body
12051
12250
  )),
12052
- helperText && /* @__PURE__ */ React115.createElement("div", { className: `rf-rte-helper-text ${error ? "rf-rte-helper-error" : ""}` }, helperText)
12251
+ helperText && /* @__PURE__ */ React116.createElement("div", { className: `rf-rte-helper-text ${error ? "rf-rte-helper-error" : ""}` }, helperText)
12053
12252
  );
12253
+ return isFullscreen ? createPortal8(wrapperJsx, document.body) : wrapperJsx;
12054
12254
  };
12055
12255
  var RufousTextContent = ({ content, className, style, sx }) => {
12056
12256
  const sxClass = useSx(sx);
12057
12257
  const transformedContent = useMemo4(() => transformLegacyTodos(content || ""), [content]);
12058
- return /* @__PURE__ */ React115.createElement(
12258
+ return /* @__PURE__ */ React116.createElement(
12059
12259
  "div",
12060
12260
  {
12061
12261
  className: `rf-rte-content ${sxClass} ${className || ""}`,