@rufous/ui 0.2.54 → 0.2.56

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
@@ -9183,7 +9183,7 @@ var TranslateModal = ({ editor, onClose, onTranslate, initialSource, initialTarg
9183
9183
  },
9184
9184
  /* @__PURE__ */ import_react54.default.createElement("span", { className: "translate-code" }, lang.code),
9185
9185
  /* @__PURE__ */ import_react54.default.createElement("span", { className: "translate-name" }, lang.name)
9186
- ))))), error && /* @__PURE__ */ import_react54.default.createElement("div", { className: "translate-error" }, error)), /* @__PURE__ */ import_react54.default.createElement("div", { className: "modal-footer" }, /* @__PURE__ */ import_react54.default.createElement("div", { className: "modal-footer-left" }, /* @__PURE__ */ import_react54.default.createElement("button", { className: "modal-btn-cancel", onClick: onClose }, "\xD7 Cancel")), /* @__PURE__ */ import_react54.default.createElement("button", { className: "modal-btn-apply", onClick: handleSave, disabled: translating }, translating ? "Translating..." : "\u2714 Save"))));
9186
+ ))))), error && /* @__PURE__ */ import_react54.default.createElement("div", { className: "translate-error" }, error)), /* @__PURE__ */ import_react54.default.createElement("div", { className: "modal-footer" }, /* @__PURE__ */ import_react54.default.createElement("div", { className: "modal-footer-left" }, /* @__PURE__ */ import_react54.default.createElement("button", { className: "modal-btn-cancel", onClick: onClose }, "Cancel")), /* @__PURE__ */ import_react54.default.createElement("button", { className: "modal-btn-apply", onClick: handleSave, disabled: translating }, translating ? "Translating..." : "Save"))));
9187
9187
  };
9188
9188
  var TranslateModal_default = TranslateModal;
9189
9189
 
@@ -9706,31 +9706,32 @@ var CustomTaskItem = import_extension_task_item.default.extend({
9706
9706
  }
9707
9707
  }
9708
9708
  if (taskItemDepth === -1) {
9709
- const parentDepth = $from.depth > 0 ? $from.depth - 1 : 0;
9709
+ if ($from.depth < 1) return false;
9710
+ const parentDepth = $from.depth - 1;
9710
9711
  const indexInParent = $from.index(parentDepth);
9711
9712
  if (indexInParent > 0) {
9712
9713
  const prevNode = $from.node(parentDepth).child(indexInParent - 1);
9713
9714
  if (prevNode.type.name === "taskList") {
9714
- const lastTaskItem = prevNode.lastChild;
9715
- if (lastTaskItem) {
9715
+ try {
9716
9716
  const tr = state.tr;
9717
- const paraStart = $from.before($from.depth > 0 ? $from.depth : 1);
9718
- const paraEnd = $from.after($from.depth > 0 ? $from.depth : 1);
9717
+ const paraStart = $from.before($from.depth);
9718
+ const paraEnd = $from.after($from.depth);
9719
9719
  const paraContent = $from.parent.content;
9720
- const taskListStart = $from.before(parentDepth) !== void 0 ? paraStart - 1 : null;
9721
- if (taskListStart !== null) {
9722
- const $taskListEnd = tr.doc.resolve(taskListStart);
9723
- const lastItemParaEnd = $taskListEnd.end($taskListEnd.depth);
9724
- tr.delete(paraStart, paraEnd);
9725
- let insertAt = lastItemParaEnd;
9726
- paraContent.forEach((inline) => {
9727
- tr.insert(insertAt, inline);
9728
- insertAt += inline.nodeSize;
9729
- });
9730
- tr.setSelection(import_prosemirror_state.TextSelection.create(tr.doc, lastItemParaEnd));
9731
- this.editor.view.dispatch(tr);
9732
- return true;
9733
- }
9720
+ const taskListEndPos = paraStart - 1;
9721
+ if (taskListEndPos < 0) return false;
9722
+ const $taskListEnd = tr.doc.resolve(taskListEndPos);
9723
+ const lastItemParaEnd = $taskListEnd.end($taskListEnd.depth);
9724
+ tr.delete(paraStart, paraEnd);
9725
+ let insertAt = lastItemParaEnd;
9726
+ paraContent.forEach((inline) => {
9727
+ tr.insert(insertAt, inline);
9728
+ insertAt += inline.nodeSize;
9729
+ });
9730
+ tr.setSelection(import_prosemirror_state.TextSelection.create(tr.doc, lastItemParaEnd));
9731
+ this.editor.view.dispatch(tr);
9732
+ return true;
9733
+ } catch {
9734
+ return false;
9734
9735
  }
9735
9736
  }
9736
9737
  }
@@ -9801,7 +9802,8 @@ var CustomTaskItem = import_extension_task_item.default.extend({
9801
9802
  "border: 2px solid " + colors.border,
9802
9803
  `background-image: url("${imageUrl}")`,
9803
9804
  "background-repeat: no-repeat",
9804
- "background-position: center"
9805
+ "background-position: center",
9806
+ "box-sizing: unset !important"
9805
9807
  ].join("; ");
9806
9808
  li.setAttribute("data-status", status);
9807
9809
  };
@@ -10032,12 +10034,24 @@ var Dropdown = ({ trigger, children, className = "", keepOpen = false }) => {
10032
10034
  const menu = menuRef.current;
10033
10035
  menu.style.left = "0";
10034
10036
  menu.style.right = "auto";
10035
- const rect = menu.getBoundingClientRect();
10036
- const vw = window.innerWidth;
10037
- if (rect.right > vw - 8) {
10038
- menu.style.left = "auto";
10039
- menu.style.right = "0";
10040
- }
10037
+ requestAnimationFrame(() => {
10038
+ if (!menu) return;
10039
+ const rect = menu.getBoundingClientRect();
10040
+ const vw = window.innerWidth;
10041
+ const parentLeft = ref.current?.getBoundingClientRect().left || 0;
10042
+ if (rect.right > vw - 8) {
10043
+ menu.style.left = "auto";
10044
+ menu.style.right = "0";
10045
+ const newRect = menu.getBoundingClientRect();
10046
+ if (newRect.left < 8) {
10047
+ menu.style.left = `${8 - parentLeft}px`;
10048
+ menu.style.right = "auto";
10049
+ }
10050
+ } else if (rect.left < 8) {
10051
+ menu.style.left = `${8 - parentLeft}px`;
10052
+ menu.style.right = "auto";
10053
+ }
10054
+ });
10041
10055
  }, [open]);
10042
10056
  return /* @__PURE__ */ import_react55.default.createElement("div", { className: `dropdown ${className}`, ref }, /* @__PURE__ */ import_react55.default.createElement(
10043
10057
  "button",
@@ -10302,10 +10316,11 @@ var ColorPickerPanel = ({ editor, onClose }) => {
10302
10316
  }
10303
10317
  ))), /* @__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")));
10304
10318
  };
10305
- var Toolbar = ({ editor, setLink, onAICommand, onTranslate, onSpeechToText, onTextToSpeech, onClose, onImageUpload }) => {
10319
+ var Toolbar = ({ editor, setLink, onAICommand, onTranslate, onSpeechToText, onTextToSpeech, onClose, onImageUpload, visibleButtons }) => {
10306
10320
  const [, setEditorState] = (0, import_react55.useState)(0);
10307
10321
  const [isFullscreen, setIsFullscreen] = (0, import_react55.useState)(false);
10308
10322
  const [todoEnabled, setTodoEnabled] = (0, import_react55.useState)(false);
10323
+ const show = (id) => !visibleButtons || visibleButtons.has(id);
10309
10324
  (0, import_react55.useEffect)(() => {
10310
10325
  if (!editor) return;
10311
10326
  const onTransaction = () => setEditorState((n) => n + 1);
@@ -10389,7 +10404,7 @@ var Toolbar = ({ editor, setLink, onAICommand, onTranslate, onSpeechToText, onTe
10389
10404
  setTimeout(() => setTranslateStatus(""), 2e3);
10390
10405
  }, [editor, translateSource, translateTarget, onTranslate]);
10391
10406
  if (!editor) return null;
10392
- return /* @__PURE__ */ import_react55.default.createElement("div", { className: "toolbar" }, /* @__PURE__ */ import_react55.default.createElement("div", { className: `toolbar-row ${onClose ? "with-close" : ""}` }, /* @__PURE__ */ import_react55.default.createElement("div", { className: "toolbar-group" }, /* @__PURE__ */ import_react55.default.createElement(
10407
+ return /* @__PURE__ */ import_react55.default.createElement("div", { className: "toolbar" }, /* @__PURE__ */ import_react55.default.createElement("div", { className: `toolbar-row ${onClose ? "with-close" : ""}` }, (show("undo") || show("redo")) && /* @__PURE__ */ import_react55.default.createElement("div", { className: "toolbar-group" }, show("undo") && /* @__PURE__ */ import_react55.default.createElement(
10393
10408
  "button",
10394
10409
  {
10395
10410
  className: "toolbar-btn",
@@ -10398,7 +10413,7 @@ var Toolbar = ({ editor, setLink, onAICommand, onTranslate, onSpeechToText, onTe
10398
10413
  title: "Undo (Ctrl+Z)"
10399
10414
  },
10400
10415
  /* @__PURE__ */ import_react55.default.createElement(IconUndo, null)
10401
- ), /* @__PURE__ */ import_react55.default.createElement(
10416
+ ), show("redo") && /* @__PURE__ */ import_react55.default.createElement(
10402
10417
  "button",
10403
10418
  {
10404
10419
  className: "toolbar-btn",
@@ -10407,7 +10422,7 @@ var Toolbar = ({ editor, setLink, onAICommand, onTranslate, onSpeechToText, onTe
10407
10422
  title: "Redo (Ctrl+Y)"
10408
10423
  },
10409
10424
  /* @__PURE__ */ import_react55.default.createElement(IconRedo, null)
10410
- )), /* @__PURE__ */ import_react55.default.createElement("div", { className: "toolbar-group" }, /* @__PURE__ */ import_react55.default.createElement(AICommands_default, { editor, onAICommand })), /* @__PURE__ */ import_react55.default.createElement("div", { className: "toolbar-group" }, /* @__PURE__ */ import_react55.default.createElement(
10425
+ )), show("ai") && /* @__PURE__ */ import_react55.default.createElement("div", { className: "toolbar-group" }, /* @__PURE__ */ import_react55.default.createElement(AICommands_default, { editor, onAICommand })), /* @__PURE__ */ import_react55.default.createElement("div", { className: "toolbar-group" }, show("paragraph") && /* @__PURE__ */ import_react55.default.createElement(
10411
10426
  Dropdown,
10412
10427
  {
10413
10428
  trigger: {
@@ -10474,7 +10489,7 @@ var Toolbar = ({ editor, setLink, onAICommand, onTranslate, onSpeechToText, onTe
10474
10489
  " Code Block"
10475
10490
  ),
10476
10491
  /* @__PURE__ */ import_react55.default.createElement("button", { className: "dropdown-item", onClick: () => editor.chain().focus().setHorizontalRule().run() }, "\u2014 Horizontal Rule")
10477
- ), /* @__PURE__ */ import_react55.default.createElement(
10492
+ ), show("fontsize") && /* @__PURE__ */ import_react55.default.createElement(
10478
10493
  Dropdown,
10479
10494
  {
10480
10495
  trigger: {
@@ -10501,7 +10516,7 @@ var Toolbar = ({ editor, setLink, onAICommand, onTranslate, onSpeechToText, onTe
10501
10516
  sizeStr
10502
10517
  );
10503
10518
  })
10504
- ), /* @__PURE__ */ import_react55.default.createElement(
10519
+ ), show("font") && /* @__PURE__ */ import_react55.default.createElement(
10505
10520
  Dropdown,
10506
10521
  {
10507
10522
  trigger: {
@@ -10528,7 +10543,7 @@ var Toolbar = ({ editor, setLink, onAICommand, onTranslate, onSpeechToText, onTe
10528
10543
  font
10529
10544
  );
10530
10545
  })
10531
- ), /* @__PURE__ */ import_react55.default.createElement(
10546
+ ), show("color") && /* @__PURE__ */ import_react55.default.createElement(
10532
10547
  Dropdown,
10533
10548
  {
10534
10549
  trigger: {
@@ -10538,7 +10553,7 @@ var Toolbar = ({ editor, setLink, onAICommand, onTranslate, onSpeechToText, onTe
10538
10553
  keepOpen: true
10539
10554
  },
10540
10555
  (close) => /* @__PURE__ */ import_react55.default.createElement(ColorPickerPanel, { editor, onClose: close })
10541
- ), /* @__PURE__ */ import_react55.default.createElement(
10556
+ ), show("bold") && /* @__PURE__ */ import_react55.default.createElement(
10542
10557
  "button",
10543
10558
  {
10544
10559
  className: `toolbar-btn ${editor.isActive("bold") ? "is-active" : ""}`,
@@ -10546,7 +10561,7 @@ var Toolbar = ({ editor, setLink, onAICommand, onTranslate, onSpeechToText, onTe
10546
10561
  title: "Bold (Ctrl+B)"
10547
10562
  },
10548
10563
  /* @__PURE__ */ import_react55.default.createElement(IconBold, null)
10549
- ), /* @__PURE__ */ import_react55.default.createElement(
10564
+ ), show("italic") && /* @__PURE__ */ import_react55.default.createElement(
10550
10565
  "button",
10551
10566
  {
10552
10567
  className: `toolbar-btn ${editor.isActive("italic") ? "is-active" : ""}`,
@@ -10554,7 +10569,7 @@ var Toolbar = ({ editor, setLink, onAICommand, onTranslate, onSpeechToText, onTe
10554
10569
  title: "Italic (Ctrl+I)"
10555
10570
  },
10556
10571
  /* @__PURE__ */ import_react55.default.createElement(IconItalic, null)
10557
- ), /* @__PURE__ */ import_react55.default.createElement(
10572
+ ), show("strike") && /* @__PURE__ */ import_react55.default.createElement(
10558
10573
  Dropdown,
10559
10574
  {
10560
10575
  trigger: { label: /* @__PURE__ */ import_react55.default.createElement(IconStrike, null), title: "Text decoration", className: editor.isActive("strike") ? "is-active" : "" }
@@ -10579,7 +10594,7 @@ var Toolbar = ({ editor, setLink, onAICommand, onTranslate, onSpeechToText, onTe
10579
10594
  c.run();
10580
10595
  }
10581
10596
  } }, "\u2715 Clear formatting")
10582
- ), /* @__PURE__ */ import_react55.default.createElement(
10597
+ ), show("link") && /* @__PURE__ */ import_react55.default.createElement(
10583
10598
  "button",
10584
10599
  {
10585
10600
  className: `toolbar-btn ${editor.isActive("link") ? "is-active" : ""}`,
@@ -10587,7 +10602,7 @@ var Toolbar = ({ editor, setLink, onAICommand, onTranslate, onSpeechToText, onTe
10587
10602
  title: "Insert Link"
10588
10603
  },
10589
10604
  /* @__PURE__ */ import_react55.default.createElement(IconLink, null)
10590
- ), /* @__PURE__ */ import_react55.default.createElement(
10605
+ ), show("lineheight") && /* @__PURE__ */ import_react55.default.createElement(
10591
10606
  Dropdown,
10592
10607
  {
10593
10608
  trigger: {
@@ -10614,7 +10629,7 @@ var Toolbar = ({ editor, setLink, onAICommand, onTranslate, onSpeechToText, onTe
10614
10629
  lh
10615
10630
  );
10616
10631
  })
10617
- )), /* @__PURE__ */ import_react55.default.createElement("div", { className: "toolbar-group" }, /* @__PURE__ */ import_react55.default.createElement(
10632
+ )), (show("ul") || show("ol")) && /* @__PURE__ */ import_react55.default.createElement("div", { className: "toolbar-group" }, show("ul") && /* @__PURE__ */ import_react55.default.createElement(
10618
10633
  Dropdown,
10619
10634
  {
10620
10635
  trigger: {
@@ -10657,7 +10672,7 @@ var Toolbar = ({ editor, setLink, onAICommand, onTranslate, onSpeechToText, onTe
10657
10672
  " ",
10658
10673
  item.label
10659
10674
  ))
10660
- ), /* @__PURE__ */ import_react55.default.createElement(
10675
+ ), show("ol") && /* @__PURE__ */ import_react55.default.createElement(
10661
10676
  Dropdown,
10662
10677
  {
10663
10678
  trigger: {
@@ -10702,7 +10717,7 @@ var Toolbar = ({ editor, setLink, onAICommand, onTranslate, onSpeechToText, onTe
10702
10717
  " ",
10703
10718
  item.label
10704
10719
  ))
10705
- )), /* @__PURE__ */ import_react55.default.createElement("div", { className: "toolbar-group" }, /* @__PURE__ */ import_react55.default.createElement(
10720
+ )), (show("align") || show("indent") || show("outdent")) && /* @__PURE__ */ import_react55.default.createElement("div", { className: "toolbar-group" }, show("align") && /* @__PURE__ */ import_react55.default.createElement(
10706
10721
  Dropdown,
10707
10722
  {
10708
10723
  trigger: {
@@ -10727,7 +10742,7 @@ var Toolbar = ({ editor, setLink, onAICommand, onTranslate, onSpeechToText, onTe
10727
10742
  " ",
10728
10743
  item.label
10729
10744
  ))
10730
- ), /* @__PURE__ */ import_react55.default.createElement(
10745
+ ), show("indent") && /* @__PURE__ */ import_react55.default.createElement(
10731
10746
  "button",
10732
10747
  {
10733
10748
  className: "toolbar-btn",
@@ -10748,7 +10763,7 @@ var Toolbar = ({ editor, setLink, onAICommand, onTranslate, onSpeechToText, onTe
10748
10763
  title: "Increase Indent"
10749
10764
  },
10750
10765
  /* @__PURE__ */ import_react55.default.createElement(IconIndentIncrease, null)
10751
- ), /* @__PURE__ */ import_react55.default.createElement(
10766
+ ), show("outdent") && /* @__PURE__ */ import_react55.default.createElement(
10752
10767
  "button",
10753
10768
  {
10754
10769
  className: "toolbar-btn",
@@ -10769,7 +10784,7 @@ var Toolbar = ({ editor, setLink, onAICommand, onTranslate, onSpeechToText, onTe
10769
10784
  title: "Decrease Indent"
10770
10785
  },
10771
10786
  /* @__PURE__ */ import_react55.default.createElement(IconIndentDecrease, null)
10772
- )), /* @__PURE__ */ import_react55.default.createElement(Dropdown, { trigger: { label: /* @__PURE__ */ import_react55.default.createElement(IconTable, null), title: "Insert Table" }, keepOpen: true }, (close) => /* @__PURE__ */ import_react55.default.createElement(TableGridSelector, { editor, onClose: close })), /* @__PURE__ */ import_react55.default.createElement(Dropdown, { trigger: { label: /* @__PURE__ */ import_react55.default.createElement(IconImage, null), title: "Insert Image" }, keepOpen: true }, (close) => /* @__PURE__ */ import_react55.default.createElement(ImagePanel, { editor, onClose: close, onImageUpload })), /* @__PURE__ */ import_react55.default.createElement(Dropdown, { trigger: { label: /* @__PURE__ */ import_react55.default.createElement(IconVideo, null), title: "Insert Video" }, keepOpen: true }, (close) => /* @__PURE__ */ import_react55.default.createElement(InsertPanel, { editor, onClose: close, mode: "video" })), /* @__PURE__ */ import_react55.default.createElement(
10787
+ )), show("table") && /* @__PURE__ */ import_react55.default.createElement(Dropdown, { trigger: { label: /* @__PURE__ */ import_react55.default.createElement(IconTable, null), title: "Insert Table" }, keepOpen: true }, (close) => /* @__PURE__ */ import_react55.default.createElement(TableGridSelector, { editor, onClose: close })), show("image") && /* @__PURE__ */ import_react55.default.createElement(Dropdown, { trigger: { label: /* @__PURE__ */ import_react55.default.createElement(IconImage, null), title: "Insert Image" }, keepOpen: true }, (close) => /* @__PURE__ */ import_react55.default.createElement(ImagePanel, { editor, onClose: close, onImageUpload })), show("video") && /* @__PURE__ */ import_react55.default.createElement(Dropdown, { trigger: { label: /* @__PURE__ */ import_react55.default.createElement(IconVideo, null), title: "Insert Video" }, keepOpen: true }, (close) => /* @__PURE__ */ import_react55.default.createElement(InsertPanel, { editor, onClose: close, mode: "video" })), show("cut") && /* @__PURE__ */ import_react55.default.createElement(
10773
10788
  "button",
10774
10789
  {
10775
10790
  className: "toolbar-btn",
@@ -10777,7 +10792,7 @@ var Toolbar = ({ editor, setLink, onAICommand, onTranslate, onSpeechToText, onTe
10777
10792
  title: "Cut (Ctrl+X)"
10778
10793
  },
10779
10794
  /* @__PURE__ */ import_react55.default.createElement(IconCut, null)
10780
- ), /* @__PURE__ */ import_react55.default.createElement(
10795
+ ), show("copy") && /* @__PURE__ */ import_react55.default.createElement(
10781
10796
  "button",
10782
10797
  {
10783
10798
  className: "toolbar-btn",
@@ -10785,7 +10800,7 @@ var Toolbar = ({ editor, setLink, onAICommand, onTranslate, onSpeechToText, onTe
10785
10800
  title: "Copy selected text"
10786
10801
  },
10787
10802
  copySuccess ? /* @__PURE__ */ import_react55.default.createElement(IconCheck, null) : /* @__PURE__ */ import_react55.default.createElement(IconCopy, null)
10788
- ), /* @__PURE__ */ import_react55.default.createElement(
10803
+ ), show("paste") && /* @__PURE__ */ import_react55.default.createElement(
10789
10804
  "button",
10790
10805
  {
10791
10806
  className: "toolbar-btn",
@@ -10793,7 +10808,7 @@ var Toolbar = ({ editor, setLink, onAICommand, onTranslate, onSpeechToText, onTe
10793
10808
  title: "Paste (Ctrl+V)"
10794
10809
  },
10795
10810
  /* @__PURE__ */ import_react55.default.createElement(IconPaste, null)
10796
- ), /* @__PURE__ */ import_react55.default.createElement(Dropdown, { trigger: { label: "\u03A9", title: "Special characters", className: "special-characters-btn" } }, /* @__PURE__ */ import_react55.default.createElement("div", { className: "char-grid" }, SPECIAL_CHARS.map((char) => /* @__PURE__ */ import_react55.default.createElement(
10811
+ ), show("specialchars") && /* @__PURE__ */ import_react55.default.createElement(Dropdown, { trigger: { label: "\u03A9", title: "Special characters", className: "special-characters-btn" } }, /* @__PURE__ */ import_react55.default.createElement("div", { className: "char-grid" }, SPECIAL_CHARS.map((char) => /* @__PURE__ */ import_react55.default.createElement(
10797
10812
  "button",
10798
10813
  {
10799
10814
  key: char,
@@ -10801,7 +10816,7 @@ var Toolbar = ({ editor, setLink, onAICommand, onTranslate, onSpeechToText, onTe
10801
10816
  onClick: () => insertSpecialChar(char)
10802
10817
  },
10803
10818
  char
10804
- )))), /* @__PURE__ */ import_react55.default.createElement(
10819
+ )))), show("code") && /* @__PURE__ */ import_react55.default.createElement(
10805
10820
  Dropdown,
10806
10821
  {
10807
10822
  trigger: { label: /* @__PURE__ */ import_react55.default.createElement(IconCode, null), title: "Code", className: editor.isActive("code") || editor.isActive("codeBlock") ? "is-active" : "" }
@@ -10825,7 +10840,7 @@ var Toolbar = ({ editor, setLink, onAICommand, onTranslate, onSpeechToText, onTe
10825
10840
  }
10826
10841
  } }, "</>", " Inline Code"),
10827
10842
  /* @__PURE__ */ import_react55.default.createElement("button", { className: "dropdown-item", onClick: () => editor.chain().focus().toggleCodeBlock().run() }, "{ }", " Code Block")
10828
- ), /* @__PURE__ */ import_react55.default.createElement(
10843
+ ), show("fullscreen") && /* @__PURE__ */ import_react55.default.createElement(
10829
10844
  "button",
10830
10845
  {
10831
10846
  className: `toolbar-btn ${isFullscreen ? "is-active" : ""}`,
@@ -10833,7 +10848,7 @@ var Toolbar = ({ editor, setLink, onAICommand, onTranslate, onSpeechToText, onTe
10833
10848
  title: "Toggle Fullscreen"
10834
10849
  },
10835
10850
  /* @__PURE__ */ import_react55.default.createElement(IconFullscreen, null)
10836
- ), /* @__PURE__ */ import_react55.default.createElement(TextToSpeech_default, { editor, onTextToSpeech }), /* @__PURE__ */ import_react55.default.createElement(SpeechToText_default, { editor, onSpeechToText }), /* @__PURE__ */ import_react55.default.createElement("div", { className: "translate-split-btn" }, /* @__PURE__ */ import_react55.default.createElement(
10851
+ ), 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(
10837
10852
  "button",
10838
10853
  {
10839
10854
  className: "toolbar-btn",
@@ -10841,7 +10856,7 @@ var Toolbar = ({ editor, setLink, onAICommand, onTranslate, onSpeechToText, onTe
10841
10856
  title: "Translate selected text"
10842
10857
  },
10843
10858
  /* @__PURE__ */ import_react55.default.createElement(IconTranslate, null)
10844
- ), /* @__PURE__ */ import_react55.default.createElement(Dropdown, { trigger: { label: "", title: "Translate options", className: "translate-arrow-btn" } }, /* @__PURE__ */ import_react55.default.createElement("button", { className: "dropdown-item", onClick: () => setShowTranslateModal(true) }, "Options")), translateStatus && /* @__PURE__ */ import_react55.default.createElement("span", { className: `translate-toast-popup ${translateStatus === "Please select the text" || translateStatus === "Translation failed" ? "error" : ""}` }, translateStatus)), /* @__PURE__ */ import_react55.default.createElement("div", { className: "todo-split-btn" }, /* @__PURE__ */ import_react55.default.createElement(
10859
+ ), /* @__PURE__ */ import_react55.default.createElement(Dropdown, { trigger: { label: "", title: "Translate options", className: "translate-arrow-btn" } }, /* @__PURE__ */ import_react55.default.createElement("button", { className: "dropdown-item", onClick: () => setShowTranslateModal(true) }, "Options")), translateStatus && /* @__PURE__ */ import_react55.default.createElement("span", { className: `translate-toast-popup ${translateStatus === "Please select the text" || translateStatus === "Translation failed" ? "error" : ""}` }, translateStatus)), show("todo") && /* @__PURE__ */ import_react55.default.createElement("div", { className: "todo-split-btn" }, /* @__PURE__ */ import_react55.default.createElement(
10845
10860
  "button",
10846
10861
  {
10847
10862
  className: `toolbar-btn ${todoEnabled ? "is-active" : ""}`,
@@ -11084,7 +11099,7 @@ var ImagePropertiesModal = ({ editor, node, onClose }) => {
11084
11099
  checked: openInNewTab,
11085
11100
  onChange: (e) => setOpenInNewTab(e.target.checked)
11086
11101
  }
11087
- ), "Open link in new tab")) : /* @__PURE__ */ import_react56.default.createElement(import_react56.default.Fragment, null, /* @__PURE__ */ import_react56.default.createElement("label", { className: "modal-label" }, "CSS Class"), /* @__PURE__ */ import_react56.default.createElement("input", { type: "text", className: "modal-input", placeholder: "e.g. rounded shadow" }), /* @__PURE__ */ import_react56.default.createElement("label", { className: "modal-label" }, "Inline Style"), /* @__PURE__ */ import_react56.default.createElement("input", { type: "text", className: "modal-input", placeholder: "e.g. border: 1px solid #ccc" }))))), /* @__PURE__ */ import_react56.default.createElement("div", { className: "modal-footer" }, /* @__PURE__ */ import_react56.default.createElement("div", { className: "modal-footer-left" }, /* @__PURE__ */ import_react56.default.createElement("button", { className: "modal-btn-cancel", onClick: onClose }, "\xD7 Cancel"), /* @__PURE__ */ import_react56.default.createElement("button", { className: "modal-btn-delete", onClick: handleDelete }, "\u{1F5D1} Delete")), /* @__PURE__ */ import_react56.default.createElement("button", { className: "modal-btn-apply", onClick: handleApply }, "\u2714 Apply"))));
11102
+ ), "Open link in new tab")) : /* @__PURE__ */ import_react56.default.createElement(import_react56.default.Fragment, null, /* @__PURE__ */ import_react56.default.createElement("label", { className: "modal-label" }, "CSS Class"), /* @__PURE__ */ import_react56.default.createElement("input", { type: "text", className: "modal-input", placeholder: "e.g. rounded shadow" }), /* @__PURE__ */ import_react56.default.createElement("label", { className: "modal-label" }, "Inline Style"), /* @__PURE__ */ import_react56.default.createElement("input", { type: "text", className: "modal-input", placeholder: "e.g. border: 1px solid #ccc" }))))), /* @__PURE__ */ import_react56.default.createElement("div", { className: "modal-footer" }, /* @__PURE__ */ import_react56.default.createElement("div", { className: "modal-footer-left" }, /* @__PURE__ */ import_react56.default.createElement("button", { className: "modal-btn-cancel", onClick: onClose }, "Cancel"), /* @__PURE__ */ import_react56.default.createElement("button", { className: "modal-btn-delete", onClick: handleDelete }, "Delete")), /* @__PURE__ */ import_react56.default.createElement("button", { className: "modal-btn-apply", onClick: handleApply }, "Apply"))));
11088
11103
  };
11089
11104
  var ImageToolbar = ({ editor }) => {
11090
11105
  const [showModal, setShowModal] = (0, import_react56.useState)(false);
@@ -11337,7 +11352,7 @@ var VideoPropertiesModal = ({ editor, node, nodeType, onClose }) => {
11337
11352
  value: height,
11338
11353
  onChange: (e) => handleHeightChange(e.target.value)
11339
11354
  }
11340
- )))), /* @__PURE__ */ import_react57.default.createElement("div", { className: "modal-footer" }, /* @__PURE__ */ import_react57.default.createElement("div", { className: "modal-footer-left" }, /* @__PURE__ */ import_react57.default.createElement("button", { className: "modal-btn-cancel", onClick: onClose }, "\xD7 Cancel"), /* @__PURE__ */ import_react57.default.createElement("button", { className: "modal-btn-delete", onClick: handleDelete }, "\u{1F5D1} Delete")), /* @__PURE__ */ import_react57.default.createElement("button", { className: "modal-btn-apply", onClick: handleApply }, "\u2714 Apply"))));
11355
+ )))), /* @__PURE__ */ import_react57.default.createElement("div", { className: "modal-footer" }, /* @__PURE__ */ import_react57.default.createElement("div", { className: "modal-footer-left" }, /* @__PURE__ */ import_react57.default.createElement("button", { className: "modal-btn-cancel", onClick: onClose }, "Cancel"), /* @__PURE__ */ import_react57.default.createElement("button", { className: "modal-btn-delete", onClick: handleDelete }, "Delete")), /* @__PURE__ */ import_react57.default.createElement("button", { className: "modal-btn-apply", onClick: handleApply }, "Apply"))));
11341
11356
  };
11342
11357
  var VideoToolbar = ({ editor }) => {
11343
11358
  const [showModal, setShowModal] = (0, import_react57.useState)(false);
@@ -11470,6 +11485,62 @@ var VideoToolbar = ({ editor }) => {
11470
11485
  var VideoToolbar_default = VideoToolbar;
11471
11486
 
11472
11487
  // lib/RufousTextEditor/RufousTextEditor.tsx
11488
+ var VARIANT_BUTTONS = {
11489
+ default: [
11490
+ "undo",
11491
+ "redo",
11492
+ "|",
11493
+ "ai",
11494
+ "|",
11495
+ "paragraph",
11496
+ "fontsize",
11497
+ "font",
11498
+ "color",
11499
+ "bold",
11500
+ "italic",
11501
+ "strike",
11502
+ "link",
11503
+ "lineheight",
11504
+ "|",
11505
+ "ul",
11506
+ "ol",
11507
+ "|",
11508
+ "align",
11509
+ "indent",
11510
+ "outdent",
11511
+ "|",
11512
+ "table",
11513
+ "image",
11514
+ "video",
11515
+ "|",
11516
+ "cut",
11517
+ "copy",
11518
+ "paste",
11519
+ "specialchars",
11520
+ "code",
11521
+ "fullscreen",
11522
+ "|",
11523
+ "tts",
11524
+ "stt",
11525
+ "translate",
11526
+ "|",
11527
+ "todo"
11528
+ ],
11529
+ basic: [
11530
+ "undo",
11531
+ "redo",
11532
+ "|",
11533
+ "paragraph",
11534
+ "fontsize",
11535
+ "font",
11536
+ "bold",
11537
+ "italic",
11538
+ "link",
11539
+ "|",
11540
+ "ul",
11541
+ "ol"
11542
+ ]
11543
+ };
11473
11544
  var RufousTextEditor = ({
11474
11545
  content: initialContent,
11475
11546
  placeholder: customPlaceholder,
@@ -11485,6 +11556,10 @@ var RufousTextEditor = ({
11485
11556
  onImageUpload,
11486
11557
  onClose,
11487
11558
  mentions,
11559
+ variant = "default",
11560
+ buttons,
11561
+ hideButtons,
11562
+ width,
11488
11563
  height,
11489
11564
  resizable = false,
11490
11565
  className,
@@ -11492,6 +11567,14 @@ var RufousTextEditor = ({
11492
11567
  sx
11493
11568
  }) => {
11494
11569
  const sxClass = useSx(sx);
11570
+ const toolbarButtons = (0, import_react58.useMemo)(() => {
11571
+ const list = buttons || VARIANT_BUTTONS[variant] || VARIANT_BUTTONS.default;
11572
+ const visible = new Set(list.filter((b) => b !== "|"));
11573
+ if (hideButtons) {
11574
+ hideButtons.forEach((b) => visible.delete(b));
11575
+ }
11576
+ return visible;
11577
+ }, [buttons, variant, hideButtons]);
11495
11578
  const mentionSuggestion = (0, import_react58.useMemo)(() => createMentionSuggestion(mentions), [mentions]);
11496
11579
  const onChangeRef = (0, import_react58.useRef)(onChange);
11497
11580
  const onBlurRef = (0, import_react58.useRef)(onBlur);
@@ -11657,6 +11740,25 @@ var RufousTextEditor = ({
11657
11740
  if ((event.ctrlKey || event.metaKey) && event.key === "k") {
11658
11741
  event.preventDefault();
11659
11742
  setLinkRef.current?.();
11743
+ return;
11744
+ }
11745
+ if (event.key === " " && editor.isActive("link")) {
11746
+ const { $from } = editor.state.selection;
11747
+ const linkMark = editor.state.schema.marks.link;
11748
+ const parent = $from.parent;
11749
+ let atLinkEnd = false;
11750
+ parent.forEach((child, offset2) => {
11751
+ if (child.isText && child.marks.some((m) => m.type === linkMark)) {
11752
+ const childEnd = offset2 + child.nodeSize;
11753
+ if ($from.parentOffset === childEnd) {
11754
+ atLinkEnd = true;
11755
+ }
11756
+ }
11757
+ });
11758
+ if (atLinkEnd) {
11759
+ event.preventDefault();
11760
+ editor.chain().focus().unsetMark("link").insertContent(" ").run();
11761
+ }
11660
11762
  }
11661
11763
  };
11662
11764
  editor.view.dom.addEventListener("keydown", handleKeyDown);
@@ -11717,7 +11819,6 @@ var RufousTextEditor = ({
11717
11819
  setLinkSelection(null);
11718
11820
  editor?.chain().focus().run();
11719
11821
  }, [editor]);
11720
- const [saveFormat, setSaveFormat] = (0, import_react58.useState)("html");
11721
11822
  const [saveStatus, setSaveStatus] = (0, import_react58.useState)("");
11722
11823
  const handleSave = (0, import_react58.useCallback)(() => {
11723
11824
  if (!editor || !onSaveProp) return;
@@ -11729,12 +11830,6 @@ var RufousTextEditor = ({
11729
11830
  if (!editor || !onExportProp) return;
11730
11831
  onExportProp(editor.getHTML(), editor.getJSON());
11731
11832
  }, [editor, onExportProp]);
11732
- const handleClear = (0, import_react58.useCallback)(() => {
11733
- if (!editor) return;
11734
- if (window.confirm("Clear all content? This cannot be undone.")) {
11735
- editor.commands.clearContent();
11736
- }
11737
- }, [editor]);
11738
11833
  const providerValue = (0, import_react58.useMemo)(() => ({ editor }), [editor]);
11739
11834
  return /* @__PURE__ */ import_react58.default.createElement(
11740
11835
  "div",
@@ -11742,6 +11837,7 @@ var RufousTextEditor = ({
11742
11837
  className: `rf-rte-wrapper editor-wrapper ${resizable ? "rf-rte-resizable" : ""} ${sxClass} ${className || ""}`,
11743
11838
  style: {
11744
11839
  ...style,
11840
+ ...width ? { width: typeof width === "number" ? `${width}px` : width } : {},
11745
11841
  ...height ? { height: typeof height === "number" ? `${height}px` : height } : {}
11746
11842
  }
11747
11843
  },
@@ -11755,7 +11851,8 @@ var RufousTextEditor = ({
11755
11851
  onSpeechToText,
11756
11852
  onTextToSpeech,
11757
11853
  onImageUpload,
11758
- onClose
11854
+ onClose,
11855
+ visibleButtons: toolbarButtons
11759
11856
  }
11760
11857
  ), /* @__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(
11761
11858
  import_react59.BubbleMenu,
@@ -11870,16 +11967,7 @@ var RufousTextEditor = ({
11870
11967
  },
11871
11968
  "\u201C Quote"
11872
11969
  )
11873
- ), /* @__PURE__ */ import_react58.default.createElement("div", { className: "status-bar" }, /* @__PURE__ */ import_react58.default.createElement("div", { className: "status-bar-left" }, /* @__PURE__ */ import_react58.default.createElement(
11874
- "select",
11875
- {
11876
- value: saveFormat,
11877
- onChange: (e) => setSaveFormat(e.target.value),
11878
- className: "format-select"
11879
- },
11880
- /* @__PURE__ */ import_react58.default.createElement("option", { value: "html" }, "HTML"),
11881
- /* @__PURE__ */ import_react58.default.createElement("option", { value: "json" }, "JSON")
11882
- ), 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("button", { onClick: handleClear, className: "status-btn clear-btn" }, "Clear")), /* @__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 && /* @__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(
11970
+ ), /* @__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 && /* @__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(
11883
11971
  "input",
11884
11972
  {
11885
11973
  type: "url",
@@ -11904,18 +11992,6 @@ var RufousTextEditor = ({
11904
11992
  },
11905
11993
  placeholder: "Link text"
11906
11994
  }
11907
- )), /* @__PURE__ */ import_react58.default.createElement("div", { className: "link-modal-field" }, /* @__PURE__ */ import_react58.default.createElement("label", { className: "link-modal-label" }, "Class name"), /* @__PURE__ */ import_react58.default.createElement(
11908
- "input",
11909
- {
11910
- type: "text",
11911
- className: "link-modal-input",
11912
- value: linkClassName,
11913
- onChange: (e) => setLinkClassName(e.target.value),
11914
- onKeyDown: (e) => {
11915
- if (e.key === "Enter") handleLinkSubmit();
11916
- },
11917
- placeholder: ""
11918
- }
11919
11995
  )), /* @__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(
11920
11996
  "input",
11921
11997
  {